sol: daily-ledger lane status 2026-11-01 (triage)
This commit is contained in:
1 parent
3152149c4e
commit
6b5fc526de
4 files changed
+264
No files matched your search
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"artifact": "Sol-Lane-Status-2026-11-01.json",
|
||||
"source": "daily ledger logs under /root/.hermes/wizard-outputs/<lane>-*.txt (latest by mtime)",
|
||||
"measured_at_utc": "2026-11-01T09:56:37Z",
|
||||
"status_rule": "ACTIVE = latest log within 24h; WATCH = 24h-168h; STALE = >168h",
|
||||
"lanes": [
|
||||
{
|
||||
"id": "forge",
|
||||
"latest_log": "forge-2026-10-16-1446.txt",
|
||||
"latest_mtime_utc": "2026-10-16T14:56:18Z",
|
||||
"age_h": 379.01,
|
||||
"status": "STALE"
|
||||
},
|
||||
{
|
||||
"id": "ledger",
|
||||
"latest_log": "ledger-2026-10-16-1446.txt",
|
||||
"latest_mtime_utc": "2026-10-16T14:47:33Z",
|
||||
"age_h": 379.15,
|
||||
"status": "STALE"
|
||||
},
|
||||
{
|
||||
"id": "null",
|
||||
"latest_log": "null-2026-10-16-1446.txt",
|
||||
"latest_mtime_utc": "2026-10-16T14:47:52Z",
|
||||
"age_h": 379.15,
|
||||
"status": "STALE"
|
||||
},
|
||||
{
|
||||
"id": "quill",
|
||||
"latest_log": "quill-2026-10-16-1446.txt",
|
||||
"latest_mtime_utc": "2026-10-16T14:47:07Z",
|
||||
"age_h": 379.16,
|
||||
"status": "STALE"
|
||||
},
|
||||
{
|
||||
"id": "sphinx",
|
||||
"latest_log": "sphinx-2026-10-16-1446.txt",
|
||||
"latest_mtime_utc": "2026-10-16T14:50:35Z",
|
||||
"age_h": 379.1,
|
||||
"status": "STALE"
|
||||
},
|
||||
{
|
||||
"id": "sol",
|
||||
"latest_log": "sol-2026-10-28-183533.txt",
|
||||
"latest_mtime_utc": "2026-10-28T18:35:33Z",
|
||||
"age_h": 87.35,
|
||||
"status": "WATCH"
|
||||
},
|
||||
{
|
||||
"id": "spark",
|
||||
"latest_log": "spark-2026-10-16-1446.txt",
|
||||
"latest_mtime_utc": "2026-10-16T14:56:18Z",
|
||||
"age_h": 379.01,
|
||||
"status": "STALE"
|
||||
}
|
||||
],
|
||||
"status_counts": {
|
||||
"STALE": 6,
|
||||
"WATCH": 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
# Sol Daily-Lane Status - 2026-11-01 (measured)
|
||||
|
||||
Classification measured live from the on-disk mtimes of each primary lane's daily ledger logs under /root/.hermes/wizard-outputs/.
|
||||
Rules: ACTIVE = latest log within 24h; WATCH = 24h-168h; STALE = >168h.
|
||||
|
||||
## Verdict
|
||||
|
||||
- status_counts: {"STALE": 6, "WATCH": 1}
|
||||
|
||||
## Per-lane table
|
||||
|
||||
| Lane | Latest daily log | Last written (UTC) | Age (h) | Status |
|
||||
|-------|------------------|--------------------|---------|--------|
|
||||
| forge | forge-2026-10-16-1446.txt | 2026-10-16T14:56:18Z | 379.01 | STALE |
|
||||
| ledger | ledger-2026-10-16-1446.txt | 2026-10-16T14:47:33Z | 379.15 | STALE |
|
||||
| null | null-2026-10-16-1446.txt | 2026-10-16T14:47:52Z | 379.15 | STALE |
|
||||
| quill | quill-2026-10-16-1446.txt | 2026-10-16T14:47:07Z | 379.16 | STALE |
|
||||
| sphinx | sphinx-2026-10-16-1446.txt | 2026-10-16T14:50:35Z | 379.10 | STALE |
|
||||
| sol | sol-2026-10-28-183533.txt | 2026-10-28T18:35:33Z | 87.35 | WATCH |
|
||||
| spark | spark-2026-10-16-1446.txt | 2026-10-16T14:56:18Z | 379.01 | STALE |
|
||||
@@ -0,0 +1,110 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Build the sol daily-lane triage record for 2026-11-01 from live filesystem mtimes.
|
||||
|
||||
Classifies each primary lane (forge, ledger, null, quill, sphinx, sol, spark)
|
||||
by the latest mtime of its daily ledger log sol-*.txt under
|
||||
/root/.hermes/wizard-outputs/. Rules: ACTIVE <=24h; WATCH 24-168h; STALE >168h.
|
||||
Writes Sol-Lane-Status-2026-11-01.json + .md to wizard-outputs/sol/.
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
import datetime
|
||||
|
||||
BASE = "/root/.hermes/wizard-outputs"
|
||||
LANES = ["forge", "ledger", "null", "quill", "sphinx", "sol", "spark"]
|
||||
OUT_DIR = "/root/.hermes/wizard-outputs/sol"
|
||||
|
||||
RULE = "ACTIVE = latest log within 24h; WATCH = 24h-168h; STALE = >168h"
|
||||
|
||||
|
||||
def classify(age_h):
|
||||
if age_h <= 24.0:
|
||||
return "ACTIVE"
|
||||
if age_h <= 168.0:
|
||||
return "WATCH"
|
||||
return "STALE"
|
||||
|
||||
|
||||
def build():
|
||||
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)
|
||||
m = datetime.datetime.fromtimestamp(mt, tz=datetime.timezone.utc)
|
||||
age = (now - m).total_seconds() / 3600.0
|
||||
status = classify(age)
|
||||
lanes.append({
|
||||
"id": pid,
|
||||
"latest_log": os.path.basename(latest),
|
||||
"latest_mtime_utc": m.strftime("%Y-%m-%dT%H:%M:%SZ"),
|
||||
"age_h": round(age, 2),
|
||||
"status": status,
|
||||
})
|
||||
counts[status] = counts.get(status, 0) + 1
|
||||
|
||||
record = {
|
||||
"artifact": "Sol-Lane-Status-2026-11-01.json",
|
||||
"source": "daily ledger logs under /root/.hermes/wizard-outputs/<lane>-*.txt (latest by mtime)",
|
||||
"measured_at_utc": now.strftime("%Y-%m-%dT%H:%M:%SZ"),
|
||||
"status_rule": RULE,
|
||||
"lanes": lanes,
|
||||
"status_counts": counts,
|
||||
}
|
||||
return record, lanes, counts
|
||||
|
||||
|
||||
def glob_glob(pat):
|
||||
import glob
|
||||
return glob.glob(pat)
|
||||
|
||||
|
||||
def as_markdown(lanes, counts):
|
||||
lines = [
|
||||
"# Sol Daily-Lane Status - 2026-11-01 (measured)",
|
||||
"",
|
||||
"Classification measured live from the on-disk mtimes of each primary lane's daily ledger logs under /root/.hermes/wizard-outputs/.",
|
||||
"Rules: " + RULE + ".",
|
||||
"",
|
||||
"## Verdict",
|
||||
"",
|
||||
"- status_counts: %s" % json.dumps(counts),
|
||||
"",
|
||||
"## Per-lane table",
|
||||
"",
|
||||
"| Lane | Latest daily log | Last written (UTC) | Age (h) | Status |",
|
||||
"|-------|------------------|--------------------|---------|--------|",
|
||||
]
|
||||
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("")
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def main():
|
||||
record, lanes, counts = build()
|
||||
os.makedirs(OUT_DIR, exist_ok=True)
|
||||
json_path = os.path.join(OUT_DIR, "Sol-Lane-Status-2026-11-01.json")
|
||||
md_path = os.path.join(OUT_DIR, "Sol-Lane-Status-2026-11-01.md")
|
||||
with open(json_path, "w") as fh:
|
||||
json.dump(record, fh, indent=2)
|
||||
fh.write("\n")
|
||||
with open(md_path, "w") as fh:
|
||||
fh.write(as_markdown(lanes, counts))
|
||||
print("measured_at_utc:", record["measured_at_utc"])
|
||||
print("status_counts:", json.dumps(counts))
|
||||
print("lanes:")
|
||||
for ln in lanes:
|
||||
print(" %s %s %s age=%.2f -> %s" % (ln["id"], ln["latest_log"], ln["latest_mtime_utc"], ln["age_h"], ln["status"]))
|
||||
print("Wrote:", json_path)
|
||||
print("Wrote:", md_path)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env bash
|
||||
# CHECK -- sol: daily-ledger lane status for 2026-11-01 (forge: sol lane).
|
||||
#
|
||||
# Verdict: exit 0 iff the committed machine record
|
||||
# Sol-Lane-Status-2026-11-01.json
|
||||
# re-derives from the live filesystem (latest mtime of /root/.hermes/wizard-outputs/<lane>-*.txt)
|
||||
# and the status counts match. The exit code IS the verdict: 0 = correct, nonzero = wrong.
|
||||
set -u
|
||||
|
||||
cd "$(dirname "${BASH_SOURCE[0]}")" || exit 1
|
||||
REPO_ROOT="$(pwd)/.."
|
||||
OUT="/root/.hermes/wizard-outputs"
|
||||
JSON="$OUT/sol/Sol-Lane-Status-2026-11-01.json"
|
||||
LANE_LIST="forge ledger null quill sphinx sol spark"
|
||||
|
||||
python3 - "$JSON" "$OUT" "$LANE_LIST" <<'PY'
|
||||
import json, os, sys, glob, time
|
||||
|
||||
json_path, out, lane_list = sys.argv[1:4]
|
||||
lanes = lane_list.split()
|
||||
now = time.time()
|
||||
|
||||
recomputed = {}
|
||||
for L in lanes:
|
||||
files = sorted(glob.glob(os.path.join(out, L + "-*.txt")))
|
||||
if not files:
|
||||
print("FAIL: no ledger logs for lane %s" % L)
|
||||
sys.exit(1)
|
||||
latest = max(files, key=os.path.getmtime)
|
||||
age = (now - os.path.getmtime(latest)) / 3600.0
|
||||
status = "ACTIVE" if age < 24 else ("WATCH" if age <= 168 else "STALE")
|
||||
recomputed[L] = (status, os.path.basename(latest))
|
||||
|
||||
with open(json_path) as fh:
|
||||
rec = json.load(fh)
|
||||
|
||||
problems = []
|
||||
for L in lanes:
|
||||
jl = next((x for x in rec.get("lanes", []) if x.get("id") == L), None)
|
||||
if jl is None:
|
||||
problems.append("lane %s missing from JSON" % L)
|
||||
continue
|
||||
exp_status, exp_log = recomputed[L]
|
||||
if jl.get("status") != exp_status or jl.get("latest_log") != exp_log:
|
||||
problems.append("lane %s mismatch json=%s/%s recomputed=%s/%s"
|
||||
% (L, jl.get("status"), jl.get("latest_log"), exp_status, exp_log))
|
||||
if round(jl.get("age_h", -1), 2) < 0:
|
||||
problems.append("lane %s age_h missing or negative" % L)
|
||||
|
||||
exp_counts = {}
|
||||
for s, _ in recomputed.values():
|
||||
exp_counts[s] = exp_counts.get(s, 0) + 1
|
||||
if rec.get("status_counts") != exp_counts:
|
||||
problems.append("status_counts json=%s recomputed=%s" % (rec.get("status_counts"), exp_counts))
|
||||
|
||||
if problems:
|
||||
print("FAIL: %d problem(s)" % len(problems))
|
||||
for p in problems:
|
||||
print(" -", p)
|
||||
sys.exit(1)
|
||||
|
||||
print("PASS: lanes=%d statuses=%s counts=%s ids_match=yes"
|
||||
% (len(lanes), ",".join("%s=%s" % (k, v) for k, v in sorted(recomputed.items())),
|
||||
rec.get("status_counts")))
|
||||
sys.exit(0)
|
||||
PY
|
||||
rc=$?
|
||||
if [ $rc -ne 0 ]; then
|
||||
echo "FAIL: independent recompute disagrees with committed artifact (exit $rc)" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "PASS: Sol-Lane-Status-2026-11-01.json verified against the live filesystem"
|
||||
exit 0
|
||||
Reference in new issue
Block a user