nmarshall commited on
Commit
b6e9de3
·
1 Parent(s): a9b587d

gameplay: port linked collision mask policy

Browse files
crates/urt-gameplay/src/bin/urt-client-move-context.rs CHANGED
@@ -56,6 +56,56 @@ fn main() {
56
  list(&copy)
57
  );
58
  }
 
59
  _ => panic!("unknown contract"),
60
  }
61
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  list(&copy)
57
  );
58
  }
59
+ "mask" => println!("{}", mask(&w)),
60
  _ => panic!("unknown contract"),
61
  }
62
  }
63
+
64
+ fn mask(w: &[u32]) -> String {
65
+ assert_eq!(w.len(), 12);
66
+ let entity = MoveEntityBox {
67
+ pm_type: w[0],
68
+ health: w[7],
69
+ origin: [0.; 3],
70
+ mins: [-1.; 3],
71
+ maxs: [1.; 3],
72
+ };
73
+ let other = MoveEntityBox {
74
+ pm_type: w[5],
75
+ health: w[6],
76
+ origin: [
77
+ f32::from_bits(w[8]),
78
+ f32::from_bits(w[9]),
79
+ f32::from_bits(w[10]),
80
+ ],
81
+ mins: [-1.; 3],
82
+ maxs: [1.; 3],
83
+ };
84
+ let mut links = MoveLinks {
85
+ linked: w[1] != 0,
86
+ other_linked: w[11] != 0,
87
+ };
88
+ let o = select_move_mask(
89
+ &mut links,
90
+ MoveMaskInput {
91
+ entity,
92
+ other,
93
+ entity_flags: w[2],
94
+ mode: w[3],
95
+ ghost: w[4],
96
+ },
97
+ )
98
+ .unwrap();
99
+ let results = o
100
+ .overlap
101
+ .map(|v| u32::from(v))
102
+ .into_iter()
103
+ .collect::<Vec<_>>();
104
+ format!(
105
+ r#"{{"mask":{},"linked":{},"other_linked":{},"overlap_results":{}}}"#,
106
+ o.mask,
107
+ links.linked,
108
+ links.other_linked,
109
+ list(&results)
110
+ )
111
+ }
crates/urt-gameplay/src/client_move_context.rs CHANGED
@@ -104,3 +104,164 @@ mod suppression_tests {
104
  }
105
  }
106
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
  }
105
  }
106
  }
