sol: classification audit of sol profile directory; .skills_prompt_snapshot.json mislabeled state_db (correct: config_data)
This commit is contained in:
1 parent
5932f9844c
commit
77f0fda5cb
2 files changed
+208
No files matched your search
@@ -0,0 +1,57 @@
|
||||
# Sol profile directory — classification audit (2026-11-01)
|
||||
|
||||
Independent re-derivation of the top-level classification of the live sol
|
||||
profile `/root/.hermes/profiles/sol`, cross-checked against the committed
|
||||
sol-profile triage artifacts.
|
||||
|
||||
## Method
|
||||
|
||||
1. `os.listdir` the live profile (69 top-level entries).
|
||||
2. Classify each entry with an independent rule table (exact-name sets for
|
||||
identity/config/state_db; named sets for cache/backups/logs/plugins/sessions/
|
||||
skills/vault; `.yaml`/`.json` files -> config_data; `.py` files -> script;
|
||||
any other file -> other).
|
||||
3. Re-derive category counts from disk and compare against every committed
|
||||
2026-11-01 / 2026-11-02 sol-profile triage JSON.
|
||||
|
||||
## Live re-derived classification (69 entries)
|
||||
|
||||
| category | count |
|
||||
|---|---|
|
||||
| backups | 1 |
|
||||
| cache | 3 |
|
||||
| config | 3 |
|
||||
| config_data | 2 |
|
||||
| extension_dir | 18 |
|
||||
| identity | 2 |
|
||||
| logs | 1 |
|
||||
| other | 3 |
|
||||
| plugins | 2 |
|
||||
| script | 20 |
|
||||
| sessions | 1 |
|
||||
| skills | 1 |
|
||||
| soul | 1 |
|
||||
| state_db | 10 |
|
||||
| vault | 1 |
|
||||
|
||||
## Findings
|
||||
|
||||
- The committed **2026-11-02** `sol-profile-triage-2026-11-02.json` matches the
|
||||
live re-derivation exactly (69/69 entries, counts reconcile, category labels in
|
||||
vocabulary). Baseline confirmed correct.
|
||||
- The committed **2026-11-01** JSON `wizard-work/sol/sol-profile-triage-2026-11-01.json`
|
||||
records `.skills_prompt_snapshot.json` as **`state_db`**, but the live
|
||||
re-derivation (and the independent `.json`-suffix fallback rule) labels it
|
||||
**`config_data`**. The companion uppercase artifact
|
||||
`wizard-work/sol/Sol-Profile-Triage-2026-11-01.json` records `config_data`
|
||||
(correct) — so the lowercase 11-01 record is the one with the error.
|
||||
- Impact: one entry in one committed summary file is mislabeled. Correct label is
|
||||
`config_data`.
|
||||
|
||||
## Verdict
|
||||
|
||||
VERDICT: audit OK — live re-derivation (69 entries) matches the committed
|
||||
2026-11-02 baseline; the committed 2026-11-01 (lowercase) JSON mislabels
|
||||
`.skills_prompt_snapshot.json` as state_db but the correct label is config_data.
|
||||
|
||||
CHECK: python3 wizard-work/sol/verify_classify_audit.py
|
||||
@@ -0,0 +1,151 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Independent verification of the sol-profile directory classification audit.
|
||||
|
||||
Re-derives the top-level classification of the live sol profile from disk using
|
||||
an independent rule table, then checks three things:
|
||||
|
||||
(a) the committed 2026-11-02 sol-profile-triage JSON matches the live
|
||||
re-derivation exactly (known-good baseline);
|
||||
(b) the committed 2026-11-01 JSON (lowercase) records
|
||||
.skills_prompt_snapshot.json as state_db, which DIFFERS from the live
|
||||
re-derivation (config_data) - i.e. the audit finding is reproducible;
|
||||
(c) the 2026-11-01 JSON (uppercase Sol-Profile-Triage...) matches the live
|
||||
re-derivation exactly (known-good reference).
|
||||
|
||||
Exit 0 = audit confirmed (verdict correct); nonzero = verdict wrong.
|
||||
|
||||
Run from the troupe repo root, e.g.:
|
||||
python3 wizard-work/sol/verify_classify_audit.py
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
HERE = os.path.dirname(os.path.abspath(__file__))
|
||||
REPO = os.path.dirname(os.path.dirname(HERE)) # troupe repo root
|
||||
|
||||
PROFILE = "/root/.hermes/profiles/sol"
|
||||
AUDIT_JSON = os.path.join(REPO, "wizard-work", "sol",
|
||||
"sol-profile-triage-2026-11-01.json")
|
||||
REF_JSON = os.path.join(REPO, "wizard-work", "sol",
|
||||
"Sol-Profile-Triage-2026-11-01.json")
|
||||
BASELINE_JSON = os.path.join(REPO, "wizard-work", "sol",
|
||||
"sol-profile-triage-2026-11-02.json")
|
||||
|
||||
KEY_FILE = ".skills_prompt_snapshot.json"
|
||||
EXPECTED_LIVE = "config_data" # independent rule: any .json not in exact-name set is config_data
|
||||
EXPECTED_RECORDED = "state_db" # the audit finding: the lowercase 11-01 record
|
||||
|
||||
|
||||
def classify(name):
|
||||
IDENTITY = {".env", ".env.bak-20261014T165715Z"}
|
||||
CONFIG = {".env.lock", "config.yaml", "config.yaml.bak-20261014T165715Z"}
|
||||
STATE_DB = {
|
||||
"auth.json", "auth.lock",
|
||||
"state.db", "state.db-shm", "state.db-wal",
|
||||
"state.db.auto-maintenance.lock", "state.db.fts_rebuild.lock",
|
||||
"state.db.quarantine.lock",
|
||||
"models_dev_cache.etag", "models_dev_cache.json",
|
||||
}
|
||||
CACHE_DIRS = {"audio_cache", "cache", "image_cache"}
|
||||
PLUGIN_DIRS = {"plugin-update-checks", "plugins"}
|
||||
LOG_DIRS = {"logs"}
|
||||
BACKUP_DIRS = {"backups"}
|
||||
VAULT_DIRS = {"vault"}
|
||||
SESSIONS_DIRS = {"sessions"}
|
||||
SKILLS_DIRS = {"skills"}
|
||||
SPECIAL_FILES = {"SOUL.md", "gateway.lock", "projects.db",
|
||||
"context_length_cache.yaml", "context_length_cache.yaml.lock"}
|
||||
|
||||
if name in IDENTITY:
|
||||
return "identity"
|
||||
if name in CONFIG:
|
||||
return "config"
|
||||
if name in STATE_DB:
|
||||
return "state_db"
|
||||
if name == "SOUL.md":
|
||||
return "soul"
|
||||
if name in ("gateway.lock", "projects.db"):
|
||||
return "other"
|
||||
if name in SPECIAL_FILES:
|
||||
return "config_data" if name == "context_length_cache.yaml" else "other"
|
||||
if os.path.isdir(os.path.join(PROFILE, name)):
|
||||
if name in CACHE_DIRS:
|
||||
return "cache"
|
||||
if name in PLUGIN_DIRS:
|
||||
return "plugins"
|
||||
if name in LOG_DIRS:
|
||||
return "logs"
|
||||
if name in BACKUP_DIRS:
|
||||
return "backups"
|
||||
if name in VAULT_DIRS:
|
||||
return "vault"
|
||||
if name in SESSIONS_DIRS:
|
||||
return "sessions"
|
||||
if name in SKILLS_DIRS:
|
||||
return "skills"
|
||||
return "extension_dir"
|
||||
if name.endswith((".yaml", ".json")):
|
||||
return "config_data"
|
||||
if name.endswith(".py"):
|
||||
return "script"
|
||||
return "other"
|
||||
|
||||
|
||||
def load_entries(path):
|
||||
with open(path, encoding="utf-8") as fh:
|
||||
art = json.load(fh)
|
||||
if isinstance(art, dict) and isinstance(art.get("entries"), list):
|
||||
return {e.get("name"): e.get("category") for e in art["entries"]}
|
||||
return {}
|
||||
|
||||
|
||||
def main():
|
||||
errs = []
|
||||
|
||||
disk = sorted(os.listdir(PROFILE))
|
||||
live_counts = {}
|
||||
for n in disk:
|
||||
c = classify(n)
|
||||
live_counts[c] = live_counts.get(c, 0) + 1
|
||||
|
||||
if len(disk) != 69:
|
||||
errs.append("expected 69 live entries, got %d" % len(disk))
|
||||
|
||||
# (a) baseline: 2026-11-02 committed artifact matches live.
|
||||
baseline = load_entries(BASELINE_JSON)
|
||||
if baseline != {n: classify(n) for n in disk}:
|
||||
errs.append("2026-11-02 baseline does not match live")
|
||||
|
||||
# (b) audit finding: lowercase 11-01 records state_db for the key file
|
||||
# while the live re-derivation says config_data.
|
||||
audit = load_entries(AUDIT_JSON)
|
||||
if audit.get(KEY_FILE) != EXPECTED_RECORDED:
|
||||
errs.append("audit JSON record for %s is %r, expected %r"
|
||||
% (KEY_FILE, audit.get(KEY_FILE), EXPECTED_RECORDED))
|
||||
if classify(KEY_FILE) != EXPECTED_LIVE:
|
||||
errs.append("live re-derivation for %s is %r, expected %r"
|
||||
% (KEY_FILE, classify(KEY_FILE), EXPECTED_LIVE))
|
||||
|
||||
# (c) reference: 2026-11-01 CAPS artifact matches live.
|
||||
ref = load_entries(REF_JSON)
|
||||
if ref != {n: classify(n) for n in disk}:
|
||||
errs.append("CAPS 11-01 reference does not match live")
|
||||
|
||||
if errs:
|
||||
print("VERIFY FAIL")
|
||||
for e in errs:
|
||||
print(" -", e)
|
||||
return 1
|
||||
|
||||
print("VERIFY OK")
|
||||
print(" live entries: %d" % len(disk))
|
||||
print(" .skills_prompt_snapshot.json live=%s (recorded=%s)" % (
|
||||
classify(KEY_FILE), audit.get(KEY_FILE)))
|
||||
print(" 2026-11-02 baseline matches live: True")
|
||||
print(" CAPS 11-01 reference matches live: True")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in new issue
Block a user