import io


def rw(path, pairs):
    s = io.open(path, 'r', encoding='utf-8', newline='').read()
    out = s
    for old, new in pairs:
        assert old in out, 'anchor missing in %s: %r' % (path, old[:70])
        out = out.replace(old, new, 1)
    assert out != s
    io.open(path, 'w', encoding='utf-8', newline='').write(out)
    print('patched', path)


# ---------------------------------------------------------------- 1. the probe's parameters
P_OLD = """[CmdletBinding()]
param(
    [Parameter(Mandatory)] [string[]] $Names,
    [Parameter(Mandatory)] [string]   $ControlName,   # a rule KNOWN to exist, addressed the same way
    [string[]] $Stores = @('ActiveStore','PersistentStore')
)
$ErrorActionPreference = 'Stop'
Set-StrictMode -Version Latest

"RULEPROBE_UTC $([DateTime]::UtcNow.ToString('o'))\""""

P_NEW = """[CmdletBinding()]
param(
    # ONE DELIMITED TOKEN, SPLIT HERE, AND THE COUNT IS ASSERTED (measured 2026-09-13).
    # powershell.exe -File collapses an array argument: `-Names "a","b"` arrives as the SINGLE
    # string "a,b", and `-Names "a" "b"` silently binds "b" to the NEXT parameter. Either way the
    # probe would have read one name, reported two readings instead of four, and the caller would
    # have seen an incomplete sample rather than an answer. So the caller passes one token, this
    # splits it, and a parsed count that is not what the caller EXPECTED is a refusal -- not a
    # smaller sample quietly returned.
    [Parameter(Mandatory)] [string] $NamesCsv,
    [Parameter(Mandatory)] [int]    $ExpectNames,
    [Parameter(Mandatory)] [string] $ControlName,   # a rule KNOWN to exist, addressed the same way
    [string[]] $Stores = @('ActiveStore','PersistentStore')
)
$ErrorActionPreference = 'Stop'
Set-StrictMode -Version Latest

"RULEPROBE_UTC $([DateTime]::UtcNow.ToString('o'))"
$Names = @($NamesCsv -split ',' | ForEach-Object { $_.Trim() } | Where-Object { $_ -ne '' })
"RULEPROBE_ARGS raw=[$NamesCsv] parsed=$($Names.Count) expected=$ExpectNames"
foreach ($n in $Names) { "RULEPROBE_ARG name=[$n]" }
if ($Names.Count -ne $ExpectNames) {
    "RULEPROBE_ARGS_REFUSED parsed=$($Names.Count) expected=$ExpectNames - the shell did not deliver the names this probe was asked about. A smaller sample is NOT a smaller answer."
    exit 7
}
if (@($Names | Sort-Object -Unique).Count -ne $Names.Count) {
    "RULEPROBE_ARGS_REFUSED duplicate names in [$NamesCsv] - two readings of one name are not two readings."
    exit 7
}"""

rw('rule-probe.ps1', [(P_OLD, P_NEW)])

# ---------------------------------------------------------------- 2. narrow the probe's prose
rw('rule-probe.ps1', [(
    """IT IS READ-ONLY. Get-NetFirewallRule only. It creates nothing, removes nothing, stops no listener
and touches no process. It is not the remover; it is the second opinion on the remover's work.""",
    """IT IS READ-ONLY. Get-NetFirewallRule only. It creates nothing, removes nothing, stops no listener
and touches no process. It is not the remover; it is the second opinion on the remover's work.

WHAT A READING DOES AND DOES NOT MEAN (narrowed, doyle 2026-09-13). PRESENT in ActiveStore means a
rule object with that InstanceID is in that store at this instant. It does NOT establish that any
traffic is being admitted: admission depends on the rule's own enabled/direction/action/filters and
on every other rule and policy on the host, none of which this probe reads. And a partial reading --
one name gone, one present -- does NOT by itself establish that any particular invocation removed
anything: without the preceding state and the action record, "one is missing now" is consistent with
its never having been created.""")])

# ---------------------------------------------------------------- 3. the driver's invocation
rw('_part_cleanup.sh', [(
    '  pwsh -NoProfile -File "$RULE_PROBE" -Names "$RULE_TAILNET","$RULE_LAN" -ControlName "$CONTROL_RULE" > "$out" 2>&1',
    '  # ONE DELIMITED TOKEN, AND THE PROBE IS TOLD HOW MANY TO EXPECT. Measured 2026-09-13:\n'
    '  # powershell.exe -File collapses `-Names "a","b"` into the single string "a,b", and\n'
    '  # `-Names "a" "b"` binds "b" to the NEXT parameter instead. Both forms silently delivered ONE\n'
    '  # name. The probe now parses the token itself and REFUSES (exit 7) when the parsed count is\n'
    '  # not the expected one, so a binding regression is a refusal rather than a smaller sample.\n'
    '  pwsh -NoProfile -File "$RULE_PROBE" -NamesCsv "$RULE_TAILNET,$RULE_LAN" -ExpectNames 2 -ControlName "$CONTROL_RULE" > "$out" 2>&1')])

