nmarshall commited on
Commit
41ceee2
·
1 Parent(s): 4ec14d9

gameplay: port filter export effects

Browse files
crates/urt-gameplay/src/bin/urt-filter-policy.rs ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ use urt_gameplay::filter_lifecycle::*;
2
+ use urt_gameplay::native_policy::FilterRecord;
3
+ fn hex(s: &[u8]) -> String {
4
+ s.iter().map(|v| format!("{v:02x}")).collect()
5
+ }
6
+ fn export_json(p: Option<FilterExport>) -> String {
7
+ match p {
8
+ None => "{\"events\":[],\"formats\":[],\"buffer\":\"7374616c65\"}".into(),
9
+ Some(p) => format!(
10
+ "{{\"events\":[{{\"op\":\"print\",\"text\":\"57726974696e673a2062616e6c6973742e7478740a\"}},{{\"op\":\"open\",\"path\":\"62616e6c6973742e747874\",\"mode\":1}},{{\"op\":\"write\",\"handle\":{},\"text\":\"{}\"}},{{\"op\":\"close\",\"handle\":{}}}],\"formats\":[{}],\"buffer\":\"{}\"}}",
11
+ p.handle,
12
+ hex(&p.text),
13
+ p.handle,
14
+ p.lines
15
+ .iter()
16
+ .map(|l| format!("\"{}\"", hex(l)))
17
+ .collect::<Vec<_>>()
18
+ .join(","),
19
+ hex(&p.text)
20
+ ),
21
+ }
22
+ }
23
+ fn main() {
24
+ let mut args = std::env::args().skip(1);
25
+ let kind = args.next().unwrap();
26
+ let w: Vec<u32> = args.map(|s| s.parse().unwrap()).collect();
27
+ let n = w[0] as usize;
28
+ let handle = w[1];
29
+ assert_eq!(w.len(), 2 + 3 * n);
30
+ let rows: Vec<_> = w[2..]
31
+ .chunks_exact(3)
32
+ .map(|r| FilterRecord {
33
+ mask: r[0],
34
+ comparison: r[1],
35
+ metadata: r[2],
36
+ })
37
+ .collect();
38
+ match kind.as_str() {
39
+ "export" => println!("{}", export_json(export_filters(&rows, handle).unwrap())),
40
+ _ => panic!("unknown policy"),
41
+ }
42
+ }
crates/urt-gameplay/src/filter_lifecycle.rs ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //! Recovered filter persistence policies; native file operations stay explicit.
2
+ use crate::native_policy::{Error, FilterRecord};
3
+ #[derive(Clone, Debug, PartialEq, Eq)]
4
+ pub struct FilterExport {
5
+ pub lines: Vec<Vec<u8>>,
6
+ pub text: Vec<u8>,
7
+ pub handle: u32,
8
+ }
9
+ /// Original252500: count zero leaves storage/files untouched; a nonempty table
10
+ /// always opens, writes and closes, even when all comparison words are holes.
11
+ /// Masks are deliberately absent from the serialized form.
12
+ pub fn export_filters(
13
+ records: &[FilterRecord],
14
+ handle: u32,
15
+ ) -> Result<Option<FilterExport>, Error> {
16
+ if records.len() > 4096 {
17
+ return Err(Error::InvalidCount);
18
+ }
19
+ if records.is_empty() {
20
+ return Ok(None);
21
+ }
22
+ let lines: Vec<Vec<u8>> = records
23
+ .iter()
24
+ .filter(|r| r.comparison != u32::MAX)
25
+ .map(|r| {
26
+ let a = r.comparison.to_le_bytes();
27
+ let mut line = format!("{}.{}.{}.{}:", a[0], a[1], a[2], a[3]).into_bytes();
28
+ line.extend(crate::qvm_format::decimal(r.metadata as i32));
29
+ line.push(b'\n');
30
+ line
31
+ })
32
+ .collect();
33
+ let text = lines.concat();
34
+ // Every row is at most 28 bytes, so all 4096 rows fit the 131072-byte buffer.
35
+ debug_assert!(text.len() < 131072);
36
+ Ok(Some(FilterExport {
37
+ lines,
38
+ text,
39
+ handle,
40
+ }))
41
+ }
42
+ #[cfg(test)]
43
+ mod tests {
44
+ use super::*;
45
+ #[test]
46
+ fn empty_and_all_holes_have_distinct_effects() {
47
+ assert_eq!(export_filters(&[], 0).unwrap(), None);
48
+ let hole = FilterRecord {
49
+ mask: 0,
50
+ comparison: u32::MAX,
51
+ metadata: 0,
52
+ };
53
+ assert_eq!(export_filters(&[hole], 0).unwrap().unwrap().text, b"");
54
+ }
55
+ #[test]
56
+ fn maximum_table_fits_and_invalid_handles_are_retained() {
57
+ let row = FilterRecord {
58
+ mask: 0,
59
+ comparison: 0xfeffffff,
60
+ metadata: 0x80000000,
61
+ };
62
+ let p = export_filters(&vec![row; 4096], u32::MAX).unwrap().unwrap();
63
+ assert_eq!(p.text.len(), 28 * 4096);
64
+ assert_eq!(p.handle, u32::MAX);
65
+ assert!(export_filters(&vec![row; 4097], 7).is_err());
66
+ }
67
+ }
crates/urt-gameplay/src/lib.rs CHANGED
@@ -181,3 +181,5 @@ pub mod camera_world;
181
  pub mod map_commands;
