Files
2026-10-27 00:53:24 +00:00

142 lines
4.7 KiB
Python

#!/usr/bin/env python3
"""Generate a real, filesystem-grounded SOL PROFILE TRIAGE report.
Scans every file under /root/.hermes/profiles/sol/ and classifies each one
into a category, then writes a markdown report to the troupe repo.
"""
import os
import sys
from datetime import datetime, timezone
from pathlib import Path
PROFILE_ROOT = Path("/root/.hermes/profiles/sol")
REPORT_PATH = Path(
"/root/troupe-standup/wizard-work/sol/sol-profile-triage-report.md"
)
def category_for(path: Path) -> str:
name = path.name.lower()
if path.suffix in (".py",):
return "script"
if path.suffix in (".yaml", ".yml", ".json", ".toml", ".env"):
return "config"
if path.suffix in (".db",):
return "data"
if path.suffix in (".lock",):
return "lock"
if path.suffix in (".mp3", ".wav", ".png", ".jpeg", ".jpg", ".etag"):
return "media"
if path.suffix in (".log",):
return "log"
if path.suffix in (".md", ".txt"):
return "doc"
if path.name in ("auth.json",):
return "secret"
if path.name == "state.db":
return "data"
return "other"
def main() -> int:
if not PROFILE_ROOT.is_dir():
print(f"FATAL: profile root missing: {PROFILE_ROOT}", file=sys.stderr)
return 1
files = []
for dirpath, dirnames, filenames in os.walk(PROFILE_ROOT):
dirnames.sort()
for fn in sorted(filenames):
p = Path(dirpath) / fn
try:
st = p.stat()
except OSError:
continue
files.append(
{
"rel": p.relative_to(PROFILE_ROOT).as_posix(),
"size": st.st_size,
"mtime": datetime.fromtimestamp(
st.st_mtime, tz=timezone.utc
).isoformat(),
"cat": category_for(p),
}
)
# Category rollup
cats = {}
for f in files:
cats.setdefault(f["cat"], []).append(f)
lines = []
w = lines.append
w("# SOL PROFILE TRIAGE REPORT")
w("")
w(f"*generated-by*: sol (Hermes profile agent)")
w(f"*generated-at*: {datetime.now(timezone.utc).isoformat()}")
w(f"*profile-root*: `{PROFILE_ROOT}`")
w(f"*file-count*: {len(files)}")
w(f"*total-size*: {sum(f['size'] for f in files):,} bytes")
w("")
w("## Category rollup")
w("")
w("| category | files | bytes | example |")
w("|---|---|---|---|")
for cat in sorted(cats):
examples = cats[cat][:2]
ex = ", ".join(f"`{e['rel']}`" for e in examples)
w(f"| {cat} | {len(cats[cat])} | {sum(e['size'] for e in cats[cat]):,} | {ex} |")
w("")
w("## File inventory")
w("")
w("| category | relpath | bytes | mtime(UTC) |")
w("|---|---|---|---|")
for f in sorted(files, key=lambda x: (x["cat"], x["rel"])):
w(f"| {f['cat']} | `{f['rel']}` | {f['size']:,} | {f['mtime']} |")
w("")
w("## Key facts")
w("")
for name in ("config.yaml", "SOUL.md", "auth.json", "models_dev_cache.json"):
p = PROFILE_ROOT / name
if not p.is_file():
continue
w(f"### `{name}`")
w("")
if name == "models_dev_cache.json":
# Summarize the model registry by provider instead of dumping
# the whole 5.9MB file; the raw file is unchanged on disk.
try:
import json
data = json.loads(p.read_text(encoding="utf-8", errors="replace"))
except Exception as exc: # pragma: no cover
w(f"(could not parse: {exc})")
continue
providers = data.get("providers", {})
w(f"*active_provider*: `{data.get('active_provider')}`")
w(f"*model_count*: {sum(len(v.get('models', {})) for v in providers.values())}")
w("*providers*: " + ", ".join(sorted(providers)))
w("*entries-eg*: " + ", ".join(
f"`{k}`" for k in list(providers.get("openai", {}).get("models", {}).keys())[:8]
))
else:
w("```")
with p.open("r", errors="replace") as fh:
w(fh.read())
w("```")
w("")
w("## Verdict")
w("")
w("Inventory complete. All entries below are measured from the live")
w(f"filesystem ({len(files)} files, {sum(f['size'] for f in files):,} bytes).")
w("")
REPORT_PATH.parent.mkdir(parents=True, exist_ok=True)
REPORT_PATH.write_text("\n".join(lines), encoding="utf-8")
print(f"wrote {REPORT_PATH}")
print(f"files={len(files)} bytes={sum(f['size'] for f in files):,} cats={len(cats)}")
return 0
if __name__ == "__main__":
sys.exit(main())