nmarshall commited on
Commit
ac0c9c0
·
1 Parent(s): 707168b

gameplay: port bounded location text semantics

Browse files
crates/urt-gameplay/src/bin/urt-location-feedback.rs CHANGED
@@ -20,6 +20,7 @@ fn main() {
20
  let w: Vec<u32> = args.map(|v| v.parse().unwrap()).collect();
21
  match kind.as_str() {
22
  "nearest" => println!("{}", nearest(&w)),
 
23
  _ => panic!("unknown contract"),
24
  }
25
  }
@@ -75,3 +76,27 @@ fn nearest(w: &[u32]) -> String {
75
  optional(out.cache)
76
  )
77
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  let w: Vec<u32> = args.map(|v| v.parse().unwrap()).collect();
21
  match kind.as_str() {
22
  "nearest" => println!("{}", nearest(&w)),
23
+ "text" => println!("{}", text(&w)),
24
  _ => panic!("unknown contract"),
25
  }
26
  }
 
76
  optional(out.cache)
77
  )
78
  }
79
+
80
+ fn text(w: &[u32]) -> String {
81
+ assert!(w.len() >= 3);
82
+ assert_eq!(w.len(), 3 + w[2] as usize);
83
+ let payload = w[3..].iter().map(|v| *v as u8).collect::<Vec<_>>();
84
+ let mut guarded = vec![65; w[1] as usize + 8];
85
+ let out = location_text(&mut guarded[4..4 + w[1] as usize], || {
86
+ if w[0] != 0 {
87
+ Some(payload.as_slice())
88
+ } else {
89
+ None
90
+ }
91
+ })
92
+ .unwrap();
93
+ format!(
94
+ r#"{{"result":{},"buffer":"{}","guards":["{}","{}"],"warnings":{},"lookups":{}}}"#,
95
+ u32::from(out.result),
96
+ hex(&guarded[4..4 + w[1] as usize]),
97
+ hex(&guarded[..4]),
98
+ hex(&guarded[4 + w[1] as usize..]),
99
+ out.warnings,
100
+ out.lookups
101
+ )
102
+ }
crates/urt-gameplay/src/location_feedback.rs CHANGED
@@ -147,3 +147,68 @@ mod nearest_tests {
147
  );
148
  }
149
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
  );
148
  }
149
  }
150
+
151
+ #[derive(Clone, Copy, Debug, PartialEq, Eq)]
152
+ pub struct LocationTextOutcome {
153
+ pub result: bool,
154
+ pub warnings: usize,
155
+ pub lookups: usize,
156
+ }
157
+ /// Original268637 with actual bounded formatter policy. Missing location leaves
158
+ /// the destination untouched; a found empty/clipped string still returns true.
159
+ pub fn location_text<'a>(
160
+ destination: &mut [u8],
161
+ mut lookup: impl FnMut() -> Option<&'a [u8]>,
162
+ ) -> Result<LocationTextOutcome, Error> {
163
+ let Some(text) = lookup() else {
164
+ return Ok(LocationTextOutcome {
165
+ result: false,
166
+ warnings: 0,
167
+ lookups: 1,
168
+ });
169
+ };
170
+ let bounded = crate::qvm_format::bounded(
171
+ b"%s",
172
+ &[crate::qvm_format::Argument::Bytes(Some(text))],
173
+ destination.len(),
174
+ )
175
+ .map_err(|_| Error::InvalidInput)?;
176
+ destination.copy_from_slice(&bounded.bytes);
177
+ Ok(LocationTextOutcome {
178
+ result: true,
179
+ warnings: usize::from(bounded.warning),
180
+ lookups: 1,
181
+ })
182
+ }
183
+ #[cfg(test)]
184
+ mod text_tests {
185
+ use super::*;
186
+ #[test]
187
+ fn missing_preserves_buffer_and_found_clipping_returns_true() {
188
+ let mut b = [65; 4];
189
+ assert!(!location_text(&mut b, || None).unwrap().result);
190
+ assert_eq!(b, [65; 4]);
191
+ let out = location_text(&mut b, || Some(b"ABCDE")).unwrap();
192
+ assert!(out.result);
193
+ assert_eq!(out.warnings, 1);
194
+ assert_eq!(&b, b"ABC\0");
195
+ let mut b = [65; 1];
196
+ assert!(location_text(&mut b, || Some(b"A")).unwrap().result);
197
+ assert_eq!(b, [0]);
198
+ }
199
+ #[test]
200
+ fn lookup_once_and_invalid_capacity_is_atomic() {
201
+ let mut n = 0;
202
+ let mut b = [65; 8];
203
+ location_text(&mut b, || {
204
+ n += 1;
205
+ Some(b"A\"B")
206
+ })
207
+ .unwrap();
208
+ assert_eq!(n, 1);
209
+ assert_eq!(&b[..4], b"A\"B\0");
210
+ let mut b = [];
211
+ assert!(location_text(&mut b, || Some(b"A")).is_err());
212
+ assert!(!location_text(&mut b, || None).unwrap().result);
213
+ }
214
+ }
docs/FINDINGS.md CHANGED
@@ -2015,3 +2015,5 @@ RE-1034: Sixteen original-QVM cases recover268248. A cached pointer returns only
2015
  RE-1035: Rust matches16 original location-selection cases with signed cache expiry, supplied query order, trigger precedence, PVS filtering and later-wins distance ties. Typed indices and finite math reject unsupported domains. Cache values remain unchanged; tests show live cache bypasses unused invalid geometry and trigger selection bypasses the fallback list. Engine query/PVS and identity remain supplied inputs. [Evidence](research/RUST_LOCATION_NEAREST.md).
