gameplay: port temporary event construction
Browse files- crates/urt-gameplay/src/bin/urt-transition.rs +56 -0
- crates/urt-gameplay/src/transition.rs +126 -0
- docs/FINDINGS.md +3 -0
- docs/PROVISIONAL_TODO.md +7 -1
- docs/RESEARCH_LEDGER.md +9 -0
- docs/REVERSE_ENGINEERING_TODO.md +7 -1
- docs/TESTING.md +5 -0
- docs/research/QVM_CAMERA_MAP_EVENT_BATCH.md +44 -0
- docs/research/README.md +5 -0
- docs/research/RUST_EVENT_CONSTRUCT.md +7 -0
- docs/research/rust-event-construct.json +0 -0
- docs/research/rust-health-impulse.json +1 -1
- scripts/analyze_rust_event_construct.py +16 -0
- scripts/test_rust_event_construct.py +11 -0
- xtask/checks.tsv +13 -0
- xtask/src/lib.rs +7 -0
crates/urt-gameplay/src/bin/urt-transition.rs
CHANGED
|
@@ -176,6 +176,62 @@ fn run() -> Result<String, String> {
|
|
| 176 |
map_clients_json(&c)
|
| 177 |
))
|
| 178 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 179 |
_ => Err("unknown command".into()),
|
| 180 |
}
|
| 181 |
}
|
|
|
|
| 176 |
map_clients_json(&c)
|
| 177 |
))
|
| 178 |
}
|
| 179 |
+
"event" => {
|
| 180 |
+
if w.len() != 6 {
|
| 181 |
+
return Err("invalid event input".into());
|
| 182 |
+
}
|
| 183 |
+
let init = 0x13579bdf;
|
| 184 |
+
let mut e = EventRecord {
|
| 185 |
+
kind: init,
|
| 186 |
+
trajectory: [init; 3],
|
| 187 |
+
origin: [init; 3],
|
| 188 |
+
velocity: [init; 3],
|
| 189 |
+
caller_time: init,
|
| 190 |
+
owner: init,
|
| 191 |
+
field400: init,
|
| 192 |
+
flags: w[5],
|
| 193 |
+
current_origin: [init; 3],
|
| 194 |
+
class_token: init,
|
| 195 |
+
class_hash: init,
|
| 196 |
+
event_time: init as i32,
|
| 197 |
+
free_after_event: init,
|
| 198 |
+
};
|
| 199 |
+
let link = temporary_event(&mut e, w[..3].try_into().unwrap(), w[3], w[4] as i32)
|
| 200 |
+
.map_err(|e| format!("{e:?}"))?;
|
| 201 |
+
let f = object(
|
| 202 |
+
&[
|
| 203 |
+
4, 12, 16, 20, 24, 28, 32, 36, 40, 44, 84, 140, 400, 424, 488, 492, 496, 536,
|
| 204 |
+
540, 568, 572,
|
| 205 |
+
],
|
| 206 |
+
&[
|
| 207 |
+
e.kind,
|
| 208 |
+
e.trajectory[0],
|
| 209 |
+
e.trajectory[1],
|
| 210 |
+
e.trajectory[2],
|
| 211 |
+
e.origin[0],
|
| 212 |
+
e.origin[1],
|
| 213 |
+
e.origin[2],
|
| 214 |
+
e.velocity[0],
|
| 215 |
+
e.velocity[1],
|
| 216 |
+
e.velocity[2],
|
| 217 |
+
e.caller_time,
|
| 218 |
+
e.owner,
|
| 219 |
+
e.field400,
|
| 220 |
+
e.flags,
|
| 221 |
+
e.current_origin[0],
|
| 222 |
+
e.current_origin[1],
|
| 223 |
+
e.current_origin[2],
|
| 224 |
+
e.class_token,
|
| 225 |
+
e.class_hash,
|
| 226 |
+
e.event_time as u32,
|
| 227 |
+
e.free_after_event,
|
| 228 |
+
],
|
| 229 |
+
);
|
| 230 |
+
Ok(format!(
|
| 231 |
+
"{{\"fields\":{f},\"link\":{}}}",
|
| 232 |
+
link == EventIntent::Link
|
| 233 |
+
))
|
| 234 |
+
}
|
| 235 |
_ => Err("unknown command".into()),
|
| 236 |
}
|
| 237 |
}
|
crates/urt-gameplay/src/transition.rs
CHANGED
|
@@ -371,3 +371,129 @@ mod normal_tests {
|
|
| 371 |
assert_eq!(mark_connecting(&mut c, 1), Err(Error::InvalidCount));
|
| 372 |
}
|
| 373 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 371 |
assert_eq!(mark_connecting(&mut c, 1), Err(Error::InvalidCount));
|
| 372 |
}
|
| 373 |
}
|
| 374 |
+
|
| 375 |
+
/// Word-level source record. Class token97191 identifies the original tempEntity
|
| 376 |
+
/// string; runtime code must resolve metadata rather than use it as a native pointer.
|
| 377 |
+
#[derive(Clone, Debug, PartialEq, Eq)]
|
| 378 |
+
pub struct EventRecord {
|
| 379 |
+
pub kind: u32,
|
| 380 |
+
pub trajectory: [u32; 3],
|
| 381 |
+
pub origin: [u32; 3],
|
| 382 |
+
pub velocity: [u32; 3],
|
| 383 |
+
pub caller_time: u32,
|
| 384 |
+
pub owner: u32,
|
| 385 |
+
pub field400: u32,
|
| 386 |
+
pub flags: u32,
|
| 387 |
+
pub current_origin: [u32; 3],
|
| 388 |
+
pub class_token: u32,
|
| 389 |
+
pub class_hash: u32,
|
| 390 |
+
pub event_time: i32,
|
| 391 |
+
pub free_after_event: u32,
|
| 392 |
+
}
|
| 393 |
+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
| 394 |
+
pub enum EventIntent {
|
| 395 |
+
Link,
|
| 396 |
+
}
|
| 397 |
+
pub fn temporary_event(
|
| 398 |
+
record: &mut EventRecord,
|
| 399 |
+
origin: [u32; 3],
|
| 400 |
+
kind: u32,
|
| 401 |
+
now: i32,
|
| 402 |
+
) -> Result<EventIntent, Error> {
|
| 403 |
+
let mut snap = [0; 3];
|
| 404 |
+
for j in 0..3 {
|
| 405 |
+
let x = f32::from_bits(origin[j]);
|
| 406 |
+
if !x.is_finite() || !(-2147483648.0..2147483648.0).contains(&x) {
|
| 407 |
+
return Err(Error::FloatDomain);
|
| 408 |
+
}
|
| 409 |
+
snap[j] = ((x as i32) as f32).to_bits();
|
| 410 |
+
}
|
| 411 |
+
record.kind = kind.wrapping_add(19);
|
| 412 |
+
record.class_token = 97191;
|
| 413 |
+
record.class_hash = 662184166;
|
| 414 |
+
record.event_time = now;
|
| 415 |
+
record.free_after_event = 1;
|
| 416 |
+
record.origin = snap;
|
| 417 |
+
record.current_origin = snap;
|
| 418 |
+
record.trajectory = [0; 3];
|
| 419 |
+
record.velocity = [0; 3];
|
| 420 |
+
Ok(EventIntent::Link)
|
| 421 |
+
}
|
| 422 |
+
#[cfg(test)]
|
| 423 |
+
mod event_tests {
|
| 424 |
+
use super::*;
|
| 425 |
+
fn allocated() -> EventRecord {
|
| 426 |
+
EventRecord {
|
| 427 |
+
kind: 7,
|
| 428 |
+
trajectory: [7; 3],
|
| 429 |
+
origin: [7; 3],
|
| 430 |
+
velocity: [7; 3],
|
| 431 |
+
caller_time: 42,
|
| 432 |
+
owner: 99,
|
| 433 |
+
field400: 13,
|
| 434 |
+
flags: 16,
|
| 435 |
+
current_origin: [7; 3],
|
| 436 |
+
class_token: 7,
|
| 437 |
+
class_hash: 7,
|
| 438 |
+
event_time: 7,
|
| 439 |
+
free_after_event: 7,
|
| 440 |
+
}
|
| 441 |
+
}
|
| 442 |
+
#[test]
|
| 443 |
+
fn snapped_origin_preserves_allocator_and_caller_fields() {
|
| 444 |
+
let mut e = allocated();
|
| 445 |
+
assert_eq!(
|
| 446 |
+
temporary_event(
|
| 447 |
+
&mut e,
|
| 448 |
+
[1.9f32.to_bits(), (-1.9f32).to_bits(), (-0.0f32).to_bits()],
|
| 449 |
+
u32::MAX,
|
| 450 |
+
i32::MIN
|
| 451 |
+
),
|
| 452 |
+
Ok(EventIntent::Link)
|
| 453 |
+
);
|
| 454 |
+
assert_eq!(e.kind, 18);
|
| 455 |
+
assert_eq!(e.origin, [1.0f32.to_bits(), (-1.0f32).to_bits(), 0]);
|
| 456 |
+
assert_eq!(e.current_origin, e.origin);
|
| 457 |
+
assert_eq!(
|
| 458 |
+
(e.flags, e.caller_time, e.owner, e.field400),
|
| 459 |
+
(16, 42, 99, 13)
|
| 460 |
+
);
|
| 461 |
+
assert_eq!(
|
| 462 |
+
(
|
| 463 |
+
e.class_token,
|
| 464 |
+
e.class_hash,
|
| 465 |
+
e.event_time,
|
| 466 |
+
e.free_after_event
|
| 467 |
+
),
|
| 468 |
+
(97191, 662184166, i32::MIN, 1)
|
| 469 |
+
);
|
| 470 |
+
}
|
| 471 |
+
#[test]
|
| 472 |
+
fn invalid_conversion_rejects_before_mutation() {
|
| 473 |
+
for v in [
|
| 474 |
+
f32::NAN,
|
| 475 |
+
f32::INFINITY,
|
| 476 |
+
f32::NEG_INFINITY,
|
| 477 |
+
2147483648.0,
|
| 478 |
+
-2147483904.0,
|
| 479 |
+
] {
|
| 480 |
+
let mut e = allocated();
|
| 481 |
+
let old = e.clone();
|
| 482 |
+
assert_eq!(
|
| 483 |
+
temporary_event(&mut e, [0, v.to_bits(), 0], 69, 1000),
|
| 484 |
+
Err(Error::FloatDomain)
|
| 485 |
+
);
|
| 486 |
+
assert_eq!(e, old);
|
| 487 |
+
}
|
| 488 |
+
let mut e = allocated();
|
| 489 |
+
assert!(
|
| 490 |
+
temporary_event(
|
| 491 |
+
&mut e,
|
| 492 |
+
[(-2147483648.0f32).to_bits(), 2147483520.0f32.to_bits(), 0],
|
| 493 |
+
69,
|
| 494 |
+
0
|
| 495 |
+
)
|
| 496 |
+
.is_ok()
|
| 497 |
+
);
|
| 498 |
+
}
|
| 499 |
+
}
|
docs/FINDINGS.md
CHANGED
|
@@ -1556,3 +1556,6 @@ RE-813–822 replaces the scoreboard decimal assumption with actual37914 executi
|
|
| 1556 |
|
| 1557 |
|
| 1558 |
**RE-852:** 144 original 277695/278138 cases recover tempEntity metadata, wrapped event kind+19, CVFI/CVIF origin snapping, trajectory/current-origin writes and link order. Five invalid float domains reject. Allocator flags424 and caller-owned84/140 are preserved; allocation277165 and native linking remain supplied/captured. [Evidence](research/QVM_EVENT_CONSTRUCT.md).
|
|
|
|
|
|
|
|
|
|
|
|
| 1556 |
|
| 1557 |
|
| 1558 |
**RE-852:** 144 original 277695/278138 cases recover tempEntity metadata, wrapped event kind+19, CVFI/CVIF origin snapping, trajectory/current-origin writes and link order. Five invalid float domains reject. Allocator flags424 and caller-owned84/140 are preserved; allocation277165 and native linking remain supplied/captured. [Evidence](research/QVM_EVENT_CONSTRUCT.md).
|
| 1559 |
+
|
| 1560 |
+
|
| 1561 |
+
**RE-853:** Rust matches 144 original temporary-event cases, including exact snap words, event-kind wrapping, metadata and preservation of allocator/caller fields. Five invalid source domains reject atomically in Rust. Allocation and native linking remain caller-owned; source class tokens require runtime metadata resolution. [Evidence](research/RUST_EVENT_CONSTRUCT.md).
|
docs/PROVISIONAL_TODO.md
CHANGED
|
@@ -1547,7 +1547,7 @@ RE-842: 150 continuous 7805 fixtures now execute actual tie, readiness, begin-tr
|
|
| 1547 |
RE-843: Rust composes recovered tie, readiness, begin and exit-log policies with prior exit timers/limits across150 continuous source fixtures. Atomic staged updates preserve shared pending/client state; reset and lower-level world/I/O effects remain explicit intentions. Source branch labels are independently classified by the tested composition oracle; captured requests and actual final source state supply effect parity. Full runtime completion remains open. [Evidence](research/RUST_INTERMISSION_FLOW.md).
|
| 1548 |
|
| 1549 |
|
| 1550 |
-
- [
|
| 1551 |
|
| 1552 |
|
| 1553 |
RE-844: 72 original 6575 fixtures recover entity/player origin and view-angle copies, velocity clear, movement type5 and cleared entity/client fields. Coherent byte copies preserve arbitrary float words, including NaN payloads; two entity-to-client targets prove indirection. Mode/field4324 gates converge without extra effects. Native renderer/camera integration remains open. Full runtime completion remains open. [Evidence](research/QVM_CAMERA_PLACE.md).
|
|
@@ -1575,3 +1575,9 @@ RE-851: Rust matches 48 original normal-reset cases with separate pre-map score
|
|
| 1575 |
|
| 1576 |
|
| 1577 |
RE-852: 144 original 277695/278138 cases recover tempEntity metadata, wrapped event kind+19, CVFI/CVIF origin snapping, trajectory/current-origin writes and link order. Five invalid float domains reject. Allocator flags424 and caller-owned84/140 are preserved; allocation277165 and native linking remain supplied/captured. Full runtime completion remains open. [Evidence](research/QVM_EVENT_CONSTRUCT.md).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1547 |
RE-843: Rust composes recovered tie, readiness, begin and exit-log policies with prior exit timers/limits across150 continuous source fixtures. Atomic staged updates preserve shared pending/client state; reset and lower-level world/I/O effects remain explicit intentions. Source branch labels are independently classified by the tested composition oracle; captured requests and actual final source state supply effect parity. Full runtime completion remains open. [Evidence](research/RUST_INTERMISSION_FLOW.md).
|
| 1548 |
|
| 1549 |
|
| 1550 |
+
- [x] RE-844–853: Recover bounded camera, map-reset and event-construction policies; deeper native/runtime work continues under RE-854. [Batch evidence](research/QVM_CAMERA_MAP_EVENT_BATCH.md).
|
| 1551 |
|
| 1552 |
|
| 1553 |
RE-844: 72 original 6575 fixtures recover entity/player origin and view-angle copies, velocity clear, movement type5 and cleared entity/client fields. Coherent byte copies preserve arbitrary float words, including NaN payloads; two entity-to-client targets prove indirection. Mode/field4324 gates converge without extra effects. Native renderer/camera integration remains open. Full runtime completion remains open. [Evidence](research/QVM_CAMERA_PLACE.md).
|
|
|
|
| 1575 |
|
| 1576 |
|
| 1577 |
RE-852: 144 original 277695/278138 cases recover tempEntity metadata, wrapped event kind+19, CVFI/CVIF origin snapping, trajectory/current-origin writes and link order. Five invalid float domains reject. Allocator flags424 and caller-owned84/140 are preserved; allocation277165 and native linking remain supplied/captured. Full runtime completion remains open. [Evidence](research/QVM_EVENT_CONSTRUCT.md).
|
| 1578 |
+
|
| 1579 |
+
|
| 1580 |
+
RE-853: Rust matches 144 original temporary-event cases, including exact snap words, event-kind wrapping, metadata and preservation of allocator/caller fields. Five invalid source domains reject atomically in Rust. Allocation and native linking remain caller-owned; source class tokens require runtime metadata resolution. Full runtime completion remains open. [Evidence](research/RUST_EVENT_CONSTRUCT.md).
|
| 1581 |
+
|
| 1582 |
+
|
| 1583 |
+
- [ ] RE-854: Compose recovered camera/map/event policies into intermission flows; recover searches, angles, commands, allocation, respawn and publication; validate actual macOS/Linux runtime traces. [Scope](research/QVM_CAMERA_MAP_EVENT_BATCH.md).
|
docs/RESEARCH_LEDGER.md
CHANGED
|
@@ -1938,3 +1938,12 @@ Rust matches 48 original normal-reset cases with separate pre-map score reset an
|
|
| 1938 |
## 2026-10-27 — RE-852 Original temporary event construction and origin snapping
|
| 1939 |
|
| 1940 |
144 original 277695/278138 cases recover tempEntity metadata, wrapped event kind+19, CVFI/CVIF origin snapping, trajectory/current-origin writes and link order. Five invalid float domains reject. Allocator flags424 and caller-owned84/140 are preserved; allocation277165 and native linking remain supplied/captured. Focused `cargo xtask test-group event-construct` passes (5 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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1938 |
## 2026-10-27 — RE-852 Original temporary event construction and origin snapping
|
| 1939 |
|
| 1940 |
144 original 277695/278138 cases recover tempEntity metadata, wrapped event kind+19, CVFI/CVIF origin snapping, trajectory/current-origin writes and link order. Five invalid float domains reject. Allocator flags424 and caller-owned84/140 are preserved; allocation277165 and native linking remain supplied/captured. Focused `cargo xtask test-group event-construct` passes (5 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.
|
| 1941 |
+
|
| 1942 |
+
|
| 1943 |
+
## 2026-10-27 — RE-853 Rust temporary event construction and ownership boundaries
|
| 1944 |
+
|
| 1945 |
+
Rust matches 144 original temporary-event cases, including exact snap words, event-kind wrapping, metadata and preservation of allocator/caller fields. Five invalid source domains reject atomically in Rust. Allocation and native linking remain caller-owned; source class tokens require runtime metadata resolution. Focused `cargo xtask test-group rust-event-construct` 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.
|
| 1946 |
+
|
| 1947 |
+
RE-853 final review: targeted xtask registry regression passes for all five source-report parity edges, transition module selection and the shared intermission mode-classifier dependency. Added batch evidence, validation cadence and RE-854 integration/native follow-ups.
|
| 1948 |
+
|
| 1949 |
+
Batch RE-844–853 boundary: the single `cargo xtask test-full --since 15d7fcac` run passed after commit ten: 1,668 Python tests, 147 Rust tests (assets 10, gameplay 109, xtask 28), 46 deterministic report producers, storage policy, 414 documentation files and whitespace checks. No generated report drift; validation notes amended into task ten. Original assets unchanged.
|
docs/REVERSE_ENGINEERING_TODO.md
CHANGED
|
@@ -1584,7 +1584,7 @@ Purpose: turn the supplied installation into an evidence-backed specification of
|
|
| 1584 |
- [x] RE-843 Rust composed exit and intermission state machine ([evidence](research/RUST_INTERMISSION_FLOW.md)).
|
| 1585 |
|
| 1586 |
|
| 1587 |
-
- [
|
| 1588 |
|
| 1589 |
|
| 1590 |
- [x] RE-844 Original intermission camera placement and client indirection ([evidence](research/QVM_CAMERA_PLACE.md)).
|
|
@@ -1612,3 +1612,9 @@ Purpose: turn the supplied installation into an evidence-backed specification of
|
|
| 1612 |
|
| 1613 |
|
| 1614 |
- [x] RE-852 Original temporary event construction and origin snapping ([evidence](research/QVM_EVENT_CONSTRUCT.md)).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1584 |
- [x] RE-843 Rust composed exit and intermission state machine ([evidence](research/RUST_INTERMISSION_FLOW.md)).
|
| 1585 |
|
| 1586 |
|
| 1587 |
+
- [x] RE-844–853: Recover bounded camera, map-reset and event-construction policies; deeper native/runtime work continues under RE-854. [Batch evidence](research/QVM_CAMERA_MAP_EVENT_BATCH.md).
|
| 1588 |
|
| 1589 |
|
| 1590 |
- [x] RE-844 Original intermission camera placement and client indirection ([evidence](research/QVM_CAMERA_PLACE.md)).
|
|
|
|
| 1612 |
|
| 1613 |
|
| 1614 |
- [x] RE-852 Original temporary event construction and origin snapping ([evidence](research/QVM_EVENT_CONSTRUCT.md)).
|
| 1615 |
+
|
| 1616 |
+
|
| 1617 |
+
- [x] RE-853 Rust temporary event construction and ownership boundaries ([evidence](research/RUST_EVENT_CONSTRUCT.md)).
|
| 1618 |
+
|
| 1619 |
+
|
| 1620 |
+
- [ ] RE-854: Compose recovered camera/map/event policies into intermission flows; recover searches, angles, commands, allocation, respawn and publication; validate actual macOS/Linux runtime traces. [Scope](research/QVM_CAMERA_MAP_EVENT_BATCH.md).
|
docs/TESTING.md
CHANGED
|
@@ -138,3 +138,8 @@ Use `cargo xtask test-group <name>` with `format-float`, `rust-format-float`, `e
|
|
| 138 |
## Exit predicate and intermission groups
|
| 139 |
|
| 140 |
Focused source/Rust pairs: `exit-predicate`/`rust-exit-predicate`, `intermission-ready`/`rust-intermission-ready`, `intermission-begin`/`rust-intermission-begin`, `exit-log`/`rust-exit-log`, and `intermission-flow`/`rust-intermission-flow`. Run `cargo xtask test-group <name>` before the task commit. The scoped intermission executable has its own adapter inputs; common module changes select every intermission consumer and scoped gameplay test-count metadata. The registry regression verifies source-report edges and module selection. Run one `test-full --since <batch-base>` after ten commits. See the [batch contracts and boundaries](research/QVM_INTERMISSION_BATCH.md).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 138 |
## Exit predicate and intermission groups
|
| 139 |
|
| 140 |
Focused source/Rust pairs: `exit-predicate`/`rust-exit-predicate`, `intermission-ready`/`rust-intermission-ready`, `intermission-begin`/`rust-intermission-begin`, `exit-log`/`rust-exit-log`, and `intermission-flow`/`rust-intermission-flow`. Run `cargo xtask test-group <name>` before the task commit. The scoped intermission executable has its own adapter inputs; common module changes select every intermission consumer and scoped gameplay test-count metadata. The registry regression verifies source-report edges and module selection. Run one `test-full --since <batch-base>` after ten commits. See the [batch contracts and boundaries](research/QVM_INTERMISSION_BATCH.md).
|
| 141 |
+
|
| 142 |
+
|
| 143 |
+
## Camera, map and event groups
|
| 144 |
+
|
| 145 |
+
Focused source/Rust pairs: `camera-place`/`rust-camera-place`, `camera-select`/`rust-camera-select`, `nextmap-series`/`rust-nextmap-series`, `nextmap-reset`/`rust-nextmap-reset`, and `event-construct`/`rust-event-construct`. Invoke `cargo xtask test-group <name>` before each task commit. The scoped transition adapter covers each word-level contract; Rust groups also run scoped gameplay tests and refresh their test-count metadata. The registry regression verifies source-report edges, transition module consumers and the shared mode-classifier dependency. Continue one full suite after ten commits. [Batch contracts and boundaries](research/QVM_CAMERA_MAP_EVENT_BATCH.md).
|
docs/research/QVM_CAMERA_MAP_EVENT_BATCH.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Camera, next-map and event construction: RE-844–853
|
| 2 |
+
|
| 3 |
+
Five original source contracts now have matching Rust ports. This batch recovers concrete world-record mutations and ordered intentions; complete runtime, renderer and native side-effect parity remain open.
|
| 4 |
+
|
| 5 |
+
| Task | Evidence |
|
| 6 |
+
| --- | --- |
|
| 7 |
+
| RE-844 | [6575 intermission camera placement](QVM_CAMERA_PLACE.md) |
|
| 8 |
+
| RE-845 | [Rust camera placement](RUST_CAMERA_PLACE.md) |
|
| 9 |
+
| RE-846 | [6717 camera selection and target direction](QVM_CAMERA_SELECT.md) |
|
| 10 |
+
| RE-847 | [Rust view selection](RUST_CAMERA_SELECT.md) |
|
| 11 |
+
| RE-848 | [6939 team-series branch](QVM_NEXTMAP_SERIES.md) |
|
| 12 |
+
| RE-849 | [Rust series policy](RUST_NEXTMAP_SERIES.md) |
|
| 13 |
+
| RE-850 | [6939 normal reset suffix](QVM_NEXTMAP_RESET.md) |
|
| 14 |
+
| RE-851 | [Rust staged normal reset](RUST_NEXTMAP_RESET.md) |
|
| 15 |
+
| RE-852 | [277695 temporary event and 278138 origin setter](QVM_EVENT_CONSTRUCT.md) |
|
| 16 |
+
| RE-853 | [Rust temporary event construction](RUST_EVENT_CONSTRUCT.md) |
|
| 17 |
+
|
| 18 |
+
## Findings and evidence limits
|
| 19 |
+
|
| 20 |
+
Camera placement has 72 coherent byte/word fixtures. It copies the camera position into entity and resolved-player origins, copies view angles, zeros velocity, sets movement type 5 and clears the observed entity/player fields. Both apparent mode/field 4324 gates reach the same body. Raw NaN payloads, infinities and signed zero copy exactly. Two distinct entity-to-client pointers exercise indirection; the Rust API accepts a resolved mutable client. This does not establish arbitrary pointer alias behavior or renderer integration.
|
| 21 |
+
|
| 22 |
+
View selection has 36 fixtures covering absent selection, absent target key, failed target lookup and found target. Original source copies selected or supplied-fallback view vectors and computes f32 target-minus-origin. Rust returns ordered search/fallback/aim intentions and exact finite direction words. The selector results and fallback 168114 writes are supplied. The original 62944 angle converter is captured without modifying angles, so this is not complete aiming or camera setup.
|
| 23 |
+
|
| 24 |
+
The series branch has 300 cases. It handles only positive phase and team-classified modes. A nonzero option requests restart unless both flag bits 2 and 4 are set. Otherwise it saves second then first score, clears active scores/pending/blocked/phase, removes those flags, and requests formatted configstrings 1005 and 2 plus downstream work. Actual 33715 mode classification executes. The original format strings are `%d` and `1 %i %i`; 70458 output is supplied as distinct pointers. The normal branch stops at 7070 in this report.
|
| 25 |
+
|
| 26 |
+
The normal suffix has 48 cases. After captured 122230/7188 calls, it clears round/blocked/global scores and connected-client scores; mode 9 additionally clears fields 304/308. A snapshot at captured 249007 proves those changes happen before the second loop changes connected state 2 to 1. Pending, phase, series flags and saved scores remain untouched. Rust exposes separate preparation and post-map connection APIs so real map-child mutations can occur between stages. Fixture parity assumes those captured children do not mutate state.
|
| 27 |
+
|
| 28 |
+
The temporary-event constructor has 144 valid cases and five invalid float-domain rejections. Actual 277695 and 278138 execute against a supplied allocator record. Origin components truncate through CVFI/CVIF, normalizing negative zero, and feed both trajectory base and current origin. The constructor zeros trajectory time/type/duration and velocity, writes wrapped kind + 19, the `tempEntity` class token/hash, clock 568 and free flag 572, then requests syscall−31. It preserves allocator flags 424 and caller-owned fields 84/140. This does not prove the real allocator supplies flags 16. Rust validates conversion before changing its record, then returns a link intention; invalid-domain atomic rejection is a deliberate safe boundary. Original class token 97191 is source metadata, not a portable native pointer.
|
| 29 |
+
|
| 30 |
+
## Validation
|
| 31 |
+
|
| 32 |
+
Each task used its focused cargo xtask group before its own commit; affected reports regenerated twice and relevant Python plus scoped gameplay Rust tests passed. Storage, documentation links and whitespace guards ran throughout. The registry regression verifies all five source-report-to-Rust edges, transition module selection and the shared intermission mode-classifier dependency. The single full-suite run after commit ten, `cargo xtask test-full --since 15d7fcac`, passed: 1,668 Python tests and 147 Rust tests (assets 10, gameplay 109, xtask 28). All 46 affected report producers regenerated twice deterministically. Storage policy, links across 414 documentation files and whitespace checks passed. No generated reports changed. Validation notes were amended into task ten.
|
| 33 |
+
|
| 34 |
+
Use `cargo xtask test-group <name>` with `camera-place`, `rust-camera-place`, `camera-select`, `rust-camera-select`, `nextmap-series`, `rust-nextmap-series`, `nextmap-reset`, `rust-nextmap-reset`, `event-construct` or `rust-event-construct`.
|
| 35 |
+
|
| 36 |
+
## Next work: RE-854
|
| 37 |
+
|
| 38 |
+
- [ ] Recover actual 276433/276586 searches, 168114 fallback selection and 62944 direction-to-angle conversion.
|
| 39 |
+
- [ ] Compose 6717 and 6575 into begin-intermission source/Rust flows, including client-pointer alias fixtures and actual camera/respawn state ownership.
|
| 40 |
+
- [ ] Recover 122230/7188/249007 and 256248/256651 command/map effects, then compose complete 6939 into readiness and runtime handling.
|
| 41 |
+
- [ ] Recover 277165 allocation/initialization, resolve class metadata portably and integrate 277695 with mode 9 caller fields and real linking/event lifetime.
|
| 42 |
+
- [ ] Recover respawn 175123 and slow setup 156523, and execute publication 6328 with verified formatter/configstring/network ownership.
|
| 43 |
+
- [ ] Integrate ranking→exit/intermission→camera/map/event→scoreboard state, compare real game/native traces, and continue legacy trace audits.
|
| 44 |
+
- [ ] Validate actual macOS/Linux Bevy/Solari gameplay and rendering. These bounded Rust policies do not establish full-game completion.
|
docs/research/README.md
CHANGED
|
@@ -1150,3 +1150,8 @@ The extension collector adds five focused tests for native tail calls, command-r
|
|
| 1150 |
|
| 1151 |
|
| 1152 |
[RE-852: Original temporary event construction and origin snapping](QVM_EVENT_CONSTRUCT.md).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1150 |
|
| 1151 |
|
| 1152 |
[RE-852: Original temporary event construction and origin snapping](QVM_EVENT_CONSTRUCT.md).
|
| 1153 |
+
|
| 1154 |
+
|
| 1155 |
+
[RE-853: Rust temporary event construction and ownership boundaries](RUST_EVENT_CONSTRUCT.md).
|
| 1156 |
+
|
| 1157 |
+
- [RE-844–853 camera, map and event batch evidence and next work](QVM_CAMERA_MAP_EVENT_BATCH.md).
|
docs/research/RUST_EVENT_CONSTRUCT.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Rust temporary event construction and ownership boundaries
|
| 2 |
+
|
| 3 |
+
RE-853. Reproduce with `python3 scripts/analyze_rust_event_construct.py`; focused validation: `cargo xtask test-group rust-event-construct`. [Machine report](rust-event-construct.json).
|
| 4 |
+
|
| 5 |
+
Rust matches 144 original temporary-event cases, including exact snap words, event-kind wrapping, metadata and preservation of allocator/caller fields. Five invalid source domains reject atomically in Rust. Allocation and native linking remain caller-owned; source class tokens require runtime metadata resolution.
|
| 6 |
+
|
| 7 |
+
Original executable/native runtime and complete Linux/macOS Rust/Bevy/Solari acceptance remain unverified.
|
docs/research/rust-event-construct.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": 109,
|
| 2989 |
"source_report": "docs/research/qvm-health-impulse.json",
|
| 2990 |
"source_report_sha256": "625fd8064004ea6dbdf398d51d0af844d9c635ff04c0a0790886dddb6ab81e71"
|
| 2991 |
}
|
scripts/analyze_rust_event_construct.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
import hashlib,json
|
| 3 |
+
from pathlib import Path
|
| 4 |
+
from rust_transition_support import binary,result,invoke
|
| 5 |
+
from analyze_qvm import write_json
|
| 6 |
+
def encode(s):
|
| 7 |
+
a=s['input'];return [*a['origin'],a['kind'],a['now'],a['flags']]
|
| 8 |
+
def project(s):return {'fields':s['fields'],'link':s['requests'][-1]['target']==-31}
|
| 9 |
+
def main():
|
| 10 |
+
b=binary();p=Path('docs/research/qvm-event-construct.json');data=p.read_bytes();rows=[]
|
| 11 |
+
for s in json.loads(data)['probes']:rows.append({'source':project(s),'rust':result(b,'event',encode(s))})
|
| 12 |
+
rejected=[]
|
| 13 |
+
for bad in json.loads(data)['rejections']:
|
| 14 |
+
r=invoke(b,'event',[*bad['origin'],69,1000,16],check=False);assert r.returncode!=0;rejected.append({'origin':bad['origin'],'exit_code':r.returncode,'error':r.stderr.strip()})
|
| 15 |
+
write_json(Path('docs/research/rust-event-construct.json'),{'source_report':str(p),'source_report_sha256':hashlib.sha256(data).hexdigest(),'probes':rows,'rejections':rejected,'limits':'Rust matches 144 original temporary-event cases, including exact snap words, event-kind wrapping, metadata and preservation of allocator/caller fields. Five invalid source domains reject atomically in Rust. Allocation and native linking remain caller-owned; source class tokens require runtime metadata resolution.'})
|
| 16 |
+
if __name__=='__main__':main()
|
scripts/test_rust_event_construct.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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-event-construct.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 |
+
self.assertEqual(len(r['rejections']),5)
|
| 8 |
+
for p in r['rejections']:self.assertNotEqual(p['exit_code'],0);self.assertEqual(p['error'],'FloatDomain')
|
| 9 |
+
def test_source_identity(self):
|
| 10 |
+
r=json.loads(Path('docs/research/rust-event-construct.json').read_text());self.assertEqual(hashlib.sha256(Path(r['source_report']).read_bytes()).hexdigest(),r['source_report_sha256'])
|
| 11 |
+
if __name__=='__main__':unittest.main()
|
xtask/checks.tsv
CHANGED
|
@@ -2320,3 +2320,16 @@ report scripts/analyze_qvm_event_construct.py docs/research/qvm-event-construct.
|
|
| 2320 |
edge docs/research/qvm-event-construct.json scripts/test_qvm_event_construct.py
|
| 2321 |
group event-construct scripts/analyze_qvm_event_construct.py
|
| 2322 |
edge scripts/analyze_qvm_event_construct.py scripts/analyze_qvm_resumer_audit.py
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2320 |
edge docs/research/qvm-event-construct.json scripts/test_qvm_event_construct.py
|
| 2321 |
group event-construct scripts/analyze_qvm_event_construct.py
|
| 2322 |
edge scripts/analyze_qvm_event_construct.py scripts/analyze_qvm_resumer_audit.py
|
| 2323 |
+
edge Cargo.toml scripts/analyze_rust_event_construct.py
|
| 2324 |
+
edge Cargo.lock scripts/analyze_rust_event_construct.py
|
| 2325 |
+
edge crates/urt-gameplay/Cargo.toml scripts/analyze_rust_event_construct.py
|
| 2326 |
+
edge crates/urt-gameplay/src/lib.rs scripts/analyze_rust_event_construct.py
|
| 2327 |
+
edge crates/urt-gameplay/src/transition.rs scripts/analyze_rust_event_construct.py
|
| 2328 |
+
edge crates/urt-gameplay/src/bin/urt-transition.rs scripts/analyze_rust_event_construct.py
|
| 2329 |
+
edge docs/research/qvm-event-construct.json scripts/analyze_rust_event_construct.py
|
| 2330 |
+
group rust-event-construct scripts/analyze_rust_health_impulse.py
|
| 2331 |
+
group gameplay scripts/analyze_rust_event_construct.py
|
| 2332 |
+
report scripts/analyze_rust_event_construct.py docs/research/rust-event-construct.json
|
| 2333 |
+
edge docs/research/rust-event-construct.json scripts/test_rust_event_construct.py
|
| 2334 |
+
group rust-event-construct scripts/analyze_rust_event_construct.py
|
| 2335 |
+
edge scripts/analyze_rust_event_construct.py scripts/analyze_qvm_resumer_audit.py
|
xtask/src/lib.rs
CHANGED
|
@@ -1049,6 +1049,8 @@ mod integration_tests {
|
|
| 1049 |
("exit_prefix", "exit_prefix"),
|
| 1050 |
("exit_rules", "exit_class"),
|
| 1051 |
("intermission", "intermission_flow"),
|
|
|
|
|
|
|
| 1052 |
("leaderboard", "leaderboard"),
|
| 1053 |
("recipient_wire", "recipient_wire"),
|
| 1054 |
] {
|
|
@@ -1109,6 +1111,11 @@ mod integration_tests {
|
|
| 1109 |
("qvm-intermission-begin", "intermission_begin"),
|
| 1110 |
("qvm-exit-log", "exit_log"),
|
| 1111 |
("qvm-intermission-flow", "intermission_flow"),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1112 |
] {
|
| 1113 |
let selected = plan(
|
| 1114 |
&g,
|
|
|
|
| 1049 |
("exit_prefix", "exit_prefix"),
|
| 1050 |
("exit_rules", "exit_class"),
|
| 1051 |
("intermission", "intermission_flow"),
|
| 1052 |
+
("intermission", "nextmap_series"),
|
| 1053 |
+
("transition", "event_construct"),
|
| 1054 |
("leaderboard", "leaderboard"),
|
| 1055 |
("recipient_wire", "recipient_wire"),
|
| 1056 |
] {
|
|
|
|
| 1111 |
("qvm-intermission-begin", "intermission_begin"),
|
| 1112 |
("qvm-exit-log", "exit_log"),
|
| 1113 |
("qvm-intermission-flow", "intermission_flow"),
|
| 1114 |
+
("qvm-camera-place", "camera_place"),
|
| 1115 |
+
("qvm-camera-select", "camera_select"),
|
| 1116 |
+
("qvm-nextmap-series", "nextmap_series"),
|
| 1117 |
+
("qvm-nextmap-reset", "nextmap_reset"),
|
| 1118 |
+
("qvm-event-construct", "event_construct"),
|
| 1119 |
] {
|
| 1120 |
let selected = plan(
|
| 1121 |
&g,
|