diff --git a/crates/rrt-runtime/src/smp.rs b/crates/rrt-runtime/src/smp.rs index a3428d7..773e78b 100644 --- a/crates/rrt-runtime/src/smp.rs +++ b/crates/rrt-runtime/src/smp.rs @@ -1829,6 +1829,16 @@ pub struct SmpSavePlacedStructureDynamicSideBufferProbe { pub owner_shared_dword_hex: String, pub owner_shared_dword_relative_offset: usize, pub owner_shared_dword_matches_first_compact_prefix_leading_dword: bool, + #[serde(default)] + pub first_record_child_count_after_owner_shared: Option, + #[serde(default)] + pub first_record_child_count_after_owner_shared_hex: Option, + #[serde(default)] + pub first_record_saved_primary_child_byte_after_owner_shared: Option, + #[serde(default)] + pub first_record_saved_primary_child_byte_after_owner_shared_hex: Option, + #[serde(default)] + pub first_record_first_name_tag_relative_offset_after_owner_shared: Option, pub prefix_leading_dword: u32, pub prefix_leading_dword_hex: String, pub prefix_trailing_word: u16, @@ -1858,6 +1868,9 @@ pub struct SmpSavePlacedStructureDynamicSideBufferProbe { #[serde(default)] pub payload_envelope_summary: Option, + #[serde(default)] + pub live_entry_prelude_summary: + Option, pub evidence: Vec, } @@ -2036,6 +2049,57 @@ pub struct SmpSavePlacedStructureDynamicSideBufferPayloadEnvelopeSample { pub profile_chunk_len_to_next_name_or_end: Option, } +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct SmpSavePlacedStructureDynamicSideBufferLiveEntryPreludeSummary { + pub live_entry_directory_row_count: usize, + pub decoded_live_entry_id_count: usize, + pub payload_relative_offset_monotonic: bool, + pub rows_with_payload_pointer_inside_records_span: usize, + pub rows_with_zero_child_count: usize, + pub rows_with_nonzero_child_count: usize, + pub rows_with_first_name_tag_after_prelude: usize, + pub rows_with_first_name_tag_at_offset_3: usize, + #[serde(default)] + pub unique_child_count_values: Vec, + #[serde(default)] + pub unique_first_name_tag_relative_offsets: Vec, + #[serde(default)] + pub dominant_child_count: Option, + pub dominant_child_count_count: usize, + #[serde(default)] + pub dominant_saved_primary_child_byte: Option, + #[serde(default)] + pub dominant_saved_primary_child_byte_hex: Option, + pub dominant_saved_primary_child_byte_count: usize, + #[serde(default)] + pub dominant_first_name_tag_relative_offset: Option, + pub dominant_first_name_tag_relative_offset_count: usize, + #[serde(default)] + pub sample_rows: Vec, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct SmpSavePlacedStructureDynamicSideBufferLiveEntryPreludeSample { + pub sample_index: usize, + pub live_entry_id: u32, + pub payload_relative_offset: u32, + pub payload_relative_offset_hex: String, + pub payload_relative_to_records: usize, + pub child_count: u16, + pub child_count_hex: String, + pub saved_primary_child_byte: u8, + pub saved_primary_child_byte_hex: String, + pub first_payload_dword_hex: String, + #[serde(default)] + pub first_name_tag_relative_offset: Option, + #[serde(default)] + pub first_primary_name: Option, + #[serde(default)] + pub first_secondary_name: Option, + #[serde(default)] + pub first_tertiary_name: Option, +} + #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct SmpSavePlacedStructureDynamicSideBufferAlignmentProbe { pub unique_side_buffer_name_pair_count: usize, @@ -4031,6 +4095,7 @@ fn build_infrastructure_asset_trace_report( "0x004133b0 placed-structure local-runtime refresh outer owner".to_string(), ]; let known_owner_bridge_fields = vec![ + "outer stream prelude [u16 child count, optional saved primary-child byte]".to_string(), "[this+0x248] cached primary-child slot".to_string(), "[this+0x206/+0x20a/+0x20e] route-entry resolver fields".to_string(), "[this+0x1e2/+0x1e6/+0x1ea] published anchor triplet".to_string(), @@ -4055,7 +4120,7 @@ fn build_infrastructure_asset_trace_report( "0x0048e140 / 0x0048e160 / 0x0048e180 route-entry resolver helpers".to_string(), ]; let next_owner_questions = vec![ - "Which exact 0x38a5 rows or compact-prefix regimes feed the child count and optional primary-child ordinal that 0x0048dcf0 restores before the later rebuild loop runs?".to_string(), + "How do the observed 0x55f3-to-next-0x55f1 gaps partition between child-local 0x52ebd0 flag bytes and the now-grounded next-record prelude [u16 child count, saved primary-child byte], starting from the first 0x38a6 record head 0x0001/0xff/0x55f1?".to_string(), "Which 0x38a5 embedded name-pair groups survive into the per-child vtable +0x40 payload callbacks dispatched through 0x00455a50?".to_string(), "Is cached primary-child slot [this+0x248] the first owner-visible bridge from the restored child stream into route-entry rebuild?".to_string(), ]; @@ -4087,6 +4152,28 @@ fn build_infrastructure_asset_trace_report( "atlas already bounds these helpers under the literal Infrastructure owner".to_string(), "the side-buffer corpus is disjoint from the placed-structure triplet corpus, so a separate child/rebuild family is more plausible than a compact alias".to_string(), "direct disassembly now shows 0x00493be0 opening tag family 0x38a5/0x38a6/0x38a7, reading one shared dword into the owner-local 0x90/0x94 lane, iterating each live collection entry, and dispatching every loaded infrastructure record through 0x0048dcf0 before the later follow-on owners run".to_string(), + side_buffer + .and_then(|probe| probe.first_record_child_count_after_owner_shared) + .map(|child_count| { + format!( + "grounded q.gms bytes now also show the first 0x38a6 record starting immediately after that shared dword with child_count={}, saved_primary_child_byte={}, and first 0x55f1 at offset +0x{:x}", + child_count, + side_buffer + .and_then(|probe| { + probe.first_record_saved_primary_child_byte_after_owner_shared_hex + .as_deref() + }) + .unwrap_or("0x00"), + side_buffer + .and_then(|probe| { + probe.first_record_first_name_tag_relative_offset_after_owner_shared + }) + .unwrap_or_default() + ) + }) + .unwrap_or_else(|| { + "no grounded first-record prelude summary was available after the shared 0x38a6 owner dword".to_string() + }), "direct disassembly now shows 0x00518140 resolving a non-direct live entry through the tombstone bitset and then returning the first dword of a 12-byte row from [collection+0x3c] for the 0x38a5 path".to_string(), "direct disassembly now also shows 0x005181f0/0x00518260 treating the same 12-byte rows as a live-entry directory: dword +0 is the payload pointer, dword +4 is previous live id, and dword +8 is next live id, with collection head/tail caches alongside them".to_string(), "direct disassembly now also shows 0x00493be0 iterating live-entry ordinals through 0x00518380(ordinal, 0), converting each ordinal to a live id, then resolving that live id through 0x00518140 before handing the resulting payload pointer to 0x0048dcf0".to_string(), @@ -4161,6 +4248,26 @@ fn build_infrastructure_asset_trace_report( .unwrap_or_default() ), "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 + .and_then(|probe| probe.live_entry_prelude_summary.as_ref()) + .map(|summary| { + format!( + "the widened save-side probe now also decodes {} live-entry payload starts inside the records span; dominant child count={} x{}, dominant saved primary-child byte={} x{}, and {} payloads reach the first 0x55f1 child callback at offset +0x3", + summary.rows_with_payload_pointer_inside_records_span, + summary.dominant_child_count.unwrap_or_default(), + summary.dominant_child_count_count, + summary + .dominant_saved_primary_child_byte_hex + .as_deref() + .unwrap_or("0x00"), + summary.dominant_saved_primary_child_byte_count, + summary.rows_with_first_name_tag_at_offset_3 + ) + }) + .unwrap_or_else(|| { + "no live-entry payload-start summary was available for the outer prelude".to_string() + }), "local .rdata at 0x005cfd00 now also proves the infrastructure child table uses the shared tagged callback strip directly: slot +0x40 = 0x455fc0, slot +0x48 = 0x455870, and slot +0x4c = 0x455930".to_string(), "direct disassembly now shows 0x0048a1e0 cloning the first child triplet bands through 0x52e880/0x52e720, destroying the prior child, seeding a new literal Infrastructure child through 0x455b70 with payload seed 0x5c87a8, attaching through 0x5395d0 or 0x53a5d0, and republishing the two bands through 0x52e8b0/0x530720".to_string(), "direct disassembly now also shows the outer owner at 0x0048dcf0 reading a child count plus optional primary-child ordinal from the tagged stream through 0x531150, zeroing [this+0x08], dispatching each fresh child through 0x455a50 -> vtable slot +0x40, culling ordinals above 5, and restoring cached primary-child slot [this+0x248] from the saved ordinal".to_string(), @@ -4168,7 +4275,7 @@ fn build_infrastructure_asset_trace_report( ], blockers: vec![ "how the payload streams reached through 0x00518380 -> 0x00518140 align with the embedded 0x55f1 name-pair groups and compact-prefix regimes surfaced by the save-side probe".to_string(), - "which outer-stream tagged values, outside the now-spoken-for fixed 0x55f2 triplets and short trailing flag bytes, correspond to the child count and optional primary-child ordinal consumed by 0x0048dcf0".to_string(), + "how the observed 0x55f3-to-next-0x55f1 gaps partition between the two 0x52ebd0 flag bytes and the next-record prelude now that the first 0x38a6 record head is grounded as child_count=1, saved_primary_child_byte=0xff, first 0x55f1 at +0x3".to_string(), "which restored child fields or grouped rows retain the 0x38a5 embedded name-pair semantics before route/local-runtime follow-ons take over".to_string(), ], }, @@ -12120,6 +12227,13 @@ fn parse_save_placed_structure_dynamic_side_buffer_probe( continue; }; let owner_shared_dword_relative_offset = 0usize; + let first_record_child_count_after_owner_shared = read_u16_at(records_payload, 4); + let first_record_saved_primary_child_byte_after_owner_shared = + read_u8_at(records_payload, 6); + let first_record_first_name_tag_relative_offset_after_owner_shared = (3usize..=16usize) + .find(|offset| { + read_u16_at(records_payload, 4 + *offset) == Some(SAVE_REGION_RECORD_NAME_TAG) + }); let prefix_leading_dword = owner_shared_dword; let Some(prefix_trailing_word) = read_u16_at(prefix_payload, 4) else { continue; @@ -12716,6 +12830,190 @@ fn parse_save_placed_structure_dynamic_side_buffer_probe( .collect(), }, ); + let bitset_len = ((usize::try_from(summary.live_id_bound).ok()?).saturating_add(8)) / 8; + let live_entry_prelude_summary = payload + .get( + INDEXED_COLLECTION_SERIALIZED_HEADER_LEN + ..INDEXED_COLLECTION_SERIALIZED_HEADER_LEN + bitset_len, + ) + .and_then(|bitset| { + let live_entry_ids = + decode_live_entry_ids_from_tombstone_bitset(bitset, summary.live_id_bound)?; + if live_entry_ids.len() != usize::try_from(summary.live_record_count).ok()? { + return None; + } + #[derive(Clone)] + struct LiveEntryPreludeRow { + live_entry_id: u32, + payload_relative_offset: usize, + child_count: u16, + saved_primary_child_byte: u8, + first_payload_dword: u32, + first_name_tag_relative_offset: Option, + first_primary_name: Option, + first_secondary_name: Option, + first_tertiary_name: Option, + } + let mut rows = Vec::new(); + let mut cursor = 0usize; + for live_entry_id in live_entry_ids.iter().copied() { + let payload_len = usize::from(read_u16_at(records_payload, cursor)?); + let payload_relative_offset = cursor.checked_add(2)?; + let payload_end = payload_relative_offset.checked_add(payload_len)?; + let payload_bytes = + records_payload.get(payload_relative_offset..payload_end)?; + let child_count = read_u16_at(payload_bytes, 0)?; + let saved_primary_child_byte = read_u8_at(payload_bytes, 2)?; + let first_payload_dword = read_u32_at(payload_bytes, 0)?; + let first_name_tag_relative_offset = (0usize..=16usize).find(|offset| { + read_u16_at(payload_bytes, *offset) == Some(SAVE_REGION_RECORD_NAME_TAG) + }); + let (first_primary_name, first_secondary_name, first_tertiary_name) = + first_name_tag_relative_offset + .and_then(|relative_offset| { + let name_payload = + payload_bytes.get(relative_offset.checked_add(4)?..)?; + parse_save_len_prefixed_ascii_name_triplet(name_payload) + }) + .unwrap_or_default(); + rows.push(LiveEntryPreludeRow { + live_entry_id, + payload_relative_offset, + child_count, + saved_primary_child_byte, + first_payload_dword, + first_name_tag_relative_offset, + first_primary_name: (!first_primary_name.is_empty()) + .then_some(first_primary_name), + first_secondary_name: (!first_secondary_name.is_empty()) + .then_some(first_secondary_name), + first_tertiary_name, + }); + cursor = payload_end; + } + let payload_relative_offset_monotonic = rows.windows(2).all(|window| { + window[0].payload_relative_offset < window[1].payload_relative_offset + }); + let mut child_count_counts = BTreeMap::::new(); + let mut saved_primary_child_byte_counts = BTreeMap::::new(); + let mut first_name_tag_relative_offset_counts = BTreeMap::::new(); + for row in &rows { + *child_count_counts.entry(row.child_count).or_default() += 1; + *saved_primary_child_byte_counts + .entry(row.saved_primary_child_byte) + .or_default() += 1; + if let Some(first_name_tag_relative_offset) = row.first_name_tag_relative_offset + { + *first_name_tag_relative_offset_counts + .entry(first_name_tag_relative_offset) + .or_default() += 1; + } + } + 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_child_byte = saved_primary_child_byte_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_first_name_tag_relative_offset = first_name_tag_relative_offset_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)); + Some( + SmpSavePlacedStructureDynamicSideBufferLiveEntryPreludeSummary { + live_entry_directory_row_count: rows.len(), + decoded_live_entry_id_count: live_entry_ids.len(), + payload_relative_offset_monotonic, + rows_with_payload_pointer_inside_records_span: rows.len(), + rows_with_zero_child_count: rows + .iter() + .filter(|row| row.child_count == 0) + .count(), + rows_with_nonzero_child_count: rows + .iter() + .filter(|row| row.child_count != 0) + .count(), + rows_with_first_name_tag_after_prelude: rows + .iter() + .filter(|row| row.first_name_tag_relative_offset.is_some()) + .count(), + rows_with_first_name_tag_at_offset_3: rows + .iter() + .filter(|row| row.first_name_tag_relative_offset == Some(3)) + .count(), + unique_child_count_values: child_count_counts.keys().copied().collect(), + unique_first_name_tag_relative_offsets: + first_name_tag_relative_offset_counts + .keys() + .copied() + .collect(), + dominant_child_count: dominant_child_count.map(|(value, _)| value), + dominant_child_count_count: dominant_child_count + .map(|(_, count)| count) + .unwrap_or_default(), + dominant_saved_primary_child_byte: dominant_saved_primary_child_byte + .map(|(value, _)| value), + dominant_saved_primary_child_byte_hex: dominant_saved_primary_child_byte + .map(|(value, _)| format!("0x{value:02x}")), + dominant_saved_primary_child_byte_count: dominant_saved_primary_child_byte + .map(|(_, count)| count) + .unwrap_or_default(), + dominant_first_name_tag_relative_offset: + dominant_first_name_tag_relative_offset.map(|(value, _)| value), + dominant_first_name_tag_relative_offset_count: + dominant_first_name_tag_relative_offset + .map(|(_, count)| count) + .unwrap_or_default(), + sample_rows: rows + .iter() + .take(8) + .enumerate() + .map(|(sample_index, row)| { + SmpSavePlacedStructureDynamicSideBufferLiveEntryPreludeSample { + sample_index, + live_entry_id: row.live_entry_id, + payload_relative_offset: row.payload_relative_offset as u32, + payload_relative_offset_hex: format!( + "0x{:08x}", + row.payload_relative_offset + ), + payload_relative_to_records: row.payload_relative_offset, + child_count: row.child_count, + child_count_hex: format!("0x{:04x}", row.child_count), + saved_primary_child_byte: row.saved_primary_child_byte, + saved_primary_child_byte_hex: format!( + "0x{:02x}", + row.saved_primary_child_byte + ), + first_payload_dword_hex: format!( + "0x{:08x}", + row.first_payload_dword + ), + first_name_tag_relative_offset: row + .first_name_tag_relative_offset, + first_primary_name: row.first_primary_name.clone(), + first_secondary_name: row.first_secondary_name.clone(), + first_tertiary_name: row.first_tertiary_name.clone(), + } + }) + .collect(), + }, + ) + }); let unique_embedded_name_pair_count = name_pair_summaries.len(); let dominant_compact_prefix_pattern = compact_prefix_pattern_summaries.first().cloned(); let decoded_embedded_name_row_count = embedded_name_rows @@ -12749,6 +13047,14 @@ fn parse_save_placed_structure_dynamic_side_buffer_probe( owner_shared_dword_relative_offset, owner_shared_dword_matches_first_compact_prefix_leading_dword: owner_shared_dword == prefix_leading_dword, + first_record_child_count_after_owner_shared, + first_record_child_count_after_owner_shared_hex: first_record_child_count_after_owner_shared + .map(|value| format!("0x{value:04x}")), + first_record_saved_primary_child_byte_after_owner_shared, + first_record_saved_primary_child_byte_after_owner_shared_hex: + first_record_saved_primary_child_byte_after_owner_shared + .map(|value| format!("0x{value:02x}")), + first_record_first_name_tag_relative_offset_after_owner_shared, prefix_leading_dword, prefix_leading_dword_hex: format!("0x{prefix_leading_dword:08x}"), prefix_trailing_word, @@ -12769,11 +13075,21 @@ fn parse_save_placed_structure_dynamic_side_buffer_probe( compact_prefix_pattern_summaries, name_pair_summaries, payload_envelope_summary, + live_entry_prelude_summary: live_entry_prelude_summary.clone(), evidence: vec![ "exact little-endian u32 tag family 0x38a5/0x38a6/0x38a7 appears as a separate save-side tagged collection on grounded saves".to_string(), format!( "direct disassembly now shows 0x00493be0 consuming shared owner-local dword 0x{owner_shared_dword:08x} from the 0x38a6 stream before iterating live infrastructure records" ), + format!( + "grounded 0x38a6 record stream then starts the first infrastructure payload with child_count={}, saved_primary_child_byte={}, and first 0x55f1 at relative offset {:?} after that shared dword", + first_record_child_count_after_owner_shared.unwrap_or_default(), + first_record_saved_primary_child_byte_after_owner_shared + .map(|value| format!("0x{value:02x}")) + .as_deref() + .unwrap_or("0x00"), + first_record_first_name_tag_relative_offset_after_owner_shared + ), "records payload begins with a compact 6-byte prefix plus one separator byte before the first embedded 0x55f1 name row".to_string(), "first embedded 0x55f1 row decodes with placed-structure-style dual names, which makes this the strongest current candidate for the separate placed-structure dynamic side-buffer owner seam".to_string(), format!( @@ -12856,6 +13172,29 @@ fn parse_save_placed_structure_dynamic_side_buffer_probe( .unwrap_or_else(|| { "no fixed 0x55f2 policy summary was available".to_string() }), + live_entry_prelude_summary + .as_ref() + .map(|summary| { + format!( + "decoded {} live-entry directory rows with payload pointers inside the records span; dominant child count={} x{}, dominant saved primary-child byte={} x{}, dominant first 0x55f1 offset={} x{}, and {} rows start the first child callback immediately at payload +0x3", + summary.rows_with_payload_pointer_inside_records_span, + summary.dominant_child_count.unwrap_or_default(), + summary.dominant_child_count_count, + summary + .dominant_saved_primary_child_byte_hex + .as_deref() + .unwrap_or("0x00"), + summary.dominant_saved_primary_child_byte_count, + summary + .dominant_first_name_tag_relative_offset + .unwrap_or_default(), + summary.dominant_first_name_tag_relative_offset_count, + summary.rows_with_first_name_tag_at_offset_3 + ) + }) + .unwrap_or_else(|| { + "no live-entry prelude summary was available".to_string() + }), dominant_compact_prefix_pattern .map(|pattern| { format!( @@ -20970,6 +21309,17 @@ mod tests { assert_eq!(probe.owner_shared_dword_hex, "0x0005d368"); assert_eq!(probe.owner_shared_dword_relative_offset, 0); assert!(probe.owner_shared_dword_matches_first_compact_prefix_leading_dword); + assert_eq!(probe.first_record_child_count_after_owner_shared, Some(1)); + assert_eq!( + probe + .first_record_saved_primary_child_byte_after_owner_shared_hex + .as_deref(), + Some("0xff") + ); + assert_eq!( + probe.first_record_first_name_tag_relative_offset_after_owner_shared, + Some(3) + ); assert_eq!(probe.prefix_leading_dword_hex, "0x0005d368"); assert_eq!(probe.prefix_trailing_word_hex, "0x0001"); assert_eq!(probe.prefix_separator_byte_hex, "0xff"); @@ -21196,6 +21546,11 @@ mod tests { owner_shared_dword_hex: "0x00000000".to_string(), owner_shared_dword_relative_offset: 0, owner_shared_dword_matches_first_compact_prefix_leading_dword: true, + first_record_child_count_after_owner_shared: None, + first_record_child_count_after_owner_shared_hex: None, + first_record_saved_primary_child_byte_after_owner_shared: None, + first_record_saved_primary_child_byte_after_owner_shared_hex: None, + first_record_first_name_tag_relative_offset_after_owner_shared: None, prefix_leading_dword: 0, prefix_leading_dword_hex: "0x00000000".to_string(), prefix_trailing_word: 1, @@ -21245,6 +21600,7 @@ mod tests { }, ], payload_envelope_summary: None, + live_entry_prelude_summary: None, evidence: vec![], }; let triplets = SmpSavePlacedStructureRecordTripletProbe { @@ -22851,6 +23207,13 @@ mod tests { owner_shared_dword_hex: "0xff000000".to_string(), owner_shared_dword_relative_offset: 0, owner_shared_dword_matches_first_compact_prefix_leading_dword: true, + first_record_child_count_after_owner_shared: Some(1), + first_record_child_count_after_owner_shared_hex: Some("0x0001".to_string()), + first_record_saved_primary_child_byte_after_owner_shared: Some(0xff), + first_record_saved_primary_child_byte_after_owner_shared_hex: Some( + "0xff".to_string(), + ), + first_record_first_name_tag_relative_offset_after_owner_shared: Some(3), prefix_leading_dword: 0xff000000, prefix_leading_dword_hex: "0xff000000".to_string(), prefix_trailing_word: 1, @@ -22930,6 +23293,28 @@ mod tests { sample_rows: Vec::new(), }, ), + live_entry_prelude_summary: Some( + SmpSavePlacedStructureDynamicSideBufferLiveEntryPreludeSummary { + live_entry_directory_row_count: 3865, + decoded_live_entry_id_count: 3865, + payload_relative_offset_monotonic: true, + rows_with_payload_pointer_inside_records_span: 138, + rows_with_zero_child_count: 0, + rows_with_nonzero_child_count: 138, + rows_with_first_name_tag_after_prelude: 138, + rows_with_first_name_tag_at_offset_3: 138, + unique_child_count_values: vec![1], + unique_first_name_tag_relative_offsets: vec![3], + dominant_child_count: Some(1), + dominant_child_count_count: 138, + dominant_saved_primary_child_byte: Some(0), + dominant_saved_primary_child_byte_hex: Some("0x00".to_string()), + dominant_saved_primary_child_byte_count: 138, + dominant_first_name_tag_relative_offset: Some(3), + dominant_first_name_tag_relative_offset_count: 138, + sample_rows: Vec::new(), + }, + ), evidence: Vec::new(), }); analysis.placed_structure_dynamic_side_buffer_alignment = @@ -22949,7 +23334,7 @@ mod tests { let trace = build_infrastructure_asset_trace_report(&analysis); assert!(trace.side_buffer_present); assert_eq!(trace.triplet_alignment_overlap_count, 0); - assert_eq!(trace.known_owner_bridge_fields.len(), 6); + assert_eq!(trace.known_owner_bridge_fields.len(), 7); assert_eq!(trace.known_bridge_helpers.len(), 13); assert_eq!(trace.next_owner_questions.len(), 3); assert_eq!(trace.candidate_consumer_hypotheses.len(), 3); @@ -23009,6 +23394,13 @@ mod tests { && line.contains("[this+0x4b/+0x4f/+0x53]") }) ); + assert!( + trace.candidate_consumer_hypotheses[0] + .evidence + .iter() + .any(|line| line.contains("u16 child count") + && line.contains("saved primary-child byte")) + ); assert_eq!(trace.branches[0].status, "grounded_separate_owner_seam"); assert_eq!(trace.branches[1].status, "disproved_by_grounded_probe"); } 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 328d500..c72442a 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 @@ -2966,6 +2966,15 @@ The low helper strip beneath that shared family is tighter now too: `0x0052ecd0` infrastructure question is no longer whether the fixed `0x55f2` row hides the child count or saved primary-child ordinal at all. Those values now have to live outside the fixed row, most likely in the surrounding payload-stream header or compact-prefix regime above `0x0048dcf0`. + The outer prelude is explicit now too: direct disassembly of `0x0048dcf0` shows it reading one + `u16` child count through `0x00531150`, zeroing `[this+0x08]`, and conditionally reading one + saved primary-child byte before the per-child callback loop begins. Grounded `q.gms` bytes now + also show the first `0x38a6` record starting immediately after the shared owner-local dword with + `child_count = 1`, `saved_primary_child_byte = 0xff`, and the first child `0x55f1` opening at + offset `+0x3`. So the remaining infrastructure question is no longer “what kind of value should + 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 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 86570bd..37257ac 100644 --- a/docs/rehost-queue.md +++ b/docs/rehost-queue.md @@ -116,6 +116,15 @@ Working rule: primary-child ordinal at all; those outer-header values now have to live outside the fixed row, most likely in the surrounding payload-stream header or compact-prefix regime above `0x0048dcf0`. +- The outer prelude itself is tighter now too: direct disassembly of `0x0048dcf0` shows it reading + one `u16` child count through `0x00531150`, zeroing `[this+0x08]`, and conditionally reading one + saved primary-child byte before the per-child callback loop runs. Grounded `q.gms` bytes now also + show the first `0x38a6` record starting immediately after the shared owner-local dword with + `child_count = 1`, `saved_primary_child_byte = 0xff`, and the first child `0x55f1` opening at + offset `+0x3`. So the next infrastructure question is no longer “what kind of values are we + 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. - 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