import io

p = '.spt/preserved/hertz-fp-driver-review/d2/d2_capture.ps1'
s = open(p, 'rb').read().decode('utf-8')

old_start = s.index("# --- the four-state encoding")
old_end = s.index("# Documentation defines these properties ONLY")

new = '''# --- value encoding (doyle's ruling, 2026-09-13) --------------------------------------------------
# TYPE AND CARDINALITY ARE PRESERVED. A present empty string is "", a present empty array is [], a
# present null is null, and a property the provider never exposed is explicitly ABSENT. Those are
# FOUR DIFFERENT FACTS; collapsing any into another destroys a distinction this capture exists to
# make. EnforcementStatus is uint16[], so [5,20], [1] and [] must serialize as arrays of two, one and
# zero elements -- never 5,20 or 1 or null. PowerShell unwraps a one-element array to a scalar and an
# empty one to $null if allowed to, and the field this investigation turns on is the one most at risk.
#
#   PRESENT  the provider exposed the property; value, type and cardinality recorded as returned
#   ABSENT   the provider did not expose the property at all
#   DENIED   the producing query raised an EXPLICIT ACCESS-DENIED error
#   ERROR    the producing query failed for any other reason; the error is recorded verbatim
#   NO_RULE  the query succeeded and returned no rule, so there was no object to have properties
#
# DENIED IS DECIDED BY THE QUERY'S OWN ERROR, EXIT AND ELEVATION -- NEVER BY A VALUE. A denied
# firewall read on this box is measured to render as a clean zero at the value site, so inferring
# denial from emptiness would relabel refusals as ordinary values and rebuild the exact trap this
# status exists to catch. A SUCCESSFUL EMPTY RESULT REMAINS AN EMPTY RESULT, and its COMPLETENESS IS
# UNPROVEN wherever the provider can silently filter what it returns.
function ConvertTo-RawScalar {
    param($V)
    if ($null -eq $V) { return $null }
    # No host-rendered name is ever substituted for a code: an enum keeps both halves.
    if ($V -is [System.Enum]) { return [ordered]@{ rendered = "$V"; underlying = [int64]$V } }
    return $V                                  # numbers stay numbers; "" stays ""
}

function New-ValueRecord {
    param([string]$State, $Value = $null, [switch]$HasValue)

    $rec = [ordered]@{ state = $State; value = $null; type = $null; is_array = $false; cardinality = $null }
    if (-not $HasValue) { return $rec }

    if ($null -eq $Value) { $rec['type'] = 'null'; return $rec }      # a PRESENT null

    $rec['type'] = $Value.GetType().FullName
    if (($Value -is [System.Collections.IEnumerable]) -and ($Value -isnot [string])) {
        $items = @($Value)                                            # @() so a singleton stays an array
        $rec['is_array'] = $true
        $rec['cardinality'] = $items.Count
        $out = New-Object System.Collections.ArrayList
        foreach ($i in $items) { $null = $out.Add((ConvertTo-RawScalar $i)) }
        $rec['value'] = ,@($out.ToArray())                            # leading comma: no pipeline collapse
    } else {
        $rec['is_array'] = $false
        $rec['cardinality'] = 1
        $rec['value'] = (ConvertTo-RawScalar $Value)
    }
    return $rec
}

function Get-PropState {
    param($Object, [string]$Name, [ValidateSet('OK', 'DENIED', 'ERROR', 'NO_RULE')][string]$QueryOutcome = 'OK')

    if ($QueryOutcome -ne 'OK') { return (New-ValueRecord -State $QueryOutcome) }
    if ($null -eq $Object)      { return (New-ValueRecord -State 'NO_RULE') }

    $prop = $Object.PSObject.Properties[$Name]
    if ($null -eq $prop) { return (New-ValueRecord -State 'ABSENT') }

    return (New-ValueRecord -State 'PRESENT' -Value $prop.Value -HasValue)
}

'''

s = s[:old_start] + new + s[old_end:]

