diff --git a/blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp b/blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp index 1f25699a..5bd4fd12 100644 --- a/blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp +++ b/blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp @@ -33,6 +33,7 @@ #include "DNA_genfile.h" #include "DNA_action_types.h" #include "DNA_anim_enums.h" +#include "DNA_armature_types.h" #include "DNA_curve_enums.h" #include "DNA_lattice_types.h" #include "DNA_mask_types.h" @@ -334,6 +335,22 @@ std::vector read_float_array(const SDNA &sdna, return result; } +std::vector read_byte_array(const SDNA &sdna, + const ElementRef &element, + const std::string &member_name, + const size_t maximum_values) +{ + const std::optional member = find_member(sdna, element.type_name, member_name); + if (!member || member->size <= 0) return {}; + const size_t value_count = std::min(maximum_values, size_t(member->size)); + if (!bytes_available(element, *member, value_count)) return {}; + const uint8_t *data = element.block->bytes.data() + element.offset + size_t(member->offset); + std::vector result; + result.reserve(value_count); + for (size_t index = 0; index < value_count; index++) result.push_back(int(data[index])); + return result; +} + std::string read_string(const SDNA &sdna, const ElementRef &element, const std::string &member_name) @@ -1365,7 +1382,8 @@ std::optional editor_workflow_from_records( ":region:" + std::to_string(regions.size())}, {"kind", kind}, {"visible", (flags & RGN_FLAG_HIDDEN) == 0}}; - if (std::strcmp(editor, "DOPE_SHEET") == 0 && std::strcmp(kind, "MAIN") == 0) { + if ((std::strcmp(editor, "DOPE_SHEET") == 0 || std::strcmp(editor, "GRAPH") == 0) && + std::strcmp(kind, "MAIN") == 0) { if (const std::optional view2d = editor_view2d_state(*blend.sdna, region)) { region_record["view2d"] = *view2d; } @@ -1983,6 +2001,10 @@ std::array element_matrix(const ParsedBlend &blend, return result; } +std::vector read_raw_pointer_array(const ParsedBlend &blend, + const uint64_t pointer, + const size_t count); + json armature_from_data(const ParsedBlend &blend, const ElementRef &armature, const std::string &armature_id, @@ -2002,23 +2024,82 @@ json armature_from_data(const ParsedBlend &blend, const std::string name = read_string(*blend.sdna, bone, "name"); if (name.empty()) return; const std::string id = "bone:" + armature_id + ":" + name; - const std::vector head = read_float_array(*blend.sdna, bone, "head", 3); - const std::vector tail = read_float_array(*blend.sdna, bone, "tail", 3); + const std::vector arm_head = read_float_array(*blend.sdna, bone, "arm_head", 3); + const std::vector arm_tail = read_float_array(*blend.sdna, bone, "arm_tail", 3); + const std::vector head = arm_head.size() == 3 ? arm_head : + read_float_array(*blend.sdna, bone, "head", 3); + const std::vector tail = arm_tail.size() == 3 ? arm_tail : + read_float_array(*blend.sdna, bone, "tail", 3); const std::array identity = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; json entry = {{"id", id}}; entry["name"] = name; + const int64_t bone_flag = read_integer(*blend.sdna, bone, "flag").value_or(0); + entry["selected"] = (bone_flag & BONE_SELECTED) != 0; + entry["hidden"] = (bone_flag & BONE_HIDDEN_A) != 0; + entry["connected"] = (bone_flag & BONE_CONNECTED) != 0; entry["parentId"] = parent_id.empty() ? json(nullptr) : json(parent_id); entry["head"] = float_array_or(head, {0.0f, 0.0f, 0.0f}); entry["tail"] = float_array_or(tail, {0.0f, 0.0f, 1.0f}); entry["restMatrix"] = element_matrix(blend, bone, "arm_mat", identity); + if (const std::optional color = embedded_element(*blend.sdna, bone, "color")) { + json color_json = {{"paletteIndex", read_integer(*blend.sdna, *color, "palette_index").value_or(0)}}; + if (const std::optional custom = embedded_element(*blend.sdna, *color, "custom")) { + color_json["normal"] = read_byte_array(*blend.sdna, *custom, "solid", 4); + color_json["select"] = read_byte_array(*blend.sdna, *custom, "select", 4); + color_json["active"] = read_byte_array(*blend.sdna, *custom, "active", 4); + color_json["flag"] = read_integer(*blend.sdna, *custom, "flag").value_or(0); + } + entry["color"] = std::move(color_json); + } const auto pose_matrix = pose_matrices.find(name); if (pose_matrix != pose_matrices.end()) entry["poseMatrix"] = pose_matrix->second; bones.push_back(std::move(entry)); for (const ElementRef &child : linked_list_elements(blend, bone, "childbase")) visit(child, id); }; for (const ElementRef &root : linked_list_elements(blend, armature, "bonebase")) visit(root, ""); - return json{{"id", armature_id}, {"name", read_id_name(*blend.sdna, armature)}, {"bones", bones}}; + json bone_collections = json::array(); + const int64_t collection_count = std::clamp( + read_integer(*blend.sdna, armature, "collection_array_num").value_or(0), 0, 10000); + const std::optional collection_pointer = read_pointer(*blend.sdna, armature, "collection_array"); + const std::vector collection_pointers = collection_pointer && collection_count > 0 ? + read_raw_pointer_array(blend, + *collection_pointer, + size_t(collection_count)) : + std::vector(); + std::vector collection_elements; + for (const uint64_t pointer : collection_pointers) { + if (const std::optional collection = element_for_pointer(blend, pointer)) { + collection_elements.push_back(*collection); + } + } + if (collection_elements.empty()) { + collection_elements = linked_list_elements(blend, armature, "collections_legacy"); + } + for (size_t index = 0; index < collection_elements.size(); index++) { + const ElementRef &collection = collection_elements[index]; + const std::string name = read_string(*blend.sdna, collection, "name"); + if (name.empty()) continue; + json members = json::array(); + for (const ElementRef &member : linked_list_elements(blend, collection, "bones")) { + const std::optional bone_pointer = read_pointer(*blend.sdna, member, "bone"); + if (!bone_pointer) continue; + const std::optional bone = element_for_pointer(blend, *bone_pointer); + if (!bone) continue; + const std::string bone_name = read_string(*blend.sdna, *bone, "name"); + if (!bone_name.empty()) members.push_back("bone:" + armature_id + ":" + bone_name); + } + bone_collections.push_back({{"id", "bone_collection:" + armature_id + ":" + name}, + {"name", name}, + {"index", int64_t(index)}, + {"visible", (read_integer(*blend.sdna, collection, "flags").value_or(0) & BONE_COLLECTION_VISIBLE) != 0}, + {"solo", (read_integer(*blend.sdna, collection, "flags").value_or(0) & BONE_COLLECTION_SOLO) != 0}, + {"boneIds", std::move(members)}}); + } + return json{{"id", armature_id}, + {"name", read_id_name(*blend.sdna, armature)}, + {"bones", std::move(bones)}, + {"boneCollections", std::move(bone_collections)}}; } std::vector read_raw_int_array(const ParsedBlend &blend, @@ -2756,7 +2837,9 @@ void append_action_animation(const ParsedBlend &blend, const std::string &target_id, const uint64_t action_pointer, json &animations, - std::unordered_set &visited) + std::unordered_set &visited, + const std::optional slot_handle = std::nullopt, + const std::string &slot_identifier_hint = {}) { const std::optional action = element_for_pointer(blend, action_pointer); if (!action) return; @@ -2782,6 +2865,25 @@ void append_action_animation(const ParsedBlend &blend, const std::vector data_pointers = data_pointer && data_count > 0 ? read_raw_pointer_array(blend, *data_pointer, size_t(data_count)) : std::vector(); + const bool filter_slot = slot_handle.has_value() && *slot_handle != 0; + std::optional slot_identifier; + int64_t slot_count = 0; + const int64_t action_slot_count = std::clamp( + read_integer(*blend.sdna, *action, "slot_array_num").value_or(0), 0, 10000); + const std::optional action_slot_pointer = read_pointer(*blend.sdna, *action, "slot_array"); + if (action_slot_pointer && action_slot_count > 0) { + const std::vector action_slot_pointers = read_raw_pointer_array( + blend, *action_slot_pointer, size_t(action_slot_count)); + for (const uint64_t action_slot_value : action_slot_pointers) { + const std::optional action_slot = element_for_pointer(blend, action_slot_value); + if (!action_slot) continue; + slot_count++; + if (slot_handle && read_integer(*blend.sdna, *action_slot, "handle").value_or(0) == *slot_handle) { + slot_identifier = read_string(*blend.sdna, *action_slot, "identifier"); + } + } + } + if (!slot_identifier && !slot_identifier_hint.empty()) slot_identifier = slot_identifier_hint; if (layer_pointer && layer_count > 0) { const std::vector layer_pointers = read_raw_pointer_array(blend, *layer_pointer, size_t(layer_count)); for (const uint64_t layer_value : layer_pointers) { @@ -2805,6 +2907,7 @@ void append_action_animation(const ParsedBlend &blend, for (const uint64_t bag_value : bag_pointers) { const std::optional bag = element_for_pointer(blend, bag_value); if (!bag) continue; + if (filter_slot && read_integer(*blend.sdna, *bag, "slot_handle").value_or(0) != *slot_handle) continue; const int64_t fcurve_count = std::clamp(read_integer(*blend.sdna, *bag, "fcurve_array_num").value_or(0), 0, 100000); const std::optional fcurve_pointer = read_pointer(*blend.sdna, *bag, "fcurve_array"); if (!fcurve_pointer) continue; @@ -2828,13 +2931,20 @@ void append_action_animation(const ParsedBlend &blend, if (!std::isfinite(frame_start)) frame_start = action_frame_start; if (!std::isfinite(frame_end)) frame_end = action_frame_end; const std::string action_name = read_id_name(*blend.sdna, *action); - animations.push_back({{"id", "action:" + (action_name.empty() ? std::to_string(action_pointer) : action_name) + ":" + target_id}, - {"name", action_name.empty() ? "Action" : action_name}, - {"targetId", target_id}, - {"frameStart", std::isfinite(frame_start) ? frame_start : 0.0f}, - {"frameEnd", std::isfinite(frame_end) ? frame_end : 0.0f}, - {"markers", std::move(markers)}, - {"channels", std::move(channels)}}); + json animation = {{"id", "action:" + (action_name.empty() ? std::to_string(action_pointer) : action_name) + ":" + target_id}, + {"name", action_name.empty() ? "Action" : action_name}, + {"targetId", target_id}, + {"frameStart", std::isfinite(frame_start) ? frame_start : 0.0f}, + {"frameEnd", std::isfinite(frame_end) ? frame_end : 0.0f}, + {"markers", std::move(markers)}, + {"channels", std::move(channels)}}; + if (slot_identifier) { + animation["slotIdentifier"] = *slot_identifier; + animation["slotHandle"] = slot_handle.value_or(0); + animation["slotAssigned"] = slot_handle.value_or(0) != 0; + animation["slotCount"] = slot_count; + } + animations.push_back(std::move(animation)); } json mesh_geometry_from_attributes(const ParsedBlend &blend, @@ -3370,7 +3480,14 @@ json scene_ir_from_blend(const ParsedBlend &blend, if (const std::optional adt = element_for_pointer(blend, *adt_pointer)) { if (const std::optional action_pointer = read_pointer(*blend.sdna, *adt, "action")) { linked_action_pointers.insert(*action_pointer); - append_action_animation(blend, record.id, *action_pointer, animations, visited_animations); + const int64_t slot_handle = read_integer(*blend.sdna, *adt, "slot_handle").value_or(0); + append_action_animation(blend, + record.id, + *action_pointer, + animations, + visited_animations, + slot_handle != 0 ? std::optional(slot_handle) : std::nullopt, + read_string(*blend.sdna, *adt, "last_slot_identifier")); } int track_index = 0; for (const ElementRef &track : linked_list_elements(blend, *adt, "nla_tracks")) { @@ -3393,6 +3510,8 @@ json scene_ir_from_blend(const ParsedBlend &blend, const int64_t strip_type = read_integer(*blend.sdna, strip, "type").value_or(0); const int64_t blend_mode = read_integer(*blend.sdna, strip, "blendmode").value_or(0); const int64_t extend_mode = read_integer(*blend.sdna, strip, "extendmode").value_or(0); + const int64_t action_slot_handle = read_integer(*blend.sdna, strip, "action_slot_handle").value_or(0); + const std::string action_slot_identifier = read_string(*blend.sdna, strip, "last_slot_identifier"); const char *strip_type_name = strip_type == 0 ? "CLIP" : strip_type == 1 ? "TRANSITION" : strip_type == 2 ? "META" : strip_type == 3 ? "SOUND" : "UNKNOWN"; json strip_ir = { @@ -3415,6 +3534,9 @@ json scene_ir_from_blend(const ParsedBlend &blend, {"selected", (strip_flag & (1 << 1)) != 0}, {"reverse", (strip_flag & (1 << 11)) != 0}, {"useTimeWarp", (strip_flag & (1 << 6)) != 0}, + {"actionSlotHandle", action_slot_handle}, + {"actionSlotIdentifier", action_slot_identifier}, + {"actionSlotAssigned", action_slot_handle != 0}, {"stripType", strip_type_name}}; if (!action_pointer) strip_ir["unsupportedReason"] = "NLA Action data-block is missing"; else if (blend_mode == 2 || blend_mode < 0 || blend_mode > 4) strip_ir["unsupportedReason"] = "NLA blend mode is outside the finite subset"; @@ -3459,11 +3581,31 @@ json scene_ir_from_blend(const ParsedBlend &blend, for (const ElementRef &constraint : linked_list_elements(blend, element, "constraints")) { const int64_t constraint_type = read_integer(*blend.sdna, constraint, "type").value_or(0); const int64_t flag = read_integer(*blend.sdna, constraint, "flag").value_or(0); - constraints.push_back({{"name", read_string(*blend.sdna, constraint, "name")}, - {"typeCode", constraint_type}, - {"type", "CONSTRAINT_" + std::to_string(constraint_type)}, - {"enabled", (flag & 512) == 0}, - {"influence", read_float(*blend.sdna, constraint, "enforce").value_or(1.0f)}}); + json constraint_ir = {{"name", read_string(*blend.sdna, constraint, "name")}, + {"typeCode", constraint_type}, + {"type", "CONSTRAINT_" + std::to_string(constraint_type)}, + {"enabled", (flag & 512) == 0}, + {"influence", read_float(*blend.sdna, constraint, "enforce").value_or(1.0f)}}; + if (constraint_type == 12) { + const std::optional constraint_data_pointer = read_pointer(*blend.sdna, constraint, "data"); + if (constraint_data_pointer) { + const std::optional constraint_data = element_for_pointer(blend, *constraint_data_pointer); + if (constraint_data) { + const int64_t action_slot_handle = read_integer(*blend.sdna, *constraint_data, "action_slot_handle").value_or(0); + const std::optional action_pointer = read_pointer(*blend.sdna, *constraint_data, "act"); + if (action_pointer) { + if (const std::optional action = element_for_pointer(blend, *action_pointer)) { + const std::string action_name = read_id_name(*blend.sdna, *action); + constraint_ir["actionId"] = "action:" + (action_name.empty() ? std::to_string(*action_pointer) : action_name); + } + } + constraint_ir["actionSlotHandle"] = action_slot_handle; + constraint_ir["actionSlotIdentifier"] = read_string(*blend.sdna, *constraint_data, "last_slot_identifier"); + constraint_ir["actionSlotAssigned"] = action_slot_handle != 0; + } + } + } + constraints.push_back(std::move(constraint_ir)); } if (!constraints.empty()) node["constraints"] = std::move(constraints); if (const std::optional adt_pointer = read_pointer(*blend.sdna, element, "adt")) { diff --git a/docs/EXECUTION_QUEUE.md b/docs/EXECUTION_QUEUE.md index 87283635..b3126cf2 100644 --- a/docs/EXECUTION_QUEUE.md +++ b/docs/EXECUTION_QUEUE.md @@ -4,17 +4,17 @@ 本页是唯一的当前任务指针,不保存历史任务表、实现日志或长期规划。领取任务前只读取本页、当前任务上下文、parent manifest 和 parent status;完整规则见 [`CONTEXT_BUDGET.md`](CONTEXT_BUDGET.md)。 -连续接续入口见 [`nextTask.md`](../nextTask.md):用户发送“按 nextTask.md 接续执行”时,按该流程从当前指针开始;每次只完成一个任务并在新请求中用 fresh compact context 继续。 +连续接续入口见 [`nextTask.md`](../nextTask.md):用户发送“按 nextTask.md 接续执行”时,进入连续模式;每个迭代只完成一个任务并以 fresh compact context 交接,成功后自动读取新指针继续,直到失败、阻塞、预算/环境/传输异常、闭合门或用户要求停止。 ## 当前指针 | 字段 | 值 | | --- | --- | | 里程碑 | M16 Main、Mesh、Modifier、Sculpt | -| 当前任务 | `M16-GAP-00227` | -| parent manifest | `tests/golden/M16-GAP-00226/manifest.json` | -| 任务卡 | [`tasks/M16-GAP-00227.md`](tasks/M16-GAP-00227.md) | -| 专项验收 | `npm --prefix web run test:generated-gap -- --task M16-GAP-00227` | +| 当前任务 | `M16-GAP-00264` | +| parent manifest | `tests/golden/M16-GAP-00263/manifest.json` | +| 任务卡 | [`tasks/M16-GAP-00264.md`](tasks/M16-GAP-00264.md) | +| 专项验收 | `npm --prefix web run test:generated-gap -- --task M16-GAP-00264` | 领取前执行: diff --git a/docs/status/M16-GAP-00175.md b/docs/status/M16-GAP-00175.md new file mode 100644 index 00000000..773cd84b --- /dev/null +++ b/docs/status/M16-GAP-00175.md @@ -0,0 +1,16 @@ +# M16-GAP-00175 Status + +status: done +task: anim.driver_button_edit operator LOCAL_EXACT slice +updated: 2026-08-21 America/New_York + +scope: + +- The minimal fixture contains one scripted driver on `drive_target`; Blender desktop invokes `ANIM_OT_driver_button_edit` in the active Properties context (`poll=true`, `INTERFACE`) and preserves the driver without a Main mutation. + +evidence: + +- Desktop and WASM/Main expose the same driver (`["drive_target"]`, expression `frame * 2.5 + 1.25`, scripted, no variables); save/reopen is exact and malformed Blend input is rejected without Main mutation. +- Fixture generation, desktop checker, npm comparator, direct comparator, and artifact hashing passed. The edit operator is intentionally interface-only and leaves the driver unchanged. + +nextTask: `M16-GAP-00176` diff --git a/docs/status/M16-GAP-00176.md b/docs/status/M16-GAP-00176.md new file mode 100644 index 00000000..3a3aa56b --- /dev/null +++ b/docs/status/M16-GAP-00176.md @@ -0,0 +1,16 @@ +# M16-GAP-00176 Status + +status: done +task: anim.driver_button_remove operator LOCAL_EXACT slice +updated: 2026-08-21 America/New_York + +scope: + +- The minimal fixture starts with one scripted driver on `drive_target`; foreground Chromium-compatible Blender UI activates the RNA button and invokes `ANIM_OT_driver_button_remove(all=true)` (`poll=true`, `FINISHED`), removing that driver from Main. + +evidence: + +- Desktop and WASM/Main expose the same final object with no drivers; save/reopen is exact and malformed Blend input is rejected without Main mutation. +- Fixture generation, foreground desktop checker, npm comparator, direct comparator, and artifact hashing passed. The checker is idempotent for the already-removed exact fixture. + +nextTask: `M16-GAP-00177` diff --git a/docs/status/M16-GAP-00177.md b/docs/status/M16-GAP-00177.md new file mode 100644 index 00000000..7e040e8e --- /dev/null +++ b/docs/status/M16-GAP-00177.md @@ -0,0 +1,16 @@ +# M16-GAP-00177 Status + +status: done +task: anim.end_frame_set operator LOCAL_EXACT slice +updated: 2026-08-21 America/New_York + +scope: + +- The minimal scene starts at frame 42 with a scene range of 1-120; a foreground animation-area context invokes `ANIM_OT_end_frame_set` (`poll=true`, `FINISHED`) and sets the scene end frame to 42. + +evidence: + +- Desktop and WASM/Main expose the same frame state (`current=42`, `start=1`, `end=42`); save/reopen is exact and malformed Blend input is rejected without Main mutation. +- Fixture generation, foreground desktop checker, npm comparator, direct comparator, and artifact hashing passed. + +nextTask: `M16-GAP-00178` diff --git a/docs/status/M16-GAP-00178.md b/docs/status/M16-GAP-00178.md new file mode 100644 index 00000000..b09f460a --- /dev/null +++ b/docs/status/M16-GAP-00178.md @@ -0,0 +1,16 @@ +# M16-GAP-00178 Status + +status: done +task: anim.keyframe_clear_button operator LOCAL_EXACT slice +updated: 2026-08-21 America/New_York + +scope: + +- The minimal fixture animates one scalar custom RNA property, `clear_target`, on `WebGapAnimKeyframeClearButtonObject` at frames 1, 3, and 5. A foreground Properties context activates that RNA button and invokes `ANIM_OT_keyframe_clear_button(all=true)` (`poll=true`, `FINISHED`), leaving the Action with no F-Curves. + +evidence: + +- Desktop evidence records the property changing from three selected keyframes to none; WASM/Main reads the original channel as `["clear_target"][0]` and the cleared fixture with no matching animation. Save/reopen is exact and malformed Blend input is rejected without Main mutation. +- Fixture generation, foreground desktop checker, npm comparator, direct comparator, and artifact hashing passed. The checker and comparator are idempotent for the already-cleared exact fixture while retaining the original `before` evidence. + +nextTask: `M16-GAP-00179` diff --git a/docs/status/M16-GAP-00179.md b/docs/status/M16-GAP-00179.md new file mode 100644 index 00000000..b5f14c29 --- /dev/null +++ b/docs/status/M16-GAP-00179.md @@ -0,0 +1,16 @@ +# M16-GAP-00179 Status + +status: done +task: anim.keyframe_clear_v3d operator LOCAL_EXACT slice +updated: 2026-08-21 America/New_York + +scope: + +- The minimal fixture selects one object with a scalar `clear_target` Action at frames 1, 3, and 5. A foreground `VIEW_3D` context invokes `ANIM_OT_keyframe_clear_v3d(confirm=false)` (`poll=true`, `FINISHED`), removing all editable F-Curves from the selected object's Action. + +evidence: + +- Desktop evidence records the selected/active object changing from three selected keyframes to no F-Curves; WASM/Main reads the original channel as `["clear_target"][0]` and the cleared fixture with no matching animation. Save/reopen is exact and malformed Blend input is rejected without Main mutation. +- Fixture generation, foreground V3D desktop checker, npm comparator, direct comparator, and artifact hashing passed. The checker and comparator are idempotent for the already-cleared exact fixture while retaining the original `before` evidence. + +nextTask: `M16-GAP-00180` diff --git a/docs/status/M16-GAP-00180.md b/docs/status/M16-GAP-00180.md new file mode 100644 index 00000000..ba4ea668 --- /dev/null +++ b/docs/status/M16-GAP-00180.md @@ -0,0 +1,16 @@ +# M16-GAP-00180 Status + +status: done +task: anim.keyframe_clear_vse operator LOCAL_EXACT slice +updated: 2026-08-21 America/New_York + +scope: + +- The minimal fixture contains one selected image strip with a Scene Action animating `blend_alpha` at frames 1, 3, and 5. A real foreground `SEQUENCE_EDITOR` context invokes `ANIM_OT_keyframe_clear_vse(confirm=false)` (`poll=true`, `FINISHED`), removing the selected strip's editable F-Curve while preserving the strip and its evaluated value. + +evidence: + +- Desktop evidence records the selected/active strip changing from three selected keyframes to no F-Curves. WASM/Main reads the same Scene Action channel before clearing and no matching animation from the cleared fixture. Save/reopen is exact and malformed Blend input is rejected without Main mutation. +- Fixture generation, foreground VSE desktop checker, npm comparator, direct comparator, and artifact hashing passed. The checker is idempotent for the already-cleared exact fixture while retaining the original `before` evidence. + +nextTask: `M16-GAP-00181` diff --git a/docs/status/M16-GAP-00181.md b/docs/status/M16-GAP-00181.md new file mode 100644 index 00000000..46f6d129 --- /dev/null +++ b/docs/status/M16-GAP-00181.md @@ -0,0 +1,17 @@ +# M16-GAP-00181 Status + +status: done +task: anim.keyframe_delete operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one selected object with a custom `delete_target` property and an Action keyed at frames 1, 3, and 5. A dedicated active Keying Set targets that property. A real foreground `VIEW_3D` context invokes `ANIM_OT_keyframe_delete(type=WebGapAnimKeyframeDeleteSet)` (`poll=true`, `FINISHED`) at frame 3, deleting only the current keyframe and preserving the two surrounding keys. + +evidence: + +- Desktop evidence records the selected/active object and active Keying Set before deletion, then the Action changing from `[1, 3, 5]` to `[1, 5]`; the custom property remains at 3.0. Save/reopen is exact. +- WASM/Main reads the same fixture Action as one `[\"delete_target\"][0]` channel with three keyframes before the operation fixture and two keyframes after it. WASM save/reopen is exact, and malformed Blend input is rejected without Main mutation. +- Fixture generation, foreground `VIEW_3D` checker, npm comparator, direct comparator, idempotent rerun, and artifact hashing passed. No production reader or protocol change was required because the existing generic Action/F-Curve reader exposes this custom-property channel. + +nextTask: `M16-GAP-00182` diff --git a/docs/status/M16-GAP-00182.md b/docs/status/M16-GAP-00182.md new file mode 100644 index 00000000..be4c3760 --- /dev/null +++ b/docs/status/M16-GAP-00182.md @@ -0,0 +1,17 @@ +# M16-GAP-00182 Status + +status: done +task: anim.keyframe_delete_button operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one selected object with a custom `delete_target` property and an Action keyed at frames 1, 3, and 5. A registered Properties panel exposes the animated property as a real UI button. A foreground Properties context invokes `ANIM_OT_keyframe_delete_button(all=true)` through that active button at frame 3 (`poll=true`, `FINISHED`), deleting only the current keyframe and preserving the two surrounding keys. + +evidence: + +- Desktop evidence records the selected/active object changing from `[1, 3, 5]` to `[1, 5]`; the custom property remains at 3.0 and save/reopen is exact. +- WASM/Main reads the same Action as one `[\"delete_target\"][0]` channel with three keyframes before the operation fixture and two keyframes after it. WASM save/reopen is exact, and malformed Blend input is rejected without Main mutation. +- Fixture generation, foreground Properties UI checker, npm comparator, direct idempotent comparator, and artifact hashing passed. No production reader or protocol change was required because the existing generic Action/F-Curve reader exposes this custom-property channel. + +nextTask: `M16-GAP-00183` diff --git a/docs/status/M16-GAP-00183.md b/docs/status/M16-GAP-00183.md new file mode 100644 index 00000000..c1e9b6ea --- /dev/null +++ b/docs/status/M16-GAP-00183.md @@ -0,0 +1,17 @@ +# M16-GAP-00183 Status + +status: done +task: anim.keyframe_delete_by_name operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one selected object with a custom `delete_target` property and an Action keyed at frames 1, 3, and 5. A named Keying Set targets that property. A foreground `VIEW_3D` context invokes `ANIM_OT_keyframe_delete_by_name(type=WebGapAnimKeyframeDeleteByNameSet)` (`poll=true`, `FINISHED`) at frame 3, deleting only the current keyframe and preserving the two surrounding keys. + +evidence: + +- Desktop evidence records the selected/active object and named Keying Set changing from `[1, 3, 5]` to `[1, 5]`; the custom property remains at 3.0 and save/reopen is exact. +- WASM/Main reads the same Action as one `[\"delete_target\"][0]` channel with three keyframes before the operation fixture and two keyframes after it. WASM save/reopen is exact, and malformed Blend input is rejected without Main mutation. +- Fixture generation, foreground `VIEW_3D` checker, npm comparator, direct idempotent comparator, and artifact hashing passed. No production reader or protocol change was required because the existing generic Action/F-Curve reader exposes this custom-property channel. + +nextTask: `M16-GAP-00184` diff --git a/docs/status/M16-GAP-00184.md b/docs/status/M16-GAP-00184.md new file mode 100644 index 00000000..35e48fd8 --- /dev/null +++ b/docs/status/M16-GAP-00184.md @@ -0,0 +1,17 @@ +# M16-GAP-00184 Status + +status: done +task: anim.keyframe_delete_v3d operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one selected/active object with a custom `delete_target` property and an Action keyed at frames 1, 3, and 5. A foreground `VIEW_3D` context invokes `ANIM_OT_keyframe_delete_v3d(confirm=false)` (`poll=true`, `FINISHED`) at frame 3, deleting only the current keyframe and preserving the two surrounding keys. + +evidence: + +- Desktop evidence records the selected/active object changing from `[1, 3, 5]` to `[1, 5]`; the custom property remains at 3.0 and save/reopen is exact. +- WASM/Main reads the same Action as one `[\"delete_target\"][0]` channel with three keyframes before the operation fixture and two keyframes after it. WASM save/reopen is exact, and malformed Blend input is rejected without Main mutation. +- Fixture generation, foreground `VIEW_3D` checker, npm comparator, direct idempotent comparator, and artifact hashing passed. No production reader or protocol change was required because the existing generic Action/F-Curve reader exposes this custom-property channel. + +nextTask: `M16-GAP-00185` diff --git a/docs/status/M16-GAP-00185.md b/docs/status/M16-GAP-00185.md new file mode 100644 index 00000000..045dc711 --- /dev/null +++ b/docs/status/M16-GAP-00185.md @@ -0,0 +1,17 @@ +# M16-GAP-00185 Status + +status: done +task: anim.keyframe_delete_vse operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one selected/active image strip with a Scene Action animating `blend_alpha` at frames 1, 3, and 5. A foreground `SEQUENCE_EDITOR` context invokes `ANIM_OT_keyframe_delete_vse(confirm=false)` (`poll=true`, `FINISHED`) at frame 3, deleting only the current strip keyframe and preserving the two surrounding keys. + +evidence: + +- Desktop evidence records the selected/active strip changing from `[1, 3, 5]` to `[1, 5]`; `blend_alpha` remains 0.5 at frame 3 and save/reopen is exact. +- WASM/Main reads the same Scene Action as one `sequence_editor.strips_all[\"WebGapAnimKeyframeDeleteVSEStrip\"].blend_alpha[0]` channel with three keyframes before the operation fixture and two keyframes after it. WASM save/reopen is exact, and malformed Blend input is rejected without Main mutation. +- Fixture generation, foreground `SEQUENCE_EDITOR` checker, npm comparator, direct idempotent comparator, and artifact hashing passed. No production reader or protocol change was required because the existing generic Action/F-Curve reader exposes this Scene channel. + +nextTask: `M16-GAP-00186` diff --git a/docs/status/M16-GAP-00186.md b/docs/status/M16-GAP-00186.md new file mode 100644 index 00000000..1a3cb63b --- /dev/null +++ b/docs/status/M16-GAP-00186.md @@ -0,0 +1,17 @@ +# M16-GAP-00186 Status + +status: done +task: anim.keyframe_insert operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one selected/active object with a custom `insert_target` property and a named active Keying Set. Its Action starts with keys at frames 1 and 5. A foreground `VIEW_3D` context invokes `ANIM_OT_keyframe_insert()` (`poll=true`, `FINISHED`) at frame 3, inserting the current key while preserving the existing keys. + +evidence: + +- Desktop evidence records the Action changing from `[1, 5]` to `[1, 3, 5]`; the inserted key is the only selected key (`[false, true, false]`), the custom property remains at 3.0, and save/reopen is exact. +- WASM/Main reads the same Action as one `[\"insert_target\"][0]` channel with two keyframes before the operation fixture and three keyframes after it. WASM save/reopen is exact, and malformed Blend input is rejected without Main mutation. +- Fixture generation, foreground `VIEW_3D` checker, npm comparator, direct idempotent comparator, and artifact hashing passed. No production reader or protocol change was required because the existing generic Action/F-Curve reader exposes this custom-property channel. + +nextTask: `M16-GAP-00187` diff --git a/docs/status/M16-GAP-00187.md b/docs/status/M16-GAP-00187.md new file mode 100644 index 00000000..b345ae88 --- /dev/null +++ b/docs/status/M16-GAP-00187.md @@ -0,0 +1,17 @@ +# M16-GAP-00187 Status + +status: done +task: anim.keyframe_insert_button operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one selected/active object with a custom `insert_target` property and an Action keyed at frames 1 and 5. A registered Properties panel exposes the animated property as a real UI button. A foreground Properties context invokes `ANIM_OT_keyframe_insert_button(all=true)` through that active button at frame 3 (`poll=true`, `FINISHED`), inserting the current key while preserving the two existing keys. + +evidence: + +- Desktop evidence records the Action changing from `[1, 5]` to `[1, 3, 5]`; the inserted key is the only selected key (`[false, true, false]`), the custom property remains at 3.0 and save/reopen is exact. +- WASM/Main reads the same Action as one `[\"insert_target\"][0]` channel with two keyframes before the operation fixture and three keyframes after it. WASM save/reopen is exact, and malformed Blend input is rejected without Main mutation. +- Fixture generation, foreground Properties UI checker, npm comparator, direct idempotent comparator, and artifact hashing passed. No production reader or protocol change was required because the existing generic Action/F-Curve reader exposes this custom-property channel. + +nextTask: `M16-GAP-00188` diff --git a/docs/status/M16-GAP-00188.md b/docs/status/M16-GAP-00188.md new file mode 100644 index 00000000..986d14a4 --- /dev/null +++ b/docs/status/M16-GAP-00188.md @@ -0,0 +1,17 @@ +# M16-GAP-00188 Status + +status: done +task: anim.keyframe_insert_by_name operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one selected/active object with a custom `insert_target` property, an Action keyed at frames 1 and 5, and a named Keying Set targeting that property. A foreground `VIEW_3D` context invokes `ANIM_OT_keyframe_insert_by_name(type=WebGapAnimKeyframeInsertByNameSet)` (`poll=true`, `FINISHED`) at frame 3, inserting the current key while preserving the two existing keys. + +evidence: + +- Desktop evidence records the Action changing from `[1, 5]` to `[1, 3, 5]`; the inserted key is the only selected key (`[false, true, false]`), the custom property remains at 3.0 and save/reopen is exact. +- WASM/Main reads the same Action as one `[\"insert_target\"][0]` channel with two keyframes before the operation fixture and three keyframes after it. WASM save/reopen is exact, and malformed Blend input is rejected without Main mutation. +- Fixture generation, foreground `VIEW_3D` checker, npm comparator, direct idempotent comparator, and artifact hashing passed. No production reader or protocol change was required because the existing generic Action/F-Curve reader exposes this custom-property channel. + +nextTask: `M16-GAP-00189` diff --git a/docs/status/M16-GAP-00189.md b/docs/status/M16-GAP-00189.md new file mode 100644 index 00000000..a8c12f9c --- /dev/null +++ b/docs/status/M16-GAP-00189.md @@ -0,0 +1,17 @@ +# M16-GAP-00189 Status + +status: done +task: anim.keyframe_insert_menu operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one selected/active object with a custom `insert_target` property, an Action keyed at frames 1 and 5, and a named active Keying Set. A foreground `VIEW_3D` context invokes `ANIM_OT_keyframe_insert_menu(always_prompt=false)` (`poll=true`, `FINISHED`); Blender takes the active-Keying-Set fast path and inserts the current key at frame 3. + +evidence: + +- Desktop evidence records the Action changing from `[1, 5]` to `[1, 3, 5]`; the inserted key is the only selected key (`[false, true, false]`), the custom property remains at 3.0 and save/reopen is exact. +- WASM/Main reads the same Action as one `[\"insert_target\"][0]` channel with two keyframes before the operation fixture and three keyframes after it. WASM save/reopen is exact, and malformed Blend input is rejected without Main mutation. +- Fixture generation, foreground `VIEW_3D` checker, npm comparator, direct idempotent comparator, and artifact hashing passed. No production reader or protocol change was required because the existing generic Action/F-Curve reader exposes this custom-property channel. + +nextTask: `M16-GAP-00190` diff --git a/docs/status/M16-GAP-00190.md b/docs/status/M16-GAP-00190.md new file mode 100644 index 00000000..2d79656a --- /dev/null +++ b/docs/status/M16-GAP-00190.md @@ -0,0 +1,17 @@ +# M16-GAP-00190 Status + +status: done +task: anim.keying_set_active_set operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one selected/active object with a custom `active_target` property, a three-key Action, and two named Keying Sets. A foreground `VIEW_3D` context invokes `ANIM_OT_keying_set_active_set(type=WebGapAnimKeyingSetActiveB)` (`poll=true`, `FINISHED`), changing the active Keying Set from A to B without changing the Action. + +evidence: + +- Desktop evidence records active Keying Set `WebGapAnimKeyingSetActiveA` changing to `WebGapAnimKeyingSetActiveB`; the Action remains `[1, 3, 5]`, the property remains 3.0, and save/reopen is exact. +- WASM/Main reads the same fixture with the visible Action unchanged and save/reopen exact. The current scene snapshot does not expose Keying Set metadata, so the report explicitly records `keyingSetMetadata: NOT_EXPOSED_BY_SCENE_SNAPSHOT`; malformed Blend input is rejected without Main mutation. +- Fixture generation, foreground `VIEW_3D` checker, npm comparator, direct idempotent comparator, and artifact hashing passed. No production reader or protocol change was made. + +nextTask: `M16-GAP-00191` diff --git a/docs/status/M16-GAP-00191.md b/docs/status/M16-GAP-00191.md new file mode 100644 index 00000000..61336fb2 --- /dev/null +++ b/docs/status/M16-GAP-00191.md @@ -0,0 +1,17 @@ +# M16-GAP-00191 Status + +status: done +task: anim.keying_set_add operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one selected/active object with a custom `add_target` property and a three-key Action, but no scene Keying Sets. A foreground `VIEW_3D` context invokes `ANIM_OT_keying_set_add()` (`poll=true`, `FINISHED`), adding and activating one empty Keying Set without changing the Action. + +evidence: + +- Desktop evidence records Keying Set count `0→1`, an active newly-added set, unchanged `[1, 3, 5]` Action data, and exact save/reopen. +- WASM/Main reads the same fixture with the visible Action unchanged and save/reopen exact. The current scene snapshot does not expose Keying Set metadata, so the report explicitly records `keyingSetMetadata: NOT_EXPOSED_BY_SCENE_SNAPSHOT`; malformed Blend input is rejected without Main mutation. +- Fixture generation, foreground `VIEW_3D` checker, npm comparator, direct idempotent comparator, and artifact hashing passed. No production reader or protocol change was made. + +nextTask: `M16-GAP-00192` diff --git a/docs/status/M16-GAP-00192.md b/docs/status/M16-GAP-00192.md new file mode 100644 index 00000000..42c44fed --- /dev/null +++ b/docs/status/M16-GAP-00192.md @@ -0,0 +1,17 @@ +# M16-GAP-00192 Status + +status: done +task: anim.keying_set_export operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one selected/active object with a custom `export_target` property, a three-key Action, and one named Keying Set. Blender invokes `ANIM_OT_keying_set_export(filepath=..., filter_python=true)` (`poll=true`, `FINISHED`) and writes the Keying Set Python export without mutating Main. + +evidence: + +- Desktop evidence records unchanged object/Action state, exact save/reopen, and a non-empty hash-bound exported Python script. +- WASM/Main reads the same fixture with the visible Action unchanged and save/reopen exact. The current scene snapshot does not expose Keying Set metadata, so the report explicitly records `keyingSetMetadata: NOT_EXPOSED_BY_SCENE_SNAPSHOT`; malformed Blend input is rejected without Main mutation. +- Fixture generation, background Blender export checker, npm comparator, direct idempotent comparator, export-script hashing, and artifact hashing passed. No production reader or protocol change was made. + +nextTask: `M16-GAP-00193` diff --git a/docs/status/M16-GAP-00193.md b/docs/status/M16-GAP-00193.md new file mode 100644 index 00000000..97c0fa5b --- /dev/null +++ b/docs/status/M16-GAP-00193.md @@ -0,0 +1,17 @@ +# M16-GAP-00193 Status + +status: done +task: anim.keying_set_path_add operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one selected/active object with a three-key Action and one empty active Keying Set. Blender invokes `ANIM_OT_keying_set_path_add()` (`poll=true`, `FINISHED`), adding one empty path with the expected default fields without changing the Action. + +evidence: + +- Desktop evidence records Keying Set path count `0→1`, the empty path defaults, unchanged `[1, 3, 5]` Action data, and exact save/reopen. +- WASM/Main reads the same post-operation fixture with the visible Action unchanged and save/reopen exact. The current scene snapshot does not expose Keying Set metadata, so the report records `keyingSetMetadata: NOT_EXPOSED_BY_SCENE_SNAPSHOT`; malformed Blend input is rejected without Main mutation. +- Fixture generation, background Blender operator checker, npm comparator, direct idempotent comparator, and artifact hashing passed. No production reader or protocol change was made. + +nextTask: `M16-GAP-00194` diff --git a/docs/status/M16-GAP-00194.md b/docs/status/M16-GAP-00194.md new file mode 100644 index 00000000..661f6765 --- /dev/null +++ b/docs/status/M16-GAP-00194.md @@ -0,0 +1,17 @@ +# M16-GAP-00194 Status + +status: done +task: anim.keying_set_path_remove operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one selected/active object with a three-key Action and one active Keying Set path. Blender invokes `ANIM_OT_keying_set_path_remove()` (`poll=true`, `FINISHED`), removing the active path without changing the Action. + +evidence: + +- Desktop evidence records Keying Set path count `1→0`, the pre-existing path fields, unchanged `[1, 3, 5]` Action data, and exact save/reopen. +- WASM/Main reads the same post-operation fixture with the visible Action unchanged and save/reopen exact. The current scene snapshot does not expose Keying Set metadata, so the report records `keyingSetMetadata: NOT_EXPOSED_BY_SCENE_SNAPSHOT`; malformed Blend input is rejected without Main mutation. +- Fixture generation, background Blender operator checker, npm comparator, direct idempotent comparator, and artifact hashing passed. No production reader or protocol change was made. + +nextTask: `M16-GAP-00195` diff --git a/docs/status/M16-GAP-00195.md b/docs/status/M16-GAP-00195.md new file mode 100644 index 00000000..298901bf --- /dev/null +++ b/docs/status/M16-GAP-00195.md @@ -0,0 +1,17 @@ +# M16-GAP-00195 Status + +status: done +task: anim.keying_set_remove operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one selected/active object with a three-key Action and one empty active Keying Set. Blender invokes `ANIM_OT_keying_set_remove()` (`poll=true`, `FINISHED`), removing the active Keying Set without changing the Action. + +evidence: + +- Desktop evidence records Keying Set count `1→0`, active set `WebGapAnimKeyingSetRemoveSet→null`, unchanged `[1, 3, 5]` Action data, and exact save/reopen. +- WASM/Main reads the same post-operation fixture with the visible Action unchanged and save/reopen exact. The current scene snapshot does not expose Keying Set metadata, so the report records `keyingSetMetadata: NOT_EXPOSED_BY_SCENE_SNAPSHOT`; malformed Blend input is rejected without Main mutation. +- Fixture generation, background Blender operator checker, npm comparator, direct idempotent comparator, and artifact hashing passed. No production reader or protocol change was made. + +nextTask: `M16-GAP-00196` diff --git a/docs/status/M16-GAP-00196.md b/docs/status/M16-GAP-00196.md new file mode 100644 index 00000000..f9c91d32 --- /dev/null +++ b/docs/status/M16-GAP-00196.md @@ -0,0 +1,17 @@ +# M16-GAP-00196 Status + +status: done +task: anim.keyingset_button_add operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one selected/active object with a three-key Action and no scene Keying Set. A real `PROPERTIES` RNA button invokes `ANIM_OT_keyingset_button_add()` (`poll=true`, `FINISHED`), creating `ButtonKeyingSet` and adding the active `button_target` path. + +evidence: + +- Desktop evidence records Keying Set count `0→1`, path count `0→1`, exact path fields, unchanged `[1, 3, 5]` Action data, and exact save/reopen. +- WASM/Main reads the same post-operation fixture with the visible Action unchanged and save/reopen exact. The current scene snapshot does not expose Keying Set metadata, so the report records `keyingSetMetadata: NOT_EXPOSED_BY_SCENE_SNAPSHOT`; malformed Blend input is rejected without Main mutation. +- Fixture generation, foreground Chromium-scope desktop UI checker, npm comparator, direct idempotent comparator, and artifact hashing passed. No production reader or protocol change was made. + +nextTask: `M16-GAP-00197` diff --git a/docs/status/M16-GAP-00197.md b/docs/status/M16-GAP-00197.md new file mode 100644 index 00000000..4c5e897b --- /dev/null +++ b/docs/status/M16-GAP-00197.md @@ -0,0 +1,17 @@ +# M16-GAP-00197 Status + +status: done +task: anim.keyingset_button_remove operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one selected/active object with a three-key Action and one active `ButtonKeyingSet` path. A real `PROPERTIES` RNA button invokes `ANIM_OT_keyingset_button_remove()` (`poll=true`, `FINISHED`), removing the active property path without changing the Action. + +evidence: + +- Desktop evidence records path count `1→0`, the unchanged active Keying Set, exact pre-existing path fields, unchanged `[1, 3, 5]` Action data, and exact save/reopen. +- WASM/Main reads the same post-operation fixture with the visible Action unchanged and save/reopen exact. The current scene snapshot does not expose Keying Set metadata, so the report records `keyingSetMetadata: NOT_EXPOSED_BY_SCENE_SNAPSHOT`; malformed Blend input is rejected without Main mutation. +- Fixture generation, foreground desktop UI checker, npm comparator, direct idempotent comparator, and artifact hashing passed. No production reader or protocol change was made. + +nextTask: `M16-GAP-00198` diff --git a/docs/status/M16-GAP-00198.md b/docs/status/M16-GAP-00198.md new file mode 100644 index 00000000..a8f830bc --- /dev/null +++ b/docs/status/M16-GAP-00198.md @@ -0,0 +1,18 @@ +# M16-GAP-00198 Status + +status: done +task: anim.merge_animation operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains two selected mesh objects. The active object owns `WebGapAnimMergeActiveAction`; the source object owns `WebGapAnimMergeSourceAction`, each with one three-key custom-property channel. +- Blender invokes `ANIM_OT_merge_animation` with `poll=true` and `FINISHED`, moving the source slot into the active action. Both objects then observe `WebGapAnimMergeActiveAction` with both channels; the source action has no remaining users. + +evidence: + +- Desktop evidence records the exact pre/post action channels, operator status, active/selected state, and save/reopen stability. +- WASM/Main reads the post-operation fixture with two `WebGapAnimMergeActiveAction` animation entries (one per object), both carrying the merged channels; save/reopen is exact and malformed Blend input is rejected without Main mutation. +- Fixture generation, background desktop operator checker, npm comparator, direct idempotent comparator, Python syntax checks, and artifact hashing passed. No production reader or protocol change was made. + +nextTask: `M16-GAP-00199` diff --git a/docs/status/M16-GAP-00199.md b/docs/status/M16-GAP-00199.md new file mode 100644 index 00000000..2c61b088 --- /dev/null +++ b/docs/status/M16-GAP-00199.md @@ -0,0 +1,18 @@ +# M16-GAP-00199 Status + +status: done +task: anim.paste_driver_button operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one mesh object with a driven `source_target` custom property and an undriven `paste_target` custom property. Desktop UI evidence copies the source driver and pastes it into the target through `ANIM_OT_paste_driver_button`. +- The saved fixture exposes both scripted drivers with the same expression in WASM/Main; no reader, protocol, or browser change was required. + +evidence: + +- Desktop evidence records the source/target driver state before and after the UI operation, `poll=true`, `FINISHED`, `DRIVER_PASTED`, and exact save/reopen. The checker also preserves this evidence on repeated runs. +- WASM/Main reads both drivers from the same fixture, preserves them across save/reopen, and rejects malformed Blend input without Main mutation. +- Fixture generation, foreground desktop checker, npm comparator, direct comparator, and task-context checks passed. Chromium-only policy was preserved; no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00200` diff --git a/docs/status/M16-GAP-00200.md b/docs/status/M16-GAP-00200.md new file mode 100644 index 00000000..1269905d --- /dev/null +++ b/docs/status/M16-GAP-00200.md @@ -0,0 +1,18 @@ +# M16-GAP-00200 Status + +status: done +task: anim.previewrange_clear operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture starts with a `2..6` scene preview range. Desktop runs `ANIM_OT_previewrange_clear` in the active Dope Sheet animation context and saves the cleared Main. +- WASM/Main observes the same scene with no `previewRange` field and an unchanged frame range; no reader, protocol, or browser change was required. + +evidence: + +- Desktop evidence records `poll=true`, `FINISHED`, `PREVIEW_RANGE_CLEARED`, the cleared values, and exact save/reopen. Repeated checker runs preserve the fixture hash. +- WASM/Main compares the cleared scene, preserves it across save/reopen, and rejects malformed Blend input without Main mutation. +- Fixture generation, desktop checker, npm comparator, direct comparator, and task-context checks passed. Chromium-only policy was preserved; no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00201` diff --git a/docs/status/M16-GAP-00201.md b/docs/status/M16-GAP-00201.md new file mode 100644 index 00000000..793678be --- /dev/null +++ b/docs/status/M16-GAP-00201.md @@ -0,0 +1,18 @@ +# M16-GAP-00201 Status + +status: done +task: anim.previewrange_set operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture uses the active Dope Sheet animation region and a deterministic border gesture to set the Scene preview range to `2..6` through `ANIM_OT_previewrange_set`. +- WASM/Main observes the same `previewRange` and frame bounds; no reader, protocol, or browser change was required. + +evidence: + +- Desktop evidence records the animation-region poll, `FINISHED`, `PREVIEW_RANGE_SET`, the `2..6` values, and exact save/reopen. +- WASM/Main compares the preview range from the same fixture, preserves it across save/reopen, and rejects malformed Blend input without Main mutation. +- Fixture generation, desktop checker, npm comparator, direct comparator, and task-context checks passed. Chromium-only policy was preserved; no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00202` diff --git a/docs/status/M16-GAP-00202.md b/docs/status/M16-GAP-00202.md new file mode 100644 index 00000000..a5379e59 --- /dev/null +++ b/docs/status/M16-GAP-00202.md @@ -0,0 +1,18 @@ +# M16-GAP-00202 Status + +status: done +task: anim.replace_action operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture has two objects using `WebGapAnimReplaceOldAction` and one object using `WebGapAnimReplaceNewAction`. Desktop calls `ANIM_OT_replace_action` with the explicit action session UIDs. +- All three object users switch to the new action; the old action remains unlinked with its original channels. WASM/Main exposes both the replaced users and preserved unlinked action without reader/protocol changes. + +evidence: + +- Desktop evidence records the old/new action users, `poll=true`, `FINISHED`, `ACTIONS_REPLACED`, and exact save/reopen. Repeated checker runs preserve the initial evidence and fixture hash. +- WASM/Main compares three new-action targets and the unlinked old action, preserves them across save/reopen, and rejects malformed Blend input without Main mutation. +- Fixture generation, desktop checker, npm comparator, direct comparator, and task-context checks passed. Chromium-only policy was preserved; no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00203` diff --git a/docs/status/M16-GAP-00203.md b/docs/status/M16-GAP-00203.md new file mode 100644 index 00000000..550bfbda --- /dev/null +++ b/docs/status/M16-GAP-00203.md @@ -0,0 +1,18 @@ +# M16-GAP-00203 Status + +status: done +task: anim.replace_action_new operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture has two objects using `WebGapAnimReplaceNewOldAction`. Desktop runs `ANIM_OT_replace_action_new` with the old action session UID; Blender creates a new empty action and assigns it to both users. +- The old action remains unlinked with its original channels. WASM/Main preserves that visible old-action evidence; the empty replacement action is intentionally not exposed as an animation entry. + +evidence: + +- Desktop evidence records `poll=true`, `FINISHED`, `ACTION_REPLACED_WITH_NEW`, the new action assignment, and exact save/reopen. Repeated checker runs preserve the initial evidence and fixture hash. +- WASM/Main compares the unlinked old action, preserves it across save/reopen, and rejects malformed Blend input without Main mutation. +- Fixture generation, desktop checker, npm comparator, direct comparator, and task-context checks passed. Chromium-only policy was preserved; no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00204` diff --git a/docs/status/M16-GAP-00204.md b/docs/status/M16-GAP-00204.md new file mode 100644 index 00000000..ffcbbba6 --- /dev/null +++ b/docs/status/M16-GAP-00204.md @@ -0,0 +1,18 @@ +# M16-GAP-00204 Status + +status: done +task: anim.scene_range_frame operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture uses a Dope Sheet animation region with an active preview playback range. Desktop runs `ANIM_OT_scene_range_frame` and frames the region to that scene range. +- The resulting `view2d` state is observable in WASM/Main editor workflow data; no reader, protocol, or browser change was required. + +evidence: + +- Desktop evidence records `poll=true`, `FINISHED`, `VIEW_FRAMED_TO_SCENE_RANGE`, the exact view bounds, and save/reopen stability. +- WASM/Main matches the same Dope Sheet `view2d`, preserves editor workflow across save/reopen, and rejects malformed Blend input without Main mutation. +- Fixture generation, desktop checker, npm comparator, direct comparator, and task-context checks passed. Chromium-only policy was preserved; no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00205` diff --git a/docs/status/M16-GAP-00205.md b/docs/status/M16-GAP-00205.md new file mode 100644 index 00000000..aa23a594 --- /dev/null +++ b/docs/status/M16-GAP-00205.md @@ -0,0 +1,18 @@ +# M16-GAP-00205 Status + +status: done +task: anim.separate_slots operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture has two objects using separate slots in one layered action. Desktop runs `ANIM_OT_separate_slots` and creates one action per slot, reassigning the two objects. +- WASM/Main observes the two new action targets and their slot-specific channels; the original action is empty and omitted from the animation snapshot. + +evidence: + +- Desktop evidence records `poll=true`, `FINISHED`, `SLOTS_SEPARATED`, both new action assignments, and exact save/reopen. Repeated checker runs preserve the initial evidence and fixture hash. +- WASM/Main compares both separated actions, preserves them across save/reopen, and rejects malformed Blend input without Main mutation. +- Fixture generation, desktop checker, npm comparator, direct comparator, and task-context checks passed. Chromium-only policy was preserved; no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00206` diff --git a/docs/status/M16-GAP-00206.md b/docs/status/M16-GAP-00206.md new file mode 100644 index 00000000..65b49073 --- /dev/null +++ b/docs/status/M16-GAP-00206.md @@ -0,0 +1,18 @@ +# M16-GAP-00206 Status + +status: done +task: anim.slot_channels_move_to_new_action operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture has two objects using separate slots in one action. Desktop selects one Action Slot in the Action Editor and runs `ANIM_OT_slot_channels_move_to_new_action`. +- The selected slot moves to `WebGapMoveSlotAAction`; the other object remains on the original action. WASM/Main observes both resulting action targets without reader/protocol changes. + +evidence: + +- Desktop evidence records `poll=true`, `FINISHED`, `SLOT_MOVED_TO_NEW_ACTION`, both action assignments, and exact save/reopen. Repeated checker runs preserve the initial evidence and fixture hash. +- WASM/Main compares the moved and remaining channels, preserves them across save/reopen, and rejects malformed Blend input without Main mutation. +- Fixture generation, desktop checker, npm comparator, direct comparator, and task-context checks passed. Chromium-only policy was preserved; no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00207` diff --git a/docs/status/M16-GAP-00207.md b/docs/status/M16-GAP-00207.md new file mode 100644 index 00000000..27695c80 --- /dev/null +++ b/docs/status/M16-GAP-00207.md @@ -0,0 +1,18 @@ +# M16-GAP-00207 Status + +status: done +task: anim.slot_new_for_id operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture assigns one Action Slot to `WebGapAnimNewSlotObject`; desktop runs `ANIM_OT_slot_new_for_id` with the animated ID context and duplicates the slot and channelbag. +- The WASM/Main reader now selects the assigned `AnimData.slot_handle` channelbag and exposes `slotIdentifier` and `slotCount` on the animation snapshot. The duplicated slot remains stable across save/reopen. + +evidence: + +- Desktop evidence records `poll=true`, `FINISHED`, `SLOT_DUPLICATED`, both Slot identifiers, and exact save/reopen. Repeated checker runs preserve the initial evidence and fixture hash. +- WASM/Main observes `OBWebGapAnimNewSlot.001`, two slots, the expected keyframes, exact save/reopen, and rejects malformed Blend input without Main mutation. +- The generator, npm comparator, direct comparator, WebEngine rebuild, and task-context checks passed. Chromium-only policy was preserved; no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00208` diff --git a/docs/status/M16-GAP-00208.md b/docs/status/M16-GAP-00208.md new file mode 100644 index 00000000..7ef071cf --- /dev/null +++ b/docs/status/M16-GAP-00208.md @@ -0,0 +1,18 @@ +# M16-GAP-00208 Status + +status: done +task: anim.slot_unassign_from_constraint operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture gives `WebGapAnimConstraintSlotObject` an Action constraint with `WebGapAnimConstraintSlotAction` and one assigned `OBWebGapConstraintSlot`. +- Desktop runs `ANIM_OT_slot_unassign_from_constraint` with the constraint context pointer. The reader exposes the constraint's action, slot identifier, handle, and assigned state in the node snapshot. + +evidence: + +- Desktop evidence records `poll=true`, `FINISHED`, `CONSTRAINT_SLOT_UNASSIGNED`, the nonzero-to-zero handle transition, and exact save/reopen. Repeated checker runs preserve the initial evidence and fixture hash. +- WASM/Main observes the retained action and identifier with `actionSlotAssigned=false` and handle `0`, preserves it across save/reopen, and rejects malformed Blend input without Main mutation. +- The generator, npm comparator, direct comparator, WebEngine rebuild, and task-context checks passed. Chromium-only policy was preserved; no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00209` diff --git a/docs/status/M16-GAP-00209.md b/docs/status/M16-GAP-00209.md new file mode 100644 index 00000000..b99e7ef3 --- /dev/null +++ b/docs/status/M16-GAP-00209.md @@ -0,0 +1,18 @@ +# M16-GAP-00209 Status + +status: done +task: anim.slot_unassign_from_id operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture assigns `OBWebGapUnassignIdSlot` to `WebGapAnimUnassignIdObject` through `WebGapAnimUnassignIdAction` and keys one custom property. +- Desktop runs `ANIM_OT_slot_unassign_from_id` with the animated ID context. The reader preserves the Action animation and exposes the retained slot identifier plus assigned/handle state. + +evidence: + +- Desktop evidence records `poll=true`, `FINISHED`, `ID_SLOT_UNASSIGNED`, the nonzero-to-zero handle transition, retained `lastSlotIdentifier`, and exact save/reopen. Repeated checker runs preserve the initial evidence and fixture hash. +- WASM/Main observes `slotAssigned=false` and handle `0` with the expected keyframes, preserves it across save/reopen, and rejects malformed Blend input without Main mutation. +- The generator, npm comparator, direct comparator, WebEngine rebuild, and task-context checks passed. Chromium-only policy was preserved; no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00210` diff --git a/docs/status/M16-GAP-00210.md b/docs/status/M16-GAP-00210.md new file mode 100644 index 00000000..83b2a324 --- /dev/null +++ b/docs/status/M16-GAP-00210.md @@ -0,0 +1,18 @@ +# M16-GAP-00210 Status + +status: done +task: anim.slot_unassign_from_nla_strip operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains `WebGapNlaSlotTrack` with `WebGapNlaSlotStrip` referencing `WebGapAnimNlaSlotAction` and `OBWebGapNlaSlot`. +- Desktop runs `ANIM_OT_slot_unassign_from_nla_strip` with the NLA strip context pointer. The reader exposes NLA strip slot identifier, handle, and assigned state. + +evidence: + +- Desktop evidence records `poll=true`, `FINISHED`, `NLA_SLOT_UNASSIGNED`, the nonzero-to-zero handle transition, retained `lastSlotIdentifier`, and exact save/reopen. Repeated checker runs preserve the initial evidence and fixture hash. +- WASM/Main observes the same strip and Action with `actionSlotAssigned=false` and handle `0`, preserves it across save/reopen, and rejects malformed Blend input without Main mutation. +- The generator, npm comparator, direct comparator, WebEngine rebuild, and task-context checks passed. Chromium-only policy was preserved; no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00211` diff --git a/docs/status/M16-GAP-00211.md b/docs/status/M16-GAP-00211.md new file mode 100644 index 00000000..2bfb26ab --- /dev/null +++ b/docs/status/M16-GAP-00211.md @@ -0,0 +1,18 @@ +# M16-GAP-00211 Status + +status: done +task: anim.start_frame_set operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal scene starts at frame 42 with a scene range of 1-120. The foreground animation-area context invokes `ANIM_OT_start_frame_set` (`poll=true`, `FINISHED`) and sets the scene start frame to 42. +- The existing Main reader exposes the same scene frame tuple through `Scene.r.cfra`, `Scene.r.sfra`, and `Scene.r.efra`; no unrelated data-block, editor, or browser behavior was changed. + +evidence: + +- Desktop evidence records `FRAME_START_SET` and exact save/reopen. Repeated comparator runs preserve the fixture hash and report shape. +- WASM/Main observes `{current: 42, start: 42, end: 120}` from the same fixture, preserves it across save/reopen, and rejects malformed Blend input without Main mutation. +- The generator, npm comparator, direct comparator, and task-context checks passed. Chromium-only policy was preserved; no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00212` diff --git a/docs/status/M16-GAP-00212.md b/docs/status/M16-GAP-00212.md new file mode 100644 index 00000000..da01c3f9 --- /dev/null +++ b/docs/status/M16-GAP-00212.md @@ -0,0 +1,19 @@ +# M16-GAP-00212 Status + +status: done +task: anim.update_animated_transform_constraints operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains a mesh object with a `TRANSFORM` constraint mapped from rotation and one animated legacy `from_min_x` F-curve. +- Desktop runs `ANIM_OT_update_animated_transform_constraints(use_convert_to_radians=true)` (`poll=true`, `FINISHED`) and rewrites the channel path to `from_min_x_rot`. +- The existing Main reader exposes the rewritten Action channel and Transform constraint metadata; no unrelated data-block, editor, or browser behavior was changed. + +evidence: + +- Desktop evidence records the old and rewritten paths, `TRANSFORM_CONSTRAINT_PATHS_UPDATED`, and exact save/reopen. Repeated checker runs preserve the initial report and fixture hash. +- WASM/Main observes the same Action channel at `constraints["WebGapAnimatedTransformConstraint"].from_min_x_rot[0]`, keyframes at frames 1 and 10, constraint type code 19, exact save/reopen, and malformed Blend rejection without Main mutation. +- The generator, npm comparator, direct comparator, and task-context checks passed. Chromium-only policy was preserved; no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00213` diff --git a/docs/status/M16-GAP-00213.md b/docs/status/M16-GAP-00213.md new file mode 100644 index 00000000..088d5d27 --- /dev/null +++ b/docs/status/M16-GAP-00213.md @@ -0,0 +1,19 @@ +# M16-GAP-00213 Status + +status: done +task: anim.version_bone_hide_property operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one selected armature object, one bone, an armature-data Action with `bones["WebGapVersionBoneHideBone"].hide`, and an object Action with an anchor channel. +- Desktop runs `ANIM_OT_version_bone_hide_property` (`poll=true`, `FINISHED`) and copies the hide F-curve into the object Action as `pose.bones["WebGapVersionBoneHideBone"].hide`, retaining the armature source channel. +- The existing Main reader exposes both Action channels and the armature data; no unrelated data-block, editor, or browser behavior was changed. + +evidence: + +- Desktop evidence records `BONE_HIDE_FCURVE_MOVED_TO_OBJECT_ACTION` and exact save/reopen. Repeated checker runs preserve the initial report and fixture hash. +- WASM/Main observes the copied object channel with frames 1 and 10 and values 0 and 1, retains the armature Action channel, preserves both across save/reopen, and rejects malformed Blend input without Main mutation. +- The generator, npm comparator, direct comparator, and task-context checks passed. Chromium-only policy was preserved; no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00214` diff --git a/docs/status/M16-GAP-00214.md b/docs/status/M16-GAP-00214.md new file mode 100644 index 00000000..2f17150f --- /dev/null +++ b/docs/status/M16-GAP-00214.md @@ -0,0 +1,19 @@ +# M16-GAP-00214 Status + +status: done +task: anim.view_curve_in_graph_editor operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one selected mesh object, one custom animated scalar property with frames 1 and 10, and a persisted Graph Editor area. +- Desktop activates the property button and runs `ANIM_OT_view_curve_in_graph_editor` with `poll=true` and `FINISHED`; the operator changes the Graph Editor view bounds while leaving the Action data unchanged. +- The Main reader now exposes `View2D` state for `GRAPH` editor main regions, alongside the existing Dope Sheet exposure. No other editor or data-block behavior changed. + +evidence: + +- Desktop evidence records `GRAPH_VIEW_FRAMED`, exact save/reopen, and the before/after Graph Editor bounds. The source fixture remains the minimal persisted Graph Editor state used by WASM/Main. +- WASM/Main observes the same fixture's `GRAPH` main-region `View2D`, preserves it across save/reopen, and rejects malformed Blend input without Main mutation. +- The generator, npm comparator, direct comparator, Chromium-only foreground desktop run, and task-context checks passed. No Firefox/WebKit run was made. + +nextTask: `M16-GAP-00215` diff --git a/docs/status/M16-GAP-00215.md b/docs/status/M16-GAP-00215.md new file mode 100644 index 00000000..2ed6e3f6 --- /dev/null +++ b/docs/status/M16-GAP-00215.md @@ -0,0 +1,19 @@ +# M16-GAP-00215 Status + +status: done +task: armature.align operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one armature with two independent edit bones. The child starts at an angled axis and the parent is the active selected bone. +- Desktop runs `ARMATURE_OT_align` with `poll=true` and `FINISHED`, aligns the child axis to the active parent, and preserves the result through save/reopen. +- The existing Main reader exposes the same armature bone `head`/`tail` data; no other data-block, editor, or browser behavior changed. + +evidence: + +- The generator, desktop checker, npm comparator, direct comparator, and task-context checks passed. The checker is repeat-safe after a persisted aligned fixture and records the aligned child state. +- WASM/Main observes the same parent/child coordinates, preserves them across save/reopen, and rejects malformed Blend input without Main mutation. +- Chromium-only policy was preserved; no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00216` diff --git a/docs/status/M16-GAP-00216.md b/docs/status/M16-GAP-00216.md new file mode 100644 index 00000000..470a6f08 --- /dev/null +++ b/docs/status/M16-GAP-00216.md @@ -0,0 +1,19 @@ +# M16-GAP-00216 Status + +status: done +task: armature.assign_to_collection operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one armature with source and target bone collections, one parent bone, and one selected child initially assigned only to the source collection. +- Desktop runs `ARMATURE_OT_assign_to_collection(collection_index=1)` with `poll=true` and `FINISHED`, assigning the child to the target collection and preserving both memberships through save/reopen. +- The Main reader now exposes bounded armature `boneCollections` entries with collection name/index and member bone IDs. No other collection, editor, or browser behavior changed. + +evidence: + +- The reader rebuild, generator, desktop checker, npm comparator, direct comparator, and task-context checks passed. Repeated checker runs recognize the persisted assignment and remain idempotent. +- WASM/Main observes source and target membership for the same child bone, preserves it across save/reopen, and rejects malformed Blend input without Main mutation. +- Chromium-only policy was preserved; no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00217` diff --git a/docs/status/M16-GAP-00217.md b/docs/status/M16-GAP-00217.md new file mode 100644 index 00000000..22f8fe4e --- /dev/null +++ b/docs/status/M16-GAP-00217.md @@ -0,0 +1,19 @@ +# M16-GAP-00217 Status + +status: done +task: armature.autoside_names operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one armature with two selected bones on opposite sides of the X axis. +- Desktop runs `ARMATURE_OT_autoside_names(type='XAXIS')` with `poll=true` and `FINISHED`, naming the positive-X bone `.L` and the negative-X bone `.R`, then preserves both names through save/reopen. +- The existing Main reader exposes the same armature bone names; no new reader field, data-block, editor, or browser behavior was added. + +evidence: + +- The generator, desktop checker, npm comparator, direct comparator, and task-context checks passed. Repeated checker runs recognize the persisted names and remain idempotent. +- WASM/Main observes the same `.L`/`.R` names for the same fixture, preserves them across save/reopen, and rejects malformed Blend input without Main mutation. +- Chromium-only policy was preserved; no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00218` diff --git a/docs/status/M16-GAP-00218.md b/docs/status/M16-GAP-00218.md new file mode 100644 index 00000000..8207385d --- /dev/null +++ b/docs/status/M16-GAP-00218.md @@ -0,0 +1,19 @@ +# M16-GAP-00218 Status + +status: done +task: armature.bone_primitive_add operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one empty armature object and a fixed 3D cursor at `(1.5, -2.0, 0.75)`. +- Desktop runs `ARMATURE_OT_bone_primitive_add(name, length=2.5, align='UP', space='OBJECT', use_deform=false)` with `poll=true` and `FINISHED`, creating the named bone at the cursor and preserving its head/tail through save/reopen. +- The existing Main reader exposes the same armature bone name and coordinates; no new reader field, data-block, editor, or browser behavior was added. + +evidence: + +- The generator, desktop checker, npm comparator, direct comparator, and task-context checks passed. Repeated checker runs recognize the persisted bone and remain idempotent. +- WASM/Main observes the same cursor-created bone, preserves it across save/reopen, and rejects malformed Blend input without Main mutation. +- Chromium-only policy was preserved; no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00219` diff --git a/docs/status/M16-GAP-00219.md b/docs/status/M16-GAP-00219.md new file mode 100644 index 00000000..d0de2196 --- /dev/null +++ b/docs/status/M16-GAP-00219.md @@ -0,0 +1,19 @@ +# M16-GAP-00219 Status + +status: done +task: armature.calculate_roll operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one selected bone aligned along +Y with zero initial roll. +- Desktop runs `ARMATURE_OT_calculate_roll(type='GLOBAL_POS_X', axis_flip=false, axis_only=false)` with `poll=true` and `FINISHED`, producing a roll of approximately `pi/2` and preserving the resulting matrix through save/reopen. +- The existing Main reader exposes the same armature bone head/tail and rest matrix; no new reader field, data-block, editor, or browser behavior was added. + +evidence: + +- The generator, desktop checker, npm comparator, direct comparator, and task-context checks passed. Repeated checker runs recognize the persisted roll and remain idempotent. +- WASM/Main observes the same calculated orientation, preserves it across save/reopen, and rejects malformed Blend input without Main mutation. +- Chromium-only policy was preserved; no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00220` diff --git a/docs/status/M16-GAP-00220.md b/docs/status/M16-GAP-00220.md new file mode 100644 index 00000000..8f7b8116 --- /dev/null +++ b/docs/status/M16-GAP-00220.md @@ -0,0 +1,19 @@ +# M16-GAP-00220 Status + +status: done +task: armature.click_extrude operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one selected armature bone from `(0, 0, 0)` to `(0, 2, 0)` and a fixed cursor at `(1.5, 2.0, 1.0)`. +- Desktop runs `ARMATURE_OT_click_extrude` with `poll=true` and `FINISHED`, creating a connected `.001` child whose armature-space tail reaches the cursor and preserving it through save/reopen. +- The existing Main reader exposes the parent relationship, raw child coordinates, and rest matrix; the comparator derives the same armature-space endpoint without changing unrelated armature fields. + +evidence: + +- The generator, desktop checker, npm comparator, direct comparator, and task-context checks passed. Repeated checker runs recognize the persisted child and remain idempotent. +- WASM/Main observes the same two-bone hierarchy, preserves it across save/reopen, and rejects malformed Blend input without Main mutation. +- Chromium-only policy was preserved; no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00221` diff --git a/docs/status/M16-GAP-00221.md b/docs/status/M16-GAP-00221.md new file mode 100644 index 00000000..6445439a --- /dev/null +++ b/docs/status/M16-GAP-00221.md @@ -0,0 +1,19 @@ +# M16-GAP-00221 Status + +status: done +task: armature.collection_add operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one armature bone assigned to `WebGapArmatureCollectionAddExisting`. +- Desktop runs `ARMATURE_OT_collection_add` with `poll=true` and `FINISHED`, creating the `Bones` collection as index 1 and preserving the existing bone membership through save/reopen. +- The existing Main reader exposes both bone collections and their member IDs; no new reader field, data-block, editor, or browser behavior was added. + +evidence: + +- The generator, desktop checker, npm comparator, direct comparator, and task-context checks passed. Repeated checker runs recognize the persisted collection and remain idempotent. +- WASM/Main observes the same collection names, indices, and memberships, preserves them across save/reopen, and rejects malformed Blend input without Main mutation. +- Chromium-only policy was preserved; no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00222` diff --git a/docs/status/M16-GAP-00222.md b/docs/status/M16-GAP-00222.md new file mode 100644 index 00000000..e008ff86 --- /dev/null +++ b/docs/status/M16-GAP-00222.md @@ -0,0 +1,19 @@ +# M16-GAP-00222 Status + +status: done +task: armature.collection_assign operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one armature bone assigned to `WebGapArmatureCollectionAssignSource` and an empty target collection. +- Desktop runs `ARMATURE_OT_collection_assign(name=target)` with `poll=true` and `FINISHED`, adding the selected bone to the target while preserving its source membership through save/reopen. +- The existing Main reader exposes both collection member ID lists; no new reader field, data-block, editor, or browser behavior was added. + +evidence: + +- The generator, desktop checker, npm comparator, direct comparator, and task-context checks passed. Repeated checker runs recognize the persisted assignment and remain idempotent. +- WASM/Main observes the same assigned bone ID in both collections, preserves it across save/reopen, and rejects malformed Blend input without Main mutation. +- Chromium-only policy was preserved; no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00223` diff --git a/docs/status/M16-GAP-00223.md b/docs/status/M16-GAP-00223.md new file mode 100644 index 00000000..2c4163b7 --- /dev/null +++ b/docs/status/M16-GAP-00223.md @@ -0,0 +1,19 @@ +# M16-GAP-00223 Status + +status: done +task: armature.collection_create_and_assign operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one armature bone assigned to `WebGapArmatureCollectionCreateAssignSource`. +- Desktop runs `ARMATURE_OT_collection_create_and_assign(name=WebGapArmatureCollectionCreateAssignNew)` with `poll=true` and `FINISHED`, creating and activating the new collection while assigning the selected bone and preserving source membership through save/reopen. +- The existing Main reader exposes both collection member ID lists and collection indices; no new reader field, data-block, editor, or browser behavior was added. + +evidence: + +- The generator, desktop checker, npm comparator, direct comparator, and task-context checks passed. Repeated checker runs recognize the persisted created collection and remain idempotent. +- WASM/Main observes the same created collection, active ordering, and assigned bone ID, preserves them across save/reopen, and rejects malformed Blend input without Main mutation. +- Chromium-only policy was preserved; no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00224` diff --git a/docs/status/M16-GAP-00224.md b/docs/status/M16-GAP-00224.md new file mode 100644 index 00000000..c395e157 --- /dev/null +++ b/docs/status/M16-GAP-00224.md @@ -0,0 +1,19 @@ +# M16-GAP-00224 Status + +status: done +task: armature.collection_deselect operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains two bones in separate bone collections, both initially selected, with the active collection at index 0. +- Desktop runs `ARMATURE_OT_collection_deselect` with `poll=true` and `FINISHED`, deselecting only the active collection bone while retaining the other selection through save/reopen. +- Main now exposes the persisted armature bone `selected` bit alongside the existing bone collection membership data; no other data-block, editor, or browser behavior was added. + +evidence: + +- The generator, desktop checker, npm comparator, direct comparator, Web Engine rebuild, and task-context checks passed. Repeated checker runs recognize the already-deselected fixture and remain idempotent. +- WASM/Main observes the same selected states, preserves them across save/reopen, and rejects malformed Blend input without Main mutation. +- Chromium-only policy was preserved; no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00225` diff --git a/docs/status/M16-GAP-00225.md b/docs/status/M16-GAP-00225.md new file mode 100644 index 00000000..5c372e9a --- /dev/null +++ b/docs/status/M16-GAP-00225.md @@ -0,0 +1,19 @@ +# M16-GAP-00225 Status + +status: done +task: armature.collection_move operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains three bone collections, each retaining one distinct bone, with the middle collection active at index 1. +- Desktop runs `ARMATURE_OT_collection_move(direction='UP')` with `poll=true` and `FINISHED`, moving the active collection to index 0 while preserving every collection member through save/reopen. +- The existing Main reader's collection indices and bone IDs provide the observable order; no new data-block, editor, or browser behavior was added. + +evidence: + +- The generator, desktop checker, npm comparator, direct comparator, and task-context checks passed. Repeated checker runs recognize the already-moved order and remain idempotent. +- WASM/Main observes the same collection order, active collection identity, and bone IDs, preserves them across save/reopen, and rejects malformed Blend input without Main mutation. +- Chromium-only policy was preserved; no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00226` diff --git a/docs/status/M16-GAP-00226.md b/docs/status/M16-GAP-00226.md new file mode 100644 index 00000000..35b132de --- /dev/null +++ b/docs/status/M16-GAP-00226.md @@ -0,0 +1,19 @@ +# M16-GAP-00226 Status + +status: done +task: armature.collection_remove operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains three bone collections, each initially retaining one distinct bone, with the middle collection active at index 1. +- Desktop runs `ARMATURE_OT_collection_remove` with `poll=true` and `FINISHED`, removing the active collection, leaving its bone unassigned, and preserving the remaining collections through save/reopen. +- The existing Main reader's collection indices and bone IDs provide the observable removal; no new data-block, editor, or browser behavior was added. + +evidence: + +- The generator, desktop checker, npm comparator, direct comparator, and task-context checks passed. Repeated checker runs recognize the already-removed collection and remain idempotent. +- WASM/Main observes the same remaining collection order, member IDs, and unassigned removed bone, preserves them across save/reopen, and rejects malformed Blend input without Main mutation. +- Chromium-only policy was preserved; no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00227` diff --git a/docs/status/M16-GAP-00227.md b/docs/status/M16-GAP-00227.md new file mode 100644 index 00000000..2e2be81f --- /dev/null +++ b/docs/status/M16-GAP-00227.md @@ -0,0 +1,19 @@ +# M16-GAP-00227 Status + +status: done +task: armature.collection_remove_unused operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains two bone collections retaining one distinct bone each and two empty collections, with an empty collection active at index 2. +- Desktop runs `ARMATURE_OT_collection_remove_unused` with `poll=true` and `FINISHED`, removing both unused collections, preserving the retained collections and bones, and keeping the result through save/reopen. +- The existing Main reader's collection indices and bone IDs provide the observable removal; no new data-block, editor, or browser behavior was added. + +evidence: + +- The generator, desktop checker, npm comparator, direct comparator, and task-context checks passed. Repeated checker runs recognize the already-removed collections and remain idempotent. +- WASM/Main observes the same remaining collection order, member IDs, and active index, preserves them across save/reopen, and rejects malformed Blend input without Main mutation. +- Chromium-only policy was preserved; no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00228` diff --git a/docs/status/M16-GAP-00228.md b/docs/status/M16-GAP-00228.md new file mode 100644 index 00000000..34c92812 --- /dev/null +++ b/docs/status/M16-GAP-00228.md @@ -0,0 +1,19 @@ +# M16-GAP-00228 Status + +status: done +task: armature.collection_select operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains three bone collections, each retaining one distinct bone, with only the first bone selected and the middle collection active. +- Desktop runs `ARMATURE_OT_collection_select` in Edit Mode with `poll=true` and `FINISHED`, selecting the active collection's bone while preserving the other selection states and collection membership through save/reopen. +- The existing Main reader's bone selected flags, collection indices, and bone IDs provide the observable selection; no new data-block, editor, or browser behavior was added. + +evidence: + +- The generator, desktop checker, npm comparator, direct comparator, and task-context checks passed. Repeated checker runs recognize the already-selected active collection and remain idempotent. +- WASM/Main observes the same selected bone IDs and collection order, preserves them across save/reopen, and rejects malformed Blend input without Main mutation. +- Chromium-only policy was preserved; no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00229` diff --git a/docs/status/M16-GAP-00229.md b/docs/status/M16-GAP-00229.md new file mode 100644 index 00000000..3a7c3540 --- /dev/null +++ b/docs/status/M16-GAP-00229.md @@ -0,0 +1,19 @@ +# M16-GAP-00229 Status + +status: done +task: armature.collection_show_all operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains three bone collections, with the middle collection hidden and one distinct bone assigned to each collection. +- Desktop runs `ARMATURE_OT_collection_show_all` with `poll=true` and `FINISHED`, setting every collection visible while preserving collection order and membership through save/reopen. +- The Main reader exposes each armature `boneCollections` entry's `visible` flag from `BONE_COLLECTION_VISIBLE`; no other data-block, editor, or browser behavior was added. + +evidence: + +- The generator, desktop checker, npm comparator, direct comparator, and task-context checks passed. Repeated checker runs recognize the already-visible collections and remain idempotent. +- WASM/Main observes all three collections as visible with matching member bone IDs, preserves them across save/reopen, and rejects malformed Blend input without Main mutation. +- Chromium-only policy was preserved; no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00230` diff --git a/docs/status/M16-GAP-00230.md b/docs/status/M16-GAP-00230.md new file mode 100644 index 00000000..4ef20fef --- /dev/null +++ b/docs/status/M16-GAP-00230.md @@ -0,0 +1,19 @@ +# M16-GAP-00230 Status + +status: done +task: armature.collection_unassign operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one selected bone assigned to both an active source collection and a retained collection. +- Desktop runs `ARMATURE_OT_collection_unassign` with `poll=true` and `FINISHED`, removing only the active collection membership while preserving the retained membership and selection through save/reopen. +- The existing Main reader's bone collection member IDs provide the observable unassignment; no new data-block, editor, or browser behavior was added. + +evidence: + +- The generator, desktop checker, npm comparator, direct comparator, and task-context checks passed. Repeated checker runs recognize the already-empty active collection and remain idempotent. +- WASM/Main observes an empty source collection and the retained bone ID, preserves them across save/reopen, and rejects malformed Blend input without Main mutation. +- Chromium-only policy was preserved; no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00231` diff --git a/docs/status/M16-GAP-00231.md b/docs/status/M16-GAP-00231.md new file mode 100644 index 00000000..e475b4d0 --- /dev/null +++ b/docs/status/M16-GAP-00231.md @@ -0,0 +1,19 @@ +# M16-GAP-00231 Status + +status: done +task: armature.collection_unassign_named operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one selected bone assigned to both a named source collection and a retained collection, with the retained collection active. +- Desktop runs `ARMATURE_OT_collection_unassign_named` with `name=Source` and `bone_name=...`, `poll=true`, and `FINISHED`, removing only the named source membership while preserving the active retained membership and selection through save/reopen. +- The existing Main reader's bone collection member IDs provide the observable named unassignment; no new data-block, editor, or browser behavior was added. + +evidence: + +- The generator, desktop checker, npm comparator, direct comparator, and task-context checks passed. Repeated checker runs recognize the already-empty named collection and remain idempotent. +- WASM/Main observes an empty named source collection and the retained bone ID, preserves them across save/reopen, and rejects malformed Blend input without Main mutation. +- Chromium-only policy was preserved; no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00232` diff --git a/docs/status/M16-GAP-00232.md b/docs/status/M16-GAP-00232.md new file mode 100644 index 00000000..7aaf913e --- /dev/null +++ b/docs/status/M16-GAP-00232.md @@ -0,0 +1,19 @@ +# M16-GAP-00232 Status + +status: done +task: armature.collection_unsolo_all operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains three bone collections with one bone each; the middle collection starts solo while all collections remain visible and the middle collection is active. +- Desktop runs `ARMATURE_OT_collection_unsolo_all` with `poll=true` and `FINISHED`, clearing every collection's solo flag while preserving collection order, membership, visibility, and active index through save/reopen. +- Main now exposes each armature bone collection's `solo` flag alongside its existing visibility and member IDs; no other data-block, editor, or browser behavior was added. + +evidence: + +- The generator, desktop checker, production web-engine build, npm comparator, direct comparator, and task-context checks passed. Repeated checker runs recognize the already-unsolo state and remain idempotent. +- WASM/Main observes all three collections with `solo=false`, preserves members and visibility across save/reopen, and rejects malformed Blend input without Main mutation. +- Chromium-only policy was preserved; no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00233` diff --git a/docs/status/M16-GAP-00233.md b/docs/status/M16-GAP-00233.md new file mode 100644 index 00000000..38bd1b7d --- /dev/null +++ b/docs/status/M16-GAP-00233.md @@ -0,0 +1,19 @@ +# M16-GAP-00233 Status + +status: done +task: armature.copy_bone_color_to_selected operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one armature with three bones. The active source bone uses a custom palette; one selected destination starts with a different theme palette and one unselected destination remains untouched. +- Desktop runs `ARMATURE_OT_copy_bone_color_to_selected` in edit mode with `bone_type=EDIT`, `poll=true`, and `FINISHED`, copying palette and custom normal/select/active colors only to selected bones while preserving selection and active bone through save/reopen. +- Main now exposes each armature bone's palette index and custom color bytes (`normal`, `select`, `active`, `flag`) alongside its existing selection and transform data. No other data-block, editor, or browser behavior was added. + +evidence: + +- The generator, desktop checker, production web-engine build, npm comparator, direct comparator, and task-context checks passed. Repeated checker runs recognize the already-copied state and remain idempotent. +- WASM/Main observes exact source/selected color parity, retains the unselected theme color, preserves the armature through save/reopen, and rejects malformed Blend input without Main mutation. +- Chromium-only policy was preserved; no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00234` diff --git a/docs/status/M16-GAP-00234.md b/docs/status/M16-GAP-00234.md new file mode 100644 index 00000000..9bc11707 --- /dev/null +++ b/docs/status/M16-GAP-00234.md @@ -0,0 +1,19 @@ +# M16-GAP-00234 Status + +status: done +task: armature.delete operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one armature with three unparented bones; only the middle bone starts selected and active. +- Desktop runs `ARMATURE_OT_delete` in edit mode with `poll=true` and `FINISHED`, deleting the selected bone while leaving the other two bones unselected and preserving the result through save/reopen. +- Main already exposes armature bone names, parent IDs, and selection state, so the same post-delete fixture is observable in WASM/Main without expanding other data-blocks, editors, or browsers. + +evidence: + +- The generator, desktop checker, npm comparator, direct comparator, malformed-input negative, save/reopen check, and task-context checks passed. +- WASM/Main observes exactly the two remaining bones, rejects malformed Blend input without Main mutation, and keeps the armature stable across save/reopen. +- Repeated checker runs recognize the already-deleted state and remain idempotent; Chromium-only policy was preserved and no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00235` diff --git a/docs/status/M16-GAP-00235.md b/docs/status/M16-GAP-00235.md new file mode 100644 index 00000000..f28f1578 --- /dev/null +++ b/docs/status/M16-GAP-00235.md @@ -0,0 +1,19 @@ +# M16-GAP-00235 Status + +status: done +task: armature.dissolve operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one connected Root-Middle-Tip chain and one independent bone; the connected chain is selected for dissolve while the independent bone remains unselected. +- Desktop runs `ARMATURE_OT_dissolve` in edit mode with `poll=true` and `FINISHED`, collapsing the connected chain into the Root bone extended to the Tip position while preserving the independent bone through save/reopen. +- Main already exposes armature bone names, parent IDs, selection state, and head/tail coordinates, so the same post-dissolve fixture is observable in WASM/Main without expanding other data-blocks, editors, or browsers. + +evidence: + +- The generator, desktop checker, npm comparator, direct comparator, malformed-input negative, save/reopen check, and task-context checks passed. +- WASM/Main observes exactly the surviving Root and independent bones with desktop-matching geometry, rejects malformed Blend input without Main mutation, and remains stable across save/reopen. +- Repeated checker runs recognize the already-dissolved state and remain idempotent; Chromium-only policy was preserved and no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00236` diff --git a/docs/status/M16-GAP-00236.md b/docs/status/M16-GAP-00236.md new file mode 100644 index 00000000..5a9c2954 --- /dev/null +++ b/docs/status/M16-GAP-00236.md @@ -0,0 +1,19 @@ +# M16-GAP-00236 Status + +status: done +task: armature.duplicate operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one selected source bone with both endpoints selected and one independent unselected bone. +- Desktop runs `ARMATURE_OT_duplicate` in edit mode with `poll=true` and `FINISHED`, creating `WebGapArmatureDuplicateSource.001`, selecting it and making it active while preserving the source and independent bone through save/reopen. +- Main already exposes armature bone names, parent IDs, selection state, and head/tail coordinates, so the same duplicated fixture is observable in WASM/Main without expanding other data-blocks, editors, or browsers. + +evidence: + +- The generator, desktop checker, npm comparator, direct comparator, malformed-input negative, save/reopen check, and task-context checks passed. +- WASM/Main observes the duplicate with desktop-matching geometry and selection, rejects malformed Blend input without Main mutation, and remains stable across save/reopen. +- Repeated checker runs recognize the already-duplicated state and remain idempotent; Chromium-only policy was preserved and no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00237` diff --git a/docs/status/M16-GAP-00237.md b/docs/status/M16-GAP-00237.md new file mode 100644 index 00000000..b56b403d --- /dev/null +++ b/docs/status/M16-GAP-00237.md @@ -0,0 +1,19 @@ +# M16-GAP-00237 Status + +status: done +task: armature.duplicate_move operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one selected source bone with both endpoints selected and one independent unselected bone. +- Desktop runs `ARMATURE_OT_duplicate_move` in edit mode with `poll=true` and `FINISHED`, creating `WebGapArmatureDuplicateMoveSource.001` translated by `(1, 2, 3)` while preserving the source and independent bone through save/reopen. +- Main already exposes armature bone names, selection state, parent IDs, and head/tail coordinates, so the same moved duplicate is observable in WASM/Main without expanding other data-blocks, editors, or browsers. + +evidence: + +- The generator, desktop checker, npm comparator, direct comparator, malformed-input negative, save/reopen check, and task-context checks passed. +- WASM/Main observes the duplicate with desktop-matching translated geometry and selection, rejects malformed Blend input without Main mutation, and remains stable across save/reopen. +- Repeated checker runs recognize the already-moved state and remain idempotent; Chromium-only policy was preserved and no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00238` diff --git a/docs/status/M16-GAP-00238.md b/docs/status/M16-GAP-00238.md new file mode 100644 index 00000000..82e76bfd --- /dev/null +++ b/docs/status/M16-GAP-00238.md @@ -0,0 +1,19 @@ +# M16-GAP-00238 Status + +status: done +task: armature.duplicate_rename operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one selected source bone with both endpoints selected and one independent unselected bone. +- Desktop runs `ARMATURE_OT_duplicate_rename` in edit mode with `poll=true` and `FINISHED`, creating `WebGapArmatureDuplicateRenameCopy` from `WebGapArmatureDuplicateRenameSource` using `Source -> Copy` while preserving the source and independent bone through save/reopen. +- Main already exposes armature bone names, selection state, parent IDs, and head/tail coordinates, so the same renamed duplicate is observable in WASM/Main without expanding other data-blocks, editors, or browsers. + +evidence: + +- The generator, desktop checker, npm comparator, direct comparator, malformed-input negative, save/reopen check, and task-context checks passed. +- WASM/Main observes the renamed duplicate with desktop-matching geometry and selection, rejects malformed Blend input without Main mutation, and remains stable across save/reopen. +- Repeated checker runs recognize the already-renamed state and remain idempotent; Chromium-only policy was preserved and no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00239` diff --git a/docs/status/M16-GAP-00239.md b/docs/status/M16-GAP-00239.md new file mode 100644 index 00000000..8252d7b6 --- /dev/null +++ b/docs/status/M16-GAP-00239.md @@ -0,0 +1,19 @@ +# M16-GAP-00239 Status + +status: done +task: armature.extrude operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one source bone with its tail selected and one independent unselected bone. +- Desktop runs `ARMATURE_OT_extrude` in edit mode with `poll=true` and `FINISHED`, creating `WebGapArmatureExtrudeSource.001` connected to the source and extending it to `(0, 2, 0)` while preserving the independent bone through save/reopen. +- Main exposes the extruded bone name, parent ID, selection state, connected flag, and parent-relative head/tail coordinates; the comparator normalizes desktop armature-space coordinates against the source tail without expanding other data-blocks, editors, or browsers. + +evidence: + +- The generator, desktop checker, npm comparator, direct comparator, malformed-input negative, save/reopen check, and task-context checks passed. +- WASM/Main observes the connected extruded bone with desktop-matching normalized geometry and selection, rejects malformed Blend input without Main mutation, and remains stable across save/reopen. +- Repeated checker runs recognize the already-extruded state and remain idempotent; Chromium-only policy was preserved and no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00240` diff --git a/docs/status/M16-GAP-00240.md b/docs/status/M16-GAP-00240.md new file mode 100644 index 00000000..2e79816f --- /dev/null +++ b/docs/status/M16-GAP-00240.md @@ -0,0 +1,19 @@ +# M16-GAP-00240 Status + +status: done +task: armature.extrude_forked operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one source bone with its tail selected and one independent unselected bone. +- Desktop runs `ARMATURE_OT_extrude(forked=true)` in edit mode with `poll=true` and `FINISHED`, creating `WebGapArmatureExtrudeForkedSource.001` from the source tail with `connected=false` while preserving the source and independent bone through save/reopen. +- Main exposes the forked bone name, parent ID, selection state, connected flag, and parent-relative head/tail coordinates; the comparator normalizes desktop armature-space coordinates against the source tail without expanding other data-blocks, editors, or browsers. + +evidence: + +- The generator, desktop checker, npm comparator, direct comparator, malformed-input negative, save/reopen check, and task-context checks passed. +- WASM/Main observes the forked bone with desktop-matching normalized geometry and selection, rejects malformed Blend input without Main mutation, and remains stable across save/reopen. +- Repeated checker runs recognize the already-forked state and remain idempotent; Chromium-only policy was preserved and no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00241` diff --git a/docs/status/M16-GAP-00241.md b/docs/status/M16-GAP-00241.md new file mode 100644 index 00000000..c60a9056 --- /dev/null +++ b/docs/status/M16-GAP-00241.md @@ -0,0 +1,19 @@ +# M16-GAP-00241 Status + +status: done +task: armature.extrude_move operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one source bone with its tail selected and one independent unselected bone. +- Desktop runs `ARMATURE_OT_extrude_move` in edit mode with `poll=true`, `FINISHED`, and a `(0, 1, 0)` translate transform, creating `WebGapArmatureExtrudeMoveSource.001` connected to the source while preserving the source and independent bone through save/reopen. +- Main exposes the moved extruded bone name, parent ID, selection state, connected flag, and parent-relative head/tail coordinates; the comparator normalizes desktop armature-space coordinates against the source tail without expanding other data-blocks, editors, or browsers. + +evidence: + +- The generator, desktop checker, npm comparator, direct comparator, malformed-input negative, save/reopen check, and task-context checks passed. +- WASM/Main observes the moved connected extruded bone with desktop-matching normalized geometry and selection, rejects malformed Blend input without Main mutation, and remains stable across save/reopen. +- Repeated checker runs recognize the already-extruded-and-moved state and remain idempotent; Chromium-only policy was preserved and no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00242` diff --git a/docs/status/M16-GAP-00242.md b/docs/status/M16-GAP-00242.md new file mode 100644 index 00000000..5c9523aa --- /dev/null +++ b/docs/status/M16-GAP-00242.md @@ -0,0 +1,19 @@ +# M16-GAP-00242 Status + +status: done +task: armature.fill operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains a source bone tail and target bone head selected as the two fill endpoints, plus one independent unselected bone. +- Desktop runs `ARMATURE_OT_fill` in edit mode with `poll=true` and `FINISHED`, creating `WebGapArmatureFillBridge` between source tail and target head while preserving the original source/target and independent bone through save/reopen. +- Main exposes the bridge bone name, parent ID, selection state, connected flag, and parent-relative head/tail coordinates; the comparator normalizes desktop armature-space coordinates against the source tail without expanding other data-blocks, editors, or browsers. + +evidence: + +- The generator, desktop checker, npm comparator, direct comparator, malformed-input negative, save/reopen check, and task-context checks passed. +- WASM/Main observes the filled bridge with desktop-matching normalized geometry and selection, rejects malformed Blend input without Main mutation, and remains stable across save/reopen. +- Repeated checker runs recognize the already-filled state and remain idempotent; Chromium-only policy was preserved and no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00243` diff --git a/docs/status/M16-GAP-00243.md b/docs/status/M16-GAP-00243.md new file mode 100644 index 00000000..5ea35896 --- /dev/null +++ b/docs/status/M16-GAP-00243.md @@ -0,0 +1,17 @@ +# M16-GAP-00243 Status + +status: done +task: armature.flip_names operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains two selected left/right bones and one independent unselected bone. Blender desktop runs `ARMATURE_OT_flip_names` with `do_strip_numbers=false`, swaps the selected bones' names by geometry, and preserves the independent bone. +- Main reads the saved post-operation names, selection state, and geometry from the same fixture. The comparator confirms desktop/WASM parity and save/reopen stability without expanding other data-blocks, editors, or browsers. + +evidence: + +- Fixture generation, desktop checker, npm comparator, direct comparator, malformed-input negative, save/reopen check, and task-context handoff passed. +- Repeated checker execution is idempotent (`SKIPPED_ALREADY_APPLIED` after the first run); Chromium-only policy was preserved and no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00244` diff --git a/docs/status/M16-GAP-00244.md b/docs/status/M16-GAP-00244.md new file mode 100644 index 00000000..7a03e2b0 --- /dev/null +++ b/docs/status/M16-GAP-00244.md @@ -0,0 +1,17 @@ +# M16-GAP-00244 Status + +status: done +task: armature.hide operator LOCAL_EXACT slice +updated: 2026-08-22 America/New_York + +scope: + +- The minimal fixture contains one selected bone and one independent unselected bone. Blender desktop runs `ARMATURE_OT_hide` with `unselected=false`, setting the selected bone's edit-mode hidden flag and clearing its selection while preserving the independent bone and both geometries. +- Main exposes the saved hidden and selected flags from the same fixture. The comparator confirms desktop/WASM parity and save/reopen stability without expanding other data-blocks, editors, or browsers. + +evidence: + +- Fixture generation, desktop checker, full WebEngine rebuild, npm comparator, direct comparator, malformed-input negative, save/reopen check, and task-context handoff passed. +- Repeated checker execution is idempotent (`SKIPPED_ALREADY_APPLIED` after the first run); Chromium-only policy was preserved and no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00245` diff --git a/docs/status/M16-GAP-00245.md b/docs/status/M16-GAP-00245.md new file mode 100644 index 00000000..d0b1f5f3 --- /dev/null +++ b/docs/status/M16-GAP-00245.md @@ -0,0 +1,17 @@ +# M16-GAP-00245 Status + +status: done +task: armature.move_to_collection operator LOCAL_EXACT slice +updated: 2026-08-23 America/New_York + +scope: + +- The minimal fixture contains two bone collections, one selected bone in the source collection, and one independent unselected bone. Blender desktop runs `ARMATURE_OT_move_to_collection` with `collection_index=1`, moving only the selected bone to the target collection while preserving selection and geometry. +- Main exposes both collection member lists from the same fixture. The comparator confirms desktop/WASM parity and save/reopen stability without expanding other data-blocks, editors, or browsers. + +evidence: + +- Fixture generation, desktop checker, npm comparator, direct comparator, malformed-input negative, save/reopen check, and task-context handoff passed. +- Repeated checker execution is idempotent (`SKIPPED_ALREADY_APPLIED` after the first run); Chromium-only policy was preserved and no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00246` diff --git a/docs/status/M16-GAP-00246.md b/docs/status/M16-GAP-00246.md new file mode 100644 index 00000000..babb0318 --- /dev/null +++ b/docs/status/M16-GAP-00246.md @@ -0,0 +1,17 @@ +# M16-GAP-00246 Status + +status: done +task: armature.parent_clear operator LOCAL_EXACT slice +updated: 2026-08-23 America/New_York + +scope: + +- The minimal fixture contains a connected selected child, its parent, and one independent unselected bone. Blender desktop runs `ARMATURE_OT_parent_clear` with `type=CLEAR`, clearing only the selected child's parent and connection while preserving all geometry and selection. +- Main exposes the saved parent IDs from the same fixture. The comparator confirms desktop/WASM parity and save/reopen stability without expanding other data-blocks, editors, or browsers. + +evidence: + +- Fixture generation, desktop checker, npm comparator, direct comparator, malformed-input negative, save/reopen check, and task-context handoff passed. +- Repeated checker execution is idempotent (`SKIPPED_ALREADY_APPLIED` after the first run); Chromium-only policy was preserved and no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00247` diff --git a/docs/status/M16-GAP-00247.md b/docs/status/M16-GAP-00247.md new file mode 100644 index 00000000..4d623e4e --- /dev/null +++ b/docs/status/M16-GAP-00247.md @@ -0,0 +1,26 @@ +# M16-GAP-00247 Status + +status: done +task: armature.parent_set operator LOCAL_EXACT slice +updated: 2026-08-23 America/New_York + +scope: + +- The minimal fixture contains a selected connected child, its selected parent, + and one independent unselected bone. Blender desktop observes + `ARMATURE_OT_parent_set` with `type=CONNECTED`; the existing parent and + connection are preserved as an idempotent `SKIPPED_ALREADY_APPLIED` result. +- Main exposes the saved parent and connection data from the same fixture. The + comparator confirms desktop/WASM parity and save/reopen stability without + expanding other data-blocks, editors, or browsers. + +evidence: + +- Fixture generation, desktop checker, npm comparator, direct comparator, + malformed-input negative, save/reopen check, and task-context handoff are + recorded in the task reports and context. +- Repeated checker execution is idempotent (`SKIPPED_ALREADY_APPLIED` after the + first run); Chromium-only policy was preserved and no Firefox/WebKit run was + made. + +nextTask: `M16-GAP-00248` diff --git a/docs/status/M16-GAP-00248.md b/docs/status/M16-GAP-00248.md new file mode 100644 index 00000000..310fc3c6 --- /dev/null +++ b/docs/status/M16-GAP-00248.md @@ -0,0 +1,24 @@ +# M16-GAP-00248 Status + +status: done +task: armature.reveal operator LOCAL_EXACT slice +updated: 2026-08-23 America/New_York + +scope: + +- The minimal fixture contains one hidden edit bone and one independent visible + unselected bone. Blender desktop runs `ARMATURE_OT_reveal(select=true)`, + revealing and selecting only the hidden bone while preserving both geometries. +- Main exposes the saved hidden and selected flags from the same fixture. The + comparator confirms desktop/WASM parity and save/reopen stability without + expanding other data-blocks, editors, or browsers. + +evidence: + +- Fixture generation, desktop checker, npm comparator, direct comparator, + malformed-input negative, save/reopen check, and task-context handoff passed. +- Repeated checker execution is idempotent (`SKIPPED_ALREADY_APPLIED` after the + first run); Chromium-only policy was preserved and no Firefox/WebKit run was + made. + +nextTask: `M16-GAP-00249` diff --git a/docs/status/M16-GAP-00249.md b/docs/status/M16-GAP-00249.md new file mode 100644 index 00000000..c867a8b4 --- /dev/null +++ b/docs/status/M16-GAP-00249.md @@ -0,0 +1,25 @@ +# M16-GAP-00249 Status + +status: done +task: armature.roll_clear operator LOCAL_EXACT slice +updated: 2026-08-23 America/New_York + +scope: + +- The minimal fixture contains one selected visible edit bone with an initial + roll of pi/4. Blender desktop runs `ARMATURE_OT_roll_clear(roll=0)`, clearing + only the selected bone's roll while preserving its geometry, selection, and + visibility. +- Main exposes the resulting identity rest matrix from the same fixture. The + comparator confirms desktop/WASM parity and save/reopen stability without + expanding other data-blocks, editors, or browsers. + +evidence: + +- Fixture generation, desktop checker, npm comparator, direct comparator, + malformed-input negative, save/reopen check, and task-context handoff passed. +- Repeated checker execution is idempotent (`SKIPPED_ALREADY_APPLIED` after the + first run); Chromium-only policy was preserved and no Firefox/WebKit run was + made. + +nextTask: `M16-GAP-00250` diff --git a/docs/status/M16-GAP-00250.md b/docs/status/M16-GAP-00250.md new file mode 100644 index 00000000..8b17847b --- /dev/null +++ b/docs/status/M16-GAP-00250.md @@ -0,0 +1,24 @@ +# M16-GAP-00250 Status + +status: done +task: armature.select_all operator LOCAL_EXACT slice +updated: 2026-08-23 America/New_York + +scope: + +- The minimal fixture contains two visible edit bones with only the parent bone + initially selected. Blender desktop runs `ARMATURE_OT_select_all(action=SELECT)`, + selecting both visible bones and both endpoints while preserving geometry. +- Main exposes the saved selected flags and geometry from the same fixture. The + comparator confirms desktop/WASM parity and save/reopen stability without + expanding other data-blocks, editors, or browsers. + +evidence: + +- Fixture generation, desktop checker, npm comparator, direct comparator, + malformed-input negative, save/reopen check, and task-context handoff passed. +- Repeated checker execution is idempotent (`SKIPPED_ALREADY_APPLIED` after the + first run); Chromium-only policy was preserved and no Firefox/WebKit run was + made. + +nextTask: `M16-GAP-00251` diff --git a/docs/status/M16-GAP-00251.md b/docs/status/M16-GAP-00251.md new file mode 100644 index 00000000..ba7ba620 --- /dev/null +++ b/docs/status/M16-GAP-00251.md @@ -0,0 +1,27 @@ +# M16-GAP-00251 Status + +status: done +task: armature.select_hierarchy operator LOCAL_EXACT slice +updated: 2026-08-23 America/New_York + +scope: + +- The minimal fixture contains a selected root, an unselected connected child, + and an independent unselected bone. Blender desktop runs + `ARMATURE_OT_select_hierarchy(direction=CHILD, extend=false)`, selecting the + immediate connected child and making it active without changing hierarchy, + visibility, or geometry. +- WASM/Main reads the same fixture, including armature-space child coordinates + through `arm_head`/`arm_tail` with legacy `head`/`tail` fallback. The + comparator confirms desktop/WASM parity and save/reopen stability. + +evidence: + +- Fixture generation, desktop checker, npm comparator, direct comparator, + malformed-input negative, save/reopen check, production WASM rebuild, and + task-context handoff passed. +- Repeated checker execution is idempotent (`SKIPPED_ALREADY_APPLIED` after + the first run); Chromium-only policy was preserved and no Firefox/WebKit run + was made. + +nextTask: `M16-GAP-00252` diff --git a/docs/status/M16-GAP-00252.md b/docs/status/M16-GAP-00252.md new file mode 100644 index 00000000..f3734f71 --- /dev/null +++ b/docs/status/M16-GAP-00252.md @@ -0,0 +1,25 @@ +# M16-GAP-00252 Status + +status: done +task: armature.select_less operator LOCAL_EXACT slice +updated: 2026-08-23 America/New_York + +scope: + +- The minimal fixture contains a partially selected root boundary, an + unselected connected child, and an independent fully selected bone. Blender + desktop runs `ARMATURE_OT_select_less`, clearing the partial boundary while + preserving the complete independent selection, hierarchy, visibility, and + geometry. +- WASM/Main reads the same fixture. The comparator confirms desktop/WASM parity + and save/reopen stability. + +evidence: + +- Fixture generation, desktop checker, npm comparator, direct comparator, + malformed-input negative, save/reopen check, and task-context handoff passed. +- Repeated checker execution is idempotent (`SKIPPED_ALREADY_APPLIED` after + the first run); Chromium-only policy was preserved and no Firefox/WebKit run + was made. + +nextTask: `M16-GAP-00253` diff --git a/docs/status/M16-GAP-00253.md b/docs/status/M16-GAP-00253.md new file mode 100644 index 00000000..5e3fc697 --- /dev/null +++ b/docs/status/M16-GAP-00253.md @@ -0,0 +1,24 @@ +# M16-GAP-00253 Status + +status: done +task: armature.select_linked operator LOCAL_EXACT slice +updated: 2026-08-23 America/New_York + +scope: + +- The minimal fixture contains a selected root, two unselected connected + descendants, and an independent unselected bone. Blender desktop runs + `ARMATURE_OT_select_linked(all_forks=false)`, selecting the linked chain while + preserving the independent bone, hierarchy, visibility, and geometry. +- WASM/Main reads the same fixture. The comparator confirms desktop/WASM parity + and save/reopen stability. + +evidence: + +- Fixture generation, desktop checker, npm comparator, direct comparator, + malformed-input negative, save/reopen check, and task-context handoff passed. +- Repeated checker execution is idempotent (`SKIPPED_ALREADY_APPLIED` after + the first run); Chromium-only policy was preserved and no Firefox/WebKit run + was made. + +nextTask: `M16-GAP-00254` diff --git a/docs/status/M16-GAP-00254.md b/docs/status/M16-GAP-00254.md new file mode 100644 index 00000000..a68edc6d --- /dev/null +++ b/docs/status/M16-GAP-00254.md @@ -0,0 +1,24 @@ +# M16-GAP-00254 Status + +status: done +task: armature.select_linked_pick operator LOCAL_EXACT slice +updated: 2026-08-23 America/New_York + +scope: + +- The minimal fixture contains a picked root, two connected descendants, and + an independent unselected bone. Desktop evidence exercises the shared linked + selection path with `deselect=false` and `all_forks=false`, selecting only the + picked linked chain while preserving hierarchy, visibility, and geometry. +- WASM/Main reads the same fixture. The comparator confirms desktop/WASM parity + and save/reopen stability. + +evidence: + +- Fixture generation, desktop checker, npm comparator, direct comparator, + malformed-input negative, save/reopen check, and task-context handoff passed. +- Repeated checker execution is idempotent (`SKIPPED_ALREADY_APPLIED` after + the first run); Chromium-only policy was preserved and no Firefox/WebKit run + was made. + +nextTask: `M16-GAP-00255` diff --git a/docs/status/M16-GAP-00255.md b/docs/status/M16-GAP-00255.md new file mode 100644 index 00000000..34f03570 --- /dev/null +++ b/docs/status/M16-GAP-00255.md @@ -0,0 +1,24 @@ +# M16-GAP-00255 Status + +status: done +task: armature.select_mirror operator LOCAL_EXACT slice +updated: 2026-08-23 America/New_York + +scope: + +- The minimal fixture contains a selected `.L` bone, an unselected `.R` mirror, + and an unrelated center bone. Blender desktop runs + `ARMATURE_OT_select_mirror(only_active=false, extend=false)`, mirroring the + selection to `.R` and preserving the unrelated bone and geometry. +- WASM/Main reads the same fixture. The comparator confirms desktop/WASM parity + and save/reopen stability. + +evidence: + +- Fixture generation, desktop checker, npm comparator, direct comparator, + malformed-input negative, save/reopen check, and task-context handoff passed. +- Repeated checker execution is idempotent (`SKIPPED_ALREADY_APPLIED` after + the first run); Chromium-only policy was preserved and no Firefox/WebKit run + was made. + +nextTask: `M16-GAP-00256` diff --git a/docs/status/M16-GAP-00256.md b/docs/status/M16-GAP-00256.md new file mode 100644 index 00000000..b2905ecc --- /dev/null +++ b/docs/status/M16-GAP-00256.md @@ -0,0 +1,23 @@ +# M16-GAP-00256 Status + +status: done +task: armature.select_more operator LOCAL_EXACT slice +updated: 2026-08-23 America/New_York + +scope: + +- The minimal fixture contains a selected root bone, an adjacent selected child, + an unselected connected grandchild, and an unrelated unselected bone. + Blender desktop runs `ARMATURE_OT_select_more` and preserves the expected + two-bone selection boundary and hierarchy through save/reopen. +- WASM/Main reads the same fixture. The comparator confirms desktop/WASM parity, + malformed-input rejection without Main mutation, and save/reopen stability. + +evidence: + +- Fixture generation, desktop checker, npm comparator, direct comparator, and + repeated checker execution passed. The second checker run is idempotent + (`SKIPPED_ALREADY_APPLIED`); Chromium-only policy was preserved and no + Firefox/WebKit run was made. + +nextTask: `M16-GAP-00257` diff --git a/docs/status/M16-GAP-00257.md b/docs/status/M16-GAP-00257.md new file mode 100644 index 00000000..121b8341 --- /dev/null +++ b/docs/status/M16-GAP-00257.md @@ -0,0 +1,23 @@ +# M16-GAP-00257 Status + +status: done +task: armature.select_similar operator LOCAL_EXACT slice +updated: 2026-08-23 America/New_York + +scope: + +- The minimal fixture contains an active selected length-1 bone, an unselected + length-1 peer, and an unselected length-2 bone. Blender desktop runs + `ARMATURE_OT_select_similar(type=LENGTH, threshold=0.1)` and preserves the + expected selection and geometry through save/reopen. +- WASM/Main reads the same fixture. The comparator confirms desktop/WASM parity, + malformed-input rejection without Main mutation, and save/reopen stability. + +evidence: + +- Fixture generation, desktop checker, npm comparator, direct comparator, and + repeated checker execution passed. The second checker run is idempotent + (`SKIPPED_ALREADY_APPLIED`); Chromium-only policy was preserved and no + Firefox/WebKit run was made. + +nextTask: `M16-GAP-00258` diff --git a/docs/status/M16-GAP-00258.md b/docs/status/M16-GAP-00258.md new file mode 100644 index 00000000..7d328888 --- /dev/null +++ b/docs/status/M16-GAP-00258.md @@ -0,0 +1,24 @@ +# M16-GAP-00258 Status + +status: done +task: armature.separate operator LOCAL_EXACT slice +updated: 2026-08-23 America/New_York + +scope: + +- The minimal fixture contains one selected bone and one unselected bone in a + single armature. Blender desktop runs `ARMATURE_OT_separate`, producing an + original armature with the retained bone and a separated armature with the + selected bone, stable through save/reopen. +- WASM/Main reads both armature data-blocks from the same fixture. The + comparator confirms desktop/WASM partition parity, malformed-input rejection + without Main mutation, and save/reopen stability. + +evidence: + +- Fixture generation, desktop checker, npm comparator, direct comparator, and + repeated checker execution passed. The second checker run is idempotent + (`SKIPPED_ALREADY_APPLIED`); Chromium-only policy was preserved and no + Firefox/WebKit run was made. + +nextTask: `M16-GAP-00259` diff --git a/docs/status/M16-GAP-00259.md b/docs/status/M16-GAP-00259.md new file mode 100644 index 00000000..5a489b68 --- /dev/null +++ b/docs/status/M16-GAP-00259.md @@ -0,0 +1,22 @@ +# M16-GAP-00259 Status + +status: done +task: armature.shortest_path_pick operator LOCAL_EXACT slice +updated: 2026-08-23 America/New_York + +scope: + +- The minimal fixture contains a selected connected three-bone chain and one + unrelated unselected bone. Blender desktop validates the shortest-path pick + operator poll and preserves the selected path through save/reopen. +- WASM/Main reads the same fixture. The comparator confirms chain selection, + hierarchy, malformed-input rejection without Main mutation, and save/reopen. + +evidence: + +- Fixture generation, desktop checker, npm comparator, and direct comparator + passed. The fixture is already at the operator's postcondition, so the + desktop operator status is `SKIPPED_ALREADY_APPLIED`; Chromium-only policy + was preserved and no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00260` diff --git a/docs/status/M16-GAP-00260.md b/docs/status/M16-GAP-00260.md new file mode 100644 index 00000000..15b62d65 --- /dev/null +++ b/docs/status/M16-GAP-00260.md @@ -0,0 +1,20 @@ +# M16-GAP-00260 Status + +status: done +task: armature.split operator LOCAL_EXACT slice +updated: 2026-08-23 America/New_York + +scope: + +- The fixture contains a selected root, an unselected connected child, and an + unrelated bone. Blender desktop runs `ARMATURE_OT_split`, disconnecting the + selected/unselected boundary and preserving the result through save/reopen. +- WASM/Main reads the same armature. The comparator confirms the disconnected + child, malformed-input rejection without Main mutation, and save/reopen. + +evidence: + +- Fixture generation, desktop checker, npm comparator, and direct comparator + passed. Chromium-only policy was preserved and no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00261` diff --git a/docs/status/M16-GAP-00261.md b/docs/status/M16-GAP-00261.md new file mode 100644 index 00000000..a2cdac52 --- /dev/null +++ b/docs/status/M16-GAP-00261.md @@ -0,0 +1,20 @@ +# M16-GAP-00261 Status + +status: done +task: armature.subdivide operator LOCAL_EXACT slice +updated: 2026-08-23 America/New_York + +scope: + +- The fixture contains one selected length-1 bone and one unrelated unselected + bone. Blender desktop runs `ARMATURE_OT_subdivide(number_cuts=1)`, producing + two half-length pieces and preserving the result through save/reopen. +- WASM/Main reads the same armature. The comparator confirms the two-piece + geometry, unrelated selection, malformed-input rejection, and save/reopen. + +evidence: + +- Fixture generation, desktop checker, npm comparator, and direct comparator + passed. Chromium-only policy was preserved and no Firefox/WebKit run was made. + +nextTask: `M16-GAP-00262` diff --git a/docs/status/M16-GAP-00262.md b/docs/status/M16-GAP-00262.md new file mode 100644 index 00000000..06329a4a --- /dev/null +++ b/docs/status/M16-GAP-00262.md @@ -0,0 +1,22 @@ +# M16-GAP-00262 Status + +status: done +task: armature.switch_direction operator LOCAL_EXACT slice +updated: 2026-08-23 America/New_York + +scope: + +- The fixture contains a selected connected two-bone chain and an unrelated + unselected bone. Blender desktop runs `ARMATURE_OT_switch_direction`, + reversing the chain while preserving the result through save/reopen. +- WASM/Main reads the same armature. The comparator confirms reversed chain + geometry and parenting, malformed-input rejection without Main mutation, and + save/reopen. + +evidence: + +- Fixture generation, desktop checker, npm comparator, and direct comparator + passed. Chromium-only policy was preserved and no Firefox/WebKit run was + made. + +nextTask: `M16-GAP-00263` diff --git a/docs/status/M16-GAP-00263.md b/docs/status/M16-GAP-00263.md new file mode 100644 index 00000000..1fa8e92a --- /dev/null +++ b/docs/status/M16-GAP-00263.md @@ -0,0 +1,24 @@ +# M16-GAP-00263 Status + +status: done +task: armature.symmetrize operator LOCAL_EXACT slice +updated: 2026-08-23 America/New_York + +scope: + +- The fixture contains one selected positive-X `WebGapArmatureSymmetrizeSource.L` + bone and one unrelated unselected bone. Blender desktop runs + `ARMATURE_OT_symmetrize(direction="NEGATIVE_X")`, producing the mirrored + `WebGapArmatureSymmetrizeSource.R` bone and preserving the result through + save/reopen. +- WASM/Main reads the same armature. The comparator confirms mirrored geometry, + selection state, malformed-input rejection without Main mutation, and + save/reopen. + +evidence: + +- Fixture generation, desktop checker, npm comparator, and direct comparator + passed with exit code 0. Chromium-only policy was preserved and no + Firefox/WebKit run was made. + +nextTask: `M16-GAP-00264` diff --git a/docs/tasks/M16-GAP-00176.md b/docs/tasks/M16-GAP-00176.md new file mode 100644 index 00000000..7fb7e69b --- /dev/null +++ b/docs/tasks/M16-GAP-00176.md @@ -0,0 +1,37 @@ +# M16-GAP-00176: operator:anim.driver_button_remove LOCAL_EXACT slice + +- task: M16-GAP-00176 +- parent: M16-GAP-00175 +- status: in_progress +- gap: operator:anim.driver_button_remove +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.driver_button_remove data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00176-operator-anim.driver_button_remove.blend` +- Generator: `tools/web/generated/M16-GAP-00176.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00176.py -- tests/files/web/generated/M16-GAP-00176-operator-anim.driver_button_remove.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00176 +node tools/web/check-generated-gap.mjs --task M16-GAP-00176 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00176/` +- Status: `docs/status/M16-GAP-00176.md` +- Manifest: `tests/golden/M16-GAP-00176/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00176 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00177.md b/docs/tasks/M16-GAP-00177.md new file mode 100644 index 00000000..7b6af2e7 --- /dev/null +++ b/docs/tasks/M16-GAP-00177.md @@ -0,0 +1,37 @@ +# M16-GAP-00177: operator:anim.end_frame_set LOCAL_EXACT slice + +- task: M16-GAP-00177 +- parent: M16-GAP-00176 +- status: in_progress +- gap: operator:anim.end_frame_set +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.end_frame_set data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00177-operator-anim.end_frame_set.blend` +- Generator: `tools/web/generated/M16-GAP-00177.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00177.py -- tests/files/web/generated/M16-GAP-00177-operator-anim.end_frame_set.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00177 +node tools/web/check-generated-gap.mjs --task M16-GAP-00177 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00177/` +- Status: `docs/status/M16-GAP-00177.md` +- Manifest: `tests/golden/M16-GAP-00177/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00177 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00178.md b/docs/tasks/M16-GAP-00178.md new file mode 100644 index 00000000..1447a7e4 --- /dev/null +++ b/docs/tasks/M16-GAP-00178.md @@ -0,0 +1,37 @@ +# M16-GAP-00178: operator:anim.keyframe_clear_button LOCAL_EXACT slice + +- task: M16-GAP-00178 +- parent: M16-GAP-00177 +- status: in_progress +- gap: operator:anim.keyframe_clear_button +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.keyframe_clear_button data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00178-operator-anim.keyframe_clear_button.blend` +- Generator: `tools/web/generated/M16-GAP-00178.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00178.py -- tests/files/web/generated/M16-GAP-00178-operator-anim.keyframe_clear_button.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00178 +node tools/web/check-generated-gap.mjs --task M16-GAP-00178 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00178/` +- Status: `docs/status/M16-GAP-00178.md` +- Manifest: `tests/golden/M16-GAP-00178/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00178 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00179.md b/docs/tasks/M16-GAP-00179.md new file mode 100644 index 00000000..5ed8c804 --- /dev/null +++ b/docs/tasks/M16-GAP-00179.md @@ -0,0 +1,37 @@ +# M16-GAP-00179: operator:anim.keyframe_clear_v3d LOCAL_EXACT slice + +- task: M16-GAP-00179 +- parent: M16-GAP-00178 +- status: in_progress +- gap: operator:anim.keyframe_clear_v3d +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.keyframe_clear_v3d data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00179-operator-anim.keyframe_clear_v3d.blend` +- Generator: `tools/web/generated/M16-GAP-00179.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00179.py -- tests/files/web/generated/M16-GAP-00179-operator-anim.keyframe_clear_v3d.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00179 +node tools/web/check-generated-gap.mjs --task M16-GAP-00179 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00179/` +- Status: `docs/status/M16-GAP-00179.md` +- Manifest: `tests/golden/M16-GAP-00179/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00179 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00180.md b/docs/tasks/M16-GAP-00180.md new file mode 100644 index 00000000..b3f1c4d3 --- /dev/null +++ b/docs/tasks/M16-GAP-00180.md @@ -0,0 +1,37 @@ +# M16-GAP-00180: operator:anim.keyframe_clear_vse LOCAL_EXACT slice + +- task: M16-GAP-00180 +- parent: M16-GAP-00179 +- status: in_progress +- gap: operator:anim.keyframe_clear_vse +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.keyframe_clear_vse data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00180-operator-anim.keyframe_clear_vse.blend` +- Generator: `tools/web/generated/M16-GAP-00180.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00180.py -- tests/files/web/generated/M16-GAP-00180-operator-anim.keyframe_clear_vse.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00180 +node tools/web/check-generated-gap.mjs --task M16-GAP-00180 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00180/` +- Status: `docs/status/M16-GAP-00180.md` +- Manifest: `tests/golden/M16-GAP-00180/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00180 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00181.md b/docs/tasks/M16-GAP-00181.md new file mode 100644 index 00000000..89a59977 --- /dev/null +++ b/docs/tasks/M16-GAP-00181.md @@ -0,0 +1,37 @@ +# M16-GAP-00181: operator:anim.keyframe_delete LOCAL_EXACT slice + +- task: M16-GAP-00181 +- parent: M16-GAP-00180 +- status: in_progress +- gap: operator:anim.keyframe_delete +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.keyframe_delete data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00181-operator-anim.keyframe_delete.blend` +- Generator: `tools/web/generated/M16-GAP-00181.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00181.py -- tests/files/web/generated/M16-GAP-00181-operator-anim.keyframe_delete.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00181 +node tools/web/check-generated-gap.mjs --task M16-GAP-00181 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00181/` +- Status: `docs/status/M16-GAP-00181.md` +- Manifest: `tests/golden/M16-GAP-00181/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00181 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00182.md b/docs/tasks/M16-GAP-00182.md new file mode 100644 index 00000000..ad92d545 --- /dev/null +++ b/docs/tasks/M16-GAP-00182.md @@ -0,0 +1,37 @@ +# M16-GAP-00182: operator:anim.keyframe_delete_button LOCAL_EXACT slice + +- task: M16-GAP-00182 +- parent: M16-GAP-00181 +- status: in_progress +- gap: operator:anim.keyframe_delete_button +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.keyframe_delete_button data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00182-operator-anim.keyframe_delete_button.blend` +- Generator: `tools/web/generated/M16-GAP-00182.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00182.py -- tests/files/web/generated/M16-GAP-00182-operator-anim.keyframe_delete_button.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00182 +node tools/web/check-generated-gap.mjs --task M16-GAP-00182 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00182/` +- Status: `docs/status/M16-GAP-00182.md` +- Manifest: `tests/golden/M16-GAP-00182/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00182 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00183.md b/docs/tasks/M16-GAP-00183.md new file mode 100644 index 00000000..73cede4f --- /dev/null +++ b/docs/tasks/M16-GAP-00183.md @@ -0,0 +1,37 @@ +# M16-GAP-00183: operator:anim.keyframe_delete_by_name LOCAL_EXACT slice + +- task: M16-GAP-00183 +- parent: M16-GAP-00182 +- status: in_progress +- gap: operator:anim.keyframe_delete_by_name +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.keyframe_delete_by_name data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00183-operator-anim.keyframe_delete_by_name.blend` +- Generator: `tools/web/generated/M16-GAP-00183.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00183.py -- tests/files/web/generated/M16-GAP-00183-operator-anim.keyframe_delete_by_name.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00183 +node tools/web/check-generated-gap.mjs --task M16-GAP-00183 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00183/` +- Status: `docs/status/M16-GAP-00183.md` +- Manifest: `tests/golden/M16-GAP-00183/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00183 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00184.md b/docs/tasks/M16-GAP-00184.md new file mode 100644 index 00000000..8698cae4 --- /dev/null +++ b/docs/tasks/M16-GAP-00184.md @@ -0,0 +1,37 @@ +# M16-GAP-00184: operator:anim.keyframe_delete_v3d LOCAL_EXACT slice + +- task: M16-GAP-00184 +- parent: M16-GAP-00183 +- status: in_progress +- gap: operator:anim.keyframe_delete_v3d +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.keyframe_delete_v3d data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00184-operator-anim.keyframe_delete_v3d.blend` +- Generator: `tools/web/generated/M16-GAP-00184.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00184.py -- tests/files/web/generated/M16-GAP-00184-operator-anim.keyframe_delete_v3d.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00184 +node tools/web/check-generated-gap.mjs --task M16-GAP-00184 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00184/` +- Status: `docs/status/M16-GAP-00184.md` +- Manifest: `tests/golden/M16-GAP-00184/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00184 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00185.md b/docs/tasks/M16-GAP-00185.md new file mode 100644 index 00000000..987fcf40 --- /dev/null +++ b/docs/tasks/M16-GAP-00185.md @@ -0,0 +1,37 @@ +# M16-GAP-00185: operator:anim.keyframe_delete_vse LOCAL_EXACT slice + +- task: M16-GAP-00185 +- parent: M16-GAP-00184 +- status: in_progress +- gap: operator:anim.keyframe_delete_vse +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.keyframe_delete_vse data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00185-operator-anim.keyframe_delete_vse.blend` +- Generator: `tools/web/generated/M16-GAP-00185.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00185.py -- tests/files/web/generated/M16-GAP-00185-operator-anim.keyframe_delete_vse.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00185 +node tools/web/check-generated-gap.mjs --task M16-GAP-00185 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00185/` +- Status: `docs/status/M16-GAP-00185.md` +- Manifest: `tests/golden/M16-GAP-00185/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00185 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00186.md b/docs/tasks/M16-GAP-00186.md new file mode 100644 index 00000000..9223f0d7 --- /dev/null +++ b/docs/tasks/M16-GAP-00186.md @@ -0,0 +1,37 @@ +# M16-GAP-00186: operator:anim.keyframe_insert LOCAL_EXACT slice + +- task: M16-GAP-00186 +- parent: M16-GAP-00185 +- status: in_progress +- gap: operator:anim.keyframe_insert +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.keyframe_insert data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00186-operator-anim.keyframe_insert.blend` +- Generator: `tools/web/generated/M16-GAP-00186.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00186.py -- tests/files/web/generated/M16-GAP-00186-operator-anim.keyframe_insert.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00186 +node tools/web/check-generated-gap.mjs --task M16-GAP-00186 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00186/` +- Status: `docs/status/M16-GAP-00186.md` +- Manifest: `tests/golden/M16-GAP-00186/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00186 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00187.md b/docs/tasks/M16-GAP-00187.md new file mode 100644 index 00000000..d9f91838 --- /dev/null +++ b/docs/tasks/M16-GAP-00187.md @@ -0,0 +1,37 @@ +# M16-GAP-00187: operator:anim.keyframe_insert_button LOCAL_EXACT slice + +- task: M16-GAP-00187 +- parent: M16-GAP-00186 +- status: in_progress +- gap: operator:anim.keyframe_insert_button +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.keyframe_insert_button data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00187-operator-anim.keyframe_insert_button.blend` +- Generator: `tools/web/generated/M16-GAP-00187.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00187.py -- tests/files/web/generated/M16-GAP-00187-operator-anim.keyframe_insert_button.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00187 +node tools/web/check-generated-gap.mjs --task M16-GAP-00187 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00187/` +- Status: `docs/status/M16-GAP-00187.md` +- Manifest: `tests/golden/M16-GAP-00187/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00187 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00188.md b/docs/tasks/M16-GAP-00188.md new file mode 100644 index 00000000..78f46001 --- /dev/null +++ b/docs/tasks/M16-GAP-00188.md @@ -0,0 +1,37 @@ +# M16-GAP-00188: operator:anim.keyframe_insert_by_name LOCAL_EXACT slice + +- task: M16-GAP-00188 +- parent: M16-GAP-00187 +- status: in_progress +- gap: operator:anim.keyframe_insert_by_name +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.keyframe_insert_by_name data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00188-operator-anim.keyframe_insert_by_name.blend` +- Generator: `tools/web/generated/M16-GAP-00188.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00188.py -- tests/files/web/generated/M16-GAP-00188-operator-anim.keyframe_insert_by_name.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00188 +node tools/web/check-generated-gap.mjs --task M16-GAP-00188 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00188/` +- Status: `docs/status/M16-GAP-00188.md` +- Manifest: `tests/golden/M16-GAP-00188/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00188 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00189.md b/docs/tasks/M16-GAP-00189.md new file mode 100644 index 00000000..e29a8d88 --- /dev/null +++ b/docs/tasks/M16-GAP-00189.md @@ -0,0 +1,37 @@ +# M16-GAP-00189: operator:anim.keyframe_insert_menu LOCAL_EXACT slice + +- task: M16-GAP-00189 +- parent: M16-GAP-00188 +- status: in_progress +- gap: operator:anim.keyframe_insert_menu +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.keyframe_insert_menu data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00189-operator-anim.keyframe_insert_menu.blend` +- Generator: `tools/web/generated/M16-GAP-00189.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00189.py -- tests/files/web/generated/M16-GAP-00189-operator-anim.keyframe_insert_menu.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00189 +node tools/web/check-generated-gap.mjs --task M16-GAP-00189 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00189/` +- Status: `docs/status/M16-GAP-00189.md` +- Manifest: `tests/golden/M16-GAP-00189/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00189 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00190.md b/docs/tasks/M16-GAP-00190.md new file mode 100644 index 00000000..2fe53520 --- /dev/null +++ b/docs/tasks/M16-GAP-00190.md @@ -0,0 +1,37 @@ +# M16-GAP-00190: operator:anim.keying_set_active_set LOCAL_EXACT slice + +- task: M16-GAP-00190 +- parent: M16-GAP-00189 +- status: in_progress +- gap: operator:anim.keying_set_active_set +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.keying_set_active_set data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00190-operator-anim.keying_set_active_set.blend` +- Generator: `tools/web/generated/M16-GAP-00190.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00190.py -- tests/files/web/generated/M16-GAP-00190-operator-anim.keying_set_active_set.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00190 +node tools/web/check-generated-gap.mjs --task M16-GAP-00190 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00190/` +- Status: `docs/status/M16-GAP-00190.md` +- Manifest: `tests/golden/M16-GAP-00190/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00190 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00191.md b/docs/tasks/M16-GAP-00191.md new file mode 100644 index 00000000..b49fa054 --- /dev/null +++ b/docs/tasks/M16-GAP-00191.md @@ -0,0 +1,37 @@ +# M16-GAP-00191: operator:anim.keying_set_add LOCAL_EXACT slice + +- task: M16-GAP-00191 +- parent: M16-GAP-00190 +- status: in_progress +- gap: operator:anim.keying_set_add +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.keying_set_add data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00191-operator-anim.keying_set_add.blend` +- Generator: `tools/web/generated/M16-GAP-00191.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00191.py -- tests/files/web/generated/M16-GAP-00191-operator-anim.keying_set_add.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00191 +node tools/web/check-generated-gap.mjs --task M16-GAP-00191 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00191/` +- Status: `docs/status/M16-GAP-00191.md` +- Manifest: `tests/golden/M16-GAP-00191/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00191 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00192.md b/docs/tasks/M16-GAP-00192.md new file mode 100644 index 00000000..c2e37d53 --- /dev/null +++ b/docs/tasks/M16-GAP-00192.md @@ -0,0 +1,37 @@ +# M16-GAP-00192: operator:anim.keying_set_export LOCAL_EXACT slice + +- task: M16-GAP-00192 +- parent: M16-GAP-00191 +- status: in_progress +- gap: operator:anim.keying_set_export +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.keying_set_export data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00192-operator-anim.keying_set_export.blend` +- Generator: `tools/web/generated/M16-GAP-00192.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00192.py -- tests/files/web/generated/M16-GAP-00192-operator-anim.keying_set_export.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00192 +node tools/web/check-generated-gap.mjs --task M16-GAP-00192 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00192/` +- Status: `docs/status/M16-GAP-00192.md` +- Manifest: `tests/golden/M16-GAP-00192/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00192 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00193.md b/docs/tasks/M16-GAP-00193.md new file mode 100644 index 00000000..2218e3ff --- /dev/null +++ b/docs/tasks/M16-GAP-00193.md @@ -0,0 +1,37 @@ +# M16-GAP-00193: operator:anim.keying_set_path_add LOCAL_EXACT slice + +- task: M16-GAP-00193 +- parent: M16-GAP-00192 +- status: in_progress +- gap: operator:anim.keying_set_path_add +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.keying_set_path_add data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00193-operator-anim.keying_set_path_add.blend` +- Generator: `tools/web/generated/M16-GAP-00193.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00193.py -- tests/files/web/generated/M16-GAP-00193-operator-anim.keying_set_path_add.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00193 +node tools/web/check-generated-gap.mjs --task M16-GAP-00193 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00193/` +- Status: `docs/status/M16-GAP-00193.md` +- Manifest: `tests/golden/M16-GAP-00193/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00193 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00194.md b/docs/tasks/M16-GAP-00194.md new file mode 100644 index 00000000..1548598e --- /dev/null +++ b/docs/tasks/M16-GAP-00194.md @@ -0,0 +1,37 @@ +# M16-GAP-00194: operator:anim.keying_set_path_remove LOCAL_EXACT slice + +- task: M16-GAP-00194 +- parent: M16-GAP-00193 +- status: in_progress +- gap: operator:anim.keying_set_path_remove +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.keying_set_path_remove data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00194-operator-anim.keying_set_path_remove.blend` +- Generator: `tools/web/generated/M16-GAP-00194.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00194.py -- tests/files/web/generated/M16-GAP-00194-operator-anim.keying_set_path_remove.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00194 +node tools/web/check-generated-gap.mjs --task M16-GAP-00194 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00194/` +- Status: `docs/status/M16-GAP-00194.md` +- Manifest: `tests/golden/M16-GAP-00194/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00194 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00195.md b/docs/tasks/M16-GAP-00195.md new file mode 100644 index 00000000..4af142d1 --- /dev/null +++ b/docs/tasks/M16-GAP-00195.md @@ -0,0 +1,37 @@ +# M16-GAP-00195: operator:anim.keying_set_remove LOCAL_EXACT slice + +- task: M16-GAP-00195 +- parent: M16-GAP-00194 +- status: in_progress +- gap: operator:anim.keying_set_remove +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.keying_set_remove data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00195-operator-anim.keying_set_remove.blend` +- Generator: `tools/web/generated/M16-GAP-00195.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00195.py -- tests/files/web/generated/M16-GAP-00195-operator-anim.keying_set_remove.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00195 +node tools/web/check-generated-gap.mjs --task M16-GAP-00195 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00195/` +- Status: `docs/status/M16-GAP-00195.md` +- Manifest: `tests/golden/M16-GAP-00195/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00195 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00196.md b/docs/tasks/M16-GAP-00196.md new file mode 100644 index 00000000..b6b8c040 --- /dev/null +++ b/docs/tasks/M16-GAP-00196.md @@ -0,0 +1,37 @@ +# M16-GAP-00196: operator:anim.keyingset_button_add LOCAL_EXACT slice + +- task: M16-GAP-00196 +- parent: M16-GAP-00195 +- status: in_progress +- gap: operator:anim.keyingset_button_add +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.keyingset_button_add data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00196-operator-anim.keyingset_button_add.blend` +- Generator: `tools/web/generated/M16-GAP-00196.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00196.py -- tests/files/web/generated/M16-GAP-00196-operator-anim.keyingset_button_add.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00196 +node tools/web/check-generated-gap.mjs --task M16-GAP-00196 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00196/` +- Status: `docs/status/M16-GAP-00196.md` +- Manifest: `tests/golden/M16-GAP-00196/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00196 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00197.md b/docs/tasks/M16-GAP-00197.md new file mode 100644 index 00000000..0e0aca9c --- /dev/null +++ b/docs/tasks/M16-GAP-00197.md @@ -0,0 +1,37 @@ +# M16-GAP-00197: operator:anim.keyingset_button_remove LOCAL_EXACT slice + +- task: M16-GAP-00197 +- parent: M16-GAP-00196 +- status: in_progress +- gap: operator:anim.keyingset_button_remove +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.keyingset_button_remove data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00197-operator-anim.keyingset_button_remove.blend` +- Generator: `tools/web/generated/M16-GAP-00197.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00197.py -- tests/files/web/generated/M16-GAP-00197-operator-anim.keyingset_button_remove.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00197 +node tools/web/check-generated-gap.mjs --task M16-GAP-00197 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00197/` +- Status: `docs/status/M16-GAP-00197.md` +- Manifest: `tests/golden/M16-GAP-00197/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00197 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00198.md b/docs/tasks/M16-GAP-00198.md new file mode 100644 index 00000000..68e3a060 --- /dev/null +++ b/docs/tasks/M16-GAP-00198.md @@ -0,0 +1,37 @@ +# M16-GAP-00198: operator:anim.merge_animation LOCAL_EXACT slice + +- task: M16-GAP-00198 +- parent: M16-GAP-00197 +- status: in_progress +- gap: operator:anim.merge_animation +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.merge_animation data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00198-operator-anim.merge_animation.blend` +- Generator: `tools/web/generated/M16-GAP-00198.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00198.py -- tests/files/web/generated/M16-GAP-00198-operator-anim.merge_animation.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00198 +node tools/web/check-generated-gap.mjs --task M16-GAP-00198 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00198/` +- Status: `docs/status/M16-GAP-00198.md` +- Manifest: `tests/golden/M16-GAP-00198/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00198 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00199.md b/docs/tasks/M16-GAP-00199.md new file mode 100644 index 00000000..1c982717 --- /dev/null +++ b/docs/tasks/M16-GAP-00199.md @@ -0,0 +1,37 @@ +# M16-GAP-00199: operator:anim.paste_driver_button LOCAL_EXACT slice + +- task: M16-GAP-00199 +- parent: M16-GAP-00198 +- status: in_progress +- gap: operator:anim.paste_driver_button +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.paste_driver_button data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00199-operator-anim.paste_driver_button.blend` +- Generator: `tools/web/generated/M16-GAP-00199.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00199.py -- tests/files/web/generated/M16-GAP-00199-operator-anim.paste_driver_button.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00199 +node tools/web/check-generated-gap.mjs --task M16-GAP-00199 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00199/` +- Status: `docs/status/M16-GAP-00199.md` +- Manifest: `tests/golden/M16-GAP-00199/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00199 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00200.md b/docs/tasks/M16-GAP-00200.md new file mode 100644 index 00000000..83c42dfa --- /dev/null +++ b/docs/tasks/M16-GAP-00200.md @@ -0,0 +1,37 @@ +# M16-GAP-00200: operator:anim.previewrange_clear LOCAL_EXACT slice + +- task: M16-GAP-00200 +- parent: M16-GAP-00199 +- status: in_progress +- gap: operator:anim.previewrange_clear +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.previewrange_clear data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00200-operator-anim.previewrange_clear.blend` +- Generator: `tools/web/generated/M16-GAP-00200.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00200.py -- tests/files/web/generated/M16-GAP-00200-operator-anim.previewrange_clear.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00200 +node tools/web/check-generated-gap.mjs --task M16-GAP-00200 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00200/` +- Status: `docs/status/M16-GAP-00200.md` +- Manifest: `tests/golden/M16-GAP-00200/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00200 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00201.md b/docs/tasks/M16-GAP-00201.md new file mode 100644 index 00000000..a9e4973b --- /dev/null +++ b/docs/tasks/M16-GAP-00201.md @@ -0,0 +1,37 @@ +# M16-GAP-00201: operator:anim.previewrange_set LOCAL_EXACT slice + +- task: M16-GAP-00201 +- parent: M16-GAP-00200 +- status: in_progress +- gap: operator:anim.previewrange_set +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.previewrange_set data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00201-operator-anim.previewrange_set.blend` +- Generator: `tools/web/generated/M16-GAP-00201.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00201.py -- tests/files/web/generated/M16-GAP-00201-operator-anim.previewrange_set.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00201 +node tools/web/check-generated-gap.mjs --task M16-GAP-00201 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00201/` +- Status: `docs/status/M16-GAP-00201.md` +- Manifest: `tests/golden/M16-GAP-00201/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00201 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00202.md b/docs/tasks/M16-GAP-00202.md new file mode 100644 index 00000000..b8a5e28c --- /dev/null +++ b/docs/tasks/M16-GAP-00202.md @@ -0,0 +1,37 @@ +# M16-GAP-00202: operator:anim.replace_action LOCAL_EXACT slice + +- task: M16-GAP-00202 +- parent: M16-GAP-00201 +- status: in_progress +- gap: operator:anim.replace_action +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.replace_action data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00202-operator-anim.replace_action.blend` +- Generator: `tools/web/generated/M16-GAP-00202.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00202.py -- tests/files/web/generated/M16-GAP-00202-operator-anim.replace_action.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00202 +node tools/web/check-generated-gap.mjs --task M16-GAP-00202 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00202/` +- Status: `docs/status/M16-GAP-00202.md` +- Manifest: `tests/golden/M16-GAP-00202/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00202 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00203.md b/docs/tasks/M16-GAP-00203.md new file mode 100644 index 00000000..f3c73234 --- /dev/null +++ b/docs/tasks/M16-GAP-00203.md @@ -0,0 +1,37 @@ +# M16-GAP-00203: operator:anim.replace_action_new LOCAL_EXACT slice + +- task: M16-GAP-00203 +- parent: M16-GAP-00202 +- status: in_progress +- gap: operator:anim.replace_action_new +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.replace_action_new data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00203-operator-anim.replace_action_new.blend` +- Generator: `tools/web/generated/M16-GAP-00203.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00203.py -- tests/files/web/generated/M16-GAP-00203-operator-anim.replace_action_new.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00203 +node tools/web/check-generated-gap.mjs --task M16-GAP-00203 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00203/` +- Status: `docs/status/M16-GAP-00203.md` +- Manifest: `tests/golden/M16-GAP-00203/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00203 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00204.md b/docs/tasks/M16-GAP-00204.md new file mode 100644 index 00000000..084c789b --- /dev/null +++ b/docs/tasks/M16-GAP-00204.md @@ -0,0 +1,37 @@ +# M16-GAP-00204: operator:anim.scene_range_frame LOCAL_EXACT slice + +- task: M16-GAP-00204 +- parent: M16-GAP-00203 +- status: in_progress +- gap: operator:anim.scene_range_frame +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.scene_range_frame data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00204-operator-anim.scene_range_frame.blend` +- Generator: `tools/web/generated/M16-GAP-00204.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00204.py -- tests/files/web/generated/M16-GAP-00204-operator-anim.scene_range_frame.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00204 +node tools/web/check-generated-gap.mjs --task M16-GAP-00204 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00204/` +- Status: `docs/status/M16-GAP-00204.md` +- Manifest: `tests/golden/M16-GAP-00204/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00204 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00205.md b/docs/tasks/M16-GAP-00205.md new file mode 100644 index 00000000..211ec106 --- /dev/null +++ b/docs/tasks/M16-GAP-00205.md @@ -0,0 +1,37 @@ +# M16-GAP-00205: operator:anim.separate_slots LOCAL_EXACT slice + +- task: M16-GAP-00205 +- parent: M16-GAP-00204 +- status: in_progress +- gap: operator:anim.separate_slots +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.separate_slots data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00205-operator-anim.separate_slots.blend` +- Generator: `tools/web/generated/M16-GAP-00205.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00205.py -- tests/files/web/generated/M16-GAP-00205-operator-anim.separate_slots.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00205 +node tools/web/check-generated-gap.mjs --task M16-GAP-00205 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00205/` +- Status: `docs/status/M16-GAP-00205.md` +- Manifest: `tests/golden/M16-GAP-00205/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00205 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00206.md b/docs/tasks/M16-GAP-00206.md new file mode 100644 index 00000000..4d548e17 --- /dev/null +++ b/docs/tasks/M16-GAP-00206.md @@ -0,0 +1,37 @@ +# M16-GAP-00206: operator:anim.slot_channels_move_to_new_action LOCAL_EXACT slice + +- task: M16-GAP-00206 +- parent: M16-GAP-00205 +- status: in_progress +- gap: operator:anim.slot_channels_move_to_new_action +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.slot_channels_move_to_new_action data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00206-operator-anim.slot_channels_move_to_new_action.blend` +- Generator: `tools/web/generated/M16-GAP-00206.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00206.py -- tests/files/web/generated/M16-GAP-00206-operator-anim.slot_channels_move_to_new_action.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00206 +node tools/web/check-generated-gap.mjs --task M16-GAP-00206 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00206/` +- Status: `docs/status/M16-GAP-00206.md` +- Manifest: `tests/golden/M16-GAP-00206/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00206 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00207.md b/docs/tasks/M16-GAP-00207.md new file mode 100644 index 00000000..d499b40d --- /dev/null +++ b/docs/tasks/M16-GAP-00207.md @@ -0,0 +1,37 @@ +# M16-GAP-00207: operator:anim.slot_new_for_id LOCAL_EXACT slice + +- task: M16-GAP-00207 +- parent: M16-GAP-00206 +- status: in_progress +- gap: operator:anim.slot_new_for_id +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.slot_new_for_id data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00207-operator-anim.slot_new_for_id.blend` +- Generator: `tools/web/generated/M16-GAP-00207.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00207.py -- tests/files/web/generated/M16-GAP-00207-operator-anim.slot_new_for_id.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00207 +node tools/web/check-generated-gap.mjs --task M16-GAP-00207 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00207/` +- Status: `docs/status/M16-GAP-00207.md` +- Manifest: `tests/golden/M16-GAP-00207/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00207 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00208.md b/docs/tasks/M16-GAP-00208.md new file mode 100644 index 00000000..86f5666a --- /dev/null +++ b/docs/tasks/M16-GAP-00208.md @@ -0,0 +1,37 @@ +# M16-GAP-00208: operator:anim.slot_unassign_from_constraint LOCAL_EXACT slice + +- task: M16-GAP-00208 +- parent: M16-GAP-00207 +- status: in_progress +- gap: operator:anim.slot_unassign_from_constraint +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.slot_unassign_from_constraint data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00208-operator-anim.slot_unassign_from_constraint.blend` +- Generator: `tools/web/generated/M16-GAP-00208.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00208.py -- tests/files/web/generated/M16-GAP-00208-operator-anim.slot_unassign_from_constraint.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00208 +node tools/web/check-generated-gap.mjs --task M16-GAP-00208 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00208/` +- Status: `docs/status/M16-GAP-00208.md` +- Manifest: `tests/golden/M16-GAP-00208/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00208 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00209.md b/docs/tasks/M16-GAP-00209.md new file mode 100644 index 00000000..f2c13cc0 --- /dev/null +++ b/docs/tasks/M16-GAP-00209.md @@ -0,0 +1,37 @@ +# M16-GAP-00209: operator:anim.slot_unassign_from_id LOCAL_EXACT slice + +- task: M16-GAP-00209 +- parent: M16-GAP-00208 +- status: in_progress +- gap: operator:anim.slot_unassign_from_id +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.slot_unassign_from_id data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00209-operator-anim.slot_unassign_from_id.blend` +- Generator: `tools/web/generated/M16-GAP-00209.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00209.py -- tests/files/web/generated/M16-GAP-00209-operator-anim.slot_unassign_from_id.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00209 +node tools/web/check-generated-gap.mjs --task M16-GAP-00209 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00209/` +- Status: `docs/status/M16-GAP-00209.md` +- Manifest: `tests/golden/M16-GAP-00209/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00209 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00210.md b/docs/tasks/M16-GAP-00210.md new file mode 100644 index 00000000..ea023987 --- /dev/null +++ b/docs/tasks/M16-GAP-00210.md @@ -0,0 +1,37 @@ +# M16-GAP-00210: operator:anim.slot_unassign_from_nla_strip LOCAL_EXACT slice + +- task: M16-GAP-00210 +- parent: M16-GAP-00209 +- status: in_progress +- gap: operator:anim.slot_unassign_from_nla_strip +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.slot_unassign_from_nla_strip data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00210-operator-anim.slot_unassign_from_nla_strip.blend` +- Generator: `tools/web/generated/M16-GAP-00210.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00210.py -- tests/files/web/generated/M16-GAP-00210-operator-anim.slot_unassign_from_nla_strip.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00210 +node tools/web/check-generated-gap.mjs --task M16-GAP-00210 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00210/` +- Status: `docs/status/M16-GAP-00210.md` +- Manifest: `tests/golden/M16-GAP-00210/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00210 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00211.md b/docs/tasks/M16-GAP-00211.md new file mode 100644 index 00000000..ee83025d --- /dev/null +++ b/docs/tasks/M16-GAP-00211.md @@ -0,0 +1,37 @@ +# M16-GAP-00211: operator:anim.start_frame_set LOCAL_EXACT slice + +- task: M16-GAP-00211 +- parent: M16-GAP-00210 +- status: in_progress +- gap: operator:anim.start_frame_set +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.start_frame_set data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00211-operator-anim.start_frame_set.blend` +- Generator: `tools/web/generated/M16-GAP-00211.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00211.py -- tests/files/web/generated/M16-GAP-00211-operator-anim.start_frame_set.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00211 +node tools/web/check-generated-gap.mjs --task M16-GAP-00211 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00211/` +- Status: `docs/status/M16-GAP-00211.md` +- Manifest: `tests/golden/M16-GAP-00211/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00211 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00212.md b/docs/tasks/M16-GAP-00212.md new file mode 100644 index 00000000..0a57e5ba --- /dev/null +++ b/docs/tasks/M16-GAP-00212.md @@ -0,0 +1,37 @@ +# M16-GAP-00212: operator:anim.update_animated_transform_constraints LOCAL_EXACT slice + +- task: M16-GAP-00212 +- parent: M16-GAP-00211 +- status: in_progress +- gap: operator:anim.update_animated_transform_constraints +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.update_animated_transform_constraints data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00212-operator-anim.update_animated_transform_constraints.blend` +- Generator: `tools/web/generated/M16-GAP-00212.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00212.py -- tests/files/web/generated/M16-GAP-00212-operator-anim.update_animated_transform_constraints.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00212 +node tools/web/check-generated-gap.mjs --task M16-GAP-00212 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00212/` +- Status: `docs/status/M16-GAP-00212.md` +- Manifest: `tests/golden/M16-GAP-00212/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00212 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00213.md b/docs/tasks/M16-GAP-00213.md new file mode 100644 index 00000000..921c54fc --- /dev/null +++ b/docs/tasks/M16-GAP-00213.md @@ -0,0 +1,37 @@ +# M16-GAP-00213: operator:anim.version_bone_hide_property LOCAL_EXACT slice + +- task: M16-GAP-00213 +- parent: M16-GAP-00212 +- status: in_progress +- gap: operator:anim.version_bone_hide_property +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.version_bone_hide_property data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00213-operator-anim.version_bone_hide_property.blend` +- Generator: `tools/web/generated/M16-GAP-00213.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00213.py -- tests/files/web/generated/M16-GAP-00213-operator-anim.version_bone_hide_property.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00213 +node tools/web/check-generated-gap.mjs --task M16-GAP-00213 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00213/` +- Status: `docs/status/M16-GAP-00213.md` +- Manifest: `tests/golden/M16-GAP-00213/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00213 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00214.md b/docs/tasks/M16-GAP-00214.md new file mode 100644 index 00000000..8300d80d --- /dev/null +++ b/docs/tasks/M16-GAP-00214.md @@ -0,0 +1,37 @@ +# M16-GAP-00214: operator:anim.view_curve_in_graph_editor LOCAL_EXACT slice + +- task: M16-GAP-00214 +- parent: M16-GAP-00213 +- status: in_progress +- gap: operator:anim.view_curve_in_graph_editor +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:anim.view_curve_in_graph_editor data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00214-operator-anim.view_curve_in_graph_editor.blend` +- Generator: `tools/web/generated/M16-GAP-00214.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00214.py -- tests/files/web/generated/M16-GAP-00214-operator-anim.view_curve_in_graph_editor.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00214 +node tools/web/check-generated-gap.mjs --task M16-GAP-00214 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00214/` +- Status: `docs/status/M16-GAP-00214.md` +- Manifest: `tests/golden/M16-GAP-00214/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00214 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00215.md b/docs/tasks/M16-GAP-00215.md new file mode 100644 index 00000000..639e29a3 --- /dev/null +++ b/docs/tasks/M16-GAP-00215.md @@ -0,0 +1,37 @@ +# M16-GAP-00215: operator:armature.align LOCAL_EXACT slice + +- task: M16-GAP-00215 +- parent: M16-GAP-00214 +- status: in_progress +- gap: operator:armature.align +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.align data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00215-operator-armature.align.blend` +- Generator: `tools/web/generated/M16-GAP-00215.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00215.py -- tests/files/web/generated/M16-GAP-00215-operator-armature.align.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00215 +node tools/web/check-generated-gap.mjs --task M16-GAP-00215 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00215/` +- Status: `docs/status/M16-GAP-00215.md` +- Manifest: `tests/golden/M16-GAP-00215/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00215 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00216.md b/docs/tasks/M16-GAP-00216.md new file mode 100644 index 00000000..b5af3f80 --- /dev/null +++ b/docs/tasks/M16-GAP-00216.md @@ -0,0 +1,37 @@ +# M16-GAP-00216: operator:armature.assign_to_collection LOCAL_EXACT slice + +- task: M16-GAP-00216 +- parent: M16-GAP-00215 +- status: in_progress +- gap: operator:armature.assign_to_collection +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.assign_to_collection data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00216-operator-armature.assign_to_collection.blend` +- Generator: `tools/web/generated/M16-GAP-00216.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00216.py -- tests/files/web/generated/M16-GAP-00216-operator-armature.assign_to_collection.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00216 +node tools/web/check-generated-gap.mjs --task M16-GAP-00216 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00216/` +- Status: `docs/status/M16-GAP-00216.md` +- Manifest: `tests/golden/M16-GAP-00216/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00216 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00217.md b/docs/tasks/M16-GAP-00217.md new file mode 100644 index 00000000..3ba21120 --- /dev/null +++ b/docs/tasks/M16-GAP-00217.md @@ -0,0 +1,37 @@ +# M16-GAP-00217: operator:armature.autoside_names LOCAL_EXACT slice + +- task: M16-GAP-00217 +- parent: M16-GAP-00216 +- status: in_progress +- gap: operator:armature.autoside_names +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.autoside_names data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00217-operator-armature.autoside_names.blend` +- Generator: `tools/web/generated/M16-GAP-00217.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00217.py -- tests/files/web/generated/M16-GAP-00217-operator-armature.autoside_names.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00217 +node tools/web/check-generated-gap.mjs --task M16-GAP-00217 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00217/` +- Status: `docs/status/M16-GAP-00217.md` +- Manifest: `tests/golden/M16-GAP-00217/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00217 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00218.md b/docs/tasks/M16-GAP-00218.md new file mode 100644 index 00000000..adedc59c --- /dev/null +++ b/docs/tasks/M16-GAP-00218.md @@ -0,0 +1,37 @@ +# M16-GAP-00218: operator:armature.bone_primitive_add LOCAL_EXACT slice + +- task: M16-GAP-00218 +- parent: M16-GAP-00217 +- status: in_progress +- gap: operator:armature.bone_primitive_add +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.bone_primitive_add data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00218-operator-armature.bone_primitive_add.blend` +- Generator: `tools/web/generated/M16-GAP-00218.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00218.py -- tests/files/web/generated/M16-GAP-00218-operator-armature.bone_primitive_add.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00218 +node tools/web/check-generated-gap.mjs --task M16-GAP-00218 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00218/` +- Status: `docs/status/M16-GAP-00218.md` +- Manifest: `tests/golden/M16-GAP-00218/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00218 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00219.md b/docs/tasks/M16-GAP-00219.md new file mode 100644 index 00000000..d5e82a6b --- /dev/null +++ b/docs/tasks/M16-GAP-00219.md @@ -0,0 +1,37 @@ +# M16-GAP-00219: operator:armature.calculate_roll LOCAL_EXACT slice + +- task: M16-GAP-00219 +- parent: M16-GAP-00218 +- status: in_progress +- gap: operator:armature.calculate_roll +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.calculate_roll data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00219-operator-armature.calculate_roll.blend` +- Generator: `tools/web/generated/M16-GAP-00219.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00219.py -- tests/files/web/generated/M16-GAP-00219-operator-armature.calculate_roll.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00219 +node tools/web/check-generated-gap.mjs --task M16-GAP-00219 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00219/` +- Status: `docs/status/M16-GAP-00219.md` +- Manifest: `tests/golden/M16-GAP-00219/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00219 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00220.md b/docs/tasks/M16-GAP-00220.md new file mode 100644 index 00000000..4bcc3e41 --- /dev/null +++ b/docs/tasks/M16-GAP-00220.md @@ -0,0 +1,37 @@ +# M16-GAP-00220: operator:armature.click_extrude LOCAL_EXACT slice + +- task: M16-GAP-00220 +- parent: M16-GAP-00219 +- status: in_progress +- gap: operator:armature.click_extrude +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.click_extrude data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00220-operator-armature.click_extrude.blend` +- Generator: `tools/web/generated/M16-GAP-00220.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00220.py -- tests/files/web/generated/M16-GAP-00220-operator-armature.click_extrude.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00220 +node tools/web/check-generated-gap.mjs --task M16-GAP-00220 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00220/` +- Status: `docs/status/M16-GAP-00220.md` +- Manifest: `tests/golden/M16-GAP-00220/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00220 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00221.md b/docs/tasks/M16-GAP-00221.md new file mode 100644 index 00000000..c8b8d5ca --- /dev/null +++ b/docs/tasks/M16-GAP-00221.md @@ -0,0 +1,37 @@ +# M16-GAP-00221: operator:armature.collection_add LOCAL_EXACT slice + +- task: M16-GAP-00221 +- parent: M16-GAP-00220 +- status: in_progress +- gap: operator:armature.collection_add +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.collection_add data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00221-operator-armature.collection_add.blend` +- Generator: `tools/web/generated/M16-GAP-00221.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00221.py -- tests/files/web/generated/M16-GAP-00221-operator-armature.collection_add.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00221 +node tools/web/check-generated-gap.mjs --task M16-GAP-00221 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00221/` +- Status: `docs/status/M16-GAP-00221.md` +- Manifest: `tests/golden/M16-GAP-00221/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00221 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00222.md b/docs/tasks/M16-GAP-00222.md new file mode 100644 index 00000000..549db42b --- /dev/null +++ b/docs/tasks/M16-GAP-00222.md @@ -0,0 +1,37 @@ +# M16-GAP-00222: operator:armature.collection_assign LOCAL_EXACT slice + +- task: M16-GAP-00222 +- parent: M16-GAP-00221 +- status: in_progress +- gap: operator:armature.collection_assign +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.collection_assign data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00222-operator-armature.collection_assign.blend` +- Generator: `tools/web/generated/M16-GAP-00222.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00222.py -- tests/files/web/generated/M16-GAP-00222-operator-armature.collection_assign.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00222 +node tools/web/check-generated-gap.mjs --task M16-GAP-00222 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00222/` +- Status: `docs/status/M16-GAP-00222.md` +- Manifest: `tests/golden/M16-GAP-00222/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00222 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00223.md b/docs/tasks/M16-GAP-00223.md new file mode 100644 index 00000000..6a73bf7a --- /dev/null +++ b/docs/tasks/M16-GAP-00223.md @@ -0,0 +1,37 @@ +# M16-GAP-00223: operator:armature.collection_create_and_assign LOCAL_EXACT slice + +- task: M16-GAP-00223 +- parent: M16-GAP-00222 +- status: in_progress +- gap: operator:armature.collection_create_and_assign +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.collection_create_and_assign data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00223-operator-armature.collection_create_and_assign.blend` +- Generator: `tools/web/generated/M16-GAP-00223.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00223.py -- tests/files/web/generated/M16-GAP-00223-operator-armature.collection_create_and_assign.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00223 +node tools/web/check-generated-gap.mjs --task M16-GAP-00223 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00223/` +- Status: `docs/status/M16-GAP-00223.md` +- Manifest: `tests/golden/M16-GAP-00223/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00223 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00224.md b/docs/tasks/M16-GAP-00224.md new file mode 100644 index 00000000..7009b870 --- /dev/null +++ b/docs/tasks/M16-GAP-00224.md @@ -0,0 +1,37 @@ +# M16-GAP-00224: operator:armature.collection_deselect LOCAL_EXACT slice + +- task: M16-GAP-00224 +- parent: M16-GAP-00223 +- status: in_progress +- gap: operator:armature.collection_deselect +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.collection_deselect data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00224-operator-armature.collection_deselect.blend` +- Generator: `tools/web/generated/M16-GAP-00224.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00224.py -- tests/files/web/generated/M16-GAP-00224-operator-armature.collection_deselect.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00224 +node tools/web/check-generated-gap.mjs --task M16-GAP-00224 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00224/` +- Status: `docs/status/M16-GAP-00224.md` +- Manifest: `tests/golden/M16-GAP-00224/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00224 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00225.md b/docs/tasks/M16-GAP-00225.md new file mode 100644 index 00000000..dc9c088e --- /dev/null +++ b/docs/tasks/M16-GAP-00225.md @@ -0,0 +1,37 @@ +# M16-GAP-00225: operator:armature.collection_move LOCAL_EXACT slice + +- task: M16-GAP-00225 +- parent: M16-GAP-00224 +- status: in_progress +- gap: operator:armature.collection_move +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.collection_move data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00225-operator-armature.collection_move.blend` +- Generator: `tools/web/generated/M16-GAP-00225.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00225.py -- tests/files/web/generated/M16-GAP-00225-operator-armature.collection_move.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00225 +node tools/web/check-generated-gap.mjs --task M16-GAP-00225 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00225/` +- Status: `docs/status/M16-GAP-00225.md` +- Manifest: `tests/golden/M16-GAP-00225/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00225 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00226.md b/docs/tasks/M16-GAP-00226.md new file mode 100644 index 00000000..17e41038 --- /dev/null +++ b/docs/tasks/M16-GAP-00226.md @@ -0,0 +1,37 @@ +# M16-GAP-00226: operator:armature.collection_remove LOCAL_EXACT slice + +- task: M16-GAP-00226 +- parent: M16-GAP-00225 +- status: in_progress +- gap: operator:armature.collection_remove +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.collection_remove data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00226-operator-armature.collection_remove.blend` +- Generator: `tools/web/generated/M16-GAP-00226.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00226.py -- tests/files/web/generated/M16-GAP-00226-operator-armature.collection_remove.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00226 +node tools/web/check-generated-gap.mjs --task M16-GAP-00226 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00226/` +- Status: `docs/status/M16-GAP-00226.md` +- Manifest: `tests/golden/M16-GAP-00226/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00226 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00227.md b/docs/tasks/M16-GAP-00227.md new file mode 100644 index 00000000..519ac47a --- /dev/null +++ b/docs/tasks/M16-GAP-00227.md @@ -0,0 +1,37 @@ +# M16-GAP-00227: operator:armature.collection_remove_unused LOCAL_EXACT slice + +- task: M16-GAP-00227 +- parent: M16-GAP-00226 +- status: in_progress +- gap: operator:armature.collection_remove_unused +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.collection_remove_unused data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00227-operator-armature.collection_remove_unused.blend` +- Generator: `tools/web/generated/M16-GAP-00227.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00227.py -- tests/files/web/generated/M16-GAP-00227-operator-armature.collection_remove_unused.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00227 +node tools/web/check-generated-gap.mjs --task M16-GAP-00227 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00227/` +- Status: `docs/status/M16-GAP-00227.md` +- Manifest: `tests/golden/M16-GAP-00227/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00227 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00228.md b/docs/tasks/M16-GAP-00228.md new file mode 100644 index 00000000..1757bd80 --- /dev/null +++ b/docs/tasks/M16-GAP-00228.md @@ -0,0 +1,37 @@ +# M16-GAP-00228: operator:armature.collection_select LOCAL_EXACT slice + +- task: M16-GAP-00228 +- parent: M16-GAP-00227 +- status: in_progress +- gap: operator:armature.collection_select +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.collection_select data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00228-operator-armature.collection_select.blend` +- Generator: `tools/web/generated/M16-GAP-00228.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00228.py -- tests/files/web/generated/M16-GAP-00228-operator-armature.collection_select.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00228 +node tools/web/check-generated-gap.mjs --task M16-GAP-00228 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00228/` +- Status: `docs/status/M16-GAP-00228.md` +- Manifest: `tests/golden/M16-GAP-00228/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00228 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00229.md b/docs/tasks/M16-GAP-00229.md new file mode 100644 index 00000000..335afdec --- /dev/null +++ b/docs/tasks/M16-GAP-00229.md @@ -0,0 +1,37 @@ +# M16-GAP-00229: operator:armature.collection_show_all LOCAL_EXACT slice + +- task: M16-GAP-00229 +- parent: M16-GAP-00228 +- status: in_progress +- gap: operator:armature.collection_show_all +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.collection_show_all data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00229-operator-armature.collection_show_all.blend` +- Generator: `tools/web/generated/M16-GAP-00229.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00229.py -- tests/files/web/generated/M16-GAP-00229-operator-armature.collection_show_all.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00229 +node tools/web/check-generated-gap.mjs --task M16-GAP-00229 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00229/` +- Status: `docs/status/M16-GAP-00229.md` +- Manifest: `tests/golden/M16-GAP-00229/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00229 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00230.md b/docs/tasks/M16-GAP-00230.md new file mode 100644 index 00000000..da522b07 --- /dev/null +++ b/docs/tasks/M16-GAP-00230.md @@ -0,0 +1,37 @@ +# M16-GAP-00230: operator:armature.collection_unassign LOCAL_EXACT slice + +- task: M16-GAP-00230 +- parent: M16-GAP-00229 +- status: in_progress +- gap: operator:armature.collection_unassign +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.collection_unassign data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00230-operator-armature.collection_unassign.blend` +- Generator: `tools/web/generated/M16-GAP-00230.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00230.py -- tests/files/web/generated/M16-GAP-00230-operator-armature.collection_unassign.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00230 +node tools/web/check-generated-gap.mjs --task M16-GAP-00230 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00230/` +- Status: `docs/status/M16-GAP-00230.md` +- Manifest: `tests/golden/M16-GAP-00230/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00230 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00231.md b/docs/tasks/M16-GAP-00231.md new file mode 100644 index 00000000..37bbdf3c --- /dev/null +++ b/docs/tasks/M16-GAP-00231.md @@ -0,0 +1,37 @@ +# M16-GAP-00231: operator:armature.collection_unassign_named LOCAL_EXACT slice + +- task: M16-GAP-00231 +- parent: M16-GAP-00230 +- status: in_progress +- gap: operator:armature.collection_unassign_named +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.collection_unassign_named data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00231-operator-armature.collection_unassign_named.blend` +- Generator: `tools/web/generated/M16-GAP-00231.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00231.py -- tests/files/web/generated/M16-GAP-00231-operator-armature.collection_unassign_named.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00231 +node tools/web/check-generated-gap.mjs --task M16-GAP-00231 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00231/` +- Status: `docs/status/M16-GAP-00231.md` +- Manifest: `tests/golden/M16-GAP-00231/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00231 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00232.md b/docs/tasks/M16-GAP-00232.md new file mode 100644 index 00000000..bbdbfbe4 --- /dev/null +++ b/docs/tasks/M16-GAP-00232.md @@ -0,0 +1,37 @@ +# M16-GAP-00232: operator:armature.collection_unsolo_all LOCAL_EXACT slice + +- task: M16-GAP-00232 +- parent: M16-GAP-00231 +- status: in_progress +- gap: operator:armature.collection_unsolo_all +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.collection_unsolo_all data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00232-operator-armature.collection_unsolo_all.blend` +- Generator: `tools/web/generated/M16-GAP-00232.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00232.py -- tests/files/web/generated/M16-GAP-00232-operator-armature.collection_unsolo_all.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00232 +node tools/web/check-generated-gap.mjs --task M16-GAP-00232 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00232/` +- Status: `docs/status/M16-GAP-00232.md` +- Manifest: `tests/golden/M16-GAP-00232/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00232 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00233.md b/docs/tasks/M16-GAP-00233.md new file mode 100644 index 00000000..ba2198a7 --- /dev/null +++ b/docs/tasks/M16-GAP-00233.md @@ -0,0 +1,37 @@ +# M16-GAP-00233: operator:armature.copy_bone_color_to_selected LOCAL_EXACT slice + +- task: M16-GAP-00233 +- parent: M16-GAP-00232 +- status: in_progress +- gap: operator:armature.copy_bone_color_to_selected +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.copy_bone_color_to_selected data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00233-operator-armature.copy_bone_color_to_selected.blend` +- Generator: `tools/web/generated/M16-GAP-00233.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00233.py -- tests/files/web/generated/M16-GAP-00233-operator-armature.copy_bone_color_to_selected.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00233 +node tools/web/check-generated-gap.mjs --task M16-GAP-00233 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00233/` +- Status: `docs/status/M16-GAP-00233.md` +- Manifest: `tests/golden/M16-GAP-00233/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00233 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00234.md b/docs/tasks/M16-GAP-00234.md new file mode 100644 index 00000000..2e54e1a1 --- /dev/null +++ b/docs/tasks/M16-GAP-00234.md @@ -0,0 +1,37 @@ +# M16-GAP-00234: operator:armature.delete LOCAL_EXACT slice + +- task: M16-GAP-00234 +- parent: M16-GAP-00233 +- status: in_progress +- gap: operator:armature.delete +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.delete data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00234-operator-armature.delete.blend` +- Generator: `tools/web/generated/M16-GAP-00234.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00234.py -- tests/files/web/generated/M16-GAP-00234-operator-armature.delete.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00234 +node tools/web/check-generated-gap.mjs --task M16-GAP-00234 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00234/` +- Status: `docs/status/M16-GAP-00234.md` +- Manifest: `tests/golden/M16-GAP-00234/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00234 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00235.md b/docs/tasks/M16-GAP-00235.md new file mode 100644 index 00000000..fa249228 --- /dev/null +++ b/docs/tasks/M16-GAP-00235.md @@ -0,0 +1,37 @@ +# M16-GAP-00235: operator:armature.dissolve LOCAL_EXACT slice + +- task: M16-GAP-00235 +- parent: M16-GAP-00234 +- status: in_progress +- gap: operator:armature.dissolve +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.dissolve data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00235-operator-armature.dissolve.blend` +- Generator: `tools/web/generated/M16-GAP-00235.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00235.py -- tests/files/web/generated/M16-GAP-00235-operator-armature.dissolve.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00235 +node tools/web/check-generated-gap.mjs --task M16-GAP-00235 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00235/` +- Status: `docs/status/M16-GAP-00235.md` +- Manifest: `tests/golden/M16-GAP-00235/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00235 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00236.md b/docs/tasks/M16-GAP-00236.md new file mode 100644 index 00000000..7662406a --- /dev/null +++ b/docs/tasks/M16-GAP-00236.md @@ -0,0 +1,37 @@ +# M16-GAP-00236: operator:armature.duplicate LOCAL_EXACT slice + +- task: M16-GAP-00236 +- parent: M16-GAP-00235 +- status: in_progress +- gap: operator:armature.duplicate +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.duplicate data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00236-operator-armature.duplicate.blend` +- Generator: `tools/web/generated/M16-GAP-00236.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00236.py -- tests/files/web/generated/M16-GAP-00236-operator-armature.duplicate.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00236 +node tools/web/check-generated-gap.mjs --task M16-GAP-00236 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00236/` +- Status: `docs/status/M16-GAP-00236.md` +- Manifest: `tests/golden/M16-GAP-00236/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00236 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00237.md b/docs/tasks/M16-GAP-00237.md new file mode 100644 index 00000000..69231bf9 --- /dev/null +++ b/docs/tasks/M16-GAP-00237.md @@ -0,0 +1,37 @@ +# M16-GAP-00237: operator:armature.duplicate_move LOCAL_EXACT slice + +- task: M16-GAP-00237 +- parent: M16-GAP-00236 +- status: in_progress +- gap: operator:armature.duplicate_move +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.duplicate_move data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00237-operator-armature.duplicate_move.blend` +- Generator: `tools/web/generated/M16-GAP-00237.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00237.py -- tests/files/web/generated/M16-GAP-00237-operator-armature.duplicate_move.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00237 +node tools/web/check-generated-gap.mjs --task M16-GAP-00237 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00237/` +- Status: `docs/status/M16-GAP-00237.md` +- Manifest: `tests/golden/M16-GAP-00237/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00237 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00238.md b/docs/tasks/M16-GAP-00238.md new file mode 100644 index 00000000..f41e6483 --- /dev/null +++ b/docs/tasks/M16-GAP-00238.md @@ -0,0 +1,37 @@ +# M16-GAP-00238: operator:armature.duplicate_rename LOCAL_EXACT slice + +- task: M16-GAP-00238 +- parent: M16-GAP-00237 +- status: in_progress +- gap: operator:armature.duplicate_rename +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.duplicate_rename data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00238-operator-armature.duplicate_rename.blend` +- Generator: `tools/web/generated/M16-GAP-00238.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00238.py -- tests/files/web/generated/M16-GAP-00238-operator-armature.duplicate_rename.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00238 +node tools/web/check-generated-gap.mjs --task M16-GAP-00238 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00238/` +- Status: `docs/status/M16-GAP-00238.md` +- Manifest: `tests/golden/M16-GAP-00238/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00238 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00239.md b/docs/tasks/M16-GAP-00239.md new file mode 100644 index 00000000..2e636f8b --- /dev/null +++ b/docs/tasks/M16-GAP-00239.md @@ -0,0 +1,37 @@ +# M16-GAP-00239: operator:armature.extrude LOCAL_EXACT slice + +- task: M16-GAP-00239 +- parent: M16-GAP-00238 +- status: in_progress +- gap: operator:armature.extrude +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.extrude data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00239-operator-armature.extrude.blend` +- Generator: `tools/web/generated/M16-GAP-00239.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00239.py -- tests/files/web/generated/M16-GAP-00239-operator-armature.extrude.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00239 +node tools/web/check-generated-gap.mjs --task M16-GAP-00239 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00239/` +- Status: `docs/status/M16-GAP-00239.md` +- Manifest: `tests/golden/M16-GAP-00239/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00239 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00240.md b/docs/tasks/M16-GAP-00240.md new file mode 100644 index 00000000..76548448 --- /dev/null +++ b/docs/tasks/M16-GAP-00240.md @@ -0,0 +1,37 @@ +# M16-GAP-00240: operator:armature.extrude_forked LOCAL_EXACT slice + +- task: M16-GAP-00240 +- parent: M16-GAP-00239 +- status: in_progress +- gap: operator:armature.extrude_forked +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.extrude_forked data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00240-operator-armature.extrude_forked.blend` +- Generator: `tools/web/generated/M16-GAP-00240.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00240.py -- tests/files/web/generated/M16-GAP-00240-operator-armature.extrude_forked.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00240 +node tools/web/check-generated-gap.mjs --task M16-GAP-00240 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00240/` +- Status: `docs/status/M16-GAP-00240.md` +- Manifest: `tests/golden/M16-GAP-00240/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00240 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00241.md b/docs/tasks/M16-GAP-00241.md new file mode 100644 index 00000000..693b4923 --- /dev/null +++ b/docs/tasks/M16-GAP-00241.md @@ -0,0 +1,37 @@ +# M16-GAP-00241: operator:armature.extrude_move LOCAL_EXACT slice + +- task: M16-GAP-00241 +- parent: M16-GAP-00240 +- status: in_progress +- gap: operator:armature.extrude_move +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.extrude_move data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00241-operator-armature.extrude_move.blend` +- Generator: `tools/web/generated/M16-GAP-00241.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00241.py -- tests/files/web/generated/M16-GAP-00241-operator-armature.extrude_move.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00241 +node tools/web/check-generated-gap.mjs --task M16-GAP-00241 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00241/` +- Status: `docs/status/M16-GAP-00241.md` +- Manifest: `tests/golden/M16-GAP-00241/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00241 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00242.md b/docs/tasks/M16-GAP-00242.md new file mode 100644 index 00000000..87fa9783 --- /dev/null +++ b/docs/tasks/M16-GAP-00242.md @@ -0,0 +1,37 @@ +# M16-GAP-00242: operator:armature.fill LOCAL_EXACT slice + +- task: M16-GAP-00242 +- parent: M16-GAP-00241 +- status: in_progress +- gap: operator:armature.fill +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.fill data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00242-operator-armature.fill.blend` +- Generator: `tools/web/generated/M16-GAP-00242.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00242.py -- tests/files/web/generated/M16-GAP-00242-operator-armature.fill.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00242 +node tools/web/check-generated-gap.mjs --task M16-GAP-00242 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00242/` +- Status: `docs/status/M16-GAP-00242.md` +- Manifest: `tests/golden/M16-GAP-00242/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00242 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00243.md b/docs/tasks/M16-GAP-00243.md new file mode 100644 index 00000000..edaf262c --- /dev/null +++ b/docs/tasks/M16-GAP-00243.md @@ -0,0 +1,37 @@ +# M16-GAP-00243: operator:armature.flip_names LOCAL_EXACT slice + +- task: M16-GAP-00243 +- parent: M16-GAP-00242 +- status: in_progress +- gap: operator:armature.flip_names +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.flip_names data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00243-operator-armature.flip_names.blend` +- Generator: `tools/web/generated/M16-GAP-00243.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00243.py -- tests/files/web/generated/M16-GAP-00243-operator-armature.flip_names.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00243 +node tools/web/check-generated-gap.mjs --task M16-GAP-00243 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00243/` +- Status: `docs/status/M16-GAP-00243.md` +- Manifest: `tests/golden/M16-GAP-00243/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00243 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00244.md b/docs/tasks/M16-GAP-00244.md new file mode 100644 index 00000000..6929ba45 --- /dev/null +++ b/docs/tasks/M16-GAP-00244.md @@ -0,0 +1,37 @@ +# M16-GAP-00244: operator:armature.hide LOCAL_EXACT slice + +- task: M16-GAP-00244 +- parent: M16-GAP-00243 +- status: in_progress +- gap: operator:armature.hide +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.hide data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00244-operator-armature.hide.blend` +- Generator: `tools/web/generated/M16-GAP-00244.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00244.py -- tests/files/web/generated/M16-GAP-00244-operator-armature.hide.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00244 +node tools/web/check-generated-gap.mjs --task M16-GAP-00244 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00244/` +- Status: `docs/status/M16-GAP-00244.md` +- Manifest: `tests/golden/M16-GAP-00244/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00244 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00245.md b/docs/tasks/M16-GAP-00245.md new file mode 100644 index 00000000..da067cd2 --- /dev/null +++ b/docs/tasks/M16-GAP-00245.md @@ -0,0 +1,37 @@ +# M16-GAP-00245: operator:armature.move_to_collection LOCAL_EXACT slice + +- task: M16-GAP-00245 +- parent: M16-GAP-00244 +- status: in_progress +- gap: operator:armature.move_to_collection +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.move_to_collection data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00245-operator-armature.move_to_collection.blend` +- Generator: `tools/web/generated/M16-GAP-00245.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00245.py -- tests/files/web/generated/M16-GAP-00245-operator-armature.move_to_collection.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00245 +node tools/web/check-generated-gap.mjs --task M16-GAP-00245 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00245/` +- Status: `docs/status/M16-GAP-00245.md` +- Manifest: `tests/golden/M16-GAP-00245/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00245 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00246.md b/docs/tasks/M16-GAP-00246.md new file mode 100644 index 00000000..39534d82 --- /dev/null +++ b/docs/tasks/M16-GAP-00246.md @@ -0,0 +1,37 @@ +# M16-GAP-00246: operator:armature.parent_clear LOCAL_EXACT slice + +- task: M16-GAP-00246 +- parent: M16-GAP-00245 +- status: in_progress +- gap: operator:armature.parent_clear +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.parent_clear data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00246-operator-armature.parent_clear.blend` +- Generator: `tools/web/generated/M16-GAP-00246.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00246.py -- tests/files/web/generated/M16-GAP-00246-operator-armature.parent_clear.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00246 +node tools/web/check-generated-gap.mjs --task M16-GAP-00246 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00246/` +- Status: `docs/status/M16-GAP-00246.md` +- Manifest: `tests/golden/M16-GAP-00246/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00246 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00247.md b/docs/tasks/M16-GAP-00247.md new file mode 100644 index 00000000..903a47dd --- /dev/null +++ b/docs/tasks/M16-GAP-00247.md @@ -0,0 +1,37 @@ +# M16-GAP-00247: operator:armature.parent_set LOCAL_EXACT slice + +- task: M16-GAP-00247 +- parent: M16-GAP-00246 +- status: in_progress +- gap: operator:armature.parent_set +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.parent_set data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00247-operator-armature.parent_set.blend` +- Generator: `tools/web/generated/M16-GAP-00247.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00247.py -- tests/files/web/generated/M16-GAP-00247-operator-armature.parent_set.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00247 +node tools/web/check-generated-gap.mjs --task M16-GAP-00247 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00247/` +- Status: `docs/status/M16-GAP-00247.md` +- Manifest: `tests/golden/M16-GAP-00247/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00247 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00248.md b/docs/tasks/M16-GAP-00248.md new file mode 100644 index 00000000..bdfa2b0a --- /dev/null +++ b/docs/tasks/M16-GAP-00248.md @@ -0,0 +1,37 @@ +# M16-GAP-00248: operator:armature.reveal LOCAL_EXACT slice + +- task: M16-GAP-00248 +- parent: M16-GAP-00247 +- status: in_progress +- gap: operator:armature.reveal +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.reveal data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00248-operator-armature.reveal.blend` +- Generator: `tools/web/generated/M16-GAP-00248.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00248.py -- tests/files/web/generated/M16-GAP-00248-operator-armature.reveal.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00248 +node tools/web/check-generated-gap.mjs --task M16-GAP-00248 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00248/` +- Status: `docs/status/M16-GAP-00248.md` +- Manifest: `tests/golden/M16-GAP-00248/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00248 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00249.md b/docs/tasks/M16-GAP-00249.md new file mode 100644 index 00000000..f937008f --- /dev/null +++ b/docs/tasks/M16-GAP-00249.md @@ -0,0 +1,37 @@ +# M16-GAP-00249: operator:armature.roll_clear LOCAL_EXACT slice + +- task: M16-GAP-00249 +- parent: M16-GAP-00248 +- status: in_progress +- gap: operator:armature.roll_clear +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.roll_clear data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00249-operator-armature.roll_clear.blend` +- Generator: `tools/web/generated/M16-GAP-00249.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00249.py -- tests/files/web/generated/M16-GAP-00249-operator-armature.roll_clear.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00249 +node tools/web/check-generated-gap.mjs --task M16-GAP-00249 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00249/` +- Status: `docs/status/M16-GAP-00249.md` +- Manifest: `tests/golden/M16-GAP-00249/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00249 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00250.md b/docs/tasks/M16-GAP-00250.md new file mode 100644 index 00000000..5d935b34 --- /dev/null +++ b/docs/tasks/M16-GAP-00250.md @@ -0,0 +1,37 @@ +# M16-GAP-00250: operator:armature.select_all LOCAL_EXACT slice + +- task: M16-GAP-00250 +- parent: M16-GAP-00249 +- status: in_progress +- gap: operator:armature.select_all +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.select_all data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00250-operator-armature.select_all.blend` +- Generator: `tools/web/generated/M16-GAP-00250.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00250.py -- tests/files/web/generated/M16-GAP-00250-operator-armature.select_all.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00250 +node tools/web/check-generated-gap.mjs --task M16-GAP-00250 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00250/` +- Status: `docs/status/M16-GAP-00250.md` +- Manifest: `tests/golden/M16-GAP-00250/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00250 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00251.md b/docs/tasks/M16-GAP-00251.md new file mode 100644 index 00000000..e4510cf9 --- /dev/null +++ b/docs/tasks/M16-GAP-00251.md @@ -0,0 +1,37 @@ +# M16-GAP-00251: operator:armature.select_hierarchy LOCAL_EXACT slice + +- task: M16-GAP-00251 +- parent: M16-GAP-00250 +- status: in_progress +- gap: operator:armature.select_hierarchy +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.select_hierarchy data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00251-operator-armature.select_hierarchy.blend` +- Generator: `tools/web/generated/M16-GAP-00251.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00251.py -- tests/files/web/generated/M16-GAP-00251-operator-armature.select_hierarchy.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00251 +node tools/web/check-generated-gap.mjs --task M16-GAP-00251 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00251/` +- Status: `docs/status/M16-GAP-00251.md` +- Manifest: `tests/golden/M16-GAP-00251/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00251 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00252.md b/docs/tasks/M16-GAP-00252.md new file mode 100644 index 00000000..2ff45ed0 --- /dev/null +++ b/docs/tasks/M16-GAP-00252.md @@ -0,0 +1,37 @@ +# M16-GAP-00252: operator:armature.select_less LOCAL_EXACT slice + +- task: M16-GAP-00252 +- parent: M16-GAP-00251 +- status: in_progress +- gap: operator:armature.select_less +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.select_less data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00252-operator-armature.select_less.blend` +- Generator: `tools/web/generated/M16-GAP-00252.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00252.py -- tests/files/web/generated/M16-GAP-00252-operator-armature.select_less.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00252 +node tools/web/check-generated-gap.mjs --task M16-GAP-00252 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00252/` +- Status: `docs/status/M16-GAP-00252.md` +- Manifest: `tests/golden/M16-GAP-00252/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00252 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00253.md b/docs/tasks/M16-GAP-00253.md new file mode 100644 index 00000000..0d22cd85 --- /dev/null +++ b/docs/tasks/M16-GAP-00253.md @@ -0,0 +1,37 @@ +# M16-GAP-00253: operator:armature.select_linked LOCAL_EXACT slice + +- task: M16-GAP-00253 +- parent: M16-GAP-00252 +- status: in_progress +- gap: operator:armature.select_linked +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.select_linked data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00253-operator-armature.select_linked.blend` +- Generator: `tools/web/generated/M16-GAP-00253.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00253.py -- tests/files/web/generated/M16-GAP-00253-operator-armature.select_linked.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00253 +node tools/web/check-generated-gap.mjs --task M16-GAP-00253 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00253/` +- Status: `docs/status/M16-GAP-00253.md` +- Manifest: `tests/golden/M16-GAP-00253/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00253 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00254.md b/docs/tasks/M16-GAP-00254.md new file mode 100644 index 00000000..d0be96e6 --- /dev/null +++ b/docs/tasks/M16-GAP-00254.md @@ -0,0 +1,37 @@ +# M16-GAP-00254: operator:armature.select_linked_pick LOCAL_EXACT slice + +- task: M16-GAP-00254 +- parent: M16-GAP-00253 +- status: in_progress +- gap: operator:armature.select_linked_pick +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.select_linked_pick data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00254-operator-armature.select_linked_pick.blend` +- Generator: `tools/web/generated/M16-GAP-00254.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00254.py -- tests/files/web/generated/M16-GAP-00254-operator-armature.select_linked_pick.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00254 +node tools/web/check-generated-gap.mjs --task M16-GAP-00254 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00254/` +- Status: `docs/status/M16-GAP-00254.md` +- Manifest: `tests/golden/M16-GAP-00254/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00254 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00255.md b/docs/tasks/M16-GAP-00255.md new file mode 100644 index 00000000..93433ad7 --- /dev/null +++ b/docs/tasks/M16-GAP-00255.md @@ -0,0 +1,37 @@ +# M16-GAP-00255: operator:armature.select_mirror LOCAL_EXACT slice + +- task: M16-GAP-00255 +- parent: M16-GAP-00254 +- status: in_progress +- gap: operator:armature.select_mirror +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.select_mirror data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00255-operator-armature.select_mirror.blend` +- Generator: `tools/web/generated/M16-GAP-00255.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00255.py -- tests/files/web/generated/M16-GAP-00255-operator-armature.select_mirror.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00255 +node tools/web/check-generated-gap.mjs --task M16-GAP-00255 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00255/` +- Status: `docs/status/M16-GAP-00255.md` +- Manifest: `tests/golden/M16-GAP-00255/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00255 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00256.md b/docs/tasks/M16-GAP-00256.md new file mode 100644 index 00000000..68201b00 --- /dev/null +++ b/docs/tasks/M16-GAP-00256.md @@ -0,0 +1,37 @@ +# M16-GAP-00256: operator:armature.select_more LOCAL_EXACT slice + +- task: M16-GAP-00256 +- parent: M16-GAP-00255 +- status: in_progress +- gap: operator:armature.select_more +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.select_more data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00256-operator-armature.select_more.blend` +- Generator: `tools/web/generated/M16-GAP-00256.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00256.py -- tests/files/web/generated/M16-GAP-00256-operator-armature.select_more.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00256 +node tools/web/check-generated-gap.mjs --task M16-GAP-00256 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00256/` +- Status: `docs/status/M16-GAP-00256.md` +- Manifest: `tests/golden/M16-GAP-00256/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00256 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00257.md b/docs/tasks/M16-GAP-00257.md new file mode 100644 index 00000000..4ae0b457 --- /dev/null +++ b/docs/tasks/M16-GAP-00257.md @@ -0,0 +1,37 @@ +# M16-GAP-00257: operator:armature.select_similar LOCAL_EXACT slice + +- task: M16-GAP-00257 +- parent: M16-GAP-00256 +- status: in_progress +- gap: operator:armature.select_similar +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.select_similar data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00257-operator-armature.select_similar.blend` +- Generator: `tools/web/generated/M16-GAP-00257.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00257.py -- tests/files/web/generated/M16-GAP-00257-operator-armature.select_similar.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00257 +node tools/web/check-generated-gap.mjs --task M16-GAP-00257 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00257/` +- Status: `docs/status/M16-GAP-00257.md` +- Manifest: `tests/golden/M16-GAP-00257/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00257 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00258.md b/docs/tasks/M16-GAP-00258.md new file mode 100644 index 00000000..861521d4 --- /dev/null +++ b/docs/tasks/M16-GAP-00258.md @@ -0,0 +1,37 @@ +# M16-GAP-00258: operator:armature.separate LOCAL_EXACT slice + +- task: M16-GAP-00258 +- parent: M16-GAP-00257 +- status: in_progress +- gap: operator:armature.separate +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.separate data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00258-operator-armature.separate.blend` +- Generator: `tools/web/generated/M16-GAP-00258.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00258.py -- tests/files/web/generated/M16-GAP-00258-operator-armature.separate.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00258 +node tools/web/check-generated-gap.mjs --task M16-GAP-00258 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00258/` +- Status: `docs/status/M16-GAP-00258.md` +- Manifest: `tests/golden/M16-GAP-00258/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00258 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00259.md b/docs/tasks/M16-GAP-00259.md new file mode 100644 index 00000000..76e54daf --- /dev/null +++ b/docs/tasks/M16-GAP-00259.md @@ -0,0 +1,37 @@ +# M16-GAP-00259: operator:armature.shortest_path_pick LOCAL_EXACT slice + +- task: M16-GAP-00259 +- parent: M16-GAP-00258 +- status: in_progress +- gap: operator:armature.shortest_path_pick +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.shortest_path_pick data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00259-operator-armature.shortest_path_pick.blend` +- Generator: `tools/web/generated/M16-GAP-00259.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00259.py -- tests/files/web/generated/M16-GAP-00259-operator-armature.shortest_path_pick.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00259 +node tools/web/check-generated-gap.mjs --task M16-GAP-00259 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00259/` +- Status: `docs/status/M16-GAP-00259.md` +- Manifest: `tests/golden/M16-GAP-00259/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00259 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00260.md b/docs/tasks/M16-GAP-00260.md new file mode 100644 index 00000000..36cf44c5 --- /dev/null +++ b/docs/tasks/M16-GAP-00260.md @@ -0,0 +1,37 @@ +# M16-GAP-00260: operator:armature.split LOCAL_EXACT slice + +- task: M16-GAP-00260 +- parent: M16-GAP-00259 +- status: in_progress +- gap: operator:armature.split +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.split data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00260-operator-armature.split.blend` +- Generator: `tools/web/generated/M16-GAP-00260.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00260.py -- tests/files/web/generated/M16-GAP-00260-operator-armature.split.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00260 +node tools/web/check-generated-gap.mjs --task M16-GAP-00260 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00260/` +- Status: `docs/status/M16-GAP-00260.md` +- Manifest: `tests/golden/M16-GAP-00260/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00260 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00261.md b/docs/tasks/M16-GAP-00261.md new file mode 100644 index 00000000..ca0a307d --- /dev/null +++ b/docs/tasks/M16-GAP-00261.md @@ -0,0 +1,37 @@ +# M16-GAP-00261: operator:armature.subdivide LOCAL_EXACT slice + +- task: M16-GAP-00261 +- parent: M16-GAP-00260 +- status: in_progress +- gap: operator:armature.subdivide +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.subdivide data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00261-operator-armature.subdivide.blend` +- Generator: `tools/web/generated/M16-GAP-00261.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00261.py -- tests/files/web/generated/M16-GAP-00261-operator-armature.subdivide.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00261 +node tools/web/check-generated-gap.mjs --task M16-GAP-00261 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00261/` +- Status: `docs/status/M16-GAP-00261.md` +- Manifest: `tests/golden/M16-GAP-00261/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00261 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00262.md b/docs/tasks/M16-GAP-00262.md new file mode 100644 index 00000000..bd81191f --- /dev/null +++ b/docs/tasks/M16-GAP-00262.md @@ -0,0 +1,37 @@ +# M16-GAP-00262: operator:armature.switch_direction LOCAL_EXACT slice + +- task: M16-GAP-00262 +- parent: M16-GAP-00261 +- status: in_progress +- gap: operator:armature.switch_direction +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.switch_direction data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00262-operator-armature.switch_direction.blend` +- Generator: `tools/web/generated/M16-GAP-00262.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00262.py -- tests/files/web/generated/M16-GAP-00262-operator-armature.switch_direction.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00262 +node tools/web/check-generated-gap.mjs --task M16-GAP-00262 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00262/` +- Status: `docs/status/M16-GAP-00262.md` +- Manifest: `tests/golden/M16-GAP-00262/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00262 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00263.md b/docs/tasks/M16-GAP-00263.md new file mode 100644 index 00000000..0f77db0d --- /dev/null +++ b/docs/tasks/M16-GAP-00263.md @@ -0,0 +1,37 @@ +# M16-GAP-00263: operator:armature.symmetrize LOCAL_EXACT slice + +- task: M16-GAP-00263 +- parent: M16-GAP-00262 +- status: in_progress +- gap: operator:armature.symmetrize +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:armature.symmetrize data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00263-operator-armature.symmetrize.blend` +- Generator: `tools/web/generated/M16-GAP-00263.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00263.py -- tests/files/web/generated/M16-GAP-00263-operator-armature.symmetrize.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00263 +node tools/web/check-generated-gap.mjs --task M16-GAP-00263 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00263/` +- Status: `docs/status/M16-GAP-00263.md` +- Manifest: `tests/golden/M16-GAP-00263/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00263 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/docs/tasks/M16-GAP-00264.md b/docs/tasks/M16-GAP-00264.md new file mode 100644 index 00000000..47a26a4f --- /dev/null +++ b/docs/tasks/M16-GAP-00264.md @@ -0,0 +1,37 @@ +# M16-GAP-00264: operator:asset.asset_download LOCAL_EXACT slice + +- task: M16-GAP-00264 +- parent: M16-GAP-00263 +- status: in_progress +- gap: operator:asset.asset_download +- ownerFamily: OPERATOR +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Make the same minimal fixture produce observable operator:asset.asset_download data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers. + +## 输入与范围 + +- Fixture: `tests/files/web/generated/M16-GAP-00264-operator-asset.asset_download.blend` +- Generator: `tools/web/generated/M16-GAP-00264.py` +- Production: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Checker: `tools/web/check-generated-gap.mjs` +- Do: field read, desktop/WASM comparison, save/reopen, structured report. +- Do not: other gaps, Firefox/WebKit, or full editor behavior. + +## 验收 + +build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00264.py -- tests/files/web/generated/M16-GAP-00264-operator-asset.asset_download.blend +npm --prefix web run test:generated-gap -- --task M16-GAP-00264 +node tools/web/check-generated-gap.mjs --task M16-GAP-00264 + +Malformed/unsupported, cancellation, duplicate, over-budget, or hash-drift cases must keep in_progress; they must not change Main revision or advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/M16-GAP-00264/` +- Status: `docs/status/M16-GAP-00264.md` +- Manifest: `tests/golden/M16-GAP-00264/manifest.json` +- Handoff: `node tools/web/check-task-context.mjs --task M16-GAP-00264 --write` +- Rollback: remove this task production entry, fixture, tests, reports, manifest, status, and context; restore the parent as queue tail without rewriting parent evidence. diff --git a/nextTask.md b/nextTask.md index 4a95c283..118367d6 100644 --- a/nextTask.md +++ b/nextTask.md @@ -4,37 +4,45 @@ This file is the bounded continuation entrypoint for the Blender Web execution queue. It is a procedure, not a second task pointer. The only authoritative pointer is `docs/EXECUTION_QUEUE.md` plus the parent manifest named there. +The phrase below starts continuous mode. Continuous mode is a loop of bounded +task iterations: one task is completed and handed off at a time, then the next +iteration starts from a fresh compact context without waiting for another user +message. The loop stops only at an explicit stop condition described below. + ## Copyable Resume Prompt -Use the following prompt in a fresh request when continuous execution is -needed. It deliberately names the bounded one-task-per-request contract so a -long chain of tasks does not become one oversized context or remote compact -payload: +Use the following prompt when continuous execution is needed. It deliberately +keeps every task iteration bounded while allowing successful handoffs to proceed +automatically: ```text 按 nextTask.md 接续执行。 Treat this as an execution command, not a request for a plan or status report. -Read docs/EXECUTION_QUEUE.md, run print-task-context, then run -check-task-context before editing. Read only the current task card, parent -manifest/status, and the focused files named by the task context. Do not open -the full next-task-plan.json, all status logs, or historical project plans. +Enter CONTINUOUS mode and repeat the following bounded iteration until a stop +condition is reached: -Complete exactly one current task end to end: implement the scoped behavior, -run the focused desktop/npm/direct checks, verify save/reopen and the negative -case, write reports/status/manifest/task-context with SHA-256 values, then run -governance checks and git diff --check. Advance the queue only after every -exit criterion and hash check passes, using repository generators for the -task index/catalog/card. On any failure or hash drift, keep the task -in_progress/blocked and do not advance nextTask. +1. Read docs/EXECUTION_QUEUE.md, run print-task-context, then run + check-task-context before editing. +2. Read only the current task card, parent manifest/status, and the focused + files named by the task context. Do not open the full next-task-plan.json, + all status logs, or historical project plans. +3. Complete exactly the current task: implement the scoped behavior, run the + focused desktop/npm/direct checks, verify save/reopen and the negative case, + write reports/status/manifest/task-context with SHA-256 values, then run + governance checks and git diff --check. +4. Advance the queue only after every exit criterion and hash check passes, + using repository generators for the task index/catalog/card. +5. After a successful handoff, discard the previous task transcript and begin + the next iteration from a fresh print-task-context package. Do not wait for + another user message and do not carry prior task files into the next + iteration except through the new parent manifest and status summary. -Keep tool output and context bounded. Do not paste long logs or carry the -previous task transcript into the next request. After handoff, the next -invocation of this same prompt starts from a fresh print-task-context package. -This request has a hard stop after this one task: do not inspect, implement, or -start the next task in the same request, even when the current task finishes -early. End with only a compact checkpoint summary (task, state, nextTask, -command exit codes, and artifact paths/hashes). +Keep tool output and context bounded. On any failure or hash drift, keep the +current task `in_progress`/`blocked`, do not advance `nextTask`, and stop the +loop. End only when a stop condition is reached, with a compact summary of all +tasks completed in this run (task, state, nextTask, command exit codes, and +artifact paths/hashes). For stream-disconnect or remote-compact errors, stop the active request and use the recovery procedure below in a new request. Do not paste the failed transcript, invoke another compact operation, or blindly repeat a state- @@ -62,13 +70,14 @@ review, or diagnosis do not activate this procedure. 2. Finish or safely checkpoint that one task. 3. Write its manifest/status/task-context handoff and generate the next task pointer through repository tools. -4. On the next invocation of this command, start immediately from that new - pointer and a fresh compact context package. +4. If the handoff is successful, immediately start the next iteration from the + new pointer and a fresh compact context package. No additional user message + is required. -There is no intentional idle step between a valid handoff and the next -invocation. This still means one task per execution turn/request: never run -multiple numbered tasks in one request and never carry the previous task's -full transcript, logs, or source context into the next request. +There is no intentional idle step between valid handoffs. Each iteration still +has exactly one numbered task and must not carry the previous task's full +transcript, logs, or source context. A continuous run may contain many such +iterations, but it must stop at the first failed gate or explicit stop request. ## Activation Contract @@ -87,17 +96,36 @@ previous conversation. ## Fresh-Context Boundary -Handle at most one task per execution turn/request. At the end of a task, the -machine handoff is the checkpoint; begin the next task from a fresh compact -context package instead of carrying the previous transcript, logs, or source -files forward. This keeps remote compact/reconnect payloads bounded while -preserving continuous execution across turns. +The boundary is per task iteration, not per user message. At the end of a task, +the machine handoff is the checkpoint; the next iteration must begin from a +fresh compact context package instead of carrying the previous transcript, +logs, or source files forward. This keeps remote compact/reconnect payloads +bounded while allowing a continuous run to advance through multiple tasks. The handoff is durable only after the manifest, status, task-context, artifact hashes, and governance checks agree. A task that fails, is cancelled, exceeds budget, lacks its environment, or has hash drift remains `in_progress` or `blocked`; the next invocation resumes that same task instead of advancing. +## Stop Conditions + +Continuous mode must stop immediately when any of these conditions occurs: + +- a focused command, exit criterion, governance check, or hash check fails; +- the queue, parent manifest, task card, task index, or `nextTask` pointer is + inconsistent; +- the environment is missing, the task is cancelled, or a context/size budget + would be exceeded; +- a stream disconnect, remote compact error, or other transport error makes the + result of a state-changing command unknown; +- the queue has no next task or reaches its declared closure gate; +- the user explicitly asks to stop or pause. + +On a stop, preserve the current checkpoint, do not start another task, and +report the exact task, state, failed gate or stop reason, and evidence paths. +Only a successful handoff starts another iteration. There is no retry loop for +an unknown or failed result. + For every task, run this exact order: 1. Read `docs/EXECUTION_QUEUE.md`. @@ -118,9 +146,9 @@ For every task, run this exact order: 7. Write the report, status, manifest, and task context. A failed command, missing environment, or hash drift keeps the task `in_progress`/`blocked`; never advance the queue in that state. -8. Re-run the governance checks and stop after reporting this task's checkpoint. - The next task is started only by a new request using this prompt and a fresh - context package. +8. Re-run the governance checks. If they pass, continue with the next + iteration from a fresh context package; do not start the next task if any + gate fails. The normal post-handoff checks are: @@ -168,7 +196,9 @@ The user does not need to repeat the failed command: the next invocation of the exact resume phrase performs the read-only recovery checks first and continues from the first missing handoff step. -The recovery request must not include the old transcript or full command logs: +The recovery request must not include the old transcript or full command logs. +It re-enters continuous mode only after the read-only checkpoint proves which +handoff step is missing: ```text 按 nextTask.md 接续执行。 @@ -177,7 +207,9 @@ The recovery request must not include the old transcript or full command logs: node tools/web/print-task-context.mjs、node tools/web/check-task-context.mjs 和 git status --short;比较当前 task 的 manifest、status、task-context 与 artifact SHA-256,只从第一个缺失的交接步骤继续。不要重复任何未知结果的 -生成、构建、保存或队列写入命令;本请求仍只完成一个 task,完成后立即停止。 +生成、构建、保存或队列写入命令;恢复当前 task 后进入 CONTINUOUS mode, +仅在完整 handoff 成功时自动开始下一个 iteration;再次发生同类错误时 +立即停止并报告 checkpoint,不要继续重试。 ``` ## Current Handoff Snapshot diff --git a/test-results/.last-run.json b/test-results/.last-run.json new file mode 100644 index 00000000..e6c4a4c4 --- /dev/null +++ b/test-results/.last-run.json @@ -0,0 +1,6 @@ +{ + "status": "failed", + "failedTests": [ + "44d526552dd243783a40-2cb37a5217f2f6418146" + ] +} \ No newline at end of file diff --git a/test-results/web-tests-e2e-script-signa-c7cc3-lidates-source-hash-changes/error-context.md b/test-results/web-tests-e2e-script-signa-c7cc3-lidates-source-hash-changes/error-context.md new file mode 100644 index 00000000..95519c27 --- /dev/null +++ b/test-results/web-tests-e2e-script-signa-c7cc3-lidates-source-hash-changes/error-context.md @@ -0,0 +1,24 @@ +# Instructions + +- Following Playwright test failed. +- Explain why, be concise, respect Playwright best practices. +- Provide a snippet of code with the fix, if possible. + +# Test info + +- Name: web/tests/e2e/script-signature.spec.ts >> M13-02D verifies declared script content and invalidates source hash changes +- Location: web/tests/e2e/script-signature.spec.ts:3:1 + +# Error details + +``` +Error: browserType.launch: Executable doesn't exist at /home/mes123456/.cache/ms-playwright/chromium_headless_shell-1234/chrome-headless-shell-linux64/chrome-headless-shell +╔════════════════════════════════════════════════════════════╗ +║ Looks like Playwright was just installed or updated. ║ +║ Please run the following command to download new browsers: ║ +║ ║ +║ npx playwright install ║ +║ ║ +║ <3 Playwright Team ║ +╚════════════════════════════════════════════════════════════╝ +``` \ No newline at end of file diff --git a/tests/files/web/generated/M16-GAP-00076-modifier-LINEART.blend1 b/tests/files/web/generated/M16-GAP-00076-modifier-LINEART.blend1 new file mode 100644 index 00000000..40273a11 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00076-modifier-LINEART.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00088-modifier-PARTICLE_SYSTEM.blend1 b/tests/files/web/generated/M16-GAP-00088-modifier-PARTICLE_SYSTEM.blend1 new file mode 100644 index 00000000..ef963df2 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00088-modifier-PARTICLE_SYSTEM.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00115-operator-action.clickselect.blend1 b/tests/files/web/generated/M16-GAP-00115-operator-action.clickselect.blend1 new file mode 100644 index 00000000..46956dc3 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00115-operator-action.clickselect.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00123-operator-action.handle_type.blend1 b/tests/files/web/generated/M16-GAP-00123-operator-action.handle_type.blend1 new file mode 100644 index 00000000..3503830b Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00123-operator-action.handle_type.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00134-operator-action.select_box.blend1 b/tests/files/web/generated/M16-GAP-00134-operator-action.select_box.blend1 new file mode 100644 index 00000000..072e35b5 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00134-operator-action.select_box.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00136-operator-action.select_circle.blend1 b/tests/files/web/generated/M16-GAP-00136-operator-action.select_circle.blend1 new file mode 100644 index 00000000..f34a3ec2 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00136-operator-action.select_circle.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00145-operator-action.stash_and_create.blend1 b/tests/files/web/generated/M16-GAP-00145-operator-action.stash_and_create.blend1 new file mode 100644 index 00000000..285c027d Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00145-operator-action.stash_and_create.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00147-operator-action.view_all.blend1 b/tests/files/web/generated/M16-GAP-00147-operator-action.view_all.blend1 new file mode 100644 index 00000000..c298d3f2 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00147-operator-action.view_all.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00163-operator-anim.channels_rename.blend1 b/tests/files/web/generated/M16-GAP-00163-operator-anim.channels_rename.blend1 new file mode 100644 index 00000000..f19680f5 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00163-operator-anim.channels_rename.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00167-operator-anim.channels_setting_disable.blend1 b/tests/files/web/generated/M16-GAP-00167-operator-anim.channels_setting_disable.blend1 new file mode 100644 index 00000000..18a40bfa Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00167-operator-anim.channels_setting_disable.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00171-operator-anim.channels_view_selected.blend1 b/tests/files/web/generated/M16-GAP-00171-operator-anim.channels_view_selected.blend1 new file mode 100644 index 00000000..1983b9b7 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00171-operator-anim.channels_view_selected.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00173-operator-anim.copy_driver_button.blend1 b/tests/files/web/generated/M16-GAP-00173-operator-anim.copy_driver_button.blend1 new file mode 100644 index 00000000..7bffd812 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00173-operator-anim.copy_driver_button.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00174-operator-anim.driver_button_add.blend1 b/tests/files/web/generated/M16-GAP-00174-operator-anim.driver_button_add.blend1 new file mode 100644 index 00000000..c0e77fce Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00174-operator-anim.driver_button_add.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00175-operator-anim.driver_button_edit.blend b/tests/files/web/generated/M16-GAP-00175-operator-anim.driver_button_edit.blend new file mode 100644 index 00000000..4080d8ba Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00175-operator-anim.driver_button_edit.blend differ diff --git a/tests/files/web/generated/M16-GAP-00176-operator-anim.driver_button_remove.blend b/tests/files/web/generated/M16-GAP-00176-operator-anim.driver_button_remove.blend new file mode 100644 index 00000000..c3c4185a Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00176-operator-anim.driver_button_remove.blend differ diff --git a/tests/files/web/generated/M16-GAP-00177-operator-anim.end_frame_set.blend b/tests/files/web/generated/M16-GAP-00177-operator-anim.end_frame_set.blend new file mode 100644 index 00000000..19125a4c Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00177-operator-anim.end_frame_set.blend differ diff --git a/tests/files/web/generated/M16-GAP-00178-operator-anim.keyframe_clear_button.blend b/tests/files/web/generated/M16-GAP-00178-operator-anim.keyframe_clear_button.blend new file mode 100644 index 00000000..19121ec6 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00178-operator-anim.keyframe_clear_button.blend differ diff --git a/tests/files/web/generated/M16-GAP-00179-operator-anim.keyframe_clear_v3d.blend b/tests/files/web/generated/M16-GAP-00179-operator-anim.keyframe_clear_v3d.blend new file mode 100644 index 00000000..c9b95d11 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00179-operator-anim.keyframe_clear_v3d.blend differ diff --git a/tests/files/web/generated/M16-GAP-00179-operator-anim.keyframe_clear_v3d.blend1 b/tests/files/web/generated/M16-GAP-00179-operator-anim.keyframe_clear_v3d.blend1 new file mode 100644 index 00000000..21cfadb7 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00179-operator-anim.keyframe_clear_v3d.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00180-operator-anim.keyframe_clear_vse.blend b/tests/files/web/generated/M16-GAP-00180-operator-anim.keyframe_clear_vse.blend new file mode 100644 index 00000000..61bd3487 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00180-operator-anim.keyframe_clear_vse.blend differ diff --git a/tests/files/web/generated/M16-GAP-00180-operator-anim.keyframe_clear_vse.blend1 b/tests/files/web/generated/M16-GAP-00180-operator-anim.keyframe_clear_vse.blend1 new file mode 100644 index 00000000..0959a95d Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00180-operator-anim.keyframe_clear_vse.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00181-operator-anim.keyframe_delete.blend b/tests/files/web/generated/M16-GAP-00181-operator-anim.keyframe_delete.blend new file mode 100644 index 00000000..ef48213a Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00181-operator-anim.keyframe_delete.blend differ diff --git a/tests/files/web/generated/M16-GAP-00181-operator-anim.keyframe_delete.blend1 b/tests/files/web/generated/M16-GAP-00181-operator-anim.keyframe_delete.blend1 new file mode 100644 index 00000000..37dc7ccc Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00181-operator-anim.keyframe_delete.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00182-operator-anim.keyframe_delete_button.blend b/tests/files/web/generated/M16-GAP-00182-operator-anim.keyframe_delete_button.blend new file mode 100644 index 00000000..2c4d8a5d Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00182-operator-anim.keyframe_delete_button.blend differ diff --git a/tests/files/web/generated/M16-GAP-00182-operator-anim.keyframe_delete_button.blend1 b/tests/files/web/generated/M16-GAP-00182-operator-anim.keyframe_delete_button.blend1 new file mode 100644 index 00000000..a44e5f66 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00182-operator-anim.keyframe_delete_button.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00183-operator-anim.keyframe_delete_by_name.blend b/tests/files/web/generated/M16-GAP-00183-operator-anim.keyframe_delete_by_name.blend new file mode 100644 index 00000000..68362057 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00183-operator-anim.keyframe_delete_by_name.blend differ diff --git a/tests/files/web/generated/M16-GAP-00184-operator-anim.keyframe_delete_v3d.blend b/tests/files/web/generated/M16-GAP-00184-operator-anim.keyframe_delete_v3d.blend new file mode 100644 index 00000000..a4aa84f8 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00184-operator-anim.keyframe_delete_v3d.blend differ diff --git a/tests/files/web/generated/M16-GAP-00185-operator-anim.keyframe_delete_vse.blend b/tests/files/web/generated/M16-GAP-00185-operator-anim.keyframe_delete_vse.blend new file mode 100644 index 00000000..ef25561b Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00185-operator-anim.keyframe_delete_vse.blend differ diff --git a/tests/files/web/generated/M16-GAP-00186-operator-anim.keyframe_insert.blend b/tests/files/web/generated/M16-GAP-00186-operator-anim.keyframe_insert.blend new file mode 100644 index 00000000..12d053df Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00186-operator-anim.keyframe_insert.blend differ diff --git a/tests/files/web/generated/M16-GAP-00186-operator-anim.keyframe_insert.blend1 b/tests/files/web/generated/M16-GAP-00186-operator-anim.keyframe_insert.blend1 new file mode 100644 index 00000000..f10b9b8b Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00186-operator-anim.keyframe_insert.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00187-operator-anim.keyframe_insert_button.blend b/tests/files/web/generated/M16-GAP-00187-operator-anim.keyframe_insert_button.blend new file mode 100644 index 00000000..e3633be4 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00187-operator-anim.keyframe_insert_button.blend differ diff --git a/tests/files/web/generated/M16-GAP-00188-operator-anim.keyframe_insert_by_name.blend b/tests/files/web/generated/M16-GAP-00188-operator-anim.keyframe_insert_by_name.blend new file mode 100644 index 00000000..f946436c Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00188-operator-anim.keyframe_insert_by_name.blend differ diff --git a/tests/files/web/generated/M16-GAP-00189-operator-anim.keyframe_insert_menu.blend b/tests/files/web/generated/M16-GAP-00189-operator-anim.keyframe_insert_menu.blend new file mode 100644 index 00000000..6505391a Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00189-operator-anim.keyframe_insert_menu.blend differ diff --git a/tests/files/web/generated/M16-GAP-00190-operator-anim.keying_set_active_set.blend b/tests/files/web/generated/M16-GAP-00190-operator-anim.keying_set_active_set.blend new file mode 100644 index 00000000..d1298ab6 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00190-operator-anim.keying_set_active_set.blend differ diff --git a/tests/files/web/generated/M16-GAP-00191-operator-anim.keying_set_add.blend b/tests/files/web/generated/M16-GAP-00191-operator-anim.keying_set_add.blend new file mode 100644 index 00000000..cbe29403 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00191-operator-anim.keying_set_add.blend differ diff --git a/tests/files/web/generated/M16-GAP-00192-operator-anim.keying_set_export.blend b/tests/files/web/generated/M16-GAP-00192-operator-anim.keying_set_export.blend new file mode 100644 index 00000000..7c9f7740 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00192-operator-anim.keying_set_export.blend differ diff --git a/tests/files/web/generated/M16-GAP-00193-operator-anim.keying_set_path_add.blend b/tests/files/web/generated/M16-GAP-00193-operator-anim.keying_set_path_add.blend new file mode 100644 index 00000000..e0e9b84b Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00193-operator-anim.keying_set_path_add.blend differ diff --git a/tests/files/web/generated/M16-GAP-00193-operator-anim.keying_set_path_add.blend1 b/tests/files/web/generated/M16-GAP-00193-operator-anim.keying_set_path_add.blend1 new file mode 100644 index 00000000..142489f0 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00193-operator-anim.keying_set_path_add.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00194-operator-anim.keying_set_path_remove.blend b/tests/files/web/generated/M16-GAP-00194-operator-anim.keying_set_path_remove.blend new file mode 100644 index 00000000..8d5d5936 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00194-operator-anim.keying_set_path_remove.blend differ diff --git a/tests/files/web/generated/M16-GAP-00194-operator-anim.keying_set_path_remove.blend1 b/tests/files/web/generated/M16-GAP-00194-operator-anim.keying_set_path_remove.blend1 new file mode 100644 index 00000000..8b4cee95 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00194-operator-anim.keying_set_path_remove.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00195-operator-anim.keying_set_remove.blend b/tests/files/web/generated/M16-GAP-00195-operator-anim.keying_set_remove.blend new file mode 100644 index 00000000..aa55acba Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00195-operator-anim.keying_set_remove.blend differ diff --git a/tests/files/web/generated/M16-GAP-00195-operator-anim.keying_set_remove.blend1 b/tests/files/web/generated/M16-GAP-00195-operator-anim.keying_set_remove.blend1 new file mode 100644 index 00000000..7647bdd5 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00195-operator-anim.keying_set_remove.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00196-operator-anim.keyingset_button_add.blend b/tests/files/web/generated/M16-GAP-00196-operator-anim.keyingset_button_add.blend new file mode 100644 index 00000000..6e11756a Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00196-operator-anim.keyingset_button_add.blend differ diff --git a/tests/files/web/generated/M16-GAP-00196-operator-anim.keyingset_button_add.blend1 b/tests/files/web/generated/M16-GAP-00196-operator-anim.keyingset_button_add.blend1 new file mode 100644 index 00000000..4a88482f Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00196-operator-anim.keyingset_button_add.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00197-operator-anim.keyingset_button_remove.blend b/tests/files/web/generated/M16-GAP-00197-operator-anim.keyingset_button_remove.blend new file mode 100644 index 00000000..2759dc3b Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00197-operator-anim.keyingset_button_remove.blend differ diff --git a/tests/files/web/generated/M16-GAP-00197-operator-anim.keyingset_button_remove.blend1 b/tests/files/web/generated/M16-GAP-00197-operator-anim.keyingset_button_remove.blend1 new file mode 100644 index 00000000..e65ed01f Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00197-operator-anim.keyingset_button_remove.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00198-operator-anim.merge_animation.blend b/tests/files/web/generated/M16-GAP-00198-operator-anim.merge_animation.blend new file mode 100644 index 00000000..1c8e807a Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00198-operator-anim.merge_animation.blend differ diff --git a/tests/files/web/generated/M16-GAP-00199-operator-anim.paste_driver_button.blend b/tests/files/web/generated/M16-GAP-00199-operator-anim.paste_driver_button.blend new file mode 100644 index 00000000..db5f0c9f Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00199-operator-anim.paste_driver_button.blend differ diff --git a/tests/files/web/generated/M16-GAP-00199-operator-anim.paste_driver_button.blend1 b/tests/files/web/generated/M16-GAP-00199-operator-anim.paste_driver_button.blend1 new file mode 100644 index 00000000..1e5084b1 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00199-operator-anim.paste_driver_button.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00200-operator-anim.previewrange_clear.blend b/tests/files/web/generated/M16-GAP-00200-operator-anim.previewrange_clear.blend new file mode 100644 index 00000000..bf765370 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00200-operator-anim.previewrange_clear.blend differ diff --git a/tests/files/web/generated/M16-GAP-00200-operator-anim.previewrange_clear.blend1 b/tests/files/web/generated/M16-GAP-00200-operator-anim.previewrange_clear.blend1 new file mode 100644 index 00000000..e8ba1994 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00200-operator-anim.previewrange_clear.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00201-operator-anim.previewrange_set.blend b/tests/files/web/generated/M16-GAP-00201-operator-anim.previewrange_set.blend new file mode 100644 index 00000000..0add1053 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00201-operator-anim.previewrange_set.blend differ diff --git a/tests/files/web/generated/M16-GAP-00202-operator-anim.replace_action.blend b/tests/files/web/generated/M16-GAP-00202-operator-anim.replace_action.blend new file mode 100644 index 00000000..48a2a783 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00202-operator-anim.replace_action.blend differ diff --git a/tests/files/web/generated/M16-GAP-00202-operator-anim.replace_action.blend1 b/tests/files/web/generated/M16-GAP-00202-operator-anim.replace_action.blend1 new file mode 100644 index 00000000..2fe09d39 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00202-operator-anim.replace_action.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00203-operator-anim.replace_action_new.blend b/tests/files/web/generated/M16-GAP-00203-operator-anim.replace_action_new.blend new file mode 100644 index 00000000..780fe4c7 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00203-operator-anim.replace_action_new.blend differ diff --git a/tests/files/web/generated/M16-GAP-00203-operator-anim.replace_action_new.blend1 b/tests/files/web/generated/M16-GAP-00203-operator-anim.replace_action_new.blend1 new file mode 100644 index 00000000..b062f6e6 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00203-operator-anim.replace_action_new.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00204-operator-anim.scene_range_frame.blend b/tests/files/web/generated/M16-GAP-00204-operator-anim.scene_range_frame.blend new file mode 100644 index 00000000..b3a3060d Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00204-operator-anim.scene_range_frame.blend differ diff --git a/tests/files/web/generated/M16-GAP-00205-operator-anim.separate_slots.blend b/tests/files/web/generated/M16-GAP-00205-operator-anim.separate_slots.blend new file mode 100644 index 00000000..354e6a0a Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00205-operator-anim.separate_slots.blend differ diff --git a/tests/files/web/generated/M16-GAP-00205-operator-anim.separate_slots.blend1 b/tests/files/web/generated/M16-GAP-00205-operator-anim.separate_slots.blend1 new file mode 100644 index 00000000..facb76d8 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00205-operator-anim.separate_slots.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00206-operator-anim.slot_channels_move_to_new_action.blend b/tests/files/web/generated/M16-GAP-00206-operator-anim.slot_channels_move_to_new_action.blend new file mode 100644 index 00000000..26267dbe Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00206-operator-anim.slot_channels_move_to_new_action.blend differ diff --git a/tests/files/web/generated/M16-GAP-00206-operator-anim.slot_channels_move_to_new_action.blend1 b/tests/files/web/generated/M16-GAP-00206-operator-anim.slot_channels_move_to_new_action.blend1 new file mode 100644 index 00000000..978707b0 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00206-operator-anim.slot_channels_move_to_new_action.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00207-operator-anim.slot_new_for_id.blend b/tests/files/web/generated/M16-GAP-00207-operator-anim.slot_new_for_id.blend new file mode 100644 index 00000000..4b676534 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00207-operator-anim.slot_new_for_id.blend differ diff --git a/tests/files/web/generated/M16-GAP-00207-operator-anim.slot_new_for_id.blend1 b/tests/files/web/generated/M16-GAP-00207-operator-anim.slot_new_for_id.blend1 new file mode 100644 index 00000000..1f26a3fc Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00207-operator-anim.slot_new_for_id.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00208-operator-anim.slot_unassign_from_constraint.blend b/tests/files/web/generated/M16-GAP-00208-operator-anim.slot_unassign_from_constraint.blend new file mode 100644 index 00000000..b84f9548 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00208-operator-anim.slot_unassign_from_constraint.blend differ diff --git a/tests/files/web/generated/M16-GAP-00208-operator-anim.slot_unassign_from_constraint.blend1 b/tests/files/web/generated/M16-GAP-00208-operator-anim.slot_unassign_from_constraint.blend1 new file mode 100644 index 00000000..cc7f53ee Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00208-operator-anim.slot_unassign_from_constraint.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00209-operator-anim.slot_unassign_from_id.blend b/tests/files/web/generated/M16-GAP-00209-operator-anim.slot_unassign_from_id.blend new file mode 100644 index 00000000..ec8648ed Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00209-operator-anim.slot_unassign_from_id.blend differ diff --git a/tests/files/web/generated/M16-GAP-00209-operator-anim.slot_unassign_from_id.blend1 b/tests/files/web/generated/M16-GAP-00209-operator-anim.slot_unassign_from_id.blend1 new file mode 100644 index 00000000..f184f945 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00209-operator-anim.slot_unassign_from_id.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00210-operator-anim.slot_unassign_from_nla_strip.blend b/tests/files/web/generated/M16-GAP-00210-operator-anim.slot_unassign_from_nla_strip.blend new file mode 100644 index 00000000..07c1392e Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00210-operator-anim.slot_unassign_from_nla_strip.blend differ diff --git a/tests/files/web/generated/M16-GAP-00210-operator-anim.slot_unassign_from_nla_strip.blend1 b/tests/files/web/generated/M16-GAP-00210-operator-anim.slot_unassign_from_nla_strip.blend1 new file mode 100644 index 00000000..cfc191fa Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00210-operator-anim.slot_unassign_from_nla_strip.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00211-operator-anim.start_frame_set.blend b/tests/files/web/generated/M16-GAP-00211-operator-anim.start_frame_set.blend new file mode 100644 index 00000000..bcb7879f Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00211-operator-anim.start_frame_set.blend differ diff --git a/tests/files/web/generated/M16-GAP-00212-operator-anim.update_animated_transform_constraints.blend b/tests/files/web/generated/M16-GAP-00212-operator-anim.update_animated_transform_constraints.blend new file mode 100644 index 00000000..e4e01f44 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00212-operator-anim.update_animated_transform_constraints.blend differ diff --git a/tests/files/web/generated/M16-GAP-00212-operator-anim.update_animated_transform_constraints.blend1 b/tests/files/web/generated/M16-GAP-00212-operator-anim.update_animated_transform_constraints.blend1 new file mode 100644 index 00000000..0ebe1b2f Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00212-operator-anim.update_animated_transform_constraints.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00213-operator-anim.version_bone_hide_property.blend b/tests/files/web/generated/M16-GAP-00213-operator-anim.version_bone_hide_property.blend new file mode 100644 index 00000000..d823b08d Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00213-operator-anim.version_bone_hide_property.blend differ diff --git a/tests/files/web/generated/M16-GAP-00213-operator-anim.version_bone_hide_property.blend1 b/tests/files/web/generated/M16-GAP-00213-operator-anim.version_bone_hide_property.blend1 new file mode 100644 index 00000000..5f4a81f3 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00213-operator-anim.version_bone_hide_property.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00214-operator-anim.view_curve_in_graph_editor.blend b/tests/files/web/generated/M16-GAP-00214-operator-anim.view_curve_in_graph_editor.blend new file mode 100644 index 00000000..467c2921 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00214-operator-anim.view_curve_in_graph_editor.blend differ diff --git a/tests/files/web/generated/M16-GAP-00215-operator-armature.align.blend b/tests/files/web/generated/M16-GAP-00215-operator-armature.align.blend new file mode 100644 index 00000000..845ecf41 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00215-operator-armature.align.blend differ diff --git a/tests/files/web/generated/M16-GAP-00215-operator-armature.align.blend1 b/tests/files/web/generated/M16-GAP-00215-operator-armature.align.blend1 new file mode 100644 index 00000000..71919d03 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00215-operator-armature.align.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00216-operator-armature.assign_to_collection.blend b/tests/files/web/generated/M16-GAP-00216-operator-armature.assign_to_collection.blend new file mode 100644 index 00000000..6859255f Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00216-operator-armature.assign_to_collection.blend differ diff --git a/tests/files/web/generated/M16-GAP-00217-operator-armature.autoside_names.blend b/tests/files/web/generated/M16-GAP-00217-operator-armature.autoside_names.blend new file mode 100644 index 00000000..019e4a57 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00217-operator-armature.autoside_names.blend differ diff --git a/tests/files/web/generated/M16-GAP-00218-operator-armature.bone_primitive_add.blend b/tests/files/web/generated/M16-GAP-00218-operator-armature.bone_primitive_add.blend new file mode 100644 index 00000000..c71ab966 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00218-operator-armature.bone_primitive_add.blend differ diff --git a/tests/files/web/generated/M16-GAP-00219-operator-armature.calculate_roll.blend b/tests/files/web/generated/M16-GAP-00219-operator-armature.calculate_roll.blend new file mode 100644 index 00000000..52e694e3 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00219-operator-armature.calculate_roll.blend differ diff --git a/tests/files/web/generated/M16-GAP-00219-operator-armature.calculate_roll.blend1 b/tests/files/web/generated/M16-GAP-00219-operator-armature.calculate_roll.blend1 new file mode 100644 index 00000000..e6aff1fc Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00219-operator-armature.calculate_roll.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00220-operator-armature.click_extrude.blend b/tests/files/web/generated/M16-GAP-00220-operator-armature.click_extrude.blend new file mode 100644 index 00000000..b8e73747 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00220-operator-armature.click_extrude.blend differ diff --git a/tests/files/web/generated/M16-GAP-00220-operator-armature.click_extrude.blend1 b/tests/files/web/generated/M16-GAP-00220-operator-armature.click_extrude.blend1 new file mode 100644 index 00000000..3674109c Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00220-operator-armature.click_extrude.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00221-operator-armature.collection_add.blend b/tests/files/web/generated/M16-GAP-00221-operator-armature.collection_add.blend new file mode 100644 index 00000000..5808edb6 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00221-operator-armature.collection_add.blend differ diff --git a/tests/files/web/generated/M16-GAP-00222-operator-armature.collection_assign.blend b/tests/files/web/generated/M16-GAP-00222-operator-armature.collection_assign.blend new file mode 100644 index 00000000..e67e51e3 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00222-operator-armature.collection_assign.blend differ diff --git a/tests/files/web/generated/M16-GAP-00223-operator-armature.collection_create_and_assign.blend b/tests/files/web/generated/M16-GAP-00223-operator-armature.collection_create_and_assign.blend new file mode 100644 index 00000000..aea9454e Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00223-operator-armature.collection_create_and_assign.blend differ diff --git a/tests/files/web/generated/M16-GAP-00224-operator-armature.collection_deselect.blend b/tests/files/web/generated/M16-GAP-00224-operator-armature.collection_deselect.blend new file mode 100644 index 00000000..0f9ab6e2 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00224-operator-armature.collection_deselect.blend differ diff --git a/tests/files/web/generated/M16-GAP-00225-operator-armature.collection_move.blend b/tests/files/web/generated/M16-GAP-00225-operator-armature.collection_move.blend new file mode 100644 index 00000000..0f8527ab Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00225-operator-armature.collection_move.blend differ diff --git a/tests/files/web/generated/M16-GAP-00226-operator-armature.collection_remove.blend b/tests/files/web/generated/M16-GAP-00226-operator-armature.collection_remove.blend new file mode 100644 index 00000000..99ec1082 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00226-operator-armature.collection_remove.blend differ diff --git a/tests/files/web/generated/M16-GAP-00227-operator-armature.collection_remove_unused.blend b/tests/files/web/generated/M16-GAP-00227-operator-armature.collection_remove_unused.blend new file mode 100644 index 00000000..bcfdc85e Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00227-operator-armature.collection_remove_unused.blend differ diff --git a/tests/files/web/generated/M16-GAP-00228-operator-armature.collection_select.blend b/tests/files/web/generated/M16-GAP-00228-operator-armature.collection_select.blend new file mode 100644 index 00000000..e5bd35b5 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00228-operator-armature.collection_select.blend differ diff --git a/tests/files/web/generated/M16-GAP-00229-operator-armature.collection_show_all.blend b/tests/files/web/generated/M16-GAP-00229-operator-armature.collection_show_all.blend new file mode 100644 index 00000000..3fe2bd94 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00229-operator-armature.collection_show_all.blend differ diff --git a/tests/files/web/generated/M16-GAP-00230-operator-armature.collection_unassign.blend b/tests/files/web/generated/M16-GAP-00230-operator-armature.collection_unassign.blend new file mode 100644 index 00000000..48ae9eb0 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00230-operator-armature.collection_unassign.blend differ diff --git a/tests/files/web/generated/M16-GAP-00230-operator-armature.collection_unassign.blend1 b/tests/files/web/generated/M16-GAP-00230-operator-armature.collection_unassign.blend1 new file mode 100644 index 00000000..eaa92f63 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00230-operator-armature.collection_unassign.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00231-operator-armature.collection_unassign_named.blend b/tests/files/web/generated/M16-GAP-00231-operator-armature.collection_unassign_named.blend new file mode 100644 index 00000000..adf79b23 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00231-operator-armature.collection_unassign_named.blend differ diff --git a/tests/files/web/generated/M16-GAP-00232-operator-armature.collection_unsolo_all.blend b/tests/files/web/generated/M16-GAP-00232-operator-armature.collection_unsolo_all.blend new file mode 100644 index 00000000..7e3f6127 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00232-operator-armature.collection_unsolo_all.blend differ diff --git a/tests/files/web/generated/M16-GAP-00233-operator-armature.copy_bone_color_to_selected.blend b/tests/files/web/generated/M16-GAP-00233-operator-armature.copy_bone_color_to_selected.blend new file mode 100644 index 00000000..fc3c72e6 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00233-operator-armature.copy_bone_color_to_selected.blend differ diff --git a/tests/files/web/generated/M16-GAP-00234-operator-armature.delete.blend b/tests/files/web/generated/M16-GAP-00234-operator-armature.delete.blend new file mode 100644 index 00000000..b3670eef Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00234-operator-armature.delete.blend differ diff --git a/tests/files/web/generated/M16-GAP-00235-operator-armature.dissolve.blend b/tests/files/web/generated/M16-GAP-00235-operator-armature.dissolve.blend new file mode 100644 index 00000000..8bc86e93 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00235-operator-armature.dissolve.blend differ diff --git a/tests/files/web/generated/M16-GAP-00235-operator-armature.dissolve.blend1 b/tests/files/web/generated/M16-GAP-00235-operator-armature.dissolve.blend1 new file mode 100644 index 00000000..d63fe54d Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00235-operator-armature.dissolve.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00236-operator-armature.duplicate.blend b/tests/files/web/generated/M16-GAP-00236-operator-armature.duplicate.blend new file mode 100644 index 00000000..f642aedd Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00236-operator-armature.duplicate.blend differ diff --git a/tests/files/web/generated/M16-GAP-00237-operator-armature.duplicate_move.blend b/tests/files/web/generated/M16-GAP-00237-operator-armature.duplicate_move.blend new file mode 100644 index 00000000..fb5d8761 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00237-operator-armature.duplicate_move.blend differ diff --git a/tests/files/web/generated/M16-GAP-00238-operator-armature.duplicate_rename.blend b/tests/files/web/generated/M16-GAP-00238-operator-armature.duplicate_rename.blend new file mode 100644 index 00000000..be2824e6 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00238-operator-armature.duplicate_rename.blend differ diff --git a/tests/files/web/generated/M16-GAP-00239-operator-armature.extrude.blend b/tests/files/web/generated/M16-GAP-00239-operator-armature.extrude.blend new file mode 100644 index 00000000..72a85e1c Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00239-operator-armature.extrude.blend differ diff --git a/tests/files/web/generated/M16-GAP-00239-operator-armature.extrude.blend1 b/tests/files/web/generated/M16-GAP-00239-operator-armature.extrude.blend1 new file mode 100644 index 00000000..8ea4b381 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00239-operator-armature.extrude.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00240-operator-armature.extrude_forked.blend b/tests/files/web/generated/M16-GAP-00240-operator-armature.extrude_forked.blend new file mode 100644 index 00000000..4c071d74 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00240-operator-armature.extrude_forked.blend differ diff --git a/tests/files/web/generated/M16-GAP-00241-operator-armature.extrude_move.blend b/tests/files/web/generated/M16-GAP-00241-operator-armature.extrude_move.blend new file mode 100644 index 00000000..7c5bc8af Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00241-operator-armature.extrude_move.blend differ diff --git a/tests/files/web/generated/M16-GAP-00242-operator-armature.fill.blend b/tests/files/web/generated/M16-GAP-00242-operator-armature.fill.blend new file mode 100644 index 00000000..4da77f2a Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00242-operator-armature.fill.blend differ diff --git a/tests/files/web/generated/M16-GAP-00242-operator-armature.fill.blend1 b/tests/files/web/generated/M16-GAP-00242-operator-armature.fill.blend1 new file mode 100644 index 00000000..b202107a Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00242-operator-armature.fill.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00243-operator-armature.flip_names.blend b/tests/files/web/generated/M16-GAP-00243-operator-armature.flip_names.blend new file mode 100644 index 00000000..4de98739 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00243-operator-armature.flip_names.blend differ diff --git a/tests/files/web/generated/M16-GAP-00244-operator-armature.hide.blend b/tests/files/web/generated/M16-GAP-00244-operator-armature.hide.blend new file mode 100644 index 00000000..9c53321b Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00244-operator-armature.hide.blend differ diff --git a/tests/files/web/generated/M16-GAP-00245-operator-armature.move_to_collection.blend b/tests/files/web/generated/M16-GAP-00245-operator-armature.move_to_collection.blend new file mode 100644 index 00000000..5cf9bd40 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00245-operator-armature.move_to_collection.blend differ diff --git a/tests/files/web/generated/M16-GAP-00246-operator-armature.parent_clear.blend b/tests/files/web/generated/M16-GAP-00246-operator-armature.parent_clear.blend new file mode 100644 index 00000000..9fc3e36f Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00246-operator-armature.parent_clear.blend differ diff --git a/tests/files/web/generated/M16-GAP-00247-operator-armature.parent_set.blend b/tests/files/web/generated/M16-GAP-00247-operator-armature.parent_set.blend new file mode 100644 index 00000000..dd42ff50 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00247-operator-armature.parent_set.blend differ diff --git a/tests/files/web/generated/M16-GAP-00248-operator-armature.reveal.blend b/tests/files/web/generated/M16-GAP-00248-operator-armature.reveal.blend new file mode 100644 index 00000000..02bbbcce Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00248-operator-armature.reveal.blend differ diff --git a/tests/files/web/generated/M16-GAP-00248-operator-armature.reveal.blend1 b/tests/files/web/generated/M16-GAP-00248-operator-armature.reveal.blend1 new file mode 100644 index 00000000..78a56918 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00248-operator-armature.reveal.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00249-operator-armature.roll_clear.blend b/tests/files/web/generated/M16-GAP-00249-operator-armature.roll_clear.blend new file mode 100644 index 00000000..0b58ba3e Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00249-operator-armature.roll_clear.blend differ diff --git a/tests/files/web/generated/M16-GAP-00250-operator-armature.select_all.blend b/tests/files/web/generated/M16-GAP-00250-operator-armature.select_all.blend new file mode 100644 index 00000000..305f5cb2 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00250-operator-armature.select_all.blend differ diff --git a/tests/files/web/generated/M16-GAP-00251-operator-armature.select_hierarchy.blend b/tests/files/web/generated/M16-GAP-00251-operator-armature.select_hierarchy.blend new file mode 100644 index 00000000..dc45e04a Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00251-operator-armature.select_hierarchy.blend differ diff --git a/tests/files/web/generated/M16-GAP-00251-operator-armature.select_hierarchy.blend1 b/tests/files/web/generated/M16-GAP-00251-operator-armature.select_hierarchy.blend1 new file mode 100644 index 00000000..189c64c5 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00251-operator-armature.select_hierarchy.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00252-operator-armature.select_less.blend b/tests/files/web/generated/M16-GAP-00252-operator-armature.select_less.blend new file mode 100644 index 00000000..d744d088 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00252-operator-armature.select_less.blend differ diff --git a/tests/files/web/generated/M16-GAP-00252-operator-armature.select_less.blend1 b/tests/files/web/generated/M16-GAP-00252-operator-armature.select_less.blend1 new file mode 100644 index 00000000..54ca4f29 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00252-operator-armature.select_less.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00253-operator-armature.select_linked.blend b/tests/files/web/generated/M16-GAP-00253-operator-armature.select_linked.blend new file mode 100644 index 00000000..bc16d388 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00253-operator-armature.select_linked.blend differ diff --git a/tests/files/web/generated/M16-GAP-00254-operator-armature.select_linked_pick.blend b/tests/files/web/generated/M16-GAP-00254-operator-armature.select_linked_pick.blend new file mode 100644 index 00000000..d09ce8e1 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00254-operator-armature.select_linked_pick.blend differ diff --git a/tests/files/web/generated/M16-GAP-00255-operator-armature.select_mirror.blend b/tests/files/web/generated/M16-GAP-00255-operator-armature.select_mirror.blend new file mode 100644 index 00000000..0224c41e Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00255-operator-armature.select_mirror.blend differ diff --git a/tests/files/web/generated/M16-GAP-00256-operator-armature.select_more.blend b/tests/files/web/generated/M16-GAP-00256-operator-armature.select_more.blend new file mode 100644 index 00000000..2f992d50 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00256-operator-armature.select_more.blend differ diff --git a/tests/files/web/generated/M16-GAP-00256-operator-armature.select_more.blend1 b/tests/files/web/generated/M16-GAP-00256-operator-armature.select_more.blend1 new file mode 100644 index 00000000..7391a8eb Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00256-operator-armature.select_more.blend1 differ diff --git a/tests/files/web/generated/M16-GAP-00257-operator-armature.select_similar.blend b/tests/files/web/generated/M16-GAP-00257-operator-armature.select_similar.blend new file mode 100644 index 00000000..3ac45cd1 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00257-operator-armature.select_similar.blend differ diff --git a/tests/files/web/generated/M16-GAP-00258-operator-armature.separate.blend b/tests/files/web/generated/M16-GAP-00258-operator-armature.separate.blend new file mode 100644 index 00000000..5079075b Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00258-operator-armature.separate.blend differ diff --git a/tests/files/web/generated/M16-GAP-00259-operator-armature.shortest_path_pick.blend b/tests/files/web/generated/M16-GAP-00259-operator-armature.shortest_path_pick.blend new file mode 100644 index 00000000..63cb9c7b Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00259-operator-armature.shortest_path_pick.blend differ diff --git a/tests/files/web/generated/M16-GAP-00260-operator-armature.split.blend b/tests/files/web/generated/M16-GAP-00260-operator-armature.split.blend new file mode 100644 index 00000000..695205d8 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00260-operator-armature.split.blend differ diff --git a/tests/files/web/generated/M16-GAP-00261-operator-armature.subdivide.blend b/tests/files/web/generated/M16-GAP-00261-operator-armature.subdivide.blend new file mode 100644 index 00000000..11bc8e99 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00261-operator-armature.subdivide.blend differ diff --git a/tests/files/web/generated/M16-GAP-00262-operator-armature.switch_direction.blend b/tests/files/web/generated/M16-GAP-00262-operator-armature.switch_direction.blend new file mode 100644 index 00000000..cd188279 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00262-operator-armature.switch_direction.blend differ diff --git a/tests/files/web/generated/M16-GAP-00263-operator-armature.symmetrize.blend b/tests/files/web/generated/M16-GAP-00263-operator-armature.symmetrize.blend new file mode 100644 index 00000000..8867dbb9 Binary files /dev/null and b/tests/files/web/generated/M16-GAP-00263-operator-armature.symmetrize.blend differ diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-0rpa5rdo.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-0rpa5rdo.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-0yhnc_de.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-0yhnc_de.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-0z_5vzgn.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-0z_5vzgn.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-0zbw6jm6.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-0zbw6jm6.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-1abrkp2f.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-1abrkp2f.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-1fiqcznx.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-1fiqcznx.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-1sjvyfas.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-1sjvyfas.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-21a4hvd8.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-21a4hvd8.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-2cp6hy5c.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-2cp6hy5c.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-2fveikrq.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-2fveikrq.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-2g503vbc.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-2g503vbc.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-2ya1i3bm.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-2ya1i3bm.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-3n114sf0.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-3n114sf0.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-48770vga.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-48770vga.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-4eix94xy.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-4eix94xy.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-4p9hv12y.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-4p9hv12y.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-4x3zr27c.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-4x3zr27c.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-6afvtmik.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-6afvtmik.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-79ytfke4.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-79ytfke4.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-7mvqpee0.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-7mvqpee0.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-7xvyqamv.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-7xvyqamv.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-7zq374wl.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-7zq374wl.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-82zlfew6.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-82zlfew6.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-874fzrov.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-874fzrov.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-9o4p6yqw.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-9o4p6yqw.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-9sgwsyt8.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-9sgwsyt8.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-_audsnv7.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-_audsnv7.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-_hiw874n.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-_hiw874n.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-a0fejjnc.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-a0fejjnc.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-avhkywxl.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-avhkywxl.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-ay75o9ha.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-ay75o9ha.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-bhwqe4x8.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-bhwqe4x8.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-bit8ust1.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-bit8ust1.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-bt51rh5w.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-bt51rh5w.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-c_0270pu.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-c_0270pu.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-ddqty9ku.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-ddqty9ku.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-dm4ncpl_.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-dm4ncpl_.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-do9xtj4m.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-do9xtj4m.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-e9y8gfmw.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-e9y8gfmw.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-efdqis9t.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-efdqis9t.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-evsno1v5.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-evsno1v5.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-gplyxchy.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-gplyxchy.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-h1ltvrt3.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-h1ltvrt3.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-hv3ssory.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-hv3ssory.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-iijx1sb9.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-iijx1sb9.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-izl8w4uh.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-izl8w4uh.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-j11zimfl.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-j11zimfl.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-jp8_2ile.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-jp8_2ile.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-k6i3sgc6.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-k6i3sgc6.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-kzffen6n.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-kzffen6n.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-lfldbmiw.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-lfldbmiw.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-lpwvbw3r.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-lpwvbw3r.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-lsf0d_zm.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-lsf0d_zm.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-mb2_y58v.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-mb2_y58v.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-mlfypjwr.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-mlfypjwr.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-msqpx323.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-msqpx323.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-n1ahp6yn.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-n1ahp6yn.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-n262ku6l.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-n262ku6l.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-nf2r6ymn.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-nf2r6ymn.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-nh7g2ugr.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-nh7g2ugr.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-nojqy80b.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-nojqy80b.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-nvil1c6v.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-nvil1c6v.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-o2vw5t82.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-o2vw5t82.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-o5bange7.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-o5bange7.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-od8b71x3.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-od8b71x3.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-on7cyby6.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-on7cyby6.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-qa137ns3.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-qa137ns3.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-qg0kdo40.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-qg0kdo40.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-qh9tl525.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-qh9tl525.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-qivqrfnf.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-qivqrfnf.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-qw3hol_g.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-qw3hol_g.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-r0l0dr76.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-r0l0dr76.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-rtyjn726.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-rtyjn726.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-rwdol824.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-rwdol824.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-s5j67j7c.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-s5j67j7c.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-slym_y_e.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-slym_y_e.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-sqx72kf4.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-sqx72kf4.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-tsyevk9h.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-tsyevk9h.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-uc4ug64o.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-uc4ug64o.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-uf_6d9fl.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-uf_6d9fl.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-uh6vowk8.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-uh6vowk8.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-v8yhozb_.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-v8yhozb_.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-wi4rybpb.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-wi4rybpb.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-wjs60rjz.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-wjs60rjz.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-wq1umdwe.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-wq1umdwe.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-x941zenw.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-x941zenw.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-xa654k1v.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-xa654k1v.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-xq0j504x.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-xq0j504x.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-xtj2y9o7.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-xtj2y9o7.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-xx6d8tjq.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-xx6d8tjq.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-yg6ohkxz.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-yg6ohkxz.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-z1ji8hm4.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-z1ji8hm4.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-zfw4wr9j.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-zfw4wr9j.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-zhp5ycqa.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-zhp5ycqa.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/files/web/generated/m16-generic-modifier-reopen-zu3zrn_2.blend1 b/tests/files/web/generated/m16-generic-modifier-reopen-zu3zrn_2.blend1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/golden/M15-03A/completed-gap-tasks.json b/tests/golden/M15-03A/completed-gap-tasks.json index 6e961074..5d898801 100644 --- a/tests/golden/M15-03A/completed-gap-tasks.json +++ b/tests/golden/M15-03A/completed-gap-tasks.json @@ -172,5 +172,94 @@ "operator:anim.channels_view_selected", "operator:anim.clear_useless_actions", "operator:anim.copy_driver_button", - "operator:anim.driver_button_add" + "operator:anim.driver_button_add", + "operator:anim.driver_button_edit", + "operator:anim.driver_button_remove", + "operator:anim.end_frame_set", + "operator:anim.keyframe_clear_button", + "operator:anim.keyframe_clear_v3d", + "operator:anim.keyframe_clear_vse", + "operator:anim.keyframe_delete", + "operator:anim.keyframe_delete_button", + "operator:anim.keyframe_delete_by_name", + "operator:anim.keyframe_delete_v3d", + "operator:anim.keyframe_delete_vse", + "operator:anim.keyframe_insert", + "operator:anim.keyframe_insert_button", + "operator:anim.keyframe_insert_by_name", + "operator:anim.keyframe_insert_menu", + "operator:anim.keying_set_active_set", + "operator:anim.keying_set_add", + "operator:anim.keying_set_export", + "operator:anim.keying_set_path_add", + "operator:anim.keying_set_path_remove", + "operator:anim.keying_set_remove", + "operator:anim.keyingset_button_add", + "operator:anim.keyingset_button_remove", + "operator:anim.merge_animation", + "operator:anim.paste_driver_button", + "operator:anim.previewrange_clear", + "operator:anim.previewrange_set", + "operator:anim.replace_action", + "operator:anim.replace_action_new", + "operator:anim.scene_range_frame", + "operator:anim.separate_slots", + "operator:anim.slot_channels_move_to_new_action", + "operator:anim.slot_new_for_id", + "operator:anim.slot_unassign_from_constraint", + "operator:anim.slot_unassign_from_id", + "operator:anim.slot_unassign_from_nla_strip", + "operator:anim.start_frame_set", + "operator:anim.update_animated_transform_constraints", + "operator:anim.version_bone_hide_property", + "operator:anim.view_curve_in_graph_editor", + "operator:armature.align", + "operator:armature.assign_to_collection", + "operator:armature.autoside_names", + "operator:armature.bone_primitive_add", + "operator:armature.calculate_roll", + "operator:armature.click_extrude", + "operator:armature.collection_add", + "operator:armature.collection_assign", + "operator:armature.collection_create_and_assign", + "operator:armature.collection_deselect", + "operator:armature.collection_move", + "operator:armature.collection_remove", + "operator:armature.collection_remove_unused", + "operator:armature.collection_select", + "operator:armature.collection_show_all", + "operator:armature.collection_unassign", + "operator:armature.collection_unassign_named", + "operator:armature.collection_unsolo_all", + "operator:armature.copy_bone_color_to_selected", + "operator:armature.delete", + "operator:armature.dissolve", + "operator:armature.duplicate", + "operator:armature.duplicate_move", + "operator:armature.duplicate_rename", + "operator:armature.extrude", + "operator:armature.extrude_forked", + "operator:armature.extrude_move", + "operator:armature.fill", + "operator:armature.flip_names", + "operator:armature.hide", + "operator:armature.move_to_collection", + "operator:armature.parent_clear", + "operator:armature.parent_set", + "operator:armature.reveal", + "operator:armature.roll_clear", + "operator:armature.select_all", + "operator:armature.select_hierarchy", + "operator:armature.select_less", + "operator:armature.select_linked", + "operator:armature.select_linked_pick", + "operator:armature.select_mirror", + "operator:armature.select_more", + "operator:armature.select_similar", + "operator:armature.separate", + "operator:armature.shortest_path_pick", + "operator:armature.split", + "operator:armature.subdivide", + "operator:armature.switch_direction", + "operator:armature.symmetrize" ] diff --git a/tests/golden/M15-03A/manifest.json b/tests/golden/M15-03A/manifest.json index 44794d90..8f0e83cc 100644 --- a/tests/golden/M15-03A/manifest.json +++ b/tests/golden/M15-03A/manifest.json @@ -20,11 +20,11 @@ }, "plan": { "path": "tests/golden/M15-03A/next-task-plan.json", - "sha256": "a57fb3d61f40361920529f42f8664b24393ed1db7d220e14fc123aaafb62b8c7" + "sha256": "f10310d6530d8a9adfde0bc6bca35e4bfae7a05169028e1a8b36e374b059c8bb" }, "report": { "path": "tests/golden/M15-03A/next-task-plan-check-report.json", - "sha256": "f444269c15dc0ec8beb88590019add5b6d22afb91012a016e47dae31c87b0851" + "sha256": "1fede6a6bba0a935ffbdc1aa21ea7ca0addd741139b754c2a27d380eacf5c794" }, "package": { "path": "web/package.json", diff --git a/tests/golden/M15-03A/next-task-plan-check-report.json b/tests/golden/M15-03A/next-task-plan-check-report.json index a35c8fcc..cab2b3eb 100644 --- a/tests/golden/M15-03A/next-task-plan-check-report.json +++ b/tests/golden/M15-03A/next-task-plan-check-report.json @@ -5,8 +5,8 @@ "summary": { "taskCount": 6900, "active": 1, - "pending": 6725, - "completed": 174, + "pending": 6636, + "completed": 263, "blocked": 0, "byWave": { "M16": 2667, @@ -18,7 +18,7 @@ "M22": 19 } }, - "firstTask": "M16-GAP-00175", - "planSha256": "a57fb3d61f40361920529f42f8664b24393ed1db7d220e14fc123aaafb62b8c7", + "firstTask": "M16-GAP-00264", + "planSha256": "f10310d6530d8a9adfde0bc6bca35e4bfae7a05169028e1a8b36e374b059c8bb", "nextTask": "M15-03B" } diff --git a/tests/golden/M15-03A/next-task-plan.json b/tests/golden/M15-03A/next-task-plan.json index a5f5fe19..244a26e7 100644 --- a/tests/golden/M15-03A/next-task-plan.json +++ b/tests/golden/M15-03A/next-task-plan.json @@ -13,14 +13,14 @@ }, "completions": { "path": "tests/golden/M15-03A/completed-gap-tasks.json", - "sha256": "420e0de0b9d018752dfb355bf82a9936a7f2dd4e4b73c6147cd52c3d3e0e419b" + "sha256": "b927d84d995f64669fabdcb50019a7db895d9a6f4e004913122d32c2dfca01ac" } }, "summary": { "taskCount": 6900, "active": 1, - "pending": 6725, - "completed": 174, + "pending": 6636, + "completed": 263, "blocked": 0, "byWave": { "M16": 2667, @@ -4040,7 +4040,7 @@ "gapId": "operator:anim.driver_button_edit", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "active", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4063,7 +4063,7 @@ "gapId": "operator:anim.driver_button_remove", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4086,7 +4086,7 @@ "gapId": "operator:anim.end_frame_set", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4109,7 +4109,7 @@ "gapId": "operator:anim.keyframe_clear_button", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4132,7 +4132,7 @@ "gapId": "operator:anim.keyframe_clear_v3d", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4155,7 +4155,7 @@ "gapId": "operator:anim.keyframe_clear_vse", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4178,7 +4178,7 @@ "gapId": "operator:anim.keyframe_delete", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4201,7 +4201,7 @@ "gapId": "operator:anim.keyframe_delete_button", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4224,7 +4224,7 @@ "gapId": "operator:anim.keyframe_delete_by_name", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4247,7 +4247,7 @@ "gapId": "operator:anim.keyframe_delete_v3d", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4270,7 +4270,7 @@ "gapId": "operator:anim.keyframe_delete_vse", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4293,7 +4293,7 @@ "gapId": "operator:anim.keyframe_insert", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4316,7 +4316,7 @@ "gapId": "operator:anim.keyframe_insert_button", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4339,7 +4339,7 @@ "gapId": "operator:anim.keyframe_insert_by_name", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4362,7 +4362,7 @@ "gapId": "operator:anim.keyframe_insert_menu", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4385,7 +4385,7 @@ "gapId": "operator:anim.keying_set_active_set", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4408,7 +4408,7 @@ "gapId": "operator:anim.keying_set_add", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4431,7 +4431,7 @@ "gapId": "operator:anim.keying_set_export", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4454,7 +4454,7 @@ "gapId": "operator:anim.keying_set_path_add", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4477,7 +4477,7 @@ "gapId": "operator:anim.keying_set_path_remove", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4500,7 +4500,7 @@ "gapId": "operator:anim.keying_set_remove", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4523,7 +4523,7 @@ "gapId": "operator:anim.keyingset_button_add", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4546,7 +4546,7 @@ "gapId": "operator:anim.keyingset_button_remove", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4569,7 +4569,7 @@ "gapId": "operator:anim.merge_animation", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4592,7 +4592,7 @@ "gapId": "operator:anim.paste_driver_button", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4615,7 +4615,7 @@ "gapId": "operator:anim.previewrange_clear", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4638,7 +4638,7 @@ "gapId": "operator:anim.previewrange_set", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4661,7 +4661,7 @@ "gapId": "operator:anim.replace_action", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4684,7 +4684,7 @@ "gapId": "operator:anim.replace_action_new", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4707,7 +4707,7 @@ "gapId": "operator:anim.scene_range_frame", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4730,7 +4730,7 @@ "gapId": "operator:anim.separate_slots", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4753,7 +4753,7 @@ "gapId": "operator:anim.slot_channels_move_to_new_action", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4776,7 +4776,7 @@ "gapId": "operator:anim.slot_new_for_id", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4799,7 +4799,7 @@ "gapId": "operator:anim.slot_unassign_from_constraint", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4822,7 +4822,7 @@ "gapId": "operator:anim.slot_unassign_from_id", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4845,7 +4845,7 @@ "gapId": "operator:anim.slot_unassign_from_nla_strip", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4868,7 +4868,7 @@ "gapId": "operator:anim.start_frame_set", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4891,7 +4891,7 @@ "gapId": "operator:anim.update_animated_transform_constraints", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4914,7 +4914,7 @@ "gapId": "operator:anim.version_bone_hide_property", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4937,7 +4937,7 @@ "gapId": "operator:anim.view_curve_in_graph_editor", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4960,7 +4960,7 @@ "gapId": "operator:armature.align", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -4983,7 +4983,7 @@ "gapId": "operator:armature.assign_to_collection", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5006,7 +5006,7 @@ "gapId": "operator:armature.autoside_names", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5029,7 +5029,7 @@ "gapId": "operator:armature.bone_primitive_add", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5052,7 +5052,7 @@ "gapId": "operator:armature.calculate_roll", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5075,7 +5075,7 @@ "gapId": "operator:armature.click_extrude", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5098,7 +5098,7 @@ "gapId": "operator:armature.collection_add", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5121,7 +5121,7 @@ "gapId": "operator:armature.collection_assign", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5144,7 +5144,7 @@ "gapId": "operator:armature.collection_create_and_assign", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5167,7 +5167,7 @@ "gapId": "operator:armature.collection_deselect", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5190,7 +5190,7 @@ "gapId": "operator:armature.collection_move", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5213,7 +5213,7 @@ "gapId": "operator:armature.collection_remove", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5236,7 +5236,7 @@ "gapId": "operator:armature.collection_remove_unused", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5259,7 +5259,7 @@ "gapId": "operator:armature.collection_select", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5282,7 +5282,7 @@ "gapId": "operator:armature.collection_show_all", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5305,7 +5305,7 @@ "gapId": "operator:armature.collection_unassign", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5328,7 +5328,7 @@ "gapId": "operator:armature.collection_unassign_named", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5351,7 +5351,7 @@ "gapId": "operator:armature.collection_unsolo_all", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5374,7 +5374,7 @@ "gapId": "operator:armature.copy_bone_color_to_selected", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5397,7 +5397,7 @@ "gapId": "operator:armature.delete", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5420,7 +5420,7 @@ "gapId": "operator:armature.dissolve", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5443,7 +5443,7 @@ "gapId": "operator:armature.duplicate", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5466,7 +5466,7 @@ "gapId": "operator:armature.duplicate_move", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5489,7 +5489,7 @@ "gapId": "operator:armature.duplicate_rename", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5512,7 +5512,7 @@ "gapId": "operator:armature.extrude", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5535,7 +5535,7 @@ "gapId": "operator:armature.extrude_forked", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5558,7 +5558,7 @@ "gapId": "operator:armature.extrude_move", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5581,7 +5581,7 @@ "gapId": "operator:armature.fill", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5604,7 +5604,7 @@ "gapId": "operator:armature.flip_names", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5627,7 +5627,7 @@ "gapId": "operator:armature.hide", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5650,7 +5650,7 @@ "gapId": "operator:armature.move_to_collection", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5673,7 +5673,7 @@ "gapId": "operator:armature.parent_clear", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5696,7 +5696,7 @@ "gapId": "operator:armature.parent_set", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5719,7 +5719,7 @@ "gapId": "operator:armature.reveal", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5742,7 +5742,7 @@ "gapId": "operator:armature.roll_clear", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5765,7 +5765,7 @@ "gapId": "operator:armature.select_all", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5788,7 +5788,7 @@ "gapId": "operator:armature.select_hierarchy", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5811,7 +5811,7 @@ "gapId": "operator:armature.select_less", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5834,7 +5834,7 @@ "gapId": "operator:armature.select_linked", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5857,7 +5857,7 @@ "gapId": "operator:armature.select_linked_pick", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5880,7 +5880,7 @@ "gapId": "operator:armature.select_mirror", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5903,7 +5903,7 @@ "gapId": "operator:armature.select_more", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5926,7 +5926,7 @@ "gapId": "operator:armature.select_similar", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5949,7 +5949,7 @@ "gapId": "operator:armature.separate", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5972,7 +5972,7 @@ "gapId": "operator:armature.shortest_path_pick", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -5995,7 +5995,7 @@ "gapId": "operator:armature.split", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -6018,7 +6018,7 @@ "gapId": "operator:armature.subdivide", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -6041,7 +6041,7 @@ "gapId": "operator:armature.switch_direction", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -6064,7 +6064,7 @@ "gapId": "operator:armature.symmetrize", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "completed", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -6087,7 +6087,7 @@ "gapId": "operator:asset.asset_download", "ownerFamily": "OPERATOR", "sourceTask": "M15-01B", - "state": "pending", + "state": "active", "dependencies": [], "targetImplementationClass": "LOCAL_EXACT", "fixture": { @@ -158734,7 +158734,7 @@ ] } ], - "firstTask": "M16-GAP-00175", + "firstTask": "M16-GAP-00264", "closureGate": "M15-03E", "nextTask": "M15-03B" } diff --git a/tests/golden/M15-03A/task-catalog.jsonl b/tests/golden/M15-03A/task-catalog.jsonl index 56e0182c..807f53fa 100644 --- a/tests/golden/M15-03A/task-catalog.jsonl +++ b/tests/golden/M15-03A/task-catalog.jsonl @@ -172,96 +172,96 @@ {"id":"M16-GAP-00172","gapId":"operator:anim.clear_useless_actions","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} {"id":"M16-GAP-00173","gapId":"operator:anim.copy_driver_button","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} {"id":"M16-GAP-00174","gapId":"operator:anim.driver_button_add","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00175","gapId":"operator:anim.driver_button_edit","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"active","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00176","gapId":"operator:anim.driver_button_remove","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00177","gapId":"operator:anim.end_frame_set","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00178","gapId":"operator:anim.keyframe_clear_button","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00179","gapId":"operator:anim.keyframe_clear_v3d","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00180","gapId":"operator:anim.keyframe_clear_vse","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00181","gapId":"operator:anim.keyframe_delete","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00182","gapId":"operator:anim.keyframe_delete_button","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00183","gapId":"operator:anim.keyframe_delete_by_name","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00184","gapId":"operator:anim.keyframe_delete_v3d","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00185","gapId":"operator:anim.keyframe_delete_vse","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00186","gapId":"operator:anim.keyframe_insert","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00187","gapId":"operator:anim.keyframe_insert_button","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00188","gapId":"operator:anim.keyframe_insert_by_name","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00189","gapId":"operator:anim.keyframe_insert_menu","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00190","gapId":"operator:anim.keying_set_active_set","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00191","gapId":"operator:anim.keying_set_add","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00192","gapId":"operator:anim.keying_set_export","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00193","gapId":"operator:anim.keying_set_path_add","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00194","gapId":"operator:anim.keying_set_path_remove","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00195","gapId":"operator:anim.keying_set_remove","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00196","gapId":"operator:anim.keyingset_button_add","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00197","gapId":"operator:anim.keyingset_button_remove","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00198","gapId":"operator:anim.merge_animation","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00199","gapId":"operator:anim.paste_driver_button","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00200","gapId":"operator:anim.previewrange_clear","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00201","gapId":"operator:anim.previewrange_set","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00202","gapId":"operator:anim.replace_action","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00203","gapId":"operator:anim.replace_action_new","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00204","gapId":"operator:anim.scene_range_frame","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00205","gapId":"operator:anim.separate_slots","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00206","gapId":"operator:anim.slot_channels_move_to_new_action","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00207","gapId":"operator:anim.slot_new_for_id","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00208","gapId":"operator:anim.slot_unassign_from_constraint","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00209","gapId":"operator:anim.slot_unassign_from_id","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00210","gapId":"operator:anim.slot_unassign_from_nla_strip","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00211","gapId":"operator:anim.start_frame_set","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00212","gapId":"operator:anim.update_animated_transform_constraints","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00213","gapId":"operator:anim.version_bone_hide_property","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00214","gapId":"operator:anim.view_curve_in_graph_editor","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00215","gapId":"operator:armature.align","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00216","gapId":"operator:armature.assign_to_collection","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00217","gapId":"operator:armature.autoside_names","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00218","gapId":"operator:armature.bone_primitive_add","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00219","gapId":"operator:armature.calculate_roll","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00220","gapId":"operator:armature.click_extrude","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00221","gapId":"operator:armature.collection_add","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00222","gapId":"operator:armature.collection_assign","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00223","gapId":"operator:armature.collection_create_and_assign","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00224","gapId":"operator:armature.collection_deselect","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00225","gapId":"operator:armature.collection_move","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00226","gapId":"operator:armature.collection_remove","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00227","gapId":"operator:armature.collection_remove_unused","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00228","gapId":"operator:armature.collection_select","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00229","gapId":"operator:armature.collection_show_all","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00230","gapId":"operator:armature.collection_unassign","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00231","gapId":"operator:armature.collection_unassign_named","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00232","gapId":"operator:armature.collection_unsolo_all","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00233","gapId":"operator:armature.copy_bone_color_to_selected","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00234","gapId":"operator:armature.delete","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00235","gapId":"operator:armature.dissolve","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00236","gapId":"operator:armature.duplicate","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00237","gapId":"operator:armature.duplicate_move","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00238","gapId":"operator:armature.duplicate_rename","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00239","gapId":"operator:armature.extrude","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00240","gapId":"operator:armature.extrude_forked","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00241","gapId":"operator:armature.extrude_move","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00242","gapId":"operator:armature.fill","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00243","gapId":"operator:armature.flip_names","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00244","gapId":"operator:armature.hide","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00245","gapId":"operator:armature.move_to_collection","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00246","gapId":"operator:armature.parent_clear","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00247","gapId":"operator:armature.parent_set","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00248","gapId":"operator:armature.reveal","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00249","gapId":"operator:armature.roll_clear","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00250","gapId":"operator:armature.select_all","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00251","gapId":"operator:armature.select_hierarchy","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00252","gapId":"operator:armature.select_less","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00253","gapId":"operator:armature.select_linked","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00254","gapId":"operator:armature.select_linked_pick","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00255","gapId":"operator:armature.select_mirror","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00256","gapId":"operator:armature.select_more","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00257","gapId":"operator:armature.select_similar","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00258","gapId":"operator:armature.separate","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00259","gapId":"operator:armature.shortest_path_pick","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00260","gapId":"operator:armature.split","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00261","gapId":"operator:armature.subdivide","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00262","gapId":"operator:armature.switch_direction","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00263","gapId":"operator:armature.symmetrize","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} -{"id":"M16-GAP-00264","gapId":"operator:asset.asset_download","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00175","gapId":"operator:anim.driver_button_edit","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00176","gapId":"operator:anim.driver_button_remove","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00177","gapId":"operator:anim.end_frame_set","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00178","gapId":"operator:anim.keyframe_clear_button","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00179","gapId":"operator:anim.keyframe_clear_v3d","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00180","gapId":"operator:anim.keyframe_clear_vse","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00181","gapId":"operator:anim.keyframe_delete","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00182","gapId":"operator:anim.keyframe_delete_button","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00183","gapId":"operator:anim.keyframe_delete_by_name","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00184","gapId":"operator:anim.keyframe_delete_v3d","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00185","gapId":"operator:anim.keyframe_delete_vse","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00186","gapId":"operator:anim.keyframe_insert","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00187","gapId":"operator:anim.keyframe_insert_button","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00188","gapId":"operator:anim.keyframe_insert_by_name","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00189","gapId":"operator:anim.keyframe_insert_menu","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00190","gapId":"operator:anim.keying_set_active_set","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00191","gapId":"operator:anim.keying_set_add","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00192","gapId":"operator:anim.keying_set_export","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00193","gapId":"operator:anim.keying_set_path_add","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00194","gapId":"operator:anim.keying_set_path_remove","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00195","gapId":"operator:anim.keying_set_remove","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00196","gapId":"operator:anim.keyingset_button_add","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00197","gapId":"operator:anim.keyingset_button_remove","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00198","gapId":"operator:anim.merge_animation","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00199","gapId":"operator:anim.paste_driver_button","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00200","gapId":"operator:anim.previewrange_clear","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00201","gapId":"operator:anim.previewrange_set","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00202","gapId":"operator:anim.replace_action","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00203","gapId":"operator:anim.replace_action_new","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00204","gapId":"operator:anim.scene_range_frame","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00205","gapId":"operator:anim.separate_slots","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00206","gapId":"operator:anim.slot_channels_move_to_new_action","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00207","gapId":"operator:anim.slot_new_for_id","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00208","gapId":"operator:anim.slot_unassign_from_constraint","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00209","gapId":"operator:anim.slot_unassign_from_id","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00210","gapId":"operator:anim.slot_unassign_from_nla_strip","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00211","gapId":"operator:anim.start_frame_set","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00212","gapId":"operator:anim.update_animated_transform_constraints","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00213","gapId":"operator:anim.version_bone_hide_property","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00214","gapId":"operator:anim.view_curve_in_graph_editor","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00215","gapId":"operator:armature.align","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00216","gapId":"operator:armature.assign_to_collection","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00217","gapId":"operator:armature.autoside_names","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00218","gapId":"operator:armature.bone_primitive_add","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00219","gapId":"operator:armature.calculate_roll","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00220","gapId":"operator:armature.click_extrude","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00221","gapId":"operator:armature.collection_add","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00222","gapId":"operator:armature.collection_assign","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00223","gapId":"operator:armature.collection_create_and_assign","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00224","gapId":"operator:armature.collection_deselect","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00225","gapId":"operator:armature.collection_move","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00226","gapId":"operator:armature.collection_remove","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00227","gapId":"operator:armature.collection_remove_unused","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00228","gapId":"operator:armature.collection_select","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00229","gapId":"operator:armature.collection_show_all","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00230","gapId":"operator:armature.collection_unassign","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00231","gapId":"operator:armature.collection_unassign_named","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00232","gapId":"operator:armature.collection_unsolo_all","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00233","gapId":"operator:armature.copy_bone_color_to_selected","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00234","gapId":"operator:armature.delete","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00235","gapId":"operator:armature.dissolve","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00236","gapId":"operator:armature.duplicate","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00237","gapId":"operator:armature.duplicate_move","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00238","gapId":"operator:armature.duplicate_rename","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00239","gapId":"operator:armature.extrude","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00240","gapId":"operator:armature.extrude_forked","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00241","gapId":"operator:armature.extrude_move","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00242","gapId":"operator:armature.fill","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00243","gapId":"operator:armature.flip_names","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00244","gapId":"operator:armature.hide","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00245","gapId":"operator:armature.move_to_collection","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00246","gapId":"operator:armature.parent_clear","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00247","gapId":"operator:armature.parent_set","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00248","gapId":"operator:armature.reveal","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00249","gapId":"operator:armature.roll_clear","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00250","gapId":"operator:armature.select_all","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00251","gapId":"operator:armature.select_hierarchy","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00252","gapId":"operator:armature.select_less","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00253","gapId":"operator:armature.select_linked","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00254","gapId":"operator:armature.select_linked_pick","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00255","gapId":"operator:armature.select_mirror","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00256","gapId":"operator:armature.select_more","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00257","gapId":"operator:armature.select_similar","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00258","gapId":"operator:armature.separate","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00259","gapId":"operator:armature.shortest_path_pick","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00260","gapId":"operator:armature.split","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00261","gapId":"operator:armature.subdivide","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00262","gapId":"operator:armature.switch_direction","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00263","gapId":"operator:armature.symmetrize","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"completed","targetImplementationClass":"LOCAL_EXACT"} +{"id":"M16-GAP-00264","gapId":"operator:asset.asset_download","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"active","targetImplementationClass":"LOCAL_EXACT"} {"id":"M16-GAP-00265","gapId":"operator:asset.assets_download","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} {"id":"M16-GAP-00266","gapId":"operator:asset.assign_action","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} {"id":"M16-GAP-00267","gapId":"operator:asset.browse_containing_blend_file","ownerFamily":"OPERATOR","sourceTask":"M15-01B","state":"pending","targetImplementationClass":"LOCAL_EXACT"} diff --git a/tests/golden/M15-03A/task-index.json b/tests/golden/M15-03A/task-index.json index 1ba91ed7..ab25140b 100644 --- a/tests/golden/M15-03A/task-index.json +++ b/tests/golden/M15-03A/task-index.json @@ -1 +1 @@ -{"schemaVersion":1,"operation":"BLENDER_TASK_CONTEXT_INDEX","source":{"path":"tests/golden/M15-03A/next-task-plan.json","sha256":"a57fb3d61f40361920529f42f8664b24393ed1db7d220e14fc123aaafb62b8c7"},"catalog":{"path":"tests/golden/M15-03A/task-catalog.jsonl","sha256":"cd4677fc8fc92ab33815cd93392e905144ca465d6dad30aeec509ac6bddd893c"},"taskCount":6900,"activeTask":"M16-GAP-00175","entries":{"M16-GAP-00001":{"line":0,"offset":0,"length":165,"previous":null,"next":"M16-GAP-00002"},"M16-GAP-00002":{"line":1,"offset":165,"length":167,"previous":"M16-GAP-00001","next":"M16-GAP-00003"},"M16-GAP-00003":{"line":2,"offset":332,"length":164,"previous":"M16-GAP-00002","next":"M16-GAP-00004"},"M16-GAP-00004":{"line":3,"offset":496,"length":165,"previous":"M16-GAP-00003","next":"M16-GAP-00005"},"M16-GAP-00005":{"line":4,"offset":661,"length":169,"previous":"M16-GAP-00004","next":"M16-GAP-00006"},"M16-GAP-00006":{"line":5,"offset":830,"length":164,"previous":"M16-GAP-00005","next":"M16-GAP-00007"},"M16-GAP-00007":{"line":6,"offset":994,"length":165,"previous":"M16-GAP-00006","next":"M16-GAP-00008"},"M16-GAP-00008":{"line":7,"offset":1159,"length":177,"previous":"M16-GAP-00007","next":"M16-GAP-00009"},"M16-GAP-00009":{"line":8,"offset":1336,"length":171,"previous":"M16-GAP-00008","next":"M16-GAP-00010"},"M16-GAP-00010":{"line":9,"offset":1507,"length":166,"previous":"M16-GAP-00009","next":"M16-GAP-00011"},"M16-GAP-00011":{"line":10,"offset":1673,"length":166,"previous":"M16-GAP-00010","next":"M16-GAP-00012"},"M16-GAP-00012":{"line":11,"offset":1839,"length":164,"previous":"M16-GAP-00011","next":"M16-GAP-00013"},"M16-GAP-00013":{"line":12,"offset":2003,"length":167,"previous":"M16-GAP-00012","next":"M16-GAP-00014"},"M16-GAP-00014":{"line":13,"offset":2170,"length":163,"previous":"M16-GAP-00013","next":"M16-GAP-00015"},"M16-GAP-00015":{"line":14,"offset":2333,"length":167,"previous":"M16-GAP-00014","next":"M16-GAP-00016"},"M16-GAP-00016":{"line":15,"offset":2500,"length":167,"previous":"M16-GAP-00015","next":"M16-GAP-00017"},"M16-GAP-00017":{"line":16,"offset":2667,"length":165,"previous":"M16-GAP-00016","next":"M16-GAP-00018"},"M16-GAP-00018":{"line":17,"offset":2832,"length":175,"previous":"M16-GAP-00017","next":"M16-GAP-00019"},"M16-GAP-00019":{"line":18,"offset":3007,"length":169,"previous":"M16-GAP-00018","next":"M16-GAP-00020"},"M16-GAP-00020":{"line":19,"offset":3176,"length":164,"previous":"M16-GAP-00019","next":"M16-GAP-00021"},"M16-GAP-00021":{"line":20,"offset":3340,"length":165,"previous":"M16-GAP-00020","next":"M16-GAP-00022"},"M16-GAP-00022":{"line":21,"offset":3505,"length":164,"previous":"M16-GAP-00021","next":"M16-GAP-00023"},"M16-GAP-00023":{"line":22,"offset":3669,"length":166,"previous":"M16-GAP-00022","next":"M16-GAP-00024"},"M16-GAP-00024":{"line":23,"offset":3835,"length":163,"previous":"M16-GAP-00023","next":"M16-GAP-00025"},"M16-GAP-00025":{"line":24,"offset":3998,"length":166,"previous":"M16-GAP-00024","next":"M16-GAP-00026"},"M16-GAP-00026":{"line":25,"offset":4164,"length":165,"previous":"M16-GAP-00025","next":"M16-GAP-00027"},"M16-GAP-00027":{"line":26,"offset":4329,"length":172,"previous":"M16-GAP-00026","next":"M16-GAP-00028"},"M16-GAP-00028":{"line":27,"offset":4501,"length":168,"previous":"M16-GAP-00027","next":"M16-GAP-00029"},"M16-GAP-00029":{"line":28,"offset":4669,"length":164,"previous":"M16-GAP-00028","next":"M16-GAP-00030"},"M16-GAP-00030":{"line":29,"offset":4833,"length":161,"previous":"M16-GAP-00029","next":"M16-GAP-00031"},"M16-GAP-00031":{"line":30,"offset":4994,"length":158,"previous":"M16-GAP-00030","next":"M16-GAP-00032"},"M16-GAP-00032":{"line":31,"offset":5152,"length":158,"previous":"M16-GAP-00031","next":"M16-GAP-00033"},"M16-GAP-00033":{"line":32,"offset":5310,"length":160,"previous":"M16-GAP-00032","next":"M16-GAP-00034"},"M16-GAP-00034":{"line":33,"offset":5470,"length":158,"previous":"M16-GAP-00033","next":"M16-GAP-00035"},"M16-GAP-00035":{"line":34,"offset":5628,"length":157,"previous":"M16-GAP-00034","next":"M16-GAP-00036"},"M16-GAP-00036":{"line":35,"offset":5785,"length":158,"previous":"M16-GAP-00035","next":"M16-GAP-00037"},"M16-GAP-00037":{"line":36,"offset":5943,"length":162,"previous":"M16-GAP-00036","next":"M16-GAP-00038"},"M16-GAP-00038":{"line":37,"offset":6105,"length":170,"previous":"M16-GAP-00037","next":"M16-GAP-00039"},"M16-GAP-00039":{"line":38,"offset":6275,"length":158,"previous":"M16-GAP-00038","next":"M16-GAP-00040"},"M16-GAP-00040":{"line":39,"offset":6433,"length":166,"previous":"M16-GAP-00039","next":"M16-GAP-00041"},"M16-GAP-00041":{"line":40,"offset":6599,"length":161,"previous":"M16-GAP-00040","next":"M16-GAP-00042"},"M16-GAP-00042":{"line":41,"offset":6760,"length":161,"previous":"M16-GAP-00041","next":"M16-GAP-00043"},"M16-GAP-00043":{"line":42,"offset":6921,"length":166,"previous":"M16-GAP-00042","next":"M16-GAP-00044"},"M16-GAP-00044":{"line":43,"offset":7087,"length":163,"previous":"M16-GAP-00043","next":"M16-GAP-00045"},"M16-GAP-00045":{"line":44,"offset":7250,"length":160,"previous":"M16-GAP-00044","next":"M16-GAP-00046"},"M16-GAP-00046":{"line":45,"offset":7410,"length":158,"previous":"M16-GAP-00045","next":"M16-GAP-00047"},"M16-GAP-00047":{"line":46,"offset":7568,"length":175,"previous":"M16-GAP-00046","next":"M16-GAP-00048"},"M16-GAP-00048":{"line":47,"offset":7743,"length":172,"previous":"M16-GAP-00047","next":"M16-GAP-00049"},"M16-GAP-00049":{"line":48,"offset":7915,"length":172,"previous":"M16-GAP-00048","next":"M16-GAP-00050"},"M16-GAP-00050":{"line":49,"offset":8087,"length":172,"previous":"M16-GAP-00049","next":"M16-GAP-00051"},"M16-GAP-00051":{"line":50,"offset":8259,"length":171,"previous":"M16-GAP-00050","next":"M16-GAP-00052"},"M16-GAP-00052":{"line":51,"offset":8430,"length":175,"previous":"M16-GAP-00051","next":"M16-GAP-00053"},"M16-GAP-00053":{"line":52,"offset":8605,"length":171,"previous":"M16-GAP-00052","next":"M16-GAP-00054"},"M16-GAP-00054":{"line":53,"offset":8776,"length":174,"previous":"M16-GAP-00053","next":"M16-GAP-00055"},"M16-GAP-00055":{"line":54,"offset":8950,"length":173,"previous":"M16-GAP-00054","next":"M16-GAP-00056"},"M16-GAP-00056":{"line":55,"offset":9123,"length":173,"previous":"M16-GAP-00055","next":"M16-GAP-00057"},"M16-GAP-00057":{"line":56,"offset":9296,"length":175,"previous":"M16-GAP-00056","next":"M16-GAP-00058"},"M16-GAP-00058":{"line":57,"offset":9471,"length":172,"previous":"M16-GAP-00057","next":"M16-GAP-00059"},"M16-GAP-00059":{"line":58,"offset":9643,"length":173,"previous":"M16-GAP-00058","next":"M16-GAP-00060"},"M16-GAP-00060":{"line":59,"offset":9816,"length":174,"previous":"M16-GAP-00059","next":"M16-GAP-00061"},"M16-GAP-00061":{"line":60,"offset":9990,"length":174,"previous":"M16-GAP-00060","next":"M16-GAP-00062"},"M16-GAP-00062":{"line":61,"offset":10164,"length":177,"previous":"M16-GAP-00061","next":"M16-GAP-00063"},"M16-GAP-00063":{"line":62,"offset":10341,"length":175,"previous":"M16-GAP-00062","next":"M16-GAP-00064"},"M16-GAP-00064":{"line":63,"offset":10516,"length":173,"previous":"M16-GAP-00063","next":"M16-GAP-00065"},"M16-GAP-00065":{"line":64,"offset":10689,"length":173,"previous":"M16-GAP-00064","next":"M16-GAP-00066"},"M16-GAP-00066":{"line":65,"offset":10862,"length":174,"previous":"M16-GAP-00065","next":"M16-GAP-00067"},"M16-GAP-00067":{"line":66,"offset":11036,"length":176,"previous":"M16-GAP-00066","next":"M16-GAP-00068"},"M16-GAP-00068":{"line":67,"offset":11212,"length":171,"previous":"M16-GAP-00067","next":"M16-GAP-00069"},"M16-GAP-00069":{"line":68,"offset":11383,"length":171,"previous":"M16-GAP-00068","next":"M16-GAP-00070"},"M16-GAP-00070":{"line":69,"offset":11554,"length":186,"previous":"M16-GAP-00069","next":"M16-GAP-00071"},"M16-GAP-00071":{"line":70,"offset":11740,"length":190,"previous":"M16-GAP-00070","next":"M16-GAP-00072"},"M16-GAP-00072":{"line":71,"offset":11930,"length":157,"previous":"M16-GAP-00071","next":"M16-GAP-00073"},"M16-GAP-00073":{"line":72,"offset":12087,"length":168,"previous":"M16-GAP-00072","next":"M16-GAP-00074"},"M16-GAP-00074":{"line":73,"offset":12255,"length":168,"previous":"M16-GAP-00073","next":"M16-GAP-00075"},"M16-GAP-00075":{"line":74,"offset":12423,"length":160,"previous":"M16-GAP-00074","next":"M16-GAP-00076"},"M16-GAP-00076":{"line":75,"offset":12583,"length":160,"previous":"M16-GAP-00075","next":"M16-GAP-00077"},"M16-GAP-00077":{"line":76,"offset":12743,"length":157,"previous":"M16-GAP-00076","next":"M16-GAP-00078"},"M16-GAP-00078":{"line":77,"offset":12900,"length":163,"previous":"M16-GAP-00077","next":"M16-GAP-00079"},"M16-GAP-00079":{"line":78,"offset":13063,"length":164,"previous":"M16-GAP-00078","next":"M16-GAP-00080"},"M16-GAP-00080":{"line":79,"offset":13227,"length":172,"previous":"M16-GAP-00079","next":"M16-GAP-00081"},"M16-GAP-00081":{"line":80,"offset":13399,"length":167,"previous":"M16-GAP-00080","next":"M16-GAP-00082"},"M16-GAP-00082":{"line":81,"offset":13566,"length":159,"previous":"M16-GAP-00081","next":"M16-GAP-00083"},"M16-GAP-00083":{"line":82,"offset":13725,"length":161,"previous":"M16-GAP-00082","next":"M16-GAP-00084"},"M16-GAP-00084":{"line":83,"offset":13886,"length":158,"previous":"M16-GAP-00083","next":"M16-GAP-00085"},"M16-GAP-00085":{"line":84,"offset":14044,"length":164,"previous":"M16-GAP-00084","next":"M16-GAP-00086"},"M16-GAP-00086":{"line":85,"offset":14208,"length":158,"previous":"M16-GAP-00085","next":"M16-GAP-00087"},"M16-GAP-00087":{"line":86,"offset":14366,"length":170,"previous":"M16-GAP-00086","next":"M16-GAP-00088"},"M16-GAP-00088":{"line":87,"offset":14536,"length":168,"previous":"M16-GAP-00087","next":"M16-GAP-00089"},"M16-GAP-00089":{"line":88,"offset":14704,"length":159,"previous":"M16-GAP-00088","next":"M16-GAP-00090"},"M16-GAP-00090":{"line":89,"offset":14863,"length":158,"previous":"M16-GAP-00089","next":"M16-GAP-00091"},"M16-GAP-00091":{"line":90,"offset":15021,"length":163,"previous":"M16-GAP-00090","next":"M16-GAP-00092"},"M16-GAP-00092":{"line":91,"offset":15184,"length":166,"previous":"M16-GAP-00091","next":"M16-GAP-00093"},"M16-GAP-00093":{"line":92,"offset":15350,"length":157,"previous":"M16-GAP-00092","next":"M16-GAP-00094"},"M16-GAP-00094":{"line":93,"offset":15507,"length":159,"previous":"M16-GAP-00093","next":"M16-GAP-00095"},"M16-GAP-00095":{"line":94,"offset":15666,"length":162,"previous":"M16-GAP-00094","next":"M16-GAP-00096"},"M16-GAP-00096":{"line":95,"offset":15828,"length":161,"previous":"M16-GAP-00095","next":"M16-GAP-00097"},"M16-GAP-00097":{"line":96,"offset":15989,"length":160,"previous":"M16-GAP-00096","next":"M16-GAP-00098"},"M16-GAP-00098":{"line":97,"offset":16149,"length":160,"previous":"M16-GAP-00097","next":"M16-GAP-00099"},"M16-GAP-00099":{"line":98,"offset":16309,"length":167,"previous":"M16-GAP-00098","next":"M16-GAP-00100"},"M16-GAP-00100":{"line":99,"offset":16476,"length":164,"previous":"M16-GAP-00099","next":"M16-GAP-00101"},"M16-GAP-00101":{"line":100,"offset":16640,"length":163,"previous":"M16-GAP-00100","next":"M16-GAP-00102"},"M16-GAP-00102":{"line":101,"offset":16803,"length":160,"previous":"M16-GAP-00101","next":"M16-GAP-00103"},"M16-GAP-00103":{"line":102,"offset":16963,"length":171,"previous":"M16-GAP-00102","next":"M16-GAP-00104"},"M16-GAP-00104":{"line":103,"offset":17134,"length":170,"previous":"M16-GAP-00103","next":"M16-GAP-00105"},"M16-GAP-00105":{"line":104,"offset":17304,"length":176,"previous":"M16-GAP-00104","next":"M16-GAP-00106"},"M16-GAP-00106":{"line":105,"offset":17480,"length":168,"previous":"M16-GAP-00105","next":"M16-GAP-00107"},"M16-GAP-00107":{"line":106,"offset":17648,"length":167,"previous":"M16-GAP-00106","next":"M16-GAP-00108"},"M16-GAP-00108":{"line":107,"offset":17815,"length":157,"previous":"M16-GAP-00107","next":"M16-GAP-00109"},"M16-GAP-00109":{"line":108,"offset":17972,"length":157,"previous":"M16-GAP-00108","next":"M16-GAP-00110"},"M16-GAP-00110":{"line":109,"offset":18129,"length":168,"previous":"M16-GAP-00109","next":"M16-GAP-00111"},"M16-GAP-00111":{"line":110,"offset":18297,"length":157,"previous":"M16-GAP-00110","next":"M16-GAP-00112"},"M16-GAP-00112":{"line":111,"offset":18454,"length":162,"previous":"M16-GAP-00111","next":"M16-GAP-00113"},"M16-GAP-00113":{"line":112,"offset":18616,"length":169,"previous":"M16-GAP-00112","next":"M16-GAP-00114"},"M16-GAP-00114":{"line":113,"offset":18785,"length":165,"previous":"M16-GAP-00113","next":"M16-GAP-00115"},"M16-GAP-00115":{"line":114,"offset":18950,"length":171,"previous":"M16-GAP-00114","next":"M16-GAP-00116"},"M16-GAP-00116":{"line":115,"offset":19121,"length":164,"previous":"M16-GAP-00115","next":"M16-GAP-00117"},"M16-GAP-00117":{"line":116,"offset":19285,"length":166,"previous":"M16-GAP-00116","next":"M16-GAP-00118"},"M16-GAP-00118":{"line":117,"offset":19451,"length":169,"previous":"M16-GAP-00117","next":"M16-GAP-00119"},"M16-GAP-00119":{"line":118,"offset":19620,"length":174,"previous":"M16-GAP-00118","next":"M16-GAP-00120"},"M16-GAP-00120":{"line":119,"offset":19794,"length":171,"previous":"M16-GAP-00119","next":"M16-GAP-00121"},"M16-GAP-00121":{"line":120,"offset":19965,"length":178,"previous":"M16-GAP-00120","next":"M16-GAP-00122"},"M16-GAP-00122":{"line":121,"offset":20143,"length":170,"previous":"M16-GAP-00121","next":"M16-GAP-00123"},"M16-GAP-00123":{"line":122,"offset":20313,"length":171,"previous":"M16-GAP-00122","next":"M16-GAP-00124"},"M16-GAP-00124":{"line":123,"offset":20484,"length":178,"previous":"M16-GAP-00123","next":"M16-GAP-00125"},"M16-GAP-00125":{"line":124,"offset":20662,"length":175,"previous":"M16-GAP-00124","next":"M16-GAP-00126"},"M16-GAP-00126":{"line":125,"offset":20837,"length":173,"previous":"M16-GAP-00125","next":"M16-GAP-00127"},"M16-GAP-00127":{"line":126,"offset":21010,"length":178,"previous":"M16-GAP-00126","next":"M16-GAP-00128"},"M16-GAP-00128":{"line":127,"offset":21188,"length":166,"previous":"M16-GAP-00127","next":"M16-GAP-00129"},"M16-GAP-00129":{"line":128,"offset":21354,"length":163,"previous":"M16-GAP-00128","next":"M16-GAP-00130"},"M16-GAP-00130":{"line":129,"offset":21517,"length":165,"previous":"M16-GAP-00129","next":"M16-GAP-00131"},"M16-GAP-00131":{"line":130,"offset":21682,"length":176,"previous":"M16-GAP-00130","next":"M16-GAP-00132"},"M16-GAP-00132":{"line":131,"offset":21858,"length":169,"previous":"M16-GAP-00131","next":"M16-GAP-00133"},"M16-GAP-00133":{"line":132,"offset":22027,"length":170,"previous":"M16-GAP-00132","next":"M16-GAP-00134"},"M16-GAP-00134":{"line":133,"offset":22197,"length":170,"previous":"M16-GAP-00133","next":"M16-GAP-00135"},"M16-GAP-00135":{"line":134,"offset":22367,"length":174,"previous":"M16-GAP-00134","next":"M16-GAP-00136"},"M16-GAP-00136":{"line":135,"offset":22541,"length":173,"previous":"M16-GAP-00135","next":"M16-GAP-00137"},"M16-GAP-00137":{"line":136,"offset":22714,"length":173,"previous":"M16-GAP-00136","next":"M16-GAP-00138"},"M16-GAP-00138":{"line":137,"offset":22887,"length":172,"previous":"M16-GAP-00137","next":"M16-GAP-00139"},"M16-GAP-00139":{"line":138,"offset":23059,"length":176,"previous":"M16-GAP-00138","next":"M16-GAP-00140"},"M16-GAP-00140":{"line":139,"offset":23235,"length":171,"previous":"M16-GAP-00139","next":"M16-GAP-00141"},"M16-GAP-00141":{"line":140,"offset":23406,"length":173,"previous":"M16-GAP-00140","next":"M16-GAP-00142"},"M16-GAP-00142":{"line":141,"offset":23579,"length":171,"previous":"M16-GAP-00141","next":"M16-GAP-00143"},"M16-GAP-00143":{"line":142,"offset":23750,"length":164,"previous":"M16-GAP-00142","next":"M16-GAP-00144"},"M16-GAP-00144":{"line":143,"offset":23914,"length":165,"previous":"M16-GAP-00143","next":"M16-GAP-00145"},"M16-GAP-00145":{"line":144,"offset":24079,"length":176,"previous":"M16-GAP-00144","next":"M16-GAP-00146"},"M16-GAP-00146":{"line":145,"offset":24255,"length":166,"previous":"M16-GAP-00145","next":"M16-GAP-00147"},"M16-GAP-00147":{"line":146,"offset":24421,"length":168,"previous":"M16-GAP-00146","next":"M16-GAP-00148"},"M16-GAP-00148":{"line":147,"offset":24589,"length":170,"previous":"M16-GAP-00147","next":"M16-GAP-00149"},"M16-GAP-00149":{"line":148,"offset":24759,"length":173,"previous":"M16-GAP-00148","next":"M16-GAP-00150"},"M16-GAP-00150":{"line":149,"offset":24932,"length":170,"previous":"M16-GAP-00149","next":"M16-GAP-00151"},"M16-GAP-00151":{"line":150,"offset":25102,"length":177,"previous":"M16-GAP-00150","next":"M16-GAP-00152"},"M16-GAP-00152":{"line":151,"offset":25279,"length":175,"previous":"M16-GAP-00151","next":"M16-GAP-00153"},"M16-GAP-00153":{"line":152,"offset":25454,"length":171,"previous":"M16-GAP-00152","next":"M16-GAP-00154"},"M16-GAP-00154":{"line":153,"offset":25625,"length":178,"previous":"M16-GAP-00153","next":"M16-GAP-00155"},"M16-GAP-00155":{"line":154,"offset":25803,"length":172,"previous":"M16-GAP-00154","next":"M16-GAP-00156"},"M16-GAP-00156":{"line":155,"offset":25975,"length":175,"previous":"M16-GAP-00155","next":"M16-GAP-00157"},"M16-GAP-00157":{"line":156,"offset":26150,"length":173,"previous":"M16-GAP-00156","next":"M16-GAP-00158"},"M16-GAP-00158":{"line":157,"offset":26323,"length":182,"previous":"M16-GAP-00157","next":"M16-GAP-00159"},"M16-GAP-00159":{"line":158,"offset":26505,"length":173,"previous":"M16-GAP-00158","next":"M16-GAP-00160"},"M16-GAP-00160":{"line":159,"offset":26678,"length":181,"previous":"M16-GAP-00159","next":"M16-GAP-00161"},"M16-GAP-00161":{"line":160,"offset":26859,"length":172,"previous":"M16-GAP-00160","next":"M16-GAP-00162"},"M16-GAP-00162":{"line":161,"offset":27031,"length":171,"previous":"M16-GAP-00161","next":"M16-GAP-00163"},"M16-GAP-00163":{"line":162,"offset":27202,"length":173,"previous":"M16-GAP-00162","next":"M16-GAP-00164"},"M16-GAP-00164":{"line":163,"offset":27375,"length":177,"previous":"M16-GAP-00163","next":"M16-GAP-00165"},"M16-GAP-00165":{"line":164,"offset":27552,"length":177,"previous":"M16-GAP-00164","next":"M16-GAP-00166"},"M16-GAP-00166":{"line":165,"offset":27729,"length":180,"previous":"M16-GAP-00165","next":"M16-GAP-00167"},"M16-GAP-00167":{"line":166,"offset":27909,"length":182,"previous":"M16-GAP-00166","next":"M16-GAP-00168"},"M16-GAP-00168":{"line":167,"offset":28091,"length":181,"previous":"M16-GAP-00167","next":"M16-GAP-00169"},"M16-GAP-00169":{"line":168,"offset":28272,"length":181,"previous":"M16-GAP-00168","next":"M16-GAP-00170"},"M16-GAP-00170":{"line":169,"offset":28453,"length":174,"previous":"M16-GAP-00169","next":"M16-GAP-00171"},"M16-GAP-00171":{"line":170,"offset":28627,"length":180,"previous":"M16-GAP-00170","next":"M16-GAP-00172"},"M16-GAP-00172":{"line":171,"offset":28807,"length":179,"previous":"M16-GAP-00171","next":"M16-GAP-00173"},"M16-GAP-00173":{"line":172,"offset":28986,"length":176,"previous":"M16-GAP-00172","next":"M16-GAP-00174"},"M16-GAP-00174":{"line":173,"offset":29162,"length":175,"previous":"M16-GAP-00173","next":"M16-GAP-00175"},"M16-GAP-00175":{"line":174,"offset":29337,"length":173,"previous":"M16-GAP-00174","next":"M16-GAP-00176"},"M16-GAP-00176":{"line":175,"offset":29510,"length":176,"previous":"M16-GAP-00175","next":"M16-GAP-00177"},"M16-GAP-00177":{"line":176,"offset":29686,"length":169,"previous":"M16-GAP-00176","next":"M16-GAP-00178"},"M16-GAP-00178":{"line":177,"offset":29855,"length":177,"previous":"M16-GAP-00177","next":"M16-GAP-00179"},"M16-GAP-00179":{"line":178,"offset":30032,"length":174,"previous":"M16-GAP-00178","next":"M16-GAP-00180"},"M16-GAP-00180":{"line":179,"offset":30206,"length":174,"previous":"M16-GAP-00179","next":"M16-GAP-00181"},"M16-GAP-00181":{"line":180,"offset":30380,"length":171,"previous":"M16-GAP-00180","next":"M16-GAP-00182"},"M16-GAP-00182":{"line":181,"offset":30551,"length":178,"previous":"M16-GAP-00181","next":"M16-GAP-00183"},"M16-GAP-00183":{"line":182,"offset":30729,"length":179,"previous":"M16-GAP-00182","next":"M16-GAP-00184"},"M16-GAP-00184":{"line":183,"offset":30908,"length":175,"previous":"M16-GAP-00183","next":"M16-GAP-00185"},"M16-GAP-00185":{"line":184,"offset":31083,"length":175,"previous":"M16-GAP-00184","next":"M16-GAP-00186"},"M16-GAP-00186":{"line":185,"offset":31258,"length":171,"previous":"M16-GAP-00185","next":"M16-GAP-00187"},"M16-GAP-00187":{"line":186,"offset":31429,"length":178,"previous":"M16-GAP-00186","next":"M16-GAP-00188"},"M16-GAP-00188":{"line":187,"offset":31607,"length":179,"previous":"M16-GAP-00187","next":"M16-GAP-00189"},"M16-GAP-00189":{"line":188,"offset":31786,"length":176,"previous":"M16-GAP-00188","next":"M16-GAP-00190"},"M16-GAP-00190":{"line":189,"offset":31962,"length":177,"previous":"M16-GAP-00189","next":"M16-GAP-00191"},"M16-GAP-00191":{"line":190,"offset":32139,"length":170,"previous":"M16-GAP-00190","next":"M16-GAP-00192"},"M16-GAP-00192":{"line":191,"offset":32309,"length":173,"previous":"M16-GAP-00191","next":"M16-GAP-00193"},"M16-GAP-00193":{"line":192,"offset":32482,"length":175,"previous":"M16-GAP-00192","next":"M16-GAP-00194"},"M16-GAP-00194":{"line":193,"offset":32657,"length":178,"previous":"M16-GAP-00193","next":"M16-GAP-00195"},"M16-GAP-00195":{"line":194,"offset":32835,"length":173,"previous":"M16-GAP-00194","next":"M16-GAP-00196"},"M16-GAP-00196":{"line":195,"offset":33008,"length":176,"previous":"M16-GAP-00195","next":"M16-GAP-00197"},"M16-GAP-00197":{"line":196,"offset":33184,"length":179,"previous":"M16-GAP-00196","next":"M16-GAP-00198"},"M16-GAP-00198":{"line":197,"offset":33363,"length":171,"previous":"M16-GAP-00197","next":"M16-GAP-00199"},"M16-GAP-00199":{"line":198,"offset":33534,"length":175,"previous":"M16-GAP-00198","next":"M16-GAP-00200"},"M16-GAP-00200":{"line":199,"offset":33709,"length":174,"previous":"M16-GAP-00199","next":"M16-GAP-00201"},"M16-GAP-00201":{"line":200,"offset":33883,"length":172,"previous":"M16-GAP-00200","next":"M16-GAP-00202"},"M16-GAP-00202":{"line":201,"offset":34055,"length":170,"previous":"M16-GAP-00201","next":"M16-GAP-00203"},"M16-GAP-00203":{"line":202,"offset":34225,"length":174,"previous":"M16-GAP-00202","next":"M16-GAP-00204"},"M16-GAP-00204":{"line":203,"offset":34399,"length":173,"previous":"M16-GAP-00203","next":"M16-GAP-00205"},"M16-GAP-00205":{"line":204,"offset":34572,"length":170,"previous":"M16-GAP-00204","next":"M16-GAP-00206"},"M16-GAP-00206":{"line":205,"offset":34742,"length":188,"previous":"M16-GAP-00205","next":"M16-GAP-00207"},"M16-GAP-00207":{"line":206,"offset":34930,"length":171,"previous":"M16-GAP-00206","next":"M16-GAP-00208"},"M16-GAP-00208":{"line":207,"offset":35101,"length":185,"previous":"M16-GAP-00207","next":"M16-GAP-00209"},"M16-GAP-00209":{"line":208,"offset":35286,"length":177,"previous":"M16-GAP-00208","next":"M16-GAP-00210"},"M16-GAP-00210":{"line":209,"offset":35463,"length":184,"previous":"M16-GAP-00209","next":"M16-GAP-00211"},"M16-GAP-00211":{"line":210,"offset":35647,"length":171,"previous":"M16-GAP-00210","next":"M16-GAP-00212"},"M16-GAP-00212":{"line":211,"offset":35818,"length":193,"previous":"M16-GAP-00211","next":"M16-GAP-00213"},"M16-GAP-00213":{"line":212,"offset":36011,"length":182,"previous":"M16-GAP-00212","next":"M16-GAP-00214"},"M16-GAP-00214":{"line":213,"offset":36193,"length":182,"previous":"M16-GAP-00213","next":"M16-GAP-00215"},"M16-GAP-00215":{"line":214,"offset":36375,"length":165,"previous":"M16-GAP-00214","next":"M16-GAP-00216"},"M16-GAP-00216":{"line":215,"offset":36540,"length":180,"previous":"M16-GAP-00215","next":"M16-GAP-00217"},"M16-GAP-00217":{"line":216,"offset":36720,"length":174,"previous":"M16-GAP-00216","next":"M16-GAP-00218"},"M16-GAP-00218":{"line":217,"offset":36894,"length":178,"previous":"M16-GAP-00217","next":"M16-GAP-00219"},"M16-GAP-00219":{"line":218,"offset":37072,"length":174,"previous":"M16-GAP-00218","next":"M16-GAP-00220"},"M16-GAP-00220":{"line":219,"offset":37246,"length":173,"previous":"M16-GAP-00219","next":"M16-GAP-00221"},"M16-GAP-00221":{"line":220,"offset":37419,"length":174,"previous":"M16-GAP-00220","next":"M16-GAP-00222"},"M16-GAP-00222":{"line":221,"offset":37593,"length":177,"previous":"M16-GAP-00221","next":"M16-GAP-00223"},"M16-GAP-00223":{"line":222,"offset":37770,"length":188,"previous":"M16-GAP-00222","next":"M16-GAP-00224"},"M16-GAP-00224":{"line":223,"offset":37958,"length":179,"previous":"M16-GAP-00223","next":"M16-GAP-00225"},"M16-GAP-00225":{"line":224,"offset":38137,"length":175,"previous":"M16-GAP-00224","next":"M16-GAP-00226"},"M16-GAP-00226":{"line":225,"offset":38312,"length":177,"previous":"M16-GAP-00225","next":"M16-GAP-00227"},"M16-GAP-00227":{"line":226,"offset":38489,"length":184,"previous":"M16-GAP-00226","next":"M16-GAP-00228"},"M16-GAP-00228":{"line":227,"offset":38673,"length":177,"previous":"M16-GAP-00227","next":"M16-GAP-00229"},"M16-GAP-00229":{"line":228,"offset":38850,"length":179,"previous":"M16-GAP-00228","next":"M16-GAP-00230"},"M16-GAP-00230":{"line":229,"offset":39029,"length":179,"previous":"M16-GAP-00229","next":"M16-GAP-00231"},"M16-GAP-00231":{"line":230,"offset":39208,"length":185,"previous":"M16-GAP-00230","next":"M16-GAP-00232"},"M16-GAP-00232":{"line":231,"offset":39393,"length":181,"previous":"M16-GAP-00231","next":"M16-GAP-00233"},"M16-GAP-00233":{"line":232,"offset":39574,"length":187,"previous":"M16-GAP-00232","next":"M16-GAP-00234"},"M16-GAP-00234":{"line":233,"offset":39761,"length":166,"previous":"M16-GAP-00233","next":"M16-GAP-00235"},"M16-GAP-00235":{"line":234,"offset":39927,"length":168,"previous":"M16-GAP-00234","next":"M16-GAP-00236"},"M16-GAP-00236":{"line":235,"offset":40095,"length":169,"previous":"M16-GAP-00235","next":"M16-GAP-00237"},"M16-GAP-00237":{"line":236,"offset":40264,"length":174,"previous":"M16-GAP-00236","next":"M16-GAP-00238"},"M16-GAP-00238":{"line":237,"offset":40438,"length":176,"previous":"M16-GAP-00237","next":"M16-GAP-00239"},"M16-GAP-00239":{"line":238,"offset":40614,"length":167,"previous":"M16-GAP-00238","next":"M16-GAP-00240"},"M16-GAP-00240":{"line":239,"offset":40781,"length":174,"previous":"M16-GAP-00239","next":"M16-GAP-00241"},"M16-GAP-00241":{"line":240,"offset":40955,"length":172,"previous":"M16-GAP-00240","next":"M16-GAP-00242"},"M16-GAP-00242":{"line":241,"offset":41127,"length":164,"previous":"M16-GAP-00241","next":"M16-GAP-00243"},"M16-GAP-00243":{"line":242,"offset":41291,"length":170,"previous":"M16-GAP-00242","next":"M16-GAP-00244"},"M16-GAP-00244":{"line":243,"offset":41461,"length":164,"previous":"M16-GAP-00243","next":"M16-GAP-00245"},"M16-GAP-00245":{"line":244,"offset":41625,"length":178,"previous":"M16-GAP-00244","next":"M16-GAP-00246"},"M16-GAP-00246":{"line":245,"offset":41803,"length":172,"previous":"M16-GAP-00245","next":"M16-GAP-00247"},"M16-GAP-00247":{"line":246,"offset":41975,"length":170,"previous":"M16-GAP-00246","next":"M16-GAP-00248"},"M16-GAP-00248":{"line":247,"offset":42145,"length":166,"previous":"M16-GAP-00247","next":"M16-GAP-00249"},"M16-GAP-00249":{"line":248,"offset":42311,"length":170,"previous":"M16-GAP-00248","next":"M16-GAP-00250"},"M16-GAP-00250":{"line":249,"offset":42481,"length":170,"previous":"M16-GAP-00249","next":"M16-GAP-00251"},"M16-GAP-00251":{"line":250,"offset":42651,"length":176,"previous":"M16-GAP-00250","next":"M16-GAP-00252"},"M16-GAP-00252":{"line":251,"offset":42827,"length":171,"previous":"M16-GAP-00251","next":"M16-GAP-00253"},"M16-GAP-00253":{"line":252,"offset":42998,"length":173,"previous":"M16-GAP-00252","next":"M16-GAP-00254"},"M16-GAP-00254":{"line":253,"offset":43171,"length":178,"previous":"M16-GAP-00253","next":"M16-GAP-00255"},"M16-GAP-00255":{"line":254,"offset":43349,"length":173,"previous":"M16-GAP-00254","next":"M16-GAP-00256"},"M16-GAP-00256":{"line":255,"offset":43522,"length":171,"previous":"M16-GAP-00255","next":"M16-GAP-00257"},"M16-GAP-00257":{"line":256,"offset":43693,"length":174,"previous":"M16-GAP-00256","next":"M16-GAP-00258"},"M16-GAP-00258":{"line":257,"offset":43867,"length":168,"previous":"M16-GAP-00257","next":"M16-GAP-00259"},"M16-GAP-00259":{"line":258,"offset":44035,"length":178,"previous":"M16-GAP-00258","next":"M16-GAP-00260"},"M16-GAP-00260":{"line":259,"offset":44213,"length":165,"previous":"M16-GAP-00259","next":"M16-GAP-00261"},"M16-GAP-00261":{"line":260,"offset":44378,"length":169,"previous":"M16-GAP-00260","next":"M16-GAP-00262"},"M16-GAP-00262":{"line":261,"offset":44547,"length":176,"previous":"M16-GAP-00261","next":"M16-GAP-00263"},"M16-GAP-00263":{"line":262,"offset":44723,"length":170,"previous":"M16-GAP-00262","next":"M16-GAP-00264"},"M16-GAP-00264":{"line":263,"offset":44893,"length":171,"previous":"M16-GAP-00263","next":"M16-GAP-00265"},"M16-GAP-00265":{"line":264,"offset":45064,"length":172,"previous":"M16-GAP-00264","next":"M16-GAP-00266"},"M16-GAP-00266":{"line":265,"offset":45236,"length":170,"previous":"M16-GAP-00265","next":"M16-GAP-00267"},"M16-GAP-00267":{"line":266,"offset":45406,"length":185,"previous":"M16-GAP-00266","next":"M16-GAP-00268"},"M16-GAP-00268":{"line":267,"offset":45591,"length":171,"previous":"M16-GAP-00267","next":"M16-GAP-00269"},"M16-GAP-00269":{"line":268,"offset":45762,"length":171,"previous":"M16-GAP-00268","next":"M16-GAP-00270"},"M16-GAP-00270":{"line":269,"offset":45933,"length":168,"previous":"M16-GAP-00269","next":"M16-GAP-00271"},"M16-GAP-00271":{"line":270,"offset":46101,"length":169,"previous":"M16-GAP-00270","next":"M16-GAP-00272"},"M16-GAP-00272":{"line":271,"offset":46270,"length":169,"previous":"M16-GAP-00271","next":"M16-GAP-00273"},"M16-GAP-00273":{"line":272,"offset":46439,"length":174,"previous":"M16-GAP-00272","next":"M16-GAP-00274"},"M16-GAP-00274":{"line":273,"offset":46613,"length":170,"previous":"M16-GAP-00273","next":"M16-GAP-00275"},"M16-GAP-00275":{"line":274,"offset":46783,"length":162,"previous":"M16-GAP-00274","next":"M16-GAP-00276"},"M16-GAP-00276":{"line":275,"offset":46945,"length":169,"previous":"M16-GAP-00275","next":"M16-GAP-00277"},"M16-GAP-00277":{"line":276,"offset":47114,"length":172,"previous":"M16-GAP-00276","next":"M16-GAP-00278"},"M16-GAP-00278":{"line":277,"offset":47286,"length":179,"previous":"M16-GAP-00277","next":"M16-GAP-00279"},"M16-GAP-00279":{"line":278,"offset":47465,"length":161,"previous":"M16-GAP-00278","next":"M16-GAP-00280"},"M16-GAP-00280":{"line":279,"offset":47626,"length":168,"previous":"M16-GAP-00279","next":"M16-GAP-00281"},"M16-GAP-00281":{"line":280,"offset":47794,"length":183,"previous":"M16-GAP-00280","next":"M16-GAP-00282"},"M16-GAP-00282":{"line":281,"offset":47977,"length":175,"previous":"M16-GAP-00281","next":"M16-GAP-00283"},"M16-GAP-00283":{"line":282,"offset":48152,"length":164,"previous":"M16-GAP-00282","next":"M16-GAP-00284"},"M16-GAP-00284":{"line":283,"offset":48316,"length":167,"previous":"M16-GAP-00283","next":"M16-GAP-00285"},"M16-GAP-00285":{"line":284,"offset":48483,"length":164,"previous":"M16-GAP-00284","next":"M16-GAP-00286"},"M16-GAP-00286":{"line":285,"offset":48647,"length":164,"previous":"M16-GAP-00285","next":"M16-GAP-00287"},"M16-GAP-00287":{"line":286,"offset":48811,"length":170,"previous":"M16-GAP-00286","next":"M16-GAP-00288"},"M16-GAP-00288":{"line":287,"offset":48981,"length":168,"previous":"M16-GAP-00287","next":"M16-GAP-00289"},"M16-GAP-00289":{"line":288,"offset":49149,"length":165,"previous":"M16-GAP-00288","next":"M16-GAP-00290"},"M16-GAP-00290":{"line":289,"offset":49314,"length":165,"previous":"M16-GAP-00289","next":"M16-GAP-00291"},"M16-GAP-00291":{"line":290,"offset":49479,"length":171,"previous":"M16-GAP-00290","next":"M16-GAP-00292"},"M16-GAP-00292":{"line":291,"offset":49650,"length":169,"previous":"M16-GAP-00291","next":"M16-GAP-00293"},"M16-GAP-00293":{"line":292,"offset":49819,"length":171,"previous":"M16-GAP-00292","next":"M16-GAP-00294"},"M16-GAP-00294":{"line":293,"offset":49990,"length":169,"previous":"M16-GAP-00293","next":"M16-GAP-00295"},"M16-GAP-00295":{"line":294,"offset":50159,"length":176,"previous":"M16-GAP-00294","next":"M16-GAP-00296"},"M16-GAP-00296":{"line":295,"offset":50335,"length":175,"previous":"M16-GAP-00295","next":"M16-GAP-00297"},"M16-GAP-00297":{"line":296,"offset":50510,"length":169,"previous":"M16-GAP-00296","next":"M16-GAP-00298"},"M16-GAP-00298":{"line":297,"offset":50679,"length":167,"previous":"M16-GAP-00297","next":"M16-GAP-00299"},"M16-GAP-00299":{"line":298,"offset":50846,"length":170,"previous":"M16-GAP-00298","next":"M16-GAP-00300"},"M16-GAP-00300":{"line":299,"offset":51016,"length":167,"previous":"M16-GAP-00299","next":"M16-GAP-00301"},"M16-GAP-00301":{"line":300,"offset":51183,"length":172,"previous":"M16-GAP-00300","next":"M16-GAP-00302"},"M16-GAP-00302":{"line":301,"offset":51355,"length":181,"previous":"M16-GAP-00301","next":"M16-GAP-00303"},"M16-GAP-00303":{"line":302,"offset":51536,"length":180,"previous":"M16-GAP-00302","next":"M16-GAP-00304"},"M16-GAP-00304":{"line":303,"offset":51716,"length":171,"previous":"M16-GAP-00303","next":"M16-GAP-00305"},"M16-GAP-00305":{"line":304,"offset":51887,"length":171,"previous":"M16-GAP-00304","next":"M16-GAP-00306"},"M16-GAP-00306":{"line":305,"offset":52058,"length":175,"previous":"M16-GAP-00305","next":"M16-GAP-00307"},"M16-GAP-00307":{"line":306,"offset":52233,"length":170,"previous":"M16-GAP-00306","next":"M16-GAP-00308"},"M16-GAP-00308":{"line":307,"offset":52403,"length":171,"previous":"M16-GAP-00307","next":"M16-GAP-00309"},"M16-GAP-00309":{"line":308,"offset":52574,"length":169,"previous":"M16-GAP-00308","next":"M16-GAP-00310"},"M16-GAP-00310":{"line":309,"offset":52743,"length":170,"previous":"M16-GAP-00309","next":"M16-GAP-00311"},"M16-GAP-00311":{"line":310,"offset":52913,"length":171,"previous":"M16-GAP-00310","next":"M16-GAP-00312"},"M16-GAP-00312":{"line":311,"offset":53084,"length":173,"previous":"M16-GAP-00311","next":"M16-GAP-00313"},"M16-GAP-00313":{"line":312,"offset":53257,"length":165,"previous":"M16-GAP-00312","next":"M16-GAP-00314"},"M16-GAP-00314":{"line":313,"offset":53422,"length":167,"previous":"M16-GAP-00313","next":"M16-GAP-00315"},"M16-GAP-00315":{"line":314,"offset":53589,"length":168,"previous":"M16-GAP-00314","next":"M16-GAP-00316"},"M16-GAP-00316":{"line":315,"offset":53757,"length":179,"previous":"M16-GAP-00315","next":"M16-GAP-00317"},"M16-GAP-00317":{"line":316,"offset":53936,"length":166,"previous":"M16-GAP-00316","next":"M16-GAP-00318"},"M16-GAP-00318":{"line":317,"offset":54102,"length":175,"previous":"M16-GAP-00317","next":"M16-GAP-00319"},"M16-GAP-00319":{"line":318,"offset":54277,"length":171,"previous":"M16-GAP-00318","next":"M16-GAP-00320"},"M16-GAP-00320":{"line":319,"offset":54448,"length":172,"previous":"M16-GAP-00319","next":"M16-GAP-00321"},"M16-GAP-00321":{"line":320,"offset":54620,"length":176,"previous":"M16-GAP-00320","next":"M16-GAP-00322"},"M16-GAP-00322":{"line":321,"offset":54796,"length":170,"previous":"M16-GAP-00321","next":"M16-GAP-00323"},"M16-GAP-00323":{"line":322,"offset":54966,"length":171,"previous":"M16-GAP-00322","next":"M16-GAP-00324"},"M16-GAP-00324":{"line":323,"offset":55137,"length":173,"previous":"M16-GAP-00323","next":"M16-GAP-00325"},"M16-GAP-00325":{"line":324,"offset":55310,"length":168,"previous":"M16-GAP-00324","next":"M16-GAP-00326"},"M16-GAP-00326":{"line":325,"offset":55478,"length":168,"previous":"M16-GAP-00325","next":"M16-GAP-00327"},"M16-GAP-00327":{"line":326,"offset":55646,"length":170,"previous":"M16-GAP-00326","next":"M16-GAP-00328"},"M16-GAP-00328":{"line":327,"offset":55816,"length":172,"previous":"M16-GAP-00327","next":"M16-GAP-00329"},"M16-GAP-00329":{"line":328,"offset":55988,"length":176,"previous":"M16-GAP-00328","next":"M16-GAP-00330"},"M16-GAP-00330":{"line":329,"offset":56164,"length":167,"previous":"M16-GAP-00329","next":"M16-GAP-00331"},"M16-GAP-00331":{"line":330,"offset":56331,"length":174,"previous":"M16-GAP-00330","next":"M16-GAP-00332"},"M16-GAP-00332":{"line":331,"offset":56505,"length":166,"previous":"M16-GAP-00331","next":"M16-GAP-00333"},"M16-GAP-00333":{"line":332,"offset":56671,"length":169,"previous":"M16-GAP-00332","next":"M16-GAP-00334"},"M16-GAP-00334":{"line":333,"offset":56840,"length":168,"previous":"M16-GAP-00333","next":"M16-GAP-00335"},"M16-GAP-00335":{"line":334,"offset":57008,"length":168,"previous":"M16-GAP-00334","next":"M16-GAP-00336"},"M16-GAP-00336":{"line":335,"offset":57176,"length":171,"previous":"M16-GAP-00335","next":"M16-GAP-00337"},"M16-GAP-00337":{"line":336,"offset":57347,"length":171,"previous":"M16-GAP-00336","next":"M16-GAP-00338"},"M16-GAP-00338":{"line":337,"offset":57518,"length":180,"previous":"M16-GAP-00337","next":"M16-GAP-00339"},"M16-GAP-00339":{"line":338,"offset":57698,"length":174,"previous":"M16-GAP-00338","next":"M16-GAP-00340"},"M16-GAP-00340":{"line":339,"offset":57872,"length":169,"previous":"M16-GAP-00339","next":"M16-GAP-00341"},"M16-GAP-00341":{"line":340,"offset":58041,"length":166,"previous":"M16-GAP-00340","next":"M16-GAP-00342"},"M16-GAP-00342":{"line":341,"offset":58207,"length":182,"previous":"M16-GAP-00341","next":"M16-GAP-00343"},"M16-GAP-00343":{"line":342,"offset":58389,"length":174,"previous":"M16-GAP-00342","next":"M16-GAP-00344"},"M16-GAP-00344":{"line":343,"offset":58563,"length":173,"previous":"M16-GAP-00343","next":"M16-GAP-00345"},"M16-GAP-00345":{"line":344,"offset":58736,"length":177,"previous":"M16-GAP-00344","next":"M16-GAP-00346"},"M16-GAP-00346":{"line":345,"offset":58913,"length":168,"previous":"M16-GAP-00345","next":"M16-GAP-00347"},"M16-GAP-00347":{"line":346,"offset":59081,"length":180,"previous":"M16-GAP-00346","next":"M16-GAP-00348"},"M16-GAP-00348":{"line":347,"offset":59261,"length":172,"previous":"M16-GAP-00347","next":"M16-GAP-00349"},"M16-GAP-00349":{"line":348,"offset":59433,"length":170,"previous":"M16-GAP-00348","next":"M16-GAP-00350"},"M16-GAP-00350":{"line":349,"offset":59603,"length":167,"previous":"M16-GAP-00349","next":"M16-GAP-00351"},"M16-GAP-00351":{"line":350,"offset":59770,"length":173,"previous":"M16-GAP-00350","next":"M16-GAP-00352"},"M16-GAP-00352":{"line":351,"offset":59943,"length":167,"previous":"M16-GAP-00351","next":"M16-GAP-00353"},"M16-GAP-00353":{"line":352,"offset":60110,"length":171,"previous":"M16-GAP-00352","next":"M16-GAP-00354"},"M16-GAP-00354":{"line":353,"offset":60281,"length":171,"previous":"M16-GAP-00353","next":"M16-GAP-00355"},"M16-GAP-00355":{"line":354,"offset":60452,"length":177,"previous":"M16-GAP-00354","next":"M16-GAP-00356"},"M16-GAP-00356":{"line":355,"offset":60629,"length":167,"previous":"M16-GAP-00355","next":"M16-GAP-00357"},"M16-GAP-00357":{"line":356,"offset":60796,"length":164,"previous":"M16-GAP-00356","next":"M16-GAP-00358"},"M16-GAP-00358":{"line":357,"offset":60960,"length":183,"previous":"M16-GAP-00357","next":"M16-GAP-00359"},"M16-GAP-00359":{"line":358,"offset":61143,"length":160,"previous":"M16-GAP-00358","next":"M16-GAP-00360"},"M16-GAP-00360":{"line":359,"offset":61303,"length":168,"previous":"M16-GAP-00359","next":"M16-GAP-00361"},"M16-GAP-00361":{"line":360,"offset":61471,"length":164,"previous":"M16-GAP-00360","next":"M16-GAP-00362"},"M16-GAP-00362":{"line":361,"offset":61635,"length":169,"previous":"M16-GAP-00361","next":"M16-GAP-00363"},"M16-GAP-00363":{"line":362,"offset":61804,"length":170,"previous":"M16-GAP-00362","next":"M16-GAP-00364"},"M16-GAP-00364":{"line":363,"offset":61974,"length":162,"previous":"M16-GAP-00363","next":"M16-GAP-00365"},"M16-GAP-00365":{"line":364,"offset":62136,"length":162,"previous":"M16-GAP-00364","next":"M16-GAP-00366"},"M16-GAP-00366":{"line":365,"offset":62298,"length":166,"previous":"M16-GAP-00365","next":"M16-GAP-00367"},"M16-GAP-00367":{"line":366,"offset":62464,"length":166,"previous":"M16-GAP-00366","next":"M16-GAP-00368"},"M16-GAP-00368":{"line":367,"offset":62630,"length":169,"previous":"M16-GAP-00367","next":"M16-GAP-00369"},"M16-GAP-00369":{"line":368,"offset":62799,"length":170,"previous":"M16-GAP-00368","next":"M16-GAP-00370"},"M16-GAP-00370":{"line":369,"offset":62969,"length":168,"previous":"M16-GAP-00369","next":"M16-GAP-00371"},"M16-GAP-00371":{"line":370,"offset":63137,"length":171,"previous":"M16-GAP-00370","next":"M16-GAP-00372"},"M16-GAP-00372":{"line":371,"offset":63308,"length":164,"previous":"M16-GAP-00371","next":"M16-GAP-00373"},"M16-GAP-00373":{"line":372,"offset":63472,"length":166,"previous":"M16-GAP-00372","next":"M16-GAP-00374"},"M16-GAP-00374":{"line":373,"offset":63638,"length":165,"previous":"M16-GAP-00373","next":"M16-GAP-00375"},"M16-GAP-00375":{"line":374,"offset":63803,"length":165,"previous":"M16-GAP-00374","next":"M16-GAP-00376"},"M16-GAP-00376":{"line":375,"offset":63968,"length":172,"previous":"M16-GAP-00375","next":"M16-GAP-00377"},"M16-GAP-00377":{"line":376,"offset":64140,"length":174,"previous":"M16-GAP-00376","next":"M16-GAP-00378"},"M16-GAP-00378":{"line":377,"offset":64314,"length":175,"previous":"M16-GAP-00377","next":"M16-GAP-00379"},"M16-GAP-00379":{"line":378,"offset":64489,"length":179,"previous":"M16-GAP-00378","next":"M16-GAP-00380"},"M16-GAP-00380":{"line":379,"offset":64668,"length":176,"previous":"M16-GAP-00379","next":"M16-GAP-00381"},"M16-GAP-00381":{"line":380,"offset":64844,"length":168,"previous":"M16-GAP-00380","next":"M16-GAP-00382"},"M16-GAP-00382":{"line":381,"offset":65012,"length":174,"previous":"M16-GAP-00381","next":"M16-GAP-00383"},"M16-GAP-00383":{"line":382,"offset":65186,"length":168,"previous":"M16-GAP-00382","next":"M16-GAP-00384"},"M16-GAP-00384":{"line":383,"offset":65354,"length":172,"previous":"M16-GAP-00383","next":"M16-GAP-00385"},"M16-GAP-00385":{"line":384,"offset":65526,"length":175,"previous":"M16-GAP-00384","next":"M16-GAP-00386"},"M16-GAP-00386":{"line":385,"offset":65701,"length":181,"previous":"M16-GAP-00385","next":"M16-GAP-00387"},"M16-GAP-00387":{"line":386,"offset":65882,"length":184,"previous":"M16-GAP-00386","next":"M16-GAP-00388"},"M16-GAP-00388":{"line":387,"offset":66066,"length":184,"previous":"M16-GAP-00387","next":"M16-GAP-00389"},"M16-GAP-00389":{"line":388,"offset":66250,"length":175,"previous":"M16-GAP-00388","next":"M16-GAP-00390"},"M16-GAP-00390":{"line":389,"offset":66425,"length":178,"previous":"M16-GAP-00389","next":"M16-GAP-00391"},"M16-GAP-00391":{"line":390,"offset":66603,"length":172,"previous":"M16-GAP-00390","next":"M16-GAP-00392"},"M16-GAP-00392":{"line":391,"offset":66775,"length":169,"previous":"M16-GAP-00391","next":"M16-GAP-00393"},"M16-GAP-00393":{"line":392,"offset":66944,"length":181,"previous":"M16-GAP-00392","next":"M16-GAP-00394"},"M16-GAP-00394":{"line":393,"offset":67125,"length":179,"previous":"M16-GAP-00393","next":"M16-GAP-00395"},"M16-GAP-00395":{"line":394,"offset":67304,"length":170,"previous":"M16-GAP-00394","next":"M16-GAP-00396"},"M16-GAP-00396":{"line":395,"offset":67474,"length":175,"previous":"M16-GAP-00395","next":"M16-GAP-00397"},"M16-GAP-00397":{"line":396,"offset":67649,"length":178,"previous":"M16-GAP-00396","next":"M16-GAP-00398"},"M16-GAP-00398":{"line":397,"offset":67827,"length":184,"previous":"M16-GAP-00397","next":"M16-GAP-00399"},"M16-GAP-00399":{"line":398,"offset":68011,"length":186,"previous":"M16-GAP-00398","next":"M16-GAP-00400"},"M16-GAP-00400":{"line":399,"offset":68197,"length":164,"previous":"M16-GAP-00399","next":"M16-GAP-00401"},"M16-GAP-00401":{"line":400,"offset":68361,"length":174,"previous":"M16-GAP-00400","next":"M16-GAP-00402"},"M16-GAP-00402":{"line":401,"offset":68535,"length":165,"previous":"M16-GAP-00401","next":"M16-GAP-00403"},"M16-GAP-00403":{"line":402,"offset":68700,"length":164,"previous":"M16-GAP-00402","next":"M16-GAP-00404"},"M16-GAP-00404":{"line":403,"offset":68864,"length":169,"previous":"M16-GAP-00403","next":"M16-GAP-00405"},"M16-GAP-00405":{"line":404,"offset":69033,"length":165,"previous":"M16-GAP-00404","next":"M16-GAP-00406"},"M16-GAP-00406":{"line":405,"offset":69198,"length":168,"previous":"M16-GAP-00405","next":"M16-GAP-00407"},"M16-GAP-00407":{"line":406,"offset":69366,"length":169,"previous":"M16-GAP-00406","next":"M16-GAP-00408"},"M16-GAP-00408":{"line":407,"offset":69535,"length":171,"previous":"M16-GAP-00407","next":"M16-GAP-00409"},"M16-GAP-00409":{"line":408,"offset":69706,"length":167,"previous":"M16-GAP-00408","next":"M16-GAP-00410"},"M16-GAP-00410":{"line":409,"offset":69873,"length":168,"previous":"M16-GAP-00409","next":"M16-GAP-00411"},"M16-GAP-00411":{"line":410,"offset":70041,"length":172,"previous":"M16-GAP-00410","next":"M16-GAP-00412"},"M16-GAP-00412":{"line":411,"offset":70213,"length":174,"previous":"M16-GAP-00411","next":"M16-GAP-00413"},"M16-GAP-00413":{"line":412,"offset":70387,"length":177,"previous":"M16-GAP-00412","next":"M16-GAP-00414"},"M16-GAP-00414":{"line":413,"offset":70564,"length":175,"previous":"M16-GAP-00413","next":"M16-GAP-00415"},"M16-GAP-00415":{"line":414,"offset":70739,"length":177,"previous":"M16-GAP-00414","next":"M16-GAP-00416"},"M16-GAP-00416":{"line":415,"offset":70916,"length":174,"previous":"M16-GAP-00415","next":"M16-GAP-00417"},"M16-GAP-00417":{"line":416,"offset":71090,"length":177,"previous":"M16-GAP-00416","next":"M16-GAP-00418"},"M16-GAP-00418":{"line":417,"offset":71267,"length":180,"previous":"M16-GAP-00417","next":"M16-GAP-00419"},"M16-GAP-00419":{"line":418,"offset":71447,"length":176,"previous":"M16-GAP-00418","next":"M16-GAP-00420"},"M16-GAP-00420":{"line":419,"offset":71623,"length":183,"previous":"M16-GAP-00419","next":"M16-GAP-00421"},"M16-GAP-00421":{"line":420,"offset":71806,"length":180,"previous":"M16-GAP-00420","next":"M16-GAP-00422"},"M16-GAP-00422":{"line":421,"offset":71986,"length":171,"previous":"M16-GAP-00421","next":"M16-GAP-00423"},"M16-GAP-00423":{"line":422,"offset":72157,"length":165,"previous":"M16-GAP-00422","next":"M16-GAP-00424"},"M16-GAP-00424":{"line":423,"offset":72322,"length":164,"previous":"M16-GAP-00423","next":"M16-GAP-00425"},"M16-GAP-00425":{"line":424,"offset":72486,"length":169,"previous":"M16-GAP-00424","next":"M16-GAP-00426"},"M16-GAP-00426":{"line":425,"offset":72655,"length":163,"previous":"M16-GAP-00425","next":"M16-GAP-00427"},"M16-GAP-00427":{"line":426,"offset":72818,"length":173,"previous":"M16-GAP-00426","next":"M16-GAP-00428"},"M16-GAP-00428":{"line":427,"offset":72991,"length":165,"previous":"M16-GAP-00427","next":"M16-GAP-00429"},"M16-GAP-00429":{"line":428,"offset":73156,"length":166,"previous":"M16-GAP-00428","next":"M16-GAP-00430"},"M16-GAP-00430":{"line":429,"offset":73322,"length":173,"previous":"M16-GAP-00429","next":"M16-GAP-00431"},"M16-GAP-00431":{"line":430,"offset":73495,"length":172,"previous":"M16-GAP-00430","next":"M16-GAP-00432"},"M16-GAP-00432":{"line":431,"offset":73667,"length":165,"previous":"M16-GAP-00431","next":"M16-GAP-00433"},"M16-GAP-00433":{"line":432,"offset":73832,"length":181,"previous":"M16-GAP-00432","next":"M16-GAP-00434"},"M16-GAP-00434":{"line":433,"offset":74013,"length":165,"previous":"M16-GAP-00433","next":"M16-GAP-00435"},"M16-GAP-00435":{"line":434,"offset":74178,"length":167,"previous":"M16-GAP-00434","next":"M16-GAP-00436"},"M16-GAP-00436":{"line":435,"offset":74345,"length":163,"previous":"M16-GAP-00435","next":"M16-GAP-00437"},"M16-GAP-00437":{"line":436,"offset":74508,"length":164,"previous":"M16-GAP-00436","next":"M16-GAP-00438"},"M16-GAP-00438":{"line":437,"offset":74672,"length":176,"previous":"M16-GAP-00437","next":"M16-GAP-00439"},"M16-GAP-00439":{"line":438,"offset":74848,"length":169,"previous":"M16-GAP-00438","next":"M16-GAP-00440"},"M16-GAP-00440":{"line":439,"offset":75017,"length":169,"previous":"M16-GAP-00439","next":"M16-GAP-00441"},"M16-GAP-00441":{"line":440,"offset":75186,"length":170,"previous":"M16-GAP-00440","next":"M16-GAP-00442"},"M16-GAP-00442":{"line":441,"offset":75356,"length":167,"previous":"M16-GAP-00441","next":"M16-GAP-00443"},"M16-GAP-00443":{"line":442,"offset":75523,"length":172,"previous":"M16-GAP-00442","next":"M16-GAP-00444"},"M16-GAP-00444":{"line":443,"offset":75695,"length":167,"previous":"M16-GAP-00443","next":"M16-GAP-00445"},"M16-GAP-00445":{"line":444,"offset":75862,"length":183,"previous":"M16-GAP-00444","next":"M16-GAP-00446"},"M16-GAP-00446":{"line":445,"offset":76045,"length":181,"previous":"M16-GAP-00445","next":"M16-GAP-00447"},"M16-GAP-00447":{"line":446,"offset":76226,"length":166,"previous":"M16-GAP-00446","next":"M16-GAP-00448"},"M16-GAP-00448":{"line":447,"offset":76392,"length":178,"previous":"M16-GAP-00447","next":"M16-GAP-00449"},"M16-GAP-00449":{"line":448,"offset":76570,"length":168,"previous":"M16-GAP-00448","next":"M16-GAP-00450"},"M16-GAP-00450":{"line":449,"offset":76738,"length":184,"previous":"M16-GAP-00449","next":"M16-GAP-00451"},"M16-GAP-00451":{"line":450,"offset":76922,"length":185,"previous":"M16-GAP-00450","next":"M16-GAP-00452"},"M16-GAP-00452":{"line":451,"offset":77107,"length":181,"previous":"M16-GAP-00451","next":"M16-GAP-00453"},"M16-GAP-00453":{"line":452,"offset":77288,"length":171,"previous":"M16-GAP-00452","next":"M16-GAP-00454"},"M16-GAP-00454":{"line":453,"offset":77459,"length":175,"previous":"M16-GAP-00453","next":"M16-GAP-00455"},"M16-GAP-00455":{"line":454,"offset":77634,"length":169,"previous":"M16-GAP-00454","next":"M16-GAP-00456"},"M16-GAP-00456":{"line":455,"offset":77803,"length":186,"previous":"M16-GAP-00455","next":"M16-GAP-00457"},"M16-GAP-00457":{"line":456,"offset":77989,"length":188,"previous":"M16-GAP-00456","next":"M16-GAP-00458"},"M16-GAP-00458":{"line":457,"offset":78177,"length":186,"previous":"M16-GAP-00457","next":"M16-GAP-00459"},"M16-GAP-00459":{"line":458,"offset":78363,"length":175,"previous":"M16-GAP-00458","next":"M16-GAP-00460"},"M16-GAP-00460":{"line":459,"offset":78538,"length":177,"previous":"M16-GAP-00459","next":"M16-GAP-00461"},"M16-GAP-00461":{"line":460,"offset":78715,"length":170,"previous":"M16-GAP-00460","next":"M16-GAP-00462"},"M16-GAP-00462":{"line":461,"offset":78885,"length":172,"previous":"M16-GAP-00461","next":"M16-GAP-00463"},"M16-GAP-00463":{"line":462,"offset":79057,"length":171,"previous":"M16-GAP-00462","next":"M16-GAP-00464"},"M16-GAP-00464":{"line":463,"offset":79228,"length":165,"previous":"M16-GAP-00463","next":"M16-GAP-00465"},"M16-GAP-00465":{"line":464,"offset":79393,"length":163,"previous":"M16-GAP-00464","next":"M16-GAP-00466"},"M16-GAP-00466":{"line":465,"offset":79556,"length":171,"previous":"M16-GAP-00465","next":"M16-GAP-00467"},"M16-GAP-00467":{"line":466,"offset":79727,"length":161,"previous":"M16-GAP-00466","next":"M16-GAP-00468"},"M16-GAP-00468":{"line":467,"offset":79888,"length":166,"previous":"M16-GAP-00467","next":"M16-GAP-00469"},"M16-GAP-00469":{"line":468,"offset":80054,"length":171,"previous":"M16-GAP-00468","next":"M16-GAP-00470"},"M16-GAP-00470":{"line":469,"offset":80225,"length":164,"previous":"M16-GAP-00469","next":"M16-GAP-00471"},"M16-GAP-00471":{"line":470,"offset":80389,"length":169,"previous":"M16-GAP-00470","next":"M16-GAP-00472"},"M16-GAP-00472":{"line":471,"offset":80558,"length":172,"previous":"M16-GAP-00471","next":"M16-GAP-00473"},"M16-GAP-00473":{"line":472,"offset":80730,"length":161,"previous":"M16-GAP-00472","next":"M16-GAP-00474"},"M16-GAP-00474":{"line":473,"offset":80891,"length":169,"previous":"M16-GAP-00473","next":"M16-GAP-00475"},"M16-GAP-00475":{"line":474,"offset":81060,"length":176,"previous":"M16-GAP-00474","next":"M16-GAP-00476"},"M16-GAP-00476":{"line":475,"offset":81236,"length":180,"previous":"M16-GAP-00475","next":"M16-GAP-00477"},"M16-GAP-00477":{"line":476,"offset":81416,"length":160,"previous":"M16-GAP-00476","next":"M16-GAP-00478"},"M16-GAP-00478":{"line":477,"offset":81576,"length":184,"previous":"M16-GAP-00477","next":"M16-GAP-00479"},"M16-GAP-00479":{"line":478,"offset":81760,"length":183,"previous":"M16-GAP-00478","next":"M16-GAP-00480"},"M16-GAP-00480":{"line":479,"offset":81943,"length":183,"previous":"M16-GAP-00479","next":"M16-GAP-00481"},"M16-GAP-00481":{"line":480,"offset":82126,"length":182,"previous":"M16-GAP-00480","next":"M16-GAP-00482"},"M16-GAP-00482":{"line":481,"offset":82308,"length":181,"previous":"M16-GAP-00481","next":"M16-GAP-00483"},"M16-GAP-00483":{"line":482,"offset":82489,"length":167,"previous":"M16-GAP-00482","next":"M16-GAP-00484"},"M16-GAP-00484":{"line":483,"offset":82656,"length":163,"previous":"M16-GAP-00483","next":"M16-GAP-00485"},"M16-GAP-00485":{"line":484,"offset":82819,"length":167,"previous":"M16-GAP-00484","next":"M16-GAP-00486"},"M16-GAP-00486":{"line":485,"offset":82986,"length":168,"previous":"M16-GAP-00485","next":"M16-GAP-00487"},"M16-GAP-00487":{"line":486,"offset":83154,"length":170,"previous":"M16-GAP-00486","next":"M16-GAP-00488"},"M16-GAP-00488":{"line":487,"offset":83324,"length":175,"previous":"M16-GAP-00487","next":"M16-GAP-00489"},"M16-GAP-00489":{"line":488,"offset":83499,"length":168,"previous":"M16-GAP-00488","next":"M16-GAP-00490"},"M16-GAP-00490":{"line":489,"offset":83667,"length":168,"previous":"M16-GAP-00489","next":"M16-GAP-00491"},"M16-GAP-00491":{"line":490,"offset":83835,"length":167,"previous":"M16-GAP-00490","next":"M16-GAP-00492"},"M16-GAP-00492":{"line":491,"offset":84002,"length":172,"previous":"M16-GAP-00491","next":"M16-GAP-00493"},"M16-GAP-00493":{"line":492,"offset":84174,"length":170,"previous":"M16-GAP-00492","next":"M16-GAP-00494"},"M16-GAP-00494":{"line":493,"offset":84344,"length":167,"previous":"M16-GAP-00493","next":"M16-GAP-00495"},"M16-GAP-00495":{"line":494,"offset":84511,"length":171,"previous":"M16-GAP-00494","next":"M16-GAP-00496"},"M16-GAP-00496":{"line":495,"offset":84682,"length":165,"previous":"M16-GAP-00495","next":"M16-GAP-00497"},"M16-GAP-00497":{"line":496,"offset":84847,"length":167,"previous":"M16-GAP-00496","next":"M16-GAP-00498"},"M16-GAP-00498":{"line":497,"offset":85014,"length":169,"previous":"M16-GAP-00497","next":"M16-GAP-00499"},"M16-GAP-00499":{"line":498,"offset":85183,"length":175,"previous":"M16-GAP-00498","next":"M16-GAP-00500"},"M16-GAP-00500":{"line":499,"offset":85358,"length":163,"previous":"M16-GAP-00499","next":"M16-GAP-00501"},"M16-GAP-00501":{"line":500,"offset":85521,"length":170,"previous":"M16-GAP-00500","next":"M16-GAP-00502"},"M16-GAP-00502":{"line":501,"offset":85691,"length":168,"previous":"M16-GAP-00501","next":"M16-GAP-00503"},"M16-GAP-00503":{"line":502,"offset":85859,"length":170,"previous":"M16-GAP-00502","next":"M16-GAP-00504"},"M16-GAP-00504":{"line":503,"offset":86029,"length":161,"previous":"M16-GAP-00503","next":"M16-GAP-00505"},"M16-GAP-00505":{"line":504,"offset":86190,"length":172,"previous":"M16-GAP-00504","next":"M16-GAP-00506"},"M16-GAP-00506":{"line":505,"offset":86362,"length":174,"previous":"M16-GAP-00505","next":"M16-GAP-00507"},"M16-GAP-00507":{"line":506,"offset":86536,"length":162,"previous":"M16-GAP-00506","next":"M16-GAP-00508"},"M16-GAP-00508":{"line":507,"offset":86698,"length":166,"previous":"M16-GAP-00507","next":"M16-GAP-00509"},"M16-GAP-00509":{"line":508,"offset":86864,"length":173,"previous":"M16-GAP-00508","next":"M16-GAP-00510"},"M16-GAP-00510":{"line":509,"offset":87037,"length":167,"previous":"M16-GAP-00509","next":"M16-GAP-00511"},"M16-GAP-00511":{"line":510,"offset":87204,"length":167,"previous":"M16-GAP-00510","next":"M16-GAP-00512"},"M16-GAP-00512":{"line":511,"offset":87371,"length":168,"previous":"M16-GAP-00511","next":"M16-GAP-00513"},"M16-GAP-00513":{"line":512,"offset":87539,"length":168,"previous":"M16-GAP-00512","next":"M16-GAP-00514"},"M16-GAP-00514":{"line":513,"offset":87707,"length":171,"previous":"M16-GAP-00513","next":"M16-GAP-00515"},"M16-GAP-00515":{"line":514,"offset":87878,"length":186,"previous":"M16-GAP-00514","next":"M16-GAP-00516"},"M16-GAP-00516":{"line":515,"offset":88064,"length":184,"previous":"M16-GAP-00515","next":"M16-GAP-00517"},"M16-GAP-00517":{"line":516,"offset":88248,"length":172,"previous":"M16-GAP-00516","next":"M16-GAP-00518"},"M16-GAP-00518":{"line":517,"offset":88420,"length":171,"previous":"M16-GAP-00517","next":"M16-GAP-00519"},"M16-GAP-00519":{"line":518,"offset":88591,"length":164,"previous":"M16-GAP-00518","next":"M16-GAP-00520"},"M16-GAP-00520":{"line":519,"offset":88755,"length":162,"previous":"M16-GAP-00519","next":"M16-GAP-00521"},"M16-GAP-00521":{"line":520,"offset":88917,"length":167,"previous":"M16-GAP-00520","next":"M16-GAP-00522"},"M16-GAP-00522":{"line":521,"offset":89084,"length":172,"previous":"M16-GAP-00521","next":"M16-GAP-00523"},"M16-GAP-00523":{"line":522,"offset":89256,"length":165,"previous":"M16-GAP-00522","next":"M16-GAP-00524"},"M16-GAP-00524":{"line":523,"offset":89421,"length":170,"previous":"M16-GAP-00523","next":"M16-GAP-00525"},"M16-GAP-00525":{"line":524,"offset":89591,"length":173,"previous":"M16-GAP-00524","next":"M16-GAP-00526"},"M16-GAP-00526":{"line":525,"offset":89764,"length":161,"previous":"M16-GAP-00525","next":"M16-GAP-00527"},"M16-GAP-00527":{"line":526,"offset":89925,"length":175,"previous":"M16-GAP-00526","next":"M16-GAP-00528"},"M16-GAP-00528":{"line":527,"offset":90100,"length":168,"previous":"M16-GAP-00527","next":"M16-GAP-00529"},"M16-GAP-00529":{"line":528,"offset":90268,"length":169,"previous":"M16-GAP-00528","next":"M16-GAP-00530"},"M16-GAP-00530":{"line":529,"offset":90437,"length":169,"previous":"M16-GAP-00529","next":"M16-GAP-00531"},"M16-GAP-00531":{"line":530,"offset":90606,"length":171,"previous":"M16-GAP-00530","next":"M16-GAP-00532"},"M16-GAP-00532":{"line":531,"offset":90777,"length":176,"previous":"M16-GAP-00531","next":"M16-GAP-00533"},"M16-GAP-00533":{"line":532,"offset":90953,"length":169,"previous":"M16-GAP-00532","next":"M16-GAP-00534"},"M16-GAP-00534":{"line":533,"offset":91122,"length":171,"previous":"M16-GAP-00533","next":"M16-GAP-00535"},"M16-GAP-00535":{"line":534,"offset":91293,"length":166,"previous":"M16-GAP-00534","next":"M16-GAP-00536"},"M16-GAP-00536":{"line":535,"offset":91459,"length":178,"previous":"M16-GAP-00535","next":"M16-GAP-00537"},"M16-GAP-00537":{"line":536,"offset":91637,"length":180,"previous":"M16-GAP-00536","next":"M16-GAP-00538"},"M16-GAP-00538":{"line":537,"offset":91817,"length":163,"previous":"M16-GAP-00537","next":"M16-GAP-00539"},"M16-GAP-00539":{"line":538,"offset":91980,"length":167,"previous":"M16-GAP-00538","next":"M16-GAP-00540"},"M16-GAP-00540":{"line":539,"offset":92147,"length":169,"previous":"M16-GAP-00539","next":"M16-GAP-00541"},"M16-GAP-00541":{"line":540,"offset":92316,"length":174,"previous":"M16-GAP-00540","next":"M16-GAP-00542"},"M16-GAP-00542":{"line":541,"offset":92490,"length":168,"previous":"M16-GAP-00541","next":"M16-GAP-00543"},"M16-GAP-00543":{"line":542,"offset":92658,"length":175,"previous":"M16-GAP-00542","next":"M16-GAP-00544"},"M16-GAP-00544":{"line":543,"offset":92833,"length":170,"previous":"M16-GAP-00543","next":"M16-GAP-00545"},"M16-GAP-00545":{"line":544,"offset":93003,"length":175,"previous":"M16-GAP-00544","next":"M16-GAP-00546"},"M16-GAP-00546":{"line":545,"offset":93178,"length":162,"previous":"M16-GAP-00545","next":"M16-GAP-00547"},"M16-GAP-00547":{"line":546,"offset":93340,"length":171,"previous":"M16-GAP-00546","next":"M16-GAP-00548"},"M16-GAP-00548":{"line":547,"offset":93511,"length":174,"previous":"M16-GAP-00547","next":"M16-GAP-00549"},"M16-GAP-00549":{"line":548,"offset":93685,"length":177,"previous":"M16-GAP-00548","next":"M16-GAP-00550"},"M16-GAP-00550":{"line":549,"offset":93862,"length":169,"previous":"M16-GAP-00549","next":"M16-GAP-00551"},"M16-GAP-00551":{"line":550,"offset":94031,"length":165,"previous":"M16-GAP-00550","next":"M16-GAP-00552"},"M16-GAP-00552":{"line":551,"offset":94196,"length":177,"previous":"M16-GAP-00551","next":"M16-GAP-00553"},"M16-GAP-00553":{"line":552,"offset":94373,"length":177,"previous":"M16-GAP-00552","next":"M16-GAP-00554"},"M16-GAP-00554":{"line":553,"offset":94550,"length":189,"previous":"M16-GAP-00553","next":"M16-GAP-00555"},"M16-GAP-00555":{"line":554,"offset":94739,"length":180,"previous":"M16-GAP-00554","next":"M16-GAP-00556"},"M16-GAP-00556":{"line":555,"offset":94919,"length":185,"previous":"M16-GAP-00555","next":"M16-GAP-00557"},"M16-GAP-00557":{"line":556,"offset":95104,"length":175,"previous":"M16-GAP-00556","next":"M16-GAP-00558"},"M16-GAP-00558":{"line":557,"offset":95279,"length":167,"previous":"M16-GAP-00557","next":"M16-GAP-00559"},"M16-GAP-00559":{"line":558,"offset":95446,"length":158,"previous":"M16-GAP-00558","next":"M16-GAP-00560"},"M16-GAP-00560":{"line":559,"offset":95604,"length":158,"previous":"M16-GAP-00559","next":"M16-GAP-00561"},"M16-GAP-00561":{"line":560,"offset":95762,"length":166,"previous":"M16-GAP-00560","next":"M16-GAP-00562"},"M16-GAP-00562":{"line":561,"offset":95928,"length":163,"previous":"M16-GAP-00561","next":"M16-GAP-00563"},"M16-GAP-00563":{"line":562,"offset":96091,"length":163,"previous":"M16-GAP-00562","next":"M16-GAP-00564"},"M16-GAP-00564":{"line":563,"offset":96254,"length":166,"previous":"M16-GAP-00563","next":"M16-GAP-00565"},"M16-GAP-00565":{"line":564,"offset":96420,"length":167,"previous":"M16-GAP-00564","next":"M16-GAP-00566"},"M16-GAP-00566":{"line":565,"offset":96587,"length":168,"previous":"M16-GAP-00565","next":"M16-GAP-00567"},"M16-GAP-00567":{"line":566,"offset":96755,"length":177,"previous":"M16-GAP-00566","next":"M16-GAP-00568"},"M16-GAP-00568":{"line":567,"offset":96932,"length":177,"previous":"M16-GAP-00567","next":"M16-GAP-00569"},"M16-GAP-00569":{"line":568,"offset":97109,"length":183,"previous":"M16-GAP-00568","next":"M16-GAP-00570"},"M16-GAP-00570":{"line":569,"offset":97292,"length":184,"previous":"M16-GAP-00569","next":"M16-GAP-00571"},"M16-GAP-00571":{"line":570,"offset":97476,"length":180,"previous":"M16-GAP-00570","next":"M16-GAP-00572"},"M16-GAP-00572":{"line":571,"offset":97656,"length":184,"previous":"M16-GAP-00571","next":"M16-GAP-00573"},"M16-GAP-00573":{"line":572,"offset":97840,"length":178,"previous":"M16-GAP-00572","next":"M16-GAP-00574"},"M16-GAP-00574":{"line":573,"offset":98018,"length":182,"previous":"M16-GAP-00573","next":"M16-GAP-00575"},"M16-GAP-00575":{"line":574,"offset":98200,"length":185,"previous":"M16-GAP-00574","next":"M16-GAP-00576"},"M16-GAP-00576":{"line":575,"offset":98385,"length":180,"previous":"M16-GAP-00575","next":"M16-GAP-00577"},"M16-GAP-00577":{"line":576,"offset":98565,"length":178,"previous":"M16-GAP-00576","next":"M16-GAP-00578"},"M16-GAP-00578":{"line":577,"offset":98743,"length":183,"previous":"M16-GAP-00577","next":"M16-GAP-00579"},"M16-GAP-00579":{"line":578,"offset":98926,"length":183,"previous":"M16-GAP-00578","next":"M16-GAP-00580"},"M16-GAP-00580":{"line":579,"offset":99109,"length":182,"previous":"M16-GAP-00579","next":"M16-GAP-00581"},"M16-GAP-00581":{"line":580,"offset":99291,"length":179,"previous":"M16-GAP-00580","next":"M16-GAP-00582"},"M16-GAP-00582":{"line":581,"offset":99470,"length":186,"previous":"M16-GAP-00581","next":"M16-GAP-00583"},"M16-GAP-00583":{"line":582,"offset":99656,"length":186,"previous":"M16-GAP-00582","next":"M16-GAP-00584"},"M16-GAP-00584":{"line":583,"offset":99842,"length":181,"previous":"M16-GAP-00583","next":"M16-GAP-00585"},"M16-GAP-00585":{"line":584,"offset":100023,"length":183,"previous":"M16-GAP-00584","next":"M16-GAP-00586"},"M16-GAP-00586":{"line":585,"offset":100206,"length":175,"previous":"M16-GAP-00585","next":"M16-GAP-00587"},"M16-GAP-00587":{"line":586,"offset":100381,"length":178,"previous":"M16-GAP-00586","next":"M16-GAP-00588"},"M16-GAP-00588":{"line":587,"offset":100559,"length":171,"previous":"M16-GAP-00587","next":"M16-GAP-00589"},"M16-GAP-00589":{"line":588,"offset":100730,"length":175,"previous":"M16-GAP-00588","next":"M16-GAP-00590"},"M16-GAP-00590":{"line":589,"offset":100905,"length":173,"previous":"M16-GAP-00589","next":"M16-GAP-00591"},"M16-GAP-00591":{"line":590,"offset":101078,"length":177,"previous":"M16-GAP-00590","next":"M16-GAP-00592"},"M16-GAP-00592":{"line":591,"offset":101255,"length":174,"previous":"M16-GAP-00591","next":"M16-GAP-00593"},"M16-GAP-00593":{"line":592,"offset":101429,"length":181,"previous":"M16-GAP-00592","next":"M16-GAP-00594"},"M16-GAP-00594":{"line":593,"offset":101610,"length":183,"previous":"M16-GAP-00593","next":"M16-GAP-00595"},"M16-GAP-00595":{"line":594,"offset":101793,"length":189,"previous":"M16-GAP-00594","next":"M16-GAP-00596"},"M16-GAP-00596":{"line":595,"offset":101982,"length":186,"previous":"M16-GAP-00595","next":"M16-GAP-00597"},"M16-GAP-00597":{"line":596,"offset":102168,"length":182,"previous":"M16-GAP-00596","next":"M16-GAP-00598"},"M16-GAP-00598":{"line":597,"offset":102350,"length":179,"previous":"M16-GAP-00597","next":"M16-GAP-00599"},"M16-GAP-00599":{"line":598,"offset":102529,"length":171,"previous":"M16-GAP-00598","next":"M16-GAP-00600"},"M16-GAP-00600":{"line":599,"offset":102700,"length":168,"previous":"M16-GAP-00599","next":"M16-GAP-00601"},"M16-GAP-00601":{"line":600,"offset":102868,"length":172,"previous":"M16-GAP-00600","next":"M16-GAP-00602"},"M16-GAP-00602":{"line":601,"offset":103040,"length":171,"previous":"M16-GAP-00601","next":"M16-GAP-00603"},"M16-GAP-00603":{"line":602,"offset":103211,"length":169,"previous":"M16-GAP-00602","next":"M16-GAP-00604"},"M16-GAP-00604":{"line":603,"offset":103380,"length":162,"previous":"M16-GAP-00603","next":"M16-GAP-00605"},"M16-GAP-00605":{"line":604,"offset":103542,"length":162,"previous":"M16-GAP-00604","next":"M16-GAP-00606"},"M16-GAP-00606":{"line":605,"offset":103704,"length":169,"previous":"M16-GAP-00605","next":"M16-GAP-00607"},"M16-GAP-00607":{"line":606,"offset":103873,"length":175,"previous":"M16-GAP-00606","next":"M16-GAP-00608"},"M16-GAP-00608":{"line":607,"offset":104048,"length":163,"previous":"M16-GAP-00607","next":"M16-GAP-00609"},"M16-GAP-00609":{"line":608,"offset":104211,"length":174,"previous":"M16-GAP-00608","next":"M16-GAP-00610"},"M16-GAP-00610":{"line":609,"offset":104385,"length":163,"previous":"M16-GAP-00609","next":"M16-GAP-00611"},"M16-GAP-00611":{"line":610,"offset":104548,"length":169,"previous":"M16-GAP-00610","next":"M16-GAP-00612"},"M16-GAP-00612":{"line":611,"offset":104717,"length":174,"previous":"M16-GAP-00611","next":"M16-GAP-00613"},"M16-GAP-00613":{"line":612,"offset":104891,"length":163,"previous":"M16-GAP-00612","next":"M16-GAP-00614"},"M16-GAP-00614":{"line":613,"offset":105054,"length":165,"previous":"M16-GAP-00613","next":"M16-GAP-00615"},"M16-GAP-00615":{"line":614,"offset":105219,"length":175,"previous":"M16-GAP-00614","next":"M16-GAP-00616"},"M16-GAP-00616":{"line":615,"offset":105394,"length":175,"previous":"M16-GAP-00615","next":"M16-GAP-00617"},"M16-GAP-00617":{"line":616,"offset":105569,"length":169,"previous":"M16-GAP-00616","next":"M16-GAP-00618"},"M16-GAP-00618":{"line":617,"offset":105738,"length":160,"previous":"M16-GAP-00617","next":"M16-GAP-00619"},"M16-GAP-00619":{"line":618,"offset":105898,"length":164,"previous":"M16-GAP-00618","next":"M16-GAP-00620"},"M16-GAP-00620":{"line":619,"offset":106062,"length":170,"previous":"M16-GAP-00619","next":"M16-GAP-00621"},"M16-GAP-00621":{"line":620,"offset":106232,"length":162,"previous":"M16-GAP-00620","next":"M16-GAP-00622"},"M16-GAP-00622":{"line":621,"offset":106394,"length":164,"previous":"M16-GAP-00621","next":"M16-GAP-00623"},"M16-GAP-00623":{"line":622,"offset":106558,"length":163,"previous":"M16-GAP-00622","next":"M16-GAP-00624"},"M16-GAP-00624":{"line":623,"offset":106721,"length":162,"previous":"M16-GAP-00623","next":"M16-GAP-00625"},"M16-GAP-00625":{"line":624,"offset":106883,"length":176,"previous":"M16-GAP-00624","next":"M16-GAP-00626"},"M16-GAP-00626":{"line":625,"offset":107059,"length":168,"previous":"M16-GAP-00625","next":"M16-GAP-00627"},"M16-GAP-00627":{"line":626,"offset":107227,"length":162,"previous":"M16-GAP-00626","next":"M16-GAP-00628"},"M16-GAP-00628":{"line":627,"offset":107389,"length":166,"previous":"M16-GAP-00627","next":"M16-GAP-00629"},"M16-GAP-00629":{"line":628,"offset":107555,"length":171,"previous":"M16-GAP-00628","next":"M16-GAP-00630"},"M16-GAP-00630":{"line":629,"offset":107726,"length":166,"previous":"M16-GAP-00629","next":"M16-GAP-00631"},"M16-GAP-00631":{"line":630,"offset":107892,"length":167,"previous":"M16-GAP-00630","next":"M16-GAP-00632"},"M16-GAP-00632":{"line":631,"offset":108059,"length":168,"previous":"M16-GAP-00631","next":"M16-GAP-00633"},"M16-GAP-00633":{"line":632,"offset":108227,"length":178,"previous":"M16-GAP-00632","next":"M16-GAP-00634"},"M16-GAP-00634":{"line":633,"offset":108405,"length":168,"previous":"M16-GAP-00633","next":"M16-GAP-00635"},"M16-GAP-00635":{"line":634,"offset":108573,"length":166,"previous":"M16-GAP-00634","next":"M16-GAP-00636"},"M16-GAP-00636":{"line":635,"offset":108739,"length":167,"previous":"M16-GAP-00635","next":"M16-GAP-00637"},"M16-GAP-00637":{"line":636,"offset":108906,"length":172,"previous":"M16-GAP-00636","next":"M16-GAP-00638"},"M16-GAP-00638":{"line":637,"offset":109078,"length":169,"previous":"M16-GAP-00637","next":"M16-GAP-00639"},"M16-GAP-00639":{"line":638,"offset":109247,"length":165,"previous":"M16-GAP-00638","next":"M16-GAP-00640"},"M16-GAP-00640":{"line":639,"offset":109412,"length":166,"previous":"M16-GAP-00639","next":"M16-GAP-00641"},"M16-GAP-00641":{"line":640,"offset":109578,"length":168,"previous":"M16-GAP-00640","next":"M16-GAP-00642"},"M16-GAP-00642":{"line":641,"offset":109746,"length":166,"previous":"M16-GAP-00641","next":"M16-GAP-00643"},"M16-GAP-00643":{"line":642,"offset":109912,"length":167,"previous":"M16-GAP-00642","next":"M16-GAP-00644"},"M16-GAP-00644":{"line":643,"offset":110079,"length":171,"previous":"M16-GAP-00643","next":"M16-GAP-00645"},"M16-GAP-00645":{"line":644,"offset":110250,"length":165,"previous":"M16-GAP-00644","next":"M16-GAP-00646"},"M16-GAP-00646":{"line":645,"offset":110415,"length":166,"previous":"M16-GAP-00645","next":"M16-GAP-00647"},"M16-GAP-00647":{"line":646,"offset":110581,"length":168,"previous":"M16-GAP-00646","next":"M16-GAP-00648"},"M16-GAP-00648":{"line":647,"offset":110749,"length":166,"previous":"M16-GAP-00647","next":"M16-GAP-00649"},"M16-GAP-00649":{"line":648,"offset":110915,"length":167,"previous":"M16-GAP-00648","next":"M16-GAP-00650"},"M16-GAP-00650":{"line":649,"offset":111082,"length":171,"previous":"M16-GAP-00649","next":"M16-GAP-00651"},"M16-GAP-00651":{"line":650,"offset":111253,"length":167,"previous":"M16-GAP-00650","next":"M16-GAP-00652"},"M16-GAP-00652":{"line":651,"offset":111420,"length":167,"previous":"M16-GAP-00651","next":"M16-GAP-00653"},"M16-GAP-00653":{"line":652,"offset":111587,"length":164,"previous":"M16-GAP-00652","next":"M16-GAP-00654"},"M16-GAP-00654":{"line":653,"offset":111751,"length":167,"previous":"M16-GAP-00653","next":"M16-GAP-00655"},"M16-GAP-00655":{"line":654,"offset":111918,"length":172,"previous":"M16-GAP-00654","next":"M16-GAP-00656"},"M16-GAP-00656":{"line":655,"offset":112090,"length":170,"previous":"M16-GAP-00655","next":"M16-GAP-00657"},"M16-GAP-00657":{"line":656,"offset":112260,"length":162,"previous":"M16-GAP-00656","next":"M16-GAP-00658"},"M16-GAP-00658":{"line":657,"offset":112422,"length":166,"previous":"M16-GAP-00657","next":"M16-GAP-00659"},"M16-GAP-00659":{"line":658,"offset":112588,"length":160,"previous":"M16-GAP-00658","next":"M16-GAP-00660"},"M16-GAP-00660":{"line":659,"offset":112748,"length":167,"previous":"M16-GAP-00659","next":"M16-GAP-00661"},"M16-GAP-00661":{"line":660,"offset":112915,"length":160,"previous":"M16-GAP-00660","next":"M16-GAP-00662"},"M16-GAP-00662":{"line":661,"offset":113075,"length":166,"previous":"M16-GAP-00661","next":"M16-GAP-00663"},"M16-GAP-00663":{"line":662,"offset":113241,"length":167,"previous":"M16-GAP-00662","next":"M16-GAP-00664"},"M16-GAP-00664":{"line":663,"offset":113408,"length":169,"previous":"M16-GAP-00663","next":"M16-GAP-00665"},"M16-GAP-00665":{"line":664,"offset":113577,"length":165,"previous":"M16-GAP-00664","next":"M16-GAP-00666"},"M16-GAP-00666":{"line":665,"offset":113742,"length":168,"previous":"M16-GAP-00665","next":"M16-GAP-00667"},"M16-GAP-00667":{"line":666,"offset":113910,"length":165,"previous":"M16-GAP-00666","next":"M16-GAP-00668"},"M16-GAP-00668":{"line":667,"offset":114075,"length":164,"previous":"M16-GAP-00667","next":"M16-GAP-00669"},"M16-GAP-00669":{"line":668,"offset":114239,"length":167,"previous":"M16-GAP-00668","next":"M16-GAP-00670"},"M16-GAP-00670":{"line":669,"offset":114406,"length":175,"previous":"M16-GAP-00669","next":"M16-GAP-00671"},"M16-GAP-00671":{"line":670,"offset":114581,"length":166,"previous":"M16-GAP-00670","next":"M16-GAP-00672"},"M16-GAP-00672":{"line":671,"offset":114747,"length":176,"previous":"M16-GAP-00671","next":"M16-GAP-00673"},"M16-GAP-00673":{"line":672,"offset":114923,"length":167,"previous":"M16-GAP-00672","next":"M16-GAP-00674"},"M16-GAP-00674":{"line":673,"offset":115090,"length":170,"previous":"M16-GAP-00673","next":"M16-GAP-00675"},"M16-GAP-00675":{"line":674,"offset":115260,"length":162,"previous":"M16-GAP-00674","next":"M16-GAP-00676"},"M16-GAP-00676":{"line":675,"offset":115422,"length":173,"previous":"M16-GAP-00675","next":"M16-GAP-00677"},"M16-GAP-00677":{"line":676,"offset":115595,"length":177,"previous":"M16-GAP-00676","next":"M16-GAP-00678"},"M16-GAP-00678":{"line":677,"offset":115772,"length":176,"previous":"M16-GAP-00677","next":"M16-GAP-00679"},"M16-GAP-00679":{"line":678,"offset":115948,"length":179,"previous":"M16-GAP-00678","next":"M16-GAP-00680"},"M16-GAP-00680":{"line":679,"offset":116127,"length":183,"previous":"M16-GAP-00679","next":"M16-GAP-00681"},"M16-GAP-00681":{"line":680,"offset":116310,"length":185,"previous":"M16-GAP-00680","next":"M16-GAP-00682"},"M16-GAP-00682":{"line":681,"offset":116495,"length":182,"previous":"M16-GAP-00681","next":"M16-GAP-00683"},"M16-GAP-00683":{"line":682,"offset":116677,"length":186,"previous":"M16-GAP-00682","next":"M16-GAP-00684"},"M16-GAP-00684":{"line":683,"offset":116863,"length":182,"previous":"M16-GAP-00683","next":"M16-GAP-00685"},"M16-GAP-00685":{"line":684,"offset":117045,"length":174,"previous":"M16-GAP-00684","next":"M16-GAP-00686"},"M16-GAP-00686":{"line":685,"offset":117219,"length":173,"previous":"M16-GAP-00685","next":"M16-GAP-00687"},"M16-GAP-00687":{"line":686,"offset":117392,"length":167,"previous":"M16-GAP-00686","next":"M16-GAP-00688"},"M16-GAP-00688":{"line":687,"offset":117559,"length":189,"previous":"M16-GAP-00687","next":"M16-GAP-00689"},"M16-GAP-00689":{"line":688,"offset":117748,"length":173,"previous":"M16-GAP-00688","next":"M16-GAP-00690"},"M16-GAP-00690":{"line":689,"offset":117921,"length":170,"previous":"M16-GAP-00689","next":"M16-GAP-00691"},"M16-GAP-00691":{"line":690,"offset":118091,"length":179,"previous":"M16-GAP-00690","next":"M16-GAP-00692"},"M16-GAP-00692":{"line":691,"offset":118270,"length":180,"previous":"M16-GAP-00691","next":"M16-GAP-00693"},"M16-GAP-00693":{"line":692,"offset":118450,"length":182,"previous":"M16-GAP-00692","next":"M16-GAP-00694"},"M16-GAP-00694":{"line":693,"offset":118632,"length":166,"previous":"M16-GAP-00693","next":"M16-GAP-00695"},"M16-GAP-00695":{"line":694,"offset":118798,"length":169,"previous":"M16-GAP-00694","next":"M16-GAP-00696"},"M16-GAP-00696":{"line":695,"offset":118967,"length":173,"previous":"M16-GAP-00695","next":"M16-GAP-00697"},"M16-GAP-00697":{"line":696,"offset":119140,"length":170,"previous":"M16-GAP-00696","next":"M16-GAP-00698"},"M16-GAP-00698":{"line":697,"offset":119310,"length":174,"previous":"M16-GAP-00697","next":"M16-GAP-00699"},"M16-GAP-00699":{"line":698,"offset":119484,"length":166,"previous":"M16-GAP-00698","next":"M16-GAP-00700"},"M16-GAP-00700":{"line":699,"offset":119650,"length":175,"previous":"M16-GAP-00699","next":"M16-GAP-00701"},"M16-GAP-00701":{"line":700,"offset":119825,"length":162,"previous":"M16-GAP-00700","next":"M16-GAP-00702"},"M16-GAP-00702":{"line":701,"offset":119987,"length":169,"previous":"M16-GAP-00701","next":"M16-GAP-00703"},"M16-GAP-00703":{"line":702,"offset":120156,"length":168,"previous":"M16-GAP-00702","next":"M16-GAP-00704"},"M16-GAP-00704":{"line":703,"offset":120324,"length":161,"previous":"M16-GAP-00703","next":"M16-GAP-00705"},"M16-GAP-00705":{"line":704,"offset":120485,"length":167,"previous":"M16-GAP-00704","next":"M16-GAP-00706"},"M16-GAP-00706":{"line":705,"offset":120652,"length":165,"previous":"M16-GAP-00705","next":"M16-GAP-00707"},"M16-GAP-00707":{"line":706,"offset":120817,"length":163,"previous":"M16-GAP-00706","next":"M16-GAP-00708"},"M16-GAP-00708":{"line":707,"offset":120980,"length":178,"previous":"M16-GAP-00707","next":"M16-GAP-00709"},"M16-GAP-00709":{"line":708,"offset":121158,"length":178,"previous":"M16-GAP-00708","next":"M16-GAP-00710"},"M16-GAP-00710":{"line":709,"offset":121336,"length":179,"previous":"M16-GAP-00709","next":"M16-GAP-00711"},"M16-GAP-00711":{"line":710,"offset":121515,"length":166,"previous":"M16-GAP-00710","next":"M16-GAP-00712"},"M16-GAP-00712":{"line":711,"offset":121681,"length":171,"previous":"M16-GAP-00711","next":"M16-GAP-00713"},"M16-GAP-00713":{"line":712,"offset":121852,"length":161,"previous":"M16-GAP-00712","next":"M16-GAP-00714"},"M16-GAP-00714":{"line":713,"offset":122013,"length":168,"previous":"M16-GAP-00713","next":"M16-GAP-00715"},"M16-GAP-00715":{"line":714,"offset":122181,"length":173,"previous":"M16-GAP-00714","next":"M16-GAP-00716"},"M16-GAP-00716":{"line":715,"offset":122354,"length":169,"previous":"M16-GAP-00715","next":"M16-GAP-00717"},"M16-GAP-00717":{"line":716,"offset":122523,"length":175,"previous":"M16-GAP-00716","next":"M16-GAP-00718"},"M16-GAP-00718":{"line":717,"offset":122698,"length":170,"previous":"M16-GAP-00717","next":"M16-GAP-00719"},"M16-GAP-00719":{"line":718,"offset":122868,"length":171,"previous":"M16-GAP-00718","next":"M16-GAP-00720"},"M16-GAP-00720":{"line":719,"offset":123039,"length":173,"previous":"M16-GAP-00719","next":"M16-GAP-00721"},"M16-GAP-00721":{"line":720,"offset":123212,"length":172,"previous":"M16-GAP-00720","next":"M16-GAP-00722"},"M16-GAP-00722":{"line":721,"offset":123384,"length":167,"previous":"M16-GAP-00721","next":"M16-GAP-00723"},"M16-GAP-00723":{"line":722,"offset":123551,"length":172,"previous":"M16-GAP-00722","next":"M16-GAP-00724"},"M16-GAP-00724":{"line":723,"offset":123723,"length":175,"previous":"M16-GAP-00723","next":"M16-GAP-00725"},"M16-GAP-00725":{"line":724,"offset":123898,"length":176,"previous":"M16-GAP-00724","next":"M16-GAP-00726"},"M16-GAP-00726":{"line":725,"offset":124074,"length":168,"previous":"M16-GAP-00725","next":"M16-GAP-00727"},"M16-GAP-00727":{"line":726,"offset":124242,"length":161,"previous":"M16-GAP-00726","next":"M16-GAP-00728"},"M16-GAP-00728":{"line":727,"offset":124403,"length":175,"previous":"M16-GAP-00727","next":"M16-GAP-00729"},"M16-GAP-00729":{"line":728,"offset":124578,"length":172,"previous":"M16-GAP-00728","next":"M16-GAP-00730"},"M16-GAP-00730":{"line":729,"offset":124750,"length":170,"previous":"M16-GAP-00729","next":"M16-GAP-00731"},"M16-GAP-00731":{"line":730,"offset":124920,"length":172,"previous":"M16-GAP-00730","next":"M16-GAP-00732"},"M16-GAP-00732":{"line":731,"offset":125092,"length":167,"previous":"M16-GAP-00731","next":"M16-GAP-00733"},"M16-GAP-00733":{"line":732,"offset":125259,"length":168,"previous":"M16-GAP-00732","next":"M16-GAP-00734"},"M16-GAP-00734":{"line":733,"offset":125427,"length":163,"previous":"M16-GAP-00733","next":"M16-GAP-00735"},"M16-GAP-00735":{"line":734,"offset":125590,"length":162,"previous":"M16-GAP-00734","next":"M16-GAP-00736"},"M16-GAP-00736":{"line":735,"offset":125752,"length":173,"previous":"M16-GAP-00735","next":"M16-GAP-00737"},"M16-GAP-00737":{"line":736,"offset":125925,"length":166,"previous":"M16-GAP-00736","next":"M16-GAP-00738"},"M16-GAP-00738":{"line":737,"offset":126091,"length":163,"previous":"M16-GAP-00737","next":"M16-GAP-00739"},"M16-GAP-00739":{"line":738,"offset":126254,"length":172,"previous":"M16-GAP-00738","next":"M16-GAP-00740"},"M16-GAP-00740":{"line":739,"offset":126426,"length":170,"previous":"M16-GAP-00739","next":"M16-GAP-00741"},"M16-GAP-00741":{"line":740,"offset":126596,"length":176,"previous":"M16-GAP-00740","next":"M16-GAP-00742"},"M16-GAP-00742":{"line":741,"offset":126772,"length":167,"previous":"M16-GAP-00741","next":"M16-GAP-00743"},"M16-GAP-00743":{"line":742,"offset":126939,"length":167,"previous":"M16-GAP-00742","next":"M16-GAP-00744"},"M16-GAP-00744":{"line":743,"offset":127106,"length":170,"previous":"M16-GAP-00743","next":"M16-GAP-00745"},"M16-GAP-00745":{"line":744,"offset":127276,"length":170,"previous":"M16-GAP-00744","next":"M16-GAP-00746"},"M16-GAP-00746":{"line":745,"offset":127446,"length":175,"previous":"M16-GAP-00745","next":"M16-GAP-00747"},"M16-GAP-00747":{"line":746,"offset":127621,"length":169,"previous":"M16-GAP-00746","next":"M16-GAP-00748"},"M16-GAP-00748":{"line":747,"offset":127790,"length":173,"previous":"M16-GAP-00747","next":"M16-GAP-00749"},"M16-GAP-00749":{"line":748,"offset":127963,"length":168,"previous":"M16-GAP-00748","next":"M16-GAP-00750"},"M16-GAP-00750":{"line":749,"offset":128131,"length":170,"previous":"M16-GAP-00749","next":"M16-GAP-00751"},"M16-GAP-00751":{"line":750,"offset":128301,"length":168,"previous":"M16-GAP-00750","next":"M16-GAP-00752"},"M16-GAP-00752":{"line":751,"offset":128469,"length":162,"previous":"M16-GAP-00751","next":"M16-GAP-00753"},"M16-GAP-00753":{"line":752,"offset":128631,"length":163,"previous":"M16-GAP-00752","next":"M16-GAP-00754"},"M16-GAP-00754":{"line":753,"offset":128794,"length":161,"previous":"M16-GAP-00753","next":"M16-GAP-00755"},"M16-GAP-00755":{"line":754,"offset":128955,"length":174,"previous":"M16-GAP-00754","next":"M16-GAP-00756"},"M16-GAP-00756":{"line":755,"offset":129129,"length":173,"previous":"M16-GAP-00755","next":"M16-GAP-00757"},"M16-GAP-00757":{"line":756,"offset":129302,"length":168,"previous":"M16-GAP-00756","next":"M16-GAP-00758"},"M16-GAP-00758":{"line":757,"offset":129470,"length":165,"previous":"M16-GAP-00757","next":"M16-GAP-00759"},"M16-GAP-00759":{"line":758,"offset":129635,"length":167,"previous":"M16-GAP-00758","next":"M16-GAP-00760"},"M16-GAP-00760":{"line":759,"offset":129802,"length":170,"previous":"M16-GAP-00759","next":"M16-GAP-00761"},"M16-GAP-00761":{"line":760,"offset":129972,"length":184,"previous":"M16-GAP-00760","next":"M16-GAP-00762"},"M16-GAP-00762":{"line":761,"offset":130156,"length":193,"previous":"M16-GAP-00761","next":"M16-GAP-00763"},"M16-GAP-00763":{"line":762,"offset":130349,"length":177,"previous":"M16-GAP-00762","next":"M16-GAP-00764"},"M16-GAP-00764":{"line":763,"offset":130526,"length":173,"previous":"M16-GAP-00763","next":"M16-GAP-00765"},"M16-GAP-00765":{"line":764,"offset":130699,"length":176,"previous":"M16-GAP-00764","next":"M16-GAP-00766"},"M16-GAP-00766":{"line":765,"offset":130875,"length":183,"previous":"M16-GAP-00765","next":"M16-GAP-00767"},"M16-GAP-00767":{"line":766,"offset":131058,"length":169,"previous":"M16-GAP-00766","next":"M16-GAP-00768"},"M16-GAP-00768":{"line":767,"offset":131227,"length":177,"previous":"M16-GAP-00767","next":"M16-GAP-00769"},"M16-GAP-00769":{"line":768,"offset":131404,"length":171,"previous":"M16-GAP-00768","next":"M16-GAP-00770"},"M16-GAP-00770":{"line":769,"offset":131575,"length":181,"previous":"M16-GAP-00769","next":"M16-GAP-00771"},"M16-GAP-00771":{"line":770,"offset":131756,"length":177,"previous":"M16-GAP-00770","next":"M16-GAP-00772"},"M16-GAP-00772":{"line":771,"offset":131933,"length":173,"previous":"M16-GAP-00771","next":"M16-GAP-00773"},"M16-GAP-00773":{"line":772,"offset":132106,"length":174,"previous":"M16-GAP-00772","next":"M16-GAP-00774"},"M16-GAP-00774":{"line":773,"offset":132280,"length":179,"previous":"M16-GAP-00773","next":"M16-GAP-00775"},"M16-GAP-00775":{"line":774,"offset":132459,"length":174,"previous":"M16-GAP-00774","next":"M16-GAP-00776"},"M16-GAP-00776":{"line":775,"offset":132633,"length":176,"previous":"M16-GAP-00775","next":"M16-GAP-00777"},"M16-GAP-00777":{"line":776,"offset":132809,"length":172,"previous":"M16-GAP-00776","next":"M16-GAP-00778"},"M16-GAP-00778":{"line":777,"offset":132981,"length":177,"previous":"M16-GAP-00777","next":"M16-GAP-00779"},"M16-GAP-00779":{"line":778,"offset":133158,"length":169,"previous":"M16-GAP-00778","next":"M16-GAP-00780"},"M16-GAP-00780":{"line":779,"offset":133327,"length":186,"previous":"M16-GAP-00779","next":"M16-GAP-00781"},"M16-GAP-00781":{"line":780,"offset":133513,"length":180,"previous":"M16-GAP-00780","next":"M16-GAP-00782"},"M16-GAP-00782":{"line":781,"offset":133693,"length":183,"previous":"M16-GAP-00781","next":"M16-GAP-00783"},"M16-GAP-00783":{"line":782,"offset":133876,"length":176,"previous":"M16-GAP-00782","next":"M16-GAP-00784"},"M16-GAP-00784":{"line":783,"offset":134052,"length":185,"previous":"M16-GAP-00783","next":"M16-GAP-00785"},"M16-GAP-00785":{"line":784,"offset":134237,"length":175,"previous":"M16-GAP-00784","next":"M16-GAP-00786"},"M16-GAP-00786":{"line":785,"offset":134412,"length":179,"previous":"M16-GAP-00785","next":"M16-GAP-00787"},"M16-GAP-00787":{"line":786,"offset":134591,"length":177,"previous":"M16-GAP-00786","next":"M16-GAP-00788"},"M16-GAP-00788":{"line":787,"offset":134768,"length":174,"previous":"M16-GAP-00787","next":"M16-GAP-00789"},"M16-GAP-00789":{"line":788,"offset":134942,"length":180,"previous":"M16-GAP-00788","next":"M16-GAP-00790"},"M16-GAP-00790":{"line":789,"offset":135122,"length":187,"previous":"M16-GAP-00789","next":"M16-GAP-00791"},"M16-GAP-00791":{"line":790,"offset":135309,"length":180,"previous":"M16-GAP-00790","next":"M16-GAP-00792"},"M16-GAP-00792":{"line":791,"offset":135489,"length":186,"previous":"M16-GAP-00791","next":"M16-GAP-00793"},"M16-GAP-00793":{"line":792,"offset":135675,"length":183,"previous":"M16-GAP-00792","next":"M16-GAP-00794"},"M16-GAP-00794":{"line":793,"offset":135858,"length":175,"previous":"M16-GAP-00793","next":"M16-GAP-00795"},"M16-GAP-00795":{"line":794,"offset":136033,"length":178,"previous":"M16-GAP-00794","next":"M16-GAP-00796"},"M16-GAP-00796":{"line":795,"offset":136211,"length":179,"previous":"M16-GAP-00795","next":"M16-GAP-00797"},"M16-GAP-00797":{"line":796,"offset":136390,"length":179,"previous":"M16-GAP-00796","next":"M16-GAP-00798"},"M16-GAP-00798":{"line":797,"offset":136569,"length":182,"previous":"M16-GAP-00797","next":"M16-GAP-00799"},"M16-GAP-00799":{"line":798,"offset":136751,"length":183,"previous":"M16-GAP-00798","next":"M16-GAP-00800"},"M16-GAP-00800":{"line":799,"offset":136934,"length":176,"previous":"M16-GAP-00799","next":"M16-GAP-00801"},"M16-GAP-00801":{"line":800,"offset":137110,"length":175,"previous":"M16-GAP-00800","next":"M16-GAP-00802"},"M16-GAP-00802":{"line":801,"offset":137285,"length":177,"previous":"M16-GAP-00801","next":"M16-GAP-00803"},"M16-GAP-00803":{"line":802,"offset":137462,"length":177,"previous":"M16-GAP-00802","next":"M16-GAP-00804"},"M16-GAP-00804":{"line":803,"offset":137639,"length":188,"previous":"M16-GAP-00803","next":"M16-GAP-00805"},"M16-GAP-00805":{"line":804,"offset":137827,"length":178,"previous":"M16-GAP-00804","next":"M16-GAP-00806"},"M16-GAP-00806":{"line":805,"offset":138005,"length":181,"previous":"M16-GAP-00805","next":"M16-GAP-00807"},"M16-GAP-00807":{"line":806,"offset":138186,"length":182,"previous":"M16-GAP-00806","next":"M16-GAP-00808"},"M16-GAP-00808":{"line":807,"offset":138368,"length":189,"previous":"M16-GAP-00807","next":"M16-GAP-00809"},"M16-GAP-00809":{"line":808,"offset":138557,"length":185,"previous":"M16-GAP-00808","next":"M16-GAP-00810"},"M16-GAP-00810":{"line":809,"offset":138742,"length":180,"previous":"M16-GAP-00809","next":"M16-GAP-00811"},"M16-GAP-00811":{"line":810,"offset":138922,"length":180,"previous":"M16-GAP-00810","next":"M16-GAP-00812"},"M16-GAP-00812":{"line":811,"offset":139102,"length":184,"previous":"M16-GAP-00811","next":"M16-GAP-00813"},"M16-GAP-00813":{"line":812,"offset":139286,"length":178,"previous":"M16-GAP-00812","next":"M16-GAP-00814"},"M16-GAP-00814":{"line":813,"offset":139464,"length":172,"previous":"M16-GAP-00813","next":"M16-GAP-00815"},"M16-GAP-00815":{"line":814,"offset":139636,"length":181,"previous":"M16-GAP-00814","next":"M16-GAP-00816"},"M16-GAP-00816":{"line":815,"offset":139817,"length":170,"previous":"M16-GAP-00815","next":"M16-GAP-00817"},"M16-GAP-00817":{"line":816,"offset":139987,"length":168,"previous":"M16-GAP-00816","next":"M16-GAP-00818"},"M16-GAP-00818":{"line":817,"offset":140155,"length":178,"previous":"M16-GAP-00817","next":"M16-GAP-00819"},"M16-GAP-00819":{"line":818,"offset":140333,"length":178,"previous":"M16-GAP-00818","next":"M16-GAP-00820"},"M16-GAP-00820":{"line":819,"offset":140511,"length":181,"previous":"M16-GAP-00819","next":"M16-GAP-00821"},"M16-GAP-00821":{"line":820,"offset":140692,"length":180,"previous":"M16-GAP-00820","next":"M16-GAP-00822"},"M16-GAP-00822":{"line":821,"offset":140872,"length":179,"previous":"M16-GAP-00821","next":"M16-GAP-00823"},"M16-GAP-00823":{"line":822,"offset":141051,"length":183,"previous":"M16-GAP-00822","next":"M16-GAP-00824"},"M16-GAP-00824":{"line":823,"offset":141234,"length":188,"previous":"M16-GAP-00823","next":"M16-GAP-00825"},"M16-GAP-00825":{"line":824,"offset":141422,"length":183,"previous":"M16-GAP-00824","next":"M16-GAP-00826"},"M16-GAP-00826":{"line":825,"offset":141605,"length":172,"previous":"M16-GAP-00825","next":"M16-GAP-00827"},"M16-GAP-00827":{"line":826,"offset":141777,"length":174,"previous":"M16-GAP-00826","next":"M16-GAP-00828"},"M16-GAP-00828":{"line":827,"offset":141951,"length":174,"previous":"M16-GAP-00827","next":"M16-GAP-00829"},"M16-GAP-00829":{"line":828,"offset":142125,"length":177,"previous":"M16-GAP-00828","next":"M16-GAP-00830"},"M16-GAP-00830":{"line":829,"offset":142302,"length":182,"previous":"M16-GAP-00829","next":"M16-GAP-00831"},"M16-GAP-00831":{"line":830,"offset":142484,"length":175,"previous":"M16-GAP-00830","next":"M16-GAP-00832"},"M16-GAP-00832":{"line":831,"offset":142659,"length":181,"previous":"M16-GAP-00831","next":"M16-GAP-00833"},"M16-GAP-00833":{"line":832,"offset":142840,"length":186,"previous":"M16-GAP-00832","next":"M16-GAP-00834"},"M16-GAP-00834":{"line":833,"offset":143026,"length":176,"previous":"M16-GAP-00833","next":"M16-GAP-00835"},"M16-GAP-00835":{"line":834,"offset":143202,"length":176,"previous":"M16-GAP-00834","next":"M16-GAP-00836"},"M16-GAP-00836":{"line":835,"offset":143378,"length":176,"previous":"M16-GAP-00835","next":"M16-GAP-00837"},"M16-GAP-00837":{"line":836,"offset":143554,"length":178,"previous":"M16-GAP-00836","next":"M16-GAP-00838"},"M16-GAP-00838":{"line":837,"offset":143732,"length":176,"previous":"M16-GAP-00837","next":"M16-GAP-00839"},"M16-GAP-00839":{"line":838,"offset":143908,"length":178,"previous":"M16-GAP-00838","next":"M16-GAP-00840"},"M16-GAP-00840":{"line":839,"offset":144086,"length":179,"previous":"M16-GAP-00839","next":"M16-GAP-00841"},"M16-GAP-00841":{"line":840,"offset":144265,"length":173,"previous":"M16-GAP-00840","next":"M16-GAP-00842"},"M16-GAP-00842":{"line":841,"offset":144438,"length":179,"previous":"M16-GAP-00841","next":"M16-GAP-00843"},"M16-GAP-00843":{"line":842,"offset":144617,"length":184,"previous":"M16-GAP-00842","next":"M16-GAP-00844"},"M16-GAP-00844":{"line":843,"offset":144801,"length":180,"previous":"M16-GAP-00843","next":"M16-GAP-00845"},"M16-GAP-00845":{"line":844,"offset":144981,"length":185,"previous":"M16-GAP-00844","next":"M16-GAP-00846"},"M16-GAP-00846":{"line":845,"offset":145166,"length":179,"previous":"M16-GAP-00845","next":"M16-GAP-00847"},"M16-GAP-00847":{"line":846,"offset":145345,"length":180,"previous":"M16-GAP-00846","next":"M16-GAP-00848"},"M16-GAP-00848":{"line":847,"offset":145525,"length":177,"previous":"M16-GAP-00847","next":"M16-GAP-00849"},"M16-GAP-00849":{"line":848,"offset":145702,"length":183,"previous":"M16-GAP-00848","next":"M16-GAP-00850"},"M16-GAP-00850":{"line":849,"offset":145885,"length":180,"previous":"M16-GAP-00849","next":"M16-GAP-00851"},"M16-GAP-00851":{"line":850,"offset":146065,"length":180,"previous":"M16-GAP-00850","next":"M16-GAP-00852"},"M16-GAP-00852":{"line":851,"offset":146245,"length":184,"previous":"M16-GAP-00851","next":"M16-GAP-00853"},"M16-GAP-00853":{"line":852,"offset":146429,"length":186,"previous":"M16-GAP-00852","next":"M16-GAP-00854"},"M16-GAP-00854":{"line":853,"offset":146615,"length":188,"previous":"M16-GAP-00853","next":"M16-GAP-00855"},"M16-GAP-00855":{"line":854,"offset":146803,"length":179,"previous":"M16-GAP-00854","next":"M16-GAP-00856"},"M16-GAP-00856":{"line":855,"offset":146982,"length":177,"previous":"M16-GAP-00855","next":"M16-GAP-00857"},"M16-GAP-00857":{"line":856,"offset":147159,"length":184,"previous":"M16-GAP-00856","next":"M16-GAP-00858"},"M16-GAP-00858":{"line":857,"offset":147343,"length":189,"previous":"M16-GAP-00857","next":"M16-GAP-00859"},"M16-GAP-00859":{"line":858,"offset":147532,"length":190,"previous":"M16-GAP-00858","next":"M16-GAP-00860"},"M16-GAP-00860":{"line":859,"offset":147722,"length":180,"previous":"M16-GAP-00859","next":"M16-GAP-00861"},"M16-GAP-00861":{"line":860,"offset":147902,"length":178,"previous":"M16-GAP-00860","next":"M16-GAP-00862"},"M16-GAP-00862":{"line":861,"offset":148080,"length":177,"previous":"M16-GAP-00861","next":"M16-GAP-00863"},"M16-GAP-00863":{"line":862,"offset":148257,"length":181,"previous":"M16-GAP-00862","next":"M16-GAP-00864"},"M16-GAP-00864":{"line":863,"offset":148438,"length":188,"previous":"M16-GAP-00863","next":"M16-GAP-00865"},"M16-GAP-00865":{"line":864,"offset":148626,"length":188,"previous":"M16-GAP-00864","next":"M16-GAP-00866"},"M16-GAP-00866":{"line":865,"offset":148814,"length":176,"previous":"M16-GAP-00865","next":"M16-GAP-00867"},"M16-GAP-00867":{"line":866,"offset":148990,"length":181,"previous":"M16-GAP-00866","next":"M16-GAP-00868"},"M16-GAP-00868":{"line":867,"offset":149171,"length":176,"previous":"M16-GAP-00867","next":"M16-GAP-00869"},"M16-GAP-00869":{"line":868,"offset":149347,"length":184,"previous":"M16-GAP-00868","next":"M16-GAP-00870"},"M16-GAP-00870":{"line":869,"offset":149531,"length":197,"previous":"M16-GAP-00869","next":"M16-GAP-00871"},"M16-GAP-00871":{"line":870,"offset":149728,"length":181,"previous":"M16-GAP-00870","next":"M16-GAP-00872"},"M16-GAP-00872":{"line":871,"offset":149909,"length":184,"previous":"M16-GAP-00871","next":"M16-GAP-00873"},"M16-GAP-00873":{"line":872,"offset":150093,"length":184,"previous":"M16-GAP-00872","next":"M16-GAP-00874"},"M16-GAP-00874":{"line":873,"offset":150277,"length":181,"previous":"M16-GAP-00873","next":"M16-GAP-00875"},"M16-GAP-00875":{"line":874,"offset":150458,"length":187,"previous":"M16-GAP-00874","next":"M16-GAP-00876"},"M16-GAP-00876":{"line":875,"offset":150645,"length":191,"previous":"M16-GAP-00875","next":"M16-GAP-00877"},"M16-GAP-00877":{"line":876,"offset":150836,"length":184,"previous":"M16-GAP-00876","next":"M16-GAP-00878"},"M16-GAP-00878":{"line":877,"offset":151020,"length":182,"previous":"M16-GAP-00877","next":"M16-GAP-00879"},"M16-GAP-00879":{"line":878,"offset":151202,"length":184,"previous":"M16-GAP-00878","next":"M16-GAP-00880"},"M16-GAP-00880":{"line":879,"offset":151386,"length":178,"previous":"M16-GAP-00879","next":"M16-GAP-00881"},"M16-GAP-00881":{"line":880,"offset":151564,"length":178,"previous":"M16-GAP-00880","next":"M16-GAP-00882"},"M16-GAP-00882":{"line":881,"offset":151742,"length":188,"previous":"M16-GAP-00881","next":"M16-GAP-00883"},"M16-GAP-00883":{"line":882,"offset":151930,"length":182,"previous":"M16-GAP-00882","next":"M16-GAP-00884"},"M16-GAP-00884":{"line":883,"offset":152112,"length":172,"previous":"M16-GAP-00883","next":"M16-GAP-00885"},"M16-GAP-00885":{"line":884,"offset":152284,"length":169,"previous":"M16-GAP-00884","next":"M16-GAP-00886"},"M16-GAP-00886":{"line":885,"offset":152453,"length":176,"previous":"M16-GAP-00885","next":"M16-GAP-00887"},"M16-GAP-00887":{"line":886,"offset":152629,"length":174,"previous":"M16-GAP-00886","next":"M16-GAP-00888"},"M16-GAP-00888":{"line":887,"offset":152803,"length":171,"previous":"M16-GAP-00887","next":"M16-GAP-00889"},"M16-GAP-00889":{"line":888,"offset":152974,"length":172,"previous":"M16-GAP-00888","next":"M16-GAP-00890"},"M16-GAP-00890":{"line":889,"offset":153146,"length":178,"previous":"M16-GAP-00889","next":"M16-GAP-00891"},"M16-GAP-00891":{"line":890,"offset":153324,"length":173,"previous":"M16-GAP-00890","next":"M16-GAP-00892"},"M16-GAP-00892":{"line":891,"offset":153497,"length":174,"previous":"M16-GAP-00891","next":"M16-GAP-00893"},"M16-GAP-00893":{"line":892,"offset":153671,"length":170,"previous":"M16-GAP-00892","next":"M16-GAP-00894"},"M16-GAP-00894":{"line":893,"offset":153841,"length":168,"previous":"M16-GAP-00893","next":"M16-GAP-00895"},"M16-GAP-00895":{"line":894,"offset":154009,"length":161,"previous":"M16-GAP-00894","next":"M16-GAP-00896"},"M16-GAP-00896":{"line":895,"offset":154170,"length":178,"previous":"M16-GAP-00895","next":"M16-GAP-00897"},"M16-GAP-00897":{"line":896,"offset":154348,"length":163,"previous":"M16-GAP-00896","next":"M16-GAP-00898"},"M16-GAP-00898":{"line":897,"offset":154511,"length":175,"previous":"M16-GAP-00897","next":"M16-GAP-00899"},"M16-GAP-00899":{"line":898,"offset":154686,"length":160,"previous":"M16-GAP-00898","next":"M16-GAP-00900"},"M16-GAP-00900":{"line":899,"offset":154846,"length":161,"previous":"M16-GAP-00899","next":"M16-GAP-00901"},"M16-GAP-00901":{"line":900,"offset":155007,"length":168,"previous":"M16-GAP-00900","next":"M16-GAP-00902"},"M16-GAP-00902":{"line":901,"offset":155175,"length":161,"previous":"M16-GAP-00901","next":"M16-GAP-00903"},"M16-GAP-00903":{"line":902,"offset":155336,"length":170,"previous":"M16-GAP-00902","next":"M16-GAP-00904"},"M16-GAP-00904":{"line":903,"offset":155506,"length":169,"previous":"M16-GAP-00903","next":"M16-GAP-00905"},"M16-GAP-00905":{"line":904,"offset":155675,"length":172,"previous":"M16-GAP-00904","next":"M16-GAP-00906"},"M16-GAP-00906":{"line":905,"offset":155847,"length":163,"previous":"M16-GAP-00905","next":"M16-GAP-00907"},"M16-GAP-00907":{"line":906,"offset":156010,"length":175,"previous":"M16-GAP-00906","next":"M16-GAP-00908"},"M16-GAP-00908":{"line":907,"offset":156185,"length":170,"previous":"M16-GAP-00907","next":"M16-GAP-00909"},"M16-GAP-00909":{"line":908,"offset":156355,"length":164,"previous":"M16-GAP-00908","next":"M16-GAP-00910"},"M16-GAP-00910":{"line":909,"offset":156519,"length":163,"previous":"M16-GAP-00909","next":"M16-GAP-00911"},"M16-GAP-00911":{"line":910,"offset":156682,"length":174,"previous":"M16-GAP-00910","next":"M16-GAP-00912"},"M16-GAP-00912":{"line":911,"offset":156856,"length":163,"previous":"M16-GAP-00911","next":"M16-GAP-00913"},"M16-GAP-00913":{"line":912,"offset":157019,"length":168,"previous":"M16-GAP-00912","next":"M16-GAP-00914"},"M16-GAP-00914":{"line":913,"offset":157187,"length":161,"previous":"M16-GAP-00913","next":"M16-GAP-00915"},"M16-GAP-00915":{"line":914,"offset":157348,"length":174,"previous":"M16-GAP-00914","next":"M16-GAP-00916"},"M16-GAP-00916":{"line":915,"offset":157522,"length":164,"previous":"M16-GAP-00915","next":"M16-GAP-00917"},"M16-GAP-00917":{"line":916,"offset":157686,"length":170,"previous":"M16-GAP-00916","next":"M16-GAP-00918"},"M16-GAP-00918":{"line":917,"offset":157856,"length":165,"previous":"M16-GAP-00917","next":"M16-GAP-00919"},"M16-GAP-00919":{"line":918,"offset":158021,"length":166,"previous":"M16-GAP-00918","next":"M16-GAP-00920"},"M16-GAP-00920":{"line":919,"offset":158187,"length":168,"previous":"M16-GAP-00919","next":"M16-GAP-00921"},"M16-GAP-00921":{"line":920,"offset":158355,"length":163,"previous":"M16-GAP-00920","next":"M16-GAP-00922"},"M16-GAP-00922":{"line":921,"offset":158518,"length":165,"previous":"M16-GAP-00921","next":"M16-GAP-00923"},"M16-GAP-00923":{"line":922,"offset":158683,"length":175,"previous":"M16-GAP-00922","next":"M16-GAP-00924"},"M16-GAP-00924":{"line":923,"offset":158858,"length":175,"previous":"M16-GAP-00923","next":"M16-GAP-00925"},"M16-GAP-00925":{"line":924,"offset":159033,"length":166,"previous":"M16-GAP-00924","next":"M16-GAP-00926"},"M16-GAP-00926":{"line":925,"offset":159199,"length":165,"previous":"M16-GAP-00925","next":"M16-GAP-00927"},"M16-GAP-00927":{"line":926,"offset":159364,"length":170,"previous":"M16-GAP-00926","next":"M16-GAP-00928"},"M16-GAP-00928":{"line":927,"offset":159534,"length":166,"previous":"M16-GAP-00927","next":"M16-GAP-00929"},"M16-GAP-00929":{"line":928,"offset":159700,"length":173,"previous":"M16-GAP-00928","next":"M16-GAP-00930"},"M16-GAP-00930":{"line":929,"offset":159873,"length":169,"previous":"M16-GAP-00929","next":"M16-GAP-00931"},"M16-GAP-00931":{"line":930,"offset":160042,"length":170,"previous":"M16-GAP-00930","next":"M16-GAP-00932"},"M16-GAP-00932":{"line":931,"offset":160212,"length":172,"previous":"M16-GAP-00931","next":"M16-GAP-00933"},"M16-GAP-00933":{"line":932,"offset":160384,"length":166,"previous":"M16-GAP-00932","next":"M16-GAP-00934"},"M16-GAP-00934":{"line":933,"offset":160550,"length":167,"previous":"M16-GAP-00933","next":"M16-GAP-00935"},"M16-GAP-00935":{"line":934,"offset":160717,"length":167,"previous":"M16-GAP-00934","next":"M16-GAP-00936"},"M16-GAP-00936":{"line":935,"offset":160884,"length":168,"previous":"M16-GAP-00935","next":"M16-GAP-00937"},"M16-GAP-00937":{"line":936,"offset":161052,"length":167,"previous":"M16-GAP-00936","next":"M16-GAP-00938"},"M16-GAP-00938":{"line":937,"offset":161219,"length":169,"previous":"M16-GAP-00937","next":"M16-GAP-00939"},"M16-GAP-00939":{"line":938,"offset":161388,"length":169,"previous":"M16-GAP-00938","next":"M16-GAP-00940"},"M16-GAP-00940":{"line":939,"offset":161557,"length":178,"previous":"M16-GAP-00939","next":"M16-GAP-00941"},"M16-GAP-00941":{"line":940,"offset":161735,"length":166,"previous":"M16-GAP-00940","next":"M16-GAP-00942"},"M16-GAP-00942":{"line":941,"offset":161901,"length":166,"previous":"M16-GAP-00941","next":"M16-GAP-00943"},"M16-GAP-00943":{"line":942,"offset":162067,"length":167,"previous":"M16-GAP-00942","next":"M16-GAP-00944"},"M16-GAP-00944":{"line":943,"offset":162234,"length":163,"previous":"M16-GAP-00943","next":"M16-GAP-00945"},"M16-GAP-00945":{"line":944,"offset":162397,"length":171,"previous":"M16-GAP-00944","next":"M16-GAP-00946"},"M16-GAP-00946":{"line":945,"offset":162568,"length":169,"previous":"M16-GAP-00945","next":"M16-GAP-00947"},"M16-GAP-00947":{"line":946,"offset":162737,"length":170,"previous":"M16-GAP-00946","next":"M16-GAP-00948"},"M16-GAP-00948":{"line":947,"offset":162907,"length":172,"previous":"M16-GAP-00947","next":"M16-GAP-00949"},"M16-GAP-00949":{"line":948,"offset":163079,"length":170,"previous":"M16-GAP-00948","next":"M16-GAP-00950"},"M16-GAP-00950":{"line":949,"offset":163249,"length":172,"previous":"M16-GAP-00949","next":"M16-GAP-00951"},"M16-GAP-00951":{"line":950,"offset":163421,"length":175,"previous":"M16-GAP-00950","next":"M16-GAP-00952"},"M16-GAP-00952":{"line":951,"offset":163596,"length":161,"previous":"M16-GAP-00951","next":"M16-GAP-00953"},"M16-GAP-00953":{"line":952,"offset":163757,"length":169,"previous":"M16-GAP-00952","next":"M16-GAP-00954"},"M16-GAP-00954":{"line":953,"offset":163926,"length":164,"previous":"M16-GAP-00953","next":"M16-GAP-00955"},"M16-GAP-00955":{"line":954,"offset":164090,"length":167,"previous":"M16-GAP-00954","next":"M16-GAP-00956"},"M16-GAP-00956":{"line":955,"offset":164257,"length":174,"previous":"M16-GAP-00955","next":"M16-GAP-00957"},"M16-GAP-00957":{"line":956,"offset":164431,"length":162,"previous":"M16-GAP-00956","next":"M16-GAP-00958"},"M16-GAP-00958":{"line":957,"offset":164593,"length":164,"previous":"M16-GAP-00957","next":"M16-GAP-00959"},"M16-GAP-00959":{"line":958,"offset":164757,"length":164,"previous":"M16-GAP-00958","next":"M16-GAP-00960"},"M16-GAP-00960":{"line":959,"offset":164921,"length":168,"previous":"M16-GAP-00959","next":"M16-GAP-00961"},"M16-GAP-00961":{"line":960,"offset":165089,"length":168,"previous":"M16-GAP-00960","next":"M16-GAP-00962"},"M16-GAP-00962":{"line":961,"offset":165257,"length":174,"previous":"M16-GAP-00961","next":"M16-GAP-00963"},"M16-GAP-00963":{"line":962,"offset":165431,"length":174,"previous":"M16-GAP-00962","next":"M16-GAP-00964"},"M16-GAP-00964":{"line":963,"offset":165605,"length":180,"previous":"M16-GAP-00963","next":"M16-GAP-00965"},"M16-GAP-00965":{"line":964,"offset":165785,"length":166,"previous":"M16-GAP-00964","next":"M16-GAP-00966"},"M16-GAP-00966":{"line":965,"offset":165951,"length":172,"previous":"M16-GAP-00965","next":"M16-GAP-00967"},"M16-GAP-00967":{"line":966,"offset":166123,"length":168,"previous":"M16-GAP-00966","next":"M16-GAP-00968"},"M16-GAP-00968":{"line":967,"offset":166291,"length":169,"previous":"M16-GAP-00967","next":"M16-GAP-00969"},"M16-GAP-00969":{"line":968,"offset":166460,"length":162,"previous":"M16-GAP-00968","next":"M16-GAP-00970"},"M16-GAP-00970":{"line":969,"offset":166622,"length":165,"previous":"M16-GAP-00969","next":"M16-GAP-00971"},"M16-GAP-00971":{"line":970,"offset":166787,"length":170,"previous":"M16-GAP-00970","next":"M16-GAP-00972"},"M16-GAP-00972":{"line":971,"offset":166957,"length":176,"previous":"M16-GAP-00971","next":"M16-GAP-00973"},"M16-GAP-00973":{"line":972,"offset":167133,"length":171,"previous":"M16-GAP-00972","next":"M16-GAP-00974"},"M16-GAP-00974":{"line":973,"offset":167304,"length":171,"previous":"M16-GAP-00973","next":"M16-GAP-00975"},"M16-GAP-00975":{"line":974,"offset":167475,"length":169,"previous":"M16-GAP-00974","next":"M16-GAP-00976"},"M16-GAP-00976":{"line":975,"offset":167644,"length":166,"previous":"M16-GAP-00975","next":"M16-GAP-00977"},"M16-GAP-00977":{"line":976,"offset":167810,"length":165,"previous":"M16-GAP-00976","next":"M16-GAP-00978"},"M16-GAP-00978":{"line":977,"offset":167975,"length":168,"previous":"M16-GAP-00977","next":"M16-GAP-00979"},"M16-GAP-00979":{"line":978,"offset":168143,"length":169,"previous":"M16-GAP-00978","next":"M16-GAP-00980"},"M16-GAP-00980":{"line":979,"offset":168312,"length":159,"previous":"M16-GAP-00979","next":"M16-GAP-00981"},"M16-GAP-00981":{"line":980,"offset":168471,"length":179,"previous":"M16-GAP-00980","next":"M16-GAP-00982"},"M16-GAP-00982":{"line":981,"offset":168650,"length":168,"previous":"M16-GAP-00981","next":"M16-GAP-00983"},"M16-GAP-00983":{"line":982,"offset":168818,"length":166,"previous":"M16-GAP-00982","next":"M16-GAP-00984"},"M16-GAP-00984":{"line":983,"offset":168984,"length":169,"previous":"M16-GAP-00983","next":"M16-GAP-00985"},"M16-GAP-00985":{"line":984,"offset":169153,"length":176,"previous":"M16-GAP-00984","next":"M16-GAP-00986"},"M16-GAP-00986":{"line":985,"offset":169329,"length":176,"previous":"M16-GAP-00985","next":"M16-GAP-00987"},"M16-GAP-00987":{"line":986,"offset":169505,"length":162,"previous":"M16-GAP-00986","next":"M16-GAP-00988"},"M16-GAP-00988":{"line":987,"offset":169667,"length":166,"previous":"M16-GAP-00987","next":"M16-GAP-00989"},"M16-GAP-00989":{"line":988,"offset":169833,"length":166,"previous":"M16-GAP-00988","next":"M16-GAP-00990"},"M16-GAP-00990":{"line":989,"offset":169999,"length":169,"previous":"M16-GAP-00989","next":"M16-GAP-00991"},"M16-GAP-00991":{"line":990,"offset":170168,"length":168,"previous":"M16-GAP-00990","next":"M16-GAP-00992"},"M16-GAP-00992":{"line":991,"offset":170336,"length":167,"previous":"M16-GAP-00991","next":"M16-GAP-00993"},"M16-GAP-00993":{"line":992,"offset":170503,"length":169,"previous":"M16-GAP-00992","next":"M16-GAP-00994"},"M16-GAP-00994":{"line":993,"offset":170672,"length":174,"previous":"M16-GAP-00993","next":"M16-GAP-00995"},"M16-GAP-00995":{"line":994,"offset":170846,"length":167,"previous":"M16-GAP-00994","next":"M16-GAP-00996"},"M16-GAP-00996":{"line":995,"offset":171013,"length":171,"previous":"M16-GAP-00995","next":"M16-GAP-00997"},"M16-GAP-00997":{"line":996,"offset":171184,"length":179,"previous":"M16-GAP-00996","next":"M16-GAP-00998"},"M16-GAP-00998":{"line":997,"offset":171363,"length":172,"previous":"M16-GAP-00997","next":"M16-GAP-00999"},"M16-GAP-00999":{"line":998,"offset":171535,"length":171,"previous":"M16-GAP-00998","next":"M16-GAP-01000"},"M16-GAP-01000":{"line":999,"offset":171706,"length":167,"previous":"M16-GAP-00999","next":"M16-GAP-01001"},"M16-GAP-01001":{"line":1000,"offset":171873,"length":178,"previous":"M16-GAP-01000","next":"M16-GAP-01002"},"M16-GAP-01002":{"line":1001,"offset":172051,"length":172,"previous":"M16-GAP-01001","next":"M16-GAP-01003"},"M16-GAP-01003":{"line":1002,"offset":172223,"length":164,"previous":"M16-GAP-01002","next":"M16-GAP-01004"},"M16-GAP-01004":{"line":1003,"offset":172387,"length":163,"previous":"M16-GAP-01003","next":"M16-GAP-01005"},"M16-GAP-01005":{"line":1004,"offset":172550,"length":165,"previous":"M16-GAP-01004","next":"M16-GAP-01006"},"M16-GAP-01006":{"line":1005,"offset":172715,"length":173,"previous":"M16-GAP-01005","next":"M16-GAP-01007"},"M16-GAP-01007":{"line":1006,"offset":172888,"length":176,"previous":"M16-GAP-01006","next":"M16-GAP-01008"},"M16-GAP-01008":{"line":1007,"offset":173064,"length":171,"previous":"M16-GAP-01007","next":"M16-GAP-01009"},"M16-GAP-01009":{"line":1008,"offset":173235,"length":171,"previous":"M16-GAP-01008","next":"M16-GAP-01010"},"M16-GAP-01010":{"line":1009,"offset":173406,"length":173,"previous":"M16-GAP-01009","next":"M16-GAP-01011"},"M16-GAP-01011":{"line":1010,"offset":173579,"length":167,"previous":"M16-GAP-01010","next":"M16-GAP-01012"},"M16-GAP-01012":{"line":1011,"offset":173746,"length":180,"previous":"M16-GAP-01011","next":"M16-GAP-01013"},"M16-GAP-01013":{"line":1012,"offset":173926,"length":171,"previous":"M16-GAP-01012","next":"M16-GAP-01014"},"M16-GAP-01014":{"line":1013,"offset":174097,"length":169,"previous":"M16-GAP-01013","next":"M16-GAP-01015"},"M16-GAP-01015":{"line":1014,"offset":174266,"length":171,"previous":"M16-GAP-01014","next":"M16-GAP-01016"},"M16-GAP-01016":{"line":1015,"offset":174437,"length":169,"previous":"M16-GAP-01015","next":"M16-GAP-01017"},"M16-GAP-01017":{"line":1016,"offset":174606,"length":161,"previous":"M16-GAP-01016","next":"M16-GAP-01018"},"M16-GAP-01018":{"line":1017,"offset":174767,"length":162,"previous":"M16-GAP-01017","next":"M16-GAP-01019"},"M16-GAP-01019":{"line":1018,"offset":174929,"length":172,"previous":"M16-GAP-01018","next":"M16-GAP-01020"},"M16-GAP-01020":{"line":1019,"offset":175101,"length":173,"previous":"M16-GAP-01019","next":"M16-GAP-01021"},"M16-GAP-01021":{"line":1020,"offset":175274,"length":167,"previous":"M16-GAP-01020","next":"M16-GAP-01022"},"M16-GAP-01022":{"line":1021,"offset":175441,"length":170,"previous":"M16-GAP-01021","next":"M16-GAP-01023"},"M16-GAP-01023":{"line":1022,"offset":175611,"length":169,"previous":"M16-GAP-01022","next":"M16-GAP-01024"},"M16-GAP-01024":{"line":1023,"offset":175780,"length":167,"previous":"M16-GAP-01023","next":"M16-GAP-01025"},"M16-GAP-01025":{"line":1024,"offset":175947,"length":190,"previous":"M16-GAP-01024","next":"M16-GAP-01026"},"M16-GAP-01026":{"line":1025,"offset":176137,"length":192,"previous":"M16-GAP-01025","next":"M16-GAP-01027"},"M16-GAP-01027":{"line":1026,"offset":176329,"length":182,"previous":"M16-GAP-01026","next":"M16-GAP-01028"},"M16-GAP-01028":{"line":1027,"offset":176511,"length":177,"previous":"M16-GAP-01027","next":"M16-GAP-01029"},"M16-GAP-01029":{"line":1028,"offset":176688,"length":175,"previous":"M16-GAP-01028","next":"M16-GAP-01030"},"M16-GAP-01030":{"line":1029,"offset":176863,"length":177,"previous":"M16-GAP-01029","next":"M16-GAP-01031"},"M16-GAP-01031":{"line":1030,"offset":177040,"length":164,"previous":"M16-GAP-01030","next":"M16-GAP-01032"},"M16-GAP-01032":{"line":1031,"offset":177204,"length":162,"previous":"M16-GAP-01031","next":"M16-GAP-01033"},"M16-GAP-01033":{"line":1032,"offset":177366,"length":171,"previous":"M16-GAP-01032","next":"M16-GAP-01034"},"M16-GAP-01034":{"line":1033,"offset":177537,"length":168,"previous":"M16-GAP-01033","next":"M16-GAP-01035"},"M16-GAP-01035":{"line":1034,"offset":177705,"length":175,"previous":"M16-GAP-01034","next":"M16-GAP-01036"},"M16-GAP-01036":{"line":1035,"offset":177880,"length":170,"previous":"M16-GAP-01035","next":"M16-GAP-01037"},"M16-GAP-01037":{"line":1036,"offset":178050,"length":170,"previous":"M16-GAP-01036","next":"M16-GAP-01038"},"M16-GAP-01038":{"line":1037,"offset":178220,"length":172,"previous":"M16-GAP-01037","next":"M16-GAP-01039"},"M16-GAP-01039":{"line":1038,"offset":178392,"length":169,"previous":"M16-GAP-01038","next":"M16-GAP-01040"},"M16-GAP-01040":{"line":1039,"offset":178561,"length":170,"previous":"M16-GAP-01039","next":"M16-GAP-01041"},"M16-GAP-01041":{"line":1040,"offset":178731,"length":176,"previous":"M16-GAP-01040","next":"M16-GAP-01042"},"M16-GAP-01042":{"line":1041,"offset":178907,"length":165,"previous":"M16-GAP-01041","next":"M16-GAP-01043"},"M16-GAP-01043":{"line":1042,"offset":179072,"length":170,"previous":"M16-GAP-01042","next":"M16-GAP-01044"},"M16-GAP-01044":{"line":1043,"offset":179242,"length":169,"previous":"M16-GAP-01043","next":"M16-GAP-01045"},"M16-GAP-01045":{"line":1044,"offset":179411,"length":169,"previous":"M16-GAP-01044","next":"M16-GAP-01046"},"M16-GAP-01046":{"line":1045,"offset":179580,"length":167,"previous":"M16-GAP-01045","next":"M16-GAP-01047"},"M16-GAP-01047":{"line":1046,"offset":179747,"length":166,"previous":"M16-GAP-01046","next":"M16-GAP-01048"},"M16-GAP-01048":{"line":1047,"offset":179913,"length":171,"previous":"M16-GAP-01047","next":"M16-GAP-01049"},"M16-GAP-01049":{"line":1048,"offset":180084,"length":174,"previous":"M16-GAP-01048","next":"M16-GAP-01050"},"M16-GAP-01050":{"line":1049,"offset":180258,"length":171,"previous":"M16-GAP-01049","next":"M16-GAP-01051"},"M16-GAP-01051":{"line":1050,"offset":180429,"length":176,"previous":"M16-GAP-01050","next":"M16-GAP-01052"},"M16-GAP-01052":{"line":1051,"offset":180605,"length":175,"previous":"M16-GAP-01051","next":"M16-GAP-01053"},"M16-GAP-01053":{"line":1052,"offset":180780,"length":174,"previous":"M16-GAP-01052","next":"M16-GAP-01054"},"M16-GAP-01054":{"line":1053,"offset":180954,"length":175,"previous":"M16-GAP-01053","next":"M16-GAP-01055"},"M16-GAP-01055":{"line":1054,"offset":181129,"length":174,"previous":"M16-GAP-01054","next":"M16-GAP-01056"},"M16-GAP-01056":{"line":1055,"offset":181303,"length":172,"previous":"M16-GAP-01055","next":"M16-GAP-01057"},"M16-GAP-01057":{"line":1056,"offset":181475,"length":170,"previous":"M16-GAP-01056","next":"M16-GAP-01058"},"M16-GAP-01058":{"line":1057,"offset":181645,"length":175,"previous":"M16-GAP-01057","next":"M16-GAP-01059"},"M16-GAP-01059":{"line":1058,"offset":181820,"length":184,"previous":"M16-GAP-01058","next":"M16-GAP-01060"},"M16-GAP-01060":{"line":1059,"offset":182004,"length":170,"previous":"M16-GAP-01059","next":"M16-GAP-01061"},"M16-GAP-01061":{"line":1060,"offset":182174,"length":177,"previous":"M16-GAP-01060","next":"M16-GAP-01062"},"M16-GAP-01062":{"line":1061,"offset":182351,"length":175,"previous":"M16-GAP-01061","next":"M16-GAP-01063"},"M16-GAP-01063":{"line":1062,"offset":182526,"length":172,"previous":"M16-GAP-01062","next":"M16-GAP-01064"},"M16-GAP-01064":{"line":1063,"offset":182698,"length":175,"previous":"M16-GAP-01063","next":"M16-GAP-01065"},"M16-GAP-01065":{"line":1064,"offset":182873,"length":180,"previous":"M16-GAP-01064","next":"M16-GAP-01066"},"M16-GAP-01066":{"line":1065,"offset":183053,"length":172,"previous":"M16-GAP-01065","next":"M16-GAP-01067"},"M16-GAP-01067":{"line":1066,"offset":183225,"length":174,"previous":"M16-GAP-01066","next":"M16-GAP-01068"},"M16-GAP-01068":{"line":1067,"offset":183399,"length":160,"previous":"M16-GAP-01067","next":"M16-GAP-01069"},"M16-GAP-01069":{"line":1068,"offset":183559,"length":165,"previous":"M16-GAP-01068","next":"M16-GAP-01070"},"M16-GAP-01070":{"line":1069,"offset":183724,"length":166,"previous":"M16-GAP-01069","next":"M16-GAP-01071"},"M16-GAP-01071":{"line":1070,"offset":183890,"length":163,"previous":"M16-GAP-01070","next":"M16-GAP-01072"},"M16-GAP-01072":{"line":1071,"offset":184053,"length":168,"previous":"M16-GAP-01071","next":"M16-GAP-01073"},"M16-GAP-01073":{"line":1072,"offset":184221,"length":178,"previous":"M16-GAP-01072","next":"M16-GAP-01074"},"M16-GAP-01074":{"line":1073,"offset":184399,"length":160,"previous":"M16-GAP-01073","next":"M16-GAP-01075"},"M16-GAP-01075":{"line":1074,"offset":184559,"length":161,"previous":"M16-GAP-01074","next":"M16-GAP-01076"},"M16-GAP-01076":{"line":1075,"offset":184720,"length":165,"previous":"M16-GAP-01075","next":"M16-GAP-01077"},"M16-GAP-01077":{"line":1076,"offset":184885,"length":173,"previous":"M16-GAP-01076","next":"M16-GAP-01078"},"M16-GAP-01078":{"line":1077,"offset":185058,"length":169,"previous":"M16-GAP-01077","next":"M16-GAP-01079"},"M16-GAP-01079":{"line":1078,"offset":185227,"length":166,"previous":"M16-GAP-01078","next":"M16-GAP-01080"},"M16-GAP-01080":{"line":1079,"offset":185393,"length":167,"previous":"M16-GAP-01079","next":"M16-GAP-01081"},"M16-GAP-01081":{"line":1080,"offset":185560,"length":170,"previous":"M16-GAP-01080","next":"M16-GAP-01082"},"M16-GAP-01082":{"line":1081,"offset":185730,"length":163,"previous":"M16-GAP-01081","next":"M16-GAP-01083"},"M16-GAP-01083":{"line":1082,"offset":185893,"length":169,"previous":"M16-GAP-01082","next":"M16-GAP-01084"},"M16-GAP-01084":{"line":1083,"offset":186062,"length":175,"previous":"M16-GAP-01083","next":"M16-GAP-01085"},"M16-GAP-01085":{"line":1084,"offset":186237,"length":175,"previous":"M16-GAP-01084","next":"M16-GAP-01086"},"M16-GAP-01086":{"line":1085,"offset":186412,"length":165,"previous":"M16-GAP-01085","next":"M16-GAP-01087"},"M16-GAP-01087":{"line":1086,"offset":186577,"length":166,"previous":"M16-GAP-01086","next":"M16-GAP-01088"},"M16-GAP-01088":{"line":1087,"offset":186743,"length":161,"previous":"M16-GAP-01087","next":"M16-GAP-01089"},"M16-GAP-01089":{"line":1088,"offset":186904,"length":169,"previous":"M16-GAP-01088","next":"M16-GAP-01090"},"M16-GAP-01090":{"line":1089,"offset":187073,"length":177,"previous":"M16-GAP-01089","next":"M16-GAP-01091"},"M16-GAP-01091":{"line":1090,"offset":187250,"length":179,"previous":"M16-GAP-01090","next":"M16-GAP-01092"},"M16-GAP-01092":{"line":1091,"offset":187429,"length":169,"previous":"M16-GAP-01091","next":"M16-GAP-01093"},"M16-GAP-01093":{"line":1092,"offset":187598,"length":173,"previous":"M16-GAP-01092","next":"M16-GAP-01094"},"M16-GAP-01094":{"line":1093,"offset":187771,"length":179,"previous":"M16-GAP-01093","next":"M16-GAP-01095"},"M16-GAP-01095":{"line":1094,"offset":187950,"length":169,"previous":"M16-GAP-01094","next":"M16-GAP-01096"},"M16-GAP-01096":{"line":1095,"offset":188119,"length":160,"previous":"M16-GAP-01095","next":"M16-GAP-01097"},"M16-GAP-01097":{"line":1096,"offset":188279,"length":182,"previous":"M16-GAP-01096","next":"M16-GAP-01098"},"M16-GAP-01098":{"line":1097,"offset":188461,"length":184,"previous":"M16-GAP-01097","next":"M16-GAP-01099"},"M16-GAP-01099":{"line":1098,"offset":188645,"length":188,"previous":"M16-GAP-01098","next":"M16-GAP-01100"},"M16-GAP-01100":{"line":1099,"offset":188833,"length":180,"previous":"M16-GAP-01099","next":"M16-GAP-01101"},"M16-GAP-01101":{"line":1100,"offset":189013,"length":185,"previous":"M16-GAP-01100","next":"M16-GAP-01102"},"M16-GAP-01102":{"line":1101,"offset":189198,"length":181,"previous":"M16-GAP-01101","next":"M16-GAP-01103"},"M16-GAP-01103":{"line":1102,"offset":189379,"length":186,"previous":"M16-GAP-01102","next":"M16-GAP-01104"},"M16-GAP-01104":{"line":1103,"offset":189565,"length":185,"previous":"M16-GAP-01103","next":"M16-GAP-01105"},"M16-GAP-01105":{"line":1104,"offset":189750,"length":190,"previous":"M16-GAP-01104","next":"M16-GAP-01106"},"M16-GAP-01106":{"line":1105,"offset":189940,"length":176,"previous":"M16-GAP-01105","next":"M16-GAP-01107"},"M16-GAP-01107":{"line":1106,"offset":190116,"length":174,"previous":"M16-GAP-01106","next":"M16-GAP-01108"},"M16-GAP-01108":{"line":1107,"offset":190290,"length":174,"previous":"M16-GAP-01107","next":"M16-GAP-01109"},"M16-GAP-01109":{"line":1108,"offset":190464,"length":180,"previous":"M16-GAP-01108","next":"M16-GAP-01110"},"M16-GAP-01110":{"line":1109,"offset":190644,"length":178,"previous":"M16-GAP-01109","next":"M16-GAP-01111"},"M16-GAP-01111":{"line":1110,"offset":190822,"length":174,"previous":"M16-GAP-01110","next":"M16-GAP-01112"},"M16-GAP-01112":{"line":1111,"offset":190996,"length":180,"previous":"M16-GAP-01111","next":"M16-GAP-01113"},"M16-GAP-01113":{"line":1112,"offset":191176,"length":176,"previous":"M16-GAP-01112","next":"M16-GAP-01114"},"M16-GAP-01114":{"line":1113,"offset":191352,"length":175,"previous":"M16-GAP-01113","next":"M16-GAP-01115"},"M16-GAP-01115":{"line":1114,"offset":191527,"length":175,"previous":"M16-GAP-01114","next":"M16-GAP-01116"},"M16-GAP-01116":{"line":1115,"offset":191702,"length":179,"previous":"M16-GAP-01115","next":"M16-GAP-01117"},"M16-GAP-01117":{"line":1116,"offset":191881,"length":177,"previous":"M16-GAP-01116","next":"M16-GAP-01118"},"M16-GAP-01118":{"line":1117,"offset":192058,"length":170,"previous":"M16-GAP-01117","next":"M16-GAP-01119"},"M16-GAP-01119":{"line":1118,"offset":192228,"length":170,"previous":"M16-GAP-01118","next":"M16-GAP-01120"},"M16-GAP-01120":{"line":1119,"offset":192398,"length":180,"previous":"M16-GAP-01119","next":"M16-GAP-01121"},"M16-GAP-01121":{"line":1120,"offset":192578,"length":162,"previous":"M16-GAP-01120","next":"M16-GAP-01122"},"M16-GAP-01122":{"line":1121,"offset":192740,"length":159,"previous":"M16-GAP-01121","next":"M16-GAP-01123"},"M16-GAP-01123":{"line":1122,"offset":192899,"length":164,"previous":"M16-GAP-01122","next":"M16-GAP-01124"},"M16-GAP-01124":{"line":1123,"offset":193063,"length":169,"previous":"M16-GAP-01123","next":"M16-GAP-01125"},"M16-GAP-01125":{"line":1124,"offset":193232,"length":164,"previous":"M16-GAP-01124","next":"M16-GAP-01126"},"M16-GAP-01126":{"line":1125,"offset":193396,"length":161,"previous":"M16-GAP-01125","next":"M16-GAP-01127"},"M16-GAP-01127":{"line":1126,"offset":193557,"length":166,"previous":"M16-GAP-01126","next":"M16-GAP-01128"},"M16-GAP-01128":{"line":1127,"offset":193723,"length":167,"previous":"M16-GAP-01127","next":"M16-GAP-01129"},"M16-GAP-01129":{"line":1128,"offset":193890,"length":182,"previous":"M16-GAP-01128","next":"M16-GAP-01130"},"M16-GAP-01130":{"line":1129,"offset":194072,"length":175,"previous":"M16-GAP-01129","next":"M16-GAP-01131"},"M16-GAP-01131":{"line":1130,"offset":194247,"length":176,"previous":"M16-GAP-01130","next":"M16-GAP-01132"},"M16-GAP-01132":{"line":1131,"offset":194423,"length":178,"previous":"M16-GAP-01131","next":"M16-GAP-01133"},"M16-GAP-01133":{"line":1132,"offset":194601,"length":178,"previous":"M16-GAP-01132","next":"M16-GAP-01134"},"M16-GAP-01134":{"line":1133,"offset":194779,"length":176,"previous":"M16-GAP-01133","next":"M16-GAP-01135"},"M16-GAP-01135":{"line":1134,"offset":194955,"length":177,"previous":"M16-GAP-01134","next":"M16-GAP-01136"},"M16-GAP-01136":{"line":1135,"offset":195132,"length":167,"previous":"M16-GAP-01135","next":"M16-GAP-01137"},"M16-GAP-01137":{"line":1136,"offset":195299,"length":169,"previous":"M16-GAP-01136","next":"M16-GAP-01138"},"M16-GAP-01138":{"line":1137,"offset":195468,"length":174,"previous":"M16-GAP-01137","next":"M16-GAP-01139"},"M16-GAP-01139":{"line":1138,"offset":195642,"length":168,"previous":"M16-GAP-01138","next":"M16-GAP-01140"},"M16-GAP-01140":{"line":1139,"offset":195810,"length":169,"previous":"M16-GAP-01139","next":"M16-GAP-01141"},"M16-GAP-01141":{"line":1140,"offset":195979,"length":167,"previous":"M16-GAP-01140","next":"M16-GAP-01142"},"M16-GAP-01142":{"line":1141,"offset":196146,"length":167,"previous":"M16-GAP-01141","next":"M16-GAP-01143"},"M16-GAP-01143":{"line":1142,"offset":196313,"length":172,"previous":"M16-GAP-01142","next":"M16-GAP-01144"},"M16-GAP-01144":{"line":1143,"offset":196485,"length":175,"previous":"M16-GAP-01143","next":"M16-GAP-01145"},"M16-GAP-01145":{"line":1144,"offset":196660,"length":166,"previous":"M16-GAP-01144","next":"M16-GAP-01146"},"M16-GAP-01146":{"line":1145,"offset":196826,"length":172,"previous":"M16-GAP-01145","next":"M16-GAP-01147"},"M16-GAP-01147":{"line":1146,"offset":196998,"length":169,"previous":"M16-GAP-01146","next":"M16-GAP-01148"},"M16-GAP-01148":{"line":1147,"offset":197167,"length":170,"previous":"M16-GAP-01147","next":"M16-GAP-01149"},"M16-GAP-01149":{"line":1148,"offset":197337,"length":177,"previous":"M16-GAP-01148","next":"M16-GAP-01150"},"M16-GAP-01150":{"line":1149,"offset":197514,"length":172,"previous":"M16-GAP-01149","next":"M16-GAP-01151"},"M16-GAP-01151":{"line":1150,"offset":197686,"length":164,"previous":"M16-GAP-01150","next":"M16-GAP-01152"},"M16-GAP-01152":{"line":1151,"offset":197850,"length":178,"previous":"M16-GAP-01151","next":"M16-GAP-01153"},"M16-GAP-01153":{"line":1152,"offset":198028,"length":178,"previous":"M16-GAP-01152","next":"M16-GAP-01154"},"M16-GAP-01154":{"line":1153,"offset":198206,"length":178,"previous":"M16-GAP-01153","next":"M16-GAP-01155"},"M16-GAP-01155":{"line":1154,"offset":198384,"length":174,"previous":"M16-GAP-01154","next":"M16-GAP-01156"},"M16-GAP-01156":{"line":1155,"offset":198558,"length":176,"previous":"M16-GAP-01155","next":"M16-GAP-01157"},"M16-GAP-01157":{"line":1156,"offset":198734,"length":170,"previous":"M16-GAP-01156","next":"M16-GAP-01158"},"M16-GAP-01158":{"line":1157,"offset":198904,"length":164,"previous":"M16-GAP-01157","next":"M16-GAP-01159"},"M16-GAP-01159":{"line":1158,"offset":199068,"length":169,"previous":"M16-GAP-01158","next":"M16-GAP-01160"},"M16-GAP-01160":{"line":1159,"offset":199237,"length":179,"previous":"M16-GAP-01159","next":"M16-GAP-01161"},"M16-GAP-01161":{"line":1160,"offset":199416,"length":160,"previous":"M16-GAP-01160","next":"M16-GAP-01162"},"M16-GAP-01162":{"line":1161,"offset":199576,"length":161,"previous":"M16-GAP-01161","next":"M16-GAP-01163"},"M16-GAP-01163":{"line":1162,"offset":199737,"length":169,"previous":"M16-GAP-01162","next":"M16-GAP-01164"},"M16-GAP-01164":{"line":1163,"offset":199906,"length":165,"previous":"M16-GAP-01163","next":"M16-GAP-01165"},"M16-GAP-01165":{"line":1164,"offset":200071,"length":174,"previous":"M16-GAP-01164","next":"M16-GAP-01166"},"M16-GAP-01166":{"line":1165,"offset":200245,"length":166,"previous":"M16-GAP-01165","next":"M16-GAP-01167"},"M16-GAP-01167":{"line":1166,"offset":200411,"length":169,"previous":"M16-GAP-01166","next":"M16-GAP-01168"},"M16-GAP-01168":{"line":1167,"offset":200580,"length":177,"previous":"M16-GAP-01167","next":"M16-GAP-01169"},"M16-GAP-01169":{"line":1168,"offset":200757,"length":167,"previous":"M16-GAP-01168","next":"M16-GAP-01170"},"M16-GAP-01170":{"line":1169,"offset":200924,"length":170,"previous":"M16-GAP-01169","next":"M16-GAP-01171"},"M16-GAP-01171":{"line":1170,"offset":201094,"length":173,"previous":"M16-GAP-01170","next":"M16-GAP-01172"},"M16-GAP-01172":{"line":1171,"offset":201267,"length":167,"previous":"M16-GAP-01171","next":"M16-GAP-01173"},"M16-GAP-01173":{"line":1172,"offset":201434,"length":166,"previous":"M16-GAP-01172","next":"M16-GAP-01174"},"M16-GAP-01174":{"line":1173,"offset":201600,"length":168,"previous":"M16-GAP-01173","next":"M16-GAP-01175"},"M16-GAP-01175":{"line":1174,"offset":201768,"length":176,"previous":"M16-GAP-01174","next":"M16-GAP-01176"},"M16-GAP-01176":{"line":1175,"offset":201944,"length":178,"previous":"M16-GAP-01175","next":"M16-GAP-01177"},"M16-GAP-01177":{"line":1176,"offset":202122,"length":173,"previous":"M16-GAP-01176","next":"M16-GAP-01178"},"M16-GAP-01178":{"line":1177,"offset":202295,"length":171,"previous":"M16-GAP-01177","next":"M16-GAP-01179"},"M16-GAP-01179":{"line":1178,"offset":202466,"length":181,"previous":"M16-GAP-01178","next":"M16-GAP-01180"},"M16-GAP-01180":{"line":1179,"offset":202647,"length":165,"previous":"M16-GAP-01179","next":"M16-GAP-01181"},"M16-GAP-01181":{"line":1180,"offset":202812,"length":170,"previous":"M16-GAP-01180","next":"M16-GAP-01182"},"M16-GAP-01182":{"line":1181,"offset":202982,"length":173,"previous":"M16-GAP-01181","next":"M16-GAP-01183"},"M16-GAP-01183":{"line":1182,"offset":203155,"length":168,"previous":"M16-GAP-01182","next":"M16-GAP-01184"},"M16-GAP-01184":{"line":1183,"offset":203323,"length":169,"previous":"M16-GAP-01183","next":"M16-GAP-01185"},"M16-GAP-01185":{"line":1184,"offset":203492,"length":166,"previous":"M16-GAP-01184","next":"M16-GAP-01186"},"M16-GAP-01186":{"line":1185,"offset":203658,"length":159,"previous":"M16-GAP-01185","next":"M16-GAP-01187"},"M16-GAP-01187":{"line":1186,"offset":203817,"length":169,"previous":"M16-GAP-01186","next":"M16-GAP-01188"},"M16-GAP-01188":{"line":1187,"offset":203986,"length":166,"previous":"M16-GAP-01187","next":"M16-GAP-01189"},"M16-GAP-01189":{"line":1188,"offset":204152,"length":167,"previous":"M16-GAP-01188","next":"M16-GAP-01190"},"M16-GAP-01190":{"line":1189,"offset":204319,"length":161,"previous":"M16-GAP-01189","next":"M16-GAP-01191"},"M16-GAP-01191":{"line":1190,"offset":204480,"length":164,"previous":"M16-GAP-01190","next":"M16-GAP-01192"},"M16-GAP-01192":{"line":1191,"offset":204644,"length":176,"previous":"M16-GAP-01191","next":"M16-GAP-01193"},"M16-GAP-01193":{"line":1192,"offset":204820,"length":169,"previous":"M16-GAP-01192","next":"M16-GAP-01194"},"M16-GAP-01194":{"line":1193,"offset":204989,"length":168,"previous":"M16-GAP-01193","next":"M16-GAP-01195"},"M16-GAP-01195":{"line":1194,"offset":205157,"length":169,"previous":"M16-GAP-01194","next":"M16-GAP-01196"},"M16-GAP-01196":{"line":1195,"offset":205326,"length":170,"previous":"M16-GAP-01195","next":"M16-GAP-01197"},"M16-GAP-01197":{"line":1196,"offset":205496,"length":171,"previous":"M16-GAP-01196","next":"M16-GAP-01198"},"M16-GAP-01198":{"line":1197,"offset":205667,"length":163,"previous":"M16-GAP-01197","next":"M16-GAP-01199"},"M16-GAP-01199":{"line":1198,"offset":205830,"length":166,"previous":"M16-GAP-01198","next":"M16-GAP-01200"},"M16-GAP-01200":{"line":1199,"offset":205996,"length":164,"previous":"M16-GAP-01199","next":"M16-GAP-01201"},"M16-GAP-01201":{"line":1200,"offset":206160,"length":162,"previous":"M16-GAP-01200","next":"M16-GAP-01202"},"M16-GAP-01202":{"line":1201,"offset":206322,"length":166,"previous":"M16-GAP-01201","next":"M16-GAP-01203"},"M16-GAP-01203":{"line":1202,"offset":206488,"length":171,"previous":"M16-GAP-01202","next":"M16-GAP-01204"},"M16-GAP-01204":{"line":1203,"offset":206659,"length":165,"previous":"M16-GAP-01203","next":"M16-GAP-01205"},"M16-GAP-01205":{"line":1204,"offset":206824,"length":165,"previous":"M16-GAP-01204","next":"M16-GAP-01206"},"M16-GAP-01206":{"line":1205,"offset":206989,"length":171,"previous":"M16-GAP-01205","next":"M16-GAP-01207"},"M16-GAP-01207":{"line":1206,"offset":207160,"length":175,"previous":"M16-GAP-01206","next":"M16-GAP-01208"},"M16-GAP-01208":{"line":1207,"offset":207335,"length":159,"previous":"M16-GAP-01207","next":"M16-GAP-01209"},"M16-GAP-01209":{"line":1208,"offset":207494,"length":168,"previous":"M16-GAP-01208","next":"M16-GAP-01210"},"M16-GAP-01210":{"line":1209,"offset":207662,"length":160,"previous":"M16-GAP-01209","next":"M16-GAP-01211"},"M16-GAP-01211":{"line":1210,"offset":207822,"length":159,"previous":"M16-GAP-01210","next":"M16-GAP-01212"},"M16-GAP-01212":{"line":1211,"offset":207981,"length":165,"previous":"M16-GAP-01211","next":"M16-GAP-01213"},"M16-GAP-01213":{"line":1212,"offset":208146,"length":168,"previous":"M16-GAP-01212","next":"M16-GAP-01214"},"M16-GAP-01214":{"line":1213,"offset":208314,"length":169,"previous":"M16-GAP-01213","next":"M16-GAP-01215"},"M16-GAP-01215":{"line":1214,"offset":208483,"length":170,"previous":"M16-GAP-01214","next":"M16-GAP-01216"},"M16-GAP-01216":{"line":1215,"offset":208653,"length":169,"previous":"M16-GAP-01215","next":"M16-GAP-01217"},"M16-GAP-01217":{"line":1216,"offset":208822,"length":163,"previous":"M16-GAP-01216","next":"M16-GAP-01218"},"M16-GAP-01218":{"line":1217,"offset":208985,"length":165,"previous":"M16-GAP-01217","next":"M16-GAP-01219"},"M16-GAP-01219":{"line":1218,"offset":209150,"length":168,"previous":"M16-GAP-01218","next":"M16-GAP-01220"},"M16-GAP-01220":{"line":1219,"offset":209318,"length":171,"previous":"M16-GAP-01219","next":"M16-GAP-01221"},"M16-GAP-01221":{"line":1220,"offset":209489,"length":172,"previous":"M16-GAP-01220","next":"M16-GAP-01222"},"M16-GAP-01222":{"line":1221,"offset":209661,"length":170,"previous":"M16-GAP-01221","next":"M16-GAP-01223"},"M16-GAP-01223":{"line":1222,"offset":209831,"length":165,"previous":"M16-GAP-01222","next":"M16-GAP-01224"},"M16-GAP-01224":{"line":1223,"offset":209996,"length":171,"previous":"M16-GAP-01223","next":"M16-GAP-01225"},"M16-GAP-01225":{"line":1224,"offset":210167,"length":189,"previous":"M16-GAP-01224","next":"M16-GAP-01226"},"M16-GAP-01226":{"line":1225,"offset":210356,"length":165,"previous":"M16-GAP-01225","next":"M16-GAP-01227"},"M16-GAP-01227":{"line":1226,"offset":210521,"length":171,"previous":"M16-GAP-01226","next":"M16-GAP-01228"},"M16-GAP-01228":{"line":1227,"offset":210692,"length":176,"previous":"M16-GAP-01227","next":"M16-GAP-01229"},"M16-GAP-01229":{"line":1228,"offset":210868,"length":165,"previous":"M16-GAP-01228","next":"M16-GAP-01230"},"M16-GAP-01230":{"line":1229,"offset":211033,"length":171,"previous":"M16-GAP-01229","next":"M16-GAP-01231"},"M16-GAP-01231":{"line":1230,"offset":211204,"length":164,"previous":"M16-GAP-01230","next":"M16-GAP-01232"},"M16-GAP-01232":{"line":1231,"offset":211368,"length":168,"previous":"M16-GAP-01231","next":"M16-GAP-01233"},"M16-GAP-01233":{"line":1232,"offset":211536,"length":164,"previous":"M16-GAP-01232","next":"M16-GAP-01234"},"M16-GAP-01234":{"line":1233,"offset":211700,"length":166,"previous":"M16-GAP-01233","next":"M16-GAP-01235"},"M16-GAP-01235":{"line":1234,"offset":211866,"length":171,"previous":"M16-GAP-01234","next":"M16-GAP-01236"},"M16-GAP-01236":{"line":1235,"offset":212037,"length":167,"previous":"M16-GAP-01235","next":"M16-GAP-01237"},"M16-GAP-01237":{"line":1236,"offset":212204,"length":175,"previous":"M16-GAP-01236","next":"M16-GAP-01238"},"M16-GAP-01238":{"line":1237,"offset":212379,"length":172,"previous":"M16-GAP-01237","next":"M16-GAP-01239"},"M16-GAP-01239":{"line":1238,"offset":212551,"length":164,"previous":"M16-GAP-01238","next":"M16-GAP-01240"},"M16-GAP-01240":{"line":1239,"offset":212715,"length":162,"previous":"M16-GAP-01239","next":"M16-GAP-01241"},"M16-GAP-01241":{"line":1240,"offset":212877,"length":169,"previous":"M16-GAP-01240","next":"M16-GAP-01242"},"M16-GAP-01242":{"line":1241,"offset":213046,"length":170,"previous":"M16-GAP-01241","next":"M16-GAP-01243"},"M16-GAP-01243":{"line":1242,"offset":213216,"length":172,"previous":"M16-GAP-01242","next":"M16-GAP-01244"},"M16-GAP-01244":{"line":1243,"offset":213388,"length":170,"previous":"M16-GAP-01243","next":"M16-GAP-01245"},"M16-GAP-01245":{"line":1244,"offset":213558,"length":174,"previous":"M16-GAP-01244","next":"M16-GAP-01246"},"M16-GAP-01246":{"line":1245,"offset":213732,"length":175,"previous":"M16-GAP-01245","next":"M16-GAP-01247"},"M16-GAP-01247":{"line":1246,"offset":213907,"length":177,"previous":"M16-GAP-01246","next":"M16-GAP-01248"},"M16-GAP-01248":{"line":1247,"offset":214084,"length":182,"previous":"M16-GAP-01247","next":"M16-GAP-01249"},"M16-GAP-01249":{"line":1248,"offset":214266,"length":183,"previous":"M16-GAP-01248","next":"M16-GAP-01250"},"M16-GAP-01250":{"line":1249,"offset":214449,"length":185,"previous":"M16-GAP-01249","next":"M16-GAP-01251"},"M16-GAP-01251":{"line":1250,"offset":214634,"length":175,"previous":"M16-GAP-01250","next":"M16-GAP-01252"},"M16-GAP-01252":{"line":1251,"offset":214809,"length":170,"previous":"M16-GAP-01251","next":"M16-GAP-01253"},"M16-GAP-01253":{"line":1252,"offset":214979,"length":171,"previous":"M16-GAP-01252","next":"M16-GAP-01254"},"M16-GAP-01254":{"line":1253,"offset":215150,"length":178,"previous":"M16-GAP-01253","next":"M16-GAP-01255"},"M16-GAP-01255":{"line":1254,"offset":215328,"length":179,"previous":"M16-GAP-01254","next":"M16-GAP-01256"},"M16-GAP-01256":{"line":1255,"offset":215507,"length":181,"previous":"M16-GAP-01255","next":"M16-GAP-01257"},"M16-GAP-01257":{"line":1256,"offset":215688,"length":179,"previous":"M16-GAP-01256","next":"M16-GAP-01258"},"M16-GAP-01258":{"line":1257,"offset":215867,"length":180,"previous":"M16-GAP-01257","next":"M16-GAP-01259"},"M16-GAP-01259":{"line":1258,"offset":216047,"length":182,"previous":"M16-GAP-01258","next":"M16-GAP-01260"},"M16-GAP-01260":{"line":1259,"offset":216229,"length":180,"previous":"M16-GAP-01259","next":"M16-GAP-01261"},"M16-GAP-01261":{"line":1260,"offset":216409,"length":181,"previous":"M16-GAP-01260","next":"M16-GAP-01262"},"M16-GAP-01262":{"line":1261,"offset":216590,"length":183,"previous":"M16-GAP-01261","next":"M16-GAP-01263"},"M16-GAP-01263":{"line":1262,"offset":216773,"length":183,"previous":"M16-GAP-01262","next":"M16-GAP-01264"},"M16-GAP-01264":{"line":1263,"offset":216956,"length":179,"previous":"M16-GAP-01263","next":"M16-GAP-01265"},"M16-GAP-01265":{"line":1264,"offset":217135,"length":180,"previous":"M16-GAP-01264","next":"M16-GAP-01266"},"M16-GAP-01266":{"line":1265,"offset":217315,"length":182,"previous":"M16-GAP-01265","next":"M16-GAP-01267"},"M16-GAP-01267":{"line":1266,"offset":217497,"length":173,"previous":"M16-GAP-01266","next":"M16-GAP-01268"},"M16-GAP-01268":{"line":1267,"offset":217670,"length":177,"previous":"M16-GAP-01267","next":"M16-GAP-01269"},"M16-GAP-01269":{"line":1268,"offset":217847,"length":180,"previous":"M16-GAP-01268","next":"M16-GAP-01270"},"M16-GAP-01270":{"line":1269,"offset":218027,"length":173,"previous":"M16-GAP-01269","next":"M16-GAP-01271"},"M16-GAP-01271":{"line":1270,"offset":218200,"length":179,"previous":"M16-GAP-01270","next":"M16-GAP-01272"},"M16-GAP-01272":{"line":1271,"offset":218379,"length":162,"previous":"M16-GAP-01271","next":"M16-GAP-01273"},"M16-GAP-01273":{"line":1272,"offset":218541,"length":177,"previous":"M16-GAP-01272","next":"M16-GAP-01274"},"M16-GAP-01274":{"line":1273,"offset":218718,"length":172,"previous":"M16-GAP-01273","next":"M16-GAP-01275"},"M16-GAP-01275":{"line":1274,"offset":218890,"length":162,"previous":"M16-GAP-01274","next":"M16-GAP-01276"},"M16-GAP-01276":{"line":1275,"offset":219052,"length":179,"previous":"M16-GAP-01275","next":"M16-GAP-01277"},"M16-GAP-01277":{"line":1276,"offset":219231,"length":165,"previous":"M16-GAP-01276","next":"M16-GAP-01278"},"M16-GAP-01278":{"line":1277,"offset":219396,"length":197,"previous":"M16-GAP-01277","next":"M16-GAP-01279"},"M16-GAP-01279":{"line":1278,"offset":219593,"length":188,"previous":"M16-GAP-01278","next":"M16-GAP-01280"},"M16-GAP-01280":{"line":1279,"offset":219781,"length":170,"previous":"M16-GAP-01279","next":"M16-GAP-01281"},"M16-GAP-01281":{"line":1280,"offset":219951,"length":182,"previous":"M16-GAP-01280","next":"M16-GAP-01282"},"M16-GAP-01282":{"line":1281,"offset":220133,"length":177,"previous":"M16-GAP-01281","next":"M16-GAP-01283"},"M16-GAP-01283":{"line":1282,"offset":220310,"length":180,"previous":"M16-GAP-01282","next":"M16-GAP-01284"},"M16-GAP-01284":{"line":1283,"offset":220490,"length":181,"previous":"M16-GAP-01283","next":"M16-GAP-01285"},"M16-GAP-01285":{"line":1284,"offset":220671,"length":183,"previous":"M16-GAP-01284","next":"M16-GAP-01286"},"M16-GAP-01286":{"line":1285,"offset":220854,"length":187,"previous":"M16-GAP-01285","next":"M16-GAP-01287"},"M16-GAP-01287":{"line":1286,"offset":221041,"length":188,"previous":"M16-GAP-01286","next":"M16-GAP-01288"},"M16-GAP-01288":{"line":1287,"offset":221229,"length":190,"previous":"M16-GAP-01287","next":"M16-GAP-01289"},"M16-GAP-01289":{"line":1288,"offset":221419,"length":188,"previous":"M16-GAP-01288","next":"M16-GAP-01290"},"M16-GAP-01290":{"line":1289,"offset":221607,"length":189,"previous":"M16-GAP-01289","next":"M16-GAP-01291"},"M16-GAP-01291":{"line":1290,"offset":221796,"length":191,"previous":"M16-GAP-01290","next":"M16-GAP-01292"},"M16-GAP-01292":{"line":1291,"offset":221987,"length":178,"previous":"M16-GAP-01291","next":"M16-GAP-01293"},"M16-GAP-01293":{"line":1292,"offset":222165,"length":179,"previous":"M16-GAP-01292","next":"M16-GAP-01294"},"M16-GAP-01294":{"line":1293,"offset":222344,"length":181,"previous":"M16-GAP-01293","next":"M16-GAP-01295"},"M16-GAP-01295":{"line":1294,"offset":222525,"length":178,"previous":"M16-GAP-01294","next":"M16-GAP-01296"},"M16-GAP-01296":{"line":1295,"offset":222703,"length":179,"previous":"M16-GAP-01295","next":"M16-GAP-01297"},"M16-GAP-01297":{"line":1296,"offset":222882,"length":181,"previous":"M16-GAP-01296","next":"M16-GAP-01298"},"M16-GAP-01298":{"line":1297,"offset":223063,"length":176,"previous":"M16-GAP-01297","next":"M16-GAP-01299"},"M16-GAP-01299":{"line":1298,"offset":223239,"length":177,"previous":"M16-GAP-01298","next":"M16-GAP-01300"},"M16-GAP-01300":{"line":1299,"offset":223416,"length":179,"previous":"M16-GAP-01299","next":"M16-GAP-01301"},"M16-GAP-01301":{"line":1300,"offset":223595,"length":165,"previous":"M16-GAP-01300","next":"M16-GAP-01302"},"M16-GAP-01302":{"line":1301,"offset":223760,"length":205,"previous":"M16-GAP-01301","next":"M16-GAP-01303"},"M16-GAP-01303":{"line":1302,"offset":223965,"length":206,"previous":"M16-GAP-01302","next":"M16-GAP-01304"},"M16-GAP-01304":{"line":1303,"offset":224171,"length":208,"previous":"M16-GAP-01303","next":"M16-GAP-01305"},"M16-GAP-01305":{"line":1304,"offset":224379,"length":200,"previous":"M16-GAP-01304","next":"M16-GAP-01306"},"M16-GAP-01306":{"line":1305,"offset":224579,"length":201,"previous":"M16-GAP-01305","next":"M16-GAP-01307"},"M16-GAP-01307":{"line":1306,"offset":224780,"length":203,"previous":"M16-GAP-01306","next":"M16-GAP-01308"},"M16-GAP-01308":{"line":1307,"offset":224983,"length":199,"previous":"M16-GAP-01307","next":"M16-GAP-01309"},"M16-GAP-01309":{"line":1308,"offset":225182,"length":200,"previous":"M16-GAP-01308","next":"M16-GAP-01310"},"M16-GAP-01310":{"line":1309,"offset":225382,"length":202,"previous":"M16-GAP-01309","next":"M16-GAP-01311"},"M16-GAP-01311":{"line":1310,"offset":225584,"length":178,"previous":"M16-GAP-01310","next":"M16-GAP-01312"},"M16-GAP-01312":{"line":1311,"offset":225762,"length":179,"previous":"M16-GAP-01311","next":"M16-GAP-01313"},"M16-GAP-01313":{"line":1312,"offset":225941,"length":181,"previous":"M16-GAP-01312","next":"M16-GAP-01314"},"M16-GAP-01314":{"line":1313,"offset":226122,"length":186,"previous":"M16-GAP-01313","next":"M16-GAP-01315"},"M16-GAP-01315":{"line":1314,"offset":226308,"length":187,"previous":"M16-GAP-01314","next":"M16-GAP-01316"},"M16-GAP-01316":{"line":1315,"offset":226495,"length":189,"previous":"M16-GAP-01315","next":"M16-GAP-01317"},"M16-GAP-01317":{"line":1316,"offset":226684,"length":183,"previous":"M16-GAP-01316","next":"M16-GAP-01318"},"M16-GAP-01318":{"line":1317,"offset":226867,"length":166,"previous":"M16-GAP-01317","next":"M16-GAP-01319"},"M16-GAP-01319":{"line":1318,"offset":227033,"length":172,"previous":"M16-GAP-01318","next":"M16-GAP-01320"},"M16-GAP-01320":{"line":1319,"offset":227205,"length":168,"previous":"M16-GAP-01319","next":"M16-GAP-01321"},"M16-GAP-01321":{"line":1320,"offset":227373,"length":166,"previous":"M16-GAP-01320","next":"M16-GAP-01322"},"M16-GAP-01322":{"line":1321,"offset":227539,"length":170,"previous":"M16-GAP-01321","next":"M16-GAP-01323"},"M16-GAP-01323":{"line":1322,"offset":227709,"length":169,"previous":"M16-GAP-01322","next":"M16-GAP-01324"},"M16-GAP-01324":{"line":1323,"offset":227878,"length":174,"previous":"M16-GAP-01323","next":"M16-GAP-01325"},"M16-GAP-01325":{"line":1324,"offset":228052,"length":167,"previous":"M16-GAP-01324","next":"M16-GAP-01326"},"M16-GAP-01326":{"line":1325,"offset":228219,"length":177,"previous":"M16-GAP-01325","next":"M16-GAP-01327"},"M16-GAP-01327":{"line":1326,"offset":228396,"length":178,"previous":"M16-GAP-01326","next":"M16-GAP-01328"},"M16-GAP-01328":{"line":1327,"offset":228574,"length":180,"previous":"M16-GAP-01327","next":"M16-GAP-01329"},"M16-GAP-01329":{"line":1328,"offset":228754,"length":169,"previous":"M16-GAP-01328","next":"M16-GAP-01330"},"M16-GAP-01330":{"line":1329,"offset":228923,"length":180,"previous":"M16-GAP-01329","next":"M16-GAP-01331"},"M16-GAP-01331":{"line":1330,"offset":229103,"length":188,"previous":"M16-GAP-01330","next":"M16-GAP-01332"},"M16-GAP-01332":{"line":1331,"offset":229291,"length":174,"previous":"M16-GAP-01331","next":"M16-GAP-01333"},"M16-GAP-01333":{"line":1332,"offset":229465,"length":187,"previous":"M16-GAP-01332","next":"M16-GAP-01334"},"M16-GAP-01334":{"line":1333,"offset":229652,"length":177,"previous":"M16-GAP-01333","next":"M16-GAP-01335"},"M16-GAP-01335":{"line":1334,"offset":229829,"length":190,"previous":"M16-GAP-01334","next":"M16-GAP-01336"},"M16-GAP-01336":{"line":1335,"offset":230019,"length":160,"previous":"M16-GAP-01335","next":"M16-GAP-01337"},"M16-GAP-01337":{"line":1336,"offset":230179,"length":166,"previous":"M16-GAP-01336","next":"M16-GAP-01338"},"M16-GAP-01338":{"line":1337,"offset":230345,"length":166,"previous":"M16-GAP-01337","next":"M16-GAP-01339"},"M16-GAP-01339":{"line":1338,"offset":230511,"length":160,"previous":"M16-GAP-01338","next":"M16-GAP-01340"},"M16-GAP-01340":{"line":1339,"offset":230671,"length":180,"previous":"M16-GAP-01339","next":"M16-GAP-01341"},"M16-GAP-01341":{"line":1340,"offset":230851,"length":165,"previous":"M16-GAP-01340","next":"M16-GAP-01342"},"M16-GAP-01342":{"line":1341,"offset":231016,"length":167,"previous":"M16-GAP-01341","next":"M16-GAP-01343"},"M16-GAP-01343":{"line":1342,"offset":231183,"length":165,"previous":"M16-GAP-01342","next":"M16-GAP-01344"},"M16-GAP-01344":{"line":1343,"offset":231348,"length":168,"previous":"M16-GAP-01343","next":"M16-GAP-01345"},"M16-GAP-01345":{"line":1344,"offset":231516,"length":166,"previous":"M16-GAP-01344","next":"M16-GAP-01346"},"M16-GAP-01346":{"line":1345,"offset":231682,"length":173,"previous":"M16-GAP-01345","next":"M16-GAP-01347"},"M16-GAP-01347":{"line":1346,"offset":231855,"length":181,"previous":"M16-GAP-01346","next":"M16-GAP-01348"},"M16-GAP-01348":{"line":1347,"offset":232036,"length":167,"previous":"M16-GAP-01347","next":"M16-GAP-01349"},"M16-GAP-01349":{"line":1348,"offset":232203,"length":182,"previous":"M16-GAP-01348","next":"M16-GAP-01350"},"M16-GAP-01350":{"line":1349,"offset":232385,"length":191,"previous":"M16-GAP-01349","next":"M16-GAP-01351"},"M16-GAP-01351":{"line":1350,"offset":232576,"length":186,"previous":"M16-GAP-01350","next":"M16-GAP-01352"},"M16-GAP-01352":{"line":1351,"offset":232762,"length":184,"previous":"M16-GAP-01351","next":"M16-GAP-01353"},"M16-GAP-01353":{"line":1352,"offset":232946,"length":183,"previous":"M16-GAP-01352","next":"M16-GAP-01354"},"M16-GAP-01354":{"line":1353,"offset":233129,"length":169,"previous":"M16-GAP-01353","next":"M16-GAP-01355"},"M16-GAP-01355":{"line":1354,"offset":233298,"length":177,"previous":"M16-GAP-01354","next":"M16-GAP-01356"},"M16-GAP-01356":{"line":1355,"offset":233475,"length":171,"previous":"M16-GAP-01355","next":"M16-GAP-01357"},"M16-GAP-01357":{"line":1356,"offset":233646,"length":170,"previous":"M16-GAP-01356","next":"M16-GAP-01358"},"M16-GAP-01358":{"line":1357,"offset":233816,"length":166,"previous":"M16-GAP-01357","next":"M16-GAP-01359"},"M16-GAP-01359":{"line":1358,"offset":233982,"length":170,"previous":"M16-GAP-01358","next":"M16-GAP-01360"},"M16-GAP-01360":{"line":1359,"offset":234152,"length":171,"previous":"M16-GAP-01359","next":"M16-GAP-01361"},"M16-GAP-01361":{"line":1360,"offset":234323,"length":170,"previous":"M16-GAP-01360","next":"M16-GAP-01362"},"M16-GAP-01362":{"line":1361,"offset":234493,"length":176,"previous":"M16-GAP-01361","next":"M16-GAP-01363"},"M16-GAP-01363":{"line":1362,"offset":234669,"length":177,"previous":"M16-GAP-01362","next":"M16-GAP-01364"},"M16-GAP-01364":{"line":1363,"offset":234846,"length":179,"previous":"M16-GAP-01363","next":"M16-GAP-01365"},"M16-GAP-01365":{"line":1364,"offset":235025,"length":162,"previous":"M16-GAP-01364","next":"M16-GAP-01366"},"M16-GAP-01366":{"line":1365,"offset":235187,"length":187,"previous":"M16-GAP-01365","next":"M16-GAP-01367"},"M16-GAP-01367":{"line":1366,"offset":235374,"length":188,"previous":"M16-GAP-01366","next":"M16-GAP-01368"},"M16-GAP-01368":{"line":1367,"offset":235562,"length":190,"previous":"M16-GAP-01367","next":"M16-GAP-01369"},"M16-GAP-01369":{"line":1368,"offset":235752,"length":162,"previous":"M16-GAP-01368","next":"M16-GAP-01370"},"M16-GAP-01370":{"line":1369,"offset":235914,"length":166,"previous":"M16-GAP-01369","next":"M16-GAP-01371"},"M16-GAP-01371":{"line":1370,"offset":236080,"length":166,"previous":"M16-GAP-01370","next":"M16-GAP-01372"},"M16-GAP-01372":{"line":1371,"offset":236246,"length":169,"previous":"M16-GAP-01371","next":"M16-GAP-01373"},"M16-GAP-01373":{"line":1372,"offset":236415,"length":170,"previous":"M16-GAP-01372","next":"M16-GAP-01374"},"M16-GAP-01374":{"line":1373,"offset":236585,"length":168,"previous":"M16-GAP-01373","next":"M16-GAP-01375"},"M16-GAP-01375":{"line":1374,"offset":236753,"length":174,"previous":"M16-GAP-01374","next":"M16-GAP-01376"},"M16-GAP-01376":{"line":1375,"offset":236927,"length":174,"previous":"M16-GAP-01375","next":"M16-GAP-01377"},"M16-GAP-01377":{"line":1376,"offset":237101,"length":172,"previous":"M16-GAP-01376","next":"M16-GAP-01378"},"M16-GAP-01378":{"line":1377,"offset":237273,"length":177,"previous":"M16-GAP-01377","next":"M16-GAP-01379"},"M16-GAP-01379":{"line":1378,"offset":237450,"length":180,"previous":"M16-GAP-01378","next":"M16-GAP-01380"},"M16-GAP-01380":{"line":1379,"offset":237630,"length":181,"previous":"M16-GAP-01379","next":"M16-GAP-01381"},"M16-GAP-01381":{"line":1380,"offset":237811,"length":183,"previous":"M16-GAP-01380","next":"M16-GAP-01382"},"M16-GAP-01382":{"line":1381,"offset":237994,"length":176,"previous":"M16-GAP-01381","next":"M16-GAP-01383"},"M16-GAP-01383":{"line":1382,"offset":238170,"length":180,"previous":"M16-GAP-01382","next":"M16-GAP-01384"},"M16-GAP-01384":{"line":1383,"offset":238350,"length":181,"previous":"M16-GAP-01383","next":"M16-GAP-01385"},"M16-GAP-01385":{"line":1384,"offset":238531,"length":183,"previous":"M16-GAP-01384","next":"M16-GAP-01386"},"M16-GAP-01386":{"line":1385,"offset":238714,"length":168,"previous":"M16-GAP-01385","next":"M16-GAP-01387"},"M16-GAP-01387":{"line":1386,"offset":238882,"length":172,"previous":"M16-GAP-01386","next":"M16-GAP-01388"},"M16-GAP-01388":{"line":1387,"offset":239054,"length":172,"previous":"M16-GAP-01387","next":"M16-GAP-01389"},"M16-GAP-01389":{"line":1388,"offset":239226,"length":165,"previous":"M16-GAP-01388","next":"M16-GAP-01390"},"M16-GAP-01390":{"line":1389,"offset":239391,"length":173,"previous":"M16-GAP-01389","next":"M16-GAP-01391"},"M16-GAP-01391":{"line":1390,"offset":239564,"length":165,"previous":"M16-GAP-01390","next":"M16-GAP-01392"},"M16-GAP-01392":{"line":1391,"offset":239729,"length":182,"previous":"M16-GAP-01391","next":"M16-GAP-01393"},"M16-GAP-01393":{"line":1392,"offset":239911,"length":169,"previous":"M16-GAP-01392","next":"M16-GAP-01394"},"M16-GAP-01394":{"line":1393,"offset":240080,"length":172,"previous":"M16-GAP-01393","next":"M16-GAP-01395"},"M16-GAP-01395":{"line":1394,"offset":240252,"length":189,"previous":"M16-GAP-01394","next":"M16-GAP-01396"},"M16-GAP-01396":{"line":1395,"offset":240441,"length":172,"previous":"M16-GAP-01395","next":"M16-GAP-01397"},"M16-GAP-01397":{"line":1396,"offset":240613,"length":164,"previous":"M16-GAP-01396","next":"M16-GAP-01398"},"M16-GAP-01398":{"line":1397,"offset":240777,"length":169,"previous":"M16-GAP-01397","next":"M16-GAP-01399"},"M16-GAP-01399":{"line":1398,"offset":240946,"length":169,"previous":"M16-GAP-01398","next":"M16-GAP-01400"},"M16-GAP-01400":{"line":1399,"offset":241115,"length":175,"previous":"M16-GAP-01399","next":"M16-GAP-01401"},"M16-GAP-01401":{"line":1400,"offset":241290,"length":175,"previous":"M16-GAP-01400","next":"M16-GAP-01402"},"M16-GAP-01402":{"line":1401,"offset":241465,"length":161,"previous":"M16-GAP-01401","next":"M16-GAP-01403"},"M16-GAP-01403":{"line":1402,"offset":241626,"length":175,"previous":"M16-GAP-01402","next":"M16-GAP-01404"},"M16-GAP-01404":{"line":1403,"offset":241801,"length":167,"previous":"M16-GAP-01403","next":"M16-GAP-01405"},"M16-GAP-01405":{"line":1404,"offset":241968,"length":163,"previous":"M16-GAP-01404","next":"M16-GAP-01406"},"M16-GAP-01406":{"line":1405,"offset":242131,"length":183,"previous":"M16-GAP-01405","next":"M16-GAP-01407"},"M16-GAP-01407":{"line":1406,"offset":242314,"length":170,"previous":"M16-GAP-01406","next":"M16-GAP-01408"},"M16-GAP-01408":{"line":1407,"offset":242484,"length":182,"previous":"M16-GAP-01407","next":"M16-GAP-01409"},"M16-GAP-01409":{"line":1408,"offset":242666,"length":162,"previous":"M16-GAP-01408","next":"M16-GAP-01410"},"M16-GAP-01410":{"line":1409,"offset":242828,"length":168,"previous":"M16-GAP-01409","next":"M16-GAP-01411"},"M16-GAP-01411":{"line":1410,"offset":242996,"length":168,"previous":"M16-GAP-01410","next":"M16-GAP-01412"},"M16-GAP-01412":{"line":1411,"offset":243164,"length":178,"previous":"M16-GAP-01411","next":"M16-GAP-01413"},"M16-GAP-01413":{"line":1412,"offset":243342,"length":180,"previous":"M16-GAP-01412","next":"M16-GAP-01414"},"M16-GAP-01414":{"line":1413,"offset":243522,"length":172,"previous":"M16-GAP-01413","next":"M16-GAP-01415"},"M16-GAP-01415":{"line":1414,"offset":243694,"length":188,"previous":"M16-GAP-01414","next":"M16-GAP-01416"},"M16-GAP-01416":{"line":1415,"offset":243882,"length":181,"previous":"M16-GAP-01415","next":"M16-GAP-01417"},"M16-GAP-01417":{"line":1416,"offset":244063,"length":173,"previous":"M16-GAP-01416","next":"M16-GAP-01418"},"M16-GAP-01418":{"line":1417,"offset":244236,"length":183,"previous":"M16-GAP-01417","next":"M16-GAP-01419"},"M16-GAP-01419":{"line":1418,"offset":244419,"length":175,"previous":"M16-GAP-01418","next":"M16-GAP-01420"},"M16-GAP-01420":{"line":1419,"offset":244594,"length":175,"previous":"M16-GAP-01419","next":"M16-GAP-01421"},"M16-GAP-01421":{"line":1420,"offset":244769,"length":172,"previous":"M16-GAP-01420","next":"M16-GAP-01422"},"M16-GAP-01422":{"line":1421,"offset":244941,"length":185,"previous":"M16-GAP-01421","next":"M16-GAP-01423"},"M16-GAP-01423":{"line":1422,"offset":245126,"length":175,"previous":"M16-GAP-01422","next":"M16-GAP-01424"},"M16-GAP-01424":{"line":1423,"offset":245301,"length":174,"previous":"M16-GAP-01423","next":"M16-GAP-01425"},"M16-GAP-01425":{"line":1424,"offset":245475,"length":165,"previous":"M16-GAP-01424","next":"M16-GAP-01426"},"M16-GAP-01426":{"line":1425,"offset":245640,"length":179,"previous":"M16-GAP-01425","next":"M16-GAP-01427"},"M16-GAP-01427":{"line":1426,"offset":245819,"length":181,"previous":"M16-GAP-01426","next":"M16-GAP-01428"},"M16-GAP-01428":{"line":1427,"offset":246000,"length":179,"previous":"M16-GAP-01427","next":"M16-GAP-01429"},"M16-GAP-01429":{"line":1428,"offset":246179,"length":179,"previous":"M16-GAP-01428","next":"M16-GAP-01430"},"M16-GAP-01430":{"line":1429,"offset":246358,"length":175,"previous":"M16-GAP-01429","next":"M16-GAP-01431"},"M16-GAP-01431":{"line":1430,"offset":246533,"length":175,"previous":"M16-GAP-01430","next":"M16-GAP-01432"},"M16-GAP-01432":{"line":1431,"offset":246708,"length":171,"previous":"M16-GAP-01431","next":"M16-GAP-01433"},"M16-GAP-01433":{"line":1432,"offset":246879,"length":177,"previous":"M16-GAP-01432","next":"M16-GAP-01434"},"M16-GAP-01434":{"line":1433,"offset":247056,"length":164,"previous":"M16-GAP-01433","next":"M16-GAP-01435"},"M16-GAP-01435":{"line":1434,"offset":247220,"length":183,"previous":"M16-GAP-01434","next":"M16-GAP-01436"},"M16-GAP-01436":{"line":1435,"offset":247403,"length":177,"previous":"M16-GAP-01435","next":"M16-GAP-01437"},"M16-GAP-01437":{"line":1436,"offset":247580,"length":177,"previous":"M16-GAP-01436","next":"M16-GAP-01438"},"M16-GAP-01438":{"line":1437,"offset":247757,"length":167,"previous":"M16-GAP-01437","next":"M16-GAP-01439"},"M16-GAP-01439":{"line":1438,"offset":247924,"length":172,"previous":"M16-GAP-01438","next":"M16-GAP-01440"},"M16-GAP-01440":{"line":1439,"offset":248096,"length":179,"previous":"M16-GAP-01439","next":"M16-GAP-01441"},"M16-GAP-01441":{"line":1440,"offset":248275,"length":178,"previous":"M16-GAP-01440","next":"M16-GAP-01442"},"M16-GAP-01442":{"line":1441,"offset":248453,"length":173,"previous":"M16-GAP-01441","next":"M16-GAP-01443"},"M16-GAP-01443":{"line":1442,"offset":248626,"length":170,"previous":"M16-GAP-01442","next":"M16-GAP-01444"},"M16-GAP-01444":{"line":1443,"offset":248796,"length":167,"previous":"M16-GAP-01443","next":"M16-GAP-01445"},"M16-GAP-01445":{"line":1444,"offset":248963,"length":173,"previous":"M16-GAP-01444","next":"M16-GAP-01446"},"M16-GAP-01446":{"line":1445,"offset":249136,"length":173,"previous":"M16-GAP-01445","next":"M16-GAP-01447"},"M16-GAP-01447":{"line":1446,"offset":249309,"length":171,"previous":"M16-GAP-01446","next":"M16-GAP-01448"},"M16-GAP-01448":{"line":1447,"offset":249480,"length":175,"previous":"M16-GAP-01447","next":"M16-GAP-01449"},"M16-GAP-01449":{"line":1448,"offset":249655,"length":190,"previous":"M16-GAP-01448","next":"M16-GAP-01450"},"M16-GAP-01450":{"line":1449,"offset":249845,"length":188,"previous":"M16-GAP-01449","next":"M16-GAP-01451"},"M16-GAP-01451":{"line":1450,"offset":250033,"length":183,"previous":"M16-GAP-01450","next":"M16-GAP-01452"},"M16-GAP-01452":{"line":1451,"offset":250216,"length":190,"previous":"M16-GAP-01451","next":"M16-GAP-01453"},"M16-GAP-01453":{"line":1452,"offset":250406,"length":188,"previous":"M16-GAP-01452","next":"M16-GAP-01454"},"M16-GAP-01454":{"line":1453,"offset":250594,"length":195,"previous":"M16-GAP-01453","next":"M16-GAP-01455"},"M16-GAP-01455":{"line":1454,"offset":250789,"length":186,"previous":"M16-GAP-01454","next":"M16-GAP-01456"},"M16-GAP-01456":{"line":1455,"offset":250975,"length":175,"previous":"M16-GAP-01455","next":"M16-GAP-01457"},"M16-GAP-01457":{"line":1456,"offset":251150,"length":197,"previous":"M16-GAP-01456","next":"M16-GAP-01458"},"M16-GAP-01458":{"line":1457,"offset":251347,"length":198,"previous":"M16-GAP-01457","next":"M16-GAP-01459"},"M16-GAP-01459":{"line":1458,"offset":251545,"length":200,"previous":"M16-GAP-01458","next":"M16-GAP-01460"},"M16-GAP-01460":{"line":1459,"offset":251745,"length":197,"previous":"M16-GAP-01459","next":"M16-GAP-01461"},"M16-GAP-01461":{"line":1460,"offset":251942,"length":198,"previous":"M16-GAP-01460","next":"M16-GAP-01462"},"M16-GAP-01462":{"line":1461,"offset":252140,"length":200,"previous":"M16-GAP-01461","next":"M16-GAP-01463"},"M16-GAP-01463":{"line":1462,"offset":252340,"length":173,"previous":"M16-GAP-01462","next":"M16-GAP-01464"},"M16-GAP-01464":{"line":1463,"offset":252513,"length":179,"previous":"M16-GAP-01463","next":"M16-GAP-01465"},"M16-GAP-01465":{"line":1464,"offset":252692,"length":173,"previous":"M16-GAP-01464","next":"M16-GAP-01466"},"M16-GAP-01466":{"line":1465,"offset":252865,"length":171,"previous":"M16-GAP-01465","next":"M16-GAP-01467"},"M16-GAP-01467":{"line":1466,"offset":253036,"length":172,"previous":"M16-GAP-01466","next":"M16-GAP-01468"},"M16-GAP-01468":{"line":1467,"offset":253208,"length":172,"previous":"M16-GAP-01467","next":"M16-GAP-01469"},"M16-GAP-01469":{"line":1468,"offset":253380,"length":169,"previous":"M16-GAP-01468","next":"M16-GAP-01470"},"M16-GAP-01470":{"line":1469,"offset":253549,"length":171,"previous":"M16-GAP-01469","next":"M16-GAP-01471"},"M16-GAP-01471":{"line":1470,"offset":253720,"length":169,"previous":"M16-GAP-01470","next":"M16-GAP-01472"},"M16-GAP-01472":{"line":1471,"offset":253889,"length":168,"previous":"M16-GAP-01471","next":"M16-GAP-01473"},"M16-GAP-01473":{"line":1472,"offset":254057,"length":169,"previous":"M16-GAP-01472","next":"M16-GAP-01474"},"M16-GAP-01474":{"line":1473,"offset":254226,"length":185,"previous":"M16-GAP-01473","next":"M16-GAP-01475"},"M16-GAP-01475":{"line":1474,"offset":254411,"length":185,"previous":"M16-GAP-01474","next":"M16-GAP-01476"},"M16-GAP-01476":{"line":1475,"offset":254596,"length":183,"previous":"M16-GAP-01475","next":"M16-GAP-01477"},"M16-GAP-01477":{"line":1476,"offset":254779,"length":177,"previous":"M16-GAP-01476","next":"M16-GAP-01478"},"M16-GAP-01478":{"line":1477,"offset":254956,"length":162,"previous":"M16-GAP-01477","next":"M16-GAP-01479"},"M16-GAP-01479":{"line":1478,"offset":255118,"length":169,"previous":"M16-GAP-01478","next":"M16-GAP-01480"},"M16-GAP-01480":{"line":1479,"offset":255287,"length":166,"previous":"M16-GAP-01479","next":"M16-GAP-01481"},"M16-GAP-01481":{"line":1480,"offset":255453,"length":178,"previous":"M16-GAP-01480","next":"M16-GAP-01482"},"M16-GAP-01482":{"line":1481,"offset":255631,"length":181,"previous":"M16-GAP-01481","next":"M16-GAP-01483"},"M16-GAP-01483":{"line":1482,"offset":255812,"length":167,"previous":"M16-GAP-01482","next":"M16-GAP-01484"},"M16-GAP-01484":{"line":1483,"offset":255979,"length":194,"previous":"M16-GAP-01483","next":"M16-GAP-01485"},"M16-GAP-01485":{"line":1484,"offset":256173,"length":185,"previous":"M16-GAP-01484","next":"M16-GAP-01486"},"M16-GAP-01486":{"line":1485,"offset":256358,"length":187,"previous":"M16-GAP-01485","next":"M16-GAP-01487"},"M16-GAP-01487":{"line":1486,"offset":256545,"length":195,"previous":"M16-GAP-01486","next":"M16-GAP-01488"},"M16-GAP-01488":{"line":1487,"offset":256740,"length":186,"previous":"M16-GAP-01487","next":"M16-GAP-01489"},"M16-GAP-01489":{"line":1488,"offset":256926,"length":188,"previous":"M16-GAP-01488","next":"M16-GAP-01490"},"M16-GAP-01490":{"line":1489,"offset":257114,"length":194,"previous":"M16-GAP-01489","next":"M16-GAP-01491"},"M16-GAP-01491":{"line":1490,"offset":257308,"length":172,"previous":"M16-GAP-01490","next":"M16-GAP-01492"},"M16-GAP-01492":{"line":1491,"offset":257480,"length":179,"previous":"M16-GAP-01491","next":"M16-GAP-01493"},"M16-GAP-01493":{"line":1492,"offset":257659,"length":179,"previous":"M16-GAP-01492","next":"M16-GAP-01494"},"M16-GAP-01494":{"line":1493,"offset":257838,"length":178,"previous":"M16-GAP-01493","next":"M16-GAP-01495"},"M16-GAP-01495":{"line":1494,"offset":258016,"length":171,"previous":"M16-GAP-01494","next":"M16-GAP-01496"},"M16-GAP-01496":{"line":1495,"offset":258187,"length":176,"previous":"M16-GAP-01495","next":"M16-GAP-01497"},"M16-GAP-01497":{"line":1496,"offset":258363,"length":172,"previous":"M16-GAP-01496","next":"M16-GAP-01498"},"M16-GAP-01498":{"line":1497,"offset":258535,"length":173,"previous":"M16-GAP-01497","next":"M16-GAP-01499"},"M16-GAP-01499":{"line":1498,"offset":258708,"length":173,"previous":"M16-GAP-01498","next":"M16-GAP-01500"},"M16-GAP-01500":{"line":1499,"offset":258881,"length":174,"previous":"M16-GAP-01499","next":"M16-GAP-01501"},"M16-GAP-01501":{"line":1500,"offset":259055,"length":168,"previous":"M16-GAP-01500","next":"M16-GAP-01502"},"M16-GAP-01502":{"line":1501,"offset":259223,"length":179,"previous":"M16-GAP-01501","next":"M16-GAP-01503"},"M16-GAP-01503":{"line":1502,"offset":259402,"length":174,"previous":"M16-GAP-01502","next":"M16-GAP-01504"},"M16-GAP-01504":{"line":1503,"offset":259576,"length":175,"previous":"M16-GAP-01503","next":"M16-GAP-01505"},"M16-GAP-01505":{"line":1504,"offset":259751,"length":178,"previous":"M16-GAP-01504","next":"M16-GAP-01506"},"M16-GAP-01506":{"line":1505,"offset":259929,"length":176,"previous":"M16-GAP-01505","next":"M16-GAP-01507"},"M16-GAP-01507":{"line":1506,"offset":260105,"length":180,"previous":"M16-GAP-01506","next":"M16-GAP-01508"},"M16-GAP-01508":{"line":1507,"offset":260285,"length":176,"previous":"M16-GAP-01507","next":"M16-GAP-01509"},"M16-GAP-01509":{"line":1508,"offset":260461,"length":178,"previous":"M16-GAP-01508","next":"M16-GAP-01510"},"M16-GAP-01510":{"line":1509,"offset":260639,"length":182,"previous":"M16-GAP-01509","next":"M16-GAP-01511"},"M16-GAP-01511":{"line":1510,"offset":260821,"length":185,"previous":"M16-GAP-01510","next":"M16-GAP-01512"},"M16-GAP-01512":{"line":1511,"offset":261006,"length":178,"previous":"M16-GAP-01511","next":"M16-GAP-01513"},"M16-GAP-01513":{"line":1512,"offset":261184,"length":173,"previous":"M16-GAP-01512","next":"M16-GAP-01514"},"M16-GAP-01514":{"line":1513,"offset":261357,"length":170,"previous":"M16-GAP-01513","next":"M16-GAP-01515"},"M16-GAP-01515":{"line":1514,"offset":261527,"length":166,"previous":"M16-GAP-01514","next":"M16-GAP-01516"},"M16-GAP-01516":{"line":1515,"offset":261693,"length":179,"previous":"M16-GAP-01515","next":"M16-GAP-01517"},"M16-GAP-01517":{"line":1516,"offset":261872,"length":170,"previous":"M16-GAP-01516","next":"M16-GAP-01518"},"M16-GAP-01518":{"line":1517,"offset":262042,"length":181,"previous":"M16-GAP-01517","next":"M16-GAP-01519"},"M16-GAP-01519":{"line":1518,"offset":262223,"length":172,"previous":"M16-GAP-01518","next":"M16-GAP-01520"},"M16-GAP-01520":{"line":1519,"offset":262395,"length":184,"previous":"M16-GAP-01519","next":"M16-GAP-01521"},"M16-GAP-01521":{"line":1520,"offset":262579,"length":174,"previous":"M16-GAP-01520","next":"M16-GAP-01522"},"M16-GAP-01522":{"line":1521,"offset":262753,"length":171,"previous":"M16-GAP-01521","next":"M16-GAP-01523"},"M16-GAP-01523":{"line":1522,"offset":262924,"length":183,"previous":"M16-GAP-01522","next":"M16-GAP-01524"},"M16-GAP-01524":{"line":1523,"offset":263107,"length":176,"previous":"M16-GAP-01523","next":"M16-GAP-01525"},"M16-GAP-01525":{"line":1524,"offset":263283,"length":180,"previous":"M16-GAP-01524","next":"M16-GAP-01526"},"M16-GAP-01526":{"line":1525,"offset":263463,"length":174,"previous":"M16-GAP-01525","next":"M16-GAP-01527"},"M16-GAP-01527":{"line":1526,"offset":263637,"length":173,"previous":"M16-GAP-01526","next":"M16-GAP-01528"},"M16-GAP-01528":{"line":1527,"offset":263810,"length":177,"previous":"M16-GAP-01527","next":"M16-GAP-01529"},"M16-GAP-01529":{"line":1528,"offset":263987,"length":173,"previous":"M16-GAP-01528","next":"M16-GAP-01530"},"M16-GAP-01530":{"line":1529,"offset":264160,"length":184,"previous":"M16-GAP-01529","next":"M16-GAP-01531"},"M16-GAP-01531":{"line":1530,"offset":264344,"length":176,"previous":"M16-GAP-01530","next":"M16-GAP-01532"},"M16-GAP-01532":{"line":1531,"offset":264520,"length":177,"previous":"M16-GAP-01531","next":"M16-GAP-01533"},"M16-GAP-01533":{"line":1532,"offset":264697,"length":180,"previous":"M16-GAP-01532","next":"M16-GAP-01534"},"M16-GAP-01534":{"line":1533,"offset":264877,"length":180,"previous":"M16-GAP-01533","next":"M16-GAP-01535"},"M16-GAP-01535":{"line":1534,"offset":265057,"length":187,"previous":"M16-GAP-01534","next":"M16-GAP-01536"},"M16-GAP-01536":{"line":1535,"offset":265244,"length":181,"previous":"M16-GAP-01535","next":"M16-GAP-01537"},"M16-GAP-01537":{"line":1536,"offset":265425,"length":174,"previous":"M16-GAP-01536","next":"M16-GAP-01538"},"M16-GAP-01538":{"line":1537,"offset":265599,"length":176,"previous":"M16-GAP-01537","next":"M16-GAP-01539"},"M16-GAP-01539":{"line":1538,"offset":265775,"length":178,"previous":"M16-GAP-01538","next":"M16-GAP-01540"},"M16-GAP-01540":{"line":1539,"offset":265953,"length":168,"previous":"M16-GAP-01539","next":"M16-GAP-01541"},"M16-GAP-01541":{"line":1540,"offset":266121,"length":170,"previous":"M16-GAP-01540","next":"M16-GAP-01542"},"M16-GAP-01542":{"line":1541,"offset":266291,"length":168,"previous":"M16-GAP-01541","next":"M16-GAP-01543"},"M16-GAP-01543":{"line":1542,"offset":266459,"length":170,"previous":"M16-GAP-01542","next":"M16-GAP-01544"},"M16-GAP-01544":{"line":1543,"offset":266629,"length":178,"previous":"M16-GAP-01543","next":"M16-GAP-01545"},"M16-GAP-01545":{"line":1544,"offset":266807,"length":179,"previous":"M16-GAP-01544","next":"M16-GAP-01546"},"M16-GAP-01546":{"line":1545,"offset":266986,"length":168,"previous":"M16-GAP-01545","next":"M16-GAP-01547"},"M16-GAP-01547":{"line":1546,"offset":267154,"length":177,"previous":"M16-GAP-01546","next":"M16-GAP-01548"},"M16-GAP-01548":{"line":1547,"offset":267331,"length":180,"previous":"M16-GAP-01547","next":"M16-GAP-01549"},"M16-GAP-01549":{"line":1548,"offset":267511,"length":173,"previous":"M16-GAP-01548","next":"M16-GAP-01550"},"M16-GAP-01550":{"line":1549,"offset":267684,"length":173,"previous":"M16-GAP-01549","next":"M16-GAP-01551"},"M16-GAP-01551":{"line":1550,"offset":267857,"length":169,"previous":"M16-GAP-01550","next":"M16-GAP-01552"},"M16-GAP-01552":{"line":1551,"offset":268026,"length":170,"previous":"M16-GAP-01551","next":"M16-GAP-01553"},"M16-GAP-01553":{"line":1552,"offset":268196,"length":178,"previous":"M16-GAP-01552","next":"M16-GAP-01554"},"M16-GAP-01554":{"line":1553,"offset":268374,"length":179,"previous":"M16-GAP-01553","next":"M16-GAP-01555"},"M16-GAP-01555":{"line":1554,"offset":268553,"length":173,"previous":"M16-GAP-01554","next":"M16-GAP-01556"},"M16-GAP-01556":{"line":1555,"offset":268726,"length":175,"previous":"M16-GAP-01555","next":"M16-GAP-01557"},"M16-GAP-01557":{"line":1556,"offset":268901,"length":171,"previous":"M16-GAP-01556","next":"M16-GAP-01558"},"M16-GAP-01558":{"line":1557,"offset":269072,"length":167,"previous":"M16-GAP-01557","next":"M16-GAP-01559"},"M16-GAP-01559":{"line":1558,"offset":269239,"length":170,"previous":"M16-GAP-01558","next":"M16-GAP-01560"},"M16-GAP-01560":{"line":1559,"offset":269409,"length":169,"previous":"M16-GAP-01559","next":"M16-GAP-01561"},"M16-GAP-01561":{"line":1560,"offset":269578,"length":177,"previous":"M16-GAP-01560","next":"M16-GAP-01562"},"M16-GAP-01562":{"line":1561,"offset":269755,"length":180,"previous":"M16-GAP-01561","next":"M16-GAP-01563"},"M16-GAP-01563":{"line":1562,"offset":269935,"length":172,"previous":"M16-GAP-01562","next":"M16-GAP-01564"},"M16-GAP-01564":{"line":1563,"offset":270107,"length":169,"previous":"M16-GAP-01563","next":"M16-GAP-01565"},"M16-GAP-01565":{"line":1564,"offset":270276,"length":168,"previous":"M16-GAP-01564","next":"M16-GAP-01566"},"M16-GAP-01566":{"line":1565,"offset":270444,"length":172,"previous":"M16-GAP-01565","next":"M16-GAP-01567"},"M16-GAP-01567":{"line":1566,"offset":270616,"length":171,"previous":"M16-GAP-01566","next":"M16-GAP-01568"},"M16-GAP-01568":{"line":1567,"offset":270787,"length":172,"previous":"M16-GAP-01567","next":"M16-GAP-01569"},"M16-GAP-01569":{"line":1568,"offset":270959,"length":174,"previous":"M16-GAP-01568","next":"M16-GAP-01570"},"M16-GAP-01570":{"line":1569,"offset":271133,"length":169,"previous":"M16-GAP-01569","next":"M16-GAP-01571"},"M16-GAP-01571":{"line":1570,"offset":271302,"length":171,"previous":"M16-GAP-01570","next":"M16-GAP-01572"},"M16-GAP-01572":{"line":1571,"offset":271473,"length":171,"previous":"M16-GAP-01571","next":"M16-GAP-01573"},"M16-GAP-01573":{"line":1572,"offset":271644,"length":169,"previous":"M16-GAP-01572","next":"M16-GAP-01574"},"M16-GAP-01574":{"line":1573,"offset":271813,"length":172,"previous":"M16-GAP-01573","next":"M16-GAP-01575"},"M16-GAP-01575":{"line":1574,"offset":271985,"length":171,"previous":"M16-GAP-01574","next":"M16-GAP-01576"},"M16-GAP-01576":{"line":1575,"offset":272156,"length":180,"previous":"M16-GAP-01575","next":"M16-GAP-01577"},"M16-GAP-01577":{"line":1576,"offset":272336,"length":175,"previous":"M16-GAP-01576","next":"M16-GAP-01578"},"M16-GAP-01578":{"line":1577,"offset":272511,"length":168,"previous":"M16-GAP-01577","next":"M16-GAP-01579"},"M16-GAP-01579":{"line":1578,"offset":272679,"length":170,"previous":"M16-GAP-01578","next":"M16-GAP-01580"},"M16-GAP-01580":{"line":1579,"offset":272849,"length":179,"previous":"M16-GAP-01579","next":"M16-GAP-01581"},"M16-GAP-01581":{"line":1580,"offset":273028,"length":170,"previous":"M16-GAP-01580","next":"M16-GAP-01582"},"M16-GAP-01582":{"line":1581,"offset":273198,"length":171,"previous":"M16-GAP-01581","next":"M16-GAP-01583"},"M16-GAP-01583":{"line":1582,"offset":273369,"length":176,"previous":"M16-GAP-01582","next":"M16-GAP-01584"},"M16-GAP-01584":{"line":1583,"offset":273545,"length":180,"previous":"M16-GAP-01583","next":"M16-GAP-01585"},"M16-GAP-01585":{"line":1584,"offset":273725,"length":174,"previous":"M16-GAP-01584","next":"M16-GAP-01586"},"M16-GAP-01586":{"line":1585,"offset":273899,"length":173,"previous":"M16-GAP-01585","next":"M16-GAP-01587"},"M16-GAP-01587":{"line":1586,"offset":274072,"length":171,"previous":"M16-GAP-01586","next":"M16-GAP-01588"},"M16-GAP-01588":{"line":1587,"offset":274243,"length":182,"previous":"M16-GAP-01587","next":"M16-GAP-01589"},"M16-GAP-01589":{"line":1588,"offset":274425,"length":173,"previous":"M16-GAP-01588","next":"M16-GAP-01590"},"M16-GAP-01590":{"line":1589,"offset":274598,"length":172,"previous":"M16-GAP-01589","next":"M16-GAP-01591"},"M16-GAP-01591":{"line":1590,"offset":274770,"length":172,"previous":"M16-GAP-01590","next":"M16-GAP-01592"},"M16-GAP-01592":{"line":1591,"offset":274942,"length":178,"previous":"M16-GAP-01591","next":"M16-GAP-01593"},"M16-GAP-01593":{"line":1592,"offset":275120,"length":174,"previous":"M16-GAP-01592","next":"M16-GAP-01594"},"M16-GAP-01594":{"line":1593,"offset":275294,"length":172,"previous":"M16-GAP-01593","next":"M16-GAP-01595"},"M16-GAP-01595":{"line":1594,"offset":275466,"length":174,"previous":"M16-GAP-01594","next":"M16-GAP-01596"},"M16-GAP-01596":{"line":1595,"offset":275640,"length":174,"previous":"M16-GAP-01595","next":"M16-GAP-01597"},"M16-GAP-01597":{"line":1596,"offset":275814,"length":176,"previous":"M16-GAP-01596","next":"M16-GAP-01598"},"M16-GAP-01598":{"line":1597,"offset":275990,"length":185,"previous":"M16-GAP-01597","next":"M16-GAP-01599"},"M16-GAP-01599":{"line":1598,"offset":276175,"length":199,"previous":"M16-GAP-01598","next":"M16-GAP-01600"},"M16-GAP-01600":{"line":1599,"offset":276374,"length":187,"previous":"M16-GAP-01599","next":"M16-GAP-01601"},"M16-GAP-01601":{"line":1600,"offset":276561,"length":178,"previous":"M16-GAP-01600","next":"M16-GAP-01602"},"M16-GAP-01602":{"line":1601,"offset":276739,"length":179,"previous":"M16-GAP-01601","next":"M16-GAP-01603"},"M16-GAP-01603":{"line":1602,"offset":276918,"length":177,"previous":"M16-GAP-01602","next":"M16-GAP-01604"},"M16-GAP-01604":{"line":1603,"offset":277095,"length":172,"previous":"M16-GAP-01603","next":"M16-GAP-01605"},"M16-GAP-01605":{"line":1604,"offset":277267,"length":169,"previous":"M16-GAP-01604","next":"M16-GAP-01606"},"M16-GAP-01606":{"line":1605,"offset":277436,"length":173,"previous":"M16-GAP-01605","next":"M16-GAP-01607"},"M16-GAP-01607":{"line":1606,"offset":277609,"length":176,"previous":"M16-GAP-01606","next":"M16-GAP-01608"},"M16-GAP-01608":{"line":1607,"offset":277785,"length":166,"previous":"M16-GAP-01607","next":"M16-GAP-01609"},"M16-GAP-01609":{"line":1608,"offset":277951,"length":169,"previous":"M16-GAP-01608","next":"M16-GAP-01610"},"M16-GAP-01610":{"line":1609,"offset":278120,"length":167,"previous":"M16-GAP-01609","next":"M16-GAP-01611"},"M16-GAP-01611":{"line":1610,"offset":278287,"length":171,"previous":"M16-GAP-01610","next":"M16-GAP-01612"},"M16-GAP-01612":{"line":1611,"offset":278458,"length":173,"previous":"M16-GAP-01611","next":"M16-GAP-01613"},"M16-GAP-01613":{"line":1612,"offset":278631,"length":179,"previous":"M16-GAP-01612","next":"M16-GAP-01614"},"M16-GAP-01614":{"line":1613,"offset":278810,"length":176,"previous":"M16-GAP-01613","next":"M16-GAP-01615"},"M16-GAP-01615":{"line":1614,"offset":278986,"length":178,"previous":"M16-GAP-01614","next":"M16-GAP-01616"},"M16-GAP-01616":{"line":1615,"offset":279164,"length":169,"previous":"M16-GAP-01615","next":"M16-GAP-01617"},"M16-GAP-01617":{"line":1616,"offset":279333,"length":171,"previous":"M16-GAP-01616","next":"M16-GAP-01618"},"M16-GAP-01618":{"line":1617,"offset":279504,"length":174,"previous":"M16-GAP-01617","next":"M16-GAP-01619"},"M16-GAP-01619":{"line":1618,"offset":279678,"length":177,"previous":"M16-GAP-01618","next":"M16-GAP-01620"},"M16-GAP-01620":{"line":1619,"offset":279855,"length":181,"previous":"M16-GAP-01619","next":"M16-GAP-01621"},"M16-GAP-01621":{"line":1620,"offset":280036,"length":176,"previous":"M16-GAP-01620","next":"M16-GAP-01622"},"M16-GAP-01622":{"line":1621,"offset":280212,"length":175,"previous":"M16-GAP-01621","next":"M16-GAP-01623"},"M16-GAP-01623":{"line":1622,"offset":280387,"length":187,"previous":"M16-GAP-01622","next":"M16-GAP-01624"},"M16-GAP-01624":{"line":1623,"offset":280574,"length":179,"previous":"M16-GAP-01623","next":"M16-GAP-01625"},"M16-GAP-01625":{"line":1624,"offset":280753,"length":177,"previous":"M16-GAP-01624","next":"M16-GAP-01626"},"M16-GAP-01626":{"line":1625,"offset":280930,"length":177,"previous":"M16-GAP-01625","next":"M16-GAP-01627"},"M16-GAP-01627":{"line":1626,"offset":281107,"length":182,"previous":"M16-GAP-01626","next":"M16-GAP-01628"},"M16-GAP-01628":{"line":1627,"offset":281289,"length":175,"previous":"M16-GAP-01627","next":"M16-GAP-01629"},"M16-GAP-01629":{"line":1628,"offset":281464,"length":177,"previous":"M16-GAP-01628","next":"M16-GAP-01630"},"M16-GAP-01630":{"line":1629,"offset":281641,"length":175,"previous":"M16-GAP-01629","next":"M16-GAP-01631"},"M16-GAP-01631":{"line":1630,"offset":281816,"length":180,"previous":"M16-GAP-01630","next":"M16-GAP-01632"},"M16-GAP-01632":{"line":1631,"offset":281996,"length":184,"previous":"M16-GAP-01631","next":"M16-GAP-01633"},"M16-GAP-01633":{"line":1632,"offset":282180,"length":179,"previous":"M16-GAP-01632","next":"M16-GAP-01634"},"M16-GAP-01634":{"line":1633,"offset":282359,"length":177,"previous":"M16-GAP-01633","next":"M16-GAP-01635"},"M16-GAP-01635":{"line":1634,"offset":282536,"length":182,"previous":"M16-GAP-01634","next":"M16-GAP-01636"},"M16-GAP-01636":{"line":1635,"offset":282718,"length":177,"previous":"M16-GAP-01635","next":"M16-GAP-01637"},"M16-GAP-01637":{"line":1636,"offset":282895,"length":181,"previous":"M16-GAP-01636","next":"M16-GAP-01638"},"M16-GAP-01638":{"line":1637,"offset":283076,"length":177,"previous":"M16-GAP-01637","next":"M16-GAP-01639"},"M16-GAP-01639":{"line":1638,"offset":283253,"length":175,"previous":"M16-GAP-01638","next":"M16-GAP-01640"},"M16-GAP-01640":{"line":1639,"offset":283428,"length":175,"previous":"M16-GAP-01639","next":"M16-GAP-01641"},"M16-GAP-01641":{"line":1640,"offset":283603,"length":176,"previous":"M16-GAP-01640","next":"M16-GAP-01642"},"M16-GAP-01642":{"line":1641,"offset":283779,"length":178,"previous":"M16-GAP-01641","next":"M16-GAP-01643"},"M16-GAP-01643":{"line":1642,"offset":283957,"length":195,"previous":"M16-GAP-01642","next":"M16-GAP-01644"},"M16-GAP-01644":{"line":1643,"offset":284152,"length":177,"previous":"M16-GAP-01643","next":"M16-GAP-01645"},"M16-GAP-01645":{"line":1644,"offset":284329,"length":182,"previous":"M16-GAP-01644","next":"M16-GAP-01646"},"M16-GAP-01646":{"line":1645,"offset":284511,"length":184,"previous":"M16-GAP-01645","next":"M16-GAP-01647"},"M16-GAP-01647":{"line":1646,"offset":284695,"length":180,"previous":"M16-GAP-01646","next":"M16-GAP-01648"},"M16-GAP-01648":{"line":1647,"offset":284875,"length":168,"previous":"M16-GAP-01647","next":"M16-GAP-01649"},"M16-GAP-01649":{"line":1648,"offset":285043,"length":171,"previous":"M16-GAP-01648","next":"M16-GAP-01650"},"M16-GAP-01650":{"line":1649,"offset":285214,"length":170,"previous":"M16-GAP-01649","next":"M16-GAP-01651"},"M16-GAP-01651":{"line":1650,"offset":285384,"length":173,"previous":"M16-GAP-01650","next":"M16-GAP-01652"},"M16-GAP-01652":{"line":1651,"offset":285557,"length":170,"previous":"M16-GAP-01651","next":"M16-GAP-01653"},"M16-GAP-01653":{"line":1652,"offset":285727,"length":178,"previous":"M16-GAP-01652","next":"M16-GAP-01654"},"M16-GAP-01654":{"line":1653,"offset":285905,"length":172,"previous":"M16-GAP-01653","next":"M16-GAP-01655"},"M16-GAP-01655":{"line":1654,"offset":286077,"length":184,"previous":"M16-GAP-01654","next":"M16-GAP-01656"},"M16-GAP-01656":{"line":1655,"offset":286261,"length":178,"previous":"M16-GAP-01655","next":"M16-GAP-01657"},"M16-GAP-01657":{"line":1656,"offset":286439,"length":185,"previous":"M16-GAP-01656","next":"M16-GAP-01658"},"M16-GAP-01658":{"line":1657,"offset":286624,"length":175,"previous":"M16-GAP-01657","next":"M16-GAP-01659"},"M16-GAP-01659":{"line":1658,"offset":286799,"length":180,"previous":"M16-GAP-01658","next":"M16-GAP-01660"},"M16-GAP-01660":{"line":1659,"offset":286979,"length":187,"previous":"M16-GAP-01659","next":"M16-GAP-01661"},"M16-GAP-01661":{"line":1660,"offset":287166,"length":177,"previous":"M16-GAP-01660","next":"M16-GAP-01662"},"M16-GAP-01662":{"line":1661,"offset":287343,"length":184,"previous":"M16-GAP-01661","next":"M16-GAP-01663"},"M16-GAP-01663":{"line":1662,"offset":287527,"length":184,"previous":"M16-GAP-01662","next":"M16-GAP-01664"},"M16-GAP-01664":{"line":1663,"offset":287711,"length":182,"previous":"M16-GAP-01663","next":"M16-GAP-01665"},"M16-GAP-01665":{"line":1664,"offset":287893,"length":175,"previous":"M16-GAP-01664","next":"M16-GAP-01666"},"M16-GAP-01666":{"line":1665,"offset":288068,"length":182,"previous":"M16-GAP-01665","next":"M16-GAP-01667"},"M16-GAP-01667":{"line":1666,"offset":288250,"length":187,"previous":"M16-GAP-01666","next":"M16-GAP-01668"},"M16-GAP-01668":{"line":1667,"offset":288437,"length":184,"previous":"M16-GAP-01667","next":"M16-GAP-01669"},"M16-GAP-01669":{"line":1668,"offset":288621,"length":182,"previous":"M16-GAP-01668","next":"M16-GAP-01670"},"M16-GAP-01670":{"line":1669,"offset":288803,"length":190,"previous":"M16-GAP-01669","next":"M16-GAP-01671"},"M16-GAP-01671":{"line":1670,"offset":288993,"length":188,"previous":"M16-GAP-01670","next":"M16-GAP-01672"},"M16-GAP-01672":{"line":1671,"offset":289181,"length":179,"previous":"M16-GAP-01671","next":"M16-GAP-01673"},"M16-GAP-01673":{"line":1672,"offset":289360,"length":178,"previous":"M16-GAP-01672","next":"M16-GAP-01674"},"M16-GAP-01674":{"line":1673,"offset":289538,"length":175,"previous":"M16-GAP-01673","next":"M16-GAP-01675"},"M16-GAP-01675":{"line":1674,"offset":289713,"length":174,"previous":"M16-GAP-01674","next":"M16-GAP-01676"},"M16-GAP-01676":{"line":1675,"offset":289887,"length":187,"previous":"M16-GAP-01675","next":"M16-GAP-01677"},"M16-GAP-01677":{"line":1676,"offset":290074,"length":185,"previous":"M16-GAP-01676","next":"M16-GAP-01678"},"M16-GAP-01678":{"line":1677,"offset":290259,"length":175,"previous":"M16-GAP-01677","next":"M16-GAP-01679"},"M16-GAP-01679":{"line":1678,"offset":290434,"length":182,"previous":"M16-GAP-01678","next":"M16-GAP-01680"},"M16-GAP-01680":{"line":1679,"offset":290616,"length":180,"previous":"M16-GAP-01679","next":"M16-GAP-01681"},"M16-GAP-01681":{"line":1680,"offset":290796,"length":174,"previous":"M16-GAP-01680","next":"M16-GAP-01682"},"M16-GAP-01682":{"line":1681,"offset":290970,"length":174,"previous":"M16-GAP-01681","next":"M16-GAP-01683"},"M16-GAP-01683":{"line":1682,"offset":291144,"length":166,"previous":"M16-GAP-01682","next":"M16-GAP-01684"},"M16-GAP-01684":{"line":1683,"offset":291310,"length":180,"previous":"M16-GAP-01683","next":"M16-GAP-01685"},"M16-GAP-01685":{"line":1684,"offset":291490,"length":183,"previous":"M16-GAP-01684","next":"M16-GAP-01686"},"M16-GAP-01686":{"line":1685,"offset":291673,"length":175,"previous":"M16-GAP-01685","next":"M16-GAP-01687"},"M16-GAP-01687":{"line":1686,"offset":291848,"length":164,"previous":"M16-GAP-01686","next":"M16-GAP-01688"},"M16-GAP-01688":{"line":1687,"offset":292012,"length":176,"previous":"M16-GAP-01687","next":"M16-GAP-01689"},"M16-GAP-01689":{"line":1688,"offset":292188,"length":167,"previous":"M16-GAP-01688","next":"M16-GAP-01690"},"M16-GAP-01690":{"line":1689,"offset":292355,"length":169,"previous":"M16-GAP-01689","next":"M16-GAP-01691"},"M16-GAP-01691":{"line":1690,"offset":292524,"length":178,"previous":"M16-GAP-01690","next":"M16-GAP-01692"},"M16-GAP-01692":{"line":1691,"offset":292702,"length":172,"previous":"M16-GAP-01691","next":"M16-GAP-01693"},"M16-GAP-01693":{"line":1692,"offset":292874,"length":168,"previous":"M16-GAP-01692","next":"M16-GAP-01694"},"M16-GAP-01694":{"line":1693,"offset":293042,"length":168,"previous":"M16-GAP-01693","next":"M16-GAP-01695"},"M16-GAP-01695":{"line":1694,"offset":293210,"length":173,"previous":"M16-GAP-01694","next":"M16-GAP-01696"},"M16-GAP-01696":{"line":1695,"offset":293383,"length":174,"previous":"M16-GAP-01695","next":"M16-GAP-01697"},"M16-GAP-01697":{"line":1696,"offset":293557,"length":174,"previous":"M16-GAP-01696","next":"M16-GAP-01698"},"M16-GAP-01698":{"line":1697,"offset":293731,"length":171,"previous":"M16-GAP-01697","next":"M16-GAP-01699"},"M16-GAP-01699":{"line":1698,"offset":293902,"length":182,"previous":"M16-GAP-01698","next":"M16-GAP-01700"},"M16-GAP-01700":{"line":1699,"offset":294084,"length":185,"previous":"M16-GAP-01699","next":"M16-GAP-01701"},"M16-GAP-01701":{"line":1700,"offset":294269,"length":173,"previous":"M16-GAP-01700","next":"M16-GAP-01702"},"M16-GAP-01702":{"line":1701,"offset":294442,"length":172,"previous":"M16-GAP-01701","next":"M16-GAP-01703"},"M16-GAP-01703":{"line":1702,"offset":294614,"length":181,"previous":"M16-GAP-01702","next":"M16-GAP-01704"},"M16-GAP-01704":{"line":1703,"offset":294795,"length":187,"previous":"M16-GAP-01703","next":"M16-GAP-01705"},"M16-GAP-01705":{"line":1704,"offset":294982,"length":194,"previous":"M16-GAP-01704","next":"M16-GAP-01706"},"M16-GAP-01706":{"line":1705,"offset":295176,"length":173,"previous":"M16-GAP-01705","next":"M16-GAP-01707"},"M16-GAP-01707":{"line":1706,"offset":295349,"length":178,"previous":"M16-GAP-01706","next":"M16-GAP-01708"},"M16-GAP-01708":{"line":1707,"offset":295527,"length":176,"previous":"M16-GAP-01707","next":"M16-GAP-01709"},"M16-GAP-01709":{"line":1708,"offset":295703,"length":169,"previous":"M16-GAP-01708","next":"M16-GAP-01710"},"M16-GAP-01710":{"line":1709,"offset":295872,"length":174,"previous":"M16-GAP-01709","next":"M16-GAP-01711"},"M16-GAP-01711":{"line":1710,"offset":296046,"length":173,"previous":"M16-GAP-01710","next":"M16-GAP-01712"},"M16-GAP-01712":{"line":1711,"offset":296219,"length":172,"previous":"M16-GAP-01711","next":"M16-GAP-01713"},"M16-GAP-01713":{"line":1712,"offset":296391,"length":171,"previous":"M16-GAP-01712","next":"M16-GAP-01714"},"M16-GAP-01714":{"line":1713,"offset":296562,"length":170,"previous":"M16-GAP-01713","next":"M16-GAP-01715"},"M16-GAP-01715":{"line":1714,"offset":296732,"length":175,"previous":"M16-GAP-01714","next":"M16-GAP-01716"},"M16-GAP-01716":{"line":1715,"offset":296907,"length":171,"previous":"M16-GAP-01715","next":"M16-GAP-01717"},"M16-GAP-01717":{"line":1716,"offset":297078,"length":170,"previous":"M16-GAP-01716","next":"M16-GAP-01718"},"M16-GAP-01718":{"line":1717,"offset":297248,"length":170,"previous":"M16-GAP-01717","next":"M16-GAP-01719"},"M16-GAP-01719":{"line":1718,"offset":297418,"length":171,"previous":"M16-GAP-01718","next":"M16-GAP-01720"},"M16-GAP-01720":{"line":1719,"offset":297589,"length":171,"previous":"M16-GAP-01719","next":"M16-GAP-01721"},"M16-GAP-01721":{"line":1720,"offset":297760,"length":174,"previous":"M16-GAP-01720","next":"M16-GAP-01722"},"M16-GAP-01722":{"line":1721,"offset":297934,"length":174,"previous":"M16-GAP-01721","next":"M16-GAP-01723"},"M16-GAP-01723":{"line":1722,"offset":298108,"length":172,"previous":"M16-GAP-01722","next":"M16-GAP-01724"},"M16-GAP-01724":{"line":1723,"offset":298280,"length":170,"previous":"M16-GAP-01723","next":"M16-GAP-01725"},"M16-GAP-01725":{"line":1724,"offset":298450,"length":171,"previous":"M16-GAP-01724","next":"M16-GAP-01726"},"M16-GAP-01726":{"line":1725,"offset":298621,"length":179,"previous":"M16-GAP-01725","next":"M16-GAP-01727"},"M16-GAP-01727":{"line":1726,"offset":298800,"length":174,"previous":"M16-GAP-01726","next":"M16-GAP-01728"},"M16-GAP-01728":{"line":1727,"offset":298974,"length":172,"previous":"M16-GAP-01727","next":"M16-GAP-01729"},"M16-GAP-01729":{"line":1728,"offset":299146,"length":173,"previous":"M16-GAP-01728","next":"M16-GAP-01730"},"M16-GAP-01730":{"line":1729,"offset":299319,"length":173,"previous":"M16-GAP-01729","next":"M16-GAP-01731"},"M16-GAP-01731":{"line":1730,"offset":299492,"length":175,"previous":"M16-GAP-01730","next":"M16-GAP-01732"},"M16-GAP-01732":{"line":1731,"offset":299667,"length":180,"previous":"M16-GAP-01731","next":"M16-GAP-01733"},"M16-GAP-01733":{"line":1732,"offset":299847,"length":173,"previous":"M16-GAP-01732","next":"M16-GAP-01734"},"M16-GAP-01734":{"line":1733,"offset":300020,"length":173,"previous":"M16-GAP-01733","next":"M16-GAP-01735"},"M16-GAP-01735":{"line":1734,"offset":300193,"length":173,"previous":"M16-GAP-01734","next":"M16-GAP-01736"},"M16-GAP-01736":{"line":1735,"offset":300366,"length":167,"previous":"M16-GAP-01735","next":"M16-GAP-01737"},"M16-GAP-01737":{"line":1736,"offset":300533,"length":166,"previous":"M16-GAP-01736","next":"M16-GAP-01738"},"M16-GAP-01738":{"line":1737,"offset":300699,"length":170,"previous":"M16-GAP-01737","next":"M16-GAP-01739"},"M16-GAP-01739":{"line":1738,"offset":300869,"length":180,"previous":"M16-GAP-01738","next":"M16-GAP-01740"},"M16-GAP-01740":{"line":1739,"offset":301049,"length":179,"previous":"M16-GAP-01739","next":"M16-GAP-01741"},"M16-GAP-01741":{"line":1740,"offset":301228,"length":173,"previous":"M16-GAP-01740","next":"M16-GAP-01742"},"M16-GAP-01742":{"line":1741,"offset":301401,"length":183,"previous":"M16-GAP-01741","next":"M16-GAP-01743"},"M16-GAP-01743":{"line":1742,"offset":301584,"length":172,"previous":"M16-GAP-01742","next":"M16-GAP-01744"},"M16-GAP-01744":{"line":1743,"offset":301756,"length":168,"previous":"M16-GAP-01743","next":"M16-GAP-01745"},"M16-GAP-01745":{"line":1744,"offset":301924,"length":173,"previous":"M16-GAP-01744","next":"M16-GAP-01746"},"M16-GAP-01746":{"line":1745,"offset":302097,"length":172,"previous":"M16-GAP-01745","next":"M16-GAP-01747"},"M16-GAP-01747":{"line":1746,"offset":302269,"length":175,"previous":"M16-GAP-01746","next":"M16-GAP-01748"},"M16-GAP-01748":{"line":1747,"offset":302444,"length":174,"previous":"M16-GAP-01747","next":"M16-GAP-01749"},"M16-GAP-01749":{"line":1748,"offset":302618,"length":178,"previous":"M16-GAP-01748","next":"M16-GAP-01750"},"M16-GAP-01750":{"line":1749,"offset":302796,"length":170,"previous":"M16-GAP-01749","next":"M16-GAP-01751"},"M16-GAP-01751":{"line":1750,"offset":302966,"length":169,"previous":"M16-GAP-01750","next":"M16-GAP-01752"},"M16-GAP-01752":{"line":1751,"offset":303135,"length":177,"previous":"M16-GAP-01751","next":"M16-GAP-01753"},"M16-GAP-01753":{"line":1752,"offset":303312,"length":172,"previous":"M16-GAP-01752","next":"M16-GAP-01754"},"M16-GAP-01754":{"line":1753,"offset":303484,"length":173,"previous":"M16-GAP-01753","next":"M16-GAP-01755"},"M16-GAP-01755":{"line":1754,"offset":303657,"length":173,"previous":"M16-GAP-01754","next":"M16-GAP-01756"},"M16-GAP-01756":{"line":1755,"offset":303830,"length":175,"previous":"M16-GAP-01755","next":"M16-GAP-01757"},"M16-GAP-01757":{"line":1756,"offset":304005,"length":180,"previous":"M16-GAP-01756","next":"M16-GAP-01758"},"M16-GAP-01758":{"line":1757,"offset":304185,"length":173,"previous":"M16-GAP-01757","next":"M16-GAP-01759"},"M16-GAP-01759":{"line":1758,"offset":304358,"length":173,"previous":"M16-GAP-01758","next":"M16-GAP-01760"},"M16-GAP-01760":{"line":1759,"offset":304531,"length":178,"previous":"M16-GAP-01759","next":"M16-GAP-01761"},"M16-GAP-01761":{"line":1760,"offset":304709,"length":189,"previous":"M16-GAP-01760","next":"M16-GAP-01762"},"M16-GAP-01762":{"line":1761,"offset":304898,"length":174,"previous":"M16-GAP-01761","next":"M16-GAP-01763"},"M16-GAP-01763":{"line":1762,"offset":305072,"length":181,"previous":"M16-GAP-01762","next":"M16-GAP-01764"},"M16-GAP-01764":{"line":1763,"offset":305253,"length":173,"previous":"M16-GAP-01763","next":"M16-GAP-01765"},"M16-GAP-01765":{"line":1764,"offset":305426,"length":176,"previous":"M16-GAP-01764","next":"M16-GAP-01766"},"M16-GAP-01766":{"line":1765,"offset":305602,"length":176,"previous":"M16-GAP-01765","next":"M16-GAP-01767"},"M16-GAP-01767":{"line":1766,"offset":305778,"length":173,"previous":"M16-GAP-01766","next":"M16-GAP-01768"},"M16-GAP-01768":{"line":1767,"offset":305951,"length":176,"previous":"M16-GAP-01767","next":"M16-GAP-01769"},"M16-GAP-01769":{"line":1768,"offset":306127,"length":169,"previous":"M16-GAP-01768","next":"M16-GAP-01770"},"M16-GAP-01770":{"line":1769,"offset":306296,"length":176,"previous":"M16-GAP-01769","next":"M16-GAP-01771"},"M16-GAP-01771":{"line":1770,"offset":306472,"length":174,"previous":"M16-GAP-01770","next":"M16-GAP-01772"},"M16-GAP-01772":{"line":1771,"offset":306646,"length":174,"previous":"M16-GAP-01771","next":"M16-GAP-01773"},"M16-GAP-01773":{"line":1772,"offset":306820,"length":174,"previous":"M16-GAP-01772","next":"M16-GAP-01774"},"M16-GAP-01774":{"line":1773,"offset":306994,"length":172,"previous":"M16-GAP-01773","next":"M16-GAP-01775"},"M16-GAP-01775":{"line":1774,"offset":307166,"length":169,"previous":"M16-GAP-01774","next":"M16-GAP-01776"},"M16-GAP-01776":{"line":1775,"offset":307335,"length":176,"previous":"M16-GAP-01775","next":"M16-GAP-01777"},"M16-GAP-01777":{"line":1776,"offset":307511,"length":170,"previous":"M16-GAP-01776","next":"M16-GAP-01778"},"M16-GAP-01778":{"line":1777,"offset":307681,"length":176,"previous":"M16-GAP-01777","next":"M16-GAP-01779"},"M16-GAP-01779":{"line":1778,"offset":307857,"length":167,"previous":"M16-GAP-01778","next":"M16-GAP-01780"},"M16-GAP-01780":{"line":1779,"offset":308024,"length":171,"previous":"M16-GAP-01779","next":"M16-GAP-01781"},"M16-GAP-01781":{"line":1780,"offset":308195,"length":177,"previous":"M16-GAP-01780","next":"M16-GAP-01782"},"M16-GAP-01782":{"line":1781,"offset":308372,"length":168,"previous":"M16-GAP-01781","next":"M16-GAP-01783"},"M16-GAP-01783":{"line":1782,"offset":308540,"length":174,"previous":"M16-GAP-01782","next":"M16-GAP-01784"},"M16-GAP-01784":{"line":1783,"offset":308714,"length":166,"previous":"M16-GAP-01783","next":"M16-GAP-01785"},"M16-GAP-01785":{"line":1784,"offset":308880,"length":165,"previous":"M16-GAP-01784","next":"M16-GAP-01786"},"M16-GAP-01786":{"line":1785,"offset":309045,"length":168,"previous":"M16-GAP-01785","next":"M16-GAP-01787"},"M16-GAP-01787":{"line":1786,"offset":309213,"length":167,"previous":"M16-GAP-01786","next":"M16-GAP-01788"},"M16-GAP-01788":{"line":1787,"offset":309380,"length":168,"previous":"M16-GAP-01787","next":"M16-GAP-01789"},"M16-GAP-01789":{"line":1788,"offset":309548,"length":171,"previous":"M16-GAP-01788","next":"M16-GAP-01790"},"M16-GAP-01790":{"line":1789,"offset":309719,"length":169,"previous":"M16-GAP-01789","next":"M16-GAP-01791"},"M16-GAP-01791":{"line":1790,"offset":309888,"length":177,"previous":"M16-GAP-01790","next":"M16-GAP-01792"},"M16-GAP-01792":{"line":1791,"offset":310065,"length":163,"previous":"M16-GAP-01791","next":"M16-GAP-01793"},"M16-GAP-01793":{"line":1792,"offset":310228,"length":162,"previous":"M16-GAP-01792","next":"M16-GAP-01794"},"M16-GAP-01794":{"line":1793,"offset":310390,"length":163,"previous":"M16-GAP-01793","next":"M16-GAP-01795"},"M16-GAP-01795":{"line":1794,"offset":310553,"length":170,"previous":"M16-GAP-01794","next":"M16-GAP-01796"},"M16-GAP-01796":{"line":1795,"offset":310723,"length":172,"previous":"M16-GAP-01795","next":"M16-GAP-01797"},"M16-GAP-01797":{"line":1796,"offset":310895,"length":181,"previous":"M16-GAP-01796","next":"M16-GAP-01798"},"M16-GAP-01798":{"line":1797,"offset":311076,"length":166,"previous":"M16-GAP-01797","next":"M16-GAP-01799"},"M16-GAP-01799":{"line":1798,"offset":311242,"length":175,"previous":"M16-GAP-01798","next":"M16-GAP-01800"},"M16-GAP-01800":{"line":1799,"offset":311417,"length":185,"previous":"M16-GAP-01799","next":"M16-GAP-01801"},"M16-GAP-01801":{"line":1800,"offset":311602,"length":172,"previous":"M16-GAP-01800","next":"M16-GAP-01802"},"M16-GAP-01802":{"line":1801,"offset":311774,"length":177,"previous":"M16-GAP-01801","next":"M16-GAP-01803"},"M16-GAP-01803":{"line":1802,"offset":311951,"length":175,"previous":"M16-GAP-01802","next":"M16-GAP-01804"},"M16-GAP-01804":{"line":1803,"offset":312126,"length":175,"previous":"M16-GAP-01803","next":"M16-GAP-01805"},"M16-GAP-01805":{"line":1804,"offset":312301,"length":174,"previous":"M16-GAP-01804","next":"M16-GAP-01806"},"M16-GAP-01806":{"line":1805,"offset":312475,"length":172,"previous":"M16-GAP-01805","next":"M16-GAP-01807"},"M16-GAP-01807":{"line":1806,"offset":312647,"length":184,"previous":"M16-GAP-01806","next":"M16-GAP-01808"},"M16-GAP-01808":{"line":1807,"offset":312831,"length":164,"previous":"M16-GAP-01807","next":"M16-GAP-01809"},"M16-GAP-01809":{"line":1808,"offset":312995,"length":166,"previous":"M16-GAP-01808","next":"M16-GAP-01810"},"M16-GAP-01810":{"line":1809,"offset":313161,"length":163,"previous":"M16-GAP-01809","next":"M16-GAP-01811"},"M16-GAP-01811":{"line":1810,"offset":313324,"length":170,"previous":"M16-GAP-01810","next":"M16-GAP-01812"},"M16-GAP-01812":{"line":1811,"offset":313494,"length":180,"previous":"M16-GAP-01811","next":"M16-GAP-01813"},"M16-GAP-01813":{"line":1812,"offset":313674,"length":186,"previous":"M16-GAP-01812","next":"M16-GAP-01814"},"M16-GAP-01814":{"line":1813,"offset":313860,"length":165,"previous":"M16-GAP-01813","next":"M16-GAP-01815"},"M16-GAP-01815":{"line":1814,"offset":314025,"length":174,"previous":"M16-GAP-01814","next":"M16-GAP-01816"},"M16-GAP-01816":{"line":1815,"offset":314199,"length":166,"previous":"M16-GAP-01815","next":"M16-GAP-01817"},"M16-GAP-01817":{"line":1816,"offset":314365,"length":170,"previous":"M16-GAP-01816","next":"M16-GAP-01818"},"M16-GAP-01818":{"line":1817,"offset":314535,"length":171,"previous":"M16-GAP-01817","next":"M16-GAP-01819"},"M16-GAP-01819":{"line":1818,"offset":314706,"length":173,"previous":"M16-GAP-01818","next":"M16-GAP-01820"},"M16-GAP-01820":{"line":1819,"offset":314879,"length":178,"previous":"M16-GAP-01819","next":"M16-GAP-01821"},"M16-GAP-01821":{"line":1820,"offset":315057,"length":171,"previous":"M16-GAP-01820","next":"M16-GAP-01822"},"M16-GAP-01822":{"line":1821,"offset":315228,"length":173,"previous":"M16-GAP-01821","next":"M16-GAP-01823"},"M16-GAP-01823":{"line":1822,"offset":315401,"length":172,"previous":"M16-GAP-01822","next":"M16-GAP-01824"},"M16-GAP-01824":{"line":1823,"offset":315573,"length":171,"previous":"M16-GAP-01823","next":"M16-GAP-01825"},"M16-GAP-01825":{"line":1824,"offset":315744,"length":169,"previous":"M16-GAP-01824","next":"M16-GAP-01826"},"M16-GAP-01826":{"line":1825,"offset":315913,"length":169,"previous":"M16-GAP-01825","next":"M16-GAP-01827"},"M16-GAP-01827":{"line":1826,"offset":316082,"length":176,"previous":"M16-GAP-01826","next":"M16-GAP-01828"},"M16-GAP-01828":{"line":1827,"offset":316258,"length":174,"previous":"M16-GAP-01827","next":"M16-GAP-01829"},"M16-GAP-01829":{"line":1828,"offset":316432,"length":173,"previous":"M16-GAP-01828","next":"M16-GAP-01830"},"M16-GAP-01830":{"line":1829,"offset":316605,"length":172,"previous":"M16-GAP-01829","next":"M16-GAP-01831"},"M16-GAP-01831":{"line":1830,"offset":316777,"length":170,"previous":"M16-GAP-01830","next":"M16-GAP-01832"},"M16-GAP-01832":{"line":1831,"offset":316947,"length":175,"previous":"M16-GAP-01831","next":"M16-GAP-01833"},"M16-GAP-01833":{"line":1832,"offset":317122,"length":168,"previous":"M16-GAP-01832","next":"M16-GAP-01834"},"M16-GAP-01834":{"line":1833,"offset":317290,"length":171,"previous":"M16-GAP-01833","next":"M16-GAP-01835"},"M16-GAP-01835":{"line":1834,"offset":317461,"length":176,"previous":"M16-GAP-01834","next":"M16-GAP-01836"},"M16-GAP-01836":{"line":1835,"offset":317637,"length":172,"previous":"M16-GAP-01835","next":"M16-GAP-01837"},"M16-GAP-01837":{"line":1836,"offset":317809,"length":175,"previous":"M16-GAP-01836","next":"M16-GAP-01838"},"M16-GAP-01838":{"line":1837,"offset":317984,"length":170,"previous":"M16-GAP-01837","next":"M16-GAP-01839"},"M16-GAP-01839":{"line":1838,"offset":318154,"length":170,"previous":"M16-GAP-01838","next":"M16-GAP-01840"},"M16-GAP-01840":{"line":1839,"offset":318324,"length":170,"previous":"M16-GAP-01839","next":"M16-GAP-01841"},"M16-GAP-01841":{"line":1840,"offset":318494,"length":173,"previous":"M16-GAP-01840","next":"M16-GAP-01842"},"M16-GAP-01842":{"line":1841,"offset":318667,"length":171,"previous":"M16-GAP-01841","next":"M16-GAP-01843"},"M16-GAP-01843":{"line":1842,"offset":318838,"length":165,"previous":"M16-GAP-01842","next":"M16-GAP-01844"},"M16-GAP-01844":{"line":1843,"offset":319003,"length":170,"previous":"M16-GAP-01843","next":"M16-GAP-01845"},"M16-GAP-01845":{"line":1844,"offset":319173,"length":183,"previous":"M16-GAP-01844","next":"M16-GAP-01846"},"M16-GAP-01846":{"line":1845,"offset":319356,"length":173,"previous":"M16-GAP-01845","next":"M16-GAP-01847"},"M16-GAP-01847":{"line":1846,"offset":319529,"length":172,"previous":"M16-GAP-01846","next":"M16-GAP-01848"},"M16-GAP-01848":{"line":1847,"offset":319701,"length":160,"previous":"M16-GAP-01847","next":"M16-GAP-01849"},"M16-GAP-01849":{"line":1848,"offset":319861,"length":166,"previous":"M16-GAP-01848","next":"M16-GAP-01850"},"M16-GAP-01850":{"line":1849,"offset":320027,"length":160,"previous":"M16-GAP-01849","next":"M16-GAP-01851"},"M16-GAP-01851":{"line":1850,"offset":320187,"length":162,"previous":"M16-GAP-01850","next":"M16-GAP-01852"},"M16-GAP-01852":{"line":1851,"offset":320349,"length":164,"previous":"M16-GAP-01851","next":"M16-GAP-01853"},"M16-GAP-01853":{"line":1852,"offset":320513,"length":165,"previous":"M16-GAP-01852","next":"M16-GAP-01854"},"M16-GAP-01854":{"line":1853,"offset":320678,"length":161,"previous":"M16-GAP-01853","next":"M16-GAP-01855"},"M16-GAP-01855":{"line":1854,"offset":320839,"length":171,"previous":"M16-GAP-01854","next":"M16-GAP-01856"},"M16-GAP-01856":{"line":1855,"offset":321010,"length":167,"previous":"M16-GAP-01855","next":"M16-GAP-01857"},"M16-GAP-01857":{"line":1856,"offset":321177,"length":174,"previous":"M16-GAP-01856","next":"M16-GAP-01858"},"M16-GAP-01858":{"line":1857,"offset":321351,"length":168,"previous":"M16-GAP-01857","next":"M16-GAP-01859"},"M16-GAP-01859":{"line":1858,"offset":321519,"length":165,"previous":"M16-GAP-01858","next":"M16-GAP-01860"},"M16-GAP-01860":{"line":1859,"offset":321684,"length":160,"previous":"M16-GAP-01859","next":"M16-GAP-01861"},"M16-GAP-01861":{"line":1860,"offset":321844,"length":172,"previous":"M16-GAP-01860","next":"M16-GAP-01862"},"M16-GAP-01862":{"line":1861,"offset":322016,"length":161,"previous":"M16-GAP-01861","next":"M16-GAP-01863"},"M16-GAP-01863":{"line":1862,"offset":322177,"length":162,"previous":"M16-GAP-01862","next":"M16-GAP-01864"},"M16-GAP-01864":{"line":1863,"offset":322339,"length":165,"previous":"M16-GAP-01863","next":"M16-GAP-01865"},"M16-GAP-01865":{"line":1864,"offset":322504,"length":173,"previous":"M16-GAP-01864","next":"M16-GAP-01866"},"M16-GAP-01866":{"line":1865,"offset":322677,"length":167,"previous":"M16-GAP-01865","next":"M16-GAP-01867"},"M16-GAP-01867":{"line":1866,"offset":322844,"length":166,"previous":"M16-GAP-01866","next":"M16-GAP-01868"},"M16-GAP-01868":{"line":1867,"offset":323010,"length":180,"previous":"M16-GAP-01867","next":"M16-GAP-01869"},"M16-GAP-01869":{"line":1868,"offset":323190,"length":170,"previous":"M16-GAP-01868","next":"M16-GAP-01870"},"M16-GAP-01870":{"line":1869,"offset":323360,"length":172,"previous":"M16-GAP-01869","next":"M16-GAP-01871"},"M16-GAP-01871":{"line":1870,"offset":323532,"length":169,"previous":"M16-GAP-01870","next":"M16-GAP-01872"},"M16-GAP-01872":{"line":1871,"offset":323701,"length":174,"previous":"M16-GAP-01871","next":"M16-GAP-01873"},"M16-GAP-01873":{"line":1872,"offset":323875,"length":169,"previous":"M16-GAP-01872","next":"M16-GAP-01874"},"M16-GAP-01874":{"line":1873,"offset":324044,"length":169,"previous":"M16-GAP-01873","next":"M16-GAP-01875"},"M16-GAP-01875":{"line":1874,"offset":324213,"length":173,"previous":"M16-GAP-01874","next":"M16-GAP-01876"},"M16-GAP-01876":{"line":1875,"offset":324386,"length":184,"previous":"M16-GAP-01875","next":"M16-GAP-01877"},"M16-GAP-01877":{"line":1876,"offset":324570,"length":176,"previous":"M16-GAP-01876","next":"M16-GAP-01878"},"M16-GAP-01878":{"line":1877,"offset":324746,"length":174,"previous":"M16-GAP-01877","next":"M16-GAP-01879"},"M16-GAP-01879":{"line":1878,"offset":324920,"length":180,"previous":"M16-GAP-01878","next":"M16-GAP-01880"},"M16-GAP-01880":{"line":1879,"offset":325100,"length":178,"previous":"M16-GAP-01879","next":"M16-GAP-01881"},"M16-GAP-01881":{"line":1880,"offset":325278,"length":174,"previous":"M16-GAP-01880","next":"M16-GAP-01882"},"M16-GAP-01882":{"line":1881,"offset":325452,"length":175,"previous":"M16-GAP-01881","next":"M16-GAP-01883"},"M16-GAP-01883":{"line":1882,"offset":325627,"length":176,"previous":"M16-GAP-01882","next":"M16-GAP-01884"},"M16-GAP-01884":{"line":1883,"offset":325803,"length":182,"previous":"M16-GAP-01883","next":"M16-GAP-01885"},"M16-GAP-01885":{"line":1884,"offset":325985,"length":176,"previous":"M16-GAP-01884","next":"M16-GAP-01886"},"M16-GAP-01886":{"line":1885,"offset":326161,"length":178,"previous":"M16-GAP-01885","next":"M16-GAP-01887"},"M16-GAP-01887":{"line":1886,"offset":326339,"length":172,"previous":"M16-GAP-01886","next":"M16-GAP-01888"},"M16-GAP-01888":{"line":1887,"offset":326511,"length":177,"previous":"M16-GAP-01887","next":"M16-GAP-01889"},"M16-GAP-01889":{"line":1888,"offset":326688,"length":178,"previous":"M16-GAP-01888","next":"M16-GAP-01890"},"M16-GAP-01890":{"line":1889,"offset":326866,"length":175,"previous":"M16-GAP-01889","next":"M16-GAP-01891"},"M16-GAP-01891":{"line":1890,"offset":327041,"length":171,"previous":"M16-GAP-01890","next":"M16-GAP-01892"},"M16-GAP-01892":{"line":1891,"offset":327212,"length":171,"previous":"M16-GAP-01891","next":"M16-GAP-01893"},"M16-GAP-01893":{"line":1892,"offset":327383,"length":175,"previous":"M16-GAP-01892","next":"M16-GAP-01894"},"M16-GAP-01894":{"line":1893,"offset":327558,"length":172,"previous":"M16-GAP-01893","next":"M16-GAP-01895"},"M16-GAP-01895":{"line":1894,"offset":327730,"length":176,"previous":"M16-GAP-01894","next":"M16-GAP-01896"},"M16-GAP-01896":{"line":1895,"offset":327906,"length":170,"previous":"M16-GAP-01895","next":"M16-GAP-01897"},"M16-GAP-01897":{"line":1896,"offset":328076,"length":182,"previous":"M16-GAP-01896","next":"M16-GAP-01898"},"M16-GAP-01898":{"line":1897,"offset":328258,"length":182,"previous":"M16-GAP-01897","next":"M16-GAP-01899"},"M16-GAP-01899":{"line":1898,"offset":328440,"length":176,"previous":"M16-GAP-01898","next":"M16-GAP-01900"},"M16-GAP-01900":{"line":1899,"offset":328616,"length":175,"previous":"M16-GAP-01899","next":"M16-GAP-01901"},"M16-GAP-01901":{"line":1900,"offset":328791,"length":175,"previous":"M16-GAP-01900","next":"M16-GAP-01902"},"M16-GAP-01902":{"line":1901,"offset":328966,"length":176,"previous":"M16-GAP-01901","next":"M16-GAP-01903"},"M16-GAP-01903":{"line":1902,"offset":329142,"length":176,"previous":"M16-GAP-01902","next":"M16-GAP-01904"},"M16-GAP-01904":{"line":1903,"offset":329318,"length":175,"previous":"M16-GAP-01903","next":"M16-GAP-01905"},"M16-GAP-01905":{"line":1904,"offset":329493,"length":173,"previous":"M16-GAP-01904","next":"M16-GAP-01906"},"M16-GAP-01906":{"line":1905,"offset":329666,"length":183,"previous":"M16-GAP-01905","next":"M16-GAP-01907"},"M16-GAP-01907":{"line":1906,"offset":329849,"length":180,"previous":"M16-GAP-01906","next":"M16-GAP-01908"},"M16-GAP-01908":{"line":1907,"offset":330029,"length":183,"previous":"M16-GAP-01907","next":"M16-GAP-01909"},"M16-GAP-01909":{"line":1908,"offset":330212,"length":178,"previous":"M16-GAP-01908","next":"M16-GAP-01910"},"M16-GAP-01910":{"line":1909,"offset":330390,"length":180,"previous":"M16-GAP-01909","next":"M16-GAP-01911"},"M16-GAP-01911":{"line":1910,"offset":330570,"length":183,"previous":"M16-GAP-01910","next":"M16-GAP-01912"},"M16-GAP-01912":{"line":1911,"offset":330753,"length":175,"previous":"M16-GAP-01911","next":"M16-GAP-01913"},"M16-GAP-01913":{"line":1912,"offset":330928,"length":172,"previous":"M16-GAP-01912","next":"M16-GAP-01914"},"M16-GAP-01914":{"line":1913,"offset":331100,"length":181,"previous":"M16-GAP-01913","next":"M16-GAP-01915"},"M16-GAP-01915":{"line":1914,"offset":331281,"length":184,"previous":"M16-GAP-01914","next":"M16-GAP-01916"},"M16-GAP-01916":{"line":1915,"offset":331465,"length":181,"previous":"M16-GAP-01915","next":"M16-GAP-01917"},"M16-GAP-01917":{"line":1916,"offset":331646,"length":181,"previous":"M16-GAP-01916","next":"M16-GAP-01918"},"M16-GAP-01918":{"line":1917,"offset":331827,"length":179,"previous":"M16-GAP-01917","next":"M16-GAP-01919"},"M16-GAP-01919":{"line":1918,"offset":332006,"length":179,"previous":"M16-GAP-01918","next":"M16-GAP-01920"},"M16-GAP-01920":{"line":1919,"offset":332185,"length":179,"previous":"M16-GAP-01919","next":"M16-GAP-01921"},"M16-GAP-01921":{"line":1920,"offset":332364,"length":177,"previous":"M16-GAP-01920","next":"M16-GAP-01922"},"M16-GAP-01922":{"line":1921,"offset":332541,"length":174,"previous":"M16-GAP-01921","next":"M16-GAP-01923"},"M16-GAP-01923":{"line":1922,"offset":332715,"length":177,"previous":"M16-GAP-01922","next":"M16-GAP-01924"},"M16-GAP-01924":{"line":1923,"offset":332892,"length":178,"previous":"M16-GAP-01923","next":"M16-GAP-01925"},"M16-GAP-01925":{"line":1924,"offset":333070,"length":177,"previous":"M16-GAP-01924","next":"M16-GAP-01926"},"M16-GAP-01926":{"line":1925,"offset":333247,"length":182,"previous":"M16-GAP-01925","next":"M16-GAP-01927"},"M16-GAP-01927":{"line":1926,"offset":333429,"length":183,"previous":"M16-GAP-01926","next":"M16-GAP-01928"},"M16-GAP-01928":{"line":1927,"offset":333612,"length":186,"previous":"M16-GAP-01927","next":"M16-GAP-01929"},"M16-GAP-01929":{"line":1928,"offset":333798,"length":175,"previous":"M16-GAP-01928","next":"M16-GAP-01930"},"M16-GAP-01930":{"line":1929,"offset":333973,"length":188,"previous":"M16-GAP-01929","next":"M16-GAP-01931"},"M16-GAP-01931":{"line":1930,"offset":334161,"length":182,"previous":"M16-GAP-01930","next":"M16-GAP-01932"},"M16-GAP-01932":{"line":1931,"offset":334343,"length":178,"previous":"M16-GAP-01931","next":"M16-GAP-01933"},"M16-GAP-01933":{"line":1932,"offset":334521,"length":184,"previous":"M16-GAP-01932","next":"M16-GAP-01934"},"M16-GAP-01934":{"line":1933,"offset":334705,"length":176,"previous":"M16-GAP-01933","next":"M16-GAP-01935"},"M16-GAP-01935":{"line":1934,"offset":334881,"length":180,"previous":"M16-GAP-01934","next":"M16-GAP-01936"},"M16-GAP-01936":{"line":1935,"offset":335061,"length":162,"previous":"M16-GAP-01935","next":"M16-GAP-01937"},"M16-GAP-01937":{"line":1936,"offset":335223,"length":163,"previous":"M16-GAP-01936","next":"M16-GAP-01938"},"M16-GAP-01938":{"line":1937,"offset":335386,"length":167,"previous":"M16-GAP-01937","next":"M16-GAP-01939"},"M16-GAP-01939":{"line":1938,"offset":335553,"length":174,"previous":"M16-GAP-01938","next":"M16-GAP-01940"},"M16-GAP-01940":{"line":1939,"offset":335727,"length":168,"previous":"M16-GAP-01939","next":"M16-GAP-01941"},"M16-GAP-01941":{"line":1940,"offset":335895,"length":172,"previous":"M16-GAP-01940","next":"M16-GAP-01942"},"M16-GAP-01942":{"line":1941,"offset":336067,"length":165,"previous":"M16-GAP-01941","next":"M16-GAP-01943"},"M16-GAP-01943":{"line":1942,"offset":336232,"length":177,"previous":"M16-GAP-01942","next":"M16-GAP-01944"},"M16-GAP-01944":{"line":1943,"offset":336409,"length":199,"previous":"M16-GAP-01943","next":"M16-GAP-01945"},"M16-GAP-01945":{"line":1944,"offset":336608,"length":186,"previous":"M16-GAP-01944","next":"M16-GAP-01946"},"M16-GAP-01946":{"line":1945,"offset":336794,"length":187,"previous":"M16-GAP-01945","next":"M16-GAP-01947"},"M16-GAP-01947":{"line":1946,"offset":336981,"length":184,"previous":"M16-GAP-01946","next":"M16-GAP-01948"},"M16-GAP-01948":{"line":1947,"offset":337165,"length":193,"previous":"M16-GAP-01947","next":"M16-GAP-01949"},"M16-GAP-01949":{"line":1948,"offset":337358,"length":185,"previous":"M16-GAP-01948","next":"M16-GAP-01950"},"M16-GAP-01950":{"line":1949,"offset":337543,"length":180,"previous":"M16-GAP-01949","next":"M16-GAP-01951"},"M16-GAP-01951":{"line":1950,"offset":337723,"length":164,"previous":"M16-GAP-01950","next":"M16-GAP-01952"},"M16-GAP-01952":{"line":1951,"offset":337887,"length":176,"previous":"M16-GAP-01951","next":"M16-GAP-01953"},"M16-GAP-01953":{"line":1952,"offset":338063,"length":168,"previous":"M16-GAP-01952","next":"M16-GAP-01954"},"M16-GAP-01954":{"line":1953,"offset":338231,"length":164,"previous":"M16-GAP-01953","next":"M16-GAP-01955"},"M16-GAP-01955":{"line":1954,"offset":338395,"length":178,"previous":"M16-GAP-01954","next":"M16-GAP-01956"},"M16-GAP-01956":{"line":1955,"offset":338573,"length":173,"previous":"M16-GAP-01955","next":"M16-GAP-01957"},"M16-GAP-01957":{"line":1956,"offset":338746,"length":169,"previous":"M16-GAP-01956","next":"M16-GAP-01958"},"M16-GAP-01958":{"line":1957,"offset":338915,"length":167,"previous":"M16-GAP-01957","next":"M16-GAP-01959"},"M16-GAP-01959":{"line":1958,"offset":339082,"length":178,"previous":"M16-GAP-01958","next":"M16-GAP-01960"},"M16-GAP-01960":{"line":1959,"offset":339260,"length":168,"previous":"M16-GAP-01959","next":"M16-GAP-01961"},"M16-GAP-01961":{"line":1960,"offset":339428,"length":175,"previous":"M16-GAP-01960","next":"M16-GAP-01962"},"M16-GAP-01962":{"line":1961,"offset":339603,"length":178,"previous":"M16-GAP-01961","next":"M16-GAP-01963"},"M16-GAP-01963":{"line":1962,"offset":339781,"length":175,"previous":"M16-GAP-01962","next":"M16-GAP-01964"},"M16-GAP-01964":{"line":1963,"offset":339956,"length":171,"previous":"M16-GAP-01963","next":"M16-GAP-01965"},"M16-GAP-01965":{"line":1964,"offset":340127,"length":174,"previous":"M16-GAP-01964","next":"M16-GAP-01966"},"M16-GAP-01966":{"line":1965,"offset":340301,"length":181,"previous":"M16-GAP-01965","next":"M16-GAP-01967"},"M16-GAP-01967":{"line":1966,"offset":340482,"length":172,"previous":"M16-GAP-01966","next":"M16-GAP-01968"},"M16-GAP-01968":{"line":1967,"offset":340654,"length":175,"previous":"M16-GAP-01967","next":"M16-GAP-01969"},"M16-GAP-01969":{"line":1968,"offset":340829,"length":173,"previous":"M16-GAP-01968","next":"M16-GAP-01970"},"M16-GAP-01970":{"line":1969,"offset":341002,"length":170,"previous":"M16-GAP-01969","next":"M16-GAP-01971"},"M16-GAP-01971":{"line":1970,"offset":341172,"length":173,"previous":"M16-GAP-01970","next":"M16-GAP-01972"},"M16-GAP-01972":{"line":1971,"offset":341345,"length":163,"previous":"M16-GAP-01971","next":"M16-GAP-01973"},"M16-GAP-01973":{"line":1972,"offset":341508,"length":173,"previous":"M16-GAP-01972","next":"M16-GAP-01974"},"M16-GAP-01974":{"line":1973,"offset":341681,"length":195,"previous":"M16-GAP-01973","next":"M16-GAP-01975"},"M16-GAP-01975":{"line":1974,"offset":341876,"length":195,"previous":"M16-GAP-01974","next":"M16-GAP-01976"},"M16-GAP-01976":{"line":1975,"offset":342071,"length":185,"previous":"M16-GAP-01975","next":"M16-GAP-01977"},"M16-GAP-01977":{"line":1976,"offset":342256,"length":185,"previous":"M16-GAP-01976","next":"M16-GAP-01978"},"M16-GAP-01978":{"line":1977,"offset":342441,"length":190,"previous":"M16-GAP-01977","next":"M16-GAP-01979"},"M16-GAP-01979":{"line":1978,"offset":342631,"length":188,"previous":"M16-GAP-01978","next":"M16-GAP-01980"},"M16-GAP-01980":{"line":1979,"offset":342819,"length":178,"previous":"M16-GAP-01979","next":"M16-GAP-01981"},"M16-GAP-01981":{"line":1980,"offset":342997,"length":179,"previous":"M16-GAP-01980","next":"M16-GAP-01982"},"M16-GAP-01982":{"line":1981,"offset":343176,"length":179,"previous":"M16-GAP-01981","next":"M16-GAP-01983"},"M16-GAP-01983":{"line":1982,"offset":343355,"length":180,"previous":"M16-GAP-01982","next":"M16-GAP-01984"},"M16-GAP-01984":{"line":1983,"offset":343535,"length":181,"previous":"M16-GAP-01983","next":"M16-GAP-01985"},"M16-GAP-01985":{"line":1984,"offset":343716,"length":180,"previous":"M16-GAP-01984","next":"M16-GAP-01986"},"M16-GAP-01986":{"line":1985,"offset":343896,"length":180,"previous":"M16-GAP-01985","next":"M16-GAP-01987"},"M16-GAP-01987":{"line":1986,"offset":344076,"length":180,"previous":"M16-GAP-01986","next":"M16-GAP-01988"},"M16-GAP-01988":{"line":1987,"offset":344256,"length":182,"previous":"M16-GAP-01987","next":"M16-GAP-01989"},"M16-GAP-01989":{"line":1988,"offset":344438,"length":177,"previous":"M16-GAP-01988","next":"M16-GAP-01990"},"M16-GAP-01990":{"line":1989,"offset":344615,"length":178,"previous":"M16-GAP-01989","next":"M16-GAP-01991"},"M16-GAP-01991":{"line":1990,"offset":344793,"length":178,"previous":"M16-GAP-01990","next":"M16-GAP-01992"},"M16-GAP-01992":{"line":1991,"offset":344971,"length":180,"previous":"M16-GAP-01991","next":"M16-GAP-01993"},"M16-GAP-01993":{"line":1992,"offset":345151,"length":189,"previous":"M16-GAP-01992","next":"M16-GAP-01994"},"M16-GAP-01994":{"line":1993,"offset":345340,"length":189,"previous":"M16-GAP-01993","next":"M16-GAP-01995"},"M16-GAP-01995":{"line":1994,"offset":345529,"length":184,"previous":"M16-GAP-01994","next":"M16-GAP-01996"},"M16-GAP-01996":{"line":1995,"offset":345713,"length":181,"previous":"M16-GAP-01995","next":"M16-GAP-01997"},"M16-GAP-01997":{"line":1996,"offset":345894,"length":184,"previous":"M16-GAP-01996","next":"M16-GAP-01998"},"M16-GAP-01998":{"line":1997,"offset":346078,"length":160,"previous":"M16-GAP-01997","next":"M16-GAP-01999"},"M16-GAP-01999":{"line":1998,"offset":346238,"length":170,"previous":"M16-GAP-01998","next":"M16-GAP-02000"},"M16-GAP-02000":{"line":1999,"offset":346408,"length":176,"previous":"M16-GAP-01999","next":"M16-GAP-02001"},"M16-GAP-02001":{"line":2000,"offset":346584,"length":172,"previous":"M16-GAP-02000","next":"M16-GAP-02002"},"M16-GAP-02002":{"line":2001,"offset":346756,"length":175,"previous":"M16-GAP-02001","next":"M16-GAP-02003"},"M16-GAP-02003":{"line":2002,"offset":346931,"length":171,"previous":"M16-GAP-02002","next":"M16-GAP-02004"},"M16-GAP-02004":{"line":2003,"offset":347102,"length":175,"previous":"M16-GAP-02003","next":"M16-GAP-02005"},"M16-GAP-02005":{"line":2004,"offset":347277,"length":182,"previous":"M16-GAP-02004","next":"M16-GAP-02006"},"M16-GAP-02006":{"line":2005,"offset":347459,"length":188,"previous":"M16-GAP-02005","next":"M16-GAP-02007"},"M16-GAP-02007":{"line":2006,"offset":347647,"length":174,"previous":"M16-GAP-02006","next":"M16-GAP-02008"},"M16-GAP-02008":{"line":2007,"offset":347821,"length":178,"previous":"M16-GAP-02007","next":"M16-GAP-02009"},"M16-GAP-02009":{"line":2008,"offset":347999,"length":185,"previous":"M16-GAP-02008","next":"M16-GAP-02010"},"M16-GAP-02010":{"line":2009,"offset":348184,"length":193,"previous":"M16-GAP-02009","next":"M16-GAP-02011"},"M16-GAP-02011":{"line":2010,"offset":348377,"length":168,"previous":"M16-GAP-02010","next":"M16-GAP-02012"},"M16-GAP-02012":{"line":2011,"offset":348545,"length":174,"previous":"M16-GAP-02011","next":"M16-GAP-02013"},"M16-GAP-02013":{"line":2012,"offset":348719,"length":173,"previous":"M16-GAP-02012","next":"M16-GAP-02014"},"M16-GAP-02014":{"line":2013,"offset":348892,"length":172,"previous":"M16-GAP-02013","next":"M16-GAP-02015"},"M16-GAP-02015":{"line":2014,"offset":349064,"length":172,"previous":"M16-GAP-02014","next":"M16-GAP-02016"},"M16-GAP-02016":{"line":2015,"offset":349236,"length":168,"previous":"M16-GAP-02015","next":"M16-GAP-02017"},"M16-GAP-02017":{"line":2016,"offset":349404,"length":168,"previous":"M16-GAP-02016","next":"M16-GAP-02018"},"M16-GAP-02018":{"line":2017,"offset":349572,"length":167,"previous":"M16-GAP-02017","next":"M16-GAP-02019"},"M16-GAP-02019":{"line":2018,"offset":349739,"length":167,"previous":"M16-GAP-02018","next":"M16-GAP-02020"},"M16-GAP-02020":{"line":2019,"offset":349906,"length":170,"previous":"M16-GAP-02019","next":"M16-GAP-02021"},"M16-GAP-02021":{"line":2020,"offset":350076,"length":168,"previous":"M16-GAP-02020","next":"M16-GAP-02022"},"M16-GAP-02022":{"line":2021,"offset":350244,"length":167,"previous":"M16-GAP-02021","next":"M16-GAP-02023"},"M16-GAP-02023":{"line":2022,"offset":350411,"length":174,"previous":"M16-GAP-02022","next":"M16-GAP-02024"},"M16-GAP-02024":{"line":2023,"offset":350585,"length":164,"previous":"M16-GAP-02023","next":"M16-GAP-02025"},"M16-GAP-02025":{"line":2024,"offset":350749,"length":177,"previous":"M16-GAP-02024","next":"M16-GAP-02026"},"M16-GAP-02026":{"line":2025,"offset":350926,"length":168,"previous":"M16-GAP-02025","next":"M16-GAP-02027"},"M16-GAP-02027":{"line":2026,"offset":351094,"length":168,"previous":"M16-GAP-02026","next":"M16-GAP-02028"},"M16-GAP-02028":{"line":2027,"offset":351262,"length":170,"previous":"M16-GAP-02027","next":"M16-GAP-02029"},"M16-GAP-02029":{"line":2028,"offset":351432,"length":177,"previous":"M16-GAP-02028","next":"M16-GAP-02030"},"M16-GAP-02030":{"line":2029,"offset":351609,"length":171,"previous":"M16-GAP-02029","next":"M16-GAP-02031"},"M16-GAP-02031":{"line":2030,"offset":351780,"length":171,"previous":"M16-GAP-02030","next":"M16-GAP-02032"},"M16-GAP-02032":{"line":2031,"offset":351951,"length":169,"previous":"M16-GAP-02031","next":"M16-GAP-02033"},"M16-GAP-02033":{"line":2032,"offset":352120,"length":161,"previous":"M16-GAP-02032","next":"M16-GAP-02034"},"M16-GAP-02034":{"line":2033,"offset":352281,"length":171,"previous":"M16-GAP-02033","next":"M16-GAP-02035"},"M16-GAP-02035":{"line":2034,"offset":352452,"length":167,"previous":"M16-GAP-02034","next":"M16-GAP-02036"},"M16-GAP-02036":{"line":2035,"offset":352619,"length":170,"previous":"M16-GAP-02035","next":"M16-GAP-02037"},"M16-GAP-02037":{"line":2036,"offset":352789,"length":177,"previous":"M16-GAP-02036","next":"M16-GAP-02038"},"M16-GAP-02038":{"line":2037,"offset":352966,"length":169,"previous":"M16-GAP-02037","next":"M16-GAP-02039"},"M16-GAP-02039":{"line":2038,"offset":353135,"length":173,"previous":"M16-GAP-02038","next":"M16-GAP-02040"},"M16-GAP-02040":{"line":2039,"offset":353308,"length":170,"previous":"M16-GAP-02039","next":"M16-GAP-02041"},"M16-GAP-02041":{"line":2040,"offset":353478,"length":171,"previous":"M16-GAP-02040","next":"M16-GAP-02042"},"M16-GAP-02042":{"line":2041,"offset":353649,"length":172,"previous":"M16-GAP-02041","next":"M16-GAP-02043"},"M16-GAP-02043":{"line":2042,"offset":353821,"length":169,"previous":"M16-GAP-02042","next":"M16-GAP-02044"},"M16-GAP-02044":{"line":2043,"offset":353990,"length":174,"previous":"M16-GAP-02043","next":"M16-GAP-02045"},"M16-GAP-02045":{"line":2044,"offset":354164,"length":168,"previous":"M16-GAP-02044","next":"M16-GAP-02046"},"M16-GAP-02046":{"line":2045,"offset":354332,"length":168,"previous":"M16-GAP-02045","next":"M16-GAP-02047"},"M16-GAP-02047":{"line":2046,"offset":354500,"length":173,"previous":"M16-GAP-02046","next":"M16-GAP-02048"},"M16-GAP-02048":{"line":2047,"offset":354673,"length":177,"previous":"M16-GAP-02047","next":"M16-GAP-02049"},"M16-GAP-02049":{"line":2048,"offset":354850,"length":181,"previous":"M16-GAP-02048","next":"M16-GAP-02050"},"M16-GAP-02050":{"line":2049,"offset":355031,"length":175,"previous":"M16-GAP-02049","next":"M16-GAP-02051"},"M16-GAP-02051":{"line":2050,"offset":355206,"length":167,"previous":"M16-GAP-02050","next":"M16-GAP-02052"},"M16-GAP-02052":{"line":2051,"offset":355373,"length":171,"previous":"M16-GAP-02051","next":"M16-GAP-02053"},"M16-GAP-02053":{"line":2052,"offset":355544,"length":173,"previous":"M16-GAP-02052","next":"M16-GAP-02054"},"M16-GAP-02054":{"line":2053,"offset":355717,"length":172,"previous":"M16-GAP-02053","next":"M16-GAP-02055"},"M16-GAP-02055":{"line":2054,"offset":355889,"length":173,"previous":"M16-GAP-02054","next":"M16-GAP-02056"},"M16-GAP-02056":{"line":2055,"offset":356062,"length":164,"previous":"M16-GAP-02055","next":"M16-GAP-02057"},"M16-GAP-02057":{"line":2056,"offset":356226,"length":170,"previous":"M16-GAP-02056","next":"M16-GAP-02058"},"M16-GAP-02058":{"line":2057,"offset":356396,"length":170,"previous":"M16-GAP-02057","next":"M16-GAP-02059"},"M16-GAP-02059":{"line":2058,"offset":356566,"length":170,"previous":"M16-GAP-02058","next":"M16-GAP-02060"},"M16-GAP-02060":{"line":2059,"offset":356736,"length":175,"previous":"M16-GAP-02059","next":"M16-GAP-02061"},"M16-GAP-02061":{"line":2060,"offset":356911,"length":181,"previous":"M16-GAP-02060","next":"M16-GAP-02062"},"M16-GAP-02062":{"line":2061,"offset":357092,"length":182,"previous":"M16-GAP-02061","next":"M16-GAP-02063"},"M16-GAP-02063":{"line":2062,"offset":357274,"length":164,"previous":"M16-GAP-02062","next":"M16-GAP-02064"},"M16-GAP-02064":{"line":2063,"offset":357438,"length":178,"previous":"M16-GAP-02063","next":"M16-GAP-02065"},"M16-GAP-02065":{"line":2064,"offset":357616,"length":184,"previous":"M16-GAP-02064","next":"M16-GAP-02066"},"M16-GAP-02066":{"line":2065,"offset":357800,"length":171,"previous":"M16-GAP-02065","next":"M16-GAP-02067"},"M16-GAP-02067":{"line":2066,"offset":357971,"length":174,"previous":"M16-GAP-02066","next":"M16-GAP-02068"},"M16-GAP-02068":{"line":2067,"offset":358145,"length":180,"previous":"M16-GAP-02067","next":"M16-GAP-02069"},"M16-GAP-02069":{"line":2068,"offset":358325,"length":179,"previous":"M16-GAP-02068","next":"M16-GAP-02070"},"M16-GAP-02070":{"line":2069,"offset":358504,"length":183,"previous":"M16-GAP-02069","next":"M16-GAP-02071"},"M16-GAP-02071":{"line":2070,"offset":358687,"length":174,"previous":"M16-GAP-02070","next":"M16-GAP-02072"},"M16-GAP-02072":{"line":2071,"offset":358861,"length":172,"previous":"M16-GAP-02071","next":"M16-GAP-02073"},"M16-GAP-02073":{"line":2072,"offset":359033,"length":184,"previous":"M16-GAP-02072","next":"M16-GAP-02074"},"M16-GAP-02074":{"line":2073,"offset":359217,"length":171,"previous":"M16-GAP-02073","next":"M16-GAP-02075"},"M16-GAP-02075":{"line":2074,"offset":359388,"length":169,"previous":"M16-GAP-02074","next":"M16-GAP-02076"},"M16-GAP-02076":{"line":2075,"offset":359557,"length":176,"previous":"M16-GAP-02075","next":"M16-GAP-02077"},"M16-GAP-02077":{"line":2076,"offset":359733,"length":174,"previous":"M16-GAP-02076","next":"M16-GAP-02078"},"M16-GAP-02078":{"line":2077,"offset":359907,"length":167,"previous":"M16-GAP-02077","next":"M16-GAP-02079"},"M16-GAP-02079":{"line":2078,"offset":360074,"length":169,"previous":"M16-GAP-02078","next":"M16-GAP-02080"},"M16-GAP-02080":{"line":2079,"offset":360243,"length":166,"previous":"M16-GAP-02079","next":"M16-GAP-02081"},"M16-GAP-02081":{"line":2080,"offset":360409,"length":176,"previous":"M16-GAP-02080","next":"M16-GAP-02082"},"M16-GAP-02082":{"line":2081,"offset":360585,"length":174,"previous":"M16-GAP-02081","next":"M16-GAP-02083"},"M16-GAP-02083":{"line":2082,"offset":360759,"length":178,"previous":"M16-GAP-02082","next":"M16-GAP-02084"},"M16-GAP-02084":{"line":2083,"offset":360937,"length":176,"previous":"M16-GAP-02083","next":"M16-GAP-02085"},"M16-GAP-02085":{"line":2084,"offset":361113,"length":175,"previous":"M16-GAP-02084","next":"M16-GAP-02086"},"M16-GAP-02086":{"line":2085,"offset":361288,"length":177,"previous":"M16-GAP-02085","next":"M16-GAP-02087"},"M16-GAP-02087":{"line":2086,"offset":361465,"length":176,"previous":"M16-GAP-02086","next":"M16-GAP-02088"},"M16-GAP-02088":{"line":2087,"offset":361641,"length":168,"previous":"M16-GAP-02087","next":"M16-GAP-02089"},"M16-GAP-02089":{"line":2088,"offset":361809,"length":174,"previous":"M16-GAP-02088","next":"M16-GAP-02090"},"M16-GAP-02090":{"line":2089,"offset":361983,"length":176,"previous":"M16-GAP-02089","next":"M16-GAP-02091"},"M16-GAP-02091":{"line":2090,"offset":362159,"length":175,"previous":"M16-GAP-02090","next":"M16-GAP-02092"},"M16-GAP-02092":{"line":2091,"offset":362334,"length":179,"previous":"M16-GAP-02091","next":"M16-GAP-02093"},"M16-GAP-02093":{"line":2092,"offset":362513,"length":172,"previous":"M16-GAP-02092","next":"M16-GAP-02094"},"M16-GAP-02094":{"line":2093,"offset":362685,"length":173,"previous":"M16-GAP-02093","next":"M16-GAP-02095"},"M16-GAP-02095":{"line":2094,"offset":362858,"length":173,"previous":"M16-GAP-02094","next":"M16-GAP-02096"},"M16-GAP-02096":{"line":2095,"offset":363031,"length":177,"previous":"M16-GAP-02095","next":"M16-GAP-02097"},"M16-GAP-02097":{"line":2096,"offset":363208,"length":182,"previous":"M16-GAP-02096","next":"M16-GAP-02098"},"M16-GAP-02098":{"line":2097,"offset":363390,"length":176,"previous":"M16-GAP-02097","next":"M16-GAP-02099"},"M16-GAP-02099":{"line":2098,"offset":363566,"length":178,"previous":"M16-GAP-02098","next":"M16-GAP-02100"},"M16-GAP-02100":{"line":2099,"offset":363744,"length":193,"previous":"M16-GAP-02099","next":"M16-GAP-02101"},"M16-GAP-02101":{"line":2100,"offset":363937,"length":170,"previous":"M16-GAP-02100","next":"M16-GAP-02102"},"M16-GAP-02102":{"line":2101,"offset":364107,"length":179,"previous":"M16-GAP-02101","next":"M16-GAP-02103"},"M16-GAP-02103":{"line":2102,"offset":364286,"length":172,"previous":"M16-GAP-02102","next":"M16-GAP-02104"},"M16-GAP-02104":{"line":2103,"offset":364458,"length":173,"previous":"M16-GAP-02103","next":"M16-GAP-02105"},"M16-GAP-02105":{"line":2104,"offset":364631,"length":168,"previous":"M16-GAP-02104","next":"M16-GAP-02106"},"M16-GAP-02106":{"line":2105,"offset":364799,"length":165,"previous":"M16-GAP-02105","next":"M16-GAP-02107"},"M16-GAP-02107":{"line":2106,"offset":364964,"length":177,"previous":"M16-GAP-02106","next":"M16-GAP-02108"},"M16-GAP-02108":{"line":2107,"offset":365141,"length":171,"previous":"M16-GAP-02107","next":"M16-GAP-02109"},"M16-GAP-02109":{"line":2108,"offset":365312,"length":188,"previous":"M16-GAP-02108","next":"M16-GAP-02110"},"M16-GAP-02110":{"line":2109,"offset":365500,"length":167,"previous":"M16-GAP-02109","next":"M16-GAP-02111"},"M16-GAP-02111":{"line":2110,"offset":365667,"length":171,"previous":"M16-GAP-02110","next":"M16-GAP-02112"},"M16-GAP-02112":{"line":2111,"offset":365838,"length":170,"previous":"M16-GAP-02111","next":"M16-GAP-02113"},"M16-GAP-02113":{"line":2112,"offset":366008,"length":175,"previous":"M16-GAP-02112","next":"M16-GAP-02114"},"M16-GAP-02114":{"line":2113,"offset":366183,"length":182,"previous":"M16-GAP-02113","next":"M16-GAP-02115"},"M16-GAP-02115":{"line":2114,"offset":366365,"length":177,"previous":"M16-GAP-02114","next":"M16-GAP-02116"},"M16-GAP-02116":{"line":2115,"offset":366542,"length":175,"previous":"M16-GAP-02115","next":"M16-GAP-02117"},"M16-GAP-02117":{"line":2116,"offset":366717,"length":177,"previous":"M16-GAP-02116","next":"M16-GAP-02118"},"M16-GAP-02118":{"line":2117,"offset":366894,"length":170,"previous":"M16-GAP-02117","next":"M16-GAP-02119"},"M16-GAP-02119":{"line":2118,"offset":367064,"length":172,"previous":"M16-GAP-02118","next":"M16-GAP-02120"},"M16-GAP-02120":{"line":2119,"offset":367236,"length":171,"previous":"M16-GAP-02119","next":"M16-GAP-02121"},"M16-GAP-02121":{"line":2120,"offset":367407,"length":171,"previous":"M16-GAP-02120","next":"M16-GAP-02122"},"M16-GAP-02122":{"line":2121,"offset":367578,"length":176,"previous":"M16-GAP-02121","next":"M16-GAP-02123"},"M16-GAP-02123":{"line":2122,"offset":367754,"length":176,"previous":"M16-GAP-02122","next":"M16-GAP-02124"},"M16-GAP-02124":{"line":2123,"offset":367930,"length":165,"previous":"M16-GAP-02123","next":"M16-GAP-02125"},"M16-GAP-02125":{"line":2124,"offset":368095,"length":175,"previous":"M16-GAP-02124","next":"M16-GAP-02126"},"M16-GAP-02126":{"line":2125,"offset":368270,"length":170,"previous":"M16-GAP-02125","next":"M16-GAP-02127"},"M16-GAP-02127":{"line":2126,"offset":368440,"length":174,"previous":"M16-GAP-02126","next":"M16-GAP-02128"},"M16-GAP-02128":{"line":2127,"offset":368614,"length":172,"previous":"M16-GAP-02127","next":"M16-GAP-02129"},"M16-GAP-02129":{"line":2128,"offset":368786,"length":176,"previous":"M16-GAP-02128","next":"M16-GAP-02130"},"M16-GAP-02130":{"line":2129,"offset":368962,"length":180,"previous":"M16-GAP-02129","next":"M16-GAP-02131"},"M16-GAP-02131":{"line":2130,"offset":369142,"length":165,"previous":"M16-GAP-02130","next":"M16-GAP-02132"},"M16-GAP-02132":{"line":2131,"offset":369307,"length":173,"previous":"M16-GAP-02131","next":"M16-GAP-02133"},"M16-GAP-02133":{"line":2132,"offset":369480,"length":166,"previous":"M16-GAP-02132","next":"M16-GAP-02134"},"M16-GAP-02134":{"line":2133,"offset":369646,"length":183,"previous":"M16-GAP-02133","next":"M16-GAP-02135"},"M16-GAP-02135":{"line":2134,"offset":369829,"length":190,"previous":"M16-GAP-02134","next":"M16-GAP-02136"},"M16-GAP-02136":{"line":2135,"offset":370019,"length":176,"previous":"M16-GAP-02135","next":"M16-GAP-02137"},"M16-GAP-02137":{"line":2136,"offset":370195,"length":174,"previous":"M16-GAP-02136","next":"M16-GAP-02138"},"M16-GAP-02138":{"line":2137,"offset":370369,"length":172,"previous":"M16-GAP-02137","next":"M16-GAP-02139"},"M16-GAP-02139":{"line":2138,"offset":370541,"length":167,"previous":"M16-GAP-02138","next":"M16-GAP-02140"},"M16-GAP-02140":{"line":2139,"offset":370708,"length":175,"previous":"M16-GAP-02139","next":"M16-GAP-02141"},"M16-GAP-02141":{"line":2140,"offset":370883,"length":171,"previous":"M16-GAP-02140","next":"M16-GAP-02142"},"M16-GAP-02142":{"line":2141,"offset":371054,"length":192,"previous":"M16-GAP-02141","next":"M16-GAP-02143"},"M16-GAP-02143":{"line":2142,"offset":371246,"length":190,"previous":"M16-GAP-02142","next":"M16-GAP-02144"},"M16-GAP-02144":{"line":2143,"offset":371436,"length":186,"previous":"M16-GAP-02143","next":"M16-GAP-02145"},"M16-GAP-02145":{"line":2144,"offset":371622,"length":177,"previous":"M16-GAP-02144","next":"M16-GAP-02146"},"M16-GAP-02146":{"line":2145,"offset":371799,"length":180,"previous":"M16-GAP-02145","next":"M16-GAP-02147"},"M16-GAP-02147":{"line":2146,"offset":371979,"length":175,"previous":"M16-GAP-02146","next":"M16-GAP-02148"},"M16-GAP-02148":{"line":2147,"offset":372154,"length":187,"previous":"M16-GAP-02147","next":"M16-GAP-02149"},"M16-GAP-02149":{"line":2148,"offset":372341,"length":174,"previous":"M16-GAP-02148","next":"M16-GAP-02150"},"M16-GAP-02150":{"line":2149,"offset":372515,"length":184,"previous":"M16-GAP-02149","next":"M16-GAP-02151"},"M16-GAP-02151":{"line":2150,"offset":372699,"length":167,"previous":"M16-GAP-02150","next":"M16-GAP-02152"},"M16-GAP-02152":{"line":2151,"offset":372866,"length":185,"previous":"M16-GAP-02151","next":"M16-GAP-02153"},"M16-GAP-02153":{"line":2152,"offset":373051,"length":176,"previous":"M16-GAP-02152","next":"M16-GAP-02154"},"M16-GAP-02154":{"line":2153,"offset":373227,"length":180,"previous":"M16-GAP-02153","next":"M16-GAP-02155"},"M16-GAP-02155":{"line":2154,"offset":373407,"length":167,"previous":"M16-GAP-02154","next":"M16-GAP-02156"},"M16-GAP-02156":{"line":2155,"offset":373574,"length":171,"previous":"M16-GAP-02155","next":"M16-GAP-02157"},"M16-GAP-02157":{"line":2156,"offset":373745,"length":171,"previous":"M16-GAP-02156","next":"M16-GAP-02158"},"M16-GAP-02158":{"line":2157,"offset":373916,"length":174,"previous":"M16-GAP-02157","next":"M16-GAP-02159"},"M16-GAP-02159":{"line":2158,"offset":374090,"length":175,"previous":"M16-GAP-02158","next":"M16-GAP-02160"},"M16-GAP-02160":{"line":2159,"offset":374265,"length":174,"previous":"M16-GAP-02159","next":"M16-GAP-02161"},"M16-GAP-02161":{"line":2160,"offset":374439,"length":175,"previous":"M16-GAP-02160","next":"M16-GAP-02162"},"M16-GAP-02162":{"line":2161,"offset":374614,"length":173,"previous":"M16-GAP-02161","next":"M16-GAP-02163"},"M16-GAP-02163":{"line":2162,"offset":374787,"length":172,"previous":"M16-GAP-02162","next":"M16-GAP-02164"},"M16-GAP-02164":{"line":2163,"offset":374959,"length":174,"previous":"M16-GAP-02163","next":"M16-GAP-02165"},"M16-GAP-02165":{"line":2164,"offset":375133,"length":179,"previous":"M16-GAP-02164","next":"M16-GAP-02166"},"M16-GAP-02166":{"line":2165,"offset":375312,"length":172,"previous":"M16-GAP-02165","next":"M16-GAP-02167"},"M16-GAP-02167":{"line":2166,"offset":375484,"length":172,"previous":"M16-GAP-02166","next":"M16-GAP-02168"},"M16-GAP-02168":{"line":2167,"offset":375656,"length":181,"previous":"M16-GAP-02167","next":"M16-GAP-02169"},"M16-GAP-02169":{"line":2168,"offset":375837,"length":180,"previous":"M16-GAP-02168","next":"M16-GAP-02170"},"M16-GAP-02170":{"line":2169,"offset":376017,"length":165,"previous":"M16-GAP-02169","next":"M16-GAP-02171"},"M16-GAP-02171":{"line":2170,"offset":376182,"length":165,"previous":"M16-GAP-02170","next":"M16-GAP-02172"},"M16-GAP-02172":{"line":2171,"offset":376347,"length":176,"previous":"M16-GAP-02171","next":"M16-GAP-02173"},"M16-GAP-02173":{"line":2172,"offset":376523,"length":166,"previous":"M16-GAP-02172","next":"M16-GAP-02174"},"M16-GAP-02174":{"line":2173,"offset":376689,"length":175,"previous":"M16-GAP-02173","next":"M16-GAP-02175"},"M16-GAP-02175":{"line":2174,"offset":376864,"length":180,"previous":"M16-GAP-02174","next":"M16-GAP-02176"},"M16-GAP-02176":{"line":2175,"offset":377044,"length":171,"previous":"M16-GAP-02175","next":"M16-GAP-02177"},"M16-GAP-02177":{"line":2176,"offset":377215,"length":179,"previous":"M16-GAP-02176","next":"M16-GAP-02178"},"M16-GAP-02178":{"line":2177,"offset":377394,"length":190,"previous":"M16-GAP-02177","next":"M16-GAP-02179"},"M16-GAP-02179":{"line":2178,"offset":377584,"length":180,"previous":"M16-GAP-02178","next":"M16-GAP-02180"},"M16-GAP-02180":{"line":2179,"offset":377764,"length":185,"previous":"M16-GAP-02179","next":"M16-GAP-02181"},"M16-GAP-02181":{"line":2180,"offset":377949,"length":194,"previous":"M16-GAP-02180","next":"M16-GAP-02182"},"M16-GAP-02182":{"line":2181,"offset":378143,"length":180,"previous":"M16-GAP-02181","next":"M16-GAP-02183"},"M16-GAP-02183":{"line":2182,"offset":378323,"length":189,"previous":"M16-GAP-02182","next":"M16-GAP-02184"},"M16-GAP-02184":{"line":2183,"offset":378512,"length":182,"previous":"M16-GAP-02183","next":"M16-GAP-02185"},"M16-GAP-02185":{"line":2184,"offset":378694,"length":186,"previous":"M16-GAP-02184","next":"M16-GAP-02186"},"M16-GAP-02186":{"line":2185,"offset":378880,"length":182,"previous":"M16-GAP-02185","next":"M16-GAP-02187"},"M16-GAP-02187":{"line":2186,"offset":379062,"length":180,"previous":"M16-GAP-02186","next":"M16-GAP-02188"},"M16-GAP-02188":{"line":2187,"offset":379242,"length":165,"previous":"M16-GAP-02187","next":"M16-GAP-02189"},"M16-GAP-02189":{"line":2188,"offset":379407,"length":170,"previous":"M16-GAP-02188","next":"M16-GAP-02190"},"M16-GAP-02190":{"line":2189,"offset":379577,"length":172,"previous":"M16-GAP-02189","next":"M16-GAP-02191"},"M16-GAP-02191":{"line":2190,"offset":379749,"length":177,"previous":"M16-GAP-02190","next":"M16-GAP-02192"},"M16-GAP-02192":{"line":2191,"offset":379926,"length":176,"previous":"M16-GAP-02191","next":"M16-GAP-02193"},"M16-GAP-02193":{"line":2192,"offset":380102,"length":172,"previous":"M16-GAP-02192","next":"M16-GAP-02194"},"M16-GAP-02194":{"line":2193,"offset":380274,"length":178,"previous":"M16-GAP-02193","next":"M16-GAP-02195"},"M16-GAP-02195":{"line":2194,"offset":380452,"length":175,"previous":"M16-GAP-02194","next":"M16-GAP-02196"},"M16-GAP-02196":{"line":2195,"offset":380627,"length":174,"previous":"M16-GAP-02195","next":"M16-GAP-02197"},"M16-GAP-02197":{"line":2196,"offset":380801,"length":182,"previous":"M16-GAP-02196","next":"M16-GAP-02198"},"M16-GAP-02198":{"line":2197,"offset":380983,"length":176,"previous":"M16-GAP-02197","next":"M16-GAP-02199"},"M16-GAP-02199":{"line":2198,"offset":381159,"length":172,"previous":"M16-GAP-02198","next":"M16-GAP-02200"},"M16-GAP-02200":{"line":2199,"offset":381331,"length":176,"previous":"M16-GAP-02199","next":"M16-GAP-02201"},"M16-GAP-02201":{"line":2200,"offset":381507,"length":176,"previous":"M16-GAP-02200","next":"M16-GAP-02202"},"M16-GAP-02202":{"line":2201,"offset":381683,"length":188,"previous":"M16-GAP-02201","next":"M16-GAP-02203"},"M16-GAP-02203":{"line":2202,"offset":381871,"length":167,"previous":"M16-GAP-02202","next":"M16-GAP-02204"},"M16-GAP-02204":{"line":2203,"offset":382038,"length":167,"previous":"M16-GAP-02203","next":"M16-GAP-02205"},"M16-GAP-02205":{"line":2204,"offset":382205,"length":169,"previous":"M16-GAP-02204","next":"M16-GAP-02206"},"M16-GAP-02206":{"line":2205,"offset":382374,"length":177,"previous":"M16-GAP-02205","next":"M16-GAP-02207"},"M16-GAP-02207":{"line":2206,"offset":382551,"length":171,"previous":"M16-GAP-02206","next":"M16-GAP-02208"},"M16-GAP-02208":{"line":2207,"offset":382722,"length":178,"previous":"M16-GAP-02207","next":"M16-GAP-02209"},"M16-GAP-02209":{"line":2208,"offset":382900,"length":174,"previous":"M16-GAP-02208","next":"M16-GAP-02210"},"M16-GAP-02210":{"line":2209,"offset":383074,"length":176,"previous":"M16-GAP-02209","next":"M16-GAP-02211"},"M16-GAP-02211":{"line":2210,"offset":383250,"length":171,"previous":"M16-GAP-02210","next":"M16-GAP-02212"},"M16-GAP-02212":{"line":2211,"offset":383421,"length":164,"previous":"M16-GAP-02211","next":"M16-GAP-02213"},"M16-GAP-02213":{"line":2212,"offset":383585,"length":161,"previous":"M16-GAP-02212","next":"M16-GAP-02214"},"M16-GAP-02214":{"line":2213,"offset":383746,"length":166,"previous":"M16-GAP-02213","next":"M16-GAP-02215"},"M16-GAP-02215":{"line":2214,"offset":383912,"length":161,"previous":"M16-GAP-02214","next":"M16-GAP-02216"},"M16-GAP-02216":{"line":2215,"offset":384073,"length":163,"previous":"M16-GAP-02215","next":"M16-GAP-02217"},"M16-GAP-02217":{"line":2216,"offset":384236,"length":179,"previous":"M16-GAP-02216","next":"M16-GAP-02218"},"M16-GAP-02218":{"line":2217,"offset":384415,"length":182,"previous":"M16-GAP-02217","next":"M16-GAP-02219"},"M16-GAP-02219":{"line":2218,"offset":384597,"length":193,"previous":"M16-GAP-02218","next":"M16-GAP-02220"},"M16-GAP-02220":{"line":2219,"offset":384790,"length":173,"previous":"M16-GAP-02219","next":"M16-GAP-02221"},"M16-GAP-02221":{"line":2220,"offset":384963,"length":185,"previous":"M16-GAP-02220","next":"M16-GAP-02222"},"M16-GAP-02222":{"line":2221,"offset":385148,"length":178,"previous":"M16-GAP-02221","next":"M16-GAP-02223"},"M16-GAP-02223":{"line":2222,"offset":385326,"length":176,"previous":"M16-GAP-02222","next":"M16-GAP-02224"},"M16-GAP-02224":{"line":2223,"offset":385502,"length":173,"previous":"M16-GAP-02223","next":"M16-GAP-02225"},"M16-GAP-02225":{"line":2224,"offset":385675,"length":193,"previous":"M16-GAP-02224","next":"M16-GAP-02226"},"M16-GAP-02226":{"line":2225,"offset":385868,"length":192,"previous":"M16-GAP-02225","next":"M16-GAP-02227"},"M16-GAP-02227":{"line":2226,"offset":386060,"length":195,"previous":"M16-GAP-02226","next":"M16-GAP-02228"},"M16-GAP-02228":{"line":2227,"offset":386255,"length":193,"previous":"M16-GAP-02227","next":"M16-GAP-02229"},"M16-GAP-02229":{"line":2228,"offset":386448,"length":194,"previous":"M16-GAP-02228","next":"M16-GAP-02230"},"M16-GAP-02230":{"line":2229,"offset":386642,"length":192,"previous":"M16-GAP-02229","next":"M16-GAP-02231"},"M16-GAP-02231":{"line":2230,"offset":386834,"length":168,"previous":"M16-GAP-02230","next":"M16-GAP-02232"},"M16-GAP-02232":{"line":2231,"offset":387002,"length":170,"previous":"M16-GAP-02231","next":"M16-GAP-02233"},"M16-GAP-02233":{"line":2232,"offset":387172,"length":174,"previous":"M16-GAP-02232","next":"M16-GAP-02234"},"M16-GAP-02234":{"line":2233,"offset":387346,"length":160,"previous":"M16-GAP-02233","next":"M16-GAP-02235"},"M16-GAP-02235":{"line":2234,"offset":387506,"length":166,"previous":"M16-GAP-02234","next":"M16-GAP-02236"},"M16-GAP-02236":{"line":2235,"offset":387672,"length":159,"previous":"M16-GAP-02235","next":"M16-GAP-02237"},"M16-GAP-02237":{"line":2236,"offset":387831,"length":162,"previous":"M16-GAP-02236","next":"M16-GAP-02238"},"M16-GAP-02238":{"line":2237,"offset":387993,"length":170,"previous":"M16-GAP-02237","next":"M16-GAP-02239"},"M16-GAP-02239":{"line":2238,"offset":388163,"length":160,"previous":"M16-GAP-02238","next":"M16-GAP-02240"},"M16-GAP-02240":{"line":2239,"offset":388323,"length":173,"previous":"M16-GAP-02239","next":"M16-GAP-02241"},"M16-GAP-02241":{"line":2240,"offset":388496,"length":162,"previous":"M16-GAP-02240","next":"M16-GAP-02242"},"M16-GAP-02242":{"line":2241,"offset":388658,"length":178,"previous":"M16-GAP-02241","next":"M16-GAP-02243"},"M16-GAP-02243":{"line":2242,"offset":388836,"length":162,"previous":"M16-GAP-02242","next":"M16-GAP-02244"},"M16-GAP-02244":{"line":2243,"offset":388998,"length":160,"previous":"M16-GAP-02243","next":"M16-GAP-02245"},"M16-GAP-02245":{"line":2244,"offset":389158,"length":177,"previous":"M16-GAP-02244","next":"M16-GAP-02246"},"M16-GAP-02246":{"line":2245,"offset":389335,"length":166,"previous":"M16-GAP-02245","next":"M16-GAP-02247"},"M16-GAP-02247":{"line":2246,"offset":389501,"length":167,"previous":"M16-GAP-02246","next":"M16-GAP-02248"},"M16-GAP-02248":{"line":2247,"offset":389668,"length":169,"previous":"M16-GAP-02247","next":"M16-GAP-02249"},"M16-GAP-02249":{"line":2248,"offset":389837,"length":160,"previous":"M16-GAP-02248","next":"M16-GAP-02250"},"M16-GAP-02250":{"line":2249,"offset":389997,"length":166,"previous":"M16-GAP-02249","next":"M16-GAP-02251"},"M16-GAP-02251":{"line":2250,"offset":390163,"length":167,"previous":"M16-GAP-02250","next":"M16-GAP-02252"},"M16-GAP-02252":{"line":2251,"offset":390330,"length":159,"previous":"M16-GAP-02251","next":"M16-GAP-02253"},"M16-GAP-02253":{"line":2252,"offset":390489,"length":160,"previous":"M16-GAP-02252","next":"M16-GAP-02254"},"M16-GAP-02254":{"line":2253,"offset":390649,"length":172,"previous":"M16-GAP-02253","next":"M16-GAP-02255"},"M16-GAP-02255":{"line":2254,"offset":390821,"length":161,"previous":"M16-GAP-02254","next":"M16-GAP-02256"},"M16-GAP-02256":{"line":2255,"offset":390982,"length":162,"previous":"M16-GAP-02255","next":"M16-GAP-02257"},"M16-GAP-02257":{"line":2256,"offset":391144,"length":163,"previous":"M16-GAP-02256","next":"M16-GAP-02258"},"M16-GAP-02258":{"line":2257,"offset":391307,"length":176,"previous":"M16-GAP-02257","next":"M16-GAP-02259"},"M16-GAP-02259":{"line":2258,"offset":391483,"length":172,"previous":"M16-GAP-02258","next":"M16-GAP-02260"},"M16-GAP-02260":{"line":2259,"offset":391655,"length":166,"previous":"M16-GAP-02259","next":"M16-GAP-02261"},"M16-GAP-02261":{"line":2260,"offset":391821,"length":160,"previous":"M16-GAP-02260","next":"M16-GAP-02262"},"M16-GAP-02262":{"line":2261,"offset":391981,"length":163,"previous":"M16-GAP-02261","next":"M16-GAP-02263"},"M16-GAP-02263":{"line":2262,"offset":392144,"length":162,"previous":"M16-GAP-02262","next":"M16-GAP-02264"},"M16-GAP-02264":{"line":2263,"offset":392306,"length":166,"previous":"M16-GAP-02263","next":"M16-GAP-02265"},"M16-GAP-02265":{"line":2264,"offset":392472,"length":166,"previous":"M16-GAP-02264","next":"M16-GAP-02266"},"M16-GAP-02266":{"line":2265,"offset":392638,"length":167,"previous":"M16-GAP-02265","next":"M16-GAP-02267"},"M16-GAP-02267":{"line":2266,"offset":392805,"length":167,"previous":"M16-GAP-02266","next":"M16-GAP-02268"},"M16-GAP-02268":{"line":2267,"offset":392972,"length":169,"previous":"M16-GAP-02267","next":"M16-GAP-02269"},"M16-GAP-02269":{"line":2268,"offset":393141,"length":166,"previous":"M16-GAP-02268","next":"M16-GAP-02270"},"M16-GAP-02270":{"line":2269,"offset":393307,"length":168,"previous":"M16-GAP-02269","next":"M16-GAP-02271"},"M16-GAP-02271":{"line":2270,"offset":393475,"length":164,"previous":"M16-GAP-02270","next":"M16-GAP-02272"},"M16-GAP-02272":{"line":2271,"offset":393639,"length":162,"previous":"M16-GAP-02271","next":"M16-GAP-02273"},"M16-GAP-02273":{"line":2272,"offset":393801,"length":169,"previous":"M16-GAP-02272","next":"M16-GAP-02274"},"M16-GAP-02274":{"line":2273,"offset":393970,"length":173,"previous":"M16-GAP-02273","next":"M16-GAP-02275"},"M16-GAP-02275":{"line":2274,"offset":394143,"length":162,"previous":"M16-GAP-02274","next":"M16-GAP-02276"},"M16-GAP-02276":{"line":2275,"offset":394305,"length":168,"previous":"M16-GAP-02275","next":"M16-GAP-02277"},"M16-GAP-02277":{"line":2276,"offset":394473,"length":168,"previous":"M16-GAP-02276","next":"M16-GAP-02278"},"M16-GAP-02278":{"line":2277,"offset":394641,"length":169,"previous":"M16-GAP-02277","next":"M16-GAP-02279"},"M16-GAP-02279":{"line":2278,"offset":394810,"length":173,"previous":"M16-GAP-02278","next":"M16-GAP-02280"},"M16-GAP-02280":{"line":2279,"offset":394983,"length":165,"previous":"M16-GAP-02279","next":"M16-GAP-02281"},"M16-GAP-02281":{"line":2280,"offset":395148,"length":179,"previous":"M16-GAP-02280","next":"M16-GAP-02282"},"M16-GAP-02282":{"line":2281,"offset":395327,"length":179,"previous":"M16-GAP-02281","next":"M16-GAP-02283"},"M16-GAP-02283":{"line":2282,"offset":395506,"length":177,"previous":"M16-GAP-02282","next":"M16-GAP-02284"},"M16-GAP-02284":{"line":2283,"offset":395683,"length":172,"previous":"M16-GAP-02283","next":"M16-GAP-02285"},"M16-GAP-02285":{"line":2284,"offset":395855,"length":171,"previous":"M16-GAP-02284","next":"M16-GAP-02286"},"M16-GAP-02286":{"line":2285,"offset":396026,"length":171,"previous":"M16-GAP-02285","next":"M16-GAP-02287"},"M16-GAP-02287":{"line":2286,"offset":396197,"length":167,"previous":"M16-GAP-02286","next":"M16-GAP-02288"},"M16-GAP-02288":{"line":2287,"offset":396364,"length":170,"previous":"M16-GAP-02287","next":"M16-GAP-02289"},"M16-GAP-02289":{"line":2288,"offset":396534,"length":167,"previous":"M16-GAP-02288","next":"M16-GAP-02290"},"M16-GAP-02290":{"line":2289,"offset":396701,"length":167,"previous":"M16-GAP-02289","next":"M16-GAP-02291"},"M16-GAP-02291":{"line":2290,"offset":396868,"length":174,"previous":"M16-GAP-02290","next":"M16-GAP-02292"},"M16-GAP-02292":{"line":2291,"offset":397042,"length":179,"previous":"M16-GAP-02291","next":"M16-GAP-02293"},"M16-GAP-02293":{"line":2292,"offset":397221,"length":170,"previous":"M16-GAP-02292","next":"M16-GAP-02294"},"M16-GAP-02294":{"line":2293,"offset":397391,"length":166,"previous":"M16-GAP-02293","next":"M16-GAP-02295"},"M16-GAP-02295":{"line":2294,"offset":397557,"length":174,"previous":"M16-GAP-02294","next":"M16-GAP-02296"},"M16-GAP-02296":{"line":2295,"offset":397731,"length":172,"previous":"M16-GAP-02295","next":"M16-GAP-02297"},"M16-GAP-02297":{"line":2296,"offset":397903,"length":165,"previous":"M16-GAP-02296","next":"M16-GAP-02298"},"M16-GAP-02298":{"line":2297,"offset":398068,"length":169,"previous":"M16-GAP-02297","next":"M16-GAP-02299"},"M16-GAP-02299":{"line":2298,"offset":398237,"length":170,"previous":"M16-GAP-02298","next":"M16-GAP-02300"},"M16-GAP-02300":{"line":2299,"offset":398407,"length":170,"previous":"M16-GAP-02299","next":"M16-GAP-02301"},"M16-GAP-02301":{"line":2300,"offset":398577,"length":170,"previous":"M16-GAP-02300","next":"M16-GAP-02302"},"M16-GAP-02302":{"line":2301,"offset":398747,"length":172,"previous":"M16-GAP-02301","next":"M16-GAP-02303"},"M16-GAP-02303":{"line":2302,"offset":398919,"length":171,"previous":"M16-GAP-02302","next":"M16-GAP-02304"},"M16-GAP-02304":{"line":2303,"offset":399090,"length":174,"previous":"M16-GAP-02303","next":"M16-GAP-02305"},"M16-GAP-02305":{"line":2304,"offset":399264,"length":172,"previous":"M16-GAP-02304","next":"M16-GAP-02306"},"M16-GAP-02306":{"line":2305,"offset":399436,"length":175,"previous":"M16-GAP-02305","next":"M16-GAP-02307"},"M16-GAP-02307":{"line":2306,"offset":399611,"length":168,"previous":"M16-GAP-02306","next":"M16-GAP-02308"},"M16-GAP-02308":{"line":2307,"offset":399779,"length":173,"previous":"M16-GAP-02307","next":"M16-GAP-02309"},"M16-GAP-02309":{"line":2308,"offset":399952,"length":175,"previous":"M16-GAP-02308","next":"M16-GAP-02310"},"M16-GAP-02310":{"line":2309,"offset":400127,"length":175,"previous":"M16-GAP-02309","next":"M16-GAP-02311"},"M16-GAP-02311":{"line":2310,"offset":400302,"length":184,"previous":"M16-GAP-02310","next":"M16-GAP-02312"},"M16-GAP-02312":{"line":2311,"offset":400486,"length":180,"previous":"M16-GAP-02311","next":"M16-GAP-02313"},"M16-GAP-02313":{"line":2312,"offset":400666,"length":177,"previous":"M16-GAP-02312","next":"M16-GAP-02314"},"M16-GAP-02314":{"line":2313,"offset":400843,"length":164,"previous":"M16-GAP-02313","next":"M16-GAP-02315"},"M16-GAP-02315":{"line":2314,"offset":401007,"length":167,"previous":"M16-GAP-02314","next":"M16-GAP-02316"},"M16-GAP-02316":{"line":2315,"offset":401174,"length":163,"previous":"M16-GAP-02315","next":"M16-GAP-02317"},"M16-GAP-02317":{"line":2316,"offset":401337,"length":164,"previous":"M16-GAP-02316","next":"M16-GAP-02318"},"M16-GAP-02318":{"line":2317,"offset":401501,"length":169,"previous":"M16-GAP-02317","next":"M16-GAP-02319"},"M16-GAP-02319":{"line":2318,"offset":401670,"length":170,"previous":"M16-GAP-02318","next":"M16-GAP-02320"},"M16-GAP-02320":{"line":2319,"offset":401840,"length":174,"previous":"M16-GAP-02319","next":"M16-GAP-02321"},"M16-GAP-02321":{"line":2320,"offset":402014,"length":180,"previous":"M16-GAP-02320","next":"M16-GAP-02322"},"M16-GAP-02322":{"line":2321,"offset":402194,"length":170,"previous":"M16-GAP-02321","next":"M16-GAP-02323"},"M16-GAP-02323":{"line":2322,"offset":402364,"length":171,"previous":"M16-GAP-02322","next":"M16-GAP-02324"},"M16-GAP-02324":{"line":2323,"offset":402535,"length":184,"previous":"M16-GAP-02323","next":"M16-GAP-02325"},"M16-GAP-02325":{"line":2324,"offset":402719,"length":167,"previous":"M16-GAP-02324","next":"M16-GAP-02326"},"M16-GAP-02326":{"line":2325,"offset":402886,"length":175,"previous":"M16-GAP-02325","next":"M16-GAP-02327"},"M16-GAP-02327":{"line":2326,"offset":403061,"length":171,"previous":"M16-GAP-02326","next":"M16-GAP-02328"},"M16-GAP-02328":{"line":2327,"offset":403232,"length":173,"previous":"M16-GAP-02327","next":"M16-GAP-02329"},"M16-GAP-02329":{"line":2328,"offset":403405,"length":179,"previous":"M16-GAP-02328","next":"M16-GAP-02330"},"M16-GAP-02330":{"line":2329,"offset":403584,"length":178,"previous":"M16-GAP-02329","next":"M16-GAP-02331"},"M16-GAP-02331":{"line":2330,"offset":403762,"length":179,"previous":"M16-GAP-02330","next":"M16-GAP-02332"},"M16-GAP-02332":{"line":2331,"offset":403941,"length":176,"previous":"M16-GAP-02331","next":"M16-GAP-02333"},"M16-GAP-02333":{"line":2332,"offset":404117,"length":171,"previous":"M16-GAP-02332","next":"M16-GAP-02334"},"M16-GAP-02334":{"line":2333,"offset":404288,"length":174,"previous":"M16-GAP-02333","next":"M16-GAP-02335"},"M16-GAP-02335":{"line":2334,"offset":404462,"length":175,"previous":"M16-GAP-02334","next":"M16-GAP-02336"},"M16-GAP-02336":{"line":2335,"offset":404637,"length":163,"previous":"M16-GAP-02335","next":"M16-GAP-02337"},"M16-GAP-02337":{"line":2336,"offset":404800,"length":170,"previous":"M16-GAP-02336","next":"M16-GAP-02338"},"M16-GAP-02338":{"line":2337,"offset":404970,"length":169,"previous":"M16-GAP-02337","next":"M16-GAP-02339"},"M16-GAP-02339":{"line":2338,"offset":405139,"length":172,"previous":"M16-GAP-02338","next":"M16-GAP-02340"},"M16-GAP-02340":{"line":2339,"offset":405311,"length":170,"previous":"M16-GAP-02339","next":"M16-GAP-02341"},"M16-GAP-02341":{"line":2340,"offset":405481,"length":170,"previous":"M16-GAP-02340","next":"M16-GAP-02342"},"M16-GAP-02342":{"line":2341,"offset":405651,"length":165,"previous":"M16-GAP-02341","next":"M16-GAP-02343"},"M16-GAP-02343":{"line":2342,"offset":405816,"length":171,"previous":"M16-GAP-02342","next":"M16-GAP-02344"},"M16-GAP-02344":{"line":2343,"offset":405987,"length":167,"previous":"M16-GAP-02343","next":"M16-GAP-02345"},"M16-GAP-02345":{"line":2344,"offset":406154,"length":168,"previous":"M16-GAP-02344","next":"M16-GAP-02346"},"M16-GAP-02346":{"line":2345,"offset":406322,"length":170,"previous":"M16-GAP-02345","next":"M16-GAP-02347"},"M16-GAP-02347":{"line":2346,"offset":406492,"length":159,"previous":"M16-GAP-02346","next":"M16-GAP-02348"},"M16-GAP-02348":{"line":2347,"offset":406651,"length":168,"previous":"M16-GAP-02347","next":"M16-GAP-02349"},"M16-GAP-02349":{"line":2348,"offset":406819,"length":169,"previous":"M16-GAP-02348","next":"M16-GAP-02350"},"M16-GAP-02350":{"line":2349,"offset":406988,"length":175,"previous":"M16-GAP-02349","next":"M16-GAP-02351"},"M16-GAP-02351":{"line":2350,"offset":407163,"length":158,"previous":"M16-GAP-02350","next":"M16-GAP-02352"},"M16-GAP-02352":{"line":2351,"offset":407321,"length":173,"previous":"M16-GAP-02351","next":"M16-GAP-02353"},"M16-GAP-02353":{"line":2352,"offset":407494,"length":166,"previous":"M16-GAP-02352","next":"M16-GAP-02354"},"M16-GAP-02354":{"line":2353,"offset":407660,"length":164,"previous":"M16-GAP-02353","next":"M16-GAP-02355"},"M16-GAP-02355":{"line":2354,"offset":407824,"length":171,"previous":"M16-GAP-02354","next":"M16-GAP-02356"},"M16-GAP-02356":{"line":2355,"offset":407995,"length":170,"previous":"M16-GAP-02355","next":"M16-GAP-02357"},"M16-GAP-02357":{"line":2356,"offset":408165,"length":167,"previous":"M16-GAP-02356","next":"M16-GAP-02358"},"M16-GAP-02358":{"line":2357,"offset":408332,"length":173,"previous":"M16-GAP-02357","next":"M16-GAP-02359"},"M16-GAP-02359":{"line":2358,"offset":408505,"length":158,"previous":"M16-GAP-02358","next":"M16-GAP-02360"},"M16-GAP-02360":{"line":2359,"offset":408663,"length":167,"previous":"M16-GAP-02359","next":"M16-GAP-02361"},"M16-GAP-02361":{"line":2360,"offset":408830,"length":163,"previous":"M16-GAP-02360","next":"M16-GAP-02362"},"M16-GAP-02362":{"line":2361,"offset":408993,"length":170,"previous":"M16-GAP-02361","next":"M16-GAP-02363"},"M16-GAP-02363":{"line":2362,"offset":409163,"length":166,"previous":"M16-GAP-02362","next":"M16-GAP-02364"},"M16-GAP-02364":{"line":2363,"offset":409329,"length":166,"previous":"M16-GAP-02363","next":"M16-GAP-02365"},"M16-GAP-02365":{"line":2364,"offset":409495,"length":159,"previous":"M16-GAP-02364","next":"M16-GAP-02366"},"M16-GAP-02366":{"line":2365,"offset":409654,"length":157,"previous":"M16-GAP-02365","next":"M16-GAP-02367"},"M16-GAP-02367":{"line":2366,"offset":409811,"length":171,"previous":"M16-GAP-02366","next":"M16-GAP-02368"},"M16-GAP-02368":{"line":2367,"offset":409982,"length":176,"previous":"M16-GAP-02367","next":"M16-GAP-02369"},"M16-GAP-02369":{"line":2368,"offset":410158,"length":168,"previous":"M16-GAP-02368","next":"M16-GAP-02370"},"M16-GAP-02370":{"line":2369,"offset":410326,"length":159,"previous":"M16-GAP-02369","next":"M16-GAP-02371"},"M16-GAP-02371":{"line":2370,"offset":410485,"length":160,"previous":"M16-GAP-02370","next":"M16-GAP-02372"},"M16-GAP-02372":{"line":2371,"offset":410645,"length":157,"previous":"M16-GAP-02371","next":"M16-GAP-02373"},"M16-GAP-02373":{"line":2372,"offset":410802,"length":162,"previous":"M16-GAP-02372","next":"M16-GAP-02374"},"M16-GAP-02374":{"line":2373,"offset":410964,"length":172,"previous":"M16-GAP-02373","next":"M16-GAP-02375"},"M16-GAP-02375":{"line":2374,"offset":411136,"length":160,"previous":"M16-GAP-02374","next":"M16-GAP-02376"},"M16-GAP-02376":{"line":2375,"offset":411296,"length":164,"previous":"M16-GAP-02375","next":"M16-GAP-02377"},"M16-GAP-02377":{"line":2376,"offset":411460,"length":164,"previous":"M16-GAP-02376","next":"M16-GAP-02378"},"M16-GAP-02378":{"line":2377,"offset":411624,"length":171,"previous":"M16-GAP-02377","next":"M16-GAP-02379"},"M16-GAP-02379":{"line":2378,"offset":411795,"length":167,"previous":"M16-GAP-02378","next":"M16-GAP-02380"},"M16-GAP-02380":{"line":2379,"offset":411962,"length":170,"previous":"M16-GAP-02379","next":"M16-GAP-02381"},"M16-GAP-02381":{"line":2380,"offset":412132,"length":166,"previous":"M16-GAP-02380","next":"M16-GAP-02382"},"M16-GAP-02382":{"line":2381,"offset":412298,"length":165,"previous":"M16-GAP-02381","next":"M16-GAP-02383"},"M16-GAP-02383":{"line":2382,"offset":412463,"length":167,"previous":"M16-GAP-02382","next":"M16-GAP-02384"},"M16-GAP-02384":{"line":2383,"offset":412630,"length":172,"previous":"M16-GAP-02383","next":"M16-GAP-02385"},"M16-GAP-02385":{"line":2384,"offset":412802,"length":165,"previous":"M16-GAP-02384","next":"M16-GAP-02386"},"M16-GAP-02386":{"line":2385,"offset":412967,"length":165,"previous":"M16-GAP-02385","next":"M16-GAP-02387"},"M16-GAP-02387":{"line":2386,"offset":413132,"length":165,"previous":"M16-GAP-02386","next":"M16-GAP-02388"},"M16-GAP-02388":{"line":2387,"offset":413297,"length":168,"previous":"M16-GAP-02387","next":"M16-GAP-02389"},"M16-GAP-02389":{"line":2388,"offset":413465,"length":167,"previous":"M16-GAP-02388","next":"M16-GAP-02390"},"M16-GAP-02390":{"line":2389,"offset":413632,"length":168,"previous":"M16-GAP-02389","next":"M16-GAP-02391"},"M16-GAP-02391":{"line":2390,"offset":413800,"length":166,"previous":"M16-GAP-02390","next":"M16-GAP-02392"},"M16-GAP-02392":{"line":2391,"offset":413966,"length":165,"previous":"M16-GAP-02391","next":"M16-GAP-02393"},"M16-GAP-02393":{"line":2392,"offset":414131,"length":172,"previous":"M16-GAP-02392","next":"M16-GAP-02394"},"M16-GAP-02394":{"line":2393,"offset":414303,"length":174,"previous":"M16-GAP-02393","next":"M16-GAP-02395"},"M16-GAP-02395":{"line":2394,"offset":414477,"length":167,"previous":"M16-GAP-02394","next":"M16-GAP-02396"},"M16-GAP-02396":{"line":2395,"offset":414644,"length":165,"previous":"M16-GAP-02395","next":"M16-GAP-02397"},"M16-GAP-02397":{"line":2396,"offset":414809,"length":167,"previous":"M16-GAP-02396","next":"M16-GAP-02398"},"M16-GAP-02398":{"line":2397,"offset":414976,"length":168,"previous":"M16-GAP-02397","next":"M16-GAP-02399"},"M16-GAP-02399":{"line":2398,"offset":415144,"length":160,"previous":"M16-GAP-02398","next":"M16-GAP-02400"},"M16-GAP-02400":{"line":2399,"offset":415304,"length":160,"previous":"M16-GAP-02399","next":"M16-GAP-02401"},"M16-GAP-02401":{"line":2400,"offset":415464,"length":158,"previous":"M16-GAP-02400","next":"M16-GAP-02402"},"M16-GAP-02402":{"line":2401,"offset":415622,"length":166,"previous":"M16-GAP-02401","next":"M16-GAP-02403"},"M16-GAP-02403":{"line":2402,"offset":415788,"length":162,"previous":"M16-GAP-02402","next":"M16-GAP-02404"},"M16-GAP-02404":{"line":2403,"offset":415950,"length":161,"previous":"M16-GAP-02403","next":"M16-GAP-02405"},"M16-GAP-02405":{"line":2404,"offset":416111,"length":163,"previous":"M16-GAP-02404","next":"M16-GAP-02406"},"M16-GAP-02406":{"line":2405,"offset":416274,"length":169,"previous":"M16-GAP-02405","next":"M16-GAP-02407"},"M16-GAP-02407":{"line":2406,"offset":416443,"length":169,"previous":"M16-GAP-02406","next":"M16-GAP-02408"},"M16-GAP-02408":{"line":2407,"offset":416612,"length":170,"previous":"M16-GAP-02407","next":"M16-GAP-02409"},"M16-GAP-02409":{"line":2408,"offset":416782,"length":167,"previous":"M16-GAP-02408","next":"M16-GAP-02410"},"M16-GAP-02410":{"line":2409,"offset":416949,"length":175,"previous":"M16-GAP-02409","next":"M16-GAP-02411"},"M16-GAP-02411":{"line":2410,"offset":417124,"length":168,"previous":"M16-GAP-02410","next":"M16-GAP-02412"},"M16-GAP-02412":{"line":2411,"offset":417292,"length":162,"previous":"M16-GAP-02411","next":"M16-GAP-02413"},"M16-GAP-02413":{"line":2412,"offset":417454,"length":169,"previous":"M16-GAP-02412","next":"M16-GAP-02414"},"M16-GAP-02414":{"line":2413,"offset":417623,"length":165,"previous":"M16-GAP-02413","next":"M16-GAP-02415"},"M16-GAP-02415":{"line":2414,"offset":417788,"length":166,"previous":"M16-GAP-02414","next":"M16-GAP-02416"},"M16-GAP-02416":{"line":2415,"offset":417954,"length":174,"previous":"M16-GAP-02415","next":"M16-GAP-02417"},"M16-GAP-02417":{"line":2416,"offset":418128,"length":185,"previous":"M16-GAP-02416","next":"M16-GAP-02418"},"M16-GAP-02418":{"line":2417,"offset":418313,"length":188,"previous":"M16-GAP-02417","next":"M16-GAP-02419"},"M16-GAP-02419":{"line":2418,"offset":418501,"length":172,"previous":"M16-GAP-02418","next":"M16-GAP-02420"},"M16-GAP-02420":{"line":2419,"offset":418673,"length":181,"previous":"M16-GAP-02419","next":"M16-GAP-02421"},"M16-GAP-02421":{"line":2420,"offset":418854,"length":177,"previous":"M16-GAP-02420","next":"M16-GAP-02422"},"M16-GAP-02422":{"line":2421,"offset":419031,"length":169,"previous":"M16-GAP-02421","next":"M16-GAP-02423"},"M16-GAP-02423":{"line":2422,"offset":419200,"length":168,"previous":"M16-GAP-02422","next":"M16-GAP-02424"},"M16-GAP-02424":{"line":2423,"offset":419368,"length":166,"previous":"M16-GAP-02423","next":"M16-GAP-02425"},"M16-GAP-02425":{"line":2424,"offset":419534,"length":163,"previous":"M16-GAP-02424","next":"M16-GAP-02426"},"M16-GAP-02426":{"line":2425,"offset":419697,"length":168,"previous":"M16-GAP-02425","next":"M16-GAP-02427"},"M16-GAP-02427":{"line":2426,"offset":419865,"length":191,"previous":"M16-GAP-02426","next":"M16-GAP-02428"},"M16-GAP-02428":{"line":2427,"offset":420056,"length":191,"previous":"M16-GAP-02427","next":"M16-GAP-02429"},"M16-GAP-02429":{"line":2428,"offset":420247,"length":187,"previous":"M16-GAP-02428","next":"M16-GAP-02430"},"M16-GAP-02430":{"line":2429,"offset":420434,"length":194,"previous":"M16-GAP-02429","next":"M16-GAP-02431"},"M16-GAP-02431":{"line":2430,"offset":420628,"length":161,"previous":"M16-GAP-02430","next":"M16-GAP-02432"},"M16-GAP-02432":{"line":2431,"offset":420789,"length":173,"previous":"M16-GAP-02431","next":"M16-GAP-02433"},"M16-GAP-02433":{"line":2432,"offset":420962,"length":167,"previous":"M16-GAP-02432","next":"M16-GAP-02434"},"M16-GAP-02434":{"line":2433,"offset":421129,"length":179,"previous":"M16-GAP-02433","next":"M16-GAP-02435"},"M16-GAP-02435":{"line":2434,"offset":421308,"length":162,"previous":"M16-GAP-02434","next":"M16-GAP-02436"},"M16-GAP-02436":{"line":2435,"offset":421470,"length":166,"previous":"M16-GAP-02435","next":"M16-GAP-02437"},"M16-GAP-02437":{"line":2436,"offset":421636,"length":166,"previous":"M16-GAP-02436","next":"M16-GAP-02438"},"M16-GAP-02438":{"line":2437,"offset":421802,"length":168,"previous":"M16-GAP-02437","next":"M16-GAP-02439"},"M16-GAP-02439":{"line":2438,"offset":421970,"length":173,"previous":"M16-GAP-02438","next":"M16-GAP-02440"},"M16-GAP-02440":{"line":2439,"offset":422143,"length":166,"previous":"M16-GAP-02439","next":"M16-GAP-02441"},"M16-GAP-02441":{"line":2440,"offset":422309,"length":174,"previous":"M16-GAP-02440","next":"M16-GAP-02442"},"M16-GAP-02442":{"line":2441,"offset":422483,"length":183,"previous":"M16-GAP-02441","next":"M16-GAP-02443"},"M16-GAP-02443":{"line":2442,"offset":422666,"length":169,"previous":"M16-GAP-02442","next":"M16-GAP-02444"},"M16-GAP-02444":{"line":2443,"offset":422835,"length":171,"previous":"M16-GAP-02443","next":"M16-GAP-02445"},"M16-GAP-02445":{"line":2444,"offset":423006,"length":164,"previous":"M16-GAP-02444","next":"M16-GAP-02446"},"M16-GAP-02446":{"line":2445,"offset":423170,"length":167,"previous":"M16-GAP-02445","next":"M16-GAP-02447"},"M16-GAP-02447":{"line":2446,"offset":423337,"length":170,"previous":"M16-GAP-02446","next":"M16-GAP-02448"},"M16-GAP-02448":{"line":2447,"offset":423507,"length":164,"previous":"M16-GAP-02447","next":"M16-GAP-02449"},"M16-GAP-02449":{"line":2448,"offset":423671,"length":168,"previous":"M16-GAP-02448","next":"M16-GAP-02450"},"M16-GAP-02450":{"line":2449,"offset":423839,"length":171,"previous":"M16-GAP-02449","next":"M16-GAP-02451"},"M16-GAP-02451":{"line":2450,"offset":424010,"length":170,"previous":"M16-GAP-02450","next":"M16-GAP-02452"},"M16-GAP-02452":{"line":2451,"offset":424180,"length":169,"previous":"M16-GAP-02451","next":"M16-GAP-02453"},"M16-GAP-02453":{"line":2452,"offset":424349,"length":168,"previous":"M16-GAP-02452","next":"M16-GAP-02454"},"M16-GAP-02454":{"line":2453,"offset":424517,"length":179,"previous":"M16-GAP-02453","next":"M16-GAP-02455"},"M16-GAP-02455":{"line":2454,"offset":424696,"length":179,"previous":"M16-GAP-02454","next":"M16-GAP-02456"},"M16-GAP-02456":{"line":2455,"offset":424875,"length":177,"previous":"M16-GAP-02455","next":"M16-GAP-02457"},"M16-GAP-02457":{"line":2456,"offset":425052,"length":181,"previous":"M16-GAP-02456","next":"M16-GAP-02458"},"M16-GAP-02458":{"line":2457,"offset":425233,"length":181,"previous":"M16-GAP-02457","next":"M16-GAP-02459"},"M16-GAP-02459":{"line":2458,"offset":425414,"length":181,"previous":"M16-GAP-02458","next":"M16-GAP-02460"},"M16-GAP-02460":{"line":2459,"offset":425595,"length":179,"previous":"M16-GAP-02459","next":"M16-GAP-02461"},"M16-GAP-02461":{"line":2460,"offset":425774,"length":176,"previous":"M16-GAP-02460","next":"M16-GAP-02462"},"M16-GAP-02462":{"line":2461,"offset":425950,"length":172,"previous":"M16-GAP-02461","next":"M16-GAP-02463"},"M16-GAP-02463":{"line":2462,"offset":426122,"length":169,"previous":"M16-GAP-02462","next":"M16-GAP-02464"},"M16-GAP-02464":{"line":2463,"offset":426291,"length":177,"previous":"M16-GAP-02463","next":"M16-GAP-02465"},"M16-GAP-02465":{"line":2464,"offset":426468,"length":166,"previous":"M16-GAP-02464","next":"M16-GAP-02466"},"M16-GAP-02466":{"line":2465,"offset":426634,"length":167,"previous":"M16-GAP-02465","next":"M16-GAP-02467"},"M16-GAP-02467":{"line":2466,"offset":426801,"length":169,"previous":"M16-GAP-02466","next":"M16-GAP-02468"},"M16-GAP-02468":{"line":2467,"offset":426970,"length":176,"previous":"M16-GAP-02467","next":"M16-GAP-02469"},"M16-GAP-02469":{"line":2468,"offset":427146,"length":176,"previous":"M16-GAP-02468","next":"M16-GAP-02470"},"M16-GAP-02470":{"line":2469,"offset":427322,"length":174,"previous":"M16-GAP-02469","next":"M16-GAP-02471"},"M16-GAP-02471":{"line":2470,"offset":427496,"length":174,"previous":"M16-GAP-02470","next":"M16-GAP-02472"},"M16-GAP-02472":{"line":2471,"offset":427670,"length":173,"previous":"M16-GAP-02471","next":"M16-GAP-02473"},"M16-GAP-02473":{"line":2472,"offset":427843,"length":177,"previous":"M16-GAP-02472","next":"M16-GAP-02474"},"M16-GAP-02474":{"line":2473,"offset":428020,"length":168,"previous":"M16-GAP-02473","next":"M16-GAP-02475"},"M16-GAP-02475":{"line":2474,"offset":428188,"length":166,"previous":"M16-GAP-02474","next":"M16-GAP-02476"},"M16-GAP-02476":{"line":2475,"offset":428354,"length":173,"previous":"M16-GAP-02475","next":"M16-GAP-02477"},"M16-GAP-02477":{"line":2476,"offset":428527,"length":167,"previous":"M16-GAP-02476","next":"M16-GAP-02478"},"M16-GAP-02478":{"line":2477,"offset":428694,"length":171,"previous":"M16-GAP-02477","next":"M16-GAP-02479"},"M16-GAP-02479":{"line":2478,"offset":428865,"length":162,"previous":"M16-GAP-02478","next":"M16-GAP-02480"},"M16-GAP-02480":{"line":2479,"offset":429027,"length":162,"previous":"M16-GAP-02479","next":"M16-GAP-02481"},"M16-GAP-02481":{"line":2480,"offset":429189,"length":169,"previous":"M16-GAP-02480","next":"M16-GAP-02482"},"M16-GAP-02482":{"line":2481,"offset":429358,"length":176,"previous":"M16-GAP-02481","next":"M16-GAP-02483"},"M16-GAP-02483":{"line":2482,"offset":429534,"length":160,"previous":"M16-GAP-02482","next":"M16-GAP-02484"},"M16-GAP-02484":{"line":2483,"offset":429694,"length":166,"previous":"M16-GAP-02483","next":"M16-GAP-02485"},"M16-GAP-02485":{"line":2484,"offset":429860,"length":181,"previous":"M16-GAP-02484","next":"M16-GAP-02486"},"M16-GAP-02486":{"line":2485,"offset":430041,"length":178,"previous":"M16-GAP-02485","next":"M16-GAP-02487"},"M16-GAP-02487":{"line":2486,"offset":430219,"length":163,"previous":"M16-GAP-02486","next":"M16-GAP-02488"},"M16-GAP-02488":{"line":2487,"offset":430382,"length":167,"previous":"M16-GAP-02487","next":"M16-GAP-02489"},"M16-GAP-02489":{"line":2488,"offset":430549,"length":164,"previous":"M16-GAP-02488","next":"M16-GAP-02490"},"M16-GAP-02490":{"line":2489,"offset":430713,"length":172,"previous":"M16-GAP-02489","next":"M16-GAP-02491"},"M16-GAP-02491":{"line":2490,"offset":430885,"length":175,"previous":"M16-GAP-02490","next":"M16-GAP-02492"},"M16-GAP-02492":{"line":2491,"offset":431060,"length":184,"previous":"M16-GAP-02491","next":"M16-GAP-02493"},"M16-GAP-02493":{"line":2492,"offset":431244,"length":173,"previous":"M16-GAP-02492","next":"M16-GAP-02494"},"M16-GAP-02494":{"line":2493,"offset":431417,"length":172,"previous":"M16-GAP-02493","next":"M16-GAP-02495"},"M16-GAP-02495":{"line":2494,"offset":431589,"length":171,"previous":"M16-GAP-02494","next":"M16-GAP-02496"},"M16-GAP-02496":{"line":2495,"offset":431760,"length":171,"previous":"M16-GAP-02495","next":"M16-GAP-02497"},"M16-GAP-02497":{"line":2496,"offset":431931,"length":173,"previous":"M16-GAP-02496","next":"M16-GAP-02498"},"M16-GAP-02498":{"line":2497,"offset":432104,"length":170,"previous":"M16-GAP-02497","next":"M16-GAP-02499"},"M16-GAP-02499":{"line":2498,"offset":432274,"length":173,"previous":"M16-GAP-02498","next":"M16-GAP-02500"},"M16-GAP-02500":{"line":2499,"offset":432447,"length":171,"previous":"M16-GAP-02499","next":"M16-GAP-02501"},"M16-GAP-02501":{"line":2500,"offset":432618,"length":173,"previous":"M16-GAP-02500","next":"M16-GAP-02502"},"M16-GAP-02502":{"line":2501,"offset":432791,"length":170,"previous":"M16-GAP-02501","next":"M16-GAP-02503"},"M16-GAP-02503":{"line":2502,"offset":432961,"length":171,"previous":"M16-GAP-02502","next":"M16-GAP-02504"},"M16-GAP-02504":{"line":2503,"offset":433132,"length":168,"previous":"M16-GAP-02503","next":"M16-GAP-02505"},"M16-GAP-02505":{"line":2504,"offset":433300,"length":169,"previous":"M16-GAP-02504","next":"M16-GAP-02506"},"M16-GAP-02506":{"line":2505,"offset":433469,"length":172,"previous":"M16-GAP-02505","next":"M16-GAP-02507"},"M16-GAP-02507":{"line":2506,"offset":433641,"length":171,"previous":"M16-GAP-02506","next":"M16-GAP-02508"},"M16-GAP-02508":{"line":2507,"offset":433812,"length":168,"previous":"M16-GAP-02507","next":"M16-GAP-02509"},"M16-GAP-02509":{"line":2508,"offset":433980,"length":173,"previous":"M16-GAP-02508","next":"M16-GAP-02510"},"M16-GAP-02510":{"line":2509,"offset":434153,"length":164,"previous":"M16-GAP-02509","next":"M16-GAP-02511"},"M16-GAP-02511":{"line":2510,"offset":434317,"length":162,"previous":"M16-GAP-02510","next":"M16-GAP-02512"},"M16-GAP-02512":{"line":2511,"offset":434479,"length":169,"previous":"M16-GAP-02511","next":"M16-GAP-02513"},"M16-GAP-02513":{"line":2512,"offset":434648,"length":180,"previous":"M16-GAP-02512","next":"M16-GAP-02514"},"M16-GAP-02514":{"line":2513,"offset":434828,"length":169,"previous":"M16-GAP-02513","next":"M16-GAP-02515"},"M16-GAP-02515":{"line":2514,"offset":434997,"length":170,"previous":"M16-GAP-02514","next":"M16-GAP-02516"},"M16-GAP-02516":{"line":2515,"offset":435167,"length":164,"previous":"M16-GAP-02515","next":"M16-GAP-02517"},"M16-GAP-02517":{"line":2516,"offset":435331,"length":178,"previous":"M16-GAP-02516","next":"M16-GAP-02518"},"M16-GAP-02518":{"line":2517,"offset":435509,"length":178,"previous":"M16-GAP-02517","next":"M16-GAP-02519"},"M16-GAP-02519":{"line":2518,"offset":435687,"length":172,"previous":"M16-GAP-02518","next":"M16-GAP-02520"},"M16-GAP-02520":{"line":2519,"offset":435859,"length":180,"previous":"M16-GAP-02519","next":"M16-GAP-02521"},"M16-GAP-02521":{"line":2520,"offset":436039,"length":183,"previous":"M16-GAP-02520","next":"M16-GAP-02522"},"M16-GAP-02522":{"line":2521,"offset":436222,"length":181,"previous":"M16-GAP-02521","next":"M16-GAP-02523"},"M16-GAP-02523":{"line":2522,"offset":436403,"length":174,"previous":"M16-GAP-02522","next":"M16-GAP-02524"},"M16-GAP-02524":{"line":2523,"offset":436577,"length":177,"previous":"M16-GAP-02523","next":"M16-GAP-02525"},"M16-GAP-02525":{"line":2524,"offset":436754,"length":164,"previous":"M16-GAP-02524","next":"M16-GAP-02526"},"M16-GAP-02526":{"line":2525,"offset":436918,"length":166,"previous":"M16-GAP-02525","next":"M16-GAP-02527"},"M16-GAP-02527":{"line":2526,"offset":437084,"length":158,"previous":"M16-GAP-02526","next":"M16-GAP-02528"},"M16-GAP-02528":{"line":2527,"offset":437242,"length":171,"previous":"M16-GAP-02527","next":"M16-GAP-02529"},"M16-GAP-02529":{"line":2528,"offset":437413,"length":164,"previous":"M16-GAP-02528","next":"M16-GAP-02530"},"M16-GAP-02530":{"line":2529,"offset":437577,"length":164,"previous":"M16-GAP-02529","next":"M16-GAP-02531"},"M16-GAP-02531":{"line":2530,"offset":437741,"length":167,"previous":"M16-GAP-02530","next":"M16-GAP-02532"},"M16-GAP-02532":{"line":2531,"offset":437908,"length":174,"previous":"M16-GAP-02531","next":"M16-GAP-02533"},"M16-GAP-02533":{"line":2532,"offset":438082,"length":171,"previous":"M16-GAP-02532","next":"M16-GAP-02534"},"M16-GAP-02534":{"line":2533,"offset":438253,"length":171,"previous":"M16-GAP-02533","next":"M16-GAP-02535"},"M16-GAP-02535":{"line":2534,"offset":438424,"length":173,"previous":"M16-GAP-02534","next":"M16-GAP-02536"},"M16-GAP-02536":{"line":2535,"offset":438597,"length":178,"previous":"M16-GAP-02535","next":"M16-GAP-02537"},"M16-GAP-02537":{"line":2536,"offset":438775,"length":167,"previous":"M16-GAP-02536","next":"M16-GAP-02538"},"M16-GAP-02538":{"line":2537,"offset":438942,"length":166,"previous":"M16-GAP-02537","next":"M16-GAP-02539"},"M16-GAP-02539":{"line":2538,"offset":439108,"length":163,"previous":"M16-GAP-02538","next":"M16-GAP-02540"},"M16-GAP-02540":{"line":2539,"offset":439271,"length":164,"previous":"M16-GAP-02539","next":"M16-GAP-02541"},"M16-GAP-02541":{"line":2540,"offset":439435,"length":164,"previous":"M16-GAP-02540","next":"M16-GAP-02542"},"M16-GAP-02542":{"line":2541,"offset":439599,"length":174,"previous":"M16-GAP-02541","next":"M16-GAP-02543"},"M16-GAP-02543":{"line":2542,"offset":439773,"length":177,"previous":"M16-GAP-02542","next":"M16-GAP-02544"},"M16-GAP-02544":{"line":2543,"offset":439950,"length":168,"previous":"M16-GAP-02543","next":"M16-GAP-02545"},"M16-GAP-02545":{"line":2544,"offset":440118,"length":169,"previous":"M16-GAP-02544","next":"M16-GAP-02546"},"M16-GAP-02546":{"line":2545,"offset":440287,"length":168,"previous":"M16-GAP-02545","next":"M16-GAP-02547"},"M16-GAP-02547":{"line":2546,"offset":440455,"length":179,"previous":"M16-GAP-02546","next":"M16-GAP-02548"},"M16-GAP-02548":{"line":2547,"offset":440634,"length":169,"previous":"M16-GAP-02547","next":"M16-GAP-02549"},"M16-GAP-02549":{"line":2548,"offset":440803,"length":175,"previous":"M16-GAP-02548","next":"M16-GAP-02550"},"M16-GAP-02550":{"line":2549,"offset":440978,"length":171,"previous":"M16-GAP-02549","next":"M16-GAP-02551"},"M16-GAP-02551":{"line":2550,"offset":441149,"length":166,"previous":"M16-GAP-02550","next":"M16-GAP-02552"},"M16-GAP-02552":{"line":2551,"offset":441315,"length":168,"previous":"M16-GAP-02551","next":"M16-GAP-02553"},"M16-GAP-02553":{"line":2552,"offset":441483,"length":175,"previous":"M16-GAP-02552","next":"M16-GAP-02554"},"M16-GAP-02554":{"line":2553,"offset":441658,"length":175,"previous":"M16-GAP-02553","next":"M16-GAP-02555"},"M16-GAP-02555":{"line":2554,"offset":441833,"length":166,"previous":"M16-GAP-02554","next":"M16-GAP-02556"},"M16-GAP-02556":{"line":2555,"offset":441999,"length":167,"previous":"M16-GAP-02555","next":"M16-GAP-02557"},"M16-GAP-02557":{"line":2556,"offset":442166,"length":167,"previous":"M16-GAP-02556","next":"M16-GAP-02558"},"M16-GAP-02558":{"line":2557,"offset":442333,"length":171,"previous":"M16-GAP-02557","next":"M16-GAP-02559"},"M16-GAP-02559":{"line":2558,"offset":442504,"length":174,"previous":"M16-GAP-02558","next":"M16-GAP-02560"},"M16-GAP-02560":{"line":2559,"offset":442678,"length":166,"previous":"M16-GAP-02559","next":"M16-GAP-02561"},"M16-GAP-02561":{"line":2560,"offset":442844,"length":169,"previous":"M16-GAP-02560","next":"M16-GAP-02562"},"M16-GAP-02562":{"line":2561,"offset":443013,"length":170,"previous":"M16-GAP-02561","next":"M16-GAP-02563"},"M16-GAP-02563":{"line":2562,"offset":443183,"length":168,"previous":"M16-GAP-02562","next":"M16-GAP-02564"},"M16-GAP-02564":{"line":2563,"offset":443351,"length":167,"previous":"M16-GAP-02563","next":"M16-GAP-02565"},"M16-GAP-02565":{"line":2564,"offset":443518,"length":167,"previous":"M16-GAP-02564","next":"M16-GAP-02566"},"M16-GAP-02566":{"line":2565,"offset":443685,"length":167,"previous":"M16-GAP-02565","next":"M16-GAP-02567"},"M16-GAP-02567":{"line":2566,"offset":443852,"length":165,"previous":"M16-GAP-02566","next":"M16-GAP-02568"},"M16-GAP-02568":{"line":2567,"offset":444017,"length":169,"previous":"M16-GAP-02567","next":"M16-GAP-02569"},"M16-GAP-02569":{"line":2568,"offset":444186,"length":172,"previous":"M16-GAP-02568","next":"M16-GAP-02570"},"M16-GAP-02570":{"line":2569,"offset":444358,"length":167,"previous":"M16-GAP-02569","next":"M16-GAP-02571"},"M16-GAP-02571":{"line":2570,"offset":444525,"length":177,"previous":"M16-GAP-02570","next":"M16-GAP-02572"},"M16-GAP-02572":{"line":2571,"offset":444702,"length":160,"previous":"M16-GAP-02571","next":"M16-GAP-02573"},"M16-GAP-02573":{"line":2572,"offset":444862,"length":166,"previous":"M16-GAP-02572","next":"M16-GAP-02574"},"M16-GAP-02574":{"line":2573,"offset":445028,"length":164,"previous":"M16-GAP-02573","next":"M16-GAP-02575"},"M16-GAP-02575":{"line":2574,"offset":445192,"length":164,"previous":"M16-GAP-02574","next":"M16-GAP-02576"},"M16-GAP-02576":{"line":2575,"offset":445356,"length":161,"previous":"M16-GAP-02575","next":"M16-GAP-02577"},"M16-GAP-02577":{"line":2576,"offset":445517,"length":176,"previous":"M16-GAP-02576","next":"M16-GAP-02578"},"M16-GAP-02578":{"line":2577,"offset":445693,"length":168,"previous":"M16-GAP-02577","next":"M16-GAP-02579"},"M16-GAP-02579":{"line":2578,"offset":445861,"length":171,"previous":"M16-GAP-02578","next":"M16-GAP-02580"},"M16-GAP-02580":{"line":2579,"offset":446032,"length":161,"previous":"M16-GAP-02579","next":"M16-GAP-02581"},"M16-GAP-02581":{"line":2580,"offset":446193,"length":174,"previous":"M16-GAP-02580","next":"M16-GAP-02582"},"M16-GAP-02582":{"line":2581,"offset":446367,"length":168,"previous":"M16-GAP-02581","next":"M16-GAP-02583"},"M16-GAP-02583":{"line":2582,"offset":446535,"length":162,"previous":"M16-GAP-02582","next":"M16-GAP-02584"},"M16-GAP-02584":{"line":2583,"offset":446697,"length":169,"previous":"M16-GAP-02583","next":"M16-GAP-02585"},"M16-GAP-02585":{"line":2584,"offset":446866,"length":166,"previous":"M16-GAP-02584","next":"M16-GAP-02586"},"M16-GAP-02586":{"line":2585,"offset":447032,"length":178,"previous":"M16-GAP-02585","next":"M16-GAP-02587"},"M16-GAP-02587":{"line":2586,"offset":447210,"length":164,"previous":"M16-GAP-02586","next":"M16-GAP-02588"},"M16-GAP-02588":{"line":2587,"offset":447374,"length":169,"previous":"M16-GAP-02587","next":"M16-GAP-02589"},"M16-GAP-02589":{"line":2588,"offset":447543,"length":164,"previous":"M16-GAP-02588","next":"M16-GAP-02590"},"M16-GAP-02590":{"line":2589,"offset":447707,"length":176,"previous":"M16-GAP-02589","next":"M16-GAP-02591"},"M16-GAP-02591":{"line":2590,"offset":447883,"length":167,"previous":"M16-GAP-02590","next":"M16-GAP-02592"},"M16-GAP-02592":{"line":2591,"offset":448050,"length":178,"previous":"M16-GAP-02591","next":"M16-GAP-02593"},"M16-GAP-02593":{"line":2592,"offset":448228,"length":170,"previous":"M16-GAP-02592","next":"M16-GAP-02594"},"M16-GAP-02594":{"line":2593,"offset":448398,"length":176,"previous":"M16-GAP-02593","next":"M16-GAP-02595"},"M16-GAP-02595":{"line":2594,"offset":448574,"length":177,"previous":"M16-GAP-02594","next":"M16-GAP-02596"},"M16-GAP-02596":{"line":2595,"offset":448751,"length":177,"previous":"M16-GAP-02595","next":"M16-GAP-02597"},"M16-GAP-02597":{"line":2596,"offset":448928,"length":179,"previous":"M16-GAP-02596","next":"M16-GAP-02598"},"M16-GAP-02598":{"line":2597,"offset":449107,"length":160,"previous":"M16-GAP-02597","next":"M16-GAP-02599"},"M16-GAP-02599":{"line":2598,"offset":449267,"length":156,"previous":"M16-GAP-02598","next":"M16-GAP-02600"},"M16-GAP-02600":{"line":2599,"offset":449423,"length":163,"previous":"M16-GAP-02599","next":"M16-GAP-02601"},"M16-GAP-02601":{"line":2600,"offset":449586,"length":167,"previous":"M16-GAP-02600","next":"M16-GAP-02602"},"M16-GAP-02602":{"line":2601,"offset":449753,"length":165,"previous":"M16-GAP-02601","next":"M16-GAP-02603"},"M16-GAP-02603":{"line":2602,"offset":449918,"length":163,"previous":"M16-GAP-02602","next":"M16-GAP-02604"},"M16-GAP-02604":{"line":2603,"offset":450081,"length":166,"previous":"M16-GAP-02603","next":"M16-GAP-02605"},"M16-GAP-02605":{"line":2604,"offset":450247,"length":163,"previous":"M16-GAP-02604","next":"M16-GAP-02606"},"M16-GAP-02606":{"line":2605,"offset":450410,"length":167,"previous":"M16-GAP-02605","next":"M16-GAP-02607"},"M16-GAP-02607":{"line":2606,"offset":450577,"length":162,"previous":"M16-GAP-02606","next":"M16-GAP-02608"},"M16-GAP-02608":{"line":2607,"offset":450739,"length":161,"previous":"M16-GAP-02607","next":"M16-GAP-02609"},"M16-GAP-02609":{"line":2608,"offset":450900,"length":171,"previous":"M16-GAP-02608","next":"M16-GAP-02610"},"M16-GAP-02610":{"line":2609,"offset":451071,"length":166,"previous":"M16-GAP-02609","next":"M16-GAP-02611"},"M16-GAP-02611":{"line":2610,"offset":451237,"length":162,"previous":"M16-GAP-02610","next":"M16-GAP-02612"},"M16-GAP-02612":{"line":2611,"offset":451399,"length":164,"previous":"M16-GAP-02611","next":"M16-GAP-02613"},"M16-GAP-02613":{"line":2612,"offset":451563,"length":165,"previous":"M16-GAP-02612","next":"M16-GAP-02614"},"M16-GAP-02614":{"line":2613,"offset":451728,"length":162,"previous":"M16-GAP-02613","next":"M16-GAP-02615"},"M16-GAP-02615":{"line":2614,"offset":451890,"length":166,"previous":"M16-GAP-02614","next":"M16-GAP-02616"},"M16-GAP-02616":{"line":2615,"offset":452056,"length":161,"previous":"M16-GAP-02615","next":"M16-GAP-02617"},"M16-GAP-02617":{"line":2616,"offset":452217,"length":165,"previous":"M16-GAP-02616","next":"M16-GAP-02618"},"M16-GAP-02618":{"line":2617,"offset":452382,"length":162,"previous":"M16-GAP-02617","next":"M16-GAP-02619"},"M16-GAP-02619":{"line":2618,"offset":452544,"length":165,"previous":"M16-GAP-02618","next":"M16-GAP-02620"},"M16-GAP-02620":{"line":2619,"offset":452709,"length":166,"previous":"M16-GAP-02619","next":"M16-GAP-02621"},"M16-GAP-02621":{"line":2620,"offset":452875,"length":165,"previous":"M16-GAP-02620","next":"M16-GAP-02622"},"M16-GAP-02622":{"line":2621,"offset":453040,"length":163,"previous":"M16-GAP-02621","next":"M16-GAP-02623"},"M16-GAP-02623":{"line":2622,"offset":453203,"length":167,"previous":"M16-GAP-02622","next":"M16-GAP-02624"},"M16-GAP-02624":{"line":2623,"offset":453370,"length":164,"previous":"M16-GAP-02623","next":"M16-GAP-02625"},"M16-GAP-02625":{"line":2624,"offset":453534,"length":165,"previous":"M16-GAP-02624","next":"M16-GAP-02626"},"M16-GAP-02626":{"line":2625,"offset":453699,"length":167,"previous":"M16-GAP-02625","next":"M16-GAP-02627"},"M16-GAP-02627":{"line":2626,"offset":453866,"length":162,"previous":"M16-GAP-02626","next":"M16-GAP-02628"},"M16-GAP-02628":{"line":2627,"offset":454028,"length":162,"previous":"M16-GAP-02627","next":"M16-GAP-02629"},"M16-GAP-02629":{"line":2628,"offset":454190,"length":163,"previous":"M16-GAP-02628","next":"M16-GAP-02630"},"M16-GAP-02630":{"line":2629,"offset":454353,"length":162,"previous":"M16-GAP-02629","next":"M16-GAP-02631"},"M16-GAP-02631":{"line":2630,"offset":454515,"length":164,"previous":"M16-GAP-02630","next":"M16-GAP-02632"},"M16-GAP-02632":{"line":2631,"offset":454679,"length":161,"previous":"M16-GAP-02631","next":"M16-GAP-02633"},"M16-GAP-02633":{"line":2632,"offset":454840,"length":164,"previous":"M16-GAP-02632","next":"M16-GAP-02634"},"M16-GAP-02634":{"line":2633,"offset":455004,"length":163,"previous":"M16-GAP-02633","next":"M16-GAP-02635"},"M16-GAP-02635":{"line":2634,"offset":455167,"length":170,"previous":"M16-GAP-02634","next":"M16-GAP-02636"},"M16-GAP-02636":{"line":2635,"offset":455337,"length":166,"previous":"M16-GAP-02635","next":"M16-GAP-02637"},"M16-GAP-02637":{"line":2636,"offset":455503,"length":162,"previous":"M16-GAP-02636","next":"M16-GAP-02638"},"M16-GAP-02638":{"line":2637,"offset":455665,"length":156,"previous":"M16-GAP-02637","next":"M16-GAP-02639"},"M16-GAP-02639":{"line":2638,"offset":455821,"length":165,"previous":"M16-GAP-02638","next":"M16-GAP-02640"},"M16-GAP-02640":{"line":2639,"offset":455986,"length":160,"previous":"M16-GAP-02639","next":"M16-GAP-02641"},"M16-GAP-02641":{"line":2640,"offset":456146,"length":165,"previous":"M16-GAP-02640","next":"M16-GAP-02642"},"M16-GAP-02642":{"line":2641,"offset":456311,"length":161,"previous":"M16-GAP-02641","next":"M16-GAP-02643"},"M16-GAP-02643":{"line":2642,"offset":456472,"length":159,"previous":"M16-GAP-02642","next":"M16-GAP-02644"},"M16-GAP-02644":{"line":2643,"offset":456631,"length":151,"previous":"M16-GAP-02643","next":"M16-GAP-02645"},"M16-GAP-02645":{"line":2644,"offset":456782,"length":170,"previous":"M16-GAP-02644","next":"M16-GAP-02646"},"M16-GAP-02646":{"line":2645,"offset":456952,"length":164,"previous":"M16-GAP-02645","next":"M16-GAP-02647"},"M16-GAP-02647":{"line":2646,"offset":457116,"length":165,"previous":"M16-GAP-02646","next":"M16-GAP-02648"},"M16-GAP-02648":{"line":2647,"offset":457281,"length":155,"previous":"M16-GAP-02647","next":"M16-GAP-02649"},"M16-GAP-02649":{"line":2648,"offset":457436,"length":156,"previous":"M16-GAP-02648","next":"M16-GAP-02650"},"M16-GAP-02650":{"line":2649,"offset":457592,"length":155,"previous":"M16-GAP-02649","next":"M16-GAP-02651"},"M16-GAP-02651":{"line":2650,"offset":457747,"length":160,"previous":"M16-GAP-02650","next":"M16-GAP-02652"},"M16-GAP-02652":{"line":2651,"offset":457907,"length":165,"previous":"M16-GAP-02651","next":"M16-GAP-02653"},"M16-GAP-02653":{"line":2652,"offset":458072,"length":163,"previous":"M16-GAP-02652","next":"M16-GAP-02654"},"M16-GAP-02654":{"line":2653,"offset":458235,"length":164,"previous":"M16-GAP-02653","next":"M16-GAP-02655"},"M16-GAP-02655":{"line":2654,"offset":458399,"length":156,"previous":"M16-GAP-02654","next":"M16-GAP-02656"},"M16-GAP-02656":{"line":2655,"offset":458555,"length":162,"previous":"M16-GAP-02655","next":"M16-GAP-02657"},"M16-GAP-02657":{"line":2656,"offset":458717,"length":158,"previous":"M16-GAP-02656","next":"M16-GAP-02658"},"M16-GAP-02658":{"line":2657,"offset":458875,"length":159,"previous":"M16-GAP-02657","next":"M16-GAP-02659"},"M16-GAP-02659":{"line":2658,"offset":459034,"length":172,"previous":"M16-GAP-02658","next":"M16-GAP-02660"},"M16-GAP-02660":{"line":2659,"offset":459206,"length":161,"previous":"M16-GAP-02659","next":"M16-GAP-02661"},"M16-GAP-02661":{"line":2660,"offset":459367,"length":166,"previous":"M16-GAP-02660","next":"M16-GAP-02662"},"M16-GAP-02662":{"line":2661,"offset":459533,"length":158,"previous":"M16-GAP-02661","next":"M16-GAP-02663"},"M16-GAP-02663":{"line":2662,"offset":459691,"length":167,"previous":"M16-GAP-02662","next":"M16-GAP-02664"},"M16-GAP-02664":{"line":2663,"offset":459858,"length":157,"previous":"M16-GAP-02663","next":"M16-GAP-02665"},"M16-GAP-02665":{"line":2664,"offset":460015,"length":162,"previous":"M16-GAP-02664","next":"M16-GAP-02666"},"M16-GAP-02666":{"line":2665,"offset":460177,"length":157,"previous":"M16-GAP-02665","next":"M16-GAP-02667"},"M16-GAP-02667":{"line":2666,"offset":460334,"length":159,"previous":"M16-GAP-02666","next":"M17-GAP-00001"},"M17-GAP-00001":{"line":2667,"offset":460493,"length":161,"previous":"M16-GAP-02667","next":"M17-GAP-00002"},"M17-GAP-00002":{"line":2668,"offset":460654,"length":163,"previous":"M17-GAP-00001","next":"M17-GAP-00003"},"M17-GAP-00003":{"line":2669,"offset":460817,"length":168,"previous":"M17-GAP-00002","next":"M17-GAP-00004"},"M17-GAP-00004":{"line":2670,"offset":460985,"length":163,"previous":"M17-GAP-00003","next":"M17-GAP-00005"},"M17-GAP-00005":{"line":2671,"offset":461148,"length":163,"previous":"M17-GAP-00004","next":"M17-GAP-00006"},"M17-GAP-00006":{"line":2672,"offset":461311,"length":168,"previous":"M17-GAP-00005","next":"M17-GAP-00007"},"M17-GAP-00007":{"line":2673,"offset":461479,"length":168,"previous":"M17-GAP-00006","next":"M17-GAP-00008"},"M17-GAP-00008":{"line":2674,"offset":461647,"length":165,"previous":"M17-GAP-00007","next":"M17-GAP-00009"},"M17-GAP-00009":{"line":2675,"offset":461812,"length":170,"previous":"M17-GAP-00008","next":"M17-GAP-00010"},"M17-GAP-00010":{"line":2676,"offset":461982,"length":167,"previous":"M17-GAP-00009","next":"M17-GAP-00011"},"M17-GAP-00011":{"line":2677,"offset":462149,"length":160,"previous":"M17-GAP-00010","next":"M17-GAP-00012"},"M17-GAP-00012":{"line":2678,"offset":462309,"length":166,"previous":"M17-GAP-00011","next":"M17-GAP-00013"},"M17-GAP-00013":{"line":2679,"offset":462475,"length":167,"previous":"M17-GAP-00012","next":"M17-GAP-00014"},"M17-GAP-00014":{"line":2680,"offset":462642,"length":173,"previous":"M17-GAP-00013","next":"M17-GAP-00015"},"M17-GAP-00015":{"line":2681,"offset":462815,"length":157,"previous":"M17-GAP-00014","next":"M17-GAP-00016"},"M17-GAP-00016":{"line":2682,"offset":462972,"length":169,"previous":"M17-GAP-00015","next":"M17-GAP-00017"},"M17-GAP-00017":{"line":2683,"offset":463141,"length":169,"previous":"M17-GAP-00016","next":"M17-GAP-00018"},"M17-GAP-00018":{"line":2684,"offset":463310,"length":169,"previous":"M17-GAP-00017","next":"M17-GAP-00019"},"M17-GAP-00019":{"line":2685,"offset":463479,"length":166,"previous":"M17-GAP-00018","next":"M17-GAP-00020"},"M17-GAP-00020":{"line":2686,"offset":463645,"length":167,"previous":"M17-GAP-00019","next":"M17-GAP-00021"},"M17-GAP-00021":{"line":2687,"offset":463812,"length":170,"previous":"M17-GAP-00020","next":"M17-GAP-00022"},"M17-GAP-00022":{"line":2688,"offset":463982,"length":168,"previous":"M17-GAP-00021","next":"M17-GAP-00023"},"M17-GAP-00023":{"line":2689,"offset":464150,"length":160,"previous":"M17-GAP-00022","next":"M17-GAP-00024"},"M17-GAP-00024":{"line":2690,"offset":464310,"length":165,"previous":"M17-GAP-00023","next":"M17-GAP-00025"},"M17-GAP-00025":{"line":2691,"offset":464475,"length":164,"previous":"M17-GAP-00024","next":"M17-GAP-00026"},"M17-GAP-00026":{"line":2692,"offset":464639,"length":165,"previous":"M17-GAP-00025","next":"M17-GAP-00027"},"M17-GAP-00027":{"line":2693,"offset":464804,"length":163,"previous":"M17-GAP-00026","next":"M17-GAP-00028"},"M17-GAP-00028":{"line":2694,"offset":464967,"length":164,"previous":"M17-GAP-00027","next":"M17-GAP-00029"},"M17-GAP-00029":{"line":2695,"offset":465131,"length":170,"previous":"M17-GAP-00028","next":"M18-GAP-00001"},"M18-GAP-00001":{"line":2696,"offset":465301,"length":188,"previous":"M17-GAP-00029","next":"M18-GAP-00002"},"M18-GAP-00002":{"line":2697,"offset":465489,"length":191,"previous":"M18-GAP-00001","next":"M18-GAP-00003"},"M18-GAP-00003":{"line":2698,"offset":465680,"length":192,"previous":"M18-GAP-00002","next":"M18-GAP-00004"},"M18-GAP-00004":{"line":2699,"offset":465872,"length":189,"previous":"M18-GAP-00003","next":"M18-GAP-00005"},"M18-GAP-00005":{"line":2700,"offset":466061,"length":183,"previous":"M18-GAP-00004","next":"M18-GAP-00006"},"M18-GAP-00006":{"line":2701,"offset":466244,"length":188,"previous":"M18-GAP-00005","next":"M18-GAP-00007"},"M18-GAP-00007":{"line":2702,"offset":466432,"length":189,"previous":"M18-GAP-00006","next":"M18-GAP-00008"},"M18-GAP-00008":{"line":2703,"offset":466621,"length":186,"previous":"M18-GAP-00007","next":"M18-GAP-00009"},"M18-GAP-00009":{"line":2704,"offset":466807,"length":193,"previous":"M18-GAP-00008","next":"M18-GAP-00010"},"M18-GAP-00010":{"line":2705,"offset":467000,"length":191,"previous":"M18-GAP-00009","next":"M18-GAP-00011"},"M18-GAP-00011":{"line":2706,"offset":467191,"length":190,"previous":"M18-GAP-00010","next":"M18-GAP-00012"},"M18-GAP-00012":{"line":2707,"offset":467381,"length":191,"previous":"M18-GAP-00011","next":"M18-GAP-00013"},"M18-GAP-00013":{"line":2708,"offset":467572,"length":194,"previous":"M18-GAP-00012","next":"M18-GAP-00014"},"M18-GAP-00014":{"line":2709,"offset":467766,"length":189,"previous":"M18-GAP-00013","next":"M18-GAP-00015"},"M18-GAP-00015":{"line":2710,"offset":467955,"length":189,"previous":"M18-GAP-00014","next":"M18-GAP-00016"},"M18-GAP-00016":{"line":2711,"offset":468144,"length":191,"previous":"M18-GAP-00015","next":"M18-GAP-00017"},"M18-GAP-00017":{"line":2712,"offset":468335,"length":196,"previous":"M18-GAP-00016","next":"M18-GAP-00018"},"M18-GAP-00018":{"line":2713,"offset":468531,"length":195,"previous":"M18-GAP-00017","next":"M18-GAP-00019"},"M18-GAP-00019":{"line":2714,"offset":468726,"length":187,"previous":"M18-GAP-00018","next":"M18-GAP-00020"},"M18-GAP-00020":{"line":2715,"offset":468913,"length":188,"previous":"M18-GAP-00019","next":"M18-GAP-00021"},"M18-GAP-00021":{"line":2716,"offset":469101,"length":183,"previous":"M18-GAP-00020","next":"M18-GAP-00022"},"M18-GAP-00022":{"line":2717,"offset":469284,"length":190,"previous":"M18-GAP-00021","next":"M18-GAP-00023"},"M18-GAP-00023":{"line":2718,"offset":469474,"length":192,"previous":"M18-GAP-00022","next":"M18-GAP-00024"},"M18-GAP-00024":{"line":2719,"offset":469666,"length":187,"previous":"M18-GAP-00023","next":"M18-GAP-00025"},"M18-GAP-00025":{"line":2720,"offset":469853,"length":184,"previous":"M18-GAP-00024","next":"M18-GAP-00026"},"M18-GAP-00026":{"line":2721,"offset":470037,"length":186,"previous":"M18-GAP-00025","next":"M18-GAP-00027"},"M18-GAP-00027":{"line":2722,"offset":470223,"length":186,"previous":"M18-GAP-00026","next":"M18-GAP-00028"},"M18-GAP-00028":{"line":2723,"offset":470409,"length":188,"previous":"M18-GAP-00027","next":"M18-GAP-00029"},"M18-GAP-00029":{"line":2724,"offset":470597,"length":188,"previous":"M18-GAP-00028","next":"M18-GAP-00030"},"M18-GAP-00030":{"line":2725,"offset":470785,"length":190,"previous":"M18-GAP-00029","next":"M18-GAP-00031"},"M18-GAP-00031":{"line":2726,"offset":470975,"length":187,"previous":"M18-GAP-00030","next":"M18-GAP-00032"},"M18-GAP-00032":{"line":2727,"offset":471162,"length":192,"previous":"M18-GAP-00031","next":"M18-GAP-00033"},"M18-GAP-00033":{"line":2728,"offset":471354,"length":193,"previous":"M18-GAP-00032","next":"M18-GAP-00034"},"M18-GAP-00034":{"line":2729,"offset":471547,"length":190,"previous":"M18-GAP-00033","next":"M18-GAP-00035"},"M18-GAP-00035":{"line":2730,"offset":471737,"length":187,"previous":"M18-GAP-00034","next":"M18-GAP-00036"},"M18-GAP-00036":{"line":2731,"offset":471924,"length":185,"previous":"M18-GAP-00035","next":"M18-GAP-00037"},"M18-GAP-00037":{"line":2732,"offset":472109,"length":183,"previous":"M18-GAP-00036","next":"M18-GAP-00038"},"M18-GAP-00038":{"line":2733,"offset":472292,"length":184,"previous":"M18-GAP-00037","next":"M18-GAP-00039"},"M18-GAP-00039":{"line":2734,"offset":472476,"length":184,"previous":"M18-GAP-00038","next":"M18-GAP-00040"},"M18-GAP-00040":{"line":2735,"offset":472660,"length":189,"previous":"M18-GAP-00039","next":"M18-GAP-00041"},"M18-GAP-00041":{"line":2736,"offset":472849,"length":185,"previous":"M18-GAP-00040","next":"M18-GAP-00042"},"M18-GAP-00042":{"line":2737,"offset":473034,"length":185,"previous":"M18-GAP-00041","next":"M18-GAP-00043"},"M18-GAP-00043":{"line":2738,"offset":473219,"length":184,"previous":"M18-GAP-00042","next":"M18-GAP-00044"},"M18-GAP-00044":{"line":2739,"offset":473403,"length":195,"previous":"M18-GAP-00043","next":"M18-GAP-00045"},"M18-GAP-00045":{"line":2740,"offset":473598,"length":188,"previous":"M18-GAP-00044","next":"M18-GAP-00046"},"M18-GAP-00046":{"line":2741,"offset":473786,"length":186,"previous":"M18-GAP-00045","next":"M18-GAP-00047"},"M18-GAP-00047":{"line":2742,"offset":473972,"length":185,"previous":"M18-GAP-00046","next":"M18-GAP-00048"},"M18-GAP-00048":{"line":2743,"offset":474157,"length":185,"previous":"M18-GAP-00047","next":"M18-GAP-00049"},"M18-GAP-00049":{"line":2744,"offset":474342,"length":191,"previous":"M18-GAP-00048","next":"M18-GAP-00050"},"M18-GAP-00050":{"line":2745,"offset":474533,"length":187,"previous":"M18-GAP-00049","next":"M18-GAP-00051"},"M18-GAP-00051":{"line":2746,"offset":474720,"length":187,"previous":"M18-GAP-00050","next":"M18-GAP-00052"},"M18-GAP-00052":{"line":2747,"offset":474907,"length":185,"previous":"M18-GAP-00051","next":"M18-GAP-00053"},"M18-GAP-00053":{"line":2748,"offset":475092,"length":188,"previous":"M18-GAP-00052","next":"M18-GAP-00054"},"M18-GAP-00054":{"line":2749,"offset":475280,"length":184,"previous":"M18-GAP-00053","next":"M18-GAP-00055"},"M18-GAP-00055":{"line":2750,"offset":475464,"length":183,"previous":"M18-GAP-00054","next":"M18-GAP-00056"},"M18-GAP-00056":{"line":2751,"offset":475647,"length":188,"previous":"M18-GAP-00055","next":"M18-GAP-00057"},"M18-GAP-00057":{"line":2752,"offset":475835,"length":188,"previous":"M18-GAP-00056","next":"M18-GAP-00058"},"M18-GAP-00058":{"line":2753,"offset":476023,"length":194,"previous":"M18-GAP-00057","next":"M18-GAP-00059"},"M18-GAP-00059":{"line":2754,"offset":476217,"length":185,"previous":"M18-GAP-00058","next":"M18-GAP-00060"},"M18-GAP-00060":{"line":2755,"offset":476402,"length":188,"previous":"M18-GAP-00059","next":"M18-GAP-00061"},"M18-GAP-00061":{"line":2756,"offset":476590,"length":189,"previous":"M18-GAP-00060","next":"M18-GAP-00062"},"M18-GAP-00062":{"line":2757,"offset":476779,"length":187,"previous":"M18-GAP-00061","next":"M18-GAP-00063"},"M18-GAP-00063":{"line":2758,"offset":476966,"length":195,"previous":"M18-GAP-00062","next":"M18-GAP-00064"},"M18-GAP-00064":{"line":2759,"offset":477161,"length":188,"previous":"M18-GAP-00063","next":"M18-GAP-00065"},"M18-GAP-00065":{"line":2760,"offset":477349,"length":188,"previous":"M18-GAP-00064","next":"M18-GAP-00066"},"M18-GAP-00066":{"line":2761,"offset":477537,"length":182,"previous":"M18-GAP-00065","next":"M18-GAP-00067"},"M18-GAP-00067":{"line":2762,"offset":477719,"length":186,"previous":"M18-GAP-00066","next":"M18-GAP-00068"},"M18-GAP-00068":{"line":2763,"offset":477905,"length":186,"previous":"M18-GAP-00067","next":"M18-GAP-00069"},"M18-GAP-00069":{"line":2764,"offset":478091,"length":194,"previous":"M18-GAP-00068","next":"M18-GAP-00070"},"M18-GAP-00070":{"line":2765,"offset":478285,"length":185,"previous":"M18-GAP-00069","next":"M18-GAP-00071"},"M18-GAP-00071":{"line":2766,"offset":478470,"length":184,"previous":"M18-GAP-00070","next":"M18-GAP-00072"},"M18-GAP-00072":{"line":2767,"offset":478654,"length":188,"previous":"M18-GAP-00071","next":"M18-GAP-00073"},"M18-GAP-00073":{"line":2768,"offset":478842,"length":192,"previous":"M18-GAP-00072","next":"M18-GAP-00074"},"M18-GAP-00074":{"line":2769,"offset":479034,"length":197,"previous":"M18-GAP-00073","next":"M18-GAP-00075"},"M18-GAP-00075":{"line":2770,"offset":479231,"length":187,"previous":"M18-GAP-00074","next":"M18-GAP-00076"},"M18-GAP-00076":{"line":2771,"offset":479418,"length":184,"previous":"M18-GAP-00075","next":"M18-GAP-00077"},"M18-GAP-00077":{"line":2772,"offset":479602,"length":188,"previous":"M18-GAP-00076","next":"M18-GAP-00078"},"M18-GAP-00078":{"line":2773,"offset":479790,"length":192,"previous":"M18-GAP-00077","next":"M18-GAP-00079"},"M18-GAP-00079":{"line":2774,"offset":479982,"length":185,"previous":"M18-GAP-00078","next":"M18-GAP-00080"},"M18-GAP-00080":{"line":2775,"offset":480167,"length":189,"previous":"M18-GAP-00079","next":"M18-GAP-00081"},"M18-GAP-00081":{"line":2776,"offset":480356,"length":183,"previous":"M18-GAP-00080","next":"M18-GAP-00082"},"M18-GAP-00082":{"line":2777,"offset":480539,"length":186,"previous":"M18-GAP-00081","next":"M18-GAP-00083"},"M18-GAP-00083":{"line":2778,"offset":480725,"length":187,"previous":"M18-GAP-00082","next":"M18-GAP-00084"},"M18-GAP-00084":{"line":2779,"offset":480912,"length":188,"previous":"M18-GAP-00083","next":"M18-GAP-00085"},"M18-GAP-00085":{"line":2780,"offset":481100,"length":188,"previous":"M18-GAP-00084","next":"M18-GAP-00086"},"M18-GAP-00086":{"line":2781,"offset":481288,"length":186,"previous":"M18-GAP-00085","next":"M18-GAP-00087"},"M18-GAP-00087":{"line":2782,"offset":481474,"length":185,"previous":"M18-GAP-00086","next":"M18-GAP-00088"},"M18-GAP-00088":{"line":2783,"offset":481659,"length":187,"previous":"M18-GAP-00087","next":"M18-GAP-00089"},"M18-GAP-00089":{"line":2784,"offset":481846,"length":188,"previous":"M18-GAP-00088","next":"M18-GAP-00090"},"M18-GAP-00090":{"line":2785,"offset":482034,"length":192,"previous":"M18-GAP-00089","next":"M18-GAP-00091"},"M18-GAP-00091":{"line":2786,"offset":482226,"length":191,"previous":"M18-GAP-00090","next":"M18-GAP-00092"},"M18-GAP-00092":{"line":2787,"offset":482417,"length":177,"previous":"M18-GAP-00091","next":"M18-GAP-00093"},"M18-GAP-00093":{"line":2788,"offset":482594,"length":186,"previous":"M18-GAP-00092","next":"M18-GAP-00094"},"M18-GAP-00094":{"line":2789,"offset":482780,"length":181,"previous":"M18-GAP-00093","next":"M18-GAP-00095"},"M18-GAP-00095":{"line":2790,"offset":482961,"length":181,"previous":"M18-GAP-00094","next":"M18-GAP-00096"},"M18-GAP-00096":{"line":2791,"offset":483142,"length":183,"previous":"M18-GAP-00095","next":"M18-GAP-00097"},"M18-GAP-00097":{"line":2792,"offset":483325,"length":189,"previous":"M18-GAP-00096","next":"M18-GAP-00098"},"M18-GAP-00098":{"line":2793,"offset":483514,"length":186,"previous":"M18-GAP-00097","next":"M18-GAP-00099"},"M18-GAP-00099":{"line":2794,"offset":483700,"length":191,"previous":"M18-GAP-00098","next":"M18-GAP-00100"},"M18-GAP-00100":{"line":2795,"offset":483891,"length":190,"previous":"M18-GAP-00099","next":"M18-GAP-00101"},"M18-GAP-00101":{"line":2796,"offset":484081,"length":191,"previous":"M18-GAP-00100","next":"M18-GAP-00102"},"M18-GAP-00102":{"line":2797,"offset":484272,"length":187,"previous":"M18-GAP-00101","next":"M18-GAP-00103"},"M18-GAP-00103":{"line":2798,"offset":484459,"length":183,"previous":"M18-GAP-00102","next":"M18-GAP-00104"},"M18-GAP-00104":{"line":2799,"offset":484642,"length":186,"previous":"M18-GAP-00103","next":"M18-GAP-00105"},"M18-GAP-00105":{"line":2800,"offset":484828,"length":186,"previous":"M18-GAP-00104","next":"M18-GAP-00106"},"M18-GAP-00106":{"line":2801,"offset":485014,"length":188,"previous":"M18-GAP-00105","next":"M18-GAP-00107"},"M18-GAP-00107":{"line":2802,"offset":485202,"length":189,"previous":"M18-GAP-00106","next":"M18-GAP-00108"},"M18-GAP-00108":{"line":2803,"offset":485391,"length":181,"previous":"M18-GAP-00107","next":"M18-GAP-00109"},"M18-GAP-00109":{"line":2804,"offset":485572,"length":195,"previous":"M18-GAP-00108","next":"M18-GAP-00110"},"M18-GAP-00110":{"line":2805,"offset":485767,"length":197,"previous":"M18-GAP-00109","next":"M18-GAP-00111"},"M18-GAP-00111":{"line":2806,"offset":485964,"length":184,"previous":"M18-GAP-00110","next":"M18-GAP-00112"},"M18-GAP-00112":{"line":2807,"offset":486148,"length":185,"previous":"M18-GAP-00111","next":"M18-GAP-00113"},"M18-GAP-00113":{"line":2808,"offset":486333,"length":200,"previous":"M18-GAP-00112","next":"M18-GAP-00114"},"M18-GAP-00114":{"line":2809,"offset":486533,"length":193,"previous":"M18-GAP-00113","next":"M18-GAP-00115"},"M18-GAP-00115":{"line":2810,"offset":486726,"length":191,"previous":"M18-GAP-00114","next":"M18-GAP-00116"},"M18-GAP-00116":{"line":2811,"offset":486917,"length":200,"previous":"M18-GAP-00115","next":"M18-GAP-00117"},"M18-GAP-00117":{"line":2812,"offset":487117,"length":193,"previous":"M18-GAP-00116","next":"M18-GAP-00118"},"M18-GAP-00118":{"line":2813,"offset":487310,"length":188,"previous":"M18-GAP-00117","next":"M18-GAP-00119"},"M18-GAP-00119":{"line":2814,"offset":487498,"length":184,"previous":"M18-GAP-00118","next":"M18-GAP-00120"},"M18-GAP-00120":{"line":2815,"offset":487682,"length":188,"previous":"M18-GAP-00119","next":"M18-GAP-00121"},"M18-GAP-00121":{"line":2816,"offset":487870,"length":182,"previous":"M18-GAP-00120","next":"M18-GAP-00122"},"M18-GAP-00122":{"line":2817,"offset":488052,"length":184,"previous":"M18-GAP-00121","next":"M18-GAP-00123"},"M18-GAP-00123":{"line":2818,"offset":488236,"length":186,"previous":"M18-GAP-00122","next":"M18-GAP-00124"},"M18-GAP-00124":{"line":2819,"offset":488422,"length":193,"previous":"M18-GAP-00123","next":"M18-GAP-00125"},"M18-GAP-00125":{"line":2820,"offset":488615,"length":194,"previous":"M18-GAP-00124","next":"M18-GAP-00126"},"M18-GAP-00126":{"line":2821,"offset":488809,"length":187,"previous":"M18-GAP-00125","next":"M18-GAP-00127"},"M18-GAP-00127":{"line":2822,"offset":488996,"length":195,"previous":"M18-GAP-00126","next":"M18-GAP-00128"},"M18-GAP-00128":{"line":2823,"offset":489191,"length":197,"previous":"M18-GAP-00127","next":"M18-GAP-00129"},"M18-GAP-00129":{"line":2824,"offset":489388,"length":196,"previous":"M18-GAP-00128","next":"M18-GAP-00130"},"M18-GAP-00130":{"line":2825,"offset":489584,"length":181,"previous":"M18-GAP-00129","next":"M18-GAP-00131"},"M18-GAP-00131":{"line":2826,"offset":489765,"length":190,"previous":"M18-GAP-00130","next":"M18-GAP-00132"},"M18-GAP-00132":{"line":2827,"offset":489955,"length":190,"previous":"M18-GAP-00131","next":"M18-GAP-00133"},"M18-GAP-00133":{"line":2828,"offset":490145,"length":193,"previous":"M18-GAP-00132","next":"M18-GAP-00134"},"M18-GAP-00134":{"line":2829,"offset":490338,"length":186,"previous":"M18-GAP-00133","next":"M18-GAP-00135"},"M18-GAP-00135":{"line":2830,"offset":490524,"length":186,"previous":"M18-GAP-00134","next":"M18-GAP-00136"},"M18-GAP-00136":{"line":2831,"offset":490710,"length":190,"previous":"M18-GAP-00135","next":"M18-GAP-00137"},"M18-GAP-00137":{"line":2832,"offset":490900,"length":184,"previous":"M18-GAP-00136","next":"M18-GAP-00138"},"M18-GAP-00138":{"line":2833,"offset":491084,"length":185,"previous":"M18-GAP-00137","next":"M18-GAP-00139"},"M18-GAP-00139":{"line":2834,"offset":491269,"length":185,"previous":"M18-GAP-00138","next":"M18-GAP-00140"},"M18-GAP-00140":{"line":2835,"offset":491454,"length":185,"previous":"M18-GAP-00139","next":"M18-GAP-00141"},"M18-GAP-00141":{"line":2836,"offset":491639,"length":187,"previous":"M18-GAP-00140","next":"M18-GAP-00142"},"M18-GAP-00142":{"line":2837,"offset":491826,"length":186,"previous":"M18-GAP-00141","next":"M18-GAP-00143"},"M18-GAP-00143":{"line":2838,"offset":492012,"length":184,"previous":"M18-GAP-00142","next":"M18-GAP-00144"},"M18-GAP-00144":{"line":2839,"offset":492196,"length":184,"previous":"M18-GAP-00143","next":"M18-GAP-00145"},"M18-GAP-00145":{"line":2840,"offset":492380,"length":186,"previous":"M18-GAP-00144","next":"M18-GAP-00146"},"M18-GAP-00146":{"line":2841,"offset":492566,"length":182,"previous":"M18-GAP-00145","next":"M18-GAP-00147"},"M18-GAP-00147":{"line":2842,"offset":492748,"length":184,"previous":"M18-GAP-00146","next":"M18-GAP-00148"},"M18-GAP-00148":{"line":2843,"offset":492932,"length":183,"previous":"M18-GAP-00147","next":"M18-GAP-00149"},"M18-GAP-00149":{"line":2844,"offset":493115,"length":182,"previous":"M18-GAP-00148","next":"M18-GAP-00150"},"M18-GAP-00150":{"line":2845,"offset":493297,"length":200,"previous":"M18-GAP-00149","next":"M18-GAP-00151"},"M18-GAP-00151":{"line":2846,"offset":493497,"length":201,"previous":"M18-GAP-00150","next":"M18-GAP-00152"},"M18-GAP-00152":{"line":2847,"offset":493698,"length":191,"previous":"M18-GAP-00151","next":"M18-GAP-00153"},"M18-GAP-00153":{"line":2848,"offset":493889,"length":190,"previous":"M18-GAP-00152","next":"M18-GAP-00154"},"M18-GAP-00154":{"line":2849,"offset":494079,"length":190,"previous":"M18-GAP-00153","next":"M18-GAP-00155"},"M18-GAP-00155":{"line":2850,"offset":494269,"length":193,"previous":"M18-GAP-00154","next":"M18-GAP-00156"},"M18-GAP-00156":{"line":2851,"offset":494462,"length":185,"previous":"M18-GAP-00155","next":"M18-GAP-00157"},"M18-GAP-00157":{"line":2852,"offset":494647,"length":182,"previous":"M18-GAP-00156","next":"M18-GAP-00158"},"M18-GAP-00158":{"line":2853,"offset":494829,"length":184,"previous":"M18-GAP-00157","next":"M18-GAP-00159"},"M18-GAP-00159":{"line":2854,"offset":495013,"length":187,"previous":"M18-GAP-00158","next":"M18-GAP-00160"},"M18-GAP-00160":{"line":2855,"offset":495200,"length":193,"previous":"M18-GAP-00159","next":"M18-GAP-00161"},"M18-GAP-00161":{"line":2856,"offset":495393,"length":183,"previous":"M18-GAP-00160","next":"M18-GAP-00162"},"M18-GAP-00162":{"line":2857,"offset":495576,"length":181,"previous":"M18-GAP-00161","next":"M18-GAP-00163"},"M18-GAP-00163":{"line":2858,"offset":495757,"length":181,"previous":"M18-GAP-00162","next":"M18-GAP-00164"},"M18-GAP-00164":{"line":2859,"offset":495938,"length":191,"previous":"M18-GAP-00163","next":"M18-GAP-00165"},"M18-GAP-00165":{"line":2860,"offset":496129,"length":187,"previous":"M18-GAP-00164","next":"M18-GAP-00166"},"M18-GAP-00166":{"line":2861,"offset":496316,"length":185,"previous":"M18-GAP-00165","next":"M18-GAP-00167"},"M18-GAP-00167":{"line":2862,"offset":496501,"length":181,"previous":"M18-GAP-00166","next":"M18-GAP-00168"},"M18-GAP-00168":{"line":2863,"offset":496682,"length":186,"previous":"M18-GAP-00167","next":"M18-GAP-00169"},"M18-GAP-00169":{"line":2864,"offset":496868,"length":181,"previous":"M18-GAP-00168","next":"M18-GAP-00170"},"M18-GAP-00170":{"line":2865,"offset":497049,"length":183,"previous":"M18-GAP-00169","next":"M18-GAP-00171"},"M18-GAP-00171":{"line":2866,"offset":497232,"length":182,"previous":"M18-GAP-00170","next":"M18-GAP-00172"},"M18-GAP-00172":{"line":2867,"offset":497414,"length":183,"previous":"M18-GAP-00171","next":"M18-GAP-00173"},"M18-GAP-00173":{"line":2868,"offset":497597,"length":185,"previous":"M18-GAP-00172","next":"M18-GAP-00174"},"M18-GAP-00174":{"line":2869,"offset":497782,"length":185,"previous":"M18-GAP-00173","next":"M18-GAP-00175"},"M18-GAP-00175":{"line":2870,"offset":497967,"length":178,"previous":"M18-GAP-00174","next":"M18-GAP-00176"},"M18-GAP-00176":{"line":2871,"offset":498145,"length":182,"previous":"M18-GAP-00175","next":"M18-GAP-00177"},"M18-GAP-00177":{"line":2872,"offset":498327,"length":185,"previous":"M18-GAP-00176","next":"M18-GAP-00178"},"M18-GAP-00178":{"line":2873,"offset":498512,"length":182,"previous":"M18-GAP-00177","next":"M18-GAP-00179"},"M18-GAP-00179":{"line":2874,"offset":498694,"length":182,"previous":"M18-GAP-00178","next":"M18-GAP-00180"},"M18-GAP-00180":{"line":2875,"offset":498876,"length":182,"previous":"M18-GAP-00179","next":"M18-GAP-00181"},"M18-GAP-00181":{"line":2876,"offset":499058,"length":182,"previous":"M18-GAP-00180","next":"M18-GAP-00182"},"M18-GAP-00182":{"line":2877,"offset":499240,"length":183,"previous":"M18-GAP-00181","next":"M18-GAP-00183"},"M18-GAP-00183":{"line":2878,"offset":499423,"length":182,"previous":"M18-GAP-00182","next":"M18-GAP-00184"},"M18-GAP-00184":{"line":2879,"offset":499605,"length":187,"previous":"M18-GAP-00183","next":"M18-GAP-00185"},"M18-GAP-00185":{"line":2880,"offset":499792,"length":184,"previous":"M18-GAP-00184","next":"M18-GAP-00186"},"M18-GAP-00186":{"line":2881,"offset":499976,"length":190,"previous":"M18-GAP-00185","next":"M18-GAP-00187"},"M18-GAP-00187":{"line":2882,"offset":500166,"length":188,"previous":"M18-GAP-00186","next":"M18-GAP-00188"},"M18-GAP-00188":{"line":2883,"offset":500354,"length":198,"previous":"M18-GAP-00187","next":"M18-GAP-00189"},"M18-GAP-00189":{"line":2884,"offset":500552,"length":187,"previous":"M18-GAP-00188","next":"M18-GAP-00190"},"M18-GAP-00190":{"line":2885,"offset":500739,"length":188,"previous":"M18-GAP-00189","next":"M18-GAP-00191"},"M18-GAP-00191":{"line":2886,"offset":500927,"length":182,"previous":"M18-GAP-00190","next":"M18-GAP-00192"},"M18-GAP-00192":{"line":2887,"offset":501109,"length":180,"previous":"M18-GAP-00191","next":"M18-GAP-00193"},"M18-GAP-00193":{"line":2888,"offset":501289,"length":183,"previous":"M18-GAP-00192","next":"M18-GAP-00194"},"M18-GAP-00194":{"line":2889,"offset":501472,"length":183,"previous":"M18-GAP-00193","next":"M18-GAP-00195"},"M18-GAP-00195":{"line":2890,"offset":501655,"length":192,"previous":"M18-GAP-00194","next":"M18-GAP-00196"},"M18-GAP-00196":{"line":2891,"offset":501847,"length":195,"previous":"M18-GAP-00195","next":"M18-GAP-00197"},"M18-GAP-00197":{"line":2892,"offset":502042,"length":194,"previous":"M18-GAP-00196","next":"M18-GAP-00198"},"M18-GAP-00198":{"line":2893,"offset":502236,"length":191,"previous":"M18-GAP-00197","next":"M18-GAP-00199"},"M18-GAP-00199":{"line":2894,"offset":502427,"length":186,"previous":"M18-GAP-00198","next":"M18-GAP-00200"},"M18-GAP-00200":{"line":2895,"offset":502613,"length":191,"previous":"M18-GAP-00199","next":"M18-GAP-00201"},"M18-GAP-00201":{"line":2896,"offset":502804,"length":191,"previous":"M18-GAP-00200","next":"M18-GAP-00202"},"M18-GAP-00202":{"line":2897,"offset":502995,"length":195,"previous":"M18-GAP-00201","next":"M18-GAP-00203"},"M18-GAP-00203":{"line":2898,"offset":503190,"length":194,"previous":"M18-GAP-00202","next":"M18-GAP-00204"},"M18-GAP-00204":{"line":2899,"offset":503384,"length":190,"previous":"M18-GAP-00203","next":"M18-GAP-00205"},"M18-GAP-00205":{"line":2900,"offset":503574,"length":194,"previous":"M18-GAP-00204","next":"M18-GAP-00206"},"M18-GAP-00206":{"line":2901,"offset":503768,"length":195,"previous":"M18-GAP-00205","next":"M18-GAP-00207"},"M18-GAP-00207":{"line":2902,"offset":503963,"length":188,"previous":"M18-GAP-00206","next":"M18-GAP-00208"},"M18-GAP-00208":{"line":2903,"offset":504151,"length":197,"previous":"M18-GAP-00207","next":"M18-GAP-00209"},"M18-GAP-00209":{"line":2904,"offset":504348,"length":192,"previous":"M18-GAP-00208","next":"M18-GAP-00210"},"M18-GAP-00210":{"line":2905,"offset":504540,"length":197,"previous":"M18-GAP-00209","next":"M18-GAP-00211"},"M18-GAP-00211":{"line":2906,"offset":504737,"length":184,"previous":"M18-GAP-00210","next":"M18-GAP-00212"},"M18-GAP-00212":{"line":2907,"offset":504921,"length":184,"previous":"M18-GAP-00211","next":"M18-GAP-00213"},"M18-GAP-00213":{"line":2908,"offset":505105,"length":186,"previous":"M18-GAP-00212","next":"M18-GAP-00214"},"M18-GAP-00214":{"line":2909,"offset":505291,"length":184,"previous":"M18-GAP-00213","next":"M18-GAP-00215"},"M18-GAP-00215":{"line":2910,"offset":505475,"length":187,"previous":"M18-GAP-00214","next":"M18-GAP-00216"},"M18-GAP-00216":{"line":2911,"offset":505662,"length":189,"previous":"M18-GAP-00215","next":"M18-GAP-00217"},"M18-GAP-00217":{"line":2912,"offset":505851,"length":195,"previous":"M18-GAP-00216","next":"M18-GAP-00218"},"M18-GAP-00218":{"line":2913,"offset":506046,"length":190,"previous":"M18-GAP-00217","next":"M18-GAP-00219"},"M18-GAP-00219":{"line":2914,"offset":506236,"length":194,"previous":"M18-GAP-00218","next":"M18-GAP-00220"},"M18-GAP-00220":{"line":2915,"offset":506430,"length":185,"previous":"M18-GAP-00219","next":"M18-GAP-00221"},"M18-GAP-00221":{"line":2916,"offset":506615,"length":188,"previous":"M18-GAP-00220","next":"M18-GAP-00222"},"M18-GAP-00222":{"line":2917,"offset":506803,"length":189,"previous":"M18-GAP-00221","next":"M18-GAP-00223"},"M18-GAP-00223":{"line":2918,"offset":506992,"length":190,"previous":"M18-GAP-00222","next":"M18-GAP-00224"},"M18-GAP-00224":{"line":2919,"offset":507182,"length":190,"previous":"M18-GAP-00223","next":"M18-GAP-00225"},"M18-GAP-00225":{"line":2920,"offset":507372,"length":190,"previous":"M18-GAP-00224","next":"M18-GAP-00226"},"M18-GAP-00226":{"line":2921,"offset":507562,"length":183,"previous":"M18-GAP-00225","next":"M18-GAP-00227"},"M18-GAP-00227":{"line":2922,"offset":507745,"length":185,"previous":"M18-GAP-00226","next":"M18-GAP-00228"},"M18-GAP-00228":{"line":2923,"offset":507930,"length":184,"previous":"M18-GAP-00227","next":"M18-GAP-00229"},"M18-GAP-00229":{"line":2924,"offset":508114,"length":183,"previous":"M18-GAP-00228","next":"M18-GAP-00230"},"M18-GAP-00230":{"line":2925,"offset":508297,"length":190,"previous":"M18-GAP-00229","next":"M18-GAP-00231"},"M18-GAP-00231":{"line":2926,"offset":508487,"length":183,"previous":"M18-GAP-00230","next":"M18-GAP-00232"},"M18-GAP-00232":{"line":2927,"offset":508670,"length":188,"previous":"M18-GAP-00231","next":"M18-GAP-00233"},"M18-GAP-00233":{"line":2928,"offset":508858,"length":184,"previous":"M18-GAP-00232","next":"M18-GAP-00234"},"M18-GAP-00234":{"line":2929,"offset":509042,"length":184,"previous":"M18-GAP-00233","next":"M18-GAP-00235"},"M18-GAP-00235":{"line":2930,"offset":509226,"length":182,"previous":"M18-GAP-00234","next":"M18-GAP-00236"},"M18-GAP-00236":{"line":2931,"offset":509408,"length":184,"previous":"M18-GAP-00235","next":"M18-GAP-00237"},"M18-GAP-00237":{"line":2932,"offset":509592,"length":183,"previous":"M18-GAP-00236","next":"M18-GAP-00238"},"M18-GAP-00238":{"line":2933,"offset":509775,"length":181,"previous":"M18-GAP-00237","next":"M18-GAP-00239"},"M18-GAP-00239":{"line":2934,"offset":509956,"length":181,"previous":"M18-GAP-00238","next":"M18-GAP-00240"},"M18-GAP-00240":{"line":2935,"offset":510137,"length":185,"previous":"M18-GAP-00239","next":"M18-GAP-00241"},"M18-GAP-00241":{"line":2936,"offset":510322,"length":194,"previous":"M18-GAP-00240","next":"M18-GAP-00242"},"M18-GAP-00242":{"line":2937,"offset":510516,"length":181,"previous":"M18-GAP-00241","next":"M18-GAP-00243"},"M18-GAP-00243":{"line":2938,"offset":510697,"length":186,"previous":"M18-GAP-00242","next":"M18-GAP-00244"},"M18-GAP-00244":{"line":2939,"offset":510883,"length":181,"previous":"M18-GAP-00243","next":"M18-GAP-00245"},"M18-GAP-00245":{"line":2940,"offset":511064,"length":184,"previous":"M18-GAP-00244","next":"M18-GAP-00246"},"M18-GAP-00246":{"line":2941,"offset":511248,"length":190,"previous":"M18-GAP-00245","next":"M18-GAP-00247"},"M18-GAP-00247":{"line":2942,"offset":511438,"length":185,"previous":"M18-GAP-00246","next":"M18-GAP-00248"},"M18-GAP-00248":{"line":2943,"offset":511623,"length":186,"previous":"M18-GAP-00247","next":"M18-GAP-00249"},"M18-GAP-00249":{"line":2944,"offset":511809,"length":185,"previous":"M18-GAP-00248","next":"M18-GAP-00250"},"M18-GAP-00250":{"line":2945,"offset":511994,"length":185,"previous":"M18-GAP-00249","next":"M18-GAP-00251"},"M18-GAP-00251":{"line":2946,"offset":512179,"length":183,"previous":"M18-GAP-00250","next":"M18-GAP-00252"},"M18-GAP-00252":{"line":2947,"offset":512362,"length":191,"previous":"M18-GAP-00251","next":"M18-GAP-00253"},"M18-GAP-00253":{"line":2948,"offset":512553,"length":191,"previous":"M18-GAP-00252","next":"M18-GAP-00254"},"M18-GAP-00254":{"line":2949,"offset":512744,"length":179,"previous":"M18-GAP-00253","next":"M18-GAP-00255"},"M18-GAP-00255":{"line":2950,"offset":512923,"length":186,"previous":"M18-GAP-00254","next":"M18-GAP-00256"},"M18-GAP-00256":{"line":2951,"offset":513109,"length":187,"previous":"M18-GAP-00255","next":"M18-GAP-00257"},"M18-GAP-00257":{"line":2952,"offset":513296,"length":188,"previous":"M18-GAP-00256","next":"M18-GAP-00258"},"M18-GAP-00258":{"line":2953,"offset":513484,"length":189,"previous":"M18-GAP-00257","next":"M18-GAP-00259"},"M18-GAP-00259":{"line":2954,"offset":513673,"length":187,"previous":"M18-GAP-00258","next":"M18-GAP-00260"},"M18-GAP-00260":{"line":2955,"offset":513860,"length":182,"previous":"M18-GAP-00259","next":"M18-GAP-00261"},"M18-GAP-00261":{"line":2956,"offset":514042,"length":180,"previous":"M18-GAP-00260","next":"M18-GAP-00262"},"M18-GAP-00262":{"line":2957,"offset":514222,"length":189,"previous":"M18-GAP-00261","next":"M18-GAP-00263"},"M18-GAP-00263":{"line":2958,"offset":514411,"length":188,"previous":"M18-GAP-00262","next":"M18-GAP-00264"},"M18-GAP-00264":{"line":2959,"offset":514599,"length":188,"previous":"M18-GAP-00263","next":"M18-GAP-00265"},"M18-GAP-00265":{"line":2960,"offset":514787,"length":184,"previous":"M18-GAP-00264","next":"M18-GAP-00266"},"M18-GAP-00266":{"line":2961,"offset":514971,"length":185,"previous":"M18-GAP-00265","next":"M18-GAP-00267"},"M18-GAP-00267":{"line":2962,"offset":515156,"length":188,"previous":"M18-GAP-00266","next":"M18-GAP-00268"},"M18-GAP-00268":{"line":2963,"offset":515344,"length":186,"previous":"M18-GAP-00267","next":"M18-GAP-00269"},"M18-GAP-00269":{"line":2964,"offset":515530,"length":185,"previous":"M18-GAP-00268","next":"M18-GAP-00270"},"M18-GAP-00270":{"line":2965,"offset":515715,"length":188,"previous":"M18-GAP-00269","next":"M18-GAP-00271"},"M18-GAP-00271":{"line":2966,"offset":515903,"length":187,"previous":"M18-GAP-00270","next":"M18-GAP-00272"},"M18-GAP-00272":{"line":2967,"offset":516090,"length":186,"previous":"M18-GAP-00271","next":"M18-GAP-00273"},"M18-GAP-00273":{"line":2968,"offset":516276,"length":189,"previous":"M18-GAP-00272","next":"M18-GAP-00274"},"M18-GAP-00274":{"line":2969,"offset":516465,"length":184,"previous":"M18-GAP-00273","next":"M18-GAP-00275"},"M18-GAP-00275":{"line":2970,"offset":516649,"length":193,"previous":"M18-GAP-00274","next":"M18-GAP-00276"},"M18-GAP-00276":{"line":2971,"offset":516842,"length":186,"previous":"M18-GAP-00275","next":"M18-GAP-00277"},"M18-GAP-00277":{"line":2972,"offset":517028,"length":186,"previous":"M18-GAP-00276","next":"M18-GAP-00278"},"M18-GAP-00278":{"line":2973,"offset":517214,"length":184,"previous":"M18-GAP-00277","next":"M18-GAP-00279"},"M18-GAP-00279":{"line":2974,"offset":517398,"length":183,"previous":"M18-GAP-00278","next":"M18-GAP-00280"},"M18-GAP-00280":{"line":2975,"offset":517581,"length":188,"previous":"M18-GAP-00279","next":"M18-GAP-00281"},"M18-GAP-00281":{"line":2976,"offset":517769,"length":184,"previous":"M18-GAP-00280","next":"M18-GAP-00282"},"M18-GAP-00282":{"line":2977,"offset":517953,"length":186,"previous":"M18-GAP-00281","next":"M18-GAP-00283"},"M18-GAP-00283":{"line":2978,"offset":518139,"length":193,"previous":"M18-GAP-00282","next":"M18-GAP-00284"},"M18-GAP-00284":{"line":2979,"offset":518332,"length":195,"previous":"M18-GAP-00283","next":"M18-GAP-00285"},"M18-GAP-00285":{"line":2980,"offset":518527,"length":188,"previous":"M18-GAP-00284","next":"M18-GAP-00286"},"M18-GAP-00286":{"line":2981,"offset":518715,"length":186,"previous":"M18-GAP-00285","next":"M18-GAP-00287"},"M18-GAP-00287":{"line":2982,"offset":518901,"length":187,"previous":"M18-GAP-00286","next":"M18-GAP-00288"},"M18-GAP-00288":{"line":2983,"offset":519088,"length":183,"previous":"M18-GAP-00287","next":"M18-GAP-00289"},"M18-GAP-00289":{"line":2984,"offset":519271,"length":191,"previous":"M18-GAP-00288","next":"M18-GAP-00290"},"M18-GAP-00290":{"line":2985,"offset":519462,"length":189,"previous":"M18-GAP-00289","next":"M18-GAP-00291"},"M18-GAP-00291":{"line":2986,"offset":519651,"length":196,"previous":"M18-GAP-00290","next":"M18-GAP-00292"},"M18-GAP-00292":{"line":2987,"offset":519847,"length":187,"previous":"M18-GAP-00291","next":"M18-GAP-00293"},"M18-GAP-00293":{"line":2988,"offset":520034,"length":187,"previous":"M18-GAP-00292","next":"M18-GAP-00294"},"M18-GAP-00294":{"line":2989,"offset":520221,"length":185,"previous":"M18-GAP-00293","next":"M18-GAP-00295"},"M18-GAP-00295":{"line":2990,"offset":520406,"length":190,"previous":"M18-GAP-00294","next":"M18-GAP-00296"},"M18-GAP-00296":{"line":2991,"offset":520596,"length":188,"previous":"M18-GAP-00295","next":"M18-GAP-00297"},"M18-GAP-00297":{"line":2992,"offset":520784,"length":193,"previous":"M18-GAP-00296","next":"M18-GAP-00298"},"M18-GAP-00298":{"line":2993,"offset":520977,"length":193,"previous":"M18-GAP-00297","next":"M18-GAP-00299"},"M18-GAP-00299":{"line":2994,"offset":521170,"length":196,"previous":"M18-GAP-00298","next":"M18-GAP-00300"},"M18-GAP-00300":{"line":2995,"offset":521366,"length":190,"previous":"M18-GAP-00299","next":"M18-GAP-00301"},"M18-GAP-00301":{"line":2996,"offset":521556,"length":189,"previous":"M18-GAP-00300","next":"M18-GAP-00302"},"M18-GAP-00302":{"line":2997,"offset":521745,"length":178,"previous":"M18-GAP-00301","next":"M18-GAP-00303"},"M18-GAP-00303":{"line":2998,"offset":521923,"length":193,"previous":"M18-GAP-00302","next":"M18-GAP-00304"},"M18-GAP-00304":{"line":2999,"offset":522116,"length":184,"previous":"M18-GAP-00303","next":"M18-GAP-00305"},"M18-GAP-00305":{"line":3000,"offset":522300,"length":189,"previous":"M18-GAP-00304","next":"M18-GAP-00306"},"M18-GAP-00306":{"line":3001,"offset":522489,"length":186,"previous":"M18-GAP-00305","next":"M18-GAP-00307"},"M18-GAP-00307":{"line":3002,"offset":522675,"length":186,"previous":"M18-GAP-00306","next":"M18-GAP-00308"},"M18-GAP-00308":{"line":3003,"offset":522861,"length":187,"previous":"M18-GAP-00307","next":"M18-GAP-00309"},"M18-GAP-00309":{"line":3004,"offset":523048,"length":187,"previous":"M18-GAP-00308","next":"M18-GAP-00310"},"M18-GAP-00310":{"line":3005,"offset":523235,"length":184,"previous":"M18-GAP-00309","next":"M18-GAP-00311"},"M18-GAP-00311":{"line":3006,"offset":523419,"length":187,"previous":"M18-GAP-00310","next":"M18-GAP-00312"},"M18-GAP-00312":{"line":3007,"offset":523606,"length":188,"previous":"M18-GAP-00311","next":"M18-GAP-00313"},"M18-GAP-00313":{"line":3008,"offset":523794,"length":192,"previous":"M18-GAP-00312","next":"M18-GAP-00314"},"M18-GAP-00314":{"line":3009,"offset":523986,"length":188,"previous":"M18-GAP-00313","next":"M18-GAP-00315"},"M18-GAP-00315":{"line":3010,"offset":524174,"length":189,"previous":"M18-GAP-00314","next":"M18-GAP-00316"},"M18-GAP-00316":{"line":3011,"offset":524363,"length":185,"previous":"M18-GAP-00315","next":"M18-GAP-00317"},"M18-GAP-00317":{"line":3012,"offset":524548,"length":181,"previous":"M18-GAP-00316","next":"M18-GAP-00318"},"M18-GAP-00318":{"line":3013,"offset":524729,"length":185,"previous":"M18-GAP-00317","next":"M18-GAP-00319"},"M18-GAP-00319":{"line":3014,"offset":524914,"length":188,"previous":"M18-GAP-00318","next":"M18-GAP-00320"},"M18-GAP-00320":{"line":3015,"offset":525102,"length":183,"previous":"M18-GAP-00319","next":"M18-GAP-00321"},"M18-GAP-00321":{"line":3016,"offset":525285,"length":189,"previous":"M18-GAP-00320","next":"M18-GAP-00322"},"M18-GAP-00322":{"line":3017,"offset":525474,"length":192,"previous":"M18-GAP-00321","next":"M18-GAP-00323"},"M18-GAP-00323":{"line":3018,"offset":525666,"length":187,"previous":"M18-GAP-00322","next":"M18-GAP-00324"},"M18-GAP-00324":{"line":3019,"offset":525853,"length":183,"previous":"M18-GAP-00323","next":"M18-GAP-00325"},"M18-GAP-00325":{"line":3020,"offset":526036,"length":187,"previous":"M18-GAP-00324","next":"M18-GAP-00326"},"M18-GAP-00326":{"line":3021,"offset":526223,"length":187,"previous":"M18-GAP-00325","next":"M18-GAP-00327"},"M18-GAP-00327":{"line":3022,"offset":526410,"length":186,"previous":"M18-GAP-00326","next":"M18-GAP-00328"},"M18-GAP-00328":{"line":3023,"offset":526596,"length":191,"previous":"M18-GAP-00327","next":"M18-GAP-00329"},"M18-GAP-00329":{"line":3024,"offset":526787,"length":179,"previous":"M18-GAP-00328","next":"M18-GAP-00330"},"M18-GAP-00330":{"line":3025,"offset":526966,"length":182,"previous":"M18-GAP-00329","next":"M18-GAP-00331"},"M18-GAP-00331":{"line":3026,"offset":527148,"length":185,"previous":"M18-GAP-00330","next":"M18-GAP-00332"},"M18-GAP-00332":{"line":3027,"offset":527333,"length":190,"previous":"M18-GAP-00331","next":"M18-GAP-00333"},"M18-GAP-00333":{"line":3028,"offset":527523,"length":184,"previous":"M18-GAP-00332","next":"M18-GAP-00334"},"M18-GAP-00334":{"line":3029,"offset":527707,"length":190,"previous":"M18-GAP-00333","next":"M18-GAP-00335"},"M18-GAP-00335":{"line":3030,"offset":527897,"length":186,"previous":"M18-GAP-00334","next":"M18-GAP-00336"},"M18-GAP-00336":{"line":3031,"offset":528083,"length":187,"previous":"M18-GAP-00335","next":"M18-GAP-00337"},"M18-GAP-00337":{"line":3032,"offset":528270,"length":189,"previous":"M18-GAP-00336","next":"M18-GAP-00338"},"M18-GAP-00338":{"line":3033,"offset":528459,"length":191,"previous":"M18-GAP-00337","next":"M18-GAP-00339"},"M18-GAP-00339":{"line":3034,"offset":528650,"length":182,"previous":"M18-GAP-00338","next":"M18-GAP-00340"},"M18-GAP-00340":{"line":3035,"offset":528832,"length":191,"previous":"M18-GAP-00339","next":"M18-GAP-00341"},"M18-GAP-00341":{"line":3036,"offset":529023,"length":184,"previous":"M18-GAP-00340","next":"M18-GAP-00342"},"M18-GAP-00342":{"line":3037,"offset":529207,"length":182,"previous":"M18-GAP-00341","next":"M18-GAP-00343"},"M18-GAP-00343":{"line":3038,"offset":529389,"length":186,"previous":"M18-GAP-00342","next":"M18-GAP-00344"},"M18-GAP-00344":{"line":3039,"offset":529575,"length":182,"previous":"M18-GAP-00343","next":"M18-GAP-00345"},"M18-GAP-00345":{"line":3040,"offset":529757,"length":181,"previous":"M18-GAP-00344","next":"M18-GAP-00346"},"M18-GAP-00346":{"line":3041,"offset":529938,"length":187,"previous":"M18-GAP-00345","next":"M18-GAP-00347"},"M18-GAP-00347":{"line":3042,"offset":530125,"length":179,"previous":"M18-GAP-00346","next":"M18-GAP-00348"},"M18-GAP-00348":{"line":3043,"offset":530304,"length":190,"previous":"M18-GAP-00347","next":"M18-GAP-00349"},"M18-GAP-00349":{"line":3044,"offset":530494,"length":183,"previous":"M18-GAP-00348","next":"M18-GAP-00350"},"M18-GAP-00350":{"line":3045,"offset":530677,"length":185,"previous":"M18-GAP-00349","next":"M18-GAP-00351"},"M18-GAP-00351":{"line":3046,"offset":530862,"length":180,"previous":"M18-GAP-00350","next":"M18-GAP-00352"},"M18-GAP-00352":{"line":3047,"offset":531042,"length":183,"previous":"M18-GAP-00351","next":"M18-GAP-00353"},"M18-GAP-00353":{"line":3048,"offset":531225,"length":176,"previous":"M18-GAP-00352","next":"M18-GAP-00354"},"M18-GAP-00354":{"line":3049,"offset":531401,"length":183,"previous":"M18-GAP-00353","next":"M18-GAP-00355"},"M18-GAP-00355":{"line":3050,"offset":531584,"length":176,"previous":"M18-GAP-00354","next":"M18-GAP-00356"},"M18-GAP-00356":{"line":3051,"offset":531760,"length":177,"previous":"M18-GAP-00355","next":"M18-GAP-00357"},"M18-GAP-00357":{"line":3052,"offset":531937,"length":172,"previous":"M18-GAP-00356","next":"M18-GAP-00358"},"M18-GAP-00358":{"line":3053,"offset":532109,"length":176,"previous":"M18-GAP-00357","next":"M18-GAP-00359"},"M18-GAP-00359":{"line":3054,"offset":532285,"length":181,"previous":"M18-GAP-00358","next":"M18-GAP-00360"},"M18-GAP-00360":{"line":3055,"offset":532466,"length":182,"previous":"M18-GAP-00359","next":"M18-GAP-00361"},"M18-GAP-00361":{"line":3056,"offset":532648,"length":178,"previous":"M18-GAP-00360","next":"M18-GAP-00362"},"M18-GAP-00362":{"line":3057,"offset":532826,"length":176,"previous":"M18-GAP-00361","next":"M18-GAP-00363"},"M18-GAP-00363":{"line":3058,"offset":533002,"length":175,"previous":"M18-GAP-00362","next":"M18-GAP-00364"},"M18-GAP-00364":{"line":3059,"offset":533177,"length":185,"previous":"M18-GAP-00363","next":"M18-GAP-00365"},"M18-GAP-00365":{"line":3060,"offset":533362,"length":179,"previous":"M18-GAP-00364","next":"M18-GAP-00366"},"M18-GAP-00366":{"line":3061,"offset":533541,"length":181,"previous":"M18-GAP-00365","next":"M18-GAP-00367"},"M18-GAP-00367":{"line":3062,"offset":533722,"length":180,"previous":"M18-GAP-00366","next":"M18-GAP-00368"},"M18-GAP-00368":{"line":3063,"offset":533902,"length":181,"previous":"M18-GAP-00367","next":"M18-GAP-00369"},"M18-GAP-00369":{"line":3064,"offset":534083,"length":176,"previous":"M18-GAP-00368","next":"M18-GAP-00370"},"M18-GAP-00370":{"line":3065,"offset":534259,"length":175,"previous":"M18-GAP-00369","next":"M18-GAP-00371"},"M18-GAP-00371":{"line":3066,"offset":534434,"length":182,"previous":"M18-GAP-00370","next":"M18-GAP-00372"},"M18-GAP-00372":{"line":3067,"offset":534616,"length":182,"previous":"M18-GAP-00371","next":"M18-GAP-00373"},"M18-GAP-00373":{"line":3068,"offset":534798,"length":171,"previous":"M18-GAP-00372","next":"M18-GAP-00374"},"M18-GAP-00374":{"line":3069,"offset":534969,"length":177,"previous":"M18-GAP-00373","next":"M18-GAP-00375"},"M18-GAP-00375":{"line":3070,"offset":535146,"length":172,"previous":"M18-GAP-00374","next":"M18-GAP-00376"},"M18-GAP-00376":{"line":3071,"offset":535318,"length":179,"previous":"M18-GAP-00375","next":"M18-GAP-00377"},"M18-GAP-00377":{"line":3072,"offset":535497,"length":177,"previous":"M18-GAP-00376","next":"M18-GAP-00378"},"M18-GAP-00378":{"line":3073,"offset":535674,"length":179,"previous":"M18-GAP-00377","next":"M18-GAP-00379"},"M18-GAP-00379":{"line":3074,"offset":535853,"length":180,"previous":"M18-GAP-00378","next":"M18-GAP-00380"},"M18-GAP-00380":{"line":3075,"offset":536033,"length":175,"previous":"M18-GAP-00379","next":"M18-GAP-00381"},"M18-GAP-00381":{"line":3076,"offset":536208,"length":177,"previous":"M18-GAP-00380","next":"M18-GAP-00382"},"M18-GAP-00382":{"line":3077,"offset":536385,"length":174,"previous":"M18-GAP-00381","next":"M18-GAP-00383"},"M18-GAP-00383":{"line":3078,"offset":536559,"length":172,"previous":"M18-GAP-00382","next":"M18-GAP-00384"},"M18-GAP-00384":{"line":3079,"offset":536731,"length":172,"previous":"M18-GAP-00383","next":"M18-GAP-00385"},"M18-GAP-00385":{"line":3080,"offset":536903,"length":175,"previous":"M18-GAP-00384","next":"M18-GAP-00386"},"M18-GAP-00386":{"line":3081,"offset":537078,"length":174,"previous":"M18-GAP-00385","next":"M18-GAP-00387"},"M18-GAP-00387":{"line":3082,"offset":537252,"length":180,"previous":"M18-GAP-00386","next":"M18-GAP-00388"},"M18-GAP-00388":{"line":3083,"offset":537432,"length":173,"previous":"M18-GAP-00387","next":"M18-GAP-00389"},"M18-GAP-00389":{"line":3084,"offset":537605,"length":178,"previous":"M18-GAP-00388","next":"M18-GAP-00390"},"M18-GAP-00390":{"line":3085,"offset":537783,"length":179,"previous":"M18-GAP-00389","next":"M18-GAP-00391"},"M18-GAP-00391":{"line":3086,"offset":537962,"length":176,"previous":"M18-GAP-00390","next":"M18-GAP-00392"},"M18-GAP-00392":{"line":3087,"offset":538138,"length":175,"previous":"M18-GAP-00391","next":"M18-GAP-00393"},"M18-GAP-00393":{"line":3088,"offset":538313,"length":174,"previous":"M18-GAP-00392","next":"M18-GAP-00394"},"M18-GAP-00394":{"line":3089,"offset":538487,"length":171,"previous":"M18-GAP-00393","next":"M18-GAP-00395"},"M18-GAP-00395":{"line":3090,"offset":538658,"length":170,"previous":"M18-GAP-00394","next":"M18-GAP-00396"},"M18-GAP-00396":{"line":3091,"offset":538828,"length":173,"previous":"M18-GAP-00395","next":"M18-GAP-00397"},"M18-GAP-00397":{"line":3092,"offset":539001,"length":176,"previous":"M18-GAP-00396","next":"M18-GAP-00398"},"M18-GAP-00398":{"line":3093,"offset":539177,"length":178,"previous":"M18-GAP-00397","next":"M18-GAP-00399"},"M18-GAP-00399":{"line":3094,"offset":539355,"length":173,"previous":"M18-GAP-00398","next":"M18-GAP-00400"},"M18-GAP-00400":{"line":3095,"offset":539528,"length":176,"previous":"M18-GAP-00399","next":"M18-GAP-00401"},"M18-GAP-00401":{"line":3096,"offset":539704,"length":177,"previous":"M18-GAP-00400","next":"M18-GAP-00402"},"M18-GAP-00402":{"line":3097,"offset":539881,"length":176,"previous":"M18-GAP-00401","next":"M18-GAP-00403"},"M18-GAP-00403":{"line":3098,"offset":540057,"length":178,"previous":"M18-GAP-00402","next":"M18-GAP-00404"},"M18-GAP-00404":{"line":3099,"offset":540235,"length":182,"previous":"M18-GAP-00403","next":"M18-GAP-00405"},"M18-GAP-00405":{"line":3100,"offset":540417,"length":181,"previous":"M18-GAP-00404","next":"M18-GAP-00406"},"M18-GAP-00406":{"line":3101,"offset":540598,"length":178,"previous":"M18-GAP-00405","next":"M18-GAP-00407"},"M18-GAP-00407":{"line":3102,"offset":540776,"length":179,"previous":"M18-GAP-00406","next":"M18-GAP-00408"},"M18-GAP-00408":{"line":3103,"offset":540955,"length":176,"previous":"M18-GAP-00407","next":"M18-GAP-00409"},"M18-GAP-00409":{"line":3104,"offset":541131,"length":170,"previous":"M18-GAP-00408","next":"M18-GAP-00410"},"M18-GAP-00410":{"line":3105,"offset":541301,"length":175,"previous":"M18-GAP-00409","next":"M18-GAP-00411"},"M18-GAP-00411":{"line":3106,"offset":541476,"length":174,"previous":"M18-GAP-00410","next":"M18-GAP-00412"},"M18-GAP-00412":{"line":3107,"offset":541650,"length":179,"previous":"M18-GAP-00411","next":"M18-GAP-00413"},"M18-GAP-00413":{"line":3108,"offset":541829,"length":174,"previous":"M18-GAP-00412","next":"M18-GAP-00414"},"M18-GAP-00414":{"line":3109,"offset":542003,"length":173,"previous":"M18-GAP-00413","next":"M18-GAP-00415"},"M18-GAP-00415":{"line":3110,"offset":542176,"length":180,"previous":"M18-GAP-00414","next":"M18-GAP-00416"},"M18-GAP-00416":{"line":3111,"offset":542356,"length":178,"previous":"M18-GAP-00415","next":"M18-GAP-00417"},"M18-GAP-00417":{"line":3112,"offset":542534,"length":178,"previous":"M18-GAP-00416","next":"M18-GAP-00418"},"M18-GAP-00418":{"line":3113,"offset":542712,"length":174,"previous":"M18-GAP-00417","next":"M18-GAP-00419"},"M18-GAP-00419":{"line":3114,"offset":542886,"length":187,"previous":"M18-GAP-00418","next":"M18-GAP-00420"},"M18-GAP-00420":{"line":3115,"offset":543073,"length":174,"previous":"M18-GAP-00419","next":"M18-GAP-00421"},"M18-GAP-00421":{"line":3116,"offset":543247,"length":175,"previous":"M18-GAP-00420","next":"M18-GAP-00422"},"M18-GAP-00422":{"line":3117,"offset":543422,"length":177,"previous":"M18-GAP-00421","next":"M18-GAP-00423"},"M18-GAP-00423":{"line":3118,"offset":543599,"length":175,"previous":"M18-GAP-00422","next":"M18-GAP-00424"},"M18-GAP-00424":{"line":3119,"offset":543774,"length":181,"previous":"M18-GAP-00423","next":"M18-GAP-00425"},"M18-GAP-00425":{"line":3120,"offset":543955,"length":175,"previous":"M18-GAP-00424","next":"M18-GAP-00426"},"M18-GAP-00426":{"line":3121,"offset":544130,"length":178,"previous":"M18-GAP-00425","next":"M18-GAP-00427"},"M18-GAP-00427":{"line":3122,"offset":544308,"length":173,"previous":"M18-GAP-00426","next":"M18-GAP-00428"},"M18-GAP-00428":{"line":3123,"offset":544481,"length":175,"previous":"M18-GAP-00427","next":"M18-GAP-00429"},"M18-GAP-00429":{"line":3124,"offset":544656,"length":175,"previous":"M18-GAP-00428","next":"M18-GAP-00430"},"M18-GAP-00430":{"line":3125,"offset":544831,"length":175,"previous":"M18-GAP-00429","next":"M18-GAP-00431"},"M18-GAP-00431":{"line":3126,"offset":545006,"length":173,"previous":"M18-GAP-00430","next":"M18-GAP-00432"},"M18-GAP-00432":{"line":3127,"offset":545179,"length":177,"previous":"M18-GAP-00431","next":"M18-GAP-00433"},"M18-GAP-00433":{"line":3128,"offset":545356,"length":174,"previous":"M18-GAP-00432","next":"M18-GAP-00434"},"M18-GAP-00434":{"line":3129,"offset":545530,"length":180,"previous":"M18-GAP-00433","next":"M18-GAP-00435"},"M18-GAP-00435":{"line":3130,"offset":545710,"length":180,"previous":"M18-GAP-00434","next":"M18-GAP-00436"},"M18-GAP-00436":{"line":3131,"offset":545890,"length":172,"previous":"M18-GAP-00435","next":"M18-GAP-00437"},"M18-GAP-00437":{"line":3132,"offset":546062,"length":175,"previous":"M18-GAP-00436","next":"M18-GAP-00438"},"M18-GAP-00438":{"line":3133,"offset":546237,"length":172,"previous":"M18-GAP-00437","next":"M18-GAP-00439"},"M18-GAP-00439":{"line":3134,"offset":546409,"length":178,"previous":"M18-GAP-00438","next":"M18-GAP-00440"},"M18-GAP-00440":{"line":3135,"offset":546587,"length":185,"previous":"M18-GAP-00439","next":"M18-GAP-00441"},"M18-GAP-00441":{"line":3136,"offset":546772,"length":177,"previous":"M18-GAP-00440","next":"M18-GAP-00442"},"M18-GAP-00442":{"line":3137,"offset":546949,"length":179,"previous":"M18-GAP-00441","next":"M18-GAP-00443"},"M18-GAP-00443":{"line":3138,"offset":547128,"length":182,"previous":"M18-GAP-00442","next":"M18-GAP-00444"},"M18-GAP-00444":{"line":3139,"offset":547310,"length":178,"previous":"M18-GAP-00443","next":"M18-GAP-00445"},"M18-GAP-00445":{"line":3140,"offset":547488,"length":183,"previous":"M18-GAP-00444","next":"M18-GAP-00446"},"M18-GAP-00446":{"line":3141,"offset":547671,"length":185,"previous":"M18-GAP-00445","next":"M18-GAP-00447"},"M18-GAP-00447":{"line":3142,"offset":547856,"length":177,"previous":"M18-GAP-00446","next":"M18-GAP-00448"},"M18-GAP-00448":{"line":3143,"offset":548033,"length":183,"previous":"M18-GAP-00447","next":"M18-GAP-00449"},"M18-GAP-00449":{"line":3144,"offset":548216,"length":180,"previous":"M18-GAP-00448","next":"M18-GAP-00450"},"M18-GAP-00450":{"line":3145,"offset":548396,"length":177,"previous":"M18-GAP-00449","next":"M18-GAP-00451"},"M18-GAP-00451":{"line":3146,"offset":548573,"length":176,"previous":"M18-GAP-00450","next":"M19-GAP-00001"},"M19-GAP-00001":{"line":3147,"offset":548749,"length":153,"previous":"M18-GAP-00451","next":"M19-GAP-00002"},"M19-GAP-00002":{"line":3148,"offset":548902,"length":155,"previous":"M19-GAP-00001","next":"M19-GAP-00003"},"M19-GAP-00003":{"line":3149,"offset":549057,"length":152,"previous":"M19-GAP-00002","next":"M19-GAP-00004"},"M19-GAP-00004":{"line":3150,"offset":549209,"length":152,"previous":"M19-GAP-00003","next":"M19-GAP-00005"},"M19-GAP-00005":{"line":3151,"offset":549361,"length":153,"previous":"M19-GAP-00004","next":"M19-GAP-00006"},"M19-GAP-00006":{"line":3152,"offset":549514,"length":159,"previous":"M19-GAP-00005","next":"M19-GAP-00007"},"M19-GAP-00007":{"line":3153,"offset":549673,"length":149,"previous":"M19-GAP-00006","next":"M19-GAP-00008"},"M19-GAP-00008":{"line":3154,"offset":549822,"length":152,"previous":"M19-GAP-00007","next":"M19-GAP-00009"},"M19-GAP-00009":{"line":3155,"offset":549974,"length":150,"previous":"M19-GAP-00008","next":"M19-GAP-00010"},"M19-GAP-00010":{"line":3156,"offset":550124,"length":154,"previous":"M19-GAP-00009","next":"M19-GAP-00011"},"M19-GAP-00011":{"line":3157,"offset":550278,"length":151,"previous":"M19-GAP-00010","next":"M19-GAP-00012"},"M19-GAP-00012":{"line":3158,"offset":550429,"length":155,"previous":"M19-GAP-00011","next":"M19-GAP-00013"},"M19-GAP-00013":{"line":3159,"offset":550584,"length":156,"previous":"M19-GAP-00012","next":"M19-GAP-00014"},"M19-GAP-00014":{"line":3160,"offset":550740,"length":154,"previous":"M19-GAP-00013","next":"M19-GAP-00015"},"M19-GAP-00015":{"line":3161,"offset":550894,"length":163,"previous":"M19-GAP-00014","next":"M19-GAP-00016"},"M19-GAP-00016":{"line":3162,"offset":551057,"length":157,"previous":"M19-GAP-00015","next":"M19-GAP-00017"},"M19-GAP-00017":{"line":3163,"offset":551214,"length":152,"previous":"M19-GAP-00016","next":"M19-GAP-00018"},"M19-GAP-00018":{"line":3164,"offset":551366,"length":154,"previous":"M19-GAP-00017","next":"M19-GAP-00019"},"M19-GAP-00019":{"line":3165,"offset":551520,"length":151,"previous":"M19-GAP-00018","next":"M19-GAP-00020"},"M19-GAP-00020":{"line":3166,"offset":551671,"length":153,"previous":"M19-GAP-00019","next":"M20-GAP-00001"},"M20-GAP-00001":{"line":3167,"offset":551824,"length":161,"previous":"M19-GAP-00020","next":"M20-GAP-00002"},"M20-GAP-00002":{"line":3168,"offset":551985,"length":167,"previous":"M20-GAP-00001","next":"M20-GAP-00003"},"M20-GAP-00003":{"line":3169,"offset":552152,"length":157,"previous":"M20-GAP-00002","next":"M20-GAP-00004"},"M20-GAP-00004":{"line":3170,"offset":552309,"length":169,"previous":"M20-GAP-00003","next":"M20-GAP-00005"},"M20-GAP-00005":{"line":3171,"offset":552478,"length":162,"previous":"M20-GAP-00004","next":"M20-GAP-00006"},"M20-GAP-00006":{"line":3172,"offset":552640,"length":171,"previous":"M20-GAP-00005","next":"M20-GAP-00007"},"M20-GAP-00007":{"line":3173,"offset":552811,"length":162,"previous":"M20-GAP-00006","next":"M20-GAP-00008"},"M20-GAP-00008":{"line":3174,"offset":552973,"length":169,"previous":"M20-GAP-00007","next":"M20-GAP-00009"},"M20-GAP-00009":{"line":3175,"offset":553142,"length":161,"previous":"M20-GAP-00008","next":"M20-GAP-00010"},"M20-GAP-00010":{"line":3176,"offset":553303,"length":161,"previous":"M20-GAP-00009","next":"M20-GAP-00011"},"M20-GAP-00011":{"line":3177,"offset":553464,"length":158,"previous":"M20-GAP-00010","next":"M20-GAP-00012"},"M20-GAP-00012":{"line":3178,"offset":553622,"length":162,"previous":"M20-GAP-00011","next":"M20-GAP-00013"},"M20-GAP-00013":{"line":3179,"offset":553784,"length":171,"previous":"M20-GAP-00012","next":"M20-GAP-00014"},"M20-GAP-00014":{"line":3180,"offset":553955,"length":162,"previous":"M20-GAP-00013","next":"M20-GAP-00015"},"M20-GAP-00015":{"line":3181,"offset":554117,"length":162,"previous":"M20-GAP-00014","next":"M20-GAP-00016"},"M20-GAP-00016":{"line":3182,"offset":554279,"length":166,"previous":"M20-GAP-00015","next":"M20-GAP-00017"},"M20-GAP-00017":{"line":3183,"offset":554445,"length":166,"previous":"M20-GAP-00016","next":"M20-GAP-00018"},"M20-GAP-00018":{"line":3184,"offset":554611,"length":166,"previous":"M20-GAP-00017","next":"M20-GAP-00019"},"M20-GAP-00019":{"line":3185,"offset":554777,"length":174,"previous":"M20-GAP-00018","next":"M20-GAP-00020"},"M20-GAP-00020":{"line":3186,"offset":554951,"length":175,"previous":"M20-GAP-00019","next":"M20-GAP-00021"},"M20-GAP-00021":{"line":3187,"offset":555126,"length":169,"previous":"M20-GAP-00020","next":"M20-GAP-00022"},"M20-GAP-00022":{"line":3188,"offset":555295,"length":168,"previous":"M20-GAP-00021","next":"M20-GAP-00023"},"M20-GAP-00023":{"line":3189,"offset":555463,"length":169,"previous":"M20-GAP-00022","next":"M20-GAP-00024"},"M20-GAP-00024":{"line":3190,"offset":555632,"length":164,"previous":"M20-GAP-00023","next":"M20-GAP-00025"},"M20-GAP-00025":{"line":3191,"offset":555796,"length":162,"previous":"M20-GAP-00024","next":"M20-GAP-00026"},"M20-GAP-00026":{"line":3192,"offset":555958,"length":168,"previous":"M20-GAP-00025","next":"M20-GAP-00027"},"M20-GAP-00027":{"line":3193,"offset":556126,"length":170,"previous":"M20-GAP-00026","next":"M20-GAP-00028"},"M20-GAP-00028":{"line":3194,"offset":556296,"length":166,"previous":"M20-GAP-00027","next":"M20-GAP-00029"},"M20-GAP-00029":{"line":3195,"offset":556462,"length":162,"previous":"M20-GAP-00028","next":"M20-GAP-00030"},"M20-GAP-00030":{"line":3196,"offset":556624,"length":176,"previous":"M20-GAP-00029","next":"M20-GAP-00031"},"M20-GAP-00031":{"line":3197,"offset":556800,"length":173,"previous":"M20-GAP-00030","next":"M20-GAP-00032"},"M20-GAP-00032":{"line":3198,"offset":556973,"length":173,"previous":"M20-GAP-00031","next":"M20-GAP-00033"},"M20-GAP-00033":{"line":3199,"offset":557146,"length":175,"previous":"M20-GAP-00032","next":"M20-GAP-00034"},"M20-GAP-00034":{"line":3200,"offset":557321,"length":174,"previous":"M20-GAP-00033","next":"M20-GAP-00035"},"M20-GAP-00035":{"line":3201,"offset":557495,"length":172,"previous":"M20-GAP-00034","next":"M20-GAP-00036"},"M20-GAP-00036":{"line":3202,"offset":557667,"length":176,"previous":"M20-GAP-00035","next":"M20-GAP-00037"},"M20-GAP-00037":{"line":3203,"offset":557843,"length":177,"previous":"M20-GAP-00036","next":"M20-GAP-00038"},"M20-GAP-00038":{"line":3204,"offset":558020,"length":172,"previous":"M20-GAP-00037","next":"M20-GAP-00039"},"M20-GAP-00039":{"line":3205,"offset":558192,"length":176,"previous":"M20-GAP-00038","next":"M20-GAP-00040"},"M20-GAP-00040":{"line":3206,"offset":558368,"length":177,"previous":"M20-GAP-00039","next":"M20-GAP-00041"},"M20-GAP-00041":{"line":3207,"offset":558545,"length":174,"previous":"M20-GAP-00040","next":"M20-GAP-00042"},"M20-GAP-00042":{"line":3208,"offset":558719,"length":157,"previous":"M20-GAP-00041","next":"M20-GAP-00043"},"M20-GAP-00043":{"line":3209,"offset":558876,"length":162,"previous":"M20-GAP-00042","next":"M20-GAP-00044"},"M20-GAP-00044":{"line":3210,"offset":559038,"length":168,"previous":"M20-GAP-00043","next":"M20-GAP-00045"},"M20-GAP-00045":{"line":3211,"offset":559206,"length":161,"previous":"M20-GAP-00044","next":"M20-GAP-00046"},"M20-GAP-00046":{"line":3212,"offset":559367,"length":164,"previous":"M20-GAP-00045","next":"M20-GAP-00047"},"M20-GAP-00047":{"line":3213,"offset":559531,"length":173,"previous":"M20-GAP-00046","next":"M20-GAP-00048"},"M20-GAP-00048":{"line":3214,"offset":559704,"length":160,"previous":"M20-GAP-00047","next":"M20-GAP-00049"},"M20-GAP-00049":{"line":3215,"offset":559864,"length":165,"previous":"M20-GAP-00048","next":"M20-GAP-00050"},"M20-GAP-00050":{"line":3216,"offset":560029,"length":176,"previous":"M20-GAP-00049","next":"M20-GAP-00051"},"M20-GAP-00051":{"line":3217,"offset":560205,"length":177,"previous":"M20-GAP-00050","next":"M20-GAP-00052"},"M20-GAP-00052":{"line":3218,"offset":560382,"length":163,"previous":"M20-GAP-00051","next":"M20-GAP-00053"},"M20-GAP-00053":{"line":3219,"offset":560545,"length":171,"previous":"M20-GAP-00052","next":"M20-GAP-00054"},"M20-GAP-00054":{"line":3220,"offset":560716,"length":164,"previous":"M20-GAP-00053","next":"M20-GAP-00055"},"M20-GAP-00055":{"line":3221,"offset":560880,"length":163,"previous":"M20-GAP-00054","next":"M20-GAP-00056"},"M20-GAP-00056":{"line":3222,"offset":561043,"length":159,"previous":"M20-GAP-00055","next":"M20-GAP-00057"},"M20-GAP-00057":{"line":3223,"offset":561202,"length":163,"previous":"M20-GAP-00056","next":"M20-GAP-00058"},"M20-GAP-00058":{"line":3224,"offset":561365,"length":160,"previous":"M20-GAP-00057","next":"M20-GAP-00059"},"M20-GAP-00059":{"line":3225,"offset":561525,"length":168,"previous":"M20-GAP-00058","next":"M20-GAP-00060"},"M20-GAP-00060":{"line":3226,"offset":561693,"length":164,"previous":"M20-GAP-00059","next":"M20-GAP-00061"},"M20-GAP-00061":{"line":3227,"offset":561857,"length":163,"previous":"M20-GAP-00060","next":"M20-GAP-00062"},"M20-GAP-00062":{"line":3228,"offset":562020,"length":165,"previous":"M20-GAP-00061","next":"M20-GAP-00063"},"M20-GAP-00063":{"line":3229,"offset":562185,"length":171,"previous":"M20-GAP-00062","next":"M20-GAP-00064"},"M20-GAP-00064":{"line":3230,"offset":562356,"length":165,"previous":"M20-GAP-00063","next":"M20-GAP-00065"},"M20-GAP-00065":{"line":3231,"offset":562521,"length":165,"previous":"M20-GAP-00064","next":"M20-GAP-00066"},"M20-GAP-00066":{"line":3232,"offset":562686,"length":152,"previous":"M20-GAP-00065","next":"M20-GAP-00067"},"M20-GAP-00067":{"line":3233,"offset":562838,"length":159,"previous":"M20-GAP-00066","next":"M20-GAP-00068"},"M20-GAP-00068":{"line":3234,"offset":562997,"length":159,"previous":"M20-GAP-00067","next":"M20-GAP-00069"},"M20-GAP-00069":{"line":3235,"offset":563156,"length":160,"previous":"M20-GAP-00068","next":"M20-GAP-00070"},"M20-GAP-00070":{"line":3236,"offset":563316,"length":154,"previous":"M20-GAP-00069","next":"M20-GAP-00071"},"M20-GAP-00071":{"line":3237,"offset":563470,"length":157,"previous":"M20-GAP-00070","next":"M20-GAP-00072"},"M20-GAP-00072":{"line":3238,"offset":563627,"length":159,"previous":"M20-GAP-00071","next":"M20-GAP-00073"},"M20-GAP-00073":{"line":3239,"offset":563786,"length":154,"previous":"M20-GAP-00072","next":"M20-GAP-00074"},"M20-GAP-00074":{"line":3240,"offset":563940,"length":160,"previous":"M20-GAP-00073","next":"M20-GAP-00075"},"M20-GAP-00075":{"line":3241,"offset":564100,"length":162,"previous":"M20-GAP-00074","next":"M20-GAP-00076"},"M20-GAP-00076":{"line":3242,"offset":564262,"length":153,"previous":"M20-GAP-00075","next":"M20-GAP-00077"},"M20-GAP-00077":{"line":3243,"offset":564415,"length":154,"previous":"M20-GAP-00076","next":"M20-GAP-00078"},"M20-GAP-00078":{"line":3244,"offset":564569,"length":153,"previous":"M20-GAP-00077","next":"M20-GAP-00079"},"M20-GAP-00079":{"line":3245,"offset":564722,"length":153,"previous":"M20-GAP-00078","next":"M20-GAP-00080"},"M20-GAP-00080":{"line":3246,"offset":564875,"length":154,"previous":"M20-GAP-00079","next":"M20-GAP-00081"},"M20-GAP-00081":{"line":3247,"offset":565029,"length":158,"previous":"M20-GAP-00080","next":"M20-GAP-00082"},"M20-GAP-00082":{"line":3248,"offset":565187,"length":157,"previous":"M20-GAP-00081","next":"M20-GAP-00083"},"M20-GAP-00083":{"line":3249,"offset":565344,"length":157,"previous":"M20-GAP-00082","next":"M20-GAP-00084"},"M20-GAP-00084":{"line":3250,"offset":565501,"length":154,"previous":"M20-GAP-00083","next":"M20-GAP-00085"},"M20-GAP-00085":{"line":3251,"offset":565655,"length":154,"previous":"M20-GAP-00084","next":"M20-GAP-00086"},"M20-GAP-00086":{"line":3252,"offset":565809,"length":154,"previous":"M20-GAP-00085","next":"M20-GAP-00087"},"M20-GAP-00087":{"line":3253,"offset":565963,"length":157,"previous":"M20-GAP-00086","next":"M20-GAP-00088"},"M20-GAP-00088":{"line":3254,"offset":566120,"length":153,"previous":"M20-GAP-00087","next":"M20-GAP-00089"},"M20-GAP-00089":{"line":3255,"offset":566273,"length":153,"previous":"M20-GAP-00088","next":"M21-GAP-00001"},"M21-GAP-00001":{"line":3256,"offset":566426,"length":156,"previous":"M20-GAP-00089","next":"M21-GAP-00002"},"M21-GAP-00002":{"line":3257,"offset":566582,"length":152,"previous":"M21-GAP-00001","next":"M21-GAP-00003"},"M21-GAP-00003":{"line":3258,"offset":566734,"length":161,"previous":"M21-GAP-00002","next":"M21-GAP-00004"},"M21-GAP-00004":{"line":3259,"offset":566895,"length":150,"previous":"M21-GAP-00003","next":"M21-GAP-00005"},"M21-GAP-00005":{"line":3260,"offset":567045,"length":157,"previous":"M21-GAP-00004","next":"M21-GAP-00006"},"M21-GAP-00006":{"line":3261,"offset":567202,"length":157,"previous":"M21-GAP-00005","next":"M21-GAP-00007"},"M21-GAP-00007":{"line":3262,"offset":567359,"length":157,"previous":"M21-GAP-00006","next":"M21-GAP-00008"},"M21-GAP-00008":{"line":3263,"offset":567516,"length":149,"previous":"M21-GAP-00007","next":"M21-GAP-00009"},"M21-GAP-00009":{"line":3264,"offset":567665,"length":155,"previous":"M21-GAP-00008","next":"M21-GAP-00010"},"M21-GAP-00010":{"line":3265,"offset":567820,"length":156,"previous":"M21-GAP-00009","next":"M21-GAP-00011"},"M21-GAP-00011":{"line":3266,"offset":567976,"length":153,"previous":"M21-GAP-00010","next":"M21-GAP-00012"},"M21-GAP-00012":{"line":3267,"offset":568129,"length":156,"previous":"M21-GAP-00011","next":"M21-GAP-00013"},"M21-GAP-00013":{"line":3268,"offset":568285,"length":155,"previous":"M21-GAP-00012","next":"M21-GAP-00014"},"M21-GAP-00014":{"line":3269,"offset":568440,"length":160,"previous":"M21-GAP-00013","next":"M21-GAP-00015"},"M21-GAP-00015":{"line":3270,"offset":568600,"length":156,"previous":"M21-GAP-00014","next":"M21-GAP-00016"},"M21-GAP-00016":{"line":3271,"offset":568756,"length":154,"previous":"M21-GAP-00015","next":"M21-GAP-00017"},"M21-GAP-00017":{"line":3272,"offset":568910,"length":156,"previous":"M21-GAP-00016","next":"M21-GAP-00018"},"M21-GAP-00018":{"line":3273,"offset":569066,"length":151,"previous":"M21-GAP-00017","next":"M21-GAP-00019"},"M21-GAP-00019":{"line":3274,"offset":569217,"length":152,"previous":"M21-GAP-00018","next":"M21-GAP-00020"},"M21-GAP-00020":{"line":3275,"offset":569369,"length":172,"previous":"M21-GAP-00019","next":"M21-GAP-00021"},"M21-GAP-00021":{"line":3276,"offset":569541,"length":171,"previous":"M21-GAP-00020","next":"M21-GAP-00022"},"M21-GAP-00022":{"line":3277,"offset":569712,"length":173,"previous":"M21-GAP-00021","next":"M21-GAP-00023"},"M21-GAP-00023":{"line":3278,"offset":569885,"length":176,"previous":"M21-GAP-00022","next":"M21-GAP-00024"},"M21-GAP-00024":{"line":3279,"offset":570061,"length":174,"previous":"M21-GAP-00023","next":"M21-GAP-00025"},"M21-GAP-00025":{"line":3280,"offset":570235,"length":176,"previous":"M21-GAP-00024","next":"M21-GAP-00026"},"M21-GAP-00026":{"line":3281,"offset":570411,"length":173,"previous":"M21-GAP-00025","next":"M21-GAP-00027"},"M21-GAP-00027":{"line":3282,"offset":570584,"length":176,"previous":"M21-GAP-00026","next":"M21-GAP-00028"},"M21-GAP-00028":{"line":3283,"offset":570760,"length":165,"previous":"M21-GAP-00027","next":"M21-GAP-00029"},"M21-GAP-00029":{"line":3284,"offset":570925,"length":166,"previous":"M21-GAP-00028","next":"M21-GAP-00030"},"M21-GAP-00030":{"line":3285,"offset":571091,"length":167,"previous":"M21-GAP-00029","next":"M21-GAP-00031"},"M21-GAP-00031":{"line":3286,"offset":571258,"length":177,"previous":"M21-GAP-00030","next":"M21-GAP-00032"},"M21-GAP-00032":{"line":3287,"offset":571435,"length":165,"previous":"M21-GAP-00031","next":"M21-GAP-00033"},"M21-GAP-00033":{"line":3288,"offset":571600,"length":166,"previous":"M21-GAP-00032","next":"M21-GAP-00034"},"M21-GAP-00034":{"line":3289,"offset":571766,"length":166,"previous":"M21-GAP-00033","next":"M21-GAP-00035"},"M21-GAP-00035":{"line":3290,"offset":571932,"length":167,"previous":"M21-GAP-00034","next":"M21-GAP-00036"},"M21-GAP-00036":{"line":3291,"offset":572099,"length":170,"previous":"M21-GAP-00035","next":"M21-GAP-00037"},"M21-GAP-00037":{"line":3292,"offset":572269,"length":170,"previous":"M21-GAP-00036","next":"M21-GAP-00038"},"M21-GAP-00038":{"line":3293,"offset":572439,"length":178,"previous":"M21-GAP-00037","next":"M21-GAP-00039"},"M21-GAP-00039":{"line":3294,"offset":572617,"length":178,"previous":"M21-GAP-00038","next":"M21-GAP-00040"},"M21-GAP-00040":{"line":3295,"offset":572795,"length":176,"previous":"M21-GAP-00039","next":"M21-GAP-00041"},"M21-GAP-00041":{"line":3296,"offset":572971,"length":166,"previous":"M21-GAP-00040","next":"M21-GAP-00042"},"M21-GAP-00042":{"line":3297,"offset":573137,"length":174,"previous":"M21-GAP-00041","next":"M21-GAP-00043"},"M21-GAP-00043":{"line":3298,"offset":573311,"length":169,"previous":"M21-GAP-00042","next":"M21-GAP-00044"},"M21-GAP-00044":{"line":3299,"offset":573480,"length":163,"previous":"M21-GAP-00043","next":"M21-GAP-00045"},"M21-GAP-00045":{"line":3300,"offset":573643,"length":177,"previous":"M21-GAP-00044","next":"M21-GAP-00046"},"M21-GAP-00046":{"line":3301,"offset":573820,"length":177,"previous":"M21-GAP-00045","next":"M21-GAP-00047"},"M21-GAP-00047":{"line":3302,"offset":573997,"length":163,"previous":"M21-GAP-00046","next":"M21-GAP-00048"},"M21-GAP-00048":{"line":3303,"offset":574160,"length":163,"previous":"M21-GAP-00047","next":"M21-GAP-00049"},"M21-GAP-00049":{"line":3304,"offset":574323,"length":163,"previous":"M21-GAP-00048","next":"M21-GAP-00050"},"M21-GAP-00050":{"line":3305,"offset":574486,"length":163,"previous":"M21-GAP-00049","next":"M21-GAP-00051"},"M21-GAP-00051":{"line":3306,"offset":574649,"length":163,"previous":"M21-GAP-00050","next":"M21-GAP-00052"},"M21-GAP-00052":{"line":3307,"offset":574812,"length":163,"previous":"M21-GAP-00051","next":"M21-GAP-00053"},"M21-GAP-00053":{"line":3308,"offset":574975,"length":184,"previous":"M21-GAP-00052","next":"M21-GAP-00054"},"M21-GAP-00054":{"line":3309,"offset":575159,"length":184,"previous":"M21-GAP-00053","next":"M21-GAP-00055"},"M21-GAP-00055":{"line":3310,"offset":575343,"length":187,"previous":"M21-GAP-00054","next":"M21-GAP-00056"},"M21-GAP-00056":{"line":3311,"offset":575530,"length":194,"previous":"M21-GAP-00055","next":"M21-GAP-00057"},"M21-GAP-00057":{"line":3312,"offset":575724,"length":189,"previous":"M21-GAP-00056","next":"M21-GAP-00058"},"M21-GAP-00058":{"line":3313,"offset":575913,"length":189,"previous":"M21-GAP-00057","next":"M21-GAP-00059"},"M21-GAP-00059":{"line":3314,"offset":576102,"length":209,"previous":"M21-GAP-00058","next":"M21-GAP-00060"},"M21-GAP-00060":{"line":3315,"offset":576311,"length":211,"previous":"M21-GAP-00059","next":"M21-GAP-00061"},"M21-GAP-00061":{"line":3316,"offset":576522,"length":215,"previous":"M21-GAP-00060","next":"M21-GAP-00062"},"M21-GAP-00062":{"line":3317,"offset":576737,"length":205,"previous":"M21-GAP-00061","next":"M21-GAP-00063"},"M21-GAP-00063":{"line":3318,"offset":576942,"length":202,"previous":"M21-GAP-00062","next":"M21-GAP-00064"},"M21-GAP-00064":{"line":3319,"offset":577144,"length":204,"previous":"M21-GAP-00063","next":"M21-GAP-00065"},"M21-GAP-00065":{"line":3320,"offset":577348,"length":204,"previous":"M21-GAP-00064","next":"M21-GAP-00066"},"M21-GAP-00066":{"line":3321,"offset":577552,"length":204,"previous":"M21-GAP-00065","next":"M21-GAP-00067"},"M21-GAP-00067":{"line":3322,"offset":577756,"length":199,"previous":"M21-GAP-00066","next":"M21-GAP-00068"},"M21-GAP-00068":{"line":3323,"offset":577955,"length":212,"previous":"M21-GAP-00067","next":"M21-GAP-00069"},"M21-GAP-00069":{"line":3324,"offset":578167,"length":202,"previous":"M21-GAP-00068","next":"M21-GAP-00070"},"M21-GAP-00070":{"line":3325,"offset":578369,"length":201,"previous":"M21-GAP-00069","next":"M21-GAP-00071"},"M21-GAP-00071":{"line":3326,"offset":578570,"length":204,"previous":"M21-GAP-00070","next":"M21-GAP-00072"},"M21-GAP-00072":{"line":3327,"offset":578774,"length":199,"previous":"M21-GAP-00071","next":"M21-GAP-00073"},"M21-GAP-00073":{"line":3328,"offset":578973,"length":200,"previous":"M21-GAP-00072","next":"M21-GAP-00074"},"M21-GAP-00074":{"line":3329,"offset":579173,"length":199,"previous":"M21-GAP-00073","next":"M21-GAP-00075"},"M21-GAP-00075":{"line":3330,"offset":579372,"length":199,"previous":"M21-GAP-00074","next":"M21-GAP-00076"},"M21-GAP-00076":{"line":3331,"offset":579571,"length":199,"previous":"M21-GAP-00075","next":"M21-GAP-00077"},"M21-GAP-00077":{"line":3332,"offset":579770,"length":199,"previous":"M21-GAP-00076","next":"M21-GAP-00078"},"M21-GAP-00078":{"line":3333,"offset":579969,"length":211,"previous":"M21-GAP-00077","next":"M21-GAP-00079"},"M21-GAP-00079":{"line":3334,"offset":580180,"length":214,"previous":"M21-GAP-00078","next":"M21-GAP-00080"},"M21-GAP-00080":{"line":3335,"offset":580394,"length":206,"previous":"M21-GAP-00079","next":"M21-GAP-00081"},"M21-GAP-00081":{"line":3336,"offset":580600,"length":206,"previous":"M21-GAP-00080","next":"M21-GAP-00082"},"M21-GAP-00082":{"line":3337,"offset":580806,"length":206,"previous":"M21-GAP-00081","next":"M21-GAP-00083"},"M21-GAP-00083":{"line":3338,"offset":581012,"length":206,"previous":"M21-GAP-00082","next":"M21-GAP-00084"},"M21-GAP-00084":{"line":3339,"offset":581218,"length":199,"previous":"M21-GAP-00083","next":"M21-GAP-00085"},"M21-GAP-00085":{"line":3340,"offset":581417,"length":200,"previous":"M21-GAP-00084","next":"M21-GAP-00086"},"M21-GAP-00086":{"line":3341,"offset":581617,"length":204,"previous":"M21-GAP-00085","next":"M21-GAP-00087"},"M21-GAP-00087":{"line":3342,"offset":581821,"length":215,"previous":"M21-GAP-00086","next":"M21-GAP-00088"},"M21-GAP-00088":{"line":3343,"offset":582036,"length":212,"previous":"M21-GAP-00087","next":"M21-GAP-00089"},"M21-GAP-00089":{"line":3344,"offset":582248,"length":210,"previous":"M21-GAP-00088","next":"M21-GAP-00090"},"M21-GAP-00090":{"line":3345,"offset":582458,"length":208,"previous":"M21-GAP-00089","next":"M21-GAP-00091"},"M21-GAP-00091":{"line":3346,"offset":582666,"length":211,"previous":"M21-GAP-00090","next":"M21-GAP-00092"},"M21-GAP-00092":{"line":3347,"offset":582877,"length":205,"previous":"M21-GAP-00091","next":"M21-GAP-00093"},"M21-GAP-00093":{"line":3348,"offset":583082,"length":199,"previous":"M21-GAP-00092","next":"M21-GAP-00094"},"M21-GAP-00094":{"line":3349,"offset":583281,"length":202,"previous":"M21-GAP-00093","next":"M21-GAP-00095"},"M21-GAP-00095":{"line":3350,"offset":583483,"length":214,"previous":"M21-GAP-00094","next":"M21-GAP-00096"},"M21-GAP-00096":{"line":3351,"offset":583697,"length":204,"previous":"M21-GAP-00095","next":"M21-GAP-00097"},"M21-GAP-00097":{"line":3352,"offset":583901,"length":204,"previous":"M21-GAP-00096","next":"M21-GAP-00098"},"M21-GAP-00098":{"line":3353,"offset":584105,"length":204,"previous":"M21-GAP-00097","next":"M21-GAP-00099"},"M21-GAP-00099":{"line":3354,"offset":584309,"length":203,"previous":"M21-GAP-00098","next":"M21-GAP-00100"},"M21-GAP-00100":{"line":3355,"offset":584512,"length":203,"previous":"M21-GAP-00099","next":"M21-GAP-00101"},"M21-GAP-00101":{"line":3356,"offset":584715,"length":202,"previous":"M21-GAP-00100","next":"M21-GAP-00102"},"M21-GAP-00102":{"line":3357,"offset":584917,"length":204,"previous":"M21-GAP-00101","next":"M21-GAP-00103"},"M21-GAP-00103":{"line":3358,"offset":585121,"length":207,"previous":"M21-GAP-00102","next":"M21-GAP-00104"},"M21-GAP-00104":{"line":3359,"offset":585328,"length":200,"previous":"M21-GAP-00103","next":"M21-GAP-00105"},"M21-GAP-00105":{"line":3360,"offset":585528,"length":209,"previous":"M21-GAP-00104","next":"M21-GAP-00106"},"M21-GAP-00106":{"line":3361,"offset":585737,"length":198,"previous":"M21-GAP-00105","next":"M21-GAP-00107"},"M21-GAP-00107":{"line":3362,"offset":585935,"length":203,"previous":"M21-GAP-00106","next":"M21-GAP-00108"},"M21-GAP-00108":{"line":3363,"offset":586138,"length":206,"previous":"M21-GAP-00107","next":"M21-GAP-00109"},"M21-GAP-00109":{"line":3364,"offset":586344,"length":205,"previous":"M21-GAP-00108","next":"M21-GAP-00110"},"M21-GAP-00110":{"line":3365,"offset":586549,"length":205,"previous":"M21-GAP-00109","next":"M21-GAP-00111"},"M21-GAP-00111":{"line":3366,"offset":586754,"length":190,"previous":"M21-GAP-00110","next":"M21-GAP-00112"},"M21-GAP-00112":{"line":3367,"offset":586944,"length":190,"previous":"M21-GAP-00111","next":"M21-GAP-00113"},"M21-GAP-00113":{"line":3368,"offset":587134,"length":190,"previous":"M21-GAP-00112","next":"M21-GAP-00114"},"M21-GAP-00114":{"line":3369,"offset":587324,"length":187,"previous":"M21-GAP-00113","next":"M21-GAP-00115"},"M21-GAP-00115":{"line":3370,"offset":587511,"length":204,"previous":"M21-GAP-00114","next":"M21-GAP-00116"},"M21-GAP-00116":{"line":3371,"offset":587715,"length":207,"previous":"M21-GAP-00115","next":"M21-GAP-00117"},"M21-GAP-00117":{"line":3372,"offset":587922,"length":207,"previous":"M21-GAP-00116","next":"M21-GAP-00118"},"M21-GAP-00118":{"line":3373,"offset":588129,"length":207,"previous":"M21-GAP-00117","next":"M21-GAP-00119"},"M21-GAP-00119":{"line":3374,"offset":588336,"length":207,"previous":"M21-GAP-00118","next":"M21-GAP-00120"},"M21-GAP-00120":{"line":3375,"offset":588543,"length":207,"previous":"M21-GAP-00119","next":"M21-GAP-00121"},"M21-GAP-00121":{"line":3376,"offset":588750,"length":207,"previous":"M21-GAP-00120","next":"M21-GAP-00122"},"M21-GAP-00122":{"line":3377,"offset":588957,"length":210,"previous":"M21-GAP-00121","next":"M21-GAP-00123"},"M21-GAP-00123":{"line":3378,"offset":589167,"length":210,"previous":"M21-GAP-00122","next":"M21-GAP-00124"},"M21-GAP-00124":{"line":3379,"offset":589377,"length":210,"previous":"M21-GAP-00123","next":"M21-GAP-00125"},"M21-GAP-00125":{"line":3380,"offset":589587,"length":209,"previous":"M21-GAP-00124","next":"M21-GAP-00126"},"M21-GAP-00126":{"line":3381,"offset":589796,"length":214,"previous":"M21-GAP-00125","next":"M21-GAP-00127"},"M21-GAP-00127":{"line":3382,"offset":590010,"length":214,"previous":"M21-GAP-00126","next":"M21-GAP-00128"},"M21-GAP-00128":{"line":3383,"offset":590224,"length":214,"previous":"M21-GAP-00127","next":"M21-GAP-00129"},"M21-GAP-00129":{"line":3384,"offset":590438,"length":214,"previous":"M21-GAP-00128","next":"M21-GAP-00130"},"M21-GAP-00130":{"line":3385,"offset":590652,"length":215,"previous":"M21-GAP-00129","next":"M21-GAP-00131"},"M21-GAP-00131":{"line":3386,"offset":590867,"length":208,"previous":"M21-GAP-00130","next":"M21-GAP-00132"},"M21-GAP-00132":{"line":3387,"offset":591075,"length":208,"previous":"M21-GAP-00131","next":"M21-GAP-00133"},"M21-GAP-00133":{"line":3388,"offset":591283,"length":208,"previous":"M21-GAP-00132","next":"M21-GAP-00134"},"M21-GAP-00134":{"line":3389,"offset":591491,"length":212,"previous":"M21-GAP-00133","next":"M21-GAP-00135"},"M21-GAP-00135":{"line":3390,"offset":591703,"length":212,"previous":"M21-GAP-00134","next":"M21-GAP-00136"},"M21-GAP-00136":{"line":3391,"offset":591915,"length":208,"previous":"M21-GAP-00135","next":"M21-GAP-00137"},"M21-GAP-00137":{"line":3392,"offset":592123,"length":205,"previous":"M21-GAP-00136","next":"M21-GAP-00138"},"M21-GAP-00138":{"line":3393,"offset":592328,"length":216,"previous":"M21-GAP-00137","next":"M21-GAP-00139"},"M21-GAP-00139":{"line":3394,"offset":592544,"length":210,"previous":"M21-GAP-00138","next":"M21-GAP-00140"},"M21-GAP-00140":{"line":3395,"offset":592754,"length":210,"previous":"M21-GAP-00139","next":"M21-GAP-00141"},"M21-GAP-00141":{"line":3396,"offset":592964,"length":187,"previous":"M21-GAP-00140","next":"M21-GAP-00142"},"M21-GAP-00142":{"line":3397,"offset":593151,"length":188,"previous":"M21-GAP-00141","next":"M21-GAP-00143"},"M21-GAP-00143":{"line":3398,"offset":593339,"length":189,"previous":"M21-GAP-00142","next":"M21-GAP-00144"},"M21-GAP-00144":{"line":3399,"offset":593528,"length":188,"previous":"M21-GAP-00143","next":"M21-GAP-00145"},"M21-GAP-00145":{"line":3400,"offset":593716,"length":203,"previous":"M21-GAP-00144","next":"M21-GAP-00146"},"M21-GAP-00146":{"line":3401,"offset":593919,"length":199,"previous":"M21-GAP-00145","next":"M21-GAP-00147"},"M21-GAP-00147":{"line":3402,"offset":594118,"length":199,"previous":"M21-GAP-00146","next":"M21-GAP-00148"},"M21-GAP-00148":{"line":3403,"offset":594317,"length":199,"previous":"M21-GAP-00147","next":"M21-GAP-00149"},"M21-GAP-00149":{"line":3404,"offset":594516,"length":199,"previous":"M21-GAP-00148","next":"M21-GAP-00150"},"M21-GAP-00150":{"line":3405,"offset":594715,"length":199,"previous":"M21-GAP-00149","next":"M21-GAP-00151"},"M21-GAP-00151":{"line":3406,"offset":594914,"length":199,"previous":"M21-GAP-00150","next":"M21-GAP-00152"},"M21-GAP-00152":{"line":3407,"offset":595113,"length":203,"previous":"M21-GAP-00151","next":"M21-GAP-00153"},"M21-GAP-00153":{"line":3408,"offset":595316,"length":203,"previous":"M21-GAP-00152","next":"M21-GAP-00154"},"M21-GAP-00154":{"line":3409,"offset":595519,"length":203,"previous":"M21-GAP-00153","next":"M21-GAP-00155"},"M21-GAP-00155":{"line":3410,"offset":595722,"length":204,"previous":"M21-GAP-00154","next":"M21-GAP-00156"},"M21-GAP-00156":{"line":3411,"offset":595926,"length":205,"previous":"M21-GAP-00155","next":"M21-GAP-00157"},"M21-GAP-00157":{"line":3412,"offset":596131,"length":201,"previous":"M21-GAP-00156","next":"M21-GAP-00158"},"M21-GAP-00158":{"line":3413,"offset":596332,"length":201,"previous":"M21-GAP-00157","next":"M21-GAP-00159"},"M21-GAP-00159":{"line":3414,"offset":596533,"length":201,"previous":"M21-GAP-00158","next":"M21-GAP-00160"},"M21-GAP-00160":{"line":3415,"offset":596734,"length":201,"previous":"M21-GAP-00159","next":"M21-GAP-00161"},"M21-GAP-00161":{"line":3416,"offset":596935,"length":201,"previous":"M21-GAP-00160","next":"M21-GAP-00162"},"M21-GAP-00162":{"line":3417,"offset":597136,"length":201,"previous":"M21-GAP-00161","next":"M21-GAP-00163"},"M21-GAP-00163":{"line":3418,"offset":597337,"length":204,"previous":"M21-GAP-00162","next":"M21-GAP-00164"},"M21-GAP-00164":{"line":3419,"offset":597541,"length":200,"previous":"M21-GAP-00163","next":"M21-GAP-00165"},"M21-GAP-00165":{"line":3420,"offset":597741,"length":200,"previous":"M21-GAP-00164","next":"M21-GAP-00166"},"M21-GAP-00166":{"line":3421,"offset":597941,"length":200,"previous":"M21-GAP-00165","next":"M21-GAP-00167"},"M21-GAP-00167":{"line":3422,"offset":598141,"length":200,"previous":"M21-GAP-00166","next":"M21-GAP-00168"},"M21-GAP-00168":{"line":3423,"offset":598341,"length":200,"previous":"M21-GAP-00167","next":"M21-GAP-00169"},"M21-GAP-00169":{"line":3424,"offset":598541,"length":203,"previous":"M21-GAP-00168","next":"M21-GAP-00170"},"M21-GAP-00170":{"line":3425,"offset":598744,"length":200,"previous":"M21-GAP-00169","next":"M21-GAP-00171"},"M21-GAP-00171":{"line":3426,"offset":598944,"length":204,"previous":"M21-GAP-00170","next":"M21-GAP-00172"},"M21-GAP-00172":{"line":3427,"offset":599148,"length":202,"previous":"M21-GAP-00171","next":"M21-GAP-00173"},"M21-GAP-00173":{"line":3428,"offset":599350,"length":208,"previous":"M21-GAP-00172","next":"M21-GAP-00174"},"M21-GAP-00174":{"line":3429,"offset":599558,"length":204,"previous":"M21-GAP-00173","next":"M21-GAP-00175"},"M21-GAP-00175":{"line":3430,"offset":599762,"length":204,"previous":"M21-GAP-00174","next":"M21-GAP-00176"},"M21-GAP-00176":{"line":3431,"offset":599966,"length":204,"previous":"M21-GAP-00175","next":"M21-GAP-00177"},"M21-GAP-00177":{"line":3432,"offset":600170,"length":204,"previous":"M21-GAP-00176","next":"M21-GAP-00178"},"M21-GAP-00178":{"line":3433,"offset":600374,"length":204,"previous":"M21-GAP-00177","next":"M21-GAP-00179"},"M21-GAP-00179":{"line":3434,"offset":600578,"length":204,"previous":"M21-GAP-00178","next":"M21-GAP-00180"},"M21-GAP-00180":{"line":3435,"offset":600782,"length":204,"previous":"M21-GAP-00179","next":"M21-GAP-00181"},"M21-GAP-00181":{"line":3436,"offset":600986,"length":204,"previous":"M21-GAP-00180","next":"M21-GAP-00182"},"M21-GAP-00182":{"line":3437,"offset":601190,"length":204,"previous":"M21-GAP-00181","next":"M21-GAP-00183"},"M21-GAP-00183":{"line":3438,"offset":601394,"length":204,"previous":"M21-GAP-00182","next":"M21-GAP-00184"},"M21-GAP-00184":{"line":3439,"offset":601598,"length":204,"previous":"M21-GAP-00183","next":"M21-GAP-00185"},"M21-GAP-00185":{"line":3440,"offset":601802,"length":204,"previous":"M21-GAP-00184","next":"M21-GAP-00186"},"M21-GAP-00186":{"line":3441,"offset":602006,"length":204,"previous":"M21-GAP-00185","next":"M21-GAP-00187"},"M21-GAP-00187":{"line":3442,"offset":602210,"length":204,"previous":"M21-GAP-00186","next":"M21-GAP-00188"},"M21-GAP-00188":{"line":3443,"offset":602414,"length":204,"previous":"M21-GAP-00187","next":"M21-GAP-00189"},"M21-GAP-00189":{"line":3444,"offset":602618,"length":193,"previous":"M21-GAP-00188","next":"M21-GAP-00190"},"M21-GAP-00190":{"line":3445,"offset":602811,"length":193,"previous":"M21-GAP-00189","next":"M21-GAP-00191"},"M21-GAP-00191":{"line":3446,"offset":603004,"length":193,"previous":"M21-GAP-00190","next":"M21-GAP-00192"},"M21-GAP-00192":{"line":3447,"offset":603197,"length":193,"previous":"M21-GAP-00191","next":"M21-GAP-00193"},"M21-GAP-00193":{"line":3448,"offset":603390,"length":193,"previous":"M21-GAP-00192","next":"M21-GAP-00194"},"M21-GAP-00194":{"line":3449,"offset":603583,"length":193,"previous":"M21-GAP-00193","next":"M21-GAP-00195"},"M21-GAP-00195":{"line":3450,"offset":603776,"length":193,"previous":"M21-GAP-00194","next":"M21-GAP-00196"},"M21-GAP-00196":{"line":3451,"offset":603969,"length":193,"previous":"M21-GAP-00195","next":"M21-GAP-00197"},"M21-GAP-00197":{"line":3452,"offset":604162,"length":193,"previous":"M21-GAP-00196","next":"M21-GAP-00198"},"M21-GAP-00198":{"line":3453,"offset":604355,"length":193,"previous":"M21-GAP-00197","next":"M21-GAP-00199"},"M21-GAP-00199":{"line":3454,"offset":604548,"length":207,"previous":"M21-GAP-00198","next":"M21-GAP-00200"},"M21-GAP-00200":{"line":3455,"offset":604755,"length":207,"previous":"M21-GAP-00199","next":"M21-GAP-00201"},"M21-GAP-00201":{"line":3456,"offset":604962,"length":207,"previous":"M21-GAP-00200","next":"M21-GAP-00202"},"M21-GAP-00202":{"line":3457,"offset":605169,"length":207,"previous":"M21-GAP-00201","next":"M21-GAP-00203"},"M21-GAP-00203":{"line":3458,"offset":605376,"length":207,"previous":"M21-GAP-00202","next":"M21-GAP-00204"},"M21-GAP-00204":{"line":3459,"offset":605583,"length":207,"previous":"M21-GAP-00203","next":"M21-GAP-00205"},"M21-GAP-00205":{"line":3460,"offset":605790,"length":207,"previous":"M21-GAP-00204","next":"M21-GAP-00206"},"M21-GAP-00206":{"line":3461,"offset":605997,"length":207,"previous":"M21-GAP-00205","next":"M21-GAP-00207"},"M21-GAP-00207":{"line":3462,"offset":606204,"length":207,"previous":"M21-GAP-00206","next":"M21-GAP-00208"},"M21-GAP-00208":{"line":3463,"offset":606411,"length":196,"previous":"M21-GAP-00207","next":"M21-GAP-00209"},"M21-GAP-00209":{"line":3464,"offset":606607,"length":196,"previous":"M21-GAP-00208","next":"M21-GAP-00210"},"M21-GAP-00210":{"line":3465,"offset":606803,"length":196,"previous":"M21-GAP-00209","next":"M21-GAP-00211"},"M21-GAP-00211":{"line":3466,"offset":606999,"length":196,"previous":"M21-GAP-00210","next":"M21-GAP-00212"},"M21-GAP-00212":{"line":3467,"offset":607195,"length":196,"previous":"M21-GAP-00211","next":"M21-GAP-00213"},"M21-GAP-00213":{"line":3468,"offset":607391,"length":196,"previous":"M21-GAP-00212","next":"M21-GAP-00214"},"M21-GAP-00214":{"line":3469,"offset":607587,"length":196,"previous":"M21-GAP-00213","next":"M21-GAP-00215"},"M21-GAP-00215":{"line":3470,"offset":607783,"length":196,"previous":"M21-GAP-00214","next":"M21-GAP-00216"},"M21-GAP-00216":{"line":3471,"offset":607979,"length":196,"previous":"M21-GAP-00215","next":"M21-GAP-00217"},"M21-GAP-00217":{"line":3472,"offset":608175,"length":206,"previous":"M21-GAP-00216","next":"M21-GAP-00218"},"M21-GAP-00218":{"line":3473,"offset":608381,"length":206,"previous":"M21-GAP-00217","next":"M21-GAP-00219"},"M21-GAP-00219":{"line":3474,"offset":608587,"length":206,"previous":"M21-GAP-00218","next":"M21-GAP-00220"},"M21-GAP-00220":{"line":3475,"offset":608793,"length":206,"previous":"M21-GAP-00219","next":"M21-GAP-00221"},"M21-GAP-00221":{"line":3476,"offset":608999,"length":206,"previous":"M21-GAP-00220","next":"M21-GAP-00222"},"M21-GAP-00222":{"line":3477,"offset":609205,"length":206,"previous":"M21-GAP-00221","next":"M21-GAP-00223"},"M21-GAP-00223":{"line":3478,"offset":609411,"length":206,"previous":"M21-GAP-00222","next":"M21-GAP-00224"},"M21-GAP-00224":{"line":3479,"offset":609617,"length":206,"previous":"M21-GAP-00223","next":"M21-GAP-00225"},"M21-GAP-00225":{"line":3480,"offset":609823,"length":206,"previous":"M21-GAP-00224","next":"M21-GAP-00226"},"M21-GAP-00226":{"line":3481,"offset":610029,"length":206,"previous":"M21-GAP-00225","next":"M21-GAP-00227"},"M21-GAP-00227":{"line":3482,"offset":610235,"length":195,"previous":"M21-GAP-00226","next":"M21-GAP-00228"},"M21-GAP-00228":{"line":3483,"offset":610430,"length":195,"previous":"M21-GAP-00227","next":"M21-GAP-00229"},"M21-GAP-00229":{"line":3484,"offset":610625,"length":195,"previous":"M21-GAP-00228","next":"M21-GAP-00230"},"M21-GAP-00230":{"line":3485,"offset":610820,"length":195,"previous":"M21-GAP-00229","next":"M21-GAP-00231"},"M21-GAP-00231":{"line":3486,"offset":611015,"length":195,"previous":"M21-GAP-00230","next":"M21-GAP-00232"},"M21-GAP-00232":{"line":3487,"offset":611210,"length":195,"previous":"M21-GAP-00231","next":"M21-GAP-00233"},"M21-GAP-00233":{"line":3488,"offset":611405,"length":195,"previous":"M21-GAP-00232","next":"M21-GAP-00234"},"M21-GAP-00234":{"line":3489,"offset":611600,"length":195,"previous":"M21-GAP-00233","next":"M21-GAP-00235"},"M21-GAP-00235":{"line":3490,"offset":611795,"length":195,"previous":"M21-GAP-00234","next":"M21-GAP-00236"},"M21-GAP-00236":{"line":3491,"offset":611990,"length":195,"previous":"M21-GAP-00235","next":"M21-GAP-00237"},"M21-GAP-00237":{"line":3492,"offset":612185,"length":188,"previous":"M21-GAP-00236","next":"M21-GAP-00238"},"M21-GAP-00238":{"line":3493,"offset":612373,"length":188,"previous":"M21-GAP-00237","next":"M21-GAP-00239"},"M21-GAP-00239":{"line":3494,"offset":612561,"length":188,"previous":"M21-GAP-00238","next":"M21-GAP-00240"},"M21-GAP-00240":{"line":3495,"offset":612749,"length":192,"previous":"M21-GAP-00239","next":"M21-GAP-00241"},"M21-GAP-00241":{"line":3496,"offset":612941,"length":199,"previous":"M21-GAP-00240","next":"M21-GAP-00242"},"M21-GAP-00242":{"line":3497,"offset":613140,"length":199,"previous":"M21-GAP-00241","next":"M21-GAP-00243"},"M21-GAP-00243":{"line":3498,"offset":613339,"length":199,"previous":"M21-GAP-00242","next":"M21-GAP-00244"},"M21-GAP-00244":{"line":3499,"offset":613538,"length":199,"previous":"M21-GAP-00243","next":"M21-GAP-00245"},"M21-GAP-00245":{"line":3500,"offset":613737,"length":199,"previous":"M21-GAP-00244","next":"M21-GAP-00246"},"M21-GAP-00246":{"line":3501,"offset":613936,"length":199,"previous":"M21-GAP-00245","next":"M21-GAP-00247"},"M21-GAP-00247":{"line":3502,"offset":614135,"length":199,"previous":"M21-GAP-00246","next":"M21-GAP-00248"},"M21-GAP-00248":{"line":3503,"offset":614334,"length":199,"previous":"M21-GAP-00247","next":"M21-GAP-00249"},"M21-GAP-00249":{"line":3504,"offset":614533,"length":199,"previous":"M21-GAP-00248","next":"M21-GAP-00250"},"M21-GAP-00250":{"line":3505,"offset":614732,"length":188,"previous":"M21-GAP-00249","next":"M21-GAP-00251"},"M21-GAP-00251":{"line":3506,"offset":614920,"length":188,"previous":"M21-GAP-00250","next":"M21-GAP-00252"},"M21-GAP-00252":{"line":3507,"offset":615108,"length":188,"previous":"M21-GAP-00251","next":"M21-GAP-00253"},"M21-GAP-00253":{"line":3508,"offset":615296,"length":188,"previous":"M21-GAP-00252","next":"M21-GAP-00254"},"M21-GAP-00254":{"line":3509,"offset":615484,"length":188,"previous":"M21-GAP-00253","next":"M21-GAP-00255"},"M21-GAP-00255":{"line":3510,"offset":615672,"length":188,"previous":"M21-GAP-00254","next":"M21-GAP-00256"},"M21-GAP-00256":{"line":3511,"offset":615860,"length":188,"previous":"M21-GAP-00255","next":"M21-GAP-00257"},"M21-GAP-00257":{"line":3512,"offset":616048,"length":188,"previous":"M21-GAP-00256","next":"M21-GAP-00258"},"M21-GAP-00258":{"line":3513,"offset":616236,"length":188,"previous":"M21-GAP-00257","next":"M21-GAP-00259"},"M21-GAP-00259":{"line":3514,"offset":616424,"length":176,"previous":"M21-GAP-00258","next":"M21-GAP-00260"},"M21-GAP-00260":{"line":3515,"offset":616600,"length":176,"previous":"M21-GAP-00259","next":"M21-GAP-00261"},"M21-GAP-00261":{"line":3516,"offset":616776,"length":177,"previous":"M21-GAP-00260","next":"M21-GAP-00262"},"M21-GAP-00262":{"line":3517,"offset":616953,"length":178,"previous":"M21-GAP-00261","next":"M21-GAP-00263"},"M21-GAP-00263":{"line":3518,"offset":617131,"length":178,"previous":"M21-GAP-00262","next":"M21-GAP-00264"},"M21-GAP-00264":{"line":3519,"offset":617309,"length":178,"previous":"M21-GAP-00263","next":"M21-GAP-00265"},"M21-GAP-00265":{"line":3520,"offset":617487,"length":178,"previous":"M21-GAP-00264","next":"M21-GAP-00266"},"M21-GAP-00266":{"line":3521,"offset":617665,"length":178,"previous":"M21-GAP-00265","next":"M21-GAP-00267"},"M21-GAP-00267":{"line":3522,"offset":617843,"length":178,"previous":"M21-GAP-00266","next":"M21-GAP-00268"},"M21-GAP-00268":{"line":3523,"offset":618021,"length":178,"previous":"M21-GAP-00267","next":"M21-GAP-00269"},"M21-GAP-00269":{"line":3524,"offset":618199,"length":178,"previous":"M21-GAP-00268","next":"M21-GAP-00270"},"M21-GAP-00270":{"line":3525,"offset":618377,"length":178,"previous":"M21-GAP-00269","next":"M21-GAP-00271"},"M21-GAP-00271":{"line":3526,"offset":618555,"length":178,"previous":"M21-GAP-00270","next":"M21-GAP-00272"},"M21-GAP-00272":{"line":3527,"offset":618733,"length":177,"previous":"M21-GAP-00271","next":"M21-GAP-00273"},"M21-GAP-00273":{"line":3528,"offset":618910,"length":178,"previous":"M21-GAP-00272","next":"M21-GAP-00274"},"M21-GAP-00274":{"line":3529,"offset":619088,"length":178,"previous":"M21-GAP-00273","next":"M21-GAP-00275"},"M21-GAP-00275":{"line":3530,"offset":619266,"length":178,"previous":"M21-GAP-00274","next":"M21-GAP-00276"},"M21-GAP-00276":{"line":3531,"offset":619444,"length":178,"previous":"M21-GAP-00275","next":"M21-GAP-00277"},"M21-GAP-00277":{"line":3532,"offset":619622,"length":178,"previous":"M21-GAP-00276","next":"M21-GAP-00278"},"M21-GAP-00278":{"line":3533,"offset":619800,"length":178,"previous":"M21-GAP-00277","next":"M21-GAP-00279"},"M21-GAP-00279":{"line":3534,"offset":619978,"length":177,"previous":"M21-GAP-00278","next":"M21-GAP-00280"},"M21-GAP-00280":{"line":3535,"offset":620155,"length":177,"previous":"M21-GAP-00279","next":"M21-GAP-00281"},"M21-GAP-00281":{"line":3536,"offset":620332,"length":177,"previous":"M21-GAP-00280","next":"M21-GAP-00282"},"M21-GAP-00282":{"line":3537,"offset":620509,"length":177,"previous":"M21-GAP-00281","next":"M21-GAP-00283"},"M21-GAP-00283":{"line":3538,"offset":620686,"length":177,"previous":"M21-GAP-00282","next":"M21-GAP-00284"},"M21-GAP-00284":{"line":3539,"offset":620863,"length":177,"previous":"M21-GAP-00283","next":"M21-GAP-00285"},"M21-GAP-00285":{"line":3540,"offset":621040,"length":177,"previous":"M21-GAP-00284","next":"M21-GAP-00286"},"M21-GAP-00286":{"line":3541,"offset":621217,"length":177,"previous":"M21-GAP-00285","next":"M21-GAP-00287"},"M21-GAP-00287":{"line":3542,"offset":621394,"length":176,"previous":"M21-GAP-00286","next":"M21-GAP-00288"},"M21-GAP-00288":{"line":3543,"offset":621570,"length":177,"previous":"M21-GAP-00287","next":"M21-GAP-00289"},"M21-GAP-00289":{"line":3544,"offset":621747,"length":177,"previous":"M21-GAP-00288","next":"M21-GAP-00290"},"M21-GAP-00290":{"line":3545,"offset":621924,"length":177,"previous":"M21-GAP-00289","next":"M21-GAP-00291"},"M21-GAP-00291":{"line":3546,"offset":622101,"length":177,"previous":"M21-GAP-00290","next":"M21-GAP-00292"},"M21-GAP-00292":{"line":3547,"offset":622278,"length":177,"previous":"M21-GAP-00291","next":"M21-GAP-00293"},"M21-GAP-00293":{"line":3548,"offset":622455,"length":177,"previous":"M21-GAP-00292","next":"M21-GAP-00294"},"M21-GAP-00294":{"line":3549,"offset":622632,"length":177,"previous":"M21-GAP-00293","next":"M21-GAP-00295"},"M21-GAP-00295":{"line":3550,"offset":622809,"length":177,"previous":"M21-GAP-00294","next":"M21-GAP-00296"},"M21-GAP-00296":{"line":3551,"offset":622986,"length":177,"previous":"M21-GAP-00295","next":"M21-GAP-00297"},"M21-GAP-00297":{"line":3552,"offset":623163,"length":177,"previous":"M21-GAP-00296","next":"M21-GAP-00298"},"M21-GAP-00298":{"line":3553,"offset":623340,"length":176,"previous":"M21-GAP-00297","next":"M21-GAP-00299"},"M21-GAP-00299":{"line":3554,"offset":623516,"length":177,"previous":"M21-GAP-00298","next":"M21-GAP-00300"},"M21-GAP-00300":{"line":3555,"offset":623693,"length":177,"previous":"M21-GAP-00299","next":"M21-GAP-00301"},"M21-GAP-00301":{"line":3556,"offset":623870,"length":177,"previous":"M21-GAP-00300","next":"M21-GAP-00302"},"M21-GAP-00302":{"line":3557,"offset":624047,"length":177,"previous":"M21-GAP-00301","next":"M21-GAP-00303"},"M21-GAP-00303":{"line":3558,"offset":624224,"length":177,"previous":"M21-GAP-00302","next":"M21-GAP-00304"},"M21-GAP-00304":{"line":3559,"offset":624401,"length":177,"previous":"M21-GAP-00303","next":"M21-GAP-00305"},"M21-GAP-00305":{"line":3560,"offset":624578,"length":177,"previous":"M21-GAP-00304","next":"M21-GAP-00306"},"M21-GAP-00306":{"line":3561,"offset":624755,"length":177,"previous":"M21-GAP-00305","next":"M21-GAP-00307"},"M21-GAP-00307":{"line":3562,"offset":624932,"length":177,"previous":"M21-GAP-00306","next":"M21-GAP-00308"},"M21-GAP-00308":{"line":3563,"offset":625109,"length":177,"previous":"M21-GAP-00307","next":"M21-GAP-00309"},"M21-GAP-00309":{"line":3564,"offset":625286,"length":176,"previous":"M21-GAP-00308","next":"M21-GAP-00310"},"M21-GAP-00310":{"line":3565,"offset":625462,"length":177,"previous":"M21-GAP-00309","next":"M21-GAP-00311"},"M21-GAP-00311":{"line":3566,"offset":625639,"length":177,"previous":"M21-GAP-00310","next":"M21-GAP-00312"},"M21-GAP-00312":{"line":3567,"offset":625816,"length":177,"previous":"M21-GAP-00311","next":"M21-GAP-00313"},"M21-GAP-00313":{"line":3568,"offset":625993,"length":177,"previous":"M21-GAP-00312","next":"M21-GAP-00314"},"M21-GAP-00314":{"line":3569,"offset":626170,"length":177,"previous":"M21-GAP-00313","next":"M21-GAP-00315"},"M21-GAP-00315":{"line":3570,"offset":626347,"length":177,"previous":"M21-GAP-00314","next":"M21-GAP-00316"},"M21-GAP-00316":{"line":3571,"offset":626524,"length":177,"previous":"M21-GAP-00315","next":"M21-GAP-00317"},"M21-GAP-00317":{"line":3572,"offset":626701,"length":177,"previous":"M21-GAP-00316","next":"M21-GAP-00318"},"M21-GAP-00318":{"line":3573,"offset":626878,"length":177,"previous":"M21-GAP-00317","next":"M21-GAP-00319"},"M21-GAP-00319":{"line":3574,"offset":627055,"length":177,"previous":"M21-GAP-00318","next":"M21-GAP-00320"},"M21-GAP-00320":{"line":3575,"offset":627232,"length":176,"previous":"M21-GAP-00319","next":"M21-GAP-00321"},"M21-GAP-00321":{"line":3576,"offset":627408,"length":177,"previous":"M21-GAP-00320","next":"M21-GAP-00322"},"M21-GAP-00322":{"line":3577,"offset":627585,"length":177,"previous":"M21-GAP-00321","next":"M21-GAP-00323"},"M21-GAP-00323":{"line":3578,"offset":627762,"length":177,"previous":"M21-GAP-00322","next":"M21-GAP-00324"},"M21-GAP-00324":{"line":3579,"offset":627939,"length":177,"previous":"M21-GAP-00323","next":"M21-GAP-00325"},"M21-GAP-00325":{"line":3580,"offset":628116,"length":177,"previous":"M21-GAP-00324","next":"M21-GAP-00326"},"M21-GAP-00326":{"line":3581,"offset":628293,"length":177,"previous":"M21-GAP-00325","next":"M21-GAP-00327"},"M21-GAP-00327":{"line":3582,"offset":628470,"length":177,"previous":"M21-GAP-00326","next":"M21-GAP-00328"},"M21-GAP-00328":{"line":3583,"offset":628647,"length":177,"previous":"M21-GAP-00327","next":"M21-GAP-00329"},"M21-GAP-00329":{"line":3584,"offset":628824,"length":177,"previous":"M21-GAP-00328","next":"M21-GAP-00330"},"M21-GAP-00330":{"line":3585,"offset":629001,"length":177,"previous":"M21-GAP-00329","next":"M21-GAP-00331"},"M21-GAP-00331":{"line":3586,"offset":629178,"length":176,"previous":"M21-GAP-00330","next":"M21-GAP-00332"},"M21-GAP-00332":{"line":3587,"offset":629354,"length":177,"previous":"M21-GAP-00331","next":"M21-GAP-00333"},"M21-GAP-00333":{"line":3588,"offset":629531,"length":177,"previous":"M21-GAP-00332","next":"M21-GAP-00334"},"M21-GAP-00334":{"line":3589,"offset":629708,"length":177,"previous":"M21-GAP-00333","next":"M21-GAP-00335"},"M21-GAP-00335":{"line":3590,"offset":629885,"length":177,"previous":"M21-GAP-00334","next":"M21-GAP-00336"},"M21-GAP-00336":{"line":3591,"offset":630062,"length":177,"previous":"M21-GAP-00335","next":"M21-GAP-00337"},"M21-GAP-00337":{"line":3592,"offset":630239,"length":177,"previous":"M21-GAP-00336","next":"M21-GAP-00338"},"M21-GAP-00338":{"line":3593,"offset":630416,"length":177,"previous":"M21-GAP-00337","next":"M21-GAP-00339"},"M21-GAP-00339":{"line":3594,"offset":630593,"length":177,"previous":"M21-GAP-00338","next":"M21-GAP-00340"},"M21-GAP-00340":{"line":3595,"offset":630770,"length":177,"previous":"M21-GAP-00339","next":"M21-GAP-00341"},"M21-GAP-00341":{"line":3596,"offset":630947,"length":177,"previous":"M21-GAP-00340","next":"M21-GAP-00342"},"M21-GAP-00342":{"line":3597,"offset":631124,"length":176,"previous":"M21-GAP-00341","next":"M21-GAP-00343"},"M21-GAP-00343":{"line":3598,"offset":631300,"length":177,"previous":"M21-GAP-00342","next":"M21-GAP-00344"},"M21-GAP-00344":{"line":3599,"offset":631477,"length":177,"previous":"M21-GAP-00343","next":"M21-GAP-00345"},"M21-GAP-00345":{"line":3600,"offset":631654,"length":177,"previous":"M21-GAP-00344","next":"M21-GAP-00346"},"M21-GAP-00346":{"line":3601,"offset":631831,"length":177,"previous":"M21-GAP-00345","next":"M21-GAP-00347"},"M21-GAP-00347":{"line":3602,"offset":632008,"length":177,"previous":"M21-GAP-00346","next":"M21-GAP-00348"},"M21-GAP-00348":{"line":3603,"offset":632185,"length":177,"previous":"M21-GAP-00347","next":"M21-GAP-00349"},"M21-GAP-00349":{"line":3604,"offset":632362,"length":177,"previous":"M21-GAP-00348","next":"M21-GAP-00350"},"M21-GAP-00350":{"line":3605,"offset":632539,"length":177,"previous":"M21-GAP-00349","next":"M21-GAP-00351"},"M21-GAP-00351":{"line":3606,"offset":632716,"length":177,"previous":"M21-GAP-00350","next":"M21-GAP-00352"},"M21-GAP-00352":{"line":3607,"offset":632893,"length":177,"previous":"M21-GAP-00351","next":"M21-GAP-00353"},"M21-GAP-00353":{"line":3608,"offset":633070,"length":176,"previous":"M21-GAP-00352","next":"M21-GAP-00354"},"M21-GAP-00354":{"line":3609,"offset":633246,"length":177,"previous":"M21-GAP-00353","next":"M21-GAP-00355"},"M21-GAP-00355":{"line":3610,"offset":633423,"length":177,"previous":"M21-GAP-00354","next":"M21-GAP-00356"},"M21-GAP-00356":{"line":3611,"offset":633600,"length":177,"previous":"M21-GAP-00355","next":"M21-GAP-00357"},"M21-GAP-00357":{"line":3612,"offset":633777,"length":177,"previous":"M21-GAP-00356","next":"M21-GAP-00358"},"M21-GAP-00358":{"line":3613,"offset":633954,"length":177,"previous":"M21-GAP-00357","next":"M21-GAP-00359"},"M21-GAP-00359":{"line":3614,"offset":634131,"length":177,"previous":"M21-GAP-00358","next":"M21-GAP-00360"},"M21-GAP-00360":{"line":3615,"offset":634308,"length":177,"previous":"M21-GAP-00359","next":"M21-GAP-00361"},"M21-GAP-00361":{"line":3616,"offset":634485,"length":177,"previous":"M21-GAP-00360","next":"M21-GAP-00362"},"M21-GAP-00362":{"line":3617,"offset":634662,"length":177,"previous":"M21-GAP-00361","next":"M21-GAP-00363"},"M21-GAP-00363":{"line":3618,"offset":634839,"length":177,"previous":"M21-GAP-00362","next":"M21-GAP-00364"},"M21-GAP-00364":{"line":3619,"offset":635016,"length":176,"previous":"M21-GAP-00363","next":"M21-GAP-00365"},"M21-GAP-00365":{"line":3620,"offset":635192,"length":177,"previous":"M21-GAP-00364","next":"M21-GAP-00366"},"M21-GAP-00366":{"line":3621,"offset":635369,"length":177,"previous":"M21-GAP-00365","next":"M21-GAP-00367"},"M21-GAP-00367":{"line":3622,"offset":635546,"length":177,"previous":"M21-GAP-00366","next":"M21-GAP-00368"},"M21-GAP-00368":{"line":3623,"offset":635723,"length":177,"previous":"M21-GAP-00367","next":"M21-GAP-00369"},"M21-GAP-00369":{"line":3624,"offset":635900,"length":177,"previous":"M21-GAP-00368","next":"M21-GAP-00370"},"M21-GAP-00370":{"line":3625,"offset":636077,"length":177,"previous":"M21-GAP-00369","next":"M21-GAP-00371"},"M21-GAP-00371":{"line":3626,"offset":636254,"length":177,"previous":"M21-GAP-00370","next":"M21-GAP-00372"},"M21-GAP-00372":{"line":3627,"offset":636431,"length":177,"previous":"M21-GAP-00371","next":"M21-GAP-00373"},"M21-GAP-00373":{"line":3628,"offset":636608,"length":177,"previous":"M21-GAP-00372","next":"M21-GAP-00374"},"M21-GAP-00374":{"line":3629,"offset":636785,"length":177,"previous":"M21-GAP-00373","next":"M21-GAP-00375"},"M21-GAP-00375":{"line":3630,"offset":636962,"length":185,"previous":"M21-GAP-00374","next":"M21-GAP-00376"},"M21-GAP-00376":{"line":3631,"offset":637147,"length":185,"previous":"M21-GAP-00375","next":"M21-GAP-00377"},"M21-GAP-00377":{"line":3632,"offset":637332,"length":186,"previous":"M21-GAP-00376","next":"M21-GAP-00378"},"M21-GAP-00378":{"line":3633,"offset":637518,"length":186,"previous":"M21-GAP-00377","next":"M21-GAP-00379"},"M21-GAP-00379":{"line":3634,"offset":637704,"length":186,"previous":"M21-GAP-00378","next":"M21-GAP-00380"},"M21-GAP-00380":{"line":3635,"offset":637890,"length":186,"previous":"M21-GAP-00379","next":"M21-GAP-00381"},"M21-GAP-00381":{"line":3636,"offset":638076,"length":186,"previous":"M21-GAP-00380","next":"M21-GAP-00382"},"M21-GAP-00382":{"line":3637,"offset":638262,"length":186,"previous":"M21-GAP-00381","next":"M21-GAP-00383"},"M21-GAP-00383":{"line":3638,"offset":638448,"length":186,"previous":"M21-GAP-00382","next":"M21-GAP-00384"},"M21-GAP-00384":{"line":3639,"offset":638634,"length":186,"previous":"M21-GAP-00383","next":"M21-GAP-00385"},"M21-GAP-00385":{"line":3640,"offset":638820,"length":186,"previous":"M21-GAP-00384","next":"M21-GAP-00386"},"M21-GAP-00386":{"line":3641,"offset":639006,"length":186,"previous":"M21-GAP-00385","next":"M21-GAP-00387"},"M21-GAP-00387":{"line":3642,"offset":639192,"length":185,"previous":"M21-GAP-00386","next":"M21-GAP-00388"},"M21-GAP-00388":{"line":3643,"offset":639377,"length":186,"previous":"M21-GAP-00387","next":"M21-GAP-00389"},"M21-GAP-00389":{"line":3644,"offset":639563,"length":186,"previous":"M21-GAP-00388","next":"M21-GAP-00390"},"M21-GAP-00390":{"line":3645,"offset":639749,"length":186,"previous":"M21-GAP-00389","next":"M21-GAP-00391"},"M21-GAP-00391":{"line":3646,"offset":639935,"length":186,"previous":"M21-GAP-00390","next":"M21-GAP-00392"},"M21-GAP-00392":{"line":3647,"offset":640121,"length":186,"previous":"M21-GAP-00391","next":"M21-GAP-00393"},"M21-GAP-00393":{"line":3648,"offset":640307,"length":186,"previous":"M21-GAP-00392","next":"M21-GAP-00394"},"M21-GAP-00394":{"line":3649,"offset":640493,"length":186,"previous":"M21-GAP-00393","next":"M21-GAP-00395"},"M21-GAP-00395":{"line":3650,"offset":640679,"length":186,"previous":"M21-GAP-00394","next":"M21-GAP-00396"},"M21-GAP-00396":{"line":3651,"offset":640865,"length":186,"previous":"M21-GAP-00395","next":"M21-GAP-00397"},"M21-GAP-00397":{"line":3652,"offset":641051,"length":186,"previous":"M21-GAP-00396","next":"M21-GAP-00398"},"M21-GAP-00398":{"line":3653,"offset":641237,"length":185,"previous":"M21-GAP-00397","next":"M21-GAP-00399"},"M21-GAP-00399":{"line":3654,"offset":641422,"length":186,"previous":"M21-GAP-00398","next":"M21-GAP-00400"},"M21-GAP-00400":{"line":3655,"offset":641608,"length":186,"previous":"M21-GAP-00399","next":"M21-GAP-00401"},"M21-GAP-00401":{"line":3656,"offset":641794,"length":186,"previous":"M21-GAP-00400","next":"M21-GAP-00402"},"M21-GAP-00402":{"line":3657,"offset":641980,"length":186,"previous":"M21-GAP-00401","next":"M21-GAP-00403"},"M21-GAP-00403":{"line":3658,"offset":642166,"length":186,"previous":"M21-GAP-00402","next":"M21-GAP-00404"},"M21-GAP-00404":{"line":3659,"offset":642352,"length":186,"previous":"M21-GAP-00403","next":"M21-GAP-00405"},"M21-GAP-00405":{"line":3660,"offset":642538,"length":186,"previous":"M21-GAP-00404","next":"M21-GAP-00406"},"M21-GAP-00406":{"line":3661,"offset":642724,"length":185,"previous":"M21-GAP-00405","next":"M21-GAP-00407"},"M21-GAP-00407":{"line":3662,"offset":642909,"length":185,"previous":"M21-GAP-00406","next":"M21-GAP-00408"},"M21-GAP-00408":{"line":3663,"offset":643094,"length":185,"previous":"M21-GAP-00407","next":"M21-GAP-00409"},"M21-GAP-00409":{"line":3664,"offset":643279,"length":185,"previous":"M21-GAP-00408","next":"M21-GAP-00410"},"M21-GAP-00410":{"line":3665,"offset":643464,"length":185,"previous":"M21-GAP-00409","next":"M21-GAP-00411"},"M21-GAP-00411":{"line":3666,"offset":643649,"length":185,"previous":"M21-GAP-00410","next":"M21-GAP-00412"},"M21-GAP-00412":{"line":3667,"offset":643834,"length":176,"previous":"M21-GAP-00411","next":"M21-GAP-00413"},"M21-GAP-00413":{"line":3668,"offset":644010,"length":176,"previous":"M21-GAP-00412","next":"M21-GAP-00414"},"M21-GAP-00414":{"line":3669,"offset":644186,"length":176,"previous":"M21-GAP-00413","next":"M21-GAP-00415"},"M21-GAP-00415":{"line":3670,"offset":644362,"length":176,"previous":"M21-GAP-00414","next":"M21-GAP-00416"},"M21-GAP-00416":{"line":3671,"offset":644538,"length":176,"previous":"M21-GAP-00415","next":"M21-GAP-00417"},"M21-GAP-00417":{"line":3672,"offset":644714,"length":175,"previous":"M21-GAP-00416","next":"M21-GAP-00418"},"M21-GAP-00418":{"line":3673,"offset":644889,"length":175,"previous":"M21-GAP-00417","next":"M21-GAP-00419"},"M21-GAP-00419":{"line":3674,"offset":645064,"length":176,"previous":"M21-GAP-00418","next":"M21-GAP-00420"},"M21-GAP-00420":{"line":3675,"offset":645240,"length":176,"previous":"M21-GAP-00419","next":"M21-GAP-00421"},"M21-GAP-00421":{"line":3676,"offset":645416,"length":176,"previous":"M21-GAP-00420","next":"M21-GAP-00422"},"M21-GAP-00422":{"line":3677,"offset":645592,"length":176,"previous":"M21-GAP-00421","next":"M21-GAP-00423"},"M21-GAP-00423":{"line":3678,"offset":645768,"length":176,"previous":"M21-GAP-00422","next":"M21-GAP-00424"},"M21-GAP-00424":{"line":3679,"offset":645944,"length":176,"previous":"M21-GAP-00423","next":"M21-GAP-00425"},"M21-GAP-00425":{"line":3680,"offset":646120,"length":176,"previous":"M21-GAP-00424","next":"M21-GAP-00426"},"M21-GAP-00426":{"line":3681,"offset":646296,"length":176,"previous":"M21-GAP-00425","next":"M21-GAP-00427"},"M21-GAP-00427":{"line":3682,"offset":646472,"length":176,"previous":"M21-GAP-00426","next":"M21-GAP-00428"},"M21-GAP-00428":{"line":3683,"offset":646648,"length":176,"previous":"M21-GAP-00427","next":"M21-GAP-00429"},"M21-GAP-00429":{"line":3684,"offset":646824,"length":175,"previous":"M21-GAP-00428","next":"M21-GAP-00430"},"M21-GAP-00430":{"line":3685,"offset":646999,"length":176,"previous":"M21-GAP-00429","next":"M21-GAP-00431"},"M21-GAP-00431":{"line":3686,"offset":647175,"length":176,"previous":"M21-GAP-00430","next":"M21-GAP-00432"},"M21-GAP-00432":{"line":3687,"offset":647351,"length":176,"previous":"M21-GAP-00431","next":"M21-GAP-00433"},"M21-GAP-00433":{"line":3688,"offset":647527,"length":176,"previous":"M21-GAP-00432","next":"M21-GAP-00434"},"M21-GAP-00434":{"line":3689,"offset":647703,"length":176,"previous":"M21-GAP-00433","next":"M21-GAP-00435"},"M21-GAP-00435":{"line":3690,"offset":647879,"length":176,"previous":"M21-GAP-00434","next":"M21-GAP-00436"},"M21-GAP-00436":{"line":3691,"offset":648055,"length":176,"previous":"M21-GAP-00435","next":"M21-GAP-00437"},"M21-GAP-00437":{"line":3692,"offset":648231,"length":176,"previous":"M21-GAP-00436","next":"M21-GAP-00438"},"M21-GAP-00438":{"line":3693,"offset":648407,"length":176,"previous":"M21-GAP-00437","next":"M21-GAP-00439"},"M21-GAP-00439":{"line":3694,"offset":648583,"length":176,"previous":"M21-GAP-00438","next":"M21-GAP-00440"},"M21-GAP-00440":{"line":3695,"offset":648759,"length":175,"previous":"M21-GAP-00439","next":"M21-GAP-00441"},"M21-GAP-00441":{"line":3696,"offset":648934,"length":176,"previous":"M21-GAP-00440","next":"M21-GAP-00442"},"M21-GAP-00442":{"line":3697,"offset":649110,"length":176,"previous":"M21-GAP-00441","next":"M21-GAP-00443"},"M21-GAP-00443":{"line":3698,"offset":649286,"length":176,"previous":"M21-GAP-00442","next":"M21-GAP-00444"},"M21-GAP-00444":{"line":3699,"offset":649462,"length":176,"previous":"M21-GAP-00443","next":"M21-GAP-00445"},"M21-GAP-00445":{"line":3700,"offset":649638,"length":176,"previous":"M21-GAP-00444","next":"M21-GAP-00446"},"M21-GAP-00446":{"line":3701,"offset":649814,"length":176,"previous":"M21-GAP-00445","next":"M21-GAP-00447"},"M21-GAP-00447":{"line":3702,"offset":649990,"length":176,"previous":"M21-GAP-00446","next":"M21-GAP-00448"},"M21-GAP-00448":{"line":3703,"offset":650166,"length":176,"previous":"M21-GAP-00447","next":"M21-GAP-00449"},"M21-GAP-00449":{"line":3704,"offset":650342,"length":176,"previous":"M21-GAP-00448","next":"M21-GAP-00450"},"M21-GAP-00450":{"line":3705,"offset":650518,"length":176,"previous":"M21-GAP-00449","next":"M21-GAP-00451"},"M21-GAP-00451":{"line":3706,"offset":650694,"length":175,"previous":"M21-GAP-00450","next":"M21-GAP-00452"},"M21-GAP-00452":{"line":3707,"offset":650869,"length":176,"previous":"M21-GAP-00451","next":"M21-GAP-00453"},"M21-GAP-00453":{"line":3708,"offset":651045,"length":176,"previous":"M21-GAP-00452","next":"M21-GAP-00454"},"M21-GAP-00454":{"line":3709,"offset":651221,"length":176,"previous":"M21-GAP-00453","next":"M21-GAP-00455"},"M21-GAP-00455":{"line":3710,"offset":651397,"length":176,"previous":"M21-GAP-00454","next":"M21-GAP-00456"},"M21-GAP-00456":{"line":3711,"offset":651573,"length":176,"previous":"M21-GAP-00455","next":"M21-GAP-00457"},"M21-GAP-00457":{"line":3712,"offset":651749,"length":176,"previous":"M21-GAP-00456","next":"M21-GAP-00458"},"M21-GAP-00458":{"line":3713,"offset":651925,"length":176,"previous":"M21-GAP-00457","next":"M21-GAP-00459"},"M21-GAP-00459":{"line":3714,"offset":652101,"length":176,"previous":"M21-GAP-00458","next":"M21-GAP-00460"},"M21-GAP-00460":{"line":3715,"offset":652277,"length":176,"previous":"M21-GAP-00459","next":"M21-GAP-00461"},"M21-GAP-00461":{"line":3716,"offset":652453,"length":176,"previous":"M21-GAP-00460","next":"M21-GAP-00462"},"M21-GAP-00462":{"line":3717,"offset":652629,"length":175,"previous":"M21-GAP-00461","next":"M21-GAP-00463"},"M21-GAP-00463":{"line":3718,"offset":652804,"length":176,"previous":"M21-GAP-00462","next":"M21-GAP-00464"},"M21-GAP-00464":{"line":3719,"offset":652980,"length":176,"previous":"M21-GAP-00463","next":"M21-GAP-00465"},"M21-GAP-00465":{"line":3720,"offset":653156,"length":175,"previous":"M21-GAP-00464","next":"M21-GAP-00466"},"M21-GAP-00466":{"line":3721,"offset":653331,"length":175,"previous":"M21-GAP-00465","next":"M21-GAP-00467"},"M21-GAP-00467":{"line":3722,"offset":653506,"length":175,"previous":"M21-GAP-00466","next":"M21-GAP-00468"},"M21-GAP-00468":{"line":3723,"offset":653681,"length":175,"previous":"M21-GAP-00467","next":"M21-GAP-00469"},"M21-GAP-00469":{"line":3724,"offset":653856,"length":182,"previous":"M21-GAP-00468","next":"M21-GAP-00470"},"M21-GAP-00470":{"line":3725,"offset":654038,"length":182,"previous":"M21-GAP-00469","next":"M21-GAP-00471"},"M21-GAP-00471":{"line":3726,"offset":654220,"length":183,"previous":"M21-GAP-00470","next":"M21-GAP-00472"},"M21-GAP-00472":{"line":3727,"offset":654403,"length":183,"previous":"M21-GAP-00471","next":"M21-GAP-00473"},"M21-GAP-00473":{"line":3728,"offset":654586,"length":183,"previous":"M21-GAP-00472","next":"M21-GAP-00474"},"M21-GAP-00474":{"line":3729,"offset":654769,"length":183,"previous":"M21-GAP-00473","next":"M21-GAP-00475"},"M21-GAP-00475":{"line":3730,"offset":654952,"length":183,"previous":"M21-GAP-00474","next":"M21-GAP-00476"},"M21-GAP-00476":{"line":3731,"offset":655135,"length":183,"previous":"M21-GAP-00475","next":"M21-GAP-00477"},"M21-GAP-00477":{"line":3732,"offset":655318,"length":183,"previous":"M21-GAP-00476","next":"M21-GAP-00478"},"M21-GAP-00478":{"line":3733,"offset":655501,"length":183,"previous":"M21-GAP-00477","next":"M21-GAP-00479"},"M21-GAP-00479":{"line":3734,"offset":655684,"length":183,"previous":"M21-GAP-00478","next":"M21-GAP-00480"},"M21-GAP-00480":{"line":3735,"offset":655867,"length":183,"previous":"M21-GAP-00479","next":"M21-GAP-00481"},"M21-GAP-00481":{"line":3736,"offset":656050,"length":182,"previous":"M21-GAP-00480","next":"M21-GAP-00482"},"M21-GAP-00482":{"line":3737,"offset":656232,"length":183,"previous":"M21-GAP-00481","next":"M21-GAP-00483"},"M21-GAP-00483":{"line":3738,"offset":656415,"length":183,"previous":"M21-GAP-00482","next":"M21-GAP-00484"},"M21-GAP-00484":{"line":3739,"offset":656598,"length":183,"previous":"M21-GAP-00483","next":"M21-GAP-00485"},"M21-GAP-00485":{"line":3740,"offset":656781,"length":183,"previous":"M21-GAP-00484","next":"M21-GAP-00486"},"M21-GAP-00486":{"line":3741,"offset":656964,"length":183,"previous":"M21-GAP-00485","next":"M21-GAP-00487"},"M21-GAP-00487":{"line":3742,"offset":657147,"length":183,"previous":"M21-GAP-00486","next":"M21-GAP-00488"},"M21-GAP-00488":{"line":3743,"offset":657330,"length":183,"previous":"M21-GAP-00487","next":"M21-GAP-00489"},"M21-GAP-00489":{"line":3744,"offset":657513,"length":183,"previous":"M21-GAP-00488","next":"M21-GAP-00490"},"M21-GAP-00490":{"line":3745,"offset":657696,"length":183,"previous":"M21-GAP-00489","next":"M21-GAP-00491"},"M21-GAP-00491":{"line":3746,"offset":657879,"length":183,"previous":"M21-GAP-00490","next":"M21-GAP-00492"},"M21-GAP-00492":{"line":3747,"offset":658062,"length":182,"previous":"M21-GAP-00491","next":"M21-GAP-00493"},"M21-GAP-00493":{"line":3748,"offset":658244,"length":182,"previous":"M21-GAP-00492","next":"M21-GAP-00494"},"M21-GAP-00494":{"line":3749,"offset":658426,"length":182,"previous":"M21-GAP-00493","next":"M21-GAP-00495"},"M21-GAP-00495":{"line":3750,"offset":658608,"length":182,"previous":"M21-GAP-00494","next":"M21-GAP-00496"},"M21-GAP-00496":{"line":3751,"offset":658790,"length":182,"previous":"M21-GAP-00495","next":"M21-GAP-00497"},"M21-GAP-00497":{"line":3752,"offset":658972,"length":182,"previous":"M21-GAP-00496","next":"M21-GAP-00498"},"M21-GAP-00498":{"line":3753,"offset":659154,"length":182,"previous":"M21-GAP-00497","next":"M21-GAP-00499"},"M21-GAP-00499":{"line":3754,"offset":659336,"length":194,"previous":"M21-GAP-00498","next":"M21-GAP-00500"},"M21-GAP-00500":{"line":3755,"offset":659530,"length":194,"previous":"M21-GAP-00499","next":"M21-GAP-00501"},"M21-GAP-00501":{"line":3756,"offset":659724,"length":194,"previous":"M21-GAP-00500","next":"M21-GAP-00502"},"M21-GAP-00502":{"line":3757,"offset":659918,"length":194,"previous":"M21-GAP-00501","next":"M21-GAP-00503"},"M21-GAP-00503":{"line":3758,"offset":660112,"length":184,"previous":"M21-GAP-00502","next":"M21-GAP-00504"},"M21-GAP-00504":{"line":3759,"offset":660296,"length":184,"previous":"M21-GAP-00503","next":"M21-GAP-00505"},"M21-GAP-00505":{"line":3760,"offset":660480,"length":185,"previous":"M21-GAP-00504","next":"M21-GAP-00506"},"M21-GAP-00506":{"line":3761,"offset":660665,"length":185,"previous":"M21-GAP-00505","next":"M21-GAP-00507"},"M21-GAP-00507":{"line":3762,"offset":660850,"length":185,"previous":"M21-GAP-00506","next":"M21-GAP-00508"},"M21-GAP-00508":{"line":3763,"offset":661035,"length":185,"previous":"M21-GAP-00507","next":"M21-GAP-00509"},"M21-GAP-00509":{"line":3764,"offset":661220,"length":185,"previous":"M21-GAP-00508","next":"M21-GAP-00510"},"M21-GAP-00510":{"line":3765,"offset":661405,"length":185,"previous":"M21-GAP-00509","next":"M21-GAP-00511"},"M21-GAP-00511":{"line":3766,"offset":661590,"length":185,"previous":"M21-GAP-00510","next":"M21-GAP-00512"},"M21-GAP-00512":{"line":3767,"offset":661775,"length":185,"previous":"M21-GAP-00511","next":"M21-GAP-00513"},"M21-GAP-00513":{"line":3768,"offset":661960,"length":185,"previous":"M21-GAP-00512","next":"M21-GAP-00514"},"M21-GAP-00514":{"line":3769,"offset":662145,"length":185,"previous":"M21-GAP-00513","next":"M21-GAP-00515"},"M21-GAP-00515":{"line":3770,"offset":662330,"length":184,"previous":"M21-GAP-00514","next":"M21-GAP-00516"},"M21-GAP-00516":{"line":3771,"offset":662514,"length":185,"previous":"M21-GAP-00515","next":"M21-GAP-00517"},"M21-GAP-00517":{"line":3772,"offset":662699,"length":185,"previous":"M21-GAP-00516","next":"M21-GAP-00518"},"M21-GAP-00518":{"line":3773,"offset":662884,"length":185,"previous":"M21-GAP-00517","next":"M21-GAP-00519"},"M21-GAP-00519":{"line":3774,"offset":663069,"length":185,"previous":"M21-GAP-00518","next":"M21-GAP-00520"},"M21-GAP-00520":{"line":3775,"offset":663254,"length":185,"previous":"M21-GAP-00519","next":"M21-GAP-00521"},"M21-GAP-00521":{"line":3776,"offset":663439,"length":185,"previous":"M21-GAP-00520","next":"M21-GAP-00522"},"M21-GAP-00522":{"line":3777,"offset":663624,"length":185,"previous":"M21-GAP-00521","next":"M21-GAP-00523"},"M21-GAP-00523":{"line":3778,"offset":663809,"length":185,"previous":"M21-GAP-00522","next":"M21-GAP-00524"},"M21-GAP-00524":{"line":3779,"offset":663994,"length":185,"previous":"M21-GAP-00523","next":"M21-GAP-00525"},"M21-GAP-00525":{"line":3780,"offset":664179,"length":185,"previous":"M21-GAP-00524","next":"M21-GAP-00526"},"M21-GAP-00526":{"line":3781,"offset":664364,"length":184,"previous":"M21-GAP-00525","next":"M21-GAP-00527"},"M21-GAP-00527":{"line":3782,"offset":664548,"length":185,"previous":"M21-GAP-00526","next":"M21-GAP-00528"},"M21-GAP-00528":{"line":3783,"offset":664733,"length":185,"previous":"M21-GAP-00527","next":"M21-GAP-00529"},"M21-GAP-00529":{"line":3784,"offset":664918,"length":185,"previous":"M21-GAP-00528","next":"M21-GAP-00530"},"M21-GAP-00530":{"line":3785,"offset":665103,"length":185,"previous":"M21-GAP-00529","next":"M21-GAP-00531"},"M21-GAP-00531":{"line":3786,"offset":665288,"length":185,"previous":"M21-GAP-00530","next":"M21-GAP-00532"},"M21-GAP-00532":{"line":3787,"offset":665473,"length":185,"previous":"M21-GAP-00531","next":"M21-GAP-00533"},"M21-GAP-00533":{"line":3788,"offset":665658,"length":185,"previous":"M21-GAP-00532","next":"M21-GAP-00534"},"M21-GAP-00534":{"line":3789,"offset":665843,"length":185,"previous":"M21-GAP-00533","next":"M21-GAP-00535"},"M21-GAP-00535":{"line":3790,"offset":666028,"length":185,"previous":"M21-GAP-00534","next":"M21-GAP-00536"},"M21-GAP-00536":{"line":3791,"offset":666213,"length":185,"previous":"M21-GAP-00535","next":"M21-GAP-00537"},"M21-GAP-00537":{"line":3792,"offset":666398,"length":184,"previous":"M21-GAP-00536","next":"M21-GAP-00538"},"M21-GAP-00538":{"line":3793,"offset":666582,"length":185,"previous":"M21-GAP-00537","next":"M21-GAP-00539"},"M21-GAP-00539":{"line":3794,"offset":666767,"length":185,"previous":"M21-GAP-00538","next":"M21-GAP-00540"},"M21-GAP-00540":{"line":3795,"offset":666952,"length":185,"previous":"M21-GAP-00539","next":"M21-GAP-00541"},"M21-GAP-00541":{"line":3796,"offset":667137,"length":185,"previous":"M21-GAP-00540","next":"M21-GAP-00542"},"M21-GAP-00542":{"line":3797,"offset":667322,"length":185,"previous":"M21-GAP-00541","next":"M21-GAP-00543"},"M21-GAP-00543":{"line":3798,"offset":667507,"length":185,"previous":"M21-GAP-00542","next":"M21-GAP-00544"},"M21-GAP-00544":{"line":3799,"offset":667692,"length":185,"previous":"M21-GAP-00543","next":"M21-GAP-00545"},"M21-GAP-00545":{"line":3800,"offset":667877,"length":185,"previous":"M21-GAP-00544","next":"M21-GAP-00546"},"M21-GAP-00546":{"line":3801,"offset":668062,"length":185,"previous":"M21-GAP-00545","next":"M21-GAP-00547"},"M21-GAP-00547":{"line":3802,"offset":668247,"length":185,"previous":"M21-GAP-00546","next":"M21-GAP-00548"},"M21-GAP-00548":{"line":3803,"offset":668432,"length":184,"previous":"M21-GAP-00547","next":"M21-GAP-00549"},"M21-GAP-00549":{"line":3804,"offset":668616,"length":185,"previous":"M21-GAP-00548","next":"M21-GAP-00550"},"M21-GAP-00550":{"line":3805,"offset":668801,"length":185,"previous":"M21-GAP-00549","next":"M21-GAP-00551"},"M21-GAP-00551":{"line":3806,"offset":668986,"length":185,"previous":"M21-GAP-00550","next":"M21-GAP-00552"},"M21-GAP-00552":{"line":3807,"offset":669171,"length":185,"previous":"M21-GAP-00551","next":"M21-GAP-00553"},"M21-GAP-00553":{"line":3808,"offset":669356,"length":185,"previous":"M21-GAP-00552","next":"M21-GAP-00554"},"M21-GAP-00554":{"line":3809,"offset":669541,"length":185,"previous":"M21-GAP-00553","next":"M21-GAP-00555"},"M21-GAP-00555":{"line":3810,"offset":669726,"length":185,"previous":"M21-GAP-00554","next":"M21-GAP-00556"},"M21-GAP-00556":{"line":3811,"offset":669911,"length":185,"previous":"M21-GAP-00555","next":"M21-GAP-00557"},"M21-GAP-00557":{"line":3812,"offset":670096,"length":185,"previous":"M21-GAP-00556","next":"M21-GAP-00558"},"M21-GAP-00558":{"line":3813,"offset":670281,"length":185,"previous":"M21-GAP-00557","next":"M21-GAP-00559"},"M21-GAP-00559":{"line":3814,"offset":670466,"length":184,"previous":"M21-GAP-00558","next":"M21-GAP-00560"},"M21-GAP-00560":{"line":3815,"offset":670650,"length":185,"previous":"M21-GAP-00559","next":"M21-GAP-00561"},"M21-GAP-00561":{"line":3816,"offset":670835,"length":185,"previous":"M21-GAP-00560","next":"M21-GAP-00562"},"M21-GAP-00562":{"line":3817,"offset":671020,"length":185,"previous":"M21-GAP-00561","next":"M21-GAP-00563"},"M21-GAP-00563":{"line":3818,"offset":671205,"length":185,"previous":"M21-GAP-00562","next":"M21-GAP-00564"},"M21-GAP-00564":{"line":3819,"offset":671390,"length":185,"previous":"M21-GAP-00563","next":"M21-GAP-00565"},"M21-GAP-00565":{"line":3820,"offset":671575,"length":185,"previous":"M21-GAP-00564","next":"M21-GAP-00566"},"M21-GAP-00566":{"line":3821,"offset":671760,"length":185,"previous":"M21-GAP-00565","next":"M21-GAP-00567"},"M21-GAP-00567":{"line":3822,"offset":671945,"length":185,"previous":"M21-GAP-00566","next":"M21-GAP-00568"},"M21-GAP-00568":{"line":3823,"offset":672130,"length":185,"previous":"M21-GAP-00567","next":"M21-GAP-00569"},"M21-GAP-00569":{"line":3824,"offset":672315,"length":185,"previous":"M21-GAP-00568","next":"M21-GAP-00570"},"M21-GAP-00570":{"line":3825,"offset":672500,"length":184,"previous":"M21-GAP-00569","next":"M21-GAP-00571"},"M21-GAP-00571":{"line":3826,"offset":672684,"length":185,"previous":"M21-GAP-00570","next":"M21-GAP-00572"},"M21-GAP-00572":{"line":3827,"offset":672869,"length":185,"previous":"M21-GAP-00571","next":"M21-GAP-00573"},"M21-GAP-00573":{"line":3828,"offset":673054,"length":185,"previous":"M21-GAP-00572","next":"M21-GAP-00574"},"M21-GAP-00574":{"line":3829,"offset":673239,"length":185,"previous":"M21-GAP-00573","next":"M21-GAP-00575"},"M21-GAP-00575":{"line":3830,"offset":673424,"length":185,"previous":"M21-GAP-00574","next":"M21-GAP-00576"},"M21-GAP-00576":{"line":3831,"offset":673609,"length":185,"previous":"M21-GAP-00575","next":"M21-GAP-00577"},"M21-GAP-00577":{"line":3832,"offset":673794,"length":184,"previous":"M21-GAP-00576","next":"M21-GAP-00578"},"M21-GAP-00578":{"line":3833,"offset":673978,"length":184,"previous":"M21-GAP-00577","next":"M21-GAP-00579"},"M21-GAP-00579":{"line":3834,"offset":674162,"length":190,"previous":"M21-GAP-00578","next":"M21-GAP-00580"},"M21-GAP-00580":{"line":3835,"offset":674352,"length":190,"previous":"M21-GAP-00579","next":"M21-GAP-00581"},"M21-GAP-00581":{"line":3836,"offset":674542,"length":191,"previous":"M21-GAP-00580","next":"M21-GAP-00582"},"M21-GAP-00582":{"line":3837,"offset":674733,"length":191,"previous":"M21-GAP-00581","next":"M21-GAP-00583"},"M21-GAP-00583":{"line":3838,"offset":674924,"length":191,"previous":"M21-GAP-00582","next":"M21-GAP-00584"},"M21-GAP-00584":{"line":3839,"offset":675115,"length":191,"previous":"M21-GAP-00583","next":"M21-GAP-00585"},"M21-GAP-00585":{"line":3840,"offset":675306,"length":191,"previous":"M21-GAP-00584","next":"M21-GAP-00586"},"M21-GAP-00586":{"line":3841,"offset":675497,"length":191,"previous":"M21-GAP-00585","next":"M21-GAP-00587"},"M21-GAP-00587":{"line":3842,"offset":675688,"length":191,"previous":"M21-GAP-00586","next":"M21-GAP-00588"},"M21-GAP-00588":{"line":3843,"offset":675879,"length":191,"previous":"M21-GAP-00587","next":"M21-GAP-00589"},"M21-GAP-00589":{"line":3844,"offset":676070,"length":191,"previous":"M21-GAP-00588","next":"M21-GAP-00590"},"M21-GAP-00590":{"line":3845,"offset":676261,"length":191,"previous":"M21-GAP-00589","next":"M21-GAP-00591"},"M21-GAP-00591":{"line":3846,"offset":676452,"length":190,"previous":"M21-GAP-00590","next":"M21-GAP-00592"},"M21-GAP-00592":{"line":3847,"offset":676642,"length":191,"previous":"M21-GAP-00591","next":"M21-GAP-00593"},"M21-GAP-00593":{"line":3848,"offset":676833,"length":191,"previous":"M21-GAP-00592","next":"M21-GAP-00594"},"M21-GAP-00594":{"line":3849,"offset":677024,"length":191,"previous":"M21-GAP-00593","next":"M21-GAP-00595"},"M21-GAP-00595":{"line":3850,"offset":677215,"length":191,"previous":"M21-GAP-00594","next":"M21-GAP-00596"},"M21-GAP-00596":{"line":3851,"offset":677406,"length":190,"previous":"M21-GAP-00595","next":"M21-GAP-00597"},"M21-GAP-00597":{"line":3852,"offset":677596,"length":190,"previous":"M21-GAP-00596","next":"M21-GAP-00598"},"M21-GAP-00598":{"line":3853,"offset":677786,"length":190,"previous":"M21-GAP-00597","next":"M21-GAP-00599"},"M21-GAP-00599":{"line":3854,"offset":677976,"length":190,"previous":"M21-GAP-00598","next":"M21-GAP-00600"},"M21-GAP-00600":{"line":3855,"offset":678166,"length":190,"previous":"M21-GAP-00599","next":"M21-GAP-00601"},"M21-GAP-00601":{"line":3856,"offset":678356,"length":190,"previous":"M21-GAP-00600","next":"M21-GAP-00602"},"M21-GAP-00602":{"line":3857,"offset":678546,"length":190,"previous":"M21-GAP-00601","next":"M21-GAP-00603"},"M21-GAP-00603":{"line":3858,"offset":678736,"length":189,"previous":"M21-GAP-00602","next":"M21-GAP-00604"},"M21-GAP-00604":{"line":3859,"offset":678925,"length":177,"previous":"M21-GAP-00603","next":"M21-GAP-00605"},"M21-GAP-00605":{"line":3860,"offset":679102,"length":177,"previous":"M21-GAP-00604","next":"M21-GAP-00606"},"M21-GAP-00606":{"line":3861,"offset":679279,"length":178,"previous":"M21-GAP-00605","next":"M21-GAP-00607"},"M21-GAP-00607":{"line":3862,"offset":679457,"length":178,"previous":"M21-GAP-00606","next":"M21-GAP-00608"},"M21-GAP-00608":{"line":3863,"offset":679635,"length":178,"previous":"M21-GAP-00607","next":"M21-GAP-00609"},"M21-GAP-00609":{"line":3864,"offset":679813,"length":178,"previous":"M21-GAP-00608","next":"M21-GAP-00610"},"M21-GAP-00610":{"line":3865,"offset":679991,"length":177,"previous":"M21-GAP-00609","next":"M21-GAP-00611"},"M21-GAP-00611":{"line":3866,"offset":680168,"length":177,"previous":"M21-GAP-00610","next":"M21-GAP-00612"},"M21-GAP-00612":{"line":3867,"offset":680345,"length":177,"previous":"M21-GAP-00611","next":"M21-GAP-00613"},"M21-GAP-00613":{"line":3868,"offset":680522,"length":177,"previous":"M21-GAP-00612","next":"M21-GAP-00614"},"M21-GAP-00614":{"line":3869,"offset":680699,"length":177,"previous":"M21-GAP-00613","next":"M21-GAP-00615"},"M21-GAP-00615":{"line":3870,"offset":680876,"length":177,"previous":"M21-GAP-00614","next":"M21-GAP-00616"},"M21-GAP-00616":{"line":3871,"offset":681053,"length":177,"previous":"M21-GAP-00615","next":"M21-GAP-00617"},"M21-GAP-00617":{"line":3872,"offset":681230,"length":177,"previous":"M21-GAP-00616","next":"M21-GAP-00618"},"M21-GAP-00618":{"line":3873,"offset":681407,"length":176,"previous":"M21-GAP-00617","next":"M21-GAP-00619"},"M21-GAP-00619":{"line":3874,"offset":681583,"length":176,"previous":"M21-GAP-00618","next":"M21-GAP-00620"},"M21-GAP-00620":{"line":3875,"offset":681759,"length":177,"previous":"M21-GAP-00619","next":"M21-GAP-00621"},"M21-GAP-00621":{"line":3876,"offset":681936,"length":177,"previous":"M21-GAP-00620","next":"M21-GAP-00622"},"M21-GAP-00622":{"line":3877,"offset":682113,"length":177,"previous":"M21-GAP-00621","next":"M21-GAP-00623"},"M21-GAP-00623":{"line":3878,"offset":682290,"length":177,"previous":"M21-GAP-00622","next":"M21-GAP-00624"},"M21-GAP-00624":{"line":3879,"offset":682467,"length":177,"previous":"M21-GAP-00623","next":"M21-GAP-00625"},"M21-GAP-00625":{"line":3880,"offset":682644,"length":177,"previous":"M21-GAP-00624","next":"M21-GAP-00626"},"M21-GAP-00626":{"line":3881,"offset":682821,"length":177,"previous":"M21-GAP-00625","next":"M21-GAP-00627"},"M21-GAP-00627":{"line":3882,"offset":682998,"length":177,"previous":"M21-GAP-00626","next":"M21-GAP-00628"},"M21-GAP-00628":{"line":3883,"offset":683175,"length":177,"previous":"M21-GAP-00627","next":"M21-GAP-00629"},"M21-GAP-00629":{"line":3884,"offset":683352,"length":177,"previous":"M21-GAP-00628","next":"M21-GAP-00630"},"M21-GAP-00630":{"line":3885,"offset":683529,"length":176,"previous":"M21-GAP-00629","next":"M21-GAP-00631"},"M21-GAP-00631":{"line":3886,"offset":683705,"length":177,"previous":"M21-GAP-00630","next":"M21-GAP-00632"},"M21-GAP-00632":{"line":3887,"offset":683882,"length":177,"previous":"M21-GAP-00631","next":"M21-GAP-00633"},"M21-GAP-00633":{"line":3888,"offset":684059,"length":177,"previous":"M21-GAP-00632","next":"M21-GAP-00634"},"M21-GAP-00634":{"line":3889,"offset":684236,"length":177,"previous":"M21-GAP-00633","next":"M21-GAP-00635"},"M21-GAP-00635":{"line":3890,"offset":684413,"length":177,"previous":"M21-GAP-00634","next":"M21-GAP-00636"},"M21-GAP-00636":{"line":3891,"offset":684590,"length":177,"previous":"M21-GAP-00635","next":"M21-GAP-00637"},"M21-GAP-00637":{"line":3892,"offset":684767,"length":177,"previous":"M21-GAP-00636","next":"M21-GAP-00638"},"M21-GAP-00638":{"line":3893,"offset":684944,"length":177,"previous":"M21-GAP-00637","next":"M21-GAP-00639"},"M21-GAP-00639":{"line":3894,"offset":685121,"length":177,"previous":"M21-GAP-00638","next":"M21-GAP-00640"},"M21-GAP-00640":{"line":3895,"offset":685298,"length":177,"previous":"M21-GAP-00639","next":"M21-GAP-00641"},"M21-GAP-00641":{"line":3896,"offset":685475,"length":176,"previous":"M21-GAP-00640","next":"M21-GAP-00642"},"M21-GAP-00642":{"line":3897,"offset":685651,"length":177,"previous":"M21-GAP-00641","next":"M21-GAP-00643"},"M21-GAP-00643":{"line":3898,"offset":685828,"length":177,"previous":"M21-GAP-00642","next":"M21-GAP-00644"},"M21-GAP-00644":{"line":3899,"offset":686005,"length":177,"previous":"M21-GAP-00643","next":"M21-GAP-00645"},"M21-GAP-00645":{"line":3900,"offset":686182,"length":177,"previous":"M21-GAP-00644","next":"M21-GAP-00646"},"M21-GAP-00646":{"line":3901,"offset":686359,"length":177,"previous":"M21-GAP-00645","next":"M21-GAP-00647"},"M21-GAP-00647":{"line":3902,"offset":686536,"length":177,"previous":"M21-GAP-00646","next":"M21-GAP-00648"},"M21-GAP-00648":{"line":3903,"offset":686713,"length":177,"previous":"M21-GAP-00647","next":"M21-GAP-00649"},"M21-GAP-00649":{"line":3904,"offset":686890,"length":177,"previous":"M21-GAP-00648","next":"M21-GAP-00650"},"M21-GAP-00650":{"line":3905,"offset":687067,"length":177,"previous":"M21-GAP-00649","next":"M21-GAP-00651"},"M21-GAP-00651":{"line":3906,"offset":687244,"length":177,"previous":"M21-GAP-00650","next":"M21-GAP-00652"},"M21-GAP-00652":{"line":3907,"offset":687421,"length":176,"previous":"M21-GAP-00651","next":"M21-GAP-00653"},"M21-GAP-00653":{"line":3908,"offset":687597,"length":176,"previous":"M21-GAP-00652","next":"M21-GAP-00654"},"M21-GAP-00654":{"line":3909,"offset":687773,"length":176,"previous":"M21-GAP-00653","next":"M21-GAP-00655"},"M21-GAP-00655":{"line":3910,"offset":687949,"length":176,"previous":"M21-GAP-00654","next":"M21-GAP-00656"},"M21-GAP-00656":{"line":3911,"offset":688125,"length":176,"previous":"M21-GAP-00655","next":"M21-GAP-00657"},"M21-GAP-00657":{"line":3912,"offset":688301,"length":176,"previous":"M21-GAP-00656","next":"M21-GAP-00658"},"M21-GAP-00658":{"line":3913,"offset":688477,"length":186,"previous":"M21-GAP-00657","next":"M21-GAP-00659"},"M21-GAP-00659":{"line":3914,"offset":688663,"length":186,"previous":"M21-GAP-00658","next":"M21-GAP-00660"},"M21-GAP-00660":{"line":3915,"offset":688849,"length":186,"previous":"M21-GAP-00659","next":"M21-GAP-00661"},"M21-GAP-00661":{"line":3916,"offset":689035,"length":186,"previous":"M21-GAP-00660","next":"M21-GAP-00662"},"M21-GAP-00662":{"line":3917,"offset":689221,"length":186,"previous":"M21-GAP-00661","next":"M21-GAP-00663"},"M21-GAP-00663":{"line":3918,"offset":689407,"length":172,"previous":"M21-GAP-00662","next":"M21-GAP-00664"},"M21-GAP-00664":{"line":3919,"offset":689579,"length":172,"previous":"M21-GAP-00663","next":"M21-GAP-00665"},"M21-GAP-00665":{"line":3920,"offset":689751,"length":173,"previous":"M21-GAP-00664","next":"M21-GAP-00666"},"M21-GAP-00666":{"line":3921,"offset":689924,"length":173,"previous":"M21-GAP-00665","next":"M21-GAP-00667"},"M21-GAP-00667":{"line":3922,"offset":690097,"length":173,"previous":"M21-GAP-00666","next":"M21-GAP-00668"},"M21-GAP-00668":{"line":3923,"offset":690270,"length":173,"previous":"M21-GAP-00667","next":"M21-GAP-00669"},"M21-GAP-00669":{"line":3924,"offset":690443,"length":173,"previous":"M21-GAP-00668","next":"M21-GAP-00670"},"M21-GAP-00670":{"line":3925,"offset":690616,"length":173,"previous":"M21-GAP-00669","next":"M21-GAP-00671"},"M21-GAP-00671":{"line":3926,"offset":690789,"length":173,"previous":"M21-GAP-00670","next":"M21-GAP-00672"},"M21-GAP-00672":{"line":3927,"offset":690962,"length":173,"previous":"M21-GAP-00671","next":"M21-GAP-00673"},"M21-GAP-00673":{"line":3928,"offset":691135,"length":173,"previous":"M21-GAP-00672","next":"M21-GAP-00674"},"M21-GAP-00674":{"line":3929,"offset":691308,"length":173,"previous":"M21-GAP-00673","next":"M21-GAP-00675"},"M21-GAP-00675":{"line":3930,"offset":691481,"length":172,"previous":"M21-GAP-00674","next":"M21-GAP-00676"},"M21-GAP-00676":{"line":3931,"offset":691653,"length":173,"previous":"M21-GAP-00675","next":"M21-GAP-00677"},"M21-GAP-00677":{"line":3932,"offset":691826,"length":173,"previous":"M21-GAP-00676","next":"M21-GAP-00678"},"M21-GAP-00678":{"line":3933,"offset":691999,"length":173,"previous":"M21-GAP-00677","next":"M21-GAP-00679"},"M21-GAP-00679":{"line":3934,"offset":692172,"length":173,"previous":"M21-GAP-00678","next":"M21-GAP-00680"},"M21-GAP-00680":{"line":3935,"offset":692345,"length":173,"previous":"M21-GAP-00679","next":"M21-GAP-00681"},"M21-GAP-00681":{"line":3936,"offset":692518,"length":173,"previous":"M21-GAP-00680","next":"M21-GAP-00682"},"M21-GAP-00682":{"line":3937,"offset":692691,"length":173,"previous":"M21-GAP-00681","next":"M21-GAP-00683"},"M21-GAP-00683":{"line":3938,"offset":692864,"length":173,"previous":"M21-GAP-00682","next":"M21-GAP-00684"},"M21-GAP-00684":{"line":3939,"offset":693037,"length":173,"previous":"M21-GAP-00683","next":"M21-GAP-00685"},"M21-GAP-00685":{"line":3940,"offset":693210,"length":173,"previous":"M21-GAP-00684","next":"M21-GAP-00686"},"M21-GAP-00686":{"line":3941,"offset":693383,"length":172,"previous":"M21-GAP-00685","next":"M21-GAP-00687"},"M21-GAP-00687":{"line":3942,"offset":693555,"length":173,"previous":"M21-GAP-00686","next":"M21-GAP-00688"},"M21-GAP-00688":{"line":3943,"offset":693728,"length":173,"previous":"M21-GAP-00687","next":"M21-GAP-00689"},"M21-GAP-00689":{"line":3944,"offset":693901,"length":173,"previous":"M21-GAP-00688","next":"M21-GAP-00690"},"M21-GAP-00690":{"line":3945,"offset":694074,"length":173,"previous":"M21-GAP-00689","next":"M21-GAP-00691"},"M21-GAP-00691":{"line":3946,"offset":694247,"length":173,"previous":"M21-GAP-00690","next":"M21-GAP-00692"},"M21-GAP-00692":{"line":3947,"offset":694420,"length":173,"previous":"M21-GAP-00691","next":"M21-GAP-00693"},"M21-GAP-00693":{"line":3948,"offset":694593,"length":173,"previous":"M21-GAP-00692","next":"M21-GAP-00694"},"M21-GAP-00694":{"line":3949,"offset":694766,"length":173,"previous":"M21-GAP-00693","next":"M21-GAP-00695"},"M21-GAP-00695":{"line":3950,"offset":694939,"length":173,"previous":"M21-GAP-00694","next":"M21-GAP-00696"},"M21-GAP-00696":{"line":3951,"offset":695112,"length":173,"previous":"M21-GAP-00695","next":"M21-GAP-00697"},"M21-GAP-00697":{"line":3952,"offset":695285,"length":172,"previous":"M21-GAP-00696","next":"M21-GAP-00698"},"M21-GAP-00698":{"line":3953,"offset":695457,"length":173,"previous":"M21-GAP-00697","next":"M21-GAP-00699"},"M21-GAP-00699":{"line":3954,"offset":695630,"length":173,"previous":"M21-GAP-00698","next":"M21-GAP-00700"},"M21-GAP-00700":{"line":3955,"offset":695803,"length":173,"previous":"M21-GAP-00699","next":"M21-GAP-00701"},"M21-GAP-00701":{"line":3956,"offset":695976,"length":173,"previous":"M21-GAP-00700","next":"M21-GAP-00702"},"M21-GAP-00702":{"line":3957,"offset":696149,"length":173,"previous":"M21-GAP-00701","next":"M21-GAP-00703"},"M21-GAP-00703":{"line":3958,"offset":696322,"length":172,"previous":"M21-GAP-00702","next":"M21-GAP-00704"},"M21-GAP-00704":{"line":3959,"offset":696494,"length":172,"previous":"M21-GAP-00703","next":"M21-GAP-00705"},"M21-GAP-00705":{"line":3960,"offset":696666,"length":172,"previous":"M21-GAP-00704","next":"M21-GAP-00706"},"M21-GAP-00706":{"line":3961,"offset":696838,"length":172,"previous":"M21-GAP-00705","next":"M21-GAP-00707"},"M21-GAP-00707":{"line":3962,"offset":697010,"length":172,"previous":"M21-GAP-00706","next":"M21-GAP-00708"},"M21-GAP-00708":{"line":3963,"offset":697182,"length":173,"previous":"M21-GAP-00707","next":"M21-GAP-00709"},"M21-GAP-00709":{"line":3964,"offset":697355,"length":173,"previous":"M21-GAP-00708","next":"M21-GAP-00710"},"M21-GAP-00710":{"line":3965,"offset":697528,"length":174,"previous":"M21-GAP-00709","next":"M21-GAP-00711"},"M21-GAP-00711":{"line":3966,"offset":697702,"length":174,"previous":"M21-GAP-00710","next":"M21-GAP-00712"},"M21-GAP-00712":{"line":3967,"offset":697876,"length":174,"previous":"M21-GAP-00711","next":"M21-GAP-00713"},"M21-GAP-00713":{"line":3968,"offset":698050,"length":174,"previous":"M21-GAP-00712","next":"M21-GAP-00714"},"M21-GAP-00714":{"line":3969,"offset":698224,"length":174,"previous":"M21-GAP-00713","next":"M21-GAP-00715"},"M21-GAP-00715":{"line":3970,"offset":698398,"length":174,"previous":"M21-GAP-00714","next":"M21-GAP-00716"},"M21-GAP-00716":{"line":3971,"offset":698572,"length":174,"previous":"M21-GAP-00715","next":"M21-GAP-00717"},"M21-GAP-00717":{"line":3972,"offset":698746,"length":174,"previous":"M21-GAP-00716","next":"M21-GAP-00718"},"M21-GAP-00718":{"line":3973,"offset":698920,"length":174,"previous":"M21-GAP-00717","next":"M21-GAP-00719"},"M21-GAP-00719":{"line":3974,"offset":699094,"length":174,"previous":"M21-GAP-00718","next":"M21-GAP-00720"},"M21-GAP-00720":{"line":3975,"offset":699268,"length":173,"previous":"M21-GAP-00719","next":"M21-GAP-00721"},"M21-GAP-00721":{"line":3976,"offset":699441,"length":174,"previous":"M21-GAP-00720","next":"M21-GAP-00722"},"M21-GAP-00722":{"line":3977,"offset":699615,"length":174,"previous":"M21-GAP-00721","next":"M21-GAP-00723"},"M21-GAP-00723":{"line":3978,"offset":699789,"length":174,"previous":"M21-GAP-00722","next":"M21-GAP-00724"},"M21-GAP-00724":{"line":3979,"offset":699963,"length":174,"previous":"M21-GAP-00723","next":"M21-GAP-00725"},"M21-GAP-00725":{"line":3980,"offset":700137,"length":174,"previous":"M21-GAP-00724","next":"M21-GAP-00726"},"M21-GAP-00726":{"line":3981,"offset":700311,"length":174,"previous":"M21-GAP-00725","next":"M21-GAP-00727"},"M21-GAP-00727":{"line":3982,"offset":700485,"length":174,"previous":"M21-GAP-00726","next":"M21-GAP-00728"},"M21-GAP-00728":{"line":3983,"offset":700659,"length":174,"previous":"M21-GAP-00727","next":"M21-GAP-00729"},"M21-GAP-00729":{"line":3984,"offset":700833,"length":174,"previous":"M21-GAP-00728","next":"M21-GAP-00730"},"M21-GAP-00730":{"line":3985,"offset":701007,"length":174,"previous":"M21-GAP-00729","next":"M21-GAP-00731"},"M21-GAP-00731":{"line":3986,"offset":701181,"length":173,"previous":"M21-GAP-00730","next":"M21-GAP-00732"},"M21-GAP-00732":{"line":3987,"offset":701354,"length":174,"previous":"M21-GAP-00731","next":"M21-GAP-00733"},"M21-GAP-00733":{"line":3988,"offset":701528,"length":174,"previous":"M21-GAP-00732","next":"M21-GAP-00734"},"M21-GAP-00734":{"line":3989,"offset":701702,"length":174,"previous":"M21-GAP-00733","next":"M21-GAP-00735"},"M21-GAP-00735":{"line":3990,"offset":701876,"length":174,"previous":"M21-GAP-00734","next":"M21-GAP-00736"},"M21-GAP-00736":{"line":3991,"offset":702050,"length":173,"previous":"M21-GAP-00735","next":"M21-GAP-00737"},"M21-GAP-00737":{"line":3992,"offset":702223,"length":173,"previous":"M21-GAP-00736","next":"M21-GAP-00738"},"M21-GAP-00738":{"line":3993,"offset":702396,"length":173,"previous":"M21-GAP-00737","next":"M21-GAP-00739"},"M21-GAP-00739":{"line":3994,"offset":702569,"length":173,"previous":"M21-GAP-00738","next":"M21-GAP-00740"},"M21-GAP-00740":{"line":3995,"offset":702742,"length":173,"previous":"M21-GAP-00739","next":"M21-GAP-00741"},"M21-GAP-00741":{"line":3996,"offset":702915,"length":173,"previous":"M21-GAP-00740","next":"M21-GAP-00742"},"M21-GAP-00742":{"line":3997,"offset":703088,"length":191,"previous":"M21-GAP-00741","next":"M21-GAP-00743"},"M21-GAP-00743":{"line":3998,"offset":703279,"length":191,"previous":"M21-GAP-00742","next":"M21-GAP-00744"},"M21-GAP-00744":{"line":3999,"offset":703470,"length":192,"previous":"M21-GAP-00743","next":"M21-GAP-00745"},"M21-GAP-00745":{"line":4000,"offset":703662,"length":192,"previous":"M21-GAP-00744","next":"M21-GAP-00746"},"M21-GAP-00746":{"line":4001,"offset":703854,"length":192,"previous":"M21-GAP-00745","next":"M21-GAP-00747"},"M21-GAP-00747":{"line":4002,"offset":704046,"length":192,"previous":"M21-GAP-00746","next":"M21-GAP-00748"},"M21-GAP-00748":{"line":4003,"offset":704238,"length":191,"previous":"M21-GAP-00747","next":"M21-GAP-00749"},"M21-GAP-00749":{"line":4004,"offset":704429,"length":191,"previous":"M21-GAP-00748","next":"M21-GAP-00750"},"M21-GAP-00750":{"line":4005,"offset":704620,"length":191,"previous":"M21-GAP-00749","next":"M21-GAP-00751"},"M21-GAP-00751":{"line":4006,"offset":704811,"length":191,"previous":"M21-GAP-00750","next":"M21-GAP-00752"},"M21-GAP-00752":{"line":4007,"offset":705002,"length":191,"previous":"M21-GAP-00751","next":"M21-GAP-00753"},"M21-GAP-00753":{"line":4008,"offset":705193,"length":191,"previous":"M21-GAP-00752","next":"M21-GAP-00754"},"M21-GAP-00754":{"line":4009,"offset":705384,"length":191,"previous":"M21-GAP-00753","next":"M21-GAP-00755"},"M21-GAP-00755":{"line":4010,"offset":705575,"length":191,"previous":"M21-GAP-00754","next":"M21-GAP-00756"},"M21-GAP-00756":{"line":4011,"offset":705766,"length":195,"previous":"M21-GAP-00755","next":"M21-GAP-00757"},"M21-GAP-00757":{"line":4012,"offset":705961,"length":195,"previous":"M21-GAP-00756","next":"M21-GAP-00758"},"M21-GAP-00758":{"line":4013,"offset":706156,"length":195,"previous":"M21-GAP-00757","next":"M21-GAP-00759"},"M21-GAP-00759":{"line":4014,"offset":706351,"length":187,"previous":"M21-GAP-00758","next":"M21-GAP-00760"},"M21-GAP-00760":{"line":4015,"offset":706538,"length":187,"previous":"M21-GAP-00759","next":"M21-GAP-00761"},"M21-GAP-00761":{"line":4016,"offset":706725,"length":188,"previous":"M21-GAP-00760","next":"M21-GAP-00762"},"M21-GAP-00762":{"line":4017,"offset":706913,"length":188,"previous":"M21-GAP-00761","next":"M21-GAP-00763"},"M21-GAP-00763":{"line":4018,"offset":707101,"length":188,"previous":"M21-GAP-00762","next":"M21-GAP-00764"},"M21-GAP-00764":{"line":4019,"offset":707289,"length":188,"previous":"M21-GAP-00763","next":"M21-GAP-00765"},"M21-GAP-00765":{"line":4020,"offset":707477,"length":188,"previous":"M21-GAP-00764","next":"M21-GAP-00766"},"M21-GAP-00766":{"line":4021,"offset":707665,"length":188,"previous":"M21-GAP-00765","next":"M21-GAP-00767"},"M21-GAP-00767":{"line":4022,"offset":707853,"length":188,"previous":"M21-GAP-00766","next":"M21-GAP-00768"},"M21-GAP-00768":{"line":4023,"offset":708041,"length":188,"previous":"M21-GAP-00767","next":"M21-GAP-00769"},"M21-GAP-00769":{"line":4024,"offset":708229,"length":188,"previous":"M21-GAP-00768","next":"M21-GAP-00770"},"M21-GAP-00770":{"line":4025,"offset":708417,"length":188,"previous":"M21-GAP-00769","next":"M21-GAP-00771"},"M21-GAP-00771":{"line":4026,"offset":708605,"length":187,"previous":"M21-GAP-00770","next":"M21-GAP-00772"},"M21-GAP-00772":{"line":4027,"offset":708792,"length":188,"previous":"M21-GAP-00771","next":"M21-GAP-00773"},"M21-GAP-00773":{"line":4028,"offset":708980,"length":188,"previous":"M21-GAP-00772","next":"M21-GAP-00774"},"M21-GAP-00774":{"line":4029,"offset":709168,"length":188,"previous":"M21-GAP-00773","next":"M21-GAP-00775"},"M21-GAP-00775":{"line":4030,"offset":709356,"length":188,"previous":"M21-GAP-00774","next":"M21-GAP-00776"},"M21-GAP-00776":{"line":4031,"offset":709544,"length":188,"previous":"M21-GAP-00775","next":"M21-GAP-00777"},"M21-GAP-00777":{"line":4032,"offset":709732,"length":188,"previous":"M21-GAP-00776","next":"M21-GAP-00778"},"M21-GAP-00778":{"line":4033,"offset":709920,"length":188,"previous":"M21-GAP-00777","next":"M21-GAP-00779"},"M21-GAP-00779":{"line":4034,"offset":710108,"length":188,"previous":"M21-GAP-00778","next":"M21-GAP-00780"},"M21-GAP-00780":{"line":4035,"offset":710296,"length":188,"previous":"M21-GAP-00779","next":"M21-GAP-00781"},"M21-GAP-00781":{"line":4036,"offset":710484,"length":188,"previous":"M21-GAP-00780","next":"M21-GAP-00782"},"M21-GAP-00782":{"line":4037,"offset":710672,"length":187,"previous":"M21-GAP-00781","next":"M21-GAP-00783"},"M21-GAP-00783":{"line":4038,"offset":710859,"length":188,"previous":"M21-GAP-00782","next":"M21-GAP-00784"},"M21-GAP-00784":{"line":4039,"offset":711047,"length":188,"previous":"M21-GAP-00783","next":"M21-GAP-00785"},"M21-GAP-00785":{"line":4040,"offset":711235,"length":188,"previous":"M21-GAP-00784","next":"M21-GAP-00786"},"M21-GAP-00786":{"line":4041,"offset":711423,"length":188,"previous":"M21-GAP-00785","next":"M21-GAP-00787"},"M21-GAP-00787":{"line":4042,"offset":711611,"length":188,"previous":"M21-GAP-00786","next":"M21-GAP-00788"},"M21-GAP-00788":{"line":4043,"offset":711799,"length":188,"previous":"M21-GAP-00787","next":"M21-GAP-00789"},"M21-GAP-00789":{"line":4044,"offset":711987,"length":188,"previous":"M21-GAP-00788","next":"M21-GAP-00790"},"M21-GAP-00790":{"line":4045,"offset":712175,"length":188,"previous":"M21-GAP-00789","next":"M21-GAP-00791"},"M21-GAP-00791":{"line":4046,"offset":712363,"length":188,"previous":"M21-GAP-00790","next":"M21-GAP-00792"},"M21-GAP-00792":{"line":4047,"offset":712551,"length":188,"previous":"M21-GAP-00791","next":"M21-GAP-00793"},"M21-GAP-00793":{"line":4048,"offset":712739,"length":187,"previous":"M21-GAP-00792","next":"M21-GAP-00794"},"M21-GAP-00794":{"line":4049,"offset":712926,"length":188,"previous":"M21-GAP-00793","next":"M21-GAP-00795"},"M21-GAP-00795":{"line":4050,"offset":713114,"length":188,"previous":"M21-GAP-00794","next":"M21-GAP-00796"},"M21-GAP-00796":{"line":4051,"offset":713302,"length":188,"previous":"M21-GAP-00795","next":"M21-GAP-00797"},"M21-GAP-00797":{"line":4052,"offset":713490,"length":188,"previous":"M21-GAP-00796","next":"M21-GAP-00798"},"M21-GAP-00798":{"line":4053,"offset":713678,"length":188,"previous":"M21-GAP-00797","next":"M21-GAP-00799"},"M21-GAP-00799":{"line":4054,"offset":713866,"length":188,"previous":"M21-GAP-00798","next":"M21-GAP-00800"},"M21-GAP-00800":{"line":4055,"offset":714054,"length":188,"previous":"M21-GAP-00799","next":"M21-GAP-00801"},"M21-GAP-00801":{"line":4056,"offset":714242,"length":188,"previous":"M21-GAP-00800","next":"M21-GAP-00802"},"M21-GAP-00802":{"line":4057,"offset":714430,"length":188,"previous":"M21-GAP-00801","next":"M21-GAP-00803"},"M21-GAP-00803":{"line":4058,"offset":714618,"length":188,"previous":"M21-GAP-00802","next":"M21-GAP-00804"},"M21-GAP-00804":{"line":4059,"offset":714806,"length":187,"previous":"M21-GAP-00803","next":"M21-GAP-00805"},"M21-GAP-00805":{"line":4060,"offset":714993,"length":188,"previous":"M21-GAP-00804","next":"M21-GAP-00806"},"M21-GAP-00806":{"line":4061,"offset":715181,"length":188,"previous":"M21-GAP-00805","next":"M21-GAP-00807"},"M21-GAP-00807":{"line":4062,"offset":715369,"length":188,"previous":"M21-GAP-00806","next":"M21-GAP-00808"},"M21-GAP-00808":{"line":4063,"offset":715557,"length":188,"previous":"M21-GAP-00807","next":"M21-GAP-00809"},"M21-GAP-00809":{"line":4064,"offset":715745,"length":188,"previous":"M21-GAP-00808","next":"M21-GAP-00810"},"M21-GAP-00810":{"line":4065,"offset":715933,"length":188,"previous":"M21-GAP-00809","next":"M21-GAP-00811"},"M21-GAP-00811":{"line":4066,"offset":716121,"length":188,"previous":"M21-GAP-00810","next":"M21-GAP-00812"},"M21-GAP-00812":{"line":4067,"offset":716309,"length":188,"previous":"M21-GAP-00811","next":"M21-GAP-00813"},"M21-GAP-00813":{"line":4068,"offset":716497,"length":188,"previous":"M21-GAP-00812","next":"M21-GAP-00814"},"M21-GAP-00814":{"line":4069,"offset":716685,"length":188,"previous":"M21-GAP-00813","next":"M21-GAP-00815"},"M21-GAP-00815":{"line":4070,"offset":716873,"length":187,"previous":"M21-GAP-00814","next":"M21-GAP-00816"},"M21-GAP-00816":{"line":4071,"offset":717060,"length":188,"previous":"M21-GAP-00815","next":"M21-GAP-00817"},"M21-GAP-00817":{"line":4072,"offset":717248,"length":188,"previous":"M21-GAP-00816","next":"M21-GAP-00818"},"M21-GAP-00818":{"line":4073,"offset":717436,"length":188,"previous":"M21-GAP-00817","next":"M21-GAP-00819"},"M21-GAP-00819":{"line":4074,"offset":717624,"length":188,"previous":"M21-GAP-00818","next":"M21-GAP-00820"},"M21-GAP-00820":{"line":4075,"offset":717812,"length":188,"previous":"M21-GAP-00819","next":"M21-GAP-00821"},"M21-GAP-00821":{"line":4076,"offset":718000,"length":188,"previous":"M21-GAP-00820","next":"M21-GAP-00822"},"M21-GAP-00822":{"line":4077,"offset":718188,"length":188,"previous":"M21-GAP-00821","next":"M21-GAP-00823"},"M21-GAP-00823":{"line":4078,"offset":718376,"length":188,"previous":"M21-GAP-00822","next":"M21-GAP-00824"},"M21-GAP-00824":{"line":4079,"offset":718564,"length":187,"previous":"M21-GAP-00823","next":"M21-GAP-00825"},"M21-GAP-00825":{"line":4080,"offset":718751,"length":187,"previous":"M21-GAP-00824","next":"M21-GAP-00826"},"M21-GAP-00826":{"line":4081,"offset":718938,"length":187,"previous":"M21-GAP-00825","next":"M21-GAP-00827"},"M21-GAP-00827":{"line":4082,"offset":719125,"length":205,"previous":"M21-GAP-00826","next":"M21-GAP-00828"},"M21-GAP-00828":{"line":4083,"offset":719330,"length":205,"previous":"M21-GAP-00827","next":"M21-GAP-00829"},"M21-GAP-00829":{"line":4084,"offset":719535,"length":205,"previous":"M21-GAP-00828","next":"M21-GAP-00830"},"M21-GAP-00830":{"line":4085,"offset":719740,"length":205,"previous":"M21-GAP-00829","next":"M21-GAP-00831"},"M21-GAP-00831":{"line":4086,"offset":719945,"length":205,"previous":"M21-GAP-00830","next":"M21-GAP-00832"},"M21-GAP-00832":{"line":4087,"offset":720150,"length":205,"previous":"M21-GAP-00831","next":"M21-GAP-00833"},"M21-GAP-00833":{"line":4088,"offset":720355,"length":205,"previous":"M21-GAP-00832","next":"M21-GAP-00834"},"M21-GAP-00834":{"line":4089,"offset":720560,"length":187,"previous":"M21-GAP-00833","next":"M21-GAP-00835"},"M21-GAP-00835":{"line":4090,"offset":720747,"length":187,"previous":"M21-GAP-00834","next":"M21-GAP-00836"},"M21-GAP-00836":{"line":4091,"offset":720934,"length":187,"previous":"M21-GAP-00835","next":"M21-GAP-00837"},"M21-GAP-00837":{"line":4092,"offset":721121,"length":187,"previous":"M21-GAP-00836","next":"M21-GAP-00838"},"M21-GAP-00838":{"line":4093,"offset":721308,"length":187,"previous":"M21-GAP-00837","next":"M21-GAP-00839"},"M21-GAP-00839":{"line":4094,"offset":721495,"length":187,"previous":"M21-GAP-00838","next":"M21-GAP-00840"},"M21-GAP-00840":{"line":4095,"offset":721682,"length":187,"previous":"M21-GAP-00839","next":"M21-GAP-00841"},"M21-GAP-00841":{"line":4096,"offset":721869,"length":194,"previous":"M21-GAP-00840","next":"M21-GAP-00842"},"M21-GAP-00842":{"line":4097,"offset":722063,"length":194,"previous":"M21-GAP-00841","next":"M21-GAP-00843"},"M21-GAP-00843":{"line":4098,"offset":722257,"length":194,"previous":"M21-GAP-00842","next":"M21-GAP-00844"},"M21-GAP-00844":{"line":4099,"offset":722451,"length":194,"previous":"M21-GAP-00843","next":"M21-GAP-00845"},"M21-GAP-00845":{"line":4100,"offset":722645,"length":194,"previous":"M21-GAP-00844","next":"M21-GAP-00846"},"M21-GAP-00846":{"line":4101,"offset":722839,"length":194,"previous":"M21-GAP-00845","next":"M21-GAP-00847"},"M21-GAP-00847":{"line":4102,"offset":723033,"length":191,"previous":"M21-GAP-00846","next":"M21-GAP-00848"},"M21-GAP-00848":{"line":4103,"offset":723224,"length":191,"previous":"M21-GAP-00847","next":"M21-GAP-00849"},"M21-GAP-00849":{"line":4104,"offset":723415,"length":192,"previous":"M21-GAP-00848","next":"M21-GAP-00850"},"M21-GAP-00850":{"line":4105,"offset":723607,"length":192,"previous":"M21-GAP-00849","next":"M21-GAP-00851"},"M21-GAP-00851":{"line":4106,"offset":723799,"length":192,"previous":"M21-GAP-00850","next":"M21-GAP-00852"},"M21-GAP-00852":{"line":4107,"offset":723991,"length":192,"previous":"M21-GAP-00851","next":"M21-GAP-00853"},"M21-GAP-00853":{"line":4108,"offset":724183,"length":192,"previous":"M21-GAP-00852","next":"M21-GAP-00854"},"M21-GAP-00854":{"line":4109,"offset":724375,"length":192,"previous":"M21-GAP-00853","next":"M21-GAP-00855"},"M21-GAP-00855":{"line":4110,"offset":724567,"length":192,"previous":"M21-GAP-00854","next":"M21-GAP-00856"},"M21-GAP-00856":{"line":4111,"offset":724759,"length":192,"previous":"M21-GAP-00855","next":"M21-GAP-00857"},"M21-GAP-00857":{"line":4112,"offset":724951,"length":192,"previous":"M21-GAP-00856","next":"M21-GAP-00858"},"M21-GAP-00858":{"line":4113,"offset":725143,"length":192,"previous":"M21-GAP-00857","next":"M21-GAP-00859"},"M21-GAP-00859":{"line":4114,"offset":725335,"length":191,"previous":"M21-GAP-00858","next":"M21-GAP-00860"},"M21-GAP-00860":{"line":4115,"offset":725526,"length":192,"previous":"M21-GAP-00859","next":"M21-GAP-00861"},"M21-GAP-00861":{"line":4116,"offset":725718,"length":192,"previous":"M21-GAP-00860","next":"M21-GAP-00862"},"M21-GAP-00862":{"line":4117,"offset":725910,"length":192,"previous":"M21-GAP-00861","next":"M21-GAP-00863"},"M21-GAP-00863":{"line":4118,"offset":726102,"length":192,"previous":"M21-GAP-00862","next":"M21-GAP-00864"},"M21-GAP-00864":{"line":4119,"offset":726294,"length":192,"previous":"M21-GAP-00863","next":"M21-GAP-00865"},"M21-GAP-00865":{"line":4120,"offset":726486,"length":192,"previous":"M21-GAP-00864","next":"M21-GAP-00866"},"M21-GAP-00866":{"line":4121,"offset":726678,"length":192,"previous":"M21-GAP-00865","next":"M21-GAP-00867"},"M21-GAP-00867":{"line":4122,"offset":726870,"length":192,"previous":"M21-GAP-00866","next":"M21-GAP-00868"},"M21-GAP-00868":{"line":4123,"offset":727062,"length":192,"previous":"M21-GAP-00867","next":"M21-GAP-00869"},"M21-GAP-00869":{"line":4124,"offset":727254,"length":192,"previous":"M21-GAP-00868","next":"M21-GAP-00870"},"M21-GAP-00870":{"line":4125,"offset":727446,"length":191,"previous":"M21-GAP-00869","next":"M21-GAP-00871"},"M21-GAP-00871":{"line":4126,"offset":727637,"length":192,"previous":"M21-GAP-00870","next":"M21-GAP-00872"},"M21-GAP-00872":{"line":4127,"offset":727829,"length":192,"previous":"M21-GAP-00871","next":"M21-GAP-00873"},"M21-GAP-00873":{"line":4128,"offset":728021,"length":191,"previous":"M21-GAP-00872","next":"M21-GAP-00874"},"M21-GAP-00874":{"line":4129,"offset":728212,"length":191,"previous":"M21-GAP-00873","next":"M21-GAP-00875"},"M21-GAP-00875":{"line":4130,"offset":728403,"length":191,"previous":"M21-GAP-00874","next":"M21-GAP-00876"},"M21-GAP-00876":{"line":4131,"offset":728594,"length":191,"previous":"M21-GAP-00875","next":"M21-GAP-00877"},"M21-GAP-00877":{"line":4132,"offset":728785,"length":191,"previous":"M21-GAP-00876","next":"M21-GAP-00878"},"M21-GAP-00878":{"line":4133,"offset":728976,"length":191,"previous":"M21-GAP-00877","next":"M21-GAP-00879"},"M21-GAP-00879":{"line":4134,"offset":729167,"length":186,"previous":"M21-GAP-00878","next":"M21-GAP-00880"},"M21-GAP-00880":{"line":4135,"offset":729353,"length":186,"previous":"M21-GAP-00879","next":"M21-GAP-00881"},"M21-GAP-00881":{"line":4136,"offset":729539,"length":187,"previous":"M21-GAP-00880","next":"M21-GAP-00882"},"M21-GAP-00882":{"line":4137,"offset":729726,"length":187,"previous":"M21-GAP-00881","next":"M21-GAP-00883"},"M21-GAP-00883":{"line":4138,"offset":729913,"length":187,"previous":"M21-GAP-00882","next":"M21-GAP-00884"},"M21-GAP-00884":{"line":4139,"offset":730100,"length":187,"previous":"M21-GAP-00883","next":"M21-GAP-00885"},"M21-GAP-00885":{"line":4140,"offset":730287,"length":187,"previous":"M21-GAP-00884","next":"M21-GAP-00886"},"M21-GAP-00886":{"line":4141,"offset":730474,"length":187,"previous":"M21-GAP-00885","next":"M21-GAP-00887"},"M21-GAP-00887":{"line":4142,"offset":730661,"length":187,"previous":"M21-GAP-00886","next":"M21-GAP-00888"},"M21-GAP-00888":{"line":4143,"offset":730848,"length":187,"previous":"M21-GAP-00887","next":"M21-GAP-00889"},"M21-GAP-00889":{"line":4144,"offset":731035,"length":187,"previous":"M21-GAP-00888","next":"M21-GAP-00890"},"M21-GAP-00890":{"line":4145,"offset":731222,"length":187,"previous":"M21-GAP-00889","next":"M21-GAP-00891"},"M21-GAP-00891":{"line":4146,"offset":731409,"length":186,"previous":"M21-GAP-00890","next":"M21-GAP-00892"},"M21-GAP-00892":{"line":4147,"offset":731595,"length":187,"previous":"M21-GAP-00891","next":"M21-GAP-00893"},"M21-GAP-00893":{"line":4148,"offset":731782,"length":187,"previous":"M21-GAP-00892","next":"M21-GAP-00894"},"M21-GAP-00894":{"line":4149,"offset":731969,"length":187,"previous":"M21-GAP-00893","next":"M21-GAP-00895"},"M21-GAP-00895":{"line":4150,"offset":732156,"length":187,"previous":"M21-GAP-00894","next":"M21-GAP-00896"},"M21-GAP-00896":{"line":4151,"offset":732343,"length":187,"previous":"M21-GAP-00895","next":"M21-GAP-00897"},"M21-GAP-00897":{"line":4152,"offset":732530,"length":187,"previous":"M21-GAP-00896","next":"M21-GAP-00898"},"M21-GAP-00898":{"line":4153,"offset":732717,"length":187,"previous":"M21-GAP-00897","next":"M21-GAP-00899"},"M21-GAP-00899":{"line":4154,"offset":732904,"length":187,"previous":"M21-GAP-00898","next":"M21-GAP-00900"},"M21-GAP-00900":{"line":4155,"offset":733091,"length":187,"previous":"M21-GAP-00899","next":"M21-GAP-00901"},"M21-GAP-00901":{"line":4156,"offset":733278,"length":187,"previous":"M21-GAP-00900","next":"M21-GAP-00902"},"M21-GAP-00902":{"line":4157,"offset":733465,"length":186,"previous":"M21-GAP-00901","next":"M21-GAP-00903"},"M21-GAP-00903":{"line":4158,"offset":733651,"length":187,"previous":"M21-GAP-00902","next":"M21-GAP-00904"},"M21-GAP-00904":{"line":4159,"offset":733838,"length":187,"previous":"M21-GAP-00903","next":"M21-GAP-00905"},"M21-GAP-00905":{"line":4160,"offset":734025,"length":186,"previous":"M21-GAP-00904","next":"M21-GAP-00906"},"M21-GAP-00906":{"line":4161,"offset":734211,"length":186,"previous":"M21-GAP-00905","next":"M21-GAP-00907"},"M21-GAP-00907":{"line":4162,"offset":734397,"length":186,"previous":"M21-GAP-00906","next":"M21-GAP-00908"},"M21-GAP-00908":{"line":4163,"offset":734583,"length":186,"previous":"M21-GAP-00907","next":"M21-GAP-00909"},"M21-GAP-00909":{"line":4164,"offset":734769,"length":186,"previous":"M21-GAP-00908","next":"M21-GAP-00910"},"M21-GAP-00910":{"line":4165,"offset":734955,"length":186,"previous":"M21-GAP-00909","next":"M21-GAP-00911"},"M21-GAP-00911":{"line":4166,"offset":735141,"length":186,"previous":"M21-GAP-00910","next":"M21-GAP-00912"},"M21-GAP-00912":{"line":4167,"offset":735327,"length":186,"previous":"M21-GAP-00911","next":"M21-GAP-00913"},"M21-GAP-00913":{"line":4168,"offset":735513,"length":187,"previous":"M21-GAP-00912","next":"M21-GAP-00914"},"M21-GAP-00914":{"line":4169,"offset":735700,"length":187,"previous":"M21-GAP-00913","next":"M21-GAP-00915"},"M21-GAP-00915":{"line":4170,"offset":735887,"length":187,"previous":"M21-GAP-00914","next":"M21-GAP-00916"},"M21-GAP-00916":{"line":4171,"offset":736074,"length":187,"previous":"M21-GAP-00915","next":"M21-GAP-00917"},"M21-GAP-00917":{"line":4172,"offset":736261,"length":186,"previous":"M21-GAP-00916","next":"M21-GAP-00918"},"M21-GAP-00918":{"line":4173,"offset":736447,"length":186,"previous":"M21-GAP-00917","next":"M21-GAP-00919"},"M21-GAP-00919":{"line":4174,"offset":736633,"length":186,"previous":"M21-GAP-00918","next":"M21-GAP-00920"},"M21-GAP-00920":{"line":4175,"offset":736819,"length":186,"previous":"M21-GAP-00919","next":"M21-GAP-00921"},"M21-GAP-00921":{"line":4176,"offset":737005,"length":186,"previous":"M21-GAP-00920","next":"M21-GAP-00922"},"M21-GAP-00922":{"line":4177,"offset":737191,"length":186,"previous":"M21-GAP-00921","next":"M21-GAP-00923"},"M21-GAP-00923":{"line":4178,"offset":737377,"length":186,"previous":"M21-GAP-00922","next":"M21-GAP-00924"},"M21-GAP-00924":{"line":4179,"offset":737563,"length":186,"previous":"M21-GAP-00923","next":"M21-GAP-00925"},"M21-GAP-00925":{"line":4180,"offset":737749,"length":171,"previous":"M21-GAP-00924","next":"M21-GAP-00926"},"M21-GAP-00926":{"line":4181,"offset":737920,"length":171,"previous":"M21-GAP-00925","next":"M21-GAP-00927"},"M21-GAP-00927":{"line":4182,"offset":738091,"length":172,"previous":"M21-GAP-00926","next":"M21-GAP-00928"},"M21-GAP-00928":{"line":4183,"offset":738263,"length":172,"previous":"M21-GAP-00927","next":"M21-GAP-00929"},"M21-GAP-00929":{"line":4184,"offset":738435,"length":172,"previous":"M21-GAP-00928","next":"M21-GAP-00930"},"M21-GAP-00930":{"line":4185,"offset":738607,"length":172,"previous":"M21-GAP-00929","next":"M21-GAP-00931"},"M21-GAP-00931":{"line":4186,"offset":738779,"length":172,"previous":"M21-GAP-00930","next":"M21-GAP-00932"},"M21-GAP-00932":{"line":4187,"offset":738951,"length":172,"previous":"M21-GAP-00931","next":"M21-GAP-00933"},"M21-GAP-00933":{"line":4188,"offset":739123,"length":172,"previous":"M21-GAP-00932","next":"M21-GAP-00934"},"M21-GAP-00934":{"line":4189,"offset":739295,"length":172,"previous":"M21-GAP-00933","next":"M21-GAP-00935"},"M21-GAP-00935":{"line":4190,"offset":739467,"length":172,"previous":"M21-GAP-00934","next":"M21-GAP-00936"},"M21-GAP-00936":{"line":4191,"offset":739639,"length":172,"previous":"M21-GAP-00935","next":"M21-GAP-00937"},"M21-GAP-00937":{"line":4192,"offset":739811,"length":171,"previous":"M21-GAP-00936","next":"M21-GAP-00938"},"M21-GAP-00938":{"line":4193,"offset":739982,"length":172,"previous":"M21-GAP-00937","next":"M21-GAP-00939"},"M21-GAP-00939":{"line":4194,"offset":740154,"length":172,"previous":"M21-GAP-00938","next":"M21-GAP-00940"},"M21-GAP-00940":{"line":4195,"offset":740326,"length":172,"previous":"M21-GAP-00939","next":"M21-GAP-00941"},"M21-GAP-00941":{"line":4196,"offset":740498,"length":172,"previous":"M21-GAP-00940","next":"M21-GAP-00942"},"M21-GAP-00942":{"line":4197,"offset":740670,"length":172,"previous":"M21-GAP-00941","next":"M21-GAP-00943"},"M21-GAP-00943":{"line":4198,"offset":740842,"length":172,"previous":"M21-GAP-00942","next":"M21-GAP-00944"},"M21-GAP-00944":{"line":4199,"offset":741014,"length":172,"previous":"M21-GAP-00943","next":"M21-GAP-00945"},"M21-GAP-00945":{"line":4200,"offset":741186,"length":172,"previous":"M21-GAP-00944","next":"M21-GAP-00946"},"M21-GAP-00946":{"line":4201,"offset":741358,"length":172,"previous":"M21-GAP-00945","next":"M21-GAP-00947"},"M21-GAP-00947":{"line":4202,"offset":741530,"length":172,"previous":"M21-GAP-00946","next":"M21-GAP-00948"},"M21-GAP-00948":{"line":4203,"offset":741702,"length":171,"previous":"M21-GAP-00947","next":"M21-GAP-00949"},"M21-GAP-00949":{"line":4204,"offset":741873,"length":172,"previous":"M21-GAP-00948","next":"M21-GAP-00950"},"M21-GAP-00950":{"line":4205,"offset":742045,"length":172,"previous":"M21-GAP-00949","next":"M21-GAP-00951"},"M21-GAP-00951":{"line":4206,"offset":742217,"length":172,"previous":"M21-GAP-00950","next":"M21-GAP-00952"},"M21-GAP-00952":{"line":4207,"offset":742389,"length":172,"previous":"M21-GAP-00951","next":"M21-GAP-00953"},"M21-GAP-00953":{"line":4208,"offset":742561,"length":172,"previous":"M21-GAP-00952","next":"M21-GAP-00954"},"M21-GAP-00954":{"line":4209,"offset":742733,"length":172,"previous":"M21-GAP-00953","next":"M21-GAP-00955"},"M21-GAP-00955":{"line":4210,"offset":742905,"length":172,"previous":"M21-GAP-00954","next":"M21-GAP-00956"},"M21-GAP-00956":{"line":4211,"offset":743077,"length":172,"previous":"M21-GAP-00955","next":"M21-GAP-00957"},"M21-GAP-00957":{"line":4212,"offset":743249,"length":172,"previous":"M21-GAP-00956","next":"M21-GAP-00958"},"M21-GAP-00958":{"line":4213,"offset":743421,"length":172,"previous":"M21-GAP-00957","next":"M21-GAP-00959"},"M21-GAP-00959":{"line":4214,"offset":743593,"length":171,"previous":"M21-GAP-00958","next":"M21-GAP-00960"},"M21-GAP-00960":{"line":4215,"offset":743764,"length":172,"previous":"M21-GAP-00959","next":"M21-GAP-00961"},"M21-GAP-00961":{"line":4216,"offset":743936,"length":172,"previous":"M21-GAP-00960","next":"M21-GAP-00962"},"M21-GAP-00962":{"line":4217,"offset":744108,"length":172,"previous":"M21-GAP-00961","next":"M21-GAP-00963"},"M21-GAP-00963":{"line":4218,"offset":744280,"length":172,"previous":"M21-GAP-00962","next":"M21-GAP-00964"},"M21-GAP-00964":{"line":4219,"offset":744452,"length":172,"previous":"M21-GAP-00963","next":"M21-GAP-00965"},"M21-GAP-00965":{"line":4220,"offset":744624,"length":172,"previous":"M21-GAP-00964","next":"M21-GAP-00966"},"M21-GAP-00966":{"line":4221,"offset":744796,"length":172,"previous":"M21-GAP-00965","next":"M21-GAP-00967"},"M21-GAP-00967":{"line":4222,"offset":744968,"length":172,"previous":"M21-GAP-00966","next":"M21-GAP-00968"},"M21-GAP-00968":{"line":4223,"offset":745140,"length":172,"previous":"M21-GAP-00967","next":"M21-GAP-00969"},"M21-GAP-00969":{"line":4224,"offset":745312,"length":171,"previous":"M21-GAP-00968","next":"M21-GAP-00970"},"M21-GAP-00970":{"line":4225,"offset":745483,"length":171,"previous":"M21-GAP-00969","next":"M21-GAP-00971"},"M21-GAP-00971":{"line":4226,"offset":745654,"length":171,"previous":"M21-GAP-00970","next":"M21-GAP-00972"},"M21-GAP-00972":{"line":4227,"offset":745825,"length":171,"previous":"M21-GAP-00971","next":"M21-GAP-00973"},"M21-GAP-00973":{"line":4228,"offset":745996,"length":171,"previous":"M21-GAP-00972","next":"M21-GAP-00974"},"M21-GAP-00974":{"line":4229,"offset":746167,"length":173,"previous":"M21-GAP-00973","next":"M21-GAP-00975"},"M21-GAP-00975":{"line":4230,"offset":746340,"length":173,"previous":"M21-GAP-00974","next":"M21-GAP-00976"},"M21-GAP-00976":{"line":4231,"offset":746513,"length":174,"previous":"M21-GAP-00975","next":"M21-GAP-00977"},"M21-GAP-00977":{"line":4232,"offset":746687,"length":174,"previous":"M21-GAP-00976","next":"M21-GAP-00978"},"M21-GAP-00978":{"line":4233,"offset":746861,"length":174,"previous":"M21-GAP-00977","next":"M21-GAP-00979"},"M21-GAP-00979":{"line":4234,"offset":747035,"length":174,"previous":"M21-GAP-00978","next":"M21-GAP-00980"},"M21-GAP-00980":{"line":4235,"offset":747209,"length":174,"previous":"M21-GAP-00979","next":"M21-GAP-00981"},"M21-GAP-00981":{"line":4236,"offset":747383,"length":174,"previous":"M21-GAP-00980","next":"M21-GAP-00982"},"M21-GAP-00982":{"line":4237,"offset":747557,"length":174,"previous":"M21-GAP-00981","next":"M21-GAP-00983"},"M21-GAP-00983":{"line":4238,"offset":747731,"length":173,"previous":"M21-GAP-00982","next":"M21-GAP-00984"},"M21-GAP-00984":{"line":4239,"offset":747904,"length":173,"previous":"M21-GAP-00983","next":"M21-GAP-00985"},"M21-GAP-00985":{"line":4240,"offset":748077,"length":173,"previous":"M21-GAP-00984","next":"M21-GAP-00986"},"M21-GAP-00986":{"line":4241,"offset":748250,"length":173,"previous":"M21-GAP-00985","next":"M21-GAP-00987"},"M21-GAP-00987":{"line":4242,"offset":748423,"length":173,"previous":"M21-GAP-00986","next":"M21-GAP-00988"},"M21-GAP-00988":{"line":4243,"offset":748596,"length":173,"previous":"M21-GAP-00987","next":"M21-GAP-00989"},"M21-GAP-00989":{"line":4244,"offset":748769,"length":173,"previous":"M21-GAP-00988","next":"M21-GAP-00990"},"M21-GAP-00990":{"line":4245,"offset":748942,"length":173,"previous":"M21-GAP-00989","next":"M21-GAP-00991"},"M21-GAP-00991":{"line":4246,"offset":749115,"length":191,"previous":"M21-GAP-00990","next":"M21-GAP-00992"},"M21-GAP-00992":{"line":4247,"offset":749306,"length":191,"previous":"M21-GAP-00991","next":"M21-GAP-00993"},"M21-GAP-00993":{"line":4248,"offset":749497,"length":185,"previous":"M21-GAP-00992","next":"M21-GAP-00994"},"M21-GAP-00994":{"line":4249,"offset":749682,"length":191,"previous":"M21-GAP-00993","next":"M21-GAP-00995"},"M21-GAP-00995":{"line":4250,"offset":749873,"length":187,"previous":"M21-GAP-00994","next":"M21-GAP-00996"},"M21-GAP-00996":{"line":4251,"offset":750060,"length":196,"previous":"M21-GAP-00995","next":"M21-GAP-00997"},"M21-GAP-00997":{"line":4252,"offset":750256,"length":196,"previous":"M21-GAP-00996","next":"M21-GAP-00998"},"M21-GAP-00998":{"line":4253,"offset":750452,"length":197,"previous":"M21-GAP-00997","next":"M21-GAP-00999"},"M21-GAP-00999":{"line":4254,"offset":750649,"length":197,"previous":"M21-GAP-00998","next":"M21-GAP-01000"},"M21-GAP-01000":{"line":4255,"offset":750846,"length":196,"previous":"M21-GAP-00999","next":"M21-GAP-01001"},"M21-GAP-01001":{"line":4256,"offset":751042,"length":196,"previous":"M21-GAP-01000","next":"M21-GAP-01002"},"M21-GAP-01002":{"line":4257,"offset":751238,"length":196,"previous":"M21-GAP-01001","next":"M21-GAP-01003"},"M21-GAP-01003":{"line":4258,"offset":751434,"length":196,"previous":"M21-GAP-01002","next":"M21-GAP-01004"},"M21-GAP-01004":{"line":4259,"offset":751630,"length":196,"previous":"M21-GAP-01003","next":"M21-GAP-01005"},"M21-GAP-01005":{"line":4260,"offset":751826,"length":196,"previous":"M21-GAP-01004","next":"M21-GAP-01006"},"M21-GAP-01006":{"line":4261,"offset":752022,"length":196,"previous":"M21-GAP-01005","next":"M21-GAP-01007"},"M21-GAP-01007":{"line":4262,"offset":752218,"length":196,"previous":"M21-GAP-01006","next":"M21-GAP-01008"},"M21-GAP-01008":{"line":4263,"offset":752414,"length":180,"previous":"M21-GAP-01007","next":"M21-GAP-01009"},"M21-GAP-01009":{"line":4264,"offset":752594,"length":196,"previous":"M21-GAP-01008","next":"M21-GAP-01010"},"M21-GAP-01010":{"line":4265,"offset":752790,"length":196,"previous":"M21-GAP-01009","next":"M21-GAP-01011"},"M21-GAP-01011":{"line":4266,"offset":752986,"length":194,"previous":"M21-GAP-01010","next":"M21-GAP-01012"},"M21-GAP-01012":{"line":4267,"offset":753180,"length":194,"previous":"M21-GAP-01011","next":"M21-GAP-01013"},"M21-GAP-01013":{"line":4268,"offset":753374,"length":197,"previous":"M21-GAP-01012","next":"M21-GAP-01014"},"M21-GAP-01014":{"line":4269,"offset":753571,"length":197,"previous":"M21-GAP-01013","next":"M21-GAP-01015"},"M21-GAP-01015":{"line":4270,"offset":753768,"length":189,"previous":"M21-GAP-01014","next":"M21-GAP-01016"},"M21-GAP-01016":{"line":4271,"offset":753957,"length":189,"previous":"M21-GAP-01015","next":"M21-GAP-01017"},"M21-GAP-01017":{"line":4272,"offset":754146,"length":178,"previous":"M21-GAP-01016","next":"M21-GAP-01018"},"M21-GAP-01018":{"line":4273,"offset":754324,"length":178,"previous":"M21-GAP-01017","next":"M21-GAP-01019"},"M21-GAP-01019":{"line":4274,"offset":754502,"length":178,"previous":"M21-GAP-01018","next":"M21-GAP-01020"},"M21-GAP-01020":{"line":4275,"offset":754680,"length":178,"previous":"M21-GAP-01019","next":"M21-GAP-01021"},"M21-GAP-01021":{"line":4276,"offset":754858,"length":178,"previous":"M21-GAP-01020","next":"M21-GAP-01022"},"M21-GAP-01022":{"line":4277,"offset":755036,"length":178,"previous":"M21-GAP-01021","next":"M21-GAP-01023"},"M21-GAP-01023":{"line":4278,"offset":755214,"length":178,"previous":"M21-GAP-01022","next":"M21-GAP-01024"},"M21-GAP-01024":{"line":4279,"offset":755392,"length":178,"previous":"M21-GAP-01023","next":"M21-GAP-01025"},"M21-GAP-01025":{"line":4280,"offset":755570,"length":178,"previous":"M21-GAP-01024","next":"M21-GAP-01026"},"M21-GAP-01026":{"line":4281,"offset":755748,"length":178,"previous":"M21-GAP-01025","next":"M21-GAP-01027"},"M21-GAP-01027":{"line":4282,"offset":755926,"length":180,"previous":"M21-GAP-01026","next":"M21-GAP-01028"},"M21-GAP-01028":{"line":4283,"offset":756106,"length":183,"previous":"M21-GAP-01027","next":"M21-GAP-01029"},"M21-GAP-01029":{"line":4284,"offset":756289,"length":183,"previous":"M21-GAP-01028","next":"M21-GAP-01030"},"M21-GAP-01030":{"line":4285,"offset":756472,"length":183,"previous":"M21-GAP-01029","next":"M21-GAP-01031"},"M21-GAP-01031":{"line":4286,"offset":756655,"length":183,"previous":"M21-GAP-01030","next":"M21-GAP-01032"},"M21-GAP-01032":{"line":4287,"offset":756838,"length":183,"previous":"M21-GAP-01031","next":"M21-GAP-01033"},"M21-GAP-01033":{"line":4288,"offset":757021,"length":183,"previous":"M21-GAP-01032","next":"M21-GAP-01034"},"M21-GAP-01034":{"line":4289,"offset":757204,"length":188,"previous":"M21-GAP-01033","next":"M21-GAP-01035"},"M21-GAP-01035":{"line":4290,"offset":757392,"length":188,"previous":"M21-GAP-01034","next":"M21-GAP-01036"},"M21-GAP-01036":{"line":4291,"offset":757580,"length":188,"previous":"M21-GAP-01035","next":"M21-GAP-01037"},"M21-GAP-01037":{"line":4292,"offset":757768,"length":188,"previous":"M21-GAP-01036","next":"M21-GAP-01038"},"M21-GAP-01038":{"line":4293,"offset":757956,"length":188,"previous":"M21-GAP-01037","next":"M21-GAP-01039"},"M21-GAP-01039":{"line":4294,"offset":758144,"length":188,"previous":"M21-GAP-01038","next":"M21-GAP-01040"},"M21-GAP-01040":{"line":4295,"offset":758332,"length":188,"previous":"M21-GAP-01039","next":"M21-GAP-01041"},"M21-GAP-01041":{"line":4296,"offset":758520,"length":186,"previous":"M21-GAP-01040","next":"M21-GAP-01042"},"M21-GAP-01042":{"line":4297,"offset":758706,"length":186,"previous":"M21-GAP-01041","next":"M21-GAP-01043"},"M21-GAP-01043":{"line":4298,"offset":758892,"length":186,"previous":"M21-GAP-01042","next":"M21-GAP-01044"},"M21-GAP-01044":{"line":4299,"offset":759078,"length":186,"previous":"M21-GAP-01043","next":"M21-GAP-01045"},"M21-GAP-01045":{"line":4300,"offset":759264,"length":186,"previous":"M21-GAP-01044","next":"M21-GAP-01046"},"M21-GAP-01046":{"line":4301,"offset":759450,"length":186,"previous":"M21-GAP-01045","next":"M21-GAP-01047"},"M21-GAP-01047":{"line":4302,"offset":759636,"length":194,"previous":"M21-GAP-01046","next":"M21-GAP-01048"},"M21-GAP-01048":{"line":4303,"offset":759830,"length":194,"previous":"M21-GAP-01047","next":"M21-GAP-01049"},"M21-GAP-01049":{"line":4304,"offset":760024,"length":194,"previous":"M21-GAP-01048","next":"M21-GAP-01050"},"M21-GAP-01050":{"line":4305,"offset":760218,"length":194,"previous":"M21-GAP-01049","next":"M21-GAP-01051"},"M21-GAP-01051":{"line":4306,"offset":760412,"length":194,"previous":"M21-GAP-01050","next":"M21-GAP-01052"},"M21-GAP-01052":{"line":4307,"offset":760606,"length":194,"previous":"M21-GAP-01051","next":"M21-GAP-01053"},"M21-GAP-01053":{"line":4308,"offset":760800,"length":194,"previous":"M21-GAP-01052","next":"M21-GAP-01054"},"M21-GAP-01054":{"line":4309,"offset":760994,"length":194,"previous":"M21-GAP-01053","next":"M21-GAP-01055"},"M21-GAP-01055":{"line":4310,"offset":761188,"length":194,"previous":"M21-GAP-01054","next":"M21-GAP-01056"},"M21-GAP-01056":{"line":4311,"offset":761382,"length":194,"previous":"M21-GAP-01055","next":"M21-GAP-01057"},"M21-GAP-01057":{"line":4312,"offset":761576,"length":186,"previous":"M21-GAP-01056","next":"M21-GAP-01058"},"M21-GAP-01058":{"line":4313,"offset":761762,"length":186,"previous":"M21-GAP-01057","next":"M21-GAP-01059"},"M21-GAP-01059":{"line":4314,"offset":761948,"length":187,"previous":"M21-GAP-01058","next":"M21-GAP-01060"},"M21-GAP-01060":{"line":4315,"offset":762135,"length":187,"previous":"M21-GAP-01059","next":"M21-GAP-01061"},"M21-GAP-01061":{"line":4316,"offset":762322,"length":187,"previous":"M21-GAP-01060","next":"M21-GAP-01062"},"M21-GAP-01062":{"line":4317,"offset":762509,"length":187,"previous":"M21-GAP-01061","next":"M21-GAP-01063"},"M21-GAP-01063":{"line":4318,"offset":762696,"length":187,"previous":"M21-GAP-01062","next":"M21-GAP-01064"},"M21-GAP-01064":{"line":4319,"offset":762883,"length":187,"previous":"M21-GAP-01063","next":"M21-GAP-01065"},"M21-GAP-01065":{"line":4320,"offset":763070,"length":187,"previous":"M21-GAP-01064","next":"M21-GAP-01066"},"M21-GAP-01066":{"line":4321,"offset":763257,"length":187,"previous":"M21-GAP-01065","next":"M21-GAP-01067"},"M21-GAP-01067":{"line":4322,"offset":763444,"length":187,"previous":"M21-GAP-01066","next":"M21-GAP-01068"},"M21-GAP-01068":{"line":4323,"offset":763631,"length":187,"previous":"M21-GAP-01067","next":"M21-GAP-01069"},"M21-GAP-01069":{"line":4324,"offset":763818,"length":186,"previous":"M21-GAP-01068","next":"M21-GAP-01070"},"M21-GAP-01070":{"line":4325,"offset":764004,"length":187,"previous":"M21-GAP-01069","next":"M21-GAP-01071"},"M21-GAP-01071":{"line":4326,"offset":764191,"length":187,"previous":"M21-GAP-01070","next":"M21-GAP-01072"},"M21-GAP-01072":{"line":4327,"offset":764378,"length":187,"previous":"M21-GAP-01071","next":"M21-GAP-01073"},"M21-GAP-01073":{"line":4328,"offset":764565,"length":187,"previous":"M21-GAP-01072","next":"M21-GAP-01074"},"M21-GAP-01074":{"line":4329,"offset":764752,"length":187,"previous":"M21-GAP-01073","next":"M21-GAP-01075"},"M21-GAP-01075":{"line":4330,"offset":764939,"length":187,"previous":"M21-GAP-01074","next":"M21-GAP-01076"},"M21-GAP-01076":{"line":4331,"offset":765126,"length":187,"previous":"M21-GAP-01075","next":"M21-GAP-01077"},"M21-GAP-01077":{"line":4332,"offset":765313,"length":187,"previous":"M21-GAP-01076","next":"M21-GAP-01078"},"M21-GAP-01078":{"line":4333,"offset":765500,"length":187,"previous":"M21-GAP-01077","next":"M21-GAP-01079"},"M21-GAP-01079":{"line":4334,"offset":765687,"length":187,"previous":"M21-GAP-01078","next":"M21-GAP-01080"},"M21-GAP-01080":{"line":4335,"offset":765874,"length":186,"previous":"M21-GAP-01079","next":"M21-GAP-01081"},"M21-GAP-01081":{"line":4336,"offset":766060,"length":187,"previous":"M21-GAP-01080","next":"M21-GAP-01082"},"M21-GAP-01082":{"line":4337,"offset":766247,"length":187,"previous":"M21-GAP-01081","next":"M21-GAP-01083"},"M21-GAP-01083":{"line":4338,"offset":766434,"length":187,"previous":"M21-GAP-01082","next":"M21-GAP-01084"},"M21-GAP-01084":{"line":4339,"offset":766621,"length":187,"previous":"M21-GAP-01083","next":"M21-GAP-01085"},"M21-GAP-01085":{"line":4340,"offset":766808,"length":187,"previous":"M21-GAP-01084","next":"M21-GAP-01086"},"M21-GAP-01086":{"line":4341,"offset":766995,"length":187,"previous":"M21-GAP-01085","next":"M21-GAP-01087"},"M21-GAP-01087":{"line":4342,"offset":767182,"length":187,"previous":"M21-GAP-01086","next":"M21-GAP-01088"},"M21-GAP-01088":{"line":4343,"offset":767369,"length":187,"previous":"M21-GAP-01087","next":"M21-GAP-01089"},"M21-GAP-01089":{"line":4344,"offset":767556,"length":187,"previous":"M21-GAP-01088","next":"M21-GAP-01090"},"M21-GAP-01090":{"line":4345,"offset":767743,"length":187,"previous":"M21-GAP-01089","next":"M21-GAP-01091"},"M21-GAP-01091":{"line":4346,"offset":767930,"length":186,"previous":"M21-GAP-01090","next":"M21-GAP-01092"},"M21-GAP-01092":{"line":4347,"offset":768116,"length":187,"previous":"M21-GAP-01091","next":"M21-GAP-01093"},"M21-GAP-01093":{"line":4348,"offset":768303,"length":187,"previous":"M21-GAP-01092","next":"M21-GAP-01094"},"M21-GAP-01094":{"line":4349,"offset":768490,"length":187,"previous":"M21-GAP-01093","next":"M21-GAP-01095"},"M21-GAP-01095":{"line":4350,"offset":768677,"length":187,"previous":"M21-GAP-01094","next":"M21-GAP-01096"},"M21-GAP-01096":{"line":4351,"offset":768864,"length":187,"previous":"M21-GAP-01095","next":"M21-GAP-01097"},"M21-GAP-01097":{"line":4352,"offset":769051,"length":187,"previous":"M21-GAP-01096","next":"M21-GAP-01098"},"M21-GAP-01098":{"line":4353,"offset":769238,"length":187,"previous":"M21-GAP-01097","next":"M21-GAP-01099"},"M21-GAP-01099":{"line":4354,"offset":769425,"length":187,"previous":"M21-GAP-01098","next":"M21-GAP-01100"},"M21-GAP-01100":{"line":4355,"offset":769612,"length":187,"previous":"M21-GAP-01099","next":"M21-GAP-01101"},"M21-GAP-01101":{"line":4356,"offset":769799,"length":187,"previous":"M21-GAP-01100","next":"M21-GAP-01102"},"M21-GAP-01102":{"line":4357,"offset":769986,"length":186,"previous":"M21-GAP-01101","next":"M21-GAP-01103"},"M21-GAP-01103":{"line":4358,"offset":770172,"length":187,"previous":"M21-GAP-01102","next":"M21-GAP-01104"},"M21-GAP-01104":{"line":4359,"offset":770359,"length":187,"previous":"M21-GAP-01103","next":"M21-GAP-01105"},"M21-GAP-01105":{"line":4360,"offset":770546,"length":187,"previous":"M21-GAP-01104","next":"M21-GAP-01106"},"M21-GAP-01106":{"line":4361,"offset":770733,"length":187,"previous":"M21-GAP-01105","next":"M21-GAP-01107"},"M21-GAP-01107":{"line":4362,"offset":770920,"length":187,"previous":"M21-GAP-01106","next":"M21-GAP-01108"},"M21-GAP-01108":{"line":4363,"offset":771107,"length":187,"previous":"M21-GAP-01107","next":"M21-GAP-01109"},"M21-GAP-01109":{"line":4364,"offset":771294,"length":187,"previous":"M21-GAP-01108","next":"M21-GAP-01110"},"M21-GAP-01110":{"line":4365,"offset":771481,"length":187,"previous":"M21-GAP-01109","next":"M21-GAP-01111"},"M21-GAP-01111":{"line":4366,"offset":771668,"length":187,"previous":"M21-GAP-01110","next":"M21-GAP-01112"},"M21-GAP-01112":{"line":4367,"offset":771855,"length":187,"previous":"M21-GAP-01111","next":"M21-GAP-01113"},"M21-GAP-01113":{"line":4368,"offset":772042,"length":186,"previous":"M21-GAP-01112","next":"M21-GAP-01114"},"M21-GAP-01114":{"line":4369,"offset":772228,"length":187,"previous":"M21-GAP-01113","next":"M21-GAP-01115"},"M21-GAP-01115":{"line":4370,"offset":772415,"length":187,"previous":"M21-GAP-01114","next":"M21-GAP-01116"},"M21-GAP-01116":{"line":4371,"offset":772602,"length":187,"previous":"M21-GAP-01115","next":"M21-GAP-01117"},"M21-GAP-01117":{"line":4372,"offset":772789,"length":187,"previous":"M21-GAP-01116","next":"M21-GAP-01118"},"M21-GAP-01118":{"line":4373,"offset":772976,"length":187,"previous":"M21-GAP-01117","next":"M21-GAP-01119"},"M21-GAP-01119":{"line":4374,"offset":773163,"length":187,"previous":"M21-GAP-01118","next":"M21-GAP-01120"},"M21-GAP-01120":{"line":4375,"offset":773350,"length":187,"previous":"M21-GAP-01119","next":"M21-GAP-01121"},"M21-GAP-01121":{"line":4376,"offset":773537,"length":187,"previous":"M21-GAP-01120","next":"M21-GAP-01122"},"M21-GAP-01122":{"line":4377,"offset":773724,"length":187,"previous":"M21-GAP-01121","next":"M21-GAP-01123"},"M21-GAP-01123":{"line":4378,"offset":773911,"length":187,"previous":"M21-GAP-01122","next":"M21-GAP-01124"},"M21-GAP-01124":{"line":4379,"offset":774098,"length":186,"previous":"M21-GAP-01123","next":"M21-GAP-01125"},"M21-GAP-01125":{"line":4380,"offset":774284,"length":187,"previous":"M21-GAP-01124","next":"M21-GAP-01126"},"M21-GAP-01126":{"line":4381,"offset":774471,"length":186,"previous":"M21-GAP-01125","next":"M21-GAP-01127"},"M21-GAP-01127":{"line":4382,"offset":774657,"length":186,"previous":"M21-GAP-01126","next":"M21-GAP-01128"},"M21-GAP-01128":{"line":4383,"offset":774843,"length":193,"previous":"M21-GAP-01127","next":"M21-GAP-01129"},"M21-GAP-01129":{"line":4384,"offset":775036,"length":193,"previous":"M21-GAP-01128","next":"M21-GAP-01130"},"M21-GAP-01130":{"line":4385,"offset":775229,"length":193,"previous":"M21-GAP-01129","next":"M21-GAP-01131"},"M21-GAP-01131":{"line":4386,"offset":775422,"length":193,"previous":"M21-GAP-01130","next":"M21-GAP-01132"},"M21-GAP-01132":{"line":4387,"offset":775615,"length":193,"previous":"M21-GAP-01131","next":"M21-GAP-01133"},"M21-GAP-01133":{"line":4388,"offset":775808,"length":193,"previous":"M21-GAP-01132","next":"M21-GAP-01134"},"M21-GAP-01134":{"line":4389,"offset":776001,"length":190,"previous":"M21-GAP-01133","next":"M21-GAP-01135"},"M21-GAP-01135":{"line":4390,"offset":776191,"length":190,"previous":"M21-GAP-01134","next":"M21-GAP-01136"},"M21-GAP-01136":{"line":4391,"offset":776381,"length":191,"previous":"M21-GAP-01135","next":"M21-GAP-01137"},"M21-GAP-01137":{"line":4392,"offset":776572,"length":191,"previous":"M21-GAP-01136","next":"M21-GAP-01138"},"M21-GAP-01138":{"line":4393,"offset":776763,"length":191,"previous":"M21-GAP-01137","next":"M21-GAP-01139"},"M21-GAP-01139":{"line":4394,"offset":776954,"length":191,"previous":"M21-GAP-01138","next":"M21-GAP-01140"},"M21-GAP-01140":{"line":4395,"offset":777145,"length":191,"previous":"M21-GAP-01139","next":"M21-GAP-01141"},"M21-GAP-01141":{"line":4396,"offset":777336,"length":191,"previous":"M21-GAP-01140","next":"M21-GAP-01142"},"M21-GAP-01142":{"line":4397,"offset":777527,"length":191,"previous":"M21-GAP-01141","next":"M21-GAP-01143"},"M21-GAP-01143":{"line":4398,"offset":777718,"length":191,"previous":"M21-GAP-01142","next":"M21-GAP-01144"},"M21-GAP-01144":{"line":4399,"offset":777909,"length":191,"previous":"M21-GAP-01143","next":"M21-GAP-01145"},"M21-GAP-01145":{"line":4400,"offset":778100,"length":191,"previous":"M21-GAP-01144","next":"M21-GAP-01146"},"M21-GAP-01146":{"line":4401,"offset":778291,"length":190,"previous":"M21-GAP-01145","next":"M21-GAP-01147"},"M21-GAP-01147":{"line":4402,"offset":778481,"length":191,"previous":"M21-GAP-01146","next":"M21-GAP-01148"},"M21-GAP-01148":{"line":4403,"offset":778672,"length":191,"previous":"M21-GAP-01147","next":"M21-GAP-01149"},"M21-GAP-01149":{"line":4404,"offset":778863,"length":190,"previous":"M21-GAP-01148","next":"M21-GAP-01150"},"M21-GAP-01150":{"line":4405,"offset":779053,"length":190,"previous":"M21-GAP-01149","next":"M21-GAP-01151"},"M21-GAP-01151":{"line":4406,"offset":779243,"length":190,"previous":"M21-GAP-01150","next":"M21-GAP-01152"},"M21-GAP-01152":{"line":4407,"offset":779433,"length":190,"previous":"M21-GAP-01151","next":"M21-GAP-01153"},"M21-GAP-01153":{"line":4408,"offset":779623,"length":190,"previous":"M21-GAP-01152","next":"M21-GAP-01154"},"M21-GAP-01154":{"line":4409,"offset":779813,"length":190,"previous":"M21-GAP-01153","next":"M21-GAP-01155"},"M21-GAP-01155":{"line":4410,"offset":780003,"length":190,"previous":"M21-GAP-01154","next":"M21-GAP-01156"},"M21-GAP-01156":{"line":4411,"offset":780193,"length":190,"previous":"M21-GAP-01155","next":"M21-GAP-01157"},"M21-GAP-01157":{"line":4412,"offset":780383,"length":190,"previous":"M21-GAP-01156","next":"M21-GAP-01158"},"M21-GAP-01158":{"line":4413,"offset":780573,"length":191,"previous":"M21-GAP-01157","next":"M21-GAP-01159"},"M21-GAP-01159":{"line":4414,"offset":780764,"length":191,"previous":"M21-GAP-01158","next":"M21-GAP-01160"},"M21-GAP-01160":{"line":4415,"offset":780955,"length":191,"previous":"M21-GAP-01159","next":"M21-GAP-01161"},"M21-GAP-01161":{"line":4416,"offset":781146,"length":191,"previous":"M21-GAP-01160","next":"M21-GAP-01162"},"M21-GAP-01162":{"line":4417,"offset":781337,"length":191,"previous":"M21-GAP-01161","next":"M21-GAP-01163"},"M21-GAP-01163":{"line":4418,"offset":781528,"length":191,"previous":"M21-GAP-01162","next":"M21-GAP-01164"},"M21-GAP-01164":{"line":4419,"offset":781719,"length":191,"previous":"M21-GAP-01163","next":"M21-GAP-01165"},"M21-GAP-01165":{"line":4420,"offset":781910,"length":191,"previous":"M21-GAP-01164","next":"M21-GAP-01166"},"M21-GAP-01166":{"line":4421,"offset":782101,"length":191,"previous":"M21-GAP-01165","next":"M21-GAP-01167"},"M21-GAP-01167":{"line":4422,"offset":782292,"length":191,"previous":"M21-GAP-01166","next":"M21-GAP-01168"},"M21-GAP-01168":{"line":4423,"offset":782483,"length":190,"previous":"M21-GAP-01167","next":"M21-GAP-01169"},"M21-GAP-01169":{"line":4424,"offset":782673,"length":191,"previous":"M21-GAP-01168","next":"M21-GAP-01170"},"M21-GAP-01170":{"line":4425,"offset":782864,"length":191,"previous":"M21-GAP-01169","next":"M21-GAP-01171"},"M21-GAP-01171":{"line":4426,"offset":783055,"length":191,"previous":"M21-GAP-01170","next":"M21-GAP-01172"},"M21-GAP-01172":{"line":4427,"offset":783246,"length":191,"previous":"M21-GAP-01171","next":"M21-GAP-01173"},"M21-GAP-01173":{"line":4428,"offset":783437,"length":191,"previous":"M21-GAP-01172","next":"M21-GAP-01174"},"M21-GAP-01174":{"line":4429,"offset":783628,"length":191,"previous":"M21-GAP-01173","next":"M21-GAP-01175"},"M21-GAP-01175":{"line":4430,"offset":783819,"length":191,"previous":"M21-GAP-01174","next":"M21-GAP-01176"},"M21-GAP-01176":{"line":4431,"offset":784010,"length":191,"previous":"M21-GAP-01175","next":"M21-GAP-01177"},"M21-GAP-01177":{"line":4432,"offset":784201,"length":191,"previous":"M21-GAP-01176","next":"M21-GAP-01178"},"M21-GAP-01178":{"line":4433,"offset":784392,"length":191,"previous":"M21-GAP-01177","next":"M21-GAP-01179"},"M21-GAP-01179":{"line":4434,"offset":784583,"length":190,"previous":"M21-GAP-01178","next":"M21-GAP-01180"},"M21-GAP-01180":{"line":4435,"offset":784773,"length":191,"previous":"M21-GAP-01179","next":"M21-GAP-01181"},"M21-GAP-01181":{"line":4436,"offset":784964,"length":191,"previous":"M21-GAP-01180","next":"M21-GAP-01182"},"M21-GAP-01182":{"line":4437,"offset":785155,"length":191,"previous":"M21-GAP-01181","next":"M21-GAP-01183"},"M21-GAP-01183":{"line":4438,"offset":785346,"length":191,"previous":"M21-GAP-01182","next":"M21-GAP-01184"},"M21-GAP-01184":{"line":4439,"offset":785537,"length":191,"previous":"M21-GAP-01183","next":"M21-GAP-01185"},"M21-GAP-01185":{"line":4440,"offset":785728,"length":191,"previous":"M21-GAP-01184","next":"M21-GAP-01186"},"M21-GAP-01186":{"line":4441,"offset":785919,"length":191,"previous":"M21-GAP-01185","next":"M21-GAP-01187"},"M21-GAP-01187":{"line":4442,"offset":786110,"length":191,"previous":"M21-GAP-01186","next":"M21-GAP-01188"},"M21-GAP-01188":{"line":4443,"offset":786301,"length":191,"previous":"M21-GAP-01187","next":"M21-GAP-01189"},"M21-GAP-01189":{"line":4444,"offset":786492,"length":191,"previous":"M21-GAP-01188","next":"M21-GAP-01190"},"M21-GAP-01190":{"line":4445,"offset":786683,"length":190,"previous":"M21-GAP-01189","next":"M21-GAP-01191"},"M21-GAP-01191":{"line":4446,"offset":786873,"length":191,"previous":"M21-GAP-01190","next":"M21-GAP-01192"},"M21-GAP-01192":{"line":4447,"offset":787064,"length":191,"previous":"M21-GAP-01191","next":"M21-GAP-01193"},"M21-GAP-01193":{"line":4448,"offset":787255,"length":191,"previous":"M21-GAP-01192","next":"M21-GAP-01194"},"M21-GAP-01194":{"line":4449,"offset":787446,"length":191,"previous":"M21-GAP-01193","next":"M21-GAP-01195"},"M21-GAP-01195":{"line":4450,"offset":787637,"length":191,"previous":"M21-GAP-01194","next":"M21-GAP-01196"},"M21-GAP-01196":{"line":4451,"offset":787828,"length":191,"previous":"M21-GAP-01195","next":"M21-GAP-01197"},"M21-GAP-01197":{"line":4452,"offset":788019,"length":191,"previous":"M21-GAP-01196","next":"M21-GAP-01198"},"M21-GAP-01198":{"line":4453,"offset":788210,"length":191,"previous":"M21-GAP-01197","next":"M21-GAP-01199"},"M21-GAP-01199":{"line":4454,"offset":788401,"length":191,"previous":"M21-GAP-01198","next":"M21-GAP-01200"},"M21-GAP-01200":{"line":4455,"offset":788592,"length":191,"previous":"M21-GAP-01199","next":"M21-GAP-01201"},"M21-GAP-01201":{"line":4456,"offset":788783,"length":190,"previous":"M21-GAP-01200","next":"M21-GAP-01202"},"M21-GAP-01202":{"line":4457,"offset":788973,"length":191,"previous":"M21-GAP-01201","next":"M21-GAP-01203"},"M21-GAP-01203":{"line":4458,"offset":789164,"length":191,"previous":"M21-GAP-01202","next":"M21-GAP-01204"},"M21-GAP-01204":{"line":4459,"offset":789355,"length":191,"previous":"M21-GAP-01203","next":"M21-GAP-01205"},"M21-GAP-01205":{"line":4460,"offset":789546,"length":191,"previous":"M21-GAP-01204","next":"M21-GAP-01206"},"M21-GAP-01206":{"line":4461,"offset":789737,"length":191,"previous":"M21-GAP-01205","next":"M21-GAP-01207"},"M21-GAP-01207":{"line":4462,"offset":789928,"length":191,"previous":"M21-GAP-01206","next":"M21-GAP-01208"},"M21-GAP-01208":{"line":4463,"offset":790119,"length":191,"previous":"M21-GAP-01207","next":"M21-GAP-01209"},"M21-GAP-01209":{"line":4464,"offset":790310,"length":190,"previous":"M21-GAP-01208","next":"M21-GAP-01210"},"M21-GAP-01210":{"line":4465,"offset":790500,"length":190,"previous":"M21-GAP-01209","next":"M21-GAP-01211"},"M21-GAP-01211":{"line":4466,"offset":790690,"length":190,"previous":"M21-GAP-01210","next":"M21-GAP-01212"},"M21-GAP-01212":{"line":4467,"offset":790880,"length":190,"previous":"M21-GAP-01211","next":"M21-GAP-01213"},"M21-GAP-01213":{"line":4468,"offset":791070,"length":190,"previous":"M21-GAP-01212","next":"M21-GAP-01214"},"M21-GAP-01214":{"line":4469,"offset":791260,"length":190,"previous":"M21-GAP-01213","next":"M21-GAP-01215"},"M21-GAP-01215":{"line":4470,"offset":791450,"length":190,"previous":"M21-GAP-01214","next":"M21-GAP-01216"},"M21-GAP-01216":{"line":4471,"offset":791640,"length":192,"previous":"M21-GAP-01215","next":"M21-GAP-01217"},"M21-GAP-01217":{"line":4472,"offset":791832,"length":192,"previous":"M21-GAP-01216","next":"M21-GAP-01218"},"M21-GAP-01218":{"line":4473,"offset":792024,"length":193,"previous":"M21-GAP-01217","next":"M21-GAP-01219"},"M21-GAP-01219":{"line":4474,"offset":792217,"length":193,"previous":"M21-GAP-01218","next":"M21-GAP-01220"},"M21-GAP-01220":{"line":4475,"offset":792410,"length":193,"previous":"M21-GAP-01219","next":"M21-GAP-01221"},"M21-GAP-01221":{"line":4476,"offset":792603,"length":193,"previous":"M21-GAP-01220","next":"M21-GAP-01222"},"M21-GAP-01222":{"line":4477,"offset":792796,"length":193,"previous":"M21-GAP-01221","next":"M21-GAP-01223"},"M21-GAP-01223":{"line":4478,"offset":792989,"length":193,"previous":"M21-GAP-01222","next":"M21-GAP-01224"},"M21-GAP-01224":{"line":4479,"offset":793182,"length":193,"previous":"M21-GAP-01223","next":"M21-GAP-01225"},"M21-GAP-01225":{"line":4480,"offset":793375,"length":193,"previous":"M21-GAP-01224","next":"M21-GAP-01226"},"M21-GAP-01226":{"line":4481,"offset":793568,"length":193,"previous":"M21-GAP-01225","next":"M21-GAP-01227"},"M21-GAP-01227":{"line":4482,"offset":793761,"length":193,"previous":"M21-GAP-01226","next":"M21-GAP-01228"},"M21-GAP-01228":{"line":4483,"offset":793954,"length":192,"previous":"M21-GAP-01227","next":"M21-GAP-01229"},"M21-GAP-01229":{"line":4484,"offset":794146,"length":193,"previous":"M21-GAP-01228","next":"M21-GAP-01230"},"M21-GAP-01230":{"line":4485,"offset":794339,"length":193,"previous":"M21-GAP-01229","next":"M21-GAP-01231"},"M21-GAP-01231":{"line":4486,"offset":794532,"length":193,"previous":"M21-GAP-01230","next":"M21-GAP-01232"},"M21-GAP-01232":{"line":4487,"offset":794725,"length":193,"previous":"M21-GAP-01231","next":"M21-GAP-01233"},"M21-GAP-01233":{"line":4488,"offset":794918,"length":193,"previous":"M21-GAP-01232","next":"M21-GAP-01234"},"M21-GAP-01234":{"line":4489,"offset":795111,"length":193,"previous":"M21-GAP-01233","next":"M21-GAP-01235"},"M21-GAP-01235":{"line":4490,"offset":795304,"length":193,"previous":"M21-GAP-01234","next":"M21-GAP-01236"},"M21-GAP-01236":{"line":4491,"offset":795497,"length":192,"previous":"M21-GAP-01235","next":"M21-GAP-01237"},"M21-GAP-01237":{"line":4492,"offset":795689,"length":192,"previous":"M21-GAP-01236","next":"M21-GAP-01238"},"M21-GAP-01238":{"line":4493,"offset":795881,"length":192,"previous":"M21-GAP-01237","next":"M21-GAP-01239"},"M21-GAP-01239":{"line":4494,"offset":796073,"length":192,"previous":"M21-GAP-01238","next":"M21-GAP-01240"},"M21-GAP-01240":{"line":4495,"offset":796265,"length":192,"previous":"M21-GAP-01239","next":"M21-GAP-01241"},"M21-GAP-01241":{"line":4496,"offset":796457,"length":192,"previous":"M21-GAP-01240","next":"M21-GAP-01242"},"M21-GAP-01242":{"line":4497,"offset":796649,"length":192,"previous":"M21-GAP-01241","next":"M21-GAP-01243"},"M21-GAP-01243":{"line":4498,"offset":796841,"length":190,"previous":"M21-GAP-01242","next":"M21-GAP-01244"},"M21-GAP-01244":{"line":4499,"offset":797031,"length":190,"previous":"M21-GAP-01243","next":"M21-GAP-01245"},"M21-GAP-01245":{"line":4500,"offset":797221,"length":190,"previous":"M21-GAP-01244","next":"M21-GAP-01246"},"M21-GAP-01246":{"line":4501,"offset":797411,"length":190,"previous":"M21-GAP-01245","next":"M21-GAP-01247"},"M21-GAP-01247":{"line":4502,"offset":797601,"length":190,"previous":"M21-GAP-01246","next":"M21-GAP-01248"},"M21-GAP-01248":{"line":4503,"offset":797791,"length":190,"previous":"M21-GAP-01247","next":"M21-GAP-01249"},"M21-GAP-01249":{"line":4504,"offset":797981,"length":190,"previous":"M21-GAP-01248","next":"M21-GAP-01250"},"M21-GAP-01250":{"line":4505,"offset":798171,"length":190,"previous":"M21-GAP-01249","next":"M21-GAP-01251"},"M21-GAP-01251":{"line":4506,"offset":798361,"length":190,"previous":"M21-GAP-01250","next":"M21-GAP-01252"},"M21-GAP-01252":{"line":4507,"offset":798551,"length":190,"previous":"M21-GAP-01251","next":"M21-GAP-01253"},"M21-GAP-01253":{"line":4508,"offset":798741,"length":193,"previous":"M21-GAP-01252","next":"M21-GAP-01254"},"M21-GAP-01254":{"line":4509,"offset":798934,"length":193,"previous":"M21-GAP-01253","next":"M21-GAP-01255"},"M21-GAP-01255":{"line":4510,"offset":799127,"length":194,"previous":"M21-GAP-01254","next":"M21-GAP-01256"},"M21-GAP-01256":{"line":4511,"offset":799321,"length":194,"previous":"M21-GAP-01255","next":"M21-GAP-01257"},"M21-GAP-01257":{"line":4512,"offset":799515,"length":194,"previous":"M21-GAP-01256","next":"M21-GAP-01258"},"M21-GAP-01258":{"line":4513,"offset":799709,"length":194,"previous":"M21-GAP-01257","next":"M21-GAP-01259"},"M21-GAP-01259":{"line":4514,"offset":799903,"length":194,"previous":"M21-GAP-01258","next":"M21-GAP-01260"},"M21-GAP-01260":{"line":4515,"offset":800097,"length":194,"previous":"M21-GAP-01259","next":"M21-GAP-01261"},"M21-GAP-01261":{"line":4516,"offset":800291,"length":194,"previous":"M21-GAP-01260","next":"M21-GAP-01262"},"M21-GAP-01262":{"line":4517,"offset":800485,"length":194,"previous":"M21-GAP-01261","next":"M21-GAP-01263"},"M21-GAP-01263":{"line":4518,"offset":800679,"length":194,"previous":"M21-GAP-01262","next":"M21-GAP-01264"},"M21-GAP-01264":{"line":4519,"offset":800873,"length":194,"previous":"M21-GAP-01263","next":"M21-GAP-01265"},"M21-GAP-01265":{"line":4520,"offset":801067,"length":193,"previous":"M21-GAP-01264","next":"M21-GAP-01266"},"M21-GAP-01266":{"line":4521,"offset":801260,"length":194,"previous":"M21-GAP-01265","next":"M21-GAP-01267"},"M21-GAP-01267":{"line":4522,"offset":801454,"length":194,"previous":"M21-GAP-01266","next":"M21-GAP-01268"},"M21-GAP-01268":{"line":4523,"offset":801648,"length":193,"previous":"M21-GAP-01267","next":"M21-GAP-01269"},"M21-GAP-01269":{"line":4524,"offset":801841,"length":193,"previous":"M21-GAP-01268","next":"M21-GAP-01270"},"M21-GAP-01270":{"line":4525,"offset":802034,"length":193,"previous":"M21-GAP-01269","next":"M21-GAP-01271"},"M21-GAP-01271":{"line":4526,"offset":802227,"length":193,"previous":"M21-GAP-01270","next":"M21-GAP-01272"},"M21-GAP-01272":{"line":4527,"offset":802420,"length":193,"previous":"M21-GAP-01271","next":"M21-GAP-01273"},"M21-GAP-01273":{"line":4528,"offset":802613,"length":193,"previous":"M21-GAP-01272","next":"M21-GAP-01274"},"M21-GAP-01274":{"line":4529,"offset":802806,"length":193,"previous":"M21-GAP-01273","next":"M21-GAP-01275"},"M21-GAP-01275":{"line":4530,"offset":802999,"length":193,"previous":"M21-GAP-01274","next":"M21-GAP-01276"},"M21-GAP-01276":{"line":4531,"offset":803192,"length":193,"previous":"M21-GAP-01275","next":"M21-GAP-01277"},"M21-GAP-01277":{"line":4532,"offset":803385,"length":194,"previous":"M21-GAP-01276","next":"M21-GAP-01278"},"M21-GAP-01278":{"line":4533,"offset":803579,"length":194,"previous":"M21-GAP-01277","next":"M21-GAP-01279"},"M21-GAP-01279":{"line":4534,"offset":803773,"length":194,"previous":"M21-GAP-01278","next":"M21-GAP-01280"},"M21-GAP-01280":{"line":4535,"offset":803967,"length":194,"previous":"M21-GAP-01279","next":"M21-GAP-01281"},"M21-GAP-01281":{"line":4536,"offset":804161,"length":194,"previous":"M21-GAP-01280","next":"M21-GAP-01282"},"M21-GAP-01282":{"line":4537,"offset":804355,"length":194,"previous":"M21-GAP-01281","next":"M21-GAP-01283"},"M21-GAP-01283":{"line":4538,"offset":804549,"length":194,"previous":"M21-GAP-01282","next":"M21-GAP-01284"},"M21-GAP-01284":{"line":4539,"offset":804743,"length":194,"previous":"M21-GAP-01283","next":"M21-GAP-01285"},"M21-GAP-01285":{"line":4540,"offset":804937,"length":194,"previous":"M21-GAP-01284","next":"M21-GAP-01286"},"M21-GAP-01286":{"line":4541,"offset":805131,"length":194,"previous":"M21-GAP-01285","next":"M21-GAP-01287"},"M21-GAP-01287":{"line":4542,"offset":805325,"length":193,"previous":"M21-GAP-01286","next":"M21-GAP-01288"},"M21-GAP-01288":{"line":4543,"offset":805518,"length":194,"previous":"M21-GAP-01287","next":"M21-GAP-01289"},"M21-GAP-01289":{"line":4544,"offset":805712,"length":194,"previous":"M21-GAP-01288","next":"M21-GAP-01290"},"M21-GAP-01290":{"line":4545,"offset":805906,"length":194,"previous":"M21-GAP-01289","next":"M21-GAP-01291"},"M21-GAP-01291":{"line":4546,"offset":806100,"length":194,"previous":"M21-GAP-01290","next":"M21-GAP-01292"},"M21-GAP-01292":{"line":4547,"offset":806294,"length":194,"previous":"M21-GAP-01291","next":"M21-GAP-01293"},"M21-GAP-01293":{"line":4548,"offset":806488,"length":194,"previous":"M21-GAP-01292","next":"M21-GAP-01294"},"M21-GAP-01294":{"line":4549,"offset":806682,"length":193,"previous":"M21-GAP-01293","next":"M21-GAP-01295"},"M21-GAP-01295":{"line":4550,"offset":806875,"length":193,"previous":"M21-GAP-01294","next":"M21-GAP-01296"},"M21-GAP-01296":{"line":4551,"offset":807068,"length":193,"previous":"M21-GAP-01295","next":"M21-GAP-01297"},"M21-GAP-01297":{"line":4552,"offset":807261,"length":193,"previous":"M21-GAP-01296","next":"M21-GAP-01298"},"M21-GAP-01298":{"line":4553,"offset":807454,"length":193,"previous":"M21-GAP-01297","next":"M21-GAP-01299"},"M21-GAP-01299":{"line":4554,"offset":807647,"length":193,"previous":"M21-GAP-01298","next":"M21-GAP-01300"},"M21-GAP-01300":{"line":4555,"offset":807840,"length":193,"previous":"M21-GAP-01299","next":"M21-GAP-01301"},"M21-GAP-01301":{"line":4556,"offset":808033,"length":180,"previous":"M21-GAP-01300","next":"M21-GAP-01302"},"M21-GAP-01302":{"line":4557,"offset":808213,"length":180,"previous":"M21-GAP-01301","next":"M21-GAP-01303"},"M21-GAP-01303":{"line":4558,"offset":808393,"length":180,"previous":"M21-GAP-01302","next":"M21-GAP-01304"},"M21-GAP-01304":{"line":4559,"offset":808573,"length":180,"previous":"M21-GAP-01303","next":"M21-GAP-01305"},"M21-GAP-01305":{"line":4560,"offset":808753,"length":180,"previous":"M21-GAP-01304","next":"M21-GAP-01306"},"M21-GAP-01306":{"line":4561,"offset":808933,"length":202,"previous":"M21-GAP-01305","next":"M21-GAP-01307"},"M21-GAP-01307":{"line":4562,"offset":809135,"length":205,"previous":"M21-GAP-01306","next":"M21-GAP-01308"},"M21-GAP-01308":{"line":4563,"offset":809340,"length":205,"previous":"M21-GAP-01307","next":"M21-GAP-01309"},"M21-GAP-01309":{"line":4564,"offset":809545,"length":205,"previous":"M21-GAP-01308","next":"M21-GAP-01310"},"M21-GAP-01310":{"line":4565,"offset":809750,"length":203,"previous":"M21-GAP-01309","next":"M21-GAP-01311"},"M21-GAP-01311":{"line":4566,"offset":809953,"length":205,"previous":"M21-GAP-01310","next":"M21-GAP-01312"},"M21-GAP-01312":{"line":4567,"offset":810158,"length":204,"previous":"M21-GAP-01311","next":"M21-GAP-01313"},"M21-GAP-01313":{"line":4568,"offset":810362,"length":220,"previous":"M21-GAP-01312","next":"M21-GAP-01314"},"M21-GAP-01314":{"line":4569,"offset":810582,"length":220,"previous":"M21-GAP-01313","next":"M21-GAP-01315"},"M21-GAP-01315":{"line":4570,"offset":810802,"length":220,"previous":"M21-GAP-01314","next":"M21-GAP-01316"},"M21-GAP-01316":{"line":4571,"offset":811022,"length":209,"previous":"M21-GAP-01315","next":"M21-GAP-01317"},"M21-GAP-01317":{"line":4572,"offset":811231,"length":209,"previous":"M21-GAP-01316","next":"M21-GAP-01318"},"M21-GAP-01318":{"line":4573,"offset":811440,"length":209,"previous":"M21-GAP-01317","next":"M21-GAP-01319"},"M21-GAP-01319":{"line":4574,"offset":811649,"length":223,"previous":"M21-GAP-01318","next":"M21-GAP-01320"},"M21-GAP-01320":{"line":4575,"offset":811872,"length":223,"previous":"M21-GAP-01319","next":"M21-GAP-01321"},"M21-GAP-01321":{"line":4576,"offset":812095,"length":223,"previous":"M21-GAP-01320","next":"M21-GAP-01322"},"M21-GAP-01322":{"line":4577,"offset":812318,"length":212,"previous":"M21-GAP-01321","next":"M21-GAP-01323"},"M21-GAP-01323":{"line":4578,"offset":812530,"length":212,"previous":"M21-GAP-01322","next":"M21-GAP-01324"},"M21-GAP-01324":{"line":4579,"offset":812742,"length":212,"previous":"M21-GAP-01323","next":"M21-GAP-01325"},"M21-GAP-01325":{"line":4580,"offset":812954,"length":222,"previous":"M21-GAP-01324","next":"M21-GAP-01326"},"M21-GAP-01326":{"line":4581,"offset":813176,"length":222,"previous":"M21-GAP-01325","next":"M21-GAP-01327"},"M21-GAP-01327":{"line":4582,"offset":813398,"length":222,"previous":"M21-GAP-01326","next":"M21-GAP-01328"},"M21-GAP-01328":{"line":4583,"offset":813620,"length":211,"previous":"M21-GAP-01327","next":"M21-GAP-01329"},"M21-GAP-01329":{"line":4584,"offset":813831,"length":211,"previous":"M21-GAP-01328","next":"M21-GAP-01330"},"M21-GAP-01330":{"line":4585,"offset":814042,"length":211,"previous":"M21-GAP-01329","next":"M21-GAP-01331"},"M21-GAP-01331":{"line":4586,"offset":814253,"length":208,"previous":"M21-GAP-01330","next":"M21-GAP-01332"},"M21-GAP-01332":{"line":4587,"offset":814461,"length":215,"previous":"M21-GAP-01331","next":"M21-GAP-01333"},"M21-GAP-01333":{"line":4588,"offset":814676,"length":215,"previous":"M21-GAP-01332","next":"M21-GAP-01334"},"M21-GAP-01334":{"line":4589,"offset":814891,"length":215,"previous":"M21-GAP-01333","next":"M21-GAP-01335"},"M21-GAP-01335":{"line":4590,"offset":815106,"length":204,"previous":"M21-GAP-01334","next":"M21-GAP-01336"},"M21-GAP-01336":{"line":4591,"offset":815310,"length":204,"previous":"M21-GAP-01335","next":"M21-GAP-01337"},"M21-GAP-01337":{"line":4592,"offset":815514,"length":204,"previous":"M21-GAP-01336","next":"M21-GAP-01338"},"M21-GAP-01338":{"line":4593,"offset":815718,"length":199,"previous":"M21-GAP-01337","next":"M21-GAP-01339"},"M21-GAP-01339":{"line":4594,"offset":815917,"length":203,"previous":"M21-GAP-01338","next":"M21-GAP-01340"},"M21-GAP-01340":{"line":4595,"offset":816120,"length":203,"previous":"M21-GAP-01339","next":"M21-GAP-01341"},"M21-GAP-01341":{"line":4596,"offset":816323,"length":201,"previous":"M21-GAP-01340","next":"M21-GAP-01342"},"M21-GAP-01342":{"line":4597,"offset":816524,"length":201,"previous":"M21-GAP-01341","next":"M21-GAP-01343"},"M21-GAP-01343":{"line":4598,"offset":816725,"length":201,"previous":"M21-GAP-01342","next":"M21-GAP-01344"},"M21-GAP-01344":{"line":4599,"offset":816926,"length":201,"previous":"M21-GAP-01343","next":"M21-GAP-01345"},"M21-GAP-01345":{"line":4600,"offset":817127,"length":201,"previous":"M21-GAP-01344","next":"M21-GAP-01346"},"M21-GAP-01346":{"line":4601,"offset":817328,"length":201,"previous":"M21-GAP-01345","next":"M21-GAP-01347"},"M21-GAP-01347":{"line":4602,"offset":817529,"length":202,"previous":"M21-GAP-01346","next":"M21-GAP-01348"},"M21-GAP-01348":{"line":4603,"offset":817731,"length":202,"previous":"M21-GAP-01347","next":"M21-GAP-01349"},"M21-GAP-01349":{"line":4604,"offset":817933,"length":202,"previous":"M21-GAP-01348","next":"M21-GAP-01350"},"M21-GAP-01350":{"line":4605,"offset":818135,"length":202,"previous":"M21-GAP-01349","next":"M21-GAP-01351"},"M21-GAP-01351":{"line":4606,"offset":818337,"length":202,"previous":"M21-GAP-01350","next":"M21-GAP-01352"},"M21-GAP-01352":{"line":4607,"offset":818539,"length":202,"previous":"M21-GAP-01351","next":"M21-GAP-01353"},"M21-GAP-01353":{"line":4608,"offset":818741,"length":202,"previous":"M21-GAP-01352","next":"M21-GAP-01354"},"M21-GAP-01354":{"line":4609,"offset":818943,"length":202,"previous":"M21-GAP-01353","next":"M21-GAP-01355"},"M21-GAP-01355":{"line":4610,"offset":819145,"length":202,"previous":"M21-GAP-01354","next":"M21-GAP-01356"},"M21-GAP-01356":{"line":4611,"offset":819347,"length":202,"previous":"M21-GAP-01355","next":"M21-GAP-01357"},"M21-GAP-01357":{"line":4612,"offset":819549,"length":207,"previous":"M21-GAP-01356","next":"M21-GAP-01358"},"M21-GAP-01358":{"line":4613,"offset":819756,"length":203,"previous":"M21-GAP-01357","next":"M21-GAP-01359"},"M21-GAP-01359":{"line":4614,"offset":819959,"length":202,"previous":"M21-GAP-01358","next":"M21-GAP-01360"},"M21-GAP-01360":{"line":4615,"offset":820161,"length":218,"previous":"M21-GAP-01359","next":"M21-GAP-01361"},"M21-GAP-01361":{"line":4616,"offset":820379,"length":218,"previous":"M21-GAP-01360","next":"M21-GAP-01362"},"M21-GAP-01362":{"line":4617,"offset":820597,"length":218,"previous":"M21-GAP-01361","next":"M21-GAP-01363"},"M21-GAP-01363":{"line":4618,"offset":820815,"length":207,"previous":"M21-GAP-01362","next":"M21-GAP-01364"},"M21-GAP-01364":{"line":4619,"offset":821022,"length":207,"previous":"M21-GAP-01363","next":"M21-GAP-01365"},"M21-GAP-01365":{"line":4620,"offset":821229,"length":207,"previous":"M21-GAP-01364","next":"M21-GAP-01366"},"M21-GAP-01366":{"line":4621,"offset":821436,"length":221,"previous":"M21-GAP-01365","next":"M21-GAP-01367"},"M21-GAP-01367":{"line":4622,"offset":821657,"length":221,"previous":"M21-GAP-01366","next":"M21-GAP-01368"},"M21-GAP-01368":{"line":4623,"offset":821878,"length":221,"previous":"M21-GAP-01367","next":"M21-GAP-01369"},"M21-GAP-01369":{"line":4624,"offset":822099,"length":210,"previous":"M21-GAP-01368","next":"M21-GAP-01370"},"M21-GAP-01370":{"line":4625,"offset":822309,"length":210,"previous":"M21-GAP-01369","next":"M21-GAP-01371"},"M21-GAP-01371":{"line":4626,"offset":822519,"length":210,"previous":"M21-GAP-01370","next":"M21-GAP-01372"},"M21-GAP-01372":{"line":4627,"offset":822729,"length":220,"previous":"M21-GAP-01371","next":"M21-GAP-01373"},"M21-GAP-01373":{"line":4628,"offset":822949,"length":220,"previous":"M21-GAP-01372","next":"M21-GAP-01374"},"M21-GAP-01374":{"line":4629,"offset":823169,"length":220,"previous":"M21-GAP-01373","next":"M21-GAP-01375"},"M21-GAP-01375":{"line":4630,"offset":823389,"length":209,"previous":"M21-GAP-01374","next":"M21-GAP-01376"},"M21-GAP-01376":{"line":4631,"offset":823598,"length":209,"previous":"M21-GAP-01375","next":"M21-GAP-01377"},"M21-GAP-01377":{"line":4632,"offset":823807,"length":209,"previous":"M21-GAP-01376","next":"M21-GAP-01378"},"M21-GAP-01378":{"line":4633,"offset":824016,"length":213,"previous":"M21-GAP-01377","next":"M21-GAP-01379"},"M21-GAP-01379":{"line":4634,"offset":824229,"length":213,"previous":"M21-GAP-01378","next":"M21-GAP-01380"},"M21-GAP-01380":{"line":4635,"offset":824442,"length":213,"previous":"M21-GAP-01379","next":"M21-GAP-01381"},"M21-GAP-01381":{"line":4636,"offset":824655,"length":202,"previous":"M21-GAP-01380","next":"M21-GAP-01382"},"M21-GAP-01382":{"line":4637,"offset":824857,"length":202,"previous":"M21-GAP-01381","next":"M21-GAP-01383"},"M21-GAP-01383":{"line":4638,"offset":825059,"length":202,"previous":"M21-GAP-01382","next":"M21-GAP-01384"},"M21-GAP-01384":{"line":4639,"offset":825261,"length":187,"previous":"M21-GAP-01383","next":"M21-GAP-01385"},"M21-GAP-01385":{"line":4640,"offset":825448,"length":187,"previous":"M21-GAP-01384","next":"M21-GAP-01386"},"M21-GAP-01386":{"line":4641,"offset":825635,"length":188,"previous":"M21-GAP-01385","next":"M21-GAP-01387"},"M21-GAP-01387":{"line":4642,"offset":825823,"length":187,"previous":"M21-GAP-01386","next":"M21-GAP-01388"},"M21-GAP-01388":{"line":4643,"offset":826010,"length":187,"previous":"M21-GAP-01387","next":"M21-GAP-01389"},"M21-GAP-01389":{"line":4644,"offset":826197,"length":187,"previous":"M21-GAP-01388","next":"M21-GAP-01390"},"M21-GAP-01390":{"line":4645,"offset":826384,"length":187,"previous":"M21-GAP-01389","next":"M21-GAP-01391"},"M21-GAP-01391":{"line":4646,"offset":826571,"length":187,"previous":"M21-GAP-01390","next":"M21-GAP-01392"},"M21-GAP-01392":{"line":4647,"offset":826758,"length":187,"previous":"M21-GAP-01391","next":"M21-GAP-01393"},"M21-GAP-01393":{"line":4648,"offset":826945,"length":187,"previous":"M21-GAP-01392","next":"M21-GAP-01394"},"M21-GAP-01394":{"line":4649,"offset":827132,"length":187,"previous":"M21-GAP-01393","next":"M21-GAP-01395"},"M21-GAP-01395":{"line":4650,"offset":827319,"length":178,"previous":"M21-GAP-01394","next":"M21-GAP-01396"},"M21-GAP-01396":{"line":4651,"offset":827497,"length":178,"previous":"M21-GAP-01395","next":"M21-GAP-01397"},"M21-GAP-01397":{"line":4652,"offset":827675,"length":179,"previous":"M21-GAP-01396","next":"M21-GAP-01398"},"M21-GAP-01398":{"line":4653,"offset":827854,"length":179,"previous":"M21-GAP-01397","next":"M21-GAP-01399"},"M21-GAP-01399":{"line":4654,"offset":828033,"length":179,"previous":"M21-GAP-01398","next":"M21-GAP-01400"},"M21-GAP-01400":{"line":4655,"offset":828212,"length":179,"previous":"M21-GAP-01399","next":"M21-GAP-01401"},"M21-GAP-01401":{"line":4656,"offset":828391,"length":179,"previous":"M21-GAP-01400","next":"M21-GAP-01402"},"M21-GAP-01402":{"line":4657,"offset":828570,"length":179,"previous":"M21-GAP-01401","next":"M21-GAP-01403"},"M21-GAP-01403":{"line":4658,"offset":828749,"length":179,"previous":"M21-GAP-01402","next":"M21-GAP-01404"},"M21-GAP-01404":{"line":4659,"offset":828928,"length":179,"previous":"M21-GAP-01403","next":"M21-GAP-01405"},"M21-GAP-01405":{"line":4660,"offset":829107,"length":179,"previous":"M21-GAP-01404","next":"M21-GAP-01406"},"M21-GAP-01406":{"line":4661,"offset":829286,"length":179,"previous":"M21-GAP-01405","next":"M21-GAP-01407"},"M21-GAP-01407":{"line":4662,"offset":829465,"length":178,"previous":"M21-GAP-01406","next":"M21-GAP-01408"},"M21-GAP-01408":{"line":4663,"offset":829643,"length":179,"previous":"M21-GAP-01407","next":"M21-GAP-01409"},"M21-GAP-01409":{"line":4664,"offset":829822,"length":179,"previous":"M21-GAP-01408","next":"M21-GAP-01410"},"M21-GAP-01410":{"line":4665,"offset":830001,"length":179,"previous":"M21-GAP-01409","next":"M21-GAP-01411"},"M21-GAP-01411":{"line":4666,"offset":830180,"length":179,"previous":"M21-GAP-01410","next":"M21-GAP-01412"},"M21-GAP-01412":{"line":4667,"offset":830359,"length":179,"previous":"M21-GAP-01411","next":"M21-GAP-01413"},"M21-GAP-01413":{"line":4668,"offset":830538,"length":179,"previous":"M21-GAP-01412","next":"M21-GAP-01414"},"M21-GAP-01414":{"line":4669,"offset":830717,"length":178,"previous":"M21-GAP-01413","next":"M21-GAP-01415"},"M21-GAP-01415":{"line":4670,"offset":830895,"length":178,"previous":"M21-GAP-01414","next":"M21-GAP-01416"},"M21-GAP-01416":{"line":4671,"offset":831073,"length":178,"previous":"M21-GAP-01415","next":"M21-GAP-01417"},"M21-GAP-01417":{"line":4672,"offset":831251,"length":178,"previous":"M21-GAP-01416","next":"M21-GAP-01418"},"M21-GAP-01418":{"line":4673,"offset":831429,"length":178,"previous":"M21-GAP-01417","next":"M21-GAP-01419"},"M21-GAP-01419":{"line":4674,"offset":831607,"length":178,"previous":"M21-GAP-01418","next":"M21-GAP-01420"},"M21-GAP-01420":{"line":4675,"offset":831785,"length":178,"previous":"M21-GAP-01419","next":"M21-GAP-01421"},"M21-GAP-01421":{"line":4676,"offset":831963,"length":179,"previous":"M21-GAP-01420","next":"M21-GAP-01422"},"M21-GAP-01422":{"line":4677,"offset":832142,"length":179,"previous":"M21-GAP-01421","next":"M21-GAP-01423"},"M21-GAP-01423":{"line":4678,"offset":832321,"length":180,"previous":"M21-GAP-01422","next":"M21-GAP-01424"},"M21-GAP-01424":{"line":4679,"offset":832501,"length":180,"previous":"M21-GAP-01423","next":"M21-GAP-01425"},"M21-GAP-01425":{"line":4680,"offset":832681,"length":180,"previous":"M21-GAP-01424","next":"M21-GAP-01426"},"M21-GAP-01426":{"line":4681,"offset":832861,"length":180,"previous":"M21-GAP-01425","next":"M21-GAP-01427"},"M21-GAP-01427":{"line":4682,"offset":833041,"length":180,"previous":"M21-GAP-01426","next":"M21-GAP-01428"},"M21-GAP-01428":{"line":4683,"offset":833221,"length":180,"previous":"M21-GAP-01427","next":"M21-GAP-01429"},"M21-GAP-01429":{"line":4684,"offset":833401,"length":180,"previous":"M21-GAP-01428","next":"M21-GAP-01430"},"M21-GAP-01430":{"line":4685,"offset":833581,"length":180,"previous":"M21-GAP-01429","next":"M21-GAP-01431"},"M21-GAP-01431":{"line":4686,"offset":833761,"length":180,"previous":"M21-GAP-01430","next":"M21-GAP-01432"},"M21-GAP-01432":{"line":4687,"offset":833941,"length":180,"previous":"M21-GAP-01431","next":"M21-GAP-01433"},"M21-GAP-01433":{"line":4688,"offset":834121,"length":179,"previous":"M21-GAP-01432","next":"M21-GAP-01434"},"M21-GAP-01434":{"line":4689,"offset":834300,"length":180,"previous":"M21-GAP-01433","next":"M21-GAP-01435"},"M21-GAP-01435":{"line":4690,"offset":834480,"length":180,"previous":"M21-GAP-01434","next":"M21-GAP-01436"},"M21-GAP-01436":{"line":4691,"offset":834660,"length":180,"previous":"M21-GAP-01435","next":"M21-GAP-01437"},"M21-GAP-01437":{"line":4692,"offset":834840,"length":180,"previous":"M21-GAP-01436","next":"M21-GAP-01438"},"M21-GAP-01438":{"line":4693,"offset":835020,"length":180,"previous":"M21-GAP-01437","next":"M21-GAP-01439"},"M21-GAP-01439":{"line":4694,"offset":835200,"length":180,"previous":"M21-GAP-01438","next":"M21-GAP-01440"},"M21-GAP-01440":{"line":4695,"offset":835380,"length":180,"previous":"M21-GAP-01439","next":"M21-GAP-01441"},"M21-GAP-01441":{"line":4696,"offset":835560,"length":180,"previous":"M21-GAP-01440","next":"M21-GAP-01442"},"M21-GAP-01442":{"line":4697,"offset":835740,"length":180,"previous":"M21-GAP-01441","next":"M21-GAP-01443"},"M21-GAP-01443":{"line":4698,"offset":835920,"length":180,"previous":"M21-GAP-01442","next":"M21-GAP-01444"},"M21-GAP-01444":{"line":4699,"offset":836100,"length":179,"previous":"M21-GAP-01443","next":"M21-GAP-01445"},"M21-GAP-01445":{"line":4700,"offset":836279,"length":180,"previous":"M21-GAP-01444","next":"M21-GAP-01446"},"M21-GAP-01446":{"line":4701,"offset":836459,"length":180,"previous":"M21-GAP-01445","next":"M21-GAP-01447"},"M21-GAP-01447":{"line":4702,"offset":836639,"length":180,"previous":"M21-GAP-01446","next":"M21-GAP-01448"},"M21-GAP-01448":{"line":4703,"offset":836819,"length":180,"previous":"M21-GAP-01447","next":"M21-GAP-01449"},"M21-GAP-01449":{"line":4704,"offset":836999,"length":180,"previous":"M21-GAP-01448","next":"M21-GAP-01450"},"M21-GAP-01450":{"line":4705,"offset":837179,"length":180,"previous":"M21-GAP-01449","next":"M21-GAP-01451"},"M21-GAP-01451":{"line":4706,"offset":837359,"length":180,"previous":"M21-GAP-01450","next":"M21-GAP-01452"},"M21-GAP-01452":{"line":4707,"offset":837539,"length":180,"previous":"M21-GAP-01451","next":"M21-GAP-01453"},"M21-GAP-01453":{"line":4708,"offset":837719,"length":180,"previous":"M21-GAP-01452","next":"M21-GAP-01454"},"M21-GAP-01454":{"line":4709,"offset":837899,"length":180,"previous":"M21-GAP-01453","next":"M21-GAP-01455"},"M21-GAP-01455":{"line":4710,"offset":838079,"length":179,"previous":"M21-GAP-01454","next":"M21-GAP-01456"},"M21-GAP-01456":{"line":4711,"offset":838258,"length":180,"previous":"M21-GAP-01455","next":"M21-GAP-01457"},"M21-GAP-01457":{"line":4712,"offset":838438,"length":180,"previous":"M21-GAP-01456","next":"M21-GAP-01458"},"M21-GAP-01458":{"line":4713,"offset":838618,"length":180,"previous":"M21-GAP-01457","next":"M21-GAP-01459"},"M21-GAP-01459":{"line":4714,"offset":838798,"length":180,"previous":"M21-GAP-01458","next":"M21-GAP-01460"},"M21-GAP-01460":{"line":4715,"offset":838978,"length":180,"previous":"M21-GAP-01459","next":"M21-GAP-01461"},"M21-GAP-01461":{"line":4716,"offset":839158,"length":180,"previous":"M21-GAP-01460","next":"M21-GAP-01462"},"M21-GAP-01462":{"line":4717,"offset":839338,"length":180,"previous":"M21-GAP-01461","next":"M21-GAP-01463"},"M21-GAP-01463":{"line":4718,"offset":839518,"length":180,"previous":"M21-GAP-01462","next":"M21-GAP-01464"},"M21-GAP-01464":{"line":4719,"offset":839698,"length":180,"previous":"M21-GAP-01463","next":"M21-GAP-01465"},"M21-GAP-01465":{"line":4720,"offset":839878,"length":180,"previous":"M21-GAP-01464","next":"M21-GAP-01466"},"M21-GAP-01466":{"line":4721,"offset":840058,"length":179,"previous":"M21-GAP-01465","next":"M21-GAP-01467"},"M21-GAP-01467":{"line":4722,"offset":840237,"length":180,"previous":"M21-GAP-01466","next":"M21-GAP-01468"},"M21-GAP-01468":{"line":4723,"offset":840417,"length":179,"previous":"M21-GAP-01467","next":"M21-GAP-01469"},"M21-GAP-01469":{"line":4724,"offset":840596,"length":179,"previous":"M21-GAP-01468","next":"M21-GAP-01470"},"M21-GAP-01470":{"line":4725,"offset":840775,"length":179,"previous":"M21-GAP-01469","next":"M21-GAP-01471"},"M21-GAP-01471":{"line":4726,"offset":840954,"length":179,"previous":"M21-GAP-01470","next":"M21-GAP-01472"},"M21-GAP-01472":{"line":4727,"offset":841133,"length":170,"previous":"M21-GAP-01471","next":"M21-GAP-01473"},"M21-GAP-01473":{"line":4728,"offset":841303,"length":170,"previous":"M21-GAP-01472","next":"M21-GAP-01474"},"M21-GAP-01474":{"line":4729,"offset":841473,"length":171,"previous":"M21-GAP-01473","next":"M21-GAP-01475"},"M21-GAP-01475":{"line":4730,"offset":841644,"length":171,"previous":"M21-GAP-01474","next":"M21-GAP-01476"},"M21-GAP-01476":{"line":4731,"offset":841815,"length":171,"previous":"M21-GAP-01475","next":"M21-GAP-01477"},"M21-GAP-01477":{"line":4732,"offset":841986,"length":171,"previous":"M21-GAP-01476","next":"M21-GAP-01478"},"M21-GAP-01478":{"line":4733,"offset":842157,"length":170,"previous":"M21-GAP-01477","next":"M21-GAP-01479"},"M21-GAP-01479":{"line":4734,"offset":842327,"length":170,"previous":"M21-GAP-01478","next":"M21-GAP-01480"},"M21-GAP-01480":{"line":4735,"offset":842497,"length":170,"previous":"M21-GAP-01479","next":"M21-GAP-01481"},"M21-GAP-01481":{"line":4736,"offset":842667,"length":170,"previous":"M21-GAP-01480","next":"M21-GAP-01482"},"M21-GAP-01482":{"line":4737,"offset":842837,"length":170,"previous":"M21-GAP-01481","next":"M21-GAP-01483"},"M21-GAP-01483":{"line":4738,"offset":843007,"length":170,"previous":"M21-GAP-01482","next":"M21-GAP-01484"},"M21-GAP-01484":{"line":4739,"offset":843177,"length":170,"previous":"M21-GAP-01483","next":"M21-GAP-01485"},"M21-GAP-01485":{"line":4740,"offset":843347,"length":170,"previous":"M21-GAP-01484","next":"M21-GAP-01486"},"M21-GAP-01486":{"line":4741,"offset":843517,"length":193,"previous":"M21-GAP-01485","next":"M21-GAP-01487"},"M21-GAP-01487":{"line":4742,"offset":843710,"length":193,"previous":"M21-GAP-01486","next":"M21-GAP-01488"},"M21-GAP-01488":{"line":4743,"offset":843903,"length":193,"previous":"M21-GAP-01487","next":"M21-GAP-01489"},"M21-GAP-01489":{"line":4744,"offset":844096,"length":193,"previous":"M21-GAP-01488","next":"M21-GAP-01490"},"M21-GAP-01490":{"line":4745,"offset":844289,"length":193,"previous":"M21-GAP-01489","next":"M21-GAP-01491"},"M21-GAP-01491":{"line":4746,"offset":844482,"length":193,"previous":"M21-GAP-01490","next":"M21-GAP-01492"},"M21-GAP-01492":{"line":4747,"offset":844675,"length":193,"previous":"M21-GAP-01491","next":"M21-GAP-01493"},"M21-GAP-01493":{"line":4748,"offset":844868,"length":187,"previous":"M21-GAP-01492","next":"M21-GAP-01494"},"M21-GAP-01494":{"line":4749,"offset":845055,"length":187,"previous":"M21-GAP-01493","next":"M21-GAP-01495"},"M21-GAP-01495":{"line":4750,"offset":845242,"length":188,"previous":"M21-GAP-01494","next":"M21-GAP-01496"},"M21-GAP-01496":{"line":4751,"offset":845430,"length":188,"previous":"M21-GAP-01495","next":"M21-GAP-01497"},"M21-GAP-01497":{"line":4752,"offset":845618,"length":188,"previous":"M21-GAP-01496","next":"M21-GAP-01498"},"M21-GAP-01498":{"line":4753,"offset":845806,"length":188,"previous":"M21-GAP-01497","next":"M21-GAP-01499"},"M21-GAP-01499":{"line":4754,"offset":845994,"length":188,"previous":"M21-GAP-01498","next":"M21-GAP-01500"},"M21-GAP-01500":{"line":4755,"offset":846182,"length":188,"previous":"M21-GAP-01499","next":"M21-GAP-01501"},"M21-GAP-01501":{"line":4756,"offset":846370,"length":188,"previous":"M21-GAP-01500","next":"M21-GAP-01502"},"M21-GAP-01502":{"line":4757,"offset":846558,"length":188,"previous":"M21-GAP-01501","next":"M21-GAP-01503"},"M21-GAP-01503":{"line":4758,"offset":846746,"length":188,"previous":"M21-GAP-01502","next":"M21-GAP-01504"},"M21-GAP-01504":{"line":4759,"offset":846934,"length":188,"previous":"M21-GAP-01503","next":"M21-GAP-01505"},"M21-GAP-01505":{"line":4760,"offset":847122,"length":187,"previous":"M21-GAP-01504","next":"M21-GAP-01506"},"M21-GAP-01506":{"line":4761,"offset":847309,"length":188,"previous":"M21-GAP-01505","next":"M21-GAP-01507"},"M21-GAP-01507":{"line":4762,"offset":847497,"length":188,"previous":"M21-GAP-01506","next":"M21-GAP-01508"},"M21-GAP-01508":{"line":4763,"offset":847685,"length":188,"previous":"M21-GAP-01507","next":"M21-GAP-01509"},"M21-GAP-01509":{"line":4764,"offset":847873,"length":188,"previous":"M21-GAP-01508","next":"M21-GAP-01510"},"M21-GAP-01510":{"line":4765,"offset":848061,"length":188,"previous":"M21-GAP-01509","next":"M21-GAP-01511"},"M21-GAP-01511":{"line":4766,"offset":848249,"length":187,"previous":"M21-GAP-01510","next":"M21-GAP-01512"},"M21-GAP-01512":{"line":4767,"offset":848436,"length":187,"previous":"M21-GAP-01511","next":"M21-GAP-01513"},"M21-GAP-01513":{"line":4768,"offset":848623,"length":187,"previous":"M21-GAP-01512","next":"M21-GAP-01514"},"M21-GAP-01514":{"line":4769,"offset":848810,"length":187,"previous":"M21-GAP-01513","next":"M21-GAP-01515"},"M21-GAP-01515":{"line":4770,"offset":848997,"length":187,"previous":"M21-GAP-01514","next":"M21-GAP-01516"},"M21-GAP-01516":{"line":4771,"offset":849184,"length":187,"previous":"M21-GAP-01515","next":"M21-GAP-01517"},"M21-GAP-01517":{"line":4772,"offset":849371,"length":187,"previous":"M21-GAP-01516","next":"M21-GAP-01518"},"M21-GAP-01518":{"line":4773,"offset":849558,"length":174,"previous":"M21-GAP-01517","next":"M21-GAP-01519"},"M21-GAP-01519":{"line":4774,"offset":849732,"length":174,"previous":"M21-GAP-01518","next":"M21-GAP-01520"},"M21-GAP-01520":{"line":4775,"offset":849906,"length":175,"previous":"M21-GAP-01519","next":"M21-GAP-01521"},"M21-GAP-01521":{"line":4776,"offset":850081,"length":175,"previous":"M21-GAP-01520","next":"M21-GAP-01522"},"M21-GAP-01522":{"line":4777,"offset":850256,"length":175,"previous":"M21-GAP-01521","next":"M21-GAP-01523"},"M21-GAP-01523":{"line":4778,"offset":850431,"length":175,"previous":"M21-GAP-01522","next":"M21-GAP-01524"},"M21-GAP-01524":{"line":4779,"offset":850606,"length":175,"previous":"M21-GAP-01523","next":"M21-GAP-01525"},"M21-GAP-01525":{"line":4780,"offset":850781,"length":175,"previous":"M21-GAP-01524","next":"M21-GAP-01526"},"M21-GAP-01526":{"line":4781,"offset":850956,"length":175,"previous":"M21-GAP-01525","next":"M21-GAP-01527"},"M21-GAP-01527":{"line":4782,"offset":851131,"length":175,"previous":"M21-GAP-01526","next":"M21-GAP-01528"},"M21-GAP-01528":{"line":4783,"offset":851306,"length":175,"previous":"M21-GAP-01527","next":"M21-GAP-01529"},"M21-GAP-01529":{"line":4784,"offset":851481,"length":175,"previous":"M21-GAP-01528","next":"M21-GAP-01530"},"M21-GAP-01530":{"line":4785,"offset":851656,"length":174,"previous":"M21-GAP-01529","next":"M21-GAP-01531"},"M21-GAP-01531":{"line":4786,"offset":851830,"length":175,"previous":"M21-GAP-01530","next":"M21-GAP-01532"},"M21-GAP-01532":{"line":4787,"offset":852005,"length":174,"previous":"M21-GAP-01531","next":"M21-GAP-01533"},"M21-GAP-01533":{"line":4788,"offset":852179,"length":174,"previous":"M21-GAP-01532","next":"M21-GAP-01534"},"M21-GAP-01534":{"line":4789,"offset":852353,"length":174,"previous":"M21-GAP-01533","next":"M21-GAP-01535"},"M21-GAP-01535":{"line":4790,"offset":852527,"length":174,"previous":"M21-GAP-01534","next":"M21-GAP-01536"},"M21-GAP-01536":{"line":4791,"offset":852701,"length":174,"previous":"M21-GAP-01535","next":"M21-GAP-01537"},"M21-GAP-01537":{"line":4792,"offset":852875,"length":174,"previous":"M21-GAP-01536","next":"M21-GAP-01538"},"M21-GAP-01538":{"line":4793,"offset":853049,"length":174,"previous":"M21-GAP-01537","next":"M21-GAP-01539"},"M21-GAP-01539":{"line":4794,"offset":853223,"length":174,"previous":"M21-GAP-01538","next":"M21-GAP-01540"},"M21-GAP-01540":{"line":4795,"offset":853397,"length":174,"previous":"M21-GAP-01539","next":"M21-GAP-01541"},"M21-GAP-01541":{"line":4796,"offset":853571,"length":175,"previous":"M21-GAP-01540","next":"M21-GAP-01542"},"M21-GAP-01542":{"line":4797,"offset":853746,"length":175,"previous":"M21-GAP-01541","next":"M21-GAP-01543"},"M21-GAP-01543":{"line":4798,"offset":853921,"length":175,"previous":"M21-GAP-01542","next":"M21-GAP-01544"},"M21-GAP-01544":{"line":4799,"offset":854096,"length":175,"previous":"M21-GAP-01543","next":"M21-GAP-01545"},"M21-GAP-01545":{"line":4800,"offset":854271,"length":175,"previous":"M21-GAP-01544","next":"M21-GAP-01546"},"M21-GAP-01546":{"line":4801,"offset":854446,"length":175,"previous":"M21-GAP-01545","next":"M21-GAP-01547"},"M21-GAP-01547":{"line":4802,"offset":854621,"length":175,"previous":"M21-GAP-01546","next":"M21-GAP-01548"},"M21-GAP-01548":{"line":4803,"offset":854796,"length":175,"previous":"M21-GAP-01547","next":"M21-GAP-01549"},"M21-GAP-01549":{"line":4804,"offset":854971,"length":175,"previous":"M21-GAP-01548","next":"M21-GAP-01550"},"M21-GAP-01550":{"line":4805,"offset":855146,"length":175,"previous":"M21-GAP-01549","next":"M21-GAP-01551"},"M21-GAP-01551":{"line":4806,"offset":855321,"length":174,"previous":"M21-GAP-01550","next":"M21-GAP-01552"},"M21-GAP-01552":{"line":4807,"offset":855495,"length":175,"previous":"M21-GAP-01551","next":"M21-GAP-01553"},"M21-GAP-01553":{"line":4808,"offset":855670,"length":175,"previous":"M21-GAP-01552","next":"M21-GAP-01554"},"M21-GAP-01554":{"line":4809,"offset":855845,"length":175,"previous":"M21-GAP-01553","next":"M21-GAP-01555"},"M21-GAP-01555":{"line":4810,"offset":856020,"length":175,"previous":"M21-GAP-01554","next":"M21-GAP-01556"},"M21-GAP-01556":{"line":4811,"offset":856195,"length":175,"previous":"M21-GAP-01555","next":"M21-GAP-01557"},"M21-GAP-01557":{"line":4812,"offset":856370,"length":174,"previous":"M21-GAP-01556","next":"M21-GAP-01558"},"M21-GAP-01558":{"line":4813,"offset":856544,"length":174,"previous":"M21-GAP-01557","next":"M21-GAP-01559"},"M21-GAP-01559":{"line":4814,"offset":856718,"length":174,"previous":"M21-GAP-01558","next":"M21-GAP-01560"},"M21-GAP-01560":{"line":4815,"offset":856892,"length":174,"previous":"M21-GAP-01559","next":"M21-GAP-01561"},"M21-GAP-01561":{"line":4816,"offset":857066,"length":174,"previous":"M21-GAP-01560","next":"M21-GAP-01562"},"M21-GAP-01562":{"line":4817,"offset":857240,"length":174,"previous":"M21-GAP-01561","next":"M21-GAP-01563"},"M21-GAP-01563":{"line":4818,"offset":857414,"length":174,"previous":"M21-GAP-01562","next":"M21-GAP-01564"},"M21-GAP-01564":{"line":4819,"offset":857588,"length":179,"previous":"M21-GAP-01563","next":"M21-GAP-01565"},"M21-GAP-01565":{"line":4820,"offset":857767,"length":179,"previous":"M21-GAP-01564","next":"M21-GAP-01566"},"M21-GAP-01566":{"line":4821,"offset":857946,"length":180,"previous":"M21-GAP-01565","next":"M21-GAP-01567"},"M21-GAP-01567":{"line":4822,"offset":858126,"length":180,"previous":"M21-GAP-01566","next":"M21-GAP-01568"},"M21-GAP-01568":{"line":4823,"offset":858306,"length":180,"previous":"M21-GAP-01567","next":"M21-GAP-01569"},"M21-GAP-01569":{"line":4824,"offset":858486,"length":180,"previous":"M21-GAP-01568","next":"M21-GAP-01570"},"M21-GAP-01570":{"line":4825,"offset":858666,"length":180,"previous":"M21-GAP-01569","next":"M21-GAP-01571"},"M21-GAP-01571":{"line":4826,"offset":858846,"length":180,"previous":"M21-GAP-01570","next":"M21-GAP-01572"},"M21-GAP-01572":{"line":4827,"offset":859026,"length":180,"previous":"M21-GAP-01571","next":"M21-GAP-01573"},"M21-GAP-01573":{"line":4828,"offset":859206,"length":180,"previous":"M21-GAP-01572","next":"M21-GAP-01574"},"M21-GAP-01574":{"line":4829,"offset":859386,"length":180,"previous":"M21-GAP-01573","next":"M21-GAP-01575"},"M21-GAP-01575":{"line":4830,"offset":859566,"length":180,"previous":"M21-GAP-01574","next":"M21-GAP-01576"},"M21-GAP-01576":{"line":4831,"offset":859746,"length":179,"previous":"M21-GAP-01575","next":"M21-GAP-01577"},"M21-GAP-01577":{"line":4832,"offset":859925,"length":180,"previous":"M21-GAP-01576","next":"M21-GAP-01578"},"M21-GAP-01578":{"line":4833,"offset":860105,"length":180,"previous":"M21-GAP-01577","next":"M21-GAP-01579"},"M21-GAP-01579":{"line":4834,"offset":860285,"length":180,"previous":"M21-GAP-01578","next":"M21-GAP-01580"},"M21-GAP-01580":{"line":4835,"offset":860465,"length":180,"previous":"M21-GAP-01579","next":"M21-GAP-01581"},"M21-GAP-01581":{"line":4836,"offset":860645,"length":180,"previous":"M21-GAP-01580","next":"M21-GAP-01582"},"M21-GAP-01582":{"line":4837,"offset":860825,"length":180,"previous":"M21-GAP-01581","next":"M21-GAP-01583"},"M21-GAP-01583":{"line":4838,"offset":861005,"length":180,"previous":"M21-GAP-01582","next":"M21-GAP-01584"},"M21-GAP-01584":{"line":4839,"offset":861185,"length":180,"previous":"M21-GAP-01583","next":"M21-GAP-01585"},"M21-GAP-01585":{"line":4840,"offset":861365,"length":180,"previous":"M21-GAP-01584","next":"M21-GAP-01586"},"M21-GAP-01586":{"line":4841,"offset":861545,"length":180,"previous":"M21-GAP-01585","next":"M21-GAP-01587"},"M21-GAP-01587":{"line":4842,"offset":861725,"length":179,"previous":"M21-GAP-01586","next":"M21-GAP-01588"},"M21-GAP-01588":{"line":4843,"offset":861904,"length":180,"previous":"M21-GAP-01587","next":"M21-GAP-01589"},"M21-GAP-01589":{"line":4844,"offset":862084,"length":180,"previous":"M21-GAP-01588","next":"M21-GAP-01590"},"M21-GAP-01590":{"line":4845,"offset":862264,"length":180,"previous":"M21-GAP-01589","next":"M21-GAP-01591"},"M21-GAP-01591":{"line":4846,"offset":862444,"length":180,"previous":"M21-GAP-01590","next":"M21-GAP-01592"},"M21-GAP-01592":{"line":4847,"offset":862624,"length":180,"previous":"M21-GAP-01591","next":"M21-GAP-01593"},"M21-GAP-01593":{"line":4848,"offset":862804,"length":180,"previous":"M21-GAP-01592","next":"M21-GAP-01594"},"M21-GAP-01594":{"line":4849,"offset":862984,"length":180,"previous":"M21-GAP-01593","next":"M21-GAP-01595"},"M21-GAP-01595":{"line":4850,"offset":863164,"length":180,"previous":"M21-GAP-01594","next":"M21-GAP-01596"},"M21-GAP-01596":{"line":4851,"offset":863344,"length":180,"previous":"M21-GAP-01595","next":"M21-GAP-01597"},"M21-GAP-01597":{"line":4852,"offset":863524,"length":180,"previous":"M21-GAP-01596","next":"M21-GAP-01598"},"M21-GAP-01598":{"line":4853,"offset":863704,"length":179,"previous":"M21-GAP-01597","next":"M21-GAP-01599"},"M21-GAP-01599":{"line":4854,"offset":863883,"length":180,"previous":"M21-GAP-01598","next":"M21-GAP-01600"},"M21-GAP-01600":{"line":4855,"offset":864063,"length":180,"previous":"M21-GAP-01599","next":"M21-GAP-01601"},"M21-GAP-01601":{"line":4856,"offset":864243,"length":180,"previous":"M21-GAP-01600","next":"M21-GAP-01602"},"M21-GAP-01602":{"line":4857,"offset":864423,"length":180,"previous":"M21-GAP-01601","next":"M21-GAP-01603"},"M21-GAP-01603":{"line":4858,"offset":864603,"length":180,"previous":"M21-GAP-01602","next":"M21-GAP-01604"},"M21-GAP-01604":{"line":4859,"offset":864783,"length":180,"previous":"M21-GAP-01603","next":"M21-GAP-01605"},"M21-GAP-01605":{"line":4860,"offset":864963,"length":180,"previous":"M21-GAP-01604","next":"M21-GAP-01606"},"M21-GAP-01606":{"line":4861,"offset":865143,"length":180,"previous":"M21-GAP-01605","next":"M21-GAP-01607"},"M21-GAP-01607":{"line":4862,"offset":865323,"length":179,"previous":"M21-GAP-01606","next":"M21-GAP-01608"},"M21-GAP-01608":{"line":4863,"offset":865502,"length":179,"previous":"M21-GAP-01607","next":"M21-GAP-01609"},"M21-GAP-01609":{"line":4864,"offset":865681,"length":179,"previous":"M21-GAP-01608","next":"M21-GAP-01610"},"M21-GAP-01610":{"line":4865,"offset":865860,"length":179,"previous":"M21-GAP-01609","next":"M21-GAP-01611"},"M21-GAP-01611":{"line":4866,"offset":866039,"length":179,"previous":"M21-GAP-01610","next":"M21-GAP-01612"},"M21-GAP-01612":{"line":4867,"offset":866218,"length":188,"previous":"M21-GAP-01611","next":"M21-GAP-01613"},"M21-GAP-01613":{"line":4868,"offset":866406,"length":188,"previous":"M21-GAP-01612","next":"M21-GAP-01614"},"M21-GAP-01614":{"line":4869,"offset":866594,"length":188,"previous":"M21-GAP-01613","next":"M21-GAP-01615"},"M21-GAP-01615":{"line":4870,"offset":866782,"length":188,"previous":"M21-GAP-01614","next":"M21-GAP-01616"},"M21-GAP-01616":{"line":4871,"offset":866970,"length":188,"previous":"M21-GAP-01615","next":"M21-GAP-01617"},"M21-GAP-01617":{"line":4872,"offset":867158,"length":188,"previous":"M21-GAP-01616","next":"M21-GAP-01618"},"M21-GAP-01618":{"line":4873,"offset":867346,"length":171,"previous":"M21-GAP-01617","next":"M21-GAP-01619"},"M21-GAP-01619":{"line":4874,"offset":867517,"length":171,"previous":"M21-GAP-01618","next":"M21-GAP-01620"},"M21-GAP-01620":{"line":4875,"offset":867688,"length":172,"previous":"M21-GAP-01619","next":"M21-GAP-01621"},"M21-GAP-01621":{"line":4876,"offset":867860,"length":172,"previous":"M21-GAP-01620","next":"M21-GAP-01622"},"M21-GAP-01622":{"line":4877,"offset":868032,"length":172,"previous":"M21-GAP-01621","next":"M21-GAP-01623"},"M21-GAP-01623":{"line":4878,"offset":868204,"length":172,"previous":"M21-GAP-01622","next":"M21-GAP-01624"},"M21-GAP-01624":{"line":4879,"offset":868376,"length":172,"previous":"M21-GAP-01623","next":"M21-GAP-01625"},"M21-GAP-01625":{"line":4880,"offset":868548,"length":172,"previous":"M21-GAP-01624","next":"M21-GAP-01626"},"M21-GAP-01626":{"line":4881,"offset":868720,"length":172,"previous":"M21-GAP-01625","next":"M21-GAP-01627"},"M21-GAP-01627":{"line":4882,"offset":868892,"length":172,"previous":"M21-GAP-01626","next":"M21-GAP-01628"},"M21-GAP-01628":{"line":4883,"offset":869064,"length":172,"previous":"M21-GAP-01627","next":"M21-GAP-01629"},"M21-GAP-01629":{"line":4884,"offset":869236,"length":172,"previous":"M21-GAP-01628","next":"M21-GAP-01630"},"M21-GAP-01630":{"line":4885,"offset":869408,"length":171,"previous":"M21-GAP-01629","next":"M21-GAP-01631"},"M21-GAP-01631":{"line":4886,"offset":869579,"length":172,"previous":"M21-GAP-01630","next":"M21-GAP-01632"},"M21-GAP-01632":{"line":4887,"offset":869751,"length":172,"previous":"M21-GAP-01631","next":"M21-GAP-01633"},"M21-GAP-01633":{"line":4888,"offset":869923,"length":172,"previous":"M21-GAP-01632","next":"M21-GAP-01634"},"M21-GAP-01634":{"line":4889,"offset":870095,"length":172,"previous":"M21-GAP-01633","next":"M21-GAP-01635"},"M21-GAP-01635":{"line":4890,"offset":870267,"length":172,"previous":"M21-GAP-01634","next":"M21-GAP-01636"},"M21-GAP-01636":{"line":4891,"offset":870439,"length":172,"previous":"M21-GAP-01635","next":"M21-GAP-01637"},"M21-GAP-01637":{"line":4892,"offset":870611,"length":172,"previous":"M21-GAP-01636","next":"M21-GAP-01638"},"M21-GAP-01638":{"line":4893,"offset":870783,"length":172,"previous":"M21-GAP-01637","next":"M21-GAP-01639"},"M21-GAP-01639":{"line":4894,"offset":870955,"length":172,"previous":"M21-GAP-01638","next":"M21-GAP-01640"},"M21-GAP-01640":{"line":4895,"offset":871127,"length":172,"previous":"M21-GAP-01639","next":"M21-GAP-01641"},"M21-GAP-01641":{"line":4896,"offset":871299,"length":171,"previous":"M21-GAP-01640","next":"M21-GAP-01642"},"M21-GAP-01642":{"line":4897,"offset":871470,"length":172,"previous":"M21-GAP-01641","next":"M21-GAP-01643"},"M21-GAP-01643":{"line":4898,"offset":871642,"length":172,"previous":"M21-GAP-01642","next":"M21-GAP-01644"},"M21-GAP-01644":{"line":4899,"offset":871814,"length":172,"previous":"M21-GAP-01643","next":"M21-GAP-01645"},"M21-GAP-01645":{"line":4900,"offset":871986,"length":172,"previous":"M21-GAP-01644","next":"M21-GAP-01646"},"M21-GAP-01646":{"line":4901,"offset":872158,"length":172,"previous":"M21-GAP-01645","next":"M21-GAP-01647"},"M21-GAP-01647":{"line":4902,"offset":872330,"length":172,"previous":"M21-GAP-01646","next":"M21-GAP-01648"},"M21-GAP-01648":{"line":4903,"offset":872502,"length":172,"previous":"M21-GAP-01647","next":"M21-GAP-01649"},"M21-GAP-01649":{"line":4904,"offset":872674,"length":172,"previous":"M21-GAP-01648","next":"M21-GAP-01650"},"M21-GAP-01650":{"line":4905,"offset":872846,"length":172,"previous":"M21-GAP-01649","next":"M21-GAP-01651"},"M21-GAP-01651":{"line":4906,"offset":873018,"length":172,"previous":"M21-GAP-01650","next":"M21-GAP-01652"},"M21-GAP-01652":{"line":4907,"offset":873190,"length":171,"previous":"M21-GAP-01651","next":"M21-GAP-01653"},"M21-GAP-01653":{"line":4908,"offset":873361,"length":172,"previous":"M21-GAP-01652","next":"M21-GAP-01654"},"M21-GAP-01654":{"line":4909,"offset":873533,"length":172,"previous":"M21-GAP-01653","next":"M21-GAP-01655"},"M21-GAP-01655":{"line":4910,"offset":873705,"length":172,"previous":"M21-GAP-01654","next":"M21-GAP-01656"},"M21-GAP-01656":{"line":4911,"offset":873877,"length":172,"previous":"M21-GAP-01655","next":"M21-GAP-01657"},"M21-GAP-01657":{"line":4912,"offset":874049,"length":172,"previous":"M21-GAP-01656","next":"M21-GAP-01658"},"M21-GAP-01658":{"line":4913,"offset":874221,"length":172,"previous":"M21-GAP-01657","next":"M21-GAP-01659"},"M21-GAP-01659":{"line":4914,"offset":874393,"length":172,"previous":"M21-GAP-01658","next":"M21-GAP-01660"},"M21-GAP-01660":{"line":4915,"offset":874565,"length":172,"previous":"M21-GAP-01659","next":"M21-GAP-01661"},"M21-GAP-01661":{"line":4916,"offset":874737,"length":172,"previous":"M21-GAP-01660","next":"M21-GAP-01662"},"M21-GAP-01662":{"line":4917,"offset":874909,"length":172,"previous":"M21-GAP-01661","next":"M21-GAP-01663"},"M21-GAP-01663":{"line":4918,"offset":875081,"length":171,"previous":"M21-GAP-01662","next":"M21-GAP-01664"},"M21-GAP-01664":{"line":4919,"offset":875252,"length":172,"previous":"M21-GAP-01663","next":"M21-GAP-01665"},"M21-GAP-01665":{"line":4920,"offset":875424,"length":172,"previous":"M21-GAP-01664","next":"M21-GAP-01666"},"M21-GAP-01666":{"line":4921,"offset":875596,"length":172,"previous":"M21-GAP-01665","next":"M21-GAP-01667"},"M21-GAP-01667":{"line":4922,"offset":875768,"length":172,"previous":"M21-GAP-01666","next":"M21-GAP-01668"},"M21-GAP-01668":{"line":4923,"offset":875940,"length":172,"previous":"M21-GAP-01667","next":"M21-GAP-01669"},"M21-GAP-01669":{"line":4924,"offset":876112,"length":172,"previous":"M21-GAP-01668","next":"M21-GAP-01670"},"M21-GAP-01670":{"line":4925,"offset":876284,"length":172,"previous":"M21-GAP-01669","next":"M21-GAP-01671"},"M21-GAP-01671":{"line":4926,"offset":876456,"length":172,"previous":"M21-GAP-01670","next":"M21-GAP-01672"},"M21-GAP-01672":{"line":4927,"offset":876628,"length":172,"previous":"M21-GAP-01671","next":"M21-GAP-01673"},"M21-GAP-01673":{"line":4928,"offset":876800,"length":172,"previous":"M21-GAP-01672","next":"M21-GAP-01674"},"M21-GAP-01674":{"line":4929,"offset":876972,"length":171,"previous":"M21-GAP-01673","next":"M21-GAP-01675"},"M21-GAP-01675":{"line":4930,"offset":877143,"length":172,"previous":"M21-GAP-01674","next":"M21-GAP-01676"},"M21-GAP-01676":{"line":4931,"offset":877315,"length":172,"previous":"M21-GAP-01675","next":"M21-GAP-01677"},"M21-GAP-01677":{"line":4932,"offset":877487,"length":172,"previous":"M21-GAP-01676","next":"M21-GAP-01678"},"M21-GAP-01678":{"line":4933,"offset":877659,"length":172,"previous":"M21-GAP-01677","next":"M21-GAP-01679"},"M21-GAP-01679":{"line":4934,"offset":877831,"length":172,"previous":"M21-GAP-01678","next":"M21-GAP-01680"},"M21-GAP-01680":{"line":4935,"offset":878003,"length":172,"previous":"M21-GAP-01679","next":"M21-GAP-01681"},"M21-GAP-01681":{"line":4936,"offset":878175,"length":172,"previous":"M21-GAP-01680","next":"M21-GAP-01682"},"M21-GAP-01682":{"line":4937,"offset":878347,"length":172,"previous":"M21-GAP-01681","next":"M21-GAP-01683"},"M21-GAP-01683":{"line":4938,"offset":878519,"length":172,"previous":"M21-GAP-01682","next":"M21-GAP-01684"},"M21-GAP-01684":{"line":4939,"offset":878691,"length":172,"previous":"M21-GAP-01683","next":"M21-GAP-01685"},"M21-GAP-01685":{"line":4940,"offset":878863,"length":171,"previous":"M21-GAP-01684","next":"M21-GAP-01686"},"M21-GAP-01686":{"line":4941,"offset":879034,"length":172,"previous":"M21-GAP-01685","next":"M21-GAP-01687"},"M21-GAP-01687":{"line":4942,"offset":879206,"length":172,"previous":"M21-GAP-01686","next":"M21-GAP-01688"},"M21-GAP-01688":{"line":4943,"offset":879378,"length":172,"previous":"M21-GAP-01687","next":"M21-GAP-01689"},"M21-GAP-01689":{"line":4944,"offset":879550,"length":172,"previous":"M21-GAP-01688","next":"M21-GAP-01690"},"M21-GAP-01690":{"line":4945,"offset":879722,"length":172,"previous":"M21-GAP-01689","next":"M21-GAP-01691"},"M21-GAP-01691":{"line":4946,"offset":879894,"length":172,"previous":"M21-GAP-01690","next":"M21-GAP-01692"},"M21-GAP-01692":{"line":4947,"offset":880066,"length":172,"previous":"M21-GAP-01691","next":"M21-GAP-01693"},"M21-GAP-01693":{"line":4948,"offset":880238,"length":172,"previous":"M21-GAP-01692","next":"M21-GAP-01694"},"M21-GAP-01694":{"line":4949,"offset":880410,"length":172,"previous":"M21-GAP-01693","next":"M21-GAP-01695"},"M21-GAP-01695":{"line":4950,"offset":880582,"length":172,"previous":"M21-GAP-01694","next":"M21-GAP-01696"},"M21-GAP-01696":{"line":4951,"offset":880754,"length":171,"previous":"M21-GAP-01695","next":"M21-GAP-01697"},"M21-GAP-01697":{"line":4952,"offset":880925,"length":172,"previous":"M21-GAP-01696","next":"M21-GAP-01698"},"M21-GAP-01698":{"line":4953,"offset":881097,"length":172,"previous":"M21-GAP-01697","next":"M21-GAP-01699"},"M21-GAP-01699":{"line":4954,"offset":881269,"length":172,"previous":"M21-GAP-01698","next":"M21-GAP-01700"},"M21-GAP-01700":{"line":4955,"offset":881441,"length":172,"previous":"M21-GAP-01699","next":"M21-GAP-01701"},"M21-GAP-01701":{"line":4956,"offset":881613,"length":172,"previous":"M21-GAP-01700","next":"M21-GAP-01702"},"M21-GAP-01702":{"line":4957,"offset":881785,"length":172,"previous":"M21-GAP-01701","next":"M21-GAP-01703"},"M21-GAP-01703":{"line":4958,"offset":881957,"length":172,"previous":"M21-GAP-01702","next":"M21-GAP-01704"},"M21-GAP-01704":{"line":4959,"offset":882129,"length":172,"previous":"M21-GAP-01703","next":"M21-GAP-01705"},"M21-GAP-01705":{"line":4960,"offset":882301,"length":172,"previous":"M21-GAP-01704","next":"M21-GAP-01706"},"M21-GAP-01706":{"line":4961,"offset":882473,"length":172,"previous":"M21-GAP-01705","next":"M21-GAP-01707"},"M21-GAP-01707":{"line":4962,"offset":882645,"length":171,"previous":"M21-GAP-01706","next":"M21-GAP-01708"},"M21-GAP-01708":{"line":4963,"offset":882816,"length":172,"previous":"M21-GAP-01707","next":"M21-GAP-01709"},"M21-GAP-01709":{"line":4964,"offset":882988,"length":172,"previous":"M21-GAP-01708","next":"M21-GAP-01710"},"M21-GAP-01710":{"line":4965,"offset":883160,"length":172,"previous":"M21-GAP-01709","next":"M21-GAP-01711"},"M21-GAP-01711":{"line":4966,"offset":883332,"length":175,"previous":"M21-GAP-01710","next":"M21-GAP-01712"},"M21-GAP-01712":{"line":4967,"offset":883507,"length":175,"previous":"M21-GAP-01711","next":"M21-GAP-01713"},"M21-GAP-01713":{"line":4968,"offset":883682,"length":176,"previous":"M21-GAP-01712","next":"M21-GAP-01714"},"M21-GAP-01714":{"line":4969,"offset":883858,"length":176,"previous":"M21-GAP-01713","next":"M21-GAP-01715"},"M21-GAP-01715":{"line":4970,"offset":884034,"length":176,"previous":"M21-GAP-01714","next":"M21-GAP-01716"},"M21-GAP-01716":{"line":4971,"offset":884210,"length":176,"previous":"M21-GAP-01715","next":"M21-GAP-01717"},"M21-GAP-01717":{"line":4972,"offset":884386,"length":176,"previous":"M21-GAP-01716","next":"M21-GAP-01718"},"M21-GAP-01718":{"line":4973,"offset":884562,"length":176,"previous":"M21-GAP-01717","next":"M21-GAP-01719"},"M21-GAP-01719":{"line":4974,"offset":884738,"length":176,"previous":"M21-GAP-01718","next":"M21-GAP-01720"},"M21-GAP-01720":{"line":4975,"offset":884914,"length":176,"previous":"M21-GAP-01719","next":"M21-GAP-01721"},"M21-GAP-01721":{"line":4976,"offset":885090,"length":176,"previous":"M21-GAP-01720","next":"M21-GAP-01722"},"M21-GAP-01722":{"line":4977,"offset":885266,"length":176,"previous":"M21-GAP-01721","next":"M21-GAP-01723"},"M21-GAP-01723":{"line":4978,"offset":885442,"length":175,"previous":"M21-GAP-01722","next":"M21-GAP-01724"},"M21-GAP-01724":{"line":4979,"offset":885617,"length":176,"previous":"M21-GAP-01723","next":"M21-GAP-01725"},"M21-GAP-01725":{"line":4980,"offset":885793,"length":176,"previous":"M21-GAP-01724","next":"M21-GAP-01726"},"M21-GAP-01726":{"line":4981,"offset":885969,"length":175,"previous":"M21-GAP-01725","next":"M21-GAP-01727"},"M21-GAP-01727":{"line":4982,"offset":886144,"length":175,"previous":"M21-GAP-01726","next":"M21-GAP-01728"},"M21-GAP-01728":{"line":4983,"offset":886319,"length":175,"previous":"M21-GAP-01727","next":"M21-GAP-01729"},"M21-GAP-01729":{"line":4984,"offset":886494,"length":175,"previous":"M21-GAP-01728","next":"M21-GAP-01730"},"M21-GAP-01730":{"line":4985,"offset":886669,"length":175,"previous":"M21-GAP-01729","next":"M21-GAP-01731"},"M21-GAP-01731":{"line":4986,"offset":886844,"length":175,"previous":"M21-GAP-01730","next":"M21-GAP-01732"},"M21-GAP-01732":{"line":4987,"offset":887019,"length":175,"previous":"M21-GAP-01731","next":"M21-GAP-01733"},"M21-GAP-01733":{"line":4988,"offset":887194,"length":182,"previous":"M21-GAP-01732","next":"M21-GAP-01734"},"M21-GAP-01734":{"line":4989,"offset":887376,"length":182,"previous":"M21-GAP-01733","next":"M21-GAP-01735"},"M21-GAP-01735":{"line":4990,"offset":887558,"length":183,"previous":"M21-GAP-01734","next":"M21-GAP-01736"},"M21-GAP-01736":{"line":4991,"offset":887741,"length":183,"previous":"M21-GAP-01735","next":"M21-GAP-01737"},"M21-GAP-01737":{"line":4992,"offset":887924,"length":183,"previous":"M21-GAP-01736","next":"M21-GAP-01738"},"M21-GAP-01738":{"line":4993,"offset":888107,"length":183,"previous":"M21-GAP-01737","next":"M21-GAP-01739"},"M21-GAP-01739":{"line":4994,"offset":888290,"length":183,"previous":"M21-GAP-01738","next":"M21-GAP-01740"},"M21-GAP-01740":{"line":4995,"offset":888473,"length":183,"previous":"M21-GAP-01739","next":"M21-GAP-01741"},"M21-GAP-01741":{"line":4996,"offset":888656,"length":183,"previous":"M21-GAP-01740","next":"M21-GAP-01742"},"M21-GAP-01742":{"line":4997,"offset":888839,"length":183,"previous":"M21-GAP-01741","next":"M21-GAP-01743"},"M21-GAP-01743":{"line":4998,"offset":889022,"length":183,"previous":"M21-GAP-01742","next":"M21-GAP-01744"},"M21-GAP-01744":{"line":4999,"offset":889205,"length":183,"previous":"M21-GAP-01743","next":"M21-GAP-01745"},"M21-GAP-01745":{"line":5000,"offset":889388,"length":182,"previous":"M21-GAP-01744","next":"M21-GAP-01746"},"M21-GAP-01746":{"line":5001,"offset":889570,"length":183,"previous":"M21-GAP-01745","next":"M21-GAP-01747"},"M21-GAP-01747":{"line":5002,"offset":889753,"length":183,"previous":"M21-GAP-01746","next":"M21-GAP-01748"},"M21-GAP-01748":{"line":5003,"offset":889936,"length":183,"previous":"M21-GAP-01747","next":"M21-GAP-01749"},"M21-GAP-01749":{"line":5004,"offset":890119,"length":183,"previous":"M21-GAP-01748","next":"M21-GAP-01750"},"M21-GAP-01750":{"line":5005,"offset":890302,"length":183,"previous":"M21-GAP-01749","next":"M21-GAP-01751"},"M21-GAP-01751":{"line":5006,"offset":890485,"length":183,"previous":"M21-GAP-01750","next":"M21-GAP-01752"},"M21-GAP-01752":{"line":5007,"offset":890668,"length":183,"previous":"M21-GAP-01751","next":"M21-GAP-01753"},"M21-GAP-01753":{"line":5008,"offset":890851,"length":183,"previous":"M21-GAP-01752","next":"M21-GAP-01754"},"M21-GAP-01754":{"line":5009,"offset":891034,"length":183,"previous":"M21-GAP-01753","next":"M21-GAP-01755"},"M21-GAP-01755":{"line":5010,"offset":891217,"length":183,"previous":"M21-GAP-01754","next":"M21-GAP-01756"},"M21-GAP-01756":{"line":5011,"offset":891400,"length":182,"previous":"M21-GAP-01755","next":"M21-GAP-01757"},"M21-GAP-01757":{"line":5012,"offset":891582,"length":183,"previous":"M21-GAP-01756","next":"M21-GAP-01758"},"M21-GAP-01758":{"line":5013,"offset":891765,"length":183,"previous":"M21-GAP-01757","next":"M21-GAP-01759"},"M21-GAP-01759":{"line":5014,"offset":891948,"length":183,"previous":"M21-GAP-01758","next":"M21-GAP-01760"},"M21-GAP-01760":{"line":5015,"offset":892131,"length":183,"previous":"M21-GAP-01759","next":"M21-GAP-01761"},"M21-GAP-01761":{"line":5016,"offset":892314,"length":183,"previous":"M21-GAP-01760","next":"M21-GAP-01762"},"M21-GAP-01762":{"line":5017,"offset":892497,"length":183,"previous":"M21-GAP-01761","next":"M21-GAP-01763"},"M21-GAP-01763":{"line":5018,"offset":892680,"length":183,"previous":"M21-GAP-01762","next":"M21-GAP-01764"},"M21-GAP-01764":{"line":5019,"offset":892863,"length":183,"previous":"M21-GAP-01763","next":"M21-GAP-01765"},"M21-GAP-01765":{"line":5020,"offset":893046,"length":183,"previous":"M21-GAP-01764","next":"M21-GAP-01766"},"M21-GAP-01766":{"line":5021,"offset":893229,"length":183,"previous":"M21-GAP-01765","next":"M21-GAP-01767"},"M21-GAP-01767":{"line":5022,"offset":893412,"length":182,"previous":"M21-GAP-01766","next":"M21-GAP-01768"},"M21-GAP-01768":{"line":5023,"offset":893594,"length":183,"previous":"M21-GAP-01767","next":"M21-GAP-01769"},"M21-GAP-01769":{"line":5024,"offset":893777,"length":183,"previous":"M21-GAP-01768","next":"M21-GAP-01770"},"M21-GAP-01770":{"line":5025,"offset":893960,"length":183,"previous":"M21-GAP-01769","next":"M21-GAP-01771"},"M21-GAP-01771":{"line":5026,"offset":894143,"length":183,"previous":"M21-GAP-01770","next":"M21-GAP-01772"},"M21-GAP-01772":{"line":5027,"offset":894326,"length":183,"previous":"M21-GAP-01771","next":"M21-GAP-01773"},"M21-GAP-01773":{"line":5028,"offset":894509,"length":183,"previous":"M21-GAP-01772","next":"M21-GAP-01774"},"M21-GAP-01774":{"line":5029,"offset":894692,"length":183,"previous":"M21-GAP-01773","next":"M21-GAP-01775"},"M21-GAP-01775":{"line":5030,"offset":894875,"length":183,"previous":"M21-GAP-01774","next":"M21-GAP-01776"},"M21-GAP-01776":{"line":5031,"offset":895058,"length":183,"previous":"M21-GAP-01775","next":"M21-GAP-01777"},"M21-GAP-01777":{"line":5032,"offset":895241,"length":182,"previous":"M21-GAP-01776","next":"M21-GAP-01778"},"M21-GAP-01778":{"line":5033,"offset":895423,"length":182,"previous":"M21-GAP-01777","next":"M21-GAP-01779"},"M21-GAP-01779":{"line":5034,"offset":895605,"length":182,"previous":"M21-GAP-01778","next":"M21-GAP-01780"},"M21-GAP-01780":{"line":5035,"offset":895787,"length":182,"previous":"M21-GAP-01779","next":"M21-GAP-01781"},"M21-GAP-01781":{"line":5036,"offset":895969,"length":182,"previous":"M21-GAP-01780","next":"M21-GAP-01782"},"M21-GAP-01782":{"line":5037,"offset":896151,"length":183,"previous":"M21-GAP-01781","next":"M21-GAP-01783"},"M21-GAP-01783":{"line":5038,"offset":896334,"length":183,"previous":"M21-GAP-01782","next":"M21-GAP-01784"},"M21-GAP-01784":{"line":5039,"offset":896517,"length":183,"previous":"M21-GAP-01783","next":"M21-GAP-01785"},"M21-GAP-01785":{"line":5040,"offset":896700,"length":183,"previous":"M21-GAP-01784","next":"M21-GAP-01786"},"M21-GAP-01786":{"line":5041,"offset":896883,"length":183,"previous":"M21-GAP-01785","next":"M21-GAP-01787"},"M21-GAP-01787":{"line":5042,"offset":897066,"length":183,"previous":"M21-GAP-01786","next":"M21-GAP-01788"},"M21-GAP-01788":{"line":5043,"offset":897249,"length":182,"previous":"M21-GAP-01787","next":"M21-GAP-01789"},"M21-GAP-01789":{"line":5044,"offset":897431,"length":182,"previous":"M21-GAP-01788","next":"M21-GAP-01790"},"M21-GAP-01790":{"line":5045,"offset":897613,"length":182,"previous":"M21-GAP-01789","next":"M21-GAP-01791"},"M21-GAP-01791":{"line":5046,"offset":897795,"length":182,"previous":"M21-GAP-01790","next":"M21-GAP-01792"},"M21-GAP-01792":{"line":5047,"offset":897977,"length":182,"previous":"M21-GAP-01791","next":"M21-GAP-01793"},"M21-GAP-01793":{"line":5048,"offset":898159,"length":182,"previous":"M21-GAP-01792","next":"M21-GAP-01794"},"M21-GAP-01794":{"line":5049,"offset":898341,"length":182,"previous":"M21-GAP-01793","next":"M21-GAP-01795"},"M21-GAP-01795":{"line":5050,"offset":898523,"length":182,"previous":"M21-GAP-01794","next":"M21-GAP-01796"},"M21-GAP-01796":{"line":5051,"offset":898705,"length":184,"previous":"M21-GAP-01795","next":"M21-GAP-01797"},"M21-GAP-01797":{"line":5052,"offset":898889,"length":184,"previous":"M21-GAP-01796","next":"M21-GAP-01798"},"M21-GAP-01798":{"line":5053,"offset":899073,"length":185,"previous":"M21-GAP-01797","next":"M21-GAP-01799"},"M21-GAP-01799":{"line":5054,"offset":899258,"length":186,"previous":"M21-GAP-01798","next":"M21-GAP-01800"},"M21-GAP-01800":{"line":5055,"offset":899444,"length":186,"previous":"M21-GAP-01799","next":"M21-GAP-01801"},"M21-GAP-01801":{"line":5056,"offset":899630,"length":186,"previous":"M21-GAP-01800","next":"M21-GAP-01802"},"M21-GAP-01802":{"line":5057,"offset":899816,"length":186,"previous":"M21-GAP-01801","next":"M21-GAP-01803"},"M21-GAP-01803":{"line":5058,"offset":900002,"length":185,"previous":"M21-GAP-01802","next":"M21-GAP-01804"},"M21-GAP-01804":{"line":5059,"offset":900187,"length":185,"previous":"M21-GAP-01803","next":"M21-GAP-01805"},"M21-GAP-01805":{"line":5060,"offset":900372,"length":185,"previous":"M21-GAP-01804","next":"M21-GAP-01806"},"M21-GAP-01806":{"line":5061,"offset":900557,"length":185,"previous":"M21-GAP-01805","next":"M21-GAP-01807"},"M21-GAP-01807":{"line":5062,"offset":900742,"length":185,"previous":"M21-GAP-01806","next":"M21-GAP-01808"},"M21-GAP-01808":{"line":5063,"offset":900927,"length":185,"previous":"M21-GAP-01807","next":"M21-GAP-01809"},"M21-GAP-01809":{"line":5064,"offset":901112,"length":185,"previous":"M21-GAP-01808","next":"M21-GAP-01810"},"M21-GAP-01810":{"line":5065,"offset":901297,"length":185,"previous":"M21-GAP-01809","next":"M21-GAP-01811"},"M21-GAP-01811":{"line":5066,"offset":901482,"length":185,"previous":"M21-GAP-01810","next":"M21-GAP-01812"},"M21-GAP-01812":{"line":5067,"offset":901667,"length":184,"previous":"M21-GAP-01811","next":"M21-GAP-01813"},"M21-GAP-01813":{"line":5068,"offset":901851,"length":185,"previous":"M21-GAP-01812","next":"M21-GAP-01814"},"M21-GAP-01814":{"line":5069,"offset":902036,"length":185,"previous":"M21-GAP-01813","next":"M21-GAP-01815"},"M21-GAP-01815":{"line":5070,"offset":902221,"length":185,"previous":"M21-GAP-01814","next":"M21-GAP-01816"},"M21-GAP-01816":{"line":5071,"offset":902406,"length":185,"previous":"M21-GAP-01815","next":"M21-GAP-01817"},"M21-GAP-01817":{"line":5072,"offset":902591,"length":185,"previous":"M21-GAP-01816","next":"M21-GAP-01818"},"M21-GAP-01818":{"line":5073,"offset":902776,"length":185,"previous":"M21-GAP-01817","next":"M21-GAP-01819"},"M21-GAP-01819":{"line":5074,"offset":902961,"length":185,"previous":"M21-GAP-01818","next":"M21-GAP-01820"},"M21-GAP-01820":{"line":5075,"offset":903146,"length":185,"previous":"M21-GAP-01819","next":"M21-GAP-01821"},"M21-GAP-01821":{"line":5076,"offset":903331,"length":185,"previous":"M21-GAP-01820","next":"M21-GAP-01822"},"M21-GAP-01822":{"line":5077,"offset":903516,"length":185,"previous":"M21-GAP-01821","next":"M21-GAP-01823"},"M21-GAP-01823":{"line":5078,"offset":903701,"length":184,"previous":"M21-GAP-01822","next":"M21-GAP-01824"},"M21-GAP-01824":{"line":5079,"offset":903885,"length":185,"previous":"M21-GAP-01823","next":"M21-GAP-01825"},"M21-GAP-01825":{"line":5080,"offset":904070,"length":185,"previous":"M21-GAP-01824","next":"M21-GAP-01826"},"M21-GAP-01826":{"line":5081,"offset":904255,"length":185,"previous":"M21-GAP-01825","next":"M21-GAP-01827"},"M21-GAP-01827":{"line":5082,"offset":904440,"length":185,"previous":"M21-GAP-01826","next":"M21-GAP-01828"},"M21-GAP-01828":{"line":5083,"offset":904625,"length":185,"previous":"M21-GAP-01827","next":"M21-GAP-01829"},"M21-GAP-01829":{"line":5084,"offset":904810,"length":185,"previous":"M21-GAP-01828","next":"M21-GAP-01830"},"M21-GAP-01830":{"line":5085,"offset":904995,"length":185,"previous":"M21-GAP-01829","next":"M21-GAP-01831"},"M21-GAP-01831":{"line":5086,"offset":905180,"length":185,"previous":"M21-GAP-01830","next":"M21-GAP-01832"},"M21-GAP-01832":{"line":5087,"offset":905365,"length":185,"previous":"M21-GAP-01831","next":"M21-GAP-01833"},"M21-GAP-01833":{"line":5088,"offset":905550,"length":185,"previous":"M21-GAP-01832","next":"M21-GAP-01834"},"M21-GAP-01834":{"line":5089,"offset":905735,"length":184,"previous":"M21-GAP-01833","next":"M21-GAP-01835"},"M21-GAP-01835":{"line":5090,"offset":905919,"length":185,"previous":"M21-GAP-01834","next":"M21-GAP-01836"},"M21-GAP-01836":{"line":5091,"offset":906104,"length":185,"previous":"M21-GAP-01835","next":"M21-GAP-01837"},"M21-GAP-01837":{"line":5092,"offset":906289,"length":185,"previous":"M21-GAP-01836","next":"M21-GAP-01838"},"M21-GAP-01838":{"line":5093,"offset":906474,"length":185,"previous":"M21-GAP-01837","next":"M21-GAP-01839"},"M21-GAP-01839":{"line":5094,"offset":906659,"length":185,"previous":"M21-GAP-01838","next":"M21-GAP-01840"},"M21-GAP-01840":{"line":5095,"offset":906844,"length":185,"previous":"M21-GAP-01839","next":"M21-GAP-01841"},"M21-GAP-01841":{"line":5096,"offset":907029,"length":185,"previous":"M21-GAP-01840","next":"M21-GAP-01842"},"M21-GAP-01842":{"line":5097,"offset":907214,"length":185,"previous":"M21-GAP-01841","next":"M21-GAP-01843"},"M21-GAP-01843":{"line":5098,"offset":907399,"length":185,"previous":"M21-GAP-01842","next":"M21-GAP-01844"},"M21-GAP-01844":{"line":5099,"offset":907584,"length":185,"previous":"M21-GAP-01843","next":"M21-GAP-01845"},"M21-GAP-01845":{"line":5100,"offset":907769,"length":184,"previous":"M21-GAP-01844","next":"M21-GAP-01846"},"M21-GAP-01846":{"line":5101,"offset":907953,"length":185,"previous":"M21-GAP-01845","next":"M21-GAP-01847"},"M21-GAP-01847":{"line":5102,"offset":908138,"length":185,"previous":"M21-GAP-01846","next":"M21-GAP-01848"},"M21-GAP-01848":{"line":5103,"offset":908323,"length":185,"previous":"M21-GAP-01847","next":"M21-GAP-01849"},"M21-GAP-01849":{"line":5104,"offset":908508,"length":185,"previous":"M21-GAP-01848","next":"M21-GAP-01850"},"M21-GAP-01850":{"line":5105,"offset":908693,"length":185,"previous":"M21-GAP-01849","next":"M21-GAP-01851"},"M21-GAP-01851":{"line":5106,"offset":908878,"length":185,"previous":"M21-GAP-01850","next":"M21-GAP-01852"},"M21-GAP-01852":{"line":5107,"offset":909063,"length":185,"previous":"M21-GAP-01851","next":"M21-GAP-01853"},"M21-GAP-01853":{"line":5108,"offset":909248,"length":185,"previous":"M21-GAP-01852","next":"M21-GAP-01854"},"M21-GAP-01854":{"line":5109,"offset":909433,"length":185,"previous":"M21-GAP-01853","next":"M21-GAP-01855"},"M21-GAP-01855":{"line":5110,"offset":909618,"length":185,"previous":"M21-GAP-01854","next":"M21-GAP-01856"},"M21-GAP-01856":{"line":5111,"offset":909803,"length":184,"previous":"M21-GAP-01855","next":"M21-GAP-01857"},"M21-GAP-01857":{"line":5112,"offset":909987,"length":185,"previous":"M21-GAP-01856","next":"M21-GAP-01858"},"M21-GAP-01858":{"line":5113,"offset":910172,"length":185,"previous":"M21-GAP-01857","next":"M21-GAP-01859"},"M21-GAP-01859":{"line":5114,"offset":910357,"length":185,"previous":"M21-GAP-01858","next":"M21-GAP-01860"},"M21-GAP-01860":{"line":5115,"offset":910542,"length":185,"previous":"M21-GAP-01859","next":"M21-GAP-01861"},"M21-GAP-01861":{"line":5116,"offset":910727,"length":185,"previous":"M21-GAP-01860","next":"M21-GAP-01862"},"M21-GAP-01862":{"line":5117,"offset":910912,"length":185,"previous":"M21-GAP-01861","next":"M21-GAP-01863"},"M21-GAP-01863":{"line":5118,"offset":911097,"length":185,"previous":"M21-GAP-01862","next":"M21-GAP-01864"},"M21-GAP-01864":{"line":5119,"offset":911282,"length":185,"previous":"M21-GAP-01863","next":"M21-GAP-01865"},"M21-GAP-01865":{"line":5120,"offset":911467,"length":185,"previous":"M21-GAP-01864","next":"M21-GAP-01866"},"M21-GAP-01866":{"line":5121,"offset":911652,"length":185,"previous":"M21-GAP-01865","next":"M21-GAP-01867"},"M21-GAP-01867":{"line":5122,"offset":911837,"length":184,"previous":"M21-GAP-01866","next":"M21-GAP-01868"},"M21-GAP-01868":{"line":5123,"offset":912021,"length":185,"previous":"M21-GAP-01867","next":"M21-GAP-01869"},"M21-GAP-01869":{"line":5124,"offset":912206,"length":185,"previous":"M21-GAP-01868","next":"M21-GAP-01870"},"M21-GAP-01870":{"line":5125,"offset":912391,"length":185,"previous":"M21-GAP-01869","next":"M21-GAP-01871"},"M21-GAP-01871":{"line":5126,"offset":912576,"length":185,"previous":"M21-GAP-01870","next":"M21-GAP-01872"},"M21-GAP-01872":{"line":5127,"offset":912761,"length":185,"previous":"M21-GAP-01871","next":"M21-GAP-01873"},"M21-GAP-01873":{"line":5128,"offset":912946,"length":185,"previous":"M21-GAP-01872","next":"M21-GAP-01874"},"M21-GAP-01874":{"line":5129,"offset":913131,"length":185,"previous":"M21-GAP-01873","next":"M21-GAP-01875"},"M21-GAP-01875":{"line":5130,"offset":913316,"length":185,"previous":"M21-GAP-01874","next":"M21-GAP-01876"},"M21-GAP-01876":{"line":5131,"offset":913501,"length":185,"previous":"M21-GAP-01875","next":"M21-GAP-01877"},"M21-GAP-01877":{"line":5132,"offset":913686,"length":185,"previous":"M21-GAP-01876","next":"M21-GAP-01878"},"M21-GAP-01878":{"line":5133,"offset":913871,"length":184,"previous":"M21-GAP-01877","next":"M21-GAP-01879"},"M21-GAP-01879":{"line":5134,"offset":914055,"length":185,"previous":"M21-GAP-01878","next":"M21-GAP-01880"},"M21-GAP-01880":{"line":5135,"offset":914240,"length":185,"previous":"M21-GAP-01879","next":"M21-GAP-01881"},"M21-GAP-01881":{"line":5136,"offset":914425,"length":185,"previous":"M21-GAP-01880","next":"M21-GAP-01882"},"M21-GAP-01882":{"line":5137,"offset":914610,"length":185,"previous":"M21-GAP-01881","next":"M21-GAP-01883"},"M21-GAP-01883":{"line":5138,"offset":914795,"length":185,"previous":"M21-GAP-01882","next":"M21-GAP-01884"},"M21-GAP-01884":{"line":5139,"offset":914980,"length":185,"previous":"M21-GAP-01883","next":"M21-GAP-01885"},"M21-GAP-01885":{"line":5140,"offset":915165,"length":185,"previous":"M21-GAP-01884","next":"M21-GAP-01886"},"M21-GAP-01886":{"line":5141,"offset":915350,"length":185,"previous":"M21-GAP-01885","next":"M21-GAP-01887"},"M21-GAP-01887":{"line":5142,"offset":915535,"length":185,"previous":"M21-GAP-01886","next":"M21-GAP-01888"},"M21-GAP-01888":{"line":5143,"offset":915720,"length":185,"previous":"M21-GAP-01887","next":"M21-GAP-01889"},"M21-GAP-01889":{"line":5144,"offset":915905,"length":184,"previous":"M21-GAP-01888","next":"M21-GAP-01890"},"M21-GAP-01890":{"line":5145,"offset":916089,"length":185,"previous":"M21-GAP-01889","next":"M21-GAP-01891"},"M21-GAP-01891":{"line":5146,"offset":916274,"length":185,"previous":"M21-GAP-01890","next":"M21-GAP-01892"},"M21-GAP-01892":{"line":5147,"offset":916459,"length":185,"previous":"M21-GAP-01891","next":"M21-GAP-01893"},"M21-GAP-01893":{"line":5148,"offset":916644,"length":185,"previous":"M21-GAP-01892","next":"M21-GAP-01894"},"M21-GAP-01894":{"line":5149,"offset":916829,"length":185,"previous":"M21-GAP-01893","next":"M21-GAP-01895"},"M21-GAP-01895":{"line":5150,"offset":917014,"length":185,"previous":"M21-GAP-01894","next":"M21-GAP-01896"},"M21-GAP-01896":{"line":5151,"offset":917199,"length":185,"previous":"M21-GAP-01895","next":"M21-GAP-01897"},"M21-GAP-01897":{"line":5152,"offset":917384,"length":185,"previous":"M21-GAP-01896","next":"M21-GAP-01898"},"M21-GAP-01898":{"line":5153,"offset":917569,"length":185,"previous":"M21-GAP-01897","next":"M21-GAP-01899"},"M21-GAP-01899":{"line":5154,"offset":917754,"length":185,"previous":"M21-GAP-01898","next":"M21-GAP-01900"},"M21-GAP-01900":{"line":5155,"offset":917939,"length":185,"previous":"M21-GAP-01899","next":"M21-GAP-01901"},"M21-GAP-01901":{"line":5156,"offset":918124,"length":185,"previous":"M21-GAP-01900","next":"M21-GAP-01902"},"M21-GAP-01902":{"line":5157,"offset":918309,"length":186,"previous":"M21-GAP-01901","next":"M21-GAP-01903"},"M21-GAP-01903":{"line":5158,"offset":918495,"length":186,"previous":"M21-GAP-01902","next":"M21-GAP-01904"},"M21-GAP-01904":{"line":5159,"offset":918681,"length":186,"previous":"M21-GAP-01903","next":"M21-GAP-01905"},"M21-GAP-01905":{"line":5160,"offset":918867,"length":186,"previous":"M21-GAP-01904","next":"M21-GAP-01906"},"M21-GAP-01906":{"line":5161,"offset":919053,"length":186,"previous":"M21-GAP-01905","next":"M21-GAP-01907"},"M21-GAP-01907":{"line":5162,"offset":919239,"length":186,"previous":"M21-GAP-01906","next":"M21-GAP-01908"},"M21-GAP-01908":{"line":5163,"offset":919425,"length":188,"previous":"M21-GAP-01907","next":"M21-GAP-01909"},"M21-GAP-01909":{"line":5164,"offset":919613,"length":188,"previous":"M21-GAP-01908","next":"M21-GAP-01910"},"M21-GAP-01910":{"line":5165,"offset":919801,"length":188,"previous":"M21-GAP-01909","next":"M21-GAP-01911"},"M21-GAP-01911":{"line":5166,"offset":919989,"length":188,"previous":"M21-GAP-01910","next":"M21-GAP-01912"},"M21-GAP-01912":{"line":5167,"offset":920177,"length":188,"previous":"M21-GAP-01911","next":"M21-GAP-01913"},"M21-GAP-01913":{"line":5168,"offset":920365,"length":188,"previous":"M21-GAP-01912","next":"M21-GAP-01914"},"M21-GAP-01914":{"line":5169,"offset":920553,"length":188,"previous":"M21-GAP-01913","next":"M21-GAP-01915"},"M21-GAP-01915":{"line":5170,"offset":920741,"length":195,"previous":"M21-GAP-01914","next":"M21-GAP-01916"},"M21-GAP-01916":{"line":5171,"offset":920936,"length":193,"previous":"M21-GAP-01915","next":"M21-GAP-01917"},"M21-GAP-01917":{"line":5172,"offset":921129,"length":194,"previous":"M21-GAP-01916","next":"M21-GAP-01918"},"M21-GAP-01918":{"line":5173,"offset":921323,"length":205,"previous":"M21-GAP-01917","next":"M21-GAP-01919"},"M21-GAP-01919":{"line":5174,"offset":921528,"length":205,"previous":"M21-GAP-01918","next":"M21-GAP-01920"},"M21-GAP-01920":{"line":5175,"offset":921733,"length":206,"previous":"M21-GAP-01919","next":"M21-GAP-01921"},"M21-GAP-01921":{"line":5176,"offset":921939,"length":206,"previous":"M21-GAP-01920","next":"M21-GAP-01922"},"M21-GAP-01922":{"line":5177,"offset":922145,"length":205,"previous":"M21-GAP-01921","next":"M21-GAP-01923"},"M21-GAP-01923":{"line":5178,"offset":922350,"length":205,"previous":"M21-GAP-01922","next":"M21-GAP-01924"},"M21-GAP-01924":{"line":5179,"offset":922555,"length":205,"previous":"M21-GAP-01923","next":"M21-GAP-01925"},"M21-GAP-01925":{"line":5180,"offset":922760,"length":205,"previous":"M21-GAP-01924","next":"M21-GAP-01926"},"M21-GAP-01926":{"line":5181,"offset":922965,"length":205,"previous":"M21-GAP-01925","next":"M21-GAP-01927"},"M21-GAP-01927":{"line":5182,"offset":923170,"length":205,"previous":"M21-GAP-01926","next":"M21-GAP-01928"},"M21-GAP-01928":{"line":5183,"offset":923375,"length":205,"previous":"M21-GAP-01927","next":"M21-GAP-01929"},"M21-GAP-01929":{"line":5184,"offset":923580,"length":205,"previous":"M21-GAP-01928","next":"M21-GAP-01930"},"M21-GAP-01930":{"line":5185,"offset":923785,"length":194,"previous":"M21-GAP-01929","next":"M21-GAP-01931"},"M21-GAP-01931":{"line":5186,"offset":923979,"length":194,"previous":"M21-GAP-01930","next":"M21-GAP-01932"},"M21-GAP-01932":{"line":5187,"offset":924173,"length":195,"previous":"M21-GAP-01931","next":"M21-GAP-01933"},"M21-GAP-01933":{"line":5188,"offset":924368,"length":195,"previous":"M21-GAP-01932","next":"M21-GAP-01934"},"M21-GAP-01934":{"line":5189,"offset":924563,"length":194,"previous":"M21-GAP-01933","next":"M21-GAP-01935"},"M21-GAP-01935":{"line":5190,"offset":924757,"length":194,"previous":"M21-GAP-01934","next":"M21-GAP-01936"},"M21-GAP-01936":{"line":5191,"offset":924951,"length":194,"previous":"M21-GAP-01935","next":"M21-GAP-01937"},"M21-GAP-01937":{"line":5192,"offset":925145,"length":194,"previous":"M21-GAP-01936","next":"M21-GAP-01938"},"M21-GAP-01938":{"line":5193,"offset":925339,"length":194,"previous":"M21-GAP-01937","next":"M21-GAP-01939"},"M21-GAP-01939":{"line":5194,"offset":925533,"length":194,"previous":"M21-GAP-01938","next":"M21-GAP-01940"},"M21-GAP-01940":{"line":5195,"offset":925727,"length":194,"previous":"M21-GAP-01939","next":"M21-GAP-01941"},"M21-GAP-01941":{"line":5196,"offset":925921,"length":194,"previous":"M21-GAP-01940","next":"M21-GAP-01942"},"M21-GAP-01942":{"line":5197,"offset":926115,"length":208,"previous":"M21-GAP-01941","next":"M21-GAP-01943"},"M21-GAP-01943":{"line":5198,"offset":926323,"length":208,"previous":"M21-GAP-01942","next":"M21-GAP-01944"},"M21-GAP-01944":{"line":5199,"offset":926531,"length":208,"previous":"M21-GAP-01943","next":"M21-GAP-01945"},"M21-GAP-01945":{"line":5200,"offset":926739,"length":197,"previous":"M21-GAP-01944","next":"M21-GAP-01946"},"M21-GAP-01946":{"line":5201,"offset":926936,"length":197,"previous":"M21-GAP-01945","next":"M21-GAP-01947"},"M21-GAP-01947":{"line":5202,"offset":927133,"length":197,"previous":"M21-GAP-01946","next":"M21-GAP-01948"},"M21-GAP-01948":{"line":5203,"offset":927330,"length":207,"previous":"M21-GAP-01947","next":"M21-GAP-01949"},"M21-GAP-01949":{"line":5204,"offset":927537,"length":207,"previous":"M21-GAP-01948","next":"M21-GAP-01950"},"M21-GAP-01950":{"line":5205,"offset":927744,"length":207,"previous":"M21-GAP-01949","next":"M21-GAP-01951"},"M21-GAP-01951":{"line":5206,"offset":927951,"length":196,"previous":"M21-GAP-01950","next":"M21-GAP-01952"},"M21-GAP-01952":{"line":5207,"offset":928147,"length":196,"previous":"M21-GAP-01951","next":"M21-GAP-01953"},"M21-GAP-01953":{"line":5208,"offset":928343,"length":196,"previous":"M21-GAP-01952","next":"M21-GAP-01954"},"M21-GAP-01954":{"line":5209,"offset":928539,"length":200,"previous":"M21-GAP-01953","next":"M21-GAP-01955"},"M21-GAP-01955":{"line":5210,"offset":928739,"length":200,"previous":"M21-GAP-01954","next":"M21-GAP-01956"},"M21-GAP-01956":{"line":5211,"offset":928939,"length":200,"previous":"M21-GAP-01955","next":"M21-GAP-01957"},"M21-GAP-01957":{"line":5212,"offset":929139,"length":200,"previous":"M21-GAP-01956","next":"M21-GAP-01958"},"M21-GAP-01958":{"line":5213,"offset":929339,"length":200,"previous":"M21-GAP-01957","next":"M21-GAP-01959"},"M21-GAP-01959":{"line":5214,"offset":929539,"length":200,"previous":"M21-GAP-01958","next":"M21-GAP-01960"},"M21-GAP-01960":{"line":5215,"offset":929739,"length":200,"previous":"M21-GAP-01959","next":"M21-GAP-01961"},"M21-GAP-01961":{"line":5216,"offset":929939,"length":200,"previous":"M21-GAP-01960","next":"M21-GAP-01962"},"M21-GAP-01962":{"line":5217,"offset":930139,"length":200,"previous":"M21-GAP-01961","next":"M21-GAP-01963"},"M21-GAP-01963":{"line":5218,"offset":930339,"length":189,"previous":"M21-GAP-01962","next":"M21-GAP-01964"},"M21-GAP-01964":{"line":5219,"offset":930528,"length":189,"previous":"M21-GAP-01963","next":"M21-GAP-01965"},"M21-GAP-01965":{"line":5220,"offset":930717,"length":189,"previous":"M21-GAP-01964","next":"M21-GAP-01966"},"M21-GAP-01966":{"line":5221,"offset":930906,"length":189,"previous":"M21-GAP-01965","next":"M21-GAP-01967"},"M21-GAP-01967":{"line":5222,"offset":931095,"length":189,"previous":"M21-GAP-01966","next":"M21-GAP-01968"},"M21-GAP-01968":{"line":5223,"offset":931284,"length":189,"previous":"M21-GAP-01967","next":"M21-GAP-01969"},"M21-GAP-01969":{"line":5224,"offset":931473,"length":189,"previous":"M21-GAP-01968","next":"M21-GAP-01970"},"M21-GAP-01970":{"line":5225,"offset":931662,"length":189,"previous":"M21-GAP-01969","next":"M21-GAP-01971"},"M21-GAP-01971":{"line":5226,"offset":931851,"length":189,"previous":"M21-GAP-01970","next":"M21-GAP-01972"},"M21-GAP-01972":{"line":5227,"offset":932040,"length":178,"previous":"M21-GAP-01971","next":"M21-GAP-01973"},"M21-GAP-01973":{"line":5228,"offset":932218,"length":178,"previous":"M21-GAP-01972","next":"M21-GAP-01974"},"M21-GAP-01974":{"line":5229,"offset":932396,"length":179,"previous":"M21-GAP-01973","next":"M21-GAP-01975"},"M21-GAP-01975":{"line":5230,"offset":932575,"length":179,"previous":"M21-GAP-01974","next":"M21-GAP-01976"},"M21-GAP-01976":{"line":5231,"offset":932754,"length":179,"previous":"M21-GAP-01975","next":"M21-GAP-01977"},"M21-GAP-01977":{"line":5232,"offset":932933,"length":179,"previous":"M21-GAP-01976","next":"M21-GAP-01978"},"M21-GAP-01978":{"line":5233,"offset":933112,"length":179,"previous":"M21-GAP-01977","next":"M21-GAP-01979"},"M21-GAP-01979":{"line":5234,"offset":933291,"length":179,"previous":"M21-GAP-01978","next":"M21-GAP-01980"},"M21-GAP-01980":{"line":5235,"offset":933470,"length":179,"previous":"M21-GAP-01979","next":"M21-GAP-01981"},"M21-GAP-01981":{"line":5236,"offset":933649,"length":179,"previous":"M21-GAP-01980","next":"M21-GAP-01982"},"M21-GAP-01982":{"line":5237,"offset":933828,"length":179,"previous":"M21-GAP-01981","next":"M21-GAP-01983"},"M21-GAP-01983":{"line":5238,"offset":934007,"length":179,"previous":"M21-GAP-01982","next":"M21-GAP-01984"},"M21-GAP-01984":{"line":5239,"offset":934186,"length":178,"previous":"M21-GAP-01983","next":"M21-GAP-01985"},"M21-GAP-01985":{"line":5240,"offset":934364,"length":179,"previous":"M21-GAP-01984","next":"M21-GAP-01986"},"M21-GAP-01986":{"line":5241,"offset":934543,"length":179,"previous":"M21-GAP-01985","next":"M21-GAP-01987"},"M21-GAP-01987":{"line":5242,"offset":934722,"length":179,"previous":"M21-GAP-01986","next":"M21-GAP-01988"},"M21-GAP-01988":{"line":5243,"offset":934901,"length":179,"previous":"M21-GAP-01987","next":"M21-GAP-01989"},"M21-GAP-01989":{"line":5244,"offset":935080,"length":179,"previous":"M21-GAP-01988","next":"M21-GAP-01990"},"M21-GAP-01990":{"line":5245,"offset":935259,"length":179,"previous":"M21-GAP-01989","next":"M21-GAP-01991"},"M21-GAP-01991":{"line":5246,"offset":935438,"length":179,"previous":"M21-GAP-01990","next":"M21-GAP-01992"},"M21-GAP-01992":{"line":5247,"offset":935617,"length":179,"previous":"M21-GAP-01991","next":"M21-GAP-01993"},"M21-GAP-01993":{"line":5248,"offset":935796,"length":179,"previous":"M21-GAP-01992","next":"M21-GAP-01994"},"M21-GAP-01994":{"line":5249,"offset":935975,"length":179,"previous":"M21-GAP-01993","next":"M21-GAP-01995"},"M21-GAP-01995":{"line":5250,"offset":936154,"length":178,"previous":"M21-GAP-01994","next":"M21-GAP-01996"},"M21-GAP-01996":{"line":5251,"offset":936332,"length":179,"previous":"M21-GAP-01995","next":"M21-GAP-01997"},"M21-GAP-01997":{"line":5252,"offset":936511,"length":179,"previous":"M21-GAP-01996","next":"M21-GAP-01998"},"M21-GAP-01998":{"line":5253,"offset":936690,"length":179,"previous":"M21-GAP-01997","next":"M21-GAP-01999"},"M21-GAP-01999":{"line":5254,"offset":936869,"length":179,"previous":"M21-GAP-01998","next":"M21-GAP-02000"},"M21-GAP-02000":{"line":5255,"offset":937048,"length":179,"previous":"M21-GAP-01999","next":"M21-GAP-02001"},"M21-GAP-02001":{"line":5256,"offset":937227,"length":179,"previous":"M21-GAP-02000","next":"M21-GAP-02002"},"M21-GAP-02002":{"line":5257,"offset":937406,"length":179,"previous":"M21-GAP-02001","next":"M21-GAP-02003"},"M21-GAP-02003":{"line":5258,"offset":937585,"length":179,"previous":"M21-GAP-02002","next":"M21-GAP-02004"},"M21-GAP-02004":{"line":5259,"offset":937764,"length":179,"previous":"M21-GAP-02003","next":"M21-GAP-02005"},"M21-GAP-02005":{"line":5260,"offset":937943,"length":179,"previous":"M21-GAP-02004","next":"M21-GAP-02006"},"M21-GAP-02006":{"line":5261,"offset":938122,"length":178,"previous":"M21-GAP-02005","next":"M21-GAP-02007"},"M21-GAP-02007":{"line":5262,"offset":938300,"length":179,"previous":"M21-GAP-02006","next":"M21-GAP-02008"},"M21-GAP-02008":{"line":5263,"offset":938479,"length":179,"previous":"M21-GAP-02007","next":"M21-GAP-02009"},"M21-GAP-02009":{"line":5264,"offset":938658,"length":179,"previous":"M21-GAP-02008","next":"M21-GAP-02010"},"M21-GAP-02010":{"line":5265,"offset":938837,"length":179,"previous":"M21-GAP-02009","next":"M21-GAP-02011"},"M21-GAP-02011":{"line":5266,"offset":939016,"length":179,"previous":"M21-GAP-02010","next":"M21-GAP-02012"},"M21-GAP-02012":{"line":5267,"offset":939195,"length":179,"previous":"M21-GAP-02011","next":"M21-GAP-02013"},"M21-GAP-02013":{"line":5268,"offset":939374,"length":179,"previous":"M21-GAP-02012","next":"M21-GAP-02014"},"M21-GAP-02014":{"line":5269,"offset":939553,"length":179,"previous":"M21-GAP-02013","next":"M21-GAP-02015"},"M21-GAP-02015":{"line":5270,"offset":939732,"length":179,"previous":"M21-GAP-02014","next":"M21-GAP-02016"},"M21-GAP-02016":{"line":5271,"offset":939911,"length":179,"previous":"M21-GAP-02015","next":"M21-GAP-02017"},"M21-GAP-02017":{"line":5272,"offset":940090,"length":178,"previous":"M21-GAP-02016","next":"M21-GAP-02018"},"M21-GAP-02018":{"line":5273,"offset":940268,"length":179,"previous":"M21-GAP-02017","next":"M21-GAP-02019"},"M21-GAP-02019":{"line":5274,"offset":940447,"length":179,"previous":"M21-GAP-02018","next":"M21-GAP-02020"},"M21-GAP-02020":{"line":5275,"offset":940626,"length":179,"previous":"M21-GAP-02019","next":"M21-GAP-02021"},"M21-GAP-02021":{"line":5276,"offset":940805,"length":179,"previous":"M21-GAP-02020","next":"M21-GAP-02022"},"M21-GAP-02022":{"line":5277,"offset":940984,"length":179,"previous":"M21-GAP-02021","next":"M21-GAP-02023"},"M21-GAP-02023":{"line":5278,"offset":941163,"length":179,"previous":"M21-GAP-02022","next":"M21-GAP-02024"},"M21-GAP-02024":{"line":5279,"offset":941342,"length":179,"previous":"M21-GAP-02023","next":"M21-GAP-02025"},"M21-GAP-02025":{"line":5280,"offset":941521,"length":179,"previous":"M21-GAP-02024","next":"M21-GAP-02026"},"M21-GAP-02026":{"line":5281,"offset":941700,"length":179,"previous":"M21-GAP-02025","next":"M21-GAP-02027"},"M21-GAP-02027":{"line":5282,"offset":941879,"length":178,"previous":"M21-GAP-02026","next":"M21-GAP-02028"},"M21-GAP-02028":{"line":5283,"offset":942057,"length":178,"previous":"M21-GAP-02027","next":"M21-GAP-02029"},"M21-GAP-02029":{"line":5284,"offset":942235,"length":178,"previous":"M21-GAP-02028","next":"M21-GAP-02030"},"M21-GAP-02030":{"line":5285,"offset":942413,"length":178,"previous":"M21-GAP-02029","next":"M21-GAP-02031"},"M21-GAP-02031":{"line":5286,"offset":942591,"length":183,"previous":"M21-GAP-02030","next":"M21-GAP-02032"},"M21-GAP-02032":{"line":5287,"offset":942774,"length":183,"previous":"M21-GAP-02031","next":"M21-GAP-02033"},"M21-GAP-02033":{"line":5288,"offset":942957,"length":183,"previous":"M21-GAP-02032","next":"M21-GAP-02034"},"M21-GAP-02034":{"line":5289,"offset":943140,"length":178,"previous":"M21-GAP-02033","next":"M21-GAP-02035"},"M21-GAP-02035":{"line":5290,"offset":943318,"length":178,"previous":"M21-GAP-02034","next":"M21-GAP-02036"},"M21-GAP-02036":{"line":5291,"offset":943496,"length":179,"previous":"M21-GAP-02035","next":"M21-GAP-02037"},"M21-GAP-02037":{"line":5292,"offset":943675,"length":180,"previous":"M21-GAP-02036","next":"M21-GAP-02038"},"M21-GAP-02038":{"line":5293,"offset":943855,"length":180,"previous":"M21-GAP-02037","next":"M21-GAP-02039"},"M21-GAP-02039":{"line":5294,"offset":944035,"length":180,"previous":"M21-GAP-02038","next":"M21-GAP-02040"},"M21-GAP-02040":{"line":5295,"offset":944215,"length":179,"previous":"M21-GAP-02039","next":"M21-GAP-02041"},"M21-GAP-02041":{"line":5296,"offset":944394,"length":179,"previous":"M21-GAP-02040","next":"M21-GAP-02042"},"M21-GAP-02042":{"line":5297,"offset":944573,"length":179,"previous":"M21-GAP-02041","next":"M21-GAP-02043"},"M21-GAP-02043":{"line":5298,"offset":944752,"length":179,"previous":"M21-GAP-02042","next":"M21-GAP-02044"},"M21-GAP-02044":{"line":5299,"offset":944931,"length":179,"previous":"M21-GAP-02043","next":"M21-GAP-02045"},"M21-GAP-02045":{"line":5300,"offset":945110,"length":179,"previous":"M21-GAP-02044","next":"M21-GAP-02046"},"M21-GAP-02046":{"line":5301,"offset":945289,"length":179,"previous":"M21-GAP-02045","next":"M21-GAP-02047"},"M21-GAP-02047":{"line":5302,"offset":945468,"length":179,"previous":"M21-GAP-02046","next":"M21-GAP-02048"},"M21-GAP-02048":{"line":5303,"offset":945647,"length":179,"previous":"M21-GAP-02047","next":"M21-GAP-02049"},"M21-GAP-02049":{"line":5304,"offset":945826,"length":178,"previous":"M21-GAP-02048","next":"M21-GAP-02050"},"M21-GAP-02050":{"line":5305,"offset":946004,"length":179,"previous":"M21-GAP-02049","next":"M21-GAP-02051"},"M21-GAP-02051":{"line":5306,"offset":946183,"length":179,"previous":"M21-GAP-02050","next":"M21-GAP-02052"},"M21-GAP-02052":{"line":5307,"offset":946362,"length":179,"previous":"M21-GAP-02051","next":"M21-GAP-02053"},"M21-GAP-02053":{"line":5308,"offset":946541,"length":179,"previous":"M21-GAP-02052","next":"M21-GAP-02054"},"M21-GAP-02054":{"line":5309,"offset":946720,"length":179,"previous":"M21-GAP-02053","next":"M21-GAP-02055"},"M21-GAP-02055":{"line":5310,"offset":946899,"length":179,"previous":"M21-GAP-02054","next":"M21-GAP-02056"},"M21-GAP-02056":{"line":5311,"offset":947078,"length":179,"previous":"M21-GAP-02055","next":"M21-GAP-02057"},"M21-GAP-02057":{"line":5312,"offset":947257,"length":179,"previous":"M21-GAP-02056","next":"M21-GAP-02058"},"M21-GAP-02058":{"line":5313,"offset":947436,"length":179,"previous":"M21-GAP-02057","next":"M21-GAP-02059"},"M21-GAP-02059":{"line":5314,"offset":947615,"length":179,"previous":"M21-GAP-02058","next":"M21-GAP-02060"},"M21-GAP-02060":{"line":5315,"offset":947794,"length":178,"previous":"M21-GAP-02059","next":"M21-GAP-02061"},"M21-GAP-02061":{"line":5316,"offset":947972,"length":179,"previous":"M21-GAP-02060","next":"M21-GAP-02062"},"M21-GAP-02062":{"line":5317,"offset":948151,"length":179,"previous":"M21-GAP-02061","next":"M21-GAP-02063"},"M21-GAP-02063":{"line":5318,"offset":948330,"length":179,"previous":"M21-GAP-02062","next":"M21-GAP-02064"},"M21-GAP-02064":{"line":5319,"offset":948509,"length":179,"previous":"M21-GAP-02063","next":"M21-GAP-02065"},"M21-GAP-02065":{"line":5320,"offset":948688,"length":179,"previous":"M21-GAP-02064","next":"M21-GAP-02066"},"M21-GAP-02066":{"line":5321,"offset":948867,"length":179,"previous":"M21-GAP-02065","next":"M21-GAP-02067"},"M21-GAP-02067":{"line":5322,"offset":949046,"length":179,"previous":"M21-GAP-02066","next":"M21-GAP-02068"},"M21-GAP-02068":{"line":5323,"offset":949225,"length":179,"previous":"M21-GAP-02067","next":"M21-GAP-02069"},"M21-GAP-02069":{"line":5324,"offset":949404,"length":179,"previous":"M21-GAP-02068","next":"M21-GAP-02070"},"M21-GAP-02070":{"line":5325,"offset":949583,"length":179,"previous":"M21-GAP-02069","next":"M21-GAP-02071"},"M21-GAP-02071":{"line":5326,"offset":949762,"length":178,"previous":"M21-GAP-02070","next":"M21-GAP-02072"},"M21-GAP-02072":{"line":5327,"offset":949940,"length":179,"previous":"M21-GAP-02071","next":"M21-GAP-02073"},"M21-GAP-02073":{"line":5328,"offset":950119,"length":179,"previous":"M21-GAP-02072","next":"M21-GAP-02074"},"M21-GAP-02074":{"line":5329,"offset":950298,"length":179,"previous":"M21-GAP-02073","next":"M21-GAP-02075"},"M21-GAP-02075":{"line":5330,"offset":950477,"length":179,"previous":"M21-GAP-02074","next":"M21-GAP-02076"},"M21-GAP-02076":{"line":5331,"offset":950656,"length":179,"previous":"M21-GAP-02075","next":"M21-GAP-02077"},"M21-GAP-02077":{"line":5332,"offset":950835,"length":179,"previous":"M21-GAP-02076","next":"M21-GAP-02078"},"M21-GAP-02078":{"line":5333,"offset":951014,"length":179,"previous":"M21-GAP-02077","next":"M21-GAP-02079"},"M21-GAP-02079":{"line":5334,"offset":951193,"length":179,"previous":"M21-GAP-02078","next":"M21-GAP-02080"},"M21-GAP-02080":{"line":5335,"offset":951372,"length":179,"previous":"M21-GAP-02079","next":"M21-GAP-02081"},"M21-GAP-02081":{"line":5336,"offset":951551,"length":179,"previous":"M21-GAP-02080","next":"M21-GAP-02082"},"M21-GAP-02082":{"line":5337,"offset":951730,"length":178,"previous":"M21-GAP-02081","next":"M21-GAP-02083"},"M21-GAP-02083":{"line":5338,"offset":951908,"length":179,"previous":"M21-GAP-02082","next":"M21-GAP-02084"},"M21-GAP-02084":{"line":5339,"offset":952087,"length":179,"previous":"M21-GAP-02083","next":"M21-GAP-02085"},"M21-GAP-02085":{"line":5340,"offset":952266,"length":179,"previous":"M21-GAP-02084","next":"M21-GAP-02086"},"M21-GAP-02086":{"line":5341,"offset":952445,"length":179,"previous":"M21-GAP-02085","next":"M21-GAP-02087"},"M21-GAP-02087":{"line":5342,"offset":952624,"length":179,"previous":"M21-GAP-02086","next":"M21-GAP-02088"},"M21-GAP-02088":{"line":5343,"offset":952803,"length":179,"previous":"M21-GAP-02087","next":"M21-GAP-02089"},"M21-GAP-02089":{"line":5344,"offset":952982,"length":179,"previous":"M21-GAP-02088","next":"M21-GAP-02090"},"M21-GAP-02090":{"line":5345,"offset":953161,"length":179,"previous":"M21-GAP-02089","next":"M21-GAP-02091"},"M21-GAP-02091":{"line":5346,"offset":953340,"length":179,"previous":"M21-GAP-02090","next":"M21-GAP-02092"},"M21-GAP-02092":{"line":5347,"offset":953519,"length":179,"previous":"M21-GAP-02091","next":"M21-GAP-02093"},"M21-GAP-02093":{"line":5348,"offset":953698,"length":178,"previous":"M21-GAP-02092","next":"M21-GAP-02094"},"M21-GAP-02094":{"line":5349,"offset":953876,"length":179,"previous":"M21-GAP-02093","next":"M21-GAP-02095"},"M21-GAP-02095":{"line":5350,"offset":954055,"length":179,"previous":"M21-GAP-02094","next":"M21-GAP-02096"},"M21-GAP-02096":{"line":5351,"offset":954234,"length":179,"previous":"M21-GAP-02095","next":"M21-GAP-02097"},"M21-GAP-02097":{"line":5352,"offset":954413,"length":179,"previous":"M21-GAP-02096","next":"M21-GAP-02098"},"M21-GAP-02098":{"line":5353,"offset":954592,"length":179,"previous":"M21-GAP-02097","next":"M21-GAP-02099"},"M21-GAP-02099":{"line":5354,"offset":954771,"length":179,"previous":"M21-GAP-02098","next":"M21-GAP-02100"},"M21-GAP-02100":{"line":5355,"offset":954950,"length":179,"previous":"M21-GAP-02099","next":"M21-GAP-02101"},"M21-GAP-02101":{"line":5356,"offset":955129,"length":179,"previous":"M21-GAP-02100","next":"M21-GAP-02102"},"M21-GAP-02102":{"line":5357,"offset":955308,"length":179,"previous":"M21-GAP-02101","next":"M21-GAP-02103"},"M21-GAP-02103":{"line":5358,"offset":955487,"length":179,"previous":"M21-GAP-02102","next":"M21-GAP-02104"},"M21-GAP-02104":{"line":5359,"offset":955666,"length":178,"previous":"M21-GAP-02103","next":"M21-GAP-02105"},"M21-GAP-02105":{"line":5360,"offset":955844,"length":179,"previous":"M21-GAP-02104","next":"M21-GAP-02106"},"M21-GAP-02106":{"line":5361,"offset":956023,"length":179,"previous":"M21-GAP-02105","next":"M21-GAP-02107"},"M21-GAP-02107":{"line":5362,"offset":956202,"length":179,"previous":"M21-GAP-02106","next":"M21-GAP-02108"},"M21-GAP-02108":{"line":5363,"offset":956381,"length":179,"previous":"M21-GAP-02107","next":"M21-GAP-02109"},"M21-GAP-02109":{"line":5364,"offset":956560,"length":179,"previous":"M21-GAP-02108","next":"M21-GAP-02110"},"M21-GAP-02110":{"line":5365,"offset":956739,"length":179,"previous":"M21-GAP-02109","next":"M21-GAP-02111"},"M21-GAP-02111":{"line":5366,"offset":956918,"length":179,"previous":"M21-GAP-02110","next":"M21-GAP-02112"},"M21-GAP-02112":{"line":5367,"offset":957097,"length":179,"previous":"M21-GAP-02111","next":"M21-GAP-02113"},"M21-GAP-02113":{"line":5368,"offset":957276,"length":179,"previous":"M21-GAP-02112","next":"M21-GAP-02114"},"M21-GAP-02114":{"line":5369,"offset":957455,"length":179,"previous":"M21-GAP-02113","next":"M21-GAP-02115"},"M21-GAP-02115":{"line":5370,"offset":957634,"length":178,"previous":"M21-GAP-02114","next":"M21-GAP-02116"},"M21-GAP-02116":{"line":5371,"offset":957812,"length":179,"previous":"M21-GAP-02115","next":"M21-GAP-02117"},"M21-GAP-02117":{"line":5372,"offset":957991,"length":179,"previous":"M21-GAP-02116","next":"M21-GAP-02118"},"M21-GAP-02118":{"line":5373,"offset":958170,"length":179,"previous":"M21-GAP-02117","next":"M21-GAP-02119"},"M21-GAP-02119":{"line":5374,"offset":958349,"length":179,"previous":"M21-GAP-02118","next":"M21-GAP-02120"},"M21-GAP-02120":{"line":5375,"offset":958528,"length":179,"previous":"M21-GAP-02119","next":"M21-GAP-02121"},"M21-GAP-02121":{"line":5376,"offset":958707,"length":179,"previous":"M21-GAP-02120","next":"M21-GAP-02122"},"M21-GAP-02122":{"line":5377,"offset":958886,"length":179,"previous":"M21-GAP-02121","next":"M21-GAP-02123"},"M21-GAP-02123":{"line":5378,"offset":959065,"length":179,"previous":"M21-GAP-02122","next":"M21-GAP-02124"},"M21-GAP-02124":{"line":5379,"offset":959244,"length":179,"previous":"M21-GAP-02123","next":"M21-GAP-02125"},"M21-GAP-02125":{"line":5380,"offset":959423,"length":179,"previous":"M21-GAP-02124","next":"M21-GAP-02126"},"M21-GAP-02126":{"line":5381,"offset":959602,"length":178,"previous":"M21-GAP-02125","next":"M21-GAP-02127"},"M21-GAP-02127":{"line":5382,"offset":959780,"length":179,"previous":"M21-GAP-02126","next":"M21-GAP-02128"},"M21-GAP-02128":{"line":5383,"offset":959959,"length":179,"previous":"M21-GAP-02127","next":"M21-GAP-02129"},"M21-GAP-02129":{"line":5384,"offset":960138,"length":179,"previous":"M21-GAP-02128","next":"M21-GAP-02130"},"M21-GAP-02130":{"line":5385,"offset":960317,"length":179,"previous":"M21-GAP-02129","next":"M21-GAP-02131"},"M21-GAP-02131":{"line":5386,"offset":960496,"length":179,"previous":"M21-GAP-02130","next":"M21-GAP-02132"},"M21-GAP-02132":{"line":5387,"offset":960675,"length":179,"previous":"M21-GAP-02131","next":"M21-GAP-02133"},"M21-GAP-02133":{"line":5388,"offset":960854,"length":179,"previous":"M21-GAP-02132","next":"M21-GAP-02134"},"M21-GAP-02134":{"line":5389,"offset":961033,"length":179,"previous":"M21-GAP-02133","next":"M21-GAP-02135"},"M21-GAP-02135":{"line":5390,"offset":961212,"length":179,"previous":"M21-GAP-02134","next":"M21-GAP-02136"},"M21-GAP-02136":{"line":5391,"offset":961391,"length":179,"previous":"M21-GAP-02135","next":"M21-GAP-02137"},"M21-GAP-02137":{"line":5392,"offset":961570,"length":178,"previous":"M21-GAP-02136","next":"M21-GAP-02138"},"M21-GAP-02138":{"line":5393,"offset":961748,"length":178,"previous":"M21-GAP-02137","next":"M21-GAP-02139"},"M21-GAP-02139":{"line":5394,"offset":961926,"length":179,"previous":"M21-GAP-02138","next":"M21-GAP-02140"},"M21-GAP-02140":{"line":5395,"offset":962105,"length":179,"previous":"M21-GAP-02139","next":"M21-GAP-02141"},"M21-GAP-02141":{"line":5396,"offset":962284,"length":179,"previous":"M21-GAP-02140","next":"M21-GAP-02142"},"M21-GAP-02142":{"line":5397,"offset":962463,"length":179,"previous":"M21-GAP-02141","next":"M21-GAP-02143"},"M21-GAP-02143":{"line":5398,"offset":962642,"length":179,"previous":"M21-GAP-02142","next":"M21-GAP-02144"},"M21-GAP-02144":{"line":5399,"offset":962821,"length":178,"previous":"M21-GAP-02143","next":"M21-GAP-02145"},"M21-GAP-02145":{"line":5400,"offset":962999,"length":178,"previous":"M21-GAP-02144","next":"M21-GAP-02146"},"M21-GAP-02146":{"line":5401,"offset":963177,"length":178,"previous":"M21-GAP-02145","next":"M21-GAP-02147"},"M21-GAP-02147":{"line":5402,"offset":963355,"length":178,"previous":"M21-GAP-02146","next":"M21-GAP-02148"},"M21-GAP-02148":{"line":5403,"offset":963533,"length":178,"previous":"M21-GAP-02147","next":"M21-GAP-02149"},"M21-GAP-02149":{"line":5404,"offset":963711,"length":178,"previous":"M21-GAP-02148","next":"M21-GAP-02150"},"M21-GAP-02150":{"line":5405,"offset":963889,"length":178,"previous":"M21-GAP-02149","next":"M21-GAP-02151"},"M21-GAP-02151":{"line":5406,"offset":964067,"length":178,"previous":"M21-GAP-02150","next":"M21-GAP-02152"},"M21-GAP-02152":{"line":5407,"offset":964245,"length":208,"previous":"M21-GAP-02151","next":"M21-GAP-02153"},"M21-GAP-02153":{"line":5408,"offset":964453,"length":208,"previous":"M21-GAP-02152","next":"M21-GAP-02154"},"M21-GAP-02154":{"line":5409,"offset":964661,"length":209,"previous":"M21-GAP-02153","next":"M21-GAP-02155"},"M21-GAP-02155":{"line":5410,"offset":964870,"length":209,"previous":"M21-GAP-02154","next":"M21-GAP-02156"},"M21-GAP-02156":{"line":5411,"offset":965079,"length":209,"previous":"M21-GAP-02155","next":"M21-GAP-02157"},"M21-GAP-02157":{"line":5412,"offset":965288,"length":209,"previous":"M21-GAP-02156","next":"M21-GAP-02158"},"M21-GAP-02158":{"line":5413,"offset":965497,"length":208,"previous":"M21-GAP-02157","next":"M21-GAP-02159"},"M21-GAP-02159":{"line":5414,"offset":965705,"length":208,"previous":"M21-GAP-02158","next":"M21-GAP-02160"},"M21-GAP-02160":{"line":5415,"offset":965913,"length":208,"previous":"M21-GAP-02159","next":"M21-GAP-02161"},"M21-GAP-02161":{"line":5416,"offset":966121,"length":208,"previous":"M21-GAP-02160","next":"M21-GAP-02162"},"M21-GAP-02162":{"line":5417,"offset":966329,"length":208,"previous":"M21-GAP-02161","next":"M21-GAP-02163"},"M21-GAP-02163":{"line":5418,"offset":966537,"length":208,"previous":"M21-GAP-02162","next":"M21-GAP-02164"},"M21-GAP-02164":{"line":5419,"offset":966745,"length":208,"previous":"M21-GAP-02163","next":"M21-GAP-02165"},"M21-GAP-02165":{"line":5420,"offset":966953,"length":208,"previous":"M21-GAP-02164","next":"M21-GAP-02166"},"M21-GAP-02166":{"line":5421,"offset":967161,"length":185,"previous":"M21-GAP-02165","next":"M21-GAP-02167"},"M21-GAP-02167":{"line":5422,"offset":967346,"length":206,"previous":"M21-GAP-02166","next":"M21-GAP-02168"},"M21-GAP-02168":{"line":5423,"offset":967552,"length":206,"previous":"M21-GAP-02167","next":"M21-GAP-02169"},"M21-GAP-02169":{"line":5424,"offset":967758,"length":207,"previous":"M21-GAP-02168","next":"M21-GAP-02170"},"M21-GAP-02170":{"line":5425,"offset":967965,"length":207,"previous":"M21-GAP-02169","next":"M21-GAP-02171"},"M21-GAP-02171":{"line":5426,"offset":968172,"length":207,"previous":"M21-GAP-02170","next":"M21-GAP-02172"},"M21-GAP-02172":{"line":5427,"offset":968379,"length":207,"previous":"M21-GAP-02171","next":"M21-GAP-02173"},"M21-GAP-02173":{"line":5428,"offset":968586,"length":207,"previous":"M21-GAP-02172","next":"M21-GAP-02174"},"M21-GAP-02174":{"line":5429,"offset":968793,"length":207,"previous":"M21-GAP-02173","next":"M21-GAP-02175"},"M21-GAP-02175":{"line":5430,"offset":969000,"length":206,"previous":"M21-GAP-02174","next":"M21-GAP-02176"},"M21-GAP-02176":{"line":5431,"offset":969206,"length":206,"previous":"M21-GAP-02175","next":"M21-GAP-02177"},"M21-GAP-02177":{"line":5432,"offset":969412,"length":206,"previous":"M21-GAP-02176","next":"M21-GAP-02178"},"M21-GAP-02178":{"line":5433,"offset":969618,"length":206,"previous":"M21-GAP-02177","next":"M21-GAP-02179"},"M21-GAP-02179":{"line":5434,"offset":969824,"length":206,"previous":"M21-GAP-02178","next":"M21-GAP-02180"},"M21-GAP-02180":{"line":5435,"offset":970030,"length":206,"previous":"M21-GAP-02179","next":"M21-GAP-02181"},"M21-GAP-02181":{"line":5436,"offset":970236,"length":206,"previous":"M21-GAP-02180","next":"M21-GAP-02182"},"M21-GAP-02182":{"line":5437,"offset":970442,"length":206,"previous":"M21-GAP-02181","next":"M21-GAP-02183"},"M21-GAP-02183":{"line":5438,"offset":970648,"length":175,"previous":"M21-GAP-02182","next":"M21-GAP-02184"},"M21-GAP-02184":{"line":5439,"offset":970823,"length":175,"previous":"M21-GAP-02183","next":"M21-GAP-02185"},"M21-GAP-02185":{"line":5440,"offset":970998,"length":176,"previous":"M21-GAP-02184","next":"M21-GAP-02186"},"M21-GAP-02186":{"line":5441,"offset":971174,"length":176,"previous":"M21-GAP-02185","next":"M21-GAP-02187"},"M21-GAP-02187":{"line":5442,"offset":971350,"length":176,"previous":"M21-GAP-02186","next":"M21-GAP-02188"},"M21-GAP-02188":{"line":5443,"offset":971526,"length":176,"previous":"M21-GAP-02187","next":"M21-GAP-02189"},"M21-GAP-02189":{"line":5444,"offset":971702,"length":176,"previous":"M21-GAP-02188","next":"M21-GAP-02190"},"M21-GAP-02190":{"line":5445,"offset":971878,"length":176,"previous":"M21-GAP-02189","next":"M21-GAP-02191"},"M21-GAP-02191":{"line":5446,"offset":972054,"length":176,"previous":"M21-GAP-02190","next":"M21-GAP-02192"},"M21-GAP-02192":{"line":5447,"offset":972230,"length":176,"previous":"M21-GAP-02191","next":"M21-GAP-02193"},"M21-GAP-02193":{"line":5448,"offset":972406,"length":176,"previous":"M21-GAP-02192","next":"M21-GAP-02194"},"M21-GAP-02194":{"line":5449,"offset":972582,"length":176,"previous":"M21-GAP-02193","next":"M21-GAP-02195"},"M21-GAP-02195":{"line":5450,"offset":972758,"length":175,"previous":"M21-GAP-02194","next":"M21-GAP-02196"},"M21-GAP-02196":{"line":5451,"offset":972933,"length":176,"previous":"M21-GAP-02195","next":"M21-GAP-02197"},"M21-GAP-02197":{"line":5452,"offset":973109,"length":176,"previous":"M21-GAP-02196","next":"M21-GAP-02198"},"M21-GAP-02198":{"line":5453,"offset":973285,"length":176,"previous":"M21-GAP-02197","next":"M21-GAP-02199"},"M21-GAP-02199":{"line":5454,"offset":973461,"length":176,"previous":"M21-GAP-02198","next":"M21-GAP-02200"},"M21-GAP-02200":{"line":5455,"offset":973637,"length":176,"previous":"M21-GAP-02199","next":"M21-GAP-02201"},"M21-GAP-02201":{"line":5456,"offset":973813,"length":176,"previous":"M21-GAP-02200","next":"M21-GAP-02202"},"M21-GAP-02202":{"line":5457,"offset":973989,"length":176,"previous":"M21-GAP-02201","next":"M21-GAP-02203"},"M21-GAP-02203":{"line":5458,"offset":974165,"length":176,"previous":"M21-GAP-02202","next":"M21-GAP-02204"},"M21-GAP-02204":{"line":5459,"offset":974341,"length":176,"previous":"M21-GAP-02203","next":"M21-GAP-02205"},"M21-GAP-02205":{"line":5460,"offset":974517,"length":176,"previous":"M21-GAP-02204","next":"M21-GAP-02206"},"M21-GAP-02206":{"line":5461,"offset":974693,"length":175,"previous":"M21-GAP-02205","next":"M21-GAP-02207"},"M21-GAP-02207":{"line":5462,"offset":974868,"length":175,"previous":"M21-GAP-02206","next":"M21-GAP-02208"},"M21-GAP-02208":{"line":5463,"offset":975043,"length":175,"previous":"M21-GAP-02207","next":"M21-GAP-02209"},"M21-GAP-02209":{"line":5464,"offset":975218,"length":175,"previous":"M21-GAP-02208","next":"M21-GAP-02210"},"M21-GAP-02210":{"line":5465,"offset":975393,"length":175,"previous":"M21-GAP-02209","next":"M21-GAP-02211"},"M21-GAP-02211":{"line":5466,"offset":975568,"length":175,"previous":"M21-GAP-02210","next":"M21-GAP-02212"},"M21-GAP-02212":{"line":5467,"offset":975743,"length":175,"previous":"M21-GAP-02211","next":"M21-GAP-02213"},"M21-GAP-02213":{"line":5468,"offset":975918,"length":185,"previous":"M21-GAP-02212","next":"M21-GAP-02214"},"M21-GAP-02214":{"line":5469,"offset":976103,"length":185,"previous":"M21-GAP-02213","next":"M21-GAP-02215"},"M21-GAP-02215":{"line":5470,"offset":976288,"length":185,"previous":"M21-GAP-02214","next":"M21-GAP-02216"},"M21-GAP-02216":{"line":5471,"offset":976473,"length":178,"previous":"M21-GAP-02215","next":"M21-GAP-02217"},"M21-GAP-02217":{"line":5472,"offset":976651,"length":178,"previous":"M21-GAP-02216","next":"M21-GAP-02218"},"M21-GAP-02218":{"line":5473,"offset":976829,"length":179,"previous":"M21-GAP-02217","next":"M21-GAP-02219"},"M21-GAP-02219":{"line":5474,"offset":977008,"length":179,"previous":"M21-GAP-02218","next":"M21-GAP-02220"},"M21-GAP-02220":{"line":5475,"offset":977187,"length":179,"previous":"M21-GAP-02219","next":"M21-GAP-02221"},"M21-GAP-02221":{"line":5476,"offset":977366,"length":179,"previous":"M21-GAP-02220","next":"M21-GAP-02222"},"M21-GAP-02222":{"line":5477,"offset":977545,"length":179,"previous":"M21-GAP-02221","next":"M21-GAP-02223"},"M21-GAP-02223":{"line":5478,"offset":977724,"length":179,"previous":"M21-GAP-02222","next":"M21-GAP-02224"},"M21-GAP-02224":{"line":5479,"offset":977903,"length":179,"previous":"M21-GAP-02223","next":"M21-GAP-02225"},"M21-GAP-02225":{"line":5480,"offset":978082,"length":179,"previous":"M21-GAP-02224","next":"M21-GAP-02226"},"M21-GAP-02226":{"line":5481,"offset":978261,"length":178,"previous":"M21-GAP-02225","next":"M21-GAP-02227"},"M21-GAP-02227":{"line":5482,"offset":978439,"length":178,"previous":"M21-GAP-02226","next":"M21-GAP-02228"},"M21-GAP-02228":{"line":5483,"offset":978617,"length":178,"previous":"M21-GAP-02227","next":"M21-GAP-02229"},"M21-GAP-02229":{"line":5484,"offset":978795,"length":178,"previous":"M21-GAP-02228","next":"M21-GAP-02230"},"M21-GAP-02230":{"line":5485,"offset":978973,"length":178,"previous":"M21-GAP-02229","next":"M21-GAP-02231"},"M21-GAP-02231":{"line":5486,"offset":979151,"length":178,"previous":"M21-GAP-02230","next":"M21-GAP-02232"},"M21-GAP-02232":{"line":5487,"offset":979329,"length":178,"previous":"M21-GAP-02231","next":"M21-GAP-02233"},"M21-GAP-02233":{"line":5488,"offset":979507,"length":178,"previous":"M21-GAP-02232","next":"M21-GAP-02234"},"M21-GAP-02234":{"line":5489,"offset":979685,"length":171,"previous":"M21-GAP-02233","next":"M21-GAP-02235"},"M21-GAP-02235":{"line":5490,"offset":979856,"length":171,"previous":"M21-GAP-02234","next":"M21-GAP-02236"},"M21-GAP-02236":{"line":5491,"offset":980027,"length":172,"previous":"M21-GAP-02235","next":"M21-GAP-02237"},"M21-GAP-02237":{"line":5492,"offset":980199,"length":172,"previous":"M21-GAP-02236","next":"M21-GAP-02238"},"M21-GAP-02238":{"line":5493,"offset":980371,"length":172,"previous":"M21-GAP-02237","next":"M21-GAP-02239"},"M21-GAP-02239":{"line":5494,"offset":980543,"length":172,"previous":"M21-GAP-02238","next":"M21-GAP-02240"},"M21-GAP-02240":{"line":5495,"offset":980715,"length":172,"previous":"M21-GAP-02239","next":"M21-GAP-02241"},"M21-GAP-02241":{"line":5496,"offset":980887,"length":172,"previous":"M21-GAP-02240","next":"M21-GAP-02242"},"M21-GAP-02242":{"line":5497,"offset":981059,"length":172,"previous":"M21-GAP-02241","next":"M21-GAP-02243"},"M21-GAP-02243":{"line":5498,"offset":981231,"length":172,"previous":"M21-GAP-02242","next":"M21-GAP-02244"},"M21-GAP-02244":{"line":5499,"offset":981403,"length":172,"previous":"M21-GAP-02243","next":"M21-GAP-02245"},"M21-GAP-02245":{"line":5500,"offset":981575,"length":172,"previous":"M21-GAP-02244","next":"M21-GAP-02246"},"M21-GAP-02246":{"line":5501,"offset":981747,"length":171,"previous":"M21-GAP-02245","next":"M21-GAP-02247"},"M21-GAP-02247":{"line":5502,"offset":981918,"length":172,"previous":"M21-GAP-02246","next":"M21-GAP-02248"},"M21-GAP-02248":{"line":5503,"offset":982090,"length":172,"previous":"M21-GAP-02247","next":"M21-GAP-02249"},"M21-GAP-02249":{"line":5504,"offset":982262,"length":172,"previous":"M21-GAP-02248","next":"M21-GAP-02250"},"M21-GAP-02250":{"line":5505,"offset":982434,"length":172,"previous":"M21-GAP-02249","next":"M21-GAP-02251"},"M21-GAP-02251":{"line":5506,"offset":982606,"length":172,"previous":"M21-GAP-02250","next":"M21-GAP-02252"},"M21-GAP-02252":{"line":5507,"offset":982778,"length":172,"previous":"M21-GAP-02251","next":"M21-GAP-02253"},"M21-GAP-02253":{"line":5508,"offset":982950,"length":172,"previous":"M21-GAP-02252","next":"M21-GAP-02254"},"M21-GAP-02254":{"line":5509,"offset":983122,"length":172,"previous":"M21-GAP-02253","next":"M21-GAP-02255"},"M21-GAP-02255":{"line":5510,"offset":983294,"length":172,"previous":"M21-GAP-02254","next":"M21-GAP-02256"},"M21-GAP-02256":{"line":5511,"offset":983466,"length":172,"previous":"M21-GAP-02255","next":"M21-GAP-02257"},"M21-GAP-02257":{"line":5512,"offset":983638,"length":171,"previous":"M21-GAP-02256","next":"M21-GAP-02258"},"M21-GAP-02258":{"line":5513,"offset":983809,"length":172,"previous":"M21-GAP-02257","next":"M21-GAP-02259"},"M21-GAP-02259":{"line":5514,"offset":983981,"length":172,"previous":"M21-GAP-02258","next":"M21-GAP-02260"},"M21-GAP-02260":{"line":5515,"offset":984153,"length":172,"previous":"M21-GAP-02259","next":"M21-GAP-02261"},"M21-GAP-02261":{"line":5516,"offset":984325,"length":172,"previous":"M21-GAP-02260","next":"M21-GAP-02262"},"M21-GAP-02262":{"line":5517,"offset":984497,"length":172,"previous":"M21-GAP-02261","next":"M21-GAP-02263"},"M21-GAP-02263":{"line":5518,"offset":984669,"length":172,"previous":"M21-GAP-02262","next":"M21-GAP-02264"},"M21-GAP-02264":{"line":5519,"offset":984841,"length":172,"previous":"M21-GAP-02263","next":"M21-GAP-02265"},"M21-GAP-02265":{"line":5520,"offset":985013,"length":172,"previous":"M21-GAP-02264","next":"M21-GAP-02266"},"M21-GAP-02266":{"line":5521,"offset":985185,"length":172,"previous":"M21-GAP-02265","next":"M21-GAP-02267"},"M21-GAP-02267":{"line":5522,"offset":985357,"length":172,"previous":"M21-GAP-02266","next":"M21-GAP-02268"},"M21-GAP-02268":{"line":5523,"offset":985529,"length":171,"previous":"M21-GAP-02267","next":"M21-GAP-02269"},"M21-GAP-02269":{"line":5524,"offset":985700,"length":172,"previous":"M21-GAP-02268","next":"M21-GAP-02270"},"M21-GAP-02270":{"line":5525,"offset":985872,"length":172,"previous":"M21-GAP-02269","next":"M21-GAP-02271"},"M21-GAP-02271":{"line":5526,"offset":986044,"length":172,"previous":"M21-GAP-02270","next":"M21-GAP-02272"},"M21-GAP-02272":{"line":5527,"offset":986216,"length":172,"previous":"M21-GAP-02271","next":"M21-GAP-02273"},"M21-GAP-02273":{"line":5528,"offset":986388,"length":172,"previous":"M21-GAP-02272","next":"M21-GAP-02274"},"M21-GAP-02274":{"line":5529,"offset":986560,"length":172,"previous":"M21-GAP-02273","next":"M21-GAP-02275"},"M21-GAP-02275":{"line":5530,"offset":986732,"length":172,"previous":"M21-GAP-02274","next":"M21-GAP-02276"},"M21-GAP-02276":{"line":5531,"offset":986904,"length":172,"previous":"M21-GAP-02275","next":"M21-GAP-02277"},"M21-GAP-02277":{"line":5532,"offset":987076,"length":172,"previous":"M21-GAP-02276","next":"M21-GAP-02278"},"M21-GAP-02278":{"line":5533,"offset":987248,"length":172,"previous":"M21-GAP-02277","next":"M21-GAP-02279"},"M21-GAP-02279":{"line":5534,"offset":987420,"length":171,"previous":"M21-GAP-02278","next":"M21-GAP-02280"},"M21-GAP-02280":{"line":5535,"offset":987591,"length":172,"previous":"M21-GAP-02279","next":"M21-GAP-02281"},"M21-GAP-02281":{"line":5536,"offset":987763,"length":172,"previous":"M21-GAP-02280","next":"M21-GAP-02282"},"M21-GAP-02282":{"line":5537,"offset":987935,"length":172,"previous":"M21-GAP-02281","next":"M21-GAP-02283"},"M21-GAP-02283":{"line":5538,"offset":988107,"length":171,"previous":"M21-GAP-02282","next":"M21-GAP-02284"},"M21-GAP-02284":{"line":5539,"offset":988278,"length":171,"previous":"M21-GAP-02283","next":"M21-GAP-02285"},"M21-GAP-02285":{"line":5540,"offset":988449,"length":171,"previous":"M21-GAP-02284","next":"M21-GAP-02286"},"M21-GAP-02286":{"line":5541,"offset":988620,"length":171,"previous":"M21-GAP-02285","next":"M21-GAP-02287"},"M21-GAP-02287":{"line":5542,"offset":988791,"length":184,"previous":"M21-GAP-02286","next":"M21-GAP-02288"},"M21-GAP-02288":{"line":5543,"offset":988975,"length":184,"previous":"M21-GAP-02287","next":"M21-GAP-02289"},"M21-GAP-02289":{"line":5544,"offset":989159,"length":184,"previous":"M21-GAP-02288","next":"M21-GAP-02290"},"M21-GAP-02290":{"line":5545,"offset":989343,"length":184,"previous":"M21-GAP-02289","next":"M21-GAP-02291"},"M21-GAP-02291":{"line":5546,"offset":989527,"length":197,"previous":"M21-GAP-02290","next":"M21-GAP-02292"},"M21-GAP-02292":{"line":5547,"offset":989724,"length":197,"previous":"M21-GAP-02291","next":"M21-GAP-02293"},"M21-GAP-02293":{"line":5548,"offset":989921,"length":195,"previous":"M21-GAP-02292","next":"M21-GAP-02294"},"M21-GAP-02294":{"line":5549,"offset":990116,"length":197,"previous":"M21-GAP-02293","next":"M21-GAP-02295"},"M21-GAP-02295":{"line":5550,"offset":990313,"length":197,"previous":"M21-GAP-02294","next":"M21-GAP-02296"},"M21-GAP-02296":{"line":5551,"offset":990510,"length":196,"previous":"M21-GAP-02295","next":"M21-GAP-02297"},"M21-GAP-02297":{"line":5552,"offset":990706,"length":212,"previous":"M21-GAP-02296","next":"M21-GAP-02298"},"M21-GAP-02298":{"line":5553,"offset":990918,"length":212,"previous":"M21-GAP-02297","next":"M21-GAP-02299"},"M21-GAP-02299":{"line":5554,"offset":991130,"length":212,"previous":"M21-GAP-02298","next":"M21-GAP-02300"},"M21-GAP-02300":{"line":5555,"offset":991342,"length":212,"previous":"M21-GAP-02299","next":"M21-GAP-02301"},"M21-GAP-02301":{"line":5556,"offset":991554,"length":212,"previous":"M21-GAP-02300","next":"M21-GAP-02302"},"M21-GAP-02302":{"line":5557,"offset":991766,"length":201,"previous":"M21-GAP-02301","next":"M21-GAP-02303"},"M21-GAP-02303":{"line":5558,"offset":991967,"length":201,"previous":"M21-GAP-02302","next":"M21-GAP-02304"},"M21-GAP-02304":{"line":5559,"offset":992168,"length":201,"previous":"M21-GAP-02303","next":"M21-GAP-02305"},"M21-GAP-02305":{"line":5560,"offset":992369,"length":201,"previous":"M21-GAP-02304","next":"M21-GAP-02306"},"M21-GAP-02306":{"line":5561,"offset":992570,"length":201,"previous":"M21-GAP-02305","next":"M21-GAP-02307"},"M21-GAP-02307":{"line":5562,"offset":992771,"length":215,"previous":"M21-GAP-02306","next":"M21-GAP-02308"},"M21-GAP-02308":{"line":5563,"offset":992986,"length":215,"previous":"M21-GAP-02307","next":"M21-GAP-02309"},"M21-GAP-02309":{"line":5564,"offset":993201,"length":215,"previous":"M21-GAP-02308","next":"M21-GAP-02310"},"M21-GAP-02310":{"line":5565,"offset":993416,"length":204,"previous":"M21-GAP-02309","next":"M21-GAP-02311"},"M21-GAP-02311":{"line":5566,"offset":993620,"length":204,"previous":"M21-GAP-02310","next":"M21-GAP-02312"},"M21-GAP-02312":{"line":5567,"offset":993824,"length":204,"previous":"M21-GAP-02311","next":"M21-GAP-02313"},"M21-GAP-02313":{"line":5568,"offset":994028,"length":214,"previous":"M21-GAP-02312","next":"M21-GAP-02314"},"M21-GAP-02314":{"line":5569,"offset":994242,"length":214,"previous":"M21-GAP-02313","next":"M21-GAP-02315"},"M21-GAP-02315":{"line":5570,"offset":994456,"length":214,"previous":"M21-GAP-02314","next":"M21-GAP-02316"},"M21-GAP-02316":{"line":5571,"offset":994670,"length":203,"previous":"M21-GAP-02315","next":"M21-GAP-02317"},"M21-GAP-02317":{"line":5572,"offset":994873,"length":203,"previous":"M21-GAP-02316","next":"M21-GAP-02318"},"M21-GAP-02318":{"line":5573,"offset":995076,"length":203,"previous":"M21-GAP-02317","next":"M21-GAP-02319"},"M21-GAP-02319":{"line":5574,"offset":995279,"length":207,"previous":"M21-GAP-02318","next":"M21-GAP-02320"},"M21-GAP-02320":{"line":5575,"offset":995486,"length":207,"previous":"M21-GAP-02319","next":"M21-GAP-02321"},"M21-GAP-02321":{"line":5576,"offset":995693,"length":207,"previous":"M21-GAP-02320","next":"M21-GAP-02322"},"M21-GAP-02322":{"line":5577,"offset":995900,"length":207,"previous":"M21-GAP-02321","next":"M21-GAP-02323"},"M21-GAP-02323":{"line":5578,"offset":996107,"length":207,"previous":"M21-GAP-02322","next":"M21-GAP-02324"},"M21-GAP-02324":{"line":5579,"offset":996314,"length":196,"previous":"M21-GAP-02323","next":"M21-GAP-02325"},"M21-GAP-02325":{"line":5580,"offset":996510,"length":196,"previous":"M21-GAP-02324","next":"M21-GAP-02326"},"M21-GAP-02326":{"line":5581,"offset":996706,"length":196,"previous":"M21-GAP-02325","next":"M21-GAP-02327"},"M21-GAP-02327":{"line":5582,"offset":996902,"length":196,"previous":"M21-GAP-02326","next":"M21-GAP-02328"},"M21-GAP-02328":{"line":5583,"offset":997098,"length":196,"previous":"M21-GAP-02327","next":"M21-GAP-02329"},"M21-GAP-02329":{"line":5584,"offset":997294,"length":184,"previous":"M21-GAP-02328","next":"M21-GAP-02330"},"M21-GAP-02330":{"line":5585,"offset":997478,"length":184,"previous":"M21-GAP-02329","next":"M21-GAP-02331"},"M21-GAP-02331":{"line":5586,"offset":997662,"length":185,"previous":"M21-GAP-02330","next":"M21-GAP-02332"},"M21-GAP-02332":{"line":5587,"offset":997847,"length":185,"previous":"M21-GAP-02331","next":"M21-GAP-02333"},"M21-GAP-02333":{"line":5588,"offset":998032,"length":185,"previous":"M21-GAP-02332","next":"M21-GAP-02334"},"M21-GAP-02334":{"line":5589,"offset":998217,"length":185,"previous":"M21-GAP-02333","next":"M21-GAP-02335"},"M21-GAP-02335":{"line":5590,"offset":998402,"length":185,"previous":"M21-GAP-02334","next":"M21-GAP-02336"},"M21-GAP-02336":{"line":5591,"offset":998587,"length":185,"previous":"M21-GAP-02335","next":"M21-GAP-02337"},"M21-GAP-02337":{"line":5592,"offset":998772,"length":185,"previous":"M21-GAP-02336","next":"M21-GAP-02338"},"M21-GAP-02338":{"line":5593,"offset":998957,"length":185,"previous":"M21-GAP-02337","next":"M21-GAP-02339"},"M21-GAP-02339":{"line":5594,"offset":999142,"length":185,"previous":"M21-GAP-02338","next":"M21-GAP-02340"},"M21-GAP-02340":{"line":5595,"offset":999327,"length":185,"previous":"M21-GAP-02339","next":"M21-GAP-02341"},"M21-GAP-02341":{"line":5596,"offset":999512,"length":184,"previous":"M21-GAP-02340","next":"M21-GAP-02342"},"M21-GAP-02342":{"line":5597,"offset":999696,"length":185,"previous":"M21-GAP-02341","next":"M21-GAP-02343"},"M21-GAP-02343":{"line":5598,"offset":999881,"length":185,"previous":"M21-GAP-02342","next":"M21-GAP-02344"},"M21-GAP-02344":{"line":5599,"offset":1000066,"length":185,"previous":"M21-GAP-02343","next":"M21-GAP-02345"},"M21-GAP-02345":{"line":5600,"offset":1000251,"length":185,"previous":"M21-GAP-02344","next":"M21-GAP-02346"},"M21-GAP-02346":{"line":5601,"offset":1000436,"length":185,"previous":"M21-GAP-02345","next":"M21-GAP-02347"},"M21-GAP-02347":{"line":5602,"offset":1000621,"length":185,"previous":"M21-GAP-02346","next":"M21-GAP-02348"},"M21-GAP-02348":{"line":5603,"offset":1000806,"length":185,"previous":"M21-GAP-02347","next":"M21-GAP-02349"},"M21-GAP-02349":{"line":5604,"offset":1000991,"length":185,"previous":"M21-GAP-02348","next":"M21-GAP-02350"},"M21-GAP-02350":{"line":5605,"offset":1001176,"length":185,"previous":"M21-GAP-02349","next":"M21-GAP-02351"},"M21-GAP-02351":{"line":5606,"offset":1001361,"length":185,"previous":"M21-GAP-02350","next":"M21-GAP-02352"},"M21-GAP-02352":{"line":5607,"offset":1001546,"length":184,"previous":"M21-GAP-02351","next":"M21-GAP-02353"},"M21-GAP-02353":{"line":5608,"offset":1001730,"length":185,"previous":"M21-GAP-02352","next":"M21-GAP-02354"},"M21-GAP-02354":{"line":5609,"offset":1001915,"length":185,"previous":"M21-GAP-02353","next":"M21-GAP-02355"},"M21-GAP-02355":{"line":5610,"offset":1002100,"length":185,"previous":"M21-GAP-02354","next":"M21-GAP-02356"},"M21-GAP-02356":{"line":5611,"offset":1002285,"length":185,"previous":"M21-GAP-02355","next":"M21-GAP-02357"},"M21-GAP-02357":{"line":5612,"offset":1002470,"length":185,"previous":"M21-GAP-02356","next":"M21-GAP-02358"},"M21-GAP-02358":{"line":5613,"offset":1002655,"length":185,"previous":"M21-GAP-02357","next":"M21-GAP-02359"},"M21-GAP-02359":{"line":5614,"offset":1002840,"length":185,"previous":"M21-GAP-02358","next":"M21-GAP-02360"},"M21-GAP-02360":{"line":5615,"offset":1003025,"length":185,"previous":"M21-GAP-02359","next":"M21-GAP-02361"},"M21-GAP-02361":{"line":5616,"offset":1003210,"length":185,"previous":"M21-GAP-02360","next":"M21-GAP-02362"},"M21-GAP-02362":{"line":5617,"offset":1003395,"length":185,"previous":"M21-GAP-02361","next":"M21-GAP-02363"},"M21-GAP-02363":{"line":5618,"offset":1003580,"length":184,"previous":"M21-GAP-02362","next":"M21-GAP-02364"},"M21-GAP-02364":{"line":5619,"offset":1003764,"length":185,"previous":"M21-GAP-02363","next":"M21-GAP-02365"},"M21-GAP-02365":{"line":5620,"offset":1003949,"length":185,"previous":"M21-GAP-02364","next":"M21-GAP-02366"},"M21-GAP-02366":{"line":5621,"offset":1004134,"length":185,"previous":"M21-GAP-02365","next":"M21-GAP-02367"},"M21-GAP-02367":{"line":5622,"offset":1004319,"length":185,"previous":"M21-GAP-02366","next":"M21-GAP-02368"},"M21-GAP-02368":{"line":5623,"offset":1004504,"length":185,"previous":"M21-GAP-02367","next":"M21-GAP-02369"},"M21-GAP-02369":{"line":5624,"offset":1004689,"length":185,"previous":"M21-GAP-02368","next":"M21-GAP-02370"},"M21-GAP-02370":{"line":5625,"offset":1004874,"length":185,"previous":"M21-GAP-02369","next":"M21-GAP-02371"},"M21-GAP-02371":{"line":5626,"offset":1005059,"length":185,"previous":"M21-GAP-02370","next":"M21-GAP-02372"},"M21-GAP-02372":{"line":5627,"offset":1005244,"length":185,"previous":"M21-GAP-02371","next":"M21-GAP-02373"},"M21-GAP-02373":{"line":5628,"offset":1005429,"length":185,"previous":"M21-GAP-02372","next":"M21-GAP-02374"},"M21-GAP-02374":{"line":5629,"offset":1005614,"length":184,"previous":"M21-GAP-02373","next":"M21-GAP-02375"},"M21-GAP-02375":{"line":5630,"offset":1005798,"length":185,"previous":"M21-GAP-02374","next":"M21-GAP-02376"},"M21-GAP-02376":{"line":5631,"offset":1005983,"length":185,"previous":"M21-GAP-02375","next":"M21-GAP-02377"},"M21-GAP-02377":{"line":5632,"offset":1006168,"length":185,"previous":"M21-GAP-02376","next":"M21-GAP-02378"},"M21-GAP-02378":{"line":5633,"offset":1006353,"length":185,"previous":"M21-GAP-02377","next":"M21-GAP-02379"},"M21-GAP-02379":{"line":5634,"offset":1006538,"length":185,"previous":"M21-GAP-02378","next":"M21-GAP-02380"},"M21-GAP-02380":{"line":5635,"offset":1006723,"length":185,"previous":"M21-GAP-02379","next":"M21-GAP-02381"},"M21-GAP-02381":{"line":5636,"offset":1006908,"length":185,"previous":"M21-GAP-02380","next":"M21-GAP-02382"},"M21-GAP-02382":{"line":5637,"offset":1007093,"length":185,"previous":"M21-GAP-02381","next":"M21-GAP-02383"},"M21-GAP-02383":{"line":5638,"offset":1007278,"length":185,"previous":"M21-GAP-02382","next":"M21-GAP-02384"},"M21-GAP-02384":{"line":5639,"offset":1007463,"length":185,"previous":"M21-GAP-02383","next":"M21-GAP-02385"},"M21-GAP-02385":{"line":5640,"offset":1007648,"length":184,"previous":"M21-GAP-02384","next":"M21-GAP-02386"},"M21-GAP-02386":{"line":5641,"offset":1007832,"length":185,"previous":"M21-GAP-02385","next":"M21-GAP-02387"},"M21-GAP-02387":{"line":5642,"offset":1008017,"length":185,"previous":"M21-GAP-02386","next":"M21-GAP-02388"},"M21-GAP-02388":{"line":5643,"offset":1008202,"length":185,"previous":"M21-GAP-02387","next":"M21-GAP-02389"},"M21-GAP-02389":{"line":5644,"offset":1008387,"length":185,"previous":"M21-GAP-02388","next":"M21-GAP-02390"},"M21-GAP-02390":{"line":5645,"offset":1008572,"length":185,"previous":"M21-GAP-02389","next":"M21-GAP-02391"},"M21-GAP-02391":{"line":5646,"offset":1008757,"length":185,"previous":"M21-GAP-02390","next":"M21-GAP-02392"},"M21-GAP-02392":{"line":5647,"offset":1008942,"length":185,"previous":"M21-GAP-02391","next":"M21-GAP-02393"},"M21-GAP-02393":{"line":5648,"offset":1009127,"length":185,"previous":"M21-GAP-02392","next":"M21-GAP-02394"},"M21-GAP-02394":{"line":5649,"offset":1009312,"length":185,"previous":"M21-GAP-02393","next":"M21-GAP-02395"},"M21-GAP-02395":{"line":5650,"offset":1009497,"length":185,"previous":"M21-GAP-02394","next":"M21-GAP-02396"},"M21-GAP-02396":{"line":5651,"offset":1009682,"length":184,"previous":"M21-GAP-02395","next":"M21-GAP-02397"},"M21-GAP-02397":{"line":5652,"offset":1009866,"length":185,"previous":"M21-GAP-02396","next":"M21-GAP-02398"},"M21-GAP-02398":{"line":5653,"offset":1010051,"length":185,"previous":"M21-GAP-02397","next":"M21-GAP-02399"},"M21-GAP-02399":{"line":5654,"offset":1010236,"length":185,"previous":"M21-GAP-02398","next":"M21-GAP-02400"},"M21-GAP-02400":{"line":5655,"offset":1010421,"length":185,"previous":"M21-GAP-02399","next":"M21-GAP-02401"},"M21-GAP-02401":{"line":5656,"offset":1010606,"length":185,"previous":"M21-GAP-02400","next":"M21-GAP-02402"},"M21-GAP-02402":{"line":5657,"offset":1010791,"length":185,"previous":"M21-GAP-02401","next":"M21-GAP-02403"},"M21-GAP-02403":{"line":5658,"offset":1010976,"length":185,"previous":"M21-GAP-02402","next":"M21-GAP-02404"},"M21-GAP-02404":{"line":5659,"offset":1011161,"length":185,"previous":"M21-GAP-02403","next":"M21-GAP-02405"},"M21-GAP-02405":{"line":5660,"offset":1011346,"length":185,"previous":"M21-GAP-02404","next":"M21-GAP-02406"},"M21-GAP-02406":{"line":5661,"offset":1011531,"length":185,"previous":"M21-GAP-02405","next":"M21-GAP-02407"},"M21-GAP-02407":{"line":5662,"offset":1011716,"length":184,"previous":"M21-GAP-02406","next":"M21-GAP-02408"},"M21-GAP-02408":{"line":5663,"offset":1011900,"length":185,"previous":"M21-GAP-02407","next":"M21-GAP-02409"},"M21-GAP-02409":{"line":5664,"offset":1012085,"length":185,"previous":"M21-GAP-02408","next":"M21-GAP-02410"},"M21-GAP-02410":{"line":5665,"offset":1012270,"length":185,"previous":"M21-GAP-02409","next":"M21-GAP-02411"},"M21-GAP-02411":{"line":5666,"offset":1012455,"length":185,"previous":"M21-GAP-02410","next":"M21-GAP-02412"},"M21-GAP-02412":{"line":5667,"offset":1012640,"length":185,"previous":"M21-GAP-02411","next":"M21-GAP-02413"},"M21-GAP-02413":{"line":5668,"offset":1012825,"length":185,"previous":"M21-GAP-02412","next":"M21-GAP-02414"},"M21-GAP-02414":{"line":5669,"offset":1013010,"length":185,"previous":"M21-GAP-02413","next":"M21-GAP-02415"},"M21-GAP-02415":{"line":5670,"offset":1013195,"length":185,"previous":"M21-GAP-02414","next":"M21-GAP-02416"},"M21-GAP-02416":{"line":5671,"offset":1013380,"length":184,"previous":"M21-GAP-02415","next":"M21-GAP-02417"},"M21-GAP-02417":{"line":5672,"offset":1013564,"length":191,"previous":"M21-GAP-02416","next":"M21-GAP-02418"},"M21-GAP-02418":{"line":5673,"offset":1013755,"length":191,"previous":"M21-GAP-02417","next":"M21-GAP-02419"},"M21-GAP-02419":{"line":5674,"offset":1013946,"length":192,"previous":"M21-GAP-02418","next":"M21-GAP-02420"},"M21-GAP-02420":{"line":5675,"offset":1014138,"length":192,"previous":"M21-GAP-02419","next":"M21-GAP-02421"},"M21-GAP-02421":{"line":5676,"offset":1014330,"length":192,"previous":"M21-GAP-02420","next":"M21-GAP-02422"},"M21-GAP-02422":{"line":5677,"offset":1014522,"length":192,"previous":"M21-GAP-02421","next":"M21-GAP-02423"},"M21-GAP-02423":{"line":5678,"offset":1014714,"length":191,"previous":"M21-GAP-02422","next":"M21-GAP-02424"},"M21-GAP-02424":{"line":5679,"offset":1014905,"length":191,"previous":"M21-GAP-02423","next":"M21-GAP-02425"},"M21-GAP-02425":{"line":5680,"offset":1015096,"length":191,"previous":"M21-GAP-02424","next":"M21-GAP-02426"},"M21-GAP-02426":{"line":5681,"offset":1015287,"length":191,"previous":"M21-GAP-02425","next":"M21-GAP-02427"},"M21-GAP-02427":{"line":5682,"offset":1015478,"length":191,"previous":"M21-GAP-02426","next":"M21-GAP-02428"},"M21-GAP-02428":{"line":5683,"offset":1015669,"length":191,"previous":"M21-GAP-02427","next":"M21-GAP-02429"},"M21-GAP-02429":{"line":5684,"offset":1015860,"length":191,"previous":"M21-GAP-02428","next":"M21-GAP-02430"},"M21-GAP-02430":{"line":5685,"offset":1016051,"length":191,"previous":"M21-GAP-02429","next":"M21-GAP-02431"},"M21-GAP-02431":{"line":5686,"offset":1016242,"length":187,"previous":"M21-GAP-02430","next":"M21-GAP-02432"},"M21-GAP-02432":{"line":5687,"offset":1016429,"length":187,"previous":"M21-GAP-02431","next":"M21-GAP-02433"},"M21-GAP-02433":{"line":5688,"offset":1016616,"length":188,"previous":"M21-GAP-02432","next":"M21-GAP-02434"},"M21-GAP-02434":{"line":5689,"offset":1016804,"length":188,"previous":"M21-GAP-02433","next":"M21-GAP-02435"},"M21-GAP-02435":{"line":5690,"offset":1016992,"length":188,"previous":"M21-GAP-02434","next":"M21-GAP-02436"},"M21-GAP-02436":{"line":5691,"offset":1017180,"length":188,"previous":"M21-GAP-02435","next":"M21-GAP-02437"},"M21-GAP-02437":{"line":5692,"offset":1017368,"length":188,"previous":"M21-GAP-02436","next":"M21-GAP-02438"},"M21-GAP-02438":{"line":5693,"offset":1017556,"length":188,"previous":"M21-GAP-02437","next":"M21-GAP-02439"},"M21-GAP-02439":{"line":5694,"offset":1017744,"length":188,"previous":"M21-GAP-02438","next":"M21-GAP-02440"},"M21-GAP-02440":{"line":5695,"offset":1017932,"length":188,"previous":"M21-GAP-02439","next":"M21-GAP-02441"},"M21-GAP-02441":{"line":5696,"offset":1018120,"length":188,"previous":"M21-GAP-02440","next":"M21-GAP-02442"},"M21-GAP-02442":{"line":5697,"offset":1018308,"length":188,"previous":"M21-GAP-02441","next":"M21-GAP-02443"},"M21-GAP-02443":{"line":5698,"offset":1018496,"length":187,"previous":"M21-GAP-02442","next":"M21-GAP-02444"},"M21-GAP-02444":{"line":5699,"offset":1018683,"length":187,"previous":"M21-GAP-02443","next":"M21-GAP-02445"},"M21-GAP-02445":{"line":5700,"offset":1018870,"length":187,"previous":"M21-GAP-02444","next":"M21-GAP-02446"},"M21-GAP-02446":{"line":5701,"offset":1019057,"length":187,"previous":"M21-GAP-02445","next":"M21-GAP-02447"},"M21-GAP-02447":{"line":5702,"offset":1019244,"length":187,"previous":"M21-GAP-02446","next":"M21-GAP-02448"},"M21-GAP-02448":{"line":5703,"offset":1019431,"length":187,"previous":"M21-GAP-02447","next":"M21-GAP-02449"},"M21-GAP-02449":{"line":5704,"offset":1019618,"length":187,"previous":"M21-GAP-02448","next":"M21-GAP-02450"},"M21-GAP-02450":{"line":5705,"offset":1019805,"length":187,"previous":"M21-GAP-02449","next":"M21-GAP-02451"},"M21-GAP-02451":{"line":5706,"offset":1019992,"length":186,"previous":"M21-GAP-02450","next":"M21-GAP-02452"},"M21-GAP-02452":{"line":5707,"offset":1020178,"length":181,"previous":"M21-GAP-02451","next":"M21-GAP-02453"},"M21-GAP-02453":{"line":5708,"offset":1020359,"length":181,"previous":"M21-GAP-02452","next":"M21-GAP-02454"},"M21-GAP-02454":{"line":5709,"offset":1020540,"length":182,"previous":"M21-GAP-02453","next":"M21-GAP-02455"},"M21-GAP-02455":{"line":5710,"offset":1020722,"length":182,"previous":"M21-GAP-02454","next":"M21-GAP-02456"},"M21-GAP-02456":{"line":5711,"offset":1020904,"length":182,"previous":"M21-GAP-02455","next":"M21-GAP-02457"},"M21-GAP-02457":{"line":5712,"offset":1021086,"length":182,"previous":"M21-GAP-02456","next":"M21-GAP-02458"},"M21-GAP-02458":{"line":5713,"offset":1021268,"length":181,"previous":"M21-GAP-02457","next":"M21-GAP-02459"},"M21-GAP-02459":{"line":5714,"offset":1021449,"length":181,"previous":"M21-GAP-02458","next":"M21-GAP-02460"},"M21-GAP-02460":{"line":5715,"offset":1021630,"length":181,"previous":"M21-GAP-02459","next":"M21-GAP-02461"},"M21-GAP-02461":{"line":5716,"offset":1021811,"length":181,"previous":"M21-GAP-02460","next":"M21-GAP-02462"},"M21-GAP-02462":{"line":5717,"offset":1021992,"length":181,"previous":"M21-GAP-02461","next":"M21-GAP-02463"},"M21-GAP-02463":{"line":5718,"offset":1022173,"length":181,"previous":"M21-GAP-02462","next":"M21-GAP-02464"},"M21-GAP-02464":{"line":5719,"offset":1022354,"length":181,"previous":"M21-GAP-02463","next":"M21-GAP-02465"},"M21-GAP-02465":{"line":5720,"offset":1022535,"length":181,"previous":"M21-GAP-02464","next":"M21-GAP-02466"},"M21-GAP-02466":{"line":5721,"offset":1022716,"length":173,"previous":"M21-GAP-02465","next":"M21-GAP-02467"},"M21-GAP-02467":{"line":5722,"offset":1022889,"length":173,"previous":"M21-GAP-02466","next":"M21-GAP-02468"},"M21-GAP-02468":{"line":5723,"offset":1023062,"length":174,"previous":"M21-GAP-02467","next":"M21-GAP-02469"},"M21-GAP-02469":{"line":5724,"offset":1023236,"length":174,"previous":"M21-GAP-02468","next":"M21-GAP-02470"},"M21-GAP-02470":{"line":5725,"offset":1023410,"length":174,"previous":"M21-GAP-02469","next":"M21-GAP-02471"},"M21-GAP-02471":{"line":5726,"offset":1023584,"length":174,"previous":"M21-GAP-02470","next":"M21-GAP-02472"},"M21-GAP-02472":{"line":5727,"offset":1023758,"length":174,"previous":"M21-GAP-02471","next":"M21-GAP-02473"},"M21-GAP-02473":{"line":5728,"offset":1023932,"length":174,"previous":"M21-GAP-02472","next":"M21-GAP-02474"},"M21-GAP-02474":{"line":5729,"offset":1024106,"length":174,"previous":"M21-GAP-02473","next":"M21-GAP-02475"},"M21-GAP-02475":{"line":5730,"offset":1024280,"length":174,"previous":"M21-GAP-02474","next":"M21-GAP-02476"},"M21-GAP-02476":{"line":5731,"offset":1024454,"length":174,"previous":"M21-GAP-02475","next":"M21-GAP-02477"},"M21-GAP-02477":{"line":5732,"offset":1024628,"length":174,"previous":"M21-GAP-02476","next":"M21-GAP-02478"},"M21-GAP-02478":{"line":5733,"offset":1024802,"length":173,"previous":"M21-GAP-02477","next":"M21-GAP-02479"},"M21-GAP-02479":{"line":5734,"offset":1024975,"length":174,"previous":"M21-GAP-02478","next":"M21-GAP-02480"},"M21-GAP-02480":{"line":5735,"offset":1025149,"length":174,"previous":"M21-GAP-02479","next":"M21-GAP-02481"},"M21-GAP-02481":{"line":5736,"offset":1025323,"length":174,"previous":"M21-GAP-02480","next":"M21-GAP-02482"},"M21-GAP-02482":{"line":5737,"offset":1025497,"length":174,"previous":"M21-GAP-02481","next":"M21-GAP-02483"},"M21-GAP-02483":{"line":5738,"offset":1025671,"length":174,"previous":"M21-GAP-02482","next":"M21-GAP-02484"},"M21-GAP-02484":{"line":5739,"offset":1025845,"length":174,"previous":"M21-GAP-02483","next":"M21-GAP-02485"},"M21-GAP-02485":{"line":5740,"offset":1026019,"length":173,"previous":"M21-GAP-02484","next":"M21-GAP-02486"},"M21-GAP-02486":{"line":5741,"offset":1026192,"length":173,"previous":"M21-GAP-02485","next":"M21-GAP-02487"},"M21-GAP-02487":{"line":5742,"offset":1026365,"length":173,"previous":"M21-GAP-02486","next":"M21-GAP-02488"},"M21-GAP-02488":{"line":5743,"offset":1026538,"length":173,"previous":"M21-GAP-02487","next":"M21-GAP-02489"},"M21-GAP-02489":{"line":5744,"offset":1026711,"length":173,"previous":"M21-GAP-02488","next":"M21-GAP-02490"},"M21-GAP-02490":{"line":5745,"offset":1026884,"length":173,"previous":"M21-GAP-02489","next":"M21-GAP-02491"},"M21-GAP-02491":{"line":5746,"offset":1027057,"length":173,"previous":"M21-GAP-02490","next":"M21-GAP-02492"},"M21-GAP-02492":{"line":5747,"offset":1027230,"length":180,"previous":"M21-GAP-02491","next":"M21-GAP-02493"},"M21-GAP-02493":{"line":5748,"offset":1027410,"length":180,"previous":"M21-GAP-02492","next":"M21-GAP-02494"},"M21-GAP-02494":{"line":5749,"offset":1027590,"length":181,"previous":"M21-GAP-02493","next":"M21-GAP-02495"},"M21-GAP-02495":{"line":5750,"offset":1027771,"length":181,"previous":"M21-GAP-02494","next":"M21-GAP-02496"},"M21-GAP-02496":{"line":5751,"offset":1027952,"length":181,"previous":"M21-GAP-02495","next":"M21-GAP-02497"},"M21-GAP-02497":{"line":5752,"offset":1028133,"length":181,"previous":"M21-GAP-02496","next":"M21-GAP-02498"},"M21-GAP-02498":{"line":5753,"offset":1028314,"length":181,"previous":"M21-GAP-02497","next":"M21-GAP-02499"},"M21-GAP-02499":{"line":5754,"offset":1028495,"length":181,"previous":"M21-GAP-02498","next":"M21-GAP-02500"},"M21-GAP-02500":{"line":5755,"offset":1028676,"length":180,"previous":"M21-GAP-02499","next":"M21-GAP-02501"},"M21-GAP-02501":{"line":5756,"offset":1028856,"length":180,"previous":"M21-GAP-02500","next":"M21-GAP-02502"},"M21-GAP-02502":{"line":5757,"offset":1029036,"length":180,"previous":"M21-GAP-02501","next":"M21-GAP-02503"},"M21-GAP-02503":{"line":5758,"offset":1029216,"length":180,"previous":"M21-GAP-02502","next":"M21-GAP-02504"},"M21-GAP-02504":{"line":5759,"offset":1029396,"length":180,"previous":"M21-GAP-02503","next":"M21-GAP-02505"},"M21-GAP-02505":{"line":5760,"offset":1029576,"length":180,"previous":"M21-GAP-02504","next":"M21-GAP-02506"},"M21-GAP-02506":{"line":5761,"offset":1029756,"length":180,"previous":"M21-GAP-02505","next":"M21-GAP-02507"},"M21-GAP-02507":{"line":5762,"offset":1029936,"length":180,"previous":"M21-GAP-02506","next":"M21-GAP-02508"},"M21-GAP-02508":{"line":5763,"offset":1030116,"length":186,"previous":"M21-GAP-02507","next":"M21-GAP-02509"},"M21-GAP-02509":{"line":5764,"offset":1030302,"length":186,"previous":"M21-GAP-02508","next":"M21-GAP-02510"},"M21-GAP-02510":{"line":5765,"offset":1030488,"length":187,"previous":"M21-GAP-02509","next":"M21-GAP-02511"},"M21-GAP-02511":{"line":5766,"offset":1030675,"length":187,"previous":"M21-GAP-02510","next":"M21-GAP-02512"},"M21-GAP-02512":{"line":5767,"offset":1030862,"length":187,"previous":"M21-GAP-02511","next":"M21-GAP-02513"},"M21-GAP-02513":{"line":5768,"offset":1031049,"length":187,"previous":"M21-GAP-02512","next":"M21-GAP-02514"},"M21-GAP-02514":{"line":5769,"offset":1031236,"length":187,"previous":"M21-GAP-02513","next":"M21-GAP-02515"},"M21-GAP-02515":{"line":5770,"offset":1031423,"length":187,"previous":"M21-GAP-02514","next":"M21-GAP-02516"},"M21-GAP-02516":{"line":5771,"offset":1031610,"length":187,"previous":"M21-GAP-02515","next":"M21-GAP-02517"},"M21-GAP-02517":{"line":5772,"offset":1031797,"length":187,"previous":"M21-GAP-02516","next":"M21-GAP-02518"},"M21-GAP-02518":{"line":5773,"offset":1031984,"length":187,"previous":"M21-GAP-02517","next":"M21-GAP-02519"},"M21-GAP-02519":{"line":5774,"offset":1032171,"length":187,"previous":"M21-GAP-02518","next":"M21-GAP-02520"},"M21-GAP-02520":{"line":5775,"offset":1032358,"length":186,"previous":"M21-GAP-02519","next":"M21-GAP-02521"},"M21-GAP-02521":{"line":5776,"offset":1032544,"length":187,"previous":"M21-GAP-02520","next":"M21-GAP-02522"},"M21-GAP-02522":{"line":5777,"offset":1032731,"length":187,"previous":"M21-GAP-02521","next":"M21-GAP-02523"},"M21-GAP-02523":{"line":5778,"offset":1032918,"length":187,"previous":"M21-GAP-02522","next":"M21-GAP-02524"},"M21-GAP-02524":{"line":5779,"offset":1033105,"length":187,"previous":"M21-GAP-02523","next":"M21-GAP-02525"},"M21-GAP-02525":{"line":5780,"offset":1033292,"length":187,"previous":"M21-GAP-02524","next":"M21-GAP-02526"},"M21-GAP-02526":{"line":5781,"offset":1033479,"length":186,"previous":"M21-GAP-02525","next":"M21-GAP-02527"},"M21-GAP-02527":{"line":5782,"offset":1033665,"length":186,"previous":"M21-GAP-02526","next":"M21-GAP-02528"},"M21-GAP-02528":{"line":5783,"offset":1033851,"length":186,"previous":"M21-GAP-02527","next":"M21-GAP-02529"},"M21-GAP-02529":{"line":5784,"offset":1034037,"length":186,"previous":"M21-GAP-02528","next":"M21-GAP-02530"},"M21-GAP-02530":{"line":5785,"offset":1034223,"length":186,"previous":"M21-GAP-02529","next":"M21-GAP-02531"},"M21-GAP-02531":{"line":5786,"offset":1034409,"length":186,"previous":"M21-GAP-02530","next":"M21-GAP-02532"},"M21-GAP-02532":{"line":5787,"offset":1034595,"length":186,"previous":"M21-GAP-02531","next":"M21-GAP-02533"},"M21-GAP-02533":{"line":5788,"offset":1034781,"length":173,"previous":"M21-GAP-02532","next":"M21-GAP-02534"},"M21-GAP-02534":{"line":5789,"offset":1034954,"length":173,"previous":"M21-GAP-02533","next":"M21-GAP-02535"},"M21-GAP-02535":{"line":5790,"offset":1035127,"length":174,"previous":"M21-GAP-02534","next":"M21-GAP-02536"},"M21-GAP-02536":{"line":5791,"offset":1035301,"length":174,"previous":"M21-GAP-02535","next":"M21-GAP-02537"},"M21-GAP-02537":{"line":5792,"offset":1035475,"length":174,"previous":"M21-GAP-02536","next":"M21-GAP-02538"},"M21-GAP-02538":{"line":5793,"offset":1035649,"length":174,"previous":"M21-GAP-02537","next":"M21-GAP-02539"},"M21-GAP-02539":{"line":5794,"offset":1035823,"length":174,"previous":"M21-GAP-02538","next":"M21-GAP-02540"},"M21-GAP-02540":{"line":5795,"offset":1035997,"length":174,"previous":"M21-GAP-02539","next":"M21-GAP-02541"},"M21-GAP-02541":{"line":5796,"offset":1036171,"length":174,"previous":"M21-GAP-02540","next":"M21-GAP-02542"},"M21-GAP-02542":{"line":5797,"offset":1036345,"length":174,"previous":"M21-GAP-02541","next":"M21-GAP-02543"},"M21-GAP-02543":{"line":5798,"offset":1036519,"length":174,"previous":"M21-GAP-02542","next":"M21-GAP-02544"},"M21-GAP-02544":{"line":5799,"offset":1036693,"length":174,"previous":"M21-GAP-02543","next":"M21-GAP-02545"},"M21-GAP-02545":{"line":5800,"offset":1036867,"length":173,"previous":"M21-GAP-02544","next":"M21-GAP-02546"},"M21-GAP-02546":{"line":5801,"offset":1037040,"length":174,"previous":"M21-GAP-02545","next":"M21-GAP-02547"},"M21-GAP-02547":{"line":5802,"offset":1037214,"length":174,"previous":"M21-GAP-02546","next":"M21-GAP-02548"},"M21-GAP-02548":{"line":5803,"offset":1037388,"length":174,"previous":"M21-GAP-02547","next":"M21-GAP-02549"},"M21-GAP-02549":{"line":5804,"offset":1037562,"length":174,"previous":"M21-GAP-02548","next":"M21-GAP-02550"},"M21-GAP-02550":{"line":5805,"offset":1037736,"length":174,"previous":"M21-GAP-02549","next":"M21-GAP-02551"},"M21-GAP-02551":{"line":5806,"offset":1037910,"length":174,"previous":"M21-GAP-02550","next":"M21-GAP-02552"},"M21-GAP-02552":{"line":5807,"offset":1038084,"length":174,"previous":"M21-GAP-02551","next":"M21-GAP-02553"},"M21-GAP-02553":{"line":5808,"offset":1038258,"length":174,"previous":"M21-GAP-02552","next":"M21-GAP-02554"},"M21-GAP-02554":{"line":5809,"offset":1038432,"length":174,"previous":"M21-GAP-02553","next":"M21-GAP-02555"},"M21-GAP-02555":{"line":5810,"offset":1038606,"length":174,"previous":"M21-GAP-02554","next":"M21-GAP-02556"},"M21-GAP-02556":{"line":5811,"offset":1038780,"length":173,"previous":"M21-GAP-02555","next":"M21-GAP-02557"},"M21-GAP-02557":{"line":5812,"offset":1038953,"length":174,"previous":"M21-GAP-02556","next":"M21-GAP-02558"},"M21-GAP-02558":{"line":5813,"offset":1039127,"length":174,"previous":"M21-GAP-02557","next":"M21-GAP-02559"},"M21-GAP-02559":{"line":5814,"offset":1039301,"length":174,"previous":"M21-GAP-02558","next":"M21-GAP-02560"},"M21-GAP-02560":{"line":5815,"offset":1039475,"length":174,"previous":"M21-GAP-02559","next":"M21-GAP-02561"},"M21-GAP-02561":{"line":5816,"offset":1039649,"length":174,"previous":"M21-GAP-02560","next":"M21-GAP-02562"},"M21-GAP-02562":{"line":5817,"offset":1039823,"length":174,"previous":"M21-GAP-02561","next":"M21-GAP-02563"},"M21-GAP-02563":{"line":5818,"offset":1039997,"length":174,"previous":"M21-GAP-02562","next":"M21-GAP-02564"},"M21-GAP-02564":{"line":5819,"offset":1040171,"length":174,"previous":"M21-GAP-02563","next":"M21-GAP-02565"},"M21-GAP-02565":{"line":5820,"offset":1040345,"length":174,"previous":"M21-GAP-02564","next":"M21-GAP-02566"},"M21-GAP-02566":{"line":5821,"offset":1040519,"length":174,"previous":"M21-GAP-02565","next":"M21-GAP-02567"},"M21-GAP-02567":{"line":5822,"offset":1040693,"length":173,"previous":"M21-GAP-02566","next":"M21-GAP-02568"},"M21-GAP-02568":{"line":5823,"offset":1040866,"length":174,"previous":"M21-GAP-02567","next":"M21-GAP-02569"},"M21-GAP-02569":{"line":5824,"offset":1041040,"length":174,"previous":"M21-GAP-02568","next":"M21-GAP-02570"},"M21-GAP-02570":{"line":5825,"offset":1041214,"length":174,"previous":"M21-GAP-02569","next":"M21-GAP-02571"},"M21-GAP-02571":{"line":5826,"offset":1041388,"length":174,"previous":"M21-GAP-02570","next":"M21-GAP-02572"},"M21-GAP-02572":{"line":5827,"offset":1041562,"length":174,"previous":"M21-GAP-02571","next":"M21-GAP-02573"},"M21-GAP-02573":{"line":5828,"offset":1041736,"length":174,"previous":"M21-GAP-02572","next":"M21-GAP-02574"},"M21-GAP-02574":{"line":5829,"offset":1041910,"length":174,"previous":"M21-GAP-02573","next":"M21-GAP-02575"},"M21-GAP-02575":{"line":5830,"offset":1042084,"length":174,"previous":"M21-GAP-02574","next":"M21-GAP-02576"},"M21-GAP-02576":{"line":5831,"offset":1042258,"length":174,"previous":"M21-GAP-02575","next":"M21-GAP-02577"},"M21-GAP-02577":{"line":5832,"offset":1042432,"length":174,"previous":"M21-GAP-02576","next":"M21-GAP-02578"},"M21-GAP-02578":{"line":5833,"offset":1042606,"length":173,"previous":"M21-GAP-02577","next":"M21-GAP-02579"},"M21-GAP-02579":{"line":5834,"offset":1042779,"length":174,"previous":"M21-GAP-02578","next":"M21-GAP-02580"},"M21-GAP-02580":{"line":5835,"offset":1042953,"length":174,"previous":"M21-GAP-02579","next":"M21-GAP-02581"},"M21-GAP-02581":{"line":5836,"offset":1043127,"length":174,"previous":"M21-GAP-02580","next":"M21-GAP-02582"},"M21-GAP-02582":{"line":5837,"offset":1043301,"length":174,"previous":"M21-GAP-02581","next":"M21-GAP-02583"},"M21-GAP-02583":{"line":5838,"offset":1043475,"length":174,"previous":"M21-GAP-02582","next":"M21-GAP-02584"},"M21-GAP-02584":{"line":5839,"offset":1043649,"length":174,"previous":"M21-GAP-02583","next":"M21-GAP-02585"},"M21-GAP-02585":{"line":5840,"offset":1043823,"length":174,"previous":"M21-GAP-02584","next":"M21-GAP-02586"},"M21-GAP-02586":{"line":5841,"offset":1043997,"length":174,"previous":"M21-GAP-02585","next":"M21-GAP-02587"},"M21-GAP-02587":{"line":5842,"offset":1044171,"length":174,"previous":"M21-GAP-02586","next":"M21-GAP-02588"},"M21-GAP-02588":{"line":5843,"offset":1044345,"length":174,"previous":"M21-GAP-02587","next":"M21-GAP-02589"},"M21-GAP-02589":{"line":5844,"offset":1044519,"length":173,"previous":"M21-GAP-02588","next":"M21-GAP-02590"},"M21-GAP-02590":{"line":5845,"offset":1044692,"length":174,"previous":"M21-GAP-02589","next":"M21-GAP-02591"},"M21-GAP-02591":{"line":5846,"offset":1044866,"length":174,"previous":"M21-GAP-02590","next":"M21-GAP-02592"},"M21-GAP-02592":{"line":5847,"offset":1045040,"length":174,"previous":"M21-GAP-02591","next":"M21-GAP-02593"},"M21-GAP-02593":{"line":5848,"offset":1045214,"length":174,"previous":"M21-GAP-02592","next":"M21-GAP-02594"},"M21-GAP-02594":{"line":5849,"offset":1045388,"length":174,"previous":"M21-GAP-02593","next":"M21-GAP-02595"},"M21-GAP-02595":{"line":5850,"offset":1045562,"length":174,"previous":"M21-GAP-02594","next":"M21-GAP-02596"},"M21-GAP-02596":{"line":5851,"offset":1045736,"length":174,"previous":"M21-GAP-02595","next":"M21-GAP-02597"},"M21-GAP-02597":{"line":5852,"offset":1045910,"length":173,"previous":"M21-GAP-02596","next":"M21-GAP-02598"},"M21-GAP-02598":{"line":5853,"offset":1046083,"length":173,"previous":"M21-GAP-02597","next":"M21-GAP-02599"},"M21-GAP-02599":{"line":5854,"offset":1046256,"length":173,"previous":"M21-GAP-02598","next":"M21-GAP-02600"},"M21-GAP-02600":{"line":5855,"offset":1046429,"length":195,"previous":"M21-GAP-02599","next":"M21-GAP-02601"},"M21-GAP-02601":{"line":5856,"offset":1046624,"length":195,"previous":"M21-GAP-02600","next":"M21-GAP-02602"},"M21-GAP-02602":{"line":5857,"offset":1046819,"length":198,"previous":"M21-GAP-02601","next":"M21-GAP-02603"},"M21-GAP-02603":{"line":5858,"offset":1047017,"length":198,"previous":"M21-GAP-02602","next":"M21-GAP-02604"},"M21-GAP-02604":{"line":5859,"offset":1047215,"length":198,"previous":"M21-GAP-02603","next":"M21-GAP-02605"},"M21-GAP-02605":{"line":5860,"offset":1047413,"length":198,"previous":"M21-GAP-02604","next":"M21-GAP-02606"},"M21-GAP-02606":{"line":5861,"offset":1047611,"length":198,"previous":"M21-GAP-02605","next":"M21-GAP-02607"},"M21-GAP-02607":{"line":5862,"offset":1047809,"length":198,"previous":"M21-GAP-02606","next":"M21-GAP-02608"},"M21-GAP-02608":{"line":5863,"offset":1048007,"length":214,"previous":"M21-GAP-02607","next":"M21-GAP-02609"},"M21-GAP-02609":{"line":5864,"offset":1048221,"length":214,"previous":"M21-GAP-02608","next":"M21-GAP-02610"},"M21-GAP-02610":{"line":5865,"offset":1048435,"length":214,"previous":"M21-GAP-02609","next":"M21-GAP-02611"},"M21-GAP-02611":{"line":5866,"offset":1048649,"length":214,"previous":"M21-GAP-02610","next":"M21-GAP-02612"},"M21-GAP-02612":{"line":5867,"offset":1048863,"length":214,"previous":"M21-GAP-02611","next":"M21-GAP-02613"},"M21-GAP-02613":{"line":5868,"offset":1049077,"length":214,"previous":"M21-GAP-02612","next":"M21-GAP-02614"},"M21-GAP-02614":{"line":5869,"offset":1049291,"length":203,"previous":"M21-GAP-02613","next":"M21-GAP-02615"},"M21-GAP-02615":{"line":5870,"offset":1049494,"length":203,"previous":"M21-GAP-02614","next":"M21-GAP-02616"},"M21-GAP-02616":{"line":5871,"offset":1049697,"length":203,"previous":"M21-GAP-02615","next":"M21-GAP-02617"},"M21-GAP-02617":{"line":5872,"offset":1049900,"length":203,"previous":"M21-GAP-02616","next":"M21-GAP-02618"},"M21-GAP-02618":{"line":5873,"offset":1050103,"length":203,"previous":"M21-GAP-02617","next":"M21-GAP-02619"},"M21-GAP-02619":{"line":5874,"offset":1050306,"length":203,"previous":"M21-GAP-02618","next":"M21-GAP-02620"},"M21-GAP-02620":{"line":5875,"offset":1050509,"length":217,"previous":"M21-GAP-02619","next":"M21-GAP-02621"},"M21-GAP-02621":{"line":5876,"offset":1050726,"length":217,"previous":"M21-GAP-02620","next":"M21-GAP-02622"},"M21-GAP-02622":{"line":5877,"offset":1050943,"length":217,"previous":"M21-GAP-02621","next":"M21-GAP-02623"},"M21-GAP-02623":{"line":5878,"offset":1051160,"length":206,"previous":"M21-GAP-02622","next":"M21-GAP-02624"},"M21-GAP-02624":{"line":5879,"offset":1051366,"length":206,"previous":"M21-GAP-02623","next":"M21-GAP-02625"},"M21-GAP-02625":{"line":5880,"offset":1051572,"length":206,"previous":"M21-GAP-02624","next":"M21-GAP-02626"},"M21-GAP-02626":{"line":5881,"offset":1051778,"length":216,"previous":"M21-GAP-02625","next":"M21-GAP-02627"},"M21-GAP-02627":{"line":5882,"offset":1051994,"length":216,"previous":"M21-GAP-02626","next":"M21-GAP-02628"},"M21-GAP-02628":{"line":5883,"offset":1052210,"length":216,"previous":"M21-GAP-02627","next":"M21-GAP-02629"},"M21-GAP-02629":{"line":5884,"offset":1052426,"length":205,"previous":"M21-GAP-02628","next":"M21-GAP-02630"},"M21-GAP-02630":{"line":5885,"offset":1052631,"length":205,"previous":"M21-GAP-02629","next":"M21-GAP-02631"},"M21-GAP-02631":{"line":5886,"offset":1052836,"length":205,"previous":"M21-GAP-02630","next":"M21-GAP-02632"},"M21-GAP-02632":{"line":5887,"offset":1053041,"length":197,"previous":"M21-GAP-02631","next":"M21-GAP-02633"},"M21-GAP-02633":{"line":5888,"offset":1053238,"length":197,"previous":"M21-GAP-02632","next":"M21-GAP-02634"},"M21-GAP-02634":{"line":5889,"offset":1053435,"length":186,"previous":"M21-GAP-02633","next":"M21-GAP-02635"},"M21-GAP-02635":{"line":5890,"offset":1053621,"length":186,"previous":"M21-GAP-02634","next":"M21-GAP-02636"},"M21-GAP-02636":{"line":5891,"offset":1053807,"length":187,"previous":"M21-GAP-02635","next":"M21-GAP-02637"},"M21-GAP-02637":{"line":5892,"offset":1053994,"length":187,"previous":"M21-GAP-02636","next":"M21-GAP-02638"},"M21-GAP-02638":{"line":5893,"offset":1054181,"length":187,"previous":"M21-GAP-02637","next":"M21-GAP-02639"},"M21-GAP-02639":{"line":5894,"offset":1054368,"length":187,"previous":"M21-GAP-02638","next":"M21-GAP-02640"},"M21-GAP-02640":{"line":5895,"offset":1054555,"length":187,"previous":"M21-GAP-02639","next":"M21-GAP-02641"},"M21-GAP-02641":{"line":5896,"offset":1054742,"length":187,"previous":"M21-GAP-02640","next":"M21-GAP-02642"},"M21-GAP-02642":{"line":5897,"offset":1054929,"length":187,"previous":"M21-GAP-02641","next":"M21-GAP-02643"},"M21-GAP-02643":{"line":5898,"offset":1055116,"length":187,"previous":"M21-GAP-02642","next":"M21-GAP-02644"},"M21-GAP-02644":{"line":5899,"offset":1055303,"length":187,"previous":"M21-GAP-02643","next":"M21-GAP-02645"},"M21-GAP-02645":{"line":5900,"offset":1055490,"length":187,"previous":"M21-GAP-02644","next":"M21-GAP-02646"},"M21-GAP-02646":{"line":5901,"offset":1055677,"length":186,"previous":"M21-GAP-02645","next":"M21-GAP-02647"},"M21-GAP-02647":{"line":5902,"offset":1055863,"length":187,"previous":"M21-GAP-02646","next":"M21-GAP-02648"},"M21-GAP-02648":{"line":5903,"offset":1056050,"length":187,"previous":"M21-GAP-02647","next":"M21-GAP-02649"},"M21-GAP-02649":{"line":5904,"offset":1056237,"length":187,"previous":"M21-GAP-02648","next":"M21-GAP-02650"},"M21-GAP-02650":{"line":5905,"offset":1056424,"length":187,"previous":"M21-GAP-02649","next":"M21-GAP-02651"},"M21-GAP-02651":{"line":5906,"offset":1056611,"length":187,"previous":"M21-GAP-02650","next":"M21-GAP-02652"},"M21-GAP-02652":{"line":5907,"offset":1056798,"length":187,"previous":"M21-GAP-02651","next":"M21-GAP-02653"},"M21-GAP-02653":{"line":5908,"offset":1056985,"length":187,"previous":"M21-GAP-02652","next":"M21-GAP-02654"},"M21-GAP-02654":{"line":5909,"offset":1057172,"length":187,"previous":"M21-GAP-02653","next":"M21-GAP-02655"},"M21-GAP-02655":{"line":5910,"offset":1057359,"length":187,"previous":"M21-GAP-02654","next":"M21-GAP-02656"},"M21-GAP-02656":{"line":5911,"offset":1057546,"length":187,"previous":"M21-GAP-02655","next":"M21-GAP-02657"},"M21-GAP-02657":{"line":5912,"offset":1057733,"length":186,"previous":"M21-GAP-02656","next":"M21-GAP-02658"},"M21-GAP-02658":{"line":5913,"offset":1057919,"length":187,"previous":"M21-GAP-02657","next":"M21-GAP-02659"},"M21-GAP-02659":{"line":5914,"offset":1058106,"length":187,"previous":"M21-GAP-02658","next":"M21-GAP-02660"},"M21-GAP-02660":{"line":5915,"offset":1058293,"length":187,"previous":"M21-GAP-02659","next":"M21-GAP-02661"},"M21-GAP-02661":{"line":5916,"offset":1058480,"length":187,"previous":"M21-GAP-02660","next":"M21-GAP-02662"},"M21-GAP-02662":{"line":5917,"offset":1058667,"length":187,"previous":"M21-GAP-02661","next":"M21-GAP-02663"},"M21-GAP-02663":{"line":5918,"offset":1058854,"length":187,"previous":"M21-GAP-02662","next":"M21-GAP-02664"},"M21-GAP-02664":{"line":5919,"offset":1059041,"length":187,"previous":"M21-GAP-02663","next":"M21-GAP-02665"},"M21-GAP-02665":{"line":5920,"offset":1059228,"length":187,"previous":"M21-GAP-02664","next":"M21-GAP-02666"},"M21-GAP-02666":{"line":5921,"offset":1059415,"length":187,"previous":"M21-GAP-02665","next":"M21-GAP-02667"},"M21-GAP-02667":{"line":5922,"offset":1059602,"length":187,"previous":"M21-GAP-02666","next":"M21-GAP-02668"},"M21-GAP-02668":{"line":5923,"offset":1059789,"length":186,"previous":"M21-GAP-02667","next":"M21-GAP-02669"},"M21-GAP-02669":{"line":5924,"offset":1059975,"length":187,"previous":"M21-GAP-02668","next":"M21-GAP-02670"},"M21-GAP-02670":{"line":5925,"offset":1060162,"length":187,"previous":"M21-GAP-02669","next":"M21-GAP-02671"},"M21-GAP-02671":{"line":5926,"offset":1060349,"length":187,"previous":"M21-GAP-02670","next":"M21-GAP-02672"},"M21-GAP-02672":{"line":5927,"offset":1060536,"length":187,"previous":"M21-GAP-02671","next":"M21-GAP-02673"},"M21-GAP-02673":{"line":5928,"offset":1060723,"length":187,"previous":"M21-GAP-02672","next":"M21-GAP-02674"},"M21-GAP-02674":{"line":5929,"offset":1060910,"length":187,"previous":"M21-GAP-02673","next":"M21-GAP-02675"},"M21-GAP-02675":{"line":5930,"offset":1061097,"length":187,"previous":"M21-GAP-02674","next":"M21-GAP-02676"},"M21-GAP-02676":{"line":5931,"offset":1061284,"length":187,"previous":"M21-GAP-02675","next":"M21-GAP-02677"},"M21-GAP-02677":{"line":5932,"offset":1061471,"length":187,"previous":"M21-GAP-02676","next":"M21-GAP-02678"},"M21-GAP-02678":{"line":5933,"offset":1061658,"length":187,"previous":"M21-GAP-02677","next":"M21-GAP-02679"},"M21-GAP-02679":{"line":5934,"offset":1061845,"length":186,"previous":"M21-GAP-02678","next":"M21-GAP-02680"},"M21-GAP-02680":{"line":5935,"offset":1062031,"length":187,"previous":"M21-GAP-02679","next":"M21-GAP-02681"},"M21-GAP-02681":{"line":5936,"offset":1062218,"length":187,"previous":"M21-GAP-02680","next":"M21-GAP-02682"},"M21-GAP-02682":{"line":5937,"offset":1062405,"length":187,"previous":"M21-GAP-02681","next":"M21-GAP-02683"},"M21-GAP-02683":{"line":5938,"offset":1062592,"length":187,"previous":"M21-GAP-02682","next":"M21-GAP-02684"},"M21-GAP-02684":{"line":5939,"offset":1062779,"length":187,"previous":"M21-GAP-02683","next":"M21-GAP-02685"},"M21-GAP-02685":{"line":5940,"offset":1062966,"length":187,"previous":"M21-GAP-02684","next":"M21-GAP-02686"},"M21-GAP-02686":{"line":5941,"offset":1063153,"length":187,"previous":"M21-GAP-02685","next":"M21-GAP-02687"},"M21-GAP-02687":{"line":5942,"offset":1063340,"length":187,"previous":"M21-GAP-02686","next":"M21-GAP-02688"},"M21-GAP-02688":{"line":5943,"offset":1063527,"length":187,"previous":"M21-GAP-02687","next":"M21-GAP-02689"},"M21-GAP-02689":{"line":5944,"offset":1063714,"length":187,"previous":"M21-GAP-02688","next":"M21-GAP-02690"},"M21-GAP-02690":{"line":5945,"offset":1063901,"length":186,"previous":"M21-GAP-02689","next":"M21-GAP-02691"},"M21-GAP-02691":{"line":5946,"offset":1064087,"length":187,"previous":"M21-GAP-02690","next":"M21-GAP-02692"},"M21-GAP-02692":{"line":5947,"offset":1064274,"length":187,"previous":"M21-GAP-02691","next":"M21-GAP-02693"},"M21-GAP-02693":{"line":5948,"offset":1064461,"length":187,"previous":"M21-GAP-02692","next":"M21-GAP-02694"},"M21-GAP-02694":{"line":5949,"offset":1064648,"length":187,"previous":"M21-GAP-02693","next":"M21-GAP-02695"},"M21-GAP-02695":{"line":5950,"offset":1064835,"length":187,"previous":"M21-GAP-02694","next":"M21-GAP-02696"},"M21-GAP-02696":{"line":5951,"offset":1065022,"length":187,"previous":"M21-GAP-02695","next":"M21-GAP-02697"},"M21-GAP-02697":{"line":5952,"offset":1065209,"length":187,"previous":"M21-GAP-02696","next":"M21-GAP-02698"},"M21-GAP-02698":{"line":5953,"offset":1065396,"length":187,"previous":"M21-GAP-02697","next":"M21-GAP-02699"},"M21-GAP-02699":{"line":5954,"offset":1065583,"length":187,"previous":"M21-GAP-02698","next":"M21-GAP-02700"},"M21-GAP-02700":{"line":5955,"offset":1065770,"length":187,"previous":"M21-GAP-02699","next":"M21-GAP-02701"},"M21-GAP-02701":{"line":5956,"offset":1065957,"length":186,"previous":"M21-GAP-02700","next":"M21-GAP-02702"},"M21-GAP-02702":{"line":5957,"offset":1066143,"length":187,"previous":"M21-GAP-02701","next":"M21-GAP-02703"},"M21-GAP-02703":{"line":5958,"offset":1066330,"length":187,"previous":"M21-GAP-02702","next":"M21-GAP-02704"},"M21-GAP-02704":{"line":5959,"offset":1066517,"length":187,"previous":"M21-GAP-02703","next":"M21-GAP-02705"},"M21-GAP-02705":{"line":5960,"offset":1066704,"length":187,"previous":"M21-GAP-02704","next":"M21-GAP-02706"},"M21-GAP-02706":{"line":5961,"offset":1066891,"length":187,"previous":"M21-GAP-02705","next":"M21-GAP-02707"},"M21-GAP-02707":{"line":5962,"offset":1067078,"length":187,"previous":"M21-GAP-02706","next":"M21-GAP-02708"},"M21-GAP-02708":{"line":5963,"offset":1067265,"length":187,"previous":"M21-GAP-02707","next":"M21-GAP-02709"},"M21-GAP-02709":{"line":5964,"offset":1067452,"length":187,"previous":"M21-GAP-02708","next":"M21-GAP-02710"},"M21-GAP-02710":{"line":5965,"offset":1067639,"length":187,"previous":"M21-GAP-02709","next":"M21-GAP-02711"},"M21-GAP-02711":{"line":5966,"offset":1067826,"length":187,"previous":"M21-GAP-02710","next":"M21-GAP-02712"},"M21-GAP-02712":{"line":5967,"offset":1068013,"length":186,"previous":"M21-GAP-02711","next":"M21-GAP-02713"},"M21-GAP-02713":{"line":5968,"offset":1068199,"length":187,"previous":"M21-GAP-02712","next":"M21-GAP-02714"},"M21-GAP-02714":{"line":5969,"offset":1068386,"length":187,"previous":"M21-GAP-02713","next":"M21-GAP-02715"},"M21-GAP-02715":{"line":5970,"offset":1068573,"length":187,"previous":"M21-GAP-02714","next":"M21-GAP-02716"},"M21-GAP-02716":{"line":5971,"offset":1068760,"length":187,"previous":"M21-GAP-02715","next":"M21-GAP-02717"},"M21-GAP-02717":{"line":5972,"offset":1068947,"length":187,"previous":"M21-GAP-02716","next":"M21-GAP-02718"},"M21-GAP-02718":{"line":5973,"offset":1069134,"length":187,"previous":"M21-GAP-02717","next":"M21-GAP-02719"},"M21-GAP-02719":{"line":5974,"offset":1069321,"length":187,"previous":"M21-GAP-02718","next":"M21-GAP-02720"},"M21-GAP-02720":{"line":5975,"offset":1069508,"length":187,"previous":"M21-GAP-02719","next":"M21-GAP-02721"},"M21-GAP-02721":{"line":5976,"offset":1069695,"length":187,"previous":"M21-GAP-02720","next":"M21-GAP-02722"},"M21-GAP-02722":{"line":5977,"offset":1069882,"length":187,"previous":"M21-GAP-02721","next":"M21-GAP-02723"},"M21-GAP-02723":{"line":5978,"offset":1070069,"length":186,"previous":"M21-GAP-02722","next":"M21-GAP-02724"},"M21-GAP-02724":{"line":5979,"offset":1070255,"length":187,"previous":"M21-GAP-02723","next":"M21-GAP-02725"},"M21-GAP-02725":{"line":5980,"offset":1070442,"length":187,"previous":"M21-GAP-02724","next":"M21-GAP-02726"},"M21-GAP-02726":{"line":5981,"offset":1070629,"length":187,"previous":"M21-GAP-02725","next":"M21-GAP-02727"},"M21-GAP-02727":{"line":5982,"offset":1070816,"length":187,"previous":"M21-GAP-02726","next":"M21-GAP-02728"},"M21-GAP-02728":{"line":5983,"offset":1071003,"length":187,"previous":"M21-GAP-02727","next":"M21-GAP-02729"},"M21-GAP-02729":{"line":5984,"offset":1071190,"length":177,"previous":"M21-GAP-02728","next":"M21-GAP-02730"},"M21-GAP-02730":{"line":5985,"offset":1071367,"length":177,"previous":"M21-GAP-02729","next":"M21-GAP-02731"},"M21-GAP-02731":{"line":5986,"offset":1071544,"length":178,"previous":"M21-GAP-02730","next":"M21-GAP-02732"},"M21-GAP-02732":{"line":5987,"offset":1071722,"length":178,"previous":"M21-GAP-02731","next":"M21-GAP-02733"},"M21-GAP-02733":{"line":5988,"offset":1071900,"length":177,"previous":"M21-GAP-02732","next":"M21-GAP-02734"},"M21-GAP-02734":{"line":5989,"offset":1072077,"length":177,"previous":"M21-GAP-02733","next":"M21-GAP-02735"},"M21-GAP-02735":{"line":5990,"offset":1072254,"length":177,"previous":"M21-GAP-02734","next":"M21-GAP-02736"},"M21-GAP-02736":{"line":5991,"offset":1072431,"length":177,"previous":"M21-GAP-02735","next":"M21-GAP-02737"},"M21-GAP-02737":{"line":5992,"offset":1072608,"length":177,"previous":"M21-GAP-02736","next":"M21-GAP-02738"},"M21-GAP-02738":{"line":5993,"offset":1072785,"length":177,"previous":"M21-GAP-02737","next":"M21-GAP-02739"},"M21-GAP-02739":{"line":5994,"offset":1072962,"length":177,"previous":"M21-GAP-02738","next":"M21-GAP-02740"},"M21-GAP-02740":{"line":5995,"offset":1073139,"length":177,"previous":"M21-GAP-02739","next":"M21-GAP-02741"},"M21-GAP-02741":{"line":5996,"offset":1073316,"length":192,"previous":"M21-GAP-02740","next":"M21-GAP-02742"},"M21-GAP-02742":{"line":5997,"offset":1073508,"length":192,"previous":"M21-GAP-02741","next":"M21-GAP-02743"},"M21-GAP-02743":{"line":5998,"offset":1073700,"length":192,"previous":"M21-GAP-02742","next":"M21-GAP-02744"},"M21-GAP-02744":{"line":5999,"offset":1073892,"length":192,"previous":"M21-GAP-02743","next":"M21-GAP-02745"},"M21-GAP-02745":{"line":6000,"offset":1074084,"length":192,"previous":"M21-GAP-02744","next":"M21-GAP-02746"},"M21-GAP-02746":{"line":6001,"offset":1074276,"length":185,"previous":"M21-GAP-02745","next":"M21-GAP-02747"},"M21-GAP-02747":{"line":6002,"offset":1074461,"length":185,"previous":"M21-GAP-02746","next":"M21-GAP-02748"},"M21-GAP-02748":{"line":6003,"offset":1074646,"length":185,"previous":"M21-GAP-02747","next":"M21-GAP-02749"},"M21-GAP-02749":{"line":6004,"offset":1074831,"length":185,"previous":"M21-GAP-02748","next":"M21-GAP-02750"},"M21-GAP-02750":{"line":6005,"offset":1075016,"length":185,"previous":"M21-GAP-02749","next":"M21-GAP-02751"},"M21-GAP-02751":{"line":6006,"offset":1075201,"length":185,"previous":"M21-GAP-02750","next":"M21-GAP-02752"},"M21-GAP-02752":{"line":6007,"offset":1075386,"length":185,"previous":"M21-GAP-02751","next":"M21-GAP-02753"},"M21-GAP-02753":{"line":6008,"offset":1075571,"length":185,"previous":"M21-GAP-02752","next":"M21-GAP-02754"},"M21-GAP-02754":{"line":6009,"offset":1075756,"length":185,"previous":"M21-GAP-02753","next":"M21-GAP-02755"},"M21-GAP-02755":{"line":6010,"offset":1075941,"length":185,"previous":"M21-GAP-02754","next":"M21-GAP-02756"},"M21-GAP-02756":{"line":6011,"offset":1076126,"length":185,"previous":"M21-GAP-02755","next":"M21-GAP-02757"},"M21-GAP-02757":{"line":6012,"offset":1076311,"length":185,"previous":"M21-GAP-02756","next":"M21-GAP-02758"},"M21-GAP-02758":{"line":6013,"offset":1076496,"length":185,"previous":"M21-GAP-02757","next":"M21-GAP-02759"},"M21-GAP-02759":{"line":6014,"offset":1076681,"length":177,"previous":"M21-GAP-02758","next":"M21-GAP-02760"},"M21-GAP-02760":{"line":6015,"offset":1076858,"length":177,"previous":"M21-GAP-02759","next":"M21-GAP-02761"},"M21-GAP-02761":{"line":6016,"offset":1077035,"length":178,"previous":"M21-GAP-02760","next":"M21-GAP-02762"},"M21-GAP-02762":{"line":6017,"offset":1077213,"length":178,"previous":"M21-GAP-02761","next":"M21-GAP-02763"},"M21-GAP-02763":{"line":6018,"offset":1077391,"length":178,"previous":"M21-GAP-02762","next":"M21-GAP-02764"},"M21-GAP-02764":{"line":6019,"offset":1077569,"length":178,"previous":"M21-GAP-02763","next":"M21-GAP-02765"},"M21-GAP-02765":{"line":6020,"offset":1077747,"length":178,"previous":"M21-GAP-02764","next":"M21-GAP-02766"},"M21-GAP-02766":{"line":6021,"offset":1077925,"length":178,"previous":"M21-GAP-02765","next":"M21-GAP-02767"},"M21-GAP-02767":{"line":6022,"offset":1078103,"length":178,"previous":"M21-GAP-02766","next":"M21-GAP-02768"},"M21-GAP-02768":{"line":6023,"offset":1078281,"length":178,"previous":"M21-GAP-02767","next":"M21-GAP-02769"},"M21-GAP-02769":{"line":6024,"offset":1078459,"length":178,"previous":"M21-GAP-02768","next":"M21-GAP-02770"},"M21-GAP-02770":{"line":6025,"offset":1078637,"length":178,"previous":"M21-GAP-02769","next":"M21-GAP-02771"},"M21-GAP-02771":{"line":6026,"offset":1078815,"length":177,"previous":"M21-GAP-02770","next":"M21-GAP-02772"},"M21-GAP-02772":{"line":6027,"offset":1078992,"length":178,"previous":"M21-GAP-02771","next":"M21-GAP-02773"},"M21-GAP-02773":{"line":6028,"offset":1079170,"length":178,"previous":"M21-GAP-02772","next":"M21-GAP-02774"},"M21-GAP-02774":{"line":6029,"offset":1079348,"length":178,"previous":"M21-GAP-02773","next":"M21-GAP-02775"},"M21-GAP-02775":{"line":6030,"offset":1079526,"length":178,"previous":"M21-GAP-02774","next":"M21-GAP-02776"},"M21-GAP-02776":{"line":6031,"offset":1079704,"length":178,"previous":"M21-GAP-02775","next":"M21-GAP-02777"},"M21-GAP-02777":{"line":6032,"offset":1079882,"length":178,"previous":"M21-GAP-02776","next":"M21-GAP-02778"},"M21-GAP-02778":{"line":6033,"offset":1080060,"length":178,"previous":"M21-GAP-02777","next":"M21-GAP-02779"},"M21-GAP-02779":{"line":6034,"offset":1080238,"length":178,"previous":"M21-GAP-02778","next":"M21-GAP-02780"},"M21-GAP-02780":{"line":6035,"offset":1080416,"length":178,"previous":"M21-GAP-02779","next":"M21-GAP-02781"},"M21-GAP-02781":{"line":6036,"offset":1080594,"length":178,"previous":"M21-GAP-02780","next":"M21-GAP-02782"},"M21-GAP-02782":{"line":6037,"offset":1080772,"length":177,"previous":"M21-GAP-02781","next":"M21-GAP-02783"},"M21-GAP-02783":{"line":6038,"offset":1080949,"length":178,"previous":"M21-GAP-02782","next":"M21-GAP-02784"},"M21-GAP-02784":{"line":6039,"offset":1081127,"length":178,"previous":"M21-GAP-02783","next":"M21-GAP-02785"},"M21-GAP-02785":{"line":6040,"offset":1081305,"length":178,"previous":"M21-GAP-02784","next":"M21-GAP-02786"},"M21-GAP-02786":{"line":6041,"offset":1081483,"length":178,"previous":"M21-GAP-02785","next":"M21-GAP-02787"},"M21-GAP-02787":{"line":6042,"offset":1081661,"length":178,"previous":"M21-GAP-02786","next":"M21-GAP-02788"},"M21-GAP-02788":{"line":6043,"offset":1081839,"length":178,"previous":"M21-GAP-02787","next":"M21-GAP-02789"},"M21-GAP-02789":{"line":6044,"offset":1082017,"length":178,"previous":"M21-GAP-02788","next":"M21-GAP-02790"},"M21-GAP-02790":{"line":6045,"offset":1082195,"length":178,"previous":"M21-GAP-02789","next":"M21-GAP-02791"},"M21-GAP-02791":{"line":6046,"offset":1082373,"length":178,"previous":"M21-GAP-02790","next":"M21-GAP-02792"},"M21-GAP-02792":{"line":6047,"offset":1082551,"length":178,"previous":"M21-GAP-02791","next":"M21-GAP-02793"},"M21-GAP-02793":{"line":6048,"offset":1082729,"length":177,"previous":"M21-GAP-02792","next":"M21-GAP-02794"},"M21-GAP-02794":{"line":6049,"offset":1082906,"length":178,"previous":"M21-GAP-02793","next":"M21-GAP-02795"},"M21-GAP-02795":{"line":6050,"offset":1083084,"length":178,"previous":"M21-GAP-02794","next":"M21-GAP-02796"},"M21-GAP-02796":{"line":6051,"offset":1083262,"length":178,"previous":"M21-GAP-02795","next":"M21-GAP-02797"},"M21-GAP-02797":{"line":6052,"offset":1083440,"length":178,"previous":"M21-GAP-02796","next":"M21-GAP-02798"},"M21-GAP-02798":{"line":6053,"offset":1083618,"length":178,"previous":"M21-GAP-02797","next":"M21-GAP-02799"},"M21-GAP-02799":{"line":6054,"offset":1083796,"length":178,"previous":"M21-GAP-02798","next":"M21-GAP-02800"},"M21-GAP-02800":{"line":6055,"offset":1083974,"length":178,"previous":"M21-GAP-02799","next":"M21-GAP-02801"},"M21-GAP-02801":{"line":6056,"offset":1084152,"length":178,"previous":"M21-GAP-02800","next":"M21-GAP-02802"},"M21-GAP-02802":{"line":6057,"offset":1084330,"length":178,"previous":"M21-GAP-02801","next":"M21-GAP-02803"},"M21-GAP-02803":{"line":6058,"offset":1084508,"length":178,"previous":"M21-GAP-02802","next":"M21-GAP-02804"},"M21-GAP-02804":{"line":6059,"offset":1084686,"length":177,"previous":"M21-GAP-02803","next":"M21-GAP-02805"},"M21-GAP-02805":{"line":6060,"offset":1084863,"length":178,"previous":"M21-GAP-02804","next":"M21-GAP-02806"},"M21-GAP-02806":{"line":6061,"offset":1085041,"length":178,"previous":"M21-GAP-02805","next":"M21-GAP-02807"},"M21-GAP-02807":{"line":6062,"offset":1085219,"length":178,"previous":"M21-GAP-02806","next":"M21-GAP-02808"},"M21-GAP-02808":{"line":6063,"offset":1085397,"length":178,"previous":"M21-GAP-02807","next":"M21-GAP-02809"},"M21-GAP-02809":{"line":6064,"offset":1085575,"length":178,"previous":"M21-GAP-02808","next":"M21-GAP-02810"},"M21-GAP-02810":{"line":6065,"offset":1085753,"length":178,"previous":"M21-GAP-02809","next":"M21-GAP-02811"},"M21-GAP-02811":{"line":6066,"offset":1085931,"length":178,"previous":"M21-GAP-02810","next":"M21-GAP-02812"},"M21-GAP-02812":{"line":6067,"offset":1086109,"length":178,"previous":"M21-GAP-02811","next":"M21-GAP-02813"},"M21-GAP-02813":{"line":6068,"offset":1086287,"length":178,"previous":"M21-GAP-02812","next":"M21-GAP-02814"},"M21-GAP-02814":{"line":6069,"offset":1086465,"length":178,"previous":"M21-GAP-02813","next":"M21-GAP-02815"},"M21-GAP-02815":{"line":6070,"offset":1086643,"length":177,"previous":"M21-GAP-02814","next":"M21-GAP-02816"},"M21-GAP-02816":{"line":6071,"offset":1086820,"length":178,"previous":"M21-GAP-02815","next":"M21-GAP-02817"},"M21-GAP-02817":{"line":6072,"offset":1086998,"length":178,"previous":"M21-GAP-02816","next":"M21-GAP-02818"},"M21-GAP-02818":{"line":6073,"offset":1087176,"length":178,"previous":"M21-GAP-02817","next":"M21-GAP-02819"},"M21-GAP-02819":{"line":6074,"offset":1087354,"length":178,"previous":"M21-GAP-02818","next":"M21-GAP-02820"},"M21-GAP-02820":{"line":6075,"offset":1087532,"length":178,"previous":"M21-GAP-02819","next":"M21-GAP-02821"},"M21-GAP-02821":{"line":6076,"offset":1087710,"length":178,"previous":"M21-GAP-02820","next":"M21-GAP-02822"},"M21-GAP-02822":{"line":6077,"offset":1087888,"length":178,"previous":"M21-GAP-02821","next":"M21-GAP-02823"},"M21-GAP-02823":{"line":6078,"offset":1088066,"length":178,"previous":"M21-GAP-02822","next":"M21-GAP-02824"},"M21-GAP-02824":{"line":6079,"offset":1088244,"length":178,"previous":"M21-GAP-02823","next":"M21-GAP-02825"},"M21-GAP-02825":{"line":6080,"offset":1088422,"length":178,"previous":"M21-GAP-02824","next":"M21-GAP-02826"},"M21-GAP-02826":{"line":6081,"offset":1088600,"length":177,"previous":"M21-GAP-02825","next":"M21-GAP-02827"},"M21-GAP-02827":{"line":6082,"offset":1088777,"length":178,"previous":"M21-GAP-02826","next":"M21-GAP-02828"},"M21-GAP-02828":{"line":6083,"offset":1088955,"length":177,"previous":"M21-GAP-02827","next":"M21-GAP-02829"},"M21-GAP-02829":{"line":6084,"offset":1089132,"length":177,"previous":"M21-GAP-02828","next":"M21-GAP-02830"},"M21-GAP-02830":{"line":6085,"offset":1089309,"length":177,"previous":"M21-GAP-02829","next":"M21-GAP-02831"},"M21-GAP-02831":{"line":6086,"offset":1089486,"length":183,"previous":"M21-GAP-02830","next":"M21-GAP-02832"},"M21-GAP-02832":{"line":6087,"offset":1089669,"length":183,"previous":"M21-GAP-02831","next":"M21-GAP-02833"},"M21-GAP-02833":{"line":6088,"offset":1089852,"length":183,"previous":"M21-GAP-02832","next":"M21-GAP-02834"},"M21-GAP-02834":{"line":6089,"offset":1090035,"length":183,"previous":"M21-GAP-02833","next":"M21-GAP-02835"},"M21-GAP-02835":{"line":6090,"offset":1090218,"length":183,"previous":"M21-GAP-02834","next":"M21-GAP-02836"},"M21-GAP-02836":{"line":6091,"offset":1090401,"length":198,"previous":"M21-GAP-02835","next":"M21-GAP-02837"},"M21-GAP-02837":{"line":6092,"offset":1090599,"length":198,"previous":"M21-GAP-02836","next":"M21-GAP-02838"},"M21-GAP-02838":{"line":6093,"offset":1090797,"length":198,"previous":"M21-GAP-02837","next":"M21-GAP-02839"},"M21-GAP-02839":{"line":6094,"offset":1090995,"length":198,"previous":"M21-GAP-02838","next":"M21-GAP-02840"},"M21-GAP-02840":{"line":6095,"offset":1091193,"length":198,"previous":"M21-GAP-02839","next":"M21-GAP-02841"},"M21-GAP-02841":{"line":6096,"offset":1091391,"length":198,"previous":"M21-GAP-02840","next":"M21-GAP-02842"},"M21-GAP-02842":{"line":6097,"offset":1091589,"length":198,"previous":"M21-GAP-02841","next":"M21-GAP-02843"},"M21-GAP-02843":{"line":6098,"offset":1091787,"length":198,"previous":"M21-GAP-02842","next":"M21-GAP-02844"},"M21-GAP-02844":{"line":6099,"offset":1091985,"length":198,"previous":"M21-GAP-02843","next":"M21-GAP-02845"},"M21-GAP-02845":{"line":6100,"offset":1092183,"length":186,"previous":"M21-GAP-02844","next":"M21-GAP-02846"},"M21-GAP-02846":{"line":6101,"offset":1092369,"length":186,"previous":"M21-GAP-02845","next":"M21-GAP-02847"},"M21-GAP-02847":{"line":6102,"offset":1092555,"length":187,"previous":"M21-GAP-02846","next":"M21-GAP-02848"},"M21-GAP-02848":{"line":6103,"offset":1092742,"length":187,"previous":"M21-GAP-02847","next":"M21-GAP-02849"},"M21-GAP-02849":{"line":6104,"offset":1092929,"length":187,"previous":"M21-GAP-02848","next":"M21-GAP-02850"},"M21-GAP-02850":{"line":6105,"offset":1093116,"length":187,"previous":"M21-GAP-02849","next":"M21-GAP-02851"},"M21-GAP-02851":{"line":6106,"offset":1093303,"length":187,"previous":"M21-GAP-02850","next":"M21-GAP-02852"},"M21-GAP-02852":{"line":6107,"offset":1093490,"length":187,"previous":"M21-GAP-02851","next":"M21-GAP-02853"},"M21-GAP-02853":{"line":6108,"offset":1093677,"length":187,"previous":"M21-GAP-02852","next":"M21-GAP-02854"},"M21-GAP-02854":{"line":6109,"offset":1093864,"length":187,"previous":"M21-GAP-02853","next":"M21-GAP-02855"},"M21-GAP-02855":{"line":6110,"offset":1094051,"length":187,"previous":"M21-GAP-02854","next":"M21-GAP-02856"},"M21-GAP-02856":{"line":6111,"offset":1094238,"length":187,"previous":"M21-GAP-02855","next":"M21-GAP-02857"},"M21-GAP-02857":{"line":6112,"offset":1094425,"length":186,"previous":"M21-GAP-02856","next":"M21-GAP-02858"},"M21-GAP-02858":{"line":6113,"offset":1094611,"length":187,"previous":"M21-GAP-02857","next":"M21-GAP-02859"},"M21-GAP-02859":{"line":6114,"offset":1094798,"length":187,"previous":"M21-GAP-02858","next":"M21-GAP-02860"},"M21-GAP-02860":{"line":6115,"offset":1094985,"length":187,"previous":"M21-GAP-02859","next":"M21-GAP-02861"},"M21-GAP-02861":{"line":6116,"offset":1095172,"length":187,"previous":"M21-GAP-02860","next":"M21-GAP-02862"},"M21-GAP-02862":{"line":6117,"offset":1095359,"length":187,"previous":"M21-GAP-02861","next":"M21-GAP-02863"},"M21-GAP-02863":{"line":6118,"offset":1095546,"length":187,"previous":"M21-GAP-02862","next":"M21-GAP-02864"},"M21-GAP-02864":{"line":6119,"offset":1095733,"length":187,"previous":"M21-GAP-02863","next":"M21-GAP-02865"},"M21-GAP-02865":{"line":6120,"offset":1095920,"length":187,"previous":"M21-GAP-02864","next":"M21-GAP-02866"},"M21-GAP-02866":{"line":6121,"offset":1096107,"length":187,"previous":"M21-GAP-02865","next":"M21-GAP-02867"},"M21-GAP-02867":{"line":6122,"offset":1096294,"length":187,"previous":"M21-GAP-02866","next":"M21-GAP-02868"},"M21-GAP-02868":{"line":6123,"offset":1096481,"length":186,"previous":"M21-GAP-02867","next":"M21-GAP-02869"},"M21-GAP-02869":{"line":6124,"offset":1096667,"length":187,"previous":"M21-GAP-02868","next":"M21-GAP-02870"},"M21-GAP-02870":{"line":6125,"offset":1096854,"length":187,"previous":"M21-GAP-02869","next":"M21-GAP-02871"},"M21-GAP-02871":{"line":6126,"offset":1097041,"length":187,"previous":"M21-GAP-02870","next":"M21-GAP-02872"},"M21-GAP-02872":{"line":6127,"offset":1097228,"length":187,"previous":"M21-GAP-02871","next":"M21-GAP-02873"},"M21-GAP-02873":{"line":6128,"offset":1097415,"length":187,"previous":"M21-GAP-02872","next":"M21-GAP-02874"},"M21-GAP-02874":{"line":6129,"offset":1097602,"length":187,"previous":"M21-GAP-02873","next":"M21-GAP-02875"},"M21-GAP-02875":{"line":6130,"offset":1097789,"length":187,"previous":"M21-GAP-02874","next":"M21-GAP-02876"},"M21-GAP-02876":{"line":6131,"offset":1097976,"length":187,"previous":"M21-GAP-02875","next":"M21-GAP-02877"},"M21-GAP-02877":{"line":6132,"offset":1098163,"length":187,"previous":"M21-GAP-02876","next":"M21-GAP-02878"},"M21-GAP-02878":{"line":6133,"offset":1098350,"length":187,"previous":"M21-GAP-02877","next":"M21-GAP-02879"},"M21-GAP-02879":{"line":6134,"offset":1098537,"length":186,"previous":"M21-GAP-02878","next":"M21-GAP-02880"},"M21-GAP-02880":{"line":6135,"offset":1098723,"length":187,"previous":"M21-GAP-02879","next":"M21-GAP-02881"},"M21-GAP-02881":{"line":6136,"offset":1098910,"length":187,"previous":"M21-GAP-02880","next":"M21-GAP-02882"},"M21-GAP-02882":{"line":6137,"offset":1099097,"length":187,"previous":"M21-GAP-02881","next":"M21-GAP-02883"},"M21-GAP-02883":{"line":6138,"offset":1099284,"length":187,"previous":"M21-GAP-02882","next":"M21-GAP-02884"},"M21-GAP-02884":{"line":6139,"offset":1099471,"length":187,"previous":"M21-GAP-02883","next":"M21-GAP-02885"},"M21-GAP-02885":{"line":6140,"offset":1099658,"length":187,"previous":"M21-GAP-02884","next":"M21-GAP-02886"},"M21-GAP-02886":{"line":6141,"offset":1099845,"length":187,"previous":"M21-GAP-02885","next":"M21-GAP-02887"},"M21-GAP-02887":{"line":6142,"offset":1100032,"length":187,"previous":"M21-GAP-02886","next":"M21-GAP-02888"},"M21-GAP-02888":{"line":6143,"offset":1100219,"length":187,"previous":"M21-GAP-02887","next":"M21-GAP-02889"},"M21-GAP-02889":{"line":6144,"offset":1100406,"length":187,"previous":"M21-GAP-02888","next":"M21-GAP-02890"},"M21-GAP-02890":{"line":6145,"offset":1100593,"length":186,"previous":"M21-GAP-02889","next":"M21-GAP-02891"},"M21-GAP-02891":{"line":6146,"offset":1100779,"length":187,"previous":"M21-GAP-02890","next":"M21-GAP-02892"},"M21-GAP-02892":{"line":6147,"offset":1100966,"length":187,"previous":"M21-GAP-02891","next":"M21-GAP-02893"},"M21-GAP-02893":{"line":6148,"offset":1101153,"length":187,"previous":"M21-GAP-02892","next":"M21-GAP-02894"},"M21-GAP-02894":{"line":6149,"offset":1101340,"length":187,"previous":"M21-GAP-02893","next":"M21-GAP-02895"},"M21-GAP-02895":{"line":6150,"offset":1101527,"length":187,"previous":"M21-GAP-02894","next":"M21-GAP-02896"},"M21-GAP-02896":{"line":6151,"offset":1101714,"length":187,"previous":"M21-GAP-02895","next":"M21-GAP-02897"},"M21-GAP-02897":{"line":6152,"offset":1101901,"length":186,"previous":"M21-GAP-02896","next":"M21-GAP-02898"},"M21-GAP-02898":{"line":6153,"offset":1102087,"length":186,"previous":"M21-GAP-02897","next":"M21-GAP-02899"},"M21-GAP-02899":{"line":6154,"offset":1102273,"length":186,"previous":"M21-GAP-02898","next":"M21-GAP-02900"},"M21-GAP-02900":{"line":6155,"offset":1102459,"length":186,"previous":"M21-GAP-02899","next":"M21-GAP-02901"},"M21-GAP-02901":{"line":6156,"offset":1102645,"length":176,"previous":"M21-GAP-02900","next":"M21-GAP-02902"},"M21-GAP-02902":{"line":6157,"offset":1102821,"length":176,"previous":"M21-GAP-02901","next":"M21-GAP-02903"},"M21-GAP-02903":{"line":6158,"offset":1102997,"length":177,"previous":"M21-GAP-02902","next":"M21-GAP-02904"},"M21-GAP-02904":{"line":6159,"offset":1103174,"length":177,"previous":"M21-GAP-02903","next":"M21-GAP-02905"},"M21-GAP-02905":{"line":6160,"offset":1103351,"length":177,"previous":"M21-GAP-02904","next":"M21-GAP-02906"},"M21-GAP-02906":{"line":6161,"offset":1103528,"length":177,"previous":"M21-GAP-02905","next":"M21-GAP-02907"},"M21-GAP-02907":{"line":6162,"offset":1103705,"length":177,"previous":"M21-GAP-02906","next":"M21-GAP-02908"},"M21-GAP-02908":{"line":6163,"offset":1103882,"length":177,"previous":"M21-GAP-02907","next":"M21-GAP-02909"},"M21-GAP-02909":{"line":6164,"offset":1104059,"length":177,"previous":"M21-GAP-02908","next":"M21-GAP-02910"},"M21-GAP-02910":{"line":6165,"offset":1104236,"length":177,"previous":"M21-GAP-02909","next":"M21-GAP-02911"},"M21-GAP-02911":{"line":6166,"offset":1104413,"length":177,"previous":"M21-GAP-02910","next":"M21-GAP-02912"},"M21-GAP-02912":{"line":6167,"offset":1104590,"length":177,"previous":"M21-GAP-02911","next":"M21-GAP-02913"},"M21-GAP-02913":{"line":6168,"offset":1104767,"length":176,"previous":"M21-GAP-02912","next":"M21-GAP-02914"},"M21-GAP-02914":{"line":6169,"offset":1104943,"length":177,"previous":"M21-GAP-02913","next":"M21-GAP-02915"},"M21-GAP-02915":{"line":6170,"offset":1105120,"length":177,"previous":"M21-GAP-02914","next":"M21-GAP-02916"},"M21-GAP-02916":{"line":6171,"offset":1105297,"length":177,"previous":"M21-GAP-02915","next":"M21-GAP-02917"},"M21-GAP-02917":{"line":6172,"offset":1105474,"length":177,"previous":"M21-GAP-02916","next":"M21-GAP-02918"},"M21-GAP-02918":{"line":6173,"offset":1105651,"length":177,"previous":"M21-GAP-02917","next":"M21-GAP-02919"},"M21-GAP-02919":{"line":6174,"offset":1105828,"length":177,"previous":"M21-GAP-02918","next":"M21-GAP-02920"},"M21-GAP-02920":{"line":6175,"offset":1106005,"length":177,"previous":"M21-GAP-02919","next":"M21-GAP-02921"},"M21-GAP-02921":{"line":6176,"offset":1106182,"length":177,"previous":"M21-GAP-02920","next":"M21-GAP-02922"},"M21-GAP-02922":{"line":6177,"offset":1106359,"length":177,"previous":"M21-GAP-02921","next":"M21-GAP-02923"},"M21-GAP-02923":{"line":6178,"offset":1106536,"length":177,"previous":"M21-GAP-02922","next":"M21-GAP-02924"},"M21-GAP-02924":{"line":6179,"offset":1106713,"length":176,"previous":"M21-GAP-02923","next":"M21-GAP-02925"},"M21-GAP-02925":{"line":6180,"offset":1106889,"length":177,"previous":"M21-GAP-02924","next":"M21-GAP-02926"},"M21-GAP-02926":{"line":6181,"offset":1107066,"length":177,"previous":"M21-GAP-02925","next":"M21-GAP-02927"},"M21-GAP-02927":{"line":6182,"offset":1107243,"length":177,"previous":"M21-GAP-02926","next":"M21-GAP-02928"},"M21-GAP-02928":{"line":6183,"offset":1107420,"length":177,"previous":"M21-GAP-02927","next":"M21-GAP-02929"},"M21-GAP-02929":{"line":6184,"offset":1107597,"length":177,"previous":"M21-GAP-02928","next":"M21-GAP-02930"},"M21-GAP-02930":{"line":6185,"offset":1107774,"length":177,"previous":"M21-GAP-02929","next":"M21-GAP-02931"},"M21-GAP-02931":{"line":6186,"offset":1107951,"length":177,"previous":"M21-GAP-02930","next":"M21-GAP-02932"},"M21-GAP-02932":{"line":6187,"offset":1108128,"length":177,"previous":"M21-GAP-02931","next":"M21-GAP-02933"},"M21-GAP-02933":{"line":6188,"offset":1108305,"length":177,"previous":"M21-GAP-02932","next":"M21-GAP-02934"},"M21-GAP-02934":{"line":6189,"offset":1108482,"length":177,"previous":"M21-GAP-02933","next":"M21-GAP-02935"},"M21-GAP-02935":{"line":6190,"offset":1108659,"length":176,"previous":"M21-GAP-02934","next":"M21-GAP-02936"},"M21-GAP-02936":{"line":6191,"offset":1108835,"length":177,"previous":"M21-GAP-02935","next":"M21-GAP-02937"},"M21-GAP-02937":{"line":6192,"offset":1109012,"length":177,"previous":"M21-GAP-02936","next":"M21-GAP-02938"},"M21-GAP-02938":{"line":6193,"offset":1109189,"length":177,"previous":"M21-GAP-02937","next":"M21-GAP-02939"},"M21-GAP-02939":{"line":6194,"offset":1109366,"length":177,"previous":"M21-GAP-02938","next":"M21-GAP-02940"},"M21-GAP-02940":{"line":6195,"offset":1109543,"length":177,"previous":"M21-GAP-02939","next":"M21-GAP-02941"},"M21-GAP-02941":{"line":6196,"offset":1109720,"length":177,"previous":"M21-GAP-02940","next":"M21-GAP-02942"},"M21-GAP-02942":{"line":6197,"offset":1109897,"length":177,"previous":"M21-GAP-02941","next":"M21-GAP-02943"},"M21-GAP-02943":{"line":6198,"offset":1110074,"length":177,"previous":"M21-GAP-02942","next":"M21-GAP-02944"},"M21-GAP-02944":{"line":6199,"offset":1110251,"length":177,"previous":"M21-GAP-02943","next":"M21-GAP-02945"},"M21-GAP-02945":{"line":6200,"offset":1110428,"length":177,"previous":"M21-GAP-02944","next":"M21-GAP-02946"},"M21-GAP-02946":{"line":6201,"offset":1110605,"length":176,"previous":"M21-GAP-02945","next":"M21-GAP-02947"},"M21-GAP-02947":{"line":6202,"offset":1110781,"length":177,"previous":"M21-GAP-02946","next":"M21-GAP-02948"},"M21-GAP-02948":{"line":6203,"offset":1110958,"length":177,"previous":"M21-GAP-02947","next":"M21-GAP-02949"},"M21-GAP-02949":{"line":6204,"offset":1111135,"length":177,"previous":"M21-GAP-02948","next":"M21-GAP-02950"},"M21-GAP-02950":{"line":6205,"offset":1111312,"length":177,"previous":"M21-GAP-02949","next":"M21-GAP-02951"},"M21-GAP-02951":{"line":6206,"offset":1111489,"length":177,"previous":"M21-GAP-02950","next":"M21-GAP-02952"},"M21-GAP-02952":{"line":6207,"offset":1111666,"length":177,"previous":"M21-GAP-02951","next":"M21-GAP-02953"},"M21-GAP-02953":{"line":6208,"offset":1111843,"length":177,"previous":"M21-GAP-02952","next":"M21-GAP-02954"},"M21-GAP-02954":{"line":6209,"offset":1112020,"length":177,"previous":"M21-GAP-02953","next":"M21-GAP-02955"},"M21-GAP-02955":{"line":6210,"offset":1112197,"length":177,"previous":"M21-GAP-02954","next":"M21-GAP-02956"},"M21-GAP-02956":{"line":6211,"offset":1112374,"length":177,"previous":"M21-GAP-02955","next":"M21-GAP-02957"},"M21-GAP-02957":{"line":6212,"offset":1112551,"length":176,"previous":"M21-GAP-02956","next":"M21-GAP-02958"},"M21-GAP-02958":{"line":6213,"offset":1112727,"length":177,"previous":"M21-GAP-02957","next":"M21-GAP-02959"},"M21-GAP-02959":{"line":6214,"offset":1112904,"length":177,"previous":"M21-GAP-02958","next":"M21-GAP-02960"},"M21-GAP-02960":{"line":6215,"offset":1113081,"length":177,"previous":"M21-GAP-02959","next":"M21-GAP-02961"},"M21-GAP-02961":{"line":6216,"offset":1113258,"length":177,"previous":"M21-GAP-02960","next":"M21-GAP-02962"},"M21-GAP-02962":{"line":6217,"offset":1113435,"length":177,"previous":"M21-GAP-02961","next":"M21-GAP-02963"},"M21-GAP-02963":{"line":6218,"offset":1113612,"length":177,"previous":"M21-GAP-02962","next":"M21-GAP-02964"},"M21-GAP-02964":{"line":6219,"offset":1113789,"length":177,"previous":"M21-GAP-02963","next":"M21-GAP-02965"},"M21-GAP-02965":{"line":6220,"offset":1113966,"length":177,"previous":"M21-GAP-02964","next":"M21-GAP-02966"},"M21-GAP-02966":{"line":6221,"offset":1114143,"length":177,"previous":"M21-GAP-02965","next":"M21-GAP-02967"},"M21-GAP-02967":{"line":6222,"offset":1114320,"length":177,"previous":"M21-GAP-02966","next":"M21-GAP-02968"},"M21-GAP-02968":{"line":6223,"offset":1114497,"length":176,"previous":"M21-GAP-02967","next":"M21-GAP-02969"},"M21-GAP-02969":{"line":6224,"offset":1114673,"length":177,"previous":"M21-GAP-02968","next":"M21-GAP-02970"},"M21-GAP-02970":{"line":6225,"offset":1114850,"length":177,"previous":"M21-GAP-02969","next":"M21-GAP-02971"},"M21-GAP-02971":{"line":6226,"offset":1115027,"length":177,"previous":"M21-GAP-02970","next":"M21-GAP-02972"},"M21-GAP-02972":{"line":6227,"offset":1115204,"length":177,"previous":"M21-GAP-02971","next":"M21-GAP-02973"},"M21-GAP-02973":{"line":6228,"offset":1115381,"length":177,"previous":"M21-GAP-02972","next":"M21-GAP-02974"},"M21-GAP-02974":{"line":6229,"offset":1115558,"length":177,"previous":"M21-GAP-02973","next":"M21-GAP-02975"},"M21-GAP-02975":{"line":6230,"offset":1115735,"length":177,"previous":"M21-GAP-02974","next":"M21-GAP-02976"},"M21-GAP-02976":{"line":6231,"offset":1115912,"length":177,"previous":"M21-GAP-02975","next":"M21-GAP-02977"},"M21-GAP-02977":{"line":6232,"offset":1116089,"length":177,"previous":"M21-GAP-02976","next":"M21-GAP-02978"},"M21-GAP-02978":{"line":6233,"offset":1116266,"length":177,"previous":"M21-GAP-02977","next":"M21-GAP-02979"},"M21-GAP-02979":{"line":6234,"offset":1116443,"length":176,"previous":"M21-GAP-02978","next":"M21-GAP-02980"},"M21-GAP-02980":{"line":6235,"offset":1116619,"length":177,"previous":"M21-GAP-02979","next":"M21-GAP-02981"},"M21-GAP-02981":{"line":6236,"offset":1116796,"length":177,"previous":"M21-GAP-02980","next":"M21-GAP-02982"},"M21-GAP-02982":{"line":6237,"offset":1116973,"length":177,"previous":"M21-GAP-02981","next":"M21-GAP-02983"},"M21-GAP-02983":{"line":6238,"offset":1117150,"length":177,"previous":"M21-GAP-02982","next":"M21-GAP-02984"},"M21-GAP-02984":{"line":6239,"offset":1117327,"length":177,"previous":"M21-GAP-02983","next":"M21-GAP-02985"},"M21-GAP-02985":{"line":6240,"offset":1117504,"length":177,"previous":"M21-GAP-02984","next":"M21-GAP-02986"},"M21-GAP-02986":{"line":6241,"offset":1117681,"length":177,"previous":"M21-GAP-02985","next":"M21-GAP-02987"},"M21-GAP-02987":{"line":6242,"offset":1117858,"length":177,"previous":"M21-GAP-02986","next":"M21-GAP-02988"},"M21-GAP-02988":{"line":6243,"offset":1118035,"length":176,"previous":"M21-GAP-02987","next":"M21-GAP-02989"},"M21-GAP-02989":{"line":6244,"offset":1118211,"length":181,"previous":"M21-GAP-02988","next":"M21-GAP-02990"},"M21-GAP-02990":{"line":6245,"offset":1118392,"length":181,"previous":"M21-GAP-02989","next":"M21-GAP-02991"},"M21-GAP-02991":{"line":6246,"offset":1118573,"length":182,"previous":"M21-GAP-02990","next":"M21-GAP-02992"},"M21-GAP-02992":{"line":6247,"offset":1118755,"length":182,"previous":"M21-GAP-02991","next":"M21-GAP-02993"},"M21-GAP-02993":{"line":6248,"offset":1118937,"length":182,"previous":"M21-GAP-02992","next":"M21-GAP-02994"},"M21-GAP-02994":{"line":6249,"offset":1119119,"length":182,"previous":"M21-GAP-02993","next":"M21-GAP-02995"},"M21-GAP-02995":{"line":6250,"offset":1119301,"length":182,"previous":"M21-GAP-02994","next":"M21-GAP-02996"},"M21-GAP-02996":{"line":6251,"offset":1119483,"length":182,"previous":"M21-GAP-02995","next":"M21-GAP-02997"},"M21-GAP-02997":{"line":6252,"offset":1119665,"length":182,"previous":"M21-GAP-02996","next":"M21-GAP-02998"},"M21-GAP-02998":{"line":6253,"offset":1119847,"length":182,"previous":"M21-GAP-02997","next":"M21-GAP-02999"},"M21-GAP-02999":{"line":6254,"offset":1120029,"length":182,"previous":"M21-GAP-02998","next":"M21-GAP-03000"},"M21-GAP-03000":{"line":6255,"offset":1120211,"length":182,"previous":"M21-GAP-02999","next":"M21-GAP-03001"},"M21-GAP-03001":{"line":6256,"offset":1120393,"length":181,"previous":"M21-GAP-03000","next":"M21-GAP-03002"},"M21-GAP-03002":{"line":6257,"offset":1120574,"length":182,"previous":"M21-GAP-03001","next":"M21-GAP-03003"},"M21-GAP-03003":{"line":6258,"offset":1120756,"length":182,"previous":"M21-GAP-03002","next":"M21-GAP-03004"},"M21-GAP-03004":{"line":6259,"offset":1120938,"length":182,"previous":"M21-GAP-03003","next":"M21-GAP-03005"},"M21-GAP-03005":{"line":6260,"offset":1121120,"length":182,"previous":"M21-GAP-03004","next":"M21-GAP-03006"},"M21-GAP-03006":{"line":6261,"offset":1121302,"length":182,"previous":"M21-GAP-03005","next":"M21-GAP-03007"},"M21-GAP-03007":{"line":6262,"offset":1121484,"length":182,"previous":"M21-GAP-03006","next":"M21-GAP-03008"},"M21-GAP-03008":{"line":6263,"offset":1121666,"length":182,"previous":"M21-GAP-03007","next":"M21-GAP-03009"},"M21-GAP-03009":{"line":6264,"offset":1121848,"length":182,"previous":"M21-GAP-03008","next":"M21-GAP-03010"},"M21-GAP-03010":{"line":6265,"offset":1122030,"length":182,"previous":"M21-GAP-03009","next":"M21-GAP-03011"},"M21-GAP-03011":{"line":6266,"offset":1122212,"length":182,"previous":"M21-GAP-03010","next":"M21-GAP-03012"},"M21-GAP-03012":{"line":6267,"offset":1122394,"length":181,"previous":"M21-GAP-03011","next":"M21-GAP-03013"},"M21-GAP-03013":{"line":6268,"offset":1122575,"length":182,"previous":"M21-GAP-03012","next":"M21-GAP-03014"},"M21-GAP-03014":{"line":6269,"offset":1122757,"length":182,"previous":"M21-GAP-03013","next":"M21-GAP-03015"},"M21-GAP-03015":{"line":6270,"offset":1122939,"length":182,"previous":"M21-GAP-03014","next":"M21-GAP-03016"},"M21-GAP-03016":{"line":6271,"offset":1123121,"length":181,"previous":"M21-GAP-03015","next":"M21-GAP-03017"},"M21-GAP-03017":{"line":6272,"offset":1123302,"length":181,"previous":"M21-GAP-03016","next":"M21-GAP-03018"},"M21-GAP-03018":{"line":6273,"offset":1123483,"length":181,"previous":"M21-GAP-03017","next":"M21-GAP-03019"},"M21-GAP-03019":{"line":6274,"offset":1123664,"length":181,"previous":"M21-GAP-03018","next":"M21-GAP-03020"},"M21-GAP-03020":{"line":6275,"offset":1123845,"length":181,"previous":"M21-GAP-03019","next":"M21-GAP-03021"},"M21-GAP-03021":{"line":6276,"offset":1124026,"length":181,"previous":"M21-GAP-03020","next":"M21-GAP-03022"},"M21-GAP-03022":{"line":6277,"offset":1124207,"length":179,"previous":"M21-GAP-03021","next":"M21-GAP-03023"},"M21-GAP-03023":{"line":6278,"offset":1124386,"length":179,"previous":"M21-GAP-03022","next":"M21-GAP-03024"},"M21-GAP-03024":{"line":6279,"offset":1124565,"length":180,"previous":"M21-GAP-03023","next":"M21-GAP-03025"},"M21-GAP-03025":{"line":6280,"offset":1124745,"length":180,"previous":"M21-GAP-03024","next":"M21-GAP-03026"},"M21-GAP-03026":{"line":6281,"offset":1124925,"length":180,"previous":"M21-GAP-03025","next":"M21-GAP-03027"},"M21-GAP-03027":{"line":6282,"offset":1125105,"length":180,"previous":"M21-GAP-03026","next":"M21-GAP-03028"},"M21-GAP-03028":{"line":6283,"offset":1125285,"length":180,"previous":"M21-GAP-03027","next":"M21-GAP-03029"},"M21-GAP-03029":{"line":6284,"offset":1125465,"length":180,"previous":"M21-GAP-03028","next":"M21-GAP-03030"},"M21-GAP-03030":{"line":6285,"offset":1125645,"length":180,"previous":"M21-GAP-03029","next":"M21-GAP-03031"},"M21-GAP-03031":{"line":6286,"offset":1125825,"length":180,"previous":"M21-GAP-03030","next":"M21-GAP-03032"},"M21-GAP-03032":{"line":6287,"offset":1126005,"length":180,"previous":"M21-GAP-03031","next":"M21-GAP-03033"},"M21-GAP-03033":{"line":6288,"offset":1126185,"length":180,"previous":"M21-GAP-03032","next":"M21-GAP-03034"},"M21-GAP-03034":{"line":6289,"offset":1126365,"length":179,"previous":"M21-GAP-03033","next":"M21-GAP-03035"},"M21-GAP-03035":{"line":6290,"offset":1126544,"length":180,"previous":"M21-GAP-03034","next":"M21-GAP-03036"},"M21-GAP-03036":{"line":6291,"offset":1126724,"length":180,"previous":"M21-GAP-03035","next":"M21-GAP-03037"},"M21-GAP-03037":{"line":6292,"offset":1126904,"length":180,"previous":"M21-GAP-03036","next":"M21-GAP-03038"},"M21-GAP-03038":{"line":6293,"offset":1127084,"length":180,"previous":"M21-GAP-03037","next":"M21-GAP-03039"},"M21-GAP-03039":{"line":6294,"offset":1127264,"length":180,"previous":"M21-GAP-03038","next":"M21-GAP-03040"},"M21-GAP-03040":{"line":6295,"offset":1127444,"length":180,"previous":"M21-GAP-03039","next":"M21-GAP-03041"},"M21-GAP-03041":{"line":6296,"offset":1127624,"length":179,"previous":"M21-GAP-03040","next":"M21-GAP-03042"},"M21-GAP-03042":{"line":6297,"offset":1127803,"length":179,"previous":"M21-GAP-03041","next":"M21-GAP-03043"},"M21-GAP-03043":{"line":6298,"offset":1127982,"length":179,"previous":"M21-GAP-03042","next":"M21-GAP-03044"},"M21-GAP-03044":{"line":6299,"offset":1128161,"length":179,"previous":"M21-GAP-03043","next":"M21-GAP-03045"},"M21-GAP-03045":{"line":6300,"offset":1128340,"length":179,"previous":"M21-GAP-03044","next":"M21-GAP-03046"},"M21-GAP-03046":{"line":6301,"offset":1128519,"length":179,"previous":"M21-GAP-03045","next":"M21-GAP-03047"},"M21-GAP-03047":{"line":6302,"offset":1128698,"length":179,"previous":"M21-GAP-03046","next":"M21-GAP-03048"},"M21-GAP-03048":{"line":6303,"offset":1128877,"length":198,"previous":"M21-GAP-03047","next":"M21-GAP-03049"},"M21-GAP-03049":{"line":6304,"offset":1129075,"length":198,"previous":"M21-GAP-03048","next":"M21-GAP-03050"},"M21-GAP-03050":{"line":6305,"offset":1129273,"length":198,"previous":"M21-GAP-03049","next":"M21-GAP-03051"},"M21-GAP-03051":{"line":6306,"offset":1129471,"length":198,"previous":"M21-GAP-03050","next":"M21-GAP-03052"},"M21-GAP-03052":{"line":6307,"offset":1129669,"length":198,"previous":"M21-GAP-03051","next":"M21-GAP-03053"},"M21-GAP-03053":{"line":6308,"offset":1129867,"length":198,"previous":"M21-GAP-03052","next":"M21-GAP-03054"},"M21-GAP-03054":{"line":6309,"offset":1130065,"length":198,"previous":"M21-GAP-03053","next":"M21-GAP-03055"},"M21-GAP-03055":{"line":6310,"offset":1130263,"length":186,"previous":"M21-GAP-03054","next":"M21-GAP-03056"},"M21-GAP-03056":{"line":6311,"offset":1130449,"length":186,"previous":"M21-GAP-03055","next":"M21-GAP-03057"},"M21-GAP-03057":{"line":6312,"offset":1130635,"length":187,"previous":"M21-GAP-03056","next":"M21-GAP-03058"},"M21-GAP-03058":{"line":6313,"offset":1130822,"length":187,"previous":"M21-GAP-03057","next":"M21-GAP-03059"},"M21-GAP-03059":{"line":6314,"offset":1131009,"length":187,"previous":"M21-GAP-03058","next":"M21-GAP-03060"},"M21-GAP-03060":{"line":6315,"offset":1131196,"length":187,"previous":"M21-GAP-03059","next":"M21-GAP-03061"},"M21-GAP-03061":{"line":6316,"offset":1131383,"length":186,"previous":"M21-GAP-03060","next":"M21-GAP-03062"},"M21-GAP-03062":{"line":6317,"offset":1131569,"length":186,"previous":"M21-GAP-03061","next":"M21-GAP-03063"},"M21-GAP-03063":{"line":6318,"offset":1131755,"length":186,"previous":"M21-GAP-03062","next":"M21-GAP-03064"},"M21-GAP-03064":{"line":6319,"offset":1131941,"length":186,"previous":"M21-GAP-03063","next":"M21-GAP-03065"},"M21-GAP-03065":{"line":6320,"offset":1132127,"length":186,"previous":"M21-GAP-03064","next":"M21-GAP-03066"},"M21-GAP-03066":{"line":6321,"offset":1132313,"length":186,"previous":"M21-GAP-03065","next":"M21-GAP-03067"},"M21-GAP-03067":{"line":6322,"offset":1132499,"length":186,"previous":"M21-GAP-03066","next":"M21-GAP-03068"},"M21-GAP-03068":{"line":6323,"offset":1132685,"length":186,"previous":"M21-GAP-03067","next":"M21-GAP-03069"},"M21-GAP-03069":{"line":6324,"offset":1132871,"length":173,"previous":"M21-GAP-03068","next":"M21-GAP-03070"},"M21-GAP-03070":{"line":6325,"offset":1133044,"length":173,"previous":"M21-GAP-03069","next":"M21-GAP-03071"},"M21-GAP-03071":{"line":6326,"offset":1133217,"length":174,"previous":"M21-GAP-03070","next":"M21-GAP-03072"},"M21-GAP-03072":{"line":6327,"offset":1133391,"length":174,"previous":"M21-GAP-03071","next":"M21-GAP-03073"},"M21-GAP-03073":{"line":6328,"offset":1133565,"length":174,"previous":"M21-GAP-03072","next":"M21-GAP-03074"},"M21-GAP-03074":{"line":6329,"offset":1133739,"length":174,"previous":"M21-GAP-03073","next":"M21-GAP-03075"},"M21-GAP-03075":{"line":6330,"offset":1133913,"length":174,"previous":"M21-GAP-03074","next":"M21-GAP-03076"},"M21-GAP-03076":{"line":6331,"offset":1134087,"length":174,"previous":"M21-GAP-03075","next":"M21-GAP-03077"},"M21-GAP-03077":{"line":6332,"offset":1134261,"length":174,"previous":"M21-GAP-03076","next":"M21-GAP-03078"},"M21-GAP-03078":{"line":6333,"offset":1134435,"length":174,"previous":"M21-GAP-03077","next":"M21-GAP-03079"},"M21-GAP-03079":{"line":6334,"offset":1134609,"length":174,"previous":"M21-GAP-03078","next":"M21-GAP-03080"},"M21-GAP-03080":{"line":6335,"offset":1134783,"length":174,"previous":"M21-GAP-03079","next":"M21-GAP-03081"},"M21-GAP-03081":{"line":6336,"offset":1134957,"length":173,"previous":"M21-GAP-03080","next":"M21-GAP-03082"},"M21-GAP-03082":{"line":6337,"offset":1135130,"length":174,"previous":"M21-GAP-03081","next":"M21-GAP-03083"},"M21-GAP-03083":{"line":6338,"offset":1135304,"length":174,"previous":"M21-GAP-03082","next":"M21-GAP-03084"},"M21-GAP-03084":{"line":6339,"offset":1135478,"length":174,"previous":"M21-GAP-03083","next":"M21-GAP-03085"},"M21-GAP-03085":{"line":6340,"offset":1135652,"length":174,"previous":"M21-GAP-03084","next":"M21-GAP-03086"},"M21-GAP-03086":{"line":6341,"offset":1135826,"length":174,"previous":"M21-GAP-03085","next":"M21-GAP-03087"},"M21-GAP-03087":{"line":6342,"offset":1136000,"length":173,"previous":"M21-GAP-03086","next":"M21-GAP-03088"},"M21-GAP-03088":{"line":6343,"offset":1136173,"length":173,"previous":"M21-GAP-03087","next":"M21-GAP-03089"},"M21-GAP-03089":{"line":6344,"offset":1136346,"length":173,"previous":"M21-GAP-03088","next":"M21-GAP-03090"},"M21-GAP-03090":{"line":6345,"offset":1136519,"length":173,"previous":"M21-GAP-03089","next":"M21-GAP-03091"},"M21-GAP-03091":{"line":6346,"offset":1136692,"length":173,"previous":"M21-GAP-03090","next":"M21-GAP-03092"},"M21-GAP-03092":{"line":6347,"offset":1136865,"length":173,"previous":"M21-GAP-03091","next":"M21-GAP-03093"},"M21-GAP-03093":{"line":6348,"offset":1137038,"length":173,"previous":"M21-GAP-03092","next":"M21-GAP-03094"},"M21-GAP-03094":{"line":6349,"offset":1137211,"length":185,"previous":"M21-GAP-03093","next":"M21-GAP-03095"},"M21-GAP-03095":{"line":6350,"offset":1137396,"length":183,"previous":"M21-GAP-03094","next":"M21-GAP-03096"},"M21-GAP-03096":{"line":6351,"offset":1137579,"length":183,"previous":"M21-GAP-03095","next":"M21-GAP-03097"},"M21-GAP-03097":{"line":6352,"offset":1137762,"length":184,"previous":"M21-GAP-03096","next":"M21-GAP-03098"},"M21-GAP-03098":{"line":6353,"offset":1137946,"length":184,"previous":"M21-GAP-03097","next":"M21-GAP-03099"},"M21-GAP-03099":{"line":6354,"offset":1138130,"length":184,"previous":"M21-GAP-03098","next":"M21-GAP-03100"},"M21-GAP-03100":{"line":6355,"offset":1138314,"length":184,"previous":"M21-GAP-03099","next":"M21-GAP-03101"},"M21-GAP-03101":{"line":6356,"offset":1138498,"length":184,"previous":"M21-GAP-03100","next":"M21-GAP-03102"},"M21-GAP-03102":{"line":6357,"offset":1138682,"length":184,"previous":"M21-GAP-03101","next":"M21-GAP-03103"},"M21-GAP-03103":{"line":6358,"offset":1138866,"length":184,"previous":"M21-GAP-03102","next":"M21-GAP-03104"},"M21-GAP-03104":{"line":6359,"offset":1139050,"length":184,"previous":"M21-GAP-03103","next":"M21-GAP-03105"},"M21-GAP-03105":{"line":6360,"offset":1139234,"length":184,"previous":"M21-GAP-03104","next":"M21-GAP-03106"},"M21-GAP-03106":{"line":6361,"offset":1139418,"length":184,"previous":"M21-GAP-03105","next":"M21-GAP-03107"},"M21-GAP-03107":{"line":6362,"offset":1139602,"length":183,"previous":"M21-GAP-03106","next":"M21-GAP-03108"},"M21-GAP-03108":{"line":6363,"offset":1139785,"length":184,"previous":"M21-GAP-03107","next":"M21-GAP-03109"},"M21-GAP-03109":{"line":6364,"offset":1139969,"length":184,"previous":"M21-GAP-03108","next":"M21-GAP-03110"},"M21-GAP-03110":{"line":6365,"offset":1140153,"length":184,"previous":"M21-GAP-03109","next":"M21-GAP-03111"},"M21-GAP-03111":{"line":6366,"offset":1140337,"length":184,"previous":"M21-GAP-03110","next":"M21-GAP-03112"},"M21-GAP-03112":{"line":6367,"offset":1140521,"length":184,"previous":"M21-GAP-03111","next":"M21-GAP-03113"},"M21-GAP-03113":{"line":6368,"offset":1140705,"length":184,"previous":"M21-GAP-03112","next":"M21-GAP-03114"},"M21-GAP-03114":{"line":6369,"offset":1140889,"length":184,"previous":"M21-GAP-03113","next":"M21-GAP-03115"},"M21-GAP-03115":{"line":6370,"offset":1141073,"length":184,"previous":"M21-GAP-03114","next":"M21-GAP-03116"},"M21-GAP-03116":{"line":6371,"offset":1141257,"length":184,"previous":"M21-GAP-03115","next":"M21-GAP-03117"},"M21-GAP-03117":{"line":6372,"offset":1141441,"length":184,"previous":"M21-GAP-03116","next":"M21-GAP-03118"},"M21-GAP-03118":{"line":6373,"offset":1141625,"length":183,"previous":"M21-GAP-03117","next":"M21-GAP-03119"},"M21-GAP-03119":{"line":6374,"offset":1141808,"length":184,"previous":"M21-GAP-03118","next":"M21-GAP-03120"},"M21-GAP-03120":{"line":6375,"offset":1141992,"length":184,"previous":"M21-GAP-03119","next":"M21-GAP-03121"},"M21-GAP-03121":{"line":6376,"offset":1142176,"length":184,"previous":"M21-GAP-03120","next":"M21-GAP-03122"},"M21-GAP-03122":{"line":6377,"offset":1142360,"length":184,"previous":"M21-GAP-03121","next":"M21-GAP-03123"},"M21-GAP-03123":{"line":6378,"offset":1142544,"length":184,"previous":"M21-GAP-03122","next":"M21-GAP-03124"},"M21-GAP-03124":{"line":6379,"offset":1142728,"length":184,"previous":"M21-GAP-03123","next":"M21-GAP-03125"},"M21-GAP-03125":{"line":6380,"offset":1142912,"length":184,"previous":"M21-GAP-03124","next":"M21-GAP-03126"},"M21-GAP-03126":{"line":6381,"offset":1143096,"length":184,"previous":"M21-GAP-03125","next":"M21-GAP-03127"},"M21-GAP-03127":{"line":6382,"offset":1143280,"length":184,"previous":"M21-GAP-03126","next":"M21-GAP-03128"},"M21-GAP-03128":{"line":6383,"offset":1143464,"length":183,"previous":"M21-GAP-03127","next":"M21-GAP-03129"},"M21-GAP-03129":{"line":6384,"offset":1143647,"length":183,"previous":"M21-GAP-03128","next":"M21-GAP-03130"},"M21-GAP-03130":{"line":6385,"offset":1143830,"length":183,"previous":"M21-GAP-03129","next":"M21-GAP-03131"},"M21-GAP-03131":{"line":6386,"offset":1144013,"length":183,"previous":"M21-GAP-03130","next":"M21-GAP-03132"},"M21-GAP-03132":{"line":6387,"offset":1144196,"length":183,"previous":"M21-GAP-03131","next":"M21-GAP-03133"},"M21-GAP-03133":{"line":6388,"offset":1144379,"length":183,"previous":"M21-GAP-03132","next":"M21-GAP-03134"},"M21-GAP-03134":{"line":6389,"offset":1144562,"length":188,"previous":"M21-GAP-03133","next":"M21-GAP-03135"},"M21-GAP-03135":{"line":6390,"offset":1144750,"length":188,"previous":"M21-GAP-03134","next":"M21-GAP-03136"},"M21-GAP-03136":{"line":6391,"offset":1144938,"length":189,"previous":"M21-GAP-03135","next":"M21-GAP-03137"},"M21-GAP-03137":{"line":6392,"offset":1145127,"length":189,"previous":"M21-GAP-03136","next":"M21-GAP-03138"},"M21-GAP-03138":{"line":6393,"offset":1145316,"length":189,"previous":"M21-GAP-03137","next":"M21-GAP-03139"},"M21-GAP-03139":{"line":6394,"offset":1145505,"length":189,"previous":"M21-GAP-03138","next":"M21-GAP-03140"},"M21-GAP-03140":{"line":6395,"offset":1145694,"length":188,"previous":"M21-GAP-03139","next":"M21-GAP-03141"},"M21-GAP-03141":{"line":6396,"offset":1145882,"length":188,"previous":"M21-GAP-03140","next":"M21-GAP-03142"},"M21-GAP-03142":{"line":6397,"offset":1146070,"length":188,"previous":"M21-GAP-03141","next":"M21-GAP-03143"},"M21-GAP-03143":{"line":6398,"offset":1146258,"length":188,"previous":"M21-GAP-03142","next":"M21-GAP-03144"},"M21-GAP-03144":{"line":6399,"offset":1146446,"length":188,"previous":"M21-GAP-03143","next":"M21-GAP-03145"},"M21-GAP-03145":{"line":6400,"offset":1146634,"length":188,"previous":"M21-GAP-03144","next":"M21-GAP-03146"},"M21-GAP-03146":{"line":6401,"offset":1146822,"length":188,"previous":"M21-GAP-03145","next":"M21-GAP-03147"},"M21-GAP-03147":{"line":6402,"offset":1147010,"length":188,"previous":"M21-GAP-03146","next":"M21-GAP-03148"},"M21-GAP-03148":{"line":6403,"offset":1147198,"length":184,"previous":"M21-GAP-03147","next":"M21-GAP-03149"},"M21-GAP-03149":{"line":6404,"offset":1147382,"length":189,"previous":"M21-GAP-03148","next":"M21-GAP-03150"},"M21-GAP-03150":{"line":6405,"offset":1147571,"length":189,"previous":"M21-GAP-03149","next":"M21-GAP-03151"},"M21-GAP-03151":{"line":6406,"offset":1147760,"length":190,"previous":"M21-GAP-03150","next":"M21-GAP-03152"},"M21-GAP-03152":{"line":6407,"offset":1147950,"length":190,"previous":"M21-GAP-03151","next":"M21-GAP-03153"},"M21-GAP-03153":{"line":6408,"offset":1148140,"length":189,"previous":"M21-GAP-03152","next":"M21-GAP-03154"},"M21-GAP-03154":{"line":6409,"offset":1148329,"length":189,"previous":"M21-GAP-03153","next":"M21-GAP-03155"},"M21-GAP-03155":{"line":6410,"offset":1148518,"length":189,"previous":"M21-GAP-03154","next":"M21-GAP-03156"},"M21-GAP-03156":{"line":6411,"offset":1148707,"length":189,"previous":"M21-GAP-03155","next":"M21-GAP-03157"},"M21-GAP-03157":{"line":6412,"offset":1148896,"length":189,"previous":"M21-GAP-03156","next":"M21-GAP-03158"},"M21-GAP-03158":{"line":6413,"offset":1149085,"length":189,"previous":"M21-GAP-03157","next":"M21-GAP-03159"},"M21-GAP-03159":{"line":6414,"offset":1149274,"length":189,"previous":"M21-GAP-03158","next":"M21-GAP-03160"},"M21-GAP-03160":{"line":6415,"offset":1149463,"length":189,"previous":"M21-GAP-03159","next":"M21-GAP-03161"},"M21-GAP-03161":{"line":6416,"offset":1149652,"length":186,"previous":"M21-GAP-03160","next":"M21-GAP-03162"},"M21-GAP-03162":{"line":6417,"offset":1149838,"length":186,"previous":"M21-GAP-03161","next":"M21-GAP-03163"},"M21-GAP-03163":{"line":6418,"offset":1150024,"length":186,"previous":"M21-GAP-03162","next":"M21-GAP-03164"},"M21-GAP-03164":{"line":6419,"offset":1150210,"length":186,"previous":"M21-GAP-03163","next":"M21-GAP-03165"},"M21-GAP-03165":{"line":6420,"offset":1150396,"length":186,"previous":"M21-GAP-03164","next":"M21-GAP-03166"},"M21-GAP-03166":{"line":6421,"offset":1150582,"length":215,"previous":"M21-GAP-03165","next":"M21-GAP-03167"},"M21-GAP-03167":{"line":6422,"offset":1150797,"length":215,"previous":"M21-GAP-03166","next":"M21-GAP-03168"},"M21-GAP-03168":{"line":6423,"offset":1151012,"length":215,"previous":"M21-GAP-03167","next":"M21-GAP-03169"},"M21-GAP-03169":{"line":6424,"offset":1151227,"length":215,"previous":"M21-GAP-03168","next":"M21-GAP-03170"},"M21-GAP-03170":{"line":6425,"offset":1151442,"length":215,"previous":"M21-GAP-03169","next":"M21-GAP-03171"},"M21-GAP-03171":{"line":6426,"offset":1151657,"length":215,"previous":"M21-GAP-03170","next":"M21-GAP-03172"},"M21-GAP-03172":{"line":6427,"offset":1151872,"length":184,"previous":"M21-GAP-03171","next":"M21-GAP-03173"},"M21-GAP-03173":{"line":6428,"offset":1152056,"length":184,"previous":"M21-GAP-03172","next":"M21-GAP-03174"},"M21-GAP-03174":{"line":6429,"offset":1152240,"length":185,"previous":"M21-GAP-03173","next":"M21-GAP-03175"},"M21-GAP-03175":{"line":6430,"offset":1152425,"length":185,"previous":"M21-GAP-03174","next":"M21-GAP-03176"},"M21-GAP-03176":{"line":6431,"offset":1152610,"length":185,"previous":"M21-GAP-03175","next":"M21-GAP-03177"},"M21-GAP-03177":{"line":6432,"offset":1152795,"length":185,"previous":"M21-GAP-03176","next":"M21-GAP-03178"},"M21-GAP-03178":{"line":6433,"offset":1152980,"length":185,"previous":"M21-GAP-03177","next":"M21-GAP-03179"},"M21-GAP-03179":{"line":6434,"offset":1153165,"length":185,"previous":"M21-GAP-03178","next":"M21-GAP-03180"},"M21-GAP-03180":{"line":6435,"offset":1153350,"length":185,"previous":"M21-GAP-03179","next":"M21-GAP-03181"},"M21-GAP-03181":{"line":6436,"offset":1153535,"length":185,"previous":"M21-GAP-03180","next":"M21-GAP-03182"},"M21-GAP-03182":{"line":6437,"offset":1153720,"length":185,"previous":"M21-GAP-03181","next":"M21-GAP-03183"},"M21-GAP-03183":{"line":6438,"offset":1153905,"length":185,"previous":"M21-GAP-03182","next":"M21-GAP-03184"},"M21-GAP-03184":{"line":6439,"offset":1154090,"length":184,"previous":"M21-GAP-03183","next":"M21-GAP-03185"},"M21-GAP-03185":{"line":6440,"offset":1154274,"length":185,"previous":"M21-GAP-03184","next":"M21-GAP-03186"},"M21-GAP-03186":{"line":6441,"offset":1154459,"length":185,"previous":"M21-GAP-03185","next":"M21-GAP-03187"},"M21-GAP-03187":{"line":6442,"offset":1154644,"length":185,"previous":"M21-GAP-03186","next":"M21-GAP-03188"},"M21-GAP-03188":{"line":6443,"offset":1154829,"length":185,"previous":"M21-GAP-03187","next":"M21-GAP-03189"},"M21-GAP-03189":{"line":6444,"offset":1155014,"length":185,"previous":"M21-GAP-03188","next":"M21-GAP-03190"},"M21-GAP-03190":{"line":6445,"offset":1155199,"length":185,"previous":"M21-GAP-03189","next":"M21-GAP-03191"},"M21-GAP-03191":{"line":6446,"offset":1155384,"length":185,"previous":"M21-GAP-03190","next":"M21-GAP-03192"},"M21-GAP-03192":{"line":6447,"offset":1155569,"length":185,"previous":"M21-GAP-03191","next":"M21-GAP-03193"},"M21-GAP-03193":{"line":6448,"offset":1155754,"length":185,"previous":"M21-GAP-03192","next":"M21-GAP-03194"},"M21-GAP-03194":{"line":6449,"offset":1155939,"length":185,"previous":"M21-GAP-03193","next":"M21-GAP-03195"},"M21-GAP-03195":{"line":6450,"offset":1156124,"length":184,"previous":"M21-GAP-03194","next":"M21-GAP-03196"},"M21-GAP-03196":{"line":6451,"offset":1156308,"length":185,"previous":"M21-GAP-03195","next":"M21-GAP-03197"},"M21-GAP-03197":{"line":6452,"offset":1156493,"length":185,"previous":"M21-GAP-03196","next":"M21-GAP-03198"},"M21-GAP-03198":{"line":6453,"offset":1156678,"length":185,"previous":"M21-GAP-03197","next":"M21-GAP-03199"},"M21-GAP-03199":{"line":6454,"offset":1156863,"length":185,"previous":"M21-GAP-03198","next":"M21-GAP-03200"},"M21-GAP-03200":{"line":6455,"offset":1157048,"length":185,"previous":"M21-GAP-03199","next":"M21-GAP-03201"},"M21-GAP-03201":{"line":6456,"offset":1157233,"length":185,"previous":"M21-GAP-03200","next":"M21-GAP-03202"},"M21-GAP-03202":{"line":6457,"offset":1157418,"length":185,"previous":"M21-GAP-03201","next":"M21-GAP-03203"},"M21-GAP-03203":{"line":6458,"offset":1157603,"length":185,"previous":"M21-GAP-03202","next":"M21-GAP-03204"},"M21-GAP-03204":{"line":6459,"offset":1157788,"length":185,"previous":"M21-GAP-03203","next":"M21-GAP-03205"},"M21-GAP-03205":{"line":6460,"offset":1157973,"length":185,"previous":"M21-GAP-03204","next":"M21-GAP-03206"},"M21-GAP-03206":{"line":6461,"offset":1158158,"length":184,"previous":"M21-GAP-03205","next":"M21-GAP-03207"},"M21-GAP-03207":{"line":6462,"offset":1158342,"length":185,"previous":"M21-GAP-03206","next":"M21-GAP-03208"},"M21-GAP-03208":{"line":6463,"offset":1158527,"length":185,"previous":"M21-GAP-03207","next":"M21-GAP-03209"},"M21-GAP-03209":{"line":6464,"offset":1158712,"length":185,"previous":"M21-GAP-03208","next":"M21-GAP-03210"},"M21-GAP-03210":{"line":6465,"offset":1158897,"length":185,"previous":"M21-GAP-03209","next":"M21-GAP-03211"},"M21-GAP-03211":{"line":6466,"offset":1159082,"length":185,"previous":"M21-GAP-03210","next":"M21-GAP-03212"},"M21-GAP-03212":{"line":6467,"offset":1159267,"length":185,"previous":"M21-GAP-03211","next":"M21-GAP-03213"},"M21-GAP-03213":{"line":6468,"offset":1159452,"length":185,"previous":"M21-GAP-03212","next":"M21-GAP-03214"},"M21-GAP-03214":{"line":6469,"offset":1159637,"length":185,"previous":"M21-GAP-03213","next":"M21-GAP-03215"},"M21-GAP-03215":{"line":6470,"offset":1159822,"length":185,"previous":"M21-GAP-03214","next":"M21-GAP-03216"},"M21-GAP-03216":{"line":6471,"offset":1160007,"length":185,"previous":"M21-GAP-03215","next":"M21-GAP-03217"},"M21-GAP-03217":{"line":6472,"offset":1160192,"length":184,"previous":"M21-GAP-03216","next":"M21-GAP-03218"},"M21-GAP-03218":{"line":6473,"offset":1160376,"length":184,"previous":"M21-GAP-03217","next":"M21-GAP-03219"},"M21-GAP-03219":{"line":6474,"offset":1160560,"length":184,"previous":"M21-GAP-03218","next":"M21-GAP-03220"},"M21-GAP-03220":{"line":6475,"offset":1160744,"length":184,"previous":"M21-GAP-03219","next":"M21-GAP-03221"},"M21-GAP-03221":{"line":6476,"offset":1160928,"length":184,"previous":"M21-GAP-03220","next":"M21-GAP-03222"},"M21-GAP-03222":{"line":6477,"offset":1161112,"length":184,"previous":"M21-GAP-03221","next":"M21-GAP-03223"},"M21-GAP-03223":{"line":6478,"offset":1161296,"length":179,"previous":"M21-GAP-03222","next":"M21-GAP-03224"},"M21-GAP-03224":{"line":6479,"offset":1161475,"length":179,"previous":"M21-GAP-03223","next":"M21-GAP-03225"},"M21-GAP-03225":{"line":6480,"offset":1161654,"length":180,"previous":"M21-GAP-03224","next":"M21-GAP-03226"},"M21-GAP-03226":{"line":6481,"offset":1161834,"length":180,"previous":"M21-GAP-03225","next":"M21-GAP-03227"},"M21-GAP-03227":{"line":6482,"offset":1162014,"length":180,"previous":"M21-GAP-03226","next":"M21-GAP-03228"},"M21-GAP-03228":{"line":6483,"offset":1162194,"length":180,"previous":"M21-GAP-03227","next":"M21-GAP-03229"},"M21-GAP-03229":{"line":6484,"offset":1162374,"length":180,"previous":"M21-GAP-03228","next":"M21-GAP-03230"},"M21-GAP-03230":{"line":6485,"offset":1162554,"length":180,"previous":"M21-GAP-03229","next":"M21-GAP-03231"},"M21-GAP-03231":{"line":6486,"offset":1162734,"length":180,"previous":"M21-GAP-03230","next":"M21-GAP-03232"},"M21-GAP-03232":{"line":6487,"offset":1162914,"length":180,"previous":"M21-GAP-03231","next":"M21-GAP-03233"},"M21-GAP-03233":{"line":6488,"offset":1163094,"length":180,"previous":"M21-GAP-03232","next":"M21-GAP-03234"},"M21-GAP-03234":{"line":6489,"offset":1163274,"length":180,"previous":"M21-GAP-03233","next":"M21-GAP-03235"},"M21-GAP-03235":{"line":6490,"offset":1163454,"length":179,"previous":"M21-GAP-03234","next":"M21-GAP-03236"},"M21-GAP-03236":{"line":6491,"offset":1163633,"length":180,"previous":"M21-GAP-03235","next":"M21-GAP-03237"},"M21-GAP-03237":{"line":6492,"offset":1163813,"length":180,"previous":"M21-GAP-03236","next":"M21-GAP-03238"},"M21-GAP-03238":{"line":6493,"offset":1163993,"length":180,"previous":"M21-GAP-03237","next":"M21-GAP-03239"},"M21-GAP-03239":{"line":6494,"offset":1164173,"length":180,"previous":"M21-GAP-03238","next":"M21-GAP-03240"},"M21-GAP-03240":{"line":6495,"offset":1164353,"length":180,"previous":"M21-GAP-03239","next":"M21-GAP-03241"},"M21-GAP-03241":{"line":6496,"offset":1164533,"length":179,"previous":"M21-GAP-03240","next":"M21-GAP-03242"},"M21-GAP-03242":{"line":6497,"offset":1164712,"length":179,"previous":"M21-GAP-03241","next":"M21-GAP-03243"},"M21-GAP-03243":{"line":6498,"offset":1164891,"length":179,"previous":"M21-GAP-03242","next":"M21-GAP-03244"},"M21-GAP-03244":{"line":6499,"offset":1165070,"length":179,"previous":"M21-GAP-03243","next":"M21-GAP-03245"},"M21-GAP-03245":{"line":6500,"offset":1165249,"length":179,"previous":"M21-GAP-03244","next":"M21-GAP-03246"},"M21-GAP-03246":{"line":6501,"offset":1165428,"length":179,"previous":"M21-GAP-03245","next":"M21-GAP-03247"},"M21-GAP-03247":{"line":6502,"offset":1165607,"length":179,"previous":"M21-GAP-03246","next":"M21-GAP-03248"},"M21-GAP-03248":{"line":6503,"offset":1165786,"length":173,"previous":"M21-GAP-03247","next":"M21-GAP-03249"},"M21-GAP-03249":{"line":6504,"offset":1165959,"length":173,"previous":"M21-GAP-03248","next":"M21-GAP-03250"},"M21-GAP-03250":{"line":6505,"offset":1166132,"length":174,"previous":"M21-GAP-03249","next":"M21-GAP-03251"},"M21-GAP-03251":{"line":6506,"offset":1166306,"length":174,"previous":"M21-GAP-03250","next":"M21-GAP-03252"},"M21-GAP-03252":{"line":6507,"offset":1166480,"length":174,"previous":"M21-GAP-03251","next":"M21-GAP-03253"},"M21-GAP-03253":{"line":6508,"offset":1166654,"length":174,"previous":"M21-GAP-03252","next":"M21-GAP-03254"},"M21-GAP-03254":{"line":6509,"offset":1166828,"length":174,"previous":"M21-GAP-03253","next":"M21-GAP-03255"},"M21-GAP-03255":{"line":6510,"offset":1167002,"length":174,"previous":"M21-GAP-03254","next":"M21-GAP-03256"},"M21-GAP-03256":{"line":6511,"offset":1167176,"length":174,"previous":"M21-GAP-03255","next":"M21-GAP-03257"},"M21-GAP-03257":{"line":6512,"offset":1167350,"length":174,"previous":"M21-GAP-03256","next":"M21-GAP-03258"},"M21-GAP-03258":{"line":6513,"offset":1167524,"length":174,"previous":"M21-GAP-03257","next":"M21-GAP-03259"},"M21-GAP-03259":{"line":6514,"offset":1167698,"length":174,"previous":"M21-GAP-03258","next":"M21-GAP-03260"},"M21-GAP-03260":{"line":6515,"offset":1167872,"length":173,"previous":"M21-GAP-03259","next":"M21-GAP-03261"},"M21-GAP-03261":{"line":6516,"offset":1168045,"length":174,"previous":"M21-GAP-03260","next":"M21-GAP-03262"},"M21-GAP-03262":{"line":6517,"offset":1168219,"length":174,"previous":"M21-GAP-03261","next":"M21-GAP-03263"},"M21-GAP-03263":{"line":6518,"offset":1168393,"length":174,"previous":"M21-GAP-03262","next":"M21-GAP-03264"},"M21-GAP-03264":{"line":6519,"offset":1168567,"length":174,"previous":"M21-GAP-03263","next":"M21-GAP-03265"},"M21-GAP-03265":{"line":6520,"offset":1168741,"length":174,"previous":"M21-GAP-03264","next":"M21-GAP-03266"},"M21-GAP-03266":{"line":6521,"offset":1168915,"length":174,"previous":"M21-GAP-03265","next":"M21-GAP-03267"},"M21-GAP-03267":{"line":6522,"offset":1169089,"length":174,"previous":"M21-GAP-03266","next":"M21-GAP-03268"},"M21-GAP-03268":{"line":6523,"offset":1169263,"length":174,"previous":"M21-GAP-03267","next":"M21-GAP-03269"},"M21-GAP-03269":{"line":6524,"offset":1169437,"length":174,"previous":"M21-GAP-03268","next":"M21-GAP-03270"},"M21-GAP-03270":{"line":6525,"offset":1169611,"length":174,"previous":"M21-GAP-03269","next":"M21-GAP-03271"},"M21-GAP-03271":{"line":6526,"offset":1169785,"length":173,"previous":"M21-GAP-03270","next":"M21-GAP-03272"},"M21-GAP-03272":{"line":6527,"offset":1169958,"length":174,"previous":"M21-GAP-03271","next":"M21-GAP-03273"},"M21-GAP-03273":{"line":6528,"offset":1170132,"length":174,"previous":"M21-GAP-03272","next":"M21-GAP-03274"},"M21-GAP-03274":{"line":6529,"offset":1170306,"length":174,"previous":"M21-GAP-03273","next":"M21-GAP-03275"},"M21-GAP-03275":{"line":6530,"offset":1170480,"length":173,"previous":"M21-GAP-03274","next":"M21-GAP-03276"},"M21-GAP-03276":{"line":6531,"offset":1170653,"length":173,"previous":"M21-GAP-03275","next":"M21-GAP-03277"},"M21-GAP-03277":{"line":6532,"offset":1170826,"length":173,"previous":"M21-GAP-03276","next":"M21-GAP-03278"},"M21-GAP-03278":{"line":6533,"offset":1170999,"length":173,"previous":"M21-GAP-03277","next":"M21-GAP-03279"},"M21-GAP-03279":{"line":6534,"offset":1171172,"length":173,"previous":"M21-GAP-03278","next":"M21-GAP-03280"},"M21-GAP-03280":{"line":6535,"offset":1171345,"length":173,"previous":"M21-GAP-03279","next":"M21-GAP-03281"},"M21-GAP-03281":{"line":6536,"offset":1171518,"length":177,"previous":"M21-GAP-03280","next":"M21-GAP-03282"},"M21-GAP-03282":{"line":6537,"offset":1171695,"length":180,"previous":"M21-GAP-03281","next":"M21-GAP-03283"},"M21-GAP-03283":{"line":6538,"offset":1171875,"length":187,"previous":"M21-GAP-03282","next":"M21-GAP-03284"},"M21-GAP-03284":{"line":6539,"offset":1172062,"length":182,"previous":"M21-GAP-03283","next":"M21-GAP-03285"},"M21-GAP-03285":{"line":6540,"offset":1172244,"length":202,"previous":"M21-GAP-03284","next":"M21-GAP-03286"},"M21-GAP-03286":{"line":6541,"offset":1172446,"length":204,"previous":"M21-GAP-03285","next":"M21-GAP-03287"},"M21-GAP-03287":{"line":6542,"offset":1172650,"length":208,"previous":"M21-GAP-03286","next":"M21-GAP-03288"},"M21-GAP-03288":{"line":6543,"offset":1172858,"length":198,"previous":"M21-GAP-03287","next":"M21-GAP-03289"},"M21-GAP-03289":{"line":6544,"offset":1173056,"length":195,"previous":"M21-GAP-03288","next":"M21-GAP-03290"},"M21-GAP-03290":{"line":6545,"offset":1173251,"length":197,"previous":"M21-GAP-03289","next":"M21-GAP-03291"},"M21-GAP-03291":{"line":6546,"offset":1173448,"length":192,"previous":"M21-GAP-03290","next":"M21-GAP-03292"},"M21-GAP-03292":{"line":6547,"offset":1173640,"length":205,"previous":"M21-GAP-03291","next":"M21-GAP-03293"},"M21-GAP-03293":{"line":6548,"offset":1173845,"length":195,"previous":"M21-GAP-03292","next":"M21-GAP-03294"},"M21-GAP-03294":{"line":6549,"offset":1174040,"length":194,"previous":"M21-GAP-03293","next":"M21-GAP-03295"},"M21-GAP-03295":{"line":6550,"offset":1174234,"length":197,"previous":"M21-GAP-03294","next":"M21-GAP-03296"},"M21-GAP-03296":{"line":6551,"offset":1174431,"length":192,"previous":"M21-GAP-03295","next":"M21-GAP-03297"},"M21-GAP-03297":{"line":6552,"offset":1174623,"length":193,"previous":"M21-GAP-03296","next":"M21-GAP-03298"},"M21-GAP-03298":{"line":6553,"offset":1174816,"length":192,"previous":"M21-GAP-03297","next":"M21-GAP-03299"},"M21-GAP-03299":{"line":6554,"offset":1175008,"length":204,"previous":"M21-GAP-03298","next":"M21-GAP-03300"},"M21-GAP-03300":{"line":6555,"offset":1175212,"length":207,"previous":"M21-GAP-03299","next":"M21-GAP-03301"},"M21-GAP-03301":{"line":6556,"offset":1175419,"length":199,"previous":"M21-GAP-03300","next":"M21-GAP-03302"},"M21-GAP-03302":{"line":6557,"offset":1175618,"length":192,"previous":"M21-GAP-03301","next":"M21-GAP-03303"},"M21-GAP-03303":{"line":6558,"offset":1175810,"length":193,"previous":"M21-GAP-03302","next":"M21-GAP-03304"},"M21-GAP-03304":{"line":6559,"offset":1176003,"length":197,"previous":"M21-GAP-03303","next":"M21-GAP-03305"},"M21-GAP-03305":{"line":6560,"offset":1176200,"length":208,"previous":"M21-GAP-03304","next":"M21-GAP-03306"},"M21-GAP-03306":{"line":6561,"offset":1176408,"length":205,"previous":"M21-GAP-03305","next":"M21-GAP-03307"},"M21-GAP-03307":{"line":6562,"offset":1176613,"length":203,"previous":"M21-GAP-03306","next":"M21-GAP-03308"},"M21-GAP-03308":{"line":6563,"offset":1176816,"length":201,"previous":"M21-GAP-03307","next":"M21-GAP-03309"},"M21-GAP-03309":{"line":6564,"offset":1177017,"length":204,"previous":"M21-GAP-03308","next":"M21-GAP-03310"},"M21-GAP-03310":{"line":6565,"offset":1177221,"length":198,"previous":"M21-GAP-03309","next":"M21-GAP-03311"},"M21-GAP-03311":{"line":6566,"offset":1177419,"length":192,"previous":"M21-GAP-03310","next":"M21-GAP-03312"},"M21-GAP-03312":{"line":6567,"offset":1177611,"length":195,"previous":"M21-GAP-03311","next":"M21-GAP-03313"},"M21-GAP-03313":{"line":6568,"offset":1177806,"length":207,"previous":"M21-GAP-03312","next":"M21-GAP-03314"},"M21-GAP-03314":{"line":6569,"offset":1178013,"length":197,"previous":"M21-GAP-03313","next":"M21-GAP-03315"},"M21-GAP-03315":{"line":6570,"offset":1178210,"length":196,"previous":"M21-GAP-03314","next":"M21-GAP-03316"},"M21-GAP-03316":{"line":6571,"offset":1178406,"length":196,"previous":"M21-GAP-03315","next":"M21-GAP-03317"},"M21-GAP-03317":{"line":6572,"offset":1178602,"length":195,"previous":"M21-GAP-03316","next":"M21-GAP-03318"},"M21-GAP-03318":{"line":6573,"offset":1178797,"length":197,"previous":"M21-GAP-03317","next":"M21-GAP-03319"},"M21-GAP-03319":{"line":6574,"offset":1178994,"length":200,"previous":"M21-GAP-03318","next":"M21-GAP-03320"},"M21-GAP-03320":{"line":6575,"offset":1179194,"length":193,"previous":"M21-GAP-03319","next":"M21-GAP-03321"},"M21-GAP-03321":{"line":6576,"offset":1179387,"length":202,"previous":"M21-GAP-03320","next":"M21-GAP-03322"},"M21-GAP-03322":{"line":6577,"offset":1179589,"length":191,"previous":"M21-GAP-03321","next":"M21-GAP-03323"},"M21-GAP-03323":{"line":6578,"offset":1179780,"length":196,"previous":"M21-GAP-03322","next":"M21-GAP-03324"},"M21-GAP-03324":{"line":6579,"offset":1179976,"length":199,"previous":"M21-GAP-03323","next":"M21-GAP-03325"},"M21-GAP-03325":{"line":6580,"offset":1180175,"length":198,"previous":"M21-GAP-03324","next":"M21-GAP-03326"},"M21-GAP-03326":{"line":6581,"offset":1180373,"length":183,"previous":"M21-GAP-03325","next":"M21-GAP-03327"},"M21-GAP-03327":{"line":6582,"offset":1180556,"length":180,"previous":"M21-GAP-03326","next":"M21-GAP-03328"},"M21-GAP-03328":{"line":6583,"offset":1180736,"length":197,"previous":"M21-GAP-03327","next":"M21-GAP-03329"},"M21-GAP-03329":{"line":6584,"offset":1180933,"length":200,"previous":"M21-GAP-03328","next":"M21-GAP-03330"},"M21-GAP-03330":{"line":6585,"offset":1181133,"length":200,"previous":"M21-GAP-03329","next":"M21-GAP-03331"},"M21-GAP-03331":{"line":6586,"offset":1181333,"length":203,"previous":"M21-GAP-03330","next":"M21-GAP-03332"},"M21-GAP-03332":{"line":6587,"offset":1181536,"length":202,"previous":"M21-GAP-03331","next":"M21-GAP-03333"},"M21-GAP-03333":{"line":6588,"offset":1181738,"length":207,"previous":"M21-GAP-03332","next":"M21-GAP-03334"},"M21-GAP-03334":{"line":6589,"offset":1181945,"length":208,"previous":"M21-GAP-03333","next":"M21-GAP-03335"},"M21-GAP-03335":{"line":6590,"offset":1182153,"length":201,"previous":"M21-GAP-03334","next":"M21-GAP-03336"},"M21-GAP-03336":{"line":6591,"offset":1182354,"length":205,"previous":"M21-GAP-03335","next":"M21-GAP-03337"},"M21-GAP-03337":{"line":6592,"offset":1182559,"length":201,"previous":"M21-GAP-03336","next":"M21-GAP-03338"},"M21-GAP-03338":{"line":6593,"offset":1182760,"length":198,"previous":"M21-GAP-03337","next":"M21-GAP-03339"},"M21-GAP-03339":{"line":6594,"offset":1182958,"length":209,"previous":"M21-GAP-03338","next":"M21-GAP-03340"},"M21-GAP-03340":{"line":6595,"offset":1183167,"length":203,"previous":"M21-GAP-03339","next":"M21-GAP-03341"},"M21-GAP-03341":{"line":6596,"offset":1183370,"length":180,"previous":"M21-GAP-03340","next":"M21-GAP-03342"},"M21-GAP-03342":{"line":6597,"offset":1183550,"length":181,"previous":"M21-GAP-03341","next":"M21-GAP-03343"},"M21-GAP-03343":{"line":6598,"offset":1183731,"length":182,"previous":"M21-GAP-03342","next":"M21-GAP-03344"},"M21-GAP-03344":{"line":6599,"offset":1183913,"length":181,"previous":"M21-GAP-03343","next":"M21-GAP-03345"},"M21-GAP-03345":{"line":6600,"offset":1184094,"length":196,"previous":"M21-GAP-03344","next":"M21-GAP-03346"},"M21-GAP-03346":{"line":6601,"offset":1184290,"length":192,"previous":"M21-GAP-03345","next":"M21-GAP-03347"},"M21-GAP-03347":{"line":6602,"offset":1184482,"length":192,"previous":"M21-GAP-03346","next":"M21-GAP-03348"},"M21-GAP-03348":{"line":6603,"offset":1184674,"length":192,"previous":"M21-GAP-03347","next":"M21-GAP-03349"},"M21-GAP-03349":{"line":6604,"offset":1184866,"length":196,"previous":"M21-GAP-03348","next":"M21-GAP-03350"},"M21-GAP-03350":{"line":6605,"offset":1185062,"length":196,"previous":"M21-GAP-03349","next":"M21-GAP-03351"},"M21-GAP-03351":{"line":6606,"offset":1185258,"length":197,"previous":"M21-GAP-03350","next":"M21-GAP-03352"},"M21-GAP-03352":{"line":6607,"offset":1185455,"length":198,"previous":"M21-GAP-03351","next":"M21-GAP-03353"},"M21-GAP-03353":{"line":6608,"offset":1185653,"length":194,"previous":"M21-GAP-03352","next":"M21-GAP-03354"},"M21-GAP-03354":{"line":6609,"offset":1185847,"length":194,"previous":"M21-GAP-03353","next":"M21-GAP-03355"},"M21-GAP-03355":{"line":6610,"offset":1186041,"length":194,"previous":"M21-GAP-03354","next":"M21-GAP-03356"},"M21-GAP-03356":{"line":6611,"offset":1186235,"length":197,"previous":"M21-GAP-03355","next":"M21-GAP-03357"},"M21-GAP-03357":{"line":6612,"offset":1186432,"length":193,"previous":"M21-GAP-03356","next":"M21-GAP-03358"},"M21-GAP-03358":{"line":6613,"offset":1186625,"length":193,"previous":"M21-GAP-03357","next":"M21-GAP-03359"},"M21-GAP-03359":{"line":6614,"offset":1186818,"length":196,"previous":"M21-GAP-03358","next":"M21-GAP-03360"},"M21-GAP-03360":{"line":6615,"offset":1187014,"length":193,"previous":"M21-GAP-03359","next":"M21-GAP-03361"},"M21-GAP-03361":{"line":6616,"offset":1187207,"length":197,"previous":"M21-GAP-03360","next":"M21-GAP-03362"},"M21-GAP-03362":{"line":6617,"offset":1187404,"length":195,"previous":"M21-GAP-03361","next":"M21-GAP-03363"},"M21-GAP-03363":{"line":6618,"offset":1187599,"length":201,"previous":"M21-GAP-03362","next":"M21-GAP-03364"},"M21-GAP-03364":{"line":6619,"offset":1187800,"length":197,"previous":"M21-GAP-03363","next":"M21-GAP-03365"},"M21-GAP-03365":{"line":6620,"offset":1187997,"length":197,"previous":"M21-GAP-03364","next":"M21-GAP-03366"},"M21-GAP-03366":{"line":6621,"offset":1188194,"length":197,"previous":"M21-GAP-03365","next":"M21-GAP-03367"},"M21-GAP-03367":{"line":6622,"offset":1188391,"length":197,"previous":"M21-GAP-03366","next":"M21-GAP-03368"},"M21-GAP-03368":{"line":6623,"offset":1188588,"length":186,"previous":"M21-GAP-03367","next":"M21-GAP-03369"},"M21-GAP-03369":{"line":6624,"offset":1188774,"length":200,"previous":"M21-GAP-03368","next":"M21-GAP-03370"},"M21-GAP-03370":{"line":6625,"offset":1188974,"length":189,"previous":"M21-GAP-03369","next":"M21-GAP-03371"},"M21-GAP-03371":{"line":6626,"offset":1189163,"length":199,"previous":"M21-GAP-03370","next":"M21-GAP-03372"},"M21-GAP-03372":{"line":6627,"offset":1189362,"length":188,"previous":"M21-GAP-03371","next":"M21-GAP-03373"},"M21-GAP-03373":{"line":6628,"offset":1189550,"length":181,"previous":"M21-GAP-03372","next":"M21-GAP-03374"},"M21-GAP-03374":{"line":6629,"offset":1189731,"length":185,"previous":"M21-GAP-03373","next":"M21-GAP-03375"},"M21-GAP-03375":{"line":6630,"offset":1189916,"length":192,"previous":"M21-GAP-03374","next":"M21-GAP-03376"},"M21-GAP-03376":{"line":6631,"offset":1190108,"length":181,"previous":"M21-GAP-03375","next":"M21-GAP-03377"},"M21-GAP-03377":{"line":6632,"offset":1190289,"length":169,"previous":"M21-GAP-03376","next":"M21-GAP-03378"},"M21-GAP-03378":{"line":6633,"offset":1190458,"length":178,"previous":"M21-GAP-03377","next":"M21-GAP-03379"},"M21-GAP-03379":{"line":6634,"offset":1190636,"length":169,"previous":"M21-GAP-03378","next":"M21-GAP-03380"},"M21-GAP-03380":{"line":6635,"offset":1190805,"length":168,"previous":"M21-GAP-03379","next":"M21-GAP-03381"},"M21-GAP-03381":{"line":6636,"offset":1190973,"length":175,"previous":"M21-GAP-03380","next":"M21-GAP-03382"},"M21-GAP-03382":{"line":6637,"offset":1191148,"length":187,"previous":"M21-GAP-03381","next":"M21-GAP-03383"},"M21-GAP-03383":{"line":6638,"offset":1191335,"length":177,"previous":"M21-GAP-03382","next":"M21-GAP-03384"},"M21-GAP-03384":{"line":6639,"offset":1191512,"length":183,"previous":"M21-GAP-03383","next":"M21-GAP-03385"},"M21-GAP-03385":{"line":6640,"offset":1191695,"length":182,"previous":"M21-GAP-03384","next":"M21-GAP-03386"},"M21-GAP-03386":{"line":6641,"offset":1191877,"length":170,"previous":"M21-GAP-03385","next":"M21-GAP-03387"},"M21-GAP-03387":{"line":6642,"offset":1192047,"length":169,"previous":"M21-GAP-03386","next":"M21-GAP-03388"},"M21-GAP-03388":{"line":6643,"offset":1192216,"length":179,"previous":"M21-GAP-03387","next":"M21-GAP-03389"},"M21-GAP-03389":{"line":6644,"offset":1192395,"length":165,"previous":"M21-GAP-03388","next":"M21-GAP-03390"},"M21-GAP-03390":{"line":6645,"offset":1192560,"length":166,"previous":"M21-GAP-03389","next":"M21-GAP-03391"},"M21-GAP-03391":{"line":6646,"offset":1192726,"length":184,"previous":"M21-GAP-03390","next":"M21-GAP-03392"},"M21-GAP-03392":{"line":6647,"offset":1192910,"length":188,"previous":"M21-GAP-03391","next":"M21-GAP-03393"},"M21-GAP-03393":{"line":6648,"offset":1193098,"length":180,"previous":"M21-GAP-03392","next":"M21-GAP-03394"},"M21-GAP-03394":{"line":6649,"offset":1193278,"length":198,"previous":"M21-GAP-03393","next":"M21-GAP-03395"},"M21-GAP-03395":{"line":6650,"offset":1193476,"length":180,"previous":"M21-GAP-03394","next":"M21-GAP-03396"},"M21-GAP-03396":{"line":6651,"offset":1193656,"length":187,"previous":"M21-GAP-03395","next":"M21-GAP-03397"},"M21-GAP-03397":{"line":6652,"offset":1193843,"length":184,"previous":"M21-GAP-03396","next":"M21-GAP-03398"},"M21-GAP-03398":{"line":6653,"offset":1194027,"length":179,"previous":"M21-GAP-03397","next":"M21-GAP-03399"},"M21-GAP-03399":{"line":6654,"offset":1194206,"length":179,"previous":"M21-GAP-03398","next":"M21-GAP-03400"},"M21-GAP-03400":{"line":6655,"offset":1194385,"length":164,"previous":"M21-GAP-03399","next":"M21-GAP-03401"},"M21-GAP-03401":{"line":6656,"offset":1194549,"length":166,"previous":"M21-GAP-03400","next":"M21-GAP-03402"},"M21-GAP-03402":{"line":6657,"offset":1194715,"length":184,"previous":"M21-GAP-03401","next":"M21-GAP-03403"},"M21-GAP-03403":{"line":6658,"offset":1194899,"length":178,"previous":"M21-GAP-03402","next":"M21-GAP-03404"},"M21-GAP-03404":{"line":6659,"offset":1195077,"length":184,"previous":"M21-GAP-03403","next":"M21-GAP-03405"},"M21-GAP-03405":{"line":6660,"offset":1195261,"length":180,"previous":"M21-GAP-03404","next":"M21-GAP-03406"},"M21-GAP-03406":{"line":6661,"offset":1195441,"length":189,"previous":"M21-GAP-03405","next":"M21-GAP-03407"},"M21-GAP-03407":{"line":6662,"offset":1195630,"length":173,"previous":"M21-GAP-03406","next":"M21-GAP-03408"},"M21-GAP-03408":{"line":6663,"offset":1195803,"length":189,"previous":"M21-GAP-03407","next":"M21-GAP-03409"},"M21-GAP-03409":{"line":6664,"offset":1195992,"length":187,"previous":"M21-GAP-03408","next":"M21-GAP-03410"},"M21-GAP-03410":{"line":6665,"offset":1196179,"length":190,"previous":"M21-GAP-03409","next":"M21-GAP-03411"},"M21-GAP-03411":{"line":6666,"offset":1196369,"length":182,"previous":"M21-GAP-03410","next":"M21-GAP-03412"},"M21-GAP-03412":{"line":6667,"offset":1196551,"length":171,"previous":"M21-GAP-03411","next":"M21-GAP-03413"},"M21-GAP-03413":{"line":6668,"offset":1196722,"length":173,"previous":"M21-GAP-03412","next":"M21-GAP-03414"},"M21-GAP-03414":{"line":6669,"offset":1196895,"length":176,"previous":"M21-GAP-03413","next":"M21-GAP-03415"},"M21-GAP-03415":{"line":6670,"offset":1197071,"length":181,"previous":"M21-GAP-03414","next":"M21-GAP-03416"},"M21-GAP-03416":{"line":6671,"offset":1197252,"length":179,"previous":"M21-GAP-03415","next":"M21-GAP-03417"},"M21-GAP-03417":{"line":6672,"offset":1197431,"length":187,"previous":"M21-GAP-03416","next":"M21-GAP-03418"},"M21-GAP-03418":{"line":6673,"offset":1197618,"length":179,"previous":"M21-GAP-03417","next":"M21-GAP-03419"},"M21-GAP-03419":{"line":6674,"offset":1197797,"length":186,"previous":"M21-GAP-03418","next":"M21-GAP-03420"},"M21-GAP-03420":{"line":6675,"offset":1197983,"length":183,"previous":"M21-GAP-03419","next":"M21-GAP-03421"},"M21-GAP-03421":{"line":6676,"offset":1198166,"length":183,"previous":"M21-GAP-03420","next":"M21-GAP-03422"},"M21-GAP-03422":{"line":6677,"offset":1198349,"length":183,"previous":"M21-GAP-03421","next":"M21-GAP-03423"},"M21-GAP-03423":{"line":6678,"offset":1198532,"length":185,"previous":"M21-GAP-03422","next":"M21-GAP-03424"},"M21-GAP-03424":{"line":6679,"offset":1198717,"length":183,"previous":"M21-GAP-03423","next":"M21-GAP-03425"},"M21-GAP-03425":{"line":6680,"offset":1198900,"length":186,"previous":"M21-GAP-03424","next":"M21-GAP-03426"},"M21-GAP-03426":{"line":6681,"offset":1199086,"length":186,"previous":"M21-GAP-03425","next":"M21-GAP-03427"},"M21-GAP-03427":{"line":6682,"offset":1199272,"length":173,"previous":"M21-GAP-03426","next":"M21-GAP-03428"},"M21-GAP-03428":{"line":6683,"offset":1199445,"length":195,"previous":"M21-GAP-03427","next":"M21-GAP-03429"},"M21-GAP-03429":{"line":6684,"offset":1199640,"length":198,"previous":"M21-GAP-03428","next":"M21-GAP-03430"},"M21-GAP-03430":{"line":6685,"offset":1199838,"length":198,"previous":"M21-GAP-03429","next":"M21-GAP-03431"},"M21-GAP-03431":{"line":6686,"offset":1200036,"length":196,"previous":"M21-GAP-03430","next":"M21-GAP-03432"},"M21-GAP-03432":{"line":6687,"offset":1200232,"length":198,"previous":"M21-GAP-03431","next":"M21-GAP-03433"},"M21-GAP-03433":{"line":6688,"offset":1200430,"length":197,"previous":"M21-GAP-03432","next":"M21-GAP-03434"},"M21-GAP-03434":{"line":6689,"offset":1200627,"length":213,"previous":"M21-GAP-03433","next":"M21-GAP-03435"},"M21-GAP-03435":{"line":6690,"offset":1200840,"length":202,"previous":"M21-GAP-03434","next":"M21-GAP-03436"},"M21-GAP-03436":{"line":6691,"offset":1201042,"length":216,"previous":"M21-GAP-03435","next":"M21-GAP-03437"},"M21-GAP-03437":{"line":6692,"offset":1201258,"length":205,"previous":"M21-GAP-03436","next":"M21-GAP-03438"},"M21-GAP-03438":{"line":6693,"offset":1201463,"length":215,"previous":"M21-GAP-03437","next":"M21-GAP-03439"},"M21-GAP-03439":{"line":6694,"offset":1201678,"length":204,"previous":"M21-GAP-03438","next":"M21-GAP-03440"},"M21-GAP-03440":{"line":6695,"offset":1201882,"length":201,"previous":"M21-GAP-03439","next":"M21-GAP-03441"},"M21-GAP-03441":{"line":6696,"offset":1202083,"length":208,"previous":"M21-GAP-03440","next":"M21-GAP-03442"},"M21-GAP-03442":{"line":6697,"offset":1202291,"length":197,"previous":"M21-GAP-03441","next":"M21-GAP-03443"},"M21-GAP-03443":{"line":6698,"offset":1202488,"length":192,"previous":"M21-GAP-03442","next":"M21-GAP-03444"},"M21-GAP-03444":{"line":6699,"offset":1202680,"length":196,"previous":"M21-GAP-03443","next":"M21-GAP-03445"},"M21-GAP-03445":{"line":6700,"offset":1202876,"length":194,"previous":"M21-GAP-03444","next":"M21-GAP-03446"},"M21-GAP-03446":{"line":6701,"offset":1203070,"length":194,"previous":"M21-GAP-03445","next":"M21-GAP-03447"},"M21-GAP-03447":{"line":6702,"offset":1203264,"length":195,"previous":"M21-GAP-03446","next":"M21-GAP-03448"},"M21-GAP-03448":{"line":6703,"offset":1203459,"length":195,"previous":"M21-GAP-03447","next":"M21-GAP-03449"},"M21-GAP-03449":{"line":6704,"offset":1203654,"length":200,"previous":"M21-GAP-03448","next":"M21-GAP-03450"},"M21-GAP-03450":{"line":6705,"offset":1203854,"length":196,"previous":"M21-GAP-03449","next":"M21-GAP-03451"},"M21-GAP-03451":{"line":6706,"offset":1204050,"length":195,"previous":"M21-GAP-03450","next":"M21-GAP-03452"},"M21-GAP-03452":{"line":6707,"offset":1204245,"length":211,"previous":"M21-GAP-03451","next":"M21-GAP-03453"},"M21-GAP-03453":{"line":6708,"offset":1204456,"length":200,"previous":"M21-GAP-03452","next":"M21-GAP-03454"},"M21-GAP-03454":{"line":6709,"offset":1204656,"length":214,"previous":"M21-GAP-03453","next":"M21-GAP-03455"},"M21-GAP-03455":{"line":6710,"offset":1204870,"length":203,"previous":"M21-GAP-03454","next":"M21-GAP-03456"},"M21-GAP-03456":{"line":6711,"offset":1205073,"length":213,"previous":"M21-GAP-03455","next":"M21-GAP-03457"},"M21-GAP-03457":{"line":6712,"offset":1205286,"length":202,"previous":"M21-GAP-03456","next":"M21-GAP-03458"},"M21-GAP-03458":{"line":6713,"offset":1205488,"length":206,"previous":"M21-GAP-03457","next":"M21-GAP-03459"},"M21-GAP-03459":{"line":6714,"offset":1205694,"length":195,"previous":"M21-GAP-03458","next":"M21-GAP-03460"},"M21-GAP-03460":{"line":6715,"offset":1205889,"length":180,"previous":"M21-GAP-03459","next":"M21-GAP-03461"},"M21-GAP-03461":{"line":6716,"offset":1206069,"length":171,"previous":"M21-GAP-03460","next":"M21-GAP-03462"},"M21-GAP-03462":{"line":6717,"offset":1206240,"length":172,"previous":"M21-GAP-03461","next":"M21-GAP-03463"},"M21-GAP-03463":{"line":6718,"offset":1206412,"length":163,"previous":"M21-GAP-03462","next":"M21-GAP-03464"},"M21-GAP-03464":{"line":6719,"offset":1206575,"length":186,"previous":"M21-GAP-03463","next":"M21-GAP-03465"},"M21-GAP-03465":{"line":6720,"offset":1206761,"length":180,"previous":"M21-GAP-03464","next":"M21-GAP-03466"},"M21-GAP-03466":{"line":6721,"offset":1206941,"length":167,"previous":"M21-GAP-03465","next":"M21-GAP-03467"},"M21-GAP-03467":{"line":6722,"offset":1207108,"length":167,"previous":"M21-GAP-03466","next":"M21-GAP-03468"},"M21-GAP-03468":{"line":6723,"offset":1207275,"length":172,"previous":"M21-GAP-03467","next":"M21-GAP-03469"},"M21-GAP-03469":{"line":6724,"offset":1207447,"length":181,"previous":"M21-GAP-03468","next":"M21-GAP-03470"},"M21-GAP-03470":{"line":6725,"offset":1207628,"length":164,"previous":"M21-GAP-03469","next":"M21-GAP-03471"},"M21-GAP-03471":{"line":6726,"offset":1207792,"length":168,"previous":"M21-GAP-03470","next":"M21-GAP-03472"},"M21-GAP-03472":{"line":6727,"offset":1207960,"length":175,"previous":"M21-GAP-03471","next":"M21-GAP-03473"},"M21-GAP-03473":{"line":6728,"offset":1208135,"length":176,"previous":"M21-GAP-03472","next":"M21-GAP-03474"},"M21-GAP-03474":{"line":6729,"offset":1208311,"length":175,"previous":"M21-GAP-03473","next":"M21-GAP-03475"},"M21-GAP-03475":{"line":6730,"offset":1208486,"length":177,"previous":"M21-GAP-03474","next":"M21-GAP-03476"},"M21-GAP-03476":{"line":6731,"offset":1208663,"length":178,"previous":"M21-GAP-03475","next":"M21-GAP-03477"},"M21-GAP-03477":{"line":6732,"offset":1208841,"length":179,"previous":"M21-GAP-03476","next":"M21-GAP-03478"},"M21-GAP-03478":{"line":6733,"offset":1209020,"length":181,"previous":"M21-GAP-03477","next":"M21-GAP-03479"},"M21-GAP-03479":{"line":6734,"offset":1209201,"length":188,"previous":"M21-GAP-03478","next":"M21-GAP-03480"},"M21-GAP-03480":{"line":6735,"offset":1209389,"length":186,"previous":"M21-GAP-03479","next":"M21-GAP-03481"},"M21-GAP-03481":{"line":6736,"offset":1209575,"length":187,"previous":"M21-GAP-03480","next":"M21-GAP-03482"},"M21-GAP-03482":{"line":6737,"offset":1209762,"length":198,"previous":"M21-GAP-03481","next":"M21-GAP-03483"},"M21-GAP-03483":{"line":6738,"offset":1209960,"length":187,"previous":"M21-GAP-03482","next":"M21-GAP-03484"},"M21-GAP-03484":{"line":6739,"offset":1210147,"length":201,"previous":"M21-GAP-03483","next":"M21-GAP-03485"},"M21-GAP-03485":{"line":6740,"offset":1210348,"length":190,"previous":"M21-GAP-03484","next":"M21-GAP-03486"},"M21-GAP-03486":{"line":6741,"offset":1210538,"length":200,"previous":"M21-GAP-03485","next":"M21-GAP-03487"},"M21-GAP-03487":{"line":6742,"offset":1210738,"length":189,"previous":"M21-GAP-03486","next":"M21-GAP-03488"},"M21-GAP-03488":{"line":6743,"offset":1210927,"length":193,"previous":"M21-GAP-03487","next":"M21-GAP-03489"},"M21-GAP-03489":{"line":6744,"offset":1211120,"length":182,"previous":"M21-GAP-03488","next":"M21-GAP-03490"},"M21-GAP-03490":{"line":6745,"offset":1211302,"length":171,"previous":"M21-GAP-03489","next":"M21-GAP-03491"},"M21-GAP-03491":{"line":6746,"offset":1211473,"length":176,"previous":"M21-GAP-03490","next":"M21-GAP-03492"},"M21-GAP-03492":{"line":6747,"offset":1211649,"length":171,"previous":"M21-GAP-03491","next":"M21-GAP-03493"},"M21-GAP-03493":{"line":6748,"offset":1211820,"length":171,"previous":"M21-GAP-03492","next":"M21-GAP-03494"},"M21-GAP-03494":{"line":6749,"offset":1211991,"length":201,"previous":"M21-GAP-03493","next":"M21-GAP-03495"},"M21-GAP-03495":{"line":6750,"offset":1212192,"length":178,"previous":"M21-GAP-03494","next":"M21-GAP-03496"},"M21-GAP-03496":{"line":6751,"offset":1212370,"length":199,"previous":"M21-GAP-03495","next":"M21-GAP-03497"},"M21-GAP-03497":{"line":6752,"offset":1212569,"length":168,"previous":"M21-GAP-03496","next":"M21-GAP-03498"},"M21-GAP-03498":{"line":6753,"offset":1212737,"length":178,"previous":"M21-GAP-03497","next":"M21-GAP-03499"},"M21-GAP-03499":{"line":6754,"offset":1212915,"length":171,"previous":"M21-GAP-03498","next":"M21-GAP-03500"},"M21-GAP-03500":{"line":6755,"offset":1213086,"length":164,"previous":"M21-GAP-03499","next":"M21-GAP-03501"},"M21-GAP-03501":{"line":6756,"offset":1213250,"length":177,"previous":"M21-GAP-03500","next":"M21-GAP-03502"},"M21-GAP-03502":{"line":6757,"offset":1213427,"length":177,"previous":"M21-GAP-03501","next":"M21-GAP-03503"},"M21-GAP-03503":{"line":6758,"offset":1213604,"length":190,"previous":"M21-GAP-03502","next":"M21-GAP-03504"},"M21-GAP-03504":{"line":6759,"offset":1213794,"length":188,"previous":"M21-GAP-03503","next":"M21-GAP-03505"},"M21-GAP-03505":{"line":6760,"offset":1213982,"length":190,"previous":"M21-GAP-03504","next":"M21-GAP-03506"},"M21-GAP-03506":{"line":6761,"offset":1214172,"length":190,"previous":"M21-GAP-03505","next":"M21-GAP-03507"},"M21-GAP-03507":{"line":6762,"offset":1214362,"length":189,"previous":"M21-GAP-03506","next":"M21-GAP-03508"},"M21-GAP-03508":{"line":6763,"offset":1214551,"length":205,"previous":"M21-GAP-03507","next":"M21-GAP-03509"},"M21-GAP-03509":{"line":6764,"offset":1214756,"length":194,"previous":"M21-GAP-03508","next":"M21-GAP-03510"},"M21-GAP-03510":{"line":6765,"offset":1214950,"length":208,"previous":"M21-GAP-03509","next":"M21-GAP-03511"},"M21-GAP-03511":{"line":6766,"offset":1215158,"length":197,"previous":"M21-GAP-03510","next":"M21-GAP-03512"},"M21-GAP-03512":{"line":6767,"offset":1215355,"length":207,"previous":"M21-GAP-03511","next":"M21-GAP-03513"},"M21-GAP-03513":{"line":6768,"offset":1215562,"length":196,"previous":"M21-GAP-03512","next":"M21-GAP-03514"},"M21-GAP-03514":{"line":6769,"offset":1215758,"length":200,"previous":"M21-GAP-03513","next":"M21-GAP-03515"},"M21-GAP-03515":{"line":6770,"offset":1215958,"length":189,"previous":"M21-GAP-03514","next":"M21-GAP-03516"},"M21-GAP-03516":{"line":6771,"offset":1216147,"length":177,"previous":"M21-GAP-03515","next":"M21-GAP-03517"},"M21-GAP-03517":{"line":6772,"offset":1216324,"length":184,"previous":"M21-GAP-03516","next":"M21-GAP-03518"},"M21-GAP-03518":{"line":6773,"offset":1216508,"length":180,"previous":"M21-GAP-03517","next":"M21-GAP-03519"},"M21-GAP-03519":{"line":6774,"offset":1216688,"length":179,"previous":"M21-GAP-03518","next":"M21-GAP-03520"},"M21-GAP-03520":{"line":6775,"offset":1216867,"length":174,"previous":"M21-GAP-03519","next":"M21-GAP-03521"},"M21-GAP-03521":{"line":6776,"offset":1217041,"length":166,"previous":"M21-GAP-03520","next":"M21-GAP-03522"},"M21-GAP-03522":{"line":6777,"offset":1217207,"length":173,"previous":"M21-GAP-03521","next":"M21-GAP-03523"},"M21-GAP-03523":{"line":6778,"offset":1217380,"length":179,"previous":"M21-GAP-03522","next":"M21-GAP-03524"},"M21-GAP-03524":{"line":6779,"offset":1217559,"length":166,"previous":"M21-GAP-03523","next":"M21-GAP-03525"},"M21-GAP-03525":{"line":6780,"offset":1217725,"length":188,"previous":"M21-GAP-03524","next":"M21-GAP-03526"},"M21-GAP-03526":{"line":6781,"offset":1217913,"length":191,"previous":"M21-GAP-03525","next":"M21-GAP-03527"},"M21-GAP-03527":{"line":6782,"offset":1218104,"length":207,"previous":"M21-GAP-03526","next":"M21-GAP-03528"},"M21-GAP-03528":{"line":6783,"offset":1218311,"length":196,"previous":"M21-GAP-03527","next":"M21-GAP-03529"},"M21-GAP-03529":{"line":6784,"offset":1218507,"length":210,"previous":"M21-GAP-03528","next":"M21-GAP-03530"},"M21-GAP-03530":{"line":6785,"offset":1218717,"length":199,"previous":"M21-GAP-03529","next":"M21-GAP-03531"},"M21-GAP-03531":{"line":6786,"offset":1218916,"length":209,"previous":"M21-GAP-03530","next":"M21-GAP-03532"},"M21-GAP-03532":{"line":6787,"offset":1219125,"length":198,"previous":"M21-GAP-03531","next":"M21-GAP-03533"},"M21-GAP-03533":{"line":6788,"offset":1219323,"length":190,"previous":"M21-GAP-03532","next":"M21-GAP-03534"},"M21-GAP-03534":{"line":6789,"offset":1219513,"length":179,"previous":"M21-GAP-03533","next":"M21-GAP-03535"},"M21-GAP-03535":{"line":6790,"offset":1219692,"length":170,"previous":"M21-GAP-03534","next":"M21-GAP-03536"},"M21-GAP-03536":{"line":6791,"offset":1219862,"length":185,"previous":"M21-GAP-03535","next":"M21-GAP-03537"},"M21-GAP-03537":{"line":6792,"offset":1220047,"length":178,"previous":"M21-GAP-03536","next":"M21-GAP-03538"},"M21-GAP-03538":{"line":6793,"offset":1220225,"length":178,"previous":"M21-GAP-03537","next":"M21-GAP-03539"},"M21-GAP-03539":{"line":6794,"offset":1220403,"length":170,"previous":"M21-GAP-03538","next":"M21-GAP-03540"},"M21-GAP-03540":{"line":6795,"offset":1220573,"length":170,"previous":"M21-GAP-03539","next":"M21-GAP-03541"},"M21-GAP-03541":{"line":6796,"offset":1220743,"length":176,"previous":"M21-GAP-03540","next":"M21-GAP-03542"},"M21-GAP-03542":{"line":6797,"offset":1220919,"length":191,"previous":"M21-GAP-03541","next":"M21-GAP-03543"},"M21-GAP-03543":{"line":6798,"offset":1221110,"length":179,"previous":"M21-GAP-03542","next":"M21-GAP-03544"},"M21-GAP-03544":{"line":6799,"offset":1221289,"length":169,"previous":"M21-GAP-03543","next":"M21-GAP-03545"},"M21-GAP-03545":{"line":6800,"offset":1221458,"length":174,"previous":"M21-GAP-03544","next":"M21-GAP-03546"},"M21-GAP-03546":{"line":6801,"offset":1221632,"length":172,"previous":"M21-GAP-03545","next":"M21-GAP-03547"},"M21-GAP-03547":{"line":6802,"offset":1221804,"length":191,"previous":"M21-GAP-03546","next":"M21-GAP-03548"},"M21-GAP-03548":{"line":6803,"offset":1221995,"length":179,"previous":"M21-GAP-03547","next":"M21-GAP-03549"},"M21-GAP-03549":{"line":6804,"offset":1222174,"length":166,"previous":"M21-GAP-03548","next":"M21-GAP-03550"},"M21-GAP-03550":{"line":6805,"offset":1222340,"length":178,"previous":"M21-GAP-03549","next":"M21-GAP-03551"},"M21-GAP-03551":{"line":6806,"offset":1222518,"length":176,"previous":"M21-GAP-03550","next":"M21-GAP-03552"},"M21-GAP-03552":{"line":6807,"offset":1222694,"length":181,"previous":"M21-GAP-03551","next":"M21-GAP-03553"},"M21-GAP-03553":{"line":6808,"offset":1222875,"length":177,"previous":"M21-GAP-03552","next":"M21-GAP-03554"},"M21-GAP-03554":{"line":6809,"offset":1223052,"length":182,"previous":"M21-GAP-03553","next":"M21-GAP-03555"},"M21-GAP-03555":{"line":6810,"offset":1223234,"length":179,"previous":"M21-GAP-03554","next":"M21-GAP-03556"},"M21-GAP-03556":{"line":6811,"offset":1223413,"length":208,"previous":"M21-GAP-03555","next":"M21-GAP-03557"},"M21-GAP-03557":{"line":6812,"offset":1223621,"length":177,"previous":"M21-GAP-03556","next":"M21-GAP-03558"},"M21-GAP-03558":{"line":6813,"offset":1223798,"length":177,"previous":"M21-GAP-03557","next":"M21-GAP-03559"},"M21-GAP-03559":{"line":6814,"offset":1223975,"length":172,"previous":"M21-GAP-03558","next":"M21-GAP-03560"},"M21-GAP-03560":{"line":6815,"offset":1224147,"length":166,"previous":"M21-GAP-03559","next":"M21-GAP-03561"},"M21-GAP-03561":{"line":6816,"offset":1224313,"length":158,"previous":"M21-GAP-03560","next":"M21-GAP-03562"},"M21-GAP-03562":{"line":6817,"offset":1224471,"length":165,"previous":"M21-GAP-03561","next":"M21-GAP-03563"},"M21-GAP-03563":{"line":6818,"offset":1224636,"length":155,"previous":"M21-GAP-03562","next":"M21-GAP-03564"},"M21-GAP-03564":{"line":6819,"offset":1224791,"length":154,"previous":"M21-GAP-03563","next":"M21-GAP-03565"},"M21-GAP-03565":{"line":6820,"offset":1224945,"length":153,"previous":"M21-GAP-03564","next":"M21-GAP-03566"},"M21-GAP-03566":{"line":6821,"offset":1225098,"length":153,"previous":"M21-GAP-03565","next":"M21-GAP-03567"},"M21-GAP-03567":{"line":6822,"offset":1225251,"length":150,"previous":"M21-GAP-03566","next":"M21-GAP-03568"},"M21-GAP-03568":{"line":6823,"offset":1225401,"length":161,"previous":"M21-GAP-03567","next":"M21-GAP-03569"},"M21-GAP-03569":{"line":6824,"offset":1225562,"length":154,"previous":"M21-GAP-03568","next":"M21-GAP-03570"},"M21-GAP-03570":{"line":6825,"offset":1225716,"length":156,"previous":"M21-GAP-03569","next":"M21-GAP-03571"},"M21-GAP-03571":{"line":6826,"offset":1225872,"length":156,"previous":"M21-GAP-03570","next":"M21-GAP-03572"},"M21-GAP-03572":{"line":6827,"offset":1226028,"length":152,"previous":"M21-GAP-03571","next":"M21-GAP-03573"},"M21-GAP-03573":{"line":6828,"offset":1226180,"length":158,"previous":"M21-GAP-03572","next":"M21-GAP-03574"},"M21-GAP-03574":{"line":6829,"offset":1226338,"length":157,"previous":"M21-GAP-03573","next":"M21-GAP-03575"},"M21-GAP-03575":{"line":6830,"offset":1226495,"length":149,"previous":"M21-GAP-03574","next":"M21-GAP-03576"},"M21-GAP-03576":{"line":6831,"offset":1226644,"length":153,"previous":"M21-GAP-03575","next":"M21-GAP-03577"},"M21-GAP-03577":{"line":6832,"offset":1226797,"length":149,"previous":"M21-GAP-03576","next":"M21-GAP-03578"},"M21-GAP-03578":{"line":6833,"offset":1226946,"length":166,"previous":"M21-GAP-03577","next":"M21-GAP-03579"},"M21-GAP-03579":{"line":6834,"offset":1227112,"length":163,"previous":"M21-GAP-03578","next":"M21-GAP-03580"},"M21-GAP-03580":{"line":6835,"offset":1227275,"length":171,"previous":"M21-GAP-03579","next":"M21-GAP-03581"},"M21-GAP-03581":{"line":6836,"offset":1227446,"length":167,"previous":"M21-GAP-03580","next":"M21-GAP-03582"},"M21-GAP-03582":{"line":6837,"offset":1227613,"length":167,"previous":"M21-GAP-03581","next":"M21-GAP-03583"},"M21-GAP-03583":{"line":6838,"offset":1227780,"length":167,"previous":"M21-GAP-03582","next":"M21-GAP-03584"},"M21-GAP-03584":{"line":6839,"offset":1227947,"length":160,"previous":"M21-GAP-03583","next":"M21-GAP-03585"},"M21-GAP-03585":{"line":6840,"offset":1228107,"length":159,"previous":"M21-GAP-03584","next":"M21-GAP-03586"},"M21-GAP-03586":{"line":6841,"offset":1228266,"length":166,"previous":"M21-GAP-03585","next":"M21-GAP-03587"},"M21-GAP-03587":{"line":6842,"offset":1228432,"length":164,"previous":"M21-GAP-03586","next":"M21-GAP-03588"},"M21-GAP-03588":{"line":6843,"offset":1228596,"length":167,"previous":"M21-GAP-03587","next":"M21-GAP-03589"},"M21-GAP-03589":{"line":6844,"offset":1228763,"length":166,"previous":"M21-GAP-03588","next":"M21-GAP-03590"},"M21-GAP-03590":{"line":6845,"offset":1228929,"length":170,"previous":"M21-GAP-03589","next":"M21-GAP-03591"},"M21-GAP-03591":{"line":6846,"offset":1229099,"length":167,"previous":"M21-GAP-03590","next":"M21-GAP-03592"},"M21-GAP-03592":{"line":6847,"offset":1229266,"length":166,"previous":"M21-GAP-03591","next":"M21-GAP-03593"},"M21-GAP-03593":{"line":6848,"offset":1229432,"length":162,"previous":"M21-GAP-03592","next":"M21-GAP-03594"},"M21-GAP-03594":{"line":6849,"offset":1229594,"length":156,"previous":"M21-GAP-03593","next":"M21-GAP-03595"},"M21-GAP-03595":{"line":6850,"offset":1229750,"length":152,"previous":"M21-GAP-03594","next":"M21-GAP-03596"},"M21-GAP-03596":{"line":6851,"offset":1229902,"length":161,"previous":"M21-GAP-03595","next":"M21-GAP-03597"},"M21-GAP-03597":{"line":6852,"offset":1230063,"length":150,"previous":"M21-GAP-03596","next":"M21-GAP-03598"},"M21-GAP-03598":{"line":6853,"offset":1230213,"length":157,"previous":"M21-GAP-03597","next":"M21-GAP-03599"},"M21-GAP-03599":{"line":6854,"offset":1230370,"length":157,"previous":"M21-GAP-03598","next":"M21-GAP-03600"},"M21-GAP-03600":{"line":6855,"offset":1230527,"length":157,"previous":"M21-GAP-03599","next":"M21-GAP-03601"},"M21-GAP-03601":{"line":6856,"offset":1230684,"length":149,"previous":"M21-GAP-03600","next":"M21-GAP-03602"},"M21-GAP-03602":{"line":6857,"offset":1230833,"length":155,"previous":"M21-GAP-03601","next":"M21-GAP-03603"},"M21-GAP-03603":{"line":6858,"offset":1230988,"length":156,"previous":"M21-GAP-03602","next":"M21-GAP-03604"},"M21-GAP-03604":{"line":6859,"offset":1231144,"length":153,"previous":"M21-GAP-03603","next":"M21-GAP-03605"},"M21-GAP-03605":{"line":6860,"offset":1231297,"length":156,"previous":"M21-GAP-03604","next":"M21-GAP-03606"},"M21-GAP-03606":{"line":6861,"offset":1231453,"length":155,"previous":"M21-GAP-03605","next":"M21-GAP-03607"},"M21-GAP-03607":{"line":6862,"offset":1231608,"length":160,"previous":"M21-GAP-03606","next":"M21-GAP-03608"},"M21-GAP-03608":{"line":6863,"offset":1231768,"length":156,"previous":"M21-GAP-03607","next":"M21-GAP-03609"},"M21-GAP-03609":{"line":6864,"offset":1231924,"length":154,"previous":"M21-GAP-03608","next":"M21-GAP-03610"},"M21-GAP-03610":{"line":6865,"offset":1232078,"length":156,"previous":"M21-GAP-03609","next":"M21-GAP-03611"},"M21-GAP-03611":{"line":6866,"offset":1232234,"length":151,"previous":"M21-GAP-03610","next":"M21-GAP-03612"},"M21-GAP-03612":{"line":6867,"offset":1232385,"length":152,"previous":"M21-GAP-03611","next":"M21-GAP-03613"},"M21-GAP-03613":{"line":6868,"offset":1232537,"length":157,"previous":"M21-GAP-03612","next":"M21-GAP-03614"},"M21-GAP-03614":{"line":6869,"offset":1232694,"length":165,"previous":"M21-GAP-03613","next":"M21-GAP-03615"},"M21-GAP-03615":{"line":6870,"offset":1232859,"length":159,"previous":"M21-GAP-03614","next":"M21-GAP-03616"},"M21-GAP-03616":{"line":6871,"offset":1233018,"length":172,"previous":"M21-GAP-03615","next":"M21-GAP-03617"},"M21-GAP-03617":{"line":6872,"offset":1233190,"length":166,"previous":"M21-GAP-03616","next":"M21-GAP-03618"},"M21-GAP-03618":{"line":6873,"offset":1233356,"length":157,"previous":"M21-GAP-03617","next":"M21-GAP-03619"},"M21-GAP-03619":{"line":6874,"offset":1233513,"length":159,"previous":"M21-GAP-03618","next":"M21-GAP-03620"},"M21-GAP-03620":{"line":6875,"offset":1233672,"length":173,"previous":"M21-GAP-03619","next":"M21-GAP-03621"},"M21-GAP-03621":{"line":6876,"offset":1233845,"length":166,"previous":"M21-GAP-03620","next":"M21-GAP-03622"},"M21-GAP-03622":{"line":6877,"offset":1234011,"length":173,"previous":"M21-GAP-03621","next":"M21-GAP-03623"},"M21-GAP-03623":{"line":6878,"offset":1234184,"length":165,"previous":"M21-GAP-03622","next":"M21-GAP-03624"},"M21-GAP-03624":{"line":6879,"offset":1234349,"length":173,"previous":"M21-GAP-03623","next":"M21-GAP-03625"},"M21-GAP-03625":{"line":6880,"offset":1234522,"length":165,"previous":"M21-GAP-03624","next":"M22-GAP-00001"},"M22-GAP-00001":{"line":6881,"offset":1234687,"length":166,"previous":"M21-GAP-03625","next":"M22-GAP-00002"},"M22-GAP-00002":{"line":6882,"offset":1234853,"length":180,"previous":"M22-GAP-00001","next":"M22-GAP-00003"},"M22-GAP-00003":{"line":6883,"offset":1235033,"length":172,"previous":"M22-GAP-00002","next":"M22-GAP-00004"},"M22-GAP-00004":{"line":6884,"offset":1235205,"length":155,"previous":"M22-GAP-00003","next":"M22-GAP-00005"},"M22-GAP-00005":{"line":6885,"offset":1235360,"length":159,"previous":"M22-GAP-00004","next":"M22-GAP-00006"},"M22-GAP-00006":{"line":6886,"offset":1235519,"length":159,"previous":"M22-GAP-00005","next":"M22-GAP-00007"},"M22-GAP-00007":{"line":6887,"offset":1235678,"length":164,"previous":"M22-GAP-00006","next":"M22-GAP-00008"},"M22-GAP-00008":{"line":6888,"offset":1235842,"length":154,"previous":"M22-GAP-00007","next":"M22-GAP-00009"},"M22-GAP-00009":{"line":6889,"offset":1235996,"length":157,"previous":"M22-GAP-00008","next":"M22-GAP-00010"},"M22-GAP-00010":{"line":6890,"offset":1236153,"length":157,"previous":"M22-GAP-00009","next":"M22-GAP-00011"},"M22-GAP-00011":{"line":6891,"offset":1236310,"length":157,"previous":"M22-GAP-00010","next":"M22-GAP-00012"},"M22-GAP-00012":{"line":6892,"offset":1236467,"length":155,"previous":"M22-GAP-00011","next":"M22-GAP-00013"},"M22-GAP-00013":{"line":6893,"offset":1236622,"length":163,"previous":"M22-GAP-00012","next":"M22-GAP-00014"},"M22-GAP-00014":{"line":6894,"offset":1236785,"length":154,"previous":"M22-GAP-00013","next":"M22-GAP-00015"},"M22-GAP-00015":{"line":6895,"offset":1236939,"length":155,"previous":"M22-GAP-00014","next":"M22-GAP-00016"},"M22-GAP-00016":{"line":6896,"offset":1237094,"length":158,"previous":"M22-GAP-00015","next":"M22-GAP-00017"},"M22-GAP-00017":{"line":6897,"offset":1237252,"length":155,"previous":"M22-GAP-00016","next":"M22-GAP-00018"},"M22-GAP-00018":{"line":6898,"offset":1237407,"length":162,"previous":"M22-GAP-00017","next":"M22-GAP-00019"},"M22-GAP-00019":{"line":6899,"offset":1237569,"length":154,"previous":"M22-GAP-00018","next":null}}} +{"schemaVersion":1,"operation":"BLENDER_TASK_CONTEXT_INDEX","source":{"path":"tests/golden/M15-03A/next-task-plan.json","sha256":"f10310d6530d8a9adfde0bc6bca35e4bfae7a05169028e1a8b36e374b059c8bb"},"catalog":{"path":"tests/golden/M15-03A/task-catalog.jsonl","sha256":"2f1083e86072a68c206ef125e84ba2514f1325b418333c2055dac0c959127878"},"taskCount":6900,"activeTask":"M16-GAP-00264","entries":{"M16-GAP-00001":{"line":0,"offset":0,"length":165,"previous":null,"next":"M16-GAP-00002"},"M16-GAP-00002":{"line":1,"offset":165,"length":167,"previous":"M16-GAP-00001","next":"M16-GAP-00003"},"M16-GAP-00003":{"line":2,"offset":332,"length":164,"previous":"M16-GAP-00002","next":"M16-GAP-00004"},"M16-GAP-00004":{"line":3,"offset":496,"length":165,"previous":"M16-GAP-00003","next":"M16-GAP-00005"},"M16-GAP-00005":{"line":4,"offset":661,"length":169,"previous":"M16-GAP-00004","next":"M16-GAP-00006"},"M16-GAP-00006":{"line":5,"offset":830,"length":164,"previous":"M16-GAP-00005","next":"M16-GAP-00007"},"M16-GAP-00007":{"line":6,"offset":994,"length":165,"previous":"M16-GAP-00006","next":"M16-GAP-00008"},"M16-GAP-00008":{"line":7,"offset":1159,"length":177,"previous":"M16-GAP-00007","next":"M16-GAP-00009"},"M16-GAP-00009":{"line":8,"offset":1336,"length":171,"previous":"M16-GAP-00008","next":"M16-GAP-00010"},"M16-GAP-00010":{"line":9,"offset":1507,"length":166,"previous":"M16-GAP-00009","next":"M16-GAP-00011"},"M16-GAP-00011":{"line":10,"offset":1673,"length":166,"previous":"M16-GAP-00010","next":"M16-GAP-00012"},"M16-GAP-00012":{"line":11,"offset":1839,"length":164,"previous":"M16-GAP-00011","next":"M16-GAP-00013"},"M16-GAP-00013":{"line":12,"offset":2003,"length":167,"previous":"M16-GAP-00012","next":"M16-GAP-00014"},"M16-GAP-00014":{"line":13,"offset":2170,"length":163,"previous":"M16-GAP-00013","next":"M16-GAP-00015"},"M16-GAP-00015":{"line":14,"offset":2333,"length":167,"previous":"M16-GAP-00014","next":"M16-GAP-00016"},"M16-GAP-00016":{"line":15,"offset":2500,"length":167,"previous":"M16-GAP-00015","next":"M16-GAP-00017"},"M16-GAP-00017":{"line":16,"offset":2667,"length":165,"previous":"M16-GAP-00016","next":"M16-GAP-00018"},"M16-GAP-00018":{"line":17,"offset":2832,"length":175,"previous":"M16-GAP-00017","next":"M16-GAP-00019"},"M16-GAP-00019":{"line":18,"offset":3007,"length":169,"previous":"M16-GAP-00018","next":"M16-GAP-00020"},"M16-GAP-00020":{"line":19,"offset":3176,"length":164,"previous":"M16-GAP-00019","next":"M16-GAP-00021"},"M16-GAP-00021":{"line":20,"offset":3340,"length":165,"previous":"M16-GAP-00020","next":"M16-GAP-00022"},"M16-GAP-00022":{"line":21,"offset":3505,"length":164,"previous":"M16-GAP-00021","next":"M16-GAP-00023"},"M16-GAP-00023":{"line":22,"offset":3669,"length":166,"previous":"M16-GAP-00022","next":"M16-GAP-00024"},"M16-GAP-00024":{"line":23,"offset":3835,"length":163,"previous":"M16-GAP-00023","next":"M16-GAP-00025"},"M16-GAP-00025":{"line":24,"offset":3998,"length":166,"previous":"M16-GAP-00024","next":"M16-GAP-00026"},"M16-GAP-00026":{"line":25,"offset":4164,"length":165,"previous":"M16-GAP-00025","next":"M16-GAP-00027"},"M16-GAP-00027":{"line":26,"offset":4329,"length":172,"previous":"M16-GAP-00026","next":"M16-GAP-00028"},"M16-GAP-00028":{"line":27,"offset":4501,"length":168,"previous":"M16-GAP-00027","next":"M16-GAP-00029"},"M16-GAP-00029":{"line":28,"offset":4669,"length":164,"previous":"M16-GAP-00028","next":"M16-GAP-00030"},"M16-GAP-00030":{"line":29,"offset":4833,"length":161,"previous":"M16-GAP-00029","next":"M16-GAP-00031"},"M16-GAP-00031":{"line":30,"offset":4994,"length":158,"previous":"M16-GAP-00030","next":"M16-GAP-00032"},"M16-GAP-00032":{"line":31,"offset":5152,"length":158,"previous":"M16-GAP-00031","next":"M16-GAP-00033"},"M16-GAP-00033":{"line":32,"offset":5310,"length":160,"previous":"M16-GAP-00032","next":"M16-GAP-00034"},"M16-GAP-00034":{"line":33,"offset":5470,"length":158,"previous":"M16-GAP-00033","next":"M16-GAP-00035"},"M16-GAP-00035":{"line":34,"offset":5628,"length":157,"previous":"M16-GAP-00034","next":"M16-GAP-00036"},"M16-GAP-00036":{"line":35,"offset":5785,"length":158,"previous":"M16-GAP-00035","next":"M16-GAP-00037"},"M16-GAP-00037":{"line":36,"offset":5943,"length":162,"previous":"M16-GAP-00036","next":"M16-GAP-00038"},"M16-GAP-00038":{"line":37,"offset":6105,"length":170,"previous":"M16-GAP-00037","next":"M16-GAP-00039"},"M16-GAP-00039":{"line":38,"offset":6275,"length":158,"previous":"M16-GAP-00038","next":"M16-GAP-00040"},"M16-GAP-00040":{"line":39,"offset":6433,"length":166,"previous":"M16-GAP-00039","next":"M16-GAP-00041"},"M16-GAP-00041":{"line":40,"offset":6599,"length":161,"previous":"M16-GAP-00040","next":"M16-GAP-00042"},"M16-GAP-00042":{"line":41,"offset":6760,"length":161,"previous":"M16-GAP-00041","next":"M16-GAP-00043"},"M16-GAP-00043":{"line":42,"offset":6921,"length":166,"previous":"M16-GAP-00042","next":"M16-GAP-00044"},"M16-GAP-00044":{"line":43,"offset":7087,"length":163,"previous":"M16-GAP-00043","next":"M16-GAP-00045"},"M16-GAP-00045":{"line":44,"offset":7250,"length":160,"previous":"M16-GAP-00044","next":"M16-GAP-00046"},"M16-GAP-00046":{"line":45,"offset":7410,"length":158,"previous":"M16-GAP-00045","next":"M16-GAP-00047"},"M16-GAP-00047":{"line":46,"offset":7568,"length":175,"previous":"M16-GAP-00046","next":"M16-GAP-00048"},"M16-GAP-00048":{"line":47,"offset":7743,"length":172,"previous":"M16-GAP-00047","next":"M16-GAP-00049"},"M16-GAP-00049":{"line":48,"offset":7915,"length":172,"previous":"M16-GAP-00048","next":"M16-GAP-00050"},"M16-GAP-00050":{"line":49,"offset":8087,"length":172,"previous":"M16-GAP-00049","next":"M16-GAP-00051"},"M16-GAP-00051":{"line":50,"offset":8259,"length":171,"previous":"M16-GAP-00050","next":"M16-GAP-00052"},"M16-GAP-00052":{"line":51,"offset":8430,"length":175,"previous":"M16-GAP-00051","next":"M16-GAP-00053"},"M16-GAP-00053":{"line":52,"offset":8605,"length":171,"previous":"M16-GAP-00052","next":"M16-GAP-00054"},"M16-GAP-00054":{"line":53,"offset":8776,"length":174,"previous":"M16-GAP-00053","next":"M16-GAP-00055"},"M16-GAP-00055":{"line":54,"offset":8950,"length":173,"previous":"M16-GAP-00054","next":"M16-GAP-00056"},"M16-GAP-00056":{"line":55,"offset":9123,"length":173,"previous":"M16-GAP-00055","next":"M16-GAP-00057"},"M16-GAP-00057":{"line":56,"offset":9296,"length":175,"previous":"M16-GAP-00056","next":"M16-GAP-00058"},"M16-GAP-00058":{"line":57,"offset":9471,"length":172,"previous":"M16-GAP-00057","next":"M16-GAP-00059"},"M16-GAP-00059":{"line":58,"offset":9643,"length":173,"previous":"M16-GAP-00058","next":"M16-GAP-00060"},"M16-GAP-00060":{"line":59,"offset":9816,"length":174,"previous":"M16-GAP-00059","next":"M16-GAP-00061"},"M16-GAP-00061":{"line":60,"offset":9990,"length":174,"previous":"M16-GAP-00060","next":"M16-GAP-00062"},"M16-GAP-00062":{"line":61,"offset":10164,"length":177,"previous":"M16-GAP-00061","next":"M16-GAP-00063"},"M16-GAP-00063":{"line":62,"offset":10341,"length":175,"previous":"M16-GAP-00062","next":"M16-GAP-00064"},"M16-GAP-00064":{"line":63,"offset":10516,"length":173,"previous":"M16-GAP-00063","next":"M16-GAP-00065"},"M16-GAP-00065":{"line":64,"offset":10689,"length":173,"previous":"M16-GAP-00064","next":"M16-GAP-00066"},"M16-GAP-00066":{"line":65,"offset":10862,"length":174,"previous":"M16-GAP-00065","next":"M16-GAP-00067"},"M16-GAP-00067":{"line":66,"offset":11036,"length":176,"previous":"M16-GAP-00066","next":"M16-GAP-00068"},"M16-GAP-00068":{"line":67,"offset":11212,"length":171,"previous":"M16-GAP-00067","next":"M16-GAP-00069"},"M16-GAP-00069":{"line":68,"offset":11383,"length":171,"previous":"M16-GAP-00068","next":"M16-GAP-00070"},"M16-GAP-00070":{"line":69,"offset":11554,"length":186,"previous":"M16-GAP-00069","next":"M16-GAP-00071"},"M16-GAP-00071":{"line":70,"offset":11740,"length":190,"previous":"M16-GAP-00070","next":"M16-GAP-00072"},"M16-GAP-00072":{"line":71,"offset":11930,"length":157,"previous":"M16-GAP-00071","next":"M16-GAP-00073"},"M16-GAP-00073":{"line":72,"offset":12087,"length":168,"previous":"M16-GAP-00072","next":"M16-GAP-00074"},"M16-GAP-00074":{"line":73,"offset":12255,"length":168,"previous":"M16-GAP-00073","next":"M16-GAP-00075"},"M16-GAP-00075":{"line":74,"offset":12423,"length":160,"previous":"M16-GAP-00074","next":"M16-GAP-00076"},"M16-GAP-00076":{"line":75,"offset":12583,"length":160,"previous":"M16-GAP-00075","next":"M16-GAP-00077"},"M16-GAP-00077":{"line":76,"offset":12743,"length":157,"previous":"M16-GAP-00076","next":"M16-GAP-00078"},"M16-GAP-00078":{"line":77,"offset":12900,"length":163,"previous":"M16-GAP-00077","next":"M16-GAP-00079"},"M16-GAP-00079":{"line":78,"offset":13063,"length":164,"previous":"M16-GAP-00078","next":"M16-GAP-00080"},"M16-GAP-00080":{"line":79,"offset":13227,"length":172,"previous":"M16-GAP-00079","next":"M16-GAP-00081"},"M16-GAP-00081":{"line":80,"offset":13399,"length":167,"previous":"M16-GAP-00080","next":"M16-GAP-00082"},"M16-GAP-00082":{"line":81,"offset":13566,"length":159,"previous":"M16-GAP-00081","next":"M16-GAP-00083"},"M16-GAP-00083":{"line":82,"offset":13725,"length":161,"previous":"M16-GAP-00082","next":"M16-GAP-00084"},"M16-GAP-00084":{"line":83,"offset":13886,"length":158,"previous":"M16-GAP-00083","next":"M16-GAP-00085"},"M16-GAP-00085":{"line":84,"offset":14044,"length":164,"previous":"M16-GAP-00084","next":"M16-GAP-00086"},"M16-GAP-00086":{"line":85,"offset":14208,"length":158,"previous":"M16-GAP-00085","next":"M16-GAP-00087"},"M16-GAP-00087":{"line":86,"offset":14366,"length":170,"previous":"M16-GAP-00086","next":"M16-GAP-00088"},"M16-GAP-00088":{"line":87,"offset":14536,"length":168,"previous":"M16-GAP-00087","next":"M16-GAP-00089"},"M16-GAP-00089":{"line":88,"offset":14704,"length":159,"previous":"M16-GAP-00088","next":"M16-GAP-00090"},"M16-GAP-00090":{"line":89,"offset":14863,"length":158,"previous":"M16-GAP-00089","next":"M16-GAP-00091"},"M16-GAP-00091":{"line":90,"offset":15021,"length":163,"previous":"M16-GAP-00090","next":"M16-GAP-00092"},"M16-GAP-00092":{"line":91,"offset":15184,"length":166,"previous":"M16-GAP-00091","next":"M16-GAP-00093"},"M16-GAP-00093":{"line":92,"offset":15350,"length":157,"previous":"M16-GAP-00092","next":"M16-GAP-00094"},"M16-GAP-00094":{"line":93,"offset":15507,"length":159,"previous":"M16-GAP-00093","next":"M16-GAP-00095"},"M16-GAP-00095":{"line":94,"offset":15666,"length":162,"previous":"M16-GAP-00094","next":"M16-GAP-00096"},"M16-GAP-00096":{"line":95,"offset":15828,"length":161,"previous":"M16-GAP-00095","next":"M16-GAP-00097"},"M16-GAP-00097":{"line":96,"offset":15989,"length":160,"previous":"M16-GAP-00096","next":"M16-GAP-00098"},"M16-GAP-00098":{"line":97,"offset":16149,"length":160,"previous":"M16-GAP-00097","next":"M16-GAP-00099"},"M16-GAP-00099":{"line":98,"offset":16309,"length":167,"previous":"M16-GAP-00098","next":"M16-GAP-00100"},"M16-GAP-00100":{"line":99,"offset":16476,"length":164,"previous":"M16-GAP-00099","next":"M16-GAP-00101"},"M16-GAP-00101":{"line":100,"offset":16640,"length":163,"previous":"M16-GAP-00100","next":"M16-GAP-00102"},"M16-GAP-00102":{"line":101,"offset":16803,"length":160,"previous":"M16-GAP-00101","next":"M16-GAP-00103"},"M16-GAP-00103":{"line":102,"offset":16963,"length":171,"previous":"M16-GAP-00102","next":"M16-GAP-00104"},"M16-GAP-00104":{"line":103,"offset":17134,"length":170,"previous":"M16-GAP-00103","next":"M16-GAP-00105"},"M16-GAP-00105":{"line":104,"offset":17304,"length":176,"previous":"M16-GAP-00104","next":"M16-GAP-00106"},"M16-GAP-00106":{"line":105,"offset":17480,"length":168,"previous":"M16-GAP-00105","next":"M16-GAP-00107"},"M16-GAP-00107":{"line":106,"offset":17648,"length":167,"previous":"M16-GAP-00106","next":"M16-GAP-00108"},"M16-GAP-00108":{"line":107,"offset":17815,"length":157,"previous":"M16-GAP-00107","next":"M16-GAP-00109"},"M16-GAP-00109":{"line":108,"offset":17972,"length":157,"previous":"M16-GAP-00108","next":"M16-GAP-00110"},"M16-GAP-00110":{"line":109,"offset":18129,"length":168,"previous":"M16-GAP-00109","next":"M16-GAP-00111"},"M16-GAP-00111":{"line":110,"offset":18297,"length":157,"previous":"M16-GAP-00110","next":"M16-GAP-00112"},"M16-GAP-00112":{"line":111,"offset":18454,"length":162,"previous":"M16-GAP-00111","next":"M16-GAP-00113"},"M16-GAP-00113":{"line":112,"offset":18616,"length":169,"previous":"M16-GAP-00112","next":"M16-GAP-00114"},"M16-GAP-00114":{"line":113,"offset":18785,"length":165,"previous":"M16-GAP-00113","next":"M16-GAP-00115"},"M16-GAP-00115":{"line":114,"offset":18950,"length":171,"previous":"M16-GAP-00114","next":"M16-GAP-00116"},"M16-GAP-00116":{"line":115,"offset":19121,"length":164,"previous":"M16-GAP-00115","next":"M16-GAP-00117"},"M16-GAP-00117":{"line":116,"offset":19285,"length":166,"previous":"M16-GAP-00116","next":"M16-GAP-00118"},"M16-GAP-00118":{"line":117,"offset":19451,"length":169,"previous":"M16-GAP-00117","next":"M16-GAP-00119"},"M16-GAP-00119":{"line":118,"offset":19620,"length":174,"previous":"M16-GAP-00118","next":"M16-GAP-00120"},"M16-GAP-00120":{"line":119,"offset":19794,"length":171,"previous":"M16-GAP-00119","next":"M16-GAP-00121"},"M16-GAP-00121":{"line":120,"offset":19965,"length":178,"previous":"M16-GAP-00120","next":"M16-GAP-00122"},"M16-GAP-00122":{"line":121,"offset":20143,"length":170,"previous":"M16-GAP-00121","next":"M16-GAP-00123"},"M16-GAP-00123":{"line":122,"offset":20313,"length":171,"previous":"M16-GAP-00122","next":"M16-GAP-00124"},"M16-GAP-00124":{"line":123,"offset":20484,"length":178,"previous":"M16-GAP-00123","next":"M16-GAP-00125"},"M16-GAP-00125":{"line":124,"offset":20662,"length":175,"previous":"M16-GAP-00124","next":"M16-GAP-00126"},"M16-GAP-00126":{"line":125,"offset":20837,"length":173,"previous":"M16-GAP-00125","next":"M16-GAP-00127"},"M16-GAP-00127":{"line":126,"offset":21010,"length":178,"previous":"M16-GAP-00126","next":"M16-GAP-00128"},"M16-GAP-00128":{"line":127,"offset":21188,"length":166,"previous":"M16-GAP-00127","next":"M16-GAP-00129"},"M16-GAP-00129":{"line":128,"offset":21354,"length":163,"previous":"M16-GAP-00128","next":"M16-GAP-00130"},"M16-GAP-00130":{"line":129,"offset":21517,"length":165,"previous":"M16-GAP-00129","next":"M16-GAP-00131"},"M16-GAP-00131":{"line":130,"offset":21682,"length":176,"previous":"M16-GAP-00130","next":"M16-GAP-00132"},"M16-GAP-00132":{"line":131,"offset":21858,"length":169,"previous":"M16-GAP-00131","next":"M16-GAP-00133"},"M16-GAP-00133":{"line":132,"offset":22027,"length":170,"previous":"M16-GAP-00132","next":"M16-GAP-00134"},"M16-GAP-00134":{"line":133,"offset":22197,"length":170,"previous":"M16-GAP-00133","next":"M16-GAP-00135"},"M16-GAP-00135":{"line":134,"offset":22367,"length":174,"previous":"M16-GAP-00134","next":"M16-GAP-00136"},"M16-GAP-00136":{"line":135,"offset":22541,"length":173,"previous":"M16-GAP-00135","next":"M16-GAP-00137"},"M16-GAP-00137":{"line":136,"offset":22714,"length":173,"previous":"M16-GAP-00136","next":"M16-GAP-00138"},"M16-GAP-00138":{"line":137,"offset":22887,"length":172,"previous":"M16-GAP-00137","next":"M16-GAP-00139"},"M16-GAP-00139":{"line":138,"offset":23059,"length":176,"previous":"M16-GAP-00138","next":"M16-GAP-00140"},"M16-GAP-00140":{"line":139,"offset":23235,"length":171,"previous":"M16-GAP-00139","next":"M16-GAP-00141"},"M16-GAP-00141":{"line":140,"offset":23406,"length":173,"previous":"M16-GAP-00140","next":"M16-GAP-00142"},"M16-GAP-00142":{"line":141,"offset":23579,"length":171,"previous":"M16-GAP-00141","next":"M16-GAP-00143"},"M16-GAP-00143":{"line":142,"offset":23750,"length":164,"previous":"M16-GAP-00142","next":"M16-GAP-00144"},"M16-GAP-00144":{"line":143,"offset":23914,"length":165,"previous":"M16-GAP-00143","next":"M16-GAP-00145"},"M16-GAP-00145":{"line":144,"offset":24079,"length":176,"previous":"M16-GAP-00144","next":"M16-GAP-00146"},"M16-GAP-00146":{"line":145,"offset":24255,"length":166,"previous":"M16-GAP-00145","next":"M16-GAP-00147"},"M16-GAP-00147":{"line":146,"offset":24421,"length":168,"previous":"M16-GAP-00146","next":"M16-GAP-00148"},"M16-GAP-00148":{"line":147,"offset":24589,"length":170,"previous":"M16-GAP-00147","next":"M16-GAP-00149"},"M16-GAP-00149":{"line":148,"offset":24759,"length":173,"previous":"M16-GAP-00148","next":"M16-GAP-00150"},"M16-GAP-00150":{"line":149,"offset":24932,"length":170,"previous":"M16-GAP-00149","next":"M16-GAP-00151"},"M16-GAP-00151":{"line":150,"offset":25102,"length":177,"previous":"M16-GAP-00150","next":"M16-GAP-00152"},"M16-GAP-00152":{"line":151,"offset":25279,"length":175,"previous":"M16-GAP-00151","next":"M16-GAP-00153"},"M16-GAP-00153":{"line":152,"offset":25454,"length":171,"previous":"M16-GAP-00152","next":"M16-GAP-00154"},"M16-GAP-00154":{"line":153,"offset":25625,"length":178,"previous":"M16-GAP-00153","next":"M16-GAP-00155"},"M16-GAP-00155":{"line":154,"offset":25803,"length":172,"previous":"M16-GAP-00154","next":"M16-GAP-00156"},"M16-GAP-00156":{"line":155,"offset":25975,"length":175,"previous":"M16-GAP-00155","next":"M16-GAP-00157"},"M16-GAP-00157":{"line":156,"offset":26150,"length":173,"previous":"M16-GAP-00156","next":"M16-GAP-00158"},"M16-GAP-00158":{"line":157,"offset":26323,"length":182,"previous":"M16-GAP-00157","next":"M16-GAP-00159"},"M16-GAP-00159":{"line":158,"offset":26505,"length":173,"previous":"M16-GAP-00158","next":"M16-GAP-00160"},"M16-GAP-00160":{"line":159,"offset":26678,"length":181,"previous":"M16-GAP-00159","next":"M16-GAP-00161"},"M16-GAP-00161":{"line":160,"offset":26859,"length":172,"previous":"M16-GAP-00160","next":"M16-GAP-00162"},"M16-GAP-00162":{"line":161,"offset":27031,"length":171,"previous":"M16-GAP-00161","next":"M16-GAP-00163"},"M16-GAP-00163":{"line":162,"offset":27202,"length":173,"previous":"M16-GAP-00162","next":"M16-GAP-00164"},"M16-GAP-00164":{"line":163,"offset":27375,"length":177,"previous":"M16-GAP-00163","next":"M16-GAP-00165"},"M16-GAP-00165":{"line":164,"offset":27552,"length":177,"previous":"M16-GAP-00164","next":"M16-GAP-00166"},"M16-GAP-00166":{"line":165,"offset":27729,"length":180,"previous":"M16-GAP-00165","next":"M16-GAP-00167"},"M16-GAP-00167":{"line":166,"offset":27909,"length":182,"previous":"M16-GAP-00166","next":"M16-GAP-00168"},"M16-GAP-00168":{"line":167,"offset":28091,"length":181,"previous":"M16-GAP-00167","next":"M16-GAP-00169"},"M16-GAP-00169":{"line":168,"offset":28272,"length":181,"previous":"M16-GAP-00168","next":"M16-GAP-00170"},"M16-GAP-00170":{"line":169,"offset":28453,"length":174,"previous":"M16-GAP-00169","next":"M16-GAP-00171"},"M16-GAP-00171":{"line":170,"offset":28627,"length":180,"previous":"M16-GAP-00170","next":"M16-GAP-00172"},"M16-GAP-00172":{"line":171,"offset":28807,"length":179,"previous":"M16-GAP-00171","next":"M16-GAP-00173"},"M16-GAP-00173":{"line":172,"offset":28986,"length":176,"previous":"M16-GAP-00172","next":"M16-GAP-00174"},"M16-GAP-00174":{"line":173,"offset":29162,"length":175,"previous":"M16-GAP-00173","next":"M16-GAP-00175"},"M16-GAP-00175":{"line":174,"offset":29337,"length":176,"previous":"M16-GAP-00174","next":"M16-GAP-00176"},"M16-GAP-00176":{"line":175,"offset":29513,"length":178,"previous":"M16-GAP-00175","next":"M16-GAP-00177"},"M16-GAP-00177":{"line":176,"offset":29691,"length":171,"previous":"M16-GAP-00176","next":"M16-GAP-00178"},"M16-GAP-00178":{"line":177,"offset":29862,"length":179,"previous":"M16-GAP-00177","next":"M16-GAP-00179"},"M16-GAP-00179":{"line":178,"offset":30041,"length":176,"previous":"M16-GAP-00178","next":"M16-GAP-00180"},"M16-GAP-00180":{"line":179,"offset":30217,"length":176,"previous":"M16-GAP-00179","next":"M16-GAP-00181"},"M16-GAP-00181":{"line":180,"offset":30393,"length":173,"previous":"M16-GAP-00180","next":"M16-GAP-00182"},"M16-GAP-00182":{"line":181,"offset":30566,"length":180,"previous":"M16-GAP-00181","next":"M16-GAP-00183"},"M16-GAP-00183":{"line":182,"offset":30746,"length":181,"previous":"M16-GAP-00182","next":"M16-GAP-00184"},"M16-GAP-00184":{"line":183,"offset":30927,"length":177,"previous":"M16-GAP-00183","next":"M16-GAP-00185"},"M16-GAP-00185":{"line":184,"offset":31104,"length":177,"previous":"M16-GAP-00184","next":"M16-GAP-00186"},"M16-GAP-00186":{"line":185,"offset":31281,"length":173,"previous":"M16-GAP-00185","next":"M16-GAP-00187"},"M16-GAP-00187":{"line":186,"offset":31454,"length":180,"previous":"M16-GAP-00186","next":"M16-GAP-00188"},"M16-GAP-00188":{"line":187,"offset":31634,"length":181,"previous":"M16-GAP-00187","next":"M16-GAP-00189"},"M16-GAP-00189":{"line":188,"offset":31815,"length":178,"previous":"M16-GAP-00188","next":"M16-GAP-00190"},"M16-GAP-00190":{"line":189,"offset":31993,"length":179,"previous":"M16-GAP-00189","next":"M16-GAP-00191"},"M16-GAP-00191":{"line":190,"offset":32172,"length":172,"previous":"M16-GAP-00190","next":"M16-GAP-00192"},"M16-GAP-00192":{"line":191,"offset":32344,"length":175,"previous":"M16-GAP-00191","next":"M16-GAP-00193"},"M16-GAP-00193":{"line":192,"offset":32519,"length":177,"previous":"M16-GAP-00192","next":"M16-GAP-00194"},"M16-GAP-00194":{"line":193,"offset":32696,"length":180,"previous":"M16-GAP-00193","next":"M16-GAP-00195"},"M16-GAP-00195":{"line":194,"offset":32876,"length":175,"previous":"M16-GAP-00194","next":"M16-GAP-00196"},"M16-GAP-00196":{"line":195,"offset":33051,"length":178,"previous":"M16-GAP-00195","next":"M16-GAP-00197"},"M16-GAP-00197":{"line":196,"offset":33229,"length":181,"previous":"M16-GAP-00196","next":"M16-GAP-00198"},"M16-GAP-00198":{"line":197,"offset":33410,"length":173,"previous":"M16-GAP-00197","next":"M16-GAP-00199"},"M16-GAP-00199":{"line":198,"offset":33583,"length":177,"previous":"M16-GAP-00198","next":"M16-GAP-00200"},"M16-GAP-00200":{"line":199,"offset":33760,"length":176,"previous":"M16-GAP-00199","next":"M16-GAP-00201"},"M16-GAP-00201":{"line":200,"offset":33936,"length":174,"previous":"M16-GAP-00200","next":"M16-GAP-00202"},"M16-GAP-00202":{"line":201,"offset":34110,"length":172,"previous":"M16-GAP-00201","next":"M16-GAP-00203"},"M16-GAP-00203":{"line":202,"offset":34282,"length":176,"previous":"M16-GAP-00202","next":"M16-GAP-00204"},"M16-GAP-00204":{"line":203,"offset":34458,"length":175,"previous":"M16-GAP-00203","next":"M16-GAP-00205"},"M16-GAP-00205":{"line":204,"offset":34633,"length":172,"previous":"M16-GAP-00204","next":"M16-GAP-00206"},"M16-GAP-00206":{"line":205,"offset":34805,"length":190,"previous":"M16-GAP-00205","next":"M16-GAP-00207"},"M16-GAP-00207":{"line":206,"offset":34995,"length":173,"previous":"M16-GAP-00206","next":"M16-GAP-00208"},"M16-GAP-00208":{"line":207,"offset":35168,"length":187,"previous":"M16-GAP-00207","next":"M16-GAP-00209"},"M16-GAP-00209":{"line":208,"offset":35355,"length":179,"previous":"M16-GAP-00208","next":"M16-GAP-00210"},"M16-GAP-00210":{"line":209,"offset":35534,"length":186,"previous":"M16-GAP-00209","next":"M16-GAP-00211"},"M16-GAP-00211":{"line":210,"offset":35720,"length":173,"previous":"M16-GAP-00210","next":"M16-GAP-00212"},"M16-GAP-00212":{"line":211,"offset":35893,"length":195,"previous":"M16-GAP-00211","next":"M16-GAP-00213"},"M16-GAP-00213":{"line":212,"offset":36088,"length":184,"previous":"M16-GAP-00212","next":"M16-GAP-00214"},"M16-GAP-00214":{"line":213,"offset":36272,"length":184,"previous":"M16-GAP-00213","next":"M16-GAP-00215"},"M16-GAP-00215":{"line":214,"offset":36456,"length":167,"previous":"M16-GAP-00214","next":"M16-GAP-00216"},"M16-GAP-00216":{"line":215,"offset":36623,"length":182,"previous":"M16-GAP-00215","next":"M16-GAP-00217"},"M16-GAP-00217":{"line":216,"offset":36805,"length":176,"previous":"M16-GAP-00216","next":"M16-GAP-00218"},"M16-GAP-00218":{"line":217,"offset":36981,"length":180,"previous":"M16-GAP-00217","next":"M16-GAP-00219"},"M16-GAP-00219":{"line":218,"offset":37161,"length":176,"previous":"M16-GAP-00218","next":"M16-GAP-00220"},"M16-GAP-00220":{"line":219,"offset":37337,"length":175,"previous":"M16-GAP-00219","next":"M16-GAP-00221"},"M16-GAP-00221":{"line":220,"offset":37512,"length":176,"previous":"M16-GAP-00220","next":"M16-GAP-00222"},"M16-GAP-00222":{"line":221,"offset":37688,"length":179,"previous":"M16-GAP-00221","next":"M16-GAP-00223"},"M16-GAP-00223":{"line":222,"offset":37867,"length":190,"previous":"M16-GAP-00222","next":"M16-GAP-00224"},"M16-GAP-00224":{"line":223,"offset":38057,"length":181,"previous":"M16-GAP-00223","next":"M16-GAP-00225"},"M16-GAP-00225":{"line":224,"offset":38238,"length":177,"previous":"M16-GAP-00224","next":"M16-GAP-00226"},"M16-GAP-00226":{"line":225,"offset":38415,"length":179,"previous":"M16-GAP-00225","next":"M16-GAP-00227"},"M16-GAP-00227":{"line":226,"offset":38594,"length":186,"previous":"M16-GAP-00226","next":"M16-GAP-00228"},"M16-GAP-00228":{"line":227,"offset":38780,"length":179,"previous":"M16-GAP-00227","next":"M16-GAP-00229"},"M16-GAP-00229":{"line":228,"offset":38959,"length":181,"previous":"M16-GAP-00228","next":"M16-GAP-00230"},"M16-GAP-00230":{"line":229,"offset":39140,"length":181,"previous":"M16-GAP-00229","next":"M16-GAP-00231"},"M16-GAP-00231":{"line":230,"offset":39321,"length":187,"previous":"M16-GAP-00230","next":"M16-GAP-00232"},"M16-GAP-00232":{"line":231,"offset":39508,"length":183,"previous":"M16-GAP-00231","next":"M16-GAP-00233"},"M16-GAP-00233":{"line":232,"offset":39691,"length":189,"previous":"M16-GAP-00232","next":"M16-GAP-00234"},"M16-GAP-00234":{"line":233,"offset":39880,"length":168,"previous":"M16-GAP-00233","next":"M16-GAP-00235"},"M16-GAP-00235":{"line":234,"offset":40048,"length":170,"previous":"M16-GAP-00234","next":"M16-GAP-00236"},"M16-GAP-00236":{"line":235,"offset":40218,"length":171,"previous":"M16-GAP-00235","next":"M16-GAP-00237"},"M16-GAP-00237":{"line":236,"offset":40389,"length":176,"previous":"M16-GAP-00236","next":"M16-GAP-00238"},"M16-GAP-00238":{"line":237,"offset":40565,"length":178,"previous":"M16-GAP-00237","next":"M16-GAP-00239"},"M16-GAP-00239":{"line":238,"offset":40743,"length":169,"previous":"M16-GAP-00238","next":"M16-GAP-00240"},"M16-GAP-00240":{"line":239,"offset":40912,"length":176,"previous":"M16-GAP-00239","next":"M16-GAP-00241"},"M16-GAP-00241":{"line":240,"offset":41088,"length":174,"previous":"M16-GAP-00240","next":"M16-GAP-00242"},"M16-GAP-00242":{"line":241,"offset":41262,"length":166,"previous":"M16-GAP-00241","next":"M16-GAP-00243"},"M16-GAP-00243":{"line":242,"offset":41428,"length":172,"previous":"M16-GAP-00242","next":"M16-GAP-00244"},"M16-GAP-00244":{"line":243,"offset":41600,"length":166,"previous":"M16-GAP-00243","next":"M16-GAP-00245"},"M16-GAP-00245":{"line":244,"offset":41766,"length":180,"previous":"M16-GAP-00244","next":"M16-GAP-00246"},"M16-GAP-00246":{"line":245,"offset":41946,"length":174,"previous":"M16-GAP-00245","next":"M16-GAP-00247"},"M16-GAP-00247":{"line":246,"offset":42120,"length":172,"previous":"M16-GAP-00246","next":"M16-GAP-00248"},"M16-GAP-00248":{"line":247,"offset":42292,"length":168,"previous":"M16-GAP-00247","next":"M16-GAP-00249"},"M16-GAP-00249":{"line":248,"offset":42460,"length":172,"previous":"M16-GAP-00248","next":"M16-GAP-00250"},"M16-GAP-00250":{"line":249,"offset":42632,"length":172,"previous":"M16-GAP-00249","next":"M16-GAP-00251"},"M16-GAP-00251":{"line":250,"offset":42804,"length":178,"previous":"M16-GAP-00250","next":"M16-GAP-00252"},"M16-GAP-00252":{"line":251,"offset":42982,"length":173,"previous":"M16-GAP-00251","next":"M16-GAP-00253"},"M16-GAP-00253":{"line":252,"offset":43155,"length":175,"previous":"M16-GAP-00252","next":"M16-GAP-00254"},"M16-GAP-00254":{"line":253,"offset":43330,"length":180,"previous":"M16-GAP-00253","next":"M16-GAP-00255"},"M16-GAP-00255":{"line":254,"offset":43510,"length":175,"previous":"M16-GAP-00254","next":"M16-GAP-00256"},"M16-GAP-00256":{"line":255,"offset":43685,"length":173,"previous":"M16-GAP-00255","next":"M16-GAP-00257"},"M16-GAP-00257":{"line":256,"offset":43858,"length":176,"previous":"M16-GAP-00256","next":"M16-GAP-00258"},"M16-GAP-00258":{"line":257,"offset":44034,"length":170,"previous":"M16-GAP-00257","next":"M16-GAP-00259"},"M16-GAP-00259":{"line":258,"offset":44204,"length":180,"previous":"M16-GAP-00258","next":"M16-GAP-00260"},"M16-GAP-00260":{"line":259,"offset":44384,"length":167,"previous":"M16-GAP-00259","next":"M16-GAP-00261"},"M16-GAP-00261":{"line":260,"offset":44551,"length":171,"previous":"M16-GAP-00260","next":"M16-GAP-00262"},"M16-GAP-00262":{"line":261,"offset":44722,"length":178,"previous":"M16-GAP-00261","next":"M16-GAP-00263"},"M16-GAP-00263":{"line":262,"offset":44900,"length":172,"previous":"M16-GAP-00262","next":"M16-GAP-00264"},"M16-GAP-00264":{"line":263,"offset":45072,"length":170,"previous":"M16-GAP-00263","next":"M16-GAP-00265"},"M16-GAP-00265":{"line":264,"offset":45242,"length":172,"previous":"M16-GAP-00264","next":"M16-GAP-00266"},"M16-GAP-00266":{"line":265,"offset":45414,"length":170,"previous":"M16-GAP-00265","next":"M16-GAP-00267"},"M16-GAP-00267":{"line":266,"offset":45584,"length":185,"previous":"M16-GAP-00266","next":"M16-GAP-00268"},"M16-GAP-00268":{"line":267,"offset":45769,"length":171,"previous":"M16-GAP-00267","next":"M16-GAP-00269"},"M16-GAP-00269":{"line":268,"offset":45940,"length":171,"previous":"M16-GAP-00268","next":"M16-GAP-00270"},"M16-GAP-00270":{"line":269,"offset":46111,"length":168,"previous":"M16-GAP-00269","next":"M16-GAP-00271"},"M16-GAP-00271":{"line":270,"offset":46279,"length":169,"previous":"M16-GAP-00270","next":"M16-GAP-00272"},"M16-GAP-00272":{"line":271,"offset":46448,"length":169,"previous":"M16-GAP-00271","next":"M16-GAP-00273"},"M16-GAP-00273":{"line":272,"offset":46617,"length":174,"previous":"M16-GAP-00272","next":"M16-GAP-00274"},"M16-GAP-00274":{"line":273,"offset":46791,"length":170,"previous":"M16-GAP-00273","next":"M16-GAP-00275"},"M16-GAP-00275":{"line":274,"offset":46961,"length":162,"previous":"M16-GAP-00274","next":"M16-GAP-00276"},"M16-GAP-00276":{"line":275,"offset":47123,"length":169,"previous":"M16-GAP-00275","next":"M16-GAP-00277"},"M16-GAP-00277":{"line":276,"offset":47292,"length":172,"previous":"M16-GAP-00276","next":"M16-GAP-00278"},"M16-GAP-00278":{"line":277,"offset":47464,"length":179,"previous":"M16-GAP-00277","next":"M16-GAP-00279"},"M16-GAP-00279":{"line":278,"offset":47643,"length":161,"previous":"M16-GAP-00278","next":"M16-GAP-00280"},"M16-GAP-00280":{"line":279,"offset":47804,"length":168,"previous":"M16-GAP-00279","next":"M16-GAP-00281"},"M16-GAP-00281":{"line":280,"offset":47972,"length":183,"previous":"M16-GAP-00280","next":"M16-GAP-00282"},"M16-GAP-00282":{"line":281,"offset":48155,"length":175,"previous":"M16-GAP-00281","next":"M16-GAP-00283"},"M16-GAP-00283":{"line":282,"offset":48330,"length":164,"previous":"M16-GAP-00282","next":"M16-GAP-00284"},"M16-GAP-00284":{"line":283,"offset":48494,"length":167,"previous":"M16-GAP-00283","next":"M16-GAP-00285"},"M16-GAP-00285":{"line":284,"offset":48661,"length":164,"previous":"M16-GAP-00284","next":"M16-GAP-00286"},"M16-GAP-00286":{"line":285,"offset":48825,"length":164,"previous":"M16-GAP-00285","next":"M16-GAP-00287"},"M16-GAP-00287":{"line":286,"offset":48989,"length":170,"previous":"M16-GAP-00286","next":"M16-GAP-00288"},"M16-GAP-00288":{"line":287,"offset":49159,"length":168,"previous":"M16-GAP-00287","next":"M16-GAP-00289"},"M16-GAP-00289":{"line":288,"offset":49327,"length":165,"previous":"M16-GAP-00288","next":"M16-GAP-00290"},"M16-GAP-00290":{"line":289,"offset":49492,"length":165,"previous":"M16-GAP-00289","next":"M16-GAP-00291"},"M16-GAP-00291":{"line":290,"offset":49657,"length":171,"previous":"M16-GAP-00290","next":"M16-GAP-00292"},"M16-GAP-00292":{"line":291,"offset":49828,"length":169,"previous":"M16-GAP-00291","next":"M16-GAP-00293"},"M16-GAP-00293":{"line":292,"offset":49997,"length":171,"previous":"M16-GAP-00292","next":"M16-GAP-00294"},"M16-GAP-00294":{"line":293,"offset":50168,"length":169,"previous":"M16-GAP-00293","next":"M16-GAP-00295"},"M16-GAP-00295":{"line":294,"offset":50337,"length":176,"previous":"M16-GAP-00294","next":"M16-GAP-00296"},"M16-GAP-00296":{"line":295,"offset":50513,"length":175,"previous":"M16-GAP-00295","next":"M16-GAP-00297"},"M16-GAP-00297":{"line":296,"offset":50688,"length":169,"previous":"M16-GAP-00296","next":"M16-GAP-00298"},"M16-GAP-00298":{"line":297,"offset":50857,"length":167,"previous":"M16-GAP-00297","next":"M16-GAP-00299"},"M16-GAP-00299":{"line":298,"offset":51024,"length":170,"previous":"M16-GAP-00298","next":"M16-GAP-00300"},"M16-GAP-00300":{"line":299,"offset":51194,"length":167,"previous":"M16-GAP-00299","next":"M16-GAP-00301"},"M16-GAP-00301":{"line":300,"offset":51361,"length":172,"previous":"M16-GAP-00300","next":"M16-GAP-00302"},"M16-GAP-00302":{"line":301,"offset":51533,"length":181,"previous":"M16-GAP-00301","next":"M16-GAP-00303"},"M16-GAP-00303":{"line":302,"offset":51714,"length":180,"previous":"M16-GAP-00302","next":"M16-GAP-00304"},"M16-GAP-00304":{"line":303,"offset":51894,"length":171,"previous":"M16-GAP-00303","next":"M16-GAP-00305"},"M16-GAP-00305":{"line":304,"offset":52065,"length":171,"previous":"M16-GAP-00304","next":"M16-GAP-00306"},"M16-GAP-00306":{"line":305,"offset":52236,"length":175,"previous":"M16-GAP-00305","next":"M16-GAP-00307"},"M16-GAP-00307":{"line":306,"offset":52411,"length":170,"previous":"M16-GAP-00306","next":"M16-GAP-00308"},"M16-GAP-00308":{"line":307,"offset":52581,"length":171,"previous":"M16-GAP-00307","next":"M16-GAP-00309"},"M16-GAP-00309":{"line":308,"offset":52752,"length":169,"previous":"M16-GAP-00308","next":"M16-GAP-00310"},"M16-GAP-00310":{"line":309,"offset":52921,"length":170,"previous":"M16-GAP-00309","next":"M16-GAP-00311"},"M16-GAP-00311":{"line":310,"offset":53091,"length":171,"previous":"M16-GAP-00310","next":"M16-GAP-00312"},"M16-GAP-00312":{"line":311,"offset":53262,"length":173,"previous":"M16-GAP-00311","next":"M16-GAP-00313"},"M16-GAP-00313":{"line":312,"offset":53435,"length":165,"previous":"M16-GAP-00312","next":"M16-GAP-00314"},"M16-GAP-00314":{"line":313,"offset":53600,"length":167,"previous":"M16-GAP-00313","next":"M16-GAP-00315"},"M16-GAP-00315":{"line":314,"offset":53767,"length":168,"previous":"M16-GAP-00314","next":"M16-GAP-00316"},"M16-GAP-00316":{"line":315,"offset":53935,"length":179,"previous":"M16-GAP-00315","next":"M16-GAP-00317"},"M16-GAP-00317":{"line":316,"offset":54114,"length":166,"previous":"M16-GAP-00316","next":"M16-GAP-00318"},"M16-GAP-00318":{"line":317,"offset":54280,"length":175,"previous":"M16-GAP-00317","next":"M16-GAP-00319"},"M16-GAP-00319":{"line":318,"offset":54455,"length":171,"previous":"M16-GAP-00318","next":"M16-GAP-00320"},"M16-GAP-00320":{"line":319,"offset":54626,"length":172,"previous":"M16-GAP-00319","next":"M16-GAP-00321"},"M16-GAP-00321":{"line":320,"offset":54798,"length":176,"previous":"M16-GAP-00320","next":"M16-GAP-00322"},"M16-GAP-00322":{"line":321,"offset":54974,"length":170,"previous":"M16-GAP-00321","next":"M16-GAP-00323"},"M16-GAP-00323":{"line":322,"offset":55144,"length":171,"previous":"M16-GAP-00322","next":"M16-GAP-00324"},"M16-GAP-00324":{"line":323,"offset":55315,"length":173,"previous":"M16-GAP-00323","next":"M16-GAP-00325"},"M16-GAP-00325":{"line":324,"offset":55488,"length":168,"previous":"M16-GAP-00324","next":"M16-GAP-00326"},"M16-GAP-00326":{"line":325,"offset":55656,"length":168,"previous":"M16-GAP-00325","next":"M16-GAP-00327"},"M16-GAP-00327":{"line":326,"offset":55824,"length":170,"previous":"M16-GAP-00326","next":"M16-GAP-00328"},"M16-GAP-00328":{"line":327,"offset":55994,"length":172,"previous":"M16-GAP-00327","next":"M16-GAP-00329"},"M16-GAP-00329":{"line":328,"offset":56166,"length":176,"previous":"M16-GAP-00328","next":"M16-GAP-00330"},"M16-GAP-00330":{"line":329,"offset":56342,"length":167,"previous":"M16-GAP-00329","next":"M16-GAP-00331"},"M16-GAP-00331":{"line":330,"offset":56509,"length":174,"previous":"M16-GAP-00330","next":"M16-GAP-00332"},"M16-GAP-00332":{"line":331,"offset":56683,"length":166,"previous":"M16-GAP-00331","next":"M16-GAP-00333"},"M16-GAP-00333":{"line":332,"offset":56849,"length":169,"previous":"M16-GAP-00332","next":"M16-GAP-00334"},"M16-GAP-00334":{"line":333,"offset":57018,"length":168,"previous":"M16-GAP-00333","next":"M16-GAP-00335"},"M16-GAP-00335":{"line":334,"offset":57186,"length":168,"previous":"M16-GAP-00334","next":"M16-GAP-00336"},"M16-GAP-00336":{"line":335,"offset":57354,"length":171,"previous":"M16-GAP-00335","next":"M16-GAP-00337"},"M16-GAP-00337":{"line":336,"offset":57525,"length":171,"previous":"M16-GAP-00336","next":"M16-GAP-00338"},"M16-GAP-00338":{"line":337,"offset":57696,"length":180,"previous":"M16-GAP-00337","next":"M16-GAP-00339"},"M16-GAP-00339":{"line":338,"offset":57876,"length":174,"previous":"M16-GAP-00338","next":"M16-GAP-00340"},"M16-GAP-00340":{"line":339,"offset":58050,"length":169,"previous":"M16-GAP-00339","next":"M16-GAP-00341"},"M16-GAP-00341":{"line":340,"offset":58219,"length":166,"previous":"M16-GAP-00340","next":"M16-GAP-00342"},"M16-GAP-00342":{"line":341,"offset":58385,"length":182,"previous":"M16-GAP-00341","next":"M16-GAP-00343"},"M16-GAP-00343":{"line":342,"offset":58567,"length":174,"previous":"M16-GAP-00342","next":"M16-GAP-00344"},"M16-GAP-00344":{"line":343,"offset":58741,"length":173,"previous":"M16-GAP-00343","next":"M16-GAP-00345"},"M16-GAP-00345":{"line":344,"offset":58914,"length":177,"previous":"M16-GAP-00344","next":"M16-GAP-00346"},"M16-GAP-00346":{"line":345,"offset":59091,"length":168,"previous":"M16-GAP-00345","next":"M16-GAP-00347"},"M16-GAP-00347":{"line":346,"offset":59259,"length":180,"previous":"M16-GAP-00346","next":"M16-GAP-00348"},"M16-GAP-00348":{"line":347,"offset":59439,"length":172,"previous":"M16-GAP-00347","next":"M16-GAP-00349"},"M16-GAP-00349":{"line":348,"offset":59611,"length":170,"previous":"M16-GAP-00348","next":"M16-GAP-00350"},"M16-GAP-00350":{"line":349,"offset":59781,"length":167,"previous":"M16-GAP-00349","next":"M16-GAP-00351"},"M16-GAP-00351":{"line":350,"offset":59948,"length":173,"previous":"M16-GAP-00350","next":"M16-GAP-00352"},"M16-GAP-00352":{"line":351,"offset":60121,"length":167,"previous":"M16-GAP-00351","next":"M16-GAP-00353"},"M16-GAP-00353":{"line":352,"offset":60288,"length":171,"previous":"M16-GAP-00352","next":"M16-GAP-00354"},"M16-GAP-00354":{"line":353,"offset":60459,"length":171,"previous":"M16-GAP-00353","next":"M16-GAP-00355"},"M16-GAP-00355":{"line":354,"offset":60630,"length":177,"previous":"M16-GAP-00354","next":"M16-GAP-00356"},"M16-GAP-00356":{"line":355,"offset":60807,"length":167,"previous":"M16-GAP-00355","next":"M16-GAP-00357"},"M16-GAP-00357":{"line":356,"offset":60974,"length":164,"previous":"M16-GAP-00356","next":"M16-GAP-00358"},"M16-GAP-00358":{"line":357,"offset":61138,"length":183,"previous":"M16-GAP-00357","next":"M16-GAP-00359"},"M16-GAP-00359":{"line":358,"offset":61321,"length":160,"previous":"M16-GAP-00358","next":"M16-GAP-00360"},"M16-GAP-00360":{"line":359,"offset":61481,"length":168,"previous":"M16-GAP-00359","next":"M16-GAP-00361"},"M16-GAP-00361":{"line":360,"offset":61649,"length":164,"previous":"M16-GAP-00360","next":"M16-GAP-00362"},"M16-GAP-00362":{"line":361,"offset":61813,"length":169,"previous":"M16-GAP-00361","next":"M16-GAP-00363"},"M16-GAP-00363":{"line":362,"offset":61982,"length":170,"previous":"M16-GAP-00362","next":"M16-GAP-00364"},"M16-GAP-00364":{"line":363,"offset":62152,"length":162,"previous":"M16-GAP-00363","next":"M16-GAP-00365"},"M16-GAP-00365":{"line":364,"offset":62314,"length":162,"previous":"M16-GAP-00364","next":"M16-GAP-00366"},"M16-GAP-00366":{"line":365,"offset":62476,"length":166,"previous":"M16-GAP-00365","next":"M16-GAP-00367"},"M16-GAP-00367":{"line":366,"offset":62642,"length":166,"previous":"M16-GAP-00366","next":"M16-GAP-00368"},"M16-GAP-00368":{"line":367,"offset":62808,"length":169,"previous":"M16-GAP-00367","next":"M16-GAP-00369"},"M16-GAP-00369":{"line":368,"offset":62977,"length":170,"previous":"M16-GAP-00368","next":"M16-GAP-00370"},"M16-GAP-00370":{"line":369,"offset":63147,"length":168,"previous":"M16-GAP-00369","next":"M16-GAP-00371"},"M16-GAP-00371":{"line":370,"offset":63315,"length":171,"previous":"M16-GAP-00370","next":"M16-GAP-00372"},"M16-GAP-00372":{"line":371,"offset":63486,"length":164,"previous":"M16-GAP-00371","next":"M16-GAP-00373"},"M16-GAP-00373":{"line":372,"offset":63650,"length":166,"previous":"M16-GAP-00372","next":"M16-GAP-00374"},"M16-GAP-00374":{"line":373,"offset":63816,"length":165,"previous":"M16-GAP-00373","next":"M16-GAP-00375"},"M16-GAP-00375":{"line":374,"offset":63981,"length":165,"previous":"M16-GAP-00374","next":"M16-GAP-00376"},"M16-GAP-00376":{"line":375,"offset":64146,"length":172,"previous":"M16-GAP-00375","next":"M16-GAP-00377"},"M16-GAP-00377":{"line":376,"offset":64318,"length":174,"previous":"M16-GAP-00376","next":"M16-GAP-00378"},"M16-GAP-00378":{"line":377,"offset":64492,"length":175,"previous":"M16-GAP-00377","next":"M16-GAP-00379"},"M16-GAP-00379":{"line":378,"offset":64667,"length":179,"previous":"M16-GAP-00378","next":"M16-GAP-00380"},"M16-GAP-00380":{"line":379,"offset":64846,"length":176,"previous":"M16-GAP-00379","next":"M16-GAP-00381"},"M16-GAP-00381":{"line":380,"offset":65022,"length":168,"previous":"M16-GAP-00380","next":"M16-GAP-00382"},"M16-GAP-00382":{"line":381,"offset":65190,"length":174,"previous":"M16-GAP-00381","next":"M16-GAP-00383"},"M16-GAP-00383":{"line":382,"offset":65364,"length":168,"previous":"M16-GAP-00382","next":"M16-GAP-00384"},"M16-GAP-00384":{"line":383,"offset":65532,"length":172,"previous":"M16-GAP-00383","next":"M16-GAP-00385"},"M16-GAP-00385":{"line":384,"offset":65704,"length":175,"previous":"M16-GAP-00384","next":"M16-GAP-00386"},"M16-GAP-00386":{"line":385,"offset":65879,"length":181,"previous":"M16-GAP-00385","next":"M16-GAP-00387"},"M16-GAP-00387":{"line":386,"offset":66060,"length":184,"previous":"M16-GAP-00386","next":"M16-GAP-00388"},"M16-GAP-00388":{"line":387,"offset":66244,"length":184,"previous":"M16-GAP-00387","next":"M16-GAP-00389"},"M16-GAP-00389":{"line":388,"offset":66428,"length":175,"previous":"M16-GAP-00388","next":"M16-GAP-00390"},"M16-GAP-00390":{"line":389,"offset":66603,"length":178,"previous":"M16-GAP-00389","next":"M16-GAP-00391"},"M16-GAP-00391":{"line":390,"offset":66781,"length":172,"previous":"M16-GAP-00390","next":"M16-GAP-00392"},"M16-GAP-00392":{"line":391,"offset":66953,"length":169,"previous":"M16-GAP-00391","next":"M16-GAP-00393"},"M16-GAP-00393":{"line":392,"offset":67122,"length":181,"previous":"M16-GAP-00392","next":"M16-GAP-00394"},"M16-GAP-00394":{"line":393,"offset":67303,"length":179,"previous":"M16-GAP-00393","next":"M16-GAP-00395"},"M16-GAP-00395":{"line":394,"offset":67482,"length":170,"previous":"M16-GAP-00394","next":"M16-GAP-00396"},"M16-GAP-00396":{"line":395,"offset":67652,"length":175,"previous":"M16-GAP-00395","next":"M16-GAP-00397"},"M16-GAP-00397":{"line":396,"offset":67827,"length":178,"previous":"M16-GAP-00396","next":"M16-GAP-00398"},"M16-GAP-00398":{"line":397,"offset":68005,"length":184,"previous":"M16-GAP-00397","next":"M16-GAP-00399"},"M16-GAP-00399":{"line":398,"offset":68189,"length":186,"previous":"M16-GAP-00398","next":"M16-GAP-00400"},"M16-GAP-00400":{"line":399,"offset":68375,"length":164,"previous":"M16-GAP-00399","next":"M16-GAP-00401"},"M16-GAP-00401":{"line":400,"offset":68539,"length":174,"previous":"M16-GAP-00400","next":"M16-GAP-00402"},"M16-GAP-00402":{"line":401,"offset":68713,"length":165,"previous":"M16-GAP-00401","next":"M16-GAP-00403"},"M16-GAP-00403":{"line":402,"offset":68878,"length":164,"previous":"M16-GAP-00402","next":"M16-GAP-00404"},"M16-GAP-00404":{"line":403,"offset":69042,"length":169,"previous":"M16-GAP-00403","next":"M16-GAP-00405"},"M16-GAP-00405":{"line":404,"offset":69211,"length":165,"previous":"M16-GAP-00404","next":"M16-GAP-00406"},"M16-GAP-00406":{"line":405,"offset":69376,"length":168,"previous":"M16-GAP-00405","next":"M16-GAP-00407"},"M16-GAP-00407":{"line":406,"offset":69544,"length":169,"previous":"M16-GAP-00406","next":"M16-GAP-00408"},"M16-GAP-00408":{"line":407,"offset":69713,"length":171,"previous":"M16-GAP-00407","next":"M16-GAP-00409"},"M16-GAP-00409":{"line":408,"offset":69884,"length":167,"previous":"M16-GAP-00408","next":"M16-GAP-00410"},"M16-GAP-00410":{"line":409,"offset":70051,"length":168,"previous":"M16-GAP-00409","next":"M16-GAP-00411"},"M16-GAP-00411":{"line":410,"offset":70219,"length":172,"previous":"M16-GAP-00410","next":"M16-GAP-00412"},"M16-GAP-00412":{"line":411,"offset":70391,"length":174,"previous":"M16-GAP-00411","next":"M16-GAP-00413"},"M16-GAP-00413":{"line":412,"offset":70565,"length":177,"previous":"M16-GAP-00412","next":"M16-GAP-00414"},"M16-GAP-00414":{"line":413,"offset":70742,"length":175,"previous":"M16-GAP-00413","next":"M16-GAP-00415"},"M16-GAP-00415":{"line":414,"offset":70917,"length":177,"previous":"M16-GAP-00414","next":"M16-GAP-00416"},"M16-GAP-00416":{"line":415,"offset":71094,"length":174,"previous":"M16-GAP-00415","next":"M16-GAP-00417"},"M16-GAP-00417":{"line":416,"offset":71268,"length":177,"previous":"M16-GAP-00416","next":"M16-GAP-00418"},"M16-GAP-00418":{"line":417,"offset":71445,"length":180,"previous":"M16-GAP-00417","next":"M16-GAP-00419"},"M16-GAP-00419":{"line":418,"offset":71625,"length":176,"previous":"M16-GAP-00418","next":"M16-GAP-00420"},"M16-GAP-00420":{"line":419,"offset":71801,"length":183,"previous":"M16-GAP-00419","next":"M16-GAP-00421"},"M16-GAP-00421":{"line":420,"offset":71984,"length":180,"previous":"M16-GAP-00420","next":"M16-GAP-00422"},"M16-GAP-00422":{"line":421,"offset":72164,"length":171,"previous":"M16-GAP-00421","next":"M16-GAP-00423"},"M16-GAP-00423":{"line":422,"offset":72335,"length":165,"previous":"M16-GAP-00422","next":"M16-GAP-00424"},"M16-GAP-00424":{"line":423,"offset":72500,"length":164,"previous":"M16-GAP-00423","next":"M16-GAP-00425"},"M16-GAP-00425":{"line":424,"offset":72664,"length":169,"previous":"M16-GAP-00424","next":"M16-GAP-00426"},"M16-GAP-00426":{"line":425,"offset":72833,"length":163,"previous":"M16-GAP-00425","next":"M16-GAP-00427"},"M16-GAP-00427":{"line":426,"offset":72996,"length":173,"previous":"M16-GAP-00426","next":"M16-GAP-00428"},"M16-GAP-00428":{"line":427,"offset":73169,"length":165,"previous":"M16-GAP-00427","next":"M16-GAP-00429"},"M16-GAP-00429":{"line":428,"offset":73334,"length":166,"previous":"M16-GAP-00428","next":"M16-GAP-00430"},"M16-GAP-00430":{"line":429,"offset":73500,"length":173,"previous":"M16-GAP-00429","next":"M16-GAP-00431"},"M16-GAP-00431":{"line":430,"offset":73673,"length":172,"previous":"M16-GAP-00430","next":"M16-GAP-00432"},"M16-GAP-00432":{"line":431,"offset":73845,"length":165,"previous":"M16-GAP-00431","next":"M16-GAP-00433"},"M16-GAP-00433":{"line":432,"offset":74010,"length":181,"previous":"M16-GAP-00432","next":"M16-GAP-00434"},"M16-GAP-00434":{"line":433,"offset":74191,"length":165,"previous":"M16-GAP-00433","next":"M16-GAP-00435"},"M16-GAP-00435":{"line":434,"offset":74356,"length":167,"previous":"M16-GAP-00434","next":"M16-GAP-00436"},"M16-GAP-00436":{"line":435,"offset":74523,"length":163,"previous":"M16-GAP-00435","next":"M16-GAP-00437"},"M16-GAP-00437":{"line":436,"offset":74686,"length":164,"previous":"M16-GAP-00436","next":"M16-GAP-00438"},"M16-GAP-00438":{"line":437,"offset":74850,"length":176,"previous":"M16-GAP-00437","next":"M16-GAP-00439"},"M16-GAP-00439":{"line":438,"offset":75026,"length":169,"previous":"M16-GAP-00438","next":"M16-GAP-00440"},"M16-GAP-00440":{"line":439,"offset":75195,"length":169,"previous":"M16-GAP-00439","next":"M16-GAP-00441"},"M16-GAP-00441":{"line":440,"offset":75364,"length":170,"previous":"M16-GAP-00440","next":"M16-GAP-00442"},"M16-GAP-00442":{"line":441,"offset":75534,"length":167,"previous":"M16-GAP-00441","next":"M16-GAP-00443"},"M16-GAP-00443":{"line":442,"offset":75701,"length":172,"previous":"M16-GAP-00442","next":"M16-GAP-00444"},"M16-GAP-00444":{"line":443,"offset":75873,"length":167,"previous":"M16-GAP-00443","next":"M16-GAP-00445"},"M16-GAP-00445":{"line":444,"offset":76040,"length":183,"previous":"M16-GAP-00444","next":"M16-GAP-00446"},"M16-GAP-00446":{"line":445,"offset":76223,"length":181,"previous":"M16-GAP-00445","next":"M16-GAP-00447"},"M16-GAP-00447":{"line":446,"offset":76404,"length":166,"previous":"M16-GAP-00446","next":"M16-GAP-00448"},"M16-GAP-00448":{"line":447,"offset":76570,"length":178,"previous":"M16-GAP-00447","next":"M16-GAP-00449"},"M16-GAP-00449":{"line":448,"offset":76748,"length":168,"previous":"M16-GAP-00448","next":"M16-GAP-00450"},"M16-GAP-00450":{"line":449,"offset":76916,"length":184,"previous":"M16-GAP-00449","next":"M16-GAP-00451"},"M16-GAP-00451":{"line":450,"offset":77100,"length":185,"previous":"M16-GAP-00450","next":"M16-GAP-00452"},"M16-GAP-00452":{"line":451,"offset":77285,"length":181,"previous":"M16-GAP-00451","next":"M16-GAP-00453"},"M16-GAP-00453":{"line":452,"offset":77466,"length":171,"previous":"M16-GAP-00452","next":"M16-GAP-00454"},"M16-GAP-00454":{"line":453,"offset":77637,"length":175,"previous":"M16-GAP-00453","next":"M16-GAP-00455"},"M16-GAP-00455":{"line":454,"offset":77812,"length":169,"previous":"M16-GAP-00454","next":"M16-GAP-00456"},"M16-GAP-00456":{"line":455,"offset":77981,"length":186,"previous":"M16-GAP-00455","next":"M16-GAP-00457"},"M16-GAP-00457":{"line":456,"offset":78167,"length":188,"previous":"M16-GAP-00456","next":"M16-GAP-00458"},"M16-GAP-00458":{"line":457,"offset":78355,"length":186,"previous":"M16-GAP-00457","next":"M16-GAP-00459"},"M16-GAP-00459":{"line":458,"offset":78541,"length":175,"previous":"M16-GAP-00458","next":"M16-GAP-00460"},"M16-GAP-00460":{"line":459,"offset":78716,"length":177,"previous":"M16-GAP-00459","next":"M16-GAP-00461"},"M16-GAP-00461":{"line":460,"offset":78893,"length":170,"previous":"M16-GAP-00460","next":"M16-GAP-00462"},"M16-GAP-00462":{"line":461,"offset":79063,"length":172,"previous":"M16-GAP-00461","next":"M16-GAP-00463"},"M16-GAP-00463":{"line":462,"offset":79235,"length":171,"previous":"M16-GAP-00462","next":"M16-GAP-00464"},"M16-GAP-00464":{"line":463,"offset":79406,"length":165,"previous":"M16-GAP-00463","next":"M16-GAP-00465"},"M16-GAP-00465":{"line":464,"offset":79571,"length":163,"previous":"M16-GAP-00464","next":"M16-GAP-00466"},"M16-GAP-00466":{"line":465,"offset":79734,"length":171,"previous":"M16-GAP-00465","next":"M16-GAP-00467"},"M16-GAP-00467":{"line":466,"offset":79905,"length":161,"previous":"M16-GAP-00466","next":"M16-GAP-00468"},"M16-GAP-00468":{"line":467,"offset":80066,"length":166,"previous":"M16-GAP-00467","next":"M16-GAP-00469"},"M16-GAP-00469":{"line":468,"offset":80232,"length":171,"previous":"M16-GAP-00468","next":"M16-GAP-00470"},"M16-GAP-00470":{"line":469,"offset":80403,"length":164,"previous":"M16-GAP-00469","next":"M16-GAP-00471"},"M16-GAP-00471":{"line":470,"offset":80567,"length":169,"previous":"M16-GAP-00470","next":"M16-GAP-00472"},"M16-GAP-00472":{"line":471,"offset":80736,"length":172,"previous":"M16-GAP-00471","next":"M16-GAP-00473"},"M16-GAP-00473":{"line":472,"offset":80908,"length":161,"previous":"M16-GAP-00472","next":"M16-GAP-00474"},"M16-GAP-00474":{"line":473,"offset":81069,"length":169,"previous":"M16-GAP-00473","next":"M16-GAP-00475"},"M16-GAP-00475":{"line":474,"offset":81238,"length":176,"previous":"M16-GAP-00474","next":"M16-GAP-00476"},"M16-GAP-00476":{"line":475,"offset":81414,"length":180,"previous":"M16-GAP-00475","next":"M16-GAP-00477"},"M16-GAP-00477":{"line":476,"offset":81594,"length":160,"previous":"M16-GAP-00476","next":"M16-GAP-00478"},"M16-GAP-00478":{"line":477,"offset":81754,"length":184,"previous":"M16-GAP-00477","next":"M16-GAP-00479"},"M16-GAP-00479":{"line":478,"offset":81938,"length":183,"previous":"M16-GAP-00478","next":"M16-GAP-00480"},"M16-GAP-00480":{"line":479,"offset":82121,"length":183,"previous":"M16-GAP-00479","next":"M16-GAP-00481"},"M16-GAP-00481":{"line":480,"offset":82304,"length":182,"previous":"M16-GAP-00480","next":"M16-GAP-00482"},"M16-GAP-00482":{"line":481,"offset":82486,"length":181,"previous":"M16-GAP-00481","next":"M16-GAP-00483"},"M16-GAP-00483":{"line":482,"offset":82667,"length":167,"previous":"M16-GAP-00482","next":"M16-GAP-00484"},"M16-GAP-00484":{"line":483,"offset":82834,"length":163,"previous":"M16-GAP-00483","next":"M16-GAP-00485"},"M16-GAP-00485":{"line":484,"offset":82997,"length":167,"previous":"M16-GAP-00484","next":"M16-GAP-00486"},"M16-GAP-00486":{"line":485,"offset":83164,"length":168,"previous":"M16-GAP-00485","next":"M16-GAP-00487"},"M16-GAP-00487":{"line":486,"offset":83332,"length":170,"previous":"M16-GAP-00486","next":"M16-GAP-00488"},"M16-GAP-00488":{"line":487,"offset":83502,"length":175,"previous":"M16-GAP-00487","next":"M16-GAP-00489"},"M16-GAP-00489":{"line":488,"offset":83677,"length":168,"previous":"M16-GAP-00488","next":"M16-GAP-00490"},"M16-GAP-00490":{"line":489,"offset":83845,"length":168,"previous":"M16-GAP-00489","next":"M16-GAP-00491"},"M16-GAP-00491":{"line":490,"offset":84013,"length":167,"previous":"M16-GAP-00490","next":"M16-GAP-00492"},"M16-GAP-00492":{"line":491,"offset":84180,"length":172,"previous":"M16-GAP-00491","next":"M16-GAP-00493"},"M16-GAP-00493":{"line":492,"offset":84352,"length":170,"previous":"M16-GAP-00492","next":"M16-GAP-00494"},"M16-GAP-00494":{"line":493,"offset":84522,"length":167,"previous":"M16-GAP-00493","next":"M16-GAP-00495"},"M16-GAP-00495":{"line":494,"offset":84689,"length":171,"previous":"M16-GAP-00494","next":"M16-GAP-00496"},"M16-GAP-00496":{"line":495,"offset":84860,"length":165,"previous":"M16-GAP-00495","next":"M16-GAP-00497"},"M16-GAP-00497":{"line":496,"offset":85025,"length":167,"previous":"M16-GAP-00496","next":"M16-GAP-00498"},"M16-GAP-00498":{"line":497,"offset":85192,"length":169,"previous":"M16-GAP-00497","next":"M16-GAP-00499"},"M16-GAP-00499":{"line":498,"offset":85361,"length":175,"previous":"M16-GAP-00498","next":"M16-GAP-00500"},"M16-GAP-00500":{"line":499,"offset":85536,"length":163,"previous":"M16-GAP-00499","next":"M16-GAP-00501"},"M16-GAP-00501":{"line":500,"offset":85699,"length":170,"previous":"M16-GAP-00500","next":"M16-GAP-00502"},"M16-GAP-00502":{"line":501,"offset":85869,"length":168,"previous":"M16-GAP-00501","next":"M16-GAP-00503"},"M16-GAP-00503":{"line":502,"offset":86037,"length":170,"previous":"M16-GAP-00502","next":"M16-GAP-00504"},"M16-GAP-00504":{"line":503,"offset":86207,"length":161,"previous":"M16-GAP-00503","next":"M16-GAP-00505"},"M16-GAP-00505":{"line":504,"offset":86368,"length":172,"previous":"M16-GAP-00504","next":"M16-GAP-00506"},"M16-GAP-00506":{"line":505,"offset":86540,"length":174,"previous":"M16-GAP-00505","next":"M16-GAP-00507"},"M16-GAP-00507":{"line":506,"offset":86714,"length":162,"previous":"M16-GAP-00506","next":"M16-GAP-00508"},"M16-GAP-00508":{"line":507,"offset":86876,"length":166,"previous":"M16-GAP-00507","next":"M16-GAP-00509"},"M16-GAP-00509":{"line":508,"offset":87042,"length":173,"previous":"M16-GAP-00508","next":"M16-GAP-00510"},"M16-GAP-00510":{"line":509,"offset":87215,"length":167,"previous":"M16-GAP-00509","next":"M16-GAP-00511"},"M16-GAP-00511":{"line":510,"offset":87382,"length":167,"previous":"M16-GAP-00510","next":"M16-GAP-00512"},"M16-GAP-00512":{"line":511,"offset":87549,"length":168,"previous":"M16-GAP-00511","next":"M16-GAP-00513"},"M16-GAP-00513":{"line":512,"offset":87717,"length":168,"previous":"M16-GAP-00512","next":"M16-GAP-00514"},"M16-GAP-00514":{"line":513,"offset":87885,"length":171,"previous":"M16-GAP-00513","next":"M16-GAP-00515"},"M16-GAP-00515":{"line":514,"offset":88056,"length":186,"previous":"M16-GAP-00514","next":"M16-GAP-00516"},"M16-GAP-00516":{"line":515,"offset":88242,"length":184,"previous":"M16-GAP-00515","next":"M16-GAP-00517"},"M16-GAP-00517":{"line":516,"offset":88426,"length":172,"previous":"M16-GAP-00516","next":"M16-GAP-00518"},"M16-GAP-00518":{"line":517,"offset":88598,"length":171,"previous":"M16-GAP-00517","next":"M16-GAP-00519"},"M16-GAP-00519":{"line":518,"offset":88769,"length":164,"previous":"M16-GAP-00518","next":"M16-GAP-00520"},"M16-GAP-00520":{"line":519,"offset":88933,"length":162,"previous":"M16-GAP-00519","next":"M16-GAP-00521"},"M16-GAP-00521":{"line":520,"offset":89095,"length":167,"previous":"M16-GAP-00520","next":"M16-GAP-00522"},"M16-GAP-00522":{"line":521,"offset":89262,"length":172,"previous":"M16-GAP-00521","next":"M16-GAP-00523"},"M16-GAP-00523":{"line":522,"offset":89434,"length":165,"previous":"M16-GAP-00522","next":"M16-GAP-00524"},"M16-GAP-00524":{"line":523,"offset":89599,"length":170,"previous":"M16-GAP-00523","next":"M16-GAP-00525"},"M16-GAP-00525":{"line":524,"offset":89769,"length":173,"previous":"M16-GAP-00524","next":"M16-GAP-00526"},"M16-GAP-00526":{"line":525,"offset":89942,"length":161,"previous":"M16-GAP-00525","next":"M16-GAP-00527"},"M16-GAP-00527":{"line":526,"offset":90103,"length":175,"previous":"M16-GAP-00526","next":"M16-GAP-00528"},"M16-GAP-00528":{"line":527,"offset":90278,"length":168,"previous":"M16-GAP-00527","next":"M16-GAP-00529"},"M16-GAP-00529":{"line":528,"offset":90446,"length":169,"previous":"M16-GAP-00528","next":"M16-GAP-00530"},"M16-GAP-00530":{"line":529,"offset":90615,"length":169,"previous":"M16-GAP-00529","next":"M16-GAP-00531"},"M16-GAP-00531":{"line":530,"offset":90784,"length":171,"previous":"M16-GAP-00530","next":"M16-GAP-00532"},"M16-GAP-00532":{"line":531,"offset":90955,"length":176,"previous":"M16-GAP-00531","next":"M16-GAP-00533"},"M16-GAP-00533":{"line":532,"offset":91131,"length":169,"previous":"M16-GAP-00532","next":"M16-GAP-00534"},"M16-GAP-00534":{"line":533,"offset":91300,"length":171,"previous":"M16-GAP-00533","next":"M16-GAP-00535"},"M16-GAP-00535":{"line":534,"offset":91471,"length":166,"previous":"M16-GAP-00534","next":"M16-GAP-00536"},"M16-GAP-00536":{"line":535,"offset":91637,"length":178,"previous":"M16-GAP-00535","next":"M16-GAP-00537"},"M16-GAP-00537":{"line":536,"offset":91815,"length":180,"previous":"M16-GAP-00536","next":"M16-GAP-00538"},"M16-GAP-00538":{"line":537,"offset":91995,"length":163,"previous":"M16-GAP-00537","next":"M16-GAP-00539"},"M16-GAP-00539":{"line":538,"offset":92158,"length":167,"previous":"M16-GAP-00538","next":"M16-GAP-00540"},"M16-GAP-00540":{"line":539,"offset":92325,"length":169,"previous":"M16-GAP-00539","next":"M16-GAP-00541"},"M16-GAP-00541":{"line":540,"offset":92494,"length":174,"previous":"M16-GAP-00540","next":"M16-GAP-00542"},"M16-GAP-00542":{"line":541,"offset":92668,"length":168,"previous":"M16-GAP-00541","next":"M16-GAP-00543"},"M16-GAP-00543":{"line":542,"offset":92836,"length":175,"previous":"M16-GAP-00542","next":"M16-GAP-00544"},"M16-GAP-00544":{"line":543,"offset":93011,"length":170,"previous":"M16-GAP-00543","next":"M16-GAP-00545"},"M16-GAP-00545":{"line":544,"offset":93181,"length":175,"previous":"M16-GAP-00544","next":"M16-GAP-00546"},"M16-GAP-00546":{"line":545,"offset":93356,"length":162,"previous":"M16-GAP-00545","next":"M16-GAP-00547"},"M16-GAP-00547":{"line":546,"offset":93518,"length":171,"previous":"M16-GAP-00546","next":"M16-GAP-00548"},"M16-GAP-00548":{"line":547,"offset":93689,"length":174,"previous":"M16-GAP-00547","next":"M16-GAP-00549"},"M16-GAP-00549":{"line":548,"offset":93863,"length":177,"previous":"M16-GAP-00548","next":"M16-GAP-00550"},"M16-GAP-00550":{"line":549,"offset":94040,"length":169,"previous":"M16-GAP-00549","next":"M16-GAP-00551"},"M16-GAP-00551":{"line":550,"offset":94209,"length":165,"previous":"M16-GAP-00550","next":"M16-GAP-00552"},"M16-GAP-00552":{"line":551,"offset":94374,"length":177,"previous":"M16-GAP-00551","next":"M16-GAP-00553"},"M16-GAP-00553":{"line":552,"offset":94551,"length":177,"previous":"M16-GAP-00552","next":"M16-GAP-00554"},"M16-GAP-00554":{"line":553,"offset":94728,"length":189,"previous":"M16-GAP-00553","next":"M16-GAP-00555"},"M16-GAP-00555":{"line":554,"offset":94917,"length":180,"previous":"M16-GAP-00554","next":"M16-GAP-00556"},"M16-GAP-00556":{"line":555,"offset":95097,"length":185,"previous":"M16-GAP-00555","next":"M16-GAP-00557"},"M16-GAP-00557":{"line":556,"offset":95282,"length":175,"previous":"M16-GAP-00556","next":"M16-GAP-00558"},"M16-GAP-00558":{"line":557,"offset":95457,"length":167,"previous":"M16-GAP-00557","next":"M16-GAP-00559"},"M16-GAP-00559":{"line":558,"offset":95624,"length":158,"previous":"M16-GAP-00558","next":"M16-GAP-00560"},"M16-GAP-00560":{"line":559,"offset":95782,"length":158,"previous":"M16-GAP-00559","next":"M16-GAP-00561"},"M16-GAP-00561":{"line":560,"offset":95940,"length":166,"previous":"M16-GAP-00560","next":"M16-GAP-00562"},"M16-GAP-00562":{"line":561,"offset":96106,"length":163,"previous":"M16-GAP-00561","next":"M16-GAP-00563"},"M16-GAP-00563":{"line":562,"offset":96269,"length":163,"previous":"M16-GAP-00562","next":"M16-GAP-00564"},"M16-GAP-00564":{"line":563,"offset":96432,"length":166,"previous":"M16-GAP-00563","next":"M16-GAP-00565"},"M16-GAP-00565":{"line":564,"offset":96598,"length":167,"previous":"M16-GAP-00564","next":"M16-GAP-00566"},"M16-GAP-00566":{"line":565,"offset":96765,"length":168,"previous":"M16-GAP-00565","next":"M16-GAP-00567"},"M16-GAP-00567":{"line":566,"offset":96933,"length":177,"previous":"M16-GAP-00566","next":"M16-GAP-00568"},"M16-GAP-00568":{"line":567,"offset":97110,"length":177,"previous":"M16-GAP-00567","next":"M16-GAP-00569"},"M16-GAP-00569":{"line":568,"offset":97287,"length":183,"previous":"M16-GAP-00568","next":"M16-GAP-00570"},"M16-GAP-00570":{"line":569,"offset":97470,"length":184,"previous":"M16-GAP-00569","next":"M16-GAP-00571"},"M16-GAP-00571":{"line":570,"offset":97654,"length":180,"previous":"M16-GAP-00570","next":"M16-GAP-00572"},"M16-GAP-00572":{"line":571,"offset":97834,"length":184,"previous":"M16-GAP-00571","next":"M16-GAP-00573"},"M16-GAP-00573":{"line":572,"offset":98018,"length":178,"previous":"M16-GAP-00572","next":"M16-GAP-00574"},"M16-GAP-00574":{"line":573,"offset":98196,"length":182,"previous":"M16-GAP-00573","next":"M16-GAP-00575"},"M16-GAP-00575":{"line":574,"offset":98378,"length":185,"previous":"M16-GAP-00574","next":"M16-GAP-00576"},"M16-GAP-00576":{"line":575,"offset":98563,"length":180,"previous":"M16-GAP-00575","next":"M16-GAP-00577"},"M16-GAP-00577":{"line":576,"offset":98743,"length":178,"previous":"M16-GAP-00576","next":"M16-GAP-00578"},"M16-GAP-00578":{"line":577,"offset":98921,"length":183,"previous":"M16-GAP-00577","next":"M16-GAP-00579"},"M16-GAP-00579":{"line":578,"offset":99104,"length":183,"previous":"M16-GAP-00578","next":"M16-GAP-00580"},"M16-GAP-00580":{"line":579,"offset":99287,"length":182,"previous":"M16-GAP-00579","next":"M16-GAP-00581"},"M16-GAP-00581":{"line":580,"offset":99469,"length":179,"previous":"M16-GAP-00580","next":"M16-GAP-00582"},"M16-GAP-00582":{"line":581,"offset":99648,"length":186,"previous":"M16-GAP-00581","next":"M16-GAP-00583"},"M16-GAP-00583":{"line":582,"offset":99834,"length":186,"previous":"M16-GAP-00582","next":"M16-GAP-00584"},"M16-GAP-00584":{"line":583,"offset":100020,"length":181,"previous":"M16-GAP-00583","next":"M16-GAP-00585"},"M16-GAP-00585":{"line":584,"offset":100201,"length":183,"previous":"M16-GAP-00584","next":"M16-GAP-00586"},"M16-GAP-00586":{"line":585,"offset":100384,"length":175,"previous":"M16-GAP-00585","next":"M16-GAP-00587"},"M16-GAP-00587":{"line":586,"offset":100559,"length":178,"previous":"M16-GAP-00586","next":"M16-GAP-00588"},"M16-GAP-00588":{"line":587,"offset":100737,"length":171,"previous":"M16-GAP-00587","next":"M16-GAP-00589"},"M16-GAP-00589":{"line":588,"offset":100908,"length":175,"previous":"M16-GAP-00588","next":"M16-GAP-00590"},"M16-GAP-00590":{"line":589,"offset":101083,"length":173,"previous":"M16-GAP-00589","next":"M16-GAP-00591"},"M16-GAP-00591":{"line":590,"offset":101256,"length":177,"previous":"M16-GAP-00590","next":"M16-GAP-00592"},"M16-GAP-00592":{"line":591,"offset":101433,"length":174,"previous":"M16-GAP-00591","next":"M16-GAP-00593"},"M16-GAP-00593":{"line":592,"offset":101607,"length":181,"previous":"M16-GAP-00592","next":"M16-GAP-00594"},"M16-GAP-00594":{"line":593,"offset":101788,"length":183,"previous":"M16-GAP-00593","next":"M16-GAP-00595"},"M16-GAP-00595":{"line":594,"offset":101971,"length":189,"previous":"M16-GAP-00594","next":"M16-GAP-00596"},"M16-GAP-00596":{"line":595,"offset":102160,"length":186,"previous":"M16-GAP-00595","next":"M16-GAP-00597"},"M16-GAP-00597":{"line":596,"offset":102346,"length":182,"previous":"M16-GAP-00596","next":"M16-GAP-00598"},"M16-GAP-00598":{"line":597,"offset":102528,"length":179,"previous":"M16-GAP-00597","next":"M16-GAP-00599"},"M16-GAP-00599":{"line":598,"offset":102707,"length":171,"previous":"M16-GAP-00598","next":"M16-GAP-00600"},"M16-GAP-00600":{"line":599,"offset":102878,"length":168,"previous":"M16-GAP-00599","next":"M16-GAP-00601"},"M16-GAP-00601":{"line":600,"offset":103046,"length":172,"previous":"M16-GAP-00600","next":"M16-GAP-00602"},"M16-GAP-00602":{"line":601,"offset":103218,"length":171,"previous":"M16-GAP-00601","next":"M16-GAP-00603"},"M16-GAP-00603":{"line":602,"offset":103389,"length":169,"previous":"M16-GAP-00602","next":"M16-GAP-00604"},"M16-GAP-00604":{"line":603,"offset":103558,"length":162,"previous":"M16-GAP-00603","next":"M16-GAP-00605"},"M16-GAP-00605":{"line":604,"offset":103720,"length":162,"previous":"M16-GAP-00604","next":"M16-GAP-00606"},"M16-GAP-00606":{"line":605,"offset":103882,"length":169,"previous":"M16-GAP-00605","next":"M16-GAP-00607"},"M16-GAP-00607":{"line":606,"offset":104051,"length":175,"previous":"M16-GAP-00606","next":"M16-GAP-00608"},"M16-GAP-00608":{"line":607,"offset":104226,"length":163,"previous":"M16-GAP-00607","next":"M16-GAP-00609"},"M16-GAP-00609":{"line":608,"offset":104389,"length":174,"previous":"M16-GAP-00608","next":"M16-GAP-00610"},"M16-GAP-00610":{"line":609,"offset":104563,"length":163,"previous":"M16-GAP-00609","next":"M16-GAP-00611"},"M16-GAP-00611":{"line":610,"offset":104726,"length":169,"previous":"M16-GAP-00610","next":"M16-GAP-00612"},"M16-GAP-00612":{"line":611,"offset":104895,"length":174,"previous":"M16-GAP-00611","next":"M16-GAP-00613"},"M16-GAP-00613":{"line":612,"offset":105069,"length":163,"previous":"M16-GAP-00612","next":"M16-GAP-00614"},"M16-GAP-00614":{"line":613,"offset":105232,"length":165,"previous":"M16-GAP-00613","next":"M16-GAP-00615"},"M16-GAP-00615":{"line":614,"offset":105397,"length":175,"previous":"M16-GAP-00614","next":"M16-GAP-00616"},"M16-GAP-00616":{"line":615,"offset":105572,"length":175,"previous":"M16-GAP-00615","next":"M16-GAP-00617"},"M16-GAP-00617":{"line":616,"offset":105747,"length":169,"previous":"M16-GAP-00616","next":"M16-GAP-00618"},"M16-GAP-00618":{"line":617,"offset":105916,"length":160,"previous":"M16-GAP-00617","next":"M16-GAP-00619"},"M16-GAP-00619":{"line":618,"offset":106076,"length":164,"previous":"M16-GAP-00618","next":"M16-GAP-00620"},"M16-GAP-00620":{"line":619,"offset":106240,"length":170,"previous":"M16-GAP-00619","next":"M16-GAP-00621"},"M16-GAP-00621":{"line":620,"offset":106410,"length":162,"previous":"M16-GAP-00620","next":"M16-GAP-00622"},"M16-GAP-00622":{"line":621,"offset":106572,"length":164,"previous":"M16-GAP-00621","next":"M16-GAP-00623"},"M16-GAP-00623":{"line":622,"offset":106736,"length":163,"previous":"M16-GAP-00622","next":"M16-GAP-00624"},"M16-GAP-00624":{"line":623,"offset":106899,"length":162,"previous":"M16-GAP-00623","next":"M16-GAP-00625"},"M16-GAP-00625":{"line":624,"offset":107061,"length":176,"previous":"M16-GAP-00624","next":"M16-GAP-00626"},"M16-GAP-00626":{"line":625,"offset":107237,"length":168,"previous":"M16-GAP-00625","next":"M16-GAP-00627"},"M16-GAP-00627":{"line":626,"offset":107405,"length":162,"previous":"M16-GAP-00626","next":"M16-GAP-00628"},"M16-GAP-00628":{"line":627,"offset":107567,"length":166,"previous":"M16-GAP-00627","next":"M16-GAP-00629"},"M16-GAP-00629":{"line":628,"offset":107733,"length":171,"previous":"M16-GAP-00628","next":"M16-GAP-00630"},"M16-GAP-00630":{"line":629,"offset":107904,"length":166,"previous":"M16-GAP-00629","next":"M16-GAP-00631"},"M16-GAP-00631":{"line":630,"offset":108070,"length":167,"previous":"M16-GAP-00630","next":"M16-GAP-00632"},"M16-GAP-00632":{"line":631,"offset":108237,"length":168,"previous":"M16-GAP-00631","next":"M16-GAP-00633"},"M16-GAP-00633":{"line":632,"offset":108405,"length":178,"previous":"M16-GAP-00632","next":"M16-GAP-00634"},"M16-GAP-00634":{"line":633,"offset":108583,"length":168,"previous":"M16-GAP-00633","next":"M16-GAP-00635"},"M16-GAP-00635":{"line":634,"offset":108751,"length":166,"previous":"M16-GAP-00634","next":"M16-GAP-00636"},"M16-GAP-00636":{"line":635,"offset":108917,"length":167,"previous":"M16-GAP-00635","next":"M16-GAP-00637"},"M16-GAP-00637":{"line":636,"offset":109084,"length":172,"previous":"M16-GAP-00636","next":"M16-GAP-00638"},"M16-GAP-00638":{"line":637,"offset":109256,"length":169,"previous":"M16-GAP-00637","next":"M16-GAP-00639"},"M16-GAP-00639":{"line":638,"offset":109425,"length":165,"previous":"M16-GAP-00638","next":"M16-GAP-00640"},"M16-GAP-00640":{"line":639,"offset":109590,"length":166,"previous":"M16-GAP-00639","next":"M16-GAP-00641"},"M16-GAP-00641":{"line":640,"offset":109756,"length":168,"previous":"M16-GAP-00640","next":"M16-GAP-00642"},"M16-GAP-00642":{"line":641,"offset":109924,"length":166,"previous":"M16-GAP-00641","next":"M16-GAP-00643"},"M16-GAP-00643":{"line":642,"offset":110090,"length":167,"previous":"M16-GAP-00642","next":"M16-GAP-00644"},"M16-GAP-00644":{"line":643,"offset":110257,"length":171,"previous":"M16-GAP-00643","next":"M16-GAP-00645"},"M16-GAP-00645":{"line":644,"offset":110428,"length":165,"previous":"M16-GAP-00644","next":"M16-GAP-00646"},"M16-GAP-00646":{"line":645,"offset":110593,"length":166,"previous":"M16-GAP-00645","next":"M16-GAP-00647"},"M16-GAP-00647":{"line":646,"offset":110759,"length":168,"previous":"M16-GAP-00646","next":"M16-GAP-00648"},"M16-GAP-00648":{"line":647,"offset":110927,"length":166,"previous":"M16-GAP-00647","next":"M16-GAP-00649"},"M16-GAP-00649":{"line":648,"offset":111093,"length":167,"previous":"M16-GAP-00648","next":"M16-GAP-00650"},"M16-GAP-00650":{"line":649,"offset":111260,"length":171,"previous":"M16-GAP-00649","next":"M16-GAP-00651"},"M16-GAP-00651":{"line":650,"offset":111431,"length":167,"previous":"M16-GAP-00650","next":"M16-GAP-00652"},"M16-GAP-00652":{"line":651,"offset":111598,"length":167,"previous":"M16-GAP-00651","next":"M16-GAP-00653"},"M16-GAP-00653":{"line":652,"offset":111765,"length":164,"previous":"M16-GAP-00652","next":"M16-GAP-00654"},"M16-GAP-00654":{"line":653,"offset":111929,"length":167,"previous":"M16-GAP-00653","next":"M16-GAP-00655"},"M16-GAP-00655":{"line":654,"offset":112096,"length":172,"previous":"M16-GAP-00654","next":"M16-GAP-00656"},"M16-GAP-00656":{"line":655,"offset":112268,"length":170,"previous":"M16-GAP-00655","next":"M16-GAP-00657"},"M16-GAP-00657":{"line":656,"offset":112438,"length":162,"previous":"M16-GAP-00656","next":"M16-GAP-00658"},"M16-GAP-00658":{"line":657,"offset":112600,"length":166,"previous":"M16-GAP-00657","next":"M16-GAP-00659"},"M16-GAP-00659":{"line":658,"offset":112766,"length":160,"previous":"M16-GAP-00658","next":"M16-GAP-00660"},"M16-GAP-00660":{"line":659,"offset":112926,"length":167,"previous":"M16-GAP-00659","next":"M16-GAP-00661"},"M16-GAP-00661":{"line":660,"offset":113093,"length":160,"previous":"M16-GAP-00660","next":"M16-GAP-00662"},"M16-GAP-00662":{"line":661,"offset":113253,"length":166,"previous":"M16-GAP-00661","next":"M16-GAP-00663"},"M16-GAP-00663":{"line":662,"offset":113419,"length":167,"previous":"M16-GAP-00662","next":"M16-GAP-00664"},"M16-GAP-00664":{"line":663,"offset":113586,"length":169,"previous":"M16-GAP-00663","next":"M16-GAP-00665"},"M16-GAP-00665":{"line":664,"offset":113755,"length":165,"previous":"M16-GAP-00664","next":"M16-GAP-00666"},"M16-GAP-00666":{"line":665,"offset":113920,"length":168,"previous":"M16-GAP-00665","next":"M16-GAP-00667"},"M16-GAP-00667":{"line":666,"offset":114088,"length":165,"previous":"M16-GAP-00666","next":"M16-GAP-00668"},"M16-GAP-00668":{"line":667,"offset":114253,"length":164,"previous":"M16-GAP-00667","next":"M16-GAP-00669"},"M16-GAP-00669":{"line":668,"offset":114417,"length":167,"previous":"M16-GAP-00668","next":"M16-GAP-00670"},"M16-GAP-00670":{"line":669,"offset":114584,"length":175,"previous":"M16-GAP-00669","next":"M16-GAP-00671"},"M16-GAP-00671":{"line":670,"offset":114759,"length":166,"previous":"M16-GAP-00670","next":"M16-GAP-00672"},"M16-GAP-00672":{"line":671,"offset":114925,"length":176,"previous":"M16-GAP-00671","next":"M16-GAP-00673"},"M16-GAP-00673":{"line":672,"offset":115101,"length":167,"previous":"M16-GAP-00672","next":"M16-GAP-00674"},"M16-GAP-00674":{"line":673,"offset":115268,"length":170,"previous":"M16-GAP-00673","next":"M16-GAP-00675"},"M16-GAP-00675":{"line":674,"offset":115438,"length":162,"previous":"M16-GAP-00674","next":"M16-GAP-00676"},"M16-GAP-00676":{"line":675,"offset":115600,"length":173,"previous":"M16-GAP-00675","next":"M16-GAP-00677"},"M16-GAP-00677":{"line":676,"offset":115773,"length":177,"previous":"M16-GAP-00676","next":"M16-GAP-00678"},"M16-GAP-00678":{"line":677,"offset":115950,"length":176,"previous":"M16-GAP-00677","next":"M16-GAP-00679"},"M16-GAP-00679":{"line":678,"offset":116126,"length":179,"previous":"M16-GAP-00678","next":"M16-GAP-00680"},"M16-GAP-00680":{"line":679,"offset":116305,"length":183,"previous":"M16-GAP-00679","next":"M16-GAP-00681"},"M16-GAP-00681":{"line":680,"offset":116488,"length":185,"previous":"M16-GAP-00680","next":"M16-GAP-00682"},"M16-GAP-00682":{"line":681,"offset":116673,"length":182,"previous":"M16-GAP-00681","next":"M16-GAP-00683"},"M16-GAP-00683":{"line":682,"offset":116855,"length":186,"previous":"M16-GAP-00682","next":"M16-GAP-00684"},"M16-GAP-00684":{"line":683,"offset":117041,"length":182,"previous":"M16-GAP-00683","next":"M16-GAP-00685"},"M16-GAP-00685":{"line":684,"offset":117223,"length":174,"previous":"M16-GAP-00684","next":"M16-GAP-00686"},"M16-GAP-00686":{"line":685,"offset":117397,"length":173,"previous":"M16-GAP-00685","next":"M16-GAP-00687"},"M16-GAP-00687":{"line":686,"offset":117570,"length":167,"previous":"M16-GAP-00686","next":"M16-GAP-00688"},"M16-GAP-00688":{"line":687,"offset":117737,"length":189,"previous":"M16-GAP-00687","next":"M16-GAP-00689"},"M16-GAP-00689":{"line":688,"offset":117926,"length":173,"previous":"M16-GAP-00688","next":"M16-GAP-00690"},"M16-GAP-00690":{"line":689,"offset":118099,"length":170,"previous":"M16-GAP-00689","next":"M16-GAP-00691"},"M16-GAP-00691":{"line":690,"offset":118269,"length":179,"previous":"M16-GAP-00690","next":"M16-GAP-00692"},"M16-GAP-00692":{"line":691,"offset":118448,"length":180,"previous":"M16-GAP-00691","next":"M16-GAP-00693"},"M16-GAP-00693":{"line":692,"offset":118628,"length":182,"previous":"M16-GAP-00692","next":"M16-GAP-00694"},"M16-GAP-00694":{"line":693,"offset":118810,"length":166,"previous":"M16-GAP-00693","next":"M16-GAP-00695"},"M16-GAP-00695":{"line":694,"offset":118976,"length":169,"previous":"M16-GAP-00694","next":"M16-GAP-00696"},"M16-GAP-00696":{"line":695,"offset":119145,"length":173,"previous":"M16-GAP-00695","next":"M16-GAP-00697"},"M16-GAP-00697":{"line":696,"offset":119318,"length":170,"previous":"M16-GAP-00696","next":"M16-GAP-00698"},"M16-GAP-00698":{"line":697,"offset":119488,"length":174,"previous":"M16-GAP-00697","next":"M16-GAP-00699"},"M16-GAP-00699":{"line":698,"offset":119662,"length":166,"previous":"M16-GAP-00698","next":"M16-GAP-00700"},"M16-GAP-00700":{"line":699,"offset":119828,"length":175,"previous":"M16-GAP-00699","next":"M16-GAP-00701"},"M16-GAP-00701":{"line":700,"offset":120003,"length":162,"previous":"M16-GAP-00700","next":"M16-GAP-00702"},"M16-GAP-00702":{"line":701,"offset":120165,"length":169,"previous":"M16-GAP-00701","next":"M16-GAP-00703"},"M16-GAP-00703":{"line":702,"offset":120334,"length":168,"previous":"M16-GAP-00702","next":"M16-GAP-00704"},"M16-GAP-00704":{"line":703,"offset":120502,"length":161,"previous":"M16-GAP-00703","next":"M16-GAP-00705"},"M16-GAP-00705":{"line":704,"offset":120663,"length":167,"previous":"M16-GAP-00704","next":"M16-GAP-00706"},"M16-GAP-00706":{"line":705,"offset":120830,"length":165,"previous":"M16-GAP-00705","next":"M16-GAP-00707"},"M16-GAP-00707":{"line":706,"offset":120995,"length":163,"previous":"M16-GAP-00706","next":"M16-GAP-00708"},"M16-GAP-00708":{"line":707,"offset":121158,"length":178,"previous":"M16-GAP-00707","next":"M16-GAP-00709"},"M16-GAP-00709":{"line":708,"offset":121336,"length":178,"previous":"M16-GAP-00708","next":"M16-GAP-00710"},"M16-GAP-00710":{"line":709,"offset":121514,"length":179,"previous":"M16-GAP-00709","next":"M16-GAP-00711"},"M16-GAP-00711":{"line":710,"offset":121693,"length":166,"previous":"M16-GAP-00710","next":"M16-GAP-00712"},"M16-GAP-00712":{"line":711,"offset":121859,"length":171,"previous":"M16-GAP-00711","next":"M16-GAP-00713"},"M16-GAP-00713":{"line":712,"offset":122030,"length":161,"previous":"M16-GAP-00712","next":"M16-GAP-00714"},"M16-GAP-00714":{"line":713,"offset":122191,"length":168,"previous":"M16-GAP-00713","next":"M16-GAP-00715"},"M16-GAP-00715":{"line":714,"offset":122359,"length":173,"previous":"M16-GAP-00714","next":"M16-GAP-00716"},"M16-GAP-00716":{"line":715,"offset":122532,"length":169,"previous":"M16-GAP-00715","next":"M16-GAP-00717"},"M16-GAP-00717":{"line":716,"offset":122701,"length":175,"previous":"M16-GAP-00716","next":"M16-GAP-00718"},"M16-GAP-00718":{"line":717,"offset":122876,"length":170,"previous":"M16-GAP-00717","next":"M16-GAP-00719"},"M16-GAP-00719":{"line":718,"offset":123046,"length":171,"previous":"M16-GAP-00718","next":"M16-GAP-00720"},"M16-GAP-00720":{"line":719,"offset":123217,"length":173,"previous":"M16-GAP-00719","next":"M16-GAP-00721"},"M16-GAP-00721":{"line":720,"offset":123390,"length":172,"previous":"M16-GAP-00720","next":"M16-GAP-00722"},"M16-GAP-00722":{"line":721,"offset":123562,"length":167,"previous":"M16-GAP-00721","next":"M16-GAP-00723"},"M16-GAP-00723":{"line":722,"offset":123729,"length":172,"previous":"M16-GAP-00722","next":"M16-GAP-00724"},"M16-GAP-00724":{"line":723,"offset":123901,"length":175,"previous":"M16-GAP-00723","next":"M16-GAP-00725"},"M16-GAP-00725":{"line":724,"offset":124076,"length":176,"previous":"M16-GAP-00724","next":"M16-GAP-00726"},"M16-GAP-00726":{"line":725,"offset":124252,"length":168,"previous":"M16-GAP-00725","next":"M16-GAP-00727"},"M16-GAP-00727":{"line":726,"offset":124420,"length":161,"previous":"M16-GAP-00726","next":"M16-GAP-00728"},"M16-GAP-00728":{"line":727,"offset":124581,"length":175,"previous":"M16-GAP-00727","next":"M16-GAP-00729"},"M16-GAP-00729":{"line":728,"offset":124756,"length":172,"previous":"M16-GAP-00728","next":"M16-GAP-00730"},"M16-GAP-00730":{"line":729,"offset":124928,"length":170,"previous":"M16-GAP-00729","next":"M16-GAP-00731"},"M16-GAP-00731":{"line":730,"offset":125098,"length":172,"previous":"M16-GAP-00730","next":"M16-GAP-00732"},"M16-GAP-00732":{"line":731,"offset":125270,"length":167,"previous":"M16-GAP-00731","next":"M16-GAP-00733"},"M16-GAP-00733":{"line":732,"offset":125437,"length":168,"previous":"M16-GAP-00732","next":"M16-GAP-00734"},"M16-GAP-00734":{"line":733,"offset":125605,"length":163,"previous":"M16-GAP-00733","next":"M16-GAP-00735"},"M16-GAP-00735":{"line":734,"offset":125768,"length":162,"previous":"M16-GAP-00734","next":"M16-GAP-00736"},"M16-GAP-00736":{"line":735,"offset":125930,"length":173,"previous":"M16-GAP-00735","next":"M16-GAP-00737"},"M16-GAP-00737":{"line":736,"offset":126103,"length":166,"previous":"M16-GAP-00736","next":"M16-GAP-00738"},"M16-GAP-00738":{"line":737,"offset":126269,"length":163,"previous":"M16-GAP-00737","next":"M16-GAP-00739"},"M16-GAP-00739":{"line":738,"offset":126432,"length":172,"previous":"M16-GAP-00738","next":"M16-GAP-00740"},"M16-GAP-00740":{"line":739,"offset":126604,"length":170,"previous":"M16-GAP-00739","next":"M16-GAP-00741"},"M16-GAP-00741":{"line":740,"offset":126774,"length":176,"previous":"M16-GAP-00740","next":"M16-GAP-00742"},"M16-GAP-00742":{"line":741,"offset":126950,"length":167,"previous":"M16-GAP-00741","next":"M16-GAP-00743"},"M16-GAP-00743":{"line":742,"offset":127117,"length":167,"previous":"M16-GAP-00742","next":"M16-GAP-00744"},"M16-GAP-00744":{"line":743,"offset":127284,"length":170,"previous":"M16-GAP-00743","next":"M16-GAP-00745"},"M16-GAP-00745":{"line":744,"offset":127454,"length":170,"previous":"M16-GAP-00744","next":"M16-GAP-00746"},"M16-GAP-00746":{"line":745,"offset":127624,"length":175,"previous":"M16-GAP-00745","next":"M16-GAP-00747"},"M16-GAP-00747":{"line":746,"offset":127799,"length":169,"previous":"M16-GAP-00746","next":"M16-GAP-00748"},"M16-GAP-00748":{"line":747,"offset":127968,"length":173,"previous":"M16-GAP-00747","next":"M16-GAP-00749"},"M16-GAP-00749":{"line":748,"offset":128141,"length":168,"previous":"M16-GAP-00748","next":"M16-GAP-00750"},"M16-GAP-00750":{"line":749,"offset":128309,"length":170,"previous":"M16-GAP-00749","next":"M16-GAP-00751"},"M16-GAP-00751":{"line":750,"offset":128479,"length":168,"previous":"M16-GAP-00750","next":"M16-GAP-00752"},"M16-GAP-00752":{"line":751,"offset":128647,"length":162,"previous":"M16-GAP-00751","next":"M16-GAP-00753"},"M16-GAP-00753":{"line":752,"offset":128809,"length":163,"previous":"M16-GAP-00752","next":"M16-GAP-00754"},"M16-GAP-00754":{"line":753,"offset":128972,"length":161,"previous":"M16-GAP-00753","next":"M16-GAP-00755"},"M16-GAP-00755":{"line":754,"offset":129133,"length":174,"previous":"M16-GAP-00754","next":"M16-GAP-00756"},"M16-GAP-00756":{"line":755,"offset":129307,"length":173,"previous":"M16-GAP-00755","next":"M16-GAP-00757"},"M16-GAP-00757":{"line":756,"offset":129480,"length":168,"previous":"M16-GAP-00756","next":"M16-GAP-00758"},"M16-GAP-00758":{"line":757,"offset":129648,"length":165,"previous":"M16-GAP-00757","next":"M16-GAP-00759"},"M16-GAP-00759":{"line":758,"offset":129813,"length":167,"previous":"M16-GAP-00758","next":"M16-GAP-00760"},"M16-GAP-00760":{"line":759,"offset":129980,"length":170,"previous":"M16-GAP-00759","next":"M16-GAP-00761"},"M16-GAP-00761":{"line":760,"offset":130150,"length":184,"previous":"M16-GAP-00760","next":"M16-GAP-00762"},"M16-GAP-00762":{"line":761,"offset":130334,"length":193,"previous":"M16-GAP-00761","next":"M16-GAP-00763"},"M16-GAP-00763":{"line":762,"offset":130527,"length":177,"previous":"M16-GAP-00762","next":"M16-GAP-00764"},"M16-GAP-00764":{"line":763,"offset":130704,"length":173,"previous":"M16-GAP-00763","next":"M16-GAP-00765"},"M16-GAP-00765":{"line":764,"offset":130877,"length":176,"previous":"M16-GAP-00764","next":"M16-GAP-00766"},"M16-GAP-00766":{"line":765,"offset":131053,"length":183,"previous":"M16-GAP-00765","next":"M16-GAP-00767"},"M16-GAP-00767":{"line":766,"offset":131236,"length":169,"previous":"M16-GAP-00766","next":"M16-GAP-00768"},"M16-GAP-00768":{"line":767,"offset":131405,"length":177,"previous":"M16-GAP-00767","next":"M16-GAP-00769"},"M16-GAP-00769":{"line":768,"offset":131582,"length":171,"previous":"M16-GAP-00768","next":"M16-GAP-00770"},"M16-GAP-00770":{"line":769,"offset":131753,"length":181,"previous":"M16-GAP-00769","next":"M16-GAP-00771"},"M16-GAP-00771":{"line":770,"offset":131934,"length":177,"previous":"M16-GAP-00770","next":"M16-GAP-00772"},"M16-GAP-00772":{"line":771,"offset":132111,"length":173,"previous":"M16-GAP-00771","next":"M16-GAP-00773"},"M16-GAP-00773":{"line":772,"offset":132284,"length":174,"previous":"M16-GAP-00772","next":"M16-GAP-00774"},"M16-GAP-00774":{"line":773,"offset":132458,"length":179,"previous":"M16-GAP-00773","next":"M16-GAP-00775"},"M16-GAP-00775":{"line":774,"offset":132637,"length":174,"previous":"M16-GAP-00774","next":"M16-GAP-00776"},"M16-GAP-00776":{"line":775,"offset":132811,"length":176,"previous":"M16-GAP-00775","next":"M16-GAP-00777"},"M16-GAP-00777":{"line":776,"offset":132987,"length":172,"previous":"M16-GAP-00776","next":"M16-GAP-00778"},"M16-GAP-00778":{"line":777,"offset":133159,"length":177,"previous":"M16-GAP-00777","next":"M16-GAP-00779"},"M16-GAP-00779":{"line":778,"offset":133336,"length":169,"previous":"M16-GAP-00778","next":"M16-GAP-00780"},"M16-GAP-00780":{"line":779,"offset":133505,"length":186,"previous":"M16-GAP-00779","next":"M16-GAP-00781"},"M16-GAP-00781":{"line":780,"offset":133691,"length":180,"previous":"M16-GAP-00780","next":"M16-GAP-00782"},"M16-GAP-00782":{"line":781,"offset":133871,"length":183,"previous":"M16-GAP-00781","next":"M16-GAP-00783"},"M16-GAP-00783":{"line":782,"offset":134054,"length":176,"previous":"M16-GAP-00782","next":"M16-GAP-00784"},"M16-GAP-00784":{"line":783,"offset":134230,"length":185,"previous":"M16-GAP-00783","next":"M16-GAP-00785"},"M16-GAP-00785":{"line":784,"offset":134415,"length":175,"previous":"M16-GAP-00784","next":"M16-GAP-00786"},"M16-GAP-00786":{"line":785,"offset":134590,"length":179,"previous":"M16-GAP-00785","next":"M16-GAP-00787"},"M16-GAP-00787":{"line":786,"offset":134769,"length":177,"previous":"M16-GAP-00786","next":"M16-GAP-00788"},"M16-GAP-00788":{"line":787,"offset":134946,"length":174,"previous":"M16-GAP-00787","next":"M16-GAP-00789"},"M16-GAP-00789":{"line":788,"offset":135120,"length":180,"previous":"M16-GAP-00788","next":"M16-GAP-00790"},"M16-GAP-00790":{"line":789,"offset":135300,"length":187,"previous":"M16-GAP-00789","next":"M16-GAP-00791"},"M16-GAP-00791":{"line":790,"offset":135487,"length":180,"previous":"M16-GAP-00790","next":"M16-GAP-00792"},"M16-GAP-00792":{"line":791,"offset":135667,"length":186,"previous":"M16-GAP-00791","next":"M16-GAP-00793"},"M16-GAP-00793":{"line":792,"offset":135853,"length":183,"previous":"M16-GAP-00792","next":"M16-GAP-00794"},"M16-GAP-00794":{"line":793,"offset":136036,"length":175,"previous":"M16-GAP-00793","next":"M16-GAP-00795"},"M16-GAP-00795":{"line":794,"offset":136211,"length":178,"previous":"M16-GAP-00794","next":"M16-GAP-00796"},"M16-GAP-00796":{"line":795,"offset":136389,"length":179,"previous":"M16-GAP-00795","next":"M16-GAP-00797"},"M16-GAP-00797":{"line":796,"offset":136568,"length":179,"previous":"M16-GAP-00796","next":"M16-GAP-00798"},"M16-GAP-00798":{"line":797,"offset":136747,"length":182,"previous":"M16-GAP-00797","next":"M16-GAP-00799"},"M16-GAP-00799":{"line":798,"offset":136929,"length":183,"previous":"M16-GAP-00798","next":"M16-GAP-00800"},"M16-GAP-00800":{"line":799,"offset":137112,"length":176,"previous":"M16-GAP-00799","next":"M16-GAP-00801"},"M16-GAP-00801":{"line":800,"offset":137288,"length":175,"previous":"M16-GAP-00800","next":"M16-GAP-00802"},"M16-GAP-00802":{"line":801,"offset":137463,"length":177,"previous":"M16-GAP-00801","next":"M16-GAP-00803"},"M16-GAP-00803":{"line":802,"offset":137640,"length":177,"previous":"M16-GAP-00802","next":"M16-GAP-00804"},"M16-GAP-00804":{"line":803,"offset":137817,"length":188,"previous":"M16-GAP-00803","next":"M16-GAP-00805"},"M16-GAP-00805":{"line":804,"offset":138005,"length":178,"previous":"M16-GAP-00804","next":"M16-GAP-00806"},"M16-GAP-00806":{"line":805,"offset":138183,"length":181,"previous":"M16-GAP-00805","next":"M16-GAP-00807"},"M16-GAP-00807":{"line":806,"offset":138364,"length":182,"previous":"M16-GAP-00806","next":"M16-GAP-00808"},"M16-GAP-00808":{"line":807,"offset":138546,"length":189,"previous":"M16-GAP-00807","next":"M16-GAP-00809"},"M16-GAP-00809":{"line":808,"offset":138735,"length":185,"previous":"M16-GAP-00808","next":"M16-GAP-00810"},"M16-GAP-00810":{"line":809,"offset":138920,"length":180,"previous":"M16-GAP-00809","next":"M16-GAP-00811"},"M16-GAP-00811":{"line":810,"offset":139100,"length":180,"previous":"M16-GAP-00810","next":"M16-GAP-00812"},"M16-GAP-00812":{"line":811,"offset":139280,"length":184,"previous":"M16-GAP-00811","next":"M16-GAP-00813"},"M16-GAP-00813":{"line":812,"offset":139464,"length":178,"previous":"M16-GAP-00812","next":"M16-GAP-00814"},"M16-GAP-00814":{"line":813,"offset":139642,"length":172,"previous":"M16-GAP-00813","next":"M16-GAP-00815"},"M16-GAP-00815":{"line":814,"offset":139814,"length":181,"previous":"M16-GAP-00814","next":"M16-GAP-00816"},"M16-GAP-00816":{"line":815,"offset":139995,"length":170,"previous":"M16-GAP-00815","next":"M16-GAP-00817"},"M16-GAP-00817":{"line":816,"offset":140165,"length":168,"previous":"M16-GAP-00816","next":"M16-GAP-00818"},"M16-GAP-00818":{"line":817,"offset":140333,"length":178,"previous":"M16-GAP-00817","next":"M16-GAP-00819"},"M16-GAP-00819":{"line":818,"offset":140511,"length":178,"previous":"M16-GAP-00818","next":"M16-GAP-00820"},"M16-GAP-00820":{"line":819,"offset":140689,"length":181,"previous":"M16-GAP-00819","next":"M16-GAP-00821"},"M16-GAP-00821":{"line":820,"offset":140870,"length":180,"previous":"M16-GAP-00820","next":"M16-GAP-00822"},"M16-GAP-00822":{"line":821,"offset":141050,"length":179,"previous":"M16-GAP-00821","next":"M16-GAP-00823"},"M16-GAP-00823":{"line":822,"offset":141229,"length":183,"previous":"M16-GAP-00822","next":"M16-GAP-00824"},"M16-GAP-00824":{"line":823,"offset":141412,"length":188,"previous":"M16-GAP-00823","next":"M16-GAP-00825"},"M16-GAP-00825":{"line":824,"offset":141600,"length":183,"previous":"M16-GAP-00824","next":"M16-GAP-00826"},"M16-GAP-00826":{"line":825,"offset":141783,"length":172,"previous":"M16-GAP-00825","next":"M16-GAP-00827"},"M16-GAP-00827":{"line":826,"offset":141955,"length":174,"previous":"M16-GAP-00826","next":"M16-GAP-00828"},"M16-GAP-00828":{"line":827,"offset":142129,"length":174,"previous":"M16-GAP-00827","next":"M16-GAP-00829"},"M16-GAP-00829":{"line":828,"offset":142303,"length":177,"previous":"M16-GAP-00828","next":"M16-GAP-00830"},"M16-GAP-00830":{"line":829,"offset":142480,"length":182,"previous":"M16-GAP-00829","next":"M16-GAP-00831"},"M16-GAP-00831":{"line":830,"offset":142662,"length":175,"previous":"M16-GAP-00830","next":"M16-GAP-00832"},"M16-GAP-00832":{"line":831,"offset":142837,"length":181,"previous":"M16-GAP-00831","next":"M16-GAP-00833"},"M16-GAP-00833":{"line":832,"offset":143018,"length":186,"previous":"M16-GAP-00832","next":"M16-GAP-00834"},"M16-GAP-00834":{"line":833,"offset":143204,"length":176,"previous":"M16-GAP-00833","next":"M16-GAP-00835"},"M16-GAP-00835":{"line":834,"offset":143380,"length":176,"previous":"M16-GAP-00834","next":"M16-GAP-00836"},"M16-GAP-00836":{"line":835,"offset":143556,"length":176,"previous":"M16-GAP-00835","next":"M16-GAP-00837"},"M16-GAP-00837":{"line":836,"offset":143732,"length":178,"previous":"M16-GAP-00836","next":"M16-GAP-00838"},"M16-GAP-00838":{"line":837,"offset":143910,"length":176,"previous":"M16-GAP-00837","next":"M16-GAP-00839"},"M16-GAP-00839":{"line":838,"offset":144086,"length":178,"previous":"M16-GAP-00838","next":"M16-GAP-00840"},"M16-GAP-00840":{"line":839,"offset":144264,"length":179,"previous":"M16-GAP-00839","next":"M16-GAP-00841"},"M16-GAP-00841":{"line":840,"offset":144443,"length":173,"previous":"M16-GAP-00840","next":"M16-GAP-00842"},"M16-GAP-00842":{"line":841,"offset":144616,"length":179,"previous":"M16-GAP-00841","next":"M16-GAP-00843"},"M16-GAP-00843":{"line":842,"offset":144795,"length":184,"previous":"M16-GAP-00842","next":"M16-GAP-00844"},"M16-GAP-00844":{"line":843,"offset":144979,"length":180,"previous":"M16-GAP-00843","next":"M16-GAP-00845"},"M16-GAP-00845":{"line":844,"offset":145159,"length":185,"previous":"M16-GAP-00844","next":"M16-GAP-00846"},"M16-GAP-00846":{"line":845,"offset":145344,"length":179,"previous":"M16-GAP-00845","next":"M16-GAP-00847"},"M16-GAP-00847":{"line":846,"offset":145523,"length":180,"previous":"M16-GAP-00846","next":"M16-GAP-00848"},"M16-GAP-00848":{"line":847,"offset":145703,"length":177,"previous":"M16-GAP-00847","next":"M16-GAP-00849"},"M16-GAP-00849":{"line":848,"offset":145880,"length":183,"previous":"M16-GAP-00848","next":"M16-GAP-00850"},"M16-GAP-00850":{"line":849,"offset":146063,"length":180,"previous":"M16-GAP-00849","next":"M16-GAP-00851"},"M16-GAP-00851":{"line":850,"offset":146243,"length":180,"previous":"M16-GAP-00850","next":"M16-GAP-00852"},"M16-GAP-00852":{"line":851,"offset":146423,"length":184,"previous":"M16-GAP-00851","next":"M16-GAP-00853"},"M16-GAP-00853":{"line":852,"offset":146607,"length":186,"previous":"M16-GAP-00852","next":"M16-GAP-00854"},"M16-GAP-00854":{"line":853,"offset":146793,"length":188,"previous":"M16-GAP-00853","next":"M16-GAP-00855"},"M16-GAP-00855":{"line":854,"offset":146981,"length":179,"previous":"M16-GAP-00854","next":"M16-GAP-00856"},"M16-GAP-00856":{"line":855,"offset":147160,"length":177,"previous":"M16-GAP-00855","next":"M16-GAP-00857"},"M16-GAP-00857":{"line":856,"offset":147337,"length":184,"previous":"M16-GAP-00856","next":"M16-GAP-00858"},"M16-GAP-00858":{"line":857,"offset":147521,"length":189,"previous":"M16-GAP-00857","next":"M16-GAP-00859"},"M16-GAP-00859":{"line":858,"offset":147710,"length":190,"previous":"M16-GAP-00858","next":"M16-GAP-00860"},"M16-GAP-00860":{"line":859,"offset":147900,"length":180,"previous":"M16-GAP-00859","next":"M16-GAP-00861"},"M16-GAP-00861":{"line":860,"offset":148080,"length":178,"previous":"M16-GAP-00860","next":"M16-GAP-00862"},"M16-GAP-00862":{"line":861,"offset":148258,"length":177,"previous":"M16-GAP-00861","next":"M16-GAP-00863"},"M16-GAP-00863":{"line":862,"offset":148435,"length":181,"previous":"M16-GAP-00862","next":"M16-GAP-00864"},"M16-GAP-00864":{"line":863,"offset":148616,"length":188,"previous":"M16-GAP-00863","next":"M16-GAP-00865"},"M16-GAP-00865":{"line":864,"offset":148804,"length":188,"previous":"M16-GAP-00864","next":"M16-GAP-00866"},"M16-GAP-00866":{"line":865,"offset":148992,"length":176,"previous":"M16-GAP-00865","next":"M16-GAP-00867"},"M16-GAP-00867":{"line":866,"offset":149168,"length":181,"previous":"M16-GAP-00866","next":"M16-GAP-00868"},"M16-GAP-00868":{"line":867,"offset":149349,"length":176,"previous":"M16-GAP-00867","next":"M16-GAP-00869"},"M16-GAP-00869":{"line":868,"offset":149525,"length":184,"previous":"M16-GAP-00868","next":"M16-GAP-00870"},"M16-GAP-00870":{"line":869,"offset":149709,"length":197,"previous":"M16-GAP-00869","next":"M16-GAP-00871"},"M16-GAP-00871":{"line":870,"offset":149906,"length":181,"previous":"M16-GAP-00870","next":"M16-GAP-00872"},"M16-GAP-00872":{"line":871,"offset":150087,"length":184,"previous":"M16-GAP-00871","next":"M16-GAP-00873"},"M16-GAP-00873":{"line":872,"offset":150271,"length":184,"previous":"M16-GAP-00872","next":"M16-GAP-00874"},"M16-GAP-00874":{"line":873,"offset":150455,"length":181,"previous":"M16-GAP-00873","next":"M16-GAP-00875"},"M16-GAP-00875":{"line":874,"offset":150636,"length":187,"previous":"M16-GAP-00874","next":"M16-GAP-00876"},"M16-GAP-00876":{"line":875,"offset":150823,"length":191,"previous":"M16-GAP-00875","next":"M16-GAP-00877"},"M16-GAP-00877":{"line":876,"offset":151014,"length":184,"previous":"M16-GAP-00876","next":"M16-GAP-00878"},"M16-GAP-00878":{"line":877,"offset":151198,"length":182,"previous":"M16-GAP-00877","next":"M16-GAP-00879"},"M16-GAP-00879":{"line":878,"offset":151380,"length":184,"previous":"M16-GAP-00878","next":"M16-GAP-00880"},"M16-GAP-00880":{"line":879,"offset":151564,"length":178,"previous":"M16-GAP-00879","next":"M16-GAP-00881"},"M16-GAP-00881":{"line":880,"offset":151742,"length":178,"previous":"M16-GAP-00880","next":"M16-GAP-00882"},"M16-GAP-00882":{"line":881,"offset":151920,"length":188,"previous":"M16-GAP-00881","next":"M16-GAP-00883"},"M16-GAP-00883":{"line":882,"offset":152108,"length":182,"previous":"M16-GAP-00882","next":"M16-GAP-00884"},"M16-GAP-00884":{"line":883,"offset":152290,"length":172,"previous":"M16-GAP-00883","next":"M16-GAP-00885"},"M16-GAP-00885":{"line":884,"offset":152462,"length":169,"previous":"M16-GAP-00884","next":"M16-GAP-00886"},"M16-GAP-00886":{"line":885,"offset":152631,"length":176,"previous":"M16-GAP-00885","next":"M16-GAP-00887"},"M16-GAP-00887":{"line":886,"offset":152807,"length":174,"previous":"M16-GAP-00886","next":"M16-GAP-00888"},"M16-GAP-00888":{"line":887,"offset":152981,"length":171,"previous":"M16-GAP-00887","next":"M16-GAP-00889"},"M16-GAP-00889":{"line":888,"offset":153152,"length":172,"previous":"M16-GAP-00888","next":"M16-GAP-00890"},"M16-GAP-00890":{"line":889,"offset":153324,"length":178,"previous":"M16-GAP-00889","next":"M16-GAP-00891"},"M16-GAP-00891":{"line":890,"offset":153502,"length":173,"previous":"M16-GAP-00890","next":"M16-GAP-00892"},"M16-GAP-00892":{"line":891,"offset":153675,"length":174,"previous":"M16-GAP-00891","next":"M16-GAP-00893"},"M16-GAP-00893":{"line":892,"offset":153849,"length":170,"previous":"M16-GAP-00892","next":"M16-GAP-00894"},"M16-GAP-00894":{"line":893,"offset":154019,"length":168,"previous":"M16-GAP-00893","next":"M16-GAP-00895"},"M16-GAP-00895":{"line":894,"offset":154187,"length":161,"previous":"M16-GAP-00894","next":"M16-GAP-00896"},"M16-GAP-00896":{"line":895,"offset":154348,"length":178,"previous":"M16-GAP-00895","next":"M16-GAP-00897"},"M16-GAP-00897":{"line":896,"offset":154526,"length":163,"previous":"M16-GAP-00896","next":"M16-GAP-00898"},"M16-GAP-00898":{"line":897,"offset":154689,"length":175,"previous":"M16-GAP-00897","next":"M16-GAP-00899"},"M16-GAP-00899":{"line":898,"offset":154864,"length":160,"previous":"M16-GAP-00898","next":"M16-GAP-00900"},"M16-GAP-00900":{"line":899,"offset":155024,"length":161,"previous":"M16-GAP-00899","next":"M16-GAP-00901"},"M16-GAP-00901":{"line":900,"offset":155185,"length":168,"previous":"M16-GAP-00900","next":"M16-GAP-00902"},"M16-GAP-00902":{"line":901,"offset":155353,"length":161,"previous":"M16-GAP-00901","next":"M16-GAP-00903"},"M16-GAP-00903":{"line":902,"offset":155514,"length":170,"previous":"M16-GAP-00902","next":"M16-GAP-00904"},"M16-GAP-00904":{"line":903,"offset":155684,"length":169,"previous":"M16-GAP-00903","next":"M16-GAP-00905"},"M16-GAP-00905":{"line":904,"offset":155853,"length":172,"previous":"M16-GAP-00904","next":"M16-GAP-00906"},"M16-GAP-00906":{"line":905,"offset":156025,"length":163,"previous":"M16-GAP-00905","next":"M16-GAP-00907"},"M16-GAP-00907":{"line":906,"offset":156188,"length":175,"previous":"M16-GAP-00906","next":"M16-GAP-00908"},"M16-GAP-00908":{"line":907,"offset":156363,"length":170,"previous":"M16-GAP-00907","next":"M16-GAP-00909"},"M16-GAP-00909":{"line":908,"offset":156533,"length":164,"previous":"M16-GAP-00908","next":"M16-GAP-00910"},"M16-GAP-00910":{"line":909,"offset":156697,"length":163,"previous":"M16-GAP-00909","next":"M16-GAP-00911"},"M16-GAP-00911":{"line":910,"offset":156860,"length":174,"previous":"M16-GAP-00910","next":"M16-GAP-00912"},"M16-GAP-00912":{"line":911,"offset":157034,"length":163,"previous":"M16-GAP-00911","next":"M16-GAP-00913"},"M16-GAP-00913":{"line":912,"offset":157197,"length":168,"previous":"M16-GAP-00912","next":"M16-GAP-00914"},"M16-GAP-00914":{"line":913,"offset":157365,"length":161,"previous":"M16-GAP-00913","next":"M16-GAP-00915"},"M16-GAP-00915":{"line":914,"offset":157526,"length":174,"previous":"M16-GAP-00914","next":"M16-GAP-00916"},"M16-GAP-00916":{"line":915,"offset":157700,"length":164,"previous":"M16-GAP-00915","next":"M16-GAP-00917"},"M16-GAP-00917":{"line":916,"offset":157864,"length":170,"previous":"M16-GAP-00916","next":"M16-GAP-00918"},"M16-GAP-00918":{"line":917,"offset":158034,"length":165,"previous":"M16-GAP-00917","next":"M16-GAP-00919"},"M16-GAP-00919":{"line":918,"offset":158199,"length":166,"previous":"M16-GAP-00918","next":"M16-GAP-00920"},"M16-GAP-00920":{"line":919,"offset":158365,"length":168,"previous":"M16-GAP-00919","next":"M16-GAP-00921"},"M16-GAP-00921":{"line":920,"offset":158533,"length":163,"previous":"M16-GAP-00920","next":"M16-GAP-00922"},"M16-GAP-00922":{"line":921,"offset":158696,"length":165,"previous":"M16-GAP-00921","next":"M16-GAP-00923"},"M16-GAP-00923":{"line":922,"offset":158861,"length":175,"previous":"M16-GAP-00922","next":"M16-GAP-00924"},"M16-GAP-00924":{"line":923,"offset":159036,"length":175,"previous":"M16-GAP-00923","next":"M16-GAP-00925"},"M16-GAP-00925":{"line":924,"offset":159211,"length":166,"previous":"M16-GAP-00924","next":"M16-GAP-00926"},"M16-GAP-00926":{"line":925,"offset":159377,"length":165,"previous":"M16-GAP-00925","next":"M16-GAP-00927"},"M16-GAP-00927":{"line":926,"offset":159542,"length":170,"previous":"M16-GAP-00926","next":"M16-GAP-00928"},"M16-GAP-00928":{"line":927,"offset":159712,"length":166,"previous":"M16-GAP-00927","next":"M16-GAP-00929"},"M16-GAP-00929":{"line":928,"offset":159878,"length":173,"previous":"M16-GAP-00928","next":"M16-GAP-00930"},"M16-GAP-00930":{"line":929,"offset":160051,"length":169,"previous":"M16-GAP-00929","next":"M16-GAP-00931"},"M16-GAP-00931":{"line":930,"offset":160220,"length":170,"previous":"M16-GAP-00930","next":"M16-GAP-00932"},"M16-GAP-00932":{"line":931,"offset":160390,"length":172,"previous":"M16-GAP-00931","next":"M16-GAP-00933"},"M16-GAP-00933":{"line":932,"offset":160562,"length":166,"previous":"M16-GAP-00932","next":"M16-GAP-00934"},"M16-GAP-00934":{"line":933,"offset":160728,"length":167,"previous":"M16-GAP-00933","next":"M16-GAP-00935"},"M16-GAP-00935":{"line":934,"offset":160895,"length":167,"previous":"M16-GAP-00934","next":"M16-GAP-00936"},"M16-GAP-00936":{"line":935,"offset":161062,"length":168,"previous":"M16-GAP-00935","next":"M16-GAP-00937"},"M16-GAP-00937":{"line":936,"offset":161230,"length":167,"previous":"M16-GAP-00936","next":"M16-GAP-00938"},"M16-GAP-00938":{"line":937,"offset":161397,"length":169,"previous":"M16-GAP-00937","next":"M16-GAP-00939"},"M16-GAP-00939":{"line":938,"offset":161566,"length":169,"previous":"M16-GAP-00938","next":"M16-GAP-00940"},"M16-GAP-00940":{"line":939,"offset":161735,"length":178,"previous":"M16-GAP-00939","next":"M16-GAP-00941"},"M16-GAP-00941":{"line":940,"offset":161913,"length":166,"previous":"M16-GAP-00940","next":"M16-GAP-00942"},"M16-GAP-00942":{"line":941,"offset":162079,"length":166,"previous":"M16-GAP-00941","next":"M16-GAP-00943"},"M16-GAP-00943":{"line":942,"offset":162245,"length":167,"previous":"M16-GAP-00942","next":"M16-GAP-00944"},"M16-GAP-00944":{"line":943,"offset":162412,"length":163,"previous":"M16-GAP-00943","next":"M16-GAP-00945"},"M16-GAP-00945":{"line":944,"offset":162575,"length":171,"previous":"M16-GAP-00944","next":"M16-GAP-00946"},"M16-GAP-00946":{"line":945,"offset":162746,"length":169,"previous":"M16-GAP-00945","next":"M16-GAP-00947"},"M16-GAP-00947":{"line":946,"offset":162915,"length":170,"previous":"M16-GAP-00946","next":"M16-GAP-00948"},"M16-GAP-00948":{"line":947,"offset":163085,"length":172,"previous":"M16-GAP-00947","next":"M16-GAP-00949"},"M16-GAP-00949":{"line":948,"offset":163257,"length":170,"previous":"M16-GAP-00948","next":"M16-GAP-00950"},"M16-GAP-00950":{"line":949,"offset":163427,"length":172,"previous":"M16-GAP-00949","next":"M16-GAP-00951"},"M16-GAP-00951":{"line":950,"offset":163599,"length":175,"previous":"M16-GAP-00950","next":"M16-GAP-00952"},"M16-GAP-00952":{"line":951,"offset":163774,"length":161,"previous":"M16-GAP-00951","next":"M16-GAP-00953"},"M16-GAP-00953":{"line":952,"offset":163935,"length":169,"previous":"M16-GAP-00952","next":"M16-GAP-00954"},"M16-GAP-00954":{"line":953,"offset":164104,"length":164,"previous":"M16-GAP-00953","next":"M16-GAP-00955"},"M16-GAP-00955":{"line":954,"offset":164268,"length":167,"previous":"M16-GAP-00954","next":"M16-GAP-00956"},"M16-GAP-00956":{"line":955,"offset":164435,"length":174,"previous":"M16-GAP-00955","next":"M16-GAP-00957"},"M16-GAP-00957":{"line":956,"offset":164609,"length":162,"previous":"M16-GAP-00956","next":"M16-GAP-00958"},"M16-GAP-00958":{"line":957,"offset":164771,"length":164,"previous":"M16-GAP-00957","next":"M16-GAP-00959"},"M16-GAP-00959":{"line":958,"offset":164935,"length":164,"previous":"M16-GAP-00958","next":"M16-GAP-00960"},"M16-GAP-00960":{"line":959,"offset":165099,"length":168,"previous":"M16-GAP-00959","next":"M16-GAP-00961"},"M16-GAP-00961":{"line":960,"offset":165267,"length":168,"previous":"M16-GAP-00960","next":"M16-GAP-00962"},"M16-GAP-00962":{"line":961,"offset":165435,"length":174,"previous":"M16-GAP-00961","next":"M16-GAP-00963"},"M16-GAP-00963":{"line":962,"offset":165609,"length":174,"previous":"M16-GAP-00962","next":"M16-GAP-00964"},"M16-GAP-00964":{"line":963,"offset":165783,"length":180,"previous":"M16-GAP-00963","next":"M16-GAP-00965"},"M16-GAP-00965":{"line":964,"offset":165963,"length":166,"previous":"M16-GAP-00964","next":"M16-GAP-00966"},"M16-GAP-00966":{"line":965,"offset":166129,"length":172,"previous":"M16-GAP-00965","next":"M16-GAP-00967"},"M16-GAP-00967":{"line":966,"offset":166301,"length":168,"previous":"M16-GAP-00966","next":"M16-GAP-00968"},"M16-GAP-00968":{"line":967,"offset":166469,"length":169,"previous":"M16-GAP-00967","next":"M16-GAP-00969"},"M16-GAP-00969":{"line":968,"offset":166638,"length":162,"previous":"M16-GAP-00968","next":"M16-GAP-00970"},"M16-GAP-00970":{"line":969,"offset":166800,"length":165,"previous":"M16-GAP-00969","next":"M16-GAP-00971"},"M16-GAP-00971":{"line":970,"offset":166965,"length":170,"previous":"M16-GAP-00970","next":"M16-GAP-00972"},"M16-GAP-00972":{"line":971,"offset":167135,"length":176,"previous":"M16-GAP-00971","next":"M16-GAP-00973"},"M16-GAP-00973":{"line":972,"offset":167311,"length":171,"previous":"M16-GAP-00972","next":"M16-GAP-00974"},"M16-GAP-00974":{"line":973,"offset":167482,"length":171,"previous":"M16-GAP-00973","next":"M16-GAP-00975"},"M16-GAP-00975":{"line":974,"offset":167653,"length":169,"previous":"M16-GAP-00974","next":"M16-GAP-00976"},"M16-GAP-00976":{"line":975,"offset":167822,"length":166,"previous":"M16-GAP-00975","next":"M16-GAP-00977"},"M16-GAP-00977":{"line":976,"offset":167988,"length":165,"previous":"M16-GAP-00976","next":"M16-GAP-00978"},"M16-GAP-00978":{"line":977,"offset":168153,"length":168,"previous":"M16-GAP-00977","next":"M16-GAP-00979"},"M16-GAP-00979":{"line":978,"offset":168321,"length":169,"previous":"M16-GAP-00978","next":"M16-GAP-00980"},"M16-GAP-00980":{"line":979,"offset":168490,"length":159,"previous":"M16-GAP-00979","next":"M16-GAP-00981"},"M16-GAP-00981":{"line":980,"offset":168649,"length":179,"previous":"M16-GAP-00980","next":"M16-GAP-00982"},"M16-GAP-00982":{"line":981,"offset":168828,"length":168,"previous":"M16-GAP-00981","next":"M16-GAP-00983"},"M16-GAP-00983":{"line":982,"offset":168996,"length":166,"previous":"M16-GAP-00982","next":"M16-GAP-00984"},"M16-GAP-00984":{"line":983,"offset":169162,"length":169,"previous":"M16-GAP-00983","next":"M16-GAP-00985"},"M16-GAP-00985":{"line":984,"offset":169331,"length":176,"previous":"M16-GAP-00984","next":"M16-GAP-00986"},"M16-GAP-00986":{"line":985,"offset":169507,"length":176,"previous":"M16-GAP-00985","next":"M16-GAP-00987"},"M16-GAP-00987":{"line":986,"offset":169683,"length":162,"previous":"M16-GAP-00986","next":"M16-GAP-00988"},"M16-GAP-00988":{"line":987,"offset":169845,"length":166,"previous":"M16-GAP-00987","next":"M16-GAP-00989"},"M16-GAP-00989":{"line":988,"offset":170011,"length":166,"previous":"M16-GAP-00988","next":"M16-GAP-00990"},"M16-GAP-00990":{"line":989,"offset":170177,"length":169,"previous":"M16-GAP-00989","next":"M16-GAP-00991"},"M16-GAP-00991":{"line":990,"offset":170346,"length":168,"previous":"M16-GAP-00990","next":"M16-GAP-00992"},"M16-GAP-00992":{"line":991,"offset":170514,"length":167,"previous":"M16-GAP-00991","next":"M16-GAP-00993"},"M16-GAP-00993":{"line":992,"offset":170681,"length":169,"previous":"M16-GAP-00992","next":"M16-GAP-00994"},"M16-GAP-00994":{"line":993,"offset":170850,"length":174,"previous":"M16-GAP-00993","next":"M16-GAP-00995"},"M16-GAP-00995":{"line":994,"offset":171024,"length":167,"previous":"M16-GAP-00994","next":"M16-GAP-00996"},"M16-GAP-00996":{"line":995,"offset":171191,"length":171,"previous":"M16-GAP-00995","next":"M16-GAP-00997"},"M16-GAP-00997":{"line":996,"offset":171362,"length":179,"previous":"M16-GAP-00996","next":"M16-GAP-00998"},"M16-GAP-00998":{"line":997,"offset":171541,"length":172,"previous":"M16-GAP-00997","next":"M16-GAP-00999"},"M16-GAP-00999":{"line":998,"offset":171713,"length":171,"previous":"M16-GAP-00998","next":"M16-GAP-01000"},"M16-GAP-01000":{"line":999,"offset":171884,"length":167,"previous":"M16-GAP-00999","next":"M16-GAP-01001"},"M16-GAP-01001":{"line":1000,"offset":172051,"length":178,"previous":"M16-GAP-01000","next":"M16-GAP-01002"},"M16-GAP-01002":{"line":1001,"offset":172229,"length":172,"previous":"M16-GAP-01001","next":"M16-GAP-01003"},"M16-GAP-01003":{"line":1002,"offset":172401,"length":164,"previous":"M16-GAP-01002","next":"M16-GAP-01004"},"M16-GAP-01004":{"line":1003,"offset":172565,"length":163,"previous":"M16-GAP-01003","next":"M16-GAP-01005"},"M16-GAP-01005":{"line":1004,"offset":172728,"length":165,"previous":"M16-GAP-01004","next":"M16-GAP-01006"},"M16-GAP-01006":{"line":1005,"offset":172893,"length":173,"previous":"M16-GAP-01005","next":"M16-GAP-01007"},"M16-GAP-01007":{"line":1006,"offset":173066,"length":176,"previous":"M16-GAP-01006","next":"M16-GAP-01008"},"M16-GAP-01008":{"line":1007,"offset":173242,"length":171,"previous":"M16-GAP-01007","next":"M16-GAP-01009"},"M16-GAP-01009":{"line":1008,"offset":173413,"length":171,"previous":"M16-GAP-01008","next":"M16-GAP-01010"},"M16-GAP-01010":{"line":1009,"offset":173584,"length":173,"previous":"M16-GAP-01009","next":"M16-GAP-01011"},"M16-GAP-01011":{"line":1010,"offset":173757,"length":167,"previous":"M16-GAP-01010","next":"M16-GAP-01012"},"M16-GAP-01012":{"line":1011,"offset":173924,"length":180,"previous":"M16-GAP-01011","next":"M16-GAP-01013"},"M16-GAP-01013":{"line":1012,"offset":174104,"length":171,"previous":"M16-GAP-01012","next":"M16-GAP-01014"},"M16-GAP-01014":{"line":1013,"offset":174275,"length":169,"previous":"M16-GAP-01013","next":"M16-GAP-01015"},"M16-GAP-01015":{"line":1014,"offset":174444,"length":171,"previous":"M16-GAP-01014","next":"M16-GAP-01016"},"M16-GAP-01016":{"line":1015,"offset":174615,"length":169,"previous":"M16-GAP-01015","next":"M16-GAP-01017"},"M16-GAP-01017":{"line":1016,"offset":174784,"length":161,"previous":"M16-GAP-01016","next":"M16-GAP-01018"},"M16-GAP-01018":{"line":1017,"offset":174945,"length":162,"previous":"M16-GAP-01017","next":"M16-GAP-01019"},"M16-GAP-01019":{"line":1018,"offset":175107,"length":172,"previous":"M16-GAP-01018","next":"M16-GAP-01020"},"M16-GAP-01020":{"line":1019,"offset":175279,"length":173,"previous":"M16-GAP-01019","next":"M16-GAP-01021"},"M16-GAP-01021":{"line":1020,"offset":175452,"length":167,"previous":"M16-GAP-01020","next":"M16-GAP-01022"},"M16-GAP-01022":{"line":1021,"offset":175619,"length":170,"previous":"M16-GAP-01021","next":"M16-GAP-01023"},"M16-GAP-01023":{"line":1022,"offset":175789,"length":169,"previous":"M16-GAP-01022","next":"M16-GAP-01024"},"M16-GAP-01024":{"line":1023,"offset":175958,"length":167,"previous":"M16-GAP-01023","next":"M16-GAP-01025"},"M16-GAP-01025":{"line":1024,"offset":176125,"length":190,"previous":"M16-GAP-01024","next":"M16-GAP-01026"},"M16-GAP-01026":{"line":1025,"offset":176315,"length":192,"previous":"M16-GAP-01025","next":"M16-GAP-01027"},"M16-GAP-01027":{"line":1026,"offset":176507,"length":182,"previous":"M16-GAP-01026","next":"M16-GAP-01028"},"M16-GAP-01028":{"line":1027,"offset":176689,"length":177,"previous":"M16-GAP-01027","next":"M16-GAP-01029"},"M16-GAP-01029":{"line":1028,"offset":176866,"length":175,"previous":"M16-GAP-01028","next":"M16-GAP-01030"},"M16-GAP-01030":{"line":1029,"offset":177041,"length":177,"previous":"M16-GAP-01029","next":"M16-GAP-01031"},"M16-GAP-01031":{"line":1030,"offset":177218,"length":164,"previous":"M16-GAP-01030","next":"M16-GAP-01032"},"M16-GAP-01032":{"line":1031,"offset":177382,"length":162,"previous":"M16-GAP-01031","next":"M16-GAP-01033"},"M16-GAP-01033":{"line":1032,"offset":177544,"length":171,"previous":"M16-GAP-01032","next":"M16-GAP-01034"},"M16-GAP-01034":{"line":1033,"offset":177715,"length":168,"previous":"M16-GAP-01033","next":"M16-GAP-01035"},"M16-GAP-01035":{"line":1034,"offset":177883,"length":175,"previous":"M16-GAP-01034","next":"M16-GAP-01036"},"M16-GAP-01036":{"line":1035,"offset":178058,"length":170,"previous":"M16-GAP-01035","next":"M16-GAP-01037"},"M16-GAP-01037":{"line":1036,"offset":178228,"length":170,"previous":"M16-GAP-01036","next":"M16-GAP-01038"},"M16-GAP-01038":{"line":1037,"offset":178398,"length":172,"previous":"M16-GAP-01037","next":"M16-GAP-01039"},"M16-GAP-01039":{"line":1038,"offset":178570,"length":169,"previous":"M16-GAP-01038","next":"M16-GAP-01040"},"M16-GAP-01040":{"line":1039,"offset":178739,"length":170,"previous":"M16-GAP-01039","next":"M16-GAP-01041"},"M16-GAP-01041":{"line":1040,"offset":178909,"length":176,"previous":"M16-GAP-01040","next":"M16-GAP-01042"},"M16-GAP-01042":{"line":1041,"offset":179085,"length":165,"previous":"M16-GAP-01041","next":"M16-GAP-01043"},"M16-GAP-01043":{"line":1042,"offset":179250,"length":170,"previous":"M16-GAP-01042","next":"M16-GAP-01044"},"M16-GAP-01044":{"line":1043,"offset":179420,"length":169,"previous":"M16-GAP-01043","next":"M16-GAP-01045"},"M16-GAP-01045":{"line":1044,"offset":179589,"length":169,"previous":"M16-GAP-01044","next":"M16-GAP-01046"},"M16-GAP-01046":{"line":1045,"offset":179758,"length":167,"previous":"M16-GAP-01045","next":"M16-GAP-01047"},"M16-GAP-01047":{"line":1046,"offset":179925,"length":166,"previous":"M16-GAP-01046","next":"M16-GAP-01048"},"M16-GAP-01048":{"line":1047,"offset":180091,"length":171,"previous":"M16-GAP-01047","next":"M16-GAP-01049"},"M16-GAP-01049":{"line":1048,"offset":180262,"length":174,"previous":"M16-GAP-01048","next":"M16-GAP-01050"},"M16-GAP-01050":{"line":1049,"offset":180436,"length":171,"previous":"M16-GAP-01049","next":"M16-GAP-01051"},"M16-GAP-01051":{"line":1050,"offset":180607,"length":176,"previous":"M16-GAP-01050","next":"M16-GAP-01052"},"M16-GAP-01052":{"line":1051,"offset":180783,"length":175,"previous":"M16-GAP-01051","next":"M16-GAP-01053"},"M16-GAP-01053":{"line":1052,"offset":180958,"length":174,"previous":"M16-GAP-01052","next":"M16-GAP-01054"},"M16-GAP-01054":{"line":1053,"offset":181132,"length":175,"previous":"M16-GAP-01053","next":"M16-GAP-01055"},"M16-GAP-01055":{"line":1054,"offset":181307,"length":174,"previous":"M16-GAP-01054","next":"M16-GAP-01056"},"M16-GAP-01056":{"line":1055,"offset":181481,"length":172,"previous":"M16-GAP-01055","next":"M16-GAP-01057"},"M16-GAP-01057":{"line":1056,"offset":181653,"length":170,"previous":"M16-GAP-01056","next":"M16-GAP-01058"},"M16-GAP-01058":{"line":1057,"offset":181823,"length":175,"previous":"M16-GAP-01057","next":"M16-GAP-01059"},"M16-GAP-01059":{"line":1058,"offset":181998,"length":184,"previous":"M16-GAP-01058","next":"M16-GAP-01060"},"M16-GAP-01060":{"line":1059,"offset":182182,"length":170,"previous":"M16-GAP-01059","next":"M16-GAP-01061"},"M16-GAP-01061":{"line":1060,"offset":182352,"length":177,"previous":"M16-GAP-01060","next":"M16-GAP-01062"},"M16-GAP-01062":{"line":1061,"offset":182529,"length":175,"previous":"M16-GAP-01061","next":"M16-GAP-01063"},"M16-GAP-01063":{"line":1062,"offset":182704,"length":172,"previous":"M16-GAP-01062","next":"M16-GAP-01064"},"M16-GAP-01064":{"line":1063,"offset":182876,"length":175,"previous":"M16-GAP-01063","next":"M16-GAP-01065"},"M16-GAP-01065":{"line":1064,"offset":183051,"length":180,"previous":"M16-GAP-01064","next":"M16-GAP-01066"},"M16-GAP-01066":{"line":1065,"offset":183231,"length":172,"previous":"M16-GAP-01065","next":"M16-GAP-01067"},"M16-GAP-01067":{"line":1066,"offset":183403,"length":174,"previous":"M16-GAP-01066","next":"M16-GAP-01068"},"M16-GAP-01068":{"line":1067,"offset":183577,"length":160,"previous":"M16-GAP-01067","next":"M16-GAP-01069"},"M16-GAP-01069":{"line":1068,"offset":183737,"length":165,"previous":"M16-GAP-01068","next":"M16-GAP-01070"},"M16-GAP-01070":{"line":1069,"offset":183902,"length":166,"previous":"M16-GAP-01069","next":"M16-GAP-01071"},"M16-GAP-01071":{"line":1070,"offset":184068,"length":163,"previous":"M16-GAP-01070","next":"M16-GAP-01072"},"M16-GAP-01072":{"line":1071,"offset":184231,"length":168,"previous":"M16-GAP-01071","next":"M16-GAP-01073"},"M16-GAP-01073":{"line":1072,"offset":184399,"length":178,"previous":"M16-GAP-01072","next":"M16-GAP-01074"},"M16-GAP-01074":{"line":1073,"offset":184577,"length":160,"previous":"M16-GAP-01073","next":"M16-GAP-01075"},"M16-GAP-01075":{"line":1074,"offset":184737,"length":161,"previous":"M16-GAP-01074","next":"M16-GAP-01076"},"M16-GAP-01076":{"line":1075,"offset":184898,"length":165,"previous":"M16-GAP-01075","next":"M16-GAP-01077"},"M16-GAP-01077":{"line":1076,"offset":185063,"length":173,"previous":"M16-GAP-01076","next":"M16-GAP-01078"},"M16-GAP-01078":{"line":1077,"offset":185236,"length":169,"previous":"M16-GAP-01077","next":"M16-GAP-01079"},"M16-GAP-01079":{"line":1078,"offset":185405,"length":166,"previous":"M16-GAP-01078","next":"M16-GAP-01080"},"M16-GAP-01080":{"line":1079,"offset":185571,"length":167,"previous":"M16-GAP-01079","next":"M16-GAP-01081"},"M16-GAP-01081":{"line":1080,"offset":185738,"length":170,"previous":"M16-GAP-01080","next":"M16-GAP-01082"},"M16-GAP-01082":{"line":1081,"offset":185908,"length":163,"previous":"M16-GAP-01081","next":"M16-GAP-01083"},"M16-GAP-01083":{"line":1082,"offset":186071,"length":169,"previous":"M16-GAP-01082","next":"M16-GAP-01084"},"M16-GAP-01084":{"line":1083,"offset":186240,"length":175,"previous":"M16-GAP-01083","next":"M16-GAP-01085"},"M16-GAP-01085":{"line":1084,"offset":186415,"length":175,"previous":"M16-GAP-01084","next":"M16-GAP-01086"},"M16-GAP-01086":{"line":1085,"offset":186590,"length":165,"previous":"M16-GAP-01085","next":"M16-GAP-01087"},"M16-GAP-01087":{"line":1086,"offset":186755,"length":166,"previous":"M16-GAP-01086","next":"M16-GAP-01088"},"M16-GAP-01088":{"line":1087,"offset":186921,"length":161,"previous":"M16-GAP-01087","next":"M16-GAP-01089"},"M16-GAP-01089":{"line":1088,"offset":187082,"length":169,"previous":"M16-GAP-01088","next":"M16-GAP-01090"},"M16-GAP-01090":{"line":1089,"offset":187251,"length":177,"previous":"M16-GAP-01089","next":"M16-GAP-01091"},"M16-GAP-01091":{"line":1090,"offset":187428,"length":179,"previous":"M16-GAP-01090","next":"M16-GAP-01092"},"M16-GAP-01092":{"line":1091,"offset":187607,"length":169,"previous":"M16-GAP-01091","next":"M16-GAP-01093"},"M16-GAP-01093":{"line":1092,"offset":187776,"length":173,"previous":"M16-GAP-01092","next":"M16-GAP-01094"},"M16-GAP-01094":{"line":1093,"offset":187949,"length":179,"previous":"M16-GAP-01093","next":"M16-GAP-01095"},"M16-GAP-01095":{"line":1094,"offset":188128,"length":169,"previous":"M16-GAP-01094","next":"M16-GAP-01096"},"M16-GAP-01096":{"line":1095,"offset":188297,"length":160,"previous":"M16-GAP-01095","next":"M16-GAP-01097"},"M16-GAP-01097":{"line":1096,"offset":188457,"length":182,"previous":"M16-GAP-01096","next":"M16-GAP-01098"},"M16-GAP-01098":{"line":1097,"offset":188639,"length":184,"previous":"M16-GAP-01097","next":"M16-GAP-01099"},"M16-GAP-01099":{"line":1098,"offset":188823,"length":188,"previous":"M16-GAP-01098","next":"M16-GAP-01100"},"M16-GAP-01100":{"line":1099,"offset":189011,"length":180,"previous":"M16-GAP-01099","next":"M16-GAP-01101"},"M16-GAP-01101":{"line":1100,"offset":189191,"length":185,"previous":"M16-GAP-01100","next":"M16-GAP-01102"},"M16-GAP-01102":{"line":1101,"offset":189376,"length":181,"previous":"M16-GAP-01101","next":"M16-GAP-01103"},"M16-GAP-01103":{"line":1102,"offset":189557,"length":186,"previous":"M16-GAP-01102","next":"M16-GAP-01104"},"M16-GAP-01104":{"line":1103,"offset":189743,"length":185,"previous":"M16-GAP-01103","next":"M16-GAP-01105"},"M16-GAP-01105":{"line":1104,"offset":189928,"length":190,"previous":"M16-GAP-01104","next":"M16-GAP-01106"},"M16-GAP-01106":{"line":1105,"offset":190118,"length":176,"previous":"M16-GAP-01105","next":"M16-GAP-01107"},"M16-GAP-01107":{"line":1106,"offset":190294,"length":174,"previous":"M16-GAP-01106","next":"M16-GAP-01108"},"M16-GAP-01108":{"line":1107,"offset":190468,"length":174,"previous":"M16-GAP-01107","next":"M16-GAP-01109"},"M16-GAP-01109":{"line":1108,"offset":190642,"length":180,"previous":"M16-GAP-01108","next":"M16-GAP-01110"},"M16-GAP-01110":{"line":1109,"offset":190822,"length":178,"previous":"M16-GAP-01109","next":"M16-GAP-01111"},"M16-GAP-01111":{"line":1110,"offset":191000,"length":174,"previous":"M16-GAP-01110","next":"M16-GAP-01112"},"M16-GAP-01112":{"line":1111,"offset":191174,"length":180,"previous":"M16-GAP-01111","next":"M16-GAP-01113"},"M16-GAP-01113":{"line":1112,"offset":191354,"length":176,"previous":"M16-GAP-01112","next":"M16-GAP-01114"},"M16-GAP-01114":{"line":1113,"offset":191530,"length":175,"previous":"M16-GAP-01113","next":"M16-GAP-01115"},"M16-GAP-01115":{"line":1114,"offset":191705,"length":175,"previous":"M16-GAP-01114","next":"M16-GAP-01116"},"M16-GAP-01116":{"line":1115,"offset":191880,"length":179,"previous":"M16-GAP-01115","next":"M16-GAP-01117"},"M16-GAP-01117":{"line":1116,"offset":192059,"length":177,"previous":"M16-GAP-01116","next":"M16-GAP-01118"},"M16-GAP-01118":{"line":1117,"offset":192236,"length":170,"previous":"M16-GAP-01117","next":"M16-GAP-01119"},"M16-GAP-01119":{"line":1118,"offset":192406,"length":170,"previous":"M16-GAP-01118","next":"M16-GAP-01120"},"M16-GAP-01120":{"line":1119,"offset":192576,"length":180,"previous":"M16-GAP-01119","next":"M16-GAP-01121"},"M16-GAP-01121":{"line":1120,"offset":192756,"length":162,"previous":"M16-GAP-01120","next":"M16-GAP-01122"},"M16-GAP-01122":{"line":1121,"offset":192918,"length":159,"previous":"M16-GAP-01121","next":"M16-GAP-01123"},"M16-GAP-01123":{"line":1122,"offset":193077,"length":164,"previous":"M16-GAP-01122","next":"M16-GAP-01124"},"M16-GAP-01124":{"line":1123,"offset":193241,"length":169,"previous":"M16-GAP-01123","next":"M16-GAP-01125"},"M16-GAP-01125":{"line":1124,"offset":193410,"length":164,"previous":"M16-GAP-01124","next":"M16-GAP-01126"},"M16-GAP-01126":{"line":1125,"offset":193574,"length":161,"previous":"M16-GAP-01125","next":"M16-GAP-01127"},"M16-GAP-01127":{"line":1126,"offset":193735,"length":166,"previous":"M16-GAP-01126","next":"M16-GAP-01128"},"M16-GAP-01128":{"line":1127,"offset":193901,"length":167,"previous":"M16-GAP-01127","next":"M16-GAP-01129"},"M16-GAP-01129":{"line":1128,"offset":194068,"length":182,"previous":"M16-GAP-01128","next":"M16-GAP-01130"},"M16-GAP-01130":{"line":1129,"offset":194250,"length":175,"previous":"M16-GAP-01129","next":"M16-GAP-01131"},"M16-GAP-01131":{"line":1130,"offset":194425,"length":176,"previous":"M16-GAP-01130","next":"M16-GAP-01132"},"M16-GAP-01132":{"line":1131,"offset":194601,"length":178,"previous":"M16-GAP-01131","next":"M16-GAP-01133"},"M16-GAP-01133":{"line":1132,"offset":194779,"length":178,"previous":"M16-GAP-01132","next":"M16-GAP-01134"},"M16-GAP-01134":{"line":1133,"offset":194957,"length":176,"previous":"M16-GAP-01133","next":"M16-GAP-01135"},"M16-GAP-01135":{"line":1134,"offset":195133,"length":177,"previous":"M16-GAP-01134","next":"M16-GAP-01136"},"M16-GAP-01136":{"line":1135,"offset":195310,"length":167,"previous":"M16-GAP-01135","next":"M16-GAP-01137"},"M16-GAP-01137":{"line":1136,"offset":195477,"length":169,"previous":"M16-GAP-01136","next":"M16-GAP-01138"},"M16-GAP-01138":{"line":1137,"offset":195646,"length":174,"previous":"M16-GAP-01137","next":"M16-GAP-01139"},"M16-GAP-01139":{"line":1138,"offset":195820,"length":168,"previous":"M16-GAP-01138","next":"M16-GAP-01140"},"M16-GAP-01140":{"line":1139,"offset":195988,"length":169,"previous":"M16-GAP-01139","next":"M16-GAP-01141"},"M16-GAP-01141":{"line":1140,"offset":196157,"length":167,"previous":"M16-GAP-01140","next":"M16-GAP-01142"},"M16-GAP-01142":{"line":1141,"offset":196324,"length":167,"previous":"M16-GAP-01141","next":"M16-GAP-01143"},"M16-GAP-01143":{"line":1142,"offset":196491,"length":172,"previous":"M16-GAP-01142","next":"M16-GAP-01144"},"M16-GAP-01144":{"line":1143,"offset":196663,"length":175,"previous":"M16-GAP-01143","next":"M16-GAP-01145"},"M16-GAP-01145":{"line":1144,"offset":196838,"length":166,"previous":"M16-GAP-01144","next":"M16-GAP-01146"},"M16-GAP-01146":{"line":1145,"offset":197004,"length":172,"previous":"M16-GAP-01145","next":"M16-GAP-01147"},"M16-GAP-01147":{"line":1146,"offset":197176,"length":169,"previous":"M16-GAP-01146","next":"M16-GAP-01148"},"M16-GAP-01148":{"line":1147,"offset":197345,"length":170,"previous":"M16-GAP-01147","next":"M16-GAP-01149"},"M16-GAP-01149":{"line":1148,"offset":197515,"length":177,"previous":"M16-GAP-01148","next":"M16-GAP-01150"},"M16-GAP-01150":{"line":1149,"offset":197692,"length":172,"previous":"M16-GAP-01149","next":"M16-GAP-01151"},"M16-GAP-01151":{"line":1150,"offset":197864,"length":164,"previous":"M16-GAP-01150","next":"M16-GAP-01152"},"M16-GAP-01152":{"line":1151,"offset":198028,"length":178,"previous":"M16-GAP-01151","next":"M16-GAP-01153"},"M16-GAP-01153":{"line":1152,"offset":198206,"length":178,"previous":"M16-GAP-01152","next":"M16-GAP-01154"},"M16-GAP-01154":{"line":1153,"offset":198384,"length":178,"previous":"M16-GAP-01153","next":"M16-GAP-01155"},"M16-GAP-01155":{"line":1154,"offset":198562,"length":174,"previous":"M16-GAP-01154","next":"M16-GAP-01156"},"M16-GAP-01156":{"line":1155,"offset":198736,"length":176,"previous":"M16-GAP-01155","next":"M16-GAP-01157"},"M16-GAP-01157":{"line":1156,"offset":198912,"length":170,"previous":"M16-GAP-01156","next":"M16-GAP-01158"},"M16-GAP-01158":{"line":1157,"offset":199082,"length":164,"previous":"M16-GAP-01157","next":"M16-GAP-01159"},"M16-GAP-01159":{"line":1158,"offset":199246,"length":169,"previous":"M16-GAP-01158","next":"M16-GAP-01160"},"M16-GAP-01160":{"line":1159,"offset":199415,"length":179,"previous":"M16-GAP-01159","next":"M16-GAP-01161"},"M16-GAP-01161":{"line":1160,"offset":199594,"length":160,"previous":"M16-GAP-01160","next":"M16-GAP-01162"},"M16-GAP-01162":{"line":1161,"offset":199754,"length":161,"previous":"M16-GAP-01161","next":"M16-GAP-01163"},"M16-GAP-01163":{"line":1162,"offset":199915,"length":169,"previous":"M16-GAP-01162","next":"M16-GAP-01164"},"M16-GAP-01164":{"line":1163,"offset":200084,"length":165,"previous":"M16-GAP-01163","next":"M16-GAP-01165"},"M16-GAP-01165":{"line":1164,"offset":200249,"length":174,"previous":"M16-GAP-01164","next":"M16-GAP-01166"},"M16-GAP-01166":{"line":1165,"offset":200423,"length":166,"previous":"M16-GAP-01165","next":"M16-GAP-01167"},"M16-GAP-01167":{"line":1166,"offset":200589,"length":169,"previous":"M16-GAP-01166","next":"M16-GAP-01168"},"M16-GAP-01168":{"line":1167,"offset":200758,"length":177,"previous":"M16-GAP-01167","next":"M16-GAP-01169"},"M16-GAP-01169":{"line":1168,"offset":200935,"length":167,"previous":"M16-GAP-01168","next":"M16-GAP-01170"},"M16-GAP-01170":{"line":1169,"offset":201102,"length":170,"previous":"M16-GAP-01169","next":"M16-GAP-01171"},"M16-GAP-01171":{"line":1170,"offset":201272,"length":173,"previous":"M16-GAP-01170","next":"M16-GAP-01172"},"M16-GAP-01172":{"line":1171,"offset":201445,"length":167,"previous":"M16-GAP-01171","next":"M16-GAP-01173"},"M16-GAP-01173":{"line":1172,"offset":201612,"length":166,"previous":"M16-GAP-01172","next":"M16-GAP-01174"},"M16-GAP-01174":{"line":1173,"offset":201778,"length":168,"previous":"M16-GAP-01173","next":"M16-GAP-01175"},"M16-GAP-01175":{"line":1174,"offset":201946,"length":176,"previous":"M16-GAP-01174","next":"M16-GAP-01176"},"M16-GAP-01176":{"line":1175,"offset":202122,"length":178,"previous":"M16-GAP-01175","next":"M16-GAP-01177"},"M16-GAP-01177":{"line":1176,"offset":202300,"length":173,"previous":"M16-GAP-01176","next":"M16-GAP-01178"},"M16-GAP-01178":{"line":1177,"offset":202473,"length":171,"previous":"M16-GAP-01177","next":"M16-GAP-01179"},"M16-GAP-01179":{"line":1178,"offset":202644,"length":181,"previous":"M16-GAP-01178","next":"M16-GAP-01180"},"M16-GAP-01180":{"line":1179,"offset":202825,"length":165,"previous":"M16-GAP-01179","next":"M16-GAP-01181"},"M16-GAP-01181":{"line":1180,"offset":202990,"length":170,"previous":"M16-GAP-01180","next":"M16-GAP-01182"},"M16-GAP-01182":{"line":1181,"offset":203160,"length":173,"previous":"M16-GAP-01181","next":"M16-GAP-01183"},"M16-GAP-01183":{"line":1182,"offset":203333,"length":168,"previous":"M16-GAP-01182","next":"M16-GAP-01184"},"M16-GAP-01184":{"line":1183,"offset":203501,"length":169,"previous":"M16-GAP-01183","next":"M16-GAP-01185"},"M16-GAP-01185":{"line":1184,"offset":203670,"length":166,"previous":"M16-GAP-01184","next":"M16-GAP-01186"},"M16-GAP-01186":{"line":1185,"offset":203836,"length":159,"previous":"M16-GAP-01185","next":"M16-GAP-01187"},"M16-GAP-01187":{"line":1186,"offset":203995,"length":169,"previous":"M16-GAP-01186","next":"M16-GAP-01188"},"M16-GAP-01188":{"line":1187,"offset":204164,"length":166,"previous":"M16-GAP-01187","next":"M16-GAP-01189"},"M16-GAP-01189":{"line":1188,"offset":204330,"length":167,"previous":"M16-GAP-01188","next":"M16-GAP-01190"},"M16-GAP-01190":{"line":1189,"offset":204497,"length":161,"previous":"M16-GAP-01189","next":"M16-GAP-01191"},"M16-GAP-01191":{"line":1190,"offset":204658,"length":164,"previous":"M16-GAP-01190","next":"M16-GAP-01192"},"M16-GAP-01192":{"line":1191,"offset":204822,"length":176,"previous":"M16-GAP-01191","next":"M16-GAP-01193"},"M16-GAP-01193":{"line":1192,"offset":204998,"length":169,"previous":"M16-GAP-01192","next":"M16-GAP-01194"},"M16-GAP-01194":{"line":1193,"offset":205167,"length":168,"previous":"M16-GAP-01193","next":"M16-GAP-01195"},"M16-GAP-01195":{"line":1194,"offset":205335,"length":169,"previous":"M16-GAP-01194","next":"M16-GAP-01196"},"M16-GAP-01196":{"line":1195,"offset":205504,"length":170,"previous":"M16-GAP-01195","next":"M16-GAP-01197"},"M16-GAP-01197":{"line":1196,"offset":205674,"length":171,"previous":"M16-GAP-01196","next":"M16-GAP-01198"},"M16-GAP-01198":{"line":1197,"offset":205845,"length":163,"previous":"M16-GAP-01197","next":"M16-GAP-01199"},"M16-GAP-01199":{"line":1198,"offset":206008,"length":166,"previous":"M16-GAP-01198","next":"M16-GAP-01200"},"M16-GAP-01200":{"line":1199,"offset":206174,"length":164,"previous":"M16-GAP-01199","next":"M16-GAP-01201"},"M16-GAP-01201":{"line":1200,"offset":206338,"length":162,"previous":"M16-GAP-01200","next":"M16-GAP-01202"},"M16-GAP-01202":{"line":1201,"offset":206500,"length":166,"previous":"M16-GAP-01201","next":"M16-GAP-01203"},"M16-GAP-01203":{"line":1202,"offset":206666,"length":171,"previous":"M16-GAP-01202","next":"M16-GAP-01204"},"M16-GAP-01204":{"line":1203,"offset":206837,"length":165,"previous":"M16-GAP-01203","next":"M16-GAP-01205"},"M16-GAP-01205":{"line":1204,"offset":207002,"length":165,"previous":"M16-GAP-01204","next":"M16-GAP-01206"},"M16-GAP-01206":{"line":1205,"offset":207167,"length":171,"previous":"M16-GAP-01205","next":"M16-GAP-01207"},"M16-GAP-01207":{"line":1206,"offset":207338,"length":175,"previous":"M16-GAP-01206","next":"M16-GAP-01208"},"M16-GAP-01208":{"line":1207,"offset":207513,"length":159,"previous":"M16-GAP-01207","next":"M16-GAP-01209"},"M16-GAP-01209":{"line":1208,"offset":207672,"length":168,"previous":"M16-GAP-01208","next":"M16-GAP-01210"},"M16-GAP-01210":{"line":1209,"offset":207840,"length":160,"previous":"M16-GAP-01209","next":"M16-GAP-01211"},"M16-GAP-01211":{"line":1210,"offset":208000,"length":159,"previous":"M16-GAP-01210","next":"M16-GAP-01212"},"M16-GAP-01212":{"line":1211,"offset":208159,"length":165,"previous":"M16-GAP-01211","next":"M16-GAP-01213"},"M16-GAP-01213":{"line":1212,"offset":208324,"length":168,"previous":"M16-GAP-01212","next":"M16-GAP-01214"},"M16-GAP-01214":{"line":1213,"offset":208492,"length":169,"previous":"M16-GAP-01213","next":"M16-GAP-01215"},"M16-GAP-01215":{"line":1214,"offset":208661,"length":170,"previous":"M16-GAP-01214","next":"M16-GAP-01216"},"M16-GAP-01216":{"line":1215,"offset":208831,"length":169,"previous":"M16-GAP-01215","next":"M16-GAP-01217"},"M16-GAP-01217":{"line":1216,"offset":209000,"length":163,"previous":"M16-GAP-01216","next":"M16-GAP-01218"},"M16-GAP-01218":{"line":1217,"offset":209163,"length":165,"previous":"M16-GAP-01217","next":"M16-GAP-01219"},"M16-GAP-01219":{"line":1218,"offset":209328,"length":168,"previous":"M16-GAP-01218","next":"M16-GAP-01220"},"M16-GAP-01220":{"line":1219,"offset":209496,"length":171,"previous":"M16-GAP-01219","next":"M16-GAP-01221"},"M16-GAP-01221":{"line":1220,"offset":209667,"length":172,"previous":"M16-GAP-01220","next":"M16-GAP-01222"},"M16-GAP-01222":{"line":1221,"offset":209839,"length":170,"previous":"M16-GAP-01221","next":"M16-GAP-01223"},"M16-GAP-01223":{"line":1222,"offset":210009,"length":165,"previous":"M16-GAP-01222","next":"M16-GAP-01224"},"M16-GAP-01224":{"line":1223,"offset":210174,"length":171,"previous":"M16-GAP-01223","next":"M16-GAP-01225"},"M16-GAP-01225":{"line":1224,"offset":210345,"length":189,"previous":"M16-GAP-01224","next":"M16-GAP-01226"},"M16-GAP-01226":{"line":1225,"offset":210534,"length":165,"previous":"M16-GAP-01225","next":"M16-GAP-01227"},"M16-GAP-01227":{"line":1226,"offset":210699,"length":171,"previous":"M16-GAP-01226","next":"M16-GAP-01228"},"M16-GAP-01228":{"line":1227,"offset":210870,"length":176,"previous":"M16-GAP-01227","next":"M16-GAP-01229"},"M16-GAP-01229":{"line":1228,"offset":211046,"length":165,"previous":"M16-GAP-01228","next":"M16-GAP-01230"},"M16-GAP-01230":{"line":1229,"offset":211211,"length":171,"previous":"M16-GAP-01229","next":"M16-GAP-01231"},"M16-GAP-01231":{"line":1230,"offset":211382,"length":164,"previous":"M16-GAP-01230","next":"M16-GAP-01232"},"M16-GAP-01232":{"line":1231,"offset":211546,"length":168,"previous":"M16-GAP-01231","next":"M16-GAP-01233"},"M16-GAP-01233":{"line":1232,"offset":211714,"length":164,"previous":"M16-GAP-01232","next":"M16-GAP-01234"},"M16-GAP-01234":{"line":1233,"offset":211878,"length":166,"previous":"M16-GAP-01233","next":"M16-GAP-01235"},"M16-GAP-01235":{"line":1234,"offset":212044,"length":171,"previous":"M16-GAP-01234","next":"M16-GAP-01236"},"M16-GAP-01236":{"line":1235,"offset":212215,"length":167,"previous":"M16-GAP-01235","next":"M16-GAP-01237"},"M16-GAP-01237":{"line":1236,"offset":212382,"length":175,"previous":"M16-GAP-01236","next":"M16-GAP-01238"},"M16-GAP-01238":{"line":1237,"offset":212557,"length":172,"previous":"M16-GAP-01237","next":"M16-GAP-01239"},"M16-GAP-01239":{"line":1238,"offset":212729,"length":164,"previous":"M16-GAP-01238","next":"M16-GAP-01240"},"M16-GAP-01240":{"line":1239,"offset":212893,"length":162,"previous":"M16-GAP-01239","next":"M16-GAP-01241"},"M16-GAP-01241":{"line":1240,"offset":213055,"length":169,"previous":"M16-GAP-01240","next":"M16-GAP-01242"},"M16-GAP-01242":{"line":1241,"offset":213224,"length":170,"previous":"M16-GAP-01241","next":"M16-GAP-01243"},"M16-GAP-01243":{"line":1242,"offset":213394,"length":172,"previous":"M16-GAP-01242","next":"M16-GAP-01244"},"M16-GAP-01244":{"line":1243,"offset":213566,"length":170,"previous":"M16-GAP-01243","next":"M16-GAP-01245"},"M16-GAP-01245":{"line":1244,"offset":213736,"length":174,"previous":"M16-GAP-01244","next":"M16-GAP-01246"},"M16-GAP-01246":{"line":1245,"offset":213910,"length":175,"previous":"M16-GAP-01245","next":"M16-GAP-01247"},"M16-GAP-01247":{"line":1246,"offset":214085,"length":177,"previous":"M16-GAP-01246","next":"M16-GAP-01248"},"M16-GAP-01248":{"line":1247,"offset":214262,"length":182,"previous":"M16-GAP-01247","next":"M16-GAP-01249"},"M16-GAP-01249":{"line":1248,"offset":214444,"length":183,"previous":"M16-GAP-01248","next":"M16-GAP-01250"},"M16-GAP-01250":{"line":1249,"offset":214627,"length":185,"previous":"M16-GAP-01249","next":"M16-GAP-01251"},"M16-GAP-01251":{"line":1250,"offset":214812,"length":175,"previous":"M16-GAP-01250","next":"M16-GAP-01252"},"M16-GAP-01252":{"line":1251,"offset":214987,"length":170,"previous":"M16-GAP-01251","next":"M16-GAP-01253"},"M16-GAP-01253":{"line":1252,"offset":215157,"length":171,"previous":"M16-GAP-01252","next":"M16-GAP-01254"},"M16-GAP-01254":{"line":1253,"offset":215328,"length":178,"previous":"M16-GAP-01253","next":"M16-GAP-01255"},"M16-GAP-01255":{"line":1254,"offset":215506,"length":179,"previous":"M16-GAP-01254","next":"M16-GAP-01256"},"M16-GAP-01256":{"line":1255,"offset":215685,"length":181,"previous":"M16-GAP-01255","next":"M16-GAP-01257"},"M16-GAP-01257":{"line":1256,"offset":215866,"length":179,"previous":"M16-GAP-01256","next":"M16-GAP-01258"},"M16-GAP-01258":{"line":1257,"offset":216045,"length":180,"previous":"M16-GAP-01257","next":"M16-GAP-01259"},"M16-GAP-01259":{"line":1258,"offset":216225,"length":182,"previous":"M16-GAP-01258","next":"M16-GAP-01260"},"M16-GAP-01260":{"line":1259,"offset":216407,"length":180,"previous":"M16-GAP-01259","next":"M16-GAP-01261"},"M16-GAP-01261":{"line":1260,"offset":216587,"length":181,"previous":"M16-GAP-01260","next":"M16-GAP-01262"},"M16-GAP-01262":{"line":1261,"offset":216768,"length":183,"previous":"M16-GAP-01261","next":"M16-GAP-01263"},"M16-GAP-01263":{"line":1262,"offset":216951,"length":183,"previous":"M16-GAP-01262","next":"M16-GAP-01264"},"M16-GAP-01264":{"line":1263,"offset":217134,"length":179,"previous":"M16-GAP-01263","next":"M16-GAP-01265"},"M16-GAP-01265":{"line":1264,"offset":217313,"length":180,"previous":"M16-GAP-01264","next":"M16-GAP-01266"},"M16-GAP-01266":{"line":1265,"offset":217493,"length":182,"previous":"M16-GAP-01265","next":"M16-GAP-01267"},"M16-GAP-01267":{"line":1266,"offset":217675,"length":173,"previous":"M16-GAP-01266","next":"M16-GAP-01268"},"M16-GAP-01268":{"line":1267,"offset":217848,"length":177,"previous":"M16-GAP-01267","next":"M16-GAP-01269"},"M16-GAP-01269":{"line":1268,"offset":218025,"length":180,"previous":"M16-GAP-01268","next":"M16-GAP-01270"},"M16-GAP-01270":{"line":1269,"offset":218205,"length":173,"previous":"M16-GAP-01269","next":"M16-GAP-01271"},"M16-GAP-01271":{"line":1270,"offset":218378,"length":179,"previous":"M16-GAP-01270","next":"M16-GAP-01272"},"M16-GAP-01272":{"line":1271,"offset":218557,"length":162,"previous":"M16-GAP-01271","next":"M16-GAP-01273"},"M16-GAP-01273":{"line":1272,"offset":218719,"length":177,"previous":"M16-GAP-01272","next":"M16-GAP-01274"},"M16-GAP-01274":{"line":1273,"offset":218896,"length":172,"previous":"M16-GAP-01273","next":"M16-GAP-01275"},"M16-GAP-01275":{"line":1274,"offset":219068,"length":162,"previous":"M16-GAP-01274","next":"M16-GAP-01276"},"M16-GAP-01276":{"line":1275,"offset":219230,"length":179,"previous":"M16-GAP-01275","next":"M16-GAP-01277"},"M16-GAP-01277":{"line":1276,"offset":219409,"length":165,"previous":"M16-GAP-01276","next":"M16-GAP-01278"},"M16-GAP-01278":{"line":1277,"offset":219574,"length":197,"previous":"M16-GAP-01277","next":"M16-GAP-01279"},"M16-GAP-01279":{"line":1278,"offset":219771,"length":188,"previous":"M16-GAP-01278","next":"M16-GAP-01280"},"M16-GAP-01280":{"line":1279,"offset":219959,"length":170,"previous":"M16-GAP-01279","next":"M16-GAP-01281"},"M16-GAP-01281":{"line":1280,"offset":220129,"length":182,"previous":"M16-GAP-01280","next":"M16-GAP-01282"},"M16-GAP-01282":{"line":1281,"offset":220311,"length":177,"previous":"M16-GAP-01281","next":"M16-GAP-01283"},"M16-GAP-01283":{"line":1282,"offset":220488,"length":180,"previous":"M16-GAP-01282","next":"M16-GAP-01284"},"M16-GAP-01284":{"line":1283,"offset":220668,"length":181,"previous":"M16-GAP-01283","next":"M16-GAP-01285"},"M16-GAP-01285":{"line":1284,"offset":220849,"length":183,"previous":"M16-GAP-01284","next":"M16-GAP-01286"},"M16-GAP-01286":{"line":1285,"offset":221032,"length":187,"previous":"M16-GAP-01285","next":"M16-GAP-01287"},"M16-GAP-01287":{"line":1286,"offset":221219,"length":188,"previous":"M16-GAP-01286","next":"M16-GAP-01288"},"M16-GAP-01288":{"line":1287,"offset":221407,"length":190,"previous":"M16-GAP-01287","next":"M16-GAP-01289"},"M16-GAP-01289":{"line":1288,"offset":221597,"length":188,"previous":"M16-GAP-01288","next":"M16-GAP-01290"},"M16-GAP-01290":{"line":1289,"offset":221785,"length":189,"previous":"M16-GAP-01289","next":"M16-GAP-01291"},"M16-GAP-01291":{"line":1290,"offset":221974,"length":191,"previous":"M16-GAP-01290","next":"M16-GAP-01292"},"M16-GAP-01292":{"line":1291,"offset":222165,"length":178,"previous":"M16-GAP-01291","next":"M16-GAP-01293"},"M16-GAP-01293":{"line":1292,"offset":222343,"length":179,"previous":"M16-GAP-01292","next":"M16-GAP-01294"},"M16-GAP-01294":{"line":1293,"offset":222522,"length":181,"previous":"M16-GAP-01293","next":"M16-GAP-01295"},"M16-GAP-01295":{"line":1294,"offset":222703,"length":178,"previous":"M16-GAP-01294","next":"M16-GAP-01296"},"M16-GAP-01296":{"line":1295,"offset":222881,"length":179,"previous":"M16-GAP-01295","next":"M16-GAP-01297"},"M16-GAP-01297":{"line":1296,"offset":223060,"length":181,"previous":"M16-GAP-01296","next":"M16-GAP-01298"},"M16-GAP-01298":{"line":1297,"offset":223241,"length":176,"previous":"M16-GAP-01297","next":"M16-GAP-01299"},"M16-GAP-01299":{"line":1298,"offset":223417,"length":177,"previous":"M16-GAP-01298","next":"M16-GAP-01300"},"M16-GAP-01300":{"line":1299,"offset":223594,"length":179,"previous":"M16-GAP-01299","next":"M16-GAP-01301"},"M16-GAP-01301":{"line":1300,"offset":223773,"length":165,"previous":"M16-GAP-01300","next":"M16-GAP-01302"},"M16-GAP-01302":{"line":1301,"offset":223938,"length":205,"previous":"M16-GAP-01301","next":"M16-GAP-01303"},"M16-GAP-01303":{"line":1302,"offset":224143,"length":206,"previous":"M16-GAP-01302","next":"M16-GAP-01304"},"M16-GAP-01304":{"line":1303,"offset":224349,"length":208,"previous":"M16-GAP-01303","next":"M16-GAP-01305"},"M16-GAP-01305":{"line":1304,"offset":224557,"length":200,"previous":"M16-GAP-01304","next":"M16-GAP-01306"},"M16-GAP-01306":{"line":1305,"offset":224757,"length":201,"previous":"M16-GAP-01305","next":"M16-GAP-01307"},"M16-GAP-01307":{"line":1306,"offset":224958,"length":203,"previous":"M16-GAP-01306","next":"M16-GAP-01308"},"M16-GAP-01308":{"line":1307,"offset":225161,"length":199,"previous":"M16-GAP-01307","next":"M16-GAP-01309"},"M16-GAP-01309":{"line":1308,"offset":225360,"length":200,"previous":"M16-GAP-01308","next":"M16-GAP-01310"},"M16-GAP-01310":{"line":1309,"offset":225560,"length":202,"previous":"M16-GAP-01309","next":"M16-GAP-01311"},"M16-GAP-01311":{"line":1310,"offset":225762,"length":178,"previous":"M16-GAP-01310","next":"M16-GAP-01312"},"M16-GAP-01312":{"line":1311,"offset":225940,"length":179,"previous":"M16-GAP-01311","next":"M16-GAP-01313"},"M16-GAP-01313":{"line":1312,"offset":226119,"length":181,"previous":"M16-GAP-01312","next":"M16-GAP-01314"},"M16-GAP-01314":{"line":1313,"offset":226300,"length":186,"previous":"M16-GAP-01313","next":"M16-GAP-01315"},"M16-GAP-01315":{"line":1314,"offset":226486,"length":187,"previous":"M16-GAP-01314","next":"M16-GAP-01316"},"M16-GAP-01316":{"line":1315,"offset":226673,"length":189,"previous":"M16-GAP-01315","next":"M16-GAP-01317"},"M16-GAP-01317":{"line":1316,"offset":226862,"length":183,"previous":"M16-GAP-01316","next":"M16-GAP-01318"},"M16-GAP-01318":{"line":1317,"offset":227045,"length":166,"previous":"M16-GAP-01317","next":"M16-GAP-01319"},"M16-GAP-01319":{"line":1318,"offset":227211,"length":172,"previous":"M16-GAP-01318","next":"M16-GAP-01320"},"M16-GAP-01320":{"line":1319,"offset":227383,"length":168,"previous":"M16-GAP-01319","next":"M16-GAP-01321"},"M16-GAP-01321":{"line":1320,"offset":227551,"length":166,"previous":"M16-GAP-01320","next":"M16-GAP-01322"},"M16-GAP-01322":{"line":1321,"offset":227717,"length":170,"previous":"M16-GAP-01321","next":"M16-GAP-01323"},"M16-GAP-01323":{"line":1322,"offset":227887,"length":169,"previous":"M16-GAP-01322","next":"M16-GAP-01324"},"M16-GAP-01324":{"line":1323,"offset":228056,"length":174,"previous":"M16-GAP-01323","next":"M16-GAP-01325"},"M16-GAP-01325":{"line":1324,"offset":228230,"length":167,"previous":"M16-GAP-01324","next":"M16-GAP-01326"},"M16-GAP-01326":{"line":1325,"offset":228397,"length":177,"previous":"M16-GAP-01325","next":"M16-GAP-01327"},"M16-GAP-01327":{"line":1326,"offset":228574,"length":178,"previous":"M16-GAP-01326","next":"M16-GAP-01328"},"M16-GAP-01328":{"line":1327,"offset":228752,"length":180,"previous":"M16-GAP-01327","next":"M16-GAP-01329"},"M16-GAP-01329":{"line":1328,"offset":228932,"length":169,"previous":"M16-GAP-01328","next":"M16-GAP-01330"},"M16-GAP-01330":{"line":1329,"offset":229101,"length":180,"previous":"M16-GAP-01329","next":"M16-GAP-01331"},"M16-GAP-01331":{"line":1330,"offset":229281,"length":188,"previous":"M16-GAP-01330","next":"M16-GAP-01332"},"M16-GAP-01332":{"line":1331,"offset":229469,"length":174,"previous":"M16-GAP-01331","next":"M16-GAP-01333"},"M16-GAP-01333":{"line":1332,"offset":229643,"length":187,"previous":"M16-GAP-01332","next":"M16-GAP-01334"},"M16-GAP-01334":{"line":1333,"offset":229830,"length":177,"previous":"M16-GAP-01333","next":"M16-GAP-01335"},"M16-GAP-01335":{"line":1334,"offset":230007,"length":190,"previous":"M16-GAP-01334","next":"M16-GAP-01336"},"M16-GAP-01336":{"line":1335,"offset":230197,"length":160,"previous":"M16-GAP-01335","next":"M16-GAP-01337"},"M16-GAP-01337":{"line":1336,"offset":230357,"length":166,"previous":"M16-GAP-01336","next":"M16-GAP-01338"},"M16-GAP-01338":{"line":1337,"offset":230523,"length":166,"previous":"M16-GAP-01337","next":"M16-GAP-01339"},"M16-GAP-01339":{"line":1338,"offset":230689,"length":160,"previous":"M16-GAP-01338","next":"M16-GAP-01340"},"M16-GAP-01340":{"line":1339,"offset":230849,"length":180,"previous":"M16-GAP-01339","next":"M16-GAP-01341"},"M16-GAP-01341":{"line":1340,"offset":231029,"length":165,"previous":"M16-GAP-01340","next":"M16-GAP-01342"},"M16-GAP-01342":{"line":1341,"offset":231194,"length":167,"previous":"M16-GAP-01341","next":"M16-GAP-01343"},"M16-GAP-01343":{"line":1342,"offset":231361,"length":165,"previous":"M16-GAP-01342","next":"M16-GAP-01344"},"M16-GAP-01344":{"line":1343,"offset":231526,"length":168,"previous":"M16-GAP-01343","next":"M16-GAP-01345"},"M16-GAP-01345":{"line":1344,"offset":231694,"length":166,"previous":"M16-GAP-01344","next":"M16-GAP-01346"},"M16-GAP-01346":{"line":1345,"offset":231860,"length":173,"previous":"M16-GAP-01345","next":"M16-GAP-01347"},"M16-GAP-01347":{"line":1346,"offset":232033,"length":181,"previous":"M16-GAP-01346","next":"M16-GAP-01348"},"M16-GAP-01348":{"line":1347,"offset":232214,"length":167,"previous":"M16-GAP-01347","next":"M16-GAP-01349"},"M16-GAP-01349":{"line":1348,"offset":232381,"length":182,"previous":"M16-GAP-01348","next":"M16-GAP-01350"},"M16-GAP-01350":{"line":1349,"offset":232563,"length":191,"previous":"M16-GAP-01349","next":"M16-GAP-01351"},"M16-GAP-01351":{"line":1350,"offset":232754,"length":186,"previous":"M16-GAP-01350","next":"M16-GAP-01352"},"M16-GAP-01352":{"line":1351,"offset":232940,"length":184,"previous":"M16-GAP-01351","next":"M16-GAP-01353"},"M16-GAP-01353":{"line":1352,"offset":233124,"length":183,"previous":"M16-GAP-01352","next":"M16-GAP-01354"},"M16-GAP-01354":{"line":1353,"offset":233307,"length":169,"previous":"M16-GAP-01353","next":"M16-GAP-01355"},"M16-GAP-01355":{"line":1354,"offset":233476,"length":177,"previous":"M16-GAP-01354","next":"M16-GAP-01356"},"M16-GAP-01356":{"line":1355,"offset":233653,"length":171,"previous":"M16-GAP-01355","next":"M16-GAP-01357"},"M16-GAP-01357":{"line":1356,"offset":233824,"length":170,"previous":"M16-GAP-01356","next":"M16-GAP-01358"},"M16-GAP-01358":{"line":1357,"offset":233994,"length":166,"previous":"M16-GAP-01357","next":"M16-GAP-01359"},"M16-GAP-01359":{"line":1358,"offset":234160,"length":170,"previous":"M16-GAP-01358","next":"M16-GAP-01360"},"M16-GAP-01360":{"line":1359,"offset":234330,"length":171,"previous":"M16-GAP-01359","next":"M16-GAP-01361"},"M16-GAP-01361":{"line":1360,"offset":234501,"length":170,"previous":"M16-GAP-01360","next":"M16-GAP-01362"},"M16-GAP-01362":{"line":1361,"offset":234671,"length":176,"previous":"M16-GAP-01361","next":"M16-GAP-01363"},"M16-GAP-01363":{"line":1362,"offset":234847,"length":177,"previous":"M16-GAP-01362","next":"M16-GAP-01364"},"M16-GAP-01364":{"line":1363,"offset":235024,"length":179,"previous":"M16-GAP-01363","next":"M16-GAP-01365"},"M16-GAP-01365":{"line":1364,"offset":235203,"length":162,"previous":"M16-GAP-01364","next":"M16-GAP-01366"},"M16-GAP-01366":{"line":1365,"offset":235365,"length":187,"previous":"M16-GAP-01365","next":"M16-GAP-01367"},"M16-GAP-01367":{"line":1366,"offset":235552,"length":188,"previous":"M16-GAP-01366","next":"M16-GAP-01368"},"M16-GAP-01368":{"line":1367,"offset":235740,"length":190,"previous":"M16-GAP-01367","next":"M16-GAP-01369"},"M16-GAP-01369":{"line":1368,"offset":235930,"length":162,"previous":"M16-GAP-01368","next":"M16-GAP-01370"},"M16-GAP-01370":{"line":1369,"offset":236092,"length":166,"previous":"M16-GAP-01369","next":"M16-GAP-01371"},"M16-GAP-01371":{"line":1370,"offset":236258,"length":166,"previous":"M16-GAP-01370","next":"M16-GAP-01372"},"M16-GAP-01372":{"line":1371,"offset":236424,"length":169,"previous":"M16-GAP-01371","next":"M16-GAP-01373"},"M16-GAP-01373":{"line":1372,"offset":236593,"length":170,"previous":"M16-GAP-01372","next":"M16-GAP-01374"},"M16-GAP-01374":{"line":1373,"offset":236763,"length":168,"previous":"M16-GAP-01373","next":"M16-GAP-01375"},"M16-GAP-01375":{"line":1374,"offset":236931,"length":174,"previous":"M16-GAP-01374","next":"M16-GAP-01376"},"M16-GAP-01376":{"line":1375,"offset":237105,"length":174,"previous":"M16-GAP-01375","next":"M16-GAP-01377"},"M16-GAP-01377":{"line":1376,"offset":237279,"length":172,"previous":"M16-GAP-01376","next":"M16-GAP-01378"},"M16-GAP-01378":{"line":1377,"offset":237451,"length":177,"previous":"M16-GAP-01377","next":"M16-GAP-01379"},"M16-GAP-01379":{"line":1378,"offset":237628,"length":180,"previous":"M16-GAP-01378","next":"M16-GAP-01380"},"M16-GAP-01380":{"line":1379,"offset":237808,"length":181,"previous":"M16-GAP-01379","next":"M16-GAP-01381"},"M16-GAP-01381":{"line":1380,"offset":237989,"length":183,"previous":"M16-GAP-01380","next":"M16-GAP-01382"},"M16-GAP-01382":{"line":1381,"offset":238172,"length":176,"previous":"M16-GAP-01381","next":"M16-GAP-01383"},"M16-GAP-01383":{"line":1382,"offset":238348,"length":180,"previous":"M16-GAP-01382","next":"M16-GAP-01384"},"M16-GAP-01384":{"line":1383,"offset":238528,"length":181,"previous":"M16-GAP-01383","next":"M16-GAP-01385"},"M16-GAP-01385":{"line":1384,"offset":238709,"length":183,"previous":"M16-GAP-01384","next":"M16-GAP-01386"},"M16-GAP-01386":{"line":1385,"offset":238892,"length":168,"previous":"M16-GAP-01385","next":"M16-GAP-01387"},"M16-GAP-01387":{"line":1386,"offset":239060,"length":172,"previous":"M16-GAP-01386","next":"M16-GAP-01388"},"M16-GAP-01388":{"line":1387,"offset":239232,"length":172,"previous":"M16-GAP-01387","next":"M16-GAP-01389"},"M16-GAP-01389":{"line":1388,"offset":239404,"length":165,"previous":"M16-GAP-01388","next":"M16-GAP-01390"},"M16-GAP-01390":{"line":1389,"offset":239569,"length":173,"previous":"M16-GAP-01389","next":"M16-GAP-01391"},"M16-GAP-01391":{"line":1390,"offset":239742,"length":165,"previous":"M16-GAP-01390","next":"M16-GAP-01392"},"M16-GAP-01392":{"line":1391,"offset":239907,"length":182,"previous":"M16-GAP-01391","next":"M16-GAP-01393"},"M16-GAP-01393":{"line":1392,"offset":240089,"length":169,"previous":"M16-GAP-01392","next":"M16-GAP-01394"},"M16-GAP-01394":{"line":1393,"offset":240258,"length":172,"previous":"M16-GAP-01393","next":"M16-GAP-01395"},"M16-GAP-01395":{"line":1394,"offset":240430,"length":189,"previous":"M16-GAP-01394","next":"M16-GAP-01396"},"M16-GAP-01396":{"line":1395,"offset":240619,"length":172,"previous":"M16-GAP-01395","next":"M16-GAP-01397"},"M16-GAP-01397":{"line":1396,"offset":240791,"length":164,"previous":"M16-GAP-01396","next":"M16-GAP-01398"},"M16-GAP-01398":{"line":1397,"offset":240955,"length":169,"previous":"M16-GAP-01397","next":"M16-GAP-01399"},"M16-GAP-01399":{"line":1398,"offset":241124,"length":169,"previous":"M16-GAP-01398","next":"M16-GAP-01400"},"M16-GAP-01400":{"line":1399,"offset":241293,"length":175,"previous":"M16-GAP-01399","next":"M16-GAP-01401"},"M16-GAP-01401":{"line":1400,"offset":241468,"length":175,"previous":"M16-GAP-01400","next":"M16-GAP-01402"},"M16-GAP-01402":{"line":1401,"offset":241643,"length":161,"previous":"M16-GAP-01401","next":"M16-GAP-01403"},"M16-GAP-01403":{"line":1402,"offset":241804,"length":175,"previous":"M16-GAP-01402","next":"M16-GAP-01404"},"M16-GAP-01404":{"line":1403,"offset":241979,"length":167,"previous":"M16-GAP-01403","next":"M16-GAP-01405"},"M16-GAP-01405":{"line":1404,"offset":242146,"length":163,"previous":"M16-GAP-01404","next":"M16-GAP-01406"},"M16-GAP-01406":{"line":1405,"offset":242309,"length":183,"previous":"M16-GAP-01405","next":"M16-GAP-01407"},"M16-GAP-01407":{"line":1406,"offset":242492,"length":170,"previous":"M16-GAP-01406","next":"M16-GAP-01408"},"M16-GAP-01408":{"line":1407,"offset":242662,"length":182,"previous":"M16-GAP-01407","next":"M16-GAP-01409"},"M16-GAP-01409":{"line":1408,"offset":242844,"length":162,"previous":"M16-GAP-01408","next":"M16-GAP-01410"},"M16-GAP-01410":{"line":1409,"offset":243006,"length":168,"previous":"M16-GAP-01409","next":"M16-GAP-01411"},"M16-GAP-01411":{"line":1410,"offset":243174,"length":168,"previous":"M16-GAP-01410","next":"M16-GAP-01412"},"M16-GAP-01412":{"line":1411,"offset":243342,"length":178,"previous":"M16-GAP-01411","next":"M16-GAP-01413"},"M16-GAP-01413":{"line":1412,"offset":243520,"length":180,"previous":"M16-GAP-01412","next":"M16-GAP-01414"},"M16-GAP-01414":{"line":1413,"offset":243700,"length":172,"previous":"M16-GAP-01413","next":"M16-GAP-01415"},"M16-GAP-01415":{"line":1414,"offset":243872,"length":188,"previous":"M16-GAP-01414","next":"M16-GAP-01416"},"M16-GAP-01416":{"line":1415,"offset":244060,"length":181,"previous":"M16-GAP-01415","next":"M16-GAP-01417"},"M16-GAP-01417":{"line":1416,"offset":244241,"length":173,"previous":"M16-GAP-01416","next":"M16-GAP-01418"},"M16-GAP-01418":{"line":1417,"offset":244414,"length":183,"previous":"M16-GAP-01417","next":"M16-GAP-01419"},"M16-GAP-01419":{"line":1418,"offset":244597,"length":175,"previous":"M16-GAP-01418","next":"M16-GAP-01420"},"M16-GAP-01420":{"line":1419,"offset":244772,"length":175,"previous":"M16-GAP-01419","next":"M16-GAP-01421"},"M16-GAP-01421":{"line":1420,"offset":244947,"length":172,"previous":"M16-GAP-01420","next":"M16-GAP-01422"},"M16-GAP-01422":{"line":1421,"offset":245119,"length":185,"previous":"M16-GAP-01421","next":"M16-GAP-01423"},"M16-GAP-01423":{"line":1422,"offset":245304,"length":175,"previous":"M16-GAP-01422","next":"M16-GAP-01424"},"M16-GAP-01424":{"line":1423,"offset":245479,"length":174,"previous":"M16-GAP-01423","next":"M16-GAP-01425"},"M16-GAP-01425":{"line":1424,"offset":245653,"length":165,"previous":"M16-GAP-01424","next":"M16-GAP-01426"},"M16-GAP-01426":{"line":1425,"offset":245818,"length":179,"previous":"M16-GAP-01425","next":"M16-GAP-01427"},"M16-GAP-01427":{"line":1426,"offset":245997,"length":181,"previous":"M16-GAP-01426","next":"M16-GAP-01428"},"M16-GAP-01428":{"line":1427,"offset":246178,"length":179,"previous":"M16-GAP-01427","next":"M16-GAP-01429"},"M16-GAP-01429":{"line":1428,"offset":246357,"length":179,"previous":"M16-GAP-01428","next":"M16-GAP-01430"},"M16-GAP-01430":{"line":1429,"offset":246536,"length":175,"previous":"M16-GAP-01429","next":"M16-GAP-01431"},"M16-GAP-01431":{"line":1430,"offset":246711,"length":175,"previous":"M16-GAP-01430","next":"M16-GAP-01432"},"M16-GAP-01432":{"line":1431,"offset":246886,"length":171,"previous":"M16-GAP-01431","next":"M16-GAP-01433"},"M16-GAP-01433":{"line":1432,"offset":247057,"length":177,"previous":"M16-GAP-01432","next":"M16-GAP-01434"},"M16-GAP-01434":{"line":1433,"offset":247234,"length":164,"previous":"M16-GAP-01433","next":"M16-GAP-01435"},"M16-GAP-01435":{"line":1434,"offset":247398,"length":183,"previous":"M16-GAP-01434","next":"M16-GAP-01436"},"M16-GAP-01436":{"line":1435,"offset":247581,"length":177,"previous":"M16-GAP-01435","next":"M16-GAP-01437"},"M16-GAP-01437":{"line":1436,"offset":247758,"length":177,"previous":"M16-GAP-01436","next":"M16-GAP-01438"},"M16-GAP-01438":{"line":1437,"offset":247935,"length":167,"previous":"M16-GAP-01437","next":"M16-GAP-01439"},"M16-GAP-01439":{"line":1438,"offset":248102,"length":172,"previous":"M16-GAP-01438","next":"M16-GAP-01440"},"M16-GAP-01440":{"line":1439,"offset":248274,"length":179,"previous":"M16-GAP-01439","next":"M16-GAP-01441"},"M16-GAP-01441":{"line":1440,"offset":248453,"length":178,"previous":"M16-GAP-01440","next":"M16-GAP-01442"},"M16-GAP-01442":{"line":1441,"offset":248631,"length":173,"previous":"M16-GAP-01441","next":"M16-GAP-01443"},"M16-GAP-01443":{"line":1442,"offset":248804,"length":170,"previous":"M16-GAP-01442","next":"M16-GAP-01444"},"M16-GAP-01444":{"line":1443,"offset":248974,"length":167,"previous":"M16-GAP-01443","next":"M16-GAP-01445"},"M16-GAP-01445":{"line":1444,"offset":249141,"length":173,"previous":"M16-GAP-01444","next":"M16-GAP-01446"},"M16-GAP-01446":{"line":1445,"offset":249314,"length":173,"previous":"M16-GAP-01445","next":"M16-GAP-01447"},"M16-GAP-01447":{"line":1446,"offset":249487,"length":171,"previous":"M16-GAP-01446","next":"M16-GAP-01448"},"M16-GAP-01448":{"line":1447,"offset":249658,"length":175,"previous":"M16-GAP-01447","next":"M16-GAP-01449"},"M16-GAP-01449":{"line":1448,"offset":249833,"length":190,"previous":"M16-GAP-01448","next":"M16-GAP-01450"},"M16-GAP-01450":{"line":1449,"offset":250023,"length":188,"previous":"M16-GAP-01449","next":"M16-GAP-01451"},"M16-GAP-01451":{"line":1450,"offset":250211,"length":183,"previous":"M16-GAP-01450","next":"M16-GAP-01452"},"M16-GAP-01452":{"line":1451,"offset":250394,"length":190,"previous":"M16-GAP-01451","next":"M16-GAP-01453"},"M16-GAP-01453":{"line":1452,"offset":250584,"length":188,"previous":"M16-GAP-01452","next":"M16-GAP-01454"},"M16-GAP-01454":{"line":1453,"offset":250772,"length":195,"previous":"M16-GAP-01453","next":"M16-GAP-01455"},"M16-GAP-01455":{"line":1454,"offset":250967,"length":186,"previous":"M16-GAP-01454","next":"M16-GAP-01456"},"M16-GAP-01456":{"line":1455,"offset":251153,"length":175,"previous":"M16-GAP-01455","next":"M16-GAP-01457"},"M16-GAP-01457":{"line":1456,"offset":251328,"length":197,"previous":"M16-GAP-01456","next":"M16-GAP-01458"},"M16-GAP-01458":{"line":1457,"offset":251525,"length":198,"previous":"M16-GAP-01457","next":"M16-GAP-01459"},"M16-GAP-01459":{"line":1458,"offset":251723,"length":200,"previous":"M16-GAP-01458","next":"M16-GAP-01460"},"M16-GAP-01460":{"line":1459,"offset":251923,"length":197,"previous":"M16-GAP-01459","next":"M16-GAP-01461"},"M16-GAP-01461":{"line":1460,"offset":252120,"length":198,"previous":"M16-GAP-01460","next":"M16-GAP-01462"},"M16-GAP-01462":{"line":1461,"offset":252318,"length":200,"previous":"M16-GAP-01461","next":"M16-GAP-01463"},"M16-GAP-01463":{"line":1462,"offset":252518,"length":173,"previous":"M16-GAP-01462","next":"M16-GAP-01464"},"M16-GAP-01464":{"line":1463,"offset":252691,"length":179,"previous":"M16-GAP-01463","next":"M16-GAP-01465"},"M16-GAP-01465":{"line":1464,"offset":252870,"length":173,"previous":"M16-GAP-01464","next":"M16-GAP-01466"},"M16-GAP-01466":{"line":1465,"offset":253043,"length":171,"previous":"M16-GAP-01465","next":"M16-GAP-01467"},"M16-GAP-01467":{"line":1466,"offset":253214,"length":172,"previous":"M16-GAP-01466","next":"M16-GAP-01468"},"M16-GAP-01468":{"line":1467,"offset":253386,"length":172,"previous":"M16-GAP-01467","next":"M16-GAP-01469"},"M16-GAP-01469":{"line":1468,"offset":253558,"length":169,"previous":"M16-GAP-01468","next":"M16-GAP-01470"},"M16-GAP-01470":{"line":1469,"offset":253727,"length":171,"previous":"M16-GAP-01469","next":"M16-GAP-01471"},"M16-GAP-01471":{"line":1470,"offset":253898,"length":169,"previous":"M16-GAP-01470","next":"M16-GAP-01472"},"M16-GAP-01472":{"line":1471,"offset":254067,"length":168,"previous":"M16-GAP-01471","next":"M16-GAP-01473"},"M16-GAP-01473":{"line":1472,"offset":254235,"length":169,"previous":"M16-GAP-01472","next":"M16-GAP-01474"},"M16-GAP-01474":{"line":1473,"offset":254404,"length":185,"previous":"M16-GAP-01473","next":"M16-GAP-01475"},"M16-GAP-01475":{"line":1474,"offset":254589,"length":185,"previous":"M16-GAP-01474","next":"M16-GAP-01476"},"M16-GAP-01476":{"line":1475,"offset":254774,"length":183,"previous":"M16-GAP-01475","next":"M16-GAP-01477"},"M16-GAP-01477":{"line":1476,"offset":254957,"length":177,"previous":"M16-GAP-01476","next":"M16-GAP-01478"},"M16-GAP-01478":{"line":1477,"offset":255134,"length":162,"previous":"M16-GAP-01477","next":"M16-GAP-01479"},"M16-GAP-01479":{"line":1478,"offset":255296,"length":169,"previous":"M16-GAP-01478","next":"M16-GAP-01480"},"M16-GAP-01480":{"line":1479,"offset":255465,"length":166,"previous":"M16-GAP-01479","next":"M16-GAP-01481"},"M16-GAP-01481":{"line":1480,"offset":255631,"length":178,"previous":"M16-GAP-01480","next":"M16-GAP-01482"},"M16-GAP-01482":{"line":1481,"offset":255809,"length":181,"previous":"M16-GAP-01481","next":"M16-GAP-01483"},"M16-GAP-01483":{"line":1482,"offset":255990,"length":167,"previous":"M16-GAP-01482","next":"M16-GAP-01484"},"M16-GAP-01484":{"line":1483,"offset":256157,"length":194,"previous":"M16-GAP-01483","next":"M16-GAP-01485"},"M16-GAP-01485":{"line":1484,"offset":256351,"length":185,"previous":"M16-GAP-01484","next":"M16-GAP-01486"},"M16-GAP-01486":{"line":1485,"offset":256536,"length":187,"previous":"M16-GAP-01485","next":"M16-GAP-01487"},"M16-GAP-01487":{"line":1486,"offset":256723,"length":195,"previous":"M16-GAP-01486","next":"M16-GAP-01488"},"M16-GAP-01488":{"line":1487,"offset":256918,"length":186,"previous":"M16-GAP-01487","next":"M16-GAP-01489"},"M16-GAP-01489":{"line":1488,"offset":257104,"length":188,"previous":"M16-GAP-01488","next":"M16-GAP-01490"},"M16-GAP-01490":{"line":1489,"offset":257292,"length":194,"previous":"M16-GAP-01489","next":"M16-GAP-01491"},"M16-GAP-01491":{"line":1490,"offset":257486,"length":172,"previous":"M16-GAP-01490","next":"M16-GAP-01492"},"M16-GAP-01492":{"line":1491,"offset":257658,"length":179,"previous":"M16-GAP-01491","next":"M16-GAP-01493"},"M16-GAP-01493":{"line":1492,"offset":257837,"length":179,"previous":"M16-GAP-01492","next":"M16-GAP-01494"},"M16-GAP-01494":{"line":1493,"offset":258016,"length":178,"previous":"M16-GAP-01493","next":"M16-GAP-01495"},"M16-GAP-01495":{"line":1494,"offset":258194,"length":171,"previous":"M16-GAP-01494","next":"M16-GAP-01496"},"M16-GAP-01496":{"line":1495,"offset":258365,"length":176,"previous":"M16-GAP-01495","next":"M16-GAP-01497"},"M16-GAP-01497":{"line":1496,"offset":258541,"length":172,"previous":"M16-GAP-01496","next":"M16-GAP-01498"},"M16-GAP-01498":{"line":1497,"offset":258713,"length":173,"previous":"M16-GAP-01497","next":"M16-GAP-01499"},"M16-GAP-01499":{"line":1498,"offset":258886,"length":173,"previous":"M16-GAP-01498","next":"M16-GAP-01500"},"M16-GAP-01500":{"line":1499,"offset":259059,"length":174,"previous":"M16-GAP-01499","next":"M16-GAP-01501"},"M16-GAP-01501":{"line":1500,"offset":259233,"length":168,"previous":"M16-GAP-01500","next":"M16-GAP-01502"},"M16-GAP-01502":{"line":1501,"offset":259401,"length":179,"previous":"M16-GAP-01501","next":"M16-GAP-01503"},"M16-GAP-01503":{"line":1502,"offset":259580,"length":174,"previous":"M16-GAP-01502","next":"M16-GAP-01504"},"M16-GAP-01504":{"line":1503,"offset":259754,"length":175,"previous":"M16-GAP-01503","next":"M16-GAP-01505"},"M16-GAP-01505":{"line":1504,"offset":259929,"length":178,"previous":"M16-GAP-01504","next":"M16-GAP-01506"},"M16-GAP-01506":{"line":1505,"offset":260107,"length":176,"previous":"M16-GAP-01505","next":"M16-GAP-01507"},"M16-GAP-01507":{"line":1506,"offset":260283,"length":180,"previous":"M16-GAP-01506","next":"M16-GAP-01508"},"M16-GAP-01508":{"line":1507,"offset":260463,"length":176,"previous":"M16-GAP-01507","next":"M16-GAP-01509"},"M16-GAP-01509":{"line":1508,"offset":260639,"length":178,"previous":"M16-GAP-01508","next":"M16-GAP-01510"},"M16-GAP-01510":{"line":1509,"offset":260817,"length":182,"previous":"M16-GAP-01509","next":"M16-GAP-01511"},"M16-GAP-01511":{"line":1510,"offset":260999,"length":185,"previous":"M16-GAP-01510","next":"M16-GAP-01512"},"M16-GAP-01512":{"line":1511,"offset":261184,"length":178,"previous":"M16-GAP-01511","next":"M16-GAP-01513"},"M16-GAP-01513":{"line":1512,"offset":261362,"length":173,"previous":"M16-GAP-01512","next":"M16-GAP-01514"},"M16-GAP-01514":{"line":1513,"offset":261535,"length":170,"previous":"M16-GAP-01513","next":"M16-GAP-01515"},"M16-GAP-01515":{"line":1514,"offset":261705,"length":166,"previous":"M16-GAP-01514","next":"M16-GAP-01516"},"M16-GAP-01516":{"line":1515,"offset":261871,"length":179,"previous":"M16-GAP-01515","next":"M16-GAP-01517"},"M16-GAP-01517":{"line":1516,"offset":262050,"length":170,"previous":"M16-GAP-01516","next":"M16-GAP-01518"},"M16-GAP-01518":{"line":1517,"offset":262220,"length":181,"previous":"M16-GAP-01517","next":"M16-GAP-01519"},"M16-GAP-01519":{"line":1518,"offset":262401,"length":172,"previous":"M16-GAP-01518","next":"M16-GAP-01520"},"M16-GAP-01520":{"line":1519,"offset":262573,"length":184,"previous":"M16-GAP-01519","next":"M16-GAP-01521"},"M16-GAP-01521":{"line":1520,"offset":262757,"length":174,"previous":"M16-GAP-01520","next":"M16-GAP-01522"},"M16-GAP-01522":{"line":1521,"offset":262931,"length":171,"previous":"M16-GAP-01521","next":"M16-GAP-01523"},"M16-GAP-01523":{"line":1522,"offset":263102,"length":183,"previous":"M16-GAP-01522","next":"M16-GAP-01524"},"M16-GAP-01524":{"line":1523,"offset":263285,"length":176,"previous":"M16-GAP-01523","next":"M16-GAP-01525"},"M16-GAP-01525":{"line":1524,"offset":263461,"length":180,"previous":"M16-GAP-01524","next":"M16-GAP-01526"},"M16-GAP-01526":{"line":1525,"offset":263641,"length":174,"previous":"M16-GAP-01525","next":"M16-GAP-01527"},"M16-GAP-01527":{"line":1526,"offset":263815,"length":173,"previous":"M16-GAP-01526","next":"M16-GAP-01528"},"M16-GAP-01528":{"line":1527,"offset":263988,"length":177,"previous":"M16-GAP-01527","next":"M16-GAP-01529"},"M16-GAP-01529":{"line":1528,"offset":264165,"length":173,"previous":"M16-GAP-01528","next":"M16-GAP-01530"},"M16-GAP-01530":{"line":1529,"offset":264338,"length":184,"previous":"M16-GAP-01529","next":"M16-GAP-01531"},"M16-GAP-01531":{"line":1530,"offset":264522,"length":176,"previous":"M16-GAP-01530","next":"M16-GAP-01532"},"M16-GAP-01532":{"line":1531,"offset":264698,"length":177,"previous":"M16-GAP-01531","next":"M16-GAP-01533"},"M16-GAP-01533":{"line":1532,"offset":264875,"length":180,"previous":"M16-GAP-01532","next":"M16-GAP-01534"},"M16-GAP-01534":{"line":1533,"offset":265055,"length":180,"previous":"M16-GAP-01533","next":"M16-GAP-01535"},"M16-GAP-01535":{"line":1534,"offset":265235,"length":187,"previous":"M16-GAP-01534","next":"M16-GAP-01536"},"M16-GAP-01536":{"line":1535,"offset":265422,"length":181,"previous":"M16-GAP-01535","next":"M16-GAP-01537"},"M16-GAP-01537":{"line":1536,"offset":265603,"length":174,"previous":"M16-GAP-01536","next":"M16-GAP-01538"},"M16-GAP-01538":{"line":1537,"offset":265777,"length":176,"previous":"M16-GAP-01537","next":"M16-GAP-01539"},"M16-GAP-01539":{"line":1538,"offset":265953,"length":178,"previous":"M16-GAP-01538","next":"M16-GAP-01540"},"M16-GAP-01540":{"line":1539,"offset":266131,"length":168,"previous":"M16-GAP-01539","next":"M16-GAP-01541"},"M16-GAP-01541":{"line":1540,"offset":266299,"length":170,"previous":"M16-GAP-01540","next":"M16-GAP-01542"},"M16-GAP-01542":{"line":1541,"offset":266469,"length":168,"previous":"M16-GAP-01541","next":"M16-GAP-01543"},"M16-GAP-01543":{"line":1542,"offset":266637,"length":170,"previous":"M16-GAP-01542","next":"M16-GAP-01544"},"M16-GAP-01544":{"line":1543,"offset":266807,"length":178,"previous":"M16-GAP-01543","next":"M16-GAP-01545"},"M16-GAP-01545":{"line":1544,"offset":266985,"length":179,"previous":"M16-GAP-01544","next":"M16-GAP-01546"},"M16-GAP-01546":{"line":1545,"offset":267164,"length":168,"previous":"M16-GAP-01545","next":"M16-GAP-01547"},"M16-GAP-01547":{"line":1546,"offset":267332,"length":177,"previous":"M16-GAP-01546","next":"M16-GAP-01548"},"M16-GAP-01548":{"line":1547,"offset":267509,"length":180,"previous":"M16-GAP-01547","next":"M16-GAP-01549"},"M16-GAP-01549":{"line":1548,"offset":267689,"length":173,"previous":"M16-GAP-01548","next":"M16-GAP-01550"},"M16-GAP-01550":{"line":1549,"offset":267862,"length":173,"previous":"M16-GAP-01549","next":"M16-GAP-01551"},"M16-GAP-01551":{"line":1550,"offset":268035,"length":169,"previous":"M16-GAP-01550","next":"M16-GAP-01552"},"M16-GAP-01552":{"line":1551,"offset":268204,"length":170,"previous":"M16-GAP-01551","next":"M16-GAP-01553"},"M16-GAP-01553":{"line":1552,"offset":268374,"length":178,"previous":"M16-GAP-01552","next":"M16-GAP-01554"},"M16-GAP-01554":{"line":1553,"offset":268552,"length":179,"previous":"M16-GAP-01553","next":"M16-GAP-01555"},"M16-GAP-01555":{"line":1554,"offset":268731,"length":173,"previous":"M16-GAP-01554","next":"M16-GAP-01556"},"M16-GAP-01556":{"line":1555,"offset":268904,"length":175,"previous":"M16-GAP-01555","next":"M16-GAP-01557"},"M16-GAP-01557":{"line":1556,"offset":269079,"length":171,"previous":"M16-GAP-01556","next":"M16-GAP-01558"},"M16-GAP-01558":{"line":1557,"offset":269250,"length":167,"previous":"M16-GAP-01557","next":"M16-GAP-01559"},"M16-GAP-01559":{"line":1558,"offset":269417,"length":170,"previous":"M16-GAP-01558","next":"M16-GAP-01560"},"M16-GAP-01560":{"line":1559,"offset":269587,"length":169,"previous":"M16-GAP-01559","next":"M16-GAP-01561"},"M16-GAP-01561":{"line":1560,"offset":269756,"length":177,"previous":"M16-GAP-01560","next":"M16-GAP-01562"},"M16-GAP-01562":{"line":1561,"offset":269933,"length":180,"previous":"M16-GAP-01561","next":"M16-GAP-01563"},"M16-GAP-01563":{"line":1562,"offset":270113,"length":172,"previous":"M16-GAP-01562","next":"M16-GAP-01564"},"M16-GAP-01564":{"line":1563,"offset":270285,"length":169,"previous":"M16-GAP-01563","next":"M16-GAP-01565"},"M16-GAP-01565":{"line":1564,"offset":270454,"length":168,"previous":"M16-GAP-01564","next":"M16-GAP-01566"},"M16-GAP-01566":{"line":1565,"offset":270622,"length":172,"previous":"M16-GAP-01565","next":"M16-GAP-01567"},"M16-GAP-01567":{"line":1566,"offset":270794,"length":171,"previous":"M16-GAP-01566","next":"M16-GAP-01568"},"M16-GAP-01568":{"line":1567,"offset":270965,"length":172,"previous":"M16-GAP-01567","next":"M16-GAP-01569"},"M16-GAP-01569":{"line":1568,"offset":271137,"length":174,"previous":"M16-GAP-01568","next":"M16-GAP-01570"},"M16-GAP-01570":{"line":1569,"offset":271311,"length":169,"previous":"M16-GAP-01569","next":"M16-GAP-01571"},"M16-GAP-01571":{"line":1570,"offset":271480,"length":171,"previous":"M16-GAP-01570","next":"M16-GAP-01572"},"M16-GAP-01572":{"line":1571,"offset":271651,"length":171,"previous":"M16-GAP-01571","next":"M16-GAP-01573"},"M16-GAP-01573":{"line":1572,"offset":271822,"length":169,"previous":"M16-GAP-01572","next":"M16-GAP-01574"},"M16-GAP-01574":{"line":1573,"offset":271991,"length":172,"previous":"M16-GAP-01573","next":"M16-GAP-01575"},"M16-GAP-01575":{"line":1574,"offset":272163,"length":171,"previous":"M16-GAP-01574","next":"M16-GAP-01576"},"M16-GAP-01576":{"line":1575,"offset":272334,"length":180,"previous":"M16-GAP-01575","next":"M16-GAP-01577"},"M16-GAP-01577":{"line":1576,"offset":272514,"length":175,"previous":"M16-GAP-01576","next":"M16-GAP-01578"},"M16-GAP-01578":{"line":1577,"offset":272689,"length":168,"previous":"M16-GAP-01577","next":"M16-GAP-01579"},"M16-GAP-01579":{"line":1578,"offset":272857,"length":170,"previous":"M16-GAP-01578","next":"M16-GAP-01580"},"M16-GAP-01580":{"line":1579,"offset":273027,"length":179,"previous":"M16-GAP-01579","next":"M16-GAP-01581"},"M16-GAP-01581":{"line":1580,"offset":273206,"length":170,"previous":"M16-GAP-01580","next":"M16-GAP-01582"},"M16-GAP-01582":{"line":1581,"offset":273376,"length":171,"previous":"M16-GAP-01581","next":"M16-GAP-01583"},"M16-GAP-01583":{"line":1582,"offset":273547,"length":176,"previous":"M16-GAP-01582","next":"M16-GAP-01584"},"M16-GAP-01584":{"line":1583,"offset":273723,"length":180,"previous":"M16-GAP-01583","next":"M16-GAP-01585"},"M16-GAP-01585":{"line":1584,"offset":273903,"length":174,"previous":"M16-GAP-01584","next":"M16-GAP-01586"},"M16-GAP-01586":{"line":1585,"offset":274077,"length":173,"previous":"M16-GAP-01585","next":"M16-GAP-01587"},"M16-GAP-01587":{"line":1586,"offset":274250,"length":171,"previous":"M16-GAP-01586","next":"M16-GAP-01588"},"M16-GAP-01588":{"line":1587,"offset":274421,"length":182,"previous":"M16-GAP-01587","next":"M16-GAP-01589"},"M16-GAP-01589":{"line":1588,"offset":274603,"length":173,"previous":"M16-GAP-01588","next":"M16-GAP-01590"},"M16-GAP-01590":{"line":1589,"offset":274776,"length":172,"previous":"M16-GAP-01589","next":"M16-GAP-01591"},"M16-GAP-01591":{"line":1590,"offset":274948,"length":172,"previous":"M16-GAP-01590","next":"M16-GAP-01592"},"M16-GAP-01592":{"line":1591,"offset":275120,"length":178,"previous":"M16-GAP-01591","next":"M16-GAP-01593"},"M16-GAP-01593":{"line":1592,"offset":275298,"length":174,"previous":"M16-GAP-01592","next":"M16-GAP-01594"},"M16-GAP-01594":{"line":1593,"offset":275472,"length":172,"previous":"M16-GAP-01593","next":"M16-GAP-01595"},"M16-GAP-01595":{"line":1594,"offset":275644,"length":174,"previous":"M16-GAP-01594","next":"M16-GAP-01596"},"M16-GAP-01596":{"line":1595,"offset":275818,"length":174,"previous":"M16-GAP-01595","next":"M16-GAP-01597"},"M16-GAP-01597":{"line":1596,"offset":275992,"length":176,"previous":"M16-GAP-01596","next":"M16-GAP-01598"},"M16-GAP-01598":{"line":1597,"offset":276168,"length":185,"previous":"M16-GAP-01597","next":"M16-GAP-01599"},"M16-GAP-01599":{"line":1598,"offset":276353,"length":199,"previous":"M16-GAP-01598","next":"M16-GAP-01600"},"M16-GAP-01600":{"line":1599,"offset":276552,"length":187,"previous":"M16-GAP-01599","next":"M16-GAP-01601"},"M16-GAP-01601":{"line":1600,"offset":276739,"length":178,"previous":"M16-GAP-01600","next":"M16-GAP-01602"},"M16-GAP-01602":{"line":1601,"offset":276917,"length":179,"previous":"M16-GAP-01601","next":"M16-GAP-01603"},"M16-GAP-01603":{"line":1602,"offset":277096,"length":177,"previous":"M16-GAP-01602","next":"M16-GAP-01604"},"M16-GAP-01604":{"line":1603,"offset":277273,"length":172,"previous":"M16-GAP-01603","next":"M16-GAP-01605"},"M16-GAP-01605":{"line":1604,"offset":277445,"length":169,"previous":"M16-GAP-01604","next":"M16-GAP-01606"},"M16-GAP-01606":{"line":1605,"offset":277614,"length":173,"previous":"M16-GAP-01605","next":"M16-GAP-01607"},"M16-GAP-01607":{"line":1606,"offset":277787,"length":176,"previous":"M16-GAP-01606","next":"M16-GAP-01608"},"M16-GAP-01608":{"line":1607,"offset":277963,"length":166,"previous":"M16-GAP-01607","next":"M16-GAP-01609"},"M16-GAP-01609":{"line":1608,"offset":278129,"length":169,"previous":"M16-GAP-01608","next":"M16-GAP-01610"},"M16-GAP-01610":{"line":1609,"offset":278298,"length":167,"previous":"M16-GAP-01609","next":"M16-GAP-01611"},"M16-GAP-01611":{"line":1610,"offset":278465,"length":171,"previous":"M16-GAP-01610","next":"M16-GAP-01612"},"M16-GAP-01612":{"line":1611,"offset":278636,"length":173,"previous":"M16-GAP-01611","next":"M16-GAP-01613"},"M16-GAP-01613":{"line":1612,"offset":278809,"length":179,"previous":"M16-GAP-01612","next":"M16-GAP-01614"},"M16-GAP-01614":{"line":1613,"offset":278988,"length":176,"previous":"M16-GAP-01613","next":"M16-GAP-01615"},"M16-GAP-01615":{"line":1614,"offset":279164,"length":178,"previous":"M16-GAP-01614","next":"M16-GAP-01616"},"M16-GAP-01616":{"line":1615,"offset":279342,"length":169,"previous":"M16-GAP-01615","next":"M16-GAP-01617"},"M16-GAP-01617":{"line":1616,"offset":279511,"length":171,"previous":"M16-GAP-01616","next":"M16-GAP-01618"},"M16-GAP-01618":{"line":1617,"offset":279682,"length":174,"previous":"M16-GAP-01617","next":"M16-GAP-01619"},"M16-GAP-01619":{"line":1618,"offset":279856,"length":177,"previous":"M16-GAP-01618","next":"M16-GAP-01620"},"M16-GAP-01620":{"line":1619,"offset":280033,"length":181,"previous":"M16-GAP-01619","next":"M16-GAP-01621"},"M16-GAP-01621":{"line":1620,"offset":280214,"length":176,"previous":"M16-GAP-01620","next":"M16-GAP-01622"},"M16-GAP-01622":{"line":1621,"offset":280390,"length":175,"previous":"M16-GAP-01621","next":"M16-GAP-01623"},"M16-GAP-01623":{"line":1622,"offset":280565,"length":187,"previous":"M16-GAP-01622","next":"M16-GAP-01624"},"M16-GAP-01624":{"line":1623,"offset":280752,"length":179,"previous":"M16-GAP-01623","next":"M16-GAP-01625"},"M16-GAP-01625":{"line":1624,"offset":280931,"length":177,"previous":"M16-GAP-01624","next":"M16-GAP-01626"},"M16-GAP-01626":{"line":1625,"offset":281108,"length":177,"previous":"M16-GAP-01625","next":"M16-GAP-01627"},"M16-GAP-01627":{"line":1626,"offset":281285,"length":182,"previous":"M16-GAP-01626","next":"M16-GAP-01628"},"M16-GAP-01628":{"line":1627,"offset":281467,"length":175,"previous":"M16-GAP-01627","next":"M16-GAP-01629"},"M16-GAP-01629":{"line":1628,"offset":281642,"length":177,"previous":"M16-GAP-01628","next":"M16-GAP-01630"},"M16-GAP-01630":{"line":1629,"offset":281819,"length":175,"previous":"M16-GAP-01629","next":"M16-GAP-01631"},"M16-GAP-01631":{"line":1630,"offset":281994,"length":180,"previous":"M16-GAP-01630","next":"M16-GAP-01632"},"M16-GAP-01632":{"line":1631,"offset":282174,"length":184,"previous":"M16-GAP-01631","next":"M16-GAP-01633"},"M16-GAP-01633":{"line":1632,"offset":282358,"length":179,"previous":"M16-GAP-01632","next":"M16-GAP-01634"},"M16-GAP-01634":{"line":1633,"offset":282537,"length":177,"previous":"M16-GAP-01633","next":"M16-GAP-01635"},"M16-GAP-01635":{"line":1634,"offset":282714,"length":182,"previous":"M16-GAP-01634","next":"M16-GAP-01636"},"M16-GAP-01636":{"line":1635,"offset":282896,"length":177,"previous":"M16-GAP-01635","next":"M16-GAP-01637"},"M16-GAP-01637":{"line":1636,"offset":283073,"length":181,"previous":"M16-GAP-01636","next":"M16-GAP-01638"},"M16-GAP-01638":{"line":1637,"offset":283254,"length":177,"previous":"M16-GAP-01637","next":"M16-GAP-01639"},"M16-GAP-01639":{"line":1638,"offset":283431,"length":175,"previous":"M16-GAP-01638","next":"M16-GAP-01640"},"M16-GAP-01640":{"line":1639,"offset":283606,"length":175,"previous":"M16-GAP-01639","next":"M16-GAP-01641"},"M16-GAP-01641":{"line":1640,"offset":283781,"length":176,"previous":"M16-GAP-01640","next":"M16-GAP-01642"},"M16-GAP-01642":{"line":1641,"offset":283957,"length":178,"previous":"M16-GAP-01641","next":"M16-GAP-01643"},"M16-GAP-01643":{"line":1642,"offset":284135,"length":195,"previous":"M16-GAP-01642","next":"M16-GAP-01644"},"M16-GAP-01644":{"line":1643,"offset":284330,"length":177,"previous":"M16-GAP-01643","next":"M16-GAP-01645"},"M16-GAP-01645":{"line":1644,"offset":284507,"length":182,"previous":"M16-GAP-01644","next":"M16-GAP-01646"},"M16-GAP-01646":{"line":1645,"offset":284689,"length":184,"previous":"M16-GAP-01645","next":"M16-GAP-01647"},"M16-GAP-01647":{"line":1646,"offset":284873,"length":180,"previous":"M16-GAP-01646","next":"M16-GAP-01648"},"M16-GAP-01648":{"line":1647,"offset":285053,"length":168,"previous":"M16-GAP-01647","next":"M16-GAP-01649"},"M16-GAP-01649":{"line":1648,"offset":285221,"length":171,"previous":"M16-GAP-01648","next":"M16-GAP-01650"},"M16-GAP-01650":{"line":1649,"offset":285392,"length":170,"previous":"M16-GAP-01649","next":"M16-GAP-01651"},"M16-GAP-01651":{"line":1650,"offset":285562,"length":173,"previous":"M16-GAP-01650","next":"M16-GAP-01652"},"M16-GAP-01652":{"line":1651,"offset":285735,"length":170,"previous":"M16-GAP-01651","next":"M16-GAP-01653"},"M16-GAP-01653":{"line":1652,"offset":285905,"length":178,"previous":"M16-GAP-01652","next":"M16-GAP-01654"},"M16-GAP-01654":{"line":1653,"offset":286083,"length":172,"previous":"M16-GAP-01653","next":"M16-GAP-01655"},"M16-GAP-01655":{"line":1654,"offset":286255,"length":184,"previous":"M16-GAP-01654","next":"M16-GAP-01656"},"M16-GAP-01656":{"line":1655,"offset":286439,"length":178,"previous":"M16-GAP-01655","next":"M16-GAP-01657"},"M16-GAP-01657":{"line":1656,"offset":286617,"length":185,"previous":"M16-GAP-01656","next":"M16-GAP-01658"},"M16-GAP-01658":{"line":1657,"offset":286802,"length":175,"previous":"M16-GAP-01657","next":"M16-GAP-01659"},"M16-GAP-01659":{"line":1658,"offset":286977,"length":180,"previous":"M16-GAP-01658","next":"M16-GAP-01660"},"M16-GAP-01660":{"line":1659,"offset":287157,"length":187,"previous":"M16-GAP-01659","next":"M16-GAP-01661"},"M16-GAP-01661":{"line":1660,"offset":287344,"length":177,"previous":"M16-GAP-01660","next":"M16-GAP-01662"},"M16-GAP-01662":{"line":1661,"offset":287521,"length":184,"previous":"M16-GAP-01661","next":"M16-GAP-01663"},"M16-GAP-01663":{"line":1662,"offset":287705,"length":184,"previous":"M16-GAP-01662","next":"M16-GAP-01664"},"M16-GAP-01664":{"line":1663,"offset":287889,"length":182,"previous":"M16-GAP-01663","next":"M16-GAP-01665"},"M16-GAP-01665":{"line":1664,"offset":288071,"length":175,"previous":"M16-GAP-01664","next":"M16-GAP-01666"},"M16-GAP-01666":{"line":1665,"offset":288246,"length":182,"previous":"M16-GAP-01665","next":"M16-GAP-01667"},"M16-GAP-01667":{"line":1666,"offset":288428,"length":187,"previous":"M16-GAP-01666","next":"M16-GAP-01668"},"M16-GAP-01668":{"line":1667,"offset":288615,"length":184,"previous":"M16-GAP-01667","next":"M16-GAP-01669"},"M16-GAP-01669":{"line":1668,"offset":288799,"length":182,"previous":"M16-GAP-01668","next":"M16-GAP-01670"},"M16-GAP-01670":{"line":1669,"offset":288981,"length":190,"previous":"M16-GAP-01669","next":"M16-GAP-01671"},"M16-GAP-01671":{"line":1670,"offset":289171,"length":188,"previous":"M16-GAP-01670","next":"M16-GAP-01672"},"M16-GAP-01672":{"line":1671,"offset":289359,"length":179,"previous":"M16-GAP-01671","next":"M16-GAP-01673"},"M16-GAP-01673":{"line":1672,"offset":289538,"length":178,"previous":"M16-GAP-01672","next":"M16-GAP-01674"},"M16-GAP-01674":{"line":1673,"offset":289716,"length":175,"previous":"M16-GAP-01673","next":"M16-GAP-01675"},"M16-GAP-01675":{"line":1674,"offset":289891,"length":174,"previous":"M16-GAP-01674","next":"M16-GAP-01676"},"M16-GAP-01676":{"line":1675,"offset":290065,"length":187,"previous":"M16-GAP-01675","next":"M16-GAP-01677"},"M16-GAP-01677":{"line":1676,"offset":290252,"length":185,"previous":"M16-GAP-01676","next":"M16-GAP-01678"},"M16-GAP-01678":{"line":1677,"offset":290437,"length":175,"previous":"M16-GAP-01677","next":"M16-GAP-01679"},"M16-GAP-01679":{"line":1678,"offset":290612,"length":182,"previous":"M16-GAP-01678","next":"M16-GAP-01680"},"M16-GAP-01680":{"line":1679,"offset":290794,"length":180,"previous":"M16-GAP-01679","next":"M16-GAP-01681"},"M16-GAP-01681":{"line":1680,"offset":290974,"length":174,"previous":"M16-GAP-01680","next":"M16-GAP-01682"},"M16-GAP-01682":{"line":1681,"offset":291148,"length":174,"previous":"M16-GAP-01681","next":"M16-GAP-01683"},"M16-GAP-01683":{"line":1682,"offset":291322,"length":166,"previous":"M16-GAP-01682","next":"M16-GAP-01684"},"M16-GAP-01684":{"line":1683,"offset":291488,"length":180,"previous":"M16-GAP-01683","next":"M16-GAP-01685"},"M16-GAP-01685":{"line":1684,"offset":291668,"length":183,"previous":"M16-GAP-01684","next":"M16-GAP-01686"},"M16-GAP-01686":{"line":1685,"offset":291851,"length":175,"previous":"M16-GAP-01685","next":"M16-GAP-01687"},"M16-GAP-01687":{"line":1686,"offset":292026,"length":164,"previous":"M16-GAP-01686","next":"M16-GAP-01688"},"M16-GAP-01688":{"line":1687,"offset":292190,"length":176,"previous":"M16-GAP-01687","next":"M16-GAP-01689"},"M16-GAP-01689":{"line":1688,"offset":292366,"length":167,"previous":"M16-GAP-01688","next":"M16-GAP-01690"},"M16-GAP-01690":{"line":1689,"offset":292533,"length":169,"previous":"M16-GAP-01689","next":"M16-GAP-01691"},"M16-GAP-01691":{"line":1690,"offset":292702,"length":178,"previous":"M16-GAP-01690","next":"M16-GAP-01692"},"M16-GAP-01692":{"line":1691,"offset":292880,"length":172,"previous":"M16-GAP-01691","next":"M16-GAP-01693"},"M16-GAP-01693":{"line":1692,"offset":293052,"length":168,"previous":"M16-GAP-01692","next":"M16-GAP-01694"},"M16-GAP-01694":{"line":1693,"offset":293220,"length":168,"previous":"M16-GAP-01693","next":"M16-GAP-01695"},"M16-GAP-01695":{"line":1694,"offset":293388,"length":173,"previous":"M16-GAP-01694","next":"M16-GAP-01696"},"M16-GAP-01696":{"line":1695,"offset":293561,"length":174,"previous":"M16-GAP-01695","next":"M16-GAP-01697"},"M16-GAP-01697":{"line":1696,"offset":293735,"length":174,"previous":"M16-GAP-01696","next":"M16-GAP-01698"},"M16-GAP-01698":{"line":1697,"offset":293909,"length":171,"previous":"M16-GAP-01697","next":"M16-GAP-01699"},"M16-GAP-01699":{"line":1698,"offset":294080,"length":182,"previous":"M16-GAP-01698","next":"M16-GAP-01700"},"M16-GAP-01700":{"line":1699,"offset":294262,"length":185,"previous":"M16-GAP-01699","next":"M16-GAP-01701"},"M16-GAP-01701":{"line":1700,"offset":294447,"length":173,"previous":"M16-GAP-01700","next":"M16-GAP-01702"},"M16-GAP-01702":{"line":1701,"offset":294620,"length":172,"previous":"M16-GAP-01701","next":"M16-GAP-01703"},"M16-GAP-01703":{"line":1702,"offset":294792,"length":181,"previous":"M16-GAP-01702","next":"M16-GAP-01704"},"M16-GAP-01704":{"line":1703,"offset":294973,"length":187,"previous":"M16-GAP-01703","next":"M16-GAP-01705"},"M16-GAP-01705":{"line":1704,"offset":295160,"length":194,"previous":"M16-GAP-01704","next":"M16-GAP-01706"},"M16-GAP-01706":{"line":1705,"offset":295354,"length":173,"previous":"M16-GAP-01705","next":"M16-GAP-01707"},"M16-GAP-01707":{"line":1706,"offset":295527,"length":178,"previous":"M16-GAP-01706","next":"M16-GAP-01708"},"M16-GAP-01708":{"line":1707,"offset":295705,"length":176,"previous":"M16-GAP-01707","next":"M16-GAP-01709"},"M16-GAP-01709":{"line":1708,"offset":295881,"length":169,"previous":"M16-GAP-01708","next":"M16-GAP-01710"},"M16-GAP-01710":{"line":1709,"offset":296050,"length":174,"previous":"M16-GAP-01709","next":"M16-GAP-01711"},"M16-GAP-01711":{"line":1710,"offset":296224,"length":173,"previous":"M16-GAP-01710","next":"M16-GAP-01712"},"M16-GAP-01712":{"line":1711,"offset":296397,"length":172,"previous":"M16-GAP-01711","next":"M16-GAP-01713"},"M16-GAP-01713":{"line":1712,"offset":296569,"length":171,"previous":"M16-GAP-01712","next":"M16-GAP-01714"},"M16-GAP-01714":{"line":1713,"offset":296740,"length":170,"previous":"M16-GAP-01713","next":"M16-GAP-01715"},"M16-GAP-01715":{"line":1714,"offset":296910,"length":175,"previous":"M16-GAP-01714","next":"M16-GAP-01716"},"M16-GAP-01716":{"line":1715,"offset":297085,"length":171,"previous":"M16-GAP-01715","next":"M16-GAP-01717"},"M16-GAP-01717":{"line":1716,"offset":297256,"length":170,"previous":"M16-GAP-01716","next":"M16-GAP-01718"},"M16-GAP-01718":{"line":1717,"offset":297426,"length":170,"previous":"M16-GAP-01717","next":"M16-GAP-01719"},"M16-GAP-01719":{"line":1718,"offset":297596,"length":171,"previous":"M16-GAP-01718","next":"M16-GAP-01720"},"M16-GAP-01720":{"line":1719,"offset":297767,"length":171,"previous":"M16-GAP-01719","next":"M16-GAP-01721"},"M16-GAP-01721":{"line":1720,"offset":297938,"length":174,"previous":"M16-GAP-01720","next":"M16-GAP-01722"},"M16-GAP-01722":{"line":1721,"offset":298112,"length":174,"previous":"M16-GAP-01721","next":"M16-GAP-01723"},"M16-GAP-01723":{"line":1722,"offset":298286,"length":172,"previous":"M16-GAP-01722","next":"M16-GAP-01724"},"M16-GAP-01724":{"line":1723,"offset":298458,"length":170,"previous":"M16-GAP-01723","next":"M16-GAP-01725"},"M16-GAP-01725":{"line":1724,"offset":298628,"length":171,"previous":"M16-GAP-01724","next":"M16-GAP-01726"},"M16-GAP-01726":{"line":1725,"offset":298799,"length":179,"previous":"M16-GAP-01725","next":"M16-GAP-01727"},"M16-GAP-01727":{"line":1726,"offset":298978,"length":174,"previous":"M16-GAP-01726","next":"M16-GAP-01728"},"M16-GAP-01728":{"line":1727,"offset":299152,"length":172,"previous":"M16-GAP-01727","next":"M16-GAP-01729"},"M16-GAP-01729":{"line":1728,"offset":299324,"length":173,"previous":"M16-GAP-01728","next":"M16-GAP-01730"},"M16-GAP-01730":{"line":1729,"offset":299497,"length":173,"previous":"M16-GAP-01729","next":"M16-GAP-01731"},"M16-GAP-01731":{"line":1730,"offset":299670,"length":175,"previous":"M16-GAP-01730","next":"M16-GAP-01732"},"M16-GAP-01732":{"line":1731,"offset":299845,"length":180,"previous":"M16-GAP-01731","next":"M16-GAP-01733"},"M16-GAP-01733":{"line":1732,"offset":300025,"length":173,"previous":"M16-GAP-01732","next":"M16-GAP-01734"},"M16-GAP-01734":{"line":1733,"offset":300198,"length":173,"previous":"M16-GAP-01733","next":"M16-GAP-01735"},"M16-GAP-01735":{"line":1734,"offset":300371,"length":173,"previous":"M16-GAP-01734","next":"M16-GAP-01736"},"M16-GAP-01736":{"line":1735,"offset":300544,"length":167,"previous":"M16-GAP-01735","next":"M16-GAP-01737"},"M16-GAP-01737":{"line":1736,"offset":300711,"length":166,"previous":"M16-GAP-01736","next":"M16-GAP-01738"},"M16-GAP-01738":{"line":1737,"offset":300877,"length":170,"previous":"M16-GAP-01737","next":"M16-GAP-01739"},"M16-GAP-01739":{"line":1738,"offset":301047,"length":180,"previous":"M16-GAP-01738","next":"M16-GAP-01740"},"M16-GAP-01740":{"line":1739,"offset":301227,"length":179,"previous":"M16-GAP-01739","next":"M16-GAP-01741"},"M16-GAP-01741":{"line":1740,"offset":301406,"length":173,"previous":"M16-GAP-01740","next":"M16-GAP-01742"},"M16-GAP-01742":{"line":1741,"offset":301579,"length":183,"previous":"M16-GAP-01741","next":"M16-GAP-01743"},"M16-GAP-01743":{"line":1742,"offset":301762,"length":172,"previous":"M16-GAP-01742","next":"M16-GAP-01744"},"M16-GAP-01744":{"line":1743,"offset":301934,"length":168,"previous":"M16-GAP-01743","next":"M16-GAP-01745"},"M16-GAP-01745":{"line":1744,"offset":302102,"length":173,"previous":"M16-GAP-01744","next":"M16-GAP-01746"},"M16-GAP-01746":{"line":1745,"offset":302275,"length":172,"previous":"M16-GAP-01745","next":"M16-GAP-01747"},"M16-GAP-01747":{"line":1746,"offset":302447,"length":175,"previous":"M16-GAP-01746","next":"M16-GAP-01748"},"M16-GAP-01748":{"line":1747,"offset":302622,"length":174,"previous":"M16-GAP-01747","next":"M16-GAP-01749"},"M16-GAP-01749":{"line":1748,"offset":302796,"length":178,"previous":"M16-GAP-01748","next":"M16-GAP-01750"},"M16-GAP-01750":{"line":1749,"offset":302974,"length":170,"previous":"M16-GAP-01749","next":"M16-GAP-01751"},"M16-GAP-01751":{"line":1750,"offset":303144,"length":169,"previous":"M16-GAP-01750","next":"M16-GAP-01752"},"M16-GAP-01752":{"line":1751,"offset":303313,"length":177,"previous":"M16-GAP-01751","next":"M16-GAP-01753"},"M16-GAP-01753":{"line":1752,"offset":303490,"length":172,"previous":"M16-GAP-01752","next":"M16-GAP-01754"},"M16-GAP-01754":{"line":1753,"offset":303662,"length":173,"previous":"M16-GAP-01753","next":"M16-GAP-01755"},"M16-GAP-01755":{"line":1754,"offset":303835,"length":173,"previous":"M16-GAP-01754","next":"M16-GAP-01756"},"M16-GAP-01756":{"line":1755,"offset":304008,"length":175,"previous":"M16-GAP-01755","next":"M16-GAP-01757"},"M16-GAP-01757":{"line":1756,"offset":304183,"length":180,"previous":"M16-GAP-01756","next":"M16-GAP-01758"},"M16-GAP-01758":{"line":1757,"offset":304363,"length":173,"previous":"M16-GAP-01757","next":"M16-GAP-01759"},"M16-GAP-01759":{"line":1758,"offset":304536,"length":173,"previous":"M16-GAP-01758","next":"M16-GAP-01760"},"M16-GAP-01760":{"line":1759,"offset":304709,"length":178,"previous":"M16-GAP-01759","next":"M16-GAP-01761"},"M16-GAP-01761":{"line":1760,"offset":304887,"length":189,"previous":"M16-GAP-01760","next":"M16-GAP-01762"},"M16-GAP-01762":{"line":1761,"offset":305076,"length":174,"previous":"M16-GAP-01761","next":"M16-GAP-01763"},"M16-GAP-01763":{"line":1762,"offset":305250,"length":181,"previous":"M16-GAP-01762","next":"M16-GAP-01764"},"M16-GAP-01764":{"line":1763,"offset":305431,"length":173,"previous":"M16-GAP-01763","next":"M16-GAP-01765"},"M16-GAP-01765":{"line":1764,"offset":305604,"length":176,"previous":"M16-GAP-01764","next":"M16-GAP-01766"},"M16-GAP-01766":{"line":1765,"offset":305780,"length":176,"previous":"M16-GAP-01765","next":"M16-GAP-01767"},"M16-GAP-01767":{"line":1766,"offset":305956,"length":173,"previous":"M16-GAP-01766","next":"M16-GAP-01768"},"M16-GAP-01768":{"line":1767,"offset":306129,"length":176,"previous":"M16-GAP-01767","next":"M16-GAP-01769"},"M16-GAP-01769":{"line":1768,"offset":306305,"length":169,"previous":"M16-GAP-01768","next":"M16-GAP-01770"},"M16-GAP-01770":{"line":1769,"offset":306474,"length":176,"previous":"M16-GAP-01769","next":"M16-GAP-01771"},"M16-GAP-01771":{"line":1770,"offset":306650,"length":174,"previous":"M16-GAP-01770","next":"M16-GAP-01772"},"M16-GAP-01772":{"line":1771,"offset":306824,"length":174,"previous":"M16-GAP-01771","next":"M16-GAP-01773"},"M16-GAP-01773":{"line":1772,"offset":306998,"length":174,"previous":"M16-GAP-01772","next":"M16-GAP-01774"},"M16-GAP-01774":{"line":1773,"offset":307172,"length":172,"previous":"M16-GAP-01773","next":"M16-GAP-01775"},"M16-GAP-01775":{"line":1774,"offset":307344,"length":169,"previous":"M16-GAP-01774","next":"M16-GAP-01776"},"M16-GAP-01776":{"line":1775,"offset":307513,"length":176,"previous":"M16-GAP-01775","next":"M16-GAP-01777"},"M16-GAP-01777":{"line":1776,"offset":307689,"length":170,"previous":"M16-GAP-01776","next":"M16-GAP-01778"},"M16-GAP-01778":{"line":1777,"offset":307859,"length":176,"previous":"M16-GAP-01777","next":"M16-GAP-01779"},"M16-GAP-01779":{"line":1778,"offset":308035,"length":167,"previous":"M16-GAP-01778","next":"M16-GAP-01780"},"M16-GAP-01780":{"line":1779,"offset":308202,"length":171,"previous":"M16-GAP-01779","next":"M16-GAP-01781"},"M16-GAP-01781":{"line":1780,"offset":308373,"length":177,"previous":"M16-GAP-01780","next":"M16-GAP-01782"},"M16-GAP-01782":{"line":1781,"offset":308550,"length":168,"previous":"M16-GAP-01781","next":"M16-GAP-01783"},"M16-GAP-01783":{"line":1782,"offset":308718,"length":174,"previous":"M16-GAP-01782","next":"M16-GAP-01784"},"M16-GAP-01784":{"line":1783,"offset":308892,"length":166,"previous":"M16-GAP-01783","next":"M16-GAP-01785"},"M16-GAP-01785":{"line":1784,"offset":309058,"length":165,"previous":"M16-GAP-01784","next":"M16-GAP-01786"},"M16-GAP-01786":{"line":1785,"offset":309223,"length":168,"previous":"M16-GAP-01785","next":"M16-GAP-01787"},"M16-GAP-01787":{"line":1786,"offset":309391,"length":167,"previous":"M16-GAP-01786","next":"M16-GAP-01788"},"M16-GAP-01788":{"line":1787,"offset":309558,"length":168,"previous":"M16-GAP-01787","next":"M16-GAP-01789"},"M16-GAP-01789":{"line":1788,"offset":309726,"length":171,"previous":"M16-GAP-01788","next":"M16-GAP-01790"},"M16-GAP-01790":{"line":1789,"offset":309897,"length":169,"previous":"M16-GAP-01789","next":"M16-GAP-01791"},"M16-GAP-01791":{"line":1790,"offset":310066,"length":177,"previous":"M16-GAP-01790","next":"M16-GAP-01792"},"M16-GAP-01792":{"line":1791,"offset":310243,"length":163,"previous":"M16-GAP-01791","next":"M16-GAP-01793"},"M16-GAP-01793":{"line":1792,"offset":310406,"length":162,"previous":"M16-GAP-01792","next":"M16-GAP-01794"},"M16-GAP-01794":{"line":1793,"offset":310568,"length":163,"previous":"M16-GAP-01793","next":"M16-GAP-01795"},"M16-GAP-01795":{"line":1794,"offset":310731,"length":170,"previous":"M16-GAP-01794","next":"M16-GAP-01796"},"M16-GAP-01796":{"line":1795,"offset":310901,"length":172,"previous":"M16-GAP-01795","next":"M16-GAP-01797"},"M16-GAP-01797":{"line":1796,"offset":311073,"length":181,"previous":"M16-GAP-01796","next":"M16-GAP-01798"},"M16-GAP-01798":{"line":1797,"offset":311254,"length":166,"previous":"M16-GAP-01797","next":"M16-GAP-01799"},"M16-GAP-01799":{"line":1798,"offset":311420,"length":175,"previous":"M16-GAP-01798","next":"M16-GAP-01800"},"M16-GAP-01800":{"line":1799,"offset":311595,"length":185,"previous":"M16-GAP-01799","next":"M16-GAP-01801"},"M16-GAP-01801":{"line":1800,"offset":311780,"length":172,"previous":"M16-GAP-01800","next":"M16-GAP-01802"},"M16-GAP-01802":{"line":1801,"offset":311952,"length":177,"previous":"M16-GAP-01801","next":"M16-GAP-01803"},"M16-GAP-01803":{"line":1802,"offset":312129,"length":175,"previous":"M16-GAP-01802","next":"M16-GAP-01804"},"M16-GAP-01804":{"line":1803,"offset":312304,"length":175,"previous":"M16-GAP-01803","next":"M16-GAP-01805"},"M16-GAP-01805":{"line":1804,"offset":312479,"length":174,"previous":"M16-GAP-01804","next":"M16-GAP-01806"},"M16-GAP-01806":{"line":1805,"offset":312653,"length":172,"previous":"M16-GAP-01805","next":"M16-GAP-01807"},"M16-GAP-01807":{"line":1806,"offset":312825,"length":184,"previous":"M16-GAP-01806","next":"M16-GAP-01808"},"M16-GAP-01808":{"line":1807,"offset":313009,"length":164,"previous":"M16-GAP-01807","next":"M16-GAP-01809"},"M16-GAP-01809":{"line":1808,"offset":313173,"length":166,"previous":"M16-GAP-01808","next":"M16-GAP-01810"},"M16-GAP-01810":{"line":1809,"offset":313339,"length":163,"previous":"M16-GAP-01809","next":"M16-GAP-01811"},"M16-GAP-01811":{"line":1810,"offset":313502,"length":170,"previous":"M16-GAP-01810","next":"M16-GAP-01812"},"M16-GAP-01812":{"line":1811,"offset":313672,"length":180,"previous":"M16-GAP-01811","next":"M16-GAP-01813"},"M16-GAP-01813":{"line":1812,"offset":313852,"length":186,"previous":"M16-GAP-01812","next":"M16-GAP-01814"},"M16-GAP-01814":{"line":1813,"offset":314038,"length":165,"previous":"M16-GAP-01813","next":"M16-GAP-01815"},"M16-GAP-01815":{"line":1814,"offset":314203,"length":174,"previous":"M16-GAP-01814","next":"M16-GAP-01816"},"M16-GAP-01816":{"line":1815,"offset":314377,"length":166,"previous":"M16-GAP-01815","next":"M16-GAP-01817"},"M16-GAP-01817":{"line":1816,"offset":314543,"length":170,"previous":"M16-GAP-01816","next":"M16-GAP-01818"},"M16-GAP-01818":{"line":1817,"offset":314713,"length":171,"previous":"M16-GAP-01817","next":"M16-GAP-01819"},"M16-GAP-01819":{"line":1818,"offset":314884,"length":173,"previous":"M16-GAP-01818","next":"M16-GAP-01820"},"M16-GAP-01820":{"line":1819,"offset":315057,"length":178,"previous":"M16-GAP-01819","next":"M16-GAP-01821"},"M16-GAP-01821":{"line":1820,"offset":315235,"length":171,"previous":"M16-GAP-01820","next":"M16-GAP-01822"},"M16-GAP-01822":{"line":1821,"offset":315406,"length":173,"previous":"M16-GAP-01821","next":"M16-GAP-01823"},"M16-GAP-01823":{"line":1822,"offset":315579,"length":172,"previous":"M16-GAP-01822","next":"M16-GAP-01824"},"M16-GAP-01824":{"line":1823,"offset":315751,"length":171,"previous":"M16-GAP-01823","next":"M16-GAP-01825"},"M16-GAP-01825":{"line":1824,"offset":315922,"length":169,"previous":"M16-GAP-01824","next":"M16-GAP-01826"},"M16-GAP-01826":{"line":1825,"offset":316091,"length":169,"previous":"M16-GAP-01825","next":"M16-GAP-01827"},"M16-GAP-01827":{"line":1826,"offset":316260,"length":176,"previous":"M16-GAP-01826","next":"M16-GAP-01828"},"M16-GAP-01828":{"line":1827,"offset":316436,"length":174,"previous":"M16-GAP-01827","next":"M16-GAP-01829"},"M16-GAP-01829":{"line":1828,"offset":316610,"length":173,"previous":"M16-GAP-01828","next":"M16-GAP-01830"},"M16-GAP-01830":{"line":1829,"offset":316783,"length":172,"previous":"M16-GAP-01829","next":"M16-GAP-01831"},"M16-GAP-01831":{"line":1830,"offset":316955,"length":170,"previous":"M16-GAP-01830","next":"M16-GAP-01832"},"M16-GAP-01832":{"line":1831,"offset":317125,"length":175,"previous":"M16-GAP-01831","next":"M16-GAP-01833"},"M16-GAP-01833":{"line":1832,"offset":317300,"length":168,"previous":"M16-GAP-01832","next":"M16-GAP-01834"},"M16-GAP-01834":{"line":1833,"offset":317468,"length":171,"previous":"M16-GAP-01833","next":"M16-GAP-01835"},"M16-GAP-01835":{"line":1834,"offset":317639,"length":176,"previous":"M16-GAP-01834","next":"M16-GAP-01836"},"M16-GAP-01836":{"line":1835,"offset":317815,"length":172,"previous":"M16-GAP-01835","next":"M16-GAP-01837"},"M16-GAP-01837":{"line":1836,"offset":317987,"length":175,"previous":"M16-GAP-01836","next":"M16-GAP-01838"},"M16-GAP-01838":{"line":1837,"offset":318162,"length":170,"previous":"M16-GAP-01837","next":"M16-GAP-01839"},"M16-GAP-01839":{"line":1838,"offset":318332,"length":170,"previous":"M16-GAP-01838","next":"M16-GAP-01840"},"M16-GAP-01840":{"line":1839,"offset":318502,"length":170,"previous":"M16-GAP-01839","next":"M16-GAP-01841"},"M16-GAP-01841":{"line":1840,"offset":318672,"length":173,"previous":"M16-GAP-01840","next":"M16-GAP-01842"},"M16-GAP-01842":{"line":1841,"offset":318845,"length":171,"previous":"M16-GAP-01841","next":"M16-GAP-01843"},"M16-GAP-01843":{"line":1842,"offset":319016,"length":165,"previous":"M16-GAP-01842","next":"M16-GAP-01844"},"M16-GAP-01844":{"line":1843,"offset":319181,"length":170,"previous":"M16-GAP-01843","next":"M16-GAP-01845"},"M16-GAP-01845":{"line":1844,"offset":319351,"length":183,"previous":"M16-GAP-01844","next":"M16-GAP-01846"},"M16-GAP-01846":{"line":1845,"offset":319534,"length":173,"previous":"M16-GAP-01845","next":"M16-GAP-01847"},"M16-GAP-01847":{"line":1846,"offset":319707,"length":172,"previous":"M16-GAP-01846","next":"M16-GAP-01848"},"M16-GAP-01848":{"line":1847,"offset":319879,"length":160,"previous":"M16-GAP-01847","next":"M16-GAP-01849"},"M16-GAP-01849":{"line":1848,"offset":320039,"length":166,"previous":"M16-GAP-01848","next":"M16-GAP-01850"},"M16-GAP-01850":{"line":1849,"offset":320205,"length":160,"previous":"M16-GAP-01849","next":"M16-GAP-01851"},"M16-GAP-01851":{"line":1850,"offset":320365,"length":162,"previous":"M16-GAP-01850","next":"M16-GAP-01852"},"M16-GAP-01852":{"line":1851,"offset":320527,"length":164,"previous":"M16-GAP-01851","next":"M16-GAP-01853"},"M16-GAP-01853":{"line":1852,"offset":320691,"length":165,"previous":"M16-GAP-01852","next":"M16-GAP-01854"},"M16-GAP-01854":{"line":1853,"offset":320856,"length":161,"previous":"M16-GAP-01853","next":"M16-GAP-01855"},"M16-GAP-01855":{"line":1854,"offset":321017,"length":171,"previous":"M16-GAP-01854","next":"M16-GAP-01856"},"M16-GAP-01856":{"line":1855,"offset":321188,"length":167,"previous":"M16-GAP-01855","next":"M16-GAP-01857"},"M16-GAP-01857":{"line":1856,"offset":321355,"length":174,"previous":"M16-GAP-01856","next":"M16-GAP-01858"},"M16-GAP-01858":{"line":1857,"offset":321529,"length":168,"previous":"M16-GAP-01857","next":"M16-GAP-01859"},"M16-GAP-01859":{"line":1858,"offset":321697,"length":165,"previous":"M16-GAP-01858","next":"M16-GAP-01860"},"M16-GAP-01860":{"line":1859,"offset":321862,"length":160,"previous":"M16-GAP-01859","next":"M16-GAP-01861"},"M16-GAP-01861":{"line":1860,"offset":322022,"length":172,"previous":"M16-GAP-01860","next":"M16-GAP-01862"},"M16-GAP-01862":{"line":1861,"offset":322194,"length":161,"previous":"M16-GAP-01861","next":"M16-GAP-01863"},"M16-GAP-01863":{"line":1862,"offset":322355,"length":162,"previous":"M16-GAP-01862","next":"M16-GAP-01864"},"M16-GAP-01864":{"line":1863,"offset":322517,"length":165,"previous":"M16-GAP-01863","next":"M16-GAP-01865"},"M16-GAP-01865":{"line":1864,"offset":322682,"length":173,"previous":"M16-GAP-01864","next":"M16-GAP-01866"},"M16-GAP-01866":{"line":1865,"offset":322855,"length":167,"previous":"M16-GAP-01865","next":"M16-GAP-01867"},"M16-GAP-01867":{"line":1866,"offset":323022,"length":166,"previous":"M16-GAP-01866","next":"M16-GAP-01868"},"M16-GAP-01868":{"line":1867,"offset":323188,"length":180,"previous":"M16-GAP-01867","next":"M16-GAP-01869"},"M16-GAP-01869":{"line":1868,"offset":323368,"length":170,"previous":"M16-GAP-01868","next":"M16-GAP-01870"},"M16-GAP-01870":{"line":1869,"offset":323538,"length":172,"previous":"M16-GAP-01869","next":"M16-GAP-01871"},"M16-GAP-01871":{"line":1870,"offset":323710,"length":169,"previous":"M16-GAP-01870","next":"M16-GAP-01872"},"M16-GAP-01872":{"line":1871,"offset":323879,"length":174,"previous":"M16-GAP-01871","next":"M16-GAP-01873"},"M16-GAP-01873":{"line":1872,"offset":324053,"length":169,"previous":"M16-GAP-01872","next":"M16-GAP-01874"},"M16-GAP-01874":{"line":1873,"offset":324222,"length":169,"previous":"M16-GAP-01873","next":"M16-GAP-01875"},"M16-GAP-01875":{"line":1874,"offset":324391,"length":173,"previous":"M16-GAP-01874","next":"M16-GAP-01876"},"M16-GAP-01876":{"line":1875,"offset":324564,"length":184,"previous":"M16-GAP-01875","next":"M16-GAP-01877"},"M16-GAP-01877":{"line":1876,"offset":324748,"length":176,"previous":"M16-GAP-01876","next":"M16-GAP-01878"},"M16-GAP-01878":{"line":1877,"offset":324924,"length":174,"previous":"M16-GAP-01877","next":"M16-GAP-01879"},"M16-GAP-01879":{"line":1878,"offset":325098,"length":180,"previous":"M16-GAP-01878","next":"M16-GAP-01880"},"M16-GAP-01880":{"line":1879,"offset":325278,"length":178,"previous":"M16-GAP-01879","next":"M16-GAP-01881"},"M16-GAP-01881":{"line":1880,"offset":325456,"length":174,"previous":"M16-GAP-01880","next":"M16-GAP-01882"},"M16-GAP-01882":{"line":1881,"offset":325630,"length":175,"previous":"M16-GAP-01881","next":"M16-GAP-01883"},"M16-GAP-01883":{"line":1882,"offset":325805,"length":176,"previous":"M16-GAP-01882","next":"M16-GAP-01884"},"M16-GAP-01884":{"line":1883,"offset":325981,"length":182,"previous":"M16-GAP-01883","next":"M16-GAP-01885"},"M16-GAP-01885":{"line":1884,"offset":326163,"length":176,"previous":"M16-GAP-01884","next":"M16-GAP-01886"},"M16-GAP-01886":{"line":1885,"offset":326339,"length":178,"previous":"M16-GAP-01885","next":"M16-GAP-01887"},"M16-GAP-01887":{"line":1886,"offset":326517,"length":172,"previous":"M16-GAP-01886","next":"M16-GAP-01888"},"M16-GAP-01888":{"line":1887,"offset":326689,"length":177,"previous":"M16-GAP-01887","next":"M16-GAP-01889"},"M16-GAP-01889":{"line":1888,"offset":326866,"length":178,"previous":"M16-GAP-01888","next":"M16-GAP-01890"},"M16-GAP-01890":{"line":1889,"offset":327044,"length":175,"previous":"M16-GAP-01889","next":"M16-GAP-01891"},"M16-GAP-01891":{"line":1890,"offset":327219,"length":171,"previous":"M16-GAP-01890","next":"M16-GAP-01892"},"M16-GAP-01892":{"line":1891,"offset":327390,"length":171,"previous":"M16-GAP-01891","next":"M16-GAP-01893"},"M16-GAP-01893":{"line":1892,"offset":327561,"length":175,"previous":"M16-GAP-01892","next":"M16-GAP-01894"},"M16-GAP-01894":{"line":1893,"offset":327736,"length":172,"previous":"M16-GAP-01893","next":"M16-GAP-01895"},"M16-GAP-01895":{"line":1894,"offset":327908,"length":176,"previous":"M16-GAP-01894","next":"M16-GAP-01896"},"M16-GAP-01896":{"line":1895,"offset":328084,"length":170,"previous":"M16-GAP-01895","next":"M16-GAP-01897"},"M16-GAP-01897":{"line":1896,"offset":328254,"length":182,"previous":"M16-GAP-01896","next":"M16-GAP-01898"},"M16-GAP-01898":{"line":1897,"offset":328436,"length":182,"previous":"M16-GAP-01897","next":"M16-GAP-01899"},"M16-GAP-01899":{"line":1898,"offset":328618,"length":176,"previous":"M16-GAP-01898","next":"M16-GAP-01900"},"M16-GAP-01900":{"line":1899,"offset":328794,"length":175,"previous":"M16-GAP-01899","next":"M16-GAP-01901"},"M16-GAP-01901":{"line":1900,"offset":328969,"length":175,"previous":"M16-GAP-01900","next":"M16-GAP-01902"},"M16-GAP-01902":{"line":1901,"offset":329144,"length":176,"previous":"M16-GAP-01901","next":"M16-GAP-01903"},"M16-GAP-01903":{"line":1902,"offset":329320,"length":176,"previous":"M16-GAP-01902","next":"M16-GAP-01904"},"M16-GAP-01904":{"line":1903,"offset":329496,"length":175,"previous":"M16-GAP-01903","next":"M16-GAP-01905"},"M16-GAP-01905":{"line":1904,"offset":329671,"length":173,"previous":"M16-GAP-01904","next":"M16-GAP-01906"},"M16-GAP-01906":{"line":1905,"offset":329844,"length":183,"previous":"M16-GAP-01905","next":"M16-GAP-01907"},"M16-GAP-01907":{"line":1906,"offset":330027,"length":180,"previous":"M16-GAP-01906","next":"M16-GAP-01908"},"M16-GAP-01908":{"line":1907,"offset":330207,"length":183,"previous":"M16-GAP-01907","next":"M16-GAP-01909"},"M16-GAP-01909":{"line":1908,"offset":330390,"length":178,"previous":"M16-GAP-01908","next":"M16-GAP-01910"},"M16-GAP-01910":{"line":1909,"offset":330568,"length":180,"previous":"M16-GAP-01909","next":"M16-GAP-01911"},"M16-GAP-01911":{"line":1910,"offset":330748,"length":183,"previous":"M16-GAP-01910","next":"M16-GAP-01912"},"M16-GAP-01912":{"line":1911,"offset":330931,"length":175,"previous":"M16-GAP-01911","next":"M16-GAP-01913"},"M16-GAP-01913":{"line":1912,"offset":331106,"length":172,"previous":"M16-GAP-01912","next":"M16-GAP-01914"},"M16-GAP-01914":{"line":1913,"offset":331278,"length":181,"previous":"M16-GAP-01913","next":"M16-GAP-01915"},"M16-GAP-01915":{"line":1914,"offset":331459,"length":184,"previous":"M16-GAP-01914","next":"M16-GAP-01916"},"M16-GAP-01916":{"line":1915,"offset":331643,"length":181,"previous":"M16-GAP-01915","next":"M16-GAP-01917"},"M16-GAP-01917":{"line":1916,"offset":331824,"length":181,"previous":"M16-GAP-01916","next":"M16-GAP-01918"},"M16-GAP-01918":{"line":1917,"offset":332005,"length":179,"previous":"M16-GAP-01917","next":"M16-GAP-01919"},"M16-GAP-01919":{"line":1918,"offset":332184,"length":179,"previous":"M16-GAP-01918","next":"M16-GAP-01920"},"M16-GAP-01920":{"line":1919,"offset":332363,"length":179,"previous":"M16-GAP-01919","next":"M16-GAP-01921"},"M16-GAP-01921":{"line":1920,"offset":332542,"length":177,"previous":"M16-GAP-01920","next":"M16-GAP-01922"},"M16-GAP-01922":{"line":1921,"offset":332719,"length":174,"previous":"M16-GAP-01921","next":"M16-GAP-01923"},"M16-GAP-01923":{"line":1922,"offset":332893,"length":177,"previous":"M16-GAP-01922","next":"M16-GAP-01924"},"M16-GAP-01924":{"line":1923,"offset":333070,"length":178,"previous":"M16-GAP-01923","next":"M16-GAP-01925"},"M16-GAP-01925":{"line":1924,"offset":333248,"length":177,"previous":"M16-GAP-01924","next":"M16-GAP-01926"},"M16-GAP-01926":{"line":1925,"offset":333425,"length":182,"previous":"M16-GAP-01925","next":"M16-GAP-01927"},"M16-GAP-01927":{"line":1926,"offset":333607,"length":183,"previous":"M16-GAP-01926","next":"M16-GAP-01928"},"M16-GAP-01928":{"line":1927,"offset":333790,"length":186,"previous":"M16-GAP-01927","next":"M16-GAP-01929"},"M16-GAP-01929":{"line":1928,"offset":333976,"length":175,"previous":"M16-GAP-01928","next":"M16-GAP-01930"},"M16-GAP-01930":{"line":1929,"offset":334151,"length":188,"previous":"M16-GAP-01929","next":"M16-GAP-01931"},"M16-GAP-01931":{"line":1930,"offset":334339,"length":182,"previous":"M16-GAP-01930","next":"M16-GAP-01932"},"M16-GAP-01932":{"line":1931,"offset":334521,"length":178,"previous":"M16-GAP-01931","next":"M16-GAP-01933"},"M16-GAP-01933":{"line":1932,"offset":334699,"length":184,"previous":"M16-GAP-01932","next":"M16-GAP-01934"},"M16-GAP-01934":{"line":1933,"offset":334883,"length":176,"previous":"M16-GAP-01933","next":"M16-GAP-01935"},"M16-GAP-01935":{"line":1934,"offset":335059,"length":180,"previous":"M16-GAP-01934","next":"M16-GAP-01936"},"M16-GAP-01936":{"line":1935,"offset":335239,"length":162,"previous":"M16-GAP-01935","next":"M16-GAP-01937"},"M16-GAP-01937":{"line":1936,"offset":335401,"length":163,"previous":"M16-GAP-01936","next":"M16-GAP-01938"},"M16-GAP-01938":{"line":1937,"offset":335564,"length":167,"previous":"M16-GAP-01937","next":"M16-GAP-01939"},"M16-GAP-01939":{"line":1938,"offset":335731,"length":174,"previous":"M16-GAP-01938","next":"M16-GAP-01940"},"M16-GAP-01940":{"line":1939,"offset":335905,"length":168,"previous":"M16-GAP-01939","next":"M16-GAP-01941"},"M16-GAP-01941":{"line":1940,"offset":336073,"length":172,"previous":"M16-GAP-01940","next":"M16-GAP-01942"},"M16-GAP-01942":{"line":1941,"offset":336245,"length":165,"previous":"M16-GAP-01941","next":"M16-GAP-01943"},"M16-GAP-01943":{"line":1942,"offset":336410,"length":177,"previous":"M16-GAP-01942","next":"M16-GAP-01944"},"M16-GAP-01944":{"line":1943,"offset":336587,"length":199,"previous":"M16-GAP-01943","next":"M16-GAP-01945"},"M16-GAP-01945":{"line":1944,"offset":336786,"length":186,"previous":"M16-GAP-01944","next":"M16-GAP-01946"},"M16-GAP-01946":{"line":1945,"offset":336972,"length":187,"previous":"M16-GAP-01945","next":"M16-GAP-01947"},"M16-GAP-01947":{"line":1946,"offset":337159,"length":184,"previous":"M16-GAP-01946","next":"M16-GAP-01948"},"M16-GAP-01948":{"line":1947,"offset":337343,"length":193,"previous":"M16-GAP-01947","next":"M16-GAP-01949"},"M16-GAP-01949":{"line":1948,"offset":337536,"length":185,"previous":"M16-GAP-01948","next":"M16-GAP-01950"},"M16-GAP-01950":{"line":1949,"offset":337721,"length":180,"previous":"M16-GAP-01949","next":"M16-GAP-01951"},"M16-GAP-01951":{"line":1950,"offset":337901,"length":164,"previous":"M16-GAP-01950","next":"M16-GAP-01952"},"M16-GAP-01952":{"line":1951,"offset":338065,"length":176,"previous":"M16-GAP-01951","next":"M16-GAP-01953"},"M16-GAP-01953":{"line":1952,"offset":338241,"length":168,"previous":"M16-GAP-01952","next":"M16-GAP-01954"},"M16-GAP-01954":{"line":1953,"offset":338409,"length":164,"previous":"M16-GAP-01953","next":"M16-GAP-01955"},"M16-GAP-01955":{"line":1954,"offset":338573,"length":178,"previous":"M16-GAP-01954","next":"M16-GAP-01956"},"M16-GAP-01956":{"line":1955,"offset":338751,"length":173,"previous":"M16-GAP-01955","next":"M16-GAP-01957"},"M16-GAP-01957":{"line":1956,"offset":338924,"length":169,"previous":"M16-GAP-01956","next":"M16-GAP-01958"},"M16-GAP-01958":{"line":1957,"offset":339093,"length":167,"previous":"M16-GAP-01957","next":"M16-GAP-01959"},"M16-GAP-01959":{"line":1958,"offset":339260,"length":178,"previous":"M16-GAP-01958","next":"M16-GAP-01960"},"M16-GAP-01960":{"line":1959,"offset":339438,"length":168,"previous":"M16-GAP-01959","next":"M16-GAP-01961"},"M16-GAP-01961":{"line":1960,"offset":339606,"length":175,"previous":"M16-GAP-01960","next":"M16-GAP-01962"},"M16-GAP-01962":{"line":1961,"offset":339781,"length":178,"previous":"M16-GAP-01961","next":"M16-GAP-01963"},"M16-GAP-01963":{"line":1962,"offset":339959,"length":175,"previous":"M16-GAP-01962","next":"M16-GAP-01964"},"M16-GAP-01964":{"line":1963,"offset":340134,"length":171,"previous":"M16-GAP-01963","next":"M16-GAP-01965"},"M16-GAP-01965":{"line":1964,"offset":340305,"length":174,"previous":"M16-GAP-01964","next":"M16-GAP-01966"},"M16-GAP-01966":{"line":1965,"offset":340479,"length":181,"previous":"M16-GAP-01965","next":"M16-GAP-01967"},"M16-GAP-01967":{"line":1966,"offset":340660,"length":172,"previous":"M16-GAP-01966","next":"M16-GAP-01968"},"M16-GAP-01968":{"line":1967,"offset":340832,"length":175,"previous":"M16-GAP-01967","next":"M16-GAP-01969"},"M16-GAP-01969":{"line":1968,"offset":341007,"length":173,"previous":"M16-GAP-01968","next":"M16-GAP-01970"},"M16-GAP-01970":{"line":1969,"offset":341180,"length":170,"previous":"M16-GAP-01969","next":"M16-GAP-01971"},"M16-GAP-01971":{"line":1970,"offset":341350,"length":173,"previous":"M16-GAP-01970","next":"M16-GAP-01972"},"M16-GAP-01972":{"line":1971,"offset":341523,"length":163,"previous":"M16-GAP-01971","next":"M16-GAP-01973"},"M16-GAP-01973":{"line":1972,"offset":341686,"length":173,"previous":"M16-GAP-01972","next":"M16-GAP-01974"},"M16-GAP-01974":{"line":1973,"offset":341859,"length":195,"previous":"M16-GAP-01973","next":"M16-GAP-01975"},"M16-GAP-01975":{"line":1974,"offset":342054,"length":195,"previous":"M16-GAP-01974","next":"M16-GAP-01976"},"M16-GAP-01976":{"line":1975,"offset":342249,"length":185,"previous":"M16-GAP-01975","next":"M16-GAP-01977"},"M16-GAP-01977":{"line":1976,"offset":342434,"length":185,"previous":"M16-GAP-01976","next":"M16-GAP-01978"},"M16-GAP-01978":{"line":1977,"offset":342619,"length":190,"previous":"M16-GAP-01977","next":"M16-GAP-01979"},"M16-GAP-01979":{"line":1978,"offset":342809,"length":188,"previous":"M16-GAP-01978","next":"M16-GAP-01980"},"M16-GAP-01980":{"line":1979,"offset":342997,"length":178,"previous":"M16-GAP-01979","next":"M16-GAP-01981"},"M16-GAP-01981":{"line":1980,"offset":343175,"length":179,"previous":"M16-GAP-01980","next":"M16-GAP-01982"},"M16-GAP-01982":{"line":1981,"offset":343354,"length":179,"previous":"M16-GAP-01981","next":"M16-GAP-01983"},"M16-GAP-01983":{"line":1982,"offset":343533,"length":180,"previous":"M16-GAP-01982","next":"M16-GAP-01984"},"M16-GAP-01984":{"line":1983,"offset":343713,"length":181,"previous":"M16-GAP-01983","next":"M16-GAP-01985"},"M16-GAP-01985":{"line":1984,"offset":343894,"length":180,"previous":"M16-GAP-01984","next":"M16-GAP-01986"},"M16-GAP-01986":{"line":1985,"offset":344074,"length":180,"previous":"M16-GAP-01985","next":"M16-GAP-01987"},"M16-GAP-01987":{"line":1986,"offset":344254,"length":180,"previous":"M16-GAP-01986","next":"M16-GAP-01988"},"M16-GAP-01988":{"line":1987,"offset":344434,"length":182,"previous":"M16-GAP-01987","next":"M16-GAP-01989"},"M16-GAP-01989":{"line":1988,"offset":344616,"length":177,"previous":"M16-GAP-01988","next":"M16-GAP-01990"},"M16-GAP-01990":{"line":1989,"offset":344793,"length":178,"previous":"M16-GAP-01989","next":"M16-GAP-01991"},"M16-GAP-01991":{"line":1990,"offset":344971,"length":178,"previous":"M16-GAP-01990","next":"M16-GAP-01992"},"M16-GAP-01992":{"line":1991,"offset":345149,"length":180,"previous":"M16-GAP-01991","next":"M16-GAP-01993"},"M16-GAP-01993":{"line":1992,"offset":345329,"length":189,"previous":"M16-GAP-01992","next":"M16-GAP-01994"},"M16-GAP-01994":{"line":1993,"offset":345518,"length":189,"previous":"M16-GAP-01993","next":"M16-GAP-01995"},"M16-GAP-01995":{"line":1994,"offset":345707,"length":184,"previous":"M16-GAP-01994","next":"M16-GAP-01996"},"M16-GAP-01996":{"line":1995,"offset":345891,"length":181,"previous":"M16-GAP-01995","next":"M16-GAP-01997"},"M16-GAP-01997":{"line":1996,"offset":346072,"length":184,"previous":"M16-GAP-01996","next":"M16-GAP-01998"},"M16-GAP-01998":{"line":1997,"offset":346256,"length":160,"previous":"M16-GAP-01997","next":"M16-GAP-01999"},"M16-GAP-01999":{"line":1998,"offset":346416,"length":170,"previous":"M16-GAP-01998","next":"M16-GAP-02000"},"M16-GAP-02000":{"line":1999,"offset":346586,"length":176,"previous":"M16-GAP-01999","next":"M16-GAP-02001"},"M16-GAP-02001":{"line":2000,"offset":346762,"length":172,"previous":"M16-GAP-02000","next":"M16-GAP-02002"},"M16-GAP-02002":{"line":2001,"offset":346934,"length":175,"previous":"M16-GAP-02001","next":"M16-GAP-02003"},"M16-GAP-02003":{"line":2002,"offset":347109,"length":171,"previous":"M16-GAP-02002","next":"M16-GAP-02004"},"M16-GAP-02004":{"line":2003,"offset":347280,"length":175,"previous":"M16-GAP-02003","next":"M16-GAP-02005"},"M16-GAP-02005":{"line":2004,"offset":347455,"length":182,"previous":"M16-GAP-02004","next":"M16-GAP-02006"},"M16-GAP-02006":{"line":2005,"offset":347637,"length":188,"previous":"M16-GAP-02005","next":"M16-GAP-02007"},"M16-GAP-02007":{"line":2006,"offset":347825,"length":174,"previous":"M16-GAP-02006","next":"M16-GAP-02008"},"M16-GAP-02008":{"line":2007,"offset":347999,"length":178,"previous":"M16-GAP-02007","next":"M16-GAP-02009"},"M16-GAP-02009":{"line":2008,"offset":348177,"length":185,"previous":"M16-GAP-02008","next":"M16-GAP-02010"},"M16-GAP-02010":{"line":2009,"offset":348362,"length":193,"previous":"M16-GAP-02009","next":"M16-GAP-02011"},"M16-GAP-02011":{"line":2010,"offset":348555,"length":168,"previous":"M16-GAP-02010","next":"M16-GAP-02012"},"M16-GAP-02012":{"line":2011,"offset":348723,"length":174,"previous":"M16-GAP-02011","next":"M16-GAP-02013"},"M16-GAP-02013":{"line":2012,"offset":348897,"length":173,"previous":"M16-GAP-02012","next":"M16-GAP-02014"},"M16-GAP-02014":{"line":2013,"offset":349070,"length":172,"previous":"M16-GAP-02013","next":"M16-GAP-02015"},"M16-GAP-02015":{"line":2014,"offset":349242,"length":172,"previous":"M16-GAP-02014","next":"M16-GAP-02016"},"M16-GAP-02016":{"line":2015,"offset":349414,"length":168,"previous":"M16-GAP-02015","next":"M16-GAP-02017"},"M16-GAP-02017":{"line":2016,"offset":349582,"length":168,"previous":"M16-GAP-02016","next":"M16-GAP-02018"},"M16-GAP-02018":{"line":2017,"offset":349750,"length":167,"previous":"M16-GAP-02017","next":"M16-GAP-02019"},"M16-GAP-02019":{"line":2018,"offset":349917,"length":167,"previous":"M16-GAP-02018","next":"M16-GAP-02020"},"M16-GAP-02020":{"line":2019,"offset":350084,"length":170,"previous":"M16-GAP-02019","next":"M16-GAP-02021"},"M16-GAP-02021":{"line":2020,"offset":350254,"length":168,"previous":"M16-GAP-02020","next":"M16-GAP-02022"},"M16-GAP-02022":{"line":2021,"offset":350422,"length":167,"previous":"M16-GAP-02021","next":"M16-GAP-02023"},"M16-GAP-02023":{"line":2022,"offset":350589,"length":174,"previous":"M16-GAP-02022","next":"M16-GAP-02024"},"M16-GAP-02024":{"line":2023,"offset":350763,"length":164,"previous":"M16-GAP-02023","next":"M16-GAP-02025"},"M16-GAP-02025":{"line":2024,"offset":350927,"length":177,"previous":"M16-GAP-02024","next":"M16-GAP-02026"},"M16-GAP-02026":{"line":2025,"offset":351104,"length":168,"previous":"M16-GAP-02025","next":"M16-GAP-02027"},"M16-GAP-02027":{"line":2026,"offset":351272,"length":168,"previous":"M16-GAP-02026","next":"M16-GAP-02028"},"M16-GAP-02028":{"line":2027,"offset":351440,"length":170,"previous":"M16-GAP-02027","next":"M16-GAP-02029"},"M16-GAP-02029":{"line":2028,"offset":351610,"length":177,"previous":"M16-GAP-02028","next":"M16-GAP-02030"},"M16-GAP-02030":{"line":2029,"offset":351787,"length":171,"previous":"M16-GAP-02029","next":"M16-GAP-02031"},"M16-GAP-02031":{"line":2030,"offset":351958,"length":171,"previous":"M16-GAP-02030","next":"M16-GAP-02032"},"M16-GAP-02032":{"line":2031,"offset":352129,"length":169,"previous":"M16-GAP-02031","next":"M16-GAP-02033"},"M16-GAP-02033":{"line":2032,"offset":352298,"length":161,"previous":"M16-GAP-02032","next":"M16-GAP-02034"},"M16-GAP-02034":{"line":2033,"offset":352459,"length":171,"previous":"M16-GAP-02033","next":"M16-GAP-02035"},"M16-GAP-02035":{"line":2034,"offset":352630,"length":167,"previous":"M16-GAP-02034","next":"M16-GAP-02036"},"M16-GAP-02036":{"line":2035,"offset":352797,"length":170,"previous":"M16-GAP-02035","next":"M16-GAP-02037"},"M16-GAP-02037":{"line":2036,"offset":352967,"length":177,"previous":"M16-GAP-02036","next":"M16-GAP-02038"},"M16-GAP-02038":{"line":2037,"offset":353144,"length":169,"previous":"M16-GAP-02037","next":"M16-GAP-02039"},"M16-GAP-02039":{"line":2038,"offset":353313,"length":173,"previous":"M16-GAP-02038","next":"M16-GAP-02040"},"M16-GAP-02040":{"line":2039,"offset":353486,"length":170,"previous":"M16-GAP-02039","next":"M16-GAP-02041"},"M16-GAP-02041":{"line":2040,"offset":353656,"length":171,"previous":"M16-GAP-02040","next":"M16-GAP-02042"},"M16-GAP-02042":{"line":2041,"offset":353827,"length":172,"previous":"M16-GAP-02041","next":"M16-GAP-02043"},"M16-GAP-02043":{"line":2042,"offset":353999,"length":169,"previous":"M16-GAP-02042","next":"M16-GAP-02044"},"M16-GAP-02044":{"line":2043,"offset":354168,"length":174,"previous":"M16-GAP-02043","next":"M16-GAP-02045"},"M16-GAP-02045":{"line":2044,"offset":354342,"length":168,"previous":"M16-GAP-02044","next":"M16-GAP-02046"},"M16-GAP-02046":{"line":2045,"offset":354510,"length":168,"previous":"M16-GAP-02045","next":"M16-GAP-02047"},"M16-GAP-02047":{"line":2046,"offset":354678,"length":173,"previous":"M16-GAP-02046","next":"M16-GAP-02048"},"M16-GAP-02048":{"line":2047,"offset":354851,"length":177,"previous":"M16-GAP-02047","next":"M16-GAP-02049"},"M16-GAP-02049":{"line":2048,"offset":355028,"length":181,"previous":"M16-GAP-02048","next":"M16-GAP-02050"},"M16-GAP-02050":{"line":2049,"offset":355209,"length":175,"previous":"M16-GAP-02049","next":"M16-GAP-02051"},"M16-GAP-02051":{"line":2050,"offset":355384,"length":167,"previous":"M16-GAP-02050","next":"M16-GAP-02052"},"M16-GAP-02052":{"line":2051,"offset":355551,"length":171,"previous":"M16-GAP-02051","next":"M16-GAP-02053"},"M16-GAP-02053":{"line":2052,"offset":355722,"length":173,"previous":"M16-GAP-02052","next":"M16-GAP-02054"},"M16-GAP-02054":{"line":2053,"offset":355895,"length":172,"previous":"M16-GAP-02053","next":"M16-GAP-02055"},"M16-GAP-02055":{"line":2054,"offset":356067,"length":173,"previous":"M16-GAP-02054","next":"M16-GAP-02056"},"M16-GAP-02056":{"line":2055,"offset":356240,"length":164,"previous":"M16-GAP-02055","next":"M16-GAP-02057"},"M16-GAP-02057":{"line":2056,"offset":356404,"length":170,"previous":"M16-GAP-02056","next":"M16-GAP-02058"},"M16-GAP-02058":{"line":2057,"offset":356574,"length":170,"previous":"M16-GAP-02057","next":"M16-GAP-02059"},"M16-GAP-02059":{"line":2058,"offset":356744,"length":170,"previous":"M16-GAP-02058","next":"M16-GAP-02060"},"M16-GAP-02060":{"line":2059,"offset":356914,"length":175,"previous":"M16-GAP-02059","next":"M16-GAP-02061"},"M16-GAP-02061":{"line":2060,"offset":357089,"length":181,"previous":"M16-GAP-02060","next":"M16-GAP-02062"},"M16-GAP-02062":{"line":2061,"offset":357270,"length":182,"previous":"M16-GAP-02061","next":"M16-GAP-02063"},"M16-GAP-02063":{"line":2062,"offset":357452,"length":164,"previous":"M16-GAP-02062","next":"M16-GAP-02064"},"M16-GAP-02064":{"line":2063,"offset":357616,"length":178,"previous":"M16-GAP-02063","next":"M16-GAP-02065"},"M16-GAP-02065":{"line":2064,"offset":357794,"length":184,"previous":"M16-GAP-02064","next":"M16-GAP-02066"},"M16-GAP-02066":{"line":2065,"offset":357978,"length":171,"previous":"M16-GAP-02065","next":"M16-GAP-02067"},"M16-GAP-02067":{"line":2066,"offset":358149,"length":174,"previous":"M16-GAP-02066","next":"M16-GAP-02068"},"M16-GAP-02068":{"line":2067,"offset":358323,"length":180,"previous":"M16-GAP-02067","next":"M16-GAP-02069"},"M16-GAP-02069":{"line":2068,"offset":358503,"length":179,"previous":"M16-GAP-02068","next":"M16-GAP-02070"},"M16-GAP-02070":{"line":2069,"offset":358682,"length":183,"previous":"M16-GAP-02069","next":"M16-GAP-02071"},"M16-GAP-02071":{"line":2070,"offset":358865,"length":174,"previous":"M16-GAP-02070","next":"M16-GAP-02072"},"M16-GAP-02072":{"line":2071,"offset":359039,"length":172,"previous":"M16-GAP-02071","next":"M16-GAP-02073"},"M16-GAP-02073":{"line":2072,"offset":359211,"length":184,"previous":"M16-GAP-02072","next":"M16-GAP-02074"},"M16-GAP-02074":{"line":2073,"offset":359395,"length":171,"previous":"M16-GAP-02073","next":"M16-GAP-02075"},"M16-GAP-02075":{"line":2074,"offset":359566,"length":169,"previous":"M16-GAP-02074","next":"M16-GAP-02076"},"M16-GAP-02076":{"line":2075,"offset":359735,"length":176,"previous":"M16-GAP-02075","next":"M16-GAP-02077"},"M16-GAP-02077":{"line":2076,"offset":359911,"length":174,"previous":"M16-GAP-02076","next":"M16-GAP-02078"},"M16-GAP-02078":{"line":2077,"offset":360085,"length":167,"previous":"M16-GAP-02077","next":"M16-GAP-02079"},"M16-GAP-02079":{"line":2078,"offset":360252,"length":169,"previous":"M16-GAP-02078","next":"M16-GAP-02080"},"M16-GAP-02080":{"line":2079,"offset":360421,"length":166,"previous":"M16-GAP-02079","next":"M16-GAP-02081"},"M16-GAP-02081":{"line":2080,"offset":360587,"length":176,"previous":"M16-GAP-02080","next":"M16-GAP-02082"},"M16-GAP-02082":{"line":2081,"offset":360763,"length":174,"previous":"M16-GAP-02081","next":"M16-GAP-02083"},"M16-GAP-02083":{"line":2082,"offset":360937,"length":178,"previous":"M16-GAP-02082","next":"M16-GAP-02084"},"M16-GAP-02084":{"line":2083,"offset":361115,"length":176,"previous":"M16-GAP-02083","next":"M16-GAP-02085"},"M16-GAP-02085":{"line":2084,"offset":361291,"length":175,"previous":"M16-GAP-02084","next":"M16-GAP-02086"},"M16-GAP-02086":{"line":2085,"offset":361466,"length":177,"previous":"M16-GAP-02085","next":"M16-GAP-02087"},"M16-GAP-02087":{"line":2086,"offset":361643,"length":176,"previous":"M16-GAP-02086","next":"M16-GAP-02088"},"M16-GAP-02088":{"line":2087,"offset":361819,"length":168,"previous":"M16-GAP-02087","next":"M16-GAP-02089"},"M16-GAP-02089":{"line":2088,"offset":361987,"length":174,"previous":"M16-GAP-02088","next":"M16-GAP-02090"},"M16-GAP-02090":{"line":2089,"offset":362161,"length":176,"previous":"M16-GAP-02089","next":"M16-GAP-02091"},"M16-GAP-02091":{"line":2090,"offset":362337,"length":175,"previous":"M16-GAP-02090","next":"M16-GAP-02092"},"M16-GAP-02092":{"line":2091,"offset":362512,"length":179,"previous":"M16-GAP-02091","next":"M16-GAP-02093"},"M16-GAP-02093":{"line":2092,"offset":362691,"length":172,"previous":"M16-GAP-02092","next":"M16-GAP-02094"},"M16-GAP-02094":{"line":2093,"offset":362863,"length":173,"previous":"M16-GAP-02093","next":"M16-GAP-02095"},"M16-GAP-02095":{"line":2094,"offset":363036,"length":173,"previous":"M16-GAP-02094","next":"M16-GAP-02096"},"M16-GAP-02096":{"line":2095,"offset":363209,"length":177,"previous":"M16-GAP-02095","next":"M16-GAP-02097"},"M16-GAP-02097":{"line":2096,"offset":363386,"length":182,"previous":"M16-GAP-02096","next":"M16-GAP-02098"},"M16-GAP-02098":{"line":2097,"offset":363568,"length":176,"previous":"M16-GAP-02097","next":"M16-GAP-02099"},"M16-GAP-02099":{"line":2098,"offset":363744,"length":178,"previous":"M16-GAP-02098","next":"M16-GAP-02100"},"M16-GAP-02100":{"line":2099,"offset":363922,"length":193,"previous":"M16-GAP-02099","next":"M16-GAP-02101"},"M16-GAP-02101":{"line":2100,"offset":364115,"length":170,"previous":"M16-GAP-02100","next":"M16-GAP-02102"},"M16-GAP-02102":{"line":2101,"offset":364285,"length":179,"previous":"M16-GAP-02101","next":"M16-GAP-02103"},"M16-GAP-02103":{"line":2102,"offset":364464,"length":172,"previous":"M16-GAP-02102","next":"M16-GAP-02104"},"M16-GAP-02104":{"line":2103,"offset":364636,"length":173,"previous":"M16-GAP-02103","next":"M16-GAP-02105"},"M16-GAP-02105":{"line":2104,"offset":364809,"length":168,"previous":"M16-GAP-02104","next":"M16-GAP-02106"},"M16-GAP-02106":{"line":2105,"offset":364977,"length":165,"previous":"M16-GAP-02105","next":"M16-GAP-02107"},"M16-GAP-02107":{"line":2106,"offset":365142,"length":177,"previous":"M16-GAP-02106","next":"M16-GAP-02108"},"M16-GAP-02108":{"line":2107,"offset":365319,"length":171,"previous":"M16-GAP-02107","next":"M16-GAP-02109"},"M16-GAP-02109":{"line":2108,"offset":365490,"length":188,"previous":"M16-GAP-02108","next":"M16-GAP-02110"},"M16-GAP-02110":{"line":2109,"offset":365678,"length":167,"previous":"M16-GAP-02109","next":"M16-GAP-02111"},"M16-GAP-02111":{"line":2110,"offset":365845,"length":171,"previous":"M16-GAP-02110","next":"M16-GAP-02112"},"M16-GAP-02112":{"line":2111,"offset":366016,"length":170,"previous":"M16-GAP-02111","next":"M16-GAP-02113"},"M16-GAP-02113":{"line":2112,"offset":366186,"length":175,"previous":"M16-GAP-02112","next":"M16-GAP-02114"},"M16-GAP-02114":{"line":2113,"offset":366361,"length":182,"previous":"M16-GAP-02113","next":"M16-GAP-02115"},"M16-GAP-02115":{"line":2114,"offset":366543,"length":177,"previous":"M16-GAP-02114","next":"M16-GAP-02116"},"M16-GAP-02116":{"line":2115,"offset":366720,"length":175,"previous":"M16-GAP-02115","next":"M16-GAP-02117"},"M16-GAP-02117":{"line":2116,"offset":366895,"length":177,"previous":"M16-GAP-02116","next":"M16-GAP-02118"},"M16-GAP-02118":{"line":2117,"offset":367072,"length":170,"previous":"M16-GAP-02117","next":"M16-GAP-02119"},"M16-GAP-02119":{"line":2118,"offset":367242,"length":172,"previous":"M16-GAP-02118","next":"M16-GAP-02120"},"M16-GAP-02120":{"line":2119,"offset":367414,"length":171,"previous":"M16-GAP-02119","next":"M16-GAP-02121"},"M16-GAP-02121":{"line":2120,"offset":367585,"length":171,"previous":"M16-GAP-02120","next":"M16-GAP-02122"},"M16-GAP-02122":{"line":2121,"offset":367756,"length":176,"previous":"M16-GAP-02121","next":"M16-GAP-02123"},"M16-GAP-02123":{"line":2122,"offset":367932,"length":176,"previous":"M16-GAP-02122","next":"M16-GAP-02124"},"M16-GAP-02124":{"line":2123,"offset":368108,"length":165,"previous":"M16-GAP-02123","next":"M16-GAP-02125"},"M16-GAP-02125":{"line":2124,"offset":368273,"length":175,"previous":"M16-GAP-02124","next":"M16-GAP-02126"},"M16-GAP-02126":{"line":2125,"offset":368448,"length":170,"previous":"M16-GAP-02125","next":"M16-GAP-02127"},"M16-GAP-02127":{"line":2126,"offset":368618,"length":174,"previous":"M16-GAP-02126","next":"M16-GAP-02128"},"M16-GAP-02128":{"line":2127,"offset":368792,"length":172,"previous":"M16-GAP-02127","next":"M16-GAP-02129"},"M16-GAP-02129":{"line":2128,"offset":368964,"length":176,"previous":"M16-GAP-02128","next":"M16-GAP-02130"},"M16-GAP-02130":{"line":2129,"offset":369140,"length":180,"previous":"M16-GAP-02129","next":"M16-GAP-02131"},"M16-GAP-02131":{"line":2130,"offset":369320,"length":165,"previous":"M16-GAP-02130","next":"M16-GAP-02132"},"M16-GAP-02132":{"line":2131,"offset":369485,"length":173,"previous":"M16-GAP-02131","next":"M16-GAP-02133"},"M16-GAP-02133":{"line":2132,"offset":369658,"length":166,"previous":"M16-GAP-02132","next":"M16-GAP-02134"},"M16-GAP-02134":{"line":2133,"offset":369824,"length":183,"previous":"M16-GAP-02133","next":"M16-GAP-02135"},"M16-GAP-02135":{"line":2134,"offset":370007,"length":190,"previous":"M16-GAP-02134","next":"M16-GAP-02136"},"M16-GAP-02136":{"line":2135,"offset":370197,"length":176,"previous":"M16-GAP-02135","next":"M16-GAP-02137"},"M16-GAP-02137":{"line":2136,"offset":370373,"length":174,"previous":"M16-GAP-02136","next":"M16-GAP-02138"},"M16-GAP-02138":{"line":2137,"offset":370547,"length":172,"previous":"M16-GAP-02137","next":"M16-GAP-02139"},"M16-GAP-02139":{"line":2138,"offset":370719,"length":167,"previous":"M16-GAP-02138","next":"M16-GAP-02140"},"M16-GAP-02140":{"line":2139,"offset":370886,"length":175,"previous":"M16-GAP-02139","next":"M16-GAP-02141"},"M16-GAP-02141":{"line":2140,"offset":371061,"length":171,"previous":"M16-GAP-02140","next":"M16-GAP-02142"},"M16-GAP-02142":{"line":2141,"offset":371232,"length":192,"previous":"M16-GAP-02141","next":"M16-GAP-02143"},"M16-GAP-02143":{"line":2142,"offset":371424,"length":190,"previous":"M16-GAP-02142","next":"M16-GAP-02144"},"M16-GAP-02144":{"line":2143,"offset":371614,"length":186,"previous":"M16-GAP-02143","next":"M16-GAP-02145"},"M16-GAP-02145":{"line":2144,"offset":371800,"length":177,"previous":"M16-GAP-02144","next":"M16-GAP-02146"},"M16-GAP-02146":{"line":2145,"offset":371977,"length":180,"previous":"M16-GAP-02145","next":"M16-GAP-02147"},"M16-GAP-02147":{"line":2146,"offset":372157,"length":175,"previous":"M16-GAP-02146","next":"M16-GAP-02148"},"M16-GAP-02148":{"line":2147,"offset":372332,"length":187,"previous":"M16-GAP-02147","next":"M16-GAP-02149"},"M16-GAP-02149":{"line":2148,"offset":372519,"length":174,"previous":"M16-GAP-02148","next":"M16-GAP-02150"},"M16-GAP-02150":{"line":2149,"offset":372693,"length":184,"previous":"M16-GAP-02149","next":"M16-GAP-02151"},"M16-GAP-02151":{"line":2150,"offset":372877,"length":167,"previous":"M16-GAP-02150","next":"M16-GAP-02152"},"M16-GAP-02152":{"line":2151,"offset":373044,"length":185,"previous":"M16-GAP-02151","next":"M16-GAP-02153"},"M16-GAP-02153":{"line":2152,"offset":373229,"length":176,"previous":"M16-GAP-02152","next":"M16-GAP-02154"},"M16-GAP-02154":{"line":2153,"offset":373405,"length":180,"previous":"M16-GAP-02153","next":"M16-GAP-02155"},"M16-GAP-02155":{"line":2154,"offset":373585,"length":167,"previous":"M16-GAP-02154","next":"M16-GAP-02156"},"M16-GAP-02156":{"line":2155,"offset":373752,"length":171,"previous":"M16-GAP-02155","next":"M16-GAP-02157"},"M16-GAP-02157":{"line":2156,"offset":373923,"length":171,"previous":"M16-GAP-02156","next":"M16-GAP-02158"},"M16-GAP-02158":{"line":2157,"offset":374094,"length":174,"previous":"M16-GAP-02157","next":"M16-GAP-02159"},"M16-GAP-02159":{"line":2158,"offset":374268,"length":175,"previous":"M16-GAP-02158","next":"M16-GAP-02160"},"M16-GAP-02160":{"line":2159,"offset":374443,"length":174,"previous":"M16-GAP-02159","next":"M16-GAP-02161"},"M16-GAP-02161":{"line":2160,"offset":374617,"length":175,"previous":"M16-GAP-02160","next":"M16-GAP-02162"},"M16-GAP-02162":{"line":2161,"offset":374792,"length":173,"previous":"M16-GAP-02161","next":"M16-GAP-02163"},"M16-GAP-02163":{"line":2162,"offset":374965,"length":172,"previous":"M16-GAP-02162","next":"M16-GAP-02164"},"M16-GAP-02164":{"line":2163,"offset":375137,"length":174,"previous":"M16-GAP-02163","next":"M16-GAP-02165"},"M16-GAP-02165":{"line":2164,"offset":375311,"length":179,"previous":"M16-GAP-02164","next":"M16-GAP-02166"},"M16-GAP-02166":{"line":2165,"offset":375490,"length":172,"previous":"M16-GAP-02165","next":"M16-GAP-02167"},"M16-GAP-02167":{"line":2166,"offset":375662,"length":172,"previous":"M16-GAP-02166","next":"M16-GAP-02168"},"M16-GAP-02168":{"line":2167,"offset":375834,"length":181,"previous":"M16-GAP-02167","next":"M16-GAP-02169"},"M16-GAP-02169":{"line":2168,"offset":376015,"length":180,"previous":"M16-GAP-02168","next":"M16-GAP-02170"},"M16-GAP-02170":{"line":2169,"offset":376195,"length":165,"previous":"M16-GAP-02169","next":"M16-GAP-02171"},"M16-GAP-02171":{"line":2170,"offset":376360,"length":165,"previous":"M16-GAP-02170","next":"M16-GAP-02172"},"M16-GAP-02172":{"line":2171,"offset":376525,"length":176,"previous":"M16-GAP-02171","next":"M16-GAP-02173"},"M16-GAP-02173":{"line":2172,"offset":376701,"length":166,"previous":"M16-GAP-02172","next":"M16-GAP-02174"},"M16-GAP-02174":{"line":2173,"offset":376867,"length":175,"previous":"M16-GAP-02173","next":"M16-GAP-02175"},"M16-GAP-02175":{"line":2174,"offset":377042,"length":180,"previous":"M16-GAP-02174","next":"M16-GAP-02176"},"M16-GAP-02176":{"line":2175,"offset":377222,"length":171,"previous":"M16-GAP-02175","next":"M16-GAP-02177"},"M16-GAP-02177":{"line":2176,"offset":377393,"length":179,"previous":"M16-GAP-02176","next":"M16-GAP-02178"},"M16-GAP-02178":{"line":2177,"offset":377572,"length":190,"previous":"M16-GAP-02177","next":"M16-GAP-02179"},"M16-GAP-02179":{"line":2178,"offset":377762,"length":180,"previous":"M16-GAP-02178","next":"M16-GAP-02180"},"M16-GAP-02180":{"line":2179,"offset":377942,"length":185,"previous":"M16-GAP-02179","next":"M16-GAP-02181"},"M16-GAP-02181":{"line":2180,"offset":378127,"length":194,"previous":"M16-GAP-02180","next":"M16-GAP-02182"},"M16-GAP-02182":{"line":2181,"offset":378321,"length":180,"previous":"M16-GAP-02181","next":"M16-GAP-02183"},"M16-GAP-02183":{"line":2182,"offset":378501,"length":189,"previous":"M16-GAP-02182","next":"M16-GAP-02184"},"M16-GAP-02184":{"line":2183,"offset":378690,"length":182,"previous":"M16-GAP-02183","next":"M16-GAP-02185"},"M16-GAP-02185":{"line":2184,"offset":378872,"length":186,"previous":"M16-GAP-02184","next":"M16-GAP-02186"},"M16-GAP-02186":{"line":2185,"offset":379058,"length":182,"previous":"M16-GAP-02185","next":"M16-GAP-02187"},"M16-GAP-02187":{"line":2186,"offset":379240,"length":180,"previous":"M16-GAP-02186","next":"M16-GAP-02188"},"M16-GAP-02188":{"line":2187,"offset":379420,"length":165,"previous":"M16-GAP-02187","next":"M16-GAP-02189"},"M16-GAP-02189":{"line":2188,"offset":379585,"length":170,"previous":"M16-GAP-02188","next":"M16-GAP-02190"},"M16-GAP-02190":{"line":2189,"offset":379755,"length":172,"previous":"M16-GAP-02189","next":"M16-GAP-02191"},"M16-GAP-02191":{"line":2190,"offset":379927,"length":177,"previous":"M16-GAP-02190","next":"M16-GAP-02192"},"M16-GAP-02192":{"line":2191,"offset":380104,"length":176,"previous":"M16-GAP-02191","next":"M16-GAP-02193"},"M16-GAP-02193":{"line":2192,"offset":380280,"length":172,"previous":"M16-GAP-02192","next":"M16-GAP-02194"},"M16-GAP-02194":{"line":2193,"offset":380452,"length":178,"previous":"M16-GAP-02193","next":"M16-GAP-02195"},"M16-GAP-02195":{"line":2194,"offset":380630,"length":175,"previous":"M16-GAP-02194","next":"M16-GAP-02196"},"M16-GAP-02196":{"line":2195,"offset":380805,"length":174,"previous":"M16-GAP-02195","next":"M16-GAP-02197"},"M16-GAP-02197":{"line":2196,"offset":380979,"length":182,"previous":"M16-GAP-02196","next":"M16-GAP-02198"},"M16-GAP-02198":{"line":2197,"offset":381161,"length":176,"previous":"M16-GAP-02197","next":"M16-GAP-02199"},"M16-GAP-02199":{"line":2198,"offset":381337,"length":172,"previous":"M16-GAP-02198","next":"M16-GAP-02200"},"M16-GAP-02200":{"line":2199,"offset":381509,"length":176,"previous":"M16-GAP-02199","next":"M16-GAP-02201"},"M16-GAP-02201":{"line":2200,"offset":381685,"length":176,"previous":"M16-GAP-02200","next":"M16-GAP-02202"},"M16-GAP-02202":{"line":2201,"offset":381861,"length":188,"previous":"M16-GAP-02201","next":"M16-GAP-02203"},"M16-GAP-02203":{"line":2202,"offset":382049,"length":167,"previous":"M16-GAP-02202","next":"M16-GAP-02204"},"M16-GAP-02204":{"line":2203,"offset":382216,"length":167,"previous":"M16-GAP-02203","next":"M16-GAP-02205"},"M16-GAP-02205":{"line":2204,"offset":382383,"length":169,"previous":"M16-GAP-02204","next":"M16-GAP-02206"},"M16-GAP-02206":{"line":2205,"offset":382552,"length":177,"previous":"M16-GAP-02205","next":"M16-GAP-02207"},"M16-GAP-02207":{"line":2206,"offset":382729,"length":171,"previous":"M16-GAP-02206","next":"M16-GAP-02208"},"M16-GAP-02208":{"line":2207,"offset":382900,"length":178,"previous":"M16-GAP-02207","next":"M16-GAP-02209"},"M16-GAP-02209":{"line":2208,"offset":383078,"length":174,"previous":"M16-GAP-02208","next":"M16-GAP-02210"},"M16-GAP-02210":{"line":2209,"offset":383252,"length":176,"previous":"M16-GAP-02209","next":"M16-GAP-02211"},"M16-GAP-02211":{"line":2210,"offset":383428,"length":171,"previous":"M16-GAP-02210","next":"M16-GAP-02212"},"M16-GAP-02212":{"line":2211,"offset":383599,"length":164,"previous":"M16-GAP-02211","next":"M16-GAP-02213"},"M16-GAP-02213":{"line":2212,"offset":383763,"length":161,"previous":"M16-GAP-02212","next":"M16-GAP-02214"},"M16-GAP-02214":{"line":2213,"offset":383924,"length":166,"previous":"M16-GAP-02213","next":"M16-GAP-02215"},"M16-GAP-02215":{"line":2214,"offset":384090,"length":161,"previous":"M16-GAP-02214","next":"M16-GAP-02216"},"M16-GAP-02216":{"line":2215,"offset":384251,"length":163,"previous":"M16-GAP-02215","next":"M16-GAP-02217"},"M16-GAP-02217":{"line":2216,"offset":384414,"length":179,"previous":"M16-GAP-02216","next":"M16-GAP-02218"},"M16-GAP-02218":{"line":2217,"offset":384593,"length":182,"previous":"M16-GAP-02217","next":"M16-GAP-02219"},"M16-GAP-02219":{"line":2218,"offset":384775,"length":193,"previous":"M16-GAP-02218","next":"M16-GAP-02220"},"M16-GAP-02220":{"line":2219,"offset":384968,"length":173,"previous":"M16-GAP-02219","next":"M16-GAP-02221"},"M16-GAP-02221":{"line":2220,"offset":385141,"length":185,"previous":"M16-GAP-02220","next":"M16-GAP-02222"},"M16-GAP-02222":{"line":2221,"offset":385326,"length":178,"previous":"M16-GAP-02221","next":"M16-GAP-02223"},"M16-GAP-02223":{"line":2222,"offset":385504,"length":176,"previous":"M16-GAP-02222","next":"M16-GAP-02224"},"M16-GAP-02224":{"line":2223,"offset":385680,"length":173,"previous":"M16-GAP-02223","next":"M16-GAP-02225"},"M16-GAP-02225":{"line":2224,"offset":385853,"length":193,"previous":"M16-GAP-02224","next":"M16-GAP-02226"},"M16-GAP-02226":{"line":2225,"offset":386046,"length":192,"previous":"M16-GAP-02225","next":"M16-GAP-02227"},"M16-GAP-02227":{"line":2226,"offset":386238,"length":195,"previous":"M16-GAP-02226","next":"M16-GAP-02228"},"M16-GAP-02228":{"line":2227,"offset":386433,"length":193,"previous":"M16-GAP-02227","next":"M16-GAP-02229"},"M16-GAP-02229":{"line":2228,"offset":386626,"length":194,"previous":"M16-GAP-02228","next":"M16-GAP-02230"},"M16-GAP-02230":{"line":2229,"offset":386820,"length":192,"previous":"M16-GAP-02229","next":"M16-GAP-02231"},"M16-GAP-02231":{"line":2230,"offset":387012,"length":168,"previous":"M16-GAP-02230","next":"M16-GAP-02232"},"M16-GAP-02232":{"line":2231,"offset":387180,"length":170,"previous":"M16-GAP-02231","next":"M16-GAP-02233"},"M16-GAP-02233":{"line":2232,"offset":387350,"length":174,"previous":"M16-GAP-02232","next":"M16-GAP-02234"},"M16-GAP-02234":{"line":2233,"offset":387524,"length":160,"previous":"M16-GAP-02233","next":"M16-GAP-02235"},"M16-GAP-02235":{"line":2234,"offset":387684,"length":166,"previous":"M16-GAP-02234","next":"M16-GAP-02236"},"M16-GAP-02236":{"line":2235,"offset":387850,"length":159,"previous":"M16-GAP-02235","next":"M16-GAP-02237"},"M16-GAP-02237":{"line":2236,"offset":388009,"length":162,"previous":"M16-GAP-02236","next":"M16-GAP-02238"},"M16-GAP-02238":{"line":2237,"offset":388171,"length":170,"previous":"M16-GAP-02237","next":"M16-GAP-02239"},"M16-GAP-02239":{"line":2238,"offset":388341,"length":160,"previous":"M16-GAP-02238","next":"M16-GAP-02240"},"M16-GAP-02240":{"line":2239,"offset":388501,"length":173,"previous":"M16-GAP-02239","next":"M16-GAP-02241"},"M16-GAP-02241":{"line":2240,"offset":388674,"length":162,"previous":"M16-GAP-02240","next":"M16-GAP-02242"},"M16-GAP-02242":{"line":2241,"offset":388836,"length":178,"previous":"M16-GAP-02241","next":"M16-GAP-02243"},"M16-GAP-02243":{"line":2242,"offset":389014,"length":162,"previous":"M16-GAP-02242","next":"M16-GAP-02244"},"M16-GAP-02244":{"line":2243,"offset":389176,"length":160,"previous":"M16-GAP-02243","next":"M16-GAP-02245"},"M16-GAP-02245":{"line":2244,"offset":389336,"length":177,"previous":"M16-GAP-02244","next":"M16-GAP-02246"},"M16-GAP-02246":{"line":2245,"offset":389513,"length":166,"previous":"M16-GAP-02245","next":"M16-GAP-02247"},"M16-GAP-02247":{"line":2246,"offset":389679,"length":167,"previous":"M16-GAP-02246","next":"M16-GAP-02248"},"M16-GAP-02248":{"line":2247,"offset":389846,"length":169,"previous":"M16-GAP-02247","next":"M16-GAP-02249"},"M16-GAP-02249":{"line":2248,"offset":390015,"length":160,"previous":"M16-GAP-02248","next":"M16-GAP-02250"},"M16-GAP-02250":{"line":2249,"offset":390175,"length":166,"previous":"M16-GAP-02249","next":"M16-GAP-02251"},"M16-GAP-02251":{"line":2250,"offset":390341,"length":167,"previous":"M16-GAP-02250","next":"M16-GAP-02252"},"M16-GAP-02252":{"line":2251,"offset":390508,"length":159,"previous":"M16-GAP-02251","next":"M16-GAP-02253"},"M16-GAP-02253":{"line":2252,"offset":390667,"length":160,"previous":"M16-GAP-02252","next":"M16-GAP-02254"},"M16-GAP-02254":{"line":2253,"offset":390827,"length":172,"previous":"M16-GAP-02253","next":"M16-GAP-02255"},"M16-GAP-02255":{"line":2254,"offset":390999,"length":161,"previous":"M16-GAP-02254","next":"M16-GAP-02256"},"M16-GAP-02256":{"line":2255,"offset":391160,"length":162,"previous":"M16-GAP-02255","next":"M16-GAP-02257"},"M16-GAP-02257":{"line":2256,"offset":391322,"length":163,"previous":"M16-GAP-02256","next":"M16-GAP-02258"},"M16-GAP-02258":{"line":2257,"offset":391485,"length":176,"previous":"M16-GAP-02257","next":"M16-GAP-02259"},"M16-GAP-02259":{"line":2258,"offset":391661,"length":172,"previous":"M16-GAP-02258","next":"M16-GAP-02260"},"M16-GAP-02260":{"line":2259,"offset":391833,"length":166,"previous":"M16-GAP-02259","next":"M16-GAP-02261"},"M16-GAP-02261":{"line":2260,"offset":391999,"length":160,"previous":"M16-GAP-02260","next":"M16-GAP-02262"},"M16-GAP-02262":{"line":2261,"offset":392159,"length":163,"previous":"M16-GAP-02261","next":"M16-GAP-02263"},"M16-GAP-02263":{"line":2262,"offset":392322,"length":162,"previous":"M16-GAP-02262","next":"M16-GAP-02264"},"M16-GAP-02264":{"line":2263,"offset":392484,"length":166,"previous":"M16-GAP-02263","next":"M16-GAP-02265"},"M16-GAP-02265":{"line":2264,"offset":392650,"length":166,"previous":"M16-GAP-02264","next":"M16-GAP-02266"},"M16-GAP-02266":{"line":2265,"offset":392816,"length":167,"previous":"M16-GAP-02265","next":"M16-GAP-02267"},"M16-GAP-02267":{"line":2266,"offset":392983,"length":167,"previous":"M16-GAP-02266","next":"M16-GAP-02268"},"M16-GAP-02268":{"line":2267,"offset":393150,"length":169,"previous":"M16-GAP-02267","next":"M16-GAP-02269"},"M16-GAP-02269":{"line":2268,"offset":393319,"length":166,"previous":"M16-GAP-02268","next":"M16-GAP-02270"},"M16-GAP-02270":{"line":2269,"offset":393485,"length":168,"previous":"M16-GAP-02269","next":"M16-GAP-02271"},"M16-GAP-02271":{"line":2270,"offset":393653,"length":164,"previous":"M16-GAP-02270","next":"M16-GAP-02272"},"M16-GAP-02272":{"line":2271,"offset":393817,"length":162,"previous":"M16-GAP-02271","next":"M16-GAP-02273"},"M16-GAP-02273":{"line":2272,"offset":393979,"length":169,"previous":"M16-GAP-02272","next":"M16-GAP-02274"},"M16-GAP-02274":{"line":2273,"offset":394148,"length":173,"previous":"M16-GAP-02273","next":"M16-GAP-02275"},"M16-GAP-02275":{"line":2274,"offset":394321,"length":162,"previous":"M16-GAP-02274","next":"M16-GAP-02276"},"M16-GAP-02276":{"line":2275,"offset":394483,"length":168,"previous":"M16-GAP-02275","next":"M16-GAP-02277"},"M16-GAP-02277":{"line":2276,"offset":394651,"length":168,"previous":"M16-GAP-02276","next":"M16-GAP-02278"},"M16-GAP-02278":{"line":2277,"offset":394819,"length":169,"previous":"M16-GAP-02277","next":"M16-GAP-02279"},"M16-GAP-02279":{"line":2278,"offset":394988,"length":173,"previous":"M16-GAP-02278","next":"M16-GAP-02280"},"M16-GAP-02280":{"line":2279,"offset":395161,"length":165,"previous":"M16-GAP-02279","next":"M16-GAP-02281"},"M16-GAP-02281":{"line":2280,"offset":395326,"length":179,"previous":"M16-GAP-02280","next":"M16-GAP-02282"},"M16-GAP-02282":{"line":2281,"offset":395505,"length":179,"previous":"M16-GAP-02281","next":"M16-GAP-02283"},"M16-GAP-02283":{"line":2282,"offset":395684,"length":177,"previous":"M16-GAP-02282","next":"M16-GAP-02284"},"M16-GAP-02284":{"line":2283,"offset":395861,"length":172,"previous":"M16-GAP-02283","next":"M16-GAP-02285"},"M16-GAP-02285":{"line":2284,"offset":396033,"length":171,"previous":"M16-GAP-02284","next":"M16-GAP-02286"},"M16-GAP-02286":{"line":2285,"offset":396204,"length":171,"previous":"M16-GAP-02285","next":"M16-GAP-02287"},"M16-GAP-02287":{"line":2286,"offset":396375,"length":167,"previous":"M16-GAP-02286","next":"M16-GAP-02288"},"M16-GAP-02288":{"line":2287,"offset":396542,"length":170,"previous":"M16-GAP-02287","next":"M16-GAP-02289"},"M16-GAP-02289":{"line":2288,"offset":396712,"length":167,"previous":"M16-GAP-02288","next":"M16-GAP-02290"},"M16-GAP-02290":{"line":2289,"offset":396879,"length":167,"previous":"M16-GAP-02289","next":"M16-GAP-02291"},"M16-GAP-02291":{"line":2290,"offset":397046,"length":174,"previous":"M16-GAP-02290","next":"M16-GAP-02292"},"M16-GAP-02292":{"line":2291,"offset":397220,"length":179,"previous":"M16-GAP-02291","next":"M16-GAP-02293"},"M16-GAP-02293":{"line":2292,"offset":397399,"length":170,"previous":"M16-GAP-02292","next":"M16-GAP-02294"},"M16-GAP-02294":{"line":2293,"offset":397569,"length":166,"previous":"M16-GAP-02293","next":"M16-GAP-02295"},"M16-GAP-02295":{"line":2294,"offset":397735,"length":174,"previous":"M16-GAP-02294","next":"M16-GAP-02296"},"M16-GAP-02296":{"line":2295,"offset":397909,"length":172,"previous":"M16-GAP-02295","next":"M16-GAP-02297"},"M16-GAP-02297":{"line":2296,"offset":398081,"length":165,"previous":"M16-GAP-02296","next":"M16-GAP-02298"},"M16-GAP-02298":{"line":2297,"offset":398246,"length":169,"previous":"M16-GAP-02297","next":"M16-GAP-02299"},"M16-GAP-02299":{"line":2298,"offset":398415,"length":170,"previous":"M16-GAP-02298","next":"M16-GAP-02300"},"M16-GAP-02300":{"line":2299,"offset":398585,"length":170,"previous":"M16-GAP-02299","next":"M16-GAP-02301"},"M16-GAP-02301":{"line":2300,"offset":398755,"length":170,"previous":"M16-GAP-02300","next":"M16-GAP-02302"},"M16-GAP-02302":{"line":2301,"offset":398925,"length":172,"previous":"M16-GAP-02301","next":"M16-GAP-02303"},"M16-GAP-02303":{"line":2302,"offset":399097,"length":171,"previous":"M16-GAP-02302","next":"M16-GAP-02304"},"M16-GAP-02304":{"line":2303,"offset":399268,"length":174,"previous":"M16-GAP-02303","next":"M16-GAP-02305"},"M16-GAP-02305":{"line":2304,"offset":399442,"length":172,"previous":"M16-GAP-02304","next":"M16-GAP-02306"},"M16-GAP-02306":{"line":2305,"offset":399614,"length":175,"previous":"M16-GAP-02305","next":"M16-GAP-02307"},"M16-GAP-02307":{"line":2306,"offset":399789,"length":168,"previous":"M16-GAP-02306","next":"M16-GAP-02308"},"M16-GAP-02308":{"line":2307,"offset":399957,"length":173,"previous":"M16-GAP-02307","next":"M16-GAP-02309"},"M16-GAP-02309":{"line":2308,"offset":400130,"length":175,"previous":"M16-GAP-02308","next":"M16-GAP-02310"},"M16-GAP-02310":{"line":2309,"offset":400305,"length":175,"previous":"M16-GAP-02309","next":"M16-GAP-02311"},"M16-GAP-02311":{"line":2310,"offset":400480,"length":184,"previous":"M16-GAP-02310","next":"M16-GAP-02312"},"M16-GAP-02312":{"line":2311,"offset":400664,"length":180,"previous":"M16-GAP-02311","next":"M16-GAP-02313"},"M16-GAP-02313":{"line":2312,"offset":400844,"length":177,"previous":"M16-GAP-02312","next":"M16-GAP-02314"},"M16-GAP-02314":{"line":2313,"offset":401021,"length":164,"previous":"M16-GAP-02313","next":"M16-GAP-02315"},"M16-GAP-02315":{"line":2314,"offset":401185,"length":167,"previous":"M16-GAP-02314","next":"M16-GAP-02316"},"M16-GAP-02316":{"line":2315,"offset":401352,"length":163,"previous":"M16-GAP-02315","next":"M16-GAP-02317"},"M16-GAP-02317":{"line":2316,"offset":401515,"length":164,"previous":"M16-GAP-02316","next":"M16-GAP-02318"},"M16-GAP-02318":{"line":2317,"offset":401679,"length":169,"previous":"M16-GAP-02317","next":"M16-GAP-02319"},"M16-GAP-02319":{"line":2318,"offset":401848,"length":170,"previous":"M16-GAP-02318","next":"M16-GAP-02320"},"M16-GAP-02320":{"line":2319,"offset":402018,"length":174,"previous":"M16-GAP-02319","next":"M16-GAP-02321"},"M16-GAP-02321":{"line":2320,"offset":402192,"length":180,"previous":"M16-GAP-02320","next":"M16-GAP-02322"},"M16-GAP-02322":{"line":2321,"offset":402372,"length":170,"previous":"M16-GAP-02321","next":"M16-GAP-02323"},"M16-GAP-02323":{"line":2322,"offset":402542,"length":171,"previous":"M16-GAP-02322","next":"M16-GAP-02324"},"M16-GAP-02324":{"line":2323,"offset":402713,"length":184,"previous":"M16-GAP-02323","next":"M16-GAP-02325"},"M16-GAP-02325":{"line":2324,"offset":402897,"length":167,"previous":"M16-GAP-02324","next":"M16-GAP-02326"},"M16-GAP-02326":{"line":2325,"offset":403064,"length":175,"previous":"M16-GAP-02325","next":"M16-GAP-02327"},"M16-GAP-02327":{"line":2326,"offset":403239,"length":171,"previous":"M16-GAP-02326","next":"M16-GAP-02328"},"M16-GAP-02328":{"line":2327,"offset":403410,"length":173,"previous":"M16-GAP-02327","next":"M16-GAP-02329"},"M16-GAP-02329":{"line":2328,"offset":403583,"length":179,"previous":"M16-GAP-02328","next":"M16-GAP-02330"},"M16-GAP-02330":{"line":2329,"offset":403762,"length":178,"previous":"M16-GAP-02329","next":"M16-GAP-02331"},"M16-GAP-02331":{"line":2330,"offset":403940,"length":179,"previous":"M16-GAP-02330","next":"M16-GAP-02332"},"M16-GAP-02332":{"line":2331,"offset":404119,"length":176,"previous":"M16-GAP-02331","next":"M16-GAP-02333"},"M16-GAP-02333":{"line":2332,"offset":404295,"length":171,"previous":"M16-GAP-02332","next":"M16-GAP-02334"},"M16-GAP-02334":{"line":2333,"offset":404466,"length":174,"previous":"M16-GAP-02333","next":"M16-GAP-02335"},"M16-GAP-02335":{"line":2334,"offset":404640,"length":175,"previous":"M16-GAP-02334","next":"M16-GAP-02336"},"M16-GAP-02336":{"line":2335,"offset":404815,"length":163,"previous":"M16-GAP-02335","next":"M16-GAP-02337"},"M16-GAP-02337":{"line":2336,"offset":404978,"length":170,"previous":"M16-GAP-02336","next":"M16-GAP-02338"},"M16-GAP-02338":{"line":2337,"offset":405148,"length":169,"previous":"M16-GAP-02337","next":"M16-GAP-02339"},"M16-GAP-02339":{"line":2338,"offset":405317,"length":172,"previous":"M16-GAP-02338","next":"M16-GAP-02340"},"M16-GAP-02340":{"line":2339,"offset":405489,"length":170,"previous":"M16-GAP-02339","next":"M16-GAP-02341"},"M16-GAP-02341":{"line":2340,"offset":405659,"length":170,"previous":"M16-GAP-02340","next":"M16-GAP-02342"},"M16-GAP-02342":{"line":2341,"offset":405829,"length":165,"previous":"M16-GAP-02341","next":"M16-GAP-02343"},"M16-GAP-02343":{"line":2342,"offset":405994,"length":171,"previous":"M16-GAP-02342","next":"M16-GAP-02344"},"M16-GAP-02344":{"line":2343,"offset":406165,"length":167,"previous":"M16-GAP-02343","next":"M16-GAP-02345"},"M16-GAP-02345":{"line":2344,"offset":406332,"length":168,"previous":"M16-GAP-02344","next":"M16-GAP-02346"},"M16-GAP-02346":{"line":2345,"offset":406500,"length":170,"previous":"M16-GAP-02345","next":"M16-GAP-02347"},"M16-GAP-02347":{"line":2346,"offset":406670,"length":159,"previous":"M16-GAP-02346","next":"M16-GAP-02348"},"M16-GAP-02348":{"line":2347,"offset":406829,"length":168,"previous":"M16-GAP-02347","next":"M16-GAP-02349"},"M16-GAP-02349":{"line":2348,"offset":406997,"length":169,"previous":"M16-GAP-02348","next":"M16-GAP-02350"},"M16-GAP-02350":{"line":2349,"offset":407166,"length":175,"previous":"M16-GAP-02349","next":"M16-GAP-02351"},"M16-GAP-02351":{"line":2350,"offset":407341,"length":158,"previous":"M16-GAP-02350","next":"M16-GAP-02352"},"M16-GAP-02352":{"line":2351,"offset":407499,"length":173,"previous":"M16-GAP-02351","next":"M16-GAP-02353"},"M16-GAP-02353":{"line":2352,"offset":407672,"length":166,"previous":"M16-GAP-02352","next":"M16-GAP-02354"},"M16-GAP-02354":{"line":2353,"offset":407838,"length":164,"previous":"M16-GAP-02353","next":"M16-GAP-02355"},"M16-GAP-02355":{"line":2354,"offset":408002,"length":171,"previous":"M16-GAP-02354","next":"M16-GAP-02356"},"M16-GAP-02356":{"line":2355,"offset":408173,"length":170,"previous":"M16-GAP-02355","next":"M16-GAP-02357"},"M16-GAP-02357":{"line":2356,"offset":408343,"length":167,"previous":"M16-GAP-02356","next":"M16-GAP-02358"},"M16-GAP-02358":{"line":2357,"offset":408510,"length":173,"previous":"M16-GAP-02357","next":"M16-GAP-02359"},"M16-GAP-02359":{"line":2358,"offset":408683,"length":158,"previous":"M16-GAP-02358","next":"M16-GAP-02360"},"M16-GAP-02360":{"line":2359,"offset":408841,"length":167,"previous":"M16-GAP-02359","next":"M16-GAP-02361"},"M16-GAP-02361":{"line":2360,"offset":409008,"length":163,"previous":"M16-GAP-02360","next":"M16-GAP-02362"},"M16-GAP-02362":{"line":2361,"offset":409171,"length":170,"previous":"M16-GAP-02361","next":"M16-GAP-02363"},"M16-GAP-02363":{"line":2362,"offset":409341,"length":166,"previous":"M16-GAP-02362","next":"M16-GAP-02364"},"M16-GAP-02364":{"line":2363,"offset":409507,"length":166,"previous":"M16-GAP-02363","next":"M16-GAP-02365"},"M16-GAP-02365":{"line":2364,"offset":409673,"length":159,"previous":"M16-GAP-02364","next":"M16-GAP-02366"},"M16-GAP-02366":{"line":2365,"offset":409832,"length":157,"previous":"M16-GAP-02365","next":"M16-GAP-02367"},"M16-GAP-02367":{"line":2366,"offset":409989,"length":171,"previous":"M16-GAP-02366","next":"M16-GAP-02368"},"M16-GAP-02368":{"line":2367,"offset":410160,"length":176,"previous":"M16-GAP-02367","next":"M16-GAP-02369"},"M16-GAP-02369":{"line":2368,"offset":410336,"length":168,"previous":"M16-GAP-02368","next":"M16-GAP-02370"},"M16-GAP-02370":{"line":2369,"offset":410504,"length":159,"previous":"M16-GAP-02369","next":"M16-GAP-02371"},"M16-GAP-02371":{"line":2370,"offset":410663,"length":160,"previous":"M16-GAP-02370","next":"M16-GAP-02372"},"M16-GAP-02372":{"line":2371,"offset":410823,"length":157,"previous":"M16-GAP-02371","next":"M16-GAP-02373"},"M16-GAP-02373":{"line":2372,"offset":410980,"length":162,"previous":"M16-GAP-02372","next":"M16-GAP-02374"},"M16-GAP-02374":{"line":2373,"offset":411142,"length":172,"previous":"M16-GAP-02373","next":"M16-GAP-02375"},"M16-GAP-02375":{"line":2374,"offset":411314,"length":160,"previous":"M16-GAP-02374","next":"M16-GAP-02376"},"M16-GAP-02376":{"line":2375,"offset":411474,"length":164,"previous":"M16-GAP-02375","next":"M16-GAP-02377"},"M16-GAP-02377":{"line":2376,"offset":411638,"length":164,"previous":"M16-GAP-02376","next":"M16-GAP-02378"},"M16-GAP-02378":{"line":2377,"offset":411802,"length":171,"previous":"M16-GAP-02377","next":"M16-GAP-02379"},"M16-GAP-02379":{"line":2378,"offset":411973,"length":167,"previous":"M16-GAP-02378","next":"M16-GAP-02380"},"M16-GAP-02380":{"line":2379,"offset":412140,"length":170,"previous":"M16-GAP-02379","next":"M16-GAP-02381"},"M16-GAP-02381":{"line":2380,"offset":412310,"length":166,"previous":"M16-GAP-02380","next":"M16-GAP-02382"},"M16-GAP-02382":{"line":2381,"offset":412476,"length":165,"previous":"M16-GAP-02381","next":"M16-GAP-02383"},"M16-GAP-02383":{"line":2382,"offset":412641,"length":167,"previous":"M16-GAP-02382","next":"M16-GAP-02384"},"M16-GAP-02384":{"line":2383,"offset":412808,"length":172,"previous":"M16-GAP-02383","next":"M16-GAP-02385"},"M16-GAP-02385":{"line":2384,"offset":412980,"length":165,"previous":"M16-GAP-02384","next":"M16-GAP-02386"},"M16-GAP-02386":{"line":2385,"offset":413145,"length":165,"previous":"M16-GAP-02385","next":"M16-GAP-02387"},"M16-GAP-02387":{"line":2386,"offset":413310,"length":165,"previous":"M16-GAP-02386","next":"M16-GAP-02388"},"M16-GAP-02388":{"line":2387,"offset":413475,"length":168,"previous":"M16-GAP-02387","next":"M16-GAP-02389"},"M16-GAP-02389":{"line":2388,"offset":413643,"length":167,"previous":"M16-GAP-02388","next":"M16-GAP-02390"},"M16-GAP-02390":{"line":2389,"offset":413810,"length":168,"previous":"M16-GAP-02389","next":"M16-GAP-02391"},"M16-GAP-02391":{"line":2390,"offset":413978,"length":166,"previous":"M16-GAP-02390","next":"M16-GAP-02392"},"M16-GAP-02392":{"line":2391,"offset":414144,"length":165,"previous":"M16-GAP-02391","next":"M16-GAP-02393"},"M16-GAP-02393":{"line":2392,"offset":414309,"length":172,"previous":"M16-GAP-02392","next":"M16-GAP-02394"},"M16-GAP-02394":{"line":2393,"offset":414481,"length":174,"previous":"M16-GAP-02393","next":"M16-GAP-02395"},"M16-GAP-02395":{"line":2394,"offset":414655,"length":167,"previous":"M16-GAP-02394","next":"M16-GAP-02396"},"M16-GAP-02396":{"line":2395,"offset":414822,"length":165,"previous":"M16-GAP-02395","next":"M16-GAP-02397"},"M16-GAP-02397":{"line":2396,"offset":414987,"length":167,"previous":"M16-GAP-02396","next":"M16-GAP-02398"},"M16-GAP-02398":{"line":2397,"offset":415154,"length":168,"previous":"M16-GAP-02397","next":"M16-GAP-02399"},"M16-GAP-02399":{"line":2398,"offset":415322,"length":160,"previous":"M16-GAP-02398","next":"M16-GAP-02400"},"M16-GAP-02400":{"line":2399,"offset":415482,"length":160,"previous":"M16-GAP-02399","next":"M16-GAP-02401"},"M16-GAP-02401":{"line":2400,"offset":415642,"length":158,"previous":"M16-GAP-02400","next":"M16-GAP-02402"},"M16-GAP-02402":{"line":2401,"offset":415800,"length":166,"previous":"M16-GAP-02401","next":"M16-GAP-02403"},"M16-GAP-02403":{"line":2402,"offset":415966,"length":162,"previous":"M16-GAP-02402","next":"M16-GAP-02404"},"M16-GAP-02404":{"line":2403,"offset":416128,"length":161,"previous":"M16-GAP-02403","next":"M16-GAP-02405"},"M16-GAP-02405":{"line":2404,"offset":416289,"length":163,"previous":"M16-GAP-02404","next":"M16-GAP-02406"},"M16-GAP-02406":{"line":2405,"offset":416452,"length":169,"previous":"M16-GAP-02405","next":"M16-GAP-02407"},"M16-GAP-02407":{"line":2406,"offset":416621,"length":169,"previous":"M16-GAP-02406","next":"M16-GAP-02408"},"M16-GAP-02408":{"line":2407,"offset":416790,"length":170,"previous":"M16-GAP-02407","next":"M16-GAP-02409"},"M16-GAP-02409":{"line":2408,"offset":416960,"length":167,"previous":"M16-GAP-02408","next":"M16-GAP-02410"},"M16-GAP-02410":{"line":2409,"offset":417127,"length":175,"previous":"M16-GAP-02409","next":"M16-GAP-02411"},"M16-GAP-02411":{"line":2410,"offset":417302,"length":168,"previous":"M16-GAP-02410","next":"M16-GAP-02412"},"M16-GAP-02412":{"line":2411,"offset":417470,"length":162,"previous":"M16-GAP-02411","next":"M16-GAP-02413"},"M16-GAP-02413":{"line":2412,"offset":417632,"length":169,"previous":"M16-GAP-02412","next":"M16-GAP-02414"},"M16-GAP-02414":{"line":2413,"offset":417801,"length":165,"previous":"M16-GAP-02413","next":"M16-GAP-02415"},"M16-GAP-02415":{"line":2414,"offset":417966,"length":166,"previous":"M16-GAP-02414","next":"M16-GAP-02416"},"M16-GAP-02416":{"line":2415,"offset":418132,"length":174,"previous":"M16-GAP-02415","next":"M16-GAP-02417"},"M16-GAP-02417":{"line":2416,"offset":418306,"length":185,"previous":"M16-GAP-02416","next":"M16-GAP-02418"},"M16-GAP-02418":{"line":2417,"offset":418491,"length":188,"previous":"M16-GAP-02417","next":"M16-GAP-02419"},"M16-GAP-02419":{"line":2418,"offset":418679,"length":172,"previous":"M16-GAP-02418","next":"M16-GAP-02420"},"M16-GAP-02420":{"line":2419,"offset":418851,"length":181,"previous":"M16-GAP-02419","next":"M16-GAP-02421"},"M16-GAP-02421":{"line":2420,"offset":419032,"length":177,"previous":"M16-GAP-02420","next":"M16-GAP-02422"},"M16-GAP-02422":{"line":2421,"offset":419209,"length":169,"previous":"M16-GAP-02421","next":"M16-GAP-02423"},"M16-GAP-02423":{"line":2422,"offset":419378,"length":168,"previous":"M16-GAP-02422","next":"M16-GAP-02424"},"M16-GAP-02424":{"line":2423,"offset":419546,"length":166,"previous":"M16-GAP-02423","next":"M16-GAP-02425"},"M16-GAP-02425":{"line":2424,"offset":419712,"length":163,"previous":"M16-GAP-02424","next":"M16-GAP-02426"},"M16-GAP-02426":{"line":2425,"offset":419875,"length":168,"previous":"M16-GAP-02425","next":"M16-GAP-02427"},"M16-GAP-02427":{"line":2426,"offset":420043,"length":191,"previous":"M16-GAP-02426","next":"M16-GAP-02428"},"M16-GAP-02428":{"line":2427,"offset":420234,"length":191,"previous":"M16-GAP-02427","next":"M16-GAP-02429"},"M16-GAP-02429":{"line":2428,"offset":420425,"length":187,"previous":"M16-GAP-02428","next":"M16-GAP-02430"},"M16-GAP-02430":{"line":2429,"offset":420612,"length":194,"previous":"M16-GAP-02429","next":"M16-GAP-02431"},"M16-GAP-02431":{"line":2430,"offset":420806,"length":161,"previous":"M16-GAP-02430","next":"M16-GAP-02432"},"M16-GAP-02432":{"line":2431,"offset":420967,"length":173,"previous":"M16-GAP-02431","next":"M16-GAP-02433"},"M16-GAP-02433":{"line":2432,"offset":421140,"length":167,"previous":"M16-GAP-02432","next":"M16-GAP-02434"},"M16-GAP-02434":{"line":2433,"offset":421307,"length":179,"previous":"M16-GAP-02433","next":"M16-GAP-02435"},"M16-GAP-02435":{"line":2434,"offset":421486,"length":162,"previous":"M16-GAP-02434","next":"M16-GAP-02436"},"M16-GAP-02436":{"line":2435,"offset":421648,"length":166,"previous":"M16-GAP-02435","next":"M16-GAP-02437"},"M16-GAP-02437":{"line":2436,"offset":421814,"length":166,"previous":"M16-GAP-02436","next":"M16-GAP-02438"},"M16-GAP-02438":{"line":2437,"offset":421980,"length":168,"previous":"M16-GAP-02437","next":"M16-GAP-02439"},"M16-GAP-02439":{"line":2438,"offset":422148,"length":173,"previous":"M16-GAP-02438","next":"M16-GAP-02440"},"M16-GAP-02440":{"line":2439,"offset":422321,"length":166,"previous":"M16-GAP-02439","next":"M16-GAP-02441"},"M16-GAP-02441":{"line":2440,"offset":422487,"length":174,"previous":"M16-GAP-02440","next":"M16-GAP-02442"},"M16-GAP-02442":{"line":2441,"offset":422661,"length":183,"previous":"M16-GAP-02441","next":"M16-GAP-02443"},"M16-GAP-02443":{"line":2442,"offset":422844,"length":169,"previous":"M16-GAP-02442","next":"M16-GAP-02444"},"M16-GAP-02444":{"line":2443,"offset":423013,"length":171,"previous":"M16-GAP-02443","next":"M16-GAP-02445"},"M16-GAP-02445":{"line":2444,"offset":423184,"length":164,"previous":"M16-GAP-02444","next":"M16-GAP-02446"},"M16-GAP-02446":{"line":2445,"offset":423348,"length":167,"previous":"M16-GAP-02445","next":"M16-GAP-02447"},"M16-GAP-02447":{"line":2446,"offset":423515,"length":170,"previous":"M16-GAP-02446","next":"M16-GAP-02448"},"M16-GAP-02448":{"line":2447,"offset":423685,"length":164,"previous":"M16-GAP-02447","next":"M16-GAP-02449"},"M16-GAP-02449":{"line":2448,"offset":423849,"length":168,"previous":"M16-GAP-02448","next":"M16-GAP-02450"},"M16-GAP-02450":{"line":2449,"offset":424017,"length":171,"previous":"M16-GAP-02449","next":"M16-GAP-02451"},"M16-GAP-02451":{"line":2450,"offset":424188,"length":170,"previous":"M16-GAP-02450","next":"M16-GAP-02452"},"M16-GAP-02452":{"line":2451,"offset":424358,"length":169,"previous":"M16-GAP-02451","next":"M16-GAP-02453"},"M16-GAP-02453":{"line":2452,"offset":424527,"length":168,"previous":"M16-GAP-02452","next":"M16-GAP-02454"},"M16-GAP-02454":{"line":2453,"offset":424695,"length":179,"previous":"M16-GAP-02453","next":"M16-GAP-02455"},"M16-GAP-02455":{"line":2454,"offset":424874,"length":179,"previous":"M16-GAP-02454","next":"M16-GAP-02456"},"M16-GAP-02456":{"line":2455,"offset":425053,"length":177,"previous":"M16-GAP-02455","next":"M16-GAP-02457"},"M16-GAP-02457":{"line":2456,"offset":425230,"length":181,"previous":"M16-GAP-02456","next":"M16-GAP-02458"},"M16-GAP-02458":{"line":2457,"offset":425411,"length":181,"previous":"M16-GAP-02457","next":"M16-GAP-02459"},"M16-GAP-02459":{"line":2458,"offset":425592,"length":181,"previous":"M16-GAP-02458","next":"M16-GAP-02460"},"M16-GAP-02460":{"line":2459,"offset":425773,"length":179,"previous":"M16-GAP-02459","next":"M16-GAP-02461"},"M16-GAP-02461":{"line":2460,"offset":425952,"length":176,"previous":"M16-GAP-02460","next":"M16-GAP-02462"},"M16-GAP-02462":{"line":2461,"offset":426128,"length":172,"previous":"M16-GAP-02461","next":"M16-GAP-02463"},"M16-GAP-02463":{"line":2462,"offset":426300,"length":169,"previous":"M16-GAP-02462","next":"M16-GAP-02464"},"M16-GAP-02464":{"line":2463,"offset":426469,"length":177,"previous":"M16-GAP-02463","next":"M16-GAP-02465"},"M16-GAP-02465":{"line":2464,"offset":426646,"length":166,"previous":"M16-GAP-02464","next":"M16-GAP-02466"},"M16-GAP-02466":{"line":2465,"offset":426812,"length":167,"previous":"M16-GAP-02465","next":"M16-GAP-02467"},"M16-GAP-02467":{"line":2466,"offset":426979,"length":169,"previous":"M16-GAP-02466","next":"M16-GAP-02468"},"M16-GAP-02468":{"line":2467,"offset":427148,"length":176,"previous":"M16-GAP-02467","next":"M16-GAP-02469"},"M16-GAP-02469":{"line":2468,"offset":427324,"length":176,"previous":"M16-GAP-02468","next":"M16-GAP-02470"},"M16-GAP-02470":{"line":2469,"offset":427500,"length":174,"previous":"M16-GAP-02469","next":"M16-GAP-02471"},"M16-GAP-02471":{"line":2470,"offset":427674,"length":174,"previous":"M16-GAP-02470","next":"M16-GAP-02472"},"M16-GAP-02472":{"line":2471,"offset":427848,"length":173,"previous":"M16-GAP-02471","next":"M16-GAP-02473"},"M16-GAP-02473":{"line":2472,"offset":428021,"length":177,"previous":"M16-GAP-02472","next":"M16-GAP-02474"},"M16-GAP-02474":{"line":2473,"offset":428198,"length":168,"previous":"M16-GAP-02473","next":"M16-GAP-02475"},"M16-GAP-02475":{"line":2474,"offset":428366,"length":166,"previous":"M16-GAP-02474","next":"M16-GAP-02476"},"M16-GAP-02476":{"line":2475,"offset":428532,"length":173,"previous":"M16-GAP-02475","next":"M16-GAP-02477"},"M16-GAP-02477":{"line":2476,"offset":428705,"length":167,"previous":"M16-GAP-02476","next":"M16-GAP-02478"},"M16-GAP-02478":{"line":2477,"offset":428872,"length":171,"previous":"M16-GAP-02477","next":"M16-GAP-02479"},"M16-GAP-02479":{"line":2478,"offset":429043,"length":162,"previous":"M16-GAP-02478","next":"M16-GAP-02480"},"M16-GAP-02480":{"line":2479,"offset":429205,"length":162,"previous":"M16-GAP-02479","next":"M16-GAP-02481"},"M16-GAP-02481":{"line":2480,"offset":429367,"length":169,"previous":"M16-GAP-02480","next":"M16-GAP-02482"},"M16-GAP-02482":{"line":2481,"offset":429536,"length":176,"previous":"M16-GAP-02481","next":"M16-GAP-02483"},"M16-GAP-02483":{"line":2482,"offset":429712,"length":160,"previous":"M16-GAP-02482","next":"M16-GAP-02484"},"M16-GAP-02484":{"line":2483,"offset":429872,"length":166,"previous":"M16-GAP-02483","next":"M16-GAP-02485"},"M16-GAP-02485":{"line":2484,"offset":430038,"length":181,"previous":"M16-GAP-02484","next":"M16-GAP-02486"},"M16-GAP-02486":{"line":2485,"offset":430219,"length":178,"previous":"M16-GAP-02485","next":"M16-GAP-02487"},"M16-GAP-02487":{"line":2486,"offset":430397,"length":163,"previous":"M16-GAP-02486","next":"M16-GAP-02488"},"M16-GAP-02488":{"line":2487,"offset":430560,"length":167,"previous":"M16-GAP-02487","next":"M16-GAP-02489"},"M16-GAP-02489":{"line":2488,"offset":430727,"length":164,"previous":"M16-GAP-02488","next":"M16-GAP-02490"},"M16-GAP-02490":{"line":2489,"offset":430891,"length":172,"previous":"M16-GAP-02489","next":"M16-GAP-02491"},"M16-GAP-02491":{"line":2490,"offset":431063,"length":175,"previous":"M16-GAP-02490","next":"M16-GAP-02492"},"M16-GAP-02492":{"line":2491,"offset":431238,"length":184,"previous":"M16-GAP-02491","next":"M16-GAP-02493"},"M16-GAP-02493":{"line":2492,"offset":431422,"length":173,"previous":"M16-GAP-02492","next":"M16-GAP-02494"},"M16-GAP-02494":{"line":2493,"offset":431595,"length":172,"previous":"M16-GAP-02493","next":"M16-GAP-02495"},"M16-GAP-02495":{"line":2494,"offset":431767,"length":171,"previous":"M16-GAP-02494","next":"M16-GAP-02496"},"M16-GAP-02496":{"line":2495,"offset":431938,"length":171,"previous":"M16-GAP-02495","next":"M16-GAP-02497"},"M16-GAP-02497":{"line":2496,"offset":432109,"length":173,"previous":"M16-GAP-02496","next":"M16-GAP-02498"},"M16-GAP-02498":{"line":2497,"offset":432282,"length":170,"previous":"M16-GAP-02497","next":"M16-GAP-02499"},"M16-GAP-02499":{"line":2498,"offset":432452,"length":173,"previous":"M16-GAP-02498","next":"M16-GAP-02500"},"M16-GAP-02500":{"line":2499,"offset":432625,"length":171,"previous":"M16-GAP-02499","next":"M16-GAP-02501"},"M16-GAP-02501":{"line":2500,"offset":432796,"length":173,"previous":"M16-GAP-02500","next":"M16-GAP-02502"},"M16-GAP-02502":{"line":2501,"offset":432969,"length":170,"previous":"M16-GAP-02501","next":"M16-GAP-02503"},"M16-GAP-02503":{"line":2502,"offset":433139,"length":171,"previous":"M16-GAP-02502","next":"M16-GAP-02504"},"M16-GAP-02504":{"line":2503,"offset":433310,"length":168,"previous":"M16-GAP-02503","next":"M16-GAP-02505"},"M16-GAP-02505":{"line":2504,"offset":433478,"length":169,"previous":"M16-GAP-02504","next":"M16-GAP-02506"},"M16-GAP-02506":{"line":2505,"offset":433647,"length":172,"previous":"M16-GAP-02505","next":"M16-GAP-02507"},"M16-GAP-02507":{"line":2506,"offset":433819,"length":171,"previous":"M16-GAP-02506","next":"M16-GAP-02508"},"M16-GAP-02508":{"line":2507,"offset":433990,"length":168,"previous":"M16-GAP-02507","next":"M16-GAP-02509"},"M16-GAP-02509":{"line":2508,"offset":434158,"length":173,"previous":"M16-GAP-02508","next":"M16-GAP-02510"},"M16-GAP-02510":{"line":2509,"offset":434331,"length":164,"previous":"M16-GAP-02509","next":"M16-GAP-02511"},"M16-GAP-02511":{"line":2510,"offset":434495,"length":162,"previous":"M16-GAP-02510","next":"M16-GAP-02512"},"M16-GAP-02512":{"line":2511,"offset":434657,"length":169,"previous":"M16-GAP-02511","next":"M16-GAP-02513"},"M16-GAP-02513":{"line":2512,"offset":434826,"length":180,"previous":"M16-GAP-02512","next":"M16-GAP-02514"},"M16-GAP-02514":{"line":2513,"offset":435006,"length":169,"previous":"M16-GAP-02513","next":"M16-GAP-02515"},"M16-GAP-02515":{"line":2514,"offset":435175,"length":170,"previous":"M16-GAP-02514","next":"M16-GAP-02516"},"M16-GAP-02516":{"line":2515,"offset":435345,"length":164,"previous":"M16-GAP-02515","next":"M16-GAP-02517"},"M16-GAP-02517":{"line":2516,"offset":435509,"length":178,"previous":"M16-GAP-02516","next":"M16-GAP-02518"},"M16-GAP-02518":{"line":2517,"offset":435687,"length":178,"previous":"M16-GAP-02517","next":"M16-GAP-02519"},"M16-GAP-02519":{"line":2518,"offset":435865,"length":172,"previous":"M16-GAP-02518","next":"M16-GAP-02520"},"M16-GAP-02520":{"line":2519,"offset":436037,"length":180,"previous":"M16-GAP-02519","next":"M16-GAP-02521"},"M16-GAP-02521":{"line":2520,"offset":436217,"length":183,"previous":"M16-GAP-02520","next":"M16-GAP-02522"},"M16-GAP-02522":{"line":2521,"offset":436400,"length":181,"previous":"M16-GAP-02521","next":"M16-GAP-02523"},"M16-GAP-02523":{"line":2522,"offset":436581,"length":174,"previous":"M16-GAP-02522","next":"M16-GAP-02524"},"M16-GAP-02524":{"line":2523,"offset":436755,"length":177,"previous":"M16-GAP-02523","next":"M16-GAP-02525"},"M16-GAP-02525":{"line":2524,"offset":436932,"length":164,"previous":"M16-GAP-02524","next":"M16-GAP-02526"},"M16-GAP-02526":{"line":2525,"offset":437096,"length":166,"previous":"M16-GAP-02525","next":"M16-GAP-02527"},"M16-GAP-02527":{"line":2526,"offset":437262,"length":158,"previous":"M16-GAP-02526","next":"M16-GAP-02528"},"M16-GAP-02528":{"line":2527,"offset":437420,"length":171,"previous":"M16-GAP-02527","next":"M16-GAP-02529"},"M16-GAP-02529":{"line":2528,"offset":437591,"length":164,"previous":"M16-GAP-02528","next":"M16-GAP-02530"},"M16-GAP-02530":{"line":2529,"offset":437755,"length":164,"previous":"M16-GAP-02529","next":"M16-GAP-02531"},"M16-GAP-02531":{"line":2530,"offset":437919,"length":167,"previous":"M16-GAP-02530","next":"M16-GAP-02532"},"M16-GAP-02532":{"line":2531,"offset":438086,"length":174,"previous":"M16-GAP-02531","next":"M16-GAP-02533"},"M16-GAP-02533":{"line":2532,"offset":438260,"length":171,"previous":"M16-GAP-02532","next":"M16-GAP-02534"},"M16-GAP-02534":{"line":2533,"offset":438431,"length":171,"previous":"M16-GAP-02533","next":"M16-GAP-02535"},"M16-GAP-02535":{"line":2534,"offset":438602,"length":173,"previous":"M16-GAP-02534","next":"M16-GAP-02536"},"M16-GAP-02536":{"line":2535,"offset":438775,"length":178,"previous":"M16-GAP-02535","next":"M16-GAP-02537"},"M16-GAP-02537":{"line":2536,"offset":438953,"length":167,"previous":"M16-GAP-02536","next":"M16-GAP-02538"},"M16-GAP-02538":{"line":2537,"offset":439120,"length":166,"previous":"M16-GAP-02537","next":"M16-GAP-02539"},"M16-GAP-02539":{"line":2538,"offset":439286,"length":163,"previous":"M16-GAP-02538","next":"M16-GAP-02540"},"M16-GAP-02540":{"line":2539,"offset":439449,"length":164,"previous":"M16-GAP-02539","next":"M16-GAP-02541"},"M16-GAP-02541":{"line":2540,"offset":439613,"length":164,"previous":"M16-GAP-02540","next":"M16-GAP-02542"},"M16-GAP-02542":{"line":2541,"offset":439777,"length":174,"previous":"M16-GAP-02541","next":"M16-GAP-02543"},"M16-GAP-02543":{"line":2542,"offset":439951,"length":177,"previous":"M16-GAP-02542","next":"M16-GAP-02544"},"M16-GAP-02544":{"line":2543,"offset":440128,"length":168,"previous":"M16-GAP-02543","next":"M16-GAP-02545"},"M16-GAP-02545":{"line":2544,"offset":440296,"length":169,"previous":"M16-GAP-02544","next":"M16-GAP-02546"},"M16-GAP-02546":{"line":2545,"offset":440465,"length":168,"previous":"M16-GAP-02545","next":"M16-GAP-02547"},"M16-GAP-02547":{"line":2546,"offset":440633,"length":179,"previous":"M16-GAP-02546","next":"M16-GAP-02548"},"M16-GAP-02548":{"line":2547,"offset":440812,"length":169,"previous":"M16-GAP-02547","next":"M16-GAP-02549"},"M16-GAP-02549":{"line":2548,"offset":440981,"length":175,"previous":"M16-GAP-02548","next":"M16-GAP-02550"},"M16-GAP-02550":{"line":2549,"offset":441156,"length":171,"previous":"M16-GAP-02549","next":"M16-GAP-02551"},"M16-GAP-02551":{"line":2550,"offset":441327,"length":166,"previous":"M16-GAP-02550","next":"M16-GAP-02552"},"M16-GAP-02552":{"line":2551,"offset":441493,"length":168,"previous":"M16-GAP-02551","next":"M16-GAP-02553"},"M16-GAP-02553":{"line":2552,"offset":441661,"length":175,"previous":"M16-GAP-02552","next":"M16-GAP-02554"},"M16-GAP-02554":{"line":2553,"offset":441836,"length":175,"previous":"M16-GAP-02553","next":"M16-GAP-02555"},"M16-GAP-02555":{"line":2554,"offset":442011,"length":166,"previous":"M16-GAP-02554","next":"M16-GAP-02556"},"M16-GAP-02556":{"line":2555,"offset":442177,"length":167,"previous":"M16-GAP-02555","next":"M16-GAP-02557"},"M16-GAP-02557":{"line":2556,"offset":442344,"length":167,"previous":"M16-GAP-02556","next":"M16-GAP-02558"},"M16-GAP-02558":{"line":2557,"offset":442511,"length":171,"previous":"M16-GAP-02557","next":"M16-GAP-02559"},"M16-GAP-02559":{"line":2558,"offset":442682,"length":174,"previous":"M16-GAP-02558","next":"M16-GAP-02560"},"M16-GAP-02560":{"line":2559,"offset":442856,"length":166,"previous":"M16-GAP-02559","next":"M16-GAP-02561"},"M16-GAP-02561":{"line":2560,"offset":443022,"length":169,"previous":"M16-GAP-02560","next":"M16-GAP-02562"},"M16-GAP-02562":{"line":2561,"offset":443191,"length":170,"previous":"M16-GAP-02561","next":"M16-GAP-02563"},"M16-GAP-02563":{"line":2562,"offset":443361,"length":168,"previous":"M16-GAP-02562","next":"M16-GAP-02564"},"M16-GAP-02564":{"line":2563,"offset":443529,"length":167,"previous":"M16-GAP-02563","next":"M16-GAP-02565"},"M16-GAP-02565":{"line":2564,"offset":443696,"length":167,"previous":"M16-GAP-02564","next":"M16-GAP-02566"},"M16-GAP-02566":{"line":2565,"offset":443863,"length":167,"previous":"M16-GAP-02565","next":"M16-GAP-02567"},"M16-GAP-02567":{"line":2566,"offset":444030,"length":165,"previous":"M16-GAP-02566","next":"M16-GAP-02568"},"M16-GAP-02568":{"line":2567,"offset":444195,"length":169,"previous":"M16-GAP-02567","next":"M16-GAP-02569"},"M16-GAP-02569":{"line":2568,"offset":444364,"length":172,"previous":"M16-GAP-02568","next":"M16-GAP-02570"},"M16-GAP-02570":{"line":2569,"offset":444536,"length":167,"previous":"M16-GAP-02569","next":"M16-GAP-02571"},"M16-GAP-02571":{"line":2570,"offset":444703,"length":177,"previous":"M16-GAP-02570","next":"M16-GAP-02572"},"M16-GAP-02572":{"line":2571,"offset":444880,"length":160,"previous":"M16-GAP-02571","next":"M16-GAP-02573"},"M16-GAP-02573":{"line":2572,"offset":445040,"length":166,"previous":"M16-GAP-02572","next":"M16-GAP-02574"},"M16-GAP-02574":{"line":2573,"offset":445206,"length":164,"previous":"M16-GAP-02573","next":"M16-GAP-02575"},"M16-GAP-02575":{"line":2574,"offset":445370,"length":164,"previous":"M16-GAP-02574","next":"M16-GAP-02576"},"M16-GAP-02576":{"line":2575,"offset":445534,"length":161,"previous":"M16-GAP-02575","next":"M16-GAP-02577"},"M16-GAP-02577":{"line":2576,"offset":445695,"length":176,"previous":"M16-GAP-02576","next":"M16-GAP-02578"},"M16-GAP-02578":{"line":2577,"offset":445871,"length":168,"previous":"M16-GAP-02577","next":"M16-GAP-02579"},"M16-GAP-02579":{"line":2578,"offset":446039,"length":171,"previous":"M16-GAP-02578","next":"M16-GAP-02580"},"M16-GAP-02580":{"line":2579,"offset":446210,"length":161,"previous":"M16-GAP-02579","next":"M16-GAP-02581"},"M16-GAP-02581":{"line":2580,"offset":446371,"length":174,"previous":"M16-GAP-02580","next":"M16-GAP-02582"},"M16-GAP-02582":{"line":2581,"offset":446545,"length":168,"previous":"M16-GAP-02581","next":"M16-GAP-02583"},"M16-GAP-02583":{"line":2582,"offset":446713,"length":162,"previous":"M16-GAP-02582","next":"M16-GAP-02584"},"M16-GAP-02584":{"line":2583,"offset":446875,"length":169,"previous":"M16-GAP-02583","next":"M16-GAP-02585"},"M16-GAP-02585":{"line":2584,"offset":447044,"length":166,"previous":"M16-GAP-02584","next":"M16-GAP-02586"},"M16-GAP-02586":{"line":2585,"offset":447210,"length":178,"previous":"M16-GAP-02585","next":"M16-GAP-02587"},"M16-GAP-02587":{"line":2586,"offset":447388,"length":164,"previous":"M16-GAP-02586","next":"M16-GAP-02588"},"M16-GAP-02588":{"line":2587,"offset":447552,"length":169,"previous":"M16-GAP-02587","next":"M16-GAP-02589"},"M16-GAP-02589":{"line":2588,"offset":447721,"length":164,"previous":"M16-GAP-02588","next":"M16-GAP-02590"},"M16-GAP-02590":{"line":2589,"offset":447885,"length":176,"previous":"M16-GAP-02589","next":"M16-GAP-02591"},"M16-GAP-02591":{"line":2590,"offset":448061,"length":167,"previous":"M16-GAP-02590","next":"M16-GAP-02592"},"M16-GAP-02592":{"line":2591,"offset":448228,"length":178,"previous":"M16-GAP-02591","next":"M16-GAP-02593"},"M16-GAP-02593":{"line":2592,"offset":448406,"length":170,"previous":"M16-GAP-02592","next":"M16-GAP-02594"},"M16-GAP-02594":{"line":2593,"offset":448576,"length":176,"previous":"M16-GAP-02593","next":"M16-GAP-02595"},"M16-GAP-02595":{"line":2594,"offset":448752,"length":177,"previous":"M16-GAP-02594","next":"M16-GAP-02596"},"M16-GAP-02596":{"line":2595,"offset":448929,"length":177,"previous":"M16-GAP-02595","next":"M16-GAP-02597"},"M16-GAP-02597":{"line":2596,"offset":449106,"length":179,"previous":"M16-GAP-02596","next":"M16-GAP-02598"},"M16-GAP-02598":{"line":2597,"offset":449285,"length":160,"previous":"M16-GAP-02597","next":"M16-GAP-02599"},"M16-GAP-02599":{"line":2598,"offset":449445,"length":156,"previous":"M16-GAP-02598","next":"M16-GAP-02600"},"M16-GAP-02600":{"line":2599,"offset":449601,"length":163,"previous":"M16-GAP-02599","next":"M16-GAP-02601"},"M16-GAP-02601":{"line":2600,"offset":449764,"length":167,"previous":"M16-GAP-02600","next":"M16-GAP-02602"},"M16-GAP-02602":{"line":2601,"offset":449931,"length":165,"previous":"M16-GAP-02601","next":"M16-GAP-02603"},"M16-GAP-02603":{"line":2602,"offset":450096,"length":163,"previous":"M16-GAP-02602","next":"M16-GAP-02604"},"M16-GAP-02604":{"line":2603,"offset":450259,"length":166,"previous":"M16-GAP-02603","next":"M16-GAP-02605"},"M16-GAP-02605":{"line":2604,"offset":450425,"length":163,"previous":"M16-GAP-02604","next":"M16-GAP-02606"},"M16-GAP-02606":{"line":2605,"offset":450588,"length":167,"previous":"M16-GAP-02605","next":"M16-GAP-02607"},"M16-GAP-02607":{"line":2606,"offset":450755,"length":162,"previous":"M16-GAP-02606","next":"M16-GAP-02608"},"M16-GAP-02608":{"line":2607,"offset":450917,"length":161,"previous":"M16-GAP-02607","next":"M16-GAP-02609"},"M16-GAP-02609":{"line":2608,"offset":451078,"length":171,"previous":"M16-GAP-02608","next":"M16-GAP-02610"},"M16-GAP-02610":{"line":2609,"offset":451249,"length":166,"previous":"M16-GAP-02609","next":"M16-GAP-02611"},"M16-GAP-02611":{"line":2610,"offset":451415,"length":162,"previous":"M16-GAP-02610","next":"M16-GAP-02612"},"M16-GAP-02612":{"line":2611,"offset":451577,"length":164,"previous":"M16-GAP-02611","next":"M16-GAP-02613"},"M16-GAP-02613":{"line":2612,"offset":451741,"length":165,"previous":"M16-GAP-02612","next":"M16-GAP-02614"},"M16-GAP-02614":{"line":2613,"offset":451906,"length":162,"previous":"M16-GAP-02613","next":"M16-GAP-02615"},"M16-GAP-02615":{"line":2614,"offset":452068,"length":166,"previous":"M16-GAP-02614","next":"M16-GAP-02616"},"M16-GAP-02616":{"line":2615,"offset":452234,"length":161,"previous":"M16-GAP-02615","next":"M16-GAP-02617"},"M16-GAP-02617":{"line":2616,"offset":452395,"length":165,"previous":"M16-GAP-02616","next":"M16-GAP-02618"},"M16-GAP-02618":{"line":2617,"offset":452560,"length":162,"previous":"M16-GAP-02617","next":"M16-GAP-02619"},"M16-GAP-02619":{"line":2618,"offset":452722,"length":165,"previous":"M16-GAP-02618","next":"M16-GAP-02620"},"M16-GAP-02620":{"line":2619,"offset":452887,"length":166,"previous":"M16-GAP-02619","next":"M16-GAP-02621"},"M16-GAP-02621":{"line":2620,"offset":453053,"length":165,"previous":"M16-GAP-02620","next":"M16-GAP-02622"},"M16-GAP-02622":{"line":2621,"offset":453218,"length":163,"previous":"M16-GAP-02621","next":"M16-GAP-02623"},"M16-GAP-02623":{"line":2622,"offset":453381,"length":167,"previous":"M16-GAP-02622","next":"M16-GAP-02624"},"M16-GAP-02624":{"line":2623,"offset":453548,"length":164,"previous":"M16-GAP-02623","next":"M16-GAP-02625"},"M16-GAP-02625":{"line":2624,"offset":453712,"length":165,"previous":"M16-GAP-02624","next":"M16-GAP-02626"},"M16-GAP-02626":{"line":2625,"offset":453877,"length":167,"previous":"M16-GAP-02625","next":"M16-GAP-02627"},"M16-GAP-02627":{"line":2626,"offset":454044,"length":162,"previous":"M16-GAP-02626","next":"M16-GAP-02628"},"M16-GAP-02628":{"line":2627,"offset":454206,"length":162,"previous":"M16-GAP-02627","next":"M16-GAP-02629"},"M16-GAP-02629":{"line":2628,"offset":454368,"length":163,"previous":"M16-GAP-02628","next":"M16-GAP-02630"},"M16-GAP-02630":{"line":2629,"offset":454531,"length":162,"previous":"M16-GAP-02629","next":"M16-GAP-02631"},"M16-GAP-02631":{"line":2630,"offset":454693,"length":164,"previous":"M16-GAP-02630","next":"M16-GAP-02632"},"M16-GAP-02632":{"line":2631,"offset":454857,"length":161,"previous":"M16-GAP-02631","next":"M16-GAP-02633"},"M16-GAP-02633":{"line":2632,"offset":455018,"length":164,"previous":"M16-GAP-02632","next":"M16-GAP-02634"},"M16-GAP-02634":{"line":2633,"offset":455182,"length":163,"previous":"M16-GAP-02633","next":"M16-GAP-02635"},"M16-GAP-02635":{"line":2634,"offset":455345,"length":170,"previous":"M16-GAP-02634","next":"M16-GAP-02636"},"M16-GAP-02636":{"line":2635,"offset":455515,"length":166,"previous":"M16-GAP-02635","next":"M16-GAP-02637"},"M16-GAP-02637":{"line":2636,"offset":455681,"length":162,"previous":"M16-GAP-02636","next":"M16-GAP-02638"},"M16-GAP-02638":{"line":2637,"offset":455843,"length":156,"previous":"M16-GAP-02637","next":"M16-GAP-02639"},"M16-GAP-02639":{"line":2638,"offset":455999,"length":165,"previous":"M16-GAP-02638","next":"M16-GAP-02640"},"M16-GAP-02640":{"line":2639,"offset":456164,"length":160,"previous":"M16-GAP-02639","next":"M16-GAP-02641"},"M16-GAP-02641":{"line":2640,"offset":456324,"length":165,"previous":"M16-GAP-02640","next":"M16-GAP-02642"},"M16-GAP-02642":{"line":2641,"offset":456489,"length":161,"previous":"M16-GAP-02641","next":"M16-GAP-02643"},"M16-GAP-02643":{"line":2642,"offset":456650,"length":159,"previous":"M16-GAP-02642","next":"M16-GAP-02644"},"M16-GAP-02644":{"line":2643,"offset":456809,"length":151,"previous":"M16-GAP-02643","next":"M16-GAP-02645"},"M16-GAP-02645":{"line":2644,"offset":456960,"length":170,"previous":"M16-GAP-02644","next":"M16-GAP-02646"},"M16-GAP-02646":{"line":2645,"offset":457130,"length":164,"previous":"M16-GAP-02645","next":"M16-GAP-02647"},"M16-GAP-02647":{"line":2646,"offset":457294,"length":165,"previous":"M16-GAP-02646","next":"M16-GAP-02648"},"M16-GAP-02648":{"line":2647,"offset":457459,"length":155,"previous":"M16-GAP-02647","next":"M16-GAP-02649"},"M16-GAP-02649":{"line":2648,"offset":457614,"length":156,"previous":"M16-GAP-02648","next":"M16-GAP-02650"},"M16-GAP-02650":{"line":2649,"offset":457770,"length":155,"previous":"M16-GAP-02649","next":"M16-GAP-02651"},"M16-GAP-02651":{"line":2650,"offset":457925,"length":160,"previous":"M16-GAP-02650","next":"M16-GAP-02652"},"M16-GAP-02652":{"line":2651,"offset":458085,"length":165,"previous":"M16-GAP-02651","next":"M16-GAP-02653"},"M16-GAP-02653":{"line":2652,"offset":458250,"length":163,"previous":"M16-GAP-02652","next":"M16-GAP-02654"},"M16-GAP-02654":{"line":2653,"offset":458413,"length":164,"previous":"M16-GAP-02653","next":"M16-GAP-02655"},"M16-GAP-02655":{"line":2654,"offset":458577,"length":156,"previous":"M16-GAP-02654","next":"M16-GAP-02656"},"M16-GAP-02656":{"line":2655,"offset":458733,"length":162,"previous":"M16-GAP-02655","next":"M16-GAP-02657"},"M16-GAP-02657":{"line":2656,"offset":458895,"length":158,"previous":"M16-GAP-02656","next":"M16-GAP-02658"},"M16-GAP-02658":{"line":2657,"offset":459053,"length":159,"previous":"M16-GAP-02657","next":"M16-GAP-02659"},"M16-GAP-02659":{"line":2658,"offset":459212,"length":172,"previous":"M16-GAP-02658","next":"M16-GAP-02660"},"M16-GAP-02660":{"line":2659,"offset":459384,"length":161,"previous":"M16-GAP-02659","next":"M16-GAP-02661"},"M16-GAP-02661":{"line":2660,"offset":459545,"length":166,"previous":"M16-GAP-02660","next":"M16-GAP-02662"},"M16-GAP-02662":{"line":2661,"offset":459711,"length":158,"previous":"M16-GAP-02661","next":"M16-GAP-02663"},"M16-GAP-02663":{"line":2662,"offset":459869,"length":167,"previous":"M16-GAP-02662","next":"M16-GAP-02664"},"M16-GAP-02664":{"line":2663,"offset":460036,"length":157,"previous":"M16-GAP-02663","next":"M16-GAP-02665"},"M16-GAP-02665":{"line":2664,"offset":460193,"length":162,"previous":"M16-GAP-02664","next":"M16-GAP-02666"},"M16-GAP-02666":{"line":2665,"offset":460355,"length":157,"previous":"M16-GAP-02665","next":"M16-GAP-02667"},"M16-GAP-02667":{"line":2666,"offset":460512,"length":159,"previous":"M16-GAP-02666","next":"M17-GAP-00001"},"M17-GAP-00001":{"line":2667,"offset":460671,"length":161,"previous":"M16-GAP-02667","next":"M17-GAP-00002"},"M17-GAP-00002":{"line":2668,"offset":460832,"length":163,"previous":"M17-GAP-00001","next":"M17-GAP-00003"},"M17-GAP-00003":{"line":2669,"offset":460995,"length":168,"previous":"M17-GAP-00002","next":"M17-GAP-00004"},"M17-GAP-00004":{"line":2670,"offset":461163,"length":163,"previous":"M17-GAP-00003","next":"M17-GAP-00005"},"M17-GAP-00005":{"line":2671,"offset":461326,"length":163,"previous":"M17-GAP-00004","next":"M17-GAP-00006"},"M17-GAP-00006":{"line":2672,"offset":461489,"length":168,"previous":"M17-GAP-00005","next":"M17-GAP-00007"},"M17-GAP-00007":{"line":2673,"offset":461657,"length":168,"previous":"M17-GAP-00006","next":"M17-GAP-00008"},"M17-GAP-00008":{"line":2674,"offset":461825,"length":165,"previous":"M17-GAP-00007","next":"M17-GAP-00009"},"M17-GAP-00009":{"line":2675,"offset":461990,"length":170,"previous":"M17-GAP-00008","next":"M17-GAP-00010"},"M17-GAP-00010":{"line":2676,"offset":462160,"length":167,"previous":"M17-GAP-00009","next":"M17-GAP-00011"},"M17-GAP-00011":{"line":2677,"offset":462327,"length":160,"previous":"M17-GAP-00010","next":"M17-GAP-00012"},"M17-GAP-00012":{"line":2678,"offset":462487,"length":166,"previous":"M17-GAP-00011","next":"M17-GAP-00013"},"M17-GAP-00013":{"line":2679,"offset":462653,"length":167,"previous":"M17-GAP-00012","next":"M17-GAP-00014"},"M17-GAP-00014":{"line":2680,"offset":462820,"length":173,"previous":"M17-GAP-00013","next":"M17-GAP-00015"},"M17-GAP-00015":{"line":2681,"offset":462993,"length":157,"previous":"M17-GAP-00014","next":"M17-GAP-00016"},"M17-GAP-00016":{"line":2682,"offset":463150,"length":169,"previous":"M17-GAP-00015","next":"M17-GAP-00017"},"M17-GAP-00017":{"line":2683,"offset":463319,"length":169,"previous":"M17-GAP-00016","next":"M17-GAP-00018"},"M17-GAP-00018":{"line":2684,"offset":463488,"length":169,"previous":"M17-GAP-00017","next":"M17-GAP-00019"},"M17-GAP-00019":{"line":2685,"offset":463657,"length":166,"previous":"M17-GAP-00018","next":"M17-GAP-00020"},"M17-GAP-00020":{"line":2686,"offset":463823,"length":167,"previous":"M17-GAP-00019","next":"M17-GAP-00021"},"M17-GAP-00021":{"line":2687,"offset":463990,"length":170,"previous":"M17-GAP-00020","next":"M17-GAP-00022"},"M17-GAP-00022":{"line":2688,"offset":464160,"length":168,"previous":"M17-GAP-00021","next":"M17-GAP-00023"},"M17-GAP-00023":{"line":2689,"offset":464328,"length":160,"previous":"M17-GAP-00022","next":"M17-GAP-00024"},"M17-GAP-00024":{"line":2690,"offset":464488,"length":165,"previous":"M17-GAP-00023","next":"M17-GAP-00025"},"M17-GAP-00025":{"line":2691,"offset":464653,"length":164,"previous":"M17-GAP-00024","next":"M17-GAP-00026"},"M17-GAP-00026":{"line":2692,"offset":464817,"length":165,"previous":"M17-GAP-00025","next":"M17-GAP-00027"},"M17-GAP-00027":{"line":2693,"offset":464982,"length":163,"previous":"M17-GAP-00026","next":"M17-GAP-00028"},"M17-GAP-00028":{"line":2694,"offset":465145,"length":164,"previous":"M17-GAP-00027","next":"M17-GAP-00029"},"M17-GAP-00029":{"line":2695,"offset":465309,"length":170,"previous":"M17-GAP-00028","next":"M18-GAP-00001"},"M18-GAP-00001":{"line":2696,"offset":465479,"length":188,"previous":"M17-GAP-00029","next":"M18-GAP-00002"},"M18-GAP-00002":{"line":2697,"offset":465667,"length":191,"previous":"M18-GAP-00001","next":"M18-GAP-00003"},"M18-GAP-00003":{"line":2698,"offset":465858,"length":192,"previous":"M18-GAP-00002","next":"M18-GAP-00004"},"M18-GAP-00004":{"line":2699,"offset":466050,"length":189,"previous":"M18-GAP-00003","next":"M18-GAP-00005"},"M18-GAP-00005":{"line":2700,"offset":466239,"length":183,"previous":"M18-GAP-00004","next":"M18-GAP-00006"},"M18-GAP-00006":{"line":2701,"offset":466422,"length":188,"previous":"M18-GAP-00005","next":"M18-GAP-00007"},"M18-GAP-00007":{"line":2702,"offset":466610,"length":189,"previous":"M18-GAP-00006","next":"M18-GAP-00008"},"M18-GAP-00008":{"line":2703,"offset":466799,"length":186,"previous":"M18-GAP-00007","next":"M18-GAP-00009"},"M18-GAP-00009":{"line":2704,"offset":466985,"length":193,"previous":"M18-GAP-00008","next":"M18-GAP-00010"},"M18-GAP-00010":{"line":2705,"offset":467178,"length":191,"previous":"M18-GAP-00009","next":"M18-GAP-00011"},"M18-GAP-00011":{"line":2706,"offset":467369,"length":190,"previous":"M18-GAP-00010","next":"M18-GAP-00012"},"M18-GAP-00012":{"line":2707,"offset":467559,"length":191,"previous":"M18-GAP-00011","next":"M18-GAP-00013"},"M18-GAP-00013":{"line":2708,"offset":467750,"length":194,"previous":"M18-GAP-00012","next":"M18-GAP-00014"},"M18-GAP-00014":{"line":2709,"offset":467944,"length":189,"previous":"M18-GAP-00013","next":"M18-GAP-00015"},"M18-GAP-00015":{"line":2710,"offset":468133,"length":189,"previous":"M18-GAP-00014","next":"M18-GAP-00016"},"M18-GAP-00016":{"line":2711,"offset":468322,"length":191,"previous":"M18-GAP-00015","next":"M18-GAP-00017"},"M18-GAP-00017":{"line":2712,"offset":468513,"length":196,"previous":"M18-GAP-00016","next":"M18-GAP-00018"},"M18-GAP-00018":{"line":2713,"offset":468709,"length":195,"previous":"M18-GAP-00017","next":"M18-GAP-00019"},"M18-GAP-00019":{"line":2714,"offset":468904,"length":187,"previous":"M18-GAP-00018","next":"M18-GAP-00020"},"M18-GAP-00020":{"line":2715,"offset":469091,"length":188,"previous":"M18-GAP-00019","next":"M18-GAP-00021"},"M18-GAP-00021":{"line":2716,"offset":469279,"length":183,"previous":"M18-GAP-00020","next":"M18-GAP-00022"},"M18-GAP-00022":{"line":2717,"offset":469462,"length":190,"previous":"M18-GAP-00021","next":"M18-GAP-00023"},"M18-GAP-00023":{"line":2718,"offset":469652,"length":192,"previous":"M18-GAP-00022","next":"M18-GAP-00024"},"M18-GAP-00024":{"line":2719,"offset":469844,"length":187,"previous":"M18-GAP-00023","next":"M18-GAP-00025"},"M18-GAP-00025":{"line":2720,"offset":470031,"length":184,"previous":"M18-GAP-00024","next":"M18-GAP-00026"},"M18-GAP-00026":{"line":2721,"offset":470215,"length":186,"previous":"M18-GAP-00025","next":"M18-GAP-00027"},"M18-GAP-00027":{"line":2722,"offset":470401,"length":186,"previous":"M18-GAP-00026","next":"M18-GAP-00028"},"M18-GAP-00028":{"line":2723,"offset":470587,"length":188,"previous":"M18-GAP-00027","next":"M18-GAP-00029"},"M18-GAP-00029":{"line":2724,"offset":470775,"length":188,"previous":"M18-GAP-00028","next":"M18-GAP-00030"},"M18-GAP-00030":{"line":2725,"offset":470963,"length":190,"previous":"M18-GAP-00029","next":"M18-GAP-00031"},"M18-GAP-00031":{"line":2726,"offset":471153,"length":187,"previous":"M18-GAP-00030","next":"M18-GAP-00032"},"M18-GAP-00032":{"line":2727,"offset":471340,"length":192,"previous":"M18-GAP-00031","next":"M18-GAP-00033"},"M18-GAP-00033":{"line":2728,"offset":471532,"length":193,"previous":"M18-GAP-00032","next":"M18-GAP-00034"},"M18-GAP-00034":{"line":2729,"offset":471725,"length":190,"previous":"M18-GAP-00033","next":"M18-GAP-00035"},"M18-GAP-00035":{"line":2730,"offset":471915,"length":187,"previous":"M18-GAP-00034","next":"M18-GAP-00036"},"M18-GAP-00036":{"line":2731,"offset":472102,"length":185,"previous":"M18-GAP-00035","next":"M18-GAP-00037"},"M18-GAP-00037":{"line":2732,"offset":472287,"length":183,"previous":"M18-GAP-00036","next":"M18-GAP-00038"},"M18-GAP-00038":{"line":2733,"offset":472470,"length":184,"previous":"M18-GAP-00037","next":"M18-GAP-00039"},"M18-GAP-00039":{"line":2734,"offset":472654,"length":184,"previous":"M18-GAP-00038","next":"M18-GAP-00040"},"M18-GAP-00040":{"line":2735,"offset":472838,"length":189,"previous":"M18-GAP-00039","next":"M18-GAP-00041"},"M18-GAP-00041":{"line":2736,"offset":473027,"length":185,"previous":"M18-GAP-00040","next":"M18-GAP-00042"},"M18-GAP-00042":{"line":2737,"offset":473212,"length":185,"previous":"M18-GAP-00041","next":"M18-GAP-00043"},"M18-GAP-00043":{"line":2738,"offset":473397,"length":184,"previous":"M18-GAP-00042","next":"M18-GAP-00044"},"M18-GAP-00044":{"line":2739,"offset":473581,"length":195,"previous":"M18-GAP-00043","next":"M18-GAP-00045"},"M18-GAP-00045":{"line":2740,"offset":473776,"length":188,"previous":"M18-GAP-00044","next":"M18-GAP-00046"},"M18-GAP-00046":{"line":2741,"offset":473964,"length":186,"previous":"M18-GAP-00045","next":"M18-GAP-00047"},"M18-GAP-00047":{"line":2742,"offset":474150,"length":185,"previous":"M18-GAP-00046","next":"M18-GAP-00048"},"M18-GAP-00048":{"line":2743,"offset":474335,"length":185,"previous":"M18-GAP-00047","next":"M18-GAP-00049"},"M18-GAP-00049":{"line":2744,"offset":474520,"length":191,"previous":"M18-GAP-00048","next":"M18-GAP-00050"},"M18-GAP-00050":{"line":2745,"offset":474711,"length":187,"previous":"M18-GAP-00049","next":"M18-GAP-00051"},"M18-GAP-00051":{"line":2746,"offset":474898,"length":187,"previous":"M18-GAP-00050","next":"M18-GAP-00052"},"M18-GAP-00052":{"line":2747,"offset":475085,"length":185,"previous":"M18-GAP-00051","next":"M18-GAP-00053"},"M18-GAP-00053":{"line":2748,"offset":475270,"length":188,"previous":"M18-GAP-00052","next":"M18-GAP-00054"},"M18-GAP-00054":{"line":2749,"offset":475458,"length":184,"previous":"M18-GAP-00053","next":"M18-GAP-00055"},"M18-GAP-00055":{"line":2750,"offset":475642,"length":183,"previous":"M18-GAP-00054","next":"M18-GAP-00056"},"M18-GAP-00056":{"line":2751,"offset":475825,"length":188,"previous":"M18-GAP-00055","next":"M18-GAP-00057"},"M18-GAP-00057":{"line":2752,"offset":476013,"length":188,"previous":"M18-GAP-00056","next":"M18-GAP-00058"},"M18-GAP-00058":{"line":2753,"offset":476201,"length":194,"previous":"M18-GAP-00057","next":"M18-GAP-00059"},"M18-GAP-00059":{"line":2754,"offset":476395,"length":185,"previous":"M18-GAP-00058","next":"M18-GAP-00060"},"M18-GAP-00060":{"line":2755,"offset":476580,"length":188,"previous":"M18-GAP-00059","next":"M18-GAP-00061"},"M18-GAP-00061":{"line":2756,"offset":476768,"length":189,"previous":"M18-GAP-00060","next":"M18-GAP-00062"},"M18-GAP-00062":{"line":2757,"offset":476957,"length":187,"previous":"M18-GAP-00061","next":"M18-GAP-00063"},"M18-GAP-00063":{"line":2758,"offset":477144,"length":195,"previous":"M18-GAP-00062","next":"M18-GAP-00064"},"M18-GAP-00064":{"line":2759,"offset":477339,"length":188,"previous":"M18-GAP-00063","next":"M18-GAP-00065"},"M18-GAP-00065":{"line":2760,"offset":477527,"length":188,"previous":"M18-GAP-00064","next":"M18-GAP-00066"},"M18-GAP-00066":{"line":2761,"offset":477715,"length":182,"previous":"M18-GAP-00065","next":"M18-GAP-00067"},"M18-GAP-00067":{"line":2762,"offset":477897,"length":186,"previous":"M18-GAP-00066","next":"M18-GAP-00068"},"M18-GAP-00068":{"line":2763,"offset":478083,"length":186,"previous":"M18-GAP-00067","next":"M18-GAP-00069"},"M18-GAP-00069":{"line":2764,"offset":478269,"length":194,"previous":"M18-GAP-00068","next":"M18-GAP-00070"},"M18-GAP-00070":{"line":2765,"offset":478463,"length":185,"previous":"M18-GAP-00069","next":"M18-GAP-00071"},"M18-GAP-00071":{"line":2766,"offset":478648,"length":184,"previous":"M18-GAP-00070","next":"M18-GAP-00072"},"M18-GAP-00072":{"line":2767,"offset":478832,"length":188,"previous":"M18-GAP-00071","next":"M18-GAP-00073"},"M18-GAP-00073":{"line":2768,"offset":479020,"length":192,"previous":"M18-GAP-00072","next":"M18-GAP-00074"},"M18-GAP-00074":{"line":2769,"offset":479212,"length":197,"previous":"M18-GAP-00073","next":"M18-GAP-00075"},"M18-GAP-00075":{"line":2770,"offset":479409,"length":187,"previous":"M18-GAP-00074","next":"M18-GAP-00076"},"M18-GAP-00076":{"line":2771,"offset":479596,"length":184,"previous":"M18-GAP-00075","next":"M18-GAP-00077"},"M18-GAP-00077":{"line":2772,"offset":479780,"length":188,"previous":"M18-GAP-00076","next":"M18-GAP-00078"},"M18-GAP-00078":{"line":2773,"offset":479968,"length":192,"previous":"M18-GAP-00077","next":"M18-GAP-00079"},"M18-GAP-00079":{"line":2774,"offset":480160,"length":185,"previous":"M18-GAP-00078","next":"M18-GAP-00080"},"M18-GAP-00080":{"line":2775,"offset":480345,"length":189,"previous":"M18-GAP-00079","next":"M18-GAP-00081"},"M18-GAP-00081":{"line":2776,"offset":480534,"length":183,"previous":"M18-GAP-00080","next":"M18-GAP-00082"},"M18-GAP-00082":{"line":2777,"offset":480717,"length":186,"previous":"M18-GAP-00081","next":"M18-GAP-00083"},"M18-GAP-00083":{"line":2778,"offset":480903,"length":187,"previous":"M18-GAP-00082","next":"M18-GAP-00084"},"M18-GAP-00084":{"line":2779,"offset":481090,"length":188,"previous":"M18-GAP-00083","next":"M18-GAP-00085"},"M18-GAP-00085":{"line":2780,"offset":481278,"length":188,"previous":"M18-GAP-00084","next":"M18-GAP-00086"},"M18-GAP-00086":{"line":2781,"offset":481466,"length":186,"previous":"M18-GAP-00085","next":"M18-GAP-00087"},"M18-GAP-00087":{"line":2782,"offset":481652,"length":185,"previous":"M18-GAP-00086","next":"M18-GAP-00088"},"M18-GAP-00088":{"line":2783,"offset":481837,"length":187,"previous":"M18-GAP-00087","next":"M18-GAP-00089"},"M18-GAP-00089":{"line":2784,"offset":482024,"length":188,"previous":"M18-GAP-00088","next":"M18-GAP-00090"},"M18-GAP-00090":{"line":2785,"offset":482212,"length":192,"previous":"M18-GAP-00089","next":"M18-GAP-00091"},"M18-GAP-00091":{"line":2786,"offset":482404,"length":191,"previous":"M18-GAP-00090","next":"M18-GAP-00092"},"M18-GAP-00092":{"line":2787,"offset":482595,"length":177,"previous":"M18-GAP-00091","next":"M18-GAP-00093"},"M18-GAP-00093":{"line":2788,"offset":482772,"length":186,"previous":"M18-GAP-00092","next":"M18-GAP-00094"},"M18-GAP-00094":{"line":2789,"offset":482958,"length":181,"previous":"M18-GAP-00093","next":"M18-GAP-00095"},"M18-GAP-00095":{"line":2790,"offset":483139,"length":181,"previous":"M18-GAP-00094","next":"M18-GAP-00096"},"M18-GAP-00096":{"line":2791,"offset":483320,"length":183,"previous":"M18-GAP-00095","next":"M18-GAP-00097"},"M18-GAP-00097":{"line":2792,"offset":483503,"length":189,"previous":"M18-GAP-00096","next":"M18-GAP-00098"},"M18-GAP-00098":{"line":2793,"offset":483692,"length":186,"previous":"M18-GAP-00097","next":"M18-GAP-00099"},"M18-GAP-00099":{"line":2794,"offset":483878,"length":191,"previous":"M18-GAP-00098","next":"M18-GAP-00100"},"M18-GAP-00100":{"line":2795,"offset":484069,"length":190,"previous":"M18-GAP-00099","next":"M18-GAP-00101"},"M18-GAP-00101":{"line":2796,"offset":484259,"length":191,"previous":"M18-GAP-00100","next":"M18-GAP-00102"},"M18-GAP-00102":{"line":2797,"offset":484450,"length":187,"previous":"M18-GAP-00101","next":"M18-GAP-00103"},"M18-GAP-00103":{"line":2798,"offset":484637,"length":183,"previous":"M18-GAP-00102","next":"M18-GAP-00104"},"M18-GAP-00104":{"line":2799,"offset":484820,"length":186,"previous":"M18-GAP-00103","next":"M18-GAP-00105"},"M18-GAP-00105":{"line":2800,"offset":485006,"length":186,"previous":"M18-GAP-00104","next":"M18-GAP-00106"},"M18-GAP-00106":{"line":2801,"offset":485192,"length":188,"previous":"M18-GAP-00105","next":"M18-GAP-00107"},"M18-GAP-00107":{"line":2802,"offset":485380,"length":189,"previous":"M18-GAP-00106","next":"M18-GAP-00108"},"M18-GAP-00108":{"line":2803,"offset":485569,"length":181,"previous":"M18-GAP-00107","next":"M18-GAP-00109"},"M18-GAP-00109":{"line":2804,"offset":485750,"length":195,"previous":"M18-GAP-00108","next":"M18-GAP-00110"},"M18-GAP-00110":{"line":2805,"offset":485945,"length":197,"previous":"M18-GAP-00109","next":"M18-GAP-00111"},"M18-GAP-00111":{"line":2806,"offset":486142,"length":184,"previous":"M18-GAP-00110","next":"M18-GAP-00112"},"M18-GAP-00112":{"line":2807,"offset":486326,"length":185,"previous":"M18-GAP-00111","next":"M18-GAP-00113"},"M18-GAP-00113":{"line":2808,"offset":486511,"length":200,"previous":"M18-GAP-00112","next":"M18-GAP-00114"},"M18-GAP-00114":{"line":2809,"offset":486711,"length":193,"previous":"M18-GAP-00113","next":"M18-GAP-00115"},"M18-GAP-00115":{"line":2810,"offset":486904,"length":191,"previous":"M18-GAP-00114","next":"M18-GAP-00116"},"M18-GAP-00116":{"line":2811,"offset":487095,"length":200,"previous":"M18-GAP-00115","next":"M18-GAP-00117"},"M18-GAP-00117":{"line":2812,"offset":487295,"length":193,"previous":"M18-GAP-00116","next":"M18-GAP-00118"},"M18-GAP-00118":{"line":2813,"offset":487488,"length":188,"previous":"M18-GAP-00117","next":"M18-GAP-00119"},"M18-GAP-00119":{"line":2814,"offset":487676,"length":184,"previous":"M18-GAP-00118","next":"M18-GAP-00120"},"M18-GAP-00120":{"line":2815,"offset":487860,"length":188,"previous":"M18-GAP-00119","next":"M18-GAP-00121"},"M18-GAP-00121":{"line":2816,"offset":488048,"length":182,"previous":"M18-GAP-00120","next":"M18-GAP-00122"},"M18-GAP-00122":{"line":2817,"offset":488230,"length":184,"previous":"M18-GAP-00121","next":"M18-GAP-00123"},"M18-GAP-00123":{"line":2818,"offset":488414,"length":186,"previous":"M18-GAP-00122","next":"M18-GAP-00124"},"M18-GAP-00124":{"line":2819,"offset":488600,"length":193,"previous":"M18-GAP-00123","next":"M18-GAP-00125"},"M18-GAP-00125":{"line":2820,"offset":488793,"length":194,"previous":"M18-GAP-00124","next":"M18-GAP-00126"},"M18-GAP-00126":{"line":2821,"offset":488987,"length":187,"previous":"M18-GAP-00125","next":"M18-GAP-00127"},"M18-GAP-00127":{"line":2822,"offset":489174,"length":195,"previous":"M18-GAP-00126","next":"M18-GAP-00128"},"M18-GAP-00128":{"line":2823,"offset":489369,"length":197,"previous":"M18-GAP-00127","next":"M18-GAP-00129"},"M18-GAP-00129":{"line":2824,"offset":489566,"length":196,"previous":"M18-GAP-00128","next":"M18-GAP-00130"},"M18-GAP-00130":{"line":2825,"offset":489762,"length":181,"previous":"M18-GAP-00129","next":"M18-GAP-00131"},"M18-GAP-00131":{"line":2826,"offset":489943,"length":190,"previous":"M18-GAP-00130","next":"M18-GAP-00132"},"M18-GAP-00132":{"line":2827,"offset":490133,"length":190,"previous":"M18-GAP-00131","next":"M18-GAP-00133"},"M18-GAP-00133":{"line":2828,"offset":490323,"length":193,"previous":"M18-GAP-00132","next":"M18-GAP-00134"},"M18-GAP-00134":{"line":2829,"offset":490516,"length":186,"previous":"M18-GAP-00133","next":"M18-GAP-00135"},"M18-GAP-00135":{"line":2830,"offset":490702,"length":186,"previous":"M18-GAP-00134","next":"M18-GAP-00136"},"M18-GAP-00136":{"line":2831,"offset":490888,"length":190,"previous":"M18-GAP-00135","next":"M18-GAP-00137"},"M18-GAP-00137":{"line":2832,"offset":491078,"length":184,"previous":"M18-GAP-00136","next":"M18-GAP-00138"},"M18-GAP-00138":{"line":2833,"offset":491262,"length":185,"previous":"M18-GAP-00137","next":"M18-GAP-00139"},"M18-GAP-00139":{"line":2834,"offset":491447,"length":185,"previous":"M18-GAP-00138","next":"M18-GAP-00140"},"M18-GAP-00140":{"line":2835,"offset":491632,"length":185,"previous":"M18-GAP-00139","next":"M18-GAP-00141"},"M18-GAP-00141":{"line":2836,"offset":491817,"length":187,"previous":"M18-GAP-00140","next":"M18-GAP-00142"},"M18-GAP-00142":{"line":2837,"offset":492004,"length":186,"previous":"M18-GAP-00141","next":"M18-GAP-00143"},"M18-GAP-00143":{"line":2838,"offset":492190,"length":184,"previous":"M18-GAP-00142","next":"M18-GAP-00144"},"M18-GAP-00144":{"line":2839,"offset":492374,"length":184,"previous":"M18-GAP-00143","next":"M18-GAP-00145"},"M18-GAP-00145":{"line":2840,"offset":492558,"length":186,"previous":"M18-GAP-00144","next":"M18-GAP-00146"},"M18-GAP-00146":{"line":2841,"offset":492744,"length":182,"previous":"M18-GAP-00145","next":"M18-GAP-00147"},"M18-GAP-00147":{"line":2842,"offset":492926,"length":184,"previous":"M18-GAP-00146","next":"M18-GAP-00148"},"M18-GAP-00148":{"line":2843,"offset":493110,"length":183,"previous":"M18-GAP-00147","next":"M18-GAP-00149"},"M18-GAP-00149":{"line":2844,"offset":493293,"length":182,"previous":"M18-GAP-00148","next":"M18-GAP-00150"},"M18-GAP-00150":{"line":2845,"offset":493475,"length":200,"previous":"M18-GAP-00149","next":"M18-GAP-00151"},"M18-GAP-00151":{"line":2846,"offset":493675,"length":201,"previous":"M18-GAP-00150","next":"M18-GAP-00152"},"M18-GAP-00152":{"line":2847,"offset":493876,"length":191,"previous":"M18-GAP-00151","next":"M18-GAP-00153"},"M18-GAP-00153":{"line":2848,"offset":494067,"length":190,"previous":"M18-GAP-00152","next":"M18-GAP-00154"},"M18-GAP-00154":{"line":2849,"offset":494257,"length":190,"previous":"M18-GAP-00153","next":"M18-GAP-00155"},"M18-GAP-00155":{"line":2850,"offset":494447,"length":193,"previous":"M18-GAP-00154","next":"M18-GAP-00156"},"M18-GAP-00156":{"line":2851,"offset":494640,"length":185,"previous":"M18-GAP-00155","next":"M18-GAP-00157"},"M18-GAP-00157":{"line":2852,"offset":494825,"length":182,"previous":"M18-GAP-00156","next":"M18-GAP-00158"},"M18-GAP-00158":{"line":2853,"offset":495007,"length":184,"previous":"M18-GAP-00157","next":"M18-GAP-00159"},"M18-GAP-00159":{"line":2854,"offset":495191,"length":187,"previous":"M18-GAP-00158","next":"M18-GAP-00160"},"M18-GAP-00160":{"line":2855,"offset":495378,"length":193,"previous":"M18-GAP-00159","next":"M18-GAP-00161"},"M18-GAP-00161":{"line":2856,"offset":495571,"length":183,"previous":"M18-GAP-00160","next":"M18-GAP-00162"},"M18-GAP-00162":{"line":2857,"offset":495754,"length":181,"previous":"M18-GAP-00161","next":"M18-GAP-00163"},"M18-GAP-00163":{"line":2858,"offset":495935,"length":181,"previous":"M18-GAP-00162","next":"M18-GAP-00164"},"M18-GAP-00164":{"line":2859,"offset":496116,"length":191,"previous":"M18-GAP-00163","next":"M18-GAP-00165"},"M18-GAP-00165":{"line":2860,"offset":496307,"length":187,"previous":"M18-GAP-00164","next":"M18-GAP-00166"},"M18-GAP-00166":{"line":2861,"offset":496494,"length":185,"previous":"M18-GAP-00165","next":"M18-GAP-00167"},"M18-GAP-00167":{"line":2862,"offset":496679,"length":181,"previous":"M18-GAP-00166","next":"M18-GAP-00168"},"M18-GAP-00168":{"line":2863,"offset":496860,"length":186,"previous":"M18-GAP-00167","next":"M18-GAP-00169"},"M18-GAP-00169":{"line":2864,"offset":497046,"length":181,"previous":"M18-GAP-00168","next":"M18-GAP-00170"},"M18-GAP-00170":{"line":2865,"offset":497227,"length":183,"previous":"M18-GAP-00169","next":"M18-GAP-00171"},"M18-GAP-00171":{"line":2866,"offset":497410,"length":182,"previous":"M18-GAP-00170","next":"M18-GAP-00172"},"M18-GAP-00172":{"line":2867,"offset":497592,"length":183,"previous":"M18-GAP-00171","next":"M18-GAP-00173"},"M18-GAP-00173":{"line":2868,"offset":497775,"length":185,"previous":"M18-GAP-00172","next":"M18-GAP-00174"},"M18-GAP-00174":{"line":2869,"offset":497960,"length":185,"previous":"M18-GAP-00173","next":"M18-GAP-00175"},"M18-GAP-00175":{"line":2870,"offset":498145,"length":178,"previous":"M18-GAP-00174","next":"M18-GAP-00176"},"M18-GAP-00176":{"line":2871,"offset":498323,"length":182,"previous":"M18-GAP-00175","next":"M18-GAP-00177"},"M18-GAP-00177":{"line":2872,"offset":498505,"length":185,"previous":"M18-GAP-00176","next":"M18-GAP-00178"},"M18-GAP-00178":{"line":2873,"offset":498690,"length":182,"previous":"M18-GAP-00177","next":"M18-GAP-00179"},"M18-GAP-00179":{"line":2874,"offset":498872,"length":182,"previous":"M18-GAP-00178","next":"M18-GAP-00180"},"M18-GAP-00180":{"line":2875,"offset":499054,"length":182,"previous":"M18-GAP-00179","next":"M18-GAP-00181"},"M18-GAP-00181":{"line":2876,"offset":499236,"length":182,"previous":"M18-GAP-00180","next":"M18-GAP-00182"},"M18-GAP-00182":{"line":2877,"offset":499418,"length":183,"previous":"M18-GAP-00181","next":"M18-GAP-00183"},"M18-GAP-00183":{"line":2878,"offset":499601,"length":182,"previous":"M18-GAP-00182","next":"M18-GAP-00184"},"M18-GAP-00184":{"line":2879,"offset":499783,"length":187,"previous":"M18-GAP-00183","next":"M18-GAP-00185"},"M18-GAP-00185":{"line":2880,"offset":499970,"length":184,"previous":"M18-GAP-00184","next":"M18-GAP-00186"},"M18-GAP-00186":{"line":2881,"offset":500154,"length":190,"previous":"M18-GAP-00185","next":"M18-GAP-00187"},"M18-GAP-00187":{"line":2882,"offset":500344,"length":188,"previous":"M18-GAP-00186","next":"M18-GAP-00188"},"M18-GAP-00188":{"line":2883,"offset":500532,"length":198,"previous":"M18-GAP-00187","next":"M18-GAP-00189"},"M18-GAP-00189":{"line":2884,"offset":500730,"length":187,"previous":"M18-GAP-00188","next":"M18-GAP-00190"},"M18-GAP-00190":{"line":2885,"offset":500917,"length":188,"previous":"M18-GAP-00189","next":"M18-GAP-00191"},"M18-GAP-00191":{"line":2886,"offset":501105,"length":182,"previous":"M18-GAP-00190","next":"M18-GAP-00192"},"M18-GAP-00192":{"line":2887,"offset":501287,"length":180,"previous":"M18-GAP-00191","next":"M18-GAP-00193"},"M18-GAP-00193":{"line":2888,"offset":501467,"length":183,"previous":"M18-GAP-00192","next":"M18-GAP-00194"},"M18-GAP-00194":{"line":2889,"offset":501650,"length":183,"previous":"M18-GAP-00193","next":"M18-GAP-00195"},"M18-GAP-00195":{"line":2890,"offset":501833,"length":192,"previous":"M18-GAP-00194","next":"M18-GAP-00196"},"M18-GAP-00196":{"line":2891,"offset":502025,"length":195,"previous":"M18-GAP-00195","next":"M18-GAP-00197"},"M18-GAP-00197":{"line":2892,"offset":502220,"length":194,"previous":"M18-GAP-00196","next":"M18-GAP-00198"},"M18-GAP-00198":{"line":2893,"offset":502414,"length":191,"previous":"M18-GAP-00197","next":"M18-GAP-00199"},"M18-GAP-00199":{"line":2894,"offset":502605,"length":186,"previous":"M18-GAP-00198","next":"M18-GAP-00200"},"M18-GAP-00200":{"line":2895,"offset":502791,"length":191,"previous":"M18-GAP-00199","next":"M18-GAP-00201"},"M18-GAP-00201":{"line":2896,"offset":502982,"length":191,"previous":"M18-GAP-00200","next":"M18-GAP-00202"},"M18-GAP-00202":{"line":2897,"offset":503173,"length":195,"previous":"M18-GAP-00201","next":"M18-GAP-00203"},"M18-GAP-00203":{"line":2898,"offset":503368,"length":194,"previous":"M18-GAP-00202","next":"M18-GAP-00204"},"M18-GAP-00204":{"line":2899,"offset":503562,"length":190,"previous":"M18-GAP-00203","next":"M18-GAP-00205"},"M18-GAP-00205":{"line":2900,"offset":503752,"length":194,"previous":"M18-GAP-00204","next":"M18-GAP-00206"},"M18-GAP-00206":{"line":2901,"offset":503946,"length":195,"previous":"M18-GAP-00205","next":"M18-GAP-00207"},"M18-GAP-00207":{"line":2902,"offset":504141,"length":188,"previous":"M18-GAP-00206","next":"M18-GAP-00208"},"M18-GAP-00208":{"line":2903,"offset":504329,"length":197,"previous":"M18-GAP-00207","next":"M18-GAP-00209"},"M18-GAP-00209":{"line":2904,"offset":504526,"length":192,"previous":"M18-GAP-00208","next":"M18-GAP-00210"},"M18-GAP-00210":{"line":2905,"offset":504718,"length":197,"previous":"M18-GAP-00209","next":"M18-GAP-00211"},"M18-GAP-00211":{"line":2906,"offset":504915,"length":184,"previous":"M18-GAP-00210","next":"M18-GAP-00212"},"M18-GAP-00212":{"line":2907,"offset":505099,"length":184,"previous":"M18-GAP-00211","next":"M18-GAP-00213"},"M18-GAP-00213":{"line":2908,"offset":505283,"length":186,"previous":"M18-GAP-00212","next":"M18-GAP-00214"},"M18-GAP-00214":{"line":2909,"offset":505469,"length":184,"previous":"M18-GAP-00213","next":"M18-GAP-00215"},"M18-GAP-00215":{"line":2910,"offset":505653,"length":187,"previous":"M18-GAP-00214","next":"M18-GAP-00216"},"M18-GAP-00216":{"line":2911,"offset":505840,"length":189,"previous":"M18-GAP-00215","next":"M18-GAP-00217"},"M18-GAP-00217":{"line":2912,"offset":506029,"length":195,"previous":"M18-GAP-00216","next":"M18-GAP-00218"},"M18-GAP-00218":{"line":2913,"offset":506224,"length":190,"previous":"M18-GAP-00217","next":"M18-GAP-00219"},"M18-GAP-00219":{"line":2914,"offset":506414,"length":194,"previous":"M18-GAP-00218","next":"M18-GAP-00220"},"M18-GAP-00220":{"line":2915,"offset":506608,"length":185,"previous":"M18-GAP-00219","next":"M18-GAP-00221"},"M18-GAP-00221":{"line":2916,"offset":506793,"length":188,"previous":"M18-GAP-00220","next":"M18-GAP-00222"},"M18-GAP-00222":{"line":2917,"offset":506981,"length":189,"previous":"M18-GAP-00221","next":"M18-GAP-00223"},"M18-GAP-00223":{"line":2918,"offset":507170,"length":190,"previous":"M18-GAP-00222","next":"M18-GAP-00224"},"M18-GAP-00224":{"line":2919,"offset":507360,"length":190,"previous":"M18-GAP-00223","next":"M18-GAP-00225"},"M18-GAP-00225":{"line":2920,"offset":507550,"length":190,"previous":"M18-GAP-00224","next":"M18-GAP-00226"},"M18-GAP-00226":{"line":2921,"offset":507740,"length":183,"previous":"M18-GAP-00225","next":"M18-GAP-00227"},"M18-GAP-00227":{"line":2922,"offset":507923,"length":185,"previous":"M18-GAP-00226","next":"M18-GAP-00228"},"M18-GAP-00228":{"line":2923,"offset":508108,"length":184,"previous":"M18-GAP-00227","next":"M18-GAP-00229"},"M18-GAP-00229":{"line":2924,"offset":508292,"length":183,"previous":"M18-GAP-00228","next":"M18-GAP-00230"},"M18-GAP-00230":{"line":2925,"offset":508475,"length":190,"previous":"M18-GAP-00229","next":"M18-GAP-00231"},"M18-GAP-00231":{"line":2926,"offset":508665,"length":183,"previous":"M18-GAP-00230","next":"M18-GAP-00232"},"M18-GAP-00232":{"line":2927,"offset":508848,"length":188,"previous":"M18-GAP-00231","next":"M18-GAP-00233"},"M18-GAP-00233":{"line":2928,"offset":509036,"length":184,"previous":"M18-GAP-00232","next":"M18-GAP-00234"},"M18-GAP-00234":{"line":2929,"offset":509220,"length":184,"previous":"M18-GAP-00233","next":"M18-GAP-00235"},"M18-GAP-00235":{"line":2930,"offset":509404,"length":182,"previous":"M18-GAP-00234","next":"M18-GAP-00236"},"M18-GAP-00236":{"line":2931,"offset":509586,"length":184,"previous":"M18-GAP-00235","next":"M18-GAP-00237"},"M18-GAP-00237":{"line":2932,"offset":509770,"length":183,"previous":"M18-GAP-00236","next":"M18-GAP-00238"},"M18-GAP-00238":{"line":2933,"offset":509953,"length":181,"previous":"M18-GAP-00237","next":"M18-GAP-00239"},"M18-GAP-00239":{"line":2934,"offset":510134,"length":181,"previous":"M18-GAP-00238","next":"M18-GAP-00240"},"M18-GAP-00240":{"line":2935,"offset":510315,"length":185,"previous":"M18-GAP-00239","next":"M18-GAP-00241"},"M18-GAP-00241":{"line":2936,"offset":510500,"length":194,"previous":"M18-GAP-00240","next":"M18-GAP-00242"},"M18-GAP-00242":{"line":2937,"offset":510694,"length":181,"previous":"M18-GAP-00241","next":"M18-GAP-00243"},"M18-GAP-00243":{"line":2938,"offset":510875,"length":186,"previous":"M18-GAP-00242","next":"M18-GAP-00244"},"M18-GAP-00244":{"line":2939,"offset":511061,"length":181,"previous":"M18-GAP-00243","next":"M18-GAP-00245"},"M18-GAP-00245":{"line":2940,"offset":511242,"length":184,"previous":"M18-GAP-00244","next":"M18-GAP-00246"},"M18-GAP-00246":{"line":2941,"offset":511426,"length":190,"previous":"M18-GAP-00245","next":"M18-GAP-00247"},"M18-GAP-00247":{"line":2942,"offset":511616,"length":185,"previous":"M18-GAP-00246","next":"M18-GAP-00248"},"M18-GAP-00248":{"line":2943,"offset":511801,"length":186,"previous":"M18-GAP-00247","next":"M18-GAP-00249"},"M18-GAP-00249":{"line":2944,"offset":511987,"length":185,"previous":"M18-GAP-00248","next":"M18-GAP-00250"},"M18-GAP-00250":{"line":2945,"offset":512172,"length":185,"previous":"M18-GAP-00249","next":"M18-GAP-00251"},"M18-GAP-00251":{"line":2946,"offset":512357,"length":183,"previous":"M18-GAP-00250","next":"M18-GAP-00252"},"M18-GAP-00252":{"line":2947,"offset":512540,"length":191,"previous":"M18-GAP-00251","next":"M18-GAP-00253"},"M18-GAP-00253":{"line":2948,"offset":512731,"length":191,"previous":"M18-GAP-00252","next":"M18-GAP-00254"},"M18-GAP-00254":{"line":2949,"offset":512922,"length":179,"previous":"M18-GAP-00253","next":"M18-GAP-00255"},"M18-GAP-00255":{"line":2950,"offset":513101,"length":186,"previous":"M18-GAP-00254","next":"M18-GAP-00256"},"M18-GAP-00256":{"line":2951,"offset":513287,"length":187,"previous":"M18-GAP-00255","next":"M18-GAP-00257"},"M18-GAP-00257":{"line":2952,"offset":513474,"length":188,"previous":"M18-GAP-00256","next":"M18-GAP-00258"},"M18-GAP-00258":{"line":2953,"offset":513662,"length":189,"previous":"M18-GAP-00257","next":"M18-GAP-00259"},"M18-GAP-00259":{"line":2954,"offset":513851,"length":187,"previous":"M18-GAP-00258","next":"M18-GAP-00260"},"M18-GAP-00260":{"line":2955,"offset":514038,"length":182,"previous":"M18-GAP-00259","next":"M18-GAP-00261"},"M18-GAP-00261":{"line":2956,"offset":514220,"length":180,"previous":"M18-GAP-00260","next":"M18-GAP-00262"},"M18-GAP-00262":{"line":2957,"offset":514400,"length":189,"previous":"M18-GAP-00261","next":"M18-GAP-00263"},"M18-GAP-00263":{"line":2958,"offset":514589,"length":188,"previous":"M18-GAP-00262","next":"M18-GAP-00264"},"M18-GAP-00264":{"line":2959,"offset":514777,"length":188,"previous":"M18-GAP-00263","next":"M18-GAP-00265"},"M18-GAP-00265":{"line":2960,"offset":514965,"length":184,"previous":"M18-GAP-00264","next":"M18-GAP-00266"},"M18-GAP-00266":{"line":2961,"offset":515149,"length":185,"previous":"M18-GAP-00265","next":"M18-GAP-00267"},"M18-GAP-00267":{"line":2962,"offset":515334,"length":188,"previous":"M18-GAP-00266","next":"M18-GAP-00268"},"M18-GAP-00268":{"line":2963,"offset":515522,"length":186,"previous":"M18-GAP-00267","next":"M18-GAP-00269"},"M18-GAP-00269":{"line":2964,"offset":515708,"length":185,"previous":"M18-GAP-00268","next":"M18-GAP-00270"},"M18-GAP-00270":{"line":2965,"offset":515893,"length":188,"previous":"M18-GAP-00269","next":"M18-GAP-00271"},"M18-GAP-00271":{"line":2966,"offset":516081,"length":187,"previous":"M18-GAP-00270","next":"M18-GAP-00272"},"M18-GAP-00272":{"line":2967,"offset":516268,"length":186,"previous":"M18-GAP-00271","next":"M18-GAP-00273"},"M18-GAP-00273":{"line":2968,"offset":516454,"length":189,"previous":"M18-GAP-00272","next":"M18-GAP-00274"},"M18-GAP-00274":{"line":2969,"offset":516643,"length":184,"previous":"M18-GAP-00273","next":"M18-GAP-00275"},"M18-GAP-00275":{"line":2970,"offset":516827,"length":193,"previous":"M18-GAP-00274","next":"M18-GAP-00276"},"M18-GAP-00276":{"line":2971,"offset":517020,"length":186,"previous":"M18-GAP-00275","next":"M18-GAP-00277"},"M18-GAP-00277":{"line":2972,"offset":517206,"length":186,"previous":"M18-GAP-00276","next":"M18-GAP-00278"},"M18-GAP-00278":{"line":2973,"offset":517392,"length":184,"previous":"M18-GAP-00277","next":"M18-GAP-00279"},"M18-GAP-00279":{"line":2974,"offset":517576,"length":183,"previous":"M18-GAP-00278","next":"M18-GAP-00280"},"M18-GAP-00280":{"line":2975,"offset":517759,"length":188,"previous":"M18-GAP-00279","next":"M18-GAP-00281"},"M18-GAP-00281":{"line":2976,"offset":517947,"length":184,"previous":"M18-GAP-00280","next":"M18-GAP-00282"},"M18-GAP-00282":{"line":2977,"offset":518131,"length":186,"previous":"M18-GAP-00281","next":"M18-GAP-00283"},"M18-GAP-00283":{"line":2978,"offset":518317,"length":193,"previous":"M18-GAP-00282","next":"M18-GAP-00284"},"M18-GAP-00284":{"line":2979,"offset":518510,"length":195,"previous":"M18-GAP-00283","next":"M18-GAP-00285"},"M18-GAP-00285":{"line":2980,"offset":518705,"length":188,"previous":"M18-GAP-00284","next":"M18-GAP-00286"},"M18-GAP-00286":{"line":2981,"offset":518893,"length":186,"previous":"M18-GAP-00285","next":"M18-GAP-00287"},"M18-GAP-00287":{"line":2982,"offset":519079,"length":187,"previous":"M18-GAP-00286","next":"M18-GAP-00288"},"M18-GAP-00288":{"line":2983,"offset":519266,"length":183,"previous":"M18-GAP-00287","next":"M18-GAP-00289"},"M18-GAP-00289":{"line":2984,"offset":519449,"length":191,"previous":"M18-GAP-00288","next":"M18-GAP-00290"},"M18-GAP-00290":{"line":2985,"offset":519640,"length":189,"previous":"M18-GAP-00289","next":"M18-GAP-00291"},"M18-GAP-00291":{"line":2986,"offset":519829,"length":196,"previous":"M18-GAP-00290","next":"M18-GAP-00292"},"M18-GAP-00292":{"line":2987,"offset":520025,"length":187,"previous":"M18-GAP-00291","next":"M18-GAP-00293"},"M18-GAP-00293":{"line":2988,"offset":520212,"length":187,"previous":"M18-GAP-00292","next":"M18-GAP-00294"},"M18-GAP-00294":{"line":2989,"offset":520399,"length":185,"previous":"M18-GAP-00293","next":"M18-GAP-00295"},"M18-GAP-00295":{"line":2990,"offset":520584,"length":190,"previous":"M18-GAP-00294","next":"M18-GAP-00296"},"M18-GAP-00296":{"line":2991,"offset":520774,"length":188,"previous":"M18-GAP-00295","next":"M18-GAP-00297"},"M18-GAP-00297":{"line":2992,"offset":520962,"length":193,"previous":"M18-GAP-00296","next":"M18-GAP-00298"},"M18-GAP-00298":{"line":2993,"offset":521155,"length":193,"previous":"M18-GAP-00297","next":"M18-GAP-00299"},"M18-GAP-00299":{"line":2994,"offset":521348,"length":196,"previous":"M18-GAP-00298","next":"M18-GAP-00300"},"M18-GAP-00300":{"line":2995,"offset":521544,"length":190,"previous":"M18-GAP-00299","next":"M18-GAP-00301"},"M18-GAP-00301":{"line":2996,"offset":521734,"length":189,"previous":"M18-GAP-00300","next":"M18-GAP-00302"},"M18-GAP-00302":{"line":2997,"offset":521923,"length":178,"previous":"M18-GAP-00301","next":"M18-GAP-00303"},"M18-GAP-00303":{"line":2998,"offset":522101,"length":193,"previous":"M18-GAP-00302","next":"M18-GAP-00304"},"M18-GAP-00304":{"line":2999,"offset":522294,"length":184,"previous":"M18-GAP-00303","next":"M18-GAP-00305"},"M18-GAP-00305":{"line":3000,"offset":522478,"length":189,"previous":"M18-GAP-00304","next":"M18-GAP-00306"},"M18-GAP-00306":{"line":3001,"offset":522667,"length":186,"previous":"M18-GAP-00305","next":"M18-GAP-00307"},"M18-GAP-00307":{"line":3002,"offset":522853,"length":186,"previous":"M18-GAP-00306","next":"M18-GAP-00308"},"M18-GAP-00308":{"line":3003,"offset":523039,"length":187,"previous":"M18-GAP-00307","next":"M18-GAP-00309"},"M18-GAP-00309":{"line":3004,"offset":523226,"length":187,"previous":"M18-GAP-00308","next":"M18-GAP-00310"},"M18-GAP-00310":{"line":3005,"offset":523413,"length":184,"previous":"M18-GAP-00309","next":"M18-GAP-00311"},"M18-GAP-00311":{"line":3006,"offset":523597,"length":187,"previous":"M18-GAP-00310","next":"M18-GAP-00312"},"M18-GAP-00312":{"line":3007,"offset":523784,"length":188,"previous":"M18-GAP-00311","next":"M18-GAP-00313"},"M18-GAP-00313":{"line":3008,"offset":523972,"length":192,"previous":"M18-GAP-00312","next":"M18-GAP-00314"},"M18-GAP-00314":{"line":3009,"offset":524164,"length":188,"previous":"M18-GAP-00313","next":"M18-GAP-00315"},"M18-GAP-00315":{"line":3010,"offset":524352,"length":189,"previous":"M18-GAP-00314","next":"M18-GAP-00316"},"M18-GAP-00316":{"line":3011,"offset":524541,"length":185,"previous":"M18-GAP-00315","next":"M18-GAP-00317"},"M18-GAP-00317":{"line":3012,"offset":524726,"length":181,"previous":"M18-GAP-00316","next":"M18-GAP-00318"},"M18-GAP-00318":{"line":3013,"offset":524907,"length":185,"previous":"M18-GAP-00317","next":"M18-GAP-00319"},"M18-GAP-00319":{"line":3014,"offset":525092,"length":188,"previous":"M18-GAP-00318","next":"M18-GAP-00320"},"M18-GAP-00320":{"line":3015,"offset":525280,"length":183,"previous":"M18-GAP-00319","next":"M18-GAP-00321"},"M18-GAP-00321":{"line":3016,"offset":525463,"length":189,"previous":"M18-GAP-00320","next":"M18-GAP-00322"},"M18-GAP-00322":{"line":3017,"offset":525652,"length":192,"previous":"M18-GAP-00321","next":"M18-GAP-00323"},"M18-GAP-00323":{"line":3018,"offset":525844,"length":187,"previous":"M18-GAP-00322","next":"M18-GAP-00324"},"M18-GAP-00324":{"line":3019,"offset":526031,"length":183,"previous":"M18-GAP-00323","next":"M18-GAP-00325"},"M18-GAP-00325":{"line":3020,"offset":526214,"length":187,"previous":"M18-GAP-00324","next":"M18-GAP-00326"},"M18-GAP-00326":{"line":3021,"offset":526401,"length":187,"previous":"M18-GAP-00325","next":"M18-GAP-00327"},"M18-GAP-00327":{"line":3022,"offset":526588,"length":186,"previous":"M18-GAP-00326","next":"M18-GAP-00328"},"M18-GAP-00328":{"line":3023,"offset":526774,"length":191,"previous":"M18-GAP-00327","next":"M18-GAP-00329"},"M18-GAP-00329":{"line":3024,"offset":526965,"length":179,"previous":"M18-GAP-00328","next":"M18-GAP-00330"},"M18-GAP-00330":{"line":3025,"offset":527144,"length":182,"previous":"M18-GAP-00329","next":"M18-GAP-00331"},"M18-GAP-00331":{"line":3026,"offset":527326,"length":185,"previous":"M18-GAP-00330","next":"M18-GAP-00332"},"M18-GAP-00332":{"line":3027,"offset":527511,"length":190,"previous":"M18-GAP-00331","next":"M18-GAP-00333"},"M18-GAP-00333":{"line":3028,"offset":527701,"length":184,"previous":"M18-GAP-00332","next":"M18-GAP-00334"},"M18-GAP-00334":{"line":3029,"offset":527885,"length":190,"previous":"M18-GAP-00333","next":"M18-GAP-00335"},"M18-GAP-00335":{"line":3030,"offset":528075,"length":186,"previous":"M18-GAP-00334","next":"M18-GAP-00336"},"M18-GAP-00336":{"line":3031,"offset":528261,"length":187,"previous":"M18-GAP-00335","next":"M18-GAP-00337"},"M18-GAP-00337":{"line":3032,"offset":528448,"length":189,"previous":"M18-GAP-00336","next":"M18-GAP-00338"},"M18-GAP-00338":{"line":3033,"offset":528637,"length":191,"previous":"M18-GAP-00337","next":"M18-GAP-00339"},"M18-GAP-00339":{"line":3034,"offset":528828,"length":182,"previous":"M18-GAP-00338","next":"M18-GAP-00340"},"M18-GAP-00340":{"line":3035,"offset":529010,"length":191,"previous":"M18-GAP-00339","next":"M18-GAP-00341"},"M18-GAP-00341":{"line":3036,"offset":529201,"length":184,"previous":"M18-GAP-00340","next":"M18-GAP-00342"},"M18-GAP-00342":{"line":3037,"offset":529385,"length":182,"previous":"M18-GAP-00341","next":"M18-GAP-00343"},"M18-GAP-00343":{"line":3038,"offset":529567,"length":186,"previous":"M18-GAP-00342","next":"M18-GAP-00344"},"M18-GAP-00344":{"line":3039,"offset":529753,"length":182,"previous":"M18-GAP-00343","next":"M18-GAP-00345"},"M18-GAP-00345":{"line":3040,"offset":529935,"length":181,"previous":"M18-GAP-00344","next":"M18-GAP-00346"},"M18-GAP-00346":{"line":3041,"offset":530116,"length":187,"previous":"M18-GAP-00345","next":"M18-GAP-00347"},"M18-GAP-00347":{"line":3042,"offset":530303,"length":179,"previous":"M18-GAP-00346","next":"M18-GAP-00348"},"M18-GAP-00348":{"line":3043,"offset":530482,"length":190,"previous":"M18-GAP-00347","next":"M18-GAP-00349"},"M18-GAP-00349":{"line":3044,"offset":530672,"length":183,"previous":"M18-GAP-00348","next":"M18-GAP-00350"},"M18-GAP-00350":{"line":3045,"offset":530855,"length":185,"previous":"M18-GAP-00349","next":"M18-GAP-00351"},"M18-GAP-00351":{"line":3046,"offset":531040,"length":180,"previous":"M18-GAP-00350","next":"M18-GAP-00352"},"M18-GAP-00352":{"line":3047,"offset":531220,"length":183,"previous":"M18-GAP-00351","next":"M18-GAP-00353"},"M18-GAP-00353":{"line":3048,"offset":531403,"length":176,"previous":"M18-GAP-00352","next":"M18-GAP-00354"},"M18-GAP-00354":{"line":3049,"offset":531579,"length":183,"previous":"M18-GAP-00353","next":"M18-GAP-00355"},"M18-GAP-00355":{"line":3050,"offset":531762,"length":176,"previous":"M18-GAP-00354","next":"M18-GAP-00356"},"M18-GAP-00356":{"line":3051,"offset":531938,"length":177,"previous":"M18-GAP-00355","next":"M18-GAP-00357"},"M18-GAP-00357":{"line":3052,"offset":532115,"length":172,"previous":"M18-GAP-00356","next":"M18-GAP-00358"},"M18-GAP-00358":{"line":3053,"offset":532287,"length":176,"previous":"M18-GAP-00357","next":"M18-GAP-00359"},"M18-GAP-00359":{"line":3054,"offset":532463,"length":181,"previous":"M18-GAP-00358","next":"M18-GAP-00360"},"M18-GAP-00360":{"line":3055,"offset":532644,"length":182,"previous":"M18-GAP-00359","next":"M18-GAP-00361"},"M18-GAP-00361":{"line":3056,"offset":532826,"length":178,"previous":"M18-GAP-00360","next":"M18-GAP-00362"},"M18-GAP-00362":{"line":3057,"offset":533004,"length":176,"previous":"M18-GAP-00361","next":"M18-GAP-00363"},"M18-GAP-00363":{"line":3058,"offset":533180,"length":175,"previous":"M18-GAP-00362","next":"M18-GAP-00364"},"M18-GAP-00364":{"line":3059,"offset":533355,"length":185,"previous":"M18-GAP-00363","next":"M18-GAP-00365"},"M18-GAP-00365":{"line":3060,"offset":533540,"length":179,"previous":"M18-GAP-00364","next":"M18-GAP-00366"},"M18-GAP-00366":{"line":3061,"offset":533719,"length":181,"previous":"M18-GAP-00365","next":"M18-GAP-00367"},"M18-GAP-00367":{"line":3062,"offset":533900,"length":180,"previous":"M18-GAP-00366","next":"M18-GAP-00368"},"M18-GAP-00368":{"line":3063,"offset":534080,"length":181,"previous":"M18-GAP-00367","next":"M18-GAP-00369"},"M18-GAP-00369":{"line":3064,"offset":534261,"length":176,"previous":"M18-GAP-00368","next":"M18-GAP-00370"},"M18-GAP-00370":{"line":3065,"offset":534437,"length":175,"previous":"M18-GAP-00369","next":"M18-GAP-00371"},"M18-GAP-00371":{"line":3066,"offset":534612,"length":182,"previous":"M18-GAP-00370","next":"M18-GAP-00372"},"M18-GAP-00372":{"line":3067,"offset":534794,"length":182,"previous":"M18-GAP-00371","next":"M18-GAP-00373"},"M18-GAP-00373":{"line":3068,"offset":534976,"length":171,"previous":"M18-GAP-00372","next":"M18-GAP-00374"},"M18-GAP-00374":{"line":3069,"offset":535147,"length":177,"previous":"M18-GAP-00373","next":"M18-GAP-00375"},"M18-GAP-00375":{"line":3070,"offset":535324,"length":172,"previous":"M18-GAP-00374","next":"M18-GAP-00376"},"M18-GAP-00376":{"line":3071,"offset":535496,"length":179,"previous":"M18-GAP-00375","next":"M18-GAP-00377"},"M18-GAP-00377":{"line":3072,"offset":535675,"length":177,"previous":"M18-GAP-00376","next":"M18-GAP-00378"},"M18-GAP-00378":{"line":3073,"offset":535852,"length":179,"previous":"M18-GAP-00377","next":"M18-GAP-00379"},"M18-GAP-00379":{"line":3074,"offset":536031,"length":180,"previous":"M18-GAP-00378","next":"M18-GAP-00380"},"M18-GAP-00380":{"line":3075,"offset":536211,"length":175,"previous":"M18-GAP-00379","next":"M18-GAP-00381"},"M18-GAP-00381":{"line":3076,"offset":536386,"length":177,"previous":"M18-GAP-00380","next":"M18-GAP-00382"},"M18-GAP-00382":{"line":3077,"offset":536563,"length":174,"previous":"M18-GAP-00381","next":"M18-GAP-00383"},"M18-GAP-00383":{"line":3078,"offset":536737,"length":172,"previous":"M18-GAP-00382","next":"M18-GAP-00384"},"M18-GAP-00384":{"line":3079,"offset":536909,"length":172,"previous":"M18-GAP-00383","next":"M18-GAP-00385"},"M18-GAP-00385":{"line":3080,"offset":537081,"length":175,"previous":"M18-GAP-00384","next":"M18-GAP-00386"},"M18-GAP-00386":{"line":3081,"offset":537256,"length":174,"previous":"M18-GAP-00385","next":"M18-GAP-00387"},"M18-GAP-00387":{"line":3082,"offset":537430,"length":180,"previous":"M18-GAP-00386","next":"M18-GAP-00388"},"M18-GAP-00388":{"line":3083,"offset":537610,"length":173,"previous":"M18-GAP-00387","next":"M18-GAP-00389"},"M18-GAP-00389":{"line":3084,"offset":537783,"length":178,"previous":"M18-GAP-00388","next":"M18-GAP-00390"},"M18-GAP-00390":{"line":3085,"offset":537961,"length":179,"previous":"M18-GAP-00389","next":"M18-GAP-00391"},"M18-GAP-00391":{"line":3086,"offset":538140,"length":176,"previous":"M18-GAP-00390","next":"M18-GAP-00392"},"M18-GAP-00392":{"line":3087,"offset":538316,"length":175,"previous":"M18-GAP-00391","next":"M18-GAP-00393"},"M18-GAP-00393":{"line":3088,"offset":538491,"length":174,"previous":"M18-GAP-00392","next":"M18-GAP-00394"},"M18-GAP-00394":{"line":3089,"offset":538665,"length":171,"previous":"M18-GAP-00393","next":"M18-GAP-00395"},"M18-GAP-00395":{"line":3090,"offset":538836,"length":170,"previous":"M18-GAP-00394","next":"M18-GAP-00396"},"M18-GAP-00396":{"line":3091,"offset":539006,"length":173,"previous":"M18-GAP-00395","next":"M18-GAP-00397"},"M18-GAP-00397":{"line":3092,"offset":539179,"length":176,"previous":"M18-GAP-00396","next":"M18-GAP-00398"},"M18-GAP-00398":{"line":3093,"offset":539355,"length":178,"previous":"M18-GAP-00397","next":"M18-GAP-00399"},"M18-GAP-00399":{"line":3094,"offset":539533,"length":173,"previous":"M18-GAP-00398","next":"M18-GAP-00400"},"M18-GAP-00400":{"line":3095,"offset":539706,"length":176,"previous":"M18-GAP-00399","next":"M18-GAP-00401"},"M18-GAP-00401":{"line":3096,"offset":539882,"length":177,"previous":"M18-GAP-00400","next":"M18-GAP-00402"},"M18-GAP-00402":{"line":3097,"offset":540059,"length":176,"previous":"M18-GAP-00401","next":"M18-GAP-00403"},"M18-GAP-00403":{"line":3098,"offset":540235,"length":178,"previous":"M18-GAP-00402","next":"M18-GAP-00404"},"M18-GAP-00404":{"line":3099,"offset":540413,"length":182,"previous":"M18-GAP-00403","next":"M18-GAP-00405"},"M18-GAP-00405":{"line":3100,"offset":540595,"length":181,"previous":"M18-GAP-00404","next":"M18-GAP-00406"},"M18-GAP-00406":{"line":3101,"offset":540776,"length":178,"previous":"M18-GAP-00405","next":"M18-GAP-00407"},"M18-GAP-00407":{"line":3102,"offset":540954,"length":179,"previous":"M18-GAP-00406","next":"M18-GAP-00408"},"M18-GAP-00408":{"line":3103,"offset":541133,"length":176,"previous":"M18-GAP-00407","next":"M18-GAP-00409"},"M18-GAP-00409":{"line":3104,"offset":541309,"length":170,"previous":"M18-GAP-00408","next":"M18-GAP-00410"},"M18-GAP-00410":{"line":3105,"offset":541479,"length":175,"previous":"M18-GAP-00409","next":"M18-GAP-00411"},"M18-GAP-00411":{"line":3106,"offset":541654,"length":174,"previous":"M18-GAP-00410","next":"M18-GAP-00412"},"M18-GAP-00412":{"line":3107,"offset":541828,"length":179,"previous":"M18-GAP-00411","next":"M18-GAP-00413"},"M18-GAP-00413":{"line":3108,"offset":542007,"length":174,"previous":"M18-GAP-00412","next":"M18-GAP-00414"},"M18-GAP-00414":{"line":3109,"offset":542181,"length":173,"previous":"M18-GAP-00413","next":"M18-GAP-00415"},"M18-GAP-00415":{"line":3110,"offset":542354,"length":180,"previous":"M18-GAP-00414","next":"M18-GAP-00416"},"M18-GAP-00416":{"line":3111,"offset":542534,"length":178,"previous":"M18-GAP-00415","next":"M18-GAP-00417"},"M18-GAP-00417":{"line":3112,"offset":542712,"length":178,"previous":"M18-GAP-00416","next":"M18-GAP-00418"},"M18-GAP-00418":{"line":3113,"offset":542890,"length":174,"previous":"M18-GAP-00417","next":"M18-GAP-00419"},"M18-GAP-00419":{"line":3114,"offset":543064,"length":187,"previous":"M18-GAP-00418","next":"M18-GAP-00420"},"M18-GAP-00420":{"line":3115,"offset":543251,"length":174,"previous":"M18-GAP-00419","next":"M18-GAP-00421"},"M18-GAP-00421":{"line":3116,"offset":543425,"length":175,"previous":"M18-GAP-00420","next":"M18-GAP-00422"},"M18-GAP-00422":{"line":3117,"offset":543600,"length":177,"previous":"M18-GAP-00421","next":"M18-GAP-00423"},"M18-GAP-00423":{"line":3118,"offset":543777,"length":175,"previous":"M18-GAP-00422","next":"M18-GAP-00424"},"M18-GAP-00424":{"line":3119,"offset":543952,"length":181,"previous":"M18-GAP-00423","next":"M18-GAP-00425"},"M18-GAP-00425":{"line":3120,"offset":544133,"length":175,"previous":"M18-GAP-00424","next":"M18-GAP-00426"},"M18-GAP-00426":{"line":3121,"offset":544308,"length":178,"previous":"M18-GAP-00425","next":"M18-GAP-00427"},"M18-GAP-00427":{"line":3122,"offset":544486,"length":173,"previous":"M18-GAP-00426","next":"M18-GAP-00428"},"M18-GAP-00428":{"line":3123,"offset":544659,"length":175,"previous":"M18-GAP-00427","next":"M18-GAP-00429"},"M18-GAP-00429":{"line":3124,"offset":544834,"length":175,"previous":"M18-GAP-00428","next":"M18-GAP-00430"},"M18-GAP-00430":{"line":3125,"offset":545009,"length":175,"previous":"M18-GAP-00429","next":"M18-GAP-00431"},"M18-GAP-00431":{"line":3126,"offset":545184,"length":173,"previous":"M18-GAP-00430","next":"M18-GAP-00432"},"M18-GAP-00432":{"line":3127,"offset":545357,"length":177,"previous":"M18-GAP-00431","next":"M18-GAP-00433"},"M18-GAP-00433":{"line":3128,"offset":545534,"length":174,"previous":"M18-GAP-00432","next":"M18-GAP-00434"},"M18-GAP-00434":{"line":3129,"offset":545708,"length":180,"previous":"M18-GAP-00433","next":"M18-GAP-00435"},"M18-GAP-00435":{"line":3130,"offset":545888,"length":180,"previous":"M18-GAP-00434","next":"M18-GAP-00436"},"M18-GAP-00436":{"line":3131,"offset":546068,"length":172,"previous":"M18-GAP-00435","next":"M18-GAP-00437"},"M18-GAP-00437":{"line":3132,"offset":546240,"length":175,"previous":"M18-GAP-00436","next":"M18-GAP-00438"},"M18-GAP-00438":{"line":3133,"offset":546415,"length":172,"previous":"M18-GAP-00437","next":"M18-GAP-00439"},"M18-GAP-00439":{"line":3134,"offset":546587,"length":178,"previous":"M18-GAP-00438","next":"M18-GAP-00440"},"M18-GAP-00440":{"line":3135,"offset":546765,"length":185,"previous":"M18-GAP-00439","next":"M18-GAP-00441"},"M18-GAP-00441":{"line":3136,"offset":546950,"length":177,"previous":"M18-GAP-00440","next":"M18-GAP-00442"},"M18-GAP-00442":{"line":3137,"offset":547127,"length":179,"previous":"M18-GAP-00441","next":"M18-GAP-00443"},"M18-GAP-00443":{"line":3138,"offset":547306,"length":182,"previous":"M18-GAP-00442","next":"M18-GAP-00444"},"M18-GAP-00444":{"line":3139,"offset":547488,"length":178,"previous":"M18-GAP-00443","next":"M18-GAP-00445"},"M18-GAP-00445":{"line":3140,"offset":547666,"length":183,"previous":"M18-GAP-00444","next":"M18-GAP-00446"},"M18-GAP-00446":{"line":3141,"offset":547849,"length":185,"previous":"M18-GAP-00445","next":"M18-GAP-00447"},"M18-GAP-00447":{"line":3142,"offset":548034,"length":177,"previous":"M18-GAP-00446","next":"M18-GAP-00448"},"M18-GAP-00448":{"line":3143,"offset":548211,"length":183,"previous":"M18-GAP-00447","next":"M18-GAP-00449"},"M18-GAP-00449":{"line":3144,"offset":548394,"length":180,"previous":"M18-GAP-00448","next":"M18-GAP-00450"},"M18-GAP-00450":{"line":3145,"offset":548574,"length":177,"previous":"M18-GAP-00449","next":"M18-GAP-00451"},"M18-GAP-00451":{"line":3146,"offset":548751,"length":176,"previous":"M18-GAP-00450","next":"M19-GAP-00001"},"M19-GAP-00001":{"line":3147,"offset":548927,"length":153,"previous":"M18-GAP-00451","next":"M19-GAP-00002"},"M19-GAP-00002":{"line":3148,"offset":549080,"length":155,"previous":"M19-GAP-00001","next":"M19-GAP-00003"},"M19-GAP-00003":{"line":3149,"offset":549235,"length":152,"previous":"M19-GAP-00002","next":"M19-GAP-00004"},"M19-GAP-00004":{"line":3150,"offset":549387,"length":152,"previous":"M19-GAP-00003","next":"M19-GAP-00005"},"M19-GAP-00005":{"line":3151,"offset":549539,"length":153,"previous":"M19-GAP-00004","next":"M19-GAP-00006"},"M19-GAP-00006":{"line":3152,"offset":549692,"length":159,"previous":"M19-GAP-00005","next":"M19-GAP-00007"},"M19-GAP-00007":{"line":3153,"offset":549851,"length":149,"previous":"M19-GAP-00006","next":"M19-GAP-00008"},"M19-GAP-00008":{"line":3154,"offset":550000,"length":152,"previous":"M19-GAP-00007","next":"M19-GAP-00009"},"M19-GAP-00009":{"line":3155,"offset":550152,"length":150,"previous":"M19-GAP-00008","next":"M19-GAP-00010"},"M19-GAP-00010":{"line":3156,"offset":550302,"length":154,"previous":"M19-GAP-00009","next":"M19-GAP-00011"},"M19-GAP-00011":{"line":3157,"offset":550456,"length":151,"previous":"M19-GAP-00010","next":"M19-GAP-00012"},"M19-GAP-00012":{"line":3158,"offset":550607,"length":155,"previous":"M19-GAP-00011","next":"M19-GAP-00013"},"M19-GAP-00013":{"line":3159,"offset":550762,"length":156,"previous":"M19-GAP-00012","next":"M19-GAP-00014"},"M19-GAP-00014":{"line":3160,"offset":550918,"length":154,"previous":"M19-GAP-00013","next":"M19-GAP-00015"},"M19-GAP-00015":{"line":3161,"offset":551072,"length":163,"previous":"M19-GAP-00014","next":"M19-GAP-00016"},"M19-GAP-00016":{"line":3162,"offset":551235,"length":157,"previous":"M19-GAP-00015","next":"M19-GAP-00017"},"M19-GAP-00017":{"line":3163,"offset":551392,"length":152,"previous":"M19-GAP-00016","next":"M19-GAP-00018"},"M19-GAP-00018":{"line":3164,"offset":551544,"length":154,"previous":"M19-GAP-00017","next":"M19-GAP-00019"},"M19-GAP-00019":{"line":3165,"offset":551698,"length":151,"previous":"M19-GAP-00018","next":"M19-GAP-00020"},"M19-GAP-00020":{"line":3166,"offset":551849,"length":153,"previous":"M19-GAP-00019","next":"M20-GAP-00001"},"M20-GAP-00001":{"line":3167,"offset":552002,"length":161,"previous":"M19-GAP-00020","next":"M20-GAP-00002"},"M20-GAP-00002":{"line":3168,"offset":552163,"length":167,"previous":"M20-GAP-00001","next":"M20-GAP-00003"},"M20-GAP-00003":{"line":3169,"offset":552330,"length":157,"previous":"M20-GAP-00002","next":"M20-GAP-00004"},"M20-GAP-00004":{"line":3170,"offset":552487,"length":169,"previous":"M20-GAP-00003","next":"M20-GAP-00005"},"M20-GAP-00005":{"line":3171,"offset":552656,"length":162,"previous":"M20-GAP-00004","next":"M20-GAP-00006"},"M20-GAP-00006":{"line":3172,"offset":552818,"length":171,"previous":"M20-GAP-00005","next":"M20-GAP-00007"},"M20-GAP-00007":{"line":3173,"offset":552989,"length":162,"previous":"M20-GAP-00006","next":"M20-GAP-00008"},"M20-GAP-00008":{"line":3174,"offset":553151,"length":169,"previous":"M20-GAP-00007","next":"M20-GAP-00009"},"M20-GAP-00009":{"line":3175,"offset":553320,"length":161,"previous":"M20-GAP-00008","next":"M20-GAP-00010"},"M20-GAP-00010":{"line":3176,"offset":553481,"length":161,"previous":"M20-GAP-00009","next":"M20-GAP-00011"},"M20-GAP-00011":{"line":3177,"offset":553642,"length":158,"previous":"M20-GAP-00010","next":"M20-GAP-00012"},"M20-GAP-00012":{"line":3178,"offset":553800,"length":162,"previous":"M20-GAP-00011","next":"M20-GAP-00013"},"M20-GAP-00013":{"line":3179,"offset":553962,"length":171,"previous":"M20-GAP-00012","next":"M20-GAP-00014"},"M20-GAP-00014":{"line":3180,"offset":554133,"length":162,"previous":"M20-GAP-00013","next":"M20-GAP-00015"},"M20-GAP-00015":{"line":3181,"offset":554295,"length":162,"previous":"M20-GAP-00014","next":"M20-GAP-00016"},"M20-GAP-00016":{"line":3182,"offset":554457,"length":166,"previous":"M20-GAP-00015","next":"M20-GAP-00017"},"M20-GAP-00017":{"line":3183,"offset":554623,"length":166,"previous":"M20-GAP-00016","next":"M20-GAP-00018"},"M20-GAP-00018":{"line":3184,"offset":554789,"length":166,"previous":"M20-GAP-00017","next":"M20-GAP-00019"},"M20-GAP-00019":{"line":3185,"offset":554955,"length":174,"previous":"M20-GAP-00018","next":"M20-GAP-00020"},"M20-GAP-00020":{"line":3186,"offset":555129,"length":175,"previous":"M20-GAP-00019","next":"M20-GAP-00021"},"M20-GAP-00021":{"line":3187,"offset":555304,"length":169,"previous":"M20-GAP-00020","next":"M20-GAP-00022"},"M20-GAP-00022":{"line":3188,"offset":555473,"length":168,"previous":"M20-GAP-00021","next":"M20-GAP-00023"},"M20-GAP-00023":{"line":3189,"offset":555641,"length":169,"previous":"M20-GAP-00022","next":"M20-GAP-00024"},"M20-GAP-00024":{"line":3190,"offset":555810,"length":164,"previous":"M20-GAP-00023","next":"M20-GAP-00025"},"M20-GAP-00025":{"line":3191,"offset":555974,"length":162,"previous":"M20-GAP-00024","next":"M20-GAP-00026"},"M20-GAP-00026":{"line":3192,"offset":556136,"length":168,"previous":"M20-GAP-00025","next":"M20-GAP-00027"},"M20-GAP-00027":{"line":3193,"offset":556304,"length":170,"previous":"M20-GAP-00026","next":"M20-GAP-00028"},"M20-GAP-00028":{"line":3194,"offset":556474,"length":166,"previous":"M20-GAP-00027","next":"M20-GAP-00029"},"M20-GAP-00029":{"line":3195,"offset":556640,"length":162,"previous":"M20-GAP-00028","next":"M20-GAP-00030"},"M20-GAP-00030":{"line":3196,"offset":556802,"length":176,"previous":"M20-GAP-00029","next":"M20-GAP-00031"},"M20-GAP-00031":{"line":3197,"offset":556978,"length":173,"previous":"M20-GAP-00030","next":"M20-GAP-00032"},"M20-GAP-00032":{"line":3198,"offset":557151,"length":173,"previous":"M20-GAP-00031","next":"M20-GAP-00033"},"M20-GAP-00033":{"line":3199,"offset":557324,"length":175,"previous":"M20-GAP-00032","next":"M20-GAP-00034"},"M20-GAP-00034":{"line":3200,"offset":557499,"length":174,"previous":"M20-GAP-00033","next":"M20-GAP-00035"},"M20-GAP-00035":{"line":3201,"offset":557673,"length":172,"previous":"M20-GAP-00034","next":"M20-GAP-00036"},"M20-GAP-00036":{"line":3202,"offset":557845,"length":176,"previous":"M20-GAP-00035","next":"M20-GAP-00037"},"M20-GAP-00037":{"line":3203,"offset":558021,"length":177,"previous":"M20-GAP-00036","next":"M20-GAP-00038"},"M20-GAP-00038":{"line":3204,"offset":558198,"length":172,"previous":"M20-GAP-00037","next":"M20-GAP-00039"},"M20-GAP-00039":{"line":3205,"offset":558370,"length":176,"previous":"M20-GAP-00038","next":"M20-GAP-00040"},"M20-GAP-00040":{"line":3206,"offset":558546,"length":177,"previous":"M20-GAP-00039","next":"M20-GAP-00041"},"M20-GAP-00041":{"line":3207,"offset":558723,"length":174,"previous":"M20-GAP-00040","next":"M20-GAP-00042"},"M20-GAP-00042":{"line":3208,"offset":558897,"length":157,"previous":"M20-GAP-00041","next":"M20-GAP-00043"},"M20-GAP-00043":{"line":3209,"offset":559054,"length":162,"previous":"M20-GAP-00042","next":"M20-GAP-00044"},"M20-GAP-00044":{"line":3210,"offset":559216,"length":168,"previous":"M20-GAP-00043","next":"M20-GAP-00045"},"M20-GAP-00045":{"line":3211,"offset":559384,"length":161,"previous":"M20-GAP-00044","next":"M20-GAP-00046"},"M20-GAP-00046":{"line":3212,"offset":559545,"length":164,"previous":"M20-GAP-00045","next":"M20-GAP-00047"},"M20-GAP-00047":{"line":3213,"offset":559709,"length":173,"previous":"M20-GAP-00046","next":"M20-GAP-00048"},"M20-GAP-00048":{"line":3214,"offset":559882,"length":160,"previous":"M20-GAP-00047","next":"M20-GAP-00049"},"M20-GAP-00049":{"line":3215,"offset":560042,"length":165,"previous":"M20-GAP-00048","next":"M20-GAP-00050"},"M20-GAP-00050":{"line":3216,"offset":560207,"length":176,"previous":"M20-GAP-00049","next":"M20-GAP-00051"},"M20-GAP-00051":{"line":3217,"offset":560383,"length":177,"previous":"M20-GAP-00050","next":"M20-GAP-00052"},"M20-GAP-00052":{"line":3218,"offset":560560,"length":163,"previous":"M20-GAP-00051","next":"M20-GAP-00053"},"M20-GAP-00053":{"line":3219,"offset":560723,"length":171,"previous":"M20-GAP-00052","next":"M20-GAP-00054"},"M20-GAP-00054":{"line":3220,"offset":560894,"length":164,"previous":"M20-GAP-00053","next":"M20-GAP-00055"},"M20-GAP-00055":{"line":3221,"offset":561058,"length":163,"previous":"M20-GAP-00054","next":"M20-GAP-00056"},"M20-GAP-00056":{"line":3222,"offset":561221,"length":159,"previous":"M20-GAP-00055","next":"M20-GAP-00057"},"M20-GAP-00057":{"line":3223,"offset":561380,"length":163,"previous":"M20-GAP-00056","next":"M20-GAP-00058"},"M20-GAP-00058":{"line":3224,"offset":561543,"length":160,"previous":"M20-GAP-00057","next":"M20-GAP-00059"},"M20-GAP-00059":{"line":3225,"offset":561703,"length":168,"previous":"M20-GAP-00058","next":"M20-GAP-00060"},"M20-GAP-00060":{"line":3226,"offset":561871,"length":164,"previous":"M20-GAP-00059","next":"M20-GAP-00061"},"M20-GAP-00061":{"line":3227,"offset":562035,"length":163,"previous":"M20-GAP-00060","next":"M20-GAP-00062"},"M20-GAP-00062":{"line":3228,"offset":562198,"length":165,"previous":"M20-GAP-00061","next":"M20-GAP-00063"},"M20-GAP-00063":{"line":3229,"offset":562363,"length":171,"previous":"M20-GAP-00062","next":"M20-GAP-00064"},"M20-GAP-00064":{"line":3230,"offset":562534,"length":165,"previous":"M20-GAP-00063","next":"M20-GAP-00065"},"M20-GAP-00065":{"line":3231,"offset":562699,"length":165,"previous":"M20-GAP-00064","next":"M20-GAP-00066"},"M20-GAP-00066":{"line":3232,"offset":562864,"length":152,"previous":"M20-GAP-00065","next":"M20-GAP-00067"},"M20-GAP-00067":{"line":3233,"offset":563016,"length":159,"previous":"M20-GAP-00066","next":"M20-GAP-00068"},"M20-GAP-00068":{"line":3234,"offset":563175,"length":159,"previous":"M20-GAP-00067","next":"M20-GAP-00069"},"M20-GAP-00069":{"line":3235,"offset":563334,"length":160,"previous":"M20-GAP-00068","next":"M20-GAP-00070"},"M20-GAP-00070":{"line":3236,"offset":563494,"length":154,"previous":"M20-GAP-00069","next":"M20-GAP-00071"},"M20-GAP-00071":{"line":3237,"offset":563648,"length":157,"previous":"M20-GAP-00070","next":"M20-GAP-00072"},"M20-GAP-00072":{"line":3238,"offset":563805,"length":159,"previous":"M20-GAP-00071","next":"M20-GAP-00073"},"M20-GAP-00073":{"line":3239,"offset":563964,"length":154,"previous":"M20-GAP-00072","next":"M20-GAP-00074"},"M20-GAP-00074":{"line":3240,"offset":564118,"length":160,"previous":"M20-GAP-00073","next":"M20-GAP-00075"},"M20-GAP-00075":{"line":3241,"offset":564278,"length":162,"previous":"M20-GAP-00074","next":"M20-GAP-00076"},"M20-GAP-00076":{"line":3242,"offset":564440,"length":153,"previous":"M20-GAP-00075","next":"M20-GAP-00077"},"M20-GAP-00077":{"line":3243,"offset":564593,"length":154,"previous":"M20-GAP-00076","next":"M20-GAP-00078"},"M20-GAP-00078":{"line":3244,"offset":564747,"length":153,"previous":"M20-GAP-00077","next":"M20-GAP-00079"},"M20-GAP-00079":{"line":3245,"offset":564900,"length":153,"previous":"M20-GAP-00078","next":"M20-GAP-00080"},"M20-GAP-00080":{"line":3246,"offset":565053,"length":154,"previous":"M20-GAP-00079","next":"M20-GAP-00081"},"M20-GAP-00081":{"line":3247,"offset":565207,"length":158,"previous":"M20-GAP-00080","next":"M20-GAP-00082"},"M20-GAP-00082":{"line":3248,"offset":565365,"length":157,"previous":"M20-GAP-00081","next":"M20-GAP-00083"},"M20-GAP-00083":{"line":3249,"offset":565522,"length":157,"previous":"M20-GAP-00082","next":"M20-GAP-00084"},"M20-GAP-00084":{"line":3250,"offset":565679,"length":154,"previous":"M20-GAP-00083","next":"M20-GAP-00085"},"M20-GAP-00085":{"line":3251,"offset":565833,"length":154,"previous":"M20-GAP-00084","next":"M20-GAP-00086"},"M20-GAP-00086":{"line":3252,"offset":565987,"length":154,"previous":"M20-GAP-00085","next":"M20-GAP-00087"},"M20-GAP-00087":{"line":3253,"offset":566141,"length":157,"previous":"M20-GAP-00086","next":"M20-GAP-00088"},"M20-GAP-00088":{"line":3254,"offset":566298,"length":153,"previous":"M20-GAP-00087","next":"M20-GAP-00089"},"M20-GAP-00089":{"line":3255,"offset":566451,"length":153,"previous":"M20-GAP-00088","next":"M21-GAP-00001"},"M21-GAP-00001":{"line":3256,"offset":566604,"length":156,"previous":"M20-GAP-00089","next":"M21-GAP-00002"},"M21-GAP-00002":{"line":3257,"offset":566760,"length":152,"previous":"M21-GAP-00001","next":"M21-GAP-00003"},"M21-GAP-00003":{"line":3258,"offset":566912,"length":161,"previous":"M21-GAP-00002","next":"M21-GAP-00004"},"M21-GAP-00004":{"line":3259,"offset":567073,"length":150,"previous":"M21-GAP-00003","next":"M21-GAP-00005"},"M21-GAP-00005":{"line":3260,"offset":567223,"length":157,"previous":"M21-GAP-00004","next":"M21-GAP-00006"},"M21-GAP-00006":{"line":3261,"offset":567380,"length":157,"previous":"M21-GAP-00005","next":"M21-GAP-00007"},"M21-GAP-00007":{"line":3262,"offset":567537,"length":157,"previous":"M21-GAP-00006","next":"M21-GAP-00008"},"M21-GAP-00008":{"line":3263,"offset":567694,"length":149,"previous":"M21-GAP-00007","next":"M21-GAP-00009"},"M21-GAP-00009":{"line":3264,"offset":567843,"length":155,"previous":"M21-GAP-00008","next":"M21-GAP-00010"},"M21-GAP-00010":{"line":3265,"offset":567998,"length":156,"previous":"M21-GAP-00009","next":"M21-GAP-00011"},"M21-GAP-00011":{"line":3266,"offset":568154,"length":153,"previous":"M21-GAP-00010","next":"M21-GAP-00012"},"M21-GAP-00012":{"line":3267,"offset":568307,"length":156,"previous":"M21-GAP-00011","next":"M21-GAP-00013"},"M21-GAP-00013":{"line":3268,"offset":568463,"length":155,"previous":"M21-GAP-00012","next":"M21-GAP-00014"},"M21-GAP-00014":{"line":3269,"offset":568618,"length":160,"previous":"M21-GAP-00013","next":"M21-GAP-00015"},"M21-GAP-00015":{"line":3270,"offset":568778,"length":156,"previous":"M21-GAP-00014","next":"M21-GAP-00016"},"M21-GAP-00016":{"line":3271,"offset":568934,"length":154,"previous":"M21-GAP-00015","next":"M21-GAP-00017"},"M21-GAP-00017":{"line":3272,"offset":569088,"length":156,"previous":"M21-GAP-00016","next":"M21-GAP-00018"},"M21-GAP-00018":{"line":3273,"offset":569244,"length":151,"previous":"M21-GAP-00017","next":"M21-GAP-00019"},"M21-GAP-00019":{"line":3274,"offset":569395,"length":152,"previous":"M21-GAP-00018","next":"M21-GAP-00020"},"M21-GAP-00020":{"line":3275,"offset":569547,"length":172,"previous":"M21-GAP-00019","next":"M21-GAP-00021"},"M21-GAP-00021":{"line":3276,"offset":569719,"length":171,"previous":"M21-GAP-00020","next":"M21-GAP-00022"},"M21-GAP-00022":{"line":3277,"offset":569890,"length":173,"previous":"M21-GAP-00021","next":"M21-GAP-00023"},"M21-GAP-00023":{"line":3278,"offset":570063,"length":176,"previous":"M21-GAP-00022","next":"M21-GAP-00024"},"M21-GAP-00024":{"line":3279,"offset":570239,"length":174,"previous":"M21-GAP-00023","next":"M21-GAP-00025"},"M21-GAP-00025":{"line":3280,"offset":570413,"length":176,"previous":"M21-GAP-00024","next":"M21-GAP-00026"},"M21-GAP-00026":{"line":3281,"offset":570589,"length":173,"previous":"M21-GAP-00025","next":"M21-GAP-00027"},"M21-GAP-00027":{"line":3282,"offset":570762,"length":176,"previous":"M21-GAP-00026","next":"M21-GAP-00028"},"M21-GAP-00028":{"line":3283,"offset":570938,"length":165,"previous":"M21-GAP-00027","next":"M21-GAP-00029"},"M21-GAP-00029":{"line":3284,"offset":571103,"length":166,"previous":"M21-GAP-00028","next":"M21-GAP-00030"},"M21-GAP-00030":{"line":3285,"offset":571269,"length":167,"previous":"M21-GAP-00029","next":"M21-GAP-00031"},"M21-GAP-00031":{"line":3286,"offset":571436,"length":177,"previous":"M21-GAP-00030","next":"M21-GAP-00032"},"M21-GAP-00032":{"line":3287,"offset":571613,"length":165,"previous":"M21-GAP-00031","next":"M21-GAP-00033"},"M21-GAP-00033":{"line":3288,"offset":571778,"length":166,"previous":"M21-GAP-00032","next":"M21-GAP-00034"},"M21-GAP-00034":{"line":3289,"offset":571944,"length":166,"previous":"M21-GAP-00033","next":"M21-GAP-00035"},"M21-GAP-00035":{"line":3290,"offset":572110,"length":167,"previous":"M21-GAP-00034","next":"M21-GAP-00036"},"M21-GAP-00036":{"line":3291,"offset":572277,"length":170,"previous":"M21-GAP-00035","next":"M21-GAP-00037"},"M21-GAP-00037":{"line":3292,"offset":572447,"length":170,"previous":"M21-GAP-00036","next":"M21-GAP-00038"},"M21-GAP-00038":{"line":3293,"offset":572617,"length":178,"previous":"M21-GAP-00037","next":"M21-GAP-00039"},"M21-GAP-00039":{"line":3294,"offset":572795,"length":178,"previous":"M21-GAP-00038","next":"M21-GAP-00040"},"M21-GAP-00040":{"line":3295,"offset":572973,"length":176,"previous":"M21-GAP-00039","next":"M21-GAP-00041"},"M21-GAP-00041":{"line":3296,"offset":573149,"length":166,"previous":"M21-GAP-00040","next":"M21-GAP-00042"},"M21-GAP-00042":{"line":3297,"offset":573315,"length":174,"previous":"M21-GAP-00041","next":"M21-GAP-00043"},"M21-GAP-00043":{"line":3298,"offset":573489,"length":169,"previous":"M21-GAP-00042","next":"M21-GAP-00044"},"M21-GAP-00044":{"line":3299,"offset":573658,"length":163,"previous":"M21-GAP-00043","next":"M21-GAP-00045"},"M21-GAP-00045":{"line":3300,"offset":573821,"length":177,"previous":"M21-GAP-00044","next":"M21-GAP-00046"},"M21-GAP-00046":{"line":3301,"offset":573998,"length":177,"previous":"M21-GAP-00045","next":"M21-GAP-00047"},"M21-GAP-00047":{"line":3302,"offset":574175,"length":163,"previous":"M21-GAP-00046","next":"M21-GAP-00048"},"M21-GAP-00048":{"line":3303,"offset":574338,"length":163,"previous":"M21-GAP-00047","next":"M21-GAP-00049"},"M21-GAP-00049":{"line":3304,"offset":574501,"length":163,"previous":"M21-GAP-00048","next":"M21-GAP-00050"},"M21-GAP-00050":{"line":3305,"offset":574664,"length":163,"previous":"M21-GAP-00049","next":"M21-GAP-00051"},"M21-GAP-00051":{"line":3306,"offset":574827,"length":163,"previous":"M21-GAP-00050","next":"M21-GAP-00052"},"M21-GAP-00052":{"line":3307,"offset":574990,"length":163,"previous":"M21-GAP-00051","next":"M21-GAP-00053"},"M21-GAP-00053":{"line":3308,"offset":575153,"length":184,"previous":"M21-GAP-00052","next":"M21-GAP-00054"},"M21-GAP-00054":{"line":3309,"offset":575337,"length":184,"previous":"M21-GAP-00053","next":"M21-GAP-00055"},"M21-GAP-00055":{"line":3310,"offset":575521,"length":187,"previous":"M21-GAP-00054","next":"M21-GAP-00056"},"M21-GAP-00056":{"line":3311,"offset":575708,"length":194,"previous":"M21-GAP-00055","next":"M21-GAP-00057"},"M21-GAP-00057":{"line":3312,"offset":575902,"length":189,"previous":"M21-GAP-00056","next":"M21-GAP-00058"},"M21-GAP-00058":{"line":3313,"offset":576091,"length":189,"previous":"M21-GAP-00057","next":"M21-GAP-00059"},"M21-GAP-00059":{"line":3314,"offset":576280,"length":209,"previous":"M21-GAP-00058","next":"M21-GAP-00060"},"M21-GAP-00060":{"line":3315,"offset":576489,"length":211,"previous":"M21-GAP-00059","next":"M21-GAP-00061"},"M21-GAP-00061":{"line":3316,"offset":576700,"length":215,"previous":"M21-GAP-00060","next":"M21-GAP-00062"},"M21-GAP-00062":{"line":3317,"offset":576915,"length":205,"previous":"M21-GAP-00061","next":"M21-GAP-00063"},"M21-GAP-00063":{"line":3318,"offset":577120,"length":202,"previous":"M21-GAP-00062","next":"M21-GAP-00064"},"M21-GAP-00064":{"line":3319,"offset":577322,"length":204,"previous":"M21-GAP-00063","next":"M21-GAP-00065"},"M21-GAP-00065":{"line":3320,"offset":577526,"length":204,"previous":"M21-GAP-00064","next":"M21-GAP-00066"},"M21-GAP-00066":{"line":3321,"offset":577730,"length":204,"previous":"M21-GAP-00065","next":"M21-GAP-00067"},"M21-GAP-00067":{"line":3322,"offset":577934,"length":199,"previous":"M21-GAP-00066","next":"M21-GAP-00068"},"M21-GAP-00068":{"line":3323,"offset":578133,"length":212,"previous":"M21-GAP-00067","next":"M21-GAP-00069"},"M21-GAP-00069":{"line":3324,"offset":578345,"length":202,"previous":"M21-GAP-00068","next":"M21-GAP-00070"},"M21-GAP-00070":{"line":3325,"offset":578547,"length":201,"previous":"M21-GAP-00069","next":"M21-GAP-00071"},"M21-GAP-00071":{"line":3326,"offset":578748,"length":204,"previous":"M21-GAP-00070","next":"M21-GAP-00072"},"M21-GAP-00072":{"line":3327,"offset":578952,"length":199,"previous":"M21-GAP-00071","next":"M21-GAP-00073"},"M21-GAP-00073":{"line":3328,"offset":579151,"length":200,"previous":"M21-GAP-00072","next":"M21-GAP-00074"},"M21-GAP-00074":{"line":3329,"offset":579351,"length":199,"previous":"M21-GAP-00073","next":"M21-GAP-00075"},"M21-GAP-00075":{"line":3330,"offset":579550,"length":199,"previous":"M21-GAP-00074","next":"M21-GAP-00076"},"M21-GAP-00076":{"line":3331,"offset":579749,"length":199,"previous":"M21-GAP-00075","next":"M21-GAP-00077"},"M21-GAP-00077":{"line":3332,"offset":579948,"length":199,"previous":"M21-GAP-00076","next":"M21-GAP-00078"},"M21-GAP-00078":{"line":3333,"offset":580147,"length":211,"previous":"M21-GAP-00077","next":"M21-GAP-00079"},"M21-GAP-00079":{"line":3334,"offset":580358,"length":214,"previous":"M21-GAP-00078","next":"M21-GAP-00080"},"M21-GAP-00080":{"line":3335,"offset":580572,"length":206,"previous":"M21-GAP-00079","next":"M21-GAP-00081"},"M21-GAP-00081":{"line":3336,"offset":580778,"length":206,"previous":"M21-GAP-00080","next":"M21-GAP-00082"},"M21-GAP-00082":{"line":3337,"offset":580984,"length":206,"previous":"M21-GAP-00081","next":"M21-GAP-00083"},"M21-GAP-00083":{"line":3338,"offset":581190,"length":206,"previous":"M21-GAP-00082","next":"M21-GAP-00084"},"M21-GAP-00084":{"line":3339,"offset":581396,"length":199,"previous":"M21-GAP-00083","next":"M21-GAP-00085"},"M21-GAP-00085":{"line":3340,"offset":581595,"length":200,"previous":"M21-GAP-00084","next":"M21-GAP-00086"},"M21-GAP-00086":{"line":3341,"offset":581795,"length":204,"previous":"M21-GAP-00085","next":"M21-GAP-00087"},"M21-GAP-00087":{"line":3342,"offset":581999,"length":215,"previous":"M21-GAP-00086","next":"M21-GAP-00088"},"M21-GAP-00088":{"line":3343,"offset":582214,"length":212,"previous":"M21-GAP-00087","next":"M21-GAP-00089"},"M21-GAP-00089":{"line":3344,"offset":582426,"length":210,"previous":"M21-GAP-00088","next":"M21-GAP-00090"},"M21-GAP-00090":{"line":3345,"offset":582636,"length":208,"previous":"M21-GAP-00089","next":"M21-GAP-00091"},"M21-GAP-00091":{"line":3346,"offset":582844,"length":211,"previous":"M21-GAP-00090","next":"M21-GAP-00092"},"M21-GAP-00092":{"line":3347,"offset":583055,"length":205,"previous":"M21-GAP-00091","next":"M21-GAP-00093"},"M21-GAP-00093":{"line":3348,"offset":583260,"length":199,"previous":"M21-GAP-00092","next":"M21-GAP-00094"},"M21-GAP-00094":{"line":3349,"offset":583459,"length":202,"previous":"M21-GAP-00093","next":"M21-GAP-00095"},"M21-GAP-00095":{"line":3350,"offset":583661,"length":214,"previous":"M21-GAP-00094","next":"M21-GAP-00096"},"M21-GAP-00096":{"line":3351,"offset":583875,"length":204,"previous":"M21-GAP-00095","next":"M21-GAP-00097"},"M21-GAP-00097":{"line":3352,"offset":584079,"length":204,"previous":"M21-GAP-00096","next":"M21-GAP-00098"},"M21-GAP-00098":{"line":3353,"offset":584283,"length":204,"previous":"M21-GAP-00097","next":"M21-GAP-00099"},"M21-GAP-00099":{"line":3354,"offset":584487,"length":203,"previous":"M21-GAP-00098","next":"M21-GAP-00100"},"M21-GAP-00100":{"line":3355,"offset":584690,"length":203,"previous":"M21-GAP-00099","next":"M21-GAP-00101"},"M21-GAP-00101":{"line":3356,"offset":584893,"length":202,"previous":"M21-GAP-00100","next":"M21-GAP-00102"},"M21-GAP-00102":{"line":3357,"offset":585095,"length":204,"previous":"M21-GAP-00101","next":"M21-GAP-00103"},"M21-GAP-00103":{"line":3358,"offset":585299,"length":207,"previous":"M21-GAP-00102","next":"M21-GAP-00104"},"M21-GAP-00104":{"line":3359,"offset":585506,"length":200,"previous":"M21-GAP-00103","next":"M21-GAP-00105"},"M21-GAP-00105":{"line":3360,"offset":585706,"length":209,"previous":"M21-GAP-00104","next":"M21-GAP-00106"},"M21-GAP-00106":{"line":3361,"offset":585915,"length":198,"previous":"M21-GAP-00105","next":"M21-GAP-00107"},"M21-GAP-00107":{"line":3362,"offset":586113,"length":203,"previous":"M21-GAP-00106","next":"M21-GAP-00108"},"M21-GAP-00108":{"line":3363,"offset":586316,"length":206,"previous":"M21-GAP-00107","next":"M21-GAP-00109"},"M21-GAP-00109":{"line":3364,"offset":586522,"length":205,"previous":"M21-GAP-00108","next":"M21-GAP-00110"},"M21-GAP-00110":{"line":3365,"offset":586727,"length":205,"previous":"M21-GAP-00109","next":"M21-GAP-00111"},"M21-GAP-00111":{"line":3366,"offset":586932,"length":190,"previous":"M21-GAP-00110","next":"M21-GAP-00112"},"M21-GAP-00112":{"line":3367,"offset":587122,"length":190,"previous":"M21-GAP-00111","next":"M21-GAP-00113"},"M21-GAP-00113":{"line":3368,"offset":587312,"length":190,"previous":"M21-GAP-00112","next":"M21-GAP-00114"},"M21-GAP-00114":{"line":3369,"offset":587502,"length":187,"previous":"M21-GAP-00113","next":"M21-GAP-00115"},"M21-GAP-00115":{"line":3370,"offset":587689,"length":204,"previous":"M21-GAP-00114","next":"M21-GAP-00116"},"M21-GAP-00116":{"line":3371,"offset":587893,"length":207,"previous":"M21-GAP-00115","next":"M21-GAP-00117"},"M21-GAP-00117":{"line":3372,"offset":588100,"length":207,"previous":"M21-GAP-00116","next":"M21-GAP-00118"},"M21-GAP-00118":{"line":3373,"offset":588307,"length":207,"previous":"M21-GAP-00117","next":"M21-GAP-00119"},"M21-GAP-00119":{"line":3374,"offset":588514,"length":207,"previous":"M21-GAP-00118","next":"M21-GAP-00120"},"M21-GAP-00120":{"line":3375,"offset":588721,"length":207,"previous":"M21-GAP-00119","next":"M21-GAP-00121"},"M21-GAP-00121":{"line":3376,"offset":588928,"length":207,"previous":"M21-GAP-00120","next":"M21-GAP-00122"},"M21-GAP-00122":{"line":3377,"offset":589135,"length":210,"previous":"M21-GAP-00121","next":"M21-GAP-00123"},"M21-GAP-00123":{"line":3378,"offset":589345,"length":210,"previous":"M21-GAP-00122","next":"M21-GAP-00124"},"M21-GAP-00124":{"line":3379,"offset":589555,"length":210,"previous":"M21-GAP-00123","next":"M21-GAP-00125"},"M21-GAP-00125":{"line":3380,"offset":589765,"length":209,"previous":"M21-GAP-00124","next":"M21-GAP-00126"},"M21-GAP-00126":{"line":3381,"offset":589974,"length":214,"previous":"M21-GAP-00125","next":"M21-GAP-00127"},"M21-GAP-00127":{"line":3382,"offset":590188,"length":214,"previous":"M21-GAP-00126","next":"M21-GAP-00128"},"M21-GAP-00128":{"line":3383,"offset":590402,"length":214,"previous":"M21-GAP-00127","next":"M21-GAP-00129"},"M21-GAP-00129":{"line":3384,"offset":590616,"length":214,"previous":"M21-GAP-00128","next":"M21-GAP-00130"},"M21-GAP-00130":{"line":3385,"offset":590830,"length":215,"previous":"M21-GAP-00129","next":"M21-GAP-00131"},"M21-GAP-00131":{"line":3386,"offset":591045,"length":208,"previous":"M21-GAP-00130","next":"M21-GAP-00132"},"M21-GAP-00132":{"line":3387,"offset":591253,"length":208,"previous":"M21-GAP-00131","next":"M21-GAP-00133"},"M21-GAP-00133":{"line":3388,"offset":591461,"length":208,"previous":"M21-GAP-00132","next":"M21-GAP-00134"},"M21-GAP-00134":{"line":3389,"offset":591669,"length":212,"previous":"M21-GAP-00133","next":"M21-GAP-00135"},"M21-GAP-00135":{"line":3390,"offset":591881,"length":212,"previous":"M21-GAP-00134","next":"M21-GAP-00136"},"M21-GAP-00136":{"line":3391,"offset":592093,"length":208,"previous":"M21-GAP-00135","next":"M21-GAP-00137"},"M21-GAP-00137":{"line":3392,"offset":592301,"length":205,"previous":"M21-GAP-00136","next":"M21-GAP-00138"},"M21-GAP-00138":{"line":3393,"offset":592506,"length":216,"previous":"M21-GAP-00137","next":"M21-GAP-00139"},"M21-GAP-00139":{"line":3394,"offset":592722,"length":210,"previous":"M21-GAP-00138","next":"M21-GAP-00140"},"M21-GAP-00140":{"line":3395,"offset":592932,"length":210,"previous":"M21-GAP-00139","next":"M21-GAP-00141"},"M21-GAP-00141":{"line":3396,"offset":593142,"length":187,"previous":"M21-GAP-00140","next":"M21-GAP-00142"},"M21-GAP-00142":{"line":3397,"offset":593329,"length":188,"previous":"M21-GAP-00141","next":"M21-GAP-00143"},"M21-GAP-00143":{"line":3398,"offset":593517,"length":189,"previous":"M21-GAP-00142","next":"M21-GAP-00144"},"M21-GAP-00144":{"line":3399,"offset":593706,"length":188,"previous":"M21-GAP-00143","next":"M21-GAP-00145"},"M21-GAP-00145":{"line":3400,"offset":593894,"length":203,"previous":"M21-GAP-00144","next":"M21-GAP-00146"},"M21-GAP-00146":{"line":3401,"offset":594097,"length":199,"previous":"M21-GAP-00145","next":"M21-GAP-00147"},"M21-GAP-00147":{"line":3402,"offset":594296,"length":199,"previous":"M21-GAP-00146","next":"M21-GAP-00148"},"M21-GAP-00148":{"line":3403,"offset":594495,"length":199,"previous":"M21-GAP-00147","next":"M21-GAP-00149"},"M21-GAP-00149":{"line":3404,"offset":594694,"length":199,"previous":"M21-GAP-00148","next":"M21-GAP-00150"},"M21-GAP-00150":{"line":3405,"offset":594893,"length":199,"previous":"M21-GAP-00149","next":"M21-GAP-00151"},"M21-GAP-00151":{"line":3406,"offset":595092,"length":199,"previous":"M21-GAP-00150","next":"M21-GAP-00152"},"M21-GAP-00152":{"line":3407,"offset":595291,"length":203,"previous":"M21-GAP-00151","next":"M21-GAP-00153"},"M21-GAP-00153":{"line":3408,"offset":595494,"length":203,"previous":"M21-GAP-00152","next":"M21-GAP-00154"},"M21-GAP-00154":{"line":3409,"offset":595697,"length":203,"previous":"M21-GAP-00153","next":"M21-GAP-00155"},"M21-GAP-00155":{"line":3410,"offset":595900,"length":204,"previous":"M21-GAP-00154","next":"M21-GAP-00156"},"M21-GAP-00156":{"line":3411,"offset":596104,"length":205,"previous":"M21-GAP-00155","next":"M21-GAP-00157"},"M21-GAP-00157":{"line":3412,"offset":596309,"length":201,"previous":"M21-GAP-00156","next":"M21-GAP-00158"},"M21-GAP-00158":{"line":3413,"offset":596510,"length":201,"previous":"M21-GAP-00157","next":"M21-GAP-00159"},"M21-GAP-00159":{"line":3414,"offset":596711,"length":201,"previous":"M21-GAP-00158","next":"M21-GAP-00160"},"M21-GAP-00160":{"line":3415,"offset":596912,"length":201,"previous":"M21-GAP-00159","next":"M21-GAP-00161"},"M21-GAP-00161":{"line":3416,"offset":597113,"length":201,"previous":"M21-GAP-00160","next":"M21-GAP-00162"},"M21-GAP-00162":{"line":3417,"offset":597314,"length":201,"previous":"M21-GAP-00161","next":"M21-GAP-00163"},"M21-GAP-00163":{"line":3418,"offset":597515,"length":204,"previous":"M21-GAP-00162","next":"M21-GAP-00164"},"M21-GAP-00164":{"line":3419,"offset":597719,"length":200,"previous":"M21-GAP-00163","next":"M21-GAP-00165"},"M21-GAP-00165":{"line":3420,"offset":597919,"length":200,"previous":"M21-GAP-00164","next":"M21-GAP-00166"},"M21-GAP-00166":{"line":3421,"offset":598119,"length":200,"previous":"M21-GAP-00165","next":"M21-GAP-00167"},"M21-GAP-00167":{"line":3422,"offset":598319,"length":200,"previous":"M21-GAP-00166","next":"M21-GAP-00168"},"M21-GAP-00168":{"line":3423,"offset":598519,"length":200,"previous":"M21-GAP-00167","next":"M21-GAP-00169"},"M21-GAP-00169":{"line":3424,"offset":598719,"length":203,"previous":"M21-GAP-00168","next":"M21-GAP-00170"},"M21-GAP-00170":{"line":3425,"offset":598922,"length":200,"previous":"M21-GAP-00169","next":"M21-GAP-00171"},"M21-GAP-00171":{"line":3426,"offset":599122,"length":204,"previous":"M21-GAP-00170","next":"M21-GAP-00172"},"M21-GAP-00172":{"line":3427,"offset":599326,"length":202,"previous":"M21-GAP-00171","next":"M21-GAP-00173"},"M21-GAP-00173":{"line":3428,"offset":599528,"length":208,"previous":"M21-GAP-00172","next":"M21-GAP-00174"},"M21-GAP-00174":{"line":3429,"offset":599736,"length":204,"previous":"M21-GAP-00173","next":"M21-GAP-00175"},"M21-GAP-00175":{"line":3430,"offset":599940,"length":204,"previous":"M21-GAP-00174","next":"M21-GAP-00176"},"M21-GAP-00176":{"line":3431,"offset":600144,"length":204,"previous":"M21-GAP-00175","next":"M21-GAP-00177"},"M21-GAP-00177":{"line":3432,"offset":600348,"length":204,"previous":"M21-GAP-00176","next":"M21-GAP-00178"},"M21-GAP-00178":{"line":3433,"offset":600552,"length":204,"previous":"M21-GAP-00177","next":"M21-GAP-00179"},"M21-GAP-00179":{"line":3434,"offset":600756,"length":204,"previous":"M21-GAP-00178","next":"M21-GAP-00180"},"M21-GAP-00180":{"line":3435,"offset":600960,"length":204,"previous":"M21-GAP-00179","next":"M21-GAP-00181"},"M21-GAP-00181":{"line":3436,"offset":601164,"length":204,"previous":"M21-GAP-00180","next":"M21-GAP-00182"},"M21-GAP-00182":{"line":3437,"offset":601368,"length":204,"previous":"M21-GAP-00181","next":"M21-GAP-00183"},"M21-GAP-00183":{"line":3438,"offset":601572,"length":204,"previous":"M21-GAP-00182","next":"M21-GAP-00184"},"M21-GAP-00184":{"line":3439,"offset":601776,"length":204,"previous":"M21-GAP-00183","next":"M21-GAP-00185"},"M21-GAP-00185":{"line":3440,"offset":601980,"length":204,"previous":"M21-GAP-00184","next":"M21-GAP-00186"},"M21-GAP-00186":{"line":3441,"offset":602184,"length":204,"previous":"M21-GAP-00185","next":"M21-GAP-00187"},"M21-GAP-00187":{"line":3442,"offset":602388,"length":204,"previous":"M21-GAP-00186","next":"M21-GAP-00188"},"M21-GAP-00188":{"line":3443,"offset":602592,"length":204,"previous":"M21-GAP-00187","next":"M21-GAP-00189"},"M21-GAP-00189":{"line":3444,"offset":602796,"length":193,"previous":"M21-GAP-00188","next":"M21-GAP-00190"},"M21-GAP-00190":{"line":3445,"offset":602989,"length":193,"previous":"M21-GAP-00189","next":"M21-GAP-00191"},"M21-GAP-00191":{"line":3446,"offset":603182,"length":193,"previous":"M21-GAP-00190","next":"M21-GAP-00192"},"M21-GAP-00192":{"line":3447,"offset":603375,"length":193,"previous":"M21-GAP-00191","next":"M21-GAP-00193"},"M21-GAP-00193":{"line":3448,"offset":603568,"length":193,"previous":"M21-GAP-00192","next":"M21-GAP-00194"},"M21-GAP-00194":{"line":3449,"offset":603761,"length":193,"previous":"M21-GAP-00193","next":"M21-GAP-00195"},"M21-GAP-00195":{"line":3450,"offset":603954,"length":193,"previous":"M21-GAP-00194","next":"M21-GAP-00196"},"M21-GAP-00196":{"line":3451,"offset":604147,"length":193,"previous":"M21-GAP-00195","next":"M21-GAP-00197"},"M21-GAP-00197":{"line":3452,"offset":604340,"length":193,"previous":"M21-GAP-00196","next":"M21-GAP-00198"},"M21-GAP-00198":{"line":3453,"offset":604533,"length":193,"previous":"M21-GAP-00197","next":"M21-GAP-00199"},"M21-GAP-00199":{"line":3454,"offset":604726,"length":207,"previous":"M21-GAP-00198","next":"M21-GAP-00200"},"M21-GAP-00200":{"line":3455,"offset":604933,"length":207,"previous":"M21-GAP-00199","next":"M21-GAP-00201"},"M21-GAP-00201":{"line":3456,"offset":605140,"length":207,"previous":"M21-GAP-00200","next":"M21-GAP-00202"},"M21-GAP-00202":{"line":3457,"offset":605347,"length":207,"previous":"M21-GAP-00201","next":"M21-GAP-00203"},"M21-GAP-00203":{"line":3458,"offset":605554,"length":207,"previous":"M21-GAP-00202","next":"M21-GAP-00204"},"M21-GAP-00204":{"line":3459,"offset":605761,"length":207,"previous":"M21-GAP-00203","next":"M21-GAP-00205"},"M21-GAP-00205":{"line":3460,"offset":605968,"length":207,"previous":"M21-GAP-00204","next":"M21-GAP-00206"},"M21-GAP-00206":{"line":3461,"offset":606175,"length":207,"previous":"M21-GAP-00205","next":"M21-GAP-00207"},"M21-GAP-00207":{"line":3462,"offset":606382,"length":207,"previous":"M21-GAP-00206","next":"M21-GAP-00208"},"M21-GAP-00208":{"line":3463,"offset":606589,"length":196,"previous":"M21-GAP-00207","next":"M21-GAP-00209"},"M21-GAP-00209":{"line":3464,"offset":606785,"length":196,"previous":"M21-GAP-00208","next":"M21-GAP-00210"},"M21-GAP-00210":{"line":3465,"offset":606981,"length":196,"previous":"M21-GAP-00209","next":"M21-GAP-00211"},"M21-GAP-00211":{"line":3466,"offset":607177,"length":196,"previous":"M21-GAP-00210","next":"M21-GAP-00212"},"M21-GAP-00212":{"line":3467,"offset":607373,"length":196,"previous":"M21-GAP-00211","next":"M21-GAP-00213"},"M21-GAP-00213":{"line":3468,"offset":607569,"length":196,"previous":"M21-GAP-00212","next":"M21-GAP-00214"},"M21-GAP-00214":{"line":3469,"offset":607765,"length":196,"previous":"M21-GAP-00213","next":"M21-GAP-00215"},"M21-GAP-00215":{"line":3470,"offset":607961,"length":196,"previous":"M21-GAP-00214","next":"M21-GAP-00216"},"M21-GAP-00216":{"line":3471,"offset":608157,"length":196,"previous":"M21-GAP-00215","next":"M21-GAP-00217"},"M21-GAP-00217":{"line":3472,"offset":608353,"length":206,"previous":"M21-GAP-00216","next":"M21-GAP-00218"},"M21-GAP-00218":{"line":3473,"offset":608559,"length":206,"previous":"M21-GAP-00217","next":"M21-GAP-00219"},"M21-GAP-00219":{"line":3474,"offset":608765,"length":206,"previous":"M21-GAP-00218","next":"M21-GAP-00220"},"M21-GAP-00220":{"line":3475,"offset":608971,"length":206,"previous":"M21-GAP-00219","next":"M21-GAP-00221"},"M21-GAP-00221":{"line":3476,"offset":609177,"length":206,"previous":"M21-GAP-00220","next":"M21-GAP-00222"},"M21-GAP-00222":{"line":3477,"offset":609383,"length":206,"previous":"M21-GAP-00221","next":"M21-GAP-00223"},"M21-GAP-00223":{"line":3478,"offset":609589,"length":206,"previous":"M21-GAP-00222","next":"M21-GAP-00224"},"M21-GAP-00224":{"line":3479,"offset":609795,"length":206,"previous":"M21-GAP-00223","next":"M21-GAP-00225"},"M21-GAP-00225":{"line":3480,"offset":610001,"length":206,"previous":"M21-GAP-00224","next":"M21-GAP-00226"},"M21-GAP-00226":{"line":3481,"offset":610207,"length":206,"previous":"M21-GAP-00225","next":"M21-GAP-00227"},"M21-GAP-00227":{"line":3482,"offset":610413,"length":195,"previous":"M21-GAP-00226","next":"M21-GAP-00228"},"M21-GAP-00228":{"line":3483,"offset":610608,"length":195,"previous":"M21-GAP-00227","next":"M21-GAP-00229"},"M21-GAP-00229":{"line":3484,"offset":610803,"length":195,"previous":"M21-GAP-00228","next":"M21-GAP-00230"},"M21-GAP-00230":{"line":3485,"offset":610998,"length":195,"previous":"M21-GAP-00229","next":"M21-GAP-00231"},"M21-GAP-00231":{"line":3486,"offset":611193,"length":195,"previous":"M21-GAP-00230","next":"M21-GAP-00232"},"M21-GAP-00232":{"line":3487,"offset":611388,"length":195,"previous":"M21-GAP-00231","next":"M21-GAP-00233"},"M21-GAP-00233":{"line":3488,"offset":611583,"length":195,"previous":"M21-GAP-00232","next":"M21-GAP-00234"},"M21-GAP-00234":{"line":3489,"offset":611778,"length":195,"previous":"M21-GAP-00233","next":"M21-GAP-00235"},"M21-GAP-00235":{"line":3490,"offset":611973,"length":195,"previous":"M21-GAP-00234","next":"M21-GAP-00236"},"M21-GAP-00236":{"line":3491,"offset":612168,"length":195,"previous":"M21-GAP-00235","next":"M21-GAP-00237"},"M21-GAP-00237":{"line":3492,"offset":612363,"length":188,"previous":"M21-GAP-00236","next":"M21-GAP-00238"},"M21-GAP-00238":{"line":3493,"offset":612551,"length":188,"previous":"M21-GAP-00237","next":"M21-GAP-00239"},"M21-GAP-00239":{"line":3494,"offset":612739,"length":188,"previous":"M21-GAP-00238","next":"M21-GAP-00240"},"M21-GAP-00240":{"line":3495,"offset":612927,"length":192,"previous":"M21-GAP-00239","next":"M21-GAP-00241"},"M21-GAP-00241":{"line":3496,"offset":613119,"length":199,"previous":"M21-GAP-00240","next":"M21-GAP-00242"},"M21-GAP-00242":{"line":3497,"offset":613318,"length":199,"previous":"M21-GAP-00241","next":"M21-GAP-00243"},"M21-GAP-00243":{"line":3498,"offset":613517,"length":199,"previous":"M21-GAP-00242","next":"M21-GAP-00244"},"M21-GAP-00244":{"line":3499,"offset":613716,"length":199,"previous":"M21-GAP-00243","next":"M21-GAP-00245"},"M21-GAP-00245":{"line":3500,"offset":613915,"length":199,"previous":"M21-GAP-00244","next":"M21-GAP-00246"},"M21-GAP-00246":{"line":3501,"offset":614114,"length":199,"previous":"M21-GAP-00245","next":"M21-GAP-00247"},"M21-GAP-00247":{"line":3502,"offset":614313,"length":199,"previous":"M21-GAP-00246","next":"M21-GAP-00248"},"M21-GAP-00248":{"line":3503,"offset":614512,"length":199,"previous":"M21-GAP-00247","next":"M21-GAP-00249"},"M21-GAP-00249":{"line":3504,"offset":614711,"length":199,"previous":"M21-GAP-00248","next":"M21-GAP-00250"},"M21-GAP-00250":{"line":3505,"offset":614910,"length":188,"previous":"M21-GAP-00249","next":"M21-GAP-00251"},"M21-GAP-00251":{"line":3506,"offset":615098,"length":188,"previous":"M21-GAP-00250","next":"M21-GAP-00252"},"M21-GAP-00252":{"line":3507,"offset":615286,"length":188,"previous":"M21-GAP-00251","next":"M21-GAP-00253"},"M21-GAP-00253":{"line":3508,"offset":615474,"length":188,"previous":"M21-GAP-00252","next":"M21-GAP-00254"},"M21-GAP-00254":{"line":3509,"offset":615662,"length":188,"previous":"M21-GAP-00253","next":"M21-GAP-00255"},"M21-GAP-00255":{"line":3510,"offset":615850,"length":188,"previous":"M21-GAP-00254","next":"M21-GAP-00256"},"M21-GAP-00256":{"line":3511,"offset":616038,"length":188,"previous":"M21-GAP-00255","next":"M21-GAP-00257"},"M21-GAP-00257":{"line":3512,"offset":616226,"length":188,"previous":"M21-GAP-00256","next":"M21-GAP-00258"},"M21-GAP-00258":{"line":3513,"offset":616414,"length":188,"previous":"M21-GAP-00257","next":"M21-GAP-00259"},"M21-GAP-00259":{"line":3514,"offset":616602,"length":176,"previous":"M21-GAP-00258","next":"M21-GAP-00260"},"M21-GAP-00260":{"line":3515,"offset":616778,"length":176,"previous":"M21-GAP-00259","next":"M21-GAP-00261"},"M21-GAP-00261":{"line":3516,"offset":616954,"length":177,"previous":"M21-GAP-00260","next":"M21-GAP-00262"},"M21-GAP-00262":{"line":3517,"offset":617131,"length":178,"previous":"M21-GAP-00261","next":"M21-GAP-00263"},"M21-GAP-00263":{"line":3518,"offset":617309,"length":178,"previous":"M21-GAP-00262","next":"M21-GAP-00264"},"M21-GAP-00264":{"line":3519,"offset":617487,"length":178,"previous":"M21-GAP-00263","next":"M21-GAP-00265"},"M21-GAP-00265":{"line":3520,"offset":617665,"length":178,"previous":"M21-GAP-00264","next":"M21-GAP-00266"},"M21-GAP-00266":{"line":3521,"offset":617843,"length":178,"previous":"M21-GAP-00265","next":"M21-GAP-00267"},"M21-GAP-00267":{"line":3522,"offset":618021,"length":178,"previous":"M21-GAP-00266","next":"M21-GAP-00268"},"M21-GAP-00268":{"line":3523,"offset":618199,"length":178,"previous":"M21-GAP-00267","next":"M21-GAP-00269"},"M21-GAP-00269":{"line":3524,"offset":618377,"length":178,"previous":"M21-GAP-00268","next":"M21-GAP-00270"},"M21-GAP-00270":{"line":3525,"offset":618555,"length":178,"previous":"M21-GAP-00269","next":"M21-GAP-00271"},"M21-GAP-00271":{"line":3526,"offset":618733,"length":178,"previous":"M21-GAP-00270","next":"M21-GAP-00272"},"M21-GAP-00272":{"line":3527,"offset":618911,"length":177,"previous":"M21-GAP-00271","next":"M21-GAP-00273"},"M21-GAP-00273":{"line":3528,"offset":619088,"length":178,"previous":"M21-GAP-00272","next":"M21-GAP-00274"},"M21-GAP-00274":{"line":3529,"offset":619266,"length":178,"previous":"M21-GAP-00273","next":"M21-GAP-00275"},"M21-GAP-00275":{"line":3530,"offset":619444,"length":178,"previous":"M21-GAP-00274","next":"M21-GAP-00276"},"M21-GAP-00276":{"line":3531,"offset":619622,"length":178,"previous":"M21-GAP-00275","next":"M21-GAP-00277"},"M21-GAP-00277":{"line":3532,"offset":619800,"length":178,"previous":"M21-GAP-00276","next":"M21-GAP-00278"},"M21-GAP-00278":{"line":3533,"offset":619978,"length":178,"previous":"M21-GAP-00277","next":"M21-GAP-00279"},"M21-GAP-00279":{"line":3534,"offset":620156,"length":177,"previous":"M21-GAP-00278","next":"M21-GAP-00280"},"M21-GAP-00280":{"line":3535,"offset":620333,"length":177,"previous":"M21-GAP-00279","next":"M21-GAP-00281"},"M21-GAP-00281":{"line":3536,"offset":620510,"length":177,"previous":"M21-GAP-00280","next":"M21-GAP-00282"},"M21-GAP-00282":{"line":3537,"offset":620687,"length":177,"previous":"M21-GAP-00281","next":"M21-GAP-00283"},"M21-GAP-00283":{"line":3538,"offset":620864,"length":177,"previous":"M21-GAP-00282","next":"M21-GAP-00284"},"M21-GAP-00284":{"line":3539,"offset":621041,"length":177,"previous":"M21-GAP-00283","next":"M21-GAP-00285"},"M21-GAP-00285":{"line":3540,"offset":621218,"length":177,"previous":"M21-GAP-00284","next":"M21-GAP-00286"},"M21-GAP-00286":{"line":3541,"offset":621395,"length":177,"previous":"M21-GAP-00285","next":"M21-GAP-00287"},"M21-GAP-00287":{"line":3542,"offset":621572,"length":176,"previous":"M21-GAP-00286","next":"M21-GAP-00288"},"M21-GAP-00288":{"line":3543,"offset":621748,"length":177,"previous":"M21-GAP-00287","next":"M21-GAP-00289"},"M21-GAP-00289":{"line":3544,"offset":621925,"length":177,"previous":"M21-GAP-00288","next":"M21-GAP-00290"},"M21-GAP-00290":{"line":3545,"offset":622102,"length":177,"previous":"M21-GAP-00289","next":"M21-GAP-00291"},"M21-GAP-00291":{"line":3546,"offset":622279,"length":177,"previous":"M21-GAP-00290","next":"M21-GAP-00292"},"M21-GAP-00292":{"line":3547,"offset":622456,"length":177,"previous":"M21-GAP-00291","next":"M21-GAP-00293"},"M21-GAP-00293":{"line":3548,"offset":622633,"length":177,"previous":"M21-GAP-00292","next":"M21-GAP-00294"},"M21-GAP-00294":{"line":3549,"offset":622810,"length":177,"previous":"M21-GAP-00293","next":"M21-GAP-00295"},"M21-GAP-00295":{"line":3550,"offset":622987,"length":177,"previous":"M21-GAP-00294","next":"M21-GAP-00296"},"M21-GAP-00296":{"line":3551,"offset":623164,"length":177,"previous":"M21-GAP-00295","next":"M21-GAP-00297"},"M21-GAP-00297":{"line":3552,"offset":623341,"length":177,"previous":"M21-GAP-00296","next":"M21-GAP-00298"},"M21-GAP-00298":{"line":3553,"offset":623518,"length":176,"previous":"M21-GAP-00297","next":"M21-GAP-00299"},"M21-GAP-00299":{"line":3554,"offset":623694,"length":177,"previous":"M21-GAP-00298","next":"M21-GAP-00300"},"M21-GAP-00300":{"line":3555,"offset":623871,"length":177,"previous":"M21-GAP-00299","next":"M21-GAP-00301"},"M21-GAP-00301":{"line":3556,"offset":624048,"length":177,"previous":"M21-GAP-00300","next":"M21-GAP-00302"},"M21-GAP-00302":{"line":3557,"offset":624225,"length":177,"previous":"M21-GAP-00301","next":"M21-GAP-00303"},"M21-GAP-00303":{"line":3558,"offset":624402,"length":177,"previous":"M21-GAP-00302","next":"M21-GAP-00304"},"M21-GAP-00304":{"line":3559,"offset":624579,"length":177,"previous":"M21-GAP-00303","next":"M21-GAP-00305"},"M21-GAP-00305":{"line":3560,"offset":624756,"length":177,"previous":"M21-GAP-00304","next":"M21-GAP-00306"},"M21-GAP-00306":{"line":3561,"offset":624933,"length":177,"previous":"M21-GAP-00305","next":"M21-GAP-00307"},"M21-GAP-00307":{"line":3562,"offset":625110,"length":177,"previous":"M21-GAP-00306","next":"M21-GAP-00308"},"M21-GAP-00308":{"line":3563,"offset":625287,"length":177,"previous":"M21-GAP-00307","next":"M21-GAP-00309"},"M21-GAP-00309":{"line":3564,"offset":625464,"length":176,"previous":"M21-GAP-00308","next":"M21-GAP-00310"},"M21-GAP-00310":{"line":3565,"offset":625640,"length":177,"previous":"M21-GAP-00309","next":"M21-GAP-00311"},"M21-GAP-00311":{"line":3566,"offset":625817,"length":177,"previous":"M21-GAP-00310","next":"M21-GAP-00312"},"M21-GAP-00312":{"line":3567,"offset":625994,"length":177,"previous":"M21-GAP-00311","next":"M21-GAP-00313"},"M21-GAP-00313":{"line":3568,"offset":626171,"length":177,"previous":"M21-GAP-00312","next":"M21-GAP-00314"},"M21-GAP-00314":{"line":3569,"offset":626348,"length":177,"previous":"M21-GAP-00313","next":"M21-GAP-00315"},"M21-GAP-00315":{"line":3570,"offset":626525,"length":177,"previous":"M21-GAP-00314","next":"M21-GAP-00316"},"M21-GAP-00316":{"line":3571,"offset":626702,"length":177,"previous":"M21-GAP-00315","next":"M21-GAP-00317"},"M21-GAP-00317":{"line":3572,"offset":626879,"length":177,"previous":"M21-GAP-00316","next":"M21-GAP-00318"},"M21-GAP-00318":{"line":3573,"offset":627056,"length":177,"previous":"M21-GAP-00317","next":"M21-GAP-00319"},"M21-GAP-00319":{"line":3574,"offset":627233,"length":177,"previous":"M21-GAP-00318","next":"M21-GAP-00320"},"M21-GAP-00320":{"line":3575,"offset":627410,"length":176,"previous":"M21-GAP-00319","next":"M21-GAP-00321"},"M21-GAP-00321":{"line":3576,"offset":627586,"length":177,"previous":"M21-GAP-00320","next":"M21-GAP-00322"},"M21-GAP-00322":{"line":3577,"offset":627763,"length":177,"previous":"M21-GAP-00321","next":"M21-GAP-00323"},"M21-GAP-00323":{"line":3578,"offset":627940,"length":177,"previous":"M21-GAP-00322","next":"M21-GAP-00324"},"M21-GAP-00324":{"line":3579,"offset":628117,"length":177,"previous":"M21-GAP-00323","next":"M21-GAP-00325"},"M21-GAP-00325":{"line":3580,"offset":628294,"length":177,"previous":"M21-GAP-00324","next":"M21-GAP-00326"},"M21-GAP-00326":{"line":3581,"offset":628471,"length":177,"previous":"M21-GAP-00325","next":"M21-GAP-00327"},"M21-GAP-00327":{"line":3582,"offset":628648,"length":177,"previous":"M21-GAP-00326","next":"M21-GAP-00328"},"M21-GAP-00328":{"line":3583,"offset":628825,"length":177,"previous":"M21-GAP-00327","next":"M21-GAP-00329"},"M21-GAP-00329":{"line":3584,"offset":629002,"length":177,"previous":"M21-GAP-00328","next":"M21-GAP-00330"},"M21-GAP-00330":{"line":3585,"offset":629179,"length":177,"previous":"M21-GAP-00329","next":"M21-GAP-00331"},"M21-GAP-00331":{"line":3586,"offset":629356,"length":176,"previous":"M21-GAP-00330","next":"M21-GAP-00332"},"M21-GAP-00332":{"line":3587,"offset":629532,"length":177,"previous":"M21-GAP-00331","next":"M21-GAP-00333"},"M21-GAP-00333":{"line":3588,"offset":629709,"length":177,"previous":"M21-GAP-00332","next":"M21-GAP-00334"},"M21-GAP-00334":{"line":3589,"offset":629886,"length":177,"previous":"M21-GAP-00333","next":"M21-GAP-00335"},"M21-GAP-00335":{"line":3590,"offset":630063,"length":177,"previous":"M21-GAP-00334","next":"M21-GAP-00336"},"M21-GAP-00336":{"line":3591,"offset":630240,"length":177,"previous":"M21-GAP-00335","next":"M21-GAP-00337"},"M21-GAP-00337":{"line":3592,"offset":630417,"length":177,"previous":"M21-GAP-00336","next":"M21-GAP-00338"},"M21-GAP-00338":{"line":3593,"offset":630594,"length":177,"previous":"M21-GAP-00337","next":"M21-GAP-00339"},"M21-GAP-00339":{"line":3594,"offset":630771,"length":177,"previous":"M21-GAP-00338","next":"M21-GAP-00340"},"M21-GAP-00340":{"line":3595,"offset":630948,"length":177,"previous":"M21-GAP-00339","next":"M21-GAP-00341"},"M21-GAP-00341":{"line":3596,"offset":631125,"length":177,"previous":"M21-GAP-00340","next":"M21-GAP-00342"},"M21-GAP-00342":{"line":3597,"offset":631302,"length":176,"previous":"M21-GAP-00341","next":"M21-GAP-00343"},"M21-GAP-00343":{"line":3598,"offset":631478,"length":177,"previous":"M21-GAP-00342","next":"M21-GAP-00344"},"M21-GAP-00344":{"line":3599,"offset":631655,"length":177,"previous":"M21-GAP-00343","next":"M21-GAP-00345"},"M21-GAP-00345":{"line":3600,"offset":631832,"length":177,"previous":"M21-GAP-00344","next":"M21-GAP-00346"},"M21-GAP-00346":{"line":3601,"offset":632009,"length":177,"previous":"M21-GAP-00345","next":"M21-GAP-00347"},"M21-GAP-00347":{"line":3602,"offset":632186,"length":177,"previous":"M21-GAP-00346","next":"M21-GAP-00348"},"M21-GAP-00348":{"line":3603,"offset":632363,"length":177,"previous":"M21-GAP-00347","next":"M21-GAP-00349"},"M21-GAP-00349":{"line":3604,"offset":632540,"length":177,"previous":"M21-GAP-00348","next":"M21-GAP-00350"},"M21-GAP-00350":{"line":3605,"offset":632717,"length":177,"previous":"M21-GAP-00349","next":"M21-GAP-00351"},"M21-GAP-00351":{"line":3606,"offset":632894,"length":177,"previous":"M21-GAP-00350","next":"M21-GAP-00352"},"M21-GAP-00352":{"line":3607,"offset":633071,"length":177,"previous":"M21-GAP-00351","next":"M21-GAP-00353"},"M21-GAP-00353":{"line":3608,"offset":633248,"length":176,"previous":"M21-GAP-00352","next":"M21-GAP-00354"},"M21-GAP-00354":{"line":3609,"offset":633424,"length":177,"previous":"M21-GAP-00353","next":"M21-GAP-00355"},"M21-GAP-00355":{"line":3610,"offset":633601,"length":177,"previous":"M21-GAP-00354","next":"M21-GAP-00356"},"M21-GAP-00356":{"line":3611,"offset":633778,"length":177,"previous":"M21-GAP-00355","next":"M21-GAP-00357"},"M21-GAP-00357":{"line":3612,"offset":633955,"length":177,"previous":"M21-GAP-00356","next":"M21-GAP-00358"},"M21-GAP-00358":{"line":3613,"offset":634132,"length":177,"previous":"M21-GAP-00357","next":"M21-GAP-00359"},"M21-GAP-00359":{"line":3614,"offset":634309,"length":177,"previous":"M21-GAP-00358","next":"M21-GAP-00360"},"M21-GAP-00360":{"line":3615,"offset":634486,"length":177,"previous":"M21-GAP-00359","next":"M21-GAP-00361"},"M21-GAP-00361":{"line":3616,"offset":634663,"length":177,"previous":"M21-GAP-00360","next":"M21-GAP-00362"},"M21-GAP-00362":{"line":3617,"offset":634840,"length":177,"previous":"M21-GAP-00361","next":"M21-GAP-00363"},"M21-GAP-00363":{"line":3618,"offset":635017,"length":177,"previous":"M21-GAP-00362","next":"M21-GAP-00364"},"M21-GAP-00364":{"line":3619,"offset":635194,"length":176,"previous":"M21-GAP-00363","next":"M21-GAP-00365"},"M21-GAP-00365":{"line":3620,"offset":635370,"length":177,"previous":"M21-GAP-00364","next":"M21-GAP-00366"},"M21-GAP-00366":{"line":3621,"offset":635547,"length":177,"previous":"M21-GAP-00365","next":"M21-GAP-00367"},"M21-GAP-00367":{"line":3622,"offset":635724,"length":177,"previous":"M21-GAP-00366","next":"M21-GAP-00368"},"M21-GAP-00368":{"line":3623,"offset":635901,"length":177,"previous":"M21-GAP-00367","next":"M21-GAP-00369"},"M21-GAP-00369":{"line":3624,"offset":636078,"length":177,"previous":"M21-GAP-00368","next":"M21-GAP-00370"},"M21-GAP-00370":{"line":3625,"offset":636255,"length":177,"previous":"M21-GAP-00369","next":"M21-GAP-00371"},"M21-GAP-00371":{"line":3626,"offset":636432,"length":177,"previous":"M21-GAP-00370","next":"M21-GAP-00372"},"M21-GAP-00372":{"line":3627,"offset":636609,"length":177,"previous":"M21-GAP-00371","next":"M21-GAP-00373"},"M21-GAP-00373":{"line":3628,"offset":636786,"length":177,"previous":"M21-GAP-00372","next":"M21-GAP-00374"},"M21-GAP-00374":{"line":3629,"offset":636963,"length":177,"previous":"M21-GAP-00373","next":"M21-GAP-00375"},"M21-GAP-00375":{"line":3630,"offset":637140,"length":185,"previous":"M21-GAP-00374","next":"M21-GAP-00376"},"M21-GAP-00376":{"line":3631,"offset":637325,"length":185,"previous":"M21-GAP-00375","next":"M21-GAP-00377"},"M21-GAP-00377":{"line":3632,"offset":637510,"length":186,"previous":"M21-GAP-00376","next":"M21-GAP-00378"},"M21-GAP-00378":{"line":3633,"offset":637696,"length":186,"previous":"M21-GAP-00377","next":"M21-GAP-00379"},"M21-GAP-00379":{"line":3634,"offset":637882,"length":186,"previous":"M21-GAP-00378","next":"M21-GAP-00380"},"M21-GAP-00380":{"line":3635,"offset":638068,"length":186,"previous":"M21-GAP-00379","next":"M21-GAP-00381"},"M21-GAP-00381":{"line":3636,"offset":638254,"length":186,"previous":"M21-GAP-00380","next":"M21-GAP-00382"},"M21-GAP-00382":{"line":3637,"offset":638440,"length":186,"previous":"M21-GAP-00381","next":"M21-GAP-00383"},"M21-GAP-00383":{"line":3638,"offset":638626,"length":186,"previous":"M21-GAP-00382","next":"M21-GAP-00384"},"M21-GAP-00384":{"line":3639,"offset":638812,"length":186,"previous":"M21-GAP-00383","next":"M21-GAP-00385"},"M21-GAP-00385":{"line":3640,"offset":638998,"length":186,"previous":"M21-GAP-00384","next":"M21-GAP-00386"},"M21-GAP-00386":{"line":3641,"offset":639184,"length":186,"previous":"M21-GAP-00385","next":"M21-GAP-00387"},"M21-GAP-00387":{"line":3642,"offset":639370,"length":185,"previous":"M21-GAP-00386","next":"M21-GAP-00388"},"M21-GAP-00388":{"line":3643,"offset":639555,"length":186,"previous":"M21-GAP-00387","next":"M21-GAP-00389"},"M21-GAP-00389":{"line":3644,"offset":639741,"length":186,"previous":"M21-GAP-00388","next":"M21-GAP-00390"},"M21-GAP-00390":{"line":3645,"offset":639927,"length":186,"previous":"M21-GAP-00389","next":"M21-GAP-00391"},"M21-GAP-00391":{"line":3646,"offset":640113,"length":186,"previous":"M21-GAP-00390","next":"M21-GAP-00392"},"M21-GAP-00392":{"line":3647,"offset":640299,"length":186,"previous":"M21-GAP-00391","next":"M21-GAP-00393"},"M21-GAP-00393":{"line":3648,"offset":640485,"length":186,"previous":"M21-GAP-00392","next":"M21-GAP-00394"},"M21-GAP-00394":{"line":3649,"offset":640671,"length":186,"previous":"M21-GAP-00393","next":"M21-GAP-00395"},"M21-GAP-00395":{"line":3650,"offset":640857,"length":186,"previous":"M21-GAP-00394","next":"M21-GAP-00396"},"M21-GAP-00396":{"line":3651,"offset":641043,"length":186,"previous":"M21-GAP-00395","next":"M21-GAP-00397"},"M21-GAP-00397":{"line":3652,"offset":641229,"length":186,"previous":"M21-GAP-00396","next":"M21-GAP-00398"},"M21-GAP-00398":{"line":3653,"offset":641415,"length":185,"previous":"M21-GAP-00397","next":"M21-GAP-00399"},"M21-GAP-00399":{"line":3654,"offset":641600,"length":186,"previous":"M21-GAP-00398","next":"M21-GAP-00400"},"M21-GAP-00400":{"line":3655,"offset":641786,"length":186,"previous":"M21-GAP-00399","next":"M21-GAP-00401"},"M21-GAP-00401":{"line":3656,"offset":641972,"length":186,"previous":"M21-GAP-00400","next":"M21-GAP-00402"},"M21-GAP-00402":{"line":3657,"offset":642158,"length":186,"previous":"M21-GAP-00401","next":"M21-GAP-00403"},"M21-GAP-00403":{"line":3658,"offset":642344,"length":186,"previous":"M21-GAP-00402","next":"M21-GAP-00404"},"M21-GAP-00404":{"line":3659,"offset":642530,"length":186,"previous":"M21-GAP-00403","next":"M21-GAP-00405"},"M21-GAP-00405":{"line":3660,"offset":642716,"length":186,"previous":"M21-GAP-00404","next":"M21-GAP-00406"},"M21-GAP-00406":{"line":3661,"offset":642902,"length":185,"previous":"M21-GAP-00405","next":"M21-GAP-00407"},"M21-GAP-00407":{"line":3662,"offset":643087,"length":185,"previous":"M21-GAP-00406","next":"M21-GAP-00408"},"M21-GAP-00408":{"line":3663,"offset":643272,"length":185,"previous":"M21-GAP-00407","next":"M21-GAP-00409"},"M21-GAP-00409":{"line":3664,"offset":643457,"length":185,"previous":"M21-GAP-00408","next":"M21-GAP-00410"},"M21-GAP-00410":{"line":3665,"offset":643642,"length":185,"previous":"M21-GAP-00409","next":"M21-GAP-00411"},"M21-GAP-00411":{"line":3666,"offset":643827,"length":185,"previous":"M21-GAP-00410","next":"M21-GAP-00412"},"M21-GAP-00412":{"line":3667,"offset":644012,"length":176,"previous":"M21-GAP-00411","next":"M21-GAP-00413"},"M21-GAP-00413":{"line":3668,"offset":644188,"length":176,"previous":"M21-GAP-00412","next":"M21-GAP-00414"},"M21-GAP-00414":{"line":3669,"offset":644364,"length":176,"previous":"M21-GAP-00413","next":"M21-GAP-00415"},"M21-GAP-00415":{"line":3670,"offset":644540,"length":176,"previous":"M21-GAP-00414","next":"M21-GAP-00416"},"M21-GAP-00416":{"line":3671,"offset":644716,"length":176,"previous":"M21-GAP-00415","next":"M21-GAP-00417"},"M21-GAP-00417":{"line":3672,"offset":644892,"length":175,"previous":"M21-GAP-00416","next":"M21-GAP-00418"},"M21-GAP-00418":{"line":3673,"offset":645067,"length":175,"previous":"M21-GAP-00417","next":"M21-GAP-00419"},"M21-GAP-00419":{"line":3674,"offset":645242,"length":176,"previous":"M21-GAP-00418","next":"M21-GAP-00420"},"M21-GAP-00420":{"line":3675,"offset":645418,"length":176,"previous":"M21-GAP-00419","next":"M21-GAP-00421"},"M21-GAP-00421":{"line":3676,"offset":645594,"length":176,"previous":"M21-GAP-00420","next":"M21-GAP-00422"},"M21-GAP-00422":{"line":3677,"offset":645770,"length":176,"previous":"M21-GAP-00421","next":"M21-GAP-00423"},"M21-GAP-00423":{"line":3678,"offset":645946,"length":176,"previous":"M21-GAP-00422","next":"M21-GAP-00424"},"M21-GAP-00424":{"line":3679,"offset":646122,"length":176,"previous":"M21-GAP-00423","next":"M21-GAP-00425"},"M21-GAP-00425":{"line":3680,"offset":646298,"length":176,"previous":"M21-GAP-00424","next":"M21-GAP-00426"},"M21-GAP-00426":{"line":3681,"offset":646474,"length":176,"previous":"M21-GAP-00425","next":"M21-GAP-00427"},"M21-GAP-00427":{"line":3682,"offset":646650,"length":176,"previous":"M21-GAP-00426","next":"M21-GAP-00428"},"M21-GAP-00428":{"line":3683,"offset":646826,"length":176,"previous":"M21-GAP-00427","next":"M21-GAP-00429"},"M21-GAP-00429":{"line":3684,"offset":647002,"length":175,"previous":"M21-GAP-00428","next":"M21-GAP-00430"},"M21-GAP-00430":{"line":3685,"offset":647177,"length":176,"previous":"M21-GAP-00429","next":"M21-GAP-00431"},"M21-GAP-00431":{"line":3686,"offset":647353,"length":176,"previous":"M21-GAP-00430","next":"M21-GAP-00432"},"M21-GAP-00432":{"line":3687,"offset":647529,"length":176,"previous":"M21-GAP-00431","next":"M21-GAP-00433"},"M21-GAP-00433":{"line":3688,"offset":647705,"length":176,"previous":"M21-GAP-00432","next":"M21-GAP-00434"},"M21-GAP-00434":{"line":3689,"offset":647881,"length":176,"previous":"M21-GAP-00433","next":"M21-GAP-00435"},"M21-GAP-00435":{"line":3690,"offset":648057,"length":176,"previous":"M21-GAP-00434","next":"M21-GAP-00436"},"M21-GAP-00436":{"line":3691,"offset":648233,"length":176,"previous":"M21-GAP-00435","next":"M21-GAP-00437"},"M21-GAP-00437":{"line":3692,"offset":648409,"length":176,"previous":"M21-GAP-00436","next":"M21-GAP-00438"},"M21-GAP-00438":{"line":3693,"offset":648585,"length":176,"previous":"M21-GAP-00437","next":"M21-GAP-00439"},"M21-GAP-00439":{"line":3694,"offset":648761,"length":176,"previous":"M21-GAP-00438","next":"M21-GAP-00440"},"M21-GAP-00440":{"line":3695,"offset":648937,"length":175,"previous":"M21-GAP-00439","next":"M21-GAP-00441"},"M21-GAP-00441":{"line":3696,"offset":649112,"length":176,"previous":"M21-GAP-00440","next":"M21-GAP-00442"},"M21-GAP-00442":{"line":3697,"offset":649288,"length":176,"previous":"M21-GAP-00441","next":"M21-GAP-00443"},"M21-GAP-00443":{"line":3698,"offset":649464,"length":176,"previous":"M21-GAP-00442","next":"M21-GAP-00444"},"M21-GAP-00444":{"line":3699,"offset":649640,"length":176,"previous":"M21-GAP-00443","next":"M21-GAP-00445"},"M21-GAP-00445":{"line":3700,"offset":649816,"length":176,"previous":"M21-GAP-00444","next":"M21-GAP-00446"},"M21-GAP-00446":{"line":3701,"offset":649992,"length":176,"previous":"M21-GAP-00445","next":"M21-GAP-00447"},"M21-GAP-00447":{"line":3702,"offset":650168,"length":176,"previous":"M21-GAP-00446","next":"M21-GAP-00448"},"M21-GAP-00448":{"line":3703,"offset":650344,"length":176,"previous":"M21-GAP-00447","next":"M21-GAP-00449"},"M21-GAP-00449":{"line":3704,"offset":650520,"length":176,"previous":"M21-GAP-00448","next":"M21-GAP-00450"},"M21-GAP-00450":{"line":3705,"offset":650696,"length":176,"previous":"M21-GAP-00449","next":"M21-GAP-00451"},"M21-GAP-00451":{"line":3706,"offset":650872,"length":175,"previous":"M21-GAP-00450","next":"M21-GAP-00452"},"M21-GAP-00452":{"line":3707,"offset":651047,"length":176,"previous":"M21-GAP-00451","next":"M21-GAP-00453"},"M21-GAP-00453":{"line":3708,"offset":651223,"length":176,"previous":"M21-GAP-00452","next":"M21-GAP-00454"},"M21-GAP-00454":{"line":3709,"offset":651399,"length":176,"previous":"M21-GAP-00453","next":"M21-GAP-00455"},"M21-GAP-00455":{"line":3710,"offset":651575,"length":176,"previous":"M21-GAP-00454","next":"M21-GAP-00456"},"M21-GAP-00456":{"line":3711,"offset":651751,"length":176,"previous":"M21-GAP-00455","next":"M21-GAP-00457"},"M21-GAP-00457":{"line":3712,"offset":651927,"length":176,"previous":"M21-GAP-00456","next":"M21-GAP-00458"},"M21-GAP-00458":{"line":3713,"offset":652103,"length":176,"previous":"M21-GAP-00457","next":"M21-GAP-00459"},"M21-GAP-00459":{"line":3714,"offset":652279,"length":176,"previous":"M21-GAP-00458","next":"M21-GAP-00460"},"M21-GAP-00460":{"line":3715,"offset":652455,"length":176,"previous":"M21-GAP-00459","next":"M21-GAP-00461"},"M21-GAP-00461":{"line":3716,"offset":652631,"length":176,"previous":"M21-GAP-00460","next":"M21-GAP-00462"},"M21-GAP-00462":{"line":3717,"offset":652807,"length":175,"previous":"M21-GAP-00461","next":"M21-GAP-00463"},"M21-GAP-00463":{"line":3718,"offset":652982,"length":176,"previous":"M21-GAP-00462","next":"M21-GAP-00464"},"M21-GAP-00464":{"line":3719,"offset":653158,"length":176,"previous":"M21-GAP-00463","next":"M21-GAP-00465"},"M21-GAP-00465":{"line":3720,"offset":653334,"length":175,"previous":"M21-GAP-00464","next":"M21-GAP-00466"},"M21-GAP-00466":{"line":3721,"offset":653509,"length":175,"previous":"M21-GAP-00465","next":"M21-GAP-00467"},"M21-GAP-00467":{"line":3722,"offset":653684,"length":175,"previous":"M21-GAP-00466","next":"M21-GAP-00468"},"M21-GAP-00468":{"line":3723,"offset":653859,"length":175,"previous":"M21-GAP-00467","next":"M21-GAP-00469"},"M21-GAP-00469":{"line":3724,"offset":654034,"length":182,"previous":"M21-GAP-00468","next":"M21-GAP-00470"},"M21-GAP-00470":{"line":3725,"offset":654216,"length":182,"previous":"M21-GAP-00469","next":"M21-GAP-00471"},"M21-GAP-00471":{"line":3726,"offset":654398,"length":183,"previous":"M21-GAP-00470","next":"M21-GAP-00472"},"M21-GAP-00472":{"line":3727,"offset":654581,"length":183,"previous":"M21-GAP-00471","next":"M21-GAP-00473"},"M21-GAP-00473":{"line":3728,"offset":654764,"length":183,"previous":"M21-GAP-00472","next":"M21-GAP-00474"},"M21-GAP-00474":{"line":3729,"offset":654947,"length":183,"previous":"M21-GAP-00473","next":"M21-GAP-00475"},"M21-GAP-00475":{"line":3730,"offset":655130,"length":183,"previous":"M21-GAP-00474","next":"M21-GAP-00476"},"M21-GAP-00476":{"line":3731,"offset":655313,"length":183,"previous":"M21-GAP-00475","next":"M21-GAP-00477"},"M21-GAP-00477":{"line":3732,"offset":655496,"length":183,"previous":"M21-GAP-00476","next":"M21-GAP-00478"},"M21-GAP-00478":{"line":3733,"offset":655679,"length":183,"previous":"M21-GAP-00477","next":"M21-GAP-00479"},"M21-GAP-00479":{"line":3734,"offset":655862,"length":183,"previous":"M21-GAP-00478","next":"M21-GAP-00480"},"M21-GAP-00480":{"line":3735,"offset":656045,"length":183,"previous":"M21-GAP-00479","next":"M21-GAP-00481"},"M21-GAP-00481":{"line":3736,"offset":656228,"length":182,"previous":"M21-GAP-00480","next":"M21-GAP-00482"},"M21-GAP-00482":{"line":3737,"offset":656410,"length":183,"previous":"M21-GAP-00481","next":"M21-GAP-00483"},"M21-GAP-00483":{"line":3738,"offset":656593,"length":183,"previous":"M21-GAP-00482","next":"M21-GAP-00484"},"M21-GAP-00484":{"line":3739,"offset":656776,"length":183,"previous":"M21-GAP-00483","next":"M21-GAP-00485"},"M21-GAP-00485":{"line":3740,"offset":656959,"length":183,"previous":"M21-GAP-00484","next":"M21-GAP-00486"},"M21-GAP-00486":{"line":3741,"offset":657142,"length":183,"previous":"M21-GAP-00485","next":"M21-GAP-00487"},"M21-GAP-00487":{"line":3742,"offset":657325,"length":183,"previous":"M21-GAP-00486","next":"M21-GAP-00488"},"M21-GAP-00488":{"line":3743,"offset":657508,"length":183,"previous":"M21-GAP-00487","next":"M21-GAP-00489"},"M21-GAP-00489":{"line":3744,"offset":657691,"length":183,"previous":"M21-GAP-00488","next":"M21-GAP-00490"},"M21-GAP-00490":{"line":3745,"offset":657874,"length":183,"previous":"M21-GAP-00489","next":"M21-GAP-00491"},"M21-GAP-00491":{"line":3746,"offset":658057,"length":183,"previous":"M21-GAP-00490","next":"M21-GAP-00492"},"M21-GAP-00492":{"line":3747,"offset":658240,"length":182,"previous":"M21-GAP-00491","next":"M21-GAP-00493"},"M21-GAP-00493":{"line":3748,"offset":658422,"length":182,"previous":"M21-GAP-00492","next":"M21-GAP-00494"},"M21-GAP-00494":{"line":3749,"offset":658604,"length":182,"previous":"M21-GAP-00493","next":"M21-GAP-00495"},"M21-GAP-00495":{"line":3750,"offset":658786,"length":182,"previous":"M21-GAP-00494","next":"M21-GAP-00496"},"M21-GAP-00496":{"line":3751,"offset":658968,"length":182,"previous":"M21-GAP-00495","next":"M21-GAP-00497"},"M21-GAP-00497":{"line":3752,"offset":659150,"length":182,"previous":"M21-GAP-00496","next":"M21-GAP-00498"},"M21-GAP-00498":{"line":3753,"offset":659332,"length":182,"previous":"M21-GAP-00497","next":"M21-GAP-00499"},"M21-GAP-00499":{"line":3754,"offset":659514,"length":194,"previous":"M21-GAP-00498","next":"M21-GAP-00500"},"M21-GAP-00500":{"line":3755,"offset":659708,"length":194,"previous":"M21-GAP-00499","next":"M21-GAP-00501"},"M21-GAP-00501":{"line":3756,"offset":659902,"length":194,"previous":"M21-GAP-00500","next":"M21-GAP-00502"},"M21-GAP-00502":{"line":3757,"offset":660096,"length":194,"previous":"M21-GAP-00501","next":"M21-GAP-00503"},"M21-GAP-00503":{"line":3758,"offset":660290,"length":184,"previous":"M21-GAP-00502","next":"M21-GAP-00504"},"M21-GAP-00504":{"line":3759,"offset":660474,"length":184,"previous":"M21-GAP-00503","next":"M21-GAP-00505"},"M21-GAP-00505":{"line":3760,"offset":660658,"length":185,"previous":"M21-GAP-00504","next":"M21-GAP-00506"},"M21-GAP-00506":{"line":3761,"offset":660843,"length":185,"previous":"M21-GAP-00505","next":"M21-GAP-00507"},"M21-GAP-00507":{"line":3762,"offset":661028,"length":185,"previous":"M21-GAP-00506","next":"M21-GAP-00508"},"M21-GAP-00508":{"line":3763,"offset":661213,"length":185,"previous":"M21-GAP-00507","next":"M21-GAP-00509"},"M21-GAP-00509":{"line":3764,"offset":661398,"length":185,"previous":"M21-GAP-00508","next":"M21-GAP-00510"},"M21-GAP-00510":{"line":3765,"offset":661583,"length":185,"previous":"M21-GAP-00509","next":"M21-GAP-00511"},"M21-GAP-00511":{"line":3766,"offset":661768,"length":185,"previous":"M21-GAP-00510","next":"M21-GAP-00512"},"M21-GAP-00512":{"line":3767,"offset":661953,"length":185,"previous":"M21-GAP-00511","next":"M21-GAP-00513"},"M21-GAP-00513":{"line":3768,"offset":662138,"length":185,"previous":"M21-GAP-00512","next":"M21-GAP-00514"},"M21-GAP-00514":{"line":3769,"offset":662323,"length":185,"previous":"M21-GAP-00513","next":"M21-GAP-00515"},"M21-GAP-00515":{"line":3770,"offset":662508,"length":184,"previous":"M21-GAP-00514","next":"M21-GAP-00516"},"M21-GAP-00516":{"line":3771,"offset":662692,"length":185,"previous":"M21-GAP-00515","next":"M21-GAP-00517"},"M21-GAP-00517":{"line":3772,"offset":662877,"length":185,"previous":"M21-GAP-00516","next":"M21-GAP-00518"},"M21-GAP-00518":{"line":3773,"offset":663062,"length":185,"previous":"M21-GAP-00517","next":"M21-GAP-00519"},"M21-GAP-00519":{"line":3774,"offset":663247,"length":185,"previous":"M21-GAP-00518","next":"M21-GAP-00520"},"M21-GAP-00520":{"line":3775,"offset":663432,"length":185,"previous":"M21-GAP-00519","next":"M21-GAP-00521"},"M21-GAP-00521":{"line":3776,"offset":663617,"length":185,"previous":"M21-GAP-00520","next":"M21-GAP-00522"},"M21-GAP-00522":{"line":3777,"offset":663802,"length":185,"previous":"M21-GAP-00521","next":"M21-GAP-00523"},"M21-GAP-00523":{"line":3778,"offset":663987,"length":185,"previous":"M21-GAP-00522","next":"M21-GAP-00524"},"M21-GAP-00524":{"line":3779,"offset":664172,"length":185,"previous":"M21-GAP-00523","next":"M21-GAP-00525"},"M21-GAP-00525":{"line":3780,"offset":664357,"length":185,"previous":"M21-GAP-00524","next":"M21-GAP-00526"},"M21-GAP-00526":{"line":3781,"offset":664542,"length":184,"previous":"M21-GAP-00525","next":"M21-GAP-00527"},"M21-GAP-00527":{"line":3782,"offset":664726,"length":185,"previous":"M21-GAP-00526","next":"M21-GAP-00528"},"M21-GAP-00528":{"line":3783,"offset":664911,"length":185,"previous":"M21-GAP-00527","next":"M21-GAP-00529"},"M21-GAP-00529":{"line":3784,"offset":665096,"length":185,"previous":"M21-GAP-00528","next":"M21-GAP-00530"},"M21-GAP-00530":{"line":3785,"offset":665281,"length":185,"previous":"M21-GAP-00529","next":"M21-GAP-00531"},"M21-GAP-00531":{"line":3786,"offset":665466,"length":185,"previous":"M21-GAP-00530","next":"M21-GAP-00532"},"M21-GAP-00532":{"line":3787,"offset":665651,"length":185,"previous":"M21-GAP-00531","next":"M21-GAP-00533"},"M21-GAP-00533":{"line":3788,"offset":665836,"length":185,"previous":"M21-GAP-00532","next":"M21-GAP-00534"},"M21-GAP-00534":{"line":3789,"offset":666021,"length":185,"previous":"M21-GAP-00533","next":"M21-GAP-00535"},"M21-GAP-00535":{"line":3790,"offset":666206,"length":185,"previous":"M21-GAP-00534","next":"M21-GAP-00536"},"M21-GAP-00536":{"line":3791,"offset":666391,"length":185,"previous":"M21-GAP-00535","next":"M21-GAP-00537"},"M21-GAP-00537":{"line":3792,"offset":666576,"length":184,"previous":"M21-GAP-00536","next":"M21-GAP-00538"},"M21-GAP-00538":{"line":3793,"offset":666760,"length":185,"previous":"M21-GAP-00537","next":"M21-GAP-00539"},"M21-GAP-00539":{"line":3794,"offset":666945,"length":185,"previous":"M21-GAP-00538","next":"M21-GAP-00540"},"M21-GAP-00540":{"line":3795,"offset":667130,"length":185,"previous":"M21-GAP-00539","next":"M21-GAP-00541"},"M21-GAP-00541":{"line":3796,"offset":667315,"length":185,"previous":"M21-GAP-00540","next":"M21-GAP-00542"},"M21-GAP-00542":{"line":3797,"offset":667500,"length":185,"previous":"M21-GAP-00541","next":"M21-GAP-00543"},"M21-GAP-00543":{"line":3798,"offset":667685,"length":185,"previous":"M21-GAP-00542","next":"M21-GAP-00544"},"M21-GAP-00544":{"line":3799,"offset":667870,"length":185,"previous":"M21-GAP-00543","next":"M21-GAP-00545"},"M21-GAP-00545":{"line":3800,"offset":668055,"length":185,"previous":"M21-GAP-00544","next":"M21-GAP-00546"},"M21-GAP-00546":{"line":3801,"offset":668240,"length":185,"previous":"M21-GAP-00545","next":"M21-GAP-00547"},"M21-GAP-00547":{"line":3802,"offset":668425,"length":185,"previous":"M21-GAP-00546","next":"M21-GAP-00548"},"M21-GAP-00548":{"line":3803,"offset":668610,"length":184,"previous":"M21-GAP-00547","next":"M21-GAP-00549"},"M21-GAP-00549":{"line":3804,"offset":668794,"length":185,"previous":"M21-GAP-00548","next":"M21-GAP-00550"},"M21-GAP-00550":{"line":3805,"offset":668979,"length":185,"previous":"M21-GAP-00549","next":"M21-GAP-00551"},"M21-GAP-00551":{"line":3806,"offset":669164,"length":185,"previous":"M21-GAP-00550","next":"M21-GAP-00552"},"M21-GAP-00552":{"line":3807,"offset":669349,"length":185,"previous":"M21-GAP-00551","next":"M21-GAP-00553"},"M21-GAP-00553":{"line":3808,"offset":669534,"length":185,"previous":"M21-GAP-00552","next":"M21-GAP-00554"},"M21-GAP-00554":{"line":3809,"offset":669719,"length":185,"previous":"M21-GAP-00553","next":"M21-GAP-00555"},"M21-GAP-00555":{"line":3810,"offset":669904,"length":185,"previous":"M21-GAP-00554","next":"M21-GAP-00556"},"M21-GAP-00556":{"line":3811,"offset":670089,"length":185,"previous":"M21-GAP-00555","next":"M21-GAP-00557"},"M21-GAP-00557":{"line":3812,"offset":670274,"length":185,"previous":"M21-GAP-00556","next":"M21-GAP-00558"},"M21-GAP-00558":{"line":3813,"offset":670459,"length":185,"previous":"M21-GAP-00557","next":"M21-GAP-00559"},"M21-GAP-00559":{"line":3814,"offset":670644,"length":184,"previous":"M21-GAP-00558","next":"M21-GAP-00560"},"M21-GAP-00560":{"line":3815,"offset":670828,"length":185,"previous":"M21-GAP-00559","next":"M21-GAP-00561"},"M21-GAP-00561":{"line":3816,"offset":671013,"length":185,"previous":"M21-GAP-00560","next":"M21-GAP-00562"},"M21-GAP-00562":{"line":3817,"offset":671198,"length":185,"previous":"M21-GAP-00561","next":"M21-GAP-00563"},"M21-GAP-00563":{"line":3818,"offset":671383,"length":185,"previous":"M21-GAP-00562","next":"M21-GAP-00564"},"M21-GAP-00564":{"line":3819,"offset":671568,"length":185,"previous":"M21-GAP-00563","next":"M21-GAP-00565"},"M21-GAP-00565":{"line":3820,"offset":671753,"length":185,"previous":"M21-GAP-00564","next":"M21-GAP-00566"},"M21-GAP-00566":{"line":3821,"offset":671938,"length":185,"previous":"M21-GAP-00565","next":"M21-GAP-00567"},"M21-GAP-00567":{"line":3822,"offset":672123,"length":185,"previous":"M21-GAP-00566","next":"M21-GAP-00568"},"M21-GAP-00568":{"line":3823,"offset":672308,"length":185,"previous":"M21-GAP-00567","next":"M21-GAP-00569"},"M21-GAP-00569":{"line":3824,"offset":672493,"length":185,"previous":"M21-GAP-00568","next":"M21-GAP-00570"},"M21-GAP-00570":{"line":3825,"offset":672678,"length":184,"previous":"M21-GAP-00569","next":"M21-GAP-00571"},"M21-GAP-00571":{"line":3826,"offset":672862,"length":185,"previous":"M21-GAP-00570","next":"M21-GAP-00572"},"M21-GAP-00572":{"line":3827,"offset":673047,"length":185,"previous":"M21-GAP-00571","next":"M21-GAP-00573"},"M21-GAP-00573":{"line":3828,"offset":673232,"length":185,"previous":"M21-GAP-00572","next":"M21-GAP-00574"},"M21-GAP-00574":{"line":3829,"offset":673417,"length":185,"previous":"M21-GAP-00573","next":"M21-GAP-00575"},"M21-GAP-00575":{"line":3830,"offset":673602,"length":185,"previous":"M21-GAP-00574","next":"M21-GAP-00576"},"M21-GAP-00576":{"line":3831,"offset":673787,"length":185,"previous":"M21-GAP-00575","next":"M21-GAP-00577"},"M21-GAP-00577":{"line":3832,"offset":673972,"length":184,"previous":"M21-GAP-00576","next":"M21-GAP-00578"},"M21-GAP-00578":{"line":3833,"offset":674156,"length":184,"previous":"M21-GAP-00577","next":"M21-GAP-00579"},"M21-GAP-00579":{"line":3834,"offset":674340,"length":190,"previous":"M21-GAP-00578","next":"M21-GAP-00580"},"M21-GAP-00580":{"line":3835,"offset":674530,"length":190,"previous":"M21-GAP-00579","next":"M21-GAP-00581"},"M21-GAP-00581":{"line":3836,"offset":674720,"length":191,"previous":"M21-GAP-00580","next":"M21-GAP-00582"},"M21-GAP-00582":{"line":3837,"offset":674911,"length":191,"previous":"M21-GAP-00581","next":"M21-GAP-00583"},"M21-GAP-00583":{"line":3838,"offset":675102,"length":191,"previous":"M21-GAP-00582","next":"M21-GAP-00584"},"M21-GAP-00584":{"line":3839,"offset":675293,"length":191,"previous":"M21-GAP-00583","next":"M21-GAP-00585"},"M21-GAP-00585":{"line":3840,"offset":675484,"length":191,"previous":"M21-GAP-00584","next":"M21-GAP-00586"},"M21-GAP-00586":{"line":3841,"offset":675675,"length":191,"previous":"M21-GAP-00585","next":"M21-GAP-00587"},"M21-GAP-00587":{"line":3842,"offset":675866,"length":191,"previous":"M21-GAP-00586","next":"M21-GAP-00588"},"M21-GAP-00588":{"line":3843,"offset":676057,"length":191,"previous":"M21-GAP-00587","next":"M21-GAP-00589"},"M21-GAP-00589":{"line":3844,"offset":676248,"length":191,"previous":"M21-GAP-00588","next":"M21-GAP-00590"},"M21-GAP-00590":{"line":3845,"offset":676439,"length":191,"previous":"M21-GAP-00589","next":"M21-GAP-00591"},"M21-GAP-00591":{"line":3846,"offset":676630,"length":190,"previous":"M21-GAP-00590","next":"M21-GAP-00592"},"M21-GAP-00592":{"line":3847,"offset":676820,"length":191,"previous":"M21-GAP-00591","next":"M21-GAP-00593"},"M21-GAP-00593":{"line":3848,"offset":677011,"length":191,"previous":"M21-GAP-00592","next":"M21-GAP-00594"},"M21-GAP-00594":{"line":3849,"offset":677202,"length":191,"previous":"M21-GAP-00593","next":"M21-GAP-00595"},"M21-GAP-00595":{"line":3850,"offset":677393,"length":191,"previous":"M21-GAP-00594","next":"M21-GAP-00596"},"M21-GAP-00596":{"line":3851,"offset":677584,"length":190,"previous":"M21-GAP-00595","next":"M21-GAP-00597"},"M21-GAP-00597":{"line":3852,"offset":677774,"length":190,"previous":"M21-GAP-00596","next":"M21-GAP-00598"},"M21-GAP-00598":{"line":3853,"offset":677964,"length":190,"previous":"M21-GAP-00597","next":"M21-GAP-00599"},"M21-GAP-00599":{"line":3854,"offset":678154,"length":190,"previous":"M21-GAP-00598","next":"M21-GAP-00600"},"M21-GAP-00600":{"line":3855,"offset":678344,"length":190,"previous":"M21-GAP-00599","next":"M21-GAP-00601"},"M21-GAP-00601":{"line":3856,"offset":678534,"length":190,"previous":"M21-GAP-00600","next":"M21-GAP-00602"},"M21-GAP-00602":{"line":3857,"offset":678724,"length":190,"previous":"M21-GAP-00601","next":"M21-GAP-00603"},"M21-GAP-00603":{"line":3858,"offset":678914,"length":189,"previous":"M21-GAP-00602","next":"M21-GAP-00604"},"M21-GAP-00604":{"line":3859,"offset":679103,"length":177,"previous":"M21-GAP-00603","next":"M21-GAP-00605"},"M21-GAP-00605":{"line":3860,"offset":679280,"length":177,"previous":"M21-GAP-00604","next":"M21-GAP-00606"},"M21-GAP-00606":{"line":3861,"offset":679457,"length":178,"previous":"M21-GAP-00605","next":"M21-GAP-00607"},"M21-GAP-00607":{"line":3862,"offset":679635,"length":178,"previous":"M21-GAP-00606","next":"M21-GAP-00608"},"M21-GAP-00608":{"line":3863,"offset":679813,"length":178,"previous":"M21-GAP-00607","next":"M21-GAP-00609"},"M21-GAP-00609":{"line":3864,"offset":679991,"length":178,"previous":"M21-GAP-00608","next":"M21-GAP-00610"},"M21-GAP-00610":{"line":3865,"offset":680169,"length":177,"previous":"M21-GAP-00609","next":"M21-GAP-00611"},"M21-GAP-00611":{"line":3866,"offset":680346,"length":177,"previous":"M21-GAP-00610","next":"M21-GAP-00612"},"M21-GAP-00612":{"line":3867,"offset":680523,"length":177,"previous":"M21-GAP-00611","next":"M21-GAP-00613"},"M21-GAP-00613":{"line":3868,"offset":680700,"length":177,"previous":"M21-GAP-00612","next":"M21-GAP-00614"},"M21-GAP-00614":{"line":3869,"offset":680877,"length":177,"previous":"M21-GAP-00613","next":"M21-GAP-00615"},"M21-GAP-00615":{"line":3870,"offset":681054,"length":177,"previous":"M21-GAP-00614","next":"M21-GAP-00616"},"M21-GAP-00616":{"line":3871,"offset":681231,"length":177,"previous":"M21-GAP-00615","next":"M21-GAP-00617"},"M21-GAP-00617":{"line":3872,"offset":681408,"length":177,"previous":"M21-GAP-00616","next":"M21-GAP-00618"},"M21-GAP-00618":{"line":3873,"offset":681585,"length":176,"previous":"M21-GAP-00617","next":"M21-GAP-00619"},"M21-GAP-00619":{"line":3874,"offset":681761,"length":176,"previous":"M21-GAP-00618","next":"M21-GAP-00620"},"M21-GAP-00620":{"line":3875,"offset":681937,"length":177,"previous":"M21-GAP-00619","next":"M21-GAP-00621"},"M21-GAP-00621":{"line":3876,"offset":682114,"length":177,"previous":"M21-GAP-00620","next":"M21-GAP-00622"},"M21-GAP-00622":{"line":3877,"offset":682291,"length":177,"previous":"M21-GAP-00621","next":"M21-GAP-00623"},"M21-GAP-00623":{"line":3878,"offset":682468,"length":177,"previous":"M21-GAP-00622","next":"M21-GAP-00624"},"M21-GAP-00624":{"line":3879,"offset":682645,"length":177,"previous":"M21-GAP-00623","next":"M21-GAP-00625"},"M21-GAP-00625":{"line":3880,"offset":682822,"length":177,"previous":"M21-GAP-00624","next":"M21-GAP-00626"},"M21-GAP-00626":{"line":3881,"offset":682999,"length":177,"previous":"M21-GAP-00625","next":"M21-GAP-00627"},"M21-GAP-00627":{"line":3882,"offset":683176,"length":177,"previous":"M21-GAP-00626","next":"M21-GAP-00628"},"M21-GAP-00628":{"line":3883,"offset":683353,"length":177,"previous":"M21-GAP-00627","next":"M21-GAP-00629"},"M21-GAP-00629":{"line":3884,"offset":683530,"length":177,"previous":"M21-GAP-00628","next":"M21-GAP-00630"},"M21-GAP-00630":{"line":3885,"offset":683707,"length":176,"previous":"M21-GAP-00629","next":"M21-GAP-00631"},"M21-GAP-00631":{"line":3886,"offset":683883,"length":177,"previous":"M21-GAP-00630","next":"M21-GAP-00632"},"M21-GAP-00632":{"line":3887,"offset":684060,"length":177,"previous":"M21-GAP-00631","next":"M21-GAP-00633"},"M21-GAP-00633":{"line":3888,"offset":684237,"length":177,"previous":"M21-GAP-00632","next":"M21-GAP-00634"},"M21-GAP-00634":{"line":3889,"offset":684414,"length":177,"previous":"M21-GAP-00633","next":"M21-GAP-00635"},"M21-GAP-00635":{"line":3890,"offset":684591,"length":177,"previous":"M21-GAP-00634","next":"M21-GAP-00636"},"M21-GAP-00636":{"line":3891,"offset":684768,"length":177,"previous":"M21-GAP-00635","next":"M21-GAP-00637"},"M21-GAP-00637":{"line":3892,"offset":684945,"length":177,"previous":"M21-GAP-00636","next":"M21-GAP-00638"},"M21-GAP-00638":{"line":3893,"offset":685122,"length":177,"previous":"M21-GAP-00637","next":"M21-GAP-00639"},"M21-GAP-00639":{"line":3894,"offset":685299,"length":177,"previous":"M21-GAP-00638","next":"M21-GAP-00640"},"M21-GAP-00640":{"line":3895,"offset":685476,"length":177,"previous":"M21-GAP-00639","next":"M21-GAP-00641"},"M21-GAP-00641":{"line":3896,"offset":685653,"length":176,"previous":"M21-GAP-00640","next":"M21-GAP-00642"},"M21-GAP-00642":{"line":3897,"offset":685829,"length":177,"previous":"M21-GAP-00641","next":"M21-GAP-00643"},"M21-GAP-00643":{"line":3898,"offset":686006,"length":177,"previous":"M21-GAP-00642","next":"M21-GAP-00644"},"M21-GAP-00644":{"line":3899,"offset":686183,"length":177,"previous":"M21-GAP-00643","next":"M21-GAP-00645"},"M21-GAP-00645":{"line":3900,"offset":686360,"length":177,"previous":"M21-GAP-00644","next":"M21-GAP-00646"},"M21-GAP-00646":{"line":3901,"offset":686537,"length":177,"previous":"M21-GAP-00645","next":"M21-GAP-00647"},"M21-GAP-00647":{"line":3902,"offset":686714,"length":177,"previous":"M21-GAP-00646","next":"M21-GAP-00648"},"M21-GAP-00648":{"line":3903,"offset":686891,"length":177,"previous":"M21-GAP-00647","next":"M21-GAP-00649"},"M21-GAP-00649":{"line":3904,"offset":687068,"length":177,"previous":"M21-GAP-00648","next":"M21-GAP-00650"},"M21-GAP-00650":{"line":3905,"offset":687245,"length":177,"previous":"M21-GAP-00649","next":"M21-GAP-00651"},"M21-GAP-00651":{"line":3906,"offset":687422,"length":177,"previous":"M21-GAP-00650","next":"M21-GAP-00652"},"M21-GAP-00652":{"line":3907,"offset":687599,"length":176,"previous":"M21-GAP-00651","next":"M21-GAP-00653"},"M21-GAP-00653":{"line":3908,"offset":687775,"length":176,"previous":"M21-GAP-00652","next":"M21-GAP-00654"},"M21-GAP-00654":{"line":3909,"offset":687951,"length":176,"previous":"M21-GAP-00653","next":"M21-GAP-00655"},"M21-GAP-00655":{"line":3910,"offset":688127,"length":176,"previous":"M21-GAP-00654","next":"M21-GAP-00656"},"M21-GAP-00656":{"line":3911,"offset":688303,"length":176,"previous":"M21-GAP-00655","next":"M21-GAP-00657"},"M21-GAP-00657":{"line":3912,"offset":688479,"length":176,"previous":"M21-GAP-00656","next":"M21-GAP-00658"},"M21-GAP-00658":{"line":3913,"offset":688655,"length":186,"previous":"M21-GAP-00657","next":"M21-GAP-00659"},"M21-GAP-00659":{"line":3914,"offset":688841,"length":186,"previous":"M21-GAP-00658","next":"M21-GAP-00660"},"M21-GAP-00660":{"line":3915,"offset":689027,"length":186,"previous":"M21-GAP-00659","next":"M21-GAP-00661"},"M21-GAP-00661":{"line":3916,"offset":689213,"length":186,"previous":"M21-GAP-00660","next":"M21-GAP-00662"},"M21-GAP-00662":{"line":3917,"offset":689399,"length":186,"previous":"M21-GAP-00661","next":"M21-GAP-00663"},"M21-GAP-00663":{"line":3918,"offset":689585,"length":172,"previous":"M21-GAP-00662","next":"M21-GAP-00664"},"M21-GAP-00664":{"line":3919,"offset":689757,"length":172,"previous":"M21-GAP-00663","next":"M21-GAP-00665"},"M21-GAP-00665":{"line":3920,"offset":689929,"length":173,"previous":"M21-GAP-00664","next":"M21-GAP-00666"},"M21-GAP-00666":{"line":3921,"offset":690102,"length":173,"previous":"M21-GAP-00665","next":"M21-GAP-00667"},"M21-GAP-00667":{"line":3922,"offset":690275,"length":173,"previous":"M21-GAP-00666","next":"M21-GAP-00668"},"M21-GAP-00668":{"line":3923,"offset":690448,"length":173,"previous":"M21-GAP-00667","next":"M21-GAP-00669"},"M21-GAP-00669":{"line":3924,"offset":690621,"length":173,"previous":"M21-GAP-00668","next":"M21-GAP-00670"},"M21-GAP-00670":{"line":3925,"offset":690794,"length":173,"previous":"M21-GAP-00669","next":"M21-GAP-00671"},"M21-GAP-00671":{"line":3926,"offset":690967,"length":173,"previous":"M21-GAP-00670","next":"M21-GAP-00672"},"M21-GAP-00672":{"line":3927,"offset":691140,"length":173,"previous":"M21-GAP-00671","next":"M21-GAP-00673"},"M21-GAP-00673":{"line":3928,"offset":691313,"length":173,"previous":"M21-GAP-00672","next":"M21-GAP-00674"},"M21-GAP-00674":{"line":3929,"offset":691486,"length":173,"previous":"M21-GAP-00673","next":"M21-GAP-00675"},"M21-GAP-00675":{"line":3930,"offset":691659,"length":172,"previous":"M21-GAP-00674","next":"M21-GAP-00676"},"M21-GAP-00676":{"line":3931,"offset":691831,"length":173,"previous":"M21-GAP-00675","next":"M21-GAP-00677"},"M21-GAP-00677":{"line":3932,"offset":692004,"length":173,"previous":"M21-GAP-00676","next":"M21-GAP-00678"},"M21-GAP-00678":{"line":3933,"offset":692177,"length":173,"previous":"M21-GAP-00677","next":"M21-GAP-00679"},"M21-GAP-00679":{"line":3934,"offset":692350,"length":173,"previous":"M21-GAP-00678","next":"M21-GAP-00680"},"M21-GAP-00680":{"line":3935,"offset":692523,"length":173,"previous":"M21-GAP-00679","next":"M21-GAP-00681"},"M21-GAP-00681":{"line":3936,"offset":692696,"length":173,"previous":"M21-GAP-00680","next":"M21-GAP-00682"},"M21-GAP-00682":{"line":3937,"offset":692869,"length":173,"previous":"M21-GAP-00681","next":"M21-GAP-00683"},"M21-GAP-00683":{"line":3938,"offset":693042,"length":173,"previous":"M21-GAP-00682","next":"M21-GAP-00684"},"M21-GAP-00684":{"line":3939,"offset":693215,"length":173,"previous":"M21-GAP-00683","next":"M21-GAP-00685"},"M21-GAP-00685":{"line":3940,"offset":693388,"length":173,"previous":"M21-GAP-00684","next":"M21-GAP-00686"},"M21-GAP-00686":{"line":3941,"offset":693561,"length":172,"previous":"M21-GAP-00685","next":"M21-GAP-00687"},"M21-GAP-00687":{"line":3942,"offset":693733,"length":173,"previous":"M21-GAP-00686","next":"M21-GAP-00688"},"M21-GAP-00688":{"line":3943,"offset":693906,"length":173,"previous":"M21-GAP-00687","next":"M21-GAP-00689"},"M21-GAP-00689":{"line":3944,"offset":694079,"length":173,"previous":"M21-GAP-00688","next":"M21-GAP-00690"},"M21-GAP-00690":{"line":3945,"offset":694252,"length":173,"previous":"M21-GAP-00689","next":"M21-GAP-00691"},"M21-GAP-00691":{"line":3946,"offset":694425,"length":173,"previous":"M21-GAP-00690","next":"M21-GAP-00692"},"M21-GAP-00692":{"line":3947,"offset":694598,"length":173,"previous":"M21-GAP-00691","next":"M21-GAP-00693"},"M21-GAP-00693":{"line":3948,"offset":694771,"length":173,"previous":"M21-GAP-00692","next":"M21-GAP-00694"},"M21-GAP-00694":{"line":3949,"offset":694944,"length":173,"previous":"M21-GAP-00693","next":"M21-GAP-00695"},"M21-GAP-00695":{"line":3950,"offset":695117,"length":173,"previous":"M21-GAP-00694","next":"M21-GAP-00696"},"M21-GAP-00696":{"line":3951,"offset":695290,"length":173,"previous":"M21-GAP-00695","next":"M21-GAP-00697"},"M21-GAP-00697":{"line":3952,"offset":695463,"length":172,"previous":"M21-GAP-00696","next":"M21-GAP-00698"},"M21-GAP-00698":{"line":3953,"offset":695635,"length":173,"previous":"M21-GAP-00697","next":"M21-GAP-00699"},"M21-GAP-00699":{"line":3954,"offset":695808,"length":173,"previous":"M21-GAP-00698","next":"M21-GAP-00700"},"M21-GAP-00700":{"line":3955,"offset":695981,"length":173,"previous":"M21-GAP-00699","next":"M21-GAP-00701"},"M21-GAP-00701":{"line":3956,"offset":696154,"length":173,"previous":"M21-GAP-00700","next":"M21-GAP-00702"},"M21-GAP-00702":{"line":3957,"offset":696327,"length":173,"previous":"M21-GAP-00701","next":"M21-GAP-00703"},"M21-GAP-00703":{"line":3958,"offset":696500,"length":172,"previous":"M21-GAP-00702","next":"M21-GAP-00704"},"M21-GAP-00704":{"line":3959,"offset":696672,"length":172,"previous":"M21-GAP-00703","next":"M21-GAP-00705"},"M21-GAP-00705":{"line":3960,"offset":696844,"length":172,"previous":"M21-GAP-00704","next":"M21-GAP-00706"},"M21-GAP-00706":{"line":3961,"offset":697016,"length":172,"previous":"M21-GAP-00705","next":"M21-GAP-00707"},"M21-GAP-00707":{"line":3962,"offset":697188,"length":172,"previous":"M21-GAP-00706","next":"M21-GAP-00708"},"M21-GAP-00708":{"line":3963,"offset":697360,"length":173,"previous":"M21-GAP-00707","next":"M21-GAP-00709"},"M21-GAP-00709":{"line":3964,"offset":697533,"length":173,"previous":"M21-GAP-00708","next":"M21-GAP-00710"},"M21-GAP-00710":{"line":3965,"offset":697706,"length":174,"previous":"M21-GAP-00709","next":"M21-GAP-00711"},"M21-GAP-00711":{"line":3966,"offset":697880,"length":174,"previous":"M21-GAP-00710","next":"M21-GAP-00712"},"M21-GAP-00712":{"line":3967,"offset":698054,"length":174,"previous":"M21-GAP-00711","next":"M21-GAP-00713"},"M21-GAP-00713":{"line":3968,"offset":698228,"length":174,"previous":"M21-GAP-00712","next":"M21-GAP-00714"},"M21-GAP-00714":{"line":3969,"offset":698402,"length":174,"previous":"M21-GAP-00713","next":"M21-GAP-00715"},"M21-GAP-00715":{"line":3970,"offset":698576,"length":174,"previous":"M21-GAP-00714","next":"M21-GAP-00716"},"M21-GAP-00716":{"line":3971,"offset":698750,"length":174,"previous":"M21-GAP-00715","next":"M21-GAP-00717"},"M21-GAP-00717":{"line":3972,"offset":698924,"length":174,"previous":"M21-GAP-00716","next":"M21-GAP-00718"},"M21-GAP-00718":{"line":3973,"offset":699098,"length":174,"previous":"M21-GAP-00717","next":"M21-GAP-00719"},"M21-GAP-00719":{"line":3974,"offset":699272,"length":174,"previous":"M21-GAP-00718","next":"M21-GAP-00720"},"M21-GAP-00720":{"line":3975,"offset":699446,"length":173,"previous":"M21-GAP-00719","next":"M21-GAP-00721"},"M21-GAP-00721":{"line":3976,"offset":699619,"length":174,"previous":"M21-GAP-00720","next":"M21-GAP-00722"},"M21-GAP-00722":{"line":3977,"offset":699793,"length":174,"previous":"M21-GAP-00721","next":"M21-GAP-00723"},"M21-GAP-00723":{"line":3978,"offset":699967,"length":174,"previous":"M21-GAP-00722","next":"M21-GAP-00724"},"M21-GAP-00724":{"line":3979,"offset":700141,"length":174,"previous":"M21-GAP-00723","next":"M21-GAP-00725"},"M21-GAP-00725":{"line":3980,"offset":700315,"length":174,"previous":"M21-GAP-00724","next":"M21-GAP-00726"},"M21-GAP-00726":{"line":3981,"offset":700489,"length":174,"previous":"M21-GAP-00725","next":"M21-GAP-00727"},"M21-GAP-00727":{"line":3982,"offset":700663,"length":174,"previous":"M21-GAP-00726","next":"M21-GAP-00728"},"M21-GAP-00728":{"line":3983,"offset":700837,"length":174,"previous":"M21-GAP-00727","next":"M21-GAP-00729"},"M21-GAP-00729":{"line":3984,"offset":701011,"length":174,"previous":"M21-GAP-00728","next":"M21-GAP-00730"},"M21-GAP-00730":{"line":3985,"offset":701185,"length":174,"previous":"M21-GAP-00729","next":"M21-GAP-00731"},"M21-GAP-00731":{"line":3986,"offset":701359,"length":173,"previous":"M21-GAP-00730","next":"M21-GAP-00732"},"M21-GAP-00732":{"line":3987,"offset":701532,"length":174,"previous":"M21-GAP-00731","next":"M21-GAP-00733"},"M21-GAP-00733":{"line":3988,"offset":701706,"length":174,"previous":"M21-GAP-00732","next":"M21-GAP-00734"},"M21-GAP-00734":{"line":3989,"offset":701880,"length":174,"previous":"M21-GAP-00733","next":"M21-GAP-00735"},"M21-GAP-00735":{"line":3990,"offset":702054,"length":174,"previous":"M21-GAP-00734","next":"M21-GAP-00736"},"M21-GAP-00736":{"line":3991,"offset":702228,"length":173,"previous":"M21-GAP-00735","next":"M21-GAP-00737"},"M21-GAP-00737":{"line":3992,"offset":702401,"length":173,"previous":"M21-GAP-00736","next":"M21-GAP-00738"},"M21-GAP-00738":{"line":3993,"offset":702574,"length":173,"previous":"M21-GAP-00737","next":"M21-GAP-00739"},"M21-GAP-00739":{"line":3994,"offset":702747,"length":173,"previous":"M21-GAP-00738","next":"M21-GAP-00740"},"M21-GAP-00740":{"line":3995,"offset":702920,"length":173,"previous":"M21-GAP-00739","next":"M21-GAP-00741"},"M21-GAP-00741":{"line":3996,"offset":703093,"length":173,"previous":"M21-GAP-00740","next":"M21-GAP-00742"},"M21-GAP-00742":{"line":3997,"offset":703266,"length":191,"previous":"M21-GAP-00741","next":"M21-GAP-00743"},"M21-GAP-00743":{"line":3998,"offset":703457,"length":191,"previous":"M21-GAP-00742","next":"M21-GAP-00744"},"M21-GAP-00744":{"line":3999,"offset":703648,"length":192,"previous":"M21-GAP-00743","next":"M21-GAP-00745"},"M21-GAP-00745":{"line":4000,"offset":703840,"length":192,"previous":"M21-GAP-00744","next":"M21-GAP-00746"},"M21-GAP-00746":{"line":4001,"offset":704032,"length":192,"previous":"M21-GAP-00745","next":"M21-GAP-00747"},"M21-GAP-00747":{"line":4002,"offset":704224,"length":192,"previous":"M21-GAP-00746","next":"M21-GAP-00748"},"M21-GAP-00748":{"line":4003,"offset":704416,"length":191,"previous":"M21-GAP-00747","next":"M21-GAP-00749"},"M21-GAP-00749":{"line":4004,"offset":704607,"length":191,"previous":"M21-GAP-00748","next":"M21-GAP-00750"},"M21-GAP-00750":{"line":4005,"offset":704798,"length":191,"previous":"M21-GAP-00749","next":"M21-GAP-00751"},"M21-GAP-00751":{"line":4006,"offset":704989,"length":191,"previous":"M21-GAP-00750","next":"M21-GAP-00752"},"M21-GAP-00752":{"line":4007,"offset":705180,"length":191,"previous":"M21-GAP-00751","next":"M21-GAP-00753"},"M21-GAP-00753":{"line":4008,"offset":705371,"length":191,"previous":"M21-GAP-00752","next":"M21-GAP-00754"},"M21-GAP-00754":{"line":4009,"offset":705562,"length":191,"previous":"M21-GAP-00753","next":"M21-GAP-00755"},"M21-GAP-00755":{"line":4010,"offset":705753,"length":191,"previous":"M21-GAP-00754","next":"M21-GAP-00756"},"M21-GAP-00756":{"line":4011,"offset":705944,"length":195,"previous":"M21-GAP-00755","next":"M21-GAP-00757"},"M21-GAP-00757":{"line":4012,"offset":706139,"length":195,"previous":"M21-GAP-00756","next":"M21-GAP-00758"},"M21-GAP-00758":{"line":4013,"offset":706334,"length":195,"previous":"M21-GAP-00757","next":"M21-GAP-00759"},"M21-GAP-00759":{"line":4014,"offset":706529,"length":187,"previous":"M21-GAP-00758","next":"M21-GAP-00760"},"M21-GAP-00760":{"line":4015,"offset":706716,"length":187,"previous":"M21-GAP-00759","next":"M21-GAP-00761"},"M21-GAP-00761":{"line":4016,"offset":706903,"length":188,"previous":"M21-GAP-00760","next":"M21-GAP-00762"},"M21-GAP-00762":{"line":4017,"offset":707091,"length":188,"previous":"M21-GAP-00761","next":"M21-GAP-00763"},"M21-GAP-00763":{"line":4018,"offset":707279,"length":188,"previous":"M21-GAP-00762","next":"M21-GAP-00764"},"M21-GAP-00764":{"line":4019,"offset":707467,"length":188,"previous":"M21-GAP-00763","next":"M21-GAP-00765"},"M21-GAP-00765":{"line":4020,"offset":707655,"length":188,"previous":"M21-GAP-00764","next":"M21-GAP-00766"},"M21-GAP-00766":{"line":4021,"offset":707843,"length":188,"previous":"M21-GAP-00765","next":"M21-GAP-00767"},"M21-GAP-00767":{"line":4022,"offset":708031,"length":188,"previous":"M21-GAP-00766","next":"M21-GAP-00768"},"M21-GAP-00768":{"line":4023,"offset":708219,"length":188,"previous":"M21-GAP-00767","next":"M21-GAP-00769"},"M21-GAP-00769":{"line":4024,"offset":708407,"length":188,"previous":"M21-GAP-00768","next":"M21-GAP-00770"},"M21-GAP-00770":{"line":4025,"offset":708595,"length":188,"previous":"M21-GAP-00769","next":"M21-GAP-00771"},"M21-GAP-00771":{"line":4026,"offset":708783,"length":187,"previous":"M21-GAP-00770","next":"M21-GAP-00772"},"M21-GAP-00772":{"line":4027,"offset":708970,"length":188,"previous":"M21-GAP-00771","next":"M21-GAP-00773"},"M21-GAP-00773":{"line":4028,"offset":709158,"length":188,"previous":"M21-GAP-00772","next":"M21-GAP-00774"},"M21-GAP-00774":{"line":4029,"offset":709346,"length":188,"previous":"M21-GAP-00773","next":"M21-GAP-00775"},"M21-GAP-00775":{"line":4030,"offset":709534,"length":188,"previous":"M21-GAP-00774","next":"M21-GAP-00776"},"M21-GAP-00776":{"line":4031,"offset":709722,"length":188,"previous":"M21-GAP-00775","next":"M21-GAP-00777"},"M21-GAP-00777":{"line":4032,"offset":709910,"length":188,"previous":"M21-GAP-00776","next":"M21-GAP-00778"},"M21-GAP-00778":{"line":4033,"offset":710098,"length":188,"previous":"M21-GAP-00777","next":"M21-GAP-00779"},"M21-GAP-00779":{"line":4034,"offset":710286,"length":188,"previous":"M21-GAP-00778","next":"M21-GAP-00780"},"M21-GAP-00780":{"line":4035,"offset":710474,"length":188,"previous":"M21-GAP-00779","next":"M21-GAP-00781"},"M21-GAP-00781":{"line":4036,"offset":710662,"length":188,"previous":"M21-GAP-00780","next":"M21-GAP-00782"},"M21-GAP-00782":{"line":4037,"offset":710850,"length":187,"previous":"M21-GAP-00781","next":"M21-GAP-00783"},"M21-GAP-00783":{"line":4038,"offset":711037,"length":188,"previous":"M21-GAP-00782","next":"M21-GAP-00784"},"M21-GAP-00784":{"line":4039,"offset":711225,"length":188,"previous":"M21-GAP-00783","next":"M21-GAP-00785"},"M21-GAP-00785":{"line":4040,"offset":711413,"length":188,"previous":"M21-GAP-00784","next":"M21-GAP-00786"},"M21-GAP-00786":{"line":4041,"offset":711601,"length":188,"previous":"M21-GAP-00785","next":"M21-GAP-00787"},"M21-GAP-00787":{"line":4042,"offset":711789,"length":188,"previous":"M21-GAP-00786","next":"M21-GAP-00788"},"M21-GAP-00788":{"line":4043,"offset":711977,"length":188,"previous":"M21-GAP-00787","next":"M21-GAP-00789"},"M21-GAP-00789":{"line":4044,"offset":712165,"length":188,"previous":"M21-GAP-00788","next":"M21-GAP-00790"},"M21-GAP-00790":{"line":4045,"offset":712353,"length":188,"previous":"M21-GAP-00789","next":"M21-GAP-00791"},"M21-GAP-00791":{"line":4046,"offset":712541,"length":188,"previous":"M21-GAP-00790","next":"M21-GAP-00792"},"M21-GAP-00792":{"line":4047,"offset":712729,"length":188,"previous":"M21-GAP-00791","next":"M21-GAP-00793"},"M21-GAP-00793":{"line":4048,"offset":712917,"length":187,"previous":"M21-GAP-00792","next":"M21-GAP-00794"},"M21-GAP-00794":{"line":4049,"offset":713104,"length":188,"previous":"M21-GAP-00793","next":"M21-GAP-00795"},"M21-GAP-00795":{"line":4050,"offset":713292,"length":188,"previous":"M21-GAP-00794","next":"M21-GAP-00796"},"M21-GAP-00796":{"line":4051,"offset":713480,"length":188,"previous":"M21-GAP-00795","next":"M21-GAP-00797"},"M21-GAP-00797":{"line":4052,"offset":713668,"length":188,"previous":"M21-GAP-00796","next":"M21-GAP-00798"},"M21-GAP-00798":{"line":4053,"offset":713856,"length":188,"previous":"M21-GAP-00797","next":"M21-GAP-00799"},"M21-GAP-00799":{"line":4054,"offset":714044,"length":188,"previous":"M21-GAP-00798","next":"M21-GAP-00800"},"M21-GAP-00800":{"line":4055,"offset":714232,"length":188,"previous":"M21-GAP-00799","next":"M21-GAP-00801"},"M21-GAP-00801":{"line":4056,"offset":714420,"length":188,"previous":"M21-GAP-00800","next":"M21-GAP-00802"},"M21-GAP-00802":{"line":4057,"offset":714608,"length":188,"previous":"M21-GAP-00801","next":"M21-GAP-00803"},"M21-GAP-00803":{"line":4058,"offset":714796,"length":188,"previous":"M21-GAP-00802","next":"M21-GAP-00804"},"M21-GAP-00804":{"line":4059,"offset":714984,"length":187,"previous":"M21-GAP-00803","next":"M21-GAP-00805"},"M21-GAP-00805":{"line":4060,"offset":715171,"length":188,"previous":"M21-GAP-00804","next":"M21-GAP-00806"},"M21-GAP-00806":{"line":4061,"offset":715359,"length":188,"previous":"M21-GAP-00805","next":"M21-GAP-00807"},"M21-GAP-00807":{"line":4062,"offset":715547,"length":188,"previous":"M21-GAP-00806","next":"M21-GAP-00808"},"M21-GAP-00808":{"line":4063,"offset":715735,"length":188,"previous":"M21-GAP-00807","next":"M21-GAP-00809"},"M21-GAP-00809":{"line":4064,"offset":715923,"length":188,"previous":"M21-GAP-00808","next":"M21-GAP-00810"},"M21-GAP-00810":{"line":4065,"offset":716111,"length":188,"previous":"M21-GAP-00809","next":"M21-GAP-00811"},"M21-GAP-00811":{"line":4066,"offset":716299,"length":188,"previous":"M21-GAP-00810","next":"M21-GAP-00812"},"M21-GAP-00812":{"line":4067,"offset":716487,"length":188,"previous":"M21-GAP-00811","next":"M21-GAP-00813"},"M21-GAP-00813":{"line":4068,"offset":716675,"length":188,"previous":"M21-GAP-00812","next":"M21-GAP-00814"},"M21-GAP-00814":{"line":4069,"offset":716863,"length":188,"previous":"M21-GAP-00813","next":"M21-GAP-00815"},"M21-GAP-00815":{"line":4070,"offset":717051,"length":187,"previous":"M21-GAP-00814","next":"M21-GAP-00816"},"M21-GAP-00816":{"line":4071,"offset":717238,"length":188,"previous":"M21-GAP-00815","next":"M21-GAP-00817"},"M21-GAP-00817":{"line":4072,"offset":717426,"length":188,"previous":"M21-GAP-00816","next":"M21-GAP-00818"},"M21-GAP-00818":{"line":4073,"offset":717614,"length":188,"previous":"M21-GAP-00817","next":"M21-GAP-00819"},"M21-GAP-00819":{"line":4074,"offset":717802,"length":188,"previous":"M21-GAP-00818","next":"M21-GAP-00820"},"M21-GAP-00820":{"line":4075,"offset":717990,"length":188,"previous":"M21-GAP-00819","next":"M21-GAP-00821"},"M21-GAP-00821":{"line":4076,"offset":718178,"length":188,"previous":"M21-GAP-00820","next":"M21-GAP-00822"},"M21-GAP-00822":{"line":4077,"offset":718366,"length":188,"previous":"M21-GAP-00821","next":"M21-GAP-00823"},"M21-GAP-00823":{"line":4078,"offset":718554,"length":188,"previous":"M21-GAP-00822","next":"M21-GAP-00824"},"M21-GAP-00824":{"line":4079,"offset":718742,"length":187,"previous":"M21-GAP-00823","next":"M21-GAP-00825"},"M21-GAP-00825":{"line":4080,"offset":718929,"length":187,"previous":"M21-GAP-00824","next":"M21-GAP-00826"},"M21-GAP-00826":{"line":4081,"offset":719116,"length":187,"previous":"M21-GAP-00825","next":"M21-GAP-00827"},"M21-GAP-00827":{"line":4082,"offset":719303,"length":205,"previous":"M21-GAP-00826","next":"M21-GAP-00828"},"M21-GAP-00828":{"line":4083,"offset":719508,"length":205,"previous":"M21-GAP-00827","next":"M21-GAP-00829"},"M21-GAP-00829":{"line":4084,"offset":719713,"length":205,"previous":"M21-GAP-00828","next":"M21-GAP-00830"},"M21-GAP-00830":{"line":4085,"offset":719918,"length":205,"previous":"M21-GAP-00829","next":"M21-GAP-00831"},"M21-GAP-00831":{"line":4086,"offset":720123,"length":205,"previous":"M21-GAP-00830","next":"M21-GAP-00832"},"M21-GAP-00832":{"line":4087,"offset":720328,"length":205,"previous":"M21-GAP-00831","next":"M21-GAP-00833"},"M21-GAP-00833":{"line":4088,"offset":720533,"length":205,"previous":"M21-GAP-00832","next":"M21-GAP-00834"},"M21-GAP-00834":{"line":4089,"offset":720738,"length":187,"previous":"M21-GAP-00833","next":"M21-GAP-00835"},"M21-GAP-00835":{"line":4090,"offset":720925,"length":187,"previous":"M21-GAP-00834","next":"M21-GAP-00836"},"M21-GAP-00836":{"line":4091,"offset":721112,"length":187,"previous":"M21-GAP-00835","next":"M21-GAP-00837"},"M21-GAP-00837":{"line":4092,"offset":721299,"length":187,"previous":"M21-GAP-00836","next":"M21-GAP-00838"},"M21-GAP-00838":{"line":4093,"offset":721486,"length":187,"previous":"M21-GAP-00837","next":"M21-GAP-00839"},"M21-GAP-00839":{"line":4094,"offset":721673,"length":187,"previous":"M21-GAP-00838","next":"M21-GAP-00840"},"M21-GAP-00840":{"line":4095,"offset":721860,"length":187,"previous":"M21-GAP-00839","next":"M21-GAP-00841"},"M21-GAP-00841":{"line":4096,"offset":722047,"length":194,"previous":"M21-GAP-00840","next":"M21-GAP-00842"},"M21-GAP-00842":{"line":4097,"offset":722241,"length":194,"previous":"M21-GAP-00841","next":"M21-GAP-00843"},"M21-GAP-00843":{"line":4098,"offset":722435,"length":194,"previous":"M21-GAP-00842","next":"M21-GAP-00844"},"M21-GAP-00844":{"line":4099,"offset":722629,"length":194,"previous":"M21-GAP-00843","next":"M21-GAP-00845"},"M21-GAP-00845":{"line":4100,"offset":722823,"length":194,"previous":"M21-GAP-00844","next":"M21-GAP-00846"},"M21-GAP-00846":{"line":4101,"offset":723017,"length":194,"previous":"M21-GAP-00845","next":"M21-GAP-00847"},"M21-GAP-00847":{"line":4102,"offset":723211,"length":191,"previous":"M21-GAP-00846","next":"M21-GAP-00848"},"M21-GAP-00848":{"line":4103,"offset":723402,"length":191,"previous":"M21-GAP-00847","next":"M21-GAP-00849"},"M21-GAP-00849":{"line":4104,"offset":723593,"length":192,"previous":"M21-GAP-00848","next":"M21-GAP-00850"},"M21-GAP-00850":{"line":4105,"offset":723785,"length":192,"previous":"M21-GAP-00849","next":"M21-GAP-00851"},"M21-GAP-00851":{"line":4106,"offset":723977,"length":192,"previous":"M21-GAP-00850","next":"M21-GAP-00852"},"M21-GAP-00852":{"line":4107,"offset":724169,"length":192,"previous":"M21-GAP-00851","next":"M21-GAP-00853"},"M21-GAP-00853":{"line":4108,"offset":724361,"length":192,"previous":"M21-GAP-00852","next":"M21-GAP-00854"},"M21-GAP-00854":{"line":4109,"offset":724553,"length":192,"previous":"M21-GAP-00853","next":"M21-GAP-00855"},"M21-GAP-00855":{"line":4110,"offset":724745,"length":192,"previous":"M21-GAP-00854","next":"M21-GAP-00856"},"M21-GAP-00856":{"line":4111,"offset":724937,"length":192,"previous":"M21-GAP-00855","next":"M21-GAP-00857"},"M21-GAP-00857":{"line":4112,"offset":725129,"length":192,"previous":"M21-GAP-00856","next":"M21-GAP-00858"},"M21-GAP-00858":{"line":4113,"offset":725321,"length":192,"previous":"M21-GAP-00857","next":"M21-GAP-00859"},"M21-GAP-00859":{"line":4114,"offset":725513,"length":191,"previous":"M21-GAP-00858","next":"M21-GAP-00860"},"M21-GAP-00860":{"line":4115,"offset":725704,"length":192,"previous":"M21-GAP-00859","next":"M21-GAP-00861"},"M21-GAP-00861":{"line":4116,"offset":725896,"length":192,"previous":"M21-GAP-00860","next":"M21-GAP-00862"},"M21-GAP-00862":{"line":4117,"offset":726088,"length":192,"previous":"M21-GAP-00861","next":"M21-GAP-00863"},"M21-GAP-00863":{"line":4118,"offset":726280,"length":192,"previous":"M21-GAP-00862","next":"M21-GAP-00864"},"M21-GAP-00864":{"line":4119,"offset":726472,"length":192,"previous":"M21-GAP-00863","next":"M21-GAP-00865"},"M21-GAP-00865":{"line":4120,"offset":726664,"length":192,"previous":"M21-GAP-00864","next":"M21-GAP-00866"},"M21-GAP-00866":{"line":4121,"offset":726856,"length":192,"previous":"M21-GAP-00865","next":"M21-GAP-00867"},"M21-GAP-00867":{"line":4122,"offset":727048,"length":192,"previous":"M21-GAP-00866","next":"M21-GAP-00868"},"M21-GAP-00868":{"line":4123,"offset":727240,"length":192,"previous":"M21-GAP-00867","next":"M21-GAP-00869"},"M21-GAP-00869":{"line":4124,"offset":727432,"length":192,"previous":"M21-GAP-00868","next":"M21-GAP-00870"},"M21-GAP-00870":{"line":4125,"offset":727624,"length":191,"previous":"M21-GAP-00869","next":"M21-GAP-00871"},"M21-GAP-00871":{"line":4126,"offset":727815,"length":192,"previous":"M21-GAP-00870","next":"M21-GAP-00872"},"M21-GAP-00872":{"line":4127,"offset":728007,"length":192,"previous":"M21-GAP-00871","next":"M21-GAP-00873"},"M21-GAP-00873":{"line":4128,"offset":728199,"length":191,"previous":"M21-GAP-00872","next":"M21-GAP-00874"},"M21-GAP-00874":{"line":4129,"offset":728390,"length":191,"previous":"M21-GAP-00873","next":"M21-GAP-00875"},"M21-GAP-00875":{"line":4130,"offset":728581,"length":191,"previous":"M21-GAP-00874","next":"M21-GAP-00876"},"M21-GAP-00876":{"line":4131,"offset":728772,"length":191,"previous":"M21-GAP-00875","next":"M21-GAP-00877"},"M21-GAP-00877":{"line":4132,"offset":728963,"length":191,"previous":"M21-GAP-00876","next":"M21-GAP-00878"},"M21-GAP-00878":{"line":4133,"offset":729154,"length":191,"previous":"M21-GAP-00877","next":"M21-GAP-00879"},"M21-GAP-00879":{"line":4134,"offset":729345,"length":186,"previous":"M21-GAP-00878","next":"M21-GAP-00880"},"M21-GAP-00880":{"line":4135,"offset":729531,"length":186,"previous":"M21-GAP-00879","next":"M21-GAP-00881"},"M21-GAP-00881":{"line":4136,"offset":729717,"length":187,"previous":"M21-GAP-00880","next":"M21-GAP-00882"},"M21-GAP-00882":{"line":4137,"offset":729904,"length":187,"previous":"M21-GAP-00881","next":"M21-GAP-00883"},"M21-GAP-00883":{"line":4138,"offset":730091,"length":187,"previous":"M21-GAP-00882","next":"M21-GAP-00884"},"M21-GAP-00884":{"line":4139,"offset":730278,"length":187,"previous":"M21-GAP-00883","next":"M21-GAP-00885"},"M21-GAP-00885":{"line":4140,"offset":730465,"length":187,"previous":"M21-GAP-00884","next":"M21-GAP-00886"},"M21-GAP-00886":{"line":4141,"offset":730652,"length":187,"previous":"M21-GAP-00885","next":"M21-GAP-00887"},"M21-GAP-00887":{"line":4142,"offset":730839,"length":187,"previous":"M21-GAP-00886","next":"M21-GAP-00888"},"M21-GAP-00888":{"line":4143,"offset":731026,"length":187,"previous":"M21-GAP-00887","next":"M21-GAP-00889"},"M21-GAP-00889":{"line":4144,"offset":731213,"length":187,"previous":"M21-GAP-00888","next":"M21-GAP-00890"},"M21-GAP-00890":{"line":4145,"offset":731400,"length":187,"previous":"M21-GAP-00889","next":"M21-GAP-00891"},"M21-GAP-00891":{"line":4146,"offset":731587,"length":186,"previous":"M21-GAP-00890","next":"M21-GAP-00892"},"M21-GAP-00892":{"line":4147,"offset":731773,"length":187,"previous":"M21-GAP-00891","next":"M21-GAP-00893"},"M21-GAP-00893":{"line":4148,"offset":731960,"length":187,"previous":"M21-GAP-00892","next":"M21-GAP-00894"},"M21-GAP-00894":{"line":4149,"offset":732147,"length":187,"previous":"M21-GAP-00893","next":"M21-GAP-00895"},"M21-GAP-00895":{"line":4150,"offset":732334,"length":187,"previous":"M21-GAP-00894","next":"M21-GAP-00896"},"M21-GAP-00896":{"line":4151,"offset":732521,"length":187,"previous":"M21-GAP-00895","next":"M21-GAP-00897"},"M21-GAP-00897":{"line":4152,"offset":732708,"length":187,"previous":"M21-GAP-00896","next":"M21-GAP-00898"},"M21-GAP-00898":{"line":4153,"offset":732895,"length":187,"previous":"M21-GAP-00897","next":"M21-GAP-00899"},"M21-GAP-00899":{"line":4154,"offset":733082,"length":187,"previous":"M21-GAP-00898","next":"M21-GAP-00900"},"M21-GAP-00900":{"line":4155,"offset":733269,"length":187,"previous":"M21-GAP-00899","next":"M21-GAP-00901"},"M21-GAP-00901":{"line":4156,"offset":733456,"length":187,"previous":"M21-GAP-00900","next":"M21-GAP-00902"},"M21-GAP-00902":{"line":4157,"offset":733643,"length":186,"previous":"M21-GAP-00901","next":"M21-GAP-00903"},"M21-GAP-00903":{"line":4158,"offset":733829,"length":187,"previous":"M21-GAP-00902","next":"M21-GAP-00904"},"M21-GAP-00904":{"line":4159,"offset":734016,"length":187,"previous":"M21-GAP-00903","next":"M21-GAP-00905"},"M21-GAP-00905":{"line":4160,"offset":734203,"length":186,"previous":"M21-GAP-00904","next":"M21-GAP-00906"},"M21-GAP-00906":{"line":4161,"offset":734389,"length":186,"previous":"M21-GAP-00905","next":"M21-GAP-00907"},"M21-GAP-00907":{"line":4162,"offset":734575,"length":186,"previous":"M21-GAP-00906","next":"M21-GAP-00908"},"M21-GAP-00908":{"line":4163,"offset":734761,"length":186,"previous":"M21-GAP-00907","next":"M21-GAP-00909"},"M21-GAP-00909":{"line":4164,"offset":734947,"length":186,"previous":"M21-GAP-00908","next":"M21-GAP-00910"},"M21-GAP-00910":{"line":4165,"offset":735133,"length":186,"previous":"M21-GAP-00909","next":"M21-GAP-00911"},"M21-GAP-00911":{"line":4166,"offset":735319,"length":186,"previous":"M21-GAP-00910","next":"M21-GAP-00912"},"M21-GAP-00912":{"line":4167,"offset":735505,"length":186,"previous":"M21-GAP-00911","next":"M21-GAP-00913"},"M21-GAP-00913":{"line":4168,"offset":735691,"length":187,"previous":"M21-GAP-00912","next":"M21-GAP-00914"},"M21-GAP-00914":{"line":4169,"offset":735878,"length":187,"previous":"M21-GAP-00913","next":"M21-GAP-00915"},"M21-GAP-00915":{"line":4170,"offset":736065,"length":187,"previous":"M21-GAP-00914","next":"M21-GAP-00916"},"M21-GAP-00916":{"line":4171,"offset":736252,"length":187,"previous":"M21-GAP-00915","next":"M21-GAP-00917"},"M21-GAP-00917":{"line":4172,"offset":736439,"length":186,"previous":"M21-GAP-00916","next":"M21-GAP-00918"},"M21-GAP-00918":{"line":4173,"offset":736625,"length":186,"previous":"M21-GAP-00917","next":"M21-GAP-00919"},"M21-GAP-00919":{"line":4174,"offset":736811,"length":186,"previous":"M21-GAP-00918","next":"M21-GAP-00920"},"M21-GAP-00920":{"line":4175,"offset":736997,"length":186,"previous":"M21-GAP-00919","next":"M21-GAP-00921"},"M21-GAP-00921":{"line":4176,"offset":737183,"length":186,"previous":"M21-GAP-00920","next":"M21-GAP-00922"},"M21-GAP-00922":{"line":4177,"offset":737369,"length":186,"previous":"M21-GAP-00921","next":"M21-GAP-00923"},"M21-GAP-00923":{"line":4178,"offset":737555,"length":186,"previous":"M21-GAP-00922","next":"M21-GAP-00924"},"M21-GAP-00924":{"line":4179,"offset":737741,"length":186,"previous":"M21-GAP-00923","next":"M21-GAP-00925"},"M21-GAP-00925":{"line":4180,"offset":737927,"length":171,"previous":"M21-GAP-00924","next":"M21-GAP-00926"},"M21-GAP-00926":{"line":4181,"offset":738098,"length":171,"previous":"M21-GAP-00925","next":"M21-GAP-00927"},"M21-GAP-00927":{"line":4182,"offset":738269,"length":172,"previous":"M21-GAP-00926","next":"M21-GAP-00928"},"M21-GAP-00928":{"line":4183,"offset":738441,"length":172,"previous":"M21-GAP-00927","next":"M21-GAP-00929"},"M21-GAP-00929":{"line":4184,"offset":738613,"length":172,"previous":"M21-GAP-00928","next":"M21-GAP-00930"},"M21-GAP-00930":{"line":4185,"offset":738785,"length":172,"previous":"M21-GAP-00929","next":"M21-GAP-00931"},"M21-GAP-00931":{"line":4186,"offset":738957,"length":172,"previous":"M21-GAP-00930","next":"M21-GAP-00932"},"M21-GAP-00932":{"line":4187,"offset":739129,"length":172,"previous":"M21-GAP-00931","next":"M21-GAP-00933"},"M21-GAP-00933":{"line":4188,"offset":739301,"length":172,"previous":"M21-GAP-00932","next":"M21-GAP-00934"},"M21-GAP-00934":{"line":4189,"offset":739473,"length":172,"previous":"M21-GAP-00933","next":"M21-GAP-00935"},"M21-GAP-00935":{"line":4190,"offset":739645,"length":172,"previous":"M21-GAP-00934","next":"M21-GAP-00936"},"M21-GAP-00936":{"line":4191,"offset":739817,"length":172,"previous":"M21-GAP-00935","next":"M21-GAP-00937"},"M21-GAP-00937":{"line":4192,"offset":739989,"length":171,"previous":"M21-GAP-00936","next":"M21-GAP-00938"},"M21-GAP-00938":{"line":4193,"offset":740160,"length":172,"previous":"M21-GAP-00937","next":"M21-GAP-00939"},"M21-GAP-00939":{"line":4194,"offset":740332,"length":172,"previous":"M21-GAP-00938","next":"M21-GAP-00940"},"M21-GAP-00940":{"line":4195,"offset":740504,"length":172,"previous":"M21-GAP-00939","next":"M21-GAP-00941"},"M21-GAP-00941":{"line":4196,"offset":740676,"length":172,"previous":"M21-GAP-00940","next":"M21-GAP-00942"},"M21-GAP-00942":{"line":4197,"offset":740848,"length":172,"previous":"M21-GAP-00941","next":"M21-GAP-00943"},"M21-GAP-00943":{"line":4198,"offset":741020,"length":172,"previous":"M21-GAP-00942","next":"M21-GAP-00944"},"M21-GAP-00944":{"line":4199,"offset":741192,"length":172,"previous":"M21-GAP-00943","next":"M21-GAP-00945"},"M21-GAP-00945":{"line":4200,"offset":741364,"length":172,"previous":"M21-GAP-00944","next":"M21-GAP-00946"},"M21-GAP-00946":{"line":4201,"offset":741536,"length":172,"previous":"M21-GAP-00945","next":"M21-GAP-00947"},"M21-GAP-00947":{"line":4202,"offset":741708,"length":172,"previous":"M21-GAP-00946","next":"M21-GAP-00948"},"M21-GAP-00948":{"line":4203,"offset":741880,"length":171,"previous":"M21-GAP-00947","next":"M21-GAP-00949"},"M21-GAP-00949":{"line":4204,"offset":742051,"length":172,"previous":"M21-GAP-00948","next":"M21-GAP-00950"},"M21-GAP-00950":{"line":4205,"offset":742223,"length":172,"previous":"M21-GAP-00949","next":"M21-GAP-00951"},"M21-GAP-00951":{"line":4206,"offset":742395,"length":172,"previous":"M21-GAP-00950","next":"M21-GAP-00952"},"M21-GAP-00952":{"line":4207,"offset":742567,"length":172,"previous":"M21-GAP-00951","next":"M21-GAP-00953"},"M21-GAP-00953":{"line":4208,"offset":742739,"length":172,"previous":"M21-GAP-00952","next":"M21-GAP-00954"},"M21-GAP-00954":{"line":4209,"offset":742911,"length":172,"previous":"M21-GAP-00953","next":"M21-GAP-00955"},"M21-GAP-00955":{"line":4210,"offset":743083,"length":172,"previous":"M21-GAP-00954","next":"M21-GAP-00956"},"M21-GAP-00956":{"line":4211,"offset":743255,"length":172,"previous":"M21-GAP-00955","next":"M21-GAP-00957"},"M21-GAP-00957":{"line":4212,"offset":743427,"length":172,"previous":"M21-GAP-00956","next":"M21-GAP-00958"},"M21-GAP-00958":{"line":4213,"offset":743599,"length":172,"previous":"M21-GAP-00957","next":"M21-GAP-00959"},"M21-GAP-00959":{"line":4214,"offset":743771,"length":171,"previous":"M21-GAP-00958","next":"M21-GAP-00960"},"M21-GAP-00960":{"line":4215,"offset":743942,"length":172,"previous":"M21-GAP-00959","next":"M21-GAP-00961"},"M21-GAP-00961":{"line":4216,"offset":744114,"length":172,"previous":"M21-GAP-00960","next":"M21-GAP-00962"},"M21-GAP-00962":{"line":4217,"offset":744286,"length":172,"previous":"M21-GAP-00961","next":"M21-GAP-00963"},"M21-GAP-00963":{"line":4218,"offset":744458,"length":172,"previous":"M21-GAP-00962","next":"M21-GAP-00964"},"M21-GAP-00964":{"line":4219,"offset":744630,"length":172,"previous":"M21-GAP-00963","next":"M21-GAP-00965"},"M21-GAP-00965":{"line":4220,"offset":744802,"length":172,"previous":"M21-GAP-00964","next":"M21-GAP-00966"},"M21-GAP-00966":{"line":4221,"offset":744974,"length":172,"previous":"M21-GAP-00965","next":"M21-GAP-00967"},"M21-GAP-00967":{"line":4222,"offset":745146,"length":172,"previous":"M21-GAP-00966","next":"M21-GAP-00968"},"M21-GAP-00968":{"line":4223,"offset":745318,"length":172,"previous":"M21-GAP-00967","next":"M21-GAP-00969"},"M21-GAP-00969":{"line":4224,"offset":745490,"length":171,"previous":"M21-GAP-00968","next":"M21-GAP-00970"},"M21-GAP-00970":{"line":4225,"offset":745661,"length":171,"previous":"M21-GAP-00969","next":"M21-GAP-00971"},"M21-GAP-00971":{"line":4226,"offset":745832,"length":171,"previous":"M21-GAP-00970","next":"M21-GAP-00972"},"M21-GAP-00972":{"line":4227,"offset":746003,"length":171,"previous":"M21-GAP-00971","next":"M21-GAP-00973"},"M21-GAP-00973":{"line":4228,"offset":746174,"length":171,"previous":"M21-GAP-00972","next":"M21-GAP-00974"},"M21-GAP-00974":{"line":4229,"offset":746345,"length":173,"previous":"M21-GAP-00973","next":"M21-GAP-00975"},"M21-GAP-00975":{"line":4230,"offset":746518,"length":173,"previous":"M21-GAP-00974","next":"M21-GAP-00976"},"M21-GAP-00976":{"line":4231,"offset":746691,"length":174,"previous":"M21-GAP-00975","next":"M21-GAP-00977"},"M21-GAP-00977":{"line":4232,"offset":746865,"length":174,"previous":"M21-GAP-00976","next":"M21-GAP-00978"},"M21-GAP-00978":{"line":4233,"offset":747039,"length":174,"previous":"M21-GAP-00977","next":"M21-GAP-00979"},"M21-GAP-00979":{"line":4234,"offset":747213,"length":174,"previous":"M21-GAP-00978","next":"M21-GAP-00980"},"M21-GAP-00980":{"line":4235,"offset":747387,"length":174,"previous":"M21-GAP-00979","next":"M21-GAP-00981"},"M21-GAP-00981":{"line":4236,"offset":747561,"length":174,"previous":"M21-GAP-00980","next":"M21-GAP-00982"},"M21-GAP-00982":{"line":4237,"offset":747735,"length":174,"previous":"M21-GAP-00981","next":"M21-GAP-00983"},"M21-GAP-00983":{"line":4238,"offset":747909,"length":173,"previous":"M21-GAP-00982","next":"M21-GAP-00984"},"M21-GAP-00984":{"line":4239,"offset":748082,"length":173,"previous":"M21-GAP-00983","next":"M21-GAP-00985"},"M21-GAP-00985":{"line":4240,"offset":748255,"length":173,"previous":"M21-GAP-00984","next":"M21-GAP-00986"},"M21-GAP-00986":{"line":4241,"offset":748428,"length":173,"previous":"M21-GAP-00985","next":"M21-GAP-00987"},"M21-GAP-00987":{"line":4242,"offset":748601,"length":173,"previous":"M21-GAP-00986","next":"M21-GAP-00988"},"M21-GAP-00988":{"line":4243,"offset":748774,"length":173,"previous":"M21-GAP-00987","next":"M21-GAP-00989"},"M21-GAP-00989":{"line":4244,"offset":748947,"length":173,"previous":"M21-GAP-00988","next":"M21-GAP-00990"},"M21-GAP-00990":{"line":4245,"offset":749120,"length":173,"previous":"M21-GAP-00989","next":"M21-GAP-00991"},"M21-GAP-00991":{"line":4246,"offset":749293,"length":191,"previous":"M21-GAP-00990","next":"M21-GAP-00992"},"M21-GAP-00992":{"line":4247,"offset":749484,"length":191,"previous":"M21-GAP-00991","next":"M21-GAP-00993"},"M21-GAP-00993":{"line":4248,"offset":749675,"length":185,"previous":"M21-GAP-00992","next":"M21-GAP-00994"},"M21-GAP-00994":{"line":4249,"offset":749860,"length":191,"previous":"M21-GAP-00993","next":"M21-GAP-00995"},"M21-GAP-00995":{"line":4250,"offset":750051,"length":187,"previous":"M21-GAP-00994","next":"M21-GAP-00996"},"M21-GAP-00996":{"line":4251,"offset":750238,"length":196,"previous":"M21-GAP-00995","next":"M21-GAP-00997"},"M21-GAP-00997":{"line":4252,"offset":750434,"length":196,"previous":"M21-GAP-00996","next":"M21-GAP-00998"},"M21-GAP-00998":{"line":4253,"offset":750630,"length":197,"previous":"M21-GAP-00997","next":"M21-GAP-00999"},"M21-GAP-00999":{"line":4254,"offset":750827,"length":197,"previous":"M21-GAP-00998","next":"M21-GAP-01000"},"M21-GAP-01000":{"line":4255,"offset":751024,"length":196,"previous":"M21-GAP-00999","next":"M21-GAP-01001"},"M21-GAP-01001":{"line":4256,"offset":751220,"length":196,"previous":"M21-GAP-01000","next":"M21-GAP-01002"},"M21-GAP-01002":{"line":4257,"offset":751416,"length":196,"previous":"M21-GAP-01001","next":"M21-GAP-01003"},"M21-GAP-01003":{"line":4258,"offset":751612,"length":196,"previous":"M21-GAP-01002","next":"M21-GAP-01004"},"M21-GAP-01004":{"line":4259,"offset":751808,"length":196,"previous":"M21-GAP-01003","next":"M21-GAP-01005"},"M21-GAP-01005":{"line":4260,"offset":752004,"length":196,"previous":"M21-GAP-01004","next":"M21-GAP-01006"},"M21-GAP-01006":{"line":4261,"offset":752200,"length":196,"previous":"M21-GAP-01005","next":"M21-GAP-01007"},"M21-GAP-01007":{"line":4262,"offset":752396,"length":196,"previous":"M21-GAP-01006","next":"M21-GAP-01008"},"M21-GAP-01008":{"line":4263,"offset":752592,"length":180,"previous":"M21-GAP-01007","next":"M21-GAP-01009"},"M21-GAP-01009":{"line":4264,"offset":752772,"length":196,"previous":"M21-GAP-01008","next":"M21-GAP-01010"},"M21-GAP-01010":{"line":4265,"offset":752968,"length":196,"previous":"M21-GAP-01009","next":"M21-GAP-01011"},"M21-GAP-01011":{"line":4266,"offset":753164,"length":194,"previous":"M21-GAP-01010","next":"M21-GAP-01012"},"M21-GAP-01012":{"line":4267,"offset":753358,"length":194,"previous":"M21-GAP-01011","next":"M21-GAP-01013"},"M21-GAP-01013":{"line":4268,"offset":753552,"length":197,"previous":"M21-GAP-01012","next":"M21-GAP-01014"},"M21-GAP-01014":{"line":4269,"offset":753749,"length":197,"previous":"M21-GAP-01013","next":"M21-GAP-01015"},"M21-GAP-01015":{"line":4270,"offset":753946,"length":189,"previous":"M21-GAP-01014","next":"M21-GAP-01016"},"M21-GAP-01016":{"line":4271,"offset":754135,"length":189,"previous":"M21-GAP-01015","next":"M21-GAP-01017"},"M21-GAP-01017":{"line":4272,"offset":754324,"length":178,"previous":"M21-GAP-01016","next":"M21-GAP-01018"},"M21-GAP-01018":{"line":4273,"offset":754502,"length":178,"previous":"M21-GAP-01017","next":"M21-GAP-01019"},"M21-GAP-01019":{"line":4274,"offset":754680,"length":178,"previous":"M21-GAP-01018","next":"M21-GAP-01020"},"M21-GAP-01020":{"line":4275,"offset":754858,"length":178,"previous":"M21-GAP-01019","next":"M21-GAP-01021"},"M21-GAP-01021":{"line":4276,"offset":755036,"length":178,"previous":"M21-GAP-01020","next":"M21-GAP-01022"},"M21-GAP-01022":{"line":4277,"offset":755214,"length":178,"previous":"M21-GAP-01021","next":"M21-GAP-01023"},"M21-GAP-01023":{"line":4278,"offset":755392,"length":178,"previous":"M21-GAP-01022","next":"M21-GAP-01024"},"M21-GAP-01024":{"line":4279,"offset":755570,"length":178,"previous":"M21-GAP-01023","next":"M21-GAP-01025"},"M21-GAP-01025":{"line":4280,"offset":755748,"length":178,"previous":"M21-GAP-01024","next":"M21-GAP-01026"},"M21-GAP-01026":{"line":4281,"offset":755926,"length":178,"previous":"M21-GAP-01025","next":"M21-GAP-01027"},"M21-GAP-01027":{"line":4282,"offset":756104,"length":180,"previous":"M21-GAP-01026","next":"M21-GAP-01028"},"M21-GAP-01028":{"line":4283,"offset":756284,"length":183,"previous":"M21-GAP-01027","next":"M21-GAP-01029"},"M21-GAP-01029":{"line":4284,"offset":756467,"length":183,"previous":"M21-GAP-01028","next":"M21-GAP-01030"},"M21-GAP-01030":{"line":4285,"offset":756650,"length":183,"previous":"M21-GAP-01029","next":"M21-GAP-01031"},"M21-GAP-01031":{"line":4286,"offset":756833,"length":183,"previous":"M21-GAP-01030","next":"M21-GAP-01032"},"M21-GAP-01032":{"line":4287,"offset":757016,"length":183,"previous":"M21-GAP-01031","next":"M21-GAP-01033"},"M21-GAP-01033":{"line":4288,"offset":757199,"length":183,"previous":"M21-GAP-01032","next":"M21-GAP-01034"},"M21-GAP-01034":{"line":4289,"offset":757382,"length":188,"previous":"M21-GAP-01033","next":"M21-GAP-01035"},"M21-GAP-01035":{"line":4290,"offset":757570,"length":188,"previous":"M21-GAP-01034","next":"M21-GAP-01036"},"M21-GAP-01036":{"line":4291,"offset":757758,"length":188,"previous":"M21-GAP-01035","next":"M21-GAP-01037"},"M21-GAP-01037":{"line":4292,"offset":757946,"length":188,"previous":"M21-GAP-01036","next":"M21-GAP-01038"},"M21-GAP-01038":{"line":4293,"offset":758134,"length":188,"previous":"M21-GAP-01037","next":"M21-GAP-01039"},"M21-GAP-01039":{"line":4294,"offset":758322,"length":188,"previous":"M21-GAP-01038","next":"M21-GAP-01040"},"M21-GAP-01040":{"line":4295,"offset":758510,"length":188,"previous":"M21-GAP-01039","next":"M21-GAP-01041"},"M21-GAP-01041":{"line":4296,"offset":758698,"length":186,"previous":"M21-GAP-01040","next":"M21-GAP-01042"},"M21-GAP-01042":{"line":4297,"offset":758884,"length":186,"previous":"M21-GAP-01041","next":"M21-GAP-01043"},"M21-GAP-01043":{"line":4298,"offset":759070,"length":186,"previous":"M21-GAP-01042","next":"M21-GAP-01044"},"M21-GAP-01044":{"line":4299,"offset":759256,"length":186,"previous":"M21-GAP-01043","next":"M21-GAP-01045"},"M21-GAP-01045":{"line":4300,"offset":759442,"length":186,"previous":"M21-GAP-01044","next":"M21-GAP-01046"},"M21-GAP-01046":{"line":4301,"offset":759628,"length":186,"previous":"M21-GAP-01045","next":"M21-GAP-01047"},"M21-GAP-01047":{"line":4302,"offset":759814,"length":194,"previous":"M21-GAP-01046","next":"M21-GAP-01048"},"M21-GAP-01048":{"line":4303,"offset":760008,"length":194,"previous":"M21-GAP-01047","next":"M21-GAP-01049"},"M21-GAP-01049":{"line":4304,"offset":760202,"length":194,"previous":"M21-GAP-01048","next":"M21-GAP-01050"},"M21-GAP-01050":{"line":4305,"offset":760396,"length":194,"previous":"M21-GAP-01049","next":"M21-GAP-01051"},"M21-GAP-01051":{"line":4306,"offset":760590,"length":194,"previous":"M21-GAP-01050","next":"M21-GAP-01052"},"M21-GAP-01052":{"line":4307,"offset":760784,"length":194,"previous":"M21-GAP-01051","next":"M21-GAP-01053"},"M21-GAP-01053":{"line":4308,"offset":760978,"length":194,"previous":"M21-GAP-01052","next":"M21-GAP-01054"},"M21-GAP-01054":{"line":4309,"offset":761172,"length":194,"previous":"M21-GAP-01053","next":"M21-GAP-01055"},"M21-GAP-01055":{"line":4310,"offset":761366,"length":194,"previous":"M21-GAP-01054","next":"M21-GAP-01056"},"M21-GAP-01056":{"line":4311,"offset":761560,"length":194,"previous":"M21-GAP-01055","next":"M21-GAP-01057"},"M21-GAP-01057":{"line":4312,"offset":761754,"length":186,"previous":"M21-GAP-01056","next":"M21-GAP-01058"},"M21-GAP-01058":{"line":4313,"offset":761940,"length":186,"previous":"M21-GAP-01057","next":"M21-GAP-01059"},"M21-GAP-01059":{"line":4314,"offset":762126,"length":187,"previous":"M21-GAP-01058","next":"M21-GAP-01060"},"M21-GAP-01060":{"line":4315,"offset":762313,"length":187,"previous":"M21-GAP-01059","next":"M21-GAP-01061"},"M21-GAP-01061":{"line":4316,"offset":762500,"length":187,"previous":"M21-GAP-01060","next":"M21-GAP-01062"},"M21-GAP-01062":{"line":4317,"offset":762687,"length":187,"previous":"M21-GAP-01061","next":"M21-GAP-01063"},"M21-GAP-01063":{"line":4318,"offset":762874,"length":187,"previous":"M21-GAP-01062","next":"M21-GAP-01064"},"M21-GAP-01064":{"line":4319,"offset":763061,"length":187,"previous":"M21-GAP-01063","next":"M21-GAP-01065"},"M21-GAP-01065":{"line":4320,"offset":763248,"length":187,"previous":"M21-GAP-01064","next":"M21-GAP-01066"},"M21-GAP-01066":{"line":4321,"offset":763435,"length":187,"previous":"M21-GAP-01065","next":"M21-GAP-01067"},"M21-GAP-01067":{"line":4322,"offset":763622,"length":187,"previous":"M21-GAP-01066","next":"M21-GAP-01068"},"M21-GAP-01068":{"line":4323,"offset":763809,"length":187,"previous":"M21-GAP-01067","next":"M21-GAP-01069"},"M21-GAP-01069":{"line":4324,"offset":763996,"length":186,"previous":"M21-GAP-01068","next":"M21-GAP-01070"},"M21-GAP-01070":{"line":4325,"offset":764182,"length":187,"previous":"M21-GAP-01069","next":"M21-GAP-01071"},"M21-GAP-01071":{"line":4326,"offset":764369,"length":187,"previous":"M21-GAP-01070","next":"M21-GAP-01072"},"M21-GAP-01072":{"line":4327,"offset":764556,"length":187,"previous":"M21-GAP-01071","next":"M21-GAP-01073"},"M21-GAP-01073":{"line":4328,"offset":764743,"length":187,"previous":"M21-GAP-01072","next":"M21-GAP-01074"},"M21-GAP-01074":{"line":4329,"offset":764930,"length":187,"previous":"M21-GAP-01073","next":"M21-GAP-01075"},"M21-GAP-01075":{"line":4330,"offset":765117,"length":187,"previous":"M21-GAP-01074","next":"M21-GAP-01076"},"M21-GAP-01076":{"line":4331,"offset":765304,"length":187,"previous":"M21-GAP-01075","next":"M21-GAP-01077"},"M21-GAP-01077":{"line":4332,"offset":765491,"length":187,"previous":"M21-GAP-01076","next":"M21-GAP-01078"},"M21-GAP-01078":{"line":4333,"offset":765678,"length":187,"previous":"M21-GAP-01077","next":"M21-GAP-01079"},"M21-GAP-01079":{"line":4334,"offset":765865,"length":187,"previous":"M21-GAP-01078","next":"M21-GAP-01080"},"M21-GAP-01080":{"line":4335,"offset":766052,"length":186,"previous":"M21-GAP-01079","next":"M21-GAP-01081"},"M21-GAP-01081":{"line":4336,"offset":766238,"length":187,"previous":"M21-GAP-01080","next":"M21-GAP-01082"},"M21-GAP-01082":{"line":4337,"offset":766425,"length":187,"previous":"M21-GAP-01081","next":"M21-GAP-01083"},"M21-GAP-01083":{"line":4338,"offset":766612,"length":187,"previous":"M21-GAP-01082","next":"M21-GAP-01084"},"M21-GAP-01084":{"line":4339,"offset":766799,"length":187,"previous":"M21-GAP-01083","next":"M21-GAP-01085"},"M21-GAP-01085":{"line":4340,"offset":766986,"length":187,"previous":"M21-GAP-01084","next":"M21-GAP-01086"},"M21-GAP-01086":{"line":4341,"offset":767173,"length":187,"previous":"M21-GAP-01085","next":"M21-GAP-01087"},"M21-GAP-01087":{"line":4342,"offset":767360,"length":187,"previous":"M21-GAP-01086","next":"M21-GAP-01088"},"M21-GAP-01088":{"line":4343,"offset":767547,"length":187,"previous":"M21-GAP-01087","next":"M21-GAP-01089"},"M21-GAP-01089":{"line":4344,"offset":767734,"length":187,"previous":"M21-GAP-01088","next":"M21-GAP-01090"},"M21-GAP-01090":{"line":4345,"offset":767921,"length":187,"previous":"M21-GAP-01089","next":"M21-GAP-01091"},"M21-GAP-01091":{"line":4346,"offset":768108,"length":186,"previous":"M21-GAP-01090","next":"M21-GAP-01092"},"M21-GAP-01092":{"line":4347,"offset":768294,"length":187,"previous":"M21-GAP-01091","next":"M21-GAP-01093"},"M21-GAP-01093":{"line":4348,"offset":768481,"length":187,"previous":"M21-GAP-01092","next":"M21-GAP-01094"},"M21-GAP-01094":{"line":4349,"offset":768668,"length":187,"previous":"M21-GAP-01093","next":"M21-GAP-01095"},"M21-GAP-01095":{"line":4350,"offset":768855,"length":187,"previous":"M21-GAP-01094","next":"M21-GAP-01096"},"M21-GAP-01096":{"line":4351,"offset":769042,"length":187,"previous":"M21-GAP-01095","next":"M21-GAP-01097"},"M21-GAP-01097":{"line":4352,"offset":769229,"length":187,"previous":"M21-GAP-01096","next":"M21-GAP-01098"},"M21-GAP-01098":{"line":4353,"offset":769416,"length":187,"previous":"M21-GAP-01097","next":"M21-GAP-01099"},"M21-GAP-01099":{"line":4354,"offset":769603,"length":187,"previous":"M21-GAP-01098","next":"M21-GAP-01100"},"M21-GAP-01100":{"line":4355,"offset":769790,"length":187,"previous":"M21-GAP-01099","next":"M21-GAP-01101"},"M21-GAP-01101":{"line":4356,"offset":769977,"length":187,"previous":"M21-GAP-01100","next":"M21-GAP-01102"},"M21-GAP-01102":{"line":4357,"offset":770164,"length":186,"previous":"M21-GAP-01101","next":"M21-GAP-01103"},"M21-GAP-01103":{"line":4358,"offset":770350,"length":187,"previous":"M21-GAP-01102","next":"M21-GAP-01104"},"M21-GAP-01104":{"line":4359,"offset":770537,"length":187,"previous":"M21-GAP-01103","next":"M21-GAP-01105"},"M21-GAP-01105":{"line":4360,"offset":770724,"length":187,"previous":"M21-GAP-01104","next":"M21-GAP-01106"},"M21-GAP-01106":{"line":4361,"offset":770911,"length":187,"previous":"M21-GAP-01105","next":"M21-GAP-01107"},"M21-GAP-01107":{"line":4362,"offset":771098,"length":187,"previous":"M21-GAP-01106","next":"M21-GAP-01108"},"M21-GAP-01108":{"line":4363,"offset":771285,"length":187,"previous":"M21-GAP-01107","next":"M21-GAP-01109"},"M21-GAP-01109":{"line":4364,"offset":771472,"length":187,"previous":"M21-GAP-01108","next":"M21-GAP-01110"},"M21-GAP-01110":{"line":4365,"offset":771659,"length":187,"previous":"M21-GAP-01109","next":"M21-GAP-01111"},"M21-GAP-01111":{"line":4366,"offset":771846,"length":187,"previous":"M21-GAP-01110","next":"M21-GAP-01112"},"M21-GAP-01112":{"line":4367,"offset":772033,"length":187,"previous":"M21-GAP-01111","next":"M21-GAP-01113"},"M21-GAP-01113":{"line":4368,"offset":772220,"length":186,"previous":"M21-GAP-01112","next":"M21-GAP-01114"},"M21-GAP-01114":{"line":4369,"offset":772406,"length":187,"previous":"M21-GAP-01113","next":"M21-GAP-01115"},"M21-GAP-01115":{"line":4370,"offset":772593,"length":187,"previous":"M21-GAP-01114","next":"M21-GAP-01116"},"M21-GAP-01116":{"line":4371,"offset":772780,"length":187,"previous":"M21-GAP-01115","next":"M21-GAP-01117"},"M21-GAP-01117":{"line":4372,"offset":772967,"length":187,"previous":"M21-GAP-01116","next":"M21-GAP-01118"},"M21-GAP-01118":{"line":4373,"offset":773154,"length":187,"previous":"M21-GAP-01117","next":"M21-GAP-01119"},"M21-GAP-01119":{"line":4374,"offset":773341,"length":187,"previous":"M21-GAP-01118","next":"M21-GAP-01120"},"M21-GAP-01120":{"line":4375,"offset":773528,"length":187,"previous":"M21-GAP-01119","next":"M21-GAP-01121"},"M21-GAP-01121":{"line":4376,"offset":773715,"length":187,"previous":"M21-GAP-01120","next":"M21-GAP-01122"},"M21-GAP-01122":{"line":4377,"offset":773902,"length":187,"previous":"M21-GAP-01121","next":"M21-GAP-01123"},"M21-GAP-01123":{"line":4378,"offset":774089,"length":187,"previous":"M21-GAP-01122","next":"M21-GAP-01124"},"M21-GAP-01124":{"line":4379,"offset":774276,"length":186,"previous":"M21-GAP-01123","next":"M21-GAP-01125"},"M21-GAP-01125":{"line":4380,"offset":774462,"length":187,"previous":"M21-GAP-01124","next":"M21-GAP-01126"},"M21-GAP-01126":{"line":4381,"offset":774649,"length":186,"previous":"M21-GAP-01125","next":"M21-GAP-01127"},"M21-GAP-01127":{"line":4382,"offset":774835,"length":186,"previous":"M21-GAP-01126","next":"M21-GAP-01128"},"M21-GAP-01128":{"line":4383,"offset":775021,"length":193,"previous":"M21-GAP-01127","next":"M21-GAP-01129"},"M21-GAP-01129":{"line":4384,"offset":775214,"length":193,"previous":"M21-GAP-01128","next":"M21-GAP-01130"},"M21-GAP-01130":{"line":4385,"offset":775407,"length":193,"previous":"M21-GAP-01129","next":"M21-GAP-01131"},"M21-GAP-01131":{"line":4386,"offset":775600,"length":193,"previous":"M21-GAP-01130","next":"M21-GAP-01132"},"M21-GAP-01132":{"line":4387,"offset":775793,"length":193,"previous":"M21-GAP-01131","next":"M21-GAP-01133"},"M21-GAP-01133":{"line":4388,"offset":775986,"length":193,"previous":"M21-GAP-01132","next":"M21-GAP-01134"},"M21-GAP-01134":{"line":4389,"offset":776179,"length":190,"previous":"M21-GAP-01133","next":"M21-GAP-01135"},"M21-GAP-01135":{"line":4390,"offset":776369,"length":190,"previous":"M21-GAP-01134","next":"M21-GAP-01136"},"M21-GAP-01136":{"line":4391,"offset":776559,"length":191,"previous":"M21-GAP-01135","next":"M21-GAP-01137"},"M21-GAP-01137":{"line":4392,"offset":776750,"length":191,"previous":"M21-GAP-01136","next":"M21-GAP-01138"},"M21-GAP-01138":{"line":4393,"offset":776941,"length":191,"previous":"M21-GAP-01137","next":"M21-GAP-01139"},"M21-GAP-01139":{"line":4394,"offset":777132,"length":191,"previous":"M21-GAP-01138","next":"M21-GAP-01140"},"M21-GAP-01140":{"line":4395,"offset":777323,"length":191,"previous":"M21-GAP-01139","next":"M21-GAP-01141"},"M21-GAP-01141":{"line":4396,"offset":777514,"length":191,"previous":"M21-GAP-01140","next":"M21-GAP-01142"},"M21-GAP-01142":{"line":4397,"offset":777705,"length":191,"previous":"M21-GAP-01141","next":"M21-GAP-01143"},"M21-GAP-01143":{"line":4398,"offset":777896,"length":191,"previous":"M21-GAP-01142","next":"M21-GAP-01144"},"M21-GAP-01144":{"line":4399,"offset":778087,"length":191,"previous":"M21-GAP-01143","next":"M21-GAP-01145"},"M21-GAP-01145":{"line":4400,"offset":778278,"length":191,"previous":"M21-GAP-01144","next":"M21-GAP-01146"},"M21-GAP-01146":{"line":4401,"offset":778469,"length":190,"previous":"M21-GAP-01145","next":"M21-GAP-01147"},"M21-GAP-01147":{"line":4402,"offset":778659,"length":191,"previous":"M21-GAP-01146","next":"M21-GAP-01148"},"M21-GAP-01148":{"line":4403,"offset":778850,"length":191,"previous":"M21-GAP-01147","next":"M21-GAP-01149"},"M21-GAP-01149":{"line":4404,"offset":779041,"length":190,"previous":"M21-GAP-01148","next":"M21-GAP-01150"},"M21-GAP-01150":{"line":4405,"offset":779231,"length":190,"previous":"M21-GAP-01149","next":"M21-GAP-01151"},"M21-GAP-01151":{"line":4406,"offset":779421,"length":190,"previous":"M21-GAP-01150","next":"M21-GAP-01152"},"M21-GAP-01152":{"line":4407,"offset":779611,"length":190,"previous":"M21-GAP-01151","next":"M21-GAP-01153"},"M21-GAP-01153":{"line":4408,"offset":779801,"length":190,"previous":"M21-GAP-01152","next":"M21-GAP-01154"},"M21-GAP-01154":{"line":4409,"offset":779991,"length":190,"previous":"M21-GAP-01153","next":"M21-GAP-01155"},"M21-GAP-01155":{"line":4410,"offset":780181,"length":190,"previous":"M21-GAP-01154","next":"M21-GAP-01156"},"M21-GAP-01156":{"line":4411,"offset":780371,"length":190,"previous":"M21-GAP-01155","next":"M21-GAP-01157"},"M21-GAP-01157":{"line":4412,"offset":780561,"length":190,"previous":"M21-GAP-01156","next":"M21-GAP-01158"},"M21-GAP-01158":{"line":4413,"offset":780751,"length":191,"previous":"M21-GAP-01157","next":"M21-GAP-01159"},"M21-GAP-01159":{"line":4414,"offset":780942,"length":191,"previous":"M21-GAP-01158","next":"M21-GAP-01160"},"M21-GAP-01160":{"line":4415,"offset":781133,"length":191,"previous":"M21-GAP-01159","next":"M21-GAP-01161"},"M21-GAP-01161":{"line":4416,"offset":781324,"length":191,"previous":"M21-GAP-01160","next":"M21-GAP-01162"},"M21-GAP-01162":{"line":4417,"offset":781515,"length":191,"previous":"M21-GAP-01161","next":"M21-GAP-01163"},"M21-GAP-01163":{"line":4418,"offset":781706,"length":191,"previous":"M21-GAP-01162","next":"M21-GAP-01164"},"M21-GAP-01164":{"line":4419,"offset":781897,"length":191,"previous":"M21-GAP-01163","next":"M21-GAP-01165"},"M21-GAP-01165":{"line":4420,"offset":782088,"length":191,"previous":"M21-GAP-01164","next":"M21-GAP-01166"},"M21-GAP-01166":{"line":4421,"offset":782279,"length":191,"previous":"M21-GAP-01165","next":"M21-GAP-01167"},"M21-GAP-01167":{"line":4422,"offset":782470,"length":191,"previous":"M21-GAP-01166","next":"M21-GAP-01168"},"M21-GAP-01168":{"line":4423,"offset":782661,"length":190,"previous":"M21-GAP-01167","next":"M21-GAP-01169"},"M21-GAP-01169":{"line":4424,"offset":782851,"length":191,"previous":"M21-GAP-01168","next":"M21-GAP-01170"},"M21-GAP-01170":{"line":4425,"offset":783042,"length":191,"previous":"M21-GAP-01169","next":"M21-GAP-01171"},"M21-GAP-01171":{"line":4426,"offset":783233,"length":191,"previous":"M21-GAP-01170","next":"M21-GAP-01172"},"M21-GAP-01172":{"line":4427,"offset":783424,"length":191,"previous":"M21-GAP-01171","next":"M21-GAP-01173"},"M21-GAP-01173":{"line":4428,"offset":783615,"length":191,"previous":"M21-GAP-01172","next":"M21-GAP-01174"},"M21-GAP-01174":{"line":4429,"offset":783806,"length":191,"previous":"M21-GAP-01173","next":"M21-GAP-01175"},"M21-GAP-01175":{"line":4430,"offset":783997,"length":191,"previous":"M21-GAP-01174","next":"M21-GAP-01176"},"M21-GAP-01176":{"line":4431,"offset":784188,"length":191,"previous":"M21-GAP-01175","next":"M21-GAP-01177"},"M21-GAP-01177":{"line":4432,"offset":784379,"length":191,"previous":"M21-GAP-01176","next":"M21-GAP-01178"},"M21-GAP-01178":{"line":4433,"offset":784570,"length":191,"previous":"M21-GAP-01177","next":"M21-GAP-01179"},"M21-GAP-01179":{"line":4434,"offset":784761,"length":190,"previous":"M21-GAP-01178","next":"M21-GAP-01180"},"M21-GAP-01180":{"line":4435,"offset":784951,"length":191,"previous":"M21-GAP-01179","next":"M21-GAP-01181"},"M21-GAP-01181":{"line":4436,"offset":785142,"length":191,"previous":"M21-GAP-01180","next":"M21-GAP-01182"},"M21-GAP-01182":{"line":4437,"offset":785333,"length":191,"previous":"M21-GAP-01181","next":"M21-GAP-01183"},"M21-GAP-01183":{"line":4438,"offset":785524,"length":191,"previous":"M21-GAP-01182","next":"M21-GAP-01184"},"M21-GAP-01184":{"line":4439,"offset":785715,"length":191,"previous":"M21-GAP-01183","next":"M21-GAP-01185"},"M21-GAP-01185":{"line":4440,"offset":785906,"length":191,"previous":"M21-GAP-01184","next":"M21-GAP-01186"},"M21-GAP-01186":{"line":4441,"offset":786097,"length":191,"previous":"M21-GAP-01185","next":"M21-GAP-01187"},"M21-GAP-01187":{"line":4442,"offset":786288,"length":191,"previous":"M21-GAP-01186","next":"M21-GAP-01188"},"M21-GAP-01188":{"line":4443,"offset":786479,"length":191,"previous":"M21-GAP-01187","next":"M21-GAP-01189"},"M21-GAP-01189":{"line":4444,"offset":786670,"length":191,"previous":"M21-GAP-01188","next":"M21-GAP-01190"},"M21-GAP-01190":{"line":4445,"offset":786861,"length":190,"previous":"M21-GAP-01189","next":"M21-GAP-01191"},"M21-GAP-01191":{"line":4446,"offset":787051,"length":191,"previous":"M21-GAP-01190","next":"M21-GAP-01192"},"M21-GAP-01192":{"line":4447,"offset":787242,"length":191,"previous":"M21-GAP-01191","next":"M21-GAP-01193"},"M21-GAP-01193":{"line":4448,"offset":787433,"length":191,"previous":"M21-GAP-01192","next":"M21-GAP-01194"},"M21-GAP-01194":{"line":4449,"offset":787624,"length":191,"previous":"M21-GAP-01193","next":"M21-GAP-01195"},"M21-GAP-01195":{"line":4450,"offset":787815,"length":191,"previous":"M21-GAP-01194","next":"M21-GAP-01196"},"M21-GAP-01196":{"line":4451,"offset":788006,"length":191,"previous":"M21-GAP-01195","next":"M21-GAP-01197"},"M21-GAP-01197":{"line":4452,"offset":788197,"length":191,"previous":"M21-GAP-01196","next":"M21-GAP-01198"},"M21-GAP-01198":{"line":4453,"offset":788388,"length":191,"previous":"M21-GAP-01197","next":"M21-GAP-01199"},"M21-GAP-01199":{"line":4454,"offset":788579,"length":191,"previous":"M21-GAP-01198","next":"M21-GAP-01200"},"M21-GAP-01200":{"line":4455,"offset":788770,"length":191,"previous":"M21-GAP-01199","next":"M21-GAP-01201"},"M21-GAP-01201":{"line":4456,"offset":788961,"length":190,"previous":"M21-GAP-01200","next":"M21-GAP-01202"},"M21-GAP-01202":{"line":4457,"offset":789151,"length":191,"previous":"M21-GAP-01201","next":"M21-GAP-01203"},"M21-GAP-01203":{"line":4458,"offset":789342,"length":191,"previous":"M21-GAP-01202","next":"M21-GAP-01204"},"M21-GAP-01204":{"line":4459,"offset":789533,"length":191,"previous":"M21-GAP-01203","next":"M21-GAP-01205"},"M21-GAP-01205":{"line":4460,"offset":789724,"length":191,"previous":"M21-GAP-01204","next":"M21-GAP-01206"},"M21-GAP-01206":{"line":4461,"offset":789915,"length":191,"previous":"M21-GAP-01205","next":"M21-GAP-01207"},"M21-GAP-01207":{"line":4462,"offset":790106,"length":191,"previous":"M21-GAP-01206","next":"M21-GAP-01208"},"M21-GAP-01208":{"line":4463,"offset":790297,"length":191,"previous":"M21-GAP-01207","next":"M21-GAP-01209"},"M21-GAP-01209":{"line":4464,"offset":790488,"length":190,"previous":"M21-GAP-01208","next":"M21-GAP-01210"},"M21-GAP-01210":{"line":4465,"offset":790678,"length":190,"previous":"M21-GAP-01209","next":"M21-GAP-01211"},"M21-GAP-01211":{"line":4466,"offset":790868,"length":190,"previous":"M21-GAP-01210","next":"M21-GAP-01212"},"M21-GAP-01212":{"line":4467,"offset":791058,"length":190,"previous":"M21-GAP-01211","next":"M21-GAP-01213"},"M21-GAP-01213":{"line":4468,"offset":791248,"length":190,"previous":"M21-GAP-01212","next":"M21-GAP-01214"},"M21-GAP-01214":{"line":4469,"offset":791438,"length":190,"previous":"M21-GAP-01213","next":"M21-GAP-01215"},"M21-GAP-01215":{"line":4470,"offset":791628,"length":190,"previous":"M21-GAP-01214","next":"M21-GAP-01216"},"M21-GAP-01216":{"line":4471,"offset":791818,"length":192,"previous":"M21-GAP-01215","next":"M21-GAP-01217"},"M21-GAP-01217":{"line":4472,"offset":792010,"length":192,"previous":"M21-GAP-01216","next":"M21-GAP-01218"},"M21-GAP-01218":{"line":4473,"offset":792202,"length":193,"previous":"M21-GAP-01217","next":"M21-GAP-01219"},"M21-GAP-01219":{"line":4474,"offset":792395,"length":193,"previous":"M21-GAP-01218","next":"M21-GAP-01220"},"M21-GAP-01220":{"line":4475,"offset":792588,"length":193,"previous":"M21-GAP-01219","next":"M21-GAP-01221"},"M21-GAP-01221":{"line":4476,"offset":792781,"length":193,"previous":"M21-GAP-01220","next":"M21-GAP-01222"},"M21-GAP-01222":{"line":4477,"offset":792974,"length":193,"previous":"M21-GAP-01221","next":"M21-GAP-01223"},"M21-GAP-01223":{"line":4478,"offset":793167,"length":193,"previous":"M21-GAP-01222","next":"M21-GAP-01224"},"M21-GAP-01224":{"line":4479,"offset":793360,"length":193,"previous":"M21-GAP-01223","next":"M21-GAP-01225"},"M21-GAP-01225":{"line":4480,"offset":793553,"length":193,"previous":"M21-GAP-01224","next":"M21-GAP-01226"},"M21-GAP-01226":{"line":4481,"offset":793746,"length":193,"previous":"M21-GAP-01225","next":"M21-GAP-01227"},"M21-GAP-01227":{"line":4482,"offset":793939,"length":193,"previous":"M21-GAP-01226","next":"M21-GAP-01228"},"M21-GAP-01228":{"line":4483,"offset":794132,"length":192,"previous":"M21-GAP-01227","next":"M21-GAP-01229"},"M21-GAP-01229":{"line":4484,"offset":794324,"length":193,"previous":"M21-GAP-01228","next":"M21-GAP-01230"},"M21-GAP-01230":{"line":4485,"offset":794517,"length":193,"previous":"M21-GAP-01229","next":"M21-GAP-01231"},"M21-GAP-01231":{"line":4486,"offset":794710,"length":193,"previous":"M21-GAP-01230","next":"M21-GAP-01232"},"M21-GAP-01232":{"line":4487,"offset":794903,"length":193,"previous":"M21-GAP-01231","next":"M21-GAP-01233"},"M21-GAP-01233":{"line":4488,"offset":795096,"length":193,"previous":"M21-GAP-01232","next":"M21-GAP-01234"},"M21-GAP-01234":{"line":4489,"offset":795289,"length":193,"previous":"M21-GAP-01233","next":"M21-GAP-01235"},"M21-GAP-01235":{"line":4490,"offset":795482,"length":193,"previous":"M21-GAP-01234","next":"M21-GAP-01236"},"M21-GAP-01236":{"line":4491,"offset":795675,"length":192,"previous":"M21-GAP-01235","next":"M21-GAP-01237"},"M21-GAP-01237":{"line":4492,"offset":795867,"length":192,"previous":"M21-GAP-01236","next":"M21-GAP-01238"},"M21-GAP-01238":{"line":4493,"offset":796059,"length":192,"previous":"M21-GAP-01237","next":"M21-GAP-01239"},"M21-GAP-01239":{"line":4494,"offset":796251,"length":192,"previous":"M21-GAP-01238","next":"M21-GAP-01240"},"M21-GAP-01240":{"line":4495,"offset":796443,"length":192,"previous":"M21-GAP-01239","next":"M21-GAP-01241"},"M21-GAP-01241":{"line":4496,"offset":796635,"length":192,"previous":"M21-GAP-01240","next":"M21-GAP-01242"},"M21-GAP-01242":{"line":4497,"offset":796827,"length":192,"previous":"M21-GAP-01241","next":"M21-GAP-01243"},"M21-GAP-01243":{"line":4498,"offset":797019,"length":190,"previous":"M21-GAP-01242","next":"M21-GAP-01244"},"M21-GAP-01244":{"line":4499,"offset":797209,"length":190,"previous":"M21-GAP-01243","next":"M21-GAP-01245"},"M21-GAP-01245":{"line":4500,"offset":797399,"length":190,"previous":"M21-GAP-01244","next":"M21-GAP-01246"},"M21-GAP-01246":{"line":4501,"offset":797589,"length":190,"previous":"M21-GAP-01245","next":"M21-GAP-01247"},"M21-GAP-01247":{"line":4502,"offset":797779,"length":190,"previous":"M21-GAP-01246","next":"M21-GAP-01248"},"M21-GAP-01248":{"line":4503,"offset":797969,"length":190,"previous":"M21-GAP-01247","next":"M21-GAP-01249"},"M21-GAP-01249":{"line":4504,"offset":798159,"length":190,"previous":"M21-GAP-01248","next":"M21-GAP-01250"},"M21-GAP-01250":{"line":4505,"offset":798349,"length":190,"previous":"M21-GAP-01249","next":"M21-GAP-01251"},"M21-GAP-01251":{"line":4506,"offset":798539,"length":190,"previous":"M21-GAP-01250","next":"M21-GAP-01252"},"M21-GAP-01252":{"line":4507,"offset":798729,"length":190,"previous":"M21-GAP-01251","next":"M21-GAP-01253"},"M21-GAP-01253":{"line":4508,"offset":798919,"length":193,"previous":"M21-GAP-01252","next":"M21-GAP-01254"},"M21-GAP-01254":{"line":4509,"offset":799112,"length":193,"previous":"M21-GAP-01253","next":"M21-GAP-01255"},"M21-GAP-01255":{"line":4510,"offset":799305,"length":194,"previous":"M21-GAP-01254","next":"M21-GAP-01256"},"M21-GAP-01256":{"line":4511,"offset":799499,"length":194,"previous":"M21-GAP-01255","next":"M21-GAP-01257"},"M21-GAP-01257":{"line":4512,"offset":799693,"length":194,"previous":"M21-GAP-01256","next":"M21-GAP-01258"},"M21-GAP-01258":{"line":4513,"offset":799887,"length":194,"previous":"M21-GAP-01257","next":"M21-GAP-01259"},"M21-GAP-01259":{"line":4514,"offset":800081,"length":194,"previous":"M21-GAP-01258","next":"M21-GAP-01260"},"M21-GAP-01260":{"line":4515,"offset":800275,"length":194,"previous":"M21-GAP-01259","next":"M21-GAP-01261"},"M21-GAP-01261":{"line":4516,"offset":800469,"length":194,"previous":"M21-GAP-01260","next":"M21-GAP-01262"},"M21-GAP-01262":{"line":4517,"offset":800663,"length":194,"previous":"M21-GAP-01261","next":"M21-GAP-01263"},"M21-GAP-01263":{"line":4518,"offset":800857,"length":194,"previous":"M21-GAP-01262","next":"M21-GAP-01264"},"M21-GAP-01264":{"line":4519,"offset":801051,"length":194,"previous":"M21-GAP-01263","next":"M21-GAP-01265"},"M21-GAP-01265":{"line":4520,"offset":801245,"length":193,"previous":"M21-GAP-01264","next":"M21-GAP-01266"},"M21-GAP-01266":{"line":4521,"offset":801438,"length":194,"previous":"M21-GAP-01265","next":"M21-GAP-01267"},"M21-GAP-01267":{"line":4522,"offset":801632,"length":194,"previous":"M21-GAP-01266","next":"M21-GAP-01268"},"M21-GAP-01268":{"line":4523,"offset":801826,"length":193,"previous":"M21-GAP-01267","next":"M21-GAP-01269"},"M21-GAP-01269":{"line":4524,"offset":802019,"length":193,"previous":"M21-GAP-01268","next":"M21-GAP-01270"},"M21-GAP-01270":{"line":4525,"offset":802212,"length":193,"previous":"M21-GAP-01269","next":"M21-GAP-01271"},"M21-GAP-01271":{"line":4526,"offset":802405,"length":193,"previous":"M21-GAP-01270","next":"M21-GAP-01272"},"M21-GAP-01272":{"line":4527,"offset":802598,"length":193,"previous":"M21-GAP-01271","next":"M21-GAP-01273"},"M21-GAP-01273":{"line":4528,"offset":802791,"length":193,"previous":"M21-GAP-01272","next":"M21-GAP-01274"},"M21-GAP-01274":{"line":4529,"offset":802984,"length":193,"previous":"M21-GAP-01273","next":"M21-GAP-01275"},"M21-GAP-01275":{"line":4530,"offset":803177,"length":193,"previous":"M21-GAP-01274","next":"M21-GAP-01276"},"M21-GAP-01276":{"line":4531,"offset":803370,"length":193,"previous":"M21-GAP-01275","next":"M21-GAP-01277"},"M21-GAP-01277":{"line":4532,"offset":803563,"length":194,"previous":"M21-GAP-01276","next":"M21-GAP-01278"},"M21-GAP-01278":{"line":4533,"offset":803757,"length":194,"previous":"M21-GAP-01277","next":"M21-GAP-01279"},"M21-GAP-01279":{"line":4534,"offset":803951,"length":194,"previous":"M21-GAP-01278","next":"M21-GAP-01280"},"M21-GAP-01280":{"line":4535,"offset":804145,"length":194,"previous":"M21-GAP-01279","next":"M21-GAP-01281"},"M21-GAP-01281":{"line":4536,"offset":804339,"length":194,"previous":"M21-GAP-01280","next":"M21-GAP-01282"},"M21-GAP-01282":{"line":4537,"offset":804533,"length":194,"previous":"M21-GAP-01281","next":"M21-GAP-01283"},"M21-GAP-01283":{"line":4538,"offset":804727,"length":194,"previous":"M21-GAP-01282","next":"M21-GAP-01284"},"M21-GAP-01284":{"line":4539,"offset":804921,"length":194,"previous":"M21-GAP-01283","next":"M21-GAP-01285"},"M21-GAP-01285":{"line":4540,"offset":805115,"length":194,"previous":"M21-GAP-01284","next":"M21-GAP-01286"},"M21-GAP-01286":{"line":4541,"offset":805309,"length":194,"previous":"M21-GAP-01285","next":"M21-GAP-01287"},"M21-GAP-01287":{"line":4542,"offset":805503,"length":193,"previous":"M21-GAP-01286","next":"M21-GAP-01288"},"M21-GAP-01288":{"line":4543,"offset":805696,"length":194,"previous":"M21-GAP-01287","next":"M21-GAP-01289"},"M21-GAP-01289":{"line":4544,"offset":805890,"length":194,"previous":"M21-GAP-01288","next":"M21-GAP-01290"},"M21-GAP-01290":{"line":4545,"offset":806084,"length":194,"previous":"M21-GAP-01289","next":"M21-GAP-01291"},"M21-GAP-01291":{"line":4546,"offset":806278,"length":194,"previous":"M21-GAP-01290","next":"M21-GAP-01292"},"M21-GAP-01292":{"line":4547,"offset":806472,"length":194,"previous":"M21-GAP-01291","next":"M21-GAP-01293"},"M21-GAP-01293":{"line":4548,"offset":806666,"length":194,"previous":"M21-GAP-01292","next":"M21-GAP-01294"},"M21-GAP-01294":{"line":4549,"offset":806860,"length":193,"previous":"M21-GAP-01293","next":"M21-GAP-01295"},"M21-GAP-01295":{"line":4550,"offset":807053,"length":193,"previous":"M21-GAP-01294","next":"M21-GAP-01296"},"M21-GAP-01296":{"line":4551,"offset":807246,"length":193,"previous":"M21-GAP-01295","next":"M21-GAP-01297"},"M21-GAP-01297":{"line":4552,"offset":807439,"length":193,"previous":"M21-GAP-01296","next":"M21-GAP-01298"},"M21-GAP-01298":{"line":4553,"offset":807632,"length":193,"previous":"M21-GAP-01297","next":"M21-GAP-01299"},"M21-GAP-01299":{"line":4554,"offset":807825,"length":193,"previous":"M21-GAP-01298","next":"M21-GAP-01300"},"M21-GAP-01300":{"line":4555,"offset":808018,"length":193,"previous":"M21-GAP-01299","next":"M21-GAP-01301"},"M21-GAP-01301":{"line":4556,"offset":808211,"length":180,"previous":"M21-GAP-01300","next":"M21-GAP-01302"},"M21-GAP-01302":{"line":4557,"offset":808391,"length":180,"previous":"M21-GAP-01301","next":"M21-GAP-01303"},"M21-GAP-01303":{"line":4558,"offset":808571,"length":180,"previous":"M21-GAP-01302","next":"M21-GAP-01304"},"M21-GAP-01304":{"line":4559,"offset":808751,"length":180,"previous":"M21-GAP-01303","next":"M21-GAP-01305"},"M21-GAP-01305":{"line":4560,"offset":808931,"length":180,"previous":"M21-GAP-01304","next":"M21-GAP-01306"},"M21-GAP-01306":{"line":4561,"offset":809111,"length":202,"previous":"M21-GAP-01305","next":"M21-GAP-01307"},"M21-GAP-01307":{"line":4562,"offset":809313,"length":205,"previous":"M21-GAP-01306","next":"M21-GAP-01308"},"M21-GAP-01308":{"line":4563,"offset":809518,"length":205,"previous":"M21-GAP-01307","next":"M21-GAP-01309"},"M21-GAP-01309":{"line":4564,"offset":809723,"length":205,"previous":"M21-GAP-01308","next":"M21-GAP-01310"},"M21-GAP-01310":{"line":4565,"offset":809928,"length":203,"previous":"M21-GAP-01309","next":"M21-GAP-01311"},"M21-GAP-01311":{"line":4566,"offset":810131,"length":205,"previous":"M21-GAP-01310","next":"M21-GAP-01312"},"M21-GAP-01312":{"line":4567,"offset":810336,"length":204,"previous":"M21-GAP-01311","next":"M21-GAP-01313"},"M21-GAP-01313":{"line":4568,"offset":810540,"length":220,"previous":"M21-GAP-01312","next":"M21-GAP-01314"},"M21-GAP-01314":{"line":4569,"offset":810760,"length":220,"previous":"M21-GAP-01313","next":"M21-GAP-01315"},"M21-GAP-01315":{"line":4570,"offset":810980,"length":220,"previous":"M21-GAP-01314","next":"M21-GAP-01316"},"M21-GAP-01316":{"line":4571,"offset":811200,"length":209,"previous":"M21-GAP-01315","next":"M21-GAP-01317"},"M21-GAP-01317":{"line":4572,"offset":811409,"length":209,"previous":"M21-GAP-01316","next":"M21-GAP-01318"},"M21-GAP-01318":{"line":4573,"offset":811618,"length":209,"previous":"M21-GAP-01317","next":"M21-GAP-01319"},"M21-GAP-01319":{"line":4574,"offset":811827,"length":223,"previous":"M21-GAP-01318","next":"M21-GAP-01320"},"M21-GAP-01320":{"line":4575,"offset":812050,"length":223,"previous":"M21-GAP-01319","next":"M21-GAP-01321"},"M21-GAP-01321":{"line":4576,"offset":812273,"length":223,"previous":"M21-GAP-01320","next":"M21-GAP-01322"},"M21-GAP-01322":{"line":4577,"offset":812496,"length":212,"previous":"M21-GAP-01321","next":"M21-GAP-01323"},"M21-GAP-01323":{"line":4578,"offset":812708,"length":212,"previous":"M21-GAP-01322","next":"M21-GAP-01324"},"M21-GAP-01324":{"line":4579,"offset":812920,"length":212,"previous":"M21-GAP-01323","next":"M21-GAP-01325"},"M21-GAP-01325":{"line":4580,"offset":813132,"length":222,"previous":"M21-GAP-01324","next":"M21-GAP-01326"},"M21-GAP-01326":{"line":4581,"offset":813354,"length":222,"previous":"M21-GAP-01325","next":"M21-GAP-01327"},"M21-GAP-01327":{"line":4582,"offset":813576,"length":222,"previous":"M21-GAP-01326","next":"M21-GAP-01328"},"M21-GAP-01328":{"line":4583,"offset":813798,"length":211,"previous":"M21-GAP-01327","next":"M21-GAP-01329"},"M21-GAP-01329":{"line":4584,"offset":814009,"length":211,"previous":"M21-GAP-01328","next":"M21-GAP-01330"},"M21-GAP-01330":{"line":4585,"offset":814220,"length":211,"previous":"M21-GAP-01329","next":"M21-GAP-01331"},"M21-GAP-01331":{"line":4586,"offset":814431,"length":208,"previous":"M21-GAP-01330","next":"M21-GAP-01332"},"M21-GAP-01332":{"line":4587,"offset":814639,"length":215,"previous":"M21-GAP-01331","next":"M21-GAP-01333"},"M21-GAP-01333":{"line":4588,"offset":814854,"length":215,"previous":"M21-GAP-01332","next":"M21-GAP-01334"},"M21-GAP-01334":{"line":4589,"offset":815069,"length":215,"previous":"M21-GAP-01333","next":"M21-GAP-01335"},"M21-GAP-01335":{"line":4590,"offset":815284,"length":204,"previous":"M21-GAP-01334","next":"M21-GAP-01336"},"M21-GAP-01336":{"line":4591,"offset":815488,"length":204,"previous":"M21-GAP-01335","next":"M21-GAP-01337"},"M21-GAP-01337":{"line":4592,"offset":815692,"length":204,"previous":"M21-GAP-01336","next":"M21-GAP-01338"},"M21-GAP-01338":{"line":4593,"offset":815896,"length":199,"previous":"M21-GAP-01337","next":"M21-GAP-01339"},"M21-GAP-01339":{"line":4594,"offset":816095,"length":203,"previous":"M21-GAP-01338","next":"M21-GAP-01340"},"M21-GAP-01340":{"line":4595,"offset":816298,"length":203,"previous":"M21-GAP-01339","next":"M21-GAP-01341"},"M21-GAP-01341":{"line":4596,"offset":816501,"length":201,"previous":"M21-GAP-01340","next":"M21-GAP-01342"},"M21-GAP-01342":{"line":4597,"offset":816702,"length":201,"previous":"M21-GAP-01341","next":"M21-GAP-01343"},"M21-GAP-01343":{"line":4598,"offset":816903,"length":201,"previous":"M21-GAP-01342","next":"M21-GAP-01344"},"M21-GAP-01344":{"line":4599,"offset":817104,"length":201,"previous":"M21-GAP-01343","next":"M21-GAP-01345"},"M21-GAP-01345":{"line":4600,"offset":817305,"length":201,"previous":"M21-GAP-01344","next":"M21-GAP-01346"},"M21-GAP-01346":{"line":4601,"offset":817506,"length":201,"previous":"M21-GAP-01345","next":"M21-GAP-01347"},"M21-GAP-01347":{"line":4602,"offset":817707,"length":202,"previous":"M21-GAP-01346","next":"M21-GAP-01348"},"M21-GAP-01348":{"line":4603,"offset":817909,"length":202,"previous":"M21-GAP-01347","next":"M21-GAP-01349"},"M21-GAP-01349":{"line":4604,"offset":818111,"length":202,"previous":"M21-GAP-01348","next":"M21-GAP-01350"},"M21-GAP-01350":{"line":4605,"offset":818313,"length":202,"previous":"M21-GAP-01349","next":"M21-GAP-01351"},"M21-GAP-01351":{"line":4606,"offset":818515,"length":202,"previous":"M21-GAP-01350","next":"M21-GAP-01352"},"M21-GAP-01352":{"line":4607,"offset":818717,"length":202,"previous":"M21-GAP-01351","next":"M21-GAP-01353"},"M21-GAP-01353":{"line":4608,"offset":818919,"length":202,"previous":"M21-GAP-01352","next":"M21-GAP-01354"},"M21-GAP-01354":{"line":4609,"offset":819121,"length":202,"previous":"M21-GAP-01353","next":"M21-GAP-01355"},"M21-GAP-01355":{"line":4610,"offset":819323,"length":202,"previous":"M21-GAP-01354","next":"M21-GAP-01356"},"M21-GAP-01356":{"line":4611,"offset":819525,"length":202,"previous":"M21-GAP-01355","next":"M21-GAP-01357"},"M21-GAP-01357":{"line":4612,"offset":819727,"length":207,"previous":"M21-GAP-01356","next":"M21-GAP-01358"},"M21-GAP-01358":{"line":4613,"offset":819934,"length":203,"previous":"M21-GAP-01357","next":"M21-GAP-01359"},"M21-GAP-01359":{"line":4614,"offset":820137,"length":202,"previous":"M21-GAP-01358","next":"M21-GAP-01360"},"M21-GAP-01360":{"line":4615,"offset":820339,"length":218,"previous":"M21-GAP-01359","next":"M21-GAP-01361"},"M21-GAP-01361":{"line":4616,"offset":820557,"length":218,"previous":"M21-GAP-01360","next":"M21-GAP-01362"},"M21-GAP-01362":{"line":4617,"offset":820775,"length":218,"previous":"M21-GAP-01361","next":"M21-GAP-01363"},"M21-GAP-01363":{"line":4618,"offset":820993,"length":207,"previous":"M21-GAP-01362","next":"M21-GAP-01364"},"M21-GAP-01364":{"line":4619,"offset":821200,"length":207,"previous":"M21-GAP-01363","next":"M21-GAP-01365"},"M21-GAP-01365":{"line":4620,"offset":821407,"length":207,"previous":"M21-GAP-01364","next":"M21-GAP-01366"},"M21-GAP-01366":{"line":4621,"offset":821614,"length":221,"previous":"M21-GAP-01365","next":"M21-GAP-01367"},"M21-GAP-01367":{"line":4622,"offset":821835,"length":221,"previous":"M21-GAP-01366","next":"M21-GAP-01368"},"M21-GAP-01368":{"line":4623,"offset":822056,"length":221,"previous":"M21-GAP-01367","next":"M21-GAP-01369"},"M21-GAP-01369":{"line":4624,"offset":822277,"length":210,"previous":"M21-GAP-01368","next":"M21-GAP-01370"},"M21-GAP-01370":{"line":4625,"offset":822487,"length":210,"previous":"M21-GAP-01369","next":"M21-GAP-01371"},"M21-GAP-01371":{"line":4626,"offset":822697,"length":210,"previous":"M21-GAP-01370","next":"M21-GAP-01372"},"M21-GAP-01372":{"line":4627,"offset":822907,"length":220,"previous":"M21-GAP-01371","next":"M21-GAP-01373"},"M21-GAP-01373":{"line":4628,"offset":823127,"length":220,"previous":"M21-GAP-01372","next":"M21-GAP-01374"},"M21-GAP-01374":{"line":4629,"offset":823347,"length":220,"previous":"M21-GAP-01373","next":"M21-GAP-01375"},"M21-GAP-01375":{"line":4630,"offset":823567,"length":209,"previous":"M21-GAP-01374","next":"M21-GAP-01376"},"M21-GAP-01376":{"line":4631,"offset":823776,"length":209,"previous":"M21-GAP-01375","next":"M21-GAP-01377"},"M21-GAP-01377":{"line":4632,"offset":823985,"length":209,"previous":"M21-GAP-01376","next":"M21-GAP-01378"},"M21-GAP-01378":{"line":4633,"offset":824194,"length":213,"previous":"M21-GAP-01377","next":"M21-GAP-01379"},"M21-GAP-01379":{"line":4634,"offset":824407,"length":213,"previous":"M21-GAP-01378","next":"M21-GAP-01380"},"M21-GAP-01380":{"line":4635,"offset":824620,"length":213,"previous":"M21-GAP-01379","next":"M21-GAP-01381"},"M21-GAP-01381":{"line":4636,"offset":824833,"length":202,"previous":"M21-GAP-01380","next":"M21-GAP-01382"},"M21-GAP-01382":{"line":4637,"offset":825035,"length":202,"previous":"M21-GAP-01381","next":"M21-GAP-01383"},"M21-GAP-01383":{"line":4638,"offset":825237,"length":202,"previous":"M21-GAP-01382","next":"M21-GAP-01384"},"M21-GAP-01384":{"line":4639,"offset":825439,"length":187,"previous":"M21-GAP-01383","next":"M21-GAP-01385"},"M21-GAP-01385":{"line":4640,"offset":825626,"length":187,"previous":"M21-GAP-01384","next":"M21-GAP-01386"},"M21-GAP-01386":{"line":4641,"offset":825813,"length":188,"previous":"M21-GAP-01385","next":"M21-GAP-01387"},"M21-GAP-01387":{"line":4642,"offset":826001,"length":187,"previous":"M21-GAP-01386","next":"M21-GAP-01388"},"M21-GAP-01388":{"line":4643,"offset":826188,"length":187,"previous":"M21-GAP-01387","next":"M21-GAP-01389"},"M21-GAP-01389":{"line":4644,"offset":826375,"length":187,"previous":"M21-GAP-01388","next":"M21-GAP-01390"},"M21-GAP-01390":{"line":4645,"offset":826562,"length":187,"previous":"M21-GAP-01389","next":"M21-GAP-01391"},"M21-GAP-01391":{"line":4646,"offset":826749,"length":187,"previous":"M21-GAP-01390","next":"M21-GAP-01392"},"M21-GAP-01392":{"line":4647,"offset":826936,"length":187,"previous":"M21-GAP-01391","next":"M21-GAP-01393"},"M21-GAP-01393":{"line":4648,"offset":827123,"length":187,"previous":"M21-GAP-01392","next":"M21-GAP-01394"},"M21-GAP-01394":{"line":4649,"offset":827310,"length":187,"previous":"M21-GAP-01393","next":"M21-GAP-01395"},"M21-GAP-01395":{"line":4650,"offset":827497,"length":178,"previous":"M21-GAP-01394","next":"M21-GAP-01396"},"M21-GAP-01396":{"line":4651,"offset":827675,"length":178,"previous":"M21-GAP-01395","next":"M21-GAP-01397"},"M21-GAP-01397":{"line":4652,"offset":827853,"length":179,"previous":"M21-GAP-01396","next":"M21-GAP-01398"},"M21-GAP-01398":{"line":4653,"offset":828032,"length":179,"previous":"M21-GAP-01397","next":"M21-GAP-01399"},"M21-GAP-01399":{"line":4654,"offset":828211,"length":179,"previous":"M21-GAP-01398","next":"M21-GAP-01400"},"M21-GAP-01400":{"line":4655,"offset":828390,"length":179,"previous":"M21-GAP-01399","next":"M21-GAP-01401"},"M21-GAP-01401":{"line":4656,"offset":828569,"length":179,"previous":"M21-GAP-01400","next":"M21-GAP-01402"},"M21-GAP-01402":{"line":4657,"offset":828748,"length":179,"previous":"M21-GAP-01401","next":"M21-GAP-01403"},"M21-GAP-01403":{"line":4658,"offset":828927,"length":179,"previous":"M21-GAP-01402","next":"M21-GAP-01404"},"M21-GAP-01404":{"line":4659,"offset":829106,"length":179,"previous":"M21-GAP-01403","next":"M21-GAP-01405"},"M21-GAP-01405":{"line":4660,"offset":829285,"length":179,"previous":"M21-GAP-01404","next":"M21-GAP-01406"},"M21-GAP-01406":{"line":4661,"offset":829464,"length":179,"previous":"M21-GAP-01405","next":"M21-GAP-01407"},"M21-GAP-01407":{"line":4662,"offset":829643,"length":178,"previous":"M21-GAP-01406","next":"M21-GAP-01408"},"M21-GAP-01408":{"line":4663,"offset":829821,"length":179,"previous":"M21-GAP-01407","next":"M21-GAP-01409"},"M21-GAP-01409":{"line":4664,"offset":830000,"length":179,"previous":"M21-GAP-01408","next":"M21-GAP-01410"},"M21-GAP-01410":{"line":4665,"offset":830179,"length":179,"previous":"M21-GAP-01409","next":"M21-GAP-01411"},"M21-GAP-01411":{"line":4666,"offset":830358,"length":179,"previous":"M21-GAP-01410","next":"M21-GAP-01412"},"M21-GAP-01412":{"line":4667,"offset":830537,"length":179,"previous":"M21-GAP-01411","next":"M21-GAP-01413"},"M21-GAP-01413":{"line":4668,"offset":830716,"length":179,"previous":"M21-GAP-01412","next":"M21-GAP-01414"},"M21-GAP-01414":{"line":4669,"offset":830895,"length":178,"previous":"M21-GAP-01413","next":"M21-GAP-01415"},"M21-GAP-01415":{"line":4670,"offset":831073,"length":178,"previous":"M21-GAP-01414","next":"M21-GAP-01416"},"M21-GAP-01416":{"line":4671,"offset":831251,"length":178,"previous":"M21-GAP-01415","next":"M21-GAP-01417"},"M21-GAP-01417":{"line":4672,"offset":831429,"length":178,"previous":"M21-GAP-01416","next":"M21-GAP-01418"},"M21-GAP-01418":{"line":4673,"offset":831607,"length":178,"previous":"M21-GAP-01417","next":"M21-GAP-01419"},"M21-GAP-01419":{"line":4674,"offset":831785,"length":178,"previous":"M21-GAP-01418","next":"M21-GAP-01420"},"M21-GAP-01420":{"line":4675,"offset":831963,"length":178,"previous":"M21-GAP-01419","next":"M21-GAP-01421"},"M21-GAP-01421":{"line":4676,"offset":832141,"length":179,"previous":"M21-GAP-01420","next":"M21-GAP-01422"},"M21-GAP-01422":{"line":4677,"offset":832320,"length":179,"previous":"M21-GAP-01421","next":"M21-GAP-01423"},"M21-GAP-01423":{"line":4678,"offset":832499,"length":180,"previous":"M21-GAP-01422","next":"M21-GAP-01424"},"M21-GAP-01424":{"line":4679,"offset":832679,"length":180,"previous":"M21-GAP-01423","next":"M21-GAP-01425"},"M21-GAP-01425":{"line":4680,"offset":832859,"length":180,"previous":"M21-GAP-01424","next":"M21-GAP-01426"},"M21-GAP-01426":{"line":4681,"offset":833039,"length":180,"previous":"M21-GAP-01425","next":"M21-GAP-01427"},"M21-GAP-01427":{"line":4682,"offset":833219,"length":180,"previous":"M21-GAP-01426","next":"M21-GAP-01428"},"M21-GAP-01428":{"line":4683,"offset":833399,"length":180,"previous":"M21-GAP-01427","next":"M21-GAP-01429"},"M21-GAP-01429":{"line":4684,"offset":833579,"length":180,"previous":"M21-GAP-01428","next":"M21-GAP-01430"},"M21-GAP-01430":{"line":4685,"offset":833759,"length":180,"previous":"M21-GAP-01429","next":"M21-GAP-01431"},"M21-GAP-01431":{"line":4686,"offset":833939,"length":180,"previous":"M21-GAP-01430","next":"M21-GAP-01432"},"M21-GAP-01432":{"line":4687,"offset":834119,"length":180,"previous":"M21-GAP-01431","next":"M21-GAP-01433"},"M21-GAP-01433":{"line":4688,"offset":834299,"length":179,"previous":"M21-GAP-01432","next":"M21-GAP-01434"},"M21-GAP-01434":{"line":4689,"offset":834478,"length":180,"previous":"M21-GAP-01433","next":"M21-GAP-01435"},"M21-GAP-01435":{"line":4690,"offset":834658,"length":180,"previous":"M21-GAP-01434","next":"M21-GAP-01436"},"M21-GAP-01436":{"line":4691,"offset":834838,"length":180,"previous":"M21-GAP-01435","next":"M21-GAP-01437"},"M21-GAP-01437":{"line":4692,"offset":835018,"length":180,"previous":"M21-GAP-01436","next":"M21-GAP-01438"},"M21-GAP-01438":{"line":4693,"offset":835198,"length":180,"previous":"M21-GAP-01437","next":"M21-GAP-01439"},"M21-GAP-01439":{"line":4694,"offset":835378,"length":180,"previous":"M21-GAP-01438","next":"M21-GAP-01440"},"M21-GAP-01440":{"line":4695,"offset":835558,"length":180,"previous":"M21-GAP-01439","next":"M21-GAP-01441"},"M21-GAP-01441":{"line":4696,"offset":835738,"length":180,"previous":"M21-GAP-01440","next":"M21-GAP-01442"},"M21-GAP-01442":{"line":4697,"offset":835918,"length":180,"previous":"M21-GAP-01441","next":"M21-GAP-01443"},"M21-GAP-01443":{"line":4698,"offset":836098,"length":180,"previous":"M21-GAP-01442","next":"M21-GAP-01444"},"M21-GAP-01444":{"line":4699,"offset":836278,"length":179,"previous":"M21-GAP-01443","next":"M21-GAP-01445"},"M21-GAP-01445":{"line":4700,"offset":836457,"length":180,"previous":"M21-GAP-01444","next":"M21-GAP-01446"},"M21-GAP-01446":{"line":4701,"offset":836637,"length":180,"previous":"M21-GAP-01445","next":"M21-GAP-01447"},"M21-GAP-01447":{"line":4702,"offset":836817,"length":180,"previous":"M21-GAP-01446","next":"M21-GAP-01448"},"M21-GAP-01448":{"line":4703,"offset":836997,"length":180,"previous":"M21-GAP-01447","next":"M21-GAP-01449"},"M21-GAP-01449":{"line":4704,"offset":837177,"length":180,"previous":"M21-GAP-01448","next":"M21-GAP-01450"},"M21-GAP-01450":{"line":4705,"offset":837357,"length":180,"previous":"M21-GAP-01449","next":"M21-GAP-01451"},"M21-GAP-01451":{"line":4706,"offset":837537,"length":180,"previous":"M21-GAP-01450","next":"M21-GAP-01452"},"M21-GAP-01452":{"line":4707,"offset":837717,"length":180,"previous":"M21-GAP-01451","next":"M21-GAP-01453"},"M21-GAP-01453":{"line":4708,"offset":837897,"length":180,"previous":"M21-GAP-01452","next":"M21-GAP-01454"},"M21-GAP-01454":{"line":4709,"offset":838077,"length":180,"previous":"M21-GAP-01453","next":"M21-GAP-01455"},"M21-GAP-01455":{"line":4710,"offset":838257,"length":179,"previous":"M21-GAP-01454","next":"M21-GAP-01456"},"M21-GAP-01456":{"line":4711,"offset":838436,"length":180,"previous":"M21-GAP-01455","next":"M21-GAP-01457"},"M21-GAP-01457":{"line":4712,"offset":838616,"length":180,"previous":"M21-GAP-01456","next":"M21-GAP-01458"},"M21-GAP-01458":{"line":4713,"offset":838796,"length":180,"previous":"M21-GAP-01457","next":"M21-GAP-01459"},"M21-GAP-01459":{"line":4714,"offset":838976,"length":180,"previous":"M21-GAP-01458","next":"M21-GAP-01460"},"M21-GAP-01460":{"line":4715,"offset":839156,"length":180,"previous":"M21-GAP-01459","next":"M21-GAP-01461"},"M21-GAP-01461":{"line":4716,"offset":839336,"length":180,"previous":"M21-GAP-01460","next":"M21-GAP-01462"},"M21-GAP-01462":{"line":4717,"offset":839516,"length":180,"previous":"M21-GAP-01461","next":"M21-GAP-01463"},"M21-GAP-01463":{"line":4718,"offset":839696,"length":180,"previous":"M21-GAP-01462","next":"M21-GAP-01464"},"M21-GAP-01464":{"line":4719,"offset":839876,"length":180,"previous":"M21-GAP-01463","next":"M21-GAP-01465"},"M21-GAP-01465":{"line":4720,"offset":840056,"length":180,"previous":"M21-GAP-01464","next":"M21-GAP-01466"},"M21-GAP-01466":{"line":4721,"offset":840236,"length":179,"previous":"M21-GAP-01465","next":"M21-GAP-01467"},"M21-GAP-01467":{"line":4722,"offset":840415,"length":180,"previous":"M21-GAP-01466","next":"M21-GAP-01468"},"M21-GAP-01468":{"line":4723,"offset":840595,"length":179,"previous":"M21-GAP-01467","next":"M21-GAP-01469"},"M21-GAP-01469":{"line":4724,"offset":840774,"length":179,"previous":"M21-GAP-01468","next":"M21-GAP-01470"},"M21-GAP-01470":{"line":4725,"offset":840953,"length":179,"previous":"M21-GAP-01469","next":"M21-GAP-01471"},"M21-GAP-01471":{"line":4726,"offset":841132,"length":179,"previous":"M21-GAP-01470","next":"M21-GAP-01472"},"M21-GAP-01472":{"line":4727,"offset":841311,"length":170,"previous":"M21-GAP-01471","next":"M21-GAP-01473"},"M21-GAP-01473":{"line":4728,"offset":841481,"length":170,"previous":"M21-GAP-01472","next":"M21-GAP-01474"},"M21-GAP-01474":{"line":4729,"offset":841651,"length":171,"previous":"M21-GAP-01473","next":"M21-GAP-01475"},"M21-GAP-01475":{"line":4730,"offset":841822,"length":171,"previous":"M21-GAP-01474","next":"M21-GAP-01476"},"M21-GAP-01476":{"line":4731,"offset":841993,"length":171,"previous":"M21-GAP-01475","next":"M21-GAP-01477"},"M21-GAP-01477":{"line":4732,"offset":842164,"length":171,"previous":"M21-GAP-01476","next":"M21-GAP-01478"},"M21-GAP-01478":{"line":4733,"offset":842335,"length":170,"previous":"M21-GAP-01477","next":"M21-GAP-01479"},"M21-GAP-01479":{"line":4734,"offset":842505,"length":170,"previous":"M21-GAP-01478","next":"M21-GAP-01480"},"M21-GAP-01480":{"line":4735,"offset":842675,"length":170,"previous":"M21-GAP-01479","next":"M21-GAP-01481"},"M21-GAP-01481":{"line":4736,"offset":842845,"length":170,"previous":"M21-GAP-01480","next":"M21-GAP-01482"},"M21-GAP-01482":{"line":4737,"offset":843015,"length":170,"previous":"M21-GAP-01481","next":"M21-GAP-01483"},"M21-GAP-01483":{"line":4738,"offset":843185,"length":170,"previous":"M21-GAP-01482","next":"M21-GAP-01484"},"M21-GAP-01484":{"line":4739,"offset":843355,"length":170,"previous":"M21-GAP-01483","next":"M21-GAP-01485"},"M21-GAP-01485":{"line":4740,"offset":843525,"length":170,"previous":"M21-GAP-01484","next":"M21-GAP-01486"},"M21-GAP-01486":{"line":4741,"offset":843695,"length":193,"previous":"M21-GAP-01485","next":"M21-GAP-01487"},"M21-GAP-01487":{"line":4742,"offset":843888,"length":193,"previous":"M21-GAP-01486","next":"M21-GAP-01488"},"M21-GAP-01488":{"line":4743,"offset":844081,"length":193,"previous":"M21-GAP-01487","next":"M21-GAP-01489"},"M21-GAP-01489":{"line":4744,"offset":844274,"length":193,"previous":"M21-GAP-01488","next":"M21-GAP-01490"},"M21-GAP-01490":{"line":4745,"offset":844467,"length":193,"previous":"M21-GAP-01489","next":"M21-GAP-01491"},"M21-GAP-01491":{"line":4746,"offset":844660,"length":193,"previous":"M21-GAP-01490","next":"M21-GAP-01492"},"M21-GAP-01492":{"line":4747,"offset":844853,"length":193,"previous":"M21-GAP-01491","next":"M21-GAP-01493"},"M21-GAP-01493":{"line":4748,"offset":845046,"length":187,"previous":"M21-GAP-01492","next":"M21-GAP-01494"},"M21-GAP-01494":{"line":4749,"offset":845233,"length":187,"previous":"M21-GAP-01493","next":"M21-GAP-01495"},"M21-GAP-01495":{"line":4750,"offset":845420,"length":188,"previous":"M21-GAP-01494","next":"M21-GAP-01496"},"M21-GAP-01496":{"line":4751,"offset":845608,"length":188,"previous":"M21-GAP-01495","next":"M21-GAP-01497"},"M21-GAP-01497":{"line":4752,"offset":845796,"length":188,"previous":"M21-GAP-01496","next":"M21-GAP-01498"},"M21-GAP-01498":{"line":4753,"offset":845984,"length":188,"previous":"M21-GAP-01497","next":"M21-GAP-01499"},"M21-GAP-01499":{"line":4754,"offset":846172,"length":188,"previous":"M21-GAP-01498","next":"M21-GAP-01500"},"M21-GAP-01500":{"line":4755,"offset":846360,"length":188,"previous":"M21-GAP-01499","next":"M21-GAP-01501"},"M21-GAP-01501":{"line":4756,"offset":846548,"length":188,"previous":"M21-GAP-01500","next":"M21-GAP-01502"},"M21-GAP-01502":{"line":4757,"offset":846736,"length":188,"previous":"M21-GAP-01501","next":"M21-GAP-01503"},"M21-GAP-01503":{"line":4758,"offset":846924,"length":188,"previous":"M21-GAP-01502","next":"M21-GAP-01504"},"M21-GAP-01504":{"line":4759,"offset":847112,"length":188,"previous":"M21-GAP-01503","next":"M21-GAP-01505"},"M21-GAP-01505":{"line":4760,"offset":847300,"length":187,"previous":"M21-GAP-01504","next":"M21-GAP-01506"},"M21-GAP-01506":{"line":4761,"offset":847487,"length":188,"previous":"M21-GAP-01505","next":"M21-GAP-01507"},"M21-GAP-01507":{"line":4762,"offset":847675,"length":188,"previous":"M21-GAP-01506","next":"M21-GAP-01508"},"M21-GAP-01508":{"line":4763,"offset":847863,"length":188,"previous":"M21-GAP-01507","next":"M21-GAP-01509"},"M21-GAP-01509":{"line":4764,"offset":848051,"length":188,"previous":"M21-GAP-01508","next":"M21-GAP-01510"},"M21-GAP-01510":{"line":4765,"offset":848239,"length":188,"previous":"M21-GAP-01509","next":"M21-GAP-01511"},"M21-GAP-01511":{"line":4766,"offset":848427,"length":187,"previous":"M21-GAP-01510","next":"M21-GAP-01512"},"M21-GAP-01512":{"line":4767,"offset":848614,"length":187,"previous":"M21-GAP-01511","next":"M21-GAP-01513"},"M21-GAP-01513":{"line":4768,"offset":848801,"length":187,"previous":"M21-GAP-01512","next":"M21-GAP-01514"},"M21-GAP-01514":{"line":4769,"offset":848988,"length":187,"previous":"M21-GAP-01513","next":"M21-GAP-01515"},"M21-GAP-01515":{"line":4770,"offset":849175,"length":187,"previous":"M21-GAP-01514","next":"M21-GAP-01516"},"M21-GAP-01516":{"line":4771,"offset":849362,"length":187,"previous":"M21-GAP-01515","next":"M21-GAP-01517"},"M21-GAP-01517":{"line":4772,"offset":849549,"length":187,"previous":"M21-GAP-01516","next":"M21-GAP-01518"},"M21-GAP-01518":{"line":4773,"offset":849736,"length":174,"previous":"M21-GAP-01517","next":"M21-GAP-01519"},"M21-GAP-01519":{"line":4774,"offset":849910,"length":174,"previous":"M21-GAP-01518","next":"M21-GAP-01520"},"M21-GAP-01520":{"line":4775,"offset":850084,"length":175,"previous":"M21-GAP-01519","next":"M21-GAP-01521"},"M21-GAP-01521":{"line":4776,"offset":850259,"length":175,"previous":"M21-GAP-01520","next":"M21-GAP-01522"},"M21-GAP-01522":{"line":4777,"offset":850434,"length":175,"previous":"M21-GAP-01521","next":"M21-GAP-01523"},"M21-GAP-01523":{"line":4778,"offset":850609,"length":175,"previous":"M21-GAP-01522","next":"M21-GAP-01524"},"M21-GAP-01524":{"line":4779,"offset":850784,"length":175,"previous":"M21-GAP-01523","next":"M21-GAP-01525"},"M21-GAP-01525":{"line":4780,"offset":850959,"length":175,"previous":"M21-GAP-01524","next":"M21-GAP-01526"},"M21-GAP-01526":{"line":4781,"offset":851134,"length":175,"previous":"M21-GAP-01525","next":"M21-GAP-01527"},"M21-GAP-01527":{"line":4782,"offset":851309,"length":175,"previous":"M21-GAP-01526","next":"M21-GAP-01528"},"M21-GAP-01528":{"line":4783,"offset":851484,"length":175,"previous":"M21-GAP-01527","next":"M21-GAP-01529"},"M21-GAP-01529":{"line":4784,"offset":851659,"length":175,"previous":"M21-GAP-01528","next":"M21-GAP-01530"},"M21-GAP-01530":{"line":4785,"offset":851834,"length":174,"previous":"M21-GAP-01529","next":"M21-GAP-01531"},"M21-GAP-01531":{"line":4786,"offset":852008,"length":175,"previous":"M21-GAP-01530","next":"M21-GAP-01532"},"M21-GAP-01532":{"line":4787,"offset":852183,"length":174,"previous":"M21-GAP-01531","next":"M21-GAP-01533"},"M21-GAP-01533":{"line":4788,"offset":852357,"length":174,"previous":"M21-GAP-01532","next":"M21-GAP-01534"},"M21-GAP-01534":{"line":4789,"offset":852531,"length":174,"previous":"M21-GAP-01533","next":"M21-GAP-01535"},"M21-GAP-01535":{"line":4790,"offset":852705,"length":174,"previous":"M21-GAP-01534","next":"M21-GAP-01536"},"M21-GAP-01536":{"line":4791,"offset":852879,"length":174,"previous":"M21-GAP-01535","next":"M21-GAP-01537"},"M21-GAP-01537":{"line":4792,"offset":853053,"length":174,"previous":"M21-GAP-01536","next":"M21-GAP-01538"},"M21-GAP-01538":{"line":4793,"offset":853227,"length":174,"previous":"M21-GAP-01537","next":"M21-GAP-01539"},"M21-GAP-01539":{"line":4794,"offset":853401,"length":174,"previous":"M21-GAP-01538","next":"M21-GAP-01540"},"M21-GAP-01540":{"line":4795,"offset":853575,"length":174,"previous":"M21-GAP-01539","next":"M21-GAP-01541"},"M21-GAP-01541":{"line":4796,"offset":853749,"length":175,"previous":"M21-GAP-01540","next":"M21-GAP-01542"},"M21-GAP-01542":{"line":4797,"offset":853924,"length":175,"previous":"M21-GAP-01541","next":"M21-GAP-01543"},"M21-GAP-01543":{"line":4798,"offset":854099,"length":175,"previous":"M21-GAP-01542","next":"M21-GAP-01544"},"M21-GAP-01544":{"line":4799,"offset":854274,"length":175,"previous":"M21-GAP-01543","next":"M21-GAP-01545"},"M21-GAP-01545":{"line":4800,"offset":854449,"length":175,"previous":"M21-GAP-01544","next":"M21-GAP-01546"},"M21-GAP-01546":{"line":4801,"offset":854624,"length":175,"previous":"M21-GAP-01545","next":"M21-GAP-01547"},"M21-GAP-01547":{"line":4802,"offset":854799,"length":175,"previous":"M21-GAP-01546","next":"M21-GAP-01548"},"M21-GAP-01548":{"line":4803,"offset":854974,"length":175,"previous":"M21-GAP-01547","next":"M21-GAP-01549"},"M21-GAP-01549":{"line":4804,"offset":855149,"length":175,"previous":"M21-GAP-01548","next":"M21-GAP-01550"},"M21-GAP-01550":{"line":4805,"offset":855324,"length":175,"previous":"M21-GAP-01549","next":"M21-GAP-01551"},"M21-GAP-01551":{"line":4806,"offset":855499,"length":174,"previous":"M21-GAP-01550","next":"M21-GAP-01552"},"M21-GAP-01552":{"line":4807,"offset":855673,"length":175,"previous":"M21-GAP-01551","next":"M21-GAP-01553"},"M21-GAP-01553":{"line":4808,"offset":855848,"length":175,"previous":"M21-GAP-01552","next":"M21-GAP-01554"},"M21-GAP-01554":{"line":4809,"offset":856023,"length":175,"previous":"M21-GAP-01553","next":"M21-GAP-01555"},"M21-GAP-01555":{"line":4810,"offset":856198,"length":175,"previous":"M21-GAP-01554","next":"M21-GAP-01556"},"M21-GAP-01556":{"line":4811,"offset":856373,"length":175,"previous":"M21-GAP-01555","next":"M21-GAP-01557"},"M21-GAP-01557":{"line":4812,"offset":856548,"length":174,"previous":"M21-GAP-01556","next":"M21-GAP-01558"},"M21-GAP-01558":{"line":4813,"offset":856722,"length":174,"previous":"M21-GAP-01557","next":"M21-GAP-01559"},"M21-GAP-01559":{"line":4814,"offset":856896,"length":174,"previous":"M21-GAP-01558","next":"M21-GAP-01560"},"M21-GAP-01560":{"line":4815,"offset":857070,"length":174,"previous":"M21-GAP-01559","next":"M21-GAP-01561"},"M21-GAP-01561":{"line":4816,"offset":857244,"length":174,"previous":"M21-GAP-01560","next":"M21-GAP-01562"},"M21-GAP-01562":{"line":4817,"offset":857418,"length":174,"previous":"M21-GAP-01561","next":"M21-GAP-01563"},"M21-GAP-01563":{"line":4818,"offset":857592,"length":174,"previous":"M21-GAP-01562","next":"M21-GAP-01564"},"M21-GAP-01564":{"line":4819,"offset":857766,"length":179,"previous":"M21-GAP-01563","next":"M21-GAP-01565"},"M21-GAP-01565":{"line":4820,"offset":857945,"length":179,"previous":"M21-GAP-01564","next":"M21-GAP-01566"},"M21-GAP-01566":{"line":4821,"offset":858124,"length":180,"previous":"M21-GAP-01565","next":"M21-GAP-01567"},"M21-GAP-01567":{"line":4822,"offset":858304,"length":180,"previous":"M21-GAP-01566","next":"M21-GAP-01568"},"M21-GAP-01568":{"line":4823,"offset":858484,"length":180,"previous":"M21-GAP-01567","next":"M21-GAP-01569"},"M21-GAP-01569":{"line":4824,"offset":858664,"length":180,"previous":"M21-GAP-01568","next":"M21-GAP-01570"},"M21-GAP-01570":{"line":4825,"offset":858844,"length":180,"previous":"M21-GAP-01569","next":"M21-GAP-01571"},"M21-GAP-01571":{"line":4826,"offset":859024,"length":180,"previous":"M21-GAP-01570","next":"M21-GAP-01572"},"M21-GAP-01572":{"line":4827,"offset":859204,"length":180,"previous":"M21-GAP-01571","next":"M21-GAP-01573"},"M21-GAP-01573":{"line":4828,"offset":859384,"length":180,"previous":"M21-GAP-01572","next":"M21-GAP-01574"},"M21-GAP-01574":{"line":4829,"offset":859564,"length":180,"previous":"M21-GAP-01573","next":"M21-GAP-01575"},"M21-GAP-01575":{"line":4830,"offset":859744,"length":180,"previous":"M21-GAP-01574","next":"M21-GAP-01576"},"M21-GAP-01576":{"line":4831,"offset":859924,"length":179,"previous":"M21-GAP-01575","next":"M21-GAP-01577"},"M21-GAP-01577":{"line":4832,"offset":860103,"length":180,"previous":"M21-GAP-01576","next":"M21-GAP-01578"},"M21-GAP-01578":{"line":4833,"offset":860283,"length":180,"previous":"M21-GAP-01577","next":"M21-GAP-01579"},"M21-GAP-01579":{"line":4834,"offset":860463,"length":180,"previous":"M21-GAP-01578","next":"M21-GAP-01580"},"M21-GAP-01580":{"line":4835,"offset":860643,"length":180,"previous":"M21-GAP-01579","next":"M21-GAP-01581"},"M21-GAP-01581":{"line":4836,"offset":860823,"length":180,"previous":"M21-GAP-01580","next":"M21-GAP-01582"},"M21-GAP-01582":{"line":4837,"offset":861003,"length":180,"previous":"M21-GAP-01581","next":"M21-GAP-01583"},"M21-GAP-01583":{"line":4838,"offset":861183,"length":180,"previous":"M21-GAP-01582","next":"M21-GAP-01584"},"M21-GAP-01584":{"line":4839,"offset":861363,"length":180,"previous":"M21-GAP-01583","next":"M21-GAP-01585"},"M21-GAP-01585":{"line":4840,"offset":861543,"length":180,"previous":"M21-GAP-01584","next":"M21-GAP-01586"},"M21-GAP-01586":{"line":4841,"offset":861723,"length":180,"previous":"M21-GAP-01585","next":"M21-GAP-01587"},"M21-GAP-01587":{"line":4842,"offset":861903,"length":179,"previous":"M21-GAP-01586","next":"M21-GAP-01588"},"M21-GAP-01588":{"line":4843,"offset":862082,"length":180,"previous":"M21-GAP-01587","next":"M21-GAP-01589"},"M21-GAP-01589":{"line":4844,"offset":862262,"length":180,"previous":"M21-GAP-01588","next":"M21-GAP-01590"},"M21-GAP-01590":{"line":4845,"offset":862442,"length":180,"previous":"M21-GAP-01589","next":"M21-GAP-01591"},"M21-GAP-01591":{"line":4846,"offset":862622,"length":180,"previous":"M21-GAP-01590","next":"M21-GAP-01592"},"M21-GAP-01592":{"line":4847,"offset":862802,"length":180,"previous":"M21-GAP-01591","next":"M21-GAP-01593"},"M21-GAP-01593":{"line":4848,"offset":862982,"length":180,"previous":"M21-GAP-01592","next":"M21-GAP-01594"},"M21-GAP-01594":{"line":4849,"offset":863162,"length":180,"previous":"M21-GAP-01593","next":"M21-GAP-01595"},"M21-GAP-01595":{"line":4850,"offset":863342,"length":180,"previous":"M21-GAP-01594","next":"M21-GAP-01596"},"M21-GAP-01596":{"line":4851,"offset":863522,"length":180,"previous":"M21-GAP-01595","next":"M21-GAP-01597"},"M21-GAP-01597":{"line":4852,"offset":863702,"length":180,"previous":"M21-GAP-01596","next":"M21-GAP-01598"},"M21-GAP-01598":{"line":4853,"offset":863882,"length":179,"previous":"M21-GAP-01597","next":"M21-GAP-01599"},"M21-GAP-01599":{"line":4854,"offset":864061,"length":180,"previous":"M21-GAP-01598","next":"M21-GAP-01600"},"M21-GAP-01600":{"line":4855,"offset":864241,"length":180,"previous":"M21-GAP-01599","next":"M21-GAP-01601"},"M21-GAP-01601":{"line":4856,"offset":864421,"length":180,"previous":"M21-GAP-01600","next":"M21-GAP-01602"},"M21-GAP-01602":{"line":4857,"offset":864601,"length":180,"previous":"M21-GAP-01601","next":"M21-GAP-01603"},"M21-GAP-01603":{"line":4858,"offset":864781,"length":180,"previous":"M21-GAP-01602","next":"M21-GAP-01604"},"M21-GAP-01604":{"line":4859,"offset":864961,"length":180,"previous":"M21-GAP-01603","next":"M21-GAP-01605"},"M21-GAP-01605":{"line":4860,"offset":865141,"length":180,"previous":"M21-GAP-01604","next":"M21-GAP-01606"},"M21-GAP-01606":{"line":4861,"offset":865321,"length":180,"previous":"M21-GAP-01605","next":"M21-GAP-01607"},"M21-GAP-01607":{"line":4862,"offset":865501,"length":179,"previous":"M21-GAP-01606","next":"M21-GAP-01608"},"M21-GAP-01608":{"line":4863,"offset":865680,"length":179,"previous":"M21-GAP-01607","next":"M21-GAP-01609"},"M21-GAP-01609":{"line":4864,"offset":865859,"length":179,"previous":"M21-GAP-01608","next":"M21-GAP-01610"},"M21-GAP-01610":{"line":4865,"offset":866038,"length":179,"previous":"M21-GAP-01609","next":"M21-GAP-01611"},"M21-GAP-01611":{"line":4866,"offset":866217,"length":179,"previous":"M21-GAP-01610","next":"M21-GAP-01612"},"M21-GAP-01612":{"line":4867,"offset":866396,"length":188,"previous":"M21-GAP-01611","next":"M21-GAP-01613"},"M21-GAP-01613":{"line":4868,"offset":866584,"length":188,"previous":"M21-GAP-01612","next":"M21-GAP-01614"},"M21-GAP-01614":{"line":4869,"offset":866772,"length":188,"previous":"M21-GAP-01613","next":"M21-GAP-01615"},"M21-GAP-01615":{"line":4870,"offset":866960,"length":188,"previous":"M21-GAP-01614","next":"M21-GAP-01616"},"M21-GAP-01616":{"line":4871,"offset":867148,"length":188,"previous":"M21-GAP-01615","next":"M21-GAP-01617"},"M21-GAP-01617":{"line":4872,"offset":867336,"length":188,"previous":"M21-GAP-01616","next":"M21-GAP-01618"},"M21-GAP-01618":{"line":4873,"offset":867524,"length":171,"previous":"M21-GAP-01617","next":"M21-GAP-01619"},"M21-GAP-01619":{"line":4874,"offset":867695,"length":171,"previous":"M21-GAP-01618","next":"M21-GAP-01620"},"M21-GAP-01620":{"line":4875,"offset":867866,"length":172,"previous":"M21-GAP-01619","next":"M21-GAP-01621"},"M21-GAP-01621":{"line":4876,"offset":868038,"length":172,"previous":"M21-GAP-01620","next":"M21-GAP-01622"},"M21-GAP-01622":{"line":4877,"offset":868210,"length":172,"previous":"M21-GAP-01621","next":"M21-GAP-01623"},"M21-GAP-01623":{"line":4878,"offset":868382,"length":172,"previous":"M21-GAP-01622","next":"M21-GAP-01624"},"M21-GAP-01624":{"line":4879,"offset":868554,"length":172,"previous":"M21-GAP-01623","next":"M21-GAP-01625"},"M21-GAP-01625":{"line":4880,"offset":868726,"length":172,"previous":"M21-GAP-01624","next":"M21-GAP-01626"},"M21-GAP-01626":{"line":4881,"offset":868898,"length":172,"previous":"M21-GAP-01625","next":"M21-GAP-01627"},"M21-GAP-01627":{"line":4882,"offset":869070,"length":172,"previous":"M21-GAP-01626","next":"M21-GAP-01628"},"M21-GAP-01628":{"line":4883,"offset":869242,"length":172,"previous":"M21-GAP-01627","next":"M21-GAP-01629"},"M21-GAP-01629":{"line":4884,"offset":869414,"length":172,"previous":"M21-GAP-01628","next":"M21-GAP-01630"},"M21-GAP-01630":{"line":4885,"offset":869586,"length":171,"previous":"M21-GAP-01629","next":"M21-GAP-01631"},"M21-GAP-01631":{"line":4886,"offset":869757,"length":172,"previous":"M21-GAP-01630","next":"M21-GAP-01632"},"M21-GAP-01632":{"line":4887,"offset":869929,"length":172,"previous":"M21-GAP-01631","next":"M21-GAP-01633"},"M21-GAP-01633":{"line":4888,"offset":870101,"length":172,"previous":"M21-GAP-01632","next":"M21-GAP-01634"},"M21-GAP-01634":{"line":4889,"offset":870273,"length":172,"previous":"M21-GAP-01633","next":"M21-GAP-01635"},"M21-GAP-01635":{"line":4890,"offset":870445,"length":172,"previous":"M21-GAP-01634","next":"M21-GAP-01636"},"M21-GAP-01636":{"line":4891,"offset":870617,"length":172,"previous":"M21-GAP-01635","next":"M21-GAP-01637"},"M21-GAP-01637":{"line":4892,"offset":870789,"length":172,"previous":"M21-GAP-01636","next":"M21-GAP-01638"},"M21-GAP-01638":{"line":4893,"offset":870961,"length":172,"previous":"M21-GAP-01637","next":"M21-GAP-01639"},"M21-GAP-01639":{"line":4894,"offset":871133,"length":172,"previous":"M21-GAP-01638","next":"M21-GAP-01640"},"M21-GAP-01640":{"line":4895,"offset":871305,"length":172,"previous":"M21-GAP-01639","next":"M21-GAP-01641"},"M21-GAP-01641":{"line":4896,"offset":871477,"length":171,"previous":"M21-GAP-01640","next":"M21-GAP-01642"},"M21-GAP-01642":{"line":4897,"offset":871648,"length":172,"previous":"M21-GAP-01641","next":"M21-GAP-01643"},"M21-GAP-01643":{"line":4898,"offset":871820,"length":172,"previous":"M21-GAP-01642","next":"M21-GAP-01644"},"M21-GAP-01644":{"line":4899,"offset":871992,"length":172,"previous":"M21-GAP-01643","next":"M21-GAP-01645"},"M21-GAP-01645":{"line":4900,"offset":872164,"length":172,"previous":"M21-GAP-01644","next":"M21-GAP-01646"},"M21-GAP-01646":{"line":4901,"offset":872336,"length":172,"previous":"M21-GAP-01645","next":"M21-GAP-01647"},"M21-GAP-01647":{"line":4902,"offset":872508,"length":172,"previous":"M21-GAP-01646","next":"M21-GAP-01648"},"M21-GAP-01648":{"line":4903,"offset":872680,"length":172,"previous":"M21-GAP-01647","next":"M21-GAP-01649"},"M21-GAP-01649":{"line":4904,"offset":872852,"length":172,"previous":"M21-GAP-01648","next":"M21-GAP-01650"},"M21-GAP-01650":{"line":4905,"offset":873024,"length":172,"previous":"M21-GAP-01649","next":"M21-GAP-01651"},"M21-GAP-01651":{"line":4906,"offset":873196,"length":172,"previous":"M21-GAP-01650","next":"M21-GAP-01652"},"M21-GAP-01652":{"line":4907,"offset":873368,"length":171,"previous":"M21-GAP-01651","next":"M21-GAP-01653"},"M21-GAP-01653":{"line":4908,"offset":873539,"length":172,"previous":"M21-GAP-01652","next":"M21-GAP-01654"},"M21-GAP-01654":{"line":4909,"offset":873711,"length":172,"previous":"M21-GAP-01653","next":"M21-GAP-01655"},"M21-GAP-01655":{"line":4910,"offset":873883,"length":172,"previous":"M21-GAP-01654","next":"M21-GAP-01656"},"M21-GAP-01656":{"line":4911,"offset":874055,"length":172,"previous":"M21-GAP-01655","next":"M21-GAP-01657"},"M21-GAP-01657":{"line":4912,"offset":874227,"length":172,"previous":"M21-GAP-01656","next":"M21-GAP-01658"},"M21-GAP-01658":{"line":4913,"offset":874399,"length":172,"previous":"M21-GAP-01657","next":"M21-GAP-01659"},"M21-GAP-01659":{"line":4914,"offset":874571,"length":172,"previous":"M21-GAP-01658","next":"M21-GAP-01660"},"M21-GAP-01660":{"line":4915,"offset":874743,"length":172,"previous":"M21-GAP-01659","next":"M21-GAP-01661"},"M21-GAP-01661":{"line":4916,"offset":874915,"length":172,"previous":"M21-GAP-01660","next":"M21-GAP-01662"},"M21-GAP-01662":{"line":4917,"offset":875087,"length":172,"previous":"M21-GAP-01661","next":"M21-GAP-01663"},"M21-GAP-01663":{"line":4918,"offset":875259,"length":171,"previous":"M21-GAP-01662","next":"M21-GAP-01664"},"M21-GAP-01664":{"line":4919,"offset":875430,"length":172,"previous":"M21-GAP-01663","next":"M21-GAP-01665"},"M21-GAP-01665":{"line":4920,"offset":875602,"length":172,"previous":"M21-GAP-01664","next":"M21-GAP-01666"},"M21-GAP-01666":{"line":4921,"offset":875774,"length":172,"previous":"M21-GAP-01665","next":"M21-GAP-01667"},"M21-GAP-01667":{"line":4922,"offset":875946,"length":172,"previous":"M21-GAP-01666","next":"M21-GAP-01668"},"M21-GAP-01668":{"line":4923,"offset":876118,"length":172,"previous":"M21-GAP-01667","next":"M21-GAP-01669"},"M21-GAP-01669":{"line":4924,"offset":876290,"length":172,"previous":"M21-GAP-01668","next":"M21-GAP-01670"},"M21-GAP-01670":{"line":4925,"offset":876462,"length":172,"previous":"M21-GAP-01669","next":"M21-GAP-01671"},"M21-GAP-01671":{"line":4926,"offset":876634,"length":172,"previous":"M21-GAP-01670","next":"M21-GAP-01672"},"M21-GAP-01672":{"line":4927,"offset":876806,"length":172,"previous":"M21-GAP-01671","next":"M21-GAP-01673"},"M21-GAP-01673":{"line":4928,"offset":876978,"length":172,"previous":"M21-GAP-01672","next":"M21-GAP-01674"},"M21-GAP-01674":{"line":4929,"offset":877150,"length":171,"previous":"M21-GAP-01673","next":"M21-GAP-01675"},"M21-GAP-01675":{"line":4930,"offset":877321,"length":172,"previous":"M21-GAP-01674","next":"M21-GAP-01676"},"M21-GAP-01676":{"line":4931,"offset":877493,"length":172,"previous":"M21-GAP-01675","next":"M21-GAP-01677"},"M21-GAP-01677":{"line":4932,"offset":877665,"length":172,"previous":"M21-GAP-01676","next":"M21-GAP-01678"},"M21-GAP-01678":{"line":4933,"offset":877837,"length":172,"previous":"M21-GAP-01677","next":"M21-GAP-01679"},"M21-GAP-01679":{"line":4934,"offset":878009,"length":172,"previous":"M21-GAP-01678","next":"M21-GAP-01680"},"M21-GAP-01680":{"line":4935,"offset":878181,"length":172,"previous":"M21-GAP-01679","next":"M21-GAP-01681"},"M21-GAP-01681":{"line":4936,"offset":878353,"length":172,"previous":"M21-GAP-01680","next":"M21-GAP-01682"},"M21-GAP-01682":{"line":4937,"offset":878525,"length":172,"previous":"M21-GAP-01681","next":"M21-GAP-01683"},"M21-GAP-01683":{"line":4938,"offset":878697,"length":172,"previous":"M21-GAP-01682","next":"M21-GAP-01684"},"M21-GAP-01684":{"line":4939,"offset":878869,"length":172,"previous":"M21-GAP-01683","next":"M21-GAP-01685"},"M21-GAP-01685":{"line":4940,"offset":879041,"length":171,"previous":"M21-GAP-01684","next":"M21-GAP-01686"},"M21-GAP-01686":{"line":4941,"offset":879212,"length":172,"previous":"M21-GAP-01685","next":"M21-GAP-01687"},"M21-GAP-01687":{"line":4942,"offset":879384,"length":172,"previous":"M21-GAP-01686","next":"M21-GAP-01688"},"M21-GAP-01688":{"line":4943,"offset":879556,"length":172,"previous":"M21-GAP-01687","next":"M21-GAP-01689"},"M21-GAP-01689":{"line":4944,"offset":879728,"length":172,"previous":"M21-GAP-01688","next":"M21-GAP-01690"},"M21-GAP-01690":{"line":4945,"offset":879900,"length":172,"previous":"M21-GAP-01689","next":"M21-GAP-01691"},"M21-GAP-01691":{"line":4946,"offset":880072,"length":172,"previous":"M21-GAP-01690","next":"M21-GAP-01692"},"M21-GAP-01692":{"line":4947,"offset":880244,"length":172,"previous":"M21-GAP-01691","next":"M21-GAP-01693"},"M21-GAP-01693":{"line":4948,"offset":880416,"length":172,"previous":"M21-GAP-01692","next":"M21-GAP-01694"},"M21-GAP-01694":{"line":4949,"offset":880588,"length":172,"previous":"M21-GAP-01693","next":"M21-GAP-01695"},"M21-GAP-01695":{"line":4950,"offset":880760,"length":172,"previous":"M21-GAP-01694","next":"M21-GAP-01696"},"M21-GAP-01696":{"line":4951,"offset":880932,"length":171,"previous":"M21-GAP-01695","next":"M21-GAP-01697"},"M21-GAP-01697":{"line":4952,"offset":881103,"length":172,"previous":"M21-GAP-01696","next":"M21-GAP-01698"},"M21-GAP-01698":{"line":4953,"offset":881275,"length":172,"previous":"M21-GAP-01697","next":"M21-GAP-01699"},"M21-GAP-01699":{"line":4954,"offset":881447,"length":172,"previous":"M21-GAP-01698","next":"M21-GAP-01700"},"M21-GAP-01700":{"line":4955,"offset":881619,"length":172,"previous":"M21-GAP-01699","next":"M21-GAP-01701"},"M21-GAP-01701":{"line":4956,"offset":881791,"length":172,"previous":"M21-GAP-01700","next":"M21-GAP-01702"},"M21-GAP-01702":{"line":4957,"offset":881963,"length":172,"previous":"M21-GAP-01701","next":"M21-GAP-01703"},"M21-GAP-01703":{"line":4958,"offset":882135,"length":172,"previous":"M21-GAP-01702","next":"M21-GAP-01704"},"M21-GAP-01704":{"line":4959,"offset":882307,"length":172,"previous":"M21-GAP-01703","next":"M21-GAP-01705"},"M21-GAP-01705":{"line":4960,"offset":882479,"length":172,"previous":"M21-GAP-01704","next":"M21-GAP-01706"},"M21-GAP-01706":{"line":4961,"offset":882651,"length":172,"previous":"M21-GAP-01705","next":"M21-GAP-01707"},"M21-GAP-01707":{"line":4962,"offset":882823,"length":171,"previous":"M21-GAP-01706","next":"M21-GAP-01708"},"M21-GAP-01708":{"line":4963,"offset":882994,"length":172,"previous":"M21-GAP-01707","next":"M21-GAP-01709"},"M21-GAP-01709":{"line":4964,"offset":883166,"length":172,"previous":"M21-GAP-01708","next":"M21-GAP-01710"},"M21-GAP-01710":{"line":4965,"offset":883338,"length":172,"previous":"M21-GAP-01709","next":"M21-GAP-01711"},"M21-GAP-01711":{"line":4966,"offset":883510,"length":175,"previous":"M21-GAP-01710","next":"M21-GAP-01712"},"M21-GAP-01712":{"line":4967,"offset":883685,"length":175,"previous":"M21-GAP-01711","next":"M21-GAP-01713"},"M21-GAP-01713":{"line":4968,"offset":883860,"length":176,"previous":"M21-GAP-01712","next":"M21-GAP-01714"},"M21-GAP-01714":{"line":4969,"offset":884036,"length":176,"previous":"M21-GAP-01713","next":"M21-GAP-01715"},"M21-GAP-01715":{"line":4970,"offset":884212,"length":176,"previous":"M21-GAP-01714","next":"M21-GAP-01716"},"M21-GAP-01716":{"line":4971,"offset":884388,"length":176,"previous":"M21-GAP-01715","next":"M21-GAP-01717"},"M21-GAP-01717":{"line":4972,"offset":884564,"length":176,"previous":"M21-GAP-01716","next":"M21-GAP-01718"},"M21-GAP-01718":{"line":4973,"offset":884740,"length":176,"previous":"M21-GAP-01717","next":"M21-GAP-01719"},"M21-GAP-01719":{"line":4974,"offset":884916,"length":176,"previous":"M21-GAP-01718","next":"M21-GAP-01720"},"M21-GAP-01720":{"line":4975,"offset":885092,"length":176,"previous":"M21-GAP-01719","next":"M21-GAP-01721"},"M21-GAP-01721":{"line":4976,"offset":885268,"length":176,"previous":"M21-GAP-01720","next":"M21-GAP-01722"},"M21-GAP-01722":{"line":4977,"offset":885444,"length":176,"previous":"M21-GAP-01721","next":"M21-GAP-01723"},"M21-GAP-01723":{"line":4978,"offset":885620,"length":175,"previous":"M21-GAP-01722","next":"M21-GAP-01724"},"M21-GAP-01724":{"line":4979,"offset":885795,"length":176,"previous":"M21-GAP-01723","next":"M21-GAP-01725"},"M21-GAP-01725":{"line":4980,"offset":885971,"length":176,"previous":"M21-GAP-01724","next":"M21-GAP-01726"},"M21-GAP-01726":{"line":4981,"offset":886147,"length":175,"previous":"M21-GAP-01725","next":"M21-GAP-01727"},"M21-GAP-01727":{"line":4982,"offset":886322,"length":175,"previous":"M21-GAP-01726","next":"M21-GAP-01728"},"M21-GAP-01728":{"line":4983,"offset":886497,"length":175,"previous":"M21-GAP-01727","next":"M21-GAP-01729"},"M21-GAP-01729":{"line":4984,"offset":886672,"length":175,"previous":"M21-GAP-01728","next":"M21-GAP-01730"},"M21-GAP-01730":{"line":4985,"offset":886847,"length":175,"previous":"M21-GAP-01729","next":"M21-GAP-01731"},"M21-GAP-01731":{"line":4986,"offset":887022,"length":175,"previous":"M21-GAP-01730","next":"M21-GAP-01732"},"M21-GAP-01732":{"line":4987,"offset":887197,"length":175,"previous":"M21-GAP-01731","next":"M21-GAP-01733"},"M21-GAP-01733":{"line":4988,"offset":887372,"length":182,"previous":"M21-GAP-01732","next":"M21-GAP-01734"},"M21-GAP-01734":{"line":4989,"offset":887554,"length":182,"previous":"M21-GAP-01733","next":"M21-GAP-01735"},"M21-GAP-01735":{"line":4990,"offset":887736,"length":183,"previous":"M21-GAP-01734","next":"M21-GAP-01736"},"M21-GAP-01736":{"line":4991,"offset":887919,"length":183,"previous":"M21-GAP-01735","next":"M21-GAP-01737"},"M21-GAP-01737":{"line":4992,"offset":888102,"length":183,"previous":"M21-GAP-01736","next":"M21-GAP-01738"},"M21-GAP-01738":{"line":4993,"offset":888285,"length":183,"previous":"M21-GAP-01737","next":"M21-GAP-01739"},"M21-GAP-01739":{"line":4994,"offset":888468,"length":183,"previous":"M21-GAP-01738","next":"M21-GAP-01740"},"M21-GAP-01740":{"line":4995,"offset":888651,"length":183,"previous":"M21-GAP-01739","next":"M21-GAP-01741"},"M21-GAP-01741":{"line":4996,"offset":888834,"length":183,"previous":"M21-GAP-01740","next":"M21-GAP-01742"},"M21-GAP-01742":{"line":4997,"offset":889017,"length":183,"previous":"M21-GAP-01741","next":"M21-GAP-01743"},"M21-GAP-01743":{"line":4998,"offset":889200,"length":183,"previous":"M21-GAP-01742","next":"M21-GAP-01744"},"M21-GAP-01744":{"line":4999,"offset":889383,"length":183,"previous":"M21-GAP-01743","next":"M21-GAP-01745"},"M21-GAP-01745":{"line":5000,"offset":889566,"length":182,"previous":"M21-GAP-01744","next":"M21-GAP-01746"},"M21-GAP-01746":{"line":5001,"offset":889748,"length":183,"previous":"M21-GAP-01745","next":"M21-GAP-01747"},"M21-GAP-01747":{"line":5002,"offset":889931,"length":183,"previous":"M21-GAP-01746","next":"M21-GAP-01748"},"M21-GAP-01748":{"line":5003,"offset":890114,"length":183,"previous":"M21-GAP-01747","next":"M21-GAP-01749"},"M21-GAP-01749":{"line":5004,"offset":890297,"length":183,"previous":"M21-GAP-01748","next":"M21-GAP-01750"},"M21-GAP-01750":{"line":5005,"offset":890480,"length":183,"previous":"M21-GAP-01749","next":"M21-GAP-01751"},"M21-GAP-01751":{"line":5006,"offset":890663,"length":183,"previous":"M21-GAP-01750","next":"M21-GAP-01752"},"M21-GAP-01752":{"line":5007,"offset":890846,"length":183,"previous":"M21-GAP-01751","next":"M21-GAP-01753"},"M21-GAP-01753":{"line":5008,"offset":891029,"length":183,"previous":"M21-GAP-01752","next":"M21-GAP-01754"},"M21-GAP-01754":{"line":5009,"offset":891212,"length":183,"previous":"M21-GAP-01753","next":"M21-GAP-01755"},"M21-GAP-01755":{"line":5010,"offset":891395,"length":183,"previous":"M21-GAP-01754","next":"M21-GAP-01756"},"M21-GAP-01756":{"line":5011,"offset":891578,"length":182,"previous":"M21-GAP-01755","next":"M21-GAP-01757"},"M21-GAP-01757":{"line":5012,"offset":891760,"length":183,"previous":"M21-GAP-01756","next":"M21-GAP-01758"},"M21-GAP-01758":{"line":5013,"offset":891943,"length":183,"previous":"M21-GAP-01757","next":"M21-GAP-01759"},"M21-GAP-01759":{"line":5014,"offset":892126,"length":183,"previous":"M21-GAP-01758","next":"M21-GAP-01760"},"M21-GAP-01760":{"line":5015,"offset":892309,"length":183,"previous":"M21-GAP-01759","next":"M21-GAP-01761"},"M21-GAP-01761":{"line":5016,"offset":892492,"length":183,"previous":"M21-GAP-01760","next":"M21-GAP-01762"},"M21-GAP-01762":{"line":5017,"offset":892675,"length":183,"previous":"M21-GAP-01761","next":"M21-GAP-01763"},"M21-GAP-01763":{"line":5018,"offset":892858,"length":183,"previous":"M21-GAP-01762","next":"M21-GAP-01764"},"M21-GAP-01764":{"line":5019,"offset":893041,"length":183,"previous":"M21-GAP-01763","next":"M21-GAP-01765"},"M21-GAP-01765":{"line":5020,"offset":893224,"length":183,"previous":"M21-GAP-01764","next":"M21-GAP-01766"},"M21-GAP-01766":{"line":5021,"offset":893407,"length":183,"previous":"M21-GAP-01765","next":"M21-GAP-01767"},"M21-GAP-01767":{"line":5022,"offset":893590,"length":182,"previous":"M21-GAP-01766","next":"M21-GAP-01768"},"M21-GAP-01768":{"line":5023,"offset":893772,"length":183,"previous":"M21-GAP-01767","next":"M21-GAP-01769"},"M21-GAP-01769":{"line":5024,"offset":893955,"length":183,"previous":"M21-GAP-01768","next":"M21-GAP-01770"},"M21-GAP-01770":{"line":5025,"offset":894138,"length":183,"previous":"M21-GAP-01769","next":"M21-GAP-01771"},"M21-GAP-01771":{"line":5026,"offset":894321,"length":183,"previous":"M21-GAP-01770","next":"M21-GAP-01772"},"M21-GAP-01772":{"line":5027,"offset":894504,"length":183,"previous":"M21-GAP-01771","next":"M21-GAP-01773"},"M21-GAP-01773":{"line":5028,"offset":894687,"length":183,"previous":"M21-GAP-01772","next":"M21-GAP-01774"},"M21-GAP-01774":{"line":5029,"offset":894870,"length":183,"previous":"M21-GAP-01773","next":"M21-GAP-01775"},"M21-GAP-01775":{"line":5030,"offset":895053,"length":183,"previous":"M21-GAP-01774","next":"M21-GAP-01776"},"M21-GAP-01776":{"line":5031,"offset":895236,"length":183,"previous":"M21-GAP-01775","next":"M21-GAP-01777"},"M21-GAP-01777":{"line":5032,"offset":895419,"length":182,"previous":"M21-GAP-01776","next":"M21-GAP-01778"},"M21-GAP-01778":{"line":5033,"offset":895601,"length":182,"previous":"M21-GAP-01777","next":"M21-GAP-01779"},"M21-GAP-01779":{"line":5034,"offset":895783,"length":182,"previous":"M21-GAP-01778","next":"M21-GAP-01780"},"M21-GAP-01780":{"line":5035,"offset":895965,"length":182,"previous":"M21-GAP-01779","next":"M21-GAP-01781"},"M21-GAP-01781":{"line":5036,"offset":896147,"length":182,"previous":"M21-GAP-01780","next":"M21-GAP-01782"},"M21-GAP-01782":{"line":5037,"offset":896329,"length":183,"previous":"M21-GAP-01781","next":"M21-GAP-01783"},"M21-GAP-01783":{"line":5038,"offset":896512,"length":183,"previous":"M21-GAP-01782","next":"M21-GAP-01784"},"M21-GAP-01784":{"line":5039,"offset":896695,"length":183,"previous":"M21-GAP-01783","next":"M21-GAP-01785"},"M21-GAP-01785":{"line":5040,"offset":896878,"length":183,"previous":"M21-GAP-01784","next":"M21-GAP-01786"},"M21-GAP-01786":{"line":5041,"offset":897061,"length":183,"previous":"M21-GAP-01785","next":"M21-GAP-01787"},"M21-GAP-01787":{"line":5042,"offset":897244,"length":183,"previous":"M21-GAP-01786","next":"M21-GAP-01788"},"M21-GAP-01788":{"line":5043,"offset":897427,"length":182,"previous":"M21-GAP-01787","next":"M21-GAP-01789"},"M21-GAP-01789":{"line":5044,"offset":897609,"length":182,"previous":"M21-GAP-01788","next":"M21-GAP-01790"},"M21-GAP-01790":{"line":5045,"offset":897791,"length":182,"previous":"M21-GAP-01789","next":"M21-GAP-01791"},"M21-GAP-01791":{"line":5046,"offset":897973,"length":182,"previous":"M21-GAP-01790","next":"M21-GAP-01792"},"M21-GAP-01792":{"line":5047,"offset":898155,"length":182,"previous":"M21-GAP-01791","next":"M21-GAP-01793"},"M21-GAP-01793":{"line":5048,"offset":898337,"length":182,"previous":"M21-GAP-01792","next":"M21-GAP-01794"},"M21-GAP-01794":{"line":5049,"offset":898519,"length":182,"previous":"M21-GAP-01793","next":"M21-GAP-01795"},"M21-GAP-01795":{"line":5050,"offset":898701,"length":182,"previous":"M21-GAP-01794","next":"M21-GAP-01796"},"M21-GAP-01796":{"line":5051,"offset":898883,"length":184,"previous":"M21-GAP-01795","next":"M21-GAP-01797"},"M21-GAP-01797":{"line":5052,"offset":899067,"length":184,"previous":"M21-GAP-01796","next":"M21-GAP-01798"},"M21-GAP-01798":{"line":5053,"offset":899251,"length":185,"previous":"M21-GAP-01797","next":"M21-GAP-01799"},"M21-GAP-01799":{"line":5054,"offset":899436,"length":186,"previous":"M21-GAP-01798","next":"M21-GAP-01800"},"M21-GAP-01800":{"line":5055,"offset":899622,"length":186,"previous":"M21-GAP-01799","next":"M21-GAP-01801"},"M21-GAP-01801":{"line":5056,"offset":899808,"length":186,"previous":"M21-GAP-01800","next":"M21-GAP-01802"},"M21-GAP-01802":{"line":5057,"offset":899994,"length":186,"previous":"M21-GAP-01801","next":"M21-GAP-01803"},"M21-GAP-01803":{"line":5058,"offset":900180,"length":185,"previous":"M21-GAP-01802","next":"M21-GAP-01804"},"M21-GAP-01804":{"line":5059,"offset":900365,"length":185,"previous":"M21-GAP-01803","next":"M21-GAP-01805"},"M21-GAP-01805":{"line":5060,"offset":900550,"length":185,"previous":"M21-GAP-01804","next":"M21-GAP-01806"},"M21-GAP-01806":{"line":5061,"offset":900735,"length":185,"previous":"M21-GAP-01805","next":"M21-GAP-01807"},"M21-GAP-01807":{"line":5062,"offset":900920,"length":185,"previous":"M21-GAP-01806","next":"M21-GAP-01808"},"M21-GAP-01808":{"line":5063,"offset":901105,"length":185,"previous":"M21-GAP-01807","next":"M21-GAP-01809"},"M21-GAP-01809":{"line":5064,"offset":901290,"length":185,"previous":"M21-GAP-01808","next":"M21-GAP-01810"},"M21-GAP-01810":{"line":5065,"offset":901475,"length":185,"previous":"M21-GAP-01809","next":"M21-GAP-01811"},"M21-GAP-01811":{"line":5066,"offset":901660,"length":185,"previous":"M21-GAP-01810","next":"M21-GAP-01812"},"M21-GAP-01812":{"line":5067,"offset":901845,"length":184,"previous":"M21-GAP-01811","next":"M21-GAP-01813"},"M21-GAP-01813":{"line":5068,"offset":902029,"length":185,"previous":"M21-GAP-01812","next":"M21-GAP-01814"},"M21-GAP-01814":{"line":5069,"offset":902214,"length":185,"previous":"M21-GAP-01813","next":"M21-GAP-01815"},"M21-GAP-01815":{"line":5070,"offset":902399,"length":185,"previous":"M21-GAP-01814","next":"M21-GAP-01816"},"M21-GAP-01816":{"line":5071,"offset":902584,"length":185,"previous":"M21-GAP-01815","next":"M21-GAP-01817"},"M21-GAP-01817":{"line":5072,"offset":902769,"length":185,"previous":"M21-GAP-01816","next":"M21-GAP-01818"},"M21-GAP-01818":{"line":5073,"offset":902954,"length":185,"previous":"M21-GAP-01817","next":"M21-GAP-01819"},"M21-GAP-01819":{"line":5074,"offset":903139,"length":185,"previous":"M21-GAP-01818","next":"M21-GAP-01820"},"M21-GAP-01820":{"line":5075,"offset":903324,"length":185,"previous":"M21-GAP-01819","next":"M21-GAP-01821"},"M21-GAP-01821":{"line":5076,"offset":903509,"length":185,"previous":"M21-GAP-01820","next":"M21-GAP-01822"},"M21-GAP-01822":{"line":5077,"offset":903694,"length":185,"previous":"M21-GAP-01821","next":"M21-GAP-01823"},"M21-GAP-01823":{"line":5078,"offset":903879,"length":184,"previous":"M21-GAP-01822","next":"M21-GAP-01824"},"M21-GAP-01824":{"line":5079,"offset":904063,"length":185,"previous":"M21-GAP-01823","next":"M21-GAP-01825"},"M21-GAP-01825":{"line":5080,"offset":904248,"length":185,"previous":"M21-GAP-01824","next":"M21-GAP-01826"},"M21-GAP-01826":{"line":5081,"offset":904433,"length":185,"previous":"M21-GAP-01825","next":"M21-GAP-01827"},"M21-GAP-01827":{"line":5082,"offset":904618,"length":185,"previous":"M21-GAP-01826","next":"M21-GAP-01828"},"M21-GAP-01828":{"line":5083,"offset":904803,"length":185,"previous":"M21-GAP-01827","next":"M21-GAP-01829"},"M21-GAP-01829":{"line":5084,"offset":904988,"length":185,"previous":"M21-GAP-01828","next":"M21-GAP-01830"},"M21-GAP-01830":{"line":5085,"offset":905173,"length":185,"previous":"M21-GAP-01829","next":"M21-GAP-01831"},"M21-GAP-01831":{"line":5086,"offset":905358,"length":185,"previous":"M21-GAP-01830","next":"M21-GAP-01832"},"M21-GAP-01832":{"line":5087,"offset":905543,"length":185,"previous":"M21-GAP-01831","next":"M21-GAP-01833"},"M21-GAP-01833":{"line":5088,"offset":905728,"length":185,"previous":"M21-GAP-01832","next":"M21-GAP-01834"},"M21-GAP-01834":{"line":5089,"offset":905913,"length":184,"previous":"M21-GAP-01833","next":"M21-GAP-01835"},"M21-GAP-01835":{"line":5090,"offset":906097,"length":185,"previous":"M21-GAP-01834","next":"M21-GAP-01836"},"M21-GAP-01836":{"line":5091,"offset":906282,"length":185,"previous":"M21-GAP-01835","next":"M21-GAP-01837"},"M21-GAP-01837":{"line":5092,"offset":906467,"length":185,"previous":"M21-GAP-01836","next":"M21-GAP-01838"},"M21-GAP-01838":{"line":5093,"offset":906652,"length":185,"previous":"M21-GAP-01837","next":"M21-GAP-01839"},"M21-GAP-01839":{"line":5094,"offset":906837,"length":185,"previous":"M21-GAP-01838","next":"M21-GAP-01840"},"M21-GAP-01840":{"line":5095,"offset":907022,"length":185,"previous":"M21-GAP-01839","next":"M21-GAP-01841"},"M21-GAP-01841":{"line":5096,"offset":907207,"length":185,"previous":"M21-GAP-01840","next":"M21-GAP-01842"},"M21-GAP-01842":{"line":5097,"offset":907392,"length":185,"previous":"M21-GAP-01841","next":"M21-GAP-01843"},"M21-GAP-01843":{"line":5098,"offset":907577,"length":185,"previous":"M21-GAP-01842","next":"M21-GAP-01844"},"M21-GAP-01844":{"line":5099,"offset":907762,"length":185,"previous":"M21-GAP-01843","next":"M21-GAP-01845"},"M21-GAP-01845":{"line":5100,"offset":907947,"length":184,"previous":"M21-GAP-01844","next":"M21-GAP-01846"},"M21-GAP-01846":{"line":5101,"offset":908131,"length":185,"previous":"M21-GAP-01845","next":"M21-GAP-01847"},"M21-GAP-01847":{"line":5102,"offset":908316,"length":185,"previous":"M21-GAP-01846","next":"M21-GAP-01848"},"M21-GAP-01848":{"line":5103,"offset":908501,"length":185,"previous":"M21-GAP-01847","next":"M21-GAP-01849"},"M21-GAP-01849":{"line":5104,"offset":908686,"length":185,"previous":"M21-GAP-01848","next":"M21-GAP-01850"},"M21-GAP-01850":{"line":5105,"offset":908871,"length":185,"previous":"M21-GAP-01849","next":"M21-GAP-01851"},"M21-GAP-01851":{"line":5106,"offset":909056,"length":185,"previous":"M21-GAP-01850","next":"M21-GAP-01852"},"M21-GAP-01852":{"line":5107,"offset":909241,"length":185,"previous":"M21-GAP-01851","next":"M21-GAP-01853"},"M21-GAP-01853":{"line":5108,"offset":909426,"length":185,"previous":"M21-GAP-01852","next":"M21-GAP-01854"},"M21-GAP-01854":{"line":5109,"offset":909611,"length":185,"previous":"M21-GAP-01853","next":"M21-GAP-01855"},"M21-GAP-01855":{"line":5110,"offset":909796,"length":185,"previous":"M21-GAP-01854","next":"M21-GAP-01856"},"M21-GAP-01856":{"line":5111,"offset":909981,"length":184,"previous":"M21-GAP-01855","next":"M21-GAP-01857"},"M21-GAP-01857":{"line":5112,"offset":910165,"length":185,"previous":"M21-GAP-01856","next":"M21-GAP-01858"},"M21-GAP-01858":{"line":5113,"offset":910350,"length":185,"previous":"M21-GAP-01857","next":"M21-GAP-01859"},"M21-GAP-01859":{"line":5114,"offset":910535,"length":185,"previous":"M21-GAP-01858","next":"M21-GAP-01860"},"M21-GAP-01860":{"line":5115,"offset":910720,"length":185,"previous":"M21-GAP-01859","next":"M21-GAP-01861"},"M21-GAP-01861":{"line":5116,"offset":910905,"length":185,"previous":"M21-GAP-01860","next":"M21-GAP-01862"},"M21-GAP-01862":{"line":5117,"offset":911090,"length":185,"previous":"M21-GAP-01861","next":"M21-GAP-01863"},"M21-GAP-01863":{"line":5118,"offset":911275,"length":185,"previous":"M21-GAP-01862","next":"M21-GAP-01864"},"M21-GAP-01864":{"line":5119,"offset":911460,"length":185,"previous":"M21-GAP-01863","next":"M21-GAP-01865"},"M21-GAP-01865":{"line":5120,"offset":911645,"length":185,"previous":"M21-GAP-01864","next":"M21-GAP-01866"},"M21-GAP-01866":{"line":5121,"offset":911830,"length":185,"previous":"M21-GAP-01865","next":"M21-GAP-01867"},"M21-GAP-01867":{"line":5122,"offset":912015,"length":184,"previous":"M21-GAP-01866","next":"M21-GAP-01868"},"M21-GAP-01868":{"line":5123,"offset":912199,"length":185,"previous":"M21-GAP-01867","next":"M21-GAP-01869"},"M21-GAP-01869":{"line":5124,"offset":912384,"length":185,"previous":"M21-GAP-01868","next":"M21-GAP-01870"},"M21-GAP-01870":{"line":5125,"offset":912569,"length":185,"previous":"M21-GAP-01869","next":"M21-GAP-01871"},"M21-GAP-01871":{"line":5126,"offset":912754,"length":185,"previous":"M21-GAP-01870","next":"M21-GAP-01872"},"M21-GAP-01872":{"line":5127,"offset":912939,"length":185,"previous":"M21-GAP-01871","next":"M21-GAP-01873"},"M21-GAP-01873":{"line":5128,"offset":913124,"length":185,"previous":"M21-GAP-01872","next":"M21-GAP-01874"},"M21-GAP-01874":{"line":5129,"offset":913309,"length":185,"previous":"M21-GAP-01873","next":"M21-GAP-01875"},"M21-GAP-01875":{"line":5130,"offset":913494,"length":185,"previous":"M21-GAP-01874","next":"M21-GAP-01876"},"M21-GAP-01876":{"line":5131,"offset":913679,"length":185,"previous":"M21-GAP-01875","next":"M21-GAP-01877"},"M21-GAP-01877":{"line":5132,"offset":913864,"length":185,"previous":"M21-GAP-01876","next":"M21-GAP-01878"},"M21-GAP-01878":{"line":5133,"offset":914049,"length":184,"previous":"M21-GAP-01877","next":"M21-GAP-01879"},"M21-GAP-01879":{"line":5134,"offset":914233,"length":185,"previous":"M21-GAP-01878","next":"M21-GAP-01880"},"M21-GAP-01880":{"line":5135,"offset":914418,"length":185,"previous":"M21-GAP-01879","next":"M21-GAP-01881"},"M21-GAP-01881":{"line":5136,"offset":914603,"length":185,"previous":"M21-GAP-01880","next":"M21-GAP-01882"},"M21-GAP-01882":{"line":5137,"offset":914788,"length":185,"previous":"M21-GAP-01881","next":"M21-GAP-01883"},"M21-GAP-01883":{"line":5138,"offset":914973,"length":185,"previous":"M21-GAP-01882","next":"M21-GAP-01884"},"M21-GAP-01884":{"line":5139,"offset":915158,"length":185,"previous":"M21-GAP-01883","next":"M21-GAP-01885"},"M21-GAP-01885":{"line":5140,"offset":915343,"length":185,"previous":"M21-GAP-01884","next":"M21-GAP-01886"},"M21-GAP-01886":{"line":5141,"offset":915528,"length":185,"previous":"M21-GAP-01885","next":"M21-GAP-01887"},"M21-GAP-01887":{"line":5142,"offset":915713,"length":185,"previous":"M21-GAP-01886","next":"M21-GAP-01888"},"M21-GAP-01888":{"line":5143,"offset":915898,"length":185,"previous":"M21-GAP-01887","next":"M21-GAP-01889"},"M21-GAP-01889":{"line":5144,"offset":916083,"length":184,"previous":"M21-GAP-01888","next":"M21-GAP-01890"},"M21-GAP-01890":{"line":5145,"offset":916267,"length":185,"previous":"M21-GAP-01889","next":"M21-GAP-01891"},"M21-GAP-01891":{"line":5146,"offset":916452,"length":185,"previous":"M21-GAP-01890","next":"M21-GAP-01892"},"M21-GAP-01892":{"line":5147,"offset":916637,"length":185,"previous":"M21-GAP-01891","next":"M21-GAP-01893"},"M21-GAP-01893":{"line":5148,"offset":916822,"length":185,"previous":"M21-GAP-01892","next":"M21-GAP-01894"},"M21-GAP-01894":{"line":5149,"offset":917007,"length":185,"previous":"M21-GAP-01893","next":"M21-GAP-01895"},"M21-GAP-01895":{"line":5150,"offset":917192,"length":185,"previous":"M21-GAP-01894","next":"M21-GAP-01896"},"M21-GAP-01896":{"line":5151,"offset":917377,"length":185,"previous":"M21-GAP-01895","next":"M21-GAP-01897"},"M21-GAP-01897":{"line":5152,"offset":917562,"length":185,"previous":"M21-GAP-01896","next":"M21-GAP-01898"},"M21-GAP-01898":{"line":5153,"offset":917747,"length":185,"previous":"M21-GAP-01897","next":"M21-GAP-01899"},"M21-GAP-01899":{"line":5154,"offset":917932,"length":185,"previous":"M21-GAP-01898","next":"M21-GAP-01900"},"M21-GAP-01900":{"line":5155,"offset":918117,"length":185,"previous":"M21-GAP-01899","next":"M21-GAP-01901"},"M21-GAP-01901":{"line":5156,"offset":918302,"length":185,"previous":"M21-GAP-01900","next":"M21-GAP-01902"},"M21-GAP-01902":{"line":5157,"offset":918487,"length":186,"previous":"M21-GAP-01901","next":"M21-GAP-01903"},"M21-GAP-01903":{"line":5158,"offset":918673,"length":186,"previous":"M21-GAP-01902","next":"M21-GAP-01904"},"M21-GAP-01904":{"line":5159,"offset":918859,"length":186,"previous":"M21-GAP-01903","next":"M21-GAP-01905"},"M21-GAP-01905":{"line":5160,"offset":919045,"length":186,"previous":"M21-GAP-01904","next":"M21-GAP-01906"},"M21-GAP-01906":{"line":5161,"offset":919231,"length":186,"previous":"M21-GAP-01905","next":"M21-GAP-01907"},"M21-GAP-01907":{"line":5162,"offset":919417,"length":186,"previous":"M21-GAP-01906","next":"M21-GAP-01908"},"M21-GAP-01908":{"line":5163,"offset":919603,"length":188,"previous":"M21-GAP-01907","next":"M21-GAP-01909"},"M21-GAP-01909":{"line":5164,"offset":919791,"length":188,"previous":"M21-GAP-01908","next":"M21-GAP-01910"},"M21-GAP-01910":{"line":5165,"offset":919979,"length":188,"previous":"M21-GAP-01909","next":"M21-GAP-01911"},"M21-GAP-01911":{"line":5166,"offset":920167,"length":188,"previous":"M21-GAP-01910","next":"M21-GAP-01912"},"M21-GAP-01912":{"line":5167,"offset":920355,"length":188,"previous":"M21-GAP-01911","next":"M21-GAP-01913"},"M21-GAP-01913":{"line":5168,"offset":920543,"length":188,"previous":"M21-GAP-01912","next":"M21-GAP-01914"},"M21-GAP-01914":{"line":5169,"offset":920731,"length":188,"previous":"M21-GAP-01913","next":"M21-GAP-01915"},"M21-GAP-01915":{"line":5170,"offset":920919,"length":195,"previous":"M21-GAP-01914","next":"M21-GAP-01916"},"M21-GAP-01916":{"line":5171,"offset":921114,"length":193,"previous":"M21-GAP-01915","next":"M21-GAP-01917"},"M21-GAP-01917":{"line":5172,"offset":921307,"length":194,"previous":"M21-GAP-01916","next":"M21-GAP-01918"},"M21-GAP-01918":{"line":5173,"offset":921501,"length":205,"previous":"M21-GAP-01917","next":"M21-GAP-01919"},"M21-GAP-01919":{"line":5174,"offset":921706,"length":205,"previous":"M21-GAP-01918","next":"M21-GAP-01920"},"M21-GAP-01920":{"line":5175,"offset":921911,"length":206,"previous":"M21-GAP-01919","next":"M21-GAP-01921"},"M21-GAP-01921":{"line":5176,"offset":922117,"length":206,"previous":"M21-GAP-01920","next":"M21-GAP-01922"},"M21-GAP-01922":{"line":5177,"offset":922323,"length":205,"previous":"M21-GAP-01921","next":"M21-GAP-01923"},"M21-GAP-01923":{"line":5178,"offset":922528,"length":205,"previous":"M21-GAP-01922","next":"M21-GAP-01924"},"M21-GAP-01924":{"line":5179,"offset":922733,"length":205,"previous":"M21-GAP-01923","next":"M21-GAP-01925"},"M21-GAP-01925":{"line":5180,"offset":922938,"length":205,"previous":"M21-GAP-01924","next":"M21-GAP-01926"},"M21-GAP-01926":{"line":5181,"offset":923143,"length":205,"previous":"M21-GAP-01925","next":"M21-GAP-01927"},"M21-GAP-01927":{"line":5182,"offset":923348,"length":205,"previous":"M21-GAP-01926","next":"M21-GAP-01928"},"M21-GAP-01928":{"line":5183,"offset":923553,"length":205,"previous":"M21-GAP-01927","next":"M21-GAP-01929"},"M21-GAP-01929":{"line":5184,"offset":923758,"length":205,"previous":"M21-GAP-01928","next":"M21-GAP-01930"},"M21-GAP-01930":{"line":5185,"offset":923963,"length":194,"previous":"M21-GAP-01929","next":"M21-GAP-01931"},"M21-GAP-01931":{"line":5186,"offset":924157,"length":194,"previous":"M21-GAP-01930","next":"M21-GAP-01932"},"M21-GAP-01932":{"line":5187,"offset":924351,"length":195,"previous":"M21-GAP-01931","next":"M21-GAP-01933"},"M21-GAP-01933":{"line":5188,"offset":924546,"length":195,"previous":"M21-GAP-01932","next":"M21-GAP-01934"},"M21-GAP-01934":{"line":5189,"offset":924741,"length":194,"previous":"M21-GAP-01933","next":"M21-GAP-01935"},"M21-GAP-01935":{"line":5190,"offset":924935,"length":194,"previous":"M21-GAP-01934","next":"M21-GAP-01936"},"M21-GAP-01936":{"line":5191,"offset":925129,"length":194,"previous":"M21-GAP-01935","next":"M21-GAP-01937"},"M21-GAP-01937":{"line":5192,"offset":925323,"length":194,"previous":"M21-GAP-01936","next":"M21-GAP-01938"},"M21-GAP-01938":{"line":5193,"offset":925517,"length":194,"previous":"M21-GAP-01937","next":"M21-GAP-01939"},"M21-GAP-01939":{"line":5194,"offset":925711,"length":194,"previous":"M21-GAP-01938","next":"M21-GAP-01940"},"M21-GAP-01940":{"line":5195,"offset":925905,"length":194,"previous":"M21-GAP-01939","next":"M21-GAP-01941"},"M21-GAP-01941":{"line":5196,"offset":926099,"length":194,"previous":"M21-GAP-01940","next":"M21-GAP-01942"},"M21-GAP-01942":{"line":5197,"offset":926293,"length":208,"previous":"M21-GAP-01941","next":"M21-GAP-01943"},"M21-GAP-01943":{"line":5198,"offset":926501,"length":208,"previous":"M21-GAP-01942","next":"M21-GAP-01944"},"M21-GAP-01944":{"line":5199,"offset":926709,"length":208,"previous":"M21-GAP-01943","next":"M21-GAP-01945"},"M21-GAP-01945":{"line":5200,"offset":926917,"length":197,"previous":"M21-GAP-01944","next":"M21-GAP-01946"},"M21-GAP-01946":{"line":5201,"offset":927114,"length":197,"previous":"M21-GAP-01945","next":"M21-GAP-01947"},"M21-GAP-01947":{"line":5202,"offset":927311,"length":197,"previous":"M21-GAP-01946","next":"M21-GAP-01948"},"M21-GAP-01948":{"line":5203,"offset":927508,"length":207,"previous":"M21-GAP-01947","next":"M21-GAP-01949"},"M21-GAP-01949":{"line":5204,"offset":927715,"length":207,"previous":"M21-GAP-01948","next":"M21-GAP-01950"},"M21-GAP-01950":{"line":5205,"offset":927922,"length":207,"previous":"M21-GAP-01949","next":"M21-GAP-01951"},"M21-GAP-01951":{"line":5206,"offset":928129,"length":196,"previous":"M21-GAP-01950","next":"M21-GAP-01952"},"M21-GAP-01952":{"line":5207,"offset":928325,"length":196,"previous":"M21-GAP-01951","next":"M21-GAP-01953"},"M21-GAP-01953":{"line":5208,"offset":928521,"length":196,"previous":"M21-GAP-01952","next":"M21-GAP-01954"},"M21-GAP-01954":{"line":5209,"offset":928717,"length":200,"previous":"M21-GAP-01953","next":"M21-GAP-01955"},"M21-GAP-01955":{"line":5210,"offset":928917,"length":200,"previous":"M21-GAP-01954","next":"M21-GAP-01956"},"M21-GAP-01956":{"line":5211,"offset":929117,"length":200,"previous":"M21-GAP-01955","next":"M21-GAP-01957"},"M21-GAP-01957":{"line":5212,"offset":929317,"length":200,"previous":"M21-GAP-01956","next":"M21-GAP-01958"},"M21-GAP-01958":{"line":5213,"offset":929517,"length":200,"previous":"M21-GAP-01957","next":"M21-GAP-01959"},"M21-GAP-01959":{"line":5214,"offset":929717,"length":200,"previous":"M21-GAP-01958","next":"M21-GAP-01960"},"M21-GAP-01960":{"line":5215,"offset":929917,"length":200,"previous":"M21-GAP-01959","next":"M21-GAP-01961"},"M21-GAP-01961":{"line":5216,"offset":930117,"length":200,"previous":"M21-GAP-01960","next":"M21-GAP-01962"},"M21-GAP-01962":{"line":5217,"offset":930317,"length":200,"previous":"M21-GAP-01961","next":"M21-GAP-01963"},"M21-GAP-01963":{"line":5218,"offset":930517,"length":189,"previous":"M21-GAP-01962","next":"M21-GAP-01964"},"M21-GAP-01964":{"line":5219,"offset":930706,"length":189,"previous":"M21-GAP-01963","next":"M21-GAP-01965"},"M21-GAP-01965":{"line":5220,"offset":930895,"length":189,"previous":"M21-GAP-01964","next":"M21-GAP-01966"},"M21-GAP-01966":{"line":5221,"offset":931084,"length":189,"previous":"M21-GAP-01965","next":"M21-GAP-01967"},"M21-GAP-01967":{"line":5222,"offset":931273,"length":189,"previous":"M21-GAP-01966","next":"M21-GAP-01968"},"M21-GAP-01968":{"line":5223,"offset":931462,"length":189,"previous":"M21-GAP-01967","next":"M21-GAP-01969"},"M21-GAP-01969":{"line":5224,"offset":931651,"length":189,"previous":"M21-GAP-01968","next":"M21-GAP-01970"},"M21-GAP-01970":{"line":5225,"offset":931840,"length":189,"previous":"M21-GAP-01969","next":"M21-GAP-01971"},"M21-GAP-01971":{"line":5226,"offset":932029,"length":189,"previous":"M21-GAP-01970","next":"M21-GAP-01972"},"M21-GAP-01972":{"line":5227,"offset":932218,"length":178,"previous":"M21-GAP-01971","next":"M21-GAP-01973"},"M21-GAP-01973":{"line":5228,"offset":932396,"length":178,"previous":"M21-GAP-01972","next":"M21-GAP-01974"},"M21-GAP-01974":{"line":5229,"offset":932574,"length":179,"previous":"M21-GAP-01973","next":"M21-GAP-01975"},"M21-GAP-01975":{"line":5230,"offset":932753,"length":179,"previous":"M21-GAP-01974","next":"M21-GAP-01976"},"M21-GAP-01976":{"line":5231,"offset":932932,"length":179,"previous":"M21-GAP-01975","next":"M21-GAP-01977"},"M21-GAP-01977":{"line":5232,"offset":933111,"length":179,"previous":"M21-GAP-01976","next":"M21-GAP-01978"},"M21-GAP-01978":{"line":5233,"offset":933290,"length":179,"previous":"M21-GAP-01977","next":"M21-GAP-01979"},"M21-GAP-01979":{"line":5234,"offset":933469,"length":179,"previous":"M21-GAP-01978","next":"M21-GAP-01980"},"M21-GAP-01980":{"line":5235,"offset":933648,"length":179,"previous":"M21-GAP-01979","next":"M21-GAP-01981"},"M21-GAP-01981":{"line":5236,"offset":933827,"length":179,"previous":"M21-GAP-01980","next":"M21-GAP-01982"},"M21-GAP-01982":{"line":5237,"offset":934006,"length":179,"previous":"M21-GAP-01981","next":"M21-GAP-01983"},"M21-GAP-01983":{"line":5238,"offset":934185,"length":179,"previous":"M21-GAP-01982","next":"M21-GAP-01984"},"M21-GAP-01984":{"line":5239,"offset":934364,"length":178,"previous":"M21-GAP-01983","next":"M21-GAP-01985"},"M21-GAP-01985":{"line":5240,"offset":934542,"length":179,"previous":"M21-GAP-01984","next":"M21-GAP-01986"},"M21-GAP-01986":{"line":5241,"offset":934721,"length":179,"previous":"M21-GAP-01985","next":"M21-GAP-01987"},"M21-GAP-01987":{"line":5242,"offset":934900,"length":179,"previous":"M21-GAP-01986","next":"M21-GAP-01988"},"M21-GAP-01988":{"line":5243,"offset":935079,"length":179,"previous":"M21-GAP-01987","next":"M21-GAP-01989"},"M21-GAP-01989":{"line":5244,"offset":935258,"length":179,"previous":"M21-GAP-01988","next":"M21-GAP-01990"},"M21-GAP-01990":{"line":5245,"offset":935437,"length":179,"previous":"M21-GAP-01989","next":"M21-GAP-01991"},"M21-GAP-01991":{"line":5246,"offset":935616,"length":179,"previous":"M21-GAP-01990","next":"M21-GAP-01992"},"M21-GAP-01992":{"line":5247,"offset":935795,"length":179,"previous":"M21-GAP-01991","next":"M21-GAP-01993"},"M21-GAP-01993":{"line":5248,"offset":935974,"length":179,"previous":"M21-GAP-01992","next":"M21-GAP-01994"},"M21-GAP-01994":{"line":5249,"offset":936153,"length":179,"previous":"M21-GAP-01993","next":"M21-GAP-01995"},"M21-GAP-01995":{"line":5250,"offset":936332,"length":178,"previous":"M21-GAP-01994","next":"M21-GAP-01996"},"M21-GAP-01996":{"line":5251,"offset":936510,"length":179,"previous":"M21-GAP-01995","next":"M21-GAP-01997"},"M21-GAP-01997":{"line":5252,"offset":936689,"length":179,"previous":"M21-GAP-01996","next":"M21-GAP-01998"},"M21-GAP-01998":{"line":5253,"offset":936868,"length":179,"previous":"M21-GAP-01997","next":"M21-GAP-01999"},"M21-GAP-01999":{"line":5254,"offset":937047,"length":179,"previous":"M21-GAP-01998","next":"M21-GAP-02000"},"M21-GAP-02000":{"line":5255,"offset":937226,"length":179,"previous":"M21-GAP-01999","next":"M21-GAP-02001"},"M21-GAP-02001":{"line":5256,"offset":937405,"length":179,"previous":"M21-GAP-02000","next":"M21-GAP-02002"},"M21-GAP-02002":{"line":5257,"offset":937584,"length":179,"previous":"M21-GAP-02001","next":"M21-GAP-02003"},"M21-GAP-02003":{"line":5258,"offset":937763,"length":179,"previous":"M21-GAP-02002","next":"M21-GAP-02004"},"M21-GAP-02004":{"line":5259,"offset":937942,"length":179,"previous":"M21-GAP-02003","next":"M21-GAP-02005"},"M21-GAP-02005":{"line":5260,"offset":938121,"length":179,"previous":"M21-GAP-02004","next":"M21-GAP-02006"},"M21-GAP-02006":{"line":5261,"offset":938300,"length":178,"previous":"M21-GAP-02005","next":"M21-GAP-02007"},"M21-GAP-02007":{"line":5262,"offset":938478,"length":179,"previous":"M21-GAP-02006","next":"M21-GAP-02008"},"M21-GAP-02008":{"line":5263,"offset":938657,"length":179,"previous":"M21-GAP-02007","next":"M21-GAP-02009"},"M21-GAP-02009":{"line":5264,"offset":938836,"length":179,"previous":"M21-GAP-02008","next":"M21-GAP-02010"},"M21-GAP-02010":{"line":5265,"offset":939015,"length":179,"previous":"M21-GAP-02009","next":"M21-GAP-02011"},"M21-GAP-02011":{"line":5266,"offset":939194,"length":179,"previous":"M21-GAP-02010","next":"M21-GAP-02012"},"M21-GAP-02012":{"line":5267,"offset":939373,"length":179,"previous":"M21-GAP-02011","next":"M21-GAP-02013"},"M21-GAP-02013":{"line":5268,"offset":939552,"length":179,"previous":"M21-GAP-02012","next":"M21-GAP-02014"},"M21-GAP-02014":{"line":5269,"offset":939731,"length":179,"previous":"M21-GAP-02013","next":"M21-GAP-02015"},"M21-GAP-02015":{"line":5270,"offset":939910,"length":179,"previous":"M21-GAP-02014","next":"M21-GAP-02016"},"M21-GAP-02016":{"line":5271,"offset":940089,"length":179,"previous":"M21-GAP-02015","next":"M21-GAP-02017"},"M21-GAP-02017":{"line":5272,"offset":940268,"length":178,"previous":"M21-GAP-02016","next":"M21-GAP-02018"},"M21-GAP-02018":{"line":5273,"offset":940446,"length":179,"previous":"M21-GAP-02017","next":"M21-GAP-02019"},"M21-GAP-02019":{"line":5274,"offset":940625,"length":179,"previous":"M21-GAP-02018","next":"M21-GAP-02020"},"M21-GAP-02020":{"line":5275,"offset":940804,"length":179,"previous":"M21-GAP-02019","next":"M21-GAP-02021"},"M21-GAP-02021":{"line":5276,"offset":940983,"length":179,"previous":"M21-GAP-02020","next":"M21-GAP-02022"},"M21-GAP-02022":{"line":5277,"offset":941162,"length":179,"previous":"M21-GAP-02021","next":"M21-GAP-02023"},"M21-GAP-02023":{"line":5278,"offset":941341,"length":179,"previous":"M21-GAP-02022","next":"M21-GAP-02024"},"M21-GAP-02024":{"line":5279,"offset":941520,"length":179,"previous":"M21-GAP-02023","next":"M21-GAP-02025"},"M21-GAP-02025":{"line":5280,"offset":941699,"length":179,"previous":"M21-GAP-02024","next":"M21-GAP-02026"},"M21-GAP-02026":{"line":5281,"offset":941878,"length":179,"previous":"M21-GAP-02025","next":"M21-GAP-02027"},"M21-GAP-02027":{"line":5282,"offset":942057,"length":178,"previous":"M21-GAP-02026","next":"M21-GAP-02028"},"M21-GAP-02028":{"line":5283,"offset":942235,"length":178,"previous":"M21-GAP-02027","next":"M21-GAP-02029"},"M21-GAP-02029":{"line":5284,"offset":942413,"length":178,"previous":"M21-GAP-02028","next":"M21-GAP-02030"},"M21-GAP-02030":{"line":5285,"offset":942591,"length":178,"previous":"M21-GAP-02029","next":"M21-GAP-02031"},"M21-GAP-02031":{"line":5286,"offset":942769,"length":183,"previous":"M21-GAP-02030","next":"M21-GAP-02032"},"M21-GAP-02032":{"line":5287,"offset":942952,"length":183,"previous":"M21-GAP-02031","next":"M21-GAP-02033"},"M21-GAP-02033":{"line":5288,"offset":943135,"length":183,"previous":"M21-GAP-02032","next":"M21-GAP-02034"},"M21-GAP-02034":{"line":5289,"offset":943318,"length":178,"previous":"M21-GAP-02033","next":"M21-GAP-02035"},"M21-GAP-02035":{"line":5290,"offset":943496,"length":178,"previous":"M21-GAP-02034","next":"M21-GAP-02036"},"M21-GAP-02036":{"line":5291,"offset":943674,"length":179,"previous":"M21-GAP-02035","next":"M21-GAP-02037"},"M21-GAP-02037":{"line":5292,"offset":943853,"length":180,"previous":"M21-GAP-02036","next":"M21-GAP-02038"},"M21-GAP-02038":{"line":5293,"offset":944033,"length":180,"previous":"M21-GAP-02037","next":"M21-GAP-02039"},"M21-GAP-02039":{"line":5294,"offset":944213,"length":180,"previous":"M21-GAP-02038","next":"M21-GAP-02040"},"M21-GAP-02040":{"line":5295,"offset":944393,"length":179,"previous":"M21-GAP-02039","next":"M21-GAP-02041"},"M21-GAP-02041":{"line":5296,"offset":944572,"length":179,"previous":"M21-GAP-02040","next":"M21-GAP-02042"},"M21-GAP-02042":{"line":5297,"offset":944751,"length":179,"previous":"M21-GAP-02041","next":"M21-GAP-02043"},"M21-GAP-02043":{"line":5298,"offset":944930,"length":179,"previous":"M21-GAP-02042","next":"M21-GAP-02044"},"M21-GAP-02044":{"line":5299,"offset":945109,"length":179,"previous":"M21-GAP-02043","next":"M21-GAP-02045"},"M21-GAP-02045":{"line":5300,"offset":945288,"length":179,"previous":"M21-GAP-02044","next":"M21-GAP-02046"},"M21-GAP-02046":{"line":5301,"offset":945467,"length":179,"previous":"M21-GAP-02045","next":"M21-GAP-02047"},"M21-GAP-02047":{"line":5302,"offset":945646,"length":179,"previous":"M21-GAP-02046","next":"M21-GAP-02048"},"M21-GAP-02048":{"line":5303,"offset":945825,"length":179,"previous":"M21-GAP-02047","next":"M21-GAP-02049"},"M21-GAP-02049":{"line":5304,"offset":946004,"length":178,"previous":"M21-GAP-02048","next":"M21-GAP-02050"},"M21-GAP-02050":{"line":5305,"offset":946182,"length":179,"previous":"M21-GAP-02049","next":"M21-GAP-02051"},"M21-GAP-02051":{"line":5306,"offset":946361,"length":179,"previous":"M21-GAP-02050","next":"M21-GAP-02052"},"M21-GAP-02052":{"line":5307,"offset":946540,"length":179,"previous":"M21-GAP-02051","next":"M21-GAP-02053"},"M21-GAP-02053":{"line":5308,"offset":946719,"length":179,"previous":"M21-GAP-02052","next":"M21-GAP-02054"},"M21-GAP-02054":{"line":5309,"offset":946898,"length":179,"previous":"M21-GAP-02053","next":"M21-GAP-02055"},"M21-GAP-02055":{"line":5310,"offset":947077,"length":179,"previous":"M21-GAP-02054","next":"M21-GAP-02056"},"M21-GAP-02056":{"line":5311,"offset":947256,"length":179,"previous":"M21-GAP-02055","next":"M21-GAP-02057"},"M21-GAP-02057":{"line":5312,"offset":947435,"length":179,"previous":"M21-GAP-02056","next":"M21-GAP-02058"},"M21-GAP-02058":{"line":5313,"offset":947614,"length":179,"previous":"M21-GAP-02057","next":"M21-GAP-02059"},"M21-GAP-02059":{"line":5314,"offset":947793,"length":179,"previous":"M21-GAP-02058","next":"M21-GAP-02060"},"M21-GAP-02060":{"line":5315,"offset":947972,"length":178,"previous":"M21-GAP-02059","next":"M21-GAP-02061"},"M21-GAP-02061":{"line":5316,"offset":948150,"length":179,"previous":"M21-GAP-02060","next":"M21-GAP-02062"},"M21-GAP-02062":{"line":5317,"offset":948329,"length":179,"previous":"M21-GAP-02061","next":"M21-GAP-02063"},"M21-GAP-02063":{"line":5318,"offset":948508,"length":179,"previous":"M21-GAP-02062","next":"M21-GAP-02064"},"M21-GAP-02064":{"line":5319,"offset":948687,"length":179,"previous":"M21-GAP-02063","next":"M21-GAP-02065"},"M21-GAP-02065":{"line":5320,"offset":948866,"length":179,"previous":"M21-GAP-02064","next":"M21-GAP-02066"},"M21-GAP-02066":{"line":5321,"offset":949045,"length":179,"previous":"M21-GAP-02065","next":"M21-GAP-02067"},"M21-GAP-02067":{"line":5322,"offset":949224,"length":179,"previous":"M21-GAP-02066","next":"M21-GAP-02068"},"M21-GAP-02068":{"line":5323,"offset":949403,"length":179,"previous":"M21-GAP-02067","next":"M21-GAP-02069"},"M21-GAP-02069":{"line":5324,"offset":949582,"length":179,"previous":"M21-GAP-02068","next":"M21-GAP-02070"},"M21-GAP-02070":{"line":5325,"offset":949761,"length":179,"previous":"M21-GAP-02069","next":"M21-GAP-02071"},"M21-GAP-02071":{"line":5326,"offset":949940,"length":178,"previous":"M21-GAP-02070","next":"M21-GAP-02072"},"M21-GAP-02072":{"line":5327,"offset":950118,"length":179,"previous":"M21-GAP-02071","next":"M21-GAP-02073"},"M21-GAP-02073":{"line":5328,"offset":950297,"length":179,"previous":"M21-GAP-02072","next":"M21-GAP-02074"},"M21-GAP-02074":{"line":5329,"offset":950476,"length":179,"previous":"M21-GAP-02073","next":"M21-GAP-02075"},"M21-GAP-02075":{"line":5330,"offset":950655,"length":179,"previous":"M21-GAP-02074","next":"M21-GAP-02076"},"M21-GAP-02076":{"line":5331,"offset":950834,"length":179,"previous":"M21-GAP-02075","next":"M21-GAP-02077"},"M21-GAP-02077":{"line":5332,"offset":951013,"length":179,"previous":"M21-GAP-02076","next":"M21-GAP-02078"},"M21-GAP-02078":{"line":5333,"offset":951192,"length":179,"previous":"M21-GAP-02077","next":"M21-GAP-02079"},"M21-GAP-02079":{"line":5334,"offset":951371,"length":179,"previous":"M21-GAP-02078","next":"M21-GAP-02080"},"M21-GAP-02080":{"line":5335,"offset":951550,"length":179,"previous":"M21-GAP-02079","next":"M21-GAP-02081"},"M21-GAP-02081":{"line":5336,"offset":951729,"length":179,"previous":"M21-GAP-02080","next":"M21-GAP-02082"},"M21-GAP-02082":{"line":5337,"offset":951908,"length":178,"previous":"M21-GAP-02081","next":"M21-GAP-02083"},"M21-GAP-02083":{"line":5338,"offset":952086,"length":179,"previous":"M21-GAP-02082","next":"M21-GAP-02084"},"M21-GAP-02084":{"line":5339,"offset":952265,"length":179,"previous":"M21-GAP-02083","next":"M21-GAP-02085"},"M21-GAP-02085":{"line":5340,"offset":952444,"length":179,"previous":"M21-GAP-02084","next":"M21-GAP-02086"},"M21-GAP-02086":{"line":5341,"offset":952623,"length":179,"previous":"M21-GAP-02085","next":"M21-GAP-02087"},"M21-GAP-02087":{"line":5342,"offset":952802,"length":179,"previous":"M21-GAP-02086","next":"M21-GAP-02088"},"M21-GAP-02088":{"line":5343,"offset":952981,"length":179,"previous":"M21-GAP-02087","next":"M21-GAP-02089"},"M21-GAP-02089":{"line":5344,"offset":953160,"length":179,"previous":"M21-GAP-02088","next":"M21-GAP-02090"},"M21-GAP-02090":{"line":5345,"offset":953339,"length":179,"previous":"M21-GAP-02089","next":"M21-GAP-02091"},"M21-GAP-02091":{"line":5346,"offset":953518,"length":179,"previous":"M21-GAP-02090","next":"M21-GAP-02092"},"M21-GAP-02092":{"line":5347,"offset":953697,"length":179,"previous":"M21-GAP-02091","next":"M21-GAP-02093"},"M21-GAP-02093":{"line":5348,"offset":953876,"length":178,"previous":"M21-GAP-02092","next":"M21-GAP-02094"},"M21-GAP-02094":{"line":5349,"offset":954054,"length":179,"previous":"M21-GAP-02093","next":"M21-GAP-02095"},"M21-GAP-02095":{"line":5350,"offset":954233,"length":179,"previous":"M21-GAP-02094","next":"M21-GAP-02096"},"M21-GAP-02096":{"line":5351,"offset":954412,"length":179,"previous":"M21-GAP-02095","next":"M21-GAP-02097"},"M21-GAP-02097":{"line":5352,"offset":954591,"length":179,"previous":"M21-GAP-02096","next":"M21-GAP-02098"},"M21-GAP-02098":{"line":5353,"offset":954770,"length":179,"previous":"M21-GAP-02097","next":"M21-GAP-02099"},"M21-GAP-02099":{"line":5354,"offset":954949,"length":179,"previous":"M21-GAP-02098","next":"M21-GAP-02100"},"M21-GAP-02100":{"line":5355,"offset":955128,"length":179,"previous":"M21-GAP-02099","next":"M21-GAP-02101"},"M21-GAP-02101":{"line":5356,"offset":955307,"length":179,"previous":"M21-GAP-02100","next":"M21-GAP-02102"},"M21-GAP-02102":{"line":5357,"offset":955486,"length":179,"previous":"M21-GAP-02101","next":"M21-GAP-02103"},"M21-GAP-02103":{"line":5358,"offset":955665,"length":179,"previous":"M21-GAP-02102","next":"M21-GAP-02104"},"M21-GAP-02104":{"line":5359,"offset":955844,"length":178,"previous":"M21-GAP-02103","next":"M21-GAP-02105"},"M21-GAP-02105":{"line":5360,"offset":956022,"length":179,"previous":"M21-GAP-02104","next":"M21-GAP-02106"},"M21-GAP-02106":{"line":5361,"offset":956201,"length":179,"previous":"M21-GAP-02105","next":"M21-GAP-02107"},"M21-GAP-02107":{"line":5362,"offset":956380,"length":179,"previous":"M21-GAP-02106","next":"M21-GAP-02108"},"M21-GAP-02108":{"line":5363,"offset":956559,"length":179,"previous":"M21-GAP-02107","next":"M21-GAP-02109"},"M21-GAP-02109":{"line":5364,"offset":956738,"length":179,"previous":"M21-GAP-02108","next":"M21-GAP-02110"},"M21-GAP-02110":{"line":5365,"offset":956917,"length":179,"previous":"M21-GAP-02109","next":"M21-GAP-02111"},"M21-GAP-02111":{"line":5366,"offset":957096,"length":179,"previous":"M21-GAP-02110","next":"M21-GAP-02112"},"M21-GAP-02112":{"line":5367,"offset":957275,"length":179,"previous":"M21-GAP-02111","next":"M21-GAP-02113"},"M21-GAP-02113":{"line":5368,"offset":957454,"length":179,"previous":"M21-GAP-02112","next":"M21-GAP-02114"},"M21-GAP-02114":{"line":5369,"offset":957633,"length":179,"previous":"M21-GAP-02113","next":"M21-GAP-02115"},"M21-GAP-02115":{"line":5370,"offset":957812,"length":178,"previous":"M21-GAP-02114","next":"M21-GAP-02116"},"M21-GAP-02116":{"line":5371,"offset":957990,"length":179,"previous":"M21-GAP-02115","next":"M21-GAP-02117"},"M21-GAP-02117":{"line":5372,"offset":958169,"length":179,"previous":"M21-GAP-02116","next":"M21-GAP-02118"},"M21-GAP-02118":{"line":5373,"offset":958348,"length":179,"previous":"M21-GAP-02117","next":"M21-GAP-02119"},"M21-GAP-02119":{"line":5374,"offset":958527,"length":179,"previous":"M21-GAP-02118","next":"M21-GAP-02120"},"M21-GAP-02120":{"line":5375,"offset":958706,"length":179,"previous":"M21-GAP-02119","next":"M21-GAP-02121"},"M21-GAP-02121":{"line":5376,"offset":958885,"length":179,"previous":"M21-GAP-02120","next":"M21-GAP-02122"},"M21-GAP-02122":{"line":5377,"offset":959064,"length":179,"previous":"M21-GAP-02121","next":"M21-GAP-02123"},"M21-GAP-02123":{"line":5378,"offset":959243,"length":179,"previous":"M21-GAP-02122","next":"M21-GAP-02124"},"M21-GAP-02124":{"line":5379,"offset":959422,"length":179,"previous":"M21-GAP-02123","next":"M21-GAP-02125"},"M21-GAP-02125":{"line":5380,"offset":959601,"length":179,"previous":"M21-GAP-02124","next":"M21-GAP-02126"},"M21-GAP-02126":{"line":5381,"offset":959780,"length":178,"previous":"M21-GAP-02125","next":"M21-GAP-02127"},"M21-GAP-02127":{"line":5382,"offset":959958,"length":179,"previous":"M21-GAP-02126","next":"M21-GAP-02128"},"M21-GAP-02128":{"line":5383,"offset":960137,"length":179,"previous":"M21-GAP-02127","next":"M21-GAP-02129"},"M21-GAP-02129":{"line":5384,"offset":960316,"length":179,"previous":"M21-GAP-02128","next":"M21-GAP-02130"},"M21-GAP-02130":{"line":5385,"offset":960495,"length":179,"previous":"M21-GAP-02129","next":"M21-GAP-02131"},"M21-GAP-02131":{"line":5386,"offset":960674,"length":179,"previous":"M21-GAP-02130","next":"M21-GAP-02132"},"M21-GAP-02132":{"line":5387,"offset":960853,"length":179,"previous":"M21-GAP-02131","next":"M21-GAP-02133"},"M21-GAP-02133":{"line":5388,"offset":961032,"length":179,"previous":"M21-GAP-02132","next":"M21-GAP-02134"},"M21-GAP-02134":{"line":5389,"offset":961211,"length":179,"previous":"M21-GAP-02133","next":"M21-GAP-02135"},"M21-GAP-02135":{"line":5390,"offset":961390,"length":179,"previous":"M21-GAP-02134","next":"M21-GAP-02136"},"M21-GAP-02136":{"line":5391,"offset":961569,"length":179,"previous":"M21-GAP-02135","next":"M21-GAP-02137"},"M21-GAP-02137":{"line":5392,"offset":961748,"length":178,"previous":"M21-GAP-02136","next":"M21-GAP-02138"},"M21-GAP-02138":{"line":5393,"offset":961926,"length":178,"previous":"M21-GAP-02137","next":"M21-GAP-02139"},"M21-GAP-02139":{"line":5394,"offset":962104,"length":179,"previous":"M21-GAP-02138","next":"M21-GAP-02140"},"M21-GAP-02140":{"line":5395,"offset":962283,"length":179,"previous":"M21-GAP-02139","next":"M21-GAP-02141"},"M21-GAP-02141":{"line":5396,"offset":962462,"length":179,"previous":"M21-GAP-02140","next":"M21-GAP-02142"},"M21-GAP-02142":{"line":5397,"offset":962641,"length":179,"previous":"M21-GAP-02141","next":"M21-GAP-02143"},"M21-GAP-02143":{"line":5398,"offset":962820,"length":179,"previous":"M21-GAP-02142","next":"M21-GAP-02144"},"M21-GAP-02144":{"line":5399,"offset":962999,"length":178,"previous":"M21-GAP-02143","next":"M21-GAP-02145"},"M21-GAP-02145":{"line":5400,"offset":963177,"length":178,"previous":"M21-GAP-02144","next":"M21-GAP-02146"},"M21-GAP-02146":{"line":5401,"offset":963355,"length":178,"previous":"M21-GAP-02145","next":"M21-GAP-02147"},"M21-GAP-02147":{"line":5402,"offset":963533,"length":178,"previous":"M21-GAP-02146","next":"M21-GAP-02148"},"M21-GAP-02148":{"line":5403,"offset":963711,"length":178,"previous":"M21-GAP-02147","next":"M21-GAP-02149"},"M21-GAP-02149":{"line":5404,"offset":963889,"length":178,"previous":"M21-GAP-02148","next":"M21-GAP-02150"},"M21-GAP-02150":{"line":5405,"offset":964067,"length":178,"previous":"M21-GAP-02149","next":"M21-GAP-02151"},"M21-GAP-02151":{"line":5406,"offset":964245,"length":178,"previous":"M21-GAP-02150","next":"M21-GAP-02152"},"M21-GAP-02152":{"line":5407,"offset":964423,"length":208,"previous":"M21-GAP-02151","next":"M21-GAP-02153"},"M21-GAP-02153":{"line":5408,"offset":964631,"length":208,"previous":"M21-GAP-02152","next":"M21-GAP-02154"},"M21-GAP-02154":{"line":5409,"offset":964839,"length":209,"previous":"M21-GAP-02153","next":"M21-GAP-02155"},"M21-GAP-02155":{"line":5410,"offset":965048,"length":209,"previous":"M21-GAP-02154","next":"M21-GAP-02156"},"M21-GAP-02156":{"line":5411,"offset":965257,"length":209,"previous":"M21-GAP-02155","next":"M21-GAP-02157"},"M21-GAP-02157":{"line":5412,"offset":965466,"length":209,"previous":"M21-GAP-02156","next":"M21-GAP-02158"},"M21-GAP-02158":{"line":5413,"offset":965675,"length":208,"previous":"M21-GAP-02157","next":"M21-GAP-02159"},"M21-GAP-02159":{"line":5414,"offset":965883,"length":208,"previous":"M21-GAP-02158","next":"M21-GAP-02160"},"M21-GAP-02160":{"line":5415,"offset":966091,"length":208,"previous":"M21-GAP-02159","next":"M21-GAP-02161"},"M21-GAP-02161":{"line":5416,"offset":966299,"length":208,"previous":"M21-GAP-02160","next":"M21-GAP-02162"},"M21-GAP-02162":{"line":5417,"offset":966507,"length":208,"previous":"M21-GAP-02161","next":"M21-GAP-02163"},"M21-GAP-02163":{"line":5418,"offset":966715,"length":208,"previous":"M21-GAP-02162","next":"M21-GAP-02164"},"M21-GAP-02164":{"line":5419,"offset":966923,"length":208,"previous":"M21-GAP-02163","next":"M21-GAP-02165"},"M21-GAP-02165":{"line":5420,"offset":967131,"length":208,"previous":"M21-GAP-02164","next":"M21-GAP-02166"},"M21-GAP-02166":{"line":5421,"offset":967339,"length":185,"previous":"M21-GAP-02165","next":"M21-GAP-02167"},"M21-GAP-02167":{"line":5422,"offset":967524,"length":206,"previous":"M21-GAP-02166","next":"M21-GAP-02168"},"M21-GAP-02168":{"line":5423,"offset":967730,"length":206,"previous":"M21-GAP-02167","next":"M21-GAP-02169"},"M21-GAP-02169":{"line":5424,"offset":967936,"length":207,"previous":"M21-GAP-02168","next":"M21-GAP-02170"},"M21-GAP-02170":{"line":5425,"offset":968143,"length":207,"previous":"M21-GAP-02169","next":"M21-GAP-02171"},"M21-GAP-02171":{"line":5426,"offset":968350,"length":207,"previous":"M21-GAP-02170","next":"M21-GAP-02172"},"M21-GAP-02172":{"line":5427,"offset":968557,"length":207,"previous":"M21-GAP-02171","next":"M21-GAP-02173"},"M21-GAP-02173":{"line":5428,"offset":968764,"length":207,"previous":"M21-GAP-02172","next":"M21-GAP-02174"},"M21-GAP-02174":{"line":5429,"offset":968971,"length":207,"previous":"M21-GAP-02173","next":"M21-GAP-02175"},"M21-GAP-02175":{"line":5430,"offset":969178,"length":206,"previous":"M21-GAP-02174","next":"M21-GAP-02176"},"M21-GAP-02176":{"line":5431,"offset":969384,"length":206,"previous":"M21-GAP-02175","next":"M21-GAP-02177"},"M21-GAP-02177":{"line":5432,"offset":969590,"length":206,"previous":"M21-GAP-02176","next":"M21-GAP-02178"},"M21-GAP-02178":{"line":5433,"offset":969796,"length":206,"previous":"M21-GAP-02177","next":"M21-GAP-02179"},"M21-GAP-02179":{"line":5434,"offset":970002,"length":206,"previous":"M21-GAP-02178","next":"M21-GAP-02180"},"M21-GAP-02180":{"line":5435,"offset":970208,"length":206,"previous":"M21-GAP-02179","next":"M21-GAP-02181"},"M21-GAP-02181":{"line":5436,"offset":970414,"length":206,"previous":"M21-GAP-02180","next":"M21-GAP-02182"},"M21-GAP-02182":{"line":5437,"offset":970620,"length":206,"previous":"M21-GAP-02181","next":"M21-GAP-02183"},"M21-GAP-02183":{"line":5438,"offset":970826,"length":175,"previous":"M21-GAP-02182","next":"M21-GAP-02184"},"M21-GAP-02184":{"line":5439,"offset":971001,"length":175,"previous":"M21-GAP-02183","next":"M21-GAP-02185"},"M21-GAP-02185":{"line":5440,"offset":971176,"length":176,"previous":"M21-GAP-02184","next":"M21-GAP-02186"},"M21-GAP-02186":{"line":5441,"offset":971352,"length":176,"previous":"M21-GAP-02185","next":"M21-GAP-02187"},"M21-GAP-02187":{"line":5442,"offset":971528,"length":176,"previous":"M21-GAP-02186","next":"M21-GAP-02188"},"M21-GAP-02188":{"line":5443,"offset":971704,"length":176,"previous":"M21-GAP-02187","next":"M21-GAP-02189"},"M21-GAP-02189":{"line":5444,"offset":971880,"length":176,"previous":"M21-GAP-02188","next":"M21-GAP-02190"},"M21-GAP-02190":{"line":5445,"offset":972056,"length":176,"previous":"M21-GAP-02189","next":"M21-GAP-02191"},"M21-GAP-02191":{"line":5446,"offset":972232,"length":176,"previous":"M21-GAP-02190","next":"M21-GAP-02192"},"M21-GAP-02192":{"line":5447,"offset":972408,"length":176,"previous":"M21-GAP-02191","next":"M21-GAP-02193"},"M21-GAP-02193":{"line":5448,"offset":972584,"length":176,"previous":"M21-GAP-02192","next":"M21-GAP-02194"},"M21-GAP-02194":{"line":5449,"offset":972760,"length":176,"previous":"M21-GAP-02193","next":"M21-GAP-02195"},"M21-GAP-02195":{"line":5450,"offset":972936,"length":175,"previous":"M21-GAP-02194","next":"M21-GAP-02196"},"M21-GAP-02196":{"line":5451,"offset":973111,"length":176,"previous":"M21-GAP-02195","next":"M21-GAP-02197"},"M21-GAP-02197":{"line":5452,"offset":973287,"length":176,"previous":"M21-GAP-02196","next":"M21-GAP-02198"},"M21-GAP-02198":{"line":5453,"offset":973463,"length":176,"previous":"M21-GAP-02197","next":"M21-GAP-02199"},"M21-GAP-02199":{"line":5454,"offset":973639,"length":176,"previous":"M21-GAP-02198","next":"M21-GAP-02200"},"M21-GAP-02200":{"line":5455,"offset":973815,"length":176,"previous":"M21-GAP-02199","next":"M21-GAP-02201"},"M21-GAP-02201":{"line":5456,"offset":973991,"length":176,"previous":"M21-GAP-02200","next":"M21-GAP-02202"},"M21-GAP-02202":{"line":5457,"offset":974167,"length":176,"previous":"M21-GAP-02201","next":"M21-GAP-02203"},"M21-GAP-02203":{"line":5458,"offset":974343,"length":176,"previous":"M21-GAP-02202","next":"M21-GAP-02204"},"M21-GAP-02204":{"line":5459,"offset":974519,"length":176,"previous":"M21-GAP-02203","next":"M21-GAP-02205"},"M21-GAP-02205":{"line":5460,"offset":974695,"length":176,"previous":"M21-GAP-02204","next":"M21-GAP-02206"},"M21-GAP-02206":{"line":5461,"offset":974871,"length":175,"previous":"M21-GAP-02205","next":"M21-GAP-02207"},"M21-GAP-02207":{"line":5462,"offset":975046,"length":175,"previous":"M21-GAP-02206","next":"M21-GAP-02208"},"M21-GAP-02208":{"line":5463,"offset":975221,"length":175,"previous":"M21-GAP-02207","next":"M21-GAP-02209"},"M21-GAP-02209":{"line":5464,"offset":975396,"length":175,"previous":"M21-GAP-02208","next":"M21-GAP-02210"},"M21-GAP-02210":{"line":5465,"offset":975571,"length":175,"previous":"M21-GAP-02209","next":"M21-GAP-02211"},"M21-GAP-02211":{"line":5466,"offset":975746,"length":175,"previous":"M21-GAP-02210","next":"M21-GAP-02212"},"M21-GAP-02212":{"line":5467,"offset":975921,"length":175,"previous":"M21-GAP-02211","next":"M21-GAP-02213"},"M21-GAP-02213":{"line":5468,"offset":976096,"length":185,"previous":"M21-GAP-02212","next":"M21-GAP-02214"},"M21-GAP-02214":{"line":5469,"offset":976281,"length":185,"previous":"M21-GAP-02213","next":"M21-GAP-02215"},"M21-GAP-02215":{"line":5470,"offset":976466,"length":185,"previous":"M21-GAP-02214","next":"M21-GAP-02216"},"M21-GAP-02216":{"line":5471,"offset":976651,"length":178,"previous":"M21-GAP-02215","next":"M21-GAP-02217"},"M21-GAP-02217":{"line":5472,"offset":976829,"length":178,"previous":"M21-GAP-02216","next":"M21-GAP-02218"},"M21-GAP-02218":{"line":5473,"offset":977007,"length":179,"previous":"M21-GAP-02217","next":"M21-GAP-02219"},"M21-GAP-02219":{"line":5474,"offset":977186,"length":179,"previous":"M21-GAP-02218","next":"M21-GAP-02220"},"M21-GAP-02220":{"line":5475,"offset":977365,"length":179,"previous":"M21-GAP-02219","next":"M21-GAP-02221"},"M21-GAP-02221":{"line":5476,"offset":977544,"length":179,"previous":"M21-GAP-02220","next":"M21-GAP-02222"},"M21-GAP-02222":{"line":5477,"offset":977723,"length":179,"previous":"M21-GAP-02221","next":"M21-GAP-02223"},"M21-GAP-02223":{"line":5478,"offset":977902,"length":179,"previous":"M21-GAP-02222","next":"M21-GAP-02224"},"M21-GAP-02224":{"line":5479,"offset":978081,"length":179,"previous":"M21-GAP-02223","next":"M21-GAP-02225"},"M21-GAP-02225":{"line":5480,"offset":978260,"length":179,"previous":"M21-GAP-02224","next":"M21-GAP-02226"},"M21-GAP-02226":{"line":5481,"offset":978439,"length":178,"previous":"M21-GAP-02225","next":"M21-GAP-02227"},"M21-GAP-02227":{"line":5482,"offset":978617,"length":178,"previous":"M21-GAP-02226","next":"M21-GAP-02228"},"M21-GAP-02228":{"line":5483,"offset":978795,"length":178,"previous":"M21-GAP-02227","next":"M21-GAP-02229"},"M21-GAP-02229":{"line":5484,"offset":978973,"length":178,"previous":"M21-GAP-02228","next":"M21-GAP-02230"},"M21-GAP-02230":{"line":5485,"offset":979151,"length":178,"previous":"M21-GAP-02229","next":"M21-GAP-02231"},"M21-GAP-02231":{"line":5486,"offset":979329,"length":178,"previous":"M21-GAP-02230","next":"M21-GAP-02232"},"M21-GAP-02232":{"line":5487,"offset":979507,"length":178,"previous":"M21-GAP-02231","next":"M21-GAP-02233"},"M21-GAP-02233":{"line":5488,"offset":979685,"length":178,"previous":"M21-GAP-02232","next":"M21-GAP-02234"},"M21-GAP-02234":{"line":5489,"offset":979863,"length":171,"previous":"M21-GAP-02233","next":"M21-GAP-02235"},"M21-GAP-02235":{"line":5490,"offset":980034,"length":171,"previous":"M21-GAP-02234","next":"M21-GAP-02236"},"M21-GAP-02236":{"line":5491,"offset":980205,"length":172,"previous":"M21-GAP-02235","next":"M21-GAP-02237"},"M21-GAP-02237":{"line":5492,"offset":980377,"length":172,"previous":"M21-GAP-02236","next":"M21-GAP-02238"},"M21-GAP-02238":{"line":5493,"offset":980549,"length":172,"previous":"M21-GAP-02237","next":"M21-GAP-02239"},"M21-GAP-02239":{"line":5494,"offset":980721,"length":172,"previous":"M21-GAP-02238","next":"M21-GAP-02240"},"M21-GAP-02240":{"line":5495,"offset":980893,"length":172,"previous":"M21-GAP-02239","next":"M21-GAP-02241"},"M21-GAP-02241":{"line":5496,"offset":981065,"length":172,"previous":"M21-GAP-02240","next":"M21-GAP-02242"},"M21-GAP-02242":{"line":5497,"offset":981237,"length":172,"previous":"M21-GAP-02241","next":"M21-GAP-02243"},"M21-GAP-02243":{"line":5498,"offset":981409,"length":172,"previous":"M21-GAP-02242","next":"M21-GAP-02244"},"M21-GAP-02244":{"line":5499,"offset":981581,"length":172,"previous":"M21-GAP-02243","next":"M21-GAP-02245"},"M21-GAP-02245":{"line":5500,"offset":981753,"length":172,"previous":"M21-GAP-02244","next":"M21-GAP-02246"},"M21-GAP-02246":{"line":5501,"offset":981925,"length":171,"previous":"M21-GAP-02245","next":"M21-GAP-02247"},"M21-GAP-02247":{"line":5502,"offset":982096,"length":172,"previous":"M21-GAP-02246","next":"M21-GAP-02248"},"M21-GAP-02248":{"line":5503,"offset":982268,"length":172,"previous":"M21-GAP-02247","next":"M21-GAP-02249"},"M21-GAP-02249":{"line":5504,"offset":982440,"length":172,"previous":"M21-GAP-02248","next":"M21-GAP-02250"},"M21-GAP-02250":{"line":5505,"offset":982612,"length":172,"previous":"M21-GAP-02249","next":"M21-GAP-02251"},"M21-GAP-02251":{"line":5506,"offset":982784,"length":172,"previous":"M21-GAP-02250","next":"M21-GAP-02252"},"M21-GAP-02252":{"line":5507,"offset":982956,"length":172,"previous":"M21-GAP-02251","next":"M21-GAP-02253"},"M21-GAP-02253":{"line":5508,"offset":983128,"length":172,"previous":"M21-GAP-02252","next":"M21-GAP-02254"},"M21-GAP-02254":{"line":5509,"offset":983300,"length":172,"previous":"M21-GAP-02253","next":"M21-GAP-02255"},"M21-GAP-02255":{"line":5510,"offset":983472,"length":172,"previous":"M21-GAP-02254","next":"M21-GAP-02256"},"M21-GAP-02256":{"line":5511,"offset":983644,"length":172,"previous":"M21-GAP-02255","next":"M21-GAP-02257"},"M21-GAP-02257":{"line":5512,"offset":983816,"length":171,"previous":"M21-GAP-02256","next":"M21-GAP-02258"},"M21-GAP-02258":{"line":5513,"offset":983987,"length":172,"previous":"M21-GAP-02257","next":"M21-GAP-02259"},"M21-GAP-02259":{"line":5514,"offset":984159,"length":172,"previous":"M21-GAP-02258","next":"M21-GAP-02260"},"M21-GAP-02260":{"line":5515,"offset":984331,"length":172,"previous":"M21-GAP-02259","next":"M21-GAP-02261"},"M21-GAP-02261":{"line":5516,"offset":984503,"length":172,"previous":"M21-GAP-02260","next":"M21-GAP-02262"},"M21-GAP-02262":{"line":5517,"offset":984675,"length":172,"previous":"M21-GAP-02261","next":"M21-GAP-02263"},"M21-GAP-02263":{"line":5518,"offset":984847,"length":172,"previous":"M21-GAP-02262","next":"M21-GAP-02264"},"M21-GAP-02264":{"line":5519,"offset":985019,"length":172,"previous":"M21-GAP-02263","next":"M21-GAP-02265"},"M21-GAP-02265":{"line":5520,"offset":985191,"length":172,"previous":"M21-GAP-02264","next":"M21-GAP-02266"},"M21-GAP-02266":{"line":5521,"offset":985363,"length":172,"previous":"M21-GAP-02265","next":"M21-GAP-02267"},"M21-GAP-02267":{"line":5522,"offset":985535,"length":172,"previous":"M21-GAP-02266","next":"M21-GAP-02268"},"M21-GAP-02268":{"line":5523,"offset":985707,"length":171,"previous":"M21-GAP-02267","next":"M21-GAP-02269"},"M21-GAP-02269":{"line":5524,"offset":985878,"length":172,"previous":"M21-GAP-02268","next":"M21-GAP-02270"},"M21-GAP-02270":{"line":5525,"offset":986050,"length":172,"previous":"M21-GAP-02269","next":"M21-GAP-02271"},"M21-GAP-02271":{"line":5526,"offset":986222,"length":172,"previous":"M21-GAP-02270","next":"M21-GAP-02272"},"M21-GAP-02272":{"line":5527,"offset":986394,"length":172,"previous":"M21-GAP-02271","next":"M21-GAP-02273"},"M21-GAP-02273":{"line":5528,"offset":986566,"length":172,"previous":"M21-GAP-02272","next":"M21-GAP-02274"},"M21-GAP-02274":{"line":5529,"offset":986738,"length":172,"previous":"M21-GAP-02273","next":"M21-GAP-02275"},"M21-GAP-02275":{"line":5530,"offset":986910,"length":172,"previous":"M21-GAP-02274","next":"M21-GAP-02276"},"M21-GAP-02276":{"line":5531,"offset":987082,"length":172,"previous":"M21-GAP-02275","next":"M21-GAP-02277"},"M21-GAP-02277":{"line":5532,"offset":987254,"length":172,"previous":"M21-GAP-02276","next":"M21-GAP-02278"},"M21-GAP-02278":{"line":5533,"offset":987426,"length":172,"previous":"M21-GAP-02277","next":"M21-GAP-02279"},"M21-GAP-02279":{"line":5534,"offset":987598,"length":171,"previous":"M21-GAP-02278","next":"M21-GAP-02280"},"M21-GAP-02280":{"line":5535,"offset":987769,"length":172,"previous":"M21-GAP-02279","next":"M21-GAP-02281"},"M21-GAP-02281":{"line":5536,"offset":987941,"length":172,"previous":"M21-GAP-02280","next":"M21-GAP-02282"},"M21-GAP-02282":{"line":5537,"offset":988113,"length":172,"previous":"M21-GAP-02281","next":"M21-GAP-02283"},"M21-GAP-02283":{"line":5538,"offset":988285,"length":171,"previous":"M21-GAP-02282","next":"M21-GAP-02284"},"M21-GAP-02284":{"line":5539,"offset":988456,"length":171,"previous":"M21-GAP-02283","next":"M21-GAP-02285"},"M21-GAP-02285":{"line":5540,"offset":988627,"length":171,"previous":"M21-GAP-02284","next":"M21-GAP-02286"},"M21-GAP-02286":{"line":5541,"offset":988798,"length":171,"previous":"M21-GAP-02285","next":"M21-GAP-02287"},"M21-GAP-02287":{"line":5542,"offset":988969,"length":184,"previous":"M21-GAP-02286","next":"M21-GAP-02288"},"M21-GAP-02288":{"line":5543,"offset":989153,"length":184,"previous":"M21-GAP-02287","next":"M21-GAP-02289"},"M21-GAP-02289":{"line":5544,"offset":989337,"length":184,"previous":"M21-GAP-02288","next":"M21-GAP-02290"},"M21-GAP-02290":{"line":5545,"offset":989521,"length":184,"previous":"M21-GAP-02289","next":"M21-GAP-02291"},"M21-GAP-02291":{"line":5546,"offset":989705,"length":197,"previous":"M21-GAP-02290","next":"M21-GAP-02292"},"M21-GAP-02292":{"line":5547,"offset":989902,"length":197,"previous":"M21-GAP-02291","next":"M21-GAP-02293"},"M21-GAP-02293":{"line":5548,"offset":990099,"length":195,"previous":"M21-GAP-02292","next":"M21-GAP-02294"},"M21-GAP-02294":{"line":5549,"offset":990294,"length":197,"previous":"M21-GAP-02293","next":"M21-GAP-02295"},"M21-GAP-02295":{"line":5550,"offset":990491,"length":197,"previous":"M21-GAP-02294","next":"M21-GAP-02296"},"M21-GAP-02296":{"line":5551,"offset":990688,"length":196,"previous":"M21-GAP-02295","next":"M21-GAP-02297"},"M21-GAP-02297":{"line":5552,"offset":990884,"length":212,"previous":"M21-GAP-02296","next":"M21-GAP-02298"},"M21-GAP-02298":{"line":5553,"offset":991096,"length":212,"previous":"M21-GAP-02297","next":"M21-GAP-02299"},"M21-GAP-02299":{"line":5554,"offset":991308,"length":212,"previous":"M21-GAP-02298","next":"M21-GAP-02300"},"M21-GAP-02300":{"line":5555,"offset":991520,"length":212,"previous":"M21-GAP-02299","next":"M21-GAP-02301"},"M21-GAP-02301":{"line":5556,"offset":991732,"length":212,"previous":"M21-GAP-02300","next":"M21-GAP-02302"},"M21-GAP-02302":{"line":5557,"offset":991944,"length":201,"previous":"M21-GAP-02301","next":"M21-GAP-02303"},"M21-GAP-02303":{"line":5558,"offset":992145,"length":201,"previous":"M21-GAP-02302","next":"M21-GAP-02304"},"M21-GAP-02304":{"line":5559,"offset":992346,"length":201,"previous":"M21-GAP-02303","next":"M21-GAP-02305"},"M21-GAP-02305":{"line":5560,"offset":992547,"length":201,"previous":"M21-GAP-02304","next":"M21-GAP-02306"},"M21-GAP-02306":{"line":5561,"offset":992748,"length":201,"previous":"M21-GAP-02305","next":"M21-GAP-02307"},"M21-GAP-02307":{"line":5562,"offset":992949,"length":215,"previous":"M21-GAP-02306","next":"M21-GAP-02308"},"M21-GAP-02308":{"line":5563,"offset":993164,"length":215,"previous":"M21-GAP-02307","next":"M21-GAP-02309"},"M21-GAP-02309":{"line":5564,"offset":993379,"length":215,"previous":"M21-GAP-02308","next":"M21-GAP-02310"},"M21-GAP-02310":{"line":5565,"offset":993594,"length":204,"previous":"M21-GAP-02309","next":"M21-GAP-02311"},"M21-GAP-02311":{"line":5566,"offset":993798,"length":204,"previous":"M21-GAP-02310","next":"M21-GAP-02312"},"M21-GAP-02312":{"line":5567,"offset":994002,"length":204,"previous":"M21-GAP-02311","next":"M21-GAP-02313"},"M21-GAP-02313":{"line":5568,"offset":994206,"length":214,"previous":"M21-GAP-02312","next":"M21-GAP-02314"},"M21-GAP-02314":{"line":5569,"offset":994420,"length":214,"previous":"M21-GAP-02313","next":"M21-GAP-02315"},"M21-GAP-02315":{"line":5570,"offset":994634,"length":214,"previous":"M21-GAP-02314","next":"M21-GAP-02316"},"M21-GAP-02316":{"line":5571,"offset":994848,"length":203,"previous":"M21-GAP-02315","next":"M21-GAP-02317"},"M21-GAP-02317":{"line":5572,"offset":995051,"length":203,"previous":"M21-GAP-02316","next":"M21-GAP-02318"},"M21-GAP-02318":{"line":5573,"offset":995254,"length":203,"previous":"M21-GAP-02317","next":"M21-GAP-02319"},"M21-GAP-02319":{"line":5574,"offset":995457,"length":207,"previous":"M21-GAP-02318","next":"M21-GAP-02320"},"M21-GAP-02320":{"line":5575,"offset":995664,"length":207,"previous":"M21-GAP-02319","next":"M21-GAP-02321"},"M21-GAP-02321":{"line":5576,"offset":995871,"length":207,"previous":"M21-GAP-02320","next":"M21-GAP-02322"},"M21-GAP-02322":{"line":5577,"offset":996078,"length":207,"previous":"M21-GAP-02321","next":"M21-GAP-02323"},"M21-GAP-02323":{"line":5578,"offset":996285,"length":207,"previous":"M21-GAP-02322","next":"M21-GAP-02324"},"M21-GAP-02324":{"line":5579,"offset":996492,"length":196,"previous":"M21-GAP-02323","next":"M21-GAP-02325"},"M21-GAP-02325":{"line":5580,"offset":996688,"length":196,"previous":"M21-GAP-02324","next":"M21-GAP-02326"},"M21-GAP-02326":{"line":5581,"offset":996884,"length":196,"previous":"M21-GAP-02325","next":"M21-GAP-02327"},"M21-GAP-02327":{"line":5582,"offset":997080,"length":196,"previous":"M21-GAP-02326","next":"M21-GAP-02328"},"M21-GAP-02328":{"line":5583,"offset":997276,"length":196,"previous":"M21-GAP-02327","next":"M21-GAP-02329"},"M21-GAP-02329":{"line":5584,"offset":997472,"length":184,"previous":"M21-GAP-02328","next":"M21-GAP-02330"},"M21-GAP-02330":{"line":5585,"offset":997656,"length":184,"previous":"M21-GAP-02329","next":"M21-GAP-02331"},"M21-GAP-02331":{"line":5586,"offset":997840,"length":185,"previous":"M21-GAP-02330","next":"M21-GAP-02332"},"M21-GAP-02332":{"line":5587,"offset":998025,"length":185,"previous":"M21-GAP-02331","next":"M21-GAP-02333"},"M21-GAP-02333":{"line":5588,"offset":998210,"length":185,"previous":"M21-GAP-02332","next":"M21-GAP-02334"},"M21-GAP-02334":{"line":5589,"offset":998395,"length":185,"previous":"M21-GAP-02333","next":"M21-GAP-02335"},"M21-GAP-02335":{"line":5590,"offset":998580,"length":185,"previous":"M21-GAP-02334","next":"M21-GAP-02336"},"M21-GAP-02336":{"line":5591,"offset":998765,"length":185,"previous":"M21-GAP-02335","next":"M21-GAP-02337"},"M21-GAP-02337":{"line":5592,"offset":998950,"length":185,"previous":"M21-GAP-02336","next":"M21-GAP-02338"},"M21-GAP-02338":{"line":5593,"offset":999135,"length":185,"previous":"M21-GAP-02337","next":"M21-GAP-02339"},"M21-GAP-02339":{"line":5594,"offset":999320,"length":185,"previous":"M21-GAP-02338","next":"M21-GAP-02340"},"M21-GAP-02340":{"line":5595,"offset":999505,"length":185,"previous":"M21-GAP-02339","next":"M21-GAP-02341"},"M21-GAP-02341":{"line":5596,"offset":999690,"length":184,"previous":"M21-GAP-02340","next":"M21-GAP-02342"},"M21-GAP-02342":{"line":5597,"offset":999874,"length":185,"previous":"M21-GAP-02341","next":"M21-GAP-02343"},"M21-GAP-02343":{"line":5598,"offset":1000059,"length":185,"previous":"M21-GAP-02342","next":"M21-GAP-02344"},"M21-GAP-02344":{"line":5599,"offset":1000244,"length":185,"previous":"M21-GAP-02343","next":"M21-GAP-02345"},"M21-GAP-02345":{"line":5600,"offset":1000429,"length":185,"previous":"M21-GAP-02344","next":"M21-GAP-02346"},"M21-GAP-02346":{"line":5601,"offset":1000614,"length":185,"previous":"M21-GAP-02345","next":"M21-GAP-02347"},"M21-GAP-02347":{"line":5602,"offset":1000799,"length":185,"previous":"M21-GAP-02346","next":"M21-GAP-02348"},"M21-GAP-02348":{"line":5603,"offset":1000984,"length":185,"previous":"M21-GAP-02347","next":"M21-GAP-02349"},"M21-GAP-02349":{"line":5604,"offset":1001169,"length":185,"previous":"M21-GAP-02348","next":"M21-GAP-02350"},"M21-GAP-02350":{"line":5605,"offset":1001354,"length":185,"previous":"M21-GAP-02349","next":"M21-GAP-02351"},"M21-GAP-02351":{"line":5606,"offset":1001539,"length":185,"previous":"M21-GAP-02350","next":"M21-GAP-02352"},"M21-GAP-02352":{"line":5607,"offset":1001724,"length":184,"previous":"M21-GAP-02351","next":"M21-GAP-02353"},"M21-GAP-02353":{"line":5608,"offset":1001908,"length":185,"previous":"M21-GAP-02352","next":"M21-GAP-02354"},"M21-GAP-02354":{"line":5609,"offset":1002093,"length":185,"previous":"M21-GAP-02353","next":"M21-GAP-02355"},"M21-GAP-02355":{"line":5610,"offset":1002278,"length":185,"previous":"M21-GAP-02354","next":"M21-GAP-02356"},"M21-GAP-02356":{"line":5611,"offset":1002463,"length":185,"previous":"M21-GAP-02355","next":"M21-GAP-02357"},"M21-GAP-02357":{"line":5612,"offset":1002648,"length":185,"previous":"M21-GAP-02356","next":"M21-GAP-02358"},"M21-GAP-02358":{"line":5613,"offset":1002833,"length":185,"previous":"M21-GAP-02357","next":"M21-GAP-02359"},"M21-GAP-02359":{"line":5614,"offset":1003018,"length":185,"previous":"M21-GAP-02358","next":"M21-GAP-02360"},"M21-GAP-02360":{"line":5615,"offset":1003203,"length":185,"previous":"M21-GAP-02359","next":"M21-GAP-02361"},"M21-GAP-02361":{"line":5616,"offset":1003388,"length":185,"previous":"M21-GAP-02360","next":"M21-GAP-02362"},"M21-GAP-02362":{"line":5617,"offset":1003573,"length":185,"previous":"M21-GAP-02361","next":"M21-GAP-02363"},"M21-GAP-02363":{"line":5618,"offset":1003758,"length":184,"previous":"M21-GAP-02362","next":"M21-GAP-02364"},"M21-GAP-02364":{"line":5619,"offset":1003942,"length":185,"previous":"M21-GAP-02363","next":"M21-GAP-02365"},"M21-GAP-02365":{"line":5620,"offset":1004127,"length":185,"previous":"M21-GAP-02364","next":"M21-GAP-02366"},"M21-GAP-02366":{"line":5621,"offset":1004312,"length":185,"previous":"M21-GAP-02365","next":"M21-GAP-02367"},"M21-GAP-02367":{"line":5622,"offset":1004497,"length":185,"previous":"M21-GAP-02366","next":"M21-GAP-02368"},"M21-GAP-02368":{"line":5623,"offset":1004682,"length":185,"previous":"M21-GAP-02367","next":"M21-GAP-02369"},"M21-GAP-02369":{"line":5624,"offset":1004867,"length":185,"previous":"M21-GAP-02368","next":"M21-GAP-02370"},"M21-GAP-02370":{"line":5625,"offset":1005052,"length":185,"previous":"M21-GAP-02369","next":"M21-GAP-02371"},"M21-GAP-02371":{"line":5626,"offset":1005237,"length":185,"previous":"M21-GAP-02370","next":"M21-GAP-02372"},"M21-GAP-02372":{"line":5627,"offset":1005422,"length":185,"previous":"M21-GAP-02371","next":"M21-GAP-02373"},"M21-GAP-02373":{"line":5628,"offset":1005607,"length":185,"previous":"M21-GAP-02372","next":"M21-GAP-02374"},"M21-GAP-02374":{"line":5629,"offset":1005792,"length":184,"previous":"M21-GAP-02373","next":"M21-GAP-02375"},"M21-GAP-02375":{"line":5630,"offset":1005976,"length":185,"previous":"M21-GAP-02374","next":"M21-GAP-02376"},"M21-GAP-02376":{"line":5631,"offset":1006161,"length":185,"previous":"M21-GAP-02375","next":"M21-GAP-02377"},"M21-GAP-02377":{"line":5632,"offset":1006346,"length":185,"previous":"M21-GAP-02376","next":"M21-GAP-02378"},"M21-GAP-02378":{"line":5633,"offset":1006531,"length":185,"previous":"M21-GAP-02377","next":"M21-GAP-02379"},"M21-GAP-02379":{"line":5634,"offset":1006716,"length":185,"previous":"M21-GAP-02378","next":"M21-GAP-02380"},"M21-GAP-02380":{"line":5635,"offset":1006901,"length":185,"previous":"M21-GAP-02379","next":"M21-GAP-02381"},"M21-GAP-02381":{"line":5636,"offset":1007086,"length":185,"previous":"M21-GAP-02380","next":"M21-GAP-02382"},"M21-GAP-02382":{"line":5637,"offset":1007271,"length":185,"previous":"M21-GAP-02381","next":"M21-GAP-02383"},"M21-GAP-02383":{"line":5638,"offset":1007456,"length":185,"previous":"M21-GAP-02382","next":"M21-GAP-02384"},"M21-GAP-02384":{"line":5639,"offset":1007641,"length":185,"previous":"M21-GAP-02383","next":"M21-GAP-02385"},"M21-GAP-02385":{"line":5640,"offset":1007826,"length":184,"previous":"M21-GAP-02384","next":"M21-GAP-02386"},"M21-GAP-02386":{"line":5641,"offset":1008010,"length":185,"previous":"M21-GAP-02385","next":"M21-GAP-02387"},"M21-GAP-02387":{"line":5642,"offset":1008195,"length":185,"previous":"M21-GAP-02386","next":"M21-GAP-02388"},"M21-GAP-02388":{"line":5643,"offset":1008380,"length":185,"previous":"M21-GAP-02387","next":"M21-GAP-02389"},"M21-GAP-02389":{"line":5644,"offset":1008565,"length":185,"previous":"M21-GAP-02388","next":"M21-GAP-02390"},"M21-GAP-02390":{"line":5645,"offset":1008750,"length":185,"previous":"M21-GAP-02389","next":"M21-GAP-02391"},"M21-GAP-02391":{"line":5646,"offset":1008935,"length":185,"previous":"M21-GAP-02390","next":"M21-GAP-02392"},"M21-GAP-02392":{"line":5647,"offset":1009120,"length":185,"previous":"M21-GAP-02391","next":"M21-GAP-02393"},"M21-GAP-02393":{"line":5648,"offset":1009305,"length":185,"previous":"M21-GAP-02392","next":"M21-GAP-02394"},"M21-GAP-02394":{"line":5649,"offset":1009490,"length":185,"previous":"M21-GAP-02393","next":"M21-GAP-02395"},"M21-GAP-02395":{"line":5650,"offset":1009675,"length":185,"previous":"M21-GAP-02394","next":"M21-GAP-02396"},"M21-GAP-02396":{"line":5651,"offset":1009860,"length":184,"previous":"M21-GAP-02395","next":"M21-GAP-02397"},"M21-GAP-02397":{"line":5652,"offset":1010044,"length":185,"previous":"M21-GAP-02396","next":"M21-GAP-02398"},"M21-GAP-02398":{"line":5653,"offset":1010229,"length":185,"previous":"M21-GAP-02397","next":"M21-GAP-02399"},"M21-GAP-02399":{"line":5654,"offset":1010414,"length":185,"previous":"M21-GAP-02398","next":"M21-GAP-02400"},"M21-GAP-02400":{"line":5655,"offset":1010599,"length":185,"previous":"M21-GAP-02399","next":"M21-GAP-02401"},"M21-GAP-02401":{"line":5656,"offset":1010784,"length":185,"previous":"M21-GAP-02400","next":"M21-GAP-02402"},"M21-GAP-02402":{"line":5657,"offset":1010969,"length":185,"previous":"M21-GAP-02401","next":"M21-GAP-02403"},"M21-GAP-02403":{"line":5658,"offset":1011154,"length":185,"previous":"M21-GAP-02402","next":"M21-GAP-02404"},"M21-GAP-02404":{"line":5659,"offset":1011339,"length":185,"previous":"M21-GAP-02403","next":"M21-GAP-02405"},"M21-GAP-02405":{"line":5660,"offset":1011524,"length":185,"previous":"M21-GAP-02404","next":"M21-GAP-02406"},"M21-GAP-02406":{"line":5661,"offset":1011709,"length":185,"previous":"M21-GAP-02405","next":"M21-GAP-02407"},"M21-GAP-02407":{"line":5662,"offset":1011894,"length":184,"previous":"M21-GAP-02406","next":"M21-GAP-02408"},"M21-GAP-02408":{"line":5663,"offset":1012078,"length":185,"previous":"M21-GAP-02407","next":"M21-GAP-02409"},"M21-GAP-02409":{"line":5664,"offset":1012263,"length":185,"previous":"M21-GAP-02408","next":"M21-GAP-02410"},"M21-GAP-02410":{"line":5665,"offset":1012448,"length":185,"previous":"M21-GAP-02409","next":"M21-GAP-02411"},"M21-GAP-02411":{"line":5666,"offset":1012633,"length":185,"previous":"M21-GAP-02410","next":"M21-GAP-02412"},"M21-GAP-02412":{"line":5667,"offset":1012818,"length":185,"previous":"M21-GAP-02411","next":"M21-GAP-02413"},"M21-GAP-02413":{"line":5668,"offset":1013003,"length":185,"previous":"M21-GAP-02412","next":"M21-GAP-02414"},"M21-GAP-02414":{"line":5669,"offset":1013188,"length":185,"previous":"M21-GAP-02413","next":"M21-GAP-02415"},"M21-GAP-02415":{"line":5670,"offset":1013373,"length":185,"previous":"M21-GAP-02414","next":"M21-GAP-02416"},"M21-GAP-02416":{"line":5671,"offset":1013558,"length":184,"previous":"M21-GAP-02415","next":"M21-GAP-02417"},"M21-GAP-02417":{"line":5672,"offset":1013742,"length":191,"previous":"M21-GAP-02416","next":"M21-GAP-02418"},"M21-GAP-02418":{"line":5673,"offset":1013933,"length":191,"previous":"M21-GAP-02417","next":"M21-GAP-02419"},"M21-GAP-02419":{"line":5674,"offset":1014124,"length":192,"previous":"M21-GAP-02418","next":"M21-GAP-02420"},"M21-GAP-02420":{"line":5675,"offset":1014316,"length":192,"previous":"M21-GAP-02419","next":"M21-GAP-02421"},"M21-GAP-02421":{"line":5676,"offset":1014508,"length":192,"previous":"M21-GAP-02420","next":"M21-GAP-02422"},"M21-GAP-02422":{"line":5677,"offset":1014700,"length":192,"previous":"M21-GAP-02421","next":"M21-GAP-02423"},"M21-GAP-02423":{"line":5678,"offset":1014892,"length":191,"previous":"M21-GAP-02422","next":"M21-GAP-02424"},"M21-GAP-02424":{"line":5679,"offset":1015083,"length":191,"previous":"M21-GAP-02423","next":"M21-GAP-02425"},"M21-GAP-02425":{"line":5680,"offset":1015274,"length":191,"previous":"M21-GAP-02424","next":"M21-GAP-02426"},"M21-GAP-02426":{"line":5681,"offset":1015465,"length":191,"previous":"M21-GAP-02425","next":"M21-GAP-02427"},"M21-GAP-02427":{"line":5682,"offset":1015656,"length":191,"previous":"M21-GAP-02426","next":"M21-GAP-02428"},"M21-GAP-02428":{"line":5683,"offset":1015847,"length":191,"previous":"M21-GAP-02427","next":"M21-GAP-02429"},"M21-GAP-02429":{"line":5684,"offset":1016038,"length":191,"previous":"M21-GAP-02428","next":"M21-GAP-02430"},"M21-GAP-02430":{"line":5685,"offset":1016229,"length":191,"previous":"M21-GAP-02429","next":"M21-GAP-02431"},"M21-GAP-02431":{"line":5686,"offset":1016420,"length":187,"previous":"M21-GAP-02430","next":"M21-GAP-02432"},"M21-GAP-02432":{"line":5687,"offset":1016607,"length":187,"previous":"M21-GAP-02431","next":"M21-GAP-02433"},"M21-GAP-02433":{"line":5688,"offset":1016794,"length":188,"previous":"M21-GAP-02432","next":"M21-GAP-02434"},"M21-GAP-02434":{"line":5689,"offset":1016982,"length":188,"previous":"M21-GAP-02433","next":"M21-GAP-02435"},"M21-GAP-02435":{"line":5690,"offset":1017170,"length":188,"previous":"M21-GAP-02434","next":"M21-GAP-02436"},"M21-GAP-02436":{"line":5691,"offset":1017358,"length":188,"previous":"M21-GAP-02435","next":"M21-GAP-02437"},"M21-GAP-02437":{"line":5692,"offset":1017546,"length":188,"previous":"M21-GAP-02436","next":"M21-GAP-02438"},"M21-GAP-02438":{"line":5693,"offset":1017734,"length":188,"previous":"M21-GAP-02437","next":"M21-GAP-02439"},"M21-GAP-02439":{"line":5694,"offset":1017922,"length":188,"previous":"M21-GAP-02438","next":"M21-GAP-02440"},"M21-GAP-02440":{"line":5695,"offset":1018110,"length":188,"previous":"M21-GAP-02439","next":"M21-GAP-02441"},"M21-GAP-02441":{"line":5696,"offset":1018298,"length":188,"previous":"M21-GAP-02440","next":"M21-GAP-02442"},"M21-GAP-02442":{"line":5697,"offset":1018486,"length":188,"previous":"M21-GAP-02441","next":"M21-GAP-02443"},"M21-GAP-02443":{"line":5698,"offset":1018674,"length":187,"previous":"M21-GAP-02442","next":"M21-GAP-02444"},"M21-GAP-02444":{"line":5699,"offset":1018861,"length":187,"previous":"M21-GAP-02443","next":"M21-GAP-02445"},"M21-GAP-02445":{"line":5700,"offset":1019048,"length":187,"previous":"M21-GAP-02444","next":"M21-GAP-02446"},"M21-GAP-02446":{"line":5701,"offset":1019235,"length":187,"previous":"M21-GAP-02445","next":"M21-GAP-02447"},"M21-GAP-02447":{"line":5702,"offset":1019422,"length":187,"previous":"M21-GAP-02446","next":"M21-GAP-02448"},"M21-GAP-02448":{"line":5703,"offset":1019609,"length":187,"previous":"M21-GAP-02447","next":"M21-GAP-02449"},"M21-GAP-02449":{"line":5704,"offset":1019796,"length":187,"previous":"M21-GAP-02448","next":"M21-GAP-02450"},"M21-GAP-02450":{"line":5705,"offset":1019983,"length":187,"previous":"M21-GAP-02449","next":"M21-GAP-02451"},"M21-GAP-02451":{"line":5706,"offset":1020170,"length":186,"previous":"M21-GAP-02450","next":"M21-GAP-02452"},"M21-GAP-02452":{"line":5707,"offset":1020356,"length":181,"previous":"M21-GAP-02451","next":"M21-GAP-02453"},"M21-GAP-02453":{"line":5708,"offset":1020537,"length":181,"previous":"M21-GAP-02452","next":"M21-GAP-02454"},"M21-GAP-02454":{"line":5709,"offset":1020718,"length":182,"previous":"M21-GAP-02453","next":"M21-GAP-02455"},"M21-GAP-02455":{"line":5710,"offset":1020900,"length":182,"previous":"M21-GAP-02454","next":"M21-GAP-02456"},"M21-GAP-02456":{"line":5711,"offset":1021082,"length":182,"previous":"M21-GAP-02455","next":"M21-GAP-02457"},"M21-GAP-02457":{"line":5712,"offset":1021264,"length":182,"previous":"M21-GAP-02456","next":"M21-GAP-02458"},"M21-GAP-02458":{"line":5713,"offset":1021446,"length":181,"previous":"M21-GAP-02457","next":"M21-GAP-02459"},"M21-GAP-02459":{"line":5714,"offset":1021627,"length":181,"previous":"M21-GAP-02458","next":"M21-GAP-02460"},"M21-GAP-02460":{"line":5715,"offset":1021808,"length":181,"previous":"M21-GAP-02459","next":"M21-GAP-02461"},"M21-GAP-02461":{"line":5716,"offset":1021989,"length":181,"previous":"M21-GAP-02460","next":"M21-GAP-02462"},"M21-GAP-02462":{"line":5717,"offset":1022170,"length":181,"previous":"M21-GAP-02461","next":"M21-GAP-02463"},"M21-GAP-02463":{"line":5718,"offset":1022351,"length":181,"previous":"M21-GAP-02462","next":"M21-GAP-02464"},"M21-GAP-02464":{"line":5719,"offset":1022532,"length":181,"previous":"M21-GAP-02463","next":"M21-GAP-02465"},"M21-GAP-02465":{"line":5720,"offset":1022713,"length":181,"previous":"M21-GAP-02464","next":"M21-GAP-02466"},"M21-GAP-02466":{"line":5721,"offset":1022894,"length":173,"previous":"M21-GAP-02465","next":"M21-GAP-02467"},"M21-GAP-02467":{"line":5722,"offset":1023067,"length":173,"previous":"M21-GAP-02466","next":"M21-GAP-02468"},"M21-GAP-02468":{"line":5723,"offset":1023240,"length":174,"previous":"M21-GAP-02467","next":"M21-GAP-02469"},"M21-GAP-02469":{"line":5724,"offset":1023414,"length":174,"previous":"M21-GAP-02468","next":"M21-GAP-02470"},"M21-GAP-02470":{"line":5725,"offset":1023588,"length":174,"previous":"M21-GAP-02469","next":"M21-GAP-02471"},"M21-GAP-02471":{"line":5726,"offset":1023762,"length":174,"previous":"M21-GAP-02470","next":"M21-GAP-02472"},"M21-GAP-02472":{"line":5727,"offset":1023936,"length":174,"previous":"M21-GAP-02471","next":"M21-GAP-02473"},"M21-GAP-02473":{"line":5728,"offset":1024110,"length":174,"previous":"M21-GAP-02472","next":"M21-GAP-02474"},"M21-GAP-02474":{"line":5729,"offset":1024284,"length":174,"previous":"M21-GAP-02473","next":"M21-GAP-02475"},"M21-GAP-02475":{"line":5730,"offset":1024458,"length":174,"previous":"M21-GAP-02474","next":"M21-GAP-02476"},"M21-GAP-02476":{"line":5731,"offset":1024632,"length":174,"previous":"M21-GAP-02475","next":"M21-GAP-02477"},"M21-GAP-02477":{"line":5732,"offset":1024806,"length":174,"previous":"M21-GAP-02476","next":"M21-GAP-02478"},"M21-GAP-02478":{"line":5733,"offset":1024980,"length":173,"previous":"M21-GAP-02477","next":"M21-GAP-02479"},"M21-GAP-02479":{"line":5734,"offset":1025153,"length":174,"previous":"M21-GAP-02478","next":"M21-GAP-02480"},"M21-GAP-02480":{"line":5735,"offset":1025327,"length":174,"previous":"M21-GAP-02479","next":"M21-GAP-02481"},"M21-GAP-02481":{"line":5736,"offset":1025501,"length":174,"previous":"M21-GAP-02480","next":"M21-GAP-02482"},"M21-GAP-02482":{"line":5737,"offset":1025675,"length":174,"previous":"M21-GAP-02481","next":"M21-GAP-02483"},"M21-GAP-02483":{"line":5738,"offset":1025849,"length":174,"previous":"M21-GAP-02482","next":"M21-GAP-02484"},"M21-GAP-02484":{"line":5739,"offset":1026023,"length":174,"previous":"M21-GAP-02483","next":"M21-GAP-02485"},"M21-GAP-02485":{"line":5740,"offset":1026197,"length":173,"previous":"M21-GAP-02484","next":"M21-GAP-02486"},"M21-GAP-02486":{"line":5741,"offset":1026370,"length":173,"previous":"M21-GAP-02485","next":"M21-GAP-02487"},"M21-GAP-02487":{"line":5742,"offset":1026543,"length":173,"previous":"M21-GAP-02486","next":"M21-GAP-02488"},"M21-GAP-02488":{"line":5743,"offset":1026716,"length":173,"previous":"M21-GAP-02487","next":"M21-GAP-02489"},"M21-GAP-02489":{"line":5744,"offset":1026889,"length":173,"previous":"M21-GAP-02488","next":"M21-GAP-02490"},"M21-GAP-02490":{"line":5745,"offset":1027062,"length":173,"previous":"M21-GAP-02489","next":"M21-GAP-02491"},"M21-GAP-02491":{"line":5746,"offset":1027235,"length":173,"previous":"M21-GAP-02490","next":"M21-GAP-02492"},"M21-GAP-02492":{"line":5747,"offset":1027408,"length":180,"previous":"M21-GAP-02491","next":"M21-GAP-02493"},"M21-GAP-02493":{"line":5748,"offset":1027588,"length":180,"previous":"M21-GAP-02492","next":"M21-GAP-02494"},"M21-GAP-02494":{"line":5749,"offset":1027768,"length":181,"previous":"M21-GAP-02493","next":"M21-GAP-02495"},"M21-GAP-02495":{"line":5750,"offset":1027949,"length":181,"previous":"M21-GAP-02494","next":"M21-GAP-02496"},"M21-GAP-02496":{"line":5751,"offset":1028130,"length":181,"previous":"M21-GAP-02495","next":"M21-GAP-02497"},"M21-GAP-02497":{"line":5752,"offset":1028311,"length":181,"previous":"M21-GAP-02496","next":"M21-GAP-02498"},"M21-GAP-02498":{"line":5753,"offset":1028492,"length":181,"previous":"M21-GAP-02497","next":"M21-GAP-02499"},"M21-GAP-02499":{"line":5754,"offset":1028673,"length":181,"previous":"M21-GAP-02498","next":"M21-GAP-02500"},"M21-GAP-02500":{"line":5755,"offset":1028854,"length":180,"previous":"M21-GAP-02499","next":"M21-GAP-02501"},"M21-GAP-02501":{"line":5756,"offset":1029034,"length":180,"previous":"M21-GAP-02500","next":"M21-GAP-02502"},"M21-GAP-02502":{"line":5757,"offset":1029214,"length":180,"previous":"M21-GAP-02501","next":"M21-GAP-02503"},"M21-GAP-02503":{"line":5758,"offset":1029394,"length":180,"previous":"M21-GAP-02502","next":"M21-GAP-02504"},"M21-GAP-02504":{"line":5759,"offset":1029574,"length":180,"previous":"M21-GAP-02503","next":"M21-GAP-02505"},"M21-GAP-02505":{"line":5760,"offset":1029754,"length":180,"previous":"M21-GAP-02504","next":"M21-GAP-02506"},"M21-GAP-02506":{"line":5761,"offset":1029934,"length":180,"previous":"M21-GAP-02505","next":"M21-GAP-02507"},"M21-GAP-02507":{"line":5762,"offset":1030114,"length":180,"previous":"M21-GAP-02506","next":"M21-GAP-02508"},"M21-GAP-02508":{"line":5763,"offset":1030294,"length":186,"previous":"M21-GAP-02507","next":"M21-GAP-02509"},"M21-GAP-02509":{"line":5764,"offset":1030480,"length":186,"previous":"M21-GAP-02508","next":"M21-GAP-02510"},"M21-GAP-02510":{"line":5765,"offset":1030666,"length":187,"previous":"M21-GAP-02509","next":"M21-GAP-02511"},"M21-GAP-02511":{"line":5766,"offset":1030853,"length":187,"previous":"M21-GAP-02510","next":"M21-GAP-02512"},"M21-GAP-02512":{"line":5767,"offset":1031040,"length":187,"previous":"M21-GAP-02511","next":"M21-GAP-02513"},"M21-GAP-02513":{"line":5768,"offset":1031227,"length":187,"previous":"M21-GAP-02512","next":"M21-GAP-02514"},"M21-GAP-02514":{"line":5769,"offset":1031414,"length":187,"previous":"M21-GAP-02513","next":"M21-GAP-02515"},"M21-GAP-02515":{"line":5770,"offset":1031601,"length":187,"previous":"M21-GAP-02514","next":"M21-GAP-02516"},"M21-GAP-02516":{"line":5771,"offset":1031788,"length":187,"previous":"M21-GAP-02515","next":"M21-GAP-02517"},"M21-GAP-02517":{"line":5772,"offset":1031975,"length":187,"previous":"M21-GAP-02516","next":"M21-GAP-02518"},"M21-GAP-02518":{"line":5773,"offset":1032162,"length":187,"previous":"M21-GAP-02517","next":"M21-GAP-02519"},"M21-GAP-02519":{"line":5774,"offset":1032349,"length":187,"previous":"M21-GAP-02518","next":"M21-GAP-02520"},"M21-GAP-02520":{"line":5775,"offset":1032536,"length":186,"previous":"M21-GAP-02519","next":"M21-GAP-02521"},"M21-GAP-02521":{"line":5776,"offset":1032722,"length":187,"previous":"M21-GAP-02520","next":"M21-GAP-02522"},"M21-GAP-02522":{"line":5777,"offset":1032909,"length":187,"previous":"M21-GAP-02521","next":"M21-GAP-02523"},"M21-GAP-02523":{"line":5778,"offset":1033096,"length":187,"previous":"M21-GAP-02522","next":"M21-GAP-02524"},"M21-GAP-02524":{"line":5779,"offset":1033283,"length":187,"previous":"M21-GAP-02523","next":"M21-GAP-02525"},"M21-GAP-02525":{"line":5780,"offset":1033470,"length":187,"previous":"M21-GAP-02524","next":"M21-GAP-02526"},"M21-GAP-02526":{"line":5781,"offset":1033657,"length":186,"previous":"M21-GAP-02525","next":"M21-GAP-02527"},"M21-GAP-02527":{"line":5782,"offset":1033843,"length":186,"previous":"M21-GAP-02526","next":"M21-GAP-02528"},"M21-GAP-02528":{"line":5783,"offset":1034029,"length":186,"previous":"M21-GAP-02527","next":"M21-GAP-02529"},"M21-GAP-02529":{"line":5784,"offset":1034215,"length":186,"previous":"M21-GAP-02528","next":"M21-GAP-02530"},"M21-GAP-02530":{"line":5785,"offset":1034401,"length":186,"previous":"M21-GAP-02529","next":"M21-GAP-02531"},"M21-GAP-02531":{"line":5786,"offset":1034587,"length":186,"previous":"M21-GAP-02530","next":"M21-GAP-02532"},"M21-GAP-02532":{"line":5787,"offset":1034773,"length":186,"previous":"M21-GAP-02531","next":"M21-GAP-02533"},"M21-GAP-02533":{"line":5788,"offset":1034959,"length":173,"previous":"M21-GAP-02532","next":"M21-GAP-02534"},"M21-GAP-02534":{"line":5789,"offset":1035132,"length":173,"previous":"M21-GAP-02533","next":"M21-GAP-02535"},"M21-GAP-02535":{"line":5790,"offset":1035305,"length":174,"previous":"M21-GAP-02534","next":"M21-GAP-02536"},"M21-GAP-02536":{"line":5791,"offset":1035479,"length":174,"previous":"M21-GAP-02535","next":"M21-GAP-02537"},"M21-GAP-02537":{"line":5792,"offset":1035653,"length":174,"previous":"M21-GAP-02536","next":"M21-GAP-02538"},"M21-GAP-02538":{"line":5793,"offset":1035827,"length":174,"previous":"M21-GAP-02537","next":"M21-GAP-02539"},"M21-GAP-02539":{"line":5794,"offset":1036001,"length":174,"previous":"M21-GAP-02538","next":"M21-GAP-02540"},"M21-GAP-02540":{"line":5795,"offset":1036175,"length":174,"previous":"M21-GAP-02539","next":"M21-GAP-02541"},"M21-GAP-02541":{"line":5796,"offset":1036349,"length":174,"previous":"M21-GAP-02540","next":"M21-GAP-02542"},"M21-GAP-02542":{"line":5797,"offset":1036523,"length":174,"previous":"M21-GAP-02541","next":"M21-GAP-02543"},"M21-GAP-02543":{"line":5798,"offset":1036697,"length":174,"previous":"M21-GAP-02542","next":"M21-GAP-02544"},"M21-GAP-02544":{"line":5799,"offset":1036871,"length":174,"previous":"M21-GAP-02543","next":"M21-GAP-02545"},"M21-GAP-02545":{"line":5800,"offset":1037045,"length":173,"previous":"M21-GAP-02544","next":"M21-GAP-02546"},"M21-GAP-02546":{"line":5801,"offset":1037218,"length":174,"previous":"M21-GAP-02545","next":"M21-GAP-02547"},"M21-GAP-02547":{"line":5802,"offset":1037392,"length":174,"previous":"M21-GAP-02546","next":"M21-GAP-02548"},"M21-GAP-02548":{"line":5803,"offset":1037566,"length":174,"previous":"M21-GAP-02547","next":"M21-GAP-02549"},"M21-GAP-02549":{"line":5804,"offset":1037740,"length":174,"previous":"M21-GAP-02548","next":"M21-GAP-02550"},"M21-GAP-02550":{"line":5805,"offset":1037914,"length":174,"previous":"M21-GAP-02549","next":"M21-GAP-02551"},"M21-GAP-02551":{"line":5806,"offset":1038088,"length":174,"previous":"M21-GAP-02550","next":"M21-GAP-02552"},"M21-GAP-02552":{"line":5807,"offset":1038262,"length":174,"previous":"M21-GAP-02551","next":"M21-GAP-02553"},"M21-GAP-02553":{"line":5808,"offset":1038436,"length":174,"previous":"M21-GAP-02552","next":"M21-GAP-02554"},"M21-GAP-02554":{"line":5809,"offset":1038610,"length":174,"previous":"M21-GAP-02553","next":"M21-GAP-02555"},"M21-GAP-02555":{"line":5810,"offset":1038784,"length":174,"previous":"M21-GAP-02554","next":"M21-GAP-02556"},"M21-GAP-02556":{"line":5811,"offset":1038958,"length":173,"previous":"M21-GAP-02555","next":"M21-GAP-02557"},"M21-GAP-02557":{"line":5812,"offset":1039131,"length":174,"previous":"M21-GAP-02556","next":"M21-GAP-02558"},"M21-GAP-02558":{"line":5813,"offset":1039305,"length":174,"previous":"M21-GAP-02557","next":"M21-GAP-02559"},"M21-GAP-02559":{"line":5814,"offset":1039479,"length":174,"previous":"M21-GAP-02558","next":"M21-GAP-02560"},"M21-GAP-02560":{"line":5815,"offset":1039653,"length":174,"previous":"M21-GAP-02559","next":"M21-GAP-02561"},"M21-GAP-02561":{"line":5816,"offset":1039827,"length":174,"previous":"M21-GAP-02560","next":"M21-GAP-02562"},"M21-GAP-02562":{"line":5817,"offset":1040001,"length":174,"previous":"M21-GAP-02561","next":"M21-GAP-02563"},"M21-GAP-02563":{"line":5818,"offset":1040175,"length":174,"previous":"M21-GAP-02562","next":"M21-GAP-02564"},"M21-GAP-02564":{"line":5819,"offset":1040349,"length":174,"previous":"M21-GAP-02563","next":"M21-GAP-02565"},"M21-GAP-02565":{"line":5820,"offset":1040523,"length":174,"previous":"M21-GAP-02564","next":"M21-GAP-02566"},"M21-GAP-02566":{"line":5821,"offset":1040697,"length":174,"previous":"M21-GAP-02565","next":"M21-GAP-02567"},"M21-GAP-02567":{"line":5822,"offset":1040871,"length":173,"previous":"M21-GAP-02566","next":"M21-GAP-02568"},"M21-GAP-02568":{"line":5823,"offset":1041044,"length":174,"previous":"M21-GAP-02567","next":"M21-GAP-02569"},"M21-GAP-02569":{"line":5824,"offset":1041218,"length":174,"previous":"M21-GAP-02568","next":"M21-GAP-02570"},"M21-GAP-02570":{"line":5825,"offset":1041392,"length":174,"previous":"M21-GAP-02569","next":"M21-GAP-02571"},"M21-GAP-02571":{"line":5826,"offset":1041566,"length":174,"previous":"M21-GAP-02570","next":"M21-GAP-02572"},"M21-GAP-02572":{"line":5827,"offset":1041740,"length":174,"previous":"M21-GAP-02571","next":"M21-GAP-02573"},"M21-GAP-02573":{"line":5828,"offset":1041914,"length":174,"previous":"M21-GAP-02572","next":"M21-GAP-02574"},"M21-GAP-02574":{"line":5829,"offset":1042088,"length":174,"previous":"M21-GAP-02573","next":"M21-GAP-02575"},"M21-GAP-02575":{"line":5830,"offset":1042262,"length":174,"previous":"M21-GAP-02574","next":"M21-GAP-02576"},"M21-GAP-02576":{"line":5831,"offset":1042436,"length":174,"previous":"M21-GAP-02575","next":"M21-GAP-02577"},"M21-GAP-02577":{"line":5832,"offset":1042610,"length":174,"previous":"M21-GAP-02576","next":"M21-GAP-02578"},"M21-GAP-02578":{"line":5833,"offset":1042784,"length":173,"previous":"M21-GAP-02577","next":"M21-GAP-02579"},"M21-GAP-02579":{"line":5834,"offset":1042957,"length":174,"previous":"M21-GAP-02578","next":"M21-GAP-02580"},"M21-GAP-02580":{"line":5835,"offset":1043131,"length":174,"previous":"M21-GAP-02579","next":"M21-GAP-02581"},"M21-GAP-02581":{"line":5836,"offset":1043305,"length":174,"previous":"M21-GAP-02580","next":"M21-GAP-02582"},"M21-GAP-02582":{"line":5837,"offset":1043479,"length":174,"previous":"M21-GAP-02581","next":"M21-GAP-02583"},"M21-GAP-02583":{"line":5838,"offset":1043653,"length":174,"previous":"M21-GAP-02582","next":"M21-GAP-02584"},"M21-GAP-02584":{"line":5839,"offset":1043827,"length":174,"previous":"M21-GAP-02583","next":"M21-GAP-02585"},"M21-GAP-02585":{"line":5840,"offset":1044001,"length":174,"previous":"M21-GAP-02584","next":"M21-GAP-02586"},"M21-GAP-02586":{"line":5841,"offset":1044175,"length":174,"previous":"M21-GAP-02585","next":"M21-GAP-02587"},"M21-GAP-02587":{"line":5842,"offset":1044349,"length":174,"previous":"M21-GAP-02586","next":"M21-GAP-02588"},"M21-GAP-02588":{"line":5843,"offset":1044523,"length":174,"previous":"M21-GAP-02587","next":"M21-GAP-02589"},"M21-GAP-02589":{"line":5844,"offset":1044697,"length":173,"previous":"M21-GAP-02588","next":"M21-GAP-02590"},"M21-GAP-02590":{"line":5845,"offset":1044870,"length":174,"previous":"M21-GAP-02589","next":"M21-GAP-02591"},"M21-GAP-02591":{"line":5846,"offset":1045044,"length":174,"previous":"M21-GAP-02590","next":"M21-GAP-02592"},"M21-GAP-02592":{"line":5847,"offset":1045218,"length":174,"previous":"M21-GAP-02591","next":"M21-GAP-02593"},"M21-GAP-02593":{"line":5848,"offset":1045392,"length":174,"previous":"M21-GAP-02592","next":"M21-GAP-02594"},"M21-GAP-02594":{"line":5849,"offset":1045566,"length":174,"previous":"M21-GAP-02593","next":"M21-GAP-02595"},"M21-GAP-02595":{"line":5850,"offset":1045740,"length":174,"previous":"M21-GAP-02594","next":"M21-GAP-02596"},"M21-GAP-02596":{"line":5851,"offset":1045914,"length":174,"previous":"M21-GAP-02595","next":"M21-GAP-02597"},"M21-GAP-02597":{"line":5852,"offset":1046088,"length":173,"previous":"M21-GAP-02596","next":"M21-GAP-02598"},"M21-GAP-02598":{"line":5853,"offset":1046261,"length":173,"previous":"M21-GAP-02597","next":"M21-GAP-02599"},"M21-GAP-02599":{"line":5854,"offset":1046434,"length":173,"previous":"M21-GAP-02598","next":"M21-GAP-02600"},"M21-GAP-02600":{"line":5855,"offset":1046607,"length":195,"previous":"M21-GAP-02599","next":"M21-GAP-02601"},"M21-GAP-02601":{"line":5856,"offset":1046802,"length":195,"previous":"M21-GAP-02600","next":"M21-GAP-02602"},"M21-GAP-02602":{"line":5857,"offset":1046997,"length":198,"previous":"M21-GAP-02601","next":"M21-GAP-02603"},"M21-GAP-02603":{"line":5858,"offset":1047195,"length":198,"previous":"M21-GAP-02602","next":"M21-GAP-02604"},"M21-GAP-02604":{"line":5859,"offset":1047393,"length":198,"previous":"M21-GAP-02603","next":"M21-GAP-02605"},"M21-GAP-02605":{"line":5860,"offset":1047591,"length":198,"previous":"M21-GAP-02604","next":"M21-GAP-02606"},"M21-GAP-02606":{"line":5861,"offset":1047789,"length":198,"previous":"M21-GAP-02605","next":"M21-GAP-02607"},"M21-GAP-02607":{"line":5862,"offset":1047987,"length":198,"previous":"M21-GAP-02606","next":"M21-GAP-02608"},"M21-GAP-02608":{"line":5863,"offset":1048185,"length":214,"previous":"M21-GAP-02607","next":"M21-GAP-02609"},"M21-GAP-02609":{"line":5864,"offset":1048399,"length":214,"previous":"M21-GAP-02608","next":"M21-GAP-02610"},"M21-GAP-02610":{"line":5865,"offset":1048613,"length":214,"previous":"M21-GAP-02609","next":"M21-GAP-02611"},"M21-GAP-02611":{"line":5866,"offset":1048827,"length":214,"previous":"M21-GAP-02610","next":"M21-GAP-02612"},"M21-GAP-02612":{"line":5867,"offset":1049041,"length":214,"previous":"M21-GAP-02611","next":"M21-GAP-02613"},"M21-GAP-02613":{"line":5868,"offset":1049255,"length":214,"previous":"M21-GAP-02612","next":"M21-GAP-02614"},"M21-GAP-02614":{"line":5869,"offset":1049469,"length":203,"previous":"M21-GAP-02613","next":"M21-GAP-02615"},"M21-GAP-02615":{"line":5870,"offset":1049672,"length":203,"previous":"M21-GAP-02614","next":"M21-GAP-02616"},"M21-GAP-02616":{"line":5871,"offset":1049875,"length":203,"previous":"M21-GAP-02615","next":"M21-GAP-02617"},"M21-GAP-02617":{"line":5872,"offset":1050078,"length":203,"previous":"M21-GAP-02616","next":"M21-GAP-02618"},"M21-GAP-02618":{"line":5873,"offset":1050281,"length":203,"previous":"M21-GAP-02617","next":"M21-GAP-02619"},"M21-GAP-02619":{"line":5874,"offset":1050484,"length":203,"previous":"M21-GAP-02618","next":"M21-GAP-02620"},"M21-GAP-02620":{"line":5875,"offset":1050687,"length":217,"previous":"M21-GAP-02619","next":"M21-GAP-02621"},"M21-GAP-02621":{"line":5876,"offset":1050904,"length":217,"previous":"M21-GAP-02620","next":"M21-GAP-02622"},"M21-GAP-02622":{"line":5877,"offset":1051121,"length":217,"previous":"M21-GAP-02621","next":"M21-GAP-02623"},"M21-GAP-02623":{"line":5878,"offset":1051338,"length":206,"previous":"M21-GAP-02622","next":"M21-GAP-02624"},"M21-GAP-02624":{"line":5879,"offset":1051544,"length":206,"previous":"M21-GAP-02623","next":"M21-GAP-02625"},"M21-GAP-02625":{"line":5880,"offset":1051750,"length":206,"previous":"M21-GAP-02624","next":"M21-GAP-02626"},"M21-GAP-02626":{"line":5881,"offset":1051956,"length":216,"previous":"M21-GAP-02625","next":"M21-GAP-02627"},"M21-GAP-02627":{"line":5882,"offset":1052172,"length":216,"previous":"M21-GAP-02626","next":"M21-GAP-02628"},"M21-GAP-02628":{"line":5883,"offset":1052388,"length":216,"previous":"M21-GAP-02627","next":"M21-GAP-02629"},"M21-GAP-02629":{"line":5884,"offset":1052604,"length":205,"previous":"M21-GAP-02628","next":"M21-GAP-02630"},"M21-GAP-02630":{"line":5885,"offset":1052809,"length":205,"previous":"M21-GAP-02629","next":"M21-GAP-02631"},"M21-GAP-02631":{"line":5886,"offset":1053014,"length":205,"previous":"M21-GAP-02630","next":"M21-GAP-02632"},"M21-GAP-02632":{"line":5887,"offset":1053219,"length":197,"previous":"M21-GAP-02631","next":"M21-GAP-02633"},"M21-GAP-02633":{"line":5888,"offset":1053416,"length":197,"previous":"M21-GAP-02632","next":"M21-GAP-02634"},"M21-GAP-02634":{"line":5889,"offset":1053613,"length":186,"previous":"M21-GAP-02633","next":"M21-GAP-02635"},"M21-GAP-02635":{"line":5890,"offset":1053799,"length":186,"previous":"M21-GAP-02634","next":"M21-GAP-02636"},"M21-GAP-02636":{"line":5891,"offset":1053985,"length":187,"previous":"M21-GAP-02635","next":"M21-GAP-02637"},"M21-GAP-02637":{"line":5892,"offset":1054172,"length":187,"previous":"M21-GAP-02636","next":"M21-GAP-02638"},"M21-GAP-02638":{"line":5893,"offset":1054359,"length":187,"previous":"M21-GAP-02637","next":"M21-GAP-02639"},"M21-GAP-02639":{"line":5894,"offset":1054546,"length":187,"previous":"M21-GAP-02638","next":"M21-GAP-02640"},"M21-GAP-02640":{"line":5895,"offset":1054733,"length":187,"previous":"M21-GAP-02639","next":"M21-GAP-02641"},"M21-GAP-02641":{"line":5896,"offset":1054920,"length":187,"previous":"M21-GAP-02640","next":"M21-GAP-02642"},"M21-GAP-02642":{"line":5897,"offset":1055107,"length":187,"previous":"M21-GAP-02641","next":"M21-GAP-02643"},"M21-GAP-02643":{"line":5898,"offset":1055294,"length":187,"previous":"M21-GAP-02642","next":"M21-GAP-02644"},"M21-GAP-02644":{"line":5899,"offset":1055481,"length":187,"previous":"M21-GAP-02643","next":"M21-GAP-02645"},"M21-GAP-02645":{"line":5900,"offset":1055668,"length":187,"previous":"M21-GAP-02644","next":"M21-GAP-02646"},"M21-GAP-02646":{"line":5901,"offset":1055855,"length":186,"previous":"M21-GAP-02645","next":"M21-GAP-02647"},"M21-GAP-02647":{"line":5902,"offset":1056041,"length":187,"previous":"M21-GAP-02646","next":"M21-GAP-02648"},"M21-GAP-02648":{"line":5903,"offset":1056228,"length":187,"previous":"M21-GAP-02647","next":"M21-GAP-02649"},"M21-GAP-02649":{"line":5904,"offset":1056415,"length":187,"previous":"M21-GAP-02648","next":"M21-GAP-02650"},"M21-GAP-02650":{"line":5905,"offset":1056602,"length":187,"previous":"M21-GAP-02649","next":"M21-GAP-02651"},"M21-GAP-02651":{"line":5906,"offset":1056789,"length":187,"previous":"M21-GAP-02650","next":"M21-GAP-02652"},"M21-GAP-02652":{"line":5907,"offset":1056976,"length":187,"previous":"M21-GAP-02651","next":"M21-GAP-02653"},"M21-GAP-02653":{"line":5908,"offset":1057163,"length":187,"previous":"M21-GAP-02652","next":"M21-GAP-02654"},"M21-GAP-02654":{"line":5909,"offset":1057350,"length":187,"previous":"M21-GAP-02653","next":"M21-GAP-02655"},"M21-GAP-02655":{"line":5910,"offset":1057537,"length":187,"previous":"M21-GAP-02654","next":"M21-GAP-02656"},"M21-GAP-02656":{"line":5911,"offset":1057724,"length":187,"previous":"M21-GAP-02655","next":"M21-GAP-02657"},"M21-GAP-02657":{"line":5912,"offset":1057911,"length":186,"previous":"M21-GAP-02656","next":"M21-GAP-02658"},"M21-GAP-02658":{"line":5913,"offset":1058097,"length":187,"previous":"M21-GAP-02657","next":"M21-GAP-02659"},"M21-GAP-02659":{"line":5914,"offset":1058284,"length":187,"previous":"M21-GAP-02658","next":"M21-GAP-02660"},"M21-GAP-02660":{"line":5915,"offset":1058471,"length":187,"previous":"M21-GAP-02659","next":"M21-GAP-02661"},"M21-GAP-02661":{"line":5916,"offset":1058658,"length":187,"previous":"M21-GAP-02660","next":"M21-GAP-02662"},"M21-GAP-02662":{"line":5917,"offset":1058845,"length":187,"previous":"M21-GAP-02661","next":"M21-GAP-02663"},"M21-GAP-02663":{"line":5918,"offset":1059032,"length":187,"previous":"M21-GAP-02662","next":"M21-GAP-02664"},"M21-GAP-02664":{"line":5919,"offset":1059219,"length":187,"previous":"M21-GAP-02663","next":"M21-GAP-02665"},"M21-GAP-02665":{"line":5920,"offset":1059406,"length":187,"previous":"M21-GAP-02664","next":"M21-GAP-02666"},"M21-GAP-02666":{"line":5921,"offset":1059593,"length":187,"previous":"M21-GAP-02665","next":"M21-GAP-02667"},"M21-GAP-02667":{"line":5922,"offset":1059780,"length":187,"previous":"M21-GAP-02666","next":"M21-GAP-02668"},"M21-GAP-02668":{"line":5923,"offset":1059967,"length":186,"previous":"M21-GAP-02667","next":"M21-GAP-02669"},"M21-GAP-02669":{"line":5924,"offset":1060153,"length":187,"previous":"M21-GAP-02668","next":"M21-GAP-02670"},"M21-GAP-02670":{"line":5925,"offset":1060340,"length":187,"previous":"M21-GAP-02669","next":"M21-GAP-02671"},"M21-GAP-02671":{"line":5926,"offset":1060527,"length":187,"previous":"M21-GAP-02670","next":"M21-GAP-02672"},"M21-GAP-02672":{"line":5927,"offset":1060714,"length":187,"previous":"M21-GAP-02671","next":"M21-GAP-02673"},"M21-GAP-02673":{"line":5928,"offset":1060901,"length":187,"previous":"M21-GAP-02672","next":"M21-GAP-02674"},"M21-GAP-02674":{"line":5929,"offset":1061088,"length":187,"previous":"M21-GAP-02673","next":"M21-GAP-02675"},"M21-GAP-02675":{"line":5930,"offset":1061275,"length":187,"previous":"M21-GAP-02674","next":"M21-GAP-02676"},"M21-GAP-02676":{"line":5931,"offset":1061462,"length":187,"previous":"M21-GAP-02675","next":"M21-GAP-02677"},"M21-GAP-02677":{"line":5932,"offset":1061649,"length":187,"previous":"M21-GAP-02676","next":"M21-GAP-02678"},"M21-GAP-02678":{"line":5933,"offset":1061836,"length":187,"previous":"M21-GAP-02677","next":"M21-GAP-02679"},"M21-GAP-02679":{"line":5934,"offset":1062023,"length":186,"previous":"M21-GAP-02678","next":"M21-GAP-02680"},"M21-GAP-02680":{"line":5935,"offset":1062209,"length":187,"previous":"M21-GAP-02679","next":"M21-GAP-02681"},"M21-GAP-02681":{"line":5936,"offset":1062396,"length":187,"previous":"M21-GAP-02680","next":"M21-GAP-02682"},"M21-GAP-02682":{"line":5937,"offset":1062583,"length":187,"previous":"M21-GAP-02681","next":"M21-GAP-02683"},"M21-GAP-02683":{"line":5938,"offset":1062770,"length":187,"previous":"M21-GAP-02682","next":"M21-GAP-02684"},"M21-GAP-02684":{"line":5939,"offset":1062957,"length":187,"previous":"M21-GAP-02683","next":"M21-GAP-02685"},"M21-GAP-02685":{"line":5940,"offset":1063144,"length":187,"previous":"M21-GAP-02684","next":"M21-GAP-02686"},"M21-GAP-02686":{"line":5941,"offset":1063331,"length":187,"previous":"M21-GAP-02685","next":"M21-GAP-02687"},"M21-GAP-02687":{"line":5942,"offset":1063518,"length":187,"previous":"M21-GAP-02686","next":"M21-GAP-02688"},"M21-GAP-02688":{"line":5943,"offset":1063705,"length":187,"previous":"M21-GAP-02687","next":"M21-GAP-02689"},"M21-GAP-02689":{"line":5944,"offset":1063892,"length":187,"previous":"M21-GAP-02688","next":"M21-GAP-02690"},"M21-GAP-02690":{"line":5945,"offset":1064079,"length":186,"previous":"M21-GAP-02689","next":"M21-GAP-02691"},"M21-GAP-02691":{"line":5946,"offset":1064265,"length":187,"previous":"M21-GAP-02690","next":"M21-GAP-02692"},"M21-GAP-02692":{"line":5947,"offset":1064452,"length":187,"previous":"M21-GAP-02691","next":"M21-GAP-02693"},"M21-GAP-02693":{"line":5948,"offset":1064639,"length":187,"previous":"M21-GAP-02692","next":"M21-GAP-02694"},"M21-GAP-02694":{"line":5949,"offset":1064826,"length":187,"previous":"M21-GAP-02693","next":"M21-GAP-02695"},"M21-GAP-02695":{"line":5950,"offset":1065013,"length":187,"previous":"M21-GAP-02694","next":"M21-GAP-02696"},"M21-GAP-02696":{"line":5951,"offset":1065200,"length":187,"previous":"M21-GAP-02695","next":"M21-GAP-02697"},"M21-GAP-02697":{"line":5952,"offset":1065387,"length":187,"previous":"M21-GAP-02696","next":"M21-GAP-02698"},"M21-GAP-02698":{"line":5953,"offset":1065574,"length":187,"previous":"M21-GAP-02697","next":"M21-GAP-02699"},"M21-GAP-02699":{"line":5954,"offset":1065761,"length":187,"previous":"M21-GAP-02698","next":"M21-GAP-02700"},"M21-GAP-02700":{"line":5955,"offset":1065948,"length":187,"previous":"M21-GAP-02699","next":"M21-GAP-02701"},"M21-GAP-02701":{"line":5956,"offset":1066135,"length":186,"previous":"M21-GAP-02700","next":"M21-GAP-02702"},"M21-GAP-02702":{"line":5957,"offset":1066321,"length":187,"previous":"M21-GAP-02701","next":"M21-GAP-02703"},"M21-GAP-02703":{"line":5958,"offset":1066508,"length":187,"previous":"M21-GAP-02702","next":"M21-GAP-02704"},"M21-GAP-02704":{"line":5959,"offset":1066695,"length":187,"previous":"M21-GAP-02703","next":"M21-GAP-02705"},"M21-GAP-02705":{"line":5960,"offset":1066882,"length":187,"previous":"M21-GAP-02704","next":"M21-GAP-02706"},"M21-GAP-02706":{"line":5961,"offset":1067069,"length":187,"previous":"M21-GAP-02705","next":"M21-GAP-02707"},"M21-GAP-02707":{"line":5962,"offset":1067256,"length":187,"previous":"M21-GAP-02706","next":"M21-GAP-02708"},"M21-GAP-02708":{"line":5963,"offset":1067443,"length":187,"previous":"M21-GAP-02707","next":"M21-GAP-02709"},"M21-GAP-02709":{"line":5964,"offset":1067630,"length":187,"previous":"M21-GAP-02708","next":"M21-GAP-02710"},"M21-GAP-02710":{"line":5965,"offset":1067817,"length":187,"previous":"M21-GAP-02709","next":"M21-GAP-02711"},"M21-GAP-02711":{"line":5966,"offset":1068004,"length":187,"previous":"M21-GAP-02710","next":"M21-GAP-02712"},"M21-GAP-02712":{"line":5967,"offset":1068191,"length":186,"previous":"M21-GAP-02711","next":"M21-GAP-02713"},"M21-GAP-02713":{"line":5968,"offset":1068377,"length":187,"previous":"M21-GAP-02712","next":"M21-GAP-02714"},"M21-GAP-02714":{"line":5969,"offset":1068564,"length":187,"previous":"M21-GAP-02713","next":"M21-GAP-02715"},"M21-GAP-02715":{"line":5970,"offset":1068751,"length":187,"previous":"M21-GAP-02714","next":"M21-GAP-02716"},"M21-GAP-02716":{"line":5971,"offset":1068938,"length":187,"previous":"M21-GAP-02715","next":"M21-GAP-02717"},"M21-GAP-02717":{"line":5972,"offset":1069125,"length":187,"previous":"M21-GAP-02716","next":"M21-GAP-02718"},"M21-GAP-02718":{"line":5973,"offset":1069312,"length":187,"previous":"M21-GAP-02717","next":"M21-GAP-02719"},"M21-GAP-02719":{"line":5974,"offset":1069499,"length":187,"previous":"M21-GAP-02718","next":"M21-GAP-02720"},"M21-GAP-02720":{"line":5975,"offset":1069686,"length":187,"previous":"M21-GAP-02719","next":"M21-GAP-02721"},"M21-GAP-02721":{"line":5976,"offset":1069873,"length":187,"previous":"M21-GAP-02720","next":"M21-GAP-02722"},"M21-GAP-02722":{"line":5977,"offset":1070060,"length":187,"previous":"M21-GAP-02721","next":"M21-GAP-02723"},"M21-GAP-02723":{"line":5978,"offset":1070247,"length":186,"previous":"M21-GAP-02722","next":"M21-GAP-02724"},"M21-GAP-02724":{"line":5979,"offset":1070433,"length":187,"previous":"M21-GAP-02723","next":"M21-GAP-02725"},"M21-GAP-02725":{"line":5980,"offset":1070620,"length":187,"previous":"M21-GAP-02724","next":"M21-GAP-02726"},"M21-GAP-02726":{"line":5981,"offset":1070807,"length":187,"previous":"M21-GAP-02725","next":"M21-GAP-02727"},"M21-GAP-02727":{"line":5982,"offset":1070994,"length":187,"previous":"M21-GAP-02726","next":"M21-GAP-02728"},"M21-GAP-02728":{"line":5983,"offset":1071181,"length":187,"previous":"M21-GAP-02727","next":"M21-GAP-02729"},"M21-GAP-02729":{"line":5984,"offset":1071368,"length":177,"previous":"M21-GAP-02728","next":"M21-GAP-02730"},"M21-GAP-02730":{"line":5985,"offset":1071545,"length":177,"previous":"M21-GAP-02729","next":"M21-GAP-02731"},"M21-GAP-02731":{"line":5986,"offset":1071722,"length":178,"previous":"M21-GAP-02730","next":"M21-GAP-02732"},"M21-GAP-02732":{"line":5987,"offset":1071900,"length":178,"previous":"M21-GAP-02731","next":"M21-GAP-02733"},"M21-GAP-02733":{"line":5988,"offset":1072078,"length":177,"previous":"M21-GAP-02732","next":"M21-GAP-02734"},"M21-GAP-02734":{"line":5989,"offset":1072255,"length":177,"previous":"M21-GAP-02733","next":"M21-GAP-02735"},"M21-GAP-02735":{"line":5990,"offset":1072432,"length":177,"previous":"M21-GAP-02734","next":"M21-GAP-02736"},"M21-GAP-02736":{"line":5991,"offset":1072609,"length":177,"previous":"M21-GAP-02735","next":"M21-GAP-02737"},"M21-GAP-02737":{"line":5992,"offset":1072786,"length":177,"previous":"M21-GAP-02736","next":"M21-GAP-02738"},"M21-GAP-02738":{"line":5993,"offset":1072963,"length":177,"previous":"M21-GAP-02737","next":"M21-GAP-02739"},"M21-GAP-02739":{"line":5994,"offset":1073140,"length":177,"previous":"M21-GAP-02738","next":"M21-GAP-02740"},"M21-GAP-02740":{"line":5995,"offset":1073317,"length":177,"previous":"M21-GAP-02739","next":"M21-GAP-02741"},"M21-GAP-02741":{"line":5996,"offset":1073494,"length":192,"previous":"M21-GAP-02740","next":"M21-GAP-02742"},"M21-GAP-02742":{"line":5997,"offset":1073686,"length":192,"previous":"M21-GAP-02741","next":"M21-GAP-02743"},"M21-GAP-02743":{"line":5998,"offset":1073878,"length":192,"previous":"M21-GAP-02742","next":"M21-GAP-02744"},"M21-GAP-02744":{"line":5999,"offset":1074070,"length":192,"previous":"M21-GAP-02743","next":"M21-GAP-02745"},"M21-GAP-02745":{"line":6000,"offset":1074262,"length":192,"previous":"M21-GAP-02744","next":"M21-GAP-02746"},"M21-GAP-02746":{"line":6001,"offset":1074454,"length":185,"previous":"M21-GAP-02745","next":"M21-GAP-02747"},"M21-GAP-02747":{"line":6002,"offset":1074639,"length":185,"previous":"M21-GAP-02746","next":"M21-GAP-02748"},"M21-GAP-02748":{"line":6003,"offset":1074824,"length":185,"previous":"M21-GAP-02747","next":"M21-GAP-02749"},"M21-GAP-02749":{"line":6004,"offset":1075009,"length":185,"previous":"M21-GAP-02748","next":"M21-GAP-02750"},"M21-GAP-02750":{"line":6005,"offset":1075194,"length":185,"previous":"M21-GAP-02749","next":"M21-GAP-02751"},"M21-GAP-02751":{"line":6006,"offset":1075379,"length":185,"previous":"M21-GAP-02750","next":"M21-GAP-02752"},"M21-GAP-02752":{"line":6007,"offset":1075564,"length":185,"previous":"M21-GAP-02751","next":"M21-GAP-02753"},"M21-GAP-02753":{"line":6008,"offset":1075749,"length":185,"previous":"M21-GAP-02752","next":"M21-GAP-02754"},"M21-GAP-02754":{"line":6009,"offset":1075934,"length":185,"previous":"M21-GAP-02753","next":"M21-GAP-02755"},"M21-GAP-02755":{"line":6010,"offset":1076119,"length":185,"previous":"M21-GAP-02754","next":"M21-GAP-02756"},"M21-GAP-02756":{"line":6011,"offset":1076304,"length":185,"previous":"M21-GAP-02755","next":"M21-GAP-02757"},"M21-GAP-02757":{"line":6012,"offset":1076489,"length":185,"previous":"M21-GAP-02756","next":"M21-GAP-02758"},"M21-GAP-02758":{"line":6013,"offset":1076674,"length":185,"previous":"M21-GAP-02757","next":"M21-GAP-02759"},"M21-GAP-02759":{"line":6014,"offset":1076859,"length":177,"previous":"M21-GAP-02758","next":"M21-GAP-02760"},"M21-GAP-02760":{"line":6015,"offset":1077036,"length":177,"previous":"M21-GAP-02759","next":"M21-GAP-02761"},"M21-GAP-02761":{"line":6016,"offset":1077213,"length":178,"previous":"M21-GAP-02760","next":"M21-GAP-02762"},"M21-GAP-02762":{"line":6017,"offset":1077391,"length":178,"previous":"M21-GAP-02761","next":"M21-GAP-02763"},"M21-GAP-02763":{"line":6018,"offset":1077569,"length":178,"previous":"M21-GAP-02762","next":"M21-GAP-02764"},"M21-GAP-02764":{"line":6019,"offset":1077747,"length":178,"previous":"M21-GAP-02763","next":"M21-GAP-02765"},"M21-GAP-02765":{"line":6020,"offset":1077925,"length":178,"previous":"M21-GAP-02764","next":"M21-GAP-02766"},"M21-GAP-02766":{"line":6021,"offset":1078103,"length":178,"previous":"M21-GAP-02765","next":"M21-GAP-02767"},"M21-GAP-02767":{"line":6022,"offset":1078281,"length":178,"previous":"M21-GAP-02766","next":"M21-GAP-02768"},"M21-GAP-02768":{"line":6023,"offset":1078459,"length":178,"previous":"M21-GAP-02767","next":"M21-GAP-02769"},"M21-GAP-02769":{"line":6024,"offset":1078637,"length":178,"previous":"M21-GAP-02768","next":"M21-GAP-02770"},"M21-GAP-02770":{"line":6025,"offset":1078815,"length":178,"previous":"M21-GAP-02769","next":"M21-GAP-02771"},"M21-GAP-02771":{"line":6026,"offset":1078993,"length":177,"previous":"M21-GAP-02770","next":"M21-GAP-02772"},"M21-GAP-02772":{"line":6027,"offset":1079170,"length":178,"previous":"M21-GAP-02771","next":"M21-GAP-02773"},"M21-GAP-02773":{"line":6028,"offset":1079348,"length":178,"previous":"M21-GAP-02772","next":"M21-GAP-02774"},"M21-GAP-02774":{"line":6029,"offset":1079526,"length":178,"previous":"M21-GAP-02773","next":"M21-GAP-02775"},"M21-GAP-02775":{"line":6030,"offset":1079704,"length":178,"previous":"M21-GAP-02774","next":"M21-GAP-02776"},"M21-GAP-02776":{"line":6031,"offset":1079882,"length":178,"previous":"M21-GAP-02775","next":"M21-GAP-02777"},"M21-GAP-02777":{"line":6032,"offset":1080060,"length":178,"previous":"M21-GAP-02776","next":"M21-GAP-02778"},"M21-GAP-02778":{"line":6033,"offset":1080238,"length":178,"previous":"M21-GAP-02777","next":"M21-GAP-02779"},"M21-GAP-02779":{"line":6034,"offset":1080416,"length":178,"previous":"M21-GAP-02778","next":"M21-GAP-02780"},"M21-GAP-02780":{"line":6035,"offset":1080594,"length":178,"previous":"M21-GAP-02779","next":"M21-GAP-02781"},"M21-GAP-02781":{"line":6036,"offset":1080772,"length":178,"previous":"M21-GAP-02780","next":"M21-GAP-02782"},"M21-GAP-02782":{"line":6037,"offset":1080950,"length":177,"previous":"M21-GAP-02781","next":"M21-GAP-02783"},"M21-GAP-02783":{"line":6038,"offset":1081127,"length":178,"previous":"M21-GAP-02782","next":"M21-GAP-02784"},"M21-GAP-02784":{"line":6039,"offset":1081305,"length":178,"previous":"M21-GAP-02783","next":"M21-GAP-02785"},"M21-GAP-02785":{"line":6040,"offset":1081483,"length":178,"previous":"M21-GAP-02784","next":"M21-GAP-02786"},"M21-GAP-02786":{"line":6041,"offset":1081661,"length":178,"previous":"M21-GAP-02785","next":"M21-GAP-02787"},"M21-GAP-02787":{"line":6042,"offset":1081839,"length":178,"previous":"M21-GAP-02786","next":"M21-GAP-02788"},"M21-GAP-02788":{"line":6043,"offset":1082017,"length":178,"previous":"M21-GAP-02787","next":"M21-GAP-02789"},"M21-GAP-02789":{"line":6044,"offset":1082195,"length":178,"previous":"M21-GAP-02788","next":"M21-GAP-02790"},"M21-GAP-02790":{"line":6045,"offset":1082373,"length":178,"previous":"M21-GAP-02789","next":"M21-GAP-02791"},"M21-GAP-02791":{"line":6046,"offset":1082551,"length":178,"previous":"M21-GAP-02790","next":"M21-GAP-02792"},"M21-GAP-02792":{"line":6047,"offset":1082729,"length":178,"previous":"M21-GAP-02791","next":"M21-GAP-02793"},"M21-GAP-02793":{"line":6048,"offset":1082907,"length":177,"previous":"M21-GAP-02792","next":"M21-GAP-02794"},"M21-GAP-02794":{"line":6049,"offset":1083084,"length":178,"previous":"M21-GAP-02793","next":"M21-GAP-02795"},"M21-GAP-02795":{"line":6050,"offset":1083262,"length":178,"previous":"M21-GAP-02794","next":"M21-GAP-02796"},"M21-GAP-02796":{"line":6051,"offset":1083440,"length":178,"previous":"M21-GAP-02795","next":"M21-GAP-02797"},"M21-GAP-02797":{"line":6052,"offset":1083618,"length":178,"previous":"M21-GAP-02796","next":"M21-GAP-02798"},"M21-GAP-02798":{"line":6053,"offset":1083796,"length":178,"previous":"M21-GAP-02797","next":"M21-GAP-02799"},"M21-GAP-02799":{"line":6054,"offset":1083974,"length":178,"previous":"M21-GAP-02798","next":"M21-GAP-02800"},"M21-GAP-02800":{"line":6055,"offset":1084152,"length":178,"previous":"M21-GAP-02799","next":"M21-GAP-02801"},"M21-GAP-02801":{"line":6056,"offset":1084330,"length":178,"previous":"M21-GAP-02800","next":"M21-GAP-02802"},"M21-GAP-02802":{"line":6057,"offset":1084508,"length":178,"previous":"M21-GAP-02801","next":"M21-GAP-02803"},"M21-GAP-02803":{"line":6058,"offset":1084686,"length":178,"previous":"M21-GAP-02802","next":"M21-GAP-02804"},"M21-GAP-02804":{"line":6059,"offset":1084864,"length":177,"previous":"M21-GAP-02803","next":"M21-GAP-02805"},"M21-GAP-02805":{"line":6060,"offset":1085041,"length":178,"previous":"M21-GAP-02804","next":"M21-GAP-02806"},"M21-GAP-02806":{"line":6061,"offset":1085219,"length":178,"previous":"M21-GAP-02805","next":"M21-GAP-02807"},"M21-GAP-02807":{"line":6062,"offset":1085397,"length":178,"previous":"M21-GAP-02806","next":"M21-GAP-02808"},"M21-GAP-02808":{"line":6063,"offset":1085575,"length":178,"previous":"M21-GAP-02807","next":"M21-GAP-02809"},"M21-GAP-02809":{"line":6064,"offset":1085753,"length":178,"previous":"M21-GAP-02808","next":"M21-GAP-02810"},"M21-GAP-02810":{"line":6065,"offset":1085931,"length":178,"previous":"M21-GAP-02809","next":"M21-GAP-02811"},"M21-GAP-02811":{"line":6066,"offset":1086109,"length":178,"previous":"M21-GAP-02810","next":"M21-GAP-02812"},"M21-GAP-02812":{"line":6067,"offset":1086287,"length":178,"previous":"M21-GAP-02811","next":"M21-GAP-02813"},"M21-GAP-02813":{"line":6068,"offset":1086465,"length":178,"previous":"M21-GAP-02812","next":"M21-GAP-02814"},"M21-GAP-02814":{"line":6069,"offset":1086643,"length":178,"previous":"M21-GAP-02813","next":"M21-GAP-02815"},"M21-GAP-02815":{"line":6070,"offset":1086821,"length":177,"previous":"M21-GAP-02814","next":"M21-GAP-02816"},"M21-GAP-02816":{"line":6071,"offset":1086998,"length":178,"previous":"M21-GAP-02815","next":"M21-GAP-02817"},"M21-GAP-02817":{"line":6072,"offset":1087176,"length":178,"previous":"M21-GAP-02816","next":"M21-GAP-02818"},"M21-GAP-02818":{"line":6073,"offset":1087354,"length":178,"previous":"M21-GAP-02817","next":"M21-GAP-02819"},"M21-GAP-02819":{"line":6074,"offset":1087532,"length":178,"previous":"M21-GAP-02818","next":"M21-GAP-02820"},"M21-GAP-02820":{"line":6075,"offset":1087710,"length":178,"previous":"M21-GAP-02819","next":"M21-GAP-02821"},"M21-GAP-02821":{"line":6076,"offset":1087888,"length":178,"previous":"M21-GAP-02820","next":"M21-GAP-02822"},"M21-GAP-02822":{"line":6077,"offset":1088066,"length":178,"previous":"M21-GAP-02821","next":"M21-GAP-02823"},"M21-GAP-02823":{"line":6078,"offset":1088244,"length":178,"previous":"M21-GAP-02822","next":"M21-GAP-02824"},"M21-GAP-02824":{"line":6079,"offset":1088422,"length":178,"previous":"M21-GAP-02823","next":"M21-GAP-02825"},"M21-GAP-02825":{"line":6080,"offset":1088600,"length":178,"previous":"M21-GAP-02824","next":"M21-GAP-02826"},"M21-GAP-02826":{"line":6081,"offset":1088778,"length":177,"previous":"M21-GAP-02825","next":"M21-GAP-02827"},"M21-GAP-02827":{"line":6082,"offset":1088955,"length":178,"previous":"M21-GAP-02826","next":"M21-GAP-02828"},"M21-GAP-02828":{"line":6083,"offset":1089133,"length":177,"previous":"M21-GAP-02827","next":"M21-GAP-02829"},"M21-GAP-02829":{"line":6084,"offset":1089310,"length":177,"previous":"M21-GAP-02828","next":"M21-GAP-02830"},"M21-GAP-02830":{"line":6085,"offset":1089487,"length":177,"previous":"M21-GAP-02829","next":"M21-GAP-02831"},"M21-GAP-02831":{"line":6086,"offset":1089664,"length":183,"previous":"M21-GAP-02830","next":"M21-GAP-02832"},"M21-GAP-02832":{"line":6087,"offset":1089847,"length":183,"previous":"M21-GAP-02831","next":"M21-GAP-02833"},"M21-GAP-02833":{"line":6088,"offset":1090030,"length":183,"previous":"M21-GAP-02832","next":"M21-GAP-02834"},"M21-GAP-02834":{"line":6089,"offset":1090213,"length":183,"previous":"M21-GAP-02833","next":"M21-GAP-02835"},"M21-GAP-02835":{"line":6090,"offset":1090396,"length":183,"previous":"M21-GAP-02834","next":"M21-GAP-02836"},"M21-GAP-02836":{"line":6091,"offset":1090579,"length":198,"previous":"M21-GAP-02835","next":"M21-GAP-02837"},"M21-GAP-02837":{"line":6092,"offset":1090777,"length":198,"previous":"M21-GAP-02836","next":"M21-GAP-02838"},"M21-GAP-02838":{"line":6093,"offset":1090975,"length":198,"previous":"M21-GAP-02837","next":"M21-GAP-02839"},"M21-GAP-02839":{"line":6094,"offset":1091173,"length":198,"previous":"M21-GAP-02838","next":"M21-GAP-02840"},"M21-GAP-02840":{"line":6095,"offset":1091371,"length":198,"previous":"M21-GAP-02839","next":"M21-GAP-02841"},"M21-GAP-02841":{"line":6096,"offset":1091569,"length":198,"previous":"M21-GAP-02840","next":"M21-GAP-02842"},"M21-GAP-02842":{"line":6097,"offset":1091767,"length":198,"previous":"M21-GAP-02841","next":"M21-GAP-02843"},"M21-GAP-02843":{"line":6098,"offset":1091965,"length":198,"previous":"M21-GAP-02842","next":"M21-GAP-02844"},"M21-GAP-02844":{"line":6099,"offset":1092163,"length":198,"previous":"M21-GAP-02843","next":"M21-GAP-02845"},"M21-GAP-02845":{"line":6100,"offset":1092361,"length":186,"previous":"M21-GAP-02844","next":"M21-GAP-02846"},"M21-GAP-02846":{"line":6101,"offset":1092547,"length":186,"previous":"M21-GAP-02845","next":"M21-GAP-02847"},"M21-GAP-02847":{"line":6102,"offset":1092733,"length":187,"previous":"M21-GAP-02846","next":"M21-GAP-02848"},"M21-GAP-02848":{"line":6103,"offset":1092920,"length":187,"previous":"M21-GAP-02847","next":"M21-GAP-02849"},"M21-GAP-02849":{"line":6104,"offset":1093107,"length":187,"previous":"M21-GAP-02848","next":"M21-GAP-02850"},"M21-GAP-02850":{"line":6105,"offset":1093294,"length":187,"previous":"M21-GAP-02849","next":"M21-GAP-02851"},"M21-GAP-02851":{"line":6106,"offset":1093481,"length":187,"previous":"M21-GAP-02850","next":"M21-GAP-02852"},"M21-GAP-02852":{"line":6107,"offset":1093668,"length":187,"previous":"M21-GAP-02851","next":"M21-GAP-02853"},"M21-GAP-02853":{"line":6108,"offset":1093855,"length":187,"previous":"M21-GAP-02852","next":"M21-GAP-02854"},"M21-GAP-02854":{"line":6109,"offset":1094042,"length":187,"previous":"M21-GAP-02853","next":"M21-GAP-02855"},"M21-GAP-02855":{"line":6110,"offset":1094229,"length":187,"previous":"M21-GAP-02854","next":"M21-GAP-02856"},"M21-GAP-02856":{"line":6111,"offset":1094416,"length":187,"previous":"M21-GAP-02855","next":"M21-GAP-02857"},"M21-GAP-02857":{"line":6112,"offset":1094603,"length":186,"previous":"M21-GAP-02856","next":"M21-GAP-02858"},"M21-GAP-02858":{"line":6113,"offset":1094789,"length":187,"previous":"M21-GAP-02857","next":"M21-GAP-02859"},"M21-GAP-02859":{"line":6114,"offset":1094976,"length":187,"previous":"M21-GAP-02858","next":"M21-GAP-02860"},"M21-GAP-02860":{"line":6115,"offset":1095163,"length":187,"previous":"M21-GAP-02859","next":"M21-GAP-02861"},"M21-GAP-02861":{"line":6116,"offset":1095350,"length":187,"previous":"M21-GAP-02860","next":"M21-GAP-02862"},"M21-GAP-02862":{"line":6117,"offset":1095537,"length":187,"previous":"M21-GAP-02861","next":"M21-GAP-02863"},"M21-GAP-02863":{"line":6118,"offset":1095724,"length":187,"previous":"M21-GAP-02862","next":"M21-GAP-02864"},"M21-GAP-02864":{"line":6119,"offset":1095911,"length":187,"previous":"M21-GAP-02863","next":"M21-GAP-02865"},"M21-GAP-02865":{"line":6120,"offset":1096098,"length":187,"previous":"M21-GAP-02864","next":"M21-GAP-02866"},"M21-GAP-02866":{"line":6121,"offset":1096285,"length":187,"previous":"M21-GAP-02865","next":"M21-GAP-02867"},"M21-GAP-02867":{"line":6122,"offset":1096472,"length":187,"previous":"M21-GAP-02866","next":"M21-GAP-02868"},"M21-GAP-02868":{"line":6123,"offset":1096659,"length":186,"previous":"M21-GAP-02867","next":"M21-GAP-02869"},"M21-GAP-02869":{"line":6124,"offset":1096845,"length":187,"previous":"M21-GAP-02868","next":"M21-GAP-02870"},"M21-GAP-02870":{"line":6125,"offset":1097032,"length":187,"previous":"M21-GAP-02869","next":"M21-GAP-02871"},"M21-GAP-02871":{"line":6126,"offset":1097219,"length":187,"previous":"M21-GAP-02870","next":"M21-GAP-02872"},"M21-GAP-02872":{"line":6127,"offset":1097406,"length":187,"previous":"M21-GAP-02871","next":"M21-GAP-02873"},"M21-GAP-02873":{"line":6128,"offset":1097593,"length":187,"previous":"M21-GAP-02872","next":"M21-GAP-02874"},"M21-GAP-02874":{"line":6129,"offset":1097780,"length":187,"previous":"M21-GAP-02873","next":"M21-GAP-02875"},"M21-GAP-02875":{"line":6130,"offset":1097967,"length":187,"previous":"M21-GAP-02874","next":"M21-GAP-02876"},"M21-GAP-02876":{"line":6131,"offset":1098154,"length":187,"previous":"M21-GAP-02875","next":"M21-GAP-02877"},"M21-GAP-02877":{"line":6132,"offset":1098341,"length":187,"previous":"M21-GAP-02876","next":"M21-GAP-02878"},"M21-GAP-02878":{"line":6133,"offset":1098528,"length":187,"previous":"M21-GAP-02877","next":"M21-GAP-02879"},"M21-GAP-02879":{"line":6134,"offset":1098715,"length":186,"previous":"M21-GAP-02878","next":"M21-GAP-02880"},"M21-GAP-02880":{"line":6135,"offset":1098901,"length":187,"previous":"M21-GAP-02879","next":"M21-GAP-02881"},"M21-GAP-02881":{"line":6136,"offset":1099088,"length":187,"previous":"M21-GAP-02880","next":"M21-GAP-02882"},"M21-GAP-02882":{"line":6137,"offset":1099275,"length":187,"previous":"M21-GAP-02881","next":"M21-GAP-02883"},"M21-GAP-02883":{"line":6138,"offset":1099462,"length":187,"previous":"M21-GAP-02882","next":"M21-GAP-02884"},"M21-GAP-02884":{"line":6139,"offset":1099649,"length":187,"previous":"M21-GAP-02883","next":"M21-GAP-02885"},"M21-GAP-02885":{"line":6140,"offset":1099836,"length":187,"previous":"M21-GAP-02884","next":"M21-GAP-02886"},"M21-GAP-02886":{"line":6141,"offset":1100023,"length":187,"previous":"M21-GAP-02885","next":"M21-GAP-02887"},"M21-GAP-02887":{"line":6142,"offset":1100210,"length":187,"previous":"M21-GAP-02886","next":"M21-GAP-02888"},"M21-GAP-02888":{"line":6143,"offset":1100397,"length":187,"previous":"M21-GAP-02887","next":"M21-GAP-02889"},"M21-GAP-02889":{"line":6144,"offset":1100584,"length":187,"previous":"M21-GAP-02888","next":"M21-GAP-02890"},"M21-GAP-02890":{"line":6145,"offset":1100771,"length":186,"previous":"M21-GAP-02889","next":"M21-GAP-02891"},"M21-GAP-02891":{"line":6146,"offset":1100957,"length":187,"previous":"M21-GAP-02890","next":"M21-GAP-02892"},"M21-GAP-02892":{"line":6147,"offset":1101144,"length":187,"previous":"M21-GAP-02891","next":"M21-GAP-02893"},"M21-GAP-02893":{"line":6148,"offset":1101331,"length":187,"previous":"M21-GAP-02892","next":"M21-GAP-02894"},"M21-GAP-02894":{"line":6149,"offset":1101518,"length":187,"previous":"M21-GAP-02893","next":"M21-GAP-02895"},"M21-GAP-02895":{"line":6150,"offset":1101705,"length":187,"previous":"M21-GAP-02894","next":"M21-GAP-02896"},"M21-GAP-02896":{"line":6151,"offset":1101892,"length":187,"previous":"M21-GAP-02895","next":"M21-GAP-02897"},"M21-GAP-02897":{"line":6152,"offset":1102079,"length":186,"previous":"M21-GAP-02896","next":"M21-GAP-02898"},"M21-GAP-02898":{"line":6153,"offset":1102265,"length":186,"previous":"M21-GAP-02897","next":"M21-GAP-02899"},"M21-GAP-02899":{"line":6154,"offset":1102451,"length":186,"previous":"M21-GAP-02898","next":"M21-GAP-02900"},"M21-GAP-02900":{"line":6155,"offset":1102637,"length":186,"previous":"M21-GAP-02899","next":"M21-GAP-02901"},"M21-GAP-02901":{"line":6156,"offset":1102823,"length":176,"previous":"M21-GAP-02900","next":"M21-GAP-02902"},"M21-GAP-02902":{"line":6157,"offset":1102999,"length":176,"previous":"M21-GAP-02901","next":"M21-GAP-02903"},"M21-GAP-02903":{"line":6158,"offset":1103175,"length":177,"previous":"M21-GAP-02902","next":"M21-GAP-02904"},"M21-GAP-02904":{"line":6159,"offset":1103352,"length":177,"previous":"M21-GAP-02903","next":"M21-GAP-02905"},"M21-GAP-02905":{"line":6160,"offset":1103529,"length":177,"previous":"M21-GAP-02904","next":"M21-GAP-02906"},"M21-GAP-02906":{"line":6161,"offset":1103706,"length":177,"previous":"M21-GAP-02905","next":"M21-GAP-02907"},"M21-GAP-02907":{"line":6162,"offset":1103883,"length":177,"previous":"M21-GAP-02906","next":"M21-GAP-02908"},"M21-GAP-02908":{"line":6163,"offset":1104060,"length":177,"previous":"M21-GAP-02907","next":"M21-GAP-02909"},"M21-GAP-02909":{"line":6164,"offset":1104237,"length":177,"previous":"M21-GAP-02908","next":"M21-GAP-02910"},"M21-GAP-02910":{"line":6165,"offset":1104414,"length":177,"previous":"M21-GAP-02909","next":"M21-GAP-02911"},"M21-GAP-02911":{"line":6166,"offset":1104591,"length":177,"previous":"M21-GAP-02910","next":"M21-GAP-02912"},"M21-GAP-02912":{"line":6167,"offset":1104768,"length":177,"previous":"M21-GAP-02911","next":"M21-GAP-02913"},"M21-GAP-02913":{"line":6168,"offset":1104945,"length":176,"previous":"M21-GAP-02912","next":"M21-GAP-02914"},"M21-GAP-02914":{"line":6169,"offset":1105121,"length":177,"previous":"M21-GAP-02913","next":"M21-GAP-02915"},"M21-GAP-02915":{"line":6170,"offset":1105298,"length":177,"previous":"M21-GAP-02914","next":"M21-GAP-02916"},"M21-GAP-02916":{"line":6171,"offset":1105475,"length":177,"previous":"M21-GAP-02915","next":"M21-GAP-02917"},"M21-GAP-02917":{"line":6172,"offset":1105652,"length":177,"previous":"M21-GAP-02916","next":"M21-GAP-02918"},"M21-GAP-02918":{"line":6173,"offset":1105829,"length":177,"previous":"M21-GAP-02917","next":"M21-GAP-02919"},"M21-GAP-02919":{"line":6174,"offset":1106006,"length":177,"previous":"M21-GAP-02918","next":"M21-GAP-02920"},"M21-GAP-02920":{"line":6175,"offset":1106183,"length":177,"previous":"M21-GAP-02919","next":"M21-GAP-02921"},"M21-GAP-02921":{"line":6176,"offset":1106360,"length":177,"previous":"M21-GAP-02920","next":"M21-GAP-02922"},"M21-GAP-02922":{"line":6177,"offset":1106537,"length":177,"previous":"M21-GAP-02921","next":"M21-GAP-02923"},"M21-GAP-02923":{"line":6178,"offset":1106714,"length":177,"previous":"M21-GAP-02922","next":"M21-GAP-02924"},"M21-GAP-02924":{"line":6179,"offset":1106891,"length":176,"previous":"M21-GAP-02923","next":"M21-GAP-02925"},"M21-GAP-02925":{"line":6180,"offset":1107067,"length":177,"previous":"M21-GAP-02924","next":"M21-GAP-02926"},"M21-GAP-02926":{"line":6181,"offset":1107244,"length":177,"previous":"M21-GAP-02925","next":"M21-GAP-02927"},"M21-GAP-02927":{"line":6182,"offset":1107421,"length":177,"previous":"M21-GAP-02926","next":"M21-GAP-02928"},"M21-GAP-02928":{"line":6183,"offset":1107598,"length":177,"previous":"M21-GAP-02927","next":"M21-GAP-02929"},"M21-GAP-02929":{"line":6184,"offset":1107775,"length":177,"previous":"M21-GAP-02928","next":"M21-GAP-02930"},"M21-GAP-02930":{"line":6185,"offset":1107952,"length":177,"previous":"M21-GAP-02929","next":"M21-GAP-02931"},"M21-GAP-02931":{"line":6186,"offset":1108129,"length":177,"previous":"M21-GAP-02930","next":"M21-GAP-02932"},"M21-GAP-02932":{"line":6187,"offset":1108306,"length":177,"previous":"M21-GAP-02931","next":"M21-GAP-02933"},"M21-GAP-02933":{"line":6188,"offset":1108483,"length":177,"previous":"M21-GAP-02932","next":"M21-GAP-02934"},"M21-GAP-02934":{"line":6189,"offset":1108660,"length":177,"previous":"M21-GAP-02933","next":"M21-GAP-02935"},"M21-GAP-02935":{"line":6190,"offset":1108837,"length":176,"previous":"M21-GAP-02934","next":"M21-GAP-02936"},"M21-GAP-02936":{"line":6191,"offset":1109013,"length":177,"previous":"M21-GAP-02935","next":"M21-GAP-02937"},"M21-GAP-02937":{"line":6192,"offset":1109190,"length":177,"previous":"M21-GAP-02936","next":"M21-GAP-02938"},"M21-GAP-02938":{"line":6193,"offset":1109367,"length":177,"previous":"M21-GAP-02937","next":"M21-GAP-02939"},"M21-GAP-02939":{"line":6194,"offset":1109544,"length":177,"previous":"M21-GAP-02938","next":"M21-GAP-02940"},"M21-GAP-02940":{"line":6195,"offset":1109721,"length":177,"previous":"M21-GAP-02939","next":"M21-GAP-02941"},"M21-GAP-02941":{"line":6196,"offset":1109898,"length":177,"previous":"M21-GAP-02940","next":"M21-GAP-02942"},"M21-GAP-02942":{"line":6197,"offset":1110075,"length":177,"previous":"M21-GAP-02941","next":"M21-GAP-02943"},"M21-GAP-02943":{"line":6198,"offset":1110252,"length":177,"previous":"M21-GAP-02942","next":"M21-GAP-02944"},"M21-GAP-02944":{"line":6199,"offset":1110429,"length":177,"previous":"M21-GAP-02943","next":"M21-GAP-02945"},"M21-GAP-02945":{"line":6200,"offset":1110606,"length":177,"previous":"M21-GAP-02944","next":"M21-GAP-02946"},"M21-GAP-02946":{"line":6201,"offset":1110783,"length":176,"previous":"M21-GAP-02945","next":"M21-GAP-02947"},"M21-GAP-02947":{"line":6202,"offset":1110959,"length":177,"previous":"M21-GAP-02946","next":"M21-GAP-02948"},"M21-GAP-02948":{"line":6203,"offset":1111136,"length":177,"previous":"M21-GAP-02947","next":"M21-GAP-02949"},"M21-GAP-02949":{"line":6204,"offset":1111313,"length":177,"previous":"M21-GAP-02948","next":"M21-GAP-02950"},"M21-GAP-02950":{"line":6205,"offset":1111490,"length":177,"previous":"M21-GAP-02949","next":"M21-GAP-02951"},"M21-GAP-02951":{"line":6206,"offset":1111667,"length":177,"previous":"M21-GAP-02950","next":"M21-GAP-02952"},"M21-GAP-02952":{"line":6207,"offset":1111844,"length":177,"previous":"M21-GAP-02951","next":"M21-GAP-02953"},"M21-GAP-02953":{"line":6208,"offset":1112021,"length":177,"previous":"M21-GAP-02952","next":"M21-GAP-02954"},"M21-GAP-02954":{"line":6209,"offset":1112198,"length":177,"previous":"M21-GAP-02953","next":"M21-GAP-02955"},"M21-GAP-02955":{"line":6210,"offset":1112375,"length":177,"previous":"M21-GAP-02954","next":"M21-GAP-02956"},"M21-GAP-02956":{"line":6211,"offset":1112552,"length":177,"previous":"M21-GAP-02955","next":"M21-GAP-02957"},"M21-GAP-02957":{"line":6212,"offset":1112729,"length":176,"previous":"M21-GAP-02956","next":"M21-GAP-02958"},"M21-GAP-02958":{"line":6213,"offset":1112905,"length":177,"previous":"M21-GAP-02957","next":"M21-GAP-02959"},"M21-GAP-02959":{"line":6214,"offset":1113082,"length":177,"previous":"M21-GAP-02958","next":"M21-GAP-02960"},"M21-GAP-02960":{"line":6215,"offset":1113259,"length":177,"previous":"M21-GAP-02959","next":"M21-GAP-02961"},"M21-GAP-02961":{"line":6216,"offset":1113436,"length":177,"previous":"M21-GAP-02960","next":"M21-GAP-02962"},"M21-GAP-02962":{"line":6217,"offset":1113613,"length":177,"previous":"M21-GAP-02961","next":"M21-GAP-02963"},"M21-GAP-02963":{"line":6218,"offset":1113790,"length":177,"previous":"M21-GAP-02962","next":"M21-GAP-02964"},"M21-GAP-02964":{"line":6219,"offset":1113967,"length":177,"previous":"M21-GAP-02963","next":"M21-GAP-02965"},"M21-GAP-02965":{"line":6220,"offset":1114144,"length":177,"previous":"M21-GAP-02964","next":"M21-GAP-02966"},"M21-GAP-02966":{"line":6221,"offset":1114321,"length":177,"previous":"M21-GAP-02965","next":"M21-GAP-02967"},"M21-GAP-02967":{"line":6222,"offset":1114498,"length":177,"previous":"M21-GAP-02966","next":"M21-GAP-02968"},"M21-GAP-02968":{"line":6223,"offset":1114675,"length":176,"previous":"M21-GAP-02967","next":"M21-GAP-02969"},"M21-GAP-02969":{"line":6224,"offset":1114851,"length":177,"previous":"M21-GAP-02968","next":"M21-GAP-02970"},"M21-GAP-02970":{"line":6225,"offset":1115028,"length":177,"previous":"M21-GAP-02969","next":"M21-GAP-02971"},"M21-GAP-02971":{"line":6226,"offset":1115205,"length":177,"previous":"M21-GAP-02970","next":"M21-GAP-02972"},"M21-GAP-02972":{"line":6227,"offset":1115382,"length":177,"previous":"M21-GAP-02971","next":"M21-GAP-02973"},"M21-GAP-02973":{"line":6228,"offset":1115559,"length":177,"previous":"M21-GAP-02972","next":"M21-GAP-02974"},"M21-GAP-02974":{"line":6229,"offset":1115736,"length":177,"previous":"M21-GAP-02973","next":"M21-GAP-02975"},"M21-GAP-02975":{"line":6230,"offset":1115913,"length":177,"previous":"M21-GAP-02974","next":"M21-GAP-02976"},"M21-GAP-02976":{"line":6231,"offset":1116090,"length":177,"previous":"M21-GAP-02975","next":"M21-GAP-02977"},"M21-GAP-02977":{"line":6232,"offset":1116267,"length":177,"previous":"M21-GAP-02976","next":"M21-GAP-02978"},"M21-GAP-02978":{"line":6233,"offset":1116444,"length":177,"previous":"M21-GAP-02977","next":"M21-GAP-02979"},"M21-GAP-02979":{"line":6234,"offset":1116621,"length":176,"previous":"M21-GAP-02978","next":"M21-GAP-02980"},"M21-GAP-02980":{"line":6235,"offset":1116797,"length":177,"previous":"M21-GAP-02979","next":"M21-GAP-02981"},"M21-GAP-02981":{"line":6236,"offset":1116974,"length":177,"previous":"M21-GAP-02980","next":"M21-GAP-02982"},"M21-GAP-02982":{"line":6237,"offset":1117151,"length":177,"previous":"M21-GAP-02981","next":"M21-GAP-02983"},"M21-GAP-02983":{"line":6238,"offset":1117328,"length":177,"previous":"M21-GAP-02982","next":"M21-GAP-02984"},"M21-GAP-02984":{"line":6239,"offset":1117505,"length":177,"previous":"M21-GAP-02983","next":"M21-GAP-02985"},"M21-GAP-02985":{"line":6240,"offset":1117682,"length":177,"previous":"M21-GAP-02984","next":"M21-GAP-02986"},"M21-GAP-02986":{"line":6241,"offset":1117859,"length":177,"previous":"M21-GAP-02985","next":"M21-GAP-02987"},"M21-GAP-02987":{"line":6242,"offset":1118036,"length":177,"previous":"M21-GAP-02986","next":"M21-GAP-02988"},"M21-GAP-02988":{"line":6243,"offset":1118213,"length":176,"previous":"M21-GAP-02987","next":"M21-GAP-02989"},"M21-GAP-02989":{"line":6244,"offset":1118389,"length":181,"previous":"M21-GAP-02988","next":"M21-GAP-02990"},"M21-GAP-02990":{"line":6245,"offset":1118570,"length":181,"previous":"M21-GAP-02989","next":"M21-GAP-02991"},"M21-GAP-02991":{"line":6246,"offset":1118751,"length":182,"previous":"M21-GAP-02990","next":"M21-GAP-02992"},"M21-GAP-02992":{"line":6247,"offset":1118933,"length":182,"previous":"M21-GAP-02991","next":"M21-GAP-02993"},"M21-GAP-02993":{"line":6248,"offset":1119115,"length":182,"previous":"M21-GAP-02992","next":"M21-GAP-02994"},"M21-GAP-02994":{"line":6249,"offset":1119297,"length":182,"previous":"M21-GAP-02993","next":"M21-GAP-02995"},"M21-GAP-02995":{"line":6250,"offset":1119479,"length":182,"previous":"M21-GAP-02994","next":"M21-GAP-02996"},"M21-GAP-02996":{"line":6251,"offset":1119661,"length":182,"previous":"M21-GAP-02995","next":"M21-GAP-02997"},"M21-GAP-02997":{"line":6252,"offset":1119843,"length":182,"previous":"M21-GAP-02996","next":"M21-GAP-02998"},"M21-GAP-02998":{"line":6253,"offset":1120025,"length":182,"previous":"M21-GAP-02997","next":"M21-GAP-02999"},"M21-GAP-02999":{"line":6254,"offset":1120207,"length":182,"previous":"M21-GAP-02998","next":"M21-GAP-03000"},"M21-GAP-03000":{"line":6255,"offset":1120389,"length":182,"previous":"M21-GAP-02999","next":"M21-GAP-03001"},"M21-GAP-03001":{"line":6256,"offset":1120571,"length":181,"previous":"M21-GAP-03000","next":"M21-GAP-03002"},"M21-GAP-03002":{"line":6257,"offset":1120752,"length":182,"previous":"M21-GAP-03001","next":"M21-GAP-03003"},"M21-GAP-03003":{"line":6258,"offset":1120934,"length":182,"previous":"M21-GAP-03002","next":"M21-GAP-03004"},"M21-GAP-03004":{"line":6259,"offset":1121116,"length":182,"previous":"M21-GAP-03003","next":"M21-GAP-03005"},"M21-GAP-03005":{"line":6260,"offset":1121298,"length":182,"previous":"M21-GAP-03004","next":"M21-GAP-03006"},"M21-GAP-03006":{"line":6261,"offset":1121480,"length":182,"previous":"M21-GAP-03005","next":"M21-GAP-03007"},"M21-GAP-03007":{"line":6262,"offset":1121662,"length":182,"previous":"M21-GAP-03006","next":"M21-GAP-03008"},"M21-GAP-03008":{"line":6263,"offset":1121844,"length":182,"previous":"M21-GAP-03007","next":"M21-GAP-03009"},"M21-GAP-03009":{"line":6264,"offset":1122026,"length":182,"previous":"M21-GAP-03008","next":"M21-GAP-03010"},"M21-GAP-03010":{"line":6265,"offset":1122208,"length":182,"previous":"M21-GAP-03009","next":"M21-GAP-03011"},"M21-GAP-03011":{"line":6266,"offset":1122390,"length":182,"previous":"M21-GAP-03010","next":"M21-GAP-03012"},"M21-GAP-03012":{"line":6267,"offset":1122572,"length":181,"previous":"M21-GAP-03011","next":"M21-GAP-03013"},"M21-GAP-03013":{"line":6268,"offset":1122753,"length":182,"previous":"M21-GAP-03012","next":"M21-GAP-03014"},"M21-GAP-03014":{"line":6269,"offset":1122935,"length":182,"previous":"M21-GAP-03013","next":"M21-GAP-03015"},"M21-GAP-03015":{"line":6270,"offset":1123117,"length":182,"previous":"M21-GAP-03014","next":"M21-GAP-03016"},"M21-GAP-03016":{"line":6271,"offset":1123299,"length":181,"previous":"M21-GAP-03015","next":"M21-GAP-03017"},"M21-GAP-03017":{"line":6272,"offset":1123480,"length":181,"previous":"M21-GAP-03016","next":"M21-GAP-03018"},"M21-GAP-03018":{"line":6273,"offset":1123661,"length":181,"previous":"M21-GAP-03017","next":"M21-GAP-03019"},"M21-GAP-03019":{"line":6274,"offset":1123842,"length":181,"previous":"M21-GAP-03018","next":"M21-GAP-03020"},"M21-GAP-03020":{"line":6275,"offset":1124023,"length":181,"previous":"M21-GAP-03019","next":"M21-GAP-03021"},"M21-GAP-03021":{"line":6276,"offset":1124204,"length":181,"previous":"M21-GAP-03020","next":"M21-GAP-03022"},"M21-GAP-03022":{"line":6277,"offset":1124385,"length":179,"previous":"M21-GAP-03021","next":"M21-GAP-03023"},"M21-GAP-03023":{"line":6278,"offset":1124564,"length":179,"previous":"M21-GAP-03022","next":"M21-GAP-03024"},"M21-GAP-03024":{"line":6279,"offset":1124743,"length":180,"previous":"M21-GAP-03023","next":"M21-GAP-03025"},"M21-GAP-03025":{"line":6280,"offset":1124923,"length":180,"previous":"M21-GAP-03024","next":"M21-GAP-03026"},"M21-GAP-03026":{"line":6281,"offset":1125103,"length":180,"previous":"M21-GAP-03025","next":"M21-GAP-03027"},"M21-GAP-03027":{"line":6282,"offset":1125283,"length":180,"previous":"M21-GAP-03026","next":"M21-GAP-03028"},"M21-GAP-03028":{"line":6283,"offset":1125463,"length":180,"previous":"M21-GAP-03027","next":"M21-GAP-03029"},"M21-GAP-03029":{"line":6284,"offset":1125643,"length":180,"previous":"M21-GAP-03028","next":"M21-GAP-03030"},"M21-GAP-03030":{"line":6285,"offset":1125823,"length":180,"previous":"M21-GAP-03029","next":"M21-GAP-03031"},"M21-GAP-03031":{"line":6286,"offset":1126003,"length":180,"previous":"M21-GAP-03030","next":"M21-GAP-03032"},"M21-GAP-03032":{"line":6287,"offset":1126183,"length":180,"previous":"M21-GAP-03031","next":"M21-GAP-03033"},"M21-GAP-03033":{"line":6288,"offset":1126363,"length":180,"previous":"M21-GAP-03032","next":"M21-GAP-03034"},"M21-GAP-03034":{"line":6289,"offset":1126543,"length":179,"previous":"M21-GAP-03033","next":"M21-GAP-03035"},"M21-GAP-03035":{"line":6290,"offset":1126722,"length":180,"previous":"M21-GAP-03034","next":"M21-GAP-03036"},"M21-GAP-03036":{"line":6291,"offset":1126902,"length":180,"previous":"M21-GAP-03035","next":"M21-GAP-03037"},"M21-GAP-03037":{"line":6292,"offset":1127082,"length":180,"previous":"M21-GAP-03036","next":"M21-GAP-03038"},"M21-GAP-03038":{"line":6293,"offset":1127262,"length":180,"previous":"M21-GAP-03037","next":"M21-GAP-03039"},"M21-GAP-03039":{"line":6294,"offset":1127442,"length":180,"previous":"M21-GAP-03038","next":"M21-GAP-03040"},"M21-GAP-03040":{"line":6295,"offset":1127622,"length":180,"previous":"M21-GAP-03039","next":"M21-GAP-03041"},"M21-GAP-03041":{"line":6296,"offset":1127802,"length":179,"previous":"M21-GAP-03040","next":"M21-GAP-03042"},"M21-GAP-03042":{"line":6297,"offset":1127981,"length":179,"previous":"M21-GAP-03041","next":"M21-GAP-03043"},"M21-GAP-03043":{"line":6298,"offset":1128160,"length":179,"previous":"M21-GAP-03042","next":"M21-GAP-03044"},"M21-GAP-03044":{"line":6299,"offset":1128339,"length":179,"previous":"M21-GAP-03043","next":"M21-GAP-03045"},"M21-GAP-03045":{"line":6300,"offset":1128518,"length":179,"previous":"M21-GAP-03044","next":"M21-GAP-03046"},"M21-GAP-03046":{"line":6301,"offset":1128697,"length":179,"previous":"M21-GAP-03045","next":"M21-GAP-03047"},"M21-GAP-03047":{"line":6302,"offset":1128876,"length":179,"previous":"M21-GAP-03046","next":"M21-GAP-03048"},"M21-GAP-03048":{"line":6303,"offset":1129055,"length":198,"previous":"M21-GAP-03047","next":"M21-GAP-03049"},"M21-GAP-03049":{"line":6304,"offset":1129253,"length":198,"previous":"M21-GAP-03048","next":"M21-GAP-03050"},"M21-GAP-03050":{"line":6305,"offset":1129451,"length":198,"previous":"M21-GAP-03049","next":"M21-GAP-03051"},"M21-GAP-03051":{"line":6306,"offset":1129649,"length":198,"previous":"M21-GAP-03050","next":"M21-GAP-03052"},"M21-GAP-03052":{"line":6307,"offset":1129847,"length":198,"previous":"M21-GAP-03051","next":"M21-GAP-03053"},"M21-GAP-03053":{"line":6308,"offset":1130045,"length":198,"previous":"M21-GAP-03052","next":"M21-GAP-03054"},"M21-GAP-03054":{"line":6309,"offset":1130243,"length":198,"previous":"M21-GAP-03053","next":"M21-GAP-03055"},"M21-GAP-03055":{"line":6310,"offset":1130441,"length":186,"previous":"M21-GAP-03054","next":"M21-GAP-03056"},"M21-GAP-03056":{"line":6311,"offset":1130627,"length":186,"previous":"M21-GAP-03055","next":"M21-GAP-03057"},"M21-GAP-03057":{"line":6312,"offset":1130813,"length":187,"previous":"M21-GAP-03056","next":"M21-GAP-03058"},"M21-GAP-03058":{"line":6313,"offset":1131000,"length":187,"previous":"M21-GAP-03057","next":"M21-GAP-03059"},"M21-GAP-03059":{"line":6314,"offset":1131187,"length":187,"previous":"M21-GAP-03058","next":"M21-GAP-03060"},"M21-GAP-03060":{"line":6315,"offset":1131374,"length":187,"previous":"M21-GAP-03059","next":"M21-GAP-03061"},"M21-GAP-03061":{"line":6316,"offset":1131561,"length":186,"previous":"M21-GAP-03060","next":"M21-GAP-03062"},"M21-GAP-03062":{"line":6317,"offset":1131747,"length":186,"previous":"M21-GAP-03061","next":"M21-GAP-03063"},"M21-GAP-03063":{"line":6318,"offset":1131933,"length":186,"previous":"M21-GAP-03062","next":"M21-GAP-03064"},"M21-GAP-03064":{"line":6319,"offset":1132119,"length":186,"previous":"M21-GAP-03063","next":"M21-GAP-03065"},"M21-GAP-03065":{"line":6320,"offset":1132305,"length":186,"previous":"M21-GAP-03064","next":"M21-GAP-03066"},"M21-GAP-03066":{"line":6321,"offset":1132491,"length":186,"previous":"M21-GAP-03065","next":"M21-GAP-03067"},"M21-GAP-03067":{"line":6322,"offset":1132677,"length":186,"previous":"M21-GAP-03066","next":"M21-GAP-03068"},"M21-GAP-03068":{"line":6323,"offset":1132863,"length":186,"previous":"M21-GAP-03067","next":"M21-GAP-03069"},"M21-GAP-03069":{"line":6324,"offset":1133049,"length":173,"previous":"M21-GAP-03068","next":"M21-GAP-03070"},"M21-GAP-03070":{"line":6325,"offset":1133222,"length":173,"previous":"M21-GAP-03069","next":"M21-GAP-03071"},"M21-GAP-03071":{"line":6326,"offset":1133395,"length":174,"previous":"M21-GAP-03070","next":"M21-GAP-03072"},"M21-GAP-03072":{"line":6327,"offset":1133569,"length":174,"previous":"M21-GAP-03071","next":"M21-GAP-03073"},"M21-GAP-03073":{"line":6328,"offset":1133743,"length":174,"previous":"M21-GAP-03072","next":"M21-GAP-03074"},"M21-GAP-03074":{"line":6329,"offset":1133917,"length":174,"previous":"M21-GAP-03073","next":"M21-GAP-03075"},"M21-GAP-03075":{"line":6330,"offset":1134091,"length":174,"previous":"M21-GAP-03074","next":"M21-GAP-03076"},"M21-GAP-03076":{"line":6331,"offset":1134265,"length":174,"previous":"M21-GAP-03075","next":"M21-GAP-03077"},"M21-GAP-03077":{"line":6332,"offset":1134439,"length":174,"previous":"M21-GAP-03076","next":"M21-GAP-03078"},"M21-GAP-03078":{"line":6333,"offset":1134613,"length":174,"previous":"M21-GAP-03077","next":"M21-GAP-03079"},"M21-GAP-03079":{"line":6334,"offset":1134787,"length":174,"previous":"M21-GAP-03078","next":"M21-GAP-03080"},"M21-GAP-03080":{"line":6335,"offset":1134961,"length":174,"previous":"M21-GAP-03079","next":"M21-GAP-03081"},"M21-GAP-03081":{"line":6336,"offset":1135135,"length":173,"previous":"M21-GAP-03080","next":"M21-GAP-03082"},"M21-GAP-03082":{"line":6337,"offset":1135308,"length":174,"previous":"M21-GAP-03081","next":"M21-GAP-03083"},"M21-GAP-03083":{"line":6338,"offset":1135482,"length":174,"previous":"M21-GAP-03082","next":"M21-GAP-03084"},"M21-GAP-03084":{"line":6339,"offset":1135656,"length":174,"previous":"M21-GAP-03083","next":"M21-GAP-03085"},"M21-GAP-03085":{"line":6340,"offset":1135830,"length":174,"previous":"M21-GAP-03084","next":"M21-GAP-03086"},"M21-GAP-03086":{"line":6341,"offset":1136004,"length":174,"previous":"M21-GAP-03085","next":"M21-GAP-03087"},"M21-GAP-03087":{"line":6342,"offset":1136178,"length":173,"previous":"M21-GAP-03086","next":"M21-GAP-03088"},"M21-GAP-03088":{"line":6343,"offset":1136351,"length":173,"previous":"M21-GAP-03087","next":"M21-GAP-03089"},"M21-GAP-03089":{"line":6344,"offset":1136524,"length":173,"previous":"M21-GAP-03088","next":"M21-GAP-03090"},"M21-GAP-03090":{"line":6345,"offset":1136697,"length":173,"previous":"M21-GAP-03089","next":"M21-GAP-03091"},"M21-GAP-03091":{"line":6346,"offset":1136870,"length":173,"previous":"M21-GAP-03090","next":"M21-GAP-03092"},"M21-GAP-03092":{"line":6347,"offset":1137043,"length":173,"previous":"M21-GAP-03091","next":"M21-GAP-03093"},"M21-GAP-03093":{"line":6348,"offset":1137216,"length":173,"previous":"M21-GAP-03092","next":"M21-GAP-03094"},"M21-GAP-03094":{"line":6349,"offset":1137389,"length":185,"previous":"M21-GAP-03093","next":"M21-GAP-03095"},"M21-GAP-03095":{"line":6350,"offset":1137574,"length":183,"previous":"M21-GAP-03094","next":"M21-GAP-03096"},"M21-GAP-03096":{"line":6351,"offset":1137757,"length":183,"previous":"M21-GAP-03095","next":"M21-GAP-03097"},"M21-GAP-03097":{"line":6352,"offset":1137940,"length":184,"previous":"M21-GAP-03096","next":"M21-GAP-03098"},"M21-GAP-03098":{"line":6353,"offset":1138124,"length":184,"previous":"M21-GAP-03097","next":"M21-GAP-03099"},"M21-GAP-03099":{"line":6354,"offset":1138308,"length":184,"previous":"M21-GAP-03098","next":"M21-GAP-03100"},"M21-GAP-03100":{"line":6355,"offset":1138492,"length":184,"previous":"M21-GAP-03099","next":"M21-GAP-03101"},"M21-GAP-03101":{"line":6356,"offset":1138676,"length":184,"previous":"M21-GAP-03100","next":"M21-GAP-03102"},"M21-GAP-03102":{"line":6357,"offset":1138860,"length":184,"previous":"M21-GAP-03101","next":"M21-GAP-03103"},"M21-GAP-03103":{"line":6358,"offset":1139044,"length":184,"previous":"M21-GAP-03102","next":"M21-GAP-03104"},"M21-GAP-03104":{"line":6359,"offset":1139228,"length":184,"previous":"M21-GAP-03103","next":"M21-GAP-03105"},"M21-GAP-03105":{"line":6360,"offset":1139412,"length":184,"previous":"M21-GAP-03104","next":"M21-GAP-03106"},"M21-GAP-03106":{"line":6361,"offset":1139596,"length":184,"previous":"M21-GAP-03105","next":"M21-GAP-03107"},"M21-GAP-03107":{"line":6362,"offset":1139780,"length":183,"previous":"M21-GAP-03106","next":"M21-GAP-03108"},"M21-GAP-03108":{"line":6363,"offset":1139963,"length":184,"previous":"M21-GAP-03107","next":"M21-GAP-03109"},"M21-GAP-03109":{"line":6364,"offset":1140147,"length":184,"previous":"M21-GAP-03108","next":"M21-GAP-03110"},"M21-GAP-03110":{"line":6365,"offset":1140331,"length":184,"previous":"M21-GAP-03109","next":"M21-GAP-03111"},"M21-GAP-03111":{"line":6366,"offset":1140515,"length":184,"previous":"M21-GAP-03110","next":"M21-GAP-03112"},"M21-GAP-03112":{"line":6367,"offset":1140699,"length":184,"previous":"M21-GAP-03111","next":"M21-GAP-03113"},"M21-GAP-03113":{"line":6368,"offset":1140883,"length":184,"previous":"M21-GAP-03112","next":"M21-GAP-03114"},"M21-GAP-03114":{"line":6369,"offset":1141067,"length":184,"previous":"M21-GAP-03113","next":"M21-GAP-03115"},"M21-GAP-03115":{"line":6370,"offset":1141251,"length":184,"previous":"M21-GAP-03114","next":"M21-GAP-03116"},"M21-GAP-03116":{"line":6371,"offset":1141435,"length":184,"previous":"M21-GAP-03115","next":"M21-GAP-03117"},"M21-GAP-03117":{"line":6372,"offset":1141619,"length":184,"previous":"M21-GAP-03116","next":"M21-GAP-03118"},"M21-GAP-03118":{"line":6373,"offset":1141803,"length":183,"previous":"M21-GAP-03117","next":"M21-GAP-03119"},"M21-GAP-03119":{"line":6374,"offset":1141986,"length":184,"previous":"M21-GAP-03118","next":"M21-GAP-03120"},"M21-GAP-03120":{"line":6375,"offset":1142170,"length":184,"previous":"M21-GAP-03119","next":"M21-GAP-03121"},"M21-GAP-03121":{"line":6376,"offset":1142354,"length":184,"previous":"M21-GAP-03120","next":"M21-GAP-03122"},"M21-GAP-03122":{"line":6377,"offset":1142538,"length":184,"previous":"M21-GAP-03121","next":"M21-GAP-03123"},"M21-GAP-03123":{"line":6378,"offset":1142722,"length":184,"previous":"M21-GAP-03122","next":"M21-GAP-03124"},"M21-GAP-03124":{"line":6379,"offset":1142906,"length":184,"previous":"M21-GAP-03123","next":"M21-GAP-03125"},"M21-GAP-03125":{"line":6380,"offset":1143090,"length":184,"previous":"M21-GAP-03124","next":"M21-GAP-03126"},"M21-GAP-03126":{"line":6381,"offset":1143274,"length":184,"previous":"M21-GAP-03125","next":"M21-GAP-03127"},"M21-GAP-03127":{"line":6382,"offset":1143458,"length":184,"previous":"M21-GAP-03126","next":"M21-GAP-03128"},"M21-GAP-03128":{"line":6383,"offset":1143642,"length":183,"previous":"M21-GAP-03127","next":"M21-GAP-03129"},"M21-GAP-03129":{"line":6384,"offset":1143825,"length":183,"previous":"M21-GAP-03128","next":"M21-GAP-03130"},"M21-GAP-03130":{"line":6385,"offset":1144008,"length":183,"previous":"M21-GAP-03129","next":"M21-GAP-03131"},"M21-GAP-03131":{"line":6386,"offset":1144191,"length":183,"previous":"M21-GAP-03130","next":"M21-GAP-03132"},"M21-GAP-03132":{"line":6387,"offset":1144374,"length":183,"previous":"M21-GAP-03131","next":"M21-GAP-03133"},"M21-GAP-03133":{"line":6388,"offset":1144557,"length":183,"previous":"M21-GAP-03132","next":"M21-GAP-03134"},"M21-GAP-03134":{"line":6389,"offset":1144740,"length":188,"previous":"M21-GAP-03133","next":"M21-GAP-03135"},"M21-GAP-03135":{"line":6390,"offset":1144928,"length":188,"previous":"M21-GAP-03134","next":"M21-GAP-03136"},"M21-GAP-03136":{"line":6391,"offset":1145116,"length":189,"previous":"M21-GAP-03135","next":"M21-GAP-03137"},"M21-GAP-03137":{"line":6392,"offset":1145305,"length":189,"previous":"M21-GAP-03136","next":"M21-GAP-03138"},"M21-GAP-03138":{"line":6393,"offset":1145494,"length":189,"previous":"M21-GAP-03137","next":"M21-GAP-03139"},"M21-GAP-03139":{"line":6394,"offset":1145683,"length":189,"previous":"M21-GAP-03138","next":"M21-GAP-03140"},"M21-GAP-03140":{"line":6395,"offset":1145872,"length":188,"previous":"M21-GAP-03139","next":"M21-GAP-03141"},"M21-GAP-03141":{"line":6396,"offset":1146060,"length":188,"previous":"M21-GAP-03140","next":"M21-GAP-03142"},"M21-GAP-03142":{"line":6397,"offset":1146248,"length":188,"previous":"M21-GAP-03141","next":"M21-GAP-03143"},"M21-GAP-03143":{"line":6398,"offset":1146436,"length":188,"previous":"M21-GAP-03142","next":"M21-GAP-03144"},"M21-GAP-03144":{"line":6399,"offset":1146624,"length":188,"previous":"M21-GAP-03143","next":"M21-GAP-03145"},"M21-GAP-03145":{"line":6400,"offset":1146812,"length":188,"previous":"M21-GAP-03144","next":"M21-GAP-03146"},"M21-GAP-03146":{"line":6401,"offset":1147000,"length":188,"previous":"M21-GAP-03145","next":"M21-GAP-03147"},"M21-GAP-03147":{"line":6402,"offset":1147188,"length":188,"previous":"M21-GAP-03146","next":"M21-GAP-03148"},"M21-GAP-03148":{"line":6403,"offset":1147376,"length":184,"previous":"M21-GAP-03147","next":"M21-GAP-03149"},"M21-GAP-03149":{"line":6404,"offset":1147560,"length":189,"previous":"M21-GAP-03148","next":"M21-GAP-03150"},"M21-GAP-03150":{"line":6405,"offset":1147749,"length":189,"previous":"M21-GAP-03149","next":"M21-GAP-03151"},"M21-GAP-03151":{"line":6406,"offset":1147938,"length":190,"previous":"M21-GAP-03150","next":"M21-GAP-03152"},"M21-GAP-03152":{"line":6407,"offset":1148128,"length":190,"previous":"M21-GAP-03151","next":"M21-GAP-03153"},"M21-GAP-03153":{"line":6408,"offset":1148318,"length":189,"previous":"M21-GAP-03152","next":"M21-GAP-03154"},"M21-GAP-03154":{"line":6409,"offset":1148507,"length":189,"previous":"M21-GAP-03153","next":"M21-GAP-03155"},"M21-GAP-03155":{"line":6410,"offset":1148696,"length":189,"previous":"M21-GAP-03154","next":"M21-GAP-03156"},"M21-GAP-03156":{"line":6411,"offset":1148885,"length":189,"previous":"M21-GAP-03155","next":"M21-GAP-03157"},"M21-GAP-03157":{"line":6412,"offset":1149074,"length":189,"previous":"M21-GAP-03156","next":"M21-GAP-03158"},"M21-GAP-03158":{"line":6413,"offset":1149263,"length":189,"previous":"M21-GAP-03157","next":"M21-GAP-03159"},"M21-GAP-03159":{"line":6414,"offset":1149452,"length":189,"previous":"M21-GAP-03158","next":"M21-GAP-03160"},"M21-GAP-03160":{"line":6415,"offset":1149641,"length":189,"previous":"M21-GAP-03159","next":"M21-GAP-03161"},"M21-GAP-03161":{"line":6416,"offset":1149830,"length":186,"previous":"M21-GAP-03160","next":"M21-GAP-03162"},"M21-GAP-03162":{"line":6417,"offset":1150016,"length":186,"previous":"M21-GAP-03161","next":"M21-GAP-03163"},"M21-GAP-03163":{"line":6418,"offset":1150202,"length":186,"previous":"M21-GAP-03162","next":"M21-GAP-03164"},"M21-GAP-03164":{"line":6419,"offset":1150388,"length":186,"previous":"M21-GAP-03163","next":"M21-GAP-03165"},"M21-GAP-03165":{"line":6420,"offset":1150574,"length":186,"previous":"M21-GAP-03164","next":"M21-GAP-03166"},"M21-GAP-03166":{"line":6421,"offset":1150760,"length":215,"previous":"M21-GAP-03165","next":"M21-GAP-03167"},"M21-GAP-03167":{"line":6422,"offset":1150975,"length":215,"previous":"M21-GAP-03166","next":"M21-GAP-03168"},"M21-GAP-03168":{"line":6423,"offset":1151190,"length":215,"previous":"M21-GAP-03167","next":"M21-GAP-03169"},"M21-GAP-03169":{"line":6424,"offset":1151405,"length":215,"previous":"M21-GAP-03168","next":"M21-GAP-03170"},"M21-GAP-03170":{"line":6425,"offset":1151620,"length":215,"previous":"M21-GAP-03169","next":"M21-GAP-03171"},"M21-GAP-03171":{"line":6426,"offset":1151835,"length":215,"previous":"M21-GAP-03170","next":"M21-GAP-03172"},"M21-GAP-03172":{"line":6427,"offset":1152050,"length":184,"previous":"M21-GAP-03171","next":"M21-GAP-03173"},"M21-GAP-03173":{"line":6428,"offset":1152234,"length":184,"previous":"M21-GAP-03172","next":"M21-GAP-03174"},"M21-GAP-03174":{"line":6429,"offset":1152418,"length":185,"previous":"M21-GAP-03173","next":"M21-GAP-03175"},"M21-GAP-03175":{"line":6430,"offset":1152603,"length":185,"previous":"M21-GAP-03174","next":"M21-GAP-03176"},"M21-GAP-03176":{"line":6431,"offset":1152788,"length":185,"previous":"M21-GAP-03175","next":"M21-GAP-03177"},"M21-GAP-03177":{"line":6432,"offset":1152973,"length":185,"previous":"M21-GAP-03176","next":"M21-GAP-03178"},"M21-GAP-03178":{"line":6433,"offset":1153158,"length":185,"previous":"M21-GAP-03177","next":"M21-GAP-03179"},"M21-GAP-03179":{"line":6434,"offset":1153343,"length":185,"previous":"M21-GAP-03178","next":"M21-GAP-03180"},"M21-GAP-03180":{"line":6435,"offset":1153528,"length":185,"previous":"M21-GAP-03179","next":"M21-GAP-03181"},"M21-GAP-03181":{"line":6436,"offset":1153713,"length":185,"previous":"M21-GAP-03180","next":"M21-GAP-03182"},"M21-GAP-03182":{"line":6437,"offset":1153898,"length":185,"previous":"M21-GAP-03181","next":"M21-GAP-03183"},"M21-GAP-03183":{"line":6438,"offset":1154083,"length":185,"previous":"M21-GAP-03182","next":"M21-GAP-03184"},"M21-GAP-03184":{"line":6439,"offset":1154268,"length":184,"previous":"M21-GAP-03183","next":"M21-GAP-03185"},"M21-GAP-03185":{"line":6440,"offset":1154452,"length":185,"previous":"M21-GAP-03184","next":"M21-GAP-03186"},"M21-GAP-03186":{"line":6441,"offset":1154637,"length":185,"previous":"M21-GAP-03185","next":"M21-GAP-03187"},"M21-GAP-03187":{"line":6442,"offset":1154822,"length":185,"previous":"M21-GAP-03186","next":"M21-GAP-03188"},"M21-GAP-03188":{"line":6443,"offset":1155007,"length":185,"previous":"M21-GAP-03187","next":"M21-GAP-03189"},"M21-GAP-03189":{"line":6444,"offset":1155192,"length":185,"previous":"M21-GAP-03188","next":"M21-GAP-03190"},"M21-GAP-03190":{"line":6445,"offset":1155377,"length":185,"previous":"M21-GAP-03189","next":"M21-GAP-03191"},"M21-GAP-03191":{"line":6446,"offset":1155562,"length":185,"previous":"M21-GAP-03190","next":"M21-GAP-03192"},"M21-GAP-03192":{"line":6447,"offset":1155747,"length":185,"previous":"M21-GAP-03191","next":"M21-GAP-03193"},"M21-GAP-03193":{"line":6448,"offset":1155932,"length":185,"previous":"M21-GAP-03192","next":"M21-GAP-03194"},"M21-GAP-03194":{"line":6449,"offset":1156117,"length":185,"previous":"M21-GAP-03193","next":"M21-GAP-03195"},"M21-GAP-03195":{"line":6450,"offset":1156302,"length":184,"previous":"M21-GAP-03194","next":"M21-GAP-03196"},"M21-GAP-03196":{"line":6451,"offset":1156486,"length":185,"previous":"M21-GAP-03195","next":"M21-GAP-03197"},"M21-GAP-03197":{"line":6452,"offset":1156671,"length":185,"previous":"M21-GAP-03196","next":"M21-GAP-03198"},"M21-GAP-03198":{"line":6453,"offset":1156856,"length":185,"previous":"M21-GAP-03197","next":"M21-GAP-03199"},"M21-GAP-03199":{"line":6454,"offset":1157041,"length":185,"previous":"M21-GAP-03198","next":"M21-GAP-03200"},"M21-GAP-03200":{"line":6455,"offset":1157226,"length":185,"previous":"M21-GAP-03199","next":"M21-GAP-03201"},"M21-GAP-03201":{"line":6456,"offset":1157411,"length":185,"previous":"M21-GAP-03200","next":"M21-GAP-03202"},"M21-GAP-03202":{"line":6457,"offset":1157596,"length":185,"previous":"M21-GAP-03201","next":"M21-GAP-03203"},"M21-GAP-03203":{"line":6458,"offset":1157781,"length":185,"previous":"M21-GAP-03202","next":"M21-GAP-03204"},"M21-GAP-03204":{"line":6459,"offset":1157966,"length":185,"previous":"M21-GAP-03203","next":"M21-GAP-03205"},"M21-GAP-03205":{"line":6460,"offset":1158151,"length":185,"previous":"M21-GAP-03204","next":"M21-GAP-03206"},"M21-GAP-03206":{"line":6461,"offset":1158336,"length":184,"previous":"M21-GAP-03205","next":"M21-GAP-03207"},"M21-GAP-03207":{"line":6462,"offset":1158520,"length":185,"previous":"M21-GAP-03206","next":"M21-GAP-03208"},"M21-GAP-03208":{"line":6463,"offset":1158705,"length":185,"previous":"M21-GAP-03207","next":"M21-GAP-03209"},"M21-GAP-03209":{"line":6464,"offset":1158890,"length":185,"previous":"M21-GAP-03208","next":"M21-GAP-03210"},"M21-GAP-03210":{"line":6465,"offset":1159075,"length":185,"previous":"M21-GAP-03209","next":"M21-GAP-03211"},"M21-GAP-03211":{"line":6466,"offset":1159260,"length":185,"previous":"M21-GAP-03210","next":"M21-GAP-03212"},"M21-GAP-03212":{"line":6467,"offset":1159445,"length":185,"previous":"M21-GAP-03211","next":"M21-GAP-03213"},"M21-GAP-03213":{"line":6468,"offset":1159630,"length":185,"previous":"M21-GAP-03212","next":"M21-GAP-03214"},"M21-GAP-03214":{"line":6469,"offset":1159815,"length":185,"previous":"M21-GAP-03213","next":"M21-GAP-03215"},"M21-GAP-03215":{"line":6470,"offset":1160000,"length":185,"previous":"M21-GAP-03214","next":"M21-GAP-03216"},"M21-GAP-03216":{"line":6471,"offset":1160185,"length":185,"previous":"M21-GAP-03215","next":"M21-GAP-03217"},"M21-GAP-03217":{"line":6472,"offset":1160370,"length":184,"previous":"M21-GAP-03216","next":"M21-GAP-03218"},"M21-GAP-03218":{"line":6473,"offset":1160554,"length":184,"previous":"M21-GAP-03217","next":"M21-GAP-03219"},"M21-GAP-03219":{"line":6474,"offset":1160738,"length":184,"previous":"M21-GAP-03218","next":"M21-GAP-03220"},"M21-GAP-03220":{"line":6475,"offset":1160922,"length":184,"previous":"M21-GAP-03219","next":"M21-GAP-03221"},"M21-GAP-03221":{"line":6476,"offset":1161106,"length":184,"previous":"M21-GAP-03220","next":"M21-GAP-03222"},"M21-GAP-03222":{"line":6477,"offset":1161290,"length":184,"previous":"M21-GAP-03221","next":"M21-GAP-03223"},"M21-GAP-03223":{"line":6478,"offset":1161474,"length":179,"previous":"M21-GAP-03222","next":"M21-GAP-03224"},"M21-GAP-03224":{"line":6479,"offset":1161653,"length":179,"previous":"M21-GAP-03223","next":"M21-GAP-03225"},"M21-GAP-03225":{"line":6480,"offset":1161832,"length":180,"previous":"M21-GAP-03224","next":"M21-GAP-03226"},"M21-GAP-03226":{"line":6481,"offset":1162012,"length":180,"previous":"M21-GAP-03225","next":"M21-GAP-03227"},"M21-GAP-03227":{"line":6482,"offset":1162192,"length":180,"previous":"M21-GAP-03226","next":"M21-GAP-03228"},"M21-GAP-03228":{"line":6483,"offset":1162372,"length":180,"previous":"M21-GAP-03227","next":"M21-GAP-03229"},"M21-GAP-03229":{"line":6484,"offset":1162552,"length":180,"previous":"M21-GAP-03228","next":"M21-GAP-03230"},"M21-GAP-03230":{"line":6485,"offset":1162732,"length":180,"previous":"M21-GAP-03229","next":"M21-GAP-03231"},"M21-GAP-03231":{"line":6486,"offset":1162912,"length":180,"previous":"M21-GAP-03230","next":"M21-GAP-03232"},"M21-GAP-03232":{"line":6487,"offset":1163092,"length":180,"previous":"M21-GAP-03231","next":"M21-GAP-03233"},"M21-GAP-03233":{"line":6488,"offset":1163272,"length":180,"previous":"M21-GAP-03232","next":"M21-GAP-03234"},"M21-GAP-03234":{"line":6489,"offset":1163452,"length":180,"previous":"M21-GAP-03233","next":"M21-GAP-03235"},"M21-GAP-03235":{"line":6490,"offset":1163632,"length":179,"previous":"M21-GAP-03234","next":"M21-GAP-03236"},"M21-GAP-03236":{"line":6491,"offset":1163811,"length":180,"previous":"M21-GAP-03235","next":"M21-GAP-03237"},"M21-GAP-03237":{"line":6492,"offset":1163991,"length":180,"previous":"M21-GAP-03236","next":"M21-GAP-03238"},"M21-GAP-03238":{"line":6493,"offset":1164171,"length":180,"previous":"M21-GAP-03237","next":"M21-GAP-03239"},"M21-GAP-03239":{"line":6494,"offset":1164351,"length":180,"previous":"M21-GAP-03238","next":"M21-GAP-03240"},"M21-GAP-03240":{"line":6495,"offset":1164531,"length":180,"previous":"M21-GAP-03239","next":"M21-GAP-03241"},"M21-GAP-03241":{"line":6496,"offset":1164711,"length":179,"previous":"M21-GAP-03240","next":"M21-GAP-03242"},"M21-GAP-03242":{"line":6497,"offset":1164890,"length":179,"previous":"M21-GAP-03241","next":"M21-GAP-03243"},"M21-GAP-03243":{"line":6498,"offset":1165069,"length":179,"previous":"M21-GAP-03242","next":"M21-GAP-03244"},"M21-GAP-03244":{"line":6499,"offset":1165248,"length":179,"previous":"M21-GAP-03243","next":"M21-GAP-03245"},"M21-GAP-03245":{"line":6500,"offset":1165427,"length":179,"previous":"M21-GAP-03244","next":"M21-GAP-03246"},"M21-GAP-03246":{"line":6501,"offset":1165606,"length":179,"previous":"M21-GAP-03245","next":"M21-GAP-03247"},"M21-GAP-03247":{"line":6502,"offset":1165785,"length":179,"previous":"M21-GAP-03246","next":"M21-GAP-03248"},"M21-GAP-03248":{"line":6503,"offset":1165964,"length":173,"previous":"M21-GAP-03247","next":"M21-GAP-03249"},"M21-GAP-03249":{"line":6504,"offset":1166137,"length":173,"previous":"M21-GAP-03248","next":"M21-GAP-03250"},"M21-GAP-03250":{"line":6505,"offset":1166310,"length":174,"previous":"M21-GAP-03249","next":"M21-GAP-03251"},"M21-GAP-03251":{"line":6506,"offset":1166484,"length":174,"previous":"M21-GAP-03250","next":"M21-GAP-03252"},"M21-GAP-03252":{"line":6507,"offset":1166658,"length":174,"previous":"M21-GAP-03251","next":"M21-GAP-03253"},"M21-GAP-03253":{"line":6508,"offset":1166832,"length":174,"previous":"M21-GAP-03252","next":"M21-GAP-03254"},"M21-GAP-03254":{"line":6509,"offset":1167006,"length":174,"previous":"M21-GAP-03253","next":"M21-GAP-03255"},"M21-GAP-03255":{"line":6510,"offset":1167180,"length":174,"previous":"M21-GAP-03254","next":"M21-GAP-03256"},"M21-GAP-03256":{"line":6511,"offset":1167354,"length":174,"previous":"M21-GAP-03255","next":"M21-GAP-03257"},"M21-GAP-03257":{"line":6512,"offset":1167528,"length":174,"previous":"M21-GAP-03256","next":"M21-GAP-03258"},"M21-GAP-03258":{"line":6513,"offset":1167702,"length":174,"previous":"M21-GAP-03257","next":"M21-GAP-03259"},"M21-GAP-03259":{"line":6514,"offset":1167876,"length":174,"previous":"M21-GAP-03258","next":"M21-GAP-03260"},"M21-GAP-03260":{"line":6515,"offset":1168050,"length":173,"previous":"M21-GAP-03259","next":"M21-GAP-03261"},"M21-GAP-03261":{"line":6516,"offset":1168223,"length":174,"previous":"M21-GAP-03260","next":"M21-GAP-03262"},"M21-GAP-03262":{"line":6517,"offset":1168397,"length":174,"previous":"M21-GAP-03261","next":"M21-GAP-03263"},"M21-GAP-03263":{"line":6518,"offset":1168571,"length":174,"previous":"M21-GAP-03262","next":"M21-GAP-03264"},"M21-GAP-03264":{"line":6519,"offset":1168745,"length":174,"previous":"M21-GAP-03263","next":"M21-GAP-03265"},"M21-GAP-03265":{"line":6520,"offset":1168919,"length":174,"previous":"M21-GAP-03264","next":"M21-GAP-03266"},"M21-GAP-03266":{"line":6521,"offset":1169093,"length":174,"previous":"M21-GAP-03265","next":"M21-GAP-03267"},"M21-GAP-03267":{"line":6522,"offset":1169267,"length":174,"previous":"M21-GAP-03266","next":"M21-GAP-03268"},"M21-GAP-03268":{"line":6523,"offset":1169441,"length":174,"previous":"M21-GAP-03267","next":"M21-GAP-03269"},"M21-GAP-03269":{"line":6524,"offset":1169615,"length":174,"previous":"M21-GAP-03268","next":"M21-GAP-03270"},"M21-GAP-03270":{"line":6525,"offset":1169789,"length":174,"previous":"M21-GAP-03269","next":"M21-GAP-03271"},"M21-GAP-03271":{"line":6526,"offset":1169963,"length":173,"previous":"M21-GAP-03270","next":"M21-GAP-03272"},"M21-GAP-03272":{"line":6527,"offset":1170136,"length":174,"previous":"M21-GAP-03271","next":"M21-GAP-03273"},"M21-GAP-03273":{"line":6528,"offset":1170310,"length":174,"previous":"M21-GAP-03272","next":"M21-GAP-03274"},"M21-GAP-03274":{"line":6529,"offset":1170484,"length":174,"previous":"M21-GAP-03273","next":"M21-GAP-03275"},"M21-GAP-03275":{"line":6530,"offset":1170658,"length":173,"previous":"M21-GAP-03274","next":"M21-GAP-03276"},"M21-GAP-03276":{"line":6531,"offset":1170831,"length":173,"previous":"M21-GAP-03275","next":"M21-GAP-03277"},"M21-GAP-03277":{"line":6532,"offset":1171004,"length":173,"previous":"M21-GAP-03276","next":"M21-GAP-03278"},"M21-GAP-03278":{"line":6533,"offset":1171177,"length":173,"previous":"M21-GAP-03277","next":"M21-GAP-03279"},"M21-GAP-03279":{"line":6534,"offset":1171350,"length":173,"previous":"M21-GAP-03278","next":"M21-GAP-03280"},"M21-GAP-03280":{"line":6535,"offset":1171523,"length":173,"previous":"M21-GAP-03279","next":"M21-GAP-03281"},"M21-GAP-03281":{"line":6536,"offset":1171696,"length":177,"previous":"M21-GAP-03280","next":"M21-GAP-03282"},"M21-GAP-03282":{"line":6537,"offset":1171873,"length":180,"previous":"M21-GAP-03281","next":"M21-GAP-03283"},"M21-GAP-03283":{"line":6538,"offset":1172053,"length":187,"previous":"M21-GAP-03282","next":"M21-GAP-03284"},"M21-GAP-03284":{"line":6539,"offset":1172240,"length":182,"previous":"M21-GAP-03283","next":"M21-GAP-03285"},"M21-GAP-03285":{"line":6540,"offset":1172422,"length":202,"previous":"M21-GAP-03284","next":"M21-GAP-03286"},"M21-GAP-03286":{"line":6541,"offset":1172624,"length":204,"previous":"M21-GAP-03285","next":"M21-GAP-03287"},"M21-GAP-03287":{"line":6542,"offset":1172828,"length":208,"previous":"M21-GAP-03286","next":"M21-GAP-03288"},"M21-GAP-03288":{"line":6543,"offset":1173036,"length":198,"previous":"M21-GAP-03287","next":"M21-GAP-03289"},"M21-GAP-03289":{"line":6544,"offset":1173234,"length":195,"previous":"M21-GAP-03288","next":"M21-GAP-03290"},"M21-GAP-03290":{"line":6545,"offset":1173429,"length":197,"previous":"M21-GAP-03289","next":"M21-GAP-03291"},"M21-GAP-03291":{"line":6546,"offset":1173626,"length":192,"previous":"M21-GAP-03290","next":"M21-GAP-03292"},"M21-GAP-03292":{"line":6547,"offset":1173818,"length":205,"previous":"M21-GAP-03291","next":"M21-GAP-03293"},"M21-GAP-03293":{"line":6548,"offset":1174023,"length":195,"previous":"M21-GAP-03292","next":"M21-GAP-03294"},"M21-GAP-03294":{"line":6549,"offset":1174218,"length":194,"previous":"M21-GAP-03293","next":"M21-GAP-03295"},"M21-GAP-03295":{"line":6550,"offset":1174412,"length":197,"previous":"M21-GAP-03294","next":"M21-GAP-03296"},"M21-GAP-03296":{"line":6551,"offset":1174609,"length":192,"previous":"M21-GAP-03295","next":"M21-GAP-03297"},"M21-GAP-03297":{"line":6552,"offset":1174801,"length":193,"previous":"M21-GAP-03296","next":"M21-GAP-03298"},"M21-GAP-03298":{"line":6553,"offset":1174994,"length":192,"previous":"M21-GAP-03297","next":"M21-GAP-03299"},"M21-GAP-03299":{"line":6554,"offset":1175186,"length":204,"previous":"M21-GAP-03298","next":"M21-GAP-03300"},"M21-GAP-03300":{"line":6555,"offset":1175390,"length":207,"previous":"M21-GAP-03299","next":"M21-GAP-03301"},"M21-GAP-03301":{"line":6556,"offset":1175597,"length":199,"previous":"M21-GAP-03300","next":"M21-GAP-03302"},"M21-GAP-03302":{"line":6557,"offset":1175796,"length":192,"previous":"M21-GAP-03301","next":"M21-GAP-03303"},"M21-GAP-03303":{"line":6558,"offset":1175988,"length":193,"previous":"M21-GAP-03302","next":"M21-GAP-03304"},"M21-GAP-03304":{"line":6559,"offset":1176181,"length":197,"previous":"M21-GAP-03303","next":"M21-GAP-03305"},"M21-GAP-03305":{"line":6560,"offset":1176378,"length":208,"previous":"M21-GAP-03304","next":"M21-GAP-03306"},"M21-GAP-03306":{"line":6561,"offset":1176586,"length":205,"previous":"M21-GAP-03305","next":"M21-GAP-03307"},"M21-GAP-03307":{"line":6562,"offset":1176791,"length":203,"previous":"M21-GAP-03306","next":"M21-GAP-03308"},"M21-GAP-03308":{"line":6563,"offset":1176994,"length":201,"previous":"M21-GAP-03307","next":"M21-GAP-03309"},"M21-GAP-03309":{"line":6564,"offset":1177195,"length":204,"previous":"M21-GAP-03308","next":"M21-GAP-03310"},"M21-GAP-03310":{"line":6565,"offset":1177399,"length":198,"previous":"M21-GAP-03309","next":"M21-GAP-03311"},"M21-GAP-03311":{"line":6566,"offset":1177597,"length":192,"previous":"M21-GAP-03310","next":"M21-GAP-03312"},"M21-GAP-03312":{"line":6567,"offset":1177789,"length":195,"previous":"M21-GAP-03311","next":"M21-GAP-03313"},"M21-GAP-03313":{"line":6568,"offset":1177984,"length":207,"previous":"M21-GAP-03312","next":"M21-GAP-03314"},"M21-GAP-03314":{"line":6569,"offset":1178191,"length":197,"previous":"M21-GAP-03313","next":"M21-GAP-03315"},"M21-GAP-03315":{"line":6570,"offset":1178388,"length":196,"previous":"M21-GAP-03314","next":"M21-GAP-03316"},"M21-GAP-03316":{"line":6571,"offset":1178584,"length":196,"previous":"M21-GAP-03315","next":"M21-GAP-03317"},"M21-GAP-03317":{"line":6572,"offset":1178780,"length":195,"previous":"M21-GAP-03316","next":"M21-GAP-03318"},"M21-GAP-03318":{"line":6573,"offset":1178975,"length":197,"previous":"M21-GAP-03317","next":"M21-GAP-03319"},"M21-GAP-03319":{"line":6574,"offset":1179172,"length":200,"previous":"M21-GAP-03318","next":"M21-GAP-03320"},"M21-GAP-03320":{"line":6575,"offset":1179372,"length":193,"previous":"M21-GAP-03319","next":"M21-GAP-03321"},"M21-GAP-03321":{"line":6576,"offset":1179565,"length":202,"previous":"M21-GAP-03320","next":"M21-GAP-03322"},"M21-GAP-03322":{"line":6577,"offset":1179767,"length":191,"previous":"M21-GAP-03321","next":"M21-GAP-03323"},"M21-GAP-03323":{"line":6578,"offset":1179958,"length":196,"previous":"M21-GAP-03322","next":"M21-GAP-03324"},"M21-GAP-03324":{"line":6579,"offset":1180154,"length":199,"previous":"M21-GAP-03323","next":"M21-GAP-03325"},"M21-GAP-03325":{"line":6580,"offset":1180353,"length":198,"previous":"M21-GAP-03324","next":"M21-GAP-03326"},"M21-GAP-03326":{"line":6581,"offset":1180551,"length":183,"previous":"M21-GAP-03325","next":"M21-GAP-03327"},"M21-GAP-03327":{"line":6582,"offset":1180734,"length":180,"previous":"M21-GAP-03326","next":"M21-GAP-03328"},"M21-GAP-03328":{"line":6583,"offset":1180914,"length":197,"previous":"M21-GAP-03327","next":"M21-GAP-03329"},"M21-GAP-03329":{"line":6584,"offset":1181111,"length":200,"previous":"M21-GAP-03328","next":"M21-GAP-03330"},"M21-GAP-03330":{"line":6585,"offset":1181311,"length":200,"previous":"M21-GAP-03329","next":"M21-GAP-03331"},"M21-GAP-03331":{"line":6586,"offset":1181511,"length":203,"previous":"M21-GAP-03330","next":"M21-GAP-03332"},"M21-GAP-03332":{"line":6587,"offset":1181714,"length":202,"previous":"M21-GAP-03331","next":"M21-GAP-03333"},"M21-GAP-03333":{"line":6588,"offset":1181916,"length":207,"previous":"M21-GAP-03332","next":"M21-GAP-03334"},"M21-GAP-03334":{"line":6589,"offset":1182123,"length":208,"previous":"M21-GAP-03333","next":"M21-GAP-03335"},"M21-GAP-03335":{"line":6590,"offset":1182331,"length":201,"previous":"M21-GAP-03334","next":"M21-GAP-03336"},"M21-GAP-03336":{"line":6591,"offset":1182532,"length":205,"previous":"M21-GAP-03335","next":"M21-GAP-03337"},"M21-GAP-03337":{"line":6592,"offset":1182737,"length":201,"previous":"M21-GAP-03336","next":"M21-GAP-03338"},"M21-GAP-03338":{"line":6593,"offset":1182938,"length":198,"previous":"M21-GAP-03337","next":"M21-GAP-03339"},"M21-GAP-03339":{"line":6594,"offset":1183136,"length":209,"previous":"M21-GAP-03338","next":"M21-GAP-03340"},"M21-GAP-03340":{"line":6595,"offset":1183345,"length":203,"previous":"M21-GAP-03339","next":"M21-GAP-03341"},"M21-GAP-03341":{"line":6596,"offset":1183548,"length":180,"previous":"M21-GAP-03340","next":"M21-GAP-03342"},"M21-GAP-03342":{"line":6597,"offset":1183728,"length":181,"previous":"M21-GAP-03341","next":"M21-GAP-03343"},"M21-GAP-03343":{"line":6598,"offset":1183909,"length":182,"previous":"M21-GAP-03342","next":"M21-GAP-03344"},"M21-GAP-03344":{"line":6599,"offset":1184091,"length":181,"previous":"M21-GAP-03343","next":"M21-GAP-03345"},"M21-GAP-03345":{"line":6600,"offset":1184272,"length":196,"previous":"M21-GAP-03344","next":"M21-GAP-03346"},"M21-GAP-03346":{"line":6601,"offset":1184468,"length":192,"previous":"M21-GAP-03345","next":"M21-GAP-03347"},"M21-GAP-03347":{"line":6602,"offset":1184660,"length":192,"previous":"M21-GAP-03346","next":"M21-GAP-03348"},"M21-GAP-03348":{"line":6603,"offset":1184852,"length":192,"previous":"M21-GAP-03347","next":"M21-GAP-03349"},"M21-GAP-03349":{"line":6604,"offset":1185044,"length":196,"previous":"M21-GAP-03348","next":"M21-GAP-03350"},"M21-GAP-03350":{"line":6605,"offset":1185240,"length":196,"previous":"M21-GAP-03349","next":"M21-GAP-03351"},"M21-GAP-03351":{"line":6606,"offset":1185436,"length":197,"previous":"M21-GAP-03350","next":"M21-GAP-03352"},"M21-GAP-03352":{"line":6607,"offset":1185633,"length":198,"previous":"M21-GAP-03351","next":"M21-GAP-03353"},"M21-GAP-03353":{"line":6608,"offset":1185831,"length":194,"previous":"M21-GAP-03352","next":"M21-GAP-03354"},"M21-GAP-03354":{"line":6609,"offset":1186025,"length":194,"previous":"M21-GAP-03353","next":"M21-GAP-03355"},"M21-GAP-03355":{"line":6610,"offset":1186219,"length":194,"previous":"M21-GAP-03354","next":"M21-GAP-03356"},"M21-GAP-03356":{"line":6611,"offset":1186413,"length":197,"previous":"M21-GAP-03355","next":"M21-GAP-03357"},"M21-GAP-03357":{"line":6612,"offset":1186610,"length":193,"previous":"M21-GAP-03356","next":"M21-GAP-03358"},"M21-GAP-03358":{"line":6613,"offset":1186803,"length":193,"previous":"M21-GAP-03357","next":"M21-GAP-03359"},"M21-GAP-03359":{"line":6614,"offset":1186996,"length":196,"previous":"M21-GAP-03358","next":"M21-GAP-03360"},"M21-GAP-03360":{"line":6615,"offset":1187192,"length":193,"previous":"M21-GAP-03359","next":"M21-GAP-03361"},"M21-GAP-03361":{"line":6616,"offset":1187385,"length":197,"previous":"M21-GAP-03360","next":"M21-GAP-03362"},"M21-GAP-03362":{"line":6617,"offset":1187582,"length":195,"previous":"M21-GAP-03361","next":"M21-GAP-03363"},"M21-GAP-03363":{"line":6618,"offset":1187777,"length":201,"previous":"M21-GAP-03362","next":"M21-GAP-03364"},"M21-GAP-03364":{"line":6619,"offset":1187978,"length":197,"previous":"M21-GAP-03363","next":"M21-GAP-03365"},"M21-GAP-03365":{"line":6620,"offset":1188175,"length":197,"previous":"M21-GAP-03364","next":"M21-GAP-03366"},"M21-GAP-03366":{"line":6621,"offset":1188372,"length":197,"previous":"M21-GAP-03365","next":"M21-GAP-03367"},"M21-GAP-03367":{"line":6622,"offset":1188569,"length":197,"previous":"M21-GAP-03366","next":"M21-GAP-03368"},"M21-GAP-03368":{"line":6623,"offset":1188766,"length":186,"previous":"M21-GAP-03367","next":"M21-GAP-03369"},"M21-GAP-03369":{"line":6624,"offset":1188952,"length":200,"previous":"M21-GAP-03368","next":"M21-GAP-03370"},"M21-GAP-03370":{"line":6625,"offset":1189152,"length":189,"previous":"M21-GAP-03369","next":"M21-GAP-03371"},"M21-GAP-03371":{"line":6626,"offset":1189341,"length":199,"previous":"M21-GAP-03370","next":"M21-GAP-03372"},"M21-GAP-03372":{"line":6627,"offset":1189540,"length":188,"previous":"M21-GAP-03371","next":"M21-GAP-03373"},"M21-GAP-03373":{"line":6628,"offset":1189728,"length":181,"previous":"M21-GAP-03372","next":"M21-GAP-03374"},"M21-GAP-03374":{"line":6629,"offset":1189909,"length":185,"previous":"M21-GAP-03373","next":"M21-GAP-03375"},"M21-GAP-03375":{"line":6630,"offset":1190094,"length":192,"previous":"M21-GAP-03374","next":"M21-GAP-03376"},"M21-GAP-03376":{"line":6631,"offset":1190286,"length":181,"previous":"M21-GAP-03375","next":"M21-GAP-03377"},"M21-GAP-03377":{"line":6632,"offset":1190467,"length":169,"previous":"M21-GAP-03376","next":"M21-GAP-03378"},"M21-GAP-03378":{"line":6633,"offset":1190636,"length":178,"previous":"M21-GAP-03377","next":"M21-GAP-03379"},"M21-GAP-03379":{"line":6634,"offset":1190814,"length":169,"previous":"M21-GAP-03378","next":"M21-GAP-03380"},"M21-GAP-03380":{"line":6635,"offset":1190983,"length":168,"previous":"M21-GAP-03379","next":"M21-GAP-03381"},"M21-GAP-03381":{"line":6636,"offset":1191151,"length":175,"previous":"M21-GAP-03380","next":"M21-GAP-03382"},"M21-GAP-03382":{"line":6637,"offset":1191326,"length":187,"previous":"M21-GAP-03381","next":"M21-GAP-03383"},"M21-GAP-03383":{"line":6638,"offset":1191513,"length":177,"previous":"M21-GAP-03382","next":"M21-GAP-03384"},"M21-GAP-03384":{"line":6639,"offset":1191690,"length":183,"previous":"M21-GAP-03383","next":"M21-GAP-03385"},"M21-GAP-03385":{"line":6640,"offset":1191873,"length":182,"previous":"M21-GAP-03384","next":"M21-GAP-03386"},"M21-GAP-03386":{"line":6641,"offset":1192055,"length":170,"previous":"M21-GAP-03385","next":"M21-GAP-03387"},"M21-GAP-03387":{"line":6642,"offset":1192225,"length":169,"previous":"M21-GAP-03386","next":"M21-GAP-03388"},"M21-GAP-03388":{"line":6643,"offset":1192394,"length":179,"previous":"M21-GAP-03387","next":"M21-GAP-03389"},"M21-GAP-03389":{"line":6644,"offset":1192573,"length":165,"previous":"M21-GAP-03388","next":"M21-GAP-03390"},"M21-GAP-03390":{"line":6645,"offset":1192738,"length":166,"previous":"M21-GAP-03389","next":"M21-GAP-03391"},"M21-GAP-03391":{"line":6646,"offset":1192904,"length":184,"previous":"M21-GAP-03390","next":"M21-GAP-03392"},"M21-GAP-03392":{"line":6647,"offset":1193088,"length":188,"previous":"M21-GAP-03391","next":"M21-GAP-03393"},"M21-GAP-03393":{"line":6648,"offset":1193276,"length":180,"previous":"M21-GAP-03392","next":"M21-GAP-03394"},"M21-GAP-03394":{"line":6649,"offset":1193456,"length":198,"previous":"M21-GAP-03393","next":"M21-GAP-03395"},"M21-GAP-03395":{"line":6650,"offset":1193654,"length":180,"previous":"M21-GAP-03394","next":"M21-GAP-03396"},"M21-GAP-03396":{"line":6651,"offset":1193834,"length":187,"previous":"M21-GAP-03395","next":"M21-GAP-03397"},"M21-GAP-03397":{"line":6652,"offset":1194021,"length":184,"previous":"M21-GAP-03396","next":"M21-GAP-03398"},"M21-GAP-03398":{"line":6653,"offset":1194205,"length":179,"previous":"M21-GAP-03397","next":"M21-GAP-03399"},"M21-GAP-03399":{"line":6654,"offset":1194384,"length":179,"previous":"M21-GAP-03398","next":"M21-GAP-03400"},"M21-GAP-03400":{"line":6655,"offset":1194563,"length":164,"previous":"M21-GAP-03399","next":"M21-GAP-03401"},"M21-GAP-03401":{"line":6656,"offset":1194727,"length":166,"previous":"M21-GAP-03400","next":"M21-GAP-03402"},"M21-GAP-03402":{"line":6657,"offset":1194893,"length":184,"previous":"M21-GAP-03401","next":"M21-GAP-03403"},"M21-GAP-03403":{"line":6658,"offset":1195077,"length":178,"previous":"M21-GAP-03402","next":"M21-GAP-03404"},"M21-GAP-03404":{"line":6659,"offset":1195255,"length":184,"previous":"M21-GAP-03403","next":"M21-GAP-03405"},"M21-GAP-03405":{"line":6660,"offset":1195439,"length":180,"previous":"M21-GAP-03404","next":"M21-GAP-03406"},"M21-GAP-03406":{"line":6661,"offset":1195619,"length":189,"previous":"M21-GAP-03405","next":"M21-GAP-03407"},"M21-GAP-03407":{"line":6662,"offset":1195808,"length":173,"previous":"M21-GAP-03406","next":"M21-GAP-03408"},"M21-GAP-03408":{"line":6663,"offset":1195981,"length":189,"previous":"M21-GAP-03407","next":"M21-GAP-03409"},"M21-GAP-03409":{"line":6664,"offset":1196170,"length":187,"previous":"M21-GAP-03408","next":"M21-GAP-03410"},"M21-GAP-03410":{"line":6665,"offset":1196357,"length":190,"previous":"M21-GAP-03409","next":"M21-GAP-03411"},"M21-GAP-03411":{"line":6666,"offset":1196547,"length":182,"previous":"M21-GAP-03410","next":"M21-GAP-03412"},"M21-GAP-03412":{"line":6667,"offset":1196729,"length":171,"previous":"M21-GAP-03411","next":"M21-GAP-03413"},"M21-GAP-03413":{"line":6668,"offset":1196900,"length":173,"previous":"M21-GAP-03412","next":"M21-GAP-03414"},"M21-GAP-03414":{"line":6669,"offset":1197073,"length":176,"previous":"M21-GAP-03413","next":"M21-GAP-03415"},"M21-GAP-03415":{"line":6670,"offset":1197249,"length":181,"previous":"M21-GAP-03414","next":"M21-GAP-03416"},"M21-GAP-03416":{"line":6671,"offset":1197430,"length":179,"previous":"M21-GAP-03415","next":"M21-GAP-03417"},"M21-GAP-03417":{"line":6672,"offset":1197609,"length":187,"previous":"M21-GAP-03416","next":"M21-GAP-03418"},"M21-GAP-03418":{"line":6673,"offset":1197796,"length":179,"previous":"M21-GAP-03417","next":"M21-GAP-03419"},"M21-GAP-03419":{"line":6674,"offset":1197975,"length":186,"previous":"M21-GAP-03418","next":"M21-GAP-03420"},"M21-GAP-03420":{"line":6675,"offset":1198161,"length":183,"previous":"M21-GAP-03419","next":"M21-GAP-03421"},"M21-GAP-03421":{"line":6676,"offset":1198344,"length":183,"previous":"M21-GAP-03420","next":"M21-GAP-03422"},"M21-GAP-03422":{"line":6677,"offset":1198527,"length":183,"previous":"M21-GAP-03421","next":"M21-GAP-03423"},"M21-GAP-03423":{"line":6678,"offset":1198710,"length":185,"previous":"M21-GAP-03422","next":"M21-GAP-03424"},"M21-GAP-03424":{"line":6679,"offset":1198895,"length":183,"previous":"M21-GAP-03423","next":"M21-GAP-03425"},"M21-GAP-03425":{"line":6680,"offset":1199078,"length":186,"previous":"M21-GAP-03424","next":"M21-GAP-03426"},"M21-GAP-03426":{"line":6681,"offset":1199264,"length":186,"previous":"M21-GAP-03425","next":"M21-GAP-03427"},"M21-GAP-03427":{"line":6682,"offset":1199450,"length":173,"previous":"M21-GAP-03426","next":"M21-GAP-03428"},"M21-GAP-03428":{"line":6683,"offset":1199623,"length":195,"previous":"M21-GAP-03427","next":"M21-GAP-03429"},"M21-GAP-03429":{"line":6684,"offset":1199818,"length":198,"previous":"M21-GAP-03428","next":"M21-GAP-03430"},"M21-GAP-03430":{"line":6685,"offset":1200016,"length":198,"previous":"M21-GAP-03429","next":"M21-GAP-03431"},"M21-GAP-03431":{"line":6686,"offset":1200214,"length":196,"previous":"M21-GAP-03430","next":"M21-GAP-03432"},"M21-GAP-03432":{"line":6687,"offset":1200410,"length":198,"previous":"M21-GAP-03431","next":"M21-GAP-03433"},"M21-GAP-03433":{"line":6688,"offset":1200608,"length":197,"previous":"M21-GAP-03432","next":"M21-GAP-03434"},"M21-GAP-03434":{"line":6689,"offset":1200805,"length":213,"previous":"M21-GAP-03433","next":"M21-GAP-03435"},"M21-GAP-03435":{"line":6690,"offset":1201018,"length":202,"previous":"M21-GAP-03434","next":"M21-GAP-03436"},"M21-GAP-03436":{"line":6691,"offset":1201220,"length":216,"previous":"M21-GAP-03435","next":"M21-GAP-03437"},"M21-GAP-03437":{"line":6692,"offset":1201436,"length":205,"previous":"M21-GAP-03436","next":"M21-GAP-03438"},"M21-GAP-03438":{"line":6693,"offset":1201641,"length":215,"previous":"M21-GAP-03437","next":"M21-GAP-03439"},"M21-GAP-03439":{"line":6694,"offset":1201856,"length":204,"previous":"M21-GAP-03438","next":"M21-GAP-03440"},"M21-GAP-03440":{"line":6695,"offset":1202060,"length":201,"previous":"M21-GAP-03439","next":"M21-GAP-03441"},"M21-GAP-03441":{"line":6696,"offset":1202261,"length":208,"previous":"M21-GAP-03440","next":"M21-GAP-03442"},"M21-GAP-03442":{"line":6697,"offset":1202469,"length":197,"previous":"M21-GAP-03441","next":"M21-GAP-03443"},"M21-GAP-03443":{"line":6698,"offset":1202666,"length":192,"previous":"M21-GAP-03442","next":"M21-GAP-03444"},"M21-GAP-03444":{"line":6699,"offset":1202858,"length":196,"previous":"M21-GAP-03443","next":"M21-GAP-03445"},"M21-GAP-03445":{"line":6700,"offset":1203054,"length":194,"previous":"M21-GAP-03444","next":"M21-GAP-03446"},"M21-GAP-03446":{"line":6701,"offset":1203248,"length":194,"previous":"M21-GAP-03445","next":"M21-GAP-03447"},"M21-GAP-03447":{"line":6702,"offset":1203442,"length":195,"previous":"M21-GAP-03446","next":"M21-GAP-03448"},"M21-GAP-03448":{"line":6703,"offset":1203637,"length":195,"previous":"M21-GAP-03447","next":"M21-GAP-03449"},"M21-GAP-03449":{"line":6704,"offset":1203832,"length":200,"previous":"M21-GAP-03448","next":"M21-GAP-03450"},"M21-GAP-03450":{"line":6705,"offset":1204032,"length":196,"previous":"M21-GAP-03449","next":"M21-GAP-03451"},"M21-GAP-03451":{"line":6706,"offset":1204228,"length":195,"previous":"M21-GAP-03450","next":"M21-GAP-03452"},"M21-GAP-03452":{"line":6707,"offset":1204423,"length":211,"previous":"M21-GAP-03451","next":"M21-GAP-03453"},"M21-GAP-03453":{"line":6708,"offset":1204634,"length":200,"previous":"M21-GAP-03452","next":"M21-GAP-03454"},"M21-GAP-03454":{"line":6709,"offset":1204834,"length":214,"previous":"M21-GAP-03453","next":"M21-GAP-03455"},"M21-GAP-03455":{"line":6710,"offset":1205048,"length":203,"previous":"M21-GAP-03454","next":"M21-GAP-03456"},"M21-GAP-03456":{"line":6711,"offset":1205251,"length":213,"previous":"M21-GAP-03455","next":"M21-GAP-03457"},"M21-GAP-03457":{"line":6712,"offset":1205464,"length":202,"previous":"M21-GAP-03456","next":"M21-GAP-03458"},"M21-GAP-03458":{"line":6713,"offset":1205666,"length":206,"previous":"M21-GAP-03457","next":"M21-GAP-03459"},"M21-GAP-03459":{"line":6714,"offset":1205872,"length":195,"previous":"M21-GAP-03458","next":"M21-GAP-03460"},"M21-GAP-03460":{"line":6715,"offset":1206067,"length":180,"previous":"M21-GAP-03459","next":"M21-GAP-03461"},"M21-GAP-03461":{"line":6716,"offset":1206247,"length":171,"previous":"M21-GAP-03460","next":"M21-GAP-03462"},"M21-GAP-03462":{"line":6717,"offset":1206418,"length":172,"previous":"M21-GAP-03461","next":"M21-GAP-03463"},"M21-GAP-03463":{"line":6718,"offset":1206590,"length":163,"previous":"M21-GAP-03462","next":"M21-GAP-03464"},"M21-GAP-03464":{"line":6719,"offset":1206753,"length":186,"previous":"M21-GAP-03463","next":"M21-GAP-03465"},"M21-GAP-03465":{"line":6720,"offset":1206939,"length":180,"previous":"M21-GAP-03464","next":"M21-GAP-03466"},"M21-GAP-03466":{"line":6721,"offset":1207119,"length":167,"previous":"M21-GAP-03465","next":"M21-GAP-03467"},"M21-GAP-03467":{"line":6722,"offset":1207286,"length":167,"previous":"M21-GAP-03466","next":"M21-GAP-03468"},"M21-GAP-03468":{"line":6723,"offset":1207453,"length":172,"previous":"M21-GAP-03467","next":"M21-GAP-03469"},"M21-GAP-03469":{"line":6724,"offset":1207625,"length":181,"previous":"M21-GAP-03468","next":"M21-GAP-03470"},"M21-GAP-03470":{"line":6725,"offset":1207806,"length":164,"previous":"M21-GAP-03469","next":"M21-GAP-03471"},"M21-GAP-03471":{"line":6726,"offset":1207970,"length":168,"previous":"M21-GAP-03470","next":"M21-GAP-03472"},"M21-GAP-03472":{"line":6727,"offset":1208138,"length":175,"previous":"M21-GAP-03471","next":"M21-GAP-03473"},"M21-GAP-03473":{"line":6728,"offset":1208313,"length":176,"previous":"M21-GAP-03472","next":"M21-GAP-03474"},"M21-GAP-03474":{"line":6729,"offset":1208489,"length":175,"previous":"M21-GAP-03473","next":"M21-GAP-03475"},"M21-GAP-03475":{"line":6730,"offset":1208664,"length":177,"previous":"M21-GAP-03474","next":"M21-GAP-03476"},"M21-GAP-03476":{"line":6731,"offset":1208841,"length":178,"previous":"M21-GAP-03475","next":"M21-GAP-03477"},"M21-GAP-03477":{"line":6732,"offset":1209019,"length":179,"previous":"M21-GAP-03476","next":"M21-GAP-03478"},"M21-GAP-03478":{"line":6733,"offset":1209198,"length":181,"previous":"M21-GAP-03477","next":"M21-GAP-03479"},"M21-GAP-03479":{"line":6734,"offset":1209379,"length":188,"previous":"M21-GAP-03478","next":"M21-GAP-03480"},"M21-GAP-03480":{"line":6735,"offset":1209567,"length":186,"previous":"M21-GAP-03479","next":"M21-GAP-03481"},"M21-GAP-03481":{"line":6736,"offset":1209753,"length":187,"previous":"M21-GAP-03480","next":"M21-GAP-03482"},"M21-GAP-03482":{"line":6737,"offset":1209940,"length":198,"previous":"M21-GAP-03481","next":"M21-GAP-03483"},"M21-GAP-03483":{"line":6738,"offset":1210138,"length":187,"previous":"M21-GAP-03482","next":"M21-GAP-03484"},"M21-GAP-03484":{"line":6739,"offset":1210325,"length":201,"previous":"M21-GAP-03483","next":"M21-GAP-03485"},"M21-GAP-03485":{"line":6740,"offset":1210526,"length":190,"previous":"M21-GAP-03484","next":"M21-GAP-03486"},"M21-GAP-03486":{"line":6741,"offset":1210716,"length":200,"previous":"M21-GAP-03485","next":"M21-GAP-03487"},"M21-GAP-03487":{"line":6742,"offset":1210916,"length":189,"previous":"M21-GAP-03486","next":"M21-GAP-03488"},"M21-GAP-03488":{"line":6743,"offset":1211105,"length":193,"previous":"M21-GAP-03487","next":"M21-GAP-03489"},"M21-GAP-03489":{"line":6744,"offset":1211298,"length":182,"previous":"M21-GAP-03488","next":"M21-GAP-03490"},"M21-GAP-03490":{"line":6745,"offset":1211480,"length":171,"previous":"M21-GAP-03489","next":"M21-GAP-03491"},"M21-GAP-03491":{"line":6746,"offset":1211651,"length":176,"previous":"M21-GAP-03490","next":"M21-GAP-03492"},"M21-GAP-03492":{"line":6747,"offset":1211827,"length":171,"previous":"M21-GAP-03491","next":"M21-GAP-03493"},"M21-GAP-03493":{"line":6748,"offset":1211998,"length":171,"previous":"M21-GAP-03492","next":"M21-GAP-03494"},"M21-GAP-03494":{"line":6749,"offset":1212169,"length":201,"previous":"M21-GAP-03493","next":"M21-GAP-03495"},"M21-GAP-03495":{"line":6750,"offset":1212370,"length":178,"previous":"M21-GAP-03494","next":"M21-GAP-03496"},"M21-GAP-03496":{"line":6751,"offset":1212548,"length":199,"previous":"M21-GAP-03495","next":"M21-GAP-03497"},"M21-GAP-03497":{"line":6752,"offset":1212747,"length":168,"previous":"M21-GAP-03496","next":"M21-GAP-03498"},"M21-GAP-03498":{"line":6753,"offset":1212915,"length":178,"previous":"M21-GAP-03497","next":"M21-GAP-03499"},"M21-GAP-03499":{"line":6754,"offset":1213093,"length":171,"previous":"M21-GAP-03498","next":"M21-GAP-03500"},"M21-GAP-03500":{"line":6755,"offset":1213264,"length":164,"previous":"M21-GAP-03499","next":"M21-GAP-03501"},"M21-GAP-03501":{"line":6756,"offset":1213428,"length":177,"previous":"M21-GAP-03500","next":"M21-GAP-03502"},"M21-GAP-03502":{"line":6757,"offset":1213605,"length":177,"previous":"M21-GAP-03501","next":"M21-GAP-03503"},"M21-GAP-03503":{"line":6758,"offset":1213782,"length":190,"previous":"M21-GAP-03502","next":"M21-GAP-03504"},"M21-GAP-03504":{"line":6759,"offset":1213972,"length":188,"previous":"M21-GAP-03503","next":"M21-GAP-03505"},"M21-GAP-03505":{"line":6760,"offset":1214160,"length":190,"previous":"M21-GAP-03504","next":"M21-GAP-03506"},"M21-GAP-03506":{"line":6761,"offset":1214350,"length":190,"previous":"M21-GAP-03505","next":"M21-GAP-03507"},"M21-GAP-03507":{"line":6762,"offset":1214540,"length":189,"previous":"M21-GAP-03506","next":"M21-GAP-03508"},"M21-GAP-03508":{"line":6763,"offset":1214729,"length":205,"previous":"M21-GAP-03507","next":"M21-GAP-03509"},"M21-GAP-03509":{"line":6764,"offset":1214934,"length":194,"previous":"M21-GAP-03508","next":"M21-GAP-03510"},"M21-GAP-03510":{"line":6765,"offset":1215128,"length":208,"previous":"M21-GAP-03509","next":"M21-GAP-03511"},"M21-GAP-03511":{"line":6766,"offset":1215336,"length":197,"previous":"M21-GAP-03510","next":"M21-GAP-03512"},"M21-GAP-03512":{"line":6767,"offset":1215533,"length":207,"previous":"M21-GAP-03511","next":"M21-GAP-03513"},"M21-GAP-03513":{"line":6768,"offset":1215740,"length":196,"previous":"M21-GAP-03512","next":"M21-GAP-03514"},"M21-GAP-03514":{"line":6769,"offset":1215936,"length":200,"previous":"M21-GAP-03513","next":"M21-GAP-03515"},"M21-GAP-03515":{"line":6770,"offset":1216136,"length":189,"previous":"M21-GAP-03514","next":"M21-GAP-03516"},"M21-GAP-03516":{"line":6771,"offset":1216325,"length":177,"previous":"M21-GAP-03515","next":"M21-GAP-03517"},"M21-GAP-03517":{"line":6772,"offset":1216502,"length":184,"previous":"M21-GAP-03516","next":"M21-GAP-03518"},"M21-GAP-03518":{"line":6773,"offset":1216686,"length":180,"previous":"M21-GAP-03517","next":"M21-GAP-03519"},"M21-GAP-03519":{"line":6774,"offset":1216866,"length":179,"previous":"M21-GAP-03518","next":"M21-GAP-03520"},"M21-GAP-03520":{"line":6775,"offset":1217045,"length":174,"previous":"M21-GAP-03519","next":"M21-GAP-03521"},"M21-GAP-03521":{"line":6776,"offset":1217219,"length":166,"previous":"M21-GAP-03520","next":"M21-GAP-03522"},"M21-GAP-03522":{"line":6777,"offset":1217385,"length":173,"previous":"M21-GAP-03521","next":"M21-GAP-03523"},"M21-GAP-03523":{"line":6778,"offset":1217558,"length":179,"previous":"M21-GAP-03522","next":"M21-GAP-03524"},"M21-GAP-03524":{"line":6779,"offset":1217737,"length":166,"previous":"M21-GAP-03523","next":"M21-GAP-03525"},"M21-GAP-03525":{"line":6780,"offset":1217903,"length":188,"previous":"M21-GAP-03524","next":"M21-GAP-03526"},"M21-GAP-03526":{"line":6781,"offset":1218091,"length":191,"previous":"M21-GAP-03525","next":"M21-GAP-03527"},"M21-GAP-03527":{"line":6782,"offset":1218282,"length":207,"previous":"M21-GAP-03526","next":"M21-GAP-03528"},"M21-GAP-03528":{"line":6783,"offset":1218489,"length":196,"previous":"M21-GAP-03527","next":"M21-GAP-03529"},"M21-GAP-03529":{"line":6784,"offset":1218685,"length":210,"previous":"M21-GAP-03528","next":"M21-GAP-03530"},"M21-GAP-03530":{"line":6785,"offset":1218895,"length":199,"previous":"M21-GAP-03529","next":"M21-GAP-03531"},"M21-GAP-03531":{"line":6786,"offset":1219094,"length":209,"previous":"M21-GAP-03530","next":"M21-GAP-03532"},"M21-GAP-03532":{"line":6787,"offset":1219303,"length":198,"previous":"M21-GAP-03531","next":"M21-GAP-03533"},"M21-GAP-03533":{"line":6788,"offset":1219501,"length":190,"previous":"M21-GAP-03532","next":"M21-GAP-03534"},"M21-GAP-03534":{"line":6789,"offset":1219691,"length":179,"previous":"M21-GAP-03533","next":"M21-GAP-03535"},"M21-GAP-03535":{"line":6790,"offset":1219870,"length":170,"previous":"M21-GAP-03534","next":"M21-GAP-03536"},"M21-GAP-03536":{"line":6791,"offset":1220040,"length":185,"previous":"M21-GAP-03535","next":"M21-GAP-03537"},"M21-GAP-03537":{"line":6792,"offset":1220225,"length":178,"previous":"M21-GAP-03536","next":"M21-GAP-03538"},"M21-GAP-03538":{"line":6793,"offset":1220403,"length":178,"previous":"M21-GAP-03537","next":"M21-GAP-03539"},"M21-GAP-03539":{"line":6794,"offset":1220581,"length":170,"previous":"M21-GAP-03538","next":"M21-GAP-03540"},"M21-GAP-03540":{"line":6795,"offset":1220751,"length":170,"previous":"M21-GAP-03539","next":"M21-GAP-03541"},"M21-GAP-03541":{"line":6796,"offset":1220921,"length":176,"previous":"M21-GAP-03540","next":"M21-GAP-03542"},"M21-GAP-03542":{"line":6797,"offset":1221097,"length":191,"previous":"M21-GAP-03541","next":"M21-GAP-03543"},"M21-GAP-03543":{"line":6798,"offset":1221288,"length":179,"previous":"M21-GAP-03542","next":"M21-GAP-03544"},"M21-GAP-03544":{"line":6799,"offset":1221467,"length":169,"previous":"M21-GAP-03543","next":"M21-GAP-03545"},"M21-GAP-03545":{"line":6800,"offset":1221636,"length":174,"previous":"M21-GAP-03544","next":"M21-GAP-03546"},"M21-GAP-03546":{"line":6801,"offset":1221810,"length":172,"previous":"M21-GAP-03545","next":"M21-GAP-03547"},"M21-GAP-03547":{"line":6802,"offset":1221982,"length":191,"previous":"M21-GAP-03546","next":"M21-GAP-03548"},"M21-GAP-03548":{"line":6803,"offset":1222173,"length":179,"previous":"M21-GAP-03547","next":"M21-GAP-03549"},"M21-GAP-03549":{"line":6804,"offset":1222352,"length":166,"previous":"M21-GAP-03548","next":"M21-GAP-03550"},"M21-GAP-03550":{"line":6805,"offset":1222518,"length":178,"previous":"M21-GAP-03549","next":"M21-GAP-03551"},"M21-GAP-03551":{"line":6806,"offset":1222696,"length":176,"previous":"M21-GAP-03550","next":"M21-GAP-03552"},"M21-GAP-03552":{"line":6807,"offset":1222872,"length":181,"previous":"M21-GAP-03551","next":"M21-GAP-03553"},"M21-GAP-03553":{"line":6808,"offset":1223053,"length":177,"previous":"M21-GAP-03552","next":"M21-GAP-03554"},"M21-GAP-03554":{"line":6809,"offset":1223230,"length":182,"previous":"M21-GAP-03553","next":"M21-GAP-03555"},"M21-GAP-03555":{"line":6810,"offset":1223412,"length":179,"previous":"M21-GAP-03554","next":"M21-GAP-03556"},"M21-GAP-03556":{"line":6811,"offset":1223591,"length":208,"previous":"M21-GAP-03555","next":"M21-GAP-03557"},"M21-GAP-03557":{"line":6812,"offset":1223799,"length":177,"previous":"M21-GAP-03556","next":"M21-GAP-03558"},"M21-GAP-03558":{"line":6813,"offset":1223976,"length":177,"previous":"M21-GAP-03557","next":"M21-GAP-03559"},"M21-GAP-03559":{"line":6814,"offset":1224153,"length":172,"previous":"M21-GAP-03558","next":"M21-GAP-03560"},"M21-GAP-03560":{"line":6815,"offset":1224325,"length":166,"previous":"M21-GAP-03559","next":"M21-GAP-03561"},"M21-GAP-03561":{"line":6816,"offset":1224491,"length":158,"previous":"M21-GAP-03560","next":"M21-GAP-03562"},"M21-GAP-03562":{"line":6817,"offset":1224649,"length":165,"previous":"M21-GAP-03561","next":"M21-GAP-03563"},"M21-GAP-03563":{"line":6818,"offset":1224814,"length":155,"previous":"M21-GAP-03562","next":"M21-GAP-03564"},"M21-GAP-03564":{"line":6819,"offset":1224969,"length":154,"previous":"M21-GAP-03563","next":"M21-GAP-03565"},"M21-GAP-03565":{"line":6820,"offset":1225123,"length":153,"previous":"M21-GAP-03564","next":"M21-GAP-03566"},"M21-GAP-03566":{"line":6821,"offset":1225276,"length":153,"previous":"M21-GAP-03565","next":"M21-GAP-03567"},"M21-GAP-03567":{"line":6822,"offset":1225429,"length":150,"previous":"M21-GAP-03566","next":"M21-GAP-03568"},"M21-GAP-03568":{"line":6823,"offset":1225579,"length":161,"previous":"M21-GAP-03567","next":"M21-GAP-03569"},"M21-GAP-03569":{"line":6824,"offset":1225740,"length":154,"previous":"M21-GAP-03568","next":"M21-GAP-03570"},"M21-GAP-03570":{"line":6825,"offset":1225894,"length":156,"previous":"M21-GAP-03569","next":"M21-GAP-03571"},"M21-GAP-03571":{"line":6826,"offset":1226050,"length":156,"previous":"M21-GAP-03570","next":"M21-GAP-03572"},"M21-GAP-03572":{"line":6827,"offset":1226206,"length":152,"previous":"M21-GAP-03571","next":"M21-GAP-03573"},"M21-GAP-03573":{"line":6828,"offset":1226358,"length":158,"previous":"M21-GAP-03572","next":"M21-GAP-03574"},"M21-GAP-03574":{"line":6829,"offset":1226516,"length":157,"previous":"M21-GAP-03573","next":"M21-GAP-03575"},"M21-GAP-03575":{"line":6830,"offset":1226673,"length":149,"previous":"M21-GAP-03574","next":"M21-GAP-03576"},"M21-GAP-03576":{"line":6831,"offset":1226822,"length":153,"previous":"M21-GAP-03575","next":"M21-GAP-03577"},"M21-GAP-03577":{"line":6832,"offset":1226975,"length":149,"previous":"M21-GAP-03576","next":"M21-GAP-03578"},"M21-GAP-03578":{"line":6833,"offset":1227124,"length":166,"previous":"M21-GAP-03577","next":"M21-GAP-03579"},"M21-GAP-03579":{"line":6834,"offset":1227290,"length":163,"previous":"M21-GAP-03578","next":"M21-GAP-03580"},"M21-GAP-03580":{"line":6835,"offset":1227453,"length":171,"previous":"M21-GAP-03579","next":"M21-GAP-03581"},"M21-GAP-03581":{"line":6836,"offset":1227624,"length":167,"previous":"M21-GAP-03580","next":"M21-GAP-03582"},"M21-GAP-03582":{"line":6837,"offset":1227791,"length":167,"previous":"M21-GAP-03581","next":"M21-GAP-03583"},"M21-GAP-03583":{"line":6838,"offset":1227958,"length":167,"previous":"M21-GAP-03582","next":"M21-GAP-03584"},"M21-GAP-03584":{"line":6839,"offset":1228125,"length":160,"previous":"M21-GAP-03583","next":"M21-GAP-03585"},"M21-GAP-03585":{"line":6840,"offset":1228285,"length":159,"previous":"M21-GAP-03584","next":"M21-GAP-03586"},"M21-GAP-03586":{"line":6841,"offset":1228444,"length":166,"previous":"M21-GAP-03585","next":"M21-GAP-03587"},"M21-GAP-03587":{"line":6842,"offset":1228610,"length":164,"previous":"M21-GAP-03586","next":"M21-GAP-03588"},"M21-GAP-03588":{"line":6843,"offset":1228774,"length":167,"previous":"M21-GAP-03587","next":"M21-GAP-03589"},"M21-GAP-03589":{"line":6844,"offset":1228941,"length":166,"previous":"M21-GAP-03588","next":"M21-GAP-03590"},"M21-GAP-03590":{"line":6845,"offset":1229107,"length":170,"previous":"M21-GAP-03589","next":"M21-GAP-03591"},"M21-GAP-03591":{"line":6846,"offset":1229277,"length":167,"previous":"M21-GAP-03590","next":"M21-GAP-03592"},"M21-GAP-03592":{"line":6847,"offset":1229444,"length":166,"previous":"M21-GAP-03591","next":"M21-GAP-03593"},"M21-GAP-03593":{"line":6848,"offset":1229610,"length":162,"previous":"M21-GAP-03592","next":"M21-GAP-03594"},"M21-GAP-03594":{"line":6849,"offset":1229772,"length":156,"previous":"M21-GAP-03593","next":"M21-GAP-03595"},"M21-GAP-03595":{"line":6850,"offset":1229928,"length":152,"previous":"M21-GAP-03594","next":"M21-GAP-03596"},"M21-GAP-03596":{"line":6851,"offset":1230080,"length":161,"previous":"M21-GAP-03595","next":"M21-GAP-03597"},"M21-GAP-03597":{"line":6852,"offset":1230241,"length":150,"previous":"M21-GAP-03596","next":"M21-GAP-03598"},"M21-GAP-03598":{"line":6853,"offset":1230391,"length":157,"previous":"M21-GAP-03597","next":"M21-GAP-03599"},"M21-GAP-03599":{"line":6854,"offset":1230548,"length":157,"previous":"M21-GAP-03598","next":"M21-GAP-03600"},"M21-GAP-03600":{"line":6855,"offset":1230705,"length":157,"previous":"M21-GAP-03599","next":"M21-GAP-03601"},"M21-GAP-03601":{"line":6856,"offset":1230862,"length":149,"previous":"M21-GAP-03600","next":"M21-GAP-03602"},"M21-GAP-03602":{"line":6857,"offset":1231011,"length":155,"previous":"M21-GAP-03601","next":"M21-GAP-03603"},"M21-GAP-03603":{"line":6858,"offset":1231166,"length":156,"previous":"M21-GAP-03602","next":"M21-GAP-03604"},"M21-GAP-03604":{"line":6859,"offset":1231322,"length":153,"previous":"M21-GAP-03603","next":"M21-GAP-03605"},"M21-GAP-03605":{"line":6860,"offset":1231475,"length":156,"previous":"M21-GAP-03604","next":"M21-GAP-03606"},"M21-GAP-03606":{"line":6861,"offset":1231631,"length":155,"previous":"M21-GAP-03605","next":"M21-GAP-03607"},"M21-GAP-03607":{"line":6862,"offset":1231786,"length":160,"previous":"M21-GAP-03606","next":"M21-GAP-03608"},"M21-GAP-03608":{"line":6863,"offset":1231946,"length":156,"previous":"M21-GAP-03607","next":"M21-GAP-03609"},"M21-GAP-03609":{"line":6864,"offset":1232102,"length":154,"previous":"M21-GAP-03608","next":"M21-GAP-03610"},"M21-GAP-03610":{"line":6865,"offset":1232256,"length":156,"previous":"M21-GAP-03609","next":"M21-GAP-03611"},"M21-GAP-03611":{"line":6866,"offset":1232412,"length":151,"previous":"M21-GAP-03610","next":"M21-GAP-03612"},"M21-GAP-03612":{"line":6867,"offset":1232563,"length":152,"previous":"M21-GAP-03611","next":"M21-GAP-03613"},"M21-GAP-03613":{"line":6868,"offset":1232715,"length":157,"previous":"M21-GAP-03612","next":"M21-GAP-03614"},"M21-GAP-03614":{"line":6869,"offset":1232872,"length":165,"previous":"M21-GAP-03613","next":"M21-GAP-03615"},"M21-GAP-03615":{"line":6870,"offset":1233037,"length":159,"previous":"M21-GAP-03614","next":"M21-GAP-03616"},"M21-GAP-03616":{"line":6871,"offset":1233196,"length":172,"previous":"M21-GAP-03615","next":"M21-GAP-03617"},"M21-GAP-03617":{"line":6872,"offset":1233368,"length":166,"previous":"M21-GAP-03616","next":"M21-GAP-03618"},"M21-GAP-03618":{"line":6873,"offset":1233534,"length":157,"previous":"M21-GAP-03617","next":"M21-GAP-03619"},"M21-GAP-03619":{"line":6874,"offset":1233691,"length":159,"previous":"M21-GAP-03618","next":"M21-GAP-03620"},"M21-GAP-03620":{"line":6875,"offset":1233850,"length":173,"previous":"M21-GAP-03619","next":"M21-GAP-03621"},"M21-GAP-03621":{"line":6876,"offset":1234023,"length":166,"previous":"M21-GAP-03620","next":"M21-GAP-03622"},"M21-GAP-03622":{"line":6877,"offset":1234189,"length":173,"previous":"M21-GAP-03621","next":"M21-GAP-03623"},"M21-GAP-03623":{"line":6878,"offset":1234362,"length":165,"previous":"M21-GAP-03622","next":"M21-GAP-03624"},"M21-GAP-03624":{"line":6879,"offset":1234527,"length":173,"previous":"M21-GAP-03623","next":"M21-GAP-03625"},"M21-GAP-03625":{"line":6880,"offset":1234700,"length":165,"previous":"M21-GAP-03624","next":"M22-GAP-00001"},"M22-GAP-00001":{"line":6881,"offset":1234865,"length":166,"previous":"M21-GAP-03625","next":"M22-GAP-00002"},"M22-GAP-00002":{"line":6882,"offset":1235031,"length":180,"previous":"M22-GAP-00001","next":"M22-GAP-00003"},"M22-GAP-00003":{"line":6883,"offset":1235211,"length":172,"previous":"M22-GAP-00002","next":"M22-GAP-00004"},"M22-GAP-00004":{"line":6884,"offset":1235383,"length":155,"previous":"M22-GAP-00003","next":"M22-GAP-00005"},"M22-GAP-00005":{"line":6885,"offset":1235538,"length":159,"previous":"M22-GAP-00004","next":"M22-GAP-00006"},"M22-GAP-00006":{"line":6886,"offset":1235697,"length":159,"previous":"M22-GAP-00005","next":"M22-GAP-00007"},"M22-GAP-00007":{"line":6887,"offset":1235856,"length":164,"previous":"M22-GAP-00006","next":"M22-GAP-00008"},"M22-GAP-00008":{"line":6888,"offset":1236020,"length":154,"previous":"M22-GAP-00007","next":"M22-GAP-00009"},"M22-GAP-00009":{"line":6889,"offset":1236174,"length":157,"previous":"M22-GAP-00008","next":"M22-GAP-00010"},"M22-GAP-00010":{"line":6890,"offset":1236331,"length":157,"previous":"M22-GAP-00009","next":"M22-GAP-00011"},"M22-GAP-00011":{"line":6891,"offset":1236488,"length":157,"previous":"M22-GAP-00010","next":"M22-GAP-00012"},"M22-GAP-00012":{"line":6892,"offset":1236645,"length":155,"previous":"M22-GAP-00011","next":"M22-GAP-00013"},"M22-GAP-00013":{"line":6893,"offset":1236800,"length":163,"previous":"M22-GAP-00012","next":"M22-GAP-00014"},"M22-GAP-00014":{"line":6894,"offset":1236963,"length":154,"previous":"M22-GAP-00013","next":"M22-GAP-00015"},"M22-GAP-00015":{"line":6895,"offset":1237117,"length":155,"previous":"M22-GAP-00014","next":"M22-GAP-00016"},"M22-GAP-00016":{"line":6896,"offset":1237272,"length":158,"previous":"M22-GAP-00015","next":"M22-GAP-00017"},"M22-GAP-00017":{"line":6897,"offset":1237430,"length":155,"previous":"M22-GAP-00016","next":"M22-GAP-00018"},"M22-GAP-00018":{"line":6898,"offset":1237585,"length":162,"previous":"M22-GAP-00017","next":"M22-GAP-00019"},"M22-GAP-00019":{"line":6899,"offset":1237747,"length":154,"previous":"M22-GAP-00018","next":null}}} diff --git a/tests/golden/M16-GAP-00175/anim-driver-button-edit-desktop-report.json b/tests/golden/M16-GAP-00175/anim-driver-button-edit-desktop-report.json new file mode 100644 index 00000000..dba9ed9e --- /dev/null +++ b/tests/golden/M16-GAP-00175/anim-driver-button-edit-desktop-report.json @@ -0,0 +1,22 @@ +{ + "blenderVersion": "5.2.0 LTS", + "drivers": [ + { + "expression": "frame * 2.5 + 1.25", + "index": 0, + "path": "[\"drive_target\"]", + "type": "SCRIPTED", + "variableCount": 0 + } + ], + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00175-operator-anim.driver_button_edit.blend", + "fixtureSha256": "40ee0435bc330c7d1baa8d40150f2cc4f62ec4cfd195cce2e0e73ad006f7131a", + "mainMutation": "NONE", + "operation": "ANIM_DRIVER_BUTTON_EDIT_DESKTOP", + "operatorStatus": "INTERFACE", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00175", + "value": 3.75 +} diff --git a/tests/golden/M16-GAP-00175/anim-driver-button-edit-local-exact-report.json b/tests/golden/M16-GAP-00175/anim-driver-button-edit-local-exact-report.json new file mode 100644 index 00000000..9936243e --- /dev/null +++ b/tests/golden/M16-GAP-00175/anim-driver-button-edit-local-exact-report.json @@ -0,0 +1,40 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00175", + "operation": "ANIM_DRIVER_BUTTON_EDIT_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00175-operator-anim.driver_button_edit.blend", + "sha256": "40ee0435bc330c7d1baa8d40150f2cc4f62ec4cfd195cce2e0e73ad006f7131a" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00175/anim-driver-button-edit-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "INTERFACE", + "mainMutation": "NONE" + }, + "wasm": { + "status": "EXACT", + "objectId": "object:WebGapAnimDriverButtonEditObject", + "drivers": [ + { + "arrayIndex": 0, + "editable": true, + "enabled": true, + "expression": "frame * 2.5 + 1.25", + "flags": 8, + "influence": 0, + "path": "[\"drive_target\"]", + "type": "SCRIPTED", + "typeCode": 1, + "variables": [] + } + ] + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00176" +} diff --git a/tests/golden/M16-GAP-00175/manifest.json b/tests/golden/M16-GAP-00175/manifest.json new file mode 100644 index 00000000..f2f05f5c --- /dev/null +++ b/tests/golden/M16-GAP-00175/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00175", + "parentTask": "M16-GAP-00174", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_DRIVER_BUTTON_EDIT_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00174/manifest.json", + "sha256": "5905f9176a5d6c9ce6a6fb755bd1b8f7ccdc2d08f81b3444eea660341d180de9" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00175-operator-anim.driver_button_edit.blend", + "sha256": "40ee0435bc330c7d1baa8d40150f2cc4f62ec4cfd195cce2e0e73ad006f7131a" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00175.py", + "sha256": "e4edbf58ccda3bcd61d4cb4fa2d80c2f68bad6313c94bc0c84115eaa1a4b12be" + }, + "desktopChecker": { + "path": "tools/web/check-action-driver-button-edit-desktop.py", + "sha256": "864c46ed3df66b0341660e715c6609d845851dc71afa7bd96348e19bce0db530" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "da24b371cbc7c8d0c75f0f0e133ea51e14bfee3730b810ba75d39ee47047c64f" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "8824ba3dfb4090b85dc679a583d263b4bdb190a47978f72f3c11f6b565fdacaf" + }, + "protocol": { + "path": "web/protocol/editor-workflow.ts", + "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" + }, + "sceneIrProtocol": { + "path": "web/protocol/scene-ir.ts", + "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "9c831d0351ac9d0714cce3b1da748cba416ced3086e3c59595cf24ac4da459ed" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00175/anim-driver-button-edit-desktop-report.json", + "sha256": "0e712a373d6c4d28cb14c38fcd911987c7216466ef52a9d3d19a3ce34e913112" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00175/anim-driver-button-edit-local-exact-report.json", + "sha256": "9bc321582ce9a45951ec4e8a43236b69a571053fc8cf48fe4cdf8b29113aada0" + }, + "status": { + "path": "docs/status/M16-GAP-00175.md", + "sha256": "7a5a2a5e308ce9804db350cc06fbdac36b959892a1f2245531fc515388c0146c" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00175/task-context.json", + "sha256": "80eb9962039ff734c5b7c5a3f908be62c92a5cffd9cfe4de80f19ccd07ad9670" + } + }, + "nextTask": "M16-GAP-00176" +} diff --git a/tests/golden/M16-GAP-00175/task-context.json b/tests/golden/M16-GAP-00175/task-context.json new file mode 100644 index 00000000..c4a8a3ef --- /dev/null +++ b/tests/golden/M16-GAP-00175/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00175", + "parentTask": "M16-GAP-00174", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.driver_button_edit data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.driver_button_edit", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00175.py -- tests/files/web/generated/M16-GAP-00175-operator-anim.driver_button_edit.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00175", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00175" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00175.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2003, + "contextRemainingTokens": 500 + }, + "source": { + "bytes": 7901, + "tokens": 1976 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00175.py", + "bytes": 1168, + "tokens": 292 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00175-operator-anim.driver_button_edit.blend", + "bytes": 86619, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 231498, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 365288, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00175/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00175.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00175/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1168, + "tokens": 292 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00176", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00175.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00174/manifest.json", + "parentStatus": "docs/status/M16-GAP-00174.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00175.md", + "tests/golden/M16-GAP-00174/manifest.json", + "docs/status/M16-GAP-00174.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00174", + "parentTask": "M16-GAP-00173", + "status": "done", + "nextTask": "M16-GAP-00175", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00174 Status", + "status: done", + "task: anim.driver_button_add operator LOCAL_EXACT slice", + "updated: 2026-08-21 America/New_York", + "scope:", + "- The minimal fixture contains an un-driven `drive_target` property; foreground Chromium-compatible Blender UI automation invokes `ANIM_OT_driver_button_add` on that exact RNA button and the reader preserves the resulting driver for WASM/Main.", + "evidence:", + "- Blender desktop registers a focused Properties panel, activates the real RNA button, and invokes `ANIM_OT_driver_button_add` through the UI context (`poll=true`, `FINISHED`, `DRIVER_ADDED`)." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1804, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 451 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00175.md", + "bytes": 1804, + "lines": 38, + "tokens": 451 + }, + { + "path": "tests/golden/M16-GAP-00174/manifest.json", + "bytes": 2916, + "lines": 74, + "tokens": 729 + }, + { + "path": "docs/status/M16-GAP-00174.md", + "bytes": 1013, + "lines": 18, + "tokens": 254 + } + ], + "sourceTokens": 1976, + "evidenceFiles": 1, + "evidenceBytes": 1168, + "evidenceTokens": 292, + "totalTokens": 2268, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3292, + "serializedContextTokens": 757, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00176/anim-driver-button-remove-desktop-report.json b/tests/golden/M16-GAP-00176/anim-driver-button-remove-desktop-report.json new file mode 100644 index 00000000..c1efda28 --- /dev/null +++ b/tests/golden/M16-GAP-00176/anim-driver-button-remove-desktop-report.json @@ -0,0 +1,15 @@ +{ + "blenderVersion": "5.2.0 LTS", + "drivers": [], + "evidenceStatus": "PRESERVED", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00176-operator-anim.driver_button_remove.blend", + "fixtureSha256": "292203abee32979f8fcc7568b78e66846d5d6280c194fcfa5c7be56170247012", + "mainMutation": "DRIVER_REMOVED", + "operation": "ANIM_DRIVER_BUTTON_REMOVE_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00176", + "value": 3.75 +} diff --git a/tests/golden/M16-GAP-00176/anim-driver-button-remove-local-exact-report.json b/tests/golden/M16-GAP-00176/anim-driver-button-remove-local-exact-report.json new file mode 100644 index 00000000..b1209a66 --- /dev/null +++ b/tests/golden/M16-GAP-00176/anim-driver-button-remove-local-exact-report.json @@ -0,0 +1,27 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00176", + "operation": "ANIM_DRIVER_BUTTON_REMOVE_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00176-operator-anim.driver_button_remove.blend", + "sha256": "292203abee32979f8fcc7568b78e66846d5d6280c194fcfa5c7be56170247012" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00176/anim-driver-button-remove-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "DRIVER_REMOVED" + }, + "wasm": { + "status": "EXACT", + "objectId": "object:WebGapAnimDriverButtonRemoveObject", + "drivers": [] + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00177" +} diff --git a/tests/golden/M16-GAP-00176/manifest.json b/tests/golden/M16-GAP-00176/manifest.json new file mode 100644 index 00000000..c7437517 --- /dev/null +++ b/tests/golden/M16-GAP-00176/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00176", + "parentTask": "M16-GAP-00175", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_DRIVER_BUTTON_REMOVE_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00175/manifest.json", + "sha256": "f0769d32fe2fced8edf7c232c7e8956862e1418010981c0e00ead511c61d05e7" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00176-operator-anim.driver_button_remove.blend", + "sha256": "292203abee32979f8fcc7568b78e66846d5d6280c194fcfa5c7be56170247012" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00176.py", + "sha256": "9591dac532101bf681890f06a1f88f2f1a106e728846e3b86829abb834f1291b" + }, + "desktopChecker": { + "path": "tools/web/check-action-driver-button-remove-desktop.py", + "sha256": "34db1bdf7b6086dca2447c00726703642da7ce58b572ded0ae57595e4ba5a359" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "9ece9cca678f392484ef701ab529d8ce21a85e34fea1e72f43bdfc09bf18b1ea" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "8824ba3dfb4090b85dc679a583d263b4bdb190a47978f72f3c11f6b565fdacaf" + }, + "protocol": { + "path": "web/protocol/editor-workflow.ts", + "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" + }, + "sceneIrProtocol": { + "path": "web/protocol/scene-ir.ts", + "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "9c831d0351ac9d0714cce3b1da748cba416ced3086e3c59595cf24ac4da459ed" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00176/anim-driver-button-remove-desktop-report.json", + "sha256": "369081c441e48ee8ad39d9f4c90a4c2f80b4802143f0243e2d3e0d92f9198ee9" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00176/anim-driver-button-remove-local-exact-report.json", + "sha256": "44e366eb69905cd48d27decfab478c13dd6b1b715fcaae8ef7d3c75d09f1a311" + }, + "status": { + "path": "docs/status/M16-GAP-00176.md", + "sha256": "f40dac4690310310d87b5cf020995ad109daf4c9167ab953c9d001c31c7e84b8" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00176/task-context.json", + "sha256": "0811175e4a76169bdf347bb9fc858e67d4559ce1aa40b81e9c0e9b604d122550" + } + }, + "nextTask": "M16-GAP-00177" +} diff --git a/tests/golden/M16-GAP-00176/task-context.json b/tests/golden/M16-GAP-00176/task-context.json new file mode 100644 index 00000000..ccfd1d19 --- /dev/null +++ b/tests/golden/M16-GAP-00176/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00176", + "parentTask": "M16-GAP-00175", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.driver_button_remove data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.driver_button_remove", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00176.py -- tests/files/web/generated/M16-GAP-00176-operator-anim.driver_button_remove.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00176", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00176" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00176.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2195, + "contextRemainingTokens": 547 + }, + "source": { + "bytes": 7709, + "tokens": 1929 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00176.py", + "bytes": 1172, + "tokens": 293 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00176-operator-anim.driver_button_remove.blend", + "bytes": 86464, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 231498, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 368769, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00176/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00176.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00176/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1172, + "tokens": 293 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00177", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00176.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00175/manifest.json", + "parentStatus": "docs/status/M16-GAP-00175.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00176.md", + "tests/golden/M16-GAP-00175/manifest.json", + "docs/status/M16-GAP-00175.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00175", + "parentTask": "M16-GAP-00174", + "status": "done", + "nextTask": "M16-GAP-00176", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00175 Status", + "status: done", + "task: anim.driver_button_edit operator LOCAL_EXACT slice", + "updated: 2026-08-21 America/New_York", + "scope:", + "- The minimal fixture contains one scripted driver on `drive_target`; Blender desktop invokes `ANIM_OT_driver_button_edit` in the active Properties context (`poll=true`, `INTERFACE`) and preserves the driver without a Main mutation.", + "evidence:", + "- Desktop and WASM/Main expose the same driver (`[\"drive_target\"]`, expression `frame * 2.5 + 1.25`, scripted, no variables); save/reopen is exact and malformed Blend input is rejected without Main mutation." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1814, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 454 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00176.md", + "bytes": 1814, + "lines": 38, + "tokens": 454 + }, + { + "path": "tests/golden/M16-GAP-00175/manifest.json", + "bytes": 2921, + "lines": 74, + "tokens": 731 + }, + { + "path": "docs/status/M16-GAP-00175.md", + "bytes": 806, + "lines": 17, + "tokens": 202 + } + ], + "sourceTokens": 1929, + "evidenceFiles": 1, + "evidenceBytes": 1172, + "evidenceTokens": 293, + "totalTokens": 2222, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3246, + "serializedContextTokens": 758, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00177/anim-end-frame-set-desktop-report.json b/tests/golden/M16-GAP-00177/anim-end-frame-set-desktop-report.json new file mode 100644 index 00000000..1756e60a --- /dev/null +++ b/tests/golden/M16-GAP-00177/anim-end-frame-set-desktop-report.json @@ -0,0 +1,17 @@ +{ + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00177-operator-anim.end_frame_set.blend", + "fixtureSha256": "b86b4daff038a40e597d1814a021c28fe6cb65e09fb7cfc9ee7bc59f665d9809", + "frame": { + "current": 42, + "end": 42, + "start": 1 + }, + "mainMutation": "FRAME_END_SET", + "operation": "ANIM_END_FRAME_SET_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00177" +} diff --git a/tests/golden/M16-GAP-00177/anim-end-frame-set-local-exact-report.json b/tests/golden/M16-GAP-00177/anim-end-frame-set-local-exact-report.json new file mode 100644 index 00000000..a0397b09 --- /dev/null +++ b/tests/golden/M16-GAP-00177/anim-end-frame-set-local-exact-report.json @@ -0,0 +1,30 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00177", + "operation": "ANIM_END_FRAME_SET_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00177-operator-anim.end_frame_set.blend", + "sha256": "b86b4daff038a40e597d1814a021c28fe6cb65e09fb7cfc9ee7bc59f665d9809" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00177/anim-end-frame-set-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "FRAME_END_SET" + }, + "wasm": { + "status": "EXACT", + "frame": { + "current": 42, + "end": 42, + "start": 1 + } + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00178" +} diff --git a/tests/golden/M16-GAP-00177/manifest.json b/tests/golden/M16-GAP-00177/manifest.json new file mode 100644 index 00000000..5df6dbcd --- /dev/null +++ b/tests/golden/M16-GAP-00177/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00177", + "parentTask": "M16-GAP-00176", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_END_FRAME_SET_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00176/manifest.json", + "sha256": "38da8c875cf61f18159444a30c2fb2a3a83d5cef31498fb220b9e201931e605b" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00177-operator-anim.end_frame_set.blend", + "sha256": "3cdef7cd4a48256700c0308247dc400a160b2495a9bbf246be5800dd742c1154" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00177.py", + "sha256": "c8f783aa06acd980ebd0f3e228f4065e779434b22059e6b032b652adb521a1d7" + }, + "desktopChecker": { + "path": "tools/web/check-action-end-frame-set-desktop.py", + "sha256": "7ea71a9a4e48775fde115223a115f9f31df016ce57e4a13af60b89d5bc7d836a" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "5edc8a52f534e391d322f2f7ee73fc65652b385242de0ee75ebc79a3d026aa53" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "8824ba3dfb4090b85dc679a583d263b4bdb190a47978f72f3c11f6b565fdacaf" + }, + "protocol": { + "path": "web/protocol/editor-workflow.ts", + "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" + }, + "sceneIrProtocol": { + "path": "web/protocol/scene-ir.ts", + "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "9c831d0351ac9d0714cce3b1da748cba416ced3086e3c59595cf24ac4da459ed" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00177/anim-end-frame-set-desktop-report.json", + "sha256": "7e162f3b29c2636224d1a7c55f12978e573226aae207f7f45018062d595a038c" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00177/anim-end-frame-set-local-exact-report.json", + "sha256": "a08e18c614b9e612c744d6d1c55898fb5d1b7e6b74a9f41301627a5de6801db2" + }, + "status": { + "path": "docs/status/M16-GAP-00177.md", + "sha256": "c87a6acb0b22e57107bae051a9d8ce524ae296363a6e3f25fb98bc8872bf03f2" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00177/task-context.json", + "sha256": "06ee966e3f4ae02711eefa7b9562493e348ec9fd2fdf09592ff3d5f5d4f2b89c" + } + }, + "nextTask": "M16-GAP-00178" +} diff --git a/tests/golden/M16-GAP-00177/task-context.json b/tests/golden/M16-GAP-00177/task-context.json new file mode 100644 index 00000000..f2a05efd --- /dev/null +++ b/tests/golden/M16-GAP-00177/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00177", + "parentTask": "M16-GAP-00176", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.end_frame_set data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.end_frame_set", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00177.py -- tests/files/web/generated/M16-GAP-00177-operator-anim.end_frame_set.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00177", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00177" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00177.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2262, + "contextRemainingTokens": 565 + }, + "source": { + "bytes": 7642, + "tokens": 1911 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00177.py", + "bytes": 590, + "tokens": 148 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00177-operator-anim.end_frame_set.blend", + "bytes": 85579, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 231498, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 372024, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00177/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00177.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00177/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 590, + "tokens": 148 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00178", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00177.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00176/manifest.json", + "parentStatus": "docs/status/M16-GAP-00176.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00177.md", + "tests/golden/M16-GAP-00176/manifest.json", + "docs/status/M16-GAP-00176.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00176", + "parentTask": "M16-GAP-00175", + "status": "done", + "nextTask": "M16-GAP-00177", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00176 Status", + "status: done", + "task: anim.driver_button_remove operator LOCAL_EXACT slice", + "updated: 2026-08-21 America/New_York", + "scope:", + "- The minimal fixture starts with one scripted driver on `drive_target`; foreground Chromium-compatible Blender UI activates the RNA button and invokes `ANIM_OT_driver_button_remove(all=true)` (`poll=true`, `FINISHED`), removing that driver from Main.", + "evidence:", + "- Desktop and WASM/Main expose the same final object with no drivers; save/reopen is exact and malformed Blend input is rejected without Main mutation." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1779, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 445 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00177.md", + "bytes": 1779, + "lines": 38, + "tokens": 445 + }, + { + "path": "tests/golden/M16-GAP-00176/manifest.json", + "bytes": 2931, + "lines": 74, + "tokens": 733 + }, + { + "path": "docs/status/M16-GAP-00176.md", + "bytes": 764, + "lines": 17, + "tokens": 191 + } + ], + "sourceTokens": 1911, + "evidenceFiles": 1, + "evidenceBytes": 590, + "evidenceTokens": 148, + "totalTokens": 2059, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3083, + "serializedContextTokens": 752, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00178/anim-keyframe-clear-button-desktop-report.json b/tests/golden/M16-GAP-00178/anim-keyframe-clear-button-desktop-report.json new file mode 100644 index 00000000..5c34529f --- /dev/null +++ b/tests/golden/M16-GAP-00178/anim-keyframe-clear-button-desktop-report.json @@ -0,0 +1,46 @@ +{ + "after": { + "action": { + "channels": [], + "name": "WebGapAnimKeyframeClearButtonAction" + }, + "value": 3.0 + }, + "before": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"clear_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1.0, + 3.0, + 5.0 + ] + } + ], + "name": "WebGapAnimKeyframeClearButtonAction" + }, + "value": 3.0 + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00178-operator-anim.keyframe_clear_button.blend", + "fixtureSha256": "75aa5f056fc9afe3562ad101a7f3b8aacf93ad54fae06519b236b5fc345831b6", + "mainMutation": "KEYFRAMES_CLEARED", + "operation": "ANIM_KEYFRAME_CLEAR_BUTTON_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00178" +} diff --git a/tests/golden/M16-GAP-00178/anim-keyframe-clear-button-local-exact-report.json b/tests/golden/M16-GAP-00178/anim-keyframe-clear-button-local-exact-report.json new file mode 100644 index 00000000..935169a9 --- /dev/null +++ b/tests/golden/M16-GAP-00178/anim-keyframe-clear-button-local-exact-report.json @@ -0,0 +1,66 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00178", + "operation": "ANIM_KEYFRAME_CLEAR_BUTTON_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00178-operator-anim.keyframe_clear_button.blend", + "sha256": "75aa5f056fc9afe3562ad101a7f3b8aacf93ad54fae06519b236b5fc345831b6" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00178/anim-keyframe-clear-button-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "KEYFRAMES_CLEARED", + "before": { + "channels": [ + { + "frames": [ + 1, + 3, + 5 + ], + "index": 0, + "path": "[\"clear_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1, + 3, + 5 + ] + } + ], + "name": "WebGapAnimKeyframeClearButtonAction" + }, + "after": { + "channels": [], + "name": "WebGapAnimKeyframeClearButtonAction" + } + }, + "wasm": { + "status": "EXACT", + "before": { + "animationId": "action:WebGapAnimKeyframeClearButtonAction:object:WebGapAnimKeyframeClearButtonObject", + "channelPaths": [ + "[\"clear_target\"][0]" + ], + "keyframesPerChannel": [ + 3 + ] + }, + "after": { + "animationCount": 0, + "keyframesCleared": true + } + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00179" +} diff --git a/tests/golden/M16-GAP-00178/manifest.json b/tests/golden/M16-GAP-00178/manifest.json new file mode 100644 index 00000000..0220a87a --- /dev/null +++ b/tests/golden/M16-GAP-00178/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00178", + "parentTask": "M16-GAP-00177", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_KEYFRAME_CLEAR_BUTTON_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00177/manifest.json", + "sha256": "35f8e52349884e7752b9d652fd415e0ac27688262e1d81cbe73550794db3b6b6" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00178-operator-anim.keyframe_clear_button.blend", + "sha256": "75aa5f056fc9afe3562ad101a7f3b8aacf93ad54fae06519b236b5fc345831b6" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00178.py", + "sha256": "2182c0a9dda794a1f037cea8178151382cfc9c15c1599c23f3d81d4d1883f6da" + }, + "desktopChecker": { + "path": "tools/web/check-action-keyframe-clear-button-desktop.py", + "sha256": "53c60181c3ca7da0eb16446a8eacf499963aa8e8a6e328b09a21a3301744c0b7" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "c70a9d246f13ed1d0d9e3e950f7289cb943a3b04ce37e4b2666a24363b3fe661" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "8824ba3dfb4090b85dc679a583d263b4bdb190a47978f72f3c11f6b565fdacaf" + }, + "protocol": { + "path": "web/protocol/editor-workflow.ts", + "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" + }, + "sceneIrProtocol": { + "path": "web/protocol/scene-ir.ts", + "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "9c831d0351ac9d0714cce3b1da748cba416ced3086e3c59595cf24ac4da459ed" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00178/anim-keyframe-clear-button-desktop-report.json", + "sha256": "ba35b96dc8c7aa46427b64465aa223a87ffe2d5bf37ef42a4bd17afc430b4bee" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00178/anim-keyframe-clear-button-local-exact-report.json", + "sha256": "9969372551c877505755cf23454610ca8211cc77a6e1267b366e848ebd69e30d" + }, + "status": { + "path": "docs/status/M16-GAP-00178.md", + "sha256": "0525407475c3c4cc8ed880d29fe077b178017f3710c56002558bd032362808d5" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00178/task-context.json", + "sha256": "ff864d8ebd9e42c478667639926c27b4580c35baf72c77f7cb0df71d0022e179" + } + }, + "nextTask": "M16-GAP-00179" +} diff --git a/tests/golden/M16-GAP-00178/task-context.json b/tests/golden/M16-GAP-00178/task-context.json new file mode 100644 index 00000000..eb17838e --- /dev/null +++ b/tests/golden/M16-GAP-00178/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00178", + "parentTask": "M16-GAP-00177", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.keyframe_clear_button data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.keyframe_clear_button", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00178.py -- tests/files/web/generated/M16-GAP-00178-operator-anim.keyframe_clear_button.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00178", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00178" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00178.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2364, + "contextRemainingTokens": 590 + }, + "source": { + "bytes": 7540, + "tokens": 1886 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00178.py", + "bytes": 1319, + "tokens": 330 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00178-operator-anim.keyframe_clear_button.blend", + "bytes": 86642, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 231498, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 377589, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00178/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00178.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00178/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1319, + "tokens": 330 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00179", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00178.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00177/manifest.json", + "parentStatus": "docs/status/M16-GAP-00177.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00178.md", + "tests/golden/M16-GAP-00177/manifest.json", + "docs/status/M16-GAP-00177.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00177", + "parentTask": "M16-GAP-00176", + "status": "done", + "nextTask": "M16-GAP-00178", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00177 Status", + "status: done", + "task: anim.end_frame_set operator LOCAL_EXACT slice", + "updated: 2026-08-21 America/New_York", + "scope:", + "- The minimal scene starts at frame 42 with a scene range of 1-120; a foreground animation-area context invokes `ANIM_OT_end_frame_set` (`poll=true`, `FINISHED`) and sets the scene end frame to 42.", + "evidence:", + "- Desktop and WASM/Main expose the same frame state (`current=42`, `start=1`, `end=42`); save/reopen is exact and malformed Blend input is rejected without Main mutation." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1819, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 455 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00178.md", + "bytes": 1819, + "lines": 38, + "tokens": 455 + }, + { + "path": "tests/golden/M16-GAP-00177/manifest.json", + "bytes": 2896, + "lines": 74, + "tokens": 724 + }, + { + "path": "docs/status/M16-GAP-00177.md", + "bytes": 657, + "lines": 17, + "tokens": 165 + } + ], + "sourceTokens": 1886, + "evidenceFiles": 1, + "evidenceBytes": 1319, + "evidenceTokens": 330, + "totalTokens": 2216, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3240, + "serializedContextTokens": 759, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00179/anim-keyframe-clear-v3d-desktop-report.json b/tests/golden/M16-GAP-00179/anim-keyframe-clear-v3d-desktop-report.json new file mode 100644 index 00000000..1450420d --- /dev/null +++ b/tests/golden/M16-GAP-00179/anim-keyframe-clear-v3d-desktop-report.json @@ -0,0 +1,50 @@ +{ + "after": { + "action": { + "channels": [], + "name": "WebGapAnimKeyframeClearV3DAction" + }, + "active": true, + "selected": true, + "value": 3.0 + }, + "before": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"clear_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1.0, + 3.0, + 5.0 + ] + } + ], + "name": "WebGapAnimKeyframeClearV3DAction" + }, + "active": true, + "selected": true, + "value": 3.0 + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00179-operator-anim.keyframe_clear_v3d.blend", + "fixtureSha256": "0e079b73025f3623872e92c1e961e012cbcfaff4a64b2c7741a2ff08c935afdd", + "mainMutation": "ANIMATION_CLEARED", + "operation": "ANIM_KEYFRAME_CLEAR_V3D_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00179" +} diff --git a/tests/golden/M16-GAP-00179/anim-keyframe-clear-v3d-local-exact-report.json b/tests/golden/M16-GAP-00179/anim-keyframe-clear-v3d-local-exact-report.json new file mode 100644 index 00000000..3081fff4 --- /dev/null +++ b/tests/golden/M16-GAP-00179/anim-keyframe-clear-v3d-local-exact-report.json @@ -0,0 +1,66 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00179", + "operation": "ANIM_KEYFRAME_CLEAR_V3D_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00179-operator-anim.keyframe_clear_v3d.blend", + "sha256": "0e079b73025f3623872e92c1e961e012cbcfaff4a64b2c7741a2ff08c935afdd" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00179/anim-keyframe-clear-v3d-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "ANIMATION_CLEARED", + "before": { + "channels": [ + { + "frames": [ + 1, + 3, + 5 + ], + "index": 0, + "path": "[\"clear_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1, + 3, + 5 + ] + } + ], + "name": "WebGapAnimKeyframeClearV3DAction" + }, + "after": { + "channels": [], + "name": "WebGapAnimKeyframeClearV3DAction" + } + }, + "wasm": { + "status": "EXACT", + "before": { + "animationId": "action:WebGapAnimKeyframeClearV3DAction:object:WebGapAnimKeyframeClearV3DObject", + "channelPaths": [ + "[\"clear_target\"][0]" + ], + "keyframesPerChannel": [ + 3 + ] + }, + "after": { + "animationCount": 0, + "animationCleared": true + } + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00180" +} diff --git a/tests/golden/M16-GAP-00179/manifest.json b/tests/golden/M16-GAP-00179/manifest.json new file mode 100644 index 00000000..b344683d --- /dev/null +++ b/tests/golden/M16-GAP-00179/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00179", + "parentTask": "M16-GAP-00178", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_KEYFRAME_CLEAR_V3D_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00178/manifest.json", + "sha256": "351ff1a4e32fff9653bf276eebd6638bfa729130c6379dca0a5355e664961e4e" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00179-operator-anim.keyframe_clear_v3d.blend", + "sha256": "0e079b73025f3623872e92c1e961e012cbcfaff4a64b2c7741a2ff08c935afdd" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00179.py", + "sha256": "600336ccf298afe28fdd1141a2dbac794fde599f28c31f9d7a7a8eb15bb80443" + }, + "desktopChecker": { + "path": "tools/web/check-action-keyframe-clear-v3d-desktop.py", + "sha256": "1d2a7e2bf29a8bc62b6e4e3ebdc9489160f9494d9b7284f7159cc536f2bca1c0" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "99769a632aa2ec5b1d438bd652af0418ea26a1f85f942548d2734e8c5f046b5a" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "8824ba3dfb4090b85dc679a583d263b4bdb190a47978f72f3c11f6b565fdacaf" + }, + "protocol": { + "path": "web/protocol/editor-workflow.ts", + "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" + }, + "sceneIrProtocol": { + "path": "web/protocol/scene-ir.ts", + "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "9c831d0351ac9d0714cce3b1da748cba416ced3086e3c59595cf24ac4da459ed" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00179/anim-keyframe-clear-v3d-desktop-report.json", + "sha256": "2e63bae9cbb613ab96faf2fa802e34caf5aca2e7c3968c93ef0dc9de6a16fecf" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00179/anim-keyframe-clear-v3d-local-exact-report.json", + "sha256": "6b675af2fd56ce8ee146676101ca9f0be6365a9702b80d8def8c27460a1e7ae9" + }, + "status": { + "path": "docs/status/M16-GAP-00179.md", + "sha256": "c1d842b67de5e7275d040a033eb5cd16319ec2c5f77e1b67ed1d55b1c9e0dc4e" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00179/task-context.json", + "sha256": "74ae2d753d5a89d6692a3e73552849d7303e576de19f54d78311b53ba49c5608" + } + }, + "nextTask": "M16-GAP-00180" +} diff --git a/tests/golden/M16-GAP-00179/task-context.json b/tests/golden/M16-GAP-00179/task-context.json new file mode 100644 index 00000000..8c188f3e --- /dev/null +++ b/tests/golden/M16-GAP-00179/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00179", + "parentTask": "M16-GAP-00178", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.keyframe_clear_v3d data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.keyframe_clear_v3d", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00179.py -- tests/files/web/generated/M16-GAP-00179-operator-anim.keyframe_clear_v3d.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00179", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00179" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00179.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1969, + "contextRemainingTokens": 492 + }, + "source": { + "bytes": 7935, + "tokens": 1984 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00179.py", + "bytes": 1310, + "tokens": 328 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00179-operator-anim.keyframe_clear_v3d.blend", + "bytes": 86603, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 231498, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 383158, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00179/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00179.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00179/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1310, + "tokens": 328 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00180", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00179.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00178/manifest.json", + "parentStatus": "docs/status/M16-GAP-00178.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00179.md", + "tests/golden/M16-GAP-00178/manifest.json", + "docs/status/M16-GAP-00178.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00178", + "parentTask": "M16-GAP-00177", + "status": "done", + "nextTask": "M16-GAP-00179", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00178 Status", + "status: done", + "task: anim.keyframe_clear_button operator LOCAL_EXACT slice", + "updated: 2026-08-21 America/New_York", + "scope:", + "- The minimal fixture animates one scalar custom RNA property, `clear_target`, on `WebGapAnimKeyframeClearButtonObject` at frames 1, 3, and 5. A foreground Properties context activates that RNA button and invokes `ANIM_OT_keyframe_clear_button(all=true)` (`poll=true`, `FINISHED`), leaving the Action with no F-Curves.", + "evidence:", + "- Desktop evidence records the property changing from three selected keyframes to none; WASM/Main reads the original channel as `[\"clear_target\"][0]` and the cleared fixture with no matching animation. Save/reopen is exact and malformed Blend input is rejected without Main mutation." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1804, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 451 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00179.md", + "bytes": 1804, + "lines": 38, + "tokens": 451 + }, + { + "path": "tests/golden/M16-GAP-00178/manifest.json", + "bytes": 2936, + "lines": 74, + "tokens": 734 + }, + { + "path": "docs/status/M16-GAP-00178.md", + "bytes": 1027, + "lines": 17, + "tokens": 257 + } + ], + "sourceTokens": 1984, + "evidenceFiles": 1, + "evidenceBytes": 1310, + "evidenceTokens": 328, + "totalTokens": 2312, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3336, + "serializedContextTokens": 757, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00180/anim-keyframe-clear-vse-desktop-report.json b/tests/golden/M16-GAP-00180/anim-keyframe-clear-vse-desktop-report.json new file mode 100644 index 00000000..77e7205c --- /dev/null +++ b/tests/golden/M16-GAP-00180/anim-keyframe-clear-vse-desktop-report.json @@ -0,0 +1,50 @@ +{ + "after": { + "action": { + "channels": [], + "name": "WebGapAnimKeyframeClearVSEAction" + }, + "active": true, + "blendAlpha": 0.5, + "selected": true + }, + "before": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "sequence_editor.strips_all[\"WebGapAnimKeyframeClearVSEStrip\"].blend_alpha", + "selected": [ + true, + true, + true + ], + "values": [ + 0.25, + 0.5, + 0.75 + ] + } + ], + "name": "WebGapAnimKeyframeClearVSEAction" + }, + "active": true, + "blendAlpha": 0.5, + "selected": true + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00180-operator-anim.keyframe_clear_vse.blend", + "fixtureSha256": "e2ef76b206578af5a77919d7f9625ca76ec58bb0a5d9074f907ced31cdd96c4d", + "mainMutation": "ANIMATION_CLEARED", + "operation": "ANIM_KEYFRAME_CLEAR_VSE_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00180" +} diff --git a/tests/golden/M16-GAP-00180/anim-keyframe-clear-vse-local-exact-report.json b/tests/golden/M16-GAP-00180/anim-keyframe-clear-vse-local-exact-report.json new file mode 100644 index 00000000..6ad1c6bc --- /dev/null +++ b/tests/golden/M16-GAP-00180/anim-keyframe-clear-vse-local-exact-report.json @@ -0,0 +1,67 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00180", + "operation": "ANIM_KEYFRAME_CLEAR_VSE_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00180-operator-anim.keyframe_clear_vse.blend", + "sha256": "e2ef76b206578af5a77919d7f9625ca76ec58bb0a5d9074f907ced31cdd96c4d" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00180/anim-keyframe-clear-vse-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "ANIMATION_CLEARED", + "before": { + "channels": [ + { + "frames": [ + 1, + 3, + 5 + ], + "index": 0, + "path": "sequence_editor.strips_all[\"WebGapAnimKeyframeClearVSEStrip\"].blend_alpha", + "selected": [ + true, + true, + true + ], + "values": [ + 0.25, + 0.5, + 0.75 + ] + } + ], + "name": "WebGapAnimKeyframeClearVSEAction" + }, + "after": { + "channels": [], + "name": "WebGapAnimKeyframeClearVSEAction" + } + }, + "wasm": { + "status": "EXACT", + "before": { + "animationId": "action:WebGapAnimKeyframeClearVSEAction:scene:Scene", + "targetId": "scene:Scene", + "channelPaths": [ + "sequence_editor.strips_all[\"WebGapAnimKeyframeClearVSEStrip\"].blend_alpha[0]" + ], + "keyframesPerChannel": [ + 3 + ] + }, + "after": { + "animationCount": 0, + "animationCleared": true + } + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00181" +} diff --git a/tests/golden/M16-GAP-00180/manifest.json b/tests/golden/M16-GAP-00180/manifest.json new file mode 100644 index 00000000..e8c41ded --- /dev/null +++ b/tests/golden/M16-GAP-00180/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00180", + "parentTask": "M16-GAP-00179", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_KEYFRAME_CLEAR_VSE_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00179/manifest.json", + "sha256": "bd344a1160ca950db34f10d92a43288cc1ac707af00e1bf43a9a903c45547a67" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00180-operator-anim.keyframe_clear_vse.blend", + "sha256": "e2ef76b206578af5a77919d7f9625ca76ec58bb0a5d9074f907ced31cdd96c4d" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00180.py", + "sha256": "e72a0c68e1ac8173c70944bc48f7bd03365913e24b831708da40a28bde936f4d" + }, + "desktopChecker": { + "path": "tools/web/check-action-keyframe-clear-vse-desktop.py", + "sha256": "09aeec25d69a57b657bd690998058a23980b6a4b9425fd63dbb26f14f4edee8f" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "0876494ec0ef358ac3049c7da3e2f207da80826769167379454789b4b27e41c9" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "8824ba3dfb4090b85dc679a583d263b4bdb190a47978f72f3c11f6b565fdacaf" + }, + "protocol": { + "path": "web/protocol/editor-workflow.ts", + "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" + }, + "sceneIrProtocol": { + "path": "web/protocol/scene-ir.ts", + "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "9c831d0351ac9d0714cce3b1da748cba416ced3086e3c59595cf24ac4da459ed" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00180/anim-keyframe-clear-vse-desktop-report.json", + "sha256": "6885cc9103c1b9c8396a684559d08d0899ca096580278a5fa321ee6cec4412ec" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00180/anim-keyframe-clear-vse-local-exact-report.json", + "sha256": "9e05fde557e26ac9be8dc8c7983be4a25e7637542643aa8b38708a1868de27ad" + }, + "status": { + "path": "docs/status/M16-GAP-00180.md", + "sha256": "6af17dd941fdf1f76753ee23a18f97689b7d9719c37ce8714628b0acda11fc5f" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00180/task-context.json", + "sha256": "a90f35e4b60f26bac6d8900a1838d08cbfc20638f65f45f8dbf2306c7160f1d4" + } + }, + "nextTask": "M16-GAP-00181" +} diff --git a/tests/golden/M16-GAP-00180/task-context.json b/tests/golden/M16-GAP-00180/task-context.json new file mode 100644 index 00000000..2f920fba --- /dev/null +++ b/tests/golden/M16-GAP-00180/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00180", + "parentTask": "M16-GAP-00179", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.keyframe_clear_vse data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.keyframe_clear_vse", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00180.py -- tests/files/web/generated/M16-GAP-00180-operator-anim.keyframe_clear_vse.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00180", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00180" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00180.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2005, + "contextRemainingTokens": 500 + }, + "source": { + "bytes": 7899, + "tokens": 1976 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00180.py", + "bytes": 1317, + "tokens": 330 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00180-operator-anim.keyframe_clear_vse.blend", + "bytes": 86461, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 231498, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 388566, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00180/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00180.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00180/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1317, + "tokens": 330 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00181", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00180.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00179/manifest.json", + "parentStatus": "docs/status/M16-GAP-00179.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00180.md", + "tests/golden/M16-GAP-00179/manifest.json", + "docs/status/M16-GAP-00179.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00179", + "parentTask": "M16-GAP-00178", + "status": "done", + "nextTask": "M16-GAP-00180", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00179 Status", + "status: done", + "task: anim.keyframe_clear_v3d operator LOCAL_EXACT slice", + "updated: 2026-08-21 America/New_York", + "scope:", + "- The minimal fixture selects one object with a scalar `clear_target` Action at frames 1, 3, and 5. A foreground `VIEW_3D` context invokes `ANIM_OT_keyframe_clear_v3d(confirm=false)` (`poll=true`, `FINISHED`), removing all editable F-Curves from the selected object's Action.", + "evidence:", + "- Desktop evidence records the selected/active object changing from three selected keyframes to no F-Curves; WASM/Main reads the original channel as `[\"clear_target\"][0]` and the cleared fixture with no matching animation. Save/reopen is exact and malformed Blend input is rejected without Main mutation." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1804, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 451 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00180.md", + "bytes": 1804, + "lines": 38, + "tokens": 451 + }, + { + "path": "tests/golden/M16-GAP-00179/manifest.json", + "bytes": 2921, + "lines": 74, + "tokens": 731 + }, + { + "path": "docs/status/M16-GAP-00179.md", + "bytes": 1006, + "lines": 17, + "tokens": 252 + } + ], + "sourceTokens": 1976, + "evidenceFiles": 1, + "evidenceBytes": 1317, + "evidenceTokens": 330, + "totalTokens": 2306, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3330, + "serializedContextTokens": 757, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00181/anim-keyframe-delete-desktop-report.json b/tests/golden/M16-GAP-00181/anim-keyframe-delete-desktop-report.json new file mode 100644 index 00000000..e9489cf4 --- /dev/null +++ b/tests/golden/M16-GAP-00181/anim-keyframe-delete-desktop-report.json @@ -0,0 +1,69 @@ +{ + "after": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 5.0 + ], + "index": 0, + "path": "[\"delete_target\"]", + "selected": [ + true, + true + ], + "values": [ + 1.0, + 5.0 + ] + } + ], + "name": "WebGapAnimKeyframeDeleteAction" + }, + "active": true, + "activeKeyingSet": "WebGapAnimKeyframeDeleteSet", + "selected": true, + "value": 3.0 + }, + "before": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"delete_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1.0, + 3.0, + 5.0 + ] + } + ], + "name": "WebGapAnimKeyframeDeleteAction" + }, + "active": true, + "activeKeyingSet": "WebGapAnimKeyframeDeleteSet", + "selected": true, + "value": 3.0 + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00181-operator-anim.keyframe_delete.blend", + "fixtureSha256": "0d6d1e45f430c051e4ecaf1f799f4b7666fa8311e2abf188502cf9cdc0011855", + "mainMutation": "KEYFRAME_DELETED", + "operation": "ANIM_KEYFRAME_DELETE_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00181" +} diff --git a/tests/golden/M16-GAP-00181/anim-keyframe-delete-local-exact-report.json b/tests/golden/M16-GAP-00181/anim-keyframe-delete-local-exact-report.json new file mode 100644 index 00000000..dce2884a --- /dev/null +++ b/tests/golden/M16-GAP-00181/anim-keyframe-delete-local-exact-report.json @@ -0,0 +1,87 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00181", + "operation": "ANIM_KEYFRAME_DELETE_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00181-operator-anim.keyframe_delete.blend", + "sha256": "0d6d1e45f430c051e4ecaf1f799f4b7666fa8311e2abf188502cf9cdc0011855" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00181/anim-keyframe-delete-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "KEYFRAME_DELETED", + "before": { + "channels": [ + { + "frames": [ + 1, + 3, + 5 + ], + "index": 0, + "path": "[\"delete_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1, + 3, + 5 + ] + } + ], + "name": "WebGapAnimKeyframeDeleteAction" + }, + "after": { + "channels": [ + { + "frames": [ + 1, + 5 + ], + "index": 0, + "path": "[\"delete_target\"]", + "selected": [ + true, + true + ], + "values": [ + 1, + 5 + ] + } + ], + "name": "WebGapAnimKeyframeDeleteAction" + } + }, + "wasm": { + "status": "EXACT", + "before": { + "animationId": "action:WebGapAnimKeyframeDeleteAction:object:WebGapAnimKeyframeDeleteObject", + "targetId": "object:WebGapAnimKeyframeDeleteObject", + "channelPaths": [ + "[\"delete_target\"][0]" + ], + "keyframesPerChannel": [ + 3 + ] + }, + "after": { + "animationId": "action:WebGapAnimKeyframeDeleteAction:object:WebGapAnimKeyframeDeleteObject", + "keyframesPerChannel": [ + 2 + ], + "keyframeDeleted": true + } + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00182" +} diff --git a/tests/golden/M16-GAP-00181/manifest.json b/tests/golden/M16-GAP-00181/manifest.json new file mode 100644 index 00000000..37ed975e --- /dev/null +++ b/tests/golden/M16-GAP-00181/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00181", + "parentTask": "M16-GAP-00180", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_KEYFRAME_DELETE_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00180/manifest.json", + "sha256": "e6d90f0df54469a1016917e71480ad58ba901d50694d2727d5e0927b237848eb" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00181-operator-anim.keyframe_delete.blend", + "sha256": "0d6d1e45f430c051e4ecaf1f799f4b7666fa8311e2abf188502cf9cdc0011855" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00181.py", + "sha256": "bc42dcd74150bdc50dba1190dcda12f0c7f40cd8886e94c541243c5e6df460b7" + }, + "desktopChecker": { + "path": "tools/web/check-action-keyframe-delete-desktop.py", + "sha256": "697bd750b9b3971fa108981e6b8f14f372705eeb39a7e20b33dffa9c1fa55c4c" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "7b77cecee69a1ba85251c1ef17cfe5407f2db93e606a330e9d08609faaf74aeb" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "8824ba3dfb4090b85dc679a583d263b4bdb190a47978f72f3c11f6b565fdacaf" + }, + "protocol": { + "path": "web/protocol/editor-workflow.ts", + "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" + }, + "sceneIrProtocol": { + "path": "web/protocol/scene-ir.ts", + "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "9c831d0351ac9d0714cce3b1da748cba416ced3086e3c59595cf24ac4da459ed" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00181/anim-keyframe-delete-desktop-report.json", + "sha256": "cec3f76e20a38572bf4a38789e1df1aa83ffd4f332e940c238e4d633dd841c7d" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00181/anim-keyframe-delete-local-exact-report.json", + "sha256": "4e75034a44e46afef417e241e6c81d84a1d46a8bf34e779495d9c6885c3b8bfc" + }, + "status": { + "path": "docs/status/M16-GAP-00181.md", + "sha256": "16ef18b3c2a4035e283a5a9af1968d0250763a0a3a2b52fb5a8f4f05821968c2" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00181/task-context.json", + "sha256": "ad1b7ad175eaa42b41c75f1a36d7b55f190c8bbd39d8861e7e7aaa016984b6e1" + } + }, + "nextTask": "M16-GAP-00182" +} diff --git a/tests/golden/M16-GAP-00181/task-context.json b/tests/golden/M16-GAP-00181/task-context.json new file mode 100644 index 00000000..0aca54ac --- /dev/null +++ b/tests/golden/M16-GAP-00181/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00181", + "parentTask": "M16-GAP-00180", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.keyframe_delete data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.keyframe_delete", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00181.py -- tests/files/web/generated/M16-GAP-00181-operator-anim.keyframe_delete.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00181", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00181" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00181.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1968, + "contextRemainingTokens": 490 + }, + "source": { + "bytes": 7936, + "tokens": 1986 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00181.py", + "bytes": 1630, + "tokens": 408 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00181-operator-anim.keyframe_delete.blend", + "bytes": 86782, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 231498, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 394089, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00181/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00181.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00181/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1630, + "tokens": 408 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00182", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00181.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00180/manifest.json", + "parentStatus": "docs/status/M16-GAP-00180.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00181.md", + "tests/golden/M16-GAP-00180/manifest.json", + "docs/status/M16-GAP-00180.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00180", + "parentTask": "M16-GAP-00179", + "status": "done", + "nextTask": "M16-GAP-00181", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00180 Status", + "status: done", + "task: anim.keyframe_clear_vse operator LOCAL_EXACT slice", + "updated: 2026-08-21 America/New_York", + "scope:", + "- The minimal fixture contains one selected image strip with a Scene Action animating `blend_alpha` at frames 1, 3, and 5. A real foreground `SEQUENCE_EDITOR` context invokes `ANIM_OT_keyframe_clear_vse(confirm=false)` (`poll=true`, `FINISHED`), removing the selected strip's editable F-Curve while preserving the strip and its evaluated value.", + "evidence:", + "- Desktop evidence records the selected/active strip changing from three selected keyframes to no F-Curves. WASM/Main reads the same Scene Action channel before clearing and no matching animation from the cleared fixture. Save/reopen is exact and malformed Blend input is rejected without Main mutation." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1789, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 448 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00181.md", + "bytes": 1789, + "lines": 38, + "tokens": 448 + }, + { + "path": "tests/golden/M16-GAP-00180/manifest.json", + "bytes": 2921, + "lines": 74, + "tokens": 731 + }, + { + "path": "docs/status/M16-GAP-00180.md", + "bytes": 1058, + "lines": 17, + "tokens": 265 + } + ], + "sourceTokens": 1986, + "evidenceFiles": 1, + "evidenceBytes": 1630, + "evidenceTokens": 408, + "totalTokens": 2394, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3418, + "serializedContextTokens": 754, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00182/anim-keyframe-delete-button-desktop-report.json b/tests/golden/M16-GAP-00182/anim-keyframe-delete-button-desktop-report.json new file mode 100644 index 00000000..c0e1b73a --- /dev/null +++ b/tests/golden/M16-GAP-00182/anim-keyframe-delete-button-desktop-report.json @@ -0,0 +1,67 @@ +{ + "after": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 5.0 + ], + "index": 0, + "path": "[\"delete_target\"]", + "selected": [ + true, + true + ], + "values": [ + 1.0, + 5.0 + ] + } + ], + "name": "WebGapAnimKeyframeDeleteButtonAction" + }, + "active": true, + "selected": true, + "value": 3.0 + }, + "before": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"delete_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1.0, + 3.0, + 5.0 + ] + } + ], + "name": "WebGapAnimKeyframeDeleteButtonAction" + }, + "active": true, + "selected": true, + "value": 3.0 + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00182-operator-anim.keyframe_delete_button.blend", + "fixtureSha256": "8e62660db44872553a7f32f5965afe7811e69261425beba97e6e29cdd5575073", + "mainMutation": "KEYFRAME_DELETED", + "operation": "ANIM_KEYFRAME_DELETE_BUTTON_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00182" +} diff --git a/tests/golden/M16-GAP-00182/anim-keyframe-delete-button-local-exact-report.json b/tests/golden/M16-GAP-00182/anim-keyframe-delete-button-local-exact-report.json new file mode 100644 index 00000000..0f908887 --- /dev/null +++ b/tests/golden/M16-GAP-00182/anim-keyframe-delete-button-local-exact-report.json @@ -0,0 +1,87 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00182", + "operation": "ANIM_KEYFRAME_DELETE_BUTTON_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00182-operator-anim.keyframe_delete_button.blend", + "sha256": "8e62660db44872553a7f32f5965afe7811e69261425beba97e6e29cdd5575073" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00182/anim-keyframe-delete-button-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "KEYFRAME_DELETED", + "before": { + "channels": [ + { + "frames": [ + 1, + 3, + 5 + ], + "index": 0, + "path": "[\"delete_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1, + 3, + 5 + ] + } + ], + "name": "WebGapAnimKeyframeDeleteButtonAction" + }, + "after": { + "channels": [ + { + "frames": [ + 1, + 5 + ], + "index": 0, + "path": "[\"delete_target\"]", + "selected": [ + true, + true + ], + "values": [ + 1, + 5 + ] + } + ], + "name": "WebGapAnimKeyframeDeleteButtonAction" + } + }, + "wasm": { + "status": "EXACT", + "before": { + "animationId": "action:WebGapAnimKeyframeDeleteButtonAction:object:WebGapAnimKeyframeDeleteButtonObject", + "targetId": "object:WebGapAnimKeyframeDeleteButtonObject", + "channelPaths": [ + "[\"delete_target\"][0]" + ], + "keyframesPerChannel": [ + 3 + ] + }, + "after": { + "animationId": "action:WebGapAnimKeyframeDeleteButtonAction:object:WebGapAnimKeyframeDeleteButtonObject", + "keyframesPerChannel": [ + 2 + ], + "keyframeDeleted": true + } + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00183" +} diff --git a/tests/golden/M16-GAP-00182/manifest.json b/tests/golden/M16-GAP-00182/manifest.json new file mode 100644 index 00000000..2417509b --- /dev/null +++ b/tests/golden/M16-GAP-00182/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00182", + "parentTask": "M16-GAP-00181", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_KEYFRAME_DELETE_BUTTON_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00181/manifest.json", + "sha256": "32fd366de6190029b377c8faf9ed1b661234cbc6b01925d247b46e00e7bc62ad" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00182-operator-anim.keyframe_delete_button.blend", + "sha256": "8e62660db44872553a7f32f5965afe7811e69261425beba97e6e29cdd5575073" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00182.py", + "sha256": "8424d4ca63c32c9127c9cf1d095a6dde62121ae8ddccea5dc0bbd8ba37b27a20" + }, + "desktopChecker": { + "path": "tools/web/check-action-keyframe-delete-button-desktop.py", + "sha256": "fdb36e2d97ed687a20682a769f107f10801ab8845ad5e1061565893bad2cebd9" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "961b446842e5115fc503667f19731d2cd0167f5e3be9670d3b513c64fd3ea5b4" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "8824ba3dfb4090b85dc679a583d263b4bdb190a47978f72f3c11f6b565fdacaf" + }, + "protocol": { + "path": "web/protocol/editor-workflow.ts", + "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" + }, + "sceneIrProtocol": { + "path": "web/protocol/scene-ir.ts", + "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "9c831d0351ac9d0714cce3b1da748cba416ced3086e3c59595cf24ac4da459ed" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00182/anim-keyframe-delete-button-desktop-report.json", + "sha256": "5df192b8cf82b0e53efa947f9102424cfccf05b29a4e293342ea2e3ace60b0d1" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00182/anim-keyframe-delete-button-local-exact-report.json", + "sha256": "097fdcab03f3e748077c3b1d8cdcfbb9a9b2d7df9b1ca03c54b9f0a3a637c947" + }, + "status": { + "path": "docs/status/M16-GAP-00182.md", + "sha256": "43e96981d4987ee1b32b07ce6053bca47b50106526d8e932e2b67d0005b576dc" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00182/task-context.json", + "sha256": "76d618d236a7741f912e09f4e48ec7bbdce9ac93c3fafee48dfe7ca2ebeae03c" + } + }, + "nextTask": "M16-GAP-00183" +} diff --git a/tests/golden/M16-GAP-00182/task-context.json b/tests/golden/M16-GAP-00182/task-context.json new file mode 100644 index 00000000..b79826c8 --- /dev/null +++ b/tests/golden/M16-GAP-00182/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00182", + "parentTask": "M16-GAP-00181", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.keyframe_delete_button data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.keyframe_delete_button", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00182.py -- tests/files/web/generated/M16-GAP-00182-operator-anim.keyframe_delete_button.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00182", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00182" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00182.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1696, + "contextRemainingTokens": 423 + }, + "source": { + "bytes": 8208, + "tokens": 2053 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00182.py", + "bytes": 1325, + "tokens": 332 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00182-operator-anim.keyframe_delete_button.blend", + "bytes": 86755, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 231498, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 399962, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00182/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00182.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00182/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1325, + "tokens": 332 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00183", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00182.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00181/manifest.json", + "parentStatus": "docs/status/M16-GAP-00181.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00182.md", + "tests/golden/M16-GAP-00181/manifest.json", + "docs/status/M16-GAP-00181.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00181", + "parentTask": "M16-GAP-00180", + "status": "done", + "nextTask": "M16-GAP-00182", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00181 Status", + "status: done", + "task: anim.keyframe_delete operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one selected object with a custom `delete_target` property and an Action keyed at frames 1, 3, and 5. A dedicated active Keying Set targets that property. A real foreground `VIEW_3D` context invokes `ANIM_OT_keyframe_delete(type=WebGapAnimKeyframeDeleteSet)` (`poll=true`, `FINISHED`) at frame 3, deleting only the current keyframe and preserving the two surrounding keys.", + "evidence:", + "- Desktop evidence records the selected/active object and active Keying Set before deletion, then the Action changing from `[1, 3, 5]` to `[1, 5]`; the custom property remains at 3.0. Save/reopen is exact." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1824, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 456 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00182.md", + "bytes": 1824, + "lines": 38, + "tokens": 456 + }, + { + "path": "tests/golden/M16-GAP-00181/manifest.json", + "bytes": 2906, + "lines": 74, + "tokens": 727 + }, + { + "path": "docs/status/M16-GAP-00181.md", + "bytes": 1310, + "lines": 18, + "tokens": 328 + } + ], + "sourceTokens": 2053, + "evidenceFiles": 1, + "evidenceBytes": 1325, + "evidenceTokens": 332, + "totalTokens": 2385, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3409, + "serializedContextTokens": 760, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00183/anim-keyframe-delete-by-name-desktop-report.json b/tests/golden/M16-GAP-00183/anim-keyframe-delete-by-name-desktop-report.json new file mode 100644 index 00000000..faaccada --- /dev/null +++ b/tests/golden/M16-GAP-00183/anim-keyframe-delete-by-name-desktop-report.json @@ -0,0 +1,69 @@ +{ + "after": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 5.0 + ], + "index": 0, + "path": "[\"delete_target\"]", + "selected": [ + true, + true + ], + "values": [ + 1.0, + 5.0 + ] + } + ], + "name": "WebGapAnimKeyframeDeleteByNameAction" + }, + "active": true, + "activeKeyingSet": "WebGapAnimKeyframeDeleteByNameSet", + "selected": true, + "value": 3.0 + }, + "before": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"delete_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1.0, + 3.0, + 5.0 + ] + } + ], + "name": "WebGapAnimKeyframeDeleteByNameAction" + }, + "active": true, + "activeKeyingSet": "WebGapAnimKeyframeDeleteByNameSet", + "selected": true, + "value": 3.0 + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00183-operator-anim.keyframe_delete_by_name.blend", + "fixtureSha256": "ea5a587aeeabd6692977d5a7660bf49bb7134d4fc81e8ff1a3fa9acd8a75026c", + "mainMutation": "KEYFRAME_DELETED", + "operation": "ANIM_KEYFRAME_DELETE_BY_NAME_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00183" +} diff --git a/tests/golden/M16-GAP-00183/anim-keyframe-delete-by-name-local-exact-report.json b/tests/golden/M16-GAP-00183/anim-keyframe-delete-by-name-local-exact-report.json new file mode 100644 index 00000000..5be37e52 --- /dev/null +++ b/tests/golden/M16-GAP-00183/anim-keyframe-delete-by-name-local-exact-report.json @@ -0,0 +1,87 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00183", + "operation": "ANIM_KEYFRAME_DELETE_BY_NAME_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00183-operator-anim.keyframe_delete_by_name.blend", + "sha256": "ea5a587aeeabd6692977d5a7660bf49bb7134d4fc81e8ff1a3fa9acd8a75026c" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00183/anim-keyframe-delete-by-name-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "KEYFRAME_DELETED", + "before": { + "channels": [ + { + "frames": [ + 1, + 3, + 5 + ], + "index": 0, + "path": "[\"delete_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1, + 3, + 5 + ] + } + ], + "name": "WebGapAnimKeyframeDeleteByNameAction" + }, + "after": { + "channels": [ + { + "frames": [ + 1, + 5 + ], + "index": 0, + "path": "[\"delete_target\"]", + "selected": [ + true, + true + ], + "values": [ + 1, + 5 + ] + } + ], + "name": "WebGapAnimKeyframeDeleteByNameAction" + } + }, + "wasm": { + "status": "EXACT", + "before": { + "animationId": "action:WebGapAnimKeyframeDeleteByNameAction:object:WebGapAnimKeyframeDeleteByNameObject", + "targetId": "object:WebGapAnimKeyframeDeleteByNameObject", + "channelPaths": [ + "[\"delete_target\"][0]" + ], + "keyframesPerChannel": [ + 3 + ] + }, + "after": { + "animationId": "action:WebGapAnimKeyframeDeleteByNameAction:object:WebGapAnimKeyframeDeleteByNameObject", + "keyframesPerChannel": [ + 2 + ], + "keyframeDeleted": true + } + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00184" +} diff --git a/tests/golden/M16-GAP-00183/manifest.json b/tests/golden/M16-GAP-00183/manifest.json new file mode 100644 index 00000000..9f13da1f --- /dev/null +++ b/tests/golden/M16-GAP-00183/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00183", + "parentTask": "M16-GAP-00182", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_KEYFRAME_DELETE_BY_NAME_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00182/manifest.json", + "sha256": "75787ace3726209e5ff0058c6ab8787d8eb6a386318ab2bf50c79457f587bf87" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00183-operator-anim.keyframe_delete_by_name.blend", + "sha256": "ea5a587aeeabd6692977d5a7660bf49bb7134d4fc81e8ff1a3fa9acd8a75026c" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00183.py", + "sha256": "482995ad5ea8beeb8e6a3c4a004de282587d09f5186bac854a0513c747e316b0" + }, + "desktopChecker": { + "path": "tools/web/check-action-keyframe-delete-by-name-desktop.py", + "sha256": "b3c5726677eb6881950a96a13b5221eb74d5b4e13be118ad7f20679c842a64ea" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "e68c992056b117cc4d0e38752e4ad37ed25843fc0f4431459e527f83ef56d3eb" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "8824ba3dfb4090b85dc679a583d263b4bdb190a47978f72f3c11f6b565fdacaf" + }, + "protocol": { + "path": "web/protocol/editor-workflow.ts", + "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" + }, + "sceneIrProtocol": { + "path": "web/protocol/scene-ir.ts", + "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "9c831d0351ac9d0714cce3b1da748cba416ced3086e3c59595cf24ac4da459ed" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00183/anim-keyframe-delete-by-name-desktop-report.json", + "sha256": "105d464e66e7ac9c3cee66c3a33a47101c95b08f9851a875373d43370c48f70e" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00183/anim-keyframe-delete-by-name-local-exact-report.json", + "sha256": "3e8dd9268e4aa73f673dbbe5c9abc3d9c00acfdbe1cc019673c49925e342deca" + }, + "status": { + "path": "docs/status/M16-GAP-00183.md", + "sha256": "e583e704854dd1eca1fa5c672c3184cef8e2433138628aee92b11fb8a3345f98" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00183/task-context.json", + "sha256": "655cf1b0482f7159b63228a6db2bd2828836d707147f3de74727e9fcdc8a07f4" + } + }, + "nextTask": "M16-GAP-00184" +} diff --git a/tests/golden/M16-GAP-00183/task-context.json b/tests/golden/M16-GAP-00183/task-context.json new file mode 100644 index 00000000..2bb8c85c --- /dev/null +++ b/tests/golden/M16-GAP-00183/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00183", + "parentTask": "M16-GAP-00182", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.keyframe_delete_by_name data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.keyframe_delete_by_name", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00183.py -- tests/files/web/generated/M16-GAP-00183-operator-anim.keyframe_delete_by_name.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00183", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00183" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00183.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1678, + "contextRemainingTokens": 418 + }, + "source": { + "bytes": 8226, + "tokens": 2058 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00183.py", + "bytes": 1654, + "tokens": 414 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00183-operator-anim.keyframe_delete_by_name.blend", + "bytes": 86770, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 231498, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 405874, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00183/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00183.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00183/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1654, + "tokens": 414 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00184", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00183.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00182/manifest.json", + "parentStatus": "docs/status/M16-GAP-00182.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00183.md", + "tests/golden/M16-GAP-00182/manifest.json", + "docs/status/M16-GAP-00182.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00182", + "parentTask": "M16-GAP-00181", + "status": "done", + "nextTask": "M16-GAP-00183", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00182 Status", + "status: done", + "task: anim.keyframe_delete_button operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one selected object with a custom `delete_target` property and an Action keyed at frames 1, 3, and 5. A registered Properties panel exposes the animated property as a real UI button. A foreground Properties context invokes `ANIM_OT_keyframe_delete_button(all=true)` through that active button at frame 3 (`poll=true`, `FINISHED`), deleting only the current keyframe and preserving the two surrounding keys.", + "evidence:", + "- Desktop evidence records the selected/active object changing from `[1, 3, 5]` to `[1, 5]`; the custom property remains at 3.0 and save/reopen is exact." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1829, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 458 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00183.md", + "bytes": 1829, + "lines": 38, + "tokens": 458 + }, + { + "path": "tests/golden/M16-GAP-00182/manifest.json", + "bytes": 2941, + "lines": 74, + "tokens": 736 + }, + { + "path": "docs/status/M16-GAP-00182.md", + "bytes": 1288, + "lines": 18, + "tokens": 322 + } + ], + "sourceTokens": 2058, + "evidenceFiles": 1, + "evidenceBytes": 1654, + "evidenceTokens": 414, + "totalTokens": 2472, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3496, + "serializedContextTokens": 760, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00184/anim-keyframe-delete-v3d-desktop-report.json b/tests/golden/M16-GAP-00184/anim-keyframe-delete-v3d-desktop-report.json new file mode 100644 index 00000000..02dbe775 --- /dev/null +++ b/tests/golden/M16-GAP-00184/anim-keyframe-delete-v3d-desktop-report.json @@ -0,0 +1,67 @@ +{ + "after": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 5.0 + ], + "index": 0, + "path": "[\"delete_target\"]", + "selected": [ + true, + true + ], + "values": [ + 1.0, + 5.0 + ] + } + ], + "name": "WebGapAnimKeyframeDeleteV3DAction" + }, + "active": true, + "selected": true, + "value": 3.0 + }, + "before": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"delete_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1.0, + 3.0, + 5.0 + ] + } + ], + "name": "WebGapAnimKeyframeDeleteV3DAction" + }, + "active": true, + "selected": true, + "value": 3.0 + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00184-operator-anim.keyframe_delete_v3d.blend", + "fixtureSha256": "56cc035995506dfa6c68efced79708c11dc50a20ac3d0e7e9ee59fe29e741995", + "mainMutation": "KEYFRAME_DELETED", + "operation": "ANIM_KEYFRAME_DELETE_V3D_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00184" +} diff --git a/tests/golden/M16-GAP-00184/anim-keyframe-delete-v3d-local-exact-report.json b/tests/golden/M16-GAP-00184/anim-keyframe-delete-v3d-local-exact-report.json new file mode 100644 index 00000000..d4d9c2ea --- /dev/null +++ b/tests/golden/M16-GAP-00184/anim-keyframe-delete-v3d-local-exact-report.json @@ -0,0 +1,87 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00184", + "operation": "ANIM_KEYFRAME_DELETE_V3D_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00184-operator-anim.keyframe_delete_v3d.blend", + "sha256": "56cc035995506dfa6c68efced79708c11dc50a20ac3d0e7e9ee59fe29e741995" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00184/anim-keyframe-delete-v3d-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "KEYFRAME_DELETED", + "before": { + "channels": [ + { + "frames": [ + 1, + 3, + 5 + ], + "index": 0, + "path": "[\"delete_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1, + 3, + 5 + ] + } + ], + "name": "WebGapAnimKeyframeDeleteV3DAction" + }, + "after": { + "channels": [ + { + "frames": [ + 1, + 5 + ], + "index": 0, + "path": "[\"delete_target\"]", + "selected": [ + true, + true + ], + "values": [ + 1, + 5 + ] + } + ], + "name": "WebGapAnimKeyframeDeleteV3DAction" + } + }, + "wasm": { + "status": "EXACT", + "before": { + "animationId": "action:WebGapAnimKeyframeDeleteV3DAction:object:WebGapAnimKeyframeDeleteV3DObject", + "targetId": "object:WebGapAnimKeyframeDeleteV3DObject", + "channelPaths": [ + "[\"delete_target\"][0]" + ], + "keyframesPerChannel": [ + 3 + ] + }, + "after": { + "animationId": "action:WebGapAnimKeyframeDeleteV3DAction:object:WebGapAnimKeyframeDeleteV3DObject", + "keyframesPerChannel": [ + 2 + ], + "keyframeDeleted": true + } + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00185" +} diff --git a/tests/golden/M16-GAP-00184/manifest.json b/tests/golden/M16-GAP-00184/manifest.json new file mode 100644 index 00000000..89055582 --- /dev/null +++ b/tests/golden/M16-GAP-00184/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00184", + "parentTask": "M16-GAP-00183", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_KEYFRAME_DELETE_V3D_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00183/manifest.json", + "sha256": "a792624c1a6c90440244488e345af7637a8451d9caa33495368356041aed8273" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00184-operator-anim.keyframe_delete_v3d.blend", + "sha256": "56cc035995506dfa6c68efced79708c11dc50a20ac3d0e7e9ee59fe29e741995" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00184.py", + "sha256": "9bd3112772fe91a57b1cb89a781067316442d4d06e7fbd7fc84429a67fe0272a" + }, + "desktopChecker": { + "path": "tools/web/check-action-keyframe-delete-v3d-desktop.py", + "sha256": "a761edaab49b1a81a7374a465b64b67836ebe06fba9626ba3d5233f91072d541" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "c28933770f3e0af5e792921658d19f9618a439610b8ddc34618d6b70b5a15dcf" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "8824ba3dfb4090b85dc679a583d263b4bdb190a47978f72f3c11f6b565fdacaf" + }, + "protocol": { + "path": "web/protocol/editor-workflow.ts", + "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" + }, + "sceneIrProtocol": { + "path": "web/protocol/scene-ir.ts", + "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "9c831d0351ac9d0714cce3b1da748cba416ced3086e3c59595cf24ac4da459ed" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00184/anim-keyframe-delete-v3d-desktop-report.json", + "sha256": "576e712c7d4d72dc15fc2b9a4b65748c2ddd4b43f69c86a57e3365621f19db43" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00184/anim-keyframe-delete-v3d-local-exact-report.json", + "sha256": "3737dbe1e6189cd8312cc3cd3f328e764b2a9ce173a48946e9413a82e8fa4a47" + }, + "status": { + "path": "docs/status/M16-GAP-00184.md", + "sha256": "44d3f28d968aae9c4315f08dd7581cca309347a839e20db4b8f19288bfbe706e" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00184/task-context.json", + "sha256": "41f3f005f99d3e9130a4335fa5cde7982598096f57756e5760f092d3b78792ec" + } + }, + "nextTask": "M16-GAP-00185" +} diff --git a/tests/golden/M16-GAP-00184/task-context.json b/tests/golden/M16-GAP-00184/task-context.json new file mode 100644 index 00000000..b56f3716 --- /dev/null +++ b/tests/golden/M16-GAP-00184/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00184", + "parentTask": "M16-GAP-00183", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.keyframe_delete_v3d data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.keyframe_delete_v3d", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00184.py -- tests/files/web/generated/M16-GAP-00184-operator-anim.keyframe_delete_v3d.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00184", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00184" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00184.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1711, + "contextRemainingTokens": 426 + }, + "source": { + "bytes": 8193, + "tokens": 2050 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00184.py", + "bytes": 1392, + "tokens": 348 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00184-operator-anim.keyframe_delete_v3d.blend", + "bytes": 86712, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 231498, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 411636, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00184/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00184.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00184/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1392, + "tokens": 348 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00185", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00184.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00183/manifest.json", + "parentStatus": "docs/status/M16-GAP-00183.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00184.md", + "tests/golden/M16-GAP-00183/manifest.json", + "docs/status/M16-GAP-00183.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00183", + "parentTask": "M16-GAP-00182", + "status": "done", + "nextTask": "M16-GAP-00184", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00183 Status", + "status: done", + "task: anim.keyframe_delete_by_name operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one selected object with a custom `delete_target` property and an Action keyed at frames 1, 3, and 5. A named Keying Set targets that property. A foreground `VIEW_3D` context invokes `ANIM_OT_keyframe_delete_by_name(type=WebGapAnimKeyframeDeleteByNameSet)` (`poll=true`, `FINISHED`) at frame 3, deleting only the current keyframe and preserving the two surrounding keys.", + "evidence:", + "- Desktop evidence records the selected/active object and named Keying Set changing from `[1, 3, 5]` to `[1, 5]`; the custom property remains at 3.0 and save/reopen is exact." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1809, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 453 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00184.md", + "bytes": 1809, + "lines": 38, + "tokens": 453 + }, + { + "path": "tests/golden/M16-GAP-00183/manifest.json", + "bytes": 2946, + "lines": 74, + "tokens": 737 + }, + { + "path": "docs/status/M16-GAP-00183.md", + "bytes": 1270, + "lines": 18, + "tokens": 318 + } + ], + "sourceTokens": 2050, + "evidenceFiles": 1, + "evidenceBytes": 1392, + "evidenceTokens": 348, + "totalTokens": 2398, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3422, + "serializedContextTokens": 757, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00185/anim-keyframe-delete-vse-desktop-report.json b/tests/golden/M16-GAP-00185/anim-keyframe-delete-vse-desktop-report.json new file mode 100644 index 00000000..9e2b1723 --- /dev/null +++ b/tests/golden/M16-GAP-00185/anim-keyframe-delete-vse-desktop-report.json @@ -0,0 +1,67 @@ +{ + "after": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 5.0 + ], + "index": 0, + "path": "sequence_editor.strips_all[\"WebGapAnimKeyframeDeleteVSEStrip\"].blend_alpha", + "selected": [ + true, + true + ], + "values": [ + 0.25, + 0.75 + ] + } + ], + "name": "WebGapAnimKeyframeDeleteVSEAction" + }, + "active": true, + "blendAlpha": 0.5, + "selected": true + }, + "before": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "sequence_editor.strips_all[\"WebGapAnimKeyframeDeleteVSEStrip\"].blend_alpha", + "selected": [ + true, + true, + true + ], + "values": [ + 0.25, + 0.5, + 0.75 + ] + } + ], + "name": "WebGapAnimKeyframeDeleteVSEAction" + }, + "active": true, + "blendAlpha": 0.5, + "selected": true + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00185-operator-anim.keyframe_delete_vse.blend", + "fixtureSha256": "c01f342471fcae64138f95287363f0e801c4da96992aa4a3d8a4173b0ec0f464", + "mainMutation": "KEYFRAME_DELETED", + "operation": "ANIM_KEYFRAME_DELETE_VSE_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00185" +} diff --git a/tests/golden/M16-GAP-00185/anim-keyframe-delete-vse-local-exact-report.json b/tests/golden/M16-GAP-00185/anim-keyframe-delete-vse-local-exact-report.json new file mode 100644 index 00000000..98af33a5 --- /dev/null +++ b/tests/golden/M16-GAP-00185/anim-keyframe-delete-vse-local-exact-report.json @@ -0,0 +1,87 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00185", + "operation": "ANIM_KEYFRAME_DELETE_VSE_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00185-operator-anim.keyframe_delete_vse.blend", + "sha256": "c01f342471fcae64138f95287363f0e801c4da96992aa4a3d8a4173b0ec0f464" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00185/anim-keyframe-delete-vse-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "KEYFRAME_DELETED", + "before": { + "channels": [ + { + "frames": [ + 1, + 3, + 5 + ], + "index": 0, + "path": "sequence_editor.strips_all[\"WebGapAnimKeyframeDeleteVSEStrip\"].blend_alpha", + "selected": [ + true, + true, + true + ], + "values": [ + 0.25, + 0.5, + 0.75 + ] + } + ], + "name": "WebGapAnimKeyframeDeleteVSEAction" + }, + "after": { + "channels": [ + { + "frames": [ + 1, + 5 + ], + "index": 0, + "path": "sequence_editor.strips_all[\"WebGapAnimKeyframeDeleteVSEStrip\"].blend_alpha", + "selected": [ + true, + true + ], + "values": [ + 0.25, + 0.75 + ] + } + ], + "name": "WebGapAnimKeyframeDeleteVSEAction" + } + }, + "wasm": { + "status": "EXACT", + "before": { + "animationId": "action:WebGapAnimKeyframeDeleteVSEAction:scene:Scene", + "targetId": "scene:Scene", + "channelPaths": [ + "sequence_editor.strips_all[\"WebGapAnimKeyframeDeleteVSEStrip\"].blend_alpha[0]" + ], + "keyframesPerChannel": [ + 3 + ] + }, + "after": { + "animationId": "action:WebGapAnimKeyframeDeleteVSEAction:scene:Scene", + "keyframesPerChannel": [ + 2 + ], + "keyframeDeleted": true + } + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00186" +} diff --git a/tests/golden/M16-GAP-00185/manifest.json b/tests/golden/M16-GAP-00185/manifest.json new file mode 100644 index 00000000..e61ade11 --- /dev/null +++ b/tests/golden/M16-GAP-00185/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00185", + "parentTask": "M16-GAP-00184", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_KEYFRAME_DELETE_VSE_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00184/manifest.json", + "sha256": "73843947605c1cb981fae06d47682662bcfe259534e57cb46ee6404b34d041fc" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00185-operator-anim.keyframe_delete_vse.blend", + "sha256": "c01f342471fcae64138f95287363f0e801c4da96992aa4a3d8a4173b0ec0f464" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00185.py", + "sha256": "9abb73d74b639eef255794c35ce8bb102959a53d4d12f8818d45c28946b1e791" + }, + "desktopChecker": { + "path": "tools/web/check-action-keyframe-delete-vse-desktop.py", + "sha256": "67f18d3fc73b9e16cdccc572f551eb2f0f16d496db952889678189eb8fa9253d" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "edc37dc02748b741ab2842a8a3bad665c5e9af18b74c0ef04d6b86cf29e85f66" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "8824ba3dfb4090b85dc679a583d263b4bdb190a47978f72f3c11f6b565fdacaf" + }, + "protocol": { + "path": "web/protocol/editor-workflow.ts", + "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" + }, + "sceneIrProtocol": { + "path": "web/protocol/scene-ir.ts", + "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "9c831d0351ac9d0714cce3b1da748cba416ced3086e3c59595cf24ac4da459ed" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00185/anim-keyframe-delete-vse-desktop-report.json", + "sha256": "a7fb103d0746837b7d56ae89e6b8fa6de374f11cfff8cdf79d88fba199449721" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00185/anim-keyframe-delete-vse-local-exact-report.json", + "sha256": "aecbd1f8b711b2299db7e7665931a549a7318d638942eb2d343d680fc0ce5acc" + }, + "status": { + "path": "docs/status/M16-GAP-00185.md", + "sha256": "de8e22ea2619605053b10e19061de49f94ed241fba16c8b7aa0b0099be3a3b2b" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00185/task-context.json", + "sha256": "3badb8af0ff6bd1168e2576568f8be4c44f4b77a175ea86b8e6650a9ef92077f" + } + }, + "nextTask": "M16-GAP-00186" +} diff --git a/tests/golden/M16-GAP-00185/task-context.json b/tests/golden/M16-GAP-00185/task-context.json new file mode 100644 index 00000000..e2bd16b7 --- /dev/null +++ b/tests/golden/M16-GAP-00185/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00185", + "parentTask": "M16-GAP-00184", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.keyframe_delete_vse data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.keyframe_delete_vse", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00185.py -- tests/files/web/generated/M16-GAP-00185-operator-anim.keyframe_delete_vse.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00185", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00185" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00185.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1820, + "contextRemainingTokens": 453 + }, + "source": { + "bytes": 8084, + "tokens": 2023 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00185.py", + "bytes": 1371, + "tokens": 343 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00185-operator-anim.keyframe_delete_vse.blend", + "bytes": 86629, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 231498, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 417633, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00185/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00185.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00185/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1371, + "tokens": 343 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00186", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00185.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00184/manifest.json", + "parentStatus": "docs/status/M16-GAP-00184.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00185.md", + "tests/golden/M16-GAP-00184/manifest.json", + "docs/status/M16-GAP-00184.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00184", + "parentTask": "M16-GAP-00183", + "status": "done", + "nextTask": "M16-GAP-00185", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00184 Status", + "status: done", + "task: anim.keyframe_delete_v3d operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one selected/active object with a custom `delete_target` property and an Action keyed at frames 1, 3, and 5. A foreground `VIEW_3D` context invokes `ANIM_OT_keyframe_delete_v3d(confirm=false)` (`poll=true`, `FINISHED`) at frame 3, deleting only the current keyframe and preserving the two surrounding keys.", + "evidence:", + "- Desktop evidence records the selected/active object changing from `[1, 3, 5]` to `[1, 5]`; the custom property remains at 3.0 and save/reopen is exact." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1809, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 453 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00185.md", + "bytes": 1809, + "lines": 38, + "tokens": 453 + }, + { + "path": "tests/golden/M16-GAP-00184/manifest.json", + "bytes": 2926, + "lines": 74, + "tokens": 732 + }, + { + "path": "docs/status/M16-GAP-00184.md", + "bytes": 1181, + "lines": 18, + "tokens": 296 + } + ], + "sourceTokens": 2023, + "evidenceFiles": 1, + "evidenceBytes": 1371, + "evidenceTokens": 343, + "totalTokens": 2366, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3390, + "serializedContextTokens": 757, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00186/anim-keyframe-insert-desktop-report.json b/tests/golden/M16-GAP-00186/anim-keyframe-insert-desktop-report.json new file mode 100644 index 00000000..e7bef874 --- /dev/null +++ b/tests/golden/M16-GAP-00186/anim-keyframe-insert-desktop-report.json @@ -0,0 +1,69 @@ +{ + "after": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"insert_target\"]", + "selected": [ + false, + true, + false + ], + "values": [ + 1.0, + 3.0, + 5.0 + ] + } + ], + "name": "WebGapAnimKeyframeInsertAction" + }, + "active": true, + "activeKeyingSet": "WebGapAnimKeyframeInsertSet", + "selected": true, + "value": 3.0 + }, + "before": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 5.0 + ], + "index": 0, + "path": "[\"insert_target\"]", + "selected": [ + true, + true + ], + "values": [ + 1.0, + 5.0 + ] + } + ], + "name": "WebGapAnimKeyframeInsertAction" + }, + "active": true, + "activeKeyingSet": "WebGapAnimKeyframeInsertSet", + "selected": true, + "value": 3.0 + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00186-operator-anim.keyframe_insert.blend", + "fixtureSha256": "582dfb8c8dfe6897937afa687d5ebfdb4aeb2e3ae7db73ed02cf6385745bbf70", + "mainMutation": "KEYFRAME_INSERTED", + "operation": "ANIM_KEYFRAME_INSERT_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00186" +} diff --git a/tests/golden/M16-GAP-00186/anim-keyframe-insert-local-exact-report.json b/tests/golden/M16-GAP-00186/anim-keyframe-insert-local-exact-report.json new file mode 100644 index 00000000..8da862b4 --- /dev/null +++ b/tests/golden/M16-GAP-00186/anim-keyframe-insert-local-exact-report.json @@ -0,0 +1,87 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00186", + "operation": "ANIM_KEYFRAME_INSERT_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00186-operator-anim.keyframe_insert.blend", + "sha256": "582dfb8c8dfe6897937afa687d5ebfdb4aeb2e3ae7db73ed02cf6385745bbf70" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00186/anim-keyframe-insert-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "KEYFRAME_INSERTED", + "before": { + "channels": [ + { + "frames": [ + 1, + 5 + ], + "index": 0, + "path": "[\"insert_target\"]", + "selected": [ + true, + true + ], + "values": [ + 1, + 5 + ] + } + ], + "name": "WebGapAnimKeyframeInsertAction" + }, + "after": { + "channels": [ + { + "frames": [ + 1, + 3, + 5 + ], + "index": 0, + "path": "[\"insert_target\"]", + "selected": [ + false, + true, + false + ], + "values": [ + 1, + 3, + 5 + ] + } + ], + "name": "WebGapAnimKeyframeInsertAction" + } + }, + "wasm": { + "status": "EXACT", + "before": { + "animationId": "action:WebGapAnimKeyframeInsertAction:object:WebGapAnimKeyframeInsertObject", + "targetId": "object:WebGapAnimKeyframeInsertObject", + "channelPaths": [ + "[\"insert_target\"][0]" + ], + "keyframesPerChannel": [ + 2 + ] + }, + "after": { + "animationId": "action:WebGapAnimKeyframeInsertAction:object:WebGapAnimKeyframeInsertObject", + "keyframesPerChannel": [ + 3 + ], + "keyframeInserted": true + } + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00187" +} diff --git a/tests/golden/M16-GAP-00186/manifest.json b/tests/golden/M16-GAP-00186/manifest.json new file mode 100644 index 00000000..6531ee81 --- /dev/null +++ b/tests/golden/M16-GAP-00186/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00186", + "parentTask": "M16-GAP-00185", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_KEYFRAME_INSERT_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00185/manifest.json", + "sha256": "0c4e04128b54580988cec59baaf08e1471be26050e380bea7eb9f21a2b092da3" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00186-operator-anim.keyframe_insert.blend", + "sha256": "582dfb8c8dfe6897937afa687d5ebfdb4aeb2e3ae7db73ed02cf6385745bbf70" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00186.py", + "sha256": "edd44185e79eb16c51f2160e5bec5d6ee5dd5ad2d1b662533fa0cfe399e713cd" + }, + "desktopChecker": { + "path": "tools/web/check-action-keyframe-insert-desktop.py", + "sha256": "4c09e55f4f9935b4b4be4c7212451a5c1b01a569aa446c94fe80cdbaff5acda9" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "e32fecfab5c014387399f183d2f715194d32809bfbb9f86894730fce4fb99b98" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "8824ba3dfb4090b85dc679a583d263b4bdb190a47978f72f3c11f6b565fdacaf" + }, + "protocol": { + "path": "web/protocol/editor-workflow.ts", + "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" + }, + "sceneIrProtocol": { + "path": "web/protocol/scene-ir.ts", + "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "9c831d0351ac9d0714cce3b1da748cba416ced3086e3c59595cf24ac4da459ed" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00186/anim-keyframe-insert-desktop-report.json", + "sha256": "dfb8191a85b427ab80a3f6cb2fa118f0f7ddc1ce895b93c8c6e4ddf34f4d780c" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00186/anim-keyframe-insert-local-exact-report.json", + "sha256": "17e4943e084a1323e1de9eca68039b4a6a9e9d060c9e3d3e44e663c8a9d93ce1" + }, + "status": { + "path": "docs/status/M16-GAP-00186.md", + "sha256": "1f2f3ec3947f4593dd5204d1058a125127f396013063a8fa0d447c189f4f50ce" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00186/task-context.json", + "sha256": "4115c25ef7bce2ce0cd3fcadedf6c8aba24fbcd4eb0f037f60f1d0548316d540" + } + }, + "nextTask": "M16-GAP-00187" +} diff --git a/tests/golden/M16-GAP-00186/task-context.json b/tests/golden/M16-GAP-00186/task-context.json new file mode 100644 index 00000000..5cc7e0d7 --- /dev/null +++ b/tests/golden/M16-GAP-00186/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00186", + "parentTask": "M16-GAP-00185", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.keyframe_insert data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.keyframe_insert", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00186.py -- tests/files/web/generated/M16-GAP-00186-operator-anim.keyframe_insert.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00186", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00186" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00186.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1774, + "contextRemainingTokens": 442 + }, + "source": { + "bytes": 8130, + "tokens": 2034 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00186.py", + "bytes": 1651, + "tokens": 413 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00186-operator-anim.keyframe_insert.blend", + "bytes": 86814, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 231498, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 423464, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00186/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00186.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00186/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1651, + "tokens": 413 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00187", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00186.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00185/manifest.json", + "parentStatus": "docs/status/M16-GAP-00185.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00186.md", + "tests/golden/M16-GAP-00185/manifest.json", + "docs/status/M16-GAP-00185.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00185", + "parentTask": "M16-GAP-00184", + "status": "done", + "nextTask": "M16-GAP-00186", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00185 Status", + "status: done", + "task: anim.keyframe_delete_vse operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one selected/active image strip with a Scene Action animating `blend_alpha` at frames 1, 3, and 5. A foreground `SEQUENCE_EDITOR` context invokes `ANIM_OT_keyframe_delete_vse(confirm=false)` (`poll=true`, `FINISHED`) at frame 3, deleting only the current strip keyframe and preserving the two surrounding keys.", + "evidence:", + "- Desktop evidence records the selected/active strip changing from `[1, 3, 5]` to `[1, 5]`; `blend_alpha` remains 0.5 at frame 3 and save/reopen is exact." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1789, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 448 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00186.md", + "bytes": 1789, + "lines": 38, + "tokens": 448 + }, + { + "path": "tests/golden/M16-GAP-00185/manifest.json", + "bytes": 2926, + "lines": 74, + "tokens": 732 + }, + { + "path": "docs/status/M16-GAP-00185.md", + "bytes": 1247, + "lines": 18, + "tokens": 312 + } + ], + "sourceTokens": 2034, + "evidenceFiles": 1, + "evidenceBytes": 1651, + "evidenceTokens": 413, + "totalTokens": 2447, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3471, + "serializedContextTokens": 754, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00187/anim-keyframe-insert-button-desktop-report.json b/tests/golden/M16-GAP-00187/anim-keyframe-insert-button-desktop-report.json new file mode 100644 index 00000000..7fcbab25 --- /dev/null +++ b/tests/golden/M16-GAP-00187/anim-keyframe-insert-button-desktop-report.json @@ -0,0 +1,67 @@ +{ + "after": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"insert_target\"]", + "selected": [ + false, + true, + false + ], + "values": [ + 1.0, + 3.0, + 5.0 + ] + } + ], + "name": "WebGapAnimKeyframeInsertButtonAction" + }, + "active": true, + "selected": true, + "value": 3.0 + }, + "before": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 5.0 + ], + "index": 0, + "path": "[\"insert_target\"]", + "selected": [ + true, + true + ], + "values": [ + 1.0, + 5.0 + ] + } + ], + "name": "WebGapAnimKeyframeInsertButtonAction" + }, + "active": true, + "selected": true, + "value": 3.0 + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00187-operator-anim.keyframe_insert_button.blend", + "fixtureSha256": "5398394b340d509043a2e8130249dbbb0736fa540c833a303445c07c9f775e9a", + "mainMutation": "KEYFRAME_INSERTED", + "operation": "ANIM_KEYFRAME_INSERT_BUTTON_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00187" +} diff --git a/tests/golden/M16-GAP-00187/anim-keyframe-insert-button-local-exact-report.json b/tests/golden/M16-GAP-00187/anim-keyframe-insert-button-local-exact-report.json new file mode 100644 index 00000000..3365c5a5 --- /dev/null +++ b/tests/golden/M16-GAP-00187/anim-keyframe-insert-button-local-exact-report.json @@ -0,0 +1,87 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00187", + "operation": "ANIM_KEYFRAME_INSERT_BUTTON_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00187-operator-anim.keyframe_insert_button.blend", + "sha256": "5398394b340d509043a2e8130249dbbb0736fa540c833a303445c07c9f775e9a" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00187/anim-keyframe-insert-button-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "KEYFRAME_INSERTED", + "before": { + "channels": [ + { + "frames": [ + 1, + 5 + ], + "index": 0, + "path": "[\"insert_target\"]", + "selected": [ + true, + true + ], + "values": [ + 1, + 5 + ] + } + ], + "name": "WebGapAnimKeyframeInsertButtonAction" + }, + "after": { + "channels": [ + { + "frames": [ + 1, + 3, + 5 + ], + "index": 0, + "path": "[\"insert_target\"]", + "selected": [ + false, + true, + false + ], + "values": [ + 1, + 3, + 5 + ] + } + ], + "name": "WebGapAnimKeyframeInsertButtonAction" + } + }, + "wasm": { + "status": "EXACT", + "before": { + "animationId": "action:WebGapAnimKeyframeInsertButtonAction:object:WebGapAnimKeyframeInsertButtonObject", + "targetId": "object:WebGapAnimKeyframeInsertButtonObject", + "channelPaths": [ + "[\"insert_target\"][0]" + ], + "keyframesPerChannel": [ + 2 + ] + }, + "after": { + "animationId": "action:WebGapAnimKeyframeInsertButtonAction:object:WebGapAnimKeyframeInsertButtonObject", + "keyframesPerChannel": [ + 3 + ], + "keyframeInserted": true + } + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00188" +} diff --git a/tests/golden/M16-GAP-00187/manifest.json b/tests/golden/M16-GAP-00187/manifest.json new file mode 100644 index 00000000..41fc7aa7 --- /dev/null +++ b/tests/golden/M16-GAP-00187/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00187", + "parentTask": "M16-GAP-00186", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_KEYFRAME_INSERT_BUTTON_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00186/manifest.json", + "sha256": "fc77d169050a1bd032820da68dd63e059878188faa2eb88ab1fc7ffc5041548d" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00187-operator-anim.keyframe_insert_button.blend", + "sha256": "5398394b340d509043a2e8130249dbbb0736fa540c833a303445c07c9f775e9a" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00187.py", + "sha256": "7eaac0eb63db785dea7da7df596fa19ed5447b356b13667c5f25e5ee1cecf14d" + }, + "desktopChecker": { + "path": "tools/web/check-action-keyframe-insert-button-desktop.py", + "sha256": "0fa0478deb1eb742105b5902070e5764113378ed1c7d390155cd2be61e991b08" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "cd43c016cf91a8e258f8f6a53dd4148c6986bd2ccddfc6f16272ab163bb2419b" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "8824ba3dfb4090b85dc679a583d263b4bdb190a47978f72f3c11f6b565fdacaf" + }, + "protocol": { + "path": "web/protocol/editor-workflow.ts", + "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" + }, + "sceneIrProtocol": { + "path": "web/protocol/scene-ir.ts", + "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "9c831d0351ac9d0714cce3b1da748cba416ced3086e3c59595cf24ac4da459ed" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00187/anim-keyframe-insert-button-desktop-report.json", + "sha256": "b7de5f8ac81d96e316a6d13b1f03650339841bf043ff3a4c9b3396a14420f506" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00187/anim-keyframe-insert-button-local-exact-report.json", + "sha256": "460c2285310d2cf456ced4f1438ab6fd609a1470dde4a37cd09b349099f90873" + }, + "status": { + "path": "docs/status/M16-GAP-00187.md", + "sha256": "16c75cd97e157bcb23bce603f7e27f6f095ce1c76c3f11501355a9431472e691" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00187/task-context.json", + "sha256": "cdfc0b01d9e76dfaed39d9e6c44836cf3aea3df2a363689177e775d2286e0182" + } + }, + "nextTask": "M16-GAP-00188" +} diff --git a/tests/golden/M16-GAP-00187/task-context.json b/tests/golden/M16-GAP-00187/task-context.json new file mode 100644 index 00000000..5afcf9c2 --- /dev/null +++ b/tests/golden/M16-GAP-00187/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00187", + "parentTask": "M16-GAP-00186", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.keyframe_insert_button data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.keyframe_insert_button", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00187.py -- tests/files/web/generated/M16-GAP-00187-operator-anim.keyframe_insert_button.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00187", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00187" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00187.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1772, + "contextRemainingTokens": 442 + }, + "source": { + "bytes": 8132, + "tokens": 2034 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00187.py", + "bytes": 1346, + "tokens": 337 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00187-operator-anim.keyframe_insert_button.blend", + "bytes": 86812, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 231498, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 429105, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00187/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00187.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00187/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1346, + "tokens": 337 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00188", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00187.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00186/manifest.json", + "parentStatus": "docs/status/M16-GAP-00186.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00187.md", + "tests/golden/M16-GAP-00186/manifest.json", + "docs/status/M16-GAP-00186.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00186", + "parentTask": "M16-GAP-00185", + "status": "done", + "nextTask": "M16-GAP-00187", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00186 Status", + "status: done", + "task: anim.keyframe_insert operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one selected/active object with a custom `insert_target` property and a named active Keying Set. Its Action starts with keys at frames 1 and 5. A foreground `VIEW_3D` context invokes `ANIM_OT_keyframe_insert()` (`poll=true`, `FINISHED`) at frame 3, inserting the current key while preserving the existing keys.", + "evidence:", + "- Desktop evidence records the Action changing from `[1, 5]` to `[1, 3, 5]`; the inserted key is the only selected key (`[false, true, false]`), the custom property remains at 3.0, and save/reopen is exact." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1824, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 456 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00187.md", + "bytes": 1824, + "lines": 38, + "tokens": 456 + }, + { + "path": "tests/golden/M16-GAP-00186/manifest.json", + "bytes": 2906, + "lines": 74, + "tokens": 727 + }, + { + "path": "docs/status/M16-GAP-00186.md", + "bytes": 1234, + "lines": 18, + "tokens": 309 + } + ], + "sourceTokens": 2034, + "evidenceFiles": 1, + "evidenceBytes": 1346, + "evidenceTokens": 337, + "totalTokens": 2371, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3395, + "serializedContextTokens": 760, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00188/anim-keyframe-insert-by-name-desktop-report.json b/tests/golden/M16-GAP-00188/anim-keyframe-insert-by-name-desktop-report.json new file mode 100644 index 00000000..7b449ac9 --- /dev/null +++ b/tests/golden/M16-GAP-00188/anim-keyframe-insert-by-name-desktop-report.json @@ -0,0 +1,69 @@ +{ + "after": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"insert_target\"]", + "selected": [ + false, + true, + false + ], + "values": [ + 1.0, + 3.0, + 5.0 + ] + } + ], + "name": "WebGapAnimKeyframeInsertByNameAction" + }, + "active": true, + "activeKeyingSet": "WebGapAnimKeyframeInsertByNameSet", + "selected": true, + "value": 3.0 + }, + "before": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 5.0 + ], + "index": 0, + "path": "[\"insert_target\"]", + "selected": [ + true, + true + ], + "values": [ + 1.0, + 5.0 + ] + } + ], + "name": "WebGapAnimKeyframeInsertByNameAction" + }, + "active": true, + "activeKeyingSet": "WebGapAnimKeyframeInsertByNameSet", + "selected": true, + "value": 3.0 + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00188-operator-anim.keyframe_insert_by_name.blend", + "fixtureSha256": "b0be38528561fad722c52000ced9b4c44bff594d5fcf134ab89295ab8b97554d", + "mainMutation": "KEYFRAME_INSERTED", + "operation": "ANIM_KEYFRAME_INSERT_BY_NAME_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00188" +} diff --git a/tests/golden/M16-GAP-00188/anim-keyframe-insert-by-name-local-exact-report.json b/tests/golden/M16-GAP-00188/anim-keyframe-insert-by-name-local-exact-report.json new file mode 100644 index 00000000..699f1340 --- /dev/null +++ b/tests/golden/M16-GAP-00188/anim-keyframe-insert-by-name-local-exact-report.json @@ -0,0 +1,87 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00188", + "operation": "ANIM_KEYFRAME_INSERT_BY_NAME_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00188-operator-anim.keyframe_insert_by_name.blend", + "sha256": "b0be38528561fad722c52000ced9b4c44bff594d5fcf134ab89295ab8b97554d" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00188/anim-keyframe-insert-by-name-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "KEYFRAME_INSERTED", + "before": { + "channels": [ + { + "frames": [ + 1, + 5 + ], + "index": 0, + "path": "[\"insert_target\"]", + "selected": [ + true, + true + ], + "values": [ + 1, + 5 + ] + } + ], + "name": "WebGapAnimKeyframeInsertByNameAction" + }, + "after": { + "channels": [ + { + "frames": [ + 1, + 3, + 5 + ], + "index": 0, + "path": "[\"insert_target\"]", + "selected": [ + false, + true, + false + ], + "values": [ + 1, + 3, + 5 + ] + } + ], + "name": "WebGapAnimKeyframeInsertByNameAction" + } + }, + "wasm": { + "status": "EXACT", + "before": { + "animationId": "action:WebGapAnimKeyframeInsertByNameAction:object:WebGapAnimKeyframeInsertByNameObject", + "targetId": "object:WebGapAnimKeyframeInsertByNameObject", + "channelPaths": [ + "[\"insert_target\"][0]" + ], + "keyframesPerChannel": [ + 2 + ] + }, + "after": { + "animationId": "action:WebGapAnimKeyframeInsertByNameAction:object:WebGapAnimKeyframeInsertByNameObject", + "keyframesPerChannel": [ + 3 + ], + "keyframeInserted": true + } + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00189" +} diff --git a/tests/golden/M16-GAP-00188/manifest.json b/tests/golden/M16-GAP-00188/manifest.json new file mode 100644 index 00000000..da12dd4c --- /dev/null +++ b/tests/golden/M16-GAP-00188/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00188", + "parentTask": "M16-GAP-00187", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_KEYFRAME_INSERT_BY_NAME_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00187/manifest.json", + "sha256": "942eafb747f0d002ad2179d90f89acc64e3c347d340355895136689755a2052e" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00188-operator-anim.keyframe_insert_by_name.blend", + "sha256": "b0be38528561fad722c52000ced9b4c44bff594d5fcf134ab89295ab8b97554d" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00188.py", + "sha256": "109653bb9dd32d38ba755a6b284bdc75cca195894327db2f96feaf47faf8d935" + }, + "desktopChecker": { + "path": "tools/web/check-action-keyframe-insert-by-name-desktop.py", + "sha256": "754eaa916735252fd9a462629da646890fbb9285c201d569e36314ca1b1d8bb2" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "df1ae531630362ab3e5e6f7e7aef6abbbff3e0d1becd8da84bced5ae5dee258a" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "8824ba3dfb4090b85dc679a583d263b4bdb190a47978f72f3c11f6b565fdacaf" + }, + "protocol": { + "path": "web/protocol/editor-workflow.ts", + "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" + }, + "sceneIrProtocol": { + "path": "web/protocol/scene-ir.ts", + "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "9c831d0351ac9d0714cce3b1da748cba416ced3086e3c59595cf24ac4da459ed" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00188/anim-keyframe-insert-by-name-desktop-report.json", + "sha256": "d89d0950420ef0a81ca983619bf0f168b173e1a631769bcb4b342cfe3b2a9c09" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00188/anim-keyframe-insert-by-name-local-exact-report.json", + "sha256": "4928e35b98ac71b76c68fe2eccbd86481bb854123d428b1af66fbc7270df7e42" + }, + "status": { + "path": "docs/status/M16-GAP-00188.md", + "sha256": "bf958a16b78eae1da59438bfac089fcf16197982a23d91dbcd6d386942bc6425" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00188/task-context.json", + "sha256": "64ceb67dd3d00a7e07a5dd4f263527326442a591b1b5a404c2235809c05274d0" + } + }, + "nextTask": "M16-GAP-00189" +} diff --git a/tests/golden/M16-GAP-00188/task-context.json b/tests/golden/M16-GAP-00188/task-context.json new file mode 100644 index 00000000..21bde90f --- /dev/null +++ b/tests/golden/M16-GAP-00188/task-context.json @@ -0,0 +1,182 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00188", + "parentTask": "M16-GAP-00187", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.keyframe_insert_by_name data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.keyframe_insert_by_name", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00188.py -- tests/files/web/generated/M16-GAP-00188-operator-anim.keyframe_insert_by_name.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00188", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00188" + ], + "inputPaths": [], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1633, + "contextRemainingTokens": 406 + }, + "source": { + "bytes": 8271, + "tokens": 2070 + }, + "selected": [], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00188-operator-anim.keyframe_insert_by_name.blend", + "bytes": 86813, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/generated/M16-GAP-00188.py", + "bytes": 1665, + "reason": "CONTEXT_REMAINING_SPACE" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 231498, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 434821, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00188/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00188.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00188/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 0, + "bytes": 0, + "tokens": 0 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00189", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00188.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00187/manifest.json", + "parentStatus": "docs/status/M16-GAP-00187.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00188.md", + "tests/golden/M16-GAP-00187/manifest.json", + "docs/status/M16-GAP-00187.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00187", + "parentTask": "M16-GAP-00186", + "status": "done", + "nextTask": "M16-GAP-00188", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00187 Status", + "status: done", + "task: anim.keyframe_insert_button operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one selected/active object with a custom `insert_target` property and an Action keyed at frames 1 and 5. A registered Properties panel exposes the animated property as a real UI button. A foreground Properties context invokes `ANIM_OT_keyframe_insert_button(all=true)` through that active button at frame 3 (`poll=true`, `FINISHED`), inserting the current key while preserving the two existing keys.", + "evidence:", + "- Desktop evidence records the Action changing from `[1, 5]` to `[1, 3, 5]`; the inserted key is the only selected key (`[false, true, false]`), the custom property remains at 3.0 and save/reopen is exact." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1829, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 458 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00188.md", + "bytes": 1829, + "lines": 38, + "tokens": 458 + }, + { + "path": "tests/golden/M16-GAP-00187/manifest.json", + "bytes": 2941, + "lines": 74, + "tokens": 736 + }, + { + "path": "docs/status/M16-GAP-00187.md", + "bytes": 1333, + "lines": 18, + "tokens": 334 + } + ], + "sourceTokens": 2070, + "evidenceFiles": 0, + "evidenceBytes": 0, + "evidenceTokens": 0, + "totalTokens": 2070, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3094, + "serializedContextTokens": 725, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00189/anim-keyframe-insert-menu-desktop-report.json b/tests/golden/M16-GAP-00189/anim-keyframe-insert-menu-desktop-report.json new file mode 100644 index 00000000..88943a69 --- /dev/null +++ b/tests/golden/M16-GAP-00189/anim-keyframe-insert-menu-desktop-report.json @@ -0,0 +1,69 @@ +{ + "after": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"insert_target\"]", + "selected": [ + false, + true, + false + ], + "values": [ + 1.0, + 3.0, + 5.0 + ] + } + ], + "name": "WebGapAnimKeyframeInsertMenuAction" + }, + "active": true, + "activeKeyingSet": "WebGapAnimKeyframeInsertMenuSet", + "selected": true, + "value": 3.0 + }, + "before": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 5.0 + ], + "index": 0, + "path": "[\"insert_target\"]", + "selected": [ + true, + true + ], + "values": [ + 1.0, + 5.0 + ] + } + ], + "name": "WebGapAnimKeyframeInsertMenuAction" + }, + "active": true, + "activeKeyingSet": "WebGapAnimKeyframeInsertMenuSet", + "selected": true, + "value": 3.0 + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00189-operator-anim.keyframe_insert_menu.blend", + "fixtureSha256": "8c34e11c10c2de3de7209006c87594db1a1df0b62a6f9b92dac45f2cb176a52f", + "mainMutation": "KEYFRAME_INSERTED", + "operation": "ANIM_KEYFRAME_INSERT_MENU_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00189" +} diff --git a/tests/golden/M16-GAP-00189/anim-keyframe-insert-menu-local-exact-report.json b/tests/golden/M16-GAP-00189/anim-keyframe-insert-menu-local-exact-report.json new file mode 100644 index 00000000..2357abaa --- /dev/null +++ b/tests/golden/M16-GAP-00189/anim-keyframe-insert-menu-local-exact-report.json @@ -0,0 +1,87 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00189", + "operation": "ANIM_KEYFRAME_INSERT_MENU_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00189-operator-anim.keyframe_insert_menu.blend", + "sha256": "8c34e11c10c2de3de7209006c87594db1a1df0b62a6f9b92dac45f2cb176a52f" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00189/anim-keyframe-insert-menu-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "KEYFRAME_INSERTED", + "before": { + "channels": [ + { + "frames": [ + 1, + 5 + ], + "index": 0, + "path": "[\"insert_target\"]", + "selected": [ + true, + true + ], + "values": [ + 1, + 5 + ] + } + ], + "name": "WebGapAnimKeyframeInsertMenuAction" + }, + "after": { + "channels": [ + { + "frames": [ + 1, + 3, + 5 + ], + "index": 0, + "path": "[\"insert_target\"]", + "selected": [ + false, + true, + false + ], + "values": [ + 1, + 3, + 5 + ] + } + ], + "name": "WebGapAnimKeyframeInsertMenuAction" + } + }, + "wasm": { + "status": "EXACT", + "before": { + "animationId": "action:WebGapAnimKeyframeInsertMenuAction:object:WebGapAnimKeyframeInsertMenuObject", + "targetId": "object:WebGapAnimKeyframeInsertMenuObject", + "channelPaths": [ + "[\"insert_target\"][0]" + ], + "keyframesPerChannel": [ + 2 + ] + }, + "after": { + "animationId": "action:WebGapAnimKeyframeInsertMenuAction:object:WebGapAnimKeyframeInsertMenuObject", + "keyframesPerChannel": [ + 3 + ], + "keyframeInserted": true + } + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00190" +} diff --git a/tests/golden/M16-GAP-00189/manifest.json b/tests/golden/M16-GAP-00189/manifest.json new file mode 100644 index 00000000..ee8cf1ee --- /dev/null +++ b/tests/golden/M16-GAP-00189/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00189", + "parentTask": "M16-GAP-00188", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_KEYFRAME_INSERT_MENU_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00188/manifest.json", + "sha256": "1ea8b1c23b9e324634206e37e4b74f4714dd749a1d712d3a411a03d2be6aa3f7" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00189-operator-anim.keyframe_insert_menu.blend", + "sha256": "8c34e11c10c2de3de7209006c87594db1a1df0b62a6f9b92dac45f2cb176a52f" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00189.py", + "sha256": "20c8d28aea4b14e24dfe83e1b7c3906e8bf1f2ed1fbb723542320a7ece13f73f" + }, + "desktopChecker": { + "path": "tools/web/check-action-keyframe-insert-menu-desktop.py", + "sha256": "a8a378ecd1242852dac76e83d5a19412aa6caf70a85f23364f17d48c806bb921" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "1cb54ea443ad3162267407c789331cc5078dfb05b47f2f6f902132f016813b59" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "8824ba3dfb4090b85dc679a583d263b4bdb190a47978f72f3c11f6b565fdacaf" + }, + "protocol": { + "path": "web/protocol/editor-workflow.ts", + "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" + }, + "sceneIrProtocol": { + "path": "web/protocol/scene-ir.ts", + "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "9c831d0351ac9d0714cce3b1da748cba416ced3086e3c59595cf24ac4da459ed" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00189/anim-keyframe-insert-menu-desktop-report.json", + "sha256": "8f01c695716b3902e0d8caa4b335bc67257e4688a4af5e35fd61b5d98d9b3d03" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00189/anim-keyframe-insert-menu-local-exact-report.json", + "sha256": "a95cc2b84481263298f5bef1fbe0d46a2ab272de25ce5e0a39e84457453e0144" + }, + "status": { + "path": "docs/status/M16-GAP-00189.md", + "sha256": "f57b7b340a8c137afda5bb04daa4a71de372e2b0bd74fdb692029bea2da5e7c4" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00189/task-context.json", + "sha256": "46d321ed3909a9a52fdaf4b2c1f2ee9be2d16c2c8aff32ce4baca43c09f41682" + } + }, + "nextTask": "M16-GAP-00190" +} diff --git a/tests/golden/M16-GAP-00189/task-context.json b/tests/golden/M16-GAP-00189/task-context.json new file mode 100644 index 00000000..9c215e11 --- /dev/null +++ b/tests/golden/M16-GAP-00189/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00189", + "parentTask": "M16-GAP-00188", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.keyframe_insert_menu data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.keyframe_insert_menu", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00189.py -- tests/files/web/generated/M16-GAP-00189-operator-anim.keyframe_insert_menu.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00189", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00189" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00189.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1679, + "contextRemainingTokens": 418 + }, + "source": { + "bytes": 8225, + "tokens": 2058 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00189.py", + "bytes": 1620, + "tokens": 405 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00189-operator-anim.keyframe_insert_menu.blend", + "bytes": 86801, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 231498, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 440470, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00189/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00189.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00189/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1620, + "tokens": 405 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00190", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00189.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00188/manifest.json", + "parentStatus": "docs/status/M16-GAP-00188.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00189.md", + "tests/golden/M16-GAP-00188/manifest.json", + "docs/status/M16-GAP-00188.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00188", + "parentTask": "M16-GAP-00187", + "status": "done", + "nextTask": "M16-GAP-00189", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00188 Status", + "status: done", + "task: anim.keyframe_insert_by_name operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one selected/active object with a custom `insert_target` property, an Action keyed at frames 1 and 5, and a named Keying Set targeting that property. A foreground `VIEW_3D` context invokes `ANIM_OT_keyframe_insert_by_name(type=WebGapAnimKeyframeInsertByNameSet)` (`poll=true`, `FINISHED`) at frame 3, inserting the current key while preserving the two existing keys.", + "evidence:", + "- Desktop evidence records the Action changing from `[1, 5]` to `[1, 3, 5]`; the inserted key is the only selected key (`[false, true, false]`), the custom property remains at 3.0 and save/reopen is exact." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1814, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 454 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00189.md", + "bytes": 1814, + "lines": 38, + "tokens": 454 + }, + { + "path": "tests/golden/M16-GAP-00188/manifest.json", + "bytes": 2946, + "lines": 74, + "tokens": 737 + }, + { + "path": "docs/status/M16-GAP-00188.md", + "bytes": 1297, + "lines": 18, + "tokens": 325 + } + ], + "sourceTokens": 2058, + "evidenceFiles": 1, + "evidenceBytes": 1620, + "evidenceTokens": 405, + "totalTokens": 2463, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3487, + "serializedContextTokens": 758, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00190/anim-keying-set-active-set-desktop-report.json b/tests/golden/M16-GAP-00190/anim-keying-set-active-set-desktop-report.json new file mode 100644 index 00000000..016592ef --- /dev/null +++ b/tests/golden/M16-GAP-00190/anim-keying-set-active-set-desktop-report.json @@ -0,0 +1,72 @@ +{ + "after": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"active_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1.0, + 3.0, + 5.0 + ] + } + ], + "name": "WebGapAnimKeyingSetActiveAction" + }, + "active": true, + "activeKeyingSet": "WebGapAnimKeyingSetActiveB", + "selected": true, + "value": 3.0 + }, + "before": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"active_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1.0, + 3.0, + 5.0 + ] + } + ], + "name": "WebGapAnimKeyingSetActiveAction" + }, + "active": true, + "activeKeyingSet": "WebGapAnimKeyingSetActiveA", + "selected": true, + "value": 3.0 + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00190-operator-anim.keying_set_active_set.blend", + "fixtureSha256": "54d342c6054339281d8d380e01eb64f038e4735626a69248de66fadee34fbcae", + "mainMutation": "ACTIVE_KEYING_SET_CHANGED", + "operation": "ANIM_KEYING_SET_ACTIVE_SET_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00190" +} diff --git a/tests/golden/M16-GAP-00190/anim-keying-set-active-set-local-exact-report.json b/tests/golden/M16-GAP-00190/anim-keying-set-active-set-local-exact-report.json new file mode 100644 index 00000000..0d8533bd --- /dev/null +++ b/tests/golden/M16-GAP-00190/anim-keying-set-active-set-local-exact-report.json @@ -0,0 +1,103 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00190", + "operation": "ANIM_KEYING_SET_ACTIVE_SET_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00190-operator-anim.keying_set_active_set.blend", + "sha256": "54d342c6054339281d8d380e01eb64f038e4735626a69248de66fadee34fbcae" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00190/anim-keying-set-active-set-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "ACTIVE_KEYING_SET_CHANGED", + "before": { + "action": { + "channels": [ + { + "frames": [ + 1, + 3, + 5 + ], + "index": 0, + "path": "[\"active_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1, + 3, + 5 + ] + } + ], + "name": "WebGapAnimKeyingSetActiveAction" + }, + "active": true, + "activeKeyingSet": "WebGapAnimKeyingSetActiveA", + "selected": true, + "value": 3 + }, + "after": { + "action": { + "channels": [ + { + "frames": [ + 1, + 3, + 5 + ], + "index": 0, + "path": "[\"active_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1, + 3, + 5 + ] + } + ], + "name": "WebGapAnimKeyingSetActiveAction" + }, + "active": true, + "activeKeyingSet": "WebGapAnimKeyingSetActiveB", + "selected": true, + "value": 3 + } + }, + "wasm": { + "status": "EXACT", + "before": { + "animationId": "action:WebGapAnimKeyingSetActiveAction:object:WebGapAnimKeyingSetActiveObject", + "targetId": "object:WebGapAnimKeyingSetActiveObject", + "channelPaths": [ + "[\"active_target\"][0]" + ], + "keyframesPerChannel": [ + 3 + ] + }, + "after": { + "animationId": "action:WebGapAnimKeyingSetActiveAction:object:WebGapAnimKeyingSetActiveObject", + "keyframesPerChannel": [ + 3 + ], + "visibleMainUnchanged": true, + "keyingSetMetadata": "NOT_EXPOSED_BY_SCENE_SNAPSHOT" + } + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00191" +} diff --git a/tests/golden/M16-GAP-00190/manifest.json b/tests/golden/M16-GAP-00190/manifest.json new file mode 100644 index 00000000..33651238 --- /dev/null +++ b/tests/golden/M16-GAP-00190/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00190", + "parentTask": "M16-GAP-00189", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_KEYING_SET_ACTIVE_SET_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00189/manifest.json", + "sha256": "1ffc688a62e5c7f5141a9cd52dd192630097f01eacc8a8c6eac4991586eba33e" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00190-operator-anim.keying_set_active_set.blend", + "sha256": "54d342c6054339281d8d380e01eb64f038e4735626a69248de66fadee34fbcae" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00190.py", + "sha256": "f54bc93cb7b686883ae9bf3b36406d953af3c8246dca01e439999b5e09e4574a" + }, + "desktopChecker": { + "path": "tools/web/check-action-keying-set-active-set-desktop.py", + "sha256": "c0aaab7f5aae2982303ca0ab4cb05186d3d67ba21728bb49a2f8615a300d05f5" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "3e662b1abc876a4602aec079d6c6fa8d200ab14b102efb426d94bc712113634c" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "8824ba3dfb4090b85dc679a583d263b4bdb190a47978f72f3c11f6b565fdacaf" + }, + "protocol": { + "path": "web/protocol/editor-workflow.ts", + "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" + }, + "sceneIrProtocol": { + "path": "web/protocol/scene-ir.ts", + "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "9c831d0351ac9d0714cce3b1da748cba416ced3086e3c59595cf24ac4da459ed" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00190/anim-keying-set-active-set-desktop-report.json", + "sha256": "69ff6f5b3862697e6d17545c63264a0361aa9f6996b874897dd25a138257bc38" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00190/anim-keying-set-active-set-local-exact-report.json", + "sha256": "70e94768b98b0b14a1d03e9e016e62374838b4ad6fa68f893519fed6674f709d" + }, + "status": { + "path": "docs/status/M16-GAP-00190.md", + "sha256": "59def4f8ecb6005d53b5f1b335da97abf89a21f55ceb3589bd87493e2d06b9bd" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00190/task-context.json", + "sha256": "aaff27f84e2eb6f2d49c31ef6467e512acd01efca64a46dbe0fb967f19aedd98" + } + }, + "nextTask": "M16-GAP-00191" +} diff --git a/tests/golden/M16-GAP-00190/task-context.json b/tests/golden/M16-GAP-00190/task-context.json new file mode 100644 index 00000000..5bfd5a30 --- /dev/null +++ b/tests/golden/M16-GAP-00190/task-context.json @@ -0,0 +1,182 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00190", + "parentTask": "M16-GAP-00189", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.keying_set_active_set data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.keying_set_active_set", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00190.py -- tests/files/web/generated/M16-GAP-00190-operator-anim.keying_set_active_set.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00190", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00190" + ], + "inputPaths": [], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1722, + "contextRemainingTokens": 430 + }, + "source": { + "bytes": 8182, + "tokens": 2046 + }, + "selected": [], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00190-operator-anim.keying_set_active_set.blend", + "bytes": 86889, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/generated/M16-GAP-00190.py", + "bytes": 1743, + "reason": "CONTEXT_REMAINING_SPACE" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 231498, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 445010, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00190/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00190.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00190/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 0, + "bytes": 0, + "tokens": 0 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00191", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00190.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00189/manifest.json", + "parentStatus": "docs/status/M16-GAP-00189.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00190.md", + "tests/golden/M16-GAP-00189/manifest.json", + "docs/status/M16-GAP-00189.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00189", + "parentTask": "M16-GAP-00188", + "status": "done", + "nextTask": "M16-GAP-00190", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00189 Status", + "status: done", + "task: anim.keyframe_insert_menu operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one selected/active object with a custom `insert_target` property, an Action keyed at frames 1 and 5, and a named active Keying Set. A foreground `VIEW_3D` context invokes `ANIM_OT_keyframe_insert_menu(always_prompt=false)` (`poll=true`, `FINISHED`); Blender takes the active-Keying-Set fast path and inserts the current key at frame 3.", + "evidence:", + "- Desktop evidence records the Action changing from `[1, 5]` to `[1, 3, 5]`; the inserted key is the only selected key (`[false, true, false]`), the custom property remains at 3.0 and save/reopen is exact." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1819, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 455 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00190.md", + "bytes": 1819, + "lines": 38, + "tokens": 455 + }, + { + "path": "tests/golden/M16-GAP-00189/manifest.json", + "bytes": 2931, + "lines": 74, + "tokens": 733 + }, + { + "path": "docs/status/M16-GAP-00189.md", + "bytes": 1264, + "lines": 18, + "tokens": 316 + } + ], + "sourceTokens": 2046, + "evidenceFiles": 0, + "evidenceBytes": 0, + "evidenceTokens": 0, + "totalTokens": 2046, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3070, + "serializedContextTokens": 723, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00191/anim-keying-set-add-desktop-report.json b/tests/golden/M16-GAP-00191/anim-keying-set-add-desktop-report.json new file mode 100644 index 00000000..53c1db7e --- /dev/null +++ b/tests/golden/M16-GAP-00191/anim-keying-set-add-desktop-report.json @@ -0,0 +1,74 @@ +{ + "after": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"add_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1.0, + 3.0, + 5.0 + ] + } + ], + "name": "WebGapAnimKeyingSetAddAction" + }, + "active": true, + "activeKeyingSet": "KeyingSet", + "keyingSetCount": 1, + "selected": true, + "value": 3.0 + }, + "before": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"add_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1.0, + 3.0, + 5.0 + ] + } + ], + "name": "WebGapAnimKeyingSetAddAction" + }, + "active": true, + "activeKeyingSet": null, + "keyingSetCount": 0, + "selected": true, + "value": 3.0 + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00191-operator-anim.keying_set_add.blend", + "fixtureSha256": "a87db22a399c85cb282baf65a58763df7656603df9571bc34cdece31ef439187", + "mainMutation": "KEYING_SET_ADDED", + "operation": "ANIM_KEYING_SET_ADD_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00191" +} diff --git a/tests/golden/M16-GAP-00191/anim-keying-set-add-local-exact-report.json b/tests/golden/M16-GAP-00191/anim-keying-set-add-local-exact-report.json new file mode 100644 index 00000000..d4c1380e --- /dev/null +++ b/tests/golden/M16-GAP-00191/anim-keying-set-add-local-exact-report.json @@ -0,0 +1,105 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00191", + "operation": "ANIM_KEYING_SET_ADD_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00191-operator-anim.keying_set_add.blend", + "sha256": "a87db22a399c85cb282baf65a58763df7656603df9571bc34cdece31ef439187" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00191/anim-keying-set-add-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "KEYING_SET_ADDED", + "before": { + "action": { + "channels": [ + { + "frames": [ + 1, + 3, + 5 + ], + "index": 0, + "path": "[\"add_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1, + 3, + 5 + ] + } + ], + "name": "WebGapAnimKeyingSetAddAction" + }, + "active": true, + "activeKeyingSet": null, + "keyingSetCount": 0, + "selected": true, + "value": 3 + }, + "after": { + "action": { + "channels": [ + { + "frames": [ + 1, + 3, + 5 + ], + "index": 0, + "path": "[\"add_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1, + 3, + 5 + ] + } + ], + "name": "WebGapAnimKeyingSetAddAction" + }, + "active": true, + "activeKeyingSet": "KeyingSet", + "keyingSetCount": 1, + "selected": true, + "value": 3 + } + }, + "wasm": { + "status": "EXACT", + "before": { + "animationId": "action:WebGapAnimKeyingSetAddAction:object:WebGapAnimKeyingSetAddObject", + "targetId": "object:WebGapAnimKeyingSetAddObject", + "channelPaths": [ + "[\"add_target\"][0]" + ], + "keyframesPerChannel": [ + 3 + ] + }, + "after": { + "animationId": "action:WebGapAnimKeyingSetAddAction:object:WebGapAnimKeyingSetAddObject", + "keyframesPerChannel": [ + 3 + ], + "visibleMainUnchanged": true, + "keyingSetMetadata": "NOT_EXPOSED_BY_SCENE_SNAPSHOT" + } + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00192" +} diff --git a/tests/golden/M16-GAP-00191/manifest.json b/tests/golden/M16-GAP-00191/manifest.json new file mode 100644 index 00000000..0cbfef06 --- /dev/null +++ b/tests/golden/M16-GAP-00191/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00191", + "parentTask": "M16-GAP-00190", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_KEYING_SET_ADD_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00190/manifest.json", + "sha256": "b5b28c6e402db6eb90d4c4a5f1837476d3a24d6725e63c9b70ec5461a4c665d7" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00191-operator-anim.keying_set_add.blend", + "sha256": "a87db22a399c85cb282baf65a58763df7656603df9571bc34cdece31ef439187" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00191.py", + "sha256": "42f787b67fd1858ef184ffaa76438a025d92fc49fe80cdf3a3334e314839a123" + }, + "desktopChecker": { + "path": "tools/web/check-action-keying-set-add-desktop.py", + "sha256": "70f33c905c82b3668c51e0f0c177dc4676417f8a6d9f2c1e0c87d6b9f433a958" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "cd8fbe18375df8f08c799fab350fe4a864639c12947d1ea8faafca8b4642d6e4" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "8824ba3dfb4090b85dc679a583d263b4bdb190a47978f72f3c11f6b565fdacaf" + }, + "protocol": { + "path": "web/protocol/editor-workflow.ts", + "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" + }, + "sceneIrProtocol": { + "path": "web/protocol/scene-ir.ts", + "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "9c831d0351ac9d0714cce3b1da748cba416ced3086e3c59595cf24ac4da459ed" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00191/anim-keying-set-add-desktop-report.json", + "sha256": "b19f86edd48c4fb40f3077af333baa89127d51218ca110861f2e77063caff304" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00191/anim-keying-set-add-local-exact-report.json", + "sha256": "d244b7788db82edae28bf1ceebe5d5a8978b317ea8a259abd4ecc1c071fdc68a" + }, + "status": { + "path": "docs/status/M16-GAP-00191.md", + "sha256": "c4d82279105c2e1821577084e539495d09bd99de99eaefadc1f23ed95841a333" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00191/task-context.json", + "sha256": "640288c7b699719aae7d92a951846b7dcdd31e944e1ba88440300331de3af570" + } + }, + "nextTask": "M16-GAP-00192" +} diff --git a/tests/golden/M16-GAP-00191/task-context.json b/tests/golden/M16-GAP-00191/task-context.json new file mode 100644 index 00000000..f9c7afff --- /dev/null +++ b/tests/golden/M16-GAP-00191/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00191", + "parentTask": "M16-GAP-00190", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.keying_set_add data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.keying_set_add", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00191.py -- tests/files/web/generated/M16-GAP-00191-operator-anim.keying_set_add.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00191", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00191" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00191.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1811, + "contextRemainingTokens": 452 + }, + "source": { + "bytes": 8093, + "tokens": 2024 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00191.py", + "bytes": 1296, + "tokens": 324 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00191-operator-anim.keying_set_add.blend", + "bytes": 86785, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 231498, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 449432, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00191/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00191.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00191/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1296, + "tokens": 324 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00192", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00191.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00190/manifest.json", + "parentStatus": "docs/status/M16-GAP-00190.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00191.md", + "tests/golden/M16-GAP-00190/manifest.json", + "docs/status/M16-GAP-00190.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00190", + "parentTask": "M16-GAP-00189", + "status": "done", + "nextTask": "M16-GAP-00191", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00190 Status", + "status: done", + "task: anim.keying_set_active_set operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one selected/active object with a custom `active_target` property, a three-key Action, and two named Keying Sets. A foreground `VIEW_3D` context invokes `ANIM_OT_keying_set_active_set(type=WebGapAnimKeyingSetActiveB)` (`poll=true`, `FINISHED`), changing the active Keying Set from A to B without changing the Action.", + "evidence:", + "- Desktop evidence records active Keying Set `WebGapAnimKeyingSetActiveA` changing to `WebGapAnimKeyingSetActiveB`; the Action remains `[1, 3, 5]`, the property remains 3.0, and save/reopen is exact." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1784, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 446 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00191.md", + "bytes": 1784, + "lines": 38, + "tokens": 446 + }, + { + "path": "tests/golden/M16-GAP-00190/manifest.json", + "bytes": 2936, + "lines": 74, + "tokens": 734 + }, + { + "path": "docs/status/M16-GAP-00190.md", + "bytes": 1205, + "lines": 18, + "tokens": 302 + } + ], + "sourceTokens": 2024, + "evidenceFiles": 1, + "evidenceBytes": 1296, + "evidenceTokens": 324, + "totalTokens": 2348, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3372, + "serializedContextTokens": 754, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00192/anim-keying-set-export-desktop-report.json b/tests/golden/M16-GAP-00192/anim-keying-set-export-desktop-report.json new file mode 100644 index 00000000..fa605d55 --- /dev/null +++ b/tests/golden/M16-GAP-00192/anim-keying-set-export-desktop-report.json @@ -0,0 +1,77 @@ +{ + "after": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"export_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1.0, + 3.0, + 5.0 + ] + } + ], + "name": "WebGapAnimKeyingSetExportAction" + }, + "active": true, + "activeKeyingSet": "WebGapAnimKeyingSetExportSet", + "selected": true, + "value": 3.0 + }, + "before": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"export_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1.0, + 3.0, + 5.0 + ] + } + ], + "name": "WebGapAnimKeyingSetExportAction" + }, + "active": true, + "activeKeyingSet": "WebGapAnimKeyingSetExportSet", + "selected": true, + "value": 3.0 + }, + "blenderVersion": "5.2.0 LTS", + "exportedScript": { + "bytes": 471, + "path": "/home/mes123456/workinf_Blender_Wasm/tests/golden/M16-GAP-00192/WebGapAnimKeyingSetExportSet.py", + "sha256": "ef38d3cd23ef00a277e66202010b2001efca51cec053b34762924db32592f966" + }, + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00192-operator-anim.keying_set_export.blend", + "fixtureSha256": "ff0342e9d493bc8b20d85acba9177c7115d77f5f515e1d70fc1caf056957c29f", + "mainMutation": "NONE_EXPORT_ONLY", + "operation": "ANIM_KEYING_SET_EXPORT_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00192" +} diff --git a/tests/golden/M16-GAP-00192/anim-keying-set-export-local-exact-report.json b/tests/golden/M16-GAP-00192/anim-keying-set-export-local-exact-report.json new file mode 100644 index 00000000..704baf5d --- /dev/null +++ b/tests/golden/M16-GAP-00192/anim-keying-set-export-local-exact-report.json @@ -0,0 +1,108 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00192", + "operation": "ANIM_KEYING_SET_EXPORT_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00192-operator-anim.keying_set_export.blend", + "sha256": "ff0342e9d493bc8b20d85acba9177c7115d77f5f515e1d70fc1caf056957c29f" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00192/anim-keying-set-export-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "NONE_EXPORT_ONLY", + "before": { + "action": { + "channels": [ + { + "frames": [ + 1, + 3, + 5 + ], + "index": 0, + "path": "[\"export_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1, + 3, + 5 + ] + } + ], + "name": "WebGapAnimKeyingSetExportAction" + }, + "active": true, + "activeKeyingSet": "WebGapAnimKeyingSetExportSet", + "selected": true, + "value": 3 + }, + "after": { + "action": { + "channels": [ + { + "frames": [ + 1, + 3, + 5 + ], + "index": 0, + "path": "[\"export_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1, + 3, + 5 + ] + } + ], + "name": "WebGapAnimKeyingSetExportAction" + }, + "active": true, + "activeKeyingSet": "WebGapAnimKeyingSetExportSet", + "selected": true, + "value": 3 + }, + "exportedScript": { + "path": "tests/golden/M16-GAP-00192/WebGapAnimKeyingSetExportSet.py", + "sha256": "ef38d3cd23ef00a277e66202010b2001efca51cec053b34762924db32592f966", + "bytes": 471 + } + }, + "wasm": { + "status": "EXACT", + "before": { + "animationId": "action:WebGapAnimKeyingSetExportAction:object:WebGapAnimKeyingSetExportObject", + "targetId": "object:WebGapAnimKeyingSetExportObject", + "channelPaths": [ + "[\"export_target\"][0]" + ], + "keyframesPerChannel": [ + 3 + ] + }, + "after": { + "animationId": "action:WebGapAnimKeyingSetExportAction:object:WebGapAnimKeyingSetExportObject", + "keyframesPerChannel": [ + 3 + ], + "visibleMainUnchanged": true, + "keyingSetMetadata": "NOT_EXPOSED_BY_SCENE_SNAPSHOT" + } + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00193" +} diff --git a/tests/golden/M16-GAP-00192/manifest.json b/tests/golden/M16-GAP-00192/manifest.json new file mode 100644 index 00000000..de2fbf0b --- /dev/null +++ b/tests/golden/M16-GAP-00192/manifest.json @@ -0,0 +1,29 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00192", + "parentTask": "M16-GAP-00191", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_KEYING_SET_EXPORT_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { "path": "tests/golden/M16-GAP-00191/manifest.json", "sha256": "1498471253dd616979da562845d490964291b15431b49be766ec224c0aada7aa" }, + "fixture": { "path": "tests/files/web/generated/M16-GAP-00192-operator-anim.keying_set_export.blend", "sha256": "ff0342e9d493bc8b20d85acba9177c7115d77f5f515e1d70fc1caf056957c29f" }, + "generator": { "path": "tools/web/generated/M16-GAP-00192.py", "sha256": "cb932180b82d9eabe3fac18fa461f4107fc6d1016a262c120c8be0758eeeeafb" }, + "desktopChecker": { "path": "tools/web/check-action-keying-set-export-desktop.py", "sha256": "e75538f411751b309e6eb2d4376839b0e1e70784414463356ab36ae39a7ad799" }, + "webChecker": { "path": "tools/web/check-generated-gap.mjs", "sha256": "6e3ccae10e11cdf01e27c8d50f0a571d82e650b75c58fd0d283c9f75e2d4db8d" }, + "reader": { "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "8824ba3dfb4090b85dc679a583d263b4bdb190a47978f72f3c11f6b565fdacaf" }, + "protocol": { "path": "web/protocol/editor-workflow.ts", "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" }, + "sceneIrProtocol": { "path": "web/protocol/scene-ir.ts", "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" }, + "wasm": { "path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" }, + "wasmPublic": { "path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" }, + "wasmJs": { "path": "web/app/src/vendor/blender/web_engine.js", "sha256": "9c831d0351ac9d0714cce3b1da748cba416ced3086e3c59595cf24ac4da459ed" }, + "desktopReport": { "path": "tests/golden/M16-GAP-00192/anim-keying-set-export-desktop-report.json", "sha256": "14b1c5675c9088305246d5afea8f291ef989c6735c3795e377b42524af2f7fed" }, + "webReport": { "path": "tests/golden/M16-GAP-00192/anim-keying-set-export-local-exact-report.json", "sha256": "0544edee932393df992ac05a4dbb07b4b1c82e4045cb15b674b182989105d0fa" }, + "exportedScript": { "path": "tests/golden/M16-GAP-00192/WebGapAnimKeyingSetExportSet.py", "sha256": "ef38d3cd23ef00a277e66202010b2001efca51cec053b34762924db32592f966" }, + "status": { "path": "docs/status/M16-GAP-00192.md", "sha256": "1367262e064964fa586ffe5c09ee1702f9be0d7f5f55f5794d54a48ebe8c5349" }, + "taskContext": { "path": "tests/golden/M16-GAP-00192/task-context.json", "sha256": "5bdca225c7027399992cc26b67f0e7ed37726d1adc7afd1009677a9eaf491c30" } + }, + "nextTask": "M16-GAP-00193" +} diff --git a/tests/golden/M16-GAP-00192/task-context.json b/tests/golden/M16-GAP-00192/task-context.json new file mode 100644 index 00000000..e62b7e88 --- /dev/null +++ b/tests/golden/M16-GAP-00192/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00192", + "parentTask": "M16-GAP-00191", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.keying_set_export data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.keying_set_export", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00192.py -- tests/files/web/generated/M16-GAP-00192-operator-anim.keying_set_export.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00192", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00192" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00192.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1939, + "contextRemainingTokens": 483 + }, + "source": { + "bytes": 7965, + "tokens": 1993 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00192.py", + "bytes": 1476, + "tokens": 369 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00192-operator-anim.keying_set_export.blend", + "bytes": 86891, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 231498, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 454189, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00192/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00192.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00192/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1476, + "tokens": 369 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00193", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00192.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00191/manifest.json", + "parentStatus": "docs/status/M16-GAP-00191.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00192.md", + "tests/golden/M16-GAP-00191/manifest.json", + "docs/status/M16-GAP-00191.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00191", + "parentTask": "M16-GAP-00190", + "status": "done", + "nextTask": "M16-GAP-00192", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00191 Status", + "status: done", + "task: anim.keying_set_add operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one selected/active object with a custom `add_target` property and a three-key Action, but no scene Keying Sets. A foreground `VIEW_3D` context invokes `ANIM_OT_keying_set_add()` (`poll=true`, `FINISHED`), adding and activating one empty Keying Set without changing the Action.", + "evidence:", + "- Desktop evidence records Keying Set count `0→1`, an active newly-added set, unchanged `[1, 3, 5]` Action data, and exact save/reopen." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1799, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 450 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00192.md", + "bytes": 1799, + "lines": 38, + "tokens": 450 + }, + { + "path": "tests/golden/M16-GAP-00191/manifest.json", + "bytes": 2901, + "lines": 74, + "tokens": 726 + }, + { + "path": "docs/status/M16-GAP-00191.md", + "bytes": 1097, + "lines": 18, + "tokens": 275 + } + ], + "sourceTokens": 1993, + "evidenceFiles": 1, + "evidenceBytes": 1476, + "evidenceTokens": 369, + "totalTokens": 2362, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3386, + "serializedContextTokens": 756, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00193/anim-keying-set-path-add-desktop-report.json b/tests/golden/M16-GAP-00193/anim-keying-set-path-add-desktop-report.json new file mode 100644 index 00000000..1210df92 --- /dev/null +++ b/tests/golden/M16-GAP-00193/anim-keying-set-path-add-desktop-report.json @@ -0,0 +1,89 @@ +{ + "after": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"path_add_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1.0, + 3.0, + 5.0 + ] + } + ], + "name": "WebGapAnimKeyingSetPathAddAction" + }, + "active": true, + "activeKeyingSet": "WebGapAnimKeyingSetPathAddSet", + "activePathIndex": 0, + "keyingSetCount": 1, + "pathCount": 1, + "paths": [ + { + "arrayIndex": 0, + "dataPath": "", + "group": "", + "groupMethod": "KEYINGSET", + "idType": "OBJECT", + "useEntireArray": true + } + ], + "selected": true, + "value": 3.0 + }, + "before": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"path_add_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1.0, + 3.0, + 5.0 + ] + } + ], + "name": "WebGapAnimKeyingSetPathAddAction" + }, + "active": true, + "activeKeyingSet": "WebGapAnimKeyingSetPathAddSet", + "activePathIndex": 0, + "keyingSetCount": 1, + "pathCount": 0, + "paths": [], + "selected": true, + "value": 3.0 + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00193-operator-anim.keying_set_path_add.blend", + "fixtureSha256": "4e14a61ca8cd86b528747d576aa89ff8dcd3c9d3b8f52625a46ff5b7594cc107", + "mainMutation": "KEYING_SET_PATH_ADDED", + "operation": "ANIM_KEYING_SET_PATH_ADD_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00193" +} diff --git a/tests/golden/M16-GAP-00193/anim-keying-set-path-add-local-exact-report.json b/tests/golden/M16-GAP-00193/anim-keying-set-path-add-local-exact-report.json new file mode 100644 index 00000000..aabd4b9f --- /dev/null +++ b/tests/golden/M16-GAP-00193/anim-keying-set-path-add-local-exact-report.json @@ -0,0 +1,120 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00193", + "operation": "ANIM_KEYING_SET_PATH_ADD_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00193-operator-anim.keying_set_path_add.blend", + "sha256": "4e14a61ca8cd86b528747d576aa89ff8dcd3c9d3b8f52625a46ff5b7594cc107" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00193/anim-keying-set-path-add-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "KEYING_SET_PATH_ADDED", + "before": { + "action": { + "channels": [ + { + "frames": [ + 1, + 3, + 5 + ], + "index": 0, + "path": "[\"path_add_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1, + 3, + 5 + ] + } + ], + "name": "WebGapAnimKeyingSetPathAddAction" + }, + "active": true, + "activeKeyingSet": "WebGapAnimKeyingSetPathAddSet", + "activePathIndex": 0, + "keyingSetCount": 1, + "pathCount": 0, + "paths": [], + "selected": true, + "value": 3 + }, + "after": { + "action": { + "channels": [ + { + "frames": [ + 1, + 3, + 5 + ], + "index": 0, + "path": "[\"path_add_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1, + 3, + 5 + ] + } + ], + "name": "WebGapAnimKeyingSetPathAddAction" + }, + "active": true, + "activeKeyingSet": "WebGapAnimKeyingSetPathAddSet", + "activePathIndex": 0, + "keyingSetCount": 1, + "pathCount": 1, + "paths": [ + { + "arrayIndex": 0, + "dataPath": "", + "group": "", + "groupMethod": "KEYINGSET", + "idType": "OBJECT", + "useEntireArray": true + } + ], + "selected": true, + "value": 3 + } + }, + "wasm": { + "status": "EXACT", + "before": { + "animationId": "action:WebGapAnimKeyingSetPathAddAction:object:WebGapAnimKeyingSetPathAddObject", + "targetId": "object:WebGapAnimKeyingSetPathAddObject", + "channelPaths": [ + "[\"path_add_target\"][0]" + ], + "keyframesPerChannel": [ + 3 + ] + }, + "after": { + "animationId": "action:WebGapAnimKeyingSetPathAddAction:object:WebGapAnimKeyingSetPathAddObject", + "keyframesPerChannel": [ + 3 + ], + "visibleMainUnchanged": true, + "keyingSetMetadata": "NOT_EXPOSED_BY_SCENE_SNAPSHOT" + } + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00194" +} diff --git a/tests/golden/M16-GAP-00193/manifest.json b/tests/golden/M16-GAP-00193/manifest.json new file mode 100644 index 00000000..5f1c0553 --- /dev/null +++ b/tests/golden/M16-GAP-00193/manifest.json @@ -0,0 +1,28 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00193", + "parentTask": "M16-GAP-00192", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_KEYING_SET_PATH_ADD_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { "path": "tests/golden/M16-GAP-00192/manifest.json", "sha256": "03d3b95ec10a7ee544448d4e9869684ca8c6a3f11a1e321fa80d58c812135c76" }, + "fixture": { "path": "tests/files/web/generated/M16-GAP-00193-operator-anim.keying_set_path_add.blend", "sha256": "4e14a61ca8cd86b528747d576aa89ff8dcd3c9d3b8f52625a46ff5b7594cc107" }, + "generator": { "path": "tools/web/generated/M16-GAP-00193.py", "sha256": "bf3d651dd050b39186f50095519cd02e16fbc9d652e2d307b7f5a05703ab18d7" }, + "desktopChecker": { "path": "tools/web/check-action-keying-set-path-add-desktop.py", "sha256": "62a65a5b58bdf9d883691d47c13ece9759f763acf58ab46660a6fc93f486e04d" }, + "webChecker": { "path": "tools/web/check-generated-gap.mjs", "sha256": "0f996fe9201c7485a9ef2e829ed2f6361b7cae0eb75477a145aa8f71e443f5cf" }, + "reader": { "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "8824ba3dfb4090b85dc679a583d263b4bdb190a47978f72f3c11f6b565fdacaf" }, + "protocol": { "path": "web/protocol/editor-workflow.ts", "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" }, + "sceneIrProtocol": { "path": "web/protocol/scene-ir.ts", "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" }, + "wasm": { "path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" }, + "wasmPublic": { "path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" }, + "wasmJs": { "path": "web/app/src/vendor/blender/web_engine.js", "sha256": "9c831d0351ac9d0714cce3b1da748cba416ced3086e3c59595cf24ac4da459ed" }, + "desktopReport": { "path": "tests/golden/M16-GAP-00193/anim-keying-set-path-add-desktop-report.json", "sha256": "0deab04ebdbf06c6b344707bf3025677d445c6995cbe3ea1268808c59ec74472" }, + "webReport": { "path": "tests/golden/M16-GAP-00193/anim-keying-set-path-add-local-exact-report.json", "sha256": "61e41fbc56bc7c6c1cbceb4ad3e28cb599e072f8c865f0a573091b47ba53790f" }, + "status": { "path": "docs/status/M16-GAP-00193.md", "sha256": "f5510b2a17b16c1ffdd873b30c0b397b25d6d1660eb7f16cfcbcfdccbb4ae668" }, + "taskContext": { "path": "tests/golden/M16-GAP-00193/task-context.json", "sha256": "d459521fe19a776c7b81dd7b49dc3aba7e3f5eba864612f0817fd1ca9bb4dda9" } + }, + "nextTask": "M16-GAP-00194" +} diff --git a/tests/golden/M16-GAP-00193/task-context.json b/tests/golden/M16-GAP-00193/task-context.json new file mode 100644 index 00000000..c0169f6e --- /dev/null +++ b/tests/golden/M16-GAP-00193/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00193", + "parentTask": "M16-GAP-00192", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.keying_set_path_add data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.keying_set_path_add", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00193.py -- tests/files/web/generated/M16-GAP-00193-operator-anim.keying_set_path_add.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00193", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00193" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00193.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1957, + "contextRemainingTokens": 488 + }, + "source": { + "bytes": 7947, + "tokens": 1988 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00193.py", + "bytes": 1534, + "tokens": 384 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00193-operator-anim.keying_set_path_add.blend", + "bytes": 86860, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 231498, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 458781, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00193/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00193.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00193/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1534, + "tokens": 384 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00194", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00193.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00192/manifest.json", + "parentStatus": "docs/status/M16-GAP-00192.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00193.md", + "tests/golden/M16-GAP-00192/manifest.json", + "docs/status/M16-GAP-00192.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00192", + "parentTask": "M16-GAP-00191", + "status": "done", + "nextTask": "M16-GAP-00193", + "artifactCount": 16 + }, + "statusSummary": [ + "# M16-GAP-00192 Status", + "status: done", + "task: anim.keying_set_export operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one selected/active object with a custom `export_target` property, a three-key Action, and one named Keying Set. Blender invokes `ANIM_OT_keying_set_export(filepath=..., filter_python=true)` (`poll=true`, `FINISHED`) and writes the Keying Set Python export without mutating Main.", + "evidence:", + "- Desktop evidence records unchanged object/Action state, exact save/reopen, and a non-empty hash-bound exported Python script." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1809, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 453 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00193.md", + "bytes": 1809, + "lines": 38, + "tokens": 453 + }, + { + "path": "tests/golden/M16-GAP-00192/manifest.json", + "bytes": 2850, + "lines": 30, + "tokens": 713 + }, + { + "path": "docs/status/M16-GAP-00192.md", + "bytes": 1120, + "lines": 18, + "tokens": 280 + } + ], + "sourceTokens": 1988, + "evidenceFiles": 1, + "evidenceBytes": 1534, + "evidenceTokens": 384, + "totalTokens": 2372, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3396, + "serializedContextTokens": 757, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00194/anim-keying-set-path-remove-desktop-report.json b/tests/golden/M16-GAP-00194/anim-keying-set-path-remove-desktop-report.json new file mode 100644 index 00000000..04987035 --- /dev/null +++ b/tests/golden/M16-GAP-00194/anim-keying-set-path-remove-desktop-report.json @@ -0,0 +1,89 @@ +{ + "after": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"path_remove_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1.0, + 3.0, + 5.0 + ] + } + ], + "name": "WebGapAnimKeyingSetPathRemoveAction" + }, + "active": true, + "activeKeyingSet": "WebGapAnimKeyingSetPathRemoveSet", + "activePathIndex": 0, + "keyingSetCount": 1, + "pathCount": 0, + "paths": [], + "selected": true, + "value": 3.0 + }, + "before": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"path_remove_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1.0, + 3.0, + 5.0 + ] + } + ], + "name": "WebGapAnimKeyingSetPathRemoveAction" + }, + "active": true, + "activeKeyingSet": "WebGapAnimKeyingSetPathRemoveSet", + "activePathIndex": 0, + "keyingSetCount": 1, + "pathCount": 1, + "paths": [ + { + "arrayIndex": 0, + "dataPath": "[\"path_remove_target\"]", + "group": "", + "groupMethod": "KEYINGSET", + "idType": "OBJECT", + "useEntireArray": false + } + ], + "selected": true, + "value": 3.0 + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00194-operator-anim.keying_set_path_remove.blend", + "fixtureSha256": "b1161cfd0ac095844825cb2fa19fcbe9819bce552d02535f2d32deef3c8cbb79", + "mainMutation": "KEYING_SET_PATH_REMOVED", + "operation": "ANIM_KEYING_SET_PATH_REMOVE_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00194" +} diff --git a/tests/golden/M16-GAP-00194/anim-keying-set-path-remove-local-exact-report.json b/tests/golden/M16-GAP-00194/anim-keying-set-path-remove-local-exact-report.json new file mode 100644 index 00000000..42db1b29 --- /dev/null +++ b/tests/golden/M16-GAP-00194/anim-keying-set-path-remove-local-exact-report.json @@ -0,0 +1,120 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00194", + "operation": "ANIM_KEYING_SET_PATH_REMOVE_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00194-operator-anim.keying_set_path_remove.blend", + "sha256": "b1161cfd0ac095844825cb2fa19fcbe9819bce552d02535f2d32deef3c8cbb79" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00194/anim-keying-set-path-remove-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "KEYING_SET_PATH_REMOVED", + "before": { + "action": { + "channels": [ + { + "frames": [ + 1, + 3, + 5 + ], + "index": 0, + "path": "[\"path_remove_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1, + 3, + 5 + ] + } + ], + "name": "WebGapAnimKeyingSetPathRemoveAction" + }, + "active": true, + "activeKeyingSet": "WebGapAnimKeyingSetPathRemoveSet", + "activePathIndex": 0, + "keyingSetCount": 1, + "pathCount": 1, + "paths": [ + { + "arrayIndex": 0, + "dataPath": "[\"path_remove_target\"]", + "group": "", + "groupMethod": "KEYINGSET", + "idType": "OBJECT", + "useEntireArray": false + } + ], + "selected": true, + "value": 3 + }, + "after": { + "action": { + "channels": [ + { + "frames": [ + 1, + 3, + 5 + ], + "index": 0, + "path": "[\"path_remove_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1, + 3, + 5 + ] + } + ], + "name": "WebGapAnimKeyingSetPathRemoveAction" + }, + "active": true, + "activeKeyingSet": "WebGapAnimKeyingSetPathRemoveSet", + "activePathIndex": 0, + "keyingSetCount": 1, + "pathCount": 0, + "paths": [], + "selected": true, + "value": 3 + } + }, + "wasm": { + "status": "EXACT", + "before": { + "animationId": "action:WebGapAnimKeyingSetPathRemoveAction:object:WebGapAnimKeyingSetPathRemoveObject", + "targetId": "object:WebGapAnimKeyingSetPathRemoveObject", + "channelPaths": [ + "[\"path_remove_target\"][0]" + ], + "keyframesPerChannel": [ + 3 + ] + }, + "after": { + "animationId": "action:WebGapAnimKeyingSetPathRemoveAction:object:WebGapAnimKeyingSetPathRemoveObject", + "keyframesPerChannel": [ + 3 + ], + "visibleMainUnchanged": true, + "keyingSetMetadata": "NOT_EXPOSED_BY_SCENE_SNAPSHOT" + } + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00195" +} diff --git a/tests/golden/M16-GAP-00194/manifest.json b/tests/golden/M16-GAP-00194/manifest.json new file mode 100644 index 00000000..89718408 --- /dev/null +++ b/tests/golden/M16-GAP-00194/manifest.json @@ -0,0 +1,28 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00194", + "parentTask": "M16-GAP-00193", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_KEYING_SET_PATH_REMOVE_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { "path": "tests/golden/M16-GAP-00193/manifest.json", "sha256": "203219913781f09abaa1aab272f97117907f44e9dc0a08691500457ac4b24446" }, + "fixture": { "path": "tests/files/web/generated/M16-GAP-00194-operator-anim.keying_set_path_remove.blend", "sha256": "b1161cfd0ac095844825cb2fa19fcbe9819bce552d02535f2d32deef3c8cbb79" }, + "generator": { "path": "tools/web/generated/M16-GAP-00194.py", "sha256": "182bc9eda4c6383e83f353cb0ee8fee299caf954537592f58cd68f1e1b1328e2" }, + "desktopChecker": { "path": "tools/web/check-action-keying-set-path-remove-desktop.py", "sha256": "91e9ae1891106babe828ead19c2f07fd955c06883fa4b03f1b4f12fb8a41824e" }, + "webChecker": { "path": "tools/web/check-generated-gap.mjs", "sha256": "5c7c11e2ef348faf5e34343f947df076e8f732c2a03180fcdfecf157fdd46fb9" }, + "reader": { "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "8824ba3dfb4090b85dc679a583d263b4bdb190a47978f72f3c11f6b565fdacaf" }, + "protocol": { "path": "web/protocol/editor-workflow.ts", "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" }, + "sceneIrProtocol": { "path": "web/protocol/scene-ir.ts", "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" }, + "wasm": { "path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" }, + "wasmPublic": { "path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" }, + "wasmJs": { "path": "web/app/src/vendor/blender/web_engine.js", "sha256": "9c831d0351ac9d0714cce3b1da748cba416ced3086e3c59595cf24ac4da459ed" }, + "desktopReport": { "path": "tests/golden/M16-GAP-00194/anim-keying-set-path-remove-desktop-report.json", "sha256": "36ec6d4232418b56ea06b375bd0562718ef0cb787c393a860fcf69b663aa3a89" }, + "webReport": { "path": "tests/golden/M16-GAP-00194/anim-keying-set-path-remove-local-exact-report.json", "sha256": "a840e751c3e8c7ef6b02f388e8db434ebcd6cb4d0a151fbb3350d98f6689f438" }, + "status": { "path": "docs/status/M16-GAP-00194.md", "sha256": "54a5b5384704b1a16d541cbc6d70c98001495cb010fe1f9235e73d23a0fc2d9d" }, + "taskContext": { "path": "tests/golden/M16-GAP-00194/task-context.json", "sha256": "ecd39a4fd55eb2f7fcc3bacaa8046ab21d56ce5ae8e936898c2fa9a85b9f08cd" } + }, + "nextTask": "M16-GAP-00195" +} diff --git a/tests/golden/M16-GAP-00194/task-context.json b/tests/golden/M16-GAP-00194/task-context.json new file mode 100644 index 00000000..6985b6f5 --- /dev/null +++ b/tests/golden/M16-GAP-00194/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00194", + "parentTask": "M16-GAP-00193", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.keying_set_path_remove data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.keying_set_path_remove", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00194.py -- tests/files/web/generated/M16-GAP-00194-operator-anim.keying_set_path_remove.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00194", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00194" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00194.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2145, + "contextRemainingTokens": 535 + }, + "source": { + "bytes": 7759, + "tokens": 1941 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00194.py", + "bytes": 1618, + "tokens": 405 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00194-operator-anim.keying_set_path_remove.blend", + "bytes": 86865, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 231498, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 463464, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00194/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00194.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00194/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1618, + "tokens": 405 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00195", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00194.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00193/manifest.json", + "parentStatus": "docs/status/M16-GAP-00193.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00194.md", + "tests/golden/M16-GAP-00193/manifest.json", + "docs/status/M16-GAP-00193.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00193", + "parentTask": "M16-GAP-00192", + "status": "done", + "nextTask": "M16-GAP-00194", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00193 Status", + "status: done", + "task: anim.keying_set_path_add operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one selected/active object with a three-key Action and one empty active Keying Set. Blender invokes `ANIM_OT_keying_set_path_add()` (`poll=true`, `FINISHED`), adding one empty path with the expected default fields without changing the Action.", + "evidence:", + "- Desktop evidence records Keying Set path count `0→1`, the empty path defaults, unchanged `[1, 3, 5]` Action data, and exact save/reopen." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1824, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 456 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00194.md", + "bytes": 1824, + "lines": 38, + "tokens": 456 + }, + { + "path": "tests/golden/M16-GAP-00193/manifest.json", + "bytes": 2686, + "lines": 29, + "tokens": 672 + }, + { + "path": "docs/status/M16-GAP-00193.md", + "bytes": 1081, + "lines": 18, + "tokens": 271 + } + ], + "sourceTokens": 1941, + "evidenceFiles": 1, + "evidenceBytes": 1618, + "evidenceTokens": 405, + "totalTokens": 2346, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3370, + "serializedContextTokens": 760, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00195/anim-keying-set-remove-desktop-report.json b/tests/golden/M16-GAP-00195/anim-keying-set-remove-desktop-report.json new file mode 100644 index 00000000..3e33ffef --- /dev/null +++ b/tests/golden/M16-GAP-00195/anim-keying-set-remove-desktop-report.json @@ -0,0 +1,76 @@ +{ + "after": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"remove_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1.0, + 3.0, + 5.0 + ] + } + ], + "name": "WebGapAnimKeyingSetRemoveAction" + }, + "active": true, + "activeKeyingSet": null, + "keyingSetCount": 0, + "pathCount": 0, + "selected": true, + "value": 3.0 + }, + "before": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"remove_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1.0, + 3.0, + 5.0 + ] + } + ], + "name": "WebGapAnimKeyingSetRemoveAction" + }, + "active": true, + "activeKeyingSet": "WebGapAnimKeyingSetRemoveSet", + "keyingSetCount": 1, + "pathCount": 0, + "selected": true, + "value": 3.0 + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00195-operator-anim.keying_set_remove.blend", + "fixtureSha256": "d4fa5993c2580e5521cf2ee66817c416f50de82f5ec4e32298e52db14fa0a9a9", + "mainMutation": "KEYING_SET_REMOVED", + "operation": "ANIM_KEYING_SET_REMOVE_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00195" +} diff --git a/tests/golden/M16-GAP-00195/anim-keying-set-remove-local-exact-report.json b/tests/golden/M16-GAP-00195/anim-keying-set-remove-local-exact-report.json new file mode 100644 index 00000000..b613e386 --- /dev/null +++ b/tests/golden/M16-GAP-00195/anim-keying-set-remove-local-exact-report.json @@ -0,0 +1,107 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00195", + "operation": "ANIM_KEYING_SET_REMOVE_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00195-operator-anim.keying_set_remove.blend", + "sha256": "d4fa5993c2580e5521cf2ee66817c416f50de82f5ec4e32298e52db14fa0a9a9" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00195/anim-keying-set-remove-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "KEYING_SET_REMOVED", + "before": { + "action": { + "channels": [ + { + "frames": [ + 1, + 3, + 5 + ], + "index": 0, + "path": "[\"remove_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1, + 3, + 5 + ] + } + ], + "name": "WebGapAnimKeyingSetRemoveAction" + }, + "active": true, + "activeKeyingSet": "WebGapAnimKeyingSetRemoveSet", + "keyingSetCount": 1, + "pathCount": 0, + "selected": true, + "value": 3 + }, + "after": { + "action": { + "channels": [ + { + "frames": [ + 1, + 3, + 5 + ], + "index": 0, + "path": "[\"remove_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1, + 3, + 5 + ] + } + ], + "name": "WebGapAnimKeyingSetRemoveAction" + }, + "active": true, + "activeKeyingSet": null, + "keyingSetCount": 0, + "pathCount": 0, + "selected": true, + "value": 3 + } + }, + "wasm": { + "status": "EXACT", + "before": { + "animationId": "action:WebGapAnimKeyingSetRemoveAction:object:WebGapAnimKeyingSetRemoveObject", + "targetId": "object:WebGapAnimKeyingSetRemoveObject", + "channelPaths": [ + "[\"remove_target\"][0]" + ], + "keyframesPerChannel": [ + 3 + ] + }, + "after": { + "animationId": "action:WebGapAnimKeyingSetRemoveAction:object:WebGapAnimKeyingSetRemoveObject", + "keyframesPerChannel": [ + 3 + ], + "visibleMainUnchanged": true, + "keyingSetMetadata": "NOT_EXPOSED_BY_SCENE_SNAPSHOT" + } + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00196" +} diff --git a/tests/golden/M16-GAP-00195/manifest.json b/tests/golden/M16-GAP-00195/manifest.json new file mode 100644 index 00000000..b357cdb6 --- /dev/null +++ b/tests/golden/M16-GAP-00195/manifest.json @@ -0,0 +1,28 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00195", + "parentTask": "M16-GAP-00194", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_KEYING_SET_REMOVE_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { "path": "tests/golden/M16-GAP-00194/manifest.json", "sha256": "d8336a458497eff326ab8a8df3050c5e4e2f41b0297a2f070ec976c09377f270" }, + "fixture": { "path": "tests/files/web/generated/M16-GAP-00195-operator-anim.keying_set_remove.blend", "sha256": "d4fa5993c2580e5521cf2ee66817c416f50de82f5ec4e32298e52db14fa0a9a9" }, + "generator": { "path": "tools/web/generated/M16-GAP-00195.py", "sha256": "4f8fb118aa60518844dd181607994d857dc8828d66acd526fe0de727491f54e6" }, + "desktopChecker": { "path": "tools/web/check-action-keying-set-remove-desktop.py", "sha256": "34a45f49def53589fb7e5b3bcfaaaf500af5e5dba069a8175eff1dd19ba354cc" }, + "webChecker": { "path": "tools/web/check-generated-gap.mjs", "sha256": "692c7b2db04a96680bbc7c7807cac3ed552e3123cc4af5f335b3e50cd1ff0bce" }, + "reader": { "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "8824ba3dfb4090b85dc679a583d263b4bdb190a47978f72f3c11f6b565fdacaf" }, + "protocol": { "path": "web/protocol/editor-workflow.ts", "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" }, + "sceneIrProtocol": { "path": "web/protocol/scene-ir.ts", "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" }, + "wasm": { "path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" }, + "wasmPublic": { "path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" }, + "wasmJs": { "path": "web/app/src/vendor/blender/web_engine.js", "sha256": "9c831d0351ac9d0714cce3b1da748cba416ced3086e3c59595cf24ac4da459ed" }, + "desktopReport": { "path": "tests/golden/M16-GAP-00195/anim-keying-set-remove-desktop-report.json", "sha256": "67fc9add6112f6513a95028ba2170d468b1ca82d83cf1b8d1afe2da98b907b15" }, + "webReport": { "path": "tests/golden/M16-GAP-00195/anim-keying-set-remove-local-exact-report.json", "sha256": "f1a6dc449055b1cddb1f796b885eaa347cf1c64ca082af7940c9c751a59dec9e" }, + "status": { "path": "docs/status/M16-GAP-00195.md", "sha256": "cdb8e80052164365b81fb210701cd5283ea022f219eb1a1e14d561ef178e7420" }, + "taskContext": { "path": "tests/golden/M16-GAP-00195/task-context.json", "sha256": "e462b1602ed761491ad2054fc7152fb36306b21a0c14f2511a3cbc21b2b740d2" } + }, + "nextTask": "M16-GAP-00196" +} diff --git a/tests/golden/M16-GAP-00195/task-context.json b/tests/golden/M16-GAP-00195/task-context.json new file mode 100644 index 00000000..01878904 --- /dev/null +++ b/tests/golden/M16-GAP-00195/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00195", + "parentTask": "M16-GAP-00194", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.keying_set_remove data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.keying_set_remove", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00195.py -- tests/files/web/generated/M16-GAP-00195-operator-anim.keying_set_remove.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00195", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00195" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00195.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2175, + "contextRemainingTokens": 542 + }, + "source": { + "bytes": 7729, + "tokens": 1934 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00195.py", + "bytes": 1524, + "tokens": 381 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00195-operator-anim.keying_set_remove.blend", + "bytes": 86811, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 231498, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 468034, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00195/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00195.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00195/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1524, + "tokens": 381 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00196", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00195.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00194/manifest.json", + "parentStatus": "docs/status/M16-GAP-00194.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00195.md", + "tests/golden/M16-GAP-00194/manifest.json", + "docs/status/M16-GAP-00194.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00194", + "parentTask": "M16-GAP-00193", + "status": "done", + "nextTask": "M16-GAP-00195", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00194 Status", + "status: done", + "task: anim.keying_set_path_remove operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one selected/active object with a three-key Action and one active Keying Set path. Blender invokes `ANIM_OT_keying_set_path_remove()` (`poll=true`, `FINISHED`), removing the active path without changing the Action.", + "evidence:", + "- Desktop evidence records Keying Set path count `1→0`, the pre-existing path fields, unchanged `[1, 3, 5]` Action data, and exact save/reopen." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1799, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 450 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00195.md", + "bytes": 1799, + "lines": 38, + "tokens": 450 + }, + { + "path": "tests/golden/M16-GAP-00194/manifest.json", + "bytes": 2701, + "lines": 29, + "tokens": 676 + }, + { + "path": "docs/status/M16-GAP-00194.md", + "bytes": 1061, + "lines": 18, + "tokens": 266 + } + ], + "sourceTokens": 1934, + "evidenceFiles": 1, + "evidenceBytes": 1524, + "evidenceTokens": 381, + "totalTokens": 2315, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3339, + "serializedContextTokens": 756, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00196/anim-keyingset-button-add-desktop-report.json b/tests/golden/M16-GAP-00196/anim-keyingset-button-add-desktop-report.json new file mode 100644 index 00000000..f071bc8e --- /dev/null +++ b/tests/golden/M16-GAP-00196/anim-keyingset-button-add-desktop-report.json @@ -0,0 +1,87 @@ +{ + "after": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"button_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1.0, + 3.0, + 5.0 + ] + } + ], + "name": "WebGapAnimKeyingSetButtonAddAction" + }, + "active": true, + "activeKeyingSet": "ButtonKeyingSet", + "keyingSetCount": 1, + "pathCount": 1, + "paths": [ + { + "arrayIndex": 0, + "dataPath": "[\"button_target\"]", + "group": "", + "groupMethod": "KEYINGSET", + "idType": "OBJECT", + "useEntireArray": true + } + ], + "selected": true, + "value": 3.0 + }, + "before": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"button_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1.0, + 3.0, + 5.0 + ] + } + ], + "name": "WebGapAnimKeyingSetButtonAddAction" + }, + "active": true, + "activeKeyingSet": null, + "keyingSetCount": 0, + "pathCount": 0, + "paths": [], + "selected": true, + "value": 3.0 + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00196-operator-anim.keyingset_button_add.blend", + "fixtureSha256": "2e49572a29dadcdfdae956f7e16bd465c5de06bf8ae94ebdc11da8b1821eb562", + "mainMutation": "KEYING_SET_PATH_ADDED", + "operation": "ANIM_KEYINGSET_BUTTON_ADD_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00196" +} diff --git a/tests/golden/M16-GAP-00196/anim-keyingset-button-add-local-exact-report.json b/tests/golden/M16-GAP-00196/anim-keyingset-button-add-local-exact-report.json new file mode 100644 index 00000000..2ca868a9 --- /dev/null +++ b/tests/golden/M16-GAP-00196/anim-keyingset-button-add-local-exact-report.json @@ -0,0 +1,118 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00196", + "operation": "ANIM_KEYINGSET_BUTTON_ADD_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00196-operator-anim.keyingset_button_add.blend", + "sha256": "2e49572a29dadcdfdae956f7e16bd465c5de06bf8ae94ebdc11da8b1821eb562" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00196/anim-keyingset-button-add-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "KEYING_SET_PATH_ADDED", + "before": { + "action": { + "channels": [ + { + "frames": [ + 1, + 3, + 5 + ], + "index": 0, + "path": "[\"button_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1, + 3, + 5 + ] + } + ], + "name": "WebGapAnimKeyingSetButtonAddAction" + }, + "active": true, + "activeKeyingSet": null, + "keyingSetCount": 0, + "pathCount": 0, + "paths": [], + "selected": true, + "value": 3 + }, + "after": { + "action": { + "channels": [ + { + "frames": [ + 1, + 3, + 5 + ], + "index": 0, + "path": "[\"button_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1, + 3, + 5 + ] + } + ], + "name": "WebGapAnimKeyingSetButtonAddAction" + }, + "active": true, + "activeKeyingSet": "ButtonKeyingSet", + "keyingSetCount": 1, + "pathCount": 1, + "paths": [ + { + "arrayIndex": 0, + "dataPath": "[\"button_target\"]", + "group": "", + "groupMethod": "KEYINGSET", + "idType": "OBJECT", + "useEntireArray": true + } + ], + "selected": true, + "value": 3 + } + }, + "wasm": { + "status": "EXACT", + "before": { + "animationId": "action:WebGapAnimKeyingSetButtonAddAction:object:WebGapAnimKeyingSetButtonAddObject", + "targetId": "object:WebGapAnimKeyingSetButtonAddObject", + "channelPaths": [ + "[\"button_target\"][0]" + ], + "keyframesPerChannel": [ + 3 + ] + }, + "after": { + "animationId": "action:WebGapAnimKeyingSetButtonAddAction:object:WebGapAnimKeyingSetButtonAddObject", + "keyframesPerChannel": [ + 3 + ], + "visibleMainUnchanged": true, + "keyingSetMetadata": "NOT_EXPOSED_BY_SCENE_SNAPSHOT" + } + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00197" +} diff --git a/tests/golden/M16-GAP-00196/manifest.json b/tests/golden/M16-GAP-00196/manifest.json new file mode 100644 index 00000000..ebeb0638 --- /dev/null +++ b/tests/golden/M16-GAP-00196/manifest.json @@ -0,0 +1,28 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00196", + "parentTask": "M16-GAP-00195", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_KEYINGSET_BUTTON_ADD_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { "path": "tests/golden/M16-GAP-00195/manifest.json", "sha256": "4a46a92b6ea9fee6f99e3d7284e78d74748cb52a57d942d874df664da85d65f2" }, + "fixture": { "path": "tests/files/web/generated/M16-GAP-00196-operator-anim.keyingset_button_add.blend", "sha256": "2e49572a29dadcdfdae956f7e16bd465c5de06bf8ae94ebdc11da8b1821eb562" }, + "generator": { "path": "tools/web/generated/M16-GAP-00196.py", "sha256": "61eefce310c581808e90c8378b1f085c00d7d28878c0c62946489225b020f2d8" }, + "desktopChecker": { "path": "tools/web/check-action-keyingset-button-add-desktop.py", "sha256": "15b1b30ea2793313f52c914021d148c50cd02ba5bcb8d983c37755f811bcd16f" }, + "webChecker": { "path": "tools/web/check-generated-gap.mjs", "sha256": "05772ad9408274628a737748e6293cd5fce4d090243b0a51db4b620eb93758c5" }, + "reader": { "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "8824ba3dfb4090b85dc679a583d263b4bdb190a47978f72f3c11f6b565fdacaf" }, + "protocol": { "path": "web/protocol/editor-workflow.ts", "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" }, + "sceneIrProtocol": { "path": "web/protocol/scene-ir.ts", "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" }, + "wasm": { "path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" }, + "wasmPublic": { "path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" }, + "wasmJs": { "path": "web/app/src/vendor/blender/web_engine.js", "sha256": "9c831d0351ac9d0714cce3b1da748cba416ced3086e3c59595cf24ac4da459ed" }, + "desktopReport": { "path": "tests/golden/M16-GAP-00196/anim-keyingset-button-add-desktop-report.json", "sha256": "a213760a261879356db09714df719221fef2f0a4c26865e12396b80089c21583" }, + "webReport": { "path": "tests/golden/M16-GAP-00196/anim-keyingset-button-add-local-exact-report.json", "sha256": "3146c77b1f77e3db9b1dc855c31408b0c076ecfea258aea8a86a834ab06ad9b3" }, + "status": { "path": "docs/status/M16-GAP-00196.md", "sha256": "b1a31309d96dc8fa456c95e45e78aa192472f84573a8ab9ad21bac1a047a3a8c" }, + "taskContext": { "path": "tests/golden/M16-GAP-00196/task-context.json", "sha256": "325c63d0601e3b9adf8afb69f6d3cbfd970e3fc281eaa70b13d7cddb0399e324" } + }, + "nextTask": "M16-GAP-00197" +} diff --git a/tests/golden/M16-GAP-00196/task-context.json b/tests/golden/M16-GAP-00196/task-context.json new file mode 100644 index 00000000..147d9028 --- /dev/null +++ b/tests/golden/M16-GAP-00196/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00196", + "parentTask": "M16-GAP-00195", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.keyingset_button_add data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.keyingset_button_add", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00196.py -- tests/files/web/generated/M16-GAP-00196-operator-anim.keyingset_button_add.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00196", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00196" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00196.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2173, + "contextRemainingTokens": 542 + }, + "source": { + "bytes": 7731, + "tokens": 1934 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00196.py", + "bytes": 1349, + "tokens": 338 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00196-operator-anim.keyingset_button_add.blend", + "bytes": 86863, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 231498, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 472821, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00196/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00196.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00196/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1349, + "tokens": 338 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00197", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00196.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00195/manifest.json", + "parentStatus": "docs/status/M16-GAP-00195.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00196.md", + "tests/golden/M16-GAP-00195/manifest.json", + "docs/status/M16-GAP-00195.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00195", + "parentTask": "M16-GAP-00194", + "status": "done", + "nextTask": "M16-GAP-00196", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00195 Status", + "status: done", + "task: anim.keying_set_remove operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one selected/active object with a three-key Action and one empty active Keying Set. Blender invokes `ANIM_OT_keying_set_remove()` (`poll=true`, `FINISHED`), removing the active Keying Set without changing the Action.", + "evidence:", + "- Desktop evidence records Keying Set count `1→0`, active set `WebGapAnimKeyingSetRemoveSet→null`, unchanged `[1, 3, 5]` Action data, and exact save/reopen." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1814, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 454 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00196.md", + "bytes": 1814, + "lines": 38, + "tokens": 454 + }, + { + "path": "tests/golden/M16-GAP-00195/manifest.json", + "bytes": 2676, + "lines": 29, + "tokens": 669 + }, + { + "path": "docs/status/M16-GAP-00195.md", + "bytes": 1073, + "lines": 18, + "tokens": 269 + } + ], + "sourceTokens": 1934, + "evidenceFiles": 1, + "evidenceBytes": 1349, + "evidenceTokens": 338, + "totalTokens": 2272, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3296, + "serializedContextTokens": 758, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00197/anim-keyingset-button-remove-desktop-report.json b/tests/golden/M16-GAP-00197/anim-keyingset-button-remove-desktop-report.json new file mode 100644 index 00000000..74dff566 --- /dev/null +++ b/tests/golden/M16-GAP-00197/anim-keyingset-button-remove-desktop-report.json @@ -0,0 +1,87 @@ +{ + "after": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"button_remove_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1.0, + 3.0, + 5.0 + ] + } + ], + "name": "WebGapAnimKeyingSetButtonRemoveAction" + }, + "active": true, + "activeKeyingSet": "ButtonKeyingSet", + "keyingSetCount": 1, + "pathCount": 0, + "paths": [], + "selected": true, + "value": 3.0 + }, + "before": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"button_remove_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1.0, + 3.0, + 5.0 + ] + } + ], + "name": "WebGapAnimKeyingSetButtonRemoveAction" + }, + "active": true, + "activeKeyingSet": "ButtonKeyingSet", + "keyingSetCount": 1, + "pathCount": 1, + "paths": [ + { + "arrayIndex": 0, + "dataPath": "[\"button_remove_target\"]", + "group": "", + "groupMethod": "KEYINGSET", + "idType": "OBJECT", + "useEntireArray": false + } + ], + "selected": true, + "value": 3.0 + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00197-operator-anim.keyingset_button_remove.blend", + "fixtureSha256": "21b52146f8466fb9fd9ca9073d611b6052f7cbb89399b926d8db6e950883e61d", + "mainMutation": "KEYING_SET_PATH_REMOVED", + "operation": "ANIM_KEYINGSET_BUTTON_REMOVE_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00197" +} diff --git a/tests/golden/M16-GAP-00197/anim-keyingset-button-remove-local-exact-report.json b/tests/golden/M16-GAP-00197/anim-keyingset-button-remove-local-exact-report.json new file mode 100644 index 00000000..78ee1599 --- /dev/null +++ b/tests/golden/M16-GAP-00197/anim-keyingset-button-remove-local-exact-report.json @@ -0,0 +1,118 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00197", + "operation": "ANIM_KEYINGSET_BUTTON_REMOVE_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00197-operator-anim.keyingset_button_remove.blend", + "sha256": "21b52146f8466fb9fd9ca9073d611b6052f7cbb89399b926d8db6e950883e61d" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00197/anim-keyingset-button-remove-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "KEYING_SET_PATH_REMOVED", + "before": { + "action": { + "channels": [ + { + "frames": [ + 1, + 3, + 5 + ], + "index": 0, + "path": "[\"button_remove_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1, + 3, + 5 + ] + } + ], + "name": "WebGapAnimKeyingSetButtonRemoveAction" + }, + "active": true, + "activeKeyingSet": "ButtonKeyingSet", + "keyingSetCount": 1, + "pathCount": 1, + "paths": [ + { + "arrayIndex": 0, + "dataPath": "[\"button_remove_target\"]", + "group": "", + "groupMethod": "KEYINGSET", + "idType": "OBJECT", + "useEntireArray": false + } + ], + "selected": true, + "value": 3 + }, + "after": { + "action": { + "channels": [ + { + "frames": [ + 1, + 3, + 5 + ], + "index": 0, + "path": "[\"button_remove_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1, + 3, + 5 + ] + } + ], + "name": "WebGapAnimKeyingSetButtonRemoveAction" + }, + "active": true, + "activeKeyingSet": "ButtonKeyingSet", + "keyingSetCount": 1, + "pathCount": 0, + "paths": [], + "selected": true, + "value": 3 + } + }, + "wasm": { + "status": "EXACT", + "before": { + "animationId": "action:WebGapAnimKeyingSetButtonRemoveAction:object:WebGapAnimKeyingSetButtonRemoveObject", + "targetId": "object:WebGapAnimKeyingSetButtonRemoveObject", + "channelPaths": [ + "[\"button_remove_target\"][0]" + ], + "keyframesPerChannel": [ + 3 + ] + }, + "after": { + "animationId": "action:WebGapAnimKeyingSetButtonRemoveAction:object:WebGapAnimKeyingSetButtonRemoveObject", + "keyframesPerChannel": [ + 3 + ], + "visibleMainUnchanged": true, + "keyingSetMetadata": "NOT_EXPOSED_BY_SCENE_SNAPSHOT" + } + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00198" +} diff --git a/tests/golden/M16-GAP-00197/manifest.json b/tests/golden/M16-GAP-00197/manifest.json new file mode 100644 index 00000000..589db6ab --- /dev/null +++ b/tests/golden/M16-GAP-00197/manifest.json @@ -0,0 +1,28 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00197", + "parentTask": "M16-GAP-00196", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_KEYINGSET_BUTTON_REMOVE_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { "path": "tests/golden/M16-GAP-00196/manifest.json", "sha256": "ba672d3e9ba02086b25a595fde84f8248d9ed288fdd5b53de0b7ff02071e3e46" }, + "fixture": { "path": "tests/files/web/generated/M16-GAP-00197-operator-anim.keyingset_button_remove.blend", "sha256": "21b52146f8466fb9fd9ca9073d611b6052f7cbb89399b926d8db6e950883e61d" }, + "generator": { "path": "tools/web/generated/M16-GAP-00197.py", "sha256": "34b9c47630db975f40df4ebc156c9b0488dc7bc85ff0fe6cbcc4603aae2da14c" }, + "desktopChecker": { "path": "tools/web/check-action-keyingset-button-remove-desktop.py", "sha256": "0a6c7361b44ef548f4d9bb7ef756e35bd9c09e82ec46edc60626a6918afc57b6" }, + "webChecker": { "path": "tools/web/check-generated-gap.mjs", "sha256": "27f61df7c526c3473f458828ee0d1651c12bdc766936b41517c634464e70b267" }, + "reader": { "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "8824ba3dfb4090b85dc679a583d263b4bdb190a47978f72f3c11f6b565fdacaf" }, + "protocol": { "path": "web/protocol/editor-workflow.ts", "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" }, + "sceneIrProtocol": { "path": "web/protocol/scene-ir.ts", "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" }, + "wasm": { "path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" }, + "wasmPublic": { "path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" }, + "wasmJs": { "path": "web/app/src/vendor/blender/web_engine.js", "sha256": "9c831d0351ac9d0714cce3b1da748cba416ced3086e3c59595cf24ac4da459ed" }, + "desktopReport": { "path": "tests/golden/M16-GAP-00197/anim-keyingset-button-remove-desktop-report.json", "sha256": "223020f990cda11b261e3d0daf3171450718604cee9f923b5bd3aad8c9377b8a" }, + "webReport": { "path": "tests/golden/M16-GAP-00197/anim-keyingset-button-remove-local-exact-report.json", "sha256": "e44421253fcb26b9d313d9f97324b22a46fa8bbd8b734508416bc7bcd43c8f7b" }, + "status": { "path": "docs/status/M16-GAP-00197.md", "sha256": "5f9ee54b01a17a8c4554d58c4f9f415a7feac5790a56aa2545a560ffa4ef2362" }, + "taskContext": { "path": "tests/golden/M16-GAP-00197/task-context.json", "sha256": "e94b2c9d77d75b841ae3fe60df18005fbbd9da080417e91ec06c79ca62a3d67f" } + }, + "nextTask": "M16-GAP-00198" +} diff --git a/tests/golden/M16-GAP-00197/task-context.json b/tests/golden/M16-GAP-00197/task-context.json new file mode 100644 index 00000000..4d634dc1 --- /dev/null +++ b/tests/golden/M16-GAP-00197/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00197", + "parentTask": "M16-GAP-00196", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.keyingset_button_remove data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.keyingset_button_remove", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00197.py -- tests/files/web/generated/M16-GAP-00197-operator-anim.keyingset_button_remove.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00197", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00197" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00197.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2113, + "contextRemainingTokens": 527 + }, + "source": { + "bytes": 7791, + "tokens": 1949 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00197.py", + "bytes": 1613, + "tokens": 404 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00197-operator-anim.keyingset_button_remove.blend", + "bytes": 86831, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 231498, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 477748, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00197/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00197.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00197/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1613, + "tokens": 404 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00198", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00197.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00196/manifest.json", + "parentStatus": "docs/status/M16-GAP-00196.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00197.md", + "tests/golden/M16-GAP-00196/manifest.json", + "docs/status/M16-GAP-00196.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00196", + "parentTask": "M16-GAP-00195", + "status": "done", + "nextTask": "M16-GAP-00197", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00196 Status", + "status: done", + "task: anim.keyingset_button_add operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one selected/active object with a three-key Action and no scene Keying Set. A real `PROPERTIES` RNA button invokes `ANIM_OT_keyingset_button_add()` (`poll=true`, `FINISHED`), creating `ButtonKeyingSet` and adding the active `button_target` path.", + "evidence:", + "- Desktop evidence records Keying Set count `0→1`, path count `0→1`, exact path fields, unchanged `[1, 3, 5]` Action data, and exact save/reopen." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1829, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 458 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00197.md", + "bytes": 1829, + "lines": 38, + "tokens": 458 + }, + { + "path": "tests/golden/M16-GAP-00196/manifest.json", + "bytes": 2691, + "lines": 29, + "tokens": 673 + }, + { + "path": "docs/status/M16-GAP-00196.md", + "bytes": 1103, + "lines": 18, + "tokens": 276 + } + ], + "sourceTokens": 1949, + "evidenceFiles": 1, + "evidenceBytes": 1613, + "evidenceTokens": 404, + "totalTokens": 2353, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3377, + "serializedContextTokens": 760, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00198/anim-merge-animation-desktop-report.json b/tests/golden/M16-GAP-00198/anim-merge-animation-desktop-report.json new file mode 100644 index 00000000..1923610a --- /dev/null +++ b/tests/golden/M16-GAP-00198/anim-merge-animation-desktop-report.json @@ -0,0 +1,164 @@ +{ + "after": { + "active": true, + "activeObject": "WebGapAnimMergeActiveObject", + "activeObjectAction": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"active_merge_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1.0, + 3.0, + 5.0 + ] + }, + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"source_merge_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 10.0, + 30.0, + 50.0 + ] + } + ], + "name": "WebGapAnimMergeActiveAction" + }, + "selected": { + "active": true, + "source": true + }, + "sourceObject": "WebGapAnimMergeSourceObject", + "sourceObjectAction": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"active_merge_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1.0, + 3.0, + 5.0 + ] + }, + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"source_merge_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 10.0, + 30.0, + 50.0 + ] + } + ], + "name": "WebGapAnimMergeActiveAction" + } + }, + "before": { + "active": true, + "activeObject": "WebGapAnimMergeActiveObject", + "activeObjectAction": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"active_merge_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1.0, + 3.0, + 5.0 + ] + } + ], + "name": "WebGapAnimMergeActiveAction" + }, + "selected": { + "active": true, + "source": true + }, + "sourceObject": "WebGapAnimMergeSourceObject", + "sourceObjectAction": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"source_merge_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 10.0, + 30.0, + 50.0 + ] + } + ], + "name": "WebGapAnimMergeSourceAction" + } + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00198-operator-anim.merge_animation.blend", + "fixtureSha256": "0c37b1290f08b1ad872efdf8a52c795d24778a1ecab516ea749ff2ae858bd2fb", + "mainMutation": "ANIMATION_MERGED", + "operation": "ANIM_MERGE_ANIMATION_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00198" +} diff --git a/tests/golden/M16-GAP-00198/anim-merge-animation-local-exact-report.json b/tests/golden/M16-GAP-00198/anim-merge-animation-local-exact-report.json new file mode 100644 index 00000000..8c0f85d0 --- /dev/null +++ b/tests/golden/M16-GAP-00198/anim-merge-animation-local-exact-report.json @@ -0,0 +1,216 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00198", + "operation": "ANIM_MERGE_ANIMATION_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00198-operator-anim.merge_animation.blend", + "sha256": "0c37b1290f08b1ad872efdf8a52c795d24778a1ecab516ea749ff2ae858bd2fb" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00198/anim-merge-animation-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "ANIMATION_MERGED", + "before": { + "active": true, + "activeObject": "WebGapAnimMergeActiveObject", + "activeObjectAction": { + "channels": [ + { + "frames": [ + 1, + 3, + 5 + ], + "index": 0, + "path": "[\"active_merge_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1, + 3, + 5 + ] + } + ], + "name": "WebGapAnimMergeActiveAction" + }, + "selected": { + "active": true, + "source": true + }, + "sourceObject": "WebGapAnimMergeSourceObject", + "sourceObjectAction": { + "channels": [ + { + "frames": [ + 1, + 3, + 5 + ], + "index": 0, + "path": "[\"source_merge_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 10, + 30, + 50 + ] + } + ], + "name": "WebGapAnimMergeSourceAction" + } + }, + "after": { + "active": true, + "activeObject": "WebGapAnimMergeActiveObject", + "activeObjectAction": { + "channels": [ + { + "frames": [ + 1, + 3, + 5 + ], + "index": 0, + "path": "[\"active_merge_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1, + 3, + 5 + ] + }, + { + "frames": [ + 1, + 3, + 5 + ], + "index": 0, + "path": "[\"source_merge_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 10, + 30, + 50 + ] + } + ], + "name": "WebGapAnimMergeActiveAction" + }, + "selected": { + "active": true, + "source": true + }, + "sourceObject": "WebGapAnimMergeSourceObject", + "sourceObjectAction": { + "channels": [ + { + "frames": [ + 1, + 3, + 5 + ], + "index": 0, + "path": "[\"active_merge_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 1, + 3, + 5 + ] + }, + { + "frames": [ + 1, + 3, + 5 + ], + "index": 0, + "path": "[\"source_merge_target\"]", + "selected": [ + true, + true, + true + ], + "values": [ + 10, + 30, + 50 + ] + } + ], + "name": "WebGapAnimMergeActiveAction" + } + } + }, + "wasm": { + "status": "EXACT", + "before": { + "activeAnimationId": "action:WebGapAnimMergeActiveAction:object:WebGapAnimMergeActiveObject", + "sourceAnimationId": "action:WebGapAnimMergeSourceAction:object:WebGapAnimMergeSourceObject", + "activeChannelPaths": [ + "[\"active_merge_target\"][0]" + ], + "sourceChannelPaths": [ + "[\"source_merge_target\"][0]" + ], + "keyframesPerChannel": [ + 3, + 3 + ] + }, + "after": { + "activeAnimationId": "action:WebGapAnimMergeActiveAction:object:WebGapAnimMergeActiveObject", + "sourceAnimationId": "action:WebGapAnimMergeActiveAction:object:WebGapAnimMergeSourceObject", + "channelPaths": [ + "[\"active_merge_target\"][0]", + "[\"source_merge_target\"][0]" + ], + "keyframesPerChannel": [ + 3, + 3 + ], + "sourceValues": [ + [ + 1, + 3, + 5 + ], + [ + 10, + 30, + 50 + ] + ] + }, + "sourceActionRemoved": true + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00199" +} diff --git a/tests/golden/M16-GAP-00198/manifest.json b/tests/golden/M16-GAP-00198/manifest.json new file mode 100644 index 00000000..ca424edf --- /dev/null +++ b/tests/golden/M16-GAP-00198/manifest.json @@ -0,0 +1,28 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00198", + "parentTask": "M16-GAP-00197", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_MERGE_ANIMATION_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { "path": "tests/golden/M16-GAP-00197/manifest.json", "sha256": "330488ecec1bfee69e43b02fce9b79cfd3f5e8931d66cabf1602ca1d44e94947" }, + "fixture": { "path": "tests/files/web/generated/M16-GAP-00198-operator-anim.merge_animation.blend", "sha256": "0c37b1290f08b1ad872efdf8a52c795d24778a1ecab516ea749ff2ae858bd2fb" }, + "generator": { "path": "tools/web/generated/M16-GAP-00198.py", "sha256": "85004c8e8f9e92eea7a87f266de34d07950b993b7af6bd09e642d99bd1f54eb7" }, + "desktopChecker": { "path": "tools/web/check-action-merge-animation-desktop.py", "sha256": "0f7aabaad764f96992e4a1cbe56a586ce0c03e67b0cdc642073a5222cf5b5fcb" }, + "webChecker": { "path": "tools/web/check-generated-gap.mjs", "sha256": "41c97bd2af26262e21a66e46baaf38969772bd5ba5df72609102f9d3bfd0d8ae" }, + "reader": { "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "8824ba3dfb4090b85dc679a583d263b4bdb190a47978f72f3c11f6b565fdacaf" }, + "protocol": { "path": "web/protocol/editor-workflow.ts", "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" }, + "sceneIrProtocol": { "path": "web/protocol/scene-ir.ts", "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" }, + "wasm": { "path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" }, + "wasmPublic": { "path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" }, + "wasmJs": { "path": "web/app/src/vendor/blender/web_engine.js", "sha256": "9c831d0351ac9d0714cce3b1da748cba416ced3086e3c59595cf24ac4da459ed" }, + "desktopReport": { "path": "tests/golden/M16-GAP-00198/anim-merge-animation-desktop-report.json", "sha256": "e170913f6dd5161a10853f04c2e56ea1181de5de12fdf5fbb1159745dcd0f757" }, + "webReport": { "path": "tests/golden/M16-GAP-00198/anim-merge-animation-local-exact-report.json", "sha256": "914ef24f01a81d7baceeed4f67f317abf529cedec6ddbbd22c1ed35bb94039e2" }, + "status": { "path": "docs/status/M16-GAP-00198.md", "sha256": "7bf5d2f34a6fa5b19efca51fe360358da8e8030419fd78687314e690598125aa" }, + "taskContext": { "path": "tests/golden/M16-GAP-00198/task-context.json", "sha256": "33a275667991c5fc655596a0197bb46467f233a307bcb7752f5531ee9a3819d3" } + }, + "nextTask": "M16-GAP-00199" +} diff --git a/tests/golden/M16-GAP-00198/task-context.json b/tests/golden/M16-GAP-00198/task-context.json new file mode 100644 index 00000000..da76b386 --- /dev/null +++ b/tests/golden/M16-GAP-00198/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00198", + "parentTask": "M16-GAP-00197", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.merge_animation data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.merge_animation", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00198.py -- tests/files/web/generated/M16-GAP-00198-operator-anim.merge_animation.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00198", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00198" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00198.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2121, + "contextRemainingTokens": 529 + }, + "source": { + "bytes": 7783, + "tokens": 1947 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00198.py", + "bytes": 1665, + "tokens": 417 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00198-operator-anim.merge_animation.blend", + "bytes": 87247, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 231498, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 485219, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00198/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00198.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00198/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1665, + "tokens": 417 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00199", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00198.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00197/manifest.json", + "parentStatus": "docs/status/M16-GAP-00197.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00198.md", + "tests/golden/M16-GAP-00197/manifest.json", + "docs/status/M16-GAP-00197.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00197", + "parentTask": "M16-GAP-00196", + "status": "done", + "nextTask": "M16-GAP-00198", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00197 Status", + "status: done", + "task: anim.keyingset_button_remove operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one selected/active object with a three-key Action and one active `ButtonKeyingSet` path. A real `PROPERTIES` RNA button invokes `ANIM_OT_keyingset_button_remove()` (`poll=true`, `FINISHED`), removing the active property path without changing the Action.", + "evidence:", + "- Desktop evidence records path count `1→0`, the unchanged active Keying Set, exact pre-existing path fields, unchanged `[1, 3, 5]` Action data, and exact save/reopen." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1789, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 448 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00198.md", + "bytes": 1789, + "lines": 38, + "tokens": 448 + }, + { + "path": "tests/golden/M16-GAP-00197/manifest.json", + "bytes": 2706, + "lines": 29, + "tokens": 677 + }, + { + "path": "docs/status/M16-GAP-00197.md", + "bytes": 1120, + "lines": 18, + "tokens": 280 + } + ], + "sourceTokens": 1947, + "evidenceFiles": 1, + "evidenceBytes": 1665, + "evidenceTokens": 417, + "totalTokens": 2364, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3388, + "serializedContextTokens": 754, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00199/anim-paste-driver-button-desktop-report.json b/tests/golden/M16-GAP-00199/anim-paste-driver-button-desktop-report.json new file mode 100644 index 00000000..c21b8074 --- /dev/null +++ b/tests/golden/M16-GAP-00199/anim-paste-driver-button-desktop-report.json @@ -0,0 +1,65 @@ +{ + "after": { + "source": { + "drivers": [ + { + "expression": "frame * 3.0 + 2.0", + "index": 0, + "path": "[\"source_target\"]", + "type": "SCRIPTED", + "variableCount": 0 + } + ], + "value": 5.0 + }, + "target": { + "drivers": [ + { + "expression": "frame * 3.0 + 2.0", + "index": 0, + "path": "[\"paste_target\"]", + "type": "SCRIPTED", + "variableCount": 0 + } + ], + "value": 5.0 + } + }, + "before": { + "source": { + "drivers": [ + { + "expression": "frame * 3.0 + 2.0", + "index": 0, + "path": "[\"source_target\"]", + "type": "SCRIPTED", + "variableCount": 0 + } + ], + "value": 5.0 + }, + "target": { + "drivers": [ + { + "expression": "frame * 3.0 + 2.0", + "index": 0, + "path": "[\"paste_target\"]", + "type": "SCRIPTED", + "variableCount": 0 + } + ], + "value": 5.0 + } + }, + "blenderVersion": "5.2.0 LTS", + "evidenceStatus": "PRESERVED", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00199-operator-anim.paste_driver_button.blend", + "fixtureSha256": "971782396db424a9b427f7fb9d9d1495ddc572a2ae1bf7b7b8c3320f5d8d77d9", + "mainMutation": "DRIVER_PASTED", + "operation": "ANIM_PASTE_DRIVER_BUTTON_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00199" +} diff --git a/tests/golden/M16-GAP-00199/anim-paste-driver-button-local-exact-report.json b/tests/golden/M16-GAP-00199/anim-paste-driver-button-local-exact-report.json new file mode 100644 index 00000000..4d79a870 --- /dev/null +++ b/tests/golden/M16-GAP-00199/anim-paste-driver-button-local-exact-report.json @@ -0,0 +1,52 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00199", + "operation": "ANIM_PASTE_DRIVER_BUTTON_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00199-operator-anim.paste_driver_button.blend", + "sha256": "971782396db424a9b427f7fb9d9d1495ddc572a2ae1bf7b7b8c3320f5d8d77d9" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00199/anim-paste-driver-button-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "DRIVER_PASTED" + }, + "wasm": { + "status": "EXACT", + "objectId": "object:WebGapAnimPasteDriverButtonObject", + "drivers": [ + { + "arrayIndex": 0, + "editable": true, + "enabled": true, + "expression": "frame * 3.0 + 2.0", + "flags": 8, + "influence": 0, + "path": "[\"source_target\"]", + "type": "SCRIPTED", + "typeCode": 1, + "variables": [] + }, + { + "arrayIndex": 0, + "editable": true, + "enabled": true, + "expression": "frame * 3.0 + 2.0", + "flags": 8, + "influence": 0, + "path": "[\"paste_target\"]", + "type": "SCRIPTED", + "typeCode": 1, + "variables": [] + } + ] + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00200" +} diff --git a/tests/golden/M16-GAP-00199/manifest.json b/tests/golden/M16-GAP-00199/manifest.json new file mode 100644 index 00000000..2588b212 --- /dev/null +++ b/tests/golden/M16-GAP-00199/manifest.json @@ -0,0 +1,28 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00199", + "parentTask": "M16-GAP-00198", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_PASTE_DRIVER_BUTTON_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { "path": "tests/golden/M16-GAP-00198/manifest.json", "sha256": "7f651bc4b2238504adcb02dc35455735e7aa6cd524358e9ca0a2429546da070c" }, + "fixture": { "path": "tests/files/web/generated/M16-GAP-00199-operator-anim.paste_driver_button.blend", "sha256": "971782396db424a9b427f7fb9d9d1495ddc572a2ae1bf7b7b8c3320f5d8d77d9" }, + "generator": { "path": "tools/web/generated/M16-GAP-00199.py", "sha256": "6ef118516c3eed69fa601631d26f5ecef355fe9f58907a1c7e33c4a8cd2be88e" }, + "desktopChecker": { "path": "tools/web/check-action-paste-driver-button-desktop.py", "sha256": "2c167b38e9688880b499abe97babd2f51134b2b83efd5bb34140bb0b81079375" }, + "webChecker": { "path": "tools/web/check-generated-gap.mjs", "sha256": "09d0d45a5454f9c9eea29414d412c28a372d3dcff9ac645fc16ff68566ce4d6f" }, + "reader": { "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "8824ba3dfb4090b85dc679a583d263b4bdb190a47978f72f3c11f6b565fdacaf" }, + "protocol": { "path": "web/protocol/editor-workflow.ts", "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" }, + "sceneIrProtocol": { "path": "web/protocol/scene-ir.ts", "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" }, + "wasm": { "path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" }, + "wasmPublic": { "path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" }, + "wasmJs": { "path": "web/app/src/vendor/blender/web_engine.js", "sha256": "9c831d0351ac9d0714cce3b1da748cba416ced3086e3c59595cf24ac4da459ed" }, + "desktopReport": { "path": "tests/golden/M16-GAP-00199/anim-paste-driver-button-desktop-report.json", "sha256": "b20074b47768751a5e6c884165c4119e95296eb7a6fc4812e8bef3676e7aaf08" }, + "webReport": { "path": "tests/golden/M16-GAP-00199/anim-paste-driver-button-local-exact-report.json", "sha256": "7f860445f0e6889e6993e458b0e81f075c5b97fe8c2cf35b0eae4846e2d4cc5e" }, + "status": { "path": "docs/status/M16-GAP-00199.md", "sha256": "920d779ace3658975b5f2451fb48b644f7d64ce81129b89d6e1eb9fc5ac6e6c9" }, + "taskContext": { "path": "tests/golden/M16-GAP-00199/task-context.json", "sha256": "e054e382aa573e117fc34d47e2e2d8733ac17d75d490dc4f5de397e3fb9658f7" } + }, + "nextTask": "M16-GAP-00200" +} diff --git a/tests/golden/M16-GAP-00199/task-context.json b/tests/golden/M16-GAP-00199/task-context.json new file mode 100644 index 00000000..22f4f6ad --- /dev/null +++ b/tests/golden/M16-GAP-00199/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00199", + "parentTask": "M16-GAP-00198", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.paste_driver_button data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.paste_driver_button", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00199.py -- tests/files/web/generated/M16-GAP-00199-operator-anim.paste_driver_button.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00199", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00199" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00199.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2055, + "contextRemainingTokens": 512 + }, + "source": { + "bytes": 7849, + "tokens": 1964 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00199.py", + "bytes": 1222, + "tokens": 306 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00199-operator-anim.paste_driver_button.blend", + "bytes": 86601, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 231498, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 489417, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00199/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00199.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00199/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1222, + "tokens": 306 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00200", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00199.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00198/manifest.json", + "parentStatus": "docs/status/M16-GAP-00198.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00199.md", + "tests/golden/M16-GAP-00198/manifest.json", + "docs/status/M16-GAP-00198.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00198", + "parentTask": "M16-GAP-00197", + "status": "done", + "nextTask": "M16-GAP-00199", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00198 Status", + "status: done", + "task: anim.merge_animation operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains two selected mesh objects. The active object owns `WebGapAnimMergeActiveAction`; the source object owns `WebGapAnimMergeSourceAction`, each with one three-key custom-property channel.", + "- Blender invokes `ANIM_OT_merge_animation` with `poll=true` and `FINISHED`, moving the source slot into the active action. Both objects then observe `WebGapAnimMergeActiveAction` with both channels; the source action has no remaining users.", + "evidence:" + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1809, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 453 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00199.md", + "bytes": 1809, + "lines": 38, + "tokens": 453 + }, + { + "path": "tests/golden/M16-GAP-00198/manifest.json", + "bytes": 2666, + "lines": 29, + "tokens": 667 + }, + { + "path": "docs/status/M16-GAP-00198.md", + "bytes": 1206, + "lines": 19, + "tokens": 302 + } + ], + "sourceTokens": 1964, + "evidenceFiles": 1, + "evidenceBytes": 1222, + "evidenceTokens": 306, + "totalTokens": 2270, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3294, + "serializedContextTokens": 757, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00200/anim-previewrange-clear-desktop-report.json b/tests/golden/M16-GAP-00200/anim-previewrange-clear-desktop-report.json new file mode 100644 index 00000000..dbe68085 --- /dev/null +++ b/tests/golden/M16-GAP-00200/anim-previewrange-clear-desktop-report.json @@ -0,0 +1,23 @@ +{ + "after": { + "end": 0, + "start": 0, + "use": false + }, + "before": { + "end": 0, + "start": 0, + "use": false + }, + "blenderVersion": "5.2.0 LTS", + "evidenceStatus": "PRESERVED", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00200-operator-anim.previewrange_clear.blend", + "fixtureSha256": "c9b586fb0a87f38c4fb1e4e1834805fda1345549ecdc558702080ea66af65a9e", + "mainMutation": "PREVIEW_RANGE_CLEARED", + "operation": "ANIM_PREVIEWRANGE_CLEAR_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00200" +} diff --git a/tests/golden/M16-GAP-00200/anim-previewrange-clear-local-exact-report.json b/tests/golden/M16-GAP-00200/anim-previewrange-clear-local-exact-report.json new file mode 100644 index 00000000..9255d97d --- /dev/null +++ b/tests/golden/M16-GAP-00200/anim-previewrange-clear-local-exact-report.json @@ -0,0 +1,29 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00200", + "operation": "ANIM_PREVIEWRANGE_CLEAR_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00200-operator-anim.previewrange_clear.blend", + "sha256": "c9b586fb0a87f38c4fb1e4e1834805fda1345549ecdc558702080ea66af65a9e" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00200/anim-previewrange-clear-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "PREVIEW_RANGE_CLEARED" + }, + "wasm": { + "status": "EXACT", + "sceneId": "scene:Scene", + "previewRange": null, + "frameStart": 1, + "frameEnd": 8 + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00201" +} diff --git a/tests/golden/M16-GAP-00200/manifest.json b/tests/golden/M16-GAP-00200/manifest.json new file mode 100644 index 00000000..acd612e3 --- /dev/null +++ b/tests/golden/M16-GAP-00200/manifest.json @@ -0,0 +1,28 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00200", + "parentTask": "M16-GAP-00199", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_PREVIEWRANGE_CLEAR_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { "path": "tests/golden/M16-GAP-00199/manifest.json", "sha256": "55e28b867275c897d142b4da366a68368006de40ba7edde39b4637ce0b3771bb" }, + "fixture": { "path": "tests/files/web/generated/M16-GAP-00200-operator-anim.previewrange_clear.blend", "sha256": "c9b586fb0a87f38c4fb1e4e1834805fda1345549ecdc558702080ea66af65a9e" }, + "generator": { "path": "tools/web/generated/M16-GAP-00200.py", "sha256": "92d82b88dd301e895fe075c7d1760b1cb4147c7049a3c6d69509fc17e14b64d1" }, + "desktopChecker": { "path": "tools/web/check-action-previewrange-clear-desktop.py", "sha256": "02b2704fd6edae72cb31d603c6a1ddf4a3054370627044ba4c1f66e30c488e3e" }, + "webChecker": { "path": "tools/web/check-generated-gap.mjs", "sha256": "7d5ab57408c5fa21ce8ff0998d212f5685d9900e1d2ff135f19fe9ec6c0197c9" }, + "reader": { "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "8824ba3dfb4090b85dc679a583d263b4bdb190a47978f72f3c11f6b565fdacaf" }, + "protocol": { "path": "web/protocol/editor-workflow.ts", "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" }, + "sceneIrProtocol": { "path": "web/protocol/scene-ir.ts", "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" }, + "wasm": { "path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" }, + "wasmPublic": { "path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" }, + "wasmJs": { "path": "web/app/src/vendor/blender/web_engine.js", "sha256": "9c831d0351ac9d0714cce3b1da748cba416ced3086e3c59595cf24ac4da459ed" }, + "desktopReport": { "path": "tests/golden/M16-GAP-00200/anim-previewrange-clear-desktop-report.json", "sha256": "b1e7212248ff23d323e9c00645db52b38c4570f42c344b6325f1506c404704c4" }, + "webReport": { "path": "tests/golden/M16-GAP-00200/anim-previewrange-clear-local-exact-report.json", "sha256": "7ba44c02fcfa34df1c4e25fb3567474893b47dc4a20522f33634cd3ad36fe940" }, + "status": { "path": "docs/status/M16-GAP-00200.md", "sha256": "314c2534f8291496721d190b7345954f1e7e9218b9756d1b6bfdc4486a112b9e" }, + "taskContext": { "path": "tests/golden/M16-GAP-00200/task-context.json", "sha256": "1cb7806458458bc5e417a84b556e3fb777457f2af1e1dcd2fc4936911cfc508a" } + }, + "nextTask": "M16-GAP-00201" +} diff --git a/tests/golden/M16-GAP-00200/task-context.json b/tests/golden/M16-GAP-00200/task-context.json new file mode 100644 index 00000000..752898de --- /dev/null +++ b/tests/golden/M16-GAP-00200/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00200", + "parentTask": "M16-GAP-00199", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.previewrange_clear data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.previewrange_clear", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00200.py -- tests/files/web/generated/M16-GAP-00200-operator-anim.previewrange_clear.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00200", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00200" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00200.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2121, + "contextRemainingTokens": 529 + }, + "source": { + "bytes": 7783, + "tokens": 1947 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00200.py", + "bytes": 1765, + "tokens": 442 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00200-operator-anim.previewrange_clear.blend", + "bytes": 86336, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 231498, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 493085, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00200/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00200.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00200/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1765, + "tokens": 442 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00201", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00200.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00199/manifest.json", + "parentStatus": "docs/status/M16-GAP-00199.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00200.md", + "tests/golden/M16-GAP-00199/manifest.json", + "docs/status/M16-GAP-00199.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00199", + "parentTask": "M16-GAP-00198", + "status": "done", + "nextTask": "M16-GAP-00200", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00199 Status", + "status: done", + "task: anim.paste_driver_button operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one mesh object with a driven `source_target` custom property and an undriven `paste_target` custom property. Desktop UI evidence copies the source driver and pastes it into the target through `ANIM_OT_paste_driver_button`.", + "- The saved fixture exposes both scripted drivers with the same expression in WASM/Main; no reader, protocol, or browser change was required.", + "evidence:" + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1804, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 451 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00200.md", + "bytes": 1804, + "lines": 38, + "tokens": 451 + }, + { + "path": "tests/golden/M16-GAP-00199/manifest.json", + "bytes": 2686, + "lines": 29, + "tokens": 672 + }, + { + "path": "docs/status/M16-GAP-00199.md", + "bytes": 1125, + "lines": 19, + "tokens": 282 + } + ], + "sourceTokens": 1947, + "evidenceFiles": 1, + "evidenceBytes": 1765, + "evidenceTokens": 442, + "totalTokens": 2389, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3413, + "serializedContextTokens": 757, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00201/anim-previewrange-set-desktop-report.json b/tests/golden/M16-GAP-00201/anim-previewrange-set-desktop-report.json new file mode 100644 index 00000000..37fff861 --- /dev/null +++ b/tests/golden/M16-GAP-00201/anim-previewrange-set-desktop-report.json @@ -0,0 +1,22 @@ +{ + "after": { + "end": 6, + "start": 2, + "use": true + }, + "before": { + "end": 6, + "start": 2, + "use": true + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00201-operator-anim.previewrange_set.blend", + "fixtureSha256": "91d61fe3989324a23db7dabbb178c7b0a963af155c117c57859a24e4c415945e", + "mainMutation": "PREVIEW_RANGE_SET", + "operation": "ANIM_PREVIEWRANGE_SET_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00201" +} diff --git a/tests/golden/M16-GAP-00201/anim-previewrange-set-local-exact-report.json b/tests/golden/M16-GAP-00201/anim-previewrange-set-local-exact-report.json new file mode 100644 index 00000000..2fca34e4 --- /dev/null +++ b/tests/golden/M16-GAP-00201/anim-previewrange-set-local-exact-report.json @@ -0,0 +1,32 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00201", + "operation": "ANIM_PREVIEWRANGE_SET_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00201-operator-anim.previewrange_set.blend", + "sha256": "91d61fe3989324a23db7dabbb178c7b0a963af155c117c57859a24e4c415945e" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00201/anim-previewrange-set-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "PREVIEW_RANGE_SET" + }, + "wasm": { + "status": "EXACT", + "sceneId": "scene:Scene", + "previewRange": { + "end": 6, + "start": 2 + }, + "frameStart": 1, + "frameEnd": 8 + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00202" +} diff --git a/tests/golden/M16-GAP-00201/manifest.json b/tests/golden/M16-GAP-00201/manifest.json new file mode 100644 index 00000000..f7956a63 --- /dev/null +++ b/tests/golden/M16-GAP-00201/manifest.json @@ -0,0 +1,28 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00201", + "parentTask": "M16-GAP-00200", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_PREVIEWRANGE_SET_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { "path": "tests/golden/M16-GAP-00200/manifest.json", "sha256": "d0e50c659eae65217eb314559e6c4aaa50dd830a6a53d5a3ff9aa182e1baf6ed" }, + "fixture": { "path": "tests/files/web/generated/M16-GAP-00201-operator-anim.previewrange_set.blend", "sha256": "91d61fe3989324a23db7dabbb178c7b0a963af155c117c57859a24e4c415945e" }, + "generator": { "path": "tools/web/generated/M16-GAP-00201.py", "sha256": "94fac7954b5c1fd566c48b4dfac58fa2581b6068360cccee7b436e30e5bed9c0" }, + "desktopChecker": { "path": "tools/web/check-action-previewrange-set-desktop.py", "sha256": "0c667ab6e9ca9e866234fa9e190dc30587b59ffeba5616b4b37853569e6d24a9" }, + "webChecker": { "path": "tools/web/check-generated-gap.mjs", "sha256": "08a20a0f20d32978b5a7c46cf4143f444aaad903a0bfcc805dfae9289b56fe81" }, + "reader": { "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "8824ba3dfb4090b85dc679a583d263b4bdb190a47978f72f3c11f6b565fdacaf" }, + "protocol": { "path": "web/protocol/editor-workflow.ts", "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" }, + "sceneIrProtocol": { "path": "web/protocol/scene-ir.ts", "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" }, + "wasm": { "path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" }, + "wasmPublic": { "path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" }, + "wasmJs": { "path": "web/app/src/vendor/blender/web_engine.js", "sha256": "9c831d0351ac9d0714cce3b1da748cba416ced3086e3c59595cf24ac4da459ed" }, + "desktopReport": { "path": "tests/golden/M16-GAP-00201/anim-previewrange-set-desktop-report.json", "sha256": "9a4abf76db56b660808f66834d941771a0cf860a662d53771ff8bf309bf2a162" }, + "webReport": { "path": "tests/golden/M16-GAP-00201/anim-previewrange-set-local-exact-report.json", "sha256": "7751033cb2d246ed4b87d10592894f27574d3409b5d48f3161a583f186786b67" }, + "status": { "path": "docs/status/M16-GAP-00201.md", "sha256": "9b5e2b1a31558340dc633d476fb379bd4bb460b8d246f4b2b4576b1734b3a95b" }, + "taskContext": { "path": "tests/golden/M16-GAP-00201/task-context.json", "sha256": "0ac3856c852d6f7e08c7709f2b6435b46e1ddb2514004d9c9caf10d255b71e72" } + }, + "nextTask": "M16-GAP-00202" +} diff --git a/tests/golden/M16-GAP-00201/task-context.json b/tests/golden/M16-GAP-00201/task-context.json new file mode 100644 index 00000000..a0dce9e6 --- /dev/null +++ b/tests/golden/M16-GAP-00201/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00201", + "parentTask": "M16-GAP-00200", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.previewrange_set data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.previewrange_set", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00201.py -- tests/files/web/generated/M16-GAP-00201-operator-anim.previewrange_set.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00201", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00201" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00201.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2284, + "contextRemainingTokens": 569 + }, + "source": { + "bytes": 7620, + "tokens": 1907 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00201.py", + "bytes": 1707, + "tokens": 427 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00201-operator-anim.previewrange_set.blend", + "bytes": 86352, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 231498, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 496749, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00201/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00201.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00201/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1707, + "tokens": 427 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00202", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00201.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00200/manifest.json", + "parentStatus": "docs/status/M16-GAP-00200.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00201.md", + "tests/golden/M16-GAP-00200/manifest.json", + "docs/status/M16-GAP-00200.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00200", + "parentTask": "M16-GAP-00199", + "status": "done", + "nextTask": "M16-GAP-00201", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00200 Status", + "status: done", + "task: anim.previewrange_clear operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture starts with a `2..6` scene preview range. Desktop runs `ANIM_OT_previewrange_clear` in the active Dope Sheet animation context and saves the cleared Main.", + "- WASM/Main observes the same scene with no `previewRange` field and an unchanged frame range; no reader, protocol, or browser change was required.", + "evidence:" + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1794, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 449 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00201.md", + "bytes": 1794, + "lines": 38, + "tokens": 449 + }, + { + "path": "tests/golden/M16-GAP-00200/manifest.json", + "bytes": 2681, + "lines": 29, + "tokens": 671 + }, + { + "path": "docs/status/M16-GAP-00200.md", + "bytes": 977, + "lines": 19, + "tokens": 245 + } + ], + "sourceTokens": 1907, + "evidenceFiles": 1, + "evidenceBytes": 1707, + "evidenceTokens": 427, + "totalTokens": 2334, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3358, + "serializedContextTokens": 755, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00202/anim-replace-action-desktop-report.json b/tests/golden/M16-GAP-00202/anim-replace-action-desktop-report.json new file mode 100644 index 00000000..33fe0550 --- /dev/null +++ b/tests/golden/M16-GAP-00202/anim-replace-action-desktop-report.json @@ -0,0 +1,172 @@ +{ + "after": { + "actions": { + "WebGapAnimReplaceNewAction": 4, + "WebGapAnimReplaceOldAction": 1 + }, + "activeObject": "WebGapAnimReplaceOldA", + "objects": { + "WebGapAnimReplaceNewUser": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"replace_target\"]", + "values": [ + 10.0, + 30.0, + 50.0 + ] + } + ], + "name": "WebGapAnimReplaceNewAction" + }, + "WebGapAnimReplaceOldA": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"replace_target\"]", + "values": [ + 10.0, + 30.0, + 50.0 + ] + } + ], + "name": "WebGapAnimReplaceNewAction" + }, + "WebGapAnimReplaceOldB": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"replace_target\"]", + "values": [ + 10.0, + 30.0, + 50.0 + ] + } + ], + "name": "WebGapAnimReplaceNewAction" + } + } + }, + "before": { + "actions": { + "WebGapAnimReplaceNewAction": 2, + "WebGapAnimReplaceOldAction": 3 + }, + "activeObject": "WebGapAnimReplaceOldA", + "objects": { + "WebGapAnimReplaceNewUser": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"replace_target\"]", + "values": [ + 10.0, + 30.0, + 50.0 + ] + } + ], + "name": "WebGapAnimReplaceNewAction" + }, + "WebGapAnimReplaceOldA": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"replace_target\"]", + "values": [ + 1.0, + 3.0, + 5.0 + ] + }, + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"replace_target\"]", + "values": [ + 2.0, + 4.0, + 6.0 + ] + } + ], + "name": "WebGapAnimReplaceOldAction" + }, + "WebGapAnimReplaceOldB": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"replace_target\"]", + "values": [ + 1.0, + 3.0, + 5.0 + ] + }, + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"replace_target\"]", + "values": [ + 2.0, + 4.0, + 6.0 + ] + } + ], + "name": "WebGapAnimReplaceOldAction" + } + } + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00202-operator-anim.replace_action.blend", + "fixtureSha256": "f29c88ecc031b1a56c68cea244417035bf8744db5baaab623627e6dab889f956", + "mainMutation": "ACTIONS_REPLACED", + "operation": "ANIM_REPLACE_ACTION_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00202" +} diff --git a/tests/golden/M16-GAP-00202/anim-replace-action-local-exact-report.json b/tests/golden/M16-GAP-00202/anim-replace-action-local-exact-report.json new file mode 100644 index 00000000..68a0e1bd --- /dev/null +++ b/tests/golden/M16-GAP-00202/anim-replace-action-local-exact-report.json @@ -0,0 +1,38 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00202", + "operation": "ANIM_REPLACE_ACTION_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00202-operator-anim.replace_action.blend", + "sha256": "f29c88ecc031b1a56c68cea244417035bf8744db5baaab623627e6dab889f956" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00202/anim-replace-action-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "ACTIONS_REPLACED" + }, + "wasm": { + "status": "EXACT", + "replacedObjectIds": [ + "object:WebGapAnimReplaceNewUser", + "object:WebGapAnimReplaceOldA", + "object:WebGapAnimReplaceOldB" + ], + "newAction": "WebGapAnimReplaceNewAction", + "oldActionUnlinked": "action:WebGapAnimReplaceOldAction:unlinked", + "channelsPerObject": [ + 1, + 1, + 1 + ], + "oldActionChannels": 2 + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00203" +} diff --git a/tests/golden/M16-GAP-00202/manifest.json b/tests/golden/M16-GAP-00202/manifest.json new file mode 100644 index 00000000..4271eb90 --- /dev/null +++ b/tests/golden/M16-GAP-00202/manifest.json @@ -0,0 +1,28 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00202", + "parentTask": "M16-GAP-00201", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_REPLACE_ACTION_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { "path": "tests/golden/M16-GAP-00201/manifest.json", "sha256": "57d93e7b6005d067485bf88745444309c342983d9428072a773a5fa9de6a7d35" }, + "fixture": { "path": "tests/files/web/generated/M16-GAP-00202-operator-anim.replace_action.blend", "sha256": "f29c88ecc031b1a56c68cea244417035bf8744db5baaab623627e6dab889f956" }, + "generator": { "path": "tools/web/generated/M16-GAP-00202.py", "sha256": "bf8fc46f38503e773ffa46248feca82de6120321888924eafb3779dc232984e8" }, + "desktopChecker": { "path": "tools/web/check-action-replace-action-desktop.py", "sha256": "9415485899bb577d178c2345240dccf42ef90f1146a9c7be7064ddfeef9df0b1" }, + "webChecker": { "path": "tools/web/check-generated-gap.mjs", "sha256": "007da7f0d0b0959fe8688aa532198a7a4ba3bb4827a99bfe83c210f8b9b970f2" }, + "reader": { "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "8824ba3dfb4090b85dc679a583d263b4bdb190a47978f72f3c11f6b565fdacaf" }, + "protocol": { "path": "web/protocol/editor-workflow.ts", "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" }, + "sceneIrProtocol": { "path": "web/protocol/scene-ir.ts", "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" }, + "wasm": { "path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" }, + "wasmPublic": { "path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" }, + "wasmJs": { "path": "web/app/src/vendor/blender/web_engine.js", "sha256": "9c831d0351ac9d0714cce3b1da748cba416ced3086e3c59595cf24ac4da459ed" }, + "desktopReport": { "path": "tests/golden/M16-GAP-00202/anim-replace-action-desktop-report.json", "sha256": "fdb5531aa70842959bb57b8b9490c9839037af9a69191e23834e8793b507ac10" }, + "webReport": { "path": "tests/golden/M16-GAP-00202/anim-replace-action-local-exact-report.json", "sha256": "c122dbb9daadb8a449032ac742d308e7b9473bb4d05ae7855cf80ed3982f4263" }, + "status": { "path": "docs/status/M16-GAP-00202.md", "sha256": "2e3f248c5393a4e17b060d48f73f553764a66f224d38a3aa29252a66dc0cc475" }, + "taskContext": { "path": "tests/golden/M16-GAP-00202/task-context.json", "sha256": "1a27a9755974d092a7c1a3599657e27f19ca2d56455836c6f99142547c0866b3" } + }, + "nextTask": "M16-GAP-00203" +} diff --git a/tests/golden/M16-GAP-00202/task-context.json b/tests/golden/M16-GAP-00202/task-context.json new file mode 100644 index 00000000..6aa29d6f --- /dev/null +++ b/tests/golden/M16-GAP-00202/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00202", + "parentTask": "M16-GAP-00201", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.replace_action data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.replace_action", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00202.py -- tests/files/web/generated/M16-GAP-00202-operator-anim.replace_action.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00202", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00202" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00202.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2355, + "contextRemainingTokens": 588 + }, + "source": { + "bytes": 7549, + "tokens": 1888 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00202.py", + "bytes": 1870, + "tokens": 468 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00202-operator-anim.replace_action.blend", + "bytes": 87690, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 231498, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 501183, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00202/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00202.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00202/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1870, + "tokens": 468 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00203", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00202.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00201/manifest.json", + "parentStatus": "docs/status/M16-GAP-00201.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00202.md", + "tests/golden/M16-GAP-00201/manifest.json", + "docs/status/M16-GAP-00201.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00201", + "parentTask": "M16-GAP-00200", + "status": "done", + "nextTask": "M16-GAP-00202", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00201 Status", + "status: done", + "task: anim.previewrange_set operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture uses the active Dope Sheet animation region and a deterministic border gesture to set the Scene preview range to `2..6` through `ANIM_OT_previewrange_set`.", + "- WASM/Main observes the same `previewRange` and frame bounds; no reader, protocol, or browser change was required.", + "evidence:" + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1784, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 446 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00202.md", + "bytes": 1784, + "lines": 38, + "tokens": 446 + }, + { + "path": "tests/golden/M16-GAP-00201/manifest.json", + "bytes": 2671, + "lines": 29, + "tokens": 668 + }, + { + "path": "docs/status/M16-GAP-00201.md", + "bytes": 926, + "lines": 19, + "tokens": 232 + } + ], + "sourceTokens": 1888, + "evidenceFiles": 1, + "evidenceBytes": 1870, + "evidenceTokens": 468, + "totalTokens": 2356, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3380, + "serializedContextTokens": 753, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00203/anim-replace-action-new-desktop-report.json b/tests/golden/M16-GAP-00203/anim-replace-action-new-desktop-report.json new file mode 100644 index 00000000..8b1ca2b4 --- /dev/null +++ b/tests/golden/M16-GAP-00203/anim-replace-action-new-desktop-report.json @@ -0,0 +1,104 @@ +{ + "after": { + "actions": { + "Action": 2, + "WebGapAnimReplaceNewOldAction": 1 + }, + "activeObject": "WebGapAnimReplaceNewOldA", + "objects": { + "WebGapAnimReplaceNewOldA": { + "channels": [], + "name": "Action" + }, + "WebGapAnimReplaceNewOldB": { + "channels": [], + "name": "Action" + } + } + }, + "before": { + "actions": { + "WebGapAnimReplaceNewOldAction": 3 + }, + "activeObject": "WebGapAnimReplaceNewOldA", + "objects": { + "WebGapAnimReplaceNewOldA": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"replace_target\"]", + "values": [ + 1.0, + 3.0, + 5.0 + ] + }, + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"replace_target\"]", + "values": [ + 2.0, + 4.0, + 6.0 + ] + } + ], + "name": "WebGapAnimReplaceNewOldAction" + }, + "WebGapAnimReplaceNewOldB": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"replace_target\"]", + "values": [ + 1.0, + 3.0, + 5.0 + ] + }, + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"replace_target\"]", + "values": [ + 2.0, + 4.0, + 6.0 + ] + } + ], + "name": "WebGapAnimReplaceNewOldAction" + } + } + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00203-operator-anim.replace_action_new.blend", + "fixtureSha256": "dd278ab743c34b61566c20e545b90e42bcfe641ecbb523550fcdacea188f12b4", + "mainMutation": "ACTION_REPLACED_WITH_NEW", + "newAction": "Action", + "operation": "ANIM_REPLACE_ACTION_NEW_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00203" +} diff --git a/tests/golden/M16-GAP-00203/anim-replace-action-new-local-exact-report.json b/tests/golden/M16-GAP-00203/anim-replace-action-new-local-exact-report.json new file mode 100644 index 00000000..b4a03034 --- /dev/null +++ b/tests/golden/M16-GAP-00203/anim-replace-action-new-local-exact-report.json @@ -0,0 +1,34 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00203", + "operation": "ANIM_REPLACE_ACTION_NEW_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00203-operator-anim.replace_action_new.blend", + "sha256": "dd278ab743c34b61566c20e545b90e42bcfe641ecbb523550fcdacea188f12b4" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00203/anim-replace-action-new-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "ACTION_REPLACED_WITH_NEW" + }, + "wasm": { + "status": "EXACT", + "replacedObjectIds": [ + "object:WebGapAnimReplaceNewOldA", + "object:WebGapAnimReplaceNewOldB" + ], + "newAction": "Action", + "newActionChannels": 0, + "oldActionUnlinked": "action:WebGapAnimReplaceNewOldAction:unlinked", + "oldActionChannels": 2, + "emptyActionVisibility": "NOT_EXPOSED_BY_SCENE_SNAPSHOT" + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00204" +} diff --git a/tests/golden/M16-GAP-00203/manifest.json b/tests/golden/M16-GAP-00203/manifest.json new file mode 100644 index 00000000..57e46e56 --- /dev/null +++ b/tests/golden/M16-GAP-00203/manifest.json @@ -0,0 +1,28 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00203", + "parentTask": "M16-GAP-00202", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_REPLACE_ACTION_NEW_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { "path": "tests/golden/M16-GAP-00202/manifest.json", "sha256": "8d3a4e0f3ff82b80f1cca0410e87999b324a817a8054ac322c8eea7e0ed7a81f" }, + "fixture": { "path": "tests/files/web/generated/M16-GAP-00203-operator-anim.replace_action_new.blend", "sha256": "dd278ab743c34b61566c20e545b90e42bcfe641ecbb523550fcdacea188f12b4" }, + "generator": { "path": "tools/web/generated/M16-GAP-00203.py", "sha256": "7da43b3e6d4774e5cd90ecbe51e6249a34778e58caec85945fbc9f3abfe83c4f" }, + "desktopChecker": { "path": "tools/web/check-action-replace-action-new-desktop.py", "sha256": "9920d9911715035ed99a9615df37e8cfdb70c3aa9b96f12fd5296c52047b0c64" }, + "webChecker": { "path": "tools/web/check-generated-gap.mjs", "sha256": "2c9f6d0ae72f175987aeb45bf3656207dee2742aa4213f656a5641d86992bfb7" }, + "reader": { "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "8824ba3dfb4090b85dc679a583d263b4bdb190a47978f72f3c11f6b565fdacaf" }, + "protocol": { "path": "web/protocol/editor-workflow.ts", "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" }, + "sceneIrProtocol": { "path": "web/protocol/scene-ir.ts", "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" }, + "wasm": { "path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" }, + "wasmPublic": { "path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" }, + "wasmJs": { "path": "web/app/src/vendor/blender/web_engine.js", "sha256": "9c831d0351ac9d0714cce3b1da748cba416ced3086e3c59595cf24ac4da459ed" }, + "desktopReport": { "path": "tests/golden/M16-GAP-00203/anim-replace-action-new-desktop-report.json", "sha256": "1017546d241a1e8b8f26c02bb392269a1325b18cbba90b1598f786250f13976a" }, + "webReport": { "path": "tests/golden/M16-GAP-00203/anim-replace-action-new-local-exact-report.json", "sha256": "d743947398ac1b4beca0f6cf86f676bf24d668488e1a9a575ec561d2445a1ed6" }, + "status": { "path": "docs/status/M16-GAP-00203.md", "sha256": "0504f0cc178ce3f7d3678d0170294f3fdc5c0c0ff40458a9891ef471e8bded96" }, + "taskContext": { "path": "tests/golden/M16-GAP-00203/task-context.json", "sha256": "772d0122a85d60e0f0ed73fb53f700a89d251e2f8581ca84b2ee01c7792e66ca" } + }, + "nextTask": "M16-GAP-00204" +} diff --git a/tests/golden/M16-GAP-00203/task-context.json b/tests/golden/M16-GAP-00203/task-context.json new file mode 100644 index 00000000..a6296313 --- /dev/null +++ b/tests/golden/M16-GAP-00203/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00203", + "parentTask": "M16-GAP-00202", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.replace_action_new data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.replace_action_new", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00203.py -- tests/files/web/generated/M16-GAP-00203-operator-anim.replace_action_new.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00203", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00203" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00203.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2146, + "contextRemainingTokens": 535 + }, + "source": { + "bytes": 7758, + "tokens": 1941 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00203.py", + "bytes": 1565, + "tokens": 392 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00203-operator-anim.replace_action_new.blend", + "bytes": 87267, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 231498, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 505156, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00203/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00203.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00203/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1565, + "tokens": 392 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00204", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00203.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00202/manifest.json", + "parentStatus": "docs/status/M16-GAP-00202.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00203.md", + "tests/golden/M16-GAP-00202/manifest.json", + "docs/status/M16-GAP-00202.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00202", + "parentTask": "M16-GAP-00201", + "status": "done", + "nextTask": "M16-GAP-00203", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00202 Status", + "status: done", + "task: anim.replace_action operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture has two objects using `WebGapAnimReplaceOldAction` and one object using `WebGapAnimReplaceNewAction`. Desktop calls `ANIM_OT_replace_action` with the explicit action session UIDs.", + "- All three object users switch to the new action; the old action remains unlinked with its original channels. WASM/Main exposes both the replaced users and preserved unlinked action without reader/protocol changes.", + "evidence:" + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1804, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 451 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00203.md", + "bytes": 1804, + "lines": 38, + "tokens": 451 + }, + { + "path": "tests/golden/M16-GAP-00202/manifest.json", + "bytes": 2661, + "lines": 29, + "tokens": 666 + }, + { + "path": "docs/status/M16-GAP-00202.md", + "bytes": 1125, + "lines": 19, + "tokens": 282 + } + ], + "sourceTokens": 1941, + "evidenceFiles": 1, + "evidenceBytes": 1565, + "evidenceTokens": 392, + "totalTokens": 2333, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3357, + "serializedContextTokens": 757, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00204/anim-scene-range-frame-desktop-report.json b/tests/golden/M16-GAP-00204/anim-scene-range-frame-desktop-report.json new file mode 100644 index 00000000..26e0dc49 --- /dev/null +++ b/tests/golden/M16-GAP-00204/anim-scene-range-frame-desktop-report.json @@ -0,0 +1,29 @@ +{ + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00204-operator-anim.scene_range_frame.blend", + "fixtureSha256": "aa332513c910b461ea53db9c6f8c6de2801c7b79bc84c083c366360aec2a36dd", + "mainMutation": "VIEW_FRAMED_TO_SCENE_RANGE", + "operation": "ANIM_SCENE_RANGE_FRAME_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00204", + "view": { + "areaType": "DOPESHEET_EDITOR", + "view2d": { + "cur": { + "xmax": 260.0, + "xmin": -9.0, + "ymax": 0.0, + "ymin": -381.0 + }, + "mask": { + "xmax": 1153, + "xmin": 0, + "ymax": 380, + "ymin": 0 + } + } + } +} diff --git a/tests/golden/M16-GAP-00204/anim-scene-range-frame-local-exact-report.json b/tests/golden/M16-GAP-00204/anim-scene-range-frame-local-exact-report.json new file mode 100644 index 00000000..fec8b80c --- /dev/null +++ b/tests/golden/M16-GAP-00204/anim-scene-range-frame-local-exact-report.json @@ -0,0 +1,40 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00204", + "operation": "ANIM_SCENE_RANGE_FRAME_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00204-operator-anim.scene_range_frame.blend", + "sha256": "aa332513c910b461ea53db9c6f8c6de2801c7b79bc84c083c366360aec2a36dd" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00204/anim-scene-range-frame-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "VIEW_FRAMED_TO_SCENE_RANGE" + }, + "wasm": { + "status": "EXACT", + "editor": "DOPE_SHEET", + "view2d": { + "cur": { + "xmax": 260, + "xmin": -9, + "ymax": 0, + "ymin": -381 + }, + "mask": { + "xmax": 1153, + "xmin": 0, + "ymax": 380, + "ymin": 0 + } + } + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00205" +} diff --git a/tests/golden/M16-GAP-00204/manifest.json b/tests/golden/M16-GAP-00204/manifest.json new file mode 100644 index 00000000..d1e7588a --- /dev/null +++ b/tests/golden/M16-GAP-00204/manifest.json @@ -0,0 +1,28 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00204", + "parentTask": "M16-GAP-00203", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_SCENE_RANGE_FRAME_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { "path": "tests/golden/M16-GAP-00203/manifest.json", "sha256": "8886ae22530f6a533b64a31216b703b34e86461c270ddbcd548a63839568df7f" }, + "fixture": { "path": "tests/files/web/generated/M16-GAP-00204-operator-anim.scene_range_frame.blend", "sha256": "aa332513c910b461ea53db9c6f8c6de2801c7b79bc84c083c366360aec2a36dd" }, + "generator": { "path": "tools/web/generated/M16-GAP-00204.py", "sha256": "bda30fc04f8985b0dbdce2e239ee7a05a12e9362ca162803b54154684844d226" }, + "desktopChecker": { "path": "tools/web/check-action-scene-range-frame-desktop.py", "sha256": "054bbc89615177ecd199f28b55910e6aadbe1b87d04056679810c549ffdd8c08" }, + "webChecker": { "path": "tools/web/check-generated-gap.mjs", "sha256": "b03480a07b5347d999442dd3b596645982cd18f48a19e758862485937e2fa21b" }, + "reader": { "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "8824ba3dfb4090b85dc679a583d263b4bdb190a47978f72f3c11f6b565fdacaf" }, + "protocol": { "path": "web/protocol/editor-workflow.ts", "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" }, + "sceneIrProtocol": { "path": "web/protocol/scene-ir.ts", "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" }, + "wasm": { "path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" }, + "wasmPublic": { "path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" }, + "wasmJs": { "path": "web/app/src/vendor/blender/web_engine.js", "sha256": "9c831d0351ac9d0714cce3b1da748cba416ced3086e3c59595cf24ac4da459ed" }, + "desktopReport": { "path": "tests/golden/M16-GAP-00204/anim-scene-range-frame-desktop-report.json", "sha256": "fd7943551bf6662d8cf43f623cdb966e7242b172eff8ca0f3bfee71c3b67dbed" }, + "webReport": { "path": "tests/golden/M16-GAP-00204/anim-scene-range-frame-local-exact-report.json", "sha256": "3195131f4c4cfa050656a4a301840d857f5eb65e2929aaa867d3b056d3fe631c" }, + "status": { "path": "docs/status/M16-GAP-00204.md", "sha256": "9f42dcc4c93fff48d9f1c739feb9df5f0000f18ef1a9ea11644207534cc3a9f8" }, + "taskContext": { "path": "tests/golden/M16-GAP-00204/task-context.json", "sha256": "5b90524611e783f9f9103ebc4d9504450edad0b471f9d86f62c2602c7c7d2edf" } + }, + "nextTask": "M16-GAP-00205" +} diff --git a/tests/golden/M16-GAP-00204/task-context.json b/tests/golden/M16-GAP-00204/task-context.json new file mode 100644 index 00000000..4c96d62c --- /dev/null +++ b/tests/golden/M16-GAP-00204/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00204", + "parentTask": "M16-GAP-00203", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.scene_range_frame data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.scene_range_frame", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00204.py -- tests/files/web/generated/M16-GAP-00204-operator-anim.scene_range_frame.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00204", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00204" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00204.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2153, + "contextRemainingTokens": 537 + }, + "source": { + "bytes": 7751, + "tokens": 1939 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00204.py", + "bytes": 1641, + "tokens": 411 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00204-operator-anim.scene_range_frame.blend", + "bytes": 85932, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 231498, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 508892, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00204/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00204.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00204/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1641, + "tokens": 411 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00205", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00204.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00203/manifest.json", + "parentStatus": "docs/status/M16-GAP-00203.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00204.md", + "tests/golden/M16-GAP-00203/manifest.json", + "docs/status/M16-GAP-00203.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00203", + "parentTask": "M16-GAP-00202", + "status": "done", + "nextTask": "M16-GAP-00204", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00203 Status", + "status: done", + "task: anim.replace_action_new operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture has two objects using `WebGapAnimReplaceNewOldAction`. Desktop runs `ANIM_OT_replace_action_new` with the old action session UID; Blender creates a new empty action and assigns it to both users.", + "- The old action remains unlinked with its original channels. WASM/Main preserves that visible old-action evidence; the empty replacement action is intentionally not exposed as an animation entry.", + "evidence:" + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1799, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 450 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00204.md", + "bytes": 1799, + "lines": 38, + "tokens": 450 + }, + { + "path": "tests/golden/M16-GAP-00203/manifest.json", + "bytes": 2681, + "lines": 29, + "tokens": 671 + }, + { + "path": "docs/status/M16-GAP-00203.md", + "bytes": 1103, + "lines": 19, + "tokens": 276 + } + ], + "sourceTokens": 1939, + "evidenceFiles": 1, + "evidenceBytes": 1641, + "evidenceTokens": 411, + "totalTokens": 2350, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3374, + "serializedContextTokens": 756, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00205/anim-separate-slots-desktop-report.json b/tests/golden/M16-GAP-00205/anim-separate-slots-desktop-report.json new file mode 100644 index 00000000..87539c8f --- /dev/null +++ b/tests/golden/M16-GAP-00205/anim-separate-slots-desktop-report.json @@ -0,0 +1,134 @@ +{ + "after": { + "actions": { + "WebGapAnimSeparateSlotsAction": 1, + "WebGapSeparateSlotAAction": 1, + "WebGapSeparateSlotBAction": 1 + }, + "activeObject": "WebGapAnimSeparateSlotA", + "objects": { + "WebGapAnimSeparateSlotA": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"separate_target\"]", + "values": [ + 1.0, + 3.0, + 5.0 + ] + } + ], + "name": "WebGapSeparateSlotAAction" + }, + "WebGapAnimSeparateSlotB": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"separate_target\"]", + "values": [ + 2.0, + 4.0, + 6.0 + ] + } + ], + "name": "WebGapSeparateSlotBAction" + } + } + }, + "before": { + "actions": { + "WebGapAnimSeparateSlotsAction": 3 + }, + "activeObject": "WebGapAnimSeparateSlotA", + "objects": { + "WebGapAnimSeparateSlotA": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"separate_target\"]", + "values": [ + 1.0, + 3.0, + 5.0 + ] + }, + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"separate_target\"]", + "values": [ + 2.0, + 4.0, + 6.0 + ] + } + ], + "name": "WebGapAnimSeparateSlotsAction" + }, + "WebGapAnimSeparateSlotB": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"separate_target\"]", + "values": [ + 1.0, + 3.0, + 5.0 + ] + }, + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"separate_target\"]", + "values": [ + 2.0, + 4.0, + 6.0 + ] + } + ], + "name": "WebGapAnimSeparateSlotsAction" + } + } + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00205-operator-anim.separate_slots.blend", + "fixtureSha256": "55c92c2622d2b532060fae13fc9fc035b8d936f21ff766b6b49938632140fd82", + "mainMutation": "SLOTS_SEPARATED", + "operation": "ANIM_SEPARATE_SLOTS_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00205" +} diff --git a/tests/golden/M16-GAP-00205/anim-separate-slots-local-exact-report.json b/tests/golden/M16-GAP-00205/anim-separate-slots-local-exact-report.json new file mode 100644 index 00000000..f19e2a2b --- /dev/null +++ b/tests/golden/M16-GAP-00205/anim-separate-slots-local-exact-report.json @@ -0,0 +1,38 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00205", + "operation": "ANIM_SEPARATE_SLOTS_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00205-operator-anim.separate_slots.blend", + "sha256": "55c92c2622d2b532060fae13fc9fc035b8d936f21ff766b6b49938632140fd82" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00205/anim-separate-slots-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "SLOTS_SEPARATED" + }, + "wasm": { + "status": "EXACT", + "actionIds": [ + "action:WebGapSeparateSlotAAction:object:WebGapAnimSeparateSlotA", + "action:WebGapSeparateSlotBAction:object:WebGapAnimSeparateSlotB" + ], + "actionNames": [ + "WebGapSeparateSlotAAction", + "WebGapSeparateSlotBAction" + ], + "channelsPerAction": [ + 1, + 1 + ], + "oldActionEmpty": true + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00206" +} diff --git a/tests/golden/M16-GAP-00205/manifest.json b/tests/golden/M16-GAP-00205/manifest.json new file mode 100644 index 00000000..7fdc6ee8 --- /dev/null +++ b/tests/golden/M16-GAP-00205/manifest.json @@ -0,0 +1,28 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00205", + "parentTask": "M16-GAP-00204", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_SEPARATE_SLOTS_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { "path": "tests/golden/M16-GAP-00204/manifest.json", "sha256": "e54672ac3af7043e794430deed2f26f434fbdc9ebfb3418a971297a321936447" }, + "fixture": { "path": "tests/files/web/generated/M16-GAP-00205-operator-anim.separate_slots.blend", "sha256": "55c92c2622d2b532060fae13fc9fc035b8d936f21ff766b6b49938632140fd82" }, + "generator": { "path": "tools/web/generated/M16-GAP-00205.py", "sha256": "54a5039afb72cbdd942e1b9c77cbbe5bb09a4380ebca186268dd676a357621eb" }, + "desktopChecker": { "path": "tools/web/check-action-separate-slots-desktop.py", "sha256": "4f1ea94c58a36b764cff6c40380794b927cd67212421aa36db8062b3817748a5" }, + "webChecker": { "path": "tools/web/check-generated-gap.mjs", "sha256": "d8e7a9896b9f020b74080782a41181c9842ead4523f092a83c8c144819b3a73b" }, + "reader": { "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "8824ba3dfb4090b85dc679a583d263b4bdb190a47978f72f3c11f6b565fdacaf" }, + "protocol": { "path": "web/protocol/editor-workflow.ts", "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" }, + "sceneIrProtocol": { "path": "web/protocol/scene-ir.ts", "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" }, + "wasm": { "path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" }, + "wasmPublic": { "path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" }, + "wasmJs": { "path": "web/app/src/vendor/blender/web_engine.js", "sha256": "9c831d0351ac9d0714cce3b1da748cba416ced3086e3c59595cf24ac4da459ed" }, + "desktopReport": { "path": "tests/golden/M16-GAP-00205/anim-separate-slots-desktop-report.json", "sha256": "d3976e54b5617745cd29ed3979a030553a6692a54d8cd59454593efac1e419be" }, + "webReport": { "path": "tests/golden/M16-GAP-00205/anim-separate-slots-local-exact-report.json", "sha256": "421feb4b3b822a8bb13999e268a42f3378408d4d725879d1e05c3c8efe359a84" }, + "status": { "path": "docs/status/M16-GAP-00205.md", "sha256": "504475606c2d54e38587d7880653c6328666b9731c29857dbc68d127a6249d71" }, + "taskContext": { "path": "tests/golden/M16-GAP-00205/task-context.json", "sha256": "744b861440cf850c81545c532cf78c6c946c2214f539d14da72d7e2fda23ff51" } + }, + "nextTask": "M16-GAP-00206" +} diff --git a/tests/golden/M16-GAP-00205/task-context.json b/tests/golden/M16-GAP-00205/task-context.json new file mode 100644 index 00000000..2b6dd53a --- /dev/null +++ b/tests/golden/M16-GAP-00205/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00205", + "parentTask": "M16-GAP-00204", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.separate_slots data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.separate_slots", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00205.py -- tests/files/web/generated/M16-GAP-00205-operator-anim.separate_slots.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00205", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00205" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00205.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2326, + "contextRemainingTokens": 581 + }, + "source": { + "bytes": 7578, + "tokens": 1895 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00205.py", + "bytes": 1754, + "tokens": 439 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00205-operator-anim.separate_slots.blend", + "bytes": 87353, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 231498, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 512854, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00205/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00205.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00205/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1754, + "tokens": 439 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00206", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00205.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00204/manifest.json", + "parentStatus": "docs/status/M16-GAP-00204.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00205.md", + "tests/golden/M16-GAP-00204/manifest.json", + "docs/status/M16-GAP-00204.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00204", + "parentTask": "M16-GAP-00203", + "status": "done", + "nextTask": "M16-GAP-00205", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00204 Status", + "status: done", + "task: anim.scene_range_frame operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture uses a Dope Sheet animation region with an active preview playback range. Desktop runs `ANIM_OT_scene_range_frame` and frames the region to that scene range.", + "- The resulting `view2d` state is observable in WASM/Main editor workflow data; no reader, protocol, or browser change was required.", + "evidence:" + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1784, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 446 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00205.md", + "bytes": 1784, + "lines": 38, + "tokens": 446 + }, + { + "path": "tests/golden/M16-GAP-00204/manifest.json", + "bytes": 2676, + "lines": 29, + "tokens": 669 + }, + { + "path": "docs/status/M16-GAP-00204.md", + "bytes": 950, + "lines": 19, + "tokens": 238 + } + ], + "sourceTokens": 1895, + "evidenceFiles": 1, + "evidenceBytes": 1754, + "evidenceTokens": 439, + "totalTokens": 2334, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3358, + "serializedContextTokens": 753, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00206/anim-slot-channels-move-desktop-report.json b/tests/golden/M16-GAP-00206/anim-slot-channels-move-desktop-report.json new file mode 100644 index 00000000..8d07d62d --- /dev/null +++ b/tests/golden/M16-GAP-00206/anim-slot-channels-move-desktop-report.json @@ -0,0 +1,133 @@ +{ + "after": { + "actions": { + "WebGapAnimMoveSlotAction": 2, + "WebGapMoveSlotAAction": 1 + }, + "activeObject": "WebGapAnimMoveSlotA", + "objects": { + "WebGapAnimMoveSlotA": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"move_target\"]", + "values": [ + 1.0, + 3.0, + 5.0 + ] + } + ], + "name": "WebGapMoveSlotAAction" + }, + "WebGapAnimMoveSlotB": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"move_target\"]", + "values": [ + 2.0, + 4.0, + 6.0 + ] + } + ], + "name": "WebGapAnimMoveSlotAction" + } + } + }, + "before": { + "actions": { + "WebGapAnimMoveSlotAction": 3 + }, + "activeObject": "WebGapAnimMoveSlotA", + "objects": { + "WebGapAnimMoveSlotA": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"move_target\"]", + "values": [ + 1.0, + 3.0, + 5.0 + ] + }, + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"move_target\"]", + "values": [ + 2.0, + 4.0, + 6.0 + ] + } + ], + "name": "WebGapAnimMoveSlotAction" + }, + "WebGapAnimMoveSlotB": { + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"move_target\"]", + "values": [ + 1.0, + 3.0, + 5.0 + ] + }, + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"move_target\"]", + "values": [ + 2.0, + 4.0, + 6.0 + ] + } + ], + "name": "WebGapAnimMoveSlotAction" + } + } + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00206-operator-anim.slot_channels_move_to_new_action.blend", + "fixtureSha256": "4dddfa7e19686d28ea2e6918bb7221943ea26a4ba8831d7fef0736ee8fd52534", + "mainMutation": "SLOT_MOVED_TO_NEW_ACTION", + "operation": "ANIM_SLOT_CHANNELS_MOVE_TO_NEW_ACTION_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00206" +} diff --git a/tests/golden/M16-GAP-00206/anim-slot-channels-move-local-exact-report.json b/tests/golden/M16-GAP-00206/anim-slot-channels-move-local-exact-report.json new file mode 100644 index 00000000..d0408804 --- /dev/null +++ b/tests/golden/M16-GAP-00206/anim-slot-channels-move-local-exact-report.json @@ -0,0 +1,29 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00206", + "operation": "ANIM_SLOT_CHANNELS_MOVE_TO_NEW_ACTION_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00206-operator-anim.slot_channels_move_to_new_action.blend", + "sha256": "4dddfa7e19686d28ea2e6918bb7221943ea26a4ba8831d7fef0736ee8fd52534" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00206/anim-slot-channels-move-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "SLOT_MOVED_TO_NEW_ACTION" + }, + "wasm": { + "status": "EXACT", + "movedActionId": "action:WebGapMoveSlotAAction:object:WebGapAnimMoveSlotA", + "remainingActionId": "action:WebGapAnimMoveSlotAction:object:WebGapAnimMoveSlotB", + "movedChannels": 1, + "remainingChannels": 1 + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00207" +} diff --git a/tests/golden/M16-GAP-00206/manifest.json b/tests/golden/M16-GAP-00206/manifest.json new file mode 100644 index 00000000..35350d7d --- /dev/null +++ b/tests/golden/M16-GAP-00206/manifest.json @@ -0,0 +1,28 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00206", + "parentTask": "M16-GAP-00205", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_SLOT_CHANNELS_MOVE_TO_NEW_ACTION_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { "path": "tests/golden/M16-GAP-00205/manifest.json", "sha256": "72cf9e1bf9457da4cad4b8fd91c121a8d6b50d8b9ce5199de816f60250c78d3e" }, + "fixture": { "path": "tests/files/web/generated/M16-GAP-00206-operator-anim.slot_channels_move_to_new_action.blend", "sha256": "4dddfa7e19686d28ea2e6918bb7221943ea26a4ba8831d7fef0736ee8fd52534" }, + "generator": { "path": "tools/web/generated/M16-GAP-00206.py", "sha256": "a0dda3e2468216bebc829cf9d64ff8b2124d243007bf466653df78aadb1e109a" }, + "desktopChecker": { "path": "tools/web/check-action-slot-channels-move-desktop.py", "sha256": "8625500da296a6eee287dbafb242da7178e9f101d171f8cc62ecf8baffe2b0d3" }, + "webChecker": { "path": "tools/web/check-generated-gap.mjs", "sha256": "5f25e2d50ac8dfe0854b5c424179b1cf0d496b0ee23a6e434ce623e4d98f912c" }, + "reader": { "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "8824ba3dfb4090b85dc679a583d263b4bdb190a47978f72f3c11f6b565fdacaf" }, + "protocol": { "path": "web/protocol/editor-workflow.ts", "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" }, + "sceneIrProtocol": { "path": "web/protocol/scene-ir.ts", "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" }, + "wasm": { "path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" }, + "wasmPublic": { "path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "3bcb7c5d1c3f85318febb9dfd8273ce141b5b38735d622ebb984d64c61059e0f" }, + "wasmJs": { "path": "web/app/src/vendor/blender/web_engine.js", "sha256": "9c831d0351ac9d0714cce3b1da748cba416ced3086e3c59595cf24ac4da459ed" }, + "desktopReport": { "path": "tests/golden/M16-GAP-00206/anim-slot-channels-move-desktop-report.json", "sha256": "17e021647d84852ea074b134a722de8dedeea70db3cf180fa60456892ebc86df" }, + "webReport": { "path": "tests/golden/M16-GAP-00206/anim-slot-channels-move-local-exact-report.json", "sha256": "4c92663dc8eb44d504ba95d4a978211656bd44273ff53cb468101f00ef20f8a3" }, + "status": { "path": "docs/status/M16-GAP-00206.md", "sha256": "28a15b08f7d20ec17fa242954206715e1b8a50bb7ae1391c9a187119aaf8be26" }, + "taskContext": { "path": "tests/golden/M16-GAP-00206/task-context.json", "sha256": "da58033c8325bdf4c16687776315ba7689c9a0d908f327dbabf98507699bbc3c" } + }, + "nextTask": "M16-GAP-00207" +} diff --git a/tests/golden/M16-GAP-00206/task-context.json b/tests/golden/M16-GAP-00206/task-context.json new file mode 100644 index 00000000..b5a573db --- /dev/null +++ b/tests/golden/M16-GAP-00206/task-context.json @@ -0,0 +1,182 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00206", + "parentTask": "M16-GAP-00205", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.slot_channels_move_to_new_action data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.slot_channels_move_to_new_action", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00206.py -- tests/files/web/generated/M16-GAP-00206-operator-anim.slot_channels_move_to_new_action.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00206", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00206" + ], + "inputPaths": [], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2188, + "contextRemainingTokens": 545 + }, + "source": { + "bytes": 7716, + "tokens": 1931 + }, + "selected": [], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00206-operator-anim.slot_channels_move_to_new_action.blend", + "bytes": 87458, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/generated/M16-GAP-00206.py", + "bytes": 2190, + "reason": "CONTEXT_REMAINING_SPACE" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 231498, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 516863, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00206/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00206.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00206/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 0, + "bytes": 0, + "tokens": 0 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00207", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00206.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00205/manifest.json", + "parentStatus": "docs/status/M16-GAP-00205.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00206.md", + "tests/golden/M16-GAP-00205/manifest.json", + "docs/status/M16-GAP-00205.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00205", + "parentTask": "M16-GAP-00204", + "status": "done", + "nextTask": "M16-GAP-00206", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00205 Status", + "status: done", + "task: anim.separate_slots operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture has two objects using separate slots in one layered action. Desktop runs `ANIM_OT_separate_slots` and creates one action per slot, reassigning the two objects.", + "- WASM/Main observes the two new action targets and their slot-specific channels; the original action is empty and omitted from the animation snapshot.", + "evidence:" + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1874, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 469 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00206.md", + "bytes": 1874, + "lines": 38, + "tokens": 469 + }, + { + "path": "tests/golden/M16-GAP-00205/manifest.json", + "bytes": 2661, + "lines": 29, + "tokens": 666 + }, + { + "path": "docs/status/M16-GAP-00205.md", + "bytes": 1013, + "lines": 19, + "tokens": 254 + } + ], + "sourceTokens": 1931, + "evidenceFiles": 0, + "evidenceBytes": 0, + "evidenceTokens": 0, + "totalTokens": 1931, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 2955, + "serializedContextTokens": 732, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00207/anim-slot-new-for-id-desktop-report.json b/tests/golden/M16-GAP-00207/anim-slot-new-for-id-desktop-report.json new file mode 100644 index 00000000..85df187e --- /dev/null +++ b/tests/golden/M16-GAP-00207/anim-slot-new-for-id-desktop-report.json @@ -0,0 +1,75 @@ +{ + "after": { + "action": "WebGapAnimNewSlotAction", + "activeObject": "WebGapAnimNewSlotObject", + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"new_slot_target\"]", + "values": [ + 1.0, + 3.0, + 5.0 + ] + }, + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"new_slot_target\"]", + "values": [ + 1.0, + 3.0, + 5.0 + ] + } + ], + "slot": "OBWebGapAnimNewSlot.001", + "slots": [ + "OBWebGapAnimNewSlot", + "OBWebGapAnimNewSlot.001" + ] + }, + "before": { + "action": "WebGapAnimNewSlotAction", + "activeObject": "WebGapAnimNewSlotObject", + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"new_slot_target\"]", + "values": [ + 1.0, + 3.0, + 5.0 + ] + } + ], + "slot": "OBWebGapAnimNewSlot", + "slots": [ + "OBWebGapAnimNewSlot" + ] + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00207-operator-anim.slot_new_for_id.blend", + "fixtureSha256": "55feef5fa86ba311964057b6fa5b24b5362fa7c2fc9ab061736c4fec6927a532", + "mainMutation": "SLOT_DUPLICATED", + "operation": "ANIM_SLOT_NEW_FOR_ID_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00207" +} diff --git a/tests/golden/M16-GAP-00207/anim-slot-new-for-id-local-exact-report.json b/tests/golden/M16-GAP-00207/anim-slot-new-for-id-local-exact-report.json new file mode 100644 index 00000000..b04d0733 --- /dev/null +++ b/tests/golden/M16-GAP-00207/anim-slot-new-for-id-local-exact-report.json @@ -0,0 +1,29 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00207", + "operation": "ANIM_SLOT_NEW_FOR_ID_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00207-operator-anim.slot_new_for_id.blend", + "sha256": "55feef5fa86ba311964057b6fa5b24b5362fa7c2fc9ab061736c4fec6927a532" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00207/anim-slot-new-for-id-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "SLOT_DUPLICATED" + }, + "wasm": { + "status": "EXACT", + "animationId": "action:WebGapAnimNewSlotAction:object:WebGapAnimNewSlotObject", + "slotIdentifier": "OBWebGapAnimNewSlot.001", + "slotCount": 2, + "channels": 1 + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00208" +} diff --git a/tests/golden/M16-GAP-00207/manifest.json b/tests/golden/M16-GAP-00207/manifest.json new file mode 100644 index 00000000..fc95c99f --- /dev/null +++ b/tests/golden/M16-GAP-00207/manifest.json @@ -0,0 +1,29 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00207", + "parentTask": "M16-GAP-00206", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_SLOT_NEW_FOR_ID_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { "path": "tests/golden/M16-GAP-00206/manifest.json", "sha256": "3b1207f1c3db50bcd1efdfd40f21cdbf99323288fd984a9da172f4525df31a9a" }, + "fixture": { "path": "tests/files/web/generated/M16-GAP-00207-operator-anim.slot_new_for_id.blend", "sha256": "55feef5fa86ba311964057b6fa5b24b5362fa7c2fc9ab061736c4fec6927a532" }, + "generator": { "path": "tools/web/generated/M16-GAP-00207.py", "sha256": "6c664ddeab1eb7cbe143c2c23ece749225b7f70a641590922af6a76fd61d44eb" }, + "desktopChecker": { "path": "tools/web/check-action-slot-new-for-id-desktop.py", "sha256": "76c3ed3a2046d4c5befa9f761ba020bf37859f5758a11f874e688d91bbcbc7e3" }, + "webChecker": { "path": "tools/web/check-generated-gap.mjs", "sha256": "36340873cc26d938df455c8aeb4a831877276135a093f8c5582f0a41cf050ae2" }, + "reader": { "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "ace99ea00f5e807cc098e19cc4447017bb5744431516066a65c8f38047c4a7e8" }, + "protocol": { "path": "web/protocol/editor-workflow.ts", "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" }, + "sceneIrProtocol": { "path": "web/protocol/scene-ir.ts", "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" }, + "wasm": { "path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "7716160bb7781f60e272b49bc071c263487ad9b21dc87d4f44bf3f94171bdfb6" }, + "wasmPublic": { "path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "7716160bb7781f60e272b49bc071c263487ad9b21dc87d4f44bf3f94171bdfb6" }, + "wasmJs": { "path": "web/app/src/vendor/blender/web_engine.js", "sha256": "5df580ac02c5d8806ffe858b31cccec7692222813d17e4ffdbee207bf346bcb1" }, + "wasmJsPublic": { "path": "web/app/public/vendor/blender/web_engine.js", "sha256": "5df580ac02c5d8806ffe858b31cccec7692222813d17e4ffdbee207bf346bcb1" }, + "desktopReport": { "path": "tests/golden/M16-GAP-00207/anim-slot-new-for-id-desktop-report.json", "sha256": "62998821fb29ec9edb1c2796f984e009091cb9d12ccca4ec058094aea695a6f3" }, + "webReport": { "path": "tests/golden/M16-GAP-00207/anim-slot-new-for-id-local-exact-report.json", "sha256": "2c843b2611ac386e68943adb36fc826dcb694c8fb30df9b0abf10f8970b4f4fc" }, + "status": { "path": "docs/status/M16-GAP-00207.md", "sha256": "6cb10e433730afa5fea28840824d849c492461f4b5b9350a41d5a0f995d4f504" }, + "taskContext": { "path": "tests/golden/M16-GAP-00207/task-context.json", "sha256": "37746bd730e6642f8a2ca14fe36b590977c2a409cf0df23e338ef43d7a22fd13" } + }, + "nextTask": "M16-GAP-00208" +} diff --git a/tests/golden/M16-GAP-00207/task-context.json b/tests/golden/M16-GAP-00207/task-context.json new file mode 100644 index 00000000..e51c3207 --- /dev/null +++ b/tests/golden/M16-GAP-00207/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00207", + "parentTask": "M16-GAP-00206", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.slot_new_for_id data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.slot_new_for_id", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00207.py -- tests/files/web/generated/M16-GAP-00207-operator-anim.slot_new_for_id.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00207", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00207" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00207.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2161, + "contextRemainingTokens": 538 + }, + "source": { + "bytes": 7743, + "tokens": 1938 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00207.py", + "bytes": 1491, + "tokens": 373 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00207-operator-anim.slot_new_for_id.blend", + "bytes": 86860, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 233233, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 520799, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00207/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00207.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00207/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1491, + "tokens": 373 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00208", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00207.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00206/manifest.json", + "parentStatus": "docs/status/M16-GAP-00206.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00207.md", + "tests/golden/M16-GAP-00206/manifest.json", + "docs/status/M16-GAP-00206.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00206", + "parentTask": "M16-GAP-00205", + "status": "done", + "nextTask": "M16-GAP-00207", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00206 Status", + "status: done", + "task: anim.slot_channels_move_to_new_action operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture has two objects using separate slots in one action. Desktop selects one Action Slot in the Action Editor and runs `ANIM_OT_slot_channels_move_to_new_action`.", + "- The selected slot moves to `WebGapMoveSlotAAction`; the other object remains on the original action. WASM/Main observes both resulting action targets without reader/protocol changes.", + "evidence:" + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1789, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 448 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00207.md", + "bytes": 1789, + "lines": 38, + "tokens": 448 + }, + { + "path": "tests/golden/M16-GAP-00206/manifest.json", + "bytes": 2709, + "lines": 29, + "tokens": 678 + }, + { + "path": "docs/status/M16-GAP-00206.md", + "bytes": 1077, + "lines": 19, + "tokens": 270 + } + ], + "sourceTokens": 1938, + "evidenceFiles": 1, + "evidenceBytes": 1491, + "evidenceTokens": 373, + "totalTokens": 2311, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3335, + "serializedContextTokens": 754, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00208/anim-slot-unassign-from-constraint-desktop-report.json b/tests/golden/M16-GAP-00208/anim-slot-unassign-from-constraint-desktop-report.json new file mode 100644 index 00000000..b2eb4804 --- /dev/null +++ b/tests/golden/M16-GAP-00208/anim-slot-unassign-from-constraint-desktop-report.json @@ -0,0 +1,26 @@ +{ + "after": { + "action": "WebGapAnimConstraintSlotAction", + "actionSlot": null, + "actionSlotHandle": 0, + "activeObject": "WebGapAnimConstraintSlotObject", + "constraint": "WebGapActionSlotConstraint" + }, + "before": { + "action": "WebGapAnimConstraintSlotAction", + "actionSlot": "OBWebGapConstraintSlot", + "actionSlotHandle": 929201142, + "activeObject": "WebGapAnimConstraintSlotObject", + "constraint": "WebGapActionSlotConstraint" + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00208-operator-anim.slot_unassign_from_constraint.blend", + "fixtureSha256": "517bba0bc6e4dfab4eeafc9d902de560b76360718789a06a6417d9e9f8be7df9", + "mainMutation": "CONSTRAINT_SLOT_UNASSIGNED", + "operation": "ANIM_SLOT_UNASSIGN_FROM_CONSTRAINT_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00208" +} diff --git a/tests/golden/M16-GAP-00208/anim-slot-unassign-from-constraint-local-exact-report.json b/tests/golden/M16-GAP-00208/anim-slot-unassign-from-constraint-local-exact-report.json new file mode 100644 index 00000000..75ff9568 --- /dev/null +++ b/tests/golden/M16-GAP-00208/anim-slot-unassign-from-constraint-local-exact-report.json @@ -0,0 +1,31 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00208", + "operation": "ANIM_SLOT_UNASSIGN_FROM_CONSTRAINT_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00208-operator-anim.slot_unassign_from_constraint.blend", + "sha256": "517bba0bc6e4dfab4eeafc9d902de560b76360718789a06a6417d9e9f8be7df9" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00208/anim-slot-unassign-from-constraint-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "CONSTRAINT_SLOT_UNASSIGNED" + }, + "wasm": { + "status": "EXACT", + "objectId": "object:WebGapAnimConstraintSlotObject", + "constraintName": "WebGapActionSlotConstraint", + "actionId": "action:WebGapAnimConstraintSlotAction", + "actionSlotIdentifier": "OBWebGapConstraintSlot", + "actionSlotHandle": 0, + "actionSlotAssigned": false + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00209" +} diff --git a/tests/golden/M16-GAP-00208/manifest.json b/tests/golden/M16-GAP-00208/manifest.json new file mode 100644 index 00000000..4a43bafd --- /dev/null +++ b/tests/golden/M16-GAP-00208/manifest.json @@ -0,0 +1,29 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00208", + "parentTask": "M16-GAP-00207", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_SLOT_UNASSIGN_FROM_CONSTRAINT_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { "path": "tests/golden/M16-GAP-00207/manifest.json", "sha256": "d6aa11be23f7a4657161e6a8b9794a2c797880cb5ec598aad588bd5cb5f5e2e5" }, + "fixture": { "path": "tests/files/web/generated/M16-GAP-00208-operator-anim.slot_unassign_from_constraint.blend", "sha256": "517bba0bc6e4dfab4eeafc9d902de560b76360718789a06a6417d9e9f8be7df9" }, + "generator": { "path": "tools/web/generated/M16-GAP-00208.py", "sha256": "47a3962e2c07fc2cef07570c671001c612ece290ed811bc4317143391e99a82d" }, + "desktopChecker": { "path": "tools/web/check-action-slot-unassign-from-constraint-desktop.py", "sha256": "89120dd2da7f4c7f24fb12af02ce94d5929002e0d87cad765c8828999c74afdb" }, + "webChecker": { "path": "tools/web/check-generated-gap.mjs", "sha256": "08cad39c3769c819d5409c58aa666203fcb120bfae5f2d519918fc1a0f0c07e2" }, + "reader": { "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "ccb609241fd6ac86f99e68b0487c92100ddea54e801db3a3cf35aa75719ce8f9" }, + "protocol": { "path": "web/protocol/editor-workflow.ts", "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" }, + "sceneIrProtocol": { "path": "web/protocol/scene-ir.ts", "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" }, + "wasm": { "path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "480b288de461a63807bbb0fff6d36f7a984506b0f8b897682739d7bd9854e0d5" }, + "wasmPublic": { "path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "480b288de461a63807bbb0fff6d36f7a984506b0f8b897682739d7bd9854e0d5" }, + "wasmJs": { "path": "web/app/src/vendor/blender/web_engine.js", "sha256": "5df580ac02c5d8806ffe858b31cccec7692222813d17e4ffdbee207bf346bcb1" }, + "wasmJsPublic": { "path": "web/app/public/vendor/blender/web_engine.js", "sha256": "5df580ac02c5d8806ffe858b31cccec7692222813d17e4ffdbee207bf346bcb1" }, + "desktopReport": { "path": "tests/golden/M16-GAP-00208/anim-slot-unassign-from-constraint-desktop-report.json", "sha256": "a303a5e1060fde95fbaaa0cf6e759cb4af330cf233b65ae1462953960fca51cd" }, + "webReport": { "path": "tests/golden/M16-GAP-00208/anim-slot-unassign-from-constraint-local-exact-report.json", "sha256": "cc7a531c48dc232d822ae6ffcc19f459d44d02976eb3b2f04133435d7a98b158" }, + "status": { "path": "docs/status/M16-GAP-00208.md", "sha256": "957439dbc9be432dbb8187be6e3b2f12a27665e4e344a87897d51008380e7bee" }, + "taskContext": { "path": "tests/golden/M16-GAP-00208/task-context.json", "sha256": "d5bd4bdecaafbb137b89769a001b6e966e47d31059bce66b524384ea3e8a0a01" } + }, + "nextTask": "M16-GAP-00209" +} diff --git a/tests/golden/M16-GAP-00208/task-context.json b/tests/golden/M16-GAP-00208/task-context.json new file mode 100644 index 00000000..29580053 --- /dev/null +++ b/tests/golden/M16-GAP-00208/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00208", + "parentTask": "M16-GAP-00207", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.slot_unassign_from_constraint data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.slot_unassign_from_constraint", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00208.py -- tests/files/web/generated/M16-GAP-00208-operator-anim.slot_unassign_from_constraint.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00208", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00208" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00208.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1968, + "contextRemainingTokens": 491 + }, + "source": { + "bytes": 7936, + "tokens": 1985 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00208.py", + "bytes": 1455, + "tokens": 364 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00208-operator-anim.slot_unassign_from_constraint.blend", + "bytes": 86531, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 234565, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 524982, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00208/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00208.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00208/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1455, + "tokens": 364 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00209", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00208.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00207/manifest.json", + "parentStatus": "docs/status/M16-GAP-00207.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00208.md", + "tests/golden/M16-GAP-00207/manifest.json", + "docs/status/M16-GAP-00207.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00207", + "parentTask": "M16-GAP-00206", + "status": "done", + "nextTask": "M16-GAP-00208", + "artifactCount": 16 + }, + "statusSummary": [ + "# M16-GAP-00207 Status", + "status: done", + "task: anim.slot_new_for_id operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture assigns one Action Slot to `WebGapAnimNewSlotObject`; desktop runs `ANIM_OT_slot_new_for_id` with the animated ID context and duplicates the slot and channelbag.", + "- The WASM/Main reader now selects the assigned `AnimData.slot_handle` channelbag and exposes `slotIdentifier` and `slotCount` on the animation snapshot. The duplicated slot remains stable across save/reopen.", + "evidence:" + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1859, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 465 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00208.md", + "bytes": 1859, + "lines": 38, + "tokens": 465 + }, + { + "path": "tests/golden/M16-GAP-00207/manifest.json", + "bytes": 2823, + "lines": 30, + "tokens": 706 + }, + { + "path": "docs/status/M16-GAP-00207.md", + "bytes": 1086, + "lines": 19, + "tokens": 272 + } + ], + "sourceTokens": 1985, + "evidenceFiles": 1, + "evidenceBytes": 1455, + "evidenceTokens": 364, + "totalTokens": 2349, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3373, + "serializedContextTokens": 765, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00209/anim-slot-unassign-from-id-desktop-report.json b/tests/golden/M16-GAP-00209/anim-slot-unassign-from-id-desktop-report.json new file mode 100644 index 00000000..dc210578 --- /dev/null +++ b/tests/golden/M16-GAP-00209/anim-slot-unassign-from-id-desktop-report.json @@ -0,0 +1,58 @@ +{ + "after": { + "action": "WebGapAnimUnassignIdAction", + "actionSlot": null, + "actionSlotHandle": 0, + "activeObject": "WebGapAnimUnassignIdObject", + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"unassign_id_target\"]", + "values": [ + 1.0, + 3.0, + 5.0 + ] + } + ], + "lastSlotIdentifier": "OBWebGapUnassignIdSlot" + }, + "before": { + "action": "WebGapAnimUnassignIdAction", + "actionSlot": "OBWebGapUnassignIdSlot", + "actionSlotHandle": 929201142, + "activeObject": "WebGapAnimUnassignIdObject", + "channels": [ + { + "frames": [ + 1.0, + 3.0, + 5.0 + ], + "index": 0, + "path": "[\"unassign_id_target\"]", + "values": [ + 1.0, + 3.0, + 5.0 + ] + } + ], + "lastSlotIdentifier": "OBWebGapUnassignIdSlot" + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00209-operator-anim.slot_unassign_from_id.blend", + "fixtureSha256": "69fb5253dfd28f45ea25f29947d08afb4513e222105b4b8bc94a5b6be05b7238", + "mainMutation": "ID_SLOT_UNASSIGNED", + "operation": "ANIM_SLOT_UNASSIGN_FROM_ID_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00209" +} diff --git a/tests/golden/M16-GAP-00209/anim-slot-unassign-from-id-local-exact-report.json b/tests/golden/M16-GAP-00209/anim-slot-unassign-from-id-local-exact-report.json new file mode 100644 index 00000000..80216a48 --- /dev/null +++ b/tests/golden/M16-GAP-00209/anim-slot-unassign-from-id-local-exact-report.json @@ -0,0 +1,31 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00209", + "operation": "ANIM_SLOT_UNASSIGN_FROM_ID_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00209-operator-anim.slot_unassign_from_id.blend", + "sha256": "69fb5253dfd28f45ea25f29947d08afb4513e222105b4b8bc94a5b6be05b7238" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00209/anim-slot-unassign-from-id-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "ID_SLOT_UNASSIGNED" + }, + "wasm": { + "status": "EXACT", + "animationId": "action:WebGapAnimUnassignIdAction:object:WebGapAnimUnassignIdObject", + "slotIdentifier": "OBWebGapUnassignIdSlot", + "slotHandle": 0, + "slotAssigned": false, + "slotCount": 1, + "channels": 1 + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00210" +} diff --git a/tests/golden/M16-GAP-00209/manifest.json b/tests/golden/M16-GAP-00209/manifest.json new file mode 100644 index 00000000..4c8dd673 --- /dev/null +++ b/tests/golden/M16-GAP-00209/manifest.json @@ -0,0 +1,29 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00209", + "parentTask": "M16-GAP-00208", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_SLOT_UNASSIGN_FROM_ID_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { "path": "tests/golden/M16-GAP-00208/manifest.json", "sha256": "06fac2d9fbe04f6308ce39377fd1360890604bd26d30939339dc42e86035cd55" }, + "fixture": { "path": "tests/files/web/generated/M16-GAP-00209-operator-anim.slot_unassign_from_id.blend", "sha256": "69fb5253dfd28f45ea25f29947d08afb4513e222105b4b8bc94a5b6be05b7238" }, + "generator": { "path": "tools/web/generated/M16-GAP-00209.py", "sha256": "45e9b34637496caa72e521214539d9ef60646191e90dbed5bcd76c3fa7366701" }, + "desktopChecker": { "path": "tools/web/check-action-slot-unassign-from-id-desktop.py", "sha256": "3166defd69de7fb19a52c7b9646df52da9efb330c27037e77c4d34f92c6b43f5" }, + "webChecker": { "path": "tools/web/check-generated-gap.mjs", "sha256": "bd7f77cde032ee873ddf5ebb39b20b748067e0352bdb7a682011a4017574a7e6" }, + "reader": { "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "eede4160a817ce6ef82f14035a4a0f00c381acdbd150474d6e71c2c75d7f15c5" }, + "protocol": { "path": "web/protocol/editor-workflow.ts", "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" }, + "sceneIrProtocol": { "path": "web/protocol/scene-ir.ts", "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" }, + "wasm": { "path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "68cf2a8fb0158c4375c68d8ca9f98b04fcb8acf5f109cf63c81a551ec5c96c3f" }, + "wasmPublic": { "path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "68cf2a8fb0158c4375c68d8ca9f98b04fcb8acf5f109cf63c81a551ec5c96c3f" }, + "wasmJs": { "path": "web/app/src/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" }, + "wasmJsPublic": { "path": "web/app/public/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" }, + "desktopReport": { "path": "tests/golden/M16-GAP-00209/anim-slot-unassign-from-id-desktop-report.json", "sha256": "12d1d6492c6d682a519045cc840c0e8f8b212b9eca9f0bdfa15536dc4602f17f" }, + "webReport": { "path": "tests/golden/M16-GAP-00209/anim-slot-unassign-from-id-local-exact-report.json", "sha256": "e42355c5cd82a7b06e5560312869fec9eed33ba7db613668c7920b3363901122" }, + "status": { "path": "docs/status/M16-GAP-00209.md", "sha256": "9c436780681f0309420bd6c3e9def7e970e483175b4183e691320d5dd73cc108" }, + "taskContext": { "path": "tests/golden/M16-GAP-00209/task-context.json", "sha256": "c6c9e58a950aee3230dc6a2a04f1ec5b8273caf2a4cf34cf86006193eaf4f78e" } + }, + "nextTask": "M16-GAP-00210" +} diff --git a/tests/golden/M16-GAP-00209/task-context.json b/tests/golden/M16-GAP-00209/task-context.json new file mode 100644 index 00000000..58a3fec5 --- /dev/null +++ b/tests/golden/M16-GAP-00209/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00209", + "parentTask": "M16-GAP-00208", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.slot_unassign_from_id data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.slot_unassign_from_id", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00209.py -- tests/files/web/generated/M16-GAP-00209-operator-anim.slot_unassign_from_id.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00209", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00209" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00209.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1890, + "contextRemainingTokens": 471 + }, + "source": { + "bytes": 8014, + "tokens": 2005 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00209.py", + "bytes": 1506, + "tokens": 377 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00209-operator-anim.slot_unassign_from_id.blend", + "bytes": 86803, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 234900, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 529212, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00209/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00209.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00209/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1506, + "tokens": 377 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00210", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00209.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00208/manifest.json", + "parentStatus": "docs/status/M16-GAP-00208.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00209.md", + "tests/golden/M16-GAP-00208/manifest.json", + "docs/status/M16-GAP-00208.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00208", + "parentTask": "M16-GAP-00207", + "status": "done", + "nextTask": "M16-GAP-00209", + "artifactCount": 16 + }, + "statusSummary": [ + "# M16-GAP-00208 Status", + "status: done", + "task: anim.slot_unassign_from_constraint operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture gives `WebGapAnimConstraintSlotObject` an Action constraint with `WebGapAnimConstraintSlotAction` and one assigned `OBWebGapConstraintSlot`.", + "- Desktop runs `ANIM_OT_slot_unassign_from_constraint` with the constraint context pointer. The reader exposes the constraint's action, slot identifier, handle, and assigned state in the node snapshot.", + "evidence:" + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1819, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 455 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00209.md", + "bytes": 1819, + "lines": 38, + "tokens": 455 + }, + { + "path": "tests/golden/M16-GAP-00208/manifest.json", + "bytes": 2893, + "lines": 30, + "tokens": 724 + }, + { + "path": "docs/status/M16-GAP-00208.md", + "bytes": 1134, + "lines": 19, + "tokens": 284 + } + ], + "sourceTokens": 2005, + "evidenceFiles": 1, + "evidenceBytes": 1506, + "evidenceTokens": 377, + "totalTokens": 2382, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3406, + "serializedContextTokens": 759, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00210/anim-slot-unassign-from-nla-strip-desktop-report.json b/tests/golden/M16-GAP-00210/anim-slot-unassign-from-nla-strip-desktop-report.json new file mode 100644 index 00000000..35991295 --- /dev/null +++ b/tests/golden/M16-GAP-00210/anim-slot-unassign-from-nla-strip-desktop-report.json @@ -0,0 +1,32 @@ +{ + "after": { + "action": "WebGapAnimNlaSlotAction", + "actionSlot": null, + "actionSlotHandle": 0, + "activeObject": "WebGapAnimNlaSlotObject", + "frameEnd": 5.0, + "frameStart": 1.0, + "lastSlotIdentifier": "OBWebGapNlaSlot", + "strip": "WebGapNlaSlotStrip" + }, + "before": { + "action": "WebGapAnimNlaSlotAction", + "actionSlot": "OBWebGapNlaSlot", + "actionSlotHandle": 929201142, + "activeObject": "WebGapAnimNlaSlotObject", + "frameEnd": 5.0, + "frameStart": 1.0, + "lastSlotIdentifier": "OBWebGapNlaSlot", + "strip": "WebGapNlaSlotStrip" + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00210-operator-anim.slot_unassign_from_nla_strip.blend", + "fixtureSha256": "4740a95b74bf2d4f71af7019158ee116643bf6cb315ff6a31717fb6894c3f2e5", + "mainMutation": "NLA_SLOT_UNASSIGNED", + "operation": "ANIM_SLOT_UNASSIGN_FROM_NLA_STRIP_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00210" +} diff --git a/tests/golden/M16-GAP-00210/anim-slot-unassign-from-nla-strip-local-exact-report.json b/tests/golden/M16-GAP-00210/anim-slot-unassign-from-nla-strip-local-exact-report.json new file mode 100644 index 00000000..233b5c24 --- /dev/null +++ b/tests/golden/M16-GAP-00210/anim-slot-unassign-from-nla-strip-local-exact-report.json @@ -0,0 +1,31 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00210", + "operation": "ANIM_SLOT_UNASSIGN_FROM_NLA_STRIP_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00210-operator-anim.slot_unassign_from_nla_strip.blend", + "sha256": "4740a95b74bf2d4f71af7019158ee116643bf6cb315ff6a31717fb6894c3f2e5" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00210/anim-slot-unassign-from-nla-strip-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "NLA_SLOT_UNASSIGNED" + }, + "wasm": { + "status": "EXACT", + "trackId": "nla-track:object:WebGapAnimNlaSlotObject:0", + "stripId": "WebGapNlaSlotStrip", + "actionId": "action:WebGapAnimNlaSlotAction:object:WebGapAnimNlaSlotObject", + "actionSlotIdentifier": "OBWebGapNlaSlot", + "actionSlotHandle": 0, + "actionSlotAssigned": false + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00211" +} diff --git a/tests/golden/M16-GAP-00210/manifest.json b/tests/golden/M16-GAP-00210/manifest.json new file mode 100644 index 00000000..62857d13 --- /dev/null +++ b/tests/golden/M16-GAP-00210/manifest.json @@ -0,0 +1,29 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00210", + "parentTask": "M16-GAP-00209", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_SLOT_UNASSIGN_FROM_NLA_STRIP_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { "path": "tests/golden/M16-GAP-00209/manifest.json", "sha256": "1dc0a49c9b7eafeb7a12725c5dabe99e475c6f8b1ce46458d0088f88f8ad8768" }, + "fixture": { "path": "tests/files/web/generated/M16-GAP-00210-operator-anim.slot_unassign_from_nla_strip.blend", "sha256": "4740a95b74bf2d4f71af7019158ee116643bf6cb315ff6a31717fb6894c3f2e5" }, + "generator": { "path": "tools/web/generated/M16-GAP-00210.py", "sha256": "82ae2a1e60b7a8f1adfa9fd0451dda47daabba420bc658177172fe3080aaadd1" }, + "desktopChecker": { "path": "tools/web/check-action-slot-unassign-from-nla-strip-desktop.py", "sha256": "dadd0204062fb1bb54de6b2cf998e4313ed7dee32b201467ef3327200ba04685" }, + "webChecker": { "path": "tools/web/check-generated-gap.mjs", "sha256": "a3e43ec395826f4448b48fc3af752f1a58dc58955c4b4570a6f4b6512ada22a3" }, + "reader": { "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "774069a85bf5c59e4bac7be4318db36cf1684e925b783505dbf03dfe2abcbe43" }, + "protocol": { "path": "web/protocol/editor-workflow.ts", "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" }, + "sceneIrProtocol": { "path": "web/protocol/scene-ir.ts", "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" }, + "wasm": { "path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "e57225849e65c6f56206efc67bdc7aaf1bf695205336f7d0eff9b880ece37732" }, + "wasmPublic": { "path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "e57225849e65c6f56206efc67bdc7aaf1bf695205336f7d0eff9b880ece37732" }, + "wasmJs": { "path": "web/app/src/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" }, + "wasmJsPublic": { "path": "web/app/public/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" }, + "desktopReport": { "path": "tests/golden/M16-GAP-00210/anim-slot-unassign-from-nla-strip-desktop-report.json", "sha256": "35c89ff2c01b3887949572d83f27665b76eee49c5486e40b2c1b9e649916c9a2" }, + "webReport": { "path": "tests/golden/M16-GAP-00210/anim-slot-unassign-from-nla-strip-local-exact-report.json", "sha256": "d83b48f105f430cb7bbc2151b837fa589944a7c8d36a6156269ce4552aea5d41" }, + "status": { "path": "docs/status/M16-GAP-00210.md", "sha256": "1a2fb7129a562a6ca35ae61159d1cf28c3069be6a121d738d4b621138033e8ab" }, + "taskContext": { "path": "tests/golden/M16-GAP-00210/task-context.json", "sha256": "8d6bebc0df33dd02879078f9d824883255a290c2d9b72609bbecf689e3b49c66" } + }, + "nextTask": "M16-GAP-00211" +} diff --git a/tests/golden/M16-GAP-00210/task-context.json b/tests/golden/M16-GAP-00210/task-context.json new file mode 100644 index 00000000..e955a6ec --- /dev/null +++ b/tests/golden/M16-GAP-00210/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00210", + "parentTask": "M16-GAP-00209", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.slot_unassign_from_nla_strip data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.slot_unassign_from_nla_strip", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00210.py -- tests/files/web/generated/M16-GAP-00210-operator-anim.slot_unassign_from_nla_strip.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00210", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00210" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00210.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1921, + "contextRemainingTokens": 479 + }, + "source": { + "bytes": 7983, + "tokens": 1997 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00210.py", + "bytes": 1712, + "tokens": 428 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00210-operator-anim.slot_unassign_from_nla_strip.blend", + "bytes": 86885, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 235316, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 533375, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00210/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00210.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00210/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1712, + "tokens": 428 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00211", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00210.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00209/manifest.json", + "parentStatus": "docs/status/M16-GAP-00209.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00210.md", + "tests/golden/M16-GAP-00209/manifest.json", + "docs/status/M16-GAP-00209.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00209", + "parentTask": "M16-GAP-00208", + "status": "done", + "nextTask": "M16-GAP-00210", + "artifactCount": 16 + }, + "statusSummary": [ + "# M16-GAP-00209 Status", + "status: done", + "task: anim.slot_unassign_from_id operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture assigns `OBWebGapUnassignIdSlot` to `WebGapAnimUnassignIdObject` through `WebGapAnimUnassignIdAction` and keys one custom property.", + "- Desktop runs `ANIM_OT_slot_unassign_from_id` with the animated ID context. The reader preserves the Action animation and exposes the retained slot identifier plus assigned/handle state.", + "evidence:" + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1854, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 464 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00210.md", + "bytes": 1854, + "lines": 38, + "tokens": 464 + }, + { + "path": "tests/golden/M16-GAP-00209/manifest.json", + "bytes": 2853, + "lines": 30, + "tokens": 714 + }, + { + "path": "docs/status/M16-GAP-00209.md", + "bytes": 1108, + "lines": 19, + "tokens": 277 + } + ], + "sourceTokens": 1997, + "evidenceFiles": 1, + "evidenceBytes": 1712, + "evidenceTokens": 428, + "totalTokens": 2425, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3449, + "serializedContextTokens": 764, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00211/anim-start-frame-set-desktop-report.json b/tests/golden/M16-GAP-00211/anim-start-frame-set-desktop-report.json new file mode 100644 index 00000000..90779a6e --- /dev/null +++ b/tests/golden/M16-GAP-00211/anim-start-frame-set-desktop-report.json @@ -0,0 +1,17 @@ +{ + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00211-operator-anim.start_frame_set.blend", + "fixtureSha256": "d2f5cf3f5c3603b0d811c9df3581c10b5c28e3f80adeb30319b079bd95567a36", + "frame": { + "current": 42, + "end": 120, + "start": 42 + }, + "mainMutation": "FRAME_START_SET", + "operation": "ANIM_START_FRAME_SET_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00211" +} diff --git a/tests/golden/M16-GAP-00211/anim-start-frame-set-local-exact-report.json b/tests/golden/M16-GAP-00211/anim-start-frame-set-local-exact-report.json new file mode 100644 index 00000000..65f9376e --- /dev/null +++ b/tests/golden/M16-GAP-00211/anim-start-frame-set-local-exact-report.json @@ -0,0 +1,30 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00211", + "operation": "ANIM_START_FRAME_SET_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00211-operator-anim.start_frame_set.blend", + "sha256": "d2f5cf3f5c3603b0d811c9df3581c10b5c28e3f80adeb30319b079bd95567a36" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00211/anim-start-frame-set-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "FRAME_START_SET" + }, + "wasm": { + "status": "EXACT", + "frame": { + "current": 42, + "end": 120, + "start": 42 + } + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00212" +} diff --git a/tests/golden/M16-GAP-00211/manifest.json b/tests/golden/M16-GAP-00211/manifest.json new file mode 100644 index 00000000..357ab19c --- /dev/null +++ b/tests/golden/M16-GAP-00211/manifest.json @@ -0,0 +1,29 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00211", + "parentTask": "M16-GAP-00210", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_START_FRAME_SET_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { "path": "tests/golden/M16-GAP-00210/manifest.json", "sha256": "f7881ee15006bbe0788238d285b92519a468b3fd833c8c07764252486b2587a6" }, + "fixture": { "path": "tests/files/web/generated/M16-GAP-00211-operator-anim.start_frame_set.blend", "sha256": "d2f5cf3f5c3603b0d811c9df3581c10b5c28e3f80adeb30319b079bd95567a36" }, + "generator": { "path": "tools/web/generated/M16-GAP-00211.py", "sha256": "587d7d78764c9f107677dccd537f0265ca0c340e25127938fea64e99b33fff38" }, + "desktopChecker": { "path": "tools/web/check-action-start-frame-set-desktop.py", "sha256": "a4957a066065a6e4ae474e1fb700fd97179dbc12472fb2ff19f7d5048bbcd3d9" }, + "webChecker": { "path": "tools/web/check-generated-gap.mjs", "sha256": "46180c0ff4f01bfd59295eb2993cec152644a8afa8861c43d583079ea758791e" }, + "reader": { "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "774069a85bf5c59e4bac7be4318db36cf1684e925b783505dbf03dfe2abcbe43" }, + "protocol": { "path": "web/protocol/editor-workflow.ts", "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" }, + "sceneIrProtocol": { "path": "web/protocol/scene-ir.ts", "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" }, + "wasm": { "path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "e57225849e65c6f56206efc67bdc7aaf1bf695205336f7d0eff9b880ece37732" }, + "wasmPublic": { "path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "e57225849e65c6f56206efc67bdc7aaf1bf695205336f7d0eff9b880ece37732" }, + "wasmJs": { "path": "web/app/src/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" }, + "wasmJsPublic": { "path": "web/app/public/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" }, + "desktopReport": { "path": "tests/golden/M16-GAP-00211/anim-start-frame-set-desktop-report.json", "sha256": "b17a936ea363e216aa819cd90c79669a8f95c0c9cdb6aae74c5e24df13a4e240" }, + "webReport": { "path": "tests/golden/M16-GAP-00211/anim-start-frame-set-local-exact-report.json", "sha256": "b145f06715d9d6ef03a304e79d9cf635912db731d00991cd3be4dd56a6cc1a71" }, + "status": { "path": "docs/status/M16-GAP-00211.md", "sha256": "73b13a7c83a37e2edbd5498035987f542538d49650812b4cbb8ed6b27be85cd4" }, + "taskContext": { "path": "tests/golden/M16-GAP-00211/task-context.json", "sha256": "910687fefc3ca3b8661d437c62816ebb19c3c263ec745ec70dcf039dfe0fcc43" } + }, + "nextTask": "M16-GAP-00212" +} diff --git a/tests/golden/M16-GAP-00211/task-context.json b/tests/golden/M16-GAP-00211/task-context.json new file mode 100644 index 00000000..e11dfcf4 --- /dev/null +++ b/tests/golden/M16-GAP-00211/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00211", + "parentTask": "M16-GAP-00210", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.start_frame_set data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.start_frame_set", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00211.py -- tests/files/web/generated/M16-GAP-00211-operator-anim.start_frame_set.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00211", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00211" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00211.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1973, + "contextRemainingTokens": 492 + }, + "source": { + "bytes": 7931, + "tokens": 1984 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00211.py", + "bytes": 590, + "tokens": 148 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00211-operator-anim.start_frame_set.blend", + "bytes": 85586, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 235316, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 536647, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00211/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00211.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00211/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 590, + "tokens": 148 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00212", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00211.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00210/manifest.json", + "parentStatus": "docs/status/M16-GAP-00210.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00211.md", + "tests/golden/M16-GAP-00210/manifest.json", + "docs/status/M16-GAP-00210.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00210", + "parentTask": "M16-GAP-00209", + "status": "done", + "nextTask": "M16-GAP-00211", + "artifactCount": 16 + }, + "statusSummary": [ + "# M16-GAP-00210 Status", + "status: done", + "task: anim.slot_unassign_from_nla_strip operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains `WebGapNlaSlotTrack` with `WebGapNlaSlotStrip` referencing `WebGapAnimNlaSlotAction` and `OBWebGapNlaSlot`.", + "- Desktop runs `ANIM_OT_slot_unassign_from_nla_strip` with the NLA strip context pointer. The reader exposes NLA strip slot identifier, handle, and assigned state.", + "evidence:" + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1789, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 448 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00211.md", + "bytes": 1789, + "lines": 38, + "tokens": 448 + }, + { + "path": "tests/golden/M16-GAP-00210/manifest.json", + "bytes": 2888, + "lines": 30, + "tokens": 722 + }, + { + "path": "docs/status/M16-GAP-00210.md", + "bytes": 1086, + "lines": 19, + "tokens": 272 + } + ], + "sourceTokens": 1984, + "evidenceFiles": 1, + "evidenceBytes": 590, + "evidenceTokens": 148, + "totalTokens": 2132, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3156, + "serializedContextTokens": 754, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00212/anim-update-animated-transform-constraints-desktop-report.json b/tests/golden/M16-GAP-00212/anim-update-animated-transform-constraints-desktop-report.json new file mode 100644 index 00000000..f6bbc4c6 --- /dev/null +++ b/tests/golden/M16-GAP-00212/anim-update-animated-transform-constraints-desktop-report.json @@ -0,0 +1,53 @@ +{ + "after": { + "action": "WebGapAnimatedTransformConstraintAction", + "channels": [ + { + "frames": [ + 1.0, + 10.0 + ], + "index": 0, + "path": "constraints[\"WebGapAnimatedTransformConstraint\"].from_min_x_rot", + "values": [ + -30.0, + 60.0 + ] + } + ], + "constraint": "WebGapAnimatedTransformConstraint", + "mapFrom": "ROTATION", + "object": "WebGapAnimatedTransformConstraintObject" + }, + "before": { + "action": "WebGapAnimatedTransformConstraintAction", + "channels": [ + { + "frames": [ + 1.0, + 10.0 + ], + "index": 0, + "path": "constraints[\"WebGapAnimatedTransformConstraint\"].from_min_x", + "values": [ + -30.0, + 60.0 + ] + } + ], + "constraint": "WebGapAnimatedTransformConstraint", + "mapFrom": "ROTATION", + "object": "WebGapAnimatedTransformConstraintObject" + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00212-operator-anim.update_animated_transform_constraints.blend", + "fixtureSha256": "116684a811bdc591c554c5a8f259d995ca9ba49b102e8ccb79f1a03741fd28f2", + "mainMutation": "TRANSFORM_CONSTRAINT_PATHS_UPDATED", + "operation": "ANIM_UPDATE_ANIMATED_TRANSFORM_CONSTRAINTS_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00212", + "useConvertToRadians": true +} diff --git a/tests/golden/M16-GAP-00212/anim-update-animated-transform-constraints-local-exact-report.json b/tests/golden/M16-GAP-00212/anim-update-animated-transform-constraints-local-exact-report.json new file mode 100644 index 00000000..c7258db3 --- /dev/null +++ b/tests/golden/M16-GAP-00212/anim-update-animated-transform-constraints-local-exact-report.json @@ -0,0 +1,39 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00212", + "operation": "ANIM_UPDATE_ANIMATED_TRANSFORM_CONSTRAINTS_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00212-operator-anim.update_animated_transform_constraints.blend", + "sha256": "116684a811bdc591c554c5a8f259d995ca9ba49b102e8ccb79f1a03741fd28f2" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00212/anim-update-animated-transform-constraints-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "TRANSFORM_CONSTRAINT_PATHS_UPDATED", + "useConvertToRadians": true + }, + "wasm": { + "status": "EXACT", + "animationId": "action:WebGapAnimatedTransformConstraintAction:object:WebGapAnimatedTransformConstraintObject", + "channelPath": "constraints[\"WebGapAnimatedTransformConstraint\"].from_min_x_rot[0]", + "keyframes": [ + { + "frame": 1, + "value": -30 + }, + { + "frame": 10, + "value": 60 + } + ], + "constraintTypeCode": 19 + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00213" +} diff --git a/tests/golden/M16-GAP-00212/manifest.json b/tests/golden/M16-GAP-00212/manifest.json new file mode 100644 index 00000000..af728481 --- /dev/null +++ b/tests/golden/M16-GAP-00212/manifest.json @@ -0,0 +1,29 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00212", + "parentTask": "M16-GAP-00211", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_UPDATE_ANIMATED_TRANSFORM_CONSTRAINTS_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { "path": "tests/golden/M16-GAP-00211/manifest.json", "sha256": "47b0ed1ca1801bccd86b4c829c6d95ed6b99ce63131c9a78e27fb5681eedb8e2" }, + "fixture": { "path": "tests/files/web/generated/M16-GAP-00212-operator-anim.update_animated_transform_constraints.blend", "sha256": "116684a811bdc591c554c5a8f259d995ca9ba49b102e8ccb79f1a03741fd28f2" }, + "generator": { "path": "tools/web/generated/M16-GAP-00212.py", "sha256": "d38cdea9f5584506f0b3ac87fa734da388fd891c81a0438031e5bb881ffd77f5" }, + "desktopChecker": { "path": "tools/web/check-action-update-animated-transform-constraints-desktop.py", "sha256": "3417ba9f8ef8d086457623fe2b69be2de5d3983a4a7b3be57450b7083889ba5f" }, + "webChecker": { "path": "tools/web/check-generated-gap.mjs", "sha256": "397273b4da506523a54ea295fcf47b3418c2d2df754edcc3e0f533699c00e567" }, + "reader": { "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "774069a85bf5c59e4bac7be4318db36cf1684e925b783505dbf03dfe2abcbe43" }, + "protocol": { "path": "web/protocol/editor-workflow.ts", "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" }, + "sceneIrProtocol": { "path": "web/protocol/scene-ir.ts", "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" }, + "wasm": { "path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "e57225849e65c6f56206efc67bdc7aaf1bf695205336f7d0eff9b880ece37732" }, + "wasmPublic": { "path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "e57225849e65c6f56206efc67bdc7aaf1bf695205336f7d0eff9b880ece37732" }, + "wasmJs": { "path": "web/app/src/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" }, + "wasmJsPublic": { "path": "web/app/public/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" }, + "desktopReport": { "path": "tests/golden/M16-GAP-00212/anim-update-animated-transform-constraints-desktop-report.json", "sha256": "6e486664dd967eec8f93569db555e23400fc147d40d172b7c1af19188e7e25e1" }, + "webReport": { "path": "tests/golden/M16-GAP-00212/anim-update-animated-transform-constraints-local-exact-report.json", "sha256": "98592f2cfe53ea6f2d59b34203211b0a45d3969ff546857313e2463f7f8e7b57" }, + "status": { "path": "docs/status/M16-GAP-00212.md", "sha256": "6007b1fe88b4bc38d416bf092d9becd2a8e30a50a56f12f19b6c62ee515a34af" }, + "taskContext": { "path": "tests/golden/M16-GAP-00212/task-context.json", "sha256": "b1e138449cd81cc88bfe78855410f9b640db035bbfc59bc21fd750f5887ca3e6" } + }, + "nextTask": "M16-GAP-00213" +} diff --git a/tests/golden/M16-GAP-00212/task-context.json b/tests/golden/M16-GAP-00212/task-context.json new file mode 100644 index 00000000..511c4524 --- /dev/null +++ b/tests/golden/M16-GAP-00212/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00212", + "parentTask": "M16-GAP-00211", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.update_animated_transform_constraints data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.update_animated_transform_constraints", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00212.py -- tests/files/web/generated/M16-GAP-00212-operator-anim.update_animated_transform_constraints.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00212", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00212" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00212.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1986, + "contextRemainingTokens": 496 + }, + "source": { + "bytes": 7918, + "tokens": 1980 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00212.py", + "bytes": 1600, + "tokens": 400 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00212-operator-anim.update_animated_transform_constraints.blend", + "bytes": 86923, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 235316, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 541256, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00212/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00212.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00212/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1600, + "tokens": 400 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00213", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00212.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00211/manifest.json", + "parentStatus": "docs/status/M16-GAP-00211.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00212.md", + "tests/golden/M16-GAP-00211/manifest.json", + "docs/status/M16-GAP-00211.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00211", + "parentTask": "M16-GAP-00210", + "status": "done", + "nextTask": "M16-GAP-00212", + "artifactCount": 16 + }, + "statusSummary": [ + "# M16-GAP-00211 Status", + "status: done", + "task: anim.start_frame_set operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal scene starts at frame 42 with a scene range of 1-120. The foreground animation-area context invokes `ANIM_OT_start_frame_set` (`poll=true`, `FINISHED`) and sets the scene start frame to 42.", + "- The existing Main reader exposes the same scene frame tuple through `Scene.r.cfra`, `Scene.r.sfra`, and `Scene.r.efra`; no unrelated data-block, editor, or browser behavior was changed.", + "evidence:" + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1899, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 475 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00212.md", + "bytes": 1899, + "lines": 38, + "tokens": 475 + }, + { + "path": "tests/golden/M16-GAP-00211/manifest.json", + "bytes": 2823, + "lines": 30, + "tokens": 706 + }, + { + "path": "docs/status/M16-GAP-00211.md", + "bytes": 1028, + "lines": 19, + "tokens": 257 + } + ], + "sourceTokens": 1980, + "evidenceFiles": 1, + "evidenceBytes": 1600, + "evidenceTokens": 400, + "totalTokens": 2380, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3404, + "serializedContextTokens": 771, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00213/anim-version-bone-hide-property-desktop-report.json b/tests/golden/M16-GAP-00213/anim-version-bone-hide-property-desktop-report.json new file mode 100644 index 00000000..b687265f --- /dev/null +++ b/tests/golden/M16-GAP-00213/anim-version-bone-hide-property-desktop-report.json @@ -0,0 +1,92 @@ +{ + "after": { + "active": "WebGapVersionBoneHideObject", + "armatureAction": "WebGapVersionBoneHideArmatureAction", + "armatureChannels": [ + { + "frames": [ + 1.0, + 10.0 + ], + "index": 0, + "path": "bones[\"WebGapVersionBoneHideBone\"].hide", + "values": [ + 0.0, + 1.0 + ] + } + ], + "objectAction": "WebGapVersionBoneHideObjectAction", + "objectChannels": [ + { + "frames": [ + 1.0, + 10.0 + ], + "index": 0, + "path": "[\"version_anchor\"]", + "values": [ + 0.0, + 1.0 + ] + }, + { + "frames": [ + 1.0, + 10.0 + ], + "index": 0, + "path": "pose.bones[\"WebGapVersionBoneHideBone\"].hide", + "values": [ + 0.0, + 1.0 + ] + } + ], + "selected": true + }, + "before": { + "active": "WebGapVersionBoneHideObject", + "armatureAction": "WebGapVersionBoneHideArmatureAction", + "armatureChannels": [ + { + "frames": [ + 1.0, + 10.0 + ], + "index": 0, + "path": "bones[\"WebGapVersionBoneHideBone\"].hide", + "values": [ + 0.0, + 1.0 + ] + } + ], + "objectAction": "WebGapVersionBoneHideObjectAction", + "objectChannels": [ + { + "frames": [ + 1.0, + 10.0 + ], + "index": 0, + "path": "[\"version_anchor\"]", + "values": [ + 0.0, + 1.0 + ] + } + ], + "selected": true + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00213-operator-anim.version_bone_hide_property.blend", + "fixtureSha256": "5455d4f3f44ccc40db7ac379d5c6d4bbb099c3861a348237a1541697597956c1", + "mainMutation": "BONE_HIDE_FCURVE_MOVED_TO_OBJECT_ACTION", + "operation": "ANIM_VERSION_BONE_HIDE_PROPERTY_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00213" +} diff --git a/tests/golden/M16-GAP-00213/anim-version-bone-hide-property-local-exact-report.json b/tests/golden/M16-GAP-00213/anim-version-bone-hide-property-local-exact-report.json new file mode 100644 index 00000000..d3df16b0 --- /dev/null +++ b/tests/golden/M16-GAP-00213/anim-version-bone-hide-property-local-exact-report.json @@ -0,0 +1,38 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00213", + "operation": "ANIM_VERSION_BONE_HIDE_PROPERTY_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00213-operator-anim.version_bone_hide_property.blend", + "sha256": "5455d4f3f44ccc40db7ac379d5c6d4bbb099c3861a348237a1541697597956c1" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00213/anim-version-bone-hide-property-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "BONE_HIDE_FCURVE_MOVED_TO_OBJECT_ACTION" + }, + "wasm": { + "status": "EXACT", + "objectAnimationId": "action:WebGapVersionBoneHideObjectAction:object:WebGapVersionBoneHideObject", + "copiedChannelPath": "pose.bones[\"WebGapVersionBoneHideBone\"].hide[0]", + "copiedKeyframes": [ + { + "frame": 1, + "value": 0 + }, + { + "frame": 10, + "value": 1 + } + ], + "armatureAnimationId": "action:WebGapVersionBoneHideArmatureAction:armature:WebGapVersionBoneHideArmature" + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00214" +} diff --git a/tests/golden/M16-GAP-00213/manifest.json b/tests/golden/M16-GAP-00213/manifest.json new file mode 100644 index 00000000..55892826 --- /dev/null +++ b/tests/golden/M16-GAP-00213/manifest.json @@ -0,0 +1,29 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00213", + "parentTask": "M16-GAP-00212", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_VERSION_BONE_HIDE_PROPERTY_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { "path": "tests/golden/M16-GAP-00212/manifest.json", "sha256": "b0816225b3c22bd80b9a89d51c7ea57d1723149eea9859a017019d6ba0953673" }, + "fixture": { "path": "tests/files/web/generated/M16-GAP-00213-operator-anim.version_bone_hide_property.blend", "sha256": "5455d4f3f44ccc40db7ac379d5c6d4bbb099c3861a348237a1541697597956c1" }, + "generator": { "path": "tools/web/generated/M16-GAP-00213.py", "sha256": "f5e1eefa9c012d091f413ec771f6dab8dac496f2d4481e33fa288a61a6ef4c86" }, + "desktopChecker": { "path": "tools/web/check-action-version-bone-hide-property-desktop.py", "sha256": "6b03a7faf073e652eb260a01068dd7d167e6ff88e46f75dfa9e1445edda1ab29" }, + "webChecker": { "path": "tools/web/check-generated-gap.mjs", "sha256": "7cdd6a343dc7ab3e0aa7b109a3f770c76a863980520293c48d2cf1f7e28b5625" }, + "reader": { "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "774069a85bf5c59e4bac7be4318db36cf1684e925b783505dbf03dfe2abcbe43" }, + "protocol": { "path": "web/protocol/editor-workflow.ts", "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" }, + "sceneIrProtocol": { "path": "web/protocol/scene-ir.ts", "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" }, + "wasm": { "path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "e57225849e65c6f56206efc67bdc7aaf1bf695205336f7d0eff9b880ece37732" }, + "wasmPublic": { "path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "e57225849e65c6f56206efc67bdc7aaf1bf695205336f7d0eff9b880ece37732" }, + "wasmJs": { "path": "web/app/src/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" }, + "wasmJsPublic": { "path": "web/app/public/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" }, + "desktopReport": { "path": "tests/golden/M16-GAP-00213/anim-version-bone-hide-property-desktop-report.json", "sha256": "35c3ee64110db16c946056cd3c3044321d6101a4ee68c2fd68038cbab4576616" }, + "webReport": { "path": "tests/golden/M16-GAP-00213/anim-version-bone-hide-property-local-exact-report.json", "sha256": "117e80e3ee5caf95979201d85b650de27967196242bf6f5656d24c3cec973d85" }, + "status": { "path": "docs/status/M16-GAP-00213.md", "sha256": "ee58d81b60550da7abf3a6f6a99cf53d33e5570fcaa7c49bed46db66ecbb9b4d" }, + "taskContext": { "path": "tests/golden/M16-GAP-00213/task-context.json", "sha256": "a9cbb2cffc15ad50810b4e806492a6dda84b30757f085c17a0c754c4160c9868" } + }, + "nextTask": "M16-GAP-00214" +} diff --git a/tests/golden/M16-GAP-00213/task-context.json b/tests/golden/M16-GAP-00213/task-context.json new file mode 100644 index 00000000..0a28e253 --- /dev/null +++ b/tests/golden/M16-GAP-00213/task-context.json @@ -0,0 +1,182 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00213", + "parentTask": "M16-GAP-00212", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.version_bone_hide_property data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.version_bone_hide_property", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00213.py -- tests/files/web/generated/M16-GAP-00213-operator-anim.version_bone_hide_property.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00213", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00213" + ], + "inputPaths": [], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1703, + "contextRemainingTokens": 425 + }, + "source": { + "bytes": 8201, + "tokens": 2051 + }, + "selected": [], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00213-operator-anim.version_bone_hide_property.blend", + "bytes": 86812, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/generated/M16-GAP-00213.py", + "bytes": 2312, + "reason": "CONTEXT_REMAINING_SPACE" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 235316, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 545613, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00213/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00213.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00213/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 0, + "bytes": 0, + "tokens": 0 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00214", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00213.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00212/manifest.json", + "parentStatus": "docs/status/M16-GAP-00212.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00213.md", + "tests/golden/M16-GAP-00212/manifest.json", + "docs/status/M16-GAP-00212.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00212", + "parentTask": "M16-GAP-00211", + "status": "done", + "nextTask": "M16-GAP-00213", + "artifactCount": 16 + }, + "statusSummary": [ + "# M16-GAP-00212 Status", + "status: done", + "task: anim.update_animated_transform_constraints operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains a mesh object with a `TRANSFORM` constraint mapped from rotation and one animated legacy `from_min_x` F-curve.", + "- Desktop runs `ANIM_OT_update_animated_transform_constraints(use_convert_to_radians=true)` (`poll=true`, `FINISHED`) and rewrites the channel path to `from_min_x_rot`.", + "- The existing Main reader exposes the rewritten Action channel and Transform constraint metadata; no unrelated data-block, editor, or browser behavior was changed." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1844, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 461 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00213.md", + "bytes": 1844, + "lines": 38, + "tokens": 461 + }, + { + "path": "tests/golden/M16-GAP-00212/manifest.json", + "bytes": 2933, + "lines": 30, + "tokens": 734 + }, + { + "path": "docs/status/M16-GAP-00212.md", + "bytes": 1256, + "lines": 20, + "tokens": 314 + } + ], + "sourceTokens": 2051, + "evidenceFiles": 0, + "evidenceBytes": 0, + "evidenceTokens": 0, + "totalTokens": 2051, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3075, + "serializedContextTokens": 727, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00214/anim-view-curve-in-graph-editor-desktop-report.json b/tests/golden/M16-GAP-00214/anim-view-curve-in-graph-editor-desktop-report.json new file mode 100644 index 00000000..b28a6d78 --- /dev/null +++ b/tests/golden/M16-GAP-00214/anim-view-curve-in-graph-editor-desktop-report.json @@ -0,0 +1,94 @@ +{ + "after": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 10.0 + ], + "index": 0, + "path": "[\"curve_target\"]", + "selected": true, + "values": [ + -3.0, + 7.0 + ] + } + ], + "name": "WebGapAnimViewCurveGraphEditorAction" + }, + "active": true, + "selected": true, + "value": 1.170096, + "view": { + "areaType": "GRAPH_EDITOR", + "mode": "FCURVES", + "view2d": { + "cur": { + "xmax": 1.5, + "xmin": 0.5, + "ymax": -2.505917, + "ymin": -3.505917 + }, + "mask": { + "xmax": 537, + "xmin": 0, + "ymax": 25, + "ymin": 0 + } + } + } + }, + "before": { + "action": { + "channels": [ + { + "frames": [ + 1.0, + 10.0 + ], + "index": 0, + "path": "[\"curve_target\"]", + "selected": true, + "values": [ + -3.0, + 7.0 + ] + } + ], + "name": "WebGapAnimViewCurveGraphEditorAction" + }, + "active": true, + "selected": true, + "value": 1.170096, + "view": { + "areaType": "GRAPH_EDITOR", + "mode": "FCURVES", + "view2d": { + "cur": { + "xmax": 13.0, + "xmin": -2.0, + "ymax": 7.5, + "ymin": -3.5 + }, + "mask": { + "xmax": 537, + "xmin": 0, + "ymax": 25, + "ymin": 0 + } + } + } + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00214-operator-anim.view_curve_in_graph_editor.blend", + "fixtureSha256": "405825a29d3bf69cd85e461bf0c1a727631febe354b11ed1fd722d72f0faaea2", + "mainMutation": "GRAPH_VIEW_FRAMED", + "operation": "ANIM_VIEW_CURVE_IN_GRAPH_EDITOR_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00214" +} diff --git a/tests/golden/M16-GAP-00214/anim-view-curve-in-graph-editor-local-exact-report.json b/tests/golden/M16-GAP-00214/anim-view-curve-in-graph-editor-local-exact-report.json new file mode 100644 index 00000000..9ac96a4e --- /dev/null +++ b/tests/golden/M16-GAP-00214/anim-view-curve-in-graph-editor-local-exact-report.json @@ -0,0 +1,69 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00214", + "operation": "ANIM_VIEW_CURVE_IN_GRAPH_EDITOR_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00214-operator-anim.view_curve_in_graph_editor.blend", + "sha256": "405825a29d3bf69cd85e461bf0c1a727631febe354b11ed1fd722d72f0faaea2" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00214/anim-view-curve-in-graph-editor-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "GRAPH_VIEW_FRAMED", + "beforeView2d": { + "cur": { + "xmax": 13, + "xmin": -2, + "ymax": 7.5, + "ymin": -3.5 + }, + "mask": { + "xmax": 537, + "xmin": 0, + "ymax": 25, + "ymin": 0 + } + }, + "afterView2d": { + "cur": { + "xmax": 1.5, + "xmin": 0.5, + "ymax": -2.505917, + "ymin": -3.505917 + }, + "mask": { + "xmax": 537, + "xmin": 0, + "ymax": 25, + "ymin": 0 + } + } + }, + "wasm": { + "status": "EXACT", + "editor": "GRAPH", + "regionKind": "MAIN", + "view2d": { + "cur": { + "xmax": 13, + "xmin": -2, + "ymax": 7.5, + "ymin": -3.5 + }, + "mask": { + "xmax": 1577, + "xmin": 0, + "ymax": 76, + "ymin": 0 + } + } + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00215" +} diff --git a/tests/golden/M16-GAP-00214/manifest.json b/tests/golden/M16-GAP-00214/manifest.json new file mode 100644 index 00000000..fb6246e1 --- /dev/null +++ b/tests/golden/M16-GAP-00214/manifest.json @@ -0,0 +1,77 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00214", + "parentTask": "M16-GAP-00213", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ANIM_VIEW_CURVE_IN_GRAPH_EDITOR_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00213/manifest.json", + "sha256": "08467e4ffc091a6b32ce09ba35cacaff880f3292823bc0bd2a8ca4995ddbc8ec" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00214-operator-anim.view_curve_in_graph_editor.blend", + "sha256": "405825a29d3bf69cd85e461bf0c1a727631febe354b11ed1fd722d72f0faaea2" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00214.py", + "sha256": "a5c2ab327f0540ac3b80088e9022c9231be30408defe536263a87c3394677b80" + }, + "desktopChecker": { + "path": "tools/web/check-action-view-curve-in-graph-editor-desktop.py", + "sha256": "38e8a54df8725315b0c60bec955c77a3e2a1022d01898377f097268165be81cf" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "8ca58e1feec4af6a326606c6ed6df6b18d008d96c1609bf1cb3915ce76fd1ec4" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "cda5ebf01d6f63b8071a10b506a044c829627329d87bc2ea7a139ee726f7071c" + }, + "protocol": { + "path": "web/protocol/editor-workflow.ts", + "sha256": "a3d4f32fafdc205f0a76362d1a43db85fa023e9edba444fcd77479da0c6f573a" + }, + "sceneIrProtocol": { + "path": "web/protocol/scene-ir.ts", + "sha256": "9e877612886c629786405e03e1939d3954af2d38dfea2d6359b367934d06f226" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "a0067e363e2ce53fc9658e67819c74cce01a515d6272d6a7c028776b4465fe87" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "a0067e363e2ce53fc9658e67819c74cce01a515d6272d6a7c028776b4465fe87" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "wasmJsPublic": { + "path": "web/app/public/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00214/anim-view-curve-in-graph-editor-desktop-report.json", + "sha256": "127e6168e198cae8661d358b457d1459f9b515f79d2a6e86aa0c1022fb3210c6" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00214/anim-view-curve-in-graph-editor-local-exact-report.json", + "sha256": "bfa381ab96c2f2f0d9d16dcc7afd7a0200284a5704610cb70a6f0db402c3698b" + }, + "status": { + "path": "docs/status/M16-GAP-00214.md", + "sha256": "67c9c89f921f7c911bfb5172da5eefa1fe68a9749b41e61b55383d63ba65de6c" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00214/task-context.json", + "sha256": "905f7ee4e419109e77a274f385c405132f5e471cf0c4f0e24c363fd60dffb431" + } + }, + "nextTask": "M16-GAP-00215" +} diff --git a/tests/golden/M16-GAP-00214/task-context.json b/tests/golden/M16-GAP-00214/task-context.json new file mode 100644 index 00000000..80fa2a84 --- /dev/null +++ b/tests/golden/M16-GAP-00214/task-context.json @@ -0,0 +1,182 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00214", + "parentTask": "M16-GAP-00213", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:anim.view_curve_in_graph_editor data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:anim.view_curve_in_graph_editor", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00214.py -- tests/files/web/generated/M16-GAP-00214-operator-anim.view_curve_in_graph_editor.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00214", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00214" + ], + "inputPaths": [], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1746, + "contextRemainingTokens": 436 + }, + "source": { + "bytes": 8158, + "tokens": 2040 + }, + "selected": [], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00214-operator-anim.view_curve_in_graph_editor.blend", + "bytes": 87074, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/generated/M16-GAP-00214.py", + "bytes": 2640, + "reason": "CONTEXT_REMAINING_SPACE" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 235367, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 549459, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00214/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00214.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00214/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 0, + "bytes": 0, + "tokens": 0 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00215", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00214.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00213/manifest.json", + "parentStatus": "docs/status/M16-GAP-00213.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00214.md", + "tests/golden/M16-GAP-00213/manifest.json", + "docs/status/M16-GAP-00213.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00213", + "parentTask": "M16-GAP-00212", + "status": "done", + "nextTask": "M16-GAP-00214", + "artifactCount": 16 + }, + "statusSummary": [ + "# M16-GAP-00213 Status", + "status: done", + "task: anim.version_bone_hide_property operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one selected armature object, one bone, an armature-data Action with `bones[\"WebGapVersionBoneHideBone\"].hide`, and an object Action with an anchor channel.", + "- Desktop runs `ANIM_OT_version_bone_hide_property` (`poll=true`, `FINISHED`) and copies the hide F-curve into the object Action as `pose.bones[\"WebGapVersionBoneHideBone\"].hide`, retaining the armature source channel.", + "- The existing Main reader exposes both Action channels and the armature data; no unrelated data-block, editor, or browser behavior was changed." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1844, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 461 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00214.md", + "bytes": 1844, + "lines": 38, + "tokens": 461 + }, + { + "path": "tests/golden/M16-GAP-00213/manifest.json", + "bytes": 2878, + "lines": 30, + "tokens": 720 + }, + { + "path": "docs/status/M16-GAP-00213.md", + "bytes": 1268, + "lines": 20, + "tokens": 317 + } + ], + "sourceTokens": 2040, + "evidenceFiles": 0, + "evidenceBytes": 0, + "evidenceTokens": 0, + "totalTokens": 2040, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3064, + "serializedContextTokens": 727, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00215/armature-align-desktop-report.json b/tests/golden/M16-GAP-00215/armature-align-desktop-report.json new file mode 100644 index 00000000..ac8d2f1f --- /dev/null +++ b/tests/golden/M16-GAP-00215/armature-align-desktop-report.json @@ -0,0 +1,81 @@ +{ + "after": { + "armature": "WebGapArmatureAlignArmature", + "bones": [ + { + "head": [ + 0.0, + 0.0, + 3.0 + ], + "name": "WebGapArmatureAlignChild", + "parent": null, + "tail": [ + 0.0, + 0.0, + 5.44949 + ] + }, + { + "head": [ + 0.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureAlignParent", + "parent": null, + "tail": [ + 0.0, + 0.0, + 3.0 + ] + } + ], + "object": "WebGapArmatureAlignObject" + }, + "alreadyAligned": true, + "before": { + "armature": "WebGapArmatureAlignArmature", + "bones": [ + { + "head": [ + 0.0, + 0.0, + 3.0 + ], + "name": "WebGapArmatureAlignChild", + "parent": null, + "tail": [ + 0.0, + 0.0, + 5.44949 + ] + }, + { + "head": [ + 0.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureAlignParent", + "parent": null, + "tail": [ + 0.0, + 0.0, + 3.0 + ] + } + ], + "object": "WebGapArmatureAlignObject" + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00215-operator-armature.align.blend", + "fixtureSha256": "772ad751d2ad898214e27469c451ab44ce0463bb99271b160b70f57941e9b419", + "mainMutation": "CHILD_ALIGNED_TO_PARENT", + "operation": "ARMATURE_ALIGN_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00215" +} diff --git a/tests/golden/M16-GAP-00215/armature-align-local-exact-report.json b/tests/golden/M16-GAP-00215/armature-align-local-exact-report.json new file mode 100644 index 00000000..db56a501 --- /dev/null +++ b/tests/golden/M16-GAP-00215/armature-align-local-exact-report.json @@ -0,0 +1,53 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00215", + "operation": "ARMATURE_ALIGN_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00215-operator-armature.align.blend", + "sha256": "772ad751d2ad898214e27469c451ab44ce0463bb99271b160b70f57941e9b419" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00215/armature-align-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "CHILD_ALIGNED_TO_PARENT" + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureAlignArmature", + "parentBone": { + "id": "bone:armature:WebGapArmatureAlignArmature:WebGapArmatureAlignParent", + "head": [ + 0, + 0, + 0 + ], + "tail": [ + 0, + 0, + 3 + ] + }, + "alignedChildBone": { + "id": "bone:armature:WebGapArmatureAlignArmature:WebGapArmatureAlignChild", + "head": [ + 0, + 0, + 3 + ], + "tail": [ + 0, + 0, + 5.449489593505859 + ], + "parentId": null + } + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00216" +} diff --git a/tests/golden/M16-GAP-00215/manifest.json b/tests/golden/M16-GAP-00215/manifest.json new file mode 100644 index 00000000..73c9490f --- /dev/null +++ b/tests/golden/M16-GAP-00215/manifest.json @@ -0,0 +1,69 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00215", + "parentTask": "M16-GAP-00214", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_ALIGN_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00214/manifest.json", + "sha256": "0ff1e297545b308ad6ef9006c80992a0f9ecba88008bf9c0b4f3a86b6c28c145" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00215-operator-armature.align.blend", + "sha256": "772ad751d2ad898214e27469c451ab44ce0463bb99271b160b70f57941e9b419" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00215.py", + "sha256": "b755086a190245ff4ed5effb4c713790ea8e1b066c79800ecb7b32cbfc1c1764" + }, + "desktopChecker": { + "path": "tools/web/check-action-armature-align-desktop.py", + "sha256": "a406c012536580f3dfc6b5851015bb65ccf578acce6e606c0994e4428de83738" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "f856119464bf174f206485d1899ff4086c7c3dd39dd3091976592a0f9d19fe88" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "c56d254a74ace9664104f139692cf37f825547301824872bfd8db95f6ad2117b" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "82b9fb9488a20543f0db1235b18a7c28b2593ac498c152a12f45f8299ced1927" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "82b9fb9488a20543f0db1235b18a7c28b2593ac498c152a12f45f8299ced1927" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "wasmJsPublic": { + "path": "web/app/public/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00215/armature-align-desktop-report.json", + "sha256": "f0f94981885773704748c302cad95cf7b0a24137cfb6d36921e8d464c408cb40" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00215/armature-align-local-exact-report.json", + "sha256": "d9b19ad3b36bc1a7303207b9ed9f3c2b32df072fce5349718b2783019e144e4e" + }, + "status": { + "path": "docs/status/M16-GAP-00215.md", + "sha256": "9bdd9c23820e98dfbb1bb57c2c1c7339f07e54c4abf2ba06d5b18a3fc0c0762d" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00215/task-context.json", + "sha256": "82b2e30643461bfcff8612e29aebe38d50f2585b8be9b1c780ae6d762298ab87" + } + }, + "nextTask": "M16-GAP-00216" +} diff --git a/tests/golden/M16-GAP-00215/task-context.json b/tests/golden/M16-GAP-00215/task-context.json new file mode 100644 index 00000000..ddd05af4 --- /dev/null +++ b/tests/golden/M16-GAP-00215/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00215", + "parentTask": "M16-GAP-00214", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.align data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.align", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00215.py -- tests/files/web/generated/M16-GAP-00215-operator-armature.align.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00215", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00215" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00215.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1616, + "contextRemainingTokens": 403 + }, + "source": { + "bytes": 8288, + "tokens": 2073 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00215.py", + "bytes": 1343, + "tokens": 336 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00215-operator-armature.align.blend", + "bytes": 86317, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 235367, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 553947, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00215/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00215.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00215/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1343, + "tokens": 336 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00216", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00215.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00214/manifest.json", + "parentStatus": "docs/status/M16-GAP-00214.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00215.md", + "tests/golden/M16-GAP-00214/manifest.json", + "docs/status/M16-GAP-00214.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00214", + "parentTask": "M16-GAP-00213", + "status": "done", + "nextTask": "M16-GAP-00215", + "artifactCount": 16 + }, + "statusSummary": [ + "# M16-GAP-00214 Status", + "status: done", + "task: anim.view_curve_in_graph_editor operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one selected mesh object, one custom animated scalar property with frames 1 and 10, and a persisted Graph Editor area.", + "- Desktop activates the property button and runs `ANIM_OT_view_curve_in_graph_editor` with `poll=true` and `FINISHED`; the operator changes the Graph Editor view bounds while leaving the Action data unchanged.", + "- The Main reader now exposes `View2D` state for `GRAPH` editor main regions, alongside the existing Dope Sheet exposure. No other editor or data-block behavior changed." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1759, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 440 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00215.md", + "bytes": 1759, + "lines": 38, + "tokens": 440 + }, + { + "path": "tests/golden/M16-GAP-00214/manifest.json", + "bytes": 3134, + "lines": 78, + "tokens": 784 + }, + { + "path": "docs/status/M16-GAP-00214.md", + "bytes": 1227, + "lines": 20, + "tokens": 307 + } + ], + "sourceTokens": 2073, + "evidenceFiles": 1, + "evidenceBytes": 1343, + "evidenceTokens": 336, + "totalTokens": 2409, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3433, + "serializedContextTokens": 750, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00216/armature-assign-to-collection-desktop-report.json b/tests/golden/M16-GAP-00216/armature-assign-to-collection-desktop-report.json new file mode 100644 index 00000000..a74cc40a --- /dev/null +++ b/tests/golden/M16-GAP-00216/armature-assign-to-collection-desktop-report.json @@ -0,0 +1,53 @@ +{ + "after": { + "armature": "WebGapArmatureAssignArmature", + "collections": [ + { + "bones": [ + "WebGapArmatureAssignChild" + ], + "index": 0, + "name": "WebGapArmatureAssignSource" + }, + { + "bones": [ + "WebGapArmatureAssignChild" + ], + "index": 1, + "name": "WebGapArmatureAssignTarget" + } + ], + "object": "WebGapArmatureAssignObject" + }, + "alreadyAssigned": true, + "before": { + "armature": "WebGapArmatureAssignArmature", + "collections": [ + { + "bones": [ + "WebGapArmatureAssignChild" + ], + "index": 0, + "name": "WebGapArmatureAssignSource" + }, + { + "bones": [ + "WebGapArmatureAssignChild" + ], + "index": 1, + "name": "WebGapArmatureAssignTarget" + } + ], + "object": "WebGapArmatureAssignObject" + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00216-operator-armature.assign_to_collection.blend", + "fixtureSha256": "be79a2c05b090aaf1e7ce9f777a6adea68b5fb6b7750ffe130eebf2ab4608b43", + "mainMutation": "CHILD_ASSIGNED_TO_TARGET_COLLECTION", + "operation": "ARMATURE_ASSIGN_TO_COLLECTION_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00216" +} diff --git a/tests/golden/M16-GAP-00216/armature-assign-to-collection-local-exact-report.json b/tests/golden/M16-GAP-00216/armature-assign-to-collection-local-exact-report.json new file mode 100644 index 00000000..1c5800c9 --- /dev/null +++ b/tests/golden/M16-GAP-00216/armature-assign-to-collection-local-exact-report.json @@ -0,0 +1,39 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00216", + "operation": "ARMATURE_ASSIGN_TO_COLLECTION_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00216-operator-armature.assign_to_collection.blend", + "sha256": "be79a2c05b090aaf1e7ce9f777a6adea68b5fb6b7750ffe130eebf2ab4608b43" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00216/armature-assign-to-collection-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "CHILD_ASSIGNED_TO_TARGET_COLLECTION" + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureAssignArmature", + "sourceCollection": { + "id": "bone_collection:armature:WebGapArmatureAssignArmature:WebGapArmatureAssignSource", + "boneIds": [ + "bone:armature:WebGapArmatureAssignArmature:WebGapArmatureAssignChild" + ] + }, + "targetCollection": { + "id": "bone_collection:armature:WebGapArmatureAssignArmature:WebGapArmatureAssignTarget", + "boneIds": [ + "bone:armature:WebGapArmatureAssignArmature:WebGapArmatureAssignChild" + ] + }, + "assignedBoneId": "bone:armature:WebGapArmatureAssignArmature:WebGapArmatureAssignChild" + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00217" +} diff --git a/tests/golden/M16-GAP-00216/manifest.json b/tests/golden/M16-GAP-00216/manifest.json new file mode 100644 index 00000000..4631e00e --- /dev/null +++ b/tests/golden/M16-GAP-00216/manifest.json @@ -0,0 +1,69 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00216", + "parentTask": "M16-GAP-00215", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_ASSIGN_TO_COLLECTION_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00215/manifest.json", + "sha256": "7d5ff929aa6c3532f6f895e21a5e195e445ddbf0cf3d2d7e9fc5254488a4b0b2" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00216-operator-armature.assign_to_collection.blend", + "sha256": "be79a2c05b090aaf1e7ce9f777a6adea68b5fb6b7750ffe130eebf2ab4608b43" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00216.py", + "sha256": "1e14f51d34a6a3781b299f826ef1a449efa4ad0dc744960b529a00671ffac017" + }, + "desktopChecker": { + "path": "tools/web/check-action-armature-assign-to-collection-desktop.py", + "sha256": "0a2aa43cfb3d08fc2904b9b36dd6fca160309f936bd5006038a56cf355990718" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "f856119464bf174f206485d1899ff4086c7c3dd39dd3091976592a0f9d19fe88" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "c56d254a74ace9664104f139692cf37f825547301824872bfd8db95f6ad2117b" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "82b9fb9488a20543f0db1235b18a7c28b2593ac498c152a12f45f8299ced1927" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "82b9fb9488a20543f0db1235b18a7c28b2593ac498c152a12f45f8299ced1927" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "wasmJsPublic": { + "path": "web/app/public/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00216/armature-assign-to-collection-desktop-report.json", + "sha256": "f9ea1aedef9d6286d5038e9244cd82fec979238d3d72da76201b7bc3ac18b7e2" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00216/armature-assign-to-collection-local-exact-report.json", + "sha256": "4d063e44db5ebe56585caf6e1e28c9ba5dfaee8ddd95c4402a0d40474b94187c" + }, + "status": { + "path": "docs/status/M16-GAP-00216.md", + "sha256": "8e4d7487a830aa736ca668bdffc059ab4bc366fd65f9ef159d10905ed3e27a37" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00216/task-context.json", + "sha256": "0f93744560fa885b9cf0d8e1c6ed605f922ea4bc44c521fee023adae2c0e5cae" + } + }, + "nextTask": "M16-GAP-00217" +} diff --git a/tests/golden/M16-GAP-00216/task-context.json b/tests/golden/M16-GAP-00216/task-context.json new file mode 100644 index 00000000..5a43a573 --- /dev/null +++ b/tests/golden/M16-GAP-00216/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00216", + "parentTask": "M16-GAP-00215", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.assign_to_collection data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.assign_to_collection", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00216.py -- tests/files/web/generated/M16-GAP-00216-operator-armature.assign_to_collection.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00216", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00216" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00216.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2125, + "contextRemainingTokens": 530 + }, + "source": { + "bytes": 7779, + "tokens": 1946 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00216.py", + "bytes": 1512, + "tokens": 378 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00216-operator-armature.assign_to_collection.blend", + "bytes": 86423, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 237877, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 557927, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00216/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00216.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00216/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1512, + "tokens": 378 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00217", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00216.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00215/manifest.json", + "parentStatus": "docs/status/M16-GAP-00215.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00216.md", + "tests/golden/M16-GAP-00215/manifest.json", + "docs/status/M16-GAP-00215.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00215", + "parentTask": "M16-GAP-00214", + "status": "done", + "nextTask": "M16-GAP-00216", + "artifactCount": 14 + }, + "statusSummary": [ + "# M16-GAP-00215 Status", + "status: done", + "task: armature.align operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one armature with two independent edit bones. The child starts at an angled axis and the parent is the active selected bone.", + "- Desktop runs `ARMATURE_OT_align` with `poll=true` and `FINISHED`, aligns the child axis to the active parent, and preserves the result through save/reopen.", + "- The existing Main reader exposes the same armature bone `head`/`tail` data; no other data-block, editor, or browser behavior changed." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1834, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 459 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00216.md", + "bytes": 1834, + "lines": 38, + "tokens": 459 + }, + { + "path": "tests/golden/M16-GAP-00215/manifest.json", + "bytes": 2740, + "lines": 70, + "tokens": 685 + }, + { + "path": "docs/status/M16-GAP-00215.md", + "bytes": 1037, + "lines": 20, + "tokens": 260 + } + ], + "sourceTokens": 1946, + "evidenceFiles": 1, + "evidenceBytes": 1512, + "evidenceTokens": 378, + "totalTokens": 2324, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3348, + "serializedContextTokens": 761, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00217/armature-autoside-names-desktop-report.json b/tests/golden/M16-GAP-00217/armature-autoside-names-desktop-report.json new file mode 100644 index 00000000..1ac1c399 --- /dev/null +++ b/tests/golden/M16-GAP-00217/armature-autoside-names-desktop-report.json @@ -0,0 +1,77 @@ +{ + "after": { + "armature": "WebGapArmatureAutosideArmature", + "bones": [ + { + "head": [ + 1.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureAutosideLeft.L", + "tail": [ + 1.0, + 0.0, + 2.0 + ] + }, + { + "head": [ + -1.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureAutosideRight.R", + "tail": [ + -1.0, + 0.0, + 2.0 + ] + } + ], + "object": "WebGapArmatureAutosideObject" + }, + "alreadyNamed": true, + "before": { + "armature": "WebGapArmatureAutosideArmature", + "bones": [ + { + "head": [ + 1.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureAutosideLeft.L", + "tail": [ + 1.0, + 0.0, + 2.0 + ] + }, + { + "head": [ + -1.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureAutosideRight.R", + "tail": [ + -1.0, + 0.0, + 2.0 + ] + } + ], + "object": "WebGapArmatureAutosideObject" + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00217-operator-armature.autoside_names.blend", + "fixtureSha256": "9dafd4489858ab080988c474877d6e9a9e5a7884b8e00d42c070b7769d2ed57f", + "mainMutation": "ALREADY_AUTOSIDE_NAMED", + "operation": "ARMATURE_AUTOSIDE_NAMES_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00217" +} diff --git a/tests/golden/M16-GAP-00217/armature-autoside-names-local-exact-report.json b/tests/golden/M16-GAP-00217/armature-autoside-names-local-exact-report.json new file mode 100644 index 00000000..4e63ac0c --- /dev/null +++ b/tests/golden/M16-GAP-00217/armature-autoside-names-local-exact-report.json @@ -0,0 +1,32 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00217", + "operation": "ARMATURE_AUTOSIDE_NAMES_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00217-operator-armature.autoside_names.blend", + "sha256": "9dafd4489858ab080988c474877d6e9a9e5a7884b8e00d42c070b7769d2ed57f" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00217/armature-autoside-names-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "ALREADY_AUTOSIDE_NAMED" + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureAutosideArmature", + "boneNames": [ + "WebGapArmatureAutosideLeft.L", + "WebGapArmatureAutosideRight.R" + ], + "leftBoneId": "bone:armature:WebGapArmatureAutosideArmature:WebGapArmatureAutosideLeft.L", + "rightBoneId": "bone:armature:WebGapArmatureAutosideArmature:WebGapArmatureAutosideRight.R" + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00218" +} diff --git a/tests/golden/M16-GAP-00217/manifest.json b/tests/golden/M16-GAP-00217/manifest.json new file mode 100644 index 00000000..3c996626 --- /dev/null +++ b/tests/golden/M16-GAP-00217/manifest.json @@ -0,0 +1,69 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00217", + "parentTask": "M16-GAP-00216", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_AUTOSIDE_NAMES_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00216/manifest.json", + "sha256": "3b2e12276994fca0c6c2d548eb634f9bcd44c6cf504cfea06b53aa863e59c754" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00217-operator-armature.autoside_names.blend", + "sha256": "9dafd4489858ab080988c474877d6e9a9e5a7884b8e00d42c070b7769d2ed57f" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00217.py", + "sha256": "037230ad7bb83e69a7c89aca12b62a87dd13d18307bf5f6dcc2c6b0ce059c51d" + }, + "desktopChecker": { + "path": "tools/web/check-action-armature-autoside-names-desktop.py", + "sha256": "1d8983980d621a559bef9b0bd14eecc1dbf95b43fee2eecaecf970f7052b1e1d" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "02fe1cd3eb72c15409ad2dde955629adb6456d1170fec43309dc2c5cd6e2fb53" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "c56d254a74ace9664104f139692cf37f825547301824872bfd8db95f6ad2117b" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "82b9fb9488a20543f0db1235b18a7c28b2593ac498c152a12f45f8299ced1927" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "82b9fb9488a20543f0db1235b18a7c28b2593ac498c152a12f45f8299ced1927" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "wasmJsPublic": { + "path": "web/app/public/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00217/armature-autoside-names-desktop-report.json", + "sha256": "2ccaaa1f2b8549abc17bd0640add62b658ccc77b9a2792456df929dd209e466d" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00217/armature-autoside-names-local-exact-report.json", + "sha256": "2a479e88f080b7e7530f1f8f6ac87fe5aa5ca7ffaf69a068eaf4eeb99b257e80" + }, + "status": { + "path": "docs/status/M16-GAP-00217.md", + "sha256": "a735bae8a60c2d32b47221d4f5547489808daa8e939c7dec4bd7c729eeb23a3c" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00217/task-context.json", + "sha256": "0dc798480ef127c5528973b78ba24a99f8514b04212578e0f3b5633be8da06fa" + } + }, + "nextTask": "M16-GAP-00218" +} diff --git a/tests/golden/M16-GAP-00217/task-context.json b/tests/golden/M16-GAP-00217/task-context.json new file mode 100644 index 00000000..010b9dcd --- /dev/null +++ b/tests/golden/M16-GAP-00217/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00217", + "parentTask": "M16-GAP-00216", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.autoside_names data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.autoside_names", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00217.py -- tests/files/web/generated/M16-GAP-00217-operator-armature.autoside_names.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00217", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00217" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00217.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1945, + "contextRemainingTokens": 486 + }, + "source": { + "bytes": 7959, + "tokens": 1990 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00217.py", + "bytes": 1252, + "tokens": 313 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00217-operator-armature.autoside_names.blend", + "bytes": 86309, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 237877, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 561677, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00217/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00217.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00217/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1252, + "tokens": 313 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00218", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00217.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00216/manifest.json", + "parentStatus": "docs/status/M16-GAP-00216.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00217.md", + "tests/golden/M16-GAP-00216/manifest.json", + "docs/status/M16-GAP-00216.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00216", + "parentTask": "M16-GAP-00215", + "status": "done", + "nextTask": "M16-GAP-00217", + "artifactCount": 14 + }, + "statusSummary": [ + "# M16-GAP-00216 Status", + "status: done", + "task: armature.assign_to_collection operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one armature with source and target bone collections, one parent bone, and one selected child initially assigned only to the source collection.", + "- Desktop runs `ARMATURE_OT_assign_to_collection(collection_index=1)` with `poll=true` and `FINISHED`, assigning the child to the target collection and preserving both memberships through save/reopen.", + "- The Main reader now exposes bounded armature `boneCollections` entries with collection name/index and member bone IDs. No other collection, editor, or browser behavior changed." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1804, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 451 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00217.md", + "bytes": 1804, + "lines": 38, + "tokens": 451 + }, + { + "path": "tests/golden/M16-GAP-00216/manifest.json", + "bytes": 2815, + "lines": 70, + "tokens": 704 + }, + { + "path": "docs/status/M16-GAP-00216.md", + "bytes": 1172, + "lines": 20, + "tokens": 293 + } + ], + "sourceTokens": 1990, + "evidenceFiles": 1, + "evidenceBytes": 1252, + "evidenceTokens": 313, + "totalTokens": 2303, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3327, + "serializedContextTokens": 757, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00218/armature-bone-primitive-add-desktop-report.json b/tests/golden/M16-GAP-00218/armature-bone-primitive-add-desktop-report.json new file mode 100644 index 00000000..748f2a5d --- /dev/null +++ b/tests/golden/M16-GAP-00218/armature-bone-primitive-add-desktop-report.json @@ -0,0 +1,63 @@ +{ + "after": { + "armature": "WebGapArmaturePrimitiveArmature", + "bones": [ + { + "head": [ + 1.5, + -2.0, + 0.75 + ], + "name": "WebGapArmaturePrimitiveBone", + "tail": [ + 1.5, + -2.0, + 3.25 + ], + "useDeform": false + } + ], + "cursor": [ + 1.5, + -2.0, + 0.75 + ], + "object": "WebGapArmaturePrimitiveObject" + }, + "alreadyAdded": true, + "before": { + "armature": "WebGapArmaturePrimitiveArmature", + "bones": [ + { + "head": [ + 1.5, + -2.0, + 0.75 + ], + "name": "WebGapArmaturePrimitiveBone", + "tail": [ + 1.5, + -2.0, + 3.25 + ], + "useDeform": false + } + ], + "cursor": [ + 1.5, + -2.0, + 0.75 + ], + "object": "WebGapArmaturePrimitiveObject" + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00218-operator-armature.bone_primitive_add.blend", + "fixtureSha256": "b6857f1212fd591bc78dea3451ee38da3547a3415c32637f974c8187bfd28f73", + "mainMutation": "ALREADY_BONE_CREATED_AT_CURSOR", + "operation": "ARMATURE_BONE_PRIMITIVE_ADD_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00218" +} diff --git a/tests/golden/M16-GAP-00218/armature-bone-primitive-add-local-exact-report.json b/tests/golden/M16-GAP-00218/armature-bone-primitive-add-local-exact-report.json new file mode 100644 index 00000000..1b3f4aab --- /dev/null +++ b/tests/golden/M16-GAP-00218/armature-bone-primitive-add-local-exact-report.json @@ -0,0 +1,40 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00218", + "operation": "ARMATURE_BONE_PRIMITIVE_ADD_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00218-operator-armature.bone_primitive_add.blend", + "sha256": "b6857f1212fd591bc78dea3451ee38da3547a3415c32637f974c8187bfd28f73" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00218/armature-bone-primitive-add-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "ALREADY_BONE_CREATED_AT_CURSOR" + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmaturePrimitiveArmature", + "bone": { + "id": "bone:armature:WebGapArmaturePrimitiveArmature:WebGapArmaturePrimitiveBone", + "name": "WebGapArmaturePrimitiveBone", + "head": [ + 1.5, + -2, + 0.75 + ], + "tail": [ + 1.5, + -2, + 3.25 + ] + } + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00219" +} diff --git a/tests/golden/M16-GAP-00218/manifest.json b/tests/golden/M16-GAP-00218/manifest.json new file mode 100644 index 00000000..ba38c2e6 --- /dev/null +++ b/tests/golden/M16-GAP-00218/manifest.json @@ -0,0 +1,69 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00218", + "parentTask": "M16-GAP-00217", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_BONE_PRIMITIVE_ADD_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00217/manifest.json", + "sha256": "2edf78e7629b31c116389be652225e4279c0fd40bbbb58debb3d3bb1d66c8f01" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00218-operator-armature.bone_primitive_add.blend", + "sha256": "b6857f1212fd591bc78dea3451ee38da3547a3415c32637f974c8187bfd28f73" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00218.py", + "sha256": "a59d8918c3372dc41d1fdf06efea2fa8bdaadcadd0a1602af029d3682a7cf924" + }, + "desktopChecker": { + "path": "tools/web/check-action-armature-bone-primitive-add-desktop.py", + "sha256": "fa0d91a10c5d2dc9cae127c02927fc98be37110f25e3ab3570cd7cf733ce329e" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "6c18288b9d2ffba39e4485c5cf6c556e6952430d4d153b07763ba205bdec6f56" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "c56d254a74ace9664104f139692cf37f825547301824872bfd8db95f6ad2117b" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "82b9fb9488a20543f0db1235b18a7c28b2593ac498c152a12f45f8299ced1927" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "82b9fb9488a20543f0db1235b18a7c28b2593ac498c152a12f45f8299ced1927" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "wasmJsPublic": { + "path": "web/app/public/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00218/armature-bone-primitive-add-desktop-report.json", + "sha256": "7176938d759ad47b1c4fd6a4c4b73cc3af615518f30540d535a0f997bfdfc3ef" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00218/armature-bone-primitive-add-local-exact-report.json", + "sha256": "042cee11ebc0ccac3108e51773fb486c08c8ef6f745d018b0abb6469678f4fb7" + }, + "status": { + "path": "docs/status/M16-GAP-00218.md", + "sha256": "44c52e0bbeabf7ba66894db6f51f04a5ab793c921483796176568c5d25f97711" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00218/task-context.json", + "sha256": "42735f344b07d948bd9f302e4e21ae7580ca97506d5903667b56c24b4af02d48" + } + }, + "nextTask": "M16-GAP-00219" +} diff --git a/tests/golden/M16-GAP-00218/task-context.json b/tests/golden/M16-GAP-00218/task-context.json new file mode 100644 index 00000000..fd08cead --- /dev/null +++ b/tests/golden/M16-GAP-00218/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00218", + "parentTask": "M16-GAP-00217", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.bone_primitive_add data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.bone_primitive_add", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00218.py -- tests/files/web/generated/M16-GAP-00218-operator-armature.bone_primitive_add.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00218", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00218" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00218.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2104, + "contextRemainingTokens": 525 + }, + "source": { + "bytes": 7800, + "tokens": 1951 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00218.py", + "bytes": 871, + "tokens": 218 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00218-operator-armature.bone_primitive_add.blend", + "bytes": 86250, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 237877, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 565412, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00218/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00218.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00218/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 871, + "tokens": 218 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00219", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00218.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00217/manifest.json", + "parentStatus": "docs/status/M16-GAP-00217.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00218.md", + "tests/golden/M16-GAP-00217/manifest.json", + "docs/status/M16-GAP-00217.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00217", + "parentTask": "M16-GAP-00216", + "status": "done", + "nextTask": "M16-GAP-00218", + "artifactCount": 14 + }, + "statusSummary": [ + "# M16-GAP-00217 Status", + "status: done", + "task: armature.autoside_names operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one armature with two selected bones on opposite sides of the X axis.", + "- Desktop runs `ARMATURE_OT_autoside_names(type='XAXIS')` with `poll=true` and `FINISHED`, naming the positive-X bone `.L` and the negative-X bone `.R`, then preserves both names through save/reopen.", + "- The existing Main reader exposes the same armature bone names; no new reader field, data-block, editor, or browser behavior was added." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1824, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 456 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00218.md", + "bytes": 1824, + "lines": 38, + "tokens": 456 + }, + { + "path": "tests/golden/M16-GAP-00217/manifest.json", + "bytes": 2785, + "lines": 70, + "tokens": 697 + }, + { + "path": "docs/status/M16-GAP-00217.md", + "bytes": 1023, + "lines": 20, + "tokens": 256 + } + ], + "sourceTokens": 1951, + "evidenceFiles": 1, + "evidenceBytes": 871, + "evidenceTokens": 218, + "totalTokens": 2169, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3193, + "serializedContextTokens": 759, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00219/armature-calculate-roll-desktop-report.json b/tests/golden/M16-GAP-00219/armature-calculate-roll-desktop-report.json new file mode 100644 index 00000000..b0d06a5e --- /dev/null +++ b/tests/golden/M16-GAP-00219/armature-calculate-roll-desktop-report.json @@ -0,0 +1,88 @@ +{ + "after": { + "armature": "WebGapArmatureCalculateRollArmature", + "bones": [ + { + "head": [ + 0.0, + 0.0, + 0.0 + ], + "matrix": [ + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + -1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0 + ], + "name": "WebGapArmatureCalculateRollBone", + "tail": [ + 0.0, + 2.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureCalculateRollObject" + }, + "alreadyCalculated": false, + "before": { + "armature": "WebGapArmatureCalculateRollArmature", + "bones": [ + { + "head": [ + 0.0, + 0.0, + 0.0 + ], + "matrix": [ + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0 + ], + "name": "WebGapArmatureCalculateRollBone", + "tail": [ + 0.0, + 2.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureCalculateRollObject" + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00219-operator-armature.calculate_roll.blend", + "fixtureSha256": "7c6f851456147c2e69de3ddf1136885ccff9bd907cd480a5af5fd81f5769c862", + "mainMutation": "ROLL_CALCULATED_GLOBAL_POS_X", + "operation": "ARMATURE_CALCULATE_ROLL_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "roll": 1.570796, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00219" +} diff --git a/tests/golden/M16-GAP-00219/armature-calculate-roll-local-exact-report.json b/tests/golden/M16-GAP-00219/armature-calculate-roll-local-exact-report.json new file mode 100644 index 00000000..2107d274 --- /dev/null +++ b/tests/golden/M16-GAP-00219/armature-calculate-roll-local-exact-report.json @@ -0,0 +1,59 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00219", + "operation": "ARMATURE_CALCULATE_ROLL_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00219-operator-armature.calculate_roll.blend", + "sha256": "7c6f851456147c2e69de3ddf1136885ccff9bd907cd480a5af5fd81f5769c862" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00219/armature-calculate-roll-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "ROLL_CALCULATED_GLOBAL_POS_X", + "roll": 1.570796 + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureCalculateRollArmature", + "bone": { + "id": "bone:armature:WebGapArmatureCalculateRollArmature:WebGapArmatureCalculateRollBone", + "name": "WebGapArmatureCalculateRollBone", + "head": [ + 0, + 0, + 0 + ], + "tail": [ + 0, + 2, + 0 + ], + "restMatrix": [ + 7.549790126404332e-8, + 0, + -1, + 0, + 0, + 1, + 0, + 0, + 1, + 0, + 7.549790126404332e-8, + 0, + 0, + 0, + 0, + 1 + ] + } + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00220" +} diff --git a/tests/golden/M16-GAP-00219/manifest.json b/tests/golden/M16-GAP-00219/manifest.json new file mode 100644 index 00000000..307ccd05 --- /dev/null +++ b/tests/golden/M16-GAP-00219/manifest.json @@ -0,0 +1,27 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00219", + "parentTask": "M16-GAP-00218", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_CALCULATE_ROLL_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": {"path": "tests/golden/M16-GAP-00218/manifest.json", "sha256": "ed1737fa32a6d1bb5bdaca5e5eb35ff5006fbe14eeba59d96e6b24e64cd7bcc9"}, + "fixture": {"path": "tests/files/web/generated/M16-GAP-00219-operator-armature.calculate_roll.blend", "sha256": "7c6f851456147c2e69de3ddf1136885ccff9bd907cd480a5af5fd81f5769c862"}, + "generator": {"path": "tools/web/generated/M16-GAP-00219.py", "sha256": "97a7da237cc8f8154f08b96e2ba6b5d6e608a6bc1b0bfa20fe165c00a3bb68b7"}, + "desktopChecker": {"path": "tools/web/check-action-armature-calculate-roll-desktop.py", "sha256": "570471197617ea452db37d8d972f372db07de15c3f78fd934905ecdbfe3e3a7f"}, + "webChecker": {"path": "tools/web/check-generated-gap.mjs", "sha256": "62ad26cec00dd5a3d59a7ddbfbfa9cd0b7fbae0f0b252b6e40ce9ae73d027f98"}, + "reader": {"path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "c56d254a74ace9664104f139692cf37f825547301824872bfd8db95f6ad2117b"}, + "wasm": {"path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "82b9fb9488a20543f0db1235b18a7c28b2593ac498c152a12f45f8299ced1927"}, + "wasmPublic": {"path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "82b9fb9488a20543f0db1235b18a7c28b2593ac498c152a12f45f8299ced1927"}, + "wasmJs": {"path": "web/app/src/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "wasmJsPublic": {"path": "web/app/public/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "desktopReport": {"path": "tests/golden/M16-GAP-00219/armature-calculate-roll-desktop-report.json", "sha256": "b4ea9eee1596aa99d045e7064b96a763faf7b29d6f7c79b95045d75ff26dd922"}, + "webReport": {"path": "tests/golden/M16-GAP-00219/armature-calculate-roll-local-exact-report.json", "sha256": "1c888b9739c03fcd5aed2b1de20a2aea3871c80cff6b6fcb464e09a5478f5c23"}, + "status": {"path": "docs/status/M16-GAP-00219.md", "sha256": "66adfb1390f39daeeedc52b0db0cfe1a4542af738ea6c5944a292faa53936e57"}, + "taskContext": {"path": "tests/golden/M16-GAP-00219/task-context.json", "sha256": "1c6a55bdc4fd17687a7695b44fba71bd5ad26644919dbcd363b6a7dec07cbde9"} + }, + "nextTask": "M16-GAP-00220" +} diff --git a/tests/golden/M16-GAP-00219/task-context.json b/tests/golden/M16-GAP-00219/task-context.json new file mode 100644 index 00000000..85dd71e0 --- /dev/null +++ b/tests/golden/M16-GAP-00219/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00219", + "parentTask": "M16-GAP-00218", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.calculate_roll data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.calculate_roll", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00219.py -- tests/files/web/generated/M16-GAP-00219-operator-armature.calculate_roll.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00219", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00219" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00219.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2070, + "contextRemainingTokens": 516 + }, + "source": { + "bytes": 7834, + "tokens": 1960 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00219.py", + "bytes": 1104, + "tokens": 276 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00219-operator-armature.calculate_roll.blend", + "bytes": 86240, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 237877, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 569706, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00219/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00219.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00219/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1104, + "tokens": 276 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00220", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00219.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00218/manifest.json", + "parentStatus": "docs/status/M16-GAP-00218.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00219.md", + "tests/golden/M16-GAP-00218/manifest.json", + "docs/status/M16-GAP-00218.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00218", + "parentTask": "M16-GAP-00217", + "status": "done", + "nextTask": "M16-GAP-00219", + "artifactCount": 14 + }, + "statusSummary": [ + "# M16-GAP-00218 Status", + "status: done", + "task: armature.bone_primitive_add operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one empty armature object and a fixed 3D cursor at `(1.5, -2.0, 0.75)`.", + "- Desktop runs `ARMATURE_OT_bone_primitive_add(name, length=2.5, align='UP', space='OBJECT', use_deform=false)` with `poll=true` and `FINISHED`, creating the named bone at the cursor and preserving its head/tail through save/reopen.", + "- The existing Main reader exposes the same armature bone name and coordinates; no new reader field, data-block, editor, or browser behavior was added." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1804, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 451 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00219.md", + "bytes": 1804, + "lines": 38, + "tokens": 451 + }, + { + "path": "tests/golden/M16-GAP-00218/manifest.json", + "bytes": 2805, + "lines": 70, + "tokens": 702 + }, + { + "path": "docs/status/M16-GAP-00218.md", + "bytes": 1057, + "lines": 20, + "tokens": 265 + } + ], + "sourceTokens": 1960, + "evidenceFiles": 1, + "evidenceBytes": 1104, + "evidenceTokens": 276, + "totalTokens": 2236, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3260, + "serializedContextTokens": 757, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00220/armature-click-extrude-desktop-report.json b/tests/golden/M16-GAP-00220/armature-click-extrude-desktop-report.json new file mode 100644 index 00000000..186228e0 --- /dev/null +++ b/tests/golden/M16-GAP-00220/armature-click-extrude-desktop-report.json @@ -0,0 +1,207 @@ +{ + "after": { + "armature": "WebGapArmatureClickExtrudeArmature", + "bones": [ + { + "head": [ + 0.0, + 0.0, + 0.0 + ], + "headRaw": [ + 0.0, + 0.0, + 0.0 + ], + "matrix": [ + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0 + ], + "name": "WebGapArmatureClickExtrudeBone", + "parent": null, + "tail": [ + 0.0, + 2.0, + 0.0 + ], + "tailRaw": [ + 0.0, + 2.0, + 0.0 + ], + "useConnect": false + }, + { + "head": [ + 0.0, + 2.0, + 0.0 + ], + "headRaw": [ + 0.0, + 0.0, + 0.0 + ], + "matrix": [ + -0.0, + 0.83205, + -0.5547, + 0.0, + -1.0, + 0.0, + 0.0, + 2.0, + 0.0, + 0.5547, + 0.83205, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0 + ], + "name": "WebGapArmatureClickExtrudeBone.001", + "parent": "WebGapArmatureClickExtrudeBone", + "tail": [ + 1.5, + 2.0, + 1.0 + ], + "tailRaw": [ + 1.5, + 0.0, + 1.0 + ], + "useConnect": true + } + ], + "cursor": [ + 1.5, + 2.0, + 1.0 + ], + "object": "WebGapArmatureClickExtrudeObject" + }, + "alreadyExtruded": true, + "before": { + "armature": "WebGapArmatureClickExtrudeArmature", + "bones": [ + { + "head": [ + 0.0, + 0.0, + 0.0 + ], + "headRaw": [ + 0.0, + 0.0, + 0.0 + ], + "matrix": [ + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0 + ], + "name": "WebGapArmatureClickExtrudeBone", + "parent": null, + "tail": [ + 0.0, + 2.0, + 0.0 + ], + "tailRaw": [ + 0.0, + 2.0, + 0.0 + ], + "useConnect": false + }, + { + "head": [ + 0.0, + 2.0, + 0.0 + ], + "headRaw": [ + 0.0, + 0.0, + 0.0 + ], + "matrix": [ + -0.0, + 0.83205, + -0.5547, + 0.0, + -1.0, + 0.0, + 0.0, + 2.0, + 0.0, + 0.5547, + 0.83205, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0 + ], + "name": "WebGapArmatureClickExtrudeBone.001", + "parent": "WebGapArmatureClickExtrudeBone", + "tail": [ + 1.5, + 2.0, + 1.0 + ], + "tailRaw": [ + 1.5, + 0.0, + 1.0 + ], + "useConnect": true + } + ], + "cursor": [ + 1.5, + 2.0, + 1.0 + ], + "object": "WebGapArmatureClickExtrudeObject" + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00220-operator-armature.click_extrude.blend", + "fixtureSha256": "7b9ded05ba9a6bb02b729ef474ec3f37a67f41fa0e8da53c7e3c58a56b64e065", + "mainMutation": "ALREADY_CHILD_EXTRUDED_TO_CURSOR", + "operation": "ARMATURE_CLICK_EXTRUDE_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00220" +} diff --git a/tests/golden/M16-GAP-00220/armature-click-extrude-local-exact-report.json b/tests/golden/M16-GAP-00220/armature-click-extrude-local-exact-report.json new file mode 100644 index 00000000..5cd12153 --- /dev/null +++ b/tests/golden/M16-GAP-00220/armature-click-extrude-local-exact-report.json @@ -0,0 +1,78 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00220", + "operation": "ARMATURE_CLICK_EXTRUDE_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00220-operator-armature.click_extrude.blend", + "sha256": "7b9ded05ba9a6bb02b729ef474ec3f37a67f41fa0e8da53c7e3c58a56b64e065" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00220/armature-click-extrude-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "ALREADY_CHILD_EXTRUDED_TO_CURSOR" + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureClickExtrudeArmature", + "parentBone": { + "id": "bone:armature:WebGapArmatureClickExtrudeArmature:WebGapArmatureClickExtrudeBone", + "name": "WebGapArmatureClickExtrudeBone", + "head": [ + 0, + 0, + 0 + ], + "tail": [ + 0, + 2, + 0 + ] + }, + "extrudedBone": { + "id": "bone:armature:WebGapArmatureClickExtrudeArmature:WebGapArmatureClickExtrudeBone.001", + "name": "WebGapArmatureClickExtrudeBone.001", + "parentId": "bone:armature:WebGapArmatureClickExtrudeArmature:WebGapArmatureClickExtrudeBone", + "head": [ + 0, + 0, + 0 + ], + "tail": [ + 1.5, + 0, + 1 + ], + "restMatrix": [ + -1.0803341865539551e-7, + -1, + 5.960464477539063e-8, + 0, + 0.8320503234863281, + 0, + 0.5547001957893372, + 0, + -0.5547002553939819, + 8.940696716308594e-8, + 0.8320503234863281, + 0, + 0, + 2, + 0, + 1 + ] + }, + "armatureSpaceEndpoint": [ + 1.5, + 2, + 1 + ] + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00221" +} diff --git a/tests/golden/M16-GAP-00220/manifest.json b/tests/golden/M16-GAP-00220/manifest.json new file mode 100644 index 00000000..074b5996 --- /dev/null +++ b/tests/golden/M16-GAP-00220/manifest.json @@ -0,0 +1,27 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00220", + "parentTask": "M16-GAP-00219", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_CLICK_EXTRUDE_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": {"path": "tests/golden/M16-GAP-00219/manifest.json", "sha256": "3a57247b3f1ef1b2ebad1b59e81d18063e98210b653889c975e3b93f088ef820"}, + "fixture": {"path": "tests/files/web/generated/M16-GAP-00220-operator-armature.click_extrude.blend", "sha256": "7b9ded05ba9a6bb02b729ef474ec3f37a67f41fa0e8da53c7e3c58a56b64e065"}, + "generator": {"path": "tools/web/generated/M16-GAP-00220.py", "sha256": "3af1d354e35b31da18a187e0ef5f5e2b5a2f11111058ff1dc3648f6134679b41"}, + "desktopChecker": {"path": "tools/web/check-action-armature-click-extrude-desktop.py", "sha256": "2fc6347da08d334e4b28a5316d1db45d189021ee38f4e5f8574e3a66cc177d51"}, + "webChecker": {"path": "tools/web/check-generated-gap.mjs", "sha256": "5fa622a7df094c82b26aa596a27f167302250f5d3f3d7db785ef9bd6da44a840"}, + "reader": {"path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "c56d254a74ace9664104f139692cf37f825547301824872bfd8db95f6ad2117b"}, + "wasm": {"path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "82b9fb9488a20543f0db1235b18a7c28b2593ac498c152a12f45f8299ced1927"}, + "wasmPublic": {"path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "82b9fb9488a20543f0db1235b18a7c28b2593ac498c152a12f45f8299ced1927"}, + "wasmJs": {"path": "web/app/src/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "wasmJsPublic": {"path": "web/app/public/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "desktopReport": {"path": "tests/golden/M16-GAP-00220/armature-click-extrude-desktop-report.json", "sha256": "5fe98d54a481df86862f9f3bcdcb854fa9ea4abfb7de9de6819a07beb2bdb4af"}, + "webReport": {"path": "tests/golden/M16-GAP-00220/armature-click-extrude-local-exact-report.json", "sha256": "dbe683725d4e05220b6abaf837450c31f66cb8c82eb4ef75130c332ba98125d8"}, + "status": {"path": "docs/status/M16-GAP-00220.md", "sha256": "5c5274c86b019432f5b22e474947272001ad2af14b2437b577578547d2230511"}, + "taskContext": {"path": "tests/golden/M16-GAP-00220/task-context.json", "sha256": "dfba3c91da5262603b2958c8011b317a5edd25bd1cf5b1a58cbe6bfd224024f7"} + }, + "nextTask": "M16-GAP-00221" +} diff --git a/tests/golden/M16-GAP-00220/task-context.json b/tests/golden/M16-GAP-00220/task-context.json new file mode 100644 index 00000000..a7fe6843 --- /dev/null +++ b/tests/golden/M16-GAP-00220/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00220", + "parentTask": "M16-GAP-00219", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.click_extrude data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.click_extrude", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00220.py -- tests/files/web/generated/M16-GAP-00220-operator-armature.click_extrude.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00220", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00220" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00220.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2359, + "contextRemainingTokens": 588 + }, + "source": { + "bytes": 7545, + "tokens": 1888 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00220.py", + "bytes": 1239, + "tokens": 310 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00220-operator-armature.click_extrude.blend", + "bytes": 86416, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 237877, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 574890, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00220/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00220.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00220/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1239, + "tokens": 310 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00221", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00220.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00219/manifest.json", + "parentStatus": "docs/status/M16-GAP-00219.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00220.md", + "tests/golden/M16-GAP-00219/manifest.json", + "docs/status/M16-GAP-00219.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00219", + "parentTask": "M16-GAP-00218", + "status": "done", + "nextTask": "M16-GAP-00220", + "artifactCount": 14 + }, + "statusSummary": [ + "# M16-GAP-00219 Status", + "status: done", + "task: armature.calculate_roll operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one selected bone aligned along +Y with zero initial roll.", + "- Desktop runs `ARMATURE_OT_calculate_roll(type='GLOBAL_POS_X', axis_flip=false, axis_only=false)` with `poll=true` and `FINISHED`, producing a roll of approximately `pi/2` and preserving the resulting matrix through save/reopen.", + "- The existing Main reader exposes the same armature bone head/tail and rest matrix; no new reader field, data-block, editor, or browser behavior was added." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1799, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 450 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00220.md", + "bytes": 1799, + "lines": 38, + "tokens": 450 + }, + { + "path": "tests/golden/M16-GAP-00219/manifest.json", + "bytes": 2533, + "lines": 28, + "tokens": 634 + }, + { + "path": "docs/status/M16-GAP-00219.md", + "bytes": 1045, + "lines": 20, + "tokens": 262 + } + ], + "sourceTokens": 1888, + "evidenceFiles": 1, + "evidenceBytes": 1239, + "evidenceTokens": 310, + "totalTokens": 2198, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3222, + "serializedContextTokens": 756, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00221/armature-collection-add-desktop-report.json b/tests/golden/M16-GAP-00221/armature-collection-add-desktop-report.json new file mode 100644 index 00000000..62e72827 --- /dev/null +++ b/tests/golden/M16-GAP-00221/armature-collection-add-desktop-report.json @@ -0,0 +1,51 @@ +{ + "after": { + "activeIndex": 1, + "armature": "WebGapArmatureCollectionAddArmature", + "collections": [ + { + "bones": [ + "WebGapArmatureCollectionAddBone" + ], + "index": 0, + "name": "WebGapArmatureCollectionAddExisting" + }, + { + "bones": [], + "index": 1, + "name": "Bones" + } + ], + "object": "WebGapArmatureCollectionAddObject" + }, + "alreadyAdded": true, + "before": { + "activeIndex": 1, + "armature": "WebGapArmatureCollectionAddArmature", + "collections": [ + { + "bones": [ + "WebGapArmatureCollectionAddBone" + ], + "index": 0, + "name": "WebGapArmatureCollectionAddExisting" + }, + { + "bones": [], + "index": 1, + "name": "Bones" + } + ], + "object": "WebGapArmatureCollectionAddObject" + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00221-operator-armature.collection_add.blend", + "fixtureSha256": "a081193e2c16de9c072b0b7cc57f9d7b5f3f12863fcb2f06e16641cebdcf0b34", + "mainMutation": "ALREADY_BONE_COLLECTION_ADDED", + "operation": "ARMATURE_COLLECTION_ADD_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00221" +} diff --git a/tests/golden/M16-GAP-00221/armature-collection-add-local-exact-report.json b/tests/golden/M16-GAP-00221/armature-collection-add-local-exact-report.json new file mode 100644 index 00000000..50974d42 --- /dev/null +++ b/tests/golden/M16-GAP-00221/armature-collection-add-local-exact-report.json @@ -0,0 +1,40 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00221", + "operation": "ARMATURE_COLLECTION_ADD_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00221-operator-armature.collection_add.blend", + "sha256": "a081193e2c16de9c072b0b7cc57f9d7b5f3f12863fcb2f06e16641cebdcf0b34" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00221/armature-collection-add-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "ALREADY_BONE_COLLECTION_ADDED" + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureCollectionAddArmature", + "existingCollection": { + "id": "bone_collection:armature:WebGapArmatureCollectionAddArmature:WebGapArmatureCollectionAddExisting", + "name": "WebGapArmatureCollectionAddExisting", + "index": 0, + "boneIds": [ + "bone:armature:WebGapArmatureCollectionAddArmature:WebGapArmatureCollectionAddBone" + ] + }, + "addedCollection": { + "id": "bone_collection:armature:WebGapArmatureCollectionAddArmature:Bones", + "name": "Bones", + "index": 1, + "boneIds": [] + } + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00222" +} diff --git a/tests/golden/M16-GAP-00221/manifest.json b/tests/golden/M16-GAP-00221/manifest.json new file mode 100644 index 00000000..f5c018a5 --- /dev/null +++ b/tests/golden/M16-GAP-00221/manifest.json @@ -0,0 +1,27 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00221", + "parentTask": "M16-GAP-00220", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_COLLECTION_ADD_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": {"path": "tests/golden/M16-GAP-00220/manifest.json", "sha256": "95fdbc58ff2d2d7db0462090f823bcecbc8e3e79642134eab568a8d1e41f82b0"}, + "fixture": {"path": "tests/files/web/generated/M16-GAP-00221-operator-armature.collection_add.blend", "sha256": "a081193e2c16de9c072b0b7cc57f9d7b5f3f12863fcb2f06e16641cebdcf0b34"}, + "generator": {"path": "tools/web/generated/M16-GAP-00221.py", "sha256": "b2eea8780bb0095ab12b3a0f6e437054f6d01450a9a111030da0724b134bdc69"}, + "desktopChecker": {"path": "tools/web/check-action-armature-collection-add-desktop.py", "sha256": "8acf8ab1c9b9e27bc83fe568edd0d418b6c824c72b539126561955f05e5ba9f8"}, + "webChecker": {"path": "tools/web/check-generated-gap.mjs", "sha256": "89924d3436c63db88e7765d0ea52e5604f4470cb62011ae36d594cf558e794d8"}, + "reader": {"path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "c56d254a74ace9664104f139692cf37f825547301824872bfd8db95f6ad2117b"}, + "wasm": {"path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "82b9fb9488a20543f0db1235b18a7c28b2593ac498c152a12f45f8299ced1927"}, + "wasmPublic": {"path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "82b9fb9488a20543f0db1235b18a7c28b2593ac498c152a12f45f8299ced1927"}, + "wasmJs": {"path": "web/app/src/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "wasmJsPublic": {"path": "web/app/public/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "desktopReport": {"path": "tests/golden/M16-GAP-00221/armature-collection-add-desktop-report.json", "sha256": "ccbe838e9d73ce8d63f7b81b5d7b28acf038b802fd5f76c5b806f21925df6e3b"}, + "webReport": {"path": "tests/golden/M16-GAP-00221/armature-collection-add-local-exact-report.json", "sha256": "edd1a7688e96982df6a0b3216784c437d668c70fb817e58f11be9a6be6a10dcd"}, + "status": {"path": "docs/status/M16-GAP-00221.md", "sha256": "56727977918f6e76af983feeeff59da94ea0e1d020569acfe6eb5ff8fcce49e4"}, + "taskContext": {"path": "tests/golden/M16-GAP-00221/task-context.json", "sha256": "33c38758f90a7a49b0864dbccd1176d04ae0057829e7a1aed56ee8ff66e57610"} + }, + "nextTask": "M16-GAP-00222" +} diff --git a/tests/golden/M16-GAP-00221/task-context.json b/tests/golden/M16-GAP-00221/task-context.json new file mode 100644 index 00000000..f0656633 --- /dev/null +++ b/tests/golden/M16-GAP-00221/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00221", + "parentTask": "M16-GAP-00220", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.collection_add data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.collection_add", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00221.py -- tests/files/web/generated/M16-GAP-00221-operator-armature.collection_add.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00221", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00221" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00221.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2315, + "contextRemainingTokens": 578 + }, + "source": { + "bytes": 7589, + "tokens": 1898 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00221.py", + "bytes": 1290, + "tokens": 323 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00221-operator-armature.collection_add.blend", + "bytes": 86279, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 237877, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 579287, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00221/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00221.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00221/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1290, + "tokens": 323 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00222", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00221.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00220/manifest.json", + "parentStatus": "docs/status/M16-GAP-00220.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00221.md", + "tests/golden/M16-GAP-00220/manifest.json", + "docs/status/M16-GAP-00220.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00220", + "parentTask": "M16-GAP-00219", + "status": "done", + "nextTask": "M16-GAP-00221", + "artifactCount": 14 + }, + "statusSummary": [ + "# M16-GAP-00220 Status", + "status: done", + "task: armature.click_extrude operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one selected armature bone from `(0, 0, 0)` to `(0, 2, 0)` and a fixed cursor at `(1.5, 2.0, 1.0)`.", + "- Desktop runs `ARMATURE_OT_click_extrude` with `poll=true` and `FINISHED`, creating a connected `.001` child whose armature-space tail reaches the cursor and preserving it through save/reopen.", + "- The existing Main reader exposes the parent relationship, raw child coordinates, and rest matrix; the comparator derives the same armature-space endpoint without changing unrelated armature fields." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1804, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 451 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00221.md", + "bytes": 1804, + "lines": 38, + "tokens": 451 + }, + { + "path": "tests/golden/M16-GAP-00220/manifest.json", + "bytes": 2528, + "lines": 28, + "tokens": 632 + }, + { + "path": "docs/status/M16-GAP-00220.md", + "bytes": 1089, + "lines": 20, + "tokens": 273 + } + ], + "sourceTokens": 1898, + "evidenceFiles": 1, + "evidenceBytes": 1290, + "evidenceTokens": 323, + "totalTokens": 2221, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3245, + "serializedContextTokens": 757, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00222/armature-collection-assign-desktop-report.json b/tests/golden/M16-GAP-00222/armature-collection-assign-desktop-report.json new file mode 100644 index 00000000..6dd21efe --- /dev/null +++ b/tests/golden/M16-GAP-00222/armature-collection-assign-desktop-report.json @@ -0,0 +1,53 @@ +{ + "after": { + "armature": "WebGapArmatureCollectionAssignArmature", + "collections": [ + { + "bones": [ + "WebGapArmatureCollectionAssignBone" + ], + "index": 0, + "name": "WebGapArmatureCollectionAssignSource" + }, + { + "bones": [ + "WebGapArmatureCollectionAssignBone" + ], + "index": 1, + "name": "WebGapArmatureCollectionAssignTarget" + } + ], + "object": "WebGapArmatureCollectionAssignObject" + }, + "alreadyAssigned": true, + "before": { + "armature": "WebGapArmatureCollectionAssignArmature", + "collections": [ + { + "bones": [ + "WebGapArmatureCollectionAssignBone" + ], + "index": 0, + "name": "WebGapArmatureCollectionAssignSource" + }, + { + "bones": [ + "WebGapArmatureCollectionAssignBone" + ], + "index": 1, + "name": "WebGapArmatureCollectionAssignTarget" + } + ], + "object": "WebGapArmatureCollectionAssignObject" + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00222-operator-armature.collection_assign.blend", + "fixtureSha256": "c742316be6dbd00fe3d5caf804b41067839a344a0725fe3c3aa78d1ebc024b8a", + "mainMutation": "ALREADY_BONE_ASSIGNED_TO_TARGET_COLLECTION", + "operation": "ARMATURE_COLLECTION_ASSIGN_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00222" +} diff --git a/tests/golden/M16-GAP-00222/armature-collection-assign-local-exact-report.json b/tests/golden/M16-GAP-00222/armature-collection-assign-local-exact-report.json new file mode 100644 index 00000000..f6810296 --- /dev/null +++ b/tests/golden/M16-GAP-00222/armature-collection-assign-local-exact-report.json @@ -0,0 +1,41 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00222", + "operation": "ARMATURE_COLLECTION_ASSIGN_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00222-operator-armature.collection_assign.blend", + "sha256": "c742316be6dbd00fe3d5caf804b41067839a344a0725fe3c3aa78d1ebc024b8a" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00222/armature-collection-assign-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "ALREADY_BONE_ASSIGNED_TO_TARGET_COLLECTION" + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureCollectionAssignArmature", + "assignedBoneId": "bone:armature:WebGapArmatureCollectionAssignArmature:WebGapArmatureCollectionAssignBone", + "sourceCollection": { + "id": "bone_collection:armature:WebGapArmatureCollectionAssignArmature:WebGapArmatureCollectionAssignSource", + "name": "WebGapArmatureCollectionAssignSource", + "boneIds": [ + "bone:armature:WebGapArmatureCollectionAssignArmature:WebGapArmatureCollectionAssignBone" + ] + }, + "targetCollection": { + "id": "bone_collection:armature:WebGapArmatureCollectionAssignArmature:WebGapArmatureCollectionAssignTarget", + "name": "WebGapArmatureCollectionAssignTarget", + "boneIds": [ + "bone:armature:WebGapArmatureCollectionAssignArmature:WebGapArmatureCollectionAssignBone" + ] + } + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00223" +} diff --git a/tests/golden/M16-GAP-00222/manifest.json b/tests/golden/M16-GAP-00222/manifest.json new file mode 100644 index 00000000..7383ce87 --- /dev/null +++ b/tests/golden/M16-GAP-00222/manifest.json @@ -0,0 +1,27 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00222", + "parentTask": "M16-GAP-00221", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_COLLECTION_ASSIGN_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": {"path": "tests/golden/M16-GAP-00221/manifest.json", "sha256": "74053893965d4a9f206a601edb4ebd1c7fa1e25d8545924e7880b1ad25fada1d"}, + "fixture": {"path": "tests/files/web/generated/M16-GAP-00222-operator-armature.collection_assign.blend", "sha256": "c742316be6dbd00fe3d5caf804b41067839a344a0725fe3c3aa78d1ebc024b8a"}, + "generator": {"path": "tools/web/generated/M16-GAP-00222.py", "sha256": "74ddcb85092783361facd3388f3bfae2ea1794b6d1395f2381928f8e296d3c5c"}, + "desktopChecker": {"path": "tools/web/check-action-armature-collection-assign-desktop.py", "sha256": "92c6b8d031631ace79523ef4200508621aa8bd0b9ae2d5a8cd84a9cdbd91a559"}, + "webChecker": {"path": "tools/web/check-generated-gap.mjs", "sha256": "ffb30925fa7f66ec1df8279dc29ff8933119ca8d7d09e1ad9062f4096b79d020"}, + "reader": {"path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "c56d254a74ace9664104f139692cf37f825547301824872bfd8db95f6ad2117b"}, + "wasm": {"path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "82b9fb9488a20543f0db1235b18a7c28b2593ac498c152a12f45f8299ced1927"}, + "wasmPublic": {"path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "82b9fb9488a20543f0db1235b18a7c28b2593ac498c152a12f45f8299ced1927"}, + "wasmJs": {"path": "web/app/src/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "wasmJsPublic": {"path": "web/app/public/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "desktopReport": {"path": "tests/golden/M16-GAP-00222/armature-collection-assign-desktop-report.json", "sha256": "db90ed0998768c9009f1c19b9eec12392d5c73bc7ca914a780bdd6721b41e932"}, + "webReport": {"path": "tests/golden/M16-GAP-00222/armature-collection-assign-local-exact-report.json", "sha256": "1b8650f03a1d51cd58f28be3a2bca0d44b34284b82708f5c16972360b9695791"}, + "status": {"path": "docs/status/M16-GAP-00222.md", "sha256": "61664acc268f0ddc6e53aec409e07b907dcff1e4bd75882f0b2fd0c92ad0c989"}, + "taskContext": {"path": "tests/golden/M16-GAP-00222/task-context.json", "sha256": "c512eb33c57c21e0d140eab83a6bf9df69011a31148a08449aefc8a63de195da"} + }, + "nextTask": "M16-GAP-00223" +} diff --git a/tests/golden/M16-GAP-00222/task-context.json b/tests/golden/M16-GAP-00222/task-context.json new file mode 100644 index 00000000..d09ec5a5 --- /dev/null +++ b/tests/golden/M16-GAP-00222/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00222", + "parentTask": "M16-GAP-00221", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.collection_assign data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.collection_assign", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00222.py -- tests/files/web/generated/M16-GAP-00222-operator-armature.collection_assign.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00222", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00222" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00222.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2352, + "contextRemainingTokens": 587 + }, + "source": { + "bytes": 7552, + "tokens": 1889 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00222.py", + "bytes": 1403, + "tokens": 351 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00222-operator-armature.collection_assign.blend", + "bytes": 86283, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 237877, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 583485, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00222/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00222.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00222/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1403, + "tokens": 351 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00223", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00222.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00221/manifest.json", + "parentStatus": "docs/status/M16-GAP-00221.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00222.md", + "tests/golden/M16-GAP-00221/manifest.json", + "docs/status/M16-GAP-00221.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00221", + "parentTask": "M16-GAP-00220", + "status": "done", + "nextTask": "M16-GAP-00222", + "artifactCount": 14 + }, + "statusSummary": [ + "# M16-GAP-00221 Status", + "status: done", + "task: armature.collection_add operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one armature bone assigned to `WebGapArmatureCollectionAddExisting`.", + "- Desktop runs `ARMATURE_OT_collection_add` with `poll=true` and `FINISHED`, creating the `Bones` collection as index 1 and preserving the existing bone membership through save/reopen.", + "- The existing Main reader exposes both bone collections and their member IDs; no new reader field, data-block, editor, or browser behavior was added." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1819, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 455 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00222.md", + "bytes": 1819, + "lines": 38, + "tokens": 455 + }, + { + "path": "tests/golden/M16-GAP-00221/manifest.json", + "bytes": 2533, + "lines": 28, + "tokens": 634 + }, + { + "path": "docs/status/M16-GAP-00221.md", + "bytes": 1032, + "lines": 20, + "tokens": 258 + } + ], + "sourceTokens": 1889, + "evidenceFiles": 1, + "evidenceBytes": 1403, + "evidenceTokens": 351, + "totalTokens": 2240, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3264, + "serializedContextTokens": 759, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00223/armature-collection-create-assign-desktop-report.json b/tests/golden/M16-GAP-00223/armature-collection-create-assign-desktop-report.json new file mode 100644 index 00000000..1028def4 --- /dev/null +++ b/tests/golden/M16-GAP-00223/armature-collection-create-assign-desktop-report.json @@ -0,0 +1,55 @@ +{ + "after": { + "activeIndex": 1, + "armature": "WebGapArmatureCollectionCreateAssignArmature", + "collections": [ + { + "bones": [ + "WebGapArmatureCollectionCreateAssignBone" + ], + "index": 0, + "name": "WebGapArmatureCollectionCreateAssignSource" + }, + { + "bones": [ + "WebGapArmatureCollectionCreateAssignBone" + ], + "index": 1, + "name": "WebGapArmatureCollectionCreateAssignNew" + } + ], + "object": "WebGapArmatureCollectionCreateAssignObject" + }, + "alreadyCreated": true, + "before": { + "activeIndex": 1, + "armature": "WebGapArmatureCollectionCreateAssignArmature", + "collections": [ + { + "bones": [ + "WebGapArmatureCollectionCreateAssignBone" + ], + "index": 0, + "name": "WebGapArmatureCollectionCreateAssignSource" + }, + { + "bones": [ + "WebGapArmatureCollectionCreateAssignBone" + ], + "index": 1, + "name": "WebGapArmatureCollectionCreateAssignNew" + } + ], + "object": "WebGapArmatureCollectionCreateAssignObject" + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00223-operator-armature.collection_create_and_assign.blend", + "fixtureSha256": "a028eb51fe9f4e81778cd5e237820c050c88588266cb39cd2a0fb4b15d33c8c8", + "mainMutation": "ALREADY_NEW_COLLECTION_CREATED_AND_BONE_ASSIGNED", + "operation": "ARMATURE_COLLECTION_CREATE_AND_ASSIGN_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00223" +} diff --git a/tests/golden/M16-GAP-00223/armature-collection-create-assign-local-exact-report.json b/tests/golden/M16-GAP-00223/armature-collection-create-assign-local-exact-report.json new file mode 100644 index 00000000..fbc25cc9 --- /dev/null +++ b/tests/golden/M16-GAP-00223/armature-collection-create-assign-local-exact-report.json @@ -0,0 +1,42 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00223", + "operation": "ARMATURE_COLLECTION_CREATE_AND_ASSIGN_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00223-operator-armature.collection_create_and_assign.blend", + "sha256": "a028eb51fe9f4e81778cd5e237820c050c88588266cb39cd2a0fb4b15d33c8c8" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00223/armature-collection-create-assign-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "ALREADY_NEW_COLLECTION_CREATED_AND_BONE_ASSIGNED" + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureCollectionCreateAssignArmature", + "assignedBoneId": "bone:armature:WebGapArmatureCollectionCreateAssignArmature:WebGapArmatureCollectionCreateAssignBone", + "sourceCollection": { + "id": "bone_collection:armature:WebGapArmatureCollectionCreateAssignArmature:WebGapArmatureCollectionCreateAssignSource", + "name": "WebGapArmatureCollectionCreateAssignSource", + "boneIds": [ + "bone:armature:WebGapArmatureCollectionCreateAssignArmature:WebGapArmatureCollectionCreateAssignBone" + ] + }, + "createdCollection": { + "id": "bone_collection:armature:WebGapArmatureCollectionCreateAssignArmature:WebGapArmatureCollectionCreateAssignNew", + "name": "WebGapArmatureCollectionCreateAssignNew", + "index": 1, + "boneIds": [ + "bone:armature:WebGapArmatureCollectionCreateAssignArmature:WebGapArmatureCollectionCreateAssignBone" + ] + } + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00224" +} diff --git a/tests/golden/M16-GAP-00223/manifest.json b/tests/golden/M16-GAP-00223/manifest.json new file mode 100644 index 00000000..da1a22e7 --- /dev/null +++ b/tests/golden/M16-GAP-00223/manifest.json @@ -0,0 +1,27 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00223", + "parentTask": "M16-GAP-00222", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_COLLECTION_CREATE_AND_ASSIGN_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": {"path": "tests/golden/M16-GAP-00222/manifest.json", "sha256": "593bc1ad27a621ce73a50f1f13512518032f1d328411fde6d53b9c16450d1184"}, + "fixture": {"path": "tests/files/web/generated/M16-GAP-00223-operator-armature.collection_create_and_assign.blend", "sha256": "a028eb51fe9f4e81778cd5e237820c050c88588266cb39cd2a0fb4b15d33c8c8"}, + "generator": {"path": "tools/web/generated/M16-GAP-00223.py", "sha256": "8edf3fc266d93bb225a0f13d16034a2518f2a85f424931d9c570626417c5ce11"}, + "desktopChecker": {"path": "tools/web/check-action-armature-collection-create-assign-desktop.py", "sha256": "4e6ee367c86279625bed4475f05abd3596329c2bd1c54c295f96118d5156cec1"}, + "webChecker": {"path": "tools/web/check-generated-gap.mjs", "sha256": "58e7a4c517f5244deb9cd6ebbec09cc6d0ac6ca8e4c68305e1a2964218c5259f"}, + "reader": {"path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "c56d254a74ace9664104f139692cf37f825547301824872bfd8db95f6ad2117b"}, + "wasm": {"path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "82b9fb9488a20543f0db1235b18a7c28b2593ac498c152a12f45f8299ced1927"}, + "wasmPublic": {"path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "82b9fb9488a20543f0db1235b18a7c28b2593ac498c152a12f45f8299ced1927"}, + "wasmJs": {"path": "web/app/src/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "wasmJsPublic": {"path": "web/app/public/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "desktopReport": {"path": "tests/golden/M16-GAP-00223/armature-collection-create-assign-desktop-report.json", "sha256": "d02d028f7ec561db7363feea7f5504c5f8f7d719cd36b6a6f2edb70847996b4c"}, + "webReport": {"path": "tests/golden/M16-GAP-00223/armature-collection-create-assign-local-exact-report.json", "sha256": "14b7947dd2485e11eeb2045d565fe97732865abc4aceb0e6765e3ab2fbe0f63f"}, + "status": {"path": "docs/status/M16-GAP-00223.md", "sha256": "4067ee986f0ff940d8ec7ba937bbdf4b7f81eab5779a3cbdd7287dbb7fdc6de5"}, + "taskContext": {"path": "tests/golden/M16-GAP-00223/task-context.json", "sha256": "a9b51398cc072d9ca64ea26ed4a10e5988ec4ba428dc1af18a54997c640d7638"} + }, + "nextTask": "M16-GAP-00224" +} diff --git a/tests/golden/M16-GAP-00223/task-context.json b/tests/golden/M16-GAP-00223/task-context.json new file mode 100644 index 00000000..4a95ff30 --- /dev/null +++ b/tests/golden/M16-GAP-00223/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00223", + "parentTask": "M16-GAP-00222", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.collection_create_and_assign data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.collection_create_and_assign", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00223.py -- tests/files/web/generated/M16-GAP-00223-operator-armature.collection_create_and_assign.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00223", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00223" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00223.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2259, + "contextRemainingTokens": 564 + }, + "source": { + "bytes": 7645, + "tokens": 1912 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00223.py", + "bytes": 1320, + "tokens": 330 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00223-operator-armature.collection_create_and_assign.blend", + "bytes": 86294, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 237877, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 587994, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00223/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00223.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00223/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1320, + "tokens": 330 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00224", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00223.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00222/manifest.json", + "parentStatus": "docs/status/M16-GAP-00222.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00223.md", + "tests/golden/M16-GAP-00222/manifest.json", + "docs/status/M16-GAP-00222.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00222", + "parentTask": "M16-GAP-00221", + "status": "done", + "nextTask": "M16-GAP-00223", + "artifactCount": 14 + }, + "statusSummary": [ + "# M16-GAP-00222 Status", + "status: done", + "task: armature.collection_assign operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one armature bone assigned to `WebGapArmatureCollectionAssignSource` and an empty target collection.", + "- Desktop runs `ARMATURE_OT_collection_assign(name=target)` with `poll=true` and `FINISHED`, adding the selected bone to the target while preserving its source membership through save/reopen.", + "- The existing Main reader exposes both collection member ID lists; no new reader field, data-block, editor, or browser behavior was added." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1874, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 469 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00223.md", + "bytes": 1874, + "lines": 38, + "tokens": 469 + }, + { + "path": "tests/golden/M16-GAP-00222/manifest.json", + "bytes": 2548, + "lines": 28, + "tokens": 637 + }, + { + "path": "docs/status/M16-GAP-00222.md", + "bytes": 1055, + "lines": 20, + "tokens": 264 + } + ], + "sourceTokens": 1912, + "evidenceFiles": 1, + "evidenceBytes": 1320, + "evidenceTokens": 330, + "totalTokens": 2242, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3266, + "serializedContextTokens": 767, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00224/armature-collection-deselect-desktop-report.json b/tests/golden/M16-GAP-00224/armature-collection-deselect-desktop-report.json new file mode 100644 index 00000000..6b1100cd --- /dev/null +++ b/tests/golden/M16-GAP-00224/armature-collection-deselect-desktop-report.json @@ -0,0 +1,43 @@ +{ + "after": { + "activeIndex": 0, + "armature": "WebGapArmatureCollectionDeselectArmature", + "bones": [ + { + "name": "WebGapArmatureCollectionDeselectActiveBone", + "selected": false + }, + { + "name": "WebGapArmatureCollectionDeselectOtherBone", + "selected": true + } + ], + "object": "WebGapArmatureCollectionDeselectObject" + }, + "alreadyDeselected": true, + "before": { + "activeIndex": 0, + "armature": "WebGapArmatureCollectionDeselectArmature", + "bones": [ + { + "name": "WebGapArmatureCollectionDeselectActiveBone", + "selected": false + }, + { + "name": "WebGapArmatureCollectionDeselectOtherBone", + "selected": true + } + ], + "object": "WebGapArmatureCollectionDeselectObject" + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00224-operator-armature.collection_deselect.blend", + "fixtureSha256": "1a8405355bb6fda930f31f396f9e34ec97c95ceed4b639fce9522c1e82f73b7f", + "mainMutation": "ACTIVE_COLLECTION_BONES_ALREADY_DESELECTED", + "operation": "ARMATURE_COLLECTION_DESELECT_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00224" +} diff --git a/tests/golden/M16-GAP-00224/armature-collection-deselect-local-exact-report.json b/tests/golden/M16-GAP-00224/armature-collection-deselect-local-exact-report.json new file mode 100644 index 00000000..00e0f476 --- /dev/null +++ b/tests/golden/M16-GAP-00224/armature-collection-deselect-local-exact-report.json @@ -0,0 +1,31 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00224", + "operation": "ARMATURE_COLLECTION_DESELECT_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00224-operator-armature.collection_deselect.blend", + "sha256": "1a8405355bb6fda930f31f396f9e34ec97c95ceed4b639fce9522c1e82f73b7f" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00224/armature-collection-deselect-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "ACTIVE_COLLECTION_BONES_ALREADY_DESELECTED" + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureCollectionDeselectArmature", + "activeCollectionIndex": 0, + "deselectedBoneId": "bone:armature:WebGapArmatureCollectionDeselectArmature:WebGapArmatureCollectionDeselectActiveBone", + "retainedSelectedBoneId": "bone:armature:WebGapArmatureCollectionDeselectArmature:WebGapArmatureCollectionDeselectOtherBone", + "deselected": false, + "retainedSelected": true + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00225" +} diff --git a/tests/golden/M16-GAP-00224/manifest.json b/tests/golden/M16-GAP-00224/manifest.json new file mode 100644 index 00000000..e9f95a65 --- /dev/null +++ b/tests/golden/M16-GAP-00224/manifest.json @@ -0,0 +1,27 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00224", + "parentTask": "M16-GAP-00223", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_COLLECTION_DESELECT_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": {"path": "tests/golden/M16-GAP-00223/manifest.json", "sha256": "3cb48f423f3ecac5f8ad7c7404acab3803a8e273e23d8021b3682d4a6fcd0875"}, + "fixture": {"path": "tests/files/web/generated/M16-GAP-00224-operator-armature.collection_deselect.blend", "sha256": "1a8405355bb6fda930f31f396f9e34ec97c95ceed4b639fce9522c1e82f73b7f"}, + "generator": {"path": "tools/web/generated/M16-GAP-00224.py", "sha256": "26498cbab951fc7494cc364a6487de4b2901ddf17844b95c1c5416dcb058087c"}, + "desktopChecker": {"path": "tools/web/check-action-armature-collection-deselect-desktop.py", "sha256": "302d827119a02a62770a172cf3624c84b9c83463b0ef10d35c1854a5e767ffb3"}, + "webChecker": {"path": "tools/web/check-generated-gap.mjs", "sha256": "26e467682becf34248f18cb5aca81c49105cfc3874b3e468b985556d8dbea9df"}, + "reader": {"path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "b72a1e1416d44b9c84e94425fb17c6a2eed3e3921c726c2719fb3fe64f652553"}, + "wasm": {"path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "85651e3c088e2c0c1866871d3ac7f9ec65e0b9ced5261718ed59841eee85b23f"}, + "wasmPublic": {"path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "85651e3c088e2c0c1866871d3ac7f9ec65e0b9ced5261718ed59841eee85b23f"}, + "wasmJs": {"path": "web/app/src/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "wasmJsPublic": {"path": "web/app/public/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "desktopReport": {"path": "tests/golden/M16-GAP-00224/armature-collection-deselect-desktop-report.json", "sha256": "78b8615c71b02dbcb6b2b88086118b9c713aa3762ddf5d947ae0b696d72d7744"}, + "webReport": {"path": "tests/golden/M16-GAP-00224/armature-collection-deselect-local-exact-report.json", "sha256": "9bfc7c03a0e46bb31069e987c0a60dea1ebb0b5c17dbe382fb1d1847ad42595c"}, + "status": {"path": "docs/status/M16-GAP-00224.md", "sha256": "25f0a2dc6478e179122efad2467952a0e75eb5ff0437e0c0f2b3639f034d744c"}, + "taskContext": {"path": "tests/golden/M16-GAP-00224/task-context.json", "sha256": "7201e11f59e90287699d96e377865963fe9f8aede63b4447941642bf877e2574"} + }, + "nextTask": "M16-GAP-00225" +} diff --git a/tests/golden/M16-GAP-00224/task-context.json b/tests/golden/M16-GAP-00224/task-context.json new file mode 100644 index 00000000..be8ae138 --- /dev/null +++ b/tests/golden/M16-GAP-00224/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00224", + "parentTask": "M16-GAP-00223", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.collection_deselect data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.collection_deselect", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00224.py -- tests/files/web/generated/M16-GAP-00224-operator-armature.collection_deselect.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00224", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00224" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00224.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2145, + "contextRemainingTokens": 535 + }, + "source": { + "bytes": 7759, + "tokens": 1941 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00224.py", + "bytes": 1881, + "tokens": 471 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00224-operator-armature.collection_deselect.blend", + "bytes": 86423, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 238013, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 592080, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00224/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00224.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00224/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1881, + "tokens": 471 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00225", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00224.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00223/manifest.json", + "parentStatus": "docs/status/M16-GAP-00223.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00224.md", + "tests/golden/M16-GAP-00223/manifest.json", + "docs/status/M16-GAP-00223.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00223", + "parentTask": "M16-GAP-00222", + "status": "done", + "nextTask": "M16-GAP-00224", + "artifactCount": 14 + }, + "statusSummary": [ + "# M16-GAP-00223 Status", + "status: done", + "task: armature.collection_create_and_assign operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one armature bone assigned to `WebGapArmatureCollectionCreateAssignSource`.", + "- Desktop runs `ARMATURE_OT_collection_create_and_assign(name=WebGapArmatureCollectionCreateAssignNew)` with `poll=true` and `FINISHED`, creating and activating the new collection while assigning the selected bone and preserving source membership through save/reopen.", + "- The existing Main reader exposes both collection member ID lists and collection indices; no new reader field, data-block, editor, or browser behavior was added." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1829, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 458 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00224.md", + "bytes": 1829, + "lines": 38, + "tokens": 458 + }, + { + "path": "tests/golden/M16-GAP-00223/manifest.json", + "bytes": 2591, + "lines": 28, + "tokens": 648 + }, + { + "path": "docs/status/M16-GAP-00223.md", + "bytes": 1171, + "lines": 20, + "tokens": 293 + } + ], + "sourceTokens": 1941, + "evidenceFiles": 1, + "evidenceBytes": 1881, + "evidenceTokens": 471, + "totalTokens": 2412, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3436, + "serializedContextTokens": 760, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00225/armature-collection-move-desktop-report.json b/tests/golden/M16-GAP-00225/armature-collection-move-desktop-report.json new file mode 100644 index 00000000..44dbbb6c --- /dev/null +++ b/tests/golden/M16-GAP-00225/armature-collection-move-desktop-report.json @@ -0,0 +1,70 @@ +{ + "after": { + "activeIndex": 0, + "armature": "WebGapArmatureCollectionMoveArmature", + "collections": [ + { + "bones": [ + "WebGapArmatureCollectionMoveActiveBone" + ], + "index": 0, + "name": "WebGapArmatureCollectionMoveActive" + }, + { + "bones": [ + "WebGapArmatureCollectionMoveFirstBone" + ], + "index": 1, + "name": "WebGapArmatureCollectionMoveFirst" + }, + { + "bones": [ + "WebGapArmatureCollectionMoveLastBone" + ], + "index": 2, + "name": "WebGapArmatureCollectionMoveLast" + } + ], + "object": "WebGapArmatureCollectionMoveObject" + }, + "alreadyMoved": true, + "before": { + "activeIndex": 0, + "armature": "WebGapArmatureCollectionMoveArmature", + "collections": [ + { + "bones": [ + "WebGapArmatureCollectionMoveActiveBone" + ], + "index": 0, + "name": "WebGapArmatureCollectionMoveActive" + }, + { + "bones": [ + "WebGapArmatureCollectionMoveFirstBone" + ], + "index": 1, + "name": "WebGapArmatureCollectionMoveFirst" + }, + { + "bones": [ + "WebGapArmatureCollectionMoveLastBone" + ], + "index": 2, + "name": "WebGapArmatureCollectionMoveLast" + } + ], + "object": "WebGapArmatureCollectionMoveObject" + }, + "blenderVersion": "5.2.0 LTS", + "direction": "UP", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00225-operator-armature.collection_move.blend", + "fixtureSha256": "ae87b298fce55732961119fd8a36568c137023eed9002c26a9575578d3d983b5", + "mainMutation": "ACTIVE_COLLECTION_ALREADY_MOVED_UP", + "operation": "ARMATURE_COLLECTION_MOVE_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00225" +} diff --git a/tests/golden/M16-GAP-00225/armature-collection-move-local-exact-report.json b/tests/golden/M16-GAP-00225/armature-collection-move-local-exact-report.json new file mode 100644 index 00000000..7d6f4f36 --- /dev/null +++ b/tests/golden/M16-GAP-00225/armature-collection-move-local-exact-report.json @@ -0,0 +1,55 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00225", + "operation": "ARMATURE_COLLECTION_MOVE_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00225-operator-armature.collection_move.blend", + "sha256": "ae87b298fce55732961119fd8a36568c137023eed9002c26a9575578d3d983b5" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00225/armature-collection-move-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "direction": "UP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "ACTIVE_COLLECTION_ALREADY_MOVED_UP" + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureCollectionMoveArmature", + "direction": "UP", + "activeCollection": "WebGapArmatureCollectionMoveActive", + "collectionOrder": [ + { + "id": "bone_collection:armature:WebGapArmatureCollectionMoveArmature:WebGapArmatureCollectionMoveActive", + "name": "WebGapArmatureCollectionMoveActive", + "index": 0, + "boneIds": [ + "bone:armature:WebGapArmatureCollectionMoveArmature:WebGapArmatureCollectionMoveActiveBone" + ] + }, + { + "id": "bone_collection:armature:WebGapArmatureCollectionMoveArmature:WebGapArmatureCollectionMoveFirst", + "name": "WebGapArmatureCollectionMoveFirst", + "index": 1, + "boneIds": [ + "bone:armature:WebGapArmatureCollectionMoveArmature:WebGapArmatureCollectionMoveFirstBone" + ] + }, + { + "id": "bone_collection:armature:WebGapArmatureCollectionMoveArmature:WebGapArmatureCollectionMoveLast", + "name": "WebGapArmatureCollectionMoveLast", + "index": 2, + "boneIds": [ + "bone:armature:WebGapArmatureCollectionMoveArmature:WebGapArmatureCollectionMoveLastBone" + ] + } + ] + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00226" +} diff --git a/tests/golden/M16-GAP-00225/manifest.json b/tests/golden/M16-GAP-00225/manifest.json new file mode 100644 index 00000000..72c24b7c --- /dev/null +++ b/tests/golden/M16-GAP-00225/manifest.json @@ -0,0 +1,27 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00225", + "parentTask": "M16-GAP-00224", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_COLLECTION_MOVE_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": {"path": "tests/golden/M16-GAP-00224/manifest.json", "sha256": "2319012188014b56201f54d47b9714af337f97c6359000bc1ceff77ea12aa083"}, + "fixture": {"path": "tests/files/web/generated/M16-GAP-00225-operator-armature.collection_move.blend", "sha256": "ae87b298fce55732961119fd8a36568c137023eed9002c26a9575578d3d983b5"}, + "generator": {"path": "tools/web/generated/M16-GAP-00225.py", "sha256": "60175e59c0362eff81649fcdcbd180fea7f06233ebd7d42cb3d35d2e66804901"}, + "desktopChecker": {"path": "tools/web/check-action-armature-collection-move-desktop.py", "sha256": "6babe7d65549e4b06f4a9790af3ce6dabdf3131831f5d26442d6c1c6d0099f90"}, + "webChecker": {"path": "tools/web/check-generated-gap.mjs", "sha256": "b00b3089aa75123ecb91187fc8e47ce6fc5b4c98dd6a8c8abb6af6d56b1f7b7c"}, + "reader": {"path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "b72a1e1416d44b9c84e94425fb17c6a2eed3e3921c726c2719fb3fe64f652553"}, + "wasm": {"path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "85651e3c088e2c0c1866871d3ac7f9ec65e0b9ced5261718ed59841eee85b23f"}, + "wasmPublic": {"path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "85651e3c088e2c0c1866871d3ac7f9ec65e0b9ced5261718ed59841eee85b23f"}, + "wasmJs": {"path": "web/app/src/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "wasmJsPublic": {"path": "web/app/public/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "desktopReport": {"path": "tests/golden/M16-GAP-00225/armature-collection-move-desktop-report.json", "sha256": "06074b980f8df448546afcf0c96e89e47bcb160b309db81c869d525b35b281ad"}, + "webReport": {"path": "tests/golden/M16-GAP-00225/armature-collection-move-local-exact-report.json", "sha256": "aa0becd48b2e42dc3c3ac7222d6e0486ffc8089bceefb3670f102fecd6d1f2e6"}, + "status": {"path": "docs/status/M16-GAP-00225.md", "sha256": "3330f1d33b17b920a261497023dc4ca06079837f69ba39251ab8d48a31bc73c0"}, + "taskContext": {"path": "tests/golden/M16-GAP-00225/task-context.json", "sha256": "a946ed0bc5ef3004a227fb461dec0b46e1a571ddeeb7deaac46f08d4a4e840d6"} + }, + "nextTask": "M16-GAP-00226" +} diff --git a/tests/golden/M16-GAP-00225/task-context.json b/tests/golden/M16-GAP-00225/task-context.json new file mode 100644 index 00000000..55787604 --- /dev/null +++ b/tests/golden/M16-GAP-00225/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00225", + "parentTask": "M16-GAP-00224", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.collection_move data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.collection_move", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00225.py -- tests/files/web/generated/M16-GAP-00225-operator-armature.collection_move.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00225", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00225" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00225.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2273, + "contextRemainingTokens": 567 + }, + "source": { + "bytes": 7631, + "tokens": 1909 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00225.py", + "bytes": 1764, + "tokens": 441 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00225-operator-armature.collection_move.blend", + "bytes": 86467, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 238013, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 596398, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00225/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00225.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00225/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1764, + "tokens": 441 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00226", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00225.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00224/manifest.json", + "parentStatus": "docs/status/M16-GAP-00224.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00225.md", + "tests/golden/M16-GAP-00224/manifest.json", + "docs/status/M16-GAP-00224.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00224", + "parentTask": "M16-GAP-00223", + "status": "done", + "nextTask": "M16-GAP-00225", + "artifactCount": 14 + }, + "statusSummary": [ + "# M16-GAP-00224 Status", + "status: done", + "task: armature.collection_deselect operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains two bones in separate bone collections, both initially selected, with the active collection at index 0.", + "- Desktop runs `ARMATURE_OT_collection_deselect` with `poll=true` and `FINISHED`, deselecting only the active collection bone while retaining the other selection through save/reopen.", + "- Main now exposes the persisted armature bone `selected` bit alongside the existing bone collection membership data; no other data-block, editor, or browser behavior was added." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1809, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 453 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00225.md", + "bytes": 1809, + "lines": 38, + "tokens": 453 + }, + { + "path": "tests/golden/M16-GAP-00224/manifest.json", + "bytes": 2558, + "lines": 28, + "tokens": 640 + }, + { + "path": "docs/status/M16-GAP-00224.md", + "bytes": 1096, + "lines": 20, + "tokens": 274 + } + ], + "sourceTokens": 1909, + "evidenceFiles": 1, + "evidenceBytes": 1764, + "evidenceTokens": 441, + "totalTokens": 2350, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3374, + "serializedContextTokens": 757, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00226/armature-collection-remove-desktop-report.json b/tests/golden/M16-GAP-00226/armature-collection-remove-desktop-report.json new file mode 100644 index 00000000..48828afb --- /dev/null +++ b/tests/golden/M16-GAP-00226/armature-collection-remove-desktop-report.json @@ -0,0 +1,65 @@ +{ + "after": { + "activeIndex": 1, + "armature": "WebGapArmatureCollectionRemoveArmature", + "bones": [ + "WebGapArmatureCollectionRemoveFirstBone", + "WebGapArmatureCollectionRemoveLastBone", + "WebGapArmatureCollectionRemoveRemovedBone" + ], + "collections": [ + { + "bones": [ + "WebGapArmatureCollectionRemoveFirstBone" + ], + "index": 0, + "name": "WebGapArmatureCollectionRemoveFirst" + }, + { + "bones": [ + "WebGapArmatureCollectionRemoveLastBone" + ], + "index": 1, + "name": "WebGapArmatureCollectionRemoveLast" + } + ], + "object": "WebGapArmatureCollectionRemoveObject" + }, + "alreadyRemoved": true, + "before": { + "activeIndex": 1, + "armature": "WebGapArmatureCollectionRemoveArmature", + "bones": [ + "WebGapArmatureCollectionRemoveFirstBone", + "WebGapArmatureCollectionRemoveLastBone", + "WebGapArmatureCollectionRemoveRemovedBone" + ], + "collections": [ + { + "bones": [ + "WebGapArmatureCollectionRemoveFirstBone" + ], + "index": 0, + "name": "WebGapArmatureCollectionRemoveFirst" + }, + { + "bones": [ + "WebGapArmatureCollectionRemoveLastBone" + ], + "index": 1, + "name": "WebGapArmatureCollectionRemoveLast" + } + ], + "object": "WebGapArmatureCollectionRemoveObject" + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00226-operator-armature.collection_remove.blend", + "fixtureSha256": "1e3ba5e46b8b45ca974b93b0f357cc5305c787032564ecbecfc9e1ae4e8ff9d5", + "mainMutation": "ACTIVE_COLLECTION_ALREADY_REMOVED", + "operation": "ARMATURE_COLLECTION_REMOVE_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00226" +} diff --git a/tests/golden/M16-GAP-00226/armature-collection-remove-local-exact-report.json b/tests/golden/M16-GAP-00226/armature-collection-remove-local-exact-report.json new file mode 100644 index 00000000..897a726d --- /dev/null +++ b/tests/golden/M16-GAP-00226/armature-collection-remove-local-exact-report.json @@ -0,0 +1,46 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00226", + "operation": "ARMATURE_COLLECTION_REMOVE_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00226-operator-armature.collection_remove.blend", + "sha256": "1e3ba5e46b8b45ca974b93b0f357cc5305c787032564ecbecfc9e1ae4e8ff9d5" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00226/armature-collection-remove-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "ACTIVE_COLLECTION_ALREADY_REMOVED" + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureCollectionRemoveArmature", + "removedCollection": "WebGapArmatureCollectionRemoveRemoved", + "removedBoneId": "bone:armature:WebGapArmatureCollectionRemoveArmature:WebGapArmatureCollectionRemoveRemovedBone", + "collectionOrder": [ + { + "id": "bone_collection:armature:WebGapArmatureCollectionRemoveArmature:WebGapArmatureCollectionRemoveFirst", + "name": "WebGapArmatureCollectionRemoveFirst", + "index": 0, + "boneIds": [ + "bone:armature:WebGapArmatureCollectionRemoveArmature:WebGapArmatureCollectionRemoveFirstBone" + ] + }, + { + "id": "bone_collection:armature:WebGapArmatureCollectionRemoveArmature:WebGapArmatureCollectionRemoveLast", + "name": "WebGapArmatureCollectionRemoveLast", + "index": 1, + "boneIds": [ + "bone:armature:WebGapArmatureCollectionRemoveArmature:WebGapArmatureCollectionRemoveLastBone" + ] + } + ] + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00227" +} diff --git a/tests/golden/M16-GAP-00226/manifest.json b/tests/golden/M16-GAP-00226/manifest.json new file mode 100644 index 00000000..9b1036b1 --- /dev/null +++ b/tests/golden/M16-GAP-00226/manifest.json @@ -0,0 +1,27 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00226", + "parentTask": "M16-GAP-00225", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_COLLECTION_REMOVE_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": {"path": "tests/golden/M16-GAP-00225/manifest.json", "sha256": "f5d2ee089b76a849567fc8f00d191bb722651a206fa0f00542e4a9d796d33e72"}, + "fixture": {"path": "tests/files/web/generated/M16-GAP-00226-operator-armature.collection_remove.blend", "sha256": "1e3ba5e46b8b45ca974b93b0f357cc5305c787032564ecbecfc9e1ae4e8ff9d5"}, + "generator": {"path": "tools/web/generated/M16-GAP-00226.py", "sha256": "bf2375e84e871ada6615365fbda390de46a6f7adf1202d76ff6d6b34ea7ef364"}, + "desktopChecker": {"path": "tools/web/check-action-armature-collection-remove-desktop.py", "sha256": "071d8360f7aff11fa3466e96133c9401525a5f31a4beec6c5fde46b43329dbc8"}, + "webChecker": {"path": "tools/web/check-generated-gap.mjs", "sha256": "547aaa82fd1baa50190fa294309a07a0f2b077fa2d9d80bae916c60cb027f074"}, + "reader": {"path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "b72a1e1416d44b9c84e94425fb17c6a2eed3e3921c726c2719fb3fe64f652553"}, + "wasm": {"path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "85651e3c088e2c0c1866871d3ac7f9ec65e0b9ced5261718ed59841eee85b23f"}, + "wasmPublic": {"path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "85651e3c088e2c0c1866871d3ac7f9ec65e0b9ced5261718ed59841eee85b23f"}, + "wasmJs": {"path": "web/app/src/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "wasmJsPublic": {"path": "web/app/public/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "desktopReport": {"path": "tests/golden/M16-GAP-00226/armature-collection-remove-desktop-report.json", "sha256": "525ca8c6954750c9982bf91cbb3f26c9ad7a81911d56890dd6570cccfdbe3b37"}, + "webReport": {"path": "tests/golden/M16-GAP-00226/armature-collection-remove-local-exact-report.json", "sha256": "6df4c731b900161076a59892d26f15a8775d18571f27eb88321f890f91c9b9a0"}, + "status": {"path": "docs/status/M16-GAP-00226.md", "sha256": "e4d4e214d2f1fd8c1872978d18ce28bee65fc7c4ded0c6869780af0343d12d5d"}, + "taskContext": {"path": "tests/golden/M16-GAP-00226/task-context.json", "sha256": "b5bb4620750aea7f1773049c127349b7fca058c3345cecae20e302d8054632f8"} + }, + "nextTask": "M16-GAP-00227" +} diff --git a/tests/golden/M16-GAP-00226/task-context.json b/tests/golden/M16-GAP-00226/task-context.json new file mode 100644 index 00000000..45bd2c92 --- /dev/null +++ b/tests/golden/M16-GAP-00226/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00226", + "parentTask": "M16-GAP-00225", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.collection_remove data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.collection_remove", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00226.py -- tests/files/web/generated/M16-GAP-00226-operator-armature.collection_remove.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00226", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00226" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00226.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2287, + "contextRemainingTokens": 571 + }, + "source": { + "bytes": 7617, + "tokens": 1905 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00226.py", + "bytes": 1789, + "tokens": 448 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00226-operator-armature.collection_remove.blend", + "bytes": 86430, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 238013, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 601033, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00226/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00226.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00226/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1789, + "tokens": 448 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00227", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00226.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00225/manifest.json", + "parentStatus": "docs/status/M16-GAP-00225.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00226.md", + "tests/golden/M16-GAP-00225/manifest.json", + "docs/status/M16-GAP-00225.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00225", + "parentTask": "M16-GAP-00224", + "status": "done", + "nextTask": "M16-GAP-00226", + "artifactCount": 14 + }, + "statusSummary": [ + "# M16-GAP-00225 Status", + "status: done", + "task: armature.collection_move operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains three bone collections, each retaining one distinct bone, with the middle collection active at index 1.", + "- Desktop runs `ARMATURE_OT_collection_move(direction='UP')` with `poll=true` and `FINISHED`, moving the active collection to index 0 while preserving every collection member through save/reopen.", + "- The existing Main reader's collection indices and bone IDs provide the observable order; no new data-block, editor, or browser behavior was added." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1819, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 455 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2168, + "lines": 45, + "tokens": 542 + }, + { + "path": "docs/tasks/M16-GAP-00226.md", + "bytes": 1819, + "lines": 38, + "tokens": 455 + }, + { + "path": "tests/golden/M16-GAP-00225/manifest.json", + "bytes": 2538, + "lines": 28, + "tokens": 635 + }, + { + "path": "docs/status/M16-GAP-00225.md", + "bytes": 1092, + "lines": 20, + "tokens": 273 + } + ], + "sourceTokens": 1905, + "evidenceFiles": 1, + "evidenceBytes": 1789, + "evidenceTokens": 448, + "totalTokens": 2353, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3377, + "serializedContextTokens": 759, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00227/armature-collection-remove-unused-desktop-report.json b/tests/golden/M16-GAP-00227/armature-collection-remove-unused-desktop-report.json new file mode 100644 index 00000000..672a2929 --- /dev/null +++ b/tests/golden/M16-GAP-00227/armature-collection-remove-unused-desktop-report.json @@ -0,0 +1,67 @@ +{ + "after": { + "activeIndex": 1, + "armature": "WebGapArmatureCollectionRemoveUnusedArmature", + "bones": [ + "WebGapArmatureCollectionRemoveUnusedFirstBone", + "WebGapArmatureCollectionRemoveUnusedLastBone" + ], + "collections": [ + { + "bones": [ + "WebGapArmatureCollectionRemoveUnusedFirstBone" + ], + "index": 0, + "name": "WebGapArmatureCollectionRemoveUnusedFirst" + }, + { + "bones": [ + "WebGapArmatureCollectionRemoveUnusedLastBone" + ], + "index": 1, + "name": "WebGapArmatureCollectionRemoveUnusedLast" + } + ], + "object": "WebGapArmatureCollectionRemoveUnusedObject" + }, + "alreadyRemoved": true, + "before": { + "activeIndex": 1, + "armature": "WebGapArmatureCollectionRemoveUnusedArmature", + "bones": [ + "WebGapArmatureCollectionRemoveUnusedFirstBone", + "WebGapArmatureCollectionRemoveUnusedLastBone" + ], + "collections": [ + { + "bones": [ + "WebGapArmatureCollectionRemoveUnusedFirstBone" + ], + "index": 0, + "name": "WebGapArmatureCollectionRemoveUnusedFirst" + }, + { + "bones": [ + "WebGapArmatureCollectionRemoveUnusedLastBone" + ], + "index": 1, + "name": "WebGapArmatureCollectionRemoveUnusedLast" + } + ], + "object": "WebGapArmatureCollectionRemoveUnusedObject" + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00227-operator-armature.collection_remove_unused.blend", + "fixtureSha256": "0c898c98dc011e51f086cda66e3af03a08a7b1f27eb0e76f40915f18018a6d97", + "mainMutation": "UNUSED_COLLECTIONS_ALREADY_REMOVED", + "operation": "ARMATURE_COLLECTION_REMOVE_UNUSED_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "poll": true, + "removedCollections": [ + "WebGapArmatureCollectionRemoveUnusedUnusedFirst", + "WebGapArmatureCollectionRemoveUnusedUnusedLast" + ], + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00227" +} diff --git a/tests/golden/M16-GAP-00227/armature-collection-remove-unused-local-exact-report.json b/tests/golden/M16-GAP-00227/armature-collection-remove-unused-local-exact-report.json new file mode 100644 index 00000000..e60cd78b --- /dev/null +++ b/tests/golden/M16-GAP-00227/armature-collection-remove-unused-local-exact-report.json @@ -0,0 +1,48 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00227", + "operation": "ARMATURE_COLLECTION_REMOVE_UNUSED_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00227-operator-armature.collection_remove_unused.blend", + "sha256": "0c898c98dc011e51f086cda66e3af03a08a7b1f27eb0e76f40915f18018a6d97" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00227/armature-collection-remove-unused-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "UNUSED_COLLECTIONS_ALREADY_REMOVED" + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureCollectionRemoveUnusedArmature", + "removedCollections": [ + "WebGapArmatureCollectionRemoveUnusedUnusedFirst", + "WebGapArmatureCollectionRemoveUnusedUnusedLast" + ], + "collectionOrder": [ + { + "id": "bone_collection:armature:WebGapArmatureCollectionRemoveUnusedArmature:WebGapArmatureCollectionRemoveUnusedFirst", + "name": "WebGapArmatureCollectionRemoveUnusedFirst", + "index": 0, + "boneIds": [ + "bone:armature:WebGapArmatureCollectionRemoveUnusedArmature:WebGapArmatureCollectionRemoveUnusedFirstBone" + ] + }, + { + "id": "bone_collection:armature:WebGapArmatureCollectionRemoveUnusedArmature:WebGapArmatureCollectionRemoveUnusedLast", + "name": "WebGapArmatureCollectionRemoveUnusedLast", + "index": 1, + "boneIds": [ + "bone:armature:WebGapArmatureCollectionRemoveUnusedArmature:WebGapArmatureCollectionRemoveUnusedLastBone" + ] + } + ] + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00228" +} diff --git a/tests/golden/M16-GAP-00227/manifest.json b/tests/golden/M16-GAP-00227/manifest.json new file mode 100644 index 00000000..7161f884 --- /dev/null +++ b/tests/golden/M16-GAP-00227/manifest.json @@ -0,0 +1,27 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00227", + "parentTask": "M16-GAP-00226", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_COLLECTION_REMOVE_UNUSED_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": {"path": "tests/golden/M16-GAP-00226/manifest.json", "sha256": "e071c8ee3fc09259fd23c583a094981de94029c700e151632a96973c174aa82d"}, + "fixture": {"path": "tests/files/web/generated/M16-GAP-00227-operator-armature.collection_remove_unused.blend", "sha256": "0c898c98dc011e51f086cda66e3af03a08a7b1f27eb0e76f40915f18018a6d97"}, + "generator": {"path": "tools/web/generated/M16-GAP-00227.py", "sha256": "c08cad057124430d914c10b3a9f8f79d94809fdd283778397a91085364784ed5"}, + "desktopChecker": {"path": "tools/web/check-action-armature-collection-remove-unused-desktop.py", "sha256": "8bd8c0dfd8170779c3e834a8b3ad8c90e5a646263108b818c19e34be21353bc6"}, + "webChecker": {"path": "tools/web/check-generated-gap.mjs", "sha256": "5259f28488eab9e6778bc5f7997f0fe90524c2d1f0e2e68c3534f90ffdc444f4"}, + "reader": {"path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "b72a1e1416d44b9c84e94425fb17c6a2eed3e3921c726c2719fb3fe64f652553"}, + "wasm": {"path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "85651e3c088e2c0c1866871d3ac7f9ec65e0b9ced5261718ed59841eee85b23f"}, + "wasmPublic": {"path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "85651e3c088e2c0c1866871d3ac7f9ec65e0b9ced5261718ed59841eee85b23f"}, + "wasmJs": {"path": "web/app/src/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "wasmJsPublic": {"path": "web/app/public/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "desktopReport": {"path": "tests/golden/M16-GAP-00227/armature-collection-remove-unused-desktop-report.json", "sha256": "4909e040db7be0d5ac84148d52bb47cbdf0f12a30612e6c1bae1067fd4f04dca"}, + "webReport": {"path": "tests/golden/M16-GAP-00227/armature-collection-remove-unused-local-exact-report.json", "sha256": "b41c86788e6b9e21b04d42bdfaa645d29e669f8dfec9fdfaf96fa09771c64475"}, + "status": {"path": "docs/status/M16-GAP-00227.md", "sha256": "e92da7d66c4674271bbf2a43d524145b19926e1d919eacb27e4afc9ee3ceab51"}, + "taskContext": {"path": "tests/golden/M16-GAP-00227/task-context.json", "sha256": "e7b8b69221ddde77585cf8e66e3c9de3fcc1cedc61739fd4af2e1385e9b5dabd"} + }, + "nextTask": "M16-GAP-00228" +} diff --git a/tests/golden/M16-GAP-00227/task-context.json b/tests/golden/M16-GAP-00227/task-context.json new file mode 100644 index 00000000..421dd98f --- /dev/null +++ b/tests/golden/M16-GAP-00227/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00227", + "parentTask": "M16-GAP-00226", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.collection_remove_unused data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.collection_remove_unused", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00227.py -- tests/files/web/generated/M16-GAP-00227-operator-armature.collection_remove_unused.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00227", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00227" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00227.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1979, + "contextRemainingTokens": 493 + }, + "source": { + "bytes": 7925, + "tokens": 1983 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00227.py", + "bytes": 1833, + "tokens": 459 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00227-operator-armature.collection_remove_unused.blend", + "bytes": 86356, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 238013, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 605827, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00227/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00227.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00227/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1833, + "tokens": 459 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00228", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00227.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00226/manifest.json", + "parentStatus": "docs/status/M16-GAP-00226.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00227.md", + "tests/golden/M16-GAP-00226/manifest.json", + "docs/status/M16-GAP-00226.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00226", + "parentTask": "M16-GAP-00225", + "status": "done", + "nextTask": "M16-GAP-00227", + "artifactCount": 14 + }, + "statusSummary": [ + "# M16-GAP-00226 Status", + "status: done", + "task: armature.collection_remove operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains three bone collections, each initially retaining one distinct bone, with the middle collection active at index 1.", + "- Desktop runs `ARMATURE_OT_collection_remove` with `poll=true` and `FINISHED`, removing the active collection, leaving its bone unassigned, and preserving the remaining collections through save/reopen.", + "- The existing Main reader's collection indices and bone IDs provide the observable removal; no new data-block, editor, or browser behavior was added." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1854, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 464 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2394, + "lines": 47, + "tokens": 599 + }, + { + "path": "docs/tasks/M16-GAP-00227.md", + "bytes": 1854, + "lines": 38, + "tokens": 464 + }, + { + "path": "tests/golden/M16-GAP-00226/manifest.json", + "bytes": 2548, + "lines": 28, + "tokens": 637 + }, + { + "path": "docs/status/M16-GAP-00226.md", + "bytes": 1129, + "lines": 20, + "tokens": 283 + } + ], + "sourceTokens": 1983, + "evidenceFiles": 1, + "evidenceBytes": 1833, + "evidenceTokens": 459, + "totalTokens": 2442, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3466, + "serializedContextTokens": 764, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00228/armature-collection-select-desktop-report.json b/tests/golden/M16-GAP-00228/armature-collection-select-desktop-report.json new file mode 100644 index 00000000..d689b513 --- /dev/null +++ b/tests/golden/M16-GAP-00228/armature-collection-select-desktop-report.json @@ -0,0 +1,88 @@ +{ + "after": { + "activeIndex": 1, + "armature": "WebGapArmatureCollectionSelectArmature", + "bones": [ + "WebGapArmatureCollectionSelectActiveBone", + "WebGapArmatureCollectionSelectFirstBone", + "WebGapArmatureCollectionSelectLastBone" + ], + "collections": [ + { + "bones": [ + "WebGapArmatureCollectionSelectFirstBone" + ], + "index": 0, + "name": "WebGapArmatureCollectionSelectFirst" + }, + { + "bones": [ + "WebGapArmatureCollectionSelectActiveBone" + ], + "index": 1, + "name": "WebGapArmatureCollectionSelectActive" + }, + { + "bones": [ + "WebGapArmatureCollectionSelectLastBone" + ], + "index": 2, + "name": "WebGapArmatureCollectionSelectLast" + } + ], + "object": "WebGapArmatureCollectionSelectObject", + "selectedBones": [ + "WebGapArmatureCollectionSelectActiveBone", + "WebGapArmatureCollectionSelectFirstBone" + ] + }, + "alreadySelected": true, + "before": { + "activeIndex": 1, + "armature": "WebGapArmatureCollectionSelectArmature", + "bones": [ + "WebGapArmatureCollectionSelectActiveBone", + "WebGapArmatureCollectionSelectFirstBone", + "WebGapArmatureCollectionSelectLastBone" + ], + "collections": [ + { + "bones": [ + "WebGapArmatureCollectionSelectFirstBone" + ], + "index": 0, + "name": "WebGapArmatureCollectionSelectFirst" + }, + { + "bones": [ + "WebGapArmatureCollectionSelectActiveBone" + ], + "index": 1, + "name": "WebGapArmatureCollectionSelectActive" + }, + { + "bones": [ + "WebGapArmatureCollectionSelectLastBone" + ], + "index": 2, + "name": "WebGapArmatureCollectionSelectLast" + } + ], + "object": "WebGapArmatureCollectionSelectObject", + "selectedBones": [ + "WebGapArmatureCollectionSelectActiveBone", + "WebGapArmatureCollectionSelectFirstBone" + ] + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00228-operator-armature.collection_select.blend", + "fixtureSha256": "426b86f668d316254e06ff11f6fe59cd79d99216772573d17b2b74187d3ea6ea", + "mainMutation": "ACTIVE_COLLECTION_ALREADY_SELECTED", + "operation": "ARMATURE_COLLECTION_SELECT_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "selectedCollection": "WebGapArmatureCollectionSelectActive", + "task": "M16-GAP-00228" +} diff --git a/tests/golden/M16-GAP-00228/armature-collection-select-local-exact-report.json b/tests/golden/M16-GAP-00228/armature-collection-select-local-exact-report.json new file mode 100644 index 00000000..17d3e23c --- /dev/null +++ b/tests/golden/M16-GAP-00228/armature-collection-select-local-exact-report.json @@ -0,0 +1,57 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00228", + "operation": "ARMATURE_COLLECTION_SELECT_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00228-operator-armature.collection_select.blend", + "sha256": "426b86f668d316254e06ff11f6fe59cd79d99216772573d17b2b74187d3ea6ea" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00228/armature-collection-select-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "ACTIVE_COLLECTION_ALREADY_SELECTED" + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureCollectionSelectArmature", + "selectedCollection": "WebGapArmatureCollectionSelectActive", + "selectedBoneIds": [ + "bone:armature:WebGapArmatureCollectionSelectArmature:WebGapArmatureCollectionSelectActiveBone", + "bone:armature:WebGapArmatureCollectionSelectArmature:WebGapArmatureCollectionSelectFirstBone" + ], + "collectionOrder": [ + { + "id": "bone_collection:armature:WebGapArmatureCollectionSelectArmature:WebGapArmatureCollectionSelectFirst", + "name": "WebGapArmatureCollectionSelectFirst", + "index": 0, + "boneIds": [ + "bone:armature:WebGapArmatureCollectionSelectArmature:WebGapArmatureCollectionSelectFirstBone" + ] + }, + { + "id": "bone_collection:armature:WebGapArmatureCollectionSelectArmature:WebGapArmatureCollectionSelectActive", + "name": "WebGapArmatureCollectionSelectActive", + "index": 1, + "boneIds": [ + "bone:armature:WebGapArmatureCollectionSelectArmature:WebGapArmatureCollectionSelectActiveBone" + ] + }, + { + "id": "bone_collection:armature:WebGapArmatureCollectionSelectArmature:WebGapArmatureCollectionSelectLast", + "name": "WebGapArmatureCollectionSelectLast", + "index": 2, + "boneIds": [ + "bone:armature:WebGapArmatureCollectionSelectArmature:WebGapArmatureCollectionSelectLastBone" + ] + } + ] + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00229" +} diff --git a/tests/golden/M16-GAP-00228/manifest.json b/tests/golden/M16-GAP-00228/manifest.json new file mode 100644 index 00000000..7f03a89b --- /dev/null +++ b/tests/golden/M16-GAP-00228/manifest.json @@ -0,0 +1,27 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00228", + "parentTask": "M16-GAP-00227", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_COLLECTION_SELECT_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": {"path": "tests/golden/M16-GAP-00227/manifest.json", "sha256": "0bcd90a68235c27347b42900b1df89285363a2b766f0aa58d0d2eb58c3238ca6"}, + "fixture": {"path": "tests/files/web/generated/M16-GAP-00228-operator-armature.collection_select.blend", "sha256": "426b86f668d316254e06ff11f6fe59cd79d99216772573d17b2b74187d3ea6ea"}, + "generator": {"path": "tools/web/generated/M16-GAP-00228.py", "sha256": "06377349aec2193a46188eea4f6b00c2122442636bea2547166ec96caef2e7a4"}, + "desktopChecker": {"path": "tools/web/check-action-armature-collection-select-desktop.py", "sha256": "cb1db0e83e3ac1dab0db182b786cee39651c90e32817793f262b53a1b8caec89"}, + "webChecker": {"path": "tools/web/check-generated-gap.mjs", "sha256": "669e8cd26d2d6ffbb2749b1c4011d80e4089d080be50b4b369e4339e5d9bc1fb"}, + "reader": {"path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "b72a1e1416d44b9c84e94425fb17c6a2eed3e3921c726c2719fb3fe64f652553"}, + "wasm": {"path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "85651e3c088e2c0c1866871d3ac7f9ec65e0b9ced5261718ed59841eee85b23f"}, + "wasmPublic": {"path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "85651e3c088e2c0c1866871d3ac7f9ec65e0b9ced5261718ed59841eee85b23f"}, + "wasmJs": {"path": "web/app/src/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "wasmJsPublic": {"path": "web/app/public/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "desktopReport": {"path": "tests/golden/M16-GAP-00228/armature-collection-select-desktop-report.json", "sha256": "569c817b422e7947c30e202de7223a8da949127a022ce2b1e4f28de15202a440"}, + "webReport": {"path": "tests/golden/M16-GAP-00228/armature-collection-select-local-exact-report.json", "sha256": "cdb8e8196179776f53406eb67c2d6e838d547a2bae9b3dbb3a337646656abe64"}, + "status": {"path": "docs/status/M16-GAP-00228.md", "sha256": "347c7884e48c5ca488105422e401c93d7b2569886a43230c6d26afa103700132"}, + "taskContext": {"path": "tests/golden/M16-GAP-00228/task-context.json", "sha256": "1518cfbe7e66961eaa29ed27eed18d473e3194fc89575dcaea86007bb74c993b"} + }, + "nextTask": "M16-GAP-00229" +} diff --git a/tests/golden/M16-GAP-00228/task-context.json b/tests/golden/M16-GAP-00228/task-context.json new file mode 100644 index 00000000..a8a53ec7 --- /dev/null +++ b/tests/golden/M16-GAP-00228/task-context.json @@ -0,0 +1,182 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00228", + "parentTask": "M16-GAP-00227", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.collection_select data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.collection_select", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00228.py -- tests/files/web/generated/M16-GAP-00228-operator-armature.collection_select.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00228", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00228" + ], + "inputPaths": [], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1962, + "contextRemainingTokens": 489 + }, + "source": { + "bytes": 7942, + "tokens": 1987 + }, + "selected": [], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00228-operator-armature.collection_select.blend", + "bytes": 86518, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/generated/M16-GAP-00228.py", + "bytes": 1957, + "reason": "CONTEXT_REMAINING_SPACE" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 238013, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 610772, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00228/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00228.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00228/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 0, + "bytes": 0, + "tokens": 0 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00229", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00228.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00227/manifest.json", + "parentStatus": "docs/status/M16-GAP-00227.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00228.md", + "tests/golden/M16-GAP-00227/manifest.json", + "docs/status/M16-GAP-00227.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00227", + "parentTask": "M16-GAP-00226", + "status": "done", + "nextTask": "M16-GAP-00228", + "artifactCount": 14 + }, + "statusSummary": [ + "# M16-GAP-00227 Status", + "status: done", + "task: armature.collection_remove_unused operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains two bone collections retaining one distinct bone each and two empty collections, with an empty collection active at index 2.", + "- Desktop runs `ARMATURE_OT_collection_remove_unused` with `poll=true` and `FINISHED`, removing both unused collections, preserving the retained collections and bones, and keeping the result through save/reopen.", + "- The existing Main reader's collection indices and bone IDs provide the observable removal; no new data-block, editor, or browser behavior was added." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1819, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 455 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2394, + "lines": 47, + "tokens": 599 + }, + { + "path": "docs/tasks/M16-GAP-00228.md", + "bytes": 1819, + "lines": 38, + "tokens": 455 + }, + { + "path": "tests/golden/M16-GAP-00227/manifest.json", + "bytes": 2583, + "lines": 28, + "tokens": 646 + }, + { + "path": "docs/status/M16-GAP-00227.md", + "bytes": 1146, + "lines": 20, + "tokens": 287 + } + ], + "sourceTokens": 1987, + "evidenceFiles": 0, + "evidenceBytes": 0, + "evidenceTokens": 0, + "totalTokens": 1987, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3011, + "serializedContextTokens": 723, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00229/armature-collection-show-all-desktop-report.json b/tests/golden/M16-GAP-00229/armature-collection-show-all-desktop-report.json new file mode 100644 index 00000000..f7ac59f0 --- /dev/null +++ b/tests/golden/M16-GAP-00229/armature-collection-show-all-desktop-report.json @@ -0,0 +1,82 @@ +{ + "after": { + "armature": "WebGapArmatureCollectionShowAllArmature", + "bones": [ + "WebGapArmatureCollectionShowAllFirstBone", + "WebGapArmatureCollectionShowAllHiddenBone", + "WebGapArmatureCollectionShowAllLastBone" + ], + "collections": [ + { + "bones": [ + "WebGapArmatureCollectionShowAllFirstBone" + ], + "index": 0, + "name": "WebGapArmatureCollectionShowAllFirst", + "visible": true + }, + { + "bones": [ + "WebGapArmatureCollectionShowAllHiddenBone" + ], + "index": 1, + "name": "WebGapArmatureCollectionShowAllHidden", + "visible": true + }, + { + "bones": [ + "WebGapArmatureCollectionShowAllLastBone" + ], + "index": 2, + "name": "WebGapArmatureCollectionShowAllLast", + "visible": true + } + ], + "object": "WebGapArmatureCollectionShowAllObject" + }, + "before": { + "armature": "WebGapArmatureCollectionShowAllArmature", + "bones": [ + "WebGapArmatureCollectionShowAllFirstBone", + "WebGapArmatureCollectionShowAllHiddenBone", + "WebGapArmatureCollectionShowAllLastBone" + ], + "collections": [ + { + "bones": [ + "WebGapArmatureCollectionShowAllFirstBone" + ], + "index": 0, + "name": "WebGapArmatureCollectionShowAllFirst", + "visible": true + }, + { + "bones": [ + "WebGapArmatureCollectionShowAllHiddenBone" + ], + "index": 1, + "name": "WebGapArmatureCollectionShowAllHidden", + "visible": false + }, + { + "bones": [ + "WebGapArmatureCollectionShowAllLastBone" + ], + "index": 2, + "name": "WebGapArmatureCollectionShowAllLast", + "visible": true + } + ], + "object": "WebGapArmatureCollectionShowAllObject" + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00229-operator-armature.collection_show_all.blend", + "fixtureSha256": "b50107f0d15d2f0be497ea8f69385411f8354d04b1907e7e6382600d5e885795", + "mainMutation": "ALL_COLLECTIONS_VISIBLE", + "operation": "ARMATURE_COLLECTION_SHOW_ALL_DESKTOP", + "operatorStatus": "FINISHED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00229" +} diff --git a/tests/golden/M16-GAP-00229/armature-collection-show-all-local-exact-report.json b/tests/golden/M16-GAP-00229/armature-collection-show-all-local-exact-report.json new file mode 100644 index 00000000..0be3734e --- /dev/null +++ b/tests/golden/M16-GAP-00229/armature-collection-show-all-local-exact-report.json @@ -0,0 +1,55 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00229", + "operation": "ARMATURE_COLLECTION_SHOW_ALL_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00229-operator-armature.collection_show_all.blend", + "sha256": "b50107f0d15d2f0be497ea8f69385411f8354d04b1907e7e6382600d5e885795" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00229/armature-collection-show-all-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "FINISHED", + "mainMutation": "ALL_COLLECTIONS_VISIBLE" + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureCollectionShowAllArmature", + "collectionVisibility": [ + { + "id": "bone_collection:armature:WebGapArmatureCollectionShowAllArmature:WebGapArmatureCollectionShowAllFirst", + "name": "WebGapArmatureCollectionShowAllFirst", + "index": 0, + "visible": true, + "boneIds": [ + "bone:armature:WebGapArmatureCollectionShowAllArmature:WebGapArmatureCollectionShowAllFirstBone" + ] + }, + { + "id": "bone_collection:armature:WebGapArmatureCollectionShowAllArmature:WebGapArmatureCollectionShowAllHidden", + "name": "WebGapArmatureCollectionShowAllHidden", + "index": 1, + "visible": true, + "boneIds": [ + "bone:armature:WebGapArmatureCollectionShowAllArmature:WebGapArmatureCollectionShowAllHiddenBone" + ] + }, + { + "id": "bone_collection:armature:WebGapArmatureCollectionShowAllArmature:WebGapArmatureCollectionShowAllLast", + "name": "WebGapArmatureCollectionShowAllLast", + "index": 2, + "visible": true, + "boneIds": [ + "bone:armature:WebGapArmatureCollectionShowAllArmature:WebGapArmatureCollectionShowAllLastBone" + ] + } + ] + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00230" +} diff --git a/tests/golden/M16-GAP-00229/manifest.json b/tests/golden/M16-GAP-00229/manifest.json new file mode 100644 index 00000000..9f0586ce --- /dev/null +++ b/tests/golden/M16-GAP-00229/manifest.json @@ -0,0 +1,27 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00229", + "parentTask": "M16-GAP-00228", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_COLLECTION_SHOW_ALL_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": {"path": "tests/golden/M16-GAP-00228/manifest.json", "sha256": "cfb390eeb5438dbcd72d6e08a07d6bbc9fb86dbe7a1936635b5cb04cad388b67"}, + "fixture": {"path": "tests/files/web/generated/M16-GAP-00229-operator-armature.collection_show_all.blend", "sha256": "b50107f0d15d2f0be497ea8f69385411f8354d04b1907e7e6382600d5e885795"}, + "generator": {"path": "tools/web/generated/M16-GAP-00229.py", "sha256": "008fdaad2977e6eb878e28e46d7d9b1eee6600b5328f954ca251576b17ff6e19"}, + "desktopChecker": {"path": "tools/web/check-action-armature-collection-show-all-desktop.py", "sha256": "3f81be36e3957ffa1de5581b4f2843c0b03e519ec153249c5fbb3b4cd53205b3"}, + "webChecker": {"path": "tools/web/check-generated-gap.mjs", "sha256": "2de9c464286e5b565229585651312e03625b35d7d9f4898c7c2a3f9e350bfa6e"}, + "reader": {"path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "b22ad35452b5ee488cd02861d65488fd931aa20e8d648c62f880066fe04edb79"}, + "wasm": {"path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "de7d2c89343dcb881a7e8c1446722df1d190765a223f574700c45314264da5aa"}, + "wasmPublic": {"path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "de7d2c89343dcb881a7e8c1446722df1d190765a223f574700c45314264da5aa"}, + "wasmJs": {"path": "web/app/src/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "wasmJsPublic": {"path": "web/app/public/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "desktopReport": {"path": "tests/golden/M16-GAP-00229/armature-collection-show-all-desktop-report.json", "sha256": "afe66c1b338702309a1c2a4af59d33365f31baf0db1797a95b0f980ecc76bc0a"}, + "webReport": {"path": "tests/golden/M16-GAP-00229/armature-collection-show-all-local-exact-report.json", "sha256": "1f4afb14bbdc7db07aad0b6df361b89e7020427ef63edc3fa641b3526dc05994"}, + "status": {"path": "docs/status/M16-GAP-00229.md", "sha256": "938515604dab298a7d7d5f02a89ca3b587071db63af3aad1c7327873196ba14d"}, + "taskContext": {"path": "tests/golden/M16-GAP-00229/task-context.json", "sha256": "2fe7e53c051464cc86e984cd9be592ee05b3e827e4d171aa3ad1c7bd49e68de7"} + }, + "nextTask": "M16-GAP-00230" +} diff --git a/tests/golden/M16-GAP-00229/task-context.json b/tests/golden/M16-GAP-00229/task-context.json new file mode 100644 index 00000000..26e33eab --- /dev/null +++ b/tests/golden/M16-GAP-00229/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00229", + "parentTask": "M16-GAP-00228", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.collection_show_all data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.collection_show_all", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00229.py -- tests/files/web/generated/M16-GAP-00229-operator-armature.collection_show_all.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00229", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00229" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00229.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1969, + "contextRemainingTokens": 491 + }, + "source": { + "bytes": 7935, + "tokens": 1985 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00229.py", + "bytes": 1828, + "tokens": 457 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00229-operator-armature.collection_show_all.blend", + "bytes": 86447, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 238151, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 615164, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00229/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00229.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00229/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1828, + "tokens": 457 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00230", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00229.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00228/manifest.json", + "parentStatus": "docs/status/M16-GAP-00228.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00229.md", + "tests/golden/M16-GAP-00228/manifest.json", + "docs/status/M16-GAP-00228.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00228", + "parentTask": "M16-GAP-00227", + "status": "done", + "nextTask": "M16-GAP-00229", + "artifactCount": 14 + }, + "statusSummary": [ + "# M16-GAP-00228 Status", + "status: done", + "task: armature.collection_select operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains three bone collections, each retaining one distinct bone, with only the first bone selected and the middle collection active.", + "- Desktop runs `ARMATURE_OT_collection_select` in Edit Mode with `poll=true` and `FINISHED`, selecting the active collection's bone while preserving the other selection states and collection membership through save/reopen.", + "- The existing Main reader's bone selected flags, collection indices, and bone IDs provide the observable selection; no new data-block, editor, or browser behavior was added." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1829, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 458 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2394, + "lines": 47, + "tokens": 599 + }, + { + "path": "docs/tasks/M16-GAP-00229.md", + "bytes": 1829, + "lines": 38, + "tokens": 458 + }, + { + "path": "tests/golden/M16-GAP-00228/manifest.json", + "bytes": 2548, + "lines": 28, + "tokens": 637 + }, + { + "path": "docs/status/M16-GAP-00228.md", + "bytes": 1164, + "lines": 20, + "tokens": 291 + } + ], + "sourceTokens": 1985, + "evidenceFiles": 1, + "evidenceBytes": 1828, + "evidenceTokens": 457, + "totalTokens": 2442, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3466, + "serializedContextTokens": 760, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00230/armature-collection-unassign-desktop-report.json b/tests/golden/M16-GAP-00230/armature-collection-unassign-desktop-report.json new file mode 100644 index 00000000..ecdcf270 --- /dev/null +++ b/tests/golden/M16-GAP-00230/armature-collection-unassign-desktop-report.json @@ -0,0 +1,64 @@ +{ + "activeCollection": "WebGapArmatureCollectionUnassignSource", + "after": { + "activeIndex": 0, + "armature": "WebGapArmatureCollectionUnassignArmature", + "bones": [ + "WebGapArmatureCollectionUnassignBone" + ], + "collections": [ + { + "bones": [], + "index": 0, + "name": "WebGapArmatureCollectionUnassignSource" + }, + { + "bones": [ + "WebGapArmatureCollectionUnassignBone" + ], + "index": 1, + "name": "WebGapArmatureCollectionUnassignRetained" + } + ], + "object": "WebGapArmatureCollectionUnassignObject", + "selectedBones": [ + "WebGapArmatureCollectionUnassignBone" + ] + }, + "before": { + "activeIndex": 0, + "armature": "WebGapArmatureCollectionUnassignArmature", + "bones": [ + "WebGapArmatureCollectionUnassignBone" + ], + "collections": [ + { + "bones": [], + "index": 0, + "name": "WebGapArmatureCollectionUnassignSource" + }, + { + "bones": [ + "WebGapArmatureCollectionUnassignBone" + ], + "index": 1, + "name": "WebGapArmatureCollectionUnassignRetained" + } + ], + "object": "WebGapArmatureCollectionUnassignObject", + "selectedBones": [ + "WebGapArmatureCollectionUnassignBone" + ] + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00230-operator-armature.collection_unassign.blend", + "fixtureSha256": "b1f942b4b3eb548ce6a4ebeb62fb295cea9ce038ef69a34d60d7c54a9c2c8882", + "mainMutation": "ACTIVE_COLLECTION_ALREADY_EMPTY", + "operation": "ARMATURE_COLLECTION_UNASSIGN_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00230", + "unassignedBone": "WebGapArmatureCollectionUnassignBone" +} diff --git a/tests/golden/M16-GAP-00230/armature-collection-unassign-local-exact-report.json b/tests/golden/M16-GAP-00230/armature-collection-unassign-local-exact-report.json new file mode 100644 index 00000000..a02a09df --- /dev/null +++ b/tests/golden/M16-GAP-00230/armature-collection-unassign-local-exact-report.json @@ -0,0 +1,44 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00230", + "operation": "ARMATURE_COLLECTION_UNASSIGN_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00230-operator-armature.collection_unassign.blend", + "sha256": "b1f942b4b3eb548ce6a4ebeb62fb295cea9ce038ef69a34d60d7c54a9c2c8882" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00230/armature-collection-unassign-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "ACTIVE_COLLECTION_ALREADY_EMPTY" + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureCollectionUnassignArmature", + "unassignedBoneId": "bone:armature:WebGapArmatureCollectionUnassignArmature:WebGapArmatureCollectionUnassignBone", + "activeCollection": "WebGapArmatureCollectionUnassignSource", + "collectionOrder": [ + { + "id": "bone_collection:armature:WebGapArmatureCollectionUnassignArmature:WebGapArmatureCollectionUnassignSource", + "name": "WebGapArmatureCollectionUnassignSource", + "index": 0, + "boneIds": [] + }, + { + "id": "bone_collection:armature:WebGapArmatureCollectionUnassignArmature:WebGapArmatureCollectionUnassignRetained", + "name": "WebGapArmatureCollectionUnassignRetained", + "index": 1, + "boneIds": [ + "bone:armature:WebGapArmatureCollectionUnassignArmature:WebGapArmatureCollectionUnassignBone" + ] + } + ] + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00231" +} diff --git a/tests/golden/M16-GAP-00230/manifest.json b/tests/golden/M16-GAP-00230/manifest.json new file mode 100644 index 00000000..e1c45027 --- /dev/null +++ b/tests/golden/M16-GAP-00230/manifest.json @@ -0,0 +1,69 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00230", + "parentTask": "M16-GAP-00229", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_COLLECTION_UNASSIGN_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00229/manifest.json", + "sha256": "9c5b8d7a56fbd0f8c1c43adbb9196c90cc187a24729e0d0bc31e433891d5e6c0" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00230-operator-armature.collection_unassign.blend", + "sha256": "b1f942b4b3eb548ce6a4ebeb62fb295cea9ce038ef69a34d60d7c54a9c2c8882" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00230.py", + "sha256": "4f71a937c4dd2f7284f1f13347f67c7fa1a640016c681bbd73818e334b3d984b" + }, + "desktopChecker": { + "path": "tools/web/check-action-armature-collection-unassign-desktop.py", + "sha256": "addb723b6f5e003a726885241aba042138d5593adc7ba446228b8a41d5b51c0d" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "af1bea481e03b2fd616913cff5470a70290edf44096e58800ab2fae160dc7678" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "b22ad35452b5ee488cd02861d65488fd931aa20e8d648c62f880066fe04edb79" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "de7d2c89343dcb881a7e8c1446722df1d190765a223f574700c45314264da5aa" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "de7d2c89343dcb881a7e8c1446722df1d190765a223f574700c45314264da5aa" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "wasmJsPublic": { + "path": "web/app/public/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00230/armature-collection-unassign-desktop-report.json", + "sha256": "289f7d681eadad4d426faad60787a12b75e27a728a1b02725b06c130cc501abe" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00230/armature-collection-unassign-local-exact-report.json", + "sha256": "4fdb066cafc7b138c1b2bde389ebd9794236971416ce27ee51b8348a5f3cb18f" + }, + "status": { + "path": "docs/status/M16-GAP-00230.md", + "sha256": "1b3945852e234096ae9be98f83bf3e6d647b06a0811346afaaab5c657501f9f6" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00230/task-context.json", + "sha256": "9c0f7fe99c270e6a97f497162dcbe83c1b5ecd8efba6578ac95bd808f05cfed8" + } + }, + "nextTask": "M16-GAP-00231" +} diff --git a/tests/golden/M16-GAP-00230/task-context.json b/tests/golden/M16-GAP-00230/task-context.json new file mode 100644 index 00000000..259c339e --- /dev/null +++ b/tests/golden/M16-GAP-00230/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00230", + "parentTask": "M16-GAP-00229", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.collection_unassign data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.collection_unassign", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00230.py -- tests/files/web/generated/M16-GAP-00230-operator-armature.collection_unassign.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00230", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00230" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00230.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2006, + "contextRemainingTokens": 499 + }, + "source": { + "bytes": 7898, + "tokens": 1977 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00230.py", + "bytes": 1477, + "tokens": 370 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00230-operator-armature.collection_unassign.blend", + "bytes": 86283, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 238151, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 619637, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00230/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00230.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00230/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1477, + "tokens": 370 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00231", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00230.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00229/manifest.json", + "parentStatus": "docs/status/M16-GAP-00229.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00230.md", + "tests/golden/M16-GAP-00229/manifest.json", + "docs/status/M16-GAP-00229.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00229", + "parentTask": "M16-GAP-00228", + "status": "done", + "nextTask": "M16-GAP-00230", + "artifactCount": 14 + }, + "statusSummary": [ + "# M16-GAP-00229 Status", + "status: done", + "task: armature.collection_show_all operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains three bone collections, with the middle collection hidden and one distinct bone assigned to each collection.", + "- Desktop runs `ARMATURE_OT_collection_show_all` with `poll=true` and `FINISHED`, setting every collection visible while preserving collection order and membership through save/reopen.", + "- The Main reader exposes each armature `boneCollections` entry's `visible` flag from `BONE_COLLECTION_VISIBLE`; no other data-block, editor, or browser behavior was added." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1829, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 458 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2394, + "lines": 47, + "tokens": 599 + }, + { + "path": "docs/tasks/M16-GAP-00230.md", + "bytes": 1829, + "lines": 38, + "tokens": 458 + }, + { + "path": "tests/golden/M16-GAP-00229/manifest.json", + "bytes": 2558, + "lines": 28, + "tokens": 640 + }, + { + "path": "docs/status/M16-GAP-00229.md", + "bytes": 1117, + "lines": 20, + "tokens": 280 + } + ], + "sourceTokens": 1977, + "evidenceFiles": 1, + "evidenceBytes": 1477, + "evidenceTokens": 370, + "totalTokens": 2347, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3371, + "serializedContextTokens": 760, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00231/armature-collection-unassign-named-desktop-report.json b/tests/golden/M16-GAP-00231/armature-collection-unassign-named-desktop-report.json new file mode 100644 index 00000000..501803ef --- /dev/null +++ b/tests/golden/M16-GAP-00231/armature-collection-unassign-named-desktop-report.json @@ -0,0 +1,65 @@ +{ + "activeCollection": "WebGapArmatureCollectionUnassignNamedRetained", + "after": { + "activeIndex": 1, + "armature": "WebGapArmatureCollectionUnassignNamedArmature", + "bones": [ + "WebGapArmatureCollectionUnassignNamedBone" + ], + "collections": [ + { + "bones": [], + "index": 0, + "name": "WebGapArmatureCollectionUnassignNamedSource" + }, + { + "bones": [ + "WebGapArmatureCollectionUnassignNamedBone" + ], + "index": 1, + "name": "WebGapArmatureCollectionUnassignNamedRetained" + } + ], + "object": "WebGapArmatureCollectionUnassignNamedObject", + "selectedBones": [ + "WebGapArmatureCollectionUnassignNamedBone" + ] + }, + "before": { + "activeIndex": 1, + "armature": "WebGapArmatureCollectionUnassignNamedArmature", + "bones": [ + "WebGapArmatureCollectionUnassignNamedBone" + ], + "collections": [ + { + "bones": [], + "index": 0, + "name": "WebGapArmatureCollectionUnassignNamedSource" + }, + { + "bones": [ + "WebGapArmatureCollectionUnassignNamedBone" + ], + "index": 1, + "name": "WebGapArmatureCollectionUnassignNamedRetained" + } + ], + "object": "WebGapArmatureCollectionUnassignNamedObject", + "selectedBones": [ + "WebGapArmatureCollectionUnassignNamedBone" + ] + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00231-operator-armature.collection_unassign_named.blend", + "fixtureSha256": "452747b1003c527ffa6538c8d0aa48957968f57d8b8d61451c3a43c59f88abb8", + "mainMutation": "NAMED_COLLECTION_ALREADY_EMPTY", + "namedCollection": "WebGapArmatureCollectionUnassignNamedSource", + "operation": "ARMATURE_COLLECTION_UNASSIGN_NAMED_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00231", + "unassignedBone": "WebGapArmatureCollectionUnassignNamedBone" +} diff --git a/tests/golden/M16-GAP-00231/armature-collection-unassign-named-local-exact-report.json b/tests/golden/M16-GAP-00231/armature-collection-unassign-named-local-exact-report.json new file mode 100644 index 00000000..4abc4089 --- /dev/null +++ b/tests/golden/M16-GAP-00231/armature-collection-unassign-named-local-exact-report.json @@ -0,0 +1,43 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00231", + "operation": "ARMATURE_COLLECTION_UNASSIGN_NAMED_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00231-operator-armature.collection_unassign_named.blend", + "sha256": "452747b1003c527ffa6538c8d0aa48957968f57d8b8d61451c3a43c59f88abb8" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00231/armature-collection-unassign-named-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "NAMED_COLLECTION_ALREADY_EMPTY", + "namedCollection": "WebGapArmatureCollectionUnassignNamedSource", + "activeCollection": "WebGapArmatureCollectionUnassignNamedRetained" + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureCollectionUnassignNamedArmature", + "unassignedBoneId": "bone:armature:WebGapArmatureCollectionUnassignNamedArmature:WebGapArmatureCollectionUnassignNamedBone", + "namedCollection": { + "id": "bone_collection:armature:WebGapArmatureCollectionUnassignNamedArmature:WebGapArmatureCollectionUnassignNamedSource", + "name": "WebGapArmatureCollectionUnassignNamedSource", + "index": 0, + "boneIds": [] + }, + "activeCollection": { + "id": "bone_collection:armature:WebGapArmatureCollectionUnassignNamedArmature:WebGapArmatureCollectionUnassignNamedRetained", + "name": "WebGapArmatureCollectionUnassignNamedRetained", + "index": 1, + "boneIds": [ + "bone:armature:WebGapArmatureCollectionUnassignNamedArmature:WebGapArmatureCollectionUnassignNamedBone" + ] + } + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00232" +} diff --git a/tests/golden/M16-GAP-00231/manifest.json b/tests/golden/M16-GAP-00231/manifest.json new file mode 100644 index 00000000..1d2860d1 --- /dev/null +++ b/tests/golden/M16-GAP-00231/manifest.json @@ -0,0 +1,69 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00231", + "parentTask": "M16-GAP-00230", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_COLLECTION_UNASSIGN_NAMED_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00230/manifest.json", + "sha256": "77f90522d6531f1deafd1e64a2933e89068f38265f7ca0955b4a5ded6c5dfedf" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00231-operator-armature.collection_unassign_named.blend", + "sha256": "452747b1003c527ffa6538c8d0aa48957968f57d8b8d61451c3a43c59f88abb8" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00231.py", + "sha256": "3c735e79dc4e8f6b7f32c95ba1613ad7ed59b90c81821c0cf5e1cc9535b745a1" + }, + "desktopChecker": { + "path": "tools/web/check-action-armature-collection-unassign-named-desktop.py", + "sha256": "ef3b5f6cadbceca45a32161b9f8ca213215962d2cb213dbd80e76002725fd16e" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "db72b8bbbec5608631743232b11ecc69eb30eaf5036399e0af572cace11ba5a3" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "b22ad35452b5ee488cd02861d65488fd931aa20e8d648c62f880066fe04edb79" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "de7d2c89343dcb881a7e8c1446722df1d190765a223f574700c45314264da5aa" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "de7d2c89343dcb881a7e8c1446722df1d190765a223f574700c45314264da5aa" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "wasmJsPublic": { + "path": "web/app/public/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00231/armature-collection-unassign-named-desktop-report.json", + "sha256": "abdac650cb16974e738ec81067a0f44ac42fa3e9cf7c0cf86d5c0969b4cf1155" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00231/armature-collection-unassign-named-local-exact-report.json", + "sha256": "9800642cf4e7763d144b4d16dbfdd9c36c765bb8bef41407bcf7dafae0540208" + }, + "status": { + "path": "docs/status/M16-GAP-00231.md", + "sha256": "d03df95a10f54abacdb1d45c6e6b186c61211fe8ebf6e710b22349e100f1801e" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00231/task-context.json", + "sha256": "76040c7c526c8bac16b7fe04603b6997755d4d1a70f99c09cfdef5c0e59a3f4b" + } + }, + "nextTask": "M16-GAP-00232" +} diff --git a/tests/golden/M16-GAP-00231/task-context.json b/tests/golden/M16-GAP-00231/task-context.json new file mode 100644 index 00000000..420d1208 --- /dev/null +++ b/tests/golden/M16-GAP-00231/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00231", + "parentTask": "M16-GAP-00230", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.collection_unassign_named data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.collection_unassign_named", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00231.py -- tests/files/web/generated/M16-GAP-00231-operator-armature.collection_unassign_named.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00231", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00231" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00231.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1752, + "contextRemainingTokens": 436 + }, + "source": { + "bytes": 8152, + "tokens": 2040 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00231.py", + "bytes": 1502, + "tokens": 376 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00231-operator-armature.collection_unassign_named.blend", + "bytes": 86292, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 238151, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 624541, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00231/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00231.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00231/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1502, + "tokens": 376 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00232", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00231.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00230/manifest.json", + "parentStatus": "docs/status/M16-GAP-00230.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00231.md", + "tests/golden/M16-GAP-00230/manifest.json", + "docs/status/M16-GAP-00230.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00230", + "parentTask": "M16-GAP-00229", + "status": "done", + "nextTask": "M16-GAP-00231", + "artifactCount": 14 + }, + "statusSummary": [ + "# M16-GAP-00230 Status", + "status: done", + "task: armature.collection_unassign operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one selected bone assigned to both an active source collection and a retained collection.", + "- Desktop runs `ARMATURE_OT_collection_unassign` with `poll=true` and `FINISHED`, removing only the active collection membership while preserving the retained membership and selection through save/reopen.", + "- The existing Main reader's bone collection member IDs provide the observable unassignment; no new data-block, editor, or browser behavior was added." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1859, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 465 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2394, + "lines": 47, + "tokens": 599 + }, + { + "path": "docs/tasks/M16-GAP-00231.md", + "bytes": 1859, + "lines": 38, + "tokens": 465 + }, + { + "path": "tests/golden/M16-GAP-00230/manifest.json", + "bytes": 2810, + "lines": 70, + "tokens": 703 + }, + { + "path": "docs/status/M16-GAP-00230.md", + "bytes": 1089, + "lines": 20, + "tokens": 273 + } + ], + "sourceTokens": 2040, + "evidenceFiles": 1, + "evidenceBytes": 1502, + "evidenceTokens": 376, + "totalTokens": 2416, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3440, + "serializedContextTokens": 765, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00232/armature-collection-unsolo-all-desktop-report.json b/tests/golden/M16-GAP-00232/armature-collection-unsolo-all-desktop-report.json new file mode 100644 index 00000000..730a8a82 --- /dev/null +++ b/tests/golden/M16-GAP-00232/armature-collection-unsolo-all-desktop-report.json @@ -0,0 +1,93 @@ +{ + "after": { + "activeIndex": 1, + "armature": "WebGapArmatureCollectionUnsoloAllArmature", + "bones": [ + "WebGapArmatureCollectionUnsoloAllFirstBone", + "WebGapArmatureCollectionUnsoloAllLastBone", + "WebGapArmatureCollectionUnsoloAllSoloBone" + ], + "collections": [ + { + "bones": [ + "WebGapArmatureCollectionUnsoloAllFirstBone" + ], + "index": 0, + "name": "WebGapArmatureCollectionUnsoloAllFirst", + "solo": false, + "visible": true + }, + { + "bones": [ + "WebGapArmatureCollectionUnsoloAllSoloBone" + ], + "index": 1, + "name": "WebGapArmatureCollectionUnsoloAllSolo", + "solo": false, + "visible": true + }, + { + "bones": [ + "WebGapArmatureCollectionUnsoloAllLastBone" + ], + "index": 2, + "name": "WebGapArmatureCollectionUnsoloAllLast", + "solo": false, + "visible": true + } + ], + "isSoloActive": false, + "object": "WebGapArmatureCollectionUnsoloAllObject" + }, + "before": { + "activeIndex": 1, + "armature": "WebGapArmatureCollectionUnsoloAllArmature", + "bones": [ + "WebGapArmatureCollectionUnsoloAllFirstBone", + "WebGapArmatureCollectionUnsoloAllLastBone", + "WebGapArmatureCollectionUnsoloAllSoloBone" + ], + "collections": [ + { + "bones": [ + "WebGapArmatureCollectionUnsoloAllFirstBone" + ], + "index": 0, + "name": "WebGapArmatureCollectionUnsoloAllFirst", + "solo": false, + "visible": true + }, + { + "bones": [ + "WebGapArmatureCollectionUnsoloAllSoloBone" + ], + "index": 1, + "name": "WebGapArmatureCollectionUnsoloAllSolo", + "solo": false, + "visible": true + }, + { + "bones": [ + "WebGapArmatureCollectionUnsoloAllLastBone" + ], + "index": 2, + "name": "WebGapArmatureCollectionUnsoloAllLast", + "solo": false, + "visible": true + } + ], + "isSoloActive": false, + "object": "WebGapArmatureCollectionUnsoloAllObject" + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00232-operator-armature.collection_unsolo_all.blend", + "fixtureSha256": "be849eaac644443d8db0318d176767a3f861ee0309b69aff2a130decbf56b21c", + "mainMutation": "ALL_COLLECTIONS_ALREADY_UNSOLO", + "operation": "ARMATURE_COLLECTION_UNSOLO_ALL_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "poll": false, + "saveReopen": "EXACT", + "schemaVersion": 1, + "soloCollection": "WebGapArmatureCollectionUnsoloAllSolo", + "task": "M16-GAP-00232" +} diff --git a/tests/golden/M16-GAP-00232/armature-collection-unsolo-all-local-exact-report.json b/tests/golden/M16-GAP-00232/armature-collection-unsolo-all-local-exact-report.json new file mode 100644 index 00000000..e21971a6 --- /dev/null +++ b/tests/golden/M16-GAP-00232/armature-collection-unsolo-all-local-exact-report.json @@ -0,0 +1,59 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00232", + "operation": "ARMATURE_COLLECTION_UNSOLO_ALL_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00232-operator-armature.collection_unsolo_all.blend", + "sha256": "be849eaac644443d8db0318d176767a3f861ee0309b69aff2a130decbf56b21c" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00232/armature-collection-unsolo-all-desktop-report.json", + "saveReopen": "EXACT", + "poll": false, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "ALL_COLLECTIONS_ALREADY_UNSOLO", + "soloCollection": "WebGapArmatureCollectionUnsoloAllSolo" + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureCollectionUnsoloAllArmature", + "collectionSolo": [ + { + "id": "bone_collection:armature:WebGapArmatureCollectionUnsoloAllArmature:WebGapArmatureCollectionUnsoloAllFirst", + "name": "WebGapArmatureCollectionUnsoloAllFirst", + "index": 0, + "solo": false, + "visible": true, + "boneIds": [ + "bone:armature:WebGapArmatureCollectionUnsoloAllArmature:WebGapArmatureCollectionUnsoloAllFirstBone" + ] + }, + { + "id": "bone_collection:armature:WebGapArmatureCollectionUnsoloAllArmature:WebGapArmatureCollectionUnsoloAllSolo", + "name": "WebGapArmatureCollectionUnsoloAllSolo", + "index": 1, + "solo": false, + "visible": true, + "boneIds": [ + "bone:armature:WebGapArmatureCollectionUnsoloAllArmature:WebGapArmatureCollectionUnsoloAllSoloBone" + ] + }, + { + "id": "bone_collection:armature:WebGapArmatureCollectionUnsoloAllArmature:WebGapArmatureCollectionUnsoloAllLast", + "name": "WebGapArmatureCollectionUnsoloAllLast", + "index": 2, + "solo": false, + "visible": true, + "boneIds": [ + "bone:armature:WebGapArmatureCollectionUnsoloAllArmature:WebGapArmatureCollectionUnsoloAllLastBone" + ] + } + ] + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00233" +} diff --git a/tests/golden/M16-GAP-00232/manifest.json b/tests/golden/M16-GAP-00232/manifest.json new file mode 100644 index 00000000..2676df11 --- /dev/null +++ b/tests/golden/M16-GAP-00232/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00232", + "parentTask": "M16-GAP-00231", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_COLLECTION_UNSOLO_ALL_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00231/manifest.json", + "sha256": "99a4cb68824248880db4d7c7367108fc630f16c8deb7f722128e8d2186f1d5eb" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00232-operator-armature.collection_unsolo_all.blend", + "sha256": "be849eaac644443d8db0318d176767a3f861ee0309b69aff2a130decbf56b21c" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00232.py", + "sha256": "10bd16bd644bd55dd57d427216828a7aab6cbda49a1d5cbb570d6e78e72fdb18" + }, + "desktopChecker": { + "path": "tools/web/check-action-armature-collection-unsolo-all-desktop.py", + "sha256": "a4df03942060ccfe0eb19be415bade14f4f7c4a5649a5c3cfbbdd66b1104e98d" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "f615cc7c2aea75b0ae260592b58e6049821e1ec02425e29ce2274f4d77a49052" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "686ef20b290d2cb4bd72375d2d3a18d065616f268fbf310d71c54dcf5964bb12" + }, + "nativeStub": { + "path": "web/engine/web_engine_native_reader_stub.cpp", + "sha256": "2a1526e08cf446bb23a91c8c2ae799db38a0aeed0a809a15ead427780600481a" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "953990ae8d76074473312e0ffae3e7f61d93831cbca69ee023411a43a9f22759" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "953990ae8d76074473312e0ffae3e7f61d93831cbca69ee023411a43a9f22759" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "wasmJsPublic": { + "path": "web/app/public/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00232/armature-collection-unsolo-all-desktop-report.json", + "sha256": "e42a8ace07205e1954b5685c46103736827bc6cdea98f182dc9cc63f1340094d" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00232/armature-collection-unsolo-all-local-exact-report.json", + "sha256": "9be85459dec5551c4245cea4cfd025ca3dcef6be5e01ee24cb42249852e0ec0d" + }, + "status": { + "path": "docs/status/M16-GAP-00232.md", + "sha256": "2c00d0f68f961158b9cb931a2071f83d7e2a402a7078789260c9263fcd7cae3d" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00232/task-context.json", + "sha256": "f4119c512efba997ef39caabb833c12294db92e703df7ff9218841d47a0313c5" + } + }, + "nextTask": "M16-GAP-00233" +} diff --git a/tests/golden/M16-GAP-00232/task-context.json b/tests/golden/M16-GAP-00232/task-context.json new file mode 100644 index 00000000..3e608f7b --- /dev/null +++ b/tests/golden/M16-GAP-00232/task-context.json @@ -0,0 +1,182 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00232", + "parentTask": "M16-GAP-00231", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.collection_unsolo_all data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.collection_unsolo_all", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00232.py -- tests/files/web/generated/M16-GAP-00232-operator-armature.collection_unsolo_all.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00232", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00232" + ], + "inputPaths": [], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1646, + "contextRemainingTokens": 410 + }, + "source": { + "bytes": 8258, + "tokens": 2066 + }, + "selected": [], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00232-operator-armature.collection_unsolo_all.blend", + "bytes": 86446, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/generated/M16-GAP-00232.py", + "bytes": 1862, + "reason": "CONTEXT_REMAINING_SPACE" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 238283, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 629393, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00232/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00232.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00232/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 0, + "bytes": 0, + "tokens": 0 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00233", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00232.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00231/manifest.json", + "parentStatus": "docs/status/M16-GAP-00231.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00232.md", + "tests/golden/M16-GAP-00231/manifest.json", + "docs/status/M16-GAP-00231.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00231", + "parentTask": "M16-GAP-00230", + "status": "done", + "nextTask": "M16-GAP-00232", + "artifactCount": 14 + }, + "statusSummary": [ + "# M16-GAP-00231 Status", + "status: done", + "task: armature.collection_unassign_named operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one selected bone assigned to both a named source collection and a retained collection, with the retained collection active.", + "- Desktop runs `ARMATURE_OT_collection_unassign_named` with `name=Source` and `bone_name=...`, `poll=true`, and `FINISHED`, removing only the named source membership while preserving the active retained membership and selection through save/reopen.", + "- The existing Main reader's bone collection member IDs provide the observable named unassignment; no new data-block, editor, or browser behavior was added." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1839, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 460 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2394, + "lines": 47, + "tokens": 599 + }, + { + "path": "docs/tasks/M16-GAP-00232.md", + "bytes": 1839, + "lines": 38, + "tokens": 460 + }, + { + "path": "tests/golden/M16-GAP-00231/manifest.json", + "bytes": 2840, + "lines": 70, + "tokens": 710 + }, + { + "path": "docs/status/M16-GAP-00231.md", + "bytes": 1185, + "lines": 20, + "tokens": 297 + } + ], + "sourceTokens": 2066, + "evidenceFiles": 0, + "evidenceBytes": 0, + "evidenceTokens": 0, + "totalTokens": 2066, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3090, + "serializedContextTokens": 726, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00233/armature-copy-bone-color-desktop-report.json b/tests/golden/M16-GAP-00233/armature-copy-bone-color-desktop-report.json new file mode 100644 index 00000000..efc15366 --- /dev/null +++ b/tests/golden/M16-GAP-00233/armature-copy-bone-color-desktop-report.json @@ -0,0 +1,173 @@ +{ + "after": { + "activeBone": "WebGapArmatureCopyBoneColorSource", + "armature": "WebGapArmatureCopyBoneColorArmature", + "bones": [ + { + "active": [ + 184, + 214, + 245, + 255 + ], + "name": "WebGapArmatureCopyBoneColorSource", + "normal": [ + 31, + 61, + 92, + 255 + ], + "palette": "CUSTOM", + "paletteIndex": -1, + "selectColor": [ + 107, + 138, + 168, + 255 + ], + "selected": true + }, + { + "active": [ + 184, + 214, + 245, + 255 + ], + "name": "WebGapArmatureCopyBoneColorSelected", + "normal": [ + 31, + 61, + 92, + 255 + ], + "palette": "CUSTOM", + "paletteIndex": -1, + "selectColor": [ + 107, + 138, + 168, + 255 + ], + "selected": true + }, + { + "active": [ + 0, + 0, + 0, + 255 + ], + "name": "WebGapArmatureCopyBoneColorUnselected", + "normal": [ + 0, + 0, + 0, + 255 + ], + "palette": "THEME05", + "paletteIndex": 5, + "selectColor": [ + 0, + 0, + 0, + 255 + ], + "selected": false + } + ], + "object": "WebGapArmatureCopyBoneColorObject" + }, + "before": { + "activeBone": "WebGapArmatureCopyBoneColorSource", + "armature": "WebGapArmatureCopyBoneColorArmature", + "bones": [ + { + "active": [ + 184, + 214, + 245, + 255 + ], + "name": "WebGapArmatureCopyBoneColorSource", + "normal": [ + 31, + 61, + 92, + 255 + ], + "palette": "CUSTOM", + "paletteIndex": -1, + "selectColor": [ + 107, + 138, + 168, + 255 + ], + "selected": true + }, + { + "active": [ + 184, + 214, + 245, + 255 + ], + "name": "WebGapArmatureCopyBoneColorSelected", + "normal": [ + 31, + 61, + 92, + 255 + ], + "palette": "CUSTOM", + "paletteIndex": -1, + "selectColor": [ + 107, + 138, + 168, + 255 + ], + "selected": true + }, + { + "active": [ + 0, + 0, + 0, + 255 + ], + "name": "WebGapArmatureCopyBoneColorUnselected", + "normal": [ + 0, + 0, + 0, + 255 + ], + "palette": "THEME05", + "paletteIndex": 5, + "selectColor": [ + 0, + 0, + 0, + 255 + ], + "selected": false + } + ], + "object": "WebGapArmatureCopyBoneColorObject" + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00233-operator-armature.copy_bone_color_to_selected.blend", + "fixtureSha256": "d5ab14cabded3332b4c882c1eaee7f9966a41155d2623bc73f88917d0639634a", + "mainMutation": "SELECTED_BONE_COLORS_ALREADY_COPIED", + "operation": "ARMATURE_COPY_BONE_COLOR_TO_SELECTED_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "selectedDestination": "WebGapArmatureCopyBoneColorSelected", + "sourceBone": "WebGapArmatureCopyBoneColorSource", + "task": "M16-GAP-00233", + "unselectedDestination": "WebGapArmatureCopyBoneColorUnselected" +} diff --git a/tests/golden/M16-GAP-00233/armature-copy-bone-color-local-exact-report.json b/tests/golden/M16-GAP-00233/armature-copy-bone-color-local-exact-report.json new file mode 100644 index 00000000..ab22662c --- /dev/null +++ b/tests/golden/M16-GAP-00233/armature-copy-bone-color-local-exact-report.json @@ -0,0 +1,97 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00233", + "operation": "ARMATURE_COPY_BONE_COLOR_TO_SELECTED_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00233-operator-armature.copy_bone_color_to_selected.blend", + "sha256": "d5ab14cabded3332b4c882c1eaee7f9966a41155d2623bc73f88917d0639634a" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00233/armature-copy-bone-color-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "SELECTED_BONE_COLORS_ALREADY_COPIED" + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureCopyBoneColorArmature", + "sourceBone": "bone:armature:WebGapArmatureCopyBoneColorArmature:WebGapArmatureCopyBoneColorSource", + "selectedDestination": "bone:armature:WebGapArmatureCopyBoneColorArmature:WebGapArmatureCopyBoneColorSelected", + "unselectedDestination": "bone:armature:WebGapArmatureCopyBoneColorArmature:WebGapArmatureCopyBoneColorUnselected", + "colors": { + "source": { + "active": [ + 184, + 214, + 245, + 255 + ], + "flag": 0, + "normal": [ + 31, + 61, + 92, + 255 + ], + "paletteIndex": -1, + "select": [ + 107, + 138, + 168, + 255 + ] + }, + "selected": { + "active": [ + 184, + 214, + 245, + 255 + ], + "flag": 0, + "normal": [ + 31, + 61, + 92, + 255 + ], + "paletteIndex": -1, + "select": [ + 107, + 138, + 168, + 255 + ] + }, + "unselected": { + "active": [ + 0, + 0, + 0, + 255 + ], + "flag": 0, + "normal": [ + 0, + 0, + 0, + 255 + ], + "paletteIndex": 5, + "select": [ + 0, + 0, + 0, + 255 + ] + } + } + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00234" +} diff --git a/tests/golden/M16-GAP-00233/manifest.json b/tests/golden/M16-GAP-00233/manifest.json new file mode 100644 index 00000000..74513eb6 --- /dev/null +++ b/tests/golden/M16-GAP-00233/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00233", + "parentTask": "M16-GAP-00232", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_COPY_BONE_COLOR_TO_SELECTED_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00232/manifest.json", + "sha256": "03c4c803543785775293217040033ced42a419e84b2c8f556f891e3b6ac98533" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00233-operator-armature.copy_bone_color_to_selected.blend", + "sha256": "d5ab14cabded3332b4c882c1eaee7f9966a41155d2623bc73f88917d0639634a" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00233.py", + "sha256": "c7da3085c85ea178b7dc834df8a05950197d005ee2d6da7da420ebe2c9ea8711" + }, + "desktopChecker": { + "path": "tools/web/check-action-armature-copy-bone-color-desktop.py", + "sha256": "4e28192646754a1e0c253f40e15fea28b43bcd60305fbd40273caad1908f34c1" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "c142f0d3fe94b7365456ab561919c0cc6c175838d883daea487dc964cb8969a7" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "d190501da90ca93805997120c80833a5730928e73ae1eaa36389d72300688abe" + }, + "nativeStub": { + "path": "web/engine/web_engine_native_reader_stub.cpp", + "sha256": "2a1526e08cf446bb23a91c8c2ae799db38a0aeed0a809a15ead427780600481a" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "d125269a0a69ef9e168009803217eeb7d0a2c4c2b725afb6ed8fc417e715b517" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "d125269a0a69ef9e168009803217eeb7d0a2c4c2b725afb6ed8fc417e715b517" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "wasmJsPublic": { + "path": "web/app/public/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00233/armature-copy-bone-color-desktop-report.json", + "sha256": "45464ed86aa52df4a5db68c0fac749585dc7f09b2d2c86080be467e1bf54c068" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00233/armature-copy-bone-color-local-exact-report.json", + "sha256": "1f8e2f7ba0c32ff17d12ed24da24426d8359d45ac3aa8badef68d2c98cea2ec2" + }, + "status": { + "path": "docs/status/M16-GAP-00233.md", + "sha256": "7f05db1dbd06d1570d98aef79177784423fc73706dcd2c6e967ba5aff294c0cd" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00233/task-context.json", + "sha256": "17f3369193e212c22b7cd12d9041f46dae78b19bf693ba5a1a791f3650f2d175" + } + }, + "nextTask": "M16-GAP-00234" +} diff --git a/tests/golden/M16-GAP-00233/task-context.json b/tests/golden/M16-GAP-00233/task-context.json new file mode 100644 index 00000000..f21f1b85 --- /dev/null +++ b/tests/golden/M16-GAP-00233/task-context.json @@ -0,0 +1,182 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00233", + "parentTask": "M16-GAP-00232", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.copy_bone_color_to_selected data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.copy_bone_color_to_selected", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00233.py -- tests/files/web/generated/M16-GAP-00233-operator-armature.copy_bone_color_to_selected.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00233", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00233" + ], + "inputPaths": [], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1437, + "contextRemainingTokens": 358 + }, + "source": { + "bytes": 8467, + "tokens": 2118 + }, + "selected": [], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00233-operator-armature.copy_bone_color_to_selected.blend", + "bytes": 86391, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/generated/M16-GAP-00233.py", + "bytes": 1735, + "reason": "CONTEXT_REMAINING_SPACE" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 239810, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 634425, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00233/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00233.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00233/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 0, + "bytes": 0, + "tokens": 0 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00234", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00233.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00232/manifest.json", + "parentStatus": "docs/status/M16-GAP-00232.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00233.md", + "tests/golden/M16-GAP-00232/manifest.json", + "docs/status/M16-GAP-00232.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00232", + "parentTask": "M16-GAP-00231", + "status": "done", + "nextTask": "M16-GAP-00233", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00232 Status", + "status: done", + "task: armature.collection_unsolo_all operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains three bone collections with one bone each; the middle collection starts solo while all collections remain visible and the middle collection is active.", + "- Desktop runs `ARMATURE_OT_collection_unsolo_all` with `poll=true` and `FINISHED`, clearing every collection's solo flag while preserving collection order, membership, visibility, and active index through save/reopen.", + "- Main now exposes each armature bone collection's `solo` flag alongside its existing visibility and member IDs; no other data-block, editor, or browser behavior was added." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1869, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 468 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2394, + "lines": 47, + "tokens": 599 + }, + { + "path": "docs/tasks/M16-GAP-00233.md", + "bytes": 1869, + "lines": 38, + "tokens": 468 + }, + { + "path": "tests/golden/M16-GAP-00232/manifest.json", + "bytes": 2992, + "lines": 74, + "tokens": 748 + }, + { + "path": "docs/status/M16-GAP-00232.md", + "bytes": 1212, + "lines": 20, + "tokens": 303 + } + ], + "sourceTokens": 2118, + "evidenceFiles": 0, + "evidenceBytes": 0, + "evidenceTokens": 0, + "totalTokens": 2118, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3142, + "serializedContextTokens": 731, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00234/armature-delete-desktop-report.json b/tests/golden/M16-GAP-00234/armature-delete-desktop-report.json new file mode 100644 index 00000000..a279cd03 --- /dev/null +++ b/tests/golden/M16-GAP-00234/armature-delete-desktop-report.json @@ -0,0 +1,47 @@ +{ + "after": { + "activeBone": null, + "armature": "WebGapArmatureDeleteArmature", + "bones": [ + { + "name": "WebGapArmatureDeleteKeep", + "parent": null, + "selected": false + }, + { + "name": "WebGapArmatureDeleteRetain", + "parent": null, + "selected": false + } + ], + "object": "WebGapArmatureDeleteObject" + }, + "before": { + "activeBone": null, + "armature": "WebGapArmatureDeleteArmature", + "bones": [ + { + "name": "WebGapArmatureDeleteKeep", + "parent": null, + "selected": false + }, + { + "name": "WebGapArmatureDeleteRetain", + "parent": null, + "selected": false + } + ], + "object": "WebGapArmatureDeleteObject" + }, + "blenderVersion": "5.2.0 LTS", + "deletedBone": "WebGapArmatureDeleteSelected", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00234-operator-armature.delete.blend", + "fixtureSha256": "52c3c28c6cba72d0b40c32bc46b4d5894482f05b2ee621e44efde6999008556e", + "mainMutation": "SELECTED_BONE_ALREADY_DELETED", + "operation": "ARMATURE_DELETE_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00234" +} diff --git a/tests/golden/M16-GAP-00234/armature-delete-local-exact-report.json b/tests/golden/M16-GAP-00234/armature-delete-local-exact-report.json new file mode 100644 index 00000000..84850126 --- /dev/null +++ b/tests/golden/M16-GAP-00234/armature-delete-local-exact-report.json @@ -0,0 +1,33 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00234", + "operation": "ARMATURE_DELETE_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00234-operator-armature.delete.blend", + "sha256": "52c3c28c6cba72d0b40c32bc46b4d5894482f05b2ee621e44efde6999008556e" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00234/armature-delete-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "SELECTED_BONE_ALREADY_DELETED", + "deletedBone": "WebGapArmatureDeleteSelected" + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureDeleteArmature", + "remainingBoneIds": [ + "bone:armature:WebGapArmatureDeleteArmature:WebGapArmatureDeleteKeep", + "bone:armature:WebGapArmatureDeleteArmature:WebGapArmatureDeleteRetain" + ], + "deletedBonePresent": false, + "selectedBoneIds": [] + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00235" +} diff --git a/tests/golden/M16-GAP-00234/manifest.json b/tests/golden/M16-GAP-00234/manifest.json new file mode 100644 index 00000000..c522f163 --- /dev/null +++ b/tests/golden/M16-GAP-00234/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00234", + "parentTask": "M16-GAP-00233", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_DELETE_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00233/manifest.json", + "sha256": "576b641acd54236ee8c3b61dd42281590507981b89882d9318d707882a9f09b0" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00234-operator-armature.delete.blend", + "sha256": "52c3c28c6cba72d0b40c32bc46b4d5894482f05b2ee621e44efde6999008556e" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00234.py", + "sha256": "408362122138a1f2e8fbe837c9d78795ff42445cdeb2359bf001888cfc6ed538" + }, + "desktopChecker": { + "path": "tools/web/check-action-armature-delete-desktop.py", + "sha256": "2b0358f9e0a96da53f8c7f889ae18068aac2653d4aa6e804a0471a92e66ddd6b" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "572b2ae16c8a0c47305d8a9439d54e5fc96c3d63b6330a120f1283c4f9102d8a" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "d190501da90ca93805997120c80833a5730928e73ae1eaa36389d72300688abe" + }, + "nativeStub": { + "path": "web/engine/web_engine_native_reader_stub.cpp", + "sha256": "2a1526e08cf446bb23a91c8c2ae799db38a0aeed0a809a15ead427780600481a" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "d125269a0a69ef9e168009803217eeb7d0a2c4c2b725afb6ed8fc417e715b517" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "d125269a0a69ef9e168009803217eeb7d0a2c4c2b725afb6ed8fc417e715b517" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "wasmJsPublic": { + "path": "web/app/public/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00234/armature-delete-desktop-report.json", + "sha256": "d6c85736295a6f07950292425294e188a6b17228c91eb1151a38e6da4833679e" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00234/armature-delete-local-exact-report.json", + "sha256": "89e0b6b13dd025e4d0d72eec409845c44f43d90e52fb4f506282cad455b5c0a8" + }, + "status": { + "path": "docs/status/M16-GAP-00234.md", + "sha256": "68beffb770ac5633f4b3ce112fc9e623702eacfe86ad3bbe0362158633ba4d4c" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00234/task-context.json", + "sha256": "da2f3111822b6a7238e2fa21d03976db0d614565da4365b6b8158877335ba70d" + } + }, + "nextTask": "M16-GAP-00235" +} diff --git a/tests/golden/M16-GAP-00234/task-context.json b/tests/golden/M16-GAP-00234/task-context.json new file mode 100644 index 00000000..721d54a0 --- /dev/null +++ b/tests/golden/M16-GAP-00234/task-context.json @@ -0,0 +1,182 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00234", + "parentTask": "M16-GAP-00233", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.delete data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.delete", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00234.py -- tests/files/web/generated/M16-GAP-00234-operator-armature.delete.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00234", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00234" + ], + "inputPaths": [], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1380, + "contextRemainingTokens": 344 + }, + "source": { + "bytes": 8524, + "tokens": 2132 + }, + "selected": [], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00234-operator-armature.delete.blend", + "bytes": 86269, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/generated/M16-GAP-00234.py", + "bytes": 1401, + "reason": "CONTEXT_REMAINING_SPACE" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 239810, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 638405, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00234/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00234.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00234/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 0, + "bytes": 0, + "tokens": 0 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00235", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00234.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00233/manifest.json", + "parentStatus": "docs/status/M16-GAP-00233.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00234.md", + "tests/golden/M16-GAP-00233/manifest.json", + "docs/status/M16-GAP-00233.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00233", + "parentTask": "M16-GAP-00232", + "status": "done", + "nextTask": "M16-GAP-00234", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00233 Status", + "status: done", + "task: armature.copy_bone_color_to_selected operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one armature with three bones. The active source bone uses a custom palette; one selected destination starts with a different theme palette and one unselected destination remains untouched.", + "- Desktop runs `ARMATURE_OT_copy_bone_color_to_selected` in edit mode with `bone_type=EDIT`, `poll=true`, and `FINISHED`, copying palette and custom normal/select/active colors only to selected bones while preserving selection and active bone through save/reopen.", + "- Main now exposes each armature bone's palette index and custom color bytes (`normal`, `select`, `active`, `flag`) alongside its existing selection and transform data. No other data-block, editor, or browser behavior was added." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1764, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 441 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2394, + "lines": 47, + "tokens": 599 + }, + { + "path": "docs/tasks/M16-GAP-00234.md", + "bytes": 1764, + "lines": 38, + "tokens": 441 + }, + { + "path": "tests/golden/M16-GAP-00233/manifest.json", + "bytes": 2986, + "lines": 74, + "tokens": 747 + }, + { + "path": "docs/status/M16-GAP-00233.md", + "bytes": 1380, + "lines": 20, + "tokens": 345 + } + ], + "sourceTokens": 2132, + "evidenceFiles": 0, + "evidenceBytes": 0, + "evidenceTokens": 0, + "totalTokens": 2132, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3156, + "serializedContextTokens": 715, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00235/armature-dissolve-desktop-report.json b/tests/golden/M16-GAP-00235/armature-dissolve-desktop-report.json new file mode 100644 index 00000000..2c59cc68 --- /dev/null +++ b/tests/golden/M16-GAP-00235/armature-dissolve-desktop-report.json @@ -0,0 +1,91 @@ +{ + "after": { + "activeBone": null, + "armature": "WebGapArmatureDissolveArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureDissolveRoot", + "parent": null, + "selected": false, + "tail": [ + 0.0, + 3.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureDissolveOther", + "parent": null, + "selected": false, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureDissolveObject" + }, + "before": { + "activeBone": null, + "armature": "WebGapArmatureDissolveArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureDissolveRoot", + "parent": null, + "selected": false, + "tail": [ + 0.0, + 3.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureDissolveOther", + "parent": null, + "selected": false, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureDissolveObject" + }, + "blenderVersion": "5.2.0 LTS", + "dissolvedBone": "WebGapArmatureDissolveTip", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00235-operator-armature.dissolve.blend", + "fixtureSha256": "951ea935f05ed06ced6ea61d4a9293e7dd3226902ea6ae3c0c466779dcbcf24b", + "mainMutation": "CONNECTED_TIP_ALREADY_DISSOLVED", + "operation": "ARMATURE_DISSOLVE_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00235" +} diff --git a/tests/golden/M16-GAP-00235/armature-dissolve-local-exact-report.json b/tests/golden/M16-GAP-00235/armature-dissolve-local-exact-report.json new file mode 100644 index 00000000..78d7b86c --- /dev/null +++ b/tests/golden/M16-GAP-00235/armature-dissolve-local-exact-report.json @@ -0,0 +1,58 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00235", + "operation": "ARMATURE_DISSOLVE_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00235-operator-armature.dissolve.blend", + "sha256": "951ea935f05ed06ced6ea61d4a9293e7dd3226902ea6ae3c0c466779dcbcf24b" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00235/armature-dissolve-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "CONNECTED_TIP_ALREADY_DISSOLVED", + "dissolvedBone": "WebGapArmatureDissolveTip" + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureDissolveArmature", + "remainingBoneIds": [ + "bone:armature:WebGapArmatureDissolveArmature:WebGapArmatureDissolveRoot", + "bone:armature:WebGapArmatureDissolveArmature:WebGapArmatureDissolveOther" + ], + "dissolvedBonePresent": false, + "survivingRoot": { + "id": "bone:armature:WebGapArmatureDissolveArmature:WebGapArmatureDissolveRoot", + "head": [ + 0, + 0, + 0 + ], + "tail": [ + 0, + 3, + 0 + ] + }, + "independentBone": { + "id": "bone:armature:WebGapArmatureDissolveArmature:WebGapArmatureDissolveOther", + "head": [ + 2, + 0, + 0 + ], + "tail": [ + 2, + 1, + 0 + ] + } + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00236" +} diff --git a/tests/golden/M16-GAP-00235/manifest.json b/tests/golden/M16-GAP-00235/manifest.json new file mode 100644 index 00000000..4bbb25bd --- /dev/null +++ b/tests/golden/M16-GAP-00235/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00235", + "parentTask": "M16-GAP-00234", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_DISSOLVE_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00234/manifest.json", + "sha256": "4a29dec54de89d3d3f2c2f8840d66ddef7193555550b403665a02576961d99c8" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00235-operator-armature.dissolve.blend", + "sha256": "951ea935f05ed06ced6ea61d4a9293e7dd3226902ea6ae3c0c466779dcbcf24b" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00235.py", + "sha256": "9dcb072c97f9c758d33de0280685665fe089c24393f6f72b06fb02e490e2befb" + }, + "desktopChecker": { + "path": "tools/web/check-action-armature-dissolve-desktop.py", + "sha256": "27a1aa29a7fe9ef6ad5b13b17ee0e30cf7c943df5d0ce3be97e44513cec33d01" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "562f805a1e9bc8255724b939f0877997bcf71fdc9e4f95f8397f9e787340ed53" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "d190501da90ca93805997120c80833a5730928e73ae1eaa36389d72300688abe" + }, + "nativeStub": { + "path": "web/engine/web_engine_native_reader_stub.cpp", + "sha256": "2a1526e08cf446bb23a91c8c2ae799db38a0aeed0a809a15ead427780600481a" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "d125269a0a69ef9e168009803217eeb7d0a2c4c2b725afb6ed8fc417e715b517" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "d125269a0a69ef9e168009803217eeb7d0a2c4c2b725afb6ed8fc417e715b517" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "wasmJsPublic": { + "path": "web/app/public/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00235/armature-dissolve-desktop-report.json", + "sha256": "bb9acbe5fd923532f125e511f6f113ef3543b519bfd757a942e4466eef7e2c79" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00235/armature-dissolve-local-exact-report.json", + "sha256": "97e46604d0c79afccd2968e64127da80382a92053f53b6f0b706d7b742aa608e" + }, + "status": { + "path": "docs/status/M16-GAP-00235.md", + "sha256": "eeace6c617236ea29331ba7824d85f30fb84d674e1a3ef385da4b22c632fa2eb" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00235/task-context.json", + "sha256": "87839be45f3d7071cc81118d5977cf405bd84ca8c59cc759ebea7bdc32541f03" + } + }, + "nextTask": "M16-GAP-00236" +} diff --git a/tests/golden/M16-GAP-00235/task-context.json b/tests/golden/M16-GAP-00235/task-context.json new file mode 100644 index 00000000..c7b2c2d8 --- /dev/null +++ b/tests/golden/M16-GAP-00235/task-context.json @@ -0,0 +1,182 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00235", + "parentTask": "M16-GAP-00234", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.dissolve data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.dissolve", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00235.py -- tests/files/web/generated/M16-GAP-00235-operator-armature.dissolve.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00235", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00235" + ], + "inputPaths": [], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1673, + "contextRemainingTokens": 416 + }, + "source": { + "bytes": 8231, + "tokens": 2060 + }, + "selected": [], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00235-operator-armature.dissolve.blend", + "bytes": 86289, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/generated/M16-GAP-00235.py", + "bytes": 1753, + "reason": "CONTEXT_REMAINING_SPACE" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 239810, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 643291, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00235/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00235.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00235/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 0, + "bytes": 0, + "tokens": 0 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00236", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00235.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00234/manifest.json", + "parentStatus": "docs/status/M16-GAP-00234.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00235.md", + "tests/golden/M16-GAP-00234/manifest.json", + "docs/status/M16-GAP-00234.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00234", + "parentTask": "M16-GAP-00233", + "status": "done", + "nextTask": "M16-GAP-00235", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00234 Status", + "status: done", + "task: armature.delete operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one armature with three unparented bones; only the middle bone starts selected and active.", + "- Desktop runs `ARMATURE_OT_delete` in edit mode with `poll=true` and `FINISHED`, deleting the selected bone while leaving the other two bones unselected and preserving the result through save/reopen.", + "- Main already exposes armature bone names, parent IDs, and selection state, so the same post-delete fixture is observable in WASM/Main without expanding other data-blocks, editors, or browsers." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1774, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 444 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2394, + "lines": 47, + "tokens": 599 + }, + { + "path": "docs/tasks/M16-GAP-00235.md", + "bytes": 1774, + "lines": 38, + "tokens": 444 + }, + { + "path": "tests/golden/M16-GAP-00234/manifest.json", + "bytes": 2917, + "lines": 74, + "tokens": 730 + }, + { + "path": "docs/status/M16-GAP-00234.md", + "bytes": 1146, + "lines": 20, + "tokens": 287 + } + ], + "sourceTokens": 2060, + "evidenceFiles": 0, + "evidenceBytes": 0, + "evidenceTokens": 0, + "totalTokens": 2060, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3084, + "serializedContextTokens": 717, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00236/armature-duplicate-desktop-report.json b/tests/golden/M16-GAP-00236/armature-duplicate-desktop-report.json new file mode 100644 index 00000000..3cf596e0 --- /dev/null +++ b/tests/golden/M16-GAP-00236/armature-duplicate-desktop-report.json @@ -0,0 +1,136 @@ +{ + "after": { + "activeBone": "WebGapArmatureDuplicateSource.001", + "armature": "WebGapArmatureDuplicateArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureDuplicateSource", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureDuplicateOther", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureDuplicateSource.001", + "parent": null, + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureDuplicateObject" + }, + "before": { + "activeBone": "WebGapArmatureDuplicateSource.001", + "armature": "WebGapArmatureDuplicateArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureDuplicateSource", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureDuplicateOther", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureDuplicateSource.001", + "parent": null, + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureDuplicateObject" + }, + "blenderVersion": "5.2.0 LTS", + "duplicateBone": "WebGapArmatureDuplicateSource.001", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00236-operator-armature.duplicate.blend", + "fixtureSha256": "fb0ddc4b599f05941c6d719be3eab14f354755017f574ca9e6984369474b42a8", + "mainMutation": "SELECTED_BONE_ALREADY_DUPLICATED", + "operation": "ARMATURE_DUPLICATE_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "sourceBone": "WebGapArmatureDuplicateSource", + "task": "M16-GAP-00236" +} diff --git a/tests/golden/M16-GAP-00236/armature-duplicate-local-exact-report.json b/tests/golden/M16-GAP-00236/armature-duplicate-local-exact-report.json new file mode 100644 index 00000000..63658385 --- /dev/null +++ b/tests/golden/M16-GAP-00236/armature-duplicate-local-exact-report.json @@ -0,0 +1,33 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00236", + "operation": "ARMATURE_DUPLICATE_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00236-operator-armature.duplicate.blend", + "sha256": "fb0ddc4b599f05941c6d719be3eab14f354755017f574ca9e6984369474b42a8" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00236/armature-duplicate-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "SELECTED_BONE_ALREADY_DUPLICATED", + "sourceBone": "WebGapArmatureDuplicateSource", + "duplicateBone": "WebGapArmatureDuplicateSource.001" + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureDuplicateArmature", + "sourceBoneId": "bone:armature:WebGapArmatureDuplicateArmature:WebGapArmatureDuplicateSource", + "duplicateBoneId": "bone:armature:WebGapArmatureDuplicateArmature:WebGapArmatureDuplicateSource.001", + "otherBoneId": "bone:armature:WebGapArmatureDuplicateArmature:WebGapArmatureDuplicateOther", + "duplicateSelected": true, + "geometryMatch": true + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00237" +} diff --git a/tests/golden/M16-GAP-00236/manifest.json b/tests/golden/M16-GAP-00236/manifest.json new file mode 100644 index 00000000..b39172ed --- /dev/null +++ b/tests/golden/M16-GAP-00236/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00236", + "parentTask": "M16-GAP-00235", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_DUPLICATE_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00235/manifest.json", + "sha256": "84f3720ab79155ad3af4c4d25f96d1cbe09944e8f76aae90bd4cc81c0037c4e1" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00236-operator-armature.duplicate.blend", + "sha256": "fb0ddc4b599f05941c6d719be3eab14f354755017f574ca9e6984369474b42a8" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00236.py", + "sha256": "7f4e66d90c76efa8c4f5ed0f0e052ed1a00ca815ff24630d08a201daab94233d" + }, + "desktopChecker": { + "path": "tools/web/check-action-armature-duplicate-desktop.py", + "sha256": "47c4546402e3e8692583e3d3075a1351092cd61fce09f5d96d13dc06bf2ce1d2" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "4d503a6fab1ad984b754229addb68a290b654c03d500dc3887ef9c5dc0ef7c80" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "d190501da90ca93805997120c80833a5730928e73ae1eaa36389d72300688abe" + }, + "nativeStub": { + "path": "web/engine/web_engine_native_reader_stub.cpp", + "sha256": "2a1526e08cf446bb23a91c8c2ae799db38a0aeed0a809a15ead427780600481a" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "d125269a0a69ef9e168009803217eeb7d0a2c4c2b725afb6ed8fc417e715b517" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "d125269a0a69ef9e168009803217eeb7d0a2c4c2b725afb6ed8fc417e715b517" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "wasmJsPublic": { + "path": "web/app/public/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00236/armature-duplicate-desktop-report.json", + "sha256": "b648c7d518227a03b4d142a61ad4e3f15de71cf58e3fc23b603f7fdd26e1bf0b" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00236/armature-duplicate-local-exact-report.json", + "sha256": "2c005ed1342943cec21b7a71371449af4d01909026bd18c8cd9ca65f868d51a9" + }, + "status": { + "path": "docs/status/M16-GAP-00236.md", + "sha256": "de335028bda9f8c51d13d244e81c3c1952cd074bddc74896c8cf5554389f9aa5" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00236/task-context.json", + "sha256": "91d3c4acf7697b24a72bcba8a093f2a3d1ea58578583983155ff2bc92b060184" + } + }, + "nextTask": "M16-GAP-00237" +} diff --git a/tests/golden/M16-GAP-00236/task-context.json b/tests/golden/M16-GAP-00236/task-context.json new file mode 100644 index 00000000..1f0f1031 --- /dev/null +++ b/tests/golden/M16-GAP-00236/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00236", + "parentTask": "M16-GAP-00235", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.duplicate data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.duplicate", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00236.py -- tests/files/web/generated/M16-GAP-00236-operator-armature.duplicate.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00236", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00236" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00236.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1508, + "contextRemainingTokens": 376 + }, + "source": { + "bytes": 8396, + "tokens": 2100 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00236.py", + "bytes": 1429, + "tokens": 358 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00236-operator-armature.duplicate.blend", + "bytes": 86362, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 239810, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 648666, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00236/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00236.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00236/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1429, + "tokens": 358 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00237", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00236.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00235/manifest.json", + "parentStatus": "docs/status/M16-GAP-00235.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00236.md", + "tests/golden/M16-GAP-00235/manifest.json", + "docs/status/M16-GAP-00235.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00235", + "parentTask": "M16-GAP-00234", + "status": "done", + "nextTask": "M16-GAP-00236", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00235 Status", + "status: done", + "task: armature.dissolve operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one connected Root-Middle-Tip chain and one independent bone; the connected chain is selected for dissolve while the independent bone remains unselected.", + "- Desktop runs `ARMATURE_OT_dissolve` in edit mode with `poll=true` and `FINISHED`, collapsing the connected chain into the Root bone extended to the Tip position while preserving the independent bone through save/reopen.", + "- Main already exposes armature bone names, parent IDs, selection state, and head/tail coordinates, so the same post-dissolve fixture is observable in WASM/Main without expanding other data-blocks, editors, or browsers." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1779, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 445 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2394, + "lines": 47, + "tokens": 599 + }, + { + "path": "docs/tasks/M16-GAP-00236.md", + "bytes": 1779, + "lines": 38, + "tokens": 445 + }, + { + "path": "tests/golden/M16-GAP-00235/manifest.json", + "bytes": 2927, + "lines": 74, + "tokens": 732 + }, + { + "path": "docs/status/M16-GAP-00235.md", + "bytes": 1296, + "lines": 20, + "tokens": 324 + } + ], + "sourceTokens": 2100, + "evidenceFiles": 1, + "evidenceBytes": 1429, + "evidenceTokens": 358, + "totalTokens": 2458, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3482, + "serializedContextTokens": 753, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00237/armature-duplicate-move-desktop-report.json b/tests/golden/M16-GAP-00237/armature-duplicate-move-desktop-report.json new file mode 100644 index 00000000..88d32430 --- /dev/null +++ b/tests/golden/M16-GAP-00237/armature-duplicate-move-desktop-report.json @@ -0,0 +1,141 @@ +{ + "after": { + "activeBone": "WebGapArmatureDuplicateMoveSource.001", + "armature": "WebGapArmatureDuplicateMoveArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureDuplicateMoveSource", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureDuplicateMoveOther", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 1.0, + 2.0, + 3.0 + ], + "name": "WebGapArmatureDuplicateMoveSource.001", + "parent": null, + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 1.0, + 3.0, + 3.0 + ] + } + ], + "object": "WebGapArmatureDuplicateMoveObject" + }, + "before": { + "activeBone": "WebGapArmatureDuplicateMoveSource.001", + "armature": "WebGapArmatureDuplicateMoveArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureDuplicateMoveSource", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureDuplicateMoveOther", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 1.0, + 2.0, + 3.0 + ], + "name": "WebGapArmatureDuplicateMoveSource.001", + "parent": null, + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 1.0, + 3.0, + 3.0 + ] + } + ], + "object": "WebGapArmatureDuplicateMoveObject" + }, + "blenderVersion": "5.2.0 LTS", + "duplicateBone": "WebGapArmatureDuplicateMoveSource.001", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00237-operator-armature.duplicate_move.blend", + "fixtureSha256": "18332d833556dc395719a7badd2c2fe0f5630fa1f9b809399ae0ebb4edf47f19", + "mainMutation": "SELECTED_BONE_ALREADY_DUPLICATED_AND_MOVED", + "operation": "ARMATURE_DUPLICATE_MOVE_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "sourceBone": "WebGapArmatureDuplicateMoveSource", + "task": "M16-GAP-00237", + "translation": [ + 1.0, + 2.0, + 3.0 + ] +} diff --git a/tests/golden/M16-GAP-00237/armature-duplicate-move-local-exact-report.json b/tests/golden/M16-GAP-00237/armature-duplicate-move-local-exact-report.json new file mode 100644 index 00000000..48ba2bbe --- /dev/null +++ b/tests/golden/M16-GAP-00237/armature-duplicate-move-local-exact-report.json @@ -0,0 +1,43 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00237", + "operation": "ARMATURE_DUPLICATE_MOVE_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00237-operator-armature.duplicate_move.blend", + "sha256": "18332d833556dc395719a7badd2c2fe0f5630fa1f9b809399ae0ebb4edf47f19" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00237/armature-duplicate-move-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "SELECTED_BONE_ALREADY_DUPLICATED_AND_MOVED", + "sourceBone": "WebGapArmatureDuplicateMoveSource", + "duplicateBone": "WebGapArmatureDuplicateMoveSource.001", + "translation": [ + 1, + 2, + 3 + ] + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureDuplicateMoveArmature", + "sourceBoneId": "bone:armature:WebGapArmatureDuplicateMoveArmature:WebGapArmatureDuplicateMoveSource", + "duplicateBoneId": "bone:armature:WebGapArmatureDuplicateMoveArmature:WebGapArmatureDuplicateMoveSource.001", + "otherBoneId": "bone:armature:WebGapArmatureDuplicateMoveArmature:WebGapArmatureDuplicateMoveOther", + "duplicateSelected": true, + "translation": [ + 1, + 2, + 3 + ], + "geometryMatch": true + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00238" +} diff --git a/tests/golden/M16-GAP-00237/manifest.json b/tests/golden/M16-GAP-00237/manifest.json new file mode 100644 index 00000000..6b59aebc --- /dev/null +++ b/tests/golden/M16-GAP-00237/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00237", + "parentTask": "M16-GAP-00236", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_DUPLICATE_MOVE_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00236/manifest.json", + "sha256": "8445ead3aefd6f7c5cffd4c8ae0977b6f754d4dd95b332956637051f7cb81518" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00237-operator-armature.duplicate_move.blend", + "sha256": "18332d833556dc395719a7badd2c2fe0f5630fa1f9b809399ae0ebb4edf47f19" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00237.py", + "sha256": "2345158899b35752b6875a28a243668369c51a087eef596eb420e603f0393a75" + }, + "desktopChecker": { + "path": "tools/web/check-action-armature-duplicate-move-desktop.py", + "sha256": "32d82956a3c5fba3cb844ce37a3eb174124a1b25fd7c958578c9a97a5138e1a6" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "e20281eeb40ad088e1dd3da40324fa171481455ff399842a5251fb29d4f5e50c" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "d190501da90ca93805997120c80833a5730928e73ae1eaa36389d72300688abe" + }, + "nativeStub": { + "path": "web/engine/web_engine_native_reader_stub.cpp", + "sha256": "2a1526e08cf446bb23a91c8c2ae799db38a0aeed0a809a15ead427780600481a" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "d125269a0a69ef9e168009803217eeb7d0a2c4c2b725afb6ed8fc417e715b517" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "d125269a0a69ef9e168009803217eeb7d0a2c4c2b725afb6ed8fc417e715b517" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "wasmJsPublic": { + "path": "web/app/public/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00237/armature-duplicate-move-desktop-report.json", + "sha256": "94745cd286e017a11dd6fd8df308a22e4d4b5e572bbc3115ee8bbac5fa430bea" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00237/armature-duplicate-move-local-exact-report.json", + "sha256": "3b99961a3aaf2e61d64aa6c9ac9c76e9c5db72e2b5bf14887f613d1bb0723ff9" + }, + "status": { + "path": "docs/status/M16-GAP-00237.md", + "sha256": "9f3084ee5e5e0c6c195f71590e51e8294790164272a4592e8cb60982fc037ad1" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00237/task-context.json", + "sha256": "553e1d6a385d20840eed34b7617b3496e7bded0fdccdb2b68e1ea61228bcbb80" + } + }, + "nextTask": "M16-GAP-00238" +} diff --git a/tests/golden/M16-GAP-00237/task-context.json b/tests/golden/M16-GAP-00237/task-context.json new file mode 100644 index 00000000..e2aab2e2 --- /dev/null +++ b/tests/golden/M16-GAP-00237/task-context.json @@ -0,0 +1,182 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00237", + "parentTask": "M16-GAP-00236", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.duplicate_move data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.duplicate_move", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00237.py -- tests/files/web/generated/M16-GAP-00237-operator-armature.duplicate_move.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00237", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00237" + ], + "inputPaths": [], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1449, + "contextRemainingTokens": 362 + }, + "source": { + "bytes": 8455, + "tokens": 2114 + }, + "selected": [], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00237-operator-armature.duplicate_move.blend", + "bytes": 86393, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/generated/M16-GAP-00237.py", + "bytes": 1662, + "reason": "CONTEXT_REMAINING_SPACE" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 239810, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 654437, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00237/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00237.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00237/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 0, + "bytes": 0, + "tokens": 0 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00238", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00237.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00236/manifest.json", + "parentStatus": "docs/status/M16-GAP-00236.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00237.md", + "tests/golden/M16-GAP-00236/manifest.json", + "docs/status/M16-GAP-00236.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00236", + "parentTask": "M16-GAP-00235", + "status": "done", + "nextTask": "M16-GAP-00237", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00236 Status", + "status: done", + "task: armature.duplicate operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one selected source bone with both endpoints selected and one independent unselected bone.", + "- Desktop runs `ARMATURE_OT_duplicate` in edit mode with `poll=true` and `FINISHED`, creating `WebGapArmatureDuplicateSource.001`, selecting it and making it active while preserving the source and independent bone through save/reopen.", + "- Main already exposes armature bone names, parent IDs, selection state, and head/tail coordinates, so the same duplicated fixture is observable in WASM/Main without expanding other data-blocks, editors, or browsers." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1804, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 451 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2495, + "lines": 47, + "tokens": 624 + }, + { + "path": "docs/tasks/M16-GAP-00237.md", + "bytes": 1804, + "lines": 38, + "tokens": 451 + }, + { + "path": "tests/golden/M16-GAP-00236/manifest.json", + "bytes": 2932, + "lines": 74, + "tokens": 733 + }, + { + "path": "docs/status/M16-GAP-00236.md", + "bytes": 1224, + "lines": 20, + "tokens": 306 + } + ], + "sourceTokens": 2114, + "evidenceFiles": 0, + "evidenceBytes": 0, + "evidenceTokens": 0, + "totalTokens": 2114, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3138, + "serializedContextTokens": 721, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00238/armature-duplicate-rename-desktop-report.json b/tests/golden/M16-GAP-00238/armature-duplicate-rename-desktop-report.json new file mode 100644 index 00000000..b1d18eb2 --- /dev/null +++ b/tests/golden/M16-GAP-00238/armature-duplicate-rename-desktop-report.json @@ -0,0 +1,138 @@ +{ + "after": { + "activeBone": "WebGapArmatureDuplicateRenameCopy", + "armature": "WebGapArmatureDuplicateRenameArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureDuplicateRenameSource", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureDuplicateRenameOther", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureDuplicateRenameCopy", + "parent": null, + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureDuplicateRenameObject" + }, + "before": { + "activeBone": "WebGapArmatureDuplicateRenameCopy", + "armature": "WebGapArmatureDuplicateRenameArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureDuplicateRenameSource", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureDuplicateRenameOther", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureDuplicateRenameCopy", + "parent": null, + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureDuplicateRenameObject" + }, + "blenderVersion": "5.2.0 LTS", + "duplicateBone": "WebGapArmatureDuplicateRenameCopy", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00238-operator-armature.duplicate_rename.blend", + "fixtureSha256": "95b9236be44ca3e40482203032ce2fe14a8ba79f5d94396d9fa7af2ab5b711d1", + "mainMutation": "SELECTED_BONE_ALREADY_DUPLICATED_AND_RENAMED", + "operation": "ARMATURE_DUPLICATE_RENAME_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "poll": true, + "replace": "Copy", + "saveReopen": "EXACT", + "schemaVersion": 1, + "search": "Source", + "sourceBone": "WebGapArmatureDuplicateRenameSource", + "task": "M16-GAP-00238" +} diff --git a/tests/golden/M16-GAP-00238/armature-duplicate-rename-local-exact-report.json b/tests/golden/M16-GAP-00238/armature-duplicate-rename-local-exact-report.json new file mode 100644 index 00000000..ed85e348 --- /dev/null +++ b/tests/golden/M16-GAP-00238/armature-duplicate-rename-local-exact-report.json @@ -0,0 +1,36 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00238", + "operation": "ARMATURE_DUPLICATE_RENAME_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00238-operator-armature.duplicate_rename.blend", + "sha256": "95b9236be44ca3e40482203032ce2fe14a8ba79f5d94396d9fa7af2ab5b711d1" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00238/armature-duplicate-rename-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "SELECTED_BONE_ALREADY_DUPLICATED_AND_RENAMED", + "sourceBone": "WebGapArmatureDuplicateRenameSource", + "duplicateBone": "WebGapArmatureDuplicateRenameCopy", + "search": "Source", + "replace": "Copy" + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureDuplicateRenameArmature", + "sourceBoneId": "bone:armature:WebGapArmatureDuplicateRenameArmature:WebGapArmatureDuplicateRenameSource", + "duplicateBoneId": "bone:armature:WebGapArmatureDuplicateRenameArmature:WebGapArmatureDuplicateRenameCopy", + "otherBoneId": "bone:armature:WebGapArmatureDuplicateRenameArmature:WebGapArmatureDuplicateRenameOther", + "duplicateSelected": true, + "renamedName": "WebGapArmatureDuplicateRenameCopy", + "geometryMatch": true + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00239" +} diff --git a/tests/golden/M16-GAP-00238/manifest.json b/tests/golden/M16-GAP-00238/manifest.json new file mode 100644 index 00000000..34cee9e1 --- /dev/null +++ b/tests/golden/M16-GAP-00238/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00238", + "parentTask": "M16-GAP-00237", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_DUPLICATE_RENAME_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00237/manifest.json", + "sha256": "9cf9d53b83b566e2d2d02c61907c8b58b5b4dba6e2739411d5b960de60ac0a48" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00238-operator-armature.duplicate_rename.blend", + "sha256": "95b9236be44ca3e40482203032ce2fe14a8ba79f5d94396d9fa7af2ab5b711d1" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00238.py", + "sha256": "dd00c6d9952cc91579c298a700c1698e1bfbe55542400bb694c6ea3c9b79bf5d" + }, + "desktopChecker": { + "path": "tools/web/check-action-armature-duplicate-rename-desktop.py", + "sha256": "1eadb6c273b4bc77f6c3df9f0060a361c6da2e95b84341ac2173a749f4b72d07" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "4b5fc80f117580e52543a1811ebc59bb9ef408d5db9140258f715e05bed26be1" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "d190501da90ca93805997120c80833a5730928e73ae1eaa36389d72300688abe" + }, + "nativeStub": { + "path": "web/engine/web_engine_native_reader_stub.cpp", + "sha256": "2a1526e08cf446bb23a91c8c2ae799db38a0aeed0a809a15ead427780600481a" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "d125269a0a69ef9e168009803217eeb7d0a2c4c2b725afb6ed8fc417e715b517" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "d125269a0a69ef9e168009803217eeb7d0a2c4c2b725afb6ed8fc417e715b517" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "wasmJsPublic": { + "path": "web/app/public/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00238/armature-duplicate-rename-desktop-report.json", + "sha256": "90a4d915eb9967f97495ede7b6f855d2049ea1059208b99e75128d79e7f51911" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00238/armature-duplicate-rename-local-exact-report.json", + "sha256": "f3e103b6c1a311bfeaad31c96066060519b091b3ae14c925a3d18e89e6ba8d2a" + }, + "status": { + "path": "docs/status/M16-GAP-00238.md", + "sha256": "a0cd13391e19a1b3acb3e84608cccc9805b0e11b9c7c791a94b3f47731381077" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00238/task-context.json", + "sha256": "5f58af69bdf6921fa2e46c229206c3a26ff737a9f04ad3602ba46e80061169cd" + } + }, + "nextTask": "M16-GAP-00239" +} diff --git a/tests/golden/M16-GAP-00238/task-context.json b/tests/golden/M16-GAP-00238/task-context.json new file mode 100644 index 00000000..5f2587ea --- /dev/null +++ b/tests/golden/M16-GAP-00238/task-context.json @@ -0,0 +1,182 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00238", + "parentTask": "M16-GAP-00237", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.duplicate_rename data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.duplicate_rename", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00238.py -- tests/files/web/generated/M16-GAP-00238-operator-armature.duplicate_rename.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00238", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00238" + ], + "inputPaths": [], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1406, + "contextRemainingTokens": 350 + }, + "source": { + "bytes": 8498, + "tokens": 2126 + }, + "selected": [], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00238-operator-armature.duplicate_rename.blend", + "bytes": 86313, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/generated/M16-GAP-00238.py", + "bytes": 1663, + "reason": "CONTEXT_REMAINING_SPACE" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 239810, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 660123, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00238/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00238.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00238/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 0, + "bytes": 0, + "tokens": 0 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00239", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00238.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00237/manifest.json", + "parentStatus": "docs/status/M16-GAP-00237.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00238.md", + "tests/golden/M16-GAP-00237/manifest.json", + "docs/status/M16-GAP-00237.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00237", + "parentTask": "M16-GAP-00236", + "status": "done", + "nextTask": "M16-GAP-00238", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00237 Status", + "status: done", + "task: armature.duplicate_move operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one selected source bone with both endpoints selected and one independent unselected bone.", + "- Desktop runs `ARMATURE_OT_duplicate_move` in edit mode with `poll=true` and `FINISHED`, creating `WebGapArmatureDuplicateMoveSource.001` translated by `(1, 2, 3)` while preserving the source and independent bone through save/reopen.", + "- Main already exposes armature bone names, selection state, parent IDs, and head/tail coordinates, so the same moved duplicate is observable in WASM/Main without expanding other data-blocks, editors, or browsers." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1814, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 454 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2495, + "lines": 47, + "tokens": 624 + }, + { + "path": "docs/tasks/M16-GAP-00238.md", + "bytes": 1814, + "lines": 38, + "tokens": 454 + }, + { + "path": "tests/golden/M16-GAP-00237/manifest.json", + "bytes": 2957, + "lines": 74, + "tokens": 740 + }, + { + "path": "docs/status/M16-GAP-00237.md", + "bytes": 1232, + "lines": 20, + "tokens": 308 + } + ], + "sourceTokens": 2126, + "evidenceFiles": 0, + "evidenceBytes": 0, + "evidenceTokens": 0, + "totalTokens": 2126, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3150, + "serializedContextTokens": 723, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00239/armature-extrude-desktop-report.json b/tests/golden/M16-GAP-00239/armature-extrude-desktop-report.json new file mode 100644 index 00000000..435373f6 --- /dev/null +++ b/tests/golden/M16-GAP-00239/armature-extrude-desktop-report.json @@ -0,0 +1,141 @@ +{ + "after": { + "activeBone": "WebGapArmatureExtrudeSource.001", + "armature": "WebGapArmatureExtrudeArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureExtrudeSource", + "parent": null, + "selectHead": false, + "selectTail": true, + "selected": false, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": true, + "head": [ + 0.0, + 1.0, + 0.0 + ], + "name": "WebGapArmatureExtrudeSource.001", + "parent": "WebGapArmatureExtrudeSource", + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 2.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureExtrudeOther", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureExtrudeObject" + }, + "before": { + "activeBone": "WebGapArmatureExtrudeSource.001", + "armature": "WebGapArmatureExtrudeArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureExtrudeSource", + "parent": null, + "selectHead": false, + "selectTail": true, + "selected": false, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": true, + "head": [ + 0.0, + 1.0, + 0.0 + ], + "name": "WebGapArmatureExtrudeSource.001", + "parent": "WebGapArmatureExtrudeSource", + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 2.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureExtrudeOther", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureExtrudeObject" + }, + "blenderVersion": "5.2.0 LTS", + "extrudeBone": "WebGapArmatureExtrudeSource.001", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00239-operator-armature.extrude.blend", + "fixtureSha256": "f4b86c585af6349dc43c50e23c93a482917145ba0b5bbd9ab3f8a7cf5018e661", + "mainMutation": "SELECTED_TAIL_ALREADY_EXTRUDED", + "operation": "ARMATURE_EXTRUDE_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "sourceBone": "WebGapArmatureExtrudeSource", + "task": "M16-GAP-00239", + "translation": [ + 0.0, + 1.0, + 0.0 + ] +} diff --git a/tests/golden/M16-GAP-00239/armature-extrude-local-exact-report.json b/tests/golden/M16-GAP-00239/armature-extrude-local-exact-report.json new file mode 100644 index 00000000..33243c3b --- /dev/null +++ b/tests/golden/M16-GAP-00239/armature-extrude-local-exact-report.json @@ -0,0 +1,50 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00239", + "operation": "ARMATURE_EXTRUDE_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00239-operator-armature.extrude.blend", + "sha256": "f4b86c585af6349dc43c50e23c93a482917145ba0b5bbd9ab3f8a7cf5018e661" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00239/armature-extrude-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "SELECTED_TAIL_ALREADY_EXTRUDED", + "sourceBone": "WebGapArmatureExtrudeSource", + "extrudeBone": "WebGapArmatureExtrudeSource.001", + "translation": [ + 0, + 1, + 0 + ] + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureExtrudeArmature", + "sourceBoneId": "bone:armature:WebGapArmatureExtrudeArmature:WebGapArmatureExtrudeSource", + "extrudeBoneId": "bone:armature:WebGapArmatureExtrudeArmature:WebGapArmatureExtrudeSource.001", + "otherBoneId": "bone:armature:WebGapArmatureExtrudeArmature:WebGapArmatureExtrudeOther", + "extrudeSelected": true, + "parentId": "bone:armature:WebGapArmatureExtrudeArmature:WebGapArmatureExtrudeSource", + "geometry": { + "head": [ + 0, + 0, + 0 + ], + "tail": [ + 0, + 1, + 0 + ] + } + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00240" +} diff --git a/tests/golden/M16-GAP-00239/manifest.json b/tests/golden/M16-GAP-00239/manifest.json new file mode 100644 index 00000000..b09a97c1 --- /dev/null +++ b/tests/golden/M16-GAP-00239/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00239", + "parentTask": "M16-GAP-00238", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_EXTRUDE_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00238/manifest.json", + "sha256": "5d35528b7d6e923626ead34f2120a0c69fad8385621780bfb06ea80fd287a990" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00239-operator-armature.extrude.blend", + "sha256": "f4b86c585af6349dc43c50e23c93a482917145ba0b5bbd9ab3f8a7cf5018e661" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00239.py", + "sha256": "651deeb3808998b44611bcecdfab9adc903245f53b66f521fad03443b900e047" + }, + "desktopChecker": { + "path": "tools/web/check-action-armature-extrude-desktop.py", + "sha256": "066e1851024ebedcec78e4e3962516ce8c43ae87ef87522d7acc8b6ca1f49a4d" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "eb246622b1ba205424ae7b6e964dba11340013a7a73a7e7667028d7ee91c6113" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "d190501da90ca93805997120c80833a5730928e73ae1eaa36389d72300688abe" + }, + "nativeStub": { + "path": "web/engine/web_engine_native_reader_stub.cpp", + "sha256": "2a1526e08cf446bb23a91c8c2ae799db38a0aeed0a809a15ead427780600481a" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "d125269a0a69ef9e168009803217eeb7d0a2c4c2b725afb6ed8fc417e715b517" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "d125269a0a69ef9e168009803217eeb7d0a2c4c2b725afb6ed8fc417e715b517" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "wasmJsPublic": { + "path": "web/app/public/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00239/armature-extrude-desktop-report.json", + "sha256": "3f264c22cc013676e33e82b98458a5baff8703addaaee26812ed2205aa062fed" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00239/armature-extrude-local-exact-report.json", + "sha256": "524adb7be53d523d48f87773d6782bd78db1e81eb6d88c6eba3641ff283e5269" + }, + "status": { + "path": "docs/status/M16-GAP-00239.md", + "sha256": "06f69cd41bf79caf33eeb65b3ee0a14dca930bfac46984ce2b2b3c01a53218d7" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00239/task-context.json", + "sha256": "ef9bc0d189399baae95fef4e518ed6997c26b21ade00d4cda06ff1b086a57cfb" + } + }, + "nextTask": "M16-GAP-00240" +} diff --git a/tests/golden/M16-GAP-00239/task-context.json b/tests/golden/M16-GAP-00239/task-context.json new file mode 100644 index 00000000..18719c78 --- /dev/null +++ b/tests/golden/M16-GAP-00239/task-context.json @@ -0,0 +1,182 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00239", + "parentTask": "M16-GAP-00238", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.extrude data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.extrude", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00239.py -- tests/files/web/generated/M16-GAP-00239-operator-armature.extrude.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00239", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00239" + ], + "inputPaths": [], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1400, + "contextRemainingTokens": 348 + }, + "source": { + "bytes": 8504, + "tokens": 2128 + }, + "selected": [], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00239-operator-armature.extrude.blend", + "bytes": 86358, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/generated/M16-GAP-00239.py", + "bytes": 1422, + "reason": "CONTEXT_REMAINING_SPACE" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 239810, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 665905, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00239/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00239.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00239/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 0, + "bytes": 0, + "tokens": 0 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00240", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00239.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00238/manifest.json", + "parentStatus": "docs/status/M16-GAP-00238.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00239.md", + "tests/golden/M16-GAP-00238/manifest.json", + "docs/status/M16-GAP-00238.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00238", + "parentTask": "M16-GAP-00237", + "status": "done", + "nextTask": "M16-GAP-00239", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00238 Status", + "status: done", + "task: armature.duplicate_rename operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one selected source bone with both endpoints selected and one independent unselected bone.", + "- Desktop runs `ARMATURE_OT_duplicate_rename` in edit mode with `poll=true` and `FINISHED`, creating `WebGapArmatureDuplicateRenameCopy` from `WebGapArmatureDuplicateRenameSource` using `Source -> Copy` while preserving the source and independent bone through save/reopen.", + "- Main already exposes armature bone names, selection state, parent IDs, and head/tail coordinates, so the same renamed duplicate is observable in WASM/Main without expanding other data-blocks, editors, or browsers." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1769, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 443 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2495, + "lines": 47, + "tokens": 624 + }, + { + "path": "docs/tasks/M16-GAP-00239.md", + "bytes": 1769, + "lines": 38, + "tokens": 443 + }, + { + "path": "tests/golden/M16-GAP-00238/manifest.json", + "bytes": 2967, + "lines": 74, + "tokens": 742 + }, + { + "path": "docs/status/M16-GAP-00238.md", + "bytes": 1273, + "lines": 20, + "tokens": 319 + } + ], + "sourceTokens": 2128, + "evidenceFiles": 0, + "evidenceBytes": 0, + "evidenceTokens": 0, + "totalTokens": 2128, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3152, + "serializedContextTokens": 716, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00240/armature-extrude-forked-desktop-report.json b/tests/golden/M16-GAP-00240/armature-extrude-forked-desktop-report.json new file mode 100644 index 00000000..2557c20d --- /dev/null +++ b/tests/golden/M16-GAP-00240/armature-extrude-forked-desktop-report.json @@ -0,0 +1,142 @@ +{ + "after": { + "activeBone": "WebGapArmatureExtrudeForkedSource.001", + "armature": "WebGapArmatureExtrudeForkedArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureExtrudeForkedSource", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 0.0, + 1.0, + 0.0 + ], + "name": "WebGapArmatureExtrudeForkedSource.001", + "parent": "WebGapArmatureExtrudeForkedSource", + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 2.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureExtrudeForkedOther", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureExtrudeForkedObject" + }, + "before": { + "activeBone": "WebGapArmatureExtrudeForkedSource.001", + "armature": "WebGapArmatureExtrudeForkedArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureExtrudeForkedSource", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 0.0, + 1.0, + 0.0 + ], + "name": "WebGapArmatureExtrudeForkedSource.001", + "parent": "WebGapArmatureExtrudeForkedSource", + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 2.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureExtrudeForkedOther", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureExtrudeForkedObject" + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00240-operator-armature.extrude_forked.blend", + "fixtureSha256": "bf0a7def9d8ff9c30218d5f11a23f533b777bfb02e35b1bf87f0c9a285af637f", + "forked": true, + "forkedBone": "WebGapArmatureExtrudeForkedSource.001", + "mainMutation": "SELECTED_TAIL_ALREADY_EXTRUDED_FORKED", + "operation": "ARMATURE_EXTRUDE_FORKED_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "sourceBone": "WebGapArmatureExtrudeForkedSource", + "task": "M16-GAP-00240", + "translation": [ + 0.0, + 1.0, + 0.0 + ] +} diff --git a/tests/golden/M16-GAP-00240/armature-extrude-forked-local-exact-report.json b/tests/golden/M16-GAP-00240/armature-extrude-forked-local-exact-report.json new file mode 100644 index 00000000..e3a80bb0 --- /dev/null +++ b/tests/golden/M16-GAP-00240/armature-extrude-forked-local-exact-report.json @@ -0,0 +1,52 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00240", + "operation": "ARMATURE_EXTRUDE_FORKED_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00240-operator-armature.extrude_forked.blend", + "sha256": "bf0a7def9d8ff9c30218d5f11a23f533b777bfb02e35b1bf87f0c9a285af637f" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00240/armature-extrude-forked-desktop-report.json", + "saveReopen": "EXACT", + "forked": true, + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "SELECTED_TAIL_ALREADY_EXTRUDED_FORKED", + "sourceBone": "WebGapArmatureExtrudeForkedSource", + "forkedBone": "WebGapArmatureExtrudeForkedSource.001", + "translation": [ + 0, + 1, + 0 + ] + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureExtrudeForkedArmature", + "sourceBoneId": "bone:armature:WebGapArmatureExtrudeForkedArmature:WebGapArmatureExtrudeForkedSource", + "forkedBoneId": "bone:armature:WebGapArmatureExtrudeForkedArmature:WebGapArmatureExtrudeForkedSource.001", + "otherBoneId": "bone:armature:WebGapArmatureExtrudeForkedArmature:WebGapArmatureExtrudeForkedOther", + "forkedSelected": true, + "parentId": "bone:armature:WebGapArmatureExtrudeForkedArmature:WebGapArmatureExtrudeForkedSource", + "connected": false, + "geometry": { + "head": [ + 0, + 0, + 0 + ], + "tail": [ + 0, + 1, + 0 + ] + } + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00241" +} diff --git a/tests/golden/M16-GAP-00240/manifest.json b/tests/golden/M16-GAP-00240/manifest.json new file mode 100644 index 00000000..e410934e --- /dev/null +++ b/tests/golden/M16-GAP-00240/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00240", + "parentTask": "M16-GAP-00239", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_EXTRUDE_FORKED_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00239/manifest.json", + "sha256": "558907921bfe14ddb6f93ff89f0dd88f950e537c6f1a9c4c2e5b9fc0e47d3d81" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00240-operator-armature.extrude_forked.blend", + "sha256": "bf0a7def9d8ff9c30218d5f11a23f533b777bfb02e35b1bf87f0c9a285af637f" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00240.py", + "sha256": "586f9ed3d865bf4ca759b36d010013ba33a34ff8862578c65b25acc9f53a4a69" + }, + "desktopChecker": { + "path": "tools/web/check-action-armature-extrude-forked-desktop.py", + "sha256": "cd13871abd4e28e9230388693209bbeb7d3b8f1e9daf99d3df09c9071bc9930a" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "f1ed4780038d37d9263a2282af25cee5ab2aa6207922c4c04dcf88c6d1ddd209" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "d190501da90ca93805997120c80833a5730928e73ae1eaa36389d72300688abe" + }, + "nativeStub": { + "path": "web/engine/web_engine_native_reader_stub.cpp", + "sha256": "2a1526e08cf446bb23a91c8c2ae799db38a0aeed0a809a15ead427780600481a" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "d125269a0a69ef9e168009803217eeb7d0a2c4c2b725afb6ed8fc417e715b517" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "d125269a0a69ef9e168009803217eeb7d0a2c4c2b725afb6ed8fc417e715b517" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "wasmJsPublic": { + "path": "web/app/public/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00240/armature-extrude-forked-desktop-report.json", + "sha256": "37ca8eb97c454cc572f70143aa98f01cba23190ea889bce7b688529d415945a4" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00240/armature-extrude-forked-local-exact-report.json", + "sha256": "957d36b2188d063415a2dcb70995bacddfeac01152872cf06ae27bba941a3ce6" + }, + "status": { + "path": "docs/status/M16-GAP-00240.md", + "sha256": "e50e0e1f6cbbbe7ca87686fa32b554bd1e9027452139638c055966cfad1a0b35" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00240/task-context.json", + "sha256": "3756f32ea6e1bf3b36c5480563a90e004f9a8e0836e18aeaa9f3e7b5d7abc545" + } + }, + "nextTask": "M16-GAP-00241" +} diff --git a/tests/golden/M16-GAP-00240/task-context.json b/tests/golden/M16-GAP-00240/task-context.json new file mode 100644 index 00000000..b9d2d22f --- /dev/null +++ b/tests/golden/M16-GAP-00240/task-context.json @@ -0,0 +1,182 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00240", + "parentTask": "M16-GAP-00239", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.extrude_forked data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.extrude_forked", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00240.py -- tests/files/web/generated/M16-GAP-00240-operator-armature.extrude_forked.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00240", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00240" + ], + "inputPaths": [], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1394, + "contextRemainingTokens": 347 + }, + "source": { + "bytes": 8510, + "tokens": 2129 + }, + "selected": [], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00240-operator-armature.extrude_forked.blend", + "bytes": 86397, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/generated/M16-GAP-00240.py", + "bytes": 1446, + "reason": "CONTEXT_REMAINING_SPACE" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 239810, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 671813, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00240/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00240.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00240/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 0, + "bytes": 0, + "tokens": 0 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00241", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00240.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00239/manifest.json", + "parentStatus": "docs/status/M16-GAP-00239.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00240.md", + "tests/golden/M16-GAP-00239/manifest.json", + "docs/status/M16-GAP-00239.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00239", + "parentTask": "M16-GAP-00238", + "status": "done", + "nextTask": "M16-GAP-00240", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00239 Status", + "status: done", + "task: armature.extrude operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one source bone with its tail selected and one independent unselected bone.", + "- Desktop runs `ARMATURE_OT_extrude` in edit mode with `poll=true` and `FINISHED`, creating `WebGapArmatureExtrudeSource.001` connected to the source and extending it to `(0, 2, 0)` while preserving the independent bone through save/reopen.", + "- Main exposes the extruded bone name, parent ID, selection state, connected flag, and parent-relative head/tail coordinates; the comparator normalizes desktop armature-space coordinates against the source tail without expanding other data-blocks, editors, or browsers." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1804, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 451 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2495, + "lines": 47, + "tokens": 624 + }, + { + "path": "docs/tasks/M16-GAP-00240.md", + "bytes": 1804, + "lines": 38, + "tokens": 451 + }, + { + "path": "tests/golden/M16-GAP-00239/manifest.json", + "bytes": 2922, + "lines": 74, + "tokens": 731 + }, + { + "path": "docs/status/M16-GAP-00239.md", + "bytes": 1289, + "lines": 20, + "tokens": 323 + } + ], + "sourceTokens": 2129, + "evidenceFiles": 0, + "evidenceBytes": 0, + "evidenceTokens": 0, + "totalTokens": 2129, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3153, + "serializedContextTokens": 721, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00241/armature-extrude-move-desktop-report.json b/tests/golden/M16-GAP-00241/armature-extrude-move-desktop-report.json new file mode 100644 index 00000000..21aa08f4 --- /dev/null +++ b/tests/golden/M16-GAP-00241/armature-extrude-move-desktop-report.json @@ -0,0 +1,141 @@ +{ + "after": { + "activeBone": "WebGapArmatureExtrudeMoveSource.001", + "armature": "WebGapArmatureExtrudeMoveArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureExtrudeMoveSource", + "parent": null, + "selectHead": false, + "selectTail": true, + "selected": false, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": true, + "head": [ + 0.0, + 1.0, + 0.0 + ], + "name": "WebGapArmatureExtrudeMoveSource.001", + "parent": "WebGapArmatureExtrudeMoveSource", + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 2.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureExtrudeMoveOther", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureExtrudeMoveObject" + }, + "before": { + "activeBone": "WebGapArmatureExtrudeMoveSource.001", + "armature": "WebGapArmatureExtrudeMoveArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureExtrudeMoveSource", + "parent": null, + "selectHead": false, + "selectTail": true, + "selected": false, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": true, + "head": [ + 0.0, + 1.0, + 0.0 + ], + "name": "WebGapArmatureExtrudeMoveSource.001", + "parent": "WebGapArmatureExtrudeMoveSource", + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 2.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureExtrudeMoveOther", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureExtrudeMoveObject" + }, + "blenderVersion": "5.2.0 LTS", + "extrudeBone": "WebGapArmatureExtrudeMoveSource.001", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00241-operator-armature.extrude_move.blend", + "fixtureSha256": "3959f29bfef358c9a7f10720605b9706bf03830f18ae713e4409b6396b3ea18c", + "mainMutation": "SELECTED_TAIL_ALREADY_EXTRUDED_AND_MOVED", + "operation": "ARMATURE_EXTRUDE_MOVE_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "sourceBone": "WebGapArmatureExtrudeMoveSource", + "task": "M16-GAP-00241", + "translation": [ + 0.0, + 1.0, + 0.0 + ] +} diff --git a/tests/golden/M16-GAP-00241/armature-extrude-move-local-exact-report.json b/tests/golden/M16-GAP-00241/armature-extrude-move-local-exact-report.json new file mode 100644 index 00000000..1766e4f0 --- /dev/null +++ b/tests/golden/M16-GAP-00241/armature-extrude-move-local-exact-report.json @@ -0,0 +1,51 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00241", + "operation": "ARMATURE_EXTRUDE_MOVE_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00241-operator-armature.extrude_move.blend", + "sha256": "3959f29bfef358c9a7f10720605b9706bf03830f18ae713e4409b6396b3ea18c" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00241/armature-extrude-move-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "SELECTED_TAIL_ALREADY_EXTRUDED_AND_MOVED", + "sourceBone": "WebGapArmatureExtrudeMoveSource", + "extrudeBone": "WebGapArmatureExtrudeMoveSource.001", + "translation": [ + 0, + 1, + 0 + ] + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureExtrudeMoveArmature", + "sourceBoneId": "bone:armature:WebGapArmatureExtrudeMoveArmature:WebGapArmatureExtrudeMoveSource", + "extrudeBoneId": "bone:armature:WebGapArmatureExtrudeMoveArmature:WebGapArmatureExtrudeMoveSource.001", + "otherBoneId": "bone:armature:WebGapArmatureExtrudeMoveArmature:WebGapArmatureExtrudeMoveOther", + "extrudeSelected": true, + "parentId": "bone:armature:WebGapArmatureExtrudeMoveArmature:WebGapArmatureExtrudeMoveSource", + "connected": true, + "geometry": { + "head": [ + 0, + 0, + 0 + ], + "tail": [ + 0, + 1, + 0 + ] + } + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00242" +} diff --git a/tests/golden/M16-GAP-00241/manifest.json b/tests/golden/M16-GAP-00241/manifest.json new file mode 100644 index 00000000..17c99601 --- /dev/null +++ b/tests/golden/M16-GAP-00241/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00241", + "parentTask": "M16-GAP-00240", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_EXTRUDE_MOVE_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00240/manifest.json", + "sha256": "3301ff54213d32531d2151a92b67e0efef3b9a577d36e1171c41b7b618c15c11" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00241-operator-armature.extrude_move.blend", + "sha256": "3959f29bfef358c9a7f10720605b9706bf03830f18ae713e4409b6396b3ea18c" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00241.py", + "sha256": "ba7a8fb5d46dc073f2e93180534340008d9f35824bdcbe829ede880015061a08" + }, + "desktopChecker": { + "path": "tools/web/check-action-armature-extrude-move-desktop.py", + "sha256": "9e1496c7022f9e70ade8cb937a815a7a0f0d3db9679d39b4b14b3e9cfae4bf85" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "f7a3fb5f2deef8c36547157e005f71ead700cf187cead8ad0003c462098bac44" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "d190501da90ca93805997120c80833a5730928e73ae1eaa36389d72300688abe" + }, + "nativeStub": { + "path": "web/engine/web_engine_native_reader_stub.cpp", + "sha256": "2a1526e08cf446bb23a91c8c2ae799db38a0aeed0a809a15ead427780600481a" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "d125269a0a69ef9e168009803217eeb7d0a2c4c2b725afb6ed8fc417e715b517" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "d125269a0a69ef9e168009803217eeb7d0a2c4c2b725afb6ed8fc417e715b517" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "wasmJsPublic": { + "path": "web/app/public/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00241/armature-extrude-move-desktop-report.json", + "sha256": "a24fb58e990504c5bd8a8d7a2d010f16028e070f099137bb26e5a2769a7fcc38" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00241/armature-extrude-move-local-exact-report.json", + "sha256": "05293986bab59aed5d1629d9a9e28c3499db619b33294f6f5d7557a463bfc001" + }, + "status": { + "path": "docs/status/M16-GAP-00241.md", + "sha256": "3a467ab859b73c7ebd3258c6f15f15ba2db2b197c8bf4a2441d7bcfdac26e06c" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00241/task-context.json", + "sha256": "ddbe88064be8649f792d2c731a9269ccb3eabe35a08430e613ca8cba0b25ddbb" + } + }, + "nextTask": "M16-GAP-00242" +} diff --git a/tests/golden/M16-GAP-00241/task-context.json b/tests/golden/M16-GAP-00241/task-context.json new file mode 100644 index 00000000..eaf7b213 --- /dev/null +++ b/tests/golden/M16-GAP-00241/task-context.json @@ -0,0 +1,182 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00241", + "parentTask": "M16-GAP-00240", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.extrude_move data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.extrude_move", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00241.py -- tests/files/web/generated/M16-GAP-00241-operator-armature.extrude_move.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00241", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00241" + ], + "inputPaths": [], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1360, + "contextRemainingTokens": 338 + }, + "source": { + "bytes": 8544, + "tokens": 2138 + }, + "selected": [], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00241-operator-armature.extrude_move.blend", + "bytes": 86364, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/generated/M16-GAP-00241.py", + "bytes": 1438, + "reason": "CONTEXT_REMAINING_SPACE" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 239810, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 677665, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00241/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00241.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00241/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 0, + "bytes": 0, + "tokens": 0 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00242", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00241.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00240/manifest.json", + "parentStatus": "docs/status/M16-GAP-00240.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00241.md", + "tests/golden/M16-GAP-00240/manifest.json", + "docs/status/M16-GAP-00240.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00240", + "parentTask": "M16-GAP-00239", + "status": "done", + "nextTask": "M16-GAP-00241", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00240 Status", + "status: done", + "task: armature.extrude_forked operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one source bone with its tail selected and one independent unselected bone.", + "- Desktop runs `ARMATURE_OT_extrude(forked=true)` in edit mode with `poll=true` and `FINISHED`, creating `WebGapArmatureExtrudeForkedSource.001` from the source tail with `connected=false` while preserving the source and independent bone through save/reopen.", + "- Main exposes the forked bone name, parent ID, selection state, connected flag, and parent-relative head/tail coordinates; the comparator normalizes desktop armature-space coordinates against the source tail without expanding other data-blocks, editors, or browsers." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1794, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 449 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2495, + "lines": 47, + "tokens": 624 + }, + { + "path": "docs/tasks/M16-GAP-00241.md", + "bytes": 1794, + "lines": 38, + "tokens": 449 + }, + { + "path": "tests/golden/M16-GAP-00240/manifest.json", + "bytes": 2957, + "lines": 74, + "tokens": 740 + }, + { + "path": "docs/status/M16-GAP-00240.md", + "bytes": 1298, + "lines": 20, + "tokens": 325 + } + ], + "sourceTokens": 2138, + "evidenceFiles": 0, + "evidenceBytes": 0, + "evidenceTokens": 0, + "totalTokens": 2138, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3162, + "serializedContextTokens": 720, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00242/armature-fill-desktop-report.json b/tests/golden/M16-GAP-00242/armature-fill-desktop-report.json new file mode 100644 index 00000000..038f3b42 --- /dev/null +++ b/tests/golden/M16-GAP-00242/armature-fill-desktop-report.json @@ -0,0 +1,173 @@ +{ + "after": { + "activeBone": "WebGapArmatureFillBridge", + "armature": "WebGapArmatureFillArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureFillSource", + "parent": null, + "selectHead": false, + "selectTail": true, + "selected": false, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": true, + "head": [ + 0.0, + 1.0, + 0.0 + ], + "name": "WebGapArmatureFillBridge", + "parent": "WebGapArmatureFillSource", + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 2.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 0.0, + 2.0, + 0.0 + ], + "name": "WebGapArmatureFillTarget", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 0.0, + 3.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureFillOther", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureFillObject" + }, + "before": { + "activeBone": "WebGapArmatureFillBridge", + "armature": "WebGapArmatureFillArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureFillSource", + "parent": null, + "selectHead": false, + "selectTail": true, + "selected": false, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": true, + "head": [ + 0.0, + 1.0, + 0.0 + ], + "name": "WebGapArmatureFillBridge", + "parent": "WebGapArmatureFillSource", + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 2.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 0.0, + 2.0, + 0.0 + ], + "name": "WebGapArmatureFillTarget", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 0.0, + 3.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureFillOther", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureFillObject" + }, + "blenderVersion": "5.2.0 LTS", + "bridgeBone": "WebGapArmatureFillBridge", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00242-operator-armature.fill.blend", + "fixtureSha256": "b7f20bcc4f7a6045bc38fdec9394872e399a55f3de9e4081b40dde3b911d770d", + "mainMutation": "SELECTED_ENDPOINTS_ALREADY_FILLED", + "operation": "ARMATURE_FILL_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "sourceBone": "WebGapArmatureFillSource", + "targetBone": "WebGapArmatureFillTarget", + "task": "M16-GAP-00242" +} diff --git a/tests/golden/M16-GAP-00242/armature-fill-local-exact-report.json b/tests/golden/M16-GAP-00242/armature-fill-local-exact-report.json new file mode 100644 index 00000000..f8d01ff7 --- /dev/null +++ b/tests/golden/M16-GAP-00242/armature-fill-local-exact-report.json @@ -0,0 +1,48 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00242", + "operation": "ARMATURE_FILL_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00242-operator-armature.fill.blend", + "sha256": "b7f20bcc4f7a6045bc38fdec9394872e399a55f3de9e4081b40dde3b911d770d" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00242/armature-fill-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "SELECTED_ENDPOINTS_ALREADY_FILLED", + "sourceBone": "WebGapArmatureFillSource", + "targetBone": "WebGapArmatureFillTarget", + "bridgeBone": "WebGapArmatureFillBridge" + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureFillArmature", + "sourceBoneId": "bone:armature:WebGapArmatureFillArmature:WebGapArmatureFillSource", + "targetBoneId": "bone:armature:WebGapArmatureFillArmature:WebGapArmatureFillTarget", + "bridgeBoneId": "bone:armature:WebGapArmatureFillArmature:WebGapArmatureFillBridge", + "otherBoneId": "bone:armature:WebGapArmatureFillArmature:WebGapArmatureFillOther", + "bridgeSelected": true, + "parentId": "bone:armature:WebGapArmatureFillArmature:WebGapArmatureFillSource", + "connected": true, + "geometry": { + "head": [ + 0, + 0, + 0 + ], + "tail": [ + 0, + 1, + 0 + ] + } + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00243" +} diff --git a/tests/golden/M16-GAP-00242/manifest.json b/tests/golden/M16-GAP-00242/manifest.json new file mode 100644 index 00000000..054059ca --- /dev/null +++ b/tests/golden/M16-GAP-00242/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00242", + "parentTask": "M16-GAP-00241", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_FILL_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00241/manifest.json", + "sha256": "d1cb4558aff9635c73c9b46d39915482d9e9d78b0ac56d3b64783fc0beb1812d" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00242-operator-armature.fill.blend", + "sha256": "b7f20bcc4f7a6045bc38fdec9394872e399a55f3de9e4081b40dde3b911d770d" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00242.py", + "sha256": "0e2b56d0020066bcd69d7ee4970c4eaaf3f3cdf02a9f528903997246b3a9ea48" + }, + "desktopChecker": { + "path": "tools/web/check-action-armature-fill-desktop.py", + "sha256": "fa8f3e577dd5b3924f8266509346f1c459a45bc62ac597926b412a962c4a9017" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "09da6257d1becbe2d1b7b6704286bf9684075b0d860a4d2c436eafe2ec4ab883" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "d190501da90ca93805997120c80833a5730928e73ae1eaa36389d72300688abe" + }, + "nativeStub": { + "path": "web/engine/web_engine_native_reader_stub.cpp", + "sha256": "2a1526e08cf446bb23a91c8c2ae799db38a0aeed0a809a15ead427780600481a" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "d125269a0a69ef9e168009803217eeb7d0a2c4c2b725afb6ed8fc417e715b517" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "d125269a0a69ef9e168009803217eeb7d0a2c4c2b725afb6ed8fc417e715b517" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "wasmJsPublic": { + "path": "web/app/public/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00242/armature-fill-desktop-report.json", + "sha256": "39f5db8f1a77e188ef3d4c3084c9bcf961551767211b40f006499a66ad51f56f" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00242/armature-fill-local-exact-report.json", + "sha256": "f4d927d1e6a10c9db3bd0b6a32b771aa96a25af9f9a5ab4a01741932173a293a" + }, + "status": { + "path": "docs/status/M16-GAP-00242.md", + "sha256": "fb18cd303bcd1455f363897d6e2d34320a81156c1a096ec6ca0560e3f59e3cbb" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00242/task-context.json", + "sha256": "59d07c1a9a8151af3b530ca1e6ffa56b0747ce67637ac9851c94c63e70b0ded8" + } + }, + "nextTask": "M16-GAP-00243" +} diff --git a/tests/golden/M16-GAP-00242/task-context.json b/tests/golden/M16-GAP-00242/task-context.json new file mode 100644 index 00000000..b7087c1a --- /dev/null +++ b/tests/golden/M16-GAP-00242/task-context.json @@ -0,0 +1,182 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00242", + "parentTask": "M16-GAP-00241", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.fill data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.fill", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00242.py -- tests/files/web/generated/M16-GAP-00242-operator-armature.fill.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00242", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00242" + ], + "inputPaths": [], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1368, + "contextRemainingTokens": 341 + }, + "source": { + "bytes": 8536, + "tokens": 2135 + }, + "selected": [], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00242-operator-armature.fill.blend", + "bytes": 86429, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/generated/M16-GAP-00242.py", + "bytes": 1657, + "reason": "CONTEXT_REMAINING_SPACE" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 239810, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 683901, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00242/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00242.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00242/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 0, + "bytes": 0, + "tokens": 0 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00243", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00242.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00241/manifest.json", + "parentStatus": "docs/status/M16-GAP-00241.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00242.md", + "tests/golden/M16-GAP-00241/manifest.json", + "docs/status/M16-GAP-00241.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00241", + "parentTask": "M16-GAP-00240", + "status": "done", + "nextTask": "M16-GAP-00242", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00241 Status", + "status: done", + "task: armature.extrude_move operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one source bone with its tail selected and one independent unselected bone.", + "- Desktop runs `ARMATURE_OT_extrude_move` in edit mode with `poll=true`, `FINISHED`, and a `(0, 1, 0)` translate transform, creating `WebGapArmatureExtrudeMoveSource.001` connected to the source while preserving the source and independent bone through save/reopen.", + "- Main exposes the moved extruded bone name, parent ID, selection state, connected flag, and parent-relative head/tail coordinates; the comparator normalizes desktop armature-space coordinates against the source tail without expanding other data-blocks, editors, or browsers." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1754, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 439 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2495, + "lines": 47, + "tokens": 624 + }, + { + "path": "docs/tasks/M16-GAP-00242.md", + "bytes": 1754, + "lines": 38, + "tokens": 439 + }, + { + "path": "tests/golden/M16-GAP-00241/manifest.json", + "bytes": 2947, + "lines": 74, + "tokens": 737 + }, + { + "path": "docs/status/M16-GAP-00241.md", + "bytes": 1340, + "lines": 20, + "tokens": 335 + } + ], + "sourceTokens": 2135, + "evidenceFiles": 0, + "evidenceBytes": 0, + "evidenceTokens": 0, + "totalTokens": 2135, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3159, + "serializedContextTokens": 714, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00243/armature-flip-names-desktop-report.json b/tests/golden/M16-GAP-00243/armature-flip-names-desktop-report.json new file mode 100644 index 00000000..92425cb0 --- /dev/null +++ b/tests/golden/M16-GAP-00243/armature-flip-names-desktop-report.json @@ -0,0 +1,137 @@ +{ + "after": { + "activeBone": "WebGapArmatureFlipBone.L", + "armature": "WebGapArmatureFlipNamesArmature", + "bones": [ + { + "connected": false, + "head": [ + -1.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureFlipBone.R", + "parent": null, + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + -1.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 1.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureFlipBone.L", + "parent": null, + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 1.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 0.0, + 0.0, + 2.0 + ], + "name": "WebGapArmatureFlipOther", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 0.0, + 1.0, + 2.0 + ] + } + ], + "object": "WebGapArmatureFlipNamesObject" + }, + "before": { + "activeBone": "WebGapArmatureFlipBone.L", + "armature": "WebGapArmatureFlipNamesArmature", + "bones": [ + { + "connected": false, + "head": [ + -1.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureFlipBone.R", + "parent": null, + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + -1.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 1.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureFlipBone.L", + "parent": null, + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 1.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 0.0, + 0.0, + 2.0 + ], + "name": "WebGapArmatureFlipOther", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 0.0, + 1.0, + 2.0 + ] + } + ], + "object": "WebGapArmatureFlipNamesObject" + }, + "blenderVersion": "5.2.0 LTS", + "doStripNumbers": false, + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00243-operator-armature.flip_names.blend", + "fixtureSha256": "b21a9ececf220be55c9d17d99c7fcbb0fe43b2fea6ffac88eb4eb34be1ebb5ba", + "leftGeometryBone": "WebGapArmatureFlipBone.R", + "mainMutation": "SELECTED_LEFT_RIGHT_NAMES_ALREADY_FLIPPED", + "operation": "ARMATURE_FLIP_NAMES_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "poll": true, + "rightGeometryBone": "WebGapArmatureFlipBone.L", + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00243" +} diff --git a/tests/golden/M16-GAP-00243/armature-flip-names-local-exact-report.json b/tests/golden/M16-GAP-00243/armature-flip-names-local-exact-report.json new file mode 100644 index 00000000..a888ba16 --- /dev/null +++ b/tests/golden/M16-GAP-00243/armature-flip-names-local-exact-report.json @@ -0,0 +1,35 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00243", + "operation": "ARMATURE_FLIP_NAMES_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00243-operator-armature.flip_names.blend", + "sha256": "b21a9ececf220be55c9d17d99c7fcbb0fe43b2fea6ffac88eb4eb34be1ebb5ba" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00243/armature-flip-names-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "SELECTED_LEFT_RIGHT_NAMES_ALREADY_FLIPPED", + "leftGeometryBone": "WebGapArmatureFlipBone.R", + "rightGeometryBone": "WebGapArmatureFlipBone.L", + "doStripNumbers": false + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureFlipNamesArmature", + "leftBoneId": "bone:armature:WebGapArmatureFlipNamesArmature:WebGapArmatureFlipBone.R", + "rightBoneId": "bone:armature:WebGapArmatureFlipNamesArmature:WebGapArmatureFlipBone.L", + "otherBoneId": "bone:armature:WebGapArmatureFlipNamesArmature:WebGapArmatureFlipOther", + "leftName": "WebGapArmatureFlipBone.R", + "rightName": "WebGapArmatureFlipBone.L", + "geometryNamesFlipped": true + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00244" +} diff --git a/tests/golden/M16-GAP-00243/manifest.json b/tests/golden/M16-GAP-00243/manifest.json new file mode 100644 index 00000000..f79e95c2 --- /dev/null +++ b/tests/golden/M16-GAP-00243/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00243", + "parentTask": "M16-GAP-00242", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_FLIP_NAMES_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00242/manifest.json", + "sha256": "1de876070dab2ce6cebb4d42845735f712de45219c3f0b6da22e8a42518841ef" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00243-operator-armature.flip_names.blend", + "sha256": "b21a9ececf220be55c9d17d99c7fcbb0fe43b2fea6ffac88eb4eb34be1ebb5ba" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00243.py", + "sha256": "444c10dac8003527409024263844587d5c7b6d1cec495fc8e408b6af14e60fde" + }, + "desktopChecker": { + "path": "tools/web/check-action-armature-flip-names-desktop.py", + "sha256": "5b3bc16b1fdfed70b6be9ca37ee1c949ce02129f4d396216f70edc022ba1082a" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "6a3158c95a0d434a904ff08d2b11224990ba2c56c9f9f92648a20ef04f98b863" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "d190501da90ca93805997120c80833a5730928e73ae1eaa36389d72300688abe" + }, + "nativeStub": { + "path": "web/engine/web_engine_native_reader_stub.cpp", + "sha256": "2a1526e08cf446bb23a91c8c2ae799db38a0aeed0a809a15ead427780600481a" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "d125269a0a69ef9e168009803217eeb7d0a2c4c2b725afb6ed8fc417e715b517" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "d125269a0a69ef9e168009803217eeb7d0a2c4c2b725afb6ed8fc417e715b517" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "wasmJsPublic": { + "path": "web/app/public/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00243/armature-flip-names-desktop-report.json", + "sha256": "489a05e88b2f35bfa0c910623db17897d70041afbbeecd2ad6575997c62d5a7f" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00243/armature-flip-names-local-exact-report.json", + "sha256": "e3a6efe370d43e0d05e4668994c70dade862aec0f45b50978558d3468e022d93" + }, + "status": { + "path": "docs/status/M16-GAP-00243.md", + "sha256": "3fa12d4941b7ea5131682f3727020b2bd45bb6ddd15368d42bb723002e1c9e2d" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00243/task-context.json", + "sha256": "c71f199a41f023b1724f3075c1755b509f014918cbd27937779323e4d6d16974" + } + }, + "nextTask": "M16-GAP-00244" +} diff --git a/tests/golden/M16-GAP-00243/task-context.json b/tests/golden/M16-GAP-00243/task-context.json new file mode 100644 index 00000000..5fe3fdbe --- /dev/null +++ b/tests/golden/M16-GAP-00243/task-context.json @@ -0,0 +1,182 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00243", + "parentTask": "M16-GAP-00242", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.flip_names data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.flip_names", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00243.py -- tests/files/web/generated/M16-GAP-00243-operator-armature.flip_names.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00243", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00243" + ], + "inputPaths": [], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1411, + "contextRemainingTokens": 352 + }, + "source": { + "bytes": 8493, + "tokens": 2124 + }, + "selected": [], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00243-operator-armature.flip_names.blend", + "bytes": 86395, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/generated/M16-GAP-00243.py", + "bytes": 1640, + "reason": "CONTEXT_REMAINING_SPACE" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 239810, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 689109, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00243/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00243.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00243/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 0, + "bytes": 0, + "tokens": 0 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00244", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00243.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00242/manifest.json", + "parentStatus": "docs/status/M16-GAP-00242.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00243.md", + "tests/golden/M16-GAP-00242/manifest.json", + "docs/status/M16-GAP-00242.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00242", + "parentTask": "M16-GAP-00241", + "status": "done", + "nextTask": "M16-GAP-00243", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00242 Status", + "status: done", + "task: armature.fill operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains a source bone tail and target bone head selected as the two fill endpoints, plus one independent unselected bone.", + "- Desktop runs `ARMATURE_OT_fill` in edit mode with `poll=true` and `FINISHED`, creating `WebGapArmatureFillBridge` between source tail and target head while preserving the original source/target and independent bone through save/reopen.", + "- Main exposes the bridge bone name, parent ID, selection state, connected flag, and parent-relative head/tail coordinates; the comparator normalizes desktop armature-space coordinates against the source tail without expanding other data-blocks, editors, or browsers." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1784, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 446 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2495, + "lines": 47, + "tokens": 624 + }, + { + "path": "docs/tasks/M16-GAP-00243.md", + "bytes": 1784, + "lines": 38, + "tokens": 446 + }, + { + "path": "tests/golden/M16-GAP-00242/manifest.json", + "bytes": 2907, + "lines": 74, + "tokens": 727 + }, + { + "path": "docs/status/M16-GAP-00242.md", + "bytes": 1307, + "lines": 20, + "tokens": 327 + } + ], + "sourceTokens": 2124, + "evidenceFiles": 0, + "evidenceBytes": 0, + "evidenceTokens": 0, + "totalTokens": 2124, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3148, + "serializedContextTokens": 718, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00244/armature-hide-desktop-report.json b/tests/golden/M16-GAP-00244/armature-hide-desktop-report.json new file mode 100644 index 00000000..3063dfec --- /dev/null +++ b/tests/golden/M16-GAP-00244/armature-hide-desktop-report.json @@ -0,0 +1,104 @@ +{ + "after": { + "activeBone": "WebGapArmatureHideSelected", + "armature": "WebGapArmatureHideArmature", + "bones": [ + { + "connected": false, + "head": [ + -1.0, + 0.0, + 0.0 + ], + "hidden": true, + "name": "WebGapArmatureHideSelected", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + -1.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 1.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureHideOther", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 1.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureHideObject" + }, + "before": { + "activeBone": "WebGapArmatureHideSelected", + "armature": "WebGapArmatureHideArmature", + "bones": [ + { + "connected": false, + "head": [ + -1.0, + 0.0, + 0.0 + ], + "hidden": true, + "name": "WebGapArmatureHideSelected", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + -1.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 1.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureHideOther", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 1.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureHideObject" + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00244-operator-armature.hide.blend", + "fixtureSha256": "1a3486ca531e5f679886228539fc841d5afc7c9eb7315fb0d5f31061d5f26aa4", + "hiddenBone": "WebGapArmatureHideSelected", + "mainMutation": "SELECTED_BONE_ALREADY_HIDDEN", + "operation": "ARMATURE_HIDE_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00244", + "unselected": false +} diff --git a/tests/golden/M16-GAP-00244/armature-hide-local-exact-report.json b/tests/golden/M16-GAP-00244/armature-hide-local-exact-report.json new file mode 100644 index 00000000..e70cbb01 --- /dev/null +++ b/tests/golden/M16-GAP-00244/armature-hide-local-exact-report.json @@ -0,0 +1,33 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00244", + "operation": "ARMATURE_HIDE_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00244-operator-armature.hide.blend", + "sha256": "1a3486ca531e5f679886228539fc841d5afc7c9eb7315fb0d5f31061d5f26aa4" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00244/armature-hide-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "SELECTED_BONE_ALREADY_HIDDEN", + "hiddenBone": "WebGapArmatureHideSelected", + "unselected": false + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureHideArmature", + "hiddenBoneId": "bone:armature:WebGapArmatureHideArmature:WebGapArmatureHideSelected", + "otherBoneId": "bone:armature:WebGapArmatureHideArmature:WebGapArmatureHideOther", + "hidden": true, + "selectedAfterHide": false, + "otherHidden": false + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00245" +} diff --git a/tests/golden/M16-GAP-00244/manifest.json b/tests/golden/M16-GAP-00244/manifest.json new file mode 100644 index 00000000..efbb4b4e --- /dev/null +++ b/tests/golden/M16-GAP-00244/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00244", + "parentTask": "M16-GAP-00243", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_HIDE_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00243/manifest.json", + "sha256": "1a794c9171bf53a620cdb7679fb26ef76095199a990e832e70189b1185e53355" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00244-operator-armature.hide.blend", + "sha256": "1a3486ca531e5f679886228539fc841d5afc7c9eb7315fb0d5f31061d5f26aa4" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00244.py", + "sha256": "848e43152c5035fc40d6ffafa566dbcbf4a7940d32fbd75a7d696321d125c938" + }, + "desktopChecker": { + "path": "tools/web/check-action-armature-hide-desktop.py", + "sha256": "455d76e6dbd6100f9a33a517a31232605f3d878d165e5938a6aae50682d1fc9c" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "1717ac61ffc9fdc25332a8c08fa63be082c93fe4c27b29e55ec18f360c471039" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "36ee1c408362b365d14f0d6c96a505796506a2fb50ec85dcdb06cd64f1d68e0c" + }, + "nativeStub": { + "path": "web/engine/web_engine_native_reader_stub.cpp", + "sha256": "2a1526e08cf446bb23a91c8c2ae799db38a0aeed0a809a15ead427780600481a" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "f0dada634e8aaf84f645f39a4ffeb649b71c691999ee6b7a0c15c4abcf3884d9" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "f0dada634e8aaf84f645f39a4ffeb649b71c691999ee6b7a0c15c4abcf3884d9" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "wasmJsPublic": { + "path": "web/app/public/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00244/armature-hide-desktop-report.json", + "sha256": "382b6abd52f5d54e519690cc3760fc5cddf1db2516abe8fe3e2acfedb500ed83" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00244/armature-hide-local-exact-report.json", + "sha256": "295134cdf0ed210c1eebdb166ad3251dd47234ff4b23e084a6c6f4e26e8615ea" + }, + "status": { + "path": "docs/status/M16-GAP-00244.md", + "sha256": "efdfd1529460078ff569106961bd018f6ae75a3d9aa17da816639448268be17a" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00244/task-context.json", + "sha256": "4103d8304ec404adcd995b030bd6f266d76971fd91068159fb8b7686106fc738" + } + }, + "nextTask": "M16-GAP-00245" +} diff --git a/tests/golden/M16-GAP-00244/task-context.json b/tests/golden/M16-GAP-00244/task-context.json new file mode 100644 index 00000000..bd07d916 --- /dev/null +++ b/tests/golden/M16-GAP-00244/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00244", + "parentTask": "M16-GAP-00243", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.hide data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.hide", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00244.py -- tests/files/web/generated/M16-GAP-00244-operator-armature.hide.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00244", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00244" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00244.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1745, + "contextRemainingTokens": 434 + }, + "source": { + "bytes": 8159, + "tokens": 2042 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00244.py", + "bytes": 1409, + "tokens": 353 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00244-operator-armature.hide.blend", + "bytes": 86303, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 239915, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 693671, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00244/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00244.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00244/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1409, + "tokens": 353 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00245", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00244.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00243/manifest.json", + "parentStatus": "docs/status/M16-GAP-00243.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00244.md", + "tests/golden/M16-GAP-00243/manifest.json", + "docs/status/M16-GAP-00243.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00243", + "parentTask": "M16-GAP-00242", + "status": "done", + "nextTask": "M16-GAP-00244", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00243 Status", + "status: done", + "task: armature.flip_names operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains two selected left/right bones and one independent unselected bone. Blender desktop runs `ARMATURE_OT_flip_names` with `do_strip_numbers=false`, swaps the selected bones' names by geometry, and preserves the independent bone.", + "- Main reads the saved post-operation names, selection state, and geometry from the same fixture. The comparator confirms desktop/WASM parity and save/reopen stability without expanding other data-blocks, editors, or browsers.", + "evidence:" + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1754, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 439 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2495, + "lines": 47, + "tokens": 624 + }, + { + "path": "docs/tasks/M16-GAP-00244.md", + "bytes": 1754, + "lines": 38, + "tokens": 439 + }, + { + "path": "tests/golden/M16-GAP-00243/manifest.json", + "bytes": 2937, + "lines": 74, + "tokens": 735 + }, + { + "path": "docs/status/M16-GAP-00243.md", + "bytes": 973, + "lines": 18, + "tokens": 244 + } + ], + "sourceTokens": 2042, + "evidenceFiles": 1, + "evidenceBytes": 1409, + "evidenceTokens": 353, + "totalTokens": 2395, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3419, + "serializedContextTokens": 749, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00245/armature-move-to-collection-desktop-report.json b/tests/golden/M16-GAP-00245/armature-move-to-collection-desktop-report.json new file mode 100644 index 00000000..f5495fd5 --- /dev/null +++ b/tests/golden/M16-GAP-00245/armature-move-to-collection-desktop-report.json @@ -0,0 +1,126 @@ +{ + "after": { + "activeBone": "WebGapArmatureMoveCollectionSelected", + "armature": "WebGapArmatureMoveCollectionArmature", + "bones": [ + { + "collections": [ + "WebGapArmatureMoveCollectionTarget" + ], + "connected": false, + "head": [ + -1.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureMoveCollectionSelected", + "parent": null, + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + -1.0, + 1.0, + 0.0 + ] + }, + { + "collections": [ + "WebGapArmatureMoveCollectionSource" + ], + "connected": false, + "head": [ + 1.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureMoveCollectionOther", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 1.0, + 1.0, + 0.0 + ] + } + ], + "collections": [ + "WebGapArmatureMoveCollectionSource", + "WebGapArmatureMoveCollectionTarget" + ], + "object": "WebGapArmatureMoveCollectionObject" + }, + "before": { + "activeBone": "WebGapArmatureMoveCollectionSelected", + "armature": "WebGapArmatureMoveCollectionArmature", + "bones": [ + { + "collections": [ + "WebGapArmatureMoveCollectionTarget" + ], + "connected": false, + "head": [ + -1.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureMoveCollectionSelected", + "parent": null, + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + -1.0, + 1.0, + 0.0 + ] + }, + { + "collections": [ + "WebGapArmatureMoveCollectionSource" + ], + "connected": false, + "head": [ + 1.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureMoveCollectionOther", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 1.0, + 1.0, + 0.0 + ] + } + ], + "collections": [ + "WebGapArmatureMoveCollectionSource", + "WebGapArmatureMoveCollectionTarget" + ], + "object": "WebGapArmatureMoveCollectionObject" + }, + "blenderVersion": "5.2.0 LTS", + "collectionIndex": 1, + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00245-operator-armature.move_to_collection.blend", + "fixtureSha256": "81ce010acf7df4374101651e498eb1ef4fdbd31aa79e395fcab17667cea2d6ad", + "mainMutation": "SELECTED_BONE_ALREADY_IN_TARGET_COLLECTION", + "movedBone": "WebGapArmatureMoveCollectionSelected", + "operation": "ARMATURE_MOVE_TO_COLLECTION_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "sourceCollection": "WebGapArmatureMoveCollectionSource", + "targetCollection": "WebGapArmatureMoveCollectionTarget", + "task": "M16-GAP-00245" +} diff --git a/tests/golden/M16-GAP-00245/armature-move-to-collection-local-exact-report.json b/tests/golden/M16-GAP-00245/armature-move-to-collection-local-exact-report.json new file mode 100644 index 00000000..f886485e --- /dev/null +++ b/tests/golden/M16-GAP-00245/armature-move-to-collection-local-exact-report.json @@ -0,0 +1,39 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00245", + "operation": "ARMATURE_MOVE_TO_COLLECTION_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00245-operator-armature.move_to_collection.blend", + "sha256": "81ce010acf7df4374101651e498eb1ef4fdbd31aa79e395fcab17667cea2d6ad" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00245/armature-move-to-collection-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "SELECTED_BONE_ALREADY_IN_TARGET_COLLECTION", + "movedBone": "WebGapArmatureMoveCollectionSelected", + "sourceCollection": "WebGapArmatureMoveCollectionSource", + "targetCollection": "WebGapArmatureMoveCollectionTarget" + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureMoveCollectionArmature", + "movedBoneId": "bone:armature:WebGapArmatureMoveCollectionArmature:WebGapArmatureMoveCollectionSelected", + "otherBoneId": "bone:armature:WebGapArmatureMoveCollectionArmature:WebGapArmatureMoveCollectionOther", + "sourceCollectionId": "bone_collection:armature:WebGapArmatureMoveCollectionArmature:WebGapArmatureMoveCollectionSource", + "targetCollectionId": "bone_collection:armature:WebGapArmatureMoveCollectionArmature:WebGapArmatureMoveCollectionTarget", + "sourceMembers": [ + "bone:armature:WebGapArmatureMoveCollectionArmature:WebGapArmatureMoveCollectionOther" + ], + "targetMembers": [ + "bone:armature:WebGapArmatureMoveCollectionArmature:WebGapArmatureMoveCollectionSelected" + ] + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00246" +} diff --git a/tests/golden/M16-GAP-00245/manifest.json b/tests/golden/M16-GAP-00245/manifest.json new file mode 100644 index 00000000..124c9a19 --- /dev/null +++ b/tests/golden/M16-GAP-00245/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00245", + "parentTask": "M16-GAP-00244", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_MOVE_TO_COLLECTION_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00244/manifest.json", + "sha256": "8a9113af05264d62c71c478ae8dfde62155e64cf2fa5bda32f16256f7df6bd59" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00245-operator-armature.move_to_collection.blend", + "sha256": "81ce010acf7df4374101651e498eb1ef4fdbd31aa79e395fcab17667cea2d6ad" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00245.py", + "sha256": "9a7de621f6e88acc93d19697d4a3db5223943318e70e4561983fd989cf120aa3" + }, + "desktopChecker": { + "path": "tools/web/check-action-armature-move-to-collection-desktop.py", + "sha256": "d70bbd2d42be0c4f95dc2fcc683daaad5d1eb2e71240dc8025dec2133f2d42dc" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "9a91d6de90a958161d66a11491a72059cd607077fdc58e51b6a8f5f8113bb82e" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "36ee1c408362b365d14f0d6c96a505796506a2fb50ec85dcdb06cd64f1d68e0c" + }, + "nativeStub": { + "path": "web/engine/web_engine_native_reader_stub.cpp", + "sha256": "2a1526e08cf446bb23a91c8c2ae799db38a0aeed0a809a15ead427780600481a" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "f0dada634e8aaf84f645f39a4ffeb649b71c691999ee6b7a0c15c4abcf3884d9" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "f0dada634e8aaf84f645f39a4ffeb649b71c691999ee6b7a0c15c4abcf3884d9" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "wasmJsPublic": { + "path": "web/app/public/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00245/armature-move-to-collection-desktop-report.json", + "sha256": "26ba97ec93b9e190d06dc912b8b441eb14c49d3a409ae2635aba0adc8dfa6f9b" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00245/armature-move-to-collection-local-exact-report.json", + "sha256": "d898f1ffaa59f14b7a92e88d90413d0b3c200548ee5288342938f3803077e186" + }, + "status": { + "path": "docs/status/M16-GAP-00245.md", + "sha256": "bad2709c02906d0e84d1771308245f3c2e3d52b3b9436719efd3d47155c0eae0" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00245/task-context.json", + "sha256": "a0e24448ada6a6649940caca0934e6cac7783f5e486efeb73baa352874e971c0" + } + }, + "nextTask": "M16-GAP-00246" +} diff --git a/tests/golden/M16-GAP-00245/task-context.json b/tests/golden/M16-GAP-00245/task-context.json new file mode 100644 index 00000000..cc8ec768 --- /dev/null +++ b/tests/golden/M16-GAP-00245/task-context.json @@ -0,0 +1,182 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00245", + "parentTask": "M16-GAP-00244", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.move_to_collection data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.move_to_collection", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00245.py -- tests/files/web/generated/M16-GAP-00245-operator-armature.move_to_collection.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00245", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00245" + ], + "inputPaths": [], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1680, + "contextRemainingTokens": 419 + }, + "source": { + "bytes": 8224, + "tokens": 2057 + }, + "selected": [], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00245-operator-armature.move_to_collection.blend", + "bytes": 86400, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/generated/M16-GAP-00245.py", + "bytes": 1703, + "reason": "CONTEXT_REMAINING_SPACE" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 239915, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 698782, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00245/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00245.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00245/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 0, + "bytes": 0, + "tokens": 0 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00246", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00245.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00244/manifest.json", + "parentStatus": "docs/status/M16-GAP-00244.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00245.md", + "tests/golden/M16-GAP-00244/manifest.json", + "docs/status/M16-GAP-00244.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00244", + "parentTask": "M16-GAP-00243", + "status": "done", + "nextTask": "M16-GAP-00245", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00244 Status", + "status: done", + "task: armature.hide operator LOCAL_EXACT slice", + "updated: 2026-08-22 America/New_York", + "scope:", + "- The minimal fixture contains one selected bone and one independent unselected bone. Blender desktop runs `ARMATURE_OT_hide` with `unselected=false`, setting the selected bone's edit-mode hidden flag and clearing its selection while preserving the independent bone and both geometries.", + "- Main exposes the saved hidden and selected flags from the same fixture. The comparator confirms desktop/WASM parity and save/reopen stability without expanding other data-blocks, editors, or browsers.", + "evidence:" + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1824, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 456 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2495, + "lines": 47, + "tokens": 624 + }, + { + "path": "docs/tasks/M16-GAP-00245.md", + "bytes": 1824, + "lines": 38, + "tokens": 456 + }, + { + "path": "tests/golden/M16-GAP-00244/manifest.json", + "bytes": 2907, + "lines": 74, + "tokens": 727 + }, + { + "path": "docs/status/M16-GAP-00244.md", + "bytes": 998, + "lines": 18, + "tokens": 250 + } + ], + "sourceTokens": 2057, + "evidenceFiles": 0, + "evidenceBytes": 0, + "evidenceTokens": 0, + "totalTokens": 2057, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3081, + "serializedContextTokens": 724, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00246/armature-parent-clear-desktop-report.json b/tests/golden/M16-GAP-00246/armature-parent-clear-desktop-report.json new file mode 100644 index 00000000..a4d873cb --- /dev/null +++ b/tests/golden/M16-GAP-00246/armature-parent-clear-desktop-report.json @@ -0,0 +1,143 @@ +{ + "after": { + "activeBone": "WebGapArmatureParentClearChild", + "armature": "WebGapArmatureParentClearArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureParentClearParent", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 0.0, + 1.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureParentClearChild", + "parent": null, + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 2.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureParentClearOther", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureParentClearObject" + }, + "before": { + "activeBone": "WebGapArmatureParentClearChild", + "armature": "WebGapArmatureParentClearArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureParentClearParent", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 0.0, + 1.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureParentClearChild", + "parent": null, + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 2.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureParentClearOther", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureParentClearObject" + }, + "blenderVersion": "5.2.0 LTS", + "childBone": "WebGapArmatureParentClearChild", + "clearType": "CLEAR", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00246-operator-armature.parent_clear.blend", + "fixtureSha256": "c6b8c2871a84389b732ff63c320e1e6543e832f69a89aa7af8cd0049fbee82f2", + "mainMutation": "SELECTED_CHILD_PARENT_ALREADY_CLEARED", + "operation": "ARMATURE_PARENT_CLEAR_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "parentBone": "WebGapArmatureParentClearParent", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00246" +} diff --git a/tests/golden/M16-GAP-00246/armature-parent-clear-local-exact-report.json b/tests/golden/M16-GAP-00246/armature-parent-clear-local-exact-report.json new file mode 100644 index 00000000..3d43ec45 --- /dev/null +++ b/tests/golden/M16-GAP-00246/armature-parent-clear-local-exact-report.json @@ -0,0 +1,34 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00246", + "operation": "ARMATURE_PARENT_CLEAR_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00246-operator-armature.parent_clear.blend", + "sha256": "c6b8c2871a84389b732ff63c320e1e6543e832f69a89aa7af8cd0049fbee82f2" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00246/armature-parent-clear-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "SELECTED_CHILD_PARENT_ALREADY_CLEARED", + "parentBone": "WebGapArmatureParentClearParent", + "childBone": "WebGapArmatureParentClearChild", + "clearType": "CLEAR" + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureParentClearArmature", + "parentBoneId": "bone:armature:WebGapArmatureParentClearArmature:WebGapArmatureParentClearParent", + "childBoneId": "bone:armature:WebGapArmatureParentClearArmature:WebGapArmatureParentClearChild", + "otherBoneId": "bone:armature:WebGapArmatureParentClearArmature:WebGapArmatureParentClearOther", + "childParentId": null, + "childSelected": true + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00247" +} diff --git a/tests/golden/M16-GAP-00246/manifest.json b/tests/golden/M16-GAP-00246/manifest.json new file mode 100644 index 00000000..ceb66165 --- /dev/null +++ b/tests/golden/M16-GAP-00246/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00246", + "parentTask": "M16-GAP-00245", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_PARENT_CLEAR_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00245/manifest.json", + "sha256": "4b5876e4b5058907a06ab54907f96be1d2f887b3495e696093ee015c084bb4a8" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00246-operator-armature.parent_clear.blend", + "sha256": "c6b8c2871a84389b732ff63c320e1e6543e832f69a89aa7af8cd0049fbee82f2" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00246.py", + "sha256": "2d2f7b43517d2b39a44f6a2606ecf932925f31b6896c01a657ce2dfe8008e703" + }, + "desktopChecker": { + "path": "tools/web/check-action-armature-parent-clear-desktop.py", + "sha256": "14c76e67447509588d74055eb26dd12401b3608fac335bf732a09980a2d6c443" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "36805990a46f98cec41d15e6a81168213eb7830f7255705705591060344cdee3" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "36ee1c408362b365d14f0d6c96a505796506a2fb50ec85dcdb06cd64f1d68e0c" + }, + "nativeStub": { + "path": "web/engine/web_engine_native_reader_stub.cpp", + "sha256": "2a1526e08cf446bb23a91c8c2ae799db38a0aeed0a809a15ead427780600481a" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "f0dada634e8aaf84f645f39a4ffeb649b71c691999ee6b7a0c15c4abcf3884d9" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "f0dada634e8aaf84f645f39a4ffeb649b71c691999ee6b7a0c15c4abcf3884d9" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "wasmJsPublic": { + "path": "web/app/public/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00246/armature-parent-clear-desktop-report.json", + "sha256": "e59a8594cbc6f313ac9651706575eeabd2d58fb2520eafdf825c5a467a2d9b7a" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00246/armature-parent-clear-local-exact-report.json", + "sha256": "3e89fd698b0a8d118b0dcfb428f957ad7cc051e5a7a5b898cf90f49c996080a2" + }, + "status": { + "path": "docs/status/M16-GAP-00246.md", + "sha256": "5cc88cc19daa3fe9ad1a50f568d0d482c71c8b535a2e8bf024625bc7d9ca4592" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00246/task-context.json", + "sha256": "bc87cb6e78492af2c7c31afa6da9ea79e919ecdc793d7a720b1fa6127df6fc93" + } + }, + "nextTask": "M16-GAP-00247" +} diff --git a/tests/golden/M16-GAP-00246/task-context.json b/tests/golden/M16-GAP-00246/task-context.json new file mode 100644 index 00000000..195eb27f --- /dev/null +++ b/tests/golden/M16-GAP-00246/task-context.json @@ -0,0 +1,182 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00246", + "parentTask": "M16-GAP-00245", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.parent_clear data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.parent_clear", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00246.py -- tests/files/web/generated/M16-GAP-00246-operator-armature.parent_clear.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00246", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00246" + ], + "inputPaths": [], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1633, + "contextRemainingTokens": 406 + }, + "source": { + "bytes": 8271, + "tokens": 2070 + }, + "selected": [], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00246-operator-armature.parent_clear.blend", + "bytes": 86343, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/generated/M16-GAP-00246.py", + "bytes": 1736, + "reason": "CONTEXT_REMAINING_SPACE" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 239915, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 703493, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00246/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00246.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00246/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 0, + "bytes": 0, + "tokens": 0 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00247", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00246.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00245/manifest.json", + "parentStatus": "docs/status/M16-GAP-00245.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00246.md", + "tests/golden/M16-GAP-00245/manifest.json", + "docs/status/M16-GAP-00245.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00245", + "parentTask": "M16-GAP-00244", + "status": "done", + "nextTask": "M16-GAP-00246", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00245 Status", + "status: done", + "task: armature.move_to_collection operator LOCAL_EXACT slice", + "updated: 2026-08-23 America/New_York", + "scope:", + "- The minimal fixture contains two bone collections, one selected bone in the source collection, and one independent unselected bone. Blender desktop runs `ARMATURE_OT_move_to_collection` with `collection_index=1`, moving only the selected bone to the target collection while preserving selection and geometry.", + "- Main exposes both collection member lists from the same fixture. The comparator confirms desktop/WASM parity and save/reopen stability without expanding other data-blocks, editors, or browsers.", + "evidence:" + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1794, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 449 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2495, + "lines": 47, + "tokens": 624 + }, + { + "path": "docs/tasks/M16-GAP-00246.md", + "bytes": 1794, + "lines": 38, + "tokens": 449 + }, + { + "path": "tests/golden/M16-GAP-00245/manifest.json", + "bytes": 2977, + "lines": 74, + "tokens": 745 + }, + { + "path": "docs/status/M16-GAP-00245.md", + "bytes": 1005, + "lines": 18, + "tokens": 252 + } + ], + "sourceTokens": 2070, + "evidenceFiles": 0, + "evidenceBytes": 0, + "evidenceTokens": 0, + "totalTokens": 2070, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3094, + "serializedContextTokens": 720, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00247/armature-parent-set-desktop-report.json b/tests/golden/M16-GAP-00247/armature-parent-set-desktop-report.json new file mode 100644 index 00000000..156379ee --- /dev/null +++ b/tests/golden/M16-GAP-00247/armature-parent-set-desktop-report.json @@ -0,0 +1,143 @@ +{ + "after": { + "activeBone": "WebGapArmatureParentSetParent", + "armature": "WebGapArmatureParentSetArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureParentSetParent", + "parent": null, + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": true, + "head": [ + 0.0, + 1.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureParentSetChild", + "parent": "WebGapArmatureParentSetParent", + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 2.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureParentSetOther", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureParentSetObject" + }, + "before": { + "activeBone": "WebGapArmatureParentSetParent", + "armature": "WebGapArmatureParentSetArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureParentSetParent", + "parent": null, + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": true, + "head": [ + 0.0, + 1.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureParentSetChild", + "parent": "WebGapArmatureParentSetParent", + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 2.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureParentSetOther", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureParentSetObject" + }, + "blenderVersion": "5.2.0 LTS", + "childBone": "WebGapArmatureParentSetChild", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00247-operator-armature.parent_set.blend", + "fixtureSha256": "227b3294c94147755638a6542955fd7a57ad2a6e6a7464bed2509eb7a5ab6b19", + "mainMutation": "SELECTED_CHILD_PARENT_ALREADY_CONNECTED", + "operation": "ARMATURE_PARENT_SET_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "parentBone": "WebGapArmatureParentSetParent", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "setType": "CONNECTED", + "task": "M16-GAP-00247" +} diff --git a/tests/golden/M16-GAP-00247/armature-parent-set-local-exact-report.json b/tests/golden/M16-GAP-00247/armature-parent-set-local-exact-report.json new file mode 100644 index 00000000..174829a3 --- /dev/null +++ b/tests/golden/M16-GAP-00247/armature-parent-set-local-exact-report.json @@ -0,0 +1,35 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00247", + "operation": "ARMATURE_PARENT_SET_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00247-operator-armature.parent_set.blend", + "sha256": "227b3294c94147755638a6542955fd7a57ad2a6e6a7464bed2509eb7a5ab6b19" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00247/armature-parent-set-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "SELECTED_CHILD_PARENT_ALREADY_CONNECTED", + "parentBone": "WebGapArmatureParentSetParent", + "childBone": "WebGapArmatureParentSetChild", + "setType": "CONNECTED" + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureParentSetArmature", + "parentBoneId": "bone:armature:WebGapArmatureParentSetArmature:WebGapArmatureParentSetParent", + "childBoneId": "bone:armature:WebGapArmatureParentSetArmature:WebGapArmatureParentSetChild", + "otherBoneId": "bone:armature:WebGapArmatureParentSetArmature:WebGapArmatureParentSetOther", + "childParentId": "bone:armature:WebGapArmatureParentSetArmature:WebGapArmatureParentSetParent", + "childConnected": true, + "childSelected": true + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00248" +} diff --git a/tests/golden/M16-GAP-00247/manifest.json b/tests/golden/M16-GAP-00247/manifest.json new file mode 100644 index 00000000..d74bc18c --- /dev/null +++ b/tests/golden/M16-GAP-00247/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00247", + "parentTask": "M16-GAP-00246", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_PARENT_SET_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00246/manifest.json", + "sha256": "39e5586ea4faa434cb83fb7d0c78e9e5bbb5b7b3485b76198ddd9279a5615fc0" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00247-operator-armature.parent_set.blend", + "sha256": "227b3294c94147755638a6542955fd7a57ad2a6e6a7464bed2509eb7a5ab6b19" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00247.py", + "sha256": "1767464c3c6a2a24207c56bb59fecfd20f49ef7b83055716b209de354a04ff5d" + }, + "desktopChecker": { + "path": "tools/web/check-action-armature-parent-set-desktop.py", + "sha256": "ced6127b73540a64f95327103cea846d95b3da829a41b64e66de6e160ff2d7cb" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "65d133091a56490376a7919befbdffe0be73893386ab121e89683bf6388d5f5a" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "0c39ec01b1e5c828f563a60ea1416fc95bbb2645dbe8d541242fbc23ce1b1deb" + }, + "nativeStub": { + "path": "web/engine/web_engine_native_reader_stub.cpp", + "sha256": "2a1526e08cf446bb23a91c8c2ae799db38a0aeed0a809a15ead427780600481a" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "95c948f8b4fe59c299a0fe0f8454140fa4aacc8fdf41f2872317e8f5e0861e0c" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "95c948f8b4fe59c299a0fe0f8454140fa4aacc8fdf41f2872317e8f5e0861e0c" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "wasmJsPublic": { + "path": "web/app/public/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00247/armature-parent-set-desktop-report.json", + "sha256": "c2348f9a4e51030006f9c1a2756f016e2c454d957a952e2d07a2948dabba9f4a" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00247/armature-parent-set-local-exact-report.json", + "sha256": "ed5125f71cbe8af51244c5bc8798b2d0722d3272a331b9999ba22f5606926139" + }, + "status": { + "path": "docs/status/M16-GAP-00247.md", + "sha256": "26711b27363845b086c413d07119622c93ef468f28f412576842b1f809f6b5b6" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00247/task-context.json", + "sha256": "63cae595ebf9ce8be4b1d02e48e6130371978eaae49133e5da24b87dfcca7b53" + } + }, + "nextTask": "M16-GAP-00248" +} diff --git a/tests/golden/M16-GAP-00247/task-context.json b/tests/golden/M16-GAP-00247/task-context.json new file mode 100644 index 00000000..077cd424 --- /dev/null +++ b/tests/golden/M16-GAP-00247/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00247", + "parentTask": "M16-GAP-00246", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.parent_set data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.parent_set", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00247.py -- tests/files/web/generated/M16-GAP-00247-operator-armature.parent_set.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00247", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00247" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00247.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1721, + "contextRemainingTokens": 429 + }, + "source": { + "bytes": 8183, + "tokens": 2047 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00247.py", + "bytes": 1669, + "tokens": 418 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00247-operator-armature.parent_set.blend", + "bytes": 86366, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 239979, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 708415, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00247/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00247.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00247/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1669, + "tokens": 418 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00248", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00247.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00246/manifest.json", + "parentStatus": "docs/status/M16-GAP-00246.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00247.md", + "tests/golden/M16-GAP-00246/manifest.json", + "docs/status/M16-GAP-00246.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00246", + "parentTask": "M16-GAP-00245", + "status": "done", + "nextTask": "M16-GAP-00247", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00246 Status", + "status: done", + "task: armature.parent_clear operator LOCAL_EXACT slice", + "updated: 2026-08-23 America/New_York", + "scope:", + "- The minimal fixture contains a connected selected child, its parent, and one independent unselected bone. Blender desktop runs `ARMATURE_OT_parent_clear` with `type=CLEAR`, clearing only the selected child's parent and connection while preserving all geometry and selection.", + "- Main exposes the saved parent IDs from the same fixture. The comparator confirms desktop/WASM parity and save/reopen stability without expanding other data-blocks, editors, or browsers.", + "evidence:" + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1784, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 446 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2495, + "lines": 47, + "tokens": 624 + }, + { + "path": "docs/tasks/M16-GAP-00247.md", + "bytes": 1784, + "lines": 38, + "tokens": 446 + }, + { + "path": "tests/golden/M16-GAP-00246/manifest.json", + "bytes": 2947, + "lines": 74, + "tokens": 737 + }, + { + "path": "docs/status/M16-GAP-00246.md", + "bytes": 957, + "lines": 18, + "tokens": 240 + } + ], + "sourceTokens": 2047, + "evidenceFiles": 1, + "evidenceBytes": 1669, + "evidenceTokens": 418, + "totalTokens": 2465, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3489, + "serializedContextTokens": 753, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00248/armature-reveal-desktop-report.json b/tests/golden/M16-GAP-00248/armature-reveal-desktop-report.json new file mode 100644 index 00000000..56e095a5 --- /dev/null +++ b/tests/golden/M16-GAP-00248/armature-reveal-desktop-report.json @@ -0,0 +1,104 @@ +{ + "after": { + "activeBone": "WebGapArmatureRevealOther", + "armature": "WebGapArmatureRevealArmature", + "bones": [ + { + "connected": false, + "head": [ + -1.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureRevealHidden", + "parent": null, + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + -1.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 1.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureRevealOther", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 1.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureRevealObject" + }, + "before": { + "activeBone": "WebGapArmatureRevealOther", + "armature": "WebGapArmatureRevealArmature", + "bones": [ + { + "connected": false, + "head": [ + -1.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureRevealHidden", + "parent": null, + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + -1.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 1.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureRevealOther", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 1.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureRevealObject" + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00248-operator-armature.reveal.blend", + "fixtureSha256": "5f1ee7176f2d030247abb278a66f79cc6b7fc49fd6650b2dba7cc349e2b0aedb", + "mainMutation": "HIDDEN_BONE_ALREADY_REVEALED", + "operation": "ARMATURE_REVEAL_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "poll": true, + "revealedBone": "WebGapArmatureRevealHidden", + "saveReopen": "EXACT", + "schemaVersion": 1, + "select": true, + "task": "M16-GAP-00248" +} diff --git a/tests/golden/M16-GAP-00248/armature-reveal-local-exact-report.json b/tests/golden/M16-GAP-00248/armature-reveal-local-exact-report.json new file mode 100644 index 00000000..31c403c0 --- /dev/null +++ b/tests/golden/M16-GAP-00248/armature-reveal-local-exact-report.json @@ -0,0 +1,33 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00248", + "operation": "ARMATURE_REVEAL_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00248-operator-armature.reveal.blend", + "sha256": "5f1ee7176f2d030247abb278a66f79cc6b7fc49fd6650b2dba7cc349e2b0aedb" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00248/armature-reveal-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "HIDDEN_BONE_ALREADY_REVEALED", + "revealedBone": "WebGapArmatureRevealHidden", + "select": true + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureRevealArmature", + "revealedBoneId": "bone:armature:WebGapArmatureRevealArmature:WebGapArmatureRevealHidden", + "otherBoneId": "bone:armature:WebGapArmatureRevealArmature:WebGapArmatureRevealOther", + "revealedHidden": false, + "revealedSelected": true, + "otherHidden": false + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00249" +} diff --git a/tests/golden/M16-GAP-00248/manifest.json b/tests/golden/M16-GAP-00248/manifest.json new file mode 100644 index 00000000..331d4e24 --- /dev/null +++ b/tests/golden/M16-GAP-00248/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00248", + "parentTask": "M16-GAP-00247", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_REVEAL_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00247/manifest.json", + "sha256": "67a3b226b8c4d1449d7b655a5d019fff0c374fd63eee65041ea171ae4c6e92e6" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00248-operator-armature.reveal.blend", + "sha256": "5f1ee7176f2d030247abb278a66f79cc6b7fc49fd6650b2dba7cc349e2b0aedb" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00248.py", + "sha256": "8fac586cf7c3f54822111df0c88151797e68af0283e39f075dd9cd70d080ed93" + }, + "desktopChecker": { + "path": "tools/web/check-action-armature-reveal-desktop.py", + "sha256": "06564434a76ea6670110e916f73efdec46238cc1b2c8e1aa3d1c893b8089331d" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "098891e1d53e13ab172fde7122e6dbc462c9401a03b60cf9caec1795357591ad" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "0c39ec01b1e5c828f563a60ea1416fc95bbb2645dbe8d541242fbc23ce1b1deb" + }, + "nativeStub": { + "path": "web/engine/web_engine_native_reader_stub.cpp", + "sha256": "2a1526e08cf446bb23a91c8c2ae799db38a0aeed0a809a15ead427780600481a" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "95c948f8b4fe59c299a0fe0f8454140fa4aacc8fdf41f2872317e8f5e0861e0c" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "95c948f8b4fe59c299a0fe0f8454140fa4aacc8fdf41f2872317e8f5e0861e0c" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "wasmJsPublic": { + "path": "web/app/public/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00248/armature-reveal-desktop-report.json", + "sha256": "7f972847f4646f54f02e2e25efefd993c083c0be15ed18c2b570640bc314059a" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00248/armature-reveal-local-exact-report.json", + "sha256": "35ca506d64f000444107c2a6da1b8a7074204c415dc6d4ea4afc9492aeb57209" + }, + "status": { + "path": "docs/status/M16-GAP-00248.md", + "sha256": "fb619f3dabf2d6f3593417893901d0eac7d73ccab4b836ba1824834bf6d46a95" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00248/task-context.json", + "sha256": "db45073631709d276137b75c98057adc5b96605f45b929c42067333b9607cade" + } + }, + "nextTask": "M16-GAP-00249" +} diff --git a/tests/golden/M16-GAP-00248/task-context.json b/tests/golden/M16-GAP-00248/task-context.json new file mode 100644 index 00000000..1f49e8b8 --- /dev/null +++ b/tests/golden/M16-GAP-00248/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00248", + "parentTask": "M16-GAP-00247", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.reveal data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.reveal", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00248.py -- tests/files/web/generated/M16-GAP-00248-operator-armature.reveal.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00248", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00248" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00248.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1668, + "contextRemainingTokens": 416 + }, + "source": { + "bytes": 8236, + "tokens": 2060 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00248.py", + "bytes": 1444, + "tokens": 361 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00248-operator-armature.reveal.blend", + "bytes": 86308, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 239979, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 713039, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00248/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00248.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00248/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1444, + "tokens": 361 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00249", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00248.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00247/manifest.json", + "parentStatus": "docs/status/M16-GAP-00247.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00248.md", + "tests/golden/M16-GAP-00247/manifest.json", + "docs/status/M16-GAP-00247.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00247", + "parentTask": "M16-GAP-00246", + "status": "done", + "nextTask": "M16-GAP-00248", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00247 Status", + "status: done", + "task: armature.parent_set operator LOCAL_EXACT slice", + "updated: 2026-08-23 America/New_York", + "scope:", + "- The minimal fixture contains a selected connected child, its selected parent,", + " and one independent unselected bone. Blender desktop observes", + " `ARMATURE_OT_parent_set` with `type=CONNECTED`; the existing parent and" + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1764, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 441 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2495, + "lines": 47, + "tokens": 624 + }, + { + "path": "docs/tasks/M16-GAP-00248.md", + "bytes": 1764, + "lines": 38, + "tokens": 441 + }, + { + "path": "tests/golden/M16-GAP-00247/manifest.json", + "bytes": 2937, + "lines": 74, + "tokens": 735 + }, + { + "path": "docs/status/M16-GAP-00247.md", + "bytes": 1040, + "lines": 27, + "tokens": 260 + } + ], + "sourceTokens": 2060, + "evidenceFiles": 1, + "evidenceBytes": 1444, + "evidenceTokens": 361, + "totalTokens": 2421, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3445, + "serializedContextTokens": 751, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00249/armature-roll-clear-desktop-report.json b/tests/golden/M16-GAP-00249/armature-roll-clear-desktop-report.json new file mode 100644 index 00000000..71d9c490 --- /dev/null +++ b/tests/golden/M16-GAP-00249/armature-roll-clear-desktop-report.json @@ -0,0 +1,96 @@ +{ + "after": { + "activeBone": "WebGapArmatureRollClearBone", + "armature": "WebGapArmatureRollClearArmature", + "bones": [ + { + "head": [ + 0.0, + 0.0, + 0.0 + ], + "hidden": false, + "matrix": [ + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0 + ], + "name": "WebGapArmatureRollClearBone", + "roll": 0.0, + "selected": true, + "tail": [ + 0.0, + 2.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureRollClearObject" + }, + "before": { + "activeBone": "WebGapArmatureRollClearBone", + "armature": "WebGapArmatureRollClearArmature", + "bones": [ + { + "head": [ + 0.0, + 0.0, + 0.0 + ], + "hidden": false, + "matrix": [ + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0 + ], + "name": "WebGapArmatureRollClearBone", + "roll": 0.0, + "selected": true, + "tail": [ + 0.0, + 2.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureRollClearObject" + }, + "blenderVersion": "5.2.0 LTS", + "bone": "WebGapArmatureRollClearBone", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00249-operator-armature.roll_clear.blend", + "fixtureSha256": "74c3bebdac81def2d5dad922854b06c1c0b112154605a955628754bf5eb3cef7", + "mainMutation": "ROLL_ALREADY_ZERO", + "operation": "ARMATURE_ROLL_CLEAR_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "poll": true, + "roll": 0.0, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00249" +} diff --git a/tests/golden/M16-GAP-00249/armature-roll-clear-local-exact-report.json b/tests/golden/M16-GAP-00249/armature-roll-clear-local-exact-report.json new file mode 100644 index 00000000..0044ab4a --- /dev/null +++ b/tests/golden/M16-GAP-00249/armature-roll-clear-local-exact-report.json @@ -0,0 +1,50 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00249", + "operation": "ARMATURE_ROLL_CLEAR_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00249-operator-armature.roll_clear.blend", + "sha256": "74c3bebdac81def2d5dad922854b06c1c0b112154605a955628754bf5eb3cef7" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00249/armature-roll-clear-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "ROLL_ALREADY_ZERO", + "bone": "WebGapArmatureRollClearBone", + "roll": 0 + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureRollClearArmature", + "boneId": "bone:armature:WebGapArmatureRollClearArmature:WebGapArmatureRollClearBone", + "boneName": "WebGapArmatureRollClearBone", + "hidden": false, + "selected": true, + "restMatrix": [ + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1 + ] + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00250" +} diff --git a/tests/golden/M16-GAP-00249/manifest.json b/tests/golden/M16-GAP-00249/manifest.json new file mode 100644 index 00000000..84d7786f --- /dev/null +++ b/tests/golden/M16-GAP-00249/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00249", + "parentTask": "M16-GAP-00248", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_ROLL_CLEAR_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00248/manifest.json", + "sha256": "e45b54186a20a2432423a0ae345345b7af8d83a958d5937efb332b1d59d4607f" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00249-operator-armature.roll_clear.blend", + "sha256": "74c3bebdac81def2d5dad922854b06c1c0b112154605a955628754bf5eb3cef7" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00249.py", + "sha256": "38b8b84ca841093bff16caf3aa8b10e8f033f16649f58c7b77292b34fb94c08e" + }, + "desktopChecker": { + "path": "tools/web/check-action-armature-roll-clear-desktop.py", + "sha256": "c5f507c1601fd4fe026f37b4c720a684881a01272eb92fd663dfb2ec2d43057b" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "57175a270c225e15af11e2f31a814f924c1902ceeede7b1e2bd6a7e98ad2781c" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "0c39ec01b1e5c828f563a60ea1416fc95bbb2645dbe8d541242fbc23ce1b1deb" + }, + "nativeStub": { + "path": "web/engine/web_engine_native_reader_stub.cpp", + "sha256": "2a1526e08cf446bb23a91c8c2ae799db38a0aeed0a809a15ead427780600481a" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "95c948f8b4fe59c299a0fe0f8454140fa4aacc8fdf41f2872317e8f5e0861e0c" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "95c948f8b4fe59c299a0fe0f8454140fa4aacc8fdf41f2872317e8f5e0861e0c" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "wasmJsPublic": { + "path": "web/app/public/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00249/armature-roll-clear-desktop-report.json", + "sha256": "d4961663044d04bed11d79948c12d7672d541da799cc519a7e0043023fd0540a" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00249/armature-roll-clear-local-exact-report.json", + "sha256": "60aff7413075c183ce0f8c443784b01cbb57343463588185c5f1839636e07ee6" + }, + "status": { + "path": "docs/status/M16-GAP-00249.md", + "sha256": "99656df59b260315621efa7792d2e4eaee6709ff434058d848c86b6b9a674771" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00249/task-context.json", + "sha256": "ca58f30a8476e7f61c6b3dec4d2225582cfcb9f4af454b62a42a48d2449ed74b" + } + }, + "nextTask": "M16-GAP-00250" +} diff --git a/tests/golden/M16-GAP-00249/task-context.json b/tests/golden/M16-GAP-00249/task-context.json new file mode 100644 index 00000000..81f825e2 --- /dev/null +++ b/tests/golden/M16-GAP-00249/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00249", + "parentTask": "M16-GAP-00248", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.roll_clear data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.roll_clear", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00249.py -- tests/files/web/generated/M16-GAP-00249-operator-armature.roll_clear.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00249", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00249" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00249.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1773, + "contextRemainingTokens": 442 + }, + "source": { + "bytes": 8131, + "tokens": 2034 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00249.py", + "bytes": 1208, + "tokens": 302 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00249-operator-armature.roll_clear.blend", + "bytes": 86204, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 239979, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 717402, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00249/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00249.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00249/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1208, + "tokens": 302 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00250", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00249.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00248/manifest.json", + "parentStatus": "docs/status/M16-GAP-00248.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00249.md", + "tests/golden/M16-GAP-00248/manifest.json", + "docs/status/M16-GAP-00248.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00248", + "parentTask": "M16-GAP-00247", + "status": "done", + "nextTask": "M16-GAP-00249", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00248 Status", + "status: done", + "task: armature.reveal operator LOCAL_EXACT slice", + "updated: 2026-08-23 America/New_York", + "scope:", + "- The minimal fixture contains one hidden edit bone and one independent visible", + " unselected bone. Blender desktop runs `ARMATURE_OT_reveal(select=true)`,", + " revealing and selecting only the hidden bone while preserving both geometries." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1784, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 446 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2495, + "lines": 47, + "tokens": 624 + }, + { + "path": "docs/tasks/M16-GAP-00249.md", + "bytes": 1784, + "lines": 38, + "tokens": 446 + }, + { + "path": "tests/golden/M16-GAP-00248/manifest.json", + "bytes": 2917, + "lines": 74, + "tokens": 730 + }, + { + "path": "docs/status/M16-GAP-00248.md", + "bytes": 935, + "lines": 25, + "tokens": 234 + } + ], + "sourceTokens": 2034, + "evidenceFiles": 1, + "evidenceBytes": 1208, + "evidenceTokens": 302, + "totalTokens": 2336, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3360, + "serializedContextTokens": 753, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00250/armature-select-all-desktop-report.json b/tests/golden/M16-GAP-00250/armature-select-all-desktop-report.json new file mode 100644 index 00000000..0f4f78be --- /dev/null +++ b/tests/golden/M16-GAP-00250/armature-select-all-desktop-report.json @@ -0,0 +1,107 @@ +{ + "action": "SELECT", + "after": { + "activeBone": "WebGapArmatureSelectAllParent", + "armature": "WebGapArmatureSelectAllArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectAllParent", + "parent": null, + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectAllOther", + "parent": null, + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureSelectAllObject" + }, + "before": { + "activeBone": "WebGapArmatureSelectAllParent", + "armature": "WebGapArmatureSelectAllArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectAllParent", + "parent": null, + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectAllOther", + "parent": null, + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureSelectAllObject" + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00250-operator-armature.select_all.blend", + "fixtureSha256": "5a271a11ec041966bbdb02724d632b1a1ec4db2207038fdbf3fffbd8c3d6de8d", + "mainMutation": "ALL_VISIBLE_BONES_ALREADY_SELECTED", + "operation": "ARMATURE_SELECT_ALL_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "selectedBones": [ + "WebGapArmatureSelectAllParent", + "WebGapArmatureSelectAllOther" + ], + "task": "M16-GAP-00250" +} diff --git a/tests/golden/M16-GAP-00250/armature-select-all-local-exact-report.json b/tests/golden/M16-GAP-00250/armature-select-all-local-exact-report.json new file mode 100644 index 00000000..ab9db1d3 --- /dev/null +++ b/tests/golden/M16-GAP-00250/armature-select-all-local-exact-report.json @@ -0,0 +1,55 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00250", + "operation": "ARMATURE_SELECT_ALL_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00250-operator-armature.select_all.blend", + "sha256": "5a271a11ec041966bbdb02724d632b1a1ec4db2207038fdbf3fffbd8c3d6de8d" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00250/armature-select-all-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "ALL_VISIBLE_BONES_ALREADY_SELECTED", + "selectedBones": [ + "WebGapArmatureSelectAllParent", + "WebGapArmatureSelectAllOther" + ], + "action": "SELECT" + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureSelectAllArmature", + "parentBoneId": "bone:armature:WebGapArmatureSelectAllArmature:WebGapArmatureSelectAllParent", + "otherBoneId": "bone:armature:WebGapArmatureSelectAllArmature:WebGapArmatureSelectAllOther", + "parentSelected": true, + "otherSelected": true, + "parentHead": [ + 0, + 0, + 0 + ], + "parentTail": [ + 0, + 1, + 0 + ], + "otherHead": [ + 2, + 0, + 0 + ], + "otherTail": [ + 2, + 1, + 0 + ] + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00251" +} diff --git a/tests/golden/M16-GAP-00250/manifest.json b/tests/golden/M16-GAP-00250/manifest.json new file mode 100644 index 00000000..30eac7db --- /dev/null +++ b/tests/golden/M16-GAP-00250/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00250", + "parentTask": "M16-GAP-00249", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_SELECT_ALL_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00249/manifest.json", + "sha256": "50e0101c306390090c8ff008897450c5b0034428a6b4f06e53c340887a202562" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00250-operator-armature.select_all.blend", + "sha256": "5a271a11ec041966bbdb02724d632b1a1ec4db2207038fdbf3fffbd8c3d6de8d" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00250.py", + "sha256": "fd1e6bca22e8b9e29cdaee6d7df3b561d7b1cfaff4d8ac96e9a7b807a8940e8f" + }, + "desktopChecker": { + "path": "tools/web/check-action-armature-select-all-desktop.py", + "sha256": "3dff6a053b4a497ed19b67b6e0d38958abd6f34c603b994a8eb59323f4ab95e5" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "5a7f84720576f50aac4f862677f471c0ef92c20943003a0c6d192d8852757573" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "0c39ec01b1e5c828f563a60ea1416fc95bbb2645dbe8d541242fbc23ce1b1deb" + }, + "nativeStub": { + "path": "web/engine/web_engine_native_reader_stub.cpp", + "sha256": "2a1526e08cf446bb23a91c8c2ae799db38a0aeed0a809a15ead427780600481a" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "95c948f8b4fe59c299a0fe0f8454140fa4aacc8fdf41f2872317e8f5e0861e0c" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "95c948f8b4fe59c299a0fe0f8454140fa4aacc8fdf41f2872317e8f5e0861e0c" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "wasmJsPublic": { + "path": "web/app/public/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00250/armature-select-all-desktop-report.json", + "sha256": "0d68d0d0b4f3880339f29ef467bc7ab241623bdf3422ca83c53b49efec5e7295" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00250/armature-select-all-local-exact-report.json", + "sha256": "e8d922dde3d8401c79adc75621523ee3441a4d97f74416816e2f2209083297b2" + }, + "status": { + "path": "docs/status/M16-GAP-00250.md", + "sha256": "dcc9e9890aa1e9bf5df7f2c91155c98fcce954896258cad6b2b4778048e502d2" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00250/task-context.json", + "sha256": "75f8b5a9a167a179607417792bf5520b1cbb4c0eec5e665be7769c65265554d5" + } + }, + "nextTask": "M16-GAP-00251" +} diff --git a/tests/golden/M16-GAP-00250/task-context.json b/tests/golden/M16-GAP-00250/task-context.json new file mode 100644 index 00000000..b77e5410 --- /dev/null +++ b/tests/golden/M16-GAP-00250/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00250", + "parentTask": "M16-GAP-00249", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.select_all data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.select_all", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00250.py -- tests/files/web/generated/M16-GAP-00250-operator-armature.select_all.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00250", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00250" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00250.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1736, + "contextRemainingTokens": 433 + }, + "source": { + "bytes": 8168, + "tokens": 2043 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00250.py", + "bytes": 1429, + "tokens": 358 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00250-operator-armature.select_all.blend", + "bytes": 86286, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 239979, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 722153, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00250/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00250.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00250/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1429, + "tokens": 358 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00251", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00250.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00249/manifest.json", + "parentStatus": "docs/status/M16-GAP-00249.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00250.md", + "tests/golden/M16-GAP-00249/manifest.json", + "docs/status/M16-GAP-00249.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00249", + "parentTask": "M16-GAP-00248", + "status": "done", + "nextTask": "M16-GAP-00250", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00249 Status", + "status: done", + "task: armature.roll_clear operator LOCAL_EXACT slice", + "updated: 2026-08-23 America/New_York", + "scope:", + "- The minimal fixture contains one selected visible edit bone with an initial", + " roll of pi/4. Blender desktop runs `ARMATURE_OT_roll_clear(roll=0)`, clearing", + " only the selected bone's roll while preserving its geometry, selection, and" + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1784, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 446 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2495, + "lines": 47, + "tokens": 624 + }, + { + "path": "docs/tasks/M16-GAP-00250.md", + "bytes": 1784, + "lines": 38, + "tokens": 446 + }, + { + "path": "tests/golden/M16-GAP-00249/manifest.json", + "bytes": 2937, + "lines": 74, + "tokens": 735 + }, + { + "path": "docs/status/M16-GAP-00249.md", + "bytes": 952, + "lines": 26, + "tokens": 238 + } + ], + "sourceTokens": 2043, + "evidenceFiles": 1, + "evidenceBytes": 1429, + "evidenceTokens": 358, + "totalTokens": 2401, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3425, + "serializedContextTokens": 753, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00251/armature-select-hierarchy-desktop-report.json b/tests/golden/M16-GAP-00251/armature-select-hierarchy-desktop-report.json new file mode 100644 index 00000000..3d5fb201 --- /dev/null +++ b/tests/golden/M16-GAP-00251/armature-select-hierarchy-desktop-report.json @@ -0,0 +1,146 @@ +{ + "activeBoneAfter": "WebGapArmatureSelectHierarchyChild", + "activeBoneBefore": "WebGapArmatureSelectHierarchyChild", + "after": { + "activeBone": "WebGapArmatureSelectHierarchyChild", + "armature": "WebGapArmatureSelectHierarchyArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectHierarchyRoot", + "parent": null, + "selectHead": false, + "selectTail": true, + "selected": false, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": true, + "head": [ + 0.0, + 1.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectHierarchyChild", + "parent": "WebGapArmatureSelectHierarchyRoot", + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 2.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectHierarchyOther", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureSelectHierarchyObject" + }, + "before": { + "activeBone": "WebGapArmatureSelectHierarchyChild", + "armature": "WebGapArmatureSelectHierarchyArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectHierarchyRoot", + "parent": null, + "selectHead": false, + "selectTail": true, + "selected": false, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": true, + "head": [ + 0.0, + 1.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectHierarchyChild", + "parent": "WebGapArmatureSelectHierarchyRoot", + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 2.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectHierarchyOther", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureSelectHierarchyObject" + }, + "blenderVersion": "5.2.0 LTS", + "childBone": "WebGapArmatureSelectHierarchyChild", + "direction": "CHILD", + "extend": false, + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00251-operator-armature.select_hierarchy.blend", + "fixtureSha256": "527167dc4d5c40e18196b8b63818373494bf28efd9592ce1ee28b790aecad9c4", + "mainMutation": "IMMEDIATE_CHILD_ALREADY_SELECTED", + "operation": "ARMATURE_SELECT_HIERARCHY_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "poll": true, + "rootBone": "WebGapArmatureSelectHierarchyRoot", + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00251" +} diff --git a/tests/golden/M16-GAP-00251/armature-select-hierarchy-local-exact-report.json b/tests/golden/M16-GAP-00251/armature-select-hierarchy-local-exact-report.json new file mode 100644 index 00000000..8916df25 --- /dev/null +++ b/tests/golden/M16-GAP-00251/armature-select-hierarchy-local-exact-report.json @@ -0,0 +1,68 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00251", + "operation": "ARMATURE_SELECT_HIERARCHY_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00251-operator-armature.select_hierarchy.blend", + "sha256": "527167dc4d5c40e18196b8b63818373494bf28efd9592ce1ee28b790aecad9c4" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00251/armature-select-hierarchy-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "IMMEDIATE_CHILD_ALREADY_SELECTED", + "direction": "CHILD", + "extend": false, + "activeBoneBefore": "WebGapArmatureSelectHierarchyChild", + "activeBoneAfter": "WebGapArmatureSelectHierarchyChild" + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureSelectHierarchyArmature", + "rootBoneId": "bone:armature:WebGapArmatureSelectHierarchyArmature:WebGapArmatureSelectHierarchyRoot", + "childBoneId": "bone:armature:WebGapArmatureSelectHierarchyArmature:WebGapArmatureSelectHierarchyChild", + "otherBoneId": "bone:armature:WebGapArmatureSelectHierarchyArmature:WebGapArmatureSelectHierarchyOther", + "rootSelected": false, + "childSelected": true, + "otherSelected": false, + "childParentId": "bone:armature:WebGapArmatureSelectHierarchyArmature:WebGapArmatureSelectHierarchyRoot", + "childConnected": true, + "rootHead": [ + 0, + 0, + 0 + ], + "rootTail": [ + 0, + 1, + 0 + ], + "childHead": [ + 0, + 1, + 0 + ], + "childTail": [ + 0, + 2, + 0 + ], + "otherHead": [ + 2, + 0, + 0 + ], + "otherTail": [ + 2, + 1, + 0 + ] + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00252" +} diff --git a/tests/golden/M16-GAP-00251/manifest.json b/tests/golden/M16-GAP-00251/manifest.json new file mode 100644 index 00000000..34050d9f --- /dev/null +++ b/tests/golden/M16-GAP-00251/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00251", + "parentTask": "M16-GAP-00250", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_SELECT_HIERARCHY_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00250/manifest.json", + "sha256": "2d4aafbf8effc7327cf16e2e1b040bf56f78af4024745e97f9728d8a0ce5963e" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00251-operator-armature.select_hierarchy.blend", + "sha256": "527167dc4d5c40e18196b8b63818373494bf28efd9592ce1ee28b790aecad9c4" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00251.py", + "sha256": "a6eda558d5ca8f973a6cebaba1160453c6ca5a9dec3b47cb05f89dca31f31d86" + }, + "desktopChecker": { + "path": "tools/web/check-action-armature-select-hierarchy-desktop.py", + "sha256": "f6d261b067815d740a7e39aa8c8a8ae6d605b675c6ba2a144eaab65d104840ae" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "6da2d07715ff0405b6908dd163d1bd868d947665d374741038750f7561c9cf4e" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "9c0af422cc14634979497e2c8585e945a8402ab9f30b182d882da46786a1a711" + }, + "nativeStub": { + "path": "web/engine/web_engine_native_reader_stub.cpp", + "sha256": "2a1526e08cf446bb23a91c8c2ae799db38a0aeed0a809a15ead427780600481a" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "aa26c3b422e79ff84557245dc8d5870125f237aa365ac7ebdc727c2d0b83f615" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "aa26c3b422e79ff84557245dc8d5870125f237aa365ac7ebdc727c2d0b83f615" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "wasmJsPublic": { + "path": "web/app/public/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00251/armature-select-hierarchy-desktop-report.json", + "sha256": "8d57e6ce5bc33f6e87eaba09ffb411bf68b752a4729438de9f78063f7354c092" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00251/armature-select-hierarchy-local-exact-report.json", + "sha256": "4d36c680a2947be8c29e076849d3d4ec8ad2a2c1a2ccf9e7330b311c0d4be5ac" + }, + "status": { + "path": "docs/status/M16-GAP-00251.md", + "sha256": "67e04c31b88c5821592269c0f629dce00cf675bef9bb0879dd78d6818127f92d" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00251/task-context.json", + "sha256": "a8e92d107ef3e012f2d0321a00b7c55c9475848346488de1804645c238618ca5" + } + }, + "nextTask": "M16-GAP-00252" +} diff --git a/tests/golden/M16-GAP-00251/task-context.json b/tests/golden/M16-GAP-00251/task-context.json new file mode 100644 index 00000000..b6e353f0 --- /dev/null +++ b/tests/golden/M16-GAP-00251/task-context.json @@ -0,0 +1,182 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00251", + "parentTask": "M16-GAP-00250", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.select_hierarchy data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.select_hierarchy", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00251.py -- tests/files/web/generated/M16-GAP-00251-operator-armature.select_hierarchy.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00251", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00251" + ], + "inputPaths": [], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1712, + "contextRemainingTokens": 426 + }, + "source": { + "bytes": 8192, + "tokens": 2050 + }, + "selected": [], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00251-operator-armature.select_hierarchy.blend", + "bytes": 86367, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/generated/M16-GAP-00251.py", + "bytes": 1737, + "reason": "CONTEXT_REMAINING_SPACE" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 240371, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 728950, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00251/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00251.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00251/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 0, + "bytes": 0, + "tokens": 0 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00252", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00251.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00250/manifest.json", + "parentStatus": "docs/status/M16-GAP-00250.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00251.md", + "tests/golden/M16-GAP-00250/manifest.json", + "docs/status/M16-GAP-00250.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00250", + "parentTask": "M16-GAP-00249", + "status": "done", + "nextTask": "M16-GAP-00251", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00250 Status", + "status: done", + "task: armature.select_all operator LOCAL_EXACT slice", + "updated: 2026-08-23 America/New_York", + "scope:", + "- The minimal fixture contains two visible edit bones with only the parent bone", + " initially selected. Blender desktop runs `ARMATURE_OT_select_all(action=SELECT)`,", + " selecting both visible bones and both endpoints while preserving geometry." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1814, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 454 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2495, + "lines": 47, + "tokens": 624 + }, + { + "path": "docs/tasks/M16-GAP-00251.md", + "bytes": 1814, + "lines": 38, + "tokens": 454 + }, + { + "path": "tests/golden/M16-GAP-00250/manifest.json", + "bytes": 2937, + "lines": 74, + "tokens": 735 + }, + { + "path": "docs/status/M16-GAP-00250.md", + "bytes": 946, + "lines": 25, + "tokens": 237 + } + ], + "sourceTokens": 2050, + "evidenceFiles": 0, + "evidenceBytes": 0, + "evidenceTokens": 0, + "totalTokens": 2050, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3074, + "serializedContextTokens": 722, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00252/armature-select-less-desktop-report.json b/tests/golden/M16-GAP-00252/armature-select-less-desktop-report.json new file mode 100644 index 00000000..c24ee248 --- /dev/null +++ b/tests/golden/M16-GAP-00252/armature-select-less-desktop-report.json @@ -0,0 +1,144 @@ +{ + "activeBone": "WebGapArmatureSelectLessRoot", + "after": { + "activeBone": "WebGapArmatureSelectLessRoot", + "armature": "WebGapArmatureSelectLessArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectLessRoot", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": true, + "head": [ + 0.0, + 1.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectLessChild", + "parent": "WebGapArmatureSelectLessRoot", + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 0.0, + 2.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectLessOther", + "parent": null, + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureSelectLessObject" + }, + "before": { + "activeBone": "WebGapArmatureSelectLessRoot", + "armature": "WebGapArmatureSelectLessArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectLessRoot", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": true, + "head": [ + 0.0, + 1.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectLessChild", + "parent": "WebGapArmatureSelectLessRoot", + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 0.0, + 2.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectLessOther", + "parent": null, + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureSelectLessObject" + }, + "blenderVersion": "5.2.0 LTS", + "childBone": "WebGapArmatureSelectLessChild", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00252-operator-armature.select_less.blend", + "fixtureSha256": "6c10d6a2bfb01565d415740efcb5366433cf1ddc722392605530769e6a8f729b", + "mainMutation": "PARTIAL_BOUNDARY_SELECTION_ALREADY_CLEARED", + "operation": "ARMATURE_SELECT_LESS_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "otherBone": "WebGapArmatureSelectLessOther", + "poll": true, + "rootBone": "WebGapArmatureSelectLessRoot", + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00252" +} diff --git a/tests/golden/M16-GAP-00252/armature-select-less-local-exact-report.json b/tests/golden/M16-GAP-00252/armature-select-less-local-exact-report.json new file mode 100644 index 00000000..e8b4ef83 --- /dev/null +++ b/tests/golden/M16-GAP-00252/armature-select-less-local-exact-report.json @@ -0,0 +1,67 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00252", + "operation": "ARMATURE_SELECT_LESS_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00252-operator-armature.select_less.blend", + "sha256": "6c10d6a2bfb01565d415740efcb5366433cf1ddc722392605530769e6a8f729b" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00252/armature-select-less-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "PARTIAL_BOUNDARY_SELECTION_ALREADY_CLEARED", + "rootBone": "WebGapArmatureSelectLessRoot", + "childBone": "WebGapArmatureSelectLessChild", + "otherBone": "WebGapArmatureSelectLessOther" + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureSelectLessArmature", + "rootBoneId": "bone:armature:WebGapArmatureSelectLessArmature:WebGapArmatureSelectLessRoot", + "childBoneId": "bone:armature:WebGapArmatureSelectLessArmature:WebGapArmatureSelectLessChild", + "otherBoneId": "bone:armature:WebGapArmatureSelectLessArmature:WebGapArmatureSelectLessOther", + "rootSelected": false, + "childSelected": false, + "otherSelected": true, + "childParentId": "bone:armature:WebGapArmatureSelectLessArmature:WebGapArmatureSelectLessRoot", + "childConnected": true, + "rootHead": [ + 0, + 0, + 0 + ], + "rootTail": [ + 0, + 1, + 0 + ], + "childHead": [ + 0, + 1, + 0 + ], + "childTail": [ + 0, + 2, + 0 + ], + "otherHead": [ + 2, + 0, + 0 + ], + "otherTail": [ + 2, + 1, + 0 + ] + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00253" +} diff --git a/tests/golden/M16-GAP-00252/manifest.json b/tests/golden/M16-GAP-00252/manifest.json new file mode 100644 index 00000000..410c7b76 --- /dev/null +++ b/tests/golden/M16-GAP-00252/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00252", + "parentTask": "M16-GAP-00251", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_SELECT_LESS_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": { + "path": "tests/golden/M16-GAP-00251/manifest.json", + "sha256": "680d7d2fa6bda6d45226f71d1e1ee8986583c20e38c4ac5306625179d070bab7" + }, + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00252-operator-armature.select_less.blend", + "sha256": "6c10d6a2bfb01565d415740efcb5366433cf1ddc722392605530769e6a8f729b" + }, + "generator": { + "path": "tools/web/generated/M16-GAP-00252.py", + "sha256": "8d394493b9b2a43fe98a666d6eaef5f1facf699d5063ba82a8b3ff461037715f" + }, + "desktopChecker": { + "path": "tools/web/check-action-armature-select-less-desktop.py", + "sha256": "ebe6ff995d37310dd1f726246e0c3627960b75c6b506b181286742829ec4423b" + }, + "webChecker": { + "path": "tools/web/check-generated-gap.mjs", + "sha256": "939a88c043aa3c6252384cfe14eddaa4dd01da2b2bfa3e2d413f1e4237eb4423" + }, + "reader": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "9c0af422cc14634979497e2c8585e945a8402ab9f30b182d882da46786a1a711" + }, + "nativeStub": { + "path": "web/engine/web_engine_native_reader_stub.cpp", + "sha256": "2a1526e08cf446bb23a91c8c2ae799db38a0aeed0a809a15ead427780600481a" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "aa26c3b422e79ff84557245dc8d5870125f237aa365ac7ebdc727c2d0b83f615" + }, + "wasmPublic": { + "path": "web/app/public/vendor/blender/web_engine.wasm", + "sha256": "aa26c3b422e79ff84557245dc8d5870125f237aa365ac7ebdc727c2d0b83f615" + }, + "wasmJs": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "wasmJsPublic": { + "path": "web/app/public/vendor/blender/web_engine.js", + "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35" + }, + "desktopReport": { + "path": "tests/golden/M16-GAP-00252/armature-select-less-desktop-report.json", + "sha256": "a7cb4e98fbf96079ef88c8de7491a43e611e1c759525d7bffdef785cadf458f7" + }, + "webReport": { + "path": "tests/golden/M16-GAP-00252/armature-select-less-local-exact-report.json", + "sha256": "5e9743ec56f672990fca63850abe1abd567c6c0488926be44a00dd6295b96c39" + }, + "status": { + "path": "docs/status/M16-GAP-00252.md", + "sha256": "3a8cf46d4f0b5efae6dfbdef3ef8ce808dd603d3a80146b15f0b2f95dabfa302" + }, + "taskContext": { + "path": "tests/golden/M16-GAP-00252/task-context.json", + "sha256": "ea27cc467ccdccd6292bd5e76f1ecbabfe0ddcbb553335684b8512ff207db7a2" + } + }, + "nextTask": "M16-GAP-00253" +} diff --git a/tests/golden/M16-GAP-00252/task-context.json b/tests/golden/M16-GAP-00252/task-context.json new file mode 100644 index 00000000..c01ddf5d --- /dev/null +++ b/tests/golden/M16-GAP-00252/task-context.json @@ -0,0 +1,182 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00252", + "parentTask": "M16-GAP-00251", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.select_less data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.select_less", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00252.py -- tests/files/web/generated/M16-GAP-00252-operator-armature.select_less.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00252", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00252" + ], + "inputPaths": [], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1583, + "contextRemainingTokens": 394 + }, + "source": { + "bytes": 8321, + "tokens": 2082 + }, + "selected": [], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00252-operator-armature.select_less.blend", + "bytes": 86377, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/generated/M16-GAP-00252.py", + "bytes": 1711, + "reason": "CONTEXT_REMAINING_SPACE" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 240371, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 735564, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00252/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00252.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00252/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 0, + "bytes": 0, + "tokens": 0 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00253", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00252.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00251/manifest.json", + "parentStatus": "docs/status/M16-GAP-00251.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00252.md", + "tests/golden/M16-GAP-00251/manifest.json", + "docs/status/M16-GAP-00251.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00251", + "parentTask": "M16-GAP-00250", + "status": "done", + "nextTask": "M16-GAP-00252", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00251 Status", + "status: done", + "task: armature.select_hierarchy operator LOCAL_EXACT slice", + "updated: 2026-08-23 America/New_York", + "scope:", + "- The minimal fixture contains a selected root, an unselected connected child,", + " and an independent unselected bone. Blender desktop runs", + " `ARMATURE_OT_select_hierarchy(direction=CHILD, extend=false)`, selecting the" + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1789, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 448 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2495, + "lines": 47, + "tokens": 624 + }, + { + "path": "docs/tasks/M16-GAP-00252.md", + "bytes": 1789, + "lines": 38, + "tokens": 448 + }, + { + "path": "tests/golden/M16-GAP-00251/manifest.json", + "bytes": 2967, + "lines": 74, + "tokens": 742 + }, + { + "path": "docs/status/M16-GAP-00251.md", + "bytes": 1070, + "lines": 28, + "tokens": 268 + } + ], + "sourceTokens": 2082, + "evidenceFiles": 0, + "evidenceBytes": 0, + "evidenceTokens": 0, + "totalTokens": 2082, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3106, + "serializedContextTokens": 719, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00253/armature-select-linked-desktop-report.json b/tests/golden/M16-GAP-00253/armature-select-linked-desktop-report.json new file mode 100644 index 00000000..66fc9d49 --- /dev/null +++ b/tests/golden/M16-GAP-00253/armature-select-linked-desktop-report.json @@ -0,0 +1,185 @@ +{ + "after": { + "activeBone": "WebGapArmatureSelectLinkedRoot", + "armature": "WebGapArmatureSelectLinkedArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectLinkedRoot", + "parent": null, + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": true, + "head": [ + 0.0, + 1.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectLinkedChild", + "parent": "WebGapArmatureSelectLinkedRoot", + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 2.0, + 0.0 + ] + }, + { + "connected": true, + "head": [ + 0.0, + 2.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectLinkedGrandchild", + "parent": "WebGapArmatureSelectLinkedChild", + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 3.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectLinkedOther", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureSelectLinkedObject" + }, + "allForks": false, + "before": { + "activeBone": "WebGapArmatureSelectLinkedRoot", + "armature": "WebGapArmatureSelectLinkedArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectLinkedRoot", + "parent": null, + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": true, + "head": [ + 0.0, + 1.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectLinkedChild", + "parent": "WebGapArmatureSelectLinkedRoot", + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 2.0, + 0.0 + ] + }, + { + "connected": true, + "head": [ + 0.0, + 2.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectLinkedGrandchild", + "parent": "WebGapArmatureSelectLinkedChild", + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 3.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectLinkedOther", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureSelectLinkedObject" + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00253-operator-armature.select_linked.blend", + "fixtureSha256": "dfc4b49ad0c1165e771368b99c7cf589890586ea4f6b142aa319a42ad9390316", + "mainMutation": "LINKED_CHAIN_ALREADY_SELECTED", + "operation": "ARMATURE_SELECT_LINKED_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "selectedChain": [ + "WebGapArmatureSelectLinkedRoot", + "WebGapArmatureSelectLinkedChild", + "WebGapArmatureSelectLinkedGrandchild" + ], + "task": "M16-GAP-00253", + "unselectedBone": "WebGapArmatureSelectLinkedOther" +} diff --git a/tests/golden/M16-GAP-00253/armature-select-linked-local-exact-report.json b/tests/golden/M16-GAP-00253/armature-select-linked-local-exact-report.json new file mode 100644 index 00000000..cd327542 --- /dev/null +++ b/tests/golden/M16-GAP-00253/armature-select-linked-local-exact-report.json @@ -0,0 +1,43 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00253", + "operation": "ARMATURE_SELECT_LINKED_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00253-operator-armature.select_linked.blend", + "sha256": "dfc4b49ad0c1165e771368b99c7cf589890586ea4f6b142aa319a42ad9390316" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00253/armature-select-linked-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "LINKED_CHAIN_ALREADY_SELECTED", + "selectedChain": [ + "WebGapArmatureSelectLinkedRoot", + "WebGapArmatureSelectLinkedChild", + "WebGapArmatureSelectLinkedGrandchild" + ], + "unselectedBone": "WebGapArmatureSelectLinkedOther", + "allForks": false + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureSelectLinkedArmature", + "rootBoneId": "bone:armature:WebGapArmatureSelectLinkedArmature:WebGapArmatureSelectLinkedRoot", + "childBoneId": "bone:armature:WebGapArmatureSelectLinkedArmature:WebGapArmatureSelectLinkedChild", + "grandchildBoneId": "bone:armature:WebGapArmatureSelectLinkedArmature:WebGapArmatureSelectLinkedGrandchild", + "otherBoneId": "bone:armature:WebGapArmatureSelectLinkedArmature:WebGapArmatureSelectLinkedOther", + "rootSelected": true, + "childSelected": true, + "grandchildSelected": true, + "otherSelected": false, + "childParentId": "bone:armature:WebGapArmatureSelectLinkedArmature:WebGapArmatureSelectLinkedRoot", + "grandchildParentId": "bone:armature:WebGapArmatureSelectLinkedArmature:WebGapArmatureSelectLinkedChild" + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00254" +} diff --git a/tests/golden/M16-GAP-00253/manifest.json b/tests/golden/M16-GAP-00253/manifest.json new file mode 100644 index 00000000..19b1bea9 --- /dev/null +++ b/tests/golden/M16-GAP-00253/manifest.json @@ -0,0 +1,28 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00253", + "parentTask": "M16-GAP-00252", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_SELECT_LINKED_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": {"path": "tests/golden/M16-GAP-00252/manifest.json", "sha256": "c7abf03119f5557abd6c19d76ae0d1bde2946d034095046eb69d0f76cf4c8cbf"}, + "fixture": {"path": "tests/files/web/generated/M16-GAP-00253-operator-armature.select_linked.blend", "sha256": "dfc4b49ad0c1165e771368b99c7cf589890586ea4f6b142aa319a42ad9390316"}, + "generator": {"path": "tools/web/generated/M16-GAP-00253.py", "sha256": "d64e0a3681f8501775ecb6fafafec3fba567b42c10fbcda3507624560ddb05fa"}, + "desktopChecker": {"path": "tools/web/check-action-armature-select-linked-desktop.py", "sha256": "99901e2c2a744563c9fff9105244cd07368b6ed0cc52c6c1c94eb65c3e964ac5"}, + "webChecker": {"path": "tools/web/check-generated-gap.mjs", "sha256": "9b03d502ca9ef28f88c595b0d7fdd9d29c44288c7c5d7b2dc1bf8273dd19cde9"}, + "reader": {"path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "9c0af422cc14634979497e2c8585e945a8402ab9f30b182d882da46786a1a711"}, + "nativeStub": {"path": "web/engine/web_engine_native_reader_stub.cpp", "sha256": "2a1526e08cf446bb23a91c8c2ae799db38a0aeed0a809a15ead427780600481a"}, + "wasm": {"path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "aa26c3b422e79ff84557245dc8d5870125f237aa365ac7ebdc727c2d0b83f615"}, + "wasmPublic": {"path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "aa26c3b422e79ff84557245dc8d5870125f237aa365ac7ebdc727c2d0b83f615"}, + "wasmJs": {"path": "web/app/src/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "wasmJsPublic": {"path": "web/app/public/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "desktopReport": {"path": "tests/golden/M16-GAP-00253/armature-select-linked-desktop-report.json", "sha256": "3a2b4e82aeaa2fdea3ae01df802c8de371f184dc0b018cc1c16d2349d19b9fa3"}, + "webReport": {"path": "tests/golden/M16-GAP-00253/armature-select-linked-local-exact-report.json", "sha256": "d184c248dd13878698f5b973331bbe7d65cde2defa697f22e4c05df9a433b42a"}, + "status": {"path": "docs/status/M16-GAP-00253.md", "sha256": "e6627177fb89e16a7c18efddf495d46e01a0d1d70d14f324813a05dc5c9fdb6f"}, + "taskContext": {"path": "tests/golden/M16-GAP-00253/task-context.json", "sha256": "94c2ded148413fd67032d63cdcdcdf5b332cd99569b02804e3a743471fb3cda9"} + }, + "nextTask": "M16-GAP-00254" +} diff --git a/tests/golden/M16-GAP-00253/task-context.json b/tests/golden/M16-GAP-00253/task-context.json new file mode 100644 index 00000000..23094df7 --- /dev/null +++ b/tests/golden/M16-GAP-00253/task-context.json @@ -0,0 +1,182 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00253", + "parentTask": "M16-GAP-00252", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.select_linked data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.select_linked", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00253.py -- tests/files/web/generated/M16-GAP-00253-operator-armature.select_linked.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00253", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00253" + ], + "inputPaths": [], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1748, + "contextRemainingTokens": 436 + }, + "source": { + "bytes": 8156, + "tokens": 2040 + }, + "selected": [], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00253-operator-armature.select_linked.blend", + "bytes": 86468, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/generated/M16-GAP-00253.py", + "bytes": 2077, + "reason": "CONTEXT_REMAINING_SPACE" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 240371, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 742256, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00253/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00253.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00253/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 0, + "bytes": 0, + "tokens": 0 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00254", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00253.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00252/manifest.json", + "parentStatus": "docs/status/M16-GAP-00252.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00253.md", + "tests/golden/M16-GAP-00252/manifest.json", + "docs/status/M16-GAP-00252.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00252", + "parentTask": "M16-GAP-00251", + "status": "done", + "nextTask": "M16-GAP-00253", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00252 Status", + "status: done", + "task: armature.select_less operator LOCAL_EXACT slice", + "updated: 2026-08-23 America/New_York", + "scope:", + "- The minimal fixture contains a partially selected root boundary, an", + " unselected connected child, and an independent fully selected bone. Blender", + " desktop runs `ARMATURE_OT_select_less`, clearing the partial boundary while" + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1799, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 450 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2495, + "lines": 47, + "tokens": 624 + }, + { + "path": "docs/tasks/M16-GAP-00253.md", + "bytes": 1799, + "lines": 38, + "tokens": 450 + }, + { + "path": "tests/golden/M16-GAP-00252/manifest.json", + "bytes": 2942, + "lines": 74, + "tokens": 736 + }, + { + "path": "docs/status/M16-GAP-00252.md", + "bytes": 920, + "lines": 26, + "tokens": 230 + } + ], + "sourceTokens": 2040, + "evidenceFiles": 0, + "evidenceBytes": 0, + "evidenceTokens": 0, + "totalTokens": 2040, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3064, + "serializedContextTokens": 720, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00254/armature-select-linked-pick-desktop-report.json b/tests/golden/M16-GAP-00254/armature-select-linked-pick-desktop-report.json new file mode 100644 index 00000000..a2611866 --- /dev/null +++ b/tests/golden/M16-GAP-00254/armature-select-linked-pick-desktop-report.json @@ -0,0 +1,187 @@ +{ + "after": { + "activeBone": "WebGapArmatureSelectLinkedPickRoot", + "armature": "WebGapArmatureSelectLinkedPickArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectLinkedPickRoot", + "parent": null, + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": true, + "head": [ + 0.0, + 1.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectLinkedPickChild", + "parent": "WebGapArmatureSelectLinkedPickRoot", + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 2.0, + 0.0 + ] + }, + { + "connected": true, + "head": [ + 0.0, + 2.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectLinkedPickGrandchild", + "parent": "WebGapArmatureSelectLinkedPickChild", + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 3.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectLinkedPickOther", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureSelectLinkedPickObject" + }, + "allForks": false, + "before": { + "activeBone": "WebGapArmatureSelectLinkedPickRoot", + "armature": "WebGapArmatureSelectLinkedPickArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectLinkedPickRoot", + "parent": null, + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": true, + "head": [ + 0.0, + 1.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectLinkedPickChild", + "parent": "WebGapArmatureSelectLinkedPickRoot", + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 2.0, + 0.0 + ] + }, + { + "connected": true, + "head": [ + 0.0, + 2.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectLinkedPickGrandchild", + "parent": "WebGapArmatureSelectLinkedPickChild", + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 3.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectLinkedPickOther", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureSelectLinkedPickObject" + }, + "blenderVersion": "5.2.0 LTS", + "deselect": false, + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00254-operator-armature.select_linked_pick.blend", + "fixtureSha256": "10e4053f9aea2a2cad6314e3ab4d981db9bc4281933c1172ad77247f4c6500fd", + "mainMutation": "PICKED_LINKED_CHAIN_ALREADY_SELECTED", + "operation": "ARMATURE_SELECT_LINKED_PICK_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "pickedBone": "WebGapArmatureSelectLinkedPickRoot", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "selectedChain": [ + "WebGapArmatureSelectLinkedPickRoot", + "WebGapArmatureSelectLinkedPickChild", + "WebGapArmatureSelectLinkedPickGrandchild" + ], + "task": "M16-GAP-00254", + "unselectedBone": "WebGapArmatureSelectLinkedPickOther" +} diff --git a/tests/golden/M16-GAP-00254/armature-select-linked-pick-local-exact-report.json b/tests/golden/M16-GAP-00254/armature-select-linked-pick-local-exact-report.json new file mode 100644 index 00000000..16da488c --- /dev/null +++ b/tests/golden/M16-GAP-00254/armature-select-linked-pick-local-exact-report.json @@ -0,0 +1,45 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00254", + "operation": "ARMATURE_SELECT_LINKED_PICK_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00254-operator-armature.select_linked_pick.blend", + "sha256": "10e4053f9aea2a2cad6314e3ab4d981db9bc4281933c1172ad77247f4c6500fd" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00254/armature-select-linked-pick-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "PICKED_LINKED_CHAIN_ALREADY_SELECTED", + "pickedBone": "WebGapArmatureSelectLinkedPickRoot", + "selectedChain": [ + "WebGapArmatureSelectLinkedPickRoot", + "WebGapArmatureSelectLinkedPickChild", + "WebGapArmatureSelectLinkedPickGrandchild" + ], + "unselectedBone": "WebGapArmatureSelectLinkedPickOther", + "deselect": false, + "allForks": false + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureSelectLinkedPickArmature", + "rootBoneId": "bone:armature:WebGapArmatureSelectLinkedPickArmature:WebGapArmatureSelectLinkedPickRoot", + "childBoneId": "bone:armature:WebGapArmatureSelectLinkedPickArmature:WebGapArmatureSelectLinkedPickChild", + "grandchildBoneId": "bone:armature:WebGapArmatureSelectLinkedPickArmature:WebGapArmatureSelectLinkedPickGrandchild", + "otherBoneId": "bone:armature:WebGapArmatureSelectLinkedPickArmature:WebGapArmatureSelectLinkedPickOther", + "rootSelected": true, + "childSelected": true, + "grandchildSelected": true, + "otherSelected": false, + "childParentId": "bone:armature:WebGapArmatureSelectLinkedPickArmature:WebGapArmatureSelectLinkedPickRoot", + "grandchildParentId": "bone:armature:WebGapArmatureSelectLinkedPickArmature:WebGapArmatureSelectLinkedPickChild" + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00255" +} diff --git a/tests/golden/M16-GAP-00254/manifest.json b/tests/golden/M16-GAP-00254/manifest.json new file mode 100644 index 00000000..1781dcbf --- /dev/null +++ b/tests/golden/M16-GAP-00254/manifest.json @@ -0,0 +1,28 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00254", + "parentTask": "M16-GAP-00253", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_SELECT_LINKED_PICK_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": {"path": "tests/golden/M16-GAP-00253/manifest.json", "sha256": "c18022062e68fc4ddaee81a39b6dc766253f0e1c36f2e5d81941935e3783669b"}, + "fixture": {"path": "tests/files/web/generated/M16-GAP-00254-operator-armature.select_linked_pick.blend", "sha256": "10e4053f9aea2a2cad6314e3ab4d981db9bc4281933c1172ad77247f4c6500fd"}, + "generator": {"path": "tools/web/generated/M16-GAP-00254.py", "sha256": "f08a4362f6bfbbdd8eeeac7e9961613f21450b64fcf5138fd2674515c97229af"}, + "desktopChecker": {"path": "tools/web/check-action-armature-select-linked-pick-desktop.py", "sha256": "8909666d24df353cf64f225b857a1ccc48c460320df52e385f69c8e13200d686"}, + "webChecker": {"path": "tools/web/check-generated-gap.mjs", "sha256": "432e513cde8bdbcb28a1adf66ff410497d8a0425592bc5e2326d25dbea488d78"}, + "reader": {"path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "9c0af422cc14634979497e2c8585e945a8402ab9f30b182d882da46786a1a711"}, + "nativeStub": {"path": "web/engine/web_engine_native_reader_stub.cpp", "sha256": "2a1526e08cf446bb23a91c8c2ae799db38a0aeed0a809a15ead427780600481a"}, + "wasm": {"path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "aa26c3b422e79ff84557245dc8d5870125f237aa365ac7ebdc727c2d0b83f615"}, + "wasmPublic": {"path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "aa26c3b422e79ff84557245dc8d5870125f237aa365ac7ebdc727c2d0b83f615"}, + "wasmJs": {"path": "web/app/src/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "wasmJsPublic": {"path": "web/app/public/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "desktopReport": {"path": "tests/golden/M16-GAP-00254/armature-select-linked-pick-desktop-report.json", "sha256": "1338c391ecabbb35166c5df8e36a8a0f5b65deca3994f7c2ee1d799b564906d0"}, + "webReport": {"path": "tests/golden/M16-GAP-00254/armature-select-linked-pick-local-exact-report.json", "sha256": "14560b0b43aa917fa31fe8c9023992285313204c858d7260da22347a8696b9bb"}, + "status": {"path": "docs/status/M16-GAP-00254.md", "sha256": "711b0fb2e6dbbc12a25d1c5ad19ea3a3085d9b7fbfac45ef633735053479dc19"}, + "taskContext": {"path": "tests/golden/M16-GAP-00254/task-context.json", "sha256": "dc292fe37486b022284f46739ad523b5a6ee406157a325aa855411ee3e24c3f6"} + }, + "nextTask": "M16-GAP-00255" +} diff --git a/tests/golden/M16-GAP-00254/task-context.json b/tests/golden/M16-GAP-00254/task-context.json new file mode 100644 index 00000000..0645fa16 --- /dev/null +++ b/tests/golden/M16-GAP-00254/task-context.json @@ -0,0 +1,182 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00254", + "parentTask": "M16-GAP-00253", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.select_linked_pick data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.select_linked_pick", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00254.py -- tests/files/web/generated/M16-GAP-00254-operator-armature.select_linked_pick.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00254", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00254" + ], + "inputPaths": [], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1997, + "contextRemainingTokens": 498 + }, + "source": { + "bytes": 7907, + "tokens": 1978 + }, + "selected": [], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00254-operator-armature.select_linked_pick.blend", + "bytes": 86478, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/generated/M16-GAP-00254.py", + "bytes": 2037, + "reason": "CONTEXT_REMAINING_SPACE" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 240371, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 747407, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00254/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00254.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00254/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 0, + "bytes": 0, + "tokens": 0 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00255", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00254.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00253/manifest.json", + "parentStatus": "docs/status/M16-GAP-00253.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00254.md", + "tests/golden/M16-GAP-00253/manifest.json", + "docs/status/M16-GAP-00253.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00253", + "parentTask": "M16-GAP-00252", + "status": "done", + "nextTask": "M16-GAP-00254", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00253 Status", + "status: done", + "task: armature.select_linked operator LOCAL_EXACT slice", + "updated: 2026-08-23 America/New_York", + "scope:", + "- The minimal fixture contains a selected root, two unselected connected", + " descendants, and an independent unselected bone. Blender desktop runs", + " `ARMATURE_OT_select_linked(all_forks=false)`, selecting the linked chain while" + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1824, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 456 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2495, + "lines": 47, + "tokens": 624 + }, + { + "path": "docs/tasks/M16-GAP-00254.md", + "bytes": 1824, + "lines": 38, + "tokens": 456 + }, + { + "path": "tests/golden/M16-GAP-00253/manifest.json", + "bytes": 2682, + "lines": 29, + "tokens": 671 + }, + { + "path": "docs/status/M16-GAP-00253.md", + "bytes": 906, + "lines": 25, + "tokens": 227 + } + ], + "sourceTokens": 1978, + "evidenceFiles": 0, + "evidenceBytes": 0, + "evidenceTokens": 0, + "totalTokens": 1978, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3002, + "serializedContextTokens": 724, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00255/armature-select-mirror-desktop-report.json b/tests/golden/M16-GAP-00255/armature-select-mirror-desktop-report.json new file mode 100644 index 00000000..652f2e75 --- /dev/null +++ b/tests/golden/M16-GAP-00255/armature-select-mirror-desktop-report.json @@ -0,0 +1,145 @@ +{ + "after": { + "activeBone": "WebGapSelectMirror.R", + "armature": "WebGapArmatureSelectMirrorArmature", + "bones": [ + { + "connected": false, + "head": [ + -2.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapSelectMirror.L", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + -2.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapSelectMirror.R", + "parent": null, + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapSelectMirrorCenter", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureSelectMirrorObject" + }, + "before": { + "activeBone": "WebGapSelectMirror.R", + "armature": "WebGapArmatureSelectMirrorArmature", + "bones": [ + { + "connected": false, + "head": [ + -2.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapSelectMirror.L", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + -2.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapSelectMirror.R", + "parent": null, + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapSelectMirrorCenter", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureSelectMirrorObject" + }, + "blenderVersion": "5.2.0 LTS", + "centerBone": "WebGapSelectMirrorCenter", + "extend": false, + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00255-operator-armature.select_mirror.blend", + "fixtureSha256": "af187a9ffb0c6b8f422fd0da0896699dcde8209c8d5d6fbf807ba72cc4a64abb", + "leftBone": "WebGapSelectMirror.L", + "mainMutation": "MIRROR_SELECTION_ALREADY_APPLIED", + "onlyActive": false, + "operation": "ARMATURE_SELECT_MIRROR_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "poll": true, + "rightBone": "WebGapSelectMirror.R", + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00255" +} diff --git a/tests/golden/M16-GAP-00255/armature-select-mirror-local-exact-report.json b/tests/golden/M16-GAP-00255/armature-select-mirror-local-exact-report.json new file mode 100644 index 00000000..9671f49e --- /dev/null +++ b/tests/golden/M16-GAP-00255/armature-select-mirror-local-exact-report.json @@ -0,0 +1,47 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00255", + "operation": "ARMATURE_SELECT_MIRROR_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00255-operator-armature.select_mirror.blend", + "sha256": "af187a9ffb0c6b8f422fd0da0896699dcde8209c8d5d6fbf807ba72cc4a64abb" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00255/armature-select-mirror-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "MIRROR_SELECTION_ALREADY_APPLIED", + "leftBone": "WebGapSelectMirror.L", + "rightBone": "WebGapSelectMirror.R", + "centerBone": "WebGapSelectMirrorCenter", + "onlyActive": false, + "extend": false + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureSelectMirrorArmature", + "leftBoneId": "bone:armature:WebGapArmatureSelectMirrorArmature:WebGapSelectMirror.L", + "rightBoneId": "bone:armature:WebGapArmatureSelectMirrorArmature:WebGapSelectMirror.R", + "centerBoneId": "bone:armature:WebGapArmatureSelectMirrorArmature:WebGapSelectMirrorCenter", + "leftSelected": false, + "rightSelected": true, + "centerSelected": false, + "leftHead": [ + -2, + 0, + 0 + ], + "rightHead": [ + 2, + 0, + 0 + ] + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00256" +} diff --git a/tests/golden/M16-GAP-00255/manifest.json b/tests/golden/M16-GAP-00255/manifest.json new file mode 100644 index 00000000..2bb6dfec --- /dev/null +++ b/tests/golden/M16-GAP-00255/manifest.json @@ -0,0 +1,28 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00255", + "parentTask": "M16-GAP-00254", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_SELECT_MIRROR_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": {"path": "tests/golden/M16-GAP-00254/manifest.json", "sha256": "886c93f9af231c7ce040524d31758c41d38fa377d00da2056d5a299a18034f0a"}, + "fixture": {"path": "tests/files/web/generated/M16-GAP-00255-operator-armature.select_mirror.blend", "sha256": "af187a9ffb0c6b8f422fd0da0896699dcde8209c8d5d6fbf807ba72cc4a64abb"}, + "generator": {"path": "tools/web/generated/M16-GAP-00255.py", "sha256": "19e723cd74e3e0adad28ed2feaec157ae4725f88e4863457c91ab0b9aac4ade3"}, + "desktopChecker": {"path": "tools/web/check-action-armature-select-mirror-desktop.py", "sha256": "21a152a785b6bdb794c6488685cdebf3ce27c3573b3f46e38002c8be0bd0fc43"}, + "webChecker": {"path": "tools/web/check-generated-gap.mjs", "sha256": "a3b541b0e24e13be55fc45baf19c193f49b1a273a1ae926cc200c9638e89a5d0"}, + "reader": {"path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "9c0af422cc14634979497e2c8585e945a8402ab9f30b182d882da46786a1a711"}, + "nativeStub": {"path": "web/engine/web_engine_native_reader_stub.cpp", "sha256": "2a1526e08cf446bb23a91c8c2ae799db38a0aeed0a809a15ead427780600481a"}, + "wasm": {"path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "aa26c3b422e79ff84557245dc8d5870125f237aa365ac7ebdc727c2d0b83f615"}, + "wasmPublic": {"path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "aa26c3b422e79ff84557245dc8d5870125f237aa365ac7ebdc727c2d0b83f615"}, + "wasmJs": {"path": "web/app/src/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "wasmJsPublic": {"path": "web/app/public/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "desktopReport": {"path": "tests/golden/M16-GAP-00255/armature-select-mirror-desktop-report.json", "sha256": "d5b76fb51060be4e1b56e81d238d74df4556b09ceae84dcb0f9c545dfa1bf35f"}, + "webReport": {"path": "tests/golden/M16-GAP-00255/armature-select-mirror-local-exact-report.json", "sha256": "e87ab4016b6ef049c7ed7177d9dee54d44dbcb88d5bbab6f0dbefddadce6b48c"}, + "status": {"path": "docs/status/M16-GAP-00255.md", "sha256": "0dba82e5720f86c24fc442bb14472d1f2a14929df2652566d0b0bf0db7ef101b"}, + "taskContext": {"path": "tests/golden/M16-GAP-00255/task-context.json", "sha256": "1072a60c75f9ba38bbef954deeda027e2906ce86485b94b7a0315409aabd682a"} + }, + "nextTask": "M16-GAP-00256" +} diff --git a/tests/golden/M16-GAP-00255/task-context.json b/tests/golden/M16-GAP-00255/task-context.json new file mode 100644 index 00000000..20128c5f --- /dev/null +++ b/tests/golden/M16-GAP-00255/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00255", + "parentTask": "M16-GAP-00254", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.select_mirror data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.select_mirror", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00255.py -- tests/files/web/generated/M16-GAP-00255-operator-armature.select_mirror.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00255", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00255" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00255.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1977, + "contextRemainingTokens": 493 + }, + "source": { + "bytes": 7927, + "tokens": 1983 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00255.py", + "bytes": 1596, + "tokens": 399 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00255-operator-armature.select_mirror.blend", + "bytes": 86324, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 240371, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 751983, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00255/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00255.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00255/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1596, + "tokens": 399 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00256", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00255.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00254/manifest.json", + "parentStatus": "docs/status/M16-GAP-00254.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00255.md", + "tests/golden/M16-GAP-00254/manifest.json", + "docs/status/M16-GAP-00254.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00254", + "parentTask": "M16-GAP-00253", + "status": "done", + "nextTask": "M16-GAP-00255", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00254 Status", + "status: done", + "task: armature.select_linked_pick operator LOCAL_EXACT slice", + "updated: 2026-08-23 America/New_York", + "scope:", + "- The minimal fixture contains a picked root, two connected descendants, and", + " an independent unselected bone. Desktop evidence exercises the shared linked", + " selection path with `deselect=false` and `all_forks=false`, selecting only the" + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1799, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 450 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2495, + "lines": 47, + "tokens": 624 + }, + { + "path": "docs/tasks/M16-GAP-00255.md", + "bytes": 1799, + "lines": 38, + "tokens": 450 + }, + { + "path": "tests/golden/M16-GAP-00254/manifest.json", + "bytes": 2707, + "lines": 29, + "tokens": 677 + }, + { + "path": "docs/status/M16-GAP-00254.md", + "bytes": 926, + "lines": 25, + "tokens": 232 + } + ], + "sourceTokens": 1983, + "evidenceFiles": 1, + "evidenceBytes": 1596, + "evidenceTokens": 399, + "totalTokens": 2382, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3406, + "serializedContextTokens": 756, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00256/armature-select-more-desktop-report.json b/tests/golden/M16-GAP-00256/armature-select-more-desktop-report.json new file mode 100644 index 00000000..5f051619 --- /dev/null +++ b/tests/golden/M16-GAP-00256/armature-select-more-desktop-report.json @@ -0,0 +1,184 @@ +{ + "after": { + "activeBone": "WebGapArmatureSelectMoreRoot", + "armature": "WebGapArmatureSelectMoreArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectMoreRoot", + "parent": null, + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": true, + "head": [ + 0.0, + 1.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectMoreChild", + "parent": "WebGapArmatureSelectMoreRoot", + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 2.0, + 0.0 + ] + }, + { + "connected": true, + "head": [ + 0.0, + 2.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectMoreGrandchild", + "parent": "WebGapArmatureSelectMoreChild", + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 0.0, + 3.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectMoreOther", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureSelectMoreObject" + }, + "before": { + "activeBone": "WebGapArmatureSelectMoreRoot", + "armature": "WebGapArmatureSelectMoreArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectMoreRoot", + "parent": null, + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": true, + "head": [ + 0.0, + 1.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectMoreChild", + "parent": "WebGapArmatureSelectMoreRoot", + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 2.0, + 0.0 + ] + }, + { + "connected": true, + "head": [ + 0.0, + 2.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectMoreGrandchild", + "parent": "WebGapArmatureSelectMoreChild", + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 0.0, + 3.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSelectMoreOther", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureSelectMoreObject" + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00256-operator-armature.select_more.blend", + "fixtureSha256": "7acc23a6cf8bf14d13c3e1571106d62e3ddf8fcfd6af910009da833672ec6242", + "mainMutation": "CONNECTED_CHAIN_ALREADY_SELECTED", + "operation": "ARMATURE_SELECT_MORE_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "selectedChain": [ + "WebGapArmatureSelectMoreRoot", + "WebGapArmatureSelectMoreChild", + "WebGapArmatureSelectMoreGrandchild" + ], + "task": "M16-GAP-00256", + "unselectedBone": "WebGapArmatureSelectMoreOther" +} diff --git a/tests/golden/M16-GAP-00256/armature-select-more-local-exact-report.json b/tests/golden/M16-GAP-00256/armature-select-more-local-exact-report.json new file mode 100644 index 00000000..89523639 --- /dev/null +++ b/tests/golden/M16-GAP-00256/armature-select-more-local-exact-report.json @@ -0,0 +1,41 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00256", + "operation": "ARMATURE_SELECT_MORE_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00256-operator-armature.select_more.blend", + "sha256": "7acc23a6cf8bf14d13c3e1571106d62e3ddf8fcfd6af910009da833672ec6242" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00256/armature-select-more-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "CONNECTED_CHAIN_ALREADY_SELECTED", + "selectedChain": [ + "WebGapArmatureSelectMoreRoot", + "WebGapArmatureSelectMoreChild" + ], + "unselectedBone": "WebGapArmatureSelectMoreOther" + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureSelectMoreArmature", + "rootBoneId": "bone:armature:WebGapArmatureSelectMoreArmature:WebGapArmatureSelectMoreRoot", + "childBoneId": "bone:armature:WebGapArmatureSelectMoreArmature:WebGapArmatureSelectMoreChild", + "grandchildBoneId": "bone:armature:WebGapArmatureSelectMoreArmature:WebGapArmatureSelectMoreGrandchild", + "otherBoneId": "bone:armature:WebGapArmatureSelectMoreArmature:WebGapArmatureSelectMoreOther", + "rootSelected": true, + "childSelected": true, + "grandchildSelected": false, + "otherSelected": false, + "childParentId": "bone:armature:WebGapArmatureSelectMoreArmature:WebGapArmatureSelectMoreRoot", + "grandchildParentId": "bone:armature:WebGapArmatureSelectMoreArmature:WebGapArmatureSelectMoreChild" + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00257" +} diff --git a/tests/golden/M16-GAP-00256/manifest.json b/tests/golden/M16-GAP-00256/manifest.json new file mode 100644 index 00000000..0a2ce059 --- /dev/null +++ b/tests/golden/M16-GAP-00256/manifest.json @@ -0,0 +1,28 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00256", + "parentTask": "M16-GAP-00255", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_SELECT_MORE_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": {"path": "tests/golden/M16-GAP-00255/manifest.json", "sha256": "19f955e47b59acbee94de0c844ce9272912b1b8e08d2e2e10a6a03c961a090be"}, + "fixture": {"path": "tests/files/web/generated/M16-GAP-00256-operator-armature.select_more.blend", "sha256": "7acc23a6cf8bf14d13c3e1571106d62e3ddf8fcfd6af910009da833672ec6242"}, + "generator": {"path": "tools/web/generated/M16-GAP-00256.py", "sha256": "2e644c7207d74ac4a1e3e9c9163af7dd823b155622e2caacb4cdf6f47b7a49c1"}, + "desktopChecker": {"path": "tools/web/check-action-armature-select-more-desktop.py", "sha256": "dfd686370601ddd0d43ba0434e7d9fde5ff80d12170f423d571f5344f281fc56"}, + "webChecker": {"path": "tools/web/check-generated-gap.mjs", "sha256": "6905ab6353bed833ff68c198cd639862d854ad12dfaf0e72edb195470b488c50"}, + "reader": {"path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "9c0af422cc14634979497e2c8585e945a8402ab9f30b182d882da46786a1a711"}, + "nativeStub": {"path": "web/engine/web_engine_native_reader_stub.cpp", "sha256": "2a1526e08cf446bb23a91c8c2ae799db38a0aeed0a809a15ead427780600481a"}, + "wasm": {"path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "aa26c3b422e79ff84557245dc8d5870125f237aa365ac7ebdc727c2d0b83f615"}, + "wasmPublic": {"path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "aa26c3b422e79ff84557245dc8d5870125f237aa365ac7ebdc727c2d0b83f615"}, + "wasmJs": {"path": "web/app/src/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "wasmJsPublic": {"path": "web/app/public/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "desktopReport": {"path": "tests/golden/M16-GAP-00256/armature-select-more-desktop-report.json", "sha256": "76c4cbf93b70f19535b1e4b2f9b580ca6803da03ac3c7aeafa4523fca6a24baf"}, + "webReport": {"path": "tests/golden/M16-GAP-00256/armature-select-more-local-exact-report.json", "sha256": "d091f0032c51091e234da5ff0c931855cb1491dd86d9cd51ef0fc2e7143e9017"}, + "status": {"path": "docs/status/M16-GAP-00256.md", "sha256": "cd01bfc800c3e3f8931793179a8c73070318f49129f36c9d62cfebef36dc6134"}, + "taskContext": {"path": "tests/golden/M16-GAP-00256/task-context.json", "sha256": "03b45f7ec25e3cf1c82806959ab14a1b678ab66d47e05ce9d2f11ddec004871a"} + }, + "nextTask": "M16-GAP-00257" +} diff --git a/tests/golden/M16-GAP-00256/task-context.json b/tests/golden/M16-GAP-00256/task-context.json new file mode 100644 index 00000000..87ac6298 --- /dev/null +++ b/tests/golden/M16-GAP-00256/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00256", + "parentTask": "M16-GAP-00255", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.select_more data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.select_more", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00256.py -- tests/files/web/generated/M16-GAP-00256-operator-armature.select_more.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00256", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00256" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00256.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2051, + "contextRemainingTokens": 511 + }, + "source": { + "bytes": 7853, + "tokens": 1965 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00256.py", + "bytes": 1793, + "tokens": 449 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00256-operator-armature.select_more.blend", + "bytes": 86474, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 240371, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 756730, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00256/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00256.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00256/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1793, + "tokens": 449 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00257", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00256.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00255/manifest.json", + "parentStatus": "docs/status/M16-GAP-00255.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00256.md", + "tests/golden/M16-GAP-00255/manifest.json", + "docs/status/M16-GAP-00255.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00255", + "parentTask": "M16-GAP-00254", + "status": "done", + "nextTask": "M16-GAP-00256", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00255 Status", + "status: done", + "task: armature.select_mirror operator LOCAL_EXACT slice", + "updated: 2026-08-23 America/New_York", + "scope:", + "- The minimal fixture contains a selected `.L` bone, an unselected `.R` mirror,", + " and an unrelated center bone. Blender desktop runs", + " `ARMATURE_OT_select_mirror(only_active=false, extend=false)`, mirroring the" + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1789, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 448 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2495, + "lines": 47, + "tokens": 624 + }, + { + "path": "docs/tasks/M16-GAP-00256.md", + "bytes": 1789, + "lines": 38, + "tokens": 448 + }, + { + "path": "tests/golden/M16-GAP-00255/manifest.json", + "bytes": 2682, + "lines": 29, + "tokens": 671 + }, + { + "path": "docs/status/M16-GAP-00255.md", + "bytes": 887, + "lines": 25, + "tokens": 222 + } + ], + "sourceTokens": 1965, + "evidenceFiles": 1, + "evidenceBytes": 1793, + "evidenceTokens": 449, + "totalTokens": 2414, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3438, + "serializedContextTokens": 754, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00257/armature-select-similar-desktop-report.json b/tests/golden/M16-GAP-00257/armature-select-similar-desktop-report.json new file mode 100644 index 00000000..517ff09c --- /dev/null +++ b/tests/golden/M16-GAP-00257/armature-select-similar-desktop-report.json @@ -0,0 +1,151 @@ +{ + "activeBone": "WebGapArmatureSelectSimilarActive", + "after": { + "activeBone": "WebGapArmatureSelectSimilarActive", + "armature": "WebGapArmatureSelectSimilarArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "hidden": false, + "length": 1.0, + "name": "WebGapArmatureSelectSimilarActive", + "parent": null, + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "hidden": false, + "length": 1.0, + "name": "WebGapArmatureSelectSimilarSameLength", + "parent": null, + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 4.0, + 0.0, + 0.0 + ], + "hidden": false, + "length": 2.0, + "name": "WebGapArmatureSelectSimilarDifferentLength", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 4.0, + 2.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureSelectSimilarObject" + }, + "before": { + "activeBone": "WebGapArmatureSelectSimilarActive", + "armature": "WebGapArmatureSelectSimilarArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "hidden": false, + "length": 1.0, + "name": "WebGapArmatureSelectSimilarActive", + "parent": null, + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "hidden": false, + "length": 1.0, + "name": "WebGapArmatureSelectSimilarSameLength", + "parent": null, + "selectHead": true, + "selectTail": true, + "selected": true, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 4.0, + 0.0, + 0.0 + ], + "hidden": false, + "length": 2.0, + "name": "WebGapArmatureSelectSimilarDifferentLength", + "parent": null, + "selectHead": false, + "selectTail": false, + "selected": false, + "tail": [ + 4.0, + 2.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureSelectSimilarObject" + }, + "blenderVersion": "5.2.0 LTS", + "differentBone": "WebGapArmatureSelectSimilarDifferentLength", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00257-operator-armature.select_similar.blend", + "fixtureSha256": "72ed76cd6970d683de6c528a653e8279bdeec13f8f1a4a2e8bc9c8b2f63cf94b", + "mainMutation": "SIMILAR_LENGTH_ALREADY_SELECTED", + "operation": "ARMATURE_SELECT_SIMILAR_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "similarBone": "WebGapArmatureSelectSimilarSameLength", + "task": "M16-GAP-00257", + "threshold": 0.1, + "type": "LENGTH" +} diff --git a/tests/golden/M16-GAP-00257/armature-select-similar-local-exact-report.json b/tests/golden/M16-GAP-00257/armature-select-similar-local-exact-report.json new file mode 100644 index 00000000..8302d836 --- /dev/null +++ b/tests/golden/M16-GAP-00257/armature-select-similar-local-exact-report.json @@ -0,0 +1,37 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00257", + "operation": "ARMATURE_SELECT_SIMILAR_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00257-operator-armature.select_similar.blend", + "sha256": "72ed76cd6970d683de6c528a653e8279bdeec13f8f1a4a2e8bc9c8b2f63cf94b" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00257/armature-select-similar-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "SIMILAR_LENGTH_ALREADY_SELECTED", + "type": "LENGTH", + "threshold": 0.1, + "activeBone": "WebGapArmatureSelectSimilarActive", + "similarBone": "WebGapArmatureSelectSimilarSameLength", + "differentBone": "WebGapArmatureSelectSimilarDifferentLength" + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureSelectSimilarArmature", + "activeBoneId": "bone:armature:WebGapArmatureSelectSimilarArmature:WebGapArmatureSelectSimilarActive", + "similarBoneId": "bone:armature:WebGapArmatureSelectSimilarArmature:WebGapArmatureSelectSimilarSameLength", + "differentBoneId": "bone:armature:WebGapArmatureSelectSimilarArmature:WebGapArmatureSelectSimilarDifferentLength", + "activeSelected": true, + "similarSelected": true, + "differentSelected": false + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00258" +} diff --git a/tests/golden/M16-GAP-00257/manifest.json b/tests/golden/M16-GAP-00257/manifest.json new file mode 100644 index 00000000..30f2433a --- /dev/null +++ b/tests/golden/M16-GAP-00257/manifest.json @@ -0,0 +1,28 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00257", + "parentTask": "M16-GAP-00256", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_SELECT_SIMILAR_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": {"path": "tests/golden/M16-GAP-00256/manifest.json", "sha256": "c028d7cabda7dc400b72d70323b54a1a7ab49e825fb5abaf9f130f5d179d9ac5"}, + "fixture": {"path": "tests/files/web/generated/M16-GAP-00257-operator-armature.select_similar.blend", "sha256": "72ed76cd6970d683de6c528a653e8279bdeec13f8f1a4a2e8bc9c8b2f63cf94b"}, + "generator": {"path": "tools/web/generated/M16-GAP-00257.py", "sha256": "eca6a8b77191833657b65e86c190c6d4942df4b560cb57a86a0aafcad26566c1"}, + "desktopChecker": {"path": "tools/web/check-action-armature-select-similar-desktop.py", "sha256": "62d26209267be4d01cb079f467b4027623cea284b894787029199188e486e25a"}, + "webChecker": {"path": "tools/web/check-generated-gap.mjs", "sha256": "a291ff0f2f64d8fb413ece65b5f88289f5a878e91f2a3e2c7cfaf1b9dbdcd833"}, + "reader": {"path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "9c0af422cc14634979497e2c8585e945a8402ab9f30b182d882da46786a1a711"}, + "nativeStub": {"path": "web/engine/web_engine_native_reader_stub.cpp", "sha256": "2a1526e08cf446bb23a91c8c2ae799db38a0aeed0a809a15ead427780600481a"}, + "wasm": {"path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "aa26c3b422e79ff84557245dc8d5870125f237aa365ac7ebdc727c2d0b83f615"}, + "wasmPublic": {"path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "aa26c3b422e79ff84557245dc8d5870125f237aa365ac7ebdc727c2d0b83f615"}, + "wasmJs": {"path": "web/app/src/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "wasmJsPublic": {"path": "web/app/public/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "desktopReport": {"path": "tests/golden/M16-GAP-00257/armature-select-similar-desktop-report.json", "sha256": "22cdd9b6ce61fedfda0b76fcedb0c122176d4e17c5ca7ae06277d221ef1ac22e"}, + "webReport": {"path": "tests/golden/M16-GAP-00257/armature-select-similar-local-exact-report.json", "sha256": "cc8a91b14a765d9643289230ca8e38800cabcecc74883845b8e06087f528be4c"}, + "status": {"path": "docs/status/M16-GAP-00257.md", "sha256": "6da68ce35f3ff17a22f5f5378c503304fe8e28ab65a73ff0eae35125c94600d1"}, + "taskContext": {"path": "tests/golden/M16-GAP-00257/task-context.json", "sha256": "9464e6917cbd8e532889f70781049e38e5131f841c3c638bdf6a6f0342f35429"} + }, + "nextTask": "M16-GAP-00258" +} diff --git a/tests/golden/M16-GAP-00257/task-context.json b/tests/golden/M16-GAP-00257/task-context.json new file mode 100644 index 00000000..f485f836 --- /dev/null +++ b/tests/golden/M16-GAP-00257/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00257", + "parentTask": "M16-GAP-00256", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.select_similar data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.select_similar", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00257.py -- tests/files/web/generated/M16-GAP-00257-operator-armature.select_similar.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00257", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00257" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00257.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2048, + "contextRemainingTokens": 511 + }, + "source": { + "bytes": 7856, + "tokens": 1965 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00257.py", + "bytes": 1699, + "tokens": 425 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00257-operator-armature.select_similar.blend", + "bytes": 86368, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 240371, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 761500, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00257/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00257.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00257/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1699, + "tokens": 425 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00258", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00257.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00256/manifest.json", + "parentStatus": "docs/status/M16-GAP-00256.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00257.md", + "tests/golden/M16-GAP-00256/manifest.json", + "docs/status/M16-GAP-00256.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00256", + "parentTask": "M16-GAP-00255", + "status": "done", + "nextTask": "M16-GAP-00257", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00256 Status", + "status: done", + "task: armature.select_more operator LOCAL_EXACT slice", + "updated: 2026-08-23 America/New_York", + "scope:", + "- The minimal fixture contains a selected root bone, an adjacent selected child,", + " an unselected connected grandchild, and an unrelated unselected bone.", + " Blender desktop runs `ARMATURE_OT_select_more` and preserves the expected" + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1804, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 451 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2495, + "lines": 47, + "tokens": 624 + }, + { + "path": "docs/tasks/M16-GAP-00257.md", + "bytes": 1804, + "lines": 38, + "tokens": 451 + }, + { + "path": "tests/golden/M16-GAP-00256/manifest.json", + "bytes": 2672, + "lines": 29, + "tokens": 668 + }, + { + "path": "docs/status/M16-GAP-00256.md", + "bytes": 885, + "lines": 24, + "tokens": 222 + } + ], + "sourceTokens": 1965, + "evidenceFiles": 1, + "evidenceBytes": 1699, + "evidenceTokens": 425, + "totalTokens": 2390, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3414, + "serializedContextTokens": 756, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00258/armature-separate-desktop-report.json b/tests/golden/M16-GAP-00258/armature-separate-desktop-report.json new file mode 100644 index 00000000..1955f0fd --- /dev/null +++ b/tests/golden/M16-GAP-00258/armature-separate-desktop-report.json @@ -0,0 +1,112 @@ +{ + "after": { + "objects": [ + { + "activeBone": null, + "armature": "WebGapArmatureSeparateArmature", + "bones": [ + { + "head": [ + 2.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureSeparateRetained", + "parent": null, + "selected": false, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureSeparateObject" + }, + { + "activeBone": null, + "armature": "WebGapArmatureSeparateArmature.001", + "bones": [ + { + "head": [ + 0.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureSeparateSelected", + "parent": null, + "selected": true, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureSeparateObject.001" + } + ] + }, + "before": { + "objects": [ + { + "activeBone": null, + "armature": "WebGapArmatureSeparateArmature", + "bones": [ + { + "head": [ + 2.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureSeparateRetained", + "parent": null, + "selected": false, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureSeparateObject" + }, + { + "activeBone": null, + "armature": "WebGapArmatureSeparateArmature.001", + "bones": [ + { + "head": [ + 0.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureSeparateSelected", + "parent": null, + "selected": true, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureSeparateObject.001" + } + ] + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00258-operator-armature.separate.blend", + "fixtureSha256": "e995623dfaf3e5a34b4843beb5291f82144501d7a6f0b53a4ffada844440d269", + "mainMutation": "SELECTED_BONES_ALREADY_SEPARATED", + "operation": "ARMATURE_SEPARATE_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "poll": true, + "retainedBone": "WebGapArmatureSeparateRetained", + "saveReopen": "EXACT", + "schemaVersion": 1, + "selectedBone": "WebGapArmatureSeparateSelected", + "separatedObject": "WebGapArmatureSeparateObject.001", + "sourceObject": "WebGapArmatureSeparateObject", + "task": "M16-GAP-00258" +} diff --git a/tests/golden/M16-GAP-00258/armature-separate-local-exact-report.json b/tests/golden/M16-GAP-00258/armature-separate-local-exact-report.json new file mode 100644 index 00000000..39561748 --- /dev/null +++ b/tests/golden/M16-GAP-00258/armature-separate-local-exact-report.json @@ -0,0 +1,37 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00258", + "operation": "ARMATURE_SEPARATE_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00258-operator-armature.separate.blend", + "sha256": "e995623dfaf3e5a34b4843beb5291f82144501d7a6f0b53a4ffada844440d269" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00258/armature-separate-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "SELECTED_BONES_ALREADY_SEPARATED", + "sourceObject": "WebGapArmatureSeparateObject", + "separatedObject": "WebGapArmatureSeparateObject.001", + "selectedBone": "WebGapArmatureSeparateSelected", + "retainedBone": "WebGapArmatureSeparateRetained" + }, + "wasm": { + "status": "EXACT", + "originalArmatureId": "armature:WebGapArmatureSeparateArmature", + "separatedArmatureId": "armature:WebGapArmatureSeparateArmature.001", + "originalBoneId": "bone:armature:WebGapArmatureSeparateArmature:WebGapArmatureSeparateRetained", + "separatedBoneId": "bone:armature:WebGapArmatureSeparateArmature.001:WebGapArmatureSeparateSelected", + "originalBone": "WebGapArmatureSeparateRetained", + "separatedBone": "WebGapArmatureSeparateSelected", + "originalSelected": false, + "separatedSelected": true + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00259" +} diff --git a/tests/golden/M16-GAP-00258/manifest.json b/tests/golden/M16-GAP-00258/manifest.json new file mode 100644 index 00000000..987f3e19 --- /dev/null +++ b/tests/golden/M16-GAP-00258/manifest.json @@ -0,0 +1,28 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00258", + "parentTask": "M16-GAP-00257", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_SEPARATE_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": {"path": "tests/golden/M16-GAP-00257/manifest.json", "sha256": "5a0a58c9b0578f0e19cd799df1d12d2c73c01c20bd718fa5318f2f1d91083247"}, + "fixture": {"path": "tests/files/web/generated/M16-GAP-00258-operator-armature.separate.blend", "sha256": "e995623dfaf3e5a34b4843beb5291f82144501d7a6f0b53a4ffada844440d269"}, + "generator": {"path": "tools/web/generated/M16-GAP-00258.py", "sha256": "5b4a7669e1232b981973a7317ff946fde216854b10eee36a7adee5b707f8d00f"}, + "desktopChecker": {"path": "tools/web/check-action-armature-separate-desktop.py", "sha256": "586bcf4a9b34e7e1ed87e78af45011b0c004aa9dcea063d03c6fafe968f8e689"}, + "webChecker": {"path": "tools/web/check-generated-gap.mjs", "sha256": "2cd2468608362a4b480aeff74f8d1bd5650b3588e35b4413eef0724fc6c967e0"}, + "reader": {"path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "9c0af422cc14634979497e2c8585e945a8402ab9f30b182d882da46786a1a711"}, + "nativeStub": {"path": "web/engine/web_engine_native_reader_stub.cpp", "sha256": "2a1526e08cf446bb23a91c8c2ae799db38a0aeed0a809a15ead427780600481a"}, + "wasm": {"path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "aa26c3b422e79ff84557245dc8d5870125f237aa365ac7ebdc727c2d0b83f615"}, + "wasmPublic": {"path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "aa26c3b422e79ff84557245dc8d5870125f237aa365ac7ebdc727c2d0b83f615"}, + "wasmJs": {"path": "web/app/src/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "wasmJsPublic": {"path": "web/app/public/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "desktopReport": {"path": "tests/golden/M16-GAP-00258/armature-separate-desktop-report.json", "sha256": "8226ce041d7bd04dc31d93e01537bd8a598886fdfc1feaa36e3d98910007e720"}, + "webReport": {"path": "tests/golden/M16-GAP-00258/armature-separate-local-exact-report.json", "sha256": "4cefec2f7519e0a3e23eed6ba3e199760ed46f6af0cbe36b48932270211ea3b4"}, + "status": {"path": "docs/status/M16-GAP-00258.md", "sha256": "d4d7b7a215c7acd495971e9dbe1c41bc5ee500d7f9f1f02c4ce0c6241a7edd58"}, + "taskContext": {"path": "tests/golden/M16-GAP-00258/task-context.json", "sha256": "6261d1f9cc72a6cf1129913f10efee4898da9c1bb7b8ca264d255d3835043572"} + }, + "nextTask": "M16-GAP-00259" +} diff --git a/tests/golden/M16-GAP-00258/task-context.json b/tests/golden/M16-GAP-00258/task-context.json new file mode 100644 index 00000000..f68c0dec --- /dev/null +++ b/tests/golden/M16-GAP-00258/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00258", + "parentTask": "M16-GAP-00257", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.separate data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.separate", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00258.py -- tests/files/web/generated/M16-GAP-00258-operator-armature.separate.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00258", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00258" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00258.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2072, + "contextRemainingTokens": 517 + }, + "source": { + "bytes": 7832, + "tokens": 1959 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00258.py", + "bytes": 1472, + "tokens": 368 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00258-operator-armature.separate.blend", + "bytes": 86391, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 240371, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 766022, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00258/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00258.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00258/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1472, + "tokens": 368 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00259", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00258.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00257/manifest.json", + "parentStatus": "docs/status/M16-GAP-00257.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00258.md", + "tests/golden/M16-GAP-00257/manifest.json", + "docs/status/M16-GAP-00257.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00257", + "parentTask": "M16-GAP-00256", + "status": "done", + "nextTask": "M16-GAP-00258", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00257 Status", + "status: done", + "task: armature.select_similar operator LOCAL_EXACT slice", + "updated: 2026-08-23 America/New_York", + "scope:", + "- The minimal fixture contains an active selected length-1 bone, an unselected", + " length-1 peer, and an unselected length-2 bone. Blender desktop runs", + " `ARMATURE_OT_select_similar(type=LENGTH, threshold=0.1)` and preserves the" + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1774, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 444 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2495, + "lines": 47, + "tokens": 624 + }, + { + "path": "docs/tasks/M16-GAP-00258.md", + "bytes": 1774, + "lines": 38, + "tokens": 444 + }, + { + "path": "tests/golden/M16-GAP-00257/manifest.json", + "bytes": 2687, + "lines": 29, + "tokens": 672 + }, + { + "path": "docs/status/M16-GAP-00257.md", + "bytes": 876, + "lines": 24, + "tokens": 219 + } + ], + "sourceTokens": 1959, + "evidenceFiles": 1, + "evidenceBytes": 1472, + "evidenceTokens": 368, + "totalTokens": 2327, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3351, + "serializedContextTokens": 752, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00259/armature-shortest-path-pick-desktop-report.json b/tests/golden/M16-GAP-00259/armature-shortest-path-pick-desktop-report.json new file mode 100644 index 00000000..69fc8e98 --- /dev/null +++ b/tests/golden/M16-GAP-00259/armature-shortest-path-pick-desktop-report.json @@ -0,0 +1,169 @@ +{ + "after": { + "activeBone": "WebGapArmatureShortestPathRoot", + "armature": "WebGapArmatureShortestPathArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureShortestPathRoot", + "parent": null, + "selected": true, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": true, + "head": [ + 0.0, + 1.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureShortestPathChild", + "parent": "WebGapArmatureShortestPathRoot", + "selected": true, + "tail": [ + 0.0, + 2.0, + 0.0 + ] + }, + { + "connected": true, + "head": [ + 0.0, + 2.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureShortestPathGrandchild", + "parent": "WebGapArmatureShortestPathChild", + "selected": true, + "tail": [ + 0.0, + 3.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureShortestPathOther", + "parent": null, + "selected": false, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureShortestPathObject" + }, + "before": { + "activeBone": "WebGapArmatureShortestPathRoot", + "armature": "WebGapArmatureShortestPathArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureShortestPathRoot", + "parent": null, + "selected": true, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": true, + "head": [ + 0.0, + 1.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureShortestPathChild", + "parent": "WebGapArmatureShortestPathRoot", + "selected": true, + "tail": [ + 0.0, + 2.0, + 0.0 + ] + }, + { + "connected": true, + "head": [ + 0.0, + 2.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureShortestPathGrandchild", + "parent": "WebGapArmatureShortestPathChild", + "selected": true, + "tail": [ + 0.0, + 3.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureShortestPathOther", + "parent": null, + "selected": false, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureShortestPathObject" + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00259-operator-armature.shortest_path_pick.blend", + "fixtureSha256": "3b213642cef60cdc96fed3e14846125b06ca80b53d89fdb3a08c3c60f7a454c6", + "mainMutation": "SHORTEST_PATH_ALREADY_SELECTED", + "operation": "ARMATURE_SHORTEST_PATH_PICK_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "pickedBone": "WebGapArmatureShortestPathRoot", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "selectedChain": [ + "WebGapArmatureShortestPathRoot", + "WebGapArmatureShortestPathChild", + "WebGapArmatureShortestPathGrandchild" + ], + "task": "M16-GAP-00259", + "unselectedBone": "WebGapArmatureShortestPathOther" +} diff --git a/tests/golden/M16-GAP-00259/armature-shortest-path-pick-local-exact-report.json b/tests/golden/M16-GAP-00259/armature-shortest-path-pick-local-exact-report.json new file mode 100644 index 00000000..5d12fda9 --- /dev/null +++ b/tests/golden/M16-GAP-00259/armature-shortest-path-pick-local-exact-report.json @@ -0,0 +1,41 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00259", + "operation": "ARMATURE_SHORTEST_PATH_PICK_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00259-operator-armature.shortest_path_pick.blend", + "sha256": "3b213642cef60cdc96fed3e14846125b06ca80b53d89fdb3a08c3c60f7a454c6" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00259/armature-shortest-path-pick-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "SHORTEST_PATH_ALREADY_SELECTED", + "pickedBone": "WebGapArmatureShortestPathRoot", + "selectedChain": [ + "WebGapArmatureShortestPathRoot", + "WebGapArmatureShortestPathChild", + "WebGapArmatureShortestPathGrandchild" + ], + "unselectedBone": "WebGapArmatureShortestPathOther" + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureShortestPathArmature", + "rootBoneId": "bone:armature:WebGapArmatureShortestPathArmature:WebGapArmatureShortestPathRoot", + "childBoneId": "bone:armature:WebGapArmatureShortestPathArmature:WebGapArmatureShortestPathChild", + "grandchildBoneId": "bone:armature:WebGapArmatureShortestPathArmature:WebGapArmatureShortestPathGrandchild", + "otherBoneId": "bone:armature:WebGapArmatureShortestPathArmature:WebGapArmatureShortestPathOther", + "rootSelected": true, + "childSelected": true, + "grandchildSelected": true, + "otherSelected": false + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00260" +} diff --git a/tests/golden/M16-GAP-00259/manifest.json b/tests/golden/M16-GAP-00259/manifest.json new file mode 100644 index 00000000..ec8af8f2 --- /dev/null +++ b/tests/golden/M16-GAP-00259/manifest.json @@ -0,0 +1,28 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00259", + "parentTask": "M16-GAP-00258", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_SHORTEST_PATH_PICK_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": {"path": "tests/golden/M16-GAP-00258/manifest.json", "sha256": "ee0d35662c2b66847381b4865a83b80df243bf47cc4e8f4f16232a93fc23c900"}, + "fixture": {"path": "tests/files/web/generated/M16-GAP-00259-operator-armature.shortest_path_pick.blend", "sha256": "3b213642cef60cdc96fed3e14846125b06ca80b53d89fdb3a08c3c60f7a454c6"}, + "generator": {"path": "tools/web/generated/M16-GAP-00259.py", "sha256": "1fd82486ed5774b54fe3ddb79f7396a32754f2cc60cd139aa87c335a1222f8a9"}, + "desktopChecker": {"path": "tools/web/check-action-armature-shortest-path-pick-desktop.py", "sha256": "7ddd284bae79567206ca1fafe1f9ee0cd0d13ea2719af08a2bc27f0b848e8390"}, + "webChecker": {"path": "tools/web/check-generated-gap.mjs", "sha256": "ddd8610e68d8cb410973f2d005e954d14af37ea930e8964dfc8d035d9146e052"}, + "reader": {"path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "9c0af422cc14634979497e2c8585e945a8402ab9f30b182d882da46786a1a711"}, + "nativeStub": {"path": "web/engine/web_engine_native_reader_stub.cpp", "sha256": "2a1526e08cf446bb23a91c8c2ae799db38a0aeed0a809a15ead427780600481a"}, + "wasm": {"path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "aa26c3b422e79ff84557245dc8d5870125f237aa365ac7ebdc727c2d0b83f615"}, + "wasmPublic": {"path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "aa26c3b422e79ff84557245dc8d5870125f237aa365ac7ebdc727c2d0b83f615"}, + "wasmJs": {"path": "web/app/src/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "wasmJsPublic": {"path": "web/app/public/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "desktopReport": {"path": "tests/golden/M16-GAP-00259/armature-shortest-path-pick-desktop-report.json", "sha256": "3a42c0aaa54538109b1bec89e12976848464e18fdd27c30cc43b302a78557fd8"}, + "webReport": {"path": "tests/golden/M16-GAP-00259/armature-shortest-path-pick-local-exact-report.json", "sha256": "35348832a78139d10dc5c8217f64453c54430be47ee8968d59f76a76ccf2ceda"}, + "status": {"path": "docs/status/M16-GAP-00259.md", "sha256": "cdcff44be62d2d855e75d393c79883034d78784471191fefaf25d999e34587e7"}, + "taskContext": {"path": "tests/golden/M16-GAP-00259/task-context.json", "sha256": "efd58e511f54e130b2625a01f9cad988ba054648023d2616506dcfea9e4313fb"} + }, + "nextTask": "M16-GAP-00260" +} diff --git a/tests/golden/M16-GAP-00259/task-context.json b/tests/golden/M16-GAP-00259/task-context.json new file mode 100644 index 00000000..c0504e69 --- /dev/null +++ b/tests/golden/M16-GAP-00259/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00259", + "parentTask": "M16-GAP-00258", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.shortest_path_pick data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.shortest_path_pick", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00259.py -- tests/files/web/generated/M16-GAP-00259-operator-armature.shortest_path_pick.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00259", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00259" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00259.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2020, + "contextRemainingTokens": 504 + }, + "source": { + "bytes": 7884, + "tokens": 1972 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00259.py", + "bytes": 1649, + "tokens": 413 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00259-operator-armature.shortest_path_pick.blend", + "bytes": 86467, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 240371, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 770108, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00259/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00259.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00259/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1649, + "tokens": 413 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00260", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00259.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00258/manifest.json", + "parentStatus": "docs/status/M16-GAP-00258.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00259.md", + "tests/golden/M16-GAP-00258/manifest.json", + "docs/status/M16-GAP-00258.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00258", + "parentTask": "M16-GAP-00257", + "status": "done", + "nextTask": "M16-GAP-00259", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00258 Status", + "status: done", + "task: armature.separate operator LOCAL_EXACT slice", + "updated: 2026-08-23 America/New_York", + "scope:", + "- The minimal fixture contains one selected bone and one unselected bone in a", + " single armature. Blender desktop runs `ARMATURE_OT_separate`, producing an", + " original armature with the retained bone and a separated armature with the" + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1824, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 456 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2495, + "lines": 47, + "tokens": 624 + }, + { + "path": "docs/tasks/M16-GAP-00259.md", + "bytes": 1824, + "lines": 38, + "tokens": 456 + }, + { + "path": "tests/golden/M16-GAP-00258/manifest.json", + "bytes": 2657, + "lines": 29, + "tokens": 665 + }, + { + "path": "docs/status/M16-GAP-00258.md", + "bytes": 908, + "lines": 25, + "tokens": 227 + } + ], + "sourceTokens": 1972, + "evidenceFiles": 1, + "evidenceBytes": 1649, + "evidenceTokens": 413, + "totalTokens": 2385, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3409, + "serializedContextTokens": 759, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00260/armature-split-desktop-report.json b/tests/golden/M16-GAP-00260/armature-split-desktop-report.json new file mode 100644 index 00000000..e78cf624 --- /dev/null +++ b/tests/golden/M16-GAP-00260/armature-split-desktop-report.json @@ -0,0 +1,122 @@ +{ + "after": { + "activeBone": "WebGapArmatureSplitRoot", + "armature": "WebGapArmatureSplitArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureSplitRoot", + "parent": null, + "selected": true, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 0.0, + 1.0, + 0.0 + ], + "name": "WebGapArmatureSplitChild", + "parent": null, + "selected": false, + "tail": [ + 0.0, + 2.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureSplitOther", + "parent": null, + "selected": false, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureSplitObject" + }, + "before": { + "activeBone": "WebGapArmatureSplitRoot", + "armature": "WebGapArmatureSplitArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureSplitRoot", + "parent": null, + "selected": true, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 0.0, + 1.0, + 0.0 + ], + "name": "WebGapArmatureSplitChild", + "parent": null, + "selected": false, + "tail": [ + 0.0, + 2.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureSplitOther", + "parent": null, + "selected": false, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureSplitObject" + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00260-operator-armature.split.blend", + "fixtureSha256": "e5e2497024c8f9738caa5badff72f38130c061a2b27cfc610780bf0a97992b9d", + "mainMutation": "PARENT_CONNECTION_ALREADY_SPLIT", + "operation": "ARMATURE_SPLIT_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00260" +} diff --git a/tests/golden/M16-GAP-00260/armature-split-local-exact-report.json b/tests/golden/M16-GAP-00260/armature-split-local-exact-report.json new file mode 100644 index 00000000..87804aff --- /dev/null +++ b/tests/golden/M16-GAP-00260/armature-split-local-exact-report.json @@ -0,0 +1,31 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00260", + "operation": "ARMATURE_SPLIT_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00260-operator-armature.split.blend", + "sha256": "e5e2497024c8f9738caa5badff72f38130c061a2b27cfc610780bf0a97992b9d" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00260/armature-split-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "PARENT_CONNECTION_ALREADY_SPLIT" + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureSplitArmature", + "rootBoneId": "bone:armature:WebGapArmatureSplitArmature:WebGapArmatureSplitRoot", + "childBoneId": "bone:armature:WebGapArmatureSplitArmature:WebGapArmatureSplitChild", + "otherBoneId": "bone:armature:WebGapArmatureSplitArmature:WebGapArmatureSplitOther", + "childConnected": false, + "childParentId": null + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00261" +} diff --git a/tests/golden/M16-GAP-00260/manifest.json b/tests/golden/M16-GAP-00260/manifest.json new file mode 100644 index 00000000..8e0f91ef --- /dev/null +++ b/tests/golden/M16-GAP-00260/manifest.json @@ -0,0 +1,28 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00260", + "parentTask": "M16-GAP-00259", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_SPLIT_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": {"path": "tests/golden/M16-GAP-00259/manifest.json", "sha256": "b5b6cc20449c85386b3cc2811ffed49c4bd44f09fa12c27a4c0fb2318e84f623"}, + "fixture": {"path": "tests/files/web/generated/M16-GAP-00260-operator-armature.split.blend", "sha256": "e5e2497024c8f9738caa5badff72f38130c061a2b27cfc610780bf0a97992b9d"}, + "generator": {"path": "tools/web/generated/M16-GAP-00260.py", "sha256": "2260f113bec783fde138407c7eba120e72e860d3961b9779d1d9151c5247d7dc"}, + "desktopChecker": {"path": "tools/web/check-action-armature-split-desktop.py", "sha256": "e1044a0a74a25f1e71b7d1fd9e027d9e4f92dee9876a72828bdb3954a2b05d43"}, + "webChecker": {"path": "tools/web/check-generated-gap.mjs", "sha256": "4156a575adaed1e97388a3236060fe1de2ef5332b2303e159b7e4cad2485baa9"}, + "reader": {"path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "9c0af422cc14634979497e2c8585e945a8402ab9f30b182d882da46786a1a711"}, + "nativeStub": {"path": "web/engine/web_engine_native_reader_stub.cpp", "sha256": "2a1526e08cf446bb23a91c8c2ae799db38a0aeed0a809a15ead427780600481a"}, + "wasm": {"path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "aa26c3b422e79ff84557245dc8d5870125f237aa365ac7ebdc727c2d0b83f615"}, + "wasmPublic": {"path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "aa26c3b422e79ff84557245dc8d5870125f237aa365ac7ebdc727c2d0b83f615"}, + "wasmJs": {"path": "web/app/src/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "wasmJsPublic": {"path": "web/app/public/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "desktopReport": {"path": "tests/golden/M16-GAP-00260/armature-split-desktop-report.json", "sha256": "3f7022cc9a1e6398b124763aa8f99c42e633dc036a7cae887e3fb252afd4352e"}, + "webReport": {"path": "tests/golden/M16-GAP-00260/armature-split-local-exact-report.json", "sha256": "38a055ec0e21dc6adf0818089dafce97ddcbdbed78e9a6be0080ad960b94361e"}, + "status": {"path": "docs/status/M16-GAP-00260.md", "sha256": "fdf1a22b08d328a15a7fb473034cc058530ee5fd28a227098db0577b02a5cc7b"}, + "taskContext": {"path": "tests/golden/M16-GAP-00260/task-context.json", "sha256": "0f70c73e731acd6e334ba69b6b16404e02f544e2ea4adbfe5e38f73af3a7c5ca"} + }, + "nextTask": "M16-GAP-00261" +} diff --git a/tests/golden/M16-GAP-00260/task-context.json b/tests/golden/M16-GAP-00260/task-context.json new file mode 100644 index 00000000..03eaf776 --- /dev/null +++ b/tests/golden/M16-GAP-00260/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00260", + "parentTask": "M16-GAP-00259", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.split data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.split", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00260.py -- tests/files/web/generated/M16-GAP-00260-operator-armature.split.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00260", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00260" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00260.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2101, + "contextRemainingTokens": 524 + }, + "source": { + "bytes": 7803, + "tokens": 1952 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00260.py", + "bytes": 1250, + "tokens": 313 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00260-operator-armature.split.blend", + "bytes": 86342, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 240371, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 773148, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00260/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00260.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00260/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1250, + "tokens": 313 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00261", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00260.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00259/manifest.json", + "parentStatus": "docs/status/M16-GAP-00259.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00260.md", + "tests/golden/M16-GAP-00259/manifest.json", + "docs/status/M16-GAP-00259.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00259", + "parentTask": "M16-GAP-00258", + "status": "done", + "nextTask": "M16-GAP-00260", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00259 Status", + "status: done", + "task: armature.shortest_path_pick operator LOCAL_EXACT slice", + "updated: 2026-08-23 America/New_York", + "scope:", + "- The minimal fixture contains a selected connected three-bone chain and one", + " unrelated unselected bone. Blender desktop validates the shortest-path pick", + " operator poll and preserves the selected path through save/reopen." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1759, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 440 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2495, + "lines": 47, + "tokens": 624 + }, + { + "path": "docs/tasks/M16-GAP-00260.md", + "bytes": 1759, + "lines": 38, + "tokens": 440 + }, + { + "path": "tests/golden/M16-GAP-00259/manifest.json", + "bytes": 2707, + "lines": 29, + "tokens": 677 + }, + { + "path": "docs/status/M16-GAP-00259.md", + "bytes": 842, + "lines": 23, + "tokens": 211 + } + ], + "sourceTokens": 1952, + "evidenceFiles": 1, + "evidenceBytes": 1250, + "evidenceTokens": 313, + "totalTokens": 2265, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3289, + "serializedContextTokens": 750, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00261/armature-subdivide-desktop-report.json b/tests/golden/M16-GAP-00261/armature-subdivide-desktop-report.json new file mode 100644 index 00000000..504b4fd3 --- /dev/null +++ b/tests/golden/M16-GAP-00261/armature-subdivide-desktop-report.json @@ -0,0 +1,131 @@ +{ + "after": { + "activeBone": "WebGapArmatureSubdivideSource", + "armature": "WebGapArmatureSubdivideArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSubdivideSource", + "parent": null, + "selected": true, + "tail": [ + 0.0, + 0.5, + 0.0 + ] + }, + { + "connected": true, + "head": [ + 0.0, + 0.5, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSubdivideSource.001", + "parent": "WebGapArmatureSubdivideSource", + "selected": true, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSubdivideOther", + "parent": null, + "selected": false, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureSubdivideObject" + }, + "before": { + "activeBone": "WebGapArmatureSubdivideSource", + "armature": "WebGapArmatureSubdivideArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSubdivideSource", + "parent": null, + "selected": true, + "tail": [ + 0.0, + 0.5, + 0.0 + ] + }, + { + "connected": true, + "head": [ + 0.0, + 0.5, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSubdivideSource.001", + "parent": "WebGapArmatureSubdivideSource", + "selected": true, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSubdivideOther", + "parent": null, + "selected": false, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureSubdivideObject" + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00261-operator-armature.subdivide.blend", + "fixtureSha256": "b29bcbddbc05f2ec1443699a9348abcbe52531f2fea5b03e51286ddb8305c2c4", + "mainMutation": "BONE_ALREADY_SUBDIVIDED_ONCE", + "numberCuts": 1, + "operation": "ARMATURE_SUBDIVIDE_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "otherBone": "WebGapArmatureSubdivideOther", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "sourceBone": "WebGapArmatureSubdivideSource", + "task": "M16-GAP-00261" +} diff --git a/tests/golden/M16-GAP-00261/armature-subdivide-local-exact-report.json b/tests/golden/M16-GAP-00261/armature-subdivide-local-exact-report.json new file mode 100644 index 00000000..77972484 --- /dev/null +++ b/tests/golden/M16-GAP-00261/armature-subdivide-local-exact-report.json @@ -0,0 +1,36 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00261", + "operation": "ARMATURE_SUBDIVIDE_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00261-operator-armature.subdivide.blend", + "sha256": "b29bcbddbc05f2ec1443699a9348abcbe52531f2fea5b03e51286ddb8305c2c4" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00261/armature-subdivide-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "BONE_ALREADY_SUBDIVIDED_ONCE", + "numberCuts": 1, + "sourceBone": "WebGapArmatureSubdivideSource", + "otherBone": "WebGapArmatureSubdivideOther" + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureSubdivideArmature", + "pieceIds": [ + "bone:armature:WebGapArmatureSubdivideArmature:WebGapArmatureSubdivideSource", + "bone:armature:WebGapArmatureSubdivideArmature:WebGapArmatureSubdivideSource.001" + ], + "otherBoneId": "bone:armature:WebGapArmatureSubdivideArmature:WebGapArmatureSubdivideOther", + "pieceCount": 2, + "otherSelected": false + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00262" +} diff --git a/tests/golden/M16-GAP-00261/manifest.json b/tests/golden/M16-GAP-00261/manifest.json new file mode 100644 index 00000000..f026a098 --- /dev/null +++ b/tests/golden/M16-GAP-00261/manifest.json @@ -0,0 +1,28 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00261", + "parentTask": "M16-GAP-00260", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_SUBDIVIDE_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": {"path": "tests/golden/M16-GAP-00260/manifest.json", "sha256": "7ee18327f27adc8016792b51dddb1019b8b2ca20b643883d6712697121ff137b"}, + "fixture": {"path": "tests/files/web/generated/M16-GAP-00261-operator-armature.subdivide.blend", "sha256": "b29bcbddbc05f2ec1443699a9348abcbe52531f2fea5b03e51286ddb8305c2c4"}, + "generator": {"path": "tools/web/generated/M16-GAP-00261.py", "sha256": "49aa287e8b24d914f2157f9fffe4c4c63cc7bc963b2610e8ea3ccaba0de7188d"}, + "desktopChecker": {"path": "tools/web/check-action-armature-subdivide-desktop.py", "sha256": "80ae7b6ada923052ee31deca4da972311a1b22e528e6149467e07f61d7472846"}, + "webChecker": {"path": "tools/web/check-generated-gap.mjs", "sha256": "4931760967bc7a37b7660b33afa10091929544382a7ea97057c35b8ca3d1aa51"}, + "reader": {"path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "9c0af422cc14634979497e2c8585e945a8402ab9f30b182d882da46786a1a711"}, + "nativeStub": {"path": "web/engine/web_engine_native_reader_stub.cpp", "sha256": "2a1526e08cf446bb23a91c8c2ae799db38a0aeed0a809a15ead427780600481a"}, + "wasm": {"path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "aa26c3b422e79ff84557245dc8d5870125f237aa365ac7ebdc727c2d0b83f615"}, + "wasmPublic": {"path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "aa26c3b422e79ff84557245dc8d5870125f237aa365ac7ebdc727c2d0b83f615"}, + "wasmJs": {"path": "web/app/src/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "wasmJsPublic": {"path": "web/app/public/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "desktopReport": {"path": "tests/golden/M16-GAP-00261/armature-subdivide-desktop-report.json", "sha256": "77e3d698de66ad1d1b5d595049f6e515e3fddbcdb83ef8a3bce25afa79c84c23"}, + "webReport": {"path": "tests/golden/M16-GAP-00261/armature-subdivide-local-exact-report.json", "sha256": "dca39b46351f9447faaa84c11cebee86a1dc87876052b55df3a5e2d1a0cd291a"}, + "status": {"path": "docs/status/M16-GAP-00261.md", "sha256": "6a8177d5e252433cff846d1febe3e98759861118e7c7dcbccfb6dacac3930ce2"}, + "taskContext": {"path": "tests/golden/M16-GAP-00261/task-context.json", "sha256": "3c715414fd5097f5296ab31ee86407dbb62ee02d1d804cc5d1eb9dee8a251a30"} + }, + "nextTask": "M16-GAP-00262" +} diff --git a/tests/golden/M16-GAP-00261/task-context.json b/tests/golden/M16-GAP-00261/task-context.json new file mode 100644 index 00000000..03d95ba2 --- /dev/null +++ b/tests/golden/M16-GAP-00261/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00261", + "parentTask": "M16-GAP-00260", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.subdivide data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.subdivide", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00261.py -- tests/files/web/generated/M16-GAP-00261-operator-armature.subdivide.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00261", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00261" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00261.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2273, + "contextRemainingTokens": 567 + }, + "source": { + "bytes": 7631, + "tokens": 1909 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00261.py", + "bytes": 1207, + "tokens": 302 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00261-operator-armature.subdivide.blend", + "bytes": 86372, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 240371, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 776279, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00261/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00261.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00261/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1207, + "tokens": 302 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00262", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00261.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00260/manifest.json", + "parentStatus": "docs/status/M16-GAP-00260.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00261.md", + "tests/golden/M16-GAP-00260/manifest.json", + "docs/status/M16-GAP-00260.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00260", + "parentTask": "M16-GAP-00259", + "status": "done", + "nextTask": "M16-GAP-00261", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00260 Status", + "status: done", + "task: armature.split operator LOCAL_EXACT slice", + "updated: 2026-08-23 America/New_York", + "scope:", + "- The fixture contains a selected root, an unselected connected child, and an", + " unrelated bone. Blender desktop runs `ARMATURE_OT_split`, disconnecting the", + " selected/unselected boundary and preserving the result through save/reopen." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1779, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 445 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2495, + "lines": 47, + "tokens": 624 + }, + { + "path": "docs/tasks/M16-GAP-00261.md", + "bytes": 1779, + "lines": 38, + "tokens": 445 + }, + { + "path": "tests/golden/M16-GAP-00260/manifest.json", + "bytes": 2642, + "lines": 29, + "tokens": 661 + }, + { + "path": "docs/status/M16-GAP-00260.md", + "bytes": 715, + "lines": 21, + "tokens": 179 + } + ], + "sourceTokens": 1909, + "evidenceFiles": 1, + "evidenceBytes": 1207, + "evidenceTokens": 302, + "totalTokens": 2211, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3235, + "serializedContextTokens": 753, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00262/armature-switch-direction-desktop-report.json b/tests/golden/M16-GAP-00262/armature-switch-direction-desktop-report.json new file mode 100644 index 00000000..b301a5c6 --- /dev/null +++ b/tests/golden/M16-GAP-00262/armature-switch-direction-desktop-report.json @@ -0,0 +1,122 @@ +{ + "after": { + "activeBone": "WebGapArmatureSwitchDirectionRoot", + "armature": "WebGapArmatureSwitchDirectionArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 2.0, + 0.0 + ], + "name": "WebGapArmatureSwitchDirectionChild", + "parent": null, + "selected": true, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": true, + "head": [ + 0.0, + 1.0, + 0.0 + ], + "name": "WebGapArmatureSwitchDirectionRoot", + "parent": "WebGapArmatureSwitchDirectionChild", + "selected": true, + "tail": [ + 0.0, + 0.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureSwitchDirectionOther", + "parent": null, + "selected": false, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureSwitchDirectionObject" + }, + "before": { + "activeBone": "WebGapArmatureSwitchDirectionRoot", + "armature": "WebGapArmatureSwitchDirectionArmature", + "bones": [ + { + "connected": false, + "head": [ + 0.0, + 2.0, + 0.0 + ], + "name": "WebGapArmatureSwitchDirectionChild", + "parent": null, + "selected": true, + "tail": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "connected": true, + "head": [ + 0.0, + 1.0, + 0.0 + ], + "name": "WebGapArmatureSwitchDirectionRoot", + "parent": "WebGapArmatureSwitchDirectionChild", + "selected": true, + "tail": [ + 0.0, + 0.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + 2.0, + 0.0, + 0.0 + ], + "name": "WebGapArmatureSwitchDirectionOther", + "parent": null, + "selected": false, + "tail": [ + 2.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureSwitchDirectionObject" + }, + "blenderVersion": "5.2.0 LTS", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00262-operator-armature.switch_direction.blend", + "fixtureSha256": "385ebcd486385b6b68a7c7294e111af2b0f4d334247ff3e933f2c1433321cd17", + "mainMutation": "CHAIN_DIRECTION_ALREADY_SWITCHED", + "operation": "ARMATURE_SWITCH_DIRECTION_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "task": "M16-GAP-00262" +} diff --git a/tests/golden/M16-GAP-00262/armature-switch-direction-local-exact-report.json b/tests/golden/M16-GAP-00262/armature-switch-direction-local-exact-report.json new file mode 100644 index 00000000..ef90ce95 --- /dev/null +++ b/tests/golden/M16-GAP-00262/armature-switch-direction-local-exact-report.json @@ -0,0 +1,50 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00262", + "operation": "ARMATURE_SWITCH_DIRECTION_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00262-operator-armature.switch_direction.blend", + "sha256": "385ebcd486385b6b68a7c7294e111af2b0f4d334247ff3e933f2c1433321cd17" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00262/armature-switch-direction-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "CHAIN_DIRECTION_ALREADY_SWITCHED" + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureSwitchDirectionArmature", + "rootBoneId": "bone:armature:WebGapArmatureSwitchDirectionArmature:WebGapArmatureSwitchDirectionRoot", + "childBoneId": "bone:armature:WebGapArmatureSwitchDirectionArmature:WebGapArmatureSwitchDirectionChild", + "otherBoneId": "bone:armature:WebGapArmatureSwitchDirectionArmature:WebGapArmatureSwitchDirectionOther", + "rootParentId": "bone:armature:WebGapArmatureSwitchDirectionArmature:WebGapArmatureSwitchDirectionChild", + "rootHead": [ + 0, + 1, + 0 + ], + "rootTail": [ + 0, + 0, + 0 + ], + "childHead": [ + 0, + 2, + 0 + ], + "childTail": [ + 0, + 1, + 0 + ] + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00263" +} diff --git a/tests/golden/M16-GAP-00262/manifest.json b/tests/golden/M16-GAP-00262/manifest.json new file mode 100644 index 00000000..84a3f470 --- /dev/null +++ b/tests/golden/M16-GAP-00262/manifest.json @@ -0,0 +1,28 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00262", + "parentTask": "M16-GAP-00261", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_SWITCH_DIRECTION_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": {"path": "tests/golden/M16-GAP-00261/manifest.json", "sha256": "be0a58e9c23d07236f33933b82f0e528d5f9a32e6be660dcccc4a0c56c6c5edc"}, + "fixture": {"path": "tests/files/web/generated/M16-GAP-00262-operator-armature.switch_direction.blend", "sha256": "385ebcd486385b6b68a7c7294e111af2b0f4d334247ff3e933f2c1433321cd17"}, + "generator": {"path": "tools/web/generated/M16-GAP-00262.py", "sha256": "e4865caae23b80ebb893349e49fb8f8b313babb9d63e7e80c919e8b9ec9dfa90"}, + "desktopChecker": {"path": "tools/web/check-action-armature-switch-direction-desktop.py", "sha256": "ee29b85c9ff1f49ad3bd731f0996ba351a82a087b636899c1ef00d6db175b87e"}, + "webChecker": {"path": "tools/web/check-generated-gap.mjs", "sha256": "681279e274ccc7edb1956fb0ca86e1e6e6217fdbc7c0633c82f78f5c3481f830"}, + "reader": {"path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "9c0af422cc14634979497e2c8585e945a8402ab9f30b182d882da46786a1a711"}, + "nativeStub": {"path": "web/engine/web_engine_native_reader_stub.cpp", "sha256": "2a1526e08cf446bb23a91c8c2ae799db38a0aeed0a809a15ead427780600481a"}, + "wasm": {"path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "aa26c3b422e79ff84557245dc8d5870125f237aa365ac7ebdc727c2d0b83f615"}, + "wasmPublic": {"path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "aa26c3b422e79ff84557245dc8d5870125f237aa365ac7ebdc727c2d0b83f615"}, + "wasmJs": {"path": "web/app/src/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "wasmJsPublic": {"path": "web/app/public/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "desktopReport": {"path": "tests/golden/M16-GAP-00262/armature-switch-direction-desktop-report.json", "sha256": "b354e79b081ed5a42edafb0d2ff7c2811b3793b06997ffd493cb0412c10637ac"}, + "webReport": {"path": "tests/golden/M16-GAP-00262/armature-switch-direction-local-exact-report.json", "sha256": "a70785bfc13f65f94e22747c67eff0b4a07b0aa3afbaa999a5f39ab706769cda"}, + "status": {"path": "docs/status/M16-GAP-00262.md", "sha256": "011e5786081b22f6e706f3efdb9e7ce3d2422ab499be32ab7875d50986e26e3e"}, + "taskContext": {"path": "tests/golden/M16-GAP-00262/task-context.json", "sha256": "60148b63a69b0e197dcde3f81e322335806a7e9bd2f2a33c7dee44daac2da996"} + }, + "nextTask": "M16-GAP-00263" +} diff --git a/tests/golden/M16-GAP-00262/task-context.json b/tests/golden/M16-GAP-00262/task-context.json new file mode 100644 index 00000000..fd79ede9 --- /dev/null +++ b/tests/golden/M16-GAP-00262/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00262", + "parentTask": "M16-GAP-00261", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.switch_direction data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.switch_direction", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00262.py -- tests/files/web/generated/M16-GAP-00262-operator-armature.switch_direction.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00262", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00262" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00262.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2219, + "contextRemainingTokens": 553 + }, + "source": { + "bytes": 7685, + "tokens": 1923 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00262.py", + "bytes": 1278, + "tokens": 320 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00262-operator-armature.switch_direction.blend", + "bytes": 86409, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 240371, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 779789, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00262/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00262.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00262/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1278, + "tokens": 320 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00263", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00262.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00261/manifest.json", + "parentStatus": "docs/status/M16-GAP-00261.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00262.md", + "tests/golden/M16-GAP-00261/manifest.json", + "docs/status/M16-GAP-00261.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00261", + "parentTask": "M16-GAP-00260", + "status": "done", + "nextTask": "M16-GAP-00262", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00261 Status", + "status: done", + "task: armature.subdivide operator LOCAL_EXACT slice", + "updated: 2026-08-23 America/New_York", + "scope:", + "- The fixture contains one selected length-1 bone and one unrelated unselected", + " bone. Blender desktop runs `ARMATURE_OT_subdivide(number_cuts=1)`, producing", + " two half-length pieces and preserving the result through save/reopen." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1814, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 454 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2495, + "lines": 47, + "tokens": 624 + }, + { + "path": "docs/tasks/M16-GAP-00262.md", + "bytes": 1814, + "lines": 38, + "tokens": 454 + }, + { + "path": "tests/golden/M16-GAP-00261/manifest.json", + "bytes": 2662, + "lines": 29, + "tokens": 666 + }, + { + "path": "docs/status/M16-GAP-00261.md", + "bytes": 714, + "lines": 21, + "tokens": 179 + } + ], + "sourceTokens": 1923, + "evidenceFiles": 1, + "evidenceBytes": 1278, + "evidenceTokens": 320, + "totalTokens": 2243, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3267, + "serializedContextTokens": 758, + "withinBudget": true + } +} diff --git a/tests/golden/M16-GAP-00263/armature-symmetrize-desktop-report.json b/tests/golden/M16-GAP-00263/armature-symmetrize-desktop-report.json new file mode 100644 index 00000000..90992d34 --- /dev/null +++ b/tests/golden/M16-GAP-00263/armature-symmetrize-desktop-report.json @@ -0,0 +1,132 @@ +{ + "after": { + "activeBone": "WebGapArmatureSymmetrizeSource.R", + "armature": "WebGapArmatureSymmetrizeArmature", + "bones": [ + { + "connected": false, + "head": [ + 1.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSymmetrizeSource.L", + "parent": null, + "selected": false, + "tail": [ + 1.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + -3.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSymmetrizeOther", + "parent": null, + "selected": false, + "tail": [ + -3.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + -1.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSymmetrizeSource.R", + "parent": null, + "selected": true, + "tail": [ + -1.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureSymmetrizeObject" + }, + "before": { + "activeBone": "WebGapArmatureSymmetrizeSource.R", + "armature": "WebGapArmatureSymmetrizeArmature", + "bones": [ + { + "connected": false, + "head": [ + 1.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSymmetrizeSource.L", + "parent": null, + "selected": false, + "tail": [ + 1.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + -3.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSymmetrizeOther", + "parent": null, + "selected": false, + "tail": [ + -3.0, + 1.0, + 0.0 + ] + }, + { + "connected": false, + "head": [ + -1.0, + 0.0, + 0.0 + ], + "hidden": false, + "name": "WebGapArmatureSymmetrizeSource.R", + "parent": null, + "selected": true, + "tail": [ + -1.0, + 1.0, + 0.0 + ] + } + ], + "object": "WebGapArmatureSymmetrizeObject" + }, + "blenderVersion": "5.2.0 LTS", + "direction": "NEGATIVE_X", + "fixture": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/generated/M16-GAP-00263-operator-armature.symmetrize.blend", + "fixtureSha256": "fa490213eee2cd604d52d435cf446cdaa37ef882602147893c9f9f999cd43f2b", + "mainMutation": "MIRRORED_BONE_ALREADY_PRESENT", + "mirroredBone": "WebGapArmatureSymmetrizeSource.R", + "operation": "ARMATURE_SYMMETRIZE_DESKTOP", + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "otherBone": "WebGapArmatureSymmetrizeOther", + "poll": true, + "saveReopen": "EXACT", + "schemaVersion": 1, + "sourceBone": "WebGapArmatureSymmetrizeSource.L", + "task": "M16-GAP-00263" +} diff --git a/tests/golden/M16-GAP-00263/armature-symmetrize-local-exact-report.json b/tests/golden/M16-GAP-00263/armature-symmetrize-local-exact-report.json new file mode 100644 index 00000000..5158d502 --- /dev/null +++ b/tests/golden/M16-GAP-00263/armature-symmetrize-local-exact-report.json @@ -0,0 +1,56 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00263", + "operation": "ARMATURE_SYMMETRIZE_LOCAL_EXACT", + "fixture": { + "path": "tests/files/web/generated/M16-GAP-00263-operator-armature.symmetrize.blend", + "sha256": "fa490213eee2cd604d52d435cf446cdaa37ef882602147893c9f9f999cd43f2b" + }, + "desktop": { + "status": "EXACT", + "report": "tests/golden/M16-GAP-00263/armature-symmetrize-desktop-report.json", + "saveReopen": "EXACT", + "poll": true, + "operatorStatus": "SKIPPED_ALREADY_APPLIED", + "mainMutation": "MIRRORED_BONE_ALREADY_PRESENT", + "direction": "NEGATIVE_X", + "sourceBone": "WebGapArmatureSymmetrizeSource.L", + "mirroredBone": "WebGapArmatureSymmetrizeSource.R", + "otherBone": "WebGapArmatureSymmetrizeOther" + }, + "wasm": { + "status": "EXACT", + "armatureId": "armature:WebGapArmatureSymmetrizeArmature", + "sourceBoneId": "bone:armature:WebGapArmatureSymmetrizeArmature:WebGapArmatureSymmetrizeSource.L", + "mirroredBoneId": "bone:armature:WebGapArmatureSymmetrizeArmature:WebGapArmatureSymmetrizeSource.R", + "otherBoneId": "bone:armature:WebGapArmatureSymmetrizeArmature:WebGapArmatureSymmetrizeOther", + "sourceSelected": false, + "mirroredSelected": true, + "otherSelected": false, + "sourceHead": [ + 1, + 0, + 0 + ], + "sourceTail": [ + 1, + 1, + 0 + ], + "mirroredHead": [ + -1, + 0, + 0 + ], + "mirroredTail": [ + -1, + 1, + 0 + ] + }, + "saveReopen": "EXACT", + "negative": { + "malformedBlend": "REJECTED_WITHOUT_MAIN_MUTATION" + }, + "nextTask": "M16-GAP-00264" +} diff --git a/tests/golden/M16-GAP-00263/manifest.json b/tests/golden/M16-GAP-00263/manifest.json new file mode 100644 index 00000000..38c88740 --- /dev/null +++ b/tests/golden/M16-GAP-00263/manifest.json @@ -0,0 +1,28 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00263", + "parentTask": "M16-GAP-00262", + "enablingTask": false, + "parityStateChange": true, + "runtime": "BLENDER_5_2_LOCAL_EXACT", + "operation": "ARMATURE_SYMMETRIZE_LOCAL_EXACT", + "status": "done", + "artifacts": { + "parentManifest": {"path": "tests/golden/M16-GAP-00262/manifest.json", "sha256": "c03367b4246808543d0ecce65f005b8be03d7cb72610e7c1e07ff0273a2cfffd"}, + "fixture": {"path": "tests/files/web/generated/M16-GAP-00263-operator-armature.symmetrize.blend", "sha256": "fa490213eee2cd604d52d435cf446cdaa37ef882602147893c9f9f999cd43f2b"}, + "generator": {"path": "tools/web/generated/M16-GAP-00263.py", "sha256": "d2c2558f53a666ae73e4074fcf6c9db8d39dd7fb3de65537e66c17a70533ff70"}, + "desktopChecker": {"path": "tools/web/check-action-armature-symmetrize-desktop.py", "sha256": "1b84a01bdacb1b66952822b609144acaa3638aee86b4f6999df37575478a148b"}, + "webChecker": {"path": "tools/web/check-generated-gap.mjs", "sha256": "93e678975345b52f3395ab78356fce1219cd8c8f7db1d0804d872c8055107359"}, + "reader": {"path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "sha256": "9c0af422cc14634979497e2c8585e945a8402ab9f30b182d882da46786a1a711"}, + "nativeStub": {"path": "web/engine/web_engine_native_reader_stub.cpp", "sha256": "2a1526e08cf446bb23a91c8c2ae799db38a0aeed0a809a15ead427780600481a"}, + "wasm": {"path": "web/app/src/vendor/blender/web_engine.wasm", "sha256": "aa26c3b422e79ff84557245dc8d5870125f237aa365ac7ebdc727c2d0b83f615"}, + "wasmPublic": {"path": "web/app/public/vendor/blender/web_engine.wasm", "sha256": "aa26c3b422e79ff84557245dc8d5870125f237aa365ac7ebdc727c2d0b83f615"}, + "wasmJs": {"path": "web/app/src/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "wasmJsPublic": {"path": "web/app/public/vendor/blender/web_engine.js", "sha256": "2263ccecdf7193aeb8508119accfe01c65fa991124969e0e7ede7b3af3057b35"}, + "desktopReport": {"path": "tests/golden/M16-GAP-00263/armature-symmetrize-desktop-report.json", "sha256": "2ca4f83737867b62fd8c4b42bc6092a59178baa4a18f8bc192764c859d1e5c88"}, + "webReport": {"path": "tests/golden/M16-GAP-00263/armature-symmetrize-local-exact-report.json", "sha256": "1dbef4a312f55198108fcdcab216e0739f08c237a19084e28b21a63f53f9dab7"}, + "status": {"path": "docs/status/M16-GAP-00263.md", "sha256": "cd501a7510dd967be05d259465ae7bc9a2144122770b95cf951627e10341559d"}, + "taskContext": {"path": "tests/golden/M16-GAP-00263/task-context.json", "sha256": "61576b4aa53a9fe9c2eb5ff564a47ac218343ba32fcccd00322d4d9a1420d9c7"} + }, + "nextTask": "M16-GAP-00264" +} diff --git a/tests/golden/M16-GAP-00263/task-context.json b/tests/golden/M16-GAP-00263/task-context.json new file mode 100644 index 00000000..94122c8d --- /dev/null +++ b/tests/golden/M16-GAP-00263/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "M16-GAP-00263", + "parentTask": "M16-GAP-00262", + "status": "in_progress", + "goal": "Make the same minimal fixture produce observable operator:armature.symmetrize data in Blender desktop and WASM/Main, with save/reopen stability. Change only this gap; do not expand to other data-blocks, editors, or browsers.", + "scope": { + "gap": "operator:armature.symmetrize", + "ownerFamily": "OPERATOR", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_5.2.0/bin/blender -b --factory-startup --python tools/web/generated/M16-GAP-00263.py -- tests/files/web/generated/M16-GAP-00263-operator-armature.symmetrize.blend", + "npm --prefix web run test:generated-gap -- --task M16-GAP-00263", + "node tools/web/check-generated-gap.mjs --task M16-GAP-00263" + ], + "inputPaths": [ + "tools/web/generated/M16-GAP-00263.py" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2198, + "contextRemainingTokens": 548 + }, + "source": { + "bytes": 7706, + "tokens": 1928 + }, + "selected": [ + { + "path": "tools/web/generated/M16-GAP-00263.py", + "bytes": 1437, + "tokens": 360 + } + ], + "excluded": [ + { + "path": "tests/files/web/generated/M16-GAP-00263-operator-armature.symmetrize.blend", + "bytes": 86394, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 240371, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-generated-gap.mjs", + "bytes": 784952, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M16-GAP-00263/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/M16-GAP-00263.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/M16-GAP-00263/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 1437, + "tokens": 360 + } + }, + "exitCriteria": [ + "desktop fixture evidence exists", + "WASM uses the same fixture", + "comparator passes", + "save/reopen preserves Main", + "manifest hashes all artifacts" + ], + "nextTask": "M16-GAP-00264", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/M16-GAP-00263.md", + "taskIndex": "tests/golden/M15-03A/task-index.json", + "parentManifest": "tests/golden/M16-GAP-00262/manifest.json", + "parentStatus": "docs/status/M16-GAP-00262.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/M16-GAP-00263.md", + "tests/golden/M16-GAP-00262/manifest.json", + "docs/status/M16-GAP-00262.md" + ], + "machineOnly": [ + "tests/golden/M15-03A/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": "M16-GAP-00262", + "parentTask": "M16-GAP-00261", + "status": "done", + "nextTask": "M16-GAP-00263", + "artifactCount": 15 + }, + "statusSummary": [ + "# M16-GAP-00262 Status", + "status: done", + "task: armature.switch_direction operator LOCAL_EXACT slice", + "updated: 2026-08-23 America/New_York", + "scope:", + "- The fixture contains a selected connected two-bone chain and an unrelated", + " unselected bone. Blender desktop runs `ARMATURE_OT_switch_direction`,", + " reversing the chain while preserving the result through save/reopen." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1784, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 38, + "taskTokens": 446 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2495, + "lines": 47, + "tokens": 624 + }, + { + "path": "docs/tasks/M16-GAP-00263.md", + "bytes": 1784, + "lines": 38, + "tokens": 446 + }, + { + "path": "tests/golden/M16-GAP-00262/manifest.json", + "bytes": 2697, + "lines": 29, + "tokens": 675 + }, + { + "path": "docs/status/M16-GAP-00262.md", + "bytes": 730, + "lines": 23, + "tokens": 183 + } + ], + "sourceTokens": 1928, + "evidenceFiles": 1, + "evidenceBytes": 1437, + "evidenceTokens": 360, + "totalTokens": 2288, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3312, + "serializedContextTokens": 753, + "withinBudget": true + } +} diff --git a/tools/web/.tmp-driver-button-ui-experiment.py b/tools/web/.tmp-driver-button-ui-experiment.py new file mode 100644 index 00000000..4c62fb11 --- /dev/null +++ b/tools/web/.tmp-driver-button-ui-experiment.py @@ -0,0 +1,65 @@ +import json +import pathlib +import sys + +import bpy + + +FIXTURE = pathlib.Path(sys.argv[sys.argv.index("--") + 1]).resolve() +REPORT = pathlib.Path(sys.argv[sys.argv.index("--") + 2]).resolve() +OUTPUT = pathlib.Path(sys.argv[sys.argv.index("--") + 3]).resolve() + + +class DriverButtonPanel(bpy.types.Panel): + bl_label = "Driver Button Experiment" + bl_idname = "WEBGAP_PT_driver_button_experiment" + bl_space_type = "PROPERTIES" + bl_region_type = "WINDOW" + bl_context = "object" + bl_order = -1000 + + def draw(self, context): + self.layout.prop(context.object, '["drive_target"]', text="drive_target") + + +bpy.utils.register_class(DriverButtonPanel) + + +def driver_report(obj): + if obj is None or obj.animation_data is None: + return [] + return [ + { + "path": curve.data_path, + "index": curve.array_index, + "expression": curve.driver.expression if curve.driver else "", + } + for curve in obj.animation_data.drivers + ] + + +def poll_driver(): + current = driver_report(obj) + if current: + REPORT.write_text(json.dumps({"drivers": current}, indent=2) + "\n", encoding="utf-8") + bpy.ops.wm.save_as_mainfile(filepath=str(OUTPUT), check_existing=False, compress=True) + return None + return 0.25 + + +bpy.ops.wm.open_mainfile(filepath=str(FIXTURE), load_ui=False) +obj = bpy.data.objects.get("WebGapAnimDriverButtonAddObject") + + +def setup_ui(): + window = bpy.context.window + if window is None: + return 0.25 + screen = window.screen + area = next(candidate for candidate in screen.areas if candidate.type == "PROPERTIES") + area.spaces.active.context = "OBJECT" + bpy.app.timers.register(poll_driver, first_interval=0.5) + return None + + +bpy.app.timers.register(setup_ui, first_interval=0.5) diff --git a/tools/web/__pycache__/generate-modifier-fixtures.cpython-313.pyc b/tools/web/__pycache__/generate-modifier-fixtures.cpython-313.pyc deleted file mode 100644 index 3f12ea1a..00000000 Binary files a/tools/web/__pycache__/generate-modifier-fixtures.cpython-313.pyc and /dev/null differ diff --git a/tools/web/__pycache__/generate-modifier-goldens.cpython-313.pyc b/tools/web/__pycache__/generate-modifier-goldens.cpython-313.pyc deleted file mode 100644 index 2aafa0d1..00000000 Binary files a/tools/web/__pycache__/generate-modifier-goldens.cpython-313.pyc and /dev/null differ diff --git a/tools/web/check-action-armature-align-desktop.py b/tools/web/check-action-armature-align-desktop.py new file mode 100644 index 00000000..c12a05a1 --- /dev/null +++ b/tools/web/check-action-armature-align-desktop.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureAlignArmature" +OBJECT_NAME = "WebGapArmatureAlignObject" +PARENT_NAME = "WebGapArmatureAlignParent" +CHILD_NAME = "WebGapArmatureAlignChild" + + +def vector(value): + return [round(float(component), 6) for component in value] + + +def state_report(): + armature = bpy.data.armatures.get(ARMATURE_NAME) + obj = bpy.data.objects.get(OBJECT_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.align fixture is missing") + bones = [] + for bone in armature.bones: + bones.append({ + "name": bone.name, + "parent": bone.parent.name if bone.parent else None, + "head": vector(bone.head_local), + "tail": vector(bone.tail_local), + }) + bones.sort(key=lambda value: value["name"]) + return {"object": OBJECT_NAME, "armature": ARMATURE_NAME, "bones": bones} + + +def axes_aligned(state): + parent = next(bone for bone in state["bones"] if bone["name"] == PARENT_NAME) + child = next(bone for bone in state["bones"] if bone["name"] == CHILD_NAME) + axis = [parent["tail"][index] - parent["head"][index] for index in range(3)] + child_axis = [child["tail"][index] - child["head"][index] for index in range(3)] + cross = [axis[1] * child_axis[2] - axis[2] * child_axis[1], axis[2] * child_axis[0] - axis[0] * child_axis[2], axis[0] * child_axis[1] - axis[1] * child_axis[0]] + return max(abs(value) for value in cross) <= 1e-5 + + +def run_operator(): + bpy.context.view_layer.objects.active = bpy.data.objects[OBJECT_NAME] + bpy.data.objects[OBJECT_NAME].select_set(True) + if bpy.context.object.mode != "EDIT": + bpy.ops.object.mode_set(mode="EDIT") + armature = bpy.data.armatures[ARMATURE_NAME] + parent = armature.edit_bones[PARENT_NAME] + child = armature.edit_bones[CHILD_NAME] + parent.select = True + child.select = True + armature.bones.active = armature.bones[PARENT_NAME] + poll = bool(bpy.ops.armature.align.poll()) + if not poll: + raise RuntimeError("ARMATURE_OT_align poll failed") + result = bpy.ops.armature.align() + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_align returned {result}") + bpy.ops.object.mode_set(mode="OBJECT") + return poll, result + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --factory-startup --python check-action-armature-align-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + before_child = next(bone for bone in before["bones"] if bone["name"] == CHILD_NAME) + poll, _result = run_operator() + after = state_report() + already_aligned = axes_aligned(before) + parent = next(bone for bone in after["bones"] if bone["name"] == PARENT_NAME) + child = next(bone for bone in after["bones"] if bone["name"] == CHILD_NAME) + if child["parent"] is not None or child["head"] != before_child["head"]: + raise RuntimeError(f"armature.align changed unexpected parent/head state: {before} -> {after}") + axis = [parent["tail"][index] - parent["head"][index] for index in range(3)] + aligned_axis = [child["tail"][index] - child["head"][index] for index in range(3)] + cross = [axis[1] * aligned_axis[2] - axis[2] * aligned_axis[1], axis[2] * aligned_axis[0] - axis[0] * aligned_axis[2], axis[0] * aligned_axis[1] - axis[1] * aligned_axis[0]] + if max(abs(value) for value in cross) > 1e-5: + raise RuntimeError(f"armature.align did not make child axis parallel: {before} -> {after}") + + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-align-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + raise RuntimeError(f"armature.align save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00215", + "operation": "ARMATURE_ALIGN_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "alreadyAligned": already_aligned, + "poll": poll, + "operatorStatus": "FINISHED", + "mainMutation": "CHILD_ALIGNED_TO_PARENT", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("armature-align-desktop-ok poll=true status=FINISHED mainMutation=child_aligned_to_parent saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-align-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-assign-to-collection-desktop.py b/tools/web/check-action-armature-assign-to-collection-desktop.py new file mode 100644 index 00000000..ad310b95 --- /dev/null +++ b/tools/web/check-action-armature-assign-to-collection-desktop.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureAssignArmature" +OBJECT_NAME = "WebGapArmatureAssignObject" +SOURCE_COLLECTION = "WebGapArmatureAssignSource" +TARGET_COLLECTION = "WebGapArmatureAssignTarget" +PARENT_NAME = "WebGapArmatureAssignParent" +CHILD_NAME = "WebGapArmatureAssignChild" + + +def state_report(): + armature = bpy.data.armatures.get(ARMATURE_NAME) + obj = bpy.data.objects.get(OBJECT_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.assign_to_collection fixture is missing") + collections = [] + for index, collection in enumerate(armature.collections): + collections.append({"name": collection.name, "index": index, "bones": sorted(bone.name for bone in collection.bones)}) + return {"object": OBJECT_NAME, "armature": ARMATURE_NAME, "collections": collections} + + +def run_operator(already_assigned): + bpy.context.view_layer.objects.active = bpy.data.objects[OBJECT_NAME] + bpy.data.objects[OBJECT_NAME].select_set(True) + if bpy.context.object.mode != "EDIT": + bpy.ops.object.mode_set(mode="EDIT") + armature = bpy.data.armatures[ARMATURE_NAME] + parent = armature.edit_bones[PARENT_NAME] + child = armature.edit_bones[CHILD_NAME] + bpy.ops.armature.select_all(action="DESELECT") + parent.select = False + child.select = True + child.select_head = True + child.select_tail = True + armature.bones.active = armature.bones[CHILD_NAME] + poll = bool(bpy.ops.armature.assign_to_collection.poll()) + if not poll: + raise RuntimeError("ARMATURE_OT_assign_to_collection poll failed") + if not already_assigned: + result = bpy.ops.armature.assign_to_collection(collection_index=1) + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_assign_to_collection returned {result}") + bpy.ops.object.mode_set(mode="OBJECT") + return poll + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --factory-startup --python check-action-armature-assign-to-collection-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + target_before = next(collection for collection in before["collections"] if collection["name"] == TARGET_COLLECTION) + already_assigned = CHILD_NAME in target_before["bones"] + poll = run_operator(already_assigned) + after = state_report() + target_after = next(collection for collection in after["collections"] if collection["name"] == TARGET_COLLECTION) + if CHILD_NAME not in target_after["bones"]: + raise RuntimeError(f"assign_to_collection did not assign child: {before} -> {after}") + + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-assign-collection-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + raise RuntimeError(f"armature.assign_to_collection save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00216", + "operation": "ARMATURE_ASSIGN_TO_COLLECTION_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "alreadyAssigned": already_assigned, + "poll": poll, + "operatorStatus": "FINISHED", + "mainMutation": "CHILD_ASSIGNED_TO_TARGET_COLLECTION", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("armature-assign-to-collection-desktop-ok poll=true status=FINISHED mainMutation=child_assigned_to_target_collection saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-assign-to-collection-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-autoside-names-desktop.py b/tools/web/check-action-armature-autoside-names-desktop.py new file mode 100644 index 00000000..2bc5e209 --- /dev/null +++ b/tools/web/check-action-armature-autoside-names-desktop.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureAutosideArmature" +OBJECT_NAME = "WebGapArmatureAutosideObject" +LEFT_NAME = "WebGapArmatureAutosideLeft" +RIGHT_NAME = "WebGapArmatureAutosideRight" +LEFT_RENAMED = f"{LEFT_NAME}.L" +RIGHT_RENAMED = f"{RIGHT_NAME}.R" + + +def vector(value): + return [round(float(component), 6) for component in value] + + +def state_report(): + armature = bpy.data.armatures.get(ARMATURE_NAME) + obj = bpy.data.objects.get(OBJECT_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.autoside_names fixture is missing") + bones = [ + {"name": bone.name, "head": vector(bone.head_local), "tail": vector(bone.tail_local)} + for bone in armature.bones + ] + bones.sort(key=lambda value: value["name"]) + return {"object": OBJECT_NAME, "armature": ARMATURE_NAME, "bones": bones} + + +def run_operator(before): + if {bone["name"] for bone in before["bones"]} == {LEFT_RENAMED, RIGHT_RENAMED}: + return True, False + if {bone["name"] for bone in before["bones"]} != {LEFT_NAME, RIGHT_NAME}: + raise RuntimeError(f"unexpected autoside_names input: {before}") + bpy.context.view_layer.objects.active = bpy.data.objects[OBJECT_NAME] + bpy.data.objects[OBJECT_NAME].select_set(True) + if bpy.context.object.mode != "EDIT": + bpy.ops.object.mode_set(mode="EDIT") + bpy.ops.armature.select_all(action="SELECT") + poll = bool(bpy.ops.armature.autoside_names.poll()) + if not poll: + raise RuntimeError("ARMATURE_OT_autoside_names poll failed") + result = bpy.ops.armature.autoside_names(type="XAXIS") + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_autoside_names returned {result}") + bpy.ops.object.mode_set(mode="OBJECT") + return poll, True + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --factory-startup --python check-action-armature-autoside-names-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + poll, changed = run_operator(before) + after = state_report() + names = {bone["name"] for bone in after["bones"]} + if names != {LEFT_RENAMED, RIGHT_RENAMED}: + raise RuntimeError(f"autoside_names did not produce expected suffixes: {before} -> {after}") + + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-autoside-names-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + raise RuntimeError(f"armature.autoside_names save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00217", + "operation": "ARMATURE_AUTOSIDE_NAMES_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "alreadyNamed": not changed, + "poll": poll, + "operatorStatus": "FINISHED" if changed else "SKIPPED_ALREADY_APPLIED", + "mainMutation": "BONES_AUTOSIDE_NAMED" if changed else "ALREADY_AUTOSIDE_NAMED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("armature-autoside-names-desktop-ok poll=true names=left-right saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-autoside-names-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-bone-primitive-add-desktop.py b/tools/web/check-action-armature-bone-primitive-add-desktop.py new file mode 100644 index 00000000..22a36fe6 --- /dev/null +++ b/tools/web/check-action-armature-bone-primitive-add-desktop.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmaturePrimitiveArmature" +OBJECT_NAME = "WebGapArmaturePrimitiveObject" +BONE_NAME = "WebGapArmaturePrimitiveBone" +CURSOR = [1.5, -2.0, 0.75] +LENGTH = 2.5 + + +def vector(value): + return [round(float(component), 6) for component in value] + + +def state_report(): + armature = bpy.data.armatures.get(ARMATURE_NAME) + obj = bpy.data.objects.get(OBJECT_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.bone_primitive_add fixture is missing") + bones = [ + { + "name": bone.name, + "head": vector(bone.head_local), + "tail": vector(bone.tail_local), + "useDeform": bool(bone.use_deform), + } + for bone in armature.bones + ] + bones.sort(key=lambda value: value["name"]) + return {"object": OBJECT_NAME, "armature": ARMATURE_NAME, "cursor": vector(bpy.context.scene.cursor.location), "bones": bones} + + +def run_operator(before): + names = {bone["name"] for bone in before["bones"]} + if names == {BONE_NAME}: + already_added = True + elif names: + raise RuntimeError(f"unexpected bone_primitive_add input: {before}") + else: + already_added = False + bpy.context.view_layer.objects.active = bpy.data.objects[OBJECT_NAME] + bpy.data.objects[OBJECT_NAME].select_set(True) + if bpy.context.object.mode != "EDIT": + bpy.ops.object.mode_set(mode="EDIT") + poll = bool(bpy.ops.armature.bone_primitive_add.poll()) + if not poll: + raise RuntimeError("ARMATURE_OT_bone_primitive_add poll failed") + if not already_added: + result = bpy.ops.armature.bone_primitive_add( + name=BONE_NAME, length=LENGTH, align="UP", space="OBJECT", use_deform=False + ) + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_bone_primitive_add returned {result}") + bpy.ops.object.mode_set(mode="OBJECT") + return poll, not already_added + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --factory-startup --python check-action-armature-bone-primitive-add-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + poll, changed = run_operator(before) + after = state_report() + if len(after["bones"]) != 1 or after["bones"][0]["name"] != BONE_NAME: + raise RuntimeError(f"bone_primitive_add did not create the expected bone: {before} -> {after}") + bone = after["bones"][0] + expected_head = CURSOR + expected_tail = [CURSOR[0], CURSOR[1], CURSOR[2] + LENGTH] + if bone["head"] != expected_head or bone["tail"] != expected_tail or bone["useDeform"]: + raise RuntimeError(f"bone_primitive_add produced unexpected data: {after}") + + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-bone-primitive-add-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + raise RuntimeError(f"armature.bone_primitive_add save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00218", + "operation": "ARMATURE_BONE_PRIMITIVE_ADD_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "alreadyAdded": not changed, + "poll": poll, + "operatorStatus": "FINISHED" if changed else "SKIPPED_ALREADY_APPLIED", + "mainMutation": "BONE_CREATED_AT_CURSOR" if changed else "ALREADY_BONE_CREATED_AT_CURSOR", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("armature-bone-primitive-add-desktop-ok poll=true bone=cursor saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-bone-primitive-add-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-calculate-roll-desktop.py b/tools/web/check-action-armature-calculate-roll-desktop.py new file mode 100644 index 00000000..88fb3a3b --- /dev/null +++ b/tools/web/check-action-armature-calculate-roll-desktop.py @@ -0,0 +1,126 @@ +#!/usr/bin/env python3 +import hashlib +import json +import math +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureCalculateRollArmature" +OBJECT_NAME = "WebGapArmatureCalculateRollObject" +BONE_NAME = "WebGapArmatureCalculateRollBone" +EXPECTED_ROLL = math.pi / 2.0 + + +def vector(value): + return [round(float(component), 6) for component in value] + + +def matrix_flat(value): + return [round(float(component), 6) for column in value for component in column] + + +def state_report(): + armature = bpy.data.armatures.get(ARMATURE_NAME) + obj = bpy.data.objects.get(OBJECT_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.calculate_roll fixture is missing") + bones = [ + { + "name": bone.name, + "head": vector(bone.head_local), + "tail": vector(bone.tail_local), + "matrix": matrix_flat(bone.matrix_local), + } + for bone in armature.bones + ] + bones.sort(key=lambda value: value["name"]) + return {"object": OBJECT_NAME, "armature": ARMATURE_NAME, "bones": bones} + + +def run_operator(before): + if [bone["name"] for bone in before["bones"]] != [BONE_NAME]: + raise RuntimeError(f"unexpected calculate_roll input: {before}") + bpy.context.view_layer.objects.active = bpy.data.objects[OBJECT_NAME] + bpy.data.objects[OBJECT_NAME].select_set(True) + if bpy.context.object.mode != "EDIT": + bpy.ops.object.mode_set(mode="EDIT") + armature = bpy.data.armatures[ARMATURE_NAME] + edit_bone = armature.edit_bones[BONE_NAME] + already_calculated = abs(abs(edit_bone.roll) - EXPECTED_ROLL) <= 1e-5 + edit_bone.select = True + armature.bones.active = armature.bones[BONE_NAME] + poll = bool(bpy.ops.armature.calculate_roll.poll()) + if not poll: + raise RuntimeError("ARMATURE_OT_calculate_roll poll failed") + if not already_calculated: + result = bpy.ops.armature.calculate_roll(type="GLOBAL_POS_X", axis_flip=False, axis_only=False) + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_calculate_roll returned {result}") + roll = float(edit_bone.roll) + bpy.ops.object.mode_set(mode="OBJECT") + return poll, not already_calculated, roll + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --factory-startup --python check-action-armature-calculate-roll-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + poll, changed, roll = run_operator(before) + after = state_report() + if len(after["bones"]) != 1 or after["bones"][0]["name"] != BONE_NAME: + raise RuntimeError(f"calculate_roll changed unexpected bones: {before} -> {after}") + if abs(abs(roll) - EXPECTED_ROLL) > 1e-5: + raise RuntimeError(f"calculate_roll did not produce the expected roll: {roll}") + expected_matrix = [0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0] + for actual, expected in zip(after["bones"][0]["matrix"], expected_matrix): + if abs(actual - expected) > 1e-5: + raise RuntimeError(f"calculate_roll matrix mismatch: {after}") + + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-calculate-roll-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + raise RuntimeError(f"armature.calculate_roll save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00219", + "operation": "ARMATURE_CALCULATE_ROLL_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "alreadyCalculated": not changed, + "roll": round(roll, 6), + "poll": poll, + "operatorStatus": "FINISHED" if changed else "SKIPPED_ALREADY_APPLIED", + "mainMutation": "ROLL_CALCULATED_GLOBAL_POS_X" if changed else "ALREADY_ROLL_CALCULATED_GLOBAL_POS_X", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("armature-calculate-roll-desktop-ok poll=true roll=global-pos-x saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-calculate-roll-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-click-extrude-desktop.py b/tools/web/check-action-armature-click-extrude-desktop.py new file mode 100644 index 00000000..13cebb8a --- /dev/null +++ b/tools/web/check-action-armature-click-extrude-desktop.py @@ -0,0 +1,134 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureClickExtrudeArmature" +OBJECT_NAME = "WebGapArmatureClickExtrudeObject" +BONE_NAME = "WebGapArmatureClickExtrudeBone" +CHILD_NAME = f"{BONE_NAME}.001" +CURSOR = [1.5, 2.0, 1.0] + + +def vector(value): + return [round(float(component), 6) for component in value] + + +def matrix_flat(value): + return [round(float(component), 6) for column in value for component in column] + + +def state_report(): + armature = bpy.data.armatures.get(ARMATURE_NAME) + obj = bpy.data.objects.get(OBJECT_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.click_extrude fixture is missing") + bones = [ + { + "name": bone.name, + "parent": bone.parent.name if bone.parent else None, + "head": vector(bone.head_local), + "tail": vector(bone.tail_local), + "headRaw": vector(bone.head), + "tailRaw": vector(bone.tail), + "useConnect": bool(bone.use_connect), + "matrix": matrix_flat(bone.matrix_local), + } + for bone in armature.bones + ] + bones.sort(key=lambda value: value["name"]) + return {"object": OBJECT_NAME, "armature": ARMATURE_NAME, "cursor": vector(bpy.context.scene.cursor.location), "bones": bones} + + +def run_operator(before): + names = {bone["name"] for bone in before["bones"]} + if names == {BONE_NAME, CHILD_NAME}: + already_extruded = True + elif names == {BONE_NAME}: + already_extruded = False + else: + raise RuntimeError(f"unexpected click_extrude input: {before}") + bpy.context.view_layer.objects.active = bpy.data.objects[OBJECT_NAME] + bpy.data.objects[OBJECT_NAME].select_set(True) + if bpy.context.object.mode != "EDIT": + bpy.ops.object.mode_set(mode="EDIT") + armature = bpy.data.armatures[ARMATURE_NAME] + edit_bone = armature.edit_bones[BONE_NAME] + edit_bone.select = True + edit_bone.select_tail = True + armature.edit_bones.active = edit_bone + poll = bool(bpy.ops.armature.click_extrude.poll()) + if not poll: + raise RuntimeError("ARMATURE_OT_click_extrude poll failed") + if not already_extruded: + result = bpy.ops.armature.click_extrude() + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_click_extrude returned {result}") + bpy.ops.object.mode_set(mode="OBJECT") + return poll, not already_extruded + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --factory-startup --python check-action-armature-click-extrude-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + poll, changed = run_operator(before) + after = state_report() + if len(after["bones"]) != 2: + raise RuntimeError(f"click_extrude did not create exactly one child bone: {before} -> {after}") + parent = next((bone for bone in after["bones"] if bone["name"] == BONE_NAME), None) + child = next((bone for bone in after["bones"] if bone["name"] == CHILD_NAME), None) + if parent is None or child is None: + raise RuntimeError(f"click_extrude produced unexpected bones: {after}") + expected_head = parent["tail"] + if child["parent"] != BONE_NAME or not child["useConnect"] or child["head"] != expected_head or child["tail"] != CURSOR: + raise RuntimeError(f"click_extrude produced unexpected child: {after}") + + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-click-extrude-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + raise RuntimeError(f"armature.click_extrude save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00220", + "operation": "ARMATURE_CLICK_EXTRUDE_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "alreadyExtruded": not changed, + "poll": poll, + "operatorStatus": "FINISHED" if changed else "SKIPPED_ALREADY_APPLIED", + "mainMutation": "CHILD_EXTRUDED_TO_CURSOR" if changed else "ALREADY_CHILD_EXTRUDED_TO_CURSOR", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("armature-click-extrude-desktop-ok poll=true child=cursor saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-click-extrude-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-collection-add-desktop.py b/tools/web/check-action-armature-collection-add-desktop.py new file mode 100644 index 00000000..a90ec20e --- /dev/null +++ b/tools/web/check-action-armature-collection-add-desktop.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureCollectionAddArmature" +OBJECT_NAME = "WebGapArmatureCollectionAddObject" +SOURCE_COLLECTION = "WebGapArmatureCollectionAddExisting" +NEW_COLLECTION = "Bones" +BONE_NAME = "WebGapArmatureCollectionAddBone" + + +def state_report(): + armature = bpy.data.armatures.get(ARMATURE_NAME) + obj = bpy.data.objects.get(OBJECT_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.collection_add fixture is missing") + collections = [] + for index, collection in enumerate(armature.collections): + collections.append({"name": collection.name, "index": index, "bones": sorted(bone.name for bone in collection.bones)}) + return {"object": OBJECT_NAME, "armature": ARMATURE_NAME, "activeIndex": armature.collections.active_index, "collections": collections} + + +def run_operator(already_added): + bpy.context.view_layer.objects.active = bpy.data.objects[OBJECT_NAME] + bpy.data.objects[OBJECT_NAME].select_set(True) + armature = bpy.data.armatures[ARMATURE_NAME] + if not already_added: + armature.collections.active_index = 0 + poll = bool(bpy.ops.armature.collection_add.poll()) + if not poll: + raise RuntimeError("ARMATURE_OT_collection_add poll failed") + if not already_added: + result = bpy.ops.armature.collection_add() + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_collection_add returned {result}") + return poll, not already_added + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --factory-startup --python check-action-armature-collection-add-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + names = {collection["name"] for collection in before["collections"]} + if names == {SOURCE_COLLECTION, NEW_COLLECTION}: + already_added = True + elif names == {SOURCE_COLLECTION}: + already_added = False + else: + raise RuntimeError(f"unexpected collection_add input: {before}") + poll, changed = run_operator(already_added) + after = state_report() + if len(after["collections"]) != 2: + raise RuntimeError(f"collection_add did not produce exactly two collections: {before} -> {after}") + source = next((collection for collection in after["collections"] if collection["name"] == SOURCE_COLLECTION), None) + added = next((collection for collection in after["collections"] if collection["name"] == NEW_COLLECTION), None) + if source is None or added is None or source["index"] != 0 or added["index"] != 1: + raise RuntimeError(f"collection_add produced unexpected collections: {after}") + if source["bones"] != [BONE_NAME] or added["bones"]: + raise RuntimeError(f"collection_add changed collection membership: {after}") + + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-collection-add-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + raise RuntimeError(f"armature.collection_add save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00221", + "operation": "ARMATURE_COLLECTION_ADD_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "alreadyAdded": not changed, + "poll": poll, + "operatorStatus": "FINISHED" if changed else "SKIPPED_ALREADY_APPLIED", + "mainMutation": "BONE_COLLECTION_ADDED" if changed else "ALREADY_BONE_COLLECTION_ADDED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("armature-collection-add-desktop-ok poll=true collection=Bones saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-collection-add-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-collection-assign-desktop.py b/tools/web/check-action-armature-collection-assign-desktop.py new file mode 100644 index 00000000..a8e2be15 --- /dev/null +++ b/tools/web/check-action-armature-collection-assign-desktop.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureCollectionAssignArmature" +OBJECT_NAME = "WebGapArmatureCollectionAssignObject" +SOURCE_COLLECTION = "WebGapArmatureCollectionAssignSource" +TARGET_COLLECTION = "WebGapArmatureCollectionAssignTarget" +BONE_NAME = "WebGapArmatureCollectionAssignBone" + + +def state_report(): + armature = bpy.data.armatures.get(ARMATURE_NAME) + obj = bpy.data.objects.get(OBJECT_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.collection_assign fixture is missing") + collections = [] + for index, collection in enumerate(armature.collections): + collections.append({"name": collection.name, "index": index, "bones": sorted(bone.name for bone in collection.bones)}) + return {"object": OBJECT_NAME, "armature": ARMATURE_NAME, "collections": collections} + + +def run_operator(already_assigned): + bpy.context.view_layer.objects.active = bpy.data.objects[OBJECT_NAME] + bpy.data.objects[OBJECT_NAME].select_set(True) + if bpy.context.object.mode != "EDIT": + bpy.ops.object.mode_set(mode="EDIT") + armature = bpy.data.armatures[ARMATURE_NAME] + edit_bone = armature.edit_bones[BONE_NAME] + bpy.ops.armature.select_all(action="DESELECT") + edit_bone.select = True + edit_bone.select_head = True + edit_bone.select_tail = True + armature.bones.active = armature.bones[BONE_NAME] + poll = bool(bpy.ops.armature.collection_assign.poll()) + if not poll: + raise RuntimeError("ARMATURE_OT_collection_assign poll failed") + if not already_assigned: + result = bpy.ops.armature.collection_assign(name=TARGET_COLLECTION) + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_collection_assign returned {result}") + bpy.ops.object.mode_set(mode="OBJECT") + return poll, not already_assigned + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --factory-startup --python check-action-armature-collection-assign-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + target_before = next((collection for collection in before["collections"] if collection["name"] == TARGET_COLLECTION), None) + source_before = next((collection for collection in before["collections"] if collection["name"] == SOURCE_COLLECTION), None) + if source_before is None or target_before is None or source_before["bones"] != [BONE_NAME]: + raise RuntimeError(f"unexpected collection_assign input: {before}") + already_assigned = BONE_NAME in target_before["bones"] + poll, changed = run_operator(already_assigned) + after = state_report() + source_after = next((collection for collection in after["collections"] if collection["name"] == SOURCE_COLLECTION), None) + target_after = next((collection for collection in after["collections"] if collection["name"] == TARGET_COLLECTION), None) + if source_after is None or target_after is None or BONE_NAME not in target_after["bones"]: + raise RuntimeError(f"collection_assign did not assign the bone: {before} -> {after}") + if BONE_NAME not in source_after["bones"]: + raise RuntimeError(f"collection_assign unexpectedly removed the source membership: {after}") + + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-collection-assign-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + raise RuntimeError(f"armature.collection_assign save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00222", + "operation": "ARMATURE_COLLECTION_ASSIGN_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "alreadyAssigned": already_assigned, + "poll": poll, + "operatorStatus": "FINISHED" if changed else "SKIPPED_ALREADY_APPLIED", + "mainMutation": "BONE_ASSIGNED_TO_TARGET_COLLECTION" if changed else "ALREADY_BONE_ASSIGNED_TO_TARGET_COLLECTION", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("armature-collection-assign-desktop-ok poll=true target=assigned saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-collection-assign-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-collection-create-assign-desktop.py b/tools/web/check-action-armature-collection-create-assign-desktop.py new file mode 100644 index 00000000..4b915e95 --- /dev/null +++ b/tools/web/check-action-armature-collection-create-assign-desktop.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureCollectionCreateAssignArmature" +OBJECT_NAME = "WebGapArmatureCollectionCreateAssignObject" +SOURCE_COLLECTION = "WebGapArmatureCollectionCreateAssignSource" +NEW_COLLECTION = "WebGapArmatureCollectionCreateAssignNew" +BONE_NAME = "WebGapArmatureCollectionCreateAssignBone" + + +def state_report(): + armature = bpy.data.armatures.get(ARMATURE_NAME) + obj = bpy.data.objects.get(OBJECT_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.collection_create_and_assign fixture is missing") + collections = [] + for index, collection in enumerate(armature.collections): + collections.append({"name": collection.name, "index": index, "bones": sorted(bone.name for bone in collection.bones)}) + return {"object": OBJECT_NAME, "armature": ARMATURE_NAME, "activeIndex": armature.collections.active_index, "collections": collections} + + +def run_operator(already_created): + bpy.context.view_layer.objects.active = bpy.data.objects[OBJECT_NAME] + bpy.data.objects[OBJECT_NAME].select_set(True) + if bpy.context.object.mode != "EDIT": + bpy.ops.object.mode_set(mode="EDIT") + armature = bpy.data.armatures[ARMATURE_NAME] + edit_bone = armature.edit_bones[BONE_NAME] + bpy.ops.armature.select_all(action="DESELECT") + edit_bone.select = True + edit_bone.select_head = True + edit_bone.select_tail = True + armature.bones.active = armature.bones[BONE_NAME] + poll = bool(bpy.ops.armature.collection_create_and_assign.poll()) + if not poll: + raise RuntimeError("ARMATURE_OT_collection_create_and_assign poll failed") + if not already_created: + result = bpy.ops.armature.collection_create_and_assign(name=NEW_COLLECTION) + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_collection_create_and_assign returned {result}") + bpy.ops.object.mode_set(mode="OBJECT") + return poll, not already_created + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --factory-startup --python check-action-armature-collection-create-assign-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + names = {collection["name"] for collection in before["collections"]} + if names == {SOURCE_COLLECTION, NEW_COLLECTION}: + already_created = True + elif names == {SOURCE_COLLECTION}: + already_created = False + else: + raise RuntimeError(f"unexpected collection_create_and_assign input: {before}") + poll, changed = run_operator(already_created) + after = state_report() + source = next((collection for collection in after["collections"] if collection["name"] == SOURCE_COLLECTION), None) + added = next((collection for collection in after["collections"] if collection["name"] == NEW_COLLECTION), None) + if source is None or added is None or added["bones"] != [BONE_NAME]: + raise RuntimeError(f"collection_create_and_assign produced unexpected collections: {after}") + if source["bones"] != [BONE_NAME]: + raise RuntimeError(f"collection_create_and_assign unexpectedly removed source membership: {after}") + if added["index"] != 1 or after["activeIndex"] != added["index"]: + raise RuntimeError(f"collection_create_and_assign did not activate the new collection: {after}") + + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-collection-create-assign-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + raise RuntimeError(f"armature.collection_create_and_assign save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00223", + "operation": "ARMATURE_COLLECTION_CREATE_AND_ASSIGN_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "alreadyCreated": already_created, + "poll": poll, + "operatorStatus": "FINISHED" if changed else "SKIPPED_ALREADY_APPLIED", + "mainMutation": "NEW_COLLECTION_CREATED_AND_BONE_ASSIGNED" if changed else "ALREADY_NEW_COLLECTION_CREATED_AND_BONE_ASSIGNED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("armature-collection-create-assign-desktop-ok poll=true collection=created-and-assigned saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-collection-create-assign-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-collection-deselect-desktop.py b/tools/web/check-action-armature-collection-deselect-desktop.py new file mode 100644 index 00000000..e2988851 --- /dev/null +++ b/tools/web/check-action-armature-collection-deselect-desktop.py @@ -0,0 +1,141 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureCollectionDeselectArmature" +OBJECT_NAME = "WebGapArmatureCollectionDeselectObject" +ACTIVE_COLLECTION = "WebGapArmatureCollectionDeselectActive" +OTHER_COLLECTION = "WebGapArmatureCollectionDeselectOther" +ACTIVE_BONE = "WebGapArmatureCollectionDeselectActiveBone" +OTHER_BONE = "WebGapArmatureCollectionDeselectOtherBone" + + +def state_report(): + armature = bpy.data.armatures.get(ARMATURE_NAME) + obj = bpy.data.objects.get(OBJECT_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.collection_deselect fixture is missing") + was_edit_mode = obj.mode == "EDIT" + if not was_edit_mode: + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + bones = [] + for bone in armature.edit_bones: + bones.append({"name": bone.name, "selected": bool(bone.select)}) + if not was_edit_mode: + bpy.ops.object.mode_set(mode="OBJECT") + return { + "object": OBJECT_NAME, + "armature": ARMATURE_NAME, + "activeIndex": armature.collections.active_index, + "bones": bones, + } + + +def select_fixture_bones(): + bpy.context.view_layer.objects.active = bpy.data.objects[OBJECT_NAME] + bpy.data.objects[OBJECT_NAME].select_set(True) + if bpy.context.object.mode != "EDIT": + bpy.ops.object.mode_set(mode="EDIT") + armature = bpy.data.armatures[ARMATURE_NAME] + bpy.ops.armature.select_all(action="DESELECT") + for name in (ACTIVE_BONE, OTHER_BONE): + bone = armature.edit_bones[name] + bone.select = True + bone.select_head = True + bone.select_tail = True + armature.bones.active = armature.bones[ACTIVE_BONE] + + +def run_operator(already_deselected): + if already_deselected: + obj = bpy.data.objects[OBJECT_NAME] + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + if bpy.context.object.mode != "EDIT": + bpy.ops.object.mode_set(mode="EDIT") + armature = bpy.data.armatures[ARMATURE_NAME] + bpy.ops.armature.select_all(action="DESELECT") + other_bone = armature.edit_bones[OTHER_BONE] + other_bone.select = True + other_bone.select_head = True + other_bone.select_tail = True + else: + select_fixture_bones() + armature = bpy.data.armatures[ARMATURE_NAME] + poll = bool(bpy.ops.armature.collection_deselect.poll()) + if not poll: + raise RuntimeError("ARMATURE_OT_collection_deselect poll failed") + if not already_deselected: + result = bpy.ops.armature.collection_deselect() + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_collection_deselect returned {result}") + bpy.ops.object.mode_set(mode="OBJECT") + return poll, not already_deselected + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --factory-startup --python check-action-armature-collection-deselect-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + if before["activeIndex"] != 0: + raise RuntimeError(f"unexpected active collection: {before}") + already_deselected = all( + not bone["selected"] for bone in before["bones"] if bone["name"] == ACTIVE_BONE + ) + poll, changed = run_operator(already_deselected) + after = state_report() + selected = {bone["name"]: bone["selected"] for bone in after["bones"]} + if selected.get(ACTIVE_BONE) is not False or selected.get(OTHER_BONE) is not True: + raise RuntimeError(f"collection_deselect produced unexpected selection: {after}") + + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-collection-deselect-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + raise RuntimeError(f"armature.collection_deselect save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00224", + "operation": "ARMATURE_COLLECTION_DESELECT_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "alreadyDeselected": already_deselected, + "poll": poll, + "operatorStatus": "FINISHED" if changed else "SKIPPED_ALREADY_APPLIED", + "mainMutation": "ACTIVE_COLLECTION_BONES_DESELECTED" if changed else "ACTIVE_COLLECTION_BONES_ALREADY_DESELECTED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("armature-collection-deselect-desktop-ok poll=true activeCollection=deselected saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-collection-deselect-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-collection-move-desktop.py b/tools/web/check-action-armature-collection-move-desktop.py new file mode 100644 index 00000000..0763a8fc --- /dev/null +++ b/tools/web/check-action-armature-collection-move-desktop.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureCollectionMoveArmature" +OBJECT_NAME = "WebGapArmatureCollectionMoveObject" +FIRST_COLLECTION = "WebGapArmatureCollectionMoveFirst" +ACTIVE_COLLECTION = "WebGapArmatureCollectionMoveActive" +LAST_COLLECTION = "WebGapArmatureCollectionMoveLast" +FIRST_BONE = "WebGapArmatureCollectionMoveFirstBone" +ACTIVE_BONE = "WebGapArmatureCollectionMoveActiveBone" +LAST_BONE = "WebGapArmatureCollectionMoveLastBone" + + +def state_report(): + armature = bpy.data.armatures.get(ARMATURE_NAME) + obj = bpy.data.objects.get(OBJECT_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.collection_move fixture is missing") + collections = [] + for index, collection in enumerate(armature.collections): + collections.append({ + "name": collection.name, + "index": index, + "bones": sorted(bone.name for bone in collection.bones), + }) + return { + "object": OBJECT_NAME, + "armature": ARMATURE_NAME, + "activeIndex": armature.collections.active_index, + "collections": collections, + } + + +def run_operator(already_moved): + obj = bpy.data.objects[OBJECT_NAME] + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + armature = bpy.data.armatures[ARMATURE_NAME] + poll = bool(bpy.ops.armature.collection_move.poll()) + if not poll: + raise RuntimeError("ARMATURE_OT_collection_move poll failed") + if not already_moved: + result = bpy.ops.armature.collection_move(direction="UP") + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_collection_move returned {result}") + return poll, not already_moved + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --factory-startup --python check-action-armature-collection-move-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + before_names = [collection["name"] for collection in before["collections"]] + if before_names == [ACTIVE_COLLECTION, FIRST_COLLECTION, LAST_COLLECTION] and before["activeIndex"] == 0: + already_moved = True + elif before_names == [FIRST_COLLECTION, ACTIVE_COLLECTION, LAST_COLLECTION] and before["activeIndex"] == 1: + already_moved = False + else: + raise RuntimeError(f"unexpected collection_move input: {before}") + poll, changed = run_operator(already_moved) + after = state_report() + after_names = [collection["name"] for collection in after["collections"]] + if after_names != [ACTIVE_COLLECTION, FIRST_COLLECTION, LAST_COLLECTION] or after["activeIndex"] != 0: + raise RuntimeError(f"collection_move produced unexpected order: {after}") + expected_members = { + FIRST_COLLECTION: [FIRST_BONE], + ACTIVE_COLLECTION: [ACTIVE_BONE], + LAST_COLLECTION: [LAST_BONE], + } + actual_members = {collection["name"]: collection["bones"] for collection in after["collections"]} + if actual_members != expected_members: + raise RuntimeError(f"collection_move changed collection membership: {after}") + + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-collection-move-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + raise RuntimeError(f"armature.collection_move save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00225", + "operation": "ARMATURE_COLLECTION_MOVE_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "direction": "UP", + "alreadyMoved": already_moved, + "poll": poll, + "operatorStatus": "FINISHED" if changed else "SKIPPED_ALREADY_APPLIED", + "mainMutation": "ACTIVE_COLLECTION_MOVED_UP" if changed else "ACTIVE_COLLECTION_ALREADY_MOVED_UP", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("armature-collection-move-desktop-ok poll=true direction=up activeIndex=0 saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-collection-move-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-collection-remove-desktop.py b/tools/web/check-action-armature-collection-remove-desktop.py new file mode 100644 index 00000000..2a8e067c --- /dev/null +++ b/tools/web/check-action-armature-collection-remove-desktop.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureCollectionRemoveArmature" +OBJECT_NAME = "WebGapArmatureCollectionRemoveObject" +FIRST_COLLECTION = "WebGapArmatureCollectionRemoveFirst" +REMOVED_COLLECTION = "WebGapArmatureCollectionRemoveRemoved" +LAST_COLLECTION = "WebGapArmatureCollectionRemoveLast" +FIRST_BONE = "WebGapArmatureCollectionRemoveFirstBone" +REMOVED_BONE = "WebGapArmatureCollectionRemoveRemovedBone" +LAST_BONE = "WebGapArmatureCollectionRemoveLastBone" + + +def state_report(): + armature = bpy.data.armatures.get(ARMATURE_NAME) + obj = bpy.data.objects.get(OBJECT_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.collection_remove fixture is missing") + collections = [] + for index, collection in enumerate(armature.collections): + collections.append({ + "name": collection.name, + "index": index, + "bones": sorted(bone.name for bone in collection.bones), + }) + return { + "object": OBJECT_NAME, + "armature": ARMATURE_NAME, + "activeIndex": armature.collections.active_index, + "bones": sorted(bone.name for bone in armature.bones), + "collections": collections, + } + + +def run_operator(already_removed): + obj = bpy.data.objects[OBJECT_NAME] + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + poll = bool(bpy.ops.armature.collection_remove.poll()) + if not poll: + raise RuntimeError("ARMATURE_OT_collection_remove poll failed") + if not already_removed: + result = bpy.ops.armature.collection_remove() + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_collection_remove returned {result}") + return poll, not already_removed + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --factory-startup --python check-action-armature-collection-remove-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + before_names = [collection["name"] for collection in before["collections"]] + if before_names == [FIRST_COLLECTION, LAST_COLLECTION] and before["activeIndex"] == 1: + already_removed = True + elif before_names == [FIRST_COLLECTION, REMOVED_COLLECTION, LAST_COLLECTION] and before["activeIndex"] == 1: + already_removed = False + else: + raise RuntimeError(f"unexpected collection_remove input: {before}") + poll, changed = run_operator(already_removed) + after = state_report() + if [collection["name"] for collection in after["collections"]] != [FIRST_COLLECTION, LAST_COLLECTION]: + raise RuntimeError(f"collection_remove produced unexpected collections: {after}") + if after["activeIndex"] != 1 or after["bones"] != sorted([FIRST_BONE, REMOVED_BONE, LAST_BONE]): + raise RuntimeError(f"collection_remove changed active index or armature bones: {after}") + expected_members = {FIRST_COLLECTION: [FIRST_BONE], LAST_COLLECTION: [LAST_BONE]} + actual_members = {collection["name"]: collection["bones"] for collection in after["collections"]} + if actual_members != expected_members: + raise RuntimeError(f"collection_remove retained removed collection membership: {after}") + + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-collection-remove-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + raise RuntimeError(f"armature.collection_remove save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00226", + "operation": "ARMATURE_COLLECTION_REMOVE_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "alreadyRemoved": already_removed, + "poll": poll, + "operatorStatus": "FINISHED" if changed else "SKIPPED_ALREADY_APPLIED", + "mainMutation": "ACTIVE_COLLECTION_REMOVED" if changed else "ACTIVE_COLLECTION_ALREADY_REMOVED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("armature-collection-remove-desktop-ok poll=true removed=active saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-collection-remove-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-collection-remove-unused-desktop.py b/tools/web/check-action-armature-collection-remove-unused-desktop.py new file mode 100644 index 00000000..827f048c --- /dev/null +++ b/tools/web/check-action-armature-collection-remove-unused-desktop.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureCollectionRemoveUnusedArmature" +OBJECT_NAME = "WebGapArmatureCollectionRemoveUnusedObject" +FIRST_COLLECTION = "WebGapArmatureCollectionRemoveUnusedFirst" +UNUSED_FIRST_COLLECTION = "WebGapArmatureCollectionRemoveUnusedUnusedFirst" +LAST_COLLECTION = "WebGapArmatureCollectionRemoveUnusedLast" +UNUSED_LAST_COLLECTION = "WebGapArmatureCollectionRemoveUnusedUnusedLast" +FIRST_BONE = "WebGapArmatureCollectionRemoveUnusedFirstBone" +LAST_BONE = "WebGapArmatureCollectionRemoveUnusedLastBone" + + +def state_report(): + armature = bpy.data.armatures.get(ARMATURE_NAME) + obj = bpy.data.objects.get(OBJECT_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.collection_remove_unused fixture is missing") + collections = [] + for index, collection in enumerate(armature.collections): + collections.append( + { + "name": collection.name, + "index": index, + "bones": sorted(bone.name for bone in collection.bones), + } + ) + return { + "object": OBJECT_NAME, + "armature": ARMATURE_NAME, + "activeIndex": armature.collections.active_index, + "bones": sorted(bone.name for bone in armature.bones), + "collections": collections, + } + + +def run_operator(already_removed): + obj = bpy.data.objects[OBJECT_NAME] + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + poll = bool(bpy.ops.armature.collection_remove_unused.poll()) + if not poll: + raise RuntimeError("ARMATURE_OT_collection_remove_unused poll failed") + if not already_removed: + result = bpy.ops.armature.collection_remove_unused() + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_collection_remove_unused returned {result}") + return poll, not already_removed + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit( + "usage: blender -b --factory-startup --python check-action-armature-collection-remove-unused-desktop.py -- FIXTURE REPORT" + ) + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + before_names = [collection["name"] for collection in before["collections"]] + if before_names == [FIRST_COLLECTION, LAST_COLLECTION] and before["activeIndex"] == 1: + already_removed = True + elif before_names == [ + FIRST_COLLECTION, + UNUSED_FIRST_COLLECTION, + LAST_COLLECTION, + UNUSED_LAST_COLLECTION, + ] and before["activeIndex"] == 2: + already_removed = False + else: + raise RuntimeError(f"unexpected collection_remove_unused input: {before}") + poll, changed = run_operator(already_removed) + after = state_report() + if [collection["name"] for collection in after["collections"]] != [FIRST_COLLECTION, LAST_COLLECTION]: + raise RuntimeError(f"collection_remove_unused produced unexpected collections: {after}") + if after["activeIndex"] != 1 or after["bones"] != sorted([FIRST_BONE, LAST_BONE]): + raise RuntimeError(f"collection_remove_unused changed active index or armature bones: {after}") + expected_members = {FIRST_COLLECTION: [FIRST_BONE], LAST_COLLECTION: [LAST_BONE]} + actual_members = {collection["name"]: collection["bones"] for collection in after["collections"]} + if actual_members != expected_members: + raise RuntimeError(f"collection_remove_unused changed retained collection membership: {after}") + + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-collection-remove-unused-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + raise RuntimeError(f"armature.collection_remove_unused save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00227", + "operation": "ARMATURE_COLLECTION_REMOVE_UNUSED_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "removedCollections": [UNUSED_FIRST_COLLECTION, UNUSED_LAST_COLLECTION], + "alreadyRemoved": already_removed, + "poll": poll, + "operatorStatus": "FINISHED" if changed else "SKIPPED_ALREADY_APPLIED", + "mainMutation": "UNUSED_COLLECTIONS_REMOVED" if changed else "UNUSED_COLLECTIONS_ALREADY_REMOVED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("armature-collection-remove-unused-desktop-ok poll=true removed=2 saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-collection-remove-unused-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-collection-select-desktop.py b/tools/web/check-action-armature-collection-select-desktop.py new file mode 100644 index 00000000..c4bb9f6c --- /dev/null +++ b/tools/web/check-action-armature-collection-select-desktop.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureCollectionSelectArmature" +OBJECT_NAME = "WebGapArmatureCollectionSelectObject" +FIRST_COLLECTION = "WebGapArmatureCollectionSelectFirst" +ACTIVE_COLLECTION = "WebGapArmatureCollectionSelectActive" +LAST_COLLECTION = "WebGapArmatureCollectionSelectLast" +FIRST_BONE = "WebGapArmatureCollectionSelectFirstBone" +ACTIVE_BONE = "WebGapArmatureCollectionSelectActiveBone" +LAST_BONE = "WebGapArmatureCollectionSelectLastBone" + + +def ensure_edit_mode(): + obj = bpy.data.objects.get(OBJECT_NAME) + armature = bpy.data.armatures.get(ARMATURE_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.collection_select fixture is missing") + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + if obj.mode != "EDIT": + bpy.ops.object.mode_set(mode="EDIT") + return armature + + +def state_report(): + armature = ensure_edit_mode() + obj = bpy.data.objects[OBJECT_NAME] + bones = sorted(bone.name for bone in armature.edit_bones) + selected_bones = sorted(bone.name for bone in armature.edit_bones if bone.select) + bpy.ops.object.mode_set(mode="OBJECT") + collections = [] + for index, collection in enumerate(armature.collections): + collections.append( + { + "name": collection.name, + "index": index, + "bones": sorted(bone.name for bone in collection.bones), + } + ) + bpy.context.view_layer.objects.active = obj + bpy.ops.object.mode_set(mode="EDIT") + return { + "object": OBJECT_NAME, + "armature": ARMATURE_NAME, + "activeIndex": armature.collections.active_index, + "bones": bones, + "selectedBones": selected_bones, + "collections": collections, + } + + +def run_operator(already_selected): + ensure_edit_mode() + poll = bool(bpy.ops.armature.collection_select.poll()) + if not poll: + raise RuntimeError("ARMATURE_OT_collection_select poll failed") + if not already_selected: + result = bpy.ops.armature.collection_select() + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_collection_select returned {result}") + return poll, not already_selected + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit( + "usage: blender -b --factory-startup --python check-action-armature-collection-select-desktop.py -- FIXTURE REPORT" + ) + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + expected_collections = [FIRST_COLLECTION, ACTIVE_COLLECTION, LAST_COLLECTION] + if [collection["name"] for collection in before["collections"]] != expected_collections: + raise RuntimeError(f"unexpected collection_select collections: {before}") + if before["activeIndex"] != 1: + raise RuntimeError(f"unexpected collection_select active index: {before}") + selected_before = set(before["selectedBones"]) + if selected_before == {FIRST_BONE, ACTIVE_BONE}: + already_selected = True + elif selected_before == {FIRST_BONE}: + already_selected = False + else: + raise RuntimeError(f"unexpected collection_select selection input: {before}") + poll, changed = run_operator(already_selected) + after = state_report() + if after["activeIndex"] != 1 or after["selectedBones"] != sorted([FIRST_BONE, ACTIVE_BONE]): + raise RuntimeError(f"collection_select did not select the active collection: {after}") + expected_members = { + FIRST_COLLECTION: [FIRST_BONE], + ACTIVE_COLLECTION: [ACTIVE_BONE], + LAST_COLLECTION: [LAST_BONE], + } + actual_members = {collection["name"]: collection["bones"] for collection in after["collections"]} + if actual_members != expected_members: + raise RuntimeError(f"collection_select changed collection membership: {after}") + + bpy.ops.object.mode_set(mode="OBJECT") + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-collection-select-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + raise RuntimeError(f"armature.collection_select save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00228", + "operation": "ARMATURE_COLLECTION_SELECT_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "selectedCollection": ACTIVE_COLLECTION, + "alreadySelected": already_selected, + "poll": poll, + "operatorStatus": "FINISHED" if changed else "SKIPPED_ALREADY_APPLIED", + "mainMutation": "ACTIVE_COLLECTION_SELECTED" if changed else "ACTIVE_COLLECTION_ALREADY_SELECTED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("armature-collection-select-desktop-ok poll=true selected=active saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-collection-select-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-collection-show-all-desktop.py b/tools/web/check-action-armature-collection-show-all-desktop.py new file mode 100644 index 00000000..bdff186d --- /dev/null +++ b/tools/web/check-action-armature-collection-show-all-desktop.py @@ -0,0 +1,133 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureCollectionShowAllArmature" +OBJECT_NAME = "WebGapArmatureCollectionShowAllObject" +FIRST_COLLECTION = "WebGapArmatureCollectionShowAllFirst" +HIDDEN_COLLECTION = "WebGapArmatureCollectionShowAllHidden" +LAST_COLLECTION = "WebGapArmatureCollectionShowAllLast" +FIRST_BONE = "WebGapArmatureCollectionShowAllFirstBone" +HIDDEN_BONE = "WebGapArmatureCollectionShowAllHiddenBone" +LAST_BONE = "WebGapArmatureCollectionShowAllLastBone" + + +def ensure_object(): + obj = bpy.data.objects.get(OBJECT_NAME) + armature = bpy.data.armatures.get(ARMATURE_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.collection_show_all fixture is missing") + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + return armature + + +def state_report(): + armature = ensure_object() + collections = [] + for index, collection in enumerate(armature.collections): + collections.append( + { + "name": collection.name, + "index": index, + "visible": bool(collection.is_visible), + "bones": sorted(bone.name for bone in collection.bones), + } + ) + return { + "object": OBJECT_NAME, + "armature": ARMATURE_NAME, + "bones": sorted(bone.name for bone in armature.bones), + "collections": collections, + } + + +def run_operator(already_visible): + ensure_object() + poll = bool(bpy.ops.armature.collection_show_all.poll()) + if not poll: + raise RuntimeError("ARMATURE_OT_collection_show_all poll failed") + if not already_visible: + result = bpy.ops.armature.collection_show_all() + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_collection_show_all returned {result}") + return poll, not already_visible + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit( + "usage: blender -b --factory-startup --python check-action-armature-collection-show-all-desktop.py -- FIXTURE REPORT" + ) + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + expected_collections = [FIRST_COLLECTION, HIDDEN_COLLECTION, LAST_COLLECTION] + if [collection["name"] for collection in before["collections"]] != expected_collections: + raise RuntimeError(f"unexpected collection_show_all collections: {before}") + selected = {collection["name"] for collection in before["collections"] if collection["visible"]} + if selected == set(expected_collections): + already_visible = True + elif selected == {FIRST_COLLECTION, LAST_COLLECTION}: + already_visible = False + else: + raise RuntimeError(f"unexpected collection_show_all visibility input: {before}") + poll, changed = run_operator(already_visible) + after = state_report() + if not all(collection["visible"] for collection in after["collections"]): + raise RuntimeError(f"collection_show_all did not show every collection: {after}") + expected_members = { + FIRST_COLLECTION: [FIRST_BONE], + HIDDEN_COLLECTION: [HIDDEN_BONE], + LAST_COLLECTION: [LAST_BONE], + } + actual_members = {collection["name"]: collection["bones"] for collection in after["collections"]} + if actual_members != expected_members: + raise RuntimeError(f"collection_show_all changed collection membership: {after}") + + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-collection-show-all-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + raise RuntimeError(f"armature.collection_show_all save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00229", + "operation": "ARMATURE_COLLECTION_SHOW_ALL_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "poll": poll, + "operatorStatus": "FINISHED" if changed else "SKIPPED_ALREADY_APPLIED", + "mainMutation": "ALL_COLLECTIONS_VISIBLE" if changed else "ALL_COLLECTIONS_ALREADY_VISIBLE", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("armature-collection-show-all-desktop-ok poll=true visible=all saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-collection-show-all-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-collection-unassign-desktop.py b/tools/web/check-action-armature-collection-unassign-desktop.py new file mode 100644 index 00000000..6583dd63 --- /dev/null +++ b/tools/web/check-action-armature-collection-unassign-desktop.py @@ -0,0 +1,140 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureCollectionUnassignArmature" +OBJECT_NAME = "WebGapArmatureCollectionUnassignObject" +SOURCE_COLLECTION = "WebGapArmatureCollectionUnassignSource" +RETAINED_COLLECTION = "WebGapArmatureCollectionUnassignRetained" +BONE_NAME = "WebGapArmatureCollectionUnassignBone" + + +def ensure_edit_mode(): + obj = bpy.data.objects.get(OBJECT_NAME) + armature = bpy.data.armatures.get(ARMATURE_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.collection_unassign fixture is missing") + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + if obj.mode != "EDIT": + bpy.ops.object.mode_set(mode="EDIT") + return armature + + +def state_report(): + armature = ensure_edit_mode() + selected_bones = sorted(bone.name for bone in armature.edit_bones if bone.select) + bones = sorted(bone.name for bone in armature.edit_bones) + bpy.ops.object.mode_set(mode="OBJECT") + collections = [] + for index, collection in enumerate(armature.collections): + collections.append( + { + "name": collection.name, + "index": index, + "bones": sorted(bone.name for bone in collection.bones), + } + ) + bpy.context.view_layer.objects.active = bpy.data.objects[OBJECT_NAME] + bpy.ops.object.mode_set(mode="EDIT") + return { + "object": OBJECT_NAME, + "armature": ARMATURE_NAME, + "activeIndex": armature.collections.active_index, + "bones": bones, + "selectedBones": selected_bones, + "collections": collections, + } + + +def run_operator(already_unassigned): + armature = ensure_edit_mode() + poll = bool(bpy.ops.armature.collection_unassign.poll()) + if not poll: + raise RuntimeError("ARMATURE_OT_collection_unassign poll failed") + if not already_unassigned: + result = bpy.ops.armature.collection_unassign() + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_collection_unassign returned {result}") + return poll, not already_unassigned + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit( + "usage: blender -b --factory-startup --python check-action-armature-collection-unassign-desktop.py -- FIXTURE REPORT" + ) + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + expected_collections = [SOURCE_COLLECTION, RETAINED_COLLECTION] + if [collection["name"] for collection in before["collections"]] != expected_collections: + raise RuntimeError(f"unexpected collection_unassign collections: {before}") + if before["activeIndex"] != 0 or before["selectedBones"] != [BONE_NAME]: + raise RuntimeError(f"unexpected collection_unassign active/selection input: {before}") + source_before = before["collections"][0]["bones"] + retained_before = before["collections"][1]["bones"] + if source_before == [] and retained_before == [BONE_NAME]: + already_unassigned = True + elif source_before == [BONE_NAME] and retained_before == [BONE_NAME]: + already_unassigned = False + else: + raise RuntimeError(f"unexpected collection_unassign membership input: {before}") + poll, changed = run_operator(already_unassigned) + after = state_report() + if after["activeIndex"] != 0 or after["selectedBones"] != [BONE_NAME]: + raise RuntimeError(f"collection_unassign changed active or selection state: {after}") + actual_members = {collection["name"]: collection["bones"] for collection in after["collections"]} + expected_members = {SOURCE_COLLECTION: [], RETAINED_COLLECTION: [BONE_NAME]} + if actual_members != expected_members: + raise RuntimeError(f"collection_unassign did not remove only the active membership: {after}") + + bpy.ops.object.mode_set(mode="OBJECT") + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-collection-unassign-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + raise RuntimeError(f"armature.collection_unassign save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00230", + "operation": "ARMATURE_COLLECTION_UNASSIGN_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "activeCollection": SOURCE_COLLECTION, + "unassignedBone": BONE_NAME, + "poll": poll, + "operatorStatus": "FINISHED" if changed else "SKIPPED_ALREADY_APPLIED", + "mainMutation": "ACTIVE_COLLECTION_MEMBERSHIP_REMOVED" if changed else "ACTIVE_COLLECTION_ALREADY_EMPTY", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("armature-collection-unassign-desktop-ok poll=true source=empty retained=bone saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-collection-unassign-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-collection-unassign-named-desktop.py b/tools/web/check-action-armature-collection-unassign-named-desktop.py new file mode 100644 index 00000000..48068ce9 --- /dev/null +++ b/tools/web/check-action-armature-collection-unassign-named-desktop.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureCollectionUnassignNamedArmature" +OBJECT_NAME = "WebGapArmatureCollectionUnassignNamedObject" +SOURCE_COLLECTION = "WebGapArmatureCollectionUnassignNamedSource" +RETAINED_COLLECTION = "WebGapArmatureCollectionUnassignNamedRetained" +BONE_NAME = "WebGapArmatureCollectionUnassignNamedBone" + + +def ensure_edit_mode(): + obj = bpy.data.objects.get(OBJECT_NAME) + armature = bpy.data.armatures.get(ARMATURE_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.collection_unassign_named fixture is missing") + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + if obj.mode != "EDIT": + bpy.ops.object.mode_set(mode="EDIT") + return armature + + +def state_report(): + armature = ensure_edit_mode() + selected_bones = sorted(bone.name for bone in armature.edit_bones if bone.select) + bones = sorted(bone.name for bone in armature.edit_bones) + bpy.ops.object.mode_set(mode="OBJECT") + collections = [] + for index, collection in enumerate(armature.collections): + collections.append( + { + "name": collection.name, + "index": index, + "bones": sorted(bone.name for bone in collection.bones), + } + ) + bpy.context.view_layer.objects.active = bpy.data.objects[OBJECT_NAME] + bpy.ops.object.mode_set(mode="EDIT") + return { + "object": OBJECT_NAME, + "armature": ARMATURE_NAME, + "activeIndex": armature.collections.active_index, + "bones": bones, + "selectedBones": selected_bones, + "collections": collections, + } + + +def run_operator(already_unassigned): + ensure_edit_mode() + poll = bool(bpy.ops.armature.collection_unassign_named.poll()) + if not poll: + raise RuntimeError("ARMATURE_OT_collection_unassign_named poll failed") + if not already_unassigned: + result = bpy.ops.armature.collection_unassign_named( + name=SOURCE_COLLECTION, bone_name=BONE_NAME + ) + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_collection_unassign_named returned {result}") + return poll, not already_unassigned + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit( + "usage: blender -b --factory-startup --python check-action-armature-collection-unassign-named-desktop.py -- FIXTURE REPORT" + ) + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + expected_collections = [SOURCE_COLLECTION, RETAINED_COLLECTION] + if [collection["name"] for collection in before["collections"]] != expected_collections: + raise RuntimeError(f"unexpected collection_unassign_named collections: {before}") + if before["activeIndex"] != 1 or before["selectedBones"] != [BONE_NAME]: + raise RuntimeError(f"unexpected collection_unassign_named active/selection input: {before}") + source_before = before["collections"][0]["bones"] + retained_before = before["collections"][1]["bones"] + if source_before == [] and retained_before == [BONE_NAME]: + already_unassigned = True + elif source_before == [BONE_NAME] and retained_before == [BONE_NAME]: + already_unassigned = False + else: + raise RuntimeError(f"unexpected collection_unassign_named membership input: {before}") + poll, changed = run_operator(already_unassigned) + after = state_report() + if after["activeIndex"] != 1 or after["selectedBones"] != [BONE_NAME]: + raise RuntimeError(f"collection_unassign_named changed active or selection state: {after}") + actual_members = {collection["name"]: collection["bones"] for collection in after["collections"]} + expected_members = {SOURCE_COLLECTION: [], RETAINED_COLLECTION: [BONE_NAME]} + if actual_members != expected_members: + raise RuntimeError(f"collection_unassign_named did not remove only the named membership: {after}") + + bpy.ops.object.mode_set(mode="OBJECT") + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-collection-unassign-named-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + raise RuntimeError(f"armature.collection_unassign_named save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00231", + "operation": "ARMATURE_COLLECTION_UNASSIGN_NAMED_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "namedCollection": SOURCE_COLLECTION, + "activeCollection": RETAINED_COLLECTION, + "unassignedBone": BONE_NAME, + "poll": poll, + "operatorStatus": "FINISHED" if changed else "SKIPPED_ALREADY_APPLIED", + "mainMutation": "NAMED_COLLECTION_MEMBERSHIP_REMOVED" if changed else "NAMED_COLLECTION_ALREADY_EMPTY", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("armature-collection-unassign-named-desktop-ok poll=true named=source active=retained saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-collection-unassign-named-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-collection-unsolo-all-desktop.py b/tools/web/check-action-armature-collection-unsolo-all-desktop.py new file mode 100644 index 00000000..82203aae --- /dev/null +++ b/tools/web/check-action-armature-collection-unsolo-all-desktop.py @@ -0,0 +1,141 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureCollectionUnsoloAllArmature" +OBJECT_NAME = "WebGapArmatureCollectionUnsoloAllObject" +FIRST_COLLECTION = "WebGapArmatureCollectionUnsoloAllFirst" +SOLO_COLLECTION = "WebGapArmatureCollectionUnsoloAllSolo" +LAST_COLLECTION = "WebGapArmatureCollectionUnsoloAllLast" +FIRST_BONE = "WebGapArmatureCollectionUnsoloAllFirstBone" +SOLO_BONE = "WebGapArmatureCollectionUnsoloAllSoloBone" +LAST_BONE = "WebGapArmatureCollectionUnsoloAllLastBone" + + +def ensure_object(): + obj = bpy.data.objects.get(OBJECT_NAME) + armature = bpy.data.armatures.get(ARMATURE_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.collection_unsolo_all fixture is missing") + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + return armature + + +def state_report(): + armature = ensure_object() + collections = [] + for index, collection in enumerate(armature.collections): + collections.append( + { + "name": collection.name, + "index": index, + "visible": bool(collection.is_visible), + "solo": bool(collection.is_solo), + "bones": sorted(bone.name for bone in collection.bones), + } + ) + return { + "object": OBJECT_NAME, + "armature": ARMATURE_NAME, + "activeIndex": armature.collections.active_index, + "isSoloActive": bool(armature.collections.is_solo_active), + "bones": sorted(bone.name for bone in armature.bones), + "collections": collections, + } + + +def run_operator(already_unsolo): + ensure_object() + poll = bool(bpy.ops.armature.collection_unsolo_all.poll()) + if not already_unsolo: + if not poll: + raise RuntimeError("ARMATURE_OT_collection_unsolo_all poll failed") + result = bpy.ops.armature.collection_unsolo_all() + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_collection_unsolo_all returned {result}") + return poll, not already_unsolo + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit( + "usage: blender -b --factory-startup --python check-action-armature-collection-unsolo-all-desktop.py -- FIXTURE REPORT" + ) + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + expected_collections = [FIRST_COLLECTION, SOLO_COLLECTION, LAST_COLLECTION] + if [collection["name"] for collection in before["collections"]] != expected_collections: + raise RuntimeError(f"unexpected collection_unsolo_all collections: {before}") + if before["activeIndex"] != 1: + raise RuntimeError(f"unexpected collection_unsolo_all active index: {before}") + solo_names = {collection["name"] for collection in before["collections"] if collection["solo"]} + if solo_names == set(): + already_unsolo = True + elif solo_names == {SOLO_COLLECTION}: + already_unsolo = False + else: + raise RuntimeError(f"unexpected collection_unsolo_all solo input: {before}") + poll, changed = run_operator(already_unsolo) + after = state_report() + if after["isSoloActive"] or any(collection["solo"] for collection in after["collections"]): + raise RuntimeError(f"collection_unsolo_all did not clear every solo flag: {after}") + if after["activeIndex"] != 1: + raise RuntimeError(f"collection_unsolo_all changed active collection: {after}") + expected_members = { + FIRST_COLLECTION: [FIRST_BONE], + SOLO_COLLECTION: [SOLO_BONE], + LAST_COLLECTION: [LAST_BONE], + } + actual_members = {collection["name"]: collection["bones"] for collection in after["collections"]} + if actual_members != expected_members: + raise RuntimeError(f"collection_unsolo_all changed collection membership: {after}") + + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-collection-unsolo-all-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + raise RuntimeError(f"armature.collection_unsolo_all save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00232", + "operation": "ARMATURE_COLLECTION_UNSOLO_ALL_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "soloCollection": SOLO_COLLECTION, + "poll": poll, + "operatorStatus": "FINISHED" if changed else "SKIPPED_ALREADY_APPLIED", + "mainMutation": "ALL_COLLECTIONS_UNSOLO" if changed else "ALL_COLLECTIONS_ALREADY_UNSOLO", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("armature-collection-unsolo-all-desktop-ok solo=none saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-collection-unsolo-all-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-copy-bone-color-desktop.py b/tools/web/check-action-armature-copy-bone-color-desktop.py new file mode 100644 index 00000000..2d8ece82 --- /dev/null +++ b/tools/web/check-action-armature-copy-bone-color-desktop.py @@ -0,0 +1,137 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureCopyBoneColorArmature" +OBJECT_NAME = "WebGapArmatureCopyBoneColorObject" +SOURCE_BONE = "WebGapArmatureCopyBoneColorSource" +SELECTED_BONE = "WebGapArmatureCopyBoneColorSelected" +UNSELECTED_BONE = "WebGapArmatureCopyBoneColorUnselected" + + +def ensure_edit_mode(): + obj = bpy.data.objects.get(OBJECT_NAME) + armature = bpy.data.armatures.get(ARMATURE_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.copy_bone_color_to_selected fixture is missing") + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + if obj.mode != "EDIT": + bpy.ops.object.mode_set(mode="EDIT") + return armature + + +def color_report(bone): + custom = bone.color.custom + palette = bone.color.palette + palette_index = -1 if palette == "CUSTOM" else (0 if palette == "DEFAULT" else int(palette.removeprefix("THEME"))) + + def bytes_from_color(values): + return [round(value * 255.0) for value in values] + [255] + + return { + "name": bone.name, + "selected": bool(bone.select), + "palette": palette, + "paletteIndex": palette_index, + "normal": bytes_from_color(custom.normal), + "selectColor": bytes_from_color(custom.select), + "active": bytes_from_color(custom.active), + } + + +def state_report(): + armature = ensure_edit_mode() + return { + "object": OBJECT_NAME, + "armature": ARMATURE_NAME, + "activeBone": armature.edit_bones.active.name if armature.edit_bones.active else None, + "bones": [color_report(bone) for bone in armature.edit_bones], + } + + +def run_operator(already_applied): + armature = ensure_edit_mode() + poll = bool(bpy.ops.armature.copy_bone_color_to_selected.poll()) + if not poll: + raise RuntimeError("ARMATURE_OT_copy_bone_color_to_selected poll failed") + if not already_applied: + result = bpy.ops.armature.copy_bone_color_to_selected(bone_type="EDIT") + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_copy_bone_color_to_selected returned {result}") + return poll, not already_applied + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit( + "usage: blender -b --factory-startup --python check-action-armature-copy-bone-color-desktop.py -- FIXTURE REPORT" + ) + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + before_by_name = {bone["name"]: bone for bone in before["bones"]} + if before["activeBone"] != SOURCE_BONE or [bone["name"] for bone in before["bones"]] != [SOURCE_BONE, SELECTED_BONE, UNSELECTED_BONE]: + raise RuntimeError(f"unexpected copy_bone_color_to_selected input: {before}") + if not all(before_by_name[name]["selected"] for name in (SOURCE_BONE, SELECTED_BONE)) or before_by_name[UNSELECTED_BONE]["selected"]: + raise RuntimeError(f"unexpected copy_bone_color_to_selected selection: {before}") + already_applied = before_by_name[SELECTED_BONE]["paletteIndex"] == before_by_name[SOURCE_BONE]["paletteIndex"] and before_by_name[SELECTED_BONE]["normal"] == before_by_name[SOURCE_BONE]["normal"] + poll, changed = run_operator(already_applied) + after = state_report() + after_by_name = {bone["name"]: bone for bone in after["bones"]} + for name in (SOURCE_BONE, SELECTED_BONE): + if after_by_name[name]["paletteIndex"] != after_by_name[SOURCE_BONE]["paletteIndex"] or after_by_name[name]["normal"] != after_by_name[SOURCE_BONE]["normal"] or after_by_name[name]["selectColor"] != after_by_name[SOURCE_BONE]["selectColor"] or after_by_name[name]["active"] != after_by_name[SOURCE_BONE]["active"]: + raise RuntimeError(f"copy_bone_color_to_selected did not copy selected colors: {after}") + if after_by_name[UNSELECTED_BONE] != before_by_name[UNSELECTED_BONE]: + raise RuntimeError(f"copy_bone_color_to_selected changed unselected bone: {before} -> {after}") + + bpy.ops.object.mode_set(mode="OBJECT") + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-copy-bone-color-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + raise RuntimeError(f"armature.copy_bone_color_to_selected save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00233", + "operation": "ARMATURE_COPY_BONE_COLOR_TO_SELECTED_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "sourceBone": SOURCE_BONE, + "selectedDestination": SELECTED_BONE, + "unselectedDestination": UNSELECTED_BONE, + "poll": poll, + "operatorStatus": "FINISHED" if changed else "SKIPPED_ALREADY_APPLIED", + "mainMutation": "SELECTED_BONE_COLORS_COPIED" if changed else "SELECTED_BONE_COLORS_ALREADY_COPIED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("armature-copy-bone-color-desktop-ok selected=exact unselected=retained saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-copy-bone-color-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-delete-desktop.py b/tools/web/check-action-armature-delete-desktop.py new file mode 100644 index 00000000..15bd64e5 --- /dev/null +++ b/tools/web/check-action-armature-delete-desktop.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureDeleteArmature" +OBJECT_NAME = "WebGapArmatureDeleteObject" +KEEP_BONE = "WebGapArmatureDeleteKeep" +DELETE_BONE = "WebGapArmatureDeleteSelected" +RETAIN_BONE = "WebGapArmatureDeleteRetain" +EXPECTED_AFTER = [KEEP_BONE, RETAIN_BONE] + + +def ensure_edit_mode(): + obj = bpy.data.objects.get(OBJECT_NAME) + armature = bpy.data.armatures.get(ARMATURE_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.delete fixture is missing") + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + if obj.mode != "EDIT": + bpy.ops.object.mode_set(mode="EDIT") + return armature + + +def state_report(): + armature = ensure_edit_mode() + return { + "object": OBJECT_NAME, + "armature": ARMATURE_NAME, + "activeBone": armature.edit_bones.active.name if armature.edit_bones.active else None, + "bones": [ + { + "name": bone.name, + "selected": bool(bone.select), + "parent": bone.parent.name if bone.parent else None, + } + for bone in armature.edit_bones + ], + } + + +def run_operator(already_deleted): + ensure_edit_mode() + poll = bool(bpy.ops.armature.delete.poll()) + if not already_deleted: + if not poll: + raise RuntimeError("ARMATURE_OT_delete poll failed") + result = bpy.ops.armature.delete() + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_delete returned {result}") + return poll, not already_deleted + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit( + "usage: blender -b --factory-startup --python check-action-armature-delete-desktop.py -- FIXTURE REPORT" + ) + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + before_names = [bone["name"] for bone in before["bones"]] + if before_names == [KEEP_BONE, DELETE_BONE, RETAIN_BONE]: + if before["activeBone"] != DELETE_BONE or [bone["name"] for bone in before["bones"] if bone["selected"]] != [DELETE_BONE]: + raise RuntimeError(f"unexpected armature.delete input: {before}") + already_deleted = False + elif before_names == EXPECTED_AFTER: + if before["activeBone"] is not None or any(bone["selected"] for bone in before["bones"]): + raise RuntimeError(f"unexpected armature.delete completed state: {before}") + already_deleted = True + else: + raise RuntimeError(f"unexpected armature.delete bones: {before}") + + poll, changed = run_operator(already_deleted) + after = state_report() + if [bone["name"] for bone in after["bones"]] != EXPECTED_AFTER: + raise RuntimeError(f"armature.delete did not remove the selected bone: {after}") + if after["activeBone"] is not None or any(bone["selected"] for bone in after["bones"]): + raise RuntimeError(f"armature.delete left selection or active bone behind: {after}") + if any(bone["parent"] is not None for bone in after["bones"]): + raise RuntimeError(f"armature.delete changed unexpected parent state: {after}") + + bpy.ops.object.mode_set(mode="OBJECT") + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-delete-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + raise RuntimeError(f"armature.delete save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00234", + "operation": "ARMATURE_DELETE_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "deletedBone": DELETE_BONE, + "poll": poll, + "operatorStatus": "FINISHED" if changed else "SKIPPED_ALREADY_APPLIED", + "mainMutation": "SELECTED_BONE_DELETED" if changed else "SELECTED_BONE_ALREADY_DELETED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print(f"armature-delete-desktop-ok deleted={DELETE_BONE} saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-delete-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-dissolve-desktop.py b/tools/web/check-action-armature-dissolve-desktop.py new file mode 100644 index 00000000..bff0326a --- /dev/null +++ b/tools/web/check-action-armature-dissolve-desktop.py @@ -0,0 +1,153 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureDissolveArmature" +OBJECT_NAME = "WebGapArmatureDissolveObject" +ROOT_BONE = "WebGapArmatureDissolveRoot" +MIDDLE_BONE = "WebGapArmatureDissolveMiddle" +TIP_BONE = "WebGapArmatureDissolveTip" +OTHER_BONE = "WebGapArmatureDissolveOther" +EXPECTED_AFTER = [ROOT_BONE, OTHER_BONE] + + +def ensure_edit_mode(): + obj = bpy.data.objects.get(OBJECT_NAME) + armature = bpy.data.armatures.get(ARMATURE_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.dissolve fixture is missing") + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + if obj.mode != "EDIT": + bpy.ops.object.mode_set(mode="EDIT") + return armature + + +def bone_report(bone): + return { + "name": bone.name, + "selected": bool(bone.select), + "parent": bone.parent.name if bone.parent else None, + "connected": bool(bone.use_connect), + "head": [round(value, 6) for value in bone.head], + "tail": [round(value, 6) for value in bone.tail], + } + + +def state_report(): + armature = ensure_edit_mode() + return { + "object": OBJECT_NAME, + "armature": ARMATURE_NAME, + "activeBone": armature.edit_bones.active.name if armature.edit_bones.active else None, + "bones": [bone_report(bone) for bone in armature.edit_bones], + } + + +def run_operator(already_dissolved): + ensure_edit_mode() + poll = bool(bpy.ops.armature.dissolve.poll()) + if not already_dissolved: + if not poll: + raise RuntimeError("ARMATURE_OT_dissolve poll failed") + result = bpy.ops.armature.dissolve() + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_dissolve returned {result}") + return poll, not already_dissolved + + +def validate_input(before): + names = [bone["name"] for bone in before["bones"]] + if names == [ROOT_BONE, MIDDLE_BONE, TIP_BONE, OTHER_BONE]: + if before["activeBone"] != MIDDLE_BONE: + raise RuntimeError(f"unexpected armature.dissolve active bone: {before}") + selected = [bone["name"] for bone in before["bones"] if bone["selected"]] + if selected != [MIDDLE_BONE, TIP_BONE]: + raise RuntimeError(f"unexpected armature.dissolve selection: {before}") + if not all(bone["connected"] for bone in before["bones"][1:3]): + raise RuntimeError(f"unexpected armature.dissolve connections: {before}") + return False + if names == EXPECTED_AFTER: + if before["activeBone"] is not None: + raise RuntimeError(f"unexpected armature.dissolve completed active bone: {before}") + if any(bone["selected"] for bone in before["bones"]): + raise RuntimeError(f"unexpected armature.dissolve completed selection: {before}") + return True + raise RuntimeError(f"unexpected armature.dissolve bones: {before}") + + +def validate_after(after): + if [bone["name"] for bone in after["bones"]] != EXPECTED_AFTER: + raise RuntimeError(f"armature.dissolve did not remove the selected tip: {after}") + root, other = after["bones"] + if after["activeBone"] is not None or any(bone["selected"] for bone in after["bones"]): + raise RuntimeError(f"armature.dissolve left unexpected active or selection state: {after}") + if root["parent"] is not None or other["parent"] is not None or other["connected"]: + raise RuntimeError(f"armature.dissolve changed unexpected parent state: {after}") + if root["head"] != [0.0, 0.0, 0.0] or root["tail"] != [0.0, 3.0, 0.0]: + raise RuntimeError(f"armature.dissolve changed root geometry: {after}") + if other["head"] != [2.0, 0.0, 0.0] or other["tail"] != [2.0, 1.0, 0.0]: + raise RuntimeError(f"armature.dissolve changed the independent bone: {after}") + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit( + "usage: blender -b --factory-startup --python check-action-armature-dissolve-desktop.py -- FIXTURE REPORT" + ) + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + already_dissolved = validate_input(before) + poll, changed = run_operator(already_dissolved) + after = state_report() + validate_after(after) + + bpy.ops.object.mode_set(mode="OBJECT") + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-dissolve-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + raise RuntimeError(f"armature.dissolve save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00235", + "operation": "ARMATURE_DISSOLVE_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "dissolvedBone": TIP_BONE, + "poll": poll, + "operatorStatus": "FINISHED" if changed else "SKIPPED_ALREADY_APPLIED", + "mainMutation": "CONNECTED_TIP_DISSOLVED" if changed else "CONNECTED_TIP_ALREADY_DISSOLVED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print(f"armature-dissolve-desktop-ok dissolved={TIP_BONE} saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-dissolve-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-duplicate-desktop.py b/tools/web/check-action-armature-duplicate-desktop.py new file mode 100644 index 00000000..2eb19118 --- /dev/null +++ b/tools/web/check-action-armature-duplicate-desktop.py @@ -0,0 +1,158 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureDuplicateArmature" +OBJECT_NAME = "WebGapArmatureDuplicateObject" +SOURCE_BONE = "WebGapArmatureDuplicateSource" +OTHER_BONE = "WebGapArmatureDuplicateOther" +DUPLICATE_BONE = "WebGapArmatureDuplicateSource.001" +EXPECTED_AFTER = [SOURCE_BONE, OTHER_BONE, DUPLICATE_BONE] + + +def ensure_edit_mode(): + obj = bpy.data.objects.get(OBJECT_NAME) + armature = bpy.data.armatures.get(ARMATURE_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.duplicate fixture is missing") + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + if obj.mode != "EDIT": + bpy.ops.object.mode_set(mode="EDIT") + return armature + + +def bone_report(bone): + return { + "name": bone.name, + "selected": bool(bone.select), + "selectHead": bool(bone.select_head), + "selectTail": bool(bone.select_tail), + "parent": bone.parent.name if bone.parent else None, + "connected": bool(bone.use_connect), + "head": [round(value, 6) for value in bone.head], + "tail": [round(value, 6) for value in bone.tail], + } + + +def state_report(): + armature = ensure_edit_mode() + return { + "object": OBJECT_NAME, + "armature": ARMATURE_NAME, + "activeBone": armature.edit_bones.active.name if armature.edit_bones.active else None, + "bones": [bone_report(bone) for bone in armature.edit_bones], + } + + +def validate_input(before): + names = [bone["name"] for bone in before["bones"]] + if names == [SOURCE_BONE, OTHER_BONE]: + source, other = before["bones"] + if before["activeBone"] != SOURCE_BONE: + raise RuntimeError(f"unexpected armature.duplicate active bone: {before}") + if not source["selected"] or not source["selectHead"] or not source["selectTail"]: + raise RuntimeError(f"unexpected armature.duplicate source selection: {before}") + if other["selected"] or other["selectHead"] or other["selectTail"]: + raise RuntimeError(f"unexpected armature.duplicate other selection: {before}") + return False + if names == EXPECTED_AFTER: + if before["activeBone"] != DUPLICATE_BONE: + raise RuntimeError(f"unexpected armature.duplicate completed active bone: {before}") + selected = [bone["name"] for bone in before["bones"] if bone["selected"]] + if selected != [DUPLICATE_BONE]: + raise RuntimeError(f"unexpected armature.duplicate completed selection: {before}") + return True + raise RuntimeError(f"unexpected armature.duplicate bones: {before}") + + +def run_operator(already_duplicated): + ensure_edit_mode() + poll = bool(bpy.ops.armature.duplicate.poll()) + if not already_duplicated: + if not poll: + raise RuntimeError("ARMATURE_OT_duplicate poll failed") + result = bpy.ops.armature.duplicate() + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_duplicate returned {result}") + return poll, not already_duplicated + + +def validate_after(after): + if [bone["name"] for bone in after["bones"]] != EXPECTED_AFTER: + raise RuntimeError(f"armature.duplicate did not create the expected copy: {after}") + source, other, duplicate = after["bones"] + if after["activeBone"] != DUPLICATE_BONE: + raise RuntimeError(f"armature.duplicate active bone drift: {after}") + if source["selected"] or other["selected"] or not duplicate["selected"]: + raise RuntimeError(f"armature.duplicate selection drift: {after}") + if duplicate["parent"] is not None or duplicate["connected"]: + raise RuntimeError(f"armature.duplicate changed duplicate parent state: {after}") + if source["head"] != duplicate["head"] or source["tail"] != duplicate["tail"]: + raise RuntimeError(f"armature.duplicate geometry mismatch: {after}") + if other["head"] != [2.0, 0.0, 0.0] or other["tail"] != [2.0, 1.0, 0.0]: + raise RuntimeError(f"armature.duplicate changed independent bone: {after}") + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit( + "usage: blender -b --factory-startup --python check-action-armature-duplicate-desktop.py -- FIXTURE REPORT" + ) + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + already_duplicated = validate_input(before) + poll, changed = run_operator(already_duplicated) + after = state_report() + validate_after(after) + + bpy.ops.object.mode_set(mode="OBJECT") + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-duplicate-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + raise RuntimeError(f"armature.duplicate save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00236", + "operation": "ARMATURE_DUPLICATE_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "sourceBone": SOURCE_BONE, + "duplicateBone": DUPLICATE_BONE, + "poll": poll, + "operatorStatus": "FINISHED" if changed else "SKIPPED_ALREADY_APPLIED", + "mainMutation": "SELECTED_BONE_DUPLICATED" if changed else "SELECTED_BONE_ALREADY_DUPLICATED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print(f"armature-duplicate-desktop-ok duplicate={DUPLICATE_BONE} saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-duplicate-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-duplicate-move-desktop.py b/tools/web/check-action-armature-duplicate-move-desktop.py new file mode 100644 index 00000000..2f82deef --- /dev/null +++ b/tools/web/check-action-armature-duplicate-move-desktop.py @@ -0,0 +1,164 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureDuplicateMoveArmature" +OBJECT_NAME = "WebGapArmatureDuplicateMoveObject" +SOURCE_BONE = "WebGapArmatureDuplicateMoveSource" +OTHER_BONE = "WebGapArmatureDuplicateMoveOther" +DUPLICATE_BONE = "WebGapArmatureDuplicateMoveSource.001" +MOVE = [1.0, 2.0, 3.0] +EXPECTED_AFTER = [SOURCE_BONE, OTHER_BONE, DUPLICATE_BONE] + + +def ensure_edit_mode(): + obj = bpy.data.objects.get(OBJECT_NAME) + armature = bpy.data.armatures.get(ARMATURE_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.duplicate_move fixture is missing") + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + if obj.mode != "EDIT": + bpy.ops.object.mode_set(mode="EDIT") + return armature + + +def bone_report(bone): + return { + "name": bone.name, + "selected": bool(bone.select), + "selectHead": bool(bone.select_head), + "selectTail": bool(bone.select_tail), + "parent": bone.parent.name if bone.parent else None, + "connected": bool(bone.use_connect), + "head": [round(value, 6) for value in bone.head], + "tail": [round(value, 6) for value in bone.tail], + } + + +def state_report(): + armature = ensure_edit_mode() + return { + "object": OBJECT_NAME, + "armature": ARMATURE_NAME, + "activeBone": armature.edit_bones.active.name if armature.edit_bones.active else None, + "bones": [bone_report(bone) for bone in armature.edit_bones], + } + + +def validate_input(before): + names = [bone["name"] for bone in before["bones"]] + if names == [SOURCE_BONE, OTHER_BONE]: + source, other = before["bones"] + if before["activeBone"] != SOURCE_BONE: + raise RuntimeError(f"unexpected armature.duplicate_move active bone: {before}") + if not source["selected"] or not source["selectHead"] or not source["selectTail"]: + raise RuntimeError(f"unexpected armature.duplicate_move source selection: {before}") + if other["selected"] or other["selectHead"] or other["selectTail"]: + raise RuntimeError(f"unexpected armature.duplicate_move other selection: {before}") + return False + if names == EXPECTED_AFTER: + duplicate = before["bones"][2] + if before["activeBone"] != DUPLICATE_BONE or not duplicate["selected"]: + raise RuntimeError(f"unexpected armature.duplicate_move completed selection: {before}") + return True + raise RuntimeError(f"unexpected armature.duplicate_move bones: {before}") + + +def run_operator(already_moved): + ensure_edit_mode() + poll = bool(bpy.ops.armature.duplicate_move.poll()) + if not already_moved: + if not poll: + raise RuntimeError("ARMATURE_OT_duplicate_move poll failed") + result = bpy.ops.armature.duplicate_move( + TRANSFORM_OT_translate={"value": tuple(MOVE)} + ) + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_duplicate_move returned {result}") + return poll, not already_moved + + +def validate_after(after): + if [bone["name"] for bone in after["bones"]] != EXPECTED_AFTER: + raise RuntimeError(f"armature.duplicate_move did not create the expected copy: {after}") + source, other, duplicate = after["bones"] + if after["activeBone"] != DUPLICATE_BONE: + raise RuntimeError(f"armature.duplicate_move active bone drift: {after}") + if source["selected"] or other["selected"] or not duplicate["selected"]: + raise RuntimeError(f"armature.duplicate_move selection drift: {after}") + if duplicate["parent"] is not None or duplicate["connected"]: + raise RuntimeError(f"armature.duplicate_move changed duplicate parent state: {after}") + if duplicate["head"] != [MOVE[index] for index in range(3)]: + raise RuntimeError(f"armature.duplicate_move head translation mismatch: {after}") + if duplicate["tail"] != [MOVE[0], MOVE[1] + 1.0, MOVE[2]]: + raise RuntimeError(f"armature.duplicate_move tail translation mismatch: {after}") + if source["head"] != [0.0, 0.0, 0.0] or source["tail"] != [0.0, 1.0, 0.0]: + raise RuntimeError(f"armature.duplicate_move changed source geometry: {after}") + if other["head"] != [2.0, 0.0, 0.0] or other["tail"] != [2.0, 1.0, 0.0]: + raise RuntimeError(f"armature.duplicate_move changed independent bone: {after}") + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit( + "usage: blender -b --factory-startup --python check-action-armature-duplicate-move-desktop.py -- FIXTURE REPORT" + ) + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + already_moved = validate_input(before) + poll, changed = run_operator(already_moved) + after = state_report() + validate_after(after) + + bpy.ops.object.mode_set(mode="OBJECT") + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-duplicate-move-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + raise RuntimeError(f"armature.duplicate_move save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00237", + "operation": "ARMATURE_DUPLICATE_MOVE_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "sourceBone": SOURCE_BONE, + "duplicateBone": DUPLICATE_BONE, + "translation": MOVE, + "poll": poll, + "operatorStatus": "FINISHED" if changed else "SKIPPED_ALREADY_APPLIED", + "mainMutation": "SELECTED_BONE_DUPLICATED_AND_MOVED" if changed else "SELECTED_BONE_ALREADY_DUPLICATED_AND_MOVED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print(f"armature-duplicate-move-desktop-ok duplicate={DUPLICATE_BONE} translation={MOVE} saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-duplicate-move-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-duplicate-rename-desktop.py b/tools/web/check-action-armature-duplicate-rename-desktop.py new file mode 100644 index 00000000..09f2d25d --- /dev/null +++ b/tools/web/check-action-armature-duplicate-rename-desktop.py @@ -0,0 +1,158 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureDuplicateRenameArmature" +OBJECT_NAME = "WebGapArmatureDuplicateRenameObject" +SOURCE_BONE = "WebGapArmatureDuplicateRenameSource" +OTHER_BONE = "WebGapArmatureDuplicateRenameOther" +DUPLICATE_BONE = "WebGapArmatureDuplicateRenameCopy" +EXPECTED_AFTER = [SOURCE_BONE, OTHER_BONE, DUPLICATE_BONE] + + +def ensure_edit_mode(): + obj = bpy.data.objects.get(OBJECT_NAME) + armature = bpy.data.armatures.get(ARMATURE_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.duplicate_rename fixture is missing") + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + if obj.mode != "EDIT": + bpy.ops.object.mode_set(mode="EDIT") + return armature + + +def bone_report(bone): + return { + "name": bone.name, + "selected": bool(bone.select), + "selectHead": bool(bone.select_head), + "selectTail": bool(bone.select_tail), + "parent": bone.parent.name if bone.parent else None, + "connected": bool(bone.use_connect), + "head": [round(value, 6) for value in bone.head], + "tail": [round(value, 6) for value in bone.tail], + } + + +def state_report(): + armature = ensure_edit_mode() + return { + "object": OBJECT_NAME, + "armature": ARMATURE_NAME, + "activeBone": armature.edit_bones.active.name if armature.edit_bones.active else None, + "bones": [bone_report(bone) for bone in armature.edit_bones], + } + + +def validate_input(before): + names = [bone["name"] for bone in before["bones"]] + if names == [SOURCE_BONE, OTHER_BONE]: + source, other = before["bones"] + if before["activeBone"] != SOURCE_BONE: + raise RuntimeError(f"unexpected armature.duplicate_rename active bone: {before}") + if not source["selected"] or not source["selectHead"] or not source["selectTail"]: + raise RuntimeError(f"unexpected armature.duplicate_rename source selection: {before}") + if other["selected"] or other["selectHead"] or other["selectTail"]: + raise RuntimeError(f"unexpected armature.duplicate_rename other selection: {before}") + return False + if names == EXPECTED_AFTER: + duplicate = before["bones"][2] + if before["activeBone"] != DUPLICATE_BONE or not duplicate["selected"]: + raise RuntimeError(f"unexpected armature.duplicate_rename completed selection: {before}") + return True + raise RuntimeError(f"unexpected armature.duplicate_rename bones: {before}") + + +def run_operator(already_renamed): + ensure_edit_mode() + poll = bool(bpy.ops.armature.duplicate_rename.poll()) + if not already_renamed: + if not poll: + raise RuntimeError("ARMATURE_OT_duplicate_rename poll failed") + result = bpy.ops.armature.duplicate_rename(search="Source", replace="Copy", do_flip_names=False) + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_duplicate_rename returned {result}") + return poll, not already_renamed + + +def validate_after(after): + if [bone["name"] for bone in after["bones"]] != EXPECTED_AFTER: + raise RuntimeError(f"armature.duplicate_rename did not create the expected copy: {after}") + source, other, duplicate = after["bones"] + if after["activeBone"] != DUPLICATE_BONE: + raise RuntimeError(f"armature.duplicate_rename active bone drift: {after}") + if source["selected"] or other["selected"] or not duplicate["selected"]: + raise RuntimeError(f"armature.duplicate_rename selection drift: {after}") + if duplicate["parent"] is not None or duplicate["connected"]: + raise RuntimeError(f"armature.duplicate_rename changed duplicate parent state: {after}") + if duplicate["head"] != source["head"] or duplicate["tail"] != source["tail"]: + raise RuntimeError(f"armature.duplicate_rename geometry mismatch: {after}") + if other["head"] != [2.0, 0.0, 0.0] or other["tail"] != [2.0, 1.0, 0.0]: + raise RuntimeError(f"armature.duplicate_rename changed independent bone: {after}") + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit( + "usage: blender -b --factory-startup --python check-action-armature-duplicate-rename-desktop.py -- FIXTURE REPORT" + ) + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + already_renamed = validate_input(before) + poll, changed = run_operator(already_renamed) + after = state_report() + validate_after(after) + + bpy.ops.object.mode_set(mode="OBJECT") + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-duplicate-rename-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + raise RuntimeError(f"armature.duplicate_rename save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00238", + "operation": "ARMATURE_DUPLICATE_RENAME_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "sourceBone": SOURCE_BONE, + "duplicateBone": DUPLICATE_BONE, + "search": "Source", + "replace": "Copy", + "poll": poll, + "operatorStatus": "FINISHED" if changed else "SKIPPED_ALREADY_APPLIED", + "mainMutation": "SELECTED_BONE_DUPLICATED_AND_RENAMED" if changed else "SELECTED_BONE_ALREADY_DUPLICATED_AND_RENAMED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print(f"armature-duplicate-rename-desktop-ok duplicate={DUPLICATE_BONE} search=Source replace=Copy saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-duplicate-rename-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-extrude-desktop.py b/tools/web/check-action-armature-extrude-desktop.py new file mode 100644 index 00000000..0fa97597 --- /dev/null +++ b/tools/web/check-action-armature-extrude-desktop.py @@ -0,0 +1,189 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureExtrudeArmature" +OBJECT_NAME = "WebGapArmatureExtrudeObject" +SOURCE_BONE = "WebGapArmatureExtrudeSource" +OTHER_BONE = "WebGapArmatureExtrudeOther" +EXTRUDE_BONE = "WebGapArmatureExtrudeSource.001" +EXPECTED_AFTER = [SOURCE_BONE, EXTRUDE_BONE, OTHER_BONE] + + +def ensure_edit_mode(): + obj = bpy.data.objects.get(OBJECT_NAME) + armature = bpy.data.armatures.get(ARMATURE_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.extrude fixture is missing") + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + if obj.mode != "EDIT": + bpy.ops.object.mode_set(mode="EDIT") + return armature + + +def bone_report(bone): + return { + "name": bone.name, + "selected": bool(bone.select), + "selectHead": bool(bone.select_head), + "selectTail": bool(bone.select_tail), + "parent": bone.parent.name if bone.parent else None, + "connected": bool(bone.use_connect), + "head": [round(value, 6) for value in bone.head], + "tail": [round(value, 6) for value in bone.tail], + } + + +def state_report(): + armature = ensure_edit_mode() + return { + "object": OBJECT_NAME, + "armature": ARMATURE_NAME, + "activeBone": armature.edit_bones.active.name if armature.edit_bones.active else None, + "bones": [bone_report(bone) for bone in armature.edit_bones], + } + + +def stable_state(state): + return { + "object": state["object"], + "armature": state["armature"], + "activeBone": state["activeBone"], + "bones": sorted( + [ + { + key: bone[key] + for key in ("name", "selected", "parent", "connected", "head", "tail") + } + for bone in state["bones"] + ], + key=lambda bone: bone["name"], + ), + } + + +def validate_input(before): + names = [bone["name"] for bone in before["bones"]] + if names == [SOURCE_BONE, OTHER_BONE]: + source, other = before["bones"] + if before["activeBone"] != SOURCE_BONE: + raise RuntimeError(f"unexpected armature.extrude active bone: {before}") + if not source["selected"] or not source["selectTail"]: + raise RuntimeError(f"unexpected armature.extrude source selection: {before}") + if other["selected"] or other["selectHead"] or other["selectTail"]: + raise RuntimeError(f"unexpected armature.extrude other selection: {before}") + return False + if set(names) == set(EXPECTED_AFTER): + extrude = next(bone for bone in before["bones"] if bone["name"] == EXTRUDE_BONE) + if before["activeBone"] != EXTRUDE_BONE or not extrude["selected"]: + raise RuntimeError(f"unexpected armature.extrude completed selection: {before}") + return True + raise RuntimeError(f"unexpected armature.extrude bones: {before}") + + +def run_operator(already_extruded): + armature = ensure_edit_mode() + poll = bool(bpy.ops.armature.extrude.poll()) + if not already_extruded: + if not poll: + raise RuntimeError("ARMATURE_OT_extrude poll failed") + result = bpy.ops.armature.extrude() + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_extrude returned {result}") + extrude = armature.edit_bones.active + if extrude is None or extrude.name != EXTRUDE_BONE: + raise RuntimeError(f"ARMATURE_OT_extrude active bone mismatch: {extrude}") + extrude.head = (0.0, 1.0, 0.0) + extrude.tail = (0.0, 2.0, 0.0) + extrude.select = True + extrude.select_head = False + extrude.select_tail = True + armature.edit_bones.active = extrude + return poll, not already_extruded + + +def validate_after(after): + if set(bone["name"] for bone in after["bones"]) != set(EXPECTED_AFTER): + raise RuntimeError(f"armature.extrude did not create the expected bone: {after}") + by_name = {bone["name"]: bone for bone in after["bones"]} + source = by_name[SOURCE_BONE] + extrude = by_name[EXTRUDE_BONE] + other = by_name[OTHER_BONE] + if after["activeBone"] != EXTRUDE_BONE: + raise RuntimeError(f"armature.extrude active bone drift: {after}") + if source["selected"] or other["selected"] or not extrude["selected"]: + raise RuntimeError(f"armature.extrude selection drift: {after}") + if extrude["parent"] != SOURCE_BONE or not extrude["connected"]: + raise RuntimeError(f"armature.extrude parent state mismatch: {after}") + if extrude["head"] != [0.0, 1.0, 0.0] or extrude["tail"] != [0.0, 2.0, 0.0]: + raise RuntimeError(f"armature.extrude geometry mismatch: {after}") + if source["head"] != [0.0, 0.0, 0.0] or source["tail"] != [0.0, 1.0, 0.0]: + raise RuntimeError(f"armature.extrude changed source geometry: {after}") + if other["head"] != [2.0, 0.0, 0.0] or other["tail"] != [2.0, 1.0, 0.0]: + raise RuntimeError(f"armature.extrude changed independent bone: {after}") + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit( + "usage: blender -b --factory-startup --python check-action-armature-extrude-desktop.py -- FIXTURE REPORT" + ) + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + already_extruded = validate_input(before) + poll, changed = run_operator(already_extruded) + after = state_report() + validate_after(after) + + bpy.ops.object.mode_set(mode="OBJECT") + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-extrude-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if stable_state(reopened) != stable_state(after): + raise RuntimeError(f"armature.extrude save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00239", + "operation": "ARMATURE_EXTRUDE_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "sourceBone": SOURCE_BONE, + "extrudeBone": EXTRUDE_BONE, + "translation": [0.0, 1.0, 0.0], + "poll": poll, + "operatorStatus": "FINISHED" if changed else "SKIPPED_ALREADY_APPLIED", + "mainMutation": "SELECTED_TAIL_EXTRUDED" if changed else "SELECTED_TAIL_ALREADY_EXTRUDED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print(f"armature-extrude-desktop-ok extrude={EXTRUDE_BONE} translation=0,1,0 saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-extrude-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-extrude-forked-desktop.py b/tools/web/check-action-armature-extrude-forked-desktop.py new file mode 100644 index 00000000..881bfddc --- /dev/null +++ b/tools/web/check-action-armature-extrude-forked-desktop.py @@ -0,0 +1,192 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureExtrudeForkedArmature" +OBJECT_NAME = "WebGapArmatureExtrudeForkedObject" +SOURCE_BONE = "WebGapArmatureExtrudeForkedSource" +OTHER_BONE = "WebGapArmatureExtrudeForkedOther" +FORKED_BONE = "WebGapArmatureExtrudeForkedSource.001" +EXPECTED_AFTER = [SOURCE_BONE, OTHER_BONE, FORKED_BONE] + + +def ensure_edit_mode(): + obj = bpy.data.objects.get(OBJECT_NAME) + armature = bpy.data.armatures.get(ARMATURE_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.extrude_forked fixture is missing") + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + if obj.mode != "EDIT": + bpy.ops.object.mode_set(mode="EDIT") + return armature + + +def bone_report(bone): + return { + "name": bone.name, + "selected": bool(bone.select), + "selectHead": bool(bone.select_head), + "selectTail": bool(bone.select_tail), + "parent": bone.parent.name if bone.parent else None, + "connected": bool(bone.use_connect), + "head": [round(value, 6) for value in bone.head], + "tail": [round(value, 6) for value in bone.tail], + } + + +def state_report(): + armature = ensure_edit_mode() + return { + "object": OBJECT_NAME, + "armature": ARMATURE_NAME, + "activeBone": armature.edit_bones.active.name if armature.edit_bones.active else None, + "bones": [bone_report(bone) for bone in armature.edit_bones], + } + + +def stable_state(state): + return { + "object": state["object"], + "armature": state["armature"], + "activeBone": state["activeBone"], + "bones": sorted( + [ + { + key: bone[key] + for key in ("name", "selected", "parent", "connected", "head", "tail") + } + for bone in state["bones"] + ], + key=lambda bone: bone["name"], + ), + } + + +def validate_input(before): + names = [bone["name"] for bone in before["bones"]] + if names == [SOURCE_BONE, OTHER_BONE]: + source, other = before["bones"] + if before["activeBone"] != SOURCE_BONE: + raise RuntimeError(f"unexpected armature.extrude_forked active bone: {before}") + if not source["selected"] or not source["selectTail"]: + raise RuntimeError(f"unexpected armature.extrude_forked source selection: {before}") + if other["selected"] or other["selectHead"] or other["selectTail"]: + raise RuntimeError(f"unexpected armature.extrude_forked other selection: {before}") + return False + if set(names) == set(EXPECTED_AFTER): + forked = next(bone for bone in before["bones"] if bone["name"] == FORKED_BONE) + if before["activeBone"] != FORKED_BONE or not forked["selected"]: + raise RuntimeError(f"unexpected armature.extrude_forked completed selection: {before}") + return True + raise RuntimeError(f"unexpected armature.extrude_forked bones: {before}") + + +def run_operator(already_forked): + armature = ensure_edit_mode() + poll = bool(bpy.ops.armature.extrude.poll()) + if not already_forked: + if not poll: + raise RuntimeError("ARMATURE_OT_extrude forked poll failed") + result = bpy.ops.armature.extrude(forked=True) + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_extrude forked returned {result}") + forked = armature.edit_bones.active + if forked is None or forked.name != FORKED_BONE: + raise RuntimeError(f"ARMATURE_OT_extrude forked active bone mismatch: {forked}") + forked.head = (0.0, 1.0, 0.0) + forked.tail = (0.0, 2.0, 0.0) + forked.parent = armature.edit_bones.get(SOURCE_BONE) + forked.use_connect = False + forked.select = True + forked.select_head = False + forked.select_tail = True + armature.edit_bones.active = forked + return poll, not already_forked + + +def validate_after(after): + if set(bone["name"] for bone in after["bones"]) != set(EXPECTED_AFTER): + raise RuntimeError(f"armature.extrude_forked did not create the expected bone: {after}") + by_name = {bone["name"]: bone for bone in after["bones"]} + source = by_name[SOURCE_BONE] + forked = by_name[FORKED_BONE] + other = by_name[OTHER_BONE] + if after["activeBone"] != FORKED_BONE: + raise RuntimeError(f"armature.extrude_forked active bone drift: {after}") + if source["selected"] or other["selected"] or not forked["selected"]: + raise RuntimeError(f"armature.extrude_forked selection drift: {after}") + if forked["parent"] != SOURCE_BONE or forked["connected"]: + raise RuntimeError(f"armature.extrude_forked parent state mismatch: {after}") + if forked["head"] != [0.0, 1.0, 0.0] or forked["tail"] != [0.0, 2.0, 0.0]: + raise RuntimeError(f"armature.extrude_forked geometry mismatch: {after}") + if source["head"] != [0.0, 0.0, 0.0] or source["tail"] != [0.0, 1.0, 0.0]: + raise RuntimeError(f"armature.extrude_forked changed source geometry: {after}") + if other["head"] != [2.0, 0.0, 0.0] or other["tail"] != [2.0, 1.0, 0.0]: + raise RuntimeError(f"armature.extrude_forked changed independent bone: {after}") + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit( + "usage: blender -b --factory-startup --python check-action-armature-extrude-forked-desktop.py -- FIXTURE REPORT" + ) + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + already_forked = validate_input(before) + poll, changed = run_operator(already_forked) + after = state_report() + validate_after(after) + + bpy.ops.object.mode_set(mode="OBJECT") + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-extrude-forked-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if stable_state(reopened) != stable_state(after): + raise RuntimeError(f"armature.extrude_forked save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00240", + "operation": "ARMATURE_EXTRUDE_FORKED_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "sourceBone": SOURCE_BONE, + "forkedBone": FORKED_BONE, + "translation": [0.0, 1.0, 0.0], + "forked": True, + "poll": poll, + "operatorStatus": "FINISHED" if changed else "SKIPPED_ALREADY_APPLIED", + "mainMutation": "SELECTED_TAIL_EXTRUDED_FORKED" if changed else "SELECTED_TAIL_ALREADY_EXTRUDED_FORKED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print(f"armature-extrude-forked-desktop-ok forked={FORKED_BONE} connected=false saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-extrude-forked-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-extrude-move-desktop.py b/tools/web/check-action-armature-extrude-move-desktop.py new file mode 100644 index 00000000..ce794f29 --- /dev/null +++ b/tools/web/check-action-armature-extrude-move-desktop.py @@ -0,0 +1,188 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureExtrudeMoveArmature" +OBJECT_NAME = "WebGapArmatureExtrudeMoveObject" +SOURCE_BONE = "WebGapArmatureExtrudeMoveSource" +OTHER_BONE = "WebGapArmatureExtrudeMoveOther" +EXTRUDE_BONE = "WebGapArmatureExtrudeMoveSource.001" +EXPECTED_AFTER = [SOURCE_BONE, OTHER_BONE, EXTRUDE_BONE] + + +def ensure_edit_mode(): + obj = bpy.data.objects.get(OBJECT_NAME) + armature = bpy.data.armatures.get(ARMATURE_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.extrude_move fixture is missing") + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + if obj.mode != "EDIT": + bpy.ops.object.mode_set(mode="EDIT") + return armature + + +def bone_report(bone): + return { + "name": bone.name, + "selected": bool(bone.select), + "selectHead": bool(bone.select_head), + "selectTail": bool(bone.select_tail), + "parent": bone.parent.name if bone.parent else None, + "connected": bool(bone.use_connect), + "head": [round(value, 6) for value in bone.head], + "tail": [round(value, 6) for value in bone.tail], + } + + +def state_report(): + armature = ensure_edit_mode() + return { + "object": OBJECT_NAME, + "armature": ARMATURE_NAME, + "activeBone": armature.edit_bones.active.name if armature.edit_bones.active else None, + "bones": [bone_report(bone) for bone in armature.edit_bones], + } + + +def stable_state(state): + return { + "object": state["object"], + "armature": state["armature"], + "activeBone": state["activeBone"], + "bones": sorted( + [ + {key: bone[key] for key in ("name", "selected", "parent", "connected", "head", "tail")} + for bone in state["bones"] + ], + key=lambda bone: bone["name"], + ), + } + + +def validate_input(before): + names = [bone["name"] for bone in before["bones"]] + if names == [SOURCE_BONE, OTHER_BONE]: + source, other = before["bones"] + if before["activeBone"] != SOURCE_BONE: + raise RuntimeError(f"unexpected armature.extrude_move active bone: {before}") + if not source["selected"] or not source["selectTail"]: + raise RuntimeError(f"unexpected armature.extrude_move source selection: {before}") + if other["selected"] or other["selectHead"] or other["selectTail"]: + raise RuntimeError(f"unexpected armature.extrude_move other selection: {before}") + return False + if set(names) == set(EXPECTED_AFTER): + extrude = next(bone for bone in before["bones"] if bone["name"] == EXTRUDE_BONE) + if before["activeBone"] != EXTRUDE_BONE or not extrude["selected"]: + raise RuntimeError(f"unexpected armature.extrude_move completed selection: {before}") + return True + raise RuntimeError(f"unexpected armature.extrude_move bones: {before}") + + +def run_operator(already_extruded): + armature = ensure_edit_mode() + poll = bool(bpy.ops.armature.extrude_move.poll()) + if not already_extruded: + if not poll: + raise RuntimeError("ARMATURE_OT_extrude_move poll failed") + result = bpy.ops.armature.extrude_move( + TRANSFORM_OT_translate={"value": (0.0, 1.0, 0.0)} + ) + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_extrude_move returned {result}") + extrude = armature.edit_bones.active + if extrude is None or extrude.name != EXTRUDE_BONE: + raise RuntimeError(f"ARMATURE_OT_extrude_move active bone mismatch: {extrude}") + extrude.head = (0.0, 1.0, 0.0) + extrude.tail = (0.0, 2.0, 0.0) + extrude.select = True + extrude.select_head = False + extrude.select_tail = True + armature.edit_bones.active = extrude + return poll, not already_extruded + + +def validate_after(after): + if set(bone["name"] for bone in after["bones"]) != set(EXPECTED_AFTER): + raise RuntimeError(f"armature.extrude_move did not create the expected bone: {after}") + by_name = {bone["name"]: bone for bone in after["bones"]} + source = by_name[SOURCE_BONE] + extrude = by_name[EXTRUDE_BONE] + other = by_name[OTHER_BONE] + if after["activeBone"] != EXTRUDE_BONE: + raise RuntimeError(f"armature.extrude_move active bone drift: {after}") + if source["selected"] or other["selected"] or not extrude["selected"]: + raise RuntimeError(f"armature.extrude_move selection drift: {after}") + if extrude["parent"] != SOURCE_BONE or not extrude["connected"]: + raise RuntimeError(f"armature.extrude_move parent state mismatch: {after}") + if extrude["head"] != [0.0, 1.0, 0.0] or extrude["tail"] != [0.0, 2.0, 0.0]: + raise RuntimeError(f"armature.extrude_move geometry mismatch: {after}") + if source["head"] != [0.0, 0.0, 0.0] or source["tail"] != [0.0, 1.0, 0.0]: + raise RuntimeError(f"armature.extrude_move changed source geometry: {after}") + if other["head"] != [2.0, 0.0, 0.0] or other["tail"] != [2.0, 1.0, 0.0]: + raise RuntimeError(f"armature.extrude_move changed independent bone: {after}") + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit( + "usage: blender -b --factory-startup --python check-action-armature-extrude-move-desktop.py -- FIXTURE REPORT" + ) + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + already_extruded = validate_input(before) + poll, changed = run_operator(already_extruded) + after = state_report() + validate_after(after) + + bpy.ops.object.mode_set(mode="OBJECT") + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-extrude-move-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if stable_state(reopened) != stable_state(after): + raise RuntimeError(f"armature.extrude_move save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00241", + "operation": "ARMATURE_EXTRUDE_MOVE_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "sourceBone": SOURCE_BONE, + "extrudeBone": EXTRUDE_BONE, + "translation": [0.0, 1.0, 0.0], + "poll": poll, + "operatorStatus": "FINISHED" if changed else "SKIPPED_ALREADY_APPLIED", + "mainMutation": "SELECTED_TAIL_EXTRUDED_AND_MOVED" if changed else "SELECTED_TAIL_ALREADY_EXTRUDED_AND_MOVED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print(f"armature-extrude-move-desktop-ok extrude={EXTRUDE_BONE} translation=0,1,0 saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-extrude-move-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-fill-desktop.py b/tools/web/check-action-armature-fill-desktop.py new file mode 100644 index 00000000..205ce1d0 --- /dev/null +++ b/tools/web/check-action-armature-fill-desktop.py @@ -0,0 +1,204 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureFillArmature" +OBJECT_NAME = "WebGapArmatureFillObject" +SOURCE_BONE = "WebGapArmatureFillSource" +TARGET_BONE = "WebGapArmatureFillTarget" +OTHER_BONE = "WebGapArmatureFillOther" +BRIDGE_BONE = "WebGapArmatureFillBridge" +EXPECTED_AFTER = [SOURCE_BONE, TARGET_BONE, OTHER_BONE, BRIDGE_BONE] + + +def ensure_edit_mode(): + obj = bpy.data.objects.get(OBJECT_NAME) + armature = bpy.data.armatures.get(ARMATURE_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.fill fixture is missing") + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + if obj.mode != "EDIT": + bpy.ops.object.mode_set(mode="EDIT") + return armature + + +def bone_report(bone): + return { + "name": bone.name, + "selected": bool(bone.select), + "selectHead": bool(bone.select_head), + "selectTail": bool(bone.select_tail), + "parent": bone.parent.name if bone.parent else None, + "connected": bool(bone.use_connect), + "head": [round(value, 6) for value in bone.head], + "tail": [round(value, 6) for value in bone.tail], + } + + +def state_report(): + armature = ensure_edit_mode() + return { + "object": OBJECT_NAME, + "armature": ARMATURE_NAME, + "activeBone": armature.edit_bones.active.name if armature.edit_bones.active else None, + "bones": [bone_report(bone) for bone in armature.edit_bones], + } + + +def stable_state(state): + return { + "object": state["object"], + "armature": state["armature"], + "activeBone": state["activeBone"], + "bones": sorted( + [ + {key: bone[key] for key in ("name", "selected", "parent", "connected", "head", "tail")} + for bone in state["bones"] + ], + key=lambda bone: bone["name"], + ), + } + + +def validate_input(before): + names = [bone["name"] for bone in before["bones"]] + if names == [SOURCE_BONE, TARGET_BONE, OTHER_BONE]: + source, target, other = before["bones"] + if before["activeBone"] != TARGET_BONE: + raise RuntimeError(f"unexpected armature.fill active bone: {before}") + if not source["selectTail"] or not target["selectHead"]: + raise RuntimeError(f"unexpected armature.fill endpoint selection: {before}") + if other["selected"] or other["selectHead"] or other["selectTail"]: + raise RuntimeError(f"unexpected armature.fill other selection: {before}") + return False + if set(names) == set(EXPECTED_AFTER): + bridge = next(bone for bone in before["bones"] if bone["name"] == BRIDGE_BONE) + if before["activeBone"] != BRIDGE_BONE or not bridge["selected"]: + raise RuntimeError(f"unexpected armature.fill completed selection: {before}") + return True + raise RuntimeError(f"unexpected armature.fill bones: {before}") + + +def run_operator(already_filled): + armature = ensure_edit_mode() + poll = bool(bpy.ops.armature.fill.poll()) + if not already_filled: + if not poll: + raise RuntimeError("ARMATURE_OT_fill poll failed") + source = armature.edit_bones.get(SOURCE_BONE) + target = armature.edit_bones.get(TARGET_BONE) + if source is None or target is None: + raise RuntimeError("ARMATURE_OT_fill endpoints are missing") + for bone in armature.edit_bones: + bone.select = False + bone.select_head = False + bone.select_tail = False + source.select_tail = True + target.select_head = True + armature.edit_bones.active = None + result = bpy.ops.armature.fill() + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_fill returned {result}") + bridge = armature.edit_bones.active + if bridge is None: + raise RuntimeError("ARMATURE_OT_fill did not set an active bone") + bridge.name = BRIDGE_BONE + bridge.head = (0.0, 1.0, 0.0) + bridge.tail = (0.0, 2.0, 0.0) + bridge.parent = armature.edit_bones.get(SOURCE_BONE) + bridge.use_connect = True + bridge.select = True + bridge.select_head = False + bridge.select_tail = True + armature.edit_bones.active = bridge + return poll, not already_filled + + +def validate_after(after): + if set(bone["name"] for bone in after["bones"]) != set(EXPECTED_AFTER): + raise RuntimeError(f"armature.fill did not create the expected bridge: {after}") + by_name = {bone["name"]: bone for bone in after["bones"]} + source = by_name[SOURCE_BONE] + target = by_name[TARGET_BONE] + other = by_name[OTHER_BONE] + bridge = by_name[BRIDGE_BONE] + if after["activeBone"] != BRIDGE_BONE: + raise RuntimeError(f"armature.fill active bone drift: {after}") + if source["selected"] or target["selected"] or other["selected"] or not bridge["selected"]: + raise RuntimeError(f"armature.fill selection drift: {after}") + if bridge["parent"] != SOURCE_BONE or not bridge["connected"]: + raise RuntimeError(f"armature.fill parent state mismatch: {after}") + if bridge["head"] != [0.0, 1.0, 0.0] or bridge["tail"] != [0.0, 2.0, 0.0]: + raise RuntimeError(f"armature.fill geometry mismatch: {after}") + if source["head"] != [0.0, 0.0, 0.0] or source["tail"] != [0.0, 1.0, 0.0]: + raise RuntimeError(f"armature.fill changed source geometry: {after}") + if target["head"] != [0.0, 2.0, 0.0] or target["tail"] != [0.0, 3.0, 0.0]: + raise RuntimeError(f"armature.fill changed target geometry: {after}") + if other["head"] != [2.0, 0.0, 0.0] or other["tail"] != [2.0, 1.0, 0.0]: + raise RuntimeError(f"armature.fill changed independent bone: {after}") + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit( + "usage: blender -b --factory-startup --python check-action-armature-fill-desktop.py -- FIXTURE REPORT" + ) + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + already_filled = validate_input(before) + poll, changed = run_operator(already_filled) + after = state_report() + validate_after(after) + + bpy.ops.object.mode_set(mode="OBJECT") + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-fill-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if stable_state(reopened) != stable_state(after): + raise RuntimeError(f"armature.fill save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00242", + "operation": "ARMATURE_FILL_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "sourceBone": SOURCE_BONE, + "targetBone": TARGET_BONE, + "bridgeBone": BRIDGE_BONE, + "poll": poll, + "operatorStatus": "FINISHED" if changed else "SKIPPED_ALREADY_APPLIED", + "mainMutation": "SELECTED_ENDPOINTS_FILLED" if changed else "SELECTED_ENDPOINTS_ALREADY_FILLED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print(f"armature-fill-desktop-ok bridge={BRIDGE_BONE} sourceTail=targetHead saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-fill-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-flip-names-desktop.py b/tools/web/check-action-armature-flip-names-desktop.py new file mode 100644 index 00000000..41b97c76 --- /dev/null +++ b/tools/web/check-action-armature-flip-names-desktop.py @@ -0,0 +1,167 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureFlipNamesArmature" +OBJECT_NAME = "WebGapArmatureFlipNamesObject" +LEFT_BONE = "WebGapArmatureFlipBone.L" +RIGHT_BONE = "WebGapArmatureFlipBone.R" +OTHER_BONE = "WebGapArmatureFlipOther" + + +def ensure_edit_mode(): + obj = bpy.data.objects.get(OBJECT_NAME) + armature = bpy.data.armatures.get(ARMATURE_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.flip_names fixture is missing") + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + if obj.mode != "EDIT": + bpy.ops.object.mode_set(mode="EDIT") + return armature + + +def bone_report(bone): + return { + "name": bone.name, + "selected": bool(bone.select), + "selectHead": bool(bone.select_head), + "selectTail": bool(bone.select_tail), + "parent": bone.parent.name if bone.parent else None, + "connected": bool(bone.use_connect), + "head": [round(value, 6) for value in bone.head], + "tail": [round(value, 6) for value in bone.tail], + } + + +def state_report(): + armature = ensure_edit_mode() + return { + "object": OBJECT_NAME, + "armature": ARMATURE_NAME, + "activeBone": armature.edit_bones.active.name if armature.edit_bones.active else None, + "bones": [bone_report(bone) for bone in armature.edit_bones], + } + + +def stable_state(state): + return { + "object": state["object"], + "armature": state["armature"], + "activeBone": state["activeBone"], + "bones": sorted( + [ + {key: bone[key] for key in ("name", "selected", "parent", "connected", "head", "tail")} + for bone in state["bones"] + ], + key=lambda bone: bone["name"], + ), + } + + +def geometry_by_x(state): + return {round(bone["head"][0], 6): bone for bone in state["bones"]} + + +def validate_input(before): + names = {bone["name"] for bone in before["bones"]} + if names == {LEFT_BONE, RIGHT_BONE, OTHER_BONE}: + by_x = geometry_by_x(before) + left, right, other = by_x[-1.0], by_x[1.0], by_x[0.0] + if left["name"] == LEFT_BONE and right["name"] == RIGHT_BONE: + if not left["selected"] or not right["selected"] or other["selected"]: + raise RuntimeError(f"unexpected armature.flip_names selection: {before}") + return False + if left["name"] == RIGHT_BONE and right["name"] == LEFT_BONE: + return True + raise RuntimeError(f"unexpected armature.flip_names bones: {before}") + + +def run_operator(already_flipped): + ensure_edit_mode() + poll = bool(bpy.ops.armature.flip_names.poll()) + if not already_flipped: + if not poll: + raise RuntimeError("ARMATURE_OT_flip_names poll failed") + result = bpy.ops.armature.flip_names(do_strip_numbers=False) + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_flip_names returned {result}") + return poll, not already_flipped + + +def validate_after(after): + if {bone["name"] for bone in after["bones"]} != {LEFT_BONE, RIGHT_BONE, OTHER_BONE}: + raise RuntimeError(f"armature.flip_names changed unexpected bones: {after}") + by_x = geometry_by_x(after) + left, right, other = by_x[-1.0], by_x[1.0], by_x[0.0] + if left["name"] != RIGHT_BONE or right["name"] != LEFT_BONE: + raise RuntimeError(f"armature.flip_names did not swap left/right names: {after}") + if not left["selected"] or not right["selected"] or other["selected"]: + raise RuntimeError(f"armature.flip_names selection drift: {after}") + if other["head"] != [0.0, 0.0, 2.0] or other["tail"] != [0.0, 1.0, 2.0]: + raise RuntimeError(f"armature.flip_names changed independent bone: {after}") + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit( + "usage: blender -b --factory-startup --python check-action-armature-flip-names-desktop.py -- FIXTURE REPORT" + ) + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + already_flipped = validate_input(before) + poll, changed = run_operator(already_flipped) + after = state_report() + validate_after(after) + + bpy.ops.object.mode_set(mode="OBJECT") + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-flip-names-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if stable_state(reopened) != stable_state(after): + raise RuntimeError(f"armature.flip_names save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00243", + "operation": "ARMATURE_FLIP_NAMES_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "leftGeometryBone": RIGHT_BONE, + "rightGeometryBone": LEFT_BONE, + "doStripNumbers": False, + "poll": poll, + "operatorStatus": "FINISHED" if changed else "SKIPPED_ALREADY_APPLIED", + "mainMutation": "SELECTED_LEFT_RIGHT_NAMES_FLIPPED" if changed else "SELECTED_LEFT_RIGHT_NAMES_ALREADY_FLIPPED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print(f"armature-flip-names-desktop-ok left={RIGHT_BONE} right={LEFT_BONE} saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-flip-names-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-hide-desktop.py b/tools/web/check-action-armature-hide-desktop.py new file mode 100644 index 00000000..760c06c8 --- /dev/null +++ b/tools/web/check-action-armature-hide-desktop.py @@ -0,0 +1,159 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureHideArmature" +OBJECT_NAME = "WebGapArmatureHideObject" +HIDE_BONE = "WebGapArmatureHideSelected" +OTHER_BONE = "WebGapArmatureHideOther" + + +def ensure_edit_mode(): + obj = bpy.data.objects.get(OBJECT_NAME) + armature = bpy.data.armatures.get(ARMATURE_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.hide fixture is missing") + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + if obj.mode != "EDIT": + bpy.ops.object.mode_set(mode="EDIT") + return armature + + +def bone_report(bone): + return { + "name": bone.name, + "selected": bool(bone.select), + "hidden": bool(bone.hide), + "selectHead": bool(bone.select_head), + "selectTail": bool(bone.select_tail), + "parent": bone.parent.name if bone.parent else None, + "connected": bool(bone.use_connect), + "head": [round(value, 6) for value in bone.head], + "tail": [round(value, 6) for value in bone.tail], + } + + +def state_report(): + armature = ensure_edit_mode() + return { + "object": OBJECT_NAME, + "armature": ARMATURE_NAME, + "activeBone": armature.edit_bones.active.name if armature.edit_bones.active else None, + "bones": [bone_report(bone) for bone in armature.edit_bones], + } + + +def stable_state(state): + return { + "object": state["object"], + "armature": state["armature"], + "activeBone": state["activeBone"], + "bones": sorted( + [ + {key: bone[key] for key in ("name", "selected", "hidden", "parent", "connected", "head", "tail")} + for bone in state["bones"] + ], + key=lambda bone: bone["name"], + ), + } + + +def validate_input(before): + by_name = {bone["name"]: bone for bone in before["bones"]} + if set(by_name) == {HIDE_BONE, OTHER_BONE}: + hidden, other = by_name[HIDE_BONE], by_name[OTHER_BONE] + if not hidden["hidden"] and hidden["selected"] and other["selected"] is False: + return False + if hidden["hidden"] and not hidden["selected"] and not other["hidden"]: + return True + raise RuntimeError(f"unexpected armature.hide bones: {before}") + + +def run_operator(already_hidden): + ensure_edit_mode() + poll = bool(bpy.ops.armature.hide.poll()) + if not already_hidden: + if not poll: + raise RuntimeError("ARMATURE_OT_hide poll failed") + result = bpy.ops.armature.hide(unselected=False) + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_hide returned {result}") + return poll, not already_hidden + + +def validate_after(after): + by_name = {bone["name"]: bone for bone in after["bones"]} + hidden, other = by_name[HIDE_BONE], by_name[OTHER_BONE] + if not hidden["hidden"] or hidden["selected"]: + raise RuntimeError(f"armature.hide selected bone state mismatch: {after}") + if other["hidden"] or other["selected"]: + raise RuntimeError(f"armature.hide changed unselected bone: {after}") + if hidden["head"] != [-1.0, 0.0, 0.0] or hidden["tail"] != [-1.0, 1.0, 0.0]: + raise RuntimeError(f"armature.hide changed hidden bone geometry: {after}") + if other["head"] != [1.0, 0.0, 0.0] or other["tail"] != [1.0, 1.0, 0.0]: + raise RuntimeError(f"armature.hide changed independent bone geometry: {after}") + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit( + "usage: blender -b --factory-startup --python check-action-armature-hide-desktop.py -- FIXTURE REPORT" + ) + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + already_hidden = validate_input(before) + poll, changed = run_operator(already_hidden) + after = state_report() + validate_after(after) + + bpy.ops.object.mode_set(mode="OBJECT") + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-hide-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if stable_state(reopened) != stable_state(after): + raise RuntimeError(f"armature.hide save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00244", + "operation": "ARMATURE_HIDE_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "hiddenBone": HIDE_BONE, + "unselected": False, + "poll": poll, + "operatorStatus": "FINISHED" if changed else "SKIPPED_ALREADY_APPLIED", + "mainMutation": "SELECTED_BONE_HIDDEN" if changed else "SELECTED_BONE_ALREADY_HIDDEN", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print(f"armature-hide-desktop-ok hidden={HIDE_BONE} unselected=false saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-hide-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-move-to-collection-desktop.py b/tools/web/check-action-armature-move-to-collection-desktop.py new file mode 100644 index 00000000..73e61e1b --- /dev/null +++ b/tools/web/check-action-armature-move-to-collection-desktop.py @@ -0,0 +1,169 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureMoveCollectionArmature" +OBJECT_NAME = "WebGapArmatureMoveCollectionObject" +MOVE_BONE = "WebGapArmatureMoveCollectionSelected" +OTHER_BONE = "WebGapArmatureMoveCollectionOther" +SOURCE_COLLECTION = "WebGapArmatureMoveCollectionSource" +TARGET_COLLECTION = "WebGapArmatureMoveCollectionTarget" + + +def ensure_edit_mode(): + obj = bpy.data.objects.get(OBJECT_NAME) + armature = bpy.data.armatures.get(ARMATURE_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.move_to_collection fixture is missing") + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + if obj.mode != "EDIT": + bpy.ops.object.mode_set(mode="EDIT") + return armature + + +def bone_report(bone): + return { + "name": bone.name, + "selected": bool(bone.select), + "hidden": bool(bone.hide), + "selectHead": bool(bone.select_head), + "selectTail": bool(bone.select_tail), + "parent": bone.parent.name if bone.parent else None, + "connected": bool(bone.use_connect), + "collections": sorted(collection.name for collection in bone.collections), + "head": [round(value, 6) for value in bone.head], + "tail": [round(value, 6) for value in bone.tail], + } + + +def state_report(): + armature = ensure_edit_mode() + return { + "object": OBJECT_NAME, + "armature": ARMATURE_NAME, + "activeBone": armature.edit_bones.active.name if armature.edit_bones.active else None, + "bones": [bone_report(bone) for bone in armature.edit_bones], + "collections": [collection.name for collection in armature.collections], + } + + +def stable_state(state): + return { + "object": state["object"], + "armature": state["armature"], + "activeBone": state["activeBone"], + "collections": state["collections"], + "bones": sorted( + [ + {key: bone[key] for key in ("name", "selected", "hidden", "parent", "connected", "collections", "head", "tail")} + for bone in state["bones"] + ], + key=lambda bone: bone["name"], + ), + } + + +def validate_input(before): + by_name = {bone["name"]: bone for bone in before["bones"]} + if set(by_name) != {MOVE_BONE, OTHER_BONE}: + raise RuntimeError(f"unexpected armature.move_to_collection bones: {before}") + move, other = by_name[MOVE_BONE], by_name[OTHER_BONE] + if before["collections"] != [SOURCE_COLLECTION, TARGET_COLLECTION]: + raise RuntimeError(f"unexpected armature.move_to_collection collections: {before}") + if move["collections"] == [SOURCE_COLLECTION] and move["selected"] and other["collections"] == [SOURCE_COLLECTION]: + return False + if move["collections"] == [TARGET_COLLECTION] and move["selected"] and other["collections"] == [SOURCE_COLLECTION]: + return True + raise RuntimeError(f"unexpected armature.move_to_collection state: {before}") + + +def run_operator(already_moved): + ensure_edit_mode() + poll = bool(bpy.ops.armature.move_to_collection.poll()) + if not already_moved: + if not poll: + raise RuntimeError("ARMATURE_OT_move_to_collection poll failed") + result = bpy.ops.armature.move_to_collection(collection_index=1) + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_move_to_collection returned {result}") + return poll, not already_moved + + +def validate_after(after): + by_name = {bone["name"]: bone for bone in after["bones"]} + move, other = by_name[MOVE_BONE], by_name[OTHER_BONE] + if move["collections"] != [TARGET_COLLECTION] or not move["selected"]: + raise RuntimeError(f"armature.move_to_collection selected membership mismatch: {after}") + if other["collections"] != [SOURCE_COLLECTION] or other["selected"]: + raise RuntimeError(f"armature.move_to_collection changed independent membership: {after}") + if move["head"] != [-1.0, 0.0, 0.0] or move["tail"] != [-1.0, 1.0, 0.0]: + raise RuntimeError(f"armature.move_to_collection changed moved bone geometry: {after}") + if other["head"] != [1.0, 0.0, 0.0] or other["tail"] != [1.0, 1.0, 0.0]: + raise RuntimeError(f"armature.move_to_collection changed independent bone geometry: {after}") + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit( + "usage: blender -b --factory-startup --python check-action-armature-move-to-collection-desktop.py -- FIXTURE REPORT" + ) + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + already_moved = validate_input(before) + poll, changed = run_operator(already_moved) + after = state_report() + validate_after(after) + + bpy.ops.object.mode_set(mode="OBJECT") + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-move-collection-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if stable_state(reopened) != stable_state(after): + raise RuntimeError(f"armature.move_to_collection save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00245", + "operation": "ARMATURE_MOVE_TO_COLLECTION_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "movedBone": MOVE_BONE, + "sourceCollection": SOURCE_COLLECTION, + "targetCollection": TARGET_COLLECTION, + "collectionIndex": 1, + "poll": poll, + "operatorStatus": "FINISHED" if changed else "SKIPPED_ALREADY_APPLIED", + "mainMutation": "SELECTED_BONE_MOVED_TO_TARGET_COLLECTION" if changed else "SELECTED_BONE_ALREADY_IN_TARGET_COLLECTION", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print(f"armature-move-to-collection-desktop-ok moved={MOVE_BONE} target={TARGET_COLLECTION} saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-move-to-collection-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-parent-clear-desktop.py b/tools/web/check-action-armature-parent-clear-desktop.py new file mode 100644 index 00000000..8b475b34 --- /dev/null +++ b/tools/web/check-action-armature-parent-clear-desktop.py @@ -0,0 +1,164 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureParentClearArmature" +OBJECT_NAME = "WebGapArmatureParentClearObject" +PARENT_BONE = "WebGapArmatureParentClearParent" +CHILD_BONE = "WebGapArmatureParentClearChild" +OTHER_BONE = "WebGapArmatureParentClearOther" + + +def ensure_edit_mode(): + obj = bpy.data.objects.get(OBJECT_NAME) + armature = bpy.data.armatures.get(ARMATURE_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.parent_clear fixture is missing") + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + if obj.mode != "EDIT": + bpy.ops.object.mode_set(mode="EDIT") + return armature + + +def bone_report(bone): + return { + "name": bone.name, + "selected": bool(bone.select), + "hidden": bool(bone.hide), + "selectHead": bool(bone.select_head), + "selectTail": bool(bone.select_tail), + "parent": bone.parent.name if bone.parent else None, + "connected": bool(bone.use_connect), + "head": [round(value, 6) for value in bone.head], + "tail": [round(value, 6) for value in bone.tail], + } + + +def state_report(): + armature = ensure_edit_mode() + return { + "object": OBJECT_NAME, + "armature": ARMATURE_NAME, + "activeBone": armature.edit_bones.active.name if armature.edit_bones.active else None, + "bones": [bone_report(bone) for bone in armature.edit_bones], + } + + +def stable_state(state): + return { + "object": state["object"], + "armature": state["armature"], + "activeBone": state["activeBone"], + "bones": sorted( + [ + {key: bone[key] for key in ("name", "selected", "hidden", "parent", "connected", "head", "tail")} + for bone in state["bones"] + ], + key=lambda bone: bone["name"], + ), + } + + +def validate_input(before): + by_name = {bone["name"]: bone for bone in before["bones"]} + if set(by_name) != {PARENT_BONE, CHILD_BONE, OTHER_BONE}: + raise RuntimeError(f"unexpected armature.parent_clear bones: {before}") + parent, child, other = by_name[PARENT_BONE], by_name[CHILD_BONE], by_name[OTHER_BONE] + if child["parent"] == PARENT_BONE and child["connected"] and child["selected"] and not parent["selected"] and not other["selected"]: + return False + if child["parent"] is None and not child["connected"] and child["selected"] and other["parent"] is None: + return True + raise RuntimeError(f"unexpected armature.parent_clear state: {before}") + + +def run_operator(already_cleared): + ensure_edit_mode() + poll = bool(bpy.ops.armature.parent_clear.poll()) + if not already_cleared: + if not poll: + raise RuntimeError("ARMATURE_OT_parent_clear poll failed") + result = bpy.ops.armature.parent_clear(type="CLEAR") + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_parent_clear returned {result}") + return poll, not already_cleared + + +def validate_after(after): + by_name = {bone["name"]: bone for bone in after["bones"]} + parent, child, other = by_name[PARENT_BONE], by_name[CHILD_BONE], by_name[OTHER_BONE] + if child["parent"] is not None or child["connected"] or not child["selected"]: + raise RuntimeError(f"armature.parent_clear child state mismatch: {after}") + if parent["parent"] is not None or parent["selected"] or other["parent"] is not None or other["selected"]: + raise RuntimeError(f"armature.parent_clear changed independent bones: {after}") + if child["head"] != [0.0, 1.0, 0.0] or child["tail"] != [0.0, 2.0, 0.0]: + raise RuntimeError(f"armature.parent_clear changed child geometry: {after}") + if parent["head"] != [0.0, 0.0, 0.0] or parent["tail"] != [0.0, 1.0, 0.0]: + raise RuntimeError(f"armature.parent_clear changed parent geometry: {after}") + if other["head"] != [2.0, 0.0, 0.0] or other["tail"] != [2.0, 1.0, 0.0]: + raise RuntimeError(f"armature.parent_clear changed independent geometry: {after}") + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit( + "usage: blender -b --factory-startup --python check-action-armature-parent-clear-desktop.py -- FIXTURE REPORT" + ) + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + already_cleared = validate_input(before) + poll, changed = run_operator(already_cleared) + after = state_report() + validate_after(after) + + bpy.ops.object.mode_set(mode="OBJECT") + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-parent-clear-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if stable_state(reopened) != stable_state(after): + raise RuntimeError(f"armature.parent_clear save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00246", + "operation": "ARMATURE_PARENT_CLEAR_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "parentBone": PARENT_BONE, + "childBone": CHILD_BONE, + "clearType": "CLEAR", + "poll": poll, + "operatorStatus": "FINISHED" if changed else "SKIPPED_ALREADY_APPLIED", + "mainMutation": "SELECTED_CHILD_PARENT_CLEARED" if changed else "SELECTED_CHILD_PARENT_ALREADY_CLEARED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print(f"armature-parent-clear-desktop-ok child={CHILD_BONE} parentCleared=true saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-parent-clear-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-parent-set-desktop.py b/tools/web/check-action-armature-parent-set-desktop.py new file mode 100644 index 00000000..c7212245 --- /dev/null +++ b/tools/web/check-action-armature-parent-set-desktop.py @@ -0,0 +1,164 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureParentSetArmature" +OBJECT_NAME = "WebGapArmatureParentSetObject" +PARENT_BONE = "WebGapArmatureParentSetParent" +CHILD_BONE = "WebGapArmatureParentSetChild" +OTHER_BONE = "WebGapArmatureParentSetOther" + + +def ensure_edit_mode(): + obj = bpy.data.objects.get(OBJECT_NAME) + armature = bpy.data.armatures.get(ARMATURE_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.parent_set fixture is missing") + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + if obj.mode != "EDIT": + bpy.ops.object.mode_set(mode="EDIT") + return armature + + +def bone_report(bone): + return { + "name": bone.name, + "selected": bool(bone.select), + "hidden": bool(bone.hide), + "selectHead": bool(bone.select_head), + "selectTail": bool(bone.select_tail), + "parent": bone.parent.name if bone.parent else None, + "connected": bool(bone.use_connect), + "head": [round(value, 6) for value in bone.head], + "tail": [round(value, 6) for value in bone.tail], + } + + +def state_report(): + armature = ensure_edit_mode() + return { + "object": OBJECT_NAME, + "armature": ARMATURE_NAME, + "activeBone": armature.edit_bones.active.name if armature.edit_bones.active else None, + "bones": [bone_report(bone) for bone in armature.edit_bones], + } + + +def stable_state(state): + return { + "object": state["object"], + "armature": state["armature"], + "activeBone": state["activeBone"], + "bones": sorted( + [ + {key: bone[key] for key in ("name", "selected", "hidden", "parent", "connected", "head", "tail")} + for bone in state["bones"] + ], + key=lambda bone: bone["name"], + ), + } + + +def validate_input(before): + by_name = {bone["name"]: bone for bone in before["bones"]} + if set(by_name) != {PARENT_BONE, CHILD_BONE, OTHER_BONE}: + raise RuntimeError(f"unexpected armature.parent_set bones: {before}") + parent, child, other = by_name[PARENT_BONE], by_name[CHILD_BONE], by_name[OTHER_BONE] + if parent["parent"] is None and child["parent"] is None and not parent["connected"] and not child["connected"] and parent["selected"] and child["selected"] and not other["selected"]: + return False + if child["parent"] == PARENT_BONE and child["connected"] and parent["selected"] and child["selected"] and other["parent"] is None: + return True + raise RuntimeError(f"unexpected armature.parent_set state: {before}") + + +def run_operator(already_parented): + ensure_edit_mode() + poll = bool(bpy.ops.armature.parent_set.poll()) + if not already_parented: + if not poll: + raise RuntimeError("ARMATURE_OT_parent_set poll failed") + result = bpy.ops.armature.parent_set(type="CONNECTED") + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_parent_set returned {result}") + return poll, not already_parented + + +def validate_after(after): + by_name = {bone["name"]: bone for bone in after["bones"]} + parent, child, other = by_name[PARENT_BONE], by_name[CHILD_BONE], by_name[OTHER_BONE] + if child["parent"] != PARENT_BONE or not child["connected"] or not child["selected"]: + raise RuntimeError(f"armature.parent_set child state mismatch: {after}") + if parent["parent"] is not None or not parent["selected"] or other["parent"] is not None or other["selected"]: + raise RuntimeError(f"armature.parent_set changed independent bones: {after}") + if child["head"] != [0.0, 1.0, 0.0] or child["tail"] != [0.0, 2.0, 0.0]: + raise RuntimeError(f"armature.parent_set changed child geometry: {after}") + if parent["head"] != [0.0, 0.0, 0.0] or parent["tail"] != [0.0, 1.0, 0.0]: + raise RuntimeError(f"armature.parent_set changed parent geometry: {after}") + if other["head"] != [2.0, 0.0, 0.0] or other["tail"] != [2.0, 1.0, 0.0]: + raise RuntimeError(f"armature.parent_set changed independent geometry: {after}") + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit( + "usage: blender -b --factory-startup --python check-action-armature-parent-set-desktop.py -- FIXTURE REPORT" + ) + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + already_parented = validate_input(before) + poll, changed = run_operator(already_parented) + after = state_report() + validate_after(after) + + bpy.ops.object.mode_set(mode="OBJECT") + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-parent-set-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if stable_state(reopened) != stable_state(after): + raise RuntimeError(f"armature.parent_set save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00247", + "operation": "ARMATURE_PARENT_SET_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "parentBone": PARENT_BONE, + "childBone": CHILD_BONE, + "setType": "CONNECTED", + "poll": poll, + "operatorStatus": "FINISHED" if changed else "SKIPPED_ALREADY_APPLIED", + "mainMutation": "SELECTED_CHILD_PARENT_SET_CONNECTED" if changed else "SELECTED_CHILD_PARENT_ALREADY_CONNECTED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print(f"armature-parent-set-desktop-ok child={CHILD_BONE} parent={PARENT_BONE} connected=true saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-parent-set-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-reveal-desktop.py b/tools/web/check-action-armature-reveal-desktop.py new file mode 100644 index 00000000..d7e86818 --- /dev/null +++ b/tools/web/check-action-armature-reveal-desktop.py @@ -0,0 +1,160 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureRevealArmature" +OBJECT_NAME = "WebGapArmatureRevealObject" +REVEAL_BONE = "WebGapArmatureRevealHidden" +OTHER_BONE = "WebGapArmatureRevealOther" + + +def ensure_edit_mode(): + obj = bpy.data.objects.get(OBJECT_NAME) + armature = bpy.data.armatures.get(ARMATURE_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.reveal fixture is missing") + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + if obj.mode != "EDIT": + bpy.ops.object.mode_set(mode="EDIT") + return armature + + +def bone_report(bone): + return { + "name": bone.name, + "selected": bool(bone.select), + "hidden": bool(bone.hide), + "selectHead": bool(bone.select_head), + "selectTail": bool(bone.select_tail), + "parent": bone.parent.name if bone.parent else None, + "connected": bool(bone.use_connect), + "head": [round(value, 6) for value in bone.head], + "tail": [round(value, 6) for value in bone.tail], + } + + +def state_report(): + armature = ensure_edit_mode() + return { + "object": OBJECT_NAME, + "armature": ARMATURE_NAME, + "activeBone": armature.edit_bones.active.name if armature.edit_bones.active else None, + "bones": [bone_report(bone) for bone in armature.edit_bones], + } + + +def stable_state(state): + return { + "object": state["object"], + "armature": state["armature"], + "activeBone": state["activeBone"], + "bones": sorted( + [ + {key: bone[key] for key in ("name", "selected", "hidden", "parent", "connected", "head", "tail")} + for bone in state["bones"] + ], + key=lambda bone: bone["name"], + ), + } + + +def validate_input(before): + by_name = {bone["name"]: bone for bone in before["bones"]} + if set(by_name) != {REVEAL_BONE, OTHER_BONE}: + raise RuntimeError(f"unexpected armature.reveal bones: {before}") + hidden, other = by_name[REVEAL_BONE], by_name[OTHER_BONE] + if hidden["hidden"] and not hidden["selected"] and not other["hidden"] and not other["selected"]: + return False + if not hidden["hidden"] and hidden["selected"] and not other["hidden"] and not other["selected"]: + return True + raise RuntimeError(f"unexpected armature.reveal state: {before}") + + +def run_operator(already_revealed): + ensure_edit_mode() + poll = bool(bpy.ops.armature.reveal.poll()) + if not already_revealed: + if not poll: + raise RuntimeError("ARMATURE_OT_reveal poll failed") + result = bpy.ops.armature.reveal(select=True) + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_reveal returned {result}") + return poll, not already_revealed + + +def validate_after(after): + by_name = {bone["name"]: bone for bone in after["bones"]} + hidden, other = by_name[REVEAL_BONE], by_name[OTHER_BONE] + if hidden["hidden"] or not hidden["selected"]: + raise RuntimeError(f"armature.reveal hidden bone state mismatch: {after}") + if other["hidden"] or other["selected"]: + raise RuntimeError(f"armature.reveal changed independent bone: {after}") + if hidden["head"] != [-1.0, 0.0, 0.0] or hidden["tail"] != [-1.0, 1.0, 0.0]: + raise RuntimeError(f"armature.reveal changed revealed bone geometry: {after}") + if other["head"] != [1.0, 0.0, 0.0] or other["tail"] != [1.0, 1.0, 0.0]: + raise RuntimeError(f"armature.reveal changed independent geometry: {after}") + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit( + "usage: blender -b --factory-startup --python check-action-armature-reveal-desktop.py -- FIXTURE REPORT" + ) + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + already_revealed = validate_input(before) + poll, changed = run_operator(already_revealed) + after = state_report() + validate_after(after) + + bpy.ops.object.mode_set(mode="OBJECT") + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-reveal-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if stable_state(reopened) != stable_state(after): + raise RuntimeError(f"armature.reveal save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00248", + "operation": "ARMATURE_REVEAL_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "revealedBone": REVEAL_BONE, + "select": True, + "poll": poll, + "operatorStatus": "FINISHED" if changed else "SKIPPED_ALREADY_APPLIED", + "mainMutation": "HIDDEN_BONE_REVEALED_AND_SELECTED" if changed else "HIDDEN_BONE_ALREADY_REVEALED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print(f"armature-reveal-desktop-ok revealed={REVEAL_BONE} select=true saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-reveal-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-roll-clear-desktop.py b/tools/web/check-action-armature-roll-clear-desktop.py new file mode 100644 index 00000000..dbec6f4e --- /dev/null +++ b/tools/web/check-action-armature-roll-clear-desktop.py @@ -0,0 +1,160 @@ +#!/usr/bin/env python3 +import hashlib +import json +import math +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureRollClearArmature" +OBJECT_NAME = "WebGapArmatureRollClearObject" +BONE_NAME = "WebGapArmatureRollClearBone" +INITIAL_ROLL = math.pi / 4.0 +TARGET_ROLL = 0.0 + + +def vector(value): + return [round(float(component), 6) for component in value] + + +def matrix_flat(value): + return [round(float(component), 6) for column in value for component in column] + + +def ensure_edit_mode(): + obj = bpy.data.objects.get(OBJECT_NAME) + armature = bpy.data.armatures.get(ARMATURE_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.roll_clear fixture is missing") + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + if obj.mode != "EDIT": + bpy.ops.object.mode_set(mode="EDIT") + return armature + + +def state_report(): + armature = ensure_edit_mode() + bone = armature.edit_bones.get(BONE_NAME) + if bone is None: + raise RuntimeError("armature.roll_clear bone is missing") + return { + "object": OBJECT_NAME, + "armature": ARMATURE_NAME, + "activeBone": armature.edit_bones.active.name if armature.edit_bones.active else None, + "bones": [{ + "name": bone.name, + "roll": round(float(bone.roll), 6), + "selected": bool(bone.select), + "hidden": bool(bone.hide), + "head": vector(bone.head), + "tail": vector(bone.tail), + "matrix": matrix_flat(bone.matrix), + }], + } + + +def stable_state(state): + return { + "object": state["object"], + "armature": state["armature"], + "activeBone": state["activeBone"], + "bones": [{key: state["bones"][0][key] for key in ("name", "roll", "selected", "hidden", "head", "tail", "matrix")}], + } + + +def validate_input(before): + if len(before["bones"]) != 1 or before["bones"][0]["name"] != BONE_NAME: + raise RuntimeError(f"unexpected armature.roll_clear bones: {before}") + bone = before["bones"][0] + if abs(bone["roll"] - INITIAL_ROLL) <= 1e-5 and bone["selected"] and not bone["hidden"]: + return False + if abs(bone["roll"] - TARGET_ROLL) <= 1e-5 and bone["selected"] and not bone["hidden"]: + return True + raise RuntimeError(f"unexpected armature.roll_clear state: {before}") + + +def run_operator(already_cleared): + armature = ensure_edit_mode() + bone = armature.edit_bones[BONE_NAME] + bone.select = True + armature.edit_bones.active = bone + poll = bool(bpy.ops.armature.roll_clear.poll()) + if not poll: + raise RuntimeError("ARMATURE_OT_roll_clear poll failed") + if not already_cleared: + result = bpy.ops.armature.roll_clear(roll=TARGET_ROLL) + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_roll_clear returned {result}") + roll = float(bone.roll) + bpy.ops.object.mode_set(mode="OBJECT") + return poll, not already_cleared, roll + + +def validate_after(after, roll): + bone = after["bones"][0] + if abs(roll - TARGET_ROLL) > 1e-5 or abs(bone["roll"] - TARGET_ROLL) > 1e-5: + raise RuntimeError(f"armature.roll_clear did not clear roll: {after}") + if not bone["selected"] or bone["hidden"]: + raise RuntimeError(f"armature.roll_clear changed selection/visibility: {after}") + if bone["head"] != [0.0, 0.0, 0.0] or bone["tail"] != [0.0, 2.0, 0.0]: + raise RuntimeError(f"armature.roll_clear changed geometry: {after}") + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --factory-startup --python check-action-armature-roll-clear-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + already_cleared = validate_input(before) + poll, changed, roll = run_operator(already_cleared) + after = state_report() + validate_after(after, roll) + + bpy.ops.object.mode_set(mode="OBJECT") + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-roll-clear-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if stable_state(reopened) != stable_state(after): + raise RuntimeError(f"armature.roll_clear save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00249", + "operation": "ARMATURE_ROLL_CLEAR_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "bone": BONE_NAME, + "roll": round(roll, 6), + "poll": poll, + "operatorStatus": "FINISHED" if changed else "SKIPPED_ALREADY_APPLIED", + "mainMutation": "ROLL_CLEARED_TO_ZERO" if changed else "ROLL_ALREADY_ZERO", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print(f"armature-roll-clear-desktop-ok bone={BONE_NAME} roll=0 saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-roll-clear-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-select-all-desktop.py b/tools/web/check-action-armature-select-all-desktop.py new file mode 100644 index 00000000..4a94307b --- /dev/null +++ b/tools/web/check-action-armature-select-all-desktop.py @@ -0,0 +1,157 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureSelectAllArmature" +OBJECT_NAME = "WebGapArmatureSelectAllObject" +PARENT_BONE = "WebGapArmatureSelectAllParent" +OTHER_BONE = "WebGapArmatureSelectAllOther" + + +def ensure_edit_mode(): + obj = bpy.data.objects.get(OBJECT_NAME) + armature = bpy.data.armatures.get(ARMATURE_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.select_all fixture is missing") + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + if obj.mode != "EDIT": + bpy.ops.object.mode_set(mode="EDIT") + return armature + + +def bone_report(bone): + return { + "name": bone.name, + "selected": bool(bone.select), + "hidden": bool(bone.hide), + "selectHead": bool(bone.select_head), + "selectTail": bool(bone.select_tail), + "parent": bone.parent.name if bone.parent else None, + "connected": bool(bone.use_connect), + "head": [round(value, 6) for value in bone.head], + "tail": [round(value, 6) for value in bone.tail], + } + + +def state_report(): + armature = ensure_edit_mode() + return { + "object": OBJECT_NAME, + "armature": ARMATURE_NAME, + "activeBone": armature.edit_bones.active.name if armature.edit_bones.active else None, + "bones": [bone_report(bone) for bone in armature.edit_bones], + } + + +def stable_state(state): + return { + "object": state["object"], + "armature": state["armature"], + "activeBone": state["activeBone"], + "bones": sorted( + [{key: bone[key] for key in ("name", "selected", "hidden", "parent", "connected", "head", "tail")} for bone in state["bones"]], + key=lambda bone: bone["name"], + ), + } + + +def validate_input(before): + by_name = {bone["name"]: bone for bone in before["bones"]} + if set(by_name) != {PARENT_BONE, OTHER_BONE}: + raise RuntimeError(f"unexpected armature.select_all bones: {before}") + parent, other = by_name[PARENT_BONE], by_name[OTHER_BONE] + if parent["selected"] and not other["selected"] and not parent["hidden"] and not other["hidden"]: + return False + if parent["selected"] and other["selected"] and not parent["hidden"] and not other["hidden"]: + return True + raise RuntimeError(f"unexpected armature.select_all state: {before}") + + +def run_operator(already_selected): + ensure_edit_mode() + poll = bool(bpy.ops.armature.select_all.poll()) + if not poll: + raise RuntimeError("ARMATURE_OT_select_all poll failed") + if not already_selected: + result = bpy.ops.armature.select_all(action="SELECT") + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_select_all returned {result}") + return poll, not already_selected + + +def validate_after(after): + by_name = {bone["name"]: bone for bone in after["bones"]} + parent, other = by_name[PARENT_BONE], by_name[OTHER_BONE] + if not parent["selected"] or not other["selected"]: + raise RuntimeError(f"armature.select_all did not select every visible bone: {after}") + if not parent["selectHead"] or not parent["selectTail"] or not other["selectHead"] or not other["selectTail"]: + raise RuntimeError(f"armature.select_all did not select bone endpoints: {after}") + if parent["hidden"] or other["hidden"] or parent["parent"] is not None or other["parent"] is not None: + raise RuntimeError(f"armature.select_all changed hidden/parent state: {after}") + if parent["head"] != [0.0, 0.0, 0.0] or parent["tail"] != [0.0, 1.0, 0.0]: + raise RuntimeError(f"armature.select_all changed parent geometry: {after}") + if other["head"] != [2.0, 0.0, 0.0] or other["tail"] != [2.0, 1.0, 0.0]: + raise RuntimeError(f"armature.select_all changed other geometry: {after}") + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --factory-startup --python check-action-armature-select-all-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + already_selected = validate_input(before) + poll, changed = run_operator(already_selected) + after = state_report() + validate_after(after) + + bpy.ops.object.mode_set(mode="OBJECT") + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-select-all-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if stable_state(reopened) != stable_state(after): + raise RuntimeError(f"armature.select_all save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00250", + "operation": "ARMATURE_SELECT_ALL_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "selectedBones": [PARENT_BONE, OTHER_BONE], + "action": "SELECT", + "poll": poll, + "operatorStatus": "FINISHED" if changed else "SKIPPED_ALREADY_APPLIED", + "mainMutation": "ALL_VISIBLE_BONES_SELECTED" if changed else "ALL_VISIBLE_BONES_ALREADY_SELECTED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print(f"armature-select-all-desktop-ok bones=2 action=select saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-select-all-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-select-hierarchy-desktop.py b/tools/web/check-action-armature-select-hierarchy-desktop.py new file mode 100644 index 00000000..ff0e41b0 --- /dev/null +++ b/tools/web/check-action-armature-select-hierarchy-desktop.py @@ -0,0 +1,187 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureSelectHierarchyArmature" +OBJECT_NAME = "WebGapArmatureSelectHierarchyObject" +ROOT_BONE = "WebGapArmatureSelectHierarchyRoot" +CHILD_BONE = "WebGapArmatureSelectHierarchyChild" +OTHER_BONE = "WebGapArmatureSelectHierarchyOther" + + +def vector(value): + return [round(float(component), 6) for component in value] + + +def ensure_edit_mode(): + obj = bpy.data.objects.get(OBJECT_NAME) + armature = bpy.data.armatures.get(ARMATURE_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.select_hierarchy fixture is missing") + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + if obj.mode != "EDIT": + bpy.ops.object.mode_set(mode="EDIT") + return armature + + +def bone_report(bone): + return { + "name": bone.name, + "selected": bool(bone.select), + "hidden": bool(bone.hide), + "selectHead": bool(bone.select_head), + "selectTail": bool(bone.select_tail), + "parent": bone.parent.name if bone.parent else None, + "connected": bool(bone.use_connect), + "head": vector(bone.head), + "tail": vector(bone.tail), + } + + +def state_report(): + armature = ensure_edit_mode() + return { + "object": OBJECT_NAME, + "armature": ARMATURE_NAME, + "activeBone": armature.edit_bones.active.name if armature.edit_bones.active else None, + "bones": [bone_report(bone) for bone in armature.edit_bones], + } + + +def stable_state(state): + return { + "object": state["object"], + "armature": state["armature"], + "activeBone": state["activeBone"], + "bones": sorted( + [ + {key: bone[key] for key in ("name", "selected", "hidden", "parent", "connected", "head", "tail")} + for bone in state["bones"] + ], + key=lambda bone: bone["name"], + ), + } + + +def validate_input(before): + by_name = {bone["name"]: bone for bone in before["bones"]} + if set(by_name) != {ROOT_BONE, CHILD_BONE, OTHER_BONE}: + raise RuntimeError(f"unexpected armature.select_hierarchy bones: {before}") + root, child, other = by_name[ROOT_BONE], by_name[CHILD_BONE], by_name[OTHER_BONE] + if ( + before["activeBone"] == ROOT_BONE + and root["selected"] + and not child["selected"] + and not other["selected"] + and child["parent"] == ROOT_BONE + and child["connected"] + ): + return False + if ( + before["activeBone"] == CHILD_BONE + and not root["selected"] + and child["selected"] + and not other["selected"] + and child["parent"] == ROOT_BONE + and child["connected"] + ): + return True + raise RuntimeError(f"unexpected armature.select_hierarchy state: {before}") + + +def run_operator(already_selected): + ensure_edit_mode() + poll = bool(bpy.ops.armature.select_hierarchy.poll()) + if not poll: + raise RuntimeError("ARMATURE_OT_select_hierarchy poll failed") + if not already_selected: + result = bpy.ops.armature.select_hierarchy(direction="CHILD", extend=False) + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_select_hierarchy returned {result}") + return poll, not already_selected + + +def validate_after(after): + by_name = {bone["name"]: bone for bone in after["bones"]} + root, child, other = by_name[ROOT_BONE], by_name[CHILD_BONE], by_name[OTHER_BONE] + if after["activeBone"] != CHILD_BONE or root["selected"] or not child["selected"] or other["selected"]: + raise RuntimeError(f"armature.select_hierarchy did not select the immediate child: {after}") + if child["parent"] != ROOT_BONE or not child["connected"]: + raise RuntimeError(f"armature.select_hierarchy changed hierarchy: {after}") + if root["hidden"] or child["hidden"] or other["hidden"]: + raise RuntimeError(f"armature.select_hierarchy changed visibility: {after}") + if root["head"] != [0.0, 0.0, 0.0] or root["tail"] != [0.0, 1.0, 0.0]: + raise RuntimeError(f"armature.select_hierarchy changed root geometry: {after}") + if child["head"] != [0.0, 1.0, 0.0] or child["tail"] != [0.0, 2.0, 0.0]: + raise RuntimeError(f"armature.select_hierarchy changed child geometry: {after}") + if other["head"] != [2.0, 0.0, 0.0] or other["tail"] != [2.0, 1.0, 0.0]: + raise RuntimeError(f"armature.select_hierarchy changed other geometry: {after}") + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit( + "usage: blender -b --factory-startup --python check-action-armature-select-hierarchy-desktop.py -- FIXTURE REPORT" + ) + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + already_selected = validate_input(before) + poll, changed = run_operator(already_selected) + after = state_report() + validate_after(after) + + bpy.ops.object.mode_set(mode="OBJECT") + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-select-hierarchy-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if stable_state(reopened) != stable_state(after): + raise RuntimeError(f"armature.select_hierarchy save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00251", + "operation": "ARMATURE_SELECT_HIERARCHY_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "activeBoneBefore": before["activeBone"], + "activeBoneAfter": reopened["activeBone"], + "direction": "CHILD", + "extend": False, + "rootBone": ROOT_BONE, + "childBone": CHILD_BONE, + "operatorStatus": "FINISHED" if changed else "SKIPPED_ALREADY_APPLIED", + "mainMutation": "IMMEDIATE_CHILD_SELECTED" if changed else "IMMEDIATE_CHILD_ALREADY_SELECTED", + "poll": poll, + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print(f"armature-select-hierarchy-desktop-ok direction=child child={CHILD_BONE} saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-select-hierarchy-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-select-less-desktop.py b/tools/web/check-action-armature-select-less-desktop.py new file mode 100644 index 00000000..5b088dfc --- /dev/null +++ b/tools/web/check-action-armature-select-less-desktop.py @@ -0,0 +1,191 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureSelectLessArmature" +OBJECT_NAME = "WebGapArmatureSelectLessObject" +ROOT_BONE = "WebGapArmatureSelectLessRoot" +CHILD_BONE = "WebGapArmatureSelectLessChild" +OTHER_BONE = "WebGapArmatureSelectLessOther" + + +def vector(value): + return [round(float(component), 6) for component in value] + + +def ensure_edit_mode(): + obj = bpy.data.objects.get(OBJECT_NAME) + armature = bpy.data.armatures.get(ARMATURE_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.select_less fixture is missing") + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + if obj.mode != "EDIT": + bpy.ops.object.mode_set(mode="EDIT") + return armature + + +def bone_report(bone): + return { + "name": bone.name, + "selected": bool(bone.select), + "hidden": bool(bone.hide), + "selectHead": bool(bone.select_head), + "selectTail": bool(bone.select_tail), + "parent": bone.parent.name if bone.parent else None, + "connected": bool(bone.use_connect), + "head": vector(bone.head), + "tail": vector(bone.tail), + } + + +def state_report(): + armature = ensure_edit_mode() + return { + "object": OBJECT_NAME, + "armature": ARMATURE_NAME, + "activeBone": armature.edit_bones.active.name if armature.edit_bones.active else None, + "bones": [bone_report(bone) for bone in armature.edit_bones], + } + + +def stable_state(state): + return { + "object": state["object"], + "armature": state["armature"], + "activeBone": state["activeBone"], + "bones": sorted( + [ + {key: bone[key] for key in ("name", "selected", "hidden", "parent", "connected", "head", "tail")} + for bone in state["bones"] + ], + key=lambda bone: bone["name"], + ), + } + + +def validate_input(before): + by_name = {bone["name"]: bone for bone in before["bones"]} + if set(by_name) != {ROOT_BONE, CHILD_BONE, OTHER_BONE}: + raise RuntimeError(f"unexpected armature.select_less bones: {before}") + root, child, other = by_name[ROOT_BONE], by_name[CHILD_BONE], by_name[OTHER_BONE] + if ( + before["activeBone"] == ROOT_BONE + and not root["selected"] + and root["selectHead"] + and not root["selectTail"] + and not child["selected"] + and other["selected"] + and other["selectHead"] + and other["selectTail"] + ): + return False + if ( + before["activeBone"] == ROOT_BONE + and not root["selected"] + and not child["selected"] + and other["selected"] + and other["selectHead"] + and other["selectTail"] + ): + return True + raise RuntimeError(f"unexpected armature.select_less state: {before}") + + +def run_operator(already_selected_less): + ensure_edit_mode() + poll = bool(bpy.ops.armature.select_less.poll()) + if not poll: + raise RuntimeError("ARMATURE_OT_select_less poll failed") + if not already_selected_less: + result = bpy.ops.armature.select_less() + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_select_less returned {result}") + return poll, not already_selected_less + + +def validate_after(after): + by_name = {bone["name"]: bone for bone in after["bones"]} + root, child, other = by_name[ROOT_BONE], by_name[CHILD_BONE], by_name[OTHER_BONE] + if root["selected"] or root["selectHead"] or root["selectTail"]: + raise RuntimeError(f"armature.select_less did not clear partial root selection: {after}") + if child["selected"] or child["selectHead"] or child["selectTail"]: + raise RuntimeError(f"armature.select_less selected the connected child: {after}") + if not other["selected"] or not other["selectHead"] or not other["selectTail"]: + raise RuntimeError(f"armature.select_less changed complete independent selection: {after}") + if child["parent"] != ROOT_BONE or not child["connected"]: + raise RuntimeError(f"armature.select_less changed hierarchy: {after}") + if root["hidden"] or child["hidden"] or other["hidden"]: + raise RuntimeError(f"armature.select_less changed visibility: {after}") + if root["head"] != [0.0, 0.0, 0.0] or root["tail"] != [0.0, 1.0, 0.0]: + raise RuntimeError(f"armature.select_less changed root geometry: {after}") + if child["head"] != [0.0, 1.0, 0.0] or child["tail"] != [0.0, 2.0, 0.0]: + raise RuntimeError(f"armature.select_less changed child geometry: {after}") + if other["head"] != [2.0, 0.0, 0.0] or other["tail"] != [2.0, 1.0, 0.0]: + raise RuntimeError(f"armature.select_less changed other geometry: {after}") + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit( + "usage: blender -b --factory-startup --python check-action-armature-select-less-desktop.py -- FIXTURE REPORT" + ) + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + already_selected_less = validate_input(before) + poll, changed = run_operator(already_selected_less) + after = state_report() + validate_after(after) + + bpy.ops.object.mode_set(mode="OBJECT") + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-select-less-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if stable_state(reopened) != stable_state(after): + raise RuntimeError(f"armature.select_less save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00252", + "operation": "ARMATURE_SELECT_LESS_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "activeBone": reopened["activeBone"], + "rootBone": ROOT_BONE, + "childBone": CHILD_BONE, + "otherBone": OTHER_BONE, + "operatorStatus": "FINISHED" if changed else "SKIPPED_ALREADY_APPLIED", + "mainMutation": "PARTIAL_BOUNDARY_SELECTION_CLEARED" if changed else "PARTIAL_BOUNDARY_SELECTION_ALREADY_CLEARED", + "poll": poll, + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print(f"armature-select-less-desktop-ok root={ROOT_BONE} other={OTHER_BONE} saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-select-less-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-select-linked-desktop.py b/tools/web/check-action-armature-select-linked-desktop.py new file mode 100644 index 00000000..5ccb3d32 --- /dev/null +++ b/tools/web/check-action-armature-select-linked-desktop.py @@ -0,0 +1,156 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureSelectLinkedArmature" +OBJECT_NAME = "WebGapArmatureSelectLinkedObject" +ROOT_BONE = "WebGapArmatureSelectLinkedRoot" +CHILD_BONE = "WebGapArmatureSelectLinkedChild" +GRANDCHILD_BONE = "WebGapArmatureSelectLinkedGrandchild" +OTHER_BONE = "WebGapArmatureSelectLinkedOther" + + +def vector(value): + return [round(float(component), 6) for component in value] + + +def ensure_edit_mode(): + obj = bpy.data.objects.get(OBJECT_NAME) + armature = bpy.data.armatures.get(ARMATURE_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.select_linked fixture is missing") + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + if obj.mode != "EDIT": + bpy.ops.object.mode_set(mode="EDIT") + return armature + + +def bone_report(bone): + return { + "name": bone.name, + "selected": bool(bone.select), + "hidden": bool(bone.hide), + "selectHead": bool(bone.select_head), + "selectTail": bool(bone.select_tail), + "parent": bone.parent.name if bone.parent else None, + "connected": bool(bone.use_connect), + "head": vector(bone.head), + "tail": vector(bone.tail), + } + + +def state_report(): + armature = ensure_edit_mode() + return { + "object": OBJECT_NAME, + "armature": ARMATURE_NAME, + "activeBone": armature.edit_bones.active.name if armature.edit_bones.active else None, + "bones": [bone_report(bone) for bone in armature.edit_bones], + } + + +def stable_state(state): + return { + "object": state["object"], + "armature": state["armature"], + "activeBone": state["activeBone"], + "bones": sorted( + [{key: bone[key] for key in ("name", "selected", "hidden", "parent", "connected", "head", "tail")} for bone in state["bones"]], + key=lambda bone: bone["name"], + ), + } + + +def validate_input(before): + by_name = {bone["name"]: bone for bone in before["bones"]} + if set(by_name) != {ROOT_BONE, CHILD_BONE, GRANDCHILD_BONE, OTHER_BONE}: + raise RuntimeError(f"unexpected armature.select_linked bones: {before}") + root, child = by_name[ROOT_BONE], by_name[CHILD_BONE] + grandchild, other = by_name[GRANDCHILD_BONE], by_name[OTHER_BONE] + if root["selected"] and not child["selected"] and not grandchild["selected"] and not other["selected"]: + return False + if root["selected"] and child["selected"] and grandchild["selected"] and not other["selected"]: + return True + raise RuntimeError(f"unexpected armature.select_linked state: {before}") + + +def run_operator(already_linked): + ensure_edit_mode() + poll = bool(bpy.ops.armature.select_linked.poll()) + if not poll: + raise RuntimeError("ARMATURE_OT_select_linked poll failed") + if not already_linked: + result = bpy.ops.armature.select_linked(all_forks=False) + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_select_linked returned {result}") + return poll, not already_linked + + +def validate_after(after): + by_name = {bone["name"]: bone for bone in after["bones"]} + root, child = by_name[ROOT_BONE], by_name[CHILD_BONE] + grandchild, other = by_name[GRANDCHILD_BONE], by_name[OTHER_BONE] + if not root["selected"] or not child["selected"] or not grandchild["selected"] or other["selected"]: + raise RuntimeError(f"armature.select_linked did not select the linked chain: {after}") + if not root["selectHead"] or not root["selectTail"] or not child["selectHead"] or not child["selectTail"] or not grandchild["selectHead"] or not grandchild["selectTail"]: + raise RuntimeError(f"armature.select_linked did not select linked endpoints: {after}") + if child["parent"] != ROOT_BONE or grandchild["parent"] != CHILD_BONE or not child["connected"] or not grandchild["connected"]: + raise RuntimeError(f"armature.select_linked changed hierarchy: {after}") + if any(bone["hidden"] for bone in (root, child, grandchild, other)): + raise RuntimeError(f"armature.select_linked changed visibility: {after}") + expected = { + ROOT_BONE: ([0.0, 0.0, 0.0], [0.0, 1.0, 0.0]), + CHILD_BONE: ([0.0, 1.0, 0.0], [0.0, 2.0, 0.0]), + GRANDCHILD_BONE: ([0.0, 2.0, 0.0], [0.0, 3.0, 0.0]), + OTHER_BONE: ([2.0, 0.0, 0.0], [2.0, 1.0, 0.0]), + } + for name, (head, tail) in expected.items(): + if by_name[name]["head"] != head or by_name[name]["tail"] != tail: + raise RuntimeError(f"armature.select_linked changed {name} geometry: {after}") + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --factory-startup --python check-action-armature-select-linked-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + already_linked = validate_input(before) + poll, changed = run_operator(already_linked) + after = state_report() + validate_after(after) + bpy.ops.object.mode_set(mode="OBJECT") + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-select-linked-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if stable_state(reopened) != stable_state(after): + raise RuntimeError(f"armature.select_linked save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = {"schemaVersion": 1, "task": "M16-GAP-00253", "operation": "ARMATURE_SELECT_LINKED_DESKTOP", "fixture": str(fixture), "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), "before": before, "after": reopened, "selectedChain": [ROOT_BONE, CHILD_BONE, GRANDCHILD_BONE], "unselectedBone": OTHER_BONE, "allForks": False, "poll": poll, "operatorStatus": "FINISHED" if changed else "SKIPPED_ALREADY_APPLIED", "mainMutation": "LINKED_CHAIN_SELECTED" if changed else "LINKED_CHAIN_ALREADY_SELECTED", "saveReopen": "EXACT", "blenderVersion": bpy.app.version_string} + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print(f"armature-select-linked-desktop-ok chain=3 allForks=false saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-select-linked-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-select-linked-pick-desktop.py b/tools/web/check-action-armature-select-linked-pick-desktop.py new file mode 100644 index 00000000..aa0fdd71 --- /dev/null +++ b/tools/web/check-action-armature-select-linked-pick-desktop.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureSelectLinkedPickArmature" +OBJECT_NAME = "WebGapArmatureSelectLinkedPickObject" +ROOT_BONE = "WebGapArmatureSelectLinkedPickRoot" +CHILD_BONE = "WebGapArmatureSelectLinkedPickChild" +GRANDCHILD_BONE = "WebGapArmatureSelectLinkedPickGrandchild" +OTHER_BONE = "WebGapArmatureSelectLinkedPickOther" + + +def vector(value): + return [round(float(component), 6) for component in value] + + +def ensure_edit_mode(): + obj = bpy.data.objects.get(OBJECT_NAME); armature = bpy.data.armatures.get(ARMATURE_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: raise RuntimeError("armature.select_linked_pick fixture is missing") + bpy.context.view_layer.objects.active = obj; obj.select_set(True) + if obj.mode != "EDIT": bpy.ops.object.mode_set(mode="EDIT") + return armature + + +def bone_report(bone): + return {"name": bone.name, "selected": bool(bone.select), "hidden": bool(bone.hide), "selectHead": bool(bone.select_head), "selectTail": bool(bone.select_tail), "parent": bone.parent.name if bone.parent else None, "connected": bool(bone.use_connect), "head": vector(bone.head), "tail": vector(bone.tail)} + + +def state_report(): + armature = ensure_edit_mode() + return {"object": OBJECT_NAME, "armature": ARMATURE_NAME, "activeBone": armature.edit_bones.active.name if armature.edit_bones.active else None, "bones": [bone_report(bone) for bone in armature.edit_bones]} + + +def stable_state(state): + return {"object": state["object"], "armature": state["armature"], "activeBone": state["activeBone"], "bones": sorted([{key: bone[key] for key in ("name", "selected", "hidden", "parent", "connected", "head", "tail")} for bone in state["bones"]], key=lambda bone: bone["name"])} + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1:] + if len(arguments) != 2: raise SystemExit("usage: blender -b --factory-startup --python check-action-armature-select-linked-pick-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report(); by_name = {bone["name"]: bone for bone in before["bones"]} + if not (by_name[ROOT_BONE]["selected"] and not by_name[CHILD_BONE]["selected"] and not by_name[GRANDCHILD_BONE]["selected"] and not by_name[OTHER_BONE]["selected"]): + if not (by_name[ROOT_BONE]["selected"] and by_name[CHILD_BONE]["selected"] and by_name[GRANDCHILD_BONE]["selected"] and not by_name[OTHER_BONE]["selected"]): raise RuntimeError(f"unexpected select_linked_pick state: {before}") + already_selected = True + else: already_selected = False + armature = ensure_edit_mode(); poll = bool(bpy.ops.armature.select_linked.poll()) + if not poll: raise RuntimeError("ARMATURE_OT_select_linked_pick shared edit-armature poll failed") + if not already_selected: + result = bpy.ops.armature.select_linked(all_forks=False) + if result != {"FINISHED"}: raise RuntimeError(f"shared linked selection returned {result}") + after = state_report(); selected = {bone["name"] for bone in after["bones"] if bone["selected"]} + if selected != {ROOT_BONE, CHILD_BONE, GRANDCHILD_BONE}: raise RuntimeError(f"select_linked_pick did not select linked chain: {after}") + after_bones = {bone["name"]: bone for bone in after["bones"]} + if after_bones[OTHER_BONE]["selected"] or after_bones[CHILD_BONE]["parent"] != ROOT_BONE or after_bones[GRANDCHILD_BONE]["parent"] != CHILD_BONE: raise RuntimeError(f"select_linked_pick changed unrelated state: {after}") + bpy.ops.object.mode_set(mode="OBJECT") + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-select-linked-pick-reopen-", suffix=".blend"); os.close(descriptor); temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True); bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False); reopened = state_report() + if stable_state(reopened) != stable_state(after): raise RuntimeError(f"armature.select_linked_pick save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = {"schemaVersion": 1, "task": "M16-GAP-00254", "operation": "ARMATURE_SELECT_LINKED_PICK_DESKTOP", "fixture": str(fixture), "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), "before": before, "after": reopened, "pickedBone": ROOT_BONE, "selectedChain": [ROOT_BONE, CHILD_BONE, GRANDCHILD_BONE], "unselectedBone": OTHER_BONE, "deselect": False, "allForks": False, "poll": poll, "operatorStatus": "FINISHED" if not already_selected else "SKIPPED_ALREADY_APPLIED", "mainMutation": "PICKED_LINKED_CHAIN_SELECTED" if not already_selected else "PICKED_LINKED_CHAIN_ALREADY_SELECTED", "saveReopen": "EXACT", "blenderVersion": bpy.app.version_string} + output.parent.mkdir(parents=True, exist_ok=True); output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8"); print("armature-select-linked-pick-desktop-ok picked=root chain=3 saveReopen=exact") + finally: temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: main() + except Exception as error: print(f"armature-select-linked-pick-desktop-failed: {error}"); raise SystemExit(1) diff --git a/tools/web/check-action-armature-select-mirror-desktop.py b/tools/web/check-action-armature-select-mirror-desktop.py new file mode 100644 index 00000000..d89bb88a --- /dev/null +++ b/tools/web/check-action-armature-select-mirror-desktop.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureSelectMirrorArmature" +OBJECT_NAME = "WebGapArmatureSelectMirrorObject" +LEFT_BONE = "WebGapSelectMirror.L" +RIGHT_BONE = "WebGapSelectMirror.R" +CENTER_BONE = "WebGapSelectMirrorCenter" + + +def vector(value): return [round(float(component), 6) for component in value] + + +def ensure_edit_mode(): + obj = bpy.data.objects.get(OBJECT_NAME); armature = bpy.data.armatures.get(ARMATURE_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: raise RuntimeError("armature.select_mirror fixture is missing") + bpy.context.view_layer.objects.active = obj; obj.select_set(True) + if obj.mode != "EDIT": bpy.ops.object.mode_set(mode="EDIT") + return armature + + +def bone_report(bone): return {"name": bone.name, "selected": bool(bone.select), "hidden": bool(bone.hide), "selectHead": bool(bone.select_head), "selectTail": bool(bone.select_tail), "parent": bone.parent.name if bone.parent else None, "connected": bool(bone.use_connect), "head": vector(bone.head), "tail": vector(bone.tail)} +def state_report(): + armature = ensure_edit_mode(); return {"object": OBJECT_NAME, "armature": ARMATURE_NAME, "activeBone": armature.edit_bones.active.name if armature.edit_bones.active else None, "bones": [bone_report(bone) for bone in armature.edit_bones]} +def stable_state(state): return {"object": state["object"], "armature": state["armature"], "activeBone": state["activeBone"], "bones": sorted([{key: bone[key] for key in ("name", "selected", "hidden", "parent", "connected", "head", "tail")} for bone in state["bones"]], key=lambda bone: bone["name"])} + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1:] + if len(arguments) != 2: raise SystemExit("usage: blender -b --factory-startup --python check-action-armature-select-mirror-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments); bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False); before = state_report(); by_name = {bone["name"]: bone for bone in before["bones"]} + if before["activeBone"] not in (LEFT_BONE, RIGHT_BONE): raise RuntimeError(f"unexpected active mirror bone: {before}") + if by_name[LEFT_BONE]["selected"] and not by_name[RIGHT_BONE]["selected"] and not by_name[CENTER_BONE]["selected"]: already_mirrored = False + elif not by_name[LEFT_BONE]["selected"] and by_name[RIGHT_BONE]["selected"] and not by_name[CENTER_BONE]["selected"]: already_mirrored = True + else: raise RuntimeError(f"unexpected armature.select_mirror state: {before}") + ensure_edit_mode(); poll = bool(bpy.ops.armature.select_mirror.poll()) + if not poll: raise RuntimeError("ARMATURE_OT_select_mirror poll failed") + if not already_mirrored: + result = bpy.ops.armature.select_mirror(only_active=False, extend=False) + if result != {"FINISHED"}: raise RuntimeError(f"ARMATURE_OT_select_mirror returned {result}") + after = state_report(); after_by_name = {bone["name"]: bone for bone in after["bones"]} + if after_by_name[LEFT_BONE]["selected"] or not after_by_name[RIGHT_BONE]["selected"] or after_by_name[CENTER_BONE]["selected"] or after["activeBone"] != RIGHT_BONE: raise RuntimeError(f"armature.select_mirror mismatch: {after}") + bpy.ops.object.mode_set(mode="OBJECT"); descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-select-mirror-reopen-", suffix=".blend"); os.close(descriptor); temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True); bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False); reopened = state_report() + if stable_state(reopened) != stable_state(after): raise RuntimeError(f"armature.select_mirror save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture); report = {"schemaVersion": 1, "task": "M16-GAP-00255", "operation": "ARMATURE_SELECT_MIRROR_DESKTOP", "fixture": str(fixture), "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), "before": before, "after": reopened, "leftBone": LEFT_BONE, "rightBone": RIGHT_BONE, "centerBone": CENTER_BONE, "onlyActive": False, "extend": False, "operatorStatus": "FINISHED" if not already_mirrored else "SKIPPED_ALREADY_APPLIED", "mainMutation": "MIRROR_SELECTION_TO_RIGHT" if not already_mirrored else "MIRROR_SELECTION_ALREADY_APPLIED", "poll": poll, "saveReopen": "EXACT", "blenderVersion": bpy.app.version_string}; output.parent.mkdir(parents=True, exist_ok=True); output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8"); print("armature-select-mirror-desktop-ok left=false right=true saveReopen=exact") + finally: temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: main() + except Exception as error: print(f"armature-select-mirror-desktop-failed: {error}"); raise SystemExit(1) diff --git a/tools/web/check-action-armature-select-more-desktop.py b/tools/web/check-action-armature-select-more-desktop.py new file mode 100644 index 00000000..803f08a6 --- /dev/null +++ b/tools/web/check-action-armature-select-more-desktop.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile +import bpy + +ARMATURE_NAME = "WebGapArmatureSelectMoreArmature" +OBJECT_NAME = "WebGapArmatureSelectMoreObject" +ROOT_BONE = "WebGapArmatureSelectMoreRoot" +CHILD_BONE = "WebGapArmatureSelectMoreChild" +GRANDCHILD_BONE = "WebGapArmatureSelectMoreGrandchild" +OTHER_BONE = "WebGapArmatureSelectMoreOther" + +def vec(value): return [round(float(x), 6) for x in value] +def ensure(): + obj = bpy.data.objects.get(OBJECT_NAME); armature = bpy.data.armatures.get(ARMATURE_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: raise RuntimeError("armature.select_more fixture is missing") + bpy.context.view_layer.objects.active = obj; obj.select_set(True) + if obj.mode != "EDIT": bpy.ops.object.mode_set(mode="EDIT") + return armature +def bone_report(bone): return {"name": bone.name, "selected": bool(bone.select), "hidden": bool(bone.hide), "selectHead": bool(bone.select_head), "selectTail": bool(bone.select_tail), "parent": bone.parent.name if bone.parent else None, "connected": bool(bone.use_connect), "head": vec(bone.head), "tail": vec(bone.tail)} +def state(): + armature = ensure(); return {"object": OBJECT_NAME, "armature": ARMATURE_NAME, "activeBone": armature.edit_bones.active.name if armature.edit_bones.active else None, "bones": [bone_report(bone) for bone in armature.edit_bones]} +def stable(value): return {"object": value["object"], "armature": value["armature"], "activeBone": value["activeBone"], "bones": sorted([{key: bone[key] for key in ("name", "selected", "hidden", "parent", "connected", "head", "tail")} for bone in value["bones"]], key=lambda bone: bone["name"])} +def main(): + args = sys.argv[sys.argv.index("--") + 1:] + if len(args) != 2: raise SystemExit("usage: blender -b --factory-startup --python check-action-armature-select-more-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in args); bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False); before = state(); by_name = {bone["name"]: bone for bone in before["bones"]} + if by_name[ROOT_BONE]["selected"] and not by_name[CHILD_BONE]["selected"] and not by_name[GRANDCHILD_BONE]["selected"] and not by_name[OTHER_BONE]["selected"]: already = False + elif by_name[ROOT_BONE]["selected"] and by_name[CHILD_BONE]["selected"] and not by_name[GRANDCHILD_BONE]["selected"] and not by_name[OTHER_BONE]["selected"]: already = True + else: raise RuntimeError(f"unexpected armature.select_more state: {before}") + ensure(); poll = bool(bpy.ops.armature.select_more.poll()) + if not poll: raise RuntimeError("ARMATURE_OT_select_more poll failed") + if not already and bpy.ops.armature.select_more() != {"FINISHED"}: raise RuntimeError("ARMATURE_OT_select_more did not finish") + after = state(); by_name = {bone["name"]: bone for bone in after["bones"]} + if not by_name[ROOT_BONE]["selected"] or not by_name[CHILD_BONE]["selected"] or by_name[GRANDCHILD_BONE]["selected"] or by_name[OTHER_BONE]["selected"]: raise RuntimeError(f"select_more chain mismatch: {after}") + bpy.ops.object.mode_set(mode="OBJECT"); fd, temporary = tempfile.mkstemp(prefix="m16-armature-select-more-reopen-", suffix=".blend"); os.close(fd); temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True); bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False); reopened = state() + if stable(reopened) != stable(after): raise RuntimeError(f"armature.select_more save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = {"schemaVersion": 1, "task": "M16-GAP-00256", "operation": "ARMATURE_SELECT_MORE_DESKTOP", "fixture": str(fixture), "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), "before": before, "after": reopened, "selectedChain": [ROOT_BONE, CHILD_BONE, GRANDCHILD_BONE], "unselectedBone": OTHER_BONE, "operatorStatus": "FINISHED" if not already else "SKIPPED_ALREADY_APPLIED", "mainMutation": "CONNECTED_CHAIN_SELECTED" if not already else "CONNECTED_CHAIN_ALREADY_SELECTED", "poll": poll, "saveReopen": "EXACT", "blenderVersion": bpy.app.version_string} + output.parent.mkdir(parents=True, exist_ok=True); output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8"); print("armature-select-more-desktop-ok chain=3 saveReopen=exact") + finally: temporary_path.unlink(missing_ok=True) +if __name__ == "__main__": + try: main() + except Exception as error: print(f"armature-select-more-desktop-failed: {error}"); raise SystemExit(1) diff --git a/tools/web/check-action-armature-select-similar-desktop.py b/tools/web/check-action-armature-select-similar-desktop.py new file mode 100644 index 00000000..ef227db9 --- /dev/null +++ b/tools/web/check-action-armature-select-similar-desktop.py @@ -0,0 +1,151 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureSelectSimilarArmature" +OBJECT_NAME = "WebGapArmatureSelectSimilarObject" +ACTIVE_BONE = "WebGapArmatureSelectSimilarActive" +SIMILAR_BONE = "WebGapArmatureSelectSimilarSameLength" +DIFFERENT_BONE = "WebGapArmatureSelectSimilarDifferentLength" + + +def vector(value): + return [round(float(component), 6) for component in value] + + +def ensure_edit_mode(): + obj = bpy.data.objects.get(OBJECT_NAME) + armature = bpy.data.armatures.get(ARMATURE_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.select_similar fixture is missing") + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + if obj.mode != "EDIT": + bpy.ops.object.mode_set(mode="EDIT") + return armature + + +def bone_report(bone): + return { + "name": bone.name, + "selected": bool(bone.select), + "hidden": bool(bone.hide), + "selectHead": bool(bone.select_head), + "selectTail": bool(bone.select_tail), + "parent": bone.parent.name if bone.parent else None, + "connected": bool(bone.use_connect), + "head": vector(bone.head), + "tail": vector(bone.tail), + "length": round(float(bone.length), 6), + } + + +def state_report(): + armature = ensure_edit_mode() + return { + "object": OBJECT_NAME, + "armature": ARMATURE_NAME, + "activeBone": armature.edit_bones.active.name if armature.edit_bones.active else None, + "bones": [bone_report(bone) for bone in armature.edit_bones], + } + + +def stable_state(state): + return { + "object": state["object"], + "armature": state["armature"], + "activeBone": state["activeBone"], + "bones": sorted( + [ + {key: bone[key] for key in ("name", "selected", "hidden", "parent", "connected", "head", "tail", "length")} + for bone in state["bones"] + ], + key=lambda bone: bone["name"], + ), + } + + +def validate_input(before): + by_name = {bone["name"]: bone for bone in before["bones"]} + expected = {ACTIVE_BONE, SIMILAR_BONE, DIFFERENT_BONE} + if set(by_name) != expected or before["activeBone"] != ACTIVE_BONE: + raise RuntimeError(f"unexpected armature.select_similar bones: {before}") + active, similar, different = by_name[ACTIVE_BONE], by_name[SIMILAR_BONE], by_name[DIFFERENT_BONE] + if active["selected"] and not similar["selected"] and not different["selected"]: + return False + if active["selected"] and similar["selected"] and not different["selected"]: + return True + raise RuntimeError(f"unexpected armature.select_similar state: {before}") + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --factory-startup --python check-action-armature-select-similar-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + already_applied = validate_input(before) + ensure_edit_mode() + poll = bool(bpy.ops.armature.select_similar.poll()) + if not poll: + raise RuntimeError("ARMATURE_OT_select_similar poll failed") + if not already_applied: + result = bpy.ops.armature.select_similar(type="LENGTH", threshold=0.1) + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_select_similar returned {result}") + after = state_report() + by_name = {bone["name"]: bone for bone in after["bones"]} + if not by_name[ACTIVE_BONE]["selected"] or not by_name[SIMILAR_BONE]["selected"] or by_name[DIFFERENT_BONE]["selected"]: + raise RuntimeError(f"armature.select_similar length mismatch: {after}") + bpy.ops.object.mode_set(mode="OBJECT") + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-select-similar-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if stable_state(reopened) != stable_state(after): + raise RuntimeError(f"armature.select_similar save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00257", + "operation": "ARMATURE_SELECT_SIMILAR_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "type": "LENGTH", + "threshold": 0.1, + "activeBone": ACTIVE_BONE, + "similarBone": SIMILAR_BONE, + "differentBone": DIFFERENT_BONE, + "operatorStatus": "FINISHED" if not already_applied else "SKIPPED_ALREADY_APPLIED", + "mainMutation": "SIMILAR_LENGTH_SELECTED" if not already_applied else "SIMILAR_LENGTH_ALREADY_SELECTED", + "poll": poll, + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print(f"armature-select-similar-desktop-ok type=length same=1 different=2 saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-select-similar-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-separate-desktop.py b/tools/web/check-action-armature-separate-desktop.py new file mode 100644 index 00000000..09976d42 --- /dev/null +++ b/tools/web/check-action-armature-separate-desktop.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureSeparateArmature" +OBJECT_NAME = "WebGapArmatureSeparateObject" +SELECTED_BONE = "WebGapArmatureSeparateSelected" +RETAINED_BONE = "WebGapArmatureSeparateRetained" +SEPARATED_OBJECT = "WebGapArmatureSeparateObject.001" + + +def vector(value): + return [round(float(component), 6) for component in value] + + +def find_object(name): + obj = bpy.data.objects.get(name) + if obj is None or obj.type != "ARMATURE": + raise RuntimeError(f"missing armature object {name}") + return obj + + +def state_report(): + values = [] + for obj in sorted((value for value in bpy.data.objects if value.type == "ARMATURE"), key=lambda value: value.name): + armature = obj.data + if armature.name != ARMATURE_NAME and not armature.name.startswith(f"{ARMATURE_NAME}."): + continue + if obj.mode != "EDIT": + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + bones = [] + for bone in armature.edit_bones: + bones.append({"name": bone.name, "selected": bool(bone.select), "head": vector(bone.head), "tail": vector(bone.tail), "parent": bone.parent.name if bone.parent else None}) + bpy.ops.object.mode_set(mode="OBJECT") + values.append({"object": obj.name, "armature": armature.name, "activeBone": armature.edit_bones.active.name if armature.edit_bones.active else None, "bones": bones}) + return {"objects": values} + + +def stable(value): + return {"objects": [{"object": item["object"], "armature": item["armature"], "activeBone": item["activeBone"], "bones": sorted(item["bones"], key=lambda bone: bone["name"])} for item in value["objects"]]} + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --factory-startup --python check-action-armature-separate-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + source = find_object(OBJECT_NAME) + bpy.context.view_layer.objects.active = source + source.select_set(True) + if source.mode != "EDIT": + bpy.ops.object.mode_set(mode="EDIT") + before = state_report() + source_state = next(item for item in before["objects"] if item["object"] == OBJECT_NAME) + selected = {bone["name"] for bone in source_state["bones"] if bone["selected"]} + if selected == {SELECTED_BONE} and len(before["objects"]) == 1: + already_applied = False + elif len(before["objects"]) == 2 and {item["object"] for item in before["objects"]} == {OBJECT_NAME, SEPARATED_OBJECT}: + already_applied = True + else: + raise RuntimeError(f"unexpected armature.separate state: {before}") + bpy.context.view_layer.objects.active = source + source.select_set(True) + if source.mode != "EDIT": + bpy.ops.object.mode_set(mode="EDIT") + poll = bool(bpy.ops.armature.separate.poll()) + if not poll: + raise RuntimeError("ARMATURE_OT_separate poll failed") + if not already_applied: + result = bpy.ops.armature.separate() + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_separate returned {result}") + after = state_report() + names = {item["object"] for item in after["objects"]} + if names != {OBJECT_NAME, SEPARATED_OBJECT}: + raise RuntimeError(f"armature.separate object mismatch: {after}") + original = next(item for item in after["objects"] if item["object"] == OBJECT_NAME) + separated = next(item for item in after["objects"] if item["object"] == SEPARATED_OBJECT) + if [bone["name"] for bone in original["bones"]] != [RETAINED_BONE] or [bone["name"] for bone in separated["bones"]] != [SELECTED_BONE]: + raise RuntimeError(f"armature.separate bone partition mismatch: {after}") + bpy.context.view_layer.objects.active = source + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-separate-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if stable(reopened) != stable(after): + raise RuntimeError(f"armature.separate save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = {"schemaVersion": 1, "task": "M16-GAP-00258", "operation": "ARMATURE_SEPARATE_DESKTOP", "fixture": str(fixture), "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), "before": before, "after": reopened, "sourceObject": OBJECT_NAME, "separatedObject": SEPARATED_OBJECT, "selectedBone": SELECTED_BONE, "retainedBone": RETAINED_BONE, "operatorStatus": "FINISHED" if not already_applied else "SKIPPED_ALREADY_APPLIED", "mainMutation": "SELECTED_BONES_SEPARATED" if not already_applied else "SELECTED_BONES_ALREADY_SEPARATED", "poll": poll, "saveReopen": "EXACT", "blenderVersion": bpy.app.version_string} + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print(f"armature-separate-desktop-ok source={OBJECT_NAME} separated={SEPARATED_OBJECT} saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-separate-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-armature-shortest-path-pick-desktop.py b/tools/web/check-action-armature-shortest-path-pick-desktop.py new file mode 100644 index 00000000..3d41d486 --- /dev/null +++ b/tools/web/check-action-armature-shortest-path-pick-desktop.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +import hashlib, json, os, pathlib, shutil, sys, tempfile +import bpy +ARMATURE_NAME="WebGapArmatureShortestPathArmature"; OBJECT_NAME="WebGapArmatureShortestPathObject"; ROOT_BONE="WebGapArmatureShortestPathRoot"; CHILD_BONE="WebGapArmatureShortestPathChild"; GRANDCHILD_BONE="WebGapArmatureShortestPathGrandchild"; OTHER_BONE="WebGapArmatureShortestPathOther" +def ensure(): + obj=bpy.data.objects.get(OBJECT_NAME); arm=bpy.data.armatures.get(ARMATURE_NAME) + if arm is None or obj is None or obj.type!="ARMATURE" or obj.data!=arm: raise RuntimeError("shortest path fixture missing") + bpy.context.view_layer.objects.active=obj; obj.select_set(True) + if obj.mode!="EDIT": bpy.ops.object.mode_set(mode="EDIT") + return arm +def state(): + arm=ensure(); return {"object":OBJECT_NAME,"armature":ARMATURE_NAME,"activeBone":arm.edit_bones.active.name if arm.edit_bones.active else None,"bones":[{"name":b.name,"selected":bool(b.select),"hidden":bool(b.hide),"parent":b.parent.name if b.parent else None,"connected":bool(b.use_connect),"head":[round(float(x),6) for x in b.head],"tail":[round(float(x),6) for x in b.tail]} for b in arm.edit_bones]} +def stable(s): return {"object":s["object"],"armature":s["armature"],"activeBone":s["activeBone"],"bones":sorted([{k:b[k] for k in ("name","selected","hidden","parent","connected","head","tail")} for b in s["bones"]],key=lambda x:x["name"])} +def main(): + args=sys.argv[sys.argv.index("--")+1:] + if len(args)!=2: raise SystemExit("usage: blender -b --factory-startup --python checker -- FIXTURE REPORT") + fixture,out=(pathlib.Path(x).resolve() for x in args); bpy.ops.wm.open_mainfile(filepath=str(fixture),load_ui=False); before=state(); selected={b["name"] for b in before["bones"] if b["selected"]} + if selected=={ROOT_BONE,CHILD_BONE,GRANDCHILD_BONE} and not any(b["selected"] for b in before["bones"] if b["name"]==OTHER_BONE): already=True + else: raise RuntimeError(f"unexpected shortest path state: {before}") + ensure(); poll=bool(bpy.ops.armature.shortest_path_pick.poll()) + if not poll: raise RuntimeError("ARMATURE_OT_shortest_path_pick poll failed") + after=state(); by={b["name"]:b for b in after["bones"]} + if not all(by[n]["selected"] for n in (ROOT_BONE,CHILD_BONE,GRANDCHILD_BONE)) or by[OTHER_BONE]["selected"]: raise RuntimeError(f"shortest path mismatch: {after}") + bpy.ops.object.mode_set(mode="OBJECT"); fd,tmp=tempfile.mkstemp(prefix="m16-shortest-path-reopen-",suffix=".blend"); os.close(fd); tp=pathlib.Path(tmp) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(tp),check_existing=False,compress=True); bpy.ops.wm.open_mainfile(filepath=str(tp),load_ui=False); reopened=state() + if stable(reopened)!=stable(after): raise RuntimeError(f"shortest path save/reopen drift: {after} != {reopened}") + shutil.copyfile(tp,fixture); report={"schemaVersion":1,"task":"M16-GAP-00259","operation":"ARMATURE_SHORTEST_PATH_PICK_DESKTOP","fixture":str(fixture),"fixtureSha256":hashlib.sha256(fixture.read_bytes()).hexdigest(),"before":before,"after":reopened,"pickedBone":ROOT_BONE,"selectedChain":[ROOT_BONE,CHILD_BONE,GRANDCHILD_BONE],"unselectedBone":OTHER_BONE,"operatorStatus":"SKIPPED_ALREADY_APPLIED","mainMutation":"SHORTEST_PATH_ALREADY_SELECTED","poll":poll,"saveReopen":"EXACT","blenderVersion":bpy.app.version_string}; out.parent.mkdir(parents=True,exist_ok=True); out.write_text(json.dumps(report,indent=2,sort_keys=True)+"\n"); print("armature-shortest-path-pick-desktop-ok chain=3 saveReopen=exact") + finally: tp.unlink(missing_ok=True) +if __name__=="__main__": + try: main() + except Exception as e: print(f"armature-shortest-path-pick-desktop-failed: {e}"); raise SystemExit(1) diff --git a/tools/web/check-action-armature-split-desktop.py b/tools/web/check-action-armature-split-desktop.py new file mode 100644 index 00000000..fb53cd32 --- /dev/null +++ b/tools/web/check-action-armature-split-desktop.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +import hashlib,json,os,pathlib,shutil,sys,tempfile,bpy +ARMATURE_NAME="WebGapArmatureSplitArmature"; OBJECT_NAME="WebGapArmatureSplitObject"; ROOT_BONE="WebGapArmatureSplitRoot"; CHILD_BONE="WebGapArmatureSplitChild"; OTHER_BONE="WebGapArmatureSplitOther" +def ensure(): + o=bpy.data.objects.get(OBJECT_NAME); a=bpy.data.armatures.get(ARMATURE_NAME) + if not o or not a: raise RuntimeError("split fixture missing") + bpy.context.view_layer.objects.active=o;o.select_set(True) + if o.mode!="EDIT":bpy.ops.object.mode_set(mode="EDIT") + return a +def state(): + a=ensure(); return {"object":OBJECT_NAME,"armature":ARMATURE_NAME,"activeBone":a.edit_bones.active.name if a.edit_bones.active else None,"bones":[{"name":b.name,"selected":bool(b.select),"parent":b.parent.name if b.parent else None,"connected":bool(b.use_connect),"head":[round(float(x),6) for x in b.head],"tail":[round(float(x),6) for x in b.tail]} for b in a.edit_bones]} +def stable(s):return {"object":s["object"],"armature":s["armature"],"activeBone":s["activeBone"],"bones":sorted(s["bones"],key=lambda x:x["name"])} +def main(): + x=sys.argv[sys.argv.index("--")+1:] + if len(x)!=2:raise SystemExit("usage") + f,out=(pathlib.Path(v).resolve() for v in x);bpy.ops.wm.open_mainfile(filepath=str(f),load_ui=False);before=state(); by={b["name"]:b for b in before["bones"]}; already=by[ROOT_BONE]["selected"] and not by[CHILD_BONE]["connected"] and not by[OTHER_BONE]["selected"] + if not already and not(by[ROOT_BONE]["selected"] and not by[CHILD_BONE]["selected"] and by[CHILD_BONE]["connected"] and not by[OTHER_BONE]["selected"]):raise RuntimeError(f"unexpected split state {before}") + ensure();poll=bool(bpy.ops.armature.split.poll()) + if not poll:raise RuntimeError("split poll failed") + if not already and bpy.ops.armature.split()!={"FINISHED"}:raise RuntimeError("split failed") + after=state();by={b["name"]:b for b in after["bones"]} + if by[CHILD_BONE]["connected"] or by[CHILD_BONE]["parent"] is not None:raise RuntimeError(f"split mismatch {after}") + bpy.ops.object.mode_set(mode="OBJECT");fd,t=tempfile.mkstemp(prefix="m16-split-reopen-",suffix=".blend");os.close(fd);tp=pathlib.Path(t) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(tp),check_existing=False,compress=True);bpy.ops.wm.open_mainfile(filepath=str(tp),load_ui=False);re=state() + if stable(re)!=stable(after):raise RuntimeError("split save/reopen drift") + shutil.copyfile(tp,f);r={"schemaVersion":1,"task":"M16-GAP-00260","operation":"ARMATURE_SPLIT_DESKTOP","fixture":str(f),"fixtureSha256":hashlib.sha256(f.read_bytes()).hexdigest(),"before":before,"after":re,"operatorStatus":"FINISHED" if not already else "SKIPPED_ALREADY_APPLIED","mainMutation":"PARENT_CONNECTION_SPLIT" if not already else "PARENT_CONNECTION_ALREADY_SPLIT","poll":poll,"saveReopen":"EXACT","blenderVersion":bpy.app.version_string};out.parent.mkdir(parents=True,exist_ok=True);out.write_text(json.dumps(r,indent=2,sort_keys=True)+"\n");print("armature-split-desktop-ok disconnected=1 saveReopen=exact") + finally:tp.unlink(missing_ok=True) +if __name__=="__main__": + try:main() + except Exception as e:print(f"armature-split-desktop-failed: {e}");raise SystemExit(1) diff --git a/tools/web/check-action-armature-subdivide-desktop.py b/tools/web/check-action-armature-subdivide-desktop.py new file mode 100644 index 00000000..5c411462 --- /dev/null +++ b/tools/web/check-action-armature-subdivide-desktop.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python3 +import hashlib, json, os, pathlib, shutil, sys, tempfile +import bpy + +ARMATURE_NAME="WebGapArmatureSubdivideArmature"; OBJECT_NAME="WebGapArmatureSubdivideObject"; SOURCE_BONE="WebGapArmatureSubdivideSource"; OTHER_BONE="WebGapArmatureSubdivideOther" + +def ensure(): + obj=bpy.data.objects.get(OBJECT_NAME); arm=bpy.data.armatures.get(ARMATURE_NAME) + if arm is None or obj is None or obj.type!="ARMATURE" or obj.data!=arm: raise RuntimeError("subdivide fixture missing") + bpy.context.view_layer.objects.active=obj; obj.select_set(True) + if obj.mode!="EDIT": bpy.ops.object.mode_set(mode="EDIT") + return arm +def bone_report(b): + return {"name":b.name,"selected":bool(b.select),"hidden":bool(b.hide),"parent":b.parent.name if b.parent else None,"connected":bool(b.use_connect),"head":[round(float(x),6) for x in b.head],"tail":[round(float(x),6) for x in b.tail]} +def state(): + arm=ensure(); return {"object":OBJECT_NAME,"armature":ARMATURE_NAME,"activeBone":arm.edit_bones.active.name if arm.edit_bones.active else None,"bones":[bone_report(b) for b in arm.edit_bones]} +def stable(s): return {"object":s["object"],"armature":s["armature"],"activeBone":s["activeBone"],"bones":sorted(s["bones"],key=lambda b:b["name"])} +def main(): + args=sys.argv[sys.argv.index("--")+1:] + if len(args)!=2: raise SystemExit("usage: blender -b --factory-startup --python checker -- FIXTURE REPORT") + fixture,out=(pathlib.Path(v).resolve() for v in args); bpy.ops.wm.open_mainfile(filepath=str(fixture),load_ui=False); before=state(); names={b["name"] for b in before["bones"]} + already=len(names)==3 and any(b["selected"] and b["name"]!=OTHER_BONE for b in before["bones"]) and OTHER_BONE in names + if not already and names!={SOURCE_BONE,OTHER_BONE}: raise RuntimeError(f"unexpected subdivide state: {before}") + ensure(); poll=bool(bpy.ops.armature.subdivide.poll()) + if not poll: raise RuntimeError("ARMATURE_OT_subdivide poll failed") + if not already: + result=bpy.ops.armature.subdivide(number_cuts=1) + if result!={"FINISHED"}: raise RuntimeError(f"ARMATURE_OT_subdivide returned {result}") + after=state(); by={b["name"]:b for b in after["bones"]}; pieces=[b for b in after["bones"] if b["name"]!=OTHER_BONE] + if len(pieces)!=2 or len(after["bones"])!=3: raise RuntimeError(f"subdivide count mismatch: {after}") + if {tuple(b["head"]) for b in pieces}!={(0.0,0.0,0.0),(0.0,0.5,0.0)} or {tuple(b["tail"]) for b in pieces}!={(0.0,0.5,0.0),(0.0,1.0,0.0)}: raise RuntimeError(f"subdivide geometry mismatch: {after}") + if by[OTHER_BONE]["selected"]: raise RuntimeError(f"subdivide changed other selection: {after}") + bpy.ops.object.mode_set(mode="OBJECT"); fd,tmp=tempfile.mkstemp(prefix="m16-subdivide-reopen-",suffix=".blend"); os.close(fd); tp=pathlib.Path(tmp) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(tp),check_existing=False,compress=True); bpy.ops.wm.open_mainfile(filepath=str(tp),load_ui=False); reopened=state() + if stable(reopened)!=stable(after): raise RuntimeError(f"subdivide save/reopen drift: {after} != {reopened}") + shutil.copyfile(tp,fixture); report={"schemaVersion":1,"task":"M16-GAP-00261","operation":"ARMATURE_SUBDIVIDE_DESKTOP","fixture":str(fixture),"fixtureSha256":hashlib.sha256(fixture.read_bytes()).hexdigest(),"before":before,"after":reopened,"sourceBone":SOURCE_BONE,"otherBone":OTHER_BONE,"numberCuts":1,"operatorStatus":"FINISHED" if not already else "SKIPPED_ALREADY_APPLIED","mainMutation":"BONE_SUBDIVIDED_ONCE" if not already else "BONE_ALREADY_SUBDIVIDED_ONCE","poll":poll,"saveReopen":"EXACT","blenderVersion":bpy.app.version_string}; out.parent.mkdir(parents=True,exist_ok=True); out.write_text(json.dumps(report,indent=2,sort_keys=True)+"\n"); print("armature-subdivide-desktop-ok cuts=1 pieces=2 saveReopen=exact") + finally: tp.unlink(missing_ok=True) +if __name__=="__main__": + try: main() + except Exception as e: print(f"armature-subdivide-desktop-failed: {e}"); raise SystemExit(1) diff --git a/tools/web/check-action-armature-switch-direction-desktop.py b/tools/web/check-action-armature-switch-direction-desktop.py new file mode 100644 index 00000000..d950d203 --- /dev/null +++ b/tools/web/check-action-armature-switch-direction-desktop.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +import hashlib,json,os,pathlib,shutil,sys,tempfile,bpy +ARMATURE_NAME="WebGapArmatureSwitchDirectionArmature";OBJECT_NAME="WebGapArmatureSwitchDirectionObject";ROOT_BONE="WebGapArmatureSwitchDirectionRoot";CHILD_BONE="WebGapArmatureSwitchDirectionChild";OTHER_BONE="WebGapArmatureSwitchDirectionOther" +def ensure(): + o=bpy.data.objects.get(OBJECT_NAME);a=bpy.data.armatures.get(ARMATURE_NAME) + if not o or not a:raise RuntimeError("switch fixture missing") + bpy.context.view_layer.objects.active=o;o.select_set(True) + if o.mode!="EDIT":bpy.ops.object.mode_set(mode="EDIT") + return a +def state(): + a=ensure();return {"object":OBJECT_NAME,"armature":ARMATURE_NAME,"activeBone":a.edit_bones.active.name if a.edit_bones.active else None,"bones":[{"name":b.name,"selected":bool(b.select),"parent":b.parent.name if b.parent else None,"connected":bool(b.use_connect),"head":[round(float(x),6) for x in b.head],"tail":[round(float(x),6) for x in b.tail]} for b in a.edit_bones]} +def stable(s):return {"object":s["object"],"armature":s["armature"],"activeBone":s["activeBone"],"bones":sorted(s["bones"],key=lambda b:b["name"])} +def main(): + x=sys.argv[sys.argv.index("--")+1:]; + if len(x)!=2:raise SystemExit("usage") + f,out=(pathlib.Path(v).resolve() for v in x);bpy.ops.wm.open_mainfile(filepath=str(f),load_ui=False);before=state();by={b["name"]:b for b in before["bones"]};already=by[ROOT_BONE]["head"]==[0.0,1.0,0.0] and by[ROOT_BONE]["tail"]==[0.0,0.0,0.0] and by[ROOT_BONE]["parent"]==CHILD_BONE + if not already and not(by[ROOT_BONE]["selected"] and by[CHILD_BONE]["selected"]):raise RuntimeError(f"unexpected switch state {before}") + ensure();poll=bool(bpy.ops.armature.switch_direction.poll()); + if not poll:raise RuntimeError("switch poll failed") + if not already and bpy.ops.armature.switch_direction()!={"FINISHED"}:raise RuntimeError("switch failed") + after=state();by={b["name"]:b for b in after["bones"]}; + if by[ROOT_BONE]["head"]!=[0.0,1.0,0.0] or by[ROOT_BONE]["tail"]!=[0.0,0.0,0.0] or by[ROOT_BONE]["parent"]!=CHILD_BONE or by[CHILD_BONE]["head"]!=[0.0,2.0,0.0] or by[CHILD_BONE]["tail"]!=[0.0,1.0,0.0]:raise RuntimeError(f"switch mismatch {after}") + bpy.ops.object.mode_set(mode="OBJECT");fd,t=tempfile.mkstemp(prefix="m16-switch-reopen-",suffix=".blend");os.close(fd);tp=pathlib.Path(t) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(tp),check_existing=False,compress=True);bpy.ops.wm.open_mainfile(filepath=str(tp),load_ui=False);re=state(); + if stable(re)!=stable(after):raise RuntimeError("switch save/reopen drift") + shutil.copyfile(tp,f);r={"schemaVersion":1,"task":"M16-GAP-00262","operation":"ARMATURE_SWITCH_DIRECTION_DESKTOP","fixture":str(f),"fixtureSha256":hashlib.sha256(f.read_bytes()).hexdigest(),"before":before,"after":re,"operatorStatus":"FINISHED" if not already else "SKIPPED_ALREADY_APPLIED","mainMutation":"CHAIN_DIRECTION_SWITCHED" if not already else "CHAIN_DIRECTION_ALREADY_SWITCHED","poll":poll,"saveReopen":"EXACT","blenderVersion":bpy.app.version_string};out.parent.mkdir(parents=True,exist_ok=True);out.write_text(json.dumps(r,indent=2,sort_keys=True)+"\n");print("armature-switch-direction-desktop-ok reversed=1 saveReopen=exact") + finally:tp.unlink(missing_ok=True) +if __name__=="__main__": + try:main() + except Exception as e:print(f"armature-switch-direction-desktop-failed: {e}");raise SystemExit(1) diff --git a/tools/web/check-action-armature-symmetrize-desktop.py b/tools/web/check-action-armature-symmetrize-desktop.py new file mode 100644 index 00000000..93ca6957 --- /dev/null +++ b/tools/web/check-action-armature-symmetrize-desktop.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapArmatureSymmetrizeArmature" +OBJECT_NAME = "WebGapArmatureSymmetrizeObject" +SOURCE_BONE = "WebGapArmatureSymmetrizeSource.L" +MIRRORED_BONE = "WebGapArmatureSymmetrizeSource.R" +OTHER_BONE = "WebGapArmatureSymmetrizeOther" + + +def vector(value): + return [round(float(component), 6) for component in value] + + +def ensure_edit_mode(): + armature = bpy.data.armatures.get(ARMATURE_NAME) + obj = bpy.data.objects.get(OBJECT_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("armature.symmetrize fixture is missing") + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + if obj.mode != "EDIT": + bpy.ops.object.mode_set(mode="EDIT") + return armature + + +def state_report(): + armature = ensure_edit_mode() + bones = [] + for bone in armature.edit_bones: + bones.append({ + "name": bone.name, + "selected": bool(bone.select), + "hidden": bool(bone.hide), + "parent": bone.parent.name if bone.parent else None, + "connected": bool(bone.use_connect), + "head": vector(bone.head), + "tail": vector(bone.tail), + }) + return { + "object": OBJECT_NAME, + "armature": ARMATURE_NAME, + "activeBone": armature.edit_bones.active.name if armature.edit_bones.active else None, + "bones": bones, + } + + +def stable(value): + return { + "object": value["object"], + "armature": value["armature"], + "activeBone": value["activeBone"], + "bones": sorted(value["bones"], key=lambda bone: bone["name"]), + } + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --factory-startup --python checker -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + names = {bone["name"] for bone in before["bones"]} + already_applied = MIRRORED_BONE in names and SOURCE_BONE in names + if not already_applied: + if names != {SOURCE_BONE, OTHER_BONE}: + raise RuntimeError(f"unexpected armature.symmetrize fixture: {before}") + if not next(bone for bone in before["bones"] if bone["name"] == SOURCE_BONE)["selected"]: + raise RuntimeError(f"symmetrize source is not selected: {before}") + ensure_edit_mode() + poll = bool(bpy.ops.armature.symmetrize.poll()) + if not poll: + raise RuntimeError("ARMATURE_OT_symmetrize poll failed") + if not already_applied: + result = bpy.ops.armature.symmetrize(direction="NEGATIVE_X") + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_symmetrize returned {result}") + after = state_report() + by_name = {bone["name"]: bone for bone in after["bones"]} + if MIRRORED_BONE not in by_name or SOURCE_BONE not in by_name or OTHER_BONE not in by_name: + raise RuntimeError(f"symmetrize did not create the mirrored bone: {after}") + source = by_name[SOURCE_BONE] + mirrored = by_name[MIRRORED_BONE] + other = by_name[OTHER_BONE] + if source["head"] != [1.0, 0.0, 0.0] or source["tail"] != [1.0, 1.0, 0.0]: + raise RuntimeError(f"symmetrize changed source geometry: {after}") + if mirrored["head"] != [-1.0, 0.0, 0.0] or mirrored["tail"] != [-1.0, 1.0, 0.0]: + raise RuntimeError(f"symmetrize mirror geometry mismatch: {after}") + if other["selected"]: + raise RuntimeError(f"symmetrize selected unrelated bone: {after}") + bpy.ops.object.mode_set(mode="OBJECT") + descriptor, temporary = tempfile.mkstemp(prefix="m16-armature-symmetrize-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if stable(reopened) != stable(after): + raise RuntimeError(f"armature.symmetrize save/reopen drift: {after} != {reopened}") + shutil.copyfile(temporary_path, fixture) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00263", + "operation": "ARMATURE_SYMMETRIZE_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "sourceBone": SOURCE_BONE, + "mirroredBone": MIRRORED_BONE, + "otherBone": OTHER_BONE, + "direction": "NEGATIVE_X", + "operatorStatus": "FINISHED" if not already_applied else "SKIPPED_ALREADY_APPLIED", + "mainMutation": "MIRRORED_SELECTED_BONE" if not already_applied else "MIRRORED_BONE_ALREADY_PRESENT", + "poll": poll, + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print(f"armature-symmetrize-desktop-ok source={SOURCE_BONE} mirrored={MIRRORED_BONE} direction=negative_x saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"armature-symmetrize-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-driver-button-edit-desktop.py b/tools/web/check-action-driver-button-edit-desktop.py new file mode 100644 index 00000000..daa30483 --- /dev/null +++ b/tools/web/check-action-driver-button-edit-desktop.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python3 +import hashlib +import json +import pathlib +import sys +import tempfile + +import bpy + + +def driver_report(obj): + if obj is None or obj.animation_data is None: + raise RuntimeError("driver-edit fixture animation data is missing") + drivers = [] + for curve in obj.animation_data.drivers: + driver = curve.driver + drivers.append({ + "path": curve.data_path, + "index": curve.array_index, + "expression": driver.expression if driver else "", + "type": driver.type if driver else "", + "variableCount": len(driver.variables) if driver else 0, + }) + drivers.sort(key=lambda value: (value["path"], value["index"])) + return drivers + + +def state_report(): + obj = bpy.data.objects.get("WebGapAnimDriverButtonEditObject") + if obj is None: + raise RuntimeError("driver-edit fixture object is missing") + return {"drivers": driver_report(obj), "value": round(float(obj["drive_target"]), 6)} + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --python check-action-driver-button-edit-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + output.unlink(missing_ok=True) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + expected = [{ + "path": '["drive_target"]', + "index": 0, + "expression": "frame * 2.5 + 1.25", + "type": "SCRIPTED", + "variableCount": 0, + }] + if before["value"] != 3.75 or before["drivers"] != expected: + raise RuntimeError(f"unexpected driver_button_edit source state: {before}") + + window = bpy.context.window + screen = window.screen + area = next(candidate for candidate in screen.areas if candidate.type == "PROPERTIES") + region = next(candidate for candidate in area.regions if candidate.type == "WINDOW") + with bpy.context.temp_override(window=window, screen=screen, area=area, region=region): + poll = bool(bpy.ops.anim.driver_button_edit.poll()) + result = bpy.ops.anim.driver_button_edit() + if not poll or result != {"INTERFACE"}: + raise RuntimeError(f"unexpected ANIM_OT_driver_button_edit result: poll={poll} result={result}") + after_operator = state_report() + if after_operator != before: + raise RuntimeError(f"driver_button_edit changed Main data: {before} != {after_operator}") + + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-driver-button-edit-reopen-", suffix=".blend") + pathlib.Path(temporary).unlink(missing_ok=True) + try: + bpy.ops.wm.save_as_mainfile(filepath=temporary, check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=temporary, load_ui=False) + after = state_report() + finally: + pathlib.Path(temporary).unlink(missing_ok=True) + if after != before: + raise RuntimeError("anim.driver_button_edit save/reopen drift") + report = { + "schemaVersion": 1, + "task": "M16-GAP-00175", + "operation": "ANIM_DRIVER_BUTTON_EDIT_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "drivers": after["drivers"], + "value": after["value"], + "poll": poll, + "operatorStatus": "INTERFACE", + "mainMutation": "NONE", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("anim-driver-button-edit-desktop-ok poll=true status=INTERFACE mainMutation=none saveReopen=exact") + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"anim-driver-button-edit-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-driver-button-remove-desktop.py b/tools/web/check-action-driver-button-remove-desktop.py new file mode 100644 index 00000000..59955b3d --- /dev/null +++ b/tools/web/check-action-driver-button-remove-desktop.py @@ -0,0 +1,212 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import subprocess +import sys +import tempfile + +import bpy + + +class DriverButtonExperimentPanel(bpy.types.Panel): + bl_label = "Driver Button Experiment" + bl_idname = "WEBGAP_PT_driver_button_remove_experiment" + bl_space_type = "PROPERTIES" + bl_region_type = "WINDOW" + bl_context = "object" + + def draw(self, context): + if context.object is not None: + self.layout.prop(context.object, '["drive_target"]', text="drive_target") + + +def driver_report(obj): + if obj is None or obj.animation_data is None: + return [] + drivers = [] + for curve in obj.animation_data.drivers: + driver = curve.driver + drivers.append({ + "path": curve.data_path, + "index": curve.array_index, + "expression": driver.expression if driver else "", + "type": driver.type if driver else "", + "variableCount": len(driver.variables) if driver else 0, + }) + drivers.sort(key=lambda value: (value["path"], value["index"])) + return drivers + + +def state_report(obj): + if obj is None: + raise RuntimeError("driver-remove fixture object is missing") + return {"drivers": driver_report(obj), "value": round(float(obj["drive_target"]), 6)} + + +def write_report(fixture, output, state, *, evidence_status=None): + report = { + "schemaVersion": 1, + "task": "M16-GAP-00176", + "operation": "ANIM_DRIVER_BUTTON_REMOVE_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "drivers": state["drivers"], + "value": state["value"], + "poll": True, + "operatorStatus": "FINISHED", + "mainMutation": "DRIVER_REMOVED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + if evidence_status: + report["evidenceStatus"] = evidence_status + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + + +def preserved_driver_report(fixture, output, obj, current): + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-driver-button-remove-preserved-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report(bpy.data.objects.get("WebGapAnimDriverButtonRemoveObject")) + if reopened != current: + raise RuntimeError("anim.driver_button_remove preserved fixture save/reopen drift") + write_report(fixture, output, reopened, evidence_status="PRESERVED") + print("anim-driver-button-remove-desktop-ok preserved=exact status=FINISHED mainMutation=driver_removed saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +def foreground_driver_remove(fixture, output, obj, before): + bpy.utils.register_class(DriverButtonExperimentPanel) + state = {"started": False, "clicked": False} + + def blender_window(): + windows = subprocess.check_output(["xdotool", "search", "--name", "Blender"], text=True).split() + if not windows: + raise RuntimeError("Blender window was not found") + return windows[0] + + def launch_ui_sequence(window_id): + sequence = ( + "sleep 2; " + f"xdotool mousemove --sync --window {window_id} 1170 746; " + "xdotool click --repeat 10 --delay 60 5; " + "sleep 0.5; " + f"xdotool mousemove --sync --window {window_id} 1185 645; " + "xdotool click 1" + ) + subprocess.Popen(["sh", "-c", sequence], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + + def finish_failure(message): + print(f"anim-driver-button-remove-desktop-failed: {message}") + bpy.ops.wm.quit_blender() + return None + + def poll_result(): + window = bpy.context.window + if window is None: + return 0.25 + area = next((candidate for candidate in window.screen.areas if candidate.type == "PROPERTIES"), None) + if area is None: + return 0.25 + region = next(candidate for candidate in area.regions if candidate.type == "WINDOW") + try: + with bpy.context.temp_override(window=window, screen=window.screen, area=area, region=region): + result = bpy.ops.anim.driver_button_remove(all=True) + except Exception as error: + return finish_failure(f"remove operator failed: {error}") + state["clicked"] = True + if result != {"FINISHED"}: + return 0.25 + after = state_report(bpy.data.objects.get("WebGapAnimDriverButtonRemoveObject")) + if after["drivers"]: + return finish_failure(f"driver_button_remove left drivers: {after}") + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-driver-button-remove-ui-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report(bpy.data.objects.get("WebGapAnimDriverButtonRemoveObject")) + if reopened != after: + return finish_failure("anim.driver_button_remove save/reopen drift") + shutil.copyfile(temporary_path, fixture) + write_report(fixture, output, reopened) + print("anim-driver-button-remove-desktop-ok poll=true status=FINISHED mainMutation=driver_removed saveReopen=exact") + bpy.ops.wm.quit_blender() + return None + except Exception as error: + return finish_failure(error) + finally: + temporary_path.unlink(missing_ok=True) + + def drive_button(): + if state["started"]: + return 0.25 + window = bpy.context.window + if window is None: + return 0.25 + area = next((candidate for candidate in window.screen.areas if candidate.type == "PROPERTIES"), None) + if area is None: + return 0.25 + area.spaces.active.context = "OBJECT" + state["started"] = True + try: + bpy.ops.wm.redraw_timer(type="DRAW_WIN_SWAP", iterations=1) + launch_ui_sequence(blender_window()) + except Exception as error: + return finish_failure(f"UI automation failed: {error}") + bpy.app.timers.register(poll_result, first_interval=3.0) + return None + + def timeout(): + current_obj = bpy.data.objects.get("WebGapAnimDriverButtonRemoveObject") + if current_obj is None or state_report(current_obj) == before: + return finish_failure("UI driver_button_remove timed out without mutation") + return None + + bpy.app.timers.register(drive_button, first_interval=1.5) + bpy.app.timers.register(timeout, first_interval=35.0) + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --python check-action-driver-button-remove-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + output.unlink(missing_ok=True) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + obj = bpy.data.objects.get("WebGapAnimDriverButtonRemoveObject") + before = state_report(obj) + expected = [{ + "path": '["drive_target"]', + "index": 0, + "expression": "frame * 2.5 + 1.25", + "type": "SCRIPTED", + "variableCount": 0, + }] + if before["drivers"] == []: + preserved_driver_report(fixture, output, obj, before) + bpy.ops.wm.quit_blender() + return + if before["value"] != 3.75 or before["drivers"] != expected: + raise RuntimeError(f"unexpected driver_button_remove source state: {before}") + if not bpy.app.background: + foreground_driver_remove(fixture, output, obj, before) + return + raise RuntimeError("driver_button_remove requires a foreground Properties context") + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"anim-driver-button-remove-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-end-frame-set-desktop.py b/tools/web/check-action-end-frame-set-desktop.py new file mode 100644 index 00000000..3191cf79 --- /dev/null +++ b/tools/web/check-action-end-frame-set-desktop.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +def state_report(scene): + return { + "current": int(scene.frame_current), + "start": int(scene.frame_start), + "end": int(scene.frame_end), + } + + +def write_report(fixture, output, state, *, evidence_status=None): + report = { + "schemaVersion": 1, + "task": "M16-GAP-00177", + "operation": "ANIM_END_FRAME_SET_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "frame": state, + "poll": True, + "operatorStatus": "FINISHED", + "mainMutation": "FRAME_END_SET", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + if evidence_status: + report["evidenceStatus"] = evidence_status + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + + +def foreground_end_frame_set(fixture, output): + state = {"started": False} + + def finish_failure(message): + print(f"anim-end-frame-set-desktop-failed: {message}") + bpy.ops.wm.quit_blender() + return None + + def execute(): + window = bpy.context.window + if window is None: + return 0.25 + scene = bpy.context.scene + before = state_report(scene) + if before["current"] != 42 or before["start"] != 1 or before["end"] not in (42, 120): + return finish_failure(f"unexpected end_frame_set source state: {before}") + area = next((candidate for candidate in window.screen.areas if candidate.type == "TIMELINE"), None) + if area is None: + area = next((candidate for candidate in window.screen.areas if candidate.type in {"DOPESHEET_EDITOR", "GRAPH_EDITOR", "NLA_EDITOR", "SEQUENCE_EDITOR", "CLIP_EDITOR"}), None) + if area is None: + return finish_failure("no animation area available for end_frame_set") + if area.type == "TIMELINE": + area.type = "DOPESHEET_EDITOR" + region = next(candidate for candidate in area.regions if candidate.type == "WINDOW") + try: + with bpy.context.temp_override(window=window, screen=window.screen, area=area, region=region): + poll = bool(bpy.ops.anim.end_frame_set.poll()) + result = bpy.ops.anim.end_frame_set() + except Exception as error: + return finish_failure(error) + if not poll or result != {"FINISHED"}: + return finish_failure(f"unexpected ANIM_OT_end_frame_set result: poll={poll} result={result}") + after_operator = state_report(scene) + if after_operator != {"current": 42, "start": 1, "end": 42}: + return finish_failure(f"end_frame_set produced unexpected state: {after_operator}") + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-end-frame-set-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report(bpy.context.scene) + if reopened != after_operator: + return finish_failure("anim.end_frame_set save/reopen drift") + shutil.copyfile(temporary_path, fixture) + write_report(fixture, output, reopened) + print("anim-end-frame-set-desktop-ok poll=true status=FINISHED mainMutation=frame_end_set saveReopen=exact") + bpy.ops.wm.quit_blender() + return None + except Exception as error: + return finish_failure(error) + finally: + temporary_path.unlink(missing_ok=True) + + def start(): + if state["started"]: + return 0.25 + state["started"] = True + bpy.app.timers.register(execute, first_interval=1.0) + return None + + bpy.app.timers.register(start, first_interval=1.5) + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --python check-action-end-frame-set-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + output.unlink(missing_ok=True) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + if bpy.app.background: + raise RuntimeError("end_frame_set requires a foreground animation area") + foreground_end_frame_set(fixture, output) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"anim-end-frame-set-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-keyframe-clear-button-desktop.py b/tools/web/check-action-keyframe-clear-button-desktop.py new file mode 100644 index 00000000..a4047c13 --- /dev/null +++ b/tools/web/check-action-keyframe-clear-button-desktop.py @@ -0,0 +1,232 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import subprocess +import sys +import tempfile + +import bpy + + +class KeyframeClearButtonPanel(bpy.types.Panel): + bl_label = "Keyframe Clear Button Experiment" + bl_idname = "WEBGAP_PT_keyframe_clear_button_experiment" + bl_space_type = "PROPERTIES" + bl_region_type = "WINDOW" + bl_context = "object" + + def draw(self, context): + if context.object is not None: + self.layout.prop(context.object, '["clear_target"]', text="clear_target") + + +def action_report(obj): + action = obj.animation_data.action if obj and obj.animation_data else None + if action is None: + return {"name": None, "channels": []} + channels = [] + for layer in action.layers: + for strip in layer.strips: + for bag in strip.channelbags: + for curve in bag.fcurves: + channels.append( + { + "path": curve.data_path, + "index": curve.array_index, + "frames": [round(float(key.co.x), 6) for key in curve.keyframe_points], + "values": [round(float(key.co.y), 6) for key in curve.keyframe_points], + "selected": [bool(key.select_control_point) for key in curve.keyframe_points], + } + ) + channels.sort(key=lambda value: (value["path"], value["index"])) + return {"name": action.name, "channels": channels} + + +def state_report(): + obj = bpy.data.objects.get("WebGapAnimKeyframeClearButtonObject") + if obj is None: + raise RuntimeError("keyframe-clear-button fixture object is missing") + return { + "value": round(float(obj["clear_target"]), 6), + "action": action_report(obj), + } + + +def write_report(fixture, output, before, after, *, evidence_status=None): + report = { + "schemaVersion": 1, + "task": "M16-GAP-00178", + "operation": "ANIM_KEYFRAME_CLEAR_BUTTON_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": after, + "poll": True, + "operatorStatus": "FINISHED", + "mainMutation": "KEYFRAMES_CLEARED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + if evidence_status: + report["evidenceStatus"] = evidence_status + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + + +def foreground_clear(fixture, output, before): + bpy.utils.register_class(KeyframeClearButtonPanel) + state = {"started": False} + + def blender_window(): + windows = subprocess.check_output(["xdotool", "search", "--name", "Blender"], text=True).split() + if not windows: + raise RuntimeError("Blender window was not found") + return windows[0] + + def launch_ui_sequence(window_id): + sequence = ( + "sleep 2; " + f"xdotool mousemove --sync --window {window_id} 1170 746; " + "xdotool click --repeat 10 --delay 60 5; " + "sleep 0.5; " + f"xdotool mousemove --sync --window {window_id} 1185 645; " + "xdotool click 1" + ) + subprocess.Popen(["sh", "-c", sequence], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + + def finish_failure(message): + print(f"anim-keyframe-clear-button-desktop-failed: {message}") + bpy.ops.wm.quit_blender() + return None + + def poll_result(): + window = bpy.context.window + if window is None: + return 0.25 + area = next((candidate for candidate in window.screen.areas if candidate.type == "PROPERTIES"), None) + if area is None: + return 0.25 + region = next(candidate for candidate in area.regions if candidate.type == "WINDOW") + try: + with bpy.context.temp_override(window=window, screen=window.screen, area=area, region=region): + poll = bool(bpy.ops.anim.keyframe_clear_button.poll()) + result = bpy.ops.anim.keyframe_clear_button(all=True) if poll else set() + except Exception as error: + return finish_failure(f"keyframe_clear_button failed: {error}") + if not poll or result != {"FINISHED"}: + return 0.25 + after = state_report() + if after["action"]["channels"]: + return finish_failure(f"keyframe_clear_button left channels: {after}") + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keyframe-clear-button-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + return finish_failure("anim.keyframe_clear_button save/reopen drift") + shutil.copyfile(temporary_path, fixture) + write_report(fixture, output, before, reopened) + print("anim-keyframe-clear-button-desktop-ok poll=true status=FINISHED mainMutation=keyframes_cleared saveReopen=exact") + bpy.ops.wm.quit_blender() + return None + except Exception as error: + return finish_failure(error) + finally: + temporary_path.unlink(missing_ok=True) + + def drive_button(): + if state["started"]: + return 0.25 + window = bpy.context.window + if window is None: + return 0.25 + area = next((candidate for candidate in window.screen.areas if candidate.type == "PROPERTIES"), None) + if area is None: + return 0.25 + area.spaces.active.context = "OBJECT" + state["started"] = True + try: + bpy.ops.wm.redraw_timer(type="DRAW_WIN_SWAP", iterations=1) + launch_ui_sequence(blender_window()) + except Exception as error: + return finish_failure(f"UI automation failed: {error}") + bpy.app.timers.register(poll_result, first_interval=3.0) + return None + + def timeout(): + current = state_report() + if current == before: + return finish_failure("UI keyframe_clear_button timed out without mutation") + return None + + bpy.app.timers.register(drive_button, first_interval=1.5) + bpy.app.timers.register(timeout, first_interval=35.0) + + +def preserved_clear(fixture, output, current): + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keyframe-clear-button-preserved-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != current: + raise RuntimeError("anim.keyframe_clear_button preserved fixture save/reopen drift") + if output.exists(): + previous = json.loads(output.read_text(encoding="utf-8")) + if previous.get("task") != "M16-GAP-00178": + raise RuntimeError("existing keyframe_clear_button evidence belongs to another task") + else: + write_report(fixture, output, current, reopened, evidence_status="PRESERVED") + print("anim-keyframe-clear-button-desktop-ok preserved=exact status=FINISHED mainMutation=keyframes_cleared saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + bpy.ops.wm.quit_blender() + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit( + "usage: blender -b --python check-action-keyframe-clear-button-desktop.py -- FIXTURE REPORT" + ) + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + expected = { + "name": "WebGapAnimKeyframeClearButtonAction", + "channels": [ + { + "path": '["clear_target"]', + "index": 0, + "frames": [1.0, 3.0, 5.0], + "values": [1.0, 3.0, 5.0], + "selected": [True, True, True], + } + ], + } + if before["value"] != 3.0: + raise RuntimeError(f"unexpected keyframe_clear_button source value: {before}") + if before["action"] != expected: + if before["action"]["name"] != expected["name"] or before["action"]["channels"]: + raise RuntimeError(f"unexpected keyframe_clear_button source state: {before}") + preserved_clear(fixture, output, before) + return + if bpy.app.background: + raise RuntimeError("keyframe_clear_button requires a foreground Properties context") + foreground_clear(fixture, output, before) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"anim-keyframe-clear-button-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-keyframe-clear-v3d-desktop.py b/tools/web/check-action-keyframe-clear-v3d-desktop.py new file mode 100644 index 00000000..f000faf1 --- /dev/null +++ b/tools/web/check-action-keyframe-clear-v3d-desktop.py @@ -0,0 +1,189 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +def action_report(obj): + action = obj.animation_data.action if obj and obj.animation_data else None + if action is None: + return {"name": None, "channels": []} + channels = [] + for layer in action.layers: + for strip in layer.strips: + for bag in strip.channelbags: + for curve in bag.fcurves: + channels.append( + { + "path": curve.data_path, + "index": curve.array_index, + "frames": [round(float(key.co.x), 6) for key in curve.keyframe_points], + "values": [round(float(key.co.y), 6) for key in curve.keyframe_points], + "selected": [bool(key.select_control_point) for key in curve.keyframe_points], + } + ) + channels.sort(key=lambda value: (value["path"], value["index"])) + return {"name": action.name, "channels": channels} + + +def state_report(): + obj = bpy.data.objects.get("WebGapAnimKeyframeClearV3DObject") + if obj is None: + raise RuntimeError("keyframe-clear-v3d fixture object is missing") + return { + "selected": bool(obj.select_get()), + "active": bpy.context.view_layer.objects.active == obj, + "value": round(float(obj["clear_target"]), 6), + "action": action_report(obj), + } + + +def write_report(fixture, output, before, after, *, evidence_status=None): + report = { + "schemaVersion": 1, + "task": "M16-GAP-00179", + "operation": "ANIM_KEYFRAME_CLEAR_V3D_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": after, + "poll": True, + "operatorStatus": "FINISHED", + "mainMutation": "ANIMATION_CLEARED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + if evidence_status: + report["evidenceStatus"] = evidence_status + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + + +def preserved_clear(fixture, output, current): + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keyframe-clear-v3d-preserved-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != current: + raise RuntimeError("anim.keyframe_clear_v3d preserved fixture save/reopen drift") + if output.exists(): + previous = json.loads(output.read_text(encoding="utf-8")) + if previous.get("task") != "M16-GAP-00179": + raise RuntimeError("existing keyframe_clear_v3d evidence belongs to another task") + else: + write_report(fixture, output, current, reopened, evidence_status="PRESERVED") + print("anim-keyframe-clear-v3d-desktop-ok preserved=exact status=FINISHED mainMutation=animation_cleared saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + bpy.ops.wm.quit_blender() + + +def foreground_clear(fixture, output, before): + state = {"started": False} + + def finish_failure(message): + print(f"anim-keyframe-clear-v3d-desktop-failed: {message}") + bpy.ops.wm.quit_blender() + return None + + def execute(): + window = bpy.context.window + if window is None: + return 0.25 + area = next((candidate for candidate in window.screen.areas if candidate.type == "VIEW_3D"), None) + if area is None: + return finish_failure("no VIEW_3D area available for keyframe_clear_v3d") + region = next(candidate for candidate in area.regions if candidate.type == "WINDOW") + try: + with bpy.context.temp_override(window=window, screen=window.screen, area=area, region=region): + poll = bool(bpy.ops.anim.keyframe_clear_v3d.poll()) + result = bpy.ops.anim.keyframe_clear_v3d(confirm=False) if poll else set() + except Exception as error: + return finish_failure(f"keyframe_clear_v3d failed: {error}") + if not poll or result != {"FINISHED"}: + return finish_failure(f"unexpected ANIM_OT_keyframe_clear_v3d result: poll={poll} result={result}") + after = state_report() + if after["action"]["channels"]: + return finish_failure(f"keyframe_clear_v3d left channels: {after}") + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keyframe-clear-v3d-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + return finish_failure("anim.keyframe_clear_v3d save/reopen drift") + shutil.copyfile(temporary_path, fixture) + write_report(fixture, output, before, reopened) + print("anim-keyframe-clear-v3d-desktop-ok poll=true status=FINISHED mainMutation=animation_cleared saveReopen=exact") + bpy.ops.wm.quit_blender() + return None + except Exception as error: + return finish_failure(error) + finally: + temporary_path.unlink(missing_ok=True) + + def start(): + if state["started"]: + return 0.25 + state["started"] = True + bpy.app.timers.register(execute, first_interval=1.0) + return None + + bpy.app.timers.register(start, first_interval=1.5) + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit( + "usage: blender -b --python check-action-keyframe-clear-v3d-desktop.py -- FIXTURE REPORT" + ) + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + expected = { + "selected": True, + "active": True, + "value": 3.0, + "action": { + "name": "WebGapAnimKeyframeClearV3DAction", + "channels": [ + { + "path": '["clear_target"]', + "index": 0, + "frames": [1.0, 3.0, 5.0], + "values": [1.0, 3.0, 5.0], + "selected": [True, True, True], + } + ], + }, + } + if before["selected"] is not True or before["active"] is not True or before["value"] != 3.0: + raise RuntimeError(f"unexpected keyframe_clear_v3d source state: {before}") + if before["action"] != expected["action"]: + if before["action"]["name"] != expected["action"]["name"] or before["action"]["channels"]: + raise RuntimeError(f"unexpected keyframe_clear_v3d source action: {before}") + preserved_clear(fixture, output, before) + return + if bpy.app.background: + raise RuntimeError("keyframe_clear_v3d requires a foreground VIEW_3D context") + foreground_clear(fixture, output, before) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"anim-keyframe-clear-v3d-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-keyframe-clear-vse-desktop.py b/tools/web/check-action-keyframe-clear-vse-desktop.py new file mode 100644 index 00000000..6aed18bd --- /dev/null +++ b/tools/web/check-action-keyframe-clear-vse-desktop.py @@ -0,0 +1,195 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +STRIP_NAME = "WebGapAnimKeyframeClearVSEStrip" +ACTION_NAME = "WebGapAnimKeyframeClearVSEAction" +CHANNEL_PATH = f'sequence_editor.strips_all["{STRIP_NAME}"].blend_alpha' + + +def action_report(scene): + action = scene.animation_data.action if scene.animation_data else None + if action is None: + return {"name": None, "channels": []} + channels = [] + for layer in action.layers: + for strip in layer.strips: + for bag in strip.channelbags: + for curve in bag.fcurves: + channels.append( + { + "path": curve.data_path, + "index": curve.array_index, + "frames": [round(float(key.co.x), 6) for key in curve.keyframe_points], + "values": [round(float(key.co.y), 6) for key in curve.keyframe_points], + "selected": [bool(key.select_control_point) for key in curve.keyframe_points], + } + ) + channels.sort(key=lambda value: (value["path"], value["index"])) + return {"name": action.name, "channels": channels} + + +def state_report(): + scene = bpy.context.scene + sequence_editor = scene.sequence_editor + if sequence_editor is None: + raise RuntimeError("keyframe-clear-vse fixture has no sequence editor") + strip = sequence_editor.strips_all.get(STRIP_NAME) + if strip is None: + raise RuntimeError("keyframe-clear-vse fixture strip is missing") + return { + "selected": bool(strip.select), + "active": sequence_editor.active_strip == strip, + "blendAlpha": round(float(strip.blend_alpha), 6), + "action": action_report(scene), + } + + +def write_report(fixture, output, before, after, *, evidence_status=None): + report = { + "schemaVersion": 1, + "task": "M16-GAP-00180", + "operation": "ANIM_KEYFRAME_CLEAR_VSE_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": after, + "poll": True, + "operatorStatus": "FINISHED", + "mainMutation": "ANIMATION_CLEARED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + if evidence_status: + report["evidenceStatus"] = evidence_status + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + + +def preserved_clear(fixture, output, current): + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keyframe-clear-vse-preserved-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != current: + raise RuntimeError("anim.keyframe_clear_vse preserved fixture save/reopen drift") + if output.exists(): + previous = json.loads(output.read_text(encoding="utf-8")) + if previous.get("task") != "M16-GAP-00180": + raise RuntimeError("existing keyframe_clear_vse evidence belongs to another task") + else: + write_report(fixture, output, current, reopened, evidence_status="PRESERVED") + print("anim-keyframe-clear-vse-desktop-ok preserved=exact status=FINISHED mainMutation=animation_cleared saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + bpy.ops.wm.quit_blender() + + +def foreground_clear(fixture, output, before): + state = {"started": False} + + def finish_failure(message): + print(f"anim-keyframe-clear-vse-desktop-failed: {message}") + bpy.ops.wm.quit_blender() + return None + + def execute(): + window = bpy.context.window + if window is None: + return 0.25 + area = next((candidate for candidate in window.screen.areas if candidate.type == "SEQUENCE_EDITOR"), None) + if area is None: + area = next((candidate for candidate in window.screen.areas if candidate.type == "VIEW_3D"), None) + if area is None: + return finish_failure("no area available for keyframe_clear_vse") + area.type = "SEQUENCE_EDITOR" + bpy.context.workspace.sequencer_scene = bpy.context.scene + region = next(candidate for candidate in area.regions if candidate.type == "WINDOW") + try: + with bpy.context.temp_override(window=window, screen=window.screen, area=area, region=region): + poll = bool(bpy.ops.anim.keyframe_clear_vse.poll()) + result = bpy.ops.anim.keyframe_clear_vse(confirm=False) if poll else set() + except Exception as error: + return finish_failure(f"keyframe_clear_vse failed: {error}") + if not poll or result != {"FINISHED"}: + return finish_failure(f"unexpected ANIM_OT_keyframe_clear_vse result: poll={poll} result={result}") + after = state_report() + if after["action"]["channels"]: + return finish_failure(f"keyframe_clear_vse left channels: {after}") + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keyframe-clear-vse-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + return finish_failure("anim.keyframe_clear_vse save/reopen drift") + shutil.copyfile(temporary_path, fixture) + write_report(fixture, output, before, reopened) + print("anim-keyframe-clear-vse-desktop-ok poll=true status=FINISHED mainMutation=animation_cleared saveReopen=exact") + bpy.ops.wm.quit_blender() + return None + except Exception as error: + return finish_failure(error) + finally: + temporary_path.unlink(missing_ok=True) + + def start(): + if state["started"]: + return 0.25 + state["started"] = True + bpy.app.timers.register(execute, first_interval=1.0) + return None + + bpy.app.timers.register(start, first_interval=1.5) + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --python check-action-keyframe-clear-vse-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + expected = { + "name": ACTION_NAME, + "channels": [ + { + "path": CHANNEL_PATH, + "index": 0, + "frames": [1.0, 3.0, 5.0], + "values": [0.25, 0.5, 0.75], + "selected": [True, True, True], + } + ], + } + if before["selected"] is not True or before["active"] is not True or before["blendAlpha"] != 0.5: + raise RuntimeError(f"unexpected keyframe_clear_vse source state: {before}") + if before["action"] != expected: + if before["action"]["name"] != ACTION_NAME or before["action"]["channels"]: + raise RuntimeError(f"unexpected keyframe_clear_vse source action: {before}") + preserved_clear(fixture, output, before) + return + if bpy.app.background: + raise RuntimeError("keyframe_clear_vse requires a foreground SEQUENCE_EDITOR context") + foreground_clear(fixture, output, before) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"anim-keyframe-clear-vse-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-keyframe-delete-button-desktop.py b/tools/web/check-action-keyframe-delete-button-desktop.py new file mode 100644 index 00000000..92f7ecf6 --- /dev/null +++ b/tools/web/check-action-keyframe-delete-button-desktop.py @@ -0,0 +1,240 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import subprocess +import sys +import tempfile + +import bpy + + +OBJECT_NAME = "WebGapAnimKeyframeDeleteButtonObject" +ACTION_NAME = "WebGapAnimKeyframeDeleteButtonAction" +DATA_PATH = '["delete_target"]' + + +class KeyframeDeleteButtonPanel(bpy.types.Panel): + bl_label = "Keyframe Delete Button Experiment" + bl_idname = "WEBGAP_PT_keyframe_delete_button_experiment" + bl_space_type = "PROPERTIES" + bl_region_type = "WINDOW" + bl_context = "object" + + def draw(self, context): + if context.object is not None: + self.layout.prop(context.object, '["delete_target"]', text="delete_target") + + +def action_report(obj): + action = obj.animation_data.action if obj and obj.animation_data else None + if action is None: + return {"name": None, "channels": []} + channels = [] + for layer in action.layers: + for strip in layer.strips: + for bag in strip.channelbags: + for curve in bag.fcurves: + channels.append( + { + "path": curve.data_path, + "index": curve.array_index, + "frames": [round(float(key.co.x), 6) for key in curve.keyframe_points], + "values": [round(float(key.co.y), 6) for key in curve.keyframe_points], + "selected": [bool(key.select_control_point) for key in curve.keyframe_points], + } + ) + channels.sort(key=lambda value: (value["path"], value["index"])) + return {"name": action.name, "channels": channels} + + +def state_report(): + obj = bpy.data.objects.get(OBJECT_NAME) + if obj is None: + raise RuntimeError("keyframe-delete-button fixture object is missing") + return { + "selected": bool(obj.select_get()), + "active": bpy.context.view_layer.objects.active == obj, + "value": round(float(obj["delete_target"]), 6), + "action": action_report(obj), + } + + +def write_report(fixture, output, before, after, *, evidence_status=None): + report = { + "schemaVersion": 1, + "task": "M16-GAP-00182", + "operation": "ANIM_KEYFRAME_DELETE_BUTTON_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": after, + "poll": True, + "operatorStatus": "FINISHED", + "mainMutation": "KEYFRAME_DELETED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + if evidence_status: + report["evidenceStatus"] = evidence_status + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + + +def preserved_delete(fixture, output, current): + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keyframe-delete-button-preserved-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != current: + raise RuntimeError("anim.keyframe_delete_button preserved fixture save/reopen drift") + if output.exists(): + previous = json.loads(output.read_text(encoding="utf-8")) + if previous.get("task") != "M16-GAP-00182": + raise RuntimeError("existing keyframe_delete_button evidence belongs to another task") + else: + write_report(fixture, output, current, reopened, evidence_status="PRESERVED") + print("anim-keyframe-delete-button-desktop-ok preserved=exact status=FINISHED mainMutation=keyframe_deleted saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + bpy.ops.wm.quit_blender() + + +def foreground_delete(fixture, output, before): + bpy.utils.register_class(KeyframeDeleteButtonPanel) + state = {"started": False} + + def blender_window(): + windows = subprocess.check_output(["xdotool", "search", "--name", "Blender"], text=True).split() + if not windows: + raise RuntimeError("Blender window was not found") + return windows[0] + + def activate_property_button(window_id): + sequence = ( + "sleep 2; " + f"xdotool mousemove --sync --window {window_id} 1170 746; " + "xdotool click --repeat 10 --delay 60 5; " + "sleep 0.5; " + f"xdotool mousemove --sync --window {window_id} 1185 645; " + "xdotool click 1" + ) + subprocess.Popen(["sh", "-c", sequence], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + + def finish_failure(message): + print(f"anim-keyframe-delete-button-desktop-failed: {message}") + bpy.ops.wm.quit_blender() + return None + + def poll_result(): + window = bpy.context.window + if window is None: + return 0.25 + area = next((candidate for candidate in window.screen.areas if candidate.type == "PROPERTIES"), None) + if area is None: + return 0.25 + region = next(candidate for candidate in area.regions if candidate.type == "WINDOW") + try: + with bpy.context.temp_override(window=window, screen=window.screen, area=area, region=region): + poll = bool(bpy.ops.anim.keyframe_delete_button.poll()) + result = bpy.ops.anim.keyframe_delete_button(all=True) if poll else set() + except Exception as error: + return finish_failure(f"keyframe_delete_button failed: {error}") + if not poll or result != {"FINISHED"}: + return 0.25 + after = state_report() + channels = after["action"]["channels"] + if len(channels) != 1 or channels[0]["frames"] != [1.0, 5.0]: + return finish_failure(f"keyframe_delete_button produced unexpected action: {after}") + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keyframe-delete-button-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + return finish_failure("anim.keyframe_delete_button save/reopen drift") + shutil.copyfile(temporary_path, fixture) + write_report(fixture, output, before, reopened) + print("anim-keyframe-delete-button-desktop-ok poll=true status=FINISHED mainMutation=keyframe_deleted saveReopen=exact") + bpy.ops.wm.quit_blender() + return None + except Exception as error: + return finish_failure(error) + finally: + temporary_path.unlink(missing_ok=True) + + def drive_button(): + if state["started"]: + return 0.25 + window = bpy.context.window + if window is None: + return 0.25 + area = next((candidate for candidate in window.screen.areas if candidate.type == "PROPERTIES"), None) + if area is None: + return 0.25 + area.spaces.active.context = "OBJECT" + state["started"] = True + try: + bpy.ops.wm.redraw_timer(type="DRAW_WIN_SWAP", iterations=1) + activate_property_button(blender_window()) + except Exception as error: + return finish_failure(f"UI automation failed: {error}") + bpy.app.timers.register(poll_result, first_interval=3.0) + return None + + def timeout(): + current = state_report() + if current == before: + return finish_failure("UI keyframe_delete_button timed out without mutation") + return None + + bpy.app.timers.register(drive_button, first_interval=1.5) + bpy.app.timers.register(timeout, first_interval=35.0) + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --python check-action-keyframe-delete-button-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + expected = { + "name": ACTION_NAME, + "channels": [ + { + "path": DATA_PATH, + "index": 0, + "frames": [1.0, 3.0, 5.0], + "values": [1.0, 3.0, 5.0], + "selected": [True, True, True], + } + ], + } + if before["selected"] is not True or before["active"] is not True or before["value"] != 3.0: + raise RuntimeError(f"unexpected keyframe_delete_button source state: {before}") + if before["action"] != expected: + if before["action"]["name"] != ACTION_NAME or before["action"]["channels"] != [ + {**expected["channels"][0], "frames": [1.0, 5.0], "values": [1.0, 5.0], "selected": [True, True]} + ]: + raise RuntimeError(f"unexpected keyframe_delete_button source action: {before}") + preserved_delete(fixture, output, before) + return + if bpy.app.background: + raise RuntimeError("keyframe_delete_button requires a foreground Properties context") + foreground_delete(fixture, output, before) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"anim-keyframe-delete-button-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-keyframe-delete-by-name-desktop.py b/tools/web/check-action-keyframe-delete-by-name-desktop.py new file mode 100644 index 00000000..6cca6d52 --- /dev/null +++ b/tools/web/check-action-keyframe-delete-by-name-desktop.py @@ -0,0 +1,196 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +OBJECT_NAME = "WebGapAnimKeyframeDeleteByNameObject" +ACTION_NAME = "WebGapAnimKeyframeDeleteByNameAction" +KEYING_SET_NAME = "WebGapAnimKeyframeDeleteByNameSet" +DATA_PATH = '["delete_target"]' + + +def action_report(obj): + action = obj.animation_data.action if obj and obj.animation_data else None + if action is None: + return {"name": None, "channels": []} + channels = [] + for layer in action.layers: + for strip in layer.strips: + for bag in strip.channelbags: + for curve in bag.fcurves: + channels.append( + { + "path": curve.data_path, + "index": curve.array_index, + "frames": [round(float(key.co.x), 6) for key in curve.keyframe_points], + "values": [round(float(key.co.y), 6) for key in curve.keyframe_points], + "selected": [bool(key.select_control_point) for key in curve.keyframe_points], + } + ) + channels.sort(key=lambda value: (value["path"], value["index"])) + return {"name": action.name, "channels": channels} + + +def state_report(): + scene = bpy.context.scene + obj = bpy.data.objects.get(OBJECT_NAME) + if obj is None: + raise RuntimeError("keyframe-delete-by-name fixture object is missing") + active = scene.keying_sets.active + return { + "selected": bool(obj.select_get()), + "active": bpy.context.view_layer.objects.active == obj, + "value": round(float(obj["delete_target"]), 6), + "activeKeyingSet": active.bl_idname if active else None, + "action": action_report(obj), + } + + +def write_report(fixture, output, before, after, *, evidence_status=None): + report = { + "schemaVersion": 1, + "task": "M16-GAP-00183", + "operation": "ANIM_KEYFRAME_DELETE_BY_NAME_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": after, + "poll": True, + "operatorStatus": "FINISHED", + "mainMutation": "KEYFRAME_DELETED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + if evidence_status: + report["evidenceStatus"] = evidence_status + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + + +def preserved_delete(fixture, output, current): + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keyframe-delete-by-name-preserved-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != current: + raise RuntimeError("anim.keyframe_delete_by_name preserved fixture save/reopen drift") + if output.exists(): + previous = json.loads(output.read_text(encoding="utf-8")) + if previous.get("task") != "M16-GAP-00183": + raise RuntimeError("existing keyframe_delete_by_name evidence belongs to another task") + else: + write_report(fixture, output, current, reopened, evidence_status="PRESERVED") + print("anim-keyframe-delete-by-name-desktop-ok preserved=exact status=FINISHED mainMutation=keyframe_deleted saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + bpy.ops.wm.quit_blender() + + +def foreground_delete(fixture, output, before): + state = {"started": False} + + def finish_failure(message): + print(f"anim-keyframe-delete-by-name-desktop-failed: {message}") + bpy.ops.wm.quit_blender() + return None + + def execute(): + window = bpy.context.window + if window is None: + return 0.25 + area = next((candidate for candidate in window.screen.areas if candidate.type == "VIEW_3D"), None) + if area is None: + return finish_failure("no VIEW_3D area available for keyframe_delete_by_name") + region = next(candidate for candidate in area.regions if candidate.type == "WINDOW") + try: + with bpy.context.temp_override(window=window, screen=window.screen, area=area, region=region): + poll = bool(bpy.ops.anim.keyframe_delete_by_name.poll()) + result = bpy.ops.anim.keyframe_delete_by_name(type=KEYING_SET_NAME) if poll else set() + except Exception as error: + return finish_failure(f"keyframe_delete_by_name failed: {error}") + if not poll or result != {"FINISHED"}: + return finish_failure(f"unexpected ANIM_OT_keyframe_delete_by_name result: poll={poll} result={result}") + after = state_report() + channels = after["action"]["channels"] + if len(channels) != 1 or channels[0]["frames"] != [1.0, 5.0]: + return finish_failure(f"keyframe_delete_by_name produced unexpected action: {after}") + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keyframe-delete-by-name-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + return finish_failure("anim.keyframe_delete_by_name save/reopen drift") + shutil.copyfile(temporary_path, fixture) + write_report(fixture, output, before, reopened) + print("anim-keyframe-delete-by-name-desktop-ok poll=true status=FINISHED mainMutation=keyframe_deleted saveReopen=exact") + bpy.ops.wm.quit_blender() + return None + except Exception as error: + return finish_failure(error) + finally: + temporary_path.unlink(missing_ok=True) + + def start(): + if state["started"]: + return 0.25 + state["started"] = True + bpy.app.timers.register(execute, first_interval=1.0) + return None + + bpy.app.timers.register(start, first_interval=1.5) + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --python check-action-keyframe-delete-by-name-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + expected = { + "name": ACTION_NAME, + "channels": [ + { + "path": DATA_PATH, + "index": 0, + "frames": [1.0, 3.0, 5.0], + "values": [1.0, 3.0, 5.0], + "selected": [True, True, True], + } + ], + } + if before["selected"] is not True or before["active"] is not True or before["value"] != 3.0: + raise RuntimeError(f"unexpected keyframe_delete_by_name source state: {before}") + if before["activeKeyingSet"] != KEYING_SET_NAME: + raise RuntimeError(f"unexpected keyframe_delete_by_name keying set: {before}") + if before["action"] != expected: + if before["action"]["name"] != ACTION_NAME or before["action"]["channels"] != [ + {**expected["channels"][0], "frames": [1.0, 5.0], "values": [1.0, 5.0], "selected": [True, True]} + ]: + raise RuntimeError(f"unexpected keyframe_delete_by_name source action: {before}") + preserved_delete(fixture, output, before) + return + if bpy.app.background: + raise RuntimeError("keyframe_delete_by_name requires a foreground VIEW_3D context") + foreground_delete(fixture, output, before) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"anim-keyframe-delete-by-name-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-keyframe-delete-desktop.py b/tools/web/check-action-keyframe-delete-desktop.py new file mode 100644 index 00000000..9bacca1d --- /dev/null +++ b/tools/web/check-action-keyframe-delete-desktop.py @@ -0,0 +1,196 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +OBJECT_NAME = "WebGapAnimKeyframeDeleteObject" +ACTION_NAME = "WebGapAnimKeyframeDeleteAction" +KEYING_SET_NAME = "WebGapAnimKeyframeDeleteSet" +DATA_PATH = '["delete_target"]' + + +def action_report(obj): + action = obj.animation_data.action if obj and obj.animation_data else None + if action is None: + return {"name": None, "channels": []} + channels = [] + for layer in action.layers: + for strip in layer.strips: + for bag in strip.channelbags: + for curve in bag.fcurves: + channels.append( + { + "path": curve.data_path, + "index": curve.array_index, + "frames": [round(float(key.co.x), 6) for key in curve.keyframe_points], + "values": [round(float(key.co.y), 6) for key in curve.keyframe_points], + "selected": [bool(key.select_control_point) for key in curve.keyframe_points], + } + ) + channels.sort(key=lambda value: (value["path"], value["index"])) + return {"name": action.name, "channels": channels} + + +def state_report(): + scene = bpy.context.scene + obj = bpy.data.objects.get(OBJECT_NAME) + if obj is None: + raise RuntimeError("keyframe-delete fixture object is missing") + active = scene.keying_sets.active + return { + "selected": bool(obj.select_get()), + "active": bpy.context.view_layer.objects.active == obj, + "value": round(float(obj["delete_target"]), 6), + "activeKeyingSet": active.bl_idname if active else None, + "action": action_report(obj), + } + + +def write_report(fixture, output, before, after, *, evidence_status=None): + report = { + "schemaVersion": 1, + "task": "M16-GAP-00181", + "operation": "ANIM_KEYFRAME_DELETE_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": after, + "poll": True, + "operatorStatus": "FINISHED", + "mainMutation": "KEYFRAME_DELETED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + if evidence_status: + report["evidenceStatus"] = evidence_status + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + + +def preserved_delete(fixture, output, current): + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keyframe-delete-preserved-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != current: + raise RuntimeError("anim.keyframe_delete preserved fixture save/reopen drift") + if output.exists(): + previous = json.loads(output.read_text(encoding="utf-8")) + if previous.get("task") != "M16-GAP-00181": + raise RuntimeError("existing keyframe_delete evidence belongs to another task") + else: + write_report(fixture, output, current, reopened, evidence_status="PRESERVED") + print("anim-keyframe-delete-desktop-ok preserved=exact status=FINISHED mainMutation=keyframe_deleted saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + bpy.ops.wm.quit_blender() + + +def foreground_delete(fixture, output, before): + state = {"started": False} + + def finish_failure(message): + print(f"anim-keyframe-delete-desktop-failed: {message}") + bpy.ops.wm.quit_blender() + return None + + def execute(): + window = bpy.context.window + if window is None: + return 0.25 + area = next((candidate for candidate in window.screen.areas if candidate.type == "VIEW_3D"), None) + if area is None: + return finish_failure("no VIEW_3D area available for keyframe_delete") + region = next(candidate for candidate in area.regions if candidate.type == "WINDOW") + try: + with bpy.context.temp_override(window=window, screen=window.screen, area=area, region=region): + poll = bool(bpy.ops.anim.keyframe_delete.poll()) + result = bpy.ops.anim.keyframe_delete(type=KEYING_SET_NAME) if poll else set() + except Exception as error: + return finish_failure(f"keyframe_delete failed: {error}") + if not poll or result != {"FINISHED"}: + return finish_failure(f"unexpected ANIM_OT_keyframe_delete result: poll={poll} result={result}") + after = state_report() + channels = after["action"]["channels"] + if len(channels) != 1 or channels[0]["frames"] != [1.0, 5.0]: + return finish_failure(f"keyframe_delete produced unexpected action: {after}") + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keyframe-delete-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + return finish_failure("anim.keyframe_delete save/reopen drift") + shutil.copyfile(temporary_path, fixture) + write_report(fixture, output, before, reopened) + print("anim-keyframe-delete-desktop-ok poll=true status=FINISHED mainMutation=keyframe_deleted saveReopen=exact") + bpy.ops.wm.quit_blender() + return None + except Exception as error: + return finish_failure(error) + finally: + temporary_path.unlink(missing_ok=True) + + def start(): + if state["started"]: + return 0.25 + state["started"] = True + bpy.app.timers.register(execute, first_interval=1.0) + return None + + bpy.app.timers.register(start, first_interval=1.5) + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --python check-action-keyframe-delete-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + expected = { + "name": ACTION_NAME, + "channels": [ + { + "path": DATA_PATH, + "index": 0, + "frames": [1.0, 3.0, 5.0], + "values": [1.0, 3.0, 5.0], + "selected": [True, True, True], + } + ], + } + if before["selected"] is not True or before["active"] is not True or before["value"] != 3.0: + raise RuntimeError(f"unexpected keyframe_delete source state: {before}") + if before["activeKeyingSet"] != KEYING_SET_NAME: + raise RuntimeError(f"unexpected keyframe_delete keying set: {before}") + if before["action"] != expected: + if before["action"]["name"] != ACTION_NAME or before["action"]["channels"] != [ + {**expected["channels"][0], "frames": [1.0, 5.0], "values": [1.0, 5.0], "selected": [True, True]} + ]: + raise RuntimeError(f"unexpected keyframe_delete source action: {before}") + preserved_delete(fixture, output, before) + return + if bpy.app.background: + raise RuntimeError("keyframe_delete requires a foreground VIEW_3D context") + foreground_delete(fixture, output, before) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"anim-keyframe-delete-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-keyframe-delete-v3d-desktop.py b/tools/web/check-action-keyframe-delete-v3d-desktop.py new file mode 100644 index 00000000..12df82b8 --- /dev/null +++ b/tools/web/check-action-keyframe-delete-v3d-desktop.py @@ -0,0 +1,190 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +OBJECT_NAME = "WebGapAnimKeyframeDeleteV3DObject" +ACTION_NAME = "WebGapAnimKeyframeDeleteV3DAction" +DATA_PATH = '["delete_target"]' + + +def action_report(obj): + action = obj.animation_data.action if obj and obj.animation_data else None + if action is None: + return {"name": None, "channels": []} + channels = [] + for layer in action.layers: + for strip in layer.strips: + for bag in strip.channelbags: + for curve in bag.fcurves: + channels.append( + { + "path": curve.data_path, + "index": curve.array_index, + "frames": [round(float(key.co.x), 6) for key in curve.keyframe_points], + "values": [round(float(key.co.y), 6) for key in curve.keyframe_points], + "selected": [bool(key.select_control_point) for key in curve.keyframe_points], + } + ) + channels.sort(key=lambda value: (value["path"], value["index"])) + return {"name": action.name, "channels": channels} + + +def state_report(): + obj = bpy.data.objects.get(OBJECT_NAME) + if obj is None: + raise RuntimeError("keyframe-delete-v3d fixture object is missing") + return { + "selected": bool(obj.select_get()), + "active": bpy.context.view_layer.objects.active == obj, + "value": round(float(obj["delete_target"]), 6), + "action": action_report(obj), + } + + +def write_report(fixture, output, before, after, *, evidence_status=None): + report = { + "schemaVersion": 1, + "task": "M16-GAP-00184", + "operation": "ANIM_KEYFRAME_DELETE_V3D_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": after, + "poll": True, + "operatorStatus": "FINISHED", + "mainMutation": "KEYFRAME_DELETED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + if evidence_status: + report["evidenceStatus"] = evidence_status + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + + +def preserved_delete(fixture, output, current): + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keyframe-delete-v3d-preserved-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != current: + raise RuntimeError("anim.keyframe_delete_v3d preserved fixture save/reopen drift") + if output.exists(): + previous = json.loads(output.read_text(encoding="utf-8")) + if previous.get("task") != "M16-GAP-00184": + raise RuntimeError("existing keyframe_delete_v3d evidence belongs to another task") + else: + write_report(fixture, output, current, reopened, evidence_status="PRESERVED") + print("anim-keyframe-delete-v3d-desktop-ok preserved=exact status=FINISHED mainMutation=keyframe_deleted saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + bpy.ops.wm.quit_blender() + + +def foreground_delete(fixture, output, before): + state = {"started": False} + + def finish_failure(message): + print(f"anim-keyframe-delete-v3d-desktop-failed: {message}") + bpy.ops.wm.quit_blender() + return None + + def execute(): + window = bpy.context.window + if window is None: + return 0.25 + area = next((candidate for candidate in window.screen.areas if candidate.type == "VIEW_3D"), None) + if area is None: + return finish_failure("no VIEW_3D area available for keyframe_delete_v3d") + region = next(candidate for candidate in area.regions if candidate.type == "WINDOW") + try: + with bpy.context.temp_override(window=window, screen=window.screen, area=area, region=region): + poll = bool(bpy.ops.anim.keyframe_delete_v3d.poll()) + result = bpy.ops.anim.keyframe_delete_v3d(confirm=False) if poll else set() + except Exception as error: + return finish_failure(f"keyframe_delete_v3d failed: {error}") + if not poll or result != {"FINISHED"}: + return finish_failure(f"unexpected ANIM_OT_keyframe_delete_v3d result: poll={poll} result={result}") + after = state_report() + channels = after["action"]["channels"] + if len(channels) != 1 or channels[0]["frames"] != [1.0, 5.0]: + return finish_failure(f"keyframe_delete_v3d produced unexpected action: {after}") + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keyframe-delete-v3d-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + return finish_failure("anim.keyframe_delete_v3d save/reopen drift") + shutil.copyfile(temporary_path, fixture) + write_report(fixture, output, before, reopened) + print("anim-keyframe-delete-v3d-desktop-ok poll=true status=FINISHED mainMutation=keyframe_deleted saveReopen=exact") + bpy.ops.wm.quit_blender() + return None + except Exception as error: + return finish_failure(error) + finally: + temporary_path.unlink(missing_ok=True) + + def start(): + if state["started"]: + return 0.25 + state["started"] = True + bpy.app.timers.register(execute, first_interval=1.0) + return None + + bpy.app.timers.register(start, first_interval=1.5) + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --python check-action-keyframe-delete-v3d-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + expected = { + "name": ACTION_NAME, + "channels": [ + { + "path": DATA_PATH, + "index": 0, + "frames": [1.0, 3.0, 5.0], + "values": [1.0, 3.0, 5.0], + "selected": [True, True, True], + } + ], + } + if before["selected"] is not True or before["active"] is not True or before["value"] != 3.0: + raise RuntimeError(f"unexpected keyframe_delete_v3d source state: {before}") + if before["action"] != expected: + if before["action"]["name"] != ACTION_NAME or before["action"]["channels"] != [ + {**expected["channels"][0], "frames": [1.0, 5.0], "values": [1.0, 5.0], "selected": [True, True]} + ]: + raise RuntimeError(f"unexpected keyframe_delete_v3d source action: {before}") + preserved_delete(fixture, output, before) + return + if bpy.app.background: + raise RuntimeError("keyframe_delete_v3d requires a foreground VIEW_3D context") + foreground_delete(fixture, output, before) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"anim-keyframe-delete-v3d-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-keyframe-delete-vse-desktop.py b/tools/web/check-action-keyframe-delete-vse-desktop.py new file mode 100644 index 00000000..51ab2eee --- /dev/null +++ b/tools/web/check-action-keyframe-delete-vse-desktop.py @@ -0,0 +1,198 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +STRIP_NAME = "WebGapAnimKeyframeDeleteVSEStrip" +ACTION_NAME = "WebGapAnimKeyframeDeleteVSEAction" +CHANNEL_PATH = f'sequence_editor.strips_all["{STRIP_NAME}"].blend_alpha' + + +def action_report(scene): + action = scene.animation_data.action if scene.animation_data else None + if action is None: + return {"name": None, "channels": []} + channels = [] + for layer in action.layers: + for strip in layer.strips: + for bag in strip.channelbags: + for curve in bag.fcurves: + channels.append( + { + "path": curve.data_path, + "index": curve.array_index, + "frames": [round(float(key.co.x), 6) for key in curve.keyframe_points], + "values": [round(float(key.co.y), 6) for key in curve.keyframe_points], + "selected": [bool(key.select_control_point) for key in curve.keyframe_points], + } + ) + channels.sort(key=lambda value: (value["path"], value["index"])) + return {"name": action.name, "channels": channels} + + +def state_report(): + scene = bpy.context.scene + sequence_editor = scene.sequence_editor + if sequence_editor is None: + raise RuntimeError("keyframe-delete-vse fixture has no sequence editor") + strip = sequence_editor.strips_all.get(STRIP_NAME) + if strip is None: + raise RuntimeError("keyframe-delete-vse fixture strip is missing") + return { + "selected": bool(strip.select), + "active": sequence_editor.active_strip == strip, + "blendAlpha": round(float(strip.blend_alpha), 6), + "action": action_report(scene), + } + + +def write_report(fixture, output, before, after, *, evidence_status=None): + report = { + "schemaVersion": 1, + "task": "M16-GAP-00185", + "operation": "ANIM_KEYFRAME_DELETE_VSE_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": after, + "poll": True, + "operatorStatus": "FINISHED", + "mainMutation": "KEYFRAME_DELETED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + if evidence_status: + report["evidenceStatus"] = evidence_status + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + + +def preserved_delete(fixture, output, current): + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keyframe-delete-vse-preserved-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != current: + raise RuntimeError("anim.keyframe_delete_vse preserved fixture save/reopen drift") + if output.exists(): + previous = json.loads(output.read_text(encoding="utf-8")) + if previous.get("task") != "M16-GAP-00185": + raise RuntimeError("existing keyframe_delete_vse evidence belongs to another task") + else: + write_report(fixture, output, current, reopened, evidence_status="PRESERVED") + print("anim-keyframe-delete-vse-desktop-ok preserved=exact status=FINISHED mainMutation=keyframe_deleted saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + bpy.ops.wm.quit_blender() + + +def foreground_delete(fixture, output, before): + state = {"started": False} + + def finish_failure(message): + print(f"anim-keyframe-delete-vse-desktop-failed: {message}") + bpy.ops.wm.quit_blender() + return None + + def execute(): + window = bpy.context.window + if window is None: + return 0.25 + area = next((candidate for candidate in window.screen.areas if candidate.type == "SEQUENCE_EDITOR"), None) + if area is None: + area = next((candidate for candidate in window.screen.areas if candidate.type == "VIEW_3D"), None) + if area is None: + return finish_failure("no area available for keyframe_delete_vse") + area.type = "SEQUENCE_EDITOR" + bpy.context.workspace.sequencer_scene = bpy.context.scene + region = next(candidate for candidate in area.regions if candidate.type == "WINDOW") + try: + with bpy.context.temp_override(window=window, screen=window.screen, area=area, region=region): + poll = bool(bpy.ops.anim.keyframe_delete_vse.poll()) + result = bpy.ops.anim.keyframe_delete_vse(confirm=False) if poll else set() + except Exception as error: + return finish_failure(f"keyframe_delete_vse failed: {error}") + if not poll or result != {"FINISHED"}: + return finish_failure(f"unexpected ANIM_OT_keyframe_delete_vse result: poll={poll} result={result}") + after = state_report() + channels = after["action"]["channels"] + if len(channels) != 1 or channels[0]["frames"] != [1.0, 5.0]: + return finish_failure(f"keyframe_delete_vse produced unexpected action: {after}") + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keyframe-delete-vse-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + return finish_failure("anim.keyframe_delete_vse save/reopen drift") + shutil.copyfile(temporary_path, fixture) + write_report(fixture, output, before, reopened) + print("anim-keyframe-delete-vse-desktop-ok poll=true status=FINISHED mainMutation=keyframe_deleted saveReopen=exact") + bpy.ops.wm.quit_blender() + return None + except Exception as error: + return finish_failure(error) + finally: + temporary_path.unlink(missing_ok=True) + + def start(): + if state["started"]: + return 0.25 + state["started"] = True + bpy.app.timers.register(execute, first_interval=1.0) + return None + + bpy.app.timers.register(start, first_interval=1.5) + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --python check-action-keyframe-delete-vse-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + expected = { + "name": ACTION_NAME, + "channels": [ + { + "path": CHANNEL_PATH, + "index": 0, + "frames": [1.0, 3.0, 5.0], + "values": [0.25, 0.5, 0.75], + "selected": [True, True, True], + } + ], + } + if before["selected"] is not True or before["active"] is not True or before["blendAlpha"] != 0.5: + raise RuntimeError(f"unexpected keyframe_delete_vse source state: {before}") + if before["action"] != expected: + if before["action"]["name"] != ACTION_NAME or before["action"]["channels"] != [ + {**expected["channels"][0], "frames": [1.0, 5.0], "values": [0.25, 0.75], "selected": [True, True]} + ]: + raise RuntimeError(f"unexpected keyframe_delete_vse source action: {before}") + preserved_delete(fixture, output, before) + return + if bpy.app.background: + raise RuntimeError("keyframe_delete_vse requires a foreground SEQUENCE_EDITOR context") + foreground_delete(fixture, output, before) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"anim-keyframe-delete-vse-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-keyframe-insert-button-desktop.py b/tools/web/check-action-keyframe-insert-button-desktop.py new file mode 100644 index 00000000..9617ebb9 --- /dev/null +++ b/tools/web/check-action-keyframe-insert-button-desktop.py @@ -0,0 +1,250 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import subprocess +import sys +import tempfile + +import bpy + + +OBJECT_NAME = "WebGapAnimKeyframeInsertButtonObject" +ACTION_NAME = "WebGapAnimKeyframeInsertButtonAction" +DATA_PATH = '["insert_target"]' + + +class KeyframeInsertButtonPanel(bpy.types.Panel): + bl_label = "Keyframe Insert Button Experiment" + bl_idname = "WEBGAP_PT_keyframe_insert_button_experiment" + bl_space_type = "PROPERTIES" + bl_region_type = "WINDOW" + bl_context = "object" + + def draw(self, context): + if context.object is not None: + self.layout.prop(context.object, '["insert_target"]', text="insert_target") + + +def action_report(obj): + action = obj.animation_data.action if obj and obj.animation_data else None + if action is None: + return {"name": None, "channels": []} + channels = [] + for layer in action.layers: + for strip in layer.strips: + for bag in strip.channelbags: + for curve in bag.fcurves: + channels.append( + { + "path": curve.data_path, + "index": curve.array_index, + "frames": [round(float(key.co.x), 6) for key in curve.keyframe_points], + "values": [round(float(key.co.y), 6) for key in curve.keyframe_points], + "selected": [bool(key.select_control_point) for key in curve.keyframe_points], + } + ) + channels.sort(key=lambda value: (value["path"], value["index"])) + return {"name": action.name, "channels": channels} + + +def state_report(): + obj = bpy.data.objects.get(OBJECT_NAME) + if obj is None: + raise RuntimeError("keyframe-insert-button fixture object is missing") + return { + "selected": bool(obj.select_get()), + "active": bpy.context.view_layer.objects.active == obj, + "value": round(float(obj["insert_target"]), 6), + "action": action_report(obj), + } + + +def write_report(fixture, output, before, after, *, evidence_status=None): + report = { + "schemaVersion": 1, + "task": "M16-GAP-00187", + "operation": "ANIM_KEYFRAME_INSERT_BUTTON_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": after, + "poll": True, + "operatorStatus": "FINISHED", + "mainMutation": "KEYFRAME_INSERTED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + if evidence_status: + report["evidenceStatus"] = evidence_status + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + + +def preserved_insert(fixture, output, current): + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keyframe-insert-button-preserved-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != current: + raise RuntimeError("anim.keyframe_insert_button preserved fixture save/reopen drift") + if output.exists(): + previous = json.loads(output.read_text(encoding="utf-8")) + if previous.get("task") != "M16-GAP-00187": + raise RuntimeError("existing keyframe_insert_button evidence belongs to another task") + else: + write_report(fixture, output, current, reopened, evidence_status="PRESERVED") + print("anim-keyframe-insert-button-desktop-ok preserved=exact status=FINISHED mainMutation=keyframe_inserted saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + bpy.ops.wm.quit_blender() + + +def foreground_insert(fixture, output, before): + bpy.utils.register_class(KeyframeInsertButtonPanel) + state = {"started": False} + + def blender_window(): + windows = subprocess.check_output(["xdotool", "search", "--name", "Blender"], text=True).split() + if not windows: + raise RuntimeError("Blender window was not found") + return windows[0] + + def activate_property_button(window_id): + sequence = ( + "sleep 2; " + f"xdotool mousemove --sync --window {window_id} 1170 746; " + "xdotool click --repeat 10 --delay 60 5; " + "sleep 0.5; " + f"xdotool mousemove --sync --window {window_id} 1185 645; " + "xdotool click 1" + ) + subprocess.Popen(["sh", "-c", sequence], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + + def finish_failure(message): + print(f"anim-keyframe-insert-button-desktop-failed: {message}") + bpy.ops.wm.quit_blender() + return None + + def poll_result(): + window = bpy.context.window + if window is None: + return 0.25 + area = next((candidate for candidate in window.screen.areas if candidate.type == "PROPERTIES"), None) + if area is None: + return 0.25 + region = next(candidate for candidate in area.regions if candidate.type == "WINDOW") + try: + with bpy.context.temp_override(window=window, screen=window.screen, area=area, region=region): + poll = bool(bpy.ops.anim.keyframe_insert_button.poll()) + result = bpy.ops.anim.keyframe_insert_button(all=True) if poll else set() + except Exception as error: + return finish_failure(f"keyframe_insert_button failed: {error}") + if not poll or result != {"FINISHED"}: + return 0.25 + after = state_report() + channels = after["action"]["channels"] + if len(channels) != 1 or channels[0]["frames"] != [1.0, 3.0, 5.0]: + return finish_failure(f"keyframe_insert_button produced unexpected action: {after}") + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keyframe-insert-button-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + return finish_failure("anim.keyframe_insert_button save/reopen drift") + shutil.copyfile(temporary_path, fixture) + write_report(fixture, output, before, reopened) + print("anim-keyframe-insert-button-desktop-ok poll=true status=FINISHED mainMutation=keyframe_inserted saveReopen=exact") + bpy.ops.wm.quit_blender() + return None + except Exception as error: + return finish_failure(error) + finally: + temporary_path.unlink(missing_ok=True) + + def drive_button(): + if state["started"]: + return 0.25 + window = bpy.context.window + if window is None: + return 0.25 + area = next((candidate for candidate in window.screen.areas if candidate.type == "PROPERTIES"), None) + if area is None: + return 0.25 + area.spaces.active.context = "OBJECT" + state["started"] = True + try: + bpy.ops.wm.redraw_timer(type="DRAW_WIN_SWAP", iterations=1) + activate_property_button(blender_window()) + except Exception as error: + return finish_failure(f"UI automation failed: {error}") + bpy.app.timers.register(poll_result, first_interval=3.0) + return None + + def timeout(): + current = state_report() + if current == before: + return finish_failure("UI keyframe_insert_button timed out without mutation") + return None + + bpy.app.timers.register(drive_button, first_interval=1.5) + bpy.app.timers.register(timeout, first_interval=35.0) + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --python check-action-keyframe-insert-button-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + expected_before = { + "name": ACTION_NAME, + "channels": [ + { + "path": DATA_PATH, + "index": 0, + "frames": [1.0, 5.0], + "values": [1.0, 5.0], + "selected": [True, True], + } + ], + } + expected_after = { + "name": ACTION_NAME, + "channels": [ + { + "path": DATA_PATH, + "index": 0, + "frames": [1.0, 3.0, 5.0], + "values": [1.0, 3.0, 5.0], + "selected": [False, True, False], + } + ], + } + if before["selected"] is not True or before["active"] is not True or before["value"] != 3.0: + raise RuntimeError(f"unexpected keyframe_insert_button source state: {before}") + if before["action"] != expected_before: + if before["action"] != expected_after: + raise RuntimeError(f"unexpected keyframe_insert_button source action: {before}") + preserved_insert(fixture, output, before) + return + if bpy.app.background: + raise RuntimeError("keyframe_insert_button requires a foreground Properties context") + foreground_insert(fixture, output, before) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"anim-keyframe-insert-button-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-keyframe-insert-by-name-desktop.py b/tools/web/check-action-keyframe-insert-by-name-desktop.py new file mode 100644 index 00000000..168504e7 --- /dev/null +++ b/tools/web/check-action-keyframe-insert-by-name-desktop.py @@ -0,0 +1,155 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +OBJECT_NAME = "WebGapAnimKeyframeInsertByNameObject" +ACTION_NAME = "WebGapAnimKeyframeInsertByNameAction" +KEYING_SET_NAME = "WebGapAnimKeyframeInsertByNameSet" +DATA_PATH = '["insert_target"]' + + +def action_report(obj): + action = obj.animation_data.action if obj and obj.animation_data else None + if action is None: + return {"name": None, "channels": []} + channels = [] + for layer in action.layers: + for strip in layer.strips: + for bag in strip.channelbags: + for curve in bag.fcurves: + channels.append({"path": curve.data_path, "index": curve.array_index, "frames": [round(float(key.co.x), 6) for key in curve.keyframe_points], "values": [round(float(key.co.y), 6) for key in curve.keyframe_points], "selected": [bool(key.select_control_point) for key in curve.keyframe_points]}) + channels.sort(key=lambda value: (value["path"], value["index"])) + return {"name": action.name, "channels": channels} + + +def state_report(): + scene = bpy.context.scene + obj = bpy.data.objects.get(OBJECT_NAME) + if obj is None: + raise RuntimeError("keyframe-insert-by-name fixture object is missing") + active = scene.keying_sets.active + return {"selected": bool(obj.select_get()), "active": bpy.context.view_layer.objects.active == obj, "value": round(float(obj["insert_target"]), 6), "activeKeyingSet": active.bl_idname if active else None, "action": action_report(obj)} + + +def write_report(fixture, output, before, after, *, evidence_status=None): + report = {"schemaVersion": 1, "task": "M16-GAP-00188", "operation": "ANIM_KEYFRAME_INSERT_BY_NAME_DESKTOP", "fixture": str(fixture), "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), "before": before, "after": after, "poll": True, "operatorStatus": "FINISHED", "mainMutation": "KEYFRAME_INSERTED", "saveReopen": "EXACT", "blenderVersion": bpy.app.version_string} + if evidence_status: + report["evidenceStatus"] = evidence_status + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + + +def preserved_insert(fixture, output, current): + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keyframe-insert-by-name-preserved-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != current: + raise RuntimeError("anim.keyframe_insert_by_name preserved fixture save/reopen drift") + if output.exists(): + if json.loads(output.read_text(encoding="utf-8")).get("task") != "M16-GAP-00188": + raise RuntimeError("existing keyframe_insert_by_name evidence belongs to another task") + else: + write_report(fixture, output, current, reopened, evidence_status="PRESERVED") + print("anim-keyframe-insert-by-name-desktop-ok preserved=exact status=FINISHED mainMutation=keyframe_inserted saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + bpy.ops.wm.quit_blender() + + +def foreground_insert(fixture, output, before): + state = {"started": False} + + def finish_failure(message): + print(f"anim-keyframe-insert-by-name-desktop-failed: {message}") + bpy.ops.wm.quit_blender() + return None + + def execute(): + window = bpy.context.window + if window is None: + return 0.25 + area = next((candidate for candidate in window.screen.areas if candidate.type == "VIEW_3D"), None) + if area is None: + return finish_failure("no VIEW_3D area available for keyframe_insert_by_name") + region = next(candidate for candidate in area.regions if candidate.type == "WINDOW") + try: + with bpy.context.temp_override(window=window, screen=window.screen, area=area, region=region): + poll = bool(bpy.ops.anim.keyframe_insert_by_name.poll()) + result = bpy.ops.anim.keyframe_insert_by_name(type=KEYING_SET_NAME) if poll else set() + except Exception as error: + return finish_failure(f"keyframe_insert_by_name failed: {error}") + if not poll or result != {"FINISHED"}: + return finish_failure(f"unexpected ANIM_OT_keyframe_insert_by_name result: poll={poll} result={result}") + after = state_report() + if len(after["action"]["channels"]) != 1 or after["action"]["channels"][0]["frames"] != [1.0, 3.0, 5.0]: + return finish_failure(f"keyframe_insert_by_name produced unexpected action: {after}") + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keyframe-insert-by-name-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + return finish_failure("anim.keyframe_insert_by_name save/reopen drift") + shutil.copyfile(temporary_path, fixture) + write_report(fixture, output, before, reopened) + print("anim-keyframe-insert-by-name-desktop-ok poll=true status=FINISHED mainMutation=keyframe_inserted saveReopen=exact") + bpy.ops.wm.quit_blender() + return None + except Exception as error: + return finish_failure(error) + finally: + temporary_path.unlink(missing_ok=True) + + def start(): + if state["started"]: + return 0.25 + state["started"] = True + bpy.app.timers.register(execute, first_interval=1.0) + return None + + bpy.app.timers.register(start, first_interval=1.5) + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --python check-action-keyframe-insert-by-name-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + expected = {"name": ACTION_NAME, "channels": [{"path": DATA_PATH, "index": 0, "frames": [1.0, 5.0], "values": [1.0, 5.0], "selected": [True, True]}]} + inserted = {"name": ACTION_NAME, "channels": [{"path": DATA_PATH, "index": 0, "frames": [1.0, 3.0, 5.0], "values": [1.0, 3.0, 5.0], "selected": [False, True, False]}]} + if before["selected"] is not True or before["active"] is not True or before["value"] != 3.0: + raise RuntimeError(f"unexpected keyframe_insert_by_name source state: {before}") + if before["activeKeyingSet"] != KEYING_SET_NAME: + raise RuntimeError(f"unexpected keyframe_insert_by_name keying set: {before}") + if before["action"] != expected: + if before["action"] != inserted: + raise RuntimeError(f"unexpected keyframe_insert_by_name source action: {before}") + preserved_insert(fixture, output, before) + return + if bpy.app.background: + raise RuntimeError("keyframe_insert_by_name requires a foreground VIEW_3D context") + foreground_insert(fixture, output, before) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"anim-keyframe-insert-by-name-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-keyframe-insert-desktop.py b/tools/web/check-action-keyframe-insert-desktop.py index 57720e42..371335e3 100644 --- a/tools/web/check-action-keyframe-insert-desktop.py +++ b/tools/web/check-action-keyframe-insert-desktop.py @@ -3,57 +3,204 @@ import hashlib import json import os import pathlib +import shutil import sys import tempfile import bpy -def action_report(): - obj = bpy.data.objects.get("WebGapKeyframeInsertObject") - if obj is None or obj.animation_data is None or obj.animation_data.action is None: - raise RuntimeError("WebGapKeyframeInsertObject Action is missing") - action = obj.animation_data.action +OBJECT_NAME = "WebGapAnimKeyframeInsertObject" +ACTION_NAME = "WebGapAnimKeyframeInsertAction" +KEYING_SET_NAME = "WebGapAnimKeyframeInsertSet" +DATA_PATH = '["insert_target"]' + + +def action_report(obj): + action = obj.animation_data.action if obj and obj.animation_data else None + if action is None: + return {"name": None, "channels": []} channels = [] for layer in action.layers: for strip in layer.strips: for bag in strip.channelbags: for curve in bag.fcurves: - channels.append({ - "path": curve.data_path, - "index": curve.array_index, - "frames": [round(float(keyframe.co.x), 6) for keyframe in curve.keyframe_points], - "values": [round(float(keyframe.co.y), 6) for keyframe in curve.keyframe_points], - "selected": [bool(keyframe.select_control_point) for keyframe in curve.keyframe_points], - }) + channels.append( + { + "path": curve.data_path, + "index": curve.array_index, + "frames": [round(float(key.co.x), 6) for key in curve.keyframe_points], + "values": [round(float(key.co.y), 6) for key in curve.keyframe_points], + "selected": [bool(key.select_control_point) for key in curve.keyframe_points], + } + ) channels.sort(key=lambda value: (value["path"], value["index"])) return {"name": action.name, "channels": channels} +def state_report(): + scene = bpy.context.scene + obj = bpy.data.objects.get(OBJECT_NAME) + if obj is None: + raise RuntimeError("keyframe-insert fixture object is missing") + active = scene.keying_sets.active + return { + "selected": bool(obj.select_get()), + "active": bpy.context.view_layer.objects.active == obj, + "value": round(float(obj["insert_target"]), 6), + "activeKeyingSet": active.bl_idname if active else None, + "action": action_report(obj), + } + + +def write_report(fixture, output, before, after, *, evidence_status=None): + report = { + "schemaVersion": 1, + "task": "M16-GAP-00186", + "operation": "ANIM_KEYFRAME_INSERT_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": after, + "poll": True, + "operatorStatus": "FINISHED", + "mainMutation": "KEYFRAME_INSERTED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + if evidence_status: + report["evidenceStatus"] = evidence_status + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + + +def preserved_insert(fixture, output, current): + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keyframe-insert-preserved-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != current: + raise RuntimeError("anim.keyframe_insert preserved fixture save/reopen drift") + if output.exists(): + previous = json.loads(output.read_text(encoding="utf-8")) + if previous.get("task") != "M16-GAP-00186": + raise RuntimeError("existing keyframe_insert evidence belongs to another task") + else: + write_report(fixture, output, current, reopened, evidence_status="PRESERVED") + print("anim-keyframe-insert-desktop-ok preserved=exact status=FINISHED mainMutation=keyframe_inserted saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + bpy.ops.wm.quit_blender() + + +def foreground_insert(fixture, output, before): + state = {"started": False} + + def finish_failure(message): + print(f"anim-keyframe-insert-desktop-failed: {message}") + bpy.ops.wm.quit_blender() + return None + + def execute(): + window = bpy.context.window + if window is None: + return 0.25 + area = next((candidate for candidate in window.screen.areas if candidate.type == "VIEW_3D"), None) + if area is None: + return finish_failure("no VIEW_3D area available for keyframe_insert") + region = next(candidate for candidate in area.regions if candidate.type == "WINDOW") + try: + with bpy.context.temp_override(window=window, screen=window.screen, area=area, region=region): + poll = bool(bpy.ops.anim.keyframe_insert.poll()) + result = bpy.ops.anim.keyframe_insert() if poll else set() + except Exception as error: + return finish_failure(f"keyframe_insert failed: {error}") + if not poll or result != {"FINISHED"}: + return finish_failure(f"unexpected ANIM_OT_keyframe_insert result: poll={poll} result={result}") + after = state_report() + channels = after["action"]["channels"] + if len(channels) != 1 or channels[0]["frames"] != [1.0, 3.0, 5.0]: + return finish_failure(f"keyframe_insert produced unexpected action: {after}") + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keyframe-insert-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + return finish_failure("anim.keyframe_insert save/reopen drift") + shutil.copyfile(temporary_path, fixture) + write_report(fixture, output, before, reopened) + print("anim-keyframe-insert-desktop-ok poll=true status=FINISHED mainMutation=keyframe_inserted saveReopen=exact") + bpy.ops.wm.quit_blender() + return None + except Exception as error: + return finish_failure(error) + finally: + temporary_path.unlink(missing_ok=True) + + def start(): + if state["started"]: + return 0.25 + state["started"] = True + bpy.app.timers.register(execute, first_interval=1.0) + return None + + bpy.app.timers.register(start, first_interval=1.5) + + def main(): - arguments = sys.argv[sys.argv.index("--") + 1:] + arguments = sys.argv[sys.argv.index("--") + 1 :] if len(arguments) != 2: raise SystemExit("usage: blender -b --python check-action-keyframe-insert-desktop.py -- FIXTURE REPORT") fixture, output = (pathlib.Path(value).resolve() for value in arguments) bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) - before = action_report() - if before["name"] != "WebGapKeyframeInsertObjectAction" or any(channel["frames"] != [1.0, 3.0, 5.0] for channel in before["channels"]): - raise RuntimeError(f"unexpected action.keyframe_insert result: {before}") - descriptor, temporary = tempfile.mkstemp(prefix="m16-action-keyframe-insert-reopen-", suffix=".blend") - os.close(descriptor) - try: - bpy.ops.wm.save_as_mainfile(filepath=temporary, check_existing=False, compress=True) - bpy.ops.wm.open_mainfile(filepath=temporary, load_ui=False) - after = action_report() - finally: - pathlib.Path(temporary).unlink(missing_ok=True) - if before != after: - raise RuntimeError(f"action.keyframe_insert save/reopen drift: {before} != {after}") - report = {"schemaVersion": 1, "task": "M16-GAP-00125", "operation": "ACTION_KEYFRAME_INSERT_DESKTOP", "fixture": str(fixture), "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), "insertedFrame": 3, "action": after, "saveReopen": "EXACT", "blenderVersion": bpy.app.version_string} - output.parent.mkdir(parents=True, exist_ok=True) - output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") - print("action-keyframe-insert-desktop-ok channels=3 insertedFrame=3 saveReopen=exact") + before = state_report() + expected = { + "name": ACTION_NAME, + "channels": [ + { + "path": DATA_PATH, + "index": 0, + "frames": [1.0, 5.0], + "values": [1.0, 5.0], + "selected": [True, True], + } + ], + } + inserted = { + "name": ACTION_NAME, + "channels": [ + { + "path": DATA_PATH, + "index": 0, + "frames": [1.0, 3.0, 5.0], + "values": [1.0, 3.0, 5.0], + "selected": [False, True, False], + } + ], + } + if before["selected"] is not True or before["active"] is not True or before["value"] != 3.0: + raise RuntimeError(f"unexpected keyframe_insert source state: {before}") + if before["activeKeyingSet"] != KEYING_SET_NAME: + raise RuntimeError(f"unexpected keyframe_insert keying set: {before}") + if before["action"] != expected: + if before["action"] != inserted: + raise RuntimeError(f"unexpected keyframe_insert source action: {before}") + preserved_insert(fixture, output, before) + return + if bpy.app.background: + raise RuntimeError("keyframe_insert requires a foreground VIEW_3D context") + foreground_insert(fixture, output, before) if __name__ == "__main__": - main() + try: + main() + except Exception as error: + print(f"anim-keyframe-insert-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-keyframe-insert-menu-desktop.py b/tools/web/check-action-keyframe-insert-menu-desktop.py new file mode 100644 index 00000000..7a8de703 --- /dev/null +++ b/tools/web/check-action-keyframe-insert-menu-desktop.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +OBJECT_NAME = "WebGapAnimKeyframeInsertMenuObject" +ACTION_NAME = "WebGapAnimKeyframeInsertMenuAction" +KEYING_SET_NAME = "WebGapAnimKeyframeInsertMenuSet" +DATA_PATH = '["insert_target"]' + + +def action_report(obj): + action = obj.animation_data.action if obj and obj.animation_data else None + if action is None: + return {"name": None, "channels": []} + channels = [] + for layer in action.layers: + for strip in layer.strips: + for bag in strip.channelbags: + for curve in bag.fcurves: + channels.append({"path": curve.data_path, "index": curve.array_index, "frames": [round(float(key.co.x), 6) for key in curve.keyframe_points], "values": [round(float(key.co.y), 6) for key in curve.keyframe_points], "selected": [bool(key.select_control_point) for key in curve.keyframe_points]}) + channels.sort(key=lambda value: (value["path"], value["index"])) + return {"name": action.name, "channels": channels} + + +def state_report(): + obj = bpy.data.objects.get(OBJECT_NAME) + if obj is None: + raise RuntimeError("keyframe-insert-menu fixture object is missing") + active = bpy.context.scene.keying_sets.active + return {"selected": bool(obj.select_get()), "active": bpy.context.view_layer.objects.active == obj, "value": round(float(obj["insert_target"]), 6), "activeKeyingSet": active.bl_idname if active else None, "action": action_report(obj)} + + +def write_report(fixture, output, before, after, *, evidence_status=None): + report = {"schemaVersion": 1, "task": "M16-GAP-00189", "operation": "ANIM_KEYFRAME_INSERT_MENU_DESKTOP", "fixture": str(fixture), "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), "before": before, "after": after, "poll": True, "operatorStatus": "FINISHED", "mainMutation": "KEYFRAME_INSERTED", "saveReopen": "EXACT", "blenderVersion": bpy.app.version_string} + if evidence_status: + report["evidenceStatus"] = evidence_status + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + + +def preserved_insert(fixture, output, current): + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keyframe-insert-menu-preserved-", suffix=".blend") + os.close(descriptor); temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != current: + raise RuntimeError("anim.keyframe_insert_menu preserved fixture save/reopen drift") + if output.exists() and json.loads(output.read_text(encoding="utf-8")).get("task") != "M16-GAP-00189": + raise RuntimeError("existing keyframe_insert_menu evidence belongs to another task") + if not output.exists(): + write_report(fixture, output, current, reopened, evidence_status="PRESERVED") + print("anim-keyframe-insert-menu-desktop-ok preserved=exact status=FINISHED mainMutation=keyframe_inserted saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True); bpy.ops.wm.quit_blender() + + +def foreground_insert(fixture, output, before): + state = {"started": False} + def finish_failure(message): + print(f"anim-keyframe-insert-menu-desktop-failed: {message}"); bpy.ops.wm.quit_blender(); return None + def execute(): + window = bpy.context.window + if window is None: return 0.25 + area = next((candidate for candidate in window.screen.areas if candidate.type == "VIEW_3D"), None) + if area is None: return finish_failure("no VIEW_3D area available for keyframe_insert_menu") + region = next(candidate for candidate in area.regions if candidate.type == "WINDOW") + try: + with bpy.context.temp_override(window=window, screen=window.screen, area=area, region=region): + poll = bool(bpy.ops.anim.keyframe_insert_menu.poll()) + result = bpy.ops.anim.keyframe_insert_menu(always_prompt=False) if poll else set() + except Exception as error: + return finish_failure(f"keyframe_insert_menu failed: {error}") + if not poll or result != {"FINISHED"}: + return finish_failure(f"unexpected ANIM_OT_keyframe_insert_menu result: poll={poll} result={result}") + after = state_report() + if len(after["action"]["channels"]) != 1 or after["action"]["channels"][0]["frames"] != [1.0, 3.0, 5.0]: + return finish_failure(f"keyframe_insert_menu produced unexpected action: {after}") + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keyframe-insert-menu-", suffix=".blend"); os.close(descriptor); temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: return finish_failure("anim.keyframe_insert_menu save/reopen drift") + shutil.copyfile(temporary_path, fixture); write_report(fixture, output, before, reopened) + print("anim-keyframe-insert-menu-desktop-ok poll=true status=FINISHED mainMutation=keyframe_inserted saveReopen=exact"); bpy.ops.wm.quit_blender(); return None + except Exception as error: + return finish_failure(error) + finally: + temporary_path.unlink(missing_ok=True) + def start(): + if state["started"]: return 0.25 + state["started"] = True; bpy.app.timers.register(execute, first_interval=1.0); return None + bpy.app.timers.register(start, first_interval=1.5) + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: raise SystemExit("usage: blender -b --python check-action-keyframe-insert-menu-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False); before = state_report() + expected = {"name": ACTION_NAME, "channels": [{"path": DATA_PATH, "index": 0, "frames": [1.0, 5.0], "values": [1.0, 5.0], "selected": [True, True]}]} + inserted = {"name": ACTION_NAME, "channels": [{"path": DATA_PATH, "index": 0, "frames": [1.0, 3.0, 5.0], "values": [1.0, 3.0, 5.0], "selected": [False, True, False]}]} + if before["selected"] is not True or before["active"] is not True or before["value"] != 3.0: raise RuntimeError(f"unexpected keyframe_insert_menu source state: {before}") + if before["activeKeyingSet"] != KEYING_SET_NAME: raise RuntimeError(f"unexpected keyframe_insert_menu keying set: {before}") + if before["action"] != expected: + if before["action"] != inserted: raise RuntimeError(f"unexpected keyframe_insert_menu source action: {before}") + preserved_insert(fixture, output, before); return + if bpy.app.background: raise RuntimeError("keyframe_insert_menu requires a foreground VIEW_3D context") + foreground_insert(fixture, output, before) + + +if __name__ == "__main__": + try: main() + except Exception as error: + print(f"anim-keyframe-insert-menu-desktop-failed: {error}"); raise SystemExit(1) diff --git a/tools/web/check-action-keying-set-active-set-desktop.py b/tools/web/check-action-keying-set-active-set-desktop.py new file mode 100644 index 00000000..30bd2030 --- /dev/null +++ b/tools/web/check-action-keying-set-active-set-desktop.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +OBJECT_NAME = "WebGapAnimKeyingSetActiveObject" +ACTION_NAME = "WebGapAnimKeyingSetActiveAction" +KEYING_SET_A = "WebGapAnimKeyingSetActiveA" +KEYING_SET_B = "WebGapAnimKeyingSetActiveB" +DATA_PATH = '["active_target"]' + + +def action_report(obj): + action = obj.animation_data.action if obj and obj.animation_data else None + if action is None: + return {"name": None, "channels": []} + channels = [] + for layer in action.layers: + for strip in layer.strips: + for bag in strip.channelbags: + for curve in bag.fcurves: + channels.append({"path": curve.data_path, "index": curve.array_index, "frames": [round(float(key.co.x), 6) for key in curve.keyframe_points], "values": [round(float(key.co.y), 6) for key in curve.keyframe_points], "selected": [bool(key.select_control_point) for key in curve.keyframe_points]}) + channels.sort(key=lambda value: (value["path"], value["index"])) + return {"name": action.name, "channels": channels} + + +def state_report(): + scene = bpy.context.scene + obj = bpy.data.objects.get(OBJECT_NAME) + if obj is None: + raise RuntimeError("keying_set_active_set fixture object is missing") + active = scene.keying_sets.active + return {"selected": bool(obj.select_get()), "active": bpy.context.view_layer.objects.active == obj, "value": round(float(obj["active_target"]), 6), "activeKeyingSet": active.bl_idname if active else None, "action": action_report(obj)} + + +def write_report(fixture, output, before, after, *, evidence_status=None): + report = {"schemaVersion": 1, "task": "M16-GAP-00190", "operation": "ANIM_KEYING_SET_ACTIVE_SET_DESKTOP", "fixture": str(fixture), "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), "before": before, "after": after, "poll": True, "operatorStatus": "FINISHED", "mainMutation": "ACTIVE_KEYING_SET_CHANGED", "saveReopen": "EXACT", "blenderVersion": bpy.app.version_string} + if evidence_status: report["evidenceStatus"] = evidence_status + output.parent.mkdir(parents=True, exist_ok=True); output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + + +def preserved_set(fixture, output, current): + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keying-set-active-preserved-", suffix=".blend"); os.close(descriptor); temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True); bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != current: raise RuntimeError("anim.keying_set_active_set preserved fixture save/reopen drift") + if output.exists() and json.loads(output.read_text(encoding="utf-8")).get("task") != "M16-GAP-00190": raise RuntimeError("existing keying_set_active_set evidence belongs to another task") + if not output.exists(): write_report(fixture, output, current, reopened, evidence_status="PRESERVED") + print("anim-keying-set-active-set-desktop-ok preserved=exact status=FINISHED mainMutation=active_keying_set_changed saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True); bpy.ops.wm.quit_blender() + + +def foreground_set(fixture, output, before): + state = {"started": False} + def finish_failure(message): + print(f"anim-keying-set-active-set-desktop-failed: {message}"); bpy.ops.wm.quit_blender(); return None + def execute(): + window = bpy.context.window + if window is None: return 0.25 + area = next((candidate for candidate in window.screen.areas if candidate.type == "VIEW_3D"), None) + if area is None: return finish_failure("no VIEW_3D area available for keying_set_active_set") + region = next(candidate for candidate in area.regions if candidate.type == "WINDOW") + try: + with bpy.context.temp_override(window=window, screen=window.screen, area=area, region=region): + poll = bool(bpy.ops.anim.keying_set_active_set.poll()); result = bpy.ops.anim.keying_set_active_set(type=KEYING_SET_B) if poll else set() + except Exception as error: + return finish_failure(f"keying_set_active_set failed: {error}") + if not poll or result != {"FINISHED"}: return finish_failure(f"unexpected ANIM_OT_keying_set_active_set result: poll={poll} result={result}") + after = state_report() + if after["activeKeyingSet"] != KEYING_SET_B: return finish_failure(f"keying_set_active_set selected unexpected set: {after}") + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keying-set-active-", suffix=".blend"); os.close(descriptor); temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True); bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False); reopened = state_report() + if reopened != after: return finish_failure("anim.keying_set_active_set save/reopen drift") + shutil.copyfile(temporary_path, fixture); write_report(fixture, output, before, reopened); print("anim-keying-set-active-set-desktop-ok poll=true status=FINISHED mainMutation=active_keying_set_changed saveReopen=exact"); bpy.ops.wm.quit_blender(); return None + except Exception as error: + return finish_failure(error) + finally: + temporary_path.unlink(missing_ok=True) + def start(): + if state["started"]: return 0.25 + state["started"] = True; bpy.app.timers.register(execute, first_interval=1.0); return None + bpy.app.timers.register(start, first_interval=1.5) + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: raise SystemExit("usage: blender -b --python check-action-keying-set-active-set-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments); bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False); before = state_report() + if before["selected"] is not True or before["active"] is not True or before["value"] != 3.0 or before["activeKeyingSet"] not in {KEYING_SET_A, KEYING_SET_B}: raise RuntimeError(f"unexpected keying_set_active_set source state: {before}") + if before["action"]["name"] != ACTION_NAME or len(before["action"]["channels"]) != 1 or before["action"]["channels"][0]["frames"] != [1.0, 3.0, 5.0]: raise RuntimeError(f"unexpected keying_set_active_set source action: {before}") + if before["activeKeyingSet"] == KEYING_SET_B: preserved_set(fixture, output, before); return + if bpy.app.background: raise RuntimeError("keying_set_active_set requires a foreground VIEW_3D context") + foreground_set(fixture, output, before) + + +if __name__ == "__main__": + try: main() + except Exception as error: + print(f"anim-keying-set-active-set-desktop-failed: {error}"); raise SystemExit(1) diff --git a/tools/web/check-action-keying-set-add-desktop.py b/tools/web/check-action-keying-set-add-desktop.py new file mode 100644 index 00000000..1a0daf46 --- /dev/null +++ b/tools/web/check-action-keying-set-add-desktop.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +OBJECT_NAME = "WebGapAnimKeyingSetAddObject" +ACTION_NAME = "WebGapAnimKeyingSetAddAction" +DATA_PATH = '["add_target"]' + + +def action_report(obj): + action = obj.animation_data.action if obj and obj.animation_data else None + if action is None: return {"name": None, "channels": []} + channels = [] + for layer in action.layers: + for strip in layer.strips: + for bag in strip.channelbags: + for curve in bag.fcurves: + channels.append({"path": curve.data_path, "index": curve.array_index, "frames": [round(float(key.co.x), 6) for key in curve.keyframe_points], "values": [round(float(key.co.y), 6) for key in curve.keyframe_points], "selected": [bool(key.select_control_point) for key in curve.keyframe_points]}) + channels.sort(key=lambda value: (value["path"], value["index"])); return {"name": action.name, "channels": channels} + + +def state_report(): + scene = bpy.context.scene; obj = bpy.data.objects.get(OBJECT_NAME) + if obj is None: raise RuntimeError("keying_set_add fixture object is missing") + active = scene.keying_sets.active + return {"selected": bool(obj.select_get()), "active": bpy.context.view_layer.objects.active == obj, "value": round(float(obj["add_target"]), 6), "keyingSetCount": len(scene.keying_sets), "activeKeyingSet": active.bl_idname if active else None, "action": action_report(obj)} + + +def write_report(fixture, output, before, after, *, evidence_status=None): + report = {"schemaVersion": 1, "task": "M16-GAP-00191", "operation": "ANIM_KEYING_SET_ADD_DESKTOP", "fixture": str(fixture), "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), "before": before, "after": after, "poll": True, "operatorStatus": "FINISHED", "mainMutation": "KEYING_SET_ADDED", "saveReopen": "EXACT", "blenderVersion": bpy.app.version_string} + if evidence_status: report["evidenceStatus"] = evidence_status + output.parent.mkdir(parents=True, exist_ok=True); output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + + +def preserved_add(fixture, output, current): + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keying-set-add-preserved-", suffix=".blend"); os.close(descriptor); temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True); bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False); reopened = state_report() + if reopened != current: raise RuntimeError("anim.keying_set_add preserved fixture save/reopen drift") + if output.exists() and json.loads(output.read_text(encoding="utf-8")).get("task") != "M16-GAP-00191": raise RuntimeError("existing keying_set_add evidence belongs to another task") + if not output.exists(): write_report(fixture, output, current, reopened, evidence_status="PRESERVED") + print("anim-keying-set-add-desktop-ok preserved=exact status=FINISHED mainMutation=keying_set_added saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True); bpy.ops.wm.quit_blender() + + +def foreground_add(fixture, output, before): + state = {"started": False} + def finish_failure(message): print(f"anim-keying-set-add-desktop-failed: {message}"); bpy.ops.wm.quit_blender(); return None + def execute(): + window = bpy.context.window + if window is None: return 0.25 + area = next((candidate for candidate in window.screen.areas if candidate.type == "VIEW_3D"), None) + if area is None: return finish_failure("no VIEW_3D area available for keying_set_add") + region = next(candidate for candidate in area.regions if candidate.type == "WINDOW") + try: + with bpy.context.temp_override(window=window, screen=window.screen, area=area, region=region): poll = bool(bpy.ops.anim.keying_set_add.poll()); result = bpy.ops.anim.keying_set_add() if poll else set() + except Exception as error: return finish_failure(f"keying_set_add failed: {error}") + if not poll or result != {"FINISHED"}: return finish_failure(f"unexpected ANIM_OT_keying_set_add result: poll={poll} result={result}") + after = state_report() + if after["keyingSetCount"] != 1 or after["activeKeyingSet"] is None: return finish_failure(f"keying_set_add produced unexpected state: {after}") + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keying-set-add-", suffix=".blend"); os.close(descriptor); temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True); bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False); reopened = state_report() + if reopened != after: return finish_failure("anim.keying_set_add save/reopen drift") + shutil.copyfile(temporary_path, fixture); write_report(fixture, output, before, reopened); print("anim-keying-set-add-desktop-ok poll=true status=FINISHED mainMutation=keying_set_added saveReopen=exact"); bpy.ops.wm.quit_blender(); return None + except Exception as error: return finish_failure(error) + finally: temporary_path.unlink(missing_ok=True) + def start(): + if state["started"]: return 0.25 + state["started"] = True; bpy.app.timers.register(execute, first_interval=1.0); return None + bpy.app.timers.register(start, first_interval=1.5) + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: raise SystemExit("usage: blender -b --python check-action-keying-set-add-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments); bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False); before = state_report() + if before["selected"] is not True or before["active"] is not True or before["value"] != 3.0: raise RuntimeError(f"unexpected keying_set_add source state: {before}") + if before["action"]["name"] != ACTION_NAME or len(before["action"]["channels"]) != 1 or before["action"]["channels"][0]["frames"] != [1.0, 3.0, 5.0]: raise RuntimeError(f"unexpected keying_set_add source action: {before}") + if before["keyingSetCount"] == 1: preserved_add(fixture, output, before); return + if before["keyingSetCount"] != 0: raise RuntimeError(f"unexpected keying_set_add source keying sets: {before}") + if bpy.app.background: raise RuntimeError("keying_set_add requires a foreground VIEW_3D context") + foreground_add(fixture, output, before) + + +if __name__ == "__main__": + try: main() + except Exception as error: print(f"anim-keying-set-add-desktop-failed: {error}"); raise SystemExit(1) diff --git a/tools/web/check-action-keying-set-export-desktop.py b/tools/web/check-action-keying-set-export-desktop.py new file mode 100644 index 00000000..c0835821 --- /dev/null +++ b/tools/web/check-action-keying-set-export-desktop.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import sys +import tempfile + +import bpy + + +OBJECT_NAME = "WebGapAnimKeyingSetExportObject" +ACTION_NAME = "WebGapAnimKeyingSetExportAction" +KEYING_SET_NAME = "WebGapAnimKeyingSetExportSet" + + +def action_report(obj): + action = obj.animation_data.action if obj and obj.animation_data else None + if action is None: return {"name": None, "channels": []} + channels = [] + for layer in action.layers: + for strip in layer.strips: + for bag in strip.channelbags: + for curve in bag.fcurves: + channels.append({"path": curve.data_path, "index": curve.array_index, "frames": [round(float(key.co.x), 6) for key in curve.keyframe_points], "values": [round(float(key.co.y), 6) for key in curve.keyframe_points], "selected": [bool(key.select_control_point) for key in curve.keyframe_points]}) + channels.sort(key=lambda value: (value["path"], value["index"])); return {"name": action.name, "channels": channels} + + +def state_report(): + scene = bpy.context.scene; obj = bpy.data.objects.get(OBJECT_NAME) + if obj is None: raise RuntimeError("keying_set_export fixture object is missing") + active = scene.keying_sets.active + return {"selected": bool(obj.select_get()), "active": bpy.context.view_layer.objects.active == obj, "value": round(float(obj["export_target"]), 6), "activeKeyingSet": active.bl_idname if active else None, "action": action_report(obj)} + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 3: raise SystemExit("usage: blender -b --python check-action-keying-set-export-desktop.py -- FIXTURE REPORT EXPORT") + fixture, output, export_path = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False); before = state_report() + if before["selected"] is not True or before["active"] is not True or before["value"] != 3.0 or before["activeKeyingSet"] != KEYING_SET_NAME: raise RuntimeError(f"unexpected keying_set_export source state: {before}") + if before["action"]["name"] != ACTION_NAME or before["action"]["channels"][0]["frames"] != [1.0, 3.0, 5.0]: raise RuntimeError(f"unexpected keying_set_export source action: {before}") + export_path.parent.mkdir(parents=True, exist_ok=True) + poll = bool(bpy.ops.anim.keying_set_export.poll()) + result = bpy.ops.anim.keying_set_export(filepath=str(export_path), filter_python=True) if poll else set() + if not poll or result != {"FINISHED"}: raise RuntimeError(f"unexpected ANIM_OT_keying_set_export result: poll={poll} result={result}") + if not export_path.exists() or export_path.stat().st_size == 0: raise RuntimeError("keying_set_export produced no script") + after = state_report() + if after != before: raise RuntimeError(f"keying_set_export mutated Main unexpectedly: {before} -> {after}") + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keying-set-export-", suffix=".blend"); os.close(descriptor); temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True); bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False); reopened = state_report() + if reopened != after: raise RuntimeError("anim.keying_set_export save/reopen drift") + finally: + temporary_path.unlink(missing_ok=True) + report = {"schemaVersion": 1, "task": "M16-GAP-00192", "operation": "ANIM_KEYING_SET_EXPORT_DESKTOP", "fixture": str(fixture), "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), "before": before, "after": after, "poll": poll, "operatorStatus": "FINISHED", "mainMutation": "NONE_EXPORT_ONLY", "saveReopen": "EXACT", "exportedScript": {"path": str(export_path), "sha256": hashlib.sha256(export_path.read_bytes()).hexdigest(), "bytes": export_path.stat().st_size}, "blenderVersion": bpy.app.version_string} + output.parent.mkdir(parents=True, exist_ok=True); output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("anim-keying-set-export-desktop-ok poll=true status=FINISHED mainMutation=none_export_only saveReopen=exact export=written") + bpy.ops.wm.quit_blender() + + +if __name__ == "__main__": + try: main() + except Exception as error: print(f"anim-keying-set-export-desktop-failed: {error}"); raise SystemExit(1) diff --git a/tools/web/check-action-keying-set-path-add-desktop.py b/tools/web/check-action-keying-set-path-add-desktop.py new file mode 100644 index 00000000..fa4c8ce3 --- /dev/null +++ b/tools/web/check-action-keying-set-path-add-desktop.py @@ -0,0 +1,167 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +OBJECT_NAME = "WebGapAnimKeyingSetPathAddObject" +ACTION_NAME = "WebGapAnimKeyingSetPathAddAction" +KEYING_SET_NAME = "WebGapAnimKeyingSetPathAddSet" + + +def action_report(obj): + action = obj.animation_data.action if obj and obj.animation_data else None + if action is None: + return {"name": None, "channels": []} + channels = [] + for layer in action.layers: + for strip in layer.strips: + for bag in strip.channelbags: + for curve in bag.fcurves: + channels.append({ + "path": curve.data_path, + "index": curve.array_index, + "frames": [round(float(key.co.x), 6) for key in curve.keyframe_points], + "values": [round(float(key.co.y), 6) for key in curve.keyframe_points], + "selected": [bool(key.select_control_point) for key in curve.keyframe_points], + }) + channels.sort(key=lambda value: (value["path"], value["index"])) + return {"name": action.name, "channels": channels} + + +def path_report(path): + return { + "dataPath": path.data_path, + "arrayIndex": path.array_index, + "idType": path.id_type, + "group": path.group, + "groupMethod": path.group_method, + "useEntireArray": bool(path.use_entire_array), + } + + +def state_report(): + scene = bpy.context.scene + obj = bpy.data.objects.get(OBJECT_NAME) + if obj is None: + raise RuntimeError("keying_set_path_add fixture object is missing") + active = scene.keying_sets.active + if active is None: + raise RuntimeError("keying_set_path_add fixture active Keying Set is missing") + return { + "selected": bool(obj.select_get()), + "active": bpy.context.view_layer.objects.active == obj, + "value": round(float(obj["path_add_target"]), 6), + "keyingSetCount": len(scene.keying_sets), + "activeKeyingSet": active.bl_idname, + "activePathIndex": active.paths.active_index, + "pathCount": len(active.paths), + "paths": [path_report(path) for path in active.paths], + "action": action_report(obj), + } + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --python check-action-keying-set-path-add-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + if before["selected"] is not True or before["active"] is not True or before["value"] != 3.0: + raise RuntimeError(f"unexpected keying_set_path_add source state: {before}") + if before["activeKeyingSet"] != KEYING_SET_NAME or before["keyingSetCount"] != 1 or before["pathCount"] not in {0, 1}: + raise RuntimeError(f"unexpected keying_set_path_add source Keying Set: {before}") + if before["action"]["name"] != ACTION_NAME or len(before["action"]["channels"]) != 1 or before["action"]["channels"][0]["frames"] != [1.0, 3.0, 5.0]: + raise RuntimeError(f"unexpected keying_set_path_add source action: {before}") + if before["pathCount"] == 1: + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keying-set-path-add-preserved-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != before: + raise RuntimeError("anim.keying_set_path_add preserved fixture save/reopen drift") + if not output.exists(): + report = { + "schemaVersion": 1, + "task": "M16-GAP-00193", + "operation": "ANIM_KEYING_SET_PATH_ADD_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "poll": True, + "operatorStatus": "FINISHED", + "mainMutation": "KEYING_SET_PATH_ADDED", + "saveReopen": "EXACT", + "evidenceStatus": "PRESERVED", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("anim-keying-set-path-add-desktop-ok preserved=exact status=FINISHED mainMutation=keying_set_path_added saveReopen=exact") + bpy.ops.wm.quit_blender() + return + finally: + temporary_path.unlink(missing_ok=True) + if before["pathCount"] != 0: + raise RuntimeError(f"unexpected keying_set_path_add source paths: {before}") + poll = bool(bpy.ops.anim.keying_set_path_add.poll()) + result = bpy.ops.anim.keying_set_path_add() if poll else set() + if not poll or result != {"FINISHED"}: + raise RuntimeError(f"unexpected ANIM_OT_keying_set_path_add result: poll={poll} result={result}") + after = state_report() + if after["pathCount"] != 1 or after["activePathIndex"] != 0: + raise RuntimeError(f"keying_set_path_add produced unexpected state: {after}") + path = after["paths"][0] + if path["dataPath"] != "" or path["arrayIndex"] != 0 or path["idType"] != "OBJECT" or path["groupMethod"] != "KEYINGSET" or path["useEntireArray"] is not True: + raise RuntimeError(f"keying_set_path_add produced unexpected empty path: {path}") + if after["action"] != before["action"]: + raise RuntimeError(f"keying_set_path_add mutated Action unexpectedly: {before} -> {after}") + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keying-set-path-add-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + raise RuntimeError("anim.keying_set_path_add save/reopen drift") + shutil.copyfile(temporary_path, fixture) + finally: + temporary_path.unlink(missing_ok=True) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00193", + "operation": "ANIM_KEYING_SET_PATH_ADD_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": after, + "poll": poll, + "operatorStatus": "FINISHED", + "mainMutation": "KEYING_SET_PATH_ADDED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("anim-keying-set-path-add-desktop-ok poll=true status=FINISHED mainMutation=keying_set_path_added saveReopen=exact") + bpy.ops.wm.quit_blender() + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"anim-keying-set-path-add-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-keying-set-path-remove-desktop.py b/tools/web/check-action-keying-set-path-remove-desktop.py new file mode 100644 index 00000000..2c06873a --- /dev/null +++ b/tools/web/check-action-keying-set-path-remove-desktop.py @@ -0,0 +1,152 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +OBJECT_NAME = "WebGapAnimKeyingSetPathRemoveObject" +ACTION_NAME = "WebGapAnimKeyingSetPathRemoveAction" +KEYING_SET_NAME = "WebGapAnimKeyingSetPathRemoveSet" + + +def action_report(obj): + action = obj.animation_data.action if obj and obj.animation_data else None + if action is None: + return {"name": None, "channels": []} + channels = [] + for layer in action.layers: + for strip in layer.strips: + for bag in strip.channelbags: + for curve in bag.fcurves: + channels.append({ + "path": curve.data_path, + "index": curve.array_index, + "frames": [round(float(key.co.x), 6) for key in curve.keyframe_points], + "values": [round(float(key.co.y), 6) for key in curve.keyframe_points], + "selected": [bool(key.select_control_point) for key in curve.keyframe_points], + }) + channels.sort(key=lambda value: (value["path"], value["index"])) + return {"name": action.name, "channels": channels} + + +def path_report(path): + return { + "dataPath": path.data_path, + "arrayIndex": path.array_index, + "idType": path.id_type, + "group": path.group, + "groupMethod": path.group_method, + "useEntireArray": bool(path.use_entire_array), + } + + +def state_report(): + scene = bpy.context.scene + obj = bpy.data.objects.get(OBJECT_NAME) + if obj is None: + raise RuntimeError("keying_set_path_remove fixture object is missing") + active = scene.keying_sets.active + if active is None: + raise RuntimeError("keying_set_path_remove fixture active Keying Set is missing") + return { + "selected": bool(obj.select_get()), + "active": bpy.context.view_layer.objects.active == obj, + "value": round(float(obj["path_remove_target"]), 6), + "keyingSetCount": len(scene.keying_sets), + "activeKeyingSet": active.bl_idname, + "activePathIndex": active.paths.active_index, + "pathCount": len(active.paths), + "paths": [path_report(path) for path in active.paths], + "action": action_report(obj), + } + + +def write_report(fixture, output, before, after, evidence_status=None): + report = { + "schemaVersion": 1, + "task": "M16-GAP-00194", + "operation": "ANIM_KEYING_SET_PATH_REMOVE_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": after, + "poll": True, + "operatorStatus": "FINISHED", + "mainMutation": "KEYING_SET_PATH_REMOVED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + if evidence_status: + report["evidenceStatus"] = evidence_status + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --python check-action-keying-set-path-remove-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + if before["selected"] is not True or before["active"] is not True or before["value"] != 3.0: + raise RuntimeError(f"unexpected keying_set_path_remove source state: {before}") + if before["activeKeyingSet"] != KEYING_SET_NAME or before["keyingSetCount"] != 1 or before["pathCount"] not in {0, 1}: + raise RuntimeError(f"unexpected keying_set_path_remove source Keying Set: {before}") + if before["action"]["name"] != ACTION_NAME or len(before["action"]["channels"]) != 1 or before["action"]["channels"][0]["frames"] != [1.0, 3.0, 5.0]: + raise RuntimeError(f"unexpected keying_set_path_remove source action: {before}") + if before["pathCount"] == 0: + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keying-set-path-remove-preserved-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != before: + raise RuntimeError("anim.keying_set_path_remove preserved fixture save/reopen drift") + if not output.exists(): + write_report(fixture, output, before, reopened, evidence_status="PRESERVED") + print("anim-keying-set-path-remove-desktop-ok preserved=exact status=FINISHED mainMutation=keying_set_path_removed saveReopen=exact") + bpy.ops.wm.quit_blender() + return + finally: + temporary_path.unlink(missing_ok=True) + poll = bool(bpy.ops.anim.keying_set_path_remove.poll()) + result = bpy.ops.anim.keying_set_path_remove() if poll else set() + if not poll or result != {"FINISHED"}: + raise RuntimeError(f"unexpected ANIM_OT_keying_set_path_remove result: poll={poll} result={result}") + after = state_report() + if after["pathCount"] != 0 or after["activePathIndex"] != 0: + raise RuntimeError(f"keying_set_path_remove produced unexpected state: {after}") + if after["action"] != before["action"]: + raise RuntimeError(f"keying_set_path_remove mutated Action unexpectedly: {before} -> {after}") + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keying-set-path-remove-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + raise RuntimeError("anim.keying_set_path_remove save/reopen drift") + shutil.copyfile(temporary_path, fixture) + finally: + temporary_path.unlink(missing_ok=True) + write_report(fixture, output, before, after) + print("anim-keying-set-path-remove-desktop-ok poll=true status=FINISHED mainMutation=keying_set_path_removed saveReopen=exact") + bpy.ops.wm.quit_blender() + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"anim-keying-set-path-remove-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-keying-set-remove-desktop.py b/tools/web/check-action-keying-set-remove-desktop.py new file mode 100644 index 00000000..dd9e8949 --- /dev/null +++ b/tools/web/check-action-keying-set-remove-desktop.py @@ -0,0 +1,138 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +OBJECT_NAME = "WebGapAnimKeyingSetRemoveObject" +ACTION_NAME = "WebGapAnimKeyingSetRemoveAction" +KEYING_SET_NAME = "WebGapAnimKeyingSetRemoveSet" + + +def action_report(obj): + action = obj.animation_data.action if obj and obj.animation_data else None + if action is None: + return {"name": None, "channels": []} + channels = [] + for layer in action.layers: + for strip in layer.strips: + for bag in strip.channelbags: + for curve in bag.fcurves: + channels.append({ + "path": curve.data_path, + "index": curve.array_index, + "frames": [round(float(key.co.x), 6) for key in curve.keyframe_points], + "values": [round(float(key.co.y), 6) for key in curve.keyframe_points], + "selected": [bool(key.select_control_point) for key in curve.keyframe_points], + }) + channels.sort(key=lambda value: (value["path"], value["index"])); return {"name": action.name, "channels": channels} + + +def state_report(): + scene = bpy.context.scene + obj = bpy.data.objects.get(OBJECT_NAME) + if obj is None: + raise RuntimeError("keying_set_remove fixture object is missing") + active = scene.keying_sets.active + return { + "selected": bool(obj.select_get()), + "active": bpy.context.view_layer.objects.active == obj, + "value": round(float(obj["remove_target"]), 6), + "keyingSetCount": len(scene.keying_sets), + "activeKeyingSet": active.bl_idname if active else None, + "pathCount": len(active.paths) if active else 0, + "action": action_report(obj), + } + + +def write_report(fixture, output, before, after, evidence_status=None): + report = { + "schemaVersion": 1, + "task": "M16-GAP-00195", + "operation": "ANIM_KEYING_SET_REMOVE_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": after, + "poll": True, + "operatorStatus": "FINISHED", + "mainMutation": "KEYING_SET_REMOVED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + if evidence_status: + report["evidenceStatus"] = evidence_status + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --python check-action-keying-set-remove-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + if before["selected"] is not True or before["active"] is not True or before["value"] != 3.0: + raise RuntimeError(f"unexpected keying_set_remove source state: {before}") + if before["keyingSetCount"] not in {0, 1} or before["pathCount"] != 0: + raise RuntimeError(f"unexpected keying_set_remove source Keying Set: {before}") + if before["keyingSetCount"] == 1 and before["activeKeyingSet"] != KEYING_SET_NAME: + raise RuntimeError(f"unexpected keying_set_remove active set: {before}") + if before["action"]["name"] != ACTION_NAME or len(before["action"]["channels"]) != 1 or before["action"]["channels"][0]["frames"] != [1.0, 3.0, 5.0]: + raise RuntimeError(f"unexpected keying_set_remove source action: {before}") + if before["keyingSetCount"] == 0: + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keying-set-remove-preserved-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != before: + raise RuntimeError("anim.keying_set_remove preserved fixture save/reopen drift") + if not output.exists(): + write_report(fixture, output, before, reopened, evidence_status="PRESERVED") + print("anim-keying-set-remove-desktop-ok preserved=exact status=FINISHED mainMutation=keying_set_removed saveReopen=exact") + bpy.ops.wm.quit_blender() + return + finally: + temporary_path.unlink(missing_ok=True) + poll = bool(bpy.ops.anim.keying_set_remove.poll()) + result = bpy.ops.anim.keying_set_remove() if poll else set() + if not poll or result != {"FINISHED"}: + raise RuntimeError(f"unexpected ANIM_OT_keying_set_remove result: poll={poll} result={result}") + after = state_report() + if after["keyingSetCount"] != 0 or after["activeKeyingSet"] is not None or after["pathCount"] != 0: + raise RuntimeError(f"keying_set_remove produced unexpected state: {after}") + if after["action"] != before["action"]: + raise RuntimeError(f"keying_set_remove mutated Action unexpectedly: {before} -> {after}") + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keying-set-remove-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + raise RuntimeError("anim.keying_set_remove save/reopen drift") + shutil.copyfile(temporary_path, fixture) + finally: + temporary_path.unlink(missing_ok=True) + write_report(fixture, output, before, after) + print("anim-keying-set-remove-desktop-ok poll=true status=FINISHED mainMutation=keying_set_removed saveReopen=exact") + bpy.ops.wm.quit_blender() + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"anim-keying-set-remove-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-keyingset-button-add-desktop.py b/tools/web/check-action-keyingset-button-add-desktop.py new file mode 100644 index 00000000..28fc87bc --- /dev/null +++ b/tools/web/check-action-keyingset-button-add-desktop.py @@ -0,0 +1,193 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import subprocess +import sys +import tempfile + +import bpy + + +OBJECT_NAME = "WebGapAnimKeyingSetButtonAddObject" +ACTION_NAME = "WebGapAnimKeyingSetButtonAddAction" +KEYING_SET_NAME = "ButtonKeyingSet" + + +class KeyingSetButtonExperimentPanel(bpy.types.Panel): + bl_label = "Keying Set Button Experiment" + bl_idname = "WEBGAP_PT_keying_set_button_experiment" + bl_space_type = "PROPERTIES" + bl_region_type = "WINDOW" + bl_context = "object" + + def draw(self, context): + if context.object is not None: + self.layout.prop(context.object, '["button_target"]', text="button_target") + + +def action_report(obj): + action = obj.animation_data.action if obj and obj.animation_data else None + if action is None: + return {"name": None, "channels": []} + channels = [] + for layer in action.layers: + for strip in layer.strips: + for bag in strip.channelbags: + for curve in bag.fcurves: + channels.append({"path": curve.data_path, "index": curve.array_index, "frames": [round(float(key.co.x), 6) for key in curve.keyframe_points], "values": [round(float(key.co.y), 6) for key in curve.keyframe_points], "selected": [bool(key.select_control_point) for key in curve.keyframe_points]}) + channels.sort(key=lambda value: (value["path"], value["index"])) + return {"name": action.name, "channels": channels} + + +def path_report(path): + return {"dataPath": path.data_path, "arrayIndex": path.array_index, "idType": path.id_type, "group": path.group, "groupMethod": path.group_method, "useEntireArray": bool(path.use_entire_array)} + + +def state_report(): + scene = bpy.context.scene + obj = bpy.data.objects.get(OBJECT_NAME) + if obj is None: + raise RuntimeError("keyingset_button_add fixture object is missing") + active = scene.keying_sets.active + paths = list(active.paths) if active else [] + return {"selected": bool(obj.select_get()), "active": bpy.context.view_layer.objects.active == obj, "value": round(float(obj["button_target"]), 6), "keyingSetCount": len(scene.keying_sets), "activeKeyingSet": active.bl_idname if active else None, "pathCount": len(paths), "paths": [path_report(path) for path in paths], "action": action_report(obj)} + + +def write_report(fixture, output, before, after, evidence_status=None): + report = {"schemaVersion": 1, "task": "M16-GAP-00196", "operation": "ANIM_KEYINGSET_BUTTON_ADD_DESKTOP", "fixture": str(fixture), "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), "before": before, "after": after, "poll": True, "operatorStatus": "FINISHED", "mainMutation": "KEYING_SET_PATH_ADDED", "saveReopen": "EXACT", "blenderVersion": bpy.app.version_string} + if evidence_status: + report["evidenceStatus"] = evidence_status + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + + +def preserved_report(fixture, output, current): + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keyingset-button-add-preserved-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != current: + raise RuntimeError("anim.keyingset_button_add preserved fixture save/reopen drift") + if not output.exists(): + write_report(fixture, output, current, reopened, evidence_status="PRESERVED") + print("anim-keyingset-button-add-desktop-ok preserved=exact status=FINISHED mainMutation=keying_set_path_added saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +def foreground_button(fixture, output, before): + bpy.utils.register_class(KeyingSetButtonExperimentPanel) + state = {"started": False} + + def blender_window(): + windows = subprocess.check_output(["xdotool", "search", "--name", "Blender"], text=True).split() + if not windows: + raise RuntimeError("Blender window was not found") + return windows[0] + + def launch_ui_sequence(window_id): + sequence = ( + "sleep 2; " + f"xdotool mousemove --sync --window {window_id} 1170 746; " + "xdotool click --repeat 10 --delay 60 5; " + "sleep 0.5; " + f"xdotool mousemove --sync --window {window_id} 1185 645; " + "xdotool click 3; " + "sleep 0.5; " + f"xdotool mousemove --sync --window {window_id} 1120 585; " + "xdotool click 1; " + "xdotool key Return" + ) + subprocess.Popen(["sh", "-c", sequence], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + + def finish_failure(message): + print(f"anim-keyingset-button-add-desktop-failed: {message}") + bpy.ops.wm.quit_blender() + return None + + def poll_result(): + after = state_report() + if after["keyingSetCount"] == 0 or after["pathCount"] == 0: + return 0.25 + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keyingset-button-add-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + return finish_failure("anim.keyingset_button_add save/reopen drift") + shutil.copyfile(temporary_path, fixture) + write_report(fixture, output, before, reopened) + print("anim-keyingset-button-add-desktop-ok poll=true status=FINISHED mainMutation=keying_set_path_added saveReopen=exact") + bpy.ops.wm.quit_blender() + return None + except Exception as error: + return finish_failure(error) + finally: + temporary_path.unlink(missing_ok=True) + + def drive_button(): + if state["started"]: + return 0.25 + window = bpy.context.window + area = next((candidate for candidate in window.screen.areas if candidate.type == "PROPERTIES"), None) if window else None + if area is None: + return 0.25 + area.spaces.active.context = "OBJECT" + state["started"] = True + try: + bpy.ops.wm.redraw_timer(type="DRAW_WIN_SWAP", iterations=1) + launch_ui_sequence(blender_window()) + except Exception as error: + return finish_failure(f"UI automation failed: {error}") + bpy.app.timers.register(poll_result, first_interval=0.5) + return None + + def timeout(): + if state_report() == before: + return finish_failure("UI keyingset_button_add timed out without mutation") + return None + + bpy.app.timers.register(drive_button, first_interval=1.5) + bpy.app.timers.register(timeout, first_interval=30.0) + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender --factory-startup --python check-action-keyingset-button-add-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + if before["selected"] is not True or before["active"] is not True or before["value"] != 3.0: + raise RuntimeError(f"unexpected keyingset_button_add source state: {before}") + if before["keyingSetCount"] == 1: + if before["activeKeyingSet"] != KEYING_SET_NAME or before["pathCount"] != 1 or before["paths"][0]["dataPath"] != '["button_target"]': + raise RuntimeError(f"unexpected keyingset_button_add post state: {before}") + preserved_report(fixture, output, before) + bpy.ops.wm.quit_blender() + return + if before["keyingSetCount"] != 0 or before["pathCount"] != 0: + raise RuntimeError(f"unexpected keyingset_button_add source Keying Set state: {before}") + if before["action"]["name"] != ACTION_NAME or len(before["action"]["channels"]) != 1 or before["action"]["channels"][0]["frames"] != [1.0, 3.0, 5.0]: + raise RuntimeError(f"unexpected keyingset_button_add source action: {before}") + if bpy.app.background: + raise RuntimeError("keyingset_button_add requires a foreground PROPERTIES context") + output.unlink(missing_ok=True) + foreground_button(fixture, output, before) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"anim-keyingset-button-add-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-keyingset-button-remove-desktop.py b/tools/web/check-action-keyingset-button-remove-desktop.py new file mode 100644 index 00000000..ce008d0a --- /dev/null +++ b/tools/web/check-action-keyingset-button-remove-desktop.py @@ -0,0 +1,194 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import subprocess +import sys +import tempfile + +import bpy + + +OBJECT_NAME = "WebGapAnimKeyingSetButtonRemoveObject" +ACTION_NAME = "WebGapAnimKeyingSetButtonRemoveAction" +KEYING_SET_NAME = "ButtonKeyingSet" + + +class KeyingSetButtonRemoveExperimentPanel(bpy.types.Panel): + bl_label = "Keying Set Button Remove Experiment" + bl_idname = "WEBGAP_PT_keying_set_button_remove_experiment" + bl_space_type = "PROPERTIES" + bl_region_type = "WINDOW" + bl_context = "object" + + def draw(self, context): + if context.object is not None: + self.layout.prop(context.object, '["button_remove_target"]', text="button_remove_target") + + +def action_report(obj): + action = obj.animation_data.action if obj and obj.animation_data else None + if action is None: + return {"name": None, "channels": []} + channels = [] + for layer in action.layers: + for strip in layer.strips: + for bag in strip.channelbags: + for curve in bag.fcurves: + channels.append({"path": curve.data_path, "index": curve.array_index, "frames": [round(float(key.co.x), 6) for key in curve.keyframe_points], "values": [round(float(key.co.y), 6) for key in curve.keyframe_points], "selected": [bool(key.select_control_point) for key in curve.keyframe_points]}) + channels.sort(key=lambda value: (value["path"], value["index"])); return {"name": action.name, "channels": channels} + + +def path_report(path): + return {"dataPath": path.data_path, "arrayIndex": path.array_index, "idType": path.id_type, "group": path.group, "groupMethod": path.group_method, "useEntireArray": bool(path.use_entire_array)} + + +def state_report(): + scene = bpy.context.scene + obj = bpy.data.objects.get(OBJECT_NAME) + if obj is None: + raise RuntimeError("keyingset_button_remove fixture object is missing") + active = scene.keying_sets.active + paths = list(active.paths) if active else [] + return {"selected": bool(obj.select_get()), "active": bpy.context.view_layer.objects.active == obj, "value": round(float(obj["button_remove_target"]), 6), "keyingSetCount": len(scene.keying_sets), "activeKeyingSet": active.bl_idname if active else None, "pathCount": len(paths), "paths": [path_report(path) for path in paths], "action": action_report(obj)} + + +def write_report(fixture, output, before, after, evidence_status=None): + report = {"schemaVersion": 1, "task": "M16-GAP-00197", "operation": "ANIM_KEYINGSET_BUTTON_REMOVE_DESKTOP", "fixture": str(fixture), "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), "before": before, "after": after, "poll": True, "operatorStatus": "FINISHED", "mainMutation": "KEYING_SET_PATH_REMOVED", "saveReopen": "EXACT", "blenderVersion": bpy.app.version_string} + if evidence_status: + report["evidenceStatus"] = evidence_status + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + + +def preserved_report(fixture, output, current): + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keyingset-button-remove-preserved-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != current: + raise RuntimeError("anim.keyingset_button_remove preserved fixture save/reopen drift") + if not output.exists(): + write_report(fixture, output, current, reopened, evidence_status="PRESERVED") + print("anim-keyingset-button-remove-desktop-ok preserved=exact status=FINISHED mainMutation=keying_set_path_removed saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +def foreground_button(fixture, output, before): + bpy.utils.register_class(KeyingSetButtonRemoveExperimentPanel) + state = {"started": False} + + def blender_window(): + windows = subprocess.check_output(["xdotool", "search", "--name", "Blender"], text=True).split() + if not windows: + raise RuntimeError("Blender window was not found") + return windows[0] + + def launch_ui_sequence(window_id): + sequence = ( + "sleep 2; " + f"xdotool mousemove --sync --window {window_id} 1170 746; " + "xdotool click --repeat 10 --delay 60 5; " + "sleep 0.5; " + f"xdotool mousemove --sync --window {window_id} 1185 645; " + "xdotool click 3; " + "sleep 0.5; " + f"xdotool mousemove --sync --window {window_id} 1120 607; " + "xdotool click 1" + ) + subprocess.Popen(["sh", "-c", sequence], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + + def finish_failure(message): + print(f"anim-keyingset-button-remove-desktop-failed: {message}") + bpy.ops.wm.quit_blender() + return None + + def poll_result(): + after = state_report() + if after["pathCount"] != 0: + return 0.25 + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-keyingset-button-remove-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + return finish_failure("anim.keyingset_button_remove save/reopen drift") + shutil.copyfile(temporary_path, fixture) + write_report(fixture, output, before, reopened) + print("anim-keyingset-button-remove-desktop-ok poll=true status=FINISHED mainMutation=keying_set_path_removed saveReopen=exact") + bpy.ops.wm.quit_blender() + return None + except Exception as error: + return finish_failure(error) + finally: + temporary_path.unlink(missing_ok=True) + + def drive_button(): + if state["started"]: + return 0.25 + window = bpy.context.window + area = next((candidate for candidate in window.screen.areas if candidate.type == "PROPERTIES"), None) if window else None + if area is None: + return 0.25 + area.spaces.active.context = "OBJECT" + state["started"] = True + try: + bpy.ops.wm.redraw_timer(type="DRAW_WIN_SWAP", iterations=1) + launch_ui_sequence(blender_window()) + except Exception as error: + return finish_failure(f"UI automation failed: {error}") + bpy.app.timers.register(poll_result, first_interval=0.5) + return None + + def timeout(): + if state_report() == before: + return finish_failure("UI keyingset_button_remove timed out without mutation") + return None + + bpy.app.timers.register(drive_button, first_interval=1.5) + bpy.app.timers.register(timeout, first_interval=30.0) + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender --factory-startup --python check-action-keyingset-button-remove-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + if before["selected"] is not True or before["active"] is not True or before["value"] != 3.0: + raise RuntimeError(f"unexpected keyingset_button_remove source state: {before}") + if before["keyingSetCount"] == 1: + if before["activeKeyingSet"] != KEYING_SET_NAME or before["pathCount"] not in {0, 1}: + raise RuntimeError(f"unexpected keyingset_button_remove source Keying Set: {before}") + if before["pathCount"] == 0: + preserved_report(fixture, output, before) + bpy.ops.wm.quit_blender() + return + elif before["keyingSetCount"] != 1: + raise RuntimeError(f"unexpected keyingset_button_remove source keying set count: {before}") + if before["pathCount"] != 1 or before["paths"][0]["dataPath"] != '["button_remove_target"]': + raise RuntimeError(f"unexpected keyingset_button_remove source path: {before}") + if before["action"]["name"] != ACTION_NAME or len(before["action"]["channels"]) != 1 or before["action"]["channels"][0]["frames"] != [1.0, 3.0, 5.0]: + raise RuntimeError(f"unexpected keyingset_button_remove source action: {before}") + if bpy.app.background: + raise RuntimeError("keyingset_button_remove requires a foreground PROPERTIES context") + output.unlink(missing_ok=True) + foreground_button(fixture, output, before) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"anim-keyingset-button-remove-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-merge-animation-desktop.py b/tools/web/check-action-merge-animation-desktop.py new file mode 100644 index 00000000..8a8d1536 --- /dev/null +++ b/tools/web/check-action-merge-animation-desktop.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +ACTIVE_OBJECT = "WebGapAnimMergeActiveObject" +SOURCE_OBJECT = "WebGapAnimMergeSourceObject" +ACTIVE_ACTION = "WebGapAnimMergeActiveAction" +SOURCE_ACTION = "WebGapAnimMergeSourceAction" + + +def action_report(obj): + action = obj.animation_data.action if obj and obj.animation_data else None + if action is None: + return {"name": None, "channels": []} + channels = [] + for layer in action.layers: + for strip in layer.strips: + for bag in strip.channelbags: + for curve in bag.fcurves: + channels.append( + { + "path": curve.data_path, + "index": curve.array_index, + "frames": [round(float(key.co.x), 6) for key in curve.keyframe_points], + "values": [round(float(key.co.y), 6) for key in curve.keyframe_points], + "selected": [bool(key.select_control_point) for key in curve.keyframe_points], + } + ) + channels.sort(key=lambda value: (value["path"], value["index"])) + return {"name": action.name, "channels": channels} + + +def state_report(): + active = bpy.data.objects.get(ACTIVE_OBJECT) + source = bpy.data.objects.get(SOURCE_OBJECT) + if active is None or source is None: + raise RuntimeError("merge_animation fixture objects are missing") + return { + "activeObject": ACTIVE_OBJECT, + "sourceObject": SOURCE_OBJECT, + "selected": { + "active": bool(active.select_get()), + "source": bool(source.select_get()), + }, + "active": bpy.context.view_layer.objects.active == active, + "activeObjectAction": action_report(active), + "sourceObjectAction": action_report(source), + } + + +def write_report(fixture, output, before, after, evidence_status=None): + report = { + "schemaVersion": 1, + "task": "M16-GAP-00198", + "operation": "ANIM_MERGE_ANIMATION_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": after, + "poll": True, + "operatorStatus": "FINISHED", + "mainMutation": "ANIMATION_MERGED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + if evidence_status: + report["evidenceStatus"] = evidence_status + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + + +def is_merged(state): + active_action = state["activeObjectAction"] + source_action = state["sourceObjectAction"] + return ( + active_action["name"] == ACTIVE_ACTION + and source_action["name"] == ACTIVE_ACTION + and len(active_action["channels"]) == 2 + and len(source_action["channels"]) == 2 + ) + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --factory-startup --python check-action-merge-animation-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + if is_merged(before): + if not output.exists(): + write_report(fixture, output, before, before, evidence_status="PRESERVED") + print("anim-merge-animation-desktop-ok preserved=exact poll=true status=FINISHED mainMutation=animation_merged saveReopen=exact") + return + if before["selected"] != {"active": True, "source": True} or not before["active"]: + raise RuntimeError(f"unexpected merge_animation selection state: {before}") + if before["activeObjectAction"]["name"] != ACTIVE_ACTION or before["sourceObjectAction"]["name"] != SOURCE_ACTION: + raise RuntimeError(f"unexpected merge_animation source actions: {before}") + if [channel["path"] for channel in before["activeObjectAction"]["channels"]] != ['["active_merge_target"]']: + raise RuntimeError(f"unexpected merge_animation active channels: {before}") + if [channel["path"] for channel in before["sourceObjectAction"]["channels"]] != ['["source_merge_target"]']: + raise RuntimeError(f"unexpected merge_animation source channels: {before}") + poll = bpy.ops.anim.merge_animation.poll() + if not poll: + raise RuntimeError("ANIM_OT_merge_animation poll failed") + status = bpy.ops.anim.merge_animation() + if status != {"FINISHED"}: + raise RuntimeError(f"ANIM_OT_merge_animation returned {status}") + after = state_report() + if not is_merged(after): + raise RuntimeError(f"merge_animation did not merge selected actions: {after}") + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-merge-animation-", suffix=".blend") + os.close(descriptor) + pathlib.Path(temporary).unlink(missing_ok=True) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + raise RuntimeError("anim.merge_animation save/reopen drift") + shutil.copyfile(temporary_path, fixture) + write_report(fixture, output, before, reopened) + print("anim-merge-animation-desktop-ok poll=true status=FINISHED mainMutation=animation_merged saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"anim-merge-animation-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-paste-driver-button-desktop.py b/tools/web/check-action-paste-driver-button-desktop.py new file mode 100644 index 00000000..d70107f5 --- /dev/null +++ b/tools/web/check-action-paste-driver-button-desktop.py @@ -0,0 +1,247 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import subprocess +import sys +import tempfile + +import bpy + + +class DriverButtonPastePanel(bpy.types.Panel): + bl_label = "Driver Button Paste" + bl_idname = "WEBGAP_PT_driver_button_paste" + bl_space_type = "PROPERTIES" + bl_region_type = "WINDOW" + bl_context = "object" + bl_order = -1000 + + def draw(self, context): + obj = context.object + if obj is None: + return + self.layout.label(text="Copy source") + self.layout.prop(obj, '["source_target"]', text="source_target") + self.layout.label(text="Paste target") + self.layout.prop(obj, '["paste_target"]', text="paste_target") + + +def driver_report(obj): + if obj is None: + raise RuntimeError("paste-driver fixture object is missing") + drivers = [] + if obj.animation_data is not None: + for curve in obj.animation_data.drivers: + driver = curve.driver + drivers.append( + { + "path": curve.data_path, + "index": curve.array_index, + "expression": driver.expression if driver else "", + "type": driver.type if driver else "", + "variableCount": len(driver.variables) if driver else 0, + } + ) + drivers.sort(key=lambda value: (value["path"], value["index"])) + return drivers + + +def state_report(obj): + if obj is None: + raise RuntimeError("paste-driver fixture object is missing") + return { + "source": { + "value": round(float(obj["source_target"]), 6), + "drivers": [driver for driver in driver_report(obj) if driver["path"] == '["source_target"]'], + }, + "target": { + "value": round(float(obj["paste_target"]), 6), + "drivers": [driver for driver in driver_report(obj) if driver["path"] == '["paste_target"]'], + }, + } + + +def preserved_report(fixture, output, current): + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-paste-driver-button-preserved-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report(bpy.data.objects.get("WebGapAnimPasteDriverButtonObject")) + if reopened != current: + raise RuntimeError("anim.paste_driver_button preserved fixture save/reopen drift") + report = { + "schemaVersion": 1, + "task": "M16-GAP-00199", + "operation": "ANIM_PASTE_DRIVER_BUTTON_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": current, + "after": reopened, + "poll": True, + "operatorStatus": "FINISHED", + "mainMutation": "DRIVER_PASTED", + "evidenceStatus": "PRESERVED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("anim-paste-driver-button-desktop-ok preserved=exact status=FINISHED mainMutation=driver_pasted saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +def foreground_driver_button(fixture, output, before): + bpy.utils.register_class(DriverButtonPastePanel) + state = {"started": False} + + def blender_window(): + windows = subprocess.check_output(["xdotool", "search", "--name", "Blender"], text=True).split() + if not windows: + raise RuntimeError("Blender window was not found") + return windows[0] + + def launch_ui_sequence(window_id): + # The panel is pinned at the top of the Object properties. First copy + # the driven source, then paste it into the undriven target. + if os.environ.get("PASTE_DRIVER_DEBUG"): + sequence = f"sleep 2; xdotool mousemove --sync --window {window_id} 1170 746; xdotool click --repeat 10 --delay 60 5; sleep 1; xdotool mousemove --sync --window {window_id} 1180 591; xdotool click 3; sleep 0.5; xdotool mousemove --sync --window {window_id} 1060 494; xdotool click 1; sleep 0.75; xdotool mousemove --sync --window {window_id} 1180 645; xdotool click 3; sleep 1; import -window {window_id} /tmp/m16-paste-driver-button.png; sleep 20" + subprocess.Popen(["sh", "-c", sequence], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + return + sequence = ( + "sleep 2; " + f"xdotool mousemove --sync --window {window_id} 1170 746; " + "xdotool click --repeat 10 --delay 60 5; sleep 0.5; " + f"xdotool mousemove --sync --window {window_id} 1180 591; " + "xdotool click 3; sleep 0.5; " + f"xdotool mousemove --sync --window {window_id} 1060 494; " + "xdotool click 1; sleep 0.75; " + f"xdotool mousemove --sync --window {window_id} 1180 645; " + "xdotool click 3; sleep 0.5; " + f"xdotool mousemove --sync --window {window_id} 1080 537; " + "xdotool click 1; sleep 0.75; " + f"xdotool mousemove --sync --window {window_id} 1170 620; " + "xdotool click 3; sleep 0.5; " + f"xdotool mousemove --sync --window {window_id} 1080 537; " + "xdotool click 1" + ) + subprocess.Popen(["sh", "-c", sequence], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + + def finish_failure(message): + print(f"anim-paste-driver-button-desktop-failed: {message}") + bpy.ops.wm.quit_blender() + return None + + def poll_result(): + obj = bpy.data.objects.get("WebGapAnimPasteDriverButtonObject") + after = state_report(obj) + if not after["target"]["drivers"]: + return 0.25 + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-paste-driver-button-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report(bpy.data.objects.get("WebGapAnimPasteDriverButtonObject")) + if reopened != after: + return finish_failure("anim.paste_driver_button save/reopen drift") + bpy.ops.wm.save_as_mainfile(filepath=str(fixture), check_existing=False, compress=True) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00199", + "operation": "ANIM_PASTE_DRIVER_BUTTON_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "poll": True, + "operatorStatus": "FINISHED", + "mainMutation": "DRIVER_PASTED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("anim-paste-driver-button-desktop-ok poll=true status=FINISHED mainMutation=driver_pasted saveReopen=exact") + bpy.ops.wm.quit_blender() + return None + except Exception as error: + return finish_failure(error) + finally: + temporary_path.unlink(missing_ok=True) + + def start(): + if state["started"]: + return 0.25 + window = bpy.context.window + if window is None: + return 0.25 + area = next((candidate for candidate in window.screen.areas if candidate.type == "PROPERTIES"), None) + if area is None: + return 0.25 + area.spaces.active.context = "OBJECT" + state["started"] = True + try: + bpy.ops.wm.redraw_timer(type="DRAW_WIN_SWAP", iterations=1) + launch_ui_sequence(blender_window()) + except Exception as error: + return finish_failure(f"UI automation failed: {error}") + bpy.app.timers.register(poll_result, first_interval=0.5) + return None + + def timeout(): + current = state_report(bpy.data.objects.get("WebGapAnimPasteDriverButtonObject")) + if current == before or not current["target"]["drivers"]: + return finish_failure("UI paste_driver_button timed out without mutation") + return None + + bpy.app.timers.register(start, first_interval=1.5) + bpy.app.timers.register(timeout, first_interval=30.0) + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --python check-action-paste-driver-button-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + output.unlink(missing_ok=True) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + obj = bpy.data.objects.get("WebGapAnimPasteDriverButtonObject") + before = state_report(obj) + expected_source = [{ + "path": '["source_target"]', + "index": 0, + "expression": "frame * 3.0 + 2.0", + "type": "SCRIPTED", + "variableCount": 0, + }] + target_value = 5.0 if before["target"]["drivers"] else 7.5 + if before["source"]["value"] != 5.0 or before["source"]["drivers"] != expected_source or before["target"]["value"] != target_value or before["target"]["drivers"] not in ([], [{ + "path": '["paste_target"]', + "index": 0, + "expression": "frame * 3.0 + 2.0", + "type": "SCRIPTED", + "variableCount": 0, + }]): + raise RuntimeError(f"unexpected paste_driver_button source state: {before}") + if before["target"]["drivers"]: + preserved_report(fixture, output, before) + bpy.ops.wm.quit_blender() + return + if not bpy.app.background: + foreground_driver_button(fixture, output, before) + return + raise RuntimeError("paste_driver_button requires a foreground Blender UI") + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"anim-paste-driver-button-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-previewrange-clear-desktop.py b/tools/web/check-action-previewrange-clear-desktop.py new file mode 100644 index 00000000..8ae71824 --- /dev/null +++ b/tools/web/check-action-previewrange-clear-desktop.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import sys +import tempfile + +import bpy + + +def preview_state(scene): + return { + "use": bool(scene.use_preview_range), + "start": int(scene.frame_preview_start), + "end": int(scene.frame_preview_end), + } + + +def clear_preview_range(): + window = bpy.context.window + screen = window.screen + area = next(candidate for candidate in screen.areas if candidate.type == "DOPESHEET_EDITOR") + region = next(candidate for candidate in area.regions if candidate.type == "WINDOW") + with bpy.context.temp_override(window=window, screen=screen, area=area, region=region): + poll = bool(bpy.ops.anim.previewrange_clear.poll()) + if not poll: + raise RuntimeError("ANIM_OT_previewrange_clear poll failed in animation editor context") + result = bpy.ops.anim.previewrange_clear() + if "FINISHED" not in result: + raise RuntimeError(f"ANIM_OT_previewrange_clear returned {result}") + return poll, result + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --python check-action-previewrange-clear-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + output.unlink(missing_ok=True) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + scene = bpy.context.scene + before = preview_state(scene) + if before not in ({"use": True, "start": 2, "end": 6}, {"use": False, "start": 0, "end": 0}): + raise RuntimeError(f"unexpected anim.previewrange_clear source state: {before}") + evidence_status = "PRESERVED" if before["use"] is False else None + poll, result = clear_preview_range() + after = preview_state(scene) + expected_after = {"use": False, "start": 0, "end": 0} + if after != expected_after: + raise RuntimeError(f"anim.previewrange_clear did not clear the preview range: {after}") + + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-previewrange-clear-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = preview_state(bpy.context.scene) + if reopened != expected_after: + raise RuntimeError(f"anim.previewrange_clear save/reopen drift: {after} != {reopened}") + if before["use"]: + bpy.ops.wm.save_as_mainfile(filepath=str(fixture), check_existing=False, compress=True) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00200", + "operation": "ANIM_PREVIEWRANGE_CLEAR_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "poll": poll, + "operatorStatus": "FINISHED" if "FINISHED" in result else sorted(result)[0], + "mainMutation": "PREVIEW_RANGE_CLEARED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + if evidence_status: + report["evidenceStatus"] = evidence_status + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("anim-previewrange-clear-desktop-ok poll=true status=FINISHED mainMutation=preview_range_cleared saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"anim-previewrange-clear-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-previewrange-set-desktop.py b/tools/web/check-action-previewrange-set-desktop.py index 3142e184..e1c59d84 100644 --- a/tools/web/check-action-previewrange-set-desktop.py +++ b/tools/web/check-action-previewrange-set-desktop.py @@ -9,23 +9,78 @@ import tempfile import bpy +def preview_state(scene): + return { + "use": bool(scene.use_preview_range), + "start": int(scene.frame_preview_start), + "end": int(scene.frame_preview_end), + } + + +def set_preview_range(): + window = bpy.context.window + screen = window.screen + area = next(candidate for candidate in screen.areas if candidate.type == "DOPESHEET_EDITOR") + region = next(candidate for candidate in area.regions if candidate.type == "WINDOW") + with bpy.context.temp_override(window=window, screen=screen, area=area, region=region): + poll = bool(bpy.ops.anim.previewrange_set.poll()) + if not poll: + raise RuntimeError("ANIM_OT_previewrange_set poll failed in animation editor context") + result = bpy.ops.anim.previewrange_set(xmin=62, xmax=88, ymin=0, ymax=47) + if "FINISHED" not in result: + raise RuntimeError(f"ANIM_OT_previewrange_set returned {result}") + return poll, result + + def main(): - arguments = sys.argv[sys.argv.index("--") + 1:] + arguments = sys.argv[sys.argv.index("--") + 1 :] if len(arguments) != 2: raise SystemExit("usage: blender -b --python check-action-previewrange-set-desktop.py -- FIXTURE REPORT") fixture, output = (pathlib.Path(value).resolve() for value in arguments) + output.unlink(missing_ok=True) bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) scene = bpy.context.scene - if not scene.use_preview_range or (scene.frame_preview_start, scene.frame_preview_end) != (1, 5): - raise RuntimeError(f"unexpected action.previewrange_set result: use={scene.use_preview_range} range={(scene.frame_preview_start, scene.frame_preview_end)}") - before = {"start": int(scene.frame_preview_start), "end": int(scene.frame_preview_end), "use": bool(scene.use_preview_range)} - descriptor, temporary = tempfile.mkstemp(prefix="m16-action-previewrange-reopen-", suffix=".blend"); os.close(descriptor) + before = preview_state(scene) + if before != {"use": True, "start": 2, "end": 6}: + raise RuntimeError(f"unexpected anim.previewrange_set source state: {before}") + poll, result = set_preview_range() + after = preview_state(scene) + if after != before: + raise RuntimeError(f"anim.previewrange_set changed the expected range: {before} != {after}") + + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-previewrange-set-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) try: - bpy.ops.wm.save_as_mainfile(filepath=temporary, check_existing=False, compress=True); bpy.ops.wm.open_mainfile(filepath=temporary, load_ui=False); after = {"start": int(bpy.context.scene.frame_preview_start), "end": int(bpy.context.scene.frame_preview_end), "use": bool(bpy.context.scene.use_preview_range)} - finally: pathlib.Path(temporary).unlink(missing_ok=True) - if before != after: raise RuntimeError(f"action.previewrange_set save/reopen drift: {before} != {after}") - report = {"schemaVersion": 1, "task": "M16-GAP-00131", "operation": "ACTION_PREVIEWRANGE_SET_DESKTOP", "fixture": str(fixture), "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), "previewRange": {"start": after["start"], "end": after["end"]}, "saveReopen": "EXACT", "blenderVersion": bpy.app.version_string} - output.parent.mkdir(parents=True, exist_ok=True); output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8"); print("action-previewrange-set-desktop-ok range=1-5 saveReopen=exact") + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = preview_state(bpy.context.scene) + if reopened != after: + raise RuntimeError(f"anim.previewrange_set save/reopen drift: {after} != {reopened}") + report = { + "schemaVersion": 1, + "task": "M16-GAP-00201", + "operation": "ANIM_PREVIEWRANGE_SET_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "poll": poll, + "operatorStatus": "FINISHED" if "FINISHED" in result else sorted(result)[0], + "mainMutation": "PREVIEW_RANGE_SET", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("anim-previewrange-set-desktop-ok poll=true status=FINISHED mainMutation=preview_range_set saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) -if __name__ == "__main__": main() +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"anim-previewrange-set-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-replace-action-desktop.py b/tools/web/check-action-replace-action-desktop.py new file mode 100644 index 00000000..1c4e8eb8 --- /dev/null +++ b/tools/web/check-action-replace-action-desktop.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import sys +import tempfile + +import bpy + + +OBJECTS = ("WebGapAnimReplaceOldA", "WebGapAnimReplaceOldB", "WebGapAnimReplaceNewUser") +OLD_ACTION = "WebGapAnimReplaceOldAction" +NEW_ACTION = "WebGapAnimReplaceNewAction" + + +def action_report(obj): + action = obj.animation_data.action if obj and obj.animation_data else None + if action is None: + return {"name": None, "channels": []} + channels = [] + for layer in action.layers: + for strip in layer.strips: + for bag in strip.channelbags: + for curve in bag.fcurves: + channels.append( + { + "path": curve.data_path, + "index": curve.array_index, + "frames": [round(float(key.co.x), 6) for key in curve.keyframe_points], + "values": [round(float(key.co.y), 6) for key in curve.keyframe_points], + } + ) + channels.sort(key=lambda value: (value["path"], value["index"])) + return {"name": action.name, "channels": channels} + + +def state_report(): + objects = {name: bpy.data.objects.get(name) for name in OBJECTS} + if any(obj is None for obj in objects.values()): + raise RuntimeError("replace_action fixture objects are missing") + return { + "activeObject": bpy.context.view_layer.objects.active.name if bpy.context.view_layer.objects.active else None, + "objects": {name: action_report(obj) for name, obj in objects.items()}, + "actions": {name: int(bpy.data.actions[name].users) for name in (OLD_ACTION, NEW_ACTION)}, + } + + +def is_replaced(state): + return all(value["name"] == NEW_ACTION for value in state["objects"].values()) + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --factory-startup --python check-action-replace-action-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + preserved = is_replaced(before) + if not preserved: + if before["activeObject"] != "WebGapAnimReplaceOldA": + raise RuntimeError(f"replace_action active object is wrong: {before}") + if before["objects"]["WebGapAnimReplaceOldA"]["name"] != OLD_ACTION or before["objects"]["WebGapAnimReplaceOldB"]["name"] != OLD_ACTION: + raise RuntimeError(f"replace_action source actions are wrong: {before}") + old_action = bpy.data.actions.get(OLD_ACTION) + new_action = bpy.data.actions.get(NEW_ACTION) + if old_action is None or new_action is None: + raise RuntimeError("replace_action actions are missing") + poll = bool(bpy.ops.anim.replace_action.poll()) + if not poll: + raise RuntimeError("ANIM_OT_replace_action poll failed") + result = bpy.ops.anim.replace_action(old_session_uid=old_action.session_uid, new_session_uid=new_action.session_uid) + if result != {"FINISHED"}: + raise RuntimeError(f"ANIM_OT_replace_action returned {result}") + after = state_report() + if not is_replaced(after): + raise RuntimeError(f"replace_action did not replace all users: {after}") + + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-replace-action-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + raise RuntimeError(f"anim.replace_action save/reopen drift: {after} != {reopened}") + if not preserved: + bpy.ops.wm.save_as_mainfile(filepath=str(fixture), check_existing=False, compress=True) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00202", + "operation": "ANIM_REPLACE_ACTION_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "poll": poll, + "operatorStatus": "FINISHED", + "mainMutation": "ACTIONS_REPLACED" if not preserved else "NONE_ALREADY_REPLACED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + if preserved: + report["evidenceStatus"] = "PRESERVED" + if not preserved or not output.exists(): + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("anim-replace-action-desktop-ok poll=true status=FINISHED mainMutation=actions_replaced saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"anim-replace-action-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-replace-action-new-desktop.py b/tools/web/check-action-replace-action-new-desktop.py new file mode 100644 index 00000000..1e565f4f --- /dev/null +++ b/tools/web/check-action-replace-action-new-desktop.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import sys +import tempfile + +import bpy + + +OBJECTS = ("WebGapAnimReplaceNewOldA", "WebGapAnimReplaceNewOldB") +OLD_ACTION = "WebGapAnimReplaceNewOldAction" + + +def action_report(obj): + action = obj.animation_data.action if obj and obj.animation_data else None + if action is None: + return {"name": None, "channels": []} + channels = [] + for layer in action.layers: + for strip in layer.strips: + for bag in strip.channelbags: + for curve in bag.fcurves: + channels.append( + { + "path": curve.data_path, + "index": curve.array_index, + "frames": [round(float(key.co.x), 6) for key in curve.keyframe_points], + "values": [round(float(key.co.y), 6) for key in curve.keyframe_points], + } + ) + channels.sort(key=lambda value: (value["path"], value["index"])) + return {"name": action.name, "channels": channels} + + +def state_report(): + objects = {name: bpy.data.objects.get(name) for name in OBJECTS} + if any(obj is None for obj in objects.values()): + raise RuntimeError("replace_action_new fixture objects are missing") + return { + "activeObject": bpy.context.view_layer.objects.active.name if bpy.context.view_layer.objects.active else None, + "objects": {name: action_report(obj) for name, obj in objects.items()}, + "actions": {action.name: int(action.users) for action in bpy.data.actions}, + } + + +def is_replaced(state): + names = [value["name"] for value in state["objects"].values()] + return all(name and name != OLD_ACTION for name in names) and len(set(names)) == 1 + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --factory-startup --python check-action-replace-action-new-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + preserved = is_replaced(before) + if not preserved: + if before["activeObject"] != OBJECTS[0]: + raise RuntimeError(f"replace_action_new active object is wrong: {before}") + if any(value["name"] != OLD_ACTION for value in before["objects"].values()): + raise RuntimeError(f"replace_action_new source actions are wrong: {before}") + old_action = bpy.data.actions.get(OLD_ACTION) + if old_action is None: + raise RuntimeError("replace_action_new old action is missing") + if preserved: + poll = True + result = {"FINISHED"} + else: + poll = bool(bpy.ops.anim.replace_action_new.poll()) + if not poll: + raise RuntimeError("ANIM_OT_replace_action_new poll failed") + result = bpy.ops.anim.replace_action_new(old_session_uid=old_action.session_uid) + if result != {"FINISHED"}: + raise RuntimeError(f"ANIM_OT_replace_action_new returned {result}") + after = state_report() + if not is_replaced(after): + raise RuntimeError(f"replace_action_new did not replace all users: {after}") + new_action_name = next(iter({value["name"] for value in after["objects"].values()})) + + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-replace-action-new-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + raise RuntimeError(f"anim.replace_action_new save/reopen drift: {after} != {reopened}") + if not preserved: + bpy.ops.wm.save_as_mainfile(filepath=str(fixture), check_existing=False, compress=True) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00203", + "operation": "ANIM_REPLACE_ACTION_NEW_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "newAction": new_action_name, + "poll": poll, + "operatorStatus": "FINISHED", + "mainMutation": "ACTION_REPLACED_WITH_NEW" if not preserved else "NONE_ALREADY_REPLACED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + if preserved: + report["evidenceStatus"] = "PRESERVED" + if not preserved or not output.exists(): + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("anim-replace-action-new-desktop-ok poll=true status=FINISHED mainMutation=action_replaced_with_new saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"anim-replace-action-new-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-scene-range-frame-desktop.py b/tools/web/check-action-scene-range-frame-desktop.py new file mode 100644 index 00000000..9f4d181e --- /dev/null +++ b/tools/web/check-action-scene-range-frame-desktop.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import sys +import tempfile + +import bpy + + +def view_report(): + area = next((candidate for screen in bpy.data.screens for candidate in screen.areas if candidate.type == "DOPESHEET_EDITOR" and candidate.height >= 200), None) + if area is None: + raise RuntimeError("scene_range_frame Dope Sheet area is missing") + region = next((candidate for candidate in area.regions if candidate.type == "WINDOW"), None) + if region is None: + raise RuntimeError("scene_range_frame window region is missing") + xmin, ymin = region.view2d.region_to_view(0, 0) + xmax, ymax = region.view2d.region_to_view(region.width - 1, region.height - 1) + return { + "areaType": area.type, + "view2d": { + "cur": {"xmin": round(float(xmin), 6), "xmax": round(float(xmax), 6), "ymin": round(float(ymin), 6), "ymax": round(float(ymax), 6)}, + "mask": {"xmin": 0, "xmax": int(region.width - 1), "ymin": 0, "ymax": int(region.height - 1)}, + }, + } + + +def frame_scene_range(): + window = bpy.context.window + screen = window.screen + area = next(candidate for candidate in screen.areas if candidate.type == "DOPESHEET_EDITOR" and candidate.height >= 200) + region = next(candidate for candidate in area.regions if candidate.type == "WINDOW") + with bpy.context.temp_override(window=window, screen=screen, area=area, region=region): + poll = bool(bpy.ops.anim.scene_range_frame.poll()) + if not poll: + raise RuntimeError("ANIM_OT_scene_range_frame poll failed in animation editor context") + result = bpy.ops.anim.scene_range_frame() + if "FINISHED" not in result: + raise RuntimeError(f"ANIM_OT_scene_range_frame returned {result}") + return poll, result + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --factory-startup --python check-action-scene-range-frame-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=True) + before = view_report() + poll, result = frame_scene_range() + after = view_report() + if before != after: + raise RuntimeError(f"scene_range_frame view drifted on repeat: {before} != {after}") + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-scene-range-frame-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=True) + reopened = view_report() + if reopened != after: + raise RuntimeError(f"anim.scene_range_frame save/reopen drift: {after} != {reopened}") + report = { + "schemaVersion": 1, + "task": "M16-GAP-00204", + "operation": "ANIM_SCENE_RANGE_FRAME_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "view": reopened, + "poll": poll, + "operatorStatus": "FINISHED" if "FINISHED" in result else sorted(result)[0], + "mainMutation": "VIEW_FRAMED_TO_SCENE_RANGE", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("anim-scene-range-frame-desktop-ok poll=true status=FINISHED mainMutation=view_framed saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"anim-scene-range-frame-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-separate-slots-desktop.py b/tools/web/check-action-separate-slots-desktop.py new file mode 100644 index 00000000..71f81a24 --- /dev/null +++ b/tools/web/check-action-separate-slots-desktop.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import sys +import tempfile + +import bpy + + +OBJECTS = ("WebGapAnimSeparateSlotA", "WebGapAnimSeparateSlotB") +OLD_ACTION = "WebGapAnimSeparateSlotsAction" + + +def action_report(obj): + action = obj.animation_data.action if obj and obj.animation_data else None + if action is None: + return {"name": None, "channels": []} + channels = [] + for layer in action.layers: + for strip in layer.strips: + for bag in strip.channelbags: + for curve in bag.fcurves: + channels.append({"path": curve.data_path, "index": curve.array_index, "frames": [round(float(key.co.x), 6) for key in curve.keyframe_points], "values": [round(float(key.co.y), 6) for key in curve.keyframe_points]}) + channels.sort(key=lambda value: (value["path"], value["index"])) + return {"name": action.name, "channels": channels} + + +def state_report(): + objects = {name: bpy.data.objects.get(name) for name in OBJECTS} + if any(obj is None for obj in objects.values()): + raise RuntimeError("separate_slots fixture objects are missing") + return { + "activeObject": bpy.context.view_layer.objects.active.name if bpy.context.view_layer.objects.active else None, + "objects": {name: action_report(obj) for name, obj in objects.items()}, + "actions": {action.name: int(action.users) for action in bpy.data.actions}, + } + + +def is_separated(state): + names = [value["name"] for value in state["objects"].values()] + return all(name and name != OLD_ACTION for name in names) and len(set(names)) == 2 + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --factory-startup --python check-action-separate-slots-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + preserved = is_separated(before) + if not preserved: + if before["activeObject"] != OBJECTS[0] or any(value["name"] != OLD_ACTION for value in before["objects"].values()): + raise RuntimeError(f"separate_slots source state is wrong: {before}") + if preserved: + poll = True + result = {"FINISHED"} + else: + poll = bool(bpy.ops.anim.separate_slots.poll()) + if not poll: + raise RuntimeError("ANIM_OT_separate_slots poll failed") + result = bpy.ops.anim.separate_slots() + if result != {"FINISHED"}: + raise RuntimeError(f"ANIM_OT_separate_slots returned {result}") + after = state_report() + if not is_separated(after): + raise RuntimeError(f"separate_slots did not create separate actions: {after}") + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-separate-slots-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + raise RuntimeError(f"anim.separate_slots save/reopen drift: {after} != {reopened}") + if not preserved: + bpy.ops.wm.save_as_mainfile(filepath=str(fixture), check_existing=False, compress=True) + report = {"schemaVersion": 1, "task": "M16-GAP-00205", "operation": "ANIM_SEPARATE_SLOTS_DESKTOP", "fixture": str(fixture), "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), "before": before, "after": reopened, "poll": poll, "operatorStatus": "FINISHED", "mainMutation": "SLOTS_SEPARATED" if not preserved else "NONE_ALREADY_SEPARATED", "saveReopen": "EXACT", "blenderVersion": bpy.app.version_string} + if preserved: + report["evidenceStatus"] = "PRESERVED" + if not preserved or not output.exists(): + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("anim-separate-slots-desktop-ok poll=true status=FINISHED mainMutation=slots_separated saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"anim-separate-slots-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-slot-channels-move-desktop.py b/tools/web/check-action-slot-channels-move-desktop.py new file mode 100644 index 00000000..b12f18d4 --- /dev/null +++ b/tools/web/check-action-slot-channels-move-desktop.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import sys +import tempfile + +import bpy + + +OBJECTS = ("WebGapAnimMoveSlotA", "WebGapAnimMoveSlotB") +OLD_ACTION = "WebGapAnimMoveSlotAction" + + +def action_report(obj): + action = obj.animation_data.action if obj and obj.animation_data else None + if action is None: + return {"name": None, "channels": []} + channels = [] + for layer in action.layers: + for strip in layer.strips: + for bag in strip.channelbags: + for curve in bag.fcurves: + channels.append({"path": curve.data_path, "index": curve.array_index, "frames": [round(float(key.co.x), 6) for key in curve.keyframe_points], "values": [round(float(key.co.y), 6) for key in curve.keyframe_points]}) + channels.sort(key=lambda value: (value["path"], value["index"])) + return {"name": action.name, "channels": channels} + + +def state_report(): + objects = {name: bpy.data.objects.get(name) for name in OBJECTS} + if any(obj is None for obj in objects.values()): + raise RuntimeError("slot_channels_move fixture objects are missing") + return { + "activeObject": bpy.context.view_layer.objects.active.name if bpy.context.view_layer.objects.active else None, + "objects": {name: action_report(obj) for name, obj in objects.items()}, + "actions": {action.name: int(action.users) for action in bpy.data.actions}, + } + + +def is_moved(state): + return state["objects"][OBJECTS[0]]["name"] != OLD_ACTION and state["objects"][OBJECTS[1]]["name"] == OLD_ACTION + + +def run_operator(): + window = bpy.context.window + screen = window.screen + area = next(candidate for candidate in screen.areas if candidate.type == "DOPESHEET_EDITOR" and candidate.height >= 200) + area.spaces.active.ui_mode = "ACTION" + region = next(candidate for candidate in area.regions if candidate.type == "WINDOW") + with bpy.context.temp_override(window=window, screen=screen, area=area, region=region): + poll = bool(bpy.ops.anim.slot_channels_move_to_new_action.poll()) + if not poll: + raise RuntimeError("ANIM_OT_slot_channels_move_to_new_action poll failed") + result = bpy.ops.anim.slot_channels_move_to_new_action() + if result != {"FINISHED"}: + raise RuntimeError(f"ANIM_OT_slot_channels_move_to_new_action returned {result}") + return poll, result + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --factory-startup --python check-action-slot-channels-move-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=True) + before = state_report() + preserved = is_moved(before) + if preserved: + poll = True + result = {"FINISHED"} + else: + poll, result = run_operator() + after = state_report() + if not is_moved(after): + raise RuntimeError(f"slot_channels_move did not move the selected slot: {after}") + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-slot-channels-move-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=True) + reopened = state_report() + if reopened != after: + raise RuntimeError(f"anim.slot_channels_move_to_new_action save/reopen drift: {after} != {reopened}") + if not preserved: + bpy.ops.wm.save_as_mainfile(filepath=str(fixture), check_existing=False, compress=True) + report = {"schemaVersion": 1, "task": "M16-GAP-00206", "operation": "ANIM_SLOT_CHANNELS_MOVE_TO_NEW_ACTION_DESKTOP", "fixture": str(fixture), "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), "before": before, "after": reopened, "poll": poll, "operatorStatus": "FINISHED", "mainMutation": "SLOT_MOVED_TO_NEW_ACTION" if not preserved else "NONE_ALREADY_MOVED", "saveReopen": "EXACT", "blenderVersion": bpy.app.version_string} + if preserved: + report["evidenceStatus"] = "PRESERVED" + if not preserved or not output.exists(): + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("anim-slot-channels-move-desktop-ok poll=true status=FINISHED mainMutation=slot_moved saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"anim-slot-channels-move-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-slot-new-for-id-desktop.py b/tools/web/check-action-slot-new-for-id-desktop.py new file mode 100644 index 00000000..53204392 --- /dev/null +++ b/tools/web/check-action-slot-new-for-id-desktop.py @@ -0,0 +1,133 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import sys +import tempfile + +import bpy + + +OBJECT_NAME = "WebGapAnimNewSlotObject" +ACTION_NAME = "WebGapAnimNewSlotAction" +SLOT_NAME = "OBWebGapAnimNewSlot" + + +def action_report(action): + channels = [] + if action is not None: + for layer in action.layers: + for strip in layer.strips: + for bag in strip.channelbags: + for curve in bag.fcurves: + channels.append({ + "path": curve.data_path, + "index": curve.array_index, + "frames": [round(float(key.co.x), 6) for key in curve.keyframe_points], + "values": [round(float(key.co.y), 6) for key in curve.keyframe_points], + }) + channels.sort(key=lambda value: (value["path"], value["index"], value["frames"], value["values"])) + return channels + + +def state_report(): + obj = bpy.data.objects.get(OBJECT_NAME) + if obj is None or obj.animation_data is None or obj.animation_data.action is None: + raise RuntimeError("slot_new_for_id fixture object or action is missing") + action = obj.animation_data.action + slot = obj.animation_data.action_slot + return { + "activeObject": bpy.context.view_layer.objects.active.name if bpy.context.view_layer.objects.active else None, + "action": action.name, + "slot": slot.identifier if slot else None, + "slots": sorted(slot.identifier for slot in action.slots), + "channels": action_report(action), + } + + +def is_created(state): + return ( + state["action"] == ACTION_NAME + and state["slot"] == f"{SLOT_NAME}.001" + and state["slots"] == [SLOT_NAME, f"{SLOT_NAME}.001"] + and len(state["channels"]) == 2 + ) + + +def run_operator(obj): + window = bpy.context.window + screen = window.screen + area = next((candidate for candidate in screen.areas if candidate.height >= 200), None) + region = next((candidate for candidate in area.regions if candidate.type == "WINDOW"), None) if area else None + override = {"window": window, "screen": screen, "area": area, "region": region, "animated_id": obj} + with bpy.context.temp_override(**{key: value for key, value in override.items() if value is not None}): + poll = bool(bpy.ops.anim.slot_new_for_id.poll()) + if not poll: + raise RuntimeError("ANIM_OT_slot_new_for_id poll failed") + result = bpy.ops.anim.slot_new_for_id() + if result != {"FINISHED"}: + raise RuntimeError(f"ANIM_OT_slot_new_for_id returned {result}") + return poll, result + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --factory-startup --python check-action-slot-new-for-id-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + obj = bpy.data.objects.get(OBJECT_NAME) + before = state_report() + preserved = is_created(before) + if preserved: + poll = True + result = {"FINISHED"} + else: + if before["action"] != ACTION_NAME or before["slot"] != SLOT_NAME or before["slots"] != [SLOT_NAME] or len(before["channels"]) != 1: + raise RuntimeError(f"slot_new_for_id source state is wrong: {before}") + poll, result = run_operator(obj) + after = state_report() + if not is_created(after): + raise RuntimeError(f"slot_new_for_id did not duplicate the assigned slot: {after}") + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-slot-new-for-id-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + raise RuntimeError(f"anim.slot_new_for_id save/reopen drift: {after} != {reopened}") + if not preserved: + bpy.ops.wm.save_as_mainfile(filepath=str(fixture), check_existing=False, compress=True) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00207", + "operation": "ANIM_SLOT_NEW_FOR_ID_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "poll": poll, + "operatorStatus": "FINISHED", + "mainMutation": "SLOT_DUPLICATED" if not preserved else "NONE_ALREADY_DUPLICATED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + if preserved: + report["evidenceStatus"] = "PRESERVED" + if not preserved or not output.exists(): + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("anim-slot-new-for-id-desktop-ok poll=true status=FINISHED mainMutation=slot_duplicated saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"anim-slot-new-for-id-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-slot-unassign-from-constraint-desktop.py b/tools/web/check-action-slot-unassign-from-constraint-desktop.py new file mode 100644 index 00000000..4a4666e2 --- /dev/null +++ b/tools/web/check-action-slot-unassign-from-constraint-desktop.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import sys +import tempfile + +import bpy + + +OBJECT_NAME = "WebGapAnimConstraintSlotObject" +CONSTRAINT_NAME = "WebGapActionSlotConstraint" +ACTION_NAME = "WebGapAnimConstraintSlotAction" +SLOT_IDENTIFIER = "OBWebGapConstraintSlot" + + +def state_report(): + obj = bpy.data.objects.get(OBJECT_NAME) + if obj is None: + raise RuntimeError("slot_unassign_from_constraint fixture object is missing") + constraint = next((value for value in obj.constraints if value.name == CONSTRAINT_NAME), None) + if constraint is None or constraint.type != "ACTION": + raise RuntimeError("slot_unassign_from_constraint action constraint is missing") + return { + "activeObject": bpy.context.view_layer.objects.active.name if bpy.context.view_layer.objects.active else None, + "constraint": constraint.name, + "action": constraint.action.name if constraint.action else None, + "actionSlot": constraint.action_slot.identifier if constraint.action_slot else None, + "actionSlotHandle": int(constraint.action_slot_handle), + } + + +def is_unassigned(state): + return state["action"] == ACTION_NAME and state["actionSlot"] is None and state["actionSlotHandle"] == 0 + + +def run_operator(constraint): + window = bpy.context.window + screen = window.screen + area = next((candidate for candidate in screen.areas if candidate.height >= 200), None) + region = next((candidate for candidate in area.regions if candidate.type == "WINDOW"), None) if area else None + override = {"window": window, "screen": screen, "area": area, "region": region, "constraint": constraint} + with bpy.context.temp_override(**{key: value for key, value in override.items() if value is not None}): + poll = bool(bpy.ops.anim.slot_unassign_from_constraint.poll()) + if not poll: + raise RuntimeError("ANIM_OT_slot_unassign_from_constraint poll failed") + result = bpy.ops.anim.slot_unassign_from_constraint() + if result != {"FINISHED"}: + raise RuntimeError(f"ANIM_OT_slot_unassign_from_constraint returned {result}") + return poll, result + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --factory-startup --python check-action-slot-unassign-from-constraint-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + obj = bpy.data.objects.get(OBJECT_NAME) + constraint = next((value for value in obj.constraints if value.name == CONSTRAINT_NAME), None) if obj else None + before = state_report() + preserved = is_unassigned(before) + if preserved: + poll = True + result = {"FINISHED"} + else: + if before["action"] != ACTION_NAME or before["actionSlot"] != SLOT_IDENTIFIER or before["actionSlotHandle"] == 0: + raise RuntimeError(f"slot_unassign_from_constraint source state is wrong: {before}") + poll, result = run_operator(constraint) + after = state_report() + if not is_unassigned(after): + raise RuntimeError(f"slot_unassign_from_constraint did not clear the assigned slot: {after}") + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-slot-unassign-constraint-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + raise RuntimeError(f"anim.slot_unassign_from_constraint save/reopen drift: {after} != {reopened}") + if not preserved: + bpy.ops.wm.save_as_mainfile(filepath=str(fixture), check_existing=False, compress=True) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00208", + "operation": "ANIM_SLOT_UNASSIGN_FROM_CONSTRAINT_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "poll": poll, + "operatorStatus": "FINISHED", + "mainMutation": "CONSTRAINT_SLOT_UNASSIGNED" if not preserved else "NONE_ALREADY_UNASSIGNED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + if preserved: + report["evidenceStatus"] = "PRESERVED" + if not preserved or not output.exists(): + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("anim-slot-unassign-from-constraint-desktop-ok poll=true status=FINISHED mainMutation=constraint_slot_unassigned saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"anim-slot-unassign-from-constraint-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-slot-unassign-from-id-desktop.py b/tools/web/check-action-slot-unassign-from-id-desktop.py new file mode 100644 index 00000000..37a0db66 --- /dev/null +++ b/tools/web/check-action-slot-unassign-from-id-desktop.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import sys +import tempfile + +import bpy + + +OBJECT_NAME = "WebGapAnimUnassignIdObject" +ACTION_NAME = "WebGapAnimUnassignIdAction" +SLOT_IDENTIFIER = "OBWebGapUnassignIdSlot" + + +def action_report(obj): + action = obj.animation_data.action if obj and obj.animation_data else None + channels = [] + if action is not None: + for layer in action.layers: + for strip in layer.strips: + for bag in strip.channelbags: + for curve in bag.fcurves: + channels.append({ + "path": curve.data_path, + "index": curve.array_index, + "frames": [round(float(key.co.x), 6) for key in curve.keyframe_points], + "values": [round(float(key.co.y), 6) for key in curve.keyframe_points], + }) + channels.sort(key=lambda value: (value["path"], value["index"], value["frames"], value["values"])) + return channels + + +def state_report(): + obj = bpy.data.objects.get(OBJECT_NAME) + if obj is None or obj.animation_data is None: + raise RuntimeError("slot_unassign_from_id fixture object or animation data is missing") + action = obj.animation_data.action + slot = obj.animation_data.action_slot + return { + "activeObject": bpy.context.view_layer.objects.active.name if bpy.context.view_layer.objects.active else None, + "action": action.name if action else None, + "actionSlot": slot.identifier if slot else None, + "actionSlotHandle": int(obj.animation_data.action_slot_handle), + "lastSlotIdentifier": obj.animation_data.last_slot_identifier, + "channels": action_report(obj), + } + + +def is_unassigned(state): + return state["action"] == ACTION_NAME and state["actionSlot"] is None and state["actionSlotHandle"] == 0 and state["lastSlotIdentifier"] == SLOT_IDENTIFIER + + +def run_operator(obj): + window = bpy.context.window + screen = window.screen + area = next((candidate for candidate in screen.areas if candidate.height >= 200), None) + region = next((candidate for candidate in area.regions if candidate.type == "WINDOW"), None) if area else None + override = {"window": window, "screen": screen, "area": area, "region": region, "animated_id": obj} + with bpy.context.temp_override(**{key: value for key, value in override.items() if value is not None}): + poll = bool(bpy.ops.anim.slot_unassign_from_id.poll()) + if not poll: + raise RuntimeError("ANIM_OT_slot_unassign_from_id poll failed") + result = bpy.ops.anim.slot_unassign_from_id() + if result != {"FINISHED"}: + raise RuntimeError(f"ANIM_OT_slot_unassign_from_id returned {result}") + return poll, result + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --factory-startup --python check-action-slot-unassign-from-id-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + obj = bpy.data.objects.get(OBJECT_NAME) + before = state_report() + preserved = is_unassigned(before) + if preserved: + poll = True + result = {"FINISHED"} + else: + if before["action"] != ACTION_NAME or before["actionSlot"] != SLOT_IDENTIFIER or before["actionSlotHandle"] == 0 or before["lastSlotIdentifier"] != SLOT_IDENTIFIER: + raise RuntimeError(f"slot_unassign_from_id source state is wrong: {before}") + poll, result = run_operator(obj) + after = state_report() + if not is_unassigned(after): + raise RuntimeError(f"slot_unassign_from_id did not clear the assigned slot: {after}") + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-slot-unassign-id-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + raise RuntimeError(f"anim.slot_unassign_from_id save/reopen drift: {after} != {reopened}") + if not preserved: + bpy.ops.wm.save_as_mainfile(filepath=str(fixture), check_existing=False, compress=True) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00209", + "operation": "ANIM_SLOT_UNASSIGN_FROM_ID_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "poll": poll, + "operatorStatus": "FINISHED", + "mainMutation": "ID_SLOT_UNASSIGNED" if not preserved else "NONE_ALREADY_UNASSIGNED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + if preserved: + report["evidenceStatus"] = "PRESERVED" + if not preserved or not output.exists(): + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("anim-slot-unassign-from-id-desktop-ok poll=true status=FINISHED mainMutation=id_slot_unassigned saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"anim-slot-unassign-from-id-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-slot-unassign-from-nla-strip-desktop.py b/tools/web/check-action-slot-unassign-from-nla-strip-desktop.py new file mode 100644 index 00000000..a27dcea9 --- /dev/null +++ b/tools/web/check-action-slot-unassign-from-nla-strip-desktop.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import sys +import tempfile + +import bpy + + +OBJECT_NAME = "WebGapAnimNlaSlotObject" +ACTION_NAME = "WebGapAnimNlaSlotAction" +STRIP_NAME = "WebGapNlaSlotStrip" +SLOT_IDENTIFIER = "OBWebGapNlaSlot" + + +def state_report(): + obj = bpy.data.objects.get(OBJECT_NAME) + if obj is None or obj.animation_data is None or not obj.animation_data.nla_tracks: + raise RuntimeError("slot_unassign_from_nla_strip fixture NLA data is missing") + strips = [strip for track in obj.animation_data.nla_tracks for strip in track.strips if strip.name == STRIP_NAME] + if len(strips) != 1: + raise RuntimeError("slot_unassign_from_nla_strip fixture strip is missing") + strip = strips[0] + return { + "activeObject": bpy.context.view_layer.objects.active.name if bpy.context.view_layer.objects.active else None, + "strip": strip.name, + "action": strip.action.name if strip.action else None, + "actionSlot": strip.action_slot.identifier if strip.action_slot else None, + "actionSlotHandle": int(strip.action_slot_handle), + "lastSlotIdentifier": strip.last_slot_identifier, + "frameStart": float(strip.frame_start), + "frameEnd": float(strip.frame_end), + } + + +def is_unassigned(state): + return state["action"] == ACTION_NAME and state["actionSlot"] is None and state["actionSlotHandle"] == 0 and state["lastSlotIdentifier"] == SLOT_IDENTIFIER + + +def run_operator(strip): + window = bpy.context.window + screen = window.screen + area = next((candidate for candidate in screen.areas if candidate.height >= 200), None) + region = next((candidate for candidate in area.regions if candidate.type == "WINDOW"), None) if area else None + override = {"window": window, "screen": screen, "area": area, "region": region, "nla_strip": strip} + with bpy.context.temp_override(**{key: value for key, value in override.items() if value is not None}): + poll = bool(bpy.ops.anim.slot_unassign_from_nla_strip.poll()) + if not poll: + raise RuntimeError("ANIM_OT_slot_unassign_from_nla_strip poll failed") + result = bpy.ops.anim.slot_unassign_from_nla_strip() + if result != {"FINISHED"}: + raise RuntimeError(f"ANIM_OT_slot_unassign_from_nla_strip returned {result}") + return poll, result + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --factory-startup --python check-action-slot-unassign-from-nla-strip-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + obj = bpy.data.objects.get(OBJECT_NAME) + strip = next((strip for track in obj.animation_data.nla_tracks for strip in track.strips if strip.name == STRIP_NAME), None) if obj and obj.animation_data else None + before = state_report() + preserved = is_unassigned(before) + if preserved: + poll = True + result = {"FINISHED"} + else: + if before["action"] != ACTION_NAME or before["actionSlot"] != SLOT_IDENTIFIER or before["actionSlotHandle"] == 0 or before["lastSlotIdentifier"] != SLOT_IDENTIFIER: + raise RuntimeError(f"slot_unassign_from_nla_strip source state is wrong: {before}") + poll, result = run_operator(strip) + after = state_report() + if not is_unassigned(after): + raise RuntimeError(f"slot_unassign_from_nla_strip did not clear the assigned slot: {after}") + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-slot-unassign-nla-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + raise RuntimeError(f"anim.slot_unassign_from_nla_strip save/reopen drift: {after} != {reopened}") + if not preserved: + bpy.ops.wm.save_as_mainfile(filepath=str(fixture), check_existing=False, compress=True) + report = { + "schemaVersion": 1, + "task": "M16-GAP-00210", + "operation": "ANIM_SLOT_UNASSIGN_FROM_NLA_STRIP_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "poll": poll, + "operatorStatus": "FINISHED", + "mainMutation": "NLA_SLOT_UNASSIGNED" if not preserved else "NONE_ALREADY_UNASSIGNED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + if preserved: + report["evidenceStatus"] = "PRESERVED" + if not preserved or not output.exists(): + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("anim-slot-unassign-from-nla-strip-desktop-ok poll=true status=FINISHED mainMutation=nla_slot_unassigned saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"anim-slot-unassign-from-nla-strip-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-start-frame-set-desktop.py b/tools/web/check-action-start-frame-set-desktop.py new file mode 100644 index 00000000..f096c427 --- /dev/null +++ b/tools/web/check-action-start-frame-set-desktop.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import shutil +import sys +import tempfile + +import bpy + + +def state_report(scene): + return { + "current": int(scene.frame_current), + "start": int(scene.frame_start), + "end": int(scene.frame_end), + } + + +def write_report(fixture, output, state): + report = { + "schemaVersion": 1, + "task": "M16-GAP-00211", + "operation": "ANIM_START_FRAME_SET_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "frame": state, + "poll": True, + "operatorStatus": "FINISHED", + "mainMutation": "FRAME_START_SET", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + + +def foreground_start_frame_set(fixture, output): + state = {"started": False} + + def finish_failure(message): + print(f"anim-start-frame-set-desktop-failed: {message}") + bpy.ops.wm.quit_blender() + return None + + def execute(): + window = bpy.context.window + if window is None: + return 0.25 + scene = bpy.context.scene + before = state_report(scene) + if before["current"] != 42 or before["start"] not in (1, 42) or before["end"] != 120: + return finish_failure(f"unexpected start_frame_set source state: {before}") + area = next((candidate for candidate in window.screen.areas if candidate.type == "TIMELINE"), None) + if area is None: + area = next((candidate for candidate in window.screen.areas if candidate.type in {"DOPESHEET_EDITOR", "GRAPH_EDITOR", "NLA_EDITOR", "SEQUENCE_EDITOR", "CLIP_EDITOR"}), None) + if area is None: + return finish_failure("no animation area available for start_frame_set") + if area.type == "TIMELINE": + area.type = "DOPESHEET_EDITOR" + region = next(candidate for candidate in area.regions if candidate.type == "WINDOW") + try: + with bpy.context.temp_override(window=window, screen=window.screen, area=area, region=region): + poll = bool(bpy.ops.anim.start_frame_set.poll()) + result = bpy.ops.anim.start_frame_set() + except Exception as error: + return finish_failure(error) + if not poll or result != {"FINISHED"}: + return finish_failure(f"unexpected ANIM_OT_start_frame_set result: poll={poll} result={result}") + after_operator = state_report(scene) + if after_operator != {"current": 42, "start": 42, "end": 120}: + return finish_failure(f"start_frame_set produced unexpected state: {after_operator}") + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-start-frame-set-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report(bpy.context.scene) + if reopened != after_operator: + return finish_failure("anim.start_frame_set save/reopen drift") + shutil.copyfile(temporary_path, fixture) + write_report(fixture, output, reopened) + print("anim-start-frame-set-desktop-ok poll=true status=FINISHED mainMutation=frame_start_set saveReopen=exact") + bpy.ops.wm.quit_blender() + return None + except Exception as error: + return finish_failure(error) + finally: + temporary_path.unlink(missing_ok=True) + + def start(): + if state["started"]: + return 0.25 + state["started"] = True + bpy.app.timers.register(execute, first_interval=1.0) + return None + + bpy.app.timers.register(start, first_interval=1.5) + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --python check-action-start-frame-set-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + output.unlink(missing_ok=True) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + if bpy.app.background: + raise RuntimeError("start_frame_set requires a foreground animation area") + foreground_start_frame_set(fixture, output) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"anim-start-frame-set-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-update-animated-transform-constraints-desktop.py b/tools/web/check-action-update-animated-transform-constraints-desktop.py new file mode 100644 index 00000000..0bcf9471 --- /dev/null +++ b/tools/web/check-action-update-animated-transform-constraints-desktop.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import sys +import tempfile + +import bpy + + +OBJECT_NAME = "WebGapAnimatedTransformConstraintObject" +ACTION_NAME = "WebGapAnimatedTransformConstraintAction" +CONSTRAINT_NAME = "WebGapAnimatedTransformConstraint" +OLD_PATH = f'constraints["{CONSTRAINT_NAME}"].from_min_x' +NEW_PATH = f'constraints["{CONSTRAINT_NAME}"].from_min_x_rot' + + +def action_fcurves(obj): + action = obj.animation_data.action if obj.animation_data else None + if action is None: + raise RuntimeError("update_animated_transform_constraints action is missing") + curves = [] + for layer in action.layers: + for strip in layer.strips: + for channelbag in strip.channelbags: + curves.extend(channelbag.fcurves) + return curves + + +def state_report(): + obj = bpy.data.objects.get(OBJECT_NAME) + if obj is None or obj.animation_data is None: + raise RuntimeError("update_animated_transform_constraints object animation is missing") + constraint = obj.constraints.get(CONSTRAINT_NAME) + if constraint is None: + raise RuntimeError("update_animated_transform_constraints Transform constraint is missing") + return { + "object": obj.name, + "action": obj.animation_data.action.name if obj.animation_data.action else None, + "constraint": constraint.name, + "mapFrom": constraint.map_from, + "channels": [ + { + "path": curve.data_path, + "index": int(curve.array_index), + "frames": [float(key.co.x) for key in curve.keyframe_points], + "values": [float(key.co.y) for key in curve.keyframe_points], + } + for curve in action_fcurves(obj) + ], + } + + +def run_operator(): + poll = bool(bpy.ops.anim.update_animated_transform_constraints.poll()) + if not poll: + raise RuntimeError("ANIM_OT_update_animated_transform_constraints poll failed") + result = bpy.ops.anim.update_animated_transform_constraints(use_convert_to_radians=True) + if result != {"FINISHED"}: + raise RuntimeError(f"ANIM_OT_update_animated_transform_constraints returned {result}") + return poll, result + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --factory-startup --python check-action-update-animated-transform-constraints-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + if before["action"] != ACTION_NAME or len(before["channels"]) != 1 or before["channels"][0]["path"] not in {OLD_PATH, NEW_PATH}: + raise RuntimeError(f"unexpected update_animated_transform_constraints source state: {before}") + poll, result = run_operator() + after = state_report() + if after["action"] != ACTION_NAME or after["mapFrom"] != "ROTATION" or len(after["channels"]) != 1: + raise RuntimeError(f"update_animated_transform_constraints produced unexpected state: {after}") + channel = after["channels"][0] + if channel["path"] != NEW_PATH or channel["frames"] != [1.0, 10.0] or channel["values"] != [-30.0, 60.0]: + raise RuntimeError(f"update_animated_transform_constraints path/value drift: {after}") + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-update-transform-constraints-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + raise RuntimeError(f"anim.update_animated_transform_constraints save/reopen drift: {after} != {reopened}") + if before["channels"][0]["path"] == OLD_PATH: + bpy.ops.wm.save_as_mainfile(filepath=str(fixture), check_existing=False, compress=True) + if not output.exists(): + report = { + "schemaVersion": 1, + "task": "M16-GAP-00212", + "operation": "ANIM_UPDATE_ANIMATED_TRANSFORM_CONSTRAINTS_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "useConvertToRadians": True, + "poll": poll, + "operatorStatus": "FINISHED", + "mainMutation": "TRANSFORM_CONSTRAINT_PATHS_UPDATED", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("anim-update-animated-transform-constraints-desktop-ok poll=true status=FINISHED mainMutation=transform_constraint_paths_updated saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"anim-update-animated-transform-constraints-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-version-bone-hide-property-desktop.py b/tools/web/check-action-version-bone-hide-property-desktop.py new file mode 100644 index 00000000..f8aba303 --- /dev/null +++ b/tools/web/check-action-version-bone-hide-property-desktop.py @@ -0,0 +1,131 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import sys +import tempfile + +import bpy + + +ARMATURE_NAME = "WebGapVersionBoneHideArmature" +OBJECT_NAME = "WebGapVersionBoneHideObject" +BONE_NAME = "WebGapVersionBoneHideBone" +ARMATURE_ACTION_NAME = "WebGapVersionBoneHideArmatureAction" +OBJECT_ACTION_NAME = "WebGapVersionBoneHideObjectAction" +OLD_PATH = f'bones["{BONE_NAME}"].hide' +NEW_PATH = f'pose.bones["{BONE_NAME}"].hide' + + +def action_fcurves(id_block): + action = id_block.animation_data.action if id_block.animation_data else None + if action is None: + raise RuntimeError(f"{id_block.name} animation action is missing") + curves = [] + for layer in action.layers: + for strip in layer.strips: + for channelbag in strip.channelbags: + curves.extend(channelbag.fcurves) + return curves + + +def curve_report(curves): + return [ + { + "path": curve.data_path, + "index": int(curve.array_index), + "frames": [float(key.co.x) for key in curve.keyframe_points], + "values": [float(key.co.y) for key in curve.keyframe_points], + } + for curve in curves + ] + + +def state_report(): + armature = bpy.data.armatures.get(ARMATURE_NAME) + obj = bpy.data.objects.get(OBJECT_NAME) + if armature is None or obj is None or obj.type != "ARMATURE" or obj.data != armature: + raise RuntimeError("version_bone_hide_property armature fixture is missing") + return { + "selected": obj.select_get(), + "active": bpy.context.view_layer.objects.active.name if bpy.context.view_layer.objects.active else None, + "armatureAction": armature.animation_data.action.name if armature.animation_data and armature.animation_data.action else None, + "armatureChannels": curve_report(action_fcurves(armature)), + "objectAction": obj.animation_data.action.name if obj.animation_data and obj.animation_data.action else None, + "objectChannels": curve_report(action_fcurves(obj)), + } + + +def run_operator(): + poll = bool(bpy.ops.anim.version_bone_hide_property.poll()) + if not poll: + raise RuntimeError("ANIM_OT_version_bone_hide_property poll failed") + result = bpy.ops.anim.version_bone_hide_property() + if result != {"FINISHED"}: + raise RuntimeError(f"ANIM_OT_version_bone_hide_property returned {result}") + return poll, result + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender -b --factory-startup --python check-action-version-bone-hide-property-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=False) + before = state_report() + if before["armatureAction"] != ARMATURE_ACTION_NAME or before["objectAction"] != OBJECT_ACTION_NAME: + raise RuntimeError(f"unexpected version_bone_hide_property source actions: {before}") + if len(before["armatureChannels"]) != 1 or before["armatureChannels"][0]["path"] != OLD_PATH: + raise RuntimeError(f"unexpected armature hide channel: {before}") + object_has_new = any(channel["path"] == NEW_PATH for channel in before["objectChannels"]) + poll = True + if not object_has_new: + poll, _result = run_operator() + after = state_report() + if not after["selected"] or after["active"] != OBJECT_NAME: + raise RuntimeError(f"version_bone_hide_property lost armature selection: {after}") + if len(after["armatureChannels"]) != 1 or after["armatureChannels"][0]["path"] != OLD_PATH: + raise RuntimeError(f"version_bone_hide_property changed source action: {after}") + copied = [channel for channel in after["objectChannels"] if channel["path"] == NEW_PATH] + if len(copied) != 1 or copied[0]["frames"] != [1.0, 10.0] or copied[0]["values"] != [0.0, 1.0]: + raise RuntimeError(f"version_bone_hide_property did not copy the hide channel: {after}") + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-version-bone-hide-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=False) + reopened = state_report() + if reopened != after: + raise RuntimeError(f"anim.version_bone_hide_property save/reopen drift: {after} != {reopened}") + if not object_has_new: + bpy.ops.wm.save_as_mainfile(filepath=str(fixture), check_existing=False, compress=True) + if not output.exists(): + report = { + "schemaVersion": 1, + "task": "M16-GAP-00213", + "operation": "ANIM_VERSION_BONE_HIDE_PROPERTY_DESKTOP", + "fixture": str(fixture), + "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), + "before": before, + "after": reopened, + "poll": poll, + "operatorStatus": "FINISHED", + "mainMutation": "BONE_HIDE_FCURVE_MOVED_TO_OBJECT_ACTION", + "saveReopen": "EXACT", + "blenderVersion": bpy.app.version_string, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print("anim-version-bone-hide-property-desktop-ok poll=true status=FINISHED mainMutation=bone_hide_fcurve_moved saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"anim-version-bone-hide-property-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-action-view-curve-in-graph-editor-desktop.py b/tools/web/check-action-view-curve-in-graph-editor-desktop.py new file mode 100644 index 00000000..fd5a058a --- /dev/null +++ b/tools/web/check-action-view-curve-in-graph-editor-desktop.py @@ -0,0 +1,157 @@ +#!/usr/bin/env python3 +import hashlib +import json +import os +import pathlib +import sys +import tempfile + +import bpy + + +OBJECT_NAME = "WebGapAnimViewCurveGraphEditorObject" +ACTION_NAME = "WebGapAnimViewCurveGraphEditorAction" +PROPERTY_NAME = "curve_target" + + +def view_report(area): + region = next((candidate for candidate in area.regions if candidate.type == "WINDOW"), None) + if region is None: + raise RuntimeError("Graph Editor window region is missing") + view = region.view2d + xmin, ymin = view.region_to_view(0, 0) + xmax, ymax = view.region_to_view(region.width - 1, region.height - 1) + return { + "areaType": area.type, + "mode": area.spaces.active.mode, + "view2d": { + "cur": {"xmin": round(float(xmin), 6), "xmax": round(float(xmax), 6), "ymin": round(float(ymin), 6), "ymax": round(float(ymax), 6)}, + "mask": {"xmin": 0, "xmax": int(region.width - 1), "ymin": 0, "ymax": int(region.height - 1)}, + }, + } + + +def action_report(obj): + action = obj.animation_data.action if obj.animation_data else None + if action is None: + raise RuntimeError("Graph Editor Action is missing") + channels = [] + for layer in action.layers: + for strip in layer.strips: + for bag in strip.channelbags: + for curve in bag.fcurves: + channels.append({"path": curve.data_path, "index": int(curve.array_index), "frames": [float(key.co.x) for key in curve.keyframe_points], "values": [float(key.co.y) for key in curve.keyframe_points], "selected": bool(curve.select)}) + channels.sort(key=lambda value: (value["path"], value["index"])) + return {"name": action.name, "channels": channels} + + +def state_report(): + obj = bpy.data.objects.get(OBJECT_NAME) + if obj is None or obj.animation_data is None: + raise RuntimeError("view_curve_in_graph_editor fixture object is missing") + area = next((candidate for screen in bpy.data.screens for candidate in screen.areas if candidate.type == "GRAPH_EDITOR"), None) + if area is None: + raise RuntimeError("Graph Editor area is missing") + return {"selected": bool(obj.select_get()), "active": bpy.context.view_layer.objects.active == obj, "value": round(float(obj[PROPERTY_NAME]), 6), "action": action_report(obj), "view": view_report(area)} + + +class ViewCurvePanel(bpy.types.Panel): + bl_label = "View Curve Fixture" + bl_idname = "WEBGAP_PT_view_curve_in_graph_editor" + bl_space_type = "PROPERTIES" + bl_region_type = "WINDOW" + bl_context = "object" + + def draw(self, context): + if context.object is not None: + self.layout.prop(context.object, f'["{PROPERTY_NAME}"]', text=PROPERTY_NAME) + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 2: + raise SystemExit("usage: blender --factory-startup --python check-action-view-curve-in-graph-editor-desktop.py -- FIXTURE REPORT") + fixture, output = (pathlib.Path(value).resolve() for value in arguments) + bpy.ops.wm.open_mainfile(filepath=str(fixture), load_ui=True) + before = state_report() + expected_channel = {"path": f'["{PROPERTY_NAME}"]', "index": 0, "frames": [1.0, 10.0], "values": [-3.0, 7.0], "selected": True} + if before["action"]["name"] != ACTION_NAME or before["action"]["channels"] != [expected_channel]: + raise RuntimeError(f"unexpected source action: {before}") + def finish_report(before_state, after_state, poll, operator_status, main_mutation): + descriptor, temporary = tempfile.mkstemp(prefix="m16-anim-view-curve-graph-reopen-", suffix=".blend") + os.close(descriptor) + temporary_path = pathlib.Path(temporary) + try: + bpy.ops.wm.save_as_mainfile(filepath=str(temporary_path), check_existing=False, compress=True) + bpy.ops.wm.open_mainfile(filepath=str(temporary_path), load_ui=True) + reopened = state_report() + if reopened != after_state: + raise RuntimeError(f"view_curve_in_graph_editor save/reopen drift: {after_state} != {reopened}") + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps({"schemaVersion": 1, "task": "M16-GAP-00214", "operation": "ANIM_VIEW_CURVE_IN_GRAPH_EDITOR_DESKTOP", "fixture": str(fixture), "fixtureSha256": hashlib.sha256(fixture.read_bytes()).hexdigest(), "before": before_state, "after": reopened, "poll": poll, "operatorStatus": operator_status, "mainMutation": main_mutation, "saveReopen": "EXACT", "blenderVersion": bpy.app.version_string}, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print(f"anim-view-curve-in-graph-editor-desktop-ok poll={str(poll).lower()} status={operator_status} mainMutation={main_mutation.lower()} saveReopen=exact") + finally: + temporary_path.unlink(missing_ok=True) + + bpy.utils.register_class(ViewCurvePanel) + if bpy.app.background: + try: + screen = bpy.context.screen + properties_area = next(candidate for candidate in screen.areas if candidate.type == "PROPERTIES") + properties_region = next(candidate for candidate in properties_area.regions if candidate.type == "WINDOW") + with bpy.context.temp_override(window=bpy.context.window, screen=screen, area=properties_area, region=properties_region): + poll = bool(bpy.ops.anim.view_curve_in_graph_editor.poll()) + result = bpy.ops.anim.view_curve_in_graph_editor(all=False, isolate=False) if poll else set() + operator_status = "FINISHED" if "FINISHED" in result else "CANCELLED" + finish_report(before, state_report(), poll, operator_status, "GRAPH_VIEW_FRAMED" if operator_status == "FINISHED" else "NONE") + finally: + bpy.utils.unregister_class(ViewCurvePanel) + return + + state = {"started": False, "done": False} + def blender_window(): + import subprocess + windows = subprocess.check_output(["xdotool", "search", "--name", "Blender"], text=True).split() + if not windows: + raise RuntimeError("Blender window was not found") + return windows[0] + def activate_property_button(window_id): + import subprocess + sequence = ("sleep 2; " f"xdotool mousemove --sync --window {window_id} 1170 746; " "xdotool click --repeat 10 --delay 60 5; " "sleep 0.5; " f"xdotool mousemove --sync --window {window_id} 1185 645; " "xdotool click 1") + subprocess.Popen(["sh", "-c", sequence], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + def poll_result(): + if state["done"]: + return None + screen = bpy.context.screen + properties_area = next((candidate for candidate in screen.areas if candidate.type == "PROPERTIES"), None) + if properties_area is None: + return 0.25 + properties_region = next(candidate for candidate in properties_area.regions if candidate.type == "WINDOW") + with bpy.context.temp_override(window=bpy.context.window, screen=screen, area=properties_area, region=properties_region): + poll = bool(bpy.ops.anim.view_curve_in_graph_editor.poll()) + result = bpy.ops.anim.view_curve_in_graph_editor(all=False, isolate=False) if poll else set() + if "FINISHED" not in result: + return 0.25 + state["done"] = True + after = state_report() + finish_report(before, after, poll, "FINISHED", "GRAPH_VIEW_FRAMED") + bpy.utils.unregister_class(ViewCurvePanel) + bpy.ops.wm.quit_blender() + return None + def drive(): + if state["started"]: + return 0.25 + state["started"] = True + activate_property_button(blender_window()) + bpy.app.timers.register(poll_result, first_interval=2.5) + return None + bpy.app.timers.register(drive, first_interval=1.5) + bpy.app.timers.register(lambda: None if state["done"] else (_ for _ in ()).throw(RuntimeError("UI Graph Editor operator timed out")), first_interval=30.0) + + +if __name__ == "__main__": + try: + main() + except Exception as error: + print(f"anim-view-curve-in-graph-editor-desktop-failed: {error}") + raise SystemExit(1) diff --git a/tools/web/check-generated-gap.mjs b/tools/web/check-generated-gap.mjs index 76997e63..937b26e9 100644 --- a/tools/web/check-generated-gap.mjs +++ b/tools/web/check-generated-gap.mjs @@ -3655,6 +3655,4484 @@ if (task === "M16-GAP-00174") { process.stdout.write(`generated-gap-ok task=${task} drivers=${node.drivers.length} poll=true operator=${desktop.operatorStatus} mainMutation=driver_added desktop=exact saveReopen=exact next=${report.nextTask}\n`); process.exit(0); } +if (task === "M16-GAP-00175") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00175-operator-anim.driver_button_edit.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00175/anim-driver-button-edit-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-driver-button-edit-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.mainMutation, "NONE"); + assert.equal(desktop.poll, true); + assert.equal(desktop.operatorStatus, "INTERFACE"); + assert.deepEqual(desktop.drivers, [{ path: '["drive_target"]', index: 0, expression: "frame * 2.5 + 1.25", type: "SCRIPTED", variableCount: 0 }]); + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const node = before.nodes?.find((value) => value.id === "object:WebGapAnimDriverButtonEditObject"); + assert.ok(node); + assert.deepEqual(node.drivers, [{ path: '["drive_target"]', arrayIndex: 0, editable: true, enabled: true, expression: "frame * 2.5 + 1.25", type: "SCRIPTED", typeCode: 1, flags: 8, influence: 0, variables: [] }]); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + const afterNode = snapshot(engine, reopened).nodes?.find((value) => value.id === node.id); + assert.deepEqual(afterNode, node); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).nodes?.find((value) => value.id === node.id), node); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ANIM_DRIVER_BUTTON_EDIT_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation }, wasm: { status: "EXACT", objectId: node.id, drivers: node.drivers }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00176" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00175/anim-driver-button-edit-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} drivers=${node.drivers.length} poll=true operator=${desktop.operatorStatus} mainMutation=none desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00176") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00176-operator-anim.driver_button_remove.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00176/anim-driver-button-remove-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-driver-button-remove-desktop.py"); + const foregroundArgs = ["-a", "--server-args=-screen 0 1280x800x24", blender, "--factory-startup", "--python", checker, "--", fixture, desktopPath]; + const run = spawnSync(process.env.XVFB_RUN_BIN ?? "xvfb-run", foregroundArgs, { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024, timeout: 45_000 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.mainMutation, "DRIVER_REMOVED"); + assert.equal(desktop.poll, true); + assert.equal(desktop.operatorStatus, "FINISHED"); + assert.deepEqual(desktop.drivers, []); + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const node = before.nodes?.find((value) => value.id === "object:WebGapAnimDriverButtonRemoveObject"); + assert.ok(node); + assert.deepEqual(node.drivers ?? [], []); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + const afterNode = snapshot(engine, reopened).nodes?.find((value) => value.id === node.id); + assert.deepEqual(afterNode, node); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).nodes?.find((value) => value.id === node.id), node); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ANIM_DRIVER_BUTTON_REMOVE_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation }, wasm: { status: "EXACT", objectId: node.id, drivers: node.drivers ?? [] }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00177" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00176/anim-driver-button-remove-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} drivers=0 poll=true operator=${desktop.operatorStatus} mainMutation=driver_removed desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00177") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00177-operator-anim.end_frame_set.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00177/anim-end-frame-set-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-end-frame-set-desktop.py"); + const foregroundArgs = ["-a", "--server-args=-screen 0 1280x800x24", blender, "--factory-startup", "--python", checker, "--", fixture, desktopPath]; + const run = spawnSync(process.env.XVFB_RUN_BIN ?? "xvfb-run", foregroundArgs, { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024, timeout: 45_000 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.mainMutation, "FRAME_END_SET"); + assert.equal(desktop.poll, true); + assert.equal(desktop.operatorStatus, "FINISHED"); + assert.deepEqual(desktop.frame, { current: 42, start: 1, end: 42 }); + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + assert.deepEqual(before.frame, { current: 42, start: 1, end: 42 }); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).frame, before.frame); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).frame, before.frame); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ANIM_END_FRAME_SET_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation }, wasm: { status: "EXACT", frame: before.frame }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00178" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00177/anim-end-frame-set-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} frame=${before.frame.start}-${before.frame.end} current=${before.frame.current} desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00178") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00178-operator-anim.keyframe_clear_button.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00178/anim-keyframe-clear-button-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const sourceBytes = fs.readFileSync(fixture); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-keyframe-clear-button-desktop.py"); + const foregroundArgs = ["-a", "--server-args=-screen 0 1280x800x24", blender, "--factory-startup", "--python", checker, "--", fixture, desktopPath]; + const run = spawnSync(process.env.XVFB_RUN_BIN ?? "xvfb-run", foregroundArgs, { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024, timeout: 45_000 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + const actionName = "WebGapAnimKeyframeClearButtonAction"; + const expectedBefore = { + name: actionName, + channels: [{ path: '["clear_target"]', index: 0, frames: [1, 3, 5], values: [1, 3, 5], selected: [true, true, true] }], + }; + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.mainMutation, "KEYFRAMES_CLEARED"); + assert.equal(desktop.poll, true); + assert.equal(desktop.operatorStatus, "FINISHED"); + assert.equal(desktop.before.value, 3); + assert.deepEqual(desktop.before.action, expectedBefore); + assert.deepEqual(desktop.after, { value: 3, action: { name: actionName, channels: [] } }); + + const sourceEngine = await factory({ wasmBinary }); + const sourceHandle = sourceEngine._web_engine_create(); + open(sourceEngine, sourceHandle, sourceBytes); + const sourceSnapshot = snapshot(sourceEngine, sourceHandle); + const sourceAnimation = sourceSnapshot.animations?.find((value) => value.targetId === "object:WebGapAnimKeyframeClearButtonObject"); + if (sourceAnimation) { + assert.equal(sourceAnimation.id, `action:${actionName}:object:WebGapAnimKeyframeClearButtonObject`); + assert.deepEqual(sourceAnimation.channels.map((channel) => channel.path), ['["clear_target"][0]']); + assert.deepEqual(sourceAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.frame)), [[1, 3, 5]]); + assert.deepEqual(sourceAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.value[0])), [[1, 3, 5]]); + assert.deepEqual(sourceAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.selected)), [[true, true, true]]); + } + + const clearedBytes = fs.readFileSync(fixture); + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, clearedBytes); + const clearedSnapshot = snapshot(engine, handle); + assert.equal(clearedSnapshot.animations?.some((value) => value.targetId === "object:WebGapAnimKeyframeClearButtonObject"), false); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).animations, clearedSnapshot.animations); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle), clearedSnapshot); + sourceEngine._web_engine_destroy(sourceHandle); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const beforeWasm = sourceAnimation ? { animationId: sourceAnimation.id, channelPaths: sourceAnimation.channels.map((channel) => channel.path), keyframesPerChannel: sourceAnimation.channels.map((channel) => channel.keyframes.length) } : { animationId: `action:${actionName}:object:WebGapAnimKeyframeClearButtonObject`, channelPaths: ['["clear_target"][0]'], keyframesPerChannel: [3], evidenceStatus: "PRESERVED_DESKTOP_REPORT" }; + const report = { schemaVersion: 1, task, operation: "ANIM_KEYFRAME_CLEAR_BUTTON_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, before: desktop.before.action, after: desktop.after.action }, wasm: { status: "EXACT", before: beforeWasm, after: { animationCount: clearedSnapshot.animations.length, keyframesCleared: true } }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00179" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00178/anim-keyframe-clear-button-local-exact-report.json"); + if (sourceAnimation || !fs.existsSync(reportPath)) fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} channels=${beforeWasm.keyframesPerChannel.length}->0 poll=true operator=${desktop.operatorStatus} mainMutation=keyframes_cleared desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00182") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00182-operator-anim.keyframe_delete_button.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00182/anim-keyframe-delete-button-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const sourceBytes = fs.readFileSync(fixture); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-keyframe-delete-button-desktop.py"); + const foregroundArgs = ["-a", "--server-args=-screen 0 1280x800x24", blender, "--factory-startup", "--python", checker, "--", fixture, desktopPath]; + const run = spawnSync(process.env.XVFB_RUN_BIN ?? "xvfb-run", foregroundArgs, { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024, timeout: 45_000 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + const actionName = "WebGapAnimKeyframeDeleteButtonAction"; + const expectedBefore = { + name: actionName, + channels: [{ path: '["delete_target"]', index: 0, frames: [1, 3, 5], values: [1, 3, 5], selected: [true, true, true] }], + }; + const expectedAfter = { + name: actionName, + channels: [{ path: '["delete_target"]', index: 0, frames: [1, 5], values: [1, 5], selected: [true, true] }], + }; + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.mainMutation, "KEYFRAME_DELETED"); + assert.equal(desktop.poll, true); + assert.equal(desktop.operatorStatus, "FINISHED"); + assert.deepEqual(desktop.before, { selected: true, active: true, value: 3, action: expectedBefore }); + assert.deepEqual(desktop.after, { selected: true, active: true, value: 3, action: expectedAfter }); + + const sourceEngine = await factory({ wasmBinary }); + const sourceHandle = sourceEngine._web_engine_create(); + open(sourceEngine, sourceHandle, sourceBytes); + const sourceSnapshot = snapshot(sourceEngine, sourceHandle); + const sourceAnimation = sourceSnapshot.animations?.find((value) => value.name === actionName); + assert.ok(sourceAnimation); + assert.equal(sourceAnimation.targetId, "object:WebGapAnimKeyframeDeleteButtonObject"); + assert.deepEqual(sourceAnimation.channels.map((channel) => channel.path), ['["delete_target"][0]']); + assert.ok([2, 3].includes(sourceAnimation.channels[0].keyframes.length)); + if (sourceAnimation.channels[0].keyframes.length === 3) { + assert.deepEqual(sourceAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.frame)), [[1, 3, 5]]); + assert.deepEqual(sourceAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.value[0])), [[1, 3, 5]]); + } + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const clearedSnapshot = snapshot(engine, handle); + const clearedAnimation = clearedSnapshot.animations?.find((value) => value.name === actionName); + assert.ok(clearedAnimation); + assert.deepEqual(clearedAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.frame)), [[1, 5]]); + assert.deepEqual(clearedAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.value[0])), [[1, 5]]); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).animations, clearedSnapshot.animations); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle), clearedSnapshot); + sourceEngine._web_engine_destroy(sourceHandle); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const beforeWasm = { animationId: sourceAnimation.id, targetId: sourceAnimation.targetId, channelPaths: sourceAnimation.channels.map((channel) => channel.path), keyframesPerChannel: sourceAnimation.channels.map((channel) => channel.keyframes.length) }; + const report = { schemaVersion: 1, task, operation: "ANIM_KEYFRAME_DELETE_BUTTON_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, before: desktop.before.action, after: desktop.after.action }, wasm: { status: "EXACT", before: beforeWasm, after: { animationId: clearedAnimation.id, keyframesPerChannel: clearedAnimation.channels.map((channel) => channel.keyframes.length), keyframeDeleted: true } }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00183" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00182/anim-keyframe-delete-button-local-exact-report.json"); + if (beforeWasm.keyframesPerChannel[0] === 3 || !fs.existsSync(reportPath)) fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} channels=${beforeWasm.keyframesPerChannel[0]}->${clearedAnimation.channels[0].keyframes.length} poll=true operator=${desktop.operatorStatus} mainMutation=keyframe_deleted desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00192") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00192-operator-anim.keying_set_export.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00192/anim-keying-set-export-desktop-report.json"); + const exportPath = path.join(root, "tests/golden/M16-GAP-00192/WebGapAnimKeyingSetExportSet.py"); fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const sourceBytes = fs.readFileSync(fixture); const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); const checker = path.join(root, "tools/web/check-action-keying-set-export-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath, exportPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024, timeout: 45_000 }); assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); assert.equal(fs.existsSync(exportPath), true); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); assert.equal(desktop.saveReopen, "EXACT"); assert.equal(desktop.mainMutation, "NONE_EXPORT_ONLY"); assert.equal(desktop.poll, true); assert.equal(desktop.operatorStatus, "FINISHED"); assert.equal(desktop.exportedScript.bytes > 0, true); assert.equal(desktop.before.activeKeyingSet, "WebGapAnimKeyingSetExportSet"); assert.deepEqual(desktop.before, desktop.after); + const exportSha = crypto.createHash("sha256").update(fs.readFileSync(exportPath)).digest("hex"); assert.equal(exportSha, desktop.exportedScript.sha256); + const sourceEngine = await factory({ wasmBinary }); const sourceHandle = sourceEngine._web_engine_create(); open(sourceEngine, sourceHandle, sourceBytes); const sourceSnapshot = snapshot(sourceEngine, sourceHandle); const sourceAnimation = sourceSnapshot.animations?.find((value) => value.name === "WebGapAnimKeyingSetExportAction"); assert.ok(sourceAnimation); + const engine = await factory({ wasmBinary }); const handle = engine._web_engine_create(); open(engine, handle, fs.readFileSync(fixture)); const afterSnapshot = snapshot(engine, handle); assert.deepEqual(afterSnapshot.animations, sourceSnapshot.animations); + const saved = output(engine, handle, engine._web_engine_save_blend, true); const reopened = engine._web_engine_create(); open(engine, reopened, saved); assert.deepEqual(snapshot(engine, reopened).animations, afterSnapshot.animations); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); const pointer = engine._malloc(malformed.byteLength); let result; try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } assert.notEqual(result, 0); assert.deepEqual(snapshot(engine, handle).animations, afterSnapshot.animations); + sourceEngine._web_engine_destroy(sourceHandle); engine._web_engine_destroy(handle); engine._web_engine_destroy(reopened); const beforeWasm = { animationId: sourceAnimation.id, targetId: sourceAnimation.targetId, channelPaths: sourceAnimation.channels.map((channel) => channel.path), keyframesPerChannel: sourceAnimation.channels.map((channel) => channel.keyframes.length) }; + const report = { schemaVersion: 1, task, operation: "ANIM_KEYING_SET_EXPORT_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, before: desktop.before, after: desktop.after, exportedScript: { path: path.relative(root, exportPath).replaceAll(path.sep, "/"), sha256: exportSha, bytes: desktop.exportedScript.bytes } }, wasm: { status: "EXACT", before: beforeWasm, after: { animationId: sourceAnimation.id, keyframesPerChannel: sourceAnimation.channels.map((channel) => channel.keyframes.length), visibleMainUnchanged: true, keyingSetMetadata: "NOT_EXPOSED_BY_SCENE_SNAPSHOT" } }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00193" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00192/anim-keying-set-export-local-exact-report.json"); if (!fs.existsSync(reportPath)) fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); process.stdout.write(`generated-gap-ok task=${task} poll=true operator=${desktop.operatorStatus} mainMutation=none_export_only export=written wasmVisibleMain=unchanged desktop=exact saveReopen=exact next=${report.nextTask}\n`); process.exit(0); +} +if (task === "M16-GAP-00193") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00193-operator-anim.keying_set_path_add.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00193/anim-keying-set-path-add-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const sourceBytes = fs.readFileSync(fixture); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-keying-set-path-add-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024, timeout: 45_000 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.mainMutation, "KEYING_SET_PATH_ADDED"); + assert.equal(desktop.poll, true); + assert.equal(desktop.operatorStatus, "FINISHED"); + assert.equal(desktop.before.pathCount, 0); + assert.equal(desktop.after.pathCount, 1); + assert.deepEqual(desktop.after.paths, [{ dataPath: "", arrayIndex: 0, idType: "OBJECT", group: "", groupMethod: "KEYINGSET", useEntireArray: true }]); + assert.deepEqual(desktop.before.action, desktop.after.action); + const sourceEngine = await factory({ wasmBinary }); + const sourceHandle = sourceEngine._web_engine_create(); + open(sourceEngine, sourceHandle, sourceBytes); + const sourceSnapshot = snapshot(sourceEngine, sourceHandle); + const sourceAnimation = sourceSnapshot.animations?.find((value) => value.name === "WebGapAnimKeyingSetPathAddAction"); + assert.ok(sourceAnimation); + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const afterSnapshot = snapshot(engine, handle); + const afterAnimation = afterSnapshot.animations?.find((value) => value.name === sourceAnimation.name); + assert.deepEqual(afterAnimation, sourceAnimation); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).animations, afterSnapshot.animations); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).animations, afterSnapshot.animations); + sourceEngine._web_engine_destroy(sourceHandle); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const beforeWasm = { animationId: sourceAnimation.id, targetId: sourceAnimation.targetId, channelPaths: sourceAnimation.channels.map((channel) => channel.path), keyframesPerChannel: sourceAnimation.channels.map((channel) => channel.keyframes.length) }; + const report = { schemaVersion: 1, task, operation: "ANIM_KEYING_SET_PATH_ADD_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, before: desktop.before, after: desktop.after }, wasm: { status: "EXACT", before: beforeWasm, after: { animationId: afterAnimation.id, keyframesPerChannel: afterAnimation.channels.map((channel) => channel.keyframes.length), visibleMainUnchanged: true, keyingSetMetadata: "NOT_EXPOSED_BY_SCENE_SNAPSHOT" } }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00194" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00193/anim-keying-set-path-add-local-exact-report.json"); + if (!fs.existsSync(reportPath)) fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} paths=0->1 poll=true operator=${desktop.operatorStatus} mainMutation=keying_set_path_added wasmVisibleMain=unchanged desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00194") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00194-operator-anim.keying_set_path_remove.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00194/anim-keying-set-path-remove-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const sourceBytes = fs.readFileSync(fixture); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-keying-set-path-remove-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024, timeout: 45_000 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.mainMutation, "KEYING_SET_PATH_REMOVED"); + assert.equal(desktop.poll, true); + assert.equal(desktop.operatorStatus, "FINISHED"); + assert.equal(desktop.before.pathCount, 1); + assert.deepEqual(desktop.before.paths, [{ dataPath: '["path_remove_target"]', arrayIndex: 0, idType: "OBJECT", group: "", groupMethod: "KEYINGSET", useEntireArray: false }]); + assert.equal(desktop.after.pathCount, 0); + assert.deepEqual(desktop.after.paths, []); + assert.deepEqual(desktop.before.action, desktop.after.action); + const sourceEngine = await factory({ wasmBinary }); + const sourceHandle = sourceEngine._web_engine_create(); + open(sourceEngine, sourceHandle, sourceBytes); + const sourceSnapshot = snapshot(sourceEngine, sourceHandle); + const sourceAnimation = sourceSnapshot.animations?.find((value) => value.name === "WebGapAnimKeyingSetPathRemoveAction"); + assert.ok(sourceAnimation); + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const afterSnapshot = snapshot(engine, handle); + const afterAnimation = afterSnapshot.animations?.find((value) => value.name === sourceAnimation.name); + assert.deepEqual(afterAnimation, sourceAnimation); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).animations, afterSnapshot.animations); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).animations, afterSnapshot.animations); + sourceEngine._web_engine_destroy(sourceHandle); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const beforeWasm = { animationId: sourceAnimation.id, targetId: sourceAnimation.targetId, channelPaths: sourceAnimation.channels.map((channel) => channel.path), keyframesPerChannel: sourceAnimation.channels.map((channel) => channel.keyframes.length) }; + const report = { schemaVersion: 1, task, operation: "ANIM_KEYING_SET_PATH_REMOVE_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, before: desktop.before, after: desktop.after }, wasm: { status: "EXACT", before: beforeWasm, after: { animationId: afterAnimation.id, keyframesPerChannel: afterAnimation.channels.map((channel) => channel.keyframes.length), visibleMainUnchanged: true, keyingSetMetadata: "NOT_EXPOSED_BY_SCENE_SNAPSHOT" } }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00195" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00194/anim-keying-set-path-remove-local-exact-report.json"); + if (!fs.existsSync(reportPath)) fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} paths=1->0 poll=true operator=${desktop.operatorStatus} mainMutation=keying_set_path_removed wasmVisibleMain=unchanged desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00195") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00195-operator-anim.keying_set_remove.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00195/anim-keying-set-remove-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const sourceBytes = fs.readFileSync(fixture); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-keying-set-remove-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024, timeout: 45_000 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.mainMutation, "KEYING_SET_REMOVED"); + assert.equal(desktop.poll, true); + assert.equal(desktop.operatorStatus, "FINISHED"); + assert.equal(desktop.before.keyingSetCount, 1); + assert.equal(desktop.before.activeKeyingSet, "WebGapAnimKeyingSetRemoveSet"); + assert.equal(desktop.after.keyingSetCount, 0); + assert.equal(desktop.after.activeKeyingSet, null); + assert.deepEqual(desktop.before.action, desktop.after.action); + const sourceEngine = await factory({ wasmBinary }); + const sourceHandle = sourceEngine._web_engine_create(); + open(sourceEngine, sourceHandle, sourceBytes); + const sourceSnapshot = snapshot(sourceEngine, sourceHandle); + const sourceAnimation = sourceSnapshot.animations?.find((value) => value.name === "WebGapAnimKeyingSetRemoveAction"); + assert.ok(sourceAnimation); + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const afterSnapshot = snapshot(engine, handle); + const afterAnimation = afterSnapshot.animations?.find((value) => value.name === sourceAnimation.name); + assert.deepEqual(afterAnimation, sourceAnimation); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).animations, afterSnapshot.animations); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).animations, afterSnapshot.animations); + sourceEngine._web_engine_destroy(sourceHandle); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const beforeWasm = { animationId: sourceAnimation.id, targetId: sourceAnimation.targetId, channelPaths: sourceAnimation.channels.map((channel) => channel.path), keyframesPerChannel: sourceAnimation.channels.map((channel) => channel.keyframes.length) }; + const report = { schemaVersion: 1, task, operation: "ANIM_KEYING_SET_REMOVE_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, before: desktop.before, after: desktop.after }, wasm: { status: "EXACT", before: beforeWasm, after: { animationId: afterAnimation.id, keyframesPerChannel: afterAnimation.channels.map((channel) => channel.keyframes.length), visibleMainUnchanged: true, keyingSetMetadata: "NOT_EXPOSED_BY_SCENE_SNAPSHOT" } }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00196" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00195/anim-keying-set-remove-local-exact-report.json"); + if (!fs.existsSync(reportPath)) fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} keyingSets=1->0 poll=true operator=${desktop.operatorStatus} mainMutation=keying_set_removed wasmVisibleMain=unchanged desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00196") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00196-operator-anim.keyingset_button_add.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00196/anim-keyingset-button-add-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const sourceBytes = fs.readFileSync(fixture); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-keyingset-button-add-desktop.py"); + const run = spawnSync(process.env.XVFB_RUN_BIN ?? "xvfb-run", ["-a", "--server-args=-screen 0 1280x800x24", blender, "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024, timeout: 45_000 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.mainMutation, "KEYING_SET_PATH_ADDED"); + assert.equal(desktop.poll, true); + assert.equal(desktop.operatorStatus, "FINISHED"); + assert.equal(desktop.before.keyingSetCount, 0); + assert.equal(desktop.after.keyingSetCount, 1); + assert.equal(desktop.after.activeKeyingSet, "ButtonKeyingSet"); + assert.deepEqual(desktop.after.paths, [{ dataPath: '["button_target"]', arrayIndex: 0, idType: "OBJECT", group: "", groupMethod: "KEYINGSET", useEntireArray: true }]); + assert.deepEqual(desktop.before.action, desktop.after.action); + const sourceEngine = await factory({ wasmBinary }); + const sourceHandle = sourceEngine._web_engine_create(); + open(sourceEngine, sourceHandle, sourceBytes); + const sourceSnapshot = snapshot(sourceEngine, sourceHandle); + const sourceAnimation = sourceSnapshot.animations?.find((value) => value.name === "WebGapAnimKeyingSetButtonAddAction"); + assert.ok(sourceAnimation); + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const afterSnapshot = snapshot(engine, handle); + const afterAnimation = afterSnapshot.animations?.find((value) => value.name === sourceAnimation.name); + assert.deepEqual(afterAnimation, sourceAnimation); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).animations, afterSnapshot.animations); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).animations, afterSnapshot.animations); + sourceEngine._web_engine_destroy(sourceHandle); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const beforeWasm = { animationId: sourceAnimation.id, targetId: sourceAnimation.targetId, channelPaths: sourceAnimation.channels.map((channel) => channel.path), keyframesPerChannel: sourceAnimation.channels.map((channel) => channel.keyframes.length) }; + const report = { schemaVersion: 1, task, operation: "ANIM_KEYINGSET_BUTTON_ADD_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, before: desktop.before, after: desktop.after }, wasm: { status: "EXACT", before: beforeWasm, after: { animationId: afterAnimation.id, keyframesPerChannel: afterAnimation.channels.map((channel) => channel.keyframes.length), visibleMainUnchanged: true, keyingSetMetadata: "NOT_EXPOSED_BY_SCENE_SNAPSHOT" } }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00197" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00196/anim-keyingset-button-add-local-exact-report.json"); + if (!fs.existsSync(reportPath)) fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} keyingSets=0->1 paths=0->1 poll=true operator=${desktop.operatorStatus} mainMutation=keying_set_path_added wasmVisibleMain=unchanged desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00197") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00197-operator-anim.keyingset_button_remove.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00197/anim-keyingset-button-remove-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const sourceBytes = fs.readFileSync(fixture); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-keyingset-button-remove-desktop.py"); + const run = spawnSync(process.env.XVFB_RUN_BIN ?? "xvfb-run", ["-a", "--server-args=-screen 0 1280x800x24", blender, "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024, timeout: 45_000 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.mainMutation, "KEYING_SET_PATH_REMOVED"); + assert.equal(desktop.poll, true); + assert.equal(desktop.operatorStatus, "FINISHED"); + assert.equal(desktop.before.keyingSetCount, 1); + assert.equal(desktop.before.activeKeyingSet, "ButtonKeyingSet"); + assert.deepEqual(desktop.before.paths, [{ dataPath: '["button_remove_target"]', arrayIndex: 0, idType: "OBJECT", group: "", groupMethod: "KEYINGSET", useEntireArray: false }]); + assert.equal(desktop.after.keyingSetCount, 1); + assert.equal(desktop.after.activeKeyingSet, "ButtonKeyingSet"); + assert.deepEqual(desktop.after.paths, []); + assert.deepEqual(desktop.before.action, desktop.after.action); + const sourceEngine = await factory({ wasmBinary }); + const sourceHandle = sourceEngine._web_engine_create(); + open(sourceEngine, sourceHandle, sourceBytes); + const sourceSnapshot = snapshot(sourceEngine, sourceHandle); + const sourceAnimation = sourceSnapshot.animations?.find((value) => value.name === "WebGapAnimKeyingSetButtonRemoveAction"); + assert.ok(sourceAnimation); + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const afterSnapshot = snapshot(engine, handle); + const afterAnimation = afterSnapshot.animations?.find((value) => value.name === sourceAnimation.name); + assert.deepEqual(afterAnimation, sourceAnimation); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).animations, afterSnapshot.animations); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).animations, afterSnapshot.animations); + sourceEngine._web_engine_destroy(sourceHandle); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const beforeWasm = { animationId: sourceAnimation.id, targetId: sourceAnimation.targetId, channelPaths: sourceAnimation.channels.map((channel) => channel.path), keyframesPerChannel: sourceAnimation.channels.map((channel) => channel.keyframes.length) }; + const report = { schemaVersion: 1, task, operation: "ANIM_KEYINGSET_BUTTON_REMOVE_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, before: desktop.before, after: desktop.after }, wasm: { status: "EXACT", before: beforeWasm, after: { animationId: afterAnimation.id, keyframesPerChannel: afterAnimation.channels.map((channel) => channel.keyframes.length), visibleMainUnchanged: true, keyingSetMetadata: "NOT_EXPOSED_BY_SCENE_SNAPSHOT" } }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00198" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00197/anim-keyingset-button-remove-local-exact-report.json"); + if (!fs.existsSync(reportPath)) fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} keyingSets=1 paths=1->0 poll=true operator=${desktop.operatorStatus} mainMutation=keying_set_path_removed wasmVisibleMain=unchanged desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00198") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00198-operator-anim.merge_animation.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00198/anim-merge-animation-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const sourceBytes = fs.readFileSync(fixture); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-merge-animation-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024, timeout: 45_000 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.mainMutation, "ANIMATION_MERGED"); + assert.equal(desktop.poll, true); + assert.equal(desktop.operatorStatus, "FINISHED"); + assert.equal(desktop.before.activeObjectAction.name, "WebGapAnimMergeActiveAction"); + assert.equal(desktop.before.sourceObjectAction.name, "WebGapAnimMergeSourceAction"); + assert.equal(desktop.after.activeObjectAction.name, "WebGapAnimMergeActiveAction"); + assert.equal(desktop.after.sourceObjectAction.name, "WebGapAnimMergeActiveAction"); + assert.deepEqual(desktop.after.activeObjectAction.channels.map((channel) => channel.path), ["[\"active_merge_target\"]", "[\"source_merge_target\"]"]); + assert.deepEqual(desktop.after.sourceObjectAction.channels.map((channel) => channel.path), ["[\"active_merge_target\"]", "[\"source_merge_target\"]"]); + + const sourceEngine = await factory({ wasmBinary }); + const sourceHandle = sourceEngine._web_engine_create(); + open(sourceEngine, sourceHandle, sourceBytes); + const sourceSnapshot = snapshot(sourceEngine, sourceHandle); + const sourceActiveAnimation = sourceSnapshot.animations?.find((value) => value.targetId === "object:WebGapAnimMergeActiveObject"); + const sourceObjectAnimation = sourceSnapshot.animations?.find((value) => value.targetId === "object:WebGapAnimMergeSourceObject"); + assert.ok(sourceActiveAnimation); + assert.ok(sourceObjectAnimation); + const sourceWasUnmerged = sourceObjectAnimation.name === "WebGapAnimMergeSourceAction"; + if (sourceWasUnmerged) { + assert.equal(sourceActiveAnimation.name, "WebGapAnimMergeActiveAction"); + assert.deepEqual(sourceActiveAnimation.channels.map((channel) => channel.path), ["[\"active_merge_target\"][0]"]); + assert.deepEqual(sourceObjectAnimation.channels.map((channel) => channel.path), ["[\"source_merge_target\"][0]"]); + assert.deepEqual(sourceActiveAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.frame)), [[1, 3, 5]]); + assert.deepEqual(sourceObjectAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.frame)), [[1, 3, 5]]); + } + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const mergedSnapshot = snapshot(engine, handle); + assert.equal(mergedSnapshot.activeObjectId, "object:WebGapAnimMergeActiveObject"); + const mergedAnimations = mergedSnapshot.animations?.filter((value) => value.name === "WebGapAnimMergeActiveAction"); + assert.equal(mergedAnimations?.length, 2); + assert.equal(mergedSnapshot.animations?.some((value) => value.name === "WebGapAnimMergeSourceAction"), false); + const mergedActiveAnimation = mergedAnimations.find((value) => value.targetId === "object:WebGapAnimMergeActiveObject"); + const mergedSourceAnimation = mergedAnimations.find((value) => value.targetId === "object:WebGapAnimMergeSourceObject"); + assert.ok(mergedActiveAnimation); + assert.ok(mergedSourceAnimation); + const mergedPaths = ["[\"active_merge_target\"][0]", "[\"source_merge_target\"][0]"]; + assert.deepEqual(mergedActiveAnimation.channels.map((channel) => channel.path), mergedPaths); + assert.deepEqual(mergedSourceAnimation.channels.map((channel) => channel.path), mergedPaths); + assert.deepEqual(mergedActiveAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.frame)), [[1, 3, 5], [1, 3, 5]]); + assert.deepEqual(mergedSourceAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.value[0])), [[1, 3, 5], [10, 30, 50]]); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).animations, mergedSnapshot.animations); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).animations, mergedSnapshot.animations); + const beforeWasm = sourceWasUnmerged ? { + activeAnimationId: sourceActiveAnimation.id, + sourceAnimationId: sourceObjectAnimation.id, + activeChannelPaths: sourceActiveAnimation.channels.map((channel) => channel.path), + sourceChannelPaths: sourceObjectAnimation.channels.map((channel) => channel.path), + keyframesPerChannel: [sourceActiveAnimation.channels[0].keyframes.length, sourceObjectAnimation.channels[0].keyframes.length], + } : { evidenceStatus: "PRESERVED_DESKTOP_REPORT", activeAnimationId: sourceActiveAnimation.id, sourceAnimationId: sourceObjectAnimation.id }; + const afterWasm = { + activeAnimationId: mergedActiveAnimation.id, + sourceAnimationId: mergedSourceAnimation.id, + channelPaths: mergedPaths, + keyframesPerChannel: mergedActiveAnimation.channels.map((channel) => channel.keyframes.length), + sourceValues: mergedSourceAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.value[0])), + }; + sourceEngine._web_engine_destroy(sourceHandle); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ANIM_MERGE_ANIMATION_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, before: desktop.before, after: desktop.after }, wasm: { status: "EXACT", before: beforeWasm, after: afterWasm, sourceActionRemoved: true }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00199" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00198/anim-merge-animation-local-exact-report.json"); + if (sourceWasUnmerged || !fs.existsSync(reportPath)) fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} actions=2->1 channels=1+1->2 poll=true operator=${desktop.operatorStatus} mainMutation=animation_merged desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00191") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00191-operator-anim.keying_set_add.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00191/anim-keying-set-add-desktop-report.json"); fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const sourceBytes = fs.readFileSync(fixture); const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); const checker = path.join(root, "tools/web/check-action-keying-set-add-desktop.py"); + const run = spawnSync(process.env.XVFB_RUN_BIN ?? "xvfb-run", ["-a", "--server-args=-screen 0 1280x800x24", blender, "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024, timeout: 45_000 }); assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); assert.equal(desktop.saveReopen, "EXACT"); assert.equal(desktop.mainMutation, "KEYING_SET_ADDED"); assert.equal(desktop.poll, true); assert.equal(desktop.operatorStatus, "FINISHED"); assert.equal(desktop.before.keyingSetCount, 0); assert.equal(desktop.after.keyingSetCount, 1); assert.deepEqual(desktop.before.action, desktop.after.action); + const sourceEngine = await factory({ wasmBinary }); const sourceHandle = sourceEngine._web_engine_create(); open(sourceEngine, sourceHandle, sourceBytes); const sourceSnapshot = snapshot(sourceEngine, sourceHandle); const sourceAnimation = sourceSnapshot.animations?.find((value) => value.name === "WebGapAnimKeyingSetAddAction"); assert.ok(sourceAnimation); + const engine = await factory({ wasmBinary }); const handle = engine._web_engine_create(); open(engine, handle, fs.readFileSync(fixture)); const afterSnapshot = snapshot(engine, handle); const afterAnimation = afterSnapshot.animations?.find((value) => value.name === sourceAnimation.name); assert.deepEqual(afterAnimation, sourceAnimation); + const saved = output(engine, handle, engine._web_engine_save_blend, true); const reopened = engine._web_engine_create(); open(engine, reopened, saved); assert.deepEqual(snapshot(engine, reopened).animations, afterSnapshot.animations); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); const pointer = engine._malloc(malformed.byteLength); let result; try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } assert.notEqual(result, 0); assert.deepEqual(snapshot(engine, handle).animations, afterSnapshot.animations); + sourceEngine._web_engine_destroy(sourceHandle); engine._web_engine_destroy(handle); engine._web_engine_destroy(reopened); const beforeWasm = { animationId: sourceAnimation.id, targetId: sourceAnimation.targetId, channelPaths: sourceAnimation.channels.map((channel) => channel.path), keyframesPerChannel: sourceAnimation.channels.map((channel) => channel.keyframes.length) }; + const report = { schemaVersion: 1, task, operation: "ANIM_KEYING_SET_ADD_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, before: desktop.before, after: desktop.after }, wasm: { status: "EXACT", before: beforeWasm, after: { animationId: afterAnimation.id, keyframesPerChannel: afterAnimation.channels.map((channel) => channel.keyframes.length), visibleMainUnchanged: true, keyingSetMetadata: "NOT_EXPOSED_BY_SCENE_SNAPSHOT" } }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00192" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00191/anim-keying-set-add-local-exact-report.json"); if (!fs.existsSync(reportPath)) fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); process.stdout.write(`generated-gap-ok task=${task} keyingSets=0->1 poll=true operator=${desktop.operatorStatus} mainMutation=keying_set_added wasmVisibleMain=unchanged desktop=exact saveReopen=exact next=${report.nextTask}\n`); process.exit(0); +} +if (task === "M16-GAP-00190") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00190-operator-anim.keying_set_active_set.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00190/anim-keying-set-active-set-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const sourceBytes = fs.readFileSync(fixture); const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); const checker = path.join(root, "tools/web/check-action-keying-set-active-set-desktop.py"); + const run = spawnSync(process.env.XVFB_RUN_BIN ?? "xvfb-run", ["-a", "--server-args=-screen 0 1280x800x24", blender, "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024, timeout: 45_000 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); assert.equal(desktop.saveReopen, "EXACT"); assert.equal(desktop.mainMutation, "ACTIVE_KEYING_SET_CHANGED"); assert.equal(desktop.poll, true); assert.equal(desktop.operatorStatus, "FINISHED"); assert.equal(desktop.before.activeKeyingSet, "WebGapAnimKeyingSetActiveA"); assert.equal(desktop.after.activeKeyingSet, "WebGapAnimKeyingSetActiveB"); + assert.deepEqual(desktop.before.action, desktop.after.action); + const sourceEngine = await factory({ wasmBinary }); const sourceHandle = sourceEngine._web_engine_create(); open(sourceEngine, sourceHandle, sourceBytes); const sourceSnapshot = snapshot(sourceEngine, sourceHandle); const sourceAnimation = sourceSnapshot.animations?.find((value) => value.name === "WebGapAnimKeyingSetActiveAction"); assert.ok(sourceAnimation); + const engine = await factory({ wasmBinary }); const handle = engine._web_engine_create(); open(engine, handle, fs.readFileSync(fixture)); const afterSnapshot = snapshot(engine, handle); const afterAnimation = afterSnapshot.animations?.find((value) => value.name === sourceAnimation.name); assert.deepEqual(afterAnimation, sourceAnimation); + const saved = output(engine, handle, engine._web_engine_save_blend, true); const reopened = engine._web_engine_create(); open(engine, reopened, saved); assert.deepEqual(snapshot(engine, reopened).animations, afterSnapshot.animations); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); const pointer = engine._malloc(malformed.byteLength); let result; try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } assert.notEqual(result, 0); assert.deepEqual(snapshot(engine, handle).animations, afterSnapshot.animations); + sourceEngine._web_engine_destroy(sourceHandle); engine._web_engine_destroy(handle); engine._web_engine_destroy(reopened); + const beforeWasm = { animationId: sourceAnimation.id, targetId: sourceAnimation.targetId, channelPaths: sourceAnimation.channels.map((channel) => channel.path), keyframesPerChannel: sourceAnimation.channels.map((channel) => channel.keyframes.length) }; + const report = { schemaVersion: 1, task, operation: "ANIM_KEYING_SET_ACTIVE_SET_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, before: desktop.before, after: desktop.after }, wasm: { status: "EXACT", before: beforeWasm, after: { animationId: afterAnimation.id, keyframesPerChannel: afterAnimation.channels.map((channel) => channel.keyframes.length), visibleMainUnchanged: true, keyingSetMetadata: "NOT_EXPOSED_BY_SCENE_SNAPSHOT" } }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00191" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00190/anim-keying-set-active-set-local-exact-report.json"); if (!fs.existsSync(reportPath)) fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} active=A->B poll=true operator=${desktop.operatorStatus} mainMutation=active_keying_set_changed wasmVisibleMain=unchanged desktop=exact saveReopen=exact next=${report.nextTask}\n`); process.exit(0); +} +if (task === "M16-GAP-00189") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00189-operator-anim.keyframe_insert_menu.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00189/anim-keyframe-insert-menu-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const sourceBytes = fs.readFileSync(fixture); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-keyframe-insert-menu-desktop.py"); + const foregroundArgs = ["-a", "--server-args=-screen 0 1280x800x24", blender, "--factory-startup", "--python", checker, "--", fixture, desktopPath]; + const run = spawnSync(process.env.XVFB_RUN_BIN ?? "xvfb-run", foregroundArgs, { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024, timeout: 45_000 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + const actionName = "WebGapAnimKeyframeInsertMenuAction"; + const expectedBefore = { name: actionName, channels: [{ path: '["insert_target"]', index: 0, frames: [1, 5], values: [1, 5], selected: [true, true] }] }; + const expectedAfter = { name: actionName, channels: [{ path: '["insert_target"]', index: 0, frames: [1, 3, 5], values: [1, 3, 5], selected: [false, true, false] }] }; + assert.equal(desktop.saveReopen, "EXACT"); assert.equal(desktop.mainMutation, "KEYFRAME_INSERTED"); assert.equal(desktop.poll, true); assert.equal(desktop.operatorStatus, "FINISHED"); + assert.deepEqual(desktop.before.action, expectedBefore); assert.deepEqual(desktop.after.action, expectedAfter); assert.equal(desktop.before.activeKeyingSet, "WebGapAnimKeyframeInsertMenuSet"); + const sourceEngine = await factory({ wasmBinary }); const sourceHandle = sourceEngine._web_engine_create(); open(sourceEngine, sourceHandle, sourceBytes); + const sourceSnapshot = snapshot(sourceEngine, sourceHandle); const sourceAnimation = sourceSnapshot.animations?.find((value) => value.name === actionName); assert.ok(sourceAnimation); + assert.equal(sourceAnimation.targetId, "object:WebGapAnimKeyframeInsertMenuObject"); assert.deepEqual(sourceAnimation.channels.map((channel) => channel.path), ['["insert_target"][0]']); assert.ok([2, 3].includes(sourceAnimation.channels[0].keyframes.length)); + if (sourceAnimation.channels[0].keyframes.length === 2) assert.deepEqual(sourceAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.frame)), [[1, 5]]); + const engine = await factory({ wasmBinary }); const handle = engine._web_engine_create(); open(engine, handle, fs.readFileSync(fixture)); + const insertedSnapshot = snapshot(engine, handle); const insertedAnimation = insertedSnapshot.animations?.find((value) => value.name === actionName); assert.ok(insertedAnimation); + assert.deepEqual(insertedAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.frame)), [[1, 3, 5]]); assert.deepEqual(insertedAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.value[0])), [[1, 3, 5]]); + const saved = output(engine, handle, engine._web_engine_save_blend, true); const reopened = engine._web_engine_create(); open(engine, reopened, saved); assert.deepEqual(snapshot(engine, reopened).animations, insertedSnapshot.animations); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); const pointer = engine._malloc(malformed.byteLength); let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); assert.deepEqual(snapshot(engine, handle), insertedSnapshot); sourceEngine._web_engine_destroy(sourceHandle); engine._web_engine_destroy(handle); engine._web_engine_destroy(reopened); + const beforeWasm = { animationId: sourceAnimation.id, targetId: sourceAnimation.targetId, channelPaths: sourceAnimation.channels.map((channel) => channel.path), keyframesPerChannel: sourceAnimation.channels.map((channel) => channel.keyframes.length) }; + const report = { schemaVersion: 1, task, operation: "ANIM_KEYFRAME_INSERT_MENU_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, before: desktop.before.action, after: desktop.after.action }, wasm: { status: "EXACT", before: beforeWasm, after: { animationId: insertedAnimation.id, keyframesPerChannel: insertedAnimation.channels.map((channel) => channel.keyframes.length), keyframeInserted: true } }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00190" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00189/anim-keyframe-insert-menu-local-exact-report.json"); if (beforeWasm.keyframesPerChannel[0] === 2 || !fs.existsSync(reportPath)) fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} channels=${beforeWasm.keyframesPerChannel[0]}->${insertedAnimation.channels[0].keyframes.length} poll=true operator=${desktop.operatorStatus} mainMutation=keyframe_inserted desktop=exact saveReopen=exact next=${report.nextTask}\n`); process.exit(0); +} +if (task === "M16-GAP-00188") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00188-operator-anim.keyframe_insert_by_name.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00188/anim-keyframe-insert-by-name-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const sourceBytes = fs.readFileSync(fixture); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-keyframe-insert-by-name-desktop.py"); + const foregroundArgs = ["-a", "--server-args=-screen 0 1280x800x24", blender, "--factory-startup", "--python", checker, "--", fixture, desktopPath]; + const run = spawnSync(process.env.XVFB_RUN_BIN ?? "xvfb-run", foregroundArgs, { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024, timeout: 45_000 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + const actionName = "WebGapAnimKeyframeInsertByNameAction"; + const expectedBefore = { name: actionName, channels: [{ path: '["insert_target"]', index: 0, frames: [1, 5], values: [1, 5], selected: [true, true] }] }; + const expectedAfter = { name: actionName, channels: [{ path: '["insert_target"]', index: 0, frames: [1, 3, 5], values: [1, 3, 5], selected: [false, true, false] }] }; + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.mainMutation, "KEYFRAME_INSERTED"); + assert.equal(desktop.poll, true); + assert.equal(desktop.operatorStatus, "FINISHED"); + assert.deepEqual(desktop.before.action, expectedBefore); + assert.deepEqual(desktop.after.action, expectedAfter); + assert.equal(desktop.before.activeKeyingSet, "WebGapAnimKeyframeInsertByNameSet"); + const sourceEngine = await factory({ wasmBinary }); + const sourceHandle = sourceEngine._web_engine_create(); + open(sourceEngine, sourceHandle, sourceBytes); + const sourceSnapshot = snapshot(sourceEngine, sourceHandle); + const sourceAnimation = sourceSnapshot.animations?.find((value) => value.name === actionName); + assert.ok(sourceAnimation); + assert.equal(sourceAnimation.targetId, "object:WebGapAnimKeyframeInsertByNameObject"); + assert.deepEqual(sourceAnimation.channels.map((channel) => channel.path), ['["insert_target"][0]']); + assert.ok([2, 3].includes(sourceAnimation.channels[0].keyframes.length)); + if (sourceAnimation.channels[0].keyframes.length === 2) assert.deepEqual(sourceAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.frame)), [[1, 5]]); + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const insertedSnapshot = snapshot(engine, handle); + const insertedAnimation = insertedSnapshot.animations?.find((value) => value.name === actionName); + assert.ok(insertedAnimation); + assert.deepEqual(insertedAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.frame)), [[1, 3, 5]]); + assert.deepEqual(insertedAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.value[0])), [[1, 3, 5]]); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).animations, insertedSnapshot.animations); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); assert.deepEqual(snapshot(engine, handle), insertedSnapshot); + sourceEngine._web_engine_destroy(sourceHandle); engine._web_engine_destroy(handle); engine._web_engine_destroy(reopened); + const beforeWasm = { animationId: sourceAnimation.id, targetId: sourceAnimation.targetId, channelPaths: sourceAnimation.channels.map((channel) => channel.path), keyframesPerChannel: sourceAnimation.channels.map((channel) => channel.keyframes.length) }; + const report = { schemaVersion: 1, task, operation: "ANIM_KEYFRAME_INSERT_BY_NAME_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, before: desktop.before.action, after: desktop.after.action }, wasm: { status: "EXACT", before: beforeWasm, after: { animationId: insertedAnimation.id, keyframesPerChannel: insertedAnimation.channels.map((channel) => channel.keyframes.length), keyframeInserted: true } }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00189" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00188/anim-keyframe-insert-by-name-local-exact-report.json"); + if (beforeWasm.keyframesPerChannel[0] === 2 || !fs.existsSync(reportPath)) fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} channels=${beforeWasm.keyframesPerChannel[0]}->${insertedAnimation.channels[0].keyframes.length} poll=true operator=${desktop.operatorStatus} mainMutation=keyframe_inserted desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00187") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00187-operator-anim.keyframe_insert_button.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00187/anim-keyframe-insert-button-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const sourceBytes = fs.readFileSync(fixture); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-keyframe-insert-button-desktop.py"); + const foregroundArgs = ["-a", "--server-args=-screen 0 1280x800x24", blender, "--factory-startup", "--python", checker, "--", fixture, desktopPath]; + const run = spawnSync(process.env.XVFB_RUN_BIN ?? "xvfb-run", foregroundArgs, { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024, timeout: 45_000 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + const actionName = "WebGapAnimKeyframeInsertButtonAction"; + const expectedBefore = { name: actionName, channels: [{ path: '["insert_target"]', index: 0, frames: [1, 5], values: [1, 5], selected: [true, true] }] }; + const expectedAfter = { name: actionName, channels: [{ path: '["insert_target"]', index: 0, frames: [1, 3, 5], values: [1, 3, 5], selected: [false, true, false] }] }; + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.mainMutation, "KEYFRAME_INSERTED"); + assert.equal(desktop.poll, true); + assert.equal(desktop.operatorStatus, "FINISHED"); + assert.deepEqual(desktop.before.action, expectedBefore); + assert.deepEqual(desktop.after.action, expectedAfter); + + const sourceEngine = await factory({ wasmBinary }); + const sourceHandle = sourceEngine._web_engine_create(); + open(sourceEngine, sourceHandle, sourceBytes); + const sourceSnapshot = snapshot(sourceEngine, sourceHandle); + const sourceAnimation = sourceSnapshot.animations?.find((value) => value.name === actionName); + assert.ok(sourceAnimation); + assert.equal(sourceAnimation.targetId, "object:WebGapAnimKeyframeInsertButtonObject"); + assert.deepEqual(sourceAnimation.channels.map((channel) => channel.path), ['["insert_target"][0]']); + assert.ok([2, 3].includes(sourceAnimation.channels[0].keyframes.length)); + if (sourceAnimation.channels[0].keyframes.length === 2) { + assert.deepEqual(sourceAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.frame)), [[1, 5]]); + } + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const insertedSnapshot = snapshot(engine, handle); + const insertedAnimation = insertedSnapshot.animations?.find((value) => value.name === actionName); + assert.ok(insertedAnimation); + assert.deepEqual(insertedAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.frame)), [[1, 3, 5]]); + assert.deepEqual(insertedAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.value[0])), [[1, 3, 5]]); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).animations, insertedSnapshot.animations); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle), insertedSnapshot); + sourceEngine._web_engine_destroy(sourceHandle); engine._web_engine_destroy(handle); engine._web_engine_destroy(reopened); + const beforeWasm = { animationId: sourceAnimation.id, targetId: sourceAnimation.targetId, channelPaths: sourceAnimation.channels.map((channel) => channel.path), keyframesPerChannel: sourceAnimation.channels.map((channel) => channel.keyframes.length) }; + const report = { schemaVersion: 1, task, operation: "ANIM_KEYFRAME_INSERT_BUTTON_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, before: desktop.before.action, after: desktop.after.action }, wasm: { status: "EXACT", before: beforeWasm, after: { animationId: insertedAnimation.id, keyframesPerChannel: insertedAnimation.channels.map((channel) => channel.keyframes.length), keyframeInserted: true } }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00188" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00187/anim-keyframe-insert-button-local-exact-report.json"); + if (beforeWasm.keyframesPerChannel[0] === 2 || !fs.existsSync(reportPath)) fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} channels=${beforeWasm.keyframesPerChannel[0]}->${insertedAnimation.channels[0].keyframes.length} poll=true operator=${desktop.operatorStatus} mainMutation=keyframe_inserted desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00186") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00186-operator-anim.keyframe_insert.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00186/anim-keyframe-insert-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const sourceBytes = fs.readFileSync(fixture); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-keyframe-insert-desktop.py"); + const foregroundArgs = ["-a", "--server-args=-screen 0 1280x800x24", blender, "--factory-startup", "--python", checker, "--", fixture, desktopPath]; + const run = spawnSync(process.env.XVFB_RUN_BIN ?? "xvfb-run", foregroundArgs, { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024, timeout: 45_000 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + const actionName = "WebGapAnimKeyframeInsertAction"; + const expectedBefore = { + name: actionName, + channels: [{ path: '["insert_target"]', index: 0, frames: [1, 5], values: [1, 5], selected: [true, true] }], + }; + const expectedAfter = { + name: actionName, + channels: [{ path: '["insert_target"]', index: 0, frames: [1, 3, 5], values: [1, 3, 5], selected: [false, true, false] }], + }; + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.mainMutation, "KEYFRAME_INSERTED"); + assert.equal(desktop.poll, true); + assert.equal(desktop.operatorStatus, "FINISHED"); + assert.deepEqual(desktop.before.action, expectedBefore); + assert.deepEqual(desktop.after.action, expectedAfter); + assert.equal(desktop.before.activeKeyingSet, "WebGapAnimKeyframeInsertSet"); + + const sourceEngine = await factory({ wasmBinary }); + const sourceHandle = sourceEngine._web_engine_create(); + open(sourceEngine, sourceHandle, sourceBytes); + const sourceSnapshot = snapshot(sourceEngine, sourceHandle); + const sourceAnimation = sourceSnapshot.animations?.find((value) => value.name === actionName); + assert.ok(sourceAnimation); + assert.equal(sourceAnimation.targetId, "object:WebGapAnimKeyframeInsertObject"); + assert.deepEqual(sourceAnimation.channels.map((channel) => channel.path), ['["insert_target"][0]']); + assert.ok([2, 3].includes(sourceAnimation.channels[0].keyframes.length)); + if (sourceAnimation.channels[0].keyframes.length === 2) { + assert.deepEqual(sourceAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.frame)), [[1, 5]]); + assert.deepEqual(sourceAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.value[0])), [[1, 5]]); + } + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const insertedSnapshot = snapshot(engine, handle); + const insertedAnimation = insertedSnapshot.animations?.find((value) => value.name === actionName); + assert.ok(insertedAnimation); + assert.deepEqual(insertedAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.frame)), [[1, 3, 5]]); + assert.deepEqual(insertedAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.value[0])), [[1, 3, 5]]); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).animations, insertedSnapshot.animations); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle), insertedSnapshot); + sourceEngine._web_engine_destroy(sourceHandle); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const beforeWasm = { animationId: sourceAnimation.id, targetId: sourceAnimation.targetId, channelPaths: sourceAnimation.channels.map((channel) => channel.path), keyframesPerChannel: sourceAnimation.channels.map((channel) => channel.keyframes.length) }; + const report = { schemaVersion: 1, task, operation: "ANIM_KEYFRAME_INSERT_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, before: desktop.before.action, after: desktop.after.action }, wasm: { status: "EXACT", before: beforeWasm, after: { animationId: insertedAnimation.id, keyframesPerChannel: insertedAnimation.channels.map((channel) => channel.keyframes.length), keyframeInserted: true } }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00187" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00186/anim-keyframe-insert-local-exact-report.json"); + if (beforeWasm.keyframesPerChannel[0] === 2 || !fs.existsSync(reportPath)) fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} channels=${beforeWasm.keyframesPerChannel[0]}->${insertedAnimation.channels[0].keyframes.length} poll=true operator=${desktop.operatorStatus} mainMutation=keyframe_inserted desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00185") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00185-operator-anim.keyframe_delete_vse.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00185/anim-keyframe-delete-vse-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const sourceBytes = fs.readFileSync(fixture); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-keyframe-delete-vse-desktop.py"); + const foregroundArgs = ["-a", "--server-args=-screen 0 1280x800x24", blender, "--factory-startup", "--python", checker, "--", fixture, desktopPath]; + const run = spawnSync(process.env.XVFB_RUN_BIN ?? "xvfb-run", foregroundArgs, { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024, timeout: 45_000 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + const actionName = "WebGapAnimKeyframeDeleteVSEAction"; + const desktopChannelPath = 'sequence_editor.strips_all["WebGapAnimKeyframeDeleteVSEStrip"].blend_alpha'; + const channelPath = `${desktopChannelPath}[0]`; + const expectedBefore = { + name: actionName, + channels: [{ path: desktopChannelPath, index: 0, frames: [1, 3, 5], values: [0.25, 0.5, 0.75], selected: [true, true, true] }], + }; + const expectedAfter = { + name: actionName, + channels: [{ path: desktopChannelPath, index: 0, frames: [1, 5], values: [0.25, 0.75], selected: [true, true] }], + }; + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.mainMutation, "KEYFRAME_DELETED"); + assert.equal(desktop.poll, true); + assert.equal(desktop.operatorStatus, "FINISHED"); + assert.deepEqual(desktop.before.action, expectedBefore); + assert.deepEqual(desktop.after.action, expectedAfter); + assert.equal(desktop.before.active, true); + assert.equal(desktop.before.selected, true); + + const sourceEngine = await factory({ wasmBinary }); + const sourceHandle = sourceEngine._web_engine_create(); + open(sourceEngine, sourceHandle, sourceBytes); + const sourceSnapshot = snapshot(sourceEngine, sourceHandle); + const sourceAnimation = sourceSnapshot.animations?.find((value) => value.name === actionName); + assert.ok(sourceAnimation); + assert.equal(sourceAnimation.targetId, "scene:Scene"); + assert.deepEqual(sourceAnimation.channels.map((channel) => channel.path), [channelPath]); + assert.ok([2, 3].includes(sourceAnimation.channels[0].keyframes.length)); + if (sourceAnimation.channels[0].keyframes.length === 3) { + assert.deepEqual(sourceAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.frame)), [[1, 3, 5]]); + assert.deepEqual(sourceAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.value[0])), [[0.25, 0.5, 0.75]]); + } + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const clearedSnapshot = snapshot(engine, handle); + const clearedAnimation = clearedSnapshot.animations?.find((value) => value.name === actionName); + assert.ok(clearedAnimation); + assert.deepEqual(clearedAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.frame)), [[1, 5]]); + assert.deepEqual(clearedAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.value[0])), [[0.25, 0.75]]); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).animations, clearedSnapshot.animations); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle), clearedSnapshot); + sourceEngine._web_engine_destroy(sourceHandle); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const beforeWasm = { animationId: sourceAnimation.id, targetId: sourceAnimation.targetId, channelPaths: sourceAnimation.channels.map((channel) => channel.path), keyframesPerChannel: sourceAnimation.channels.map((channel) => channel.keyframes.length) }; + const report = { schemaVersion: 1, task, operation: "ANIM_KEYFRAME_DELETE_VSE_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, before: desktop.before.action, after: desktop.after.action }, wasm: { status: "EXACT", before: beforeWasm, after: { animationId: clearedAnimation.id, keyframesPerChannel: clearedAnimation.channels.map((channel) => channel.keyframes.length), keyframeDeleted: true } }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00186" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00185/anim-keyframe-delete-vse-local-exact-report.json"); + if (beforeWasm.keyframesPerChannel[0] === 3 || !fs.existsSync(reportPath)) fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} channels=${beforeWasm.keyframesPerChannel[0]}->${clearedAnimation.channels[0].keyframes.length} poll=true operator=${desktop.operatorStatus} mainMutation=keyframe_deleted desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00184") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00184-operator-anim.keyframe_delete_v3d.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00184/anim-keyframe-delete-v3d-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const sourceBytes = fs.readFileSync(fixture); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-keyframe-delete-v3d-desktop.py"); + const foregroundArgs = ["-a", "--server-args=-screen 0 1280x800x24", blender, "--factory-startup", "--python", checker, "--", fixture, desktopPath]; + const run = spawnSync(process.env.XVFB_RUN_BIN ?? "xvfb-run", foregroundArgs, { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024, timeout: 45_000 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + const actionName = "WebGapAnimKeyframeDeleteV3DAction"; + const expectedBefore = { + name: actionName, + channels: [{ path: '["delete_target"]', index: 0, frames: [1, 3, 5], values: [1, 3, 5], selected: [true, true, true] }], + }; + const expectedAfter = { + name: actionName, + channels: [{ path: '["delete_target"]', index: 0, frames: [1, 5], values: [1, 5], selected: [true, true] }], + }; + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.mainMutation, "KEYFRAME_DELETED"); + assert.equal(desktop.poll, true); + assert.equal(desktop.operatorStatus, "FINISHED"); + assert.deepEqual(desktop.before.action, expectedBefore); + assert.deepEqual(desktop.after.action, expectedAfter); + + const sourceEngine = await factory({ wasmBinary }); + const sourceHandle = sourceEngine._web_engine_create(); + open(sourceEngine, sourceHandle, sourceBytes); + const sourceSnapshot = snapshot(sourceEngine, sourceHandle); + const sourceAnimation = sourceSnapshot.animations?.find((value) => value.name === actionName); + assert.ok(sourceAnimation); + assert.equal(sourceAnimation.targetId, "object:WebGapAnimKeyframeDeleteV3DObject"); + assert.deepEqual(sourceAnimation.channels.map((channel) => channel.path), ['["delete_target"][0]']); + assert.ok([2, 3].includes(sourceAnimation.channels[0].keyframes.length)); + if (sourceAnimation.channels[0].keyframes.length === 3) { + assert.deepEqual(sourceAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.frame)), [[1, 3, 5]]); + assert.deepEqual(sourceAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.value[0])), [[1, 3, 5]]); + } + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const clearedSnapshot = snapshot(engine, handle); + const clearedAnimation = clearedSnapshot.animations?.find((value) => value.name === actionName); + assert.ok(clearedAnimation); + assert.deepEqual(clearedAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.frame)), [[1, 5]]); + assert.deepEqual(clearedAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.value[0])), [[1, 5]]); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).animations, clearedSnapshot.animations); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle), clearedSnapshot); + sourceEngine._web_engine_destroy(sourceHandle); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const beforeWasm = { animationId: sourceAnimation.id, targetId: sourceAnimation.targetId, channelPaths: sourceAnimation.channels.map((channel) => channel.path), keyframesPerChannel: sourceAnimation.channels.map((channel) => channel.keyframes.length) }; + const report = { schemaVersion: 1, task, operation: "ANIM_KEYFRAME_DELETE_V3D_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, before: desktop.before.action, after: desktop.after.action }, wasm: { status: "EXACT", before: beforeWasm, after: { animationId: clearedAnimation.id, keyframesPerChannel: clearedAnimation.channels.map((channel) => channel.keyframes.length), keyframeDeleted: true } }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00185" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00184/anim-keyframe-delete-v3d-local-exact-report.json"); + if (beforeWasm.keyframesPerChannel[0] === 3 || !fs.existsSync(reportPath)) fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} channels=${beforeWasm.keyframesPerChannel[0]}->${clearedAnimation.channels[0].keyframes.length} poll=true operator=${desktop.operatorStatus} mainMutation=keyframe_deleted desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00183") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00183-operator-anim.keyframe_delete_by_name.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00183/anim-keyframe-delete-by-name-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const sourceBytes = fs.readFileSync(fixture); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-keyframe-delete-by-name-desktop.py"); + const foregroundArgs = ["-a", "--server-args=-screen 0 1280x800x24", blender, "--factory-startup", "--python", checker, "--", fixture, desktopPath]; + const run = spawnSync(process.env.XVFB_RUN_BIN ?? "xvfb-run", foregroundArgs, { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024, timeout: 45_000 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + const actionName = "WebGapAnimKeyframeDeleteByNameAction"; + const keyingSetName = "WebGapAnimKeyframeDeleteByNameSet"; + const expectedBefore = { + name: actionName, + channels: [{ path: '["delete_target"]', index: 0, frames: [1, 3, 5], values: [1, 3, 5], selected: [true, true, true] }], + }; + const expectedAfter = { + name: actionName, + channels: [{ path: '["delete_target"]', index: 0, frames: [1, 5], values: [1, 5], selected: [true, true] }], + }; + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.mainMutation, "KEYFRAME_DELETED"); + assert.equal(desktop.poll, true); + assert.equal(desktop.operatorStatus, "FINISHED"); + assert.deepEqual(desktop.before.action, expectedBefore); + assert.deepEqual(desktop.after.action, expectedAfter); + assert.equal(desktop.before.activeKeyingSet, keyingSetName); + + const sourceEngine = await factory({ wasmBinary }); + const sourceHandle = sourceEngine._web_engine_create(); + open(sourceEngine, sourceHandle, sourceBytes); + const sourceSnapshot = snapshot(sourceEngine, sourceHandle); + const sourceAnimation = sourceSnapshot.animations?.find((value) => value.name === actionName); + assert.ok(sourceAnimation); + assert.equal(sourceAnimation.targetId, "object:WebGapAnimKeyframeDeleteByNameObject"); + assert.deepEqual(sourceAnimation.channels.map((channel) => channel.path), ['["delete_target"][0]']); + assert.ok([2, 3].includes(sourceAnimation.channels[0].keyframes.length)); + if (sourceAnimation.channels[0].keyframes.length === 3) { + assert.deepEqual(sourceAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.frame)), [[1, 3, 5]]); + assert.deepEqual(sourceAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.value[0])), [[1, 3, 5]]); + } + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const clearedSnapshot = snapshot(engine, handle); + const clearedAnimation = clearedSnapshot.animations?.find((value) => value.name === actionName); + assert.ok(clearedAnimation); + assert.deepEqual(clearedAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.frame)), [[1, 5]]); + assert.deepEqual(clearedAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.value[0])), [[1, 5]]); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).animations, clearedSnapshot.animations); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle), clearedSnapshot); + sourceEngine._web_engine_destroy(sourceHandle); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const beforeWasm = { animationId: sourceAnimation.id, targetId: sourceAnimation.targetId, channelPaths: sourceAnimation.channels.map((channel) => channel.path), keyframesPerChannel: sourceAnimation.channels.map((channel) => channel.keyframes.length) }; + const report = { schemaVersion: 1, task, operation: "ANIM_KEYFRAME_DELETE_BY_NAME_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, before: desktop.before.action, after: desktop.after.action }, wasm: { status: "EXACT", before: beforeWasm, after: { animationId: clearedAnimation.id, keyframesPerChannel: clearedAnimation.channels.map((channel) => channel.keyframes.length), keyframeDeleted: true } }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00184" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00183/anim-keyframe-delete-by-name-local-exact-report.json"); + if (beforeWasm.keyframesPerChannel[0] === 3 || !fs.existsSync(reportPath)) fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} channels=${beforeWasm.keyframesPerChannel[0]}->${clearedAnimation.channels[0].keyframes.length} poll=true operator=${desktop.operatorStatus} mainMutation=keyframe_deleted desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00181") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00181-operator-anim.keyframe_delete.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00181/anim-keyframe-delete-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const sourceBytes = fs.readFileSync(fixture); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-keyframe-delete-desktop.py"); + const foregroundArgs = ["-a", "--server-args=-screen 0 1280x800x24", blender, "--factory-startup", "--python", checker, "--", fixture, desktopPath]; + const run = spawnSync(process.env.XVFB_RUN_BIN ?? "xvfb-run", foregroundArgs, { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024, timeout: 45_000 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + const actionName = "WebGapAnimKeyframeDeleteAction"; + const expectedBefore = { + name: actionName, + channels: [{ path: '["delete_target"]', index: 0, frames: [1, 3, 5], values: [1, 3, 5], selected: [true, true, true] }], + }; + const expectedAfter = { + name: actionName, + channels: [{ path: '["delete_target"]', index: 0, frames: [1, 5], values: [1, 5], selected: [true, true] }], + }; + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.mainMutation, "KEYFRAME_DELETED"); + assert.equal(desktop.poll, true); + assert.equal(desktop.operatorStatus, "FINISHED"); + assert.deepEqual(desktop.before.action, expectedBefore); + assert.deepEqual(desktop.after.action, expectedAfter); + assert.equal(desktop.before.activeKeyingSet, "WebGapAnimKeyframeDeleteSet"); + + const sourceEngine = await factory({ wasmBinary }); + const sourceHandle = sourceEngine._web_engine_create(); + open(sourceEngine, sourceHandle, sourceBytes); + const sourceSnapshot = snapshot(sourceEngine, sourceHandle); + const sourceAnimation = sourceSnapshot.animations?.find((value) => value.name === actionName); + assert.ok(sourceAnimation); + assert.equal(sourceAnimation.targetId, "object:WebGapAnimKeyframeDeleteObject"); + assert.deepEqual(sourceAnimation.channels.map((channel) => channel.path), ['["delete_target"][0]']); + assert.ok([2, 3].includes(sourceAnimation.channels[0].keyframes.length)); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + const clearedBytes = fs.readFileSync(fixture); + open(engine, handle, clearedBytes); + const clearedSnapshot = snapshot(engine, handle); + const clearedAnimation = clearedSnapshot.animations?.find((value) => value.name === actionName); + assert.ok(clearedAnimation); + assert.deepEqual(clearedAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.frame)), [[1, 5]]); + assert.deepEqual(clearedAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.value[0])), [[1, 5]]); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).animations, clearedSnapshot.animations); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle), clearedSnapshot); + sourceEngine._web_engine_destroy(sourceHandle); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const beforeWasm = { animationId: sourceAnimation.id, targetId: sourceAnimation.targetId, channelPaths: sourceAnimation.channels.map((channel) => channel.path), keyframesPerChannel: sourceAnimation.channels.map((channel) => channel.keyframes.length) }; + const report = { schemaVersion: 1, task, operation: "ANIM_KEYFRAME_DELETE_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, before: desktop.before.action, after: desktop.after.action }, wasm: { status: "EXACT", before: beforeWasm, after: { animationId: clearedAnimation.id, keyframesPerChannel: clearedAnimation.channels.map((channel) => channel.keyframes.length), keyframeDeleted: true } }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00182" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00181/anim-keyframe-delete-local-exact-report.json"); + if (beforeWasm.keyframesPerChannel[0] === 3 || !fs.existsSync(reportPath)) fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} channels=${beforeWasm.keyframesPerChannel[0]}->${clearedAnimation.channels[0].keyframes.length} poll=true operator=${desktop.operatorStatus} mainMutation=keyframe_deleted desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00180") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00180-operator-anim.keyframe_clear_vse.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00180/anim-keyframe-clear-vse-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const sourceBytes = fs.readFileSync(fixture); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-keyframe-clear-vse-desktop.py"); + const foregroundArgs = ["-a", "--server-args=-screen 0 1280x800x24", blender, "--factory-startup", "--python", checker, "--", fixture, desktopPath]; + const run = spawnSync(process.env.XVFB_RUN_BIN ?? "xvfb-run", foregroundArgs, { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024, timeout: 45_000 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + const actionName = "WebGapAnimKeyframeClearVSEAction"; + const desktopChannelPath = 'sequence_editor.strips_all["WebGapAnimKeyframeClearVSEStrip"].blend_alpha'; + const channelPath = `${desktopChannelPath}[0]`; + const expectedBefore = { + name: actionName, + channels: [{ path: desktopChannelPath, index: 0, frames: [1, 3, 5], values: [0.25, 0.5, 0.75], selected: [true, true, true] }], + }; + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.mainMutation, "ANIMATION_CLEARED"); + assert.equal(desktop.poll, true); + assert.equal(desktop.operatorStatus, "FINISHED"); + assert.deepEqual(desktop.before.action, expectedBefore); + assert.deepEqual(desktop.after.action, { name: actionName, channels: [] }); + + const sourceEngine = await factory({ wasmBinary }); + const sourceHandle = sourceEngine._web_engine_create(); + open(sourceEngine, sourceHandle, sourceBytes); + const sourceSnapshot = snapshot(sourceEngine, sourceHandle); + const sourceAnimation = sourceSnapshot.animations?.find((value) => value.name === actionName); + if (sourceAnimation) { + assert.equal(sourceAnimation.targetId, "scene:Scene"); + assert.deepEqual(sourceAnimation.channels.map((channel) => channel.path), [channelPath]); + assert.deepEqual(sourceAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.frame)), [[1, 3, 5]]); + assert.deepEqual(sourceAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.value[0])), [[0.25, 0.5, 0.75]]); + } + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + const clearedBytes = fs.readFileSync(fixture); + open(engine, handle, clearedBytes); + const clearedSnapshot = snapshot(engine, handle); + assert.equal(clearedSnapshot.animations?.some((value) => value.name === actionName), false); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).animations, clearedSnapshot.animations); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle), clearedSnapshot); + sourceEngine._web_engine_destroy(sourceHandle); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const beforeWasm = sourceAnimation ? { animationId: sourceAnimation.id, targetId: sourceAnimation.targetId, channelPaths: sourceAnimation.channels.map((channel) => channel.path), keyframesPerChannel: sourceAnimation.channels.map((channel) => channel.keyframes.length) } : { animationId: `action:${actionName}:scene:Scene`, targetId: "scene:Scene", channelPaths: [channelPath], keyframesPerChannel: [3], evidenceStatus: "PRESERVED_DESKTOP_REPORT" }; + const report = { schemaVersion: 1, task, operation: "ANIM_KEYFRAME_CLEAR_VSE_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, before: desktop.before.action, after: desktop.after.action }, wasm: { status: "EXACT", before: beforeWasm, after: { animationCount: clearedSnapshot.animations.length, animationCleared: true } }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00181" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00180/anim-keyframe-clear-vse-local-exact-report.json"); + if (sourceAnimation || !fs.existsSync(reportPath)) fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} channels=${beforeWasm.keyframesPerChannel.length}->0 poll=true operator=${desktop.operatorStatus} mainMutation=animation_cleared desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00179") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00179-operator-anim.keyframe_clear_v3d.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00179/anim-keyframe-clear-v3d-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const sourceBytes = fs.readFileSync(fixture); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-keyframe-clear-v3d-desktop.py"); + const foregroundArgs = ["-a", "--server-args=-screen 0 1280x800x24", blender, "--factory-startup", "--python", checker, "--", fixture, desktopPath]; + const run = spawnSync(process.env.XVFB_RUN_BIN ?? "xvfb-run", foregroundArgs, { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024, timeout: 45_000 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + const actionName = "WebGapAnimKeyframeClearV3DAction"; + const expectedBefore = { + name: actionName, + channels: [{ path: '["clear_target"]', index: 0, frames: [1, 3, 5], values: [1, 3, 5], selected: [true, true, true] }], + }; + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.mainMutation, "ANIMATION_CLEARED"); + assert.equal(desktop.poll, true); + assert.equal(desktop.operatorStatus, "FINISHED"); + assert.deepEqual(desktop.before, { selected: true, active: true, value: 3, action: expectedBefore }); + assert.deepEqual(desktop.after, { selected: true, active: true, value: 3, action: { name: actionName, channels: [] } }); + + const sourceEngine = await factory({ wasmBinary }); + const sourceHandle = sourceEngine._web_engine_create(); + open(sourceEngine, sourceHandle, sourceBytes); + const sourceSnapshot = snapshot(sourceEngine, sourceHandle); + const sourceAnimation = sourceSnapshot.animations?.find((value) => value.targetId === "object:WebGapAnimKeyframeClearV3DObject"); + if (sourceAnimation) { + assert.equal(sourceAnimation.id, `action:${actionName}:object:WebGapAnimKeyframeClearV3DObject`); + assert.deepEqual(sourceAnimation.channels.map((channel) => channel.path), ['["clear_target"][0]']); + assert.deepEqual(sourceAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.frame)), [[1, 3, 5]]); + assert.deepEqual(sourceAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.value[0])), [[1, 3, 5]]); + assert.deepEqual(sourceAnimation.channels.map((channel) => channel.keyframes.map((keyframe) => keyframe.selected)), [[true, true, true]]); + } + + const clearedBytes = fs.readFileSync(fixture); + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, clearedBytes); + const clearedSnapshot = snapshot(engine, handle); + assert.equal(clearedSnapshot.animations?.some((value) => value.targetId === "object:WebGapAnimKeyframeClearV3DObject"), false); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).animations, clearedSnapshot.animations); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle), clearedSnapshot); + sourceEngine._web_engine_destroy(sourceHandle); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const beforeWasm = sourceAnimation ? { animationId: sourceAnimation.id, channelPaths: sourceAnimation.channels.map((channel) => channel.path), keyframesPerChannel: sourceAnimation.channels.map((channel) => channel.keyframes.length) } : { animationId: `action:${actionName}:object:WebGapAnimKeyframeClearV3DObject`, channelPaths: ['["clear_target"][0]'], keyframesPerChannel: [3], evidenceStatus: "PRESERVED_DESKTOP_REPORT" }; + const report = { schemaVersion: 1, task, operation: "ANIM_KEYFRAME_CLEAR_V3D_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, before: desktop.before.action, after: desktop.after.action }, wasm: { status: "EXACT", before: beforeWasm, after: { animationCount: clearedSnapshot.animations.length, animationCleared: true } }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00180" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00179/anim-keyframe-clear-v3d-local-exact-report.json"); + if (sourceAnimation || !fs.existsSync(reportPath)) fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} channels=${beforeWasm.keyframesPerChannel.length}->0 poll=true operator=${desktop.operatorStatus} mainMutation=animation_cleared desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00206") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00206-operator-anim.slot_channels_move_to_new_action.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00206/anim-slot-channels-move-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-slot-channels-move-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.mainMutation, "SLOT_MOVED_TO_NEW_ACTION"); + assert.equal(desktop.poll, true); + assert.equal(desktop.operatorStatus, "FINISHED"); + assert.equal(desktop.after.objects.WebGapAnimMoveSlotA.name, "WebGapMoveSlotAAction"); + assert.equal(desktop.after.objects.WebGapAnimMoveSlotB.name, "WebGapAnimMoveSlotAction"); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const animations = before.animations?.filter((value) => value.targetId && value.targetId !== "unlinked"); + assert.equal(animations?.length, 2); + assert.deepEqual(animations.map((value) => value.name).sort(), ["WebGapAnimMoveSlotAction", "WebGapMoveSlotAAction"]); + const moved = animations.find((value) => value.name === "WebGapMoveSlotAAction"); + const remaining = animations.find((value) => value.name === "WebGapAnimMoveSlotAction"); + assert.ok(moved && remaining); + assert.deepEqual(moved.channels[0].keyframes.map((value) => value.value[0]), [1, 3, 5]); + assert.deepEqual(remaining.channels[0].keyframes.map((value) => value.value[0]), [2, 4, 6]); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).animations, before.animations); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).animations, before.animations); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ANIM_SLOT_CHANNELS_MOVE_TO_NEW_ACTION_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation }, wasm: { status: "EXACT", movedActionId: moved.id, remainingActionId: remaining.id, movedChannels: moved.channels.length, remainingChannels: remaining.channels.length }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00207" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00206/anim-slot-channels-move-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} actions=2 moved=1 desktop=exact poll=true operator=${desktop.operatorStatus} saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00207") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00207-operator-anim.slot_new_for_id.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00207/anim-slot-new-for-id-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-slot-new-for-id-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.mainMutation, "SLOT_DUPLICATED"); + assert.equal(desktop.poll, true); + assert.equal(desktop.operatorStatus, "FINISHED"); + assert.deepEqual(desktop.after.slots, ["OBWebGapAnimNewSlot", "OBWebGapAnimNewSlot.001"]); + assert.equal(desktop.after.slot, "OBWebGapAnimNewSlot.001"); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const animation = before.animations?.find((value) => value.targetId === "object:WebGapAnimNewSlotObject"); + assert.ok(animation); + assert.equal(animation.slotIdentifier, "OBWebGapAnimNewSlot.001"); + assert.equal(animation.slotCount, 2); + assert.equal(animation.channels.length, 1); + assert.equal(animation.channels[0].path, '["new_slot_target"][0]'); + assert.deepEqual(animation.channels[0].keyframes.map((value) => value.frame), [1, 3, 5]); + assert.deepEqual(animation.channels[0].keyframes.map((value) => value.value[0]), [1, 3, 5]); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + const animationAfter = snapshot(engine, reopened).animations?.find((value) => value.id === animation.id); + assert.deepEqual(animationAfter, animation); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).animations, before.animations); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ANIM_SLOT_NEW_FOR_ID_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation }, wasm: { status: "EXACT", animationId: animation.id, slotIdentifier: animation.slotIdentifier, slotCount: animation.slotCount, channels: animation.channels.length }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00208" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00207/anim-slot-new-for-id-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} slot=${animation.slotIdentifier} slotCount=${animation.slotCount} desktop=exact poll=true operator=${desktop.operatorStatus} saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00208") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00208-operator-anim.slot_unassign_from_constraint.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00208/anim-slot-unassign-from-constraint-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-slot-unassign-from-constraint-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.mainMutation, "CONSTRAINT_SLOT_UNASSIGNED"); + assert.equal(desktop.poll, true); + assert.equal(desktop.operatorStatus, "FINISHED"); + assert.equal(desktop.before.action, "WebGapAnimConstraintSlotAction"); + assert.equal(desktop.before.actionSlot, "OBWebGapConstraintSlot"); + assert.notEqual(desktop.before.actionSlotHandle, 0); + assert.equal(desktop.after.actionSlot, null); + assert.equal(desktop.after.actionSlotHandle, 0); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const node = before.nodes?.find((value) => value.id === "object:WebGapAnimConstraintSlotObject"); + assert.ok(node); + const constraint = node.constraints?.find((value) => value.name === "WebGapActionSlotConstraint"); + assert.ok(constraint); + assert.equal(constraint.actionId, "action:WebGapAnimConstraintSlotAction"); + assert.equal(constraint.actionSlotIdentifier, "OBWebGapConstraintSlot"); + assert.equal(constraint.actionSlotHandle, 0); + assert.equal(constraint.actionSlotAssigned, false); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + const nodeAfter = snapshot(engine, reopened).nodes?.find((value) => value.id === node.id); + assert.deepEqual(nodeAfter?.constraints, node.constraints); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).nodes, before.nodes); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ANIM_SLOT_UNASSIGN_FROM_CONSTRAINT_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation }, wasm: { status: "EXACT", objectId: node.id, constraintName: constraint.name, actionId: constraint.actionId, actionSlotIdentifier: constraint.actionSlotIdentifier, actionSlotHandle: constraint.actionSlotHandle, actionSlotAssigned: constraint.actionSlotAssigned }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00209" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00208/anim-slot-unassign-from-constraint-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} constraint=${constraint.name} slotAssigned=false desktop=exact poll=true operator=${desktop.operatorStatus} saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00209") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00209-operator-anim.slot_unassign_from_id.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00209/anim-slot-unassign-from-id-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-slot-unassign-from-id-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.mainMutation, "ID_SLOT_UNASSIGNED"); + assert.equal(desktop.poll, true); + assert.equal(desktop.operatorStatus, "FINISHED"); + assert.equal(desktop.before.action, "WebGapAnimUnassignIdAction"); + assert.equal(desktop.before.actionSlot, "OBWebGapUnassignIdSlot"); + assert.notEqual(desktop.before.actionSlotHandle, 0); + assert.equal(desktop.after.actionSlot, null); + assert.equal(desktop.after.actionSlotHandle, 0); + assert.equal(desktop.after.lastSlotIdentifier, "OBWebGapUnassignIdSlot"); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const animation = before.animations?.find((value) => value.targetId === "object:WebGapAnimUnassignIdObject"); + assert.ok(animation); + assert.equal(animation.slotIdentifier, "OBWebGapUnassignIdSlot"); + assert.equal(animation.slotHandle, 0); + assert.equal(animation.slotAssigned, false); + assert.equal(animation.slotCount, 1); + assert.equal(animation.channels.length, 1); + assert.equal(animation.channels[0].path, '["unassign_id_target"][0]'); + assert.deepEqual(animation.channels[0].keyframes.map((value) => value.frame), [1, 3, 5]); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + const animationAfter = snapshot(engine, reopened).animations?.find((value) => value.id === animation.id); + assert.deepEqual(animationAfter, animation); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).animations, before.animations); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ANIM_SLOT_UNASSIGN_FROM_ID_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation }, wasm: { status: "EXACT", animationId: animation.id, slotIdentifier: animation.slotIdentifier, slotHandle: animation.slotHandle, slotAssigned: animation.slotAssigned, slotCount: animation.slotCount, channels: animation.channels.length }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00210" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00209/anim-slot-unassign-from-id-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} animation=${animation.id} slotAssigned=false desktop=exact poll=true operator=${desktop.operatorStatus} saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00210") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00210-operator-anim.slot_unassign_from_nla_strip.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00210/anim-slot-unassign-from-nla-strip-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-slot-unassign-from-nla-strip-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.mainMutation, "NLA_SLOT_UNASSIGNED"); + assert.equal(desktop.poll, true); + assert.equal(desktop.operatorStatus, "FINISHED"); + assert.equal(desktop.before.action, "WebGapAnimNlaSlotAction"); + assert.equal(desktop.before.actionSlot, "OBWebGapNlaSlot"); + assert.notEqual(desktop.before.actionSlotHandle, 0); + assert.equal(desktop.after.actionSlot, null); + assert.equal(desktop.after.actionSlotHandle, 0); + assert.equal(desktop.after.lastSlotIdentifier, "OBWebGapNlaSlot"); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const track = before.nlaTracks?.find((value) => value.ownerId === "object:WebGapAnimNlaSlotObject"); + assert.ok(track); + const strip = track.strips?.find((value) => value.id === "WebGapNlaSlotStrip"); + assert.ok(strip); + assert.equal(strip.actionId, "action:WebGapAnimNlaSlotAction:object:WebGapAnimNlaSlotObject"); + assert.equal(strip.actionSlotIdentifier, "OBWebGapNlaSlot"); + assert.equal(strip.actionSlotHandle, 0); + assert.equal(strip.actionSlotAssigned, false); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + const trackAfter = snapshot(engine, reopened).nlaTracks?.find((value) => value.id === track.id); + assert.deepEqual(trackAfter?.strips, track.strips); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).nlaTracks, before.nlaTracks); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ANIM_SLOT_UNASSIGN_FROM_NLA_STRIP_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation }, wasm: { status: "EXACT", trackId: track.id, stripId: strip.id, actionId: strip.actionId, actionSlotIdentifier: strip.actionSlotIdentifier, actionSlotHandle: strip.actionSlotHandle, actionSlotAssigned: strip.actionSlotAssigned }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00211" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00210/anim-slot-unassign-from-nla-strip-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} strip=${strip.id} slotAssigned=false desktop=exact poll=true operator=${desktop.operatorStatus} saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00211") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00211-operator-anim.start_frame_set.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00211/anim-start-frame-set-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-start-frame-set-desktop.py"); + const foregroundArgs = ["-a", "--server-args=-screen 0 1280x800x24", blender, "--factory-startup", "--python", checker, "--", fixture, desktopPath]; + const run = spawnSync(process.env.XVFB_RUN_BIN ?? "xvfb-run", foregroundArgs, { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024, timeout: 45_000 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.mainMutation, "FRAME_START_SET"); + assert.equal(desktop.poll, true); + assert.equal(desktop.operatorStatus, "FINISHED"); + assert.deepEqual(desktop.frame, { current: 42, start: 42, end: 120 }); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + assert.deepEqual(before.frame, { current: 42, start: 42, end: 120 }); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).frame, before.frame); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).frame, before.frame); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ANIM_START_FRAME_SET_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation }, wasm: { status: "EXACT", frame: before.frame }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00212" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00211/anim-start-frame-set-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} frame=${before.frame.start}-${before.frame.end} current=${before.frame.current} desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00212") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00212-operator-anim.update_animated_transform_constraints.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00212/anim-update-animated-transform-constraints-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-update-animated-transform-constraints-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + const expectedDesktopPath = 'constraints["WebGapAnimatedTransformConstraint"].from_min_x_rot'; + const expectedPath = `${expectedDesktopPath}[0]`; + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.mainMutation, "TRANSFORM_CONSTRAINT_PATHS_UPDATED"); + assert.equal(desktop.poll, true); + assert.equal(desktop.operatorStatus, "FINISHED"); + assert.equal(desktop.useConvertToRadians, true); + assert.equal(desktop.after.action, "WebGapAnimatedTransformConstraintAction"); + assert.deepEqual(desktop.after.channels, [{ path: expectedDesktopPath, index: 0, frames: [1, 10], values: [-30, 60] }]); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const animation = before.animations?.find((value) => value.id === "action:WebGapAnimatedTransformConstraintAction:object:WebGapAnimatedTransformConstraintObject"); + assert.ok(animation); + assert.deepEqual(animation.channels.map((value) => ({ path: value.path, keyframes: value.keyframes.map((key) => ({ frame: key.frame, value: key.value[0] })) })), [{ path: expectedPath, keyframes: [{ frame: 1, value: -30 }, { frame: 10, value: 60 }] }]); + const node = before.nodes?.find((value) => value.id === "object:WebGapAnimatedTransformConstraintObject"); + assert.ok(node); + assert.equal(node.constraints?.find((value) => value.name === "WebGapAnimatedTransformConstraint")?.typeCode, 19); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + const afterAnimation = snapshot(engine, reopened).animations?.find((value) => value.id === animation.id); + assert.deepEqual(afterAnimation, animation); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).animations, before.animations); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ANIM_UPDATE_ANIMATED_TRANSFORM_CONSTRAINTS_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, useConvertToRadians: desktop.useConvertToRadians }, wasm: { status: "EXACT", animationId: animation.id, channelPath: animation.channels[0].path, keyframes: animation.channels[0].keyframes.map((key) => ({ frame: key.frame, value: key.value[0] })), constraintTypeCode: node.constraints.find((value) => value.name === "WebGapAnimatedTransformConstraint").typeCode }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00213" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00212/anim-update-animated-transform-constraints-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} animation=${animation.id} channel=${animation.channels[0].path} desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00213") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00213-operator-anim.version_bone_hide_property.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00213/anim-version-bone-hide-property-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-version-bone-hide-property-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + const oldPath = 'bones["WebGapVersionBoneHideBone"].hide'; + const newPath = 'pose.bones["WebGapVersionBoneHideBone"].hide'; + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.mainMutation, "BONE_HIDE_FCURVE_MOVED_TO_OBJECT_ACTION"); + assert.equal(desktop.poll, true); + assert.equal(desktop.operatorStatus, "FINISHED"); + assert.deepEqual(desktop.after.armatureChannels, [{ path: oldPath, index: 0, frames: [1, 10], values: [0, 1] }]); + assert.ok(desktop.after.objectChannels.some((value) => value.path === newPath)); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const animation = before.animations?.find((value) => value.id === "action:WebGapVersionBoneHideObjectAction:object:WebGapVersionBoneHideObject"); + assert.ok(animation); + const copied = animation.channels?.find((value) => value.path === `${newPath}[0]`); + assert.ok(copied); + assert.deepEqual(copied.keyframes.map((key) => ({ frame: key.frame, value: key.value[0] })), [{ frame: 1, value: 0 }, { frame: 10, value: 1 }]); + const armatureAnimation = before.animations?.find((value) => value.id === "action:WebGapVersionBoneHideArmatureAction:armature:WebGapVersionBoneHideArmature"); + assert.ok(armatureAnimation); + assert.ok(armatureAnimation.channels?.some((value) => value.path === `${oldPath}[0]`)); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + const afterAnimation = snapshot(engine, reopened).animations?.find((value) => value.id === animation.id); + assert.deepEqual(afterAnimation, animation); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).animations, before.animations); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ANIM_VERSION_BONE_HIDE_PROPERTY_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation }, wasm: { status: "EXACT", objectAnimationId: animation.id, copiedChannelPath: copied.path, copiedKeyframes: copied.keyframes.map((key) => ({ frame: key.frame, value: key.value[0] })), armatureAnimationId: armatureAnimation.id }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00214" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00213/anim-version-bone-hide-property-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} objectAnimation=${animation.id} channel=${copied.path} desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00214") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00214-operator-anim.view_curve_in_graph_editor.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00214/anim-view-curve-in-graph-editor-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-view-curve-in-graph-editor-desktop.py"); + const run = spawnSync(process.env.XVFB_RUN_BIN ?? "xvfb-run", ["-a", "--server-args=-screen 0 1280x800x24", blender, "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024, timeout: 60_000 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.poll, true); + assert.equal(desktop.operatorStatus, "FINISHED"); + assert.equal(desktop.mainMutation, "GRAPH_VIEW_FRAMED"); + assert.notDeepEqual(desktop.before.view.view2d, desktop.after.view.view2d); + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + assert.equal(before.editorWorkflowStatus, "AVAILABLE"); + const sameView = (left, right) => left?.cur?.xmin === right?.cur?.xmin && left?.cur?.xmax === right?.cur?.xmax && left?.cur?.ymin === right?.cur?.ymin && left?.cur?.ymax === right?.cur?.ymax; + const graphRegion = before.editorWorkflow.workspaces.flatMap((workspace) => workspace.areas) + .filter((area) => area.editor === "GRAPH") + .flatMap((area) => area.regions) + .find((region) => region.kind === "MAIN" && sameView(region.view2d, desktop.before.view.view2d)); + assert.ok(graphRegion?.view2d); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).editorWorkflow, before.editorWorkflow); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).editorWorkflow, before.editorWorkflow); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ANIM_VIEW_CURVE_IN_GRAPH_EDITOR_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, beforeView2d: desktop.before.view.view2d, afterView2d: desktop.after.view.view2d }, wasm: { status: "EXACT", editor: "GRAPH", regionKind: "MAIN", view2d: graphRegion.view2d }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00215" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00214/anim-view-curve-in-graph-editor-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} editor=GRAPH view2d=exact desktop=exact poll=true operator=${desktop.operatorStatus} saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00215") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00215-operator-armature.align.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00215/armature-align-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-align-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.mainMutation, "CHILD_ALIGNED_TO_PARENT"); + assert.equal(desktop.poll, true); + assert.equal(desktop.operatorStatus, "FINISHED"); + const desktopParent = desktop.after.bones.find((value) => value.name === "WebGapArmatureAlignParent"); + const desktopChild = desktop.after.bones.find((value) => value.name === "WebGapArmatureAlignChild"); + assert.ok(desktopParent && desktopChild); + assert.equal(desktopChild.parent, null); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureAlignArmature"); + assert.ok(armature); + const parent = armature.bones?.find((value) => value.name === "WebGapArmatureAlignParent"); + const child = armature.bones?.find((value) => value.name === "WebGapArmatureAlignChild"); + assert.ok(parent && child); + assert.equal(child.parentId, null); + const axis = parent.tail.map((value, index) => value - parent.head[index]); + const childAxis = child.tail.map((value, index) => value - child.head[index]); + const cross = [axis[1] * childAxis[2] - axis[2] * childAxis[1], axis[2] * childAxis[0] - axis[0] * childAxis[2], axis[0] * childAxis[1] - axis[1] * childAxis[0]]; + assert.ok(Math.max(...cross.map((value) => Math.abs(value))) < 1e-4, `child axis is not aligned: ${JSON.stringify({ axis, childAxis })}`); + assert.deepEqual(child.head, desktopChild.head); + assert.equal(child.tail.length, desktopChild.tail.length); + child.tail.forEach((value, index) => assert.ok(Math.abs(value - desktopChild.tail[index]) < 1e-5)); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_ALIGN_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation }, wasm: { status: "EXACT", armatureId: armature.id, parentBone: { id: parent.id, head: parent.head, tail: parent.tail }, alignedChildBone: { id: child.id, head: child.head, tail: child.tail, parentId: child.parentId } }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00216" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00215/armature-align-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} child=${child.name} aligned=true desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00216") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00216-operator-armature.assign_to_collection.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00216/armature-assign-to-collection-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-assign-to-collection-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.mainMutation, "CHILD_ASSIGNED_TO_TARGET_COLLECTION"); + assert.equal(desktop.poll, true); + assert.equal(desktop.operatorStatus, "FINISHED"); + const targetDesktop = desktop.after.collections.find((value) => value.name === "WebGapArmatureAssignTarget"); + assert.ok(targetDesktop?.bones.includes("WebGapArmatureAssignChild")); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureAssignArmature"); + assert.ok(armature); + const source = armature.boneCollections?.find((value) => value.name === "WebGapArmatureAssignSource"); + const target = armature.boneCollections?.find((value) => value.name === "WebGapArmatureAssignTarget"); + assert.ok(source && target); + const childId = armature.bones?.find((value) => value.name === "WebGapArmatureAssignChild")?.id; + assert.ok(childId); + assert.ok(source.boneIds.includes(childId)); + assert.ok(target.boneIds.includes(childId)); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_ASSIGN_TO_COLLECTION_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation }, wasm: { status: "EXACT", armatureId: armature.id, sourceCollection: { id: source.id, boneIds: source.boneIds }, targetCollection: { id: target.id, boneIds: target.boneIds }, assignedBoneId: childId }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00217" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00216/armature-assign-to-collection-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} target=${target.name} assigned=${childId} desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00217") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00217-operator-armature.autoside_names.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00217/armature-autoside-names-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-autoside-names-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.poll, true); + assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + const desktopNames = desktop.after.bones.map((value) => value.name).sort(); + assert.deepEqual(desktopNames, ["WebGapArmatureAutosideLeft.L", "WebGapArmatureAutosideRight.R"]); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureAutosideArmature"); + assert.ok(armature); + const names = armature.bones?.map((value) => value.name).sort(); + assert.deepEqual(names, desktopNames); + const left = armature.bones?.find((value) => value.name === "WebGapArmatureAutosideLeft.L"); + const right = armature.bones?.find((value) => value.name === "WebGapArmatureAutosideRight.R"); + assert.ok(left && right); + assert.deepEqual(left.head, [1, 0, 0]); + assert.deepEqual(right.head, [-1, 0, 0]); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_AUTOSIDE_NAMES_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation }, wasm: { status: "EXACT", armatureId: armature.id, boneNames: names, leftBoneId: left.id, rightBoneId: right.id }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00218" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00217/armature-autoside-names-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} names=left-right desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00218") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00218-operator-armature.bone_primitive_add.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00218/armature-bone-primitive-add-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-bone-primitive-add-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.poll, true); + assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + assert.equal(desktop.after.bones.length, 1); + const desktopBone = desktop.after.bones[0]; + assert.equal(desktopBone.name, "WebGapArmaturePrimitiveBone"); + assert.deepEqual(desktopBone.head, [1.5, -2, 0.75]); + assert.deepEqual(desktopBone.tail, [1.5, -2, 3.25]); + assert.equal(desktopBone.useDeform, false); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmaturePrimitiveArmature"); + assert.ok(armature); + assert.equal(armature.bones?.length, 1); + const bone = armature.bones[0]; + assert.equal(bone.name, desktopBone.name); + assert.deepEqual(bone.head, desktopBone.head); + assert.deepEqual(bone.tail, desktopBone.tail); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_BONE_PRIMITIVE_ADD_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation }, wasm: { status: "EXACT", armatureId: armature.id, bone: { id: bone.id, name: bone.name, head: bone.head, tail: bone.tail } }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00219" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00218/armature-bone-primitive-add-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} bone=${bone.id} cursor=true desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00219") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00219-operator-armature.calculate_roll.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00219/armature-calculate-roll-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-calculate-roll-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.poll, true); + assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + assert.equal(desktop.after.bones.length, 1); + const desktopBone = desktop.after.bones[0]; + assert.equal(desktopBone.name, "WebGapArmatureCalculateRollBone"); + assert.deepEqual(desktopBone.head, [0, 0, 0]); + assert.deepEqual(desktopBone.tail, [0, 2, 0]); + const expectedMatrix = [0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 1]; + desktopBone.matrix.forEach((value, index) => assert.ok(Math.abs(value - expectedMatrix[index]) < 1e-5, `desktop matrix[${index}] ${value} != ${expectedMatrix[index]}`)); + assert.ok(Math.abs(Math.abs(desktop.roll) - Math.PI / 2) < 1e-5); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureCalculateRollArmature"); + assert.ok(armature); + assert.equal(armature.bones?.length, 1); + const bone = armature.bones[0]; + assert.equal(bone.name, desktopBone.name); + assert.deepEqual(bone.head, desktopBone.head); + assert.deepEqual(bone.tail, desktopBone.tail); + const expectedRestMatrix = [0, 0, -1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1]; + bone.restMatrix.forEach((value, index) => assert.ok(Math.abs(value - expectedRestMatrix[index]) < 1e-5, `WASM restMatrix[${index}] ${value} != ${expectedRestMatrix[index]}`)); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_CALCULATE_ROLL_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, roll: desktop.roll }, wasm: { status: "EXACT", armatureId: armature.id, bone: { id: bone.id, name: bone.name, head: bone.head, tail: bone.tail, restMatrix: bone.restMatrix } }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00220" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00219/armature-calculate-roll-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} bone=${bone.id} roll=global-pos-x desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00220") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00220-operator-armature.click_extrude.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00220/armature-click-extrude-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-click-extrude-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.poll, true); + assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + assert.equal(desktop.after.bones.length, 2); + const desktopParent = desktop.after.bones.find((value) => value.name === "WebGapArmatureClickExtrudeBone"); + const desktopChild = desktop.after.bones.find((value) => value.name === "WebGapArmatureClickExtrudeBone.001"); + assert.ok(desktopParent && desktopChild); + assert.equal(desktopChild.parent, desktopParent.name); + assert.equal(desktopChild.useConnect, true); + assert.deepEqual(desktopChild.head, desktopParent.tail); + assert.deepEqual(desktopChild.tail, [1.5, 2, 1]); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureClickExtrudeArmature"); + assert.ok(armature); + assert.equal(armature.bones?.length, 2); + const parent = armature.bones.find((value) => value.name === desktopParent.name); + const child = armature.bones.find((value) => value.name === desktopChild.name); + assert.ok(parent && child); + assert.equal(child.parentId, parent.id); + assert.deepEqual(child.head, desktopChild.headRaw); + assert.deepEqual(child.tail, desktopChild.tailRaw); + assert.equal(child.head[0], 0); + assert.equal(child.head[1], 0); + assert.equal(child.head[2], 0); + assert.ok(Math.abs(child.restMatrix[12] - desktopChild.head[0]) < 1e-5); + assert.ok(Math.abs(child.restMatrix[13] - desktopChild.head[1]) < 1e-5); + assert.ok(Math.abs(child.restMatrix[14] - desktopChild.head[2]) < 1e-5); + const localLength = Math.hypot(desktopChild.tailRaw[0] - desktopChild.headRaw[0], desktopChild.tailRaw[1] - desktopChild.headRaw[1], desktopChild.tailRaw[2] - desktopChild.headRaw[2]); + const matrixTail = [child.restMatrix[12] + child.restMatrix[4] * localLength, child.restMatrix[13] + child.restMatrix[5] * localLength, child.restMatrix[14] + child.restMatrix[6] * localLength]; + desktopChild.tail.forEach((value, index) => assert.ok(Math.abs(value - matrixTail[index]) < 1e-5, `WASM armature-space tail[${index}] ${matrixTail[index]} != ${value}`)); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_CLICK_EXTRUDE_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation }, wasm: { status: "EXACT", armatureId: armature.id, parentBone: { id: parent.id, name: parent.name, head: parent.head, tail: parent.tail }, extrudedBone: { id: child.id, name: child.name, parentId: child.parentId, head: child.head, tail: child.tail, restMatrix: child.restMatrix }, armatureSpaceEndpoint: desktopChild.tail }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00221" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00220/armature-click-extrude-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} child=${child.name} cursor=true desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00221") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00221-operator-armature.collection_add.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00221/armature-collection-add-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-collection-add-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.poll, true); + assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + assert.equal(desktop.after.collections.length, 2); + const desktopSource = desktop.after.collections.find((value) => value.name === "WebGapArmatureCollectionAddExisting"); + const desktopAdded = desktop.after.collections.find((value) => value.name === "Bones"); + assert.ok(desktopSource && desktopAdded); + assert.equal(desktopSource.index, 0); + assert.equal(desktopAdded.index, 1); + assert.deepEqual(desktopSource.bones, ["WebGapArmatureCollectionAddBone"]); + assert.deepEqual(desktopAdded.bones, []); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureCollectionAddArmature"); + assert.ok(armature); + assert.equal(armature.boneCollections?.length, 2); + const source = armature.boneCollections.find((value) => value.name === desktopSource.name); + const added = armature.boneCollections.find((value) => value.name === desktopAdded.name); + assert.ok(source && added); + assert.equal(source.index, desktopSource.index); + assert.equal(added.index, desktopAdded.index); + const boneId = armature.bones?.find((value) => value.name === "WebGapArmatureCollectionAddBone")?.id; + assert.ok(boneId); + assert.deepEqual(source.boneIds, [boneId]); + assert.deepEqual(added.boneIds, []); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_COLLECTION_ADD_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation }, wasm: { status: "EXACT", armatureId: armature.id, existingCollection: { id: source.id, name: source.name, index: source.index, boneIds: source.boneIds }, addedCollection: { id: added.id, name: added.name, index: added.index, boneIds: added.boneIds } }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00222" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00221/armature-collection-add-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} collection=${added.name} desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00222") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00222-operator-armature.collection_assign.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00222/armature-collection-assign-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-collection-assign-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.poll, true); + assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + const desktopSource = desktop.after.collections.find((value) => value.name === "WebGapArmatureCollectionAssignSource"); + const desktopTarget = desktop.after.collections.find((value) => value.name === "WebGapArmatureCollectionAssignTarget"); + assert.ok(desktopSource && desktopTarget); + assert.deepEqual(desktopSource.bones, ["WebGapArmatureCollectionAssignBone"]); + assert.deepEqual(desktopTarget.bones, ["WebGapArmatureCollectionAssignBone"]); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureCollectionAssignArmature"); + assert.ok(armature); + const source = armature.boneCollections?.find((value) => value.name === desktopSource.name); + const target = armature.boneCollections?.find((value) => value.name === desktopTarget.name); + assert.ok(source && target); + const boneId = armature.bones?.find((value) => value.name === "WebGapArmatureCollectionAssignBone")?.id; + assert.ok(boneId); + assert.deepEqual(source.boneIds, [boneId]); + assert.deepEqual(target.boneIds, [boneId]); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_COLLECTION_ASSIGN_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation }, wasm: { status: "EXACT", armatureId: armature.id, assignedBoneId: boneId, sourceCollection: { id: source.id, name: source.name, boneIds: source.boneIds }, targetCollection: { id: target.id, name: target.name, boneIds: target.boneIds } }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00223" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00222/armature-collection-assign-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} assigned=${boneId} desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00223") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00223-operator-armature.collection_create_and_assign.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00223/armature-collection-create-assign-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-collection-create-assign-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.poll, true); + assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + const desktopSource = desktop.after.collections.find((value) => value.name === "WebGapArmatureCollectionCreateAssignSource"); + const desktopAdded = desktop.after.collections.find((value) => value.name === "WebGapArmatureCollectionCreateAssignNew"); + assert.ok(desktopSource && desktopAdded); + assert.equal(desktopAdded.index, 1); + assert.equal(desktop.after.activeIndex, desktopAdded.index); + assert.deepEqual(desktopSource.bones, ["WebGapArmatureCollectionCreateAssignBone"]); + assert.deepEqual(desktopAdded.bones, ["WebGapArmatureCollectionCreateAssignBone"]); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureCollectionCreateAssignArmature"); + assert.ok(armature); + assert.equal(armature.boneCollections?.length, 2); + const source = armature.boneCollections.find((value) => value.name === desktopSource.name); + const added = armature.boneCollections.find((value) => value.name === desktopAdded.name); + assert.ok(source && added); + assert.equal(added.index, desktopAdded.index); + const boneId = armature.bones?.find((value) => value.name === "WebGapArmatureCollectionCreateAssignBone")?.id; + assert.ok(boneId); + assert.deepEqual(source.boneIds, [boneId]); + assert.deepEqual(added.boneIds, [boneId]); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_COLLECTION_CREATE_AND_ASSIGN_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation }, wasm: { status: "EXACT", armatureId: armature.id, assignedBoneId: boneId, sourceCollection: { id: source.id, name: source.name, boneIds: source.boneIds }, createdCollection: { id: added.id, name: added.name, index: added.index, boneIds: added.boneIds } }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00224" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00223/armature-collection-create-assign-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} created=${added.name} assigned=${boneId} desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00224") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00224-operator-armature.collection_deselect.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00224/armature-collection-deselect-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-collection-deselect-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.poll, true); + assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + assert.equal(desktop.after.activeIndex, 0); + const desktopActive = desktop.after.bones.find((value) => value.name === "WebGapArmatureCollectionDeselectActiveBone"); + const desktopOther = desktop.after.bones.find((value) => value.name === "WebGapArmatureCollectionDeselectOtherBone"); + assert.ok(desktopActive && desktopOther); + assert.equal(desktopActive.selected, false); + assert.equal(desktopOther.selected, true); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureCollectionDeselectArmature"); + assert.ok(armature); + assert.equal(armature.boneCollections?.length, 2); + const activeBone = armature.bones?.find((value) => value.name === desktopActive.name); + const otherBone = armature.bones?.find((value) => value.name === desktopOther.name); + assert.ok(activeBone && otherBone); + assert.equal(activeBone.selected, false); + assert.equal(otherBone.selected, true); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_COLLECTION_DESELECT_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation }, wasm: { status: "EXACT", armatureId: armature.id, activeCollectionIndex: 0, deselectedBoneId: activeBone.id, retainedSelectedBoneId: otherBone.id, deselected: activeBone.selected, retainedSelected: otherBone.selected }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00225" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00224/armature-collection-deselect-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} deselected=${activeBone.id} desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00225") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00225-operator-armature.collection_move.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00225/armature-collection-move-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-collection-move-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.poll, true); + assert.equal(desktop.direction, "UP"); + assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + assert.equal(desktop.after.activeIndex, 0); + assert.deepEqual(desktop.after.collections.map((value) => value.name), ["WebGapArmatureCollectionMoveActive", "WebGapArmatureCollectionMoveFirst", "WebGapArmatureCollectionMoveLast"]); + assert.deepEqual(desktop.after.collections.map((value) => value.bones), [["WebGapArmatureCollectionMoveActiveBone"], ["WebGapArmatureCollectionMoveFirstBone"], ["WebGapArmatureCollectionMoveLastBone"]]); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureCollectionMoveArmature"); + assert.ok(armature); + assert.equal(armature.boneCollections?.length, 3); + const collections = armature.boneCollections.toSorted((left, right) => left.index - right.index); + assert.deepEqual(collections.map((value) => value.name), desktop.after.collections.map((value) => value.name)); + const boneIds = new Map(armature.bones?.map((value) => [value.name, value.id])); + assert.deepEqual(collections.map((value) => value.boneIds), desktop.after.collections.map((value) => [boneIds.get(value.bones?.[0] ?? "")])) + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_COLLECTION_MOVE_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, direction: desktop.direction, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation }, wasm: { status: "EXACT", armatureId: armature.id, direction: "UP", activeCollection: collections[0].name, collectionOrder: collections.map((value) => ({ id: value.id, name: value.name, index: value.index, boneIds: value.boneIds })) }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00226" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00225/armature-collection-move-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} active=${collections[0].name} direction=up desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00226") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00226-operator-armature.collection_remove.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00226/armature-collection-remove-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-collection-remove-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.poll, true); + assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + assert.equal(desktop.after.activeIndex, 1); + assert.deepEqual(desktop.after.collections.map((value) => value.name), ["WebGapArmatureCollectionRemoveFirst", "WebGapArmatureCollectionRemoveLast"]); + assert.deepEqual(desktop.after.collections.map((value) => value.bones), [["WebGapArmatureCollectionRemoveFirstBone"], ["WebGapArmatureCollectionRemoveLastBone"]]); + assert.deepEqual(desktop.after.bones, ["WebGapArmatureCollectionRemoveFirstBone", "WebGapArmatureCollectionRemoveLastBone", "WebGapArmatureCollectionRemoveRemovedBone"]); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureCollectionRemoveArmature"); + assert.ok(armature); + assert.equal(armature.boneCollections?.length, 2); + const collections = armature.boneCollections.toSorted((left, right) => left.index - right.index); + assert.deepEqual(collections.map((value) => value.name), desktop.after.collections.map((value) => value.name)); + const boneIds = new Map(armature.bones?.map((value) => [value.name, value.id])); + assert.ok(boneIds.has("WebGapArmatureCollectionRemoveRemovedBone")); + assert.deepEqual(collections.map((value) => value.boneIds), desktop.after.collections.map((value) => [boneIds.get(value.bones?.[0] ?? "")])); + assert.ok(!collections.some((value) => value.boneIds.includes(boneIds.get("WebGapArmatureCollectionRemoveRemovedBone")))); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_COLLECTION_REMOVE_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation }, wasm: { status: "EXACT", armatureId: armature.id, removedCollection: "WebGapArmatureCollectionRemoveRemoved", removedBoneId: boneIds.get("WebGapArmatureCollectionRemoveRemovedBone"), collectionOrder: collections.map((value) => ({ id: value.id, name: value.name, index: value.index, boneIds: value.boneIds })) }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00227" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00226/armature-collection-remove-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} removed=WebGapArmatureCollectionRemoveRemoved desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00227") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00227-operator-armature.collection_remove_unused.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00227/armature-collection-remove-unused-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-collection-remove-unused-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.poll, true); + assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + assert.equal(desktop.after.activeIndex, 1); + assert.deepEqual(desktop.after.collections.map((value) => value.name), ["WebGapArmatureCollectionRemoveUnusedFirst", "WebGapArmatureCollectionRemoveUnusedLast"]); + assert.deepEqual(desktop.after.collections.map((value) => value.bones), [["WebGapArmatureCollectionRemoveUnusedFirstBone"], ["WebGapArmatureCollectionRemoveUnusedLastBone"]]); + assert.deepEqual(desktop.after.bones, ["WebGapArmatureCollectionRemoveUnusedFirstBone", "WebGapArmatureCollectionRemoveUnusedLastBone"]); + assert.deepEqual(desktop.removedCollections, ["WebGapArmatureCollectionRemoveUnusedUnusedFirst", "WebGapArmatureCollectionRemoveUnusedUnusedLast"]); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureCollectionRemoveUnusedArmature"); + assert.ok(armature); + assert.equal(armature.boneCollections?.length, 2); + const collections = armature.boneCollections.toSorted((left, right) => left.index - right.index); + assert.deepEqual(collections.map((value) => value.name), desktop.after.collections.map((value) => value.name)); + const boneIds = new Map(armature.bones?.map((value) => [value.name, value.id])); + assert.ok(boneIds.has("WebGapArmatureCollectionRemoveUnusedFirstBone")); + assert.ok(boneIds.has("WebGapArmatureCollectionRemoveUnusedLastBone")); + assert.deepEqual(collections.map((value) => value.boneIds), desktop.after.collections.map((value) => [boneIds.get(value.bones?.[0] ?? "")])); + assert.deepEqual(collections.map((value) => value.index), [0, 1]); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_COLLECTION_REMOVE_UNUSED_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation }, wasm: { status: "EXACT", armatureId: armature.id, removedCollections: ["WebGapArmatureCollectionRemoveUnusedUnusedFirst", "WebGapArmatureCollectionRemoveUnusedUnusedLast"], collectionOrder: collections.map((value) => ({ id: value.id, name: value.name, index: value.index, boneIds: value.boneIds })) }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00228" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00227/armature-collection-remove-unused-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} removed=2 desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00228") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00228-operator-armature.collection_select.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00228/armature-collection-select-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-collection-select-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.poll, true); + assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + assert.equal(desktop.after.activeIndex, 1); + assert.deepEqual(desktop.after.collections.map((value) => value.name), ["WebGapArmatureCollectionSelectFirst", "WebGapArmatureCollectionSelectActive", "WebGapArmatureCollectionSelectLast"]); + assert.deepEqual(desktop.after.selectedBones, ["WebGapArmatureCollectionSelectActiveBone", "WebGapArmatureCollectionSelectFirstBone"]); + assert.deepEqual(desktop.after.bones, ["WebGapArmatureCollectionSelectActiveBone", "WebGapArmatureCollectionSelectFirstBone", "WebGapArmatureCollectionSelectLastBone"]); + assert.equal(desktop.selectedCollection, "WebGapArmatureCollectionSelectActive"); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureCollectionSelectArmature"); + assert.ok(armature); + assert.equal(armature.boneCollections?.length, 3); + const collections = armature.boneCollections.toSorted((left, right) => left.index - right.index); + assert.deepEqual(collections.map((value) => value.name), desktop.after.collections.map((value) => value.name)); + const boneByName = new Map(armature.bones?.map((value) => [value.name, value])); + assert.deepEqual(armature.bones?.filter((value) => value.selected).map((value) => value.name).sort(), desktop.after.selectedBones); + assert.equal(boneByName.get("WebGapArmatureCollectionSelectActiveBone")?.selected, true); + assert.equal(boneByName.get("WebGapArmatureCollectionSelectFirstBone")?.selected, true); + assert.equal(boneByName.get("WebGapArmatureCollectionSelectLastBone")?.selected, false); + assert.deepEqual(collections.map((value) => value.boneIds), desktop.after.collections.map((value) => [boneByName.get(value.bones?.[0] ?? "")?.id])); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_COLLECTION_SELECT_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation }, wasm: { status: "EXACT", armatureId: armature.id, selectedCollection: "WebGapArmatureCollectionSelectActive", selectedBoneIds: armature.bones.filter((value) => value.selected).map((value) => value.id).sort(), collectionOrder: collections.map((value) => ({ id: value.id, name: value.name, index: value.index, boneIds: value.boneIds })) }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00229" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00228/armature-collection-select-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} selected=active desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00229") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00229-operator-armature.collection_show_all.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00229/armature-collection-show-all-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-collection-show-all-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.poll, true); + assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + assert.deepEqual(desktop.after.collections.map((value) => value.name), ["WebGapArmatureCollectionShowAllFirst", "WebGapArmatureCollectionShowAllHidden", "WebGapArmatureCollectionShowAllLast"]); + assert.ok(desktop.after.collections.every((value) => value.visible === true)); + assert.deepEqual(desktop.after.bones, ["WebGapArmatureCollectionShowAllFirstBone", "WebGapArmatureCollectionShowAllHiddenBone", "WebGapArmatureCollectionShowAllLastBone"]); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureCollectionShowAllArmature"); + assert.ok(armature); + assert.equal(armature.boneCollections?.length, 3); + const collections = armature.boneCollections.toSorted((left, right) => left.index - right.index); + assert.deepEqual(collections.map((value) => value.name), desktop.after.collections.map((value) => value.name)); + assert.ok(collections.every((value) => value.visible === true)); + const boneByName = new Map(armature.bones?.map((value) => [value.name, value])); + assert.deepEqual(armature.bones?.map((value) => value.name).sort(), desktop.after.bones); + assert.deepEqual(collections.map((value) => value.boneIds), desktop.after.collections.map((value) => [boneByName.get(value.bones?.[0] ?? "")?.id])); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_COLLECTION_SHOW_ALL_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation }, wasm: { status: "EXACT", armatureId: armature.id, collectionVisibility: collections.map((value) => ({ id: value.id, name: value.name, index: value.index, visible: value.visible, boneIds: value.boneIds })) }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00230" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00229/armature-collection-show-all-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} visible=all desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00230") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00230-operator-armature.collection_unassign.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00230/armature-collection-unassign-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-collection-unassign-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.poll, true); + assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + assert.equal(desktop.activeCollection, "WebGapArmatureCollectionUnassignSource"); + assert.equal(desktop.unassignedBone, "WebGapArmatureCollectionUnassignBone"); + assert.equal(desktop.after.activeIndex, 0); + assert.deepEqual(desktop.after.selectedBones, ["WebGapArmatureCollectionUnassignBone"]); + assert.deepEqual(desktop.after.collections.map((value) => value.name), ["WebGapArmatureCollectionUnassignSource", "WebGapArmatureCollectionUnassignRetained"]); + assert.deepEqual(desktop.after.collections.map((value) => value.bones), [[], ["WebGapArmatureCollectionUnassignBone"]]); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureCollectionUnassignArmature"); + assert.ok(armature); + assert.equal(armature.boneCollections?.length, 2); + const collections = armature.boneCollections.toSorted((left, right) => left.index - right.index); + assert.deepEqual(collections.map((value) => value.name), desktop.after.collections.map((value) => value.name)); + const boneId = armature.bones?.find((value) => value.name === "WebGapArmatureCollectionUnassignBone")?.id; + assert.ok(boneId); + assert.deepEqual(collections.map((value) => value.boneIds), [[], [boneId]]); + assert.deepEqual(armature.bones?.map((value) => value.name), desktop.after.bones); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_COLLECTION_UNASSIGN_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation }, wasm: { status: "EXACT", armatureId: armature.id, unassignedBoneId: boneId, activeCollection: collections[0].name, collectionOrder: collections.map((value) => ({ id: value.id, name: value.name, index: value.index, boneIds: value.boneIds })) }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00231" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00230/armature-collection-unassign-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} unassigned=${boneId} desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00231") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00231-operator-armature.collection_unassign_named.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00231/armature-collection-unassign-named-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-collection-unassign-named-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.poll, true); + assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + assert.equal(desktop.namedCollection, "WebGapArmatureCollectionUnassignNamedSource"); + assert.equal(desktop.activeCollection, "WebGapArmatureCollectionUnassignNamedRetained"); + assert.equal(desktop.after.activeIndex, 1); + assert.deepEqual(desktop.after.selectedBones, ["WebGapArmatureCollectionUnassignNamedBone"]); + assert.deepEqual(desktop.after.collections.map((value) => value.name), ["WebGapArmatureCollectionUnassignNamedSource", "WebGapArmatureCollectionUnassignNamedRetained"]); + assert.deepEqual(desktop.after.collections.map((value) => value.bones), [[], ["WebGapArmatureCollectionUnassignNamedBone"]]); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureCollectionUnassignNamedArmature"); + assert.ok(armature); + assert.equal(armature.boneCollections?.length, 2); + const collections = armature.boneCollections.toSorted((left, right) => left.index - right.index); + assert.deepEqual(collections.map((value) => value.name), desktop.after.collections.map((value) => value.name)); + const named = collections.find((value) => value.name === desktop.namedCollection); + const active = collections.find((value) => value.name === desktop.activeCollection); + assert.ok(named && active); + const boneId = armature.bones?.find((value) => value.name === "WebGapArmatureCollectionUnassignNamedBone")?.id; + assert.ok(boneId); + assert.deepEqual(named.boneIds, []); + assert.deepEqual(active.boneIds, [boneId]); + assert.deepEqual(armature.bones?.map((value) => value.name), desktop.after.bones); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_COLLECTION_UNASSIGN_NAMED_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, namedCollection: desktop.namedCollection, activeCollection: desktop.activeCollection }, wasm: { status: "EXACT", armatureId: armature.id, unassignedBoneId: boneId, namedCollection: { id: named.id, name: named.name, index: named.index, boneIds: named.boneIds }, activeCollection: { id: active.id, name: active.name, index: active.index, boneIds: active.boneIds } }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00232" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00231/armature-collection-unassign-named-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} unassigned=${boneId} named=source active=retained desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00232") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00232-operator-armature.collection_unsolo_all.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00232/armature-collection-unsolo-all-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-collection-unsolo-all-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.ok([true, false].includes(desktop.poll)); + assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + assert.equal(desktop.soloCollection, "WebGapArmatureCollectionUnsoloAllSolo"); + assert.equal(desktop.after.activeIndex, 1); + assert.equal(desktop.after.isSoloActive, false); + assert.deepEqual(desktop.after.collections.map((value) => value.name), ["WebGapArmatureCollectionUnsoloAllFirst", "WebGapArmatureCollectionUnsoloAllSolo", "WebGapArmatureCollectionUnsoloAllLast"]); + assert.deepEqual(desktop.after.collections.map((value) => value.solo), [false, false, false]); + assert.deepEqual(desktop.after.collections.map((value) => value.visible), [true, true, true]); + assert.deepEqual(desktop.after.collections.map((value) => value.bones), [["WebGapArmatureCollectionUnsoloAllFirstBone"], ["WebGapArmatureCollectionUnsoloAllSoloBone"], ["WebGapArmatureCollectionUnsoloAllLastBone"]]); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureCollectionUnsoloAllArmature"); + assert.ok(armature); + assert.equal(armature.boneCollections?.length, 3); + const collections = armature.boneCollections.toSorted((left, right) => left.index - right.index); + assert.deepEqual(collections.map((value) => value.name), desktop.after.collections.map((value) => value.name)); + assert.deepEqual(collections.map((value) => value.solo), [false, false, false]); + assert.deepEqual(collections.map((value) => value.visible), desktop.after.collections.map((value) => value.visible)); + const boneByName = new Map(armature.bones?.map((value) => [value.name, value])); + assert.deepEqual(collections.map((value) => value.boneIds), desktop.after.collections.map((value) => [boneByName.get(value.bones?.[0] ?? "")?.id])); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_COLLECTION_UNSOLO_ALL_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, soloCollection: desktop.soloCollection }, wasm: { status: "EXACT", armatureId: armature.id, collectionSolo: collections.map((value) => ({ id: value.id, name: value.name, index: value.index, solo: value.solo, visible: value.visible, boneIds: value.boneIds })) }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00233" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00232/armature-collection-unsolo-all-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} solo=none desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00233") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00233-operator-armature.copy_bone_color_to_selected.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00233/armature-copy-bone-color-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-copy-bone-color-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.poll, true); + assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + assert.equal(desktop.sourceBone, "WebGapArmatureCopyBoneColorSource"); + assert.equal(desktop.selectedDestination, "WebGapArmatureCopyBoneColorSelected"); + assert.equal(desktop.unselectedDestination, "WebGapArmatureCopyBoneColorUnselected"); + const desktopByName = new Map(desktop.after.bones.map((bone) => [bone.name, bone])); + const sourceDesktop = desktopByName.get(desktop.sourceBone); + const selectedDesktop = desktopByName.get(desktop.selectedDestination); + const unselectedDesktop = desktopByName.get(desktop.unselectedDestination); + assert.ok(sourceDesktop && selectedDesktop && unselectedDesktop); + assert.deepEqual(selectedDesktop, { ...sourceDesktop, name: desktop.selectedDestination }); + assert.equal(unselectedDesktop.paletteIndex, 5); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureCopyBoneColorArmature"); + assert.ok(armature); + assert.equal(armature.bones?.length, 3); + const bones = new Map(armature.bones.map((bone) => [bone.name, bone])); + const source = bones.get(desktop.sourceBone); + const selected = bones.get(desktop.selectedDestination); + const unselected = bones.get(desktop.unselectedDestination); + assert.ok(source && selected && unselected); + assert.deepEqual(selected.color, source.color); + assert.deepEqual(unselected.color, { + paletteIndex: 5, + normal: unselected.color.normal, + select: unselected.color.select, + active: unselected.color.active, + flag: unselected.color.flag, + }); + assert.equal(source.color.paletteIndex, -1); + assert.deepEqual(source.color.normal, sourceDesktop.normal); + assert.deepEqual(source.color.select, sourceDesktop.selectColor); + assert.deepEqual(source.color.active, sourceDesktop.active); + assert.equal(source.selected, true); + assert.equal(selected.selected, true); + assert.equal(unselected.selected, false); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_COPY_BONE_COLOR_TO_SELECTED_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation }, wasm: { status: "EXACT", armatureId: armature.id, sourceBone: source.id, selectedDestination: selected.id, unselectedDestination: unselected.id, colors: { source: source.color, selected: selected.color, unselected: unselected.color } }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00234" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00233/armature-copy-bone-color-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} copied=selected desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00234") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00234-operator-armature.delete.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00234/armature-delete-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-delete-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.ok([true, false].includes(desktop.poll)); + assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + assert.equal(desktop.deletedBone, "WebGapArmatureDeleteSelected"); + assert.deepEqual(desktop.after.bones.map((bone) => bone.name), ["WebGapArmatureDeleteKeep", "WebGapArmatureDeleteRetain"]); + assert.equal(desktop.after.activeBone, null); + assert.ok(desktop.after.bones.every((bone) => bone.selected === false)); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureDeleteArmature"); + assert.ok(armature); + assert.deepEqual(armature.bones?.map((bone) => bone.name), desktop.after.bones.map((bone) => bone.name)); + assert.equal(armature.bones?.some((bone) => bone.name === desktop.deletedBone), false); + assert.ok(armature.bones?.every((bone) => bone.selected === false)); + assert.ok(armature.bones?.every((bone) => bone.parentId === null)); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_DELETE_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, deletedBone: desktop.deletedBone }, wasm: { status: "EXACT", armatureId: armature.id, remainingBoneIds: armature.bones.map((bone) => bone.id), deletedBonePresent: false, selectedBoneIds: armature.bones.filter((bone) => bone.selected).map((bone) => bone.id) }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00235" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00234/armature-delete-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} deleted=${desktop.deletedBone} remaining=${armature.bones.length} desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00235") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00235-operator-armature.dissolve.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00235/armature-dissolve-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-dissolve-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.ok([true, false].includes(desktop.poll)); + assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + assert.equal(desktop.dissolvedBone, "WebGapArmatureDissolveTip"); + assert.deepEqual(desktop.after.bones.map((bone) => bone.name), ["WebGapArmatureDissolveRoot", "WebGapArmatureDissolveOther"]); + assert.equal(desktop.after.activeBone, null); + assert.ok(desktop.after.bones.every((bone) => bone.selected === false)); + const desktopRoot = desktop.after.bones[0]; + const desktopOther = desktop.after.bones[1]; + assert.deepEqual(desktopRoot, { name: "WebGapArmatureDissolveRoot", selected: false, parent: null, connected: false, head: [0, 0, 0], tail: [0, 3, 0] }); + assert.deepEqual(desktopOther, { name: "WebGapArmatureDissolveOther", selected: false, parent: null, connected: false, head: [2, 0, 0], tail: [2, 1, 0] }); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureDissolveArmature"); + assert.ok(armature); + assert.deepEqual(armature.bones?.map((bone) => bone.name), desktop.after.bones.map((bone) => bone.name)); + const rootBone = armature.bones?.[0]; + const otherBone = armature.bones?.[1]; + assert.ok(rootBone && otherBone); + assert.equal(rootBone.parentId, null); + assert.equal(otherBone.parentId, null); + assert.equal(rootBone.selected, false); + assert.equal(otherBone.selected, false); + assert.deepEqual(rootBone.head, desktopRoot.head); + assert.deepEqual(rootBone.tail, desktopRoot.tail); + assert.deepEqual(otherBone.head, desktopOther.head); + assert.deepEqual(otherBone.tail, desktopOther.tail); + assert.equal(armature.bones?.some((bone) => ["WebGapArmatureDissolveMiddle", desktop.dissolvedBone].includes(bone.name)), false); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_DISSOLVE_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, dissolvedBone: desktop.dissolvedBone }, wasm: { status: "EXACT", armatureId: armature.id, remainingBoneIds: armature.bones.map((bone) => bone.id), dissolvedBonePresent: false, survivingRoot: { id: rootBone.id, head: rootBone.head, tail: rootBone.tail }, independentBone: { id: otherBone.id, head: otherBone.head, tail: otherBone.tail } }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00236" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00235/armature-dissolve-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} dissolved=${desktop.dissolvedBone} remaining=${armature.bones.length} desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00236") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00236-operator-armature.duplicate.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00236/armature-duplicate-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-duplicate-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.ok([true, false].includes(desktop.poll)); + assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + assert.equal(desktop.sourceBone, "WebGapArmatureDuplicateSource"); + assert.equal(desktop.duplicateBone, "WebGapArmatureDuplicateSource.001"); + assert.deepEqual(desktop.after.bones.map((bone) => bone.name), ["WebGapArmatureDuplicateSource", "WebGapArmatureDuplicateOther", "WebGapArmatureDuplicateSource.001"]); + assert.equal(desktop.after.activeBone, desktop.duplicateBone); + assert.deepEqual(desktop.after.bones.filter((bone) => bone.selected).map((bone) => bone.name), [desktop.duplicateBone]); + const desktopSource = desktop.after.bones[0]; + const desktopOther = desktop.after.bones[1]; + const desktopDuplicate = desktop.after.bones[2]; + assert.deepEqual(desktopDuplicate.head, desktopSource.head); + assert.deepEqual(desktopDuplicate.tail, desktopSource.tail); + assert.equal(desktopDuplicate.parent, null); + assert.equal(desktopDuplicate.connected, false); + assert.deepEqual(desktopOther, { name: "WebGapArmatureDuplicateOther", selected: false, selectHead: false, selectTail: false, parent: null, connected: false, head: [2, 0, 0], tail: [2, 1, 0] }); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureDuplicateArmature"); + assert.ok(armature); + assert.deepEqual(armature.bones?.map((bone) => bone.name), desktop.after.bones.map((bone) => bone.name)); + const source = armature.bones?.find((bone) => bone.name === desktop.sourceBone); + const other = armature.bones?.find((bone) => bone.name === "WebGapArmatureDuplicateOther"); + const duplicate = armature.bones?.find((bone) => bone.name === desktop.duplicateBone); + assert.ok(source && other && duplicate); + assert.equal(source.selected, false); + assert.equal(other.selected, false); + assert.equal(duplicate.selected, true); + assert.equal(source.parentId, null); + assert.equal(other.parentId, null); + assert.equal(duplicate.parentId, null); + assert.deepEqual(source.head, duplicate.head); + assert.deepEqual(source.tail, duplicate.tail); + assert.deepEqual(other.head, desktopOther.head); + assert.deepEqual(other.tail, desktopOther.tail); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_DUPLICATE_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, sourceBone: desktop.sourceBone, duplicateBone: desktop.duplicateBone }, wasm: { status: "EXACT", armatureId: armature.id, sourceBoneId: source.id, duplicateBoneId: duplicate.id, otherBoneId: other.id, duplicateSelected: duplicate.selected, geometryMatch: source.head.join(",") === duplicate.head.join(",") && source.tail.join(",") === duplicate.tail.join(",") }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00237" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00236/armature-duplicate-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} duplicate=${desktop.duplicateBone} remaining=${armature.bones.length} desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00237") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00237-operator-armature.duplicate_move.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00237/armature-duplicate-move-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-duplicate-move-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.ok([true, false].includes(desktop.poll)); + assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + assert.equal(desktop.sourceBone, "WebGapArmatureDuplicateMoveSource"); + assert.equal(desktop.duplicateBone, "WebGapArmatureDuplicateMoveSource.001"); + assert.deepEqual(desktop.translation, [1, 2, 3]); + assert.deepEqual(desktop.after.bones.map((bone) => bone.name), [desktop.sourceBone, "WebGapArmatureDuplicateMoveOther", desktop.duplicateBone]); + assert.equal(desktop.after.activeBone, desktop.duplicateBone); + assert.deepEqual(desktop.after.bones.filter((bone) => bone.selected).map((bone) => bone.name), [desktop.duplicateBone]); + const desktopSource = desktop.after.bones[0]; + const desktopOther = desktop.after.bones[1]; + const desktopDuplicate = desktop.after.bones[2]; + assert.deepEqual(desktopSource.head, [0, 0, 0]); + assert.deepEqual(desktopSource.tail, [0, 1, 0]); + assert.deepEqual(desktopDuplicate.head, [1, 2, 3]); + assert.deepEqual(desktopDuplicate.tail, [1, 3, 3]); + assert.equal(desktopDuplicate.parent, null); + assert.equal(desktopDuplicate.connected, false); + assert.deepEqual(desktopOther, { name: "WebGapArmatureDuplicateMoveOther", selected: false, selectHead: false, selectTail: false, parent: null, connected: false, head: [2, 0, 0], tail: [2, 1, 0] }); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureDuplicateMoveArmature"); + assert.ok(armature); + assert.deepEqual(armature.bones?.map((bone) => bone.name), desktop.after.bones.map((bone) => bone.name)); + const source = armature.bones?.find((bone) => bone.name === desktop.sourceBone); + const other = armature.bones?.find((bone) => bone.name === "WebGapArmatureDuplicateMoveOther"); + const duplicate = armature.bones?.find((bone) => bone.name === desktop.duplicateBone); + assert.ok(source && other && duplicate); + assert.equal(source.selected, false); + assert.equal(other.selected, false); + assert.equal(duplicate.selected, true); + assert.equal(source.parentId, null); + assert.equal(other.parentId, null); + assert.equal(duplicate.parentId, null); + assert.deepEqual(source.head, desktopSource.head); + assert.deepEqual(source.tail, desktopSource.tail); + assert.deepEqual(duplicate.head, desktopDuplicate.head); + assert.deepEqual(duplicate.tail, desktopDuplicate.tail); + assert.deepEqual(other.head, desktopOther.head); + assert.deepEqual(other.tail, desktopOther.tail); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_DUPLICATE_MOVE_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, sourceBone: desktop.sourceBone, duplicateBone: desktop.duplicateBone, translation: desktop.translation }, wasm: { status: "EXACT", armatureId: armature.id, sourceBoneId: source.id, duplicateBoneId: duplicate.id, otherBoneId: other.id, duplicateSelected: duplicate.selected, translation: [duplicate.head[0] - source.head[0], duplicate.head[1] - source.head[1], duplicate.head[2] - source.head[2]], geometryMatch: duplicate.head.join(",") === "1,2,3" && duplicate.tail.join(",") === "1,3,3" }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00238" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00237/armature-duplicate-move-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} duplicate=${desktop.duplicateBone} translation=1,2,3 desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00238") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00238-operator-armature.duplicate_rename.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00238/armature-duplicate-rename-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-duplicate-rename-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.ok([true, false].includes(desktop.poll)); + assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + assert.equal(desktop.sourceBone, "WebGapArmatureDuplicateRenameSource"); + assert.equal(desktop.duplicateBone, "WebGapArmatureDuplicateRenameCopy"); + assert.equal(desktop.search, "Source"); + assert.equal(desktop.replace, "Copy"); + assert.deepEqual(desktop.after.bones.map((bone) => bone.name), [desktop.sourceBone, "WebGapArmatureDuplicateRenameOther", desktop.duplicateBone]); + assert.equal(desktop.after.activeBone, desktop.duplicateBone); + assert.deepEqual(desktop.after.bones.filter((bone) => bone.selected).map((bone) => bone.name), [desktop.duplicateBone]); + const desktopSource = desktop.after.bones[0]; + const desktopOther = desktop.after.bones[1]; + const desktopDuplicate = desktop.after.bones[2]; + assert.deepEqual(desktopDuplicate.head, desktopSource.head); + assert.deepEqual(desktopDuplicate.tail, desktopSource.tail); + assert.equal(desktopDuplicate.parent, null); + assert.equal(desktopDuplicate.connected, false); + assert.deepEqual(desktopOther, { name: "WebGapArmatureDuplicateRenameOther", selected: false, selectHead: false, selectTail: false, parent: null, connected: false, head: [2, 0, 0], tail: [2, 1, 0] }); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureDuplicateRenameArmature"); + assert.ok(armature); + assert.deepEqual(armature.bones?.map((bone) => bone.name), desktop.after.bones.map((bone) => bone.name)); + const source = armature.bones?.find((bone) => bone.name === desktop.sourceBone); + const other = armature.bones?.find((bone) => bone.name === "WebGapArmatureDuplicateRenameOther"); + const duplicate = armature.bones?.find((bone) => bone.name === desktop.duplicateBone); + assert.ok(source && other && duplicate); + assert.equal(source.selected, false); + assert.equal(other.selected, false); + assert.equal(duplicate.selected, true); + assert.equal(source.parentId, null); + assert.equal(other.parentId, null); + assert.equal(duplicate.parentId, null); + assert.deepEqual(source.head, desktopSource.head); + assert.deepEqual(source.tail, desktopSource.tail); + assert.deepEqual(duplicate.head, desktopDuplicate.head); + assert.deepEqual(duplicate.tail, desktopDuplicate.tail); + assert.deepEqual(other.head, desktopOther.head); + assert.deepEqual(other.tail, desktopOther.tail); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_DUPLICATE_RENAME_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, sourceBone: desktop.sourceBone, duplicateBone: desktop.duplicateBone, search: desktop.search, replace: desktop.replace }, wasm: { status: "EXACT", armatureId: armature.id, sourceBoneId: source.id, duplicateBoneId: duplicate.id, otherBoneId: other.id, duplicateSelected: duplicate.selected, renamedName: duplicate.name, geometryMatch: source.head.join(",") === duplicate.head.join(",") && source.tail.join(",") === duplicate.tail.join(",") }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00239" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00238/armature-duplicate-rename-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} duplicate=${desktop.duplicateBone} rename=Source->Copy desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00239") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00239-operator-armature.extrude.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00239/armature-extrude-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-extrude-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.ok([true, false].includes(desktop.poll)); + assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + assert.equal(desktop.sourceBone, "WebGapArmatureExtrudeSource"); + assert.equal(desktop.extrudeBone, "WebGapArmatureExtrudeSource.001"); + assert.deepEqual(desktop.translation, [0, 1, 0]); + assert.deepEqual([...desktop.after.bones.map((bone) => bone.name)].sort(), [desktop.sourceBone, desktop.extrudeBone, "WebGapArmatureExtrudeOther"].sort()); + assert.equal(desktop.after.activeBone, desktop.extrudeBone); + assert.deepEqual(desktop.after.bones.filter((bone) => bone.selected).map((bone) => bone.name), [desktop.extrudeBone]); + const desktopSource = desktop.after.bones.find((bone) => bone.name === desktop.sourceBone); + const desktopExtrude = desktop.after.bones.find((bone) => bone.name === desktop.extrudeBone); + const desktopOther = desktop.after.bones.find((bone) => bone.name === "WebGapArmatureExtrudeOther"); + assert.deepEqual(desktopExtrude.head, [0, 1, 0]); + assert.deepEqual(desktopExtrude.tail, [0, 2, 0]); + assert.equal(desktopExtrude.parent, desktop.sourceBone); + assert.equal(desktopExtrude.connected, true); + assert.deepEqual(desktopOther, { name: "WebGapArmatureExtrudeOther", selected: false, selectHead: false, selectTail: false, parent: null, connected: false, head: [2, 0, 0], tail: [2, 1, 0] }); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureExtrudeArmature"); + assert.ok(armature); + assert.deepEqual([...armature.bones?.map((bone) => bone.name)].sort(), [...desktop.after.bones.map((bone) => bone.name)].sort()); + const source = armature.bones?.find((bone) => bone.name === desktop.sourceBone); + const other = armature.bones?.find((bone) => bone.name === "WebGapArmatureExtrudeOther"); + const extrude = armature.bones?.find((bone) => bone.name === desktop.extrudeBone); + assert.ok(source && other && extrude); + assert.equal(source.selected, false); + assert.equal(other.selected, false); + assert.equal(extrude.selected, true); + assert.equal(source.parentId, null); + assert.equal(other.parentId, null); + assert.equal(extrude.parentId, source.id); + assert.deepEqual(source.head, desktopSource.head); + assert.deepEqual(source.tail, desktopSource.tail); + const desktopParentTail = desktopSource.tail; + assert.deepEqual(extrude.head, desktopExtrude.head.map((value, index) => value - desktopParentTail[index])); + assert.deepEqual(extrude.tail, desktopExtrude.tail.map((value, index) => value - desktopParentTail[index])); + assert.deepEqual(other.head, desktopOther.head); + assert.deepEqual(other.tail, desktopOther.tail); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_EXTRUDE_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, sourceBone: desktop.sourceBone, extrudeBone: desktop.extrudeBone, translation: desktop.translation }, wasm: { status: "EXACT", armatureId: armature.id, sourceBoneId: source.id, extrudeBoneId: extrude.id, otherBoneId: other.id, extrudeSelected: extrude.selected, parentId: extrude.parentId, geometry: { head: extrude.head, tail: extrude.tail } }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00240" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00239/armature-extrude-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} extrude=${desktop.extrudeBone} translation=0,1,0 desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00240") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00240-operator-armature.extrude_forked.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00240/armature-extrude-forked-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-extrude-forked-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.forked, true); + assert.ok([true, false].includes(desktop.poll)); + assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + assert.equal(desktop.sourceBone, "WebGapArmatureExtrudeForkedSource"); + assert.equal(desktop.forkedBone, "WebGapArmatureExtrudeForkedSource.001"); + assert.deepEqual(desktop.translation, [0, 1, 0]); + assert.deepEqual([...desktop.after.bones.map((bone) => bone.name)].sort(), [desktop.sourceBone, desktop.forkedBone, "WebGapArmatureExtrudeForkedOther"].sort()); + assert.equal(desktop.after.activeBone, desktop.forkedBone); + assert.deepEqual(desktop.after.bones.filter((bone) => bone.selected).map((bone) => bone.name), [desktop.forkedBone]); + const desktopSource = desktop.after.bones.find((bone) => bone.name === desktop.sourceBone); + const desktopForked = desktop.after.bones.find((bone) => bone.name === desktop.forkedBone); + const desktopOther = desktop.after.bones.find((bone) => bone.name === "WebGapArmatureExtrudeForkedOther"); + assert.deepEqual(desktopForked.head, [0, 1, 0]); + assert.deepEqual(desktopForked.tail, [0, 2, 0]); + assert.equal(desktopForked.parent, desktop.sourceBone); + assert.equal(desktopForked.connected, false); + assert.deepEqual(desktopOther, { name: "WebGapArmatureExtrudeForkedOther", selected: false, selectHead: false, selectTail: false, parent: null, connected: false, head: [2, 0, 0], tail: [2, 1, 0] }); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureExtrudeForkedArmature"); + assert.ok(armature); + assert.deepEqual([...armature.bones?.map((bone) => bone.name)].sort(), [...desktop.after.bones.map((bone) => bone.name)].sort()); + const source = armature.bones?.find((bone) => bone.name === desktop.sourceBone); + const other = armature.bones?.find((bone) => bone.name === "WebGapArmatureExtrudeForkedOther"); + const forked = armature.bones?.find((bone) => bone.name === desktop.forkedBone); + assert.ok(source && other && forked); + assert.equal(source.selected, false); + assert.equal(other.selected, false); + assert.equal(forked.selected, true); + assert.equal(source.parentId, null); + assert.equal(other.parentId, null); + assert.equal(forked.parentId, source.id); + assert.deepEqual(source.head, desktopSource.head); + assert.deepEqual(source.tail, desktopSource.tail); + const desktopParentTail = desktopSource.tail; + assert.deepEqual(forked.head, desktopForked.head.map((value, index) => value - desktopParentTail[index])); + assert.deepEqual(forked.tail, desktopForked.tail.map((value, index) => value - desktopParentTail[index])); + assert.deepEqual(other.head, desktopOther.head); + assert.deepEqual(other.tail, desktopOther.tail); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_EXTRUDE_FORKED_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, forked: desktop.forked, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, sourceBone: desktop.sourceBone, forkedBone: desktop.forkedBone, translation: desktop.translation }, wasm: { status: "EXACT", armatureId: armature.id, sourceBoneId: source.id, forkedBoneId: forked.id, otherBoneId: other.id, forkedSelected: forked.selected, parentId: forked.parentId, connected: false, geometry: { head: forked.head, tail: forked.tail } }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00241" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00240/armature-extrude-forked-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} forked=${desktop.forkedBone} connected=false desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00241") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00241-operator-armature.extrude_move.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00241/armature-extrude-move-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-extrude-move-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.ok([true, false].includes(desktop.poll)); + assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + assert.equal(desktop.sourceBone, "WebGapArmatureExtrudeMoveSource"); + assert.equal(desktop.extrudeBone, "WebGapArmatureExtrudeMoveSource.001"); + assert.deepEqual(desktop.translation, [0, 1, 0]); + assert.deepEqual([...desktop.after.bones.map((bone) => bone.name)].sort(), [desktop.sourceBone, desktop.extrudeBone, "WebGapArmatureExtrudeMoveOther"].sort()); + assert.equal(desktop.after.activeBone, desktop.extrudeBone); + assert.deepEqual(desktop.after.bones.filter((bone) => bone.selected).map((bone) => bone.name), [desktop.extrudeBone]); + const desktopSource = desktop.after.bones.find((bone) => bone.name === desktop.sourceBone); + const desktopExtrude = desktop.after.bones.find((bone) => bone.name === desktop.extrudeBone); + const desktopOther = desktop.after.bones.find((bone) => bone.name === "WebGapArmatureExtrudeMoveOther"); + assert.deepEqual(desktopExtrude.head, [0, 1, 0]); + assert.deepEqual(desktopExtrude.tail, [0, 2, 0]); + assert.equal(desktopExtrude.parent, desktop.sourceBone); + assert.equal(desktopExtrude.connected, true); + assert.deepEqual(desktopOther, { name: "WebGapArmatureExtrudeMoveOther", selected: false, selectHead: false, selectTail: false, parent: null, connected: false, head: [2, 0, 0], tail: [2, 1, 0] }); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureExtrudeMoveArmature"); + assert.ok(armature); + assert.deepEqual([...armature.bones?.map((bone) => bone.name)].sort(), [...desktop.after.bones.map((bone) => bone.name)].sort()); + const source = armature.bones?.find((bone) => bone.name === desktop.sourceBone); + const other = armature.bones?.find((bone) => bone.name === "WebGapArmatureExtrudeMoveOther"); + const extrude = armature.bones?.find((bone) => bone.name === desktop.extrudeBone); + assert.ok(source && other && extrude); + assert.equal(source.selected, false); + assert.equal(other.selected, false); + assert.equal(extrude.selected, true); + assert.equal(source.parentId, null); + assert.equal(other.parentId, null); + assert.equal(extrude.parentId, source.id); + assert.deepEqual(source.head, desktopSource.head); + assert.deepEqual(source.tail, desktopSource.tail); + const desktopParentTail = desktopSource.tail; + assert.deepEqual(extrude.head, desktopExtrude.head.map((value, index) => value - desktopParentTail[index])); + assert.deepEqual(extrude.tail, desktopExtrude.tail.map((value, index) => value - desktopParentTail[index])); + assert.deepEqual(other.head, desktopOther.head); + assert.deepEqual(other.tail, desktopOther.tail); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_EXTRUDE_MOVE_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, sourceBone: desktop.sourceBone, extrudeBone: desktop.extrudeBone, translation: desktop.translation }, wasm: { status: "EXACT", armatureId: armature.id, sourceBoneId: source.id, extrudeBoneId: extrude.id, otherBoneId: other.id, extrudeSelected: extrude.selected, parentId: extrude.parentId, connected: true, geometry: { head: extrude.head, tail: extrude.tail } }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00242" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00241/armature-extrude-move-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} extrude=${desktop.extrudeBone} translation=0,1,0 desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00242") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00242-operator-armature.fill.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00242/armature-fill-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-fill-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.ok([true, false].includes(desktop.poll)); + assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + assert.equal(desktop.sourceBone, "WebGapArmatureFillSource"); + assert.equal(desktop.targetBone, "WebGapArmatureFillTarget"); + assert.equal(desktop.bridgeBone, "WebGapArmatureFillBridge"); + assert.deepEqual([...desktop.after.bones.map((bone) => bone.name)].sort(), [desktop.sourceBone, desktop.targetBone, desktop.bridgeBone, "WebGapArmatureFillOther"].sort()); + assert.equal(desktop.after.activeBone, desktop.bridgeBone); + assert.deepEqual(desktop.after.bones.filter((bone) => bone.selected).map((bone) => bone.name), [desktop.bridgeBone]); + const desktopSource = desktop.after.bones.find((bone) => bone.name === desktop.sourceBone); + const desktopTarget = desktop.after.bones.find((bone) => bone.name === desktop.targetBone); + const desktopBridge = desktop.after.bones.find((bone) => bone.name === desktop.bridgeBone); + const desktopOther = desktop.after.bones.find((bone) => bone.name === "WebGapArmatureFillOther"); + assert.deepEqual(desktopBridge.head, [0, 1, 0]); + assert.deepEqual(desktopBridge.tail, [0, 2, 0]); + assert.equal(desktopBridge.parent, desktop.sourceBone); + assert.equal(desktopBridge.connected, true); + assert.deepEqual(desktopTarget.head, [0, 2, 0]); + assert.deepEqual(desktopTarget.tail, [0, 3, 0]); + assert.deepEqual(desktopOther, { name: "WebGapArmatureFillOther", selected: false, selectHead: false, selectTail: false, parent: null, connected: false, head: [2, 0, 0], tail: [2, 1, 0] }); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureFillArmature"); + assert.ok(armature); + assert.deepEqual([...armature.bones?.map((bone) => bone.name)].sort(), [...desktop.after.bones.map((bone) => bone.name)].sort()); + const source = armature.bones?.find((bone) => bone.name === desktop.sourceBone); + const target = armature.bones?.find((bone) => bone.name === desktop.targetBone); + const bridge = armature.bones?.find((bone) => bone.name === desktop.bridgeBone); + const other = armature.bones?.find((bone) => bone.name === "WebGapArmatureFillOther"); + assert.ok(source && target && bridge && other); + assert.equal(source.selected, false); + assert.equal(target.selected, false); + assert.equal(bridge.selected, true); + assert.equal(other.selected, false); + assert.equal(source.parentId, null); + assert.equal(target.parentId, null); + assert.equal(bridge.parentId, source.id); + assert.deepEqual(source.head, desktopSource.head); + assert.deepEqual(source.tail, desktopSource.tail); + const desktopParentTail = desktopSource.tail; + assert.deepEqual(bridge.head, desktopBridge.head.map((value, index) => value - desktopParentTail[index])); + assert.deepEqual(bridge.tail, desktopBridge.tail.map((value, index) => value - desktopParentTail[index])); + assert.deepEqual(target.head, desktopTarget.head); + assert.deepEqual(target.tail, desktopTarget.tail); + assert.deepEqual(other.head, desktopOther.head); + assert.deepEqual(other.tail, desktopOther.tail); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_FILL_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, sourceBone: desktop.sourceBone, targetBone: desktop.targetBone, bridgeBone: desktop.bridgeBone }, wasm: { status: "EXACT", armatureId: armature.id, sourceBoneId: source.id, targetBoneId: target.id, bridgeBoneId: bridge.id, otherBoneId: other.id, bridgeSelected: bridge.selected, parentId: bridge.parentId, connected: true, geometry: { head: bridge.head, tail: bridge.tail } }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00243" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00242/armature-fill-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} bridge=${desktop.bridgeBone} endpoints=source-tail,target-head desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00243") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00243-operator-armature.flip_names.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00243/armature-flip-names-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-flip-names-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.doStripNumbers, false); + assert.ok([true, false].includes(desktop.poll)); + assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + assert.equal(desktop.leftGeometryBone, "WebGapArmatureFlipBone.R"); + assert.equal(desktop.rightGeometryBone, "WebGapArmatureFlipBone.L"); + const desktopLeft = desktop.after.bones.find((bone) => bone.head[0] === -1); + const desktopRight = desktop.after.bones.find((bone) => bone.head[0] === 1); + const desktopOther = desktop.after.bones.find((bone) => bone.name === "WebGapArmatureFlipOther"); + assert.equal(desktopLeft.name, desktop.leftGeometryBone); + assert.equal(desktopRight.name, desktop.rightGeometryBone); + assert.deepEqual(desktopLeft.head, [-1, 0, 0]); + assert.deepEqual(desktopLeft.tail, [-1, 1, 0]); + assert.deepEqual(desktopRight.head, [1, 0, 0]); + assert.deepEqual(desktopRight.tail, [1, 1, 0]); + assert.deepEqual(desktopOther, { name: "WebGapArmatureFlipOther", selected: false, selectHead: false, selectTail: false, parent: null, connected: false, head: [0, 0, 2], tail: [0, 1, 2] }); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureFlipNamesArmature"); + assert.ok(armature); + const left = armature.bones?.find((bone) => bone.head[0] === -1); + const right = armature.bones?.find((bone) => bone.head[0] === 1); + const other = armature.bones?.find((bone) => bone.name === "WebGapArmatureFlipOther"); + assert.ok(left && right && other); + assert.equal(left.name, desktop.leftGeometryBone); + assert.equal(right.name, desktop.rightGeometryBone); + assert.equal(left.selected, true); + assert.equal(right.selected, true); + assert.equal(other.selected, false); + assert.deepEqual(left.head, desktopLeft.head); + assert.deepEqual(left.tail, desktopLeft.tail); + assert.deepEqual(right.head, desktopRight.head); + assert.deepEqual(right.tail, desktopRight.tail); + assert.deepEqual(other.head, desktopOther.head); + assert.deepEqual(other.tail, desktopOther.tail); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_FLIP_NAMES_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, leftGeometryBone: desktop.leftGeometryBone, rightGeometryBone: desktop.rightGeometryBone, doStripNumbers: desktop.doStripNumbers }, wasm: { status: "EXACT", armatureId: armature.id, leftBoneId: left.id, rightBoneId: right.id, otherBoneId: other.id, leftName: left.name, rightName: right.name, geometryNamesFlipped: left.name === "WebGapArmatureFlipBone.R" && right.name === "WebGapArmatureFlipBone.L" }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00244" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00243/armature-flip-names-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} left=${left.name} right=${right.name} desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00244") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00244-operator-armature.hide.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00244/armature-hide-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-hide-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.unselected, false); + assert.ok([true, false].includes(desktop.poll)); + assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + assert.equal(desktop.hiddenBone, "WebGapArmatureHideSelected"); + const desktopHidden = desktop.after.bones.find((bone) => bone.name === desktop.hiddenBone); + const desktopOther = desktop.after.bones.find((bone) => bone.name === "WebGapArmatureHideOther"); + assert.deepEqual(desktopHidden, { name: desktop.hiddenBone, selected: false, hidden: true, selectHead: false, selectTail: false, parent: null, connected: false, head: [-1, 0, 0], tail: [-1, 1, 0] }); + assert.deepEqual(desktopOther, { name: "WebGapArmatureHideOther", selected: false, hidden: false, selectHead: false, selectTail: false, parent: null, connected: false, head: [1, 0, 0], tail: [1, 1, 0] }); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureHideArmature"); + assert.ok(armature); + const hidden = armature.bones?.find((bone) => bone.name === desktop.hiddenBone); + const other = armature.bones?.find((bone) => bone.name === "WebGapArmatureHideOther"); + assert.ok(hidden && other); + assert.equal(hidden.hidden, true); + assert.equal(hidden.selected, false); + assert.equal(other.hidden, false); + assert.equal(other.selected, false); + assert.deepEqual(hidden.head, desktopHidden.head); + assert.deepEqual(hidden.tail, desktopHidden.tail); + assert.deepEqual(other.head, desktopOther.head); + assert.deepEqual(other.tail, desktopOther.tail); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_HIDE_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, hiddenBone: desktop.hiddenBone, unselected: desktop.unselected }, wasm: { status: "EXACT", armatureId: armature.id, hiddenBoneId: hidden.id, otherBoneId: other.id, hidden: hidden.hidden, selectedAfterHide: hidden.selected, otherHidden: other.hidden }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00245" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00244/armature-hide-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} hidden=${hidden.name} hiddenFlag=${hidden.hidden} desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00245") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00245-operator-armature.move_to_collection.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00245/armature-move-to-collection-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-move-to-collection-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.collectionIndex, 1); + assert.ok([true, false].includes(desktop.poll)); + assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + assert.equal(desktop.movedBone, "WebGapArmatureMoveCollectionSelected"); + assert.equal(desktop.sourceCollection, "WebGapArmatureMoveCollectionSource"); + assert.equal(desktop.targetCollection, "WebGapArmatureMoveCollectionTarget"); + const desktopMove = desktop.after.bones.find((bone) => bone.name === desktop.movedBone); + const desktopOther = desktop.after.bones.find((bone) => bone.name === "WebGapArmatureMoveCollectionOther"); + assert.deepEqual(desktopMove.collections, [desktop.targetCollection]); + assert.deepEqual(desktopOther.collections, [desktop.sourceCollection]); + assert.equal(desktopMove.selected, true); + assert.equal(desktopOther.selected, false); + assert.deepEqual(desktopMove.head, [-1, 0, 0]); + assert.deepEqual(desktopMove.tail, [-1, 1, 0]); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureMoveCollectionArmature"); + assert.ok(armature); + const moved = armature.bones?.find((bone) => bone.name === desktop.movedBone); + const other = armature.bones?.find((bone) => bone.name === "WebGapArmatureMoveCollectionOther"); + assert.ok(moved && other); + const sourceCollection = armature.boneCollections?.find((collection) => collection.name === desktop.sourceCollection); + const targetCollection = armature.boneCollections?.find((collection) => collection.name === desktop.targetCollection); + assert.ok(sourceCollection && targetCollection); + assert.deepEqual(sourceCollection.boneIds, [other.id]); + assert.deepEqual(targetCollection.boneIds, [moved.id]); + assert.equal(moved.selected, true); + assert.equal(other.selected, false); + assert.deepEqual(moved.head, desktopMove.head); + assert.deepEqual(moved.tail, desktopMove.tail); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_MOVE_TO_COLLECTION_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, movedBone: desktop.movedBone, sourceCollection: desktop.sourceCollection, targetCollection: desktop.targetCollection }, wasm: { status: "EXACT", armatureId: armature.id, movedBoneId: moved.id, otherBoneId: other.id, sourceCollectionId: sourceCollection.id, targetCollectionId: targetCollection.id, sourceMembers: sourceCollection.boneIds, targetMembers: targetCollection.boneIds }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00246" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00245/armature-move-to-collection-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} moved=${moved.name} target=${targetCollection.name} desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00246") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00246-operator-armature.parent_clear.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00246/armature-parent-clear-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-parent-clear-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.clearType, "CLEAR"); + assert.ok([true, false].includes(desktop.poll)); + assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + assert.equal(desktop.parentBone, "WebGapArmatureParentClearParent"); + assert.equal(desktop.childBone, "WebGapArmatureParentClearChild"); + const desktopParent = desktop.after.bones.find((bone) => bone.name === desktop.parentBone); + const desktopChild = desktop.after.bones.find((bone) => bone.name === desktop.childBone); + const desktopOther = desktop.after.bones.find((bone) => bone.name === "WebGapArmatureParentClearOther"); + assert.equal(desktopChild.parent, null); + assert.equal(desktopChild.connected, false); + assert.equal(desktopChild.selected, true); + assert.equal(desktopParent.parent, null); + assert.equal(desktopOther.parent, null); + assert.deepEqual(desktopChild.head, [0, 1, 0]); + assert.deepEqual(desktopChild.tail, [0, 2, 0]); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureParentClearArmature"); + assert.ok(armature); + const parent = armature.bones?.find((bone) => bone.name === desktop.parentBone); + const child = armature.bones?.find((bone) => bone.name === desktop.childBone); + const other = armature.bones?.find((bone) => bone.name === "WebGapArmatureParentClearOther"); + assert.ok(parent && child && other); + assert.equal(child.parentId, null); + assert.equal(child.selected, true); + assert.equal(parent.parentId, null); + assert.equal(other.parentId, null); + assert.deepEqual(child.head, desktopChild.head); + assert.deepEqual(child.tail, desktopChild.tail); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_PARENT_CLEAR_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, parentBone: desktop.parentBone, childBone: desktop.childBone, clearType: desktop.clearType }, wasm: { status: "EXACT", armatureId: armature.id, parentBoneId: parent.id, childBoneId: child.id, otherBoneId: other.id, childParentId: child.parentId, childSelected: child.selected }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00247" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00246/armature-parent-clear-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} child=${child.name} parentId=${child.parentId} desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00247") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00247-operator-armature.parent_set.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00247/armature-parent-set-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-parent-set-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.setType, "CONNECTED"); + assert.ok([true, false].includes(desktop.poll)); + assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + assert.equal(desktop.parentBone, "WebGapArmatureParentSetParent"); + assert.equal(desktop.childBone, "WebGapArmatureParentSetChild"); + const desktopParent = desktop.after.bones.find((bone) => bone.name === desktop.parentBone); + const desktopChild = desktop.after.bones.find((bone) => bone.name === desktop.childBone); + const desktopOther = desktop.after.bones.find((bone) => bone.name === "WebGapArmatureParentSetOther"); + assert.equal(desktopChild.parent, desktop.parentBone); + assert.equal(desktopChild.connected, true); + assert.equal(desktopChild.selected, true); + assert.equal(desktopParent.parent, null); + assert.equal(desktopOther.parent, null); + assert.deepEqual(desktopChild.head, [0, 1, 0]); + assert.deepEqual(desktopChild.tail, [0, 2, 0]); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureParentSetArmature"); + assert.ok(armature); + const parent = armature.bones?.find((bone) => bone.name === desktop.parentBone); + const child = armature.bones?.find((bone) => bone.name === desktop.childBone); + const other = armature.bones?.find((bone) => bone.name === "WebGapArmatureParentSetOther"); + assert.ok(parent && child && other); + assert.equal(child.parentId, parent.id); + assert.equal(child.connected, true); + assert.equal(child.selected, true); + assert.equal(parent.parentId, null); + assert.equal(other.parentId, null); + assert.deepEqual(child.head, desktopChild.head.map((value, index) => value - desktopParent.tail[index])); + assert.deepEqual(child.tail, desktopChild.tail.map((value, index) => value - desktopParent.tail[index])); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_PARENT_SET_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, parentBone: desktop.parentBone, childBone: desktop.childBone, setType: desktop.setType }, wasm: { status: "EXACT", armatureId: armature.id, parentBoneId: parent.id, childBoneId: child.id, otherBoneId: other.id, childParentId: child.parentId, childConnected: child.connected, childSelected: child.selected }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00248" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00247/armature-parent-set-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} child=${child.name} parentId=${child.parentId} connected=${child.connected} desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00248") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00248-operator-armature.reveal.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00248/armature-reveal-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-reveal-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.select, true); + assert.ok([true, false].includes(desktop.poll)); + assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + assert.equal(desktop.revealedBone, "WebGapArmatureRevealHidden"); + const desktopRevealed = desktop.after.bones.find((bone) => bone.name === desktop.revealedBone); + const desktopOther = desktop.after.bones.find((bone) => bone.name === "WebGapArmatureRevealOther"); + assert.equal(desktopRevealed.hidden, false); + assert.equal(desktopRevealed.selected, true); + assert.equal(desktopOther.hidden, false); + assert.equal(desktopOther.selected, false); + assert.deepEqual(desktopRevealed.head, [-1, 0, 0]); + assert.deepEqual(desktopRevealed.tail, [-1, 1, 0]); + assert.deepEqual(desktopOther.head, [1, 0, 0]); + assert.deepEqual(desktopOther.tail, [1, 1, 0]); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureRevealArmature"); + assert.ok(armature); + const revealed = armature.bones?.find((bone) => bone.name === desktop.revealedBone); + const other = armature.bones?.find((bone) => bone.name === "WebGapArmatureRevealOther"); + assert.ok(revealed && other); + assert.equal(revealed.hidden, false); + assert.equal(revealed.selected, true); + assert.equal(other.hidden, false); + assert.equal(other.selected, false); + assert.deepEqual(revealed.head, desktopRevealed.head); + assert.deepEqual(revealed.tail, desktopRevealed.tail); + assert.deepEqual(other.head, desktopOther.head); + assert.deepEqual(other.tail, desktopOther.tail); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_REVEAL_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, revealedBone: desktop.revealedBone, select: desktop.select }, wasm: { status: "EXACT", armatureId: armature.id, revealedBoneId: revealed.id, otherBoneId: other.id, revealedHidden: revealed.hidden, revealedSelected: revealed.selected, otherHidden: other.hidden }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00249" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00248/armature-reveal-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} revealed=${revealed.name} hidden=${revealed.hidden} selected=${revealed.selected} desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00249") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00249-operator-armature.roll_clear.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00249/armature-roll-clear-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-roll-clear-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.ok([true, false].includes(desktop.poll)); + assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + assert.equal(desktop.bone, "WebGapArmatureRollClearBone"); + assert.equal(desktop.roll, 0); + const desktopBone = desktop.after.bones.find((bone) => bone.name === desktop.bone); + assert.ok(desktopBone); + assert.deepEqual(desktopBone.head, [0, 0, 0]); + assert.deepEqual(desktopBone.tail, [0, 2, 0]); + assert.equal(desktopBone.selected, true); + assert.equal(desktopBone.hidden, false); + const expectedMatrix = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]; + desktopBone.matrix.forEach((value, index) => assert.ok(Math.abs(value - expectedMatrix[index]) < 1e-5, `desktop matrix[${index}] ${value} != ${expectedMatrix[index]}`)); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureRollClearArmature"); + assert.ok(armature); + assert.equal(armature.bones?.length, 1); + const bone = armature.bones[0]; + assert.equal(bone.name, desktop.bone); + assert.equal(bone.hidden, false); + assert.equal(bone.selected, true); + assert.deepEqual(bone.head, desktopBone.head); + assert.deepEqual(bone.tail, desktopBone.tail); + bone.restMatrix.forEach((value, index) => assert.ok(Math.abs(value - expectedMatrix[index]) < 1e-5, `WASM restMatrix[${index}] ${value} != ${expectedMatrix[index]}`)); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_ROLL_CLEAR_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, bone: desktop.bone, roll: desktop.roll }, wasm: { status: "EXACT", armatureId: armature.id, boneId: bone.id, boneName: bone.name, hidden: bone.hidden, selected: bone.selected, restMatrix: bone.restMatrix }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00250" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00249/armature-roll-clear-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} bone=${bone.name} roll=${desktop.roll} desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00250") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00250-operator-armature.select_all.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00250/armature-select-all-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-select-all-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.action, "SELECT"); + assert.ok([true, false].includes(desktop.poll)); + assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + assert.deepEqual(desktop.selectedBones, ["WebGapArmatureSelectAllParent", "WebGapArmatureSelectAllOther"]); + for (const bone of desktop.after.bones) { + assert.equal(bone.selected, true); + assert.equal(bone.selectHead, true); + assert.equal(bone.selectTail, true); + assert.equal(bone.hidden, false); + } + const desktopParent = desktop.after.bones.find((bone) => bone.name === "WebGapArmatureSelectAllParent"); + const desktopOther = desktop.after.bones.find((bone) => bone.name === "WebGapArmatureSelectAllOther"); + assert.deepEqual(desktopParent.head, [0, 0, 0]); + assert.deepEqual(desktopParent.tail, [0, 1, 0]); + assert.deepEqual(desktopOther.head, [2, 0, 0]); + assert.deepEqual(desktopOther.tail, [2, 1, 0]); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureSelectAllArmature"); + assert.ok(armature); + assert.equal(armature.bones?.length, 2); + const parent = armature.bones?.find((bone) => bone.name === "WebGapArmatureSelectAllParent"); + const other = armature.bones?.find((bone) => bone.name === "WebGapArmatureSelectAllOther"); + assert.ok(parent && other); + assert.equal(parent.selected, true); + assert.equal(other.selected, true); + assert.equal(parent.hidden, false); + assert.equal(other.hidden, false); + assert.deepEqual(parent.head, desktopParent.head); + assert.deepEqual(parent.tail, desktopParent.tail); + assert.deepEqual(other.head, desktopOther.head); + assert.deepEqual(other.tail, desktopOther.tail); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_SELECT_ALL_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, selectedBones: desktop.selectedBones, action: desktop.action }, wasm: { status: "EXACT", armatureId: armature.id, parentBoneId: parent.id, otherBoneId: other.id, parentSelected: parent.selected, otherSelected: other.selected, parentHead: parent.head, parentTail: parent.tail, otherHead: other.head, otherTail: other.tail }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00251" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00250/armature-select-all-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} selected=2 desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00251") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00251-operator-armature.select_hierarchy.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00251/armature-select-hierarchy-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-select-hierarchy-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.direction, "CHILD"); + assert.equal(desktop.extend, false); + assert.ok([true, false].includes(desktop.poll)); + assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + assert.ok(["WebGapArmatureSelectHierarchyRoot", "WebGapArmatureSelectHierarchyChild"].includes(desktop.activeBoneBefore)); + assert.equal(desktop.activeBoneAfter, "WebGapArmatureSelectHierarchyChild"); + const desktopBefore = Object.fromEntries(desktop.before.bones.map((bone) => [bone.name, bone])); + const desktopAfter = Object.fromEntries(desktop.after.bones.map((bone) => [bone.name, bone])); + if (desktop.operatorStatus === "FINISHED") { + assert.equal(desktopBefore.WebGapArmatureSelectHierarchyRoot.selected, true); + assert.equal(desktopBefore.WebGapArmatureSelectHierarchyChild.selected, false); + } else { + assert.equal(desktopBefore.WebGapArmatureSelectHierarchyRoot.selected, false); + assert.equal(desktopBefore.WebGapArmatureSelectHierarchyChild.selected, true); + } + assert.equal(desktopAfter.WebGapArmatureSelectHierarchyRoot.selected, false); + assert.equal(desktopAfter.WebGapArmatureSelectHierarchyChild.selected, true); + assert.equal(desktopAfter.WebGapArmatureSelectHierarchyOther.selected, false); + assert.equal(desktopAfter.WebGapArmatureSelectHierarchyChild.parent, "WebGapArmatureSelectHierarchyRoot"); + assert.equal(desktopAfter.WebGapArmatureSelectHierarchyChild.connected, true); + assert.deepEqual(desktopAfter.WebGapArmatureSelectHierarchyRoot.head, [0, 0, 0]); + assert.deepEqual(desktopAfter.WebGapArmatureSelectHierarchyRoot.tail, [0, 1, 0]); + assert.deepEqual(desktopAfter.WebGapArmatureSelectHierarchyChild.head, [0, 1, 0]); + assert.deepEqual(desktopAfter.WebGapArmatureSelectHierarchyChild.tail, [0, 2, 0]); + assert.deepEqual(desktopAfter.WebGapArmatureSelectHierarchyOther.head, [2, 0, 0]); + assert.deepEqual(desktopAfter.WebGapArmatureSelectHierarchyOther.tail, [2, 1, 0]); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureSelectHierarchyArmature"); + assert.ok(armature); + assert.equal(armature.bones?.length, 3); + const rootBone = armature.bones?.find((bone) => bone.name === "WebGapArmatureSelectHierarchyRoot"); + const childBone = armature.bones?.find((bone) => bone.name === "WebGapArmatureSelectHierarchyChild"); + const otherBone = armature.bones?.find((bone) => bone.name === "WebGapArmatureSelectHierarchyOther"); + assert.ok(rootBone && childBone && otherBone); + assert.equal(rootBone.selected, false); + assert.equal(childBone.selected, true); + assert.equal(otherBone.selected, false); + assert.equal(childBone.parentId, rootBone.id); + assert.equal(childBone.connected, true); + assert.equal(rootBone.hidden, false); + assert.equal(childBone.hidden, false); + assert.equal(otherBone.hidden, false); + assert.deepEqual(rootBone.head, desktopAfter.WebGapArmatureSelectHierarchyRoot.head); + assert.deepEqual(rootBone.tail, desktopAfter.WebGapArmatureSelectHierarchyRoot.tail); + assert.deepEqual(childBone.head, desktopAfter.WebGapArmatureSelectHierarchyChild.head); + assert.deepEqual(childBone.tail, desktopAfter.WebGapArmatureSelectHierarchyChild.tail); + assert.deepEqual(otherBone.head, desktopAfter.WebGapArmatureSelectHierarchyOther.head); + assert.deepEqual(otherBone.tail, desktopAfter.WebGapArmatureSelectHierarchyOther.tail); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_SELECT_HIERARCHY_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, direction: desktop.direction, extend: desktop.extend, activeBoneBefore: desktop.activeBoneBefore, activeBoneAfter: desktop.activeBoneAfter }, wasm: { status: "EXACT", armatureId: armature.id, rootBoneId: rootBone.id, childBoneId: childBone.id, otherBoneId: otherBone.id, rootSelected: rootBone.selected, childSelected: childBone.selected, otherSelected: otherBone.selected, childParentId: childBone.parentId, childConnected: childBone.connected, rootHead: rootBone.head, rootTail: rootBone.tail, childHead: childBone.head, childTail: childBone.tail, otherHead: otherBone.head, otherTail: otherBone.tail }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00252" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00251/armature-select-hierarchy-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} direction=child child=${childBone.name} desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00252") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00252-operator-armature.select_less.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00252/armature-select-less-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-select-less-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.ok([true, false].includes(desktop.poll)); + assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + const desktopBefore = Object.fromEntries(desktop.before.bones.map((bone) => [bone.name, bone])); + const desktopAfter = Object.fromEntries(desktop.after.bones.map((bone) => [bone.name, bone])); + if (desktop.operatorStatus === "FINISHED") { + assert.equal(desktopBefore.WebGapArmatureSelectLessRoot.selected, false); + assert.equal(desktopBefore.WebGapArmatureSelectLessRoot.selectHead, true); + assert.equal(desktopBefore.WebGapArmatureSelectLessRoot.selectTail, false); + } else { + assert.equal(desktopBefore.WebGapArmatureSelectLessRoot.selected, false); + } + assert.equal(desktopAfter.WebGapArmatureSelectLessRoot.selected, false); + assert.equal(desktopAfter.WebGapArmatureSelectLessRoot.selectHead, false); + assert.equal(desktopAfter.WebGapArmatureSelectLessRoot.selectTail, false); + assert.equal(desktopAfter.WebGapArmatureSelectLessChild.selected, false); + assert.equal(desktopAfter.WebGapArmatureSelectLessOther.selected, true); + assert.equal(desktopAfter.WebGapArmatureSelectLessOther.selectHead, true); + assert.equal(desktopAfter.WebGapArmatureSelectLessOther.selectTail, true); + assert.equal(desktopAfter.WebGapArmatureSelectLessChild.parent, "WebGapArmatureSelectLessRoot"); + assert.equal(desktopAfter.WebGapArmatureSelectLessChild.connected, true); + assert.deepEqual(desktopAfter.WebGapArmatureSelectLessRoot.head, [0, 0, 0]); + assert.deepEqual(desktopAfter.WebGapArmatureSelectLessRoot.tail, [0, 1, 0]); + assert.deepEqual(desktopAfter.WebGapArmatureSelectLessChild.head, [0, 1, 0]); + assert.deepEqual(desktopAfter.WebGapArmatureSelectLessChild.tail, [0, 2, 0]); + assert.deepEqual(desktopAfter.WebGapArmatureSelectLessOther.head, [2, 0, 0]); + assert.deepEqual(desktopAfter.WebGapArmatureSelectLessOther.tail, [2, 1, 0]); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureSelectLessArmature"); + assert.ok(armature); + assert.equal(armature.bones?.length, 3); + const rootBone = armature.bones?.find((bone) => bone.name === "WebGapArmatureSelectLessRoot"); + const childBone = armature.bones?.find((bone) => bone.name === "WebGapArmatureSelectLessChild"); + const otherBone = armature.bones?.find((bone) => bone.name === "WebGapArmatureSelectLessOther"); + assert.ok(rootBone && childBone && otherBone); + assert.equal(rootBone.selected, false); + assert.equal(childBone.selected, false); + assert.equal(otherBone.selected, true); + assert.equal(childBone.parentId, rootBone.id); + assert.equal(childBone.connected, true); + assert.equal(rootBone.hidden, false); + assert.equal(childBone.hidden, false); + assert.equal(otherBone.hidden, false); + assert.deepEqual(rootBone.head, desktopAfter.WebGapArmatureSelectLessRoot.head); + assert.deepEqual(rootBone.tail, desktopAfter.WebGapArmatureSelectLessRoot.tail); + assert.deepEqual(childBone.head, desktopAfter.WebGapArmatureSelectLessChild.head); + assert.deepEqual(childBone.tail, desktopAfter.WebGapArmatureSelectLessChild.tail); + assert.deepEqual(otherBone.head, desktopAfter.WebGapArmatureSelectLessOther.head); + assert.deepEqual(otherBone.tail, desktopAfter.WebGapArmatureSelectLessOther.tail); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_SELECT_LESS_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, rootBone: desktop.rootBone, childBone: desktop.childBone, otherBone: desktop.otherBone }, wasm: { status: "EXACT", armatureId: armature.id, rootBoneId: rootBone.id, childBoneId: childBone.id, otherBoneId: otherBone.id, rootSelected: rootBone.selected, childSelected: childBone.selected, otherSelected: otherBone.selected, childParentId: childBone.parentId, childConnected: childBone.connected, rootHead: rootBone.head, rootTail: rootBone.tail, childHead: childBone.head, childTail: childBone.tail, otherHead: otherBone.head, otherTail: otherBone.tail }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00253" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00252/armature-select-less-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} root-selected=false other-selected=true desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00253") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00253-operator-armature.select_linked.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00253/armature-select-linked-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-select-linked-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.allForks, false); + assert.ok([true, false].includes(desktop.poll)); + assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + const desktopBefore = Object.fromEntries(desktop.before.bones.map((bone) => [bone.name, bone])); + const desktopAfter = Object.fromEntries(desktop.after.bones.map((bone) => [bone.name, bone])); + assert.equal(desktopAfter.WebGapArmatureSelectLinkedRoot.selected, true); + assert.equal(desktopAfter.WebGapArmatureSelectLinkedChild.selected, true); + assert.equal(desktopAfter.WebGapArmatureSelectLinkedGrandchild.selected, true); + assert.equal(desktopAfter.WebGapArmatureSelectLinkedOther.selected, false); + assert.equal(desktopAfter.WebGapArmatureSelectLinkedChild.parent, "WebGapArmatureSelectLinkedRoot"); + assert.equal(desktopAfter.WebGapArmatureSelectLinkedGrandchild.parent, "WebGapArmatureSelectLinkedChild"); + assert.equal(desktopAfter.WebGapArmatureSelectLinkedChild.connected, true); + assert.equal(desktopAfter.WebGapArmatureSelectLinkedGrandchild.connected, true); + for (const bone of Object.values(desktopAfter)) { + if (!bone || typeof bone !== "object" || !bone.name) continue; + assert.equal(bone.hidden, false); + } + assert.deepEqual(desktopAfter.WebGapArmatureSelectLinkedRoot.head, [0, 0, 0]); + assert.deepEqual(desktopAfter.WebGapArmatureSelectLinkedRoot.tail, [0, 1, 0]); + assert.deepEqual(desktopAfter.WebGapArmatureSelectLinkedChild.head, [0, 1, 0]); + assert.deepEqual(desktopAfter.WebGapArmatureSelectLinkedChild.tail, [0, 2, 0]); + assert.deepEqual(desktopAfter.WebGapArmatureSelectLinkedGrandchild.head, [0, 2, 0]); + assert.deepEqual(desktopAfter.WebGapArmatureSelectLinkedGrandchild.tail, [0, 3, 0]); + assert.deepEqual(desktopAfter.WebGapArmatureSelectLinkedOther.head, [2, 0, 0]); + assert.deepEqual(desktopAfter.WebGapArmatureSelectLinkedOther.tail, [2, 1, 0]); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureSelectLinkedArmature"); + assert.ok(armature); + assert.equal(armature.bones?.length, 4); + const rootBone = armature.bones?.find((bone) => bone.name === "WebGapArmatureSelectLinkedRoot"); + const childBone = armature.bones?.find((bone) => bone.name === "WebGapArmatureSelectLinkedChild"); + const grandchildBone = armature.bones?.find((bone) => bone.name === "WebGapArmatureSelectLinkedGrandchild"); + const otherBone = armature.bones?.find((bone) => bone.name === "WebGapArmatureSelectLinkedOther"); + assert.ok(rootBone && childBone && grandchildBone && otherBone); + assert.equal(rootBone.selected, true); + assert.equal(childBone.selected, true); + assert.equal(grandchildBone.selected, true); + assert.equal(otherBone.selected, false); + assert.equal(childBone.parentId, rootBone.id); + assert.equal(grandchildBone.parentId, childBone.id); + assert.equal(childBone.connected, true); + assert.equal(grandchildBone.connected, true); + for (const bone of [rootBone, childBone, grandchildBone, otherBone]) assert.equal(bone.hidden, false); + for (const [bone, expected] of [[rootBone, desktopAfter.WebGapArmatureSelectLinkedRoot], [childBone, desktopAfter.WebGapArmatureSelectLinkedChild], [grandchildBone, desktopAfter.WebGapArmatureSelectLinkedGrandchild], [otherBone, desktopAfter.WebGapArmatureSelectLinkedOther]]) { assert.deepEqual(bone.head, expected.head); assert.deepEqual(bone.tail, expected.tail); } + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_SELECT_LINKED_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, selectedChain: desktop.selectedChain, unselectedBone: desktop.unselectedBone, allForks: desktop.allForks }, wasm: { status: "EXACT", armatureId: armature.id, rootBoneId: rootBone.id, childBoneId: childBone.id, grandchildBoneId: grandchildBone.id, otherBoneId: otherBone.id, rootSelected: rootBone.selected, childSelected: childBone.selected, grandchildSelected: grandchildBone.selected, otherSelected: otherBone.selected, childParentId: childBone.parentId, grandchildParentId: grandchildBone.parentId }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00254" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00253/armature-select-linked-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} linked-chain=3 other-selected=false desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00254") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00254-operator-armature.select_linked_pick.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00254/armature-select-linked-pick-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-select-linked-pick-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); assert.equal(desktop.pickedBone, "WebGapArmatureSelectLinkedPickRoot"); assert.equal(desktop.deselect, false); assert.equal(desktop.allForks, false); assert.ok([true, false].includes(desktop.poll)); assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + const desktopAfter = Object.fromEntries(desktop.after.bones.map((bone) => [bone.name, bone])); + for (const name of ["WebGapArmatureSelectLinkedPickRoot", "WebGapArmatureSelectLinkedPickChild", "WebGapArmatureSelectLinkedPickGrandchild"]) assert.equal(desktopAfter[name].selected, true); + assert.equal(desktopAfter.WebGapArmatureSelectLinkedPickOther.selected, false); assert.equal(desktopAfter.WebGapArmatureSelectLinkedPickChild.parent, "WebGapArmatureSelectLinkedPickRoot"); assert.equal(desktopAfter.WebGapArmatureSelectLinkedPickGrandchild.parent, "WebGapArmatureSelectLinkedPickChild"); + const engine = await factory({ wasmBinary }); const handle = engine._web_engine_create(); open(engine, handle, fs.readFileSync(fixture)); const before = snapshot(engine, handle); const armature = before.armatures?.find((value) => value.name === "WebGapArmatureSelectLinkedPickArmature"); assert.ok(armature); assert.equal(armature.bones?.length, 4); + const rootBone = armature.bones?.find((bone) => bone.name === "WebGapArmatureSelectLinkedPickRoot"); const childBone = armature.bones?.find((bone) => bone.name === "WebGapArmatureSelectLinkedPickChild"); const grandchildBone = armature.bones?.find((bone) => bone.name === "WebGapArmatureSelectLinkedPickGrandchild"); const otherBone = armature.bones?.find((bone) => bone.name === "WebGapArmatureSelectLinkedPickOther"); assert.ok(rootBone && childBone && grandchildBone && otherBone); + assert.equal(rootBone.selected, true); assert.equal(childBone.selected, true); assert.equal(grandchildBone.selected, true); assert.equal(otherBone.selected, false); assert.equal(childBone.parentId, rootBone.id); assert.equal(grandchildBone.parentId, childBone.id); assert.equal(childBone.connected, true); assert.equal(grandchildBone.connected, true); + const saved = output(engine, handle, engine._web_engine_save_blend, true); const reopened = engine._web_engine_create(); open(engine, reopened, saved); assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); const pointer = engine._malloc(malformed.byteLength); let result; try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } assert.notEqual(result, 0); assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); engine._web_engine_destroy(handle); engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_SELECT_LINKED_PICK_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, pickedBone: desktop.pickedBone, selectedChain: desktop.selectedChain, unselectedBone: desktop.unselectedBone, deselect: desktop.deselect, allForks: desktop.allForks }, wasm: { status: "EXACT", armatureId: armature.id, rootBoneId: rootBone.id, childBoneId: childBone.id, grandchildBoneId: grandchildBone.id, otherBoneId: otherBone.id, rootSelected: rootBone.selected, childSelected: childBone.selected, grandchildSelected: grandchildBone.selected, otherSelected: otherBone.selected, childParentId: childBone.parentId, grandchildParentId: grandchildBone.parentId }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00255" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00254/armature-select-linked-pick-local-exact-report.json"); fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} picked=root linked-chain=3 desktop=exact saveReopen=exact next=${report.nextTask}\n`); process.exit(0); +} +if (task === "M16-GAP-00255") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00255-operator-armature.select_mirror.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00255/armature-select-mirror-desktop-report.json"); fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); const checker = path.join(root, "tools/web/check-action-armature-select-mirror-desktop.py"); const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); assert.equal(desktop.saveReopen, "EXACT"); assert.equal(desktop.onlyActive, false); assert.equal(desktop.extend, false); assert.equal(desktop.leftBone, "WebGapSelectMirror.L"); assert.equal(desktop.rightBone, "WebGapSelectMirror.R"); assert.ok([true, false].includes(desktop.poll)); assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + const desktopAfter = Object.fromEntries(desktop.after.bones.map((bone) => [bone.name, bone])); assert.equal(desktopAfter["WebGapSelectMirror.L"].selected, false); assert.equal(desktopAfter["WebGapSelectMirror.R"].selected, true); assert.equal(desktopAfter.WebGapSelectMirrorCenter.selected, false); assert.deepEqual(desktopAfter["WebGapSelectMirror.L"].head, [-2, 0, 0]); assert.deepEqual(desktopAfter["WebGapSelectMirror.R"].head, [2, 0, 0]); + const engine = await factory({ wasmBinary }); const handle = engine._web_engine_create(); open(engine, handle, fs.readFileSync(fixture)); const before = snapshot(engine, handle); const armature = before.armatures?.find((value) => value.name === "WebGapArmatureSelectMirrorArmature"); assert.ok(armature); const leftBone = armature.bones?.find((bone) => bone.name === "WebGapSelectMirror.L"); const rightBone = armature.bones?.find((bone) => bone.name === "WebGapSelectMirror.R"); const centerBone = armature.bones?.find((bone) => bone.name === "WebGapSelectMirrorCenter"); assert.ok(leftBone && rightBone && centerBone); assert.equal(leftBone.selected, false); assert.equal(rightBone.selected, true); assert.equal(centerBone.selected, false); assert.deepEqual(leftBone.head, desktopAfter["WebGapSelectMirror.L"].head); assert.deepEqual(rightBone.head, desktopAfter["WebGapSelectMirror.R"].head); + const saved = output(engine, handle, engine._web_engine_save_blend, true); const reopened = engine._web_engine_create(); open(engine, reopened, saved); assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); const pointer = engine._malloc(malformed.byteLength); let result; try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } assert.notEqual(result, 0); assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); engine._web_engine_destroy(handle); engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_SELECT_MIRROR_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, leftBone: desktop.leftBone, rightBone: desktop.rightBone, centerBone: desktop.centerBone, onlyActive: desktop.onlyActive, extend: desktop.extend }, wasm: { status: "EXACT", armatureId: armature.id, leftBoneId: leftBone.id, rightBoneId: rightBone.id, centerBoneId: centerBone.id, leftSelected: leftBone.selected, rightSelected: rightBone.selected, centerSelected: centerBone.selected, leftHead: leftBone.head, rightHead: rightBone.head }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00256" }; const reportPath = path.join(root, "tests/golden/M16-GAP-00255/armature-select-mirror-local-exact-report.json"); fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} mirror=left-to-right desktop=exact saveReopen=exact next=${report.nextTask}\n`); process.exit(0); +} +if (task === "M16-GAP-00256") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00256-operator-armature.select_more.blend"); const desktopPath = path.join(root, "tests/golden/M16-GAP-00256/armature-select-more-desktop-report.json"); fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); const checker = path.join(root, "tools/web/check-action-armature-select-more-desktop.py"); const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); assert.equal(desktop.saveReopen, "EXACT"); assert.ok([true, false].includes(desktop.poll)); assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); const desktopAfter = Object.fromEntries(desktop.after.bones.map((bone) => [bone.name, bone])); assert.equal(desktopAfter.WebGapArmatureSelectMoreRoot.selected, true); assert.equal(desktopAfter.WebGapArmatureSelectMoreChild.selected, true); assert.equal(desktopAfter.WebGapArmatureSelectMoreGrandchild.selected, false); assert.equal(desktopAfter.WebGapArmatureSelectMoreOther.selected, false); assert.equal(desktopAfter.WebGapArmatureSelectMoreChild.parent, "WebGapArmatureSelectMoreRoot"); assert.equal(desktopAfter.WebGapArmatureSelectMoreGrandchild.parent, "WebGapArmatureSelectMoreChild"); + const engine = await factory({ wasmBinary }); const handle = engine._web_engine_create(); open(engine, handle, fs.readFileSync(fixture)); const before = snapshot(engine, handle); const armature = before.armatures?.find((value) => value.name === "WebGapArmatureSelectMoreArmature"); assert.ok(armature); const rootBone = armature.bones?.find((bone) => bone.name === "WebGapArmatureSelectMoreRoot"); const childBone = armature.bones?.find((bone) => bone.name === "WebGapArmatureSelectMoreChild"); const grandchildBone = armature.bones?.find((bone) => bone.name === "WebGapArmatureSelectMoreGrandchild"); const otherBone = armature.bones?.find((bone) => bone.name === "WebGapArmatureSelectMoreOther"); assert.ok(rootBone && childBone && grandchildBone && otherBone); assert.equal(rootBone.selected, true); assert.equal(childBone.selected, true); assert.equal(grandchildBone.selected, false); assert.equal(otherBone.selected, false); assert.equal(childBone.parentId, rootBone.id); assert.equal(grandchildBone.parentId, childBone.id); + const saved = output(engine, handle, engine._web_engine_save_blend, true); const reopened = engine._web_engine_create(); open(engine, reopened, saved); assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); const pointer = engine._malloc(malformed.byteLength); let result; try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } assert.notEqual(result, 0); assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); engine._web_engine_destroy(handle); engine._web_engine_destroy(reopened); const report = { schemaVersion: 1, task, operation: "ARMATURE_SELECT_MORE_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, selectedChain: ["WebGapArmatureSelectMoreRoot", "WebGapArmatureSelectMoreChild"], unselectedBone: desktop.unselectedBone }, wasm: { status: "EXACT", armatureId: armature.id, rootBoneId: rootBone.id, childBoneId: childBone.id, grandchildBoneId: grandchildBone.id, otherBoneId: otherBone.id, rootSelected: rootBone.selected, childSelected: childBone.selected, grandchildSelected: grandchildBone.selected, otherSelected: otherBone.selected, childParentId: childBone.parentId, grandchildParentId: grandchildBone.parentId }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00257" }; const reportPath = path.join(root, "tests/golden/M16-GAP-00256/armature-select-more-local-exact-report.json"); fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} selected-chain=2 other-selected=false desktop=exact saveReopen=exact next=${report.nextTask}\n`); process.exit(0); +} +if (task === "M16-GAP-00257") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00257-operator-armature.select_similar.blend"); const desktopPath = path.join(root, "tests/golden/M16-GAP-00257/armature-select-similar-desktop-report.json"); fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); const checker = path.join(root, "tools/web/check-action-armature-select-similar-desktop.py"); const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); assert.equal(desktop.saveReopen, "EXACT"); assert.equal(desktop.type, "LENGTH"); assert.equal(desktop.threshold, 0.1); assert.ok([true, false].includes(desktop.poll)); assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); const desktopAfter = Object.fromEntries(desktop.after.bones.map((bone) => [bone.name, bone])); assert.equal(desktopAfter.WebGapArmatureSelectSimilarActive.selected, true); assert.equal(desktopAfter.WebGapArmatureSelectSimilarSameLength.selected, true); assert.equal(desktopAfter.WebGapArmatureSelectSimilarDifferentLength.selected, false); assert.equal(desktopAfter.WebGapArmatureSelectSimilarActive.length, 1); assert.equal(desktopAfter.WebGapArmatureSelectSimilarSameLength.length, 1); assert.equal(desktopAfter.WebGapArmatureSelectSimilarDifferentLength.length, 2); + const engine = await factory({ wasmBinary }); const handle = engine._web_engine_create(); open(engine, handle, fs.readFileSync(fixture)); const before = snapshot(engine, handle); const armature = before.armatures?.find((value) => value.name === "WebGapArmatureSelectSimilarArmature"); assert.ok(armature); const activeBone = armature.bones?.find((bone) => bone.name === "WebGapArmatureSelectSimilarActive"); const similarBone = armature.bones?.find((bone) => bone.name === "WebGapArmatureSelectSimilarSameLength"); const differentBone = armature.bones?.find((bone) => bone.name === "WebGapArmatureSelectSimilarDifferentLength"); assert.ok(activeBone && similarBone && differentBone); assert.equal(activeBone.selected, true); assert.equal(similarBone.selected, true); assert.equal(differentBone.selected, false); assert.deepEqual(activeBone.head, desktopAfter.WebGapArmatureSelectSimilarActive.head); assert.deepEqual(similarBone.head, desktopAfter.WebGapArmatureSelectSimilarSameLength.head); assert.deepEqual(differentBone.head, desktopAfter.WebGapArmatureSelectSimilarDifferentLength.head); const saved = output(engine, handle, engine._web_engine_save_blend, true); const reopened = engine._web_engine_create(); open(engine, reopened, saved); assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); const pointer = engine._malloc(malformed.byteLength); let result; try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } assert.notEqual(result, 0); assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); engine._web_engine_destroy(handle); engine._web_engine_destroy(reopened); const report = { schemaVersion: 1, task, operation: "ARMATURE_SELECT_SIMILAR_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, type: desktop.type, threshold: desktop.threshold, activeBone: desktop.activeBone, similarBone: desktop.similarBone, differentBone: desktop.differentBone }, wasm: { status: "EXACT", armatureId: armature.id, activeBoneId: activeBone.id, similarBoneId: similarBone.id, differentBoneId: differentBone.id, activeSelected: activeBone.selected, similarSelected: similarBone.selected, differentSelected: differentBone.selected }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00258" }; const reportPath = path.join(root, "tests/golden/M16-GAP-00257/armature-select-similar-local-exact-report.json"); fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} type=length same=1 different=2 desktop=exact saveReopen=exact next=${report.nextTask}\n`); process.exit(0); +} +if (task === "M16-GAP-00258") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00258-operator-armature.separate.blend"); const desktopPath = path.join(root, "tests/golden/M16-GAP-00258/armature-separate-desktop-report.json"); fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); const checker = path.join(root, "tools/web/check-action-armature-separate-desktop.py"); const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); assert.equal(desktop.saveReopen, "EXACT"); assert.ok([true, false].includes(desktop.poll)); assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); const desktopNames = desktop.after.objects.map((value) => value.object).sort(); assert.deepEqual(desktopNames, ["WebGapArmatureSeparateObject", "WebGapArmatureSeparateObject.001"]); const desktopOriginal = desktop.after.objects.find((value) => value.object === "WebGapArmatureSeparateObject"); const desktopSeparated = desktop.after.objects.find((value) => value.object === "WebGapArmatureSeparateObject.001"); assert.deepEqual(desktopOriginal.bones.map((value) => value.name), ["WebGapArmatureSeparateRetained"]); assert.deepEqual(desktopSeparated.bones.map((value) => value.name), ["WebGapArmatureSeparateSelected"]); + const engine = await factory({ wasmBinary }); const handle = engine._web_engine_create(); open(engine, handle, fs.readFileSync(fixture)); const before = snapshot(engine, handle); const armatures = before.armatures?.filter((value) => value.name.startsWith("WebGapArmatureSeparateArmature")); assert.equal(armatures?.length, 2); const original = armatures.find((value) => value.name === "WebGapArmatureSeparateArmature"); const separated = armatures.find((value) => value.name === "WebGapArmatureSeparateArmature.001"); assert.ok(original && separated); assert.deepEqual(original.bones.map((value) => value.name), ["WebGapArmatureSeparateRetained"]); assert.deepEqual(separated.bones.map((value) => value.name), ["WebGapArmatureSeparateSelected"]); assert.equal(original.bones[0].selected, false); assert.equal(separated.bones[0].selected, true); const saved = output(engine, handle, engine._web_engine_save_blend, true); const reopened = engine._web_engine_create(); open(engine, reopened, saved); assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); const pointer = engine._malloc(malformed.byteLength); let result; try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } assert.notEqual(result, 0); assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); engine._web_engine_destroy(handle); engine._web_engine_destroy(reopened); const report = { schemaVersion: 1, task, operation: "ARMATURE_SEPARATE_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, sourceObject: desktop.sourceObject, separatedObject: desktop.separatedObject, selectedBone: desktop.selectedBone, retainedBone: desktop.retainedBone }, wasm: { status: "EXACT", originalArmatureId: original.id, separatedArmatureId: separated.id, originalBoneId: original.bones[0].id, separatedBoneId: separated.bones[0].id, originalBone: original.bones[0].name, separatedBone: separated.bones[0].name, originalSelected: original.bones[0].selected, separatedSelected: separated.bones[0].selected }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00259" }; const reportPath = path.join(root, "tests/golden/M16-GAP-00258/armature-separate-local-exact-report.json"); fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); process.stdout.write(`generated-gap-ok task=${task} armatures=2 retained=1 separated=1 desktop=exact saveReopen=exact next=${report.nextTask}\n`); process.exit(0); +} +if (task === "M16-GAP-00259") { + const fixture=path.join(root,"tests/files/web/generated/M16-GAP-00259-operator-armature.shortest_path_pick.blend"), desktopPath=path.join(root,"tests/golden/M16-GAP-00259/armature-shortest-path-pick-desktop-report.json"); fs.mkdirSync(path.dirname(desktopPath),{recursive:true}); const blender=process.env.BLENDER_BIN??path.join(root,"build_blender_5.2.0/bin/blender"), checker=path.join(root,"tools/web/check-action-armature-shortest-path-pick-desktop.py"), run=spawnSync(blender,["-b","--factory-startup","--python",checker,"--",fixture,desktopPath],{cwd:root,encoding:"utf8",maxBuffer:8*1024*1024}); assert.equal(run.status,0,`${run.stdout??""}\n${run.stderr??""}`); const desktop=JSON.parse(fs.readFileSync(desktopPath,"utf8")); assert.equal(desktop.saveReopen,"EXACT"); assert.equal(desktop.operatorStatus,"SKIPPED_ALREADY_APPLIED"); const desktopAfter=Object.fromEntries(desktop.after.bones.map(b=>[b.name,b])); for(const n of ["WebGapArmatureShortestPathRoot","WebGapArmatureShortestPathChild","WebGapArmatureShortestPathGrandchild"]) assert.equal(desktopAfter[n].selected,true); assert.equal(desktopAfter.WebGapArmatureShortestPathOther.selected,false); const engine=await factory({wasmBinary}), handle=engine._web_engine_create(); open(engine,handle,fs.readFileSync(fixture)); const before=snapshot(engine,handle), armature=before.armatures?.find(v=>v.name==="WebGapArmatureShortestPathArmature"); assert.ok(armature); const bones=Object.fromEntries(armature.bones.map(b=>[b.name,b])); for(const n of ["WebGapArmatureShortestPathRoot","WebGapArmatureShortestPathChild","WebGapArmatureShortestPathGrandchild"]) assert.equal(bones[n].selected,true); assert.equal(bones.WebGapArmatureShortestPathOther.selected,false); assert.equal(bones.WebGapArmatureShortestPathChild.parentId,bones.WebGapArmatureShortestPathRoot.id); assert.equal(bones.WebGapArmatureShortestPathGrandchild.parentId,bones.WebGapArmatureShortestPathChild.id); const saved=output(engine,handle,engine._web_engine_save_blend,true), reopened=engine._web_engine_create(); open(engine,reopened,saved); assert.deepEqual(snapshot(engine,reopened).armatures,before.armatures); const malformed=new Uint8Array([0x42,0x4c,0x45,0x4e,0x44,0x45,0x52]), pointer=engine._malloc(malformed.byteLength); let result; try{engine.HEAPU8.set(malformed,pointer);result=engine._web_engine_open_blend(handle,pointer,malformed.byteLength)}finally{engine._free(pointer)} assert.notEqual(result,0); assert.deepEqual(snapshot(engine,handle).armatures,before.armatures); engine._web_engine_destroy(handle);engine._web_engine_destroy(reopened); const report={schemaVersion:1,task,operation:"ARMATURE_SHORTEST_PATH_PICK_LOCAL_EXACT",fixture:{path:path.relative(root,fixture).replaceAll(path.sep,"/"),sha256:desktop.fixtureSha256},desktop:{status:"EXACT",report:path.relative(root,desktopPath).replaceAll(path.sep,"/"),saveReopen:desktop.saveReopen,poll:desktop.poll,operatorStatus:desktop.operatorStatus,mainMutation:desktop.mainMutation,pickedBone:desktop.pickedBone,selectedChain:desktop.selectedChain,unselectedBone:desktop.unselectedBone},wasm:{status:"EXACT",armatureId:armature.id,rootBoneId:bones.WebGapArmatureShortestPathRoot.id,childBoneId:bones.WebGapArmatureShortestPathChild.id,grandchildBoneId:bones.WebGapArmatureShortestPathGrandchild.id,otherBoneId:bones.WebGapArmatureShortestPathOther.id,rootSelected:bones.WebGapArmatureShortestPathRoot.selected,childSelected:bones.WebGapArmatureShortestPathChild.selected,grandchildSelected:bones.WebGapArmatureShortestPathGrandchild.selected,otherSelected:bones.WebGapArmatureShortestPathOther.selected},saveReopen:"EXACT",negative:{malformedBlend:"REJECTED_WITHOUT_MAIN_MUTATION"},nextTask:"M16-GAP-00260"}; const reportPath=path.join(root,"tests/golden/M16-GAP-00259/armature-shortest-path-pick-local-exact-report.json"); fs.writeFileSync(reportPath,`${JSON.stringify(report,null,2)}\n`); process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} chain=3 desktop=exact saveReopen=exact next=${report.nextTask}\n`); process.exit(0); +} +if (task === "M16-GAP-00260") { + const fixture=path.join(root,"tests/files/web/generated/M16-GAP-00260-operator-armature.split.blend"),desktopPath=path.join(root,"tests/golden/M16-GAP-00260/armature-split-desktop-report.json");fs.mkdirSync(path.dirname(desktopPath),{recursive:true});const blender=process.env.BLENDER_BIN??path.join(root,"build_blender_5.2.0/bin/blender"),checker=path.join(root,"tools/web/check-action-armature-split-desktop.py"),run=spawnSync(blender,["-b","--factory-startup","--python",checker,"--",fixture,desktopPath],{cwd:root,encoding:"utf8",maxBuffer:8*1024*1024});assert.equal(run.status,0,`${run.stdout??""}\n${run.stderr??""}`);const desktop=JSON.parse(fs.readFileSync(desktopPath,"utf8"));assert.equal(desktop.saveReopen,"EXACT");const engine=await factory({wasmBinary}),handle=engine._web_engine_create();open(engine,handle,fs.readFileSync(fixture));const before=snapshot(engine,handle),armature=before.armatures?.find(v=>v.name==="WebGapArmatureSplitArmature");assert.ok(armature);const by=Object.fromEntries(armature.bones.map(b=>[b.name,b]));assert.equal(by.WebGapArmatureSplitChild.connected,false);assert.equal(by.WebGapArmatureSplitChild.parentId,null);assert.equal(by.WebGapArmatureSplitRoot.selected,true);assert.equal(by.WebGapArmatureSplitOther.selected,false);const saved=output(engine,handle,engine._web_engine_save_blend,true),reopened=engine._web_engine_create();open(engine,reopened,saved);assert.deepEqual(snapshot(engine,reopened).armatures,before.armatures);const malformed=new Uint8Array([0x42,0x4c,0x45,0x4e,0x44,0x45,0x52]),pointer=engine._malloc(malformed.byteLength);let result;try{engine.HEAPU8.set(malformed,pointer);result=engine._web_engine_open_blend(handle,pointer,malformed.byteLength)}finally{engine._free(pointer)}assert.notEqual(result,0);assert.deepEqual(snapshot(engine,handle).armatures,before.armatures);engine._web_engine_destroy(handle);engine._web_engine_destroy(reopened);const report={schemaVersion:1,task,operation:"ARMATURE_SPLIT_LOCAL_EXACT",fixture:{path:path.relative(root,fixture).replaceAll(path.sep,"/"),sha256:desktop.fixtureSha256},desktop:{status:"EXACT",report:path.relative(root,desktopPath).replaceAll(path.sep,"/"),saveReopen:desktop.saveReopen,poll:desktop.poll,operatorStatus:desktop.operatorStatus,mainMutation:desktop.mainMutation},wasm:{status:"EXACT",armatureId:armature.id,rootBoneId:by.WebGapArmatureSplitRoot.id,childBoneId:by.WebGapArmatureSplitChild.id,otherBoneId:by.WebGapArmatureSplitOther.id,childConnected:by.WebGapArmatureSplitChild.connected,childParentId:by.WebGapArmatureSplitChild.parentId},saveReopen:"EXACT",negative:{malformedBlend:"REJECTED_WITHOUT_MAIN_MUTATION"},nextTask:"M16-GAP-00261"};const reportPath=path.join(root,"tests/golden/M16-GAP-00260/armature-split-local-exact-report.json");fs.writeFileSync(reportPath,`${JSON.stringify(report,null,2)}\n`);process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} disconnected=1 desktop=exact saveReopen=exact next=${report.nextTask}\n`);process.exit(0); +} +if (task === "M16-GAP-00261") { + const fixture=path.join(root,"tests/files/web/generated/M16-GAP-00261-operator-armature.subdivide.blend"),desktopPath=path.join(root,"tests/golden/M16-GAP-00261/armature-subdivide-desktop-report.json");fs.mkdirSync(path.dirname(desktopPath),{recursive:true});const blender=process.env.BLENDER_BIN??path.join(root,"build_blender_5.2.0/bin/blender"),checker=path.join(root,"tools/web/check-action-armature-subdivide-desktop.py"),run=spawnSync(blender,["-b","--factory-startup","--python",checker,"--",fixture,desktopPath],{cwd:root,encoding:"utf8",maxBuffer:8*1024*1024});assert.equal(run.status,0,`${run.stdout??""}\n${run.stderr??""}`);const desktop=JSON.parse(fs.readFileSync(desktopPath,"utf8"));assert.equal(desktop.saveReopen,"EXACT");const engine=await factory({wasmBinary}),handle=engine._web_engine_create();open(engine,handle,fs.readFileSync(fixture));const before=snapshot(engine,handle),armature=before.armatures?.find(v=>v.name==="WebGapArmatureSubdivideArmature");assert.ok(armature);assert.equal(armature.bones.length,3);const pieces=armature.bones.filter(b=>b.name!=="WebGapArmatureSubdivideOther");const other=armature.bones.find(b=>b.name==="WebGapArmatureSubdivideOther");assert.equal(pieces.length,2);assert.ok(other);assert.equal(other.selected,false);assert.deepEqual(new Set(pieces.flatMap(b=>[b.head,b.tail].map(v=>v.join(",")))),new Set(["0,0,0","0,0.5,0","0,1,0"]));const saved=output(engine,handle,engine._web_engine_save_blend,true),reopened=engine._web_engine_create();open(engine,reopened,saved);assert.deepEqual(snapshot(engine,reopened).armatures,before.armatures);const malformed=new Uint8Array([0x42,0x4c,0x45,0x4e,0x44,0x45,0x52]),pointer=engine._malloc(malformed.byteLength);let result;try{engine.HEAPU8.set(malformed,pointer);result=engine._web_engine_open_blend(handle,pointer,malformed.byteLength)}finally{engine._free(pointer)}assert.notEqual(result,0);assert.deepEqual(snapshot(engine,handle).armatures,before.armatures);engine._web_engine_destroy(handle);engine._web_engine_destroy(reopened);const report={schemaVersion:1,task,operation:"ARMATURE_SUBDIVIDE_LOCAL_EXACT",fixture:{path:path.relative(root,fixture).replaceAll(path.sep,"/"),sha256:desktop.fixtureSha256},desktop:{status:"EXACT",report:path.relative(root,desktopPath).replaceAll(path.sep,"/"),saveReopen:desktop.saveReopen,poll:desktop.poll,operatorStatus:desktop.operatorStatus,mainMutation:desktop.mainMutation,numberCuts:desktop.numberCuts,sourceBone:desktop.sourceBone,otherBone:desktop.otherBone},wasm:{status:"EXACT",armatureId:armature.id,pieceIds:pieces.map(b=>b.id),otherBoneId:other.id,pieceCount:pieces.length,otherSelected:other.selected},saveReopen:"EXACT",negative:{malformedBlend:"REJECTED_WITHOUT_MAIN_MUTATION"},nextTask:"M16-GAP-00262"};const reportPath=path.join(root,"tests/golden/M16-GAP-00261/armature-subdivide-local-exact-report.json");fs.writeFileSync(reportPath,`${JSON.stringify(report,null,2)}\n`);process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} cuts=1 pieces=2 desktop=exact saveReopen=exact next=${report.nextTask}\n`);process.exit(0); +} +if (task === "M16-GAP-00262") { + const fixture=path.join(root,"tests/files/web/generated/M16-GAP-00262-operator-armature.switch_direction.blend"),desktopPath=path.join(root,"tests/golden/M16-GAP-00262/armature-switch-direction-desktop-report.json");fs.mkdirSync(path.dirname(desktopPath),{recursive:true});const blender=process.env.BLENDER_BIN??path.join(root,"build_blender_5.2.0/bin/blender"),checker=path.join(root,"tools/web/check-action-armature-switch-direction-desktop.py"),run=spawnSync(blender,["-b","--factory-startup","--python",checker,"--",fixture,desktopPath],{cwd:root,encoding:"utf8",maxBuffer:8*1024*1024});assert.equal(run.status,0,`${run.stdout??""}\n${run.stderr??""}`);const desktop=JSON.parse(fs.readFileSync(desktopPath,"utf8"));assert.equal(desktop.saveReopen,"EXACT");const engine=await factory({wasmBinary}),handle=engine._web_engine_create();open(engine,handle,fs.readFileSync(fixture));const before=snapshot(engine,handle),armature=before.armatures?.find(v=>v.name==="WebGapArmatureSwitchDirectionArmature");assert.ok(armature);const by=Object.fromEntries(armature.bones.map(b=>[b.name,b]));assert.deepEqual(by.WebGapArmatureSwitchDirectionRoot.head,[0,1,0]);assert.deepEqual(by.WebGapArmatureSwitchDirectionRoot.tail,[0,0,0]);assert.equal(by.WebGapArmatureSwitchDirectionRoot.parentId,by.WebGapArmatureSwitchDirectionChild.id);assert.deepEqual(by.WebGapArmatureSwitchDirectionChild.head,[0,2,0]);assert.deepEqual(by.WebGapArmatureSwitchDirectionChild.tail,[0,1,0]);assert.equal(by.WebGapArmatureSwitchDirectionOther.selected,false);const saved=output(engine,handle,engine._web_engine_save_blend,true),reopened=engine._web_engine_create();open(engine,reopened,saved);assert.deepEqual(snapshot(engine,reopened).armatures,before.armatures);const malformed=new Uint8Array([0x42,0x4c,0x45,0x4e,0x44,0x45,0x52]),pointer=engine._malloc(malformed.byteLength);let result;try{engine.HEAPU8.set(malformed,pointer);result=engine._web_engine_open_blend(handle,pointer,malformed.byteLength)}finally{engine._free(pointer)}assert.notEqual(result,0);assert.deepEqual(snapshot(engine,handle).armatures,before.armatures);engine._web_engine_destroy(handle);engine._web_engine_destroy(reopened);const report={schemaVersion:1,task,operation:"ARMATURE_SWITCH_DIRECTION_LOCAL_EXACT",fixture:{path:path.relative(root,fixture).replaceAll(path.sep,"/"),sha256:desktop.fixtureSha256},desktop:{status:"EXACT",report:path.relative(root,desktopPath).replaceAll(path.sep,"/"),saveReopen:desktop.saveReopen,poll:desktop.poll,operatorStatus:desktop.operatorStatus,mainMutation:desktop.mainMutation},wasm:{status:"EXACT",armatureId:armature.id,rootBoneId:by.WebGapArmatureSwitchDirectionRoot.id,childBoneId:by.WebGapArmatureSwitchDirectionChild.id,otherBoneId:by.WebGapArmatureSwitchDirectionOther.id,rootParentId:by.WebGapArmatureSwitchDirectionRoot.parentId,rootHead:by.WebGapArmatureSwitchDirectionRoot.head,rootTail:by.WebGapArmatureSwitchDirectionRoot.tail,childHead:by.WebGapArmatureSwitchDirectionChild.head,childTail:by.WebGapArmatureSwitchDirectionChild.tail},saveReopen:"EXACT",negative:{malformedBlend:"REJECTED_WITHOUT_MAIN_MUTATION"},nextTask:"M16-GAP-00263"};const reportPath=path.join(root,"tests/golden/M16-GAP-00262/armature-switch-direction-local-exact-report.json");fs.writeFileSync(reportPath,`${JSON.stringify(report,null,2)}\n`);process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} reversed=1 desktop=exact saveReopen=exact next=${report.nextTask}\n`);process.exit(0); +} +if (task === "M16-GAP-00263") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00263-operator-armature.symmetrize.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00263/armature-symmetrize-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-armature-symmetrize-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.poll, true); + assert.ok(["FINISHED", "SKIPPED_ALREADY_APPLIED"].includes(desktop.operatorStatus)); + assert.ok(["MIRRORED_SELECTED_BONE", "MIRRORED_BONE_ALREADY_PRESENT"].includes(desktop.mainMutation)); + assert.equal(desktop.direction, "NEGATIVE_X"); + const desktopByName = Object.fromEntries(desktop.after.bones.map((bone) => [bone.name, bone])); + assert.deepEqual(desktopByName["WebGapArmatureSymmetrizeSource.L"].head, [1, 0, 0]); + assert.deepEqual(desktopByName["WebGapArmatureSymmetrizeSource.L"].tail, [1, 1, 0]); + assert.deepEqual(desktopByName["WebGapArmatureSymmetrizeSource.R"].head, [-1, 0, 0]); + assert.deepEqual(desktopByName["WebGapArmatureSymmetrizeSource.R"].tail, [-1, 1, 0]); + assert.equal(desktopByName.WebGapArmatureSymmetrizeOther.selected, false); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const armature = before.armatures?.find((value) => value.name === "WebGapArmatureSymmetrizeArmature"); + assert.ok(armature); + assert.equal(armature.bones.length, 3); + const byName = Object.fromEntries(armature.bones.map((bone) => [bone.name, bone])); + const source = byName["WebGapArmatureSymmetrizeSource.L"]; + const mirrored = byName["WebGapArmatureSymmetrizeSource.R"]; + const other = byName.WebGapArmatureSymmetrizeOther; + assert.ok(source && mirrored && other); + assert.equal(source.selected, false); + assert.equal(mirrored.selected, true); + assert.equal(other.selected, false); + assert.equal(source.parentId, null); + assert.equal(mirrored.parentId, null); + assert.deepEqual(source.head, desktopByName["WebGapArmatureSymmetrizeSource.L"].head); + assert.deepEqual(source.tail, desktopByName["WebGapArmatureSymmetrizeSource.L"].tail); + assert.deepEqual(mirrored.head, desktopByName["WebGapArmatureSymmetrizeSource.R"].head); + assert.deepEqual(mirrored.tail, desktopByName["WebGapArmatureSymmetrizeSource.R"].tail); + assert.deepEqual(other.head, desktopByName.WebGapArmatureSymmetrizeOther.head); + assert.deepEqual(other.tail, desktopByName.WebGapArmatureSymmetrizeOther.tail); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).armatures, before.armatures); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).armatures, before.armatures); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ARMATURE_SYMMETRIZE_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation, direction: desktop.direction, sourceBone: desktop.sourceBone, mirroredBone: desktop.mirroredBone, otherBone: desktop.otherBone }, wasm: { status: "EXACT", armatureId: armature.id, sourceBoneId: source.id, mirroredBoneId: mirrored.id, otherBoneId: other.id, sourceSelected: source.selected, mirroredSelected: mirrored.selected, otherSelected: other.selected, sourceHead: source.head, sourceTail: source.tail, mirroredHead: mirrored.head, mirroredTail: mirrored.tail }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00264" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00263/armature-symmetrize-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} armature=${armature.id} mirrored=1 direction=negative_x desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00205") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00205-operator-anim.separate_slots.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00205/anim-separate-slots-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-separate-slots-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.mainMutation, "SLOTS_SEPARATED"); + assert.equal(desktop.poll, true); + assert.equal(desktop.operatorStatus, "FINISHED"); + assert.deepEqual(Object.values(desktop.after.objects).map((value) => value.name).sort(), ["WebGapSeparateSlotAAction", "WebGapSeparateSlotBAction"]); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const animations = before.animations?.filter((value) => value.targetId && value.targetId !== "unlinked"); + assert.equal(animations?.length, 2); + assert.deepEqual(animations.map((value) => value.name).sort(), ["WebGapSeparateSlotAAction", "WebGapSeparateSlotBAction"]); + for (const animation of animations) { + assert.equal(animation.channels.length, 1); + assert.equal(animation.channels[0].path, '["separate_target"][0]'); + assert.deepEqual(animation.channels[0].keyframes.map((value) => value.frame), [1, 3, 5]); + } + assert.equal(before.animations?.some((value) => value.name === "WebGapAnimSeparateSlotsAction"), false); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).animations, before.animations); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).animations, before.animations); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ANIM_SEPARATE_SLOTS_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation }, wasm: { status: "EXACT", actionIds: animations.map((value) => value.id), actionNames: animations.map((value) => value.name).sort(), channelsPerAction: animations.map((value) => value.channels.length), oldActionEmpty: true }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00206" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00205/anim-separate-slots-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} actions=2 old-empty=true desktop=exact poll=true operator=${desktop.operatorStatus} saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00204") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00204-operator-anim.scene_range_frame.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00204/anim-scene-range-frame-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-scene-range-frame-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.mainMutation, "VIEW_FRAMED_TO_SCENE_RANGE"); + assert.equal(desktop.poll, true); + assert.equal(desktop.operatorStatus, "FINISHED"); + + const sameView = (left, right) => left?.cur?.xmin === right?.cur?.xmin && left?.cur?.xmax === right?.cur?.xmax && left?.cur?.ymin === right?.cur?.ymin && left?.cur?.ymax === right?.cur?.ymax && left?.mask?.xmin === right?.mask?.xmin && left?.mask?.xmax === right?.mask?.xmax && left?.mask?.ymin === right?.mask?.ymin && left?.mask?.ymax === right?.mask?.ymax; + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const actionRegion = before.editorWorkflow.workspaces.flatMap((workspace) => workspace.areas) + .filter((area) => area.editor === "DOPE_SHEET") + .flatMap((area) => area.regions) + .find((region) => region.kind === "MAIN" && sameView(region.view2d, desktop.view.view2d)); + assert.ok(actionRegion?.view2d); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).editorWorkflow, before.editorWorkflow); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).editorWorkflow, before.editorWorkflow); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ANIM_SCENE_RANGE_FRAME_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation }, wasm: { status: "EXACT", editor: "DOPE_SHEET", view2d: actionRegion.view2d }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00205" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00204/anim-scene-range-frame-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} editor=DOPE_SHEET view2d=exact poll=true operator=${desktop.operatorStatus} saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00203") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00203-operator-anim.replace_action_new.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00203/anim-replace-action-new-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-replace-action-new-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.mainMutation, "ACTION_REPLACED_WITH_NEW"); + assert.equal(desktop.poll, true); + assert.equal(desktop.operatorStatus, "FINISHED"); + assert.equal(desktop.newAction, "Action"); + assert.deepEqual(Object.values(desktop.after.objects).map((value) => value.name), ["Action", "Action"]); + assert.deepEqual(Object.values(desktop.after.objects).map((value) => value.channels.length), [0, 0]); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const oldAnimation = before.animations?.find((value) => value.name === "WebGapAnimReplaceNewOldAction" && value.unlinked); + assert.ok(oldAnimation); + assert.equal(oldAnimation.channels.length, 2); + assert.deepEqual(oldAnimation.channels.map((channel) => channel.keyframes.map((value) => value.value[0])), [[1, 3, 5], [2, 4, 6]]); + assert.equal(before.animations?.some((value) => value.name === desktop.newAction), false); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).animations, before.animations); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).animations, before.animations); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ANIM_REPLACE_ACTION_NEW_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation }, wasm: { status: "EXACT", replacedObjectIds: Object.keys(desktop.after.objects).map((name) => `object:${name}`), newAction: desktop.newAction, newActionChannels: 0, oldActionUnlinked: oldAnimation.id, oldActionChannels: oldAnimation.channels.length, emptyActionVisibility: "NOT_EXPOSED_BY_SCENE_SNAPSHOT" }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00204" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00203/anim-replace-action-new-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} actions=old->new-empty users=2 desktop=exact poll=true operator=${desktop.operatorStatus} saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00202") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00202-operator-anim.replace_action.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00202/anim-replace-action-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-replace-action-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.mainMutation, "ACTIONS_REPLACED"); + assert.equal(desktop.poll, true); + assert.equal(desktop.operatorStatus, "FINISHED"); + assert.equal(desktop.before.objects.WebGapAnimReplaceOldA.name, "WebGapAnimReplaceOldAction"); + assert.equal(desktop.before.objects.WebGapAnimReplaceOldB.name, "WebGapAnimReplaceOldAction"); + assert.deepEqual(Object.values(desktop.after.objects).map((value) => value.name), ["WebGapAnimReplaceNewAction", "WebGapAnimReplaceNewAction", "WebGapAnimReplaceNewAction"]); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const newAnimations = before.animations?.filter((value) => value.name === "WebGapAnimReplaceNewAction" && value.targetId !== "unlinked"); + const oldAnimation = before.animations?.find((value) => value.name === "WebGapAnimReplaceOldAction" && value.unlinked); + assert.equal(newAnimations?.length, 3); + assert.ok(oldAnimation); + for (const animation of newAnimations) { + assert.equal(animation.channels.length, 1); + assert.equal(animation.channels[0].path, '["replace_target"][0]'); + assert.deepEqual(animation.channels[0].keyframes.map((value) => value.frame), [1, 3, 5]); + assert.deepEqual(animation.channels[0].keyframes.map((value) => value.value[0]), [10, 30, 50]); + } + assert.deepEqual(oldAnimation.channels.map((channel) => channel.keyframes.map((value) => value.value[0])), [[1, 3, 5], [2, 4, 6]]); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).animations, before.animations); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).animations, before.animations); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ANIM_REPLACE_ACTION_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation }, wasm: { status: "EXACT", replacedObjectIds: newAnimations.map((value) => value.targetId), newAction: "WebGapAnimReplaceNewAction", oldActionUnlinked: oldAnimation.id, channelsPerObject: newAnimations.map((value) => value.channels.length), oldActionChannels: oldAnimation.channels.length }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00203" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00202/anim-replace-action-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} actions=old->new users=3 desktop=exact poll=true operator=${desktop.operatorStatus} saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00201") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00201-operator-anim.previewrange_set.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00201/anim-previewrange-set-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-previewrange-set-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.mainMutation, "PREVIEW_RANGE_SET"); + assert.equal(desktop.poll, true); + assert.equal(desktop.operatorStatus, "FINISHED"); + assert.deepEqual(desktop.after, { use: true, start: 2, end: 6 }); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const scene = before.scenes?.find((value) => value.id === before.sceneId) ?? before.scenes?.[0]; + assert.ok(scene); + assert.deepEqual(scene.previewRange, { start: 2, end: 6 }); + assert.deepEqual(scene.sequencerTimeline, { fpsDenominator: 1000, fpsNumerator: 24000, frameEnd: 8, frameStart: 1, id: "sequencer:scene:Scene", revision: 1, schemaVersion: 1, strips: [] }); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + const reopenedScene = snapshot(engine, reopened).scenes?.find((value) => value.id === scene.id); + assert.deepEqual(reopenedScene, scene); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).scenes?.find((value) => value.id === scene.id), scene); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ANIM_PREVIEWRANGE_SET_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation }, wasm: { status: "EXACT", sceneId: scene.id, previewRange: scene.previewRange, frameStart: scene.sequencerTimeline.frameStart, frameEnd: scene.sequencerTimeline.frameEnd }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00202" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00201/anim-previewrange-set-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} scene=${scene.id} preview=2-6 poll=true operator=${desktop.operatorStatus} desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00200") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00200-operator-anim.previewrange_clear.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00200/anim-previewrange-clear-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-previewrange-clear-desktop.py"); + const run = spawnSync(blender, ["-b", "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.mainMutation, "PREVIEW_RANGE_CLEARED"); + assert.equal(desktop.poll, true); + assert.equal(desktop.operatorStatus, "FINISHED"); + assert.deepEqual(desktop.after, { use: false, start: 0, end: 0 }); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const scene = before.scenes?.find((value) => value.id === before.sceneId) ?? before.scenes?.[0]; + assert.ok(scene); + assert.equal(Object.hasOwn(scene, "previewRange"), false); + assert.deepEqual(scene.sequencerTimeline, { fpsDenominator: 1000, fpsNumerator: 24000, frameEnd: 8, frameStart: 1, id: "sequencer:scene:Scene", revision: 1, schemaVersion: 1, strips: [] }); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + const reopenedScene = snapshot(engine, reopened).scenes?.find((value) => value.id === scene.id); + assert.deepEqual(reopenedScene, scene); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).scenes?.find((value) => value.id === scene.id), scene); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ANIM_PREVIEWRANGE_CLEAR_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation }, wasm: { status: "EXACT", sceneId: scene.id, previewRange: null, frameStart: scene.sequencerTimeline.frameStart, frameEnd: scene.sequencerTimeline.frameEnd }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00201" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00200/anim-previewrange-clear-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} scene=${scene.id} preview=cleared poll=true operator=${desktop.operatorStatus} desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} +if (task === "M16-GAP-00199") { + const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00199-operator-anim.paste_driver_button.blend"); + const desktopPath = path.join(root, "tests/golden/M16-GAP-00199/anim-paste-driver-button-desktop-report.json"); + fs.mkdirSync(path.dirname(desktopPath), { recursive: true }); + const blender = process.env.BLENDER_BIN ?? path.join(root, "build_blender_5.2.0/bin/blender"); + const checker = path.join(root, "tools/web/check-action-paste-driver-button-desktop.py"); + const run = spawnSync(process.env.XVFB_RUN_BIN ?? "xvfb-run", ["-a", "--server-args=-screen 0 1280x800x24", blender, "--factory-startup", "--python", checker, "--", fixture, desktopPath], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024, timeout: 45_000 }); + assert.equal(run.status, 0, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + assert.equal(fs.existsSync(desktopPath), true, `${run.stdout ?? ""}\n${run.stderr ?? ""}`); + const desktop = JSON.parse(fs.readFileSync(desktopPath, "utf8")); + assert.equal(desktop.saveReopen, "EXACT"); + assert.equal(desktop.mainMutation, "DRIVER_PASTED"); + assert.equal(desktop.poll, true); + assert.equal(desktop.operatorStatus, "FINISHED"); + assert.deepEqual(desktop.after?.source?.drivers ?? desktop.source?.drivers, [{ path: '["source_target"]', index: 0, expression: "frame * 3.0 + 2.0", type: "SCRIPTED", variableCount: 0 }]); + assert.deepEqual(desktop.after?.target?.drivers ?? desktop.target?.drivers, [{ path: '["paste_target"]', index: 0, expression: "frame * 3.0 + 2.0", type: "SCRIPTED", variableCount: 0 }]); + + const engine = await factory({ wasmBinary }); + const handle = engine._web_engine_create(); + open(engine, handle, fs.readFileSync(fixture)); + const before = snapshot(engine, handle); + const node = before.nodes?.find((value) => value.id === "object:WebGapAnimPasteDriverButtonObject"); + assert.ok(node); + const expectedDrivers = [ + { path: '["source_target"]', arrayIndex: 0, editable: true, enabled: true, expression: "frame * 3.0 + 2.0", type: "SCRIPTED", typeCode: 1, flags: 8, influence: 0, variables: [] }, + { path: '["paste_target"]', arrayIndex: 0, editable: true, enabled: true, expression: "frame * 3.0 + 2.0", type: "SCRIPTED", typeCode: 1, flags: 8, influence: 0, variables: [] }, + ]; + assert.deepEqual(node.drivers, expectedDrivers); + const saved = output(engine, handle, engine._web_engine_save_blend, true); + const reopened = engine._web_engine_create(); + open(engine, reopened, saved); + assert.deepEqual(snapshot(engine, reopened).nodes?.find((value) => value.id === node.id)?.drivers, node.drivers); + const malformed = new Uint8Array([0x42, 0x4c, 0x45, 0x4e, 0x44, 0x45, 0x52]); + const pointer = engine._malloc(malformed.byteLength); + let result; + try { engine.HEAPU8.set(malformed, pointer); result = engine._web_engine_open_blend(handle, pointer, malformed.byteLength); } finally { engine._free(pointer); } + assert.notEqual(result, 0); + assert.deepEqual(snapshot(engine, handle).nodes?.find((value) => value.id === node.id)?.drivers, node.drivers); + engine._web_engine_destroy(handle); + engine._web_engine_destroy(reopened); + const report = { schemaVersion: 1, task, operation: "ANIM_PASTE_DRIVER_BUTTON_LOCAL_EXACT", fixture: { path: path.relative(root, fixture).replaceAll(path.sep, "/"), sha256: desktop.fixtureSha256 }, desktop: { status: "EXACT", report: path.relative(root, desktopPath).replaceAll(path.sep, "/"), saveReopen: desktop.saveReopen, poll: desktop.poll, operatorStatus: desktop.operatorStatus, mainMutation: desktop.mainMutation }, wasm: { status: "EXACT", objectId: node.id, drivers: node.drivers }, saveReopen: "EXACT", negative: { malformedBlend: "REJECTED_WITHOUT_MAIN_MUTATION" }, nextTask: "M16-GAP-00200" }; + const reportPath = path.join(root, "tests/golden/M16-GAP-00199/anim-paste-driver-button-local-exact-report.json"); + fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`generated-gap-ok task=${task} drivers=${node.drivers.length} poll=true operator=${desktop.operatorStatus} mainMutation=driver_pasted desktop=exact saveReopen=exact next=${report.nextTask}\n`); + process.exit(0); +} if (task === "M16-GAP-00027") { const fixture = path.join(root, "tests/files/web/generated/M16-GAP-00027-datablock-WindowManager.blend"); const desktopPath = path.join(root, "tests/golden/M16-GAP-00027/window-manager-desktop-report.json"); diff --git a/tools/web/generated/M16-GAP-00175.py b/tools/web/generated/M16-GAP-00175.py new file mode 100644 index 00000000..861c840c --- /dev/null +++ b/tools/web/generated/M16-GAP-00175.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00175.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + mesh = bpy.data.meshes.new("WebGapAnimDriverButtonEditMesh") + mesh.from_pydata( + [(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)], + [], + [(0, 1, 2, 3)], + ) + obj = bpy.data.objects.new("WebGapAnimDriverButtonEditObject", mesh) + bpy.context.scene.collection.objects.link(obj) + obj["drive_target"] = 7.25 + driver = obj.driver_add('["drive_target"]') + driver.driver.type = "SCRIPTED" + driver.driver.expression = "frame * 2.5 + 1.25" + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.context.scene.frame_start = 1 + bpy.context.scene.frame_end = 5 + bpy.context.scene.frame_set(1) + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00176.py b/tools/web/generated/M16-GAP-00176.py new file mode 100644 index 00000000..f7c0c24e --- /dev/null +++ b/tools/web/generated/M16-GAP-00176.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00176.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + mesh = bpy.data.meshes.new("WebGapAnimDriverButtonRemoveMesh") + mesh.from_pydata( + [(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)], + [], + [(0, 1, 2, 3)], + ) + obj = bpy.data.objects.new("WebGapAnimDriverButtonRemoveObject", mesh) + bpy.context.scene.collection.objects.link(obj) + obj["drive_target"] = 7.25 + driver = obj.driver_add('["drive_target"]') + driver.driver.type = "SCRIPTED" + driver.driver.expression = "frame * 2.5 + 1.25" + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.context.scene.frame_start = 1 + bpy.context.scene.frame_end = 5 + bpy.context.scene.frame_set(1) + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00177.py b/tools/web/generated/M16-GAP-00177.py new file mode 100644 index 00000000..0bc03979 --- /dev/null +++ b/tools/web/generated/M16-GAP-00177.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00177.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + scene = bpy.context.scene + scene.frame_start = 1 + scene.frame_end = 120 + scene.frame_set(42) + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00178.py b/tools/web/generated/M16-GAP-00178.py new file mode 100644 index 00000000..f6bb9989 --- /dev/null +++ b/tools/web/generated/M16-GAP-00178.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00178.py -- OUTPUT") + + bpy.ops.wm.read_factory_settings(use_empty=True) + mesh = bpy.data.meshes.new("WebGapAnimKeyframeClearButtonMesh") + mesh.from_pydata( + [(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)], + [], + [(0, 1, 2, 3)], + ) + obj = bpy.data.objects.new("WebGapAnimKeyframeClearButtonObject", mesh) + bpy.context.scene.collection.objects.link(obj) + obj["clear_target"] = 3.0 + for frame, value in ((1, 1.0), (3, 3.0), (5, 5.0)): + bpy.context.scene.frame_set(frame) + obj["clear_target"] = value + obj.keyframe_insert(data_path='["clear_target"]', frame=frame) + obj.animation_data.action.name = "WebGapAnimKeyframeClearButtonAction" + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.context.scene.frame_start = 1 + bpy.context.scene.frame_end = 5 + bpy.context.scene.frame_set(3) + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00179.py b/tools/web/generated/M16-GAP-00179.py new file mode 100644 index 00000000..446167bf --- /dev/null +++ b/tools/web/generated/M16-GAP-00179.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00179.py -- OUTPUT") + + bpy.ops.wm.read_factory_settings(use_empty=True) + mesh = bpy.data.meshes.new("WebGapAnimKeyframeClearV3DMesh") + mesh.from_pydata( + [(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)], + [], + [(0, 1, 2, 3)], + ) + obj = bpy.data.objects.new("WebGapAnimKeyframeClearV3DObject", mesh) + bpy.context.scene.collection.objects.link(obj) + obj["clear_target"] = 3.0 + for frame, value in ((1, 1.0), (3, 3.0), (5, 5.0)): + bpy.context.scene.frame_set(frame) + obj["clear_target"] = value + obj.keyframe_insert(data_path='["clear_target"]', frame=frame) + obj.animation_data.action.name = "WebGapAnimKeyframeClearV3DAction" + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.context.scene.frame_start = 1 + bpy.context.scene.frame_end = 5 + bpy.context.scene.frame_set(3) + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00180.py b/tools/web/generated/M16-GAP-00180.py new file mode 100644 index 00000000..19771862 --- /dev/null +++ b/tools/web/generated/M16-GAP-00180.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00180.py -- OUTPUT") + + bpy.ops.wm.read_factory_settings(use_empty=True) + scene = bpy.context.scene + sequence_editor = scene.sequence_editor_create() + source = pathlib.Path(__file__).resolve().parents[3] / "tests/files/web/media/sequencer-frame.png" + strip = sequence_editor.strips.new_image( + name="WebGapAnimKeyframeClearVSEStrip", + filepath=str(source), + channel=1, + frame_start=1, + ) + strip.directory = "//../media/" + strip.frame_final_duration = 6 + strip.select = True + sequence_editor.active_strip = strip + for frame, value in ((1, 0.25), (3, 0.5), (5, 0.75)): + scene.frame_set(frame) + strip.blend_alpha = value + strip.keyframe_insert(data_path="blend_alpha", frame=frame) + scene.animation_data.action.name = "WebGapAnimKeyframeClearVSEAction" + scene.frame_start = 1 + scene.frame_end = 6 + scene.frame_set(3) + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00181.py b/tools/web/generated/M16-GAP-00181.py new file mode 100644 index 00000000..a437dd0d --- /dev/null +++ b/tools/web/generated/M16-GAP-00181.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +OBJECT_NAME = "WebGapAnimKeyframeDeleteObject" +ACTION_NAME = "WebGapAnimKeyframeDeleteAction" +KEYING_SET_NAME = "WebGapAnimKeyframeDeleteSet" +DATA_PATH = '["delete_target"]' + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00181.py -- OUTPUT") + + bpy.ops.wm.read_factory_settings(use_empty=True) + mesh = bpy.data.meshes.new("WebGapAnimKeyframeDeleteMesh") + mesh.from_pydata( + [(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)], + [], + [(0, 1, 2, 3)], + ) + obj = bpy.data.objects.new(OBJECT_NAME, mesh) + bpy.context.scene.collection.objects.link(obj) + obj["delete_target"] = 3.0 + for frame, value in ((1, 1.0), (3, 3.0), (5, 5.0)): + bpy.context.scene.frame_set(frame) + obj["delete_target"] = value + obj.keyframe_insert(data_path=DATA_PATH, frame=frame) + obj.animation_data.action.name = ACTION_NAME + + keying_set = bpy.context.scene.keying_sets.new(idname=KEYING_SET_NAME, name=KEYING_SET_NAME) + keying_set.paths.add(obj, DATA_PATH, index=0) + bpy.context.scene.keying_sets.active_index = 0 + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.context.scene.frame_start = 1 + bpy.context.scene.frame_end = 5 + bpy.context.scene.frame_set(3) + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00182.py b/tools/web/generated/M16-GAP-00182.py new file mode 100644 index 00000000..58160f7d --- /dev/null +++ b/tools/web/generated/M16-GAP-00182.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00182.py -- OUTPUT") + + bpy.ops.wm.read_factory_settings(use_empty=True) + mesh = bpy.data.meshes.new("WebGapAnimKeyframeDeleteButtonMesh") + mesh.from_pydata( + [(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)], + [], + [(0, 1, 2, 3)], + ) + obj = bpy.data.objects.new("WebGapAnimKeyframeDeleteButtonObject", mesh) + bpy.context.scene.collection.objects.link(obj) + obj["delete_target"] = 3.0 + for frame, value in ((1, 1.0), (3, 3.0), (5, 5.0)): + bpy.context.scene.frame_set(frame) + obj["delete_target"] = value + obj.keyframe_insert(data_path='["delete_target"]', frame=frame) + obj.animation_data.action.name = "WebGapAnimKeyframeDeleteButtonAction" + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.context.scene.frame_start = 1 + bpy.context.scene.frame_end = 5 + bpy.context.scene.frame_set(3) + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00183.py b/tools/web/generated/M16-GAP-00183.py new file mode 100644 index 00000000..87350bc4 --- /dev/null +++ b/tools/web/generated/M16-GAP-00183.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +OBJECT_NAME = "WebGapAnimKeyframeDeleteByNameObject" +ACTION_NAME = "WebGapAnimKeyframeDeleteByNameAction" +KEYING_SET_NAME = "WebGapAnimKeyframeDeleteByNameSet" +DATA_PATH = '["delete_target"]' + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00183.py -- OUTPUT") + + bpy.ops.wm.read_factory_settings(use_empty=True) + mesh = bpy.data.meshes.new("WebGapAnimKeyframeDeleteByNameMesh") + mesh.from_pydata( + [(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)], + [], + [(0, 1, 2, 3)], + ) + obj = bpy.data.objects.new(OBJECT_NAME, mesh) + bpy.context.scene.collection.objects.link(obj) + obj["delete_target"] = 3.0 + for frame, value in ((1, 1.0), (3, 3.0), (5, 5.0)): + bpy.context.scene.frame_set(frame) + obj["delete_target"] = value + obj.keyframe_insert(data_path=DATA_PATH, frame=frame) + obj.animation_data.action.name = ACTION_NAME + + keying_set = bpy.context.scene.keying_sets.new(idname=KEYING_SET_NAME, name=KEYING_SET_NAME) + keying_set.paths.add(obj, DATA_PATH, index=0) + bpy.context.scene.keying_sets.active_index = 0 + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.context.scene.frame_start = 1 + bpy.context.scene.frame_end = 5 + bpy.context.scene.frame_set(3) + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00184.py b/tools/web/generated/M16-GAP-00184.py new file mode 100644 index 00000000..ef2de62a --- /dev/null +++ b/tools/web/generated/M16-GAP-00184.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +OBJECT_NAME = "WebGapAnimKeyframeDeleteV3DObject" +ACTION_NAME = "WebGapAnimKeyframeDeleteV3DAction" +DATA_PATH = '["delete_target"]' + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00184.py -- OUTPUT") + + bpy.ops.wm.read_factory_settings(use_empty=True) + mesh = bpy.data.meshes.new("WebGapAnimKeyframeDeleteV3DMesh") + mesh.from_pydata( + [(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)], + [], + [(0, 1, 2, 3)], + ) + obj = bpy.data.objects.new(OBJECT_NAME, mesh) + bpy.context.scene.collection.objects.link(obj) + obj["delete_target"] = 3.0 + for frame, value in ((1, 1.0), (3, 3.0), (5, 5.0)): + bpy.context.scene.frame_set(frame) + obj["delete_target"] = value + obj.keyframe_insert(data_path=DATA_PATH, frame=frame) + obj.animation_data.action.name = ACTION_NAME + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.context.scene.frame_start = 1 + bpy.context.scene.frame_end = 5 + bpy.context.scene.frame_set(3) + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00185.py b/tools/web/generated/M16-GAP-00185.py new file mode 100644 index 00000000..1702cd3e --- /dev/null +++ b/tools/web/generated/M16-GAP-00185.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +STRIP_NAME = "WebGapAnimKeyframeDeleteVSEStrip" +ACTION_NAME = "WebGapAnimKeyframeDeleteVSEAction" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00185.py -- OUTPUT") + + bpy.ops.wm.read_factory_settings(use_empty=True) + scene = bpy.context.scene + sequence_editor = scene.sequence_editor_create() + source = pathlib.Path(__file__).resolve().parents[3] / "tests/files/web/media/sequencer-frame.png" + strip = sequence_editor.strips.new_image( + name=STRIP_NAME, + filepath=str(source), + channel=1, + frame_start=1, + ) + strip.directory = "//../media/" + strip.frame_final_duration = 6 + strip.select = True + sequence_editor.active_strip = strip + for frame, value in ((1, 0.25), (3, 0.5), (5, 0.75)): + scene.frame_set(frame) + strip.blend_alpha = value + strip.keyframe_insert(data_path="blend_alpha", frame=frame) + scene.animation_data.action.name = ACTION_NAME + scene.frame_start = 1 + scene.frame_end = 6 + scene.frame_set(3) + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00186.py b/tools/web/generated/M16-GAP-00186.py new file mode 100644 index 00000000..8cea55ac --- /dev/null +++ b/tools/web/generated/M16-GAP-00186.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +OBJECT_NAME = "WebGapAnimKeyframeInsertObject" +ACTION_NAME = "WebGapAnimKeyframeInsertAction" +KEYING_SET_NAME = "WebGapAnimKeyframeInsertSet" +DATA_PATH = '["insert_target"]' + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00186.py -- OUTPUT") + + bpy.ops.wm.read_factory_settings(use_empty=True) + mesh = bpy.data.meshes.new("WebGapAnimKeyframeInsertMesh") + mesh.from_pydata( + [(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)], + [], + [(0, 1, 2, 3)], + ) + obj = bpy.data.objects.new(OBJECT_NAME, mesh) + bpy.context.scene.collection.objects.link(obj) + obj["insert_target"] = 3.0 + for frame, value in ((1, 1.0), (5, 5.0)): + bpy.context.scene.frame_set(frame) + obj["insert_target"] = value + obj.keyframe_insert(data_path=DATA_PATH, frame=frame) + obj.animation_data.action.name = ACTION_NAME + + keying_set = bpy.context.scene.keying_sets.new(idname=KEYING_SET_NAME, name=KEYING_SET_NAME) + keying_set.paths.add(obj, DATA_PATH, index=0) + bpy.context.scene.keying_sets.active_index = 0 + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.context.scene.frame_start = 1 + bpy.context.scene.frame_end = 5 + bpy.context.scene.frame_set(3) + obj["insert_target"] = 3.0 + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00187.py b/tools/web/generated/M16-GAP-00187.py new file mode 100644 index 00000000..10546b22 --- /dev/null +++ b/tools/web/generated/M16-GAP-00187.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00187.py -- OUTPUT") + + bpy.ops.wm.read_factory_settings(use_empty=True) + mesh = bpy.data.meshes.new("WebGapAnimKeyframeInsertButtonMesh") + mesh.from_pydata( + [(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)], + [], + [(0, 1, 2, 3)], + ) + obj = bpy.data.objects.new("WebGapAnimKeyframeInsertButtonObject", mesh) + bpy.context.scene.collection.objects.link(obj) + obj["insert_target"] = 3.0 + for frame, value in ((1, 1.0), (5, 5.0)): + bpy.context.scene.frame_set(frame) + obj["insert_target"] = value + obj.keyframe_insert(data_path='["insert_target"]', frame=frame) + obj.animation_data.action.name = "WebGapAnimKeyframeInsertButtonAction" + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.context.scene.frame_start = 1 + bpy.context.scene.frame_end = 5 + bpy.context.scene.frame_set(3) + obj["insert_target"] = 3.0 + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00188.py b/tools/web/generated/M16-GAP-00188.py new file mode 100644 index 00000000..7f97e7d8 --- /dev/null +++ b/tools/web/generated/M16-GAP-00188.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +OBJECT_NAME = "WebGapAnimKeyframeInsertByNameObject" +ACTION_NAME = "WebGapAnimKeyframeInsertByNameAction" +KEYING_SET_NAME = "WebGapAnimKeyframeInsertByNameSet" +DATA_PATH = '["insert_target"]' + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00188.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + mesh = bpy.data.meshes.new("WebGapAnimKeyframeInsertByNameMesh") + mesh.from_pydata( + [(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)], + [], [(0, 1, 2, 3)], + ) + obj = bpy.data.objects.new(OBJECT_NAME, mesh) + bpy.context.scene.collection.objects.link(obj) + obj["insert_target"] = 3.0 + for frame, value in ((1, 1.0), (5, 5.0)): + bpy.context.scene.frame_set(frame) + obj["insert_target"] = value + obj.keyframe_insert(data_path=DATA_PATH, frame=frame) + obj.animation_data.action.name = ACTION_NAME + keying_set = bpy.context.scene.keying_sets.new(idname=KEYING_SET_NAME, name=KEYING_SET_NAME) + keying_set.paths.add(obj, DATA_PATH, index=0) + bpy.context.scene.keying_sets.active_index = 0 + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.context.scene.frame_start = 1 + bpy.context.scene.frame_end = 5 + bpy.context.scene.frame_set(3) + obj["insert_target"] = 3.0 + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00189.py b/tools/web/generated/M16-GAP-00189.py new file mode 100644 index 00000000..792d475c --- /dev/null +++ b/tools/web/generated/M16-GAP-00189.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +OBJECT_NAME = "WebGapAnimKeyframeInsertMenuObject" +ACTION_NAME = "WebGapAnimKeyframeInsertMenuAction" +KEYING_SET_NAME = "WebGapAnimKeyframeInsertMenuSet" +DATA_PATH = '["insert_target"]' + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00189.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + mesh = bpy.data.meshes.new("WebGapAnimKeyframeInsertMenuMesh") + mesh.from_pydata([(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)], [], [(0, 1, 2, 3)]) + obj = bpy.data.objects.new(OBJECT_NAME, mesh) + bpy.context.scene.collection.objects.link(obj) + obj["insert_target"] = 3.0 + for frame, value in ((1, 1.0), (5, 5.0)): + bpy.context.scene.frame_set(frame) + obj["insert_target"] = value + obj.keyframe_insert(data_path=DATA_PATH, frame=frame) + obj.animation_data.action.name = ACTION_NAME + keying_set = bpy.context.scene.keying_sets.new(idname=KEYING_SET_NAME, name=KEYING_SET_NAME) + keying_set.paths.add(obj, DATA_PATH, index=0) + bpy.context.scene.keying_sets.active_index = 0 + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.context.scene.frame_start = 1 + bpy.context.scene.frame_end = 5 + bpy.context.scene.frame_set(3) + obj["insert_target"] = 3.0 + bpy.ops.wm.save_as_mainfile(filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00190.py b/tools/web/generated/M16-GAP-00190.py new file mode 100644 index 00000000..f212e175 --- /dev/null +++ b/tools/web/generated/M16-GAP-00190.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +OBJECT_NAME = "WebGapAnimKeyingSetActiveObject" +ACTION_NAME = "WebGapAnimKeyingSetActiveAction" +KEYING_SET_A = "WebGapAnimKeyingSetActiveA" +KEYING_SET_B = "WebGapAnimKeyingSetActiveB" +DATA_PATH = '["active_target"]' + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00190.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + mesh = bpy.data.meshes.new("WebGapAnimKeyingSetActiveMesh") + mesh.from_pydata([(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)], [], [(0, 1, 2, 3)]) + obj = bpy.data.objects.new(OBJECT_NAME, mesh) + bpy.context.scene.collection.objects.link(obj) + obj["active_target"] = 3.0 + for frame, value in ((1, 1.0), (3, 3.0), (5, 5.0)): + bpy.context.scene.frame_set(frame) + obj["active_target"] = value + obj.keyframe_insert(data_path=DATA_PATH, frame=frame) + obj.animation_data.action.name = ACTION_NAME + first = bpy.context.scene.keying_sets.new(idname=KEYING_SET_A, name=KEYING_SET_A) + first.paths.add(obj, DATA_PATH, index=0) + second = bpy.context.scene.keying_sets.new(idname=KEYING_SET_B, name=KEYING_SET_B) + second.paths.add(obj, DATA_PATH, index=0) + bpy.context.scene.keying_sets.active_index = 0 + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.context.scene.frame_start = 1 + bpy.context.scene.frame_end = 5 + bpy.context.scene.frame_set(3) + bpy.ops.wm.save_as_mainfile(filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00191.py b/tools/web/generated/M16-GAP-00191.py new file mode 100644 index 00000000..fd841321 --- /dev/null +++ b/tools/web/generated/M16-GAP-00191.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +OBJECT_NAME = "WebGapAnimKeyingSetAddObject" +ACTION_NAME = "WebGapAnimKeyingSetAddAction" +DATA_PATH = '["add_target"]' + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00191.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + mesh = bpy.data.meshes.new("WebGapAnimKeyingSetAddMesh") + mesh.from_pydata([(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)], [], [(0, 1, 2, 3)]) + obj = bpy.data.objects.new(OBJECT_NAME, mesh) + bpy.context.scene.collection.objects.link(obj) + obj["add_target"] = 3.0 + for frame, value in ((1, 1.0), (3, 3.0), (5, 5.0)): + bpy.context.scene.frame_set(frame); obj["add_target"] = value; obj.keyframe_insert(data_path=DATA_PATH, frame=frame) + obj.animation_data.action.name = ACTION_NAME + bpy.context.view_layer.objects.active = obj; obj.select_set(True); bpy.context.scene.frame_start = 1; bpy.context.scene.frame_end = 5; bpy.context.scene.frame_set(3) + bpy.ops.wm.save_as_mainfile(filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00192.py b/tools/web/generated/M16-GAP-00192.py new file mode 100644 index 00000000..75e3d1cb --- /dev/null +++ b/tools/web/generated/M16-GAP-00192.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00192.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + mesh = bpy.data.meshes.new("WebGapAnimKeyingSetExportMesh") + mesh.from_pydata([(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)], [], [(0, 1, 2, 3)]) + obj = bpy.data.objects.new("WebGapAnimKeyingSetExportObject", mesh) + bpy.context.scene.collection.objects.link(obj) + obj["export_target"] = 3.0 + for frame, value in ((1, 1.0), (3, 3.0), (5, 5.0)): + bpy.context.scene.frame_set(frame); obj["export_target"] = value; obj.keyframe_insert(data_path='["export_target"]', frame=frame) + obj.animation_data.action.name = "WebGapAnimKeyingSetExportAction" + keying_set = bpy.context.scene.keying_sets.new(idname="WebGapAnimKeyingSetExportSet", name="WebGapAnimKeyingSetExportSet") + keying_set.paths.add(obj, '["export_target"]', index=0) + bpy.context.scene.keying_sets.active_index = 0 + bpy.context.view_layer.objects.active = obj; obj.select_set(True); bpy.context.scene.frame_start = 1; bpy.context.scene.frame_end = 5; bpy.context.scene.frame_set(3) + bpy.ops.wm.save_as_mainfile(filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00193.py b/tools/web/generated/M16-GAP-00193.py new file mode 100644 index 00000000..9a3a0873 --- /dev/null +++ b/tools/web/generated/M16-GAP-00193.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +OBJECT_NAME = "WebGapAnimKeyingSetPathAddObject" +ACTION_NAME = "WebGapAnimKeyingSetPathAddAction" +KEYING_SET_NAME = "WebGapAnimKeyingSetPathAddSet" +DATA_PATH = '["path_add_target"]' + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00193.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + mesh = bpy.data.meshes.new("WebGapAnimKeyingSetPathAddMesh") + mesh.from_pydata([(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)], [], [(0, 1, 2, 3)]) + obj = bpy.data.objects.new(OBJECT_NAME, mesh) + bpy.context.scene.collection.objects.link(obj) + obj["path_add_target"] = 3.0 + for frame, value in ((1, 1.0), (3, 3.0), (5, 5.0)): + bpy.context.scene.frame_set(frame) + obj["path_add_target"] = value + obj.keyframe_insert(data_path=DATA_PATH, frame=frame) + obj.animation_data.action.name = ACTION_NAME + bpy.context.scene.keying_sets.new(idname=KEYING_SET_NAME, name=KEYING_SET_NAME) + bpy.context.scene.keying_sets.active_index = 0 + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.context.scene.frame_start = 1 + bpy.context.scene.frame_end = 5 + bpy.context.scene.frame_set(3) + bpy.ops.wm.save_as_mainfile(filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00194.py b/tools/web/generated/M16-GAP-00194.py new file mode 100644 index 00000000..865d45da --- /dev/null +++ b/tools/web/generated/M16-GAP-00194.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +OBJECT_NAME = "WebGapAnimKeyingSetPathRemoveObject" +ACTION_NAME = "WebGapAnimKeyingSetPathRemoveAction" +KEYING_SET_NAME = "WebGapAnimKeyingSetPathRemoveSet" +DATA_PATH = '["path_remove_target"]' + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00194.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + mesh = bpy.data.meshes.new("WebGapAnimKeyingSetPathRemoveMesh") + mesh.from_pydata([(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)], [], [(0, 1, 2, 3)]) + obj = bpy.data.objects.new(OBJECT_NAME, mesh) + bpy.context.scene.collection.objects.link(obj) + obj["path_remove_target"] = 3.0 + for frame, value in ((1, 1.0), (3, 3.0), (5, 5.0)): + bpy.context.scene.frame_set(frame) + obj["path_remove_target"] = value + obj.keyframe_insert(data_path=DATA_PATH, frame=frame) + obj.animation_data.action.name = ACTION_NAME + keying_set = bpy.context.scene.keying_sets.new(idname=KEYING_SET_NAME, name=KEYING_SET_NAME) + keying_set.paths.add(obj, DATA_PATH, index=0) + bpy.context.scene.keying_sets.active_index = 0 + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.context.scene.frame_start = 1 + bpy.context.scene.frame_end = 5 + bpy.context.scene.frame_set(3) + bpy.ops.wm.save_as_mainfile(filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00195.py b/tools/web/generated/M16-GAP-00195.py new file mode 100644 index 00000000..a65440bf --- /dev/null +++ b/tools/web/generated/M16-GAP-00195.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +OBJECT_NAME = "WebGapAnimKeyingSetRemoveObject" +ACTION_NAME = "WebGapAnimKeyingSetRemoveAction" +KEYING_SET_NAME = "WebGapAnimKeyingSetRemoveSet" +DATA_PATH = '["remove_target"]' + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00195.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + mesh = bpy.data.meshes.new("WebGapAnimKeyingSetRemoveMesh") + mesh.from_pydata([(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)], [], [(0, 1, 2, 3)]) + obj = bpy.data.objects.new(OBJECT_NAME, mesh) + bpy.context.scene.collection.objects.link(obj) + obj["remove_target"] = 3.0 + for frame, value in ((1, 1.0), (3, 3.0), (5, 5.0)): + bpy.context.scene.frame_set(frame) + obj["remove_target"] = value + obj.keyframe_insert(data_path=DATA_PATH, frame=frame) + obj.animation_data.action.name = ACTION_NAME + bpy.context.scene.keying_sets.new(idname=KEYING_SET_NAME, name=KEYING_SET_NAME) + bpy.context.scene.keying_sets.active_index = 0 + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.context.scene.frame_start = 1 + bpy.context.scene.frame_end = 5 + bpy.context.scene.frame_set(3) + bpy.ops.wm.save_as_mainfile(filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00196.py b/tools/web/generated/M16-GAP-00196.py new file mode 100644 index 00000000..e79f7cab --- /dev/null +++ b/tools/web/generated/M16-GAP-00196.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +OBJECT_NAME = "WebGapAnimKeyingSetButtonAddObject" +ACTION_NAME = "WebGapAnimKeyingSetButtonAddAction" +DATA_PATH = '["button_target"]' + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00196.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + mesh = bpy.data.meshes.new("WebGapAnimKeyingSetButtonAddMesh") + mesh.from_pydata([(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)], [], [(0, 1, 2, 3)]) + obj = bpy.data.objects.new(OBJECT_NAME, mesh) + bpy.context.scene.collection.objects.link(obj) + obj["button_target"] = 3.0 + for frame, value in ((1, 1.0), (3, 3.0), (5, 5.0)): + bpy.context.scene.frame_set(frame) + obj["button_target"] = value + obj.keyframe_insert(data_path=DATA_PATH, frame=frame) + obj.animation_data.action.name = ACTION_NAME + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.context.scene.frame_start = 1 + bpy.context.scene.frame_end = 5 + bpy.context.scene.frame_set(3) + bpy.ops.wm.save_as_mainfile(filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00197.py b/tools/web/generated/M16-GAP-00197.py new file mode 100644 index 00000000..fa74b4dc --- /dev/null +++ b/tools/web/generated/M16-GAP-00197.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +OBJECT_NAME = "WebGapAnimKeyingSetButtonRemoveObject" +ACTION_NAME = "WebGapAnimKeyingSetButtonRemoveAction" +KEYING_SET_NAME = "ButtonKeyingSet" +DATA_PATH = '["button_remove_target"]' + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00197.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + mesh = bpy.data.meshes.new("WebGapAnimKeyingSetButtonRemoveMesh") + mesh.from_pydata([(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)], [], [(0, 1, 2, 3)]) + obj = bpy.data.objects.new(OBJECT_NAME, mesh) + bpy.context.scene.collection.objects.link(obj) + obj["button_remove_target"] = 3.0 + for frame, value in ((1, 1.0), (3, 3.0), (5, 5.0)): + bpy.context.scene.frame_set(frame) + obj["button_remove_target"] = value + obj.keyframe_insert(data_path=DATA_PATH, frame=frame) + obj.animation_data.action.name = ACTION_NAME + keying_set = bpy.context.scene.keying_sets.new(idname=KEYING_SET_NAME, name=KEYING_SET_NAME) + keying_set.paths.add(obj, DATA_PATH, index=0) + bpy.context.scene.keying_sets.active_index = 0 + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.context.scene.frame_start = 1 + bpy.context.scene.frame_end = 5 + bpy.context.scene.frame_set(3) + bpy.ops.wm.save_as_mainfile(filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00198.py b/tools/web/generated/M16-GAP-00198.py new file mode 100644 index 00000000..495ee6a4 --- /dev/null +++ b/tools/web/generated/M16-GAP-00198.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ACTIVE_OBJECT = "WebGapAnimMergeActiveObject" +SOURCE_OBJECT = "WebGapAnimMergeSourceObject" +ACTIVE_ACTION = "WebGapAnimMergeActiveAction" +SOURCE_ACTION = "WebGapAnimMergeSourceAction" + + +def make_object(name, prop_name, action_name, values): + mesh = bpy.data.meshes.new(f"{name}Mesh") + mesh.from_pydata([(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)], [], [(0, 1, 2, 3)]) + obj = bpy.data.objects.new(name, mesh) + bpy.context.scene.collection.objects.link(obj) + obj[prop_name] = values[1] + for frame, value in zip((1, 3, 5), values): + bpy.context.scene.frame_set(frame) + obj[prop_name] = value + obj.keyframe_insert(data_path=f'["{prop_name}"]', frame=frame) + obj.animation_data.action.name = action_name + return obj + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00198.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + active = make_object(ACTIVE_OBJECT, "active_merge_target", ACTIVE_ACTION, (1.0, 3.0, 5.0)) + source = make_object(SOURCE_OBJECT, "source_merge_target", SOURCE_ACTION, (10.0, 30.0, 50.0)) + bpy.context.view_layer.objects.active = active + active.select_set(True) + source.select_set(True) + bpy.context.scene.frame_start = 1 + bpy.context.scene.frame_end = 5 + bpy.context.scene.frame_set(3) + bpy.ops.wm.save_as_mainfile(filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00199.py b/tools/web/generated/M16-GAP-00199.py new file mode 100644 index 00000000..8a06822f --- /dev/null +++ b/tools/web/generated/M16-GAP-00199.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00199.py -- OUTPUT") + + bpy.ops.wm.read_factory_settings(use_empty=True) + mesh = bpy.data.meshes.new("WebGapAnimPasteDriverButtonMesh") + mesh.from_pydata( + [(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)], + [], + [(0, 1, 2, 3)], + ) + obj = bpy.data.objects.new("WebGapAnimPasteDriverButtonObject", mesh) + bpy.context.scene.collection.objects.link(obj) + obj["source_target"] = 2.5 + obj["paste_target"] = 7.5 + source_driver = obj.driver_add('["source_target"]') + source_driver.driver.type = "SCRIPTED" + source_driver.driver.expression = "frame * 3.0 + 2.0" + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.context.scene.frame_start = 1 + bpy.context.scene.frame_end = 5 + bpy.context.scene.frame_set(1) + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00200.py b/tools/web/generated/M16-GAP-00200.py new file mode 100644 index 00000000..8e13606a --- /dev/null +++ b/tools/web/generated/M16-GAP-00200.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +def clear_preview_range(): + window = bpy.context.window + screen = window.screen + area = next(candidate for candidate in screen.areas if candidate.type == "DOPESHEET_EDITOR") + region = next(candidate for candidate in area.regions if candidate.type == "WINDOW") + with bpy.context.temp_override(window=window, screen=screen, area=area, region=region): + if not bpy.ops.anim.previewrange_clear.poll(): + raise RuntimeError("ANIM_OT_previewrange_clear poll failed in animation editor context") + result = bpy.ops.anim.previewrange_clear() + if "FINISHED" not in result: + raise RuntimeError(f"ANIM_OT_previewrange_clear returned {result}") + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00200.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + mesh = bpy.data.meshes.new("WebGapAnimPreviewRangeClearMesh") + mesh.from_pydata( + [(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)], + [], + [(0, 1, 2, 3)], + ) + obj = bpy.data.objects.new("WebGapAnimPreviewRangeClearObject", mesh) + bpy.context.scene.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + scene = bpy.context.scene + scene.frame_start = 1 + scene.frame_end = 8 + scene.use_preview_range = True + scene.frame_preview_start = 2 + scene.frame_preview_end = 6 + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00201.py b/tools/web/generated/M16-GAP-00201.py new file mode 100644 index 00000000..386c0752 --- /dev/null +++ b/tools/web/generated/M16-GAP-00201.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +def set_preview_range(): + window = bpy.context.window + screen = window.screen + area = next(candidate for candidate in screen.areas if candidate.type == "DOPESHEET_EDITOR") + region = next(candidate for candidate in area.regions if candidate.type == "WINDOW") + with bpy.context.temp_override(window=window, screen=screen, area=area, region=region): + if not bpy.ops.anim.previewrange_set.poll(): + raise RuntimeError("ANIM_OT_previewrange_set poll failed in animation editor context") + result = bpy.ops.anim.previewrange_set(xmin=62, xmax=88, ymin=0, ymax=47) + if "FINISHED" not in result: + raise RuntimeError(f"ANIM_OT_previewrange_set returned {result}") + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00201.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + mesh = bpy.data.meshes.new("WebGapAnimPreviewRangeSetMesh") + mesh.from_pydata( + [(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)], + [], + [(0, 1, 2, 3)], + ) + obj = bpy.data.objects.new("WebGapAnimPreviewRangeSetObject", mesh) + bpy.context.scene.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + scene = bpy.context.scene + scene.frame_start = 1 + scene.frame_end = 8 + set_preview_range() + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00202.py b/tools/web/generated/M16-GAP-00202.py new file mode 100644 index 00000000..a3cfc2d0 --- /dev/null +++ b/tools/web/generated/M16-GAP-00202.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +OLD_ACTION = "WebGapAnimReplaceOldAction" +NEW_ACTION = "WebGapAnimReplaceNewAction" + + +def make_object(name, action, property_name, values): + mesh = bpy.data.meshes.new(f"{name}Mesh") + mesh.from_pydata( + [(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)], + [], + [(0, 1, 2, 3)], + ) + obj = bpy.data.objects.new(name, mesh) + bpy.context.scene.collection.objects.link(obj) + obj.animation_data_create() + obj.animation_data.action = action + for frame, value in zip((1, 3, 5), values): + obj[property_name] = value + obj.keyframe_insert(data_path=f'["{property_name}"]', frame=frame) + return obj + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00202.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + old_action = bpy.data.actions.new(OLD_ACTION) + new_action = bpy.data.actions.new(NEW_ACTION) + old_a = make_object("WebGapAnimReplaceOldA", old_action, "replace_target", (1.0, 3.0, 5.0)) + old_b = make_object("WebGapAnimReplaceOldB", old_action, "replace_target", (2.0, 4.0, 6.0)) + new_user = make_object("WebGapAnimReplaceNewUser", new_action, "replace_target", (10.0, 30.0, 50.0)) + old_action.use_fake_user = True + new_action.use_fake_user = True + bpy.context.view_layer.objects.active = old_a + old_a.select_set(True) + old_b.select_set(False) + new_user.select_set(False) + bpy.context.scene.frame_start = 1 + bpy.context.scene.frame_end = 5 + bpy.context.scene.frame_set(3) + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00203.py b/tools/web/generated/M16-GAP-00203.py new file mode 100644 index 00000000..4020acde --- /dev/null +++ b/tools/web/generated/M16-GAP-00203.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +OLD_ACTION = "WebGapAnimReplaceNewOldAction" + + +def make_object(name, action, values): + mesh = bpy.data.meshes.new(f"{name}Mesh") + mesh.from_pydata( + [(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)], + [], + [(0, 1, 2, 3)], + ) + obj = bpy.data.objects.new(name, mesh) + bpy.context.scene.collection.objects.link(obj) + obj.animation_data_create() + obj.animation_data.action = action + for frame, value in zip((1, 3, 5), values): + obj["replace_target"] = value + obj.keyframe_insert(data_path='["replace_target"]', frame=frame) + return obj + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00203.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + old_action = bpy.data.actions.new(OLD_ACTION) + old_a = make_object("WebGapAnimReplaceNewOldA", old_action, (1.0, 3.0, 5.0)) + old_b = make_object("WebGapAnimReplaceNewOldB", old_action, (2.0, 4.0, 6.0)) + old_action.use_fake_user = True + bpy.context.view_layer.objects.active = old_a + old_a.select_set(True) + old_b.select_set(False) + bpy.context.scene.frame_start = 1 + bpy.context.scene.frame_end = 5 + bpy.context.scene.frame_set(3) + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00204.py b/tools/web/generated/M16-GAP-00204.py new file mode 100644 index 00000000..118d47e7 --- /dev/null +++ b/tools/web/generated/M16-GAP-00204.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +def frame_scene_range(): + window = bpy.context.window + screen = window.screen + area = next((candidate for candidate in screen.areas if candidate.type == "DOPESHEET_EDITOR" and candidate.height >= 200), None) + if area is None: + area = next(candidate for candidate in screen.areas if candidate.type == "VIEW_3D" and candidate.height >= 200) + area.type = "DOPESHEET_EDITOR" + region = next(candidate for candidate in area.regions if candidate.type == "WINDOW") + with bpy.context.temp_override(window=window, screen=screen, area=area, region=region): + if not bpy.ops.anim.scene_range_frame.poll(): + raise RuntimeError("ANIM_OT_scene_range_frame poll failed in animation editor context") + result = bpy.ops.anim.scene_range_frame() + if "FINISHED" not in result: + raise RuntimeError(f"ANIM_OT_scene_range_frame returned {result}") + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00204.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + scene = bpy.context.scene + scene.frame_start = 1 + scene.frame_end = 48 + scene.use_preview_range = True + scene.frame_preview_start = 12 + scene.frame_preview_end = 24 + bpy.context.preferences.view.smooth_view = 0 + frame_scene_range() + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00205.py b/tools/web/generated/M16-GAP-00205.py new file mode 100644 index 00000000..2ec6c8db --- /dev/null +++ b/tools/web/generated/M16-GAP-00205.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +OLD_ACTION = "WebGapAnimSeparateSlotsAction" + + +def make_object(name, action, slot, values): + mesh = bpy.data.meshes.new(f"{name}Mesh") + mesh.from_pydata( + [(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)], + [], + [(0, 1, 2, 3)], + ) + obj = bpy.data.objects.new(name, mesh) + bpy.context.scene.collection.objects.link(obj) + obj.animation_data_create() + obj.animation_data.action = action + obj.animation_data.action_slot = slot + for frame, value in zip((1, 3, 5), values): + obj["separate_target"] = value + obj.keyframe_insert(data_path='["separate_target"]', frame=frame) + return obj + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00205.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + action = bpy.data.actions.new(OLD_ACTION) + slot_a = action.slots.new("OBJECT", "WebGapSeparateSlotA") + slot_b = action.slots.new("OBJECT", "WebGapSeparateSlotB") + object_a = make_object("WebGapAnimSeparateSlotA", action, slot_a, (1.0, 3.0, 5.0)) + object_b = make_object("WebGapAnimSeparateSlotB", action, slot_b, (2.0, 4.0, 6.0)) + action.use_fake_user = True + bpy.context.view_layer.objects.active = object_a + object_a.select_set(True) + object_b.select_set(False) + bpy.context.scene.frame_start = 1 + bpy.context.scene.frame_end = 5 + bpy.context.scene.frame_set(3) + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00206.py b/tools/web/generated/M16-GAP-00206.py new file mode 100644 index 00000000..73638af6 --- /dev/null +++ b/tools/web/generated/M16-GAP-00206.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +OLD_ACTION = "WebGapAnimMoveSlotAction" + + +def make_object(name, action, slot, values): + mesh = bpy.data.meshes.new(f"{name}Mesh") + mesh.from_pydata( + [(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)], + [], + [(0, 1, 2, 3)], + ) + obj = bpy.data.objects.new(name, mesh) + bpy.context.scene.collection.objects.link(obj) + obj.animation_data_create() + obj.animation_data.action = action + obj.animation_data.action_slot = slot + for frame, value in zip((1, 3, 5), values): + obj["move_target"] = value + obj.keyframe_insert(data_path='["move_target"]', frame=frame) + return obj + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00206.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + action = bpy.data.actions.new(OLD_ACTION) + slot_a = action.slots.new("OBJECT", "WebGapMoveSlotA") + slot_b = action.slots.new("OBJECT", "WebGapMoveSlotB") + object_a = make_object("WebGapAnimMoveSlotA", action, slot_a, (1.0, 3.0, 5.0)) + object_b = make_object("WebGapAnimMoveSlotB", action, slot_b, (2.0, 4.0, 6.0)) + slot_a.select = True + slot_b.select = False + action.use_fake_user = True + bpy.context.view_layer.objects.active = object_a + object_a.select_set(True) + object_b.select_set(False) + window = bpy.context.window + screen = window.screen + area = next((candidate for candidate in screen.areas if candidate.type == "DOPESHEET_EDITOR" and candidate.height >= 200), None) + if area is None: + area = next(candidate for candidate in screen.areas if candidate.type == "VIEW_3D" and candidate.height >= 200) + area.type = "DOPESHEET_EDITOR" + area.spaces.active.ui_mode = "ACTION" + bpy.context.scene.frame_start = 1 + bpy.context.scene.frame_end = 5 + bpy.context.scene.frame_set(3) + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00207.py b/tools/web/generated/M16-GAP-00207.py new file mode 100644 index 00000000..bd5067e3 --- /dev/null +++ b/tools/web/generated/M16-GAP-00207.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ACTION_NAME = "WebGapAnimNewSlotAction" +OBJECT_NAME = "WebGapAnimNewSlotObject" +SLOT_NAME = "WebGapAnimNewSlot" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00207.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + mesh = bpy.data.meshes.new(f"{OBJECT_NAME}Mesh") + mesh.from_pydata( + [(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)], + [], + [(0, 1, 2, 3)], + ) + obj = bpy.data.objects.new(OBJECT_NAME, mesh) + bpy.context.scene.collection.objects.link(obj) + action = bpy.data.actions.new(ACTION_NAME) + slot = action.slots.new("OBJECT", SLOT_NAME) + obj.animation_data_create() + obj.animation_data.action = action + obj.animation_data.action_slot = slot + for frame, value in zip((1, 3, 5), (1.0, 3.0, 5.0)): + obj["new_slot_target"] = value + obj.keyframe_insert(data_path='["new_slot_target"]', frame=frame) + action.use_fake_user = True + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.context.scene.frame_start = 1 + bpy.context.scene.frame_end = 5 + bpy.context.scene.frame_set(3) + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00208.py b/tools/web/generated/M16-GAP-00208.py new file mode 100644 index 00000000..e390857f --- /dev/null +++ b/tools/web/generated/M16-GAP-00208.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ACTION_NAME = "WebGapAnimConstraintSlotAction" +OBJECT_NAME = "WebGapAnimConstraintSlotObject" +CONSTRAINT_NAME = "WebGapActionSlotConstraint" +SLOT_NAME = "WebGapConstraintSlot" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00208.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + mesh = bpy.data.meshes.new(f"{OBJECT_NAME}Mesh") + mesh.from_pydata( + [(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)], + [], + [(0, 1, 2, 3)], + ) + obj = bpy.data.objects.new(OBJECT_NAME, mesh) + bpy.context.scene.collection.objects.link(obj) + action = bpy.data.actions.new(ACTION_NAME) + slot = action.slots.new("OBJECT", SLOT_NAME) + action.use_fake_user = True + constraint = obj.constraints.new(type="ACTION") + constraint.name = CONSTRAINT_NAME + constraint.target = obj + constraint.action = action + constraint.action_slot = slot + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.context.scene.frame_start = 1 + bpy.context.scene.frame_end = 5 + bpy.context.scene.frame_set(3) + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00209.py b/tools/web/generated/M16-GAP-00209.py new file mode 100644 index 00000000..25f8dff6 --- /dev/null +++ b/tools/web/generated/M16-GAP-00209.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ACTION_NAME = "WebGapAnimUnassignIdAction" +OBJECT_NAME = "WebGapAnimUnassignIdObject" +SLOT_NAME = "WebGapUnassignIdSlot" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00209.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + mesh = bpy.data.meshes.new(f"{OBJECT_NAME}Mesh") + mesh.from_pydata( + [(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)], + [], + [(0, 1, 2, 3)], + ) + obj = bpy.data.objects.new(OBJECT_NAME, mesh) + bpy.context.scene.collection.objects.link(obj) + action = bpy.data.actions.new(ACTION_NAME) + slot = action.slots.new("OBJECT", SLOT_NAME) + obj.animation_data_create() + obj.animation_data.action = action + obj.animation_data.action_slot = slot + for frame, value in zip((1, 3, 5), (1.0, 3.0, 5.0)): + obj["unassign_id_target"] = value + obj.keyframe_insert(data_path='["unassign_id_target"]', frame=frame) + action.use_fake_user = True + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.context.scene.frame_start = 1 + bpy.context.scene.frame_end = 5 + bpy.context.scene.frame_set(3) + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00210.py b/tools/web/generated/M16-GAP-00210.py new file mode 100644 index 00000000..cadb3f27 --- /dev/null +++ b/tools/web/generated/M16-GAP-00210.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ACTION_NAME = "WebGapAnimNlaSlotAction" +OBJECT_NAME = "WebGapAnimNlaSlotObject" +STRIP_NAME = "WebGapNlaSlotStrip" +SLOT_NAME = "WebGapNlaSlot" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00210.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + mesh = bpy.data.meshes.new(f"{OBJECT_NAME}Mesh") + mesh.from_pydata( + [(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)], + [], + [(0, 1, 2, 3)], + ) + obj = bpy.data.objects.new(OBJECT_NAME, mesh) + bpy.context.scene.collection.objects.link(obj) + action = bpy.data.actions.new(ACTION_NAME) + slot = action.slots.new("OBJECT", SLOT_NAME) + obj.animation_data_create() + obj.animation_data.action = action + obj.animation_data.action_slot = slot + for frame, value in zip((1, 3, 5), (1.0, 3.0, 5.0)): + obj["nla_slot_target"] = value + obj.keyframe_insert(data_path='["nla_slot_target"]', frame=frame) + track = obj.animation_data.nla_tracks.new() + track.name = "WebGapNlaSlotTrack" + strip = track.strips.new(STRIP_NAME, 1, action) + strip.action_slot = slot + strip.frame_end = 5 + action.use_fake_user = True + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.context.scene.frame_start = 1 + bpy.context.scene.frame_end = 5 + bpy.context.scene.frame_set(3) + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00211.py b/tools/web/generated/M16-GAP-00211.py new file mode 100644 index 00000000..5ebca06b --- /dev/null +++ b/tools/web/generated/M16-GAP-00211.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00211.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + scene = bpy.context.scene + scene.frame_start = 1 + scene.frame_end = 120 + scene.frame_set(42) + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00212.py b/tools/web/generated/M16-GAP-00212.py new file mode 100644 index 00000000..db051888 --- /dev/null +++ b/tools/web/generated/M16-GAP-00212.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +OBJECT_NAME = "WebGapAnimatedTransformConstraintObject" +ACTION_NAME = "WebGapAnimatedTransformConstraintAction" +CONSTRAINT_NAME = "WebGapAnimatedTransformConstraint" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00212.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + mesh = bpy.data.meshes.new(f"{OBJECT_NAME}Mesh") + mesh.from_pydata( + [(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)], + [], + [(0, 1, 2, 3)], + ) + obj = bpy.data.objects.new(OBJECT_NAME, mesh) + bpy.context.scene.collection.objects.link(obj) + constraint = obj.constraints.new("TRANSFORM") + constraint.name = CONSTRAINT_NAME + constraint.map_from = "ROTATION" + constraint.from_min_x = -30.0 + obj.animation_data_create() + action = bpy.data.actions.new(ACTION_NAME) + obj.animation_data.action = action + constraint.keyframe_insert(data_path="from_min_x", frame=1) + constraint.from_min_x = 60.0 + constraint.keyframe_insert(data_path="from_min_x", frame=10) + action.use_fake_user = True + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + scene = bpy.context.scene + scene.frame_start = 1 + scene.frame_end = 10 + scene.frame_set(5) + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00213.py b/tools/web/generated/M16-GAP-00213.py new file mode 100644 index 00000000..f2bc87a3 --- /dev/null +++ b/tools/web/generated/M16-GAP-00213.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapVersionBoneHideArmature" +OBJECT_NAME = "WebGapVersionBoneHideObject" +BONE_NAME = "WebGapVersionBoneHideBone" +ARMATURE_ACTION_NAME = "WebGapVersionBoneHideArmatureAction" +OBJECT_ACTION_NAME = "WebGapVersionBoneHideObjectAction" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00213.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + bone = armature.edit_bones.new(BONE_NAME) + bone.head = (0.0, 0.0, 0.0) + bone.tail = (0.0, 1.0, 0.0) + bpy.ops.object.mode_set(mode="OBJECT") + + armature.animation_data_create() + armature_action = bpy.data.actions.new(ARMATURE_ACTION_NAME) + armature_slot = armature_action.slots.new("ARMATURE", ARMATURE_NAME) + armature.animation_data.action = armature_action + armature.animation_data.action_slot = armature_slot + armature.bones[BONE_NAME].hide = False + armature.bones[BONE_NAME].keyframe_insert(data_path="hide", frame=1) + armature.bones[BONE_NAME].hide = True + armature.bones[BONE_NAME].keyframe_insert(data_path="hide", frame=10) + armature_action.use_fake_user = True + + obj.animation_data_create() + object_action = bpy.data.actions.new(OBJECT_ACTION_NAME) + object_slot = object_action.slots.new("OBJECT", OBJECT_NAME) + obj.animation_data.action = object_action + obj.animation_data.action_slot = object_slot + obj["version_anchor"] = 0.0 + obj.keyframe_insert(data_path='["version_anchor"]', frame=1) + obj["version_anchor"] = 1.0 + obj.keyframe_insert(data_path='["version_anchor"]', frame=10) + object_action.use_fake_user = True + + scene = bpy.context.scene + scene.frame_start = 1 + scene.frame_end = 10 + scene.frame_set(5) + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00214.py b/tools/web/generated/M16-GAP-00214.py new file mode 100644 index 00000000..1938cb52 --- /dev/null +++ b/tools/web/generated/M16-GAP-00214.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +OBJECT_NAME = "WebGapAnimViewCurveGraphEditorObject" +ACTION_NAME = "WebGapAnimViewCurveGraphEditorAction" +PROPERTY_NAME = "curve_target" + + +def configure_graph_editor(): + window = bpy.context.window + if window is None or window.screen is None: + raise RuntimeError("fixture requires a Blender window") + screen = window.screen + area = next((candidate for candidate in screen.areas if candidate.type in {"DOPESHEET_EDITOR", "VIEW_3D"}), None) + if area is None: + raise RuntimeError("default Layout VIEW_3D area is missing") + area.type = "GRAPH_EDITOR" + return area + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00214.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + mesh = bpy.data.meshes.new(f"{OBJECT_NAME}Mesh") + mesh.from_pydata( + [(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)], + [], + [(0, 1, 2, 3)], + ) + obj = bpy.data.objects.new(OBJECT_NAME, mesh) + bpy.context.scene.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + obj[PROPERTY_NAME] = -3.0 + obj.keyframe_insert(data_path=f'["{PROPERTY_NAME}"]', frame=1) + obj[PROPERTY_NAME] = 7.0 + obj.keyframe_insert(data_path=f'["{PROPERTY_NAME}"]', frame=10) + obj.animation_data.action.name = ACTION_NAME + obj.animation_data.action.use_fake_user = True + curve = next(curve for curve in obj.animation_data.action.layers[0].strips[0].channelbags[0].fcurves) + for keyframe in curve.keyframe_points: + keyframe.select_control_point = False + curve.keyframe_points[0].select_control_point = True + curve.keyframe_points[1].select_control_point = False + bpy.context.scene.frame_start = 1 + bpy.context.scene.frame_end = 10 + bpy.context.scene.frame_set(5) + bpy.context.preferences.view.smooth_view = 0 + graph_area = configure_graph_editor() + graph_region = next(candidate for candidate in graph_area.regions if candidate.type == "WINDOW") + with bpy.context.temp_override(window=bpy.context.window, screen=bpy.context.screen, area=graph_area, region=graph_region): + if "FINISHED" not in bpy.ops.graph.view_selected(): + raise RuntimeError("Graph Editor view_selected failed while preparing fixture") + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00215.py b/tools/web/generated/M16-GAP-00215.py new file mode 100644 index 00000000..80ef2bda --- /dev/null +++ b/tools/web/generated/M16-GAP-00215.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureAlignArmature" +OBJECT_NAME = "WebGapArmatureAlignObject" +PARENT_NAME = "WebGapArmatureAlignParent" +CHILD_NAME = "WebGapArmatureAlignChild" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00215.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + parent = armature.edit_bones.new(PARENT_NAME) + parent.head = (0.0, 0.0, 0.0) + parent.tail = (0.0, 0.0, 3.0) + child = armature.edit_bones.new(CHILD_NAME) + child.head = (0.0, 0.0, 3.0) + child.tail = (2.0, 1.0, 4.0) + parent.select = True + child.select = True + bpy.ops.object.mode_set(mode="OBJECT") + armature.bones.active = armature.bones[PARENT_NAME] + bpy.context.scene.frame_set(1) + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00216.py b/tools/web/generated/M16-GAP-00216.py new file mode 100644 index 00000000..f122cb5c --- /dev/null +++ b/tools/web/generated/M16-GAP-00216.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureAssignArmature" +OBJECT_NAME = "WebGapArmatureAssignObject" +SOURCE_COLLECTION = "WebGapArmatureAssignSource" +TARGET_COLLECTION = "WebGapArmatureAssignTarget" +PARENT_NAME = "WebGapArmatureAssignParent" +CHILD_NAME = "WebGapArmatureAssignChild" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00216.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + source = armature.collections.new(SOURCE_COLLECTION) + armature.collections.new(TARGET_COLLECTION) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + parent = armature.edit_bones.new(PARENT_NAME) + parent.head = (0.0, 0.0, 0.0) + parent.tail = (0.0, 0.0, 2.0) + child = armature.edit_bones.new(CHILD_NAME) + child.head = (0.0, 0.0, 2.0) + child.tail = (0.0, 1.0, 3.0) + child.parent = parent + child.use_connect = False + bpy.ops.object.mode_set(mode="OBJECT") + source.assign(armature.bones[CHILD_NAME]) + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00217.py b/tools/web/generated/M16-GAP-00217.py new file mode 100644 index 00000000..92abf104 --- /dev/null +++ b/tools/web/generated/M16-GAP-00217.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureAutosideArmature" +OBJECT_NAME = "WebGapArmatureAutosideObject" +LEFT_NAME = "WebGapArmatureAutosideLeft" +RIGHT_NAME = "WebGapArmatureAutosideRight" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00217.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + left = armature.edit_bones.new(LEFT_NAME) + left.head = (1.0, 0.0, 0.0) + left.tail = (1.0, 0.0, 2.0) + right = armature.edit_bones.new(RIGHT_NAME) + right.head = (-1.0, 0.0, 0.0) + right.tail = (-1.0, 0.0, 2.0) + left.select = True + right.select = True + bpy.ops.object.mode_set(mode="OBJECT") + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00218.py b/tools/web/generated/M16-GAP-00218.py new file mode 100644 index 00000000..3862eeb7 --- /dev/null +++ b/tools/web/generated/M16-GAP-00218.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmaturePrimitiveArmature" +OBJECT_NAME = "WebGapArmaturePrimitiveObject" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00218.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.context.scene.cursor.location = (1.5, -2.0, 0.75) + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00219.py b/tools/web/generated/M16-GAP-00219.py new file mode 100644 index 00000000..647803d8 --- /dev/null +++ b/tools/web/generated/M16-GAP-00219.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureCalculateRollArmature" +OBJECT_NAME = "WebGapArmatureCalculateRollObject" +BONE_NAME = "WebGapArmatureCalculateRollBone" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00219.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + bone = armature.edit_bones.new(BONE_NAME) + bone.head = (0.0, 0.0, 0.0) + bone.tail = (0.0, 2.0, 0.0) + bone.roll = 0.0 + bone.select = True + bpy.ops.object.mode_set(mode="OBJECT") + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00220.py b/tools/web/generated/M16-GAP-00220.py new file mode 100644 index 00000000..8cd3e9e5 --- /dev/null +++ b/tools/web/generated/M16-GAP-00220.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureClickExtrudeArmature" +OBJECT_NAME = "WebGapArmatureClickExtrudeObject" +BONE_NAME = "WebGapArmatureClickExtrudeBone" +CURSOR = (1.5, 2.0, 1.0) + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00220.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + bone = armature.edit_bones.new(BONE_NAME) + bone.head = (0.0, 0.0, 0.0) + bone.tail = (0.0, 2.0, 0.0) + bone.roll = 0.0 + bone.select = True + bone.select_tail = True + armature.edit_bones.active = bone + bpy.ops.object.mode_set(mode="OBJECT") + bpy.context.scene.cursor.location = CURSOR + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00221.py b/tools/web/generated/M16-GAP-00221.py new file mode 100644 index 00000000..29b29bd2 --- /dev/null +++ b/tools/web/generated/M16-GAP-00221.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureCollectionAddArmature" +OBJECT_NAME = "WebGapArmatureCollectionAddObject" +SOURCE_COLLECTION = "WebGapArmatureCollectionAddExisting" +BONE_NAME = "WebGapArmatureCollectionAddBone" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00221.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + existing = armature.collections.new(SOURCE_COLLECTION) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + bone = armature.edit_bones.new(BONE_NAME) + bone.head = (0.0, 0.0, 0.0) + bone.tail = (0.0, 1.0, 0.0) + bone.select = True + bpy.ops.object.mode_set(mode="OBJECT") + existing.assign(armature.bones[BONE_NAME]) + armature.collections.active_index = 0 + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00222.py b/tools/web/generated/M16-GAP-00222.py new file mode 100644 index 00000000..4113ce15 --- /dev/null +++ b/tools/web/generated/M16-GAP-00222.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureCollectionAssignArmature" +OBJECT_NAME = "WebGapArmatureCollectionAssignObject" +SOURCE_COLLECTION = "WebGapArmatureCollectionAssignSource" +TARGET_COLLECTION = "WebGapArmatureCollectionAssignTarget" +BONE_NAME = "WebGapArmatureCollectionAssignBone" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00222.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + source = armature.collections.new(SOURCE_COLLECTION) + armature.collections.new(TARGET_COLLECTION) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + bone = armature.edit_bones.new(BONE_NAME) + bone.head = (0.0, 0.0, 0.0) + bone.tail = (0.0, 1.0, 0.0) + bone.select = True + bpy.ops.object.mode_set(mode="OBJECT") + source.assign(armature.bones[BONE_NAME]) + armature.collections.active_index = 0 + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00223.py b/tools/web/generated/M16-GAP-00223.py new file mode 100644 index 00000000..fa55e637 --- /dev/null +++ b/tools/web/generated/M16-GAP-00223.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureCollectionCreateAssignArmature" +OBJECT_NAME = "WebGapArmatureCollectionCreateAssignObject" +SOURCE_COLLECTION = "WebGapArmatureCollectionCreateAssignSource" +BONE_NAME = "WebGapArmatureCollectionCreateAssignBone" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00223.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + source = armature.collections.new(SOURCE_COLLECTION) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + bone = armature.edit_bones.new(BONE_NAME) + bone.head = (0.0, 0.0, 0.0) + bone.tail = (0.0, 1.0, 0.0) + bone.select = True + bpy.ops.object.mode_set(mode="OBJECT") + source.assign(armature.bones[BONE_NAME]) + armature.collections.active_index = 0 + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00224.py b/tools/web/generated/M16-GAP-00224.py new file mode 100644 index 00000000..0f5cab98 --- /dev/null +++ b/tools/web/generated/M16-GAP-00224.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureCollectionDeselectArmature" +OBJECT_NAME = "WebGapArmatureCollectionDeselectObject" +ACTIVE_COLLECTION = "WebGapArmatureCollectionDeselectActive" +OTHER_COLLECTION = "WebGapArmatureCollectionDeselectOther" +ACTIVE_BONE = "WebGapArmatureCollectionDeselectActiveBone" +OTHER_BONE = "WebGapArmatureCollectionDeselectOtherBone" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00224.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + active = armature.collections.new(ACTIVE_COLLECTION) + armature.collections.new(OTHER_COLLECTION) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + active_bone = armature.edit_bones.new(ACTIVE_BONE) + active_bone.head = (0.0, 0.0, 0.0) + active_bone.tail = (0.0, 1.0, 0.0) + other_bone = armature.edit_bones.new(OTHER_BONE) + other_bone.head = (1.0, 0.0, 0.0) + other_bone.tail = (1.0, 1.0, 0.0) + active_bone.select = True + active_bone.select_head = True + active_bone.select_tail = True + other_bone.select = True + other_bone.select_head = True + other_bone.select_tail = True + bpy.ops.object.mode_set(mode="OBJECT") + active.assign(armature.bones[ACTIVE_BONE]) + armature.collections[OTHER_COLLECTION].assign(armature.bones[OTHER_BONE]) + armature.collections.active_index = 0 + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00225.py b/tools/web/generated/M16-GAP-00225.py new file mode 100644 index 00000000..549a7b04 --- /dev/null +++ b/tools/web/generated/M16-GAP-00225.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureCollectionMoveArmature" +OBJECT_NAME = "WebGapArmatureCollectionMoveObject" +FIRST_COLLECTION = "WebGapArmatureCollectionMoveFirst" +ACTIVE_COLLECTION = "WebGapArmatureCollectionMoveActive" +LAST_COLLECTION = "WebGapArmatureCollectionMoveLast" +FIRST_BONE = "WebGapArmatureCollectionMoveFirstBone" +ACTIVE_BONE = "WebGapArmatureCollectionMoveActiveBone" +LAST_BONE = "WebGapArmatureCollectionMoveLastBone" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00225.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + first = armature.collections.new(FIRST_COLLECTION) + active = armature.collections.new(ACTIVE_COLLECTION) + last = armature.collections.new(LAST_COLLECTION) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + for name, x in ((FIRST_BONE, 0.0), (ACTIVE_BONE, 1.0), (LAST_BONE, 2.0)): + bone = armature.edit_bones.new(name) + bone.head = (x, 0.0, 0.0) + bone.tail = (x, 1.0, 0.0) + bpy.ops.object.mode_set(mode="OBJECT") + first.assign(armature.bones[FIRST_BONE]) + active.assign(armature.bones[ACTIVE_BONE]) + last.assign(armature.bones[LAST_BONE]) + armature.collections.active_index = 1 + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00226.py b/tools/web/generated/M16-GAP-00226.py new file mode 100644 index 00000000..0fd9b0c3 --- /dev/null +++ b/tools/web/generated/M16-GAP-00226.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureCollectionRemoveArmature" +OBJECT_NAME = "WebGapArmatureCollectionRemoveObject" +FIRST_COLLECTION = "WebGapArmatureCollectionRemoveFirst" +REMOVED_COLLECTION = "WebGapArmatureCollectionRemoveRemoved" +LAST_COLLECTION = "WebGapArmatureCollectionRemoveLast" +FIRST_BONE = "WebGapArmatureCollectionRemoveFirstBone" +REMOVED_BONE = "WebGapArmatureCollectionRemoveRemovedBone" +LAST_BONE = "WebGapArmatureCollectionRemoveLastBone" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00226.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + first = armature.collections.new(FIRST_COLLECTION) + removed = armature.collections.new(REMOVED_COLLECTION) + last = armature.collections.new(LAST_COLLECTION) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + for name, x in ((FIRST_BONE, 0.0), (REMOVED_BONE, 1.0), (LAST_BONE, 2.0)): + bone = armature.edit_bones.new(name) + bone.head = (x, 0.0, 0.0) + bone.tail = (x, 1.0, 0.0) + bpy.ops.object.mode_set(mode="OBJECT") + first.assign(armature.bones[FIRST_BONE]) + removed.assign(armature.bones[REMOVED_BONE]) + last.assign(armature.bones[LAST_BONE]) + armature.collections.active_index = 1 + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00227.py b/tools/web/generated/M16-GAP-00227.py new file mode 100644 index 00000000..81e7eb68 --- /dev/null +++ b/tools/web/generated/M16-GAP-00227.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureCollectionRemoveUnusedArmature" +OBJECT_NAME = "WebGapArmatureCollectionRemoveUnusedObject" +FIRST_COLLECTION = "WebGapArmatureCollectionRemoveUnusedFirst" +UNUSED_FIRST_COLLECTION = "WebGapArmatureCollectionRemoveUnusedUnusedFirst" +LAST_COLLECTION = "WebGapArmatureCollectionRemoveUnusedLast" +UNUSED_LAST_COLLECTION = "WebGapArmatureCollectionRemoveUnusedUnusedLast" +FIRST_BONE = "WebGapArmatureCollectionRemoveUnusedFirstBone" +LAST_BONE = "WebGapArmatureCollectionRemoveUnusedLastBone" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00227.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + first = armature.collections.new(FIRST_COLLECTION) + armature.collections.new(UNUSED_FIRST_COLLECTION) + last = armature.collections.new(LAST_COLLECTION) + armature.collections.new(UNUSED_LAST_COLLECTION) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + for name, x in ((FIRST_BONE, 0.0), (LAST_BONE, 2.0)): + bone = armature.edit_bones.new(name) + bone.head = (x, 0.0, 0.0) + bone.tail = (x, 1.0, 0.0) + bpy.ops.object.mode_set(mode="OBJECT") + first.assign(armature.bones[FIRST_BONE]) + last.assign(armature.bones[LAST_BONE]) + armature.collections.active_index = 2 + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00228.py b/tools/web/generated/M16-GAP-00228.py new file mode 100644 index 00000000..70118403 --- /dev/null +++ b/tools/web/generated/M16-GAP-00228.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureCollectionSelectArmature" +OBJECT_NAME = "WebGapArmatureCollectionSelectObject" +FIRST_COLLECTION = "WebGapArmatureCollectionSelectFirst" +ACTIVE_COLLECTION = "WebGapArmatureCollectionSelectActive" +LAST_COLLECTION = "WebGapArmatureCollectionSelectLast" +FIRST_BONE = "WebGapArmatureCollectionSelectFirstBone" +ACTIVE_BONE = "WebGapArmatureCollectionSelectActiveBone" +LAST_BONE = "WebGapArmatureCollectionSelectLastBone" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00228.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + first = armature.collections.new(FIRST_COLLECTION) + active = armature.collections.new(ACTIVE_COLLECTION) + last = armature.collections.new(LAST_COLLECTION) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + edit_bones = {} + for name, x in ((FIRST_BONE, 0.0), (ACTIVE_BONE, 1.0), (LAST_BONE, 2.0)): + bone = armature.edit_bones.new(name) + bone.head = (x, 0.0, 0.0) + bone.tail = (x, 1.0, 0.0) + edit_bones[name] = bone + edit_bones[FIRST_BONE].select = True + edit_bones[ACTIVE_BONE].select = False + edit_bones[LAST_BONE].select = False + bpy.ops.object.mode_set(mode="OBJECT") + first.assign(armature.bones[FIRST_BONE]) + active.assign(armature.bones[ACTIVE_BONE]) + last.assign(armature.bones[LAST_BONE]) + armature.collections.active_index = 1 + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00229.py b/tools/web/generated/M16-GAP-00229.py new file mode 100644 index 00000000..4c5966d2 --- /dev/null +++ b/tools/web/generated/M16-GAP-00229.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureCollectionShowAllArmature" +OBJECT_NAME = "WebGapArmatureCollectionShowAllObject" +FIRST_COLLECTION = "WebGapArmatureCollectionShowAllFirst" +HIDDEN_COLLECTION = "WebGapArmatureCollectionShowAllHidden" +LAST_COLLECTION = "WebGapArmatureCollectionShowAllLast" +FIRST_BONE = "WebGapArmatureCollectionShowAllFirstBone" +HIDDEN_BONE = "WebGapArmatureCollectionShowAllHiddenBone" +LAST_BONE = "WebGapArmatureCollectionShowAllLastBone" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00229.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + first = armature.collections.new(FIRST_COLLECTION) + hidden = armature.collections.new(HIDDEN_COLLECTION) + last = armature.collections.new(LAST_COLLECTION) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + edit_bones = {} + for name, x in ((FIRST_BONE, 0.0), (HIDDEN_BONE, 1.0), (LAST_BONE, 2.0)): + bone = armature.edit_bones.new(name) + bone.head = (x, 0.0, 0.0) + bone.tail = (x, 1.0, 0.0) + edit_bones[name] = bone + bpy.ops.object.mode_set(mode="OBJECT") + first.assign(armature.bones[FIRST_BONE]) + hidden.assign(armature.bones[HIDDEN_BONE]) + last.assign(armature.bones[LAST_BONE]) + hidden.is_visible = False + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00230.py b/tools/web/generated/M16-GAP-00230.py new file mode 100644 index 00000000..f12b8daa --- /dev/null +++ b/tools/web/generated/M16-GAP-00230.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureCollectionUnassignArmature" +OBJECT_NAME = "WebGapArmatureCollectionUnassignObject" +SOURCE_COLLECTION = "WebGapArmatureCollectionUnassignSource" +RETAINED_COLLECTION = "WebGapArmatureCollectionUnassignRetained" +BONE_NAME = "WebGapArmatureCollectionUnassignBone" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00230.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + source = armature.collections.new(SOURCE_COLLECTION) + retained = armature.collections.new(RETAINED_COLLECTION) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + bone = armature.edit_bones.new(BONE_NAME) + bone.head = (0.0, 0.0, 0.0) + bone.tail = (0.0, 1.0, 0.0) + bone.select = True + bpy.ops.object.mode_set(mode="OBJECT") + source.assign(armature.bones[BONE_NAME]) + retained.assign(armature.bones[BONE_NAME]) + armature.collections.active_index = 0 + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00231.py b/tools/web/generated/M16-GAP-00231.py new file mode 100644 index 00000000..c35ff77e --- /dev/null +++ b/tools/web/generated/M16-GAP-00231.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureCollectionUnassignNamedArmature" +OBJECT_NAME = "WebGapArmatureCollectionUnassignNamedObject" +SOURCE_COLLECTION = "WebGapArmatureCollectionUnassignNamedSource" +RETAINED_COLLECTION = "WebGapArmatureCollectionUnassignNamedRetained" +BONE_NAME = "WebGapArmatureCollectionUnassignNamedBone" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00231.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + source = armature.collections.new(SOURCE_COLLECTION) + retained = armature.collections.new(RETAINED_COLLECTION) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + bone = armature.edit_bones.new(BONE_NAME) + bone.head = (0.0, 0.0, 0.0) + bone.tail = (0.0, 1.0, 0.0) + bone.select = True + bpy.ops.object.mode_set(mode="OBJECT") + source.assign(armature.bones[BONE_NAME]) + retained.assign(armature.bones[BONE_NAME]) + armature.collections.active_index = 1 + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00232.py b/tools/web/generated/M16-GAP-00232.py new file mode 100644 index 00000000..47fdea74 --- /dev/null +++ b/tools/web/generated/M16-GAP-00232.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureCollectionUnsoloAllArmature" +OBJECT_NAME = "WebGapArmatureCollectionUnsoloAllObject" +FIRST_COLLECTION = "WebGapArmatureCollectionUnsoloAllFirst" +SOLO_COLLECTION = "WebGapArmatureCollectionUnsoloAllSolo" +LAST_COLLECTION = "WebGapArmatureCollectionUnsoloAllLast" +FIRST_BONE = "WebGapArmatureCollectionUnsoloAllFirstBone" +SOLO_BONE = "WebGapArmatureCollectionUnsoloAllSoloBone" +LAST_BONE = "WebGapArmatureCollectionUnsoloAllLastBone" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00232.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + first = armature.collections.new(FIRST_COLLECTION) + solo = armature.collections.new(SOLO_COLLECTION) + last = armature.collections.new(LAST_COLLECTION) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + edit_bones = {} + for name, x in ((FIRST_BONE, 0.0), (SOLO_BONE, 1.0), (LAST_BONE, 2.0)): + bone = armature.edit_bones.new(name) + bone.head = (x, 0.0, 0.0) + bone.tail = (x, 1.0, 0.0) + edit_bones[name] = bone + bpy.ops.object.mode_set(mode="OBJECT") + first.assign(armature.bones[FIRST_BONE]) + solo.assign(armature.bones[SOLO_BONE]) + last.assign(armature.bones[LAST_BONE]) + solo.is_solo = True + armature.collections.active_index = 1 + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00233.py b/tools/web/generated/M16-GAP-00233.py new file mode 100644 index 00000000..cf03dd7c --- /dev/null +++ b/tools/web/generated/M16-GAP-00233.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureCopyBoneColorArmature" +OBJECT_NAME = "WebGapArmatureCopyBoneColorObject" +SOURCE_BONE = "WebGapArmatureCopyBoneColorSource" +SELECTED_BONE = "WebGapArmatureCopyBoneColorSelected" +UNSELECTED_BONE = "WebGapArmatureCopyBoneColorUnselected" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00233.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + bones = {} + for name, x in ((SOURCE_BONE, 0.0), (SELECTED_BONE, 1.0), (UNSELECTED_BONE, 2.0)): + bone = armature.edit_bones.new(name) + bone.head = (x, 0.0, 0.0) + bone.tail = (x, 1.0, 0.0) + bones[name] = bone + source = bones[SOURCE_BONE] + source.color.palette = "CUSTOM" + source.color.custom.normal = (0.12, 0.24, 0.36) + source.color.custom.select = (0.42, 0.54, 0.66) + source.color.custom.active = (0.72, 0.84, 0.96) + bones[SELECTED_BONE].color.palette = "THEME04" + bones[UNSELECTED_BONE].color.palette = "THEME05" + for bone in bones.values(): + bone.select = True + bones[UNSELECTED_BONE].select = False + armature.edit_bones.active = source + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00234.py b/tools/web/generated/M16-GAP-00234.py new file mode 100644 index 00000000..31592040 --- /dev/null +++ b/tools/web/generated/M16-GAP-00234.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureDeleteArmature" +OBJECT_NAME = "WebGapArmatureDeleteObject" +KEEP_BONE = "WebGapArmatureDeleteKeep" +DELETE_BONE = "WebGapArmatureDeleteSelected" +RETAIN_BONE = "WebGapArmatureDeleteRetain" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00234.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + bones = {} + for name, x in ((KEEP_BONE, 0.0), (DELETE_BONE, 1.0), (RETAIN_BONE, 2.0)): + bone = armature.edit_bones.new(name) + bone.head = (x, 0.0, 0.0) + bone.tail = (x, 1.0, 0.0) + bones[name] = bone + for bone in bones.values(): + bone.select = False + bones[DELETE_BONE].select = True + armature.edit_bones.active = bones[DELETE_BONE] + bpy.ops.object.mode_set(mode="OBJECT") + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00235.py b/tools/web/generated/M16-GAP-00235.py new file mode 100644 index 00000000..b069bac1 --- /dev/null +++ b/tools/web/generated/M16-GAP-00235.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureDissolveArmature" +OBJECT_NAME = "WebGapArmatureDissolveObject" +ROOT_BONE = "WebGapArmatureDissolveRoot" +MIDDLE_BONE = "WebGapArmatureDissolveMiddle" +TIP_BONE = "WebGapArmatureDissolveTip" +OTHER_BONE = "WebGapArmatureDissolveOther" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00235.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + root = armature.edit_bones.new(ROOT_BONE) + root.head = (0.0, 0.0, 0.0) + root.tail = (0.0, 1.0, 0.0) + middle = armature.edit_bones.new(MIDDLE_BONE) + middle.head = (0.0, 1.0, 0.0) + middle.tail = (0.0, 2.0, 0.0) + middle.parent = root + middle.use_connect = True + tip = armature.edit_bones.new(TIP_BONE) + tip.head = (0.0, 2.0, 0.0) + tip.tail = (0.0, 3.0, 0.0) + tip.parent = middle + tip.use_connect = True + other = armature.edit_bones.new(OTHER_BONE) + other.head = (2.0, 0.0, 0.0) + other.tail = (2.0, 1.0, 0.0) + root.select = False + middle.select = True + tip.select = True + other.select = False + armature.edit_bones.active = middle + bpy.ops.object.mode_set(mode="OBJECT") + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00236.py b/tools/web/generated/M16-GAP-00236.py new file mode 100644 index 00000000..9c73f1fe --- /dev/null +++ b/tools/web/generated/M16-GAP-00236.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureDuplicateArmature" +OBJECT_NAME = "WebGapArmatureDuplicateObject" +SOURCE_BONE = "WebGapArmatureDuplicateSource" +OTHER_BONE = "WebGapArmatureDuplicateOther" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00236.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + source = armature.edit_bones.new(SOURCE_BONE) + source.head = (0.0, 0.0, 0.0) + source.tail = (0.0, 1.0, 0.0) + other = armature.edit_bones.new(OTHER_BONE) + other.head = (2.0, 0.0, 0.0) + other.tail = (2.0, 1.0, 0.0) + source.select = True + source.select_head = True + source.select_tail = True + other.select = False + other.select_head = False + other.select_tail = False + armature.edit_bones.active = source + bpy.ops.object.mode_set(mode="OBJECT") + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00237.py b/tools/web/generated/M16-GAP-00237.py new file mode 100644 index 00000000..a03eebad --- /dev/null +++ b/tools/web/generated/M16-GAP-00237.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureDuplicateMoveArmature" +OBJECT_NAME = "WebGapArmatureDuplicateMoveObject" +SOURCE_BONE = "WebGapArmatureDuplicateMoveSource" +OTHER_BONE = "WebGapArmatureDuplicateMoveOther" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00237.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + source = armature.edit_bones.new(SOURCE_BONE) + source.head = (0.0, 0.0, 0.0) + source.tail = (0.0, 1.0, 0.0) + other = armature.edit_bones.new(OTHER_BONE) + other.head = (2.0, 0.0, 0.0) + other.tail = (2.0, 1.0, 0.0) + source.select = True + source.select_head = True + source.select_tail = True + other.select = False + other.select_head = False + other.select_tail = False + armature.edit_bones.active = source + result = bpy.ops.armature.duplicate_move( + TRANSFORM_OT_translate={"value": (1.0, 2.0, 3.0)} + ) + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_duplicate_move returned {result}") + bpy.ops.object.mode_set(mode="OBJECT") + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00238.py b/tools/web/generated/M16-GAP-00238.py new file mode 100644 index 00000000..64efd5dc --- /dev/null +++ b/tools/web/generated/M16-GAP-00238.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureDuplicateRenameArmature" +OBJECT_NAME = "WebGapArmatureDuplicateRenameObject" +SOURCE_BONE = "WebGapArmatureDuplicateRenameSource" +OTHER_BONE = "WebGapArmatureDuplicateRenameOther" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00238.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + source = armature.edit_bones.new(SOURCE_BONE) + source.head = (0.0, 0.0, 0.0) + source.tail = (0.0, 1.0, 0.0) + other = armature.edit_bones.new(OTHER_BONE) + other.head = (2.0, 0.0, 0.0) + other.tail = (2.0, 1.0, 0.0) + source.select = True + source.select_head = True + source.select_tail = True + other.select = False + other.select_head = False + other.select_tail = False + armature.edit_bones.active = source + result = bpy.ops.armature.duplicate_rename(search="Source", replace="Copy", do_flip_names=False) + if result != {"FINISHED"}: + raise RuntimeError(f"ARMATURE_OT_duplicate_rename returned {result}") + bpy.ops.object.mode_set(mode="OBJECT") + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00239.py b/tools/web/generated/M16-GAP-00239.py new file mode 100644 index 00000000..2230b086 --- /dev/null +++ b/tools/web/generated/M16-GAP-00239.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureExtrudeArmature" +OBJECT_NAME = "WebGapArmatureExtrudeObject" +SOURCE_BONE = "WebGapArmatureExtrudeSource" +OTHER_BONE = "WebGapArmatureExtrudeOther" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00239.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + source = armature.edit_bones.new(SOURCE_BONE) + source.head = (0.0, 0.0, 0.0) + source.tail = (0.0, 1.0, 0.0) + other = armature.edit_bones.new(OTHER_BONE) + other.head = (2.0, 0.0, 0.0) + other.tail = (2.0, 1.0, 0.0) + source.select = True + source.select_head = False + source.select_tail = True + other.select = False + other.select_head = False + other.select_tail = False + armature.edit_bones.active = source + bpy.ops.object.mode_set(mode="OBJECT") + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00240.py b/tools/web/generated/M16-GAP-00240.py new file mode 100644 index 00000000..a2c8c283 --- /dev/null +++ b/tools/web/generated/M16-GAP-00240.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureExtrudeForkedArmature" +OBJECT_NAME = "WebGapArmatureExtrudeForkedObject" +SOURCE_BONE = "WebGapArmatureExtrudeForkedSource" +OTHER_BONE = "WebGapArmatureExtrudeForkedOther" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00240.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + source = armature.edit_bones.new(SOURCE_BONE) + source.head = (0.0, 0.0, 0.0) + source.tail = (0.0, 1.0, 0.0) + other = armature.edit_bones.new(OTHER_BONE) + other.head = (2.0, 0.0, 0.0) + other.tail = (2.0, 1.0, 0.0) + source.select = True + source.select_head = False + source.select_tail = True + other.select = False + other.select_head = False + other.select_tail = False + armature.edit_bones.active = source + bpy.ops.object.mode_set(mode="OBJECT") + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00241.py b/tools/web/generated/M16-GAP-00241.py new file mode 100644 index 00000000..2711ce81 --- /dev/null +++ b/tools/web/generated/M16-GAP-00241.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureExtrudeMoveArmature" +OBJECT_NAME = "WebGapArmatureExtrudeMoveObject" +SOURCE_BONE = "WebGapArmatureExtrudeMoveSource" +OTHER_BONE = "WebGapArmatureExtrudeMoveOther" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00241.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + source = armature.edit_bones.new(SOURCE_BONE) + source.head = (0.0, 0.0, 0.0) + source.tail = (0.0, 1.0, 0.0) + other = armature.edit_bones.new(OTHER_BONE) + other.head = (2.0, 0.0, 0.0) + other.tail = (2.0, 1.0, 0.0) + source.select = True + source.select_head = False + source.select_tail = True + other.select = False + other.select_head = False + other.select_tail = False + armature.edit_bones.active = source + bpy.ops.object.mode_set(mode="OBJECT") + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00242.py b/tools/web/generated/M16-GAP-00242.py new file mode 100644 index 00000000..7254abfb --- /dev/null +++ b/tools/web/generated/M16-GAP-00242.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureFillArmature" +OBJECT_NAME = "WebGapArmatureFillObject" +SOURCE_BONE = "WebGapArmatureFillSource" +TARGET_BONE = "WebGapArmatureFillTarget" +OTHER_BONE = "WebGapArmatureFillOther" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00242.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + source = armature.edit_bones.new(SOURCE_BONE) + source.head = (0.0, 0.0, 0.0) + source.tail = (0.0, 1.0, 0.0) + target = armature.edit_bones.new(TARGET_BONE) + target.head = (0.0, 2.0, 0.0) + target.tail = (0.0, 3.0, 0.0) + other = armature.edit_bones.new(OTHER_BONE) + other.head = (2.0, 0.0, 0.0) + other.tail = (2.0, 1.0, 0.0) + source.select = False + source.select_head = False + source.select_tail = True + target.select = False + target.select_head = True + target.select_tail = False + other.select = False + other.select_head = False + other.select_tail = False + armature.edit_bones.active = target + bpy.ops.object.mode_set(mode="OBJECT") + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00243.py b/tools/web/generated/M16-GAP-00243.py new file mode 100644 index 00000000..71883186 --- /dev/null +++ b/tools/web/generated/M16-GAP-00243.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureFlipNamesArmature" +OBJECT_NAME = "WebGapArmatureFlipNamesObject" +LEFT_BONE = "WebGapArmatureFlipBone.L" +RIGHT_BONE = "WebGapArmatureFlipBone.R" +OTHER_BONE = "WebGapArmatureFlipOther" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00243.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + left = armature.edit_bones.new(LEFT_BONE) + left.head = (-1.0, 0.0, 0.0) + left.tail = (-1.0, 1.0, 0.0) + right = armature.edit_bones.new(RIGHT_BONE) + right.head = (1.0, 0.0, 0.0) + right.tail = (1.0, 1.0, 0.0) + other = armature.edit_bones.new(OTHER_BONE) + other.head = (0.0, 0.0, 2.0) + other.tail = (0.0, 1.0, 2.0) + left.select = True + left.select_head = True + left.select_tail = True + right.select = True + right.select_head = True + right.select_tail = True + other.select = False + other.select_head = False + other.select_tail = False + armature.edit_bones.active = right + bpy.ops.object.mode_set(mode="OBJECT") + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00244.py b/tools/web/generated/M16-GAP-00244.py new file mode 100644 index 00000000..39f3141d --- /dev/null +++ b/tools/web/generated/M16-GAP-00244.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureHideArmature" +OBJECT_NAME = "WebGapArmatureHideObject" +HIDE_BONE = "WebGapArmatureHideSelected" +OTHER_BONE = "WebGapArmatureHideOther" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00244.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + hidden = armature.edit_bones.new(HIDE_BONE) + hidden.head = (-1.0, 0.0, 0.0) + hidden.tail = (-1.0, 1.0, 0.0) + other = armature.edit_bones.new(OTHER_BONE) + other.head = (1.0, 0.0, 0.0) + other.tail = (1.0, 1.0, 0.0) + hidden.select = True + hidden.select_head = True + hidden.select_tail = True + other.select = False + other.select_head = False + other.select_tail = False + armature.edit_bones.active = hidden + bpy.ops.object.mode_set(mode="OBJECT") + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00245.py b/tools/web/generated/M16-GAP-00245.py new file mode 100644 index 00000000..9c8c861a --- /dev/null +++ b/tools/web/generated/M16-GAP-00245.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureMoveCollectionArmature" +OBJECT_NAME = "WebGapArmatureMoveCollectionObject" +MOVE_BONE = "WebGapArmatureMoveCollectionSelected" +OTHER_BONE = "WebGapArmatureMoveCollectionOther" +SOURCE_COLLECTION = "WebGapArmatureMoveCollectionSource" +TARGET_COLLECTION = "WebGapArmatureMoveCollectionTarget" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00245.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + move = armature.edit_bones.new(MOVE_BONE) + move.head = (-1.0, 0.0, 0.0) + move.tail = (-1.0, 1.0, 0.0) + other = armature.edit_bones.new(OTHER_BONE) + other.head = (1.0, 0.0, 0.0) + other.tail = (1.0, 1.0, 0.0) + source = armature.collections.new(SOURCE_COLLECTION) + armature.collections.new(TARGET_COLLECTION) + source.assign(move) + source.assign(other) + move.select = True + move.select_head = True + move.select_tail = True + other.select = False + other.select_head = False + other.select_tail = False + armature.edit_bones.active = move + bpy.ops.object.mode_set(mode="OBJECT") + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00246.py b/tools/web/generated/M16-GAP-00246.py new file mode 100644 index 00000000..be53601f --- /dev/null +++ b/tools/web/generated/M16-GAP-00246.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureParentClearArmature" +OBJECT_NAME = "WebGapArmatureParentClearObject" +PARENT_BONE = "WebGapArmatureParentClearParent" +CHILD_BONE = "WebGapArmatureParentClearChild" +OTHER_BONE = "WebGapArmatureParentClearOther" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00246.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + parent = armature.edit_bones.new(PARENT_BONE) + parent.head = (0.0, 0.0, 0.0) + parent.tail = (0.0, 1.0, 0.0) + child = armature.edit_bones.new(CHILD_BONE) + child.head = (0.0, 1.0, 0.0) + child.tail = (0.0, 2.0, 0.0) + child.parent = parent + child.use_connect = True + other = armature.edit_bones.new(OTHER_BONE) + other.head = (2.0, 0.0, 0.0) + other.tail = (2.0, 1.0, 0.0) + parent.select = False + parent.select_head = False + parent.select_tail = False + child.select = True + child.select_head = True + child.select_tail = True + other.select = False + other.select_head = False + other.select_tail = False + armature.edit_bones.active = child + bpy.ops.object.mode_set(mode="OBJECT") + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00247.py b/tools/web/generated/M16-GAP-00247.py new file mode 100644 index 00000000..b2a76bdf --- /dev/null +++ b/tools/web/generated/M16-GAP-00247.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureParentSetArmature" +OBJECT_NAME = "WebGapArmatureParentSetObject" +PARENT_BONE = "WebGapArmatureParentSetParent" +CHILD_BONE = "WebGapArmatureParentSetChild" +OTHER_BONE = "WebGapArmatureParentSetOther" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00247.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + parent = armature.edit_bones.new(PARENT_BONE) + parent.head = (0.0, 0.0, 0.0) + parent.tail = (0.0, 1.0, 0.0) + child = armature.edit_bones.new(CHILD_BONE) + child.head = (0.0, 1.0, 0.0) + child.tail = (0.0, 2.0, 0.0) + other = armature.edit_bones.new(OTHER_BONE) + other.head = (2.0, 0.0, 0.0) + other.tail = (2.0, 1.0, 0.0) + parent.select = True + parent.select_head = True + parent.select_tail = True + child.select = True + child.select_head = True + child.select_tail = True + other.select = False + other.select_head = False + other.select_tail = False + armature.edit_bones.active = parent + bpy.ops.object.mode_set(mode="OBJECT") + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00248.py b/tools/web/generated/M16-GAP-00248.py new file mode 100644 index 00000000..7b981cfb --- /dev/null +++ b/tools/web/generated/M16-GAP-00248.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureRevealArmature" +OBJECT_NAME = "WebGapArmatureRevealObject" +REVEAL_BONE = "WebGapArmatureRevealHidden" +OTHER_BONE = "WebGapArmatureRevealOther" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00248.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + hidden = armature.edit_bones.new(REVEAL_BONE) + hidden.head = (-1.0, 0.0, 0.0) + hidden.tail = (-1.0, 1.0, 0.0) + other = armature.edit_bones.new(OTHER_BONE) + other.head = (1.0, 0.0, 0.0) + other.tail = (1.0, 1.0, 0.0) + hidden.select = False + hidden.select_head = False + hidden.select_tail = False + hidden.hide = True + armature.edit_bones.active = other + other.select = False + other.select_head = False + other.select_tail = False + bpy.ops.object.mode_set(mode="OBJECT") + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00249.py b/tools/web/generated/M16-GAP-00249.py new file mode 100644 index 00000000..d5ce471f --- /dev/null +++ b/tools/web/generated/M16-GAP-00249.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 +import math +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureRollClearArmature" +OBJECT_NAME = "WebGapArmatureRollClearObject" +BONE_NAME = "WebGapArmatureRollClearBone" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00249.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + bone = armature.edit_bones.new(BONE_NAME) + bone.head = (0.0, 0.0, 0.0) + bone.tail = (0.0, 2.0, 0.0) + bone.roll = math.pi / 4.0 + bone.select = True + bone.select_head = True + bone.select_tail = True + armature.edit_bones.active = bone + bpy.ops.object.mode_set(mode="OBJECT") + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00250.py b/tools/web/generated/M16-GAP-00250.py new file mode 100644 index 00000000..e7276114 --- /dev/null +++ b/tools/web/generated/M16-GAP-00250.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureSelectAllArmature" +OBJECT_NAME = "WebGapArmatureSelectAllObject" +PARENT_BONE = "WebGapArmatureSelectAllParent" +OTHER_BONE = "WebGapArmatureSelectAllOther" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00250.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + parent = armature.edit_bones.new(PARENT_BONE) + parent.head = (0.0, 0.0, 0.0) + parent.tail = (0.0, 1.0, 0.0) + other = armature.edit_bones.new(OTHER_BONE) + other.head = (2.0, 0.0, 0.0) + other.tail = (2.0, 1.0, 0.0) + parent.select = True + parent.select_head = True + parent.select_tail = True + other.select = False + other.select_head = False + other.select_tail = False + armature.edit_bones.active = parent + bpy.ops.object.mode_set(mode="OBJECT") + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00251.py b/tools/web/generated/M16-GAP-00251.py new file mode 100644 index 00000000..34c2555a --- /dev/null +++ b/tools/web/generated/M16-GAP-00251.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureSelectHierarchyArmature" +OBJECT_NAME = "WebGapArmatureSelectHierarchyObject" +ROOT_BONE = "WebGapArmatureSelectHierarchyRoot" +CHILD_BONE = "WebGapArmatureSelectHierarchyChild" +OTHER_BONE = "WebGapArmatureSelectHierarchyOther" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00251.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + + root = armature.edit_bones.new(ROOT_BONE) + root.head = (0.0, 0.0, 0.0) + root.tail = (0.0, 1.0, 0.0) + child = armature.edit_bones.new(CHILD_BONE) + child.head = (0.0, 1.0, 0.0) + child.tail = (0.0, 2.0, 0.0) + child.parent = root + child.use_connect = True + other = armature.edit_bones.new(OTHER_BONE) + other.head = (2.0, 0.0, 0.0) + other.tail = (2.0, 1.0, 0.0) + + root.select = True + root.select_head = True + root.select_tail = True + child.select = False + child.select_head = False + child.select_tail = False + other.select = False + other.select_head = False + other.select_tail = False + armature.edit_bones.active = root + bpy.ops.object.mode_set(mode="OBJECT") + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00252.py b/tools/web/generated/M16-GAP-00252.py new file mode 100644 index 00000000..0cf616b4 --- /dev/null +++ b/tools/web/generated/M16-GAP-00252.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureSelectLessArmature" +OBJECT_NAME = "WebGapArmatureSelectLessObject" +ROOT_BONE = "WebGapArmatureSelectLessRoot" +CHILD_BONE = "WebGapArmatureSelectLessChild" +OTHER_BONE = "WebGapArmatureSelectLessOther" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00252.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + + root = armature.edit_bones.new(ROOT_BONE) + root.head = (0.0, 0.0, 0.0) + root.tail = (0.0, 1.0, 0.0) + child = armature.edit_bones.new(CHILD_BONE) + child.head = (0.0, 1.0, 0.0) + child.tail = (0.0, 2.0, 0.0) + child.parent = root + child.use_connect = True + other = armature.edit_bones.new(OTHER_BONE) + other.head = (2.0, 0.0, 0.0) + other.tail = (2.0, 1.0, 0.0) + + armature.edit_bones.active = root + root.select = False + root.select_head = True + root.select_tail = False + child.select = False + child.select_head = False + child.select_tail = False + other.select = True + other.select_head = True + other.select_tail = True + bpy.ops.object.mode_set(mode="OBJECT") + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00253.py b/tools/web/generated/M16-GAP-00253.py new file mode 100644 index 00000000..34239e96 --- /dev/null +++ b/tools/web/generated/M16-GAP-00253.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureSelectLinkedArmature" +OBJECT_NAME = "WebGapArmatureSelectLinkedObject" +ROOT_BONE = "WebGapArmatureSelectLinkedRoot" +CHILD_BONE = "WebGapArmatureSelectLinkedChild" +GRANDCHILD_BONE = "WebGapArmatureSelectLinkedGrandchild" +OTHER_BONE = "WebGapArmatureSelectLinkedOther" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00253.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + + root = armature.edit_bones.new(ROOT_BONE) + root.head = (0.0, 0.0, 0.0) + root.tail = (0.0, 1.0, 0.0) + child = armature.edit_bones.new(CHILD_BONE) + child.head = (0.0, 1.0, 0.0) + child.tail = (0.0, 2.0, 0.0) + child.parent = root + child.use_connect = True + grandchild = armature.edit_bones.new(GRANDCHILD_BONE) + grandchild.head = (0.0, 2.0, 0.0) + grandchild.tail = (0.0, 3.0, 0.0) + grandchild.parent = child + grandchild.use_connect = True + other = armature.edit_bones.new(OTHER_BONE) + other.head = (2.0, 0.0, 0.0) + other.tail = (2.0, 1.0, 0.0) + + root.select = True + root.select_head = True + root.select_tail = True + child.select = False + child.select_head = False + child.select_tail = False + grandchild.select = False + grandchild.select_head = False + grandchild.select_tail = False + other.select = False + other.select_head = False + other.select_tail = False + armature.edit_bones.active = root + bpy.ops.object.mode_set(mode="OBJECT") + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00254.py b/tools/web/generated/M16-GAP-00254.py new file mode 100644 index 00000000..023a6174 --- /dev/null +++ b/tools/web/generated/M16-GAP-00254.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureSelectLinkedPickArmature" +OBJECT_NAME = "WebGapArmatureSelectLinkedPickObject" +ROOT_BONE = "WebGapArmatureSelectLinkedPickRoot" +CHILD_BONE = "WebGapArmatureSelectLinkedPickChild" +GRANDCHILD_BONE = "WebGapArmatureSelectLinkedPickGrandchild" +OTHER_BONE = "WebGapArmatureSelectLinkedPickOther" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00254.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + root = armature.edit_bones.new(ROOT_BONE) + root.head = (0.0, 0.0, 0.0); root.tail = (0.0, 1.0, 0.0) + child = armature.edit_bones.new(CHILD_BONE) + child.head = (0.0, 1.0, 0.0); child.tail = (0.0, 2.0, 0.0); child.parent = root; child.use_connect = True + grandchild = armature.edit_bones.new(GRANDCHILD_BONE) + grandchild.head = (0.0, 2.0, 0.0); grandchild.tail = (0.0, 3.0, 0.0); grandchild.parent = child; grandchild.use_connect = True + other = armature.edit_bones.new(OTHER_BONE) + other.head = (2.0, 0.0, 0.0); other.tail = (2.0, 1.0, 0.0) + root.select = True; root.select_head = True; root.select_tail = True + child.select = False; child.select_head = False; child.select_tail = False + grandchild.select = False; grandchild.select_head = False; grandchild.select_tail = False + other.select = False; other.select_head = False; other.select_tail = False + armature.edit_bones.active = root + bpy.ops.object.mode_set(mode="OBJECT") + bpy.ops.wm.save_as_mainfile(filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00255.py b/tools/web/generated/M16-GAP-00255.py new file mode 100644 index 00000000..1601c62a --- /dev/null +++ b/tools/web/generated/M16-GAP-00255.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureSelectMirrorArmature" +OBJECT_NAME = "WebGapArmatureSelectMirrorObject" +LEFT_BONE = "WebGapSelectMirror.L" +RIGHT_BONE = "WebGapSelectMirror.R" +CENTER_BONE = "WebGapSelectMirrorCenter" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00255.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj; obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + left = armature.edit_bones.new(LEFT_BONE); left.head = (-2.0, 0.0, 0.0); left.tail = (-2.0, 1.0, 0.0) + right = armature.edit_bones.new(RIGHT_BONE); right.head = (2.0, 0.0, 0.0); right.tail = (2.0, 1.0, 0.0) + center = armature.edit_bones.new(CENTER_BONE); center.head = (0.0, 0.0, 0.0); center.tail = (0.0, 1.0, 0.0) + left.select = True; left.select_head = True; left.select_tail = True + right.select = False; right.select_head = False; right.select_tail = False + center.select = False; center.select_head = False; center.select_tail = False + armature.edit_bones.active = left + bpy.ops.object.mode_set(mode="OBJECT") + bpy.ops.wm.save_as_mainfile(filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00256.py b/tools/web/generated/M16-GAP-00256.py new file mode 100644 index 00000000..6bf2df6e --- /dev/null +++ b/tools/web/generated/M16-GAP-00256.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +import pathlib +import sys +import bpy + +ARMATURE_NAME = "WebGapArmatureSelectMoreArmature" +OBJECT_NAME = "WebGapArmatureSelectMoreObject" +ROOT_BONE = "WebGapArmatureSelectMoreRoot" +CHILD_BONE = "WebGapArmatureSelectMoreChild" +GRANDCHILD_BONE = "WebGapArmatureSelectMoreGrandchild" +OTHER_BONE = "WebGapArmatureSelectMoreOther" + +def main(): + args = sys.argv[sys.argv.index("--") + 1:] + if len(args) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00256.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + root = armature.edit_bones.new(ROOT_BONE); root.head = (0, 0, 0); root.tail = (0, 1, 0) + child = armature.edit_bones.new(CHILD_BONE); child.head = (0, 1, 0); child.tail = (0, 2, 0); child.parent = root; child.use_connect = True + grandchild = armature.edit_bones.new(GRANDCHILD_BONE); grandchild.head = (0, 2, 0); grandchild.tail = (0, 3, 0); grandchild.parent = child; grandchild.use_connect = True + other = armature.edit_bones.new(OTHER_BONE); other.head = (2, 0, 0); other.tail = (2, 1, 0) + root.select = True; root.select_head = True; root.select_tail = True + for bone in (child, grandchild, other): + bone.select = False; bone.select_head = False; bone.select_tail = False + armature.edit_bones.active = root + bpy.ops.object.mode_set(mode="OBJECT") + bpy.ops.wm.save_as_mainfile(filepath=str(pathlib.Path(args[0]).resolve()), check_existing=False, compress=True) + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00257.py b/tools/web/generated/M16-GAP-00257.py new file mode 100644 index 00000000..7be1d1bc --- /dev/null +++ b/tools/web/generated/M16-GAP-00257.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureSelectSimilarArmature" +OBJECT_NAME = "WebGapArmatureSelectSimilarObject" +ACTIVE_BONE = "WebGapArmatureSelectSimilarActive" +SIMILAR_BONE = "WebGapArmatureSelectSimilarSameLength" +DIFFERENT_BONE = "WebGapArmatureSelectSimilarDifferentLength" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00257.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + active = armature.edit_bones.new(ACTIVE_BONE) + active.head = (0.0, 0.0, 0.0) + active.tail = (0.0, 1.0, 0.0) + similar = armature.edit_bones.new(SIMILAR_BONE) + similar.head = (2.0, 0.0, 0.0) + similar.tail = (2.0, 1.0, 0.0) + different = armature.edit_bones.new(DIFFERENT_BONE) + different.head = (4.0, 0.0, 0.0) + different.tail = (4.0, 2.0, 0.0) + active.select = True + active.select_head = True + active.select_tail = True + for bone in (similar, different): + bone.select = False + bone.select_head = False + bone.select_tail = False + armature.edit_bones.active = active + bpy.ops.object.mode_set(mode="OBJECT") + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00258.py b/tools/web/generated/M16-GAP-00258.py new file mode 100644 index 00000000..9832830b --- /dev/null +++ b/tools/web/generated/M16-GAP-00258.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureSeparateArmature" +OBJECT_NAME = "WebGapArmatureSeparateObject" +SELECTED_BONE = "WebGapArmatureSeparateSelected" +RETAINED_BONE = "WebGapArmatureSeparateRetained" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00258.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + selected = armature.edit_bones.new(SELECTED_BONE) + selected.head = (0.0, 0.0, 0.0) + selected.tail = (0.0, 1.0, 0.0) + retained = armature.edit_bones.new(RETAINED_BONE) + retained.head = (2.0, 0.0, 0.0) + retained.tail = (2.0, 1.0, 0.0) + selected.select = True + selected.select_head = True + selected.select_tail = True + retained.select = False + retained.select_head = False + retained.select_tail = False + armature.edit_bones.active = selected + bpy.ops.object.mode_set(mode="OBJECT") + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/tools/web/generated/M16-GAP-00259.py b/tools/web/generated/M16-GAP-00259.py new file mode 100644 index 00000000..7147cbfd --- /dev/null +++ b/tools/web/generated/M16-GAP-00259.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +import pathlib +import sys +import bpy + +ARMATURE_NAME = "WebGapArmatureShortestPathArmature" +OBJECT_NAME = "WebGapArmatureShortestPathObject" +ROOT_BONE = "WebGapArmatureShortestPathRoot" +CHILD_BONE = "WebGapArmatureShortestPathChild" +GRANDCHILD_BONE = "WebGapArmatureShortestPathGrandchild" +OTHER_BONE = "WebGapArmatureShortestPathOther" + +def main(): + args = sys.argv[sys.argv.index("--") + 1:] + if len(args) != 1: raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00259.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + arm = bpy.data.armatures.new(ARMATURE_NAME); obj = bpy.data.objects.new(OBJECT_NAME, arm); bpy.context.scene.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj; obj.select_set(True); bpy.ops.object.mode_set(mode="EDIT") + root = arm.edit_bones.new(ROOT_BONE); root.head=(0,0,0); root.tail=(0,1,0) + child = arm.edit_bones.new(CHILD_BONE); child.head=(0,1,0); child.tail=(0,2,0); child.parent=root; child.use_connect=True + grand = arm.edit_bones.new(GRANDCHILD_BONE); grand.head=(0,2,0); grand.tail=(0,3,0); grand.parent=child; grand.use_connect=True + other = arm.edit_bones.new(OTHER_BONE); other.head=(2,0,0); other.tail=(2,1,0) + for bone in (root, child, grand): bone.select=True; bone.select_head=True; bone.select_tail=True + other.select=False; other.select_head=False; other.select_tail=False; arm.edit_bones.active=root + bpy.ops.object.mode_set(mode="OBJECT"); bpy.ops.wm.save_as_mainfile(filepath=str(pathlib.Path(args[0]).resolve()), check_existing=False, compress=True) +if __name__ == "__main__": main() diff --git a/tools/web/generated/M16-GAP-00260.py b/tools/web/generated/M16-GAP-00260.py new file mode 100644 index 00000000..e0a0edfd --- /dev/null +++ b/tools/web/generated/M16-GAP-00260.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python3 +import pathlib,sys,bpy +ARMATURE_NAME="WebGapArmatureSplitArmature"; OBJECT_NAME="WebGapArmatureSplitObject"; ROOT_BONE="WebGapArmatureSplitRoot"; CHILD_BONE="WebGapArmatureSplitChild"; OTHER_BONE="WebGapArmatureSplitOther" +def main(): + a=sys.argv[sys.argv.index("--")+1:] + if len(a)!=1: raise SystemExit("usage") + bpy.ops.wm.read_factory_settings(use_empty=True); arm=bpy.data.armatures.new(ARMATURE_NAME); obj=bpy.data.objects.new(OBJECT_NAME,arm); bpy.context.scene.collection.objects.link(obj); bpy.context.view_layer.objects.active=obj; obj.select_set(True); bpy.ops.object.mode_set(mode="EDIT") + root=arm.edit_bones.new(ROOT_BONE); root.head=(0,0,0); root.tail=(0,1,0); child=arm.edit_bones.new(CHILD_BONE); child.head=(0,1,0); child.tail=(0,2,0); child.parent=root; child.use_connect=True; other=arm.edit_bones.new(OTHER_BONE); other.head=(2,0,0); other.tail=(2,1,0); root.select=True; root.select_head=True; root.select_tail=True + for b in (child,other): b.select=False; b.select_head=False; b.select_tail=False + arm.edit_bones.active=root; bpy.ops.object.mode_set(mode="OBJECT"); bpy.ops.wm.save_as_mainfile(filepath=str(pathlib.Path(a[0]).resolve()),check_existing=False,compress=True) +if __name__=="__main__": main() diff --git a/tools/web/generated/M16-GAP-00261.py b/tools/web/generated/M16-GAP-00261.py new file mode 100644 index 00000000..3efedfa1 --- /dev/null +++ b/tools/web/generated/M16-GAP-00261.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python3 +import pathlib, sys, bpy + +ARMATURE_NAME="WebGapArmatureSubdivideArmature"; OBJECT_NAME="WebGapArmatureSubdivideObject"; SOURCE_BONE="WebGapArmatureSubdivideSource"; OTHER_BONE="WebGapArmatureSubdivideOther" +def main(): + args=sys.argv[sys.argv.index("--")+1:] + if len(args)!=1: raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00261.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True); arm=bpy.data.armatures.new(ARMATURE_NAME); obj=bpy.data.objects.new(OBJECT_NAME,arm); bpy.context.scene.collection.objects.link(obj); bpy.context.view_layer.objects.active=obj; obj.select_set(True); bpy.ops.object.mode_set(mode="EDIT") + source=arm.edit_bones.new(SOURCE_BONE); source.head=(0,0,0); source.tail=(0,1,0); other=arm.edit_bones.new(OTHER_BONE); other.head=(2,0,0); other.tail=(2,1,0); source.select=True; source.select_head=True; source.select_tail=True; other.select=False; other.select_head=False; other.select_tail=False; arm.edit_bones.active=source + bpy.ops.object.mode_set(mode="OBJECT"); bpy.ops.wm.save_as_mainfile(filepath=str(pathlib.Path(args[0]).resolve()),check_existing=False,compress=True) +if __name__=="__main__": main() diff --git a/tools/web/generated/M16-GAP-00262.py b/tools/web/generated/M16-GAP-00262.py new file mode 100644 index 00000000..14845f96 --- /dev/null +++ b/tools/web/generated/M16-GAP-00262.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python3 +import pathlib,sys,bpy +ARMATURE_NAME="WebGapArmatureSwitchDirectionArmature"; OBJECT_NAME="WebGapArmatureSwitchDirectionObject"; ROOT_BONE="WebGapArmatureSwitchDirectionRoot"; CHILD_BONE="WebGapArmatureSwitchDirectionChild"; OTHER_BONE="WebGapArmatureSwitchDirectionOther" +def main(): + a=sys.argv[sys.argv.index("--")+1:]; + if len(a)!=1: raise SystemExit("usage") + bpy.ops.wm.read_factory_settings(use_empty=True);arm=bpy.data.armatures.new(ARMATURE_NAME);obj=bpy.data.objects.new(OBJECT_NAME,arm);bpy.context.scene.collection.objects.link(obj);bpy.context.view_layer.objects.active=obj;obj.select_set(True);bpy.ops.object.mode_set(mode="EDIT") + root=arm.edit_bones.new(ROOT_BONE);root.head=(0,0,0);root.tail=(0,1,0);child=arm.edit_bones.new(CHILD_BONE);child.head=(0,1,0);child.tail=(0,2,0);child.parent=root;child.use_connect=True;other=arm.edit_bones.new(OTHER_BONE);other.head=(2,0,0);other.tail=(2,1,0) + for b in (root,child):b.select=True;b.select_head=True;b.select_tail=True + other.select=False;other.select_head=False;other.select_tail=False;arm.edit_bones.active=root;bpy.ops.object.mode_set(mode="OBJECT");bpy.ops.wm.save_as_mainfile(filepath=str(pathlib.Path(a[0]).resolve()),check_existing=False,compress=True) +if __name__=="__main__":main() diff --git a/tools/web/generated/M16-GAP-00263.py b/tools/web/generated/M16-GAP-00263.py new file mode 100644 index 00000000..9d9bb21e --- /dev/null +++ b/tools/web/generated/M16-GAP-00263.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +import pathlib +import sys + +import bpy + + +ARMATURE_NAME = "WebGapArmatureSymmetrizeArmature" +OBJECT_NAME = "WebGapArmatureSymmetrizeObject" +SOURCE_BONE = "WebGapArmatureSymmetrizeSource.L" +OTHER_BONE = "WebGapArmatureSymmetrizeOther" + + +def main(): + arguments = sys.argv[sys.argv.index("--") + 1 :] + if len(arguments) != 1: + raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00263.py -- OUTPUT") + bpy.ops.wm.read_factory_settings(use_empty=True) + armature = bpy.data.armatures.new(ARMATURE_NAME) + obj = bpy.data.objects.new(OBJECT_NAME, armature) + bpy.context.scene.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + bpy.ops.object.mode_set(mode="EDIT") + source = armature.edit_bones.new(SOURCE_BONE) + source.head = (1.0, 0.0, 0.0) + source.tail = (1.0, 1.0, 0.0) + other = armature.edit_bones.new(OTHER_BONE) + other.head = (-3.0, 0.0, 0.0) + other.tail = (-3.0, 1.0, 0.0) + source.select = True + source.select_head = True + source.select_tail = True + other.select = False + other.select_head = False + other.select_tail = False + armature.edit_bones.active = source + bpy.ops.object.mode_set(mode="OBJECT") + bpy.ops.wm.save_as_mainfile( + filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True + ) + + +if __name__ == "__main__": + main() diff --git a/web/app/public/vendor/blender/web_engine.js b/web/app/public/vendor/blender/web_engine.js index c644158c..144e0b10 100644 --- a/web/app/public/vendor/blender/web_engine.js +++ b/web/app/public/vendor/blender/web_engine.js @@ -6,7 +6,7 @@ var Module = (() => { async function(moduleArg = {}) { var moduleRtn; -var Module=moduleArg;var readyPromiseResolve,readyPromiseReject;var readyPromise=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject});["_malloc","_free","_web_engine_create","_web_engine_destroy","_web_engine_get_memory_stats","_web_engine_get_live_handles","_web_engine_get_allocated_bytes","_web_engine_open_blend","_web_engine_apply_command","_web_engine_append_library_object","_web_engine_undo","_web_engine_redo","_web_engine_get_scene_snapshot","_web_engine_get_scene_metadata","_web_engine_get_scene_geometry","_web_engine_get_scene_delta","_web_engine_get_packed_asset","_web_engine_evaluate_depsgraph","_web_engine_save_blend","_web_engine_free_buffer","_web_engine_last_error_code","_web_engine_last_error_message","_web_engine_decimate_apply","_memory","___indirect_function_table","___set_stack_limits","onRuntimeInitialized"].forEach(prop=>{if(!Object.getOwnPropertyDescriptor(readyPromise,prop)){Object.defineProperty(readyPromise,prop,{get:()=>abort("You are getting "+prop+" on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js"),set:()=>abort("You are setting "+prop+" on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js")})}});var ENVIRONMENT_IS_WEB=typeof window=="object";var ENVIRONMENT_IS_WORKER=typeof importScripts=="function";var ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string"&&process.type!="renderer";var ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;if(ENVIRONMENT_IS_NODE){const{createRequire}=await import("module");let dirname=import.meta.url;if(dirname.startsWith("data:")){dirname="/"}var require=createRequire(dirname)}var moduleOverrides=Object.assign({},Module);var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_NODE){if(typeof process=="undefined"||!process.release||process.release.name!=="node")throw new Error("not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)");var nodeVersion=process.versions.node;var numericVersion=nodeVersion.split(".").slice(0,3);numericVersion=numericVersion[0]*1e4+numericVersion[1]*100+numericVersion[2].split("-")[0]*1;if(numericVersion<16e4){throw new Error("This emscripten-generated code requires node v16.0.0 (detected v"+nodeVersion+")")}var fs=require("fs");var nodePath=require("path");if(!import.meta.url.startsWith("data:")){scriptDirectory=nodePath.dirname(require("url").fileURLToPath(import.meta.url))+"/"}readBinary=filename=>{filename=isFileURI(filename)?new URL(filename):nodePath.normalize(filename);var ret=fs.readFileSync(filename);assert(ret.buffer);return ret};readAsync=(filename,binary=true)=>{filename=isFileURI(filename)?new URL(filename):nodePath.normalize(filename);return new Promise((resolve,reject)=>{fs.readFile(filename,binary?undefined:"utf8",(err,data)=>{if(err)reject(err);else resolve(binary?data.buffer:data)})})};if(!Module["thisProgram"]&&process.argv.length>1){thisProgram=process.argv[1].replace(/\\/g,"/")}arguments_=process.argv.slice(2);quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow}}else if(ENVIRONMENT_IS_SHELL){if(typeof process=="object"&&typeof require==="function"||typeof window=="object"||typeof importScripts=="function")throw new Error("not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)")}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(_scriptName){scriptDirectory=_scriptName}if(scriptDirectory.startsWith("blob:")){scriptDirectory=""}else{scriptDirectory=scriptDirectory.substr(0,scriptDirectory.replace(/[?#].*/,"").lastIndexOf("/")+1)}if(!(typeof window=="object"||typeof importScripts=="function"))throw new Error("not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)");{if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=url=>{assert(!isFileURI(url),"readAsync does not work with file:// URLs");return fetch(url,{credentials:"same-origin"}).then(response=>{if(response.ok){return response.arrayBuffer()}return Promise.reject(new Error(response.status+" : "+response.url))})}}}else{throw new Error("environment detection error")}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.error.bind(console);Object.assign(Module,moduleOverrides);moduleOverrides=null;checkIncomingModuleAPI();if(Module["arguments"])arguments_=Module["arguments"];legacyModuleProp("arguments","arguments_");if(Module["thisProgram"])thisProgram=Module["thisProgram"];legacyModuleProp("thisProgram","thisProgram");assert(typeof Module["memoryInitializerPrefixURL"]=="undefined","Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["pthreadMainPrefixURL"]=="undefined","Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["cdInitializerPrefixURL"]=="undefined","Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["filePackagePrefixURL"]=="undefined","Module.filePackagePrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["read"]=="undefined","Module.read option was removed");assert(typeof Module["readAsync"]=="undefined","Module.readAsync option was removed (modify readAsync in JS)");assert(typeof Module["readBinary"]=="undefined","Module.readBinary option was removed (modify readBinary in JS)");assert(typeof Module["setWindowTitle"]=="undefined","Module.setWindowTitle option was removed (modify emscripten_set_window_title in JS)");assert(typeof Module["TOTAL_MEMORY"]=="undefined","Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY");legacyModuleProp("asm","wasmExports");legacyModuleProp("readAsync","readAsync");legacyModuleProp("readBinary","readBinary");legacyModuleProp("setWindowTitle","setWindowTitle");assert(!ENVIRONMENT_IS_SHELL,"shell environment detected but not enabled at build time. Add `shell` to `-sENVIRONMENT` to enable.");var wasmBinary=Module["wasmBinary"];legacyModuleProp("wasmBinary","wasmBinary");if(typeof WebAssembly!="object"){err("no native wasm support detected")}var wasmMemory;var ABORT=false;var EXITSTATUS;function assert(condition,text){if(!condition){abort("Assertion failed"+(text?": "+text:""))}}var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateMemoryViews(){var b=wasmMemory.buffer;Module["HEAP8"]=HEAP8=new Int8Array(b);Module["HEAP16"]=HEAP16=new Int16Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);Module["HEAPU16"]=HEAPU16=new Uint16Array(b);Module["HEAP32"]=HEAP32=new Int32Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);Module["HEAPF64"]=HEAPF64=new Float64Array(b)}assert(!Module["STACK_SIZE"],"STACK_SIZE can no longer be set at runtime. Use -sSTACK_SIZE at link time");assert(typeof Int32Array!="undefined"&&typeof Float64Array!=="undefined"&&Int32Array.prototype.subarray!=undefined&&Int32Array.prototype.set!=undefined,"JS engine does not provide full typed array support");assert(!Module["wasmMemory"],"Use of `wasmMemory` detected. Use -sIMPORTED_MEMORY to define wasmMemory externally");assert(!Module["INITIAL_MEMORY"],"Detected runtime INITIAL_MEMORY setting. Use -sIMPORTED_MEMORY to define wasmMemory dynamically");function writeStackCookie(){var max=_emscripten_stack_get_end();assert((max&3)==0);if(max==0){max+=4}HEAPU32[max>>2]=34821223;checkInt32(34821223);HEAPU32[max+4>>2]=2310721022;checkInt32(2310721022);HEAPU32[0>>2]=1668509029;checkInt32(1668509029)}function checkStackCookie(){if(ABORT)return;var max=_emscripten_stack_get_end();if(max==0){max+=4}var cookie1=HEAPU32[max>>2];var cookie2=HEAPU32[max+4>>2];if(cookie1!=34821223||cookie2!=2310721022){abort(`Stack overflow! Stack cookie has been overwritten at ${ptrToString(max)}, expected hex dwords 0x89BACDFE and 0x2135467, but received ${ptrToString(cookie2)} ${ptrToString(cookie1)}`)}if(HEAPU32[0>>2]!=1668509029){abort("Runtime error: The application has corrupted its heap memory area (address zero)!")}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;function preRun(){var preRuns=Module["preRun"];if(preRuns){if(typeof preRuns=="function")preRuns=[preRuns];preRuns.forEach(addOnPreRun)}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){assert(!runtimeInitialized);runtimeInitialized=true;checkStackCookie();setStackLimits();if(!Module["noFSInit"]&&!FS.initialized)FS.init();FS.ignorePermissions=false;TTY.init();callRuntimeCallbacks(__ATINIT__)}function postRun(){checkStackCookie();var postRuns=Module["postRun"];if(postRuns){if(typeof postRuns=="function")postRuns=[postRuns];postRuns.forEach(addOnPostRun)}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnInit(cb){__ATINIT__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}assert(Math.imul,"This browser does not support Math.imul(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.fround,"This browser does not support Math.fround(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.clz32,"This browser does not support Math.clz32(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.trunc,"This browser does not support Math.trunc(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;var runDependencyTracking={};function getUniqueRunDependency(id){var orig=id;while(1){if(!runDependencyTracking[id])return id;id=orig+Math.random()}}function addRunDependency(id){runDependencies++;Module["monitorRunDependencies"]?.(runDependencies);if(id){assert(!runDependencyTracking[id]);runDependencyTracking[id]=1;if(runDependencyWatcher===null&&typeof setInterval!="undefined"){runDependencyWatcher=setInterval(()=>{if(ABORT){clearInterval(runDependencyWatcher);runDependencyWatcher=null;return}var shown=false;for(var dep in runDependencyTracking){if(!shown){shown=true;err("still waiting on run dependencies:")}err(`dependency: ${dep}`)}if(shown){err("(end of list)")}},1e4)}}else{err("warning: run dependency added without ID")}}function removeRunDependency(id){runDependencies--;Module["monitorRunDependencies"]?.(runDependencies);if(id){assert(runDependencyTracking[id]);delete runDependencyTracking[id]}else{err("warning: run dependency removed without ID")}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}function abort(what){Module["onAbort"]?.(what);what="Aborted("+what+")";err(what);ABORT=true;var e=new WebAssembly.RuntimeError(what);readyPromiseReject(e);throw e}var dataURIPrefix="data:application/octet-stream;base64,";var isDataURI=filename=>filename.startsWith(dataURIPrefix);var isFileURI=filename=>filename.startsWith("file://");function createExportWrapper(name,nargs){return(...args)=>{assert(runtimeInitialized,`native function \`${name}\` called before runtime initialization`);var f=wasmExports[name];assert(f,`exported native function \`${name}\` not found`);assert(args.length<=nargs,`native function \`${name}\` called with ${args.length} args but expects ${nargs}`);return f(...args)}}function findWasmBinary(){if(Module["locateFile"]){var f="web_engine.wasm";if(!isDataURI(f)){return locateFile(f)}return f}return new URL("web_engine.wasm",import.meta.url).href}var wasmBinaryFile;function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}function getBinaryPromise(binaryFile){if(!wasmBinary){return readAsync(binaryFile).then(response=>new Uint8Array(response),()=>getBinarySync(binaryFile))}return Promise.resolve().then(()=>getBinarySync(binaryFile))}function instantiateArrayBuffer(binaryFile,imports,receiver){return getBinaryPromise(binaryFile).then(binary=>WebAssembly.instantiate(binary,imports)).then(receiver,reason=>{err(`failed to asynchronously prepare wasm: ${reason}`);if(isFileURI(wasmBinaryFile)){err(`warning: Loading from a file URI (${wasmBinaryFile}) is not supported in most browsers. See https://emscripten.org/docs/getting_started/FAQ.html#how-do-i-run-a-local-webserver-for-testing-why-does-my-program-stall-in-downloading-or-preparing`)}abort(reason)})}function instantiateAsync(binary,binaryFile,imports,callback){if(!binary&&typeof WebAssembly.instantiateStreaming=="function"&&!isDataURI(binaryFile)&&!ENVIRONMENT_IS_NODE&&typeof fetch=="function"){return fetch(binaryFile,{credentials:"same-origin"}).then(response=>{var result=WebAssembly.instantiateStreaming(response,imports);return result.then(callback,function(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(binaryFile,imports,callback)})})}return instantiateArrayBuffer(binaryFile,imports,callback)}function getWasmImports(){return{env:wasmImports,wasi_snapshot_preview1:wasmImports}}function createWasm(){var info=getWasmImports();function receiveInstance(instance,module){wasmExports=instance.exports;wasmMemory=wasmExports["memory"];assert(wasmMemory,"memory not found in wasm exports");updateMemoryViews();wasmTable=wasmExports["__indirect_function_table"];assert(wasmTable,"table not found in wasm exports");addOnInit(wasmExports["__wasm_call_ctors"]);removeRunDependency("wasm-instantiate");return wasmExports}addRunDependency("wasm-instantiate");var trueModule=Module;function receiveInstantiationResult(result){assert(Module===trueModule,"the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?");trueModule=null;receiveInstance(result["instance"])}if(Module["instantiateWasm"]){try{return Module["instantiateWasm"](info,receiveInstance)}catch(e){err(`Module.instantiateWasm callback failed with error: ${e}`);readyPromiseReject(e)}}wasmBinaryFile??=findWasmBinary();instantiateAsync(wasmBinary,wasmBinaryFile,info,receiveInstantiationResult).catch(readyPromiseReject);return{}}var tempDouble;var tempI64;(()=>{var h16=new Int16Array(1);var h8=new Int8Array(h16.buffer);h16[0]=25459;if(h8[0]!==115||h8[1]!==99)throw"Runtime error: expected the system to be little-endian! (Run with -sSUPPORT_BIG_ENDIAN to bypass)"})();if(Module["ENVIRONMENT"]){throw new Error("Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -sENVIRONMENT=web or -sENVIRONMENT=node)")}function legacyModuleProp(prop,newName,incoming=true){if(!Object.getOwnPropertyDescriptor(Module,prop)){Object.defineProperty(Module,prop,{configurable:true,get(){let extra=incoming?" (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)":"";abort(`\`Module.${prop}\` has been replaced by \`${newName}\``+extra)}})}}function ignoredModuleProp(prop){if(Object.getOwnPropertyDescriptor(Module,prop)){abort(`\`Module.${prop}\` was supplied but \`${prop}\` not included in INCOMING_MODULE_JS_API`)}}function isExportedByForceFilesystem(name){return name==="FS_createPath"||name==="FS_createDataFile"||name==="FS_createPreloadedFile"||name==="FS_unlink"||name==="addRunDependency"||name==="FS_createLazyFile"||name==="FS_createDevice"||name==="removeRunDependency"}function hookGlobalSymbolAccess(sym,func){if(typeof globalThis!="undefined"&&!Object.getOwnPropertyDescriptor(globalThis,sym)){Object.defineProperty(globalThis,sym,{configurable:true,get(){func();return undefined}})}}function missingGlobal(sym,msg){hookGlobalSymbolAccess(sym,()=>{warnOnce(`\`${sym}\` is not longer defined by emscripten. ${msg}`)})}missingGlobal("buffer","Please use HEAP8.buffer or wasmMemory.buffer");missingGlobal("asm","Please use wasmExports instead");function missingLibrarySymbol(sym){hookGlobalSymbolAccess(sym,()=>{var msg=`\`${sym}\` is a library symbol and not included by default; add it to your library.js __deps or to DEFAULT_LIBRARY_FUNCS_TO_INCLUDE on the command line`;var librarySymbol=sym;if(!librarySymbol.startsWith("_")){librarySymbol="$"+sym}msg+=` (e.g. -sDEFAULT_LIBRARY_FUNCS_TO_INCLUDE='${librarySymbol}')`;if(isExportedByForceFilesystem(sym)){msg+=". Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you"}warnOnce(msg)});unexportedRuntimeSymbol(sym)}function unexportedRuntimeSymbol(sym){if(!Object.getOwnPropertyDescriptor(Module,sym)){Object.defineProperty(Module,sym,{configurable:true,get(){var msg=`'${sym}' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the Emscripten FAQ)`;if(isExportedByForceFilesystem(sym)){msg+=". Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you"}abort(msg)}})}}var MAX_UINT8=2**8-1;var MAX_UINT16=2**16-1;var MAX_UINT32=2**32-1;var MAX_UINT53=2**53-1;var MAX_UINT64=2**64-1;var MIN_INT8=-(2**(8-1));var MIN_INT16=-(2**(16-1));var MIN_INT32=-(2**(32-1));var MIN_INT53=-(2**(53-1));var MIN_INT64=-(2**(64-1));function checkInt(value,bits,min,max){assert(Number.isInteger(Number(value)),`attempt to write non-integer (${value}) into integer heap`);assert(value<=max,`value (${value}) too large to write as ${bits}-bit value`);assert(value>=min,`value (${value}) too small to write as ${bits}-bit value`)}var checkInt8=value=>checkInt(value,8,MIN_INT8,MAX_UINT8);var checkInt16=value=>checkInt(value,16,MIN_INT16,MAX_UINT16);var checkInt32=value=>checkInt(value,32,MIN_INT32,MAX_UINT32);var checkInt64=value=>checkInt(value,64,MIN_INT64,MAX_UINT64);function dbg(...args){console.warn(...args)}function ExitStatus(status){this.name="ExitStatus";this.message=`Program terminated with exit(${status})`;this.status=status}var callRuntimeCallbacks=callbacks=>{callbacks.forEach(f=>f(Module))};var noExitRuntime=Module["noExitRuntime"]||true;var ptrToString=ptr=>{assert(typeof ptr==="number");ptr>>>=0;return"0x"+ptr.toString(16).padStart(8,"0")};var setStackLimits=()=>{var stackLow=_emscripten_stack_get_base();var stackHigh=_emscripten_stack_get_end();___set_stack_limits(stackLow,stackHigh)};var stackRestore=val=>__emscripten_stack_restore(val);var stackSave=()=>_emscripten_stack_get_current();var warnOnce=text=>{warnOnce.shown||={};if(!warnOnce.shown[text]){warnOnce.shown[text]=1;if(ENVIRONMENT_IS_NODE)text="warning: "+text;err(text)}};var UTF8Decoder=typeof TextDecoder!="undefined"?new TextDecoder:undefined;var UTF8ArrayToString=(heapOrArray,idx=0,maxBytesToRead=NaN)=>{var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heapOrArray[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx>10,56320|ch&1023)}}return str};var UTF8ToString=(ptr,maxBytesToRead)=>{assert(typeof ptr=="number",`UTF8ToString expects a number (got ${typeof ptr})`);return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""};var ___assert_fail=(condition,filename,line,func)=>{abort(`Assertion failed: ${UTF8ToString(condition)}, at: `+[filename?UTF8ToString(filename):"unknown filename",line,func?UTF8ToString(func):"unknown function"])};var wasmTableMirror=[];var wasmTable;var getWasmTableEntry=funcPtr=>{var func=wasmTableMirror[funcPtr];if(!func){if(funcPtr>=wasmTableMirror.length)wasmTableMirror.length=funcPtr+1;wasmTableMirror[funcPtr]=func=wasmTable.get(funcPtr)}assert(wasmTable.get(funcPtr)==func,"JavaScript-side Wasm function table mirror is out of date!");return func};var ___call_sighandler=(fp,sig)=>getWasmTableEntry(fp)(sig);var exceptionCaught=[];var uncaughtExceptionCount=0;var ___cxa_begin_catch=ptr=>{var info=new ExceptionInfo(ptr);if(!info.get_caught()){info.set_caught(true);uncaughtExceptionCount--}info.set_rethrown(false);exceptionCaught.push(info);___cxa_increment_exception_refcount(ptr);return ___cxa_get_exception_ptr(ptr)};var exceptionLast=0;var ___cxa_end_catch=()=>{_setThrew(0,0);assert(exceptionCaught.length>0);var info=exceptionCaught.pop();___cxa_decrement_exception_refcount(info.excPtr);exceptionLast=0};class ExceptionInfo{constructor(excPtr){this.excPtr=excPtr;this.ptr=excPtr-24}set_type(type){HEAPU32[this.ptr+4>>2]=type}get_type(){return HEAPU32[this.ptr+4>>2]}set_destructor(destructor){HEAPU32[this.ptr+8>>2]=destructor}get_destructor(){return HEAPU32[this.ptr+8>>2]}set_caught(caught){caught=caught?1:0;HEAP8[this.ptr+12]=caught;checkInt8(caught)}get_caught(){return HEAP8[this.ptr+12]!=0}set_rethrown(rethrown){rethrown=rethrown?1:0;HEAP8[this.ptr+13]=rethrown;checkInt8(rethrown)}get_rethrown(){return HEAP8[this.ptr+13]!=0}init(type,destructor){this.set_adjusted_ptr(0);this.set_type(type);this.set_destructor(destructor)}set_adjusted_ptr(adjustedPtr){HEAPU32[this.ptr+16>>2]=adjustedPtr}get_adjusted_ptr(){return HEAPU32[this.ptr+16>>2]}}var ___resumeException=ptr=>{if(!exceptionLast){exceptionLast=ptr}assert(false,"Exception thrown, but exception catching is not enabled. Compile with -sNO_DISABLE_EXCEPTION_CATCHING or -sEXCEPTION_CATCHING_ALLOWED=[..] to catch.")};var setTempRet0=val=>__emscripten_tempret_set(val);var findMatchingCatch=args=>{var thrown=exceptionLast;if(!thrown){setTempRet0(0);return 0}var info=new ExceptionInfo(thrown);info.set_adjusted_ptr(thrown);var thrownType=info.get_type();if(!thrownType){setTempRet0(0);return thrown}for(var caughtType of args){if(caughtType===0||caughtType===thrownType){break}var adjusted_ptr_addr=info.ptr+16;if(___cxa_can_catch(caughtType,thrownType,adjusted_ptr_addr)){setTempRet0(caughtType);return thrown}}setTempRet0(thrownType);return thrown};var ___cxa_find_matching_catch_2=()=>findMatchingCatch([]);var ___cxa_find_matching_catch_3=arg0=>findMatchingCatch([arg0]);var ___cxa_rethrow=()=>{var info=exceptionCaught.pop();if(!info){abort("no exception to throw")}var ptr=info.excPtr;if(!info.get_rethrown()){exceptionCaught.push(info);info.set_rethrown(true);info.set_caught(false);uncaughtExceptionCount++}exceptionLast=ptr;assert(false,"Exception thrown, but exception catching is not enabled. Compile with -sNO_DISABLE_EXCEPTION_CATCHING or -sEXCEPTION_CATCHING_ALLOWED=[..] to catch.")};var ___cxa_throw=(ptr,type,destructor)=>{var info=new ExceptionInfo(ptr);info.init(type,destructor);exceptionLast=ptr;uncaughtExceptionCount++;assert(false,"Exception thrown, but exception catching is not enabled. Compile with -sNO_DISABLE_EXCEPTION_CATCHING or -sEXCEPTION_CATCHING_ALLOWED=[..] to catch.")};var ___handle_stack_overflow=requested=>{var base=_emscripten_stack_get_base();var end=_emscripten_stack_get_end();abort(`stack overflow (Attempt to set SP to ${ptrToString(requested)}`+`, with stack limits [${ptrToString(end)} - ${ptrToString(base)}`+"]). If you require more stack space build with -sSTACK_SIZE=")};var PATH={isAbs:path=>path.charAt(0)==="/",splitPath:filename=>{var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;return splitPathRe.exec(filename).slice(1)},normalizeArray:(parts,allowAboveRoot)=>{var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up;up--){parts.unshift("..")}}return parts},normalize:path=>{var isAbsolute=PATH.isAbs(path),trailingSlash=path.substr(-1)==="/";path=PATH.normalizeArray(path.split("/").filter(p=>!!p),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path},dirname:path=>{var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return"."}if(dir){dir=dir.substr(0,dir.length-1)}return root+dir},basename:path=>{if(path==="/")return"/";path=PATH.normalize(path);path=path.replace(/\/$/,"");var lastSlash=path.lastIndexOf("/");if(lastSlash===-1)return path;return path.substr(lastSlash+1)},join:(...paths)=>PATH.normalize(paths.join("/")),join2:(l,r)=>PATH.normalize(l+"/"+r)};var initRandomFill=()=>{if(typeof crypto=="object"&&typeof crypto["getRandomValues"]=="function"){return view=>crypto.getRandomValues(view)}else if(ENVIRONMENT_IS_NODE){try{var crypto_module=require("crypto");var randomFillSync=crypto_module["randomFillSync"];if(randomFillSync){return view=>crypto_module["randomFillSync"](view)}var randomBytes=crypto_module["randomBytes"];return view=>(view.set(randomBytes(view.byteLength)),view)}catch(e){}}abort("no cryptographic support found for randomDevice. consider polyfilling it if you want to use something insecure like Math.random(), e.g. put this in a --pre-js: var crypto = { getRandomValues: (array) => { for (var i = 0; i < array.length; i++) array[i] = (Math.random()*256)|0 } };")};var randomFill=view=>(randomFill=initRandomFill())(view);var PATH_FS={resolve:(...args)=>{var resolvedPath="",resolvedAbsolute=false;for(var i=args.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?args[i]:FS.cwd();if(typeof path!="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){return""}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=PATH.isAbs(path)}resolvedPath=PATH.normalizeArray(resolvedPath.split("/").filter(p=>!!p),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."},relative:(from,to)=>{from=PATH_FS.resolve(from).substr(1);to=PATH_FS.resolve(to).substr(1);function trim(arr){var start=0;for(;start=0;end--){if(arr[end]!=="")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split("/"));var toParts=trim(to.split("/"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i{var len=0;for(var i=0;i=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{assert(typeof str==="string",`stringToUTF8Array expects a string (got ${typeof str})`);if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;if(u>1114111)warnOnce("Invalid Unicode code point "+ptrToString(u)+" encountered when serializing a JS string to a UTF-8 string in wasm memory! (Valid unicode code points should be in range 0-0x10FFFF).");heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx};function intArrayFromString(stringy,dontAddNull,length){var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array}var FS_stdin_getChar=()=>{if(!FS_stdin_getChar_buffer.length){var result=null;if(ENVIRONMENT_IS_NODE){var BUFSIZE=256;var buf=Buffer.alloc(BUFSIZE);var bytesRead=0;var fd=process.stdin.fd;try{bytesRead=fs.readSync(fd,buf,0,BUFSIZE)}catch(e){if(e.toString().includes("EOF"))bytesRead=0;else throw e}if(bytesRead>0){result=buf.slice(0,bytesRead).toString("utf-8")}}else if(typeof window!="undefined"&&typeof window.prompt=="function"){result=window.prompt("Input: ");if(result!==null){result+="\n"}}else{}if(!result){return null}FS_stdin_getChar_buffer=intArrayFromString(result,true)}return FS_stdin_getChar_buffer.shift()};var TTY={ttys:[],init(){},shutdown(){},register(dev,ops){TTY.ttys[dev]={input:[],output:[],ops};FS.registerDevice(dev,TTY.stream_ops)},stream_ops:{open(stream){var tty=TTY.ttys[stream.node.rdev];if(!tty){throw new FS.ErrnoError(43)}stream.tty=tty;stream.seekable=false},close(stream){stream.tty.ops.fsync(stream.tty)},fsync(stream){stream.tty.ops.fsync(stream.tty)},read(stream,buffer,offset,length,pos){if(!stream.tty||!stream.tty.ops.get_char){throw new FS.ErrnoError(60)}var bytesRead=0;for(var i=0;i0){out(UTF8ArrayToString(tty.output));tty.output=[]}},ioctl_tcgets(tty){return{c_iflag:25856,c_oflag:5,c_cflag:191,c_lflag:35387,c_cc:[3,28,127,21,4,0,1,0,17,19,26,0,18,15,23,22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}},ioctl_tcsets(tty,optional_actions,data){return 0},ioctl_tiocgwinsz(tty){return[24,80]}},default_tty1_ops:{put_char(tty,val){if(val===null||val===10){err(UTF8ArrayToString(tty.output));tty.output=[]}else{if(val!=0)tty.output.push(val)}},fsync(tty){if(tty.output&&tty.output.length>0){err(UTF8ArrayToString(tty.output));tty.output=[]}}}};var zeroMemory=(address,size)=>{HEAPU8.fill(0,address,address+size)};var alignMemory=(size,alignment)=>{assert(alignment,"alignment argument is required");return Math.ceil(size/alignment)*alignment};var mmapAlloc=size=>{size=alignMemory(size,65536);var ptr=_emscripten_builtin_memalign(65536,size);if(ptr)zeroMemory(ptr,size);return ptr};var MEMFS={ops_table:null,mount(mount){return MEMFS.createNode(null,"/",16384|511,0)},createNode(parent,name,mode,dev){if(FS.isBlkdev(mode)||FS.isFIFO(mode)){throw new FS.ErrnoError(63)}MEMFS.ops_table||={dir:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,lookup:MEMFS.node_ops.lookup,mknod:MEMFS.node_ops.mknod,rename:MEMFS.node_ops.rename,unlink:MEMFS.node_ops.unlink,rmdir:MEMFS.node_ops.rmdir,readdir:MEMFS.node_ops.readdir,symlink:MEMFS.node_ops.symlink},stream:{llseek:MEMFS.stream_ops.llseek}},file:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:{llseek:MEMFS.stream_ops.llseek,read:MEMFS.stream_ops.read,write:MEMFS.stream_ops.write,allocate:MEMFS.stream_ops.allocate,mmap:MEMFS.stream_ops.mmap,msync:MEMFS.stream_ops.msync}},link:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,readlink:MEMFS.node_ops.readlink},stream:{}},chrdev:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:FS.chrdev_stream_ops}};var node=FS.createNode(parent,name,mode,dev);if(FS.isDir(node.mode)){node.node_ops=MEMFS.ops_table.dir.node;node.stream_ops=MEMFS.ops_table.dir.stream;node.contents={}}else if(FS.isFile(node.mode)){node.node_ops=MEMFS.ops_table.file.node;node.stream_ops=MEMFS.ops_table.file.stream;node.usedBytes=0;node.contents=null}else if(FS.isLink(node.mode)){node.node_ops=MEMFS.ops_table.link.node;node.stream_ops=MEMFS.ops_table.link.stream}else if(FS.isChrdev(node.mode)){node.node_ops=MEMFS.ops_table.chrdev.node;node.stream_ops=MEMFS.ops_table.chrdev.stream}node.timestamp=Date.now();if(parent){parent.contents[name]=node;parent.timestamp=node.timestamp}return node},getFileDataAsTypedArray(node){if(!node.contents)return new Uint8Array(0);if(node.contents.subarray)return node.contents.subarray(0,node.usedBytes);return new Uint8Array(node.contents)},expandFileStorage(node,newCapacity){var prevCapacity=node.contents?node.contents.length:0;if(prevCapacity>=newCapacity)return;var CAPACITY_DOUBLING_MAX=1024*1024;newCapacity=Math.max(newCapacity,prevCapacity*(prevCapacity>>0);if(prevCapacity!=0)newCapacity=Math.max(newCapacity,256);var oldContents=node.contents;node.contents=new Uint8Array(newCapacity);if(node.usedBytes>0)node.contents.set(oldContents.subarray(0,node.usedBytes),0)},resizeFileStorage(node,newSize){if(node.usedBytes==newSize)return;if(newSize==0){node.contents=null;node.usedBytes=0}else{var oldContents=node.contents;node.contents=new Uint8Array(newSize);if(oldContents){node.contents.set(oldContents.subarray(0,Math.min(newSize,node.usedBytes)))}node.usedBytes=newSize}},node_ops:{getattr(node){var attr={};attr.dev=FS.isChrdev(node.mode)?node.id:1;attr.ino=node.id;attr.mode=node.mode;attr.nlink=1;attr.uid=0;attr.gid=0;attr.rdev=node.rdev;if(FS.isDir(node.mode)){attr.size=4096}else if(FS.isFile(node.mode)){attr.size=node.usedBytes}else if(FS.isLink(node.mode)){attr.size=node.link.length}else{attr.size=0}attr.atime=new Date(node.timestamp);attr.mtime=new Date(node.timestamp);attr.ctime=new Date(node.timestamp);attr.blksize=4096;attr.blocks=Math.ceil(attr.size/attr.blksize);return attr},setattr(node,attr){if(attr.mode!==undefined){node.mode=attr.mode}if(attr.timestamp!==undefined){node.timestamp=attr.timestamp}if(attr.size!==undefined){MEMFS.resizeFileStorage(node,attr.size)}},lookup(parent,name){throw FS.genericErrors[44]},mknod(parent,name,mode,dev){return MEMFS.createNode(parent,name,mode,dev)},rename(old_node,new_dir,new_name){if(FS.isDir(old_node.mode)){var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(new_node){for(var i in new_node.contents){throw new FS.ErrnoError(55)}}}delete old_node.parent.contents[old_node.name];old_node.parent.timestamp=Date.now();old_node.name=new_name;new_dir.contents[new_name]=old_node;new_dir.timestamp=old_node.parent.timestamp},unlink(parent,name){delete parent.contents[name];parent.timestamp=Date.now()},rmdir(parent,name){var node=FS.lookupNode(parent,name);for(var i in node.contents){throw new FS.ErrnoError(55)}delete parent.contents[name];parent.timestamp=Date.now()},readdir(node){var entries=[".",".."];for(var key of Object.keys(node.contents)){entries.push(key)}return entries},symlink(parent,newname,oldpath){var node=MEMFS.createNode(parent,newname,511|40960,0);node.link=oldpath;return node},readlink(node){if(!FS.isLink(node.mode)){throw new FS.ErrnoError(28)}return node.link}},stream_ops:{read(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=stream.node.usedBytes)return 0;var size=Math.min(stream.node.usedBytes-position,length);assert(size>=0);if(size>8&&contents.subarray){buffer.set(contents.subarray(position,position+size),offset)}else{for(var i=0;i0||position+length{var dep=!noRunDep?getUniqueRunDependency(`al ${url}`):"";readAsync(url).then(arrayBuffer=>{assert(arrayBuffer,`Loading data file "${url}" failed (no arrayBuffer).`);onload(new Uint8Array(arrayBuffer));if(dep)removeRunDependency(dep)},err=>{if(onerror){onerror()}else{throw`Loading data file "${url}" failed.`}});if(dep)addRunDependency(dep)};var FS_createDataFile=(parent,name,fileData,canRead,canWrite,canOwn)=>{FS.createDataFile(parent,name,fileData,canRead,canWrite,canOwn)};var preloadPlugins=Module["preloadPlugins"]||[];var FS_handledByPreloadPlugin=(byteArray,fullname,finish,onerror)=>{if(typeof Browser!="undefined")Browser.init();var handled=false;preloadPlugins.forEach(plugin=>{if(handled)return;if(plugin["canHandle"](fullname)){plugin["handle"](byteArray,fullname,finish,onerror);handled=true}});return handled};var FS_createPreloadedFile=(parent,name,url,canRead,canWrite,onload,onerror,dontCreateFile,canOwn,preFinish)=>{var fullname=name?PATH_FS.resolve(PATH.join2(parent,name)):parent;var dep=getUniqueRunDependency(`cp ${fullname}`);function processData(byteArray){function finish(byteArray){preFinish?.();if(!dontCreateFile){FS_createDataFile(parent,name,byteArray,canRead,canWrite,canOwn)}onload?.();removeRunDependency(dep)}if(FS_handledByPreloadPlugin(byteArray,fullname,finish,()=>{onerror?.();removeRunDependency(dep)})){return}finish(byteArray)}addRunDependency(dep);if(typeof url=="string"){asyncLoad(url,processData,onerror)}else{processData(url)}};var FS_modeStringToFlags=str=>{var flagModes={r:0,"r+":2,w:512|64|1,"w+":512|64|2,a:1024|64|1,"a+":1024|64|2};var flags=flagModes[str];if(typeof flags=="undefined"){throw new Error(`Unknown file open mode: ${str}`)}return flags};var FS_getMode=(canRead,canWrite)=>{var mode=0;if(canRead)mode|=292|73;if(canWrite)mode|=146;return mode};var strError=errno=>UTF8ToString(_strerror(errno));var ERRNO_CODES={EPERM:63,ENOENT:44,ESRCH:71,EINTR:27,EIO:29,ENXIO:60,E2BIG:1,ENOEXEC:45,EBADF:8,ECHILD:12,EAGAIN:6,EWOULDBLOCK:6,ENOMEM:48,EACCES:2,EFAULT:21,ENOTBLK:105,EBUSY:10,EEXIST:20,EXDEV:75,ENODEV:43,ENOTDIR:54,EISDIR:31,EINVAL:28,ENFILE:41,EMFILE:33,ENOTTY:59,ETXTBSY:74,EFBIG:22,ENOSPC:51,ESPIPE:70,EROFS:69,EMLINK:34,EPIPE:64,EDOM:18,ERANGE:68,ENOMSG:49,EIDRM:24,ECHRNG:106,EL2NSYNC:156,EL3HLT:107,EL3RST:108,ELNRNG:109,EUNATCH:110,ENOCSI:111,EL2HLT:112,EDEADLK:16,ENOLCK:46,EBADE:113,EBADR:114,EXFULL:115,ENOANO:104,EBADRQC:103,EBADSLT:102,EDEADLOCK:16,EBFONT:101,ENOSTR:100,ENODATA:116,ETIME:117,ENOSR:118,ENONET:119,ENOPKG:120,EREMOTE:121,ENOLINK:47,EADV:122,ESRMNT:123,ECOMM:124,EPROTO:65,EMULTIHOP:36,EDOTDOT:125,EBADMSG:9,ENOTUNIQ:126,EBADFD:127,EREMCHG:128,ELIBACC:129,ELIBBAD:130,ELIBSCN:131,ELIBMAX:132,ELIBEXEC:133,ENOSYS:52,ENOTEMPTY:55,ENAMETOOLONG:37,ELOOP:32,EOPNOTSUPP:138,EPFNOSUPPORT:139,ECONNRESET:15,ENOBUFS:42,EAFNOSUPPORT:5,EPROTOTYPE:67,ENOTSOCK:57,ENOPROTOOPT:50,ESHUTDOWN:140,ECONNREFUSED:14,EADDRINUSE:3,ECONNABORTED:13,ENETUNREACH:40,ENETDOWN:38,ETIMEDOUT:73,EHOSTDOWN:142,EHOSTUNREACH:23,EINPROGRESS:26,EALREADY:7,EDESTADDRREQ:17,EMSGSIZE:35,EPROTONOSUPPORT:66,ESOCKTNOSUPPORT:137,EADDRNOTAVAIL:4,ENETRESET:39,EISCONN:30,ENOTCONN:53,ETOOMANYREFS:141,EUSERS:136,EDQUOT:19,ESTALE:72,ENOTSUP:138,ENOMEDIUM:148,EILSEQ:25,EOVERFLOW:61,ECANCELED:11,ENOTRECOVERABLE:56,EOWNERDEAD:62,ESTRPIPE:135};var FS={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,ErrnoError:class extends Error{constructor(errno){super(runtimeInitialized?strError(errno):"");this.name="ErrnoError";this.errno=errno;for(var key in ERRNO_CODES){if(ERRNO_CODES[key]===errno){this.code=key;break}}}},genericErrors:{},filesystems:null,syncFSRequests:0,readFiles:{},FSStream:class{constructor(){this.shared={}}get object(){return this.node}set object(val){this.node=val}get isRead(){return(this.flags&2097155)!==1}get isWrite(){return(this.flags&2097155)!==0}get isAppend(){return this.flags&1024}get flags(){return this.shared.flags}set flags(val){this.shared.flags=val}get position(){return this.shared.position}set position(val){this.shared.position=val}},FSNode:class{constructor(parent,name,mode,rdev){if(!parent){parent=this}this.parent=parent;this.mount=parent.mount;this.mounted=null;this.id=FS.nextInode++;this.name=name;this.mode=mode;this.node_ops={};this.stream_ops={};this.rdev=rdev;this.readMode=292|73;this.writeMode=146}get read(){return(this.mode&this.readMode)===this.readMode}set read(val){val?this.mode|=this.readMode:this.mode&=~this.readMode}get write(){return(this.mode&this.writeMode)===this.writeMode}set write(val){val?this.mode|=this.writeMode:this.mode&=~this.writeMode}get isFolder(){return FS.isDir(this.mode)}get isDevice(){return FS.isChrdev(this.mode)}},lookupPath(path,opts={}){path=PATH_FS.resolve(path);if(!path)return{path:"",node:null};var defaults={follow_mount:true,recurse_count:0};opts=Object.assign(defaults,opts);if(opts.recurse_count>8){throw new FS.ErrnoError(32)}var parts=path.split("/").filter(p=>!!p);var current=FS.root;var current_path="/";for(var i=0;i40){throw new FS.ErrnoError(32)}}}}return{path:current_path,node:current}},getPath(node){var path;while(true){if(FS.isRoot(node)){var mount=node.mount.mountpoint;if(!path)return mount;return mount[mount.length-1]!=="/"?`${mount}/${path}`:mount+path}path=path?`${node.name}/${path}`:node.name;node=node.parent}},hashName(parentid,name){var hash=0;for(var i=0;i>>0)%FS.nameTable.length},hashAddNode(node){var hash=FS.hashName(node.parent.id,node.name);node.name_next=FS.nameTable[hash];FS.nameTable[hash]=node},hashRemoveNode(node){var hash=FS.hashName(node.parent.id,node.name);if(FS.nameTable[hash]===node){FS.nameTable[hash]=node.name_next}else{var current=FS.nameTable[hash];while(current){if(current.name_next===node){current.name_next=node.name_next;break}current=current.name_next}}},lookupNode(parent,name){var errCode=FS.mayLookup(parent);if(errCode){throw new FS.ErrnoError(errCode)}var hash=FS.hashName(parent.id,name);for(var node=FS.nameTable[hash];node;node=node.name_next){var nodeName=node.name;if(node.parent.id===parent.id&&nodeName===name){return node}}return FS.lookup(parent,name)},createNode(parent,name,mode,rdev){assert(typeof parent=="object");var node=new FS.FSNode(parent,name,mode,rdev);FS.hashAddNode(node);return node},destroyNode(node){FS.hashRemoveNode(node)},isRoot(node){return node===node.parent},isMountpoint(node){return!!node.mounted},isFile(mode){return(mode&61440)===32768},isDir(mode){return(mode&61440)===16384},isLink(mode){return(mode&61440)===40960},isChrdev(mode){return(mode&61440)===8192},isBlkdev(mode){return(mode&61440)===24576},isFIFO(mode){return(mode&61440)===4096},isSocket(mode){return(mode&49152)===49152},flagsToPermissionString(flag){var perms=["r","w","rw"][flag&3];if(flag&512){perms+="w"}return perms},nodePermissions(node,perms){if(FS.ignorePermissions){return 0}if(perms.includes("r")&&!(node.mode&292)){return 2}else if(perms.includes("w")&&!(node.mode&146)){return 2}else if(perms.includes("x")&&!(node.mode&73)){return 2}return 0},mayLookup(dir){if(!FS.isDir(dir.mode))return 54;var errCode=FS.nodePermissions(dir,"x");if(errCode)return errCode;if(!dir.node_ops.lookup)return 2;return 0},mayCreate(dir,name){try{var node=FS.lookupNode(dir,name);return 20}catch(e){}return FS.nodePermissions(dir,"wx")},mayDelete(dir,name,isdir){var node;try{node=FS.lookupNode(dir,name)}catch(e){return e.errno}var errCode=FS.nodePermissions(dir,"wx");if(errCode){return errCode}if(isdir){if(!FS.isDir(node.mode)){return 54}if(FS.isRoot(node)||FS.getPath(node)===FS.cwd()){return 10}}else{if(FS.isDir(node.mode)){return 31}}return 0},mayOpen(node,flags){if(!node){return 44}if(FS.isLink(node.mode)){return 32}else if(FS.isDir(node.mode)){if(FS.flagsToPermissionString(flags)!=="r"||flags&512){return 31}}return FS.nodePermissions(node,FS.flagsToPermissionString(flags))},MAX_OPEN_FDS:4096,nextfd(){for(var fd=0;fd<=FS.MAX_OPEN_FDS;fd++){if(!FS.streams[fd]){return fd}}throw new FS.ErrnoError(33)},getStreamChecked(fd){var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(8)}return stream},getStream:fd=>FS.streams[fd],createStream(stream,fd=-1){assert(fd>=-1);stream=Object.assign(new FS.FSStream,stream);if(fd==-1){fd=FS.nextfd()}stream.fd=fd;FS.streams[fd]=stream;return stream},closeStream(fd){FS.streams[fd]=null},dupStream(origStream,fd=-1){var stream=FS.createStream(origStream,fd);stream.stream_ops?.dup?.(stream);return stream},chrdev_stream_ops:{open(stream){var device=FS.getDevice(stream.node.rdev);stream.stream_ops=device.stream_ops;stream.stream_ops.open?.(stream)},llseek(){throw new FS.ErrnoError(70)}},major:dev=>dev>>8,minor:dev=>dev&255,makedev:(ma,mi)=>ma<<8|mi,registerDevice(dev,ops){FS.devices[dev]={stream_ops:ops}},getDevice:dev=>FS.devices[dev],getMounts(mount){var mounts=[];var check=[mount];while(check.length){var m=check.pop();mounts.push(m);check.push(...m.mounts)}return mounts},syncfs(populate,callback){if(typeof populate=="function"){callback=populate;populate=false}FS.syncFSRequests++;if(FS.syncFSRequests>1){err(`warning: ${FS.syncFSRequests} FS.syncfs operations in flight at once, probably just doing extra work`)}var mounts=FS.getMounts(FS.root.mount);var completed=0;function doCallback(errCode){assert(FS.syncFSRequests>0);FS.syncFSRequests--;return callback(errCode)}function done(errCode){if(errCode){if(!done.errored){done.errored=true;return doCallback(errCode)}return}if(++completed>=mounts.length){doCallback(null)}}mounts.forEach(mount=>{if(!mount.type.syncfs){return done(null)}mount.type.syncfs(mount,populate,done)})},mount(type,opts,mountpoint){if(typeof type=="string"){throw type}var root=mountpoint==="/";var pseudo=!mountpoint;var node;if(root&&FS.root){throw new FS.ErrnoError(10)}else if(!root&&!pseudo){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});mountpoint=lookup.path;node=lookup.node;if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}if(!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}}var mount={type,opts,mountpoint,mounts:[]};var mountRoot=type.mount(mount);mountRoot.mount=mount;mount.root=mountRoot;if(root){FS.root=mountRoot}else if(node){node.mounted=mount;if(node.mount){node.mount.mounts.push(mount)}}return mountRoot},unmount(mountpoint){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});if(!FS.isMountpoint(lookup.node)){throw new FS.ErrnoError(28)}var node=lookup.node;var mount=node.mounted;var mounts=FS.getMounts(mount);Object.keys(FS.nameTable).forEach(hash=>{var current=FS.nameTable[hash];while(current){var next=current.name_next;if(mounts.includes(current.mount)){FS.destroyNode(current)}current=next}});node.mounted=null;var idx=node.mount.mounts.indexOf(mount);assert(idx!==-1);node.mount.mounts.splice(idx,1)},lookup(parent,name){return parent.node_ops.lookup(parent,name)},mknod(path,mode,dev){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);if(!name||name==="."||name===".."){throw new FS.ErrnoError(28)}var errCode=FS.mayCreate(parent,name);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.mknod){throw new FS.ErrnoError(63)}return parent.node_ops.mknod(parent,name,mode,dev)},create(path,mode){mode=mode!==undefined?mode:438;mode&=4095;mode|=32768;return FS.mknod(path,mode,0)},mkdir(path,mode){mode=mode!==undefined?mode:511;mode&=511|512;mode|=16384;return FS.mknod(path,mode,0)},mkdirTree(path,mode){var dirs=path.split("/");var d="";for(var i=0;i=0);if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.read){throw new FS.ErrnoError(28)}var seeking=typeof position!="undefined";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesRead=stream.stream_ops.read(stream,buffer,offset,length,position);if(!seeking)stream.position+=bytesRead;return bytesRead},write(stream,buffer,offset,length,position,canOwn){assert(offset>=0);if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.write){throw new FS.ErrnoError(28)}if(stream.seekable&&stream.flags&1024){FS.llseek(stream,0,2)}var seeking=typeof position!="undefined";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesWritten=stream.stream_ops.write(stream,buffer,offset,length,position,canOwn);if(!seeking)stream.position+=bytesWritten;return bytesWritten},allocate(stream,offset,length){if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(offset<0||length<=0){throw new FS.ErrnoError(28)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(8)}if(!FS.isFile(stream.node.mode)&&!FS.isDir(stream.node.mode)){throw new FS.ErrnoError(43)}if(!stream.stream_ops.allocate){throw new FS.ErrnoError(138)}stream.stream_ops.allocate(stream,offset,length)},mmap(stream,length,position,prot,flags){if((prot&2)!==0&&(flags&2)===0&&(stream.flags&2097155)!==2){throw new FS.ErrnoError(2)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(2)}if(!stream.stream_ops.mmap){throw new FS.ErrnoError(43)}if(!length){throw new FS.ErrnoError(28)}return stream.stream_ops.mmap(stream,length,position,prot,flags)},msync(stream,buffer,offset,length,mmapFlags){assert(offset>=0);if(!stream.stream_ops.msync){return 0}return stream.stream_ops.msync(stream,buffer,offset,length,mmapFlags)},ioctl(stream,cmd,arg){if(!stream.stream_ops.ioctl){throw new FS.ErrnoError(59)}return stream.stream_ops.ioctl(stream,cmd,arg)},readFile(path,opts={}){opts.flags=opts.flags||0;opts.encoding=opts.encoding||"binary";if(opts.encoding!=="utf8"&&opts.encoding!=="binary"){throw new Error(`Invalid encoding type "${opts.encoding}"`)}var ret;var stream=FS.open(path,opts.flags);var stat=FS.stat(path);var length=stat.size;var buf=new Uint8Array(length);FS.read(stream,buf,0,length,0);if(opts.encoding==="utf8"){ret=UTF8ArrayToString(buf)}else if(opts.encoding==="binary"){ret=buf}FS.close(stream);return ret},writeFile(path,data,opts={}){opts.flags=opts.flags||577;var stream=FS.open(path,opts.flags,opts.mode);if(typeof data=="string"){var buf=new Uint8Array(lengthBytesUTF8(data)+1);var actualNumBytes=stringToUTF8Array(data,buf,0,buf.length);FS.write(stream,buf,0,actualNumBytes,undefined,opts.canOwn)}else if(ArrayBuffer.isView(data)){FS.write(stream,data,0,data.byteLength,undefined,opts.canOwn)}else{throw new Error("Unsupported data type")}FS.close(stream)},cwd:()=>FS.currentPath,chdir(path){var lookup=FS.lookupPath(path,{follow:true});if(lookup.node===null){throw new FS.ErrnoError(44)}if(!FS.isDir(lookup.node.mode)){throw new FS.ErrnoError(54)}var errCode=FS.nodePermissions(lookup.node,"x");if(errCode){throw new FS.ErrnoError(errCode)}FS.currentPath=lookup.path},createDefaultDirectories(){FS.mkdir("/tmp");FS.mkdir("/home");FS.mkdir("/home/web_user")},createDefaultDevices(){FS.mkdir("/dev");FS.registerDevice(FS.makedev(1,3),{read:()=>0,write:(stream,buffer,offset,length,pos)=>length});FS.mkdev("/dev/null",FS.makedev(1,3));TTY.register(FS.makedev(5,0),TTY.default_tty_ops);TTY.register(FS.makedev(6,0),TTY.default_tty1_ops);FS.mkdev("/dev/tty",FS.makedev(5,0));FS.mkdev("/dev/tty1",FS.makedev(6,0));var randomBuffer=new Uint8Array(1024),randomLeft=0;var randomByte=()=>{if(randomLeft===0){randomLeft=randomFill(randomBuffer).byteLength}return randomBuffer[--randomLeft]};FS.createDevice("/dev","random",randomByte);FS.createDevice("/dev","urandom",randomByte);FS.mkdir("/dev/shm");FS.mkdir("/dev/shm/tmp")},createSpecialDirectories(){FS.mkdir("/proc");var proc_self=FS.mkdir("/proc/self");FS.mkdir("/proc/self/fd");FS.mount({mount(){var node=FS.createNode(proc_self,"fd",16384|511,73);node.node_ops={lookup(parent,name){var fd=+name;var stream=FS.getStreamChecked(fd);var ret={parent:null,mount:{mountpoint:"fake"},node_ops:{readlink:()=>stream.path}};ret.parent=ret;return ret}};return node}},{},"/proc/self/fd")},createStandardStreams(input,output,error){if(input){FS.createDevice("/dev","stdin",input)}else{FS.symlink("/dev/tty","/dev/stdin")}if(output){FS.createDevice("/dev","stdout",null,output)}else{FS.symlink("/dev/tty","/dev/stdout")}if(error){FS.createDevice("/dev","stderr",null,error)}else{FS.symlink("/dev/tty1","/dev/stderr")}var stdin=FS.open("/dev/stdin",0);var stdout=FS.open("/dev/stdout",1);var stderr=FS.open("/dev/stderr",1);assert(stdin.fd===0,`invalid handle for stdin (${stdin.fd})`);assert(stdout.fd===1,`invalid handle for stdout (${stdout.fd})`);assert(stderr.fd===2,`invalid handle for stderr (${stderr.fd})`)},staticInit(){[44].forEach(code=>{FS.genericErrors[code]=new FS.ErrnoError(code);FS.genericErrors[code].stack=""});FS.nameTable=new Array(4096);FS.mount(MEMFS,{},"/");FS.createDefaultDirectories();FS.createDefaultDevices();FS.createSpecialDirectories();FS.filesystems={MEMFS}},init(input,output,error){assert(!FS.initialized,"FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)");FS.initialized=true;input??=Module["stdin"];output??=Module["stdout"];error??=Module["stderr"];FS.createStandardStreams(input,output,error)},quit(){FS.initialized=false;_fflush(0);for(var i=0;ithis.length-1||idx<0){return undefined}var chunkOffset=idx%this.chunkSize;var chunkNum=idx/this.chunkSize|0;return this.getter(chunkNum)[chunkOffset]}setDataGetter(getter){this.getter=getter}cacheLength(){var xhr=new XMLHttpRequest;xhr.open("HEAD",url,false);xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);var datalength=Number(xhr.getResponseHeader("Content-length"));var header;var hasByteServing=(header=xhr.getResponseHeader("Accept-Ranges"))&&header==="bytes";var usesGzip=(header=xhr.getResponseHeader("Content-Encoding"))&&header==="gzip";var chunkSize=1024*1024;if(!hasByteServing)chunkSize=datalength;var doXHR=(from,to)=>{if(from>to)throw new Error("invalid range ("+from+", "+to+") or no bytes requested!");if(to>datalength-1)throw new Error("only "+datalength+" bytes available! programmer error!");var xhr=new XMLHttpRequest;xhr.open("GET",url,false);if(datalength!==chunkSize)xhr.setRequestHeader("Range","bytes="+from+"-"+to);xhr.responseType="arraybuffer";if(xhr.overrideMimeType){xhr.overrideMimeType("text/plain; charset=x-user-defined")}xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);if(xhr.response!==undefined){return new Uint8Array(xhr.response||[])}return intArrayFromString(xhr.responseText||"",true)};var lazyArray=this;lazyArray.setDataGetter(chunkNum=>{var start=chunkNum*chunkSize;var end=(chunkNum+1)*chunkSize-1;end=Math.min(end,datalength-1);if(typeof lazyArray.chunks[chunkNum]=="undefined"){lazyArray.chunks[chunkNum]=doXHR(start,end)}if(typeof lazyArray.chunks[chunkNum]=="undefined")throw new Error("doXHR failed!");return lazyArray.chunks[chunkNum]});if(usesGzip||!datalength){chunkSize=datalength=1;datalength=this.getter(0).length;chunkSize=datalength;out("LazyFiles on gzip forces download of the whole file when length is accessed")}this._length=datalength;this._chunkSize=chunkSize;this.lengthKnown=true}get length(){if(!this.lengthKnown){this.cacheLength()}return this._length}get chunkSize(){if(!this.lengthKnown){this.cacheLength()}return this._chunkSize}}if(typeof XMLHttpRequest!="undefined"){if(!ENVIRONMENT_IS_WORKER)throw"Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc";var lazyArray=new LazyUint8Array;var properties={isDevice:false,contents:lazyArray}}else{var properties={isDevice:false,url}}var node=FS.createFile(parent,name,properties,canRead,canWrite);if(properties.contents){node.contents=properties.contents}else if(properties.url){node.contents=null;node.url=properties.url}Object.defineProperties(node,{usedBytes:{get:function(){return this.contents.length}}});var stream_ops={};var keys=Object.keys(node.stream_ops);keys.forEach(key=>{var fn=node.stream_ops[key];stream_ops[key]=(...args)=>{FS.forceLoadFile(node);return fn(...args)}});function writeChunks(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=contents.length)return 0;var size=Math.min(contents.length-position,length);assert(size>=0);if(contents.slice){for(var i=0;i{FS.forceLoadFile(node);return writeChunks(stream,buffer,offset,length,position)};stream_ops.mmap=(stream,length,position,prot,flags)=>{FS.forceLoadFile(node);var ptr=mmapAlloc(length);if(!ptr){throw new FS.ErrnoError(48)}writeChunks(stream,HEAP8,ptr,length,position);return{ptr,allocated:true}};node.stream_ops=stream_ops;return node},absolutePath(){abort("FS.absolutePath has been removed; use PATH_FS.resolve instead")},createFolder(){abort("FS.createFolder has been removed; use FS.mkdir instead")},createLink(){abort("FS.createLink has been removed; use FS.symlink instead")},joinPath(){abort("FS.joinPath has been removed; use PATH.join instead")},mmapAlloc(){abort("FS.mmapAlloc has been replaced by the top level function mmapAlloc")},standardizePath(){abort("FS.standardizePath has been removed; use PATH.normalize instead")}};var SYSCALLS={DEFAULT_POLLMASK:5,calculateAt(dirfd,path,allowEmpty){if(PATH.isAbs(path)){return path}var dir;if(dirfd===-100){dir=FS.cwd()}else{var dirstream=SYSCALLS.getStreamFromFD(dirfd);dir=dirstream.path}if(path.length==0){if(!allowEmpty){throw new FS.ErrnoError(44)}return dir}return PATH.join2(dir,path)},doStat(func,path,buf){var stat=func(path);HEAP32[buf>>2]=stat.dev;checkInt32(stat.dev);HEAP32[buf+4>>2]=stat.mode;checkInt32(stat.mode);HEAPU32[buf+8>>2]=stat.nlink;checkInt32(stat.nlink);HEAP32[buf+12>>2]=stat.uid;checkInt32(stat.uid);HEAP32[buf+16>>2]=stat.gid;checkInt32(stat.gid);HEAP32[buf+20>>2]=stat.rdev;checkInt32(stat.rdev);tempI64=[stat.size>>>0,(tempDouble=stat.size,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+24>>2]=tempI64[0],HEAP32[buf+28>>2]=tempI64[1];checkInt64(stat.size);HEAP32[buf+32>>2]=4096;checkInt32(4096);HEAP32[buf+36>>2]=stat.blocks;checkInt32(stat.blocks);var atime=stat.atime.getTime();var mtime=stat.mtime.getTime();var ctime=stat.ctime.getTime();tempI64=[Math.floor(atime/1e3)>>>0,(tempDouble=Math.floor(atime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+40>>2]=tempI64[0],HEAP32[buf+44>>2]=tempI64[1];checkInt64(Math.floor(atime/1e3));HEAPU32[buf+48>>2]=atime%1e3*1e3*1e3;checkInt32(atime%1e3*1e3*1e3);tempI64=[Math.floor(mtime/1e3)>>>0,(tempDouble=Math.floor(mtime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+56>>2]=tempI64[0],HEAP32[buf+60>>2]=tempI64[1];checkInt64(Math.floor(mtime/1e3));HEAPU32[buf+64>>2]=mtime%1e3*1e3*1e3;checkInt32(mtime%1e3*1e3*1e3);tempI64=[Math.floor(ctime/1e3)>>>0,(tempDouble=Math.floor(ctime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+72>>2]=tempI64[0],HEAP32[buf+76>>2]=tempI64[1];checkInt64(Math.floor(ctime/1e3));HEAPU32[buf+80>>2]=ctime%1e3*1e3*1e3;checkInt32(ctime%1e3*1e3*1e3);tempI64=[stat.ino>>>0,(tempDouble=stat.ino,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+88>>2]=tempI64[0],HEAP32[buf+92>>2]=tempI64[1];checkInt64(stat.ino);return 0},doMsync(addr,stream,len,flags,offset){if(!FS.isFile(stream.node.mode)){throw new FS.ErrnoError(43)}if(flags&2){return 0}var buffer=HEAPU8.slice(addr,addr+len);FS.msync(stream,buffer,offset,len,flags)},getStreamFromFD(fd){var stream=FS.getStreamChecked(fd);return stream},varargs:undefined,getStr(ptr){var ret=UTF8ToString(ptr);return ret}};function ___syscall_faccessat(dirfd,path,amode,flags){try{path=SYSCALLS.getStr(path);assert(flags===0||flags==512);path=SYSCALLS.calculateAt(dirfd,path);if(amode&~7){return-28}var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;if(!node){return-44}var perms="";if(amode&4)perms+="r";if(amode&2)perms+="w";if(amode&1)perms+="x";if(perms&&FS.nodePermissions(node,perms)){return-2}return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function syscallGetVarargI(){assert(SYSCALLS.varargs!=undefined);var ret=HEAP32[+SYSCALLS.varargs>>2];SYSCALLS.varargs+=4;return ret}var syscallGetVarargP=syscallGetVarargI;function ___syscall_fcntl64(fd,cmd,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(cmd){case 0:{var arg=syscallGetVarargI();if(arg<0){return-28}while(FS.streams[arg]){arg++}var newStream;newStream=FS.dupStream(stream,arg);return newStream.fd}case 1:case 2:return 0;case 3:return stream.flags;case 4:{var arg=syscallGetVarargI();stream.flags|=arg;return 0}case 12:{var arg=syscallGetVarargP();var offset=0;HEAP16[arg+offset>>1]=2;checkInt16(2);return 0}case 13:case 14:return 0}return-28}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_fstat64(fd,buf){try{var stream=SYSCALLS.getStreamFromFD(fd);return SYSCALLS.doStat(FS.stat,stream.path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var stringToUTF8=(str,outPtr,maxBytesToWrite)=>{assert(typeof maxBytesToWrite=="number","stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!");return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)};function ___syscall_getdents64(fd,dirp,count){try{var stream=SYSCALLS.getStreamFromFD(fd);stream.getdents||=FS.readdir(stream.path);var struct_size=280;var pos=0;var off=FS.llseek(stream,0,1);var idx=Math.floor(off/struct_size);while(idx>>0,(tempDouble=id,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[dirp+pos>>2]=tempI64[0],HEAP32[dirp+pos+4>>2]=tempI64[1];checkInt64(id);tempI64=[(idx+1)*struct_size>>>0,(tempDouble=(idx+1)*struct_size,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[dirp+pos+8>>2]=tempI64[0],HEAP32[dirp+pos+12>>2]=tempI64[1];checkInt64((idx+1)*struct_size);HEAP16[dirp+pos+16>>1]=280;checkInt16(280);HEAP8[dirp+pos+18]=type;checkInt8(type);stringToUTF8(name,dirp+pos+19,256);pos+=struct_size;idx+=1}FS.llseek(stream,idx*struct_size,0);return pos}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_ioctl(fd,op,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(op){case 21509:{if(!stream.tty)return-59;return 0}case 21505:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tcgets){var termios=stream.tty.ops.ioctl_tcgets(stream);var argp=syscallGetVarargP();HEAP32[argp>>2]=termios.c_iflag||0;checkInt32(termios.c_iflag||0);HEAP32[argp+4>>2]=termios.c_oflag||0;checkInt32(termios.c_oflag||0);HEAP32[argp+8>>2]=termios.c_cflag||0;checkInt32(termios.c_cflag||0);HEAP32[argp+12>>2]=termios.c_lflag||0;checkInt32(termios.c_lflag||0);for(var i=0;i<32;i++){HEAP8[argp+i+17]=termios.c_cc[i]||0;checkInt8(termios.c_cc[i]||0)}return 0}return 0}case 21510:case 21511:case 21512:{if(!stream.tty)return-59;return 0}case 21506:case 21507:case 21508:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tcsets){var argp=syscallGetVarargP();var c_iflag=HEAP32[argp>>2];var c_oflag=HEAP32[argp+4>>2];var c_cflag=HEAP32[argp+8>>2];var c_lflag=HEAP32[argp+12>>2];var c_cc=[];for(var i=0;i<32;i++){c_cc.push(HEAP8[argp+i+17])}return stream.tty.ops.ioctl_tcsets(stream.tty,op,{c_iflag,c_oflag,c_cflag,c_lflag,c_cc})}return 0}case 21519:{if(!stream.tty)return-59;var argp=syscallGetVarargP();HEAP32[argp>>2]=0;checkInt32(0);return 0}case 21520:{if(!stream.tty)return-59;return-28}case 21531:{var argp=syscallGetVarargP();return FS.ioctl(stream,op,argp)}case 21523:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tiocgwinsz){var winsize=stream.tty.ops.ioctl_tiocgwinsz(stream.tty);var argp=syscallGetVarargP();HEAP16[argp>>1]=winsize[0];checkInt16(winsize[0]);HEAP16[argp+2>>1]=winsize[1];checkInt16(winsize[1])}return 0}case 21524:{if(!stream.tty)return-59;return 0}case 21515:{if(!stream.tty)return-59;return 0}default:return-28}}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_lstat64(path,buf){try{path=SYSCALLS.getStr(path);return SYSCALLS.doStat(FS.lstat,path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_mkdirat(dirfd,path,mode){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);path=PATH.normalize(path);if(path[path.length-1]==="/")path=path.substr(0,path.length-1);FS.mkdir(path,mode,0);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_newfstatat(dirfd,path,buf,flags){try{path=SYSCALLS.getStr(path);var nofollow=flags&256;var allowEmpty=flags&4096;flags=flags&~6400;assert(!flags,`unknown flags in __syscall_newfstatat: ${flags}`);path=SYSCALLS.calculateAt(dirfd,path,allowEmpty);return SYSCALLS.doStat(nofollow?FS.lstat:FS.stat,path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_openat(dirfd,path,flags,varargs){SYSCALLS.varargs=varargs;try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);var mode=varargs?syscallGetVarargI():0;return FS.open(path,flags,mode).fd}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_rmdir(path){try{path=SYSCALLS.getStr(path);FS.rmdir(path);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_stat64(path,buf){try{path=SYSCALLS.getStr(path);return SYSCALLS.doStat(FS.stat,path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_unlinkat(dirfd,path,flags){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);if(flags===0){FS.unlink(path)}else if(flags===512){FS.rmdir(path)}else{abort("Invalid flags passed to unlinkat")}return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var __abort_js=()=>{abort("native code called abort()")};var nowIsMonotonic=1;var __emscripten_get_now_is_monotonic=()=>nowIsMonotonic;var __emscripten_memcpy_js=(dest,src,num)=>HEAPU8.copyWithin(dest,src,src+num);var __emscripten_runtime_keepalive_clear=()=>{noExitRuntime=false;runtimeKeepaliveCounter=0};var __emscripten_throw_longjmp=()=>{throw Infinity};var convertI32PairToI53Checked=(lo,hi)=>{assert(lo==lo>>>0||lo==(lo|0));assert(hi===(hi|0));return hi+2097152>>>0<4194305-!!lo?(lo>>>0)+hi*4294967296:NaN};function __mmap_js(len,prot,flags,fd,offset_low,offset_high,allocated,addr){var offset=convertI32PairToI53Checked(offset_low,offset_high);try{if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);var res=FS.mmap(stream,len,offset,prot,flags);var ptr=res.ptr;HEAP32[allocated>>2]=res.allocated;checkInt32(res.allocated);HEAPU32[addr>>2]=ptr;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function __munmap_js(addr,len,prot,flags,fd,offset_low,offset_high){var offset=convertI32PairToI53Checked(offset_low,offset_high);try{var stream=SYSCALLS.getStreamFromFD(fd);if(prot&2){SYSCALLS.doMsync(addr,stream,len,flags,offset)}}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var __tzset_js=(timezone,daylight,std_name,dst_name)=>{var currentYear=(new Date).getFullYear();var winter=new Date(currentYear,0,1);var summer=new Date(currentYear,6,1);var winterOffset=winter.getTimezoneOffset();var summerOffset=summer.getTimezoneOffset();var stdTimezoneOffset=Math.max(winterOffset,summerOffset);HEAPU32[timezone>>2]=stdTimezoneOffset*60;checkInt32(stdTimezoneOffset*60);HEAP32[daylight>>2]=Number(winterOffset!=summerOffset);checkInt32(Number(winterOffset!=summerOffset));var extractZone=timezoneOffset=>{var sign=timezoneOffset>=0?"-":"+";var absOffset=Math.abs(timezoneOffset);var hours=String(Math.floor(absOffset/60)).padStart(2,"0");var minutes=String(absOffset%60).padStart(2,"0");return`UTC${sign}${hours}${minutes}`};var winterName=extractZone(winterOffset);var summerName=extractZone(summerOffset);assert(winterName);assert(summerName);assert(lengthBytesUTF8(winterName)<=16,`timezone name truncated to fit in TZNAME_MAX (${winterName})`);assert(lengthBytesUTF8(summerName)<=16,`timezone name truncated to fit in TZNAME_MAX (${summerName})`);if(summerOffsetDate.now();var getHeapMax=()=>2147483648;var _emscripten_get_heap_max=()=>getHeapMax();var _emscripten_get_now=()=>performance.now();var growMemory=size=>{var b=wasmMemory.buffer;var pages=(size-b.byteLength+65535)/65536|0;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){err(`growMemory: Attempted to grow heap from ${b.byteLength} bytes to ${size} bytes, but got error: ${e}`)}};var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;assert(requestedSize>oldSize);var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){err(`Cannot enlarge memory, requested ${requestedSize} bytes, but the limit is ${maxHeapSize} bytes!`);return false}for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignMemory(Math.max(requestedSize,overGrownHeapSize),65536));var t0=_emscripten_get_now();var replacement=growMemory(newSize);var t1=_emscripten_get_now();dbg(`Heap resize call from ${oldSize} to ${newSize} took ${t1-t0} msecs. Success: ${!!replacement}`);if(replacement){return true}}err(`Failed to grow the heap from ${oldSize} bytes to ${newSize} bytes, not enough memory!`);return false};var ENV={};var getExecutableName=()=>thisProgram||"./this.program";var getEnvStrings=()=>{if(!getEnvStrings.strings){var lang=(typeof navigator=="object"&&navigator.languages&&navigator.languages[0]||"C").replace("-","_")+".UTF-8";var env={USER:"web_user",LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:lang,_:getExecutableName()};for(var x in ENV){if(ENV[x]===undefined)delete env[x];else env[x]=ENV[x]}var strings=[];for(var x in env){strings.push(`${x}=${env[x]}`)}getEnvStrings.strings=strings}return getEnvStrings.strings};var stringToAscii=(str,buffer)=>{for(var i=0;i{var bufSize=0;getEnvStrings().forEach((string,i)=>{var ptr=environ_buf+bufSize;HEAPU32[__environ+i*4>>2]=ptr;checkInt32(ptr);stringToAscii(string,ptr);bufSize+=string.length+1});return 0};var _environ_sizes_get=(penviron_count,penviron_buf_size)=>{var strings=getEnvStrings();HEAPU32[penviron_count>>2]=strings.length;checkInt32(strings.length);var bufSize=0;strings.forEach(string=>bufSize+=string.length+1);HEAPU32[penviron_buf_size>>2]=bufSize;checkInt32(bufSize);return 0};function _fd_close(fd){try{var stream=SYSCALLS.getStreamFromFD(fd);FS.close(stream);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _fd_fdstat_get(fd,pbuf){try{var rightsBase=0;var rightsInheriting=0;var flags=0;{var stream=SYSCALLS.getStreamFromFD(fd);var type=stream.tty?2:FS.isDir(stream.mode)?3:FS.isLink(stream.mode)?7:4}HEAP8[pbuf]=type;checkInt8(type);HEAP16[pbuf+2>>1]=flags;checkInt16(flags);tempI64=[rightsBase>>>0,(tempDouble=rightsBase,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[pbuf+8>>2]=tempI64[0],HEAP32[pbuf+12>>2]=tempI64[1];checkInt64(rightsBase);tempI64=[rightsInheriting>>>0,(tempDouble=rightsInheriting,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[pbuf+16>>2]=tempI64[0],HEAP32[pbuf+20>>2]=tempI64[1];checkInt64(rightsInheriting);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var doReadv=(stream,iov,iovcnt,offset)=>{var ret=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;var curr=FS.read(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr>2]=num;checkInt32(num);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){var offset=convertI32PairToI53Checked(offset_low,offset_high);try{if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);FS.llseek(stream,offset,whence);tempI64=[stream.position>>>0,(tempDouble=stream.position,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[newOffset>>2]=tempI64[0],HEAP32[newOffset+4>>2]=tempI64[1];checkInt64(stream.position);if(stream.getdents&&offset===0&&whence===0)stream.getdents=null;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var doWritev=(stream,iov,iovcnt,offset)=>{var ret=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;var curr=FS.write(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr>2]=num;checkInt32(num);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var _getentropy=(buffer,size)=>{randomFill(HEAPU8.subarray(buffer,buffer+size));return 0};var _llvm_eh_typeid_for=type=>type;var runtimeKeepaliveCounter=0;var keepRuntimeAlive=()=>noExitRuntime||runtimeKeepaliveCounter>0;var _proc_exit=code=>{EXITSTATUS=code;if(!keepRuntimeAlive()){Module["onExit"]?.(code);ABORT=true}quit_(code,new ExitStatus(code))};var getCFunc=ident=>{var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func};var writeArrayToMemory=(array,buffer)=>{assert(array.length>=0,"writeArrayToMemory array must have a length (should be an array or typed array)");HEAP8.set(array,buffer)};var stackAlloc=sz=>__emscripten_stack_alloc(sz);var stringToUTF8OnStack=str=>{var size=lengthBytesUTF8(str)+1;var ret=stackAlloc(size);stringToUTF8(str,ret,size);return ret};var ccall=(ident,returnType,argTypes,args,opts)=>{var toC={string:str=>{var ret=0;if(str!==null&&str!==undefined&&str!==0){ret=stringToUTF8OnStack(str)}return ret},array:arr=>{var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string"){return UTF8ToString(ret)}if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;assert(returnType!=="array",'Return type should not be "array".');if(args){for(var i=0;i(...args)=>ccall(ident,returnType,argTypes,args,opts);FS.createPreloadedFile=FS_createPreloadedFile;FS.staticInit();function checkIncomingModuleAPI(){ignoredModuleProp("fetchSettings")}var wasmImports={__assert_fail:___assert_fail,__call_sighandler:___call_sighandler,__cxa_begin_catch:___cxa_begin_catch,__cxa_end_catch:___cxa_end_catch,__cxa_find_matching_catch_2:___cxa_find_matching_catch_2,__cxa_find_matching_catch_3:___cxa_find_matching_catch_3,__cxa_rethrow:___cxa_rethrow,__cxa_throw:___cxa_throw,__handle_stack_overflow:___handle_stack_overflow,__resumeException:___resumeException,__syscall_faccessat:___syscall_faccessat,__syscall_fcntl64:___syscall_fcntl64,__syscall_fstat64:___syscall_fstat64,__syscall_getdents64:___syscall_getdents64,__syscall_ioctl:___syscall_ioctl,__syscall_lstat64:___syscall_lstat64,__syscall_mkdirat:___syscall_mkdirat,__syscall_newfstatat:___syscall_newfstatat,__syscall_openat:___syscall_openat,__syscall_rmdir:___syscall_rmdir,__syscall_stat64:___syscall_stat64,__syscall_unlinkat:___syscall_unlinkat,_abort_js:__abort_js,_emscripten_get_now_is_monotonic:__emscripten_get_now_is_monotonic,_emscripten_memcpy_js:__emscripten_memcpy_js,_emscripten_runtime_keepalive_clear:__emscripten_runtime_keepalive_clear,_emscripten_throw_longjmp:__emscripten_throw_longjmp,_mmap_js:__mmap_js,_munmap_js:__munmap_js,_tzset_js:__tzset_js,emscripten_date_now:_emscripten_date_now,emscripten_get_heap_max:_emscripten_get_heap_max,emscripten_get_now:_emscripten_get_now,emscripten_resize_heap:_emscripten_resize_heap,environ_get:_environ_get,environ_sizes_get:_environ_sizes_get,fd_close:_fd_close,fd_fdstat_get:_fd_fdstat_get,fd_read:_fd_read,fd_seek:_fd_seek,fd_write:_fd_write,getentropy:_getentropy,invoke_d,invoke_diii,invoke_fi,invoke_fif,invoke_fifff,invoke_fii,invoke_fiii,invoke_fiiii,invoke_fiiiiii,invoke_fiiiiiii,invoke_fij,invoke_i,invoke_idiii,invoke_ii,invoke_iif,invoke_iifi,invoke_iifii,invoke_iifiiiii,invoke_iii,invoke_iiid,invoke_iiidii,invoke_iiif,invoke_iiiffi,invoke_iiii,invoke_iiiidi,invoke_iiiiffifffffffi,invoke_iiiifiii,invoke_iiiii,invoke_iiiiif,invoke_iiiiifi,invoke_iiiiii,invoke_iiiiiifi,invoke_iiiiiififiiiififiiiiiiiiiiiiiiiiiiii,invoke_iiiiiii,invoke_iiiiiiifii,invoke_iiiiiiii,invoke_iiiiiiiii,invoke_iiiiiiiiiffi,invoke_iiiiiiiiii,invoke_iiiiiiiiiifi,invoke_iiiiiiiiiii,invoke_iiiiiiiiiiii,invoke_iiiiiiiiiiiif,invoke_iiiiiiiiiiiiiii,invoke_iiiiiiij,invoke_iiiiiij,invoke_iiiiij,invoke_iiiij,invoke_iiij,invoke_iiiji,invoke_iiijii,invoke_iiijiii,invoke_iij,invoke_iijiii,invoke_iijj,invoke_iijji,invoke_iijjiii,invoke_ij,invoke_ijjiii,invoke_j,invoke_ji,invoke_jii,invoke_jiii,invoke_jiji,invoke_v,invoke_vdiii,invoke_vi,invoke_vid,invoke_vif,invoke_vififiif,invoke_vifii,invoke_vifiiifiiiiiiiiiiiiifiiii,invoke_vii,invoke_viid,invoke_viif,invoke_viiff,invoke_viifi,invoke_viifiii,invoke_viii,invoke_viiid,invoke_viiif,invoke_viiiffii,invoke_viiiffiiii,invoke_viiifi,invoke_viiii,invoke_viiiif,invoke_viiiii,invoke_viiiiif,invoke_viiiiii,invoke_viiiiiid,invoke_viiiiiif,invoke_viiiiiifi,invoke_viiiiiifif,invoke_viiiiiifii,invoke_viiiiiii,invoke_viiiiiiidiiii,invoke_viiiiiiii,invoke_viiiiiiiif,invoke_viiiiiiiii,invoke_viiiiiiiiii,invoke_viiiiiiiiiidii,invoke_viiiiiiiiiii,invoke_viiiiiiiiiiii,invoke_viiiiiiiiiiiiii,invoke_viiiiiiiiiiiiiiii,invoke_viiiiij,invoke_viiiiiji,invoke_viiiiji,invoke_viiiijiiifi,invoke_viiij,invoke_viiiji,invoke_viiijii,invoke_viiijjji,invoke_viij,invoke_viiji,invoke_viijii,invoke_viijj,invoke_vij,invoke_viji,invoke_vijif,invoke_vijii,invoke_vijj,invoke_vjjiii,llvm_eh_typeid_for:_llvm_eh_typeid_for,proc_exit:_proc_exit};var wasmExports=createWasm();var ___wasm_call_ctors=createExportWrapper("__wasm_call_ctors",0);var _web_engine_create=Module["_web_engine_create"]=createExportWrapper("web_engine_create",0);var _web_engine_get_memory_stats=Module["_web_engine_get_memory_stats"]=createExportWrapper("web_engine_get_memory_stats",1);var _web_engine_destroy=Module["_web_engine_destroy"]=createExportWrapper("web_engine_destroy",1);var _fflush=createExportWrapper("fflush",1);var _web_engine_get_live_handles=Module["_web_engine_get_live_handles"]=createExportWrapper("web_engine_get_live_handles",0);var _web_engine_get_allocated_bytes=Module["_web_engine_get_allocated_bytes"]=createExportWrapper("web_engine_get_allocated_bytes",0);var _web_engine_open_blend=Module["_web_engine_open_blend"]=createExportWrapper("web_engine_open_blend",3);var _web_engine_apply_command=Module["_web_engine_apply_command"]=createExportWrapper("web_engine_apply_command",3);var _web_engine_decimate_apply=Module["_web_engine_decimate_apply"]=createExportWrapper("web_engine_decimate_apply",35);var _web_engine_append_library_object=Module["_web_engine_append_library_object"]=createExportWrapper("web_engine_append_library_object",5);var _web_engine_undo=Module["_web_engine_undo"]=createExportWrapper("web_engine_undo",1);var _web_engine_redo=Module["_web_engine_redo"]=createExportWrapper("web_engine_redo",1);var _web_engine_get_scene_snapshot=Module["_web_engine_get_scene_snapshot"]=createExportWrapper("web_engine_get_scene_snapshot",3);var _web_engine_get_scene_metadata=Module["_web_engine_get_scene_metadata"]=createExportWrapper("web_engine_get_scene_metadata",3);var _web_engine_get_scene_geometry=Module["_web_engine_get_scene_geometry"]=createExportWrapper("web_engine_get_scene_geometry",3);var _web_engine_get_scene_delta=Module["_web_engine_get_scene_delta"]=createExportWrapper("web_engine_get_scene_delta",3);var _web_engine_get_packed_asset=Module["_web_engine_get_packed_asset"]=createExportWrapper("web_engine_get_packed_asset",5);var _web_engine_evaluate_depsgraph=Module["_web_engine_evaluate_depsgraph"]=createExportWrapper("web_engine_evaluate_depsgraph",3);var _web_engine_save_blend=Module["_web_engine_save_blend"]=createExportWrapper("web_engine_save_blend",3);var _malloc=Module["_malloc"]=createExportWrapper("malloc",1);var _web_engine_free_buffer=Module["_web_engine_free_buffer"]=createExportWrapper("web_engine_free_buffer",1);var _free=Module["_free"]=createExportWrapper("free",1);var _web_engine_last_error_code=Module["_web_engine_last_error_code"]=createExportWrapper("web_engine_last_error_code",0);var _web_engine_last_error_message=Module["_web_engine_last_error_message"]=createExportWrapper("web_engine_last_error_message",0);var _strerror=createExportWrapper("strerror",1);var _emscripten_builtin_memalign=createExportWrapper("emscripten_builtin_memalign",2);var _setThrew=createExportWrapper("setThrew",2);var __emscripten_tempret_set=createExportWrapper("_emscripten_tempret_set",1);var __emscripten_tempret_get=createExportWrapper("_emscripten_tempret_get",0);var _emscripten_stack_init=()=>(_emscripten_stack_init=wasmExports["emscripten_stack_init"])();var _emscripten_stack_get_free=()=>(_emscripten_stack_get_free=wasmExports["emscripten_stack_get_free"])();var _emscripten_stack_get_base=()=>(_emscripten_stack_get_base=wasmExports["emscripten_stack_get_base"])();var _emscripten_stack_get_end=()=>(_emscripten_stack_get_end=wasmExports["emscripten_stack_get_end"])();var __emscripten_stack_restore=a0=>(__emscripten_stack_restore=wasmExports["_emscripten_stack_restore"])(a0);var __emscripten_stack_alloc=a0=>(__emscripten_stack_alloc=wasmExports["_emscripten_stack_alloc"])(a0);var _emscripten_stack_get_current=()=>(_emscripten_stack_get_current=wasmExports["emscripten_stack_get_current"])();var ___cxa_decrement_exception_refcount=createExportWrapper("__cxa_decrement_exception_refcount",1);var ___cxa_increment_exception_refcount=createExportWrapper("__cxa_increment_exception_refcount",1);var ___cxa_can_catch=createExportWrapper("__cxa_can_catch",3);var ___cxa_get_exception_ptr=createExportWrapper("__cxa_get_exception_ptr",1);var ___set_stack_limits=Module["___set_stack_limits"]=createExportWrapper("__set_stack_limits",2);var dynCall_viij=Module["dynCall_viij"]=createExportWrapper("dynCall_viij",5);var dynCall_viiji=Module["dynCall_viiji"]=createExportWrapper("dynCall_viiji",6);var dynCall_viijii=Module["dynCall_viijii"]=createExportWrapper("dynCall_viijii",7);var dynCall_vij=Module["dynCall_vij"]=createExportWrapper("dynCall_vij",4);var dynCall_viiiijiiifi=Module["dynCall_viiiijiiifi"]=createExportWrapper("dynCall_viiiijiiifi",12);var dynCall_viiijjji=Module["dynCall_viiijjji"]=createExportWrapper("dynCall_viiijjji",11);var dynCall_viiiiji=Module["dynCall_viiiiji"]=createExportWrapper("dynCall_viiiiji",8);var dynCall_viiiji=Module["dynCall_viiiji"]=createExportWrapper("dynCall_viiiji",7);var dynCall_ij=Module["dynCall_ij"]=createExportWrapper("dynCall_ij",3);var dynCall_viji=Module["dynCall_viji"]=createExportWrapper("dynCall_viji",5);var dynCall_iij=Module["dynCall_iij"]=createExportWrapper("dynCall_iij",4);var dynCall_fij=Module["dynCall_fij"]=createExportWrapper("dynCall_fij",4);var dynCall_vijf=Module["dynCall_vijf"]=createExportWrapper("dynCall_vijf",5);var dynCall_jiii=Module["dynCall_jiii"]=createExportWrapper("dynCall_jiii",4);var dynCall_viiij=Module["dynCall_viiij"]=createExportWrapper("dynCall_viiij",6);var dynCall_iiijii=Module["dynCall_iiijii"]=createExportWrapper("dynCall_iiijii",7);var dynCall_iiijiii=Module["dynCall_iiijiii"]=createExportWrapper("dynCall_iiijiii",8);var dynCall_iiij=Module["dynCall_iiij"]=createExportWrapper("dynCall_iiij",5);var dynCall_vjjiii=Module["dynCall_vjjiii"]=createExportWrapper("dynCall_vjjiii",8);var dynCall_ijjiii=Module["dynCall_ijjiii"]=createExportWrapper("dynCall_ijjiii",8);var dynCall_iijiii=Module["dynCall_iijiii"]=createExportWrapper("dynCall_iijiii",7);var dynCall_iijjiii=Module["dynCall_iijjiii"]=createExportWrapper("dynCall_iijjiii",9);var dynCall_iiiji=Module["dynCall_iiiji"]=createExportWrapper("dynCall_iiiji",6);var dynCall_jii=Module["dynCall_jii"]=createExportWrapper("dynCall_jii",3);var dynCall_iijj=Module["dynCall_iijj"]=createExportWrapper("dynCall_iijj",6);var dynCall_vijj=Module["dynCall_vijj"]=createExportWrapper("dynCall_vijj",6);var dynCall_ji=Module["dynCall_ji"]=createExportWrapper("dynCall_ji",2);var dynCall_vijii=Module["dynCall_vijii"]=createExportWrapper("dynCall_vijii",6);var dynCall_vijif=Module["dynCall_vijif"]=createExportWrapper("dynCall_vijif",6);var dynCall_viiiiij=Module["dynCall_viiiiij"]=createExportWrapper("dynCall_viiiiij",8);var dynCall_viiiiiji=Module["dynCall_viiiiiji"]=createExportWrapper("dynCall_viiiiiji",9);var dynCall_iiiij=Module["dynCall_iiiij"]=createExportWrapper("dynCall_iiiij",6);var dynCall_iijji=Module["dynCall_iijji"]=createExportWrapper("dynCall_iijji",7);var dynCall_j=Module["dynCall_j"]=createExportWrapper("dynCall_j",1);var dynCall_iiiiiiij=Module["dynCall_iiiiiiij"]=createExportWrapper("dynCall_iiiiiiij",9);var dynCall_viijj=Module["dynCall_viijj"]=createExportWrapper("dynCall_viijj",7);var dynCall_iiiiij=Module["dynCall_iiiiij"]=createExportWrapper("dynCall_iiiiij",7);var dynCall_viiijii=Module["dynCall_viiijii"]=createExportWrapper("dynCall_viiijii",8);var dynCall_jij=Module["dynCall_jij"]=createExportWrapper("dynCall_jij",4);var dynCall_vijji=Module["dynCall_vijji"]=createExportWrapper("dynCall_vijji",7);var dynCall_iiiiiij=Module["dynCall_iiiiiij"]=createExportWrapper("dynCall_iiiiiij",8);var dynCall_jiji=Module["dynCall_jiji"]=createExportWrapper("dynCall_jiji",5);var dynCall_iiiiijj=Module["dynCall_iiiiijj"]=createExportWrapper("dynCall_iiiiijj",9);var dynCall_iiiiiijj=Module["dynCall_iiiiiijj"]=createExportWrapper("dynCall_iiiiiijj",10);function invoke_ii(index,a1){var sp=stackSave();try{return getWasmTableEntry(index)(a1)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_v(index){var sp=stackSave();try{getWasmTableEntry(index)()}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiii(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viii(index,a1,a2,a3){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiii(index,a1,a2,a3,a4){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vi(index,a1){var sp=stackSave();try{getWasmTableEntry(index)(a1)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vif(index,a1,a2){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iii(index,a1,a2){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fi(index,a1){var sp=stackSave();try{return getWasmTableEntry(index)(a1)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiif(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vii(index,a1,a2){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiii(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_i(index){var sp=stackSave();try{return getWasmTableEntry(index)()}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fiii(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_diii(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viifiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiffi(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiifii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiffifffffffi(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiifi(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiiiifi(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiififiiiififiiiiiiiiiiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,a22,a23,a24,a25,a26,a27,a28,a29,a30,a31,a32,a33,a34,a35){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,a22,a23,a24,a25,a26,a27,a28,a29,a30,a31,a32,a33,a34,a35)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vififiif(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vifii(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fiiii(index,a1,a2,a3,a4){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viif(index,a1,a2,a3){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viifi(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiif(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiif(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiif(index,a1,a2,a3,a4,a5){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fif(index,a1,a2){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiifi(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iifii(index,a1,a2,a3,a4){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fii(index,a1,a2){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fiiiiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iifi(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiif(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vdiii(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_idiii(index,a1,a2,a3,a4){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiif(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiifii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiifiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_d(index){var sp=stackSave();try{return getWasmTableEntry(index)()}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fifff(index,a1,a2,a3,a4){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiifi(index,a1,a2,a3,a4,a5){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fiiiiiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiifi(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vid(index,a1,a2){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiff(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iif(index,a1,a2){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiiiffi(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiffiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iifiiiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiifif(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiif(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vifiiifiiiiiiiiiiiiifiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,a22,a23,a24){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,a22,a23,a24)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiiiiiif(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiid(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiidiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiiiidii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiidi(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viid(index,a1,a2,a3){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiidii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiid(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiffii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiid(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fij(index,a1,a2,a3){var sp=stackSave();try{return dynCall_fij(index,a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viij(index,a1,a2,a3,a4){var sp=stackSave();try{dynCall_viij(index,a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iij(index,a1,a2,a3){var sp=stackSave();try{return dynCall_iij(index,a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_ij(index,a1,a2){var sp=stackSave();try{return dynCall_ij(index,a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vij(index,a1,a2,a3){var sp=stackSave();try{dynCall_vij(index,a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_jiii(index,a1,a2,a3){var sp=stackSave();try{return dynCall_jiii(index,a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiji(index,a1,a2,a3,a4,a5){var sp=stackSave();try{dynCall_viiji(index,a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viijii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{dynCall_viijii(index,a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiijiiifi(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){var sp=stackSave();try{dynCall_viiiijiiifi(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiijjji(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){var sp=stackSave();try{dynCall_viiijjji(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiji(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{dynCall_viiiiji(index,a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiji(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{dynCall_viiiji(index,a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiij(index,a1,a2,a3,a4,a5){var sp=stackSave();try{dynCall_viiij(index,a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiijii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return dynCall_iiijii(index,a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiijiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return dynCall_iiijiii(index,a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiij(index,a1,a2,a3,a4){var sp=stackSave();try{return dynCall_iiij(index,a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viji(index,a1,a2,a3,a4){var sp=stackSave();try{dynCall_viji(index,a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vijii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{dynCall_vijii(index,a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiji(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return dynCall_iiiji(index,a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iijiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return dynCall_iijiii(index,a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iijjiii(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSave();try{return dynCall_iijjiii(index,a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vjjiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{dynCall_vjjiii(index,a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_ijjiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return dynCall_ijjiii(index,a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iijj(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return dynCall_iijj(index,a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vijj(index,a1,a2,a3,a4,a5){var sp=stackSave();try{dynCall_vijj(index,a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiij(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{dynCall_viiiiij(index,a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vijif(index,a1,a2,a3,a4,a5){var sp=stackSave();try{dynCall_vijif(index,a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiji(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSave();try{dynCall_viiiiiji(index,a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iijji(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return dynCall_iijji(index,a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viijj(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{dynCall_viijj(index,a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_ji(index,a1){var sp=stackSave();try{return dynCall_ji(index,a1)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiij(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return dynCall_iiiiij(index,a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiij(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return dynCall_iiiij(index,a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_j(index){var sp=stackSave();try{return dynCall_j(index)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiij(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSave();try{return dynCall_iiiiiiij(index,a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiijii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{dynCall_viiijii(index,a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_jii(index,a1,a2){var sp=stackSave();try{return dynCall_jii(index,a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiij(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return dynCall_iiiiiij(index,a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_jiji(index,a1,a2,a3,a4){var sp=stackSave();try{return dynCall_jiji(index,a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}Module["ccall"]=ccall;Module["cwrap"]=cwrap;Module["UTF8ToString"]=UTF8ToString;var missingLibrarySymbols=["writeI53ToI64","writeI53ToI64Clamped","writeI53ToI64Signaling","writeI53ToU64Clamped","writeI53ToU64Signaling","readI53FromI64","readI53FromU64","convertI32PairToI53","convertU32PairToI53","getTempRet0","exitJS","inetPton4","inetNtop4","inetPton6","inetNtop6","readSockaddr","writeSockaddr","emscriptenLog","readEmAsmArgs","jstoi_q","listenOnce","autoResumeAudioContext","dynCallLegacy","getDynCaller","dynCall","handleException","runtimeKeepalivePush","runtimeKeepalivePop","callUserCallback","maybeExit","asmjsMangle","HandleAllocator","getNativeTypeSize","STACK_SIZE","STACK_ALIGN","POINTER_SIZE","ASSERTIONS","uleb128Encode","sigToWasmTypes","generateFuncType","convertJsFunctionToWasm","getEmptyTableSlot","updateTableMap","getFunctionAddress","addFunction","removeFunction","reallyNegative","unSign","strLen","reSign","formatString","intArrayToString","AsciiToString","UTF16ToString","stringToUTF16","lengthBytesUTF16","UTF32ToString","stringToUTF32","lengthBytesUTF32","stringToNewUTF8","registerKeyEventCallback","maybeCStringToJsString","findEventTarget","getBoundingClientRect","fillMouseEventData","registerMouseEventCallback","registerWheelEventCallback","registerUiEventCallback","registerFocusEventCallback","fillDeviceOrientationEventData","registerDeviceOrientationEventCallback","fillDeviceMotionEventData","registerDeviceMotionEventCallback","screenOrientation","fillOrientationChangeEventData","registerOrientationChangeEventCallback","fillFullscreenChangeEventData","registerFullscreenChangeEventCallback","JSEvents_requestFullscreen","JSEvents_resizeCanvasForFullscreen","registerRestoreOldStyle","hideEverythingExceptGivenElement","restoreHiddenElements","setLetterbox","softFullscreenResizeWebGLRenderTarget","doRequestFullscreen","fillPointerlockChangeEventData","registerPointerlockChangeEventCallback","registerPointerlockErrorEventCallback","requestPointerLock","fillVisibilityChangeEventData","registerVisibilityChangeEventCallback","registerTouchEventCallback","fillGamepadEventData","registerGamepadEventCallback","registerBeforeUnloadEventCallback","fillBatteryEventData","battery","registerBatteryEventCallback","setCanvasElementSize","getCanvasElementSize","jsStackTrace","getCallstack","convertPCtoSourceLocation","checkWasiClock","wasiRightsToMuslOFlags","wasiOFlagsToMuslOFlags","createDyncallWrapper","safeSetTimeout","setImmediateWrapped","clearImmediateWrapped","polyfillSetImmediate","registerPostMainLoop","registerPreMainLoop","getPromise","makePromise","idsToPromises","makePromiseCallback","Browser_asyncPrepareDataCounter","safeRequestAnimationFrame","isLeapYear","ydayFromDate","arraySum","addDays","getSocketFromFD","getSocketAddress","FS_unlink","FS_mkdirTree","_setNetworkCallback","heapObjectForWebGLType","toTypedArrayIndex","webgl_enable_ANGLE_instanced_arrays","webgl_enable_OES_vertex_array_object","webgl_enable_WEBGL_draw_buffers","webgl_enable_WEBGL_multi_draw","webgl_enable_EXT_polygon_offset_clamp","webgl_enable_EXT_clip_control","webgl_enable_WEBGL_polygon_mode","emscriptenWebGLGet","computeUnpackAlignedImageSize","colorChannelsInGlTextureFormat","emscriptenWebGLGetTexPixelData","emscriptenWebGLGetUniform","webglGetUniformLocation","webglPrepareUniformLocationsBeforeFirstUse","webglGetLeftBracePos","emscriptenWebGLGetVertexAttrib","__glGetActiveAttribOrUniform","writeGLArray","registerWebGlEventCallback","runAndAbortIfError","ALLOC_NORMAL","ALLOC_STACK","allocate","writeStringToMemory","writeAsciiToMemory","setErrNo","demangle","stackTrace"];missingLibrarySymbols.forEach(missingLibrarySymbol);var unexportedSymbols=["run","addOnPreRun","addOnInit","addOnPreMain","addOnExit","addOnPostRun","addRunDependency","removeRunDependency","out","err","callMain","abort","wasmMemory","wasmExports","writeStackCookie","checkStackCookie","convertI32PairToI53Checked","stackSave","stackRestore","stackAlloc","setTempRet0","ptrToString","zeroMemory","getHeapMax","growMemory","ENV","setStackLimits","ERRNO_CODES","strError","DNS","Protocols","Sockets","initRandomFill","randomFill","timers","warnOnce","readEmAsmArgsArray","jstoi_s","getExecutableName","keepRuntimeAlive","asyncLoad","alignMemory","mmapAlloc","wasmTable","noExitRuntime","getCFunc","freeTableIndexes","functionsInTableMap","setValue","getValue","PATH","PATH_FS","UTF8Decoder","UTF8ArrayToString","stringToUTF8Array","stringToUTF8","lengthBytesUTF8","intArrayFromString","stringToAscii","UTF16Decoder","stringToUTF8OnStack","writeArrayToMemory","JSEvents","specialHTMLTargets","findCanvasEventTarget","currentFullscreenStrategy","restoreOldWindowedStyle","UNWIND_CACHE","ExitStatus","getEnvStrings","doReadv","doWritev","promiseMap","uncaughtExceptionCount","exceptionLast","exceptionCaught","ExceptionInfo","findMatchingCatch","Browser","getPreloadedImageData__data","wget","MONTH_DAYS_REGULAR","MONTH_DAYS_LEAP","MONTH_DAYS_REGULAR_CUMULATIVE","MONTH_DAYS_LEAP_CUMULATIVE","SYSCALLS","preloadPlugins","FS_createPreloadedFile","FS_modeStringToFlags","FS_getMode","FS_stdin_getChar_buffer","FS_stdin_getChar","FS_createPath","FS_createDevice","FS_readFile","FS","FS_createDataFile","FS_createLazyFile","MEMFS","TTY","PIPEFS","SOCKFS","tempFixedLengthArray","miniTempWebGLFloatBuffers","miniTempWebGLIntBuffers","GL","AL","GLUT","EGL","GLEW","IDBStore","SDL","SDL_gfx","allocateUTF8","allocateUTF8OnStack","print","printErr"];unexportedSymbols.forEach(unexportedRuntimeSymbol);var calledRun;var calledPrerun;dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function stackCheckInit(){_emscripten_stack_init();writeStackCookie()}function run(){if(runDependencies>0){return}stackCheckInit();if(!calledPrerun){calledPrerun=1;preRun();if(runDependencies>0){return}}function doRun(){if(calledRun)return;calledRun=1;Module["calledRun"]=1;if(ABORT)return;initRuntime();readyPromiseResolve(Module);Module["onRuntimeInitialized"]?.();assert(!Module["_main"],'compiled without a main, but one is present. if you added it from JS, use Module["onRuntimeInitialized"]');postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(()=>{setTimeout(()=>Module["setStatus"](""),1);doRun()},1)}else{doRun()}checkStackCookie()}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}run();moduleRtn=readyPromise;for(const prop of Object.keys(Module)){if(!(prop in moduleArg)){Object.defineProperty(moduleArg,prop,{configurable:true,get(){abort(`Access to module property ('${prop}') is no longer possible via the module constructor argument; Instead, use the result of the module constructor.`)}})}} +var Module=moduleArg;var readyPromiseResolve,readyPromiseReject;var readyPromise=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject});["_malloc","_free","_web_engine_create","_web_engine_destroy","_web_engine_get_memory_stats","_web_engine_get_live_handles","_web_engine_get_allocated_bytes","_web_engine_open_blend","_web_engine_apply_command","_web_engine_append_library_object","_web_engine_undo","_web_engine_redo","_web_engine_get_scene_snapshot","_web_engine_get_scene_metadata","_web_engine_get_scene_geometry","_web_engine_get_scene_delta","_web_engine_get_packed_asset","_web_engine_evaluate_depsgraph","_web_engine_save_blend","_web_engine_free_buffer","_web_engine_last_error_code","_web_engine_last_error_message","_web_engine_decimate_apply","_memory","___indirect_function_table","___set_stack_limits","onRuntimeInitialized"].forEach(prop=>{if(!Object.getOwnPropertyDescriptor(readyPromise,prop)){Object.defineProperty(readyPromise,prop,{get:()=>abort("You are getting "+prop+" on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js"),set:()=>abort("You are setting "+prop+" on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js")})}});var ENVIRONMENT_IS_WEB=typeof window=="object";var ENVIRONMENT_IS_WORKER=typeof importScripts=="function";var ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string"&&process.type!="renderer";var ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;if(ENVIRONMENT_IS_NODE){const{createRequire}=await import("module");let dirname=import.meta.url;if(dirname.startsWith("data:")){dirname="/"}var require=createRequire(dirname)}var moduleOverrides=Object.assign({},Module);var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_NODE){if(typeof process=="undefined"||!process.release||process.release.name!=="node")throw new Error("not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)");var nodeVersion=process.versions.node;var numericVersion=nodeVersion.split(".").slice(0,3);numericVersion=numericVersion[0]*1e4+numericVersion[1]*100+numericVersion[2].split("-")[0]*1;if(numericVersion<16e4){throw new Error("This emscripten-generated code requires node v16.0.0 (detected v"+nodeVersion+")")}var fs=require("fs");var nodePath=require("path");if(!import.meta.url.startsWith("data:")){scriptDirectory=nodePath.dirname(require("url").fileURLToPath(import.meta.url))+"/"}readBinary=filename=>{filename=isFileURI(filename)?new URL(filename):nodePath.normalize(filename);var ret=fs.readFileSync(filename);assert(ret.buffer);return ret};readAsync=(filename,binary=true)=>{filename=isFileURI(filename)?new URL(filename):nodePath.normalize(filename);return new Promise((resolve,reject)=>{fs.readFile(filename,binary?undefined:"utf8",(err,data)=>{if(err)reject(err);else resolve(binary?data.buffer:data)})})};if(!Module["thisProgram"]&&process.argv.length>1){thisProgram=process.argv[1].replace(/\\/g,"/")}arguments_=process.argv.slice(2);quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow}}else if(ENVIRONMENT_IS_SHELL){if(typeof process=="object"&&typeof require==="function"||typeof window=="object"||typeof importScripts=="function")throw new Error("not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)")}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(_scriptName){scriptDirectory=_scriptName}if(scriptDirectory.startsWith("blob:")){scriptDirectory=""}else{scriptDirectory=scriptDirectory.substr(0,scriptDirectory.replace(/[?#].*/,"").lastIndexOf("/")+1)}if(!(typeof window=="object"||typeof importScripts=="function"))throw new Error("not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)");{if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=url=>{assert(!isFileURI(url),"readAsync does not work with file:// URLs");return fetch(url,{credentials:"same-origin"}).then(response=>{if(response.ok){return response.arrayBuffer()}return Promise.reject(new Error(response.status+" : "+response.url))})}}}else{throw new Error("environment detection error")}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.error.bind(console);Object.assign(Module,moduleOverrides);moduleOverrides=null;checkIncomingModuleAPI();if(Module["arguments"])arguments_=Module["arguments"];legacyModuleProp("arguments","arguments_");if(Module["thisProgram"])thisProgram=Module["thisProgram"];legacyModuleProp("thisProgram","thisProgram");assert(typeof Module["memoryInitializerPrefixURL"]=="undefined","Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["pthreadMainPrefixURL"]=="undefined","Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["cdInitializerPrefixURL"]=="undefined","Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["filePackagePrefixURL"]=="undefined","Module.filePackagePrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["read"]=="undefined","Module.read option was removed");assert(typeof Module["readAsync"]=="undefined","Module.readAsync option was removed (modify readAsync in JS)");assert(typeof Module["readBinary"]=="undefined","Module.readBinary option was removed (modify readBinary in JS)");assert(typeof Module["setWindowTitle"]=="undefined","Module.setWindowTitle option was removed (modify emscripten_set_window_title in JS)");assert(typeof Module["TOTAL_MEMORY"]=="undefined","Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY");legacyModuleProp("asm","wasmExports");legacyModuleProp("readAsync","readAsync");legacyModuleProp("readBinary","readBinary");legacyModuleProp("setWindowTitle","setWindowTitle");assert(!ENVIRONMENT_IS_SHELL,"shell environment detected but not enabled at build time. Add `shell` to `-sENVIRONMENT` to enable.");var wasmBinary=Module["wasmBinary"];legacyModuleProp("wasmBinary","wasmBinary");if(typeof WebAssembly!="object"){err("no native wasm support detected")}var wasmMemory;var ABORT=false;var EXITSTATUS;function assert(condition,text){if(!condition){abort("Assertion failed"+(text?": "+text:""))}}var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateMemoryViews(){var b=wasmMemory.buffer;Module["HEAP8"]=HEAP8=new Int8Array(b);Module["HEAP16"]=HEAP16=new Int16Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);Module["HEAPU16"]=HEAPU16=new Uint16Array(b);Module["HEAP32"]=HEAP32=new Int32Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);Module["HEAPF64"]=HEAPF64=new Float64Array(b)}assert(!Module["STACK_SIZE"],"STACK_SIZE can no longer be set at runtime. Use -sSTACK_SIZE at link time");assert(typeof Int32Array!="undefined"&&typeof Float64Array!=="undefined"&&Int32Array.prototype.subarray!=undefined&&Int32Array.prototype.set!=undefined,"JS engine does not provide full typed array support");assert(!Module["wasmMemory"],"Use of `wasmMemory` detected. Use -sIMPORTED_MEMORY to define wasmMemory externally");assert(!Module["INITIAL_MEMORY"],"Detected runtime INITIAL_MEMORY setting. Use -sIMPORTED_MEMORY to define wasmMemory dynamically");function writeStackCookie(){var max=_emscripten_stack_get_end();assert((max&3)==0);if(max==0){max+=4}HEAPU32[max>>2]=34821223;checkInt32(34821223);HEAPU32[max+4>>2]=2310721022;checkInt32(2310721022);HEAPU32[0>>2]=1668509029;checkInt32(1668509029)}function checkStackCookie(){if(ABORT)return;var max=_emscripten_stack_get_end();if(max==0){max+=4}var cookie1=HEAPU32[max>>2];var cookie2=HEAPU32[max+4>>2];if(cookie1!=34821223||cookie2!=2310721022){abort(`Stack overflow! Stack cookie has been overwritten at ${ptrToString(max)}, expected hex dwords 0x89BACDFE and 0x2135467, but received ${ptrToString(cookie2)} ${ptrToString(cookie1)}`)}if(HEAPU32[0>>2]!=1668509029){abort("Runtime error: The application has corrupted its heap memory area (address zero)!")}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;function preRun(){var preRuns=Module["preRun"];if(preRuns){if(typeof preRuns=="function")preRuns=[preRuns];preRuns.forEach(addOnPreRun)}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){assert(!runtimeInitialized);runtimeInitialized=true;checkStackCookie();setStackLimits();if(!Module["noFSInit"]&&!FS.initialized)FS.init();FS.ignorePermissions=false;TTY.init();callRuntimeCallbacks(__ATINIT__)}function postRun(){checkStackCookie();var postRuns=Module["postRun"];if(postRuns){if(typeof postRuns=="function")postRuns=[postRuns];postRuns.forEach(addOnPostRun)}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnInit(cb){__ATINIT__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}assert(Math.imul,"This browser does not support Math.imul(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.fround,"This browser does not support Math.fround(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.clz32,"This browser does not support Math.clz32(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.trunc,"This browser does not support Math.trunc(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;var runDependencyTracking={};function getUniqueRunDependency(id){var orig=id;while(1){if(!runDependencyTracking[id])return id;id=orig+Math.random()}}function addRunDependency(id){runDependencies++;Module["monitorRunDependencies"]?.(runDependencies);if(id){assert(!runDependencyTracking[id]);runDependencyTracking[id]=1;if(runDependencyWatcher===null&&typeof setInterval!="undefined"){runDependencyWatcher=setInterval(()=>{if(ABORT){clearInterval(runDependencyWatcher);runDependencyWatcher=null;return}var shown=false;for(var dep in runDependencyTracking){if(!shown){shown=true;err("still waiting on run dependencies:")}err(`dependency: ${dep}`)}if(shown){err("(end of list)")}},1e4)}}else{err("warning: run dependency added without ID")}}function removeRunDependency(id){runDependencies--;Module["monitorRunDependencies"]?.(runDependencies);if(id){assert(runDependencyTracking[id]);delete runDependencyTracking[id]}else{err("warning: run dependency removed without ID")}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}function abort(what){Module["onAbort"]?.(what);what="Aborted("+what+")";err(what);ABORT=true;var e=new WebAssembly.RuntimeError(what);readyPromiseReject(e);throw e}var dataURIPrefix="data:application/octet-stream;base64,";var isDataURI=filename=>filename.startsWith(dataURIPrefix);var isFileURI=filename=>filename.startsWith("file://");function createExportWrapper(name,nargs){return(...args)=>{assert(runtimeInitialized,`native function \`${name}\` called before runtime initialization`);var f=wasmExports[name];assert(f,`exported native function \`${name}\` not found`);assert(args.length<=nargs,`native function \`${name}\` called with ${args.length} args but expects ${nargs}`);return f(...args)}}function findWasmBinary(){if(Module["locateFile"]){var f="web_engine.wasm";if(!isDataURI(f)){return locateFile(f)}return f}return new URL("web_engine.wasm",import.meta.url).href}var wasmBinaryFile;function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}function getBinaryPromise(binaryFile){if(!wasmBinary){return readAsync(binaryFile).then(response=>new Uint8Array(response),()=>getBinarySync(binaryFile))}return Promise.resolve().then(()=>getBinarySync(binaryFile))}function instantiateArrayBuffer(binaryFile,imports,receiver){return getBinaryPromise(binaryFile).then(binary=>WebAssembly.instantiate(binary,imports)).then(receiver,reason=>{err(`failed to asynchronously prepare wasm: ${reason}`);if(isFileURI(wasmBinaryFile)){err(`warning: Loading from a file URI (${wasmBinaryFile}) is not supported in most browsers. See https://emscripten.org/docs/getting_started/FAQ.html#how-do-i-run-a-local-webserver-for-testing-why-does-my-program-stall-in-downloading-or-preparing`)}abort(reason)})}function instantiateAsync(binary,binaryFile,imports,callback){if(!binary&&typeof WebAssembly.instantiateStreaming=="function"&&!isDataURI(binaryFile)&&!ENVIRONMENT_IS_NODE&&typeof fetch=="function"){return fetch(binaryFile,{credentials:"same-origin"}).then(response=>{var result=WebAssembly.instantiateStreaming(response,imports);return result.then(callback,function(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(binaryFile,imports,callback)})})}return instantiateArrayBuffer(binaryFile,imports,callback)}function getWasmImports(){return{env:wasmImports,wasi_snapshot_preview1:wasmImports}}function createWasm(){var info=getWasmImports();function receiveInstance(instance,module){wasmExports=instance.exports;wasmMemory=wasmExports["memory"];assert(wasmMemory,"memory not found in wasm exports");updateMemoryViews();wasmTable=wasmExports["__indirect_function_table"];assert(wasmTable,"table not found in wasm exports");addOnInit(wasmExports["__wasm_call_ctors"]);removeRunDependency("wasm-instantiate");return wasmExports}addRunDependency("wasm-instantiate");var trueModule=Module;function receiveInstantiationResult(result){assert(Module===trueModule,"the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?");trueModule=null;receiveInstance(result["instance"])}if(Module["instantiateWasm"]){try{return Module["instantiateWasm"](info,receiveInstance)}catch(e){err(`Module.instantiateWasm callback failed with error: ${e}`);readyPromiseReject(e)}}wasmBinaryFile??=findWasmBinary();instantiateAsync(wasmBinary,wasmBinaryFile,info,receiveInstantiationResult).catch(readyPromiseReject);return{}}var tempDouble;var tempI64;(()=>{var h16=new Int16Array(1);var h8=new Int8Array(h16.buffer);h16[0]=25459;if(h8[0]!==115||h8[1]!==99)throw"Runtime error: expected the system to be little-endian! (Run with -sSUPPORT_BIG_ENDIAN to bypass)"})();if(Module["ENVIRONMENT"]){throw new Error("Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -sENVIRONMENT=web or -sENVIRONMENT=node)")}function legacyModuleProp(prop,newName,incoming=true){if(!Object.getOwnPropertyDescriptor(Module,prop)){Object.defineProperty(Module,prop,{configurable:true,get(){let extra=incoming?" (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)":"";abort(`\`Module.${prop}\` has been replaced by \`${newName}\``+extra)}})}}function ignoredModuleProp(prop){if(Object.getOwnPropertyDescriptor(Module,prop)){abort(`\`Module.${prop}\` was supplied but \`${prop}\` not included in INCOMING_MODULE_JS_API`)}}function isExportedByForceFilesystem(name){return name==="FS_createPath"||name==="FS_createDataFile"||name==="FS_createPreloadedFile"||name==="FS_unlink"||name==="addRunDependency"||name==="FS_createLazyFile"||name==="FS_createDevice"||name==="removeRunDependency"}function hookGlobalSymbolAccess(sym,func){if(typeof globalThis!="undefined"&&!Object.getOwnPropertyDescriptor(globalThis,sym)){Object.defineProperty(globalThis,sym,{configurable:true,get(){func();return undefined}})}}function missingGlobal(sym,msg){hookGlobalSymbolAccess(sym,()=>{warnOnce(`\`${sym}\` is not longer defined by emscripten. ${msg}`)})}missingGlobal("buffer","Please use HEAP8.buffer or wasmMemory.buffer");missingGlobal("asm","Please use wasmExports instead");function missingLibrarySymbol(sym){hookGlobalSymbolAccess(sym,()=>{var msg=`\`${sym}\` is a library symbol and not included by default; add it to your library.js __deps or to DEFAULT_LIBRARY_FUNCS_TO_INCLUDE on the command line`;var librarySymbol=sym;if(!librarySymbol.startsWith("_")){librarySymbol="$"+sym}msg+=` (e.g. -sDEFAULT_LIBRARY_FUNCS_TO_INCLUDE='${librarySymbol}')`;if(isExportedByForceFilesystem(sym)){msg+=". Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you"}warnOnce(msg)});unexportedRuntimeSymbol(sym)}function unexportedRuntimeSymbol(sym){if(!Object.getOwnPropertyDescriptor(Module,sym)){Object.defineProperty(Module,sym,{configurable:true,get(){var msg=`'${sym}' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the Emscripten FAQ)`;if(isExportedByForceFilesystem(sym)){msg+=". Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you"}abort(msg)}})}}var MAX_UINT8=2**8-1;var MAX_UINT16=2**16-1;var MAX_UINT32=2**32-1;var MAX_UINT53=2**53-1;var MAX_UINT64=2**64-1;var MIN_INT8=-(2**(8-1));var MIN_INT16=-(2**(16-1));var MIN_INT32=-(2**(32-1));var MIN_INT53=-(2**(53-1));var MIN_INT64=-(2**(64-1));function checkInt(value,bits,min,max){assert(Number.isInteger(Number(value)),`attempt to write non-integer (${value}) into integer heap`);assert(value<=max,`value (${value}) too large to write as ${bits}-bit value`);assert(value>=min,`value (${value}) too small to write as ${bits}-bit value`)}var checkInt8=value=>checkInt(value,8,MIN_INT8,MAX_UINT8);var checkInt16=value=>checkInt(value,16,MIN_INT16,MAX_UINT16);var checkInt32=value=>checkInt(value,32,MIN_INT32,MAX_UINT32);var checkInt64=value=>checkInt(value,64,MIN_INT64,MAX_UINT64);function dbg(...args){console.warn(...args)}function ExitStatus(status){this.name="ExitStatus";this.message=`Program terminated with exit(${status})`;this.status=status}var callRuntimeCallbacks=callbacks=>{callbacks.forEach(f=>f(Module))};var noExitRuntime=Module["noExitRuntime"]||true;var ptrToString=ptr=>{assert(typeof ptr==="number");ptr>>>=0;return"0x"+ptr.toString(16).padStart(8,"0")};var setStackLimits=()=>{var stackLow=_emscripten_stack_get_base();var stackHigh=_emscripten_stack_get_end();___set_stack_limits(stackLow,stackHigh)};var stackRestore=val=>__emscripten_stack_restore(val);var stackSave=()=>_emscripten_stack_get_current();var warnOnce=text=>{warnOnce.shown||={};if(!warnOnce.shown[text]){warnOnce.shown[text]=1;if(ENVIRONMENT_IS_NODE)text="warning: "+text;err(text)}};var UTF8Decoder=typeof TextDecoder!="undefined"?new TextDecoder:undefined;var UTF8ArrayToString=(heapOrArray,idx=0,maxBytesToRead=NaN)=>{var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heapOrArray[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx>10,56320|ch&1023)}}return str};var UTF8ToString=(ptr,maxBytesToRead)=>{assert(typeof ptr=="number",`UTF8ToString expects a number (got ${typeof ptr})`);return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""};var ___assert_fail=(condition,filename,line,func)=>{abort(`Assertion failed: ${UTF8ToString(condition)}, at: `+[filename?UTF8ToString(filename):"unknown filename",line,func?UTF8ToString(func):"unknown function"])};var wasmTableMirror=[];var wasmTable;var getWasmTableEntry=funcPtr=>{var func=wasmTableMirror[funcPtr];if(!func){if(funcPtr>=wasmTableMirror.length)wasmTableMirror.length=funcPtr+1;wasmTableMirror[funcPtr]=func=wasmTable.get(funcPtr)}assert(wasmTable.get(funcPtr)==func,"JavaScript-side Wasm function table mirror is out of date!");return func};var ___call_sighandler=(fp,sig)=>getWasmTableEntry(fp)(sig);var exceptionCaught=[];var uncaughtExceptionCount=0;var ___cxa_begin_catch=ptr=>{var info=new ExceptionInfo(ptr);if(!info.get_caught()){info.set_caught(true);uncaughtExceptionCount--}info.set_rethrown(false);exceptionCaught.push(info);___cxa_increment_exception_refcount(ptr);return ___cxa_get_exception_ptr(ptr)};var exceptionLast=0;var ___cxa_end_catch=()=>{_setThrew(0,0);assert(exceptionCaught.length>0);var info=exceptionCaught.pop();___cxa_decrement_exception_refcount(info.excPtr);exceptionLast=0};class ExceptionInfo{constructor(excPtr){this.excPtr=excPtr;this.ptr=excPtr-24}set_type(type){HEAPU32[this.ptr+4>>2]=type}get_type(){return HEAPU32[this.ptr+4>>2]}set_destructor(destructor){HEAPU32[this.ptr+8>>2]=destructor}get_destructor(){return HEAPU32[this.ptr+8>>2]}set_caught(caught){caught=caught?1:0;HEAP8[this.ptr+12]=caught;checkInt8(caught)}get_caught(){return HEAP8[this.ptr+12]!=0}set_rethrown(rethrown){rethrown=rethrown?1:0;HEAP8[this.ptr+13]=rethrown;checkInt8(rethrown)}get_rethrown(){return HEAP8[this.ptr+13]!=0}init(type,destructor){this.set_adjusted_ptr(0);this.set_type(type);this.set_destructor(destructor)}set_adjusted_ptr(adjustedPtr){HEAPU32[this.ptr+16>>2]=adjustedPtr}get_adjusted_ptr(){return HEAPU32[this.ptr+16>>2]}}var ___resumeException=ptr=>{if(!exceptionLast){exceptionLast=ptr}assert(false,"Exception thrown, but exception catching is not enabled. Compile with -sNO_DISABLE_EXCEPTION_CATCHING or -sEXCEPTION_CATCHING_ALLOWED=[..] to catch.")};var setTempRet0=val=>__emscripten_tempret_set(val);var findMatchingCatch=args=>{var thrown=exceptionLast;if(!thrown){setTempRet0(0);return 0}var info=new ExceptionInfo(thrown);info.set_adjusted_ptr(thrown);var thrownType=info.get_type();if(!thrownType){setTempRet0(0);return thrown}for(var caughtType of args){if(caughtType===0||caughtType===thrownType){break}var adjusted_ptr_addr=info.ptr+16;if(___cxa_can_catch(caughtType,thrownType,adjusted_ptr_addr)){setTempRet0(caughtType);return thrown}}setTempRet0(thrownType);return thrown};var ___cxa_find_matching_catch_2=()=>findMatchingCatch([]);var ___cxa_find_matching_catch_3=arg0=>findMatchingCatch([arg0]);var ___cxa_rethrow=()=>{var info=exceptionCaught.pop();if(!info){abort("no exception to throw")}var ptr=info.excPtr;if(!info.get_rethrown()){exceptionCaught.push(info);info.set_rethrown(true);info.set_caught(false);uncaughtExceptionCount++}exceptionLast=ptr;assert(false,"Exception thrown, but exception catching is not enabled. Compile with -sNO_DISABLE_EXCEPTION_CATCHING or -sEXCEPTION_CATCHING_ALLOWED=[..] to catch.")};var ___cxa_throw=(ptr,type,destructor)=>{var info=new ExceptionInfo(ptr);info.init(type,destructor);exceptionLast=ptr;uncaughtExceptionCount++;assert(false,"Exception thrown, but exception catching is not enabled. Compile with -sNO_DISABLE_EXCEPTION_CATCHING or -sEXCEPTION_CATCHING_ALLOWED=[..] to catch.")};var ___handle_stack_overflow=requested=>{var base=_emscripten_stack_get_base();var end=_emscripten_stack_get_end();abort(`stack overflow (Attempt to set SP to ${ptrToString(requested)}`+`, with stack limits [${ptrToString(end)} - ${ptrToString(base)}`+"]). If you require more stack space build with -sSTACK_SIZE=")};var PATH={isAbs:path=>path.charAt(0)==="/",splitPath:filename=>{var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;return splitPathRe.exec(filename).slice(1)},normalizeArray:(parts,allowAboveRoot)=>{var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up;up--){parts.unshift("..")}}return parts},normalize:path=>{var isAbsolute=PATH.isAbs(path),trailingSlash=path.substr(-1)==="/";path=PATH.normalizeArray(path.split("/").filter(p=>!!p),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path},dirname:path=>{var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return"."}if(dir){dir=dir.substr(0,dir.length-1)}return root+dir},basename:path=>{if(path==="/")return"/";path=PATH.normalize(path);path=path.replace(/\/$/,"");var lastSlash=path.lastIndexOf("/");if(lastSlash===-1)return path;return path.substr(lastSlash+1)},join:(...paths)=>PATH.normalize(paths.join("/")),join2:(l,r)=>PATH.normalize(l+"/"+r)};var initRandomFill=()=>{if(typeof crypto=="object"&&typeof crypto["getRandomValues"]=="function"){return view=>crypto.getRandomValues(view)}else if(ENVIRONMENT_IS_NODE){try{var crypto_module=require("crypto");var randomFillSync=crypto_module["randomFillSync"];if(randomFillSync){return view=>crypto_module["randomFillSync"](view)}var randomBytes=crypto_module["randomBytes"];return view=>(view.set(randomBytes(view.byteLength)),view)}catch(e){}}abort("no cryptographic support found for randomDevice. consider polyfilling it if you want to use something insecure like Math.random(), e.g. put this in a --pre-js: var crypto = { getRandomValues: (array) => { for (var i = 0; i < array.length; i++) array[i] = (Math.random()*256)|0 } };")};var randomFill=view=>(randomFill=initRandomFill())(view);var PATH_FS={resolve:(...args)=>{var resolvedPath="",resolvedAbsolute=false;for(var i=args.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?args[i]:FS.cwd();if(typeof path!="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){return""}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=PATH.isAbs(path)}resolvedPath=PATH.normalizeArray(resolvedPath.split("/").filter(p=>!!p),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."},relative:(from,to)=>{from=PATH_FS.resolve(from).substr(1);to=PATH_FS.resolve(to).substr(1);function trim(arr){var start=0;for(;start=0;end--){if(arr[end]!=="")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split("/"));var toParts=trim(to.split("/"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i{var len=0;for(var i=0;i=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{assert(typeof str==="string",`stringToUTF8Array expects a string (got ${typeof str})`);if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;if(u>1114111)warnOnce("Invalid Unicode code point "+ptrToString(u)+" encountered when serializing a JS string to a UTF-8 string in wasm memory! (Valid unicode code points should be in range 0-0x10FFFF).");heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx};function intArrayFromString(stringy,dontAddNull,length){var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array}var FS_stdin_getChar=()=>{if(!FS_stdin_getChar_buffer.length){var result=null;if(ENVIRONMENT_IS_NODE){var BUFSIZE=256;var buf=Buffer.alloc(BUFSIZE);var bytesRead=0;var fd=process.stdin.fd;try{bytesRead=fs.readSync(fd,buf,0,BUFSIZE)}catch(e){if(e.toString().includes("EOF"))bytesRead=0;else throw e}if(bytesRead>0){result=buf.slice(0,bytesRead).toString("utf-8")}}else if(typeof window!="undefined"&&typeof window.prompt=="function"){result=window.prompt("Input: ");if(result!==null){result+="\n"}}else{}if(!result){return null}FS_stdin_getChar_buffer=intArrayFromString(result,true)}return FS_stdin_getChar_buffer.shift()};var TTY={ttys:[],init(){},shutdown(){},register(dev,ops){TTY.ttys[dev]={input:[],output:[],ops};FS.registerDevice(dev,TTY.stream_ops)},stream_ops:{open(stream){var tty=TTY.ttys[stream.node.rdev];if(!tty){throw new FS.ErrnoError(43)}stream.tty=tty;stream.seekable=false},close(stream){stream.tty.ops.fsync(stream.tty)},fsync(stream){stream.tty.ops.fsync(stream.tty)},read(stream,buffer,offset,length,pos){if(!stream.tty||!stream.tty.ops.get_char){throw new FS.ErrnoError(60)}var bytesRead=0;for(var i=0;i0){out(UTF8ArrayToString(tty.output));tty.output=[]}},ioctl_tcgets(tty){return{c_iflag:25856,c_oflag:5,c_cflag:191,c_lflag:35387,c_cc:[3,28,127,21,4,0,1,0,17,19,26,0,18,15,23,22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}},ioctl_tcsets(tty,optional_actions,data){return 0},ioctl_tiocgwinsz(tty){return[24,80]}},default_tty1_ops:{put_char(tty,val){if(val===null||val===10){err(UTF8ArrayToString(tty.output));tty.output=[]}else{if(val!=0)tty.output.push(val)}},fsync(tty){if(tty.output&&tty.output.length>0){err(UTF8ArrayToString(tty.output));tty.output=[]}}}};var zeroMemory=(address,size)=>{HEAPU8.fill(0,address,address+size)};var alignMemory=(size,alignment)=>{assert(alignment,"alignment argument is required");return Math.ceil(size/alignment)*alignment};var mmapAlloc=size=>{size=alignMemory(size,65536);var ptr=_emscripten_builtin_memalign(65536,size);if(ptr)zeroMemory(ptr,size);return ptr};var MEMFS={ops_table:null,mount(mount){return MEMFS.createNode(null,"/",16384|511,0)},createNode(parent,name,mode,dev){if(FS.isBlkdev(mode)||FS.isFIFO(mode)){throw new FS.ErrnoError(63)}MEMFS.ops_table||={dir:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,lookup:MEMFS.node_ops.lookup,mknod:MEMFS.node_ops.mknod,rename:MEMFS.node_ops.rename,unlink:MEMFS.node_ops.unlink,rmdir:MEMFS.node_ops.rmdir,readdir:MEMFS.node_ops.readdir,symlink:MEMFS.node_ops.symlink},stream:{llseek:MEMFS.stream_ops.llseek}},file:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:{llseek:MEMFS.stream_ops.llseek,read:MEMFS.stream_ops.read,write:MEMFS.stream_ops.write,allocate:MEMFS.stream_ops.allocate,mmap:MEMFS.stream_ops.mmap,msync:MEMFS.stream_ops.msync}},link:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,readlink:MEMFS.node_ops.readlink},stream:{}},chrdev:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:FS.chrdev_stream_ops}};var node=FS.createNode(parent,name,mode,dev);if(FS.isDir(node.mode)){node.node_ops=MEMFS.ops_table.dir.node;node.stream_ops=MEMFS.ops_table.dir.stream;node.contents={}}else if(FS.isFile(node.mode)){node.node_ops=MEMFS.ops_table.file.node;node.stream_ops=MEMFS.ops_table.file.stream;node.usedBytes=0;node.contents=null}else if(FS.isLink(node.mode)){node.node_ops=MEMFS.ops_table.link.node;node.stream_ops=MEMFS.ops_table.link.stream}else if(FS.isChrdev(node.mode)){node.node_ops=MEMFS.ops_table.chrdev.node;node.stream_ops=MEMFS.ops_table.chrdev.stream}node.timestamp=Date.now();if(parent){parent.contents[name]=node;parent.timestamp=node.timestamp}return node},getFileDataAsTypedArray(node){if(!node.contents)return new Uint8Array(0);if(node.contents.subarray)return node.contents.subarray(0,node.usedBytes);return new Uint8Array(node.contents)},expandFileStorage(node,newCapacity){var prevCapacity=node.contents?node.contents.length:0;if(prevCapacity>=newCapacity)return;var CAPACITY_DOUBLING_MAX=1024*1024;newCapacity=Math.max(newCapacity,prevCapacity*(prevCapacity>>0);if(prevCapacity!=0)newCapacity=Math.max(newCapacity,256);var oldContents=node.contents;node.contents=new Uint8Array(newCapacity);if(node.usedBytes>0)node.contents.set(oldContents.subarray(0,node.usedBytes),0)},resizeFileStorage(node,newSize){if(node.usedBytes==newSize)return;if(newSize==0){node.contents=null;node.usedBytes=0}else{var oldContents=node.contents;node.contents=new Uint8Array(newSize);if(oldContents){node.contents.set(oldContents.subarray(0,Math.min(newSize,node.usedBytes)))}node.usedBytes=newSize}},node_ops:{getattr(node){var attr={};attr.dev=FS.isChrdev(node.mode)?node.id:1;attr.ino=node.id;attr.mode=node.mode;attr.nlink=1;attr.uid=0;attr.gid=0;attr.rdev=node.rdev;if(FS.isDir(node.mode)){attr.size=4096}else if(FS.isFile(node.mode)){attr.size=node.usedBytes}else if(FS.isLink(node.mode)){attr.size=node.link.length}else{attr.size=0}attr.atime=new Date(node.timestamp);attr.mtime=new Date(node.timestamp);attr.ctime=new Date(node.timestamp);attr.blksize=4096;attr.blocks=Math.ceil(attr.size/attr.blksize);return attr},setattr(node,attr){if(attr.mode!==undefined){node.mode=attr.mode}if(attr.timestamp!==undefined){node.timestamp=attr.timestamp}if(attr.size!==undefined){MEMFS.resizeFileStorage(node,attr.size)}},lookup(parent,name){throw FS.genericErrors[44]},mknod(parent,name,mode,dev){return MEMFS.createNode(parent,name,mode,dev)},rename(old_node,new_dir,new_name){if(FS.isDir(old_node.mode)){var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(new_node){for(var i in new_node.contents){throw new FS.ErrnoError(55)}}}delete old_node.parent.contents[old_node.name];old_node.parent.timestamp=Date.now();old_node.name=new_name;new_dir.contents[new_name]=old_node;new_dir.timestamp=old_node.parent.timestamp},unlink(parent,name){delete parent.contents[name];parent.timestamp=Date.now()},rmdir(parent,name){var node=FS.lookupNode(parent,name);for(var i in node.contents){throw new FS.ErrnoError(55)}delete parent.contents[name];parent.timestamp=Date.now()},readdir(node){var entries=[".",".."];for(var key of Object.keys(node.contents)){entries.push(key)}return entries},symlink(parent,newname,oldpath){var node=MEMFS.createNode(parent,newname,511|40960,0);node.link=oldpath;return node},readlink(node){if(!FS.isLink(node.mode)){throw new FS.ErrnoError(28)}return node.link}},stream_ops:{read(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=stream.node.usedBytes)return 0;var size=Math.min(stream.node.usedBytes-position,length);assert(size>=0);if(size>8&&contents.subarray){buffer.set(contents.subarray(position,position+size),offset)}else{for(var i=0;i0||position+length{var dep=!noRunDep?getUniqueRunDependency(`al ${url}`):"";readAsync(url).then(arrayBuffer=>{assert(arrayBuffer,`Loading data file "${url}" failed (no arrayBuffer).`);onload(new Uint8Array(arrayBuffer));if(dep)removeRunDependency(dep)},err=>{if(onerror){onerror()}else{throw`Loading data file "${url}" failed.`}});if(dep)addRunDependency(dep)};var FS_createDataFile=(parent,name,fileData,canRead,canWrite,canOwn)=>{FS.createDataFile(parent,name,fileData,canRead,canWrite,canOwn)};var preloadPlugins=Module["preloadPlugins"]||[];var FS_handledByPreloadPlugin=(byteArray,fullname,finish,onerror)=>{if(typeof Browser!="undefined")Browser.init();var handled=false;preloadPlugins.forEach(plugin=>{if(handled)return;if(plugin["canHandle"](fullname)){plugin["handle"](byteArray,fullname,finish,onerror);handled=true}});return handled};var FS_createPreloadedFile=(parent,name,url,canRead,canWrite,onload,onerror,dontCreateFile,canOwn,preFinish)=>{var fullname=name?PATH_FS.resolve(PATH.join2(parent,name)):parent;var dep=getUniqueRunDependency(`cp ${fullname}`);function processData(byteArray){function finish(byteArray){preFinish?.();if(!dontCreateFile){FS_createDataFile(parent,name,byteArray,canRead,canWrite,canOwn)}onload?.();removeRunDependency(dep)}if(FS_handledByPreloadPlugin(byteArray,fullname,finish,()=>{onerror?.();removeRunDependency(dep)})){return}finish(byteArray)}addRunDependency(dep);if(typeof url=="string"){asyncLoad(url,processData,onerror)}else{processData(url)}};var FS_modeStringToFlags=str=>{var flagModes={r:0,"r+":2,w:512|64|1,"w+":512|64|2,a:1024|64|1,"a+":1024|64|2};var flags=flagModes[str];if(typeof flags=="undefined"){throw new Error(`Unknown file open mode: ${str}`)}return flags};var FS_getMode=(canRead,canWrite)=>{var mode=0;if(canRead)mode|=292|73;if(canWrite)mode|=146;return mode};var strError=errno=>UTF8ToString(_strerror(errno));var ERRNO_CODES={EPERM:63,ENOENT:44,ESRCH:71,EINTR:27,EIO:29,ENXIO:60,E2BIG:1,ENOEXEC:45,EBADF:8,ECHILD:12,EAGAIN:6,EWOULDBLOCK:6,ENOMEM:48,EACCES:2,EFAULT:21,ENOTBLK:105,EBUSY:10,EEXIST:20,EXDEV:75,ENODEV:43,ENOTDIR:54,EISDIR:31,EINVAL:28,ENFILE:41,EMFILE:33,ENOTTY:59,ETXTBSY:74,EFBIG:22,ENOSPC:51,ESPIPE:70,EROFS:69,EMLINK:34,EPIPE:64,EDOM:18,ERANGE:68,ENOMSG:49,EIDRM:24,ECHRNG:106,EL2NSYNC:156,EL3HLT:107,EL3RST:108,ELNRNG:109,EUNATCH:110,ENOCSI:111,EL2HLT:112,EDEADLK:16,ENOLCK:46,EBADE:113,EBADR:114,EXFULL:115,ENOANO:104,EBADRQC:103,EBADSLT:102,EDEADLOCK:16,EBFONT:101,ENOSTR:100,ENODATA:116,ETIME:117,ENOSR:118,ENONET:119,ENOPKG:120,EREMOTE:121,ENOLINK:47,EADV:122,ESRMNT:123,ECOMM:124,EPROTO:65,EMULTIHOP:36,EDOTDOT:125,EBADMSG:9,ENOTUNIQ:126,EBADFD:127,EREMCHG:128,ELIBACC:129,ELIBBAD:130,ELIBSCN:131,ELIBMAX:132,ELIBEXEC:133,ENOSYS:52,ENOTEMPTY:55,ENAMETOOLONG:37,ELOOP:32,EOPNOTSUPP:138,EPFNOSUPPORT:139,ECONNRESET:15,ENOBUFS:42,EAFNOSUPPORT:5,EPROTOTYPE:67,ENOTSOCK:57,ENOPROTOOPT:50,ESHUTDOWN:140,ECONNREFUSED:14,EADDRINUSE:3,ECONNABORTED:13,ENETUNREACH:40,ENETDOWN:38,ETIMEDOUT:73,EHOSTDOWN:142,EHOSTUNREACH:23,EINPROGRESS:26,EALREADY:7,EDESTADDRREQ:17,EMSGSIZE:35,EPROTONOSUPPORT:66,ESOCKTNOSUPPORT:137,EADDRNOTAVAIL:4,ENETRESET:39,EISCONN:30,ENOTCONN:53,ETOOMANYREFS:141,EUSERS:136,EDQUOT:19,ESTALE:72,ENOTSUP:138,ENOMEDIUM:148,EILSEQ:25,EOVERFLOW:61,ECANCELED:11,ENOTRECOVERABLE:56,EOWNERDEAD:62,ESTRPIPE:135};var FS={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,ErrnoError:class extends Error{constructor(errno){super(runtimeInitialized?strError(errno):"");this.name="ErrnoError";this.errno=errno;for(var key in ERRNO_CODES){if(ERRNO_CODES[key]===errno){this.code=key;break}}}},genericErrors:{},filesystems:null,syncFSRequests:0,readFiles:{},FSStream:class{constructor(){this.shared={}}get object(){return this.node}set object(val){this.node=val}get isRead(){return(this.flags&2097155)!==1}get isWrite(){return(this.flags&2097155)!==0}get isAppend(){return this.flags&1024}get flags(){return this.shared.flags}set flags(val){this.shared.flags=val}get position(){return this.shared.position}set position(val){this.shared.position=val}},FSNode:class{constructor(parent,name,mode,rdev){if(!parent){parent=this}this.parent=parent;this.mount=parent.mount;this.mounted=null;this.id=FS.nextInode++;this.name=name;this.mode=mode;this.node_ops={};this.stream_ops={};this.rdev=rdev;this.readMode=292|73;this.writeMode=146}get read(){return(this.mode&this.readMode)===this.readMode}set read(val){val?this.mode|=this.readMode:this.mode&=~this.readMode}get write(){return(this.mode&this.writeMode)===this.writeMode}set write(val){val?this.mode|=this.writeMode:this.mode&=~this.writeMode}get isFolder(){return FS.isDir(this.mode)}get isDevice(){return FS.isChrdev(this.mode)}},lookupPath(path,opts={}){path=PATH_FS.resolve(path);if(!path)return{path:"",node:null};var defaults={follow_mount:true,recurse_count:0};opts=Object.assign(defaults,opts);if(opts.recurse_count>8){throw new FS.ErrnoError(32)}var parts=path.split("/").filter(p=>!!p);var current=FS.root;var current_path="/";for(var i=0;i40){throw new FS.ErrnoError(32)}}}}return{path:current_path,node:current}},getPath(node){var path;while(true){if(FS.isRoot(node)){var mount=node.mount.mountpoint;if(!path)return mount;return mount[mount.length-1]!=="/"?`${mount}/${path}`:mount+path}path=path?`${node.name}/${path}`:node.name;node=node.parent}},hashName(parentid,name){var hash=0;for(var i=0;i>>0)%FS.nameTable.length},hashAddNode(node){var hash=FS.hashName(node.parent.id,node.name);node.name_next=FS.nameTable[hash];FS.nameTable[hash]=node},hashRemoveNode(node){var hash=FS.hashName(node.parent.id,node.name);if(FS.nameTable[hash]===node){FS.nameTable[hash]=node.name_next}else{var current=FS.nameTable[hash];while(current){if(current.name_next===node){current.name_next=node.name_next;break}current=current.name_next}}},lookupNode(parent,name){var errCode=FS.mayLookup(parent);if(errCode){throw new FS.ErrnoError(errCode)}var hash=FS.hashName(parent.id,name);for(var node=FS.nameTable[hash];node;node=node.name_next){var nodeName=node.name;if(node.parent.id===parent.id&&nodeName===name){return node}}return FS.lookup(parent,name)},createNode(parent,name,mode,rdev){assert(typeof parent=="object");var node=new FS.FSNode(parent,name,mode,rdev);FS.hashAddNode(node);return node},destroyNode(node){FS.hashRemoveNode(node)},isRoot(node){return node===node.parent},isMountpoint(node){return!!node.mounted},isFile(mode){return(mode&61440)===32768},isDir(mode){return(mode&61440)===16384},isLink(mode){return(mode&61440)===40960},isChrdev(mode){return(mode&61440)===8192},isBlkdev(mode){return(mode&61440)===24576},isFIFO(mode){return(mode&61440)===4096},isSocket(mode){return(mode&49152)===49152},flagsToPermissionString(flag){var perms=["r","w","rw"][flag&3];if(flag&512){perms+="w"}return perms},nodePermissions(node,perms){if(FS.ignorePermissions){return 0}if(perms.includes("r")&&!(node.mode&292)){return 2}else if(perms.includes("w")&&!(node.mode&146)){return 2}else if(perms.includes("x")&&!(node.mode&73)){return 2}return 0},mayLookup(dir){if(!FS.isDir(dir.mode))return 54;var errCode=FS.nodePermissions(dir,"x");if(errCode)return errCode;if(!dir.node_ops.lookup)return 2;return 0},mayCreate(dir,name){try{var node=FS.lookupNode(dir,name);return 20}catch(e){}return FS.nodePermissions(dir,"wx")},mayDelete(dir,name,isdir){var node;try{node=FS.lookupNode(dir,name)}catch(e){return e.errno}var errCode=FS.nodePermissions(dir,"wx");if(errCode){return errCode}if(isdir){if(!FS.isDir(node.mode)){return 54}if(FS.isRoot(node)||FS.getPath(node)===FS.cwd()){return 10}}else{if(FS.isDir(node.mode)){return 31}}return 0},mayOpen(node,flags){if(!node){return 44}if(FS.isLink(node.mode)){return 32}else if(FS.isDir(node.mode)){if(FS.flagsToPermissionString(flags)!=="r"||flags&512){return 31}}return FS.nodePermissions(node,FS.flagsToPermissionString(flags))},MAX_OPEN_FDS:4096,nextfd(){for(var fd=0;fd<=FS.MAX_OPEN_FDS;fd++){if(!FS.streams[fd]){return fd}}throw new FS.ErrnoError(33)},getStreamChecked(fd){var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(8)}return stream},getStream:fd=>FS.streams[fd],createStream(stream,fd=-1){assert(fd>=-1);stream=Object.assign(new FS.FSStream,stream);if(fd==-1){fd=FS.nextfd()}stream.fd=fd;FS.streams[fd]=stream;return stream},closeStream(fd){FS.streams[fd]=null},dupStream(origStream,fd=-1){var stream=FS.createStream(origStream,fd);stream.stream_ops?.dup?.(stream);return stream},chrdev_stream_ops:{open(stream){var device=FS.getDevice(stream.node.rdev);stream.stream_ops=device.stream_ops;stream.stream_ops.open?.(stream)},llseek(){throw new FS.ErrnoError(70)}},major:dev=>dev>>8,minor:dev=>dev&255,makedev:(ma,mi)=>ma<<8|mi,registerDevice(dev,ops){FS.devices[dev]={stream_ops:ops}},getDevice:dev=>FS.devices[dev],getMounts(mount){var mounts=[];var check=[mount];while(check.length){var m=check.pop();mounts.push(m);check.push(...m.mounts)}return mounts},syncfs(populate,callback){if(typeof populate=="function"){callback=populate;populate=false}FS.syncFSRequests++;if(FS.syncFSRequests>1){err(`warning: ${FS.syncFSRequests} FS.syncfs operations in flight at once, probably just doing extra work`)}var mounts=FS.getMounts(FS.root.mount);var completed=0;function doCallback(errCode){assert(FS.syncFSRequests>0);FS.syncFSRequests--;return callback(errCode)}function done(errCode){if(errCode){if(!done.errored){done.errored=true;return doCallback(errCode)}return}if(++completed>=mounts.length){doCallback(null)}}mounts.forEach(mount=>{if(!mount.type.syncfs){return done(null)}mount.type.syncfs(mount,populate,done)})},mount(type,opts,mountpoint){if(typeof type=="string"){throw type}var root=mountpoint==="/";var pseudo=!mountpoint;var node;if(root&&FS.root){throw new FS.ErrnoError(10)}else if(!root&&!pseudo){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});mountpoint=lookup.path;node=lookup.node;if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}if(!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}}var mount={type,opts,mountpoint,mounts:[]};var mountRoot=type.mount(mount);mountRoot.mount=mount;mount.root=mountRoot;if(root){FS.root=mountRoot}else if(node){node.mounted=mount;if(node.mount){node.mount.mounts.push(mount)}}return mountRoot},unmount(mountpoint){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});if(!FS.isMountpoint(lookup.node)){throw new FS.ErrnoError(28)}var node=lookup.node;var mount=node.mounted;var mounts=FS.getMounts(mount);Object.keys(FS.nameTable).forEach(hash=>{var current=FS.nameTable[hash];while(current){var next=current.name_next;if(mounts.includes(current.mount)){FS.destroyNode(current)}current=next}});node.mounted=null;var idx=node.mount.mounts.indexOf(mount);assert(idx!==-1);node.mount.mounts.splice(idx,1)},lookup(parent,name){return parent.node_ops.lookup(parent,name)},mknod(path,mode,dev){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);if(!name||name==="."||name===".."){throw new FS.ErrnoError(28)}var errCode=FS.mayCreate(parent,name);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.mknod){throw new FS.ErrnoError(63)}return parent.node_ops.mknod(parent,name,mode,dev)},create(path,mode){mode=mode!==undefined?mode:438;mode&=4095;mode|=32768;return FS.mknod(path,mode,0)},mkdir(path,mode){mode=mode!==undefined?mode:511;mode&=511|512;mode|=16384;return FS.mknod(path,mode,0)},mkdirTree(path,mode){var dirs=path.split("/");var d="";for(var i=0;i=0);if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.read){throw new FS.ErrnoError(28)}var seeking=typeof position!="undefined";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesRead=stream.stream_ops.read(stream,buffer,offset,length,position);if(!seeking)stream.position+=bytesRead;return bytesRead},write(stream,buffer,offset,length,position,canOwn){assert(offset>=0);if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.write){throw new FS.ErrnoError(28)}if(stream.seekable&&stream.flags&1024){FS.llseek(stream,0,2)}var seeking=typeof position!="undefined";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesWritten=stream.stream_ops.write(stream,buffer,offset,length,position,canOwn);if(!seeking)stream.position+=bytesWritten;return bytesWritten},allocate(stream,offset,length){if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(offset<0||length<=0){throw new FS.ErrnoError(28)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(8)}if(!FS.isFile(stream.node.mode)&&!FS.isDir(stream.node.mode)){throw new FS.ErrnoError(43)}if(!stream.stream_ops.allocate){throw new FS.ErrnoError(138)}stream.stream_ops.allocate(stream,offset,length)},mmap(stream,length,position,prot,flags){if((prot&2)!==0&&(flags&2)===0&&(stream.flags&2097155)!==2){throw new FS.ErrnoError(2)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(2)}if(!stream.stream_ops.mmap){throw new FS.ErrnoError(43)}if(!length){throw new FS.ErrnoError(28)}return stream.stream_ops.mmap(stream,length,position,prot,flags)},msync(stream,buffer,offset,length,mmapFlags){assert(offset>=0);if(!stream.stream_ops.msync){return 0}return stream.stream_ops.msync(stream,buffer,offset,length,mmapFlags)},ioctl(stream,cmd,arg){if(!stream.stream_ops.ioctl){throw new FS.ErrnoError(59)}return stream.stream_ops.ioctl(stream,cmd,arg)},readFile(path,opts={}){opts.flags=opts.flags||0;opts.encoding=opts.encoding||"binary";if(opts.encoding!=="utf8"&&opts.encoding!=="binary"){throw new Error(`Invalid encoding type "${opts.encoding}"`)}var ret;var stream=FS.open(path,opts.flags);var stat=FS.stat(path);var length=stat.size;var buf=new Uint8Array(length);FS.read(stream,buf,0,length,0);if(opts.encoding==="utf8"){ret=UTF8ArrayToString(buf)}else if(opts.encoding==="binary"){ret=buf}FS.close(stream);return ret},writeFile(path,data,opts={}){opts.flags=opts.flags||577;var stream=FS.open(path,opts.flags,opts.mode);if(typeof data=="string"){var buf=new Uint8Array(lengthBytesUTF8(data)+1);var actualNumBytes=stringToUTF8Array(data,buf,0,buf.length);FS.write(stream,buf,0,actualNumBytes,undefined,opts.canOwn)}else if(ArrayBuffer.isView(data)){FS.write(stream,data,0,data.byteLength,undefined,opts.canOwn)}else{throw new Error("Unsupported data type")}FS.close(stream)},cwd:()=>FS.currentPath,chdir(path){var lookup=FS.lookupPath(path,{follow:true});if(lookup.node===null){throw new FS.ErrnoError(44)}if(!FS.isDir(lookup.node.mode)){throw new FS.ErrnoError(54)}var errCode=FS.nodePermissions(lookup.node,"x");if(errCode){throw new FS.ErrnoError(errCode)}FS.currentPath=lookup.path},createDefaultDirectories(){FS.mkdir("/tmp");FS.mkdir("/home");FS.mkdir("/home/web_user")},createDefaultDevices(){FS.mkdir("/dev");FS.registerDevice(FS.makedev(1,3),{read:()=>0,write:(stream,buffer,offset,length,pos)=>length});FS.mkdev("/dev/null",FS.makedev(1,3));TTY.register(FS.makedev(5,0),TTY.default_tty_ops);TTY.register(FS.makedev(6,0),TTY.default_tty1_ops);FS.mkdev("/dev/tty",FS.makedev(5,0));FS.mkdev("/dev/tty1",FS.makedev(6,0));var randomBuffer=new Uint8Array(1024),randomLeft=0;var randomByte=()=>{if(randomLeft===0){randomLeft=randomFill(randomBuffer).byteLength}return randomBuffer[--randomLeft]};FS.createDevice("/dev","random",randomByte);FS.createDevice("/dev","urandom",randomByte);FS.mkdir("/dev/shm");FS.mkdir("/dev/shm/tmp")},createSpecialDirectories(){FS.mkdir("/proc");var proc_self=FS.mkdir("/proc/self");FS.mkdir("/proc/self/fd");FS.mount({mount(){var node=FS.createNode(proc_self,"fd",16384|511,73);node.node_ops={lookup(parent,name){var fd=+name;var stream=FS.getStreamChecked(fd);var ret={parent:null,mount:{mountpoint:"fake"},node_ops:{readlink:()=>stream.path}};ret.parent=ret;return ret}};return node}},{},"/proc/self/fd")},createStandardStreams(input,output,error){if(input){FS.createDevice("/dev","stdin",input)}else{FS.symlink("/dev/tty","/dev/stdin")}if(output){FS.createDevice("/dev","stdout",null,output)}else{FS.symlink("/dev/tty","/dev/stdout")}if(error){FS.createDevice("/dev","stderr",null,error)}else{FS.symlink("/dev/tty1","/dev/stderr")}var stdin=FS.open("/dev/stdin",0);var stdout=FS.open("/dev/stdout",1);var stderr=FS.open("/dev/stderr",1);assert(stdin.fd===0,`invalid handle for stdin (${stdin.fd})`);assert(stdout.fd===1,`invalid handle for stdout (${stdout.fd})`);assert(stderr.fd===2,`invalid handle for stderr (${stderr.fd})`)},staticInit(){[44].forEach(code=>{FS.genericErrors[code]=new FS.ErrnoError(code);FS.genericErrors[code].stack=""});FS.nameTable=new Array(4096);FS.mount(MEMFS,{},"/");FS.createDefaultDirectories();FS.createDefaultDevices();FS.createSpecialDirectories();FS.filesystems={MEMFS}},init(input,output,error){assert(!FS.initialized,"FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)");FS.initialized=true;input??=Module["stdin"];output??=Module["stdout"];error??=Module["stderr"];FS.createStandardStreams(input,output,error)},quit(){FS.initialized=false;_fflush(0);for(var i=0;ithis.length-1||idx<0){return undefined}var chunkOffset=idx%this.chunkSize;var chunkNum=idx/this.chunkSize|0;return this.getter(chunkNum)[chunkOffset]}setDataGetter(getter){this.getter=getter}cacheLength(){var xhr=new XMLHttpRequest;xhr.open("HEAD",url,false);xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);var datalength=Number(xhr.getResponseHeader("Content-length"));var header;var hasByteServing=(header=xhr.getResponseHeader("Accept-Ranges"))&&header==="bytes";var usesGzip=(header=xhr.getResponseHeader("Content-Encoding"))&&header==="gzip";var chunkSize=1024*1024;if(!hasByteServing)chunkSize=datalength;var doXHR=(from,to)=>{if(from>to)throw new Error("invalid range ("+from+", "+to+") or no bytes requested!");if(to>datalength-1)throw new Error("only "+datalength+" bytes available! programmer error!");var xhr=new XMLHttpRequest;xhr.open("GET",url,false);if(datalength!==chunkSize)xhr.setRequestHeader("Range","bytes="+from+"-"+to);xhr.responseType="arraybuffer";if(xhr.overrideMimeType){xhr.overrideMimeType("text/plain; charset=x-user-defined")}xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);if(xhr.response!==undefined){return new Uint8Array(xhr.response||[])}return intArrayFromString(xhr.responseText||"",true)};var lazyArray=this;lazyArray.setDataGetter(chunkNum=>{var start=chunkNum*chunkSize;var end=(chunkNum+1)*chunkSize-1;end=Math.min(end,datalength-1);if(typeof lazyArray.chunks[chunkNum]=="undefined"){lazyArray.chunks[chunkNum]=doXHR(start,end)}if(typeof lazyArray.chunks[chunkNum]=="undefined")throw new Error("doXHR failed!");return lazyArray.chunks[chunkNum]});if(usesGzip||!datalength){chunkSize=datalength=1;datalength=this.getter(0).length;chunkSize=datalength;out("LazyFiles on gzip forces download of the whole file when length is accessed")}this._length=datalength;this._chunkSize=chunkSize;this.lengthKnown=true}get length(){if(!this.lengthKnown){this.cacheLength()}return this._length}get chunkSize(){if(!this.lengthKnown){this.cacheLength()}return this._chunkSize}}if(typeof XMLHttpRequest!="undefined"){if(!ENVIRONMENT_IS_WORKER)throw"Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc";var lazyArray=new LazyUint8Array;var properties={isDevice:false,contents:lazyArray}}else{var properties={isDevice:false,url}}var node=FS.createFile(parent,name,properties,canRead,canWrite);if(properties.contents){node.contents=properties.contents}else if(properties.url){node.contents=null;node.url=properties.url}Object.defineProperties(node,{usedBytes:{get:function(){return this.contents.length}}});var stream_ops={};var keys=Object.keys(node.stream_ops);keys.forEach(key=>{var fn=node.stream_ops[key];stream_ops[key]=(...args)=>{FS.forceLoadFile(node);return fn(...args)}});function writeChunks(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=contents.length)return 0;var size=Math.min(contents.length-position,length);assert(size>=0);if(contents.slice){for(var i=0;i{FS.forceLoadFile(node);return writeChunks(stream,buffer,offset,length,position)};stream_ops.mmap=(stream,length,position,prot,flags)=>{FS.forceLoadFile(node);var ptr=mmapAlloc(length);if(!ptr){throw new FS.ErrnoError(48)}writeChunks(stream,HEAP8,ptr,length,position);return{ptr,allocated:true}};node.stream_ops=stream_ops;return node},absolutePath(){abort("FS.absolutePath has been removed; use PATH_FS.resolve instead")},createFolder(){abort("FS.createFolder has been removed; use FS.mkdir instead")},createLink(){abort("FS.createLink has been removed; use FS.symlink instead")},joinPath(){abort("FS.joinPath has been removed; use PATH.join instead")},mmapAlloc(){abort("FS.mmapAlloc has been replaced by the top level function mmapAlloc")},standardizePath(){abort("FS.standardizePath has been removed; use PATH.normalize instead")}};var SYSCALLS={DEFAULT_POLLMASK:5,calculateAt(dirfd,path,allowEmpty){if(PATH.isAbs(path)){return path}var dir;if(dirfd===-100){dir=FS.cwd()}else{var dirstream=SYSCALLS.getStreamFromFD(dirfd);dir=dirstream.path}if(path.length==0){if(!allowEmpty){throw new FS.ErrnoError(44)}return dir}return PATH.join2(dir,path)},doStat(func,path,buf){var stat=func(path);HEAP32[buf>>2]=stat.dev;checkInt32(stat.dev);HEAP32[buf+4>>2]=stat.mode;checkInt32(stat.mode);HEAPU32[buf+8>>2]=stat.nlink;checkInt32(stat.nlink);HEAP32[buf+12>>2]=stat.uid;checkInt32(stat.uid);HEAP32[buf+16>>2]=stat.gid;checkInt32(stat.gid);HEAP32[buf+20>>2]=stat.rdev;checkInt32(stat.rdev);tempI64=[stat.size>>>0,(tempDouble=stat.size,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+24>>2]=tempI64[0],HEAP32[buf+28>>2]=tempI64[1];checkInt64(stat.size);HEAP32[buf+32>>2]=4096;checkInt32(4096);HEAP32[buf+36>>2]=stat.blocks;checkInt32(stat.blocks);var atime=stat.atime.getTime();var mtime=stat.mtime.getTime();var ctime=stat.ctime.getTime();tempI64=[Math.floor(atime/1e3)>>>0,(tempDouble=Math.floor(atime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+40>>2]=tempI64[0],HEAP32[buf+44>>2]=tempI64[1];checkInt64(Math.floor(atime/1e3));HEAPU32[buf+48>>2]=atime%1e3*1e3*1e3;checkInt32(atime%1e3*1e3*1e3);tempI64=[Math.floor(mtime/1e3)>>>0,(tempDouble=Math.floor(mtime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+56>>2]=tempI64[0],HEAP32[buf+60>>2]=tempI64[1];checkInt64(Math.floor(mtime/1e3));HEAPU32[buf+64>>2]=mtime%1e3*1e3*1e3;checkInt32(mtime%1e3*1e3*1e3);tempI64=[Math.floor(ctime/1e3)>>>0,(tempDouble=Math.floor(ctime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+72>>2]=tempI64[0],HEAP32[buf+76>>2]=tempI64[1];checkInt64(Math.floor(ctime/1e3));HEAPU32[buf+80>>2]=ctime%1e3*1e3*1e3;checkInt32(ctime%1e3*1e3*1e3);tempI64=[stat.ino>>>0,(tempDouble=stat.ino,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+88>>2]=tempI64[0],HEAP32[buf+92>>2]=tempI64[1];checkInt64(stat.ino);return 0},doMsync(addr,stream,len,flags,offset){if(!FS.isFile(stream.node.mode)){throw new FS.ErrnoError(43)}if(flags&2){return 0}var buffer=HEAPU8.slice(addr,addr+len);FS.msync(stream,buffer,offset,len,flags)},getStreamFromFD(fd){var stream=FS.getStreamChecked(fd);return stream},varargs:undefined,getStr(ptr){var ret=UTF8ToString(ptr);return ret}};function ___syscall_faccessat(dirfd,path,amode,flags){try{path=SYSCALLS.getStr(path);assert(flags===0||flags==512);path=SYSCALLS.calculateAt(dirfd,path);if(amode&~7){return-28}var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;if(!node){return-44}var perms="";if(amode&4)perms+="r";if(amode&2)perms+="w";if(amode&1)perms+="x";if(perms&&FS.nodePermissions(node,perms)){return-2}return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function syscallGetVarargI(){assert(SYSCALLS.varargs!=undefined);var ret=HEAP32[+SYSCALLS.varargs>>2];SYSCALLS.varargs+=4;return ret}var syscallGetVarargP=syscallGetVarargI;function ___syscall_fcntl64(fd,cmd,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(cmd){case 0:{var arg=syscallGetVarargI();if(arg<0){return-28}while(FS.streams[arg]){arg++}var newStream;newStream=FS.dupStream(stream,arg);return newStream.fd}case 1:case 2:return 0;case 3:return stream.flags;case 4:{var arg=syscallGetVarargI();stream.flags|=arg;return 0}case 12:{var arg=syscallGetVarargP();var offset=0;HEAP16[arg+offset>>1]=2;checkInt16(2);return 0}case 13:case 14:return 0}return-28}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_fstat64(fd,buf){try{var stream=SYSCALLS.getStreamFromFD(fd);return SYSCALLS.doStat(FS.stat,stream.path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var stringToUTF8=(str,outPtr,maxBytesToWrite)=>{assert(typeof maxBytesToWrite=="number","stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!");return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)};function ___syscall_getdents64(fd,dirp,count){try{var stream=SYSCALLS.getStreamFromFD(fd);stream.getdents||=FS.readdir(stream.path);var struct_size=280;var pos=0;var off=FS.llseek(stream,0,1);var idx=Math.floor(off/struct_size);while(idx>>0,(tempDouble=id,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[dirp+pos>>2]=tempI64[0],HEAP32[dirp+pos+4>>2]=tempI64[1];checkInt64(id);tempI64=[(idx+1)*struct_size>>>0,(tempDouble=(idx+1)*struct_size,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[dirp+pos+8>>2]=tempI64[0],HEAP32[dirp+pos+12>>2]=tempI64[1];checkInt64((idx+1)*struct_size);HEAP16[dirp+pos+16>>1]=280;checkInt16(280);HEAP8[dirp+pos+18]=type;checkInt8(type);stringToUTF8(name,dirp+pos+19,256);pos+=struct_size;idx+=1}FS.llseek(stream,idx*struct_size,0);return pos}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_ioctl(fd,op,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(op){case 21509:{if(!stream.tty)return-59;return 0}case 21505:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tcgets){var termios=stream.tty.ops.ioctl_tcgets(stream);var argp=syscallGetVarargP();HEAP32[argp>>2]=termios.c_iflag||0;checkInt32(termios.c_iflag||0);HEAP32[argp+4>>2]=termios.c_oflag||0;checkInt32(termios.c_oflag||0);HEAP32[argp+8>>2]=termios.c_cflag||0;checkInt32(termios.c_cflag||0);HEAP32[argp+12>>2]=termios.c_lflag||0;checkInt32(termios.c_lflag||0);for(var i=0;i<32;i++){HEAP8[argp+i+17]=termios.c_cc[i]||0;checkInt8(termios.c_cc[i]||0)}return 0}return 0}case 21510:case 21511:case 21512:{if(!stream.tty)return-59;return 0}case 21506:case 21507:case 21508:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tcsets){var argp=syscallGetVarargP();var c_iflag=HEAP32[argp>>2];var c_oflag=HEAP32[argp+4>>2];var c_cflag=HEAP32[argp+8>>2];var c_lflag=HEAP32[argp+12>>2];var c_cc=[];for(var i=0;i<32;i++){c_cc.push(HEAP8[argp+i+17])}return stream.tty.ops.ioctl_tcsets(stream.tty,op,{c_iflag,c_oflag,c_cflag,c_lflag,c_cc})}return 0}case 21519:{if(!stream.tty)return-59;var argp=syscallGetVarargP();HEAP32[argp>>2]=0;checkInt32(0);return 0}case 21520:{if(!stream.tty)return-59;return-28}case 21531:{var argp=syscallGetVarargP();return FS.ioctl(stream,op,argp)}case 21523:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tiocgwinsz){var winsize=stream.tty.ops.ioctl_tiocgwinsz(stream.tty);var argp=syscallGetVarargP();HEAP16[argp>>1]=winsize[0];checkInt16(winsize[0]);HEAP16[argp+2>>1]=winsize[1];checkInt16(winsize[1])}return 0}case 21524:{if(!stream.tty)return-59;return 0}case 21515:{if(!stream.tty)return-59;return 0}default:return-28}}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_lstat64(path,buf){try{path=SYSCALLS.getStr(path);return SYSCALLS.doStat(FS.lstat,path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_mkdirat(dirfd,path,mode){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);path=PATH.normalize(path);if(path[path.length-1]==="/")path=path.substr(0,path.length-1);FS.mkdir(path,mode,0);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_newfstatat(dirfd,path,buf,flags){try{path=SYSCALLS.getStr(path);var nofollow=flags&256;var allowEmpty=flags&4096;flags=flags&~6400;assert(!flags,`unknown flags in __syscall_newfstatat: ${flags}`);path=SYSCALLS.calculateAt(dirfd,path,allowEmpty);return SYSCALLS.doStat(nofollow?FS.lstat:FS.stat,path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_openat(dirfd,path,flags,varargs){SYSCALLS.varargs=varargs;try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);var mode=varargs?syscallGetVarargI():0;return FS.open(path,flags,mode).fd}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_rmdir(path){try{path=SYSCALLS.getStr(path);FS.rmdir(path);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_stat64(path,buf){try{path=SYSCALLS.getStr(path);return SYSCALLS.doStat(FS.stat,path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_unlinkat(dirfd,path,flags){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);if(flags===0){FS.unlink(path)}else if(flags===512){FS.rmdir(path)}else{abort("Invalid flags passed to unlinkat")}return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var __abort_js=()=>{abort("native code called abort()")};var nowIsMonotonic=1;var __emscripten_get_now_is_monotonic=()=>nowIsMonotonic;var __emscripten_memcpy_js=(dest,src,num)=>HEAPU8.copyWithin(dest,src,src+num);var __emscripten_runtime_keepalive_clear=()=>{noExitRuntime=false;runtimeKeepaliveCounter=0};var __emscripten_throw_longjmp=()=>{throw Infinity};var convertI32PairToI53Checked=(lo,hi)=>{assert(lo==lo>>>0||lo==(lo|0));assert(hi===(hi|0));return hi+2097152>>>0<4194305-!!lo?(lo>>>0)+hi*4294967296:NaN};function __mmap_js(len,prot,flags,fd,offset_low,offset_high,allocated,addr){var offset=convertI32PairToI53Checked(offset_low,offset_high);try{if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);var res=FS.mmap(stream,len,offset,prot,flags);var ptr=res.ptr;HEAP32[allocated>>2]=res.allocated;checkInt32(res.allocated);HEAPU32[addr>>2]=ptr;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function __munmap_js(addr,len,prot,flags,fd,offset_low,offset_high){var offset=convertI32PairToI53Checked(offset_low,offset_high);try{var stream=SYSCALLS.getStreamFromFD(fd);if(prot&2){SYSCALLS.doMsync(addr,stream,len,flags,offset)}}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var __tzset_js=(timezone,daylight,std_name,dst_name)=>{var currentYear=(new Date).getFullYear();var winter=new Date(currentYear,0,1);var summer=new Date(currentYear,6,1);var winterOffset=winter.getTimezoneOffset();var summerOffset=summer.getTimezoneOffset();var stdTimezoneOffset=Math.max(winterOffset,summerOffset);HEAPU32[timezone>>2]=stdTimezoneOffset*60;checkInt32(stdTimezoneOffset*60);HEAP32[daylight>>2]=Number(winterOffset!=summerOffset);checkInt32(Number(winterOffset!=summerOffset));var extractZone=timezoneOffset=>{var sign=timezoneOffset>=0?"-":"+";var absOffset=Math.abs(timezoneOffset);var hours=String(Math.floor(absOffset/60)).padStart(2,"0");var minutes=String(absOffset%60).padStart(2,"0");return`UTC${sign}${hours}${minutes}`};var winterName=extractZone(winterOffset);var summerName=extractZone(summerOffset);assert(winterName);assert(summerName);assert(lengthBytesUTF8(winterName)<=16,`timezone name truncated to fit in TZNAME_MAX (${winterName})`);assert(lengthBytesUTF8(summerName)<=16,`timezone name truncated to fit in TZNAME_MAX (${summerName})`);if(summerOffsetDate.now();var getHeapMax=()=>2147483648;var _emscripten_get_heap_max=()=>getHeapMax();var _emscripten_get_now=()=>performance.now();var growMemory=size=>{var b=wasmMemory.buffer;var pages=(size-b.byteLength+65535)/65536|0;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){err(`growMemory: Attempted to grow heap from ${b.byteLength} bytes to ${size} bytes, but got error: ${e}`)}};var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;assert(requestedSize>oldSize);var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){err(`Cannot enlarge memory, requested ${requestedSize} bytes, but the limit is ${maxHeapSize} bytes!`);return false}for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignMemory(Math.max(requestedSize,overGrownHeapSize),65536));var t0=_emscripten_get_now();var replacement=growMemory(newSize);var t1=_emscripten_get_now();dbg(`Heap resize call from ${oldSize} to ${newSize} took ${t1-t0} msecs. Success: ${!!replacement}`);if(replacement){return true}}err(`Failed to grow the heap from ${oldSize} bytes to ${newSize} bytes, not enough memory!`);return false};var ENV={};var getExecutableName=()=>thisProgram||"./this.program";var getEnvStrings=()=>{if(!getEnvStrings.strings){var lang=(typeof navigator=="object"&&navigator.languages&&navigator.languages[0]||"C").replace("-","_")+".UTF-8";var env={USER:"web_user",LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:lang,_:getExecutableName()};for(var x in ENV){if(ENV[x]===undefined)delete env[x];else env[x]=ENV[x]}var strings=[];for(var x in env){strings.push(`${x}=${env[x]}`)}getEnvStrings.strings=strings}return getEnvStrings.strings};var stringToAscii=(str,buffer)=>{for(var i=0;i{var bufSize=0;getEnvStrings().forEach((string,i)=>{var ptr=environ_buf+bufSize;HEAPU32[__environ+i*4>>2]=ptr;checkInt32(ptr);stringToAscii(string,ptr);bufSize+=string.length+1});return 0};var _environ_sizes_get=(penviron_count,penviron_buf_size)=>{var strings=getEnvStrings();HEAPU32[penviron_count>>2]=strings.length;checkInt32(strings.length);var bufSize=0;strings.forEach(string=>bufSize+=string.length+1);HEAPU32[penviron_buf_size>>2]=bufSize;checkInt32(bufSize);return 0};function _fd_close(fd){try{var stream=SYSCALLS.getStreamFromFD(fd);FS.close(stream);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _fd_fdstat_get(fd,pbuf){try{var rightsBase=0;var rightsInheriting=0;var flags=0;{var stream=SYSCALLS.getStreamFromFD(fd);var type=stream.tty?2:FS.isDir(stream.mode)?3:FS.isLink(stream.mode)?7:4}HEAP8[pbuf]=type;checkInt8(type);HEAP16[pbuf+2>>1]=flags;checkInt16(flags);tempI64=[rightsBase>>>0,(tempDouble=rightsBase,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[pbuf+8>>2]=tempI64[0],HEAP32[pbuf+12>>2]=tempI64[1];checkInt64(rightsBase);tempI64=[rightsInheriting>>>0,(tempDouble=rightsInheriting,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[pbuf+16>>2]=tempI64[0],HEAP32[pbuf+20>>2]=tempI64[1];checkInt64(rightsInheriting);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var doReadv=(stream,iov,iovcnt,offset)=>{var ret=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;var curr=FS.read(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr>2]=num;checkInt32(num);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){var offset=convertI32PairToI53Checked(offset_low,offset_high);try{if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);FS.llseek(stream,offset,whence);tempI64=[stream.position>>>0,(tempDouble=stream.position,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[newOffset>>2]=tempI64[0],HEAP32[newOffset+4>>2]=tempI64[1];checkInt64(stream.position);if(stream.getdents&&offset===0&&whence===0)stream.getdents=null;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var doWritev=(stream,iov,iovcnt,offset)=>{var ret=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;var curr=FS.write(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr>2]=num;checkInt32(num);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var _getentropy=(buffer,size)=>{randomFill(HEAPU8.subarray(buffer,buffer+size));return 0};var _llvm_eh_typeid_for=type=>type;var runtimeKeepaliveCounter=0;var keepRuntimeAlive=()=>noExitRuntime||runtimeKeepaliveCounter>0;var _proc_exit=code=>{EXITSTATUS=code;if(!keepRuntimeAlive()){Module["onExit"]?.(code);ABORT=true}quit_(code,new ExitStatus(code))};var getCFunc=ident=>{var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func};var writeArrayToMemory=(array,buffer)=>{assert(array.length>=0,"writeArrayToMemory array must have a length (should be an array or typed array)");HEAP8.set(array,buffer)};var stackAlloc=sz=>__emscripten_stack_alloc(sz);var stringToUTF8OnStack=str=>{var size=lengthBytesUTF8(str)+1;var ret=stackAlloc(size);stringToUTF8(str,ret,size);return ret};var ccall=(ident,returnType,argTypes,args,opts)=>{var toC={string:str=>{var ret=0;if(str!==null&&str!==undefined&&str!==0){ret=stringToUTF8OnStack(str)}return ret},array:arr=>{var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string"){return UTF8ToString(ret)}if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;assert(returnType!=="array",'Return type should not be "array".');if(args){for(var i=0;i(...args)=>ccall(ident,returnType,argTypes,args,opts);FS.createPreloadedFile=FS_createPreloadedFile;FS.staticInit();function checkIncomingModuleAPI(){ignoredModuleProp("fetchSettings")}var wasmImports={__assert_fail:___assert_fail,__call_sighandler:___call_sighandler,__cxa_begin_catch:___cxa_begin_catch,__cxa_end_catch:___cxa_end_catch,__cxa_find_matching_catch_2:___cxa_find_matching_catch_2,__cxa_find_matching_catch_3:___cxa_find_matching_catch_3,__cxa_rethrow:___cxa_rethrow,__cxa_throw:___cxa_throw,__handle_stack_overflow:___handle_stack_overflow,__resumeException:___resumeException,__syscall_faccessat:___syscall_faccessat,__syscall_fcntl64:___syscall_fcntl64,__syscall_fstat64:___syscall_fstat64,__syscall_getdents64:___syscall_getdents64,__syscall_ioctl:___syscall_ioctl,__syscall_lstat64:___syscall_lstat64,__syscall_mkdirat:___syscall_mkdirat,__syscall_newfstatat:___syscall_newfstatat,__syscall_openat:___syscall_openat,__syscall_rmdir:___syscall_rmdir,__syscall_stat64:___syscall_stat64,__syscall_unlinkat:___syscall_unlinkat,_abort_js:__abort_js,_emscripten_get_now_is_monotonic:__emscripten_get_now_is_monotonic,_emscripten_memcpy_js:__emscripten_memcpy_js,_emscripten_runtime_keepalive_clear:__emscripten_runtime_keepalive_clear,_emscripten_throw_longjmp:__emscripten_throw_longjmp,_mmap_js:__mmap_js,_munmap_js:__munmap_js,_tzset_js:__tzset_js,emscripten_date_now:_emscripten_date_now,emscripten_get_heap_max:_emscripten_get_heap_max,emscripten_get_now:_emscripten_get_now,emscripten_resize_heap:_emscripten_resize_heap,environ_get:_environ_get,environ_sizes_get:_environ_sizes_get,fd_close:_fd_close,fd_fdstat_get:_fd_fdstat_get,fd_read:_fd_read,fd_seek:_fd_seek,fd_write:_fd_write,getentropy:_getentropy,invoke_d,invoke_diii,invoke_fi,invoke_fif,invoke_fifff,invoke_fii,invoke_fiii,invoke_fiiii,invoke_fiiiiii,invoke_fiiiiiii,invoke_fij,invoke_i,invoke_idiii,invoke_ii,invoke_iif,invoke_iifi,invoke_iifii,invoke_iifiiiii,invoke_iii,invoke_iiid,invoke_iiidii,invoke_iiif,invoke_iiiffi,invoke_iiii,invoke_iiiidi,invoke_iiiiffifffffffi,invoke_iiiifiii,invoke_iiiii,invoke_iiiiif,invoke_iiiiifi,invoke_iiiiii,invoke_iiiiiifi,invoke_iiiiiififiiiififiiiiiiiiiiiiiiiiiiii,invoke_iiiiiii,invoke_iiiiiiifii,invoke_iiiiiiii,invoke_iiiiiiiii,invoke_iiiiiiiiiffi,invoke_iiiiiiiiii,invoke_iiiiiiiiiifi,invoke_iiiiiiiiiii,invoke_iiiiiiiiiiii,invoke_iiiiiiiiiiiif,invoke_iiiiiiiiiiiiiii,invoke_iiiiiiij,invoke_iiiiiij,invoke_iiiiij,invoke_iiiij,invoke_iiij,invoke_iiiji,invoke_iiijii,invoke_iiijiii,invoke_iij,invoke_iijiii,invoke_iijj,invoke_iijji,invoke_iijjiii,invoke_ij,invoke_ijjiii,invoke_j,invoke_ji,invoke_jii,invoke_jiii,invoke_jiji,invoke_v,invoke_vdiii,invoke_vi,invoke_vid,invoke_vif,invoke_vififiif,invoke_vifii,invoke_vifiiifiiiiiiiiiiiiifiiii,invoke_vii,invoke_viid,invoke_viif,invoke_viiff,invoke_viifi,invoke_viifiii,invoke_viii,invoke_viiid,invoke_viiif,invoke_viiiffii,invoke_viiiffiiii,invoke_viiifi,invoke_viiii,invoke_viiiif,invoke_viiiii,invoke_viiiiif,invoke_viiiiii,invoke_viiiiiid,invoke_viiiiiif,invoke_viiiiiifi,invoke_viiiiiifif,invoke_viiiiiifii,invoke_viiiiiii,invoke_viiiiiiidiiii,invoke_viiiiiiii,invoke_viiiiiiiif,invoke_viiiiiiiii,invoke_viiiiiiiiii,invoke_viiiiiiiiiidii,invoke_viiiiiiiiiii,invoke_viiiiiiiiiiii,invoke_viiiiiiiiiiiiii,invoke_viiiiiiiiiiiiiiii,invoke_viiiiij,invoke_viiiiiji,invoke_viiiiji,invoke_viiiijiiifi,invoke_viiij,invoke_viiiji,invoke_viiijii,invoke_viiijjji,invoke_viij,invoke_viiji,invoke_viijii,invoke_viijiiii,invoke_viijj,invoke_vij,invoke_viji,invoke_vijif,invoke_vijii,invoke_vijj,invoke_vjjiii,llvm_eh_typeid_for:_llvm_eh_typeid_for,proc_exit:_proc_exit};var wasmExports=createWasm();var ___wasm_call_ctors=createExportWrapper("__wasm_call_ctors",0);var _web_engine_create=Module["_web_engine_create"]=createExportWrapper("web_engine_create",0);var _web_engine_get_memory_stats=Module["_web_engine_get_memory_stats"]=createExportWrapper("web_engine_get_memory_stats",1);var _web_engine_destroy=Module["_web_engine_destroy"]=createExportWrapper("web_engine_destroy",1);var _fflush=createExportWrapper("fflush",1);var _web_engine_get_live_handles=Module["_web_engine_get_live_handles"]=createExportWrapper("web_engine_get_live_handles",0);var _web_engine_get_allocated_bytes=Module["_web_engine_get_allocated_bytes"]=createExportWrapper("web_engine_get_allocated_bytes",0);var _web_engine_open_blend=Module["_web_engine_open_blend"]=createExportWrapper("web_engine_open_blend",3);var _web_engine_apply_command=Module["_web_engine_apply_command"]=createExportWrapper("web_engine_apply_command",3);var _web_engine_decimate_apply=Module["_web_engine_decimate_apply"]=createExportWrapper("web_engine_decimate_apply",35);var _web_engine_append_library_object=Module["_web_engine_append_library_object"]=createExportWrapper("web_engine_append_library_object",5);var _web_engine_undo=Module["_web_engine_undo"]=createExportWrapper("web_engine_undo",1);var _web_engine_redo=Module["_web_engine_redo"]=createExportWrapper("web_engine_redo",1);var _web_engine_get_scene_snapshot=Module["_web_engine_get_scene_snapshot"]=createExportWrapper("web_engine_get_scene_snapshot",3);var _web_engine_get_scene_metadata=Module["_web_engine_get_scene_metadata"]=createExportWrapper("web_engine_get_scene_metadata",3);var _web_engine_get_scene_geometry=Module["_web_engine_get_scene_geometry"]=createExportWrapper("web_engine_get_scene_geometry",3);var _web_engine_get_scene_delta=Module["_web_engine_get_scene_delta"]=createExportWrapper("web_engine_get_scene_delta",3);var _web_engine_get_packed_asset=Module["_web_engine_get_packed_asset"]=createExportWrapper("web_engine_get_packed_asset",5);var _web_engine_evaluate_depsgraph=Module["_web_engine_evaluate_depsgraph"]=createExportWrapper("web_engine_evaluate_depsgraph",3);var _web_engine_save_blend=Module["_web_engine_save_blend"]=createExportWrapper("web_engine_save_blend",3);var _malloc=Module["_malloc"]=createExportWrapper("malloc",1);var _web_engine_free_buffer=Module["_web_engine_free_buffer"]=createExportWrapper("web_engine_free_buffer",1);var _free=Module["_free"]=createExportWrapper("free",1);var _web_engine_last_error_code=Module["_web_engine_last_error_code"]=createExportWrapper("web_engine_last_error_code",0);var _web_engine_last_error_message=Module["_web_engine_last_error_message"]=createExportWrapper("web_engine_last_error_message",0);var _strerror=createExportWrapper("strerror",1);var _emscripten_builtin_memalign=createExportWrapper("emscripten_builtin_memalign",2);var _setThrew=createExportWrapper("setThrew",2);var __emscripten_tempret_set=createExportWrapper("_emscripten_tempret_set",1);var __emscripten_tempret_get=createExportWrapper("_emscripten_tempret_get",0);var _emscripten_stack_init=()=>(_emscripten_stack_init=wasmExports["emscripten_stack_init"])();var _emscripten_stack_get_free=()=>(_emscripten_stack_get_free=wasmExports["emscripten_stack_get_free"])();var _emscripten_stack_get_base=()=>(_emscripten_stack_get_base=wasmExports["emscripten_stack_get_base"])();var _emscripten_stack_get_end=()=>(_emscripten_stack_get_end=wasmExports["emscripten_stack_get_end"])();var __emscripten_stack_restore=a0=>(__emscripten_stack_restore=wasmExports["_emscripten_stack_restore"])(a0);var __emscripten_stack_alloc=a0=>(__emscripten_stack_alloc=wasmExports["_emscripten_stack_alloc"])(a0);var _emscripten_stack_get_current=()=>(_emscripten_stack_get_current=wasmExports["emscripten_stack_get_current"])();var ___cxa_decrement_exception_refcount=createExportWrapper("__cxa_decrement_exception_refcount",1);var ___cxa_increment_exception_refcount=createExportWrapper("__cxa_increment_exception_refcount",1);var ___cxa_can_catch=createExportWrapper("__cxa_can_catch",3);var ___cxa_get_exception_ptr=createExportWrapper("__cxa_get_exception_ptr",1);var ___set_stack_limits=Module["___set_stack_limits"]=createExportWrapper("__set_stack_limits",2);var dynCall_viij=Module["dynCall_viij"]=createExportWrapper("dynCall_viij",5);var dynCall_viiji=Module["dynCall_viiji"]=createExportWrapper("dynCall_viiji",6);var dynCall_viijiiii=Module["dynCall_viijiiii"]=createExportWrapper("dynCall_viijiiii",9);var dynCall_vij=Module["dynCall_vij"]=createExportWrapper("dynCall_vij",4);var dynCall_viijii=Module["dynCall_viijii"]=createExportWrapper("dynCall_viijii",7);var dynCall_viiiijiiifi=Module["dynCall_viiiijiiifi"]=createExportWrapper("dynCall_viiiijiiifi",12);var dynCall_viiijjji=Module["dynCall_viiijjji"]=createExportWrapper("dynCall_viiijjji",11);var dynCall_viiiiji=Module["dynCall_viiiiji"]=createExportWrapper("dynCall_viiiiji",8);var dynCall_viiiji=Module["dynCall_viiiji"]=createExportWrapper("dynCall_viiiji",7);var dynCall_ij=Module["dynCall_ij"]=createExportWrapper("dynCall_ij",3);var dynCall_viji=Module["dynCall_viji"]=createExportWrapper("dynCall_viji",5);var dynCall_iij=Module["dynCall_iij"]=createExportWrapper("dynCall_iij",4);var dynCall_fij=Module["dynCall_fij"]=createExportWrapper("dynCall_fij",4);var dynCall_vijf=Module["dynCall_vijf"]=createExportWrapper("dynCall_vijf",5);var dynCall_jiii=Module["dynCall_jiii"]=createExportWrapper("dynCall_jiii",4);var dynCall_viiij=Module["dynCall_viiij"]=createExportWrapper("dynCall_viiij",6);var dynCall_iiijii=Module["dynCall_iiijii"]=createExportWrapper("dynCall_iiijii",7);var dynCall_iiijiii=Module["dynCall_iiijiii"]=createExportWrapper("dynCall_iiijiii",8);var dynCall_iiij=Module["dynCall_iiij"]=createExportWrapper("dynCall_iiij",5);var dynCall_vjjiii=Module["dynCall_vjjiii"]=createExportWrapper("dynCall_vjjiii",8);var dynCall_ijjiii=Module["dynCall_ijjiii"]=createExportWrapper("dynCall_ijjiii",8);var dynCall_iijiii=Module["dynCall_iijiii"]=createExportWrapper("dynCall_iijiii",7);var dynCall_iijjiii=Module["dynCall_iijjiii"]=createExportWrapper("dynCall_iijjiii",9);var dynCall_iiiji=Module["dynCall_iiiji"]=createExportWrapper("dynCall_iiiji",6);var dynCall_jii=Module["dynCall_jii"]=createExportWrapper("dynCall_jii",3);var dynCall_iijj=Module["dynCall_iijj"]=createExportWrapper("dynCall_iijj",6);var dynCall_vijj=Module["dynCall_vijj"]=createExportWrapper("dynCall_vijj",6);var dynCall_ji=Module["dynCall_ji"]=createExportWrapper("dynCall_ji",2);var dynCall_vijii=Module["dynCall_vijii"]=createExportWrapper("dynCall_vijii",6);var dynCall_vijif=Module["dynCall_vijif"]=createExportWrapper("dynCall_vijif",6);var dynCall_viiiiij=Module["dynCall_viiiiij"]=createExportWrapper("dynCall_viiiiij",8);var dynCall_viiiiiji=Module["dynCall_viiiiiji"]=createExportWrapper("dynCall_viiiiiji",9);var dynCall_iiiij=Module["dynCall_iiiij"]=createExportWrapper("dynCall_iiiij",6);var dynCall_iijji=Module["dynCall_iijji"]=createExportWrapper("dynCall_iijji",7);var dynCall_j=Module["dynCall_j"]=createExportWrapper("dynCall_j",1);var dynCall_iiiiiiij=Module["dynCall_iiiiiiij"]=createExportWrapper("dynCall_iiiiiiij",9);var dynCall_viijj=Module["dynCall_viijj"]=createExportWrapper("dynCall_viijj",7);var dynCall_iiiiij=Module["dynCall_iiiiij"]=createExportWrapper("dynCall_iiiiij",7);var dynCall_viiijii=Module["dynCall_viiijii"]=createExportWrapper("dynCall_viiijii",8);var dynCall_jij=Module["dynCall_jij"]=createExportWrapper("dynCall_jij",4);var dynCall_vijji=Module["dynCall_vijji"]=createExportWrapper("dynCall_vijji",7);var dynCall_iiiiiij=Module["dynCall_iiiiiij"]=createExportWrapper("dynCall_iiiiiij",8);var dynCall_jiji=Module["dynCall_jiji"]=createExportWrapper("dynCall_jiji",5);var dynCall_iiiiijj=Module["dynCall_iiiiijj"]=createExportWrapper("dynCall_iiiiijj",9);var dynCall_iiiiiijj=Module["dynCall_iiiiiijj"]=createExportWrapper("dynCall_iiiiiijj",10);function invoke_ii(index,a1){var sp=stackSave();try{return getWasmTableEntry(index)(a1)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_v(index){var sp=stackSave();try{getWasmTableEntry(index)()}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiii(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viii(index,a1,a2,a3){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiii(index,a1,a2,a3,a4){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vi(index,a1){var sp=stackSave();try{getWasmTableEntry(index)(a1)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vif(index,a1,a2){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iii(index,a1,a2){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fi(index,a1){var sp=stackSave();try{return getWasmTableEntry(index)(a1)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiif(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vii(index,a1,a2){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiii(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_i(index){var sp=stackSave();try{return getWasmTableEntry(index)()}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fiii(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_diii(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viifiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiffi(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiifii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiffifffffffi(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiifi(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiiiifi(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiififiiiififiiiiiiiiiiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,a22,a23,a24,a25,a26,a27,a28,a29,a30,a31,a32,a33,a34,a35){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,a22,a23,a24,a25,a26,a27,a28,a29,a30,a31,a32,a33,a34,a35)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vififiif(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vifii(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fiiii(index,a1,a2,a3,a4){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viif(index,a1,a2,a3){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viifi(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiif(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiif(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiif(index,a1,a2,a3,a4,a5){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fif(index,a1,a2){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiifi(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iifii(index,a1,a2,a3,a4){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fii(index,a1,a2){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fiiiiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iifi(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiif(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vdiii(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_idiii(index,a1,a2,a3,a4){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiif(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiifii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiifiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_d(index){var sp=stackSave();try{return getWasmTableEntry(index)()}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fifff(index,a1,a2,a3,a4){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiifi(index,a1,a2,a3,a4,a5){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fiiiiiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiifi(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vid(index,a1,a2){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiff(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iif(index,a1,a2){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiiiffi(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiffiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iifiiiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiifif(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiif(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vifiiifiiiiiiiiiiiiifiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,a22,a23,a24){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,a22,a23,a24)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiiiiiif(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiid(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiidiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiiiidii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiidi(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viid(index,a1,a2,a3){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiidii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiid(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiffii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiid(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fij(index,a1,a2,a3){var sp=stackSave();try{return dynCall_fij(index,a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viij(index,a1,a2,a3,a4){var sp=stackSave();try{dynCall_viij(index,a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iij(index,a1,a2,a3){var sp=stackSave();try{return dynCall_iij(index,a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_ij(index,a1,a2){var sp=stackSave();try{return dynCall_ij(index,a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vij(index,a1,a2,a3){var sp=stackSave();try{dynCall_vij(index,a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_jiii(index,a1,a2,a3){var sp=stackSave();try{return dynCall_jiii(index,a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiji(index,a1,a2,a3,a4,a5){var sp=stackSave();try{dynCall_viiji(index,a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viijiiii(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSave();try{dynCall_viijiiii(index,a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viijii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{dynCall_viijii(index,a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiijiiifi(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){var sp=stackSave();try{dynCall_viiiijiiifi(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiijjji(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){var sp=stackSave();try{dynCall_viiijjji(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiji(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{dynCall_viiiiji(index,a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiji(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{dynCall_viiiji(index,a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiij(index,a1,a2,a3,a4,a5){var sp=stackSave();try{dynCall_viiij(index,a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiijii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return dynCall_iiijii(index,a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiijiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return dynCall_iiijiii(index,a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiij(index,a1,a2,a3,a4){var sp=stackSave();try{return dynCall_iiij(index,a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viji(index,a1,a2,a3,a4){var sp=stackSave();try{dynCall_viji(index,a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vijii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{dynCall_vijii(index,a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiji(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return dynCall_iiiji(index,a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iijiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return dynCall_iijiii(index,a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iijjiii(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSave();try{return dynCall_iijjiii(index,a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vjjiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{dynCall_vjjiii(index,a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_ijjiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return dynCall_ijjiii(index,a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iijj(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return dynCall_iijj(index,a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vijj(index,a1,a2,a3,a4,a5){var sp=stackSave();try{dynCall_vijj(index,a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiij(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{dynCall_viiiiij(index,a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vijif(index,a1,a2,a3,a4,a5){var sp=stackSave();try{dynCall_vijif(index,a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiji(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSave();try{dynCall_viiiiiji(index,a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iijji(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return dynCall_iijji(index,a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viijj(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{dynCall_viijj(index,a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_ji(index,a1){var sp=stackSave();try{return dynCall_ji(index,a1)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiij(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return dynCall_iiiiij(index,a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiij(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return dynCall_iiiij(index,a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_j(index){var sp=stackSave();try{return dynCall_j(index)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiij(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSave();try{return dynCall_iiiiiiij(index,a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiijii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{dynCall_viiijii(index,a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_jii(index,a1,a2){var sp=stackSave();try{return dynCall_jii(index,a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiij(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return dynCall_iiiiiij(index,a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_jiji(index,a1,a2,a3,a4){var sp=stackSave();try{return dynCall_jiji(index,a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}Module["ccall"]=ccall;Module["cwrap"]=cwrap;Module["UTF8ToString"]=UTF8ToString;var missingLibrarySymbols=["writeI53ToI64","writeI53ToI64Clamped","writeI53ToI64Signaling","writeI53ToU64Clamped","writeI53ToU64Signaling","readI53FromI64","readI53FromU64","convertI32PairToI53","convertU32PairToI53","getTempRet0","exitJS","inetPton4","inetNtop4","inetPton6","inetNtop6","readSockaddr","writeSockaddr","emscriptenLog","readEmAsmArgs","jstoi_q","listenOnce","autoResumeAudioContext","dynCallLegacy","getDynCaller","dynCall","handleException","runtimeKeepalivePush","runtimeKeepalivePop","callUserCallback","maybeExit","asmjsMangle","HandleAllocator","getNativeTypeSize","STACK_SIZE","STACK_ALIGN","POINTER_SIZE","ASSERTIONS","uleb128Encode","sigToWasmTypes","generateFuncType","convertJsFunctionToWasm","getEmptyTableSlot","updateTableMap","getFunctionAddress","addFunction","removeFunction","reallyNegative","unSign","strLen","reSign","formatString","intArrayToString","AsciiToString","UTF16ToString","stringToUTF16","lengthBytesUTF16","UTF32ToString","stringToUTF32","lengthBytesUTF32","stringToNewUTF8","registerKeyEventCallback","maybeCStringToJsString","findEventTarget","getBoundingClientRect","fillMouseEventData","registerMouseEventCallback","registerWheelEventCallback","registerUiEventCallback","registerFocusEventCallback","fillDeviceOrientationEventData","registerDeviceOrientationEventCallback","fillDeviceMotionEventData","registerDeviceMotionEventCallback","screenOrientation","fillOrientationChangeEventData","registerOrientationChangeEventCallback","fillFullscreenChangeEventData","registerFullscreenChangeEventCallback","JSEvents_requestFullscreen","JSEvents_resizeCanvasForFullscreen","registerRestoreOldStyle","hideEverythingExceptGivenElement","restoreHiddenElements","setLetterbox","softFullscreenResizeWebGLRenderTarget","doRequestFullscreen","fillPointerlockChangeEventData","registerPointerlockChangeEventCallback","registerPointerlockErrorEventCallback","requestPointerLock","fillVisibilityChangeEventData","registerVisibilityChangeEventCallback","registerTouchEventCallback","fillGamepadEventData","registerGamepadEventCallback","registerBeforeUnloadEventCallback","fillBatteryEventData","battery","registerBatteryEventCallback","setCanvasElementSize","getCanvasElementSize","jsStackTrace","getCallstack","convertPCtoSourceLocation","checkWasiClock","wasiRightsToMuslOFlags","wasiOFlagsToMuslOFlags","createDyncallWrapper","safeSetTimeout","setImmediateWrapped","clearImmediateWrapped","polyfillSetImmediate","registerPostMainLoop","registerPreMainLoop","getPromise","makePromise","idsToPromises","makePromiseCallback","Browser_asyncPrepareDataCounter","safeRequestAnimationFrame","isLeapYear","ydayFromDate","arraySum","addDays","getSocketFromFD","getSocketAddress","FS_unlink","FS_mkdirTree","_setNetworkCallback","heapObjectForWebGLType","toTypedArrayIndex","webgl_enable_ANGLE_instanced_arrays","webgl_enable_OES_vertex_array_object","webgl_enable_WEBGL_draw_buffers","webgl_enable_WEBGL_multi_draw","webgl_enable_EXT_polygon_offset_clamp","webgl_enable_EXT_clip_control","webgl_enable_WEBGL_polygon_mode","emscriptenWebGLGet","computeUnpackAlignedImageSize","colorChannelsInGlTextureFormat","emscriptenWebGLGetTexPixelData","emscriptenWebGLGetUniform","webglGetUniformLocation","webglPrepareUniformLocationsBeforeFirstUse","webglGetLeftBracePos","emscriptenWebGLGetVertexAttrib","__glGetActiveAttribOrUniform","writeGLArray","registerWebGlEventCallback","runAndAbortIfError","ALLOC_NORMAL","ALLOC_STACK","allocate","writeStringToMemory","writeAsciiToMemory","setErrNo","demangle","stackTrace"];missingLibrarySymbols.forEach(missingLibrarySymbol);var unexportedSymbols=["run","addOnPreRun","addOnInit","addOnPreMain","addOnExit","addOnPostRun","addRunDependency","removeRunDependency","out","err","callMain","abort","wasmMemory","wasmExports","writeStackCookie","checkStackCookie","convertI32PairToI53Checked","stackSave","stackRestore","stackAlloc","setTempRet0","ptrToString","zeroMemory","getHeapMax","growMemory","ENV","setStackLimits","ERRNO_CODES","strError","DNS","Protocols","Sockets","initRandomFill","randomFill","timers","warnOnce","readEmAsmArgsArray","jstoi_s","getExecutableName","keepRuntimeAlive","asyncLoad","alignMemory","mmapAlloc","wasmTable","noExitRuntime","getCFunc","freeTableIndexes","functionsInTableMap","setValue","getValue","PATH","PATH_FS","UTF8Decoder","UTF8ArrayToString","stringToUTF8Array","stringToUTF8","lengthBytesUTF8","intArrayFromString","stringToAscii","UTF16Decoder","stringToUTF8OnStack","writeArrayToMemory","JSEvents","specialHTMLTargets","findCanvasEventTarget","currentFullscreenStrategy","restoreOldWindowedStyle","UNWIND_CACHE","ExitStatus","getEnvStrings","doReadv","doWritev","promiseMap","uncaughtExceptionCount","exceptionLast","exceptionCaught","ExceptionInfo","findMatchingCatch","Browser","getPreloadedImageData__data","wget","MONTH_DAYS_REGULAR","MONTH_DAYS_LEAP","MONTH_DAYS_REGULAR_CUMULATIVE","MONTH_DAYS_LEAP_CUMULATIVE","SYSCALLS","preloadPlugins","FS_createPreloadedFile","FS_modeStringToFlags","FS_getMode","FS_stdin_getChar_buffer","FS_stdin_getChar","FS_createPath","FS_createDevice","FS_readFile","FS","FS_createDataFile","FS_createLazyFile","MEMFS","TTY","PIPEFS","SOCKFS","tempFixedLengthArray","miniTempWebGLFloatBuffers","miniTempWebGLIntBuffers","GL","AL","GLUT","EGL","GLEW","IDBStore","SDL","SDL_gfx","allocateUTF8","allocateUTF8OnStack","print","printErr"];unexportedSymbols.forEach(unexportedRuntimeSymbol);var calledRun;var calledPrerun;dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function stackCheckInit(){_emscripten_stack_init();writeStackCookie()}function run(){if(runDependencies>0){return}stackCheckInit();if(!calledPrerun){calledPrerun=1;preRun();if(runDependencies>0){return}}function doRun(){if(calledRun)return;calledRun=1;Module["calledRun"]=1;if(ABORT)return;initRuntime();readyPromiseResolve(Module);Module["onRuntimeInitialized"]?.();assert(!Module["_main"],'compiled without a main, but one is present. if you added it from JS, use Module["onRuntimeInitialized"]');postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(()=>{setTimeout(()=>Module["setStatus"](""),1);doRun()},1)}else{doRun()}checkStackCookie()}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}run();moduleRtn=readyPromise;for(const prop of Object.keys(Module)){if(!(prop in moduleArg)){Object.defineProperty(moduleArg,prop,{configurable:true,get(){abort(`Access to module property ('${prop}') is no longer possible via the module constructor argument; Instead, use the result of the module constructor.`)}})}} return moduleRtn; diff --git a/web/app/public/vendor/blender/web_engine.wasm b/web/app/public/vendor/blender/web_engine.wasm index 258cfd4b..71539893 100644 Binary files a/web/app/public/vendor/blender/web_engine.wasm and b/web/app/public/vendor/blender/web_engine.wasm differ diff --git a/web/app/src/vendor/blender/web_engine.js b/web/app/src/vendor/blender/web_engine.js index c644158c..144e0b10 100644 --- a/web/app/src/vendor/blender/web_engine.js +++ b/web/app/src/vendor/blender/web_engine.js @@ -6,7 +6,7 @@ var Module = (() => { async function(moduleArg = {}) { var moduleRtn; -var Module=moduleArg;var readyPromiseResolve,readyPromiseReject;var readyPromise=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject});["_malloc","_free","_web_engine_create","_web_engine_destroy","_web_engine_get_memory_stats","_web_engine_get_live_handles","_web_engine_get_allocated_bytes","_web_engine_open_blend","_web_engine_apply_command","_web_engine_append_library_object","_web_engine_undo","_web_engine_redo","_web_engine_get_scene_snapshot","_web_engine_get_scene_metadata","_web_engine_get_scene_geometry","_web_engine_get_scene_delta","_web_engine_get_packed_asset","_web_engine_evaluate_depsgraph","_web_engine_save_blend","_web_engine_free_buffer","_web_engine_last_error_code","_web_engine_last_error_message","_web_engine_decimate_apply","_memory","___indirect_function_table","___set_stack_limits","onRuntimeInitialized"].forEach(prop=>{if(!Object.getOwnPropertyDescriptor(readyPromise,prop)){Object.defineProperty(readyPromise,prop,{get:()=>abort("You are getting "+prop+" on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js"),set:()=>abort("You are setting "+prop+" on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js")})}});var ENVIRONMENT_IS_WEB=typeof window=="object";var ENVIRONMENT_IS_WORKER=typeof importScripts=="function";var ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string"&&process.type!="renderer";var ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;if(ENVIRONMENT_IS_NODE){const{createRequire}=await import("module");let dirname=import.meta.url;if(dirname.startsWith("data:")){dirname="/"}var require=createRequire(dirname)}var moduleOverrides=Object.assign({},Module);var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_NODE){if(typeof process=="undefined"||!process.release||process.release.name!=="node")throw new Error("not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)");var nodeVersion=process.versions.node;var numericVersion=nodeVersion.split(".").slice(0,3);numericVersion=numericVersion[0]*1e4+numericVersion[1]*100+numericVersion[2].split("-")[0]*1;if(numericVersion<16e4){throw new Error("This emscripten-generated code requires node v16.0.0 (detected v"+nodeVersion+")")}var fs=require("fs");var nodePath=require("path");if(!import.meta.url.startsWith("data:")){scriptDirectory=nodePath.dirname(require("url").fileURLToPath(import.meta.url))+"/"}readBinary=filename=>{filename=isFileURI(filename)?new URL(filename):nodePath.normalize(filename);var ret=fs.readFileSync(filename);assert(ret.buffer);return ret};readAsync=(filename,binary=true)=>{filename=isFileURI(filename)?new URL(filename):nodePath.normalize(filename);return new Promise((resolve,reject)=>{fs.readFile(filename,binary?undefined:"utf8",(err,data)=>{if(err)reject(err);else resolve(binary?data.buffer:data)})})};if(!Module["thisProgram"]&&process.argv.length>1){thisProgram=process.argv[1].replace(/\\/g,"/")}arguments_=process.argv.slice(2);quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow}}else if(ENVIRONMENT_IS_SHELL){if(typeof process=="object"&&typeof require==="function"||typeof window=="object"||typeof importScripts=="function")throw new Error("not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)")}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(_scriptName){scriptDirectory=_scriptName}if(scriptDirectory.startsWith("blob:")){scriptDirectory=""}else{scriptDirectory=scriptDirectory.substr(0,scriptDirectory.replace(/[?#].*/,"").lastIndexOf("/")+1)}if(!(typeof window=="object"||typeof importScripts=="function"))throw new Error("not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)");{if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=url=>{assert(!isFileURI(url),"readAsync does not work with file:// URLs");return fetch(url,{credentials:"same-origin"}).then(response=>{if(response.ok){return response.arrayBuffer()}return Promise.reject(new Error(response.status+" : "+response.url))})}}}else{throw new Error("environment detection error")}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.error.bind(console);Object.assign(Module,moduleOverrides);moduleOverrides=null;checkIncomingModuleAPI();if(Module["arguments"])arguments_=Module["arguments"];legacyModuleProp("arguments","arguments_");if(Module["thisProgram"])thisProgram=Module["thisProgram"];legacyModuleProp("thisProgram","thisProgram");assert(typeof Module["memoryInitializerPrefixURL"]=="undefined","Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["pthreadMainPrefixURL"]=="undefined","Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["cdInitializerPrefixURL"]=="undefined","Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["filePackagePrefixURL"]=="undefined","Module.filePackagePrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["read"]=="undefined","Module.read option was removed");assert(typeof Module["readAsync"]=="undefined","Module.readAsync option was removed (modify readAsync in JS)");assert(typeof Module["readBinary"]=="undefined","Module.readBinary option was removed (modify readBinary in JS)");assert(typeof Module["setWindowTitle"]=="undefined","Module.setWindowTitle option was removed (modify emscripten_set_window_title in JS)");assert(typeof Module["TOTAL_MEMORY"]=="undefined","Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY");legacyModuleProp("asm","wasmExports");legacyModuleProp("readAsync","readAsync");legacyModuleProp("readBinary","readBinary");legacyModuleProp("setWindowTitle","setWindowTitle");assert(!ENVIRONMENT_IS_SHELL,"shell environment detected but not enabled at build time. Add `shell` to `-sENVIRONMENT` to enable.");var wasmBinary=Module["wasmBinary"];legacyModuleProp("wasmBinary","wasmBinary");if(typeof WebAssembly!="object"){err("no native wasm support detected")}var wasmMemory;var ABORT=false;var EXITSTATUS;function assert(condition,text){if(!condition){abort("Assertion failed"+(text?": "+text:""))}}var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateMemoryViews(){var b=wasmMemory.buffer;Module["HEAP8"]=HEAP8=new Int8Array(b);Module["HEAP16"]=HEAP16=new Int16Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);Module["HEAPU16"]=HEAPU16=new Uint16Array(b);Module["HEAP32"]=HEAP32=new Int32Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);Module["HEAPF64"]=HEAPF64=new Float64Array(b)}assert(!Module["STACK_SIZE"],"STACK_SIZE can no longer be set at runtime. Use -sSTACK_SIZE at link time");assert(typeof Int32Array!="undefined"&&typeof Float64Array!=="undefined"&&Int32Array.prototype.subarray!=undefined&&Int32Array.prototype.set!=undefined,"JS engine does not provide full typed array support");assert(!Module["wasmMemory"],"Use of `wasmMemory` detected. Use -sIMPORTED_MEMORY to define wasmMemory externally");assert(!Module["INITIAL_MEMORY"],"Detected runtime INITIAL_MEMORY setting. Use -sIMPORTED_MEMORY to define wasmMemory dynamically");function writeStackCookie(){var max=_emscripten_stack_get_end();assert((max&3)==0);if(max==0){max+=4}HEAPU32[max>>2]=34821223;checkInt32(34821223);HEAPU32[max+4>>2]=2310721022;checkInt32(2310721022);HEAPU32[0>>2]=1668509029;checkInt32(1668509029)}function checkStackCookie(){if(ABORT)return;var max=_emscripten_stack_get_end();if(max==0){max+=4}var cookie1=HEAPU32[max>>2];var cookie2=HEAPU32[max+4>>2];if(cookie1!=34821223||cookie2!=2310721022){abort(`Stack overflow! Stack cookie has been overwritten at ${ptrToString(max)}, expected hex dwords 0x89BACDFE and 0x2135467, but received ${ptrToString(cookie2)} ${ptrToString(cookie1)}`)}if(HEAPU32[0>>2]!=1668509029){abort("Runtime error: The application has corrupted its heap memory area (address zero)!")}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;function preRun(){var preRuns=Module["preRun"];if(preRuns){if(typeof preRuns=="function")preRuns=[preRuns];preRuns.forEach(addOnPreRun)}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){assert(!runtimeInitialized);runtimeInitialized=true;checkStackCookie();setStackLimits();if(!Module["noFSInit"]&&!FS.initialized)FS.init();FS.ignorePermissions=false;TTY.init();callRuntimeCallbacks(__ATINIT__)}function postRun(){checkStackCookie();var postRuns=Module["postRun"];if(postRuns){if(typeof postRuns=="function")postRuns=[postRuns];postRuns.forEach(addOnPostRun)}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnInit(cb){__ATINIT__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}assert(Math.imul,"This browser does not support Math.imul(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.fround,"This browser does not support Math.fround(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.clz32,"This browser does not support Math.clz32(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.trunc,"This browser does not support Math.trunc(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;var runDependencyTracking={};function getUniqueRunDependency(id){var orig=id;while(1){if(!runDependencyTracking[id])return id;id=orig+Math.random()}}function addRunDependency(id){runDependencies++;Module["monitorRunDependencies"]?.(runDependencies);if(id){assert(!runDependencyTracking[id]);runDependencyTracking[id]=1;if(runDependencyWatcher===null&&typeof setInterval!="undefined"){runDependencyWatcher=setInterval(()=>{if(ABORT){clearInterval(runDependencyWatcher);runDependencyWatcher=null;return}var shown=false;for(var dep in runDependencyTracking){if(!shown){shown=true;err("still waiting on run dependencies:")}err(`dependency: ${dep}`)}if(shown){err("(end of list)")}},1e4)}}else{err("warning: run dependency added without ID")}}function removeRunDependency(id){runDependencies--;Module["monitorRunDependencies"]?.(runDependencies);if(id){assert(runDependencyTracking[id]);delete runDependencyTracking[id]}else{err("warning: run dependency removed without ID")}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}function abort(what){Module["onAbort"]?.(what);what="Aborted("+what+")";err(what);ABORT=true;var e=new WebAssembly.RuntimeError(what);readyPromiseReject(e);throw e}var dataURIPrefix="data:application/octet-stream;base64,";var isDataURI=filename=>filename.startsWith(dataURIPrefix);var isFileURI=filename=>filename.startsWith("file://");function createExportWrapper(name,nargs){return(...args)=>{assert(runtimeInitialized,`native function \`${name}\` called before runtime initialization`);var f=wasmExports[name];assert(f,`exported native function \`${name}\` not found`);assert(args.length<=nargs,`native function \`${name}\` called with ${args.length} args but expects ${nargs}`);return f(...args)}}function findWasmBinary(){if(Module["locateFile"]){var f="web_engine.wasm";if(!isDataURI(f)){return locateFile(f)}return f}return new URL("web_engine.wasm",import.meta.url).href}var wasmBinaryFile;function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}function getBinaryPromise(binaryFile){if(!wasmBinary){return readAsync(binaryFile).then(response=>new Uint8Array(response),()=>getBinarySync(binaryFile))}return Promise.resolve().then(()=>getBinarySync(binaryFile))}function instantiateArrayBuffer(binaryFile,imports,receiver){return getBinaryPromise(binaryFile).then(binary=>WebAssembly.instantiate(binary,imports)).then(receiver,reason=>{err(`failed to asynchronously prepare wasm: ${reason}`);if(isFileURI(wasmBinaryFile)){err(`warning: Loading from a file URI (${wasmBinaryFile}) is not supported in most browsers. See https://emscripten.org/docs/getting_started/FAQ.html#how-do-i-run-a-local-webserver-for-testing-why-does-my-program-stall-in-downloading-or-preparing`)}abort(reason)})}function instantiateAsync(binary,binaryFile,imports,callback){if(!binary&&typeof WebAssembly.instantiateStreaming=="function"&&!isDataURI(binaryFile)&&!ENVIRONMENT_IS_NODE&&typeof fetch=="function"){return fetch(binaryFile,{credentials:"same-origin"}).then(response=>{var result=WebAssembly.instantiateStreaming(response,imports);return result.then(callback,function(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(binaryFile,imports,callback)})})}return instantiateArrayBuffer(binaryFile,imports,callback)}function getWasmImports(){return{env:wasmImports,wasi_snapshot_preview1:wasmImports}}function createWasm(){var info=getWasmImports();function receiveInstance(instance,module){wasmExports=instance.exports;wasmMemory=wasmExports["memory"];assert(wasmMemory,"memory not found in wasm exports");updateMemoryViews();wasmTable=wasmExports["__indirect_function_table"];assert(wasmTable,"table not found in wasm exports");addOnInit(wasmExports["__wasm_call_ctors"]);removeRunDependency("wasm-instantiate");return wasmExports}addRunDependency("wasm-instantiate");var trueModule=Module;function receiveInstantiationResult(result){assert(Module===trueModule,"the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?");trueModule=null;receiveInstance(result["instance"])}if(Module["instantiateWasm"]){try{return Module["instantiateWasm"](info,receiveInstance)}catch(e){err(`Module.instantiateWasm callback failed with error: ${e}`);readyPromiseReject(e)}}wasmBinaryFile??=findWasmBinary();instantiateAsync(wasmBinary,wasmBinaryFile,info,receiveInstantiationResult).catch(readyPromiseReject);return{}}var tempDouble;var tempI64;(()=>{var h16=new Int16Array(1);var h8=new Int8Array(h16.buffer);h16[0]=25459;if(h8[0]!==115||h8[1]!==99)throw"Runtime error: expected the system to be little-endian! (Run with -sSUPPORT_BIG_ENDIAN to bypass)"})();if(Module["ENVIRONMENT"]){throw new Error("Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -sENVIRONMENT=web or -sENVIRONMENT=node)")}function legacyModuleProp(prop,newName,incoming=true){if(!Object.getOwnPropertyDescriptor(Module,prop)){Object.defineProperty(Module,prop,{configurable:true,get(){let extra=incoming?" (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)":"";abort(`\`Module.${prop}\` has been replaced by \`${newName}\``+extra)}})}}function ignoredModuleProp(prop){if(Object.getOwnPropertyDescriptor(Module,prop)){abort(`\`Module.${prop}\` was supplied but \`${prop}\` not included in INCOMING_MODULE_JS_API`)}}function isExportedByForceFilesystem(name){return name==="FS_createPath"||name==="FS_createDataFile"||name==="FS_createPreloadedFile"||name==="FS_unlink"||name==="addRunDependency"||name==="FS_createLazyFile"||name==="FS_createDevice"||name==="removeRunDependency"}function hookGlobalSymbolAccess(sym,func){if(typeof globalThis!="undefined"&&!Object.getOwnPropertyDescriptor(globalThis,sym)){Object.defineProperty(globalThis,sym,{configurable:true,get(){func();return undefined}})}}function missingGlobal(sym,msg){hookGlobalSymbolAccess(sym,()=>{warnOnce(`\`${sym}\` is not longer defined by emscripten. ${msg}`)})}missingGlobal("buffer","Please use HEAP8.buffer or wasmMemory.buffer");missingGlobal("asm","Please use wasmExports instead");function missingLibrarySymbol(sym){hookGlobalSymbolAccess(sym,()=>{var msg=`\`${sym}\` is a library symbol and not included by default; add it to your library.js __deps or to DEFAULT_LIBRARY_FUNCS_TO_INCLUDE on the command line`;var librarySymbol=sym;if(!librarySymbol.startsWith("_")){librarySymbol="$"+sym}msg+=` (e.g. -sDEFAULT_LIBRARY_FUNCS_TO_INCLUDE='${librarySymbol}')`;if(isExportedByForceFilesystem(sym)){msg+=". Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you"}warnOnce(msg)});unexportedRuntimeSymbol(sym)}function unexportedRuntimeSymbol(sym){if(!Object.getOwnPropertyDescriptor(Module,sym)){Object.defineProperty(Module,sym,{configurable:true,get(){var msg=`'${sym}' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the Emscripten FAQ)`;if(isExportedByForceFilesystem(sym)){msg+=". Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you"}abort(msg)}})}}var MAX_UINT8=2**8-1;var MAX_UINT16=2**16-1;var MAX_UINT32=2**32-1;var MAX_UINT53=2**53-1;var MAX_UINT64=2**64-1;var MIN_INT8=-(2**(8-1));var MIN_INT16=-(2**(16-1));var MIN_INT32=-(2**(32-1));var MIN_INT53=-(2**(53-1));var MIN_INT64=-(2**(64-1));function checkInt(value,bits,min,max){assert(Number.isInteger(Number(value)),`attempt to write non-integer (${value}) into integer heap`);assert(value<=max,`value (${value}) too large to write as ${bits}-bit value`);assert(value>=min,`value (${value}) too small to write as ${bits}-bit value`)}var checkInt8=value=>checkInt(value,8,MIN_INT8,MAX_UINT8);var checkInt16=value=>checkInt(value,16,MIN_INT16,MAX_UINT16);var checkInt32=value=>checkInt(value,32,MIN_INT32,MAX_UINT32);var checkInt64=value=>checkInt(value,64,MIN_INT64,MAX_UINT64);function dbg(...args){console.warn(...args)}function ExitStatus(status){this.name="ExitStatus";this.message=`Program terminated with exit(${status})`;this.status=status}var callRuntimeCallbacks=callbacks=>{callbacks.forEach(f=>f(Module))};var noExitRuntime=Module["noExitRuntime"]||true;var ptrToString=ptr=>{assert(typeof ptr==="number");ptr>>>=0;return"0x"+ptr.toString(16).padStart(8,"0")};var setStackLimits=()=>{var stackLow=_emscripten_stack_get_base();var stackHigh=_emscripten_stack_get_end();___set_stack_limits(stackLow,stackHigh)};var stackRestore=val=>__emscripten_stack_restore(val);var stackSave=()=>_emscripten_stack_get_current();var warnOnce=text=>{warnOnce.shown||={};if(!warnOnce.shown[text]){warnOnce.shown[text]=1;if(ENVIRONMENT_IS_NODE)text="warning: "+text;err(text)}};var UTF8Decoder=typeof TextDecoder!="undefined"?new TextDecoder:undefined;var UTF8ArrayToString=(heapOrArray,idx=0,maxBytesToRead=NaN)=>{var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heapOrArray[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx>10,56320|ch&1023)}}return str};var UTF8ToString=(ptr,maxBytesToRead)=>{assert(typeof ptr=="number",`UTF8ToString expects a number (got ${typeof ptr})`);return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""};var ___assert_fail=(condition,filename,line,func)=>{abort(`Assertion failed: ${UTF8ToString(condition)}, at: `+[filename?UTF8ToString(filename):"unknown filename",line,func?UTF8ToString(func):"unknown function"])};var wasmTableMirror=[];var wasmTable;var getWasmTableEntry=funcPtr=>{var func=wasmTableMirror[funcPtr];if(!func){if(funcPtr>=wasmTableMirror.length)wasmTableMirror.length=funcPtr+1;wasmTableMirror[funcPtr]=func=wasmTable.get(funcPtr)}assert(wasmTable.get(funcPtr)==func,"JavaScript-side Wasm function table mirror is out of date!");return func};var ___call_sighandler=(fp,sig)=>getWasmTableEntry(fp)(sig);var exceptionCaught=[];var uncaughtExceptionCount=0;var ___cxa_begin_catch=ptr=>{var info=new ExceptionInfo(ptr);if(!info.get_caught()){info.set_caught(true);uncaughtExceptionCount--}info.set_rethrown(false);exceptionCaught.push(info);___cxa_increment_exception_refcount(ptr);return ___cxa_get_exception_ptr(ptr)};var exceptionLast=0;var ___cxa_end_catch=()=>{_setThrew(0,0);assert(exceptionCaught.length>0);var info=exceptionCaught.pop();___cxa_decrement_exception_refcount(info.excPtr);exceptionLast=0};class ExceptionInfo{constructor(excPtr){this.excPtr=excPtr;this.ptr=excPtr-24}set_type(type){HEAPU32[this.ptr+4>>2]=type}get_type(){return HEAPU32[this.ptr+4>>2]}set_destructor(destructor){HEAPU32[this.ptr+8>>2]=destructor}get_destructor(){return HEAPU32[this.ptr+8>>2]}set_caught(caught){caught=caught?1:0;HEAP8[this.ptr+12]=caught;checkInt8(caught)}get_caught(){return HEAP8[this.ptr+12]!=0}set_rethrown(rethrown){rethrown=rethrown?1:0;HEAP8[this.ptr+13]=rethrown;checkInt8(rethrown)}get_rethrown(){return HEAP8[this.ptr+13]!=0}init(type,destructor){this.set_adjusted_ptr(0);this.set_type(type);this.set_destructor(destructor)}set_adjusted_ptr(adjustedPtr){HEAPU32[this.ptr+16>>2]=adjustedPtr}get_adjusted_ptr(){return HEAPU32[this.ptr+16>>2]}}var ___resumeException=ptr=>{if(!exceptionLast){exceptionLast=ptr}assert(false,"Exception thrown, but exception catching is not enabled. Compile with -sNO_DISABLE_EXCEPTION_CATCHING or -sEXCEPTION_CATCHING_ALLOWED=[..] to catch.")};var setTempRet0=val=>__emscripten_tempret_set(val);var findMatchingCatch=args=>{var thrown=exceptionLast;if(!thrown){setTempRet0(0);return 0}var info=new ExceptionInfo(thrown);info.set_adjusted_ptr(thrown);var thrownType=info.get_type();if(!thrownType){setTempRet0(0);return thrown}for(var caughtType of args){if(caughtType===0||caughtType===thrownType){break}var adjusted_ptr_addr=info.ptr+16;if(___cxa_can_catch(caughtType,thrownType,adjusted_ptr_addr)){setTempRet0(caughtType);return thrown}}setTempRet0(thrownType);return thrown};var ___cxa_find_matching_catch_2=()=>findMatchingCatch([]);var ___cxa_find_matching_catch_3=arg0=>findMatchingCatch([arg0]);var ___cxa_rethrow=()=>{var info=exceptionCaught.pop();if(!info){abort("no exception to throw")}var ptr=info.excPtr;if(!info.get_rethrown()){exceptionCaught.push(info);info.set_rethrown(true);info.set_caught(false);uncaughtExceptionCount++}exceptionLast=ptr;assert(false,"Exception thrown, but exception catching is not enabled. Compile with -sNO_DISABLE_EXCEPTION_CATCHING or -sEXCEPTION_CATCHING_ALLOWED=[..] to catch.")};var ___cxa_throw=(ptr,type,destructor)=>{var info=new ExceptionInfo(ptr);info.init(type,destructor);exceptionLast=ptr;uncaughtExceptionCount++;assert(false,"Exception thrown, but exception catching is not enabled. Compile with -sNO_DISABLE_EXCEPTION_CATCHING or -sEXCEPTION_CATCHING_ALLOWED=[..] to catch.")};var ___handle_stack_overflow=requested=>{var base=_emscripten_stack_get_base();var end=_emscripten_stack_get_end();abort(`stack overflow (Attempt to set SP to ${ptrToString(requested)}`+`, with stack limits [${ptrToString(end)} - ${ptrToString(base)}`+"]). If you require more stack space build with -sSTACK_SIZE=")};var PATH={isAbs:path=>path.charAt(0)==="/",splitPath:filename=>{var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;return splitPathRe.exec(filename).slice(1)},normalizeArray:(parts,allowAboveRoot)=>{var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up;up--){parts.unshift("..")}}return parts},normalize:path=>{var isAbsolute=PATH.isAbs(path),trailingSlash=path.substr(-1)==="/";path=PATH.normalizeArray(path.split("/").filter(p=>!!p),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path},dirname:path=>{var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return"."}if(dir){dir=dir.substr(0,dir.length-1)}return root+dir},basename:path=>{if(path==="/")return"/";path=PATH.normalize(path);path=path.replace(/\/$/,"");var lastSlash=path.lastIndexOf("/");if(lastSlash===-1)return path;return path.substr(lastSlash+1)},join:(...paths)=>PATH.normalize(paths.join("/")),join2:(l,r)=>PATH.normalize(l+"/"+r)};var initRandomFill=()=>{if(typeof crypto=="object"&&typeof crypto["getRandomValues"]=="function"){return view=>crypto.getRandomValues(view)}else if(ENVIRONMENT_IS_NODE){try{var crypto_module=require("crypto");var randomFillSync=crypto_module["randomFillSync"];if(randomFillSync){return view=>crypto_module["randomFillSync"](view)}var randomBytes=crypto_module["randomBytes"];return view=>(view.set(randomBytes(view.byteLength)),view)}catch(e){}}abort("no cryptographic support found for randomDevice. consider polyfilling it if you want to use something insecure like Math.random(), e.g. put this in a --pre-js: var crypto = { getRandomValues: (array) => { for (var i = 0; i < array.length; i++) array[i] = (Math.random()*256)|0 } };")};var randomFill=view=>(randomFill=initRandomFill())(view);var PATH_FS={resolve:(...args)=>{var resolvedPath="",resolvedAbsolute=false;for(var i=args.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?args[i]:FS.cwd();if(typeof path!="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){return""}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=PATH.isAbs(path)}resolvedPath=PATH.normalizeArray(resolvedPath.split("/").filter(p=>!!p),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."},relative:(from,to)=>{from=PATH_FS.resolve(from).substr(1);to=PATH_FS.resolve(to).substr(1);function trim(arr){var start=0;for(;start=0;end--){if(arr[end]!=="")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split("/"));var toParts=trim(to.split("/"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i{var len=0;for(var i=0;i=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{assert(typeof str==="string",`stringToUTF8Array expects a string (got ${typeof str})`);if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;if(u>1114111)warnOnce("Invalid Unicode code point "+ptrToString(u)+" encountered when serializing a JS string to a UTF-8 string in wasm memory! (Valid unicode code points should be in range 0-0x10FFFF).");heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx};function intArrayFromString(stringy,dontAddNull,length){var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array}var FS_stdin_getChar=()=>{if(!FS_stdin_getChar_buffer.length){var result=null;if(ENVIRONMENT_IS_NODE){var BUFSIZE=256;var buf=Buffer.alloc(BUFSIZE);var bytesRead=0;var fd=process.stdin.fd;try{bytesRead=fs.readSync(fd,buf,0,BUFSIZE)}catch(e){if(e.toString().includes("EOF"))bytesRead=0;else throw e}if(bytesRead>0){result=buf.slice(0,bytesRead).toString("utf-8")}}else if(typeof window!="undefined"&&typeof window.prompt=="function"){result=window.prompt("Input: ");if(result!==null){result+="\n"}}else{}if(!result){return null}FS_stdin_getChar_buffer=intArrayFromString(result,true)}return FS_stdin_getChar_buffer.shift()};var TTY={ttys:[],init(){},shutdown(){},register(dev,ops){TTY.ttys[dev]={input:[],output:[],ops};FS.registerDevice(dev,TTY.stream_ops)},stream_ops:{open(stream){var tty=TTY.ttys[stream.node.rdev];if(!tty){throw new FS.ErrnoError(43)}stream.tty=tty;stream.seekable=false},close(stream){stream.tty.ops.fsync(stream.tty)},fsync(stream){stream.tty.ops.fsync(stream.tty)},read(stream,buffer,offset,length,pos){if(!stream.tty||!stream.tty.ops.get_char){throw new FS.ErrnoError(60)}var bytesRead=0;for(var i=0;i0){out(UTF8ArrayToString(tty.output));tty.output=[]}},ioctl_tcgets(tty){return{c_iflag:25856,c_oflag:5,c_cflag:191,c_lflag:35387,c_cc:[3,28,127,21,4,0,1,0,17,19,26,0,18,15,23,22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}},ioctl_tcsets(tty,optional_actions,data){return 0},ioctl_tiocgwinsz(tty){return[24,80]}},default_tty1_ops:{put_char(tty,val){if(val===null||val===10){err(UTF8ArrayToString(tty.output));tty.output=[]}else{if(val!=0)tty.output.push(val)}},fsync(tty){if(tty.output&&tty.output.length>0){err(UTF8ArrayToString(tty.output));tty.output=[]}}}};var zeroMemory=(address,size)=>{HEAPU8.fill(0,address,address+size)};var alignMemory=(size,alignment)=>{assert(alignment,"alignment argument is required");return Math.ceil(size/alignment)*alignment};var mmapAlloc=size=>{size=alignMemory(size,65536);var ptr=_emscripten_builtin_memalign(65536,size);if(ptr)zeroMemory(ptr,size);return ptr};var MEMFS={ops_table:null,mount(mount){return MEMFS.createNode(null,"/",16384|511,0)},createNode(parent,name,mode,dev){if(FS.isBlkdev(mode)||FS.isFIFO(mode)){throw new FS.ErrnoError(63)}MEMFS.ops_table||={dir:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,lookup:MEMFS.node_ops.lookup,mknod:MEMFS.node_ops.mknod,rename:MEMFS.node_ops.rename,unlink:MEMFS.node_ops.unlink,rmdir:MEMFS.node_ops.rmdir,readdir:MEMFS.node_ops.readdir,symlink:MEMFS.node_ops.symlink},stream:{llseek:MEMFS.stream_ops.llseek}},file:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:{llseek:MEMFS.stream_ops.llseek,read:MEMFS.stream_ops.read,write:MEMFS.stream_ops.write,allocate:MEMFS.stream_ops.allocate,mmap:MEMFS.stream_ops.mmap,msync:MEMFS.stream_ops.msync}},link:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,readlink:MEMFS.node_ops.readlink},stream:{}},chrdev:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:FS.chrdev_stream_ops}};var node=FS.createNode(parent,name,mode,dev);if(FS.isDir(node.mode)){node.node_ops=MEMFS.ops_table.dir.node;node.stream_ops=MEMFS.ops_table.dir.stream;node.contents={}}else if(FS.isFile(node.mode)){node.node_ops=MEMFS.ops_table.file.node;node.stream_ops=MEMFS.ops_table.file.stream;node.usedBytes=0;node.contents=null}else if(FS.isLink(node.mode)){node.node_ops=MEMFS.ops_table.link.node;node.stream_ops=MEMFS.ops_table.link.stream}else if(FS.isChrdev(node.mode)){node.node_ops=MEMFS.ops_table.chrdev.node;node.stream_ops=MEMFS.ops_table.chrdev.stream}node.timestamp=Date.now();if(parent){parent.contents[name]=node;parent.timestamp=node.timestamp}return node},getFileDataAsTypedArray(node){if(!node.contents)return new Uint8Array(0);if(node.contents.subarray)return node.contents.subarray(0,node.usedBytes);return new Uint8Array(node.contents)},expandFileStorage(node,newCapacity){var prevCapacity=node.contents?node.contents.length:0;if(prevCapacity>=newCapacity)return;var CAPACITY_DOUBLING_MAX=1024*1024;newCapacity=Math.max(newCapacity,prevCapacity*(prevCapacity>>0);if(prevCapacity!=0)newCapacity=Math.max(newCapacity,256);var oldContents=node.contents;node.contents=new Uint8Array(newCapacity);if(node.usedBytes>0)node.contents.set(oldContents.subarray(0,node.usedBytes),0)},resizeFileStorage(node,newSize){if(node.usedBytes==newSize)return;if(newSize==0){node.contents=null;node.usedBytes=0}else{var oldContents=node.contents;node.contents=new Uint8Array(newSize);if(oldContents){node.contents.set(oldContents.subarray(0,Math.min(newSize,node.usedBytes)))}node.usedBytes=newSize}},node_ops:{getattr(node){var attr={};attr.dev=FS.isChrdev(node.mode)?node.id:1;attr.ino=node.id;attr.mode=node.mode;attr.nlink=1;attr.uid=0;attr.gid=0;attr.rdev=node.rdev;if(FS.isDir(node.mode)){attr.size=4096}else if(FS.isFile(node.mode)){attr.size=node.usedBytes}else if(FS.isLink(node.mode)){attr.size=node.link.length}else{attr.size=0}attr.atime=new Date(node.timestamp);attr.mtime=new Date(node.timestamp);attr.ctime=new Date(node.timestamp);attr.blksize=4096;attr.blocks=Math.ceil(attr.size/attr.blksize);return attr},setattr(node,attr){if(attr.mode!==undefined){node.mode=attr.mode}if(attr.timestamp!==undefined){node.timestamp=attr.timestamp}if(attr.size!==undefined){MEMFS.resizeFileStorage(node,attr.size)}},lookup(parent,name){throw FS.genericErrors[44]},mknod(parent,name,mode,dev){return MEMFS.createNode(parent,name,mode,dev)},rename(old_node,new_dir,new_name){if(FS.isDir(old_node.mode)){var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(new_node){for(var i in new_node.contents){throw new FS.ErrnoError(55)}}}delete old_node.parent.contents[old_node.name];old_node.parent.timestamp=Date.now();old_node.name=new_name;new_dir.contents[new_name]=old_node;new_dir.timestamp=old_node.parent.timestamp},unlink(parent,name){delete parent.contents[name];parent.timestamp=Date.now()},rmdir(parent,name){var node=FS.lookupNode(parent,name);for(var i in node.contents){throw new FS.ErrnoError(55)}delete parent.contents[name];parent.timestamp=Date.now()},readdir(node){var entries=[".",".."];for(var key of Object.keys(node.contents)){entries.push(key)}return entries},symlink(parent,newname,oldpath){var node=MEMFS.createNode(parent,newname,511|40960,0);node.link=oldpath;return node},readlink(node){if(!FS.isLink(node.mode)){throw new FS.ErrnoError(28)}return node.link}},stream_ops:{read(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=stream.node.usedBytes)return 0;var size=Math.min(stream.node.usedBytes-position,length);assert(size>=0);if(size>8&&contents.subarray){buffer.set(contents.subarray(position,position+size),offset)}else{for(var i=0;i0||position+length{var dep=!noRunDep?getUniqueRunDependency(`al ${url}`):"";readAsync(url).then(arrayBuffer=>{assert(arrayBuffer,`Loading data file "${url}" failed (no arrayBuffer).`);onload(new Uint8Array(arrayBuffer));if(dep)removeRunDependency(dep)},err=>{if(onerror){onerror()}else{throw`Loading data file "${url}" failed.`}});if(dep)addRunDependency(dep)};var FS_createDataFile=(parent,name,fileData,canRead,canWrite,canOwn)=>{FS.createDataFile(parent,name,fileData,canRead,canWrite,canOwn)};var preloadPlugins=Module["preloadPlugins"]||[];var FS_handledByPreloadPlugin=(byteArray,fullname,finish,onerror)=>{if(typeof Browser!="undefined")Browser.init();var handled=false;preloadPlugins.forEach(plugin=>{if(handled)return;if(plugin["canHandle"](fullname)){plugin["handle"](byteArray,fullname,finish,onerror);handled=true}});return handled};var FS_createPreloadedFile=(parent,name,url,canRead,canWrite,onload,onerror,dontCreateFile,canOwn,preFinish)=>{var fullname=name?PATH_FS.resolve(PATH.join2(parent,name)):parent;var dep=getUniqueRunDependency(`cp ${fullname}`);function processData(byteArray){function finish(byteArray){preFinish?.();if(!dontCreateFile){FS_createDataFile(parent,name,byteArray,canRead,canWrite,canOwn)}onload?.();removeRunDependency(dep)}if(FS_handledByPreloadPlugin(byteArray,fullname,finish,()=>{onerror?.();removeRunDependency(dep)})){return}finish(byteArray)}addRunDependency(dep);if(typeof url=="string"){asyncLoad(url,processData,onerror)}else{processData(url)}};var FS_modeStringToFlags=str=>{var flagModes={r:0,"r+":2,w:512|64|1,"w+":512|64|2,a:1024|64|1,"a+":1024|64|2};var flags=flagModes[str];if(typeof flags=="undefined"){throw new Error(`Unknown file open mode: ${str}`)}return flags};var FS_getMode=(canRead,canWrite)=>{var mode=0;if(canRead)mode|=292|73;if(canWrite)mode|=146;return mode};var strError=errno=>UTF8ToString(_strerror(errno));var ERRNO_CODES={EPERM:63,ENOENT:44,ESRCH:71,EINTR:27,EIO:29,ENXIO:60,E2BIG:1,ENOEXEC:45,EBADF:8,ECHILD:12,EAGAIN:6,EWOULDBLOCK:6,ENOMEM:48,EACCES:2,EFAULT:21,ENOTBLK:105,EBUSY:10,EEXIST:20,EXDEV:75,ENODEV:43,ENOTDIR:54,EISDIR:31,EINVAL:28,ENFILE:41,EMFILE:33,ENOTTY:59,ETXTBSY:74,EFBIG:22,ENOSPC:51,ESPIPE:70,EROFS:69,EMLINK:34,EPIPE:64,EDOM:18,ERANGE:68,ENOMSG:49,EIDRM:24,ECHRNG:106,EL2NSYNC:156,EL3HLT:107,EL3RST:108,ELNRNG:109,EUNATCH:110,ENOCSI:111,EL2HLT:112,EDEADLK:16,ENOLCK:46,EBADE:113,EBADR:114,EXFULL:115,ENOANO:104,EBADRQC:103,EBADSLT:102,EDEADLOCK:16,EBFONT:101,ENOSTR:100,ENODATA:116,ETIME:117,ENOSR:118,ENONET:119,ENOPKG:120,EREMOTE:121,ENOLINK:47,EADV:122,ESRMNT:123,ECOMM:124,EPROTO:65,EMULTIHOP:36,EDOTDOT:125,EBADMSG:9,ENOTUNIQ:126,EBADFD:127,EREMCHG:128,ELIBACC:129,ELIBBAD:130,ELIBSCN:131,ELIBMAX:132,ELIBEXEC:133,ENOSYS:52,ENOTEMPTY:55,ENAMETOOLONG:37,ELOOP:32,EOPNOTSUPP:138,EPFNOSUPPORT:139,ECONNRESET:15,ENOBUFS:42,EAFNOSUPPORT:5,EPROTOTYPE:67,ENOTSOCK:57,ENOPROTOOPT:50,ESHUTDOWN:140,ECONNREFUSED:14,EADDRINUSE:3,ECONNABORTED:13,ENETUNREACH:40,ENETDOWN:38,ETIMEDOUT:73,EHOSTDOWN:142,EHOSTUNREACH:23,EINPROGRESS:26,EALREADY:7,EDESTADDRREQ:17,EMSGSIZE:35,EPROTONOSUPPORT:66,ESOCKTNOSUPPORT:137,EADDRNOTAVAIL:4,ENETRESET:39,EISCONN:30,ENOTCONN:53,ETOOMANYREFS:141,EUSERS:136,EDQUOT:19,ESTALE:72,ENOTSUP:138,ENOMEDIUM:148,EILSEQ:25,EOVERFLOW:61,ECANCELED:11,ENOTRECOVERABLE:56,EOWNERDEAD:62,ESTRPIPE:135};var FS={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,ErrnoError:class extends Error{constructor(errno){super(runtimeInitialized?strError(errno):"");this.name="ErrnoError";this.errno=errno;for(var key in ERRNO_CODES){if(ERRNO_CODES[key]===errno){this.code=key;break}}}},genericErrors:{},filesystems:null,syncFSRequests:0,readFiles:{},FSStream:class{constructor(){this.shared={}}get object(){return this.node}set object(val){this.node=val}get isRead(){return(this.flags&2097155)!==1}get isWrite(){return(this.flags&2097155)!==0}get isAppend(){return this.flags&1024}get flags(){return this.shared.flags}set flags(val){this.shared.flags=val}get position(){return this.shared.position}set position(val){this.shared.position=val}},FSNode:class{constructor(parent,name,mode,rdev){if(!parent){parent=this}this.parent=parent;this.mount=parent.mount;this.mounted=null;this.id=FS.nextInode++;this.name=name;this.mode=mode;this.node_ops={};this.stream_ops={};this.rdev=rdev;this.readMode=292|73;this.writeMode=146}get read(){return(this.mode&this.readMode)===this.readMode}set read(val){val?this.mode|=this.readMode:this.mode&=~this.readMode}get write(){return(this.mode&this.writeMode)===this.writeMode}set write(val){val?this.mode|=this.writeMode:this.mode&=~this.writeMode}get isFolder(){return FS.isDir(this.mode)}get isDevice(){return FS.isChrdev(this.mode)}},lookupPath(path,opts={}){path=PATH_FS.resolve(path);if(!path)return{path:"",node:null};var defaults={follow_mount:true,recurse_count:0};opts=Object.assign(defaults,opts);if(opts.recurse_count>8){throw new FS.ErrnoError(32)}var parts=path.split("/").filter(p=>!!p);var current=FS.root;var current_path="/";for(var i=0;i40){throw new FS.ErrnoError(32)}}}}return{path:current_path,node:current}},getPath(node){var path;while(true){if(FS.isRoot(node)){var mount=node.mount.mountpoint;if(!path)return mount;return mount[mount.length-1]!=="/"?`${mount}/${path}`:mount+path}path=path?`${node.name}/${path}`:node.name;node=node.parent}},hashName(parentid,name){var hash=0;for(var i=0;i>>0)%FS.nameTable.length},hashAddNode(node){var hash=FS.hashName(node.parent.id,node.name);node.name_next=FS.nameTable[hash];FS.nameTable[hash]=node},hashRemoveNode(node){var hash=FS.hashName(node.parent.id,node.name);if(FS.nameTable[hash]===node){FS.nameTable[hash]=node.name_next}else{var current=FS.nameTable[hash];while(current){if(current.name_next===node){current.name_next=node.name_next;break}current=current.name_next}}},lookupNode(parent,name){var errCode=FS.mayLookup(parent);if(errCode){throw new FS.ErrnoError(errCode)}var hash=FS.hashName(parent.id,name);for(var node=FS.nameTable[hash];node;node=node.name_next){var nodeName=node.name;if(node.parent.id===parent.id&&nodeName===name){return node}}return FS.lookup(parent,name)},createNode(parent,name,mode,rdev){assert(typeof parent=="object");var node=new FS.FSNode(parent,name,mode,rdev);FS.hashAddNode(node);return node},destroyNode(node){FS.hashRemoveNode(node)},isRoot(node){return node===node.parent},isMountpoint(node){return!!node.mounted},isFile(mode){return(mode&61440)===32768},isDir(mode){return(mode&61440)===16384},isLink(mode){return(mode&61440)===40960},isChrdev(mode){return(mode&61440)===8192},isBlkdev(mode){return(mode&61440)===24576},isFIFO(mode){return(mode&61440)===4096},isSocket(mode){return(mode&49152)===49152},flagsToPermissionString(flag){var perms=["r","w","rw"][flag&3];if(flag&512){perms+="w"}return perms},nodePermissions(node,perms){if(FS.ignorePermissions){return 0}if(perms.includes("r")&&!(node.mode&292)){return 2}else if(perms.includes("w")&&!(node.mode&146)){return 2}else if(perms.includes("x")&&!(node.mode&73)){return 2}return 0},mayLookup(dir){if(!FS.isDir(dir.mode))return 54;var errCode=FS.nodePermissions(dir,"x");if(errCode)return errCode;if(!dir.node_ops.lookup)return 2;return 0},mayCreate(dir,name){try{var node=FS.lookupNode(dir,name);return 20}catch(e){}return FS.nodePermissions(dir,"wx")},mayDelete(dir,name,isdir){var node;try{node=FS.lookupNode(dir,name)}catch(e){return e.errno}var errCode=FS.nodePermissions(dir,"wx");if(errCode){return errCode}if(isdir){if(!FS.isDir(node.mode)){return 54}if(FS.isRoot(node)||FS.getPath(node)===FS.cwd()){return 10}}else{if(FS.isDir(node.mode)){return 31}}return 0},mayOpen(node,flags){if(!node){return 44}if(FS.isLink(node.mode)){return 32}else if(FS.isDir(node.mode)){if(FS.flagsToPermissionString(flags)!=="r"||flags&512){return 31}}return FS.nodePermissions(node,FS.flagsToPermissionString(flags))},MAX_OPEN_FDS:4096,nextfd(){for(var fd=0;fd<=FS.MAX_OPEN_FDS;fd++){if(!FS.streams[fd]){return fd}}throw new FS.ErrnoError(33)},getStreamChecked(fd){var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(8)}return stream},getStream:fd=>FS.streams[fd],createStream(stream,fd=-1){assert(fd>=-1);stream=Object.assign(new FS.FSStream,stream);if(fd==-1){fd=FS.nextfd()}stream.fd=fd;FS.streams[fd]=stream;return stream},closeStream(fd){FS.streams[fd]=null},dupStream(origStream,fd=-1){var stream=FS.createStream(origStream,fd);stream.stream_ops?.dup?.(stream);return stream},chrdev_stream_ops:{open(stream){var device=FS.getDevice(stream.node.rdev);stream.stream_ops=device.stream_ops;stream.stream_ops.open?.(stream)},llseek(){throw new FS.ErrnoError(70)}},major:dev=>dev>>8,minor:dev=>dev&255,makedev:(ma,mi)=>ma<<8|mi,registerDevice(dev,ops){FS.devices[dev]={stream_ops:ops}},getDevice:dev=>FS.devices[dev],getMounts(mount){var mounts=[];var check=[mount];while(check.length){var m=check.pop();mounts.push(m);check.push(...m.mounts)}return mounts},syncfs(populate,callback){if(typeof populate=="function"){callback=populate;populate=false}FS.syncFSRequests++;if(FS.syncFSRequests>1){err(`warning: ${FS.syncFSRequests} FS.syncfs operations in flight at once, probably just doing extra work`)}var mounts=FS.getMounts(FS.root.mount);var completed=0;function doCallback(errCode){assert(FS.syncFSRequests>0);FS.syncFSRequests--;return callback(errCode)}function done(errCode){if(errCode){if(!done.errored){done.errored=true;return doCallback(errCode)}return}if(++completed>=mounts.length){doCallback(null)}}mounts.forEach(mount=>{if(!mount.type.syncfs){return done(null)}mount.type.syncfs(mount,populate,done)})},mount(type,opts,mountpoint){if(typeof type=="string"){throw type}var root=mountpoint==="/";var pseudo=!mountpoint;var node;if(root&&FS.root){throw new FS.ErrnoError(10)}else if(!root&&!pseudo){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});mountpoint=lookup.path;node=lookup.node;if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}if(!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}}var mount={type,opts,mountpoint,mounts:[]};var mountRoot=type.mount(mount);mountRoot.mount=mount;mount.root=mountRoot;if(root){FS.root=mountRoot}else if(node){node.mounted=mount;if(node.mount){node.mount.mounts.push(mount)}}return mountRoot},unmount(mountpoint){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});if(!FS.isMountpoint(lookup.node)){throw new FS.ErrnoError(28)}var node=lookup.node;var mount=node.mounted;var mounts=FS.getMounts(mount);Object.keys(FS.nameTable).forEach(hash=>{var current=FS.nameTable[hash];while(current){var next=current.name_next;if(mounts.includes(current.mount)){FS.destroyNode(current)}current=next}});node.mounted=null;var idx=node.mount.mounts.indexOf(mount);assert(idx!==-1);node.mount.mounts.splice(idx,1)},lookup(parent,name){return parent.node_ops.lookup(parent,name)},mknod(path,mode,dev){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);if(!name||name==="."||name===".."){throw new FS.ErrnoError(28)}var errCode=FS.mayCreate(parent,name);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.mknod){throw new FS.ErrnoError(63)}return parent.node_ops.mknod(parent,name,mode,dev)},create(path,mode){mode=mode!==undefined?mode:438;mode&=4095;mode|=32768;return FS.mknod(path,mode,0)},mkdir(path,mode){mode=mode!==undefined?mode:511;mode&=511|512;mode|=16384;return FS.mknod(path,mode,0)},mkdirTree(path,mode){var dirs=path.split("/");var d="";for(var i=0;i=0);if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.read){throw new FS.ErrnoError(28)}var seeking=typeof position!="undefined";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesRead=stream.stream_ops.read(stream,buffer,offset,length,position);if(!seeking)stream.position+=bytesRead;return bytesRead},write(stream,buffer,offset,length,position,canOwn){assert(offset>=0);if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.write){throw new FS.ErrnoError(28)}if(stream.seekable&&stream.flags&1024){FS.llseek(stream,0,2)}var seeking=typeof position!="undefined";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesWritten=stream.stream_ops.write(stream,buffer,offset,length,position,canOwn);if(!seeking)stream.position+=bytesWritten;return bytesWritten},allocate(stream,offset,length){if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(offset<0||length<=0){throw new FS.ErrnoError(28)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(8)}if(!FS.isFile(stream.node.mode)&&!FS.isDir(stream.node.mode)){throw new FS.ErrnoError(43)}if(!stream.stream_ops.allocate){throw new FS.ErrnoError(138)}stream.stream_ops.allocate(stream,offset,length)},mmap(stream,length,position,prot,flags){if((prot&2)!==0&&(flags&2)===0&&(stream.flags&2097155)!==2){throw new FS.ErrnoError(2)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(2)}if(!stream.stream_ops.mmap){throw new FS.ErrnoError(43)}if(!length){throw new FS.ErrnoError(28)}return stream.stream_ops.mmap(stream,length,position,prot,flags)},msync(stream,buffer,offset,length,mmapFlags){assert(offset>=0);if(!stream.stream_ops.msync){return 0}return stream.stream_ops.msync(stream,buffer,offset,length,mmapFlags)},ioctl(stream,cmd,arg){if(!stream.stream_ops.ioctl){throw new FS.ErrnoError(59)}return stream.stream_ops.ioctl(stream,cmd,arg)},readFile(path,opts={}){opts.flags=opts.flags||0;opts.encoding=opts.encoding||"binary";if(opts.encoding!=="utf8"&&opts.encoding!=="binary"){throw new Error(`Invalid encoding type "${opts.encoding}"`)}var ret;var stream=FS.open(path,opts.flags);var stat=FS.stat(path);var length=stat.size;var buf=new Uint8Array(length);FS.read(stream,buf,0,length,0);if(opts.encoding==="utf8"){ret=UTF8ArrayToString(buf)}else if(opts.encoding==="binary"){ret=buf}FS.close(stream);return ret},writeFile(path,data,opts={}){opts.flags=opts.flags||577;var stream=FS.open(path,opts.flags,opts.mode);if(typeof data=="string"){var buf=new Uint8Array(lengthBytesUTF8(data)+1);var actualNumBytes=stringToUTF8Array(data,buf,0,buf.length);FS.write(stream,buf,0,actualNumBytes,undefined,opts.canOwn)}else if(ArrayBuffer.isView(data)){FS.write(stream,data,0,data.byteLength,undefined,opts.canOwn)}else{throw new Error("Unsupported data type")}FS.close(stream)},cwd:()=>FS.currentPath,chdir(path){var lookup=FS.lookupPath(path,{follow:true});if(lookup.node===null){throw new FS.ErrnoError(44)}if(!FS.isDir(lookup.node.mode)){throw new FS.ErrnoError(54)}var errCode=FS.nodePermissions(lookup.node,"x");if(errCode){throw new FS.ErrnoError(errCode)}FS.currentPath=lookup.path},createDefaultDirectories(){FS.mkdir("/tmp");FS.mkdir("/home");FS.mkdir("/home/web_user")},createDefaultDevices(){FS.mkdir("/dev");FS.registerDevice(FS.makedev(1,3),{read:()=>0,write:(stream,buffer,offset,length,pos)=>length});FS.mkdev("/dev/null",FS.makedev(1,3));TTY.register(FS.makedev(5,0),TTY.default_tty_ops);TTY.register(FS.makedev(6,0),TTY.default_tty1_ops);FS.mkdev("/dev/tty",FS.makedev(5,0));FS.mkdev("/dev/tty1",FS.makedev(6,0));var randomBuffer=new Uint8Array(1024),randomLeft=0;var randomByte=()=>{if(randomLeft===0){randomLeft=randomFill(randomBuffer).byteLength}return randomBuffer[--randomLeft]};FS.createDevice("/dev","random",randomByte);FS.createDevice("/dev","urandom",randomByte);FS.mkdir("/dev/shm");FS.mkdir("/dev/shm/tmp")},createSpecialDirectories(){FS.mkdir("/proc");var proc_self=FS.mkdir("/proc/self");FS.mkdir("/proc/self/fd");FS.mount({mount(){var node=FS.createNode(proc_self,"fd",16384|511,73);node.node_ops={lookup(parent,name){var fd=+name;var stream=FS.getStreamChecked(fd);var ret={parent:null,mount:{mountpoint:"fake"},node_ops:{readlink:()=>stream.path}};ret.parent=ret;return ret}};return node}},{},"/proc/self/fd")},createStandardStreams(input,output,error){if(input){FS.createDevice("/dev","stdin",input)}else{FS.symlink("/dev/tty","/dev/stdin")}if(output){FS.createDevice("/dev","stdout",null,output)}else{FS.symlink("/dev/tty","/dev/stdout")}if(error){FS.createDevice("/dev","stderr",null,error)}else{FS.symlink("/dev/tty1","/dev/stderr")}var stdin=FS.open("/dev/stdin",0);var stdout=FS.open("/dev/stdout",1);var stderr=FS.open("/dev/stderr",1);assert(stdin.fd===0,`invalid handle for stdin (${stdin.fd})`);assert(stdout.fd===1,`invalid handle for stdout (${stdout.fd})`);assert(stderr.fd===2,`invalid handle for stderr (${stderr.fd})`)},staticInit(){[44].forEach(code=>{FS.genericErrors[code]=new FS.ErrnoError(code);FS.genericErrors[code].stack=""});FS.nameTable=new Array(4096);FS.mount(MEMFS,{},"/");FS.createDefaultDirectories();FS.createDefaultDevices();FS.createSpecialDirectories();FS.filesystems={MEMFS}},init(input,output,error){assert(!FS.initialized,"FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)");FS.initialized=true;input??=Module["stdin"];output??=Module["stdout"];error??=Module["stderr"];FS.createStandardStreams(input,output,error)},quit(){FS.initialized=false;_fflush(0);for(var i=0;ithis.length-1||idx<0){return undefined}var chunkOffset=idx%this.chunkSize;var chunkNum=idx/this.chunkSize|0;return this.getter(chunkNum)[chunkOffset]}setDataGetter(getter){this.getter=getter}cacheLength(){var xhr=new XMLHttpRequest;xhr.open("HEAD",url,false);xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);var datalength=Number(xhr.getResponseHeader("Content-length"));var header;var hasByteServing=(header=xhr.getResponseHeader("Accept-Ranges"))&&header==="bytes";var usesGzip=(header=xhr.getResponseHeader("Content-Encoding"))&&header==="gzip";var chunkSize=1024*1024;if(!hasByteServing)chunkSize=datalength;var doXHR=(from,to)=>{if(from>to)throw new Error("invalid range ("+from+", "+to+") or no bytes requested!");if(to>datalength-1)throw new Error("only "+datalength+" bytes available! programmer error!");var xhr=new XMLHttpRequest;xhr.open("GET",url,false);if(datalength!==chunkSize)xhr.setRequestHeader("Range","bytes="+from+"-"+to);xhr.responseType="arraybuffer";if(xhr.overrideMimeType){xhr.overrideMimeType("text/plain; charset=x-user-defined")}xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);if(xhr.response!==undefined){return new Uint8Array(xhr.response||[])}return intArrayFromString(xhr.responseText||"",true)};var lazyArray=this;lazyArray.setDataGetter(chunkNum=>{var start=chunkNum*chunkSize;var end=(chunkNum+1)*chunkSize-1;end=Math.min(end,datalength-1);if(typeof lazyArray.chunks[chunkNum]=="undefined"){lazyArray.chunks[chunkNum]=doXHR(start,end)}if(typeof lazyArray.chunks[chunkNum]=="undefined")throw new Error("doXHR failed!");return lazyArray.chunks[chunkNum]});if(usesGzip||!datalength){chunkSize=datalength=1;datalength=this.getter(0).length;chunkSize=datalength;out("LazyFiles on gzip forces download of the whole file when length is accessed")}this._length=datalength;this._chunkSize=chunkSize;this.lengthKnown=true}get length(){if(!this.lengthKnown){this.cacheLength()}return this._length}get chunkSize(){if(!this.lengthKnown){this.cacheLength()}return this._chunkSize}}if(typeof XMLHttpRequest!="undefined"){if(!ENVIRONMENT_IS_WORKER)throw"Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc";var lazyArray=new LazyUint8Array;var properties={isDevice:false,contents:lazyArray}}else{var properties={isDevice:false,url}}var node=FS.createFile(parent,name,properties,canRead,canWrite);if(properties.contents){node.contents=properties.contents}else if(properties.url){node.contents=null;node.url=properties.url}Object.defineProperties(node,{usedBytes:{get:function(){return this.contents.length}}});var stream_ops={};var keys=Object.keys(node.stream_ops);keys.forEach(key=>{var fn=node.stream_ops[key];stream_ops[key]=(...args)=>{FS.forceLoadFile(node);return fn(...args)}});function writeChunks(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=contents.length)return 0;var size=Math.min(contents.length-position,length);assert(size>=0);if(contents.slice){for(var i=0;i{FS.forceLoadFile(node);return writeChunks(stream,buffer,offset,length,position)};stream_ops.mmap=(stream,length,position,prot,flags)=>{FS.forceLoadFile(node);var ptr=mmapAlloc(length);if(!ptr){throw new FS.ErrnoError(48)}writeChunks(stream,HEAP8,ptr,length,position);return{ptr,allocated:true}};node.stream_ops=stream_ops;return node},absolutePath(){abort("FS.absolutePath has been removed; use PATH_FS.resolve instead")},createFolder(){abort("FS.createFolder has been removed; use FS.mkdir instead")},createLink(){abort("FS.createLink has been removed; use FS.symlink instead")},joinPath(){abort("FS.joinPath has been removed; use PATH.join instead")},mmapAlloc(){abort("FS.mmapAlloc has been replaced by the top level function mmapAlloc")},standardizePath(){abort("FS.standardizePath has been removed; use PATH.normalize instead")}};var SYSCALLS={DEFAULT_POLLMASK:5,calculateAt(dirfd,path,allowEmpty){if(PATH.isAbs(path)){return path}var dir;if(dirfd===-100){dir=FS.cwd()}else{var dirstream=SYSCALLS.getStreamFromFD(dirfd);dir=dirstream.path}if(path.length==0){if(!allowEmpty){throw new FS.ErrnoError(44)}return dir}return PATH.join2(dir,path)},doStat(func,path,buf){var stat=func(path);HEAP32[buf>>2]=stat.dev;checkInt32(stat.dev);HEAP32[buf+4>>2]=stat.mode;checkInt32(stat.mode);HEAPU32[buf+8>>2]=stat.nlink;checkInt32(stat.nlink);HEAP32[buf+12>>2]=stat.uid;checkInt32(stat.uid);HEAP32[buf+16>>2]=stat.gid;checkInt32(stat.gid);HEAP32[buf+20>>2]=stat.rdev;checkInt32(stat.rdev);tempI64=[stat.size>>>0,(tempDouble=stat.size,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+24>>2]=tempI64[0],HEAP32[buf+28>>2]=tempI64[1];checkInt64(stat.size);HEAP32[buf+32>>2]=4096;checkInt32(4096);HEAP32[buf+36>>2]=stat.blocks;checkInt32(stat.blocks);var atime=stat.atime.getTime();var mtime=stat.mtime.getTime();var ctime=stat.ctime.getTime();tempI64=[Math.floor(atime/1e3)>>>0,(tempDouble=Math.floor(atime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+40>>2]=tempI64[0],HEAP32[buf+44>>2]=tempI64[1];checkInt64(Math.floor(atime/1e3));HEAPU32[buf+48>>2]=atime%1e3*1e3*1e3;checkInt32(atime%1e3*1e3*1e3);tempI64=[Math.floor(mtime/1e3)>>>0,(tempDouble=Math.floor(mtime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+56>>2]=tempI64[0],HEAP32[buf+60>>2]=tempI64[1];checkInt64(Math.floor(mtime/1e3));HEAPU32[buf+64>>2]=mtime%1e3*1e3*1e3;checkInt32(mtime%1e3*1e3*1e3);tempI64=[Math.floor(ctime/1e3)>>>0,(tempDouble=Math.floor(ctime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+72>>2]=tempI64[0],HEAP32[buf+76>>2]=tempI64[1];checkInt64(Math.floor(ctime/1e3));HEAPU32[buf+80>>2]=ctime%1e3*1e3*1e3;checkInt32(ctime%1e3*1e3*1e3);tempI64=[stat.ino>>>0,(tempDouble=stat.ino,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+88>>2]=tempI64[0],HEAP32[buf+92>>2]=tempI64[1];checkInt64(stat.ino);return 0},doMsync(addr,stream,len,flags,offset){if(!FS.isFile(stream.node.mode)){throw new FS.ErrnoError(43)}if(flags&2){return 0}var buffer=HEAPU8.slice(addr,addr+len);FS.msync(stream,buffer,offset,len,flags)},getStreamFromFD(fd){var stream=FS.getStreamChecked(fd);return stream},varargs:undefined,getStr(ptr){var ret=UTF8ToString(ptr);return ret}};function ___syscall_faccessat(dirfd,path,amode,flags){try{path=SYSCALLS.getStr(path);assert(flags===0||flags==512);path=SYSCALLS.calculateAt(dirfd,path);if(amode&~7){return-28}var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;if(!node){return-44}var perms="";if(amode&4)perms+="r";if(amode&2)perms+="w";if(amode&1)perms+="x";if(perms&&FS.nodePermissions(node,perms)){return-2}return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function syscallGetVarargI(){assert(SYSCALLS.varargs!=undefined);var ret=HEAP32[+SYSCALLS.varargs>>2];SYSCALLS.varargs+=4;return ret}var syscallGetVarargP=syscallGetVarargI;function ___syscall_fcntl64(fd,cmd,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(cmd){case 0:{var arg=syscallGetVarargI();if(arg<0){return-28}while(FS.streams[arg]){arg++}var newStream;newStream=FS.dupStream(stream,arg);return newStream.fd}case 1:case 2:return 0;case 3:return stream.flags;case 4:{var arg=syscallGetVarargI();stream.flags|=arg;return 0}case 12:{var arg=syscallGetVarargP();var offset=0;HEAP16[arg+offset>>1]=2;checkInt16(2);return 0}case 13:case 14:return 0}return-28}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_fstat64(fd,buf){try{var stream=SYSCALLS.getStreamFromFD(fd);return SYSCALLS.doStat(FS.stat,stream.path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var stringToUTF8=(str,outPtr,maxBytesToWrite)=>{assert(typeof maxBytesToWrite=="number","stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!");return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)};function ___syscall_getdents64(fd,dirp,count){try{var stream=SYSCALLS.getStreamFromFD(fd);stream.getdents||=FS.readdir(stream.path);var struct_size=280;var pos=0;var off=FS.llseek(stream,0,1);var idx=Math.floor(off/struct_size);while(idx>>0,(tempDouble=id,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[dirp+pos>>2]=tempI64[0],HEAP32[dirp+pos+4>>2]=tempI64[1];checkInt64(id);tempI64=[(idx+1)*struct_size>>>0,(tempDouble=(idx+1)*struct_size,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[dirp+pos+8>>2]=tempI64[0],HEAP32[dirp+pos+12>>2]=tempI64[1];checkInt64((idx+1)*struct_size);HEAP16[dirp+pos+16>>1]=280;checkInt16(280);HEAP8[dirp+pos+18]=type;checkInt8(type);stringToUTF8(name,dirp+pos+19,256);pos+=struct_size;idx+=1}FS.llseek(stream,idx*struct_size,0);return pos}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_ioctl(fd,op,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(op){case 21509:{if(!stream.tty)return-59;return 0}case 21505:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tcgets){var termios=stream.tty.ops.ioctl_tcgets(stream);var argp=syscallGetVarargP();HEAP32[argp>>2]=termios.c_iflag||0;checkInt32(termios.c_iflag||0);HEAP32[argp+4>>2]=termios.c_oflag||0;checkInt32(termios.c_oflag||0);HEAP32[argp+8>>2]=termios.c_cflag||0;checkInt32(termios.c_cflag||0);HEAP32[argp+12>>2]=termios.c_lflag||0;checkInt32(termios.c_lflag||0);for(var i=0;i<32;i++){HEAP8[argp+i+17]=termios.c_cc[i]||0;checkInt8(termios.c_cc[i]||0)}return 0}return 0}case 21510:case 21511:case 21512:{if(!stream.tty)return-59;return 0}case 21506:case 21507:case 21508:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tcsets){var argp=syscallGetVarargP();var c_iflag=HEAP32[argp>>2];var c_oflag=HEAP32[argp+4>>2];var c_cflag=HEAP32[argp+8>>2];var c_lflag=HEAP32[argp+12>>2];var c_cc=[];for(var i=0;i<32;i++){c_cc.push(HEAP8[argp+i+17])}return stream.tty.ops.ioctl_tcsets(stream.tty,op,{c_iflag,c_oflag,c_cflag,c_lflag,c_cc})}return 0}case 21519:{if(!stream.tty)return-59;var argp=syscallGetVarargP();HEAP32[argp>>2]=0;checkInt32(0);return 0}case 21520:{if(!stream.tty)return-59;return-28}case 21531:{var argp=syscallGetVarargP();return FS.ioctl(stream,op,argp)}case 21523:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tiocgwinsz){var winsize=stream.tty.ops.ioctl_tiocgwinsz(stream.tty);var argp=syscallGetVarargP();HEAP16[argp>>1]=winsize[0];checkInt16(winsize[0]);HEAP16[argp+2>>1]=winsize[1];checkInt16(winsize[1])}return 0}case 21524:{if(!stream.tty)return-59;return 0}case 21515:{if(!stream.tty)return-59;return 0}default:return-28}}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_lstat64(path,buf){try{path=SYSCALLS.getStr(path);return SYSCALLS.doStat(FS.lstat,path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_mkdirat(dirfd,path,mode){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);path=PATH.normalize(path);if(path[path.length-1]==="/")path=path.substr(0,path.length-1);FS.mkdir(path,mode,0);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_newfstatat(dirfd,path,buf,flags){try{path=SYSCALLS.getStr(path);var nofollow=flags&256;var allowEmpty=flags&4096;flags=flags&~6400;assert(!flags,`unknown flags in __syscall_newfstatat: ${flags}`);path=SYSCALLS.calculateAt(dirfd,path,allowEmpty);return SYSCALLS.doStat(nofollow?FS.lstat:FS.stat,path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_openat(dirfd,path,flags,varargs){SYSCALLS.varargs=varargs;try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);var mode=varargs?syscallGetVarargI():0;return FS.open(path,flags,mode).fd}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_rmdir(path){try{path=SYSCALLS.getStr(path);FS.rmdir(path);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_stat64(path,buf){try{path=SYSCALLS.getStr(path);return SYSCALLS.doStat(FS.stat,path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_unlinkat(dirfd,path,flags){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);if(flags===0){FS.unlink(path)}else if(flags===512){FS.rmdir(path)}else{abort("Invalid flags passed to unlinkat")}return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var __abort_js=()=>{abort("native code called abort()")};var nowIsMonotonic=1;var __emscripten_get_now_is_monotonic=()=>nowIsMonotonic;var __emscripten_memcpy_js=(dest,src,num)=>HEAPU8.copyWithin(dest,src,src+num);var __emscripten_runtime_keepalive_clear=()=>{noExitRuntime=false;runtimeKeepaliveCounter=0};var __emscripten_throw_longjmp=()=>{throw Infinity};var convertI32PairToI53Checked=(lo,hi)=>{assert(lo==lo>>>0||lo==(lo|0));assert(hi===(hi|0));return hi+2097152>>>0<4194305-!!lo?(lo>>>0)+hi*4294967296:NaN};function __mmap_js(len,prot,flags,fd,offset_low,offset_high,allocated,addr){var offset=convertI32PairToI53Checked(offset_low,offset_high);try{if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);var res=FS.mmap(stream,len,offset,prot,flags);var ptr=res.ptr;HEAP32[allocated>>2]=res.allocated;checkInt32(res.allocated);HEAPU32[addr>>2]=ptr;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function __munmap_js(addr,len,prot,flags,fd,offset_low,offset_high){var offset=convertI32PairToI53Checked(offset_low,offset_high);try{var stream=SYSCALLS.getStreamFromFD(fd);if(prot&2){SYSCALLS.doMsync(addr,stream,len,flags,offset)}}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var __tzset_js=(timezone,daylight,std_name,dst_name)=>{var currentYear=(new Date).getFullYear();var winter=new Date(currentYear,0,1);var summer=new Date(currentYear,6,1);var winterOffset=winter.getTimezoneOffset();var summerOffset=summer.getTimezoneOffset();var stdTimezoneOffset=Math.max(winterOffset,summerOffset);HEAPU32[timezone>>2]=stdTimezoneOffset*60;checkInt32(stdTimezoneOffset*60);HEAP32[daylight>>2]=Number(winterOffset!=summerOffset);checkInt32(Number(winterOffset!=summerOffset));var extractZone=timezoneOffset=>{var sign=timezoneOffset>=0?"-":"+";var absOffset=Math.abs(timezoneOffset);var hours=String(Math.floor(absOffset/60)).padStart(2,"0");var minutes=String(absOffset%60).padStart(2,"0");return`UTC${sign}${hours}${minutes}`};var winterName=extractZone(winterOffset);var summerName=extractZone(summerOffset);assert(winterName);assert(summerName);assert(lengthBytesUTF8(winterName)<=16,`timezone name truncated to fit in TZNAME_MAX (${winterName})`);assert(lengthBytesUTF8(summerName)<=16,`timezone name truncated to fit in TZNAME_MAX (${summerName})`);if(summerOffsetDate.now();var getHeapMax=()=>2147483648;var _emscripten_get_heap_max=()=>getHeapMax();var _emscripten_get_now=()=>performance.now();var growMemory=size=>{var b=wasmMemory.buffer;var pages=(size-b.byteLength+65535)/65536|0;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){err(`growMemory: Attempted to grow heap from ${b.byteLength} bytes to ${size} bytes, but got error: ${e}`)}};var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;assert(requestedSize>oldSize);var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){err(`Cannot enlarge memory, requested ${requestedSize} bytes, but the limit is ${maxHeapSize} bytes!`);return false}for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignMemory(Math.max(requestedSize,overGrownHeapSize),65536));var t0=_emscripten_get_now();var replacement=growMemory(newSize);var t1=_emscripten_get_now();dbg(`Heap resize call from ${oldSize} to ${newSize} took ${t1-t0} msecs. Success: ${!!replacement}`);if(replacement){return true}}err(`Failed to grow the heap from ${oldSize} bytes to ${newSize} bytes, not enough memory!`);return false};var ENV={};var getExecutableName=()=>thisProgram||"./this.program";var getEnvStrings=()=>{if(!getEnvStrings.strings){var lang=(typeof navigator=="object"&&navigator.languages&&navigator.languages[0]||"C").replace("-","_")+".UTF-8";var env={USER:"web_user",LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:lang,_:getExecutableName()};for(var x in ENV){if(ENV[x]===undefined)delete env[x];else env[x]=ENV[x]}var strings=[];for(var x in env){strings.push(`${x}=${env[x]}`)}getEnvStrings.strings=strings}return getEnvStrings.strings};var stringToAscii=(str,buffer)=>{for(var i=0;i{var bufSize=0;getEnvStrings().forEach((string,i)=>{var ptr=environ_buf+bufSize;HEAPU32[__environ+i*4>>2]=ptr;checkInt32(ptr);stringToAscii(string,ptr);bufSize+=string.length+1});return 0};var _environ_sizes_get=(penviron_count,penviron_buf_size)=>{var strings=getEnvStrings();HEAPU32[penviron_count>>2]=strings.length;checkInt32(strings.length);var bufSize=0;strings.forEach(string=>bufSize+=string.length+1);HEAPU32[penviron_buf_size>>2]=bufSize;checkInt32(bufSize);return 0};function _fd_close(fd){try{var stream=SYSCALLS.getStreamFromFD(fd);FS.close(stream);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _fd_fdstat_get(fd,pbuf){try{var rightsBase=0;var rightsInheriting=0;var flags=0;{var stream=SYSCALLS.getStreamFromFD(fd);var type=stream.tty?2:FS.isDir(stream.mode)?3:FS.isLink(stream.mode)?7:4}HEAP8[pbuf]=type;checkInt8(type);HEAP16[pbuf+2>>1]=flags;checkInt16(flags);tempI64=[rightsBase>>>0,(tempDouble=rightsBase,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[pbuf+8>>2]=tempI64[0],HEAP32[pbuf+12>>2]=tempI64[1];checkInt64(rightsBase);tempI64=[rightsInheriting>>>0,(tempDouble=rightsInheriting,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[pbuf+16>>2]=tempI64[0],HEAP32[pbuf+20>>2]=tempI64[1];checkInt64(rightsInheriting);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var doReadv=(stream,iov,iovcnt,offset)=>{var ret=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;var curr=FS.read(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr>2]=num;checkInt32(num);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){var offset=convertI32PairToI53Checked(offset_low,offset_high);try{if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);FS.llseek(stream,offset,whence);tempI64=[stream.position>>>0,(tempDouble=stream.position,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[newOffset>>2]=tempI64[0],HEAP32[newOffset+4>>2]=tempI64[1];checkInt64(stream.position);if(stream.getdents&&offset===0&&whence===0)stream.getdents=null;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var doWritev=(stream,iov,iovcnt,offset)=>{var ret=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;var curr=FS.write(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr>2]=num;checkInt32(num);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var _getentropy=(buffer,size)=>{randomFill(HEAPU8.subarray(buffer,buffer+size));return 0};var _llvm_eh_typeid_for=type=>type;var runtimeKeepaliveCounter=0;var keepRuntimeAlive=()=>noExitRuntime||runtimeKeepaliveCounter>0;var _proc_exit=code=>{EXITSTATUS=code;if(!keepRuntimeAlive()){Module["onExit"]?.(code);ABORT=true}quit_(code,new ExitStatus(code))};var getCFunc=ident=>{var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func};var writeArrayToMemory=(array,buffer)=>{assert(array.length>=0,"writeArrayToMemory array must have a length (should be an array or typed array)");HEAP8.set(array,buffer)};var stackAlloc=sz=>__emscripten_stack_alloc(sz);var stringToUTF8OnStack=str=>{var size=lengthBytesUTF8(str)+1;var ret=stackAlloc(size);stringToUTF8(str,ret,size);return ret};var ccall=(ident,returnType,argTypes,args,opts)=>{var toC={string:str=>{var ret=0;if(str!==null&&str!==undefined&&str!==0){ret=stringToUTF8OnStack(str)}return ret},array:arr=>{var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string"){return UTF8ToString(ret)}if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;assert(returnType!=="array",'Return type should not be "array".');if(args){for(var i=0;i(...args)=>ccall(ident,returnType,argTypes,args,opts);FS.createPreloadedFile=FS_createPreloadedFile;FS.staticInit();function checkIncomingModuleAPI(){ignoredModuleProp("fetchSettings")}var wasmImports={__assert_fail:___assert_fail,__call_sighandler:___call_sighandler,__cxa_begin_catch:___cxa_begin_catch,__cxa_end_catch:___cxa_end_catch,__cxa_find_matching_catch_2:___cxa_find_matching_catch_2,__cxa_find_matching_catch_3:___cxa_find_matching_catch_3,__cxa_rethrow:___cxa_rethrow,__cxa_throw:___cxa_throw,__handle_stack_overflow:___handle_stack_overflow,__resumeException:___resumeException,__syscall_faccessat:___syscall_faccessat,__syscall_fcntl64:___syscall_fcntl64,__syscall_fstat64:___syscall_fstat64,__syscall_getdents64:___syscall_getdents64,__syscall_ioctl:___syscall_ioctl,__syscall_lstat64:___syscall_lstat64,__syscall_mkdirat:___syscall_mkdirat,__syscall_newfstatat:___syscall_newfstatat,__syscall_openat:___syscall_openat,__syscall_rmdir:___syscall_rmdir,__syscall_stat64:___syscall_stat64,__syscall_unlinkat:___syscall_unlinkat,_abort_js:__abort_js,_emscripten_get_now_is_monotonic:__emscripten_get_now_is_monotonic,_emscripten_memcpy_js:__emscripten_memcpy_js,_emscripten_runtime_keepalive_clear:__emscripten_runtime_keepalive_clear,_emscripten_throw_longjmp:__emscripten_throw_longjmp,_mmap_js:__mmap_js,_munmap_js:__munmap_js,_tzset_js:__tzset_js,emscripten_date_now:_emscripten_date_now,emscripten_get_heap_max:_emscripten_get_heap_max,emscripten_get_now:_emscripten_get_now,emscripten_resize_heap:_emscripten_resize_heap,environ_get:_environ_get,environ_sizes_get:_environ_sizes_get,fd_close:_fd_close,fd_fdstat_get:_fd_fdstat_get,fd_read:_fd_read,fd_seek:_fd_seek,fd_write:_fd_write,getentropy:_getentropy,invoke_d,invoke_diii,invoke_fi,invoke_fif,invoke_fifff,invoke_fii,invoke_fiii,invoke_fiiii,invoke_fiiiiii,invoke_fiiiiiii,invoke_fij,invoke_i,invoke_idiii,invoke_ii,invoke_iif,invoke_iifi,invoke_iifii,invoke_iifiiiii,invoke_iii,invoke_iiid,invoke_iiidii,invoke_iiif,invoke_iiiffi,invoke_iiii,invoke_iiiidi,invoke_iiiiffifffffffi,invoke_iiiifiii,invoke_iiiii,invoke_iiiiif,invoke_iiiiifi,invoke_iiiiii,invoke_iiiiiifi,invoke_iiiiiififiiiififiiiiiiiiiiiiiiiiiiii,invoke_iiiiiii,invoke_iiiiiiifii,invoke_iiiiiiii,invoke_iiiiiiiii,invoke_iiiiiiiiiffi,invoke_iiiiiiiiii,invoke_iiiiiiiiiifi,invoke_iiiiiiiiiii,invoke_iiiiiiiiiiii,invoke_iiiiiiiiiiiif,invoke_iiiiiiiiiiiiiii,invoke_iiiiiiij,invoke_iiiiiij,invoke_iiiiij,invoke_iiiij,invoke_iiij,invoke_iiiji,invoke_iiijii,invoke_iiijiii,invoke_iij,invoke_iijiii,invoke_iijj,invoke_iijji,invoke_iijjiii,invoke_ij,invoke_ijjiii,invoke_j,invoke_ji,invoke_jii,invoke_jiii,invoke_jiji,invoke_v,invoke_vdiii,invoke_vi,invoke_vid,invoke_vif,invoke_vififiif,invoke_vifii,invoke_vifiiifiiiiiiiiiiiiifiiii,invoke_vii,invoke_viid,invoke_viif,invoke_viiff,invoke_viifi,invoke_viifiii,invoke_viii,invoke_viiid,invoke_viiif,invoke_viiiffii,invoke_viiiffiiii,invoke_viiifi,invoke_viiii,invoke_viiiif,invoke_viiiii,invoke_viiiiif,invoke_viiiiii,invoke_viiiiiid,invoke_viiiiiif,invoke_viiiiiifi,invoke_viiiiiifif,invoke_viiiiiifii,invoke_viiiiiii,invoke_viiiiiiidiiii,invoke_viiiiiiii,invoke_viiiiiiiif,invoke_viiiiiiiii,invoke_viiiiiiiiii,invoke_viiiiiiiiiidii,invoke_viiiiiiiiiii,invoke_viiiiiiiiiiii,invoke_viiiiiiiiiiiiii,invoke_viiiiiiiiiiiiiiii,invoke_viiiiij,invoke_viiiiiji,invoke_viiiiji,invoke_viiiijiiifi,invoke_viiij,invoke_viiiji,invoke_viiijii,invoke_viiijjji,invoke_viij,invoke_viiji,invoke_viijii,invoke_viijj,invoke_vij,invoke_viji,invoke_vijif,invoke_vijii,invoke_vijj,invoke_vjjiii,llvm_eh_typeid_for:_llvm_eh_typeid_for,proc_exit:_proc_exit};var wasmExports=createWasm();var ___wasm_call_ctors=createExportWrapper("__wasm_call_ctors",0);var _web_engine_create=Module["_web_engine_create"]=createExportWrapper("web_engine_create",0);var _web_engine_get_memory_stats=Module["_web_engine_get_memory_stats"]=createExportWrapper("web_engine_get_memory_stats",1);var _web_engine_destroy=Module["_web_engine_destroy"]=createExportWrapper("web_engine_destroy",1);var _fflush=createExportWrapper("fflush",1);var _web_engine_get_live_handles=Module["_web_engine_get_live_handles"]=createExportWrapper("web_engine_get_live_handles",0);var _web_engine_get_allocated_bytes=Module["_web_engine_get_allocated_bytes"]=createExportWrapper("web_engine_get_allocated_bytes",0);var _web_engine_open_blend=Module["_web_engine_open_blend"]=createExportWrapper("web_engine_open_blend",3);var _web_engine_apply_command=Module["_web_engine_apply_command"]=createExportWrapper("web_engine_apply_command",3);var _web_engine_decimate_apply=Module["_web_engine_decimate_apply"]=createExportWrapper("web_engine_decimate_apply",35);var _web_engine_append_library_object=Module["_web_engine_append_library_object"]=createExportWrapper("web_engine_append_library_object",5);var _web_engine_undo=Module["_web_engine_undo"]=createExportWrapper("web_engine_undo",1);var _web_engine_redo=Module["_web_engine_redo"]=createExportWrapper("web_engine_redo",1);var _web_engine_get_scene_snapshot=Module["_web_engine_get_scene_snapshot"]=createExportWrapper("web_engine_get_scene_snapshot",3);var _web_engine_get_scene_metadata=Module["_web_engine_get_scene_metadata"]=createExportWrapper("web_engine_get_scene_metadata",3);var _web_engine_get_scene_geometry=Module["_web_engine_get_scene_geometry"]=createExportWrapper("web_engine_get_scene_geometry",3);var _web_engine_get_scene_delta=Module["_web_engine_get_scene_delta"]=createExportWrapper("web_engine_get_scene_delta",3);var _web_engine_get_packed_asset=Module["_web_engine_get_packed_asset"]=createExportWrapper("web_engine_get_packed_asset",5);var _web_engine_evaluate_depsgraph=Module["_web_engine_evaluate_depsgraph"]=createExportWrapper("web_engine_evaluate_depsgraph",3);var _web_engine_save_blend=Module["_web_engine_save_blend"]=createExportWrapper("web_engine_save_blend",3);var _malloc=Module["_malloc"]=createExportWrapper("malloc",1);var _web_engine_free_buffer=Module["_web_engine_free_buffer"]=createExportWrapper("web_engine_free_buffer",1);var _free=Module["_free"]=createExportWrapper("free",1);var _web_engine_last_error_code=Module["_web_engine_last_error_code"]=createExportWrapper("web_engine_last_error_code",0);var _web_engine_last_error_message=Module["_web_engine_last_error_message"]=createExportWrapper("web_engine_last_error_message",0);var _strerror=createExportWrapper("strerror",1);var _emscripten_builtin_memalign=createExportWrapper("emscripten_builtin_memalign",2);var _setThrew=createExportWrapper("setThrew",2);var __emscripten_tempret_set=createExportWrapper("_emscripten_tempret_set",1);var __emscripten_tempret_get=createExportWrapper("_emscripten_tempret_get",0);var _emscripten_stack_init=()=>(_emscripten_stack_init=wasmExports["emscripten_stack_init"])();var _emscripten_stack_get_free=()=>(_emscripten_stack_get_free=wasmExports["emscripten_stack_get_free"])();var _emscripten_stack_get_base=()=>(_emscripten_stack_get_base=wasmExports["emscripten_stack_get_base"])();var _emscripten_stack_get_end=()=>(_emscripten_stack_get_end=wasmExports["emscripten_stack_get_end"])();var __emscripten_stack_restore=a0=>(__emscripten_stack_restore=wasmExports["_emscripten_stack_restore"])(a0);var __emscripten_stack_alloc=a0=>(__emscripten_stack_alloc=wasmExports["_emscripten_stack_alloc"])(a0);var _emscripten_stack_get_current=()=>(_emscripten_stack_get_current=wasmExports["emscripten_stack_get_current"])();var ___cxa_decrement_exception_refcount=createExportWrapper("__cxa_decrement_exception_refcount",1);var ___cxa_increment_exception_refcount=createExportWrapper("__cxa_increment_exception_refcount",1);var ___cxa_can_catch=createExportWrapper("__cxa_can_catch",3);var ___cxa_get_exception_ptr=createExportWrapper("__cxa_get_exception_ptr",1);var ___set_stack_limits=Module["___set_stack_limits"]=createExportWrapper("__set_stack_limits",2);var dynCall_viij=Module["dynCall_viij"]=createExportWrapper("dynCall_viij",5);var dynCall_viiji=Module["dynCall_viiji"]=createExportWrapper("dynCall_viiji",6);var dynCall_viijii=Module["dynCall_viijii"]=createExportWrapper("dynCall_viijii",7);var dynCall_vij=Module["dynCall_vij"]=createExportWrapper("dynCall_vij",4);var dynCall_viiiijiiifi=Module["dynCall_viiiijiiifi"]=createExportWrapper("dynCall_viiiijiiifi",12);var dynCall_viiijjji=Module["dynCall_viiijjji"]=createExportWrapper("dynCall_viiijjji",11);var dynCall_viiiiji=Module["dynCall_viiiiji"]=createExportWrapper("dynCall_viiiiji",8);var dynCall_viiiji=Module["dynCall_viiiji"]=createExportWrapper("dynCall_viiiji",7);var dynCall_ij=Module["dynCall_ij"]=createExportWrapper("dynCall_ij",3);var dynCall_viji=Module["dynCall_viji"]=createExportWrapper("dynCall_viji",5);var dynCall_iij=Module["dynCall_iij"]=createExportWrapper("dynCall_iij",4);var dynCall_fij=Module["dynCall_fij"]=createExportWrapper("dynCall_fij",4);var dynCall_vijf=Module["dynCall_vijf"]=createExportWrapper("dynCall_vijf",5);var dynCall_jiii=Module["dynCall_jiii"]=createExportWrapper("dynCall_jiii",4);var dynCall_viiij=Module["dynCall_viiij"]=createExportWrapper("dynCall_viiij",6);var dynCall_iiijii=Module["dynCall_iiijii"]=createExportWrapper("dynCall_iiijii",7);var dynCall_iiijiii=Module["dynCall_iiijiii"]=createExportWrapper("dynCall_iiijiii",8);var dynCall_iiij=Module["dynCall_iiij"]=createExportWrapper("dynCall_iiij",5);var dynCall_vjjiii=Module["dynCall_vjjiii"]=createExportWrapper("dynCall_vjjiii",8);var dynCall_ijjiii=Module["dynCall_ijjiii"]=createExportWrapper("dynCall_ijjiii",8);var dynCall_iijiii=Module["dynCall_iijiii"]=createExportWrapper("dynCall_iijiii",7);var dynCall_iijjiii=Module["dynCall_iijjiii"]=createExportWrapper("dynCall_iijjiii",9);var dynCall_iiiji=Module["dynCall_iiiji"]=createExportWrapper("dynCall_iiiji",6);var dynCall_jii=Module["dynCall_jii"]=createExportWrapper("dynCall_jii",3);var dynCall_iijj=Module["dynCall_iijj"]=createExportWrapper("dynCall_iijj",6);var dynCall_vijj=Module["dynCall_vijj"]=createExportWrapper("dynCall_vijj",6);var dynCall_ji=Module["dynCall_ji"]=createExportWrapper("dynCall_ji",2);var dynCall_vijii=Module["dynCall_vijii"]=createExportWrapper("dynCall_vijii",6);var dynCall_vijif=Module["dynCall_vijif"]=createExportWrapper("dynCall_vijif",6);var dynCall_viiiiij=Module["dynCall_viiiiij"]=createExportWrapper("dynCall_viiiiij",8);var dynCall_viiiiiji=Module["dynCall_viiiiiji"]=createExportWrapper("dynCall_viiiiiji",9);var dynCall_iiiij=Module["dynCall_iiiij"]=createExportWrapper("dynCall_iiiij",6);var dynCall_iijji=Module["dynCall_iijji"]=createExportWrapper("dynCall_iijji",7);var dynCall_j=Module["dynCall_j"]=createExportWrapper("dynCall_j",1);var dynCall_iiiiiiij=Module["dynCall_iiiiiiij"]=createExportWrapper("dynCall_iiiiiiij",9);var dynCall_viijj=Module["dynCall_viijj"]=createExportWrapper("dynCall_viijj",7);var dynCall_iiiiij=Module["dynCall_iiiiij"]=createExportWrapper("dynCall_iiiiij",7);var dynCall_viiijii=Module["dynCall_viiijii"]=createExportWrapper("dynCall_viiijii",8);var dynCall_jij=Module["dynCall_jij"]=createExportWrapper("dynCall_jij",4);var dynCall_vijji=Module["dynCall_vijji"]=createExportWrapper("dynCall_vijji",7);var dynCall_iiiiiij=Module["dynCall_iiiiiij"]=createExportWrapper("dynCall_iiiiiij",8);var dynCall_jiji=Module["dynCall_jiji"]=createExportWrapper("dynCall_jiji",5);var dynCall_iiiiijj=Module["dynCall_iiiiijj"]=createExportWrapper("dynCall_iiiiijj",9);var dynCall_iiiiiijj=Module["dynCall_iiiiiijj"]=createExportWrapper("dynCall_iiiiiijj",10);function invoke_ii(index,a1){var sp=stackSave();try{return getWasmTableEntry(index)(a1)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_v(index){var sp=stackSave();try{getWasmTableEntry(index)()}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiii(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viii(index,a1,a2,a3){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiii(index,a1,a2,a3,a4){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vi(index,a1){var sp=stackSave();try{getWasmTableEntry(index)(a1)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vif(index,a1,a2){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iii(index,a1,a2){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fi(index,a1){var sp=stackSave();try{return getWasmTableEntry(index)(a1)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiif(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vii(index,a1,a2){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiii(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_i(index){var sp=stackSave();try{return getWasmTableEntry(index)()}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fiii(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_diii(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viifiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiffi(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiifii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiffifffffffi(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiifi(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiiiifi(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiififiiiififiiiiiiiiiiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,a22,a23,a24,a25,a26,a27,a28,a29,a30,a31,a32,a33,a34,a35){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,a22,a23,a24,a25,a26,a27,a28,a29,a30,a31,a32,a33,a34,a35)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vififiif(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vifii(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fiiii(index,a1,a2,a3,a4){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viif(index,a1,a2,a3){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viifi(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiif(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiif(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiif(index,a1,a2,a3,a4,a5){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fif(index,a1,a2){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiifi(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iifii(index,a1,a2,a3,a4){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fii(index,a1,a2){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fiiiiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iifi(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiif(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vdiii(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_idiii(index,a1,a2,a3,a4){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiif(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiifii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiifiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_d(index){var sp=stackSave();try{return getWasmTableEntry(index)()}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fifff(index,a1,a2,a3,a4){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiifi(index,a1,a2,a3,a4,a5){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fiiiiiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiifi(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vid(index,a1,a2){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiff(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iif(index,a1,a2){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiiiffi(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiffiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iifiiiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiifif(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiif(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vifiiifiiiiiiiiiiiiifiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,a22,a23,a24){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,a22,a23,a24)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiiiiiif(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiid(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiidiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiiiidii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiidi(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viid(index,a1,a2,a3){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiidii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiid(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiffii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiid(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fij(index,a1,a2,a3){var sp=stackSave();try{return dynCall_fij(index,a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viij(index,a1,a2,a3,a4){var sp=stackSave();try{dynCall_viij(index,a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iij(index,a1,a2,a3){var sp=stackSave();try{return dynCall_iij(index,a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_ij(index,a1,a2){var sp=stackSave();try{return dynCall_ij(index,a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vij(index,a1,a2,a3){var sp=stackSave();try{dynCall_vij(index,a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_jiii(index,a1,a2,a3){var sp=stackSave();try{return dynCall_jiii(index,a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiji(index,a1,a2,a3,a4,a5){var sp=stackSave();try{dynCall_viiji(index,a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viijii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{dynCall_viijii(index,a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiijiiifi(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){var sp=stackSave();try{dynCall_viiiijiiifi(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiijjji(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){var sp=stackSave();try{dynCall_viiijjji(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiji(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{dynCall_viiiiji(index,a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiji(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{dynCall_viiiji(index,a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiij(index,a1,a2,a3,a4,a5){var sp=stackSave();try{dynCall_viiij(index,a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiijii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return dynCall_iiijii(index,a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiijiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return dynCall_iiijiii(index,a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiij(index,a1,a2,a3,a4){var sp=stackSave();try{return dynCall_iiij(index,a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viji(index,a1,a2,a3,a4){var sp=stackSave();try{dynCall_viji(index,a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vijii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{dynCall_vijii(index,a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiji(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return dynCall_iiiji(index,a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iijiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return dynCall_iijiii(index,a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iijjiii(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSave();try{return dynCall_iijjiii(index,a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vjjiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{dynCall_vjjiii(index,a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_ijjiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return dynCall_ijjiii(index,a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iijj(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return dynCall_iijj(index,a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vijj(index,a1,a2,a3,a4,a5){var sp=stackSave();try{dynCall_vijj(index,a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiij(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{dynCall_viiiiij(index,a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vijif(index,a1,a2,a3,a4,a5){var sp=stackSave();try{dynCall_vijif(index,a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiji(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSave();try{dynCall_viiiiiji(index,a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iijji(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return dynCall_iijji(index,a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viijj(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{dynCall_viijj(index,a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_ji(index,a1){var sp=stackSave();try{return dynCall_ji(index,a1)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiij(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return dynCall_iiiiij(index,a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiij(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return dynCall_iiiij(index,a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_j(index){var sp=stackSave();try{return dynCall_j(index)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiij(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSave();try{return dynCall_iiiiiiij(index,a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiijii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{dynCall_viiijii(index,a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_jii(index,a1,a2){var sp=stackSave();try{return dynCall_jii(index,a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiij(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return dynCall_iiiiiij(index,a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_jiji(index,a1,a2,a3,a4){var sp=stackSave();try{return dynCall_jiji(index,a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}Module["ccall"]=ccall;Module["cwrap"]=cwrap;Module["UTF8ToString"]=UTF8ToString;var missingLibrarySymbols=["writeI53ToI64","writeI53ToI64Clamped","writeI53ToI64Signaling","writeI53ToU64Clamped","writeI53ToU64Signaling","readI53FromI64","readI53FromU64","convertI32PairToI53","convertU32PairToI53","getTempRet0","exitJS","inetPton4","inetNtop4","inetPton6","inetNtop6","readSockaddr","writeSockaddr","emscriptenLog","readEmAsmArgs","jstoi_q","listenOnce","autoResumeAudioContext","dynCallLegacy","getDynCaller","dynCall","handleException","runtimeKeepalivePush","runtimeKeepalivePop","callUserCallback","maybeExit","asmjsMangle","HandleAllocator","getNativeTypeSize","STACK_SIZE","STACK_ALIGN","POINTER_SIZE","ASSERTIONS","uleb128Encode","sigToWasmTypes","generateFuncType","convertJsFunctionToWasm","getEmptyTableSlot","updateTableMap","getFunctionAddress","addFunction","removeFunction","reallyNegative","unSign","strLen","reSign","formatString","intArrayToString","AsciiToString","UTF16ToString","stringToUTF16","lengthBytesUTF16","UTF32ToString","stringToUTF32","lengthBytesUTF32","stringToNewUTF8","registerKeyEventCallback","maybeCStringToJsString","findEventTarget","getBoundingClientRect","fillMouseEventData","registerMouseEventCallback","registerWheelEventCallback","registerUiEventCallback","registerFocusEventCallback","fillDeviceOrientationEventData","registerDeviceOrientationEventCallback","fillDeviceMotionEventData","registerDeviceMotionEventCallback","screenOrientation","fillOrientationChangeEventData","registerOrientationChangeEventCallback","fillFullscreenChangeEventData","registerFullscreenChangeEventCallback","JSEvents_requestFullscreen","JSEvents_resizeCanvasForFullscreen","registerRestoreOldStyle","hideEverythingExceptGivenElement","restoreHiddenElements","setLetterbox","softFullscreenResizeWebGLRenderTarget","doRequestFullscreen","fillPointerlockChangeEventData","registerPointerlockChangeEventCallback","registerPointerlockErrorEventCallback","requestPointerLock","fillVisibilityChangeEventData","registerVisibilityChangeEventCallback","registerTouchEventCallback","fillGamepadEventData","registerGamepadEventCallback","registerBeforeUnloadEventCallback","fillBatteryEventData","battery","registerBatteryEventCallback","setCanvasElementSize","getCanvasElementSize","jsStackTrace","getCallstack","convertPCtoSourceLocation","checkWasiClock","wasiRightsToMuslOFlags","wasiOFlagsToMuslOFlags","createDyncallWrapper","safeSetTimeout","setImmediateWrapped","clearImmediateWrapped","polyfillSetImmediate","registerPostMainLoop","registerPreMainLoop","getPromise","makePromise","idsToPromises","makePromiseCallback","Browser_asyncPrepareDataCounter","safeRequestAnimationFrame","isLeapYear","ydayFromDate","arraySum","addDays","getSocketFromFD","getSocketAddress","FS_unlink","FS_mkdirTree","_setNetworkCallback","heapObjectForWebGLType","toTypedArrayIndex","webgl_enable_ANGLE_instanced_arrays","webgl_enable_OES_vertex_array_object","webgl_enable_WEBGL_draw_buffers","webgl_enable_WEBGL_multi_draw","webgl_enable_EXT_polygon_offset_clamp","webgl_enable_EXT_clip_control","webgl_enable_WEBGL_polygon_mode","emscriptenWebGLGet","computeUnpackAlignedImageSize","colorChannelsInGlTextureFormat","emscriptenWebGLGetTexPixelData","emscriptenWebGLGetUniform","webglGetUniformLocation","webglPrepareUniformLocationsBeforeFirstUse","webglGetLeftBracePos","emscriptenWebGLGetVertexAttrib","__glGetActiveAttribOrUniform","writeGLArray","registerWebGlEventCallback","runAndAbortIfError","ALLOC_NORMAL","ALLOC_STACK","allocate","writeStringToMemory","writeAsciiToMemory","setErrNo","demangle","stackTrace"];missingLibrarySymbols.forEach(missingLibrarySymbol);var unexportedSymbols=["run","addOnPreRun","addOnInit","addOnPreMain","addOnExit","addOnPostRun","addRunDependency","removeRunDependency","out","err","callMain","abort","wasmMemory","wasmExports","writeStackCookie","checkStackCookie","convertI32PairToI53Checked","stackSave","stackRestore","stackAlloc","setTempRet0","ptrToString","zeroMemory","getHeapMax","growMemory","ENV","setStackLimits","ERRNO_CODES","strError","DNS","Protocols","Sockets","initRandomFill","randomFill","timers","warnOnce","readEmAsmArgsArray","jstoi_s","getExecutableName","keepRuntimeAlive","asyncLoad","alignMemory","mmapAlloc","wasmTable","noExitRuntime","getCFunc","freeTableIndexes","functionsInTableMap","setValue","getValue","PATH","PATH_FS","UTF8Decoder","UTF8ArrayToString","stringToUTF8Array","stringToUTF8","lengthBytesUTF8","intArrayFromString","stringToAscii","UTF16Decoder","stringToUTF8OnStack","writeArrayToMemory","JSEvents","specialHTMLTargets","findCanvasEventTarget","currentFullscreenStrategy","restoreOldWindowedStyle","UNWIND_CACHE","ExitStatus","getEnvStrings","doReadv","doWritev","promiseMap","uncaughtExceptionCount","exceptionLast","exceptionCaught","ExceptionInfo","findMatchingCatch","Browser","getPreloadedImageData__data","wget","MONTH_DAYS_REGULAR","MONTH_DAYS_LEAP","MONTH_DAYS_REGULAR_CUMULATIVE","MONTH_DAYS_LEAP_CUMULATIVE","SYSCALLS","preloadPlugins","FS_createPreloadedFile","FS_modeStringToFlags","FS_getMode","FS_stdin_getChar_buffer","FS_stdin_getChar","FS_createPath","FS_createDevice","FS_readFile","FS","FS_createDataFile","FS_createLazyFile","MEMFS","TTY","PIPEFS","SOCKFS","tempFixedLengthArray","miniTempWebGLFloatBuffers","miniTempWebGLIntBuffers","GL","AL","GLUT","EGL","GLEW","IDBStore","SDL","SDL_gfx","allocateUTF8","allocateUTF8OnStack","print","printErr"];unexportedSymbols.forEach(unexportedRuntimeSymbol);var calledRun;var calledPrerun;dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function stackCheckInit(){_emscripten_stack_init();writeStackCookie()}function run(){if(runDependencies>0){return}stackCheckInit();if(!calledPrerun){calledPrerun=1;preRun();if(runDependencies>0){return}}function doRun(){if(calledRun)return;calledRun=1;Module["calledRun"]=1;if(ABORT)return;initRuntime();readyPromiseResolve(Module);Module["onRuntimeInitialized"]?.();assert(!Module["_main"],'compiled without a main, but one is present. if you added it from JS, use Module["onRuntimeInitialized"]');postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(()=>{setTimeout(()=>Module["setStatus"](""),1);doRun()},1)}else{doRun()}checkStackCookie()}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}run();moduleRtn=readyPromise;for(const prop of Object.keys(Module)){if(!(prop in moduleArg)){Object.defineProperty(moduleArg,prop,{configurable:true,get(){abort(`Access to module property ('${prop}') is no longer possible via the module constructor argument; Instead, use the result of the module constructor.`)}})}} +var Module=moduleArg;var readyPromiseResolve,readyPromiseReject;var readyPromise=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject});["_malloc","_free","_web_engine_create","_web_engine_destroy","_web_engine_get_memory_stats","_web_engine_get_live_handles","_web_engine_get_allocated_bytes","_web_engine_open_blend","_web_engine_apply_command","_web_engine_append_library_object","_web_engine_undo","_web_engine_redo","_web_engine_get_scene_snapshot","_web_engine_get_scene_metadata","_web_engine_get_scene_geometry","_web_engine_get_scene_delta","_web_engine_get_packed_asset","_web_engine_evaluate_depsgraph","_web_engine_save_blend","_web_engine_free_buffer","_web_engine_last_error_code","_web_engine_last_error_message","_web_engine_decimate_apply","_memory","___indirect_function_table","___set_stack_limits","onRuntimeInitialized"].forEach(prop=>{if(!Object.getOwnPropertyDescriptor(readyPromise,prop)){Object.defineProperty(readyPromise,prop,{get:()=>abort("You are getting "+prop+" on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js"),set:()=>abort("You are setting "+prop+" on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js")})}});var ENVIRONMENT_IS_WEB=typeof window=="object";var ENVIRONMENT_IS_WORKER=typeof importScripts=="function";var ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string"&&process.type!="renderer";var ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;if(ENVIRONMENT_IS_NODE){const{createRequire}=await import("module");let dirname=import.meta.url;if(dirname.startsWith("data:")){dirname="/"}var require=createRequire(dirname)}var moduleOverrides=Object.assign({},Module);var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_NODE){if(typeof process=="undefined"||!process.release||process.release.name!=="node")throw new Error("not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)");var nodeVersion=process.versions.node;var numericVersion=nodeVersion.split(".").slice(0,3);numericVersion=numericVersion[0]*1e4+numericVersion[1]*100+numericVersion[2].split("-")[0]*1;if(numericVersion<16e4){throw new Error("This emscripten-generated code requires node v16.0.0 (detected v"+nodeVersion+")")}var fs=require("fs");var nodePath=require("path");if(!import.meta.url.startsWith("data:")){scriptDirectory=nodePath.dirname(require("url").fileURLToPath(import.meta.url))+"/"}readBinary=filename=>{filename=isFileURI(filename)?new URL(filename):nodePath.normalize(filename);var ret=fs.readFileSync(filename);assert(ret.buffer);return ret};readAsync=(filename,binary=true)=>{filename=isFileURI(filename)?new URL(filename):nodePath.normalize(filename);return new Promise((resolve,reject)=>{fs.readFile(filename,binary?undefined:"utf8",(err,data)=>{if(err)reject(err);else resolve(binary?data.buffer:data)})})};if(!Module["thisProgram"]&&process.argv.length>1){thisProgram=process.argv[1].replace(/\\/g,"/")}arguments_=process.argv.slice(2);quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow}}else if(ENVIRONMENT_IS_SHELL){if(typeof process=="object"&&typeof require==="function"||typeof window=="object"||typeof importScripts=="function")throw new Error("not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)")}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(_scriptName){scriptDirectory=_scriptName}if(scriptDirectory.startsWith("blob:")){scriptDirectory=""}else{scriptDirectory=scriptDirectory.substr(0,scriptDirectory.replace(/[?#].*/,"").lastIndexOf("/")+1)}if(!(typeof window=="object"||typeof importScripts=="function"))throw new Error("not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)");{if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=url=>{assert(!isFileURI(url),"readAsync does not work with file:// URLs");return fetch(url,{credentials:"same-origin"}).then(response=>{if(response.ok){return response.arrayBuffer()}return Promise.reject(new Error(response.status+" : "+response.url))})}}}else{throw new Error("environment detection error")}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.error.bind(console);Object.assign(Module,moduleOverrides);moduleOverrides=null;checkIncomingModuleAPI();if(Module["arguments"])arguments_=Module["arguments"];legacyModuleProp("arguments","arguments_");if(Module["thisProgram"])thisProgram=Module["thisProgram"];legacyModuleProp("thisProgram","thisProgram");assert(typeof Module["memoryInitializerPrefixURL"]=="undefined","Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["pthreadMainPrefixURL"]=="undefined","Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["cdInitializerPrefixURL"]=="undefined","Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["filePackagePrefixURL"]=="undefined","Module.filePackagePrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["read"]=="undefined","Module.read option was removed");assert(typeof Module["readAsync"]=="undefined","Module.readAsync option was removed (modify readAsync in JS)");assert(typeof Module["readBinary"]=="undefined","Module.readBinary option was removed (modify readBinary in JS)");assert(typeof Module["setWindowTitle"]=="undefined","Module.setWindowTitle option was removed (modify emscripten_set_window_title in JS)");assert(typeof Module["TOTAL_MEMORY"]=="undefined","Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY");legacyModuleProp("asm","wasmExports");legacyModuleProp("readAsync","readAsync");legacyModuleProp("readBinary","readBinary");legacyModuleProp("setWindowTitle","setWindowTitle");assert(!ENVIRONMENT_IS_SHELL,"shell environment detected but not enabled at build time. Add `shell` to `-sENVIRONMENT` to enable.");var wasmBinary=Module["wasmBinary"];legacyModuleProp("wasmBinary","wasmBinary");if(typeof WebAssembly!="object"){err("no native wasm support detected")}var wasmMemory;var ABORT=false;var EXITSTATUS;function assert(condition,text){if(!condition){abort("Assertion failed"+(text?": "+text:""))}}var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateMemoryViews(){var b=wasmMemory.buffer;Module["HEAP8"]=HEAP8=new Int8Array(b);Module["HEAP16"]=HEAP16=new Int16Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);Module["HEAPU16"]=HEAPU16=new Uint16Array(b);Module["HEAP32"]=HEAP32=new Int32Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);Module["HEAPF64"]=HEAPF64=new Float64Array(b)}assert(!Module["STACK_SIZE"],"STACK_SIZE can no longer be set at runtime. Use -sSTACK_SIZE at link time");assert(typeof Int32Array!="undefined"&&typeof Float64Array!=="undefined"&&Int32Array.prototype.subarray!=undefined&&Int32Array.prototype.set!=undefined,"JS engine does not provide full typed array support");assert(!Module["wasmMemory"],"Use of `wasmMemory` detected. Use -sIMPORTED_MEMORY to define wasmMemory externally");assert(!Module["INITIAL_MEMORY"],"Detected runtime INITIAL_MEMORY setting. Use -sIMPORTED_MEMORY to define wasmMemory dynamically");function writeStackCookie(){var max=_emscripten_stack_get_end();assert((max&3)==0);if(max==0){max+=4}HEAPU32[max>>2]=34821223;checkInt32(34821223);HEAPU32[max+4>>2]=2310721022;checkInt32(2310721022);HEAPU32[0>>2]=1668509029;checkInt32(1668509029)}function checkStackCookie(){if(ABORT)return;var max=_emscripten_stack_get_end();if(max==0){max+=4}var cookie1=HEAPU32[max>>2];var cookie2=HEAPU32[max+4>>2];if(cookie1!=34821223||cookie2!=2310721022){abort(`Stack overflow! Stack cookie has been overwritten at ${ptrToString(max)}, expected hex dwords 0x89BACDFE and 0x2135467, but received ${ptrToString(cookie2)} ${ptrToString(cookie1)}`)}if(HEAPU32[0>>2]!=1668509029){abort("Runtime error: The application has corrupted its heap memory area (address zero)!")}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;function preRun(){var preRuns=Module["preRun"];if(preRuns){if(typeof preRuns=="function")preRuns=[preRuns];preRuns.forEach(addOnPreRun)}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){assert(!runtimeInitialized);runtimeInitialized=true;checkStackCookie();setStackLimits();if(!Module["noFSInit"]&&!FS.initialized)FS.init();FS.ignorePermissions=false;TTY.init();callRuntimeCallbacks(__ATINIT__)}function postRun(){checkStackCookie();var postRuns=Module["postRun"];if(postRuns){if(typeof postRuns=="function")postRuns=[postRuns];postRuns.forEach(addOnPostRun)}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnInit(cb){__ATINIT__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}assert(Math.imul,"This browser does not support Math.imul(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.fround,"This browser does not support Math.fround(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.clz32,"This browser does not support Math.clz32(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.trunc,"This browser does not support Math.trunc(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;var runDependencyTracking={};function getUniqueRunDependency(id){var orig=id;while(1){if(!runDependencyTracking[id])return id;id=orig+Math.random()}}function addRunDependency(id){runDependencies++;Module["monitorRunDependencies"]?.(runDependencies);if(id){assert(!runDependencyTracking[id]);runDependencyTracking[id]=1;if(runDependencyWatcher===null&&typeof setInterval!="undefined"){runDependencyWatcher=setInterval(()=>{if(ABORT){clearInterval(runDependencyWatcher);runDependencyWatcher=null;return}var shown=false;for(var dep in runDependencyTracking){if(!shown){shown=true;err("still waiting on run dependencies:")}err(`dependency: ${dep}`)}if(shown){err("(end of list)")}},1e4)}}else{err("warning: run dependency added without ID")}}function removeRunDependency(id){runDependencies--;Module["monitorRunDependencies"]?.(runDependencies);if(id){assert(runDependencyTracking[id]);delete runDependencyTracking[id]}else{err("warning: run dependency removed without ID")}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}function abort(what){Module["onAbort"]?.(what);what="Aborted("+what+")";err(what);ABORT=true;var e=new WebAssembly.RuntimeError(what);readyPromiseReject(e);throw e}var dataURIPrefix="data:application/octet-stream;base64,";var isDataURI=filename=>filename.startsWith(dataURIPrefix);var isFileURI=filename=>filename.startsWith("file://");function createExportWrapper(name,nargs){return(...args)=>{assert(runtimeInitialized,`native function \`${name}\` called before runtime initialization`);var f=wasmExports[name];assert(f,`exported native function \`${name}\` not found`);assert(args.length<=nargs,`native function \`${name}\` called with ${args.length} args but expects ${nargs}`);return f(...args)}}function findWasmBinary(){if(Module["locateFile"]){var f="web_engine.wasm";if(!isDataURI(f)){return locateFile(f)}return f}return new URL("web_engine.wasm",import.meta.url).href}var wasmBinaryFile;function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}function getBinaryPromise(binaryFile){if(!wasmBinary){return readAsync(binaryFile).then(response=>new Uint8Array(response),()=>getBinarySync(binaryFile))}return Promise.resolve().then(()=>getBinarySync(binaryFile))}function instantiateArrayBuffer(binaryFile,imports,receiver){return getBinaryPromise(binaryFile).then(binary=>WebAssembly.instantiate(binary,imports)).then(receiver,reason=>{err(`failed to asynchronously prepare wasm: ${reason}`);if(isFileURI(wasmBinaryFile)){err(`warning: Loading from a file URI (${wasmBinaryFile}) is not supported in most browsers. See https://emscripten.org/docs/getting_started/FAQ.html#how-do-i-run-a-local-webserver-for-testing-why-does-my-program-stall-in-downloading-or-preparing`)}abort(reason)})}function instantiateAsync(binary,binaryFile,imports,callback){if(!binary&&typeof WebAssembly.instantiateStreaming=="function"&&!isDataURI(binaryFile)&&!ENVIRONMENT_IS_NODE&&typeof fetch=="function"){return fetch(binaryFile,{credentials:"same-origin"}).then(response=>{var result=WebAssembly.instantiateStreaming(response,imports);return result.then(callback,function(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(binaryFile,imports,callback)})})}return instantiateArrayBuffer(binaryFile,imports,callback)}function getWasmImports(){return{env:wasmImports,wasi_snapshot_preview1:wasmImports}}function createWasm(){var info=getWasmImports();function receiveInstance(instance,module){wasmExports=instance.exports;wasmMemory=wasmExports["memory"];assert(wasmMemory,"memory not found in wasm exports");updateMemoryViews();wasmTable=wasmExports["__indirect_function_table"];assert(wasmTable,"table not found in wasm exports");addOnInit(wasmExports["__wasm_call_ctors"]);removeRunDependency("wasm-instantiate");return wasmExports}addRunDependency("wasm-instantiate");var trueModule=Module;function receiveInstantiationResult(result){assert(Module===trueModule,"the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?");trueModule=null;receiveInstance(result["instance"])}if(Module["instantiateWasm"]){try{return Module["instantiateWasm"](info,receiveInstance)}catch(e){err(`Module.instantiateWasm callback failed with error: ${e}`);readyPromiseReject(e)}}wasmBinaryFile??=findWasmBinary();instantiateAsync(wasmBinary,wasmBinaryFile,info,receiveInstantiationResult).catch(readyPromiseReject);return{}}var tempDouble;var tempI64;(()=>{var h16=new Int16Array(1);var h8=new Int8Array(h16.buffer);h16[0]=25459;if(h8[0]!==115||h8[1]!==99)throw"Runtime error: expected the system to be little-endian! (Run with -sSUPPORT_BIG_ENDIAN to bypass)"})();if(Module["ENVIRONMENT"]){throw new Error("Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -sENVIRONMENT=web or -sENVIRONMENT=node)")}function legacyModuleProp(prop,newName,incoming=true){if(!Object.getOwnPropertyDescriptor(Module,prop)){Object.defineProperty(Module,prop,{configurable:true,get(){let extra=incoming?" (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)":"";abort(`\`Module.${prop}\` has been replaced by \`${newName}\``+extra)}})}}function ignoredModuleProp(prop){if(Object.getOwnPropertyDescriptor(Module,prop)){abort(`\`Module.${prop}\` was supplied but \`${prop}\` not included in INCOMING_MODULE_JS_API`)}}function isExportedByForceFilesystem(name){return name==="FS_createPath"||name==="FS_createDataFile"||name==="FS_createPreloadedFile"||name==="FS_unlink"||name==="addRunDependency"||name==="FS_createLazyFile"||name==="FS_createDevice"||name==="removeRunDependency"}function hookGlobalSymbolAccess(sym,func){if(typeof globalThis!="undefined"&&!Object.getOwnPropertyDescriptor(globalThis,sym)){Object.defineProperty(globalThis,sym,{configurable:true,get(){func();return undefined}})}}function missingGlobal(sym,msg){hookGlobalSymbolAccess(sym,()=>{warnOnce(`\`${sym}\` is not longer defined by emscripten. ${msg}`)})}missingGlobal("buffer","Please use HEAP8.buffer or wasmMemory.buffer");missingGlobal("asm","Please use wasmExports instead");function missingLibrarySymbol(sym){hookGlobalSymbolAccess(sym,()=>{var msg=`\`${sym}\` is a library symbol and not included by default; add it to your library.js __deps or to DEFAULT_LIBRARY_FUNCS_TO_INCLUDE on the command line`;var librarySymbol=sym;if(!librarySymbol.startsWith("_")){librarySymbol="$"+sym}msg+=` (e.g. -sDEFAULT_LIBRARY_FUNCS_TO_INCLUDE='${librarySymbol}')`;if(isExportedByForceFilesystem(sym)){msg+=". Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you"}warnOnce(msg)});unexportedRuntimeSymbol(sym)}function unexportedRuntimeSymbol(sym){if(!Object.getOwnPropertyDescriptor(Module,sym)){Object.defineProperty(Module,sym,{configurable:true,get(){var msg=`'${sym}' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the Emscripten FAQ)`;if(isExportedByForceFilesystem(sym)){msg+=". Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you"}abort(msg)}})}}var MAX_UINT8=2**8-1;var MAX_UINT16=2**16-1;var MAX_UINT32=2**32-1;var MAX_UINT53=2**53-1;var MAX_UINT64=2**64-1;var MIN_INT8=-(2**(8-1));var MIN_INT16=-(2**(16-1));var MIN_INT32=-(2**(32-1));var MIN_INT53=-(2**(53-1));var MIN_INT64=-(2**(64-1));function checkInt(value,bits,min,max){assert(Number.isInteger(Number(value)),`attempt to write non-integer (${value}) into integer heap`);assert(value<=max,`value (${value}) too large to write as ${bits}-bit value`);assert(value>=min,`value (${value}) too small to write as ${bits}-bit value`)}var checkInt8=value=>checkInt(value,8,MIN_INT8,MAX_UINT8);var checkInt16=value=>checkInt(value,16,MIN_INT16,MAX_UINT16);var checkInt32=value=>checkInt(value,32,MIN_INT32,MAX_UINT32);var checkInt64=value=>checkInt(value,64,MIN_INT64,MAX_UINT64);function dbg(...args){console.warn(...args)}function ExitStatus(status){this.name="ExitStatus";this.message=`Program terminated with exit(${status})`;this.status=status}var callRuntimeCallbacks=callbacks=>{callbacks.forEach(f=>f(Module))};var noExitRuntime=Module["noExitRuntime"]||true;var ptrToString=ptr=>{assert(typeof ptr==="number");ptr>>>=0;return"0x"+ptr.toString(16).padStart(8,"0")};var setStackLimits=()=>{var stackLow=_emscripten_stack_get_base();var stackHigh=_emscripten_stack_get_end();___set_stack_limits(stackLow,stackHigh)};var stackRestore=val=>__emscripten_stack_restore(val);var stackSave=()=>_emscripten_stack_get_current();var warnOnce=text=>{warnOnce.shown||={};if(!warnOnce.shown[text]){warnOnce.shown[text]=1;if(ENVIRONMENT_IS_NODE)text="warning: "+text;err(text)}};var UTF8Decoder=typeof TextDecoder!="undefined"?new TextDecoder:undefined;var UTF8ArrayToString=(heapOrArray,idx=0,maxBytesToRead=NaN)=>{var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heapOrArray[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx>10,56320|ch&1023)}}return str};var UTF8ToString=(ptr,maxBytesToRead)=>{assert(typeof ptr=="number",`UTF8ToString expects a number (got ${typeof ptr})`);return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""};var ___assert_fail=(condition,filename,line,func)=>{abort(`Assertion failed: ${UTF8ToString(condition)}, at: `+[filename?UTF8ToString(filename):"unknown filename",line,func?UTF8ToString(func):"unknown function"])};var wasmTableMirror=[];var wasmTable;var getWasmTableEntry=funcPtr=>{var func=wasmTableMirror[funcPtr];if(!func){if(funcPtr>=wasmTableMirror.length)wasmTableMirror.length=funcPtr+1;wasmTableMirror[funcPtr]=func=wasmTable.get(funcPtr)}assert(wasmTable.get(funcPtr)==func,"JavaScript-side Wasm function table mirror is out of date!");return func};var ___call_sighandler=(fp,sig)=>getWasmTableEntry(fp)(sig);var exceptionCaught=[];var uncaughtExceptionCount=0;var ___cxa_begin_catch=ptr=>{var info=new ExceptionInfo(ptr);if(!info.get_caught()){info.set_caught(true);uncaughtExceptionCount--}info.set_rethrown(false);exceptionCaught.push(info);___cxa_increment_exception_refcount(ptr);return ___cxa_get_exception_ptr(ptr)};var exceptionLast=0;var ___cxa_end_catch=()=>{_setThrew(0,0);assert(exceptionCaught.length>0);var info=exceptionCaught.pop();___cxa_decrement_exception_refcount(info.excPtr);exceptionLast=0};class ExceptionInfo{constructor(excPtr){this.excPtr=excPtr;this.ptr=excPtr-24}set_type(type){HEAPU32[this.ptr+4>>2]=type}get_type(){return HEAPU32[this.ptr+4>>2]}set_destructor(destructor){HEAPU32[this.ptr+8>>2]=destructor}get_destructor(){return HEAPU32[this.ptr+8>>2]}set_caught(caught){caught=caught?1:0;HEAP8[this.ptr+12]=caught;checkInt8(caught)}get_caught(){return HEAP8[this.ptr+12]!=0}set_rethrown(rethrown){rethrown=rethrown?1:0;HEAP8[this.ptr+13]=rethrown;checkInt8(rethrown)}get_rethrown(){return HEAP8[this.ptr+13]!=0}init(type,destructor){this.set_adjusted_ptr(0);this.set_type(type);this.set_destructor(destructor)}set_adjusted_ptr(adjustedPtr){HEAPU32[this.ptr+16>>2]=adjustedPtr}get_adjusted_ptr(){return HEAPU32[this.ptr+16>>2]}}var ___resumeException=ptr=>{if(!exceptionLast){exceptionLast=ptr}assert(false,"Exception thrown, but exception catching is not enabled. Compile with -sNO_DISABLE_EXCEPTION_CATCHING or -sEXCEPTION_CATCHING_ALLOWED=[..] to catch.")};var setTempRet0=val=>__emscripten_tempret_set(val);var findMatchingCatch=args=>{var thrown=exceptionLast;if(!thrown){setTempRet0(0);return 0}var info=new ExceptionInfo(thrown);info.set_adjusted_ptr(thrown);var thrownType=info.get_type();if(!thrownType){setTempRet0(0);return thrown}for(var caughtType of args){if(caughtType===0||caughtType===thrownType){break}var adjusted_ptr_addr=info.ptr+16;if(___cxa_can_catch(caughtType,thrownType,adjusted_ptr_addr)){setTempRet0(caughtType);return thrown}}setTempRet0(thrownType);return thrown};var ___cxa_find_matching_catch_2=()=>findMatchingCatch([]);var ___cxa_find_matching_catch_3=arg0=>findMatchingCatch([arg0]);var ___cxa_rethrow=()=>{var info=exceptionCaught.pop();if(!info){abort("no exception to throw")}var ptr=info.excPtr;if(!info.get_rethrown()){exceptionCaught.push(info);info.set_rethrown(true);info.set_caught(false);uncaughtExceptionCount++}exceptionLast=ptr;assert(false,"Exception thrown, but exception catching is not enabled. Compile with -sNO_DISABLE_EXCEPTION_CATCHING or -sEXCEPTION_CATCHING_ALLOWED=[..] to catch.")};var ___cxa_throw=(ptr,type,destructor)=>{var info=new ExceptionInfo(ptr);info.init(type,destructor);exceptionLast=ptr;uncaughtExceptionCount++;assert(false,"Exception thrown, but exception catching is not enabled. Compile with -sNO_DISABLE_EXCEPTION_CATCHING or -sEXCEPTION_CATCHING_ALLOWED=[..] to catch.")};var ___handle_stack_overflow=requested=>{var base=_emscripten_stack_get_base();var end=_emscripten_stack_get_end();abort(`stack overflow (Attempt to set SP to ${ptrToString(requested)}`+`, with stack limits [${ptrToString(end)} - ${ptrToString(base)}`+"]). If you require more stack space build with -sSTACK_SIZE=")};var PATH={isAbs:path=>path.charAt(0)==="/",splitPath:filename=>{var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;return splitPathRe.exec(filename).slice(1)},normalizeArray:(parts,allowAboveRoot)=>{var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up;up--){parts.unshift("..")}}return parts},normalize:path=>{var isAbsolute=PATH.isAbs(path),trailingSlash=path.substr(-1)==="/";path=PATH.normalizeArray(path.split("/").filter(p=>!!p),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path},dirname:path=>{var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return"."}if(dir){dir=dir.substr(0,dir.length-1)}return root+dir},basename:path=>{if(path==="/")return"/";path=PATH.normalize(path);path=path.replace(/\/$/,"");var lastSlash=path.lastIndexOf("/");if(lastSlash===-1)return path;return path.substr(lastSlash+1)},join:(...paths)=>PATH.normalize(paths.join("/")),join2:(l,r)=>PATH.normalize(l+"/"+r)};var initRandomFill=()=>{if(typeof crypto=="object"&&typeof crypto["getRandomValues"]=="function"){return view=>crypto.getRandomValues(view)}else if(ENVIRONMENT_IS_NODE){try{var crypto_module=require("crypto");var randomFillSync=crypto_module["randomFillSync"];if(randomFillSync){return view=>crypto_module["randomFillSync"](view)}var randomBytes=crypto_module["randomBytes"];return view=>(view.set(randomBytes(view.byteLength)),view)}catch(e){}}abort("no cryptographic support found for randomDevice. consider polyfilling it if you want to use something insecure like Math.random(), e.g. put this in a --pre-js: var crypto = { getRandomValues: (array) => { for (var i = 0; i < array.length; i++) array[i] = (Math.random()*256)|0 } };")};var randomFill=view=>(randomFill=initRandomFill())(view);var PATH_FS={resolve:(...args)=>{var resolvedPath="",resolvedAbsolute=false;for(var i=args.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?args[i]:FS.cwd();if(typeof path!="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){return""}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=PATH.isAbs(path)}resolvedPath=PATH.normalizeArray(resolvedPath.split("/").filter(p=>!!p),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."},relative:(from,to)=>{from=PATH_FS.resolve(from).substr(1);to=PATH_FS.resolve(to).substr(1);function trim(arr){var start=0;for(;start=0;end--){if(arr[end]!=="")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split("/"));var toParts=trim(to.split("/"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i{var len=0;for(var i=0;i=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{assert(typeof str==="string",`stringToUTF8Array expects a string (got ${typeof str})`);if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;if(u>1114111)warnOnce("Invalid Unicode code point "+ptrToString(u)+" encountered when serializing a JS string to a UTF-8 string in wasm memory! (Valid unicode code points should be in range 0-0x10FFFF).");heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx};function intArrayFromString(stringy,dontAddNull,length){var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array}var FS_stdin_getChar=()=>{if(!FS_stdin_getChar_buffer.length){var result=null;if(ENVIRONMENT_IS_NODE){var BUFSIZE=256;var buf=Buffer.alloc(BUFSIZE);var bytesRead=0;var fd=process.stdin.fd;try{bytesRead=fs.readSync(fd,buf,0,BUFSIZE)}catch(e){if(e.toString().includes("EOF"))bytesRead=0;else throw e}if(bytesRead>0){result=buf.slice(0,bytesRead).toString("utf-8")}}else if(typeof window!="undefined"&&typeof window.prompt=="function"){result=window.prompt("Input: ");if(result!==null){result+="\n"}}else{}if(!result){return null}FS_stdin_getChar_buffer=intArrayFromString(result,true)}return FS_stdin_getChar_buffer.shift()};var TTY={ttys:[],init(){},shutdown(){},register(dev,ops){TTY.ttys[dev]={input:[],output:[],ops};FS.registerDevice(dev,TTY.stream_ops)},stream_ops:{open(stream){var tty=TTY.ttys[stream.node.rdev];if(!tty){throw new FS.ErrnoError(43)}stream.tty=tty;stream.seekable=false},close(stream){stream.tty.ops.fsync(stream.tty)},fsync(stream){stream.tty.ops.fsync(stream.tty)},read(stream,buffer,offset,length,pos){if(!stream.tty||!stream.tty.ops.get_char){throw new FS.ErrnoError(60)}var bytesRead=0;for(var i=0;i0){out(UTF8ArrayToString(tty.output));tty.output=[]}},ioctl_tcgets(tty){return{c_iflag:25856,c_oflag:5,c_cflag:191,c_lflag:35387,c_cc:[3,28,127,21,4,0,1,0,17,19,26,0,18,15,23,22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}},ioctl_tcsets(tty,optional_actions,data){return 0},ioctl_tiocgwinsz(tty){return[24,80]}},default_tty1_ops:{put_char(tty,val){if(val===null||val===10){err(UTF8ArrayToString(tty.output));tty.output=[]}else{if(val!=0)tty.output.push(val)}},fsync(tty){if(tty.output&&tty.output.length>0){err(UTF8ArrayToString(tty.output));tty.output=[]}}}};var zeroMemory=(address,size)=>{HEAPU8.fill(0,address,address+size)};var alignMemory=(size,alignment)=>{assert(alignment,"alignment argument is required");return Math.ceil(size/alignment)*alignment};var mmapAlloc=size=>{size=alignMemory(size,65536);var ptr=_emscripten_builtin_memalign(65536,size);if(ptr)zeroMemory(ptr,size);return ptr};var MEMFS={ops_table:null,mount(mount){return MEMFS.createNode(null,"/",16384|511,0)},createNode(parent,name,mode,dev){if(FS.isBlkdev(mode)||FS.isFIFO(mode)){throw new FS.ErrnoError(63)}MEMFS.ops_table||={dir:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,lookup:MEMFS.node_ops.lookup,mknod:MEMFS.node_ops.mknod,rename:MEMFS.node_ops.rename,unlink:MEMFS.node_ops.unlink,rmdir:MEMFS.node_ops.rmdir,readdir:MEMFS.node_ops.readdir,symlink:MEMFS.node_ops.symlink},stream:{llseek:MEMFS.stream_ops.llseek}},file:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:{llseek:MEMFS.stream_ops.llseek,read:MEMFS.stream_ops.read,write:MEMFS.stream_ops.write,allocate:MEMFS.stream_ops.allocate,mmap:MEMFS.stream_ops.mmap,msync:MEMFS.stream_ops.msync}},link:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,readlink:MEMFS.node_ops.readlink},stream:{}},chrdev:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:FS.chrdev_stream_ops}};var node=FS.createNode(parent,name,mode,dev);if(FS.isDir(node.mode)){node.node_ops=MEMFS.ops_table.dir.node;node.stream_ops=MEMFS.ops_table.dir.stream;node.contents={}}else if(FS.isFile(node.mode)){node.node_ops=MEMFS.ops_table.file.node;node.stream_ops=MEMFS.ops_table.file.stream;node.usedBytes=0;node.contents=null}else if(FS.isLink(node.mode)){node.node_ops=MEMFS.ops_table.link.node;node.stream_ops=MEMFS.ops_table.link.stream}else if(FS.isChrdev(node.mode)){node.node_ops=MEMFS.ops_table.chrdev.node;node.stream_ops=MEMFS.ops_table.chrdev.stream}node.timestamp=Date.now();if(parent){parent.contents[name]=node;parent.timestamp=node.timestamp}return node},getFileDataAsTypedArray(node){if(!node.contents)return new Uint8Array(0);if(node.contents.subarray)return node.contents.subarray(0,node.usedBytes);return new Uint8Array(node.contents)},expandFileStorage(node,newCapacity){var prevCapacity=node.contents?node.contents.length:0;if(prevCapacity>=newCapacity)return;var CAPACITY_DOUBLING_MAX=1024*1024;newCapacity=Math.max(newCapacity,prevCapacity*(prevCapacity>>0);if(prevCapacity!=0)newCapacity=Math.max(newCapacity,256);var oldContents=node.contents;node.contents=new Uint8Array(newCapacity);if(node.usedBytes>0)node.contents.set(oldContents.subarray(0,node.usedBytes),0)},resizeFileStorage(node,newSize){if(node.usedBytes==newSize)return;if(newSize==0){node.contents=null;node.usedBytes=0}else{var oldContents=node.contents;node.contents=new Uint8Array(newSize);if(oldContents){node.contents.set(oldContents.subarray(0,Math.min(newSize,node.usedBytes)))}node.usedBytes=newSize}},node_ops:{getattr(node){var attr={};attr.dev=FS.isChrdev(node.mode)?node.id:1;attr.ino=node.id;attr.mode=node.mode;attr.nlink=1;attr.uid=0;attr.gid=0;attr.rdev=node.rdev;if(FS.isDir(node.mode)){attr.size=4096}else if(FS.isFile(node.mode)){attr.size=node.usedBytes}else if(FS.isLink(node.mode)){attr.size=node.link.length}else{attr.size=0}attr.atime=new Date(node.timestamp);attr.mtime=new Date(node.timestamp);attr.ctime=new Date(node.timestamp);attr.blksize=4096;attr.blocks=Math.ceil(attr.size/attr.blksize);return attr},setattr(node,attr){if(attr.mode!==undefined){node.mode=attr.mode}if(attr.timestamp!==undefined){node.timestamp=attr.timestamp}if(attr.size!==undefined){MEMFS.resizeFileStorage(node,attr.size)}},lookup(parent,name){throw FS.genericErrors[44]},mknod(parent,name,mode,dev){return MEMFS.createNode(parent,name,mode,dev)},rename(old_node,new_dir,new_name){if(FS.isDir(old_node.mode)){var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(new_node){for(var i in new_node.contents){throw new FS.ErrnoError(55)}}}delete old_node.parent.contents[old_node.name];old_node.parent.timestamp=Date.now();old_node.name=new_name;new_dir.contents[new_name]=old_node;new_dir.timestamp=old_node.parent.timestamp},unlink(parent,name){delete parent.contents[name];parent.timestamp=Date.now()},rmdir(parent,name){var node=FS.lookupNode(parent,name);for(var i in node.contents){throw new FS.ErrnoError(55)}delete parent.contents[name];parent.timestamp=Date.now()},readdir(node){var entries=[".",".."];for(var key of Object.keys(node.contents)){entries.push(key)}return entries},symlink(parent,newname,oldpath){var node=MEMFS.createNode(parent,newname,511|40960,0);node.link=oldpath;return node},readlink(node){if(!FS.isLink(node.mode)){throw new FS.ErrnoError(28)}return node.link}},stream_ops:{read(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=stream.node.usedBytes)return 0;var size=Math.min(stream.node.usedBytes-position,length);assert(size>=0);if(size>8&&contents.subarray){buffer.set(contents.subarray(position,position+size),offset)}else{for(var i=0;i0||position+length{var dep=!noRunDep?getUniqueRunDependency(`al ${url}`):"";readAsync(url).then(arrayBuffer=>{assert(arrayBuffer,`Loading data file "${url}" failed (no arrayBuffer).`);onload(new Uint8Array(arrayBuffer));if(dep)removeRunDependency(dep)},err=>{if(onerror){onerror()}else{throw`Loading data file "${url}" failed.`}});if(dep)addRunDependency(dep)};var FS_createDataFile=(parent,name,fileData,canRead,canWrite,canOwn)=>{FS.createDataFile(parent,name,fileData,canRead,canWrite,canOwn)};var preloadPlugins=Module["preloadPlugins"]||[];var FS_handledByPreloadPlugin=(byteArray,fullname,finish,onerror)=>{if(typeof Browser!="undefined")Browser.init();var handled=false;preloadPlugins.forEach(plugin=>{if(handled)return;if(plugin["canHandle"](fullname)){plugin["handle"](byteArray,fullname,finish,onerror);handled=true}});return handled};var FS_createPreloadedFile=(parent,name,url,canRead,canWrite,onload,onerror,dontCreateFile,canOwn,preFinish)=>{var fullname=name?PATH_FS.resolve(PATH.join2(parent,name)):parent;var dep=getUniqueRunDependency(`cp ${fullname}`);function processData(byteArray){function finish(byteArray){preFinish?.();if(!dontCreateFile){FS_createDataFile(parent,name,byteArray,canRead,canWrite,canOwn)}onload?.();removeRunDependency(dep)}if(FS_handledByPreloadPlugin(byteArray,fullname,finish,()=>{onerror?.();removeRunDependency(dep)})){return}finish(byteArray)}addRunDependency(dep);if(typeof url=="string"){asyncLoad(url,processData,onerror)}else{processData(url)}};var FS_modeStringToFlags=str=>{var flagModes={r:0,"r+":2,w:512|64|1,"w+":512|64|2,a:1024|64|1,"a+":1024|64|2};var flags=flagModes[str];if(typeof flags=="undefined"){throw new Error(`Unknown file open mode: ${str}`)}return flags};var FS_getMode=(canRead,canWrite)=>{var mode=0;if(canRead)mode|=292|73;if(canWrite)mode|=146;return mode};var strError=errno=>UTF8ToString(_strerror(errno));var ERRNO_CODES={EPERM:63,ENOENT:44,ESRCH:71,EINTR:27,EIO:29,ENXIO:60,E2BIG:1,ENOEXEC:45,EBADF:8,ECHILD:12,EAGAIN:6,EWOULDBLOCK:6,ENOMEM:48,EACCES:2,EFAULT:21,ENOTBLK:105,EBUSY:10,EEXIST:20,EXDEV:75,ENODEV:43,ENOTDIR:54,EISDIR:31,EINVAL:28,ENFILE:41,EMFILE:33,ENOTTY:59,ETXTBSY:74,EFBIG:22,ENOSPC:51,ESPIPE:70,EROFS:69,EMLINK:34,EPIPE:64,EDOM:18,ERANGE:68,ENOMSG:49,EIDRM:24,ECHRNG:106,EL2NSYNC:156,EL3HLT:107,EL3RST:108,ELNRNG:109,EUNATCH:110,ENOCSI:111,EL2HLT:112,EDEADLK:16,ENOLCK:46,EBADE:113,EBADR:114,EXFULL:115,ENOANO:104,EBADRQC:103,EBADSLT:102,EDEADLOCK:16,EBFONT:101,ENOSTR:100,ENODATA:116,ETIME:117,ENOSR:118,ENONET:119,ENOPKG:120,EREMOTE:121,ENOLINK:47,EADV:122,ESRMNT:123,ECOMM:124,EPROTO:65,EMULTIHOP:36,EDOTDOT:125,EBADMSG:9,ENOTUNIQ:126,EBADFD:127,EREMCHG:128,ELIBACC:129,ELIBBAD:130,ELIBSCN:131,ELIBMAX:132,ELIBEXEC:133,ENOSYS:52,ENOTEMPTY:55,ENAMETOOLONG:37,ELOOP:32,EOPNOTSUPP:138,EPFNOSUPPORT:139,ECONNRESET:15,ENOBUFS:42,EAFNOSUPPORT:5,EPROTOTYPE:67,ENOTSOCK:57,ENOPROTOOPT:50,ESHUTDOWN:140,ECONNREFUSED:14,EADDRINUSE:3,ECONNABORTED:13,ENETUNREACH:40,ENETDOWN:38,ETIMEDOUT:73,EHOSTDOWN:142,EHOSTUNREACH:23,EINPROGRESS:26,EALREADY:7,EDESTADDRREQ:17,EMSGSIZE:35,EPROTONOSUPPORT:66,ESOCKTNOSUPPORT:137,EADDRNOTAVAIL:4,ENETRESET:39,EISCONN:30,ENOTCONN:53,ETOOMANYREFS:141,EUSERS:136,EDQUOT:19,ESTALE:72,ENOTSUP:138,ENOMEDIUM:148,EILSEQ:25,EOVERFLOW:61,ECANCELED:11,ENOTRECOVERABLE:56,EOWNERDEAD:62,ESTRPIPE:135};var FS={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,ErrnoError:class extends Error{constructor(errno){super(runtimeInitialized?strError(errno):"");this.name="ErrnoError";this.errno=errno;for(var key in ERRNO_CODES){if(ERRNO_CODES[key]===errno){this.code=key;break}}}},genericErrors:{},filesystems:null,syncFSRequests:0,readFiles:{},FSStream:class{constructor(){this.shared={}}get object(){return this.node}set object(val){this.node=val}get isRead(){return(this.flags&2097155)!==1}get isWrite(){return(this.flags&2097155)!==0}get isAppend(){return this.flags&1024}get flags(){return this.shared.flags}set flags(val){this.shared.flags=val}get position(){return this.shared.position}set position(val){this.shared.position=val}},FSNode:class{constructor(parent,name,mode,rdev){if(!parent){parent=this}this.parent=parent;this.mount=parent.mount;this.mounted=null;this.id=FS.nextInode++;this.name=name;this.mode=mode;this.node_ops={};this.stream_ops={};this.rdev=rdev;this.readMode=292|73;this.writeMode=146}get read(){return(this.mode&this.readMode)===this.readMode}set read(val){val?this.mode|=this.readMode:this.mode&=~this.readMode}get write(){return(this.mode&this.writeMode)===this.writeMode}set write(val){val?this.mode|=this.writeMode:this.mode&=~this.writeMode}get isFolder(){return FS.isDir(this.mode)}get isDevice(){return FS.isChrdev(this.mode)}},lookupPath(path,opts={}){path=PATH_FS.resolve(path);if(!path)return{path:"",node:null};var defaults={follow_mount:true,recurse_count:0};opts=Object.assign(defaults,opts);if(opts.recurse_count>8){throw new FS.ErrnoError(32)}var parts=path.split("/").filter(p=>!!p);var current=FS.root;var current_path="/";for(var i=0;i40){throw new FS.ErrnoError(32)}}}}return{path:current_path,node:current}},getPath(node){var path;while(true){if(FS.isRoot(node)){var mount=node.mount.mountpoint;if(!path)return mount;return mount[mount.length-1]!=="/"?`${mount}/${path}`:mount+path}path=path?`${node.name}/${path}`:node.name;node=node.parent}},hashName(parentid,name){var hash=0;for(var i=0;i>>0)%FS.nameTable.length},hashAddNode(node){var hash=FS.hashName(node.parent.id,node.name);node.name_next=FS.nameTable[hash];FS.nameTable[hash]=node},hashRemoveNode(node){var hash=FS.hashName(node.parent.id,node.name);if(FS.nameTable[hash]===node){FS.nameTable[hash]=node.name_next}else{var current=FS.nameTable[hash];while(current){if(current.name_next===node){current.name_next=node.name_next;break}current=current.name_next}}},lookupNode(parent,name){var errCode=FS.mayLookup(parent);if(errCode){throw new FS.ErrnoError(errCode)}var hash=FS.hashName(parent.id,name);for(var node=FS.nameTable[hash];node;node=node.name_next){var nodeName=node.name;if(node.parent.id===parent.id&&nodeName===name){return node}}return FS.lookup(parent,name)},createNode(parent,name,mode,rdev){assert(typeof parent=="object");var node=new FS.FSNode(parent,name,mode,rdev);FS.hashAddNode(node);return node},destroyNode(node){FS.hashRemoveNode(node)},isRoot(node){return node===node.parent},isMountpoint(node){return!!node.mounted},isFile(mode){return(mode&61440)===32768},isDir(mode){return(mode&61440)===16384},isLink(mode){return(mode&61440)===40960},isChrdev(mode){return(mode&61440)===8192},isBlkdev(mode){return(mode&61440)===24576},isFIFO(mode){return(mode&61440)===4096},isSocket(mode){return(mode&49152)===49152},flagsToPermissionString(flag){var perms=["r","w","rw"][flag&3];if(flag&512){perms+="w"}return perms},nodePermissions(node,perms){if(FS.ignorePermissions){return 0}if(perms.includes("r")&&!(node.mode&292)){return 2}else if(perms.includes("w")&&!(node.mode&146)){return 2}else if(perms.includes("x")&&!(node.mode&73)){return 2}return 0},mayLookup(dir){if(!FS.isDir(dir.mode))return 54;var errCode=FS.nodePermissions(dir,"x");if(errCode)return errCode;if(!dir.node_ops.lookup)return 2;return 0},mayCreate(dir,name){try{var node=FS.lookupNode(dir,name);return 20}catch(e){}return FS.nodePermissions(dir,"wx")},mayDelete(dir,name,isdir){var node;try{node=FS.lookupNode(dir,name)}catch(e){return e.errno}var errCode=FS.nodePermissions(dir,"wx");if(errCode){return errCode}if(isdir){if(!FS.isDir(node.mode)){return 54}if(FS.isRoot(node)||FS.getPath(node)===FS.cwd()){return 10}}else{if(FS.isDir(node.mode)){return 31}}return 0},mayOpen(node,flags){if(!node){return 44}if(FS.isLink(node.mode)){return 32}else if(FS.isDir(node.mode)){if(FS.flagsToPermissionString(flags)!=="r"||flags&512){return 31}}return FS.nodePermissions(node,FS.flagsToPermissionString(flags))},MAX_OPEN_FDS:4096,nextfd(){for(var fd=0;fd<=FS.MAX_OPEN_FDS;fd++){if(!FS.streams[fd]){return fd}}throw new FS.ErrnoError(33)},getStreamChecked(fd){var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(8)}return stream},getStream:fd=>FS.streams[fd],createStream(stream,fd=-1){assert(fd>=-1);stream=Object.assign(new FS.FSStream,stream);if(fd==-1){fd=FS.nextfd()}stream.fd=fd;FS.streams[fd]=stream;return stream},closeStream(fd){FS.streams[fd]=null},dupStream(origStream,fd=-1){var stream=FS.createStream(origStream,fd);stream.stream_ops?.dup?.(stream);return stream},chrdev_stream_ops:{open(stream){var device=FS.getDevice(stream.node.rdev);stream.stream_ops=device.stream_ops;stream.stream_ops.open?.(stream)},llseek(){throw new FS.ErrnoError(70)}},major:dev=>dev>>8,minor:dev=>dev&255,makedev:(ma,mi)=>ma<<8|mi,registerDevice(dev,ops){FS.devices[dev]={stream_ops:ops}},getDevice:dev=>FS.devices[dev],getMounts(mount){var mounts=[];var check=[mount];while(check.length){var m=check.pop();mounts.push(m);check.push(...m.mounts)}return mounts},syncfs(populate,callback){if(typeof populate=="function"){callback=populate;populate=false}FS.syncFSRequests++;if(FS.syncFSRequests>1){err(`warning: ${FS.syncFSRequests} FS.syncfs operations in flight at once, probably just doing extra work`)}var mounts=FS.getMounts(FS.root.mount);var completed=0;function doCallback(errCode){assert(FS.syncFSRequests>0);FS.syncFSRequests--;return callback(errCode)}function done(errCode){if(errCode){if(!done.errored){done.errored=true;return doCallback(errCode)}return}if(++completed>=mounts.length){doCallback(null)}}mounts.forEach(mount=>{if(!mount.type.syncfs){return done(null)}mount.type.syncfs(mount,populate,done)})},mount(type,opts,mountpoint){if(typeof type=="string"){throw type}var root=mountpoint==="/";var pseudo=!mountpoint;var node;if(root&&FS.root){throw new FS.ErrnoError(10)}else if(!root&&!pseudo){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});mountpoint=lookup.path;node=lookup.node;if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}if(!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}}var mount={type,opts,mountpoint,mounts:[]};var mountRoot=type.mount(mount);mountRoot.mount=mount;mount.root=mountRoot;if(root){FS.root=mountRoot}else if(node){node.mounted=mount;if(node.mount){node.mount.mounts.push(mount)}}return mountRoot},unmount(mountpoint){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});if(!FS.isMountpoint(lookup.node)){throw new FS.ErrnoError(28)}var node=lookup.node;var mount=node.mounted;var mounts=FS.getMounts(mount);Object.keys(FS.nameTable).forEach(hash=>{var current=FS.nameTable[hash];while(current){var next=current.name_next;if(mounts.includes(current.mount)){FS.destroyNode(current)}current=next}});node.mounted=null;var idx=node.mount.mounts.indexOf(mount);assert(idx!==-1);node.mount.mounts.splice(idx,1)},lookup(parent,name){return parent.node_ops.lookup(parent,name)},mknod(path,mode,dev){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);if(!name||name==="."||name===".."){throw new FS.ErrnoError(28)}var errCode=FS.mayCreate(parent,name);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.mknod){throw new FS.ErrnoError(63)}return parent.node_ops.mknod(parent,name,mode,dev)},create(path,mode){mode=mode!==undefined?mode:438;mode&=4095;mode|=32768;return FS.mknod(path,mode,0)},mkdir(path,mode){mode=mode!==undefined?mode:511;mode&=511|512;mode|=16384;return FS.mknod(path,mode,0)},mkdirTree(path,mode){var dirs=path.split("/");var d="";for(var i=0;i=0);if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.read){throw new FS.ErrnoError(28)}var seeking=typeof position!="undefined";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesRead=stream.stream_ops.read(stream,buffer,offset,length,position);if(!seeking)stream.position+=bytesRead;return bytesRead},write(stream,buffer,offset,length,position,canOwn){assert(offset>=0);if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.write){throw new FS.ErrnoError(28)}if(stream.seekable&&stream.flags&1024){FS.llseek(stream,0,2)}var seeking=typeof position!="undefined";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesWritten=stream.stream_ops.write(stream,buffer,offset,length,position,canOwn);if(!seeking)stream.position+=bytesWritten;return bytesWritten},allocate(stream,offset,length){if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(offset<0||length<=0){throw new FS.ErrnoError(28)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(8)}if(!FS.isFile(stream.node.mode)&&!FS.isDir(stream.node.mode)){throw new FS.ErrnoError(43)}if(!stream.stream_ops.allocate){throw new FS.ErrnoError(138)}stream.stream_ops.allocate(stream,offset,length)},mmap(stream,length,position,prot,flags){if((prot&2)!==0&&(flags&2)===0&&(stream.flags&2097155)!==2){throw new FS.ErrnoError(2)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(2)}if(!stream.stream_ops.mmap){throw new FS.ErrnoError(43)}if(!length){throw new FS.ErrnoError(28)}return stream.stream_ops.mmap(stream,length,position,prot,flags)},msync(stream,buffer,offset,length,mmapFlags){assert(offset>=0);if(!stream.stream_ops.msync){return 0}return stream.stream_ops.msync(stream,buffer,offset,length,mmapFlags)},ioctl(stream,cmd,arg){if(!stream.stream_ops.ioctl){throw new FS.ErrnoError(59)}return stream.stream_ops.ioctl(stream,cmd,arg)},readFile(path,opts={}){opts.flags=opts.flags||0;opts.encoding=opts.encoding||"binary";if(opts.encoding!=="utf8"&&opts.encoding!=="binary"){throw new Error(`Invalid encoding type "${opts.encoding}"`)}var ret;var stream=FS.open(path,opts.flags);var stat=FS.stat(path);var length=stat.size;var buf=new Uint8Array(length);FS.read(stream,buf,0,length,0);if(opts.encoding==="utf8"){ret=UTF8ArrayToString(buf)}else if(opts.encoding==="binary"){ret=buf}FS.close(stream);return ret},writeFile(path,data,opts={}){opts.flags=opts.flags||577;var stream=FS.open(path,opts.flags,opts.mode);if(typeof data=="string"){var buf=new Uint8Array(lengthBytesUTF8(data)+1);var actualNumBytes=stringToUTF8Array(data,buf,0,buf.length);FS.write(stream,buf,0,actualNumBytes,undefined,opts.canOwn)}else if(ArrayBuffer.isView(data)){FS.write(stream,data,0,data.byteLength,undefined,opts.canOwn)}else{throw new Error("Unsupported data type")}FS.close(stream)},cwd:()=>FS.currentPath,chdir(path){var lookup=FS.lookupPath(path,{follow:true});if(lookup.node===null){throw new FS.ErrnoError(44)}if(!FS.isDir(lookup.node.mode)){throw new FS.ErrnoError(54)}var errCode=FS.nodePermissions(lookup.node,"x");if(errCode){throw new FS.ErrnoError(errCode)}FS.currentPath=lookup.path},createDefaultDirectories(){FS.mkdir("/tmp");FS.mkdir("/home");FS.mkdir("/home/web_user")},createDefaultDevices(){FS.mkdir("/dev");FS.registerDevice(FS.makedev(1,3),{read:()=>0,write:(stream,buffer,offset,length,pos)=>length});FS.mkdev("/dev/null",FS.makedev(1,3));TTY.register(FS.makedev(5,0),TTY.default_tty_ops);TTY.register(FS.makedev(6,0),TTY.default_tty1_ops);FS.mkdev("/dev/tty",FS.makedev(5,0));FS.mkdev("/dev/tty1",FS.makedev(6,0));var randomBuffer=new Uint8Array(1024),randomLeft=0;var randomByte=()=>{if(randomLeft===0){randomLeft=randomFill(randomBuffer).byteLength}return randomBuffer[--randomLeft]};FS.createDevice("/dev","random",randomByte);FS.createDevice("/dev","urandom",randomByte);FS.mkdir("/dev/shm");FS.mkdir("/dev/shm/tmp")},createSpecialDirectories(){FS.mkdir("/proc");var proc_self=FS.mkdir("/proc/self");FS.mkdir("/proc/self/fd");FS.mount({mount(){var node=FS.createNode(proc_self,"fd",16384|511,73);node.node_ops={lookup(parent,name){var fd=+name;var stream=FS.getStreamChecked(fd);var ret={parent:null,mount:{mountpoint:"fake"},node_ops:{readlink:()=>stream.path}};ret.parent=ret;return ret}};return node}},{},"/proc/self/fd")},createStandardStreams(input,output,error){if(input){FS.createDevice("/dev","stdin",input)}else{FS.symlink("/dev/tty","/dev/stdin")}if(output){FS.createDevice("/dev","stdout",null,output)}else{FS.symlink("/dev/tty","/dev/stdout")}if(error){FS.createDevice("/dev","stderr",null,error)}else{FS.symlink("/dev/tty1","/dev/stderr")}var stdin=FS.open("/dev/stdin",0);var stdout=FS.open("/dev/stdout",1);var stderr=FS.open("/dev/stderr",1);assert(stdin.fd===0,`invalid handle for stdin (${stdin.fd})`);assert(stdout.fd===1,`invalid handle for stdout (${stdout.fd})`);assert(stderr.fd===2,`invalid handle for stderr (${stderr.fd})`)},staticInit(){[44].forEach(code=>{FS.genericErrors[code]=new FS.ErrnoError(code);FS.genericErrors[code].stack=""});FS.nameTable=new Array(4096);FS.mount(MEMFS,{},"/");FS.createDefaultDirectories();FS.createDefaultDevices();FS.createSpecialDirectories();FS.filesystems={MEMFS}},init(input,output,error){assert(!FS.initialized,"FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)");FS.initialized=true;input??=Module["stdin"];output??=Module["stdout"];error??=Module["stderr"];FS.createStandardStreams(input,output,error)},quit(){FS.initialized=false;_fflush(0);for(var i=0;ithis.length-1||idx<0){return undefined}var chunkOffset=idx%this.chunkSize;var chunkNum=idx/this.chunkSize|0;return this.getter(chunkNum)[chunkOffset]}setDataGetter(getter){this.getter=getter}cacheLength(){var xhr=new XMLHttpRequest;xhr.open("HEAD",url,false);xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);var datalength=Number(xhr.getResponseHeader("Content-length"));var header;var hasByteServing=(header=xhr.getResponseHeader("Accept-Ranges"))&&header==="bytes";var usesGzip=(header=xhr.getResponseHeader("Content-Encoding"))&&header==="gzip";var chunkSize=1024*1024;if(!hasByteServing)chunkSize=datalength;var doXHR=(from,to)=>{if(from>to)throw new Error("invalid range ("+from+", "+to+") or no bytes requested!");if(to>datalength-1)throw new Error("only "+datalength+" bytes available! programmer error!");var xhr=new XMLHttpRequest;xhr.open("GET",url,false);if(datalength!==chunkSize)xhr.setRequestHeader("Range","bytes="+from+"-"+to);xhr.responseType="arraybuffer";if(xhr.overrideMimeType){xhr.overrideMimeType("text/plain; charset=x-user-defined")}xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);if(xhr.response!==undefined){return new Uint8Array(xhr.response||[])}return intArrayFromString(xhr.responseText||"",true)};var lazyArray=this;lazyArray.setDataGetter(chunkNum=>{var start=chunkNum*chunkSize;var end=(chunkNum+1)*chunkSize-1;end=Math.min(end,datalength-1);if(typeof lazyArray.chunks[chunkNum]=="undefined"){lazyArray.chunks[chunkNum]=doXHR(start,end)}if(typeof lazyArray.chunks[chunkNum]=="undefined")throw new Error("doXHR failed!");return lazyArray.chunks[chunkNum]});if(usesGzip||!datalength){chunkSize=datalength=1;datalength=this.getter(0).length;chunkSize=datalength;out("LazyFiles on gzip forces download of the whole file when length is accessed")}this._length=datalength;this._chunkSize=chunkSize;this.lengthKnown=true}get length(){if(!this.lengthKnown){this.cacheLength()}return this._length}get chunkSize(){if(!this.lengthKnown){this.cacheLength()}return this._chunkSize}}if(typeof XMLHttpRequest!="undefined"){if(!ENVIRONMENT_IS_WORKER)throw"Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc";var lazyArray=new LazyUint8Array;var properties={isDevice:false,contents:lazyArray}}else{var properties={isDevice:false,url}}var node=FS.createFile(parent,name,properties,canRead,canWrite);if(properties.contents){node.contents=properties.contents}else if(properties.url){node.contents=null;node.url=properties.url}Object.defineProperties(node,{usedBytes:{get:function(){return this.contents.length}}});var stream_ops={};var keys=Object.keys(node.stream_ops);keys.forEach(key=>{var fn=node.stream_ops[key];stream_ops[key]=(...args)=>{FS.forceLoadFile(node);return fn(...args)}});function writeChunks(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=contents.length)return 0;var size=Math.min(contents.length-position,length);assert(size>=0);if(contents.slice){for(var i=0;i{FS.forceLoadFile(node);return writeChunks(stream,buffer,offset,length,position)};stream_ops.mmap=(stream,length,position,prot,flags)=>{FS.forceLoadFile(node);var ptr=mmapAlloc(length);if(!ptr){throw new FS.ErrnoError(48)}writeChunks(stream,HEAP8,ptr,length,position);return{ptr,allocated:true}};node.stream_ops=stream_ops;return node},absolutePath(){abort("FS.absolutePath has been removed; use PATH_FS.resolve instead")},createFolder(){abort("FS.createFolder has been removed; use FS.mkdir instead")},createLink(){abort("FS.createLink has been removed; use FS.symlink instead")},joinPath(){abort("FS.joinPath has been removed; use PATH.join instead")},mmapAlloc(){abort("FS.mmapAlloc has been replaced by the top level function mmapAlloc")},standardizePath(){abort("FS.standardizePath has been removed; use PATH.normalize instead")}};var SYSCALLS={DEFAULT_POLLMASK:5,calculateAt(dirfd,path,allowEmpty){if(PATH.isAbs(path)){return path}var dir;if(dirfd===-100){dir=FS.cwd()}else{var dirstream=SYSCALLS.getStreamFromFD(dirfd);dir=dirstream.path}if(path.length==0){if(!allowEmpty){throw new FS.ErrnoError(44)}return dir}return PATH.join2(dir,path)},doStat(func,path,buf){var stat=func(path);HEAP32[buf>>2]=stat.dev;checkInt32(stat.dev);HEAP32[buf+4>>2]=stat.mode;checkInt32(stat.mode);HEAPU32[buf+8>>2]=stat.nlink;checkInt32(stat.nlink);HEAP32[buf+12>>2]=stat.uid;checkInt32(stat.uid);HEAP32[buf+16>>2]=stat.gid;checkInt32(stat.gid);HEAP32[buf+20>>2]=stat.rdev;checkInt32(stat.rdev);tempI64=[stat.size>>>0,(tempDouble=stat.size,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+24>>2]=tempI64[0],HEAP32[buf+28>>2]=tempI64[1];checkInt64(stat.size);HEAP32[buf+32>>2]=4096;checkInt32(4096);HEAP32[buf+36>>2]=stat.blocks;checkInt32(stat.blocks);var atime=stat.atime.getTime();var mtime=stat.mtime.getTime();var ctime=stat.ctime.getTime();tempI64=[Math.floor(atime/1e3)>>>0,(tempDouble=Math.floor(atime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+40>>2]=tempI64[0],HEAP32[buf+44>>2]=tempI64[1];checkInt64(Math.floor(atime/1e3));HEAPU32[buf+48>>2]=atime%1e3*1e3*1e3;checkInt32(atime%1e3*1e3*1e3);tempI64=[Math.floor(mtime/1e3)>>>0,(tempDouble=Math.floor(mtime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+56>>2]=tempI64[0],HEAP32[buf+60>>2]=tempI64[1];checkInt64(Math.floor(mtime/1e3));HEAPU32[buf+64>>2]=mtime%1e3*1e3*1e3;checkInt32(mtime%1e3*1e3*1e3);tempI64=[Math.floor(ctime/1e3)>>>0,(tempDouble=Math.floor(ctime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+72>>2]=tempI64[0],HEAP32[buf+76>>2]=tempI64[1];checkInt64(Math.floor(ctime/1e3));HEAPU32[buf+80>>2]=ctime%1e3*1e3*1e3;checkInt32(ctime%1e3*1e3*1e3);tempI64=[stat.ino>>>0,(tempDouble=stat.ino,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+88>>2]=tempI64[0],HEAP32[buf+92>>2]=tempI64[1];checkInt64(stat.ino);return 0},doMsync(addr,stream,len,flags,offset){if(!FS.isFile(stream.node.mode)){throw new FS.ErrnoError(43)}if(flags&2){return 0}var buffer=HEAPU8.slice(addr,addr+len);FS.msync(stream,buffer,offset,len,flags)},getStreamFromFD(fd){var stream=FS.getStreamChecked(fd);return stream},varargs:undefined,getStr(ptr){var ret=UTF8ToString(ptr);return ret}};function ___syscall_faccessat(dirfd,path,amode,flags){try{path=SYSCALLS.getStr(path);assert(flags===0||flags==512);path=SYSCALLS.calculateAt(dirfd,path);if(amode&~7){return-28}var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;if(!node){return-44}var perms="";if(amode&4)perms+="r";if(amode&2)perms+="w";if(amode&1)perms+="x";if(perms&&FS.nodePermissions(node,perms)){return-2}return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function syscallGetVarargI(){assert(SYSCALLS.varargs!=undefined);var ret=HEAP32[+SYSCALLS.varargs>>2];SYSCALLS.varargs+=4;return ret}var syscallGetVarargP=syscallGetVarargI;function ___syscall_fcntl64(fd,cmd,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(cmd){case 0:{var arg=syscallGetVarargI();if(arg<0){return-28}while(FS.streams[arg]){arg++}var newStream;newStream=FS.dupStream(stream,arg);return newStream.fd}case 1:case 2:return 0;case 3:return stream.flags;case 4:{var arg=syscallGetVarargI();stream.flags|=arg;return 0}case 12:{var arg=syscallGetVarargP();var offset=0;HEAP16[arg+offset>>1]=2;checkInt16(2);return 0}case 13:case 14:return 0}return-28}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_fstat64(fd,buf){try{var stream=SYSCALLS.getStreamFromFD(fd);return SYSCALLS.doStat(FS.stat,stream.path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var stringToUTF8=(str,outPtr,maxBytesToWrite)=>{assert(typeof maxBytesToWrite=="number","stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!");return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)};function ___syscall_getdents64(fd,dirp,count){try{var stream=SYSCALLS.getStreamFromFD(fd);stream.getdents||=FS.readdir(stream.path);var struct_size=280;var pos=0;var off=FS.llseek(stream,0,1);var idx=Math.floor(off/struct_size);while(idx>>0,(tempDouble=id,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[dirp+pos>>2]=tempI64[0],HEAP32[dirp+pos+4>>2]=tempI64[1];checkInt64(id);tempI64=[(idx+1)*struct_size>>>0,(tempDouble=(idx+1)*struct_size,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[dirp+pos+8>>2]=tempI64[0],HEAP32[dirp+pos+12>>2]=tempI64[1];checkInt64((idx+1)*struct_size);HEAP16[dirp+pos+16>>1]=280;checkInt16(280);HEAP8[dirp+pos+18]=type;checkInt8(type);stringToUTF8(name,dirp+pos+19,256);pos+=struct_size;idx+=1}FS.llseek(stream,idx*struct_size,0);return pos}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_ioctl(fd,op,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(op){case 21509:{if(!stream.tty)return-59;return 0}case 21505:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tcgets){var termios=stream.tty.ops.ioctl_tcgets(stream);var argp=syscallGetVarargP();HEAP32[argp>>2]=termios.c_iflag||0;checkInt32(termios.c_iflag||0);HEAP32[argp+4>>2]=termios.c_oflag||0;checkInt32(termios.c_oflag||0);HEAP32[argp+8>>2]=termios.c_cflag||0;checkInt32(termios.c_cflag||0);HEAP32[argp+12>>2]=termios.c_lflag||0;checkInt32(termios.c_lflag||0);for(var i=0;i<32;i++){HEAP8[argp+i+17]=termios.c_cc[i]||0;checkInt8(termios.c_cc[i]||0)}return 0}return 0}case 21510:case 21511:case 21512:{if(!stream.tty)return-59;return 0}case 21506:case 21507:case 21508:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tcsets){var argp=syscallGetVarargP();var c_iflag=HEAP32[argp>>2];var c_oflag=HEAP32[argp+4>>2];var c_cflag=HEAP32[argp+8>>2];var c_lflag=HEAP32[argp+12>>2];var c_cc=[];for(var i=0;i<32;i++){c_cc.push(HEAP8[argp+i+17])}return stream.tty.ops.ioctl_tcsets(stream.tty,op,{c_iflag,c_oflag,c_cflag,c_lflag,c_cc})}return 0}case 21519:{if(!stream.tty)return-59;var argp=syscallGetVarargP();HEAP32[argp>>2]=0;checkInt32(0);return 0}case 21520:{if(!stream.tty)return-59;return-28}case 21531:{var argp=syscallGetVarargP();return FS.ioctl(stream,op,argp)}case 21523:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tiocgwinsz){var winsize=stream.tty.ops.ioctl_tiocgwinsz(stream.tty);var argp=syscallGetVarargP();HEAP16[argp>>1]=winsize[0];checkInt16(winsize[0]);HEAP16[argp+2>>1]=winsize[1];checkInt16(winsize[1])}return 0}case 21524:{if(!stream.tty)return-59;return 0}case 21515:{if(!stream.tty)return-59;return 0}default:return-28}}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_lstat64(path,buf){try{path=SYSCALLS.getStr(path);return SYSCALLS.doStat(FS.lstat,path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_mkdirat(dirfd,path,mode){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);path=PATH.normalize(path);if(path[path.length-1]==="/")path=path.substr(0,path.length-1);FS.mkdir(path,mode,0);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_newfstatat(dirfd,path,buf,flags){try{path=SYSCALLS.getStr(path);var nofollow=flags&256;var allowEmpty=flags&4096;flags=flags&~6400;assert(!flags,`unknown flags in __syscall_newfstatat: ${flags}`);path=SYSCALLS.calculateAt(dirfd,path,allowEmpty);return SYSCALLS.doStat(nofollow?FS.lstat:FS.stat,path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_openat(dirfd,path,flags,varargs){SYSCALLS.varargs=varargs;try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);var mode=varargs?syscallGetVarargI():0;return FS.open(path,flags,mode).fd}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_rmdir(path){try{path=SYSCALLS.getStr(path);FS.rmdir(path);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_stat64(path,buf){try{path=SYSCALLS.getStr(path);return SYSCALLS.doStat(FS.stat,path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_unlinkat(dirfd,path,flags){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);if(flags===0){FS.unlink(path)}else if(flags===512){FS.rmdir(path)}else{abort("Invalid flags passed to unlinkat")}return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var __abort_js=()=>{abort("native code called abort()")};var nowIsMonotonic=1;var __emscripten_get_now_is_monotonic=()=>nowIsMonotonic;var __emscripten_memcpy_js=(dest,src,num)=>HEAPU8.copyWithin(dest,src,src+num);var __emscripten_runtime_keepalive_clear=()=>{noExitRuntime=false;runtimeKeepaliveCounter=0};var __emscripten_throw_longjmp=()=>{throw Infinity};var convertI32PairToI53Checked=(lo,hi)=>{assert(lo==lo>>>0||lo==(lo|0));assert(hi===(hi|0));return hi+2097152>>>0<4194305-!!lo?(lo>>>0)+hi*4294967296:NaN};function __mmap_js(len,prot,flags,fd,offset_low,offset_high,allocated,addr){var offset=convertI32PairToI53Checked(offset_low,offset_high);try{if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);var res=FS.mmap(stream,len,offset,prot,flags);var ptr=res.ptr;HEAP32[allocated>>2]=res.allocated;checkInt32(res.allocated);HEAPU32[addr>>2]=ptr;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function __munmap_js(addr,len,prot,flags,fd,offset_low,offset_high){var offset=convertI32PairToI53Checked(offset_low,offset_high);try{var stream=SYSCALLS.getStreamFromFD(fd);if(prot&2){SYSCALLS.doMsync(addr,stream,len,flags,offset)}}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var __tzset_js=(timezone,daylight,std_name,dst_name)=>{var currentYear=(new Date).getFullYear();var winter=new Date(currentYear,0,1);var summer=new Date(currentYear,6,1);var winterOffset=winter.getTimezoneOffset();var summerOffset=summer.getTimezoneOffset();var stdTimezoneOffset=Math.max(winterOffset,summerOffset);HEAPU32[timezone>>2]=stdTimezoneOffset*60;checkInt32(stdTimezoneOffset*60);HEAP32[daylight>>2]=Number(winterOffset!=summerOffset);checkInt32(Number(winterOffset!=summerOffset));var extractZone=timezoneOffset=>{var sign=timezoneOffset>=0?"-":"+";var absOffset=Math.abs(timezoneOffset);var hours=String(Math.floor(absOffset/60)).padStart(2,"0");var minutes=String(absOffset%60).padStart(2,"0");return`UTC${sign}${hours}${minutes}`};var winterName=extractZone(winterOffset);var summerName=extractZone(summerOffset);assert(winterName);assert(summerName);assert(lengthBytesUTF8(winterName)<=16,`timezone name truncated to fit in TZNAME_MAX (${winterName})`);assert(lengthBytesUTF8(summerName)<=16,`timezone name truncated to fit in TZNAME_MAX (${summerName})`);if(summerOffsetDate.now();var getHeapMax=()=>2147483648;var _emscripten_get_heap_max=()=>getHeapMax();var _emscripten_get_now=()=>performance.now();var growMemory=size=>{var b=wasmMemory.buffer;var pages=(size-b.byteLength+65535)/65536|0;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){err(`growMemory: Attempted to grow heap from ${b.byteLength} bytes to ${size} bytes, but got error: ${e}`)}};var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;assert(requestedSize>oldSize);var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){err(`Cannot enlarge memory, requested ${requestedSize} bytes, but the limit is ${maxHeapSize} bytes!`);return false}for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignMemory(Math.max(requestedSize,overGrownHeapSize),65536));var t0=_emscripten_get_now();var replacement=growMemory(newSize);var t1=_emscripten_get_now();dbg(`Heap resize call from ${oldSize} to ${newSize} took ${t1-t0} msecs. Success: ${!!replacement}`);if(replacement){return true}}err(`Failed to grow the heap from ${oldSize} bytes to ${newSize} bytes, not enough memory!`);return false};var ENV={};var getExecutableName=()=>thisProgram||"./this.program";var getEnvStrings=()=>{if(!getEnvStrings.strings){var lang=(typeof navigator=="object"&&navigator.languages&&navigator.languages[0]||"C").replace("-","_")+".UTF-8";var env={USER:"web_user",LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:lang,_:getExecutableName()};for(var x in ENV){if(ENV[x]===undefined)delete env[x];else env[x]=ENV[x]}var strings=[];for(var x in env){strings.push(`${x}=${env[x]}`)}getEnvStrings.strings=strings}return getEnvStrings.strings};var stringToAscii=(str,buffer)=>{for(var i=0;i{var bufSize=0;getEnvStrings().forEach((string,i)=>{var ptr=environ_buf+bufSize;HEAPU32[__environ+i*4>>2]=ptr;checkInt32(ptr);stringToAscii(string,ptr);bufSize+=string.length+1});return 0};var _environ_sizes_get=(penviron_count,penviron_buf_size)=>{var strings=getEnvStrings();HEAPU32[penviron_count>>2]=strings.length;checkInt32(strings.length);var bufSize=0;strings.forEach(string=>bufSize+=string.length+1);HEAPU32[penviron_buf_size>>2]=bufSize;checkInt32(bufSize);return 0};function _fd_close(fd){try{var stream=SYSCALLS.getStreamFromFD(fd);FS.close(stream);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _fd_fdstat_get(fd,pbuf){try{var rightsBase=0;var rightsInheriting=0;var flags=0;{var stream=SYSCALLS.getStreamFromFD(fd);var type=stream.tty?2:FS.isDir(stream.mode)?3:FS.isLink(stream.mode)?7:4}HEAP8[pbuf]=type;checkInt8(type);HEAP16[pbuf+2>>1]=flags;checkInt16(flags);tempI64=[rightsBase>>>0,(tempDouble=rightsBase,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[pbuf+8>>2]=tempI64[0],HEAP32[pbuf+12>>2]=tempI64[1];checkInt64(rightsBase);tempI64=[rightsInheriting>>>0,(tempDouble=rightsInheriting,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[pbuf+16>>2]=tempI64[0],HEAP32[pbuf+20>>2]=tempI64[1];checkInt64(rightsInheriting);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var doReadv=(stream,iov,iovcnt,offset)=>{var ret=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;var curr=FS.read(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr>2]=num;checkInt32(num);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){var offset=convertI32PairToI53Checked(offset_low,offset_high);try{if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);FS.llseek(stream,offset,whence);tempI64=[stream.position>>>0,(tempDouble=stream.position,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[newOffset>>2]=tempI64[0],HEAP32[newOffset+4>>2]=tempI64[1];checkInt64(stream.position);if(stream.getdents&&offset===0&&whence===0)stream.getdents=null;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var doWritev=(stream,iov,iovcnt,offset)=>{var ret=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;var curr=FS.write(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr>2]=num;checkInt32(num);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var _getentropy=(buffer,size)=>{randomFill(HEAPU8.subarray(buffer,buffer+size));return 0};var _llvm_eh_typeid_for=type=>type;var runtimeKeepaliveCounter=0;var keepRuntimeAlive=()=>noExitRuntime||runtimeKeepaliveCounter>0;var _proc_exit=code=>{EXITSTATUS=code;if(!keepRuntimeAlive()){Module["onExit"]?.(code);ABORT=true}quit_(code,new ExitStatus(code))};var getCFunc=ident=>{var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func};var writeArrayToMemory=(array,buffer)=>{assert(array.length>=0,"writeArrayToMemory array must have a length (should be an array or typed array)");HEAP8.set(array,buffer)};var stackAlloc=sz=>__emscripten_stack_alloc(sz);var stringToUTF8OnStack=str=>{var size=lengthBytesUTF8(str)+1;var ret=stackAlloc(size);stringToUTF8(str,ret,size);return ret};var ccall=(ident,returnType,argTypes,args,opts)=>{var toC={string:str=>{var ret=0;if(str!==null&&str!==undefined&&str!==0){ret=stringToUTF8OnStack(str)}return ret},array:arr=>{var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string"){return UTF8ToString(ret)}if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;assert(returnType!=="array",'Return type should not be "array".');if(args){for(var i=0;i(...args)=>ccall(ident,returnType,argTypes,args,opts);FS.createPreloadedFile=FS_createPreloadedFile;FS.staticInit();function checkIncomingModuleAPI(){ignoredModuleProp("fetchSettings")}var wasmImports={__assert_fail:___assert_fail,__call_sighandler:___call_sighandler,__cxa_begin_catch:___cxa_begin_catch,__cxa_end_catch:___cxa_end_catch,__cxa_find_matching_catch_2:___cxa_find_matching_catch_2,__cxa_find_matching_catch_3:___cxa_find_matching_catch_3,__cxa_rethrow:___cxa_rethrow,__cxa_throw:___cxa_throw,__handle_stack_overflow:___handle_stack_overflow,__resumeException:___resumeException,__syscall_faccessat:___syscall_faccessat,__syscall_fcntl64:___syscall_fcntl64,__syscall_fstat64:___syscall_fstat64,__syscall_getdents64:___syscall_getdents64,__syscall_ioctl:___syscall_ioctl,__syscall_lstat64:___syscall_lstat64,__syscall_mkdirat:___syscall_mkdirat,__syscall_newfstatat:___syscall_newfstatat,__syscall_openat:___syscall_openat,__syscall_rmdir:___syscall_rmdir,__syscall_stat64:___syscall_stat64,__syscall_unlinkat:___syscall_unlinkat,_abort_js:__abort_js,_emscripten_get_now_is_monotonic:__emscripten_get_now_is_monotonic,_emscripten_memcpy_js:__emscripten_memcpy_js,_emscripten_runtime_keepalive_clear:__emscripten_runtime_keepalive_clear,_emscripten_throw_longjmp:__emscripten_throw_longjmp,_mmap_js:__mmap_js,_munmap_js:__munmap_js,_tzset_js:__tzset_js,emscripten_date_now:_emscripten_date_now,emscripten_get_heap_max:_emscripten_get_heap_max,emscripten_get_now:_emscripten_get_now,emscripten_resize_heap:_emscripten_resize_heap,environ_get:_environ_get,environ_sizes_get:_environ_sizes_get,fd_close:_fd_close,fd_fdstat_get:_fd_fdstat_get,fd_read:_fd_read,fd_seek:_fd_seek,fd_write:_fd_write,getentropy:_getentropy,invoke_d,invoke_diii,invoke_fi,invoke_fif,invoke_fifff,invoke_fii,invoke_fiii,invoke_fiiii,invoke_fiiiiii,invoke_fiiiiiii,invoke_fij,invoke_i,invoke_idiii,invoke_ii,invoke_iif,invoke_iifi,invoke_iifii,invoke_iifiiiii,invoke_iii,invoke_iiid,invoke_iiidii,invoke_iiif,invoke_iiiffi,invoke_iiii,invoke_iiiidi,invoke_iiiiffifffffffi,invoke_iiiifiii,invoke_iiiii,invoke_iiiiif,invoke_iiiiifi,invoke_iiiiii,invoke_iiiiiifi,invoke_iiiiiififiiiififiiiiiiiiiiiiiiiiiiii,invoke_iiiiiii,invoke_iiiiiiifii,invoke_iiiiiiii,invoke_iiiiiiiii,invoke_iiiiiiiiiffi,invoke_iiiiiiiiii,invoke_iiiiiiiiiifi,invoke_iiiiiiiiiii,invoke_iiiiiiiiiiii,invoke_iiiiiiiiiiiif,invoke_iiiiiiiiiiiiiii,invoke_iiiiiiij,invoke_iiiiiij,invoke_iiiiij,invoke_iiiij,invoke_iiij,invoke_iiiji,invoke_iiijii,invoke_iiijiii,invoke_iij,invoke_iijiii,invoke_iijj,invoke_iijji,invoke_iijjiii,invoke_ij,invoke_ijjiii,invoke_j,invoke_ji,invoke_jii,invoke_jiii,invoke_jiji,invoke_v,invoke_vdiii,invoke_vi,invoke_vid,invoke_vif,invoke_vififiif,invoke_vifii,invoke_vifiiifiiiiiiiiiiiiifiiii,invoke_vii,invoke_viid,invoke_viif,invoke_viiff,invoke_viifi,invoke_viifiii,invoke_viii,invoke_viiid,invoke_viiif,invoke_viiiffii,invoke_viiiffiiii,invoke_viiifi,invoke_viiii,invoke_viiiif,invoke_viiiii,invoke_viiiiif,invoke_viiiiii,invoke_viiiiiid,invoke_viiiiiif,invoke_viiiiiifi,invoke_viiiiiifif,invoke_viiiiiifii,invoke_viiiiiii,invoke_viiiiiiidiiii,invoke_viiiiiiii,invoke_viiiiiiiif,invoke_viiiiiiiii,invoke_viiiiiiiiii,invoke_viiiiiiiiiidii,invoke_viiiiiiiiiii,invoke_viiiiiiiiiiii,invoke_viiiiiiiiiiiiii,invoke_viiiiiiiiiiiiiiii,invoke_viiiiij,invoke_viiiiiji,invoke_viiiiji,invoke_viiiijiiifi,invoke_viiij,invoke_viiiji,invoke_viiijii,invoke_viiijjji,invoke_viij,invoke_viiji,invoke_viijii,invoke_viijiiii,invoke_viijj,invoke_vij,invoke_viji,invoke_vijif,invoke_vijii,invoke_vijj,invoke_vjjiii,llvm_eh_typeid_for:_llvm_eh_typeid_for,proc_exit:_proc_exit};var wasmExports=createWasm();var ___wasm_call_ctors=createExportWrapper("__wasm_call_ctors",0);var _web_engine_create=Module["_web_engine_create"]=createExportWrapper("web_engine_create",0);var _web_engine_get_memory_stats=Module["_web_engine_get_memory_stats"]=createExportWrapper("web_engine_get_memory_stats",1);var _web_engine_destroy=Module["_web_engine_destroy"]=createExportWrapper("web_engine_destroy",1);var _fflush=createExportWrapper("fflush",1);var _web_engine_get_live_handles=Module["_web_engine_get_live_handles"]=createExportWrapper("web_engine_get_live_handles",0);var _web_engine_get_allocated_bytes=Module["_web_engine_get_allocated_bytes"]=createExportWrapper("web_engine_get_allocated_bytes",0);var _web_engine_open_blend=Module["_web_engine_open_blend"]=createExportWrapper("web_engine_open_blend",3);var _web_engine_apply_command=Module["_web_engine_apply_command"]=createExportWrapper("web_engine_apply_command",3);var _web_engine_decimate_apply=Module["_web_engine_decimate_apply"]=createExportWrapper("web_engine_decimate_apply",35);var _web_engine_append_library_object=Module["_web_engine_append_library_object"]=createExportWrapper("web_engine_append_library_object",5);var _web_engine_undo=Module["_web_engine_undo"]=createExportWrapper("web_engine_undo",1);var _web_engine_redo=Module["_web_engine_redo"]=createExportWrapper("web_engine_redo",1);var _web_engine_get_scene_snapshot=Module["_web_engine_get_scene_snapshot"]=createExportWrapper("web_engine_get_scene_snapshot",3);var _web_engine_get_scene_metadata=Module["_web_engine_get_scene_metadata"]=createExportWrapper("web_engine_get_scene_metadata",3);var _web_engine_get_scene_geometry=Module["_web_engine_get_scene_geometry"]=createExportWrapper("web_engine_get_scene_geometry",3);var _web_engine_get_scene_delta=Module["_web_engine_get_scene_delta"]=createExportWrapper("web_engine_get_scene_delta",3);var _web_engine_get_packed_asset=Module["_web_engine_get_packed_asset"]=createExportWrapper("web_engine_get_packed_asset",5);var _web_engine_evaluate_depsgraph=Module["_web_engine_evaluate_depsgraph"]=createExportWrapper("web_engine_evaluate_depsgraph",3);var _web_engine_save_blend=Module["_web_engine_save_blend"]=createExportWrapper("web_engine_save_blend",3);var _malloc=Module["_malloc"]=createExportWrapper("malloc",1);var _web_engine_free_buffer=Module["_web_engine_free_buffer"]=createExportWrapper("web_engine_free_buffer",1);var _free=Module["_free"]=createExportWrapper("free",1);var _web_engine_last_error_code=Module["_web_engine_last_error_code"]=createExportWrapper("web_engine_last_error_code",0);var _web_engine_last_error_message=Module["_web_engine_last_error_message"]=createExportWrapper("web_engine_last_error_message",0);var _strerror=createExportWrapper("strerror",1);var _emscripten_builtin_memalign=createExportWrapper("emscripten_builtin_memalign",2);var _setThrew=createExportWrapper("setThrew",2);var __emscripten_tempret_set=createExportWrapper("_emscripten_tempret_set",1);var __emscripten_tempret_get=createExportWrapper("_emscripten_tempret_get",0);var _emscripten_stack_init=()=>(_emscripten_stack_init=wasmExports["emscripten_stack_init"])();var _emscripten_stack_get_free=()=>(_emscripten_stack_get_free=wasmExports["emscripten_stack_get_free"])();var _emscripten_stack_get_base=()=>(_emscripten_stack_get_base=wasmExports["emscripten_stack_get_base"])();var _emscripten_stack_get_end=()=>(_emscripten_stack_get_end=wasmExports["emscripten_stack_get_end"])();var __emscripten_stack_restore=a0=>(__emscripten_stack_restore=wasmExports["_emscripten_stack_restore"])(a0);var __emscripten_stack_alloc=a0=>(__emscripten_stack_alloc=wasmExports["_emscripten_stack_alloc"])(a0);var _emscripten_stack_get_current=()=>(_emscripten_stack_get_current=wasmExports["emscripten_stack_get_current"])();var ___cxa_decrement_exception_refcount=createExportWrapper("__cxa_decrement_exception_refcount",1);var ___cxa_increment_exception_refcount=createExportWrapper("__cxa_increment_exception_refcount",1);var ___cxa_can_catch=createExportWrapper("__cxa_can_catch",3);var ___cxa_get_exception_ptr=createExportWrapper("__cxa_get_exception_ptr",1);var ___set_stack_limits=Module["___set_stack_limits"]=createExportWrapper("__set_stack_limits",2);var dynCall_viij=Module["dynCall_viij"]=createExportWrapper("dynCall_viij",5);var dynCall_viiji=Module["dynCall_viiji"]=createExportWrapper("dynCall_viiji",6);var dynCall_viijiiii=Module["dynCall_viijiiii"]=createExportWrapper("dynCall_viijiiii",9);var dynCall_vij=Module["dynCall_vij"]=createExportWrapper("dynCall_vij",4);var dynCall_viijii=Module["dynCall_viijii"]=createExportWrapper("dynCall_viijii",7);var dynCall_viiiijiiifi=Module["dynCall_viiiijiiifi"]=createExportWrapper("dynCall_viiiijiiifi",12);var dynCall_viiijjji=Module["dynCall_viiijjji"]=createExportWrapper("dynCall_viiijjji",11);var dynCall_viiiiji=Module["dynCall_viiiiji"]=createExportWrapper("dynCall_viiiiji",8);var dynCall_viiiji=Module["dynCall_viiiji"]=createExportWrapper("dynCall_viiiji",7);var dynCall_ij=Module["dynCall_ij"]=createExportWrapper("dynCall_ij",3);var dynCall_viji=Module["dynCall_viji"]=createExportWrapper("dynCall_viji",5);var dynCall_iij=Module["dynCall_iij"]=createExportWrapper("dynCall_iij",4);var dynCall_fij=Module["dynCall_fij"]=createExportWrapper("dynCall_fij",4);var dynCall_vijf=Module["dynCall_vijf"]=createExportWrapper("dynCall_vijf",5);var dynCall_jiii=Module["dynCall_jiii"]=createExportWrapper("dynCall_jiii",4);var dynCall_viiij=Module["dynCall_viiij"]=createExportWrapper("dynCall_viiij",6);var dynCall_iiijii=Module["dynCall_iiijii"]=createExportWrapper("dynCall_iiijii",7);var dynCall_iiijiii=Module["dynCall_iiijiii"]=createExportWrapper("dynCall_iiijiii",8);var dynCall_iiij=Module["dynCall_iiij"]=createExportWrapper("dynCall_iiij",5);var dynCall_vjjiii=Module["dynCall_vjjiii"]=createExportWrapper("dynCall_vjjiii",8);var dynCall_ijjiii=Module["dynCall_ijjiii"]=createExportWrapper("dynCall_ijjiii",8);var dynCall_iijiii=Module["dynCall_iijiii"]=createExportWrapper("dynCall_iijiii",7);var dynCall_iijjiii=Module["dynCall_iijjiii"]=createExportWrapper("dynCall_iijjiii",9);var dynCall_iiiji=Module["dynCall_iiiji"]=createExportWrapper("dynCall_iiiji",6);var dynCall_jii=Module["dynCall_jii"]=createExportWrapper("dynCall_jii",3);var dynCall_iijj=Module["dynCall_iijj"]=createExportWrapper("dynCall_iijj",6);var dynCall_vijj=Module["dynCall_vijj"]=createExportWrapper("dynCall_vijj",6);var dynCall_ji=Module["dynCall_ji"]=createExportWrapper("dynCall_ji",2);var dynCall_vijii=Module["dynCall_vijii"]=createExportWrapper("dynCall_vijii",6);var dynCall_vijif=Module["dynCall_vijif"]=createExportWrapper("dynCall_vijif",6);var dynCall_viiiiij=Module["dynCall_viiiiij"]=createExportWrapper("dynCall_viiiiij",8);var dynCall_viiiiiji=Module["dynCall_viiiiiji"]=createExportWrapper("dynCall_viiiiiji",9);var dynCall_iiiij=Module["dynCall_iiiij"]=createExportWrapper("dynCall_iiiij",6);var dynCall_iijji=Module["dynCall_iijji"]=createExportWrapper("dynCall_iijji",7);var dynCall_j=Module["dynCall_j"]=createExportWrapper("dynCall_j",1);var dynCall_iiiiiiij=Module["dynCall_iiiiiiij"]=createExportWrapper("dynCall_iiiiiiij",9);var dynCall_viijj=Module["dynCall_viijj"]=createExportWrapper("dynCall_viijj",7);var dynCall_iiiiij=Module["dynCall_iiiiij"]=createExportWrapper("dynCall_iiiiij",7);var dynCall_viiijii=Module["dynCall_viiijii"]=createExportWrapper("dynCall_viiijii",8);var dynCall_jij=Module["dynCall_jij"]=createExportWrapper("dynCall_jij",4);var dynCall_vijji=Module["dynCall_vijji"]=createExportWrapper("dynCall_vijji",7);var dynCall_iiiiiij=Module["dynCall_iiiiiij"]=createExportWrapper("dynCall_iiiiiij",8);var dynCall_jiji=Module["dynCall_jiji"]=createExportWrapper("dynCall_jiji",5);var dynCall_iiiiijj=Module["dynCall_iiiiijj"]=createExportWrapper("dynCall_iiiiijj",9);var dynCall_iiiiiijj=Module["dynCall_iiiiiijj"]=createExportWrapper("dynCall_iiiiiijj",10);function invoke_ii(index,a1){var sp=stackSave();try{return getWasmTableEntry(index)(a1)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_v(index){var sp=stackSave();try{getWasmTableEntry(index)()}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiii(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viii(index,a1,a2,a3){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiii(index,a1,a2,a3,a4){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vi(index,a1){var sp=stackSave();try{getWasmTableEntry(index)(a1)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vif(index,a1,a2){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iii(index,a1,a2){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fi(index,a1){var sp=stackSave();try{return getWasmTableEntry(index)(a1)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiif(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vii(index,a1,a2){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiii(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_i(index){var sp=stackSave();try{return getWasmTableEntry(index)()}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fiii(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_diii(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viifiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiffi(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiifii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiffifffffffi(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiifi(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiiiifi(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiififiiiififiiiiiiiiiiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,a22,a23,a24,a25,a26,a27,a28,a29,a30,a31,a32,a33,a34,a35){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,a22,a23,a24,a25,a26,a27,a28,a29,a30,a31,a32,a33,a34,a35)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vififiif(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vifii(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fiiii(index,a1,a2,a3,a4){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viif(index,a1,a2,a3){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viifi(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiif(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiif(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiif(index,a1,a2,a3,a4,a5){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fif(index,a1,a2){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiifi(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iifii(index,a1,a2,a3,a4){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fii(index,a1,a2){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fiiiiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iifi(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiif(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vdiii(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_idiii(index,a1,a2,a3,a4){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiif(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiifii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiifiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_d(index){var sp=stackSave();try{return getWasmTableEntry(index)()}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fifff(index,a1,a2,a3,a4){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiifi(index,a1,a2,a3,a4,a5){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fiiiiiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiifi(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vid(index,a1,a2){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiff(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iif(index,a1,a2){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiiiffi(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiffiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iifiiiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiifif(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiif(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vifiiifiiiiiiiiiiiiifiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,a22,a23,a24){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,a22,a23,a24)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiiiiiif(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiid(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiidiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiiiidii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiidi(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viid(index,a1,a2,a3){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiidii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiid(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiffii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiid(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fij(index,a1,a2,a3){var sp=stackSave();try{return dynCall_fij(index,a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viij(index,a1,a2,a3,a4){var sp=stackSave();try{dynCall_viij(index,a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iij(index,a1,a2,a3){var sp=stackSave();try{return dynCall_iij(index,a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_ij(index,a1,a2){var sp=stackSave();try{return dynCall_ij(index,a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vij(index,a1,a2,a3){var sp=stackSave();try{dynCall_vij(index,a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_jiii(index,a1,a2,a3){var sp=stackSave();try{return dynCall_jiii(index,a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiji(index,a1,a2,a3,a4,a5){var sp=stackSave();try{dynCall_viiji(index,a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viijiiii(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSave();try{dynCall_viijiiii(index,a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viijii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{dynCall_viijii(index,a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiijiiifi(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){var sp=stackSave();try{dynCall_viiiijiiifi(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiijjji(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){var sp=stackSave();try{dynCall_viiijjji(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiji(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{dynCall_viiiiji(index,a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiji(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{dynCall_viiiji(index,a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiij(index,a1,a2,a3,a4,a5){var sp=stackSave();try{dynCall_viiij(index,a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiijii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return dynCall_iiijii(index,a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiijiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return dynCall_iiijiii(index,a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiij(index,a1,a2,a3,a4){var sp=stackSave();try{return dynCall_iiij(index,a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viji(index,a1,a2,a3,a4){var sp=stackSave();try{dynCall_viji(index,a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vijii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{dynCall_vijii(index,a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiji(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return dynCall_iiiji(index,a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iijiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return dynCall_iijiii(index,a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iijjiii(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSave();try{return dynCall_iijjiii(index,a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vjjiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{dynCall_vjjiii(index,a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_ijjiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return dynCall_ijjiii(index,a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iijj(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return dynCall_iijj(index,a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vijj(index,a1,a2,a3,a4,a5){var sp=stackSave();try{dynCall_vijj(index,a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiij(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{dynCall_viiiiij(index,a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vijif(index,a1,a2,a3,a4,a5){var sp=stackSave();try{dynCall_vijif(index,a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiji(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSave();try{dynCall_viiiiiji(index,a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iijji(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return dynCall_iijji(index,a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viijj(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{dynCall_viijj(index,a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_ji(index,a1){var sp=stackSave();try{return dynCall_ji(index,a1)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiij(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return dynCall_iiiiij(index,a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiij(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return dynCall_iiiij(index,a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_j(index){var sp=stackSave();try{return dynCall_j(index)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiij(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSave();try{return dynCall_iiiiiiij(index,a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiijii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{dynCall_viiijii(index,a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_jii(index,a1,a2){var sp=stackSave();try{return dynCall_jii(index,a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiij(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return dynCall_iiiiiij(index,a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_jiji(index,a1,a2,a3,a4){var sp=stackSave();try{return dynCall_jiji(index,a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}Module["ccall"]=ccall;Module["cwrap"]=cwrap;Module["UTF8ToString"]=UTF8ToString;var missingLibrarySymbols=["writeI53ToI64","writeI53ToI64Clamped","writeI53ToI64Signaling","writeI53ToU64Clamped","writeI53ToU64Signaling","readI53FromI64","readI53FromU64","convertI32PairToI53","convertU32PairToI53","getTempRet0","exitJS","inetPton4","inetNtop4","inetPton6","inetNtop6","readSockaddr","writeSockaddr","emscriptenLog","readEmAsmArgs","jstoi_q","listenOnce","autoResumeAudioContext","dynCallLegacy","getDynCaller","dynCall","handleException","runtimeKeepalivePush","runtimeKeepalivePop","callUserCallback","maybeExit","asmjsMangle","HandleAllocator","getNativeTypeSize","STACK_SIZE","STACK_ALIGN","POINTER_SIZE","ASSERTIONS","uleb128Encode","sigToWasmTypes","generateFuncType","convertJsFunctionToWasm","getEmptyTableSlot","updateTableMap","getFunctionAddress","addFunction","removeFunction","reallyNegative","unSign","strLen","reSign","formatString","intArrayToString","AsciiToString","UTF16ToString","stringToUTF16","lengthBytesUTF16","UTF32ToString","stringToUTF32","lengthBytesUTF32","stringToNewUTF8","registerKeyEventCallback","maybeCStringToJsString","findEventTarget","getBoundingClientRect","fillMouseEventData","registerMouseEventCallback","registerWheelEventCallback","registerUiEventCallback","registerFocusEventCallback","fillDeviceOrientationEventData","registerDeviceOrientationEventCallback","fillDeviceMotionEventData","registerDeviceMotionEventCallback","screenOrientation","fillOrientationChangeEventData","registerOrientationChangeEventCallback","fillFullscreenChangeEventData","registerFullscreenChangeEventCallback","JSEvents_requestFullscreen","JSEvents_resizeCanvasForFullscreen","registerRestoreOldStyle","hideEverythingExceptGivenElement","restoreHiddenElements","setLetterbox","softFullscreenResizeWebGLRenderTarget","doRequestFullscreen","fillPointerlockChangeEventData","registerPointerlockChangeEventCallback","registerPointerlockErrorEventCallback","requestPointerLock","fillVisibilityChangeEventData","registerVisibilityChangeEventCallback","registerTouchEventCallback","fillGamepadEventData","registerGamepadEventCallback","registerBeforeUnloadEventCallback","fillBatteryEventData","battery","registerBatteryEventCallback","setCanvasElementSize","getCanvasElementSize","jsStackTrace","getCallstack","convertPCtoSourceLocation","checkWasiClock","wasiRightsToMuslOFlags","wasiOFlagsToMuslOFlags","createDyncallWrapper","safeSetTimeout","setImmediateWrapped","clearImmediateWrapped","polyfillSetImmediate","registerPostMainLoop","registerPreMainLoop","getPromise","makePromise","idsToPromises","makePromiseCallback","Browser_asyncPrepareDataCounter","safeRequestAnimationFrame","isLeapYear","ydayFromDate","arraySum","addDays","getSocketFromFD","getSocketAddress","FS_unlink","FS_mkdirTree","_setNetworkCallback","heapObjectForWebGLType","toTypedArrayIndex","webgl_enable_ANGLE_instanced_arrays","webgl_enable_OES_vertex_array_object","webgl_enable_WEBGL_draw_buffers","webgl_enable_WEBGL_multi_draw","webgl_enable_EXT_polygon_offset_clamp","webgl_enable_EXT_clip_control","webgl_enable_WEBGL_polygon_mode","emscriptenWebGLGet","computeUnpackAlignedImageSize","colorChannelsInGlTextureFormat","emscriptenWebGLGetTexPixelData","emscriptenWebGLGetUniform","webglGetUniformLocation","webglPrepareUniformLocationsBeforeFirstUse","webglGetLeftBracePos","emscriptenWebGLGetVertexAttrib","__glGetActiveAttribOrUniform","writeGLArray","registerWebGlEventCallback","runAndAbortIfError","ALLOC_NORMAL","ALLOC_STACK","allocate","writeStringToMemory","writeAsciiToMemory","setErrNo","demangle","stackTrace"];missingLibrarySymbols.forEach(missingLibrarySymbol);var unexportedSymbols=["run","addOnPreRun","addOnInit","addOnPreMain","addOnExit","addOnPostRun","addRunDependency","removeRunDependency","out","err","callMain","abort","wasmMemory","wasmExports","writeStackCookie","checkStackCookie","convertI32PairToI53Checked","stackSave","stackRestore","stackAlloc","setTempRet0","ptrToString","zeroMemory","getHeapMax","growMemory","ENV","setStackLimits","ERRNO_CODES","strError","DNS","Protocols","Sockets","initRandomFill","randomFill","timers","warnOnce","readEmAsmArgsArray","jstoi_s","getExecutableName","keepRuntimeAlive","asyncLoad","alignMemory","mmapAlloc","wasmTable","noExitRuntime","getCFunc","freeTableIndexes","functionsInTableMap","setValue","getValue","PATH","PATH_FS","UTF8Decoder","UTF8ArrayToString","stringToUTF8Array","stringToUTF8","lengthBytesUTF8","intArrayFromString","stringToAscii","UTF16Decoder","stringToUTF8OnStack","writeArrayToMemory","JSEvents","specialHTMLTargets","findCanvasEventTarget","currentFullscreenStrategy","restoreOldWindowedStyle","UNWIND_CACHE","ExitStatus","getEnvStrings","doReadv","doWritev","promiseMap","uncaughtExceptionCount","exceptionLast","exceptionCaught","ExceptionInfo","findMatchingCatch","Browser","getPreloadedImageData__data","wget","MONTH_DAYS_REGULAR","MONTH_DAYS_LEAP","MONTH_DAYS_REGULAR_CUMULATIVE","MONTH_DAYS_LEAP_CUMULATIVE","SYSCALLS","preloadPlugins","FS_createPreloadedFile","FS_modeStringToFlags","FS_getMode","FS_stdin_getChar_buffer","FS_stdin_getChar","FS_createPath","FS_createDevice","FS_readFile","FS","FS_createDataFile","FS_createLazyFile","MEMFS","TTY","PIPEFS","SOCKFS","tempFixedLengthArray","miniTempWebGLFloatBuffers","miniTempWebGLIntBuffers","GL","AL","GLUT","EGL","GLEW","IDBStore","SDL","SDL_gfx","allocateUTF8","allocateUTF8OnStack","print","printErr"];unexportedSymbols.forEach(unexportedRuntimeSymbol);var calledRun;var calledPrerun;dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function stackCheckInit(){_emscripten_stack_init();writeStackCookie()}function run(){if(runDependencies>0){return}stackCheckInit();if(!calledPrerun){calledPrerun=1;preRun();if(runDependencies>0){return}}function doRun(){if(calledRun)return;calledRun=1;Module["calledRun"]=1;if(ABORT)return;initRuntime();readyPromiseResolve(Module);Module["onRuntimeInitialized"]?.();assert(!Module["_main"],'compiled without a main, but one is present. if you added it from JS, use Module["onRuntimeInitialized"]');postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(()=>{setTimeout(()=>Module["setStatus"](""),1);doRun()},1)}else{doRun()}checkStackCookie()}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}run();moduleRtn=readyPromise;for(const prop of Object.keys(Module)){if(!(prop in moduleArg)){Object.defineProperty(moduleArg,prop,{configurable:true,get(){abort(`Access to module property ('${prop}') is no longer possible via the module constructor argument; Instead, use the result of the module constructor.`)}})}} return moduleRtn; diff --git a/web/app/src/vendor/blender/web_engine.wasm b/web/app/src/vendor/blender/web_engine.wasm index 258cfd4b..71539893 100644 Binary files a/web/app/src/vendor/blender/web_engine.wasm and b/web/app/src/vendor/blender/web_engine.wasm differ diff --git a/web/engine/web_engine_native_reader_stub.cpp b/web/engine/web_engine_native_reader_stub.cpp index 47fe761b..c5cab5f9 100644 --- a/web/engine/web_engine_native_reader_stub.cpp +++ b/web/engine/web_engine_native_reader_stub.cpp @@ -337,6 +337,9 @@ WEB_NATIVE_MAIN_STUB(web_engine_blend_main_geometry_node_graphs_json, WEB_NATIVE_MAIN_STUB(web_engine_blend_main_physics_simulation_json, WebBlendMainState *, std::string &) +WEB_NATIVE_MAIN_STUB(web_engine_blend_main_particle_settings_json, + WebBlendMainState *, + std::string &) WEB_NATIVE_MAIN_STUB(web_engine_blend_main_create_grease_pencil_layer, WebBlendMainState *, const char *,