182
 
183
  pub mod native_policy;
 
 
 
181
  pub mod map_commands;
182
 
183
  pub mod native_policy;
184
+
185
+ pub mod filter_lifecycle;
docs/FINDINGS.md CHANGED
@@ -1801,3 +1801,5 @@ RE-813–822 replaces the scoreboard decimal assumption with actual37914 executi
1801
  **RE-933:** Rust matches132 original252829/252304 table cases including4096-capacity scans, first-hole reuse, wildcard/numeric masks and comparison-1 sentinel behavior. Parser failure retains count growth and requests optional export, matching the source. Typed malformed counts/token-overflow domains reject atomically. Export body252500, live table writers and native network acceptance remain open. [Evidence](research/RUST_FILTER_INSERT.md).
1802
 
1803
  RE-934: Actual252500 exports comparison bytes and signed metadata while ignoring masks. It skips comparison-1 rows, performs no IO for count zero, but truncates/writes an empty file for a nonempty all-hole table. Supplied zero/negative handles still reach write and close. The INT_MIN metadata case retains the original formatter wrapping-negation punctuation instead of host decimal output. Eighteen fixtures execute actual70386/37914/69338; native memory operations are modeled and file operations captured. Aggregate overflow and actual filesystem acceptance remain open. [Evidence](research/QVM_FILTER_EXPORT.md).
 
 
 
1801
  **RE-933:** Rust matches132 original252829/252304 table cases including4096-capacity scans, first-hole reuse, wildcard/numeric masks and comparison-1 sentinel behavior. Parser failure retains count growth and requests optional export, matching the source. Typed malformed counts/token-overflow domains reject atomically. Export body252500, live table writers and native network acceptance remain open. [Evidence](research/RUST_FILTER_INSERT.md).
1802
 
1803
  RE-934: Actual252500 exports comparison bytes and signed metadata while ignoring masks. It skips comparison-1 rows, performs no IO for count zero, but truncates/writes an empty file for a nonempty all-hole table. Supplied zero/negative handles still reach write and close. The INT_MIN metadata case retains the original formatter wrapping-negation punctuation instead of host decimal output. Eighteen fixtures execute actual70386/37914/69338; native memory operations are modeled and file operations captured. Aggregate overflow and actual filesystem acceptance remain open. [Evidence](research/QVM_FILTER_EXPORT.md).
1804
+
1805
+ RE-935: Rust matches all18 original export cases, including mask loss, all-hole truncation, invalid handles and original INT_MIN formatter bytes. Empty tables produce no plan; other tables produce ordered print/open/write/close effects. A4096-row table is bounded by28 bytes per row, below the131072-byte source buffer; unit tests check that maximum and reject4097 rows. Native IO remains an adapter boundary. [Evidence](research/RUST_FILTER_EXPORT.md).
docs/PROVISIONAL_TODO.md CHANGED
@@ -1847,3 +1847,5 @@ RE-933: Rust matches132 original252829/252304 table cases including4096-capacity
1847
  RE-924–933 completed bounded bot settings, announcement, connect-child composition and filter insertion contracts. RE-934 tracks bot setup/userinfo/filter export, native resource/network acceptance and complete runtime integration. [Batch and next work](research/QVM_BOT_ANNOUNCEMENT_FILTER_BATCH.md).
1848
 
1849
  - [x] RE-934 Original filter export and native file-operation order ([evidence](research/QVM_FILTER_EXPORT.md)).
 
 
 
1847
  RE-924–933 completed bounded bot settings, announcement, connect-child composition and filter insertion contracts. RE-934 tracks bot setup/userinfo/filter export, native resource/network acceptance and complete runtime integration. [Batch and next work](research/QVM_BOT_ANNOUNCEMENT_FILTER_BATCH.md).
1848
 
1849
  - [x] RE-934 Original filter export and native file-operation order ([evidence](research/QVM_FILTER_EXPORT.md)).
1850
+
1851
+ - [x] RE-935 Rust filter export policy and bounded storage ([evidence](research/RUST_FILTER_EXPORT.md)).
docs/RESEARCH_LEDGER.md CHANGED
@@ -2401,3 +2401,7 @@ Batch RE-924–933 boundary: the single `cargo xtask test-full --since bc3e7621`
2401
  ## 2026-10-28 — RE-934 Original filter export and native file-operation order
2402
 
2403
  Actual252500 exports comparison bytes and signed metadata while ignoring masks. It skips comparison-1 rows, performs no IO for count zero, but truncates/writes an empty file for a nonempty all-hole table. Supplied zero/negative handles still reach write and close. The INT_MIN metadata case retains the original formatter wrapping-negation punctuation instead of host decimal output. Eighteen fixtures execute actual70386/37914/69338; native memory operations are modeled and file operations captured. Aggregate overflow and actual filesystem acceptance remain open. Focused `cargo xtask test-group qvm-filter-export` passes with deterministic report regeneration, relevant regressions and storage/documentation/whitespace checks. Full suite deferred to the tenth-commit boundary. Original assets unchanged; native IO effects remain captured.
 
 
 
 
 
2401
  ## 2026-10-28 — RE-934 Original filter export and native file-operation order
2402
 
