#!/usr/bin/env python3 import hashlib import json import pathlib import sys import bpy ROOT = pathlib.Path(__file__).resolve().parents[3] PARENT_MANIFEST = ROOT / "tests/golden/WBV2-P7-001/manifest.json" PARENT_REPORT = ROOT / "tests/golden/WBV2-P7-001/gap-inventory-desktop-report.json" BEHAVIORS = ("desktopPositive", "wasmMutation", "saveReopenExact") def digest(path): return hashlib.sha256(path.read_bytes()).hexdigest() def task_id(capability_id, behavior): return "WBV2-P7-002-" + capability_id.removeprefix("CAP-") + "-" + behavior.upper() def build_receipt(): parent_manifest = json.loads(PARENT_MANIFEST.read_text(encoding="utf-8")) parent_report = json.loads(PARENT_REPORT.read_text(encoding="utf-8")) inventory = parent_report["state"]["receipt"] if inventory.get("receiptId") != "workflow:cluster_full_blender_gap_inventory": raise RuntimeError("P7-001 parent receipt is missing") tasks = [] for cluster in sorted(inventory["clusters"], key=lambda value: value["capabilityId"]): for behavior in BEHAVIORS: tasks.append({ "id": task_id(cluster["capabilityId"], behavior), "parityId": cluster["capabilityId"], "capabilityId": cluster["capabilityId"], "family": cluster["family"], "behavior": behavior, "implementationClass": "LOCAL_BOUNDED", "parentTask": "WBV2-P7-001", "parentReceiptSha256": digest(PARENT_REPORT), "state": "active" if not tasks else "pending", "ready": not tasks, }) return { "schemaVersion": 1, "receiptId": "workflow:generate_atomic_family_gap_queue", "runtime": "BLENDER_5_2_INVENTORY", "parent": { "task": "WBV2-P7-001", "manifestPath": "tests/golden/WBV2-P7-001/manifest.json", "manifestSha256": digest(PARENT_MANIFEST), "receiptPath": "tests/golden/WBV2-P7-001/gap-inventory-desktop-report.json", "receiptSha256": digest(PARENT_REPORT), }, "queue": { "activeTaskId": tasks[0]["id"], "activeCount": 1, "plannedCount": len(tasks) - 1, "ordering": "capabilityId_asc_then_behavior_order", "behaviors": list(BEHAVIORS), "implementationClasses": ["LOCAL_BOUNDED"], }, "tasks": tasks, "nextTask": "WBV2-P7-003", } def main(output): bpy.ops.wm.read_factory_settings(use_empty=True) scene = bpy.context.scene scene.name = "WBV2P7002AtomicGapQueueScene" scene.render.engine = "BLENDER_EEVEE" scene.render.resolution_x = 32 scene.render.resolution_y = 32 scene.render.resolution_percentage = 100 bpy.ops.mesh.primitive_cube_add(size=2) cube = bpy.context.object cube.name = "WBV2P7002AtomicGapQueueCube" cube.data.name = "WBV2P7002AtomicGapQueueMesh" text = bpy.data.texts.new("WBV2-P7-002-AtomicFamilyGapQueueReceipt") text.write(json.dumps(build_receipt(), sort_keys=True, separators=(",", ":"))) scene.frame_set(1) bpy.ops.wm.save_as_mainfile(filepath=str(pathlib.Path(output).resolve()), check_existing=False, compress=True) if __name__ == "__main__": arguments = sys.argv[sys.argv.index("--") + 1 :] if len(arguments) != 1: raise SystemExit("usage: blender -b --factory-startup --python WBV2-P7-002.py -- OUTPUT") main(arguments[0])