gameplay: resolve full defuse effect feedback
Browse files- crates/urt-gameplay/src/bin/urt-effect-feedback.rs +117 -0
- crates/urt-gameplay/src/effect_feedback.rs +141 -0
- docs/FINDINGS.md +4 -0
- docs/PROVISIONAL_TODO.md +5 -0
- docs/RESEARCH_LEDGER.md +4 -0
- docs/REVERSE_ENGINEERING_TODO.md +5 -0
- docs/TESTING.md +2 -0
- docs/research/QVM_DEFUSE_BATCH.md +3 -1
- docs/research/QVM_EFFECT_FEEDBACK_BATCH.md +69 -0
- docs/research/README.md +4 -0
- docs/research/RUST_EFFECT_DEFUSE_COMPLETE.md +5 -0
- docs/research/rust-effect-defuse-complete.json +0 -0
- docs/research/rust-health-impulse.json +1 -1
- scripts/analyze_rust_effect_defuse_complete.py +19 -0
- scripts/test_rust_effect_defuse_complete.py +9 -0
- xtask/checks.tsv +37 -0
- xtask/src/lib.rs +5 -0
crates/urt-gameplay/src/bin/urt-effect-feedback.rs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
|
|
| 1 |
use urt_gameplay::effect_feedback::*;
|
| 2 |
fn list(v: &[u32]) -> String {
|
| 3 |
format!(
|
|
@@ -29,6 +30,7 @@ fn main() {
|
|
| 29 |
"radio" => println!("{}", radio(&w)),
|
| 30 |
"finish" => println!("{}", fragment(&w, DefusePhase::Finish)),
|
| 31 |
"begin" => println!("{}", fragment(&w, DefusePhase::Begin)),
|
|
|
|
| 32 |
_ => panic!("unknown contract"),
|
| 33 |
}
|
| 34 |
}
|
|
@@ -267,3 +269,118 @@ fn fragment(w: &[u32], phase: DefusePhase) -> String {
|
|
| 267 |
let o = resolve_defuse_fragment(&mut s, &mut f, i, &c, phase).unwrap();
|
| 268 |
format!("{{{}}}", feedback_fields(s, &f, &o))
|
| 269 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
use urt_gameplay::defuse::*;
|
| 2 |
use urt_gameplay::effect_feedback::*;
|
| 3 |
fn list(v: &[u32]) -> String {
|
| 4 |
format!(
|
|
|
|
| 30 |
"radio" => println!("{}", radio(&w)),
|
| 31 |
"finish" => println!("{}", fragment(&w, DefusePhase::Finish)),
|
| 32 |
"begin" => println!("{}", fragment(&w, DefusePhase::Begin)),
|
| 33 |
+
"complete" => println!("{}", complete(&w)),
|
| 34 |
_ => panic!("unknown contract"),
|
| 35 |
}
|
| 36 |
}
|
|
|
|
| 269 |
let o = resolve_defuse_fragment(&mut s, &mut f, i, &c, phase).unwrap();
|
| 270 |
format!("{{{}}}", feedback_fields(s, &f, &o))
|
| 271 |
}
|
| 272 |
+
|
| 273 |
+
fn decode_full(w: &[u32]) -> (DefuseWorld, FullDefuseInput) {
|
| 274 |
+
use urt_gameplay::move_callbacks::ObjectiveClient;
|
| 275 |
+
assert_eq!(w.len(), 31);
|
| 276 |
+
let (state, base) = decode_defuse(w);
|
| 277 |
+
let selected = if w[27] == 1 { 2 } else { 1 };
|
| 278 |
+
let own_team = if w[19] == 0 { selected } else { w[19] };
|
| 279 |
+
let other_team = if w[24] == 0 { selected } else { w[24] };
|
| 280 |
+
let mut clients = vec![
|
| 281 |
+
ObjectiveClient {
|
| 282 |
+
connection: 2,
|
| 283 |
+
health: 1,
|
| 284 |
+
follow: 0,
|
| 285 |
+
team: selected,
|
| 286 |
+
busy: 0
|
| 287 |
+
};
|
| 288 |
+
(w[25] as usize).max(3)
|
| 289 |
+
];
|
| 290 |
+
clients[w[26] as usize] = ObjectiveClient {
|
| 291 |
+
connection: w[21],
|
| 292 |
+
health: w[22],
|
| 293 |
+
follow: w[23],
|
| 294 |
+
team: other_team,
|
| 295 |
+
busy: w[20],
|
| 296 |
+
};
|
| 297 |
+
clients[2] = ObjectiveClient {
|
| 298 |
+
connection: w[16],
|
| 299 |
+
health: w[17],
|
| 300 |
+
follow: w[18],
|
| 301 |
+
team: own_team,
|
| 302 |
+
busy: state.busy,
|
| 303 |
+
};
|
| 304 |
+
let mut bombs = vec![
|
| 305 |
+
DefuseBomb {
|
| 306 |
+
in_use: true,
|
| 307 |
+
has_class: true,
|
| 308 |
+
hash: 0,
|
| 309 |
+
point: [0; 3]
|
| 310 |
+
};
|
| 311 |
+
6
|
| 312 |
+
];
|
| 313 |
+
for j in [4, 5] {
|
| 314 |
+
bombs[j].hash = BOMB_CLASS_HASH;
|
| 315 |
+
bombs[j].point[0] = if j == 4 { w[28] } else { 30f32.to_bits() };
|
| 316 |
+
}
|
| 317 |
+
match w[29] {
|
| 318 |
+
1 => bombs[4].in_use = false,
|
| 319 |
+
2 => bombs[4].has_class = false,
|
| 320 |
+
3 => bombs[4].hash = 0,
|
| 321 |
+
_ => {}
|
| 322 |
+
}
|
| 323 |
+
if w[30] != 0 {
|
| 324 |
+
bombs[4].hash = 0;
|
| 325 |
+
bombs[5].hash = 0;
|
| 326 |
+
}
|
| 327 |
+
(
|
| 328 |
+
DefuseWorld {
|
| 329 |
+
state,
|
| 330 |
+
clients,
|
| 331 |
+
bombs,
|
| 332 |
+
actor_point: [0; 3],
|
| 333 |
+
},
|
| 334 |
+
FullDefuseInput {
|
| 335 |
+
base,
|
| 336 |
+
entity: w[10] != 0,
|
| 337 |
+
client: w[11] != 0,
|
| 338 |
+
enabled_a: w[12],
|
| 339 |
+
enabled_b: w[13],
|
| 340 |
+
start: w[14],
|
| 341 |
+
delay: w[15],
|
| 342 |
+
selector: w[27],
|
| 343 |
+
count: w[25] as usize,
|
| 344 |
+
},
|
| 345 |
+
)
|
| 346 |
+
}
|
| 347 |
+
fn complete(w: &[u32]) -> String {
|
| 348 |
+
assert!(w.len() >= 36);
|
| 349 |
+
assert_eq!(w.len(), 36 + w[35] as usize);
|
| 350 |
+
let (mut world, i) = decode_full(&w[..31]);
|
| 351 |
+
let mut f = feedback(w[33] != 0);
|
| 352 |
+
let c = EffectContext {
|
| 353 |
+
paused: w[31] != 0,
|
| 354 |
+
constructed: w[32] != 0,
|
| 355 |
+
tick: w[7],
|
| 356 |
+
origin: [0; 3],
|
| 357 |
+
radio: RadioInput {
|
| 358 |
+
follow: 0,
|
| 359 |
+
health: 1,
|
| 360 |
+
team: 1,
|
| 361 |
+
slot: 2,
|
| 362 |
+
mode: 8,
|
| 363 |
+
count: w[25] as usize,
|
| 364 |
+
tick: w[7],
|
| 365 |
+
code: 7,
|
| 366 |
+
success: w[34] != 0,
|
| 367 |
+
payload: w[36..].iter().map(|v| *v as u8).collect(),
|
| 368 |
+
},
|
| 369 |
+
clients: vec![],
|
| 370 |
+
};
|
| 371 |
+
let o = resolve_defuse_world(&mut world, &mut f, i, &c).unwrap();
|
| 372 |
+
let lookups = o
|
| 373 |
+
.defuse
|
| 374 |
+
.lookups
|
| 375 |
+
.iter()
|
| 376 |
+
.map(|v| v.map(|i| i.to_string()).unwrap_or("null".into()))
|
| 377 |
+
.collect::<Vec<_>>()
|
| 378 |
+
.join(",");
|
| 379 |
+
format!(
|
| 380 |
+
r#"{{{},"lookups":[{}],"distances":{},"missing":{}}}"#,
|
| 381 |
+
feedback_fields(world.state, &f, &o.feedback),
|
| 382 |
+
lookups,
|
| 383 |
+
list(&o.defuse.distances),
|
| 384 |
+
o.defuse.missing
|
| 385 |
+
)
|
| 386 |
+
}
|
crates/urt-gameplay/src/effect_feedback.rs
CHANGED
|
@@ -467,3 +467,144 @@ mod resolved_begin_tests {
|
|
| 467 |
assert_eq!((s, f), old);
|
| 468 |
}
|
| 469 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 467 |
assert_eq!((s, f), old);
|
| 468 |
}
|
| 469 |
}
|
| 470 |
+
|
| 471 |
+
#[derive(Clone, Debug, PartialEq, Eq)]
|
| 472 |
+
pub struct ResolvedWorldOutput {
|
| 473 |
+
pub defuse: crate::defuse::DefuseOutcome,
|
| 474 |
+
pub feedback: ResolvedOutput,
|
| 475 |
+
}
|
| 476 |
+
/// Complete defuse policy with resolved constructor/radio/score/counter feedback.
|
| 477 |
+
/// Both world and feedback commit only after all modeled policies succeed.
|
| 478 |
+
pub fn resolve_defuse_world(
|
| 479 |
+
world: &mut crate::defuse::DefuseWorld,
|
| 480 |
+
feedback: &mut FeedbackState,
|
| 481 |
+
input: crate::defuse::FullDefuseInput,
|
| 482 |
+
context: &EffectContext,
|
| 483 |
+
) -> Result<ResolvedWorldOutput, Error> {
|
| 484 |
+
let mut next = world.clone();
|
| 485 |
+
let mut fb = feedback.clone();
|
| 486 |
+
let defuse = crate::defuse::process_defuse(&mut next, input)?;
|
| 487 |
+
let mut context = context.clone();
|
| 488 |
+
context.tick = input.base.tick;
|
| 489 |
+
context.radio.tick = input.base.tick;
|
| 490 |
+
context.radio.slot = input.base.slot;
|
| 491 |
+
context.radio.mode = 8;
|
| 492 |
+
context.radio.count = input.count;
|
| 493 |
+
context.clients = next
|
| 494 |
+
.clients
|
| 495 |
+
.iter()
|
| 496 |
+
.map(|c| RadioClient {
|
| 497 |
+
connection: c.connection,
|
| 498 |
+
team: c.team,
|
| 499 |
+
})
|
| 500 |
+
.collect();
|
| 501 |
+
if let Some(c) = next.clients.get(input.base.slot as usize) {
|
| 502 |
+
context.radio.follow = c.follow;
|
| 503 |
+
context.radio.health = c.health;
|
| 504 |
+
context.radio.team = c.team;
|
| 505 |
+
}
|
| 506 |
+
if let Some(Some(index)) = defuse.lookups.first() {
|
| 507 |
+
context.origin = next.bombs[*index].point;
|
| 508 |
+
}
|
| 509 |
+
let output = resolve_effects(&next.state, &mut fb, defuse.effects.clone(), &context)?;
|
| 510 |
+
*world = next;
|
| 511 |
+
*feedback = fb;
|
| 512 |
+
Ok(ResolvedWorldOutput {
|
| 513 |
+
defuse,
|
| 514 |
+
feedback: output,
|
| 515 |
+
})
|
| 516 |
+
}
|
| 517 |
+
#[cfg(test)]
|
| 518 |
+
mod resolved_world_tests {
|
| 519 |
+
use super::resolved_finish_tests::{context, feedback};
|
| 520 |
+
use super::*;
|
| 521 |
+
use crate::defuse::*;
|
| 522 |
+
use crate::move_callbacks::ObjectiveClient;
|
| 523 |
+
fn world() -> DefuseWorld {
|
| 524 |
+
DefuseWorld {
|
| 525 |
+
state: DefuseState {
|
| 526 |
+
flags: 32772,
|
| 527 |
+
flags104: 16,
|
| 528 |
+
busy: 1,
|
| 529 |
+
clock: 5000,
|
| 530 |
+
complete: 0,
|
| 531 |
+
animation: 99,
|
| 532 |
+
weapon: 11,
|
| 533 |
+
event: [7, 0x80000001],
|
| 534 |
+
},
|
| 535 |
+
clients: vec![
|
| 536 |
+
ObjectiveClient {
|
| 537 |
+
connection: 2,
|
| 538 |
+
health: 1,
|
| 539 |
+
follow: 0,
|
| 540 |
+
team: 1,
|
| 541 |
+
busy: 0
|
| 542 |
+
};
|
| 543 |
+
3
|
| 544 |
+
],
|
| 545 |
+
bombs: vec![DefuseBomb {
|
| 546 |
+
in_use: true,
|
| 547 |
+
has_class: true,
|
| 548 |
+
hash: BOMB_CLASS_HASH,
|
| 549 |
+
point: [10f32.to_bits(), 0, 0],
|
| 550 |
+
}],
|
| 551 |
+
actor_point: [0; 3],
|
| 552 |
+
}
|
| 553 |
+
}
|
| 554 |
+
fn input() -> FullDefuseInput {
|
| 555 |
+
FullDefuseInput {
|
| 556 |
+
base: DefuseInput {
|
| 557 |
+
tick: 10000,
|
| 558 |
+
duration: 5,
|
| 559 |
+
index: 3,
|
| 560 |
+
slot: 2,
|
| 561 |
+
},
|
| 562 |
+
entity: true,
|
| 563 |
+
client: true,
|
| 564 |
+
enabled_a: 1,
|
| 565 |
+
enabled_b: 1,
|
| 566 |
+
start: 8000,
|
| 567 |
+
delay: 1,
|
| 568 |
+
selector: 0,
|
| 569 |
+
count: 3,
|
| 570 |
+
}
|
| 571 |
+
}
|
| 572 |
+
#[test]
|
| 573 |
+
fn full_completion_materializes_event_score_and_counter() {
|
| 574 |
+
let mut w = world();
|
| 575 |
+
let mut f = feedback();
|
| 576 |
+
let c = EffectContext {
|
| 577 |
+
constructed: true,
|
| 578 |
+
..context()
|
| 579 |
+
};
|
| 580 |
+
let o = resolve_defuse_world(&mut w, &mut f, input(), &c).unwrap();
|
| 581 |
+
assert_eq!(w.state.complete, 1);
|
| 582 |
+
assert_eq!(f.score.player, 0);
|
| 583 |
+
assert_eq!(f.counters[5], 0);
|
| 584 |
+
let e = f.event_record.unwrap();
|
| 585 |
+
assert_eq!(e.kind, 103);
|
| 586 |
+
assert_eq!(e.origin, [10f32.to_bits(), 0, 0]);
|
| 587 |
+
assert!(o.feedback.effects.contains(&ResolvedEffect::Rank));
|
| 588 |
+
assert!(o.feedback.radio.is_empty());
|
| 589 |
+
}
|
| 590 |
+
#[test]
|
| 591 |
+
fn missing_bomb_and_late_error_preserve_state() {
|
| 592 |
+
let mut w = world();
|
| 593 |
+
w.bombs.clear();
|
| 594 |
+
let mut f = feedback();
|
| 595 |
+
let old = (w.clone(), f.clone());
|
| 596 |
+
assert!(
|
| 597 |
+
resolve_defuse_world(&mut w, &mut f, input(), &context())
|
| 598 |
+
.unwrap()
|
| 599 |
+
.defuse
|
| 600 |
+
.missing
|
| 601 |
+
);
|
| 602 |
+
assert_eq!((w, f), old);
|
| 603 |
+
let mut w = world();
|
| 604 |
+
let mut f = feedback();
|
| 605 |
+
f.counters.clear();
|
| 606 |
+
let old = (w.clone(), f.clone());
|
| 607 |
+
assert!(resolve_defuse_world(&mut w, &mut f, input(), &context()).is_err());
|
| 608 |
+
assert_eq!((w, f), old);
|
| 609 |
+
}
|
| 610 |
+
}
|
docs/FINDINGS.md
CHANGED
|
@@ -2005,3 +2005,7 @@ RE-1030: Sixteen source cases execute defuse start with actual277695/278138 even
|
|
| 2005 |
RE-1031: Rust composes the recovered event constructor and team-radio policies across16 source cases. Metadata, snapped origins, caller event flags and radio commands/marker state match actual source bodies. Explicit allocate/link/radio order replaces the historical sound tag. Tests verify origin snapping and unchanged score/counters, plus rollback of prior start writes on an unsupported origin. Base allocation, linking, location and sending remain boundaries. [Evidence](research/RUST_EFFECT_DEFUSE_BEGIN.md).
|
| 2006 |
|
| 2007 |
RE-1032: Forty-eight coherent source cases execute full defuse gates/lookup/distance with actual constructor, team-radio, score and counter bodies. Reports compare event records, command plans, marker deadlines, player/team scores and counters alongside defuse state. Paused scoring, inactive gates, decoy bombs and missing-bomb boundary are covered. Base allocation, location/formatting and native link/send/ranking/log remain supplied/modeled/captured. No teleport or five-point award is inferred. [Evidence](research/QVM_EFFECT_DEFUSE_COMPLETE.md).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2005 |
RE-1031: Rust composes the recovered event constructor and team-radio policies across16 source cases. Metadata, snapped origins, caller event flags and radio commands/marker state match actual source bodies. Explicit allocate/link/radio order replaces the historical sound tag. Tests verify origin snapping and unchanged score/counters, plus rollback of prior start writes on an unsupported origin. Base allocation, linking, location and sending remain boundaries. [Evidence](research/RUST_EFFECT_DEFUSE_BEGIN.md).
|
| 2006 |
|
| 2007 |
RE-1032: Forty-eight coherent source cases execute full defuse gates/lookup/distance with actual constructor, team-radio, score and counter bodies. Reports compare event records, command plans, marker deadlines, player/team scores and counters alongside defuse state. Paused scoring, inactive gates, decoy bombs and missing-bomb boundary are covered. Base allocation, location/formatting and native link/send/ranking/log remain supplied/modeled/captured. No teleport or five-point award is inferred. [Evidence](research/QVM_EFFECT_DEFUSE_COMPLETE.md).
|
| 2008 |
+
|
| 2009 |
+
RE-1033: Rust matches48 full-source scenarios with actual constructor/radio/score/counter policies. Selected bomb origin and live teammate table feed the resolved effects rather than fixed synthetic responses. Missing-bomb and paused-score boundaries are preserved; world and feedback stage together on late errors. Tests materialize event84, wrapped score/counter changes and missing/error preservation. Native allocation/link/send/ranking/log and location/formatter boundaries remain explicit. [Evidence](research/RUST_EFFECT_DEFUSE_COMPLETE.md).
|
| 2010 |
+
|
| 2011 |
+
RE-1024–1033 batch validation passed:1,998 Python tests,329 Rust tests,141 deterministic affected producers and612 documentation files. Source205260 is score update,283463 is indexed counter increment and193620 is team radio; old capture names remain compatibility labels. [Resolved feedback and next work](research/QVM_EFFECT_FEEDBACK_BATCH.md).
|
docs/PROVISIONAL_TODO.md
CHANGED
|
@@ -2065,3 +2065,8 @@ RE-974–983 completed routing, command rewrite, inactivity, movement-parameter
|
|
| 2065 |
- [x] RE-1031 Port resolved defuse event and radio feedback ([evidence](research/RUST_EFFECT_DEFUSE_BEGIN.md)).
|
| 2066 |
|
| 2067 |
- [x] RE-1032 Resolve full defuse callback effect feedback ([evidence](research/QVM_EFFECT_DEFUSE_COMPLETE.md)).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2065 |
- [x] RE-1031 Port resolved defuse event and radio feedback ([evidence](research/RUST_EFFECT_DEFUSE_BEGIN.md)).
|
| 2066 |
|
| 2067 |
- [x] RE-1032 Resolve full defuse callback effect feedback ([evidence](research/QVM_EFFECT_DEFUSE_COMPLETE.md)).
|
| 2068 |
+
|
| 2069 |
+
- [x] RE-1033 Port full defuse policy with resolved effect bodies ([evidence](research/RUST_EFFECT_DEFUSE_COMPLETE.md)).
|
| 2070 |
+
|
| 2071 |
+
- [x] RE-1024–1033 resolved-feedback batch:174 paired scenarios with corrected score/counter/radio identities and actual QVM effect bodies ([evidence](research/QVM_EFFECT_FEEDBACK_BATCH.md)).
|
| 2072 |
+
- [ ] RE-1034 connect remaining allocation/location/format/ranking/native feedback and migrate legacy labels ([scope](research/QVM_EFFECT_FEEDBACK_BATCH.md#next-work-re-1034)).
|
docs/RESEARCH_LEDGER.md
CHANGED
|
@@ -2803,3 +2803,7 @@ Rust composes the recovered event constructor and team-radio policies across16 s
|
|
| 2803 |
## 2026-10-29 — RE-1032 Resolve full defuse callback effect feedback
|
| 2804 |
|
| 2805 |
Forty-eight coherent source cases execute full defuse gates/lookup/distance with actual constructor, team-radio, score and counter bodies. Reports compare event records, command plans, marker deadlines, player/team scores and counters alongside defuse state. Paused scoring, inactive gates, decoy bombs and missing-bomb boundary are covered. Base allocation, location/formatting and native link/send/ranking/log remain supplied/modeled/captured. No teleport or five-point award is inferred. Focused `cargo xtask test-group qvm-effect-defuse-complete` passes with deterministic report regeneration and selected regressions. Full suite deferred to task ten. Original assets unchanged; Python uses the flake-declared Nix runtime.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2803 |
## 2026-10-29 — RE-1032 Resolve full defuse callback effect feedback
|
| 2804 |
|
| 2805 |
Forty-eight coherent source cases execute full defuse gates/lookup/distance with actual constructor, team-radio, score and counter bodies. Reports compare event records, command plans, marker deadlines, player/team scores and counters alongside defuse state. Paused scoring, inactive gates, decoy bombs and missing-bomb boundary are covered. Base allocation, location/formatting and native link/send/ranking/log remain supplied/modeled/captured. No teleport or five-point award is inferred. Focused `cargo xtask test-group qvm-effect-defuse-complete` passes with deterministic report regeneration and selected regressions. Full suite deferred to task ten. Original assets unchanged; Python uses the flake-declared Nix runtime.
|
| 2806 |
+
|
| 2807 |
+
## 2026-10-29 — RE-1033 Port full defuse policy with resolved effect bodies
|
| 2808 |
+
|
| 2809 |
+
Rust matches48 full-source scenarios with actual constructor/radio/score/counter policies. Selected bomb origin and live teammate table feed the resolved effects rather than fixed synthetic responses. Missing-bomb and paused-score boundaries are preserved; world and feedback stage together on late errors. Tests materialize event84, wrapped score/counter changes and missing/error preservation. Native allocation/link/send/ranking/log and location/formatter boundaries remain explicit. Focused `cargo xtask test-group rust-effect-defuse-complete` passes with deterministic report regeneration and selected regressions. The single `cargo xtask test-full --since 74572275` run at the tenth-commit boundary passed: **1,998 Python tests** across549 modules, **329 Rust tests** (assets10, gameplay289, xtask30), **141 deterministic affected report producers**, storage policy, links across **612 documentation files** and whitespace guards. Regeneration left no changes, including earlier defuse outputs. Focused dependency-registry regression passed. Validation notes are amended into task ten, preserving ten commits. Original assets unchanged; Python uses the flake-declared Nix runtime.
|
docs/REVERSE_ENGINEERING_TODO.md
CHANGED
|
@@ -2102,3 +2102,8 @@ RE-974–983 recover routing, command rewriting, inactivity and composed setup t
|
|
| 2102 |
- [x] RE-1031 Port resolved defuse event and radio feedback ([evidence](research/RUST_EFFECT_DEFUSE_BEGIN.md)).
|
| 2103 |
|
| 2104 |
- [x] RE-1032 Resolve full defuse callback effect feedback ([evidence](research/QVM_EFFECT_DEFUSE_COMPLETE.md)).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2102 |
- [x] RE-1031 Port resolved defuse event and radio feedback ([evidence](research/RUST_EFFECT_DEFUSE_BEGIN.md)).
|
| 2103 |
|
| 2104 |
- [x] RE-1032 Resolve full defuse callback effect feedback ([evidence](research/QVM_EFFECT_DEFUSE_COMPLETE.md)).
|
| 2105 |
+
|
| 2106 |
+
- [x] RE-1033 Port full defuse policy with resolved effect bodies ([evidence](research/RUST_EFFECT_DEFUSE_COMPLETE.md)).
|
| 2107 |
+
|
| 2108 |
+
- [x] RE-1024–1033 resolved-feedback batch:174 paired scenarios with corrected score/counter/radio identities and actual QVM effect bodies ([evidence](research/QVM_EFFECT_FEEDBACK_BATCH.md)).
|
| 2109 |
+
- [ ] RE-1034 connect remaining allocation/location/format/ranking/native feedback and migrate legacy labels ([scope](research/QVM_EFFECT_FEEDBACK_BATCH.md#next-work-re-1034)).
|
docs/TESTING.md
CHANGED
|
@@ -193,3 +193,5 @@ Movement-callback focused pairs: `qvm-move-meter`/`rust-move-meter`, `qvm-move-s
|
|
| 193 |
Assistance focused pairs: `qvm-assist-acquire`/`rust-assist-acquire`, `qvm-assist-cancel`/`rust-assist-cancel`, `qvm-assist-progress`/`rust-assist-progress`, `qvm-assist-complete`/`rust-assist-complete`, and `qvm-assist-sequence`/`rust-assist-sequence`. Use one group per invocation. Assistance module/CLI and recovered meter/cleanup inputs select affected Rust reports plus gameplay test-count metadata. Complete/replay probes execute actual152792/65655/152386 with modeled sqrt and captured/supplied native effects. The batch full check is `cargo xtask test-full --since 19fce7e8` after ten tasks. [Evidence and limits](research/QVM_ASSISTANCE_BATCH.md).
|
| 194 |
|
| 195 |
Defuse focused pairs: `qvm-defuse-begin`/`rust-defuse-begin`, `qvm-defuse-cancel`/`rust-defuse-cancel`, `qvm-defuse-finish`/`rust-defuse-finish`, `qvm-defuse-complete`/`rust-defuse-complete`, and `qvm-defuse-sequence`/`rust-defuse-sequence`. Run one group per invocation. Defuse module/CLI and eligibility inputs select affected Rust producers plus gameplay test-count metadata. Full/replay source checks execute actual153419/276433/65655 with modeled sqrt and supplied/captured native effects; missing lookup stops before fatal2319. Batch-wide validation after task ten is `cargo xtask test-full --since 26cfc686`. [Evidence and boundaries](research/QVM_DEFUSE_BATCH.md).
|
|
|
|
|
|
|
|
|
| 193 |
Assistance focused pairs: `qvm-assist-acquire`/`rust-assist-acquire`, `qvm-assist-cancel`/`rust-assist-cancel`, `qvm-assist-progress`/`rust-assist-progress`, `qvm-assist-complete`/`rust-assist-complete`, and `qvm-assist-sequence`/`rust-assist-sequence`. Use one group per invocation. Assistance module/CLI and recovered meter/cleanup inputs select affected Rust reports plus gameplay test-count metadata. Complete/replay probes execute actual152792/65655/152386 with modeled sqrt and captured/supplied native effects. The batch full check is `cargo xtask test-full --since 19fce7e8` after ten tasks. [Evidence and limits](research/QVM_ASSISTANCE_BATCH.md).
|
| 194 |
|
| 195 |
Defuse focused pairs: `qvm-defuse-begin`/`rust-defuse-begin`, `qvm-defuse-cancel`/`rust-defuse-cancel`, `qvm-defuse-finish`/`rust-defuse-finish`, `qvm-defuse-complete`/`rust-defuse-complete`, and `qvm-defuse-sequence`/`rust-defuse-sequence`. Run one group per invocation. Defuse module/CLI and eligibility inputs select affected Rust producers plus gameplay test-count metadata. Full/replay source checks execute actual153419/276433/65655 with modeled sqrt and supplied/captured native effects; missing lookup stops before fatal2319. Batch-wide validation after task ten is `cargo xtask test-full --since 26cfc686`. [Evidence and boundaries](research/QVM_DEFUSE_BATCH.md).
|
| 196 |
+
|
| 197 |
+
Resolved-feedback focused pairs: `qvm-effect-counter`/`rust-effect-counter`, `qvm-effect-radio`/`rust-effect-radio`, `qvm-effect-defuse-finish`/`rust-effect-defuse-finish`, `qvm-effect-defuse-begin`/`rust-effect-defuse-begin`, and `qvm-effect-defuse-complete`/`rust-effect-defuse-complete`. Run one group per invocation. Feedback/score/constructor and defuse inputs select affected producers plus gameplay test-count metadata. Function205260 is score,283463 is indexed counter increment and193620 is team radio; historical labels remain compatible. Full validation after task ten: `cargo xtask test-full --since 74572275`. [Evidence and correction](research/QVM_EFFECT_FEEDBACK_BATCH.md).
|
docs/research/QVM_DEFUSE_BATCH.md
CHANGED
|
@@ -59,7 +59,9 @@ Event allocation277695 is supplied. Team radio193620, logs7259, score update2052
|
|
| 59 |
|
| 60 |
The single `cargo xtask test-full --since 26cfc686` run at the tenth-commit boundary passed: **1,978 Python tests** across539 modules, **319 Rust tests** (assets10, gameplay279, xtask30), **131 deterministic affected report producers**, storage policy, links across **601 documentation files** and whitespace guards. Regeneration left no changes. Focused dependency-registry regression passed. Validation notes are amended into task ten, preserving ten commits.
|
| 61 |
|
| 62 |
-
##
|
|
|
|
|
|
|
| 63 |
|
| 64 |
- [ ] Recover allocation277695, team radio193620, score update205260 and counter update283463 for bomb/assistance consumers, then replace captured state feedback with verified adapters.
|
| 65 |
- [ ] Recover bomb creation/class ownership and objective event83/84 client rendering/audio consumers; verify shared-clock and teammate ownership across actual lifecycle transitions.
|
|
|
|
| 59 |
|
| 60 |
The single `cargo xtask test-full --since 26cfc686` run at the tenth-commit boundary passed: **1,978 Python tests** across539 modules, **319 Rust tests** (assets10, gameplay279, xtask30), **131 deterministic affected report producers**, storage policy, links across **601 documentation files** and whitespace guards. Regeneration left no changes. Focused dependency-registry regression passed. Validation notes are amended into task ten, preserving ten commits.
|
| 61 |
|
| 62 |
+
## Follow-up from RE-1024
|
| 63 |
+
|
| 64 |
+
The [RE-1024–1033 feedback batch](QVM_EFFECT_FEEDBACK_BATCH.md) corrects effect identities and connects actual constructor/radio/score/counter bodies. Allocation, location/formatter, ranking and native transport/lifecycle feedback remain open. The original follow-up scope was:
|
| 65 |
|
| 66 |
- [ ] Recover allocation277695, team radio193620, score update205260 and counter update283463 for bomb/assistance consumers, then replace captured state feedback with verified adapters.
|
| 67 |
- [ ] Recover bomb creation/class ownership and objective event83/84 client rendering/audio consumers; verify shared-clock and teammate ownership across actual lifecycle transitions.
|
docs/research/QVM_EFFECT_FEEDBACK_BATCH.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Resolved defuse effect feedback: RE-1024–1033
|
| 2 |
+
|
| 3 |
+
Ten tasks recover five source/Rust contracts across **174 paired scenarios**. They extend the [defuse batch](QVM_DEFUSE_BATCH.md), correcting misleading capture labels and replacing several supplied effects with actual QVM bodies and matching Rust policies. Each task has its own commit and focused validation.
|
| 4 |
+
|
| 5 |
+
| Tasks | Contract | Paired scenarios |
|
| 6 |
+
| --- | --- | ---: |
|
| 7 |
+
| RE-1024 / RE-1025 | [Source objective counter](QVM_EFFECT_COUNTER.md) / [Rust counter](RUST_EFFECT_COUNTER.md) | 12 |
|
| 8 |
+
| RE-1026 / RE-1027 | [Source team radio](QVM_EFFECT_RADIO.md) / [Rust radio](RUST_EFFECT_RADIO.md) | 34 |
|
| 9 |
+
| RE-1028 / RE-1029 | [Source completion feedback](QVM_EFFECT_DEFUSE_FINISH.md) / [Rust completion](RUST_EFFECT_DEFUSE_FINISH.md) | 64 |
|
| 10 |
+
| RE-1030 / RE-1031 | [Source start feedback](QVM_EFFECT_DEFUSE_BEGIN.md) / [Rust start](RUST_EFFECT_DEFUSE_BEGIN.md) | 16 |
|
| 11 |
+
| RE-1032 / RE-1033 | [Source full feedback](QVM_EFFECT_DEFUSE_COMPLETE.md) / [Rust full feedback](RUST_EFFECT_DEFUSE_COMPLETE.md) | 48 |
|
| 12 |
+
|
| 13 |
+
## Semantic correction
|
| 14 |
+
|
| 15 |
+
Earlier assistance/defuse reports used capture labels `teleport`, `award` and `sound` for functions205260,283463 and193620. Inspection of their bodies establishes:
|
| 16 |
+
|
| 17 |
+
- **205260 adds score.** It checks client existence and global34992512, increments client248 by the supplied delta, optionally updates team scores in mode3, and requests ranking5864. Its origin argument is unused. The generic score policy was already recovered elsewhere; the defuse resolver now applies it.
|
| 18 |
+
- **283463 increments a selected counter by1.** It computes client3036+4×index and wraps that word upward once. Defuse passes index5. This is separate from the one-point score update.
|
| 19 |
+
- **193620 routes team radio commands.** It obtains location text and sends `rsay` commands. It performs no direct native audio playback in this body; downstream radio/audio consumers remain separate work.
|
| 20 |
+
|
| 21 |
+
Historical JSON schemas and Rust enum tags remain compatible. Their numeric function IDs/arguments remain evidence, but names such as `Teleport`, `Award` and `Sound` must not be used as semantic instructions. Rust variants carry compatibility notes, affected findings have been corrected, and new feedback reports use `score`, `counter` and `radio` tags. New adapters interpret these IDs explicitly. This corrects earlier findings rather than claiming new movement or five-point reward behavior.
|
| 22 |
+
|
| 23 |
+
## Objective counter283463
|
| 24 |
+
|
| 25 |
+
Twelve probes execute actual283463 through its void-return boundary, covering indices0/5/14 and zero/ordinary/high-bit/wrapping values. Only the selected word changes. Guards at client3032 and3096 survive. The15-word research window is a bounded supplied storage view, not proof of the complete counter enum or lifecycle. Rust validates its caller-owned slice and performs one wrapping increment.
|
| 26 |
+
|
| 27 |
+
## Team radio193620
|
| 28 |
+
|
| 29 |
+
The sender must be live, non-following and not team3. Source268637 location text is supplied with a success result. A failed lookup clears the first buffer byte. Actual33715 classifies modes: connected same-team recipients receive messages in team modes or the explicit mode9 exception; mode11 and signed negative modes do not route. Recipient health/follow state is not checked by this body, and the sender's connection word is not its initial admission gate.
|
| 30 |
+
|
| 31 |
+
The command format is `rsay sender -1 type "location"`. The fixed integer/string formatter is modeled; payload quotes are preserved without invented escaping. Text-provider behavior beyond the supplied bounded string and native transport remain open. Existing source formatter policies can be connected separately.
|
| 32 |
+
|
| 33 |
+
After a send, an existing sender marker6168 receives deadline84=tick+3500 and active204=1. No recipients means no marker change; a null marker pointer is not dereferenced. Thirty-four cases cover mode/team/connection gates, zero/64 counts, failed text, quotes, absent marker and time wrapping. Source tests execute actual193620/33715; Rust returns command plans with matching marker state.
|
| 34 |
+
|
| 35 |
+
## Completion score and counter feedback
|
| 36 |
+
|
| 37 |
+
Sixty-four active completion scenarios execute actual153644,205260 and283463. Waiting leaves state unchanged. On completion, the ordered observations are log, event allocation, score request, optional ranking request and counter-index5 increment. Starting score and counter values at0xffffffff verifies independent wrapping.
|
| 38 |
+
|
| 39 |
+
Paused scoring returns before player/team writes or ranking. The later indexed counter increment still occurs because283463 has no pause gate. Defuse runs in mode8, so the source score helper changes the player score without changing team scores. Ranking5864, logging and allocation remain explicit boundaries in this pair. Rust reuses the established score policy and stages completion, score and counter state together; late unsupported counter storage rolls back prior planned updates.
|
| 40 |
+
|
| 41 |
+
## Event construction and radio at start
|
| 42 |
+
|
| 43 |
+
Sixteen start cases execute actual277695,278138,193620 and33715. Base allocator277165 still supplies an event pointer. The constructor writes type=event+19, original class metadata/hash, event time and free-after-event state. It snaps origin components through integer conversion and back to f32, initializes trajectory/velocity and copies current origin. Native link-31 is captured before the caller writes duration payload and event mask32.
|
| 44 |
+
|
| 45 |
+
The source then executes radio routing rather than supplying a sound effect result. Reports compare constructed fields, snapped negative/fractional origins, caller flags/payload, command bytes and marker state. Rust reuses `transition::temporary_event` and the recovered radio policy. Start does not change score/counters. Invalid origin conversion rejects without committing prior start state in the typed adapter.
|
| 46 |
+
|
| 47 |
+
## Full defuse composition
|
| 48 |
+
|
| 49 |
+
Forty-eight probes execute full153419 with actual bomb lookup/distance and the resolved constructor/radio/score/counter bodies. Selected bomb origin feeds event construction. Current client connection/team state feeds radio recipients rather than fixed responses. Cases include paused score updates, three selectors, waiting/completion/cancellation, blocking teammates, decoy bombs and the missing-bomb fatal boundary.
|
| 50 |
+
|
| 51 |
+
Reports compare defuse fields, event records, ordered semantic requests, location/getter counts, command plans, marker state, player/team scores and counter words. Rust stages world and feedback state together. Missing bomb remains an explicit stop before fatal2319; no continuation or native runtime behavior is invented.
|
| 52 |
+
|
| 53 |
+
## Validation and remaining boundaries
|
| 54 |
+
|
| 55 |
+
Each task runs its corresponding `cargo xtask test-group qvm-effect-*` or `rust-effect-*` before committing. Selected reports regenerate twice identically. Source reports retain original QVM identity and traces; independent expectations check gates, arithmetic, field writes and order. Rust reports retain source-report SHA256 and compare all projected fields. Ten added Rust tests cover wrapping counters, radio routing, score pause behavior, construction and atomic errors.
|
| 56 |
+
|
| 57 |
+
Dependency mappings include the feedback module/CLI, score and event-constructor modules, defuse consumers and gameplay test-count metadata. The registry regression verifies selection. One full-suite run follows task ten: `cargo xtask test-full --since 74572275`. Python uses only the flake-declared Nix runtime, including Git hooks. Generated Rust build caches were cleared after a disk-space failure; source/assets were preserved and final validation runs without incremental compilation to limit cache growth.
|
| 58 |
+
|
| 59 |
+
Remaining boundaries: base allocation277165, native links/sends, location268637, fixed formatter70458, ranking5864 and logs7259. Some have existing generic research elsewhere, but their full feedback is not connected in these probes. This is QVM/Rust policy evidence, not actual game or native platform conformance.
|
| 60 |
+
|
| 61 |
+
The single `cargo xtask test-full --since 74572275` run at the tenth-commit boundary passed: **1,998 Python tests** across549 modules, **329 Rust tests** (assets10, gameplay289, xtask30), **141 deterministic affected report producers**, storage policy, links across **612 documentation files** and whitespace guards. Regeneration left no changes, including earlier defuse outputs. Focused dependency-registry regression passed. Validation notes are amended into task ten, preserving ten commits.
|
| 62 |
+
|
| 63 |
+
## Next work: RE-1034
|
| 64 |
+
|
| 65 |
+
- [ ] Connect actual location/formatter, allocation/lifetime, ranking and native link/send/log adapters into defuse and assistance feedback, reusing existing generic findings where applicable.
|
| 66 |
+
- [ ] Migrate legacy effect-tag APIs/report readers to corrected semantic types without losing provenance or compatibility.
|
| 67 |
+
- [ ] Verify bomb/objective counter enum ownership and event83/84 plus radio7 downstream rendering/audio consumers.
|
| 68 |
+
- [ ] Compose resolved defuse and assistance/self-recovery feedback with full154089 preparation, movement54475 and timer155714.
|
| 69 |
+
- [ ] Expand identity/aliasing, geometry, wrap/configuration and longer lifecycle scenarios; continue asset conversion, Bevy/Solari rendering and playable macOS/Linux acceptance.
|
docs/research/README.md
CHANGED
|
@@ -1633,3 +1633,7 @@ The extension collector adds five focused tests for native tail calls, command-r
|
|
| 1633 |
- [RE-1031: Port resolved defuse event and radio feedback](RUST_EFFECT_DEFUSE_BEGIN.md).
|
| 1634 |
|
| 1635 |
- [RE-1032: Resolve full defuse callback effect feedback](QVM_EFFECT_DEFUSE_COMPLETE.md).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1633 |
- [RE-1031: Port resolved defuse event and radio feedback](RUST_EFFECT_DEFUSE_BEGIN.md).
|
| 1634 |
|
| 1635 |
- [RE-1032: Resolve full defuse callback effect feedback](QVM_EFFECT_DEFUSE_COMPLETE.md).
|
| 1636 |
+
|
| 1637 |
+
- [RE-1033: Port full defuse policy with resolved effect bodies](RUST_EFFECT_DEFUSE_COMPLETE.md).
|
| 1638 |
+
|
| 1639 |
+
- [Resolved defuse effect feedback: RE-1024–1033](QVM_EFFECT_FEEDBACK_BATCH.md).
|
docs/research/RUST_EFFECT_DEFUSE_COMPLETE.md
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Port full defuse policy with resolved effect bodies
|
| 2 |
+
|
| 3 |
+
RE-1033. Focused validation: `cargo xtask test-group rust-effect-defuse-complete`. [Machine report](rust-effect-defuse-complete.json).
|
| 4 |
+
|
| 5 |
+
Rust matches48 full-source scenarios with actual constructor/radio/score/counter policies. Selected bomb origin and live teammate table feed the resolved effects rather than fixed synthetic responses. Missing-bomb and paused-score boundaries are preserved; world and feedback stage together on late errors. Tests materialize event84, wrapped score/counter changes and missing/error preservation. Native allocation/link/send/ranking/log and location/formatter boundaries remain explicit.
|
docs/research/rust-effect-defuse-complete.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": 289,
|
| 2989 |
"source_report": "docs/research/qvm-health-impulse.json",
|
| 2990 |
"source_report_sha256": "625fd8064004ea6dbdf398d51d0af844d9c635ff04c0a0790886dddb6ab81e71"
|
| 2991 |
}
|
scripts/analyze_rust_effect_defuse_complete.py
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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-effect-feedback'],check=True,capture_output=True)
|
| 9 |
+
binary=Path(os.environ.get('CARGO_TARGET_DIR','target'))/'debug'/'urt-effect-feedback'
|
| 10 |
+
path=Path('docs/research/qvm-effect-defuse-complete.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 ['flags', 'flags104', 'busy', 'clock', 'complete', 'animation', 'weapon', 'event', 'guards', 'events', 'score', 'teams', 'counters', 'radio', 'marker', 'event_record', 'lookups', 'distances', 'missing']},rust=result(binary,'complete',encode(p['input']))))
|
| 13 |
+
write_json(Path('docs/research/rust-effect-defuse-complete.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 |
+
from analyze_rust_defuse_complete import encode as base_encode
|
| 16 |
+
def encode(a):
|
| 17 |
+
payload=bytes.fromhex(a['payload'])
|
| 18 |
+
return base_encode(a)+[a['paused'],a['constructed'],a['marker'],a['success'],len(payload),*payload]
|
| 19 |
+
if __name__=='__main__':main()
|
scripts/test_rust_effect_defuse_complete.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-effect-defuse-complete.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-effect-defuse-complete.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
|
@@ -4482,3 +4482,40 @@ report scripts/analyze_qvm_effect_defuse_complete.py docs/research/qvm-effect-de
|
|
| 4482 |
edge docs/research/qvm-effect-defuse-complete.json scripts/test_qvm_effect_defuse_complete.py
|
| 4483 |
group qvm-effect-defuse-complete scripts/analyze_qvm_effect_defuse_complete.py
|
| 4484 |
edge scripts/analyze_qvm_effect_defuse_complete.py scripts/analyze_qvm_resumer_audit.py
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4482 |
edge docs/research/qvm-effect-defuse-complete.json scripts/test_qvm_effect_defuse_complete.py
|
| 4483 |
group qvm-effect-defuse-complete scripts/analyze_qvm_effect_defuse_complete.py
|
| 4484 |
edge scripts/analyze_qvm_effect_defuse_complete.py scripts/analyze_qvm_resumer_audit.py
|
| 4485 |
+
report scripts/analyze_rust_effect_defuse_complete.py docs/research/rust-effect-defuse-complete.json
|
| 4486 |
+
edge docs/research/rust-effect-defuse-complete.json scripts/test_rust_effect_defuse_complete.py
|
| 4487 |
+
group rust-effect-defuse-complete scripts/analyze_rust_effect_defuse_complete.py
|
| 4488 |
+
edge scripts/analyze_rust_effect_defuse_complete.py scripts/analyze_qvm_resumer_audit.py
|
| 4489 |
+
edge Cargo.toml scripts/analyze_rust_effect_defuse_complete.py
|
| 4490 |
+
edge Cargo.lock scripts/analyze_rust_effect_defuse_complete.py
|
| 4491 |
+
edge crates/urt-gameplay/Cargo.toml scripts/analyze_rust_effect_defuse_complete.py
|
| 4492 |
+
edge crates/urt-gameplay/src/lib.rs scripts/analyze_rust_effect_defuse_complete.py
|
| 4493 |
+
edge crates/urt-gameplay/src/filter_loading.rs scripts/analyze_rust_effect_defuse_complete.py
|
| 4494 |
+
edge crates/urt-gameplay/src/filter_lifecycle.rs scripts/analyze_rust_effect_defuse_complete.py
|
| 4495 |
+
edge crates/urt-gameplay/src/native_policy.rs scripts/analyze_rust_effect_defuse_complete.py
|
| 4496 |
+
edge crates/urt-gameplay/src/bin/urt-filter-loading.rs scripts/analyze_rust_effect_defuse_complete.py
|
| 4497 |
+
edge crates/urt-gameplay/src/qvm_format.rs scripts/analyze_rust_effect_defuse_complete.py
|
| 4498 |
+
edge docs/research/qvm-effect-defuse-complete.json scripts/analyze_rust_effect_defuse_complete.py
|
| 4499 |
+
group rust-effect-defuse-complete scripts/analyze_rust_health_impulse.py
|
| 4500 |
+
group gameplay scripts/analyze_rust_effect_defuse_complete.py
|
| 4501 |
+
edge crates/urt-gameplay/src/filter_commands.rs scripts/analyze_rust_effect_defuse_complete.py
|
| 4502 |
+
edge crates/urt-gameplay/src/bin/urt-filter-commands.rs scripts/analyze_rust_effect_defuse_complete.py
|
| 4503 |
+
edge crates/urt-gameplay/src/client_timer.rs scripts/analyze_rust_effect_defuse_complete.py
|
| 4504 |
+
edge crates/urt-gameplay/src/bin/urt-client-timer.rs scripts/analyze_rust_effect_defuse_complete.py
|
| 4505 |
+
edge crates/urt-gameplay/src/client_processing.rs scripts/analyze_rust_effect_defuse_complete.py
|
| 4506 |
+
edge crates/urt-gameplay/src/bin/urt-client-processing.rs scripts/analyze_rust_effect_defuse_complete.py
|
| 4507 |
+
edge crates/urt-gameplay/src/client_move_context.rs scripts/analyze_rust_effect_defuse_complete.py
|
| 4508 |
+
edge crates/urt-gameplay/src/bin/urt-client-move-context.rs scripts/analyze_rust_effect_defuse_complete.py
|
| 4509 |
+
edge crates/urt-gameplay/src/move_callbacks.rs scripts/analyze_rust_effect_defuse_complete.py
|
| 4510 |
+
edge crates/urt-gameplay/src/bin/urt-move-callbacks.rs scripts/analyze_rust_effect_defuse_complete.py
|
| 4511 |
+
edge crates/urt-gameplay/src/assistance.rs scripts/analyze_rust_effect_defuse_complete.py
|
| 4512 |
+
edge crates/urt-gameplay/src/bin/urt-assistance.rs scripts/analyze_rust_effect_defuse_complete.py
|
| 4513 |
+
edge crates/urt-gameplay/src/move_callbacks.rs scripts/analyze_rust_effect_defuse_complete.py
|
| 4514 |
+
edge crates/urt-gameplay/src/defuse.rs scripts/analyze_rust_effect_defuse_complete.py
|
| 4515 |
+
edge crates/urt-gameplay/src/bin/urt-defuse.rs scripts/analyze_rust_effect_defuse_complete.py
|
| 4516 |
+
edge crates/urt-gameplay/src/move_callbacks.rs scripts/analyze_rust_effect_defuse_complete.py
|
| 4517 |
+
edge crates/urt-gameplay/src/effect_feedback.rs scripts/analyze_rust_effect_defuse_complete.py
|
| 4518 |
+
edge crates/urt-gameplay/src/bin/urt-effect-feedback.rs scripts/analyze_rust_effect_defuse_complete.py
|
| 4519 |
+
edge crates/urt-gameplay/src/score.rs scripts/analyze_rust_effect_defuse_complete.py
|
| 4520 |
+
edge crates/urt-gameplay/src/transition.rs scripts/analyze_rust_effect_defuse_complete.py
|
| 4521 |
+
edge crates/urt-gameplay/src/defuse.rs scripts/analyze_rust_effect_defuse_complete.py
|
xtask/src/lib.rs
CHANGED
|
@@ -1174,6 +1174,10 @@ mod integration_tests {
|
|
| 1174 |
("effect_feedback", "effect_defuse_begin"),
|
| 1175 |
("score", "effect_defuse_begin"),
|
| 1176 |
("transition", "effect_defuse_begin"),
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1177 |
("client_move_context", "client_move_scratch"),
|
| 1178 |
("client_processing", "client_routing"),
|
| 1179 |
("client_timer", "client_routing"),
|
|
@@ -1411,6 +1415,7 @@ mod integration_tests {
|
|
| 1411 |
("qvm-effect-radio", "effect_radio"),
|
| 1412 |
("qvm-effect-defuse-finish", "effect_defuse_finish"),
|
| 1413 |
("qvm-effect-defuse-begin", "effect_defuse_begin"),
|
|
|
|
| 1414 |
("qvm-client-move-scratch", "client_move_scratch"),
|
| 1415 |
("qvm-client-routing", "client_routing"),
|
| 1416 |
("qvm-client-command-rewrite", "client_command_rewrite"),
|
|
|
|
| 1174 |
("effect_feedback", "effect_defuse_begin"),
|
| 1175 |
("score", "effect_defuse_begin"),
|
| 1176 |
("transition", "effect_defuse_begin"),
|
| 1177 |
+
("effect_feedback", "effect_defuse_complete"),
|
| 1178 |
+
("defuse", "effect_defuse_complete"),
|
| 1179 |
+
("score", "effect_defuse_complete"),
|
| 1180 |
+
("transition", "effect_defuse_complete"),
|
| 1181 |
("client_move_context", "client_move_scratch"),
|
| 1182 |
("client_processing", "client_routing"),
|
| 1183 |
("client_timer", "client_routing"),
|
|
|
|
| 1415 |
("qvm-effect-radio", "effect_radio"),
|
| 1416 |
("qvm-effect-defuse-finish", "effect_defuse_finish"),
|
| 1417 |
("qvm-effect-defuse-begin", "effect_defuse_begin"),
|
| 1418 |
+
("qvm-effect-defuse-complete", "effect_defuse_complete"),
|
| 1419 |
("qvm-client-move-scratch", "client_move_scratch"),
|
| 1420 |
("qvm-client-routing", "client_routing"),
|
| 1421 |
("qvm-client-command-rewrite", "client_command_rewrite"),
|