54 lines
3.4 KiB
Python
54 lines
3.4 KiB
Python
#!/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()
|