nmarshall commited on
Commit
39c456c
·
1 Parent(s): efc9591

qvm: audit counter and clear reentry

Browse files
docs/ASSET_PIPELINE_TODO.md CHANGED
@@ -1009,3 +1009,6 @@ Research progress: RE-784 [report](research/QVM_NOTIFICATION_REENTRY.md); origin
1009
 
1010
 
1011
  Research progress: RE-785 [report](research/QVM_AWARD_REENTRY.md); original assets unchanged.
 
 
 
 
1009
 
1010
 
1011
  Research progress: RE-785 [report](research/QVM_AWARD_REENTRY.md); original assets unchanged.
1012
+
1013
+
1014
+ Research progress: RE-786 [report](research/QVM_COUNTER_REENTRY.md); original assets unchanged.
docs/FINDINGS.md CHANGED
@@ -1355,3 +1355,6 @@ RE-725–734 batch: [health, contact and Rust impulse findings](research/QVM_HEA
1355
 
1356
 
1357
  **RE-785 — Audited dense recent-award scans timestamps and index64 alias:** 285227 uses corrected reentry;32 dense65-record fixtures preserve source scan order, signed timestamp/count gates and index64 award/count aliasing. [Evidence](research/QVM_AWARD_REENTRY.md).
 
 
 
 
1355
 
1356
 
1357
  **RE-785 — Audited dense recent-award scans timestamps and index64 alias:** 285227 uses corrected reentry;32 dense65-record fixtures preserve source scan order, signed timestamp/count gates and index64 award/count aliasing. [Evidence](research/QVM_AWARD_REENTRY.md).
1358
+
1359
+
1360
+ **RE-786 — Audited method counters team pairs and dense record clearing:** 278834,279720 and285486 now use corrected reentry; independent counter/alias/address oracles and full legacy tuple comparisons cover160 expanded fixtures. [Evidence](research/QVM_COUNTER_REENTRY.md).
docs/PROVISIONAL_TODO.md CHANGED
@@ -1356,3 +1356,6 @@ Research progress: RE-784 [report](research/QVM_NOTIFICATION_REENTRY.md); full n
1356
 
1357
 
1358
  Research progress: RE-785 [report](research/QVM_AWARD_REENTRY.md); full native/platform/game scope remains open.
 
 
 
 
1356
 
1357
 
1358
  Research progress: RE-785 [report](research/QVM_AWARD_REENTRY.md); full native/platform/game scope remains open.
1359
+
1360
+
1361
+ Research progress: RE-786 [report](research/QVM_COUNTER_REENTRY.md); full native/platform/game scope remains open.
docs/RESEARCH_LEDGER.md CHANGED
@@ -1587,3 +1587,8 @@ The movement resumer also loses non-command STORE1 writes across calls in legacy
1587
  ## 2026-10-21 — RE-785 Audited dense recent-award scans timestamps and index64 alias
1588
 
1589
  285227 uses corrected reentry;32 dense65-record fixtures preserve source scan order, signed timestamp/count gates and index64 award/count aliasing. Focused `cargo xtask test-group award-reentry` passes (10 Python tests); selected reports regenerate twice byte-identically, with storage, links and whitespace guards. New report: 659031 bytes. Full-suite validation is deferred to the tenth batch commit. Recent-award source resumption migrated. Existing Rust parity and source consumers remain bounded numeric contracts.
 
 
 
 
 
 
1587
  ## 2026-10-21 — RE-785 Audited dense recent-award scans timestamps and index64 alias
1588
 
1589
  285227 uses corrected reentry;32 dense65-record fixtures preserve source scan order, signed timestamp/count gates and index64 award/count aliasing. Focused `cargo xtask test-group award-reentry` passes (10 Python tests); selected reports regenerate twice byte-identically, with storage, links and whitespace guards. New report: 659031 bytes. Full-suite validation is deferred to the tenth batch commit. Recent-award source resumption migrated. Existing Rust parity and source consumers remain bounded numeric contracts.
1590
+
1591
+
1592
+ ## 2026-10-21 — RE-786 Audited method counters team pairs and dense record clearing
1593
+
1594
+ 278834,279720 and285486 now use corrected reentry; independent counter/alias/address oracles and full legacy tuple comparisons cover160 expanded fixtures. Focused `cargo xtask test-group counter-reentry` passes (34 Python tests); selected reports regenerate twice byte-identically, with storage, links and whitespace guards. New report: 200891 bytes. Full-suite validation is deferred to the tenth batch commit. Three bounded source helpers migrated; independent numeric/address expectations and existing source/Rust regressions check their contracts.
docs/REVERSE_ENGINEERING_TODO.md CHANGED
@@ -1405,3 +1405,6 @@ Purpose: turn the supplied installation into an evidence-backed specification of
1405
 
1406
 
1407
  - [x] RE-785 Audited dense recent-award scans timestamps and index64 alias ([report](research/QVM_AWARD_REENTRY.md)).
 
 
 
 
1405
 
1406
 
1407
  - [x] RE-785 Audited dense recent-award scans timestamps and index64 alias ([report](research/QVM_AWARD_REENTRY.md)).
1408
+
1409
+
1410
+ - [x] RE-786 Audited method counters team pairs and dense record clearing ([report](research/QVM_COUNTER_REENTRY.md)).
docs/research/QVM_COUNTER_REENTRY.md ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ # Audited method counters team pairs and dense record clearing
2
+
3
+ RE-786. Reproduce with `python3 scripts/analyze_qvm_counter_reentry.py`; validate with `cargo xtask test-group counter-reentry`. See the [machine report](qvm-counter-reentry.json).
4
+
5
+ The audit includes48 method updates with self-aliasing and unsigned wrap,64 team-pair gates, and48 record clears across sparse and fully populated64-client pools. Accepted index64 and rejected indices-minus-one/65 are checked against exact changed addresses and initialized neighbor values. Existing full method-domain, null/team gates and Rust parity reports are selected transitively. Stat update children remain captured; no claim of full stat lifecycle execution is added.
6
+
7
+ No original executable/full VM/native world collision or rendering runs. Supplied callback/native responses and fixture domains remain explicit; complete macOS/Linux Rust/Bevy/Solari gameplay remains open.
docs/research/README.md CHANGED
@@ -945,3 +945,6 @@ The extension collector adds five focused tests for native tail calls, command-r
945
 
946
 
947
  [RE-785: Audited dense recent-award scans timestamps and index64 alias](QVM_AWARD_REENTRY.md).
 
 
 
 
945
 
946
 
947
  [RE-785: Audited dense recent-award scans timestamps and index64 alias](QVM_AWARD_REENTRY.md).
948
+
949
+
950
+ [RE-786: Audited method counters team pairs and dense record clearing](QVM_COUNTER_REENTRY.md).
docs/research/qvm-counter-reentry.json ADDED
The diff for this file is too large to render. See raw diff
 
docs/research/qvm-resumer-audit.json CHANGED
@@ -8628,7 +8628,7 @@
8628
  285578
8629
  ],
