nmarshall commited on
Commit
2d840a0
·
1 Parent(s): 6d0ce63

qvm: recover session initialization lifecycle

Browse files
docs/FINDINGS.md CHANGED
@@ -1709,3 +1709,6 @@ RE-813–822 replaces the scoreboard decimal assumption with actual37914 executi
1709
 
1710
 
1711
  **RE-903:** Rust matches144 actual247219/scanner/atoi/mode/position-load compositions, preserving ignored parse result, explicit caller scratch, positive-only booleans and final team/flag gate. Ignore entries accumulate without clearing and invalid numeric text addresses slot0. State and selector stage atomically on unsupported domains. Native cvars/files, real scratch provenance and full map reload remain open. [Evidence](research/RUST_SESSION_RESTORE.md).
 
 
 
 
1709
 
1710
 
1711
  **RE-903:** Rust matches144 actual247219/scanner/atoi/mode/position-load compositions, preserving ignored parse result, explicit caller scratch, positive-only booleans and final team/flag gate. Ignore entries accumulate without clearing and invalid numeric text addresses slot0. State and selector stage atomically on unsupported domains. Native cvars/files, real scratch provenance and full map reload remain open. [Evidence](research/RUST_SESSION_RESTORE.md).
1712
+
1713
+
1714
+ **RE-904:** 96 actual247520 compositions execute team classification, userinfo lookup, bounded copy, saved-position load and session serialization. Team/default/capacity policy, wrapping timeout arithmetic, native tick snapshot, byte-only versus word clears,36-byte text initialization and64 ignored-client clears are recovered. Existing position fields persist unless the recovered load succeeds. Diagnostic7259 and engine/file operations remain captured/supplied; caller authentication and post-initialization behavior remain open. [Evidence](research/QVM_SESSION_INIT.md).
docs/PROVISIONAL_TODO.md CHANGED
@@ -1746,3 +1746,6 @@ RE-903: Rust matches144 actual247219/scanner/atoi/mode/position-load composition
1746
 
1747
 
1748
  RE-894–903 completed bounded userinfo/scanner/saved-file/session-restore source and Rust contracts. RE-904 tracks remaining numeric/scratch domains, real reload and native IO/runtime integration. [Batch and next work](research/QVM_SAVED_RESTORE_BATCH.md).
 
 
 
 
1746
 
1747
 
1748
  RE-894–903 completed bounded userinfo/scanner/saved-file/session-restore source and Rust contracts. RE-904 tracks remaining numeric/scratch domains, real reload and native IO/runtime integration. [Batch and next work](research/QVM_SAVED_RESTORE_BATCH.md).
1749
+
1750
+
1751
+ RE-904: 96 actual247520 compositions execute team classification, userinfo lookup, bounded copy, saved-position load and session serialization. Team/default/capacity policy, wrapping timeout arithmetic, native tick snapshot, byte-only versus word clears,36-byte text initialization and64 ignored-client clears are recovered. Existing position fields persist unless the recovered load succeeds. Diagnostic7259 and engine/file operations remain captured/supplied; caller authentication and post-initialization behavior remain open. Full runtime completion remains open. [Evidence](research/QVM_SESSION_INIT.md).
docs/RESEARCH_LEDGER.md CHANGED
@@ -2235,3 +2235,8 @@ Rust matches144 actual247219/scanner/atoi/mode/position-load compositions, prese
2235
  ### RE-894–903 full batch validation (2026-10-28)
2236
 
2237
  After the tenth commit, `cargo xtask test-full --since 6e01995b` passed with the flake-declared Nix Python: 1,753 Python tests,199 Rust tests (assets10, gameplay159, xtask30),22 affected report producers regenerated twice deterministically, storage policy,469 documentation link checks and whitespace guards. No generated-report drift. Ten task commits since6e01995b; results are amended into the tenth commit. [Findings and next work](research/QVM_SAVED_RESTORE_BATCH.md).
 
 
 
 
 
 
2235
  ### RE-894–903 full batch validation (2026-10-28)
2236
 
2237
  After the tenth commit, `cargo xtask test-full --since 6e01995b` passed with the flake-declared Nix Python: 1,753 Python tests,199 Rust tests (assets10, gameplay159, xtask30),22 affected report producers regenerated twice deterministically, storage policy,469 documentation link checks and whitespace guards. No generated-report drift. Ten task commits since6e01995b; results are amended into the tenth commit. [Findings and next work](research/QVM_SAVED_RESTORE_BATCH.md).
2238
+
2239
+
2240
+ ## 2026-10-28 — RE-904 Original session initialization and immediate persistence
2241
+
2242
+ 96 actual247520 compositions execute team classification, userinfo lookup, bounded copy, saved-position load and session serialization. Team/default/capacity policy, wrapping timeout arithmetic, native tick snapshot, byte-only versus word clears,36-byte text initialization and64 ignored-client clears are recovered. Existing position fields persist unless the recovered load succeeds. Diagnostic7259 and engine/file operations remain captured/supplied; caller authentication and post-initialization behavior remain open. Focused `cargo xtask test-group qvm-session-init` passes (4 Python tests); selected reports regenerate twice deterministically, with storage, documentation links and whitespace guards. Full suite deferred to task ten. Original assets unchanged; source fixtures do not establish complete native/runtime parity.
docs/REVERSE_ENGINEERING_TODO.md CHANGED
@@ -1783,3 +1783,6 @@ Purpose: turn the supplied installation into an evidence-backed specification of
1783
 
1784
 
1785
  - [ ] RE-904 Complete numeric/fatal/alias domains, scratch provenance, real reload and native IO/runtime integration ([next tasks](research/QVM_SAVED_RESTORE_BATCH.md)).
 
 
 
 
1783
 
1784
 
1785
  - [ ] RE-904 Complete numeric/fatal/alias domains, scratch provenance, real reload and native IO/runtime integration ([next tasks](research/QVM_SAVED_RESTORE_BATCH.md)).
1786
+
1787
+
1788
+ - [x] RE-904 Original session initialization and immediate persistence ([evidence](research/QVM_SESSION_INIT.md)).
docs/research/QVM_SESSION_INIT.md ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ # Original session initialization and immediate persistence
2
+
3
+ RE-904. Reproduce with `python3 scripts/analyze_qvm_session_init.py`; focused validation: `cargo xtask test-group qvm-session-init`. [Machine report](qvm-session-init.json).
4
+
5
+ 96 actual247520 compositions execute team classification, userinfo lookup, bounded copy, saved-position load and session serialization. Team/default/capacity policy, wrapping timeout arithmetic, native tick snapshot, byte-only versus word clears,36-byte text initialization and64 ignored-client clears are recovered. Existing position fields persist unless the recovered load succeeds. Diagnostic7259 and engine/file operations remain captured/supplied; caller authentication and post-initialization behavior remain open.
6
+
7
+ Original executable/native runtime and complete Linux/macOS Rust/Bevy/Solari acceptance remain unverified.
docs/research/README.md CHANGED
@@ -1318,3 +1318,6 @@ The extension collector adds five focused tests for native tail calls, command-r
1318
 
1319
 
1320
  [RE-894–903 saved-position and session restore batch](QVM_SAVED_RESTORE_BATCH.md).
 
 
 
 
1318
 
1319
 
1320
  [RE-894–903 saved-position and session restore batch](QVM_SAVED_RESTORE_BATCH.md).
1321
+
1322
+
1323
+ [RE-904: Original session initialization and immediate persistence](QVM_SESSION_INIT.md).
docs/research/qvm-resumer-audit.json CHANGED
@@ -8919,17 +8919,6 @@
8919
  "repeated_calls_opt_in": false,
8920
  "repeated_calls_setting": "default_false"
8921
  },
8922
- {
8923
- "backward_conditional_branches": [],
8924
- "calls": [],
8925
- "explicit_result_offsets": null,
8926
- "helper": "qvm_trace_support.resume",
8927
- "line": 39,
8928
- "literal_range": null,
8929
- "path": "scripts/qvm_lifecycle_support.py",
8930
- "repeated_calls_opt_in": false,
8931
- "repeated_calls_setting": "default_false"
8932
- },
8933
  {
8934
  "backward_conditional_branches": [],
8935
  "calls": [],
@@ -10036,10 +10025,10 @@
10036
  }
10037
  },
10038
  "summary": {
10039
- "call_expressions": 203,
10040
- "files": 155,
10041
- "legacy_expressions": 158,
10042
- "nonliteral_ranges": 28,
10043
  "unresolved_mode_expressions": 3
10044
  }
10045
  }
 
8919
  "repeated_calls_opt_in": false,
8920
  "repeated_calls_setting": "default_false"
8921
  },
 
 
 
 
 
 
 
 
 
 
 
8922
  {
8923
  "backward_conditional_branches": [],
8924
  "calls": [],
 
10025
  }
10026
  },
10027
  "summary": {
10028
+ "call_expressions": 202,
10029
+ "files": 154,
10030
+ "legacy_expressions": 157,
10031
+ "nonliteral_ranges": 27,
10032
  "unresolved_mode_expressions": 3
10033
  }
10034
  }
docs/research/qvm-session-init.json ADDED
The diff for this file is too large to render. See raw diff
 
scripts/analyze_qvm_session_init.py ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Execute the verified original QVM body; native effects are supplied or captured."""
3
+ import itertools
4
+ from pathlib import Path
5
+ from qvm_research_support import source,constants
6
+ from qvm_camera_world_support import B,run
7
+ from qvm_exit_rules_support import POOL,CPOOL
8
+ from analyze_qvm_acceleration import word,number
9
+ from analyze_qvm import write_json
10
+
11
+ def main():
12
+ q,raw,h,ins=source();rows=[]
13
+ from qvm_persistence_support import environment
14
+ from qvm_lifecycle_support import initialize,raw_state,SIZE
15
+ from qvm_byte_memory_support import write_bytes
16
+ from qvm_formatter_support import image_bytes
17
+ profiles=[(b'',0,0,0,100,11),(b'\\team\\s\\cl_guid\\ID',2,1,0,100,17),(b'\\team\\S\\cl_guid\\ID',2,2,2,100,19),(b'\\team\\spectator\\cl_guid\\ID',2,2,-1,2147483647,0xffffffff)]
18
+ for mode,team,profile,slot,handle in itertools.product([0,3,9],[0,2],range(4),[0,3],[0,7]):
19
+ info,limit,occupancy,seconds,now,ticks=profiles[profile];m,b=environment(raw,h);write_bytes(m,b,{a:raw[h['data_offset']+a] for a in range(83568,83824)});pointer=CPOOL+6336*slot
20
+ for j in range(0,SIZE,4):m[pointer+3096+j]=0xaabbccdd
21
+ m.update({pointer+3096:team,pointer+140:17+slot,34090788:mode,34089308:limit,34992584:occupancy,34085460:seconds,34992532:now,34992524:0,34064148:1})
22
+ before=raw_state(m,b,pointer);m,p,b=initialize(ins,m,b,pointer,info,handle,ticks);p.update(input=dict(mode=mode,team=team,profile=profile,slot=slot,handle=handle,info=info.hex(),limit=limit,occupancy=occupancy,seconds=seconds,now=now,ticks=ticks,before=before),raw=raw_state(m,b,pointer),ring=m[23708]&0xffffffff,info_ring=m[23712]&0xffffffff);rows.append(p)
23
+
24
+ write_json(Path('docs/research/qvm-session-init.json'),{'source':q['source'],'sha256':q['sha256'],'root':247520,'probes':rows,'limits':'96 actual247520 compositions execute team classification, userinfo lookup, bounded copy, saved-position load and session serialization. Team/default/capacity policy, wrapping timeout arithmetic, native tick snapshot, byte-only versus word clears,36-byte text initialization and64 ignored-client clears are recovered. Existing position fields persist unless the recovered load succeeds. Diagnostic7259 and engine/file operations remain captured/supplied; caller authentication and post-initialization behavior remain open.'})
25
+ if __name__=='__main__':main()
scripts/qvm_lifecycle_support.py CHANGED
@@ -1,40 +1,28 @@
1
- """Explicit finite fixtures for protected and mode10 lifecycle source ranges."""
2
- from qvm_health_effects_support import seed as health_seed,H,TARGET,ATTACKER,CLIENT,A_CLIENT
3
- from qvm_research_support import constants
4
- from qvm_trace_support import resume,captured
5
- from analyze_qvm_acceleration import word
6
- L=H+0xa0000
7
- EVENT=L+0x10000
8
- FIELDS=[4,12,44,76,84,104,140,144,148,184,208,220,232,236,280,3096,4300,4304,4308,4312,4380,4384,4388,4392,6324,6332]
9
- EFIELDS=[0,140,144,160,168,184,200,204,424]
10
 
11
- def seed(raw,h,**a):
12
- m=health_seed(raw,h)
13
- m.update(constants(raw,h,list(range(29584,29808,4))+list(range(4032,17416,4))))
14
- for o in range(0,180,4):m[L+o]=0
15
- m.update({L+72:TARGET,L+76:ATTACKER if a.get('attacker',True) else 0,L+80:a.get('flag',0),L+164:TARGET,L+168:ATTACKER,L+172:a.get('method',12),34090788:a.get('mode',10),34999596:a.get('blocked',0),34992532:a.get('now',10000),98588:a.get('disclose',0),34999668:7,34999672:9,34087532:a.get('penalty',1),34075396:a.get('limit',3),TARGET+168:65,ATTACKER+168:7,ATTACKER+764:a.get('strikes',0),ATTACKER+768:a.get('last',0),ATTACKER+424:a.get('attacker_flags',0)})
16
- for o in FIELDS:m[CLIENT+o]=a.get('c'+str(o),0x1ffff if o in (104,220,236) else 7)
17
- m.update({CLIENT+232:a.get('count',31990),CLIENT+6332:word(a.get('heat',10)),CLIENT+4:a.get('state',0),CLIENT+12:a.get('flags12',8),CLIENT+144:0,CLIENT+312:a.get('weapon',1),CLIENT+3096:a.get('team',1),A_CLIENT+3096:a.get('attacker_team',1),A_CLIENT+232:1234,A_CLIENT+140:7})
18
- return m
 
 
 
 
 
 
 
 
19
 
20
- def snapshot(m):
21
- return {'client':{str(o):m[CLIENT+o]&0xffffffff for o in FIELDS},'attacker_count':m[A_CLIENT+232]&0xffffffff,'entity':{str(o):m[TARGET+o]&0xffffffff for o in [684,720]},'attacker':{str(o):m[ATTACKER+o]&0xffffffff for o in [764,768]},'team_counts':[m[34999668]&0xffffffff,m[34999672]&0xffffffff]}
22
-
23
- def handlers(effects,resolvers=None):
24
- def event(ins,m,args):
25
- p=EVENT+len(effects['events'])*880
26
- for o in range(0,880,4):m[p+o]=0
27
- effects['events'].append({'arguments':args,'pointer':p,'fixture_allocation':True})
28
- return m,p,{'supplied_event_pointer':p,'original_allocator_not_executed':True}
29
- hs={t:captured(t,effects['requests']) for t in [7259,205260,6369,6439,278834,285486,-17,-18]}
30
- def predicate(ins,m,args):
31
- from qvm_contact_support import predicate as actual
32
- return actual(ins,m,args)
33
- def formatting(ins,m,args):
34
- effects['requests'].append({'target':70458,'arguments':args,'native_effect_not_executed':True});return m,EVENT+0x10000,{'supplied_string_pointer':EVENT+0x10000}
35
- hs.update({277695:event,33715:predicate,70458:formatting});hs.update(resolvers or {});return hs
36
-
37
- def probe(ins,m,start,stop,protected=False,resolvers=None):
38
- before=snapshot(m);effects={'events':[],'requests':[]};end=152671 if protected else 207154
39
- m,e=resume(ins,start,end,m,L,handlers=handlers(effects,resolvers),boundaries=[] if stop==end else [stop],limit=50000)
40
- return m,{'initial':before,'final':snapshot(m),'effects':effects,'events':[{**v,'fields':{str(o):m[v['pointer']+o]&0xffffffff for o in EFIELDS}} for v in effects['events']],'execution':e}
 
1
+ """Recovered session initialization and connected persistence compositions."""
2
+ from qvm_camera_world_support import B,run
3
+ from qvm_exit_rules_support import CPOOL
4
+ from qvm_persistence_support import info_lookup,load_position,save_position
5
+ from qvm_session_support import session,FIELDS
6
+ from qvm_string_memory_support import cstring,copy_bounded
7
+ from qvm_byte_memory_support import read_bytes
8
+ INIT=B+0x50000
9
+ SIZE=944
10
 
11
+ def initialize(ins,m,b,pointer,userinfo,handle,ticks):
12
+ from qvm_persistence_support import INFO
13
+ from qvm_map_commands_support import put_string
14
+ put_string(m,b,INFO,userinfo);parts={};diagnostics=[]
15
+ def classify(i,m,a,bs):
16
+ m,v,p,b=run(i,m,33715,33740,12,a,dict(bs),base=B+0x52000);return m,v,{'actual_source_child':33715}
17
+ def lookup(i,m,a,bs):
18
+ m,v,p,b=info_lookup(i,m,dict(bs),a);return m,v,{'actual_source_child':70503,'child_memory_bytes':{v+j:x for j,x in enumerate(cstring(m,b,v)+b'\0')}}
19
+ def clock(i,m,a,bs):return m,ticks,{'engine_ticks_supplied':True}
20
+ def copy(i,m,a,bs):return copy_bounded(i,m,a,dict(bs))
21
+ def load(i,m,a,bs):
22
+ data=b'9,8,7,6,5,4';m,p,b=load_position(i,m,dict(bs),a[8],userinfo,b'ut4_test',handle,len(data),data);parts['load']=p;return m,0,{'actual_source_child':246554}
23
+ def write(i,m,a,bs):
24
+ m,p,b=session(i,m,dict(bs),a[8]);parts['session']=p;return m,0,{'actual_source_child':246963}
25
+ def diagnostic(i,m,a,bs):diagnostics.append([a[8],a[12]&0xffffffff,a[16]&0xffffffff]);return m,0,{'diagnostic_captured':True}
26
+ m,v,p,b=run(ins,m,247520,247806,40,{8:pointer,12:INFO},b,{33715:classify,70503:lookup,-3:clock,69338:copy,246554:load,246963:write,7259:diagnostic},base=INIT);p.update(parts=parts,diagnostics=diagnostics);return m,p,b
27
 
28
+ def raw_state(m,b,pointer):return read_bytes(m,b,pointer+3096,SIZE).hex()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
scripts/test_qvm_session_init.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json,unittest
2
+ from pathlib import Path
3
+ class OriginalTests(unittest.TestCase):
4
+ def test_instruction_results(self):
5
+ rows=json.loads(Path('docs/research/qvm-session-init.json').read_text())['probes']
6
+ self.assertEqual(len(rows),96)
7
+ import struct
8
+ from analyze_qvm_acceleration import word
9
+ for p in rows:
10
+ a=p['input'];raw=bytearray.fromhex(a['before']);store=lambda o,v:raw.__setitem__(slice(o,o+4),(v&0xffffffff).to_bytes(4,'little'));team=(3 if a['team']==0 else a['team']) if a['mode']==3 else 3 if a['profile'] in [1,2,3] else 0
11
+ # Profile2 selects spectator by the capacity gate, despite uppercase S.
12
+ store(0,team);store(8,a['now']);store(12,1);store(44,a['now']+(a['seconds']*1000 if a['seconds'] else 60000));store(48,0);store(52,0);store(56,0);store(60,a['ticks']);store(64,0);raw[68:104]=b' '+b'\0'*35
13
+ for o in [104,492,592,612,616,644]:store(o,0)
14
+ for o in [108,236,496,528,560]:raw[o]=0
15
+ raw[684:940]=b'\0'*256
16
+ loaded=a['mode']==9 and a['profile']>0
17
+ if loaded and a['handle']:
18
+ for j,v in enumerate([9,8,7,6,5,4]):store(620+4*j,word(v))
19
+ self.assertEqual(p['raw'],raw.hex());self.assertEqual(p['ring'],3+int(loaded));self.assertEqual(p['info_ring'],0 if a['mode'] in [3,9] else 1);self.assertEqual(p['diagnostics'],[[83576,17+a['slot'],a['ticks']]])
20
+ vals=[int.from_bytes(raw[o:o+4],'little') for o in [0,60,48,44,52,56,612,616,644]];dec=lambda v:b'-./,),(-*,(' if v==0x80000000 else str(v if v<2**31 else v-2**32).encode();text=b','.join(dec(v) for v in vals[:5])+b',0,0,0,0';self.assertEqual(p['parts']['session']['sets'],[[f"session{a['slot']}".encode().hex(),text.hex()],[f"sessIgnore{a['slot']}".encode().hex(),'']])
21
+
22
+ if __name__=='__main__':unittest.main()
xtask/checks.tsv CHANGED
@@ -2803,3 +2803,7 @@ edge docs/research/rust-session-restore.json scripts/test_rust_session_restore.p
2803
  group rust-session-restore scripts/analyze_rust_session_restore.py
2804
  edge scripts/analyze_rust_session_restore.py scripts/analyze_qvm_resumer_audit.py
2805
  group rust-session-restore scripts/analyze_qvm_session_restore.py
 
 
 
 
 
2803
  group rust-session-restore scripts/analyze_rust_session_restore.py
2804
  edge scripts/analyze_rust_session_restore.py scripts/analyze_qvm_resumer_audit.py
2805
  group rust-session-restore scripts/analyze_qvm_session_restore.py
2806
+ report scripts/analyze_qvm_session_init.py docs/research/qvm-session-init.json
2807
+ edge docs/research/qvm-session-init.json scripts/test_qvm_session_init.py
2808
+ group qvm-session-init scripts/analyze_qvm_session_init.py
2809
+ edge scripts/analyze_qvm_session_init.py scripts/analyze_qvm_resumer_audit.py