107
+
108
+ #[derive(Clone, Copy, Debug, PartialEq)]
109
+ pub struct MoveEntityBox {
110
+ pub pm_type: u32,
111
+ pub health: u32,
112
+ pub origin: [f32; 3],
113
+ pub mins: [f32; 3],
114
+ pub maxs: [f32; 3],
115
+ }
116
+ /// Original151954: source order deliberately retains the strict first-X test.
117
+ /// Float sums outside the finite modeled domain reject before link mutation.
118
+ pub fn linked_move_overlap(
119
+ this: MoveEntityBox,
120
+ other: MoveEntityBox,
121
+ ) -> Result<bool, crate::native_policy::Error> {
122
+ if other.pm_type != 0
123
+ || other.health as i32 <= 0
124
+ || this.pm_type != 0
125
+ || this.health as i32 <= 0
126
+ {
127
+ return Ok(false);
128
+ }
129
+ let mut lo_a = [0.; 3];
130
+ let mut hi_a = [0.; 3];
131
+ let mut lo_b = [0.; 3];
132
+ let mut hi_b = [0.; 3];
133
+ for j in 0..3 {
134
+ for v in [
135
+ this.origin[j],
136
+ this.mins[j],
137
+ this.maxs[j],
138
+ other.origin[j],
139
+ other.mins[j],
140
+ other.maxs[j],
141
+ ] {
142
+ if !v.is_finite() {
143
+ return Err(crate::native_policy::Error::NonFinite);
144
+ }
145
+ }
146
+ lo_a[j] = this.origin[j] + this.mins[j];
147
+ hi_a[j] = this.origin[j] + this.maxs[j];
148
+ lo_b[j] = other.origin[j] + other.mins[j];
149
+ hi_b[j] = other.origin[j] + other.maxs[j];
150
+ if [lo_a[j], hi_a[j], lo_b[j], hi_b[j]]
151
+ .iter()
152
+ .any(|v| !v.is_finite())
153
+ {
154
+ return Err(crate::native_policy::Error::NonFinite);
155
+ }
156
+ }
157
+ Ok(lo_b[0] < hi_a[0]
158
+ && lo_b[1] <= hi_a[1]
159
+ && lo_b[2] <= hi_a[2]
160
+ && hi_b[0] >= lo_a[0]
161
+ && hi_b[1] >= lo_a[1]
162
+ && hi_b[2] >= lo_a[2])
163
+ }
164
+ #[derive(Clone, Copy, Debug, PartialEq, Eq)]
165
+ pub struct MoveLinks {
166
+ pub linked: bool,
167
+ pub other_linked: bool,
168
+ }
169
+ #[derive(Clone, Copy, Debug, PartialEq)]
170
+ pub struct MoveMaskInput {
171
+ pub entity: MoveEntityBox,
172
+ pub other: MoveEntityBox,
173
+ pub entity_flags: u32,
174
+ pub mode: u32,
175
+ pub ghost: u32,
176
+ }
177
+ #[derive(Clone, Copy, Debug, PartialEq, Eq)]
178
+ pub struct MoveMaskOutcome {
179
+ pub mask: u32,
180
+ pub overlap: Option<bool>,
181
+ }
182
+ pub fn select_move_mask(
183
+ links: &mut MoveLinks,
184
+ input: MoveMaskInput,
185
+ ) -> Result<MoveMaskOutcome, crate::native_policy::Error> {
186
+ let (mask, overlap) = if input.entity.pm_type == 3 {
187
+ (65537, None)
188
+ } else if links.linked {
189
+ let overlap = linked_move_overlap(input.entity, input.other)?;
190
+ if !overlap {
191
+ links.linked = false;
192
+ links.other_linked = false;
193
+ }
194
+ (if overlap { 65537 } else { 33619969 }, Some(overlap))
195
+ } else if input.entity_flags & 8 != 0 {
196
+ (37814273, None)
197
+ } else if input.mode == 9 && input.ghost != 0 {
198
+ (67174401, None)
199
+ } else {
200
+ (33619969, None)
201
+ };
202
+ Ok(MoveMaskOutcome { mask, overlap })
203
+ }
204
+ #[cfg(test)]
205
+ mod mask_tests {
206
+ use super::*;
207
+ fn entity() -> MoveEntityBox {
208
+ MoveEntityBox {
209
+ pm_type: 0,
210
+ health: 1,
211
+ origin: [0.; 3],
212
+ mins: [-1.; 3],
213
+ maxs: [1.; 3],
214
+ }
215
+ }
216
+ fn input() -> MoveMaskInput {
217
+ MoveMaskInput {
218
+ entity: entity(),
219
+ other: entity(),
220
+ entity_flags: 8,
221
+ mode: 9,
222
+ ghost: 1,
223
+ }
224
+ }
225
+ #[test]
226
+ fn asymmetric_boundary_and_cleanup_precede_flags() {
227
+ let mut i = input();
228
+ i.other.origin[0] = 2.;
229
+ let mut l = MoveLinks {
230
+ linked: true,
231
+ other_linked: true,
232
+ };
233
+ let o = select_move_mask(&mut l, i).unwrap();
234
+ assert_eq!(o.mask, 33619969);
235
+ assert_eq!(o.overlap, Some(false));
236
+ assert!(!l.linked && !l.other_linked);
237
+ i.other.origin = [0., 2., 0.];
238
+ let mut l = MoveLinks {
239
+ linked: true,
240
+ other_linked: true,
241
+ };
242
+ assert_eq!(select_move_mask(&mut l, i).unwrap().mask, 65537);
243
+ assert!(l.linked);
244
+ i.other.origin = [-2., 0., 0.];
245
+ assert_eq!(linked_move_overlap(i.entity, i.other), Ok(true));
246
+ }
247
+ #[test]
248
+ fn type_three_bypasses_bad_geometry_and_error_preserves_links() {
249
+ let mut i = input();
250
+ i.other.origin[0] = f32::NAN;
251
+ let mut l = MoveLinks {
252
+ linked: true,
253
+ other_linked: true,
254
+ };
255
+ let old = l;
256
+ assert!(select_move_mask(&mut l, i).is_err());
257
+ assert_eq!(l, old);
258
+ i.entity.pm_type = 3;
259
+ assert_eq!(select_move_mask(&mut l, i).unwrap().overlap, None);
260
+ assert_eq!(l, old);
261
+ l.linked = false;
262
+ i.entity.pm_type = 0;
263
+ assert_eq!(select_move_mask(&mut l, i).unwrap().mask, 37814273);
264
+ i.entity_flags = 0;
265
+ assert_eq!(select_move_mask(&mut l, i).unwrap().mask, 67174401);
266
+ }
267
+ }
docs/FINDINGS.md CHANGED
@@ -1909,3 +1909,5 @@ RE-986: 90 original-QVM fixtures recover live/non-following client mask2 suppres
1909
  RE-987: Rust snapshots six raw command words after source-backed suppression, retaining negative up bytes and all unrelated command words. Ninety source/Rust fixtures compare both the mutated command and scratch copy. Unit cases cover signed byte boundaries, neighboring button preservation and dead/follow/other-mask bypasses. The typed return represents binding to the supplied client rather than a raw address. [Evidence](research/RUST_CLIENT_MOVE_SUPPRESSION.md).
1910
 
1911
  RE-988: Forty source probes recover mask precedence and execute actual151954 overlap checks. Movement-type3 bypasses links and selects65537; overlapping live type0 linked entities select the same mask. Failed overlap clears both link words and selects33619969. Unlinked entity mask8 selects37814273 before mode9/nonzero client3704 selects67174401. The helper uses strict lower-X versus upper-X overlap, inclusive remaining comparisons, positive entity health and movement-type0 on both clients; boundary fixtures expose this asymmetry. [Evidence](research/QVM_CLIENT_MOVE_MASK.md).
 
 
 
