Bridge peer-site names to stock building family

This commit is contained in:
Jan Petykiewicz 2026-04-19 15:19:09 -07:00
commit ee8311b3f2
3 changed files with 157 additions and 0 deletions

View file

@ -3770,6 +3770,16 @@ pub struct SmpSavePlacedStructureNonzeroCompanionNamePairSummaryEntry {
pub count: usize, 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)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SmpSavePlacedStructurePolicyTrailingWordSummaryEntry { pub struct SmpSavePlacedStructurePolicyTrailingWordSummaryEntry {
pub policy_trailing_word_hex: String, pub policy_trailing_word_hex: String,
@ -3818,6 +3828,9 @@ pub struct SmpPeriodicCompanyServiceTraceReport {
pub peer_site_selector_candidate_saved_nonzero_companion_name_pair_summaries: pub peer_site_selector_candidate_saved_nonzero_companion_name_pair_summaries:
Vec<SmpSavePlacedStructureNonzeroCompanionNamePairSummaryEntry>, Vec<SmpSavePlacedStructureNonzeroCompanionNamePairSummaryEntry>,
#[serde(default)] #[serde(default)]
pub peer_site_selector_candidate_saved_nonzero_companion_building_family_overlap_summaries:
Vec<SmpSavePlacedStructureNonzeroCompanionBuildingFamilyOverlapSummaryEntry>,
#[serde(default)]
pub peer_site_persisted_selector_bundle_fields: Vec<String>, pub peer_site_persisted_selector_bundle_fields: Vec<String>,
#[serde(default)] #[serde(default)]
pub peer_site_rebuilt_transient_followon_fields: Vec<String>, pub peer_site_rebuilt_transient_followon_fields: Vec<String>,
@ -4793,6 +4806,79 @@ fn summarize_peer_site_selector_candidate_saved_nonzero_companion_name_pairs(
summaries summaries
} }
fn summarize_peer_site_selector_candidate_saved_nonzero_companion_building_family_overlaps(
summaries: &[SmpSavePlacedStructureNonzeroCompanionNamePairSummaryEntry],
) -> Vec<SmpSavePlacedStructureNonzeroCompanionBuildingFamilyOverlapSummaryEntry> {
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::<BTreeSet<_>>();
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::<Vec<_>>();
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( fn summarize_near_city_acquisition_tri_lane_save_shape_family_candidates(
analysis: &SmpSaveCompanyChairmanAnalysisReport, analysis: &SmpSaveCompanyChairmanAnalysisReport,
) -> Vec<SmpPeriodicTriLaneSaveShapeFamilyCandidateSummaryEntry> { ) -> Vec<SmpPeriodicTriLaneSaveShapeFamilyCandidateSummaryEntry> {
@ -4858,6 +4944,10 @@ fn build_periodic_company_service_trace_report(
summarize_peer_site_selector_candidate_saved_policy_trailing_words(analysis); summarize_peer_site_selector_candidate_saved_policy_trailing_words(analysis);
let peer_site_selector_candidate_saved_nonzero_companion_name_pair_summaries = let peer_site_selector_candidate_saved_nonzero_companion_name_pair_summaries =
summarize_peer_site_selector_candidate_saved_nonzero_companion_name_pairs(analysis); 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![ let peer_site_persisted_selector_bundle_fields = vec![
"0x5dc1 payload lane [owner+0x23e] restored by 0x0045c150 and later fed into 0x0045c36e" "0x5dc1 payload lane [owner+0x23e] restored by 0x0045c150 and later fed into 0x0045c36e"
.to_string(), .to_string(),
@ -5640,6 +5730,20 @@ fn build_periodic_company_service_trace_report(
dominant_nonzero_companion.count 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( 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(), "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_companion_byte_summaries,
peer_site_selector_candidate_saved_policy_trailing_word_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_name_pair_summaries,
peer_site_selector_candidate_saved_nonzero_companion_building_family_overlap_summaries,
peer_site_persisted_selector_bundle_fields, peer_site_persisted_selector_bundle_fields,
peer_site_rebuilt_transient_followon_fields, peer_site_rebuilt_transient_followon_fields,
peer_site_shellless_minimum_persisted_identity_status, peer_site_shellless_minimum_persisted_identity_status,
@ -31050,6 +31155,11 @@ mod tests {
.primary_name, .primary_name,
"StationA" "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_persisted_selector_bundle_fields.len(), 4);
assert_eq!(trace.peer_site_rebuilt_transient_followon_fields.len(), 4); assert_eq!(trace.peer_site_rebuilt_transient_followon_fields.len(), 4);
assert_eq!( 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] #[test]
fn builds_infrastructure_asset_trace_report_with_alias_disproved_status() { fn builds_infrastructure_asset_trace_report_with_alias_disproved_status() {
let mut analysis = empty_analysis_report(); let mut analysis = empty_analysis_report();

View file

@ -1324,6 +1324,13 @@
family under the stock assets; the remaining open question is why the later clone chooser favors 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 this narrower `0x000001f4` stock family over the zero-valued station and maintenance / service
rows. 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 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 stores at `0x004ecd42/0x004ecdaa` and `0x004ed5d5/0x004ed625` are only shell-side
portrait/string refresh helpers over a different id-keyed collection rooted through portrait/string refresh helpers over a different id-keyed collection rooted through

View file

@ -1268,6 +1268,11 @@ Working rule:
exposes `TextileMill x9`, `Toolndie x2`, and singleton `Brewery`, `MeatPackingPlant`, and exposes `TextileMill x9`, `Toolndie x2`, and singleton `Brewery`, `MeatPackingPlant`, and
`MunitionsFactory` rows, so the next peer-site slice should treat nonzero post-secondary-byte `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 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 - 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 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, byte `[candidate+0x8c]`, and returns true only for `0/1/2` while rejecting `3/4` and above,