From d998c08219bf1d2254d277cab6e094733a5fd26e Mon Sep 17 00:00:00 2001 From: Jan Petykiewicz Date: Sat, 18 Apr 2026 14:42:01 -0700 Subject: [PATCH] Correlate infrastructure prelude classes by profile span --- crates/rrt-runtime/src/smp.rs | 376 ++++++++++++++++++ ...ntime-roots-camera-and-support-families.md | 5 + docs/rehost-queue.md | 6 + 3 files changed, 387 insertions(+) diff --git a/crates/rrt-runtime/src/smp.rs b/crates/rrt-runtime/src/smp.rs index 773e78b..d49c5bd 100644 --- a/crates/rrt-runtime/src/smp.rs +++ b/crates/rrt-runtime/src/smp.rs @@ -1950,6 +1950,9 @@ pub struct SmpSavePlacedStructureDynamicSideBufferPayloadEnvelopeSummary { #[serde(default)] pub fixed_policy_summary: Option, #[serde(default)] + pub name_prelude_candidate_summary: + Option, + #[serde(default)] pub sample_rows: Vec, } @@ -2049,6 +2052,70 @@ pub struct SmpSavePlacedStructureDynamicSideBufferPayloadEnvelopeSample { pub profile_chunk_len_to_next_name_or_end: Option, } +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct SmpSavePlacedStructureDynamicSideBufferNamePreludeCandidateSummary { + pub row_count_with_candidate_window: usize, + pub unique_candidate_pattern_count: usize, + #[serde(default)] + pub dominant_child_count_candidate: Option, + pub dominant_child_count_candidate_count: usize, + #[serde(default)] + pub dominant_saved_primary_child_byte_candidate: Option, + #[serde(default)] + pub dominant_saved_primary_child_byte_candidate_hex: Option, + pub dominant_saved_primary_child_byte_candidate_count: usize, + #[serde(default)] + pub dominant_candidate_pattern: + Option, + #[serde(default)] + pub profile_span_correlations: + Vec, + #[serde(default)] + pub sample_rows: Vec, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct SmpSavePlacedStructureDynamicSideBufferNamePreludeCandidatePattern { + pub child_count_candidate: u16, + pub child_count_candidate_hex: String, + pub saved_primary_child_byte_candidate: u8, + pub saved_primary_child_byte_candidate_hex: String, + pub count: usize, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct SmpSavePlacedStructureDynamicSideBufferNamePreludeCandidateSample { + pub sample_index: usize, + pub name_tag_relative_offset: usize, + #[serde(default)] + pub primary_name: Option, + #[serde(default)] + pub secondary_name: Option, + pub child_count_candidate: u16, + pub child_count_candidate_hex: String, + pub saved_primary_child_byte_candidate: u8, + pub saved_primary_child_byte_candidate_hex: String, + #[serde(default)] + pub previous_profile_chunk_len_to_next_name_or_end: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct SmpSavePlacedStructureDynamicSideBufferNamePreludeProfileSpanCorrelation { + pub previous_profile_chunk_len_to_next_name_or_end: usize, + pub row_count: usize, + #[serde(default)] + pub dominant_child_count_candidate: Option, + pub dominant_child_count_candidate_count: usize, + #[serde(default)] + pub dominant_saved_primary_child_byte_candidate: Option, + #[serde(default)] + pub dominant_saved_primary_child_byte_candidate_hex: Option, + pub dominant_saved_primary_child_byte_candidate_count: usize, + #[serde(default)] + pub dominant_candidate_pattern: + Option, +} + #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct SmpSavePlacedStructureDynamicSideBufferLiveEntryPreludeSummary { pub live_entry_directory_row_count: usize, @@ -4247,6 +4314,72 @@ fn build_infrastructure_asset_trace_report( .map(|summary| summary.dominant_trailing_word_count) .unwrap_or_default() ), + side_buffer + .and_then(|probe| probe.payload_envelope_summary.as_ref()) + .and_then(|summary| summary.name_prelude_candidate_summary.as_ref()) + .and_then(|summary| { + summary + .profile_span_correlations + .iter() + .find(|row| row.previous_profile_chunk_len_to_next_name_or_end == 3) + }) + .map(|correlation| { + format!( + "current save-side probe now also shows the short 0x03-byte post-profile gaps collapsing cleanly to the next-record prelude: dominant candidate pattern is {}/{} x{} across {} rows", + correlation + .dominant_candidate_pattern + .as_ref() + .map(|pattern| pattern.child_count_candidate_hex.as_str()) + .unwrap_or("0x0000"), + correlation + .dominant_candidate_pattern + .as_ref() + .map(|pattern| pattern.saved_primary_child_byte_candidate_hex.as_str()) + .unwrap_or("0x00"), + correlation + .dominant_candidate_pattern + .as_ref() + .map(|pattern| pattern.count) + .unwrap_or_default(), + correlation.row_count + ) + }) + .unwrap_or_else(|| { + "no grounded 0x03-byte post-profile span correlation was available for the prelude candidates".to_string() + }), + side_buffer + .and_then(|probe| probe.payload_envelope_summary.as_ref()) + .and_then(|summary| summary.name_prelude_candidate_summary.as_ref()) + .and_then(|summary| { + summary + .profile_span_correlations + .iter() + .find(|row| row.previous_profile_chunk_len_to_next_name_or_end == 0) + }) + .map(|correlation| { + format!( + "the zero-length post-profile class is now a separate grounded outlier: dominant candidate pattern is {}/{} x{} across {} rows", + correlation + .dominant_candidate_pattern + .as_ref() + .map(|pattern| pattern.child_count_candidate_hex.as_str()) + .unwrap_or("0x0000"), + correlation + .dominant_candidate_pattern + .as_ref() + .map(|pattern| pattern.saved_primary_child_byte_candidate_hex.as_str()) + .unwrap_or("0x00"), + correlation + .dominant_candidate_pattern + .as_ref() + .map(|pattern| pattern.count) + .unwrap_or_default(), + correlation.row_count + ) + }) + .unwrap_or_else(|| { + "no grounded zero-length post-profile span correlation was available for the prelude candidates".to_string() + }), "direct disassembly now also shows 0x530720 publishing the first fixed-triplet lane into [this+0x1e2/+0x1e6/+0x1ea], while 0x52e8b0 publishes the second fixed-triplet lane into [this+0x4b/+0x4f/+0x53] and sets bit 0x02".to_string(), "direct disassembly now also shows the outer owner at 0x0048dcf0 reading one u16 child count through 0x531150 into the stream prelude, zeroing [this+0x08], and conditionally reading one saved primary-child byte before the per-child callback loop runs".to_string(), side_buffer @@ -12789,6 +12922,224 @@ fn parse_save_placed_structure_dynamic_side_buffer_probe( ) .collect(), }); + let name_prelude_candidate_rows = embedded_name_rows + .iter() + .enumerate() + .filter_map(|(row_index, row)| { + let candidate_offset = row.name_tag_relative_offset.checked_sub(3)?; + let child_count_candidate = read_u16_at(records_payload, candidate_offset)?; + let saved_primary_child_byte_candidate = + read_u8_at(records_payload, candidate_offset + 2)?; + Some(( + row.name_tag_relative_offset, + row.primary_name.clone(), + row.secondary_name.clone(), + child_count_candidate, + saved_primary_child_byte_candidate, + row_index + .checked_sub(1) + .and_then(|previous_index| { + payload_envelope_rows + .get(previous_index) + .and_then(|row| row.profile_chunk_len_to_next_name_or_end) + }), + )) + }) + .collect::>(); + let mut name_prelude_candidate_pattern_counts = BTreeMap::<(u16, u8), usize>::new(); + let mut name_prelude_child_count_counts = BTreeMap::::new(); + let mut name_prelude_saved_primary_counts = BTreeMap::::new(); + for (_, _, _, child_count_candidate, saved_primary_child_byte_candidate, _) in + &name_prelude_candidate_rows + { + *name_prelude_candidate_pattern_counts + .entry((*child_count_candidate, *saved_primary_child_byte_candidate)) + .or_default() += 1; + *name_prelude_child_count_counts + .entry(*child_count_candidate) + .or_default() += 1; + *name_prelude_saved_primary_counts + .entry(*saved_primary_child_byte_candidate) + .or_default() += 1; + } + let dominant_name_prelude_candidate_pattern = name_prelude_candidate_pattern_counts + .iter() + .max_by(|(left_key, left_count), (right_key, right_count)| { + left_count + .cmp(right_count) + .then_with(|| right_key.cmp(left_key)) + }) + .map( + |((child_count_candidate, saved_primary_child_byte_candidate), count)| { + SmpSavePlacedStructureDynamicSideBufferNamePreludeCandidatePattern { + child_count_candidate: *child_count_candidate, + child_count_candidate_hex: format!("0x{child_count_candidate:04x}"), + saved_primary_child_byte_candidate: *saved_primary_child_byte_candidate, + saved_primary_child_byte_candidate_hex: format!( + "0x{saved_primary_child_byte_candidate:02x}" + ), + count: *count, + } + }, + ); + let dominant_name_prelude_child_count = name_prelude_child_count_counts + .iter() + .max_by(|(left_key, left_count), (right_key, right_count)| { + left_count + .cmp(right_count) + .then_with(|| right_key.cmp(left_key)) + }) + .map(|(value, count)| (*value, *count)); + let dominant_name_prelude_saved_primary = name_prelude_saved_primary_counts + .iter() + .max_by(|(left_key, left_count), (right_key, right_count)| { + left_count + .cmp(right_count) + .then_with(|| right_key.cmp(left_key)) + }) + .map(|(value, count)| (*value, *count)); + let mut name_prelude_profile_span_groups = + BTreeMap::>::new(); + for (_, _, _, child_count_candidate, saved_primary_child_byte_candidate, previous_span) in + &name_prelude_candidate_rows + { + if let Some(previous_span) = previous_span { + name_prelude_profile_span_groups + .entry(*previous_span) + .or_default() + .push((*child_count_candidate, *saved_primary_child_byte_candidate)); + } + } + let profile_span_correlations = name_prelude_profile_span_groups + .into_iter() + .map(|(previous_profile_chunk_len_to_next_name_or_end, rows)| { + let mut pattern_counts = BTreeMap::<(u16, u8), usize>::new(); + let mut child_count_counts = BTreeMap::::new(); + let mut saved_primary_counts = BTreeMap::::new(); + for (child_count_candidate, saved_primary_child_byte_candidate) in &rows { + *pattern_counts + .entry((*child_count_candidate, *saved_primary_child_byte_candidate)) + .or_default() += 1; + *child_count_counts.entry(*child_count_candidate).or_default() += 1; + *saved_primary_counts + .entry(*saved_primary_child_byte_candidate) + .or_default() += 1; + } + let dominant_pattern = pattern_counts + .iter() + .max_by(|(left_key, left_count), (right_key, right_count)| { + left_count + .cmp(right_count) + .then_with(|| right_key.cmp(left_key)) + }) + .map( + |((child_count_candidate, saved_primary_child_byte_candidate), count)| { + SmpSavePlacedStructureDynamicSideBufferNamePreludeCandidatePattern { + child_count_candidate: *child_count_candidate, + child_count_candidate_hex: format!( + "0x{child_count_candidate:04x}" + ), + saved_primary_child_byte_candidate: + *saved_primary_child_byte_candidate, + saved_primary_child_byte_candidate_hex: format!( + "0x{saved_primary_child_byte_candidate:02x}" + ), + count: *count, + } + }, + ); + let dominant_child_count = child_count_counts + .iter() + .max_by(|(left_key, left_count), (right_key, right_count)| { + left_count + .cmp(right_count) + .then_with(|| right_key.cmp(left_key)) + }) + .map(|(value, count)| (*value, *count)); + let dominant_saved_primary = saved_primary_counts + .iter() + .max_by(|(left_key, left_count), (right_key, right_count)| { + left_count + .cmp(right_count) + .then_with(|| right_key.cmp(left_key)) + }) + .map(|(value, count)| (*value, *count)); + SmpSavePlacedStructureDynamicSideBufferNamePreludeProfileSpanCorrelation { + previous_profile_chunk_len_to_next_name_or_end, + row_count: rows.len(), + dominant_child_count_candidate: dominant_child_count.map(|(value, _)| value), + dominant_child_count_candidate_count: dominant_child_count + .map(|(_, count)| count) + .unwrap_or_default(), + dominant_saved_primary_child_byte_candidate: dominant_saved_primary + .map(|(value, _)| value), + dominant_saved_primary_child_byte_candidate_hex: dominant_saved_primary + .map(|(value, _)| format!("0x{value:02x}")), + dominant_saved_primary_child_byte_candidate_count: dominant_saved_primary + .map(|(_, count)| count) + .unwrap_or_default(), + dominant_candidate_pattern: dominant_pattern, + } + }) + .take(8) + .collect::>(); + let name_prelude_candidate_summary = + Some(SmpSavePlacedStructureDynamicSideBufferNamePreludeCandidateSummary { + row_count_with_candidate_window: name_prelude_candidate_rows.len(), + unique_candidate_pattern_count: name_prelude_candidate_pattern_counts.len(), + dominant_child_count_candidate: dominant_name_prelude_child_count + .map(|(value, _)| value), + dominant_child_count_candidate_count: dominant_name_prelude_child_count + .map(|(_, count)| count) + .unwrap_or_default(), + dominant_saved_primary_child_byte_candidate: + dominant_name_prelude_saved_primary.map(|(value, _)| value), + dominant_saved_primary_child_byte_candidate_hex: + dominant_name_prelude_saved_primary + .map(|(value, _)| format!("0x{value:02x}")), + dominant_saved_primary_child_byte_candidate_count: + dominant_name_prelude_saved_primary + .map(|(_, count)| count) + .unwrap_or_default(), + dominant_candidate_pattern: dominant_name_prelude_candidate_pattern.clone(), + profile_span_correlations, + sample_rows: name_prelude_candidate_rows + .iter() + .take(8) + .enumerate() + .map( + |( + sample_index, + ( + name_tag_relative_offset, + primary_name, + secondary_name, + child_count_candidate, + saved_primary_child_byte_candidate, + previous_profile_chunk_len_to_next_name_or_end, + ), + )| { + SmpSavePlacedStructureDynamicSideBufferNamePreludeCandidateSample { + sample_index, + name_tag_relative_offset: *name_tag_relative_offset, + primary_name: primary_name.clone(), + secondary_name: secondary_name.clone(), + child_count_candidate: *child_count_candidate, + child_count_candidate_hex: format!( + "0x{child_count_candidate:04x}" + ), + saved_primary_child_byte_candidate: + *saved_primary_child_byte_candidate, + saved_primary_child_byte_candidate_hex: format!( + "0x{saved_primary_child_byte_candidate:02x}" + ), + previous_profile_chunk_len_to_next_name_or_end: + *previous_profile_chunk_len_to_next_name_or_end, + } + }, + ) + .collect(), + }); let payload_envelope_summary = Some( SmpSavePlacedStructureDynamicSideBufferPayloadEnvelopeSummary { row_count_with_policy_tag_before_next_name, @@ -12807,6 +13158,7 @@ fn parse_save_placed_structure_dynamic_side_buffer_probe( .unwrap_or_default(), short_profile_flag_pair_summary: short_profile_flag_pair_summary.clone(), fixed_policy_summary: fixed_policy_summary.clone(), + name_prelude_candidate_summary: name_prelude_candidate_summary.clone(), sample_rows: payload_envelope_rows .iter() .take(8) @@ -23290,6 +23642,30 @@ mod tests { sample_rows: Vec::new(), }, ), + name_prelude_candidate_summary: Some( + SmpSavePlacedStructureDynamicSideBufferNamePreludeCandidateSummary { + row_count_with_candidate_window: 118, + unique_candidate_pattern_count: 2, + dominant_child_count_candidate: Some(1), + dominant_child_count_candidate_count: 110, + dominant_saved_primary_child_byte_candidate: Some(0xff), + dominant_saved_primary_child_byte_candidate_hex: Some( + "0xff".to_string(), + ), + dominant_saved_primary_child_byte_candidate_count: 110, + dominant_candidate_pattern: Some( + SmpSavePlacedStructureDynamicSideBufferNamePreludeCandidatePattern { + child_count_candidate: 1, + child_count_candidate_hex: "0x0001".to_string(), + saved_primary_child_byte_candidate: 0xff, + saved_primary_child_byte_candidate_hex: "0xff".to_string(), + count: 110, + }, + ), + profile_span_correlations: Vec::new(), + sample_rows: Vec::new(), + }, + ), sample_rows: Vec::new(), }, ), diff --git a/docs/control-loop-atlas/runtime-roots-camera-and-support-families.md b/docs/control-loop-atlas/runtime-roots-camera-and-support-families.md index c72442a..a365fa0 100644 --- a/docs/control-loop-atlas/runtime-roots-camera-and-support-families.md +++ b/docs/control-loop-atlas/runtime-roots-camera-and-support-families.md @@ -2975,6 +2975,11 @@ The low helper strip beneath that shared family is tighter now too: `0x0052ecd0` the save-side probe be looking for above the fixed rows?”; it is the narrower partitioning problem of how the observed `0x55f3`-to-next-`0x55f1` gaps divide between the two `0x52ebd0` flag bytes and the next record’s `u16 + byte` prelude. + The widened prelude correlation narrows that again on grounded `q.gms`: the `0x03` post-profile + gap class now collapses cleanly to the next-record prelude `0x0001 / 0xff` across `17/17` rows, + while the zero-length class is a separate `0x0055 / 0x00` outlier across `18/18` rows and the + `0x06` class is the only large mixed frontier left. So the next infrastructure pass should focus + on classifying the mixed `0x06` rows instead of re-proving the pure-prelude `0x03` class. The child loader family is explicit now too: local `.rdata` at `0x005cfd00` proves the `Infrastructure` child vtable uses the shared tagged callback strip directly, with `+0x40 = 0x00455fc0`, `+0x48 = 0x00455870`, and `+0x4c = 0x00455930`. So the remaining diff --git a/docs/rehost-queue.md b/docs/rehost-queue.md index 37257ac..79c7a64 100644 --- a/docs/rehost-queue.md +++ b/docs/rehost-queue.md @@ -125,6 +125,12 @@ Working rule: looking for above the fixed rows?”; it is the narrower partitioning problem of how the observed `0x55f3`-to-next-`0x55f1` gaps divide between the two `0x52ebd0` flag bytes and the next record’s `u16 + byte` prelude. +- The widened prelude correlation closes part of that partitioning too: grounded `q.gms` rows with + a `0x03` post-profile gap now collapse cleanly to the next-record prelude pattern + `0x0001 / 0xff` across `17/17` rows, while the zero-length class is a separate grounded outlier + with dominant pattern `0x0055 / 0x00` across `18/18` rows and the `0x06` class remains the only + large mixed frontier. So the next infrastructure slice should focus on classifying the mixed + `0x06` rows, not on rediscovering the already-grounded pure-prelude `0x03` rows. - Reconstruct the save-side region record body on top of the newly corrected non-direct tagged region seam (`0x5209/0x520a/0x520b`, stride hint `0x06`, `Marker09` record stems) now that the `0x55f3` payload is known to be fully consumed by the embedded profile collection on grounded