diff --git a/wizard-work/sol/fleet-state-triage-2026-11-05.json b/wizard-work/sol/fleet-state-triage-2026-11-05.json new file mode 100644 index 0000000..8ee04c6 --- /dev/null +++ b/wizard-work/sol/fleet-state-triage-2026-11-05.json @@ -0,0 +1,122 @@ +{ + "fleet": "cron", + "source": "/root/.hermes/cron/jobs.json", + "total": 103, + "classes": { + "attention_delivery": 1, + "attention_error": 14, + "attention_unknown": 1, + "completed": 5, + "paused": 51, + "scheduled": 31 + }, + "attention_total": 16, + "attention_jobs": [ + { + "id": "e61f5ce71d8b", + "name": "Hourly Ops Pulse", + "state": "paused", + "last_status": "error" + }, + { + "id": "cd8a31f5ff9f", + "name": "Evaluate every new Pi harness release", + "state": "paused", + "last_status": "error" + }, + { + "id": "e267b564eb2d", + "name": "Stackchain Lab Daily Drop \u2014 Candidate Correction Pass", + "state": "paused", + "last_status": "error" + }, + { + "id": "a348cb59a0c1", + "name": "Forge Human Value Brief \u2014 Top Repositories", + "state": "paused", + "last_status": "error" + }, + { + "id": "a9226ea81409", + "name": "Sovereign Signal \u2014 Independent Film Retrospective", + "state": "paused", + "last_status": null + }, + { + "id": "fee83aa9ed16", + "name": "[bot:timmy] Stackchain forge change triage", + "state": "paused", + "last_status": "delivery_failed" + }, + { + "id": "cfb73a4cf7ad", + "name": "Repertoire \u2014 14:00 Sovereign Media Studio", + "state": "paused", + "last_status": "error" + }, + { + "id": "ccd3a4141f52", + "name": "Repertoire \u2014 19:30 Visual Product Studio", + "state": "paused", + "last_status": "error" + }, + { + "id": "6cf100cea5f5", + "name": "Email digest (pre-6am)", + "state": "scheduled", + "last_status": "error" + }, + { + "id": "6a5db2fe8231", + "name": "Dream cycle 02 (10:30pm)", + "state": "paused", + "last_status": "error" + }, + { + "id": "01442c7c6acc", + "name": "Dream cycle 04 (1:30am)", + "state": "paused", + "last_status": "error" + }, + { + "id": "1d1cfcd3542b", + "name": "Dream cycle 05 (3am)", + "state": "paused", + "last_status": "error" + }, + { + "id": "b6cb8c490e9f", + "name": "Volt workhorse (every 2h)", + "state": "scheduled", + "last_status": "error" + }, + { + "id": "1ae8f67df4c8", + "name": "Beam Foundry (every 2h)", + "state": "paused", + "last_status": "error" + }, + { + "id": "3ac2f4a3f546", + "name": "X follows pitch monitor", + "state": "scheduled", + "last_status": "error" + }, + { + "id": "b5e9b0fd4f4f", + "name": "TM spectator commentary", + "state": "paused", + "last_status": "error" + } + ], + "class_decisions": { + "attention_error": "investigate last_error; stop delivery; do not re-run until root cause is cleared", + "attention_delivery": "fix delivery target; re-attempt dispatch", + "attention_unknown": "last_status missing; confirm the job ran ok", + "paused": "resume or confirm hold with an operator", + "scheduled": "healthy scheduled run; no action", + "completed": "archive the finished run", + "unknown": "unclassifiable; escalate" + }, + "generated_at": "2026-11-05T13:51:31.419305+00:00" +} \ No newline at end of file diff --git a/wizard-work/sol/fleet-state-triage-2026-11-05.md b/wizard-work/sol/fleet-state-triage-2026-11-05.md new file mode 100644 index 0000000..6c6a30a --- /dev/null +++ b/wizard-work/sol/fleet-state-triage-2026-11-05.md @@ -0,0 +1,33 @@ +# Cron Fleet State Triage 2026-11-05 + +Classification of every cron job in `jobs.json`. + +| Class | Count | Decision | +|---|---|---| +| attention_delivery | 1 | fix delivery target; re-attempt dispatch | +| attention_error | 14 | investigate last_error; stop delivery; do not re-run until root cause is cleared | +| attention_unknown | 1 | last_status missing; confirm the job ran ok | +| completed | 5 | archive the finished run | +| paused | 51 | resume or confirm hold with an operator | +| scheduled | 31 | healthy scheduled run; no action | + +Attention jobs (need sign-off): 16 of 103 + +| id | name | state | last_status | +|---|---|---|---| +| e61f5ce71d8b | Hourly Ops Pulse | paused | error | +| cd8a31f5ff9f | Evaluate every new Pi harness release | paused | error | +| e267b564eb2d | Stackchain Lab Daily Drop — Candidate Correction Pass | paused | error | +| a348cb59a0c1 | Forge Human Value Brief — Top Repositories | paused | error | +| a9226ea81409 | Sovereign Signal — Independent Film Retrospective | paused | None | +| fee83aa9ed16 | [bot:timmy] Stackchain forge change triage | paused | delivery_failed | +| cfb73a4cf7ad | Repertoire — 14:00 Sovereign Media Studio | paused | error | +| ccd3a4141f52 | Repertoire — 19:30 Visual Product Studio | paused | error | +| 6cf100cea5f5 | Email digest (pre-6am) | scheduled | error | +| 6a5db2fe8231 | Dream cycle 02 (10:30pm) | paused | error | +| 01442c7c6acc | Dream cycle 04 (1:30am) | paused | error | +| 1d1cfcd3542b | Dream cycle 05 (3am) | paused | error | +| b6cb8c490e9f | Volt workhorse (every 2h) | scheduled | error | +| 1ae8f67df4c8 | Beam Foundry (every 2h) | paused | error | +| 3ac2f4a3f546 | X follows pitch monitor | scheduled | error | +| b5e9b0fd4f4f | TM spectator commentary | paused | error | diff --git a/wizard-work/sol/verify_fleet_state_triage_2026_11_05.py b/wizard-work/sol/verify_fleet_state_triage_2026_11_05.py new file mode 100755 index 0000000..aaab089 --- /dev/null +++ b/wizard-work/sol/verify_fleet_state_triage_2026_11_05.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python3 +"""Independent verifier for fleet-state-triage-2026-11-05.json. + +Re-reads /root/.hermes/cron/jobs.json and re-derives every job's operational +class with the priority rule (a copy of the generator's rule, not an import). +Diffs the rollup against the committed artifact. Exit 0 iff identical. +""" +import json +import sys +from collections import Counter + +REPO = "/root/troupe-standup" +ART_PATH = REPO + "/wizard-work/sol/fleet-state-triage-2026-11-05.json" +SRC = "/root/.hermes/cron/jobs.json" + +DECISIONS = { + "attention_error": "investigate last_error; do not re-run until root cause is cleared", + "attention_delivery": "fix delivery target; re-attempt dispatch", + "attention_unknown": "last_status missing; confirm the job ran ok", + "paused": "resume or confirm hold with an operator", + "scheduled": "healthy scheduled run; no action", + "completed": "archive the finished run", +} + +def classify(job): + ls = job.get("last_status") + st = job.get("state") + if ls == "error": + return "attention_error" + if ls == "delivery_failed": + return "attention_delivery" + if ls is None: + return "attention_unknown" + if st == "paused": + return "paused" + if st == "scheduled": + return "scheduled" + if st == "completed": + return "completed" + return "unknown" + +def main(): + try: + art = json.load(open(ART_PATH, encoding="utf-8")) + except Exception as exc: + print("FAIL: cannot read artifact %s: %s" % (ART_PATH, exc)) + return 1 + try: + jobs = json.load(open(SRC, encoding="utf-8"))["jobs"] + except Exception as exc: + print("FAIL: cannot read source %s: %s" % (SRC, exc)) + return 1 + + expected_classes = Counter() + expected_attention = [] + for j in jobs: + c = classify(j) + expected_classes[c] += 1 + if c.startswith("attention"): + expected_attention.append({"id": j.get("id"), "name": j.get("name"), + "state": j.get("state"), "last_status": j.get("last_status")}) + + problems = [] + + # 1. headline numbers + if art.get("total") != len(jobs): + problems.append("total %r != %d" % (art.get("total"), len(jobs))) + if art.get("attention_total") != len(expected_attention): + problems.append("attention_total %r != %d" % (art.get("attention_total"), len(expected_attention))) + + # 2. class rollup + exp = {k: int(v) for k, v in sorted(expected_classes.items())} + if art.get("classes") != exp: + problems.append("classes rolled up %r != %r" % (art.get("classes"), exp)) + + # 3. attention job ids (sorted, set-equal) + got_ids = sorted(i.get("id") for i in art.get("attention_jobs", [])) + exp_ids = sorted(i["id"] for i in expected_attention) + if got_ids != exp_ids: + problems.append("attention job ids differ: %r != %r" % (got_ids, exp_ids)) + + # 4. artifact mentions the source and decisions map + if art.get("source") != SRC: + problems.append("source field mismatch") + if not isinstance(art.get("class_decisions"), dict) or not art["class_decisions"]: + problems.append("class_decisions missing/empty") + + if problems: + print("FAIL: %d problem(s)" % len(problems)) + for p in problems: + print(" -", p) + return 1 + + print("PASS: artifact re-derives %d jobs; classes=%s; attention=%d" % (len(jobs), exp, len(expected_attention))) + return 0 + +if __name__ == "__main__": + sys.exit(main())