# Offline report helper. Numeric CSV must round-trip independently of the
# Windows display language; JSON already uses locale-independent serialization.
# A VS/cmd child can inherit PowerShell 7's PSModulePath while actually running
# Windows PowerShell 5. Load the current host's own standard module explicitly;
# otherwise auto-discovery can miss Get-FileHash by selecting the 7.x manifest.
# This changes only this script session, never user/system environment settings.
$deepPluckNativeUtilityManifest=Join-Path $PSHOME 'Modules/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psd1'
Import-Module -Name $deepPluckNativeUtilityManifest -ErrorAction Stop
function Export-CPUCsv($Rows,[string]$Path){
    if(Test-Path -LiteralPath $Path){throw "Refusing to overwrite CSV evidence: $Path"}
    $savedTaskCulture=[Threading.Thread]::CurrentThread.CurrentCulture
    try{
        [Threading.Thread]::CurrentThread.CurrentCulture=[Globalization.CultureInfo]::InvariantCulture
        $Rows | Export-Csv -LiteralPath $Path -NoTypeInformation -Encoding utf8
    }finally{[Threading.Thread]::CurrentThread.CurrentCulture=$savedTaskCulture}
}
function Get-CPUComparisonEnvironmentHash($Provenance,[bool]$SyntheticFixture=$false){
    if($SyntheticFixture -and -not$Provenance.environment.cpuSets){return [string]$Provenance.environment_sha256}
    if(-not$Provenance.environment.cpuSets -or $Provenance.environment.cpuSets.Count -le 0){throw 'Missing real CPU topology for environment comparison'}
    $environment=($Provenance.environment | ConvertTo-Json -Depth 20 -Compress) | ConvertFrom-Json
    foreach($cpu in $environment.cpuSets){
        # Windows SDK 10.0.26100.0 winnt.h: PARKED=0x1 is a momentary scheduler
        # observation. Preserve all original metadata/flags; exclude only this bit
        # from the separate comparison identity, not allocation/priority/topology.
        $cpu.flags=([int]$cpu.flags -band 0xfe)
    }
    $text=$environment | ConvertTo-Json -Depth 20 -Compress
    $hash=[Security.Cryptography.SHA256]::Create()
    try{return ([BitConverter]::ToString($hash.ComputeHash([Text.Encoding]::UTF8.GetBytes($text)))).Replace('-','').ToLowerInvariant()}
    finally{$hash.Dispose()}
}
