gameplay: integrate connect session lifecycle branch
Browse files- crates/urt-gameplay/src/bin/urt-native-policy.rs +60 -0
- crates/urt-gameplay/src/native_policy.rs +198 -0
- docs/FINDINGS.md +3 -0
- docs/PROVISIONAL_TODO.md +6 -0
- docs/RESEARCH_LEDGER.md +10 -0
- docs/REVERSE_ENGINEERING_TODO.md +7 -1
- docs/TESTING.md +3 -0
- docs/research/QVM_SAVED_RESTORE_BATCH.md +3 -1
- docs/research/QVM_SESSION_LIFECYCLE_BATCH.md +55 -0
- docs/research/README.md +6 -0
- docs/research/RUST_CONNECT_SESSION.md +7 -0
- docs/research/qvm-resumer-audit.json +15 -4
- docs/research/qvm-session-init.json +0 -0
- docs/research/rust-connect-session.json +0 -0
- docs/research/rust-health-impulse.json +1 -1
- docs/research/rust-session-init.json +0 -0
- scripts/analyze_qvm_connect_session.py +1 -1
- scripts/analyze_qvm_normal_map_files.py +1 -1
- scripts/analyze_qvm_post_map_files.py +1 -1
- scripts/analyze_qvm_session_init.py +2 -2
- scripts/analyze_rust_connect_session.py +14 -0
- scripts/qvm_lifecycle_support.py +36 -48
- scripts/qvm_session_lifecycle_support.py +52 -0
- scripts/test_qvm_session_init.py +1 -0
- scripts/test_rust_connect_session.py +9 -0
- xtask/checks.tsv +18 -0
- xtask/src/lib.rs +17 -0
crates/urt-gameplay/src/bin/urt-native-policy.rs
CHANGED
|
@@ -713,6 +713,66 @@ fn run() -> Result<String, String> {
|
|
| 713 |
out.ring_advance
|
| 714 |
))
|
| 715 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 716 |
_ => Err("unknown command".into()),
|
| 717 |
}
|
| 718 |
}
|
|
|
|
| 713 |
out.ring_advance
|
| 714 |
))
|
| 715 |
}
|
| 716 |
+
"connect-session" => {
|
| 717 |
+
if w.len() != 6 {
|
| 718 |
+
return Err("invalid connect header".into());
|
| 719 |
+
}
|
| 720 |
+
let mut client = vec![0xdd; CLIENT_BYTES];
|
| 721 |
+
let mut entity = ConnectEntity {
|
| 722 |
+
linked_slot: None,
|
| 723 |
+
field764: 0xaabbccdd,
|
| 724 |
+
field768: 0xaabbccdd,
|
| 725 |
+
};
|
| 726 |
+
let mut selector = 0;
|
| 727 |
+
let out = connect_session(
|
| 728 |
+
&mut client,
|
| 729 |
+
&mut entity,
|
| 730 |
+
ConnectInput {
|
| 731 |
+
first_time: w[1] as i32,
|
| 732 |
+
new_session: w[2] as i32,
|
| 733 |
+
flags: 1,
|
| 734 |
+
initialize: InitializeInput {
|
| 735 |
+
mode: w[0] as i32,
|
| 736 |
+
slot: w[4] as usize,
|
| 737 |
+
userinfo: b"\\team\\S\\cl_guid\\ID",
|
| 738 |
+
limit: 2,
|
| 739 |
+
occupancy: 1,
|
| 740 |
+
seconds: 0,
|
| 741 |
+
clock: 100,
|
| 742 |
+
ticks: 17,
|
| 743 |
+
handle: w[5],
|
| 744 |
+
client_id: 999,
|
| 745 |
+
enabled: 1,
|
| 746 |
+
mapname: b"ut4_test",
|
| 747 |
+
file_length: 11,
|
| 748 |
+
file_data: b"9,8,7,6,5,4",
|
| 749 |
+
},
|
| 750 |
+
session: b"1,-2,3,4,5,1,1,1,1",
|
| 751 |
+
ignore_text: b"1,3,",
|
| 752 |
+
scratch: [w[3]; 5],
|
| 753 |
+
},
|
| 754 |
+
&mut selector,
|
| 755 |
+
)
|
| 756 |
+
.map_err(|e| format!("{e:?}"))?;
|
| 757 |
+
let nonzero = client
|
| 758 |
+
.chunks_exact(4)
|
| 759 |
+
.enumerate()
|
| 760 |
+
.filter_map(|(j, b)| {
|
| 761 |
+
let v = u32::from_le_bytes(b.try_into().unwrap());
|
| 762 |
+
(v != 0).then_some(vec![4 * j as u32, v])
|
| 763 |
+
})
|
| 764 |
+
.collect::<Vec<_>>();
|
| 765 |
+
Ok(format!(
|
| 766 |
+
"{{\"raw\":\"{}\",\"nonzero\":{},\"choice\":[{}],\"entity_linked\":{},\"entity_clear\":[{},{}],\"ring\":{},\"info_ring\":{selector}}}",
|
| 767 |
+
hex(&client[3096..3096 + SESSION_BYTES]),
|
| 768 |
+
nested(&nonzero),
|
| 769 |
+
if out.fresh { 247520 } else { 247219 },
|
| 770 |
+
entity.linked_slot == Some(w[4] as usize),
|
| 771 |
+
entity.field764,
|
| 772 |
+
entity.field768,
|
| 773 |
+
out.ring_advance
|
| 774 |
+
))
|
| 775 |
+
}
|
| 776 |
_ => Err("unknown command".into()),
|
| 777 |
}
|
| 778 |
}
|
crates/urt-gameplay/src/native_policy.rs
CHANGED
|
@@ -1894,3 +1894,201 @@ mod memory_persistence_tests {
|
|
| 1894 |
assert_eq!(selector, 0);
|
| 1895 |
}
|
| 1896 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1894 |
assert_eq!(selector, 0);
|
| 1895 |
}
|
| 1896 |
}
|
| 1897 |
+
|
| 1898 |
+
pub const CLIENT_BYTES: usize = 6336;
|
| 1899 |
+
#[derive(Clone, Debug, PartialEq, Eq)]
|
| 1900 |
+
pub struct ConnectEntity {
|
| 1901 |
+
pub linked_slot: Option<usize>,
|
| 1902 |
+
pub field764: u32,
|
| 1903 |
+
pub field768: u32,
|
| 1904 |
+
}
|
| 1905 |
+
pub struct ConnectInput<'a> {
|
| 1906 |
+
pub first_time: i32,
|
| 1907 |
+
pub new_session: i32,
|
| 1908 |
+
pub flags: u32,
|
| 1909 |
+
pub initialize: InitializeInput<'a>,
|
| 1910 |
+
pub session: &'a [u8],
|
| 1911 |
+
pub ignore_text: &'a [u8],
|
| 1912 |
+
pub scratch: [u32; 5],
|
| 1913 |
+
}
|
| 1914 |
+
#[derive(Clone, Debug, PartialEq, Eq)]
|
| 1915 |
+
pub struct ConnectedSession {
|
| 1916 |
+
pub fresh: bool,
|
| 1917 |
+
pub initialized: Option<InitializedSession>,
|
| 1918 |
+
pub restored: Option<RestoredSession>,
|
| 1919 |
+
pub ring_advance: u32,
|
| 1920 |
+
}
|
| 1921 |
+
/// Bounded173979 caller path after authentication and before later team
|
| 1922 |
+
/// normalization. Clearing client memory does not initialize caller scratch.
|
| 1923 |
+
pub fn connect_session(
|
| 1924 |
+
client: &mut [u8],
|
| 1925 |
+
entity: &mut ConnectEntity,
|
| 1926 |
+
input: ConnectInput<'_>,
|
| 1927 |
+
info_ring: &mut u32,
|
| 1928 |
+
) -> Result<ConnectedSession, Error> {
|
| 1929 |
+
let mut cfg = input.initialize;
|
| 1930 |
+
let slot = cfg.slot;
|
| 1931 |
+
if client.len() != CLIENT_BYTES || slot >= 64 {
|
| 1932 |
+
return Err(Error::InvalidCount);
|
| 1933 |
+
}
|
| 1934 |
+
let mut bytes = vec![0; CLIENT_BYTES];
|
| 1935 |
+
let mut selector = *info_ring;
|
| 1936 |
+
raw_store(&mut bytes, 468, 1);
|
| 1937 |
+
raw_store(&mut bytes, 6156, slot as u32);
|
| 1938 |
+
cfg.client_id = 0;
|
| 1939 |
+
let fresh = input.first_time != 0 || input.new_session != 0;
|
| 1940 |
+
let mut initialized = None;
|
| 1941 |
+
let mut restored = None;
|
| 1942 |
+
let ring_advance;
|
| 1943 |
+
if fresh {
|
| 1944 |
+
let out = initialize_session(&mut bytes[3096..3096 + SESSION_BYTES], cfg, &mut selector)?;
|
| 1945 |
+
ring_advance = out.ring_advance;
|
| 1946 |
+
initialized = Some(out);
|
| 1947 |
+
} else {
|
| 1948 |
+
let mut state = RestoreState {
|
| 1949 |
+
values: [0; 9],
|
| 1950 |
+
ignore: [0; 64],
|
| 1951 |
+
position: [0; 6],
|
| 1952 |
+
};
|
| 1953 |
+
let out = restore_session(
|
| 1954 |
+
&mut state,
|
| 1955 |
+
RestoreInput {
|
| 1956 |
+
flags: input.flags,
|
| 1957 |
+
session: input.session,
|
| 1958 |
+
ignore_text: input.ignore_text,
|
| 1959 |
+
scratch: input.scratch,
|
| 1960 |
+
position: PositionInput {
|
| 1961 |
+
mode: cfg.mode,
|
| 1962 |
+
enabled: cfg.enabled,
|
| 1963 |
+
slot,
|
| 1964 |
+
userinfo: cfg.userinfo,
|
| 1965 |
+
mapname: cfg.mapname,
|
| 1966 |
+
name: b"",
|
| 1967 |
+
values: [0; 6],
|
| 1968 |
+
handle: cfg.handle,
|
| 1969 |
+
},
|
| 1970 |
+
file_length: cfg.file_length,
|
| 1971 |
+
file_data: cfg.file_data,
|
| 1972 |
+
},
|
| 1973 |
+
&mut selector,
|
| 1974 |
+
)?;
|
| 1975 |
+
for (j, o) in [0, 60, 48, 44, 52, 56, 612, 616, 644]
|
| 1976 |
+
.into_iter()
|
| 1977 |
+
.enumerate()
|
| 1978 |
+
{
|
| 1979 |
+
raw_store(&mut bytes, 3096 + o, state.values[j] as u32);
|
| 1980 |
+
}
|
| 1981 |
+
for (j, v) in state.ignore.iter().enumerate() {
|
| 1982 |
+
raw_store(&mut bytes, 3780 + 4 * j, *v as u32);
|
| 1983 |
+
}
|
| 1984 |
+
for (j, v) in state.position.iter().enumerate() {
|
| 1985 |
+
raw_store(&mut bytes, 3716 + 4 * j, *v);
|
| 1986 |
+
}
|
| 1987 |
+
ring_advance = out.ring_advance;
|
| 1988 |
+
restored = Some(out);
|
| 1989 |
+
}
|
| 1990 |
+
client.copy_from_slice(&bytes);
|
| 1991 |
+
*entity = ConnectEntity {
|
| 1992 |
+
linked_slot: Some(slot),
|
| 1993 |
+
field764: 0,
|
| 1994 |
+
field768: 0,
|
| 1995 |
+
};
|
| 1996 |
+
*info_ring = selector;
|
| 1997 |
+
Ok(ConnectedSession {
|
| 1998 |
+
fresh,
|
| 1999 |
+
initialized,
|
| 2000 |
+
restored,
|
| 2001 |
+
ring_advance,
|
| 2002 |
+
})
|
| 2003 |
+
}
|
| 2004 |
+
#[cfg(test)]
|
| 2005 |
+
mod connect_tests {
|
| 2006 |
+
use super::*;
|
| 2007 |
+
#[test]
|
| 2008 |
+
fn rejected_client_preserves_entity_and_selector() {
|
| 2009 |
+
let mut client = [];
|
| 2010 |
+
let mut entity = ConnectEntity {
|
| 2011 |
+
linked_slot: None,
|
| 2012 |
+
field764: 7,
|
| 2013 |
+
field768: 8,
|
| 2014 |
+
};
|
| 2015 |
+
let before = entity.clone();
|
| 2016 |
+
let mut selector = 1;
|
| 2017 |
+
let out = connect_session(
|
| 2018 |
+
&mut client,
|
| 2019 |
+
&mut entity,
|
| 2020 |
+
ConnectInput {
|
| 2021 |
+
first_time: 1,
|
| 2022 |
+
new_session: 0,
|
| 2023 |
+
flags: 0,
|
| 2024 |
+
initialize: InitializeInput {
|
| 2025 |
+
mode: 0,
|
| 2026 |
+
slot: 0,
|
| 2027 |
+
userinfo: b"",
|
| 2028 |
+
limit: 0,
|
| 2029 |
+
occupancy: 0,
|
| 2030 |
+
seconds: 0,
|
| 2031 |
+
clock: 0,
|
| 2032 |
+
ticks: 0,
|
| 2033 |
+
handle: 0,
|
| 2034 |
+
client_id: 0,
|
| 2035 |
+
enabled: 1,
|
| 2036 |
+
mapname: b"m",
|
| 2037 |
+
file_length: 0,
|
| 2038 |
+
file_data: b"",
|
| 2039 |
+
},
|
| 2040 |
+
session: b"",
|
| 2041 |
+
ignore_text: b"",
|
| 2042 |
+
scratch: [0; 5],
|
| 2043 |
+
},
|
| 2044 |
+
&mut selector,
|
| 2045 |
+
);
|
| 2046 |
+
assert_eq!(out, Err(Error::InvalidCount));
|
| 2047 |
+
assert_eq!(entity, before);
|
| 2048 |
+
assert_eq!(selector, 1);
|
| 2049 |
+
}
|
| 2050 |
+
#[test]
|
| 2051 |
+
fn clear_client_does_not_zero_supplied_scratch() {
|
| 2052 |
+
let mut client = vec![0xdd; CLIENT_BYTES];
|
| 2053 |
+
let mut entity = ConnectEntity {
|
| 2054 |
+
linked_slot: None,
|
| 2055 |
+
field764: 7,
|
| 2056 |
+
field768: 8,
|
| 2057 |
+
};
|
| 2058 |
+
let mut selector = 0;
|
| 2059 |
+
let out = connect_session(
|
| 2060 |
+
&mut client,
|
| 2061 |
+
&mut entity,
|
| 2062 |
+
ConnectInput {
|
| 2063 |
+
first_time: 0,
|
| 2064 |
+
new_session: 0,
|
| 2065 |
+
flags: 1,
|
| 2066 |
+
initialize: InitializeInput {
|
| 2067 |
+
mode: 3,
|
| 2068 |
+
slot: 0,
|
| 2069 |
+
userinfo: b"",
|
| 2070 |
+
limit: 0,
|
| 2071 |
+
occupancy: 0,
|
| 2072 |
+
seconds: 0,
|
| 2073 |
+
clock: 0,
|
| 2074 |
+
ticks: 0,
|
| 2075 |
+
handle: 0,
|
| 2076 |
+
client_id: 0,
|
| 2077 |
+
enabled: 1,
|
| 2078 |
+
mapname: b"m",
|
| 2079 |
+
file_length: 0,
|
| 2080 |
+
file_data: b"",
|
| 2081 |
+
},
|
| 2082 |
+
session: b"1,-2,3",
|
| 2083 |
+
ignore_text: b"",
|
| 2084 |
+
scratch: [1; 5],
|
| 2085 |
+
},
|
| 2086 |
+
&mut selector,
|
| 2087 |
+
)
|
| 2088 |
+
.unwrap();
|
| 2089 |
+
assert!(!out.fresh);
|
| 2090 |
+
assert_eq!(raw_word(&client, 3152), 1);
|
| 2091 |
+
assert_eq!(raw_word(&client, 468), 1);
|
| 2092 |
+
assert_eq!(client[6332..], [0; 4]);
|
| 2093 |
+
}
|
| 2094 |
+
}
|
docs/FINDINGS.md
CHANGED
|
@@ -1736,3 +1736,6 @@ RE-813–822 replaces the scoreboard decimal assumption with actual37914 executi
|
|
| 1736 |
|
| 1737 |
|
| 1738 |
**RE-912:** 96 bounded173979 caller-path executions cover174081..174173 after userinfo/authentication: entity-client linking, actual6336-byte clear via modeled native memset, connecting-state/client-slot writes and the first-time OR new-session choice between actual247520 initialization and247219 restore. Both children execute recovered load/format/scanner policies. Uppercase team S below capacity is not the lowercase s shortcut. Authentication before the slice, post-branch normalization and native engine integration remain open. [Evidence](research/QVM_CONNECT_SESSION.md).
|
|
|
|
|
|
|
|
|
|
|
|
| 1736 |
|
| 1737 |
|
| 1738 |
**RE-912:** 96 bounded173979 caller-path executions cover174081..174173 after userinfo/authentication: entity-client linking, actual6336-byte clear via modeled native memset, connecting-state/client-slot writes and the first-time OR new-session choice between actual247520 initialization and247219 restore. Both children execute recovered load/format/scanner policies. Uppercase team S below capacity is not the lowercase s shortcut. Authentication before the slice, post-branch normalization and native engine integration remain open. [Evidence](research/QVM_CONNECT_SESSION.md).
|
| 1739 |
+
|
| 1740 |
+
|
| 1741 |
+
**RE-913:** Rust matches96 bounded173979 caller paths, including client/entity initialization, first-time OR new-session dispatch, actual initialization/restore policies and saved-position loading. Client memory clear does not erase supplied caller scratch. Errors stage client/entity/selector changes. Authentication and later caller normalization, native IO and full client-connect acceptance remain open. [Evidence](research/RUST_CONNECT_SESSION.md).
|
docs/PROVISIONAL_TODO.md
CHANGED
|
@@ -1773,3 +1773,9 @@ RE-911: Rust matches144 original save/session-write/restore/read compositions us
|
|
| 1773 |
|
| 1774 |
|
| 1775 |
RE-912: 96 bounded173979 caller-path executions cover174081..174173 after userinfo/authentication: entity-client linking, actual6336-byte clear via modeled native memset, connecting-state/client-slot writes and the first-time OR new-session choice between actual247520 initialization and247219 restore. Both children execute recovered load/format/scanner policies. Uppercase team S below capacity is not the lowercase s shortcut. Authentication before the slice, post-branch normalization and native engine integration remain open. Full runtime completion remains open. [Evidence](research/QVM_CONNECT_SESSION.md).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1773 |
|
| 1774 |
|
| 1775 |
RE-912: 96 bounded173979 caller-path executions cover174081..174173 after userinfo/authentication: entity-client linking, actual6336-byte clear via modeled native memset, connecting-state/client-slot writes and the first-time OR new-session choice between actual247520 initialization and247219 restore. Both children execute recovered load/format/scanner policies. Uppercase team S below capacity is not the lowercase s shortcut. Authentication before the slice, post-branch normalization and native engine integration remain open. Full runtime completion remains open. [Evidence](research/QVM_CONNECT_SESSION.md).
|
| 1776 |
+
|
| 1777 |
+
|
| 1778 |
+
RE-913: Rust matches96 bounded173979 caller paths, including client/entity initialization, first-time OR new-session dispatch, actual initialization/restore policies and saved-position loading. Client memory clear does not erase supplied caller scratch. Errors stage client/entity/selector changes. Authentication and later caller normalization, native IO and full client-connect acceptance remain open. Full runtime completion remains open. [Evidence](research/RUST_CONNECT_SESSION.md).
|
| 1779 |
+
|
| 1780 |
+
|
| 1781 |
+
RE-904–913 completed bounded initialization, full persistence, in-memory round trips and connect clear/dispatch policies. RE-914 tracks full connect/native IO, remaining scanner/alias domains and real runtime integration. [Batch and next work](research/QVM_SESSION_LIFECYCLE_BATCH.md).
|
docs/RESEARCH_LEDGER.md
CHANGED
|
@@ -2280,3 +2280,13 @@ Rust matches144 original save/session-write/restore/read compositions using owne
|
|
| 2280 |
## 2026-10-28 — RE-912 Original connect clear and session-branch caller
|
| 2281 |
|
| 2282 |
96 bounded173979 caller-path executions cover174081..174173 after userinfo/authentication: entity-client linking, actual6336-byte clear via modeled native memset, connecting-state/client-slot writes and the first-time OR new-session choice between actual247520 initialization and247219 restore. Both children execute recovered load/format/scanner policies. Uppercase team S below capacity is not the lowercase s shortcut. Authentication before the slice, post-branch normalization and native engine integration remain open. Focused `cargo xtask test-group qvm-connect-session` 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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2280 |
## 2026-10-28 — RE-912 Original connect clear and session-branch caller
|
| 2281 |
|
| 2282 |
96 bounded173979 caller-path executions cover174081..174173 after userinfo/authentication: entity-client linking, actual6336-byte clear via modeled native memset, connecting-state/client-slot writes and the first-time OR new-session choice between actual247520 initialization and247219 restore. Both children execute recovered load/format/scanner policies. Uppercase team S below capacity is not the lowercase s shortcut. Authentication before the slice, post-branch normalization and native engine integration remain open. Focused `cargo xtask test-group qvm-connect-session` 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.
|
| 2283 |
+
|
| 2284 |
+
|
| 2285 |
+
## 2026-10-28 — RE-913 Rust connect clear and session lifecycle branch
|
| 2286 |
+
|
| 2287 |
+
Rust matches96 bounded173979 caller paths, including client/entity initialization, first-time OR new-session dispatch, actual initialization/restore policies and saved-position loading. Client memory clear does not erase supplied caller scratch. Errors stage client/entity/selector changes. Authentication and later caller normalization, native IO and full client-connect acceptance remain open. Focused `cargo xtask test-group rust-connect-session` 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.
|
| 2288 |
+
|
| 2289 |
+
|
| 2290 |
+
### RE-904–913 full batch validation (2026-10-28)
|
| 2291 |
+
|
| 2292 |
+
At the tenth-commit boundary, the first full attempt exposed a helper filename collision with the pre-existing health lifecycle module. The original helper was restored byte-for-byte, session helpers moved to qvm_session_lifecycle_support.py, and an import smoke check added to the scoped registry regression. After focused repair checks, `cargo xtask test-full --since 6d0ce63f` completed successfully with the flake-declared Nix Python: 1,768 Python tests,207 Rust tests (assets10, gameplay167, xtask30),39 affected report producers regenerated twice deterministically, storage policy,480 documentation link checks and whitespace guards. No generated-report drift. Ten task commits since6d0ce63f; repair and results are amended into the tenth commit. [Findings and next work](research/QVM_SESSION_LIFECYCLE_BATCH.md).
|
docs/REVERSE_ENGINEERING_TODO.md
CHANGED
|
@@ -1782,7 +1782,7 @@ Purpose: turn the supplied installation into an evidence-backed specification of
|
|
| 1782 |
- [x] RE-903 Rust session restore with caller-scratch ownership ([evidence](research/RUST_SESSION_RESTORE.md)).
|
| 1783 |
|
| 1784 |
|
| 1785 |
-
- [ ] RE-
|
| 1786 |
|
| 1787 |
|
| 1788 |
- [x] RE-904 Original session initialization and immediate persistence ([evidence](research/QVM_SESSION_INIT.md)).
|
|
@@ -1810,3 +1810,9 @@ Purpose: turn the supplied installation into an evidence-backed specification of
|
|
| 1810 |
|
| 1811 |
|
| 1812 |
- [x] RE-912 Original connect clear and session-branch caller ([evidence](research/QVM_CONNECT_SESSION.md)).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1782 |
- [x] RE-903 Rust session restore with caller-scratch ownership ([evidence](research/RUST_SESSION_RESTORE.md)).
|
| 1783 |
|
| 1784 |
|
| 1785 |
+
- [ ] Follow-up after RE-903: complete numeric/fatal/alias domains, scratch provenance, real reload and native IO/runtime integration ([next tasks](research/QVM_SAVED_RESTORE_BATCH.md)).
|
| 1786 |
|
| 1787 |
|
| 1788 |
- [x] RE-904 Original session initialization and immediate persistence ([evidence](research/QVM_SESSION_INIT.md)).
|
|
|
|
| 1810 |
|
| 1811 |
|
| 1812 |
- [x] RE-912 Original connect clear and session-branch caller ([evidence](research/QVM_CONNECT_SESSION.md)).
|
| 1813 |
+
|
| 1814 |
+
|
| 1815 |
+
- [x] RE-913 Rust connect clear and session lifecycle branch ([evidence](research/RUST_CONNECT_SESSION.md)).
|
| 1816 |
+
|
| 1817 |
+
|
| 1818 |
+
- [ ] RE-914 Complete connect authentication/normalization, native IO/reload, scanner/alias domains and full runtime integration ([next work](research/QVM_SESSION_LIFECYCLE_BATCH.md)).
|
docs/TESTING.md
CHANGED
|
@@ -166,3 +166,6 @@ RE-884–893 adds focused groups `qvm-queried-spawn`, `rust-queried-spawn`, `qvm
|
|
| 166 |
|
| 167 |
|
| 168 |
RE-894–903 adds focused groups `qvm-info-lookup`, `rust-info-lookup`, `qvm-numeric-scan`, `rust-numeric-scan`, `qvm-position-save`, `rust-position-save`, `qvm-position-load`, `rust-position-load`, `qvm-session-restore` and `rust-session-restore`. Use one group per invocation. Full validation after task ten uses `cargo xtask test-full --since 6e01995b` with explicit flake-declared Nix PYTHON. [Source domains and scratch ownership](research/QVM_SAVED_RESTORE_BATCH.md).
|
|
|
|
|
|
|
|
|
|
|
|
| 166 |
|
| 167 |
|
| 168 |
RE-894–903 adds focused groups `qvm-info-lookup`, `rust-info-lookup`, `qvm-numeric-scan`, `rust-numeric-scan`, `qvm-position-save`, `rust-position-save`, `qvm-position-load`, `rust-position-load`, `qvm-session-restore` and `rust-session-restore`. Use one group per invocation. Full validation after task ten uses `cargo xtask test-full --since 6e01995b` with explicit flake-declared Nix PYTHON. [Source domains and scratch ownership](research/QVM_SAVED_RESTORE_BATCH.md).
|
| 169 |
+
|
| 170 |
+
|
| 171 |
+
RE-904–913 adds focused groups `qvm-session-init`, `rust-session-init`, `qvm-post-map-files`, `rust-post-map-files`, `qvm-normal-map-files`, `rust-normal-map-files`, `qvm-persistence-roundtrip`, `rust-persistence-roundtrip`, `qvm-connect-session` and `rust-connect-session`. Invoke one group per command. The full suite after task ten uses `cargo xtask test-full --since 6d0ce63f` with explicit flake-declared Nix PYTHON. [Bounded lifecycle evidence](research/QVM_SESSION_LIFECYCLE_BATCH.md).
|
docs/research/QVM_SAVED_RESTORE_BATCH.md
CHANGED
|
@@ -43,7 +43,7 @@ Each task used focused `cargo xtask test-group <name>` before its commit, with d
|
|
| 43 |
|
| 44 |
Dependency-selection regression coverage includes all five new source-to-Rust report pairs, native_policy consumers, formatting dependencies and intermission classification used by restore. Every Python process uses the resolved Nix runtime declared by flake.nix, with explicit PYTHON for xtask and Git hooks. No original asset payload changed. After commit ten, `cargo xtask test-full --since 6e01995b` passed once: 1,753 Python tests and199 Rust tests (assets10, gameplay159, xtask30). All22 affected report producers regenerated twice deterministically. Storage policy, links across469 documentation files and whitespace checks passed with no generated-report drift. These notes were amended into task ten.
|
| 45 |
|
| 46 |
-
##
|
| 47 |
|
| 48 |
- [ ] Recover uppercase exponent behavior and remaining38355 conversions, non-ASCII parsing, oversized/fatal userinfo and pointer/buffer alias contracts.
|
| 49 |
- [ ] Trace actual scratch provenance on malformed session restore; decide a documented production compatibility/default policy after validating native behavior.
|
|
@@ -53,3 +53,5 @@ Dependency-selection regression coverage includes all five new source-to-Rust re
|
|
| 53 |
- [ ] Replace supplied spatial-query answers with recovered native broadphase, integrate bot rotation/native genetic behavior, and recover221662 map-list parsing.
|
| 54 |
- [ ] Compose complete respawn/begin-intermission, event lifetime and ranking/scoreboard/network execution.
|
| 55 |
- [ ] Validate actual Linux/macOS Rust/Bevy/Solari gameplay/rendering. Full-game completion remains open.
|
|
|
|
|
|
|
|
|
| 43 |
|
| 44 |
Dependency-selection regression coverage includes all five new source-to-Rust report pairs, native_policy consumers, formatting dependencies and intermission classification used by restore. Every Python process uses the resolved Nix runtime declared by flake.nix, with explicit PYTHON for xtask and Git hooks. No original asset payload changed. After commit ten, `cargo xtask test-full --since 6e01995b` passed once: 1,753 Python tests and199 Rust tests (assets10, gameplay159, xtask30). All22 affected report producers regenerated twice deterministically. Storage policy, links across469 documentation files and whitespace checks passed with no generated-report drift. These notes were amended into task ten.
|
| 45 |
|
| 46 |
+
## Follow-up work (expanded by RE-904–913)
|
| 47 |
|
| 48 |
- [ ] Recover uppercase exponent behavior and remaining38355 conversions, non-ASCII parsing, oversized/fatal userinfo and pointer/buffer alias contracts.
|
| 49 |
- [ ] Trace actual scratch provenance on malformed session restore; decide a documented production compatibility/default policy after validating native behavior.
|
|
|
|
| 53 |
- [ ] Replace supplied spatial-query answers with recovered native broadphase, integrate bot rotation/native genetic behavior, and recover221662 map-list parsing.
|
| 54 |
- [ ] Compose complete respawn/begin-intermission, event lifetime and ranking/scoreboard/network execution.
|
| 55 |
- [ ] Validate actual Linux/macOS Rust/Bevy/Solari gameplay/rendering. Full-game completion remains open.
|
| 56 |
+
|
| 57 |
+
[RE-904–913](QVM_SESSION_LIFECYCLE_BATCH.md) composes initialization, full persistence, byte-fed round trips and the bounded connect caller. Its RE-914 list supersedes the historical follow-up list above.
|
docs/research/QVM_SESSION_LIFECYCLE_BATCH.md
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Session lifecycle and complete persistence: RE-904–913
|
| 2 |
+
|
| 3 |
+
Ten separately committed tasks connect original QVM lifecycle routines and their Rust policies across448 paired source cases. They cover initialization, both post-map children, normal map flow, byte-fed write/restore and the bounded connect caller branch. Native files, userinfo/cvars, timing and selected callbacks remain supplied inputs or captured intentions. This evidence does not establish real network/client-connect acceptance or a complete playable game.
|
| 4 |
+
|
| 5 |
+
| Task | Evidence | Cases |
|
| 6 |
+
| --- | --- | ---: |
|
| 7 |
+
| RE-904 | [Original247520 initializer](QVM_SESSION_INIT.md) | 96 |
|
| 8 |
+
| RE-905 | [Rust initializer and raw-field ownership](RUST_SESSION_INIT.md) | 96 |
|
| 9 |
+
| RE-906 | [Original249007 with246746/246963](QVM_POST_MAP_FILES.md) | 48 |
|
| 10 |
+
| RE-907 | [Rust complete post-map persistence](RUST_POST_MAP_FILES.md) | 48 |
|
| 11 |
+
| RE-908 | [Normal6939 with both persistence children](QVM_NORMAL_MAP_FILES.md) | 64 |
|
| 12 |
+
| RE-909 | [Rust normal map/file/cvar flow](RUST_NORMAL_MAP_FILES.md) | 64 |
|
| 13 |
+
| RE-910 | [Original byte-fed write/restore](QVM_PERSISTENCE_ROUNDTRIP.md) | 144 |
|
| 14 |
+
| RE-911 | [Rust owned in-memory persistence](RUST_PERSISTENCE_ROUNDTRIP.md) | 144 |
|
| 15 |
+
| RE-912 | [Bounded173979 caller clear/branch](QVM_CONNECT_SESSION.md) | 96 |
|
| 16 |
+
| RE-913 | [Rust connect lifecycle branch](RUST_CONNECT_SESSION.md) | 96 |
|
| 17 |
+
|
| 18 |
+
## Initialization ownership
|
| 19 |
+
|
| 20 |
+
Actual247520 selects the initial team field at3096 through original33715 classification. Team-classified modes preserve a nonzero field, while zero becomes3. Other modes query userinfo key team through70503: a first byte of lowercase s selects3; otherwise a positive capacity limit34089308 reached by34992584 selects3, and other cases select0. The caller fixtures additionally verify uppercase S below capacity selects0.
|
| 21 |
+
|
| 22 |
+
The initializer writes clock34992532 into selected fields, sets field3108 to1, and computes the timeout at3140 with wrapping arithmetic. A nonzero configured34085460 contributes seconds*1000, including negative values; zero uses60000. Field3148 receives a clock write and is later cleared. Native -3 supplies the tick snapshot stored at3156. A36-byte bounded copy writes one space and NUL padding at3164. Several fields are word-cleared, while the starts of string-like regions are only byte-cleared; neighboring bytes remain observable in warm-state fixtures. The64 ignore words at3780 are cleared. Coordinates3716..3736 survive unless the actual246554 load succeeds.
|
| 23 |
+
|
| 24 |
+
Initialization then executes actual246963 session serialization and captures7259 diagnostics. The Rust API uses a944-byte block beginning at3096 to preserve byte/word distinctions, with explicit timing and file answers. It stages state/selector changes on typed errors. Metadata meanings, native timing/file semantics and full engine lifecycle remain open.
|
| 25 |
+
|
| 26 |
+
## Post-map ordering and map transitions
|
| 27 |
+
|
| 28 |
+
Actual249007 now executes both recovered client children. The first246746 child produces ordered userinfo/map/open/write/close intentions; the second246963 writes sessionN and sessIgnoreN. Each eligible client's file operations precede its cvar pair. The48 fixtures vary connected-state patterns, level count, mode, enable and supplied open handles, while formatter and info selectors carry across clients.
|
| 29 |
+
|
| 30 |
+
The64 normal6939 fixtures compose122230,7188,249007 and both persistence children. Score/global resets precede persistence, and the final max-client state2-to1 scan follows it. Reset maximum and level count vary independently. The engine map bytes supplied to the map-command and saved-file paths are consistent. Rust shares action assembly between standalone and normal persistence; no file action is dispatched to an operating system. Bot callback internals,221662 map-list selection, actual cvar/console command dispatch and series-path composition remain open.
|
| 31 |
+
|
| 32 |
+
## Byte-fed write/restore and caller integration
|
| 33 |
+
|
| 34 |
+
The144 round trips execute actual246746 and246963, then feed their captured cvar/file bytes into actual247219/246554 on a fresh destination snapshot. The destination starts with explicit metadata/position values and a nonzero ignore table; caller scratch is also supplied. Session text containing negative/INT_MIN fields is not assumed invertible: recovered formatter and scanner behavior can produce partial writes and scratch-dependent booleans. Restored ignore entries accumulate, and six-float file prefixes remain readable with appended PLAYER text.
|
| 35 |
+
|
| 36 |
+
Rust MemoryPersistence owns ordered cvar/file byte maps. It applies captured write intentions and supplies those bytes to the restore policies, staging adapter/destination/selector changes on errors. This validates an in-memory transcript; it does not validate a filesystem, native handle lifetime, actual reload or arbitrary concurrent engine effects.
|
| 37 |
+
|
| 38 |
+
The final source fixtures execute173979's174081..174173 caller portion after its userinfo/authentication prefix. They link entity offset520 to the selected client, clear entity fields764/768, model the actual native6336-byte client memset, set connection468 to1, and copy the slot into6156. The first-time argument or nonzero global34992572 chooses actual247520 initialization; otherwise actual247219 restores. Both children execute recovered scanner/formatter/load policies. Clearing the client does not clear the separate VM caller scratch. The Rust API stages raw client bytes, typed entity linkage and selector together. Authentication before this slice, later team normalization from174174 onward, bot connection behavior, alias domains and real engine acceptance remain open.
|
| 39 |
+
|
| 40 |
+
## Validation and storage
|
| 41 |
+
|
| 42 |
+
Focused `cargo xtask test-group <name>` ran before each commit, with selected reports regenerated twice, source/Rust parity, scoped gameplay checks and storage/documentation/whitespace guards. The ten groups are qvm-session-init, rust-session-init, qvm-post-map-files, rust-post-map-files, qvm-normal-map-files, rust-normal-map-files, qvm-persistence-roundtrip, rust-persistence-roundtrip, qvm-connect-session and rust-connect-session. Shared persistence action assembly also received its standalone regression check.
|
| 43 |
+
|
| 44 |
+
The dependency-selection regression covers the five source/Rust report pairs, native_policy consumers and shared transition/map/intermission dependencies. Its import smoke check also keeps the existing health lifecycle and new session lifecycle helper namespaces independent. The first full-suite attempt caught a helper filename collision: the original health helper was restored byte-for-byte from the batch baseline, the new code moved to qvm_session_lifecycle_support.py, and affected checks were rerun before final full validation. Python runs only through the resolved Nix runtime declared by flake.nix, with explicit PYTHON inherited by xtask and Git hooks. Original assets are unchanged. After the namespace repair documented above, `cargo xtask test-full --since 6d0ce63f` completed successfully at the tenth-commit boundary: 1,768 Python tests and207 Rust tests (assets10, gameplay167, xtask30). All39 affected report producers regenerated twice deterministically. Storage policy, links across480 documentation files and whitespace checks passed with no generated-report drift. Repair and validation notes were amended into task ten.
|
| 45 |
+
|
| 46 |
+
## Next work: RE-914
|
| 47 |
+
|
| 48 |
+
- [ ] Recover the173979 authentication/userinfo prefix and post-174174 team normalization, bot branch and downstream connect callbacks; compose the complete function.
|
| 49 |
+
- [ ] Recover native file-open return/handle/close behavior and attach a platform-neutral engine IO adapter; validate actual reload and failure ownership on macOS/Linux.
|
| 50 |
+
- [ ] Trace real VM scratch provenance, non-ASCII/tail parsing, uppercase exponent and other scanner conversions, oversized/fatal strings and pointer aliases.
|
| 51 |
+
- [ ] Recover direct/indirect246938 session-clear use, remaining metadata producers, ignore-table mutations and live count/base changes during callbacks.
|
| 52 |
+
- [ ] Integrate both persistence children into series6939/readiness, plus real cvar refresh/command dispatch, bot rotation/native genetics and221662 map-list parsing.
|
| 53 |
+
- [ ] Replace supplied spatial-query answers with native broadphase/world collision and compare native math.
|
| 54 |
+
- [ ] Compose complete respawn/intermission, event lifetime and ranking/scoreboard/network execution.
|
| 55 |
+
- [ ] Validate actual Linux/macOS Rust/Bevy/Solari gameplay/rendering. Full-game completion remains open.
|
docs/research/README.md
CHANGED
|
@@ -1345,3 +1345,9 @@ The extension collector adds five focused tests for native tail calls, command-r
|
|
| 1345 |
|
| 1346 |
|
| 1347 |
[RE-912: Original connect clear and session-branch caller](QVM_CONNECT_SESSION.md).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1345 |
|
| 1346 |
|
| 1347 |
[RE-912: Original connect clear and session-branch caller](QVM_CONNECT_SESSION.md).
|
| 1348 |
+
|
| 1349 |
+
|
| 1350 |
+
[RE-913: Rust connect clear and session lifecycle branch](RUST_CONNECT_SESSION.md).
|
| 1351 |
+
|
| 1352 |
+
|
| 1353 |
+
[RE-904–913 lifecycle and complete persistence batch](QVM_SESSION_LIFECYCLE_BATCH.md).
|
docs/research/RUST_CONNECT_SESSION.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Rust connect clear and session lifecycle branch
|
| 2 |
+
|
| 3 |
+
RE-913. Reproduce with `python3 scripts/analyze_rust_connect_session.py`; focused validation: `cargo xtask test-group rust-connect-session`. [Machine report](rust-connect-session.json).
|
| 4 |
+
|
| 5 |
+
Rust matches96 bounded173979 caller paths, including client/entity initialization, first-time OR new-session dispatch, actual initialization/restore policies and saved-position loading. Client memory clear does not erase supplied caller scratch. Errors stage client/entity/selector changes. Authentication and later caller normalization, native IO and full client-connect acceptance remain open.
|
| 6 |
+
|
| 7 |
+
Original executable/native runtime and complete Linux/macOS Rust/Bevy/Solari acceptance remain unverified.
|
docs/research/qvm-resumer-audit.json
CHANGED
|
@@ -8919,6 +8919,17 @@
|
|
| 8919 |
"repeated_calls_opt_in": false,
|
| 8920 |
"repeated_calls_setting": "default_false"
|
| 8921 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8922 |
{
|
| 8923 |
"backward_conditional_branches": [],
|
| 8924 |
"calls": [],
|
|
@@ -10025,10 +10036,10 @@
|
|
| 10025 |
}
|
| 10026 |
},
|
| 10027 |
"summary": {
|
| 10028 |
-
"call_expressions":
|
| 10029 |
-
"files":
|
| 10030 |
-
"legacy_expressions":
|
| 10031 |
-
"nonliteral_ranges":
|
| 10032 |
"unresolved_mode_expressions": 3
|
| 10033 |
}
|
| 10034 |
}
|
|
|
|
| 8919 |
"repeated_calls_opt_in": false,
|
| 8920 |
"repeated_calls_setting": "default_false"
|
| 8921 |
},
|
| 8922 |
+
{
|
| 8923 |
+
"backward_conditional_branches": [],
|
| 8924 |
+
"calls": [],
|
| 8925 |
+
"explicit_result_offsets": null,
|
| 8926 |
+
"helper": "qvm_trace_support.resume",
|
| 8927 |
+
"line": 39,
|
| 8928 |
+
"literal_range": null,
|
| 8929 |
+
"path": "scripts/qvm_lifecycle_support.py",
|
| 8930 |
+
"repeated_calls_opt_in": false,
|
| 8931 |
+
"repeated_calls_setting": "default_false"
|
| 8932 |
+
},
|
| 8933 |
{
|
| 8934 |
"backward_conditional_branches": [],
|
| 8935 |
"calls": [],
|
|
|
|
| 10036 |
}
|
| 10037 |
},
|
| 10038 |
"summary": {
|
| 10039 |
+
"call_expressions": 203,
|
| 10040 |
+
"files": 155,
|
| 10041 |
+
"legacy_expressions": 158,
|
| 10042 |
+
"nonliteral_ranges": 28,
|
| 10043 |
"unresolved_mode_expressions": 3
|
| 10044 |
}
|
| 10045 |
}
|
docs/research/qvm-session-init.json
CHANGED
|
The diff for this file is too large to render.
See raw diff
|
|
|
docs/research/rust-connect-session.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": 167,
|
| 2989 |
"source_report": "docs/research/qvm-health-impulse.json",
|
| 2990 |
"source_report_sha256": "625fd8064004ea6dbdf398d51d0af844d9c635ff04c0a0790886dddb6ab81e71"
|
| 2991 |
}
|
docs/research/rust-session-init.json
CHANGED
|
The diff for this file is too large to render.
See raw diff
|
|
|
scripts/analyze_qvm_connect_session.py
CHANGED
|
@@ -11,7 +11,7 @@ from analyze_qvm import write_json
|
|
| 11 |
def main():
|
| 12 |
q,raw,h,ins=source();rows=[]
|
| 13 |
from qvm_persistence_support import environment,RESTORE,SCRATCH
|
| 14 |
-
from
|
| 15 |
from qvm_byte_memory_support import write_bytes
|
| 16 |
for mode,first,new,positive,slot,handle in itertools.product([0,3,9],[0,1],[0,-1],[False,True],[0,3],[0,7]):
|
| 17 |
m,b=environment(raw,h);write_bytes(m,b,{a:raw[h['data_offset']+a] for a in range(83568,83824)});pointer=CPOOL+6336*slot
|
|
|
|
| 11 |
def main():
|
| 12 |
q,raw,h,ins=source();rows=[]
|
| 13 |
from qvm_persistence_support import environment,RESTORE,SCRATCH
|
| 14 |
+
from qvm_session_lifecycle_support import connect_branch,raw_state,CLIENT_BYTES
|
| 15 |
from qvm_byte_memory_support import write_bytes
|
| 16 |
for mode,first,new,positive,slot,handle in itertools.product([0,3,9],[0,1],[0,-1],[False,True],[0,3],[0,7]):
|
| 17 |
m,b=environment(raw,h);write_bytes(m,b,{a:raw[h['data_offset']+a] for a in range(83568,83824)});pointer=CPOOL+6336*slot
|
scripts/analyze_qvm_normal_map_files.py
CHANGED
|
@@ -11,7 +11,7 @@ from analyze_qvm import write_json
|
|
| 11 |
def main():
|
| 12 |
q,raw,h,ins=source();rows=[]
|
| 13 |
from qvm_persistence_support import environment
|
| 14 |
-
from
|
| 15 |
from qvm_session_support import records
|
| 16 |
from qvm_map_commands_support import map_seed,normal_flow,put_string,CURSOR,ENABLED,LIMIT,WRITE,MIRROR
|
| 17 |
from qvm_transition_support import state_seed,state_words
|
|
|
|
| 11 |
def main():
|
| 12 |
q,raw,h,ins=source();rows=[]
|
| 13 |
from qvm_persistence_support import environment
|
| 14 |
+
from qvm_session_lifecycle_support import post_full
|
| 15 |
from qvm_session_support import records
|
| 16 |
from qvm_map_commands_support import map_seed,normal_flow,put_string,CURSOR,ENABLED,LIMIT,WRITE,MIRROR
|
| 17 |
from qvm_transition_support import state_seed,state_words
|
scripts/analyze_qvm_post_map_files.py
CHANGED
|
@@ -11,7 +11,7 @@ from analyze_qvm import write_json
|
|
| 11 |
def main():
|
| 12 |
q,raw,h,ins=source();rows=[]
|
| 13 |
from qvm_persistence_support import environment
|
| 14 |
-
from
|
| 15 |
from qvm_session_support import records
|
| 16 |
from qvm_map_commands_support import put_string
|
| 17 |
for mode,count,pattern,enabled,opened in itertools.product([0,9],[0,1,4],range(2),[0,1],[False,True]):
|
|
|
|
| 11 |
def main():
|
| 12 |
q,raw,h,ins=source();rows=[]
|
| 13 |
from qvm_persistence_support import environment
|
| 14 |
+
from qvm_session_lifecycle_support import post_full
|
| 15 |
from qvm_session_support import records
|
| 16 |
from qvm_map_commands_support import put_string
|
| 17 |
for mode,count,pattern,enabled,opened in itertools.product([0,9],[0,1,4],range(2),[0,1],[False,True]):
|
scripts/analyze_qvm_session_init.py
CHANGED
|
@@ -11,10 +11,10 @@ from analyze_qvm import write_json
|
|
| 11 |
def main():
|
| 12 |
q,raw,h,ins=source();rows=[]
|
| 13 |
from qvm_persistence_support import environment
|
| 14 |
-
from
|
| 15 |
from qvm_byte_memory_support import write_bytes
|
| 16 |
from qvm_formatter_support import image_bytes
|
| 17 |
-
profiles=[(b'',0,0,0,100,11),(b'\\team\\s\\cl_guid\\ID',2,1,0,100,17),(b'\\team\\S\\cl_guid\\ID',2,2,2,
|
| 18 |
for mode,team,profile,slot,handle in itertools.product([0,3,9],[0,2],range(4),[0,3],[0,7]):
|
| 19 |
info,limit,occupancy,seconds,now,ticks=profiles[profile];m,b=environment(raw,h);write_bytes(m,b,{a:raw[h['data_offset']+a] for a in range(83568,83824)});pointer=CPOOL+6336*slot
|
| 20 |
for j in range(0,SIZE,4):m[pointer+3096+j]=0xaabbccdd
|
|
|
|
| 11 |
def main():
|
| 12 |
q,raw,h,ins=source();rows=[]
|
| 13 |
from qvm_persistence_support import environment
|
| 14 |
+
from qvm_session_lifecycle_support import initialize,raw_state,SIZE
|
| 15 |
from qvm_byte_memory_support import write_bytes
|
| 16 |
from qvm_formatter_support import image_bytes
|
| 17 |
+
profiles=[(b'',0,0,0,100,11),(b'\\team\\s\\cl_guid\\ID',2,1,0,100,17),(b'\\team\\S\\cl_guid\\ID',2,2,2,2147483647,19),(b'\\team\\spectator\\cl_guid\\ID',2,2,-1,2147483647,0xffffffff)]
|
| 18 |
for mode,team,profile,slot,handle in itertools.product([0,3,9],[0,2],range(4),[0,3],[0,7]):
|
| 19 |
info,limit,occupancy,seconds,now,ticks=profiles[profile];m,b=environment(raw,h);write_bytes(m,b,{a:raw[h['data_offset']+a] for a in range(83568,83824)});pointer=CPOOL+6336*slot
|
| 20 |
for j in range(0,SIZE,4):m[pointer+3096+j]=0xaabbccdd
|
scripts/analyze_rust_connect_session.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','first','new','scratch','slot','handle']]
|
| 8 |
+
def project(s):return {k:s[k] for k in ['raw','nonzero','choice','entity_linked','entity_clear','ring','info_ring']}
|
| 9 |
+
|
| 10 |
+
def main():
|
| 11 |
+
b=binary();p=Path('docs/research/qvm-connect-session.json');data=p.read_bytes();rows=[]
|
| 12 |
+
for s in json.loads(data)['probes']:rows.append({'source':project(s),'rust':result(b,'connect-session',encode(s))})
|
| 13 |
+
write_json(Path('docs/research/rust-connect-session.json'),{'source_report':str(p),'source_report_sha256':hashlib.sha256(data).hexdigest(),'probes':rows,'limits':'Rust matches96 bounded173979 caller paths, including client/entity initialization, first-time OR new-session dispatch, actual initialization/restore policies and saved-position loading. Client memory clear does not erase supplied caller scratch. Errors stage client/entity/selector changes. Authentication and later caller normalization, native IO and full client-connect acceptance remain open.'})
|
| 14 |
+
if __name__=='__main__':main()
|
scripts/qvm_lifecycle_support.py
CHANGED
|
@@ -1,52 +1,40 @@
|
|
| 1 |
-
"""
|
| 2 |
-
from
|
| 3 |
-
from
|
| 4 |
-
from
|
| 5 |
-
from
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
|
| 11 |
-
def
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
def clock(i,m,a,bs):return m,ticks,{'engine_ticks_supplied':True}
|
| 20 |
-
def copy(i,m,a,bs):return copy_bounded(i,m,a,dict(bs))
|
| 21 |
-
def load(i,m,a,bs):
|
| 22 |
-
data=b'9,8,7,6,5,4';m,p,b=load_position(i,m,dict(bs),a[8],userinfo,b'ut4_test',handle,len(data),data);parts['load']=p;return m,0,{'actual_source_child':246554}
|
| 23 |
-
def write(i,m,a,bs):
|
| 24 |
-
m,p,b=session(i,m,dict(bs),a[8]);parts['session']=p;return m,0,{'actual_source_child':246963}
|
| 25 |
-
def diagnostic(i,m,a,bs):diagnostics.append([a[8],a[12]&0xffffffff,a[16]&0xffffffff]);return m,0,{'diagnostic_captured':True}
|
| 26 |
-
m,v,p,b=run(ins,m,247520,247806,40,{8:pointer,12:INFO},b,{33715:classify,70503:lookup,-3:clock,69338:copy,246554:load,246963:write,7259:diagnostic},base=INIT);p.update(parts=parts,diagnostics=diagnostics);return m,p,b
|
| 27 |
|
| 28 |
-
def
|
|
|
|
| 29 |
|
| 30 |
-
def
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
from qvm_map_commands_support import put_string
|
| 43 |
-
from qvm_persistence_support import restore_session
|
| 44 |
-
entity=34091368+880*slot;pointer=CPOOL+6336*slot;m[CONNECT+24]=entity;put_string(m,b,CONNECT+28,userinfo,1024);parts={};choice=[]
|
| 45 |
-
def zero(i,m,a,bs):
|
| 46 |
-
if a[8]!=pointer or a[12]!=0 or a[16]!=6336:raise ValueError('unsupported connect memset')
|
| 47 |
-
return m,a[8],{'native_memset_modeled':True,'child_memory_bytes':{pointer+j:0 for j in range(6336)}}
|
| 48 |
-
def fresh(i,m,a,bs):
|
| 49 |
-
choice.append(247520);m,p,b=initialize(i,m,dict(bs),a[8],userinfo,handle,17);parts.update(p);return m,0,{'actual_source_child':247520}
|
| 50 |
-
def restored(i,m,a,bs):
|
| 51 |
-
choice.append(247219);data=b'9,8,7,6,5,4';m,p,b=restore_session(i,m,dict(bs),a[8],b'1,-2,3,4,5,1,1,1,1',b'1,3,',userinfo,b'ut4_test',handle,len(data),data);parts.update(p);return m,0,{'actual_source_child':247219}
|
| 52 |
-
m,v,p,b=run(ins,m,174080,174174,1080,{8:slot,12:first,16:0},b,{-101:zero,247520:fresh,247219:restored},base=CONNECT);changes=p.pop('changes');p.update(change_count=len(changes),changes_sha256=hashlib.sha256(json.dumps(changes,sort_keys=True).encode()).hexdigest(),choice=choice,parts=parts,entity_linked=m[entity+520]==pointer,entity_clear=[m[entity+764]&0xffffffff,m[entity+768]&0xffffffff]);return m,p,b
|
|
|
|
| 1 |
+
"""Explicit finite fixtures for protected and mode10 lifecycle source ranges."""
|
| 2 |
+
from qvm_health_effects_support import seed as health_seed,H,TARGET,ATTACKER,CLIENT,A_CLIENT
|
| 3 |
+
from qvm_research_support import constants
|
| 4 |
+
from qvm_trace_support import resume,captured
|
| 5 |
+
from analyze_qvm_acceleration import word
|
| 6 |
+
L=H+0xa0000
|
| 7 |
+
EVENT=L+0x10000
|
| 8 |
+
FIELDS=[4,12,44,76,84,104,140,144,148,184,208,220,232,236,280,3096,4300,4304,4308,4312,4380,4384,4388,4392,6324,6332]
|
| 9 |
+
EFIELDS=[0,140,144,160,168,184,200,204,424]
|
| 10 |
|
| 11 |
+
def seed(raw,h,**a):
|
| 12 |
+
m=health_seed(raw,h)
|
| 13 |
+
m.update(constants(raw,h,list(range(29584,29808,4))+list(range(4032,17416,4))))
|
| 14 |
+
for o in range(0,180,4):m[L+o]=0
|
| 15 |
+
m.update({L+72:TARGET,L+76:ATTACKER if a.get('attacker',True) else 0,L+80:a.get('flag',0),L+164:TARGET,L+168:ATTACKER,L+172:a.get('method',12),34090788:a.get('mode',10),34999596:a.get('blocked',0),34992532:a.get('now',10000),98588:a.get('disclose',0),34999668:7,34999672:9,34087532:a.get('penalty',1),34075396:a.get('limit',3),TARGET+168:65,ATTACKER+168:7,ATTACKER+764:a.get('strikes',0),ATTACKER+768:a.get('last',0),ATTACKER+424:a.get('attacker_flags',0)})
|
| 16 |
+
for o in FIELDS:m[CLIENT+o]=a.get('c'+str(o),0x1ffff if o in (104,220,236) else 7)
|
| 17 |
+
m.update({CLIENT+232:a.get('count',31990),CLIENT+6332:word(a.get('heat',10)),CLIENT+4:a.get('state',0),CLIENT+12:a.get('flags12',8),CLIENT+144:0,CLIENT+312:a.get('weapon',1),CLIENT+3096:a.get('team',1),A_CLIENT+3096:a.get('attacker_team',1),A_CLIENT+232:1234,A_CLIENT+140:7})
|
| 18 |
+
return m
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
|
| 20 |
+
def snapshot(m):
|
| 21 |
+
return {'client':{str(o):m[CLIENT+o]&0xffffffff for o in FIELDS},'attacker_count':m[A_CLIENT+232]&0xffffffff,'entity':{str(o):m[TARGET+o]&0xffffffff for o in [684,720]},'attacker':{str(o):m[ATTACKER+o]&0xffffffff for o in [764,768]},'team_counts':[m[34999668]&0xffffffff,m[34999672]&0xffffffff]}
|
| 22 |
|
| 23 |
+
def handlers(effects,resolvers=None):
|
| 24 |
+
def event(ins,m,args):
|
| 25 |
+
p=EVENT+len(effects['events'])*880
|
| 26 |
+
for o in range(0,880,4):m[p+o]=0
|
| 27 |
+
effects['events'].append({'arguments':args,'pointer':p,'fixture_allocation':True})
|
| 28 |
+
return m,p,{'supplied_event_pointer':p,'original_allocator_not_executed':True}
|
| 29 |
+
hs={t:captured(t,effects['requests']) for t in [7259,205260,6369,6439,278834,285486,-17,-18]}
|
| 30 |
+
def predicate(ins,m,args):
|
| 31 |
+
from qvm_contact_support import predicate as actual
|
| 32 |
+
return actual(ins,m,args)
|
| 33 |
+
def formatting(ins,m,args):
|
| 34 |
+
effects['requests'].append({'target':70458,'arguments':args,'native_effect_not_executed':True});return m,EVENT+0x10000,{'supplied_string_pointer':EVENT+0x10000}
|
| 35 |
+
hs.update({277695:event,33715:predicate,70458:formatting});hs.update(resolvers or {});return hs
|
| 36 |
|
| 37 |
+
def probe(ins,m,start,stop,protected=False,resolvers=None):
|
| 38 |
+
before=snapshot(m);effects={'events':[],'requests':[]};end=152671 if protected else 207154
|
| 39 |
+
m,e=resume(ins,start,end,m,L,handlers=handlers(effects,resolvers),boundaries=[] if stop==end else [stop],limit=50000)
|
| 40 |
+
return m,{'initial':before,'final':snapshot(m),'effects':effects,'events':[{**v,'fields':{str(o):m[v['pointer']+o]&0xffffffff for o in EFIELDS}} for v in effects['events']],'execution':e}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
scripts/qvm_session_lifecycle_support.py
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Recovered session initialization and connected persistence compositions."""
|
| 2 |
+
from qvm_camera_world_support import B,run
|
| 3 |
+
from qvm_exit_rules_support import CPOOL
|
| 4 |
+
from qvm_persistence_support import info_lookup,load_position,save_position
|
| 5 |
+
from qvm_session_support import session,FIELDS
|
| 6 |
+
from qvm_string_memory_support import cstring,copy_bounded
|
| 7 |
+
from qvm_byte_memory_support import read_bytes
|
| 8 |
+
INIT=B+0x50000
|
| 9 |
+
SIZE=944
|
| 10 |
+
|
| 11 |
+
def initialize(ins,m,b,pointer,userinfo,handle,ticks):
|
| 12 |
+
from qvm_persistence_support import INFO
|
| 13 |
+
from qvm_map_commands_support import put_string
|
| 14 |
+
put_string(m,b,INFO,userinfo);parts={};diagnostics=[]
|
| 15 |
+
def classify(i,m,a,bs):
|
| 16 |
+
m,v,p,b=run(i,m,33715,33740,12,a,dict(bs),base=B+0x52000);return m,v,{'actual_source_child':33715}
|
| 17 |
+
def lookup(i,m,a,bs):
|
| 18 |
+
m,v,p,b=info_lookup(i,m,dict(bs),a);return m,v,{'actual_source_child':70503,'child_memory_bytes':{v+j:x for j,x in enumerate(cstring(m,b,v)+b'\0')}}
|
| 19 |
+
def clock(i,m,a,bs):return m,ticks,{'engine_ticks_supplied':True}
|
| 20 |
+
def copy(i,m,a,bs):return copy_bounded(i,m,a,dict(bs))
|
| 21 |
+
def load(i,m,a,bs):
|
| 22 |
+
data=b'9,8,7,6,5,4';m,p,b=load_position(i,m,dict(bs),a[8],userinfo,b'ut4_test',handle,len(data),data);parts['load']=p;return m,0,{'actual_source_child':246554}
|
| 23 |
+
def write(i,m,a,bs):
|
| 24 |
+
m,p,b=session(i,m,dict(bs),a[8]);parts['session']=p;return m,0,{'actual_source_child':246963}
|
| 25 |
+
def diagnostic(i,m,a,bs):diagnostics.append([a[8],a[12]&0xffffffff,a[16]&0xffffffff]);return m,0,{'diagnostic_captured':True}
|
| 26 |
+
m,v,p,b=run(ins,m,247520,247806,40,{8:pointer,12:INFO},b,{33715:classify,70503:lookup,-3:clock,69338:copy,246554:load,246963:write,7259:diagnostic},base=INIT);p.update(parts=parts,diagnostics=diagnostics);return m,p,b
|
| 27 |
+
|
| 28 |
+
def raw_state(m,b,pointer):return read_bytes(m,b,pointer+3096,SIZE).hex()
|
| 29 |
+
|
| 30 |
+
def post_full(ins,m,b,userinfos,names,handles):
|
| 31 |
+
calls=[];files=[];sets=[];actions=[]
|
| 32 |
+
def save(i,m,a,bs):
|
| 33 |
+
j=(a[8]-CPOOL)//6336;calls.append([246746,j]);m,p,b=save_position(i,m,dict(bs),a[8],userinfos[j],b'ut4_test',handles[j],-7);files.append([j,p['events']]);actions.extend(dict(e,kind='file',slot=j) for e in p['events']);return m,0,{'actual_source_child':246746}
|
| 34 |
+
def write(i,m,a,bs):
|
| 35 |
+
j=(a[8]-CPOOL)//6336;calls.append([246963,j]);m,p,b=session(i,m,dict(bs),a[8]);sets.extend(p['sets']);actions.extend(dict(kind='cvar',slot=j,key=k,value=v) for k,v in p['sets']);return m,0,{'actual_source_child':246963}
|
| 36 |
+
m,v,p,b=run(ins,m,249007,249058,16,b=b,handlers={246746:save,246963:write},base=B+0x54000);p.update(calls=calls,files=files,sets=sets,actions=actions);return m,p,b
|
| 37 |
+
|
| 38 |
+
CONNECT=B+0x58000
|
| 39 |
+
CLIENT_BYTES=6336
|
| 40 |
+
def connect_branch(ins,m,b,slot,first,userinfo,handle):
|
| 41 |
+
import hashlib,json
|
| 42 |
+
from qvm_map_commands_support import put_string
|
| 43 |
+
from qvm_persistence_support import restore_session
|
| 44 |
+
entity=34091368+880*slot;pointer=CPOOL+6336*slot;m[CONNECT+24]=entity;put_string(m,b,CONNECT+28,userinfo,1024);parts={};choice=[]
|
| 45 |
+
def zero(i,m,a,bs):
|
| 46 |
+
if a[8]!=pointer or a[12]!=0 or a[16]!=6336:raise ValueError('unsupported connect memset')
|
| 47 |
+
return m,a[8],{'native_memset_modeled':True,'child_memory_bytes':{pointer+j:0 for j in range(6336)}}
|
| 48 |
+
def fresh(i,m,a,bs):
|
| 49 |
+
choice.append(247520);m,p,b=initialize(i,m,dict(bs),a[8],userinfo,handle,17);parts.update(p);return m,0,{'actual_source_child':247520}
|
| 50 |
+
def restored(i,m,a,bs):
|
| 51 |
+
choice.append(247219);data=b'9,8,7,6,5,4';m,p,b=restore_session(i,m,dict(bs),a[8],b'1,-2,3,4,5,1,1,1,1',b'1,3,',userinfo,b'ut4_test',handle,len(data),data);parts.update(p);return m,0,{'actual_source_child':247219}
|
| 52 |
+
m,v,p,b=run(ins,m,174080,174174,1080,{8:slot,12:first,16:0},b,{-101:zero,247520:fresh,247219:restored},base=CONNECT);changes=p.pop('changes');p.update(change_count=len(changes),changes_sha256=hashlib.sha256(json.dumps(changes,sort_keys=True).encode()).hexdigest(),choice=choice,parts=parts,entity_linked=m[entity+520]==pointer,entity_clear=[m[entity+764]&0xffffffff,m[entity+768]&0xffffffff]);return m,p,b
|
scripts/test_qvm_session_init.py
CHANGED
|
@@ -4,6 +4,7 @@ class OriginalTests(unittest.TestCase):
|
|
| 4 |
def test_instruction_results(self):
|
| 5 |
rows=json.loads(Path('docs/research/qvm-session-init.json').read_text())['probes']
|
| 6 |
self.assertEqual(len(rows),96)
|
|
|
|
| 7 |
import struct
|
| 8 |
from analyze_qvm_acceleration import word
|
| 9 |
for p in rows:
|
|
|
|
| 4 |
def test_instruction_results(self):
|
| 5 |
rows=json.loads(Path('docs/research/qvm-session-init.json').read_text())['probes']
|
| 6 |
self.assertEqual(len(rows),96)
|
| 7 |
+
self.assertTrue(any(int.from_bytes(bytes.fromhex(p["raw"])[44:48],"little")>=2**31 for p in rows))
|
| 8 |
import struct
|
| 9 |
from analyze_qvm_acceleration import word
|
| 10 |
for p in rows:
|
scripts/test_rust_connect_session.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-session.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-session.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
|
@@ -2887,3 +2887,21 @@ report scripts/analyze_qvm_connect_session.py docs/research/qvm-connect-session.
|
|
| 2887 |
edge docs/research/qvm-connect-session.json scripts/test_qvm_connect_session.py
|
| 2888 |
group qvm-connect-session scripts/analyze_qvm_connect_session.py
|
| 2889 |
edge scripts/analyze_qvm_connect_session.py scripts/analyze_qvm_resumer_audit.py
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2887 |
edge docs/research/qvm-connect-session.json scripts/test_qvm_connect_session.py
|
| 2888 |
group qvm-connect-session scripts/analyze_qvm_connect_session.py
|
| 2889 |
edge scripts/analyze_qvm_connect_session.py scripts/analyze_qvm_resumer_audit.py
|
| 2890 |
+
edge Cargo.toml scripts/analyze_rust_connect_session.py
|
| 2891 |
+
edge Cargo.lock scripts/analyze_rust_connect_session.py
|
| 2892 |
+
edge crates/urt-gameplay/Cargo.toml scripts/analyze_rust_connect_session.py
|
| 2893 |
+
edge crates/urt-gameplay/src/lib.rs scripts/analyze_rust_connect_session.py
|
| 2894 |
+
edge crates/urt-gameplay/src/native_policy.rs scripts/analyze_rust_connect_session.py
|
| 2895 |
+
edge crates/urt-gameplay/src/bin/urt-native-policy.rs scripts/analyze_rust_connect_session.py
|
| 2896 |
+
edge docs/research/qvm-connect-session.json scripts/analyze_rust_connect_session.py
|
| 2897 |
+
group rust-connect-session scripts/analyze_rust_health_impulse.py
|
| 2898 |
+
group gameplay scripts/analyze_rust_connect_session.py
|
| 2899 |
+
edge crates/urt-gameplay/src/intermission.rs scripts/analyze_rust_connect_session.py
|
| 2900 |
+
edge crates/urt-gameplay/src/qvm_format.rs scripts/analyze_rust_connect_session.py
|
| 2901 |
+
report scripts/analyze_rust_connect_session.py docs/research/rust-connect-session.json
|
| 2902 |
+
edge docs/research/rust-connect-session.json scripts/test_rust_connect_session.py
|
| 2903 |
+
group rust-connect-session scripts/analyze_rust_connect_session.py
|
| 2904 |
+
edge scripts/analyze_rust_connect_session.py scripts/analyze_qvm_resumer_audit.py
|
| 2905 |
+
group rust-connect-session scripts/analyze_qvm_session_init.py
|
| 2906 |
+
edge scripts/qvm_session_lifecycle_support.py scripts/analyze_qvm_resumer_audit.py
|
| 2907 |
+
group rust-connect-session scripts/analyze_qvm_health_mode10.py
|
xtask/src/lib.rs
CHANGED
|
@@ -1055,6 +1055,10 @@ mod integration_tests {
|
|
| 1055 |
.unwrap();
|
| 1056 |
g.scanner(&output).unwrap();
|
| 1057 |
assert!(g.warnings.is_empty(), "{:?}", g.warnings);
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1058 |
let health = plan(
|
| 1059 |
&g,
|
| 1060 |
&["scripts/qvm_health_support.py".into()]
|
|
@@ -1105,6 +1109,14 @@ mod integration_tests {
|
|
| 1105 |
("native_policy", "position_load"),
|
| 1106 |
("native_policy", "session_restore"),
|
| 1107 |
("intermission", "session_restore"),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1108 |
("protected", "protected_update"),
|
| 1109 |
("mode10", "mode10_entry"),
|
| 1110 |
("intercept_animation", "mode10_animation"),
|
|
@@ -1179,6 +1191,11 @@ mod integration_tests {
|
|
| 1179 |
("qvm-position-save", "position_save"),
|
| 1180 |
("qvm-position-load", "position_load"),
|
| 1181 |
("qvm-session-restore", "session_restore"),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1182 |
("qvm-rank-small-sort", "rank_sort"),
|
| 1183 |
("qvm-rank-large-sort", "rank_sort"),
|
| 1184 |
("qvm-ranking-complete", "ranking_complete"),
|
|
|
|
| 1055 |
.unwrap();
|
| 1056 |
g.scanner(&output).unwrap();
|
| 1057 |
assert!(g.warnings.is_empty(), "{:?}", g.warnings);
|
| 1058 |
+
// Keep independent health and session helper namespaces importable.
|
| 1059 |
+
// A filename collision must fail this scoped registry regression.
|
| 1060 |
+
capture(root,&Cmd::new(&python_runtime().expect("run cargo test inside nix develop"),["-I","-c","import sys; sys.path.insert(0, 'scripts'); from qvm_lifecycle_support import seed, probe; from qvm_session_lifecycle_support import initialize, post_full, connect_branch"])).unwrap();
|
| 1061 |
+
|
| 1062 |
let health = plan(
|
| 1063 |
&g,
|
| 1064 |
&["scripts/qvm_health_support.py".into()]
|
|
|
|
| 1109 |
("native_policy", "position_load"),
|
| 1110 |
("native_policy", "session_restore"),
|
| 1111 |
("intermission", "session_restore"),
|
| 1112 |
+
("native_policy", "session_init"),
|
| 1113 |
+
("native_policy", "post_map_files"),
|
| 1114 |
+
("native_policy", "normal_map_files"),
|
| 1115 |
+
("native_policy", "persistence_roundtrip"),
|
| 1116 |
+
("native_policy", "connect_session"),
|
| 1117 |
+
("map_commands", "normal_map_files"),
|
| 1118 |
+
("transition", "normal_map_files"),
|
| 1119 |
+
("intermission", "connect_session"),
|
| 1120 |
("protected", "protected_update"),
|
| 1121 |
("mode10", "mode10_entry"),
|
| 1122 |
("intercept_animation", "mode10_animation"),
|
|
|
|
| 1191 |
("qvm-position-save", "position_save"),
|
| 1192 |
("qvm-position-load", "position_load"),
|
| 1193 |
("qvm-session-restore", "session_restore"),
|
| 1194 |
+
("qvm-session-init", "session_init"),
|
| 1195 |
+
("qvm-post-map-files", "post_map_files"),
|
| 1196 |
+
("qvm-normal-map-files", "normal_map_files"),
|
| 1197 |
+
("qvm-persistence-roundtrip", "persistence_roundtrip"),
|
| 1198 |
+
("qvm-connect-session", "connect_session"),
|
| 1199 |
("qvm-rank-small-sort", "rank_sort"),
|
| 1200 |
("qvm-rank-large-sort", "rank_sort"),
|
| 1201 |
("qvm-ranking-complete", "ranking_complete"),
|