qvm: wound attribution and counter cap
Browse files- docs/ASSET_PIPELINE_TODO.md +3 -0
- docs/FINDINGS.md +3 -0
- docs/PROVISIONAL_TODO.md +3 -0
- docs/RESEARCH_LEDGER.md +5 -0
- docs/REVERSE_ENGINEERING_TODO.md +3 -0
- docs/research/QVM_DAMAGE_ATTRIBUTION.md +7 -0
- docs/research/README.md +3 -0
- docs/research/qvm-damage-attribution.json +0 -0
- scripts/analyze_qvm_damage_attribution.py +14 -0
- scripts/test_qvm_damage_attribution.py +19 -0
docs/ASSET_PIPELINE_TODO.md
CHANGED
|
@@ -787,3 +787,6 @@ Research progress: RE-706 [report](research/QVM_DAMAGE_CLAMP.md); remaining nati
|
|
| 787 |
|
| 788 |
|
| 789 |
Research progress: RE-707 [report](research/QVM_DAMAGE_WOUNDS.md); remaining native/content/runtime/platform scope stays open.
|
|
|
|
|
|
|
|
|
|
|
|
| 787 |
|
| 788 |
|
| 789 |
Research progress: RE-707 [report](research/QVM_DAMAGE_WOUNDS.md); remaining native/content/runtime/platform scope stays open.
|
| 790 |
+
|
| 791 |
+
|
| 792 |
+
Research progress: RE-708 [report](research/QVM_DAMAGE_ATTRIBUTION.md); remaining native/content/runtime/platform scope stays open.
|
docs/FINDINGS.md
CHANGED
|
@@ -1133,3 +1133,6 @@ Bounded qagame paths recover bomb-plant/inactivity correction requests, direct f
|
|
| 1133 |
|
| 1134 |
|
| 1135 |
**RE-707 — Wound eligibility and client meter increments:** Mode9, entity flag16 or protection suppress the wound word. Active client wounds set leg flag128 at locations11–14 and increment client4312 with source-specific threshold rules. [Evidence](research/QVM_DAMAGE_WOUNDS.md).
|
|
|
|
|
|
|
|
|
|
|
|
| 1133 |
|
| 1134 |
|
| 1135 |
**RE-707 — Wound eligibility and client meter increments:** Mode9, entity flag16 or protection suppress the wound word. Active client wounds set leg flag128 at locations11–14 and increment client4312 with source-specific threshold rules. [Evidence](research/QVM_DAMAGE_WOUNDS.md).
|
| 1136 |
+
|
| 1137 |
+
|
| 1138 |
+
**RE-708 — Active wound attribution and counter cap:** Active wounds record attacker pointer at target836 and weapon at client4300; counter4304 increments only below4 and resets4316 there, while client220 bit256 is always set. [Evidence](research/QVM_DAMAGE_ATTRIBUTION.md).
|
docs/PROVISIONAL_TODO.md
CHANGED
|
@@ -1122,3 +1122,6 @@ Research progress: RE-706 [report](research/QVM_DAMAGE_CLAMP.md); remaining nati
|
|
| 1122 |
|
| 1123 |
|
| 1124 |
Research progress: RE-707 [report](research/QVM_DAMAGE_WOUNDS.md); remaining native/content/runtime/platform scope stays open.
|
|
|
|
|
|
|
|
|
|
|
|
| 1122 |
|
| 1123 |
|
| 1124 |
Research progress: RE-707 [report](research/QVM_DAMAGE_WOUNDS.md); remaining native/content/runtime/platform scope stays open.
|
| 1125 |
+
|
| 1126 |
+
|
| 1127 |
+
Research progress: RE-708 [report](research/QVM_DAMAGE_ATTRIBUTION.md); remaining native/content/runtime/platform scope stays open.
|
docs/RESEARCH_LEDGER.md
CHANGED
|
@@ -1177,3 +1177,8 @@ Positive damage factors cap at1 and weapon4 additionally caps at float32 0.35; i
|
|
| 1177 |
## 2026-10-21 — RE-707 Wound eligibility and client meter increments (separate task commit)
|
| 1178 |
|
| 1179 |
Mode9, entity flag16 or protection suppress the wound word. Active client wounds set leg flag128 at locations11–14 and increment client4312 with source-specific threshold rules. 302 eligibility/weapon/location/ratio/meter fixtures pass independent exact float32 and unchanged-state checks. Full suite: 1279 tests pass. Report regenerates byte-identically (464742 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1177 |
## 2026-10-21 — RE-707 Wound eligibility and client meter increments (separate task commit)
|
| 1178 |
|
| 1179 |
Mode9, entity flag16 or protection suppress the wound word. Active client wounds set leg flag128 at locations11–14 and increment client4312 with source-specific threshold rules. 302 eligibility/weapon/location/ratio/meter fixtures pass independent exact float32 and unchanged-state checks. Full suite: 1279 tests pass. Report regenerates byte-identically (464742 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
|
| 1180 |
+
|
| 1181 |
+
|
| 1182 |
+
## 2026-10-21 — RE-708 Active wound attribution and counter cap (separate task commit)
|
| 1183 |
+
|
| 1184 |
+
Active wounds record attacker pointer at target836 and weapon at client4300; counter4304 increments only below4 and resets4316 there, while client220 bit256 is always set. 120 counter/weapon/flag combinations pass independent attribution, cap, reset and bit-preservation checks. Full suite: 1283 tests pass. Report regenerates byte-identically (179647 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
|
docs/REVERSE_ENGINEERING_TODO.md
CHANGED
|
@@ -1165,3 +1165,6 @@ Purpose: turn the supplied installation into an evidence-backed specification of
|
|
| 1165 |
|
| 1166 |
|
| 1167 |
- [x] RE-707 Wound eligibility and client meter increments ([report](research/QVM_DAMAGE_WOUNDS.md)).
|
|
|
|
|
|
|
|
|
|
|
|
| 1165 |
|
| 1166 |
|
| 1167 |
- [x] RE-707 Wound eligibility and client meter increments ([report](research/QVM_DAMAGE_WOUNDS.md)).
|
| 1168 |
+
|
| 1169 |
+
|
| 1170 |
+
- [x] RE-708 Active wound attribution and counter cap ([report](research/QVM_DAMAGE_ATTRIBUTION.md)).
|
docs/research/QVM_DAMAGE_ATTRIBUTION.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Active wound attribution and counter cap
|
| 2 |
+
|
| 3 |
+
RE-708. Reproduce with `python3 scripts/analyze_qvm_damage_attribution.py`; check with `python3 scripts/test_qvm_damage_attribution.py`. The [machine report](qvm-damage-attribution.json) retains source identity and bounded fixtures.
|
| 4 |
+
|
| 5 |
+
Actual290228–290297 runs after the active client/wound gates. It writes target836 to the attacker pointer, client4300 to the weapon, and ORs256 into client220. Only signed client4304 below4 resets client4316 to zero and increments the counter. Existing counters4 and higher are preserved; negative fixtures expose signed arithmetic without establishing legal gameplay state. Other tracked client fields remain unchanged. This range does not allocate events, call external functions or apply health damage.
|
| 6 |
+
|
| 7 |
+
No original executable/full QVM/native collision/physics/rendering executes. Native responses and legal input domains are supplied or unverified where stated; full runtime/macOS/Linux Rust/Bevy/Solari gameplay remains open.
|
docs/research/README.md
CHANGED
|
@@ -723,3 +723,6 @@ The extension collector adds five focused tests for native tail calls, command-r
|
|
| 723 |
|
| 724 |
|
| 725 |
[RE-707: Wound eligibility and client meter increments](QVM_DAMAGE_WOUNDS.md). Reproduce with `python3 scripts/analyze_qvm_damage_wounds.py`; check with `python3 scripts/test_qvm_damage_wounds.py`.
|
|
|
|
|
|
|
|
|
|
|
|
| 723 |
|
| 724 |
|
| 725 |
[RE-707: Wound eligibility and client meter increments](QVM_DAMAGE_WOUNDS.md). Reproduce with `python3 scripts/analyze_qvm_damage_wounds.py`; check with `python3 scripts/test_qvm_damage_wounds.py`.
|
| 726 |
+
|
| 727 |
+
|
| 728 |
+
[RE-708: Active wound attribution and counter cap](QVM_DAMAGE_ATTRIBUTION.md). Reproduce with `python3 scripts/analyze_qvm_damage_attribution.py`; check with `python3 scripts/test_qvm_damage_attribution.py`.
|
docs/research/qvm-damage-attribution.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
scripts/analyze_qvm_damage_attribution.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""Active wound attribution, saturating counter and pending flag writes."""
|
| 3 |
+
import itertools
|
| 4 |
+
from pathlib import Path
|
| 5 |
+
from qvm_research_support import source
|
| 6 |
+
from qvm_damage_support import seed,run
|
| 7 |
+
from analyze_qvm import write_json
|
| 8 |
+
|
| 9 |
+
def main():
|
| 10 |
+
q,raw,h,ins=source();rows=[]
|
| 11 |
+
for counter,weapon,flags in itertools.product([-2,-1,0,1,3,4,5,2147483647],[3,4,24],[0,8,128,256,384]):
|
| 12 |
+
a=dict(counter=counter,weapon=weapon,flags=flags);_,p=run(ins,seed(raw,h,**a),290228,290298);p['input']=a;rows.append(p)
|
| 13 |
+
write_json(Path('docs/research/qvm-damage-attribution.json'),{'source':q['source'],'sha256':q['sha256'],'probes':rows,'limits':'Actual290228..290297 entered only for previously accepted active wounds. Negative counters are explicit arithmetic fixtures, not asserted legal state. No health damage.'})
|
| 14 |
+
if __name__=='__main__':main()
|
scripts/test_qvm_damage_attribution.py
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import json,unittest
|
| 2 |
+
from pathlib import Path
|
| 3 |
+
from qvm_damage_support import ATTACKER
|
| 4 |
+
class DamageAttributionTests(unittest.TestCase):
|
| 5 |
+
@classmethod
|
| 6 |
+
def setUpClass(cls):cls.ps=json.loads(Path('docs/research/qvm-damage-attribution.json').read_text())['probes']
|
| 7 |
+
def test_attacker_pointer_and_weapon_always_recorded(self):
|
| 8 |
+
for p in self.ps:self.assertEqual(p['final']['attacker_pointer'],ATTACKER);self.assertEqual(p['final']['client']['4300'],p['input']['weapon'])
|
| 9 |
+
def test_strict_counter_cap_and_auxiliary_reset(self):
|
| 10 |
+
for p in self.ps:
|
| 11 |
+
c=p['input']['counter'];self.assertEqual(p['final']['client']['4304'],(c+1 if c<4 else c)&0xffffffff);self.assertEqual(p['final']['client']['4316'],0 if c<4 else 77)
|
| 12 |
+
def test_pending_flag_preserves_other_bits(self):
|
| 13 |
+
for p in self.ps:self.assertEqual(p['final']['client']['220'],p['input']['flags']|256)
|
| 14 |
+
def test_meter_and_location_flags_unchanged(self):
|
| 15 |
+
self.assertEqual(len(self.ps),120)
|
| 16 |
+
for p in self.ps:
|
| 17 |
+
for o in ['192','4312','6304']:self.assertEqual(p['initial']['client'][o],p['final']['client'][o])
|
| 18 |
+
self.assertEqual(p['execution']['calls'],[])
|
| 19 |
+
if __name__=='__main__':unittest.main()
|