From 26848f96e6285351685f6d6a5ca600ce543651d4 Mon Sep 17 00:00:00 2001 From: Jan Petykiewicz Date: Sat, 18 Apr 2026 20:10:29 -0700 Subject: [PATCH] Summarize peer-site payload ladders --- crates/rrt-runtime/src/smp.rs | 219 ++++++++++++++++++++++++++++++++++ docs/rehost-queue.md | 9 ++ 2 files changed, 228 insertions(+) diff --git a/crates/rrt-runtime/src/smp.rs b/crates/rrt-runtime/src/smp.rs index ac982e5..19055a2 100644 --- a/crates/rrt-runtime/src/smp.rs +++ b/crates/rrt-runtime/src/smp.rs @@ -3555,6 +3555,23 @@ pub struct SmpPeriodicCompanyServiceTraceEntry { pub branches: Vec, } +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct SmpSavePlacedStructureProfilePayloadSummaryEntry { + pub profile_payload_dword_hex: String, + pub profile_status_kind: String, + pub count: usize, + #[serde(default)] + pub sample_primary_names: Vec, + #[serde(default)] + pub sample_secondary_names: Vec, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct SmpSavePlacedStructureProfilePayloadDeltaSummaryEntry { + pub delta_hex: String, + pub count: usize, +} + #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct SmpPeriodicCompanyServiceTraceReport { pub profile_family: String, @@ -3577,6 +3594,12 @@ pub struct SmpPeriodicCompanyServiceTraceReport { #[serde(default)] pub peer_site_selector_candidate_helper_linkage: Vec, #[serde(default)] + pub peer_site_selector_candidate_saved_payload_summaries: + Vec, + #[serde(default)] + pub peer_site_selector_candidate_saved_payload_delta_summaries: + Vec, + #[serde(default)] pub peer_site_restore_input_fields: Vec, #[serde(default)] pub peer_site_runtime_input_fields: Vec, @@ -4174,6 +4197,97 @@ pub fn inspect_save_periodic_company_service_trace_file( Ok(trace) } +fn summarize_peer_site_selector_candidate_saved_payloads( + analysis: &SmpSaveCompanyChairmanAnalysisReport, +) -> Vec { + let Some(triplets) = analysis.placed_structure_record_triplets.as_ref() else { + return Vec::new(); + }; + let mut grouped = + BTreeMap::<(String, String), (usize, BTreeSet, BTreeSet)>::new(); + for entry in &triplets.entries { + let grouped_entry = grouped + .entry(( + entry.profile_payload_dword_hex.clone(), + entry.profile_status_kind.clone(), + )) + .or_insert_with(|| (0, BTreeSet::new(), BTreeSet::new())); + grouped_entry.0 += 1; + if grouped_entry.1.len() < 4 { + grouped_entry.1.insert(entry.primary_name.clone()); + } + if grouped_entry.2.len() < 4 { + grouped_entry.2.insert(entry.secondary_name.clone()); + } + } + let mut summaries = grouped + .into_iter() + .map( + |( + (profile_payload_dword_hex, profile_status_kind), + (count, primary_names, secondary_names), + )| { + SmpSavePlacedStructureProfilePayloadSummaryEntry { + profile_payload_dword_hex, + profile_status_kind, + count, + sample_primary_names: primary_names.into_iter().collect(), + sample_secondary_names: secondary_names.into_iter().collect(), + } + }, + ) + .collect::>(); + summaries.sort_by(|left, right| { + right + .count + .cmp(&left.count) + .then_with(|| { + left.profile_payload_dword_hex + .cmp(&right.profile_payload_dword_hex) + }) + .then_with(|| left.profile_status_kind.cmp(&right.profile_status_kind)) + }); + summaries.truncate(8); + summaries +} + +fn summarize_peer_site_selector_candidate_saved_payload_deltas( + analysis: &SmpSaveCompanyChairmanAnalysisReport, +) -> Vec { + let Some(triplets) = analysis.placed_structure_record_triplets.as_ref() else { + return Vec::new(); + }; + let mut payload_values = triplets + .entries + .iter() + .map(|entry| entry.profile_payload_dword) + .collect::>(); + payload_values.sort_unstable(); + payload_values.dedup(); + let mut delta_counts = BTreeMap::::new(); + for window in payload_values.windows(2) { + let delta = window[1].wrapping_sub(window[0]); + *delta_counts.entry(delta).or_insert(0) += 1; + } + let mut summaries = delta_counts + .into_iter() + .map( + |(delta, count)| SmpSavePlacedStructureProfilePayloadDeltaSummaryEntry { + delta_hex: format!("0x{delta:08x}"), + count, + }, + ) + .collect::>(); + summaries.sort_by(|left, right| { + right + .count + .cmp(&left.count) + .then_with(|| left.delta_hex.cmp(&right.delta_hex)) + }); + summaries.truncate(6); + summaries +} + fn build_periodic_company_service_trace_report( analysis: &SmpSaveCompanyChairmanAnalysisReport, ) -> SmpPeriodicCompanyServiceTraceReport { @@ -4198,6 +4312,10 @@ fn build_periodic_company_service_trace_report( "0x0040d1e1 -> 0x0045c3c0 consumes the same owner family's [site+0x246] child lane" .to_string(), ]; + let peer_site_selector_candidate_saved_payload_summaries = + summarize_peer_site_selector_candidate_saved_payloads(analysis); + let peer_site_selector_candidate_saved_payload_delta_summaries = + summarize_peer_site_selector_candidate_saved_payload_deltas(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(), @@ -4504,6 +4622,17 @@ fn build_periodic_company_service_trace_report( notes.push( "Direct disassembly now closes the negative persistence side too: the direct 0x36b1 per-record callbacks serialize the shared base scalar triplets rooted at [this+0x206/+0x20a/+0x20e] plus the subordinate payload callback strip, while the 0x4a9d/0x4a3a/0x4a3b side-buffer owner only persists route-entry lists, three byte arrays, five proximity buckets, and the sampled-cell list. That means neither checked-in save owner seam currently persists the core peer-site identity fields [site+0x04], [site+0x2a8], or [peer+0x08] directly.".to_string(), ); + 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{}, and dominant adjacent payload delta 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, + peer_site_selector_candidate_saved_payload_delta_summaries + .first() + .map(|entry| entry.delta_hex.as_str()) + )); + } 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(), ); @@ -4521,6 +4650,8 @@ fn build_periodic_company_service_trace_report( peer_site_selector_candidate_selector_lane, 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_restore_input_fields, peer_site_runtime_input_fields, peer_site_runtime_reconstruction_status, @@ -27094,6 +27225,76 @@ mod tests { fn builds_periodic_company_service_trace_report_with_candidate_consumers() { let mut analysis = empty_analysis_report(); analysis.selected_company_id = Some(7); + analysis.placed_structure_record_triplets = + Some(SmpSavePlacedStructureRecordTripletProbe { + profile_family: analysis.profile_family.clone(), + 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: "StationA".to_string(), + secondary_name: "StationSetA".to_string(), + name_tag_relative_offset: 0, + policy_tag_relative_offset: 0, + profile_tag_relative_offset: 0, + policy_chunk_len: 0x1a, + profile_chunk_len: 0x20, + 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: 0x0101, + policy_trailing_word_hex: "0x0101".to_string(), + profile_open_marker: 0x5dc1, + profile_open_marker_hex: "0x00005dc1".to_string(), + profile_repeated_primary_name: "StationA".to_string(), + profile_repeated_secondary_name: "StationSetA".to_string(), + profile_payload_dword: 0x0e373880, + profile_payload_dword_hex: "0x0e373880".to_string(), + profile_sentinel_i32: -1, + profile_status_kind: "unset".to_string(), + farm_growth_stage_index: None, + profile_close_marker: 0x5dc2, + profile_close_marker_hex: "0x00005dc2".to_string(), + }, + SmpSavePlacedStructureRecordTripletEntryProbe { + record_index: 1, + primary_name: "StationB".to_string(), + secondary_name: "StationSetB".to_string(), + name_tag_relative_offset: 0, + policy_tag_relative_offset: 0, + profile_tag_relative_offset: 0, + policy_chunk_len: 0x1a, + profile_chunk_len: 0x20, + 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: 0x0101, + policy_trailing_word_hex: "0x0101".to_string(), + profile_open_marker: 0x5dc1, + profile_open_marker_hex: "0x00005dc1".to_string(), + profile_repeated_primary_name: "StationB".to_string(), + profile_repeated_secondary_name: "StationSetB".to_string(), + profile_payload_dword: 0x0e373500, + profile_payload_dword_hex: "0x0e373500".to_string(), + profile_sentinel_i32: -1, + profile_status_kind: "unset".to_string(), + farm_growth_stage_index: None, + profile_close_marker: 0x5dc2, + profile_close_marker_hex: "0x00005dc2".to_string(), + }, + ], + evidence: Vec::new(), + }); analysis .company_entries .push(SmpSaveCompanyRecordAnalysisEntry { @@ -27154,6 +27355,24 @@ mod tests { "grounded_direct_local_helper_strip" ); assert_eq!(trace.peer_site_selector_candidate_helper_linkage.len(), 4); + assert_eq!( + trace + .peer_site_selector_candidate_saved_payload_summaries + .len(), + 2 + ); + assert_eq!( + trace.peer_site_selector_candidate_saved_payload_summaries[0].profile_payload_dword_hex, + "0x0e373500" + ); + assert_eq!( + trace.peer_site_selector_candidate_saved_payload_summaries[0].count, + 1 + ); + assert_eq!( + trace.peer_site_selector_candidate_saved_payload_delta_summaries[0].delta_hex, + "0x00000380" + ); assert_eq!(trace.peer_site_restore_input_fields.len(), 4); assert_eq!(trace.peer_site_runtime_input_fields.len(), 3); assert_eq!( diff --git a/docs/rehost-queue.md b/docs/rehost-queue.md index 5d9543a..7d59932 100644 --- a/docs/rehost-queue.md +++ b/docs/rehost-queue.md @@ -88,6 +88,10 @@ Working rule: three-arg wrapper `0x00530640` - `0x00490a79` is one chooser-side caller of `0x00455b70`, feeding literal selector `0x005cfd74` with fallback seed `0x005c87a8` + - the periodic-company trace now also surfaces the save-side `0x5dc1` payload/status summaries + already parsed from the `0x36b1` triplet seam; on grounded `p.gms` the payload dword lane is + almost entirely unique while the status kind stays `unset`, and the dominant adjacent payload + delta is `0x00000780` across `1908` steps 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 @@ -113,6 +117,11 @@ Working rule: `grounded_direct_local_helper_strip`, and helper linkage `0x0040ceab -> 0x0045c150` / `0x0040d1a1 -> 0x0045c310` / `0x0040cd70 seeds [site+0x3cc/+0x3d0] from 0x62b2fc / 0x62b268` + - use the new `0x5dc1` payload/status summary in the same trace as negative evidence too: + the current `profile_payload_dword` lane behaves like a monotone ladder (`dominant adjacent + delta 0x780`) 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 - 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