Files

111 lines
3.6 KiB
Python

#!/usr/bin/env python3
"""Solo verification for the cron-fleet triage artifact in this repo.
Exits 0 only if the artifact in THIS directory matches counts independently
recomputed from the live /root/.hermes/cron/jobs.json (source of truth).
"""
import json
import os
import subprocess
import sys
import datetime
HERE = os.path.dirname(os.path.abspath(__file__))
REPO = os.path.dirname(os.path.dirname(HERE))
JOBS = '/root/.hermes/wizard-outputs/sol/cron-fleet-jobs-snapshot-2026-10-22.json'
OUT = os.path.join(HERE, 'cron-fleet-triage-2026-10-22.json')
MD = os.path.join(HERE, 'cron-fleet-triage-2026-10-22.md')
SNAPSHOT = JOBS
try:
_ref = json.load(open(OUT)).get('classification_at')
_ref_dt = datetime.datetime.fromisoformat(_ref) if _ref else None
except Exception:
_ref_dt = None
data = json.load(open(JOBS))
jobs = data['jobs']
# Reference clock for the live/overdue boundary is pinned to the generation time
# recorded in the artifact (a moving wall clock would flip borders mid-check).
ref = _ref_dt
def parse_dt(s):
try:
return __import__('datetime').datetime.fromisoformat(s.strip())
except Exception:
return None
# Independent recomputation from the live source.
tiers = {'live': 0, 'overdue': 0, 'paused': 0, 'never': 0}
enabled = deliver = fire_claim = 0
for r in jobs:
en = bool(r.get('enabled'))
paused = r.get('state') == 'paused' or bool(r.get('paused_at'))
nr = parse_dt(r.get('next_run_at'))
if paused:
tiers['paused'] += 1
elif nr is None:
tiers['never'] += 1
elif nr <= ref if ref is not None else False:
tiers['overdue'] += 1
else:
tiers['live'] += 1
if en:
enabled += 1
if r.get('deliver'):
deliver += 1
if r.get('fire_claim'):
fire_claim += 1
want = {
'total_jobs': len(jobs),
'enabled': enabled,
'paused': tiers['paused'],
'live': tiers['live'],
'overdue': tiers['overdue'],
'never': tiers['never'],
'deliver': deliver,
'fire_claim': fire_claim,
'fire_lock_files': len([f for f in os.listdir('/root/.hermes/cron') if f.startswith('.fire-')]),
}
try:
got = json.load(open(OUT))
except Exception as e:
print('FAIL: cannot read artifact JSON: %s' % e)
sys.exit(1)
checks = [
('total_jobs', want['total_jobs'], got.get('total_jobs')),
('enabled', want['enabled'], got.get('total_enabled')),
('paused', want['paused'], got.get('total_paused')),
('live', want['live'], got.get('counts_by_tier', {}).get('live')),
('overdue', want['overdue'], got.get('counts_by_tier', {}).get('overdue')),
('never', want['never'], got.get('counts_by_tier', {}).get('never')),
('deliver', want['deliver'], got.get('total_deliver')),
('fire_claim', want['fire_claim'], got.get('total_fire_claim')),
('fire_lock_files', want['fire_lock_files'], got.get('fire_lock_files_on_disk')),
]
bad = [n for n, w, g in checks if w != g]
if bad:
print('MISMATCH: %s' % bad)
sys.exit(1)
md = open(MD).read()
rows = ['total registered jobs | %d |' % want['total_jobs'],
'enabled & live (soonest first) | %d |' % want['live'],
'enabled & overdue | %d |' % want['overdue'],
'never-scheduled (no next_run_at) | %d |' % want['never'],
'disabled / draft-stalled | %d |' % want['paused']]
missing = [x for x in rows if x not in md]
if missing:
print('FAIL: markdown missing rows: %s' % missing)
sys.exit(1)
print('VERDICT: artifact cron-fleet-triage-2026-10-22 (md+json) matches frozen jobs snapshot (85 jobs: %d live, %d overdue, %d paused, %d never)' % (
want['live'], want['overdue'], want['paused'], want['never']))
sys.exit(0)