Enrich periodic company service traces

This commit is contained in:
Jan Petykiewicz 2026-04-18 18:09:45 -07:00
commit 2ff09f9193
2 changed files with 200 additions and 9 deletions

View file

@ -3434,6 +3434,8 @@ pub struct SmpServiceTraceBranchStatus {
#[serde(default)]
pub blocking_inputs: Vec<String>,
#[serde(default)]
pub candidate_consumers: Vec<String>,
#[serde(default)]
pub notes: Vec<String>,
}
@ -3467,6 +3469,12 @@ pub struct SmpPeriodicCompanyServiceTraceReport {
#[serde(default)]
pub infrastructure_asset_side_buffer_present: bool,
#[serde(default)]
pub atlas_candidate_consumers: Vec<String>,
#[serde(default)]
pub known_bridge_helpers: Vec<String>,
#[serde(default)]
pub next_owner_questions: Vec<String>,
#[serde(default)]
pub companies: Vec<SmpPeriodicCompanyServiceTraceEntry>,
#[serde(default)]
pub notes: Vec<String>,
@ -3999,6 +4007,7 @@ fn build_service_trace_branch_status(
status: &str,
grounded_inputs: &[&str],
blocking_inputs: &[&str],
candidate_consumers: &[&str],
notes: &[&str],
) -> SmpServiceTraceBranchStatus {
SmpServiceTraceBranchStatus {
@ -4012,6 +4021,10 @@ fn build_service_trace_branch_status(
.iter()
.map(|value| value.to_string())
.collect(),
candidate_consumers: candidate_consumers
.iter()
.map(|value| value.to_string())
.collect(),
notes: notes.iter().map(|value| value.to_string()).collect(),
}
}
@ -4021,6 +4034,19 @@ pub fn inspect_save_periodic_company_service_trace_file(
) -> Result<SmpPeriodicCompanyServiceTraceReport, Box<dyn std::error::Error>> {
let inspection = inspect_smp_file(path)?;
let analysis = inspect_save_company_and_chairman_analysis_file(path)?;
let mut trace = build_periodic_company_service_trace_report(&analysis);
let _ = inspection;
if trace.region_record_body_present || trace.placed_structure_record_body_present {
trace.notes.push(
"The current blockers are no longer collection identity; they are missing higher-layer consumer semantics for the region and infrastructure/placed-structure owner seams.".to_string(),
);
}
Ok(trace)
}
fn build_periodic_company_service_trace_report(
analysis: &SmpSaveCompanyChairmanAnalysisReport,
) -> SmpPeriodicCompanyServiceTraceReport {
let profile_family = analysis.profile_family.clone();
let selected_company_id = analysis.selected_company_id;
let region_record_body_present = analysis.region_record_triplets.is_some();
@ -4029,6 +4055,28 @@ pub fn inspect_save_periodic_company_service_trace_file(
analysis.placed_structure_dynamic_side_buffer.is_some();
let world_issue_37_present = analysis.world_issue_37.is_some();
let world_finance_neighborhood_present = analysis.world_finance_neighborhood.is_some();
let atlas_candidate_consumers = vec![
"0x004019e0 periodic company outer service owner".to_string(),
"0x00406050 city-connection bonus/news owner".to_string(),
"0x00409950 linked-transit train-roster balancer".to_string(),
"0x004014b0 near-city industry acquisition and news owner".to_string(),
"0x00401c50 annual finance-policy owner".to_string(),
"0x004093d0 / 0x00407bd0 linked-transit refresh tails".to_string(),
];
let known_bridge_helpers = vec![
"0x004078a0 preferred-locomotive chooser feeding company byte 0x0d17".to_string(),
"0x0041d550 locomotive-era and engine-type approval gate over scenario opinion lanes"
.to_string(),
"0x00420030 / 0x00420280 city-connection peer probes".to_string(),
"0x0047efe0 placed-structure linked-company resolver".to_string(),
"0x00406050 city-connection bonus/news sibling owner".to_string(),
"0x00409950 linked-transit roster sibling owner".to_string(),
];
let next_owner_questions = vec![
"Which near-city owner or collection feeds 0x004014b0 with unowned-industry candidates before the publish-news branch runs?".to_string(),
"Which city or region peer linkage survives save/load strongly enough to let the 0x00406050 / 0x004014b0 sibling strip resolve nearby bonuses and industry proximity without shell state?".to_string(),
"Which infrastructure consumer above the grounded 0x38a5 seam actually drives the linked-transit branch that 0x00409950 follows?".to_string(),
];
let companies = analysis
.company_entries
@ -4048,6 +4096,11 @@ pub fn inspect_save_periodic_company_service_trace_file(
"preferred locomotive engine-type lane",
],
&[],
&[
"0x004019e0 periodic company outer owner",
"0x004078a0 preferred-locomotive chooser",
"0x0041d550 locomotive-era and engine-type approval gate",
],
&[
"This probe keeps the outer owner at the save-owned input level; the concrete runtime reader/apply/restore seam is already grounded separately.",
],
@ -4062,6 +4115,10 @@ pub fn inspect_save_periodic_company_service_trace_file(
"derived annual-finance readers",
],
&[],
&[
"0x004019e0 periodic company outer owner",
"0x00401c50 annual finance-policy owner",
],
&[
"The shellless annual-finance helper is already rehosted on top of runtime-owned state.",
],
@ -4079,6 +4136,12 @@ pub fn inspect_save_periodic_company_service_trace_file(
"stable region id or class discriminator",
"placed-structure or infrastructure-asset consumer mapping",
],
&[
"0x004019e0 periodic company outer owner",
"0x00406050 city-connection bonus/news owner",
"0x00420030 / 0x00420280 city-connection peer probes",
"0x0047efe0 placed-structure linked-company resolver",
],
&[
"Current atlas evidence places this branch above both the region pending-bonus lane and infrastructure/placed-structure consumers.",
],
@ -4094,6 +4157,10 @@ pub fn inspect_save_periodic_company_service_trace_file(
"placed-structure record-body semantics",
"0x38a5 infrastructure-asset consumer mapping",
],
&[
"0x004019e0 periodic company outer owner",
"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.",
],
@ -4110,7 +4177,12 @@ pub fn inspect_save_periodic_company_service_trace_file(
"city or region peer linkage",
],
&[
"The outer owner is bounded, but the concrete candidate/peer scan is not yet rehosted.",
"0x004019e0 periodic company outer owner",
"0x004014b0 near-city industry acquisition and news owner",
"0x00406050 city-connection bonus/news sibling owner",
],
&[
"The outer owner is bounded and sequenced beside city-connection, linked-transit, and annual-finance siblings, but the concrete near-city candidate scan is not yet rehosted.",
],
));
SmpPeriodicCompanyServiceTraceEntry {
@ -4128,17 +4200,11 @@ pub fn inspect_save_periodic_company_service_trace_file(
.collect::<Vec<_>>();
let mut notes = Vec::new();
let _ = inspection;
notes.push(
"Periodic company service trace is intentionally an outer-owner probe: it reports save-owned branch inputs and blocker seams without serializing the full projected runtime reader state.".to_string(),
);
if region_record_body_present || placed_structure_record_body_present {
notes.push(
"The current blockers are no longer collection identity; they are missing higher-layer consumer semantics for the region and infrastructure/placed-structure owner seams.".to_string(),
);
}
Ok(SmpPeriodicCompanyServiceTraceReport {
SmpPeriodicCompanyServiceTraceReport {
profile_family,
selected_company_id,
world_issue_37_present,
@ -4146,9 +4212,12 @@ pub fn inspect_save_periodic_company_service_trace_file(
region_record_body_present,
placed_structure_record_body_present,
infrastructure_asset_side_buffer_present,
atlas_candidate_consumers,
known_bridge_helpers,
next_owner_questions,
companies,
notes,
})
}
}
pub fn inspect_save_region_service_trace_file(
@ -4340,6 +4409,10 @@ fn build_region_service_trace_report(
"[region+0x276] pending amount lane",
"[region+0x25e] severity/source lane",
],
&[
"0x00422100 periodic class-0 region picker and queue seed owner",
"0x004337c0 queued 0x20-byte notice-node append helper",
],
&["The queued kind-7 notice family is not obviously persisted in ordinary saves, so the pending queue must be treated as transient until a direct owner seam is found."],
),
build_service_trace_branch_status(
@ -4354,6 +4427,11 @@ fn build_region_service_trace_report(
"[region+0x316] one-shot notice latch",
"stable region id or class discriminator",
],
&[
"0x004358d0 pending region bonus service owner",
"0x00420030 / 0x00420280 city-connection peer probes",
"0x0047efe0 placed-structure linked-company resolver",
],
&["The remaining region blocker is a separate owner seam for the latches the city-connection branch reads and writes."],
),
],
@ -5441,6 +5519,10 @@ fn build_infrastructure_asset_trace_report(
} else {
&["0x38a5 owner seam"]
},
&[
"0x00493be0 infrastructure tagged side-buffer collection load owner",
"0x0048dcf0 infrastructure tagged child-stream restore outer owner",
],
&[
"This seam should be treated as infrastructure-asset state rather than as a compact alias of placed-structure triplets.",
],
@ -5457,6 +5539,7 @@ fn build_infrastructure_asset_trace_report(
"0x38a5 side-buffer name-pair corpus",
],
&[],
&[],
&[
"Grounded q.gms evidence currently shows zero overlap between the side-buffer name-pair corpus and the placed-structure triplet name-pair corpus.",
],
@ -5472,6 +5555,11 @@ fn build_infrastructure_asset_trace_report(
"higher-layer consumer dispatch mapping",
"compact prefix regime semantics",
],
&[
"0x0048a1e0 infrastructure child attach helper",
"0x0048dd50 infrastructure child rebuild loop",
"0x00490a3c infrastructure payload attach helper",
],
&[
"The remaining problem is how higher-layer service code consumes this separate seam, not whether the seam exists.",
],
@ -5484,6 +5572,10 @@ fn build_infrastructure_asset_trace_report(
"side-buffer consumer mapping",
"route or roster rebuild owner path",
],
&[
"0x00448a70 / 0x00493660 / 0x0048b660 route and world follow-on family",
"0x004133b0 placed-structure local-runtime refresh outer owner",
],
&[
"The next slice should target the consumer path above the side-buffer seam rather than another raw save scan.",
],
@ -25726,6 +25818,87 @@ mod tests {
);
}
#[test]
fn builds_periodic_company_service_trace_report_with_candidate_consumers() {
let mut analysis = empty_analysis_report();
analysis.selected_company_id = Some(7);
analysis
.company_entries
.push(SmpSaveCompanyRecordAnalysisEntry {
company_id: 7,
name: "Test Company".to_string(),
active: true,
linked_chairman_profile_id: Some(3),
outstanding_shares: 1000,
debt: 0,
bond_count: 0,
live_bond_slots: Vec::new(),
largest_live_bond_principal: None,
highest_coupon_live_bond_principal: None,
available_track_laying_capacity: Some(5),
company_value_scalar_f32: 1.0,
cached_share_support_scalar_f32: 1.0,
cached_share_price_f32: 1.0,
chairman_salary_baseline: 0,
chairman_salary_current: 0,
chairman_bonus_year: 0,
chairman_bonus_amount: 0,
founding_year: 1900,
last_bankruptcy_year: 0,
last_dividend_year: 0,
preferred_locomotive_engine_type_raw_u8: 2,
preferred_locomotive_engine_type_raw_hex: "0x02".to_string(),
city_connection_latch: true,
linked_transit_latch: false,
merger_cooldown_year: 0,
takeover_cooldown_year: 0,
scalar_dword_candidates: Vec::new(),
post_capacity_dword_candidates: Vec::new(),
stat_band_root_0cfb_candidates: Vec::new(),
stat_band_root_0d7f_candidates: Vec::new(),
stat_band_root_1c47_candidates: Vec::new(),
});
let trace = build_periodic_company_service_trace_report(&analysis);
assert_eq!(trace.selected_company_id, Some(7));
assert_eq!(trace.atlas_candidate_consumers.len(), 6);
assert_eq!(trace.known_bridge_helpers.len(), 6);
assert_eq!(trace.next_owner_questions.len(), 3);
assert_eq!(trace.companies.len(), 1);
let acquisition_branch = trace.companies[0]
.branches
.iter()
.find(|branch| branch.branch_name == "industry_acquisition_side_branch")
.expect("missing acquisition branch");
assert_eq!(
acquisition_branch.status,
"blocked_missing_near-city_owner_mapping"
);
assert!(
acquisition_branch
.candidate_consumers
.iter()
.any(|line| line.contains("0x004014b0"))
);
assert!(
acquisition_branch
.candidate_consumers
.iter()
.any(|line| line.contains("0x004019e0"))
);
let city_branch = trace.companies[0]
.branches
.iter()
.find(|branch| branch.branch_name == "city_connection_announcement")
.expect("missing city branch");
assert!(
city_branch
.candidate_consumers
.iter()
.any(|line| line.contains("0x00406050"))
);
}
#[test]
fn builds_infrastructure_asset_trace_report_with_alias_disproved_status() {
let mut analysis = empty_analysis_report();