Fix native reentry proof for stage-keyed progress slots

This commit is contained in:
NINI
2026-10-10 06:56:53 +09:00
parent 4941dcab52
commit 4184023769
2 changed files with 105 additions and 2 deletions
+16 -1
View File
@@ -38,6 +38,21 @@ function Same($First,$Second){
return $records[0]-ceq$records[1]
}catch{return $false}
}
function SameProgress($First,$Second){
# Save slots are keyed by unique stageId; preserve every other array's strict order.
try{
$firstCopy=Clone $First;$secondCopy=Clone $Second
foreach($copy in @($firstCopy,$secondCopy)){
if($copy-isnot[pscustomobject]-or$copy.PSObject.Properties.Name-cnotcontains'puzzleStates'-or$copy.puzzleStates-isnot[array]-or$copy.puzzleStates.Count-gt30){return $false}
$ids=[Collections.Generic.HashSet[long]]::new()
foreach($slot in $copy.puzzleStates){
if($slot-isnot[pscustomobject]-or$slot.PSObject.Properties.Name-cnotcontains'stageId'-or($slot.stageId-isnot[long]-and$slot.stageId-isnot[int])-or$slot.stageId-lt1-or$slot.stageId-gt30-or!$ids.Add([long]$slot.stageId)){return $false}
}
$copy.puzzleStates=@($copy.puzzleStates|Sort-Object stageId)
}
return Same $firstCopy $secondCopy
}catch{return $false}
}
function Slot($State,[string]$Type,[int]$Stage){if($Type-eq'free'){return $State.latestFreePlay};return @($State.puzzleStates|Where-Object stageId -eq $Stage)[0]}
function SameBalls($First,$Second,[double]$Tolerance=.004){
if((($First.balls.id|Sort-Object)-join',')-ne(($Second.balls.id|Sort-Object)-join',')){return $false}
@@ -204,7 +219,7 @@ try {
@{name=$fixture.name;entryObservationMilliseconds=$watch.Elapsed.TotalMilliseconds;editorEntryMilliseconds=$fixture.editorEntryMilliseconds;method='Native wall time includes process launch/home/readiness/UI/ADB/save pull; does not isolate GameApp entry CPU';utc=[DateTime]::UtcNow.ToString('o')}|ConvertTo-Json|Set-Content -LiteralPath (Join-Path $EvidenceDir "$($fixture.name)-timing.json")
Step "$($fixture.name)-home-again" @('shell','input','tap','312','108')
if($fixture.slot-eq'free'){Step "$($fixture.name)-reenter" @('shell','input','tap','1200','810')}else{SelectStage "$($fixture.name)-reenter" $fixture.stage}
Check "$($fixture.name)-reentry-exact" (Same $after (Save "$($fixture.name)-reentered")) 'Repair/reset is stable and cannot repeatedly shift or change other slots'
Check "$($fixture.name)-reentry-exact" (SameProgress $after (Save "$($fixture.name)-reentered")) 'Repair/reset is stable; only unique stage-keyed puzzle slot order may differ, all nested values and arrays remain exact'
}
foreach($fixture in $fixtures.drags){
$state=FixtureState $fixture.source 'free' 1;$before=LoadFixture $fixture.name $state 'free' 1;$board=$before.latestFreePlay