# ---------------------------------------------------------------- 4. the obsolete success marker
rw('_part_cleanup.sh', [(
    """      local verdict=0 absent=0 valid=0
      grep -q 'LAN_FIREWALL_CLEAN' "$HO_OUT" 2>/dev/null && verdict=1
      grep -q 'tag=cleanup-teardown-post .* subj_group=0 subj_29470=0' "$R/census.log" && absent=1""",
    """      # THE REVIEWED REMOVER SUCCEEDS SILENTLY (doyle 2026-09-13). The previous conjunction
      # required the product's LAN_FIREWALL_CLEAN line, which belonged to the `serve lan --stop`
      # verb this integration replaced. The reviewed payload prints NOTHING on success -- it
      # removes, re-reads both stores, and throws if anything remains -- so requiring that marker
      # made a successful removal unverifiable and every clean run PENDING. Removed rather than
      # manufactured: a marker this driver invents would prove only that the driver can write it.
      # WHAT REMAINS REQUIRED is what can actually be measured: the remover's own native exit, a
      # census that succeeded, and the independent per-name, per-store absence reading.
      local absent=0 valid=0
      grep -q 'tag=cleanup-teardown-post .* subj_group=0 subj_29470=0' "$R/census.log" && absent=1""")])

rw('_part_cleanup.sh', [(
    """      record "TEARDOWN_CHECK receipt_exit=$t_rc census_exit=$c_rc clean_verdict=$verdict named_rules_absent=$absent census_valid=$valid independent_removal=$REMOVAL_CHECK"
      if [ "$t_rc" -eq 0 ] && [ "$c_rc" -eq 0 ] && [ "$verdict" -eq 1 ] && [ "$absent" -eq 1 ] && [ "$valid" -eq 1 ] && [ "$REMOVAL_CHECK" = CONFIRMED ]; then
        record "TEARDOWN_VERIFIED — zero teardown exit AND a successful census AND the product's own LAN_FIREWALL_CLEAN verdict AND the owned named rules measured ABSENT by an INDEPENDENT per-name, per-store probe\"""",
    """      record "TEARDOWN_CHECK receipt_exit=$t_rc census_exit=$c_rc named_rules_absent=$absent census_valid=$valid independent_removal=$REMOVAL_CHECK (the remover succeeds SILENTLY; there is no success marker to require)"
      if [ "$t_rc" -eq 0 ] && [ "$c_rc" -eq 0 ] && [ "$absent" -eq 1 ] && [ "$valid" -eq 1 ] && [ "$REMOVAL_CHECK" = CONFIRMED ]; then
        record "TEARDOWN_VERIFIED — zero remover exit AND a successful census AND the owned named rules measured ABSENT by an INDEPENDENT per-name, per-store probe\"""")])

rw('_part_cleanup.sh', [(
    """        cfail "TEARDOWN NOT VERIFIED (receipt_exit=$t_rc census_exit=$c_rc clean_verdict=$verdict absent=$absent census_valid=$valid independent_removal=$REMOVAL_CHECK).""",
    """        cfail "TEARDOWN NOT VERIFIED (receipt_exit=$t_rc census_exit=$c_rc absent=$absent census_valid=$valid independent_removal=$REMOVAL_CHECK).""")])

# ---------------------------------------------------------------- 5. narrow the driver's own prose
rw('_part_cleanup.sh', [(
    """    record "REMOVAL_CHECK=ACTIVESTORE_RESIDUE active_present=$active_present - the persistent rule is gone and the LIVE one is not. The host is still admitting on it: PENDING/review, and nothing is retried.\"""",
    """    record "REMOVAL_CHECK=ACTIVESTORE_RESIDUE active_present=$active_present - the persistent rule is gone and a rule of that name is still in the LIVE store. Whether anything is being admitted through it is NOT established here (this reads names, not effective admission): PENDING/review, and nothing is retried.\"""")])

rw('_part_cleanup.sh', [(
    """    record "REMOVAL_CHECK=PARTIAL absent=$absent present=$present - one owned name was removed and another was not. A half-removal is open admission, not a partial success: PENDING/review, and NO second dispatch is issued.\"""",
    """    record "REMOVAL_CHECK=PARTIAL absent=$absent present=$present - one owned name is absent and another is present. Read with the pre-teardown state and the remover's exit, that is a half-removal; on its own it does not establish that THIS invocation removed anything. Either way it is not a success: PENDING/review, and NO second dispatch is issued.\"""")])