2016
 
2017
  RE-1036: Twenty-four source cases execute268637 with actual70386/37914 formatting and bounded-copy helpers. Missing location returns0 without clearing the destination. Found location returns1 even for empty or clipped text; capacity clipping emits the original warning and preserves neighboring bytes. Empty/quoted text and capacities1/4/16/150 are covered. The selected location pointer remains supplied in this wrapper contract. [Evidence](research/QVM_LOCATION_TEXT.md).
 
 
 
2015
  RE-1035: Rust matches16 original location-selection cases with signed cache expiry, supplied query order, trigger precedence, PVS filtering and later-wins distance ties. Typed indices and finite math reject unsupported domains. Cache values remain unchanged; tests show live cache bypasses unused invalid geometry and trigger selection bypasses the fallback list. Engine query/PVS and identity remain supplied inputs. [Evidence](research/RUST_LOCATION_NEAREST.md).
2016
 
2017
  RE-1036: Twenty-four source cases execute268637 with actual70386/37914 formatting and bounded-copy helpers. Missing location returns0 without clearing the destination. Found location returns1 even for empty or clipped text; capacity clipping emits the original warning and preserves neighboring bytes. Empty/quoted text and capacities1/4/16/150 are covered. The selected location pointer remains supplied in this wrapper contract. [Evidence](research/QVM_LOCATION_TEXT.md).
2018
+
2019
+ RE-1037: Rust composes one location lookup with the recovered bounded formatter across24 source cases. Missing location preserves destination bytes; found empty/clipped text returns true with matching warning behavior and zero padding. Typed slices preserve guards. Unit cases cover one lookup, quoted bytes, capacity1, missing zero-capacity bypass and unsupported found-capacity rejection. [Evidence](research/RUST_LOCATION_TEXT.md).
docs/PROVISIONAL_TODO.md CHANGED
@@ -2076,3 +2076,5 @@ RE-974–983 completed routing, command rewrite, inactivity, movement-parameter
2076
  - [x] RE-1035 Port cached trigger and nearest location policy ([evidence](research/RUST_LOCATION_NEAREST.md)).
2077
 
2078
  - [x] RE-1036 Recover location text wrapper and bounded formatting ([evidence](research/QVM_LOCATION_TEXT.md)).
 
 
 
2076
  - [x] RE-1035 Port cached trigger and nearest location policy ([evidence](research/RUST_LOCATION_NEAREST.md)).
2077
 
2078
  - [x] RE-1036 Recover location text wrapper and bounded formatting ([evidence](research/QVM_LOCATION_TEXT.md)).
2079
+
2080
+ - [x] RE-1037 Port bounded location text and missing-result semantics ([evidence](research/RUST_LOCATION_TEXT.md)).
docs/RESEARCH_LEDGER.md CHANGED
@@ -2819,3 +2819,7 @@ Rust matches16 original location-selection cases with signed cache expiry, suppl
2819
  ## 2026-10-29 — RE-1036 Recover location text wrapper and bounded formatting
