import json, os, glob, datetime BASE = "/root/.hermes/wizard-outputs" LANES = ["forge", "ledger", "null", "quill", "sphinx", "sol", "spark"] OUT = "/root/.hermes/wizard-outputs/sol" def classify(age_h): if age_h <= 24.0: return "ACTIVE" if age_h <= 168.0: return "WATCH" return "STALE" now = datetime.datetime.now(datetime.timezone.utc) lanes = [] counts = {} for pid in LANES: pat = os.path.join(BASE, pid + "-*.txt") files = glob.glob(pat) if not files: raise SystemExit("NO LOGS for lane: " + pid) latest = max(files, key=os.path.getmtime) mt = os.path.getmtime(latest) mtime_utc = datetime.datetime.fromtimestamp(mt, tz=datetime.timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ") age_h = (now - datetime.datetime.fromtimestamp(mt, tz=datetime.timezone.utc)).total_seconds() / 3600.0 status = classify(age_h) lanes.append({ "id": pid, "latest_log": os.path.basename(latest), "latest_mtime_utc": mtime_utc, "age_h": round(age_h, 2), "status": status, }) counts[status] = counts.get(status, 0) + 1 record = { "artifact": "sol-lane-status-2026-10-27.json", "source": "daily ledger logs under /root/.hermes/wizard-outputs/-*.txt (latest by mtime)", "measured_at_utc": now.strftime("%Y-%m-%dT%H:%M:%SZ"), "status_rule": "ACTIVE = latest log within 24h; WATCH = 24h-168h; STALE = >168h", "lanes": lanes, "status_counts": counts, } with open(os.path.join(OUT, "sol-lane-status-2026-10-27.json"), "w") as f: json.dump(record, f, indent=2) f.write("\n") # Written result (plain-text triage verdict). lines = ["# Sol Daily-Lane Status - 2026-10-27 (measured)", ""] lines.append("Classification measured live from the on-disk mtimes of each primary lane's daily ledger logs under /root/.hermes/wizard-outputs/.") lines.append("Rules: ACTIVE = latest log within 24h; WATCH = 24h-168h; STALE = >168h.") lines.append("") lines.append("## Verdict") lines.append("") lines.append("- status_counts: %s" % json.dumps(counts)) lines.append("") lines.append("## Per-lane table") lines.append("") lines.append("| Lane | Latest daily log | Last written (UTC) | Age (h) | Status |") lines.append("|-------|------------------|--------------------|---------|--------|") for ln in lanes: lines.append("| %s | %s | %s | %.2f | %s |" % (ln["id"], ln["latest_log"], ln["latest_mtime_utc"], ln["age_h"], ln["status"])) lines.append("") with open(os.path.join(OUT, "sol-lane-status-2026-10-27.md"), "w") as f: f.write("\n".join(lines)) print("measured_at_utc:", record["measured_at_utc"]) print("status_counts:", json.dumps(counts)) print("lanes:") for ln in lanes: print(" ", ln["id"], ln["latest_log"], ln["latest_mtime_utc"], "age=%.2f" % ln["age_h"], "->", ln["status"])