Retain aircraft through native landing and qualify bounded input diagnostics

This commit is contained in:
2026-09-19 20:34:18 +02:00
parent f870443b9b
commit 2fba12f987
129 changed files with 50369 additions and 88 deletions
+65
View File
@@ -230,4 +230,69 @@ class GateChoicesRunner(unittest.TestCase):
with self.assertRaises(ValueError):wrap(native[:-2]+['-errOrdinaryGateChoices',NONCE])
with self.assertRaises(ValueError):wrap(native+['-errOrdinaryGateChoices',NONCE],False)
class SelectionRunner(unittest.TestCase):
def make_selection(self,folder):
session,context,report,observation=fixtures.ExerciseTests.make_proof(self,folder)
context.update(look_requested=True,approach_requested=True,alignment_requested=True,selection_requested=True,approach_module_sha256=r.approach_module_hashes(r.ROOT),alignment_module_sha256=r.alignment_module_hashes(r.ROOT),selection_module_sha256=r.selection_module_hashes(r.ROOT))
report.update({k:context[k] for k in ('look_requested','approach_requested','alignment_requested','selection_requested','approach_module_sha256','alignment_module_sha256','selection_module_sha256')})
report.update(look_proof={},facing_proof={},action_selection_proof={'wheel':{'down_monotonic':31.,'up_monotonic':31.2}},wheel_events=[{'button':5,'down':True,'sent':True,'monotonic':31.},{'button':5,'down':False,'sent':True,'monotonic':31.2}])
report['events']=report['events'][:2];report['observer']['events']=['READY'];report['approach_proof']={'events':copy.deepcopy(report['events'])}
(session/'console.log').write_text('native selection')
return session,context,report,observation
def test_selection_requires_alignment_and_native_choices(self):
with self.assertRaises(ValueError):r.validate_input_exercise(SimpleNamespace(exercise_prison_selection=True))
with self.assertRaises(ValueError):r.validate_input_exercise(SimpleNamespace(exercise_prison_selection=True,exercise_prison_alignment=True))
with tempfile.TemporaryDirectory() as folder:
root=Path(folder);(root/'tools').mkdir();profile=root/'profile';profile.mkdir()
names=('headless_input_proof.py','headless_display_probe.py','prison_approach_proof.py','ordinary_gate_evidence.py','ordinary_look_evidence.py','prison_approach_evidence.py','prison_alignment_proof.py','prison_alignment_evidence.py','ordinary_gate_choices.py','prison_action_selection_proof.py','prison_action_selection_evidence.py')
for name in names:(root/'tools'/name).write_text('# fake')
native=['gamescope','--backend','headless','--','/proton','run','/game','-errOrdinaryInputObserve',NONCE,'-errOrdinaryLookObserve',NONCE,'-errOrdinaryGateObserve',NONCE]
for has_choices in (False,True):
args=native+(['-errOrdinaryGateChoices',NONCE] if has_choices else [])
wrapped,display=r.display_probe_command(args,root,Path('/compat'),profile,Path('/game'),NONCE,':0')
call=(wrapped,root,Path('/compat'),profile,Path('/game'),NONCE,':0',display,True,True,True,True)
if not has_choices:
with self.assertRaises(ValueError):r.input_exercise_command(*call)
else:
cmd,context=r.input_exercise_command(*call);self.assertIn('--enable-private-selection-proof',cmd);self.assertEqual(set(context['selection_module_sha256']),set(names[-3:]))
def test_raw_selection_validator_owns_success_and_prior_failure_survives(self):
for accepted,prior in ((True,'game-started'),(False,'game-started'),(True,'cleanup-failed')):
with tempfile.TemporaryDirectory() as folder:
session,context,report,observation=self.make_selection(Path(folder));Path(context['report']).write_text(json.dumps(report))
approach=ModuleType('prison_approach_evidence');approach.validate_approach_evidence=lambda *a:{'verified':True}
selected=ModuleType('prison_action_selection_evidence');calls=[]
def validate(*args):calls.append(args);return {'verified':accepted}
selected.validate_selection_evidence=validate
with patch.dict(sys.modules,{'prison_approach_evidence':approach,'prison_action_selection_evidence':selected}):
outcome,proof=r.input_exercise_result(prior,context,session,observation,{'verified':True})
self.assertEqual(calls,[('native selection',NONCE,report['look_proof'],report['approach_proof'],report['facing_proof'],report['action_selection_proof'])]);self.assertEqual(proof['verified'],accepted)
self.assertEqual(outcome,'input-exercise-incomplete' if not accepted and prior=='game-started' else prior)
def test_changed_hash_or_unconfirmed_unpaired_extra_wheel_refuses(self):
for fault in ('hash','held','release','extra','wrong_button','unsent','time','finally'):
with tempfile.TemporaryDirectory() as folder:
session,context,report,observation=self.make_selection(Path(folder))
if fault=='hash':report['selection_module_sha256']={}
elif fault=='held':report['unconfirmed_held_button']=5
elif fault=='release':report['wheel_release_errors']=['failed']
elif fault=='extra':report['wheel_events'].append(dict(report['wheel_events'][-1]))
elif fault=='wrong_button':report['wheel_events'][0]['button']=4
elif fault=='unsent':report['wheel_events'][0]['sent']=False
elif fault=='time':report['wheel_events'][0]['monotonic']=30.
else:report['wheel_events'][1]['finally']=True
Path(context['report']).write_text(json.dumps(report))
approach=ModuleType('prison_approach_evidence');approach.validate_approach_evidence=lambda *a:{'verified':True}
selected=ModuleType('prison_action_selection_evidence');selected.validate_selection_evidence=lambda *a:(_ for _ in ()).throw(AssertionError('malformed wheel reached validator'))
with patch.dict(sys.modules,{'prison_approach_evidence':approach,'prison_action_selection_evidence':selected}):
outcome,proof=r.input_exercise_result('game-started',context,session,observation,{'verified':True})
self.assertFalse(proof['verified'],fault)
def test_unrequested_wheel_and_facing_do_not_qualify(self):
for payload in ({'selection_requested':True},{'selection_requested':1},{'wheel_events':[{}]},{'action_selection_proof':{}},{'facing_proof':{}}):
with tempfile.TemporaryDirectory() as folder:
session,context,report,observation=fixtures.ExerciseTests.make_proof(self,Path(folder));report.update(payload);Path(context['report']).write_text(json.dumps(report))
outcome,proof=r.input_exercise_result('game-started',context,session,observation,{'verified':True});self.assertFalse(proof['verified'])
if __name__=='__main__':unittest.main()