8630
  "path": "scripts/qvm_record_clear_support.py",
8631
- "repeated_calls_opt_in": false
8632
  },
8633
  {
8634
  "backward_conditional_branches": [],
@@ -8856,7 +8856,7 @@
8856
  279584
8857
  ],
8858
  "path": "scripts/qvm_stat_update_support.py",
8859
- "repeated_calls_opt_in": false
8860
  },
8861
  {
8862
  "backward_conditional_branches": [],
@@ -8877,7 +8877,7 @@
8877
  279818
8878
  ],
8879
  "path": "scripts/qvm_team_counter_support.py",
8880
- "repeated_calls_opt_in": false
8881
  }
8882
  ],
8883
  "limits": "Static direct-import calls only, including local aliases. Computed ranges, indirect/module calls and reachability need manual/dynamic review. Backward branches and dynamic stores are review markers, not proven failures; fixture compatibility is not semantic proof.",
@@ -8920,7 +8920,7 @@
8920
  "summary": {
8921
  "call_expressions": 179,
8922
  "files": 140,
8923
- "legacy_expressions": 169,
8924
  "nonliteral_ranges": 20
8925
  }
8926
  }
 
8628
  285578
8629
  ],
8630
  "path": "scripts/qvm_record_clear_support.py",
8631
+ "repeated_calls_opt_in": true
8632
  },
