diff --git a/crates/rrt-runtime/src/smp.rs b/crates/rrt-runtime/src/smp.rs index 01d4234..951dc5f 100644 --- a/crates/rrt-runtime/src/smp.rs +++ b/crates/rrt-runtime/src/smp.rs @@ -3599,6 +3599,14 @@ pub struct SmpSavePlacedStructureProfileCompanionByteSummaryEntry { pub sample_secondary_names: Vec, } +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct SmpSavePlacedStructureNonzeroCompanionNamePairSummaryEntry { + pub companion_byte_hex: String, + pub primary_name: String, + pub secondary_name: String, + pub count: usize, +} + #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct SmpPeriodicCompanyServiceTraceReport { pub profile_family: String, @@ -3617,7 +3625,8 @@ pub struct SmpPeriodicCompanyServiceTraceReport { pub peer_site_selector_candidate_owner_strip: String, pub peer_site_selector_candidate_persisted_tag_hex: String, pub peer_site_selector_candidate_selector_lane: String, - pub peer_site_selector_candidate_companion_lane: String, + pub peer_site_selector_candidate_secondary_payload_lane: String, + pub peer_site_selector_candidate_post_secondary_byte_status: String, pub peer_site_selector_candidate_class_identity_status: String, #[serde(default)] pub peer_site_selector_candidate_helper_linkage: Vec, @@ -3634,6 +3643,9 @@ pub struct SmpPeriodicCompanyServiceTraceReport { pub peer_site_selector_candidate_saved_companion_byte_summaries: Vec, #[serde(default)] + pub peer_site_selector_candidate_saved_nonzero_companion_name_pair_summaries: + Vec, + #[serde(default)] pub peer_site_restore_input_fields: Vec, #[serde(default)] pub peer_site_runtime_input_fields: Vec, @@ -4405,6 +4417,53 @@ fn summarize_peer_site_selector_candidate_saved_companion_bytes( summaries } +fn summarize_peer_site_selector_candidate_saved_nonzero_companion_name_pairs( + analysis: &SmpSaveCompanyChairmanAnalysisReport, +) -> Vec { + let Some(triplets) = analysis.placed_structure_record_triplets.as_ref() else { + return Vec::new(); + }; + let mut grouped = BTreeMap::<(String, String, String), usize>::new(); + for entry in &triplets.entries { + let Some(companion_byte_hex) = entry.profile_companion_byte_hex.as_ref() else { + continue; + }; + if companion_byte_hex == "0x00" { + continue; + } + *grouped + .entry(( + companion_byte_hex.clone(), + entry.primary_name.clone(), + entry.secondary_name.clone(), + )) + .or_insert(0) += 1; + } + let mut summaries = grouped + .into_iter() + .map( + |((companion_byte_hex, primary_name, secondary_name), count)| { + SmpSavePlacedStructureNonzeroCompanionNamePairSummaryEntry { + companion_byte_hex, + primary_name, + secondary_name, + count, + } + }, + ) + .collect::>(); + summaries.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)) + }); + summaries.truncate(10); + summaries +} + fn build_periodic_company_service_trace_report( analysis: &SmpSaveCompanyChairmanAnalysisReport, ) -> SmpPeriodicCompanyServiceTraceReport { @@ -4420,7 +4479,9 @@ fn build_periodic_company_service_trace_report( "0x0045c150 -> 0x0045c310 -> 0x0045c36e -> 0x00456100 -> 0x00455b70".to_string(); let peer_site_selector_candidate_persisted_tag_hex = "0x5dc1".to_string(); let peer_site_selector_candidate_selector_lane = "[owner+0x23e]".to_string(); - let peer_site_selector_candidate_companion_lane = "[owner+0x242]".to_string(); + let peer_site_selector_candidate_secondary_payload_lane = "[owner+0x242]".to_string(); + let peer_site_selector_candidate_post_secondary_byte_status = + "unresolved 0x5dc1 post-secondary discriminator byte after the repeated secondary payload string".to_string(); let peer_site_selector_candidate_class_identity_status = "grounded_direct_local_helper_strip".to_string(); let peer_site_selector_candidate_helper_linkage = vec![ @@ -4438,11 +4499,16 @@ fn build_periodic_company_service_trace_report( summarize_peer_site_selector_candidate_saved_footer_padding(analysis); let peer_site_selector_candidate_saved_companion_byte_summaries = summarize_peer_site_selector_candidate_saved_companion_bytes(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_restore_input_fields = vec![ "[site+0x3cc] saved placed-structure id feeding 0x62b2fc".to_string(), "[site+0x3d0] saved companion-region id from [placed+0x173] feeding 0x62b268".to_string(), "0x5dc1 payload lane [owner+0x23e] feeding 0x0045c36e selector arg 1".to_string(), - "0x5dc1 payload lane [owner+0x242] companion lane paired with [owner+0x23e]".to_string(), + "0x5dc1 payload lane [owner+0x242] carrying the restored secondary payload string" + .to_string(), + "0x5dc1 post-secondary one-byte residue after the repeated secondary payload string" + .to_string(), ]; let peer_site_runtime_input_fields = vec![ "[site+0x04] live backing-record selector consumed by 0x0047efe0 / 0x0047fd50".to_string(), @@ -4746,7 +4812,7 @@ fn build_periodic_company_service_trace_report( ); if !peer_site_selector_candidate_saved_payload_summaries.is_empty() { notes.push(format!( - "The periodic-company trace now also carries a compact save-side summary of the tagged 0x5dc1 placed-structure profile payload/status pairs already parsed from the 0x36b1 triplet seam; dominant current pair is {} / {} x{}, dominant adjacent payload delta is {:?}, dominant one-byte companion lane is {:?}, and dominant pre-footer padding len is {:?}.", + "The periodic-company trace now also carries a compact save-side summary of the tagged 0x5dc1 placed-structure profile payload/status pairs already parsed from the 0x36b1 triplet seam; dominant current pair is {} / {} x{}, dominant adjacent payload delta is {:?}, dominant post-secondary byte is {:?}, and dominant pre-footer padding len is {:?}.", peer_site_selector_candidate_saved_payload_summaries[0].profile_payload_dword_hex, peer_site_selector_candidate_saved_payload_summaries[0].profile_status_kind, peer_site_selector_candidate_saved_payload_summaries[0].count, @@ -4761,6 +4827,17 @@ fn build_periodic_company_service_trace_report( .map(|entry| entry.padding_len) )); } + if !peer_site_selector_candidate_saved_nonzero_companion_name_pair_summaries.is_empty() { + let dominant_nonzero_companion = + &peer_site_selector_candidate_saved_nonzero_companion_name_pair_summaries[0]; + notes.push(format!( + "The nonzero 0x5dc1 post-secondary byte residue is now narrower too: the trace exposes exact saved name pairs for nonzero-byte rows, and the current leading pair is {} / {} with byte {} x{}. The same atlas-backed owner strip already restores the repeated primary and secondary payload strings into [owner+0x23e] and [owner+0x242], so this byte should now be treated as a separate discriminator after the secondary string, not as the [owner+0x242] field itself. On grounded saves the exposed nonzero sample set is dominated by industry-like names rather than stations, maintenance, or residential rows, which makes the byte a stronger acquisition-side discriminator candidate than the monotone payload dword.", + dominant_nonzero_companion.primary_name, + dominant_nonzero_companion.secondary_name, + dominant_nonzero_companion.companion_byte_hex, + dominant_nonzero_companion.count + )); + } notes.push( "The replay strip is tighter now too. 0x00444690 is the current late world bring-up caller of 0x004133b0, that outer owner drains queued site ids through 0x0040e450 and then sweeps every live placed structure through 0x0040ee10, and 0x0040ee10 itself reaches 0x0040edf6 -> 0x00480710 plus the later 0x0040e360 follow-on. A separate runtime path at 0x004160aa also re-enters 0x0040ee10 later. So [peer+0x08] replay is no longer the open question, and [site+0x04] is no longer an owner mystery either: the local linked-site helper strip seeds [site+0x3cc/+0x3d0] from 0x62b2fc / 0x62b268, reaches the save-backed 0x0045c150 / 0x0045c310 owner directly, that owner fills [owner+0x23e/+0x242] from tagged payload 0x5dc1, and 0x0045c36e then feeds [owner+0x23e] through 0x00456100 -> 0x00455b70 -> 0x0052edf0 into [site+0x04]. The remaining non-hook target is now the smaller shellless-simulation question: which subset of those persisted site/peer fields is actually sufficient to run 0x004014b0 and its city-connection sibling without shell state.".to_string(), ); @@ -4776,13 +4853,15 @@ fn build_periodic_company_service_trace_report( peer_site_selector_candidate_owner_strip, peer_site_selector_candidate_persisted_tag_hex, peer_site_selector_candidate_selector_lane, - peer_site_selector_candidate_companion_lane, + peer_site_selector_candidate_secondary_payload_lane, + peer_site_selector_candidate_post_secondary_byte_status, peer_site_selector_candidate_class_identity_status, peer_site_selector_candidate_helper_linkage, peer_site_selector_candidate_saved_payload_summaries, peer_site_selector_candidate_saved_payload_delta_summaries, peer_site_selector_candidate_saved_footer_padding_summaries, peer_site_selector_candidate_saved_companion_byte_summaries, + peer_site_selector_candidate_saved_nonzero_companion_name_pair_summaries, peer_site_restore_input_fields, peer_site_runtime_input_fields, peer_site_runtime_reconstruction_status, @@ -27545,9 +27624,14 @@ mod tests { "[owner+0x23e]" ); assert_eq!( - trace.peer_site_selector_candidate_companion_lane, + trace.peer_site_selector_candidate_secondary_payload_lane, "[owner+0x242]" ); + assert!( + trace + .peer_site_selector_candidate_post_secondary_byte_status + .contains("post-secondary discriminator byte") + ); assert_eq!( trace.peer_site_selector_candidate_class_identity_status, "grounded_direct_local_helper_strip" @@ -27579,7 +27663,12 @@ mod tests { trace.peer_site_selector_candidate_saved_companion_byte_summaries[0].companion_byte_hex, "0x00" ); - assert_eq!(trace.peer_site_restore_input_fields.len(), 4); + assert_eq!( + trace.peer_site_selector_candidate_saved_nonzero_companion_name_pair_summaries[0] + .primary_name, + "StationA" + ); + assert_eq!(trace.peer_site_restore_input_fields.len(), 5); assert_eq!(trace.peer_site_runtime_input_fields.len(), 3); assert_eq!( trace.peer_site_runtime_reconstruction_status, diff --git a/docs/rehost-queue.md b/docs/rehost-queue.md index 830d1e3..678943e 100644 --- a/docs/rehost-queue.md +++ b/docs/rehost-queue.md @@ -93,11 +93,13 @@ Working rule: almost entirely unique while the status kind stays `unset`, and the dominant adjacent payload delta is `0x00000780` across `1908` steps; grounded `q.gms` shows the same dominant adjacent delta `0x00000780` across `1868` steps - - the same trace now also promotes the one-byte `0x5dc1` companion lane explicitly: grounded + - the same trace now also promotes the one-byte `0x5dc1` post-secondary discriminator explicitly: + grounded `p.gms` shows dominant companion byte `0x00` on `2023` rows with only `3` `0x01` rows, and grounded `q.gms` shows dominant companion byte `0x00` on `2043` rows with only `14` `0x01` - rows; the old “pre-footer padding” hypothesis is now better understood as the probable - `[owner+0x242]` companion lane rather than anonymous slack bytes + rows; the old “pre-footer padding” hypothesis is now better understood as a separate + post-secondary discriminator byte after the repeated secondary payload string, not as the + `[owner+0x242]` field itself So the next owner question is no longer “what does the acquisition branch do?” or “which post- load owner replays linked-site refresh?” but “which concrete `0x00455b70` caller family applies to the live site rows, and which persisted lane becomes the selector bundle that ultimately @@ -128,10 +130,16 @@ Working rule: (`dominant adjacent delta 0x780` on both `p.gms` and `q.gms`) rather than a compact selector family, so the next peer-site slice should treat that raw dword as a likely allocator/offset lane until a stronger selector interpretation appears - - use the new `0x5dc1` companion-byte summary in the same trace as positive evidence: - the probable `[owner+0x242]` lane is overwhelmingly `0x00` with a tiny `0x01` residue on both - grounded saves, so the next peer-site slice should treat that byte as a real typed companion - discriminator and ask which later `0x004014b0` / `0x00406050` predicates actually consume it + - use the new `0x5dc1` post-secondary-byte summary in the same trace as positive evidence: + that byte is overwhelmingly `0x00` with a tiny `0x01` residue on both grounded saves, so the + next peer-site slice should treat it as a real typed discriminator after the restored + `[owner+0x23e]` / `[owner+0x242]` payload strings and ask which later `0x004014b0` / + `0x00406050` predicates actually consume it + - use the new nonzero-companion name-pair summary in the same trace as a narrower acquisition + clue too: grounded `p.gms` exposes only `TextileMill/TextileMill x3`, while grounded `q.gms` + 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 - treat the peer-site selector seam itself as grounded enough for planning purposes - use the new structured restore/runtime field split in the same trace: restore subset