From 564b8b66415c3c1f4d0aa76d9bf8fa7e38169a23 Mon Sep 17 00:00:00 2001 From: Jan Petykiewicz Date: Sat, 18 Apr 2026 12:09:08 -0700 Subject: [PATCH] Compare placed-structure side-buffer name corpus --- crates/rrt-runtime/src/lib.rs | 2 + crates/rrt-runtime/src/smp.rs | 400 +++++++++++++++++++++++++++++++++- docs/rehost-queue.md | 11 +- 3 files changed, 410 insertions(+), 3 deletions(-) diff --git a/crates/rrt-runtime/src/lib.rs b/crates/rrt-runtime/src/lib.rs index 12c66a4..2d4b053 100644 --- a/crates/rrt-runtime/src/lib.rs +++ b/crates/rrt-runtime/src/lib.rs @@ -119,6 +119,8 @@ pub use smp::{ SmpSaveAnchorRunBlock, SmpSaveBootstrapBlock, SmpSaveChairmanRecordAnalysisEntry, SmpSaveCompanyChairmanAnalysisReport, SmpSaveCompanyRecordAnalysisEntry, SmpSaveDwordCandidate, SmpSaveLoadCandidateTableSummary, SmpSaveLoadSummary, + SmpSavePlacedStructureDynamicSideBufferAlignmentProbe, + SmpSavePlacedStructureDynamicSideBufferNamePairSummary, SmpSavePlacedStructureDynamicSideBufferPrefixPatternSummary, SmpSavePlacedStructureDynamicSideBufferProbe, SmpSaveScalarCandidate, SmpSaveTaggedCollectionHeaderProbe, SmpSaveWorldEconomicTuningProbe, diff --git a/crates/rrt-runtime/src/smp.rs b/crates/rrt-runtime/src/smp.rs index 84f0bcb..cee9402 100644 --- a/crates/rrt-runtime/src/smp.rs +++ b/crates/rrt-runtime/src/smp.rs @@ -1796,8 +1796,10 @@ pub struct SmpSavePlacedStructureDynamicSideBufferProbe { pub prefix_separator_byte_hex: String, pub first_embedded_name_tag_relative_offset: usize, pub embedded_name_tag_count: usize, + pub decoded_embedded_name_row_count: usize, pub unique_compact_prefix_pattern_count: usize, pub prefix_leading_dword_matching_embedded_profile_tag_count: usize, + pub unique_embedded_name_pair_count: usize, #[serde(default)] pub first_embedded_primary_name: Option, #[serde(default)] @@ -1807,6 +1809,8 @@ pub struct SmpSavePlacedStructureDynamicSideBufferProbe { #[serde(default)] pub compact_prefix_pattern_summaries: Vec, + #[serde(default)] + pub name_pair_summaries: Vec, pub evidence: Vec, } @@ -1846,6 +1850,39 @@ pub struct SmpSavePlacedStructureDynamicSideBufferPrefixPatternSummary { pub first_secondary_name: Option, } +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct SmpSavePlacedStructureDynamicSideBufferNamePairSummary { + pub primary_name: String, + pub secondary_name: String, + pub count: usize, + pub first_name_tag_relative_offset: usize, + pub unique_compact_prefix_pattern_count: usize, + pub dominant_prefix_leading_dword: u32, + pub dominant_prefix_leading_dword_hex: String, + pub dominant_prefix_trailing_word: u16, + pub dominant_prefix_trailing_word_hex: String, + pub dominant_prefix_separator_byte: u8, + pub dominant_prefix_separator_byte_hex: String, + pub dominant_prefix_count: usize, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct SmpSavePlacedStructureDynamicSideBufferAlignmentProbe { + pub unique_side_buffer_name_pair_count: usize, + pub unique_triplet_name_pair_count: usize, + pub overlapping_name_pair_count: usize, + pub side_buffer_row_count: usize, + pub side_buffer_rows_with_matching_triplet_name_pair_count: usize, + pub side_buffer_rows_without_matching_triplet_name_pair_count: usize, + pub triplet_name_pairs_without_side_buffer_match_count: usize, + #[serde(default)] + pub matched_name_pair_samples: Vec, + #[serde(default)] + pub unmatched_side_buffer_name_pair_samples: + Vec, + pub evidence: Vec, +} + #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct SmpRt3105SaveNameTableProbe { pub profile_family: String, @@ -2794,6 +2831,9 @@ pub struct SmpSaveCompanyChairmanAnalysisReport { #[serde(default)] pub placed_structure_dynamic_side_buffer: Option, #[serde(default)] + pub placed_structure_dynamic_side_buffer_alignment: + Option, + #[serde(default)] pub unclassified_tagged_collection_headers: Vec, #[serde(default)] pub company_entries: Vec, @@ -3616,6 +3656,12 @@ pub fn inspect_save_company_and_chairman_analysis_bytes( report.container_profile.as_ref(), ) }); + let placed_structure_dynamic_side_buffer_alignment = placed_structure_dynamic_side_buffer + .as_ref() + .zip(placed_structure_record_triplets.as_ref()) + .map(|(side_buffer, triplets)| { + summarize_placed_structure_dynamic_side_buffer_alignment(side_buffer, triplets) + }); let unclassified_tagged_collection_headers = report .save_unclassified_tagged_collection_header_probes .clone(); @@ -3979,8 +4025,10 @@ pub fn inspect_save_company_and_chairman_analysis_bytes( if let Some(side_buffer) = placed_structure_dynamic_side_buffer.as_ref() { let dominant_pattern = side_buffer.compact_prefix_pattern_summaries.first(); notes.push(format!( - "Placed-structure analysis now also exports the separate 0x38a5 dynamic side-buffer owner seam with {} embedded name rows, {} unique compact prefix patterns, {} rows whose leading dword matches 0x55f3, and dominant compact pattern={}/{}/{} x{}.", + "Placed-structure analysis now also exports the separate 0x38a5 dynamic side-buffer owner seam with {} embedded name rows, {} decoded rows across {} unique name pairs, {} unique compact prefix patterns, {} rows whose leading dword matches 0x55f3, and dominant compact pattern={}/{}/{} x{}.", side_buffer.embedded_name_tag_count, + side_buffer.decoded_embedded_name_row_count, + side_buffer.unique_embedded_name_pair_count, side_buffer.unique_compact_prefix_pattern_count, side_buffer.prefix_leading_dword_matching_embedded_profile_tag_count, dominant_pattern @@ -3995,6 +4043,16 @@ pub fn inspect_save_company_and_chairman_analysis_bytes( dominant_pattern.map(|pattern| pattern.count).unwrap_or_default() )); } + if let Some(alignment) = placed_structure_dynamic_side_buffer_alignment.as_ref() { + notes.push(format!( + "Placed-structure analysis now also compares the 0x38a5 side-buffer against the grounded 0x36b1 triplet corpus: {} of {} decoded side-buffer rows reuse {} overlapping placed-structure name pairs, leaving {} unmatched side-buffer rows and {} triplet-only name pairs.", + alignment.side_buffer_rows_with_matching_triplet_name_pair_count, + alignment.side_buffer_row_count, + alignment.overlapping_name_pair_count, + alignment.side_buffer_rows_without_matching_triplet_name_pair_count, + alignment.triplet_name_pairs_without_side_buffer_match_count + )); + } if let Some(candidate) = unclassified_tagged_collection_headers.first() { notes.push(format!( "Generic save-side tagged collection scan also found {} unclassified candidate families; largest current candidate uses tags {}/{}/{} with live_record_count={} stride=0x{:x} records_span_len=0x{:x}.", @@ -4057,6 +4115,7 @@ pub fn inspect_save_company_and_chairman_analysis_bytes( .clone(), placed_structure_record_triplets, placed_structure_dynamic_side_buffer, + placed_structure_dynamic_side_buffer_alignment, unclassified_tagged_collection_headers, company_entries, chairman_entries, @@ -10689,6 +10748,13 @@ fn parse_save_placed_structure_dynamic_side_buffer_probe( other_primary_name_count: usize, } + #[derive(Default)] + struct NamePairAccumulator { + count: usize, + first_name_tag_relative_offset: usize, + prefix_counts: BTreeMap<(u32, u16, u8), usize>, + } + if file_extension_hint != Some("gms") { return None; } @@ -10858,6 +10924,7 @@ fn parse_save_placed_structure_dynamic_side_buffer_probe( .collect::>(); let mut compact_prefix_pattern_map = BTreeMap::<(u32, u16, u8), PrefixPatternAccumulator>::new(); + let mut name_pair_map = BTreeMap::<(String, String), NamePairAccumulator>::new(); for row in &embedded_name_rows { let entry = compact_prefix_pattern_map .entry(( @@ -10883,6 +10950,25 @@ fn parse_save_placed_structure_dynamic_side_buffer_probe( entry.other_primary_name_count += 1; } } + if let (Some(primary_name), Some(secondary_name)) = + (row.primary_name.as_ref(), row.secondary_name.as_ref()) + { + let entry = name_pair_map + .entry((primary_name.clone(), secondary_name.clone())) + .or_insert_with(|| NamePairAccumulator { + first_name_tag_relative_offset: row.name_tag_relative_offset, + ..Default::default() + }); + entry.count += 1; + *entry + .prefix_counts + .entry(( + row.prefix_leading_dword, + row.prefix_trailing_word, + row.prefix_separator_byte, + )) + .or_default() += 1; + } } let prefix_leading_dword_matching_embedded_profile_tag_count = embedded_name_rows .iter() @@ -10928,7 +11014,61 @@ fn parse_save_placed_structure_dynamic_side_buffer_probe( .then_with(|| left.prefix_trailing_word.cmp(&right.prefix_trailing_word)) .then_with(|| left.prefix_separator_byte.cmp(&right.prefix_separator_byte)) }); + let mut name_pair_summaries = name_pair_map + .into_iter() + .filter_map(|((primary_name, secondary_name), accumulator)| { + let dominant_prefix = accumulator.prefix_counts.iter().max_by( + |(left_key, left_count), (right_key, right_count)| { + left_count + .cmp(right_count) + .then_with(|| right_key.cmp(left_key)) + }, + )?; + let ( + dominant_prefix_leading_dword, + dominant_prefix_trailing_word, + dominant_prefix_separator_byte, + ) = *dominant_prefix.0; + let dominant_prefix_count = *dominant_prefix.1; + Some(SmpSavePlacedStructureDynamicSideBufferNamePairSummary { + primary_name, + secondary_name, + count: accumulator.count, + first_name_tag_relative_offset: accumulator.first_name_tag_relative_offset, + unique_compact_prefix_pattern_count: accumulator.prefix_counts.len(), + dominant_prefix_leading_dword, + dominant_prefix_leading_dword_hex: format!( + "0x{dominant_prefix_leading_dword:08x}" + ), + dominant_prefix_trailing_word, + dominant_prefix_trailing_word_hex: format!( + "0x{dominant_prefix_trailing_word:04x}" + ), + dominant_prefix_separator_byte, + dominant_prefix_separator_byte_hex: format!( + "0x{dominant_prefix_separator_byte:02x}" + ), + dominant_prefix_count, + }) + }) + .collect::>(); + name_pair_summaries.sort_by(|left, right| { + right + .count + .cmp(&left.count) + .then_with(|| { + left.first_name_tag_relative_offset + .cmp(&right.first_name_tag_relative_offset) + }) + .then_with(|| left.primary_name.cmp(&right.primary_name)) + .then_with(|| left.secondary_name.cmp(&right.secondary_name)) + }); + 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 + .iter() + .filter(|row| row.primary_name.is_some() && row.secondary_name.is_some()) + .count(); return Some(SmpSavePlacedStructureDynamicSideBufferProbe { profile_family: profile.profile_family.clone(), source_kind: "save-placed-structure-dynamic-side-buffer-records".to_string(), @@ -10951,12 +11091,15 @@ fn parse_save_placed_structure_dynamic_side_buffer_probe( prefix_separator_byte_hex: format!("0x{prefix_separator_byte:02x}"), first_embedded_name_tag_relative_offset, embedded_name_tag_count: embedded_name_tag_offsets.len(), + decoded_embedded_name_row_count, unique_compact_prefix_pattern_count: compact_prefix_pattern_summaries.len(), prefix_leading_dword_matching_embedded_profile_tag_count, + unique_embedded_name_pair_count, first_embedded_primary_name: Some(first_embedded_primary_name.clone()), first_embedded_secondary_name: Some(first_embedded_secondary_name.clone()), embedded_name_row_samples, compact_prefix_pattern_summaries, + name_pair_summaries, evidence: vec![ "exact little-endian u32 tag family 0x38a5/0x38a6/0x38a7 appears as a separate save-side tagged collection on grounded saves".to_string(), "records payload begins with a compact 6-byte prefix plus one separator byte before the first embedded 0x55f1 name row".to_string(), @@ -10973,6 +11116,10 @@ fn parse_save_placed_structure_dynamic_side_buffer_probe( embedded_name_rows.len(), u32::from(SAVE_REGION_RECORD_PROFILE_TAG) ), + format!( + "{decoded_embedded_name_row_count} decoded embedded name rows collapse into {} unique placed-structure name pairs", + unique_embedded_name_pair_count + ), dominant_compact_prefix_pattern .map(|pattern| { format!( @@ -10996,6 +11143,83 @@ fn parse_save_placed_structure_dynamic_side_buffer_probe( None } +fn summarize_placed_structure_dynamic_side_buffer_alignment( + side_buffer: &SmpSavePlacedStructureDynamicSideBufferProbe, + triplets: &SmpSavePlacedStructureRecordTripletProbe, +) -> SmpSavePlacedStructureDynamicSideBufferAlignmentProbe { + let triplet_name_pairs = triplets + .entries + .iter() + .map(|entry| (entry.primary_name.clone(), entry.secondary_name.clone())) + .collect::>(); + let matched_name_pair_samples = side_buffer + .name_pair_summaries + .iter() + .filter(|summary| { + triplet_name_pairs + .contains(&(summary.primary_name.clone(), summary.secondary_name.clone())) + }) + .take(5) + .cloned() + .collect::>(); + let unmatched_side_buffer_name_pair_samples = side_buffer + .name_pair_summaries + .iter() + .filter(|summary| { + !triplet_name_pairs + .contains(&(summary.primary_name.clone(), summary.secondary_name.clone())) + }) + .take(5) + .cloned() + .collect::>(); + let side_buffer_rows_with_matching_triplet_name_pair_count = side_buffer + .name_pair_summaries + .iter() + .filter(|summary| { + triplet_name_pairs + .contains(&(summary.primary_name.clone(), summary.secondary_name.clone())) + }) + .map(|summary| summary.count) + .sum::(); + let unique_side_buffer_name_pair_count = side_buffer.name_pair_summaries.len(); + let overlapping_name_pair_count = side_buffer + .name_pair_summaries + .iter() + .filter(|summary| { + triplet_name_pairs + .contains(&(summary.primary_name.clone(), summary.secondary_name.clone())) + }) + .count(); + SmpSavePlacedStructureDynamicSideBufferAlignmentProbe { + unique_side_buffer_name_pair_count, + unique_triplet_name_pair_count: triplet_name_pairs.len(), + overlapping_name_pair_count, + side_buffer_row_count: side_buffer.decoded_embedded_name_row_count, + side_buffer_rows_with_matching_triplet_name_pair_count, + side_buffer_rows_without_matching_triplet_name_pair_count: side_buffer + .decoded_embedded_name_row_count + .saturating_sub(side_buffer_rows_with_matching_triplet_name_pair_count), + triplet_name_pairs_without_side_buffer_match_count: triplet_name_pairs + .len() + .saturating_sub(overlapping_name_pair_count), + matched_name_pair_samples, + unmatched_side_buffer_name_pair_samples, + evidence: vec![ + "placed-structure dynamic side-buffer alignment compares decoded 0x38a5 embedded name pairs against the grounded 0x36b1 triplet name-pair corpus".to_string(), + format!( + "{} of {} decoded side-buffer rows currently reuse name pairs already present in the placed-structure triplet owner seam", + side_buffer_rows_with_matching_triplet_name_pair_count, + side_buffer.decoded_embedded_name_row_count + ), + format!( + "{} of {} unique side-buffer name pairs overlap the grounded triplet name-pair corpus", + overlapping_name_pair_count, + unique_side_buffer_name_pair_count + ), + ], + } +} + #[derive(Clone, Copy)] struct IndexedCollectionHeaderSummary { metadata_tag_offset: usize, @@ -18923,11 +19147,13 @@ mod tests { assert_eq!(probe.prefix_separator_byte_hex, "0xff"); assert_eq!(probe.first_embedded_name_tag_relative_offset, 7); assert_eq!(probe.embedded_name_tag_count, 1); + assert_eq!(probe.decoded_embedded_name_row_count, 1); assert_eq!(probe.unique_compact_prefix_pattern_count, 1); assert_eq!( probe.prefix_leading_dword_matching_embedded_profile_tag_count, 0 ); + assert_eq!(probe.unique_embedded_name_pair_count, 1); assert_eq!( probe.first_embedded_primary_name.as_deref(), Some("TrackCapST_Cap.3dp") @@ -18950,6 +19176,12 @@ mod tests { probe.compact_prefix_pattern_summaries[0].section_like_primary_name_count, 0 ); + assert_eq!(probe.name_pair_summaries.len(), 1); + assert_eq!(probe.name_pair_summaries[0].count, 1); + assert_eq!( + probe.name_pair_summaries[0].dominant_prefix_leading_dword_hex, + "0x0005d368" + ); } #[test] @@ -19005,11 +19237,13 @@ mod tests { .expect("placed-structure dynamic side-buffer probe should parse"); assert_eq!(probe.embedded_name_tag_count, 3); + assert_eq!(probe.decoded_embedded_name_row_count, 3); assert_eq!(probe.unique_compact_prefix_pattern_count, 2); assert_eq!( probe.prefix_leading_dword_matching_embedded_profile_tag_count, 2 ); + assert_eq!(probe.unique_embedded_name_pair_count, 2); assert_eq!(probe.compact_prefix_pattern_summaries.len(), 2); assert_eq!( probe.compact_prefix_pattern_summaries[0].prefix_leading_dword_hex, @@ -19033,6 +19267,170 @@ mod tests { "0xff0000ff" ); assert_eq!(probe.compact_prefix_pattern_summaries[1].count, 1); + assert_eq!(probe.name_pair_summaries.len(), 2); + assert_eq!(probe.name_pair_summaries[0].count, 2); + assert_eq!( + probe.name_pair_summaries[0].dominant_prefix_leading_dword_hex, + "0x000055f3" + ); + assert_eq!(probe.name_pair_summaries[1].count, 1); + } + + #[test] + fn aligns_placed_structure_dynamic_side_buffer_name_pairs_with_triplets() { + let side_buffer = SmpSavePlacedStructureDynamicSideBufferProbe { + profile_family: "rt3-105-save-container-v1".to_string(), + source_kind: "save-placed-structure-dynamic-side-buffer-records".to_string(), + semantic_family: "scenario-save-placed-structure-dynamic-side-buffer-records" + .to_string(), + metadata_tag_offset: 0, + records_tag_offset: 0, + close_tag_offset: 0, + records_span_len: 0, + direct_record_stride: 6, + direct_record_stride_hex: "0x00000006".to_string(), + live_id_bound: 1000, + live_id_bound_hex: "0x000003e8".to_string(), + live_record_count: 10, + live_record_count_hex: "0x0000000a".to_string(), + prefix_leading_dword: 0, + prefix_leading_dword_hex: "0x00000000".to_string(), + prefix_trailing_word: 1, + prefix_trailing_word_hex: "0x0001".to_string(), + prefix_separator_byte: 0xff, + prefix_separator_byte_hex: "0xff".to_string(), + first_embedded_name_tag_relative_offset: 7, + embedded_name_tag_count: 3, + decoded_embedded_name_row_count: 3, + unique_compact_prefix_pattern_count: 2, + prefix_leading_dword_matching_embedded_profile_tag_count: 2, + unique_embedded_name_pair_count: 2, + first_embedded_primary_name: Some("TunnelSTBrick_Section.3dp".to_string()), + first_embedded_secondary_name: Some("Infrastructure".to_string()), + embedded_name_row_samples: vec![], + compact_prefix_pattern_summaries: vec![], + name_pair_summaries: vec![ + SmpSavePlacedStructureDynamicSideBufferNamePairSummary { + primary_name: "TunnelSTBrick_Section.3dp".to_string(), + secondary_name: "Infrastructure".to_string(), + count: 2, + first_name_tag_relative_offset: 7, + unique_compact_prefix_pattern_count: 1, + dominant_prefix_leading_dword: 0x55f3, + dominant_prefix_leading_dword_hex: "0x000055f3".to_string(), + dominant_prefix_trailing_word: 1, + dominant_prefix_trailing_word_hex: "0x0001".to_string(), + dominant_prefix_separator_byte: 0xff, + dominant_prefix_separator_byte_hex: "0xff".to_string(), + dominant_prefix_count: 2, + }, + SmpSavePlacedStructureDynamicSideBufferNamePairSummary { + primary_name: "BridgeSTWood_Section.3dp".to_string(), + secondary_name: "Infrastructure".to_string(), + count: 1, + first_name_tag_relative_offset: 27, + unique_compact_prefix_pattern_count: 1, + dominant_prefix_leading_dword: 0xff000000, + dominant_prefix_leading_dword_hex: "0xff000000".to_string(), + dominant_prefix_trailing_word: 1, + dominant_prefix_trailing_word_hex: "0x0001".to_string(), + dominant_prefix_separator_byte: 0xff, + dominant_prefix_separator_byte_hex: "0xff".to_string(), + dominant_prefix_count: 1, + }, + ], + evidence: vec![], + }; + let triplets = SmpSavePlacedStructureRecordTripletProbe { + profile_family: "rt3-105-save-container-v1".to_string(), + source_kind: "save-placed-structure-record-triplets".to_string(), + semantic_family: "scenario-save-placed-structure-record-triplets".to_string(), + records_tag_offset: 0, + close_tag_offset: 0, + record_count: 2, + entries: vec![ + SmpSavePlacedStructureRecordTripletEntryProbe { + record_index: 0, + primary_name: "TunnelSTBrick_Section.3dp".to_string(), + secondary_name: "Infrastructure".to_string(), + name_tag_relative_offset: 0, + policy_tag_relative_offset: 0, + profile_tag_relative_offset: 0, + policy_chunk_len: 0, + profile_chunk_len: 0, + policy_f32_lane_0: 0.0, + policy_f32_lane_1: 0.0, + policy_f32_lane_2: 0.0, + policy_f32_lane_3: 0.0, + policy_f32_lane_4: 0.0, + policy_reserved_dword: 0, + policy_trailing_word: 0, + policy_trailing_word_hex: "0x0000".to_string(), + profile_open_marker: 0, + profile_open_marker_hex: "0x00000000".to_string(), + profile_repeated_primary_name: "TunnelSTBrick_Section.3dp".to_string(), + profile_repeated_secondary_name: "Infrastructure".to_string(), + profile_payload_dword: 0, + profile_payload_dword_hex: "0x00000000".to_string(), + profile_sentinel_i32: -1, + profile_status_kind: "unset".to_string(), + farm_growth_stage_index: None, + profile_close_marker: 0, + profile_close_marker_hex: "0x00000000".to_string(), + }, + SmpSavePlacedStructureRecordTripletEntryProbe { + record_index: 1, + primary_name: "TrackCapST_Cap.3dp".to_string(), + secondary_name: "Infrastructure".to_string(), + name_tag_relative_offset: 0, + policy_tag_relative_offset: 0, + profile_tag_relative_offset: 0, + policy_chunk_len: 0, + profile_chunk_len: 0, + policy_f32_lane_0: 0.0, + policy_f32_lane_1: 0.0, + policy_f32_lane_2: 0.0, + policy_f32_lane_3: 0.0, + policy_f32_lane_4: 0.0, + policy_reserved_dword: 0, + policy_trailing_word: 0, + policy_trailing_word_hex: "0x0000".to_string(), + profile_open_marker: 0, + profile_open_marker_hex: "0x00000000".to_string(), + profile_repeated_primary_name: "TrackCapST_Cap.3dp".to_string(), + profile_repeated_secondary_name: "Infrastructure".to_string(), + profile_payload_dword: 0, + profile_payload_dword_hex: "0x00000000".to_string(), + profile_sentinel_i32: -1, + profile_status_kind: "unset".to_string(), + farm_growth_stage_index: None, + profile_close_marker: 0, + profile_close_marker_hex: "0x00000000".to_string(), + }, + ], + evidence: vec![], + }; + + let alignment = + summarize_placed_structure_dynamic_side_buffer_alignment(&side_buffer, &triplets); + + assert_eq!(alignment.unique_side_buffer_name_pair_count, 2); + assert_eq!(alignment.unique_triplet_name_pair_count, 2); + assert_eq!(alignment.overlapping_name_pair_count, 1); + assert_eq!( + alignment.side_buffer_rows_with_matching_triplet_name_pair_count, + 2 + ); + assert_eq!( + alignment.side_buffer_rows_without_matching_triplet_name_pair_count, + 1 + ); + assert_eq!( + alignment.triplet_name_pairs_without_side_buffer_match_count, + 1 + ); + assert_eq!(alignment.matched_name_pair_samples.len(), 1); + assert_eq!(alignment.unmatched_side_buffer_name_pair_samples.len(), 1); } #[test] diff --git a/docs/rehost-queue.md b/docs/rehost-queue.md index f487106..fc01d37 100644 --- a/docs/rehost-queue.md +++ b/docs/rehost-queue.md @@ -26,8 +26,9 @@ Working rule: name rows now make it the grounded placed-structure dynamic side-buffer owner; the remaining blocker is semantic closure of the compact prefix regimes now summarized in real saves as seven stable patterns on `q.gms` and their relation to the embedded `0x55f1/0x55f2/0x55f3` row - subset, especially the dominant bridge-section `0xff000000/0x0001/0xff` group and the smaller - `0x000055f3/0x0001/0xff` group that matches the embedded profile tag directly. + subset, especially now that the side-buffer name-pair corpus is proven disjoint from the + grounded `0x36b1` triplet name-pair corpus on `q.gms`; the next pass should treat `0x38a5` as + a separate infrastructure-asset owner seam, not a compact alias over the triplet records. - Extend shellless clock advancement so more periodic-company service branches consume owned runtime time state directly instead of only the explicit periodic service command. - Keep widening selected-year world-owner state only when a full owning reader/rebuild family is @@ -110,6 +111,12 @@ Working rule: rows, the `0xff0000ff/0x0001/0xff` and `0xf3010100/0x0055/0x00` groups concentrating cap-like rows, and a smaller `0x000055f3/0x0001/0xff` group carrying 17 tunnel-section / cap rows whose leading dword matches the embedded placed-structure profile tag directly. +- The save-company/chairman analysis path now also compares that grounded `0x38a5` side-buffer + name-pair corpus against the grounded `0x36b1` triplet name-pair corpus directly; on `q.gms` + the overlap is currently zero (`0/138` decoded side-buffer rows and `0/5` unique side-buffer + name pairs match the 56-triplet corpus), which shifts the remaining placed-structure work away + from “prove these are aliases” toward “find how the separate infrastructure-asset owner seam is + consumed by city-connection / linked-transit service.” - The placed-structure tagged save stream now also exposes repeated `0x55f1/0x55f2/0x55f3` triplets with dual name stems, a fixed five-`f32` policy row, and a compact `0x5dc1...0x5dc2` footer carrying one raw `u32` payload lane plus one live `i32` status lane, so the remaining