2403
  Actual252500 exports comparison bytes and signed metadata while ignoring masks. It skips comparison-1 rows, performs no IO for count zero, but truncates/writes an empty file for a nonempty all-hole table. Supplied zero/negative handles still reach write and close. The INT_MIN metadata case retains the original formatter wrapping-negation punctuation instead of host decimal output. Eighteen fixtures execute actual70386/37914/69338; native memory operations are modeled and file operations captured. Aggregate overflow and actual filesystem acceptance remain open. Focused `cargo xtask test-group qvm-filter-export` passes with deterministic report regeneration, relevant regressions and storage/documentation/whitespace checks. Full suite deferred to the tenth-commit boundary. Original assets unchanged; native IO effects remain captured.
2404
+
2405
+ ## 2026-10-28 — RE-935 Rust filter export policy and bounded storage
2406
+
2407
+ Rust matches all18 original export cases, including mask loss, all-hole truncation, invalid handles and original INT_MIN formatter bytes. Empty tables produce no plan; other tables produce ordered print/open/write/close effects. A4096-row table is bounded by28 bytes per row, below the131072-byte source buffer; unit tests check that maximum and reject4097 rows. Native IO remains an adapter boundary. Focused `cargo xtask test-group rust-filter-export` passes with deterministic report regeneration, relevant regressions and storage/documentation/whitespace checks. Full suite deferred to the tenth-commit boundary. Original assets unchanged; native IO effects remain captured.
docs/REVERSE_ENGINEERING_TODO.md CHANGED
@@ -1884,3 +1884,5 @@ Purpose: turn the supplied installation into an evidence-backed specification of
1884
  - [ ] RE-934 Recover bot setup/userinfo/filter-export internals, native resource/network acceptance and remaining runtime integration ([next work](research/QVM_BOT_ANNOUNCEMENT_FILTER_BATCH.md)).
1885
 
1886
  - [x] RE-934 Original filter export and native file-operation order ([evidence](research/QVM_FILTER_EXPORT.md)).
 
 
 
1884
  - [ ] RE-934 Recover bot setup/userinfo/filter-export internals, native resource/network acceptance and remaining runtime integration ([next work](research/QVM_BOT_ANNOUNCEMENT_FILTER_BATCH.md)).
1885
 
1886
  - [x] RE-934 Original filter export and native file-operation order ([evidence](research/QVM_FILTER_EXPORT.md)).
1887
+
1888
+ - [x] RE-935 Rust filter export policy and bounded storage ([evidence](research/RUST_FILTER_EXPORT.md)).
docs/research/README.md CHANGED
@@ -1419,3 +1419,5 @@ The extension collector adds five focused tests for native tail calls, command-r
1419
  [RE-924–933 bot/announcement/filter batch](QVM_BOT_ANNOUNCEMENT_FILTER_BATCH.md).
1420
 
1421
  - [RE-934: Original filter export and native file-operation order](QVM_FILTER_EXPORT.md).
 
 
 
1419
  [RE-924–933 bot/announcement/filter batch](QVM_BOT_ANNOUNCEMENT_FILTER_BATCH.md).
1420
 
1421
  - [RE-934: Original filter export and native file-operation order](QVM_FILTER_EXPORT.md).
