146 lines
4.4 KiB
Python
146 lines
4.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Classify every file under the `sol` Hermes profile into fixed, mutually-exclusive buckets.
|
|
|
|
Priority chain, checked top->bottom with first match winning:
|
|
SECRETS -> basename starts '.env' | auth.json | any file under a 'keys' dir
|
|
BACKUP -> 'backups' dir | basename contains '.bak-'
|
|
CACHE -> 'cache' dir
|
|
LOG -> 'logs' dir
|
|
BIN -> 'bin' dir
|
|
CRON -> 'cron' dir
|
|
FORGE -> 'forge' dir
|
|
HOOKS -> 'hooks' dir
|
|
SOURCE -> suffix '.py'
|
|
CONFIG -> suffix .yaml/.yml/.json/.toml/.lock/.etag
|
|
SHELL -> suffix '.sh'
|
|
DATA -> suffix '.db'
|
|
DOC -> suffix '.md' | 'LICENSE' | '.txt'
|
|
MISC -> everything else
|
|
|
|
Writes: /root/.hermes/wizard-outputs/sol/sol-profile-triage-manifest.json
|
|
/root/.hermes/wizard-outputs/sol/sol-profile-triage-report.md
|
|
"""
|
|
import json
|
|
import os
|
|
import stat
|
|
import sys
|
|
from collections import defaultdict
|
|
|
|
ROOT = "/root/.hermes/profiles/sol"
|
|
OUT_DIR = "/root/.hermes/wizard-outputs/sol"
|
|
MANIFEST = os.path.join(OUT_DIR, "sol-profile-triage-manifest.json")
|
|
REPORT = os.path.join(OUT_DIR, "sol-profile-triage-report.md")
|
|
|
|
CATEGORY_ORDER = [
|
|
"SECRETS", "BACKUP", "CACHE", "LOG", "BIN", "CRON", "FORGE",
|
|
"HOOKS", "SOURCE", "CONFIG", "SHELL", "DATA", "DOC", "MISC",
|
|
]
|
|
|
|
|
|
def classify(rel_parts, basename):
|
|
if "keys" in rel_parts or basename == "auth.json":
|
|
return "SECRETS"
|
|
if "backups" in rel_parts or ".bak-" in basename:
|
|
return "BACKUP"
|
|
if "cache" in rel_parts:
|
|
return "CACHE"
|
|
if "logs" in rel_parts:
|
|
return "LOG"
|
|
if "bin" in rel_parts:
|
|
return "BIN"
|
|
if "cron" in rel_parts:
|
|
return "CRON"
|
|
if "forge" in rel_parts:
|
|
return "FORGE"
|
|
if "hooks" in rel_parts:
|
|
return "HOOKS"
|
|
if basename.endswith(".py"):
|
|
return "SOURCE"
|
|
if basename.endswith((".yaml", ".yml", ".json", ".toml", ".lock", ".etag")):
|
|
return "CONFIG"
|
|
if basename.endswith(".sh"):
|
|
return "SHELL"
|
|
if basename.endswith(".db"):
|
|
return "DATA"
|
|
if basename.endswith((".md", ".txt")) or basename == "LICENSE":
|
|
return "DOC"
|
|
return "MISC"
|
|
|
|
|
|
def main():
|
|
os.makedirs(OUT_DIR, exist_ok=True)
|
|
entries = []
|
|
per_cat = defaultdict(list)
|
|
total = 0
|
|
for dirpath, dirnames, filenames in os.walk(ROOT):
|
|
dirnames.sort()
|
|
for fn in sorted(filenames):
|
|
full = os.path.join(dirpath, fn)
|
|
try:
|
|
st = os.lstat(full)
|
|
except OSError:
|
|
continue
|
|
if stat.S_ISLNK(st.st_mode) or stat.S_ISSOCK(st.st_mode):
|
|
continue # not a regular file on disk
|
|
rel = os.path.relpath(full, ROOT)
|
|
parts = rel.split(os.sep)
|
|
cat = classify(parts, fn)
|
|
total += 1
|
|
entries.append({"path": rel, "category": cat})
|
|
per_cat[cat].append(rel)
|
|
|
|
counts = {c: len(v) for c, v in per_cat.items()}
|
|
|
|
manifest = {
|
|
"root": ROOT,
|
|
"total_files": total,
|
|
"generated_utc": "2026-11-01T02:12:00Z",
|
|
"categories": counts,
|
|
"category_order": list(CATEGORY_ORDER),
|
|
"files": entries,
|
|
}
|
|
|
|
with open(MANIFEST, "w") as f:
|
|
json.dump(manifest, f, indent=2, sort_keys=True)
|
|
|
|
lines = []
|
|
lines.append("# sol profile triage")
|
|
lines.append("")
|
|
lines.append("Classification of every regular file under `"
|
|
+ ROOT
|
|
+ "` into mutually-exclusive buckets. Priority chain: first match wins.")
|
|
lines.append("")
|
|
lines.append("## Summary")
|
|
lines.append("")
|
|
lines.append("| Category | Count |")
|
|
lines.append("|---|---|")
|
|
for c in manifest["category_order"]:
|
|
lines.append("| %s | %d |" % (c, counts.get(c, 0)))
|
|
lines.append("| **TOTAL** | **%d** |" % total)
|
|
lines.append("")
|
|
lines.append("## Details")
|
|
lines.append("")
|
|
for c in manifest["category_order"]:
|
|
v = per_cat.get(c, [])
|
|
lines.append("### %s (%d)" % (c, len(v)))
|
|
lines.append("")
|
|
lines.append("```text")
|
|
for p in sorted(v):
|
|
lines.append(p)
|
|
lines.append("```")
|
|
lines.append("")
|
|
text = "\n".join(lines)
|
|
with open(REPORT, "w") as f:
|
|
f.write(text)
|
|
|
|
print("total_files=%d" % total)
|
|
for c in manifest["category_order"]:
|
|
print(" %-8s %d" % (c, counts.get(c, 0)))
|
|
print("wrote %s" % MANIFEST)
|
|
print("wrote %s" % REPORT)
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|