2820
 
2821
  Twenty-four source cases execute268637 with actual70386/37914 formatting and bounded-copy helpers. Missing location returns0 without clearing the destination. Found location returns1 even for empty or clipped text; capacity clipping emits the original warning and preserves neighboring bytes. Empty/quoted text and capacities1/4/16/150 are covered. The selected location pointer remains supplied in this wrapper contract. Focused `cargo xtask test-group qvm-location-text` passes with deterministic report regeneration and selected regressions. Full suite deferred to task ten. Original assets unchanged; Python uses the flake-declared Nix runtime.
 
 
 
 
 
2819
  ## 2026-10-29 — RE-1036 Recover location text wrapper and bounded formatting
2820
 
2821
  Twenty-four source cases execute268637 with actual70386/37914 formatting and bounded-copy helpers. Missing location returns0 without clearing the destination. Found location returns1 even for empty or clipped text; capacity clipping emits the original warning and preserves neighboring bytes. Empty/quoted text and capacities1/4/16/150 are covered. The selected location pointer remains supplied in this wrapper contract. Focused `cargo xtask test-group qvm-location-text` passes with deterministic report regeneration and selected regressions. Full suite deferred to task ten. Original assets unchanged; Python uses the flake-declared Nix runtime.
2822
+
2823
+ ## 2026-10-29 — RE-1037 Port bounded location text and missing-result semantics
2824
+
2825
+ Rust composes one location lookup with the recovered bounded formatter across24 source cases. Missing location preserves destination bytes; found empty/clipped text returns true with matching warning behavior and zero padding. Typed slices preserve guards. Unit cases cover one lookup, quoted bytes, capacity1, missing zero-capacity bypass and unsupported found-capacity rejection. Focused `cargo xtask test-group rust-location-text` 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
@@ -2113,3 +2113,5 @@ RE-974–983 recover routing, command rewriting, inactivity and composed setup t
2113
  - [x] RE-1035 Port cached trigger and nearest location policy ([evidence](research/RUST_LOCATION_NEAREST.md)).
2114
 
2115
  - [x] RE-1036 Recover location text wrapper and bounded formatting ([evidence](research/QVM_LOCATION_TEXT.md)).
 
 
 
2113
  - [x] RE-1035 Port cached trigger and nearest location policy ([evidence](research/RUST_LOCATION_NEAREST.md)).
2114
 
2115
  - [x] RE-1036 Recover location text wrapper and bounded formatting ([evidence](research/QVM_LOCATION_TEXT.md)).
2116
+
2117
+ - [x] RE-1037 Port bounded location text and missing-result semantics ([evidence](research/RUST_LOCATION_TEXT.md)).
docs/research/README.md CHANGED
@@ -1643,3 +1643,5 @@ The extension collector adds five focused tests for native tail calls, command-r
1643
  - [RE-1035: Port cached trigger and nearest location policy](RUST_LOCATION_NEAREST.md).
1644
 
1645
  - [RE-1036: Recover location text wrapper and bounded formatting](QVM_LOCATION_TEXT.md).
 
 
 
1643
  - [RE-1035: Port cached trigger and nearest location policy](RUST_LOCATION_NEAREST.md).
1644
 
1645
  - [RE-1036: Recover location text wrapper and bounded formatting](QVM_LOCATION_TEXT.md).
1646
+
1647
+ - [RE-1037: Port bounded location text and missing-result semantics](RUST_LOCATION_TEXT.md).
docs/research/RUST_LOCATION_TEXT.md ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ # Port bounded location text and missing-result semantics
2
+
3
+ RE-1037. Focused validation: `cargo xtask test-group rust-location-text`. [Machine report](rust-location-text.json).
4
+
5
+ Rust composes one location lookup with the recovered bounded formatter across24 source cases. Missing location preserves destination bytes; found empty/clipped text returns true with matching warning behavior and zero padding. Typed slices preserve guards. Unit cases cover one lookup, quoted bytes, capacity1, missing zero-capacity bypass and unsupported found-capacity rejection.
docs/research/rust-health-impulse.json CHANGED
@@ -2985,7 +2985,7 @@
2985
  "exit_code": 2
2986
  }
2987
  ],
2988
- "rust_unit_tests": 291,
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": 293,
2989
  "source_report": "docs/research/qvm-health-impulse.json",