1422
+
1423
+ - [RE-935: Rust filter export policy and bounded storage](RUST_FILTER_EXPORT.md).
docs/research/RUST_FILTER_EXPORT.md ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ # Rust filter export policy and bounded storage
2
+
3
+ RE-935. Focused validation: `cargo xtask test-group rust-filter-export`. [Machine report](rust-filter-export.json).
4
+
5
+ Rust matches all18 original export cases, including mask loss, all-hole truncation, invalid handles and original INT_MIN formatter bytes. Empty tables produce no plan; other tables produce ordered print/open/write/close effects. A4096-row table is bounded by28 bytes per row, below the131072-byte source buffer; unit tests check that maximum and reject4097 rows. Native IO remains an adapter boundary.
docs/research/rust-filter-export.json ADDED
@@ -0,0 +1,853 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "limits": "Finite recovered policy parity; native filesystem/network effects are not executed.",
3
+ "probes": [
4
+ {
5
+ "rust": {
6
+ "buffer": "7374616c65",
7
+ "events": [],
8
+ "formats": []
9
+ },
10
+ "source": {
11
+ "buffer": "7374616c65",
12
+ "events": [],
13
+ "formats": []
14
+ }
15
+ },
16
+ {
17
+ "rust": {
18
+ "buffer": "7374616c65",
19
+ "events": [],
20
+ "formats": []
21
+ },
22
+ "source": {
23
+ "buffer": "7374616c65",
24
+ "events": [],
25
+ "formats": []
26
+ }
27
+ },
28
+ {
29
+ "rust": {
30
+ "buffer": "7374616c65",
31
+ "events": [],
32
+ "formats": []
33
+ },
34
+ "source": {
35
+ "buffer": "7374616c65",
36
+ "events": [],
37
+ "formats": []
38
+ }
39
+ },
40
+ {
41
+ "rust": {
42
+ "buffer": "",
43
+ "events": [
44
+ {
45
+ "op": "print",
46
+ "text": "57726974696e673a2062616e6c6973742e7478740a"
47
+ },
48
+ {
49
+ "mode": 1,
50
+ "op": "open",
51
+ "path": "62616e6c6973742e747874"
52
+ },
53
+ {
54
+ "handle": 0,
55
+ "op": "write",
56
+ "text": ""
57
+ },
58
+ {
59
+ "handle": 0,
60
+ "op": "close"
61
+ }
62
+ ],
63
+ "formats": []
64
+ },
65
+ "source": {
66
+ "buffer": "",
67
+ "events": [
68
+ {
69
+ "op": "print",
70
+ "text": "57726974696e673a2062616e6c6973742e7478740a"
71
+ },
72
+ {
73
+ "mode": 1,
74
+ "op": "open",
75
+ "path": "62616e6c6973742e747874"
76
+ },
77
+ {
78
+ "handle": 0,
79
+ "op": "write",
80
+ "text": ""
81
+ },
82
+ {
83
+ "handle": 0,
84
+ "op": "close"
85
+ }
86
+ ],
87
+ "formats": []
88
+ }
89
+ },
90
+ {
91
+ "rust": {
92
+ "buffer": "",
93
+ "events": [
94
+ {
95
+ "op": "print",
96
+ "text": "57726974696e673a2062616e6c6973742e7478740a"
97
+ },
98
+ {
99
+ "mode": 1,
100
+ "op": "open",
101
+ "path": "62616e6c6973742e747874"
102
+ },
103
+ {
104
+ "handle": 7,
105
+ "op": "write",
106
+ "text": ""
107
+ },
108
+ {
109
+ "handle": 7,
110
+ "op": "close"
111
+ }
112
+ ],
113
+ "formats": []
114
+ },
115
+ "source": {
116
+ "buffer": "",
117
+ "events": [
118
+ {
119
+ "op": "print",
120
+ "text": "57726974696e673a2062616e6c6973742e7478740a"
121
+ },
122
+ {
123
+ "mode": 1,
124
+ "op": "open",
125
+ "path": "62616e6c6973742e747874"
126
+ },
127
+ {
128
+ "handle": 7,
129
+ "op": "write",
130
+ "text": ""
131
+ },
132
+ {
133
+ "handle": 7,
134
+ "op": "close"
135
+ }
136
+ ],
137
+ "formats": []
138
+ }
139
+ },
140
+ {
141
+ "rust": {
142
+ "buffer": "",
143
+ "events": [
144
+ {
145
+ "op": "print",
146
+ "text": "57726974696e673a2062616e6c6973742e7478740a"
147
+ },
148
+ {
149
+ "mode": 1,
150
+ "op": "open",
151
+ "path": "62616e6c6973742e747874"
152
+ },
153
+ {
154
+ "handle": 4294967295,
155
+ "op": "write",
156
+ "text": ""
157
+ },
158
+ {
159
+ "handle": 4294967295,
160
+ "op": "close"
161
+ }
162
+ ],
163
+ "formats": []
164
+ },
165
+ "source": {
166
+ "buffer": "",
167
+ "events": [
168
+ {
169
+ "op": "print",
170
+ "text": "57726974696e673a2062616e6c6973742e7478740a"
171
+ },
172
+ {
173
+ "mode": 1,
174
+ "op": "open",
175
+ "path": "62616e6c6973742e747874"
176
+ },
177
+ {
178
+ "handle": 4294967295,
179
+ "op": "write",
180
+ "text": ""
181
+ },
182
+ {
183
+ "handle": 4294967295,
184
+ "op": "close"
185
+ }
186
+ ],
187
+ "formats": []
188
+ }
189
+ },
190
+ {
191
+ "rust": {
192
+ "buffer": "312e322e332e343a2d310a",
193
+ "events": [
194
+ {
195
+ "op": "print",
196
+ "text": "57726974696e673a2062616e6c6973742e7478740a"
197
+ },
198
+ {
199
+ "mode": 1,
200
+ "op": "open",
201
+ "path": "62616e6c6973742e747874"
202
+ },
203
+ {
204
+ "handle": 0,
205
+ "op": "write",
206
+ "text": "312e322e332e343a2d310a"
207
+ },
208
+ {
209
+ "handle": 0,
210
+ "op": "close"
211
+ }
212
+ ],
213
+ "formats": [
214
+ "312e322e332e343a2d310a"
215
+ ]
216
+ },
217
+ "source": {
218
+ "buffer": "312e322e332e343a2d310a",
219
+ "events": [
220
+ {
221
+ "op": "print",
222
+ "text": "57726974696e673a2062616e6c6973742e7478740a"
223
+ },
224
+ {
225
+ "mode": 1,
226
+ "op": "open",
227
+ "path": "62616e6c6973742e747874"
228
+ },
229
+ {
230
+ "handle": 0,
231
+ "op": "write",
232
+ "text": "312e322e332e343a2d310a"
233
+ },
234
+ {
235
+ "handle": 0,
236
+ "op": "close"
237
+ }
238
+ ],
239
+ "formats": [
240
+ "312e322e332e343a2d310a"
241
+ ]
242
+ }
243
+ },
244
+ {
245
+ "rust": {
246
+ "buffer": "312e322e332e343a2d310a",
247
+ "events": [
248
+ {
249
+ "op": "print",
250
+ "text": "57726974696e673a2062616e6c6973742e7478740a"
251
+ },
252
+ {
253
+ "mode": 1,
254
+ "op": "open",
255
+ "path": "62616e6c6973742e747874"
256
+ },
257
+ {
258
+ "handle": 7,
259
+ "op": "write",
260
+ "text": "312e322e332e343a2d310a"
261
+ },
262
+ {
263
+ "handle": 7,
264
+ "op": "close"
265
+ }
266
+ ],
267
+ "formats": [
268
+ "312e322e332e343a2d310a"
269
+ ]
270
+ },
271
+ "source": {
272
+ "buffer": "312e322e332e343a2d310a",
273
+ "events": [
274
+ {
275
+ "op": "print",
276
+ "text": "57726974696e673a2062616e6c6973742e7478740a"
277
+ },
278
+ {
279
+ "mode": 1,
280
+ "op": "open",
281
+ "path": "62616e6c6973742e747874"
282
+ },
283
+ {
284
+ "handle": 7,
285
+ "op": "write",
286
+ "text": "312e322e332e343a2d310a"
287
+ },
288
+ {
289
+ "handle": 7,
290
+ "op": "close"
291
+ }
292
+ ],
293
+ "formats": [
294
+ "312e322e332e343a2d310a"
295
+ ]
296
+ }
297
+ },
298
+ {
299
+ "rust": {
300
+ "buffer": "312e322e332e343a2d310a",
301
+ "events": [
302
+ {
303
+ "op": "print",
304
+ "text": "57726974696e673a2062616e6c6973742e7478740a"
305
+ },
306
+ {
307
+ "mode": 1,
308
+ "op": "open",
309
+ "path": "62616e6c6973742e747874"
310
+ },
311
+ {
312
+ "handle": 4294967295,
313
+ "op": "write",
314
+ "text": "312e322e332e343a2d310a"
315
+ },
316
+ {
317
+ "handle": 4294967295,
318
+ "op": "close"
319
+ }
320
+ ],
321
+ "formats": [
322
+ "312e322e332e343a2d310a"
323
+ ]
324
+ },
325
+ "source": {
326
+ "buffer": "312e322e332e343a2d310a",
327
+ "events": [
328
+ {
329
+ "op": "print",
330
+ "text": "57726974696e673a2062616e6c6973742e7478740a"
331
+ },
332
+ {
333
+ "mode": 1,
334
+ "op": "open",
335
+ "path": "62616e6c6973742e747874"
336
+ },
337
+ {
338
+ "handle": 4294967295,
339
+ "op": "write",
340
+ "text": "312e322e332e343a2d310a"
341
+ },
342
+ {
343
+ "handle": 4294967295,
344
+ "op": "close"
345
+ }
346
+ ],
347
+ "formats": [
348
+ "312e322e332e343a2d310a"
349
+ ]
350
+ }
351
+ },
352
+ {
353
+ "rust": {
354
+ "buffer": "302e302e302e303a300a",
355
+ "events": [
356
+ {
357
+ "op": "print",
358
+ "text": "57726974696e673a2062616e6c6973742e7478740a"
359
+ },
360
+ {
361
+ "mode": 1,
362
+ "op": "open",
363
+ "path": "62616e6c6973742e747874"
364
+ },
365
+ {
366
+ "handle": 0,
367
+ "op": "write",
368
+ "text": "302e302e302e303a300a"
369
+ },
370
+ {
371
+ "handle": 0,
372
+ "op": "close"
373
+ }
374
+ ],
375
+ "formats": [
376
+ "302e302e302e303a300a"
377
+ ]
378
+ },
379
+ "source": {
380
+ "buffer": "302e302e302e303a300a",
381
+ "events": [
382
+ {
383
+ "op": "print",
384
+ "text": "57726974696e673a2062616e6c6973742e7478740a"
385
+ },
386
+ {
387
+ "mode": 1,
388
+ "op": "open",
389
+ "path": "62616e6c6973742e747874"
390
+ },
391
+ {
392
+ "handle": 0,
393
+ "op": "write",
394
+ "text": "302e302e302e303a300a"
395
+ },
396
+ {
397
+ "handle": 0,
398
+ "op": "close"
399
+ }
400
+ ],
401
+ "formats": [
402
+ "302e302e302e303a300a"
403
+ ]
404
+ }
405
+ },
406
+ {
407
+ "rust": {
408
+ "buffer": "302e302e302e303a300a",
409
+ "events": [
410
+ {
411
+ "op": "print",
412
+ "text": "57726974696e673a2062616e6c6973742e7478740a"
413
+ },
414
+ {
415
+ "mode": 1,
416
+ "op": "open",
417
+ "path": "62616e6c6973742e747874"
418
+ },
419
+ {
420
+ "handle": 7,
421
+ "op": "write",
422
+ "text": "302e302e302e303a300a"
423
+ },
424
+ {
425
+ "handle": 7,
426
+ "op": "close"
427
+ }
428
+ ],
429
+ "formats": [
430
+ "302e302e302e303a300a"
431
+ ]
432
+ },
433
+ "source": {
434
+ "buffer": "302e302e302e303a300a",
435
+ "events": [
436
+ {
437
+ "op": "print",
438
+ "text": "57726974696e673a2062616e6c6973742e7478740a"
439
+ },
440
+ {
441
+ "mode": 1,
442
+ "op": "open",
443
+ "path": "62616e6c6973742e747874"
444
+ },
445
+ {
446
+ "handle": 7,
447
+ "op": "write",
448
+ "text": "302e302e302e303a300a"
449
+ },
450
+ {
451
+ "handle": 7,
452
+ "op": "close"
453
+ }
454
+ ],
455
+ "formats": [
456
+ "302e302e302e303a300a"
457
+ ]
458
+ }
459
+ },
460
+ {
461
+ "rust": {
462
+ "buffer": "302e302e302e303a300a",
463
+ "events": [
464
+ {
465
+ "op": "print",
466
+ "text": "57726974696e673a2062616e6c6973742e7478740a"
467
+ },
468
+ {
469
+ "mode": 1,
470
+ "op": "open",
471
+ "path": "62616e6c6973742e747874"
472
+ },
473
+ {
474
+ "handle": 4294967295,
475
+ "op": "write",
476
+ "text": "302e302e302e303a300a"
477
+ },
478
+ {
479
+ "handle": 4294967295,
480
+ "op": "close"
481
+ }
482
+ ],
483
+ "formats": [
484
+ "302e302e302e303a300a"
485
+ ]
486
+ },
487
+ "source": {
488
+ "buffer": "302e302e302e303a300a",
489
+ "events": [
490
+ {
491
+ "op": "print",
492
+ "text": "57726974696e673a2062616e6c6973742e7478740a"
493
+ },
494
+ {
495
+ "mode": 1,
496
+ "op": "open",
497
+ "path": "62616e6c6973742e747874"
498
+ },
499
+ {
500
+ "handle": 4294967295,
501
+ "op": "write",
502
+ "text": "302e302e302e303a300a"
503
+ },
504
+ {
505
+ "handle": 4294967295,
506
+ "op": "close"
507
+ }
508
+ ],
509
+ "formats": [
510
+ "302e302e302e303a300a"
511
+ ]
512
+ }
513
+ },
514
+ {
515
+ "rust": {
516
+ "buffer": "3132372e302e302e313a2d2e2f2c292c282d2a2c280a312e302e302e3235353a323134373438333634370a",
517
+ "events": [
518
+ {
519
+ "op": "print",
520
+ "text": "57726974696e673a2062616e6c6973742e7478740a"
521
+ },
522
+ {
523
+ "mode": 1,
524
+ "op": "open",
525
+ "path": "62616e6c6973742e747874"
526
+ },
527
+ {
528
+ "handle": 0,
529
+ "op": "write",
530
+ "text": "3132372e302e302e313a2d2e2f2c292c282d2a2c280a312e302e302e3235353a323134373438333634370a"
531
+ },
532
+ {
533
+ "handle": 0,
534
+ "op": "close"
535
+ }
536
+ ],
537
+ "formats": [
538
+ "3132372e302e302e313a2d2e2f2c292c282d2a2c280a",
539
+ "312e302e302e3235353a323134373438333634370a"
540
+ ]
541
+ },
542
+ "source": {
543
+ "buffer": "3132372e302e302e313a2d2e2f2c292c282d2a2c280a312e302e302e3235353a323134373438333634370a",
544
+ "events": [
545
+ {
546
+ "op": "print",
547
+ "text": "57726974696e673a2062616e6c6973742e7478740a"
548
+ },
549
+ {
550
+ "mode": 1,
551
+ "op": "open",
552
+ "path": "62616e6c6973742e747874"
553
+ },
554
+ {
555
+ "handle": 0,
556
+ "op": "write",
557
+ "text": "3132372e302e302e313a2d2e2f2c292c282d2a2c280a312e302e302e3235353a323134373438333634370a"
558
+ },
559
+ {
560
+ "handle": 0,
561
+ "op": "close"
562
+ }
563
+ ],
564
+ "formats": [
565
+ "3132372e302e302e313a2d2e2f2c292c282d2a2c280a",
566
+ "312e302e302e3235353a323134373438333634370a"
567
+ ]
568
+ }
569
+ },
570
+ {
571
+ "rust": {
572
+ "buffer": "3132372e302e302e313a2d2e2f2c292c282d2a2c280a312e302e302e3235353a323134373438333634370a",
573
+ "events": [
574
+ {
575
+ "op": "print",
576
+ "text": "57726974696e673a2062616e6c6973742e7478740a"
577
+ },
578
+ {
579
+ "mode": 1,
580
+ "op": "open",
581
+ "path": "62616e6c6973742e747874"
582
+ },
583
+ {
584
+ "handle": 7,
585
+ "op": "write",
586
+ "text": "3132372e302e302e313a2d2e2f2c292c282d2a2c280a312e302e302e3235353a323134373438333634370a"
587
+ },
588
+ {
589
+ "handle": 7,
590
+ "op": "close"
591
+ }
592
+ ],
593
+ "formats": [
594
+ "3132372e302e302e313a2d2e2f2c292c282d2a2c280a",
595
+ "312e302e302e3235353a323134373438333634370a"
596
+ ]
597
+ },
598
+ "source": {
599
+ "buffer": "3132372e302e302e313a2d2e2f2c292c282d2a2c280a312e302e302e3235353a323134373438333634370a",
600
+ "events": [
601
+ {
602
+ "op": "print",
603
+ "text": "57726974696e673a2062616e6c6973742e7478740a"
604
+ },
605
+ {
606
+ "mode": 1,
607
+ "op": "open",
608
+ "path": "62616e6c6973742e747874"
609
+ },
610
+ {
611
+ "handle": 7,
612
+ "op": "write",
613
+ "text": "3132372e302e302e313a2d2e2f2c292c282d2a2c280a312e302e302e3235353a323134373438333634370a"
614
+ },
615
+ {
616
+ "handle": 7,
617
+ "op": "close"
618
+ }
619
+ ],
620
+ "formats": [
621
+ "3132372e302e302e313a2d2e2f2c292c282d2a2c280a",
622
+ "312e302e302e3235353a323134373438333634370a"
623
+ ]
624
+ }
625
+ },
626
+ {
627
+ "rust": {
628
+ "buffer": "3132372e302e302e313a2d2e2f2c292c282d2a2c280a312e302e302e3235353a323134373438333634370a",
629
+ "events": [
630
+ {
631
+ "op": "print",
632
+ "text": "57726974696e673a2062616e6c6973742e7478740a"
633
+ },
634
+ {
635
+ "mode": 1,
636
+ "op": "open",
637
+ "path": "62616e6c6973742e747874"
638
+ },
639
+ {
640
+ "handle": 4294967295,
641
+ "op": "write",
642
+ "text": "3132372e302e302e313a2d2e2f2c292c282d2a2c280a312e302e302e3235353a323134373438333634370a"
643
+ },
644
+ {
645
+ "handle": 4294967295,
646
+ "op": "close"
647
+ }
648
+ ],
649
+ "formats": [
650
+ "3132372e302e302e313a2d2e2f2c292c282d2a2c280a",
651
+ "312e302e302e3235353a323134373438333634370a"
652
+ ]
653
+ },
654
+ "source": {
655
+ "buffer": "3132372e302e302e313a2d2e2f2c292c282d2a2c280a312e302e302e3235353a323134373438333634370a",
656
+ "events": [
657
+ {
658
+ "op": "print",
659
+ "text": "57726974696e673a2062616e6c6973742e7478740a"
660
+ },
661
+ {
662
+ "mode": 1,
663
+ "op": "open",
664
+ "path": "62616e6c6973742e747874"
665
+ },
666
+ {
667
+ "handle": 4294967295,
668
+ "op": "write",
669
+ "text": "3132372e302e302e313a2d2e2f2c292c282d2a2c280a312e302e302e3235353a323134373438333634370a"
670
+ },
671
+ {
672
+ "handle": 4294967295,
673
+ "op": "close"
674
+ }
675
+ ],
676
+ "formats": [
677
+ "3132372e302e302e313a2d2e2f2c292c282d2a2c280a",
678
+ "312e302e302e3235353a323134373438333634370a"
679
+ ]
680
+ }
681
+ },
682
+ {
683
+ "rust": {
684
+ "buffer": "312e322e332e343a310a312e322e332e343a320a",
685
+ "events": [
686
+ {
687
+ "op": "print",
688
+ "text": "57726974696e673a2062616e6c6973742e7478740a"
689
+ },
690
+ {
691
+ "mode": 1,
692
+ "op": "open",
693
+ "path": "62616e6c6973742e747874"
694
+ },
695
+ {
696
+ "handle": 0,
697
+ "op": "write",
698
+ "text": "312e322e332e343a310a312e322e332e343a320a"
699
+ },
700
+ {
701
+ "handle": 0,
702
+ "op": "close"
703
+ }
704
+ ],
705
+ "formats": [
706
+ "312e322e332e343a310a",
707
+ "312e322e332e343a320a"
708
+ ]
709
+ },
710
+ "source": {
711
+ "buffer": "312e322e332e343a310a312e322e332e343a320a",
712
+ "events": [
713
+ {
714
+ "op": "print",
715
+ "text": "57726974696e673a2062616e6c6973742e7478740a"
716
+ },
717
+ {
718
+ "mode": 1,
719
+ "op": "open",
720
+ "path": "62616e6c6973742e747874"
721
+ },
722
+ {
723
+ "handle": 0,
724
+ "op": "write",
725
+ "text": "312e322e332e343a310a312e322e332e343a320a"
726
+ },
727
+ {
728
+ "handle": 0,
729
+ "op": "close"
730
+ }
731
+ ],
732
+ "formats": [
733
+ "312e322e332e343a310a",
734
+ "312e322e332e343a320a"
735
+ ]
736
+ }
737
+ },
738
+ {
739
+ "rust": {
740
+ "buffer": "312e322e332e343a310a312e322e332e343a320a",
741
+ "events": [
742
+ {
743
+ "op": "print",
744
+ "text": "57726974696e673a2062616e6c6973742e7478740a"
745
+ },
746
+ {
747
+ "mode": 1,
748
+ "op": "open",
749
+ "path": "62616e6c6973742e747874"
750
+ },
751
+ {
752
+ "handle": 7,
753
+ "op": "write",
754
+ "text": "312e322e332e343a310a312e322e332e343a320a"
755
+ },
756
+ {
757
+ "handle": 7,
758
+ "op": "close"
759
+ }
760
+ ],
761
+ "formats": [
762
+ "312e322e332e343a310a",
763
+ "312e322e332e343a320a"
764
+ ]
765
+ },
766
+ "source": {
767
+ "buffer": "312e322e332e343a310a312e322e332e343a320a",
768
+ "events": [
769
+ {
770
+ "op": "print",
771
+ "text": "57726974696e673a2062616e6c6973742e7478740a"
772
+ },
773
+ {
774
+ "mode": 1,
775
+ "op": "open",
776
+ "path": "62616e6c6973742e747874"
777
+ },
778
+ {
779
+ "handle": 7,
780
+ "op": "write",
781
+ "text": "312e322e332e343a310a312e322e332e343a320a"
782
+ },
783
+ {
784
+ "handle": 7,
785
+ "op": "close"
786
+ }
787
+ ],
788
+ "formats": [
789
+ "312e322e332e343a310a",
790
+ "312e322e332e343a320a"
791
+ ]
792
+ }
793
+ },
794
+ {
795
+ "rust": {
796
+ "buffer": "312e322e332e343a310a312e322e332e343a320a",
797
+ "events": [
798
+ {
799
+ "op": "print",
800
+ "text": "57726974696e673a2062616e6c6973742e7478740a"
801
+ },
802
+ {
803
+ "mode": 1,
804
+ "op": "open",
805
+ "path": "62616e6c6973742e747874"
806
+ },
807
+ {
808
+ "handle": 4294967295,
809
+ "op": "write",
810
+ "text": "312e322e332e343a310a312e322e332e343a320a"
811
+ },
812
+ {
813
+ "handle": 4294967295,
814
+ "op": "close"
815
+ }
816
+ ],
817
+ "formats": [
818
+ "312e322e332e343a310a",
819
+ "312e322e332e343a320a"
820
+ ]
821
+ },
822
+ "source": {
823
+ "buffer": "312e322e332e343a310a312e322e332e343a320a",
824
+ "events": [
825
+ {
826
+ "op": "print",
827
+ "text": "57726974696e673a2062616e6c6973742e7478740a"
828
+ },
829
+ {
830
+ "mode": 1,
831
+ "op": "open",
832
+ "path": "62616e6c6973742e747874"
833
+ },
834
+ {
835
+ "handle": 4294967295,
836
+ "op": "write",
837
+ "text": "312e322e332e343a310a312e322e332e343a320a"
838
+ },
839
+ {
840
+ "handle": 4294967295,
841
+ "op": "close"
842
+ }
843
+ ],
844
+ "formats": [
845
+ "312e322e332e343a310a",
846
+ "312e322e332e343a320a"
847
+ ]
848
+ }
849
+ }
850
+ ],
851
+ "source_report": "docs/research/qvm-filter-export.json",
852
+ "source_report_sha256": "4ce6e42c9020ae43013367b4c920a94b1a6c9223ec49b8f3802e99bb7ccfb1f1"
853
+ }
docs/research/rust-health-impulse.json CHANGED
@@ -2985,7 +2985,7 @@
2985
  "exit_code": 2
