nmarshall commited on
Commit
b658af6
·
1 Parent(s): aafc848

gameplay: port connect completion callback order

Browse files
crates/urt-gameplay/src/bin/urt-native-policy.rs CHANGED
@@ -843,6 +843,36 @@ fn run() -> Result<String, String> {
843
  .map_err(|e| format!("{e:?}"))?;
844
  Ok(admission_json(&out, ring))
845
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
846
  _ => Err("unknown command".into()),
847
  }
848
  }
@@ -1167,3 +1197,64 @@ fn admission_json(out: &Admission, ring: u32) -> String {
1167
  out.accepted
1168
  )
1169
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
843
  .map_err(|e| format!("{e:?}"))?;
844
  Ok(admission_json(&out, ring))
845
  }
846
+ "connect-tail" => {
847
+ if w.len() != 8 {
848
+ return Err("invalid tail words".into());
849
+ }
850
+ let mut client = 0xaabbccddu32.to_le_bytes().repeat(1584);
851
+ client[3096..3100].copy_from_slice(&w[1].to_le_bytes());
852
+ client[504..516].fill(0);
853
+ client[504..507].copy_from_slice(b"old");
854
+ let mut entity = ConnectTailEntity {
855
+ flags: 32,
856
+ in_use: 0,
857
+ };
858
+ let out = finish_connect(
859
+ &mut client,
860
+ &mut entity,
861
+ ConnectTailInput {
862
+ mode: w[0] as i32,
863
+ slot: 3,
864
+ first_time: w[3] as i32,
865
+ bot: w[2] as i32,
866
+ bot_answer: w[4] as i32,
867
+ clock: w[6] as i32,
868
+ seconds: w[7] as i32,
869
+ after_team: if w[5] != 0 { Some(2) } else { None },
870
+ name: b"new^1name",
871
+ },
872
+ )
873
+ .map_err(|e| format!("{e:?}"))?;
874
+ Ok(tail_json(&out, &client, &entity))
875
+ }
876
  _ => Err("unknown command".into()),
877
  }
878
  }
 
1197
  out.accepted
1198
  )
1199
  }
