#!/usr/bin/env python3 """Re-derive every verdict from the captured probes using the committed `classify()`. The structural "did anything land in a mount at all?" rule was added to `classify()` after the sweep had started. It reads only fields the probe already captures (mount occupancy and the directories created outside every mount), and the Docker-touching half of the gate — the part that produces `probe` — was not changed by it. So the matrix is recomputed rather than re-measured, and the verdict every app carries is the one the COMMITTED gate produces for its captured evidence. Anything the rule could not have seen would require a fresh capture; nothing here does. Usage: reclassify.py """ import importlib.util, json, sys from pathlib import Path _spec = importlib.util.spec_from_file_location( "cvp", Path(__file__).resolve().parent / "check-volume-persistence.py") cvp = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(cvp) EV = Path(sys.argv[1]) changed = [] for d in sorted(EV.iterdir()): f = d / "probe.json" if not f.is_file(): continue rec = json.loads(f.read_text()) old = rec.get("verdict") status, why = cvp.classify(rec.get("probe") or {}) if status != old: changed.append((d.name, old, status)) rec["verdict"] = status rec["reasons"] = why rec["verdict_recomputed_by"] = "check-volume-persistence.py classify() (see reclassify.py)" f.write_text(json.dumps(rec, indent=2, sort_keys=True)) print(f"re-classified {sum(1 for d in EV.iterdir() if (d / 'probe.json').is_file())} apps") for a, o, n in changed: print(f" CHANGED {a}: {o} -> {n}") if not changed: print(" no verdict changed")