Files
troupe-standup/wizard-work/sol/build_sol_profile_triage.py

136 lines
4.9 KiB
Python

#!/usr/bin/env python3
"""Generate a real, filesystem-grounded SOL PROFILE TRIAGE report.
Lane: Triage - everyday Q&A and classification.
Scope: every content file under /root/.hermes/profiles/sol/ that the
solo-lane verifier enumerates (the 11 profile subdirs plus diag.py, with
.git / node_modules / __pycache__ pruned), classified into four tiers by mtime:
ACTIVE - touched within the last 24 hours (freshest, still warm)
STALE - touched 24h ago..90 days ago
ARTIFACT - the lane's defiitive files (config, soul, diag*, generator,
checker, the report itself), regardless of age
DEAD - everything else older than 90 days
The report is self-describing: Summary counts, a Findings table whose per-row
tier is mechanically derived from mtime, and a generated date. It is graded
by wizard-work/sol/check_sol_triage.py, which independently re-enumerates the
filesystem and re-parses the report; exit 0 = correct, nonzero = wrong.
Deliverable lives at /root/.hermes/wizard-outputs/sol/sol_triage_report.md
and is also committed to the troupe repo as wizard-work/sol/sol_triage_report.md.
"""
import os
import sys
from datetime import datetime, timezone, timedelta
from pathlib import Path
PROFILE = Path("/root/.hermes/profiles/sol")
REPORT = Path("/root/.hermes/wizard-outputs/sol/sol_triage_report.md")
EXCLUDE = {".git", "node_modules", "__pycache__"}
DIAG_FILES = ["diag.py", "diag2.py", "diag3.py", "diag4.py", "diag5.py"]
# Defiitive lane files, always ARTIFACT regardless of age.
ARTIFACT_NAMES = {
"config.yaml", "SOUL.md", "auth.json", "models_dev_cache.json",
"diag.py", "diag2.py", "diag3.py", "diag4.py", "diag5.py",
"_gen_sol_triage.py", "check_sol_triage.py", "sol_triage_report.md",
}
def enumerate_files():
"""Exact enumeration used by check_sol_triage.py."""
found = []
for sub in ("skills", "memories", "cron", "logs", "backups", "plans",
"pairing", "runtime", "diagnostics", "hooks", "image_cache"):
root = PROFILE / sub
if not root.is_dir():
continue
for _cur, dirs, names in os.walk(root):
dirs[:] = [d for d in dirs if d not in EXCLUDE]
for n in sorted(names):
found.append(Path(_cur) / n)
for f in DIAG_FILES:
p = PROFILE / f
if p.is_file():
found.append(p)
return found
def tier_for(rel: Path, st) -> str:
now = datetime.now(timezone.utc)
age = now - datetime.fromtimestamp(st.st_mtime, tz=timezone.utc)
if rel.name in ARTIFACT_NAMES:
return "ARTIFACT"
if age <= timedelta(hours=24):
return "ACTIVE"
if age <= timedelta(days=90):
return "STALE"
return "DEAD"
def main() -> int:
files = enumerate_files()
rows = []
for p in sorted(files, key=lambda x: (x.parent.name, x.name)):
rows.append({
"rel": p.relative_to(PROFILE).as_posix(),
"size": p.stat().st_size,
"mtime": datetime.fromtimestamp(p.stat().st_mtime, tz=timezone.utc),
"tier": tier_for(p.relative_to(PROFILE), p.stat()),
})
now = datetime.now(timezone.utc)
counts = {"ACTIVE": 0, "STALE": 0, "ARTIFACT": 0, "DEAD": 0}
for r in rows:
counts[r["tier"]] += 1
total = len(rows)
total_bytes = sum(r["size"] for r in rows)
L = []
w = L.append
w("# SOL PROFILE TRIAGE REPORT")
w("")
w("*generated-by*: sol (Hermes profile agent, Triage lane)")
w("*generated-at*: %s" % now.isoformat())
w("*generated*: %s" % now.strftime("%Y-%m-%d"))
w("generated: %s" % now.strftime("%Y-%m-%d"))
w("*profile-root*: `%s`" % PROFILE)
w("*file-count*: %d" % total)
w("*total-size*: %s bytes" % f"{total_bytes:,}")
w("")
w("## Summary")
w("")
w("| tier | count |")
w("|---|---|")
for t in ("ACTIVE", "STALE", "ARTIFACT", "DEAD"):
w("| %s | %d |" % (t, counts[t]))
w("")
w("## Findings")
w("")
w("- Attend to the %d fresh content items." % counts["ACTIVE"])
w("")
w("| # | relpath | tier | evidence |")
w("|---|---|---|---|")
for i, r in enumerate(sorted(rows, key=lambda x: (x["tier"], x["rel"])), 1):
w("| %d | `%s` | %s | %d bytes, mtime %s |"
% (i, r["rel"], r["tier"], r["size"], r["mtime"].strftime("%Y-%m-%dT%H:%M:%SZ")))
w("")
w("## Verdict")
w("")
w("Inventory complete and measured from the live filesystem (%d files, %s bytes)."
% (total, f"{total_bytes:,}"))
w("")
w("Tier rule applied to every file: ARTIFACT = defiitive lane files; "
"ACTIVE = touched within 24h; STALE = 24h..90d; DEAD = older than 90d.")
w("")
REPORT.parent.mkdir(parents=True, exist_ok=True)
REPORT.write_text("\n".join(L), encoding="utf-8")
print("wrote", REPORT)
print("files=%d bytes=%s counts=%s" % (total, f"{total_bytes:,}", counts))
return 0
if __name__ == "__main__":
sys.exit(main())