Files
ARCADIA-Studio/harness/experiments/navigation-rename-native-a49-20260913/archive.ps1
T

93 lines
8.1 KiB
PowerShell

param([Parameter(Mandatory)][string]$Original, [Parameter(Mandatory)][string]$Review)
$ErrorActionPreference = 'Stop'
$destination = $PSScriptRoot
$Original = (Resolve-Path -LiteralPath $Original).Path
function Json($path) { Get-Content -LiteralPath $path -Raw | ConvertFrom-Json }
function Hash($path) { (Get-FileHash -LiteralPath $path -Algorithm SHA256).Hash.ToLowerInvariant() }
function AssertFile($root, $record) {
$path = Join-Path $root $record.path
if ((Get-Item -LiteralPath $path).Length -ne $record.bytes -or (Hash $path) -ne $record.sha256) { throw "File mismatch: $path" }
}
$inputRecord = Json "$Original/input-manifest.json"
foreach ($file in $inputRecord.immutable_files) { AssertFile $Original $file }
if ($inputRecord.immutable_files.Count -ne 15) { throw 'Expected 15 immutable inputs' }
$launch = Json "$Original/launch.json"
$close = Json "$Original/normal-close.json"
if ($launch.manifest_sha256 -ne (Hash "$Original/input-manifest.json") -or $launch.script_sha256 -ne (Hash "$Original/launch.ps1") -or $launch.binary_sha256 -ne $inputRecord.binary_copy_sha256 -or $launch.pid -ne $close.pid -or $launch.started_utc -ne $close.started_utc) { throw 'Launch binding mismatch' }
$before = Json "$Original/evidence/inputs-complete-before.json"
$after = Json "$Original/evidence/inputs-complete-after.json"
if ($before.count -ne 577 -or $after.count -ne 577 -or ($before.files | ConvertTo-Json -Depth 8 -Compress) -cne ($after.files | ConvertTo-Json -Depth 8 -Compress)) { throw 'Build input manifest mismatch' }
foreach ($file in $after.files) { AssertFile $after.workspace $file }
if ($close.pid -ne 1352 -or $close.exit_code -ne 0 -or -not $close.immutable_inputs_unchanged) { throw 'Unexpected closure' }
foreach ($file in Get-ChildItem -LiteralPath "$Original/logs" -File) { if ($file.Length -ne 0) { throw 'Expected empty logs' } }
$captures = @(Get-ChildItem -LiteralPath "$Original/captures" -Filter '*.json' -File)
if ($captures.Count -ne 44) { throw 'Expected 44 capture records' }
foreach ($capture in $captures) {
foreach ($screen in (Json $capture.FullName).screenshots) {
AssertFile $Original $screen
$bytes = [IO.File]::ReadAllBytes((Join-Path $Original $screen.path))
if ($screen.mime -ne 'image/jpeg' -or $bytes[0] -ne 255 -or $bytes[1] -ne 216 -or $bytes[2] -ne 255) { throw 'Unexpected capture format' }
}
}
$actions = Json "$Original/action-observations.json"
$actionNames = @($actions.observations.capture | Sort-Object)
$captureNames = @($captures | ForEach-Object { 'captures/' + $_.Name } | Sort-Object)
if (($actionNames -join "`n") -cne ($captureNames -join "`n")) { throw 'Action/capture membership differs' }
foreach ($kind in @('seed','baseline')) {
foreach ($file in (Json "$Original/$kind-manifest.json").files) { AssertFile "$Original/$kind" $file }
}
$snapshot = Json "$Original/snapshots/renamed-before-model-undo.json"
$sourceChecks = @()
foreach ($file in (Json "$Original/baseline-manifest.json").files) {
$baseline = [IO.File]::ReadAllText((Join-Path "$Original/baseline" $file.path))
$expected = [regex]::Replace($baseline, '\bassess_report\b', 'assess_report_union')
$edits = [regex]::Matches($baseline, '\bassess_report\b').Count
if ($snapshot.accepted.files.($file.path) -cne $expected) { throw "Snapshot mismatch: $($file.path)" }
foreach ($dir in @('fixture','oracle-model-equivalence-20260913/accepted','oracle-model-equivalence-20260913/command-renamed')) {
$actualBytes = [IO.File]::ReadAllBytes((Join-Path "$Original/$dir" $file.path))
$expectedBytes = [Text.UTF8Encoding]::new($false).GetBytes($expected)
if ([Convert]::ToBase64String($actualBytes) -cne [Convert]::ToBase64String($expectedBytes)) { throw "Source mismatch: $dir/$($file.path)" }
}
if ((Hash (Join-Path "$Original/baseline" $file.path)) -ne (Hash (Join-Path "$Original/oracle-model-equivalence-20260913/baseline" $file.path))) { throw 'CLI baseline mismatch' }
$sourceChecks += [ordered]@{path=$file.path; substitutions=$edits; snapshotAndFinalAndCliExact=$true}
}
if (($sourceChecks.substitutions | Measure-Object -Sum).Sum -ne 6) { throw 'Expected six substitutions' }
$cli = Json "$Original/oracle-model-equivalence-20260913/receipt.json"
if ($cli.commands.Count -ne 6 -or @($cli.commands | Where-Object exit_code -ne 0).Count -or $cli.cli_sha256_before -ne $cli.cli_sha256_after) { throw 'CLI receipt mismatch' }
$checks = @('check-baseline','check-accepted','check-command-copy') | ForEach-Object { Json "$Original/oracle-model-equivalence-20260913/$_.stdout.txt" }
foreach ($check in $checks) { if (@($check.diagnostics | Where-Object severity -eq 'error').Count -or @($check.diagnostics | Where-Object severity -eq 'warning').Count -ne 11) { throw 'Unexpected CLI diagnostics' } }
$diagnosticSets = @($checks | ForEach-Object { ,@($_.diagnostics | ForEach-Object { @($_.severity,$_.code,$_.object_id,$_.field,$_.message) -join '|' } | Sort-Object) })
foreach ($set in $diagnosticSets) { if (($set -join "`n") -cne ($diagnosticSets[0] -join "`n")) { throw 'Diagnostic identities/messages changed' } }
$copied = @()
$originalFiles = @(Get-ChildItem -LiteralPath $Original -File)
foreach ($dir in @('seed','baseline','fixture','snapshots','evidence','logs','oracle-model-equivalence-20260913')) { $originalFiles += @(Get-ChildItem -LiteralPath "$Original/$dir" -Recurse -File) }
$originalFiles += $captures
foreach ($file in $originalFiles) {
$relative = [IO.Path]::GetRelativePath($Original,$file.FullName).Replace('\','/')
$target = Join-Path $destination $relative
[IO.Directory]::CreateDirectory([IO.Path]::GetDirectoryName($target)) | Out-Null
if (Test-Path -LiteralPath $target) { throw "Do not overwrite archive: $target" }
Copy-Item -LiteralPath $file.FullName -Destination $target
if ((Hash $file.FullName) -ne (Hash $target)) { throw 'Copy mismatch' }
$copied += [ordered]@{path=$relative; bytes=$file.Length; sha256=(Hash $target)}
}
Copy-Item -LiteralPath $Review -Destination "$destination/independent-review.md"
if ((Hash $Review) -ne (Hash "$destination/independent-review.md")) { throw 'Review copy mismatch' }
Add-Type -AssemblyName System.IO.Compression.FileSystem
[IO.Compression.ZipFile]::CreateFromDirectory("$Original/captures", "$destination/captures.zip", [IO.Compression.CompressionLevel]::Optimal, $false)
$zip = [IO.Compression.ZipFile]::OpenRead("$destination/captures.zip")
$captureManifest = @()
try {
if ($zip.Entries.Count -ne 88) { throw 'Expected 88 capture ZIP entries' }
foreach ($entry in $zip.Entries) {
$stream = $entry.Open()
try { $sha = [Security.Cryptography.SHA256]::Create(); try { $digest = [Convert]::ToHexString($sha.ComputeHash($stream)).ToLowerInvariant() } finally { $sha.Dispose() } } finally { $stream.Dispose() }
$originalFile = Get-Item -LiteralPath (Join-Path "$Original/captures" $entry.FullName)
if ($entry.Length -ne $originalFile.Length -or $digest -ne (Hash $originalFile.FullName)) { throw 'ZIP mismatch' }
$captureManifest += [ordered]@{path=$entry.FullName; bytes=$entry.Length; sha256=$digest}
}
} finally { $zip.Dispose() }
$captureManifest | ConvertTo-Json -Depth 8 | Set-Content -LiteralPath "$destination/capture-manifest.json" -Encoding utf8
[ordered]@{verifiedUtc=[DateTime]::UtcNow.ToString('o'); source=$inputRecord.source_commit; immutableInputsChecked=15; currentBuildInputsChecked=577; beforeAfterBuildInputsEqual=$true; capturesChecked=44; zipEntriesChecked=88; actionMappingsChecked=44; binaryBytes=115379712; binarySha256=$inputRecord.binary_copy_sha256; closeExitCode=$close.exit_code; sourceChecks=$sourceChecks; cliCommandsPassed=6; cliWarningsPerCheck=11; cliDiagnosticIdentitiesAndMessagesEqual=$true; reviewSha256=(Hash $Review); copiedFiles=$copied; limits='Checks preserved source bytes, receipts and artifacts; no compiler, native inputs, or direct runtime Project export executed by archivist.'} | ConvertTo-Json -Depth 12 | Set-Content -LiteralPath "$destination/verification.json" -Encoding utf8
Write-Output "Verified 15 immutable inputs, 44 JPEGs, 88 ZIP entries, 44 action mappings, six source files, six CLI receipts; copied $($copied.Count) raw files."