8633
  {
8634
  "backward_conditional_branches": [],
 
8856
  279584
8857
  ],
8858
  "path": "scripts/qvm_stat_update_support.py",
8859
+ "repeated_calls_opt_in": true
8860
  },
8861
  {
8862
  "backward_conditional_branches": [],
 
8877
  279818
8878
  ],
8879
  "path": "scripts/qvm_team_counter_support.py",
8880
+ "repeated_calls_opt_in": true
8881
  }
8882
  ],
8883
  "limits": "Static direct-import calls only, including local aliases. Computed ranges, indirect/module calls and reachability need manual/dynamic review. Backward branches and dynamic stores are review markers, not proven failures; fixture compatibility is not semantic proof.",
 
8920
  "summary": {
8921
  "call_expressions": 179,
8922
  "files": 140,
8923
+ "legacy_expressions": 166,
8924
  "nonliteral_ranges": 20
8925
  }
8926
  }
scripts/analyze_qvm_counter_reentry.py ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Differential migration of counters, aliases and sparse/dense pair clearing."""
3
+ import itertools
4
+ from pathlib import Path
5
+ import qvm_stat_update_support as stats
6
+ import qvm_record_clear_support as records
7
+ import qvm_team_counter_support as teams
8
+ from qvm_resumer_diff_support import compare
9
+ from qvm_research_support import source
10
+ from analyze_qvm import write_json
11
+
12
+ def main():
13
+ q,raw,h,ins=source();updates=[];clears=[];pairs=[]
14
+ for method,self_hit,initial in itertools.product([-1,0,6,12,20,22,25,34,37,47,48,49],[False,True],[0,0xffffffff]):
15
+ a={'method':method,'self':self_hit,'initial':initial}
16
+ old,new,equal=compare(stats,lambda:stats.update(ins,stats.seed(raw,h,**a),{8:1,12:method,16:1 if self_hit else 2}))
17
+ updates.append({'input':a,'legacy_equal':equal,'changes':new[2]['changes'],'requests':new[2]['requests']})
18
+ for mode,index,dense in itertools.product([3,9,10,11],[-1,0,1,63,64,65],[False,True]):
19
+ a={'mode':mode,'index':index,'dense':dense};old,new,equal=compare(records,lambda:records.clear(ins,records.seed(**a),{8:index}));clears.append({'input':a,'legacy_equal':equal,'changes':new[2]['changes'],'stop':new[2]['execution']['stop']})
20
+ for mode,same,self_hit,initial,actor_client in itertools.product([3,9,10,11],[False,True],[False,True],[0,0xffffffff],[False,True]):
21
+ a={'mode':mode,'same':same,'self':self_hit,'initial':initial,'actor_client':actor_client};old,new,equal=compare(teams,lambda:teams.aggregate(ins,teams.seed(raw,h,**a),{8:teams.ATTACKER,12:teams.ATTACKER if self_hit else teams.TARGET}));pairs.append({'input':a,'legacy_equal':equal,'initial':new[2]['initial'],'final':new[2]['final']})
22
+ write_json(Path('docs/research/qvm-counter-reentry.json'),{'source':q['source'],'sha256':q['sha256'],'updates':updates,'clears':clears,'pairs':pairs,'limits':'Corrected278834/285486/279720;48 stat,48 clear and64 team fixtures. Full legacy/corrected tuple comparisons; complete tracked clear changes across64 dense clients and65 indices. Stat reporting/aggregate/award children remain captured in update; lifecycle/native ownership remains open.'})
23
+ if __name__=='__main__':main()
scripts/qvm_record_clear_support.py CHANGED
@@ -16,6 +16,6 @@ def seed(**a):
16
 
17
  def clear(ins,m,args):
18
  m[R+40]=args[8];addresses=sorted({c+2520+8*j+4*k for slot in range(64) for c in [m[POOL+880*slot+520]] if c for j in range(65) for k in [0,1]});before={a:m[a]&0xffffffff for a in addresses}
19
- m,e=resume(ins,285487,285578,m,R,handlers={33715:predicate})
20
  changes=[{'address':a,'before':v,'after':m[a]&0xffffffff} for a,v in before.items() if v!=(m[a]&0xffffffff)]
21
  return m,0,{'arguments':args,'changes':changes,'execution':e}
 
16
 
17
  def clear(ins,m,args):
18
  m[R+40]=args[8];addresses=sorted({c+2520+8*j+4*k for slot in range(64) for c in [m[POOL+880*slot+520]] if c for j in range(65) for k in [0,1]});before={a:m[a]&0xffffffff for a in addresses}
19
+ m,e=resume(ins,285487,285578,m,R,handlers={33715:predicate},repeated_calls=True)
20
  changes=[{'address':a,'before':v,'after':m[a]&0xffffffff} for a,v in before.items() if v!=(m[a]&0xffffffff)]
21
  return m,0,{'arguments':args,'changes':changes,'execution':e}
scripts/qvm_stat_update_support.py CHANGED
@@ -17,6 +17,6 @@ def update(ins,m,args):
17
  for o,v in args.items():m[T+52+o]=v
18
  addresses=sorted({c+o for c in [CLIENT,A_CLIENT] for o in OFFSETS});before={a:m[a]&0xffffffff for a in addresses};requests=[]
19
  hs={c:captured(c,requests) for c in [279720,279586,285227,283622]};hs[278733]=classify
20
- m,e=resume(ins,278835,279584,m,T,handlers=hs)
21
  changes=[{'client':'actor' if a>=A_CLIENT and a<A_CLIENT+7000 else 'victim','offset':a-(A_CLIENT if a>=A_CLIENT and a<A_CLIENT+7000 else CLIENT),'before':before[a],'after':m[a]&0xffffffff} for a in addresses if before[a]!=(m[a]&0xffffffff)]
22
  return m,0,{'arguments':args,'changes':changes,'requests':requests,'execution':e}
 
17
  for o,v in args.items():m[T+52+o]=v
18
  addresses=sorted({c+o for c in [CLIENT,A_CLIENT] for o in OFFSETS});before={a:m[a]&0xffffffff for a in addresses};requests=[]
19
  hs={c:captured(c,requests) for c in [279720,279586,285227,283622]};hs[278733]=classify
20
+ m,e=resume(ins,278835,279584,m,T,handlers=hs,repeated_calls=True)
21
  changes=[{'client':'actor' if a>=A_CLIENT and a<A_CLIENT+7000 else 'victim','offset':a-(A_CLIENT if a>=A_CLIENT and a<A_CLIENT+7000 else CLIENT),'before':before[a],'after':m[a]&0xffffffff} for a in addresses if before[a]!=(m[a]&0xffffffff)]
22
  return m,0,{'arguments':args,'changes':changes,'requests':requests,'execution':e}
scripts/qvm_team_counter_support.py CHANGED
@@ -14,5 +14,5 @@ def snapshot(m):return {name:[m[c+o]&0xffffffff for o in [2444,2516]] for name,c
14
 
15
  def aggregate(ins,m,args):
16
  for o,v in args.items():m[P+32+o]=v
17
- before=snapshot(m);m,e=resume(ins,279721,279818,m,P,handlers={33715:predicate})
18
  return m,0,{'arguments':args,'initial':before,'final':snapshot(m),'execution':e}
 
14
 
15
  def aggregate(ins,m,args):
16
  for o,v in args.items():m[P+32+o]=v
17
+ before=snapshot(m);m,e=resume(ins,279721,279818,m,P,handlers={33715:predicate},repeated_calls=True)
18
  return m,0,{'arguments':args,'initial':before,'final':snapshot(m),'execution':e}
scripts/test_qvm_counter_reentry.py ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json,unittest
2
+ from pathlib import Path
3
+ from test_qvm_method_stat_updates import expected
4
+ from qvm_record_clear_support import RPOOL
5
+ class CounterReentryTests(unittest.TestCase):
6
+ @classmethod
7
+ def setUpClass(cls):cls.r=json.loads(Path('docs/research/qvm-counter-reentry.json').read_text())
8
+ def test_stat_changes_and_callback_order(self):
9
+ self.assertEqual(len(self.r['updates']),48)
10
+ for p in self.r['updates']:
11
+ changes,calls=expected(p['input']);self.assertEqual(p['changes'],changes);self.assertEqual([r['target'] for r in p['requests']],calls);self.assertTrue(p['legacy_equal'])
12
+ def test_dense_clear_exact_addresses_and_preserved_neighbors(self):
13
+ self.assertEqual(len(self.r['clears']),48)
14
+ for p in self.r['clears']:
15
+ a=p['input'];slots=range(64) if a['dense'] else [0,3,63];valid=a['mode'] in [3,10] and 0<=a['index']<=64;expected_changes=[{'address':RPOOL+j*6336+2520+8*a['index']+4*k,'before':10000+j*256+2*a['index']+k,'after':0} for j in slots for k in [0,1]] if valid else []
16
+ self.assertEqual(p['changes'],expected_changes,a);self.assertEqual(p['stop'],285578);self.assertTrue(p['legacy_equal'],a)
17
+ def test_team_pair_gate_alias_and_wrapping(self):
18
+ self.assertEqual(len(self.r['pairs']),64)
19
+ for p in self.r['pairs']:
20
+ a=p['input'];v=a['initial'];out={'actor':[v,v],'victim':[v,v]}
21
+ if a['mode'] in [3,10] and a['same'] and not a['self'] and a['actor_client']:out['actor'][0]=(v+1)&0xffffffff;out['victim'][1]=(v+1)&0xffffffff
22
+ self.assertEqual(p['final'],out,a);self.assertTrue(p['legacy_equal'])
23
+ if __name__=='__main__':unittest.main()
xtask/checks.tsv CHANGED
@@ -1741,3 +1741,13 @@ report scripts/analyze_qvm_award_reentry.py docs/research/qvm-award-reentry.json
1741
  edge docs/research/qvm-award-reentry.json scripts/test_qvm_award_reentry.py
1742
  edge scripts/analyze_qvm_award_reentry.py scripts/analyze_qvm_resumer_audit.py
1743
  group award-reentry scripts/analyze_qvm_award_reentry.py
 
 
 
 
 
 
 
 
 
 
 
1741
  edge docs/research/qvm-award-reentry.json scripts/test_qvm_award_reentry.py
1742
  edge scripts/analyze_qvm_award_reentry.py scripts/analyze_qvm_resumer_audit.py
1743
  group award-reentry scripts/analyze_qvm_award_reentry.py
1744
+
1745
+ group counter-reentry scripts/qvm_stat_update_support.py
1746
+
1747
+ group counter-reentry scripts/qvm_record_clear_support.py
1748
+
1749
+ group counter-reentry scripts/qvm_team_counter_support.py
1750
+ report scripts/analyze_qvm_counter_reentry.py docs/research/qvm-counter-reentry.json
1751
+ edge docs/research/qvm-counter-reentry.json scripts/test_qvm_counter_reentry.py
1752
+ edge scripts/analyze_qvm_counter_reentry.py scripts/analyze_qvm_resumer_audit.py
1753
+ group counter-reentry scripts/analyze_qvm_counter_reentry.py