Files
mes123456 c2c65d3a09
Some checks failed
M6 deployable RC / quick (push) Has been cancelled
M6 deployable RC / chromium (push) Has been cancelled
M6 deployable RC / release (push) Has been cancelled
Rebuild local Blender WASM environment and recovery evidence
2026-08-27 20:22:15 +08:00

118 lines
5.0 KiB
Python

#!/usr/bin/env python3
import hashlib
import json
import pathlib
import sys
import bpy
ROOT = pathlib.Path(__file__).resolve().parents[3]
PARITY_MAP = ROOT / "tests/golden/WBV2-P0-002/parity-map.json"
def digest_file(path):
return hashlib.sha256(path.read_bytes()).hexdigest()
def risk_score(capability):
levels = {"L0": 0, "L1": 1, "L2": 2, "L3": 3}
return (capability["legacyPending"] * 100 + capability["legacyActive"] * 50 +
capability["entryCount"] * 10 + levels[capability["targetParityLevel"]] * 1000)
def build_receipt():
parity = json.loads(PARITY_MAP.read_text(encoding="utf-8"))
if parity.get("schemaVersion") != 1 or parity.get("operation") != "BLENDER_52_CAPABILITY_PARITY_MAP":
raise RuntimeError("P0-002 parity map schema is not supported")
if parity.get("summary", {}).get("featureParityClaims") != 0 or parity["summary"].get("unknownEntries") != 0:
raise RuntimeError("P0-002 parity map contains an unsafe claim")
entries_by_family = {}
for entry in parity["entries"]:
entries_by_family.setdefault(entry["family"], []).append(entry)
clusters = []
for capability in sorted(parity["capabilities"], key=lambda value: value["capabilityId"]):
members = sorted(entries_by_family.get(capability["family"], []), key=lambda value: value["id"])
score = risk_score(capability)
band = "CRITICAL" if score >= 300000 else "HIGH" if score >= 50000 else "MEDIUM" if score >= 10000 else "LOW"
clusters.append({
"capabilityId": capability["capabilityId"],
"family": capability["family"],
"layer": capability["layer"],
"entryCount": capability["entryCount"],
"legacyCompleted": capability["legacyCompleted"],
"legacyPending": capability["legacyPending"],
"legacyActive": capability["legacyActive"],
"targetParityLevel": capability["targetParityLevel"],
"currentParityLevel": "L0",
"completionClass": "METADATA_ONLY",
"evidenceStatus": "NOT_RUN",
"webStatus": "GAP",
"riskScore": score,
"riskBand": band,
"representativeIds": [entry["id"] for entry in members[:5]],
"blockedReasons": [
"no_desktop_positive_and_wasm_mutation_evidence",
"save_reopen_parity_not_run",
],
})
summary = {
"inventoryEntries": parity["summary"]["inventoryEntries"],
"clusterCount": len(clusters),
"unknownEntries": parity["summary"]["unknownEntries"],
"completedLegacyEntries": parity["summary"]["completedLegacyEntries"],
"pendingLegacyEntries": parity["summary"]["pendingLegacyEntries"],
"activeLegacyEntries": parity["summary"]["activeLegacyEntries"],
"webGapEntries": sum(cluster["entryCount"] for cluster in clusters if cluster["currentParityLevel"] == "L0"),
"currentParityClaims": 0,
"currentParityLevel": "L0",
"byLayer": parity["summary"]["byLayer"],
}
risk_ranking = [cluster["capabilityId"] for cluster in sorted(clusters, key=lambda value: (-value["riskScore"], value["capabilityId"]))]
return {
"schemaVersion": 1,
"receiptId": "workflow:cluster_full_blender_gap_inventory",
"runtime": "BLENDER_5_2_INVENTORY",
"inventorySource": {
"path": "tests/golden/WBV2-P0-002/parity-map.json",
"sha256": digest_file(PARITY_MAP),
"entryCount": parity["summary"]["inventoryEntries"],
},
"classificationPolicy": {
"featureParityRequires": ["desktopPositive", "wasmMutation", "saveReopenExact"],
"negativeOnlyClasses": ["NEGATIVE_BOUNDARY", "UNSUPPORTED_DECLARED", "BLOCKED"],
"unprovenClass": "METADATA_ONLY",
"parityLevel": "L0",
},
"clusters": clusters,
"summary": summary,
"riskRanking": risk_ranking,
"nextTask": "WBV2-P7-002",
}
def main(output):
bpy.ops.wm.read_factory_settings(use_empty=True)
scene = bpy.context.scene
scene.name = "WBV2P7001GapInventoryScene"
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 = "WBV2P7001GapInventoryCube"
cube.data.name = "WBV2P7001GapInventoryMesh"
receipt = build_receipt()
text = bpy.data.texts.new("WBV2-P7-001-ClusterFullBlenderGapInventoryReceipt")
text.write(json.dumps(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-001.py -- OUTPUT")
main(arguments[0])