feat(web): close unattended operator batch loop
This commit is contained in:
@@ -435,6 +435,19 @@ PREFERRED_BATCHES = [
|
||||
},
|
||||
]
|
||||
|
||||
# Source-backed operator recipes are the unattended fallback once the finite
|
||||
# preferred list is exhausted. Every recipe points at an existing native
|
||||
# command gate and fixture; no recipe is allowed to infer coverage from a
|
||||
# source filename alone.
|
||||
AUTO_OPERATOR_RECIPES = [
|
||||
{"moduleId": "OBJECT_LOCATION_CLEAR_OPERATOR_BATCH", "title": "verify object location clear operator through native Main", "owner": "OBJECT", "identifier": "OBJECT_OT_location_clear", "fixture": "tests/files/web/basic_scene.blend", "test": "web/tests/e2e/wbv2-object-transform-clear-batch-production.spec.ts", "production": "tests/golden/{task}/object-transform-clear-production.json", "operation": "LOCATION"},
|
||||
{"moduleId": "OBJECT_ROTATION_CLEAR_OPERATOR_BATCH", "title": "verify object rotation clear operator through native Main", "owner": "OBJECT", "identifier": "OBJECT_OT_rotation_clear", "fixture": "tests/files/web/basic_scene.blend", "test": "web/tests/e2e/wbv2-object-transform-clear-batch-production.spec.ts", "production": "tests/golden/{task}/object-transform-clear-production.json", "operation": "ROTATION"},
|
||||
{"moduleId": "OBJECT_SCALE_CLEAR_OPERATOR_BATCH", "title": "verify object scale clear operator through native Main", "owner": "OBJECT", "identifier": "OBJECT_OT_scale_clear", "fixture": "tests/files/web/basic_scene.blend", "test": "web/tests/e2e/wbv2-object-transform-clear-batch-production.spec.ts", "production": "tests/golden/{task}/object-transform-clear-production.json", "operation": "SCALE"},
|
||||
{"moduleId": "MESH_EXTRUDE_OPERATOR_BATCH", "title": "verify mesh extrude operator through native Main", "owner": "MESH", "identifier": "MESH_OT_extrude_region", "fixture": "tests/files/web/generated/WBV2-P2-003-MESH.EDIT_CORE.blend", "test": "web/tests/e2e/wbv2-mesh-topology-production.spec.ts", "production": "tests/golden/{task}/mesh-topology-production.json", "operation": "EXTRUDE"},
|
||||
{"moduleId": "MESH_DISSOLVE_OPERATOR_BATCH", "title": "verify mesh dissolve operator through native Main", "owner": "MESH", "identifier": "MESH_OT_dissolve_edges", "fixture": "tests/files/web/generated/WBV2-P2-003-MESH.EDIT_CORE.blend", "test": "web/tests/e2e/wbv2-mesh-topology-production.spec.ts", "production": "tests/golden/{task}/mesh-topology-production.json", "operation": "DISSOLVE"},
|
||||
{"moduleId": "MESH_MERGE_OPERATOR_BATCH", "title": "verify mesh merge operator through native Main", "owner": "MESH", "identifier": "MESH_OT_merge", "fixture": "tests/files/web/generated/WBV2-P2-003-MESH.EDIT_CORE.blend", "test": "web/tests/e2e/wbv2-mesh-topology-production.spec.ts", "production": "tests/golden/{task}/mesh-topology-production.json", "operation": "MERGE"},
|
||||
]
|
||||
|
||||
|
||||
def sha(path: Path) -> str:
|
||||
return hashlib.sha256(path.read_bytes()).hexdigest()
|
||||
@@ -1040,6 +1053,30 @@ def select_batch(inventory: dict) -> dict:
|
||||
shader = native_shader_batch(inventory)
|
||||
if shader:
|
||||
return shader
|
||||
for recipe in AUTO_OPERATOR_RECIPES:
|
||||
unit = units.get(recipe["identifier"])
|
||||
if unit and unit.get("coverageStatus") != "VERIFIED" and (ROOT / recipe["fixture"]).is_file() and (ROOT / recipe["test"]).is_file():
|
||||
return {
|
||||
"moduleId": recipe["moduleId"],
|
||||
"title": recipe["title"],
|
||||
"owner": recipe["owner"],
|
||||
"identifiers": [recipe["identifier"]],
|
||||
"rna": [],
|
||||
"fixture": recipe["fixture"],
|
||||
"test": recipe["test"],
|
||||
"production": recipe["production"],
|
||||
"types": [],
|
||||
"batchOperation": recipe["operation"],
|
||||
"clearMode": recipe.get("operation"),
|
||||
"units": [unit],
|
||||
"candidateUnits": [unit],
|
||||
"adaptiveKey": f"{recipe['moduleId']}:LOCAL_EXACT:{recipe['owner']}",
|
||||
"adaptiveHistory": [],
|
||||
"adaptiveCurrentSize": 1,
|
||||
"adaptiveNextSize": 1,
|
||||
"adaptiveMinSize": 1,
|
||||
"adaptiveMaxSize": 1,
|
||||
}
|
||||
summary = pending_summary(inventory)
|
||||
write_planner_status({
|
||||
"status": "waiting_for_exact_evidence",
|
||||
@@ -1137,6 +1174,7 @@ def main() -> int:
|
||||
fixture_env = f"WBV2_BATCH_FIXTURE={batch['fixture']}"
|
||||
production_env = f"WBV2_BATCH_PRODUCTION={batch['production'].format(task=module_task)}"
|
||||
operation_env = f"WBV2_BATCH_OPERATION={batch['batchOperation']}" if batch.get("batchOperation") else ""
|
||||
clear_mode_env = f"WBV2_BATCH_CLEAR_MODE={batch['clearMode']}" if batch.get("clearMode") else ""
|
||||
if batch.get("dependencyReuse"):
|
||||
commands = [f"node tools/web/reuse-wbv2-source-dependencies.mjs --task {module_task} --write"]
|
||||
else:
|
||||
@@ -1144,7 +1182,7 @@ def main() -> int:
|
||||
"source tools/web/emscripten-env.sh && cmake --build build_web_blender6 --target web_engine -- -j8 && cp build_web_blender6/bin/web_engine.wasm web/app/src/vendor/blender/web_engine.wasm && cp build_web_blender6/bin/web_engine.wasm web/app/public/vendor/blender/web_engine.wasm && node tools/web/split-wbv2-wasm.mjs --input web/app/public/vendor/blender/web_engine.wasm --output-dir web/app/public/vendor/blender/modules/single --split-funcs web_engine_get_live_handles && node tools/web/split-wbv2-wasm.mjs --input web/app/public/vendor/blender/pthread/web_engine.wasm --output-dir web/app/public/vendor/blender/modules/pthread --split-funcs web_engine_get_live_handles",
|
||||
"npm --prefix web run typecheck",
|
||||
"npm --prefix web run build",
|
||||
f"WBV2_BATCH_TASK={module_task} {production_env} {fixture_env} {operation_env} WBV2_BATCH_TYPES='{batch_types}' WBV2_BATCH_UNITS='{batch_units}' WEB_TEST_PORT=5371 npm --prefix web run test:e2e -- --workers=1 tests/e2e/{Path(batch['test']).name}",
|
||||
f"WBV2_BATCH_TASK={module_task} {production_env} {fixture_env} {operation_env} {clear_mode_env} WBV2_BATCH_TYPES='{batch_types}' WBV2_BATCH_UNITS='{batch_units}' WEB_TEST_PORT=5371 npm --prefix web run test:e2e -- --workers=1 tests/e2e/{Path(batch['test']).name}",
|
||||
]
|
||||
root_record = {"id": root_task, "phase": str(phase), "title": "authorize_modifier_reader_batch", "kind": "enabling", "owner": "PROGRAM", "dependsOn": [current], "parityId": None, "implementationClass": "QUEUE_ONLY", "parallelGroup": f"module-root-{phase}", "gate": "MODULE", "card": f"docs/tasks/{root_task}.md", "behavior": "Authorize one shared source-backed modifier reader batch.", "outputs": ["successor authorization", "module plan", "manifest", "status"], "acceptance": ["prior evidence remains hash-bound", "batch source mapping is explicit", "inventory remains source-derived"], "commands": ["node tools/web/check-execution-control-plane.mjs"], "status": "done", "ready": False, "queueMutationAllowed": True}
|
||||
module_record = {"id": module_task, "phase": str(phase), "title": batch["title"], "kind": "module", "owner": batch["owner"], "dependsOn": [root_task], "parityId": batch["moduleId"], "implementationClass": "LOCAL_EXACT", "parallelGroup": f"module-{batch['moduleId'].lower()}", "gate": "MODULE", "card": f"docs/tasks/{module_task}.md", "behavior": f"Verify the {batch['moduleId']} batch through Blender Main, WASM and Chromium recovery.", "outputs": ["aggregate module receipt", "coverage bindings", "manifest", "status"], "acceptance": ["source and protocol hashes are bound", "every selected Main reader type is proven", "negative no-mutation and recovery are proven", "Chromium and save/reopen evidence are exact"], "status": "in_progress", "ready": True, "queueMutationAllowed": True, "batchId": contract["batchId"], "selectedRecordIds": contract["selectedRecordIds"], "module": {"moduleId": batch["moduleId"], "batchId": contract["batchId"], "selectedRecordIds": contract["selectedRecordIds"], "sourceBacked": True, "capabilities": [f"CAP-{batch['moduleId']}-READER", f"CAP-{batch['moduleId']}-RECOVERY", f"CAP-{batch['moduleId']}-FAIL-CLOSED"], "sourcePaths": source_paths, "reuseReceipts": batch.get("reuseReceipts", [{"manifest": "tests/golden/WBV2-P1107-000/manifest.json", "report": "tests/golden/WBV2-P1107-000/module-receipt.json"}]), "dependencyReuse": batch.get("dependencyReuse", []), "positive": [f"{name} type is read from Blender Main" for name in batch["identifiers"]] + ["shared RNA metadata is preserved", "save/reopen preserves the batch metadata"], "negative": ["malformed blend is rejected without Main mutation", "unsupported batch data fails closed", "non-finite metadata is not synthesized"], "recovery": ["save/reopen", "worker termination", "deterministic second read"], "commands": commands, "fullFamilyParity": False, "evidencePaths": [batch["production"].format(task=module_task)], "coverageBindings": contract["selectedRecordIds"]}}
|
||||
|
||||
Reference in New Issue
Block a user