gameplay: preserve filter export reload losses
Browse files- crates/urt-gameplay/src/bin/urt-filter-loading.rs +69 -0
- crates/urt-gameplay/src/filter_loading.rs +102 -0
- docs/FINDINGS.md +2 -0
- docs/PROVISIONAL_TODO.md +5 -1
- docs/RESEARCH_LEDGER.md +6 -0
- docs/REVERSE_ENGINEERING_TODO.md +5 -1
- docs/TESTING.md +2 -0
- docs/research/QVM_FILTER_LOADING_BATCH.md +55 -0
- docs/research/QVM_FILTER_PERSISTENCE_BATCH.md +3 -1
- docs/research/README.md +4 -0
- docs/research/RUST_FILTER_ROUNDTRIP.md +5 -0
- docs/research/rust-filter-roundtrip.json +0 -0
- docs/research/rust-health-impulse.json +1 -1
- scripts/analyze_rust_filter_roundtrip.py +17 -0
- scripts/test_rust_filter_roundtrip.py +9 -0
- xtask/checks.tsv +16 -0
- xtask/src/lib.rs +25 -0
crates/urt-gameplay/src/bin/urt-filter-loading.rs
CHANGED
|
@@ -63,6 +63,7 @@ fn main() {
|
|
| 63 |
}
|
| 64 |
"load" => println!("{}", loading(&w)),
|
| 65 |
"duration" => println!("{}", duration(&w)),
|
|
|
|
| 66 |
_ => panic!("unknown policy"),
|
| 67 |
}
|
| 68 |
}
|
|
@@ -240,3 +241,71 @@ fn duration(w: &[u32]) -> String {
|
|
| 240 |
effects, updates, ring, rows
|
| 241 |
)
|
| 242 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 63 |
}
|
| 64 |
"load" => println!("{}", loading(&w)),
|
| 65 |
"duration" => println!("{}", duration(&w)),
|
| 66 |
+
"roundtrip" => println!("{}", roundtrip(&w)),
|
| 67 |
_ => panic!("unknown policy"),
|
| 68 |
}
|
| 69 |
}
|
|
|
|
| 241 |
effects, updates, ring, rows
|
| 242 |
)
|
| 243 |
}
|
| 244 |
+
|
| 245 |
+
fn exported_json(p: Option<urt_gameplay::filter_lifecycle::FilterExport>) -> String {
|
| 246 |
+
let Some(p) = p else {
|
| 247 |
+
return r#"{"events":[],"formats":[],"buffer":"7374616c65"}"#.into();
|
| 248 |
+
};
|
| 249 |
+
use urt_gameplay::filter_lifecycle::FilterFileEffect;
|
| 250 |
+
let events = p
|
| 251 |
+
.effects()
|
| 252 |
+
.iter()
|
| 253 |
+
.map(|e| match e {
|
| 254 |
+
FilterFileEffect::Print(t) => format!(r#"{{"op":"print","text":"{}"}}"#, hex(t)),
|
| 255 |
+
FilterFileEffect::Open { path, mode } => {
|
| 256 |
+
format!(r#"{{"op":"open","path":"{}","mode":{}}}"#, hex(path), mode)
|
| 257 |
+
}
|
| 258 |
+
FilterFileEffect::Write { handle, bytes } => format!(
|
| 259 |
+
r#"{{"op":"write","handle":{},"text":"{}"}}"#,
|
| 260 |
+
handle,
|
| 261 |
+
hex(bytes)
|
| 262 |
+
),
|
| 263 |
+
FilterFileEffect::Close(h) => format!(r#"{{"op":"close","handle":{}}}"#, h),
|
| 264 |
+
})
|
| 265 |
+
.collect::<Vec<_>>()
|
| 266 |
+
.join(",");
|
| 267 |
+
let formats = p
|
| 268 |
+
.lines
|
| 269 |
+
.iter()
|
| 270 |
+
.map(|l| format!("\"{}\"", hex(l)))
|
| 271 |
+
.collect::<Vec<_>>()
|
| 272 |
+
.join(",");
|
| 273 |
+
format!(
|
| 274 |
+
r#"{{"events":[{}],"formats":[{}],"buffer":"{}"}}"#,
|
| 275 |
+
events,
|
| 276 |
+
formats,
|
| 277 |
+
hex(&p.text)
|
| 278 |
+
)
|
| 279 |
+
}
|
| 280 |
+
fn roundtrip(w: &[u32]) -> String {
|
| 281 |
+
let n = w[2] as usize;
|
| 282 |
+
let mut p = 3;
|
| 283 |
+
let mut source = vec![];
|
| 284 |
+
for _ in 0..n {
|
| 285 |
+
source.push(urt_gameplay::native_policy::FilterRecord {
|
| 286 |
+
mask: w[p],
|
| 287 |
+
comparison: w[p + 1],
|
| 288 |
+
metadata: w[p + 2],
|
| 289 |
+
});
|
| 290 |
+
p += 3;
|
| 291 |
+
}
|
| 292 |
+
let prior = blob(w, &mut p);
|
| 293 |
+
assert_eq!(p, w.len());
|
| 294 |
+
let mut target = vec![
|
| 295 |
+
urt_gameplay::native_policy::FilterRecord {
|
| 296 |
+
mask: 0x11223344,
|
| 297 |
+
comparison: u32::MAX,
|
| 298 |
+
metadata: 0x99aabbcc
|
| 299 |
+
};
|
| 300 |
+
8
|
| 301 |
+
];
|
| 302 |
+
let mut count = if w[1] != 0 { n } else { 0 };
|
| 303 |
+
target[..count].copy_from_slice(&source[..count]);
|
| 304 |
+
let p = filter_roundtrip(&source, &mut target, &mut count, &prior, w[0]).unwrap();
|
| 305 |
+
format!(
|
| 306 |
+
r#"{{"exported":{},"disk":"{}","loaded":{}}}"#,
|
| 307 |
+
exported_json(p.exported),
|
| 308 |
+
hex(&p.disk),
|
| 309 |
+
load_json(p.loaded, &target, count)
|
| 310 |
+
)
|
| 311 |
+
}
|
crates/urt-gameplay/src/filter_loading.rs
CHANGED
|
@@ -408,3 +408,105 @@ mod duration_tests {
|
|
| 408 |
assert_eq!(ring, 7);
|
| 409 |
}
|
| 410 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 408 |
assert_eq!(ring, 7);
|
| 409 |
}
|
| 410 |
}
|
| 411 |
+
|
| 412 |
+
#[derive(Clone, Debug, PartialEq, Eq)]
|
| 413 |
+
pub struct FilterRoundtrip {
|
| 414 |
+
pub exported: Option<crate::filter_lifecycle::FilterExport>,
|
| 415 |
+
pub disk: Vec<u8>,
|
| 416 |
+
pub loaded: FilterLoad,
|
| 417 |
+
}
|
| 418 |
+
/// Compose recovered export/load using captured write bytes as the next native
|
| 419 |
+
/// read reply. This models complete transfer, not actual filesystem acceptance.
|
| 420 |
+
/// When export is absent, the caller's prior file is supplied to the loader.
|
| 421 |
+
pub fn filter_roundtrip(
|
| 422 |
+
source: &[FilterRecord],
|
| 423 |
+
target: &mut [FilterRecord],
|
| 424 |
+
count: &mut usize,
|
| 425 |
+
prior_file: &[u8],
|
| 426 |
+
handle: u32,
|
| 427 |
+
) -> Result<FilterRoundtrip, Error> {
|
| 428 |
+
let exported = crate::filter_lifecycle::export_filters(source, handle)?;
|
| 429 |
+
let disk = exported
|
| 430 |
+
.as_ref()
|
| 431 |
+
.map(|p| p.text.as_slice())
|
| 432 |
+
.unwrap_or(prior_file)
|
| 433 |
+
.to_vec();
|
| 434 |
+
if disk.len() > 131071 {
|
| 435 |
+
return Err(Error::InvalidInput);
|
| 436 |
+
}
|
| 437 |
+
let loaded = load_filters(
|
| 438 |
+
target,
|
| 439 |
+
count,
|
| 440 |
+
FilterReadReply {
|
| 441 |
+
length: disk.len() as i32,
|
| 442 |
+
handle,
|
| 443 |
+
delivered: &disk,
|
| 444 |
+
initial: b"",
|
| 445 |
+
},
|
| 446 |
+
)?;
|
| 447 |
+
Ok(FilterRoundtrip {
|
| 448 |
+
exported,
|
| 449 |
+
disk,
|
| 450 |
+
loaded,
|
| 451 |
+
})
|
| 452 |
+
}
|
| 453 |
+
#[cfg(test)]
|
| 454 |
+
mod roundtrip_tests {
|
| 455 |
+
use super::*;
|
| 456 |
+
fn spare() -> FilterRecord {
|
| 457 |
+
FilterRecord {
|
| 458 |
+
mask: 0x11223344,
|
| 459 |
+
comparison: u32::MAX,
|
| 460 |
+
metadata: 0x99aabbcc,
|
| 461 |
+
}
|
| 462 |
+
}
|
| 463 |
+
#[test]
|
| 464 |
+
fn absent_export_reloads_prior_file_but_hole_export_truncates() {
|
| 465 |
+
let mut target = [spare(); 8];
|
| 466 |
+
let mut count = 0;
|
| 467 |
+
let p = filter_roundtrip(&[], &mut target, &mut count, b"9.8.7.6:42\n", 0).unwrap();
|
| 468 |
+
assert!(p.exported.is_none());
|
| 469 |
+
assert_eq!(count, 1);
|
| 470 |
+
assert_eq!(target[0].metadata, 42);
|
| 471 |
+
count = 0;
|
| 472 |
+
let p = filter_roundtrip(&[spare()], &mut target, &mut count, b"9.8.7.6:42\n", 0).unwrap();
|
| 473 |
+
assert!(p.exported.is_some());
|
| 474 |
+
assert_eq!(count, 0);
|
| 475 |
+
assert!(p.disk.is_empty());
|
| 476 |
+
}
|
| 477 |
+
#[test]
|
| 478 |
+
fn mask_and_minimum_integer_do_not_round_trip() {
|
| 479 |
+
let row = FilterRecord {
|
| 480 |
+
mask: 0,
|
| 481 |
+
comparison: 0x0100007f,
|
| 482 |
+
metadata: 0x80000000,
|
| 483 |
+
};
|
| 484 |
+
let mut target = [spare(); 8];
|
| 485 |
+
let mut count = 0;
|
| 486 |
+
filter_roundtrip(&[row], &mut target, &mut count, b"", 7).unwrap();
|
| 487 |
+
assert_eq!(target[0].mask, u32::MAX);
|
| 488 |
+
assert_eq!(target[0].comparison, row.comparison);
|
| 489 |
+
assert_eq!(target[0].metadata, 0);
|
| 490 |
+
}
|
| 491 |
+
#[test]
|
| 492 |
+
fn retained_duplicates_grow_and_unsupported_prior_file_is_atomic() {
|
| 493 |
+
let row = FilterRecord {
|
| 494 |
+
mask: u32::MAX,
|
| 495 |
+
comparison: 0x04030201,
|
| 496 |
+
metadata: 7,
|
| 497 |
+
};
|
| 498 |
+
let source = [row, FilterRecord { metadata: 8, ..row }];
|
| 499 |
+
let mut target = [spare(); 8];
|
| 500 |
+
target[..2].copy_from_slice(&source);
|
| 501 |
+
let mut count = 2;
|
| 502 |
+
filter_roundtrip(&source, &mut target, &mut count, b"", 7).unwrap();
|
| 503 |
+
assert_eq!(count, 4);
|
| 504 |
+
assert_eq!(target[0].metadata, 8);
|
| 505 |
+
assert_eq!(target[2].metadata, u32::MAX);
|
| 506 |
+
assert_eq!(target[3].metadata, u32::MAX);
|
| 507 |
+
let before = target;
|
| 508 |
+
assert!(filter_roundtrip(&[], &mut target, &mut count, &[b'1'; 1024], 7).is_err());
|
| 509 |
+
assert_eq!(target, before);
|
| 510 |
+
assert_eq!(count, 4);
|
| 511 |
+
}
|
| 512 |
+
}
|
docs/FINDINGS.md
CHANGED
|
@@ -1837,3 +1837,5 @@ RE-950: Eighty actual252213 fixtures compose integer/time/metadata children, pre
|
|
| 1837 |
RE-951: Rust matches80 original duration/usage command fixtures, preserving wrapping numeric prefixes, first-match metadata save requests, exact client/console text and formatter-counter wrap. Typed effects preserve time-before-update order; usage skips both. Unit tests cover client-only ring changes, negative duration producing permanent-1 metadata, duplicate preservation and atomic unsupported-address rejection. Native replies remain supplied or captured. [Evidence](research/RUST_FILTER_DURATION.md).
|
| 1838 |
|
| 1839 |
RE-952: Twenty-four actual export/reload compositions transfer captured file bytes through explicit native replies. Empty-table export leaves the prior file intact, whereas all-hole export truncates. Reload loses masks, converts the original INT_MIN formatter punctuation to metadata0, routes duplicate updates to the first match and grows retained tables. Source formatter/parser/load bodies execute; actual filesystem acceptance and unlimited reload/capacity remain open. [Evidence](research/QVM_FILTER_ROUNDTRIP.md).
|
|
|
|
|
|
|
|
|
| 1837 |
RE-951: Rust matches80 original duration/usage command fixtures, preserving wrapping numeric prefixes, first-match metadata save requests, exact client/console text and formatter-counter wrap. Typed effects preserve time-before-update order; usage skips both. Unit tests cover client-only ring changes, negative duration producing permanent-1 metadata, duplicate preservation and atomic unsupported-address rejection. Native replies remain supplied or captured. [Evidence](research/RUST_FILTER_DURATION.md).
|
| 1838 |
|
| 1839 |
RE-952: Twenty-four actual export/reload compositions transfer captured file bytes through explicit native replies. Empty-table export leaves the prior file intact, whereas all-hole export truncates. Reload loses masks, converts the original INT_MIN formatter punctuation to metadata0, routes duplicate updates to the first match and grows retained tables. Source formatter/parser/load bodies execute; actual filesystem acceptance and unlimited reload/capacity remain open. [Evidence](research/QVM_FILTER_ROUNDTRIP.md).
|
| 1840 |
+
|
| 1841 |
+
RE-953: Rust matches24 original export/reload compositions, retaining stale prior files when export is absent, all-hole truncation, wildcard-mask loss, INT_MIN metadata reload as0, duplicate routing and retained-table growth. The staged loader rejects unsupported domains without mutation. Unit tests cover these losses, duplicate growth and atomic unsupported prior-file rejection. Captured write bytes are supplied as read replies; actual filesystem acceptance remains open. [Evidence](research/RUST_FILTER_ROUNDTRIP.md).
|
docs/PROVISIONAL_TODO.md
CHANGED
|
@@ -1866,7 +1866,7 @@ RE-924–933 completed bounded bot settings, announcement, connect-child composi
|
|
| 1866 |
|
| 1867 |
- [x] RE-943 Rust removal with survivor export and typed file effects ([evidence](research/RUST_FILTER_REMOVE_EXPORT.md)).
|
| 1868 |
|
| 1869 |
-
RE-934–943 completed bounded filter export/removal/metadata and insertion/removal persistence compositions.
|
| 1870 |
|
| 1871 |
- [x] RE-944 Original filter time flattening and asymmetric inverse ([evidence](research/QVM_FILTER_TIME.md)).
|
| 1872 |
|
|
@@ -1885,3 +1885,7 @@ RE-934–943 completed bounded filter export/removal/metadata and insertion/remo
|
|
| 1885 |
- [x] RE-951 Rust expiration command with typed time and usage effects ([evidence](research/RUST_FILTER_DURATION.md)).
|
| 1886 |
|
| 1887 |
- [x] RE-952 Original export reload and lossy persistence behavior ([evidence](research/QVM_FILTER_ROUNDTRIP.md)).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1866 |
|
| 1867 |
- [x] RE-943 Rust removal with survivor export and typed file effects ([evidence](research/RUST_FILTER_REMOVE_EXPORT.md)).
|
| 1868 |
|
| 1869 |
+
RE-934–943 completed bounded filter export/removal/metadata and insertion/removal persistence compositions. The following batch recovers time, expiry, loading and duration contracts; remaining command callers, live adapters and runtime integration remain open. [Batch and next work](research/QVM_FILTER_PERSISTENCE_BATCH.md).
|
| 1870 |
|
| 1871 |
- [x] RE-944 Original filter time flattening and asymmetric inverse ([evidence](research/QVM_FILTER_TIME.md)).
|
| 1872 |
|
|
|
|
| 1885 |
- [x] RE-951 Rust expiration command with typed time and usage effects ([evidence](research/RUST_FILTER_DURATION.md)).
|
| 1886 |
|
| 1887 |
- [x] RE-952 Original export reload and lossy persistence behavior ([evidence](research/QVM_FILTER_ROUNDTRIP.md)).
|
| 1888 |
+
|
| 1889 |
+
- [x] RE-953 Rust export reload composition and persistence-loss regressions ([evidence](research/RUST_FILTER_ROUNDTRIP.md)).
|
| 1890 |
+
|
| 1891 |
+
RE-944–953 completed bounded time/expiry/loading/duration and export/reload contracts. RE-954 tracks remaining commands/callers, native ownership and runtime acceptance. [Batch and next work](research/QVM_FILTER_LOADING_BATCH.md).
|
docs/RESEARCH_LEDGER.md
CHANGED
|
@@ -2475,3 +2475,9 @@ Rust matches80 original duration/usage command fixtures, preserving wrapping num
|
|
| 2475 |
## 2026-10-28 — RE-952 Original export reload and lossy persistence behavior
|
| 2476 |
|
| 2477 |
Twenty-four actual export/reload compositions transfer captured file bytes through explicit native replies. Empty-table export leaves the prior file intact, whereas all-hole export truncates. Reload loses masks, converts the original INT_MIN formatter punctuation to metadata0, routes duplicate updates to the first match and grows retained tables. Source formatter/parser/load bodies execute; actual filesystem acceptance and unlimited reload/capacity remain open. Focused `cargo xtask test-group qvm-filter-roundtrip` 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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2475 |
## 2026-10-28 — RE-952 Original export reload and lossy persistence behavior
|
| 2476 |
|
| 2477 |
Twenty-four actual export/reload compositions transfer captured file bytes through explicit native replies. Empty-table export leaves the prior file intact, whereas all-hole export truncates. Reload loses masks, converts the original INT_MIN formatter punctuation to metadata0, routes duplicate updates to the first match and grows retained tables. Source formatter/parser/load bodies execute; actual filesystem acceptance and unlimited reload/capacity remain open. Focused `cargo xtask test-group qvm-filter-roundtrip` 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.
|
| 2478 |
+
|
| 2479 |
+
## 2026-10-28 — RE-953 Rust export reload composition and persistence-loss regressions
|
| 2480 |
+
|
| 2481 |
+
Rust matches24 original export/reload compositions, retaining stale prior files when export is absent, all-hole truncation, wildcard-mask loss, INT_MIN metadata reload as0, duplicate routing and retained-table growth. The staged loader rejects unsupported domains without mutation. Unit tests cover these losses, duplicate growth and atomic unsupported prior-file rejection. Captured write bytes are supplied as read replies; actual filesystem acceptance remains open. Focused `cargo xtask test-group rust-filter-roundtrip` 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.
|
| 2482 |
+
|
| 2483 |
+
Batch RE-944–953 boundary: the single `cargo xtask test-full --since ed9db0e6` run after commit ten passed with the flake-declared Nix Python: 1,838 Python tests, 249 Rust tests (assets10, gameplay209, xtask30), 96 deterministic report producers, storage policy, 524 documentation files and whitespace guards. No generated report drift. Focused dependency-selection regression covers all five new source/Rust pairs and shared loading/lifecycle/native-policy/formatter inputs, including gameplay test-count metadata. Validation notes were amended into task ten; original assets unchanged. See [batch findings and next work](research/QVM_FILTER_LOADING_BATCH.md).
|
docs/REVERSE_ENGINEERING_TODO.md
CHANGED
|
@@ -1903,7 +1903,7 @@ RE-934–943 continue the prior batch with filter export/removal/metadata and co
|
|
| 1903 |
|
| 1904 |
- [x] RE-943 Rust removal with survivor export and typed file effects ([evidence](research/RUST_FILTER_REMOVE_EXPORT.md)).
|
| 1905 |
|
| 1906 |
-
|
| 1907 |
|
| 1908 |
- [x] RE-944 Original filter time flattening and asymmetric inverse ([evidence](research/QVM_FILTER_TIME.md)).
|
| 1909 |
|
|
@@ -1922,3 +1922,7 @@ RE-934–943 continue the prior batch with filter export/removal/metadata and co
|
|
| 1922 |
- [x] RE-951 Rust expiration command with typed time and usage effects ([evidence](research/RUST_FILTER_DURATION.md)).
|
| 1923 |
|
| 1924 |
- [x] RE-952 Original export reload and lossy persistence behavior ([evidence](research/QVM_FILTER_ROUNDTRIP.md)).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1903 |
|
| 1904 |
- [x] RE-943 Rust removal with survivor export and typed file effects ([evidence](research/RUST_FILTER_REMOVE_EXPORT.md)).
|
| 1905 |
|
| 1906 |
+
RE-944–953 recover bounded time, expiry, loading, duration and persistence round trips; live adapters and full runtime integration remain open.
|
| 1907 |
|
| 1908 |
- [x] RE-944 Original filter time flattening and asymmetric inverse ([evidence](research/QVM_FILTER_TIME.md)).
|
| 1909 |
|
|
|
|
| 1922 |
- [x] RE-951 Rust expiration command with typed time and usage effects ([evidence](research/RUST_FILTER_DURATION.md)).
|
| 1923 |
|
| 1924 |
- [x] RE-952 Original export reload and lossy persistence behavior ([evidence](research/QVM_FILTER_ROUNDTRIP.md)).
|
| 1925 |
+
|
| 1926 |
+
- [x] RE-953 Rust export reload composition and persistence-loss regressions ([evidence](research/RUST_FILTER_ROUNDTRIP.md)).
|
| 1927 |
+
|
| 1928 |
+
- [ ] RE-954 Recover remaining filter commands/callers and native time/file/network ownership, bot setup/userinfo and full Rust/Bevy/Solari acceptance ([next work](research/QVM_FILTER_LOADING_BATCH.md)).
|
docs/TESTING.md
CHANGED
|
@@ -177,3 +177,5 @@ RE-914–923 adds `qvm-byte-compare`, `rust-byte-compare`, `qvm-address-filter`,
|
|
| 177 |
RE-924–933 adds `qvm-bot-settings`, `rust-bot-settings`, `qvm-team-announcement`, `rust-team-announcement`, `qvm-resolved-connect-tail`, `rust-resolved-connect-tail`, `qvm-resolved-connect-complete`, `rust-resolved-connect-complete`, `qvm-filter-insert` and `rust-filter-insert`. Use one group per invocation. Full validation after task ten uses `cargo xtask test-full --since bc3e7621` with explicit flake-declared Nix PYTHON. [Callback/filter evidence](research/QVM_BOT_ANNOUNCEMENT_FILTER_BATCH.md).
|
| 178 |
|
| 179 |
Filter persistence focused groups: `qvm-filter-export`, `rust-filter-export`, `qvm-filter-remove`, `rust-filter-remove`, `qvm-filter-metadata`, `rust-filter-metadata`, `qvm-filter-insert-export`, `rust-filter-insert-export`, `qvm-filter-remove-export` and `rust-filter-remove-export`. The shared Rust filter lifecycle module and adapter select all affected parity reports and scoped gameplay test metadata; formatter edits also select these consumers. Run one group per invocation. Native file effects are captured plans in these checks.
|
|
|
|
|
|
|
|
|
| 177 |
RE-924–933 adds `qvm-bot-settings`, `rust-bot-settings`, `qvm-team-announcement`, `rust-team-announcement`, `qvm-resolved-connect-tail`, `rust-resolved-connect-tail`, `qvm-resolved-connect-complete`, `rust-resolved-connect-complete`, `qvm-filter-insert` and `rust-filter-insert`. Use one group per invocation. Full validation after task ten uses `cargo xtask test-full --since bc3e7621` with explicit flake-declared Nix PYTHON. [Callback/filter evidence](research/QVM_BOT_ANNOUNCEMENT_FILTER_BATCH.md).
|
| 178 |
|
| 179 |
Filter persistence focused groups: `qvm-filter-export`, `rust-filter-export`, `qvm-filter-remove`, `rust-filter-remove`, `qvm-filter-metadata`, `rust-filter-metadata`, `qvm-filter-insert-export`, `rust-filter-insert-export`, `qvm-filter-remove-export` and `rust-filter-remove-export`. The shared Rust filter lifecycle module and adapter select all affected parity reports and scoped gameplay test metadata; formatter edits also select these consumers. Run one group per invocation. Native file effects are captured plans in these checks.
|
| 180 |
+
|
| 181 |
+
Filter loading focused groups: `qvm-filter-time`, `rust-filter-time`, `qvm-filter-expiry`, `rust-filter-expiry`, `qvm-filter-load`, `rust-filter-load`, `qvm-filter-duration`, `rust-filter-duration`, `qvm-filter-roundtrip` and `rust-filter-roundtrip`. The shared loading module/adapter, native policies, lifecycle module and formatter inputs select affected parity producers and scoped gameplay test-count metadata. Run one group per invocation. Time/file replies are supplied snapshots; native effects are captured.
|
docs/research/QVM_FILTER_LOADING_BATCH.md
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Filter time, expiry, loading and round trips: RE-944–953
|
| 2 |
+
|
| 3 |
+
Ten tasks recover five source/Rust contracts across **232 paired fixtures**. They extend the [persistence batch](QVM_FILTER_PERSISTENCE_BATCH.md) with time conversion, full-table expiry, file loading, the expiration-duration command and export/reload compositions. Every task has its own commit and focused `cargo xtask` validation. Native time and file replies remain supplied; console, network and file effects are captured plans.
|
| 4 |
+
|
| 5 |
+
| Tasks | Evidence | Paired fixtures |
|
| 6 |
+
| --- | --- | ---: |
|
| 7 |
+
| RE-944 / RE-945 | [Original time helpers](QVM_FILTER_TIME.md) / [Rust time helpers](RUST_FILTER_TIME.md) | 84 |
|
| 8 |
+
| RE-946 / RE-947 | [Original expiry](QVM_FILTER_EXPIRY.md) / [Rust expiry](RUST_FILTER_EXPIRY.md) | 12 |
|
| 9 |
+
| RE-948 / RE-949 | [Original loader](QVM_FILTER_LOAD.md) / [Rust loader](RUST_FILTER_LOAD.md) | 32 |
|
| 10 |
+
| RE-950 / RE-951 | [Original duration command](QVM_FILTER_DURATION.md) / [Rust command](RUST_FILTER_DURATION.md) | 80 |
|
| 11 |
+
| RE-952 / RE-953 | [Original export/reload](QVM_FILTER_ROUNDTRIP.md) / [Rust composition](RUST_FILTER_ROUNDTRIP.md) | 24 |
|
| 12 |
+
|
| 13 |
+
## Time and expiry findings
|
| 14 |
+
|
| 15 |
+
Actual251995 combines structure words at offsets28,8,4 as day-of-year×1440 + hour×60 + minute, using wrapping32-bit arithmetic. It does not inspect the year. Actual252024 writes the quotient at offset28 and the computed hour at offset8, then stores that hour modulo60 at offset4. This inverse loses the original minutes. Source fixtures cover negative fields, signed division truncation, INT_MIN/MAX and six unrelated structure words that remain unchanged. Rust preserves the observed arithmetic and asymmetric inverse.
|
| 16 |
+
|
| 17 |
+
Actual252067 requests native time, executes251995 and scans **all4096 records**, independent of active count. A metadata word other than-1 expires only when it is unsigned-less-than the current minute word. It sets comparison to-1 while retaining mask, metadata and count. Equality is retained, and the routine does not export. Twelve source fixtures check full-table checksums, permanent markers, high-bit times and last-slot mutation with count zero. Rust requires a complete4096-slot snapshot and has no active-count parameter. Native calendar rollover and invocation cadence remain open.
|
| 18 |
+
|
| 19 |
+
## Loading and command findings
|
| 20 |
+
|
| 21 |
+
Actual252933 opens `banlist.txt` for reading, requests the declared length, closes the supplied handle, then processes lines. It does not clear the existing count or check handle success before read/close. The bounded missing-file fixture supplies length-1 and handle0; the source still requests a read with the raw-1 length and closes0, then skips parsing. These are captured effects, not actual unsafe native reads. The Rust API supports that explicit reply while rejecting other unsupported negative lengths and unsafe buffer/line domains.
|
| 22 |
+
|
| 23 |
+
The loader splits on LF, skips raw lines of zero or one byte, accepts a final unterminated line and truncates callback text at embedded NUL. It executes actual252829 insertion, then searches for a colon through36489. If found, it parses metadata through37159 and calls252127 with saving disabled. A short supplied read leaves explicitly seeded initial-buffer bytes visible. Thirty-two source cases cover these paths, CRLF, invalid addresses, wildcard/sentinel entries, overflowing metadata prefixes and loading into existing tables.
|
| 24 |
+
|
| 25 |
+
Insertion and metadata update each perform their own scan. Inserting a duplicate can append a new record, while the subsequent metadata update changes an earlier matching record. The new duplicate retains metadata-1. Retained tables therefore grow on repeated loads; loading is not replacement. Rust stages all table/count changes and rejects unsupported later lines or token domains without partial mutation.
|
| 26 |
+
|
| 27 |
+
Actual252213 selects exact console/client usage output when either argument is empty, without requesting time or updating metadata. Client usage executes70458/37914 and advances the formatter ring, including wrapping fromUINT_MAX. With nonempty arguments, it parses duration through37159, requests native time, executes251995, adds with word wrap and calls252127 with saving enabled. Negative durations can produce metadata-1, the permanent marker used by expiry. Eighty fixtures cover duplicate matches, missing/invalid addresses, overflow, empty arguments and both usage contexts. Export requests are captured in this command contract; export bodies are already recovered separately.
|
| 28 |
+
|
| 29 |
+
## Persistence losses
|
| 30 |
+
|
| 31 |
+
The24 round-trip compositions supply captured export bytes as the next native read reply. This assumes complete byte transfer for the fixture; it does not establish real filesystem acceptance, especially for supplied invalid handles.
|
| 32 |
+
|
| 33 |
+
- Export ignores masks, so reload produces exact address masks from previously wildcarded entries.
|
| 34 |
+
- INT_MIN metadata uses the original formatter's wrapping-negation punctuation. Reload's integer-prefix conversion reads that punctuation as zero.
|
| 35 |
+
- Duplicate serialized entries update the first matching record's metadata; later inserted duplicates can retain metadata-1.
|
| 36 |
+
- An empty source table performs no write. Supplying the retained prior file to reload can restore its entries.
|
| 37 |
+
- A nonempty all-hole table writes an empty payload, so the prior file is replaced in the supplied-transfer composition.
|
| 38 |
+
- Loading into retained tables keeps old rows and count; it does not deduplicate or reset storage.
|
| 39 |
+
|
| 40 |
+
Rust exposes time, read, usage/update and persistence plans with explicit replies and ordered effects. The port preserves these observed losses rather than normalizing them.
|
| 41 |
+
|
| 42 |
+
## Validation
|
| 43 |
+
|
| 44 |
+
Each task ran its focused `cargo xtask test-group` before its commit: qvm/rust-filter-time, qvm/rust-filter-expiry, qvm/rust-filter-load, qvm/rust-filter-duration and qvm/rust-filter-roundtrip. Selected reports regenerated twice identically. Independent arithmetic/scan/parser/loading expectations check original fixtures; Rust parity compares all projected fields with the original source report and records its SHA256.
|
| 45 |
+
|
| 46 |
+
Rust unit tests additionally check arithmetic extremes, unrelated structure fields, unsigned expiry gates, complete-storage requirements, duplicate routing, explicit missing-file/partial-read replies, ring wrap, negative durations, lossy reloads and atomic unsupported-domain rejection. Dependency-selection regression coverage includes all five report pairs and shared policy/formatter inputs, including scoped gameplay test-count metadata. Python uses the flake-declared Nix runtime throughout, including Git hooks. Original assets are unchanged. The single `cargo xtask test-full --since ed9db0e6` run after task ten passed: **1,838 Python tests**, **249 Rust tests** (assets10, gameplay209, xtask30), **96 deterministic report producers**, storage policy, links across **524 documentation files** and whitespace guards. Regeneration left no changes. The focused dependency-selection regression also passed. Validation notes are amended into task ten, preserving ten commits for the batch.
|
| 47 |
+
|
| 48 |
+
## Next work: RE-954
|
| 49 |
+
|
| 50 |
+
- [ ] Recover253100 add-filter and253245 removal command wrappers, including client-number/userinfo resolution, drop/console/client effects and malformed inputs.
|
| 51 |
+
- [ ] Trace actual252067/252933 callers, initialization ordering, native time-structure ABI, year rollover and expiry cadence; test composition with address admission.
|
| 52 |
+
- [ ] Extend loader bounds toward capacity, long lines, malformed lengths, integer/string scratch provenance, repeated loads and complete engine file-error handling.
|
| 53 |
+
- [ ] Compose duration, expiry, removal, persistence and live address filtering with table ownership and all native adapters on macOS/Linux.
|
| 54 |
+
- [ ] Recover125185 bot setup/resource ownership,171668 userinfo mutation and5864 ranking/publication, then compose connect with native network effects.
|
| 55 |
+
- [ ] Continue collision/spatial-query recovery, respawn/intermission/events/scoreboard integration, assets/maps/models/shader conversion and Rust/Bevy/Solari runtime acceptance on macOS/Linux.
|
docs/research/QVM_FILTER_PERSISTENCE_BATCH.md
CHANGED
|
@@ -28,7 +28,7 @@ Each task ran its own `cargo xtask test-group` before its commit: qvm/rust-filte
|
|
| 28 |
|
| 29 |
The dependency registry maps both the new Rust module/adapter and formatter dependencies to the affected reports. Its focused regression includes all five source/Rust pairs. All Python processes use the flake-declared Nix runtime, including Git hooks. Original assets are unchanged. The single `cargo xtask test-full --since 7bb397d4` run after task ten passed: **1,818 Python tests**, **236 Rust tests** (assets10, gameplay196, xtask30), **92 deterministic report producers**, storage policy, links across **513 documentation files** and whitespace guards. Regeneration left no changes. Validation notes are amended into task ten, preserving ten commits for the batch.
|
| 30 |
|
| 31 |
-
##
|
| 32 |
|
| 33 |
- [ ] Recover file loading at actual252933, including newline bounds, colon metadata parsing,252829/252127 interactions, missing files, short reads and native handle failures. Check exact caller addresses before extending the trace.
|
| 34 |
- [ ] Recover duration command252213, actual251995 time conversion and native time-structure provenance; establish metadata/expiry semantics from callers rather than names.
|
|
@@ -37,3 +37,5 @@ The dependency registry maps both the new Rust module/adapter and formatter depe
|
|
| 37 |
- [ ] Implement and validate native file-effect adapters, preserving source ordering and actual engine error behavior on macOS/Linux.
|
| 38 |
- [ ] Recover125185 bot setup/resource ownership,171668 userinfo mutation and5864 ranking/publication; compose them with connect and native network effects.
|
| 39 |
- [ ] Continue native collision, spatial queries, respawn/intermission/event/scoreboard integration, asset conversion and Rust/Bevy/Solari runtime acceptance on macOS/Linux.
|
|
|
|
|
|
|
|
|
| 28 |
|
| 29 |
The dependency registry maps both the new Rust module/adapter and formatter dependencies to the affected reports. Its focused regression includes all five source/Rust pairs. All Python processes use the flake-declared Nix runtime, including Git hooks. Original assets are unchanged. The single `cargo xtask test-full --since 7bb397d4` run after task ten passed: **1,818 Python tests**, **236 Rust tests** (assets10, gameplay196, xtask30), **92 deterministic report producers**, storage policy, links across **513 documentation files** and whitespace guards. Regeneration left no changes. Validation notes are amended into task ten, preserving ten commits for the batch.
|
| 30 |
|
| 31 |
+
## Historical next work after RE-943
|
| 32 |
|
| 33 |
- [ ] Recover file loading at actual252933, including newline bounds, colon metadata parsing,252829/252127 interactions, missing files, short reads and native handle failures. Check exact caller addresses before extending the trace.
|
| 34 |
- [ ] Recover duration command252213, actual251995 time conversion and native time-structure provenance; establish metadata/expiry semantics from callers rather than names.
|
|
|
|
| 37 |
- [ ] Implement and validate native file-effect adapters, preserving source ordering and actual engine error behavior on macOS/Linux.
|
| 38 |
- [ ] Recover125185 bot setup/resource ownership,171668 userinfo mutation and5864 ranking/publication; compose them with connect and native network effects.
|
| 39 |
- [ ] Continue native collision, spatial queries, respawn/intermission/event/scoreboard integration, asset conversion and Rust/Bevy/Solari runtime acceptance on macOS/Linux.
|
| 40 |
+
|
| 41 |
+
Follow-up: [RE-944–953 time/loading findings and current next work](QVM_FILTER_LOADING_BATCH.md).
|
docs/research/README.md
CHANGED
|
@@ -1457,3 +1457,7 @@ The extension collector adds five focused tests for native tail calls, command-r
|
|
| 1457 |
- [RE-951: Rust expiration command with typed time and usage effects](RUST_FILTER_DURATION.md).
|
| 1458 |
|
| 1459 |
- [RE-952: Original export reload and lossy persistence behavior](QVM_FILTER_ROUNDTRIP.md).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1457 |
- [RE-951: Rust expiration command with typed time and usage effects](RUST_FILTER_DURATION.md).
|
| 1458 |
|
| 1459 |
- [RE-952: Original export reload and lossy persistence behavior](QVM_FILTER_ROUNDTRIP.md).
|
| 1460 |
+
|
| 1461 |
+
- [RE-953: Rust export reload composition and persistence-loss regressions](RUST_FILTER_ROUNDTRIP.md).
|
| 1462 |
+
|
| 1463 |
+
- [RE-944–953 filter loading batch and RE-954 next work](QVM_FILTER_LOADING_BATCH.md).
|
docs/research/RUST_FILTER_ROUNDTRIP.md
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Rust export reload composition and persistence-loss regressions
|
| 2 |
+
|
| 3 |
+
RE-953. Focused validation: `cargo xtask test-group rust-filter-roundtrip`. [Machine report](rust-filter-roundtrip.json).
|
| 4 |
+
|
| 5 |
+
Rust matches24 original export/reload compositions, retaining stale prior files when export is absent, all-hole truncation, wildcard-mask loss, INT_MIN metadata reload as0, duplicate routing and retained-table growth. The staged loader rejects unsupported domains without mutation. Unit tests cover these losses, duplicate growth and atomic unsupported prior-file rejection. Captured write bytes are supplied as read replies; actual filesystem acceptance remains open.
|
docs/research/rust-filter-roundtrip.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
docs/research/rust-health-impulse.json
CHANGED
|
@@ -2985,7 +2985,7 @@
|
|
| 2985 |
"exit_code": 2
|
| 2986 |
}
|
| 2987 |
],
|
| 2988 |
-
"rust_unit_tests":
|
| 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": 209,
|
| 2989 |
"source_report": "docs/research/qvm-health-impulse.json",
|
| 2990 |
"source_report_sha256": "625fd8064004ea6dbdf398d51d0af844d9c635ff04c0a0790886dddb6ab81e71"
|
| 2991 |
}
|
scripts/analyze_rust_filter_roundtrip.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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-filter-loading'],check=True,capture_output=True)
|
| 9 |
+
binary=Path(os.environ.get('CARGO_TARGET_DIR','target'))/'debug'/'urt-filter-loading'
|
| 10 |
+
path=Path('docs/research/qvm-filter-roundtrip.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 ['exported', 'disk', 'loaded']},rust=result(binary,'roundtrip',encode(p['input']))))
|
| 13 |
+
write_json(Path('docs/research/rust-filter-roundtrip.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 |
+
prior=bytes.fromhex(a['prior_file']);return [a['handle'],a['retain'],len(a['rows']),*[v for r in a['rows'] for v in r],len(prior),*prior]
|
| 17 |
+
if __name__=='__main__':main()
|
scripts/test_rust_filter_roundtrip.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-roundtrip.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-filter-roundtrip.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
|
@@ -3288,3 +3288,19 @@ report scripts/analyze_qvm_filter_roundtrip.py docs/research/qvm-filter-roundtri
|
|
| 3288 |
edge docs/research/qvm-filter-roundtrip.json scripts/test_qvm_filter_roundtrip.py
|
| 3289 |
group qvm-filter-roundtrip scripts/analyze_qvm_filter_roundtrip.py
|
| 3290 |
edge scripts/analyze_qvm_filter_roundtrip.py scripts/analyze_qvm_resumer_audit.py
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3288 |
edge docs/research/qvm-filter-roundtrip.json scripts/test_qvm_filter_roundtrip.py
|
| 3289 |
group qvm-filter-roundtrip scripts/analyze_qvm_filter_roundtrip.py
|
| 3290 |
edge scripts/analyze_qvm_filter_roundtrip.py scripts/analyze_qvm_resumer_audit.py
|
| 3291 |
+
report scripts/analyze_rust_filter_roundtrip.py docs/research/rust-filter-roundtrip.json
|
| 3292 |
+
edge docs/research/rust-filter-roundtrip.json scripts/test_rust_filter_roundtrip.py
|
| 3293 |
+
group rust-filter-roundtrip scripts/analyze_rust_filter_roundtrip.py
|
| 3294 |
+
edge scripts/analyze_rust_filter_roundtrip.py scripts/analyze_qvm_resumer_audit.py
|
| 3295 |
+
edge Cargo.toml scripts/analyze_rust_filter_roundtrip.py
|
| 3296 |
+
edge Cargo.lock scripts/analyze_rust_filter_roundtrip.py
|
| 3297 |
+
edge crates/urt-gameplay/Cargo.toml scripts/analyze_rust_filter_roundtrip.py
|
| 3298 |
+
edge crates/urt-gameplay/src/lib.rs scripts/analyze_rust_filter_roundtrip.py
|
| 3299 |
+
edge crates/urt-gameplay/src/filter_loading.rs scripts/analyze_rust_filter_roundtrip.py
|
| 3300 |
+
edge crates/urt-gameplay/src/filter_lifecycle.rs scripts/analyze_rust_filter_roundtrip.py
|
| 3301 |
+
edge crates/urt-gameplay/src/native_policy.rs scripts/analyze_rust_filter_roundtrip.py
|
| 3302 |
+
edge crates/urt-gameplay/src/bin/urt-filter-loading.rs scripts/analyze_rust_filter_roundtrip.py
|
| 3303 |
+
edge crates/urt-gameplay/src/qvm_format.rs scripts/analyze_rust_filter_roundtrip.py
|
| 3304 |
+
edge docs/research/qvm-filter-roundtrip.json scripts/analyze_rust_filter_roundtrip.py
|
| 3305 |
+
group rust-filter-roundtrip scripts/analyze_rust_health_impulse.py
|
| 3306 |
+
group gameplay scripts/analyze_rust_filter_roundtrip.py
|
xtask/src/lib.rs
CHANGED
|
@@ -1129,6 +1129,26 @@ mod integration_tests {
|
|
| 1129 |
("native_policy", "resolved_connect_complete"),
|
| 1130 |
("native_policy", "filter_insert"),
|
| 1131 |
("filter_lifecycle", "filter_export"),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1132 |
("native_policy", "filter_export"),
|
| 1133 |
("qvm_format", "filter_export"),
|
| 1134 |
("filter_lifecycle", "filter_remove"),
|
|
@@ -1232,6 +1252,11 @@ mod integration_tests {
|
|
| 1232 |
("qvm-resolved-connect-complete", "resolved_connect_complete"),
|
| 1233 |
("qvm-filter-insert", "filter_insert"),
|
| 1234 |
("qvm-filter-export", "filter_export"),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1235 |
("qvm-filter-remove", "filter_remove"),
|
| 1236 |
("qvm-filter-metadata", "filter_metadata"),
|
| 1237 |
("qvm-filter-insert-export", "filter_insert_export"),
|
|
|
|
| 1129 |
("native_policy", "resolved_connect_complete"),
|
| 1130 |
("native_policy", "filter_insert"),
|
| 1131 |
("filter_lifecycle", "filter_export"),
|
| 1132 |
+
("filter_loading", "filter_time"),
|
| 1133 |
+
("filter_lifecycle", "filter_time"),
|
| 1134 |
+
("native_policy", "filter_time"),
|
| 1135 |
+
("qvm_format", "filter_time"),
|
| 1136 |
+
("filter_loading", "filter_expiry"),
|
| 1137 |
+
("filter_lifecycle", "filter_expiry"),
|
| 1138 |
+
("native_policy", "filter_expiry"),
|
| 1139 |
+
("qvm_format", "filter_expiry"),
|
| 1140 |
+
("filter_loading", "filter_load"),
|
| 1141 |
+
("filter_lifecycle", "filter_load"),
|
| 1142 |
+
("native_policy", "filter_load"),
|
| 1143 |
+
("qvm_format", "filter_load"),
|
| 1144 |
+
("filter_loading", "filter_duration"),
|
| 1145 |
+
("filter_lifecycle", "filter_duration"),
|
| 1146 |
+
("native_policy", "filter_duration"),
|
| 1147 |
+
("qvm_format", "filter_duration"),
|
| 1148 |
+
("filter_loading", "filter_roundtrip"),
|
| 1149 |
+
("filter_lifecycle", "filter_roundtrip"),
|
| 1150 |
+
("native_policy", "filter_roundtrip"),
|
| 1151 |
+
("qvm_format", "filter_roundtrip"),
|
| 1152 |
("native_policy", "filter_export"),
|
| 1153 |
("qvm_format", "filter_export"),
|
| 1154 |
("filter_lifecycle", "filter_remove"),
|
|
|
|
| 1252 |
("qvm-resolved-connect-complete", "resolved_connect_complete"),
|
| 1253 |
("qvm-filter-insert", "filter_insert"),
|
| 1254 |
("qvm-filter-export", "filter_export"),
|
| 1255 |
+
("qvm-filter-time", "filter_time"),
|
| 1256 |
+
("qvm-filter-expiry", "filter_expiry"),
|
| 1257 |
+
("qvm-filter-load", "filter_load"),
|
| 1258 |
+
("qvm-filter-duration", "filter_duration"),
|
| 1259 |
+
("qvm-filter-roundtrip", "filter_roundtrip"),
|
| 1260 |
("qvm-filter-remove", "filter_remove"),
|
| 1261 |
("qvm-filter-metadata", "filter_metadata"),
|
| 1262 |
("qvm-filter-insert-export", "filter_insert_export"),
|