param([Parameter(Mandatory)][string]$EvidenceDir,[Parameter(Mandatory)][string]$Before,[Parameter(Mandatory)][string]$After,[Parameter(Mandatory)][string]$Baseline,[string]$Source=(Join-Path $PSScriptRoot 'final-common.ps1')) $ErrorActionPreference='Stop' New-Item -ItemType Directory -Path $EvidenceDir -Force|Out-Null $checks=[Collections.Generic.List[object]]::new() function Record($Id,$Passed,$Actual){$checks.Add(@{id=$Id;passed=[bool]$Passed;actual=$Actual})} function Definition($Path,$Name){$ast=[Management.Automation.Language.Parser]::ParseFile($Path,[ref]$null,[ref]$null);return $ast.Find({param($n)$n-is[Management.Automation.Language.FunctionDefinitionAst]-and$n.Name-eq$Name},$true).Extent.Text} foreach($name in @('BallPoint','BallClear','WorldSafe','Same','AssertNativeTranslation','AssertNativeMerge')){ $expected=(Definition $Source $name).Replace("function $name","function global:$name") . ([scriptblock]::Create($expected)) Record "$name-production-body-identity" ((Get-Command $name).ScriptBlock.Ast.Extent.Text-ceq$expected) $Source } function HashText($Text){return [Convert]::ToHexString([Security.Cryptography.SHA256]::HashData([Text.Encoding]::UTF8.GetBytes($Text)))} foreach($name in @('NativePointer','NativeMoveAndHold','AssertNativeTranslation','AssertNativeMerge')){Record "$name-contract-unchanged" ((Definition $Source $name)-ceq(Definition $Baseline $name)) @{baseline=$Baseline;beforeSha256=(HashText (Definition $Baseline $name));afterSha256=(HashText (Definition $Source $name))}} $script:resolution='Physical size: 1080x2400';$script:adbCalls=0 function Adb($Arguments){$script:adbCalls++;return $script:resolution} function Check($Id,$Passed,$Actual){if(!$Passed){throw "$Id : $Actual"}} function Ball($Id,$X,$Y,$Z){return [pscustomobject]@{id=$Id;position=[pscustomobject]@{x=$X;y=$Y;z=$Z}}} function Board($Balls){return [pscustomobject]@{balls=@($Balls);groups=@([pscustomobject]@{id='same';ballIds=@($Balls.id)});camera=[pscustomobject]@{target=[pscustomobject]@{x=0;y=.6;z=0};rotation=[pscustomobject]@{x=0;y=0;z=0;w=1};distance=8}}} try{ $beforeState=Get-Content -LiteralPath $Before -Raw|ConvertFrom-Json;$afterState=Get-Content -LiteralPath $After -Raw|ConvertFrom-Json $b=@($beforeState.puzzleStates|Where-Object stageId -eq 16)[0];$a=@($afterState.puzzleStates|Where-Object stageId -eq 16)[0] Record 'integer-max-overload-reproduced-and-double-preserves-radius' ([Math]::Max(0,.25-.09)-eq0-and[Math]::Abs([Math]::Max(0.0,.25-.09)-.16)-lt1e-12) @{integerMax=[Math]::Max(0,.25-.09);doubleMax=[Math]::Max(0.0,.25-.09)} $point=BallPoint $b 's16-b02' Record 'captured-wrong-source-pixel-rejected' (!(BallClear $b 's16-b02')-and$point[0]-eq733-and$point[1]-eq346) @{point=$point;requested='s16-b02';actualMoved='s16-b05'} $errorText=$null;try{AssertNativeMerge 'captured' $b $a 's16-b02'}catch{$errorText=$_.Exception.Message} Record 'captured-wrong-source-strict-merge-still-rejected' ($errorText-match'requested-source-actually-moved') $errorText foreach($case in @( @{id='single';balls=@((Ball 'target' 0 1.25 0));clear=$true}, @{id='front';balls=@((Ball 'target' 0 1.25 0),(Ball 'front' 0 1.25 -1));clear=$false}, @{id='behind';balls=@((Ball 'target' 0 1.25 0),(Ball 'behind' 0 1.25 1));clear=$true}, # Target projects to1200.45 and rounds1200. Center ray misses the left sphere, # while the actual pixel ray intersects it. Geometry expectations are analytic. @{id='rounded-pixel-front';balls=@((Ball 'target' .004 1.25 0),(Ball 'front' -.497 1.25 -1));clear=$false}, @{id='rounded-pixel-outside';balls=@((Ball 'target' .004 1.25 0),(Ball 'front' -.501 1.25 -1));clear=$true}, @{id='exact-tangent-front';balls=@((Ball 'target' 0 1.25 0),(Ball 'front' -.5 1.25 -1));clear=$false}, @{id='equal-entry-ambiguous';balls=@((Ball 'target' 0 1.25 0),(Ball 'same' 0 1.25 0));clear=$false}, @{id='behind-camera';balls=@((Ball 'target' 0 1.25 -9));clear=$false}, @{id='unsafe-ui';balls=@((Ball 'target' 20 1.25 0));clear=$false} )){$board=Board $case.balls;$snapshot=$board|ConvertTo-Json -Depth 12;$actual=BallClear $board 'target';Record $case.id ($actual-eq$case.clear-and($board|ConvertTo-Json -Depth 12)-ceq$snapshot) @{expected=$case.clear;actual=$actual}} foreach($kind in @('missing','duplicate')){ $board=Board @((Ball 'target' 0 1.25 0));if($kind-eq'duplicate'){$board.balls+=Ball 'target' 0 1.25 1} $script:adbCalls=0;$rejected=$false;try{BallClear $board $(if($kind-eq'missing'){'absent'}else{'target'})|Out-Null}catch{$rejected=$_.Exception.Message-match'exactly one existing ball ID'} Record "$kind-ID-rejected-before-projection-input" ($rejected-and$script:adbCalls-eq0) $kind } $script:resolution='unavailable';$rejected=$false;try{BallClear (Board @((Ball 'target' 0 1.25 0))) 'target'|Out-Null}catch{$rejected=$_.Exception.Message-match'Unknown device resolution'} Record 'unknown-resolution-rejected' $rejected $script:resolution }catch{Record 'production-evaluation' $false $_.Exception.Message} $passed=$checks.Count-gt0-and@($checks|Where-Object passed -ne $true).Count-eq0 @{passed=$passed;scope='Offline actual function bodies and captured wrong-source save. Analytic edge cases are counterfactual; no native raycast or product pass claim.';source=$Source;sourceSha256=(Get-FileHash $Source).Hash;before=$Before;beforeSha256=(Get-FileHash $Before).Hash;after=$After;afterSha256=(Get-FileHash $After).Hash;checks=$checks.ToArray()}|ConvertTo-Json -Depth 12|Set-Content (Join-Path $EvidenceDir 'pixel-ray-result.json') if(!$passed){exit 1};exit 0