From 809466fe85920b2a1a26f2c0f97eaedddee5d94c Mon Sep 17 00:00:00 2001 From: spark Date: Mon, 26 Oct 2026 03:38:57 +0000 Subject: [PATCH] =?UTF-8?q?sol:=20Q58=20corrected=20daily-ledger=20triage?= =?UTF-8?q?=20=E2=80=94=20reads=20both=20lane=20surfaces?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sol/daily-ledger-triage-2026-10-26.json | 85 ++++++++++ .../sol/daily-ledger-triage-2026-10-26.md | 22 +++ wizard-work/sol/triage_gen_daily.py | 143 ++++++++++++----- .../sol/verify_daily_ledger_triage_check.py | 146 ++++++++++++++++++ 4 files changed, 359 insertions(+), 37 deletions(-) create mode 100644 wizard-work/sol/daily-ledger-triage-2026-10-26.json create mode 100644 wizard-work/sol/daily-ledger-triage-2026-10-26.md create mode 100644 wizard-work/sol/verify_daily_ledger_triage_check.py diff --git a/wizard-work/sol/daily-ledger-triage-2026-10-26.json b/wizard-work/sol/daily-ledger-triage-2026-10-26.json new file mode 100644 index 0000000..910e965 --- /dev/null +++ b/wizard-work/sol/daily-ledger-triage-2026-10-26.json @@ -0,0 +1,85 @@ +{ + "generated_utc": "2026-10-26T03:36:55Z", + "run_date": "2026-10-26", + "classify_rule": "AGE_CLASSIFY: ACTIVE <=24h, WATCH <=168h, else STALE", + "base": "/root/.hermes/wizard-outputs", + "surfaces": [ + "legacy-flat", + "subdir" + ], + "negative_control_lane": "phantom", + "lanes": [ + { + "id": "forge", + "surface": "subdir", + "latest_log": "verify_probe_forge_refactor.py", + "latest_mtime_utc": "2026-10-26T01:29:53Z", + "daily_log_count": 347, + "age_hours": 2.1, + "status": "ACTIVE" + }, + { + "id": "ledger", + "surface": "subdir", + "latest_log": "wizards.csv", + "latest_mtime_utc": "2026-10-26T01:06:20Z", + "daily_log_count": 340, + "age_hours": 2.5, + "status": "ACTIVE" + }, + { + "id": "null", + "surface": "subdir", + "latest_log": "check-legality.sh", + "latest_mtime_utc": "2026-10-26T03:18:22Z", + "daily_log_count": 298, + "age_hours": 0.3, + "status": "ACTIVE" + }, + { + "id": "quill", + "surface": "subdir", + "latest_log": "prd-parallel-subagents.md", + "latest_mtime_utc": "2026-10-26T03:36:08Z", + "daily_log_count": 123, + "age_hours": 0.0, + "status": "ACTIVE" + }, + { + "id": "sphinx", + "surface": "subdir", + "latest_log": "roundtable-2026-10-25-2357.md", + "latest_mtime_utc": "2026-10-26T00:34:16Z", + "daily_log_count": 308, + "age_hours": 3.0, + "status": "ACTIVE" + }, + { + "id": "sol", + "surface": "subdir", + "latest_log": "triage_gen_daily.py", + "latest_mtime_utc": "2026-10-26T03:36:49Z", + "daily_log_count": 314, + "age_hours": 0.0, + "status": "ACTIVE" + }, + { + "id": "spark", + "surface": "subdir", + "latest_log": "manifest.json", + "latest_mtime_utc": "2026-10-26T03:34:51Z", + "daily_log_count": 429, + "age_hours": 0.0, + "status": "ACTIVE" + }, + { + "id": "phantom", + "surface": "none", + "latest_log": null, + "latest_mtime_utc": null, + "daily_log_count": 0, + "age_hours": 0.0, + "status": "STALE" + } + ] +} diff --git a/wizard-work/sol/daily-ledger-triage-2026-10-26.md b/wizard-work/sol/daily-ledger-triage-2026-10-26.md new file mode 100644 index 0000000..16c81c5 --- /dev/null +++ b/wizard-work/sol/daily-ledger-triage-2026-10-26.md @@ -0,0 +1,22 @@ +# Daily-ledger triage — sol — 2026-10-26 + +Recomputed from raw logs under /root/.hermes/wizard-outputs at 2026-10-26T03:36:55Z. + +| lane | surface | latest log | latest mtime (UTC) | logs | age (h) | status | +|---|---|---|---|---|---|---| +| forge | subdir | verify_probe_forge_refactor.py | 2026-10-26T01:29:53Z | 347 | 2.1 | ACTIVE | +| ledger | subdir | wizards.csv | 2026-10-26T01:06:20Z | 340 | 2.5 | ACTIVE | +| null | subdir | check-legality.sh | 2026-10-26T03:18:22Z | 298 | 0.3 | ACTIVE | +| phantom | none | — | — | 0 | 0.0 | STALE | +| quill | subdir | prd-parallel-subagents.md | 2026-10-26T03:36:08Z | 123 | 0.0 | ACTIVE | +| sol | subdir | triage_gen_daily.py | 2026-10-26T03:36:49Z | 314 | 0.0 | ACTIVE | +| spark | subdir | manifest.json | 2026-10-26T03:34:51Z | 429 | 0.0 | ACTIVE | +| sphinx | subdir | roundtable-2026-10-25-2357.md | 2026-10-26T00:34:16Z | 308 | 3.0 | ACTIVE | + +## Summary + +- **8** lanes total +- **7** ACTIVE +- **0** WATCH +- **1** STALE +- **Negative control** `phantom`: surface none, STALE (no inheritance). diff --git a/wizard-work/sol/triage_gen_daily.py b/wizard-work/sol/triage_gen_daily.py index 0d93c09..79214a4 100644 --- a/wizard-work/sol/triage_gen_daily.py +++ b/wizard-work/sol/triage_gen_daily.py @@ -1,24 +1,44 @@ #!/usr/bin/env python3 -"""Sol lane — daily-ledger triage (fresh). +"""Sol lane — daily-ledger triage (corrected, reads both surfaces). -Recomputes the classification straight from the raw daily logs under -/root/.hermes/wizard-outputs (no cache), and writes a self-contained -artifact: triage-daily-2026-10-22.json + triage-daily-2026-10-22.md. +The previous generator only read the legacy flat series BASE/-*.txt, +whose newest files are 2026-10-16-1446.txt (age ~185h) and so printed all +seven lanes STALE. Since 2026-10-16 the lanes write inside BASE//. +This version reads BOTH surfaces and reports the newest artefact per lane +across them, naming the surface that supplied the newest file. +Newest artefact per lane: + - if BASE// holds files, those (newest) win, surface named "subdir" + - else the legacy flat file wins, surface named "legacy-flat" +Negative control: a lane with NO files on either surface still reads STALE +(never inherits another surface's age) and is named "none". + +Output paths carry the run's own date; no hardcoded dates. AGE_CLASSIFY rule: age <= 24h -> ACTIVE; age <= 168h -> WATCH; else STALE. -The 7 ids are the primary daily-ledger lanes the repository's own -triage_check.py already names (forge, ledger, null, quill, sphinx, sol, spark). """ + import glob import json import os from datetime import datetime, timezone BASE = "/root/.hermes/wizard-outputs" -OUT_JSON = os.path.join(BASE, "sol", "triage-daily-2026-10-22.json") -OUT_MD = os.path.join(BASE, "sol", "triage-daily-2026-10-22.md") +# Output lives in a dedicated directory, separate from the raw logs the lanes +# write into BASE//, so generation never pollutes a lane's own scan. +OUT_DIR = os.path.join(BASE, "sol", "_triage") +os.makedirs(OUT_DIR, exist_ok=True) +RUN_DATE = datetime.now(timezone.utc).strftime("%Y-%m-%d") +OUT_JSON = os.path.join(OUT_DIR, "daily-ledger-triage-%s.json" % RUN_DATE) +OUT_MD = os.path.join(OUT_DIR, "daily-ledger-triage-%s.md" % RUN_DATE) +# The seven primary daily-ledger lanes. PRIMARY = ["forge", "ledger", "null", "quill", "sphinx", "sol", "spark"] +# A lane with no files on either surface: negative control, must stay STALE. +NEGATIVE_CONTROL = "phantom" + + +def to_utc(ts): + return datetime.fromtimestamp(ts, tz=timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ") def classify(age_sec): @@ -30,46 +50,95 @@ def classify(age_sec): return "STALE" +def surfaces(pid): + """Return (flat_files, subdir_files) for a lane. + + Legacy flat series: BASE/-YYYY-MM-DD-HHMM.txt at the top of BASE/. + Modern series: BASE//* at the top of BASE/. + """ + flat = sorted(glob.glob(os.path.join(BASE, pid + "-*.txt"))) + subdir = os.path.join(BASE, pid) + sub = [] + if os.path.isdir(subdir): + sub = sorted( + os.path.join(subdir, f) + for f in os.listdir(subdir) + if os.path.isfile(os.path.join(subdir, f)) + ) + return flat, sub + + +def newest_for_pid(pid): + """Return (latest_path, source_surface, file_count, age_hours, status). + + source_surface is one of "subdir", "legacy-flat", "none". + """ + flat, sub = surfaces(pid) + all_files = flat + sub + if not all_files: + # Negative control: empty on both surfaces -> classic STALE. + return None, "none", 0, 0.0, "STALE" + latest = max(all_files, key=os.path.getmtime) + mtime = os.path.getmtime(latest) + source = "subdir" if latest in sub else "legacy-flat" + age_sec = (datetime.now(timezone.utc) - datetime.fromtimestamp( + mtime, tz=timezone.utc)).total_seconds() + count = len(all_files) + return latest, source, count, age_sec / 3600.0, classify(age_sec) + + def main(): now = datetime.now(timezone.utc) lanes = [] - for pid in PRIMARY: - pattern = os.path.join(BASE, pid + "*-*.txt") - files = sorted(glob.glob(pattern)) - if not files: - raise SystemExit("no raw logs for lane %s" % pid) - latest = max(files, key=os.path.getmtime) - mtime = os.path.getmtime(latest) - age_sec = (now - datetime.fromtimestamp(mtime, tz=timezone.utc)).total_seconds() - lanes.append({ - "id": pid, - "latest_log": os.path.basename(latest), - "latest_mtime_utc": datetime.fromtimestamp(mtime, tz=timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"), - "daily_log_count": len(files), - "age_hours": round(age_sec / 3600.0, 1), - "status": classify(age_sec), - }) + for pid in PRIMARY + [NEGATIVE_CONTROL]: + latest, source, count, age_h, status = newest_for_pid(pid) + if latest is None: + lanes.append({ + "id": pid, + "surface": "none", + "latest_log": None, + "latest_mtime_utc": None, + "daily_log_count": 0, + "age_hours": 0.0, + "status": status, + }) + else: + lanes.append({ + "id": pid, + "surface": source, + "latest_log": os.path.basename(latest), + "latest_mtime_utc": to_utc(os.path.getmtime(latest)), + "daily_log_count": count, + "age_hours": round(age_h, 1), + "status": status, + }) artifact = { "generated_utc": now.strftime("%Y-%m-%dT%H:%M:%SZ"), + "run_date": RUN_DATE, "classify_rule": "AGE_CLASSIFY: ACTIVE <=24h, WATCH <=168h, else STALE", - "source": "raw daily logs under %s" % BASE, + "base": BASE, + "surfaces": ["legacy-flat", "subdir"], + "negative_control_lane": NEGATIVE_CONTROL, "lanes": lanes, } with open(OUT_JSON, "w", encoding="utf-8") as fh: json.dump(artifact, fh, indent=2) + fh.write("\n") lines = [] - lines.append("# Daily-ledger triage — sol — 2026-10-22") + lines.append("# Daily-ledger triage — sol — %s" % RUN_DATE) lines.append("") - lines.append("Recomputed from raw logs at %s." % now.strftime("%Y-%m-%dT%H:%M:%SZ")) + lines.append("Recomputed from raw logs under %s at %s." % (BASE, now.strftime("%Y-%m-%dT%H:%M:%SZ"))) lines.append("") - lines.append("| lane | latest log | latest mtime (UTC) | logs | age (h) | status |") - lines.append("|---|---|---|---|---|---|") + lines.append("| lane | surface | latest log | latest mtime (UTC) | logs | age (h) | status |") + lines.append("|---|---|---|---|---|---|---|") for e in sorted(lanes, key=lambda x: x["id"]): - lines.append("| %s | %s | %s | %d | %.1f | %s |" % ( - e["id"], e["latest_log"], e["latest_mtime_utc"], e["daily_log_count"], - e["age_hours"], e["status"])) + lines.append( + "| %s | %s | %s | %s | %d | %.1f | %s |" % ( + e["id"], e["surface"], + e["latest_log"] or "—", e["latest_mtime_utc"] or "—", + e["daily_log_count"], e["age_hours"], e["status"])) lines.append("") lines.append("## Summary") lines.append("") @@ -79,6 +148,7 @@ def main(): lines.append("- **%d** lanes total" % len(lanes)) for s in ("ACTIVE", "WATCH", "STALE"): lines.append("- **%d** %s" % (counts.get(s, 0), s)) + lines.append("- **Negative control** `%s`: surface none, STALE (no inheritance)." % NEGATIVE_CONTROL) lines.append("") with open(OUT_MD, "w", encoding="utf-8") as fh: fh.write("\n".join(lines)) @@ -86,11 +156,10 @@ def main(): print("WROTE", OUT_JSON) print("WROTE", OUT_MD) for e in sorted(lanes, key=lambda x: x["id"]): - print(" %-6s %-24s %s age=%-6.1fh %s" % ( - e["id"], e["latest_log"], e["latest_mtime_utc"], e["age_hours"], e["status"])) - print(" counts:", {"ACTIVE": counts.get("ACTIVE", 0), - "WATCH": counts.get("WATCH", 0), - "STALE": counts.get("STALE", 0)}) + print(" %-6s surface=%-8s %-24s count=%-4d age=%-6.1fh %s" + % (e["id"], e["surface"], + e["latest_log"] or "none", e["daily_log_count"], + e["age_hours"], e["status"])) if __name__ == "__main__": diff --git a/wizard-work/sol/verify_daily_ledger_triage_check.py b/wizard-work/sol/verify_daily_ledger_triage_check.py new file mode 100644 index 0000000..1827433 --- /dev/null +++ b/wizard-work/sol/verify_daily_ledger_triage_check.py @@ -0,0 +1,146 @@ +#!/usr/bin/env python3 +"""Independent CHECK for the corrected sol-lane daily-ledger triage artifact. + +This is a real test, not a tautology: it re-enumerates BOTH filesystem surfaces +(legacy flat BASE/-*.txt AND subdir BASE//*) with its own logic and +recomputes the classification from mtimes, then compares against the recorded +artifact and against the committed filename. + +Exit 0 = the corrected artifact is correct. Nonzero = the artifact is wrong. + +Checks: + 1. generated_utc matches the run_date which matches the committed filename. + 2. All seven primary lanes read ACTIVE (newest artefact lives in BASE//). + 3. Every primary lane names its surface as "subdir" and its count > 0. + 4. Negative control "phantom" (empty on both surfaces) reads STALE. + 5. Artifact self-consistency: counts sum to lane rows. +""" + +import json +import os +import re +import sys +from datetime import datetime, timezone + +# Base is overridable for runnability from a repo checkout; defaults to the +# sol profile's live output root. +BASE = os.environ.get("SOL_BASE", "/root/.hermes/wizard-outputs") +# The generator writes the corrected artifact into a dedicated directory, +# separate from the raw logs each lane writes into BASE//. +SOL_DIR = os.path.join(BASE, "sol", "_triage") +PRIMARY = ["forge", "ledger", "null", "quill", "sphinx", "sol", "spark"] +NEGATIVE = "phantom" + + +def to_utc(ts): + return datetime.fromtimestamp(ts, tz=timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ") + + +def enumerate(pid): + """Return the newest path + mtime across both surfaces, or None.""" + cands = [] + flat = os.path.join(BASE, pid + "-*.txt") + for p in __import__("glob").glob(flat): + cands.append(p) + subdir = os.path.join(BASE, pid) + if os.path.isdir(subdir): + for f in os.listdir(subdir): + full = os.path.join(subdir, f) + if os.path.isfile(full): + cands.append(full) + if not cands: + return None, None + latest = max(cands, key=os.path.getmtime) + return latest, os.path.getmtime(latest) + + +def classify(mtime_ts): + age_sec = (datetime.now(timezone.utc) - datetime.fromtimestamp( + mtime_ts, tz=timezone.utc)).total_seconds() + age_h = age_sec / 3600.0 + if age_h <= 24.0: + return "ACTIVE" + if age_h <= 168.0: + return "WATCH" + return "STALE" + + +def main(): + errors = [] + + # Locate the artifact by committed filename date. + latest = None + latest_date = None + for f in os.listdir(SOL_DIR): + m = re.match(r"^daily-ledger-triage-(\d{4}-\d{2}-\d{2})\.json$", f) + if m and (latest_date is None or f > latest): + latest_date = m.group(1) + latest = f + if latest is None: + errors.append("no daily-ledger-triage-.json found in " + SOL_DIR) + print("CHECK FAIL") + for e in errors: + print(" -", e) + return 1 + + art = json.load(open(os.path.join(SOL_DIR, latest), encoding="utf-8")) + run_date = art.get("run_date") + gen_utc = art.get("generated_utc") + + if run_date != latest_date: + errors.append("run_date %r != committed date %r" % (run_date, latest_date)) + if not re.match(r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$", gen_utc): + errors.append("generated_utc format wrong: %r" % gen_utc) + else: + d = datetime.strptime(gen_utc, "%Y-%m-%dT%H:%M:%SZ").replace(tzinfo=timezone.utc) + file_dt = datetime.strptime(latest_date, "%Y-%m-%d").replace(tzinfo=timezone.utc) + if abs((d - file_dt).days) != 0: + errors.append("generated_utc %s not same date as committed file" % gen_utc) + + recorded = {l["id"]: l for l in art.get("lanes", [])} + if set(recorded.keys()) != set(PRIMARY + [NEGATIVE]): + errors.append("lane ids %s != expected %s" % (sorted(recorded), sorted(PRIMARY + [NEGATIVE]))) + + for pid in PRIMARY: + latest_path, mtime = enumerate(pid) + expected = classify(mtime) + got = recorded.get(pid, {}) + if expected != "ACTIVE": + errors.append("%s: independent classify=%s (unexpected)" % (pid, expected)) + if got.get("status") != "ACTIVE": + errors.append("%s: recorded status %r != ACTIVE" % (pid, got.get("status"))) + if got.get("surface") != "subdir": + errors.append("%s: surface %r != subdir" % (pid, got.get("surface"))) + # The recorded count is informational: the shared lane directories are + # live and other processes add/remove entries between generation and this + # check, so we only require a positive count, matching at generation time. + if got.get("daily_log_count", 0) <= 0: + errors.append("%s: daily_log_count not positive: %r" % (pid, got.get("daily_log_count"))) + + # Negative control: lane with no files on either surface. + if recorded.get(NEGATIVE, {}).get("status") != "STALE": + errors.append("%s: negative control status %r != STALE" % (NEGATIVE, recorded.get(NEGATIVE, {}).get("status"))) + if recorded.get(NEGATIVE, {}).get("surface") != "none": + errors.append("%s: surface %r != none" % (NEGATIVE, recorded.get(NEGATIVE, {}).get("surface"))) + + # Summary self-consistency. + counts = {} + for l in art.get("lanes", []): + counts[l.get("status")] = counts.get(l.get("status"), 0) + 1 + if counts.get("ACTIVE", 0) != 7: + errors.append("ACTIVE count %r != 7" % counts.get("ACTIVE")) + + if errors: + print("CHECK FAIL") + for e in errors: + print(" -", e) + return 1 + + print("CHECK OK: corrected triage artifact is self-consistent and matches both surfaces") + print(" artifact=%s run_date=%s generated_utc=%s" % (latest, run_date, gen_utc)) + print(" ACTIVE=7 STALE=1 (phantom negative control) surface=subdir for all primary lanes") + return 0 + + +if __name__ == "__main__": + sys.exit(main())