2990
  "source_report_sha256": "625fd8064004ea6dbdf398d51d0af844d9c635ff04c0a0790886dddb6ab81e71"
2991
  }
docs/research/rust-location-text.json ADDED
@@ -0,0 +1,535 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "limits": "Finite source/Rust contract parity; native time/file/network replies remain supplied or captured.",
3
+ "probes": [
4
+ {
5
+ "rust": {
6
+ "buffer": "41",
7
+ "guards": [
8
+ "41414141",
9
+ "41414141"
10
+ ],
11
+ "lookups": 1,
12
+ "result": 0,
13
+ "warnings": 0
14
+ },
15
+ "source": {
16
+ "buffer": "41",
17
+ "guards": [
18
+ "41414141",
19
+ "41414141"
20
+ ],
21
+ "lookups": 1,
22
+ "result": 0,
23
+ "warnings": 0
24
+ }
25
+ },
26
+ {
27
+ "rust": {
28
+ "buffer": "41",
29
+ "guards": [
30
+ "41414141",
31
+ "41414141"
32
+ ],
33
+ "lookups": 1,
34
+ "result": 0,
35
+ "warnings": 0
36
+ },
37
+ "source": {
38
+ "buffer": "41",
39
+ "guards": [
40
+ "41414141",
41
+ "41414141"
42
+ ],
43
+ "lookups": 1,
44
+ "result": 0,
45
+ "warnings": 0
46
+ }
47
+ },
48
+ {
49
+ "rust": {
50
+ "buffer": "41",
51
+ "guards": [
52
+ "41414141",
53
+ "41414141"
54
+ ],
55
+ "lookups": 1,
56
+ "result": 0,
57
+ "warnings": 0
58
+ },
59
+ "source": {
60
+ "buffer": "41",
61
+ "guards": [
62
+ "41414141",
63
+ "41414141"
64
+ ],
65
+ "lookups": 1,
66
+ "result": 0,
67
+ "warnings": 0
68
+ }
69
+ },
70
+ {
71
+ "rust": {
72
+ "buffer": "41414141",
73
+ "guards": [
74
+ "41414141",
75
+ "41414141"
76
+ ],
77
+ "lookups": 1,
78
+ "result": 0,
79
+ "warnings": 0
80
+ },
81
+ "source": {
82
+ "buffer": "41414141",
83
+ "guards": [
84
+ "41414141",
85
+ "41414141"
86
+ ],
87
+ "lookups": 1,
88
+ "result": 0,
89
+ "warnings": 0
90
+ }
91
+ },
92
+ {
93
+ "rust": {
94
+ "buffer": "41414141",
95
+ "guards": [
96
+ "41414141",
97
+ "41414141"
98
+ ],
99
+ "lookups": 1,
100
+ "result": 0,
101
+ "warnings": 0
102
+ },
103
+ "source": {
104
+ "buffer": "41414141",
105
+ "guards": [
106
+ "41414141",
107
+ "41414141"
108
+ ],
109
+ "lookups": 1,
110
+ "result": 0,
111
+ "warnings": 0
112
+ }
113
+ },
114
+ {
115
+ "rust": {
116
+ "buffer": "41414141",
117
+ "guards": [
118
+ "41414141",
119
+ "41414141"
120
+ ],
121
+ "lookups": 1,
122
+ "result": 0,
123
+ "warnings": 0
124
+ },
125
+ "source": {
126
+ "buffer": "41414141",
127
+ "guards": [
128
+ "41414141",
129
+ "41414141"
130
+ ],
131
+ "lookups": 1,
132
+ "result": 0,
133
+ "warnings": 0
134
+ }
135
+ },
136
+ {
137
+ "rust": {
138
+ "buffer": "41414141414141414141414141414141",
139
+ "guards": [
140
+ "41414141",
141
+ "41414141"
142
+ ],
143
+ "lookups": 1,
144
+ "result": 0,
145
+ "warnings": 0
146
+ },
147
+ "source": {
148
+ "buffer": "41414141414141414141414141414141",
149
+ "guards": [
150
+ "41414141",
151
+ "41414141"
152
+ ],
153
+ "lookups": 1,
154
+ "result": 0,
155
+ "warnings": 0
156
+ }
157
+ },
158
+ {
159
+ "rust": {
160
+ "buffer": "41414141414141414141414141414141",
161
+ "guards": [
162
+ "41414141",
163
+ "41414141"
164
+ ],
165
+ "lookups": 1,
166
+ "result": 0,
167
+ "warnings": 0
168
+ },
169
+ "source": {
170
+ "buffer": "41414141414141414141414141414141",
171
+ "guards": [
172
+ "41414141",
173
+ "41414141"
174
+ ],
175
+ "lookups": 1,
176
+ "result": 0,
177
+ "warnings": 0
178
+ }
179
+ },
180
+ {
181
+ "rust": {
182
+ "buffer": "41414141414141414141414141414141",
183
+ "guards": [
184
+ "41414141",
185
+ "41414141"
186
+ ],
187
+ "lookups": 1,
188
+ "result": 0,
189
+ "warnings": 0
190
+ },
191
+ "source": {
192
+ "buffer": "41414141414141414141414141414141",
193
+ "guards": [
194
+ "41414141",
195
+ "41414141"
196
+ ],
197
+ "lookups": 1,
198
+ "result": 0,
199
+ "warnings": 0
200
+ }
201
+ },
202
+ {
203
+ "rust": {
204
+ "buffer": "414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141",
205
+ "guards": [
206
+ "41414141",
207
+ "41414141"
208
+ ],
209
+ "lookups": 1,
210
+ "result": 0,
211
+ "warnings": 0
212
+ },
213
+ "source": {
214
+ "buffer": "414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141",
215
+ "guards": [
216
+ "41414141",
217
+ "41414141"
218
+ ],
219
+ "lookups": 1,
220
+ "result": 0,
221
+ "warnings": 0
222
+ }
223
+ },
224
+ {
225
+ "rust": {
226
+ "buffer": "414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141",
227
+ "guards": [
228
+ "41414141",
229
+ "41414141"
230
+ ],
231
+ "lookups": 1,
232
+ "result": 0,
233
+ "warnings": 0
234
+ },
235
+ "source": {
236
+ "buffer": "414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141",
237
+ "guards": [
238
+ "41414141",
239
+ "41414141"
240
+ ],
241
+ "lookups": 1,
242
+ "result": 0,
243
+ "warnings": 0
244
+ }
245
+ },
246
+ {
247
+ "rust": {
248
+ "buffer": "414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141",
249
+ "guards": [
250
+ "41414141",
251
+ "41414141"
252
+ ],
253
+ "lookups": 1,
254
+ "result": 0,
255
+ "warnings": 0
256
+ },
257
+ "source": {
258
+ "buffer": "414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141",
259
+ "guards": [
260
+ "41414141",
261
+ "41414141"
262
+ ],
263
+ "lookups": 1,
264
+ "result": 0,
265
+ "warnings": 0
266
+ }
267
+ },
268
+ {
269
+ "rust": {
270
+ "buffer": "00",
271
+ "guards": [
272
+ "41414141",
273
+ "41414141"
274
+ ],
275
+ "lookups": 1,
276
+ "result": 1,
277
+ "warnings": 0
278
+ },
279
+ "source": {
280
+ "buffer": "00",
281
+ "guards": [
282
+ "41414141",
283
+ "41414141"
284
+ ],
285
+ "lookups": 1,
286
+ "result": 1,
287
+ "warnings": 0
288
+ }
289
+ },
290
+ {
291
+ "rust": {
292
+ "buffer": "00",
293
+ "guards": [
294
+ "41414141",
295
+ "41414141"
296
+ ],
297
+ "lookups": 1,
298
+ "result": 1,
299
+ "warnings": 1
300
+ },
301
+ "source": {
302
+ "buffer": "00",
303
+ "guards": [
304
+ "41414141",
305
+ "41414141"
306
+ ],
307
+ "lookups": 1,
308
+ "result": 1,
309
+ "warnings": 1
310
+ }
311
+ },
312
+ {
313
+ "rust": {
314
+ "buffer": "00",
315
+ "guards": [
316
+ "41414141",
317
+ "41414141"
318
+ ],
319
+ "lookups": 1,
320
+ "result": 1,
321
+ "warnings": 1
322
+ },
323
+ "source": {
324
+ "buffer": "00",
325
+ "guards": [
326
+ "41414141",
327
+ "41414141"
328
+ ],
329
+ "lookups": 1,
330
+ "result": 1,
331
+ "warnings": 1
332
+ }
333
+ },
334
+ {
335
+ "rust": {
336
+ "buffer": "00000000",
337
+ "guards": [
338
+ "41414141",
339
+ "41414141"
340
+ ],
341
+ "lookups": 1,
342
+ "result": 1,
343
+ "warnings": 0
344
+ },
345
+ "source": {
346
+ "buffer": "00000000",
347
+ "guards": [
348
+ "41414141",
349
+ "41414141"
350
+ ],
351
+ "lookups": 1,
352
+ "result": 1,
353
+ "warnings": 0
354
+ }
355
+ },
356
+ {
357
+ "rust": {
358
+ "buffer": "53697400",
359
+ "guards": [
360
+ "41414141",
361
+ "41414141"
362
+ ],
363
+ "lookups": 1,
364
+ "result": 1,
365
+ "warnings": 1
366
+ },
367
+ "source": {
368
+ "buffer": "53697400",
369
+ "guards": [
370
+ "41414141",
371
+ "41414141"
372
+ ],
373
+ "lookups": 1,
374
+ "result": 1,
375
+ "warnings": 1
376
+ }
377
+ },
378
+ {
379
+ "rust": {
380
+ "buffer": "41224200",
381
+ "guards": [
382
+ "41414141",
383
+ "41414141"
384
+ ],
385
+ "lookups": 1,
386
+ "result": 1,
387
+ "warnings": 0
388
+ },
389
+ "source": {
390
+ "buffer": "41224200",
391
+ "guards": [
392
+ "41414141",
393
+ "41414141"
394
+ ],
395
+ "lookups": 1,
396
+ "result": 1,
397
+ "warnings": 0
398
+ }
399
+ },
400
+ {
401
+ "rust": {
402
+ "buffer": "00000000000000000000000000000000",
403
+ "guards": [
404
+ "41414141",
405
+ "41414141"
406
+ ],
407
+ "lookups": 1,
408
+ "result": 1,
409
+ "warnings": 0
410
+ },
411
+ "source": {
412
+ "buffer": "00000000000000000000000000000000",
413
+ "guards": [
414
+ "41414141",
415
+ "41414141"
416
+ ],
417
+ "lookups": 1,
418
+ "result": 1,
419
+ "warnings": 0
420
+ }
421
+ },
422
+ {
423
+ "rust": {
424
+ "buffer": "53697465204100000000000000000000",
425
+ "guards": [
426
+ "41414141",
427
+ "41414141"
428
+ ],
429
+ "lookups": 1,
430
+ "result": 1,
431
+ "warnings": 0
432
+ },
433
+ "source": {
434
+ "buffer": "53697465204100000000000000000000",
435
+ "guards": [
436
+ "41414141",
437
+ "41414141"
438
+ ],
439
+ "lookups": 1,
440
+ "result": 1,
441
+ "warnings": 0
442
+ }
443
+ },
444
+ {
445
+ "rust": {
446
+ "buffer": "41224200000000000000000000000000",
447
+ "guards": [
448
+ "41414141",
449
+ "41414141"
450
+ ],
451
+ "lookups": 1,
452
+ "result": 1,
453
+ "warnings": 0
454
+ },
455
+ "source": {
456
+ "buffer": "41224200000000000000000000000000",
457
+ "guards": [
458
+ "41414141",
459
+ "41414141"
460
+ ],
461
+ "lookups": 1,
462
+ "result": 1,
463
+ "warnings": 0
464
+ }
465
+ },
466
+ {
467
+ "rust": {
468
+ "buffer": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
469
+ "guards": [
470
+ "41414141",
471
+ "41414141"
472
+ ],
473
+ "lookups": 1,
474
+ "result": 1,
475
+ "warnings": 0
476
+ },
477
+ "source": {
478
+ "buffer": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
479
+ "guards": [
480
+ "41414141",
481
+ "41414141"
482
+ ],
483
+ "lookups": 1,
484
+ "result": 1,
485
+ "warnings": 0
486
+ }
487
+ },
488
+ {
489
+ "rust": {
490
+ "buffer": "536974652041000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
491
+ "guards": [
492
+ "41414141",
493
+ "41414141"
494
+ ],
495
+ "lookups": 1,
496
+ "result": 1,
497
+ "warnings": 0
498
+ },
499
+ "source": {
500
+ "buffer": "536974652041000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
501
+ "guards": [
502
+ "41414141",
503
+ "41414141"
504
+ ],
505
+ "lookups": 1,
506
+ "result": 1,
507
+ "warnings": 0
508
+ }
509
+ },
510
+ {
511
+ "rust": {
512
+ "buffer": "412242000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
513
+ "guards": [
514
+ "41414141",
515
+ "41414141"
516
+ ],
517
+ "lookups": 1,
518
+ "result": 1,
519
+ "warnings": 0
520
+ },
521
+ "source": {
522
+ "buffer": "412242000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
523
+ "guards": [
524
+ "41414141",
525
+ "41414141"
526
+ ],
527
+ "lookups": 1,
528
+ "result": 1,
529
+ "warnings": 0
530
+ }
531
+ }
532
+ ],
533
+ "source_report": "docs/research/qvm-location-text.json",
534
+ "source_report_sha256": "8834b6ad90a1895361df46baee503e0b19ab918f0698c4f3eb1f2ccbd6a8ad74"
535
+ }
scripts/analyze_rust_location_text.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-location-feedback'],check=True,capture_output=True)
9
+ binary=Path(os.environ.get('CARGO_TARGET_DIR','target'))/'debug'/'urt-location-feedback'
10
+ path=Path('docs/research/qvm-location-text.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 ['result', 'buffer', 'guards', 'warnings', 'lookups']},rust=result(binary,'text',encode(p['input']))))
13
+ write_json(Path('docs/research/rust-location-text.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
+ text=bytes.fromhex(a['text'])
17
+ return [a['found'],a['capacity'],len(text),*text]
18
+ if __name__=='__main__':main()
scripts/test_rust_location_text.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-location-text.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-location-text.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
@@ -4568,3 +4568,42 @@ report scripts/analyze_qvm_location_text.py docs/research/qvm-location-text.json
4568
  edge docs/research/qvm-location-text.json scripts/test_qvm_location_text.py
4569
  group qvm-location-text scripts/analyze_qvm_location_text.py
4570
  edge scripts/analyze_qvm_location_text.py scripts/analyze_qvm_resumer_audit.py
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4568
  edge docs/research/qvm-location-text.json scripts/test_qvm_location_text.py
4569
  group qvm-location-text scripts/analyze_qvm_location_text.py
4570
  edge scripts/analyze_qvm_location_text.py scripts/analyze_qvm_resumer_audit.py
4571
+ report scripts/analyze_rust_location_text.py docs/research/rust-location-text.json
4572
+ edge docs/research/rust-location-text.json scripts/test_rust_location_text.py
4573
+ group rust-location-text scripts/analyze_rust_location_text.py
4574
+ edge scripts/analyze_rust_location_text.py scripts/analyze_qvm_resumer_audit.py
4575
+ edge Cargo.toml scripts/analyze_rust_location_text.py
4576
+ edge Cargo.lock scripts/analyze_rust_location_text.py
4577
+ edge crates/urt-gameplay/Cargo.toml scripts/analyze_rust_location_text.py
4578
+ edge crates/urt-gameplay/src/lib.rs scripts/analyze_rust_location_text.py
4579
+ edge crates/urt-gameplay/src/filter_loading.rs scripts/analyze_rust_location_text.py
4580
+ edge crates/urt-gameplay/src/filter_lifecycle.rs scripts/analyze_rust_location_text.py
4581
+ edge crates/urt-gameplay/src/native_policy.rs scripts/analyze_rust_location_text.py
4582
+ edge crates/urt-gameplay/src/bin/urt-filter-loading.rs scripts/analyze_rust_location_text.py
4583
+ edge crates/urt-gameplay/src/qvm_format.rs scripts/analyze_rust_location_text.py
4584
+ edge docs/research/qvm-location-text.json scripts/analyze_rust_location_text.py
4585
+ group rust-location-text scripts/analyze_rust_health_impulse.py
4586
+ group gameplay scripts/analyze_rust_location_text.py
4587
+ edge crates/urt-gameplay/src/filter_commands.rs scripts/analyze_rust_location_text.py
4588
+ edge crates/urt-gameplay/src/bin/urt-filter-commands.rs scripts/analyze_rust_location_text.py
4589
+ edge crates/urt-gameplay/src/client_timer.rs scripts/analyze_rust_location_text.py
4590
+ edge crates/urt-gameplay/src/bin/urt-client-timer.rs scripts/analyze_rust_location_text.py
4591
+ edge crates/urt-gameplay/src/client_processing.rs scripts/analyze_rust_location_text.py
4592
+ edge crates/urt-gameplay/src/bin/urt-client-processing.rs scripts/analyze_rust_location_text.py
4593
+ edge crates/urt-gameplay/src/client_move_context.rs scripts/analyze_rust_location_text.py
4594
+ edge crates/urt-gameplay/src/bin/urt-client-move-context.rs scripts/analyze_rust_location_text.py
4595
+ edge crates/urt-gameplay/src/move_callbacks.rs scripts/analyze_rust_location_text.py
4596
+ edge crates/urt-gameplay/src/bin/urt-move-callbacks.rs scripts/analyze_rust_location_text.py
4597
+ edge crates/urt-gameplay/src/assistance.rs scripts/analyze_rust_location_text.py
4598
+ edge crates/urt-gameplay/src/bin/urt-assistance.rs scripts/analyze_rust_location_text.py
4599
+ edge crates/urt-gameplay/src/move_callbacks.rs scripts/analyze_rust_location_text.py
4600
+ edge crates/urt-gameplay/src/defuse.rs scripts/analyze_rust_location_text.py
4601
+ edge crates/urt-gameplay/src/bin/urt-defuse.rs scripts/analyze_rust_location_text.py
4602
+ edge crates/urt-gameplay/src/move_callbacks.rs scripts/analyze_rust_location_text.py
4603
+ edge crates/urt-gameplay/src/effect_feedback.rs scripts/analyze_rust_location_text.py
4604
+ edge crates/urt-gameplay/src/bin/urt-effect-feedback.rs scripts/analyze_rust_location_text.py
4605
+ edge crates/urt-gameplay/src/score.rs scripts/analyze_rust_location_text.py
4606
+ edge crates/urt-gameplay/src/transition.rs scripts/analyze_rust_location_text.py
4607
+ edge crates/urt-gameplay/src/location_feedback.rs scripts/analyze_rust_location_text.py
4608
+ edge crates/urt-gameplay/src/bin/urt-location-feedback.rs scripts/analyze_rust_location_text.py
4609
+ edge crates/urt-gameplay/src/qvm_format.rs scripts/analyze_rust_location_text.py
xtask/src/lib.rs CHANGED
@@ -1180,6 +1180,8 @@ mod integration_tests {
1180
  ("transition", "effect_defuse_complete"),
1181
  ("location_feedback", "location_nearest"),
1182
  ("qvm_format", "location_nearest"),
 
 
1183
  ("client_move_context", "client_move_scratch"),
1184
  ("client_processing", "client_routing"),
1185
  ("client_timer", "client_routing"),
@@ -1419,6 +1421,7 @@ mod integration_tests {
1419
  ("qvm-effect-defuse-begin", "effect_defuse_begin"),
1420
  ("qvm-effect-defuse-complete", "effect_defuse_complete"),
1421
  ("qvm-location-nearest", "location_nearest"),
 
1422
  ("qvm-client-move-scratch", "client_move_scratch"),
1423
  ("qvm-client-routing", "client_routing"),
1424
  ("qvm-client-command-rewrite", "client_command_rewrite"),
 
1180
  ("transition", "effect_defuse_complete"),
1181
  ("location_feedback", "location_nearest"),
1182
  ("qvm_format", "location_nearest"),
1183
+ ("location_feedback", "location_text"),
1184
+ ("qvm_format", "location_text"),
1185
  ("client_move_context", "client_move_scratch"),
1186
  ("client_processing", "client_routing"),
1187
  ("client_timer", "client_routing"),
 
1421
  ("qvm-effect-defuse-begin", "effect_defuse_begin"),
1422
  ("qvm-effect-defuse-complete", "effect_defuse_complete"),
1423
  ("qvm-location-nearest", "location_nearest"),
1424
+ ("qvm-location-text", "location_text"),
1425
  ("qvm-client-move-scratch", "client_move_scratch"),
1426
  ("qvm-client-routing", "client_routing"),
1427
  ("qvm-client-command-rewrite", "client_command_rewrite"),