diff --git a/crates/rrt-runtime/src/smp.rs b/crates/rrt-runtime/src/smp.rs index 9940784..ab3fc86 100644 --- a/crates/rrt-runtime/src/smp.rs +++ b/crates/rrt-runtime/src/smp.rs @@ -3454,6 +3454,8 @@ pub struct SmpSaveCompanyRecordAnalysisEntry { pub preferred_locomotive_engine_type_raw_hex: String, pub city_connection_latch: bool, pub linked_transit_latch: bool, + pub linked_transit_autoroute_site_score_cache_refresh_absolute_counter: u32, + pub linked_transit_site_peer_cache_refresh_absolute_counter: u32, #[serde(default)] pub linked_transit_route_anchor_entry_id: Option, #[serde(default)] @@ -3564,6 +3566,8 @@ pub struct SmpPeriodicCompanyServiceTraceEntry { pub preferred_locomotive_engine_type_raw_u8: u8, pub city_connection_latch: bool, pub linked_transit_latch: bool, + pub linked_transit_autoroute_site_score_cache_refresh_absolute_counter: u32, + pub linked_transit_site_peer_cache_refresh_absolute_counter: u32, #[serde(default)] pub branches: Vec, } @@ -5045,6 +5049,9 @@ fn build_periodic_company_service_trace_report( "blocked_missing_infrastructure_asset_consumer_mapping", &[ "company linked-transit latch", + "company linked-transit route-anchor tuple", + "company linked-transit peer-cache refresh absolute counter [company+0x0d3e]", + "company linked-transit autoroute-score refresh absolute counter [company+0x0d3a]", "route-preference override seam", ], &[ @@ -5053,10 +5060,14 @@ fn build_periodic_company_service_trace_report( ], &[ "0x004019e0 periodic company outer owner", + "0x00409720 timed linked-transit cache-service wrapper", + "0x004093d0 linked-transit site-peer cache rebuild", + "0x00407bd0 linked-transit autoroute site-score cache rebuild", + "0x00408f70 linked-transit aggregate site-score pressure helper", "0x00409950 linked-transit train-roster balancer", ], &[ - "The save side now grounds the owner seams, but not yet the higher-layer consumer that turns them into roster or route actions.", + "The save side now grounds the timed cache-owner seams and route-anchor tuple, but not yet the higher-layer consumer mapping that turns the rebuilt site caches into roster or route actions.", ], )); branches.push(build_service_trace_branch_status( @@ -5109,6 +5120,10 @@ fn build_periodic_company_service_trace_report( .preferred_locomotive_engine_type_raw_u8, city_connection_latch: entry.city_connection_latch, linked_transit_latch: entry.linked_transit_latch, + linked_transit_autoroute_site_score_cache_refresh_absolute_counter: entry + .linked_transit_autoroute_site_score_cache_refresh_absolute_counter, + linked_transit_site_peer_cache_refresh_absolute_counter: entry + .linked_transit_site_peer_cache_refresh_absolute_counter, branches, } }) @@ -5148,6 +5163,9 @@ fn build_periodic_company_service_trace_report( notes.push( "Direct disassembly now closes the collection identity too: 0x00420030 is the boolean peer gate and 0x00420280 is the first-match selector over the live placed-structure / peer-site collection 0x006cec20, combining 0x0042b2d0, the optional linked-company filter through 0x0047efe0, the station-or-transit gate 0x0047fd50, and the linked-region status branch 0x0047de00 -> 0x0040c990.".to_string(), ); + notes.push( + "The linked-transit sibling owner is tighter now too: timed wrapper 0x00409720 compares world counter [world+0x15] against the save-owned company refresh counters [company+0x0d3e] and [company+0x0d3a], reruns the shorter peer-cache rebuild 0x004093d0 on the tighter 0x7ff80 cadence, reruns the heavier autoroute score-cache rebuild 0x00407bd0 on the broader 0x31380 cadence, and then feeds the raw site-score total 0x00408f70 into roster balancer 0x00409950. That means the remaining blocker for shellless linked-transit maintenance is no longer the timing seam; it is the higher-layer placed-structure / infrastructure consumer mapping above those grounded cache owners.".to_string(), + ); 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(), ); @@ -7291,6 +7309,16 @@ pub fn inspect_save_company_and_chairman_analysis_bytes( &bytes, record_offset + SAVE_COMPANY_RECORD_LINKED_TRANSIT_LATCH_OFFSET, )? != 0; + let linked_transit_autoroute_site_score_cache_refresh_absolute_counter = read_u32_at( + &bytes, + record_offset + + SAVE_COMPANY_RECORD_LINKED_TRANSIT_AUTOROUTE_SITE_SCORE_CACHE_REFRESH_ABSOLUTE_COUNTER_OFFSET, + )?; + let linked_transit_site_peer_cache_refresh_absolute_counter = read_u32_at( + &bytes, + record_offset + + SAVE_COMPANY_RECORD_LINKED_TRANSIT_SITE_PEER_CACHE_REFRESH_ABSOLUTE_COUNTER_OFFSET, + )?; let linked_transit_route_anchor_entry_id = parse_nonzero_u32( &bytes, record_offset + SAVE_COMPANY_RECORD_LINKED_TRANSIT_ROUTE_ANCHOR_ENTRY_ID_OFFSET, @@ -7369,6 +7397,8 @@ pub fn inspect_save_company_and_chairman_analysis_bytes( ), city_connection_latch, linked_transit_latch, + linked_transit_autoroute_site_score_cache_refresh_absolute_counter, + linked_transit_site_peer_cache_refresh_absolute_counter, linked_transit_route_anchor_entry_id, linked_transit_route_anchor_fallback_counts, merger_cooldown_year, @@ -8195,6 +8225,10 @@ const SAVE_COMPANY_RECORD_LAST_DIVIDEND_YEAR_OFFSET: usize = 0x0d2d; const SAVE_COMPANY_RECORD_PREFERRED_LOCOMOTIVE_ENGINE_TYPE_OFFSET: usize = 0x0d17; const SAVE_COMPANY_RECORD_CITY_CONNECTION_LATCH_OFFSET: usize = 0x0d18; const SAVE_COMPANY_RECORD_LINKED_TRANSIT_ROUTE_ANCHOR_ENTRY_ID_OFFSET: usize = 0x0d35; +const SAVE_COMPANY_RECORD_LINKED_TRANSIT_AUTOROUTE_SITE_SCORE_CACHE_REFRESH_ABSOLUTE_COUNTER_OFFSET: usize = + 0x0d3a; +const SAVE_COMPANY_RECORD_LINKED_TRANSIT_SITE_PEER_CACHE_REFRESH_ABSOLUTE_COUNTER_OFFSET: usize = + 0x0d3e; const SAVE_COMPANY_RECORD_SUPPORT_PROGRESS_OFFSET: usize = 0x0d07; const SAVE_COMPANY_RECORD_CHAIRMAN_SALARY_CURRENT_OFFSET: usize = 0x0d59; const SAVE_COMPANY_RECORD_LINKED_TRANSIT_LATCH_OFFSET: usize = 0x0d56; @@ -28153,6 +28187,8 @@ mod tests { preferred_locomotive_engine_type_raw_hex: "0x02".to_string(), city_connection_latch: true, linked_transit_latch: false, + linked_transit_autoroute_site_score_cache_refresh_absolute_counter: 0x31380, + linked_transit_site_peer_cache_refresh_absolute_counter: 0x7ff80, linked_transit_route_anchor_entry_id: Some(77), linked_transit_route_anchor_fallback_counts: vec![3, 5, 8], merger_cooldown_year: 0, @@ -28170,6 +28206,14 @@ mod tests { assert_eq!(trace.known_bridge_helpers.len(), 84); assert_eq!(trace.next_owner_questions.len(), 5); assert_eq!(trace.companies.len(), 1); + assert_eq!( + trace.companies[0].linked_transit_autoroute_site_score_cache_refresh_absolute_counter, + 0x31380 + ); + assert_eq!( + trace.companies[0].linked_transit_site_peer_cache_refresh_absolute_counter, + 0x7ff80 + ); assert_eq!( trace.peer_site_selector_candidate_owner_strip, "0x0045c150 -> 0x0045c310 -> 0x0045c36e -> 0x00456100 -> 0x00455b70" @@ -28717,6 +28761,41 @@ mod tests { .iter() .any(|line| line.contains("0x0047efe0") && line.contains("[site+0x276]")) ); + let linked_transit_branch = trace.companies[0] + .branches + .iter() + .find(|branch| branch.branch_name == "linked_transit_roster_maintenance") + .expect("linked-transit branch"); + assert!( + linked_transit_branch + .grounded_inputs + .iter() + .any(|line| line.contains("[company+0x0d3e]")) + ); + assert!( + linked_transit_branch + .grounded_inputs + .iter() + .any(|line| line.contains("[company+0x0d3a]")) + ); + assert!( + linked_transit_branch + .candidate_consumers + .iter() + .any(|line| line.contains("0x00409720")) + ); + assert!( + linked_transit_branch + .candidate_consumers + .iter() + .any(|line| line.contains("0x00408f70")) + ); + assert!(trace.notes.iter().any(|line| { + line.contains("0x00409720") + && line.contains("[company+0x0d3e]") + && line.contains("[company+0x0d3a]") + && line.contains("0x00409950") + })); assert!( trace .near_city_acquisition_runtime_backed_input_families @@ -29186,15 +29265,12 @@ mod tests { && line.contains("literal flags 1/0") && line.contains("out-param")) ); - assert!( - trace - .known_bridge_helpers - .iter() - .any(|line| line.contains("0x00508fd1 / 0x005098eb") - && line.contains("[this+0x7c]") - && line.contains("0x0040eba0") - && line.contains("arg3 forced to zero")) - ); + assert!(trace.known_bridge_helpers.iter().any(|line| { + line.contains("0x00508fd1 / 0x005098eb") + && line.contains("[this+0x7c]") + && line.contains("0x0040eba0") + && line.contains("arg3 forced to zero") + })); assert!( trace .known_bridge_helpers @@ -29226,14 +29302,11 @@ mod tests { .any(|line| line.contains("0x004269c9 / 0x00426a2a") && line.contains("[site+0x276]/[site+0x27a]")) ); - assert!( - trace - .known_bridge_helpers - .iter() - .any(|line| line.contains("0x004282a9 / 0x004300d6") - && line.contains("owner-transfer") - && line.contains("placed-structure")) - ); + assert!(trace.known_bridge_helpers.iter().any(|line| { + line.contains("0x004282a9 / 0x004300d6") + && line.contains("owner-transfer") + && line.contains("placed-structure") + })); assert!( trace .known_bridge_helpers diff --git a/docs/rehost-queue.md b/docs/rehost-queue.md index 2f98509..cb7f966 100644 --- a/docs/rehost-queue.md +++ b/docs/rehost-queue.md @@ -20,7 +20,14 @@ Working rule: `0x004019e0 -> 0x00406050` plus peer helpers `0x00420030 / 0x00420280 / 0x0047efe0` - `linked_transit_roster_maintenance` carries - `0x004019e0 -> 0x00409950` + `0x004019e0 -> 0x00409720 -> 0x004093d0 / 0x00407bd0 -> 0x00408f70 -> 0x00409950` + - the linked-transit timing seam is now grounded save-side too: + `[company+0x0d3e]` is the shorter peer-cache refresh counter, + `[company+0x0d3a]` is the heavier autoroute site-score refresh counter, and + the route-anchor tuple `[company+0x0d35] / [company+0x7664/+0x7668/+0x766c]` remains save-native + - that makes the next linked-transit question narrower: + identify which placed-structure or infrastructure consumer above the timed cache owners + actually turns those rebuilt site caches into roster mutations or route actions - Make the next static/rehost slice the near-city industry acquisition owner seam under `0x004014b0`, not another generic infrastructure pass. The concrete questions are: - which minimum persisted peer-site fields on the already-grounded `0x006cec20` placed-structure