1909
  RE-987: Rust snapshots six raw command words after source-backed suppression, retaining negative up bytes and all unrelated command words. Ninety source/Rust fixtures compare both the mutated command and scratch copy. Unit cases cover signed byte boundaries, neighboring button preservation and dead/follow/other-mask bypasses. The typed return represents binding to the supplied client rather than a raw address. [Evidence](research/RUST_CLIENT_MOVE_SUPPRESSION.md).
1910
 
1911
  RE-988: Forty source probes recover mask precedence and execute actual151954 overlap checks. Movement-type3 bypasses links and selects65537; overlapping live type0 linked entities select the same mask. Failed overlap clears both link words and selects33619969. Unlinked entity mask8 selects37814273 before mode9/nonzero client3704 selects67174401. The helper uses strict lower-X versus upper-X overlap, inclusive remaining comparisons, positive entity health and movement-type0 on both clients; boundary fixtures expose this asymmetry. [Evidence](research/QVM_CLIENT_MOVE_MASK.md).
1912
+
1913
+ RE-989: Rust ports the actual linked overlap conditions and mask precedence across forty source/Rust cases. Failed overlap clears both supplied link states before returning the default mask; movement-type3 bypasses overlap entirely. Finite f32 bounds/sums are validated before mutation. Unit tests cover asymmetric touching faces, flag precedence, reciprocal cleanup, nonfinite rollback and bypassing unused invalid geometry. Native collision traces remain outside this policy. [Evidence](research/RUST_CLIENT_MOVE_MASK.md).
docs/PROVISIONAL_TODO.md CHANGED
@@ -1965,3 +1965,5 @@ RE-974–983 completed routing, command rewrite, inactivity, movement-parameter
1965
  - [x] RE-987 Port signed movement suppression and snapshot ([evidence](research/RUST_CLIENT_MOVE_SUPPRESSION.md)).
1966
 
1967
  - [x] RE-988 Recover movement masks and linked overlap cleanup ([evidence](research/QVM_CLIENT_MOVE_MASK.md)).
 
 
 
1965
  - [x] RE-987 Port signed movement suppression and snapshot ([evidence](research/RUST_CLIENT_MOVE_SUPPRESSION.md)).
1966
 
1967
  - [x] RE-988 Recover movement masks and linked overlap cleanup ([evidence](research/QVM_CLIENT_MOVE_MASK.md)).
1968
+
1969
+ - [x] RE-989 Port linked overlap and movement mask selection ([evidence](research/RUST_CLIENT_MOVE_MASK.md)).
docs/RESEARCH_LEDGER.md CHANGED
@@ -2627,3 +2627,7 @@ Rust snapshots six raw command words after source-backed suppression, retaining
2627
  ## 2026-10-29 — RE-988 Recover movement masks and linked overlap cleanup
2628
 
2629
  Forty source probes recover mask precedence and execute actual151954 overlap checks. Movement-type3 bypasses links and selects65537; overlapping live type0 linked entities select the same mask. Failed overlap clears both link words and selects33619969. Unlinked entity mask8 selects37814273 before mode9/nonzero client3704 selects67174401. The helper uses strict lower-X versus upper-X overlap, inclusive remaining comparisons, positive entity health and movement-type0 on both clients; boundary fixtures expose this asymmetry. Focused `cargo xtask test-group qvm-client-move-mask` passes with deterministic report regeneration and selected regressions. Full suite deferred to task ten. Original assets unchanged; Python uses the flake-declared Nix runtime.
 
 
 
 
 
2627
  ## 2026-10-29 — RE-988 Recover movement masks and linked overlap cleanup
2628
 
2629
  Forty source probes recover mask precedence and execute actual151954 overlap checks. Movement-type3 bypasses links and selects65537; overlapping live type0 linked entities select the same mask. Failed overlap clears both link words and selects33619969. Unlinked entity mask8 selects37814273 before mode9/nonzero client3704 selects67174401. The helper uses strict lower-X versus upper-X overlap, inclusive remaining comparisons, positive entity health and movement-type0 on both clients; boundary fixtures expose this asymmetry. Focused `cargo xtask test-group qvm-client-move-mask` passes with deterministic report regeneration and selected regressions. Full suite deferred to task ten. Original assets unchanged; Python uses the flake-declared Nix runtime.
2630
+
2631
+ ## 2026-10-29 — RE-989 Port linked overlap and movement mask selection
2632
+
2633
+ Rust ports the actual linked overlap conditions and mask precedence across forty source/Rust cases. Failed overlap clears both supplied link states before returning the default mask; movement-type3 bypasses overlap entirely. Finite f32 bounds/sums are validated before mutation. Unit tests cover asymmetric touching faces, flag precedence, reciprocal cleanup, nonfinite rollback and bypassing unused invalid geometry. Native collision traces remain outside this policy. Focused `cargo xtask test-group rust-client-move-mask` passes with deterministic report regeneration and selected regressions. Full suite deferred to task ten. Original assets unchanged; Python uses the flake-declared Nix runtime.
docs/REVERSE_ENGINEERING_TODO.md CHANGED
@@ -2002,3 +2002,5 @@ RE-974–983 recover routing, command rewriting, inactivity and composed setup t
2002
  - [x] RE-987 Port signed movement suppression and snapshot ([evidence](research/RUST_CLIENT_MOVE_SUPPRESSION.md)).
2003
 
2004
  - [x] RE-988 Recover movement masks and linked overlap cleanup ([evidence](research/QVM_CLIENT_MOVE_MASK.md)).
 
 
 
