#!/usr/bin/env python3
"""Anchored builder: fp-driver-d2-r2.sh (FROZEN) -> fp-driver-d2-r3.sh.

ONE CHANGE, authorized by doyle 5N5TZOBG: R6's first condition. The mutation marker being set
with an UNASSIGNED receipt path now reads UNPROVEN/OUTSTANDING instead of NOT_REQUESTED.

WHY, measured (group G, out 20260913T093635Z-G):
  :2594  mark_state fw_mutation_may_have_occurred   the marker is SET
  :2622  handoff_request setup ...                  THE REQUEST IS WRITTEN TO DISK here
  :2627  SETUP_RECEIPT="$HO_RECEIPT"                the receipt path is assigned only NOW
A signal between :2622 and :2627 reaches cleanup with the marker set, a request on disk and
SETUP_RECEIPT empty. r2 classified that NOT_REQUESTED — "no elevated setup was ever dispatched" —
and G3 measured the consequence: cleanup_stop_gate=ADMITTED, daemon_stop_gate=ADMITTED, and the
run_cmd sites for the autostarting stop and the daemon stop both REACHED, identical to the
PROVEN-setup positive control.

doyle 5N5TZOBG also ruled the shape of the fix: assigning the path earlier may narrow the window
but MUST NOT BE THE SAFETY GUARANTEE. So the guarantee lives in the predicate, where an
unassigned path is treated as the absence of a reading about a leg that may be running.

The source is READ, never written. The successor is not applied anywhere and no run consumes it.
"""
import hashlib
import pathlib
import sys

HERE = pathlib.Path(__file__).resolve().parent
SRC = HERE / "fp-driver-d2-r2.sh"
DST = HERE / "fp-driver-d2-r3.sh"
SRC_SHA = "67913bd653667ca7ae19a41df4dd9be713fe1b0c1177a0fe50a1f04f78899e7a"

raw = SRC.read_bytes()
got = hashlib.sha256(raw).hexdigest()
if got != SRC_SHA:
    sys.exit(f"SOURCE_DRIFT: {SRC.name} is {got}, pin says {SRC_SHA}")
if DST.exists():
    sys.exit(f"DESTINATION_EXISTS: {DST.name} is some attempt's evidence; it is not overwritten")
text = raw.decode("utf-8")

OLD = '''  SETUP_OUTSTANDING=no
  if [ -z "${SETUP_RECEIPT:-}" ] || ! has_state fw_mutation_may_have_occurred; then
    SETUP_COMPLETION=NOT_REQUESTED
    record "R6 setup_completion=NOT_REQUESTED — no elevated setup was ever dispatched, so nothing is outstanding and the gates below decide on their own measurements"
  else'''

NEW = '''  SETUP_OUTSTANDING=no
  # THE TWO ABSENCES ARE DIFFERENT QUESTIONS, AND r2 COLLAPSED THEM (doyle 5N5TZOBG; measured in
  # group G). "No setup was ever dispatched" is a statement about the MARKER. An unassigned
  # SETUP_RECEIPT path is a statement about THIS DRIVER'S OWN BOOKKEEPING, and while the marker
  # is set it is the absence of a reading about a leg that may be running — never evidence that
  # nothing was dispatched. The driver marks fw_mutation_may_have_occurred BEFORE the dispatch and
  # assigns SETUP_RECEIPT AFTER handoff_request has already written the request to disk, so a
  # signal in between lands in exactly that state, with the request file sitting there as evidence
  # that the dispatch DID happen.
  #
  # THE GUARANTEE IS HERE, NOT IN THE ORDER OF TWO ASSIGNMENTS (doyle's ruling). Moving the
  # assignment earlier would narrow the window and would not close it: any dispatch-then-record
  # sequence has one, and a window narrowed by rearrangement is not a safety property.
  if ! has_state fw_mutation_may_have_occurred; then
    SETUP_COMPLETION=NOT_REQUESTED
    record "R6 setup_completion=NOT_REQUESTED — the mutation marker was never set, so no elevated setup was ever dispatched: nothing is outstanding and the gates below decide on their own measurements"
  elif [ -z "${SETUP_RECEIPT:-}" ]; then
    SETUP_COMPLETION="UNPROVEN: no-receipt-path-assigned"
    SETUP_OUTSTANDING=yes
    record "R6 setup_completion=UNPROVEN missing: no-receipt-path-assigned — the mutation marker IS set and this run holds no receipt path to read, which happens when it was interrupted between writing the request and recording where the answer will arrive. A DISPATCH CANNOT BE DISPROVED HERE, so the leg is treated as OUTSTANDING and every cleanup mutation is withheld. The cost of being wrong this way is a PENDING report; the cost of being wrong the other way is an autostarting stop racing a leg that may still be starting processes, which is IR-124."
  else'''

# THE DRIVER IS A CRLF FILE — 2866 CRLFs, every line. The anchor and its replacement are written
# here with LF, so both are converted before matching, and the successor is written with newline=""
# so it stays CRLF. Without this the anchor matched zero times and the builder refused, which is
# the anchored builder doing its job: a drifted anchor fails the build rather than landing half an
# edit. (The first attempt hit exactly that and is why this note exists.)
OLD = OLD.replace(chr(10), chr(13) + chr(10))
NEW = NEW.replace(chr(10), chr(13) + chr(10))

n = text.count(OLD)
if n != 1:
    sys.exit(f"ANCHOR_{'ABSENT' if n == 0 else 'AMBIGUOUS'}: R6 head matched {n} times")
text = text.replace(OLD, NEW, 1)

DST.write_text(text, encoding="utf-8", newline="")
print(f"BUILT {DST.name} sha256={hashlib.sha256(DST.read_bytes()).hexdigest()}")
print("anchors replaced: 1")