reps = [
("""    $obj = $null; $denied = $false; $found = $false
    try {""",
 """    $obj = $null; $outcome = 'OK'; $found = $false; $matched = 0
    try {"""),

("""        $found = ($null -ne $obj)
    } catch {
        $denied = Test-Denied $_
        Add-CaptureError -Command $cmd -ErrorRecord $_
    }""",
 """        $items   = @($obj)                       # @() so one match is still an array
        $matched = $items.Count
        $obj     = if ($matched -ge 1) { $items[0] } else { $null }
        $found   = ($matched -ge 1)
    } catch {
        $outcome = if (Test-Denied $_) { 'DENIED' } else { 'ERROR' }
        Add-CaptureError -Command $cmd -ErrorRecord $_
    }"""),

("""        $entry = Get-PropState -Object $obj -Name $p -Denied:$denied""",
 """        $entry = Get-PropState -Object $obj -Name $p -QueryOutcome $outcome"""),

("""        found                           = $found
        denied                          = $denied""",
 """        found                           = $found
        matched_count                   = $matched      # cardinality of the match, not just a boolean
        query_outcome                   = $outcome      # OK | DENIED | ERROR — from the ERROR, never a value
        elevated                        = $script:Elevated"""),

("""        $obj = $null; $denied = $false
        try {""",
 """        $obj = $null; $outcome = 'OK'
        try {"""),

("""            $obj = Get-NetFirewallRule -PolicyStore $Store -Name $Name | & $spec.cmd
        } catch {
            $denied = Test-Denied $_
            Add-CaptureError -Command $cmd -ErrorRecord $_
        }""",
 """            $items = @(Get-NetFirewallRule -PolicyStore $Store -Name $Name | & $spec.cmd)
            $obj   = if ($items.Count -ge 1) { $items[0] } else { $null }
        } catch {
            $outcome = if (Test-Denied $_) { 'DENIED' } else { 'ERROR' }
            Add-CaptureError -Command $cmd -ErrorRecord $_
        }"""),

("""        foreach ($p in $spec.props) { $props[$p] = Get-PropState -Object $obj -Name $p -Denied:$denied }""",
 """        foreach ($p in $spec.props) { $props[$p] = Get-PropState -Object $obj -Name $p -QueryOutcome $outcome }"""),

("""            query      = $cmd
            denied     = $denied
            properties = $props""",
 """            query         = $cmd
            query_outcome = $outcome
            elevated      = $script:Elevated
            properties    = $props"""),

("""    # An empty array is not a measurement. Each host query records whether it was denied, so a
    # denied read never reaches the document as "this host has no interfaces".
    $denied     = [ordered]@{ interfaces = $false; profiles = $false; addresses = $false }""",
 """    # An empty array is not a measurement. Each host query records its own OUTCOME, so a denied or
    # failed read never reaches the document as "this host has no interfaces".
    $outcome    = [ordered]@{ interfaces = 'OK'; profiles = 'OK'; addresses = 'OK' }"""),

("""        denied     = $denied              # per-query, because an empty array and a denied read look identical""",
 """        query_outcome = $outcome          # per-query, because an empty array and a denied read look identical"""),

("""    $out = [ordered]@{ query = $cmd; values = @{ state = 'ABSENT'; value = $null }; valuemap = @{ state = 'ABSENT'; value = $null } }""",
 """    $out = [ordered]@{ query = $cmd; values = (New-ValueRecord -State 'ABSENT'); valuemap = (New-ValueRecord -State 'ABSENT') }"""),

("""            if ($null -ne $vals) { $out['values']   = [ordered]@{ state = 'MEASURED'; value = $vals.Value } }
            if ($null -ne $vmap) { $out['valuemap'] = [ordered]@{ state = 'MEASURED'; value = $vmap.Value } }""",
 """            if ($null -ne $vals) { $out['values']   = (New-ValueRecord -State 'PRESENT' -Value $vals.Value -HasValue) }
            if ($null -ne $vmap) { $out['valuemap'] = (New-ValueRecord -State 'PRESENT' -Value $vmap.Value -HasValue) }"""),

("""        $out['values']   = [ordered]@{ state = 'DENIED'; value = $null }
        $out['valuemap'] = [ordered]@{ state = 'DENIED'; value = $null }""",
 """        $st = if (Test-Denied $_) { 'DENIED' } else { 'ERROR' }
        $out['values']   = (New-ValueRecord -State $st)
        $out['valuemap'] = (New-ValueRecord -State $st)"""),

("""        $e = $r.properties['EnforcementStatus']
        if ($e.state -ne 'MEASURED') { continue }""",
 """        $e = $r.properties['EnforcementStatus']
        if ($e.state -ne 'PRESENT') { continue }"""),

("""    elevated          = (Test-Elevated)          # measured, never assumed""",
 """    elevated          = $script:Elevated         # measured, never assumed"""),
]

for a, b in reps:
    if a not in s:
        raise SystemExit('MISS: ' + a[:70])
    s = s.replace(a, b)

for k, c in (('interfaces', 'Get-NetConnectionProfile'),
             ('profiles', 'Get-NetFirewallProfile -All'),
             ('addresses', 'Get-NetIPAddress')):
    a = "    } catch { $denied['%s'] = (Test-Denied $_); Add-CaptureError -Command '%s' -ErrorRecord $_ }" % (k, c)
    b = "    } catch { $outcome['%s'] = $(if (Test-Denied $_) { 'DENIED' } else { 'ERROR' }); Add-CaptureError -Command '%s' -ErrorRecord $_ }" % (k, c)
    if a not in s:
        raise SystemExit('MISS host: ' + k)
    s = s.replace(a, b)

anchor = "$instrumentSha = 'UNREADABLE'"
if anchor not in s:
    raise SystemExit('MISS anchor instrumentSha')
s = s.replace(anchor, "$script:Elevated = (Test-Elevated)          # measured once, recorded beside every query outcome\n\n" + anchor)

open(p, 'wb').write(s.encode('utf-8'))
print('rewritten bytes=%d' % len(s.encode('utf-8')))