2002
  - [x] RE-987 Port signed movement suppression and snapshot ([evidence](research/RUST_CLIENT_MOVE_SUPPRESSION.md)).
2003
 
2004
  - [x] RE-988 Recover movement masks and linked overlap cleanup ([evidence](research/QVM_CLIENT_MOVE_MASK.md)).
2005
+
2006
+ - [x] RE-989 Port linked overlap and movement mask selection ([evidence](research/RUST_CLIENT_MOVE_MASK.md)).
docs/research/README.md CHANGED
@@ -1537,3 +1537,5 @@ The extension collector adds five focused tests for native tail calls, command-r
1537
  - [RE-987: Port signed movement suppression and snapshot](RUST_CLIENT_MOVE_SUPPRESSION.md).
1538
 
1539
  - [RE-988: Recover movement masks and linked overlap cleanup](QVM_CLIENT_MOVE_MASK.md).
 
 
 
1537
  - [RE-987: Port signed movement suppression and snapshot](RUST_CLIENT_MOVE_SUPPRESSION.md).
1538
 
1539
  - [RE-988: Recover movement masks and linked overlap cleanup](QVM_CLIENT_MOVE_MASK.md).
1540
+
1541
+ - [RE-989: Port linked overlap and movement mask selection](RUST_CLIENT_MOVE_MASK.md).
docs/research/RUST_CLIENT_MOVE_MASK.md ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ # Port linked overlap and movement mask selection
2
+
3
+ RE-989. Focused validation: `cargo xtask test-group rust-client-move-mask`. [Machine report](rust-client-move-mask.json).
4
+
5
+ Rust ports the actual linked overlap conditions and mask precedence across forty source/Rust cases. Failed overlap clears both supplied link states before returning the default mask; movement-type3 bypasses overlap entirely. Finite f32 bounds/sums are validated before mutation. Unit tests cover asymmetric touching faces, flag precedence, reciprocal cleanup, nonfinite rollback and bypassing unused invalid geometry. Native collision traces remain outside this policy.
docs/research/rust-client-move-mask.json ADDED
@@ -0,0 +1,615 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "limits": "Finite source/Rust contract parity; native time/file/network replies remain supplied or captured.",
3
+ "probes": [
4
+ {
5
+ "rust": {
6
+ "linked": false,
7
+ "mask": 33619969,
8
+ "other_linked": true,
9
+ "overlap_results": []
10
+ },
11
+ "source": {
12
+ "linked": false,
13
+ "mask": 33619969,
14
+ "other_linked": true,
15
+ "overlap_results": []
16
+ }
17
+ },
18
+ {
19
+ "rust": {
20
+ "linked": false,
21
+ "mask": 33619969,
22
+ "other_linked": true,
23
+ "overlap_results": []
24
+ },
25
+ "source": {
26
+ "linked": false,
27
+ "mask": 33619969,
28
+ "other_linked": true,
29
+ "overlap_results": []
30
+ }
31
+ },
32
+ {
33
+ "rust": {
34
+ "linked": false,
35
+ "mask": 33619969,
36
+ "other_linked": true,
37
+ "overlap_results": []
38
+ },
39
+ "source": {
40
+ "linked": false,
41
+ "mask": 33619969,
42
+ "other_linked": true,
43
+ "overlap_results": []
44
+ }
45
+ },
46
+ {
47
+ "rust": {
48
+ "linked": false,
49
+ "mask": 67174401,
50
+ "other_linked": true,
51
+ "overlap_results": []
52
+ },
53
+ "source": {
54
+ "linked": false,
55
+ "mask": 67174401,
56
+ "other_linked": true,
57
+ "overlap_results": []
58
+ }
59
+ },
60
+ {
61
+ "rust": {
62
+ "linked": false,
63
+ "mask": 37814273,
64
+ "other_linked": true,
65
+ "overlap_results": []
66
+ },
67
+ "source": {
68
+ "linked": false,
69
+ "mask": 37814273,
70
+ "other_linked": true,
71
+ "overlap_results": []
72
+ }
73
+ },
74
+ {
75
+ "rust": {
76
+ "linked": false,
77
+ "mask": 37814273,
78
+ "other_linked": true,
79
+ "overlap_results": []
80
+ },
81
+ "source": {
82
+ "linked": false,
83
+ "mask": 37814273,
84
+ "other_linked": true,
85
+ "overlap_results": []
86
+ }
87
+ },
88
+ {
89
+ "rust": {
90
+ "linked": false,
91
+ "mask": 37814273,
92
+ "other_linked": true,
93
+ "overlap_results": []
94
+ },
95
+ "source": {
96
+ "linked": false,
97
+ "mask": 37814273,
98
+ "other_linked": true,
99
+ "overlap_results": []
100
+ }
101
+ },
102
+ {
103
+ "rust": {
104
+ "linked": false,
105
+ "mask": 37814273,
106
+ "other_linked": true,
107
+ "overlap_results": []
108
+ },
109
+ "source": {
110
+ "linked": false,
111
+ "mask": 37814273,
112
+ "other_linked": true,
113
+ "overlap_results": []
114
+ }
115
+ },
116
+ {
117
+ "rust": {
118
+ "linked": false,
119
+ "mask": 65537,
120
+ "other_linked": true,
121
+ "overlap_results": []
122
+ },
123
+ "source": {
124
+ "linked": false,
125
+ "mask": 65537,
126
+ "other_linked": true,
127
+ "overlap_results": []
128
+ }
129
+ },
130
+ {
131
+ "rust": {
132
+ "linked": false,
133
+ "mask": 65537,
134
+ "other_linked": true,
135
+ "overlap_results": []
136
+ },
137
+ "source": {
138
+ "linked": false,
139
+ "mask": 65537,
140
+ "other_linked": true,
141
+ "overlap_results": []
142
+ }
143
+ },
144
+ {
145
+ "rust": {
146
+ "linked": false,
147
+ "mask": 65537,
148
+ "other_linked": true,
149
+ "overlap_results": []
150
+ },
151
+ "source": {
152
+ "linked": false,
153
+ "mask": 65537,
154
+ "other_linked": true,
155
+ "overlap_results": []
156
+ }
157
+ },
158
+ {
159
+ "rust": {
160
+ "linked": false,
161
+ "mask": 65537,
162
+ "other_linked": true,
163
+ "overlap_results": []
164
+ },
165
+ "source": {
166
+ "linked": false,
167
+ "mask": 65537,
168
+ "other_linked": true,
169
+ "overlap_results": []
170
+ }
171
+ },
172
+ {
173
+ "rust": {
174
+ "linked": false,
175
+ "mask": 65537,
176
+ "other_linked": true,
177
+ "overlap_results": []
178
+ },
179
+ "source": {
180
+ "linked": false,
181
+ "mask": 65537,
182
+ "other_linked": true,
183
+ "overlap_results": []
184
+ }
185
+ },
186
+ {
187
+ "rust": {
188
+ "linked": false,
189
+ "mask": 65537,
190
+ "other_linked": true,
191
+ "overlap_results": []
192
+ },
193
+ "source": {
194
+ "linked": false,
195
+ "mask": 65537,
196
+ "other_linked": true,
197
+ "overlap_results": []
198
+ }
199
+ },
200
+ {
201
+ "rust": {
202
+ "linked": false,
203
+ "mask": 65537,
204
+ "other_linked": true,
205
+ "overlap_results": []
206
+ },
207
+ "source": {
208
+ "linked": false,
209
+ "mask": 65537,
210
+ "other_linked": true,
211
+ "overlap_results": []
212
+ }
213
+ },
214
+ {
215
+ "rust": {
216
+ "linked": false,
217
+ "mask": 65537,
218
+ "other_linked": true,
219
+ "overlap_results": []
220
+ },
221
+ "source": {
222
+ "linked": false,
223
+ "mask": 65537,
224
+ "other_linked": true,
225
+ "overlap_results": []
226
+ }
227
+ },
228
+ {
229
+ "rust": {
230
+ "linked": true,
231
+ "mask": 65537,
232
+ "other_linked": true,
233
+ "overlap_results": [
234
+ 1
235
+ ]
236
+ },
237
+ "source": {
238
+ "linked": true,
239
+ "mask": 65537,
240
+ "other_linked": true,
241
+ "overlap_results": [
242
+ 1
243
+ ]
244
+ }
245
+ },
246
+ {
247
+ "rust": {
248
+ "linked": true,
249
+ "mask": 65537,
250
+ "other_linked": true,
251
+ "overlap_results": []
252
+ },
253
+ "source": {
254
+ "linked": true,
255
+ "mask": 65537,
256
+ "other_linked": true,
257
+ "overlap_results": []
258
+ }
259
+ },
260
+ {
261
+ "rust": {
262
+ "linked": false,
263
+ "mask": 33619969,
264
+ "other_linked": false,
265
+ "overlap_results": [
266
+ 0
267
+ ]
268
+ },
269
+ "source": {
270
+ "linked": false,
271
+ "mask": 33619969,
272
+ "other_linked": false,
273
+ "overlap_results": [
274
+ 0
275
+ ]
276
+ }
277
+ },
278
+ {
279
+ "rust": {
280
+ "linked": true,
281
+ "mask": 65537,
282
+ "other_linked": true,
283
+ "overlap_results": []
284
+ },
285
+ "source": {
286
+ "linked": true,
287
+ "mask": 65537,
288
+ "other_linked": true,
289
+ "overlap_results": []
290
+ }
291
+ },
292
+ {
293
+ "rust": {
294
+ "linked": true,
295
+ "mask": 65537,
296
+ "other_linked": true,
297
+ "overlap_results": [
298
+ 1
299
+ ]
300
+ },
301
+ "source": {
302
+ "linked": true,
303
+ "mask": 65537,
304
+ "other_linked": true,
305
+ "overlap_results": [
306
+ 1
307
+ ]
308
+ }
309
+ },
310
+ {
311
+ "rust": {
312
+ "linked": true,
313
+ "mask": 65537,
314
+ "other_linked": true,
315
+ "overlap_results": []
316
+ },
317
+ "source": {
318
+ "linked": true,
319
+ "mask": 65537,
320
+ "other_linked": true,
321
+ "overlap_results": []
322
+ }
323
+ },
324
+ {
325
+ "rust": {
326
+ "linked": true,
327
+ "mask": 65537,
328
+ "other_linked": true,
329
+ "overlap_results": [
330
+ 1
331
+ ]
332
+ },
333
+ "source": {
334
+ "linked": true,
335
+ "mask": 65537,
336
+ "other_linked": true,
337
+ "overlap_results": [
338
+ 1
339
+ ]
340
+ }
341
+ },
342
+ {
343
+ "rust": {
344
+ "linked": true,
345
+ "mask": 65537,
346
+ "other_linked": true,
347
+ "overlap_results": []
348
+ },
349
+ "source": {
350
+ "linked": true,
351
+ "mask": 65537,
352
+ "other_linked": true,
353
+ "overlap_results": []
354
+ }
355
+ },
356
+ {
357
+ "rust": {
358
+ "linked": true,
359
+ "mask": 65537,
360
+ "other_linked": true,
361
+ "overlap_results": [
362
+ 1
363
+ ]
364
+ },
365
+ "source": {
366
+ "linked": true,
367
+ "mask": 65537,
368
+ "other_linked": true,
369
+ "overlap_results": [
370
+ 1
371
+ ]
372
+ }
373
+ },
374
+ {
375
+ "rust": {
376
+ "linked": true,
377
+ "mask": 65537,
378
+ "other_linked": true,
379
+ "overlap_results": []
380
+ },
381
+ "source": {
382
+ "linked": true,
383
+ "mask": 65537,
384
+ "other_linked": true,
385
+ "overlap_results": []
386
+ }
387
+ },
388
+ {
389
+ "rust": {
390
+ "linked": false,
391
+ "mask": 33619969,
392
+ "other_linked": false,
393
+ "overlap_results": [
394
+ 0
395
+ ]
396
+ },
397
+ "source": {
398
+ "linked": false,
399
+ "mask": 33619969,
400
+ "other_linked": false,
401
+ "overlap_results": [
402
+ 0
403
+ ]
404
+ }
405
+ },
406
+ {
407
+ "rust": {
408
+ "linked": true,
409
+ "mask": 65537,
410
+ "other_linked": true,
411
+ "overlap_results": []
412
+ },
413
+ "source": {
414
+ "linked": true,
415
+ "mask": 65537,
416
+ "other_linked": true,
417
+ "overlap_results": []
418
+ }
419
+ },
420
+ {
421
+ "rust": {
422
+ "linked": false,
423
+ "mask": 33619969,
424
+ "other_linked": false,
425
+ "overlap_results": [
426
+ 0
427
+ ]
428
+ },
429
+ "source": {
430
+ "linked": false,
431
+ "mask": 33619969,
432
+ "other_linked": false,
433
+ "overlap_results": [
434
+ 0
435
+ ]
436
+ }
437
+ },
438
+ {
439
+ "rust": {
440
+ "linked": true,
441
+ "mask": 65537,
442
+ "other_linked": true,
443
+ "overlap_results": []
444
+ },
445
+ "source": {
446
+ "linked": true,
447
+ "mask": 65537,
448
+ "other_linked": true,
449
+ "overlap_results": []
450
+ }
451
+ },
452
+ {
453
+ "rust": {
454
+ "linked": false,
455
+ "mask": 33619969,
456
+ "other_linked": false,
457
+ "overlap_results": [
458
+ 0
459
+ ]
460
+ },
461
+ "source": {
462
+ "linked": false,
463
+ "mask": 33619969,
464
+ "other_linked": false,
465
+ "overlap_results": [
466
+ 0
467
+ ]
468
+ }
469
+ },
470
+ {
471
+ "rust": {
472
+ "linked": true,
473
+ "mask": 65537,
474
+ "other_linked": true,
475
+ "overlap_results": []
476
+ },
477
+ "source": {
478
+ "linked": true,
479
+ "mask": 65537,
480
+ "other_linked": true,
481
+ "overlap_results": []
482
+ }
483
+ },
484
+ {
485
+ "rust": {
486
+ "linked": false,
487
+ "mask": 33619969,
488
+ "other_linked": false,
489
+ "overlap_results": [
490
+ 0
491
+ ]
492
+ },
493
+ "source": {
494
+ "linked": false,
495
+ "mask": 33619969,
496
+ "other_linked": false,
497
+ "overlap_results": [
498
+ 0
499
+ ]
500
+ }
501
+ },
502
+ {
503
+ "rust": {
504
+ "linked": true,
505
+ "mask": 65537,
506
+ "other_linked": true,
507
+ "overlap_results": []
508
+ },
509
+ "source": {
510
+ "linked": true,
511
+ "mask": 65537,
512
+ "other_linked": true,
513
+ "overlap_results": []
514
+ }
515
+ },
516
+ {
517
+ "rust": {
518
+ "linked": false,
519
+ "mask": 33619969,
520
+ "other_linked": false,
521
+ "overlap_results": [
522
+ 0
523
+ ]
524
+ },
525
+ "source": {
526
+ "linked": false,
527
+ "mask": 33619969,
528
+ "other_linked": false,
529
+ "overlap_results": [
530
+ 0
531
+ ]
532
+ }
533
+ },
534
+ {
535
+ "rust": {
536
+ "linked": true,
537
+ "mask": 65537,
538
+ "other_linked": true,
539
+ "overlap_results": []
540
+ },
541
+ "source": {
542
+ "linked": true,
543
+ "mask": 65537,
544
+ "other_linked": true,
545
+ "overlap_results": []
546
+ }
547
+ },
548
+ {
549
+ "rust": {
550
+ "linked": false,
551
+ "mask": 33619969,
552
+ "other_linked": false,
553
+ "overlap_results": [
554
+ 0
555
+ ]
556
+ },
557
+ "source": {
558
+ "linked": false,
559
+ "mask": 33619969,
560
+ "other_linked": false,
561
+ "overlap_results": [
562
+ 0
563
+ ]
564
+ }
565
+ },
566
+ {
567
+ "rust": {
568
+ "linked": true,
569
+ "mask": 65537,
570
+ "other_linked": true,
571
+ "overlap_results": []
572
+ },
573
+ "source": {
574
+ "linked": true,
575
+ "mask": 65537,
576
+ "other_linked": true,
577
+ "overlap_results": []
578
+ }
579
+ },
580
+ {
581
+ "rust": {
582
+ "linked": false,
583
+ "mask": 33619969,
584
+ "other_linked": false,
585
+ "overlap_results": [
586
+ 0
587
+ ]
588
+ },
589
+ "source": {
590
+ "linked": false,
591
+ "mask": 33619969,
592
+ "other_linked": false,
593
+ "overlap_results": [
594
+ 0
595
+ ]
596
+ }
597
+ },
598
+ {
599
+ "rust": {
600
+ "linked": true,
601
+ "mask": 65537,
602
+ "other_linked": true,
603
+ "overlap_results": []
604
+ },
605
+ "source": {
606
+ "linked": true,
607
+ "mask": 65537,
608
+ "other_linked": true,
609
+ "overlap_results": []
610
+ }
611
+ }
612
+ ],
613
+ "source_report": "docs/research/qvm-client-move-mask.json",
614
+ "source_report_sha256": "43f14f7ed6a171aa267b4ab52c230a5bd9fd1465ad3cc0ce9ca7e6d5fbccc99f"
615
+ }
docs/research/rust-health-impulse.json CHANGED
@@ -2985,7 +2985,7 @@
2985
  "exit_code": 2
