97 lines
3.1 KiB
Python
97 lines
3.1 KiB
Python
#!/usr/bin/env python3
|
|
"""CHECK — sol fleet-classification verdict (lite).
|
|
|
|
Independently recomputes the seven *stable* fleet classes straight from the
|
|
live filesystem and diffs them against the generated artifact. The artifact
|
|
is the sol lane's classification of the Hermes runtime instance.
|
|
|
|
Exit code 0 == CORRECT, 1 == WRONG.
|
|
|
|
NOTE on git: the troupe repo's untracked/modified set is actively churned by a
|
|
background file-writer, so git-derived fields are intentionally NOT part of
|
|
this check. This check covers only the stable, reproducibly-censusable
|
|
classes: profiles, skills, plugins, memories, cron-fires.
|
|
"""
|
|
import glob
|
|
import json
|
|
import os
|
|
import sys
|
|
|
|
HERMES = "/root/.hermes"
|
|
ARTIFACT = os.path.join(HERMES, "wizard-outputs", "sol", "fleet-classify-2026-11-01.json")
|
|
|
|
STABLE_CLASSES = [
|
|
"active-profile", "deleted-profile", "active-skill",
|
|
"archived-skill", "plugin", "memory", "cron-fire",
|
|
]
|
|
|
|
|
|
def recompute_fs():
|
|
out = {c: [] for c in STABLE_CLASSES}
|
|
|
|
profdir = os.path.join(HERMES, "profiles")
|
|
for n in os.listdir(profdir):
|
|
if not n.startswith(".deleted"):
|
|
out["active-profile"].append(n)
|
|
for n in os.listdir(os.path.join(profdir, ".deleted")):
|
|
out["deleted-profile"].append(n)
|
|
|
|
skills_dir = os.path.join(HERMES, "skills")
|
|
for n in os.listdir(skills_dir):
|
|
if n.startswith("."):
|
|
continue
|
|
out["active-skill"].append(n)
|
|
for n in os.listdir(os.path.join(skills_dir, ".archive")):
|
|
out["archived-skill"].append(n)
|
|
|
|
out["plugin"].extend(sorted(os.listdir(os.path.join(HERMES, "plugins"))))
|
|
out["memory"].extend(sorted(os.listdir(os.path.join(HERMES, "memories"))))
|
|
out["cron-fire"].extend(
|
|
sorted(os.path.basename(p) for p in glob.glob(os.path.join(HERMES, "cron", ".fire*")))
|
|
)
|
|
return out
|
|
|
|
|
|
def main():
|
|
try:
|
|
with open(ARTIFACT) as f:
|
|
art = json.load(f)
|
|
except Exception as exc:
|
|
print("VERDICT: WRONG")
|
|
print(" artifact not valid JSON:", exc)
|
|
sys.exit(1)
|
|
|
|
if not isinstance(art, dict) or "classes" not in art or "summary" not in art:
|
|
print("VERDICT: WRONG")
|
|
print(" artifact missing 'classes'/'summary'")
|
|
sys.exit(1)
|
|
|
|
fs = recompute_fs()
|
|
errors = []
|
|
|
|
# list equality for every stable class
|
|
for c in STABLE_CLASSES:
|
|
art_list = sorted(it["name"] for it in art["classes"].get(c, []) if isinstance(it, dict))
|
|
if art_list != sorted(fs[c]):
|
|
errors.append("class %r: artifact=%r fs=%r" % (c, art["classes"].get(c), fs[c]))
|
|
|
|
# summary count cross-check
|
|
for c in STABLE_CLASSES:
|
|
if art["summary"].get(c) != len(fs[c]):
|
|
errors.append("summary %r: %r != expected %d" % (c, art["summary"].get(c), len(fs[c])))
|
|
|
|
if errors:
|
|
print("VERDICT: WRONG")
|
|
for e in errors:
|
|
print(" -", e)
|
|
sys.exit(1)
|
|
|
|
print("VERDICT: CORRECT")
|
|
print(" active-profile=%d deleted-profile=%d active-skill=%d archived-skill=%d plugin=%d memory=%d cron-fire=%d"
|
|
% tuple(art["summary"][c] for c in STABLE_CLASSES))
|
|
sys.exit(0)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|