gameplay: port session initialization ownership
Browse files- crates/urt-gameplay/src/bin/urt-native-policy.rs +41 -0
- crates/urt-gameplay/src/native_policy.rs +166 -0
- docs/FINDINGS.md +3 -0
- docs/PROVISIONAL_TODO.md +3 -0
- docs/RESEARCH_LEDGER.md +5 -0
- docs/REVERSE_ENGINEERING_TODO.md +3 -0
- docs/research/README.md +3 -0
- docs/research/RUST_SESSION_INIT.md +7 -0
- docs/research/rust-health-impulse.json +1 -1
- docs/research/rust-session-init.json +0 -0
- scripts/analyze_rust_session_init.py +15 -0
- scripts/test_rust_session_init.py +9 -0
- xtask/checks.tsv +15 -0
crates/urt-gameplay/src/bin/urt-native-policy.rs
CHANGED
|
@@ -507,6 +507,47 @@ fn run() -> Result<String, String> {
|
|
| 507 |
.unwrap_or("null".into())
|
| 508 |
))
|
| 509 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 510 |
_ => Err("unknown command".into()),
|
| 511 |
}
|
| 512 |
}
|
|
|
|
| 507 |
.unwrap_or("null".into())
|
| 508 |
))
|
| 509 |
}
|
| 510 |
+
"session-init" => {
|
| 511 |
+
if w.len() < 9 {
|
| 512 |
+
return Err("missing init header".into());
|
| 513 |
+
}
|
| 514 |
+
let mut p = 9;
|
| 515 |
+
let info = input_blob(&w, &mut p)?.ok_or("null info")?;
|
| 516 |
+
let mut raw = input_blob(&w, &mut p)?.ok_or("null raw")?;
|
| 517 |
+
if p != w.len() {
|
| 518 |
+
return Err("trailing init words".into());
|
| 519 |
+
}
|
| 520 |
+
let mut selector = 0;
|
| 521 |
+
let out = initialize_session(
|
| 522 |
+
&mut raw,
|
| 523 |
+
InitializeInput {
|
| 524 |
+
enabled: 1,
|
| 525 |
+
mapname: b"ut4_test",
|
| 526 |
+
file_length: 11,
|
| 527 |
+
file_data: b"9,8,7,6,5,4",
|
| 528 |
+
mode: w[0] as i32,
|
| 529 |
+
slot: w[1] as usize,
|
| 530 |
+
limit: w[2] as i32,
|
| 531 |
+
occupancy: w[3] as i32,
|
| 532 |
+
seconds: w[4] as i32,
|
| 533 |
+
clock: w[5] as i32,
|
| 534 |
+
ticks: w[6],
|
| 535 |
+
handle: w[7],
|
| 536 |
+
client_id: w[8],
|
| 537 |
+
userinfo: &info,
|
| 538 |
+
},
|
| 539 |
+
&mut selector,
|
| 540 |
+
)
|
| 541 |
+
.map_err(|e| format!("{e:?}"))?;
|
| 542 |
+
Ok(format!(
|
| 543 |
+
"{{\"raw\":\"{}\",\"sets\":{},\"ring\":{},\"info_ring\":{selector},\"diagnostics\":[{}],\"load_events\":{}}}",
|
| 544 |
+
hex(&raw),
|
| 545 |
+
sets_json(&out.session.sets),
|
| 546 |
+
out.ring_advance,
|
| 547 |
+
list(&out.diagnostic),
|
| 548 |
+
position_events(&out.load.io.events)
|
| 549 |
+
))
|
| 550 |
+
}
|
| 551 |
_ => Err("unknown command".into()),
|
| 552 |
}
|
| 553 |
}
|
crates/urt-gameplay/src/native_policy.rs
CHANGED
|
@@ -1332,3 +1332,169 @@ mod restore_tail_tests {
|
|
| 1332 |
assert_eq!(out.words[5], 6f32.to_bits());
|
| 1333 |
}
|
| 1334 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1332 |
assert_eq!(out.words[5], 6f32.to_bits());
|
| 1333 |
}
|
| 1334 |
}
|
| 1335 |
+
|
| 1336 |
+
pub const SESSION_BYTES: usize = 944;
|
| 1337 |
+
fn raw_word(raw: &[u8], offset: usize) -> u32 {
|
| 1338 |
+
u32::from_le_bytes(raw[offset..offset + 4].try_into().unwrap())
|
| 1339 |
+
}
|
| 1340 |
+
fn raw_store(raw: &mut [u8], offset: usize, value: u32) {
|
| 1341 |
+
raw[offset..offset + 4].copy_from_slice(&value.to_le_bytes());
|
| 1342 |
+
}
|
| 1343 |
+
pub struct InitializeInput<'a> {
|
| 1344 |
+
pub mode: i32,
|
| 1345 |
+
pub slot: usize,
|
| 1346 |
+
pub userinfo: &'a [u8],
|
| 1347 |
+
pub limit: i32,
|
| 1348 |
+
pub occupancy: i32,
|
| 1349 |
+
pub seconds: i32,
|
| 1350 |
+
pub clock: i32,
|
| 1351 |
+
pub ticks: u32,
|
| 1352 |
+
pub handle: u32,
|
| 1353 |
+
pub client_id: u32,
|
| 1354 |
+
pub enabled: i32,
|
| 1355 |
+
pub mapname: &'a [u8],
|
| 1356 |
+
pub file_length: i32,
|
| 1357 |
+
pub file_data: &'a [u8],
|
| 1358 |
+
}
|
| 1359 |
+
#[derive(Clone, Debug, PartialEq, Eq)]
|
| 1360 |
+
pub struct InitializedSession {
|
| 1361 |
+
pub load: PositionLoad,
|
| 1362 |
+
pub session: SessionWrite,
|
| 1363 |
+
pub diagnostic: [u32; 3],
|
| 1364 |
+
pub ring_advance: u32,
|
| 1365 |
+
}
|
| 1366 |
+
/// Original247520 with explicit raw-field ownership. Byte clears preserve the
|
| 1367 |
+
/// other three bytes; only successful position load replaces saved coordinates.
|
| 1368 |
+
pub fn initialize_session(
|
| 1369 |
+
raw: &mut [u8],
|
| 1370 |
+
input: InitializeInput<'_>,
|
| 1371 |
+
info_ring: &mut u32,
|
| 1372 |
+
) -> Result<InitializedSession, Error> {
|
| 1373 |
+
if raw.len() != SESSION_BYTES || input.slot >= 64 {
|
| 1374 |
+
return Err(Error::InvalidCount);
|
| 1375 |
+
}
|
| 1376 |
+
let mut bytes = raw.to_vec();
|
| 1377 |
+
let mut selector = *info_ring;
|
| 1378 |
+
let team = if crate::intermission::team_mode(input.mode) {
|
| 1379 |
+
let old = raw_word(&bytes, 0);
|
| 1380 |
+
if old == 0 { 3 } else { old }
|
| 1381 |
+
} else {
|
| 1382 |
+
let t = info_lookup(Some(input.userinfo), Some(b"team"), &mut selector)?;
|
| 1383 |
+
if t.value.first() == Some(&b's') || input.limit > 0 && input.occupancy >= input.limit {
|
| 1384 |
+
3
|
| 1385 |
+
} else {
|
| 1386 |
+
0
|
| 1387 |
+
}
|
| 1388 |
+
};
|
| 1389 |
+
raw_store(&mut bytes, 0, team);
|
| 1390 |
+
raw_store(&mut bytes, 8, input.clock as u32);
|
| 1391 |
+
raw_store(&mut bytes, 12, 1);
|
| 1392 |
+
let timeout = if input.seconds != 0 {
|
| 1393 |
+
input.seconds.wrapping_mul(1000)
|
| 1394 |
+
} else {
|
| 1395 |
+
60000
|
| 1396 |
+
};
|
| 1397 |
+
raw_store(&mut bytes, 44, input.clock.wrapping_add(timeout) as u32);
|
| 1398 |
+
for offset in [48, 52, 56, 64, 104, 492, 592, 612, 616, 644] {
|
| 1399 |
+
raw_store(&mut bytes, offset, 0);
|
| 1400 |
+
}
|
| 1401 |
+
raw_store(&mut bytes, 60, input.ticks);
|
| 1402 |
+
bytes[68..104].fill(0);
|
| 1403 |
+
bytes[68] = b' ';
|
| 1404 |
+
for offset in [108, 236, 496, 528, 560] {
|
| 1405 |
+
bytes[offset] = 0;
|
| 1406 |
+
}
|
| 1407 |
+
bytes[684..940].fill(0);
|
| 1408 |
+
let values = std::array::from_fn(|j| raw_word(&bytes, 620 + 4 * j));
|
| 1409 |
+
let loaded = load_position(
|
| 1410 |
+
PositionInput {
|
| 1411 |
+
mode: input.mode,
|
| 1412 |
+
enabled: input.enabled,
|
| 1413 |
+
slot: input.slot,
|
| 1414 |
+
userinfo: input.userinfo,
|
| 1415 |
+
mapname: input.mapname,
|
| 1416 |
+
name: b"",
|
| 1417 |
+
values,
|
| 1418 |
+
handle: input.handle,
|
| 1419 |
+
},
|
| 1420 |
+
input.file_length,
|
| 1421 |
+
input.file_data,
|
| 1422 |
+
&mut selector,
|
| 1423 |
+
)?;
|
| 1424 |
+
for (j, v) in loaded.values.iter().enumerate() {
|
| 1425 |
+
raw_store(&mut bytes, 620 + 4 * j, *v);
|
| 1426 |
+
}
|
| 1427 |
+
let fields = [0, 60, 48, 44, 52, 56, 612, 616, 644].map(|o| raw_word(&bytes, o) as i32);
|
| 1428 |
+
let session = session_write(input.slot, 0, fields, &[], &[0; 64])?;
|
| 1429 |
+
let ring_advance = session.ring_advance + loaded.io.ring_advance;
|
| 1430 |
+
raw.copy_from_slice(&bytes);
|
| 1431 |
+
*info_ring = selector;
|
| 1432 |
+
Ok(InitializedSession {
|
| 1433 |
+
load: loaded,
|
| 1434 |
+
session,
|
| 1435 |
+
diagnostic: [83576, input.client_id, input.ticks],
|
| 1436 |
+
ring_advance,
|
| 1437 |
+
})
|
| 1438 |
+
}
|
| 1439 |
+
#[cfg(test)]
|
| 1440 |
+
mod init_tests {
|
| 1441 |
+
use super::*;
|
| 1442 |
+
#[test]
|
| 1443 |
+
fn byte_clear_preserves_neighbor_bytes() {
|
| 1444 |
+
let mut raw = vec![0xdd; SESSION_BYTES];
|
| 1445 |
+
let mut ring = 0;
|
| 1446 |
+
let out = initialize_session(
|
| 1447 |
+
&mut raw,
|
| 1448 |
+
InitializeInput {
|
| 1449 |
+
enabled: 1,
|
| 1450 |
+
mapname: b"ut4_test",
|
| 1451 |
+
file_length: 11,
|
| 1452 |
+
file_data: b"9,8,7,6,5,4",
|
| 1453 |
+
mode: 3,
|
| 1454 |
+
slot: 0,
|
| 1455 |
+
userinfo: b"",
|
| 1456 |
+
limit: 0,
|
| 1457 |
+
occupancy: 0,
|
| 1458 |
+
seconds: 0,
|
| 1459 |
+
clock: 7,
|
| 1460 |
+
ticks: 9,
|
| 1461 |
+
handle: 0,
|
| 1462 |
+
client_id: 2,
|
| 1463 |
+
},
|
| 1464 |
+
&mut ring,
|
| 1465 |
+
)
|
| 1466 |
+
.unwrap();
|
| 1467 |
+
assert_eq!(&raw[108..112], &[0, 0xdd, 0xdd, 0xdd]);
|
| 1468 |
+
assert_eq!(raw_word(&raw, 44), 60007);
|
| 1469 |
+
assert_eq!(out.session.sets[1].1, b"");
|
| 1470 |
+
}
|
| 1471 |
+
#[test]
|
| 1472 |
+
fn bad_raw_domain_does_not_change_selector() {
|
| 1473 |
+
let mut raw = [];
|
| 1474 |
+
let mut ring = 1;
|
| 1475 |
+
assert_eq!(
|
| 1476 |
+
initialize_session(
|
| 1477 |
+
&mut raw,
|
| 1478 |
+
InitializeInput {
|
| 1479 |
+
enabled: 1,
|
| 1480 |
+
mapname: b"ut4_test",
|
| 1481 |
+
file_length: 11,
|
| 1482 |
+
file_data: b"9,8,7,6,5,4",
|
| 1483 |
+
mode: 0,
|
| 1484 |
+
slot: 0,
|
| 1485 |
+
userinfo: b"",
|
| 1486 |
+
limit: 0,
|
| 1487 |
+
occupancy: 0,
|
| 1488 |
+
seconds: 0,
|
| 1489 |
+
clock: 0,
|
| 1490 |
+
ticks: 0,
|
| 1491 |
+
handle: 0,
|
| 1492 |
+
client_id: 0
|
| 1493 |
+
},
|
| 1494 |
+
&mut ring
|
| 1495 |
+
),
|
| 1496 |
+
Err(Error::InvalidCount)
|
| 1497 |
+
);
|
| 1498 |
+
assert_eq!(ring, 1);
|
| 1499 |
+
}
|
| 1500 |
+
}
|
docs/FINDINGS.md
CHANGED
|
@@ -1712,3 +1712,6 @@ RE-813–822 replaces the scoreboard decimal assumption with actual37914 executi
|
|
| 1712 |
|
| 1713 |
|
| 1714 |
**RE-904:** 96 actual247520 compositions execute team classification, userinfo lookup, bounded copy, saved-position load and session serialization. Team/default/capacity policy, wrapping timeout arithmetic, native tick snapshot, byte-only versus word clears,36-byte text initialization and64 ignored-client clears are recovered. Existing position fields persist unless the recovered load succeeds. Diagnostic7259 and engine/file operations remain captured/supplied; caller authentication and post-initialization behavior remain open. [Evidence](research/QVM_SESSION_INIT.md).
|
|
|
|
|
|
|
|
|
|
|
|
| 1712 |
|
| 1713 |
|
| 1714 |
**RE-904:** 96 actual247520 compositions execute team classification, userinfo lookup, bounded copy, saved-position load and session serialization. Team/default/capacity policy, wrapping timeout arithmetic, native tick snapshot, byte-only versus word clears,36-byte text initialization and64 ignored-client clears are recovered. Existing position fields persist unless the recovered load succeeds. Diagnostic7259 and engine/file operations remain captured/supplied; caller authentication and post-initialization behavior remain open. [Evidence](research/QVM_SESSION_INIT.md).
|
| 1715 |
+
|
| 1716 |
+
|
| 1717 |
+
**RE-905:** Rust matches96 original247520 initialization/load/write cases, preserving raw byte/word clears, timeout wrapping, team/capacity selection,64 ignore clears and immediate session cvar bytes. Existing coordinates survive failed/suppressed loads. Engine clock/userinfo/files and diagnostic logging remain supplied/intended; caller behavior and native lifecycle remain open. [Evidence](research/RUST_SESSION_INIT.md).
|
docs/PROVISIONAL_TODO.md
CHANGED
|
@@ -1749,3 +1749,6 @@ RE-894–903 completed bounded userinfo/scanner/saved-file/session-restore sourc
|
|
| 1749 |
|
| 1750 |
|
| 1751 |
RE-904: 96 actual247520 compositions execute team classification, userinfo lookup, bounded copy, saved-position load and session serialization. Team/default/capacity policy, wrapping timeout arithmetic, native tick snapshot, byte-only versus word clears,36-byte text initialization and64 ignored-client clears are recovered. Existing position fields persist unless the recovered load succeeds. Diagnostic7259 and engine/file operations remain captured/supplied; caller authentication and post-initialization behavior remain open. Full runtime completion remains open. [Evidence](research/QVM_SESSION_INIT.md).
|
|
|
|
|
|
|
|
|
|
|
|
| 1749 |
|
| 1750 |
|
| 1751 |
RE-904: 96 actual247520 compositions execute team classification, userinfo lookup, bounded copy, saved-position load and session serialization. Team/default/capacity policy, wrapping timeout arithmetic, native tick snapshot, byte-only versus word clears,36-byte text initialization and64 ignored-client clears are recovered. Existing position fields persist unless the recovered load succeeds. Diagnostic7259 and engine/file operations remain captured/supplied; caller authentication and post-initialization behavior remain open. Full runtime completion remains open. [Evidence](research/QVM_SESSION_INIT.md).
|
| 1752 |
+
|
| 1753 |
+
|
| 1754 |
+
RE-905: Rust matches96 original247520 initialization/load/write cases, preserving raw byte/word clears, timeout wrapping, team/capacity selection,64 ignore clears and immediate session cvar bytes. Existing coordinates survive failed/suppressed loads. Engine clock/userinfo/files and diagnostic logging remain supplied/intended; caller behavior and native lifecycle remain open. Full runtime completion remains open. [Evidence](research/RUST_SESSION_INIT.md).
|
docs/RESEARCH_LEDGER.md
CHANGED
|
@@ -2240,3 +2240,8 @@ After the tenth commit, `cargo xtask test-full --since 6e01995b` passed with the
|
|
| 2240 |
## 2026-10-28 — RE-904 Original session initialization and immediate persistence
|
| 2241 |
|
| 2242 |
96 actual247520 compositions execute team classification, userinfo lookup, bounded copy, saved-position load and session serialization. Team/default/capacity policy, wrapping timeout arithmetic, native tick snapshot, byte-only versus word clears,36-byte text initialization and64 ignored-client clears are recovered. Existing position fields persist unless the recovered load succeeds. Diagnostic7259 and engine/file operations remain captured/supplied; caller authentication and post-initialization behavior remain open. Focused `cargo xtask test-group qvm-session-init` passes (4 Python tests); selected reports regenerate twice deterministically, with storage, documentation links and whitespace guards. Full suite deferred to task ten. Original assets unchanged; source fixtures do not establish complete native/runtime parity.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2240 |
## 2026-10-28 — RE-904 Original session initialization and immediate persistence
|
| 2241 |
|
| 2242 |
96 actual247520 compositions execute team classification, userinfo lookup, bounded copy, saved-position load and session serialization. Team/default/capacity policy, wrapping timeout arithmetic, native tick snapshot, byte-only versus word clears,36-byte text initialization and64 ignored-client clears are recovered. Existing position fields persist unless the recovered load succeeds. Diagnostic7259 and engine/file operations remain captured/supplied; caller authentication and post-initialization behavior remain open. Focused `cargo xtask test-group qvm-session-init` passes (4 Python tests); selected reports regenerate twice deterministically, with storage, documentation links and whitespace guards. Full suite deferred to task ten. Original assets unchanged; source fixtures do not establish complete native/runtime parity.
|
| 2243 |
+
|
| 2244 |
+
|
| 2245 |
+
## 2026-10-28 — RE-905 Rust session initialization and raw-field ownership
|
| 2246 |
+
|
| 2247 |
+
Rust matches96 original247520 initialization/load/write cases, preserving raw byte/word clears, timeout wrapping, team/capacity selection,64 ignore clears and immediate session cvar bytes. Existing coordinates survive failed/suppressed loads. Engine clock/userinfo/files and diagnostic logging remain supplied/intended; caller behavior and native lifecycle remain open. Focused `cargo xtask test-group rust-session-init` passes (9 Python tests); selected reports regenerate twice deterministically, with storage, documentation links and whitespace guards. Full suite deferred to task ten. Original assets unchanged; source fixtures do not establish complete native/runtime parity.
|
docs/REVERSE_ENGINEERING_TODO.md
CHANGED
|
@@ -1786,3 +1786,6 @@ Purpose: turn the supplied installation into an evidence-backed specification of
|
|
| 1786 |
|
| 1787 |
|
| 1788 |
- [x] RE-904 Original session initialization and immediate persistence ([evidence](research/QVM_SESSION_INIT.md)).
|
|
|
|
|
|
|
|
|
|
|
|
| 1786 |
|
| 1787 |
|
| 1788 |
- [x] RE-904 Original session initialization and immediate persistence ([evidence](research/QVM_SESSION_INIT.md)).
|
| 1789 |
+
|
| 1790 |
+
|
| 1791 |
+
- [x] RE-905 Rust session initialization and raw-field ownership ([evidence](research/RUST_SESSION_INIT.md)).
|
docs/research/README.md
CHANGED
|
@@ -1321,3 +1321,6 @@ The extension collector adds five focused tests for native tail calls, command-r
|
|
| 1321 |
|
| 1322 |
|
| 1323 |
[RE-904: Original session initialization and immediate persistence](QVM_SESSION_INIT.md).
|
|
|
|
|
|
|
|
|
|
|
|
| 1321 |
|
| 1322 |
|
| 1323 |
[RE-904: Original session initialization and immediate persistence](QVM_SESSION_INIT.md).
|
| 1324 |
+
|
| 1325 |
+
|
| 1326 |
+
[RE-905: Rust session initialization and raw-field ownership](RUST_SESSION_INIT.md).
|
docs/research/RUST_SESSION_INIT.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Rust session initialization and raw-field ownership
|
| 2 |
+
|
| 3 |
+
RE-905. Reproduce with `python3 scripts/analyze_rust_session_init.py`; focused validation: `cargo xtask test-group rust-session-init`. [Machine report](rust-session-init.json).
|
| 4 |
+
|
| 5 |
+
Rust matches96 original247520 initialization/load/write cases, preserving raw byte/word clears, timeout wrapping, team/capacity selection,64 ignore clears and immediate session cvar bytes. Existing coordinates survive failed/suppressed loads. Engine clock/userinfo/files and diagnostic logging remain supplied/intended; caller behavior and native lifecycle remain open.
|
| 6 |
+
|
| 7 |
+
Original executable/native runtime and complete Linux/macOS Rust/Bevy/Solari acceptance remain unverified.
|
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": 161,
|
| 2989 |
"source_report": "docs/research/qvm-health-impulse.json",
|
| 2990 |
"source_report_sha256": "625fd8064004ea6dbdf398d51d0af844d9c635ff04c0a0790886dddb6ab81e71"
|
| 2991 |
}
|
docs/research/rust-session-init.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
scripts/analyze_rust_session_init.py
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
import hashlib,json
|
| 3 |
+
from pathlib import Path
|
| 4 |
+
from rust_native_policy_support import binary,result,invoke
|
| 5 |
+
from analyze_qvm import write_json
|
| 6 |
+
def blob(s):return [len(bytes.fromhex(s)),*bytes.fromhex(s)]
|
| 7 |
+
def encode(s):
|
| 8 |
+
a=s['input'];return [a['mode'],a['slot'],a['limit'],a['occupancy'],a['seconds'],a['now'],a['ticks'],a['handle'],17+a['slot'],*blob(a['info']),*blob(a['before'])]
|
| 9 |
+
def project(s):return {k:s[k] for k in ['raw','ring','info_ring','diagnostics']}|{'sets':s['parts']['session']['sets'],'load_events':s['parts']['load']['events']}
|
| 10 |
+
|
| 11 |
+
def main():
|
| 12 |
+
b=binary();p=Path('docs/research/qvm-session-init.json');data=p.read_bytes();rows=[]
|
| 13 |
+
for s in json.loads(data)['probes']:rows.append({'source':project(s),'rust':result(b,'session-init',encode(s))})
|
| 14 |
+
write_json(Path('docs/research/rust-session-init.json'),{'source_report':str(p),'source_report_sha256':hashlib.sha256(data).hexdigest(),'probes':rows,'limits':'Rust matches96 original247520 initialization/load/write cases, preserving raw byte/word clears, timeout wrapping, team/capacity selection,64 ignore clears and immediate session cvar bytes. Existing coordinates survive failed/suppressed loads. Engine clock/userinfo/files and diagnostic logging remain supplied/intended; caller behavior and native lifecycle remain open.'})
|
| 15 |
+
if __name__=='__main__':main()
|
scripts/test_rust_session_init.py
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import hashlib,json,unittest
|
| 2 |
+
from pathlib import Path
|
| 3 |
+
class PortTests(unittest.TestCase):
|
| 4 |
+
def test_all_original_cases(self):
|
| 5 |
+
r=json.loads(Path('docs/research/rust-session-init.json').read_text());src=json.loads(Path(r['source_report']).read_text());self.assertEqual(len(r['probes']),len(src['probes']));self.assertGreater(len(r['probes']),20)
|
| 6 |
+
for p in r['probes']:self.assertEqual(p['rust'],p['source'])
|
| 7 |
+
def test_source_identity(self):
|
| 8 |
+
r=json.loads(Path('docs/research/rust-session-init.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
|
@@ -2807,3 +2807,18 @@ report scripts/analyze_qvm_session_init.py docs/research/qvm-session-init.json
|
|
| 2807 |
edge docs/research/qvm-session-init.json scripts/test_qvm_session_init.py
|
| 2808 |
group qvm-session-init scripts/analyze_qvm_session_init.py
|
| 2809 |
edge scripts/analyze_qvm_session_init.py scripts/analyze_qvm_resumer_audit.py
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2807 |
edge docs/research/qvm-session-init.json scripts/test_qvm_session_init.py
|
| 2808 |
group qvm-session-init scripts/analyze_qvm_session_init.py
|
| 2809 |
edge scripts/analyze_qvm_session_init.py scripts/analyze_qvm_resumer_audit.py
|
| 2810 |
+
edge Cargo.toml scripts/analyze_rust_session_init.py
|
| 2811 |
+
edge Cargo.lock scripts/analyze_rust_session_init.py
|
| 2812 |
+
edge crates/urt-gameplay/Cargo.toml scripts/analyze_rust_session_init.py
|
| 2813 |
+
edge crates/urt-gameplay/src/lib.rs scripts/analyze_rust_session_init.py
|
| 2814 |
+
edge crates/urt-gameplay/src/native_policy.rs scripts/analyze_rust_session_init.py
|
| 2815 |
+
edge crates/urt-gameplay/src/bin/urt-native-policy.rs scripts/analyze_rust_session_init.py
|
| 2816 |
+
edge docs/research/qvm-session-init.json scripts/analyze_rust_session_init.py
|
| 2817 |
+
group rust-session-init scripts/analyze_rust_health_impulse.py
|
| 2818 |
+
group gameplay scripts/analyze_rust_session_init.py
|
| 2819 |
+
edge crates/urt-gameplay/src/intermission.rs scripts/analyze_rust_session_init.py
|
| 2820 |
+
edge crates/urt-gameplay/src/qvm_format.rs scripts/analyze_rust_session_init.py
|
| 2821 |
+
report scripts/analyze_rust_session_init.py docs/research/rust-session-init.json
|
| 2822 |
+
edge docs/research/rust-session-init.json scripts/test_rust_session_init.py
|
| 2823 |
+
group rust-session-init scripts/analyze_rust_session_init.py
|
| 2824 |
+
edge scripts/analyze_rust_session_init.py scripts/analyze_qvm_resumer_audit.py
|