#!/usr/bin/env python3 """Read-only WBV2 migration progress dashboard. The dashboard deliberately separates implementation, build, and verification; build receipts never count as completed business behavior. """ from __future__ import annotations import argparse, json, re from pathlib import Path ROOT = Path(__file__).resolve().parents[1] def read(path, default=None): try: return json.loads((ROOT / path).read_text(encoding="utf-8")) except (OSError, json.JSONDecodeError): return default def snapshot(): queue = (ROOT / "docs/EXECUTION_QUEUE.md").read_text(encoding="utf-8") task = re.search(r"\| 当前任务 \| `([^`]+)`", queue) parent = re.search(r"\| parent manifest \| `([^`]+)`", queue) backlog = read("tests/golden/WBV2/web-product-backlog.json", {}) or {} state = read("tests/golden/WBV2/autopilot/state.json", {}) or {} assignments = read("tests/golden/WBV2/autopilot/local-task-assignments.json", {}) or {} jobs = state.get("jobs", {}) tasks = backlog.get("tasks", []) counts = {} for item in tasks: counts[item.get("status", "unknown")] = counts.get(item.get("status", "unknown"), 0) + 1 needs = [a for a in assignments.get("assignments", []) if a.get("state") == "needs_implementation"] builds = {k: v for k, v in jobs.items() if v.get("state") == "built_pending_verification"} verified = [k for k, v in jobs.items() if v.get("state") == "verified"] return {"task": task.group(1) if task else None, "parentManifest": parent.group(1) if parent else None, "runner": {"state": state.get("state"), "pid": state.get("pid"), "activeJob": state.get("activeJob"), "verificationTiming": state.get("verificationTiming")}, "backlog": {"total": len(tasks), "byStatus": counts, "needsImplementation": [x.get("id") for x in tasks if x.get("status") == "pending"]}, "business": {"needsImplementation": [x.get("job") for x in needs], "readyForValidation": len(builds), "verified": verified}, "builds": {"pendingVerification": sorted(builds), "stale": sum(1 for v in jobs.values() if v.get("state") == "stale")}, "recommendations": [f"实现并绑定: {x.get('job')}" for x in needs] or ["没有新的本地实现缺口;由代理优先完成自动验证"]} def main(): parser = argparse.ArgumentParser(description="查看 Blender Web 移植真实进度") parser.add_argument("--json", action="store_true", help="输出机器可读 JSON") args = parser.parse_args() data = snapshot() if args.json: print(json.dumps(data, ensure_ascii=False, indent=2)); return print(f"WBV2 task: {data['task']} parent: {data['parentManifest']}") print(f"Runner: {data['runner']['state']} pid={data['runner']['pid']} active={data['runner']['activeJob'] or '-'} verification={data['runner']['verificationTiming']}") print("Backlog: " + ", ".join(f"{k}={v}" for k, v in sorted(data['backlog']['byStatus'].items())) + f" total={data['backlog']['total']}") print(f"Business: needs_implementation={len(data['business']['needsImplementation'])} ready_for_validation={data['business']['readyForValidation']} verified={len(data['business']['verified'])}") print(f"Builds: pending_verification={len(data['builds']['pendingVerification'])} stale={data['builds']['stale']}") for item in data["recommendations"]: print(f"Next: {item}") if __name__ == "__main__": main()