#!/usr/bin/env python3
"""FOLD-1 arms. Same discipline as W-1: anchors from the file in hand, reverts
proven by oid AND byte shape, zero-match gate on every filtered arm."""
import json, subprocess, pathlib, time, re

LANE = pathlib.Path(r"C:/Users/decid/Documents/projects/spt-core/.worktrees/304-fold-admission")
TARGET = "crates/spt-daemon/src/bootstrap_firewall/windows.rs"
OUT = pathlib.Path(r"C:/Users/decid/AppData/Local/Temp/claude/C--Users-decid-Documents-projects-spt-core/d4e86801-8514-4527-94e1-84f30b0d84d9/scratchpad")

HERTZ_SIX = [
    "bootstrap_firewall::tests::the_opt_out_disables_mutation_for_every_value_including_empty_and_zero",
    "bootstrap_firewall::tests::the_opt_out_refuses_before_the_argument_guard_and_before_any_host_command",
    "bootstrap_firewall::tests::verify_refuses_a_relative_binder_and_port_zero_under_either_opt_out_state",
    "bootstrap_firewall::tests::the_residual_cleanup_command_is_a_self_verifying_removal_that_creates_nothing",
    "bootstrap_firewall::windows::tests::binder_text_accepts_only_an_absolute_nul_free_path",
    "bootstrap_firewall::windows::tests::encoded_scripts_round_trip_as_utf16le_and_carry_the_ownership_identifiers",
]
MINE_FOUR = [
    "bootstrap_firewall::windows::tests::the_spec_is_built_for_the_bound_port_and_a_stale_port_rule_does_not_satisfy_it",
    "bootstrap_firewall::windows::tests::a_program_bearing_rule_does_not_satisfy_a_spec_that_wants_no_program_filter",
    "bootstrap_firewall::windows::tests::an_unrestricted_remote_does_not_satisfy_a_narrowed_spec",
    "bootstrap_firewall::windows::tests::a_rule_failing_hygiene_is_refused_even_when_its_scope_is_exactly_right",
]


def run(args):
    p = subprocess.run(args, cwd=LANE, capture_output=True, text=True)
    return p.returncode, p.stdout, p.stderr


def shape():
    raw = (LANE / TARGET).read_bytes()
    crlf = raw.count(b"\r\n")
    _, work, _ = run(["git", "hash-object", TARGET])
    _, head, _ = run(["git", "rev-parse", f"HEAD:{TARGET}"])
    return {"bytes": len(raw), "crlf": crlf, "bare_lf": raw.count(b"\n") - crlf,
            "work": work.strip(), "head": head.strip(), "clean": work.strip() == head.strip()}


def mutate(anchor_lf, repl_lf):
    raw = (LANE / TARGET).read_bytes()
    eol = b"\r\n" if raw.count(b"\r\n") else b"\n"
    a = anchor_lf.encode().replace(b"\n", eol)
    r = repl_lf.encode().replace(b"\n", eol)
    n = raw.count(a)
    if n != 1:
        eol_name = "CRLF" if eol == b"\r\n" else "LF"
        return False, f"ANCHOR COUNT {n} (need exactly 1) with eol={eol_name} — ABORTING, no mutation"
    (LANE / TARGET).write_bytes(raw.replace(a, r, 1))
    return True, "mutated"


def revert():
    run(["git", "checkout", "--", TARGET])
    return shape()


def nextest(label, extra):
    t0 = time.time()
    rc, out, err = run(["cargo", "nextest", "run", "-p", "spt-daemon", "--lib", "--no-fail-fast"] + extra)
    body = out + err
    (OUT / f"fold-{label}.raw").write_text(body, encoding="utf-8", errors="replace")
    summary = next((l.strip() for l in body.splitlines() if "tests run:" in l or "test run:" in l), "NO SUMMARY")
    ran = re.search(r"(\d+) tests? run", summary)
    return {"label": label, "exit": rc, "secs": round(time.time() - t0, 1), "summary": summary,
            "ran": int(ran.group(1)) if ran else None,
            "assertion": [l.strip() for l in body.splitlines() if "panicked at" in l or "assertion" in l or "left:" in l or "right:" in l][:8]}


def filt(names):
    return " | ".join(f"test(={n})" for n in names)


report = {"sha": run(["git", "rev-parse", "HEAD"])[1].strip(), "pre": shape(), "arms": []}
print("SUBJECT", report["sha"], "| pre", json.dumps(report["pre"]), flush=True)

# F1: desired_spec ignores the bound port
ok, msg = mutate("        port: bound_port,", "        port: 5470,")
print("F1 mutate:", msg, flush=True)
if ok:
    a = nextest("f1-u1R", ["--success-output", "immediate", "-E", filt([MINE_FOUR[0]])])
    a["revert"] = revert(); report["arms"].append(a); print("F1", json.dumps(a), flush=True)

# F2: the policy constant flipped
ok, msg = mutate("const DESIRED_PROGRAM: bool = false;", "const DESIRED_PROGRAM: bool = true;")
print("F2 mutate:", msg, flush=True)
if ok:
    a = nextest("f2-u2R", ["--success-output", "immediate", "-E", filt([MINE_FOUR[1]])])
    a["revert"] = revert(); report["arms"].append(a); print("F2", json.dumps(a), flush=True)

# F3 / F4 / F5
a = nextest("f3-hertz-six", ["-E", filt(HERTZ_SIX)]); a["gate"] = (a["ran"] == 6)
report["arms"].append(a); print("F3", json.dumps(a), flush=True)
a = nextest("f4-mine-four", ["-E", filt(MINE_FOUR)]); a["gate"] = (a["ran"] == 4)
report["arms"].append(a); print("F4", json.dumps(a), flush=True)

rc, out, _ = run(["cargo", "nextest", "list", "-p", "spt-daemon", "--lib"])
listed = len([l for l in out.splitlines() if l.strip().startswith("spt-daemon ")])
a = nextest("f5-unfiltered", [])
a["list_total"] = listed
a["leaky"] = [l.strip() for l in (OUT / "fold-f5-unfiltered.raw").read_text(encoding="utf-8", errors="replace").splitlines() if "LEAK" in l][:10]
report["arms"].append(a); print("F5", json.dumps(a), flush=True)

report["post"] = shape()
print("POST", json.dumps(report["post"]), flush=True)
(OUT / "fold-report.json").write_text(json.dumps(report, indent=2), encoding="utf-8")
print("REPORT WRITTEN", flush=True)
