from pathlib import Path import hashlib,json,shutil,subprocess,sys r=Path('/home/jakub/devel/escapistsrereintroduced');b=Path('/tmp/erri-gameplay-root-2237') e=r/'docs/evidence/hunter-capture-2026-10-02';ne=r/'docs/evidence/native-2026-10-02-hunter-capture-normal' load=lambda p:json.loads(p.read_text()) sha=lambda p:hashlib.sha256(p.read_bytes()).hexdigest() def write(p,v):p.write_text(json.dumps(v,indent=2)+'\n') baseline=load(b/'baseline.json');suite=load(b/'suite-result.json');inputs=load(b/'suite-inputs.json') assert suite['exit']==0 and suite['inputs_unchanged'] and suite['regression_programs']==292 assert len({x['path'] for x in suite['programs']})==292 and all(x['exit']==0 for x in suite['programs']) assert all(sha(r/n)==h for n,h in inputs.items()) sys.path.insert(0,str(r/'tools'));from source_manifest import addon_manifest source=addon_manifest(r);nr=load(ne/'runner.json.txt');report=load(ne/'report.json') assert source==load(ne/'source-sha256.json')==load(ne/'launch-source-sha256.json') assert report['assertions_passed']==63 and report['smoke_completions']==1 and not report['script_or_runtime_failures'] and len(report['engine_errors'])==13 assert nr['cleanup_confirmed'] and nr['source_unchanged_after_run'] and nr['external_addons_unchanged_after_run'] assert sha(ne/'console.log.txt')==nr['console_sha256'] allowed={'tests/test_convoy_survivors.py','addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyService.c','addons/core/Scripts/Game/ERR/10_AI/ERR_HunterService.c','tests/test_hunter_lifecycle.py','tools/check.py'} changed=[n for n,h in baseline['files'].items() if not (r/n).is_file() or sha(r/n)!=h] assert set(changed)==allowed,changed index=hashlib.sha256(subprocess.check_output(['git','diff','--cached','--binary'],cwd=r)).hexdigest();assert index==baseline['index_diff_sha256'] original=load(Path('/tmp/erri-heartbeat-20260930-1542-reference.json')) assert all(sha(Path('/home/jakub/devel/escapists')/n)==h for n,h in original.items()) candidate=r/'.build/playtest-2026-10-02-convoy-survivors' seal=load(r/'docs/evidence/playtest-refresh-2026-10-02-convoy-survivors/candidate-sha256.json') assert {str(p.relative_to(candidate)):sha(p) for p in candidate.rglob('*') if p.is_file()}==seal e.mkdir(exist_ok=False) for n in ['baseline.json','suite-result.json','suite-inputs.json','regressions.log','run-suite.py','native-normal.log','finish.py']:shutil.copyfile(b/n,e/n) shutil.copytree(b/'aborted-preintegration-check',e/'aborted-preintegration-check') for folder,name in [('/tmp/erri-hunter-capture-2237','proposal'),('/tmp/erri-hunter-capture-review-2237','independent'),('/tmp/erri-hunter-capture-admission-2237','sdk-review')]: shutil.copytree(folder,e/name,ignore=shutil.ignore_patterns('__pycache__','*.pyc')) write(e/'source-after.json',source) result={'kind':'Active original hunter capture fix','authored_files':len(source),'regression_programs':292,'normal_assertions':63,'normal_completions':1,'normal_script_failures':0,'normal_engine_errors':13,'cleanup_source_external_unchanged':True,'strict_native_failure_retained':True,'native_capture_callback_tested':False,'multiplayer_tested':False,'performance_tested':False,'new_package_created':False,'latest_candidate_preserved_files':len(seal),'original_reference_files_unchanged':len(original),'baseline_paths':len(baseline['files']),'changed_existing_paths':changed,'added_test':'tests/test_hunter_capture.py','index_diff_sha256':index,'scope':'Current admitted player entering active tracked hunter; entry before native callbacks latches capture and releases existing HQ ownership. Already-released infantry roles remain independent. No replacement/refund or actor deletion.','limits':'Actual-method regression doubles native boundaries; normal native run verifies compilation and base-loop integration, not player capture timing or remote-client behavior.'} write(e/'review.json',result) status=r/'docs/current-status.md';before=status.read_text();first,tail=before.split('\n',1) section='''**2 October 2026 — active hunter capture is remembered at vehicle entry:** when a current admitted player enters an active original HQ hunter vehicle, the server records capture before native entry callbacks can change player ownership. The existing driving/recovery order and HQ registration are released once, even if current occupancy disappears before the next one-second poll. Vehicles, crew and spent deployment allowances remain physical and unchanged. Entering an already-released vehicle does not revoke its former crew’s independent infantry role. All **292 registered regression programs pass**. Independent actual-method tests reproduce the old event gap and a missing survivor-retention guard, then pass with the fix. The installed SDK signature and callback ordering are verified. A hidden/muted normal Everon run completes **63 assertions and one round**, with **zero script/runtime failures and thirteen retained engine errors**, confirmed cleanup and unchanged inputs. This proves compilation and ordinary-loop integration; native capture-event timing, remote multiplayer and performance remain unverified. The existing convoy-survivors package is unchanged and predates this source fix. Original missions and inherited work are preserved; nothing was committed or published. [Implementation and evidence](evidence/hunter-capture-2026-10-02/review.json). ''' assert sha(status)==baseline['files']['docs/current-status.md'] status.write_text(first+'\n\n'+section+'\n'+tail.lstrip('\n')) write(e/'documentation.json',{'before':baseline['files']['docs/current-status.md'],'after':sha(status)}) write(e/'evidence-sha256.json',{str(p.relative_to(e)):sha(p) for p in sorted(e.rglob('*')) if p.is_file()}) print(json.dumps(result,indent=2))