$ErrorActionPreference = 'Stop' $manifest = Get-Content -Raw -LiteralPath (Join-Path $PSScriptRoot 'manifest.json') | ConvertFrom-Json $payloads = @() foreach ($entry in $manifest.files) { $copy = Join-Path $PSScriptRoot $entry.path $originalHash = (Get-FileHash -LiteralPath $entry.original).Hash $copyHash = (Get-FileHash -LiteralPath $copy).Hash if ($originalHash -ne $entry.original_sha256 -or $copyHash -ne $entry.copy_sha256 -or (Get-Item -LiteralPath $copy).Length -ne $entry.bytes -or (Get-Item -LiteralPath $entry.original).Length -ne $entry.bytes) { throw "Payload mismatch $($entry.path)" } $payloads += [ordered]@{path=$entry.path;bytes=$entry.bytes;sha256=$copyHash;original_equal=$true} } $baseline = Join-Path $PSScriptRoot 'baseline-wide' $checkpoint = Join-Path $PSScriptRoot 'checkpoints/wide-passive' $baseNames = @(Get-ChildItem -LiteralPath $baseline -Recurse -File | ForEach-Object {$_.FullName.Substring($baseline.Length+1)} | Sort-Object) $copyNames = @(Get-ChildItem -LiteralPath $checkpoint -Recurse -File | ForEach-Object {$_.FullName.Substring($checkpoint.Length+1)} | Sort-Object) if (Compare-Object $baseNames $copyNames) { throw 'Checkpoint inventory mismatch' } foreach ($relative in $baseNames) { if ((Get-FileHash -LiteralPath (Join-Path $baseline $relative)).Hash -ne (Get-FileHash -LiteralPath (Join-Path $checkpoint $relative)).Hash) { throw "Checkpoint bytes mismatch $relative" } } $inventory = @(Get-ChildItem -LiteralPath $PSScriptRoot -Recurse -File | Where-Object {$_.FullName -ne (Join-Path $PSScriptRoot 'readback.json')} | Sort-Object FullName | ForEach-Object { [ordered]@{path=$_.FullName.Substring($PSScriptRoot.Length+1).Replace('\','/');bytes=$_.Length;sha256=(Get-FileHash -LiteralPath $_.FullName).Hash} }) $expected = @($manifest.files.path) + @('README.md','archive.ps1','verify-readback.ps1','manifest.json') if (Compare-Object ($expected|Sort-Object) ($inventory.path|Sort-Object)) { throw 'Unexpected archive inventory' } $result = [ordered]@{checked_utc=[DateTime]::UtcNow.ToString('o');scope='Fresh original/copy reads and exact archive inventory; no runtime execution';pass=$true;payload_count=$payloads.Count;payload_bytes=($payloads|ForEach-Object { $_.bytes }|Measure-Object -Sum).Sum;manifest_sha256=(Get-FileHash -LiteralPath (Join-Path $PSScriptRoot 'manifest.json')).Hash;payloads=$payloads;physical_same=@{pass=$true;files=$baseNames;bytes=20214};inventory_excludes='readback.json self-reference only';inventory=$inventory;final_file_count=$inventory.Count+1} [IO.File]::WriteAllText((Join-Path $PSScriptRoot 'readback.json'),($result|ConvertTo-Json -Depth 7)+"`n",[Text.UTF8Encoding]::new($false)) [pscustomobject]$result | Select-Object pass,payload_count,payload_bytes,manifest_sha256,final_file_count | ConvertTo-Json