"""arm 실행 자체(transcript + stage 원장)에서 프로세스 지표를 균일 파생한다 — 하네스 ledger(old arm 엔 없음)에 의존하지 않아 3 arm 동일 잣대.""" import json import yaml def derive(transcript_path, stage_ledger_path): m = {"input-tokens": 0, "output-tokens": 0, "turns": 0, "subagent-spawns": 0, "hook-blocks": 0, "stage-retries": 0, "critique-revisions": 0, "execution-failures": 0, "artifacts-produced": 0, "wall-seconds": 0, "human-interventions": {"interactive": 0, "pre-authorized-receipts": 0}} with open(transcript_path, encoding="utf-8") as f: for line in f: line = line.strip() if not line: continue try: ev = json.loads(line) except (ValueError, TypeError): continue if not isinstance(ev, dict): continue t = ev.get("type") if t == "usage": m["input-tokens"] += ev.get("input_tokens", 0) m["output-tokens"] += ev.get("output_tokens", 0) elif t == "turn": m["turns"] += 1 elif t == "agent_spawn": m["subagent-spawns"] += 1 elif t == "hook_block": m["hook-blocks"] += 1 elif t == "human_intervention": k = "pre-authorized-receipts" if ev.get("kind") == "pre-authorized" else "interactive" m["human-interventions"][k] += 1 with open(stage_ledger_path, encoding="utf-8") as f: led = yaml.safe_load(f) or {} for s in led.get("stages", []): m["stage-retries"] += s.get("retries", 0) m["critique-revisions"] += s.get("critique-revisions", 0) m["artifacts-produced"] += len(s.get("artifacts", [])) m["wall-seconds"] += s.get("wall-seconds", 0) if s.get("exit-code", 0) != 0: m["execution-failures"] += 1 return m