From ec359ec2f9c57c60c81315356dc36bab61603219 Mon Sep 17 00:00:00 2001 From: Jan Petykiewicz Date: Sat, 18 Apr 2026 01:59:36 -0700 Subject: [PATCH] Surface annual bond retired and issued totals --- README.md | 4 ++- crates/rrt-runtime/src/import.rs | 2 ++ crates/rrt-runtime/src/runtime.rs | 4 +++ crates/rrt-runtime/src/step.rs | 47 +++++++++++++++++++++++++++---- crates/rrt-runtime/src/summary.rs | 8 ++++++ docs/README.md | 4 ++- docs/runtime-rehost-plan.md | 3 +- 7 files changed, 64 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index f08691d..f5df3b2 100644 --- a/README.md +++ b/README.md @@ -104,7 +104,9 @@ compaction path before issuing the exact staged count. The annual dividend lane shared year-or-control-transfer metric seam, the board-approved dividend ceiling helper, and the full annual dividend adjustment branch over owned current cash, public float, current dividend, building-growth policy, and recent profit history instead of leaving that policy on shell-side -dialog notes. `simulation_service_periodic_boundary_work` is now beginning to use that same owner +dialog notes. The same periodic service now also carries the annual bond lane's retired-versus- +issued principal totals as first-class runtime summary state, which is the owner seam behind the +later debt-news family. `simulation_service_periodic_boundary_work` is now beginning to use that same owner surface too: the runtime chooses one annual-finance action per active company and already commits the shellless creditor-pressure-bankruptcy, deep-distress-bankruptcy, dividend-adjustment, stock-repurchase, stock-issue, and bond-issue branches by mutating owned company activity, diff --git a/crates/rrt-runtime/src/import.rs b/crates/rrt-runtime/src/import.rs index 659278e..d15f02d 100644 --- a/crates/rrt-runtime/src/import.rs +++ b/crates/rrt-runtime/src/import.rs @@ -13993,6 +13993,8 @@ mod tests { annual_finance_last_actions: BTreeMap::new(), annual_finance_action_counts: BTreeMap::new(), annual_dividend_adjustment_commit_count: 0, + annual_bond_last_retired_principal_total: 0, + annual_bond_last_issued_principal_total: 0, chairman_issue_opinion_terms_raw_i32: BTreeMap::new(), chairman_personality_raw_u8: BTreeMap::new(), }, diff --git a/crates/rrt-runtime/src/runtime.rs b/crates/rrt-runtime/src/runtime.rs index 3de7c3e..21249a2 100644 --- a/crates/rrt-runtime/src/runtime.rs +++ b/crates/rrt-runtime/src/runtime.rs @@ -1237,6 +1237,10 @@ pub struct RuntimeServiceState { #[serde(default)] pub annual_dividend_adjustment_commit_count: u64, #[serde(default)] + pub annual_bond_last_retired_principal_total: u64, + #[serde(default)] + pub annual_bond_last_issued_principal_total: u64, + #[serde(default)] pub chairman_issue_opinion_terms_raw_i32: BTreeMap>, #[serde(default)] pub chairman_personality_raw_u8: BTreeMap, diff --git a/crates/rrt-runtime/src/step.rs b/crates/rrt-runtime/src/step.rs index 209db92..73490c7 100644 --- a/crates/rrt-runtime/src/step.rs +++ b/crates/rrt-runtime/src/step.rs @@ -385,14 +385,14 @@ fn service_apply_company_bankruptcy(state: &mut RuntimeState, company_id: u32) - fn service_repay_matured_company_live_bonds_and_compact( state: &mut RuntimeState, company_id: u32, -) -> bool { +) -> Option { let Some(current_year_word) = state .world_restore .packed_year_word_raw_u16 .map(u32::from) .or_else(|| Some(state.calendar.year)) else { - return false; + return None; }; let retired_principal_total = state .service_state @@ -408,7 +408,7 @@ fn service_repay_matured_company_live_bonds_and_compact( }) .unwrap_or(0); if retired_principal_total == 0 { - return false; + return None; } let retired_principal_total_f64 = retired_principal_total as f64; @@ -481,7 +481,7 @@ fn service_repay_matured_company_live_bonds_and_compact( company_mutated = true; } - company_mutated + company_mutated.then_some(retired_principal_total) } fn service_company_annual_finance_policy( @@ -500,6 +500,8 @@ fn service_company_annual_finance_policy( .annual_finance_last_actions .retain(|company_id, _| active_company_id_set.contains(company_id)); state.service_state.annual_finance_service_calls += 1; + state.service_state.annual_bond_last_retired_principal_total = 0; + state.service_state.annual_bond_last_issued_principal_total = 0; let mut mutated_company_ids = BTreeSet::new(); let mut applied_effect_count = 0u32; @@ -632,7 +634,14 @@ fn service_company_annual_finance_policy( if !bond_state.eligible_for_bond_issue_branch { continue; } - mutated |= service_repay_matured_company_live_bonds_and_compact(state, company_id); + let retired_principal_total = + service_repay_matured_company_live_bonds_and_compact(state, company_id) + .unwrap_or(0); + mutated |= retired_principal_total > 0; + state.service_state.annual_bond_last_retired_principal_total = state + .service_state + .annual_bond_last_retired_principal_total + .saturating_add(retired_principal_total); let issue_bond_count = bond_state.proposed_issue_bond_count.unwrap_or(0); let Some(principal) = bond_state.issue_principal_step else { @@ -734,6 +743,10 @@ fn service_company_annual_finance_policy( }) .map(|(_, principal)| principal); market_state.highest_coupon_live_bond_principal = highest_coupon_live_principal; + state.service_state.annual_bond_last_issued_principal_total = state + .service_state + .annual_bond_last_issued_principal_total + .saturating_add(u64::from(principal)); } if let Some(company) = state .companies @@ -3165,6 +3178,14 @@ mod tests { ); assert_eq!(state.companies[0].current_cash, 100_000); assert_eq!(state.service_state.company_market_state[&24].bond_count, 1); + assert_eq!( + state.service_state.annual_bond_last_retired_principal_total, + 0 + ); + assert_eq!( + state.service_state.annual_bond_last_issued_principal_total, + 500_000 + ); assert_eq!( state.service_state.company_market_state[&24].largest_live_bond_principal, Some(500_000) @@ -3314,6 +3335,14 @@ mod tests { ); assert_eq!(state.companies[0].current_cash, 550_000); assert_eq!(state.companies[0].debt, 0); + assert_eq!( + state.service_state.annual_bond_last_retired_principal_total, + 350_000 + ); + assert_eq!( + state.service_state.annual_bond_last_issued_principal_total, + 0 + ); assert_eq!(state.service_state.company_market_state[&25].bond_count, 0); assert!( state.service_state.company_market_state[&25] @@ -3461,6 +3490,14 @@ mod tests { ); assert_eq!(state.companies[0].current_cash, 250_000); assert_eq!(state.companies[0].debt, 1_000_000); + assert_eq!( + state.service_state.annual_bond_last_retired_principal_total, + 350_000 + ); + assert_eq!( + state.service_state.annual_bond_last_issued_principal_total, + 1_000_000 + ); assert_eq!(state.service_state.company_market_state[&26].bond_count, 2); assert_eq!( state.service_state.company_market_state[&26].largest_live_bond_principal, diff --git a/crates/rrt-runtime/src/summary.rs b/crates/rrt-runtime/src/summary.rs index 2a46d05..bb2d4df 100644 --- a/crates/rrt-runtime/src/summary.rs +++ b/crates/rrt-runtime/src/summary.rs @@ -259,6 +259,8 @@ pub struct RuntimeSummary { pub periodic_boundary_call_count: u64, pub annual_finance_service_call_count: u64, pub annual_dividend_adjustment_commit_count: u64, + pub annual_bond_last_retired_principal_total: u64, + pub annual_bond_last_issued_principal_total: u64, pub total_trigger_dispatch_count: u64, pub dirty_rerun_count: u64, pub total_company_cash: i64, @@ -1381,6 +1383,12 @@ impl RuntimeSummary { annual_dividend_adjustment_commit_count: state .service_state .annual_dividend_adjustment_commit_count, + annual_bond_last_retired_principal_total: state + .service_state + .annual_bond_last_retired_principal_total, + annual_bond_last_issued_principal_total: state + .service_state + .annual_bond_last_issued_principal_total, total_trigger_dispatch_count: state .service_state .trigger_dispatch_counts diff --git a/docs/README.md b/docs/README.md index 6119f21..8e6bfcc 100644 --- a/docs/README.md +++ b/docs/README.md @@ -155,7 +155,9 @@ The highest-value next passes are now: the same live bond-slot owner surface now also carries save-native maturity years into annual bond policy summaries, derives the current live coupon burden directly from owned bond slots, and now also commits the shellless “repay matured live bonds, - compact the table, then issue the exact staged count” path during periodic service + compact the table, then issue the exact staged count” path during periodic service; the same + service surface now also carries the per-cycle retired-versus-issued principal totals that feed + the later debt-news family - the project rule on the remaining closure work is now explicit too: when one runtime-facing field is still ambiguous, prefer rehosting the owning source state or real reader/setter family first instead of guessing another derived leaf field from neighboring raw offsets diff --git a/docs/runtime-rehost-plan.md b/docs/runtime-rehost-plan.md index deceb0b..c2a3bb6 100644 --- a/docs/runtime-rehost-plan.md +++ b/docs/runtime-rehost-plan.md @@ -235,7 +235,8 @@ cash reader plus the first three trailing net-profit years instead of a parallel The annual bond lane now rides it as well, using the simulated post-repayment cash window plus the linked-transit threshold split to stage `500000` principal issue counts without shell ownership, and periodic boundary service now commits the same shellless matured-bond repay/compact/issue path instead of -stopping at the staging reader. +stopping at the staging reader. That same service seam now also carries the retired-versus-issued +principal totals needed by the later debt-news tail. The annual dividend-adjustment lane now rides that same seam too: the runtime now rehosts the shared year-or-control-transfer metric reader, the board-approved dividend ceiling helper, and the full annual dividend branch over owned cash, public float, current dividend, and building-growth