From ee8311b3f2742dfa089377f81ff375afe1f9f957 Mon Sep 17 00:00:00 2001 From: Jan Petykiewicz Date: Sun, 19 Apr 2026 15:19:09 -0700 Subject: [PATCH] Bridge peer-site names to stock building family --- crates/rrt-runtime/src/smp.rs | 145 ++++++++++++++++++ ...ntime-roots-camera-and-support-families.md | 7 + docs/rehost-queue.md | 5 + 3 files changed, 157 insertions(+) diff --git a/crates/rrt-runtime/src/smp.rs b/crates/rrt-runtime/src/smp.rs index 469803f..7d3d255 100644 --- a/crates/rrt-runtime/src/smp.rs +++ b/crates/rrt-runtime/src/smp.rs @@ -3770,6 +3770,16 @@ pub struct SmpSavePlacedStructureNonzeroCompanionNamePairSummaryEntry { pub count: usize, } +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct SmpSavePlacedStructureNonzeroCompanionBuildingFamilyOverlapSummaryEntry { + pub companion_byte_hex: String, + pub primary_name: String, + pub secondary_name: String, + pub count: usize, + pub primary_matches_nonzero_stock_building_header_family: bool, + pub secondary_matches_nonzero_stock_building_header_family: bool, +} + #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct SmpSavePlacedStructurePolicyTrailingWordSummaryEntry { pub policy_trailing_word_hex: String, @@ -3818,6 +3828,9 @@ pub struct SmpPeriodicCompanyServiceTraceReport { pub peer_site_selector_candidate_saved_nonzero_companion_name_pair_summaries: Vec, #[serde(default)] + pub peer_site_selector_candidate_saved_nonzero_companion_building_family_overlap_summaries: + Vec, + #[serde(default)] pub peer_site_persisted_selector_bundle_fields: Vec, #[serde(default)] pub peer_site_rebuilt_transient_followon_fields: Vec, @@ -4793,6 +4806,79 @@ fn summarize_peer_site_selector_candidate_saved_nonzero_companion_name_pairs( summaries } +fn summarize_peer_site_selector_candidate_saved_nonzero_companion_building_family_overlaps( + summaries: &[SmpSavePlacedStructureNonzeroCompanionNamePairSummaryEntry], +) -> Vec { + let nonzero_stock_family_aliases = [ + "Brewery", + "ConcretePlant", + "ConstructionFirm", + "DairyProcessor", + "Distillery", + "ElectronicsPlant", + "Furnace", + "FurnitureFactory", + "Hospital", + "Lumbermill", + "MachineShop", + "MeatPackingPlant", + "Museum", + "PaperMill", + "PharmaceuticalPlant", + "Port", + "Recycling Plant", + "Steel Mill", + "Textile Mill", + "TextileMill", + "Tire Factory", + "Tool and Die", + "Toolndie", + "Warehouse", + ] + .into_iter() + .map(canonicalize_building_like_name) + .collect::>(); + let mut overlaps = summaries + .iter() + .filter_map(|entry| { + let primary_matches = nonzero_stock_family_aliases + .contains(&canonicalize_building_like_name(&entry.primary_name)); + let secondary_matches = nonzero_stock_family_aliases + .contains(&canonicalize_building_like_name(&entry.secondary_name)); + if !(primary_matches || secondary_matches) { + return None; + } + Some( + SmpSavePlacedStructureNonzeroCompanionBuildingFamilyOverlapSummaryEntry { + companion_byte_hex: entry.companion_byte_hex.clone(), + primary_name: entry.primary_name.clone(), + secondary_name: entry.secondary_name.clone(), + count: entry.count, + primary_matches_nonzero_stock_building_header_family: primary_matches, + secondary_matches_nonzero_stock_building_header_family: secondary_matches, + }, + ) + }) + .collect::>(); + overlaps.sort_by(|left, right| { + right + .count + .cmp(&left.count) + .then_with(|| left.companion_byte_hex.cmp(&right.companion_byte_hex)) + .then_with(|| left.primary_name.cmp(&right.primary_name)) + .then_with(|| left.secondary_name.cmp(&right.secondary_name)) + }); + overlaps.truncate(10); + overlaps +} + +fn canonicalize_building_like_name(name: &str) -> String { + name.chars() + .filter(|ch| !matches!(ch, ' ' | '_' | '-')) + .flat_map(|ch| ch.to_lowercase()) + .collect() +} + fn summarize_near_city_acquisition_tri_lane_save_shape_family_candidates( analysis: &SmpSaveCompanyChairmanAnalysisReport, ) -> Vec { @@ -4858,6 +4944,10 @@ fn build_periodic_company_service_trace_report( summarize_peer_site_selector_candidate_saved_policy_trailing_words(analysis); let peer_site_selector_candidate_saved_nonzero_companion_name_pair_summaries = summarize_peer_site_selector_candidate_saved_nonzero_companion_name_pairs(analysis); + let peer_site_selector_candidate_saved_nonzero_companion_building_family_overlap_summaries = + summarize_peer_site_selector_candidate_saved_nonzero_companion_building_family_overlaps( + &peer_site_selector_candidate_saved_nonzero_companion_name_pair_summaries, + ); let peer_site_persisted_selector_bundle_fields = vec![ "0x5dc1 payload lane [owner+0x23e] restored by 0x0045c150 and later fed into 0x0045c36e" .to_string(), @@ -5640,6 +5730,20 @@ fn build_periodic_company_service_trace_report( dominant_nonzero_companion.count )); } + if !peer_site_selector_candidate_saved_nonzero_companion_building_family_overlap_summaries + .is_empty() + { + let dominant_overlap = + &peer_site_selector_candidate_saved_nonzero_companion_building_family_overlap_summaries + [0]; + notes.push(format!( + "The same nonzero 0x5dc1 name-pair residue now bridges directly into the recovered stock Tier-2 building family too: the leading overlapping saved pair is {} / {} with byte {} x{}, and it matches the checked-in nonzero stock `.bty` header family (`dword_0xbb = 0x000001f4`) rather than the zero-valued station or maintenance/service families. That makes the acquisition-side discriminator and the Tier-2 banked-clone frontier a shared narrower industrial/commercial subset question, not two separate broad mysteries.", + dominant_overlap.primary_name, + dominant_overlap.secondary_name, + dominant_overlap.companion_byte_hex, + dominant_overlap.count + )); + } notes.push( "Direct disassembly now also separates the narrower peer-class gate from that payload residue: 0x0047fd50 resolves the linked peer through [site+0x04], reads candidate class byte [candidate+0x8c], and returns true only for values 0/1/2 while rejecting 3/4 and above. That means the newly isolated post-secondary byte is not the already-grounded station-or-transit class gate itself; it remains a separate saved discriminator above the restored name-pair payload.".to_string(), ); @@ -5689,6 +5793,7 @@ fn build_periodic_company_service_trace_report( peer_site_selector_candidate_saved_companion_byte_summaries, peer_site_selector_candidate_saved_policy_trailing_word_summaries, peer_site_selector_candidate_saved_nonzero_companion_name_pair_summaries, + peer_site_selector_candidate_saved_nonzero_companion_building_family_overlap_summaries, peer_site_persisted_selector_bundle_fields, peer_site_rebuilt_transient_followon_fields, peer_site_shellless_minimum_persisted_identity_status, @@ -31050,6 +31155,11 @@ mod tests { .primary_name, "StationA" ); + assert!( + trace + .peer_site_selector_candidate_saved_nonzero_companion_building_family_overlap_summaries + .is_empty() + ); assert_eq!(trace.peer_site_persisted_selector_bundle_fields.len(), 4); assert_eq!(trace.peer_site_rebuilt_transient_followon_fields.len(), 4); assert_eq!( @@ -32633,6 +32743,41 @@ mod tests { ); } + #[test] + fn summarizes_nonzero_companion_building_family_overlaps() { + let overlaps = + summarize_peer_site_selector_candidate_saved_nonzero_companion_building_family_overlaps( + &[ + SmpSavePlacedStructureNonzeroCompanionNamePairSummaryEntry { + companion_byte_hex: "0x01".to_string(), + primary_name: "TextileMill".to_string(), + secondary_name: "TextileMill".to_string(), + count: 9, + }, + SmpSavePlacedStructureNonzeroCompanionNamePairSummaryEntry { + companion_byte_hex: "0x01".to_string(), + primary_name: "Toolndie".to_string(), + secondary_name: "Toolndie".to_string(), + count: 2, + }, + SmpSavePlacedStructureNonzeroCompanionNamePairSummaryEntry { + companion_byte_hex: "0x01".to_string(), + primary_name: "MunitionsFactory".to_string(), + secondary_name: "MunitionsFactory".to_string(), + count: 1, + }, + ], + ); + + assert_eq!(overlaps.len(), 2); + assert_eq!(overlaps[0].primary_name, "TextileMill"); + assert!(overlaps[0].primary_matches_nonzero_stock_building_header_family); + assert!(overlaps[0].secondary_matches_nonzero_stock_building_header_family); + assert_eq!(overlaps[1].primary_name, "Toolndie"); + assert!(overlaps[1].primary_matches_nonzero_stock_building_header_family); + assert!(overlaps[1].secondary_matches_nonzero_stock_building_header_family); + } + #[test] fn builds_infrastructure_asset_trace_report_with_alias_disproved_status() { let mut analysis = empty_analysis_report(); 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 b1a5c23..fdb82fc 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 @@ -1324,6 +1324,13 @@ family under the stock assets; the remaining open question is why the later clone chooser favors this narrower `0x000001f4` stock family over the zero-valued station and maintenance / service rows. + The peer-site save residue now bridges back into that Tier-2 stock family too. The periodic + company trace can classify nonzero `0x5dc1` post-secondary name pairs against the recovered + nonzero `.bty` header family, and the current grounded overlap set is `TextileMill`, + `Toolndie`, `Brewery`, and `MeatPackingPlant` while `MunitionsFactory` remains the explicit + current residue outside the recovered `0x000001f4` stock header family. So the acquisition-side + post-secondary-byte question and the Tier-2 numbered-bank question now share one narrower + industrial/commercial subset frontier instead of two unrelated broad families. The direct `+0xba/+0xbb` writer census now rules out a broad false lead too. The obvious new stores at `0x004ecd42/0x004ecdaa` and `0x004ed5d5/0x004ed625` are only shell-side portrait/string refresh helpers over a different id-keyed collection rooted through diff --git a/docs/rehost-queue.md b/docs/rehost-queue.md index c6122d6..fcbc35d 100644 --- a/docs/rehost-queue.md +++ b/docs/rehost-queue.md @@ -1268,6 +1268,11 @@ Working rule: exposes `TextileMill x9`, `Toolndie x2`, and singleton `Brewery`, `MeatPackingPlant`, and `MunitionsFactory` rows, so the next peer-site slice should treat nonzero post-secondary-byte rows as a likely industry-like subset rather than a generic placed-structure mode split + - that bridge is explicit now too: the periodic trace can classify those nonzero companion + names against the recovered stock Tier-2 building family, and the current grounded overlap set + is `TextileMill`, `Toolndie`, `Brewery`, and `MeatPackingPlant` while + `MunitionsFactory` remains the clear current residue outside the recovered + `0x000001f4` stock header family - keep the already-grounded `0x0047fd50` class gate separate from that byte: direct disassembly now says `0x0047fd50` resolves the linked peer through `[site+0x04]`, reads candidate class byte `[candidate+0x8c]`, and returns true only for `0/1/2` while rejecting `3/4` and above,