2986
  }
2987
  ],
2988
- "rust_unit_tests": 244,
2989
  "source_report": "docs/research/qvm-health-impulse.json",
2990
  "source_report_sha256": "625fd8064004ea6dbdf398d51d0af844d9c635ff04c0a0790886dddb6ab81e71"
2991
  }
 
2985
  "exit_code": 2
2986
  }
2987
  ],
2988
+ "rust_unit_tests": 246,
2989
  "source_report": "docs/research/qvm-health-impulse.json",
2990
  "source_report_sha256": "625fd8064004ea6dbdf398d51d0af844d9c635ff04c0a0790886dddb6ab81e71"
2991
  }
scripts/analyze_rust_client_move_mask.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Compare recovered Rust policy with original QVM fixtures."""
2
+ import hashlib,json,os,subprocess
3
+ from pathlib import Path
4
+ from analyze_qvm import write_json
5
+ from rust_lifecycle_support import result
6
+
7
+ def main():
8
+ subprocess.run(['cargo','build','--offline','--package','urt-gameplay','--bin','urt-client-move-context'],check=True,capture_output=True)
9
+ binary=Path(os.environ.get('CARGO_TARGET_DIR','target'))/'debug'/'urt-client-move-context'
10
+ path=Path('docs/research/qvm-client-move-mask.json');data=path.read_bytes();probes=[]
11
+ for p in json.loads(data)['probes']:
12
+ probes.append(dict(source={k:p[k] for k in ['mask', 'linked', 'other_linked', 'overlap_results']},rust=result(binary,'mask',encode(p['input']))))
13
+ write_json(Path('docs/research/rust-client-move-mask.json'),dict(source_report=str(path),source_report_sha256=hashlib.sha256(data).hexdigest(),probes=probes,limits='Finite source/Rust contract parity; native time/file/network replies remain supplied or captured.'))
14
+
15
+ def encode(a):
16
+ from analyze_qvm_acceleration import word
17
+ return [a['pm_type'],a['linked'],a['entity_flags'],a['mode'],a['ghost'],a['other_pm'],a['other_health'],a['self_health'],*[word(v) for v in a['origin']],1]
18
+ if __name__=='__main__':main()
scripts/test_rust_client_move_mask.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ import hashlib,json,unittest
2
+ from pathlib import Path
3
+ class PortTests(unittest.TestCase):
4
+ def test_original_parity(self):
5
+ r=json.loads(Path('docs/research/rust-client-move-mask.json').read_text());self.assertGreaterEqual(len(r['probes']),12)
6
+ for p in r['probes']:self.assertEqual(p['source'],p['rust'])
7
+ def test_identity(self):
8
+ r=json.loads(Path('docs/research/rust-client-move-mask.json').read_text());self.assertEqual(hashlib.sha256(Path(r['source_report']).read_bytes()).hexdigest(),r['source_report_sha256'])
9
+ if __name__=='__main__':unittest.main()
xtask/checks.tsv CHANGED
@@ -3732,3 +3732,27 @@ report scripts/analyze_qvm_client_move_mask.py docs/research/qvm-client-move-mas
3732
  edge docs/research/qvm-client-move-mask.json scripts/test_qvm_client_move_mask.py
3733
  group qvm-client-move-mask scripts/analyze_qvm_client_move_mask.py
3734
  edge scripts/analyze_qvm_client_move_mask.py scripts/analyze_qvm_resumer_audit.py
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3732
  edge docs/research/qvm-client-move-mask.json scripts/test_qvm_client_move_mask.py
3733
  group qvm-client-move-mask scripts/analyze_qvm_client_move_mask.py
3734
  edge scripts/analyze_qvm_client_move_mask.py scripts/analyze_qvm_resumer_audit.py
3735
+ report scripts/analyze_rust_client_move_mask.py docs/research/rust-client-move-mask.json
3736
+ edge docs/research/rust-client-move-mask.json scripts/test_rust_client_move_mask.py
3737
+ group rust-client-move-mask scripts/analyze_rust_client_move_mask.py
3738
+ edge scripts/analyze_rust_client_move_mask.py scripts/analyze_qvm_resumer_audit.py
3739
+ edge Cargo.toml scripts/analyze_rust_client_move_mask.py
3740
+ edge Cargo.lock scripts/analyze_rust_client_move_mask.py
3741
+ edge crates/urt-gameplay/Cargo.toml scripts/analyze_rust_client_move_mask.py
3742
+ edge crates/urt-gameplay/src/lib.rs scripts/analyze_rust_client_move_mask.py
3743
+ edge crates/urt-gameplay/src/filter_loading.rs scripts/analyze_rust_client_move_mask.py
3744
+ edge crates/urt-gameplay/src/filter_lifecycle.rs scripts/analyze_rust_client_move_mask.py
3745
+ edge crates/urt-gameplay/src/native_policy.rs scripts/analyze_rust_client_move_mask.py
3746
+ edge crates/urt-gameplay/src/bin/urt-filter-loading.rs scripts/analyze_rust_client_move_mask.py
3747
+ edge crates/urt-gameplay/src/qvm_format.rs scripts/analyze_rust_client_move_mask.py
3748
+ edge docs/research/qvm-client-move-mask.json scripts/analyze_rust_client_move_mask.py
3749
+ group rust-client-move-mask scripts/analyze_rust_health_impulse.py
3750
+ group gameplay scripts/analyze_rust_client_move_mask.py
3751
+ edge crates/urt-gameplay/src/filter_commands.rs scripts/analyze_rust_client_move_mask.py
3752
+ edge crates/urt-gameplay/src/bin/urt-filter-commands.rs scripts/analyze_rust_client_move_mask.py
3753
+ edge crates/urt-gameplay/src/client_timer.rs scripts/analyze_rust_client_move_mask.py
3754
+ edge crates/urt-gameplay/src/bin/urt-client-timer.rs scripts/analyze_rust_client_move_mask.py
3755
+ edge crates/urt-gameplay/src/client_processing.rs scripts/analyze_rust_client_move_mask.py
3756
+ edge crates/urt-gameplay/src/bin/urt-client-processing.rs scripts/analyze_rust_client_move_mask.py
3757
+ edge crates/urt-gameplay/src/client_move_context.rs scripts/analyze_rust_client_move_mask.py
3758
+ edge crates/urt-gameplay/src/bin/urt-client-move-context.rs scripts/analyze_rust_client_move_mask.py
xtask/src/lib.rs CHANGED
@@ -1133,6 +1133,7 @@ mod integration_tests {
1133
  ("filter_commands", "filter_add_command"),
1134
  ("client_timer", "client_timer_terminal"),
1135
  ("client_move_context", "client_move_suppression"),
 
1136
  ("client_move_context", "client_move_scratch"),
1137
  ("client_processing", "client_routing"),
1138
  ("client_timer", "client_routing"),
@@ -1348,6 +1349,7 @@ mod integration_tests {
1348
  ("qvm-filter-add-command", "filter_add_command"),
1349
  ("qvm-client-timer-terminal", "client_timer_terminal"),
1350
  ("qvm-client-move-suppression", "client_move_suppression"),
 
1351
  ("qvm-client-move-scratch", "client_move_scratch"),
1352
  ("qvm-client-routing", "client_routing"),
1353
  ("qvm-client-command-rewrite", "client_command_rewrite"),
 
1133
  ("filter_commands", "filter_add_command"),
1134
  ("client_timer", "client_timer_terminal"),
1135
  ("client_move_context", "client_move_suppression"),
1136
+ ("client_move_context", "client_move_mask"),
1137
  ("client_move_context", "client_move_scratch"),
1138
  ("client_processing", "client_routing"),
1139
  ("client_timer", "client_routing"),
 
1349
  ("qvm-filter-add-command", "filter_add_command"),
1350
  ("qvm-client-timer-terminal", "client_timer_terminal"),
1351
  ("qvm-client-move-suppression", "client_move_suppression"),
1352
+ ("qvm-client-move-mask", "client_move_mask"),
1353
  ("qvm-client-move-scratch", "client_move_scratch"),
1354
  ("qvm-client-routing", "client_routing"),
1355
  ("qvm-client-command-rewrite", "client_command_rewrite"),