nmarshall commited on
Commit
f43ec68
·
1 Parent(s): 04948c0

qvm: execute persistence write-to-restore round trips

Browse files
docs/FINDINGS.md CHANGED
@@ -1727,3 +1727,6 @@ RE-813–822 replaces the scoreboard decimal assumption with actual37914 executi
1727
 
1728
 
1729
  **RE-909:** Rust matches64 original normal transitions with actual saved-file and cvar child policies. Shared client counts, score/reset ordering, native file intentions, command bytes and formatter/selector carry are preserved. Existing standalone persistence uses the same action assembly. Native engine dispatch, bot internals and map-list parsing remain open. [Evidence](research/RUST_NORMAL_MAP_FILES.md).
 
 
 
 
1727
 
1728
 
1729
  **RE-909:** Rust matches64 original normal transitions with actual saved-file and cvar child policies. Shared client counts, score/reset ordering, native file intentions, command bytes and formatter/selector carry are preserved. Existing standalone persistence uses the same action assembly. Native engine dispatch, bot internals and map-list parsing remain open. [Evidence](research/RUST_NORMAL_MAP_FILES.md).
1730
+
1731
+
1732
+ **RE-910:** 144 finite original246746/246963/247219/246554 compositions feed actual captured cvar/file bytes into a fresh destination snapshot. Negative and INT_MIN integer formatting is deliberately not assumed invertible; original partial scanner writes and supplied scratch are preserved. Ignore entries accumulate over the destination table, and six-float file prefixes survive appended names. The engine is a supplied in-memory transcript, not a native filesystem or real map reload. [Evidence](research/QVM_PERSISTENCE_ROUNDTRIP.md).
docs/PROVISIONAL_TODO.md CHANGED
@@ -1764,3 +1764,6 @@ RE-908: 64 actual6939 normal transitions compose122230/7188/249007/246746/246963
1764
 
1765
 
1766
  RE-909: Rust matches64 original normal transitions with actual saved-file and cvar child policies. Shared client counts, score/reset ordering, native file intentions, command bytes and formatter/selector carry are preserved. Existing standalone persistence uses the same action assembly. Native engine dispatch, bot internals and map-list parsing remain open. Full runtime completion remains open. [Evidence](research/RUST_NORMAL_MAP_FILES.md).
 
 
 
 
1764
 
1765
 
1766
  RE-909: Rust matches64 original normal transitions with actual saved-file and cvar child policies. Shared client counts, score/reset ordering, native file intentions, command bytes and formatter/selector carry are preserved. Existing standalone persistence uses the same action assembly. Native engine dispatch, bot internals and map-list parsing remain open. Full runtime completion remains open. [Evidence](research/RUST_NORMAL_MAP_FILES.md).
1767
+
1768
+
1769
+ RE-910: 144 finite original246746/246963/247219/246554 compositions feed actual captured cvar/file bytes into a fresh destination snapshot. Negative and INT_MIN integer formatting is deliberately not assumed invertible; original partial scanner writes and supplied scratch are preserved. Ignore entries accumulate over the destination table, and six-float file prefixes survive appended names. The engine is a supplied in-memory transcript, not a native filesystem or real map reload. Full runtime completion remains open. [Evidence](research/QVM_PERSISTENCE_ROUNDTRIP.md).
docs/RESEARCH_LEDGER.md CHANGED
@@ -2265,3 +2265,8 @@ Rust matches48 original249007 compositions with both actual saved-file and sessi
2265
  ## 2026-10-28 — RE-909 Rust normal map with full persistence
2266
 
