← back to Dw Color Image Audit
scripts/rerun_remap.py
79 lines
#!/usr/bin/env python3
"""READ-ONLY re-classification of the existing flagged set with the FIXED family-mapper.
Re-runs the audit verdict for every row in out/reextracted.jsonl WITHOUT re-downloading any
image: it re-derives the declared family from the title with the fixed name_family(), recomputes
the image family from the already-cached real_hex via fam(), and re-runs classify(). This proves
the false-positive collapse from the leather-hijack / sea-green bug. $0, no network, no DB/Shopify.
Imports the ACTUAL shipped logic from reextract2 (name_family/fam/classify) so the test can't
drift from the code it validates.
"""
import sys, os, json
from collections import Counter
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
SCRIPTS = os.path.join(ROOT, "scripts")
sys.path.insert(0, SCRIPTS)
sys.argv = [sys.argv[0]] # so reextract2 import sees no argv[1]
import reextract2 as R # noqa: E402 (importable via __main__ guard)
R.NAME_FAMILY = json.load(open(os.path.join(SCRIPTS, "name_family.json")))
def hex_rgb(h):
h = h.lstrip("#")
return int(h[0:2],16), int(h[2:4],16), int(h[4:6],16)
def reclassify(row):
"""Return (declaredFamily, imageFamily, verdict, reason) under the FIXED mapper."""
df = R.name_family(row.get("declared",""))
hx = row.get("real_hex") or row.get("cached_hex")
if not hx:
return df, row.get("imageFamily"), "ERROR", "no-hex"
imf, s, l = R.fam(*hex_rgb(hx))
v, reason = R.classify(df, imf, s, l)
return df, imf, v, reason
def main():
src = os.path.join(ROOT, "out", "reextracted.jsonl")
rows = [json.loads(x) for x in open(src) if x.strip()]
out_path = os.path.join(ROOT, "out", "reextracted_remapped.jsonl")
before = Counter(); after = Counter()
cleared = [] # was HIGH, now not HIGH
new_high = [] # was not HIGH, now HIGH (regression watch)
fam_changed = [] # declaredFamily changed
with open(out_path, "w") as f:
for r in rows:
ov = r.get("verdict"); odf = r.get("declaredFamily")
ndf, nimf, nv, nreason = reclassify(r)
before[ov] += 1; after[nv] += 1
r2 = dict(r)
r2["declaredFamily_old"] = odf; r2["verdict_old"] = ov
r2["declaredFamily"] = ndf; r2["imageFamily"] = nimf
r2["verdict"] = nv; r2["reason"] = nreason
f.write(json.dumps(r2) + "\n")
if odf != ndf: fam_changed.append((r2, odf, ndf))
if ov == "HIGH" and nv != "HIGH": cleared.append((r2, nv, nreason))
if ov != "HIGH" and nv == "HIGH": new_high.append((r2, ov, nreason))
print("=== VERDICT COUNTS (all", len(rows), "re-extracted rows) ===")
print("BEFORE:", dict(before))
print("AFTER :", dict(after))
print(f"\ndeclaredFamily changed by fix: {len(fam_changed)} rows")
print(f"HIGH -> non-HIGH (false positives cleared): {len(cleared)}")
print(f"non-HIGH -> HIGH (new flags, regression watch): {len(new_high)}")
print("\n=== CLEARED (former Tier-1 HIGH now OK/REVIEW) ===")
for r, nv, why in sorted(cleared, key=lambda x: x[0].get("dwsku","")):
print(f" {r.get('dwsku',''):14} {r.get('declared','')[:42]:42} "
f"fam {r.get('declaredFamily_old','')}->{r.get('declaredFamily','')}"
f" img={r.get('imageFamily',''):7} -> {nv:6} ({why})")
if new_high:
print("\n=== NEW HIGH (introduced by fix — inspect) ===")
for r, ov, why in new_high:
print(f" {r.get('dwsku',''):14} {r.get('declared','')[:42]:42} -> HIGH ({why})")
if __name__ == "__main__":
main()