2986
  }
2987
  ],
2988
- "rust_unit_tests": 185,
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": 187,
2989
  "source_report": "docs/research/qvm-health-impulse.json",
2990
  "source_report_sha256": "625fd8064004ea6dbdf398d51d0af844d9c635ff04c0a0790886dddb6ab81e71"
2991
  }
scripts/analyze_rust_filter_export.py ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Compare the Rust filter policy with the original QVM report."""
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-filter-policy'],check=True,capture_output=True)
9
+ binary=Path(os.environ.get('CARGO_TARGET_DIR','target'))/'debug'/'urt-filter-policy'
10
+ path=Path('docs/research/qvm-filter-export.json');data=path.read_bytes();probes=[]
11
+ for p in json.loads(data)['probes']:
12
+ a=p['input'];words=encode(a)
13
+ probes.append(dict(source={k:p[k] for k in ['events', 'formats', 'buffer']},rust=result(binary,'export',words)))
14
+ write_json(Path('docs/research/rust-filter-export.json'),dict(source_report=str(path),source_report_sha256=hashlib.sha256(data).hexdigest(),probes=probes,limits='Finite recovered policy parity; native filesystem/network effects are not executed.'))
15
+
16
+ def encode(a):return [len(a['rows']),a['handle'],*[v for r in a['rows'] for v in r]]
17
+ if __name__=='__main__':main()
scripts/test_rust_filter_export.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-filter-export.json').read_text());self.assertGreaterEqual(len(r['probes']),18)
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-filter-export.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
@@ -3109,3 +3109,18 @@ report scripts/analyze_qvm_filter_export.py docs/research/qvm-filter-export.json
3109
  edge docs/research/qvm-filter-export.json scripts/test_qvm_filter_export.py
3110
  group qvm-filter-export scripts/analyze_qvm_filter_export.py
3111
  edge scripts/analyze_qvm_filter_export.py scripts/analyze_qvm_resumer_audit.py
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3109
  edge docs/research/qvm-filter-export.json scripts/test_qvm_filter_export.py
3110
  group qvm-filter-export scripts/analyze_qvm_filter_export.py
3111
  edge scripts/analyze_qvm_filter_export.py scripts/analyze_qvm_resumer_audit.py
3112
+ report scripts/analyze_rust_filter_export.py docs/research/rust-filter-export.json
3113
+ edge docs/research/rust-filter-export.json scripts/test_rust_filter_export.py
3114
+ group rust-filter-export scripts/analyze_rust_filter_export.py
3115
+ edge scripts/analyze_rust_filter_export.py scripts/analyze_qvm_resumer_audit.py
3116
+ edge Cargo.toml scripts/analyze_rust_filter_export.py
3117
+ edge Cargo.lock scripts/analyze_rust_filter_export.py
3118
+ edge crates/urt-gameplay/Cargo.toml scripts/analyze_rust_filter_export.py
3119
+ edge crates/urt-gameplay/src/lib.rs scripts/analyze_rust_filter_export.py
3120
+ edge crates/urt-gameplay/src/filter_lifecycle.rs scripts/analyze_rust_filter_export.py
3121
+ edge crates/urt-gameplay/src/native_policy.rs scripts/analyze_rust_filter_export.py
3122
+ edge crates/urt-gameplay/src/bin/urt-filter-policy.rs scripts/analyze_rust_filter_export.py
3123
+ edge docs/research/qvm-filter-export.json scripts/analyze_rust_filter_export.py
3124
+ group rust-filter-export scripts/analyze_rust_health_impulse.py
3125
+ group gameplay scripts/analyze_rust_filter_export.py
3126
+ edge crates/urt-gameplay/src/qvm_format.rs scripts/analyze_rust_filter_export.py