1200
+
1201
+ fn tail_events(events: &[ConnectTailEvent]) -> String {
1202
+ format!(
1203
+ "[{}]",
1204
+ events
1205
+ .iter()
1206
+ .map(|e| match e {
1207
+ ConnectTailEvent::Classify(mode) => format!(r#"{{"op":"classify","mode":{mode}}}"#),
1208
+ ConnectTailEvent::Bot { slot, restart } => format!(
1209
+ r#"{{"op":"bot","slot":{slot},"restart":{}}}"#,
1210
+ u32::from(*restart)
1211
+ ),
1212
+ ConnectTailEvent::Zero { offset, length } =>
1213
+ format!(r#"{{"op":"zero","offset":{offset},"length":{length}}}"#),
1214
+ ConnectTailEvent::Log(slot) => format!(r#"{{"op":"log","slot":{slot}}}"#),
1215
+ ConnectTailEvent::Userinfo(slot) => format!(r#"{{"op":"userinfo","slot":{slot}}}"#),
1216
+ ConnectTailEvent::Format => r#"{"op":"format"}"#.into(),
1217
+ ConnectTailEvent::Send { recipient, text } => format!(
1218
+ r#"{{"op":"send","recipient":{recipient},"text":"{}"}}"#,
1219
+ hex(text)
1220
+ ),
1221
+ ConnectTailEvent::Join { slot, choice } =>
1222
+ format!(r#"{{"op":"join","slot":{slot},"choice":{choice}}}"#),
1223
+ ConnectTailEvent::Rank => r#"{"op":"rank"}"#.into(),
1224
+ })
1225
+ .collect::<Vec<_>>()
1226
+ .join(",")
1227
+ )
1228
+ }
1229
+ fn watched_words(client: &[u8]) -> String {
1230
+ let mut offsets = vec![504, 508, 512, 516, 3096, 3140];
1231
+ offsets.extend((668..696).step_by(4));
1232
+ offsets.extend((3204..3592).step_by(4));
1233
+ format!(
1234
+ "{{{}}}",
1235
+ offsets
1236
+ .iter()
1237
+ .map(|o| format!(
1238
+ r#""{o}":{}"#,
1239
+ u32::from_le_bytes(client[*o..*o + 4].try_into().unwrap())
1240
+ ))
1241
+ .collect::<Vec<_>>()
1242
+ .join(",")
1243
+ )
1244
+ }
1245
+ fn tail_json(out: &ConnectTail, client: &[u8], entity: &ConnectTailEntity) -> String {
1246
+ let msg = out
1247
+ .message
1248
+ .as_ref()
1249
+ .map(|v| format!(r#""{}""#, hex(v)))
1250
+ .unwrap_or("null".into());
1251
+ format!(
1252
+ r#"{{"accepted":{},"message":{msg},"events":{},"words":{},"entity_flags":{},"in_use":{},"ring":{}}}"#,
1253
+ out.accepted,
1254
+ tail_events(&out.events),
1255
+ watched_words(client),
1256
+ entity.flags,
1257
+ entity.in_use as u32,
1258
+ out.ring_advance
1259
+ )
1260
+ }
crates/urt-gameplay/src/native_policy.rs CHANGED
@@ -2319,3 +2319,199 @@ mod admission_tests {
2319
  assert_eq!(r, 1);
2320
  }
2321
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2319
  assert_eq!(r, 1);
2320
  }
2321
  }
2322
+
2323
+ #[derive(Clone, Debug, PartialEq, Eq)]
2324
+ pub struct ConnectTailEntity {
2325
+ pub flags: u32,
2326
+ pub in_use: i32,
2327
+ }
2328
+ pub struct ConnectTailInput<'a> {
2329
+ pub mode: i32,
2330
+ pub slot: usize,
2331
+ pub first_time: i32,
2332
+ pub bot: i32,
2333
+ pub bot_answer: i32,
2334
+ pub clock: i32,
2335
+ pub seconds: i32,
2336
+ pub after_team: Option<i32>,
2337
+ pub name: &'a [u8],
2338
+ }
2339
+ #[derive(Clone, Debug, PartialEq, Eq)]
2340
+ pub enum ConnectTailEvent {
2341
+ Classify(i32),
2342
+ Bot { slot: usize, restart: bool },
2343
+ Zero { offset: usize, length: usize },
2344
+ Log(usize),
2345
+ Userinfo(usize),
2346
+ Format,
2347
+ Send { recipient: i32, text: Vec<u8> },
2348
+ Join { slot: usize, choice: i32 },
2349
+ Rank,
2350
+ }
2351
+ #[derive(Clone, Debug, PartialEq, Eq)]
2352
+ pub struct ConnectTail {
2353
+ pub accepted: bool,
2354
+ pub message: Option<Vec<u8>>,
2355
+ pub events: Vec<ConnectTailEvent>,
2356
+ pub ring_advance: u32,
2357
+ }
2358
+ /// Original173979 suffix with supplied bot/userinfo answers and captured jobs.
2359
+ /// Bot rejection preserves mutations that precede that return in the source.
2360
+ pub fn finish_connect(
2361
+ client: &mut [u8],
2362
+ entity: &mut ConnectTailEntity,
2363
+ input: ConnectTailInput<'_>,
2364
+ ) -> Result<ConnectTail, Error> {
2365
+ if client.len() != CLIENT_BYTES || input.slot >= 64 || cbytes(input.name).len() >= 128 {
2366
+ return Err(Error::InvalidInput);
2367
+ }
2368
+ let mut bytes = client.to_vec();
2369
+ let mut e = entity.clone();
2370
+ let mut out = ConnectTail {
2371
+ accepted: true,
2372
+ message: None,
2373
+ events: vec![ConnectTailEvent::Classify(input.mode)],
2374
+ ring_advance: 0,
2375
+ };
2376
+ let mut team = raw_word(&bytes, 3096);
2377
+ team = if crate::intermission::team_mode(input.mode) {
2378
+ if team == 0 { 3 } else { team }
2379
+ } else {
2380
+ if team == 3 { 3 } else { 0 }
2381
+ };
2382
+ raw_store(&mut bytes, 3096, team);
2383
+ if input.bot != 0 {
2384
+ e.flags |= 8;
2385
+ e.in_use = 1;
2386
+ out.events.push(ConnectTailEvent::Bot {
2387
+ slot: input.slot,
2388
+ restart: input.first_time == 0,
2389
+ });
2390
+ if input.bot_answer == 0 {
2391
+ out.accepted = false;
2392
+ out.message = Some(b"BotConnectfailed".to_vec());
2393
+ client.copy_from_slice(&bytes);
2394
+ *entity = e;
2395
+ return Ok(out);
2396
+ }
2397
+ }
2398
+ if input.first_time != 0 {
2399
+ bytes[668..696].fill(0);
2400
+ raw_store(
2401
+ &mut bytes,
2402
+ 3140,
2403
+ input.clock.wrapping_add(input.seconds.wrapping_mul(1000)) as u32,
2404
+ );
2405
+ out.events.push(ConnectTailEvent::Zero {
2406
+ offset: 668,
2407
+ length: 28,
2408
+ });
2409
+ }
2410
+ out.events.push(ConnectTailEvent::Log(input.slot));
2411
+ if input.first_time != 0 {
2412
+ raw_store(&mut bytes, 3588, 0);
2413
+ bytes[3204..3332].fill(0);
2414
+ bytes[3332..3588].fill(0);
2415
+ out.events.extend([
2416
+ ConnectTailEvent::Zero {
2417
+ offset: 3204,
2418
+ length: 128,
2419
+ },
2420
+ ConnectTailEvent::Zero {
2421
+ offset: 3332,
2422
+ length: 256,
2423
+ },
2424
+ ]);
2425
+ }
2426
+ out.events.push(ConnectTailEvent::Userinfo(input.slot));
2427
+ if let Some(team) = input.after_team {
2428
+ raw_store(&mut bytes, 3096, team as u32);
2429
+ }
2430
+ let name = cbytes(input.name);
2431
+ bytes[504..504 + name.len()].copy_from_slice(name);
2432
+ bytes[504 + name.len()] = 0;
2433
+ if input.first_time != 0 {
2434
+ let text = crate::qvm_format::render(
2435
+ b"print \"%s^7 connected\n\"",
2436
+ &[crate::qvm_format::Argument::Bytes(Some(name))],
2437
+ )
2438
+ .map_err(|_| Error::InvalidInput)?;
2439
+ let text = cbytes(&text).to_vec();
2440
+ out.events.extend([
2441
+ ConnectTailEvent::Format,
2442
+ ConnectTailEvent::Send {
2443
+ recipient: -1,
2444
+ text,
2445
+ },
2446
+ ]);
2447
+ out.ring_advance = 1;
2448
+ }
2449
+ out.events.push(ConnectTailEvent::Classify(input.mode));
2450
+ if crate::intermission::team_mode(input.mode) && raw_word(&bytes, 3096) != 3 {
2451
+ out.events.push(ConnectTailEvent::Join {
2452
+ slot: input.slot,
2453
+ choice: -1,
2454
+ });
2455
+ }
2456
+ out.events.push(ConnectTailEvent::Rank);
2457
+ client.copy_from_slice(&bytes);
2458
+ *entity = e;
2459
+ Ok(out)
2460
+ }
2461
+ #[cfg(test)]
2462
+ mod connect_tail_tests {
2463
+ use super::*;
2464
+ #[test]
2465
+ fn bot_reject_keeps_prior_flags_and_team_change() {
2466
+ let mut raw = vec![0; CLIENT_BYTES];
2467
+ let mut e = ConnectTailEntity {
2468
+ flags: 32,
2469
+ in_use: 0,
2470
+ };
2471
+ let out = finish_connect(
2472
+ &mut raw,
2473
+ &mut e,
2474
+ ConnectTailInput {
2475
+ mode: 3,
2476
+ slot: 0,
2477
+ first_time: 1,
2478
+ bot: 1,
2479
+ bot_answer: 0,
2480
+ clock: 100,
2481
+ seconds: 0,
2482
+ after_team: Some(2),
2483
+ name: b"new",
2484
+ },
2485
+ )
2486
+ .unwrap();
2487
+ assert!(!out.accepted);
2488
+ assert_eq!(raw_word(&raw, 3096), 3);
2489
+ assert_eq!(e.flags, 40);
2490
+ assert_eq!(out.events.len(), 2);
2491
+ }
2492
+ #[test]
2493
+ fn first_time_zero_seconds_has_no_initializer_default() {
2494
+ let mut raw = vec![0; CLIENT_BYTES];
2495
+ let mut e = ConnectTailEntity {
2496
+ flags: 0,
2497
+ in_use: 0,
2498
+ };
2499
+ finish_connect(
2500
+ &mut raw,
2501
+ &mut e,
2502
+ ConnectTailInput {
2503
+ mode: 0,
2504
+ slot: 0,
2505
+ first_time: 1,
2506
+ bot: 0,
2507
+ bot_answer: 1,
2508
+ clock: 100,
2509
+ seconds: 0,
2510
+ after_team: None,
2511
+ name: b"new",
2512
+ },
2513
+ )
2514
+ .unwrap();
2515
+ assert_eq!(raw_word(&raw, 3140), 100);
2516
+ }
2517
+ }
docs/FINDINGS.md CHANGED
@@ -1760,3 +1760,6 @@ RE-813–822 replaces the scoreboard decimal assumption with actual37914 executi
1760
 
1761
 
1762
  **RE-920:** 144 actual173979 suffix cases execute original mode classification and broadcast formatting with explicit bot/userinfo answers. Team normalization precedes bot flags/admission; failed bots return after those mutations. First-time paths clear selected ranges and overwrite timeout without the initializer60-second default. Updated userinfo/name precedes broadcast and a second team decision; ranking is requested last. Bot, userinfo, join, ranking, logs/network and native memset remain supplied/captured/modeled boundaries. [Evidence](research/QVM_CONNECT_TAIL.md).
 
 
 
 
1760
 
1761
 
1762
  **RE-920:** 144 actual173979 suffix cases execute original mode classification and broadcast formatting with explicit bot/userinfo answers. Team normalization precedes bot flags/admission; failed bots return after those mutations. First-time paths clear selected ranges and overwrite timeout without the initializer60-second default. Updated userinfo/name precedes broadcast and a second team decision; ranking is requested last. Bot, userinfo, join, ranking, logs/network and native memset remain supplied/captured/modeled boundaries. [Evidence](research/QVM_CONNECT_TAIL.md).
1763
+
1764
+
1765
+ **RE-921:** Rust matches144 original173979 suffix cases with ordered bot admission, first-time clears, timeout wrapping, supplied userinfo changes, original broadcast bytes, team callback and ranking intentions. Bot rejection retains prior team/flag mutations. Native callbacks/logging/network/ranking and real caller acceptance remain open. [Evidence](research/RUST_CONNECT_TAIL.md).
docs/PROVISIONAL_TODO.md CHANGED
@@ -1800,3 +1800,6 @@ RE-919: Rust matches160 original173979 admission prefixes, preserving bot bypass
1800
 
1801
 
1802
  RE-920: 144 actual173979 suffix cases execute original mode classification and broadcast formatting with explicit bot/userinfo answers. Team normalization precedes bot flags/admission; failed bots return after those mutations. First-time paths clear selected ranges and overwrite timeout without the initializer60-second default. Updated userinfo/name precedes broadcast and a second team decision; ranking is requested last. Bot, userinfo, join, ranking, logs/network and native memset remain supplied/captured/modeled boundaries. Full runtime completion remains open. [Evidence](research/QVM_CONNECT_TAIL.md).
 
 
 
 
1800
 
1801
 
1802
  RE-920: 144 actual173979 suffix cases execute original mode classification and broadcast formatting with explicit bot/userinfo answers. Team normalization precedes bot flags/admission; failed bots return after those mutations. First-time paths clear selected ranges and overwrite timeout without the initializer60-second default. Updated userinfo/name precedes broadcast and a second team decision; ranking is requested last. Bot, userinfo, join, ranking, logs/network and native memset remain supplied/captured/modeled boundaries. Full runtime completion remains open. [Evidence](research/QVM_CONNECT_TAIL.md).
1803
+
1804
+
1805
+ RE-921: Rust matches144 original173979 suffix cases with ordered bot admission, first-time clears, timeout wrapping, supplied userinfo changes, original broadcast bytes, team callback and ranking intentions. Bot rejection retains prior team/flag mutations. Native callbacks/logging/network/ranking and real caller acceptance remain open. Full runtime completion remains open. [Evidence](research/RUST_CONNECT_TAIL.md).
docs/RESEARCH_LEDGER.md CHANGED
@@ -2325,3 +2325,8 @@ Rust matches160 original173979 admission prefixes, preserving bot bypass, addres
2325
  ## 2026-10-28 — RE-920 Original post-session connect normalization and callbacks
2326
 
2327
  144 actual173979 suffix cases execute original mode classification and broadcast formatting with explicit bot/userinfo answers. Team normalization precedes bot flags/admission; failed bots return after those mutations. First-time paths clear selected ranges and overwrite timeout without the initializer60-second default. Updated userinfo/name precedes broadcast and a second team decision; ranking is requested last. Bot, userinfo, join, ranking, logs/network and native memset remain supplied/captured/modeled boundaries. Focused `cargo xtask test-group qvm-connect-tail` 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.
 
 
 
 
 
 
2325
  ## 2026-10-28 — RE-920 Original post-session connect normalization and callbacks
2326
 
2327
  144 actual173979 suffix cases execute original mode classification and broadcast formatting with explicit bot/userinfo answers. Team normalization precedes bot flags/admission; failed bots return after those mutations. First-time paths clear selected ranges and overwrite timeout without the initializer60-second default. Updated userinfo/name precedes broadcast and a second team decision; ranking is requested last. Bot, userinfo, join, ranking, logs/network and native memset remain supplied/captured/modeled boundaries. Focused `cargo xtask test-group qvm-connect-tail` 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.
2328
+
2329
+
2330
+ ## 2026-10-28 — RE-921 Rust post-session connect callbacks and normalization
2331
+
2332
+ Rust matches144 original173979 suffix cases with ordered bot admission, first-time clears, timeout wrapping, supplied userinfo changes, original broadcast bytes, team callback and ranking intentions. Bot rejection retains prior team/flag mutations. Native callbacks/logging/network/ranking and real caller acceptance remain open. Focused `cargo xtask test-group rust-connect-tail` 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
@@ -1837,3 +1837,6 @@ Purpose: turn the supplied installation into an evidence-backed specification of
1837
 
1838
 
1839
  - [x] RE-920 Original post-session connect normalization and callbacks ([evidence](research/QVM_CONNECT_TAIL.md)).
 
 
 
 
1837
 
1838
 
1839
  - [x] RE-920 Original post-session connect normalization and callbacks ([evidence](research/QVM_CONNECT_TAIL.md)).
1840
+
1841
+
1842
+ - [x] RE-921 Rust post-session connect callbacks and normalization ([evidence](research/RUST_CONNECT_TAIL.md)).
docs/research/README.md CHANGED
@@ -1372,3 +1372,6 @@ The extension collector adds five focused tests for native tail calls, command-r
1372
 
1373
 
1374
  [RE-920: Original post-session connect normalization and callbacks](QVM_CONNECT_TAIL.md).
 
 
 
 
1372
 
1373
 
1374
  [RE-920: Original post-session connect normalization and callbacks](QVM_CONNECT_TAIL.md).
1375
+
1376
+
1377
+ [RE-921: Rust post-session connect callbacks and normalization](RUST_CONNECT_TAIL.md).
docs/research/RUST_CONNECT_TAIL.md ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ # Rust post-session connect callbacks and normalization
2
+
3
+ RE-921. Reproduce with `python3 scripts/analyze_rust_connect_tail.py`; focused validation: `cargo xtask test-group rust-connect-tail`. [Machine report](rust-connect-tail.json).
4
+
5
+ Rust matches144 original173979 suffix cases with ordered bot admission, first-time clears, timeout wrapping, supplied userinfo changes, original broadcast bytes, team callback and ranking intentions. Bot rejection retains prior team/flag mutations. Native callbacks/logging/network/ranking and real caller acceptance remain open.
6
+
7
+ Original executable/native runtime and complete Linux/macOS Rust/Bevy/Solari acceptance remain unverified.
docs/research/rust-connect-tail.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": 173,
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": 175,
2989
  "source_report": "docs/research/qvm-health-impulse.json",
2990
  "source_report_sha256": "625fd8064004ea6dbdf398d51d0af844d9c635ff04c0a0790886dddb6ab81e71"
2991
  }
scripts/analyze_rust_connect_tail.py ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 encode(s):
7
+ a=s['input'];return [a[k] for k in ['mode','team','bot','first','answer','changed','now','seconds']]
8
+ def project(s):return {k:s[k] for k in ['accepted','message','events','words','entity_flags','in_use','ring']}
9
+
10
+ def main():
11
+ b=binary();p=Path('docs/research/qvm-connect-tail.json');data=p.read_bytes();rows=[]
12
+ for s in json.loads(data)['probes']:rows.append({'source':project(s),'rust':result(b,'connect-tail',encode(s))})
13
+ write_json(Path('docs/research/rust-connect-tail.json'),{'source_report':str(p),'source_report_sha256':hashlib.sha256(data).hexdigest(),'probes':rows,'limits':'Rust matches144 original173979 suffix cases with ordered bot admission, first-time clears, timeout wrapping, supplied userinfo changes, original broadcast bytes, team callback and ranking intentions. Bot rejection retains prior team/flag mutations. Native callbacks/logging/network/ranking and real caller acceptance remain open.'})
14
+ if __name__=='__main__':main()
scripts/test_rust_connect_tail.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-connect-tail.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-connect-tail.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
@@ -2966,3 +2966,18 @@ edge docs/research/qvm-connect-tail.json scripts/test_qvm_connect_tail.py
2966
  group qvm-connect-tail scripts/analyze_qvm_connect_tail.py
2967
  edge scripts/analyze_qvm_connect_tail.py scripts/analyze_qvm_resumer_audit.py
2968
  edge scripts/qvm_connect_tail_oracle.py scripts/analyze_qvm_resumer_audit.py
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2966
  group qvm-connect-tail scripts/analyze_qvm_connect_tail.py
2967
  edge scripts/analyze_qvm_connect_tail.py scripts/analyze_qvm_resumer_audit.py
2968
  edge scripts/qvm_connect_tail_oracle.py scripts/analyze_qvm_resumer_audit.py
2969
+ edge Cargo.toml scripts/analyze_rust_connect_tail.py
2970
+ edge Cargo.lock scripts/analyze_rust_connect_tail.py
2971
+ edge crates/urt-gameplay/Cargo.toml scripts/analyze_rust_connect_tail.py
2972
+ edge crates/urt-gameplay/src/lib.rs scripts/analyze_rust_connect_tail.py
2973
+ edge crates/urt-gameplay/src/native_policy.rs scripts/analyze_rust_connect_tail.py
2974
+ edge crates/urt-gameplay/src/bin/urt-native-policy.rs scripts/analyze_rust_connect_tail.py
2975
+ edge docs/research/qvm-connect-tail.json scripts/analyze_rust_connect_tail.py
2976
+ group rust-connect-tail scripts/analyze_rust_health_impulse.py
2977
+ group gameplay scripts/analyze_rust_connect_tail.py
2978
+ edge crates/urt-gameplay/src/intermission.rs scripts/analyze_rust_connect_tail.py
2979
+ edge crates/urt-gameplay/src/qvm_format.rs scripts/analyze_rust_connect_tail.py
2980
+ report scripts/analyze_rust_connect_tail.py docs/research/rust-connect-tail.json
2981
+ edge docs/research/rust-connect-tail.json scripts/test_rust_connect_tail.py
2982
+ group rust-connect-tail scripts/analyze_rust_connect_tail.py
2983
+ edge scripts/analyze_rust_connect_tail.py scripts/analyze_qvm_resumer_audit.py