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

133 lines
4.5 KiB
Python

#!/usr/bin/env python3
"""Verify the sol-profile triage artifact against real disk state.
Recomputes the classification from the active profile directory
/root/.hermes/profiles/sol/ and diffs it against the recorded artifact.
Exit code 0 = artifact matches disk. Nonzero = mismatch.
Rules (must mirror the generator's EXACT map / ordering):
identity: .env, .env.bak-20261014T165715Z
soul: SOUL.md
config: .env.lock, config.yaml, config.yaml.bak-20261014T165715Z
state_db: state.db, state.db-shm, state.db-wal,
state.db.auto-maintenance.lock, state.db.fts_rebuild.lock,
state.db.quarantine.lock, auth.json, auth.lock,
.skills_prompt_snapshot.json, models_dev_cache.json,
models_dev_cache.etag
cache: cache, audio_cache, image_cache, context_length_cache.yaml
sessions: sessions
skills: skills
plugins: plugins, plugin-update-checks
logs: logs
backups: backups
vault: vault
extension_dir: any other directory
script: name ends with .py
config_data: name ends with .yaml or .json
other: none of the above
"""
import json
import os
import sys
PROFILE = "/root/.hermes/profiles/sol"
ARTIFACT = "/root/.hermes/wizard-outputs/sol/sol-profile-triage-2026-10-28.json"
EXACT = {
"identity": {".env", ".env.bak-20261014T165715Z"},
"soul": {"SOUL.md"},
"config": {".env.lock", "config.yaml", "config.yaml.bak-20261014T165715Z"},
"state_db": {
"state.db", "state.db-shm", "state.db-wal",
"state.db.auto-maintenance.lock", "state.db.fts_rebuild.lock",
"state.db.quarantine.lock", "auth.json", "auth.lock",
".skills_prompt_snapshot.json", "models_dev_cache.json",
"models_dev_cache.etag",
},
"cache": {"cache", "audio_cache", "image_cache",
"context_length_cache.yaml"},
"sessions": {"sessions"},
"skills": {"skills"},
"plugins": {"plugins", "plugin-update-checks"},
"logs": {"logs"},
"backups": {"backups"},
"vault": {"vault"},
}
EXTS = {"bin", "cron", "forge", "home", "hooks", "keys", "lsp", "memories",
"pairings", "plans", "platforms", "runtime", "sandboxes", "skins",
"source-checks", "wizard-outputs", "workspace"}
def expected_category(name, is_dir):
if name in EXACT["identity"]:
return "identity"
if name in EXACT["soul"]:
return "soul"
if name in EXACT["config"]:
return "config"
if name in EXACT["state_db"]:
return "state_db"
if name in EXACT["cache"]:
return "cache"
if name in EXACT["sessions"]:
return "sessions"
if name in EXACT["skills"]:
return "skills"
if name in EXACT["plugins"]:
return "plugins"
if name in EXACT["logs"]:
return "logs"
if name in EXACT["backups"]:
return "backups"
if name in EXACT["vault"]:
return "vault"
if is_dir:
return "extension_dir"
if name.endswith(".py"):
return "script"
if name.endswith(".yaml") or name.endswith(".json"):
return "config_data"
return "other"
def main():
with open(ARTIFACT, encoding="utf-8") as fh:
art = json.load(fh)
disk = sorted(os.listdir(PROFILE))
expected = {}
for name in disk:
path = os.path.join(PROFILE, name)
expected[name] = expected_category(name, os.path.isdir(path))
recorded = {e["name"]: e.get("category") for e in art.get("entries", [])}
problems = []
if art.get("total_entries") != len(disk):
problems.append("total_entries %r != disk %d" % (art.get("total_entries"), len(disk)))
if set(recorded.keys()) != set(disk):
problems.append("entry names differ: missing=%s extra=%s" % (
sorted(set(disk) - set(recorded)), sorted(set(recorded) - set(disk))))
for n in sorted(set(disk) & set(recorded)):
if recorded[n] != expected[n]:
problems.append("category mismatch for %r: recorded=%r expected=%r" % (n, recorded[n], expected[n]))
expected_counts = {}
for n, c in expected.items():
expected_counts[c] = expected_counts.get(c, 0) + 1
if art.get("categories") != expected_counts:
problems.append("category counts %r != expected %r" % (art.get("categories"), expected_counts))
if problems:
print("FAIL")
for p in problems:
print(" -", p)
sys.exit(1)
print("PASS: artifact matches disk (%d entries, %d bytes)" % (len(disk), os.path.getsize(ARTIFACT)))
print("categories=%s" % json.dumps(art.get("categories")))
sys.exit(0)
if __name__ == "__main__":
main()