2267
  Rust matches64 original normal transitions with actual saved-file and cvar child policies. Shared client counts, score/reset ordering, native file intentions, command bytes and formatter/selector carry are preserved. Existing standalone persistence uses the same action assembly. Native engine dispatch, bot internals and map-list parsing remain open. Focused `cargo xtask test-group rust-normal-map-files` passes (11 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.
 
 
 
 
 
 
2265
  ## 2026-10-28 — RE-909 Rust normal map with full persistence
2266
 
2267
  Rust matches64 original normal transitions with actual saved-file and cvar child policies. Shared client counts, score/reset ordering, native file intentions, command bytes and formatter/selector carry are preserved. Existing standalone persistence uses the same action assembly. Native engine dispatch, bot internals and map-list parsing remain open. Focused `cargo xtask test-group rust-normal-map-files` passes (11 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.
2268
+
2269
+
2270
+ ## 2026-10-28 — RE-910 Original write-to-restore persistence round trip
2271
+
2272
+ 144 finite original246746/246963/247219/246554 compositions feed actual captured cvar/file bytes into a fresh destination snapshot. Negative and INT_MIN integer formatting is deliberately not assumed invertible; original partial scanner writes and supplied scratch are preserved. Ignore entries accumulate over the destination table, and six-float file prefixes survive appended names. The engine is a supplied in-memory transcript, not a native filesystem or real map reload. Focused `cargo xtask test-group qvm-persistence-roundtrip` 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
@@ -1801,3 +1801,6 @@ Purpose: turn the supplied installation into an evidence-backed specification of
1801
 
1802
 
1803
  - [x] RE-909 Rust normal map with full persistence ([evidence](research/RUST_NORMAL_MAP_FILES.md)).
 
 
 
 
1801
 
1802
 
1803
  - [x] RE-909 Rust normal map with full persistence ([evidence](research/RUST_NORMAL_MAP_FILES.md)).
1804
+
1805
+
1806
+ - [x] RE-910 Original write-to-restore persistence round trip ([evidence](research/QVM_PERSISTENCE_ROUNDTRIP.md)).
docs/research/QVM_PERSISTENCE_ROUNDTRIP.md ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ # Original write-to-restore persistence round trip
2
+
3
+ RE-910. Reproduce with `python3 scripts/analyze_qvm_persistence_roundtrip.py`; focused validation: `cargo xtask test-group qvm-persistence-roundtrip`. [Machine report](qvm-persistence-roundtrip.json).
4
+
5
+ 144 finite original246746/246963/247219/246554 compositions feed actual captured cvar/file bytes into a fresh destination snapshot. Negative and INT_MIN integer formatting is deliberately not assumed invertible; original partial scanner writes and supplied scratch are preserved. Ignore entries accumulate over the destination table, and six-float file prefixes survive appended names. The engine is a supplied in-memory transcript, not a native filesystem or real map reload.
6
+
7
+ Original executable/native runtime and complete Linux/macOS Rust/Bevy/Solari acceptance remain unverified.
docs/research/README.md CHANGED
@@ -1336,3 +1336,6 @@ The extension collector adds five focused tests for native tail calls, command-r
1336
 
1337
 
1338
  [RE-909: Rust normal map with full persistence](RUST_NORMAL_MAP_FILES.md).
 
 
 
 
1336
 
1337
 
1338
  [RE-909: Rust normal map with full persistence](RUST_NORMAL_MAP_FILES.md).
1339
+
1340
+
1341
+ [RE-910: Original write-to-restore persistence round trip](QVM_PERSISTENCE_ROUNDTRIP.md).
docs/research/qvm-persistence-roundtrip.json ADDED
The diff for this file is too large to render. See raw diff
 
scripts/analyze_qvm_persistence_roundtrip.py ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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,save_position,restore_session,RESTORE,SCRATCH
14
+ from qvm_session_support import session,FIELDS
15
+ from qvm_map_commands_support import put_string
16
+ for mode,profile,opened,positive,flag,slot in itertools.product([0,3,9],range(3),[False,True],[False,True],[0,1],[0,3]):
17
+ m,b=environment(raw,h);m.update({34090788:mode,35000468:flag,34064148:1,34992524:8});pointer=CPOOL+6336*slot;values=[[1,2,3,4,5,1,0,1,1],[1,-2,3,4,5,-1,2,0,1],[-2147483648,2,3,4,5,1,1,1,1]][profile];ignore=[0,1,1,0]*16;indices=[j if profile!=2 else j%3 for j in range(8)];origin=[word(v) for v in ([0]*6 if profile==0 else [1.25,-2.5,3,90,180,-45.5])];info=b'\\cl_guid\\ID';name=b'PLAYER';handle=7 if opened else 0;put_string(m,b,pointer+504,name)
18
+ for o,v in zip(FIELDS,values):m[pointer+o]=v
19
+ for j,v in enumerate(ignore):m[pointer+3780+4*j]=v
20
+ for j,v in enumerate(indices):m[POOL+880*j+520]=CPOOL+6336*v
21
+ for j,v in enumerate(origin):m[pointer+3716+4*j]=v
22
+ m,saved,b=save_position(ins,m,b,pointer,info,b'ut4_test',handle,-7);m,written,b=session(ins,m,b,pointer);cvars={bytes.fromhex(k):bytes.fromhex(v) for k,v in written['sets']};file=next((bytes.fromhex(e['data']) for e in saved['events'] if e['op']=='write'),None)
23
+ for o in FIELDS:m[pointer+o]=0
24
+ for j in range(64):m[pointer+3780+4*j]=2
25
+ for j in range(6):m[pointer+3716+4*j]=0
26
+ scratch=0x7fffffff if positive else 0
27
+ for o in SCRATCH:m[RESTORE+o]=scratch
28
+ m,p,b=restore_session(ins,m,b,pointer,cvars[f'session{slot}'.encode()],cvars[f'sessIgnore{slot}'.encode()],info,b'ut4_test',7 if file is not None else 0,len(file) if file is not None else -1,file or b'');p.update(input=dict(mode=mode,profile=profile,opened=opened,flag=flag,slot=slot,values=values,ignore=ignore,indices=indices,origin=origin,scratch=scratch),saved=saved['events'],sets=written['sets'],file=None if file is None else file.hex(),values=[m[pointer+o]&0xffffffff for o in FIELDS],ignore=[m[pointer+3780+4*j]&0xffffffff for j in range(64)],origin=[m[pointer+3716+4*j]&0xffffffff for j in range(6)],ring=m[23708]&0xffffffff,info_ring=m[23712]&0xffffffff);rows.append(p)
29
+
30
+ write_json(Path('docs/research/qvm-persistence-roundtrip.json'),{'source':q['source'],'sha256':q['sha256'],'root':247219,'probes':rows,'limits':'144 finite original246746/246963/247219/246554 compositions feed actual captured cvar/file bytes into a fresh destination snapshot. Negative and INT_MIN integer formatting is deliberately not assumed invertible; original partial scanner writes and supplied scratch are preserved. Ignore entries accumulate over the destination table, and six-float file prefixes survive appended names. The engine is a supplied in-memory transcript, not a native filesystem or real map reload.'})
31
+ if __name__=='__main__':main()
scripts/test_qvm_persistence_roundtrip.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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-persistence-roundtrip.json').read_text())['probes']
6
+ self.assertEqual(len(rows),144)
7
+ from qvm_scan_oracle import scan
8
+ for p in rows:
9
+ a=p['input'];initial=[a['scratch'],0,0,0,0,*[a['scratch']]*4];result,parsed=scan(bytes.fromhex(p['sets'][0][1]),'i',9,initial);values=parsed[:5]+[int(0<v<2**31) for v in parsed[5:8]]+[int(0<parsed[8]<2**31 and a['mode']==3 and a['flag'])];ignored=[2]*64
10
+ for text in bytes.fromhex(p['sets'][1][1]).split(b','):
11
+ if text:ignored[int(text)]=1
12
+ origin=[0]*6
13
+ if p['file'] is not None:
14
+ count,words=scan(bytes.fromhex(p['file']),'f',6)
15
+ if count==6:origin=words
16
+ n=sum(a['ignore'][j]==1 for j in a['indices']);self.assertEqual(p['values'],values);self.assertEqual(p['ignore'],ignored);self.assertEqual(p['origin'],origin);self.assertEqual(p['scan_result'],result);self.assertEqual(p['ring'],5+n+int(a['mode']==9)*(1+int(a['profile']!=0)));self.assertEqual(p['info_ring'],0);self.assertEqual(p['cvars'],p['sets']);self.assertEqual(p['file'] is not None,a['mode']==9 and a['profile']!=0 and a['opened'])
17
+
18
+ if __name__=='__main__':unittest.main()
xtask/checks.tsv CHANGED
@@ -2863,3 +2863,8 @@ report scripts/analyze_rust_normal_map_files.py docs/research/rust-normal-map-fi
2863
  edge docs/research/rust-normal-map-files.json scripts/test_rust_normal_map_files.py
2864
  group rust-normal-map-files scripts/analyze_rust_normal_map_files.py
2865
  edge scripts/analyze_rust_normal_map_files.py scripts/analyze_qvm_resumer_audit.py
 
 
 
 
 
 
2863
  edge docs/research/rust-normal-map-files.json scripts/test_rust_normal_map_files.py
2864
  group rust-normal-map-files scripts/analyze_rust_normal_map_files.py
2865
  edge scripts/analyze_rust_normal_map_files.py scripts/analyze_qvm_resumer_audit.py
2866
+ edge scripts/qvm_scan_oracle.py scripts/test_qvm_persistence_roundtrip.py
2867
+ report scripts/analyze_qvm_persistence_roundtrip.py docs/research/qvm-persistence-roundtrip.json
2868
+ edge docs/research/qvm-persistence-roundtrip.json scripts/test_qvm_persistence_roundtrip.py
2869
+ group qvm-persistence-roundtrip scripts/analyze_qvm_persistence_roundtrip.py
2870
+ edge scripts/analyze_qvm_persistence_roundtrip.py scripts/analyze_qvm_resumer_audit.py