diff --git a/README.md b/README.md index 32f5afb..b651aaa 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,11 @@ selected-chairman scope, while wider chairman target scopes remain explicit pari chairman and governance condition batch is grounded too: selected-chairman cash / holdings / net worth / purchasing-power thresholds and company book-value-per-share thresholds now import through the normal event-service path, while wider chairman target scopes and the still-unpinned investor- -confidence / management-attitude condition ids remain explicit frontier. The first grounded +confidence / management-attitude condition ids remain explicit frontier. Checked-in save-slice +documents can now also carry explicit company rosters and chairman-profile tables, so the current +company-targeted and chairman-targeted descriptor and condition batches can execute from standalone +save-slice fixtures without overlay snapshots when that context is present; raw `.gms` inspection +still does not reconstruct those company/chairman collections automatically. The first grounded condition-side unlock now exists for negative-sentinel `raw_condition_id = -1` company scopes, and the first ordinary nonnegative condition batch now executes too: numeric-threshold company finance, company track, aggregate territory track, and company-territory track rows can import diff --git a/crates/rrt-cli/src/main.rs b/crates/rrt-cli/src/main.rs index 0c62b94..1bb8cf2 100644 --- a/crates/rrt-cli/src/main.rs +++ b/crates/rrt-cli/src/main.rs @@ -4487,8 +4487,20 @@ mod tests { .join("../../fixtures/runtime/packed-event-cargo-catalog-save-slice-fixture.json"); let chairman_cash_overlay_fixture = PathBuf::from(env!("CARGO_MANIFEST_DIR")) .join("../../fixtures/runtime/packed-event-chairman-cash-overlay-fixture.json"); + let chairman_cash_save_fixture = PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("../../fixtures/runtime/packed-event-chairman-cash-save-slice-fixture.json"); let deactivate_chairman_overlay_fixture = PathBuf::from(env!("CARGO_MANIFEST_DIR")) .join("../../fixtures/runtime/packed-event-deactivate-chairman-overlay-fixture.json"); + let deactivate_chairman_save_fixture = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join( + "../../fixtures/runtime/packed-event-deactivate-chairman-save-slice-fixture.json", + ); + let deactivate_company_save_fixture = PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("../../fixtures/runtime/packed-event-deactivate-company-save-slice-fixture.json"); + let track_capacity_save_fixture = PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("../../fixtures/runtime/packed-event-track-capacity-save-slice-fixture.json"); + let negative_company_scope_save_fixture = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join( + "../../fixtures/runtime/packed-event-negative-company-scope-save-slice-fixture.json", + ); let missing_chairman_context_fixture = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join( "../../fixtures/runtime/packed-event-chairman-missing-context-save-slice-fixture.json", ); @@ -4497,12 +4509,20 @@ mod tests { ); let chairman_condition_overlay_fixture = PathBuf::from(env!("CARGO_MANIFEST_DIR")) .join("../../fixtures/runtime/packed-event-chairman-condition-overlay-fixture.json"); + let chairman_condition_save_fixture = PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("../../fixtures/runtime/packed-event-chairman-condition-save-slice-fixture.json"); let company_governance_condition_overlay_fixture = PathBuf::from(env!( "CARGO_MANIFEST_DIR" )) .join( "../../fixtures/runtime/packed-event-company-governance-condition-overlay-fixture.json", ); + let company_governance_condition_save_fixture = PathBuf::from(env!( + "CARGO_MANIFEST_DIR" + )) + .join( + "../../fixtures/runtime/packed-event-company-governance-condition-save-slice-fixture.json", + ); run_runtime_summarize_fixture(&parity_fixture) .expect("save-slice-backed parity fixture should summarize"); @@ -4546,16 +4566,30 @@ mod tests { .expect("save-slice-backed cargo catalog fixture should summarize"); run_runtime_summarize_fixture(&chairman_cash_overlay_fixture) .expect("overlay-backed chairman-cash fixture should summarize"); + run_runtime_summarize_fixture(&chairman_cash_save_fixture) + .expect("save-slice-backed chairman-cash fixture should summarize"); run_runtime_summarize_fixture(&deactivate_chairman_overlay_fixture) .expect("overlay-backed deactivate-chairman fixture should summarize"); + run_runtime_summarize_fixture(&deactivate_chairman_save_fixture) + .expect("save-slice-backed deactivate-chairman fixture should summarize"); + run_runtime_summarize_fixture(&deactivate_company_save_fixture) + .expect("save-slice-backed deactivate-company fixture should summarize"); + run_runtime_summarize_fixture(&track_capacity_save_fixture) + .expect("save-slice-backed track-capacity fixture should summarize"); + run_runtime_summarize_fixture(&negative_company_scope_save_fixture) + .expect("save-slice-backed negative-sentinel company-scope fixture should summarize"); run_runtime_summarize_fixture(&missing_chairman_context_fixture) .expect("save-slice-backed chairman missing-context fixture should summarize"); run_runtime_summarize_fixture(&chairman_scope_parity_fixture) .expect("save-slice-backed chairman scope parity fixture should summarize"); run_runtime_summarize_fixture(&chairman_condition_overlay_fixture) .expect("overlay-backed chairman condition fixture should summarize"); + run_runtime_summarize_fixture(&chairman_condition_save_fixture) + .expect("save-slice-backed chairman condition fixture should summarize"); run_runtime_summarize_fixture(&company_governance_condition_overlay_fixture) .expect("overlay-backed company governance condition fixture should summarize"); + run_runtime_summarize_fixture(&company_governance_condition_save_fixture) + .expect("save-slice-backed company governance condition fixture should summarize"); } #[test] @@ -4583,6 +4617,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: None, notes: vec!["exported for test".to_string()], diff --git a/crates/rrt-fixtures/src/load.rs b/crates/rrt-fixtures/src/load.rs index c7bd9f6..0b3b8de 100644 --- a/crates/rrt-fixtures/src/load.rs +++ b/crates/rrt-fixtures/src/load.rs @@ -269,6 +269,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: None, notes: vec![], @@ -397,6 +399,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some( rrt_runtime::SmpLoadedEventRuntimeCollectionSummary { diff --git a/crates/rrt-runtime/src/import.rs b/crates/rrt-runtime/src/import.rs index 92b1eac..9bd6587 100644 --- a/crates/rrt-runtime/src/import.rs +++ b/crates/rrt-runtime/src/import.rs @@ -5,10 +5,10 @@ use serde::{Deserialize, Serialize}; use crate::persistence::{load_runtime_snapshot_document, validate_runtime_snapshot_document}; use crate::{ - CalendarPoint, RuntimeCargoCatalogEntry, RuntimeChairmanTarget, - RuntimeCompanyConditionTestScope, RuntimeCompanyControllerKind, RuntimeCompanyTarget, - RuntimeCondition, RuntimeEffect, RuntimeEventRecord, RuntimeEventRecordTemplate, - RuntimeLocomotiveCatalogEntry, RuntimePackedEventCollectionSummary, + CalendarPoint, RuntimeCargoCatalogEntry, RuntimeChairmanProfile, RuntimeChairmanTarget, + RuntimeCompany, RuntimeCompanyConditionTestScope, RuntimeCompanyControllerKind, + RuntimeCompanyTarget, RuntimeCondition, RuntimeEffect, RuntimeEventRecord, + RuntimeEventRecordTemplate, RuntimeLocomotiveCatalogEntry, RuntimePackedEventCollectionSummary, RuntimePackedEventCompactControlSummary, RuntimePackedEventConditionRowSummary, RuntimePackedEventGroupedEffectRowSummary, RuntimePackedEventNegativeSentinelScopeSummary, RuntimePackedEventRecordSummary, RuntimePackedEventTextBandSummary, @@ -94,6 +94,12 @@ struct SaveSliceProjection { metadata: BTreeMap, packed_event_collection: Option, event_runtime_records: Vec, + companies: Vec, + has_company_projection: bool, + selected_company_id: Option, + chairman_profiles: Vec, + has_chairman_projection: bool, + selected_chairman_profile_id: Option, candidate_availability: BTreeMap, named_locomotive_availability: BTreeMap, locomotive_catalog: Option>, @@ -253,12 +259,12 @@ pub fn project_save_slice_to_runtime_state_import( save_profile: projection.save_profile, world_restore: projection.world_restore, metadata: projection.metadata, - companies: Vec::new(), - selected_company_id: None, + companies: projection.companies, + selected_company_id: projection.selected_company_id, players: Vec::new(), selected_player_id: None, - chairman_profiles: Vec::new(), - selected_chairman_profile_id: None, + chairman_profiles: projection.chairman_profiles, + selected_chairman_profile_id: projection.selected_chairman_profile_id, trains: Vec::new(), locomotive_catalog: projection.locomotive_catalog.unwrap_or_default(), cargo_catalog: projection.cargo_catalog.unwrap_or_default(), @@ -318,12 +324,28 @@ pub fn project_save_slice_overlay_to_runtime_state_import( ..projection.world_restore }, metadata, - companies: base_state.companies.clone(), - selected_company_id: base_state.selected_company_id, + companies: if projection.has_company_projection { + projection.companies + } else { + base_state.companies.clone() + }, + selected_company_id: if projection.has_company_projection { + projection.selected_company_id + } else { + base_state.selected_company_id + }, players: base_state.players.clone(), selected_player_id: base_state.selected_player_id, - chairman_profiles: base_state.chairman_profiles.clone(), - selected_chairman_profile_id: base_state.selected_chairman_profile_id, + chairman_profiles: if projection.has_chairman_projection { + projection.chairman_profiles + } else { + base_state.chairman_profiles.clone() + }, + selected_chairman_profile_id: if projection.has_chairman_projection { + projection.selected_chairman_profile_id + } else { + base_state.selected_chairman_profile_id + }, trains: base_state.trains.clone(), locomotive_catalog: projection .locomotive_catalog @@ -756,10 +778,118 @@ fn project_save_slice_components( None }; + let (companies, has_company_projection, selected_company_id) = + if let Some(roster) = &save_slice.company_roster { + metadata.insert( + "save_slice.company_roster_source_kind".to_string(), + roster.source_kind.clone(), + ); + metadata.insert( + "save_slice.company_roster_semantic_family".to_string(), + roster.semantic_family.clone(), + ); + metadata.insert( + "save_slice.company_roster_entry_count".to_string(), + roster.observed_entry_count.to_string(), + ); + if let Some(selected_company_id) = roster.selected_company_id { + metadata.insert( + "save_slice.selected_company_id".to_string(), + selected_company_id.to_string(), + ); + } + ( + roster + .entries + .iter() + .map(|entry| RuntimeCompany { + company_id: entry.company_id, + current_cash: entry.current_cash, + debt: entry.debt, + credit_rating_score: entry.credit_rating_score, + prime_rate: entry.prime_rate, + active: entry.active, + available_track_laying_capacity: entry.available_track_laying_capacity, + controller_kind: entry.controller_kind, + linked_chairman_profile_id: entry.linked_chairman_profile_id, + book_value_per_share: entry.book_value_per_share, + investor_confidence: entry.investor_confidence, + management_attitude: entry.management_attitude, + takeover_cooldown_year: entry.takeover_cooldown_year, + merger_cooldown_year: entry.merger_cooldown_year, + track_piece_counts: entry.track_piece_counts, + }) + .collect::>(), + true, + roster.selected_company_id, + ) + } else { + (Vec::new(), false, None) + }; + + let (chairman_profiles, has_chairman_projection, selected_chairman_profile_id) = + if let Some(table) = &save_slice.chairman_profile_table { + metadata.insert( + "save_slice.chairman_profile_table_source_kind".to_string(), + table.source_kind.clone(), + ); + metadata.insert( + "save_slice.chairman_profile_table_semantic_family".to_string(), + table.semantic_family.clone(), + ); + metadata.insert( + "save_slice.chairman_profile_table_entry_count".to_string(), + table.observed_entry_count.to_string(), + ); + if let Some(selected_chairman_profile_id) = table.selected_chairman_profile_id { + metadata.insert( + "save_slice.selected_chairman_profile_id".to_string(), + selected_chairman_profile_id.to_string(), + ); + } + ( + table + .entries + .iter() + .map(|entry| RuntimeChairmanProfile { + profile_id: entry.profile_id, + name: entry.name.clone(), + active: entry.active, + current_cash: entry.current_cash, + linked_company_id: entry.linked_company_id, + company_holdings: entry.company_holdings.clone(), + holdings_value_total: entry.holdings_value_total, + net_worth_total: entry.net_worth_total, + purchasing_power_total: entry.purchasing_power_total, + }) + .collect::>(), + true, + table.selected_chairman_profile_id, + ) + } else { + (Vec::new(), false, None) + }; + let named_locomotive_cost = BTreeMap::new(); let cargo_production_overrides = BTreeMap::new(); let mut packed_event_context = company_context.clone(); + if has_company_projection { + packed_event_context.known_company_ids = + companies.iter().map(|company| company.company_id).collect(); + packed_event_context.selected_company_id = selected_company_id; + packed_event_context.has_complete_company_controller_context = !companies.is_empty() + && companies + .iter() + .all(|company| company.controller_kind != RuntimeCompanyControllerKind::Unknown); + } + if has_chairman_projection { + packed_event_context.known_chairman_profile_ids = chairman_profiles + .iter() + .map(|profile| profile.profile_id) + .collect(); + packed_event_context.selected_chairman_profile_id = selected_chairman_profile_id; + } if let Some(catalog) = &locomotive_catalog { packed_event_context.locomotive_catalog_names_by_id = catalog .iter() @@ -806,6 +936,12 @@ fn project_save_slice_components( metadata, packed_event_collection, event_runtime_records, + companies, + has_company_projection, + selected_company_id, + chairman_profiles, + has_chairman_projection, + selected_chairman_profile_id, candidate_availability, named_locomotive_availability, locomotive_catalog, @@ -3750,6 +3886,98 @@ mod tests { } } + fn save_company_roster() -> crate::SmpLoadedCompanyRoster { + crate::SmpLoadedCompanyRoster { + source_kind: "tracked-save-slice-company-roster".to_string(), + semantic_family: "save-slice-runtime-company-context".to_string(), + observed_entry_count: 2, + selected_company_id: Some(1), + entries: vec![ + crate::SmpLoadedCompanyRosterEntry { + company_id: 1, + active: true, + controller_kind: RuntimeCompanyControllerKind::Human, + current_cash: 150, + debt: 80, + credit_rating_score: Some(650), + prime_rate: Some(5), + available_track_laying_capacity: Some(6), + track_piece_counts: RuntimeTrackPieceCounts { + total: 20, + single: 5, + double: 8, + transition: 1, + electric: 3, + non_electric: 17, + }, + linked_chairman_profile_id: Some(1), + book_value_per_share: 2620, + investor_confidence: 37, + management_attitude: 58, + takeover_cooldown_year: Some(1839), + merger_cooldown_year: Some(1838), + }, + crate::SmpLoadedCompanyRosterEntry { + company_id: 2, + active: true, + controller_kind: RuntimeCompanyControllerKind::Ai, + current_cash: 90, + debt: 40, + credit_rating_score: Some(480), + prime_rate: Some(6), + available_track_laying_capacity: Some(2), + track_piece_counts: RuntimeTrackPieceCounts { + total: 8, + single: 2, + double: 2, + transition: 0, + electric: 1, + non_electric: 7, + }, + linked_chairman_profile_id: Some(2), + book_value_per_share: 1400, + investor_confidence: 22, + management_attitude: 31, + takeover_cooldown_year: None, + merger_cooldown_year: None, + }, + ], + } + } + + fn save_chairman_profile_table() -> crate::SmpLoadedChairmanProfileTable { + crate::SmpLoadedChairmanProfileTable { + source_kind: "tracked-save-slice-chairman-profile-table".to_string(), + semantic_family: "save-slice-runtime-chairman-context".to_string(), + observed_entry_count: 2, + selected_chairman_profile_id: Some(1), + entries: vec![ + crate::SmpLoadedChairmanProfileEntry { + profile_id: 1, + name: "Chairman One".to_string(), + active: true, + current_cash: 500, + linked_company_id: Some(1), + company_holdings: BTreeMap::from([(1, 1000)]), + holdings_value_total: 700, + net_worth_total: 1200, + purchasing_power_total: 1500, + }, + crate::SmpLoadedChairmanProfileEntry { + profile_id: 2, + name: "Chairman Two".to_string(), + active: true, + current_cash: 250, + linked_company_id: Some(2), + company_holdings: BTreeMap::from([(2, 900)]), + holdings_value_total: 600, + net_worth_total: 900, + purchasing_power_total: 1100, + }, + ], + } + } + fn real_cargo_production_row( descriptor_id: u32, value: i32, @@ -4032,6 +4260,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: None, notes: vec![], @@ -4073,6 +4303,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: None, notes: vec![], @@ -4192,6 +4424,8 @@ mod tests { (5, crate::RuntimeCargoClass::FarmMine), (9, crate::RuntimeCargoClass::Other), ])), + company_roster: None, + chairman_profile_table: None, special_conditions_table: Some(crate::SmpLoadedSpecialConditionsTable { source_kind: "save-fixed-special-conditions-range".to_string(), table_offset: 0x0d64, @@ -4504,6 +4738,116 @@ mod tests { assert!(import.state.event_runtime_records.is_empty()); } + #[test] + fn projects_company_and_chairman_context_from_save_slice() { + let save_slice = SmpLoadedSaveSlice { + file_extension_hint: Some("gms".to_string()), + container_profile_family: Some("rt3-classic-save-container-v1".to_string()), + mechanism_family: "classic-save-rehydrate-v1".to_string(), + mechanism_confidence: "grounded".to_string(), + trailer_family: None, + bridge_family: None, + profile: None, + candidate_availability_table: None, + named_locomotive_availability_table: None, + locomotive_catalog: None, + cargo_catalog: None, + company_roster: Some(save_company_roster()), + chairman_profile_table: Some(save_chairman_profile_table()), + special_conditions_table: None, + event_runtime_collection: None, + notes: vec![], + }; + + let import = project_save_slice_to_runtime_state_import( + &save_slice, + "save-native-company-chairman", + None, + ) + .expect("save slice should project"); + + assert_eq!(import.state.companies.len(), 2); + assert_eq!(import.state.selected_company_id, Some(1)); + assert_eq!(import.state.chairman_profiles.len(), 2); + assert_eq!(import.state.selected_chairman_profile_id, Some(1)); + assert_eq!(import.state.companies[0].book_value_per_share, 2620); + assert_eq!(import.state.chairman_profiles[0].current_cash, 500); + } + + #[test] + fn overlay_replaces_base_company_and_chairman_context_from_save_slice() { + let base_state = RuntimeState { + companies: vec![crate::RuntimeCompany { + company_id: 42, + current_cash: 5, + debt: 1, + credit_rating_score: None, + prime_rate: None, + active: true, + available_track_laying_capacity: Some(1), + controller_kind: RuntimeCompanyControllerKind::Unknown, + linked_chairman_profile_id: None, + book_value_per_share: 10, + investor_confidence: 0, + management_attitude: 0, + takeover_cooldown_year: None, + merger_cooldown_year: None, + track_piece_counts: RuntimeTrackPieceCounts::default(), + }], + selected_company_id: Some(42), + chairman_profiles: vec![crate::RuntimeChairmanProfile { + profile_id: 9, + name: "Base Chairman".to_string(), + active: true, + current_cash: 10, + linked_company_id: None, + company_holdings: BTreeMap::new(), + holdings_value_total: 0, + net_worth_total: 0, + purchasing_power_total: 0, + }], + selected_chairman_profile_id: Some(9), + territories: vec![crate::RuntimeTerritory { + territory_id: 7, + name: Some("Base Territory".to_string()), + track_piece_counts: RuntimeTrackPieceCounts::default(), + }], + ..state() + }; + let save_slice = SmpLoadedSaveSlice { + file_extension_hint: Some("gms".to_string()), + container_profile_family: Some("rt3-classic-save-container-v1".to_string()), + mechanism_family: "classic-save-rehydrate-v1".to_string(), + mechanism_confidence: "grounded".to_string(), + trailer_family: None, + bridge_family: None, + profile: None, + candidate_availability_table: None, + named_locomotive_availability_table: None, + locomotive_catalog: None, + cargo_catalog: None, + company_roster: Some(save_company_roster()), + chairman_profile_table: Some(save_chairman_profile_table()), + special_conditions_table: None, + event_runtime_collection: None, + notes: vec![], + }; + + let import = project_save_slice_overlay_to_runtime_state_import( + &base_state, + &save_slice, + "overlay-save-native-company-chairman", + None, + ) + .expect("overlay import should project"); + + assert_eq!(import.state.companies.len(), 2); + assert_eq!(import.state.selected_company_id, Some(1)); + assert_eq!(import.state.chairman_profiles.len(), 2); + assert_eq!(import.state.selected_chairman_profile_id, Some(1)); + assert_eq!(import.state.territories, base_state.territories); + } + #[test] fn projects_executable_packed_records_into_runtime_and_services_follow_on() { let save_slice = SmpLoadedSaveSlice { @@ -4522,6 +4866,8 @@ mod tests { (5, crate::RuntimeCargoClass::FarmMine), (9, crate::RuntimeCargoClass::Other), ])), + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -4642,6 +4988,8 @@ mod tests { (5, crate::RuntimeCargoClass::FarmMine), (9, crate::RuntimeCargoClass::Other), ])), + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -4740,6 +5088,8 @@ mod tests { (5, crate::RuntimeCargoClass::FarmMine), (9, crate::RuntimeCargoClass::Other), ])), + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -4864,6 +5214,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -4949,6 +5301,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -5102,6 +5456,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -5345,6 +5701,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -5423,6 +5781,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -5525,6 +5885,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -5600,6 +5962,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -5703,6 +6067,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -5781,6 +6147,8 @@ mod tests { named_locomotive_availability_table: Some(save_named_locomotive_table(112)), locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -5928,6 +6296,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -6031,6 +6401,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -6108,6 +6480,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -6185,6 +6559,8 @@ mod tests { named_locomotive_availability_table: Some(save_named_locomotive_table(112)), locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -6325,6 +6701,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -6421,6 +6799,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -6496,6 +6876,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -6581,6 +6963,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -6717,6 +7101,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -6872,6 +7258,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -6977,6 +7365,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -7063,6 +7453,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -7176,6 +7568,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -7283,6 +7677,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -7380,6 +7776,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -7473,6 +7871,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -7580,6 +7980,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -7672,6 +8074,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -7746,6 +8150,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -7825,6 +8231,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -7909,6 +8317,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -7993,6 +8403,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -8093,6 +8505,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -8184,6 +8598,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -8301,6 +8717,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -8436,6 +8854,8 @@ mod tests { (5, crate::RuntimeCargoClass::FarmMine), (9, crate::RuntimeCargoClass::Other), ])), + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -8953,6 +9373,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -9124,6 +9546,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -9252,6 +9676,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -9363,6 +9789,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -9549,6 +9977,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -9643,6 +10073,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -9739,6 +10171,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -9906,6 +10340,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -10056,6 +10492,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -10147,6 +10585,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -10271,6 +10711,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -10383,6 +10825,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -10539,6 +10983,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -10724,6 +11170,8 @@ mod tests { named_locomotive_availability_table: None, locomotive_catalog: None, cargo_catalog: None, + company_roster: None, + chairman_profile_table: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), diff --git a/crates/rrt-runtime/src/lib.rs b/crates/rrt-runtime/src/lib.rs index c16b2fc..2f457bf 100644 --- a/crates/rrt-runtime/src/lib.rs +++ b/crates/rrt-runtime/src/lib.rs @@ -55,11 +55,13 @@ pub use smp::{ SmpClassicRehydrateProfileProbe, SmpContainerProfile, SmpEarlyContentProbe, SmpHeaderVariantProbe, SmpInspectionReport, SmpKnownTagHit, SmpLoadedCandidateAvailabilityTable, SmpLoadedCargoCatalog, SmpLoadedCargoCatalogEntry, - SmpLoadedEventRuntimeCollectionSummary, SmpLoadedNamedLocomotiveAvailabilityTable, - SmpLoadedPackedEventCompactControlSummary, SmpLoadedPackedEventConditionRowSummary, - SmpLoadedPackedEventGroupedEffectRowSummary, SmpLoadedPackedEventNegativeSentinelScopeSummary, - SmpLoadedPackedEventRecordSummary, SmpLoadedPackedEventTextBandSummary, SmpLoadedProfile, - SmpLoadedSaveSlice, SmpLoadedSpecialConditionsTable, SmpLocomotivePolicyFieldObservation, + SmpLoadedChairmanProfileEntry, SmpLoadedChairmanProfileTable, SmpLoadedCompanyRoster, + SmpLoadedCompanyRosterEntry, SmpLoadedEventRuntimeCollectionSummary, + SmpLoadedNamedLocomotiveAvailabilityTable, SmpLoadedPackedEventCompactControlSummary, + SmpLoadedPackedEventConditionRowSummary, SmpLoadedPackedEventGroupedEffectRowSummary, + SmpLoadedPackedEventNegativeSentinelScopeSummary, SmpLoadedPackedEventRecordSummary, + SmpLoadedPackedEventTextBandSummary, SmpLoadedProfile, SmpLoadedSaveSlice, + SmpLoadedSpecialConditionsTable, SmpLocomotivePolicyFieldObservation, SmpLocomotivePolicyFloatAlignmentCandidate, SmpLocomotivePolicyNeighborhoodProbe, SmpPackedProfileWordLane, SmpPostSpecialConditionsScalarLane, SmpPostSpecialConditionsScalarProbe, SmpPostTextFieldNeighborhoodProbe, diff --git a/crates/rrt-runtime/src/smp.rs b/crates/rrt-runtime/src/smp.rs index 07f703d..1b4fb5b 100644 --- a/crates/rrt-runtime/src/smp.rs +++ b/crates/rrt-runtime/src/smp.rs @@ -8,10 +8,10 @@ use sha2::{Digest, Sha256}; use crate::{ RuntimeCargoClass, RuntimeChairmanMetric, RuntimeChairmanTarget, - RuntimeCompanyConditionTestScope, RuntimeCompanyMetric, RuntimeCompanyTarget, RuntimeCondition, - RuntimeConditionComparator, RuntimeEffect, RuntimeEventRecordTemplate, - RuntimePlayerConditionTestScope, RuntimePlayerTarget, RuntimeTerritoryMetric, - RuntimeTerritoryTarget, RuntimeTrackMetric, + RuntimeCompanyConditionTestScope, RuntimeCompanyControllerKind, RuntimeCompanyMetric, + RuntimeCompanyTarget, RuntimeCondition, RuntimeConditionComparator, RuntimeEffect, + RuntimeEventRecordTemplate, RuntimePlayerConditionTestScope, RuntimePlayerTarget, + RuntimeTerritoryMetric, RuntimeTerritoryTarget, RuntimeTrackMetric, RuntimeTrackPieceCounts, }; pub const SMP_FOUR_SIDECAR_BYTE_PLANES_MIN_BUNDLE_VERSION: u32 = 0x03ec; @@ -1773,6 +1773,75 @@ pub struct SmpLoadedCargoCatalog { pub entries: Vec, } +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct SmpLoadedCompanyRosterEntry { + pub company_id: u32, + pub active: bool, + #[serde(default)] + pub controller_kind: RuntimeCompanyControllerKind, + pub current_cash: i64, + pub debt: u64, + #[serde(default)] + pub credit_rating_score: Option, + #[serde(default)] + pub prime_rate: Option, + #[serde(default)] + pub available_track_laying_capacity: Option, + #[serde(default)] + pub track_piece_counts: RuntimeTrackPieceCounts, + #[serde(default)] + pub linked_chairman_profile_id: Option, + #[serde(default)] + pub book_value_per_share: i64, + #[serde(default)] + pub investor_confidence: i64, + #[serde(default)] + pub management_attitude: i64, + #[serde(default)] + pub takeover_cooldown_year: Option, + #[serde(default)] + pub merger_cooldown_year: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct SmpLoadedCompanyRoster { + pub source_kind: String, + pub semantic_family: String, + pub observed_entry_count: usize, + #[serde(default)] + pub selected_company_id: Option, + pub entries: Vec, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct SmpLoadedChairmanProfileEntry { + pub profile_id: u32, + pub name: String, + pub active: bool, + #[serde(default)] + pub current_cash: i64, + #[serde(default)] + pub linked_company_id: Option, + #[serde(default)] + pub company_holdings: BTreeMap, + #[serde(default)] + pub holdings_value_total: i64, + #[serde(default)] + pub net_worth_total: i64, + #[serde(default)] + pub purchasing_power_total: i64, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct SmpLoadedChairmanProfileTable { + pub source_kind: String, + pub semantic_family: String, + pub observed_entry_count: usize, + #[serde(default)] + pub selected_chairman_profile_id: Option, + pub entries: Vec, +} + #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct SmpLoadedSpecialConditionsTable { pub source_kind: String, @@ -1969,6 +2038,10 @@ pub struct SmpLoadedSaveSlice { pub locomotive_catalog: Option, #[serde(default)] pub cargo_catalog: Option, + #[serde(default)] + pub company_roster: Option, + #[serde(default)] + pub chairman_profile_table: Option, pub special_conditions_table: Option, pub event_runtime_collection: Option, pub notes: Vec, @@ -2162,6 +2235,8 @@ pub fn load_save_slice_from_report( named_locomotive_availability_table, locomotive_catalog, cargo_catalog, + company_roster: None, + chairman_profile_table: None, special_conditions_table, event_runtime_collection: report.event_runtime_collection_summary.clone(), notes: summary.notes.clone(), diff --git a/docs/README.md b/docs/README.md index bb2858d..22ff281 100644 --- a/docs/README.md +++ b/docs/README.md @@ -76,7 +76,7 @@ The highest-value next passes are now: - preserve the atlas and function map as the source of subsystem boundaries while continuing to avoid shell-first implementation bets - keep using overlay imports as the context bridge when selectively executable packed rows still - need live company state that save slices do not persist + need runtime context that current save slices and raw save inspection do not yet persist - treat broader real grouped-descriptor recovery as the active packed-event frontier now that the first company-scoped batch already parses, summarizes, and executes through the ordinary runtime path when overlay context resolves its symbolic company scope: descriptor `2` `Company Cash`, @@ -92,6 +92,10 @@ The highest-value next passes are now: the first grounded company governance condition family now executes too via book-value-per-share thresholds; wider chairman target ordinals and the still-unpinned investor-confidence / management-attitude condition ids remain frontier +- checked-in save-slice documents can now carry explicit company rosters and chairman profile + tables too, so the current company-targeted and chairman-targeted descriptor/condition batches + can execute from standalone save-slice fixtures without overlay snapshots when that context is + present; raw `.gms` inspection/export still does not reconstruct those company/chairman surfaces - widen real packed-event executable coverage descriptor by descriptor after identity, target mask, and normalized effect semantics are all grounded, not just after row framing is parsed - the first grounded condition-side unlock now exists for negative-sentinel `raw_condition_id = -1` @@ -156,6 +160,9 @@ The highest-value next passes are now: gates - cargo slot classification is now checked in and save-native too, so the remaining cargo frontier is broader descriptor/condition breadth rather than classification or save/import plumbing +- the company/chairman frontier has moved too: checked-in save-slice documents can now carry that + context natively, so the next work on that axis is broader recovery and eventual raw save + reconstruction rather than overlay-only ownership - keep in mind that the current local `.gms` corpus still exports with no packed event collection, so real descriptor mapping needs to stay plumbing-first until better captures exist - use `rrt-hook` primarily as optional capture or integration tooling, not as the first execution diff --git a/docs/runtime-rehost-plan.md b/docs/runtime-rehost-plan.md index 9a6607b..de1a789 100644 --- a/docs/runtime-rehost-plan.md +++ b/docs/runtime-rehost-plan.md @@ -53,6 +53,12 @@ Implemented today: purchasing-power thresholds plus company book-value-per-share thresholds; wider chairman target ordinals and the still-unpinned investor-confidence / management-attitude condition ids remain parity frontier +- checked-in save-slice documents can now carry explicit company rosters and chairman profile + tables too, and runtime projection/import will seed or replace company/chairman context from + those save-owned surfaces; that lets the currently supported company-targeted and + chairman-targeted descriptor/condition batches execute from standalone save-slice fixtures + without overlay snapshots when the checked-in documents include that context, while raw `.gms` + inspection/export still leaves those company/chairman surfaces absent - a minimal event-owned train surface and an opaque economic-status lane now exist in runtime state, and real descriptors `8` = `Economic Status`, `9` = `Confiscate All`, and `15` = `Retire Train` now import and execute through the ordinary runtime path when overlay context @@ -125,9 +131,10 @@ That means the next implementation work is breadth, not bootstrap. The recommend broader real grouped-descriptor and ordinary condition-id coverage beyond the current access, whole-game toggle, train, player, chairman selected-scope grouped effects, grounded chairman/governance conditions, numeric-threshold, named locomotive availability, named locomotive -cost, world scalar override, and world-scalar condition batches. Richer runtime ownership should -still be added only where a later descriptor or condition family needs more than the current -event-owned roster. +cost, world scalar override, and world-scalar condition batches, plus eventual raw save +reconstruction for company/chairman context once stronger evidence exists. Richer runtime ownership +should still be added only where a later descriptor or condition family needs more than the +current event-owned roster. ## Why This Boundary diff --git a/fixtures/runtime/packed-event-chairman-cash-context-save-slice.json b/fixtures/runtime/packed-event-chairman-cash-context-save-slice.json new file mode 100644 index 0000000..38482de --- /dev/null +++ b/fixtures/runtime/packed-event-chairman-cash-context-save-slice.json @@ -0,0 +1,222 @@ +{ + "format_version": 1, + "save_slice_id": "packed-event-chairman-cash-save-slice", + "source": { + "description": "Tracked save-slice document with a chairman-targeted Player Cash row using the hidden grouped target-subject lane.", + "original_save_filename": "captured-chairman-cash.gms", + "original_save_sha256": "chairman-cash-sample-sha256", + "notes": [ + "tracked as JSON save-slice document rather than raw .smp", + "proves selected-chairman descriptor import through the normal runtime path" + ] + }, + "save_slice": { + "file_extension_hint": "gms", + "container_profile_family": "rt3-classic-save-container-v1", + "mechanism_family": "classic-save-rehydrate-v1", + "mechanism_confidence": "grounded", + "trailer_family": null, + "bridge_family": null, + "profile": null, + "candidate_availability_table": null, + "special_conditions_table": null, + "event_runtime_collection": { + "source_kind": "packed-event-runtime-collection", + "mechanism_family": "classic-save-rehydrate-v1", + "mechanism_confidence": "grounded", + "container_profile_family": "rt3-classic-save-container-v1", + "metadata_tag_offset": 28928, + "records_tag_offset": 29184, + "close_tag_offset": 29696, + "packed_state_version": 1001, + "packed_state_version_hex": "0x000003e9", + "live_id_bound": 61, + "live_record_count": 1, + "live_entry_ids": [ + 61 + ], + "decoded_record_count": 1, + "imported_runtime_record_count": 1, + "records": [ + { + "record_index": 0, + "live_entry_id": 61, + "payload_offset": 29296, + "payload_len": 140, + "decode_status": "parity_only", + "payload_family": "real_packed_v1", + "trigger_kind": 6, + "one_shot": false, + "compact_control": { + "mode_byte_0x7ef": 6, + "primary_selector_0x7f0": 12, + "grouped_mode_0x7f4": 2, + "one_shot_header_0x7f5": 0, + "modifier_flag_0x7f9": 0, + "modifier_flag_0x7fa": 0, + "grouped_target_scope_ordinals_0x7fb": [ + 1, + 1, + 1, + 1 + ], + "grouped_scope_checkboxes_0x7ff": [ + 2, + 0, + 0, + 0 + ], + "summary_toggle_0x800": 1, + "grouped_territory_selectors_0x80f": [ + -1, + -1, + -1, + -1 + ] + }, + "text_bands": [], + "standalone_condition_row_count": 0, + "standalone_condition_rows": [], + "grouped_effect_row_counts": [ + 1, + 0, + 0, + 0 + ], + "grouped_effect_rows": [ + { + "group_index": 0, + "row_index": 0, + "descriptor_id": 1, + "descriptor_label": "Player Cash", + "target_mask_bits": 2, + "parameter_family": "player_cash_scalar", + "grouped_target_subject": "chairman", + "opcode": 8, + "raw_scalar_value": 999, + "value_byte_0x09": 0, + "value_dword_0x0d": 0, + "value_byte_0x11": 0, + "value_byte_0x12": 0, + "value_word_0x14": 0, + "value_word_0x16": 0, + "row_shape": "multivalue_scalar", + "semantic_family": "multivalue_scalar", + "semantic_preview": "Set Player Cash to 999 with aux [0, 0, 0, 0]", + "locomotive_name": null, + "notes": [] + } + ], + "decoded_conditions": [], + "decoded_actions": [ + { + "kind": "set_chairman_cash", + "target": { + "kind": "selected_chairman" + }, + "value": 999 + } + ], + "executable_import_ready": true, + "notes": [ + "decoded from grounded real 0x4e9a row framing", + "hidden grouped target-subject lane resolves descriptor 1 to selected chairman scope" + ] + } + ] + }, + "notes": [ + "real chairman-targeted cash descriptor sample" + ], + "company_roster": { + "source_kind": "tracked-save-slice-company-roster", + "semantic_family": "save-slice-runtime-company-context", + "observed_entry_count": 2, + "selected_company_id": 1, + "entries": [ + { + "company_id": 1, + "active": true, + "controller_kind": "human", + "current_cash": 150, + "debt": 80, + "credit_rating_score": 650, + "prime_rate": 5, + "available_track_laying_capacity": 6, + "track_piece_counts": { + "total": 20, + "single": 5, + "double": 8, + "transition": 1, + "electric": 3, + "non_electric": 17 + }, + "linked_chairman_profile_id": 1, + "book_value_per_share": 2620, + "investor_confidence": 37, + "management_attitude": 58, + "takeover_cooldown_year": 1839, + "merger_cooldown_year": 1838 + }, + { + "company_id": 2, + "active": true, + "controller_kind": "ai", + "current_cash": 90, + "debt": 40, + "credit_rating_score": 480, + "prime_rate": 6, + "available_track_laying_capacity": 2, + "track_piece_counts": { + "total": 8, + "single": 2, + "double": 2, + "transition": 0, + "electric": 1, + "non_electric": 7 + }, + "linked_chairman_profile_id": 2, + "book_value_per_share": 1400, + "investor_confidence": 22, + "management_attitude": 31, + "takeover_cooldown_year": null, + "merger_cooldown_year": null + } + ] + }, + "chairman_profile_table": { + "source_kind": "tracked-save-slice-chairman-profile-table", + "semantic_family": "save-slice-runtime-chairman-context", + "observed_entry_count": 2, + "selected_chairman_profile_id": 1, + "entries": [ + { + "profile_id": 1, + "name": "Chairman One", + "active": true, + "current_cash": 500, + "linked_company_id": 1, + "company_holdings": { + "1": 1000 + }, + "holdings_value_total": 700, + "net_worth_total": 1200, + "purchasing_power_total": 1500 + }, + { + "profile_id": 2, + "name": "Chairman Two", + "active": true, + "current_cash": 250, + "linked_company_id": 2, + "company_holdings": { + "2": 900 + }, + "holdings_value_total": 600, + "net_worth_total": 900, + "purchasing_power_total": 1100 + } + ] + } + } +} diff --git a/fixtures/runtime/packed-event-chairman-cash-save-slice-fixture.json b/fixtures/runtime/packed-event-chairman-cash-save-slice-fixture.json new file mode 100644 index 0000000..9a43d5c --- /dev/null +++ b/fixtures/runtime/packed-event-chairman-cash-save-slice-fixture.json @@ -0,0 +1,49 @@ +{ + "format_version": 1, + "fixture_id": "packed-event-chairman-cash-save-slice-fixture", + "source": { + "kind": "captured-runtime", + "description": "Fixture proving descriptor 1 executes on selected-chairman scope from save-slice-backed context." + }, + "state_save_slice_path": "packed-event-chairman-cash-context-save-slice.json", + "commands": [ + { + "kind": "service_trigger_kind", + "trigger_kind": 6 + } + ], + "expected_summary": { + "calendar_projection_source": "default-1830-placeholder", + "calendar_projection_is_placeholder": true, + "company_count": 2, + "chairman_profile_count": 2, + "active_chairman_profile_count": 2, + "selected_chairman_profile_id": 1, + "packed_event_collection_present": true, + "packed_event_record_count": 1, + "packed_event_decoded_record_count": 1, + "packed_event_imported_runtime_record_count": 1, + "event_runtime_record_count": 1, + "total_event_record_service_count": 1, + "total_trigger_dispatch_count": 1 + }, + "expected_state_fragment": { + "chairman_profiles": [ + { + "profile_id": 1, + "current_cash": 999 + }, + { + "profile_id": 2, + "current_cash": 250 + } + ], + "packed_event_collection": { + "records": [ + { + "import_outcome": "imported" + } + ] + } + } +} diff --git a/fixtures/runtime/packed-event-chairman-cash-save-slice.json b/fixtures/runtime/packed-event-chairman-cash-save-slice.json index a01ec9b..20db81a 100644 --- a/fixtures/runtime/packed-event-chairman-cash-save-slice.json +++ b/fixtures/runtime/packed-event-chairman-cash-save-slice.json @@ -32,7 +32,9 @@ "packed_state_version_hex": "0x000003e9", "live_id_bound": 61, "live_record_count": 1, - "live_entry_ids": [61], + "live_entry_ids": [ + 61 + ], "decoded_record_count": 1, "imported_runtime_record_count": 1, "records": [ @@ -52,15 +54,35 @@ "one_shot_header_0x7f5": 0, "modifier_flag_0x7f9": 0, "modifier_flag_0x7fa": 0, - "grouped_target_scope_ordinals_0x7fb": [1, 1, 1, 1], - "grouped_scope_checkboxes_0x7ff": [2, 0, 0, 0], + "grouped_target_scope_ordinals_0x7fb": [ + 1, + 1, + 1, + 1 + ], + "grouped_scope_checkboxes_0x7ff": [ + 2, + 0, + 0, + 0 + ], "summary_toggle_0x800": 1, - "grouped_territory_selectors_0x80f": [-1, -1, -1, -1] + "grouped_territory_selectors_0x80f": [ + -1, + -1, + -1, + -1 + ] }, "text_bands": [], "standalone_condition_row_count": 0, "standalone_condition_rows": [], - "grouped_effect_row_counts": [1, 0, 0, 0], + "grouped_effect_row_counts": [ + 1, + 0, + 0, + 0 + ], "grouped_effect_rows": [ { "group_index": 0, diff --git a/fixtures/runtime/packed-event-chairman-condition-context-save-slice.json b/fixtures/runtime/packed-event-chairman-condition-context-save-slice.json new file mode 100644 index 0000000..0360038 --- /dev/null +++ b/fixtures/runtime/packed-event-chairman-condition-context-save-slice.json @@ -0,0 +1,280 @@ +{ + "format_version": 1, + "save_slice_id": "packed-event-chairman-condition-save-slice", + "source": { + "description": "Tracked save-slice document proving grounded chairman metric conditions import and execute through selected-chairman context.", + "original_save_filename": "captured-chairman-condition.gms", + "original_save_sha256": "chairman-condition-sample-sha256", + "notes": [ + "tracked as JSON save-slice document rather than raw .smp", + "pins the first grounded chairman ordinary-condition family" + ] + }, + "save_slice": { + "file_extension_hint": "gms", + "container_profile_family": "rt3-classic-save-container-v1", + "mechanism_family": "classic-save-rehydrate-v1", + "mechanism_confidence": "grounded", + "trailer_family": null, + "bridge_family": null, + "profile": null, + "candidate_availability_table": null, + "named_locomotive_availability_table": null, + "cargo_catalog": null, + "special_conditions_table": null, + "event_runtime_collection": { + "source_kind": "packed-event-runtime-collection", + "mechanism_family": "classic-save-rehydrate-v1", + "mechanism_confidence": "grounded", + "container_profile_family": "rt3-classic-save-container-v1", + "metadata_tag_offset": 28928, + "records_tag_offset": 29184, + "close_tag_offset": 29696, + "packed_state_version": 1001, + "packed_state_version_hex": "0x000003e9", + "live_id_bound": 71, + "live_record_count": 1, + "live_entry_ids": [ + 71 + ], + "decoded_record_count": 1, + "imported_runtime_record_count": 0, + "records": [ + { + "record_index": 0, + "live_entry_id": 71, + "payload_offset": 29186, + "payload_len": 136, + "decode_status": "executable", + "payload_family": "real_packed_v1", + "trigger_kind": 6, + "active": null, + "marks_collection_dirty": null, + "one_shot": false, + "compact_control": { + "mode_byte_0x7ef": 6, + "primary_selector_0x7f0": 99, + "grouped_mode_0x7f4": 2, + "one_shot_header_0x7f5": 1, + "modifier_flag_0x7f9": 1, + "modifier_flag_0x7fa": 0, + "grouped_target_scope_ordinals_0x7fb": [ + 0, + 1, + 2, + 3 + ], + "grouped_scope_checkboxes_0x7ff": [ + 1, + 0, + 1, + 0 + ], + "summary_toggle_0x800": 1, + "grouped_territory_selectors_0x80f": [ + -1, + 10, + -1, + 22 + ] + }, + "text_bands": [], + "standalone_condition_row_count": 1, + "standalone_condition_rows": [ + { + "row_index": 0, + "raw_condition_id": 2218, + "subtype": 4, + "flag_bytes": [ + 244, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "candidate_name": null, + "comparator": "eq", + "metric": "Player Cash", + "semantic_family": "numeric_threshold", + "semantic_preview": "Test Player Cash == 500", + "requires_candidate_name_binding": false, + "notes": [] + } + ], + "negative_sentinel_scope": { + "company_test_scope": "disabled", + "player_test_scope": "selected_player_only", + "territory_scope_selector_is_0x63": false, + "source_row_indexes": [ + 0 + ] + }, + "grouped_effect_row_counts": [ + 1, + 0, + 0, + 0 + ], + "grouped_effect_rows": [ + { + "group_index": 0, + "row_index": 0, + "descriptor_id": 110, + "descriptor_label": "Disable Stock Buying and Selling", + "target_mask_bits": 8, + "parameter_family": "world_flag_toggle", + "opcode": 0, + "raw_scalar_value": 1, + "value_byte_0x09": 0, + "value_dword_0x0d": 0, + "value_byte_0x11": 0, + "value_byte_0x12": 0, + "value_word_0x14": 0, + "value_word_0x16": 0, + "row_shape": "bool_toggle", + "semantic_family": "bool_toggle", + "semantic_preview": "Set Disable Stock Buying and Selling to TRUE", + "locomotive_name": null, + "notes": [] + } + ], + "decoded_conditions": [ + { + "kind": "chairman_numeric_threshold", + "target": { + "kind": "selected_chairman" + }, + "metric": "current_cash", + "comparator": "eq", + "value": 500 + } + ], + "decoded_actions": [ + { + "kind": "set_world_flag", + "key": "world.chairman_condition_imported", + "value": true + } + ], + "executable_import_ready": true, + "notes": [ + "chairman metric condition gates a world-side effect" + ] + } + ] + }, + "notes": [ + "real chairman ordinary-condition sample" + ], + "company_roster": { + "source_kind": "tracked-save-slice-company-roster", + "semantic_family": "save-slice-runtime-company-context", + "observed_entry_count": 2, + "selected_company_id": 1, + "entries": [ + { + "company_id": 1, + "active": true, + "controller_kind": "human", + "current_cash": 150, + "debt": 80, + "credit_rating_score": 650, + "prime_rate": 5, + "available_track_laying_capacity": 6, + "track_piece_counts": { + "total": 20, + "single": 5, + "double": 8, + "transition": 1, + "electric": 3, + "non_electric": 17 + }, + "linked_chairman_profile_id": 1, + "book_value_per_share": 2620, + "investor_confidence": 37, + "management_attitude": 58, + "takeover_cooldown_year": 1839, + "merger_cooldown_year": 1838 + }, + { + "company_id": 2, + "active": true, + "controller_kind": "ai", + "current_cash": 90, + "debt": 40, + "credit_rating_score": 480, + "prime_rate": 6, + "available_track_laying_capacity": 2, + "track_piece_counts": { + "total": 8, + "single": 2, + "double": 2, + "transition": 0, + "electric": 1, + "non_electric": 7 + }, + "linked_chairman_profile_id": 2, + "book_value_per_share": 1400, + "investor_confidence": 22, + "management_attitude": 31, + "takeover_cooldown_year": null, + "merger_cooldown_year": null + } + ] + }, + "chairman_profile_table": { + "source_kind": "tracked-save-slice-chairman-profile-table", + "semantic_family": "save-slice-runtime-chairman-context", + "observed_entry_count": 2, + "selected_chairman_profile_id": 1, + "entries": [ + { + "profile_id": 1, + "name": "Chairman One", + "active": true, + "current_cash": 500, + "linked_company_id": 1, + "company_holdings": { + "1": 1000 + }, + "holdings_value_total": 700, + "net_worth_total": 1200, + "purchasing_power_total": 1500 + }, + { + "profile_id": 2, + "name": "Chairman Two", + "active": true, + "current_cash": 250, + "linked_company_id": 2, + "company_holdings": { + "2": 900 + }, + "holdings_value_total": 600, + "net_worth_total": 900, + "purchasing_power_total": 1100 + } + ] + } + } +} diff --git a/fixtures/runtime/packed-event-chairman-condition-save-slice-fixture.json b/fixtures/runtime/packed-event-chairman-condition-save-slice-fixture.json new file mode 100644 index 0000000..51ee1b3 --- /dev/null +++ b/fixtures/runtime/packed-event-chairman-condition-save-slice-fixture.json @@ -0,0 +1,45 @@ +{ + "format_version": 1, + "fixture_id": "packed-event-chairman-condition-save-slice-fixture", + "source": { + "kind": "captured-runtime", + "description": "Fixture proving grounded chairman metric conditions import and execute from save-slice-backed context." + }, + "state_save_slice_path": "packed-event-chairman-condition-context-save-slice.json", + "commands": [ + { + "kind": "service_trigger_kind", + "trigger_kind": 6 + } + ], + "expected_summary": { + "calendar_projection_source": "default-1830-placeholder", + "calendar_projection_is_placeholder": true, + "company_count": 2, + "chairman_profile_count": 2, + "active_chairman_profile_count": 2, + "selected_chairman_profile_id": 1, + "linked_chairman_company_count": 2, + "company_takeover_cooldown_count": 1, + "company_merger_cooldown_count": 1, + "packed_event_collection_present": true, + "packed_event_record_count": 1, + "packed_event_decoded_record_count": 1, + "packed_event_imported_runtime_record_count": 1, + "event_runtime_record_count": 1, + "total_event_record_service_count": 1, + "total_trigger_dispatch_count": 1 + }, + "expected_state_fragment": { + "world_flags": { + "world.chairman_condition_imported": true + }, + "packed_event_collection": { + "records": [ + { + "import_outcome": "imported" + } + ] + } + } +} diff --git a/fixtures/runtime/packed-event-company-governance-condition-context-save-slice.json b/fixtures/runtime/packed-event-company-governance-condition-context-save-slice.json new file mode 100644 index 0000000..6b82c31 --- /dev/null +++ b/fixtures/runtime/packed-event-company-governance-condition-context-save-slice.json @@ -0,0 +1,280 @@ +{ + "format_version": 1, + "save_slice_id": "packed-event-company-governance-condition-save-slice", + "source": { + "description": "Tracked save-slice document proving grounded company governance conditions import and execute.", + "original_save_filename": "captured-company-governance-condition.gms", + "original_save_sha256": "company-governance-condition-sample-sha256", + "notes": [ + "tracked as JSON save-slice document rather than raw .smp", + "pins the first grounded company control-transfer condition family" + ] + }, + "save_slice": { + "file_extension_hint": "gms", + "container_profile_family": "rt3-classic-save-container-v1", + "mechanism_family": "classic-save-rehydrate-v1", + "mechanism_confidence": "grounded", + "trailer_family": null, + "bridge_family": null, + "profile": null, + "candidate_availability_table": null, + "named_locomotive_availability_table": null, + "cargo_catalog": null, + "special_conditions_table": null, + "event_runtime_collection": { + "source_kind": "packed-event-runtime-collection", + "mechanism_family": "classic-save-rehydrate-v1", + "mechanism_confidence": "grounded", + "container_profile_family": "rt3-classic-save-container-v1", + "metadata_tag_offset": 28928, + "records_tag_offset": 29184, + "close_tag_offset": 29696, + "packed_state_version": 1001, + "packed_state_version_hex": "0x000003e9", + "live_id_bound": 72, + "live_record_count": 1, + "live_entry_ids": [ + 72 + ], + "decoded_record_count": 1, + "imported_runtime_record_count": 0, + "records": [ + { + "record_index": 0, + "live_entry_id": 72, + "payload_offset": 29186, + "payload_len": 136, + "decode_status": "executable", + "payload_family": "real_packed_v1", + "trigger_kind": 7, + "active": null, + "marks_collection_dirty": null, + "one_shot": false, + "compact_control": { + "mode_byte_0x7ef": 6, + "primary_selector_0x7f0": 99, + "grouped_mode_0x7f4": 2, + "one_shot_header_0x7f5": 1, + "modifier_flag_0x7f9": 1, + "modifier_flag_0x7fa": 0, + "grouped_target_scope_ordinals_0x7fb": [ + 0, + 1, + 2, + 3 + ], + "grouped_scope_checkboxes_0x7ff": [ + 1, + 0, + 1, + 0 + ], + "summary_toggle_0x800": 1, + "grouped_territory_selectors_0x80f": [ + -1, + 10, + -1, + 22 + ] + }, + "text_bands": [], + "standalone_condition_row_count": 1, + "standalone_condition_rows": [ + { + "row_index": 0, + "raw_condition_id": 2620, + "subtype": 4, + "flag_bytes": [ + 60, + 10, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "candidate_name": null, + "comparator": "eq", + "metric": "Book Value Per Share", + "semantic_family": "numeric_threshold", + "semantic_preview": "Test Book Value Per Share == 2620", + "requires_candidate_name_binding": false, + "notes": [] + } + ], + "negative_sentinel_scope": { + "company_test_scope": "selected_company_only", + "player_test_scope": "disabled", + "territory_scope_selector_is_0x63": false, + "source_row_indexes": [ + 0 + ] + }, + "grouped_effect_row_counts": [ + 1, + 0, + 0, + 0 + ], + "grouped_effect_rows": [ + { + "group_index": 0, + "row_index": 0, + "descriptor_id": 110, + "descriptor_label": "Disable Stock Buying and Selling", + "target_mask_bits": 8, + "parameter_family": "world_flag_toggle", + "opcode": 0, + "raw_scalar_value": 1, + "value_byte_0x09": 0, + "value_dword_0x0d": 0, + "value_byte_0x11": 0, + "value_byte_0x12": 0, + "value_word_0x14": 0, + "value_word_0x16": 0, + "row_shape": "bool_toggle", + "semantic_family": "bool_toggle", + "semantic_preview": "Set Disable Stock Buying and Selling to TRUE", + "locomotive_name": null, + "notes": [] + } + ], + "decoded_conditions": [ + { + "kind": "company_numeric_threshold", + "target": { + "kind": "condition_true_company" + }, + "metric": "book_value_per_share", + "comparator": "eq", + "value": 2620 + } + ], + "decoded_actions": [ + { + "kind": "set_world_flag", + "key": "world.book_value_condition_imported", + "value": true + } + ], + "executable_import_ready": true, + "notes": [ + "book value per share condition gates a world-side effect" + ] + } + ] + }, + "notes": [ + "real company-governance ordinary-condition sample" + ], + "company_roster": { + "source_kind": "tracked-save-slice-company-roster", + "semantic_family": "save-slice-runtime-company-context", + "observed_entry_count": 2, + "selected_company_id": 1, + "entries": [ + { + "company_id": 1, + "active": true, + "controller_kind": "human", + "current_cash": 150, + "debt": 80, + "credit_rating_score": 650, + "prime_rate": 5, + "available_track_laying_capacity": 6, + "track_piece_counts": { + "total": 20, + "single": 5, + "double": 8, + "transition": 1, + "electric": 3, + "non_electric": 17 + }, + "linked_chairman_profile_id": 1, + "book_value_per_share": 2620, + "investor_confidence": 37, + "management_attitude": 58, + "takeover_cooldown_year": 1839, + "merger_cooldown_year": 1838 + }, + { + "company_id": 2, + "active": true, + "controller_kind": "ai", + "current_cash": 90, + "debt": 40, + "credit_rating_score": 480, + "prime_rate": 6, + "available_track_laying_capacity": 2, + "track_piece_counts": { + "total": 8, + "single": 2, + "double": 2, + "transition": 0, + "electric": 1, + "non_electric": 7 + }, + "linked_chairman_profile_id": 2, + "book_value_per_share": 1400, + "investor_confidence": 22, + "management_attitude": 31, + "takeover_cooldown_year": null, + "merger_cooldown_year": null + } + ] + }, + "chairman_profile_table": { + "source_kind": "tracked-save-slice-chairman-profile-table", + "semantic_family": "save-slice-runtime-chairman-context", + "observed_entry_count": 2, + "selected_chairman_profile_id": 1, + "entries": [ + { + "profile_id": 1, + "name": "Chairman One", + "active": true, + "current_cash": 500, + "linked_company_id": 1, + "company_holdings": { + "1": 1000 + }, + "holdings_value_total": 700, + "net_worth_total": 1200, + "purchasing_power_total": 1500 + }, + { + "profile_id": 2, + "name": "Chairman Two", + "active": true, + "current_cash": 250, + "linked_company_id": 2, + "company_holdings": { + "2": 900 + }, + "holdings_value_total": 600, + "net_worth_total": 900, + "purchasing_power_total": 1100 + } + ] + } + } +} diff --git a/fixtures/runtime/packed-event-company-governance-condition-save-slice-fixture.json b/fixtures/runtime/packed-event-company-governance-condition-save-slice-fixture.json new file mode 100644 index 0000000..9e5fb57 --- /dev/null +++ b/fixtures/runtime/packed-event-company-governance-condition-save-slice-fixture.json @@ -0,0 +1,51 @@ +{ + "format_version": 1, + "fixture_id": "packed-event-company-governance-condition-save-slice-fixture", + "source": { + "kind": "captured-runtime", + "description": "Fixture proving grounded company governance conditions import and execute from save-slice-backed context." + }, + "state_save_slice_path": "packed-event-company-governance-condition-context-save-slice.json", + "commands": [ + { + "kind": "service_trigger_kind", + "trigger_kind": 7 + } + ], + "expected_summary": { + "calendar_projection_source": "default-1830-placeholder", + "calendar_projection_is_placeholder": true, + "company_count": 2, + "chairman_profile_count": 2, + "active_chairman_profile_count": 2, + "selected_chairman_profile_id": 1, + "linked_chairman_company_count": 2, + "company_takeover_cooldown_count": 1, + "company_merger_cooldown_count": 1, + "packed_event_collection_present": true, + "packed_event_record_count": 1, + "packed_event_decoded_record_count": 1, + "packed_event_imported_runtime_record_count": 1, + "event_runtime_record_count": 1, + "total_event_record_service_count": 1, + "total_trigger_dispatch_count": 1 + }, + "expected_state_fragment": { + "world_flags": { + "world.book_value_condition_imported": true + }, + "packed_event_collection": { + "records": [ + { + "import_outcome": "imported" + } + ] + }, + "event_runtime_records": [ + { + "record_id": 72, + "service_count": 1 + } + ] + } +} diff --git a/fixtures/runtime/packed-event-deactivate-chairman-context-save-slice.json b/fixtures/runtime/packed-event-deactivate-chairman-context-save-slice.json new file mode 100644 index 0000000..be8f501 --- /dev/null +++ b/fixtures/runtime/packed-event-deactivate-chairman-context-save-slice.json @@ -0,0 +1,221 @@ +{ + "format_version": 1, + "save_slice_id": "packed-event-deactivate-chairman-save-slice", + "source": { + "description": "Tracked save-slice document with a chairman-targeted Deactivate Player row using the hidden grouped target-subject lane.", + "original_save_filename": "captured-deactivate-chairman.gms", + "original_save_sha256": "deactivate-chairman-sample-sha256", + "notes": [ + "tracked as JSON save-slice document rather than raw .smp", + "proves selected-chairman lifecycle import through the normal runtime path" + ] + }, + "save_slice": { + "file_extension_hint": "gms", + "container_profile_family": "rt3-classic-save-container-v1", + "mechanism_family": "classic-save-rehydrate-v1", + "mechanism_confidence": "grounded", + "trailer_family": null, + "bridge_family": null, + "profile": null, + "candidate_availability_table": null, + "special_conditions_table": null, + "event_runtime_collection": { + "source_kind": "packed-event-runtime-collection", + "mechanism_family": "classic-save-rehydrate-v1", + "mechanism_confidence": "grounded", + "container_profile_family": "rt3-classic-save-container-v1", + "metadata_tag_offset": 28928, + "records_tag_offset": 29184, + "close_tag_offset": 29696, + "packed_state_version": 1001, + "packed_state_version_hex": "0x000003e9", + "live_id_bound": 62, + "live_record_count": 1, + "live_entry_ids": [ + 62 + ], + "decoded_record_count": 1, + "imported_runtime_record_count": 1, + "records": [ + { + "record_index": 0, + "live_entry_id": 62, + "payload_offset": 29296, + "payload_len": 140, + "decode_status": "parity_only", + "payload_family": "real_packed_v1", + "trigger_kind": 6, + "one_shot": false, + "compact_control": { + "mode_byte_0x7ef": 6, + "primary_selector_0x7f0": 12, + "grouped_mode_0x7f4": 2, + "one_shot_header_0x7f5": 0, + "modifier_flag_0x7f9": 0, + "modifier_flag_0x7fa": 0, + "grouped_target_scope_ordinals_0x7fb": [ + 1, + 1, + 1, + 1 + ], + "grouped_scope_checkboxes_0x7ff": [ + 2, + 0, + 0, + 0 + ], + "summary_toggle_0x800": 1, + "grouped_territory_selectors_0x80f": [ + -1, + -1, + -1, + -1 + ] + }, + "text_bands": [], + "standalone_condition_row_count": 0, + "standalone_condition_rows": [], + "grouped_effect_row_counts": [ + 1, + 0, + 0, + 0 + ], + "grouped_effect_rows": [ + { + "group_index": 0, + "row_index": 0, + "descriptor_id": 14, + "descriptor_label": "Deactivate Player", + "target_mask_bits": 2, + "parameter_family": "player_lifecycle_toggle", + "grouped_target_subject": "chairman", + "opcode": 1, + "raw_scalar_value": 1, + "value_byte_0x09": 0, + "value_dword_0x0d": 0, + "value_byte_0x11": 0, + "value_byte_0x12": 0, + "value_word_0x14": 0, + "value_word_0x16": 0, + "row_shape": "bool_toggle", + "semantic_family": "bool_toggle", + "semantic_preview": "Set Deactivate Player to TRUE", + "locomotive_name": null, + "notes": [] + } + ], + "decoded_conditions": [], + "decoded_actions": [ + { + "kind": "deactivate_chairman", + "target": { + "kind": "selected_chairman" + } + } + ], + "executable_import_ready": true, + "notes": [ + "decoded from grounded real 0x4e9a row framing", + "hidden grouped target-subject lane resolves descriptor 14 to selected chairman scope" + ] + } + ] + }, + "notes": [ + "real chairman-targeted lifecycle descriptor sample" + ], + "company_roster": { + "source_kind": "tracked-save-slice-company-roster", + "semantic_family": "save-slice-runtime-company-context", + "observed_entry_count": 2, + "selected_company_id": 1, + "entries": [ + { + "company_id": 1, + "active": true, + "controller_kind": "human", + "current_cash": 150, + "debt": 80, + "credit_rating_score": 650, + "prime_rate": 5, + "available_track_laying_capacity": 6, + "track_piece_counts": { + "total": 20, + "single": 5, + "double": 8, + "transition": 1, + "electric": 3, + "non_electric": 17 + }, + "linked_chairman_profile_id": 1, + "book_value_per_share": 2620, + "investor_confidence": 37, + "management_attitude": 58, + "takeover_cooldown_year": 1839, + "merger_cooldown_year": 1838 + }, + { + "company_id": 2, + "active": true, + "controller_kind": "ai", + "current_cash": 90, + "debt": 40, + "credit_rating_score": 480, + "prime_rate": 6, + "available_track_laying_capacity": 2, + "track_piece_counts": { + "total": 8, + "single": 2, + "double": 2, + "transition": 0, + "electric": 1, + "non_electric": 7 + }, + "linked_chairman_profile_id": 2, + "book_value_per_share": 1400, + "investor_confidence": 22, + "management_attitude": 31, + "takeover_cooldown_year": null, + "merger_cooldown_year": null + } + ] + }, + "chairman_profile_table": { + "source_kind": "tracked-save-slice-chairman-profile-table", + "semantic_family": "save-slice-runtime-chairman-context", + "observed_entry_count": 2, + "selected_chairman_profile_id": 1, + "entries": [ + { + "profile_id": 1, + "name": "Chairman One", + "active": true, + "current_cash": 500, + "linked_company_id": 1, + "company_holdings": { + "1": 1000 + }, + "holdings_value_total": 700, + "net_worth_total": 1200, + "purchasing_power_total": 1500 + }, + { + "profile_id": 2, + "name": "Chairman Two", + "active": true, + "current_cash": 250, + "linked_company_id": 2, + "company_holdings": { + "2": 900 + }, + "holdings_value_total": 600, + "net_worth_total": 900, + "purchasing_power_total": 1100 + } + ] + } + } +} diff --git a/fixtures/runtime/packed-event-deactivate-chairman-save-slice-fixture.json b/fixtures/runtime/packed-event-deactivate-chairman-save-slice-fixture.json new file mode 100644 index 0000000..fdc27aa --- /dev/null +++ b/fixtures/runtime/packed-event-deactivate-chairman-save-slice-fixture.json @@ -0,0 +1,61 @@ +{ + "format_version": 1, + "fixture_id": "packed-event-deactivate-chairman-save-slice-fixture", + "source": { + "kind": "captured-runtime", + "description": "Fixture proving descriptor 14 executes on selected-chairman scope from save-slice-backed context." + }, + "state_save_slice_path": "packed-event-deactivate-chairman-context-save-slice.json", + "commands": [ + { + "kind": "service_trigger_kind", + "trigger_kind": 6 + } + ], + "expected_summary": { + "calendar_projection_source": "default-1830-placeholder", + "calendar_projection_is_placeholder": true, + "company_count": 2, + "chairman_profile_count": 2, + "active_chairman_profile_count": 1, + "packed_event_collection_present": true, + "packed_event_record_count": 1, + "packed_event_decoded_record_count": 1, + "packed_event_imported_runtime_record_count": 1, + "event_runtime_record_count": 1, + "total_event_record_service_count": 1, + "total_trigger_dispatch_count": 1 + }, + "expected_state_fragment": { + "selected_chairman_profile_id": null, + "companies": [ + { + "company_id": 1, + "linked_chairman_profile_id": null + }, + { + "company_id": 2, + "linked_chairman_profile_id": 2 + } + ], + "chairman_profiles": [ + { + "profile_id": 1, + "active": false, + "linked_company_id": null + }, + { + "profile_id": 2, + "active": true, + "linked_company_id": 2 + } + ], + "packed_event_collection": { + "records": [ + { + "import_outcome": "imported" + } + ] + } + } +} diff --git a/fixtures/runtime/packed-event-deactivate-chairman-save-slice.json b/fixtures/runtime/packed-event-deactivate-chairman-save-slice.json index 566a266..6cd233f 100644 --- a/fixtures/runtime/packed-event-deactivate-chairman-save-slice.json +++ b/fixtures/runtime/packed-event-deactivate-chairman-save-slice.json @@ -32,7 +32,9 @@ "packed_state_version_hex": "0x000003e9", "live_id_bound": 62, "live_record_count": 1, - "live_entry_ids": [62], + "live_entry_ids": [ + 62 + ], "decoded_record_count": 1, "imported_runtime_record_count": 1, "records": [ @@ -52,15 +54,35 @@ "one_shot_header_0x7f5": 0, "modifier_flag_0x7f9": 0, "modifier_flag_0x7fa": 0, - "grouped_target_scope_ordinals_0x7fb": [1, 1, 1, 1], - "grouped_scope_checkboxes_0x7ff": [2, 0, 0, 0], + "grouped_target_scope_ordinals_0x7fb": [ + 1, + 1, + 1, + 1 + ], + "grouped_scope_checkboxes_0x7ff": [ + 2, + 0, + 0, + 0 + ], "summary_toggle_0x800": 1, - "grouped_territory_selectors_0x80f": [-1, -1, -1, -1] + "grouped_territory_selectors_0x80f": [ + -1, + -1, + -1, + -1 + ] }, "text_bands": [], "standalone_condition_row_count": 0, "standalone_condition_rows": [], - "grouped_effect_row_counts": [1, 0, 0, 0], + "grouped_effect_row_counts": [ + 1, + 0, + 0, + 0 + ], "grouped_effect_rows": [ { "group_index": 0, diff --git a/fixtures/runtime/packed-event-deactivate-company-context-save-slice.json b/fixtures/runtime/packed-event-deactivate-company-context-save-slice.json new file mode 100644 index 0000000..44e5720 --- /dev/null +++ b/fixtures/runtime/packed-event-deactivate-company-context-save-slice.json @@ -0,0 +1,218 @@ +{ + "format_version": 1, + "save_slice_id": "packed-event-deactivate-company-save-slice", + "source": { + "description": "Tracked save-slice document with a real packed-event row for Deactivate Company.", + "original_save_filename": "captured-deactivate-company.gms", + "original_save_sha256": "deactivate-company-sample-sha256", + "notes": [ + "tracked as JSON save-slice document rather than raw .smp", + "locks executable import for real descriptor 13" + ] + }, + "save_slice": { + "file_extension_hint": "gms", + "container_profile_family": "rt3-classic-save-container-v1", + "mechanism_family": "classic-save-rehydrate-v1", + "mechanism_confidence": "grounded", + "trailer_family": null, + "bridge_family": null, + "profile": null, + "candidate_availability_table": null, + "special_conditions_table": null, + "event_runtime_collection": { + "source_kind": "packed-event-runtime-collection", + "mechanism_family": "classic-save-rehydrate-v1", + "mechanism_confidence": "grounded", + "container_profile_family": "rt3-classic-save-container-v1", + "metadata_tag_offset": 28928, + "records_tag_offset": 29184, + "close_tag_offset": 29696, + "packed_state_version": 1001, + "packed_state_version_hex": "0x000003e9", + "live_id_bound": 31, + "live_record_count": 1, + "live_entry_ids": [ + 31 + ], + "decoded_record_count": 1, + "imported_runtime_record_count": 1, + "records": [ + { + "record_index": 0, + "live_entry_id": 31, + "payload_offset": 29186, + "payload_len": 120, + "decode_status": "parity_only", + "payload_family": "real_packed_v1", + "trigger_kind": 7, + "one_shot": false, + "compact_control": { + "mode_byte_0x7ef": 7, + "primary_selector_0x7f0": 99, + "grouped_mode_0x7f4": 2, + "one_shot_header_0x7f5": 0, + "modifier_flag_0x7f9": 1, + "modifier_flag_0x7fa": 0, + "grouped_target_scope_ordinals_0x7fb": [ + 1, + 1, + 1, + 1 + ], + "grouped_scope_checkboxes_0x7ff": [ + 1, + 0, + 0, + 0 + ], + "summary_toggle_0x800": 1, + "grouped_territory_selectors_0x80f": [ + -1, + -1, + -1, + -1 + ] + }, + "text_bands": [], + "standalone_condition_row_count": 0, + "standalone_condition_rows": [], + "grouped_effect_row_counts": [ + 1, + 0, + 0, + 0 + ], + "grouped_effect_rows": [ + { + "group_index": 0, + "row_index": 0, + "descriptor_id": 13, + "descriptor_label": "Deactivate Company", + "target_mask_bits": 1, + "parameter_family": "company_lifecycle_toggle", + "opcode": 1, + "raw_scalar_value": 1, + "value_byte_0x09": 0, + "value_dword_0x0d": 0, + "value_byte_0x11": 0, + "value_byte_0x12": 0, + "value_word_0x14": 0, + "value_word_0x16": 0, + "row_shape": "bool_toggle", + "semantic_family": "bool_toggle", + "semantic_preview": "Set Deactivate Company to TRUE", + "locomotive_name": null, + "notes": [] + } + ], + "decoded_actions": [ + { + "kind": "deactivate_company", + "target": { + "kind": "selected_company" + } + } + ], + "executable_import_ready": true, + "notes": [ + "decoded from grounded real 0x4e9a row framing" + ] + } + ] + }, + "notes": [ + "real descriptor 13 sample" + ], + "company_roster": { + "source_kind": "tracked-save-slice-company-roster", + "semantic_family": "save-slice-runtime-company-context", + "observed_entry_count": 2, + "selected_company_id": 1, + "entries": [ + { + "company_id": 1, + "active": true, + "controller_kind": "human", + "current_cash": 150, + "debt": 80, + "credit_rating_score": 650, + "prime_rate": 5, + "available_track_laying_capacity": 6, + "track_piece_counts": { + "total": 20, + "single": 5, + "double": 8, + "transition": 1, + "electric": 3, + "non_electric": 17 + }, + "linked_chairman_profile_id": 1, + "book_value_per_share": 2620, + "investor_confidence": 37, + "management_attitude": 58, + "takeover_cooldown_year": 1839, + "merger_cooldown_year": 1838 + }, + { + "company_id": 2, + "active": true, + "controller_kind": "ai", + "current_cash": 90, + "debt": 40, + "credit_rating_score": 480, + "prime_rate": 6, + "available_track_laying_capacity": 2, + "track_piece_counts": { + "total": 8, + "single": 2, + "double": 2, + "transition": 0, + "electric": 1, + "non_electric": 7 + }, + "linked_chairman_profile_id": 2, + "book_value_per_share": 1400, + "investor_confidence": 22, + "management_attitude": 31, + "takeover_cooldown_year": null, + "merger_cooldown_year": null + } + ] + }, + "chairman_profile_table": { + "source_kind": "tracked-save-slice-chairman-profile-table", + "semantic_family": "save-slice-runtime-chairman-context", + "observed_entry_count": 2, + "selected_chairman_profile_id": 1, + "entries": [ + { + "profile_id": 1, + "name": "Chairman One", + "active": true, + "current_cash": 500, + "linked_company_id": 1, + "company_holdings": { + "1": 1000 + }, + "holdings_value_total": 700, + "net_worth_total": 1200, + "purchasing_power_total": 1500 + }, + { + "profile_id": 2, + "name": "Chairman Two", + "active": true, + "current_cash": 250, + "linked_company_id": 2, + "company_holdings": { + "2": 900 + }, + "holdings_value_total": 600, + "net_worth_total": 900, + "purchasing_power_total": 1100 + } + ] + } + } +} diff --git a/fixtures/runtime/packed-event-deactivate-company-save-slice-fixture.json b/fixtures/runtime/packed-event-deactivate-company-save-slice-fixture.json new file mode 100644 index 0000000..1c3f824 --- /dev/null +++ b/fixtures/runtime/packed-event-deactivate-company-save-slice-fixture.json @@ -0,0 +1,55 @@ +{ + "format_version": 1, + "fixture_id": "packed-event-deactivate-company-save-slice-fixture", + "source": { + "kind": "captured-runtime", + "description": "Fixture proving descriptor 13 executes from save-slice-backed company context." + }, + "state_save_slice_path": "packed-event-deactivate-company-context-save-slice.json", + "commands": [ + { + "kind": "service_trigger_kind", + "trigger_kind": 7 + } + ], + "expected_summary": { + "calendar_projection_source": "default-1830-placeholder", + "calendar_projection_is_placeholder": true, + "company_count": 2, + "active_company_count": 1, + "chairman_profile_count": 2, + "packed_event_collection_present": true, + "packed_event_record_count": 1, + "packed_event_decoded_record_count": 1, + "packed_event_imported_runtime_record_count": 1, + "event_runtime_record_count": 1, + "total_event_record_service_count": 1, + "total_trigger_dispatch_count": 1 + }, + "expected_state_fragment": { + "selected_company_id": null, + "companies": [ + { + "company_id": 1, + "active": false + }, + { + "company_id": 2, + "active": true + } + ], + "packed_event_collection": { + "records": [ + { + "import_outcome": "imported" + } + ] + }, + "event_runtime_records": [ + { + "record_id": 31, + "service_count": 1 + } + ] + } +} diff --git a/fixtures/runtime/packed-event-deactivate-company-save-slice.json b/fixtures/runtime/packed-event-deactivate-company-save-slice.json index 818aa5d..49bc040 100644 --- a/fixtures/runtime/packed-event-deactivate-company-save-slice.json +++ b/fixtures/runtime/packed-event-deactivate-company-save-slice.json @@ -32,7 +32,9 @@ "packed_state_version_hex": "0x000003e9", "live_id_bound": 31, "live_record_count": 1, - "live_entry_ids": [31], + "live_entry_ids": [ + 31 + ], "decoded_record_count": 1, "imported_runtime_record_count": 1, "records": [ @@ -52,15 +54,35 @@ "one_shot_header_0x7f5": 0, "modifier_flag_0x7f9": 1, "modifier_flag_0x7fa": 0, - "grouped_target_scope_ordinals_0x7fb": [1, 1, 1, 1], - "grouped_scope_checkboxes_0x7ff": [1, 0, 0, 0], + "grouped_target_scope_ordinals_0x7fb": [ + 1, + 1, + 1, + 1 + ], + "grouped_scope_checkboxes_0x7ff": [ + 1, + 0, + 0, + 0 + ], "summary_toggle_0x800": 1, - "grouped_territory_selectors_0x80f": [-1, -1, -1, -1] + "grouped_territory_selectors_0x80f": [ + -1, + -1, + -1, + -1 + ] }, "text_bands": [], "standalone_condition_row_count": 0, "standalone_condition_rows": [], - "grouped_effect_row_counts": [1, 0, 0, 0], + "grouped_effect_row_counts": [ + 1, + 0, + 0, + 0 + ], "grouped_effect_rows": [ { "group_index": 0, diff --git a/fixtures/runtime/packed-event-negative-company-scope-context-save-slice.json b/fixtures/runtime/packed-event-negative-company-scope-context-save-slice.json new file mode 100644 index 0000000..bfb1bf1 --- /dev/null +++ b/fixtures/runtime/packed-event-negative-company-scope-context-save-slice.json @@ -0,0 +1,305 @@ +{ + "format_version": 1, + "save_slice_id": "packed-event-negative-company-scope-save-slice", + "source": { + "description": "Tracked save-slice document with a real packed Company Cash row unlocked by negative-sentinel company scope.", + "original_save_filename": "captured-negative-company-scope.gms", + "original_save_sha256": "negative-company-scope-sample-sha256", + "notes": [ + "tracked as JSON save-slice document rather than raw .smp", + "proves the first executable real negative-sentinel company-scope path" + ] + }, + "save_slice": { + "file_extension_hint": "gms", + "container_profile_family": "rt3-classic-save-container-v1", + "mechanism_family": "classic-save-rehydrate-v1", + "mechanism_confidence": "grounded", + "trailer_family": null, + "bridge_family": null, + "profile": null, + "candidate_availability_table": null, + "special_conditions_table": null, + "event_runtime_collection": { + "source_kind": "packed-event-runtime-collection", + "mechanism_family": "classic-save-rehydrate-v1", + "mechanism_confidence": "grounded", + "container_profile_family": "rt3-classic-save-container-v1", + "metadata_tag_offset": 28928, + "records_tag_offset": 29184, + "close_tag_offset": 29696, + "packed_state_version": 1001, + "packed_state_version_hex": "0x000003e9", + "live_id_bound": 9, + "live_record_count": 1, + "live_entry_ids": [ + 9 + ], + "decoded_record_count": 1, + "imported_runtime_record_count": 1, + "records": [ + { + "record_index": 0, + "live_entry_id": 9, + "payload_offset": 29290, + "payload_len": 109, + "decode_status": "parity_only", + "payload_family": "real_packed_v1", + "trigger_kind": 6, + "one_shot": false, + "compact_control": { + "mode_byte_0x7ef": 6, + "primary_selector_0x7f0": 42, + "grouped_mode_0x7f4": 2, + "one_shot_header_0x7f5": 0, + "modifier_flag_0x7f9": 2, + "modifier_flag_0x7fa": 0, + "grouped_target_scope_ordinals_0x7fb": [ + 0, + 1, + 2, + 3 + ], + "grouped_scope_checkboxes_0x7ff": [ + 1, + 0, + 1, + 0 + ], + "summary_toggle_0x800": 1, + "grouped_territory_selectors_0x80f": [ + -1, + 10, + -1, + 22 + ] + }, + "text_bands": [ + { + "label": "primary_text_band", + "packed_len": 8, + "present": true, + "preview": "Resolve!" + }, + { + "label": "secondary_text_band_0", + "packed_len": 0, + "present": false, + "preview": "" + }, + { + "label": "secondary_text_band_1", + "packed_len": 0, + "present": false, + "preview": "" + }, + { + "label": "secondary_text_band_2", + "packed_len": 0, + "present": false, + "preview": "" + }, + { + "label": "secondary_text_band_3", + "packed_len": 0, + "present": false, + "preview": "" + }, + { + "label": "secondary_text_band_4", + "packed_len": 0, + "present": false, + "preview": "" + } + ], + "standalone_condition_row_count": 1, + "standalone_condition_rows": [ + { + "row_index": 0, + "raw_condition_id": -1, + "subtype": 4, + "flag_bytes": [ + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72 + ], + "candidate_name": "AutoPlant", + "notes": [ + "negative sentinel-style condition row id", + "condition row carries candidate-name side string" + ] + } + ], + "negative_sentinel_scope": { + "company_test_scope": "selected_company_only", + "player_test_scope": "disabled", + "territory_scope_selector_is_0x63": false, + "source_row_indexes": [ + 0 + ] + }, + "grouped_effect_row_counts": [ + 1, + 0, + 0, + 0 + ], + "grouped_effect_rows": [ + { + "group_index": 0, + "row_index": 0, + "descriptor_id": 2, + "descriptor_label": "Company Cash", + "target_mask_bits": 1, + "parameter_family": "company_finance_scalar", + "opcode": 8, + "raw_scalar_value": 250, + "value_byte_0x09": 1, + "value_dword_0x0d": 12, + "value_byte_0x11": 2, + "value_byte_0x12": 3, + "value_word_0x14": 24, + "value_word_0x16": 36, + "row_shape": "multivalue_scalar", + "semantic_family": "multivalue_scalar", + "semantic_preview": "Set Company Cash to 250 with aux [2, 3, 24, 36]", + "locomotive_name": "Mikado", + "notes": [ + "grouped effect row carries locomotive-name side string" + ] + } + ], + "decoded_actions": [ + { + "kind": "set_company_cash", + "target": { + "kind": "condition_true_company" + }, + "value": 250 + } + ], + "executable_import_ready": true, + "notes": [ + "decoded from grounded real 0x4e9a row framing", + "negative-sentinel company scope lowers the condition-relative target at import time" + ] + } + ] + }, + "notes": [ + "real negative-sentinel company-scope sample" + ], + "company_roster": { + "source_kind": "tracked-save-slice-company-roster", + "semantic_family": "save-slice-runtime-company-context", + "observed_entry_count": 2, + "selected_company_id": 1, + "entries": [ + { + "company_id": 1, + "active": true, + "controller_kind": "human", + "current_cash": 150, + "debt": 80, + "credit_rating_score": 650, + "prime_rate": 5, + "available_track_laying_capacity": 6, + "track_piece_counts": { + "total": 20, + "single": 5, + "double": 8, + "transition": 1, + "electric": 3, + "non_electric": 17 + }, + "linked_chairman_profile_id": 1, + "book_value_per_share": 2620, + "investor_confidence": 37, + "management_attitude": 58, + "takeover_cooldown_year": 1839, + "merger_cooldown_year": 1838 + }, + { + "company_id": 2, + "active": true, + "controller_kind": "ai", + "current_cash": 90, + "debt": 40, + "credit_rating_score": 480, + "prime_rate": 6, + "available_track_laying_capacity": 2, + "track_piece_counts": { + "total": 8, + "single": 2, + "double": 2, + "transition": 0, + "electric": 1, + "non_electric": 7 + }, + "linked_chairman_profile_id": 2, + "book_value_per_share": 1400, + "investor_confidence": 22, + "management_attitude": 31, + "takeover_cooldown_year": null, + "merger_cooldown_year": null + } + ] + }, + "chairman_profile_table": { + "source_kind": "tracked-save-slice-chairman-profile-table", + "semantic_family": "save-slice-runtime-chairman-context", + "observed_entry_count": 2, + "selected_chairman_profile_id": 1, + "entries": [ + { + "profile_id": 1, + "name": "Chairman One", + "active": true, + "current_cash": 500, + "linked_company_id": 1, + "company_holdings": { + "1": 1000 + }, + "holdings_value_total": 700, + "net_worth_total": 1200, + "purchasing_power_total": 1500 + }, + { + "profile_id": 2, + "name": "Chairman Two", + "active": true, + "current_cash": 250, + "linked_company_id": 2, + "company_holdings": { + "2": 900 + }, + "holdings_value_total": 600, + "net_worth_total": 900, + "purchasing_power_total": 1100 + } + ] + } + } +} diff --git a/fixtures/runtime/packed-event-negative-company-scope-save-slice-fixture.json b/fixtures/runtime/packed-event-negative-company-scope-save-slice-fixture.json new file mode 100644 index 0000000..1ae8af4 --- /dev/null +++ b/fixtures/runtime/packed-event-negative-company-scope-save-slice-fixture.json @@ -0,0 +1,54 @@ +{ + "format_version": 1, + "fixture_id": "packed-event-negative-company-scope-save-slice-fixture", + "source": { + "kind": "captured-runtime", + "description": "Fixture proving real negative-sentinel company cash import executes from save-slice-backed company context." + }, + "state_save_slice_path": "packed-event-negative-company-scope-context-save-slice.json", + "commands": [ + { + "kind": "service_trigger_kind", + "trigger_kind": 6 + } + ], + "expected_summary": { + "calendar_projection_source": "default-1830-placeholder", + "calendar_projection_is_placeholder": true, + "company_count": 2, + "active_company_count": 2, + "chairman_profile_count": 2, + "packed_event_collection_present": true, + "packed_event_record_count": 1, + "packed_event_decoded_record_count": 1, + "packed_event_imported_runtime_record_count": 1, + "event_runtime_record_count": 1, + "total_event_record_service_count": 1, + "total_trigger_dispatch_count": 1 + }, + "expected_state_fragment": { + "companies": [ + { + "company_id": 1, + "current_cash": 250 + }, + { + "company_id": 2, + "current_cash": 90 + } + ], + "packed_event_collection": { + "records": [ + { + "import_outcome": "imported" + } + ] + }, + "event_runtime_records": [ + { + "record_id": 9, + "service_count": 1 + } + ] + } +} diff --git a/fixtures/runtime/packed-event-negative-company-scope-save-slice.json b/fixtures/runtime/packed-event-negative-company-scope-save-slice.json index 63fcc78..8583e93 100644 --- a/fixtures/runtime/packed-event-negative-company-scope-save-slice.json +++ b/fixtures/runtime/packed-event-negative-company-scope-save-slice.json @@ -32,7 +32,9 @@ "packed_state_version_hex": "0x000003e9", "live_id_bound": 9, "live_record_count": 1, - "live_entry_ids": [9], + "live_entry_ids": [ + 9 + ], "decoded_record_count": 1, "imported_runtime_record_count": 1, "records": [ @@ -52,10 +54,25 @@ "one_shot_header_0x7f5": 0, "modifier_flag_0x7f9": 2, "modifier_flag_0x7fa": 0, - "grouped_target_scope_ordinals_0x7fb": [0, 1, 2, 3], - "grouped_scope_checkboxes_0x7ff": [1, 0, 1, 0], + "grouped_target_scope_ordinals_0x7fb": [ + 0, + 1, + 2, + 3 + ], + "grouped_scope_checkboxes_0x7ff": [ + 1, + 0, + 1, + 0 + ], "summary_toggle_0x800": 1, - "grouped_territory_selectors_0x80f": [-1, 10, -1, 22] + "grouped_territory_selectors_0x80f": [ + -1, + 10, + -1, + 22 + ] }, "text_bands": [ { @@ -102,9 +119,31 @@ "raw_condition_id": -1, "subtype": 4, "flag_bytes": [ - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, - 68, 69, 70, 71, 72 + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72 ], "candidate_name": "AutoPlant", "notes": [ @@ -117,9 +156,16 @@ "company_test_scope": "selected_company_only", "player_test_scope": "disabled", "territory_scope_selector_is_0x63": false, - "source_row_indexes": [0] + "source_row_indexes": [ + 0 + ] }, - "grouped_effect_row_counts": [1, 0, 0, 0], + "grouped_effect_row_counts": [ + 1, + 0, + 0, + 0 + ], "grouped_effect_rows": [ { "group_index": 0, diff --git a/fixtures/runtime/packed-event-ordinary-company-finance-context-save-slice.json b/fixtures/runtime/packed-event-ordinary-company-finance-context-save-slice.json new file mode 100644 index 0000000..c69fb36 --- /dev/null +++ b/fixtures/runtime/packed-event-ordinary-company-finance-context-save-slice.json @@ -0,0 +1,279 @@ +{ + "format_version": 1, + "save_slice_id": "packed-event-ordinary-company-finance-save-slice", + "source": { + "description": "Tracked save-slice document with a real ordinary company-finance threshold row gating Company Cash.", + "original_save_filename": "captured-ordinary-company-finance.gms", + "original_save_sha256": "ordinary-company-finance-sample-sha256", + "notes": [ + "tracked as JSON save-slice document rather than raw .smp", + "proves ordinary Current Cash threshold import through the real packed-event path" + ] + }, + "save_slice": { + "file_extension_hint": "gms", + "container_profile_family": "rt3-classic-save-container-v1", + "mechanism_family": "classic-save-rehydrate-v1", + "mechanism_confidence": "grounded", + "trailer_family": null, + "bridge_family": null, + "profile": null, + "candidate_availability_table": null, + "special_conditions_table": null, + "event_runtime_collection": { + "source_kind": "packed-event-runtime-collection", + "mechanism_family": "classic-save-rehydrate-v1", + "mechanism_confidence": "grounded", + "container_profile_family": "rt3-classic-save-container-v1", + "metadata_tag_offset": 28928, + "records_tag_offset": 29184, + "close_tag_offset": 29696, + "packed_state_version": 1001, + "packed_state_version_hex": "0x000003e9", + "live_id_bound": 41, + "live_record_count": 1, + "live_entry_ids": [ + 41 + ], + "decoded_record_count": 1, + "imported_runtime_record_count": 1, + "records": [ + { + "record_index": 0, + "live_entry_id": 41, + "payload_offset": 29200, + "payload_len": 176, + "decode_status": "parity_only", + "payload_family": "real_packed_v1", + "trigger_kind": 7, + "one_shot": false, + "compact_control": { + "mode_byte_0x7ef": 7, + "primary_selector_0x7f0": 42, + "grouped_mode_0x7f4": 2, + "one_shot_header_0x7f5": 0, + "modifier_flag_0x7f9": 2, + "modifier_flag_0x7fa": 0, + "grouped_target_scope_ordinals_0x7fb": [ + 0, + 1, + 1, + 1 + ], + "grouped_scope_checkboxes_0x7ff": [ + 1, + 0, + 0, + 0 + ], + "summary_toggle_0x800": 1, + "grouped_territory_selectors_0x80f": [ + -1, + -1, + -1, + -1 + ] + }, + "text_bands": [], + "standalone_condition_row_count": 1, + "standalone_condition_rows": [ + { + "row_index": 0, + "raw_condition_id": 1802, + "subtype": 0, + "flag_bytes": [ + 100, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "candidate_name": null, + "comparator": "ge", + "metric": "Current Cash", + "semantic_family": "numeric_threshold", + "semantic_preview": "Test Current Cash >= 100", + "requires_candidate_name_binding": false, + "notes": [] + } + ], + "negative_sentinel_scope": { + "company_test_scope": "selected_company_only", + "player_test_scope": "disabled", + "territory_scope_selector_is_0x63": false, + "source_row_indexes": [ + 0 + ] + }, + "grouped_effect_row_counts": [ + 1, + 0, + 0, + 0 + ], + "grouped_effect_rows": [ + { + "group_index": 0, + "row_index": 0, + "descriptor_id": 2, + "descriptor_label": "Company Cash", + "target_mask_bits": 1, + "parameter_family": "company_finance_scalar", + "opcode": 8, + "raw_scalar_value": 333, + "value_byte_0x09": 1, + "value_dword_0x0d": 12, + "value_byte_0x11": 2, + "value_byte_0x12": 3, + "value_word_0x14": 24, + "value_word_0x16": 36, + "row_shape": "multivalue_scalar", + "semantic_family": "multivalue_scalar", + "semantic_preview": "Set Company Cash to 333 with aux [2, 3, 24, 36]", + "locomotive_name": null, + "notes": [] + } + ], + "decoded_conditions": [ + { + "kind": "company_numeric_threshold", + "target": { + "kind": "condition_true_company" + }, + "metric": "current_cash", + "comparator": "ge", + "value": 100 + } + ], + "decoded_actions": [ + { + "kind": "set_company_cash", + "target": { + "kind": "condition_true_company" + }, + "value": 333 + } + ], + "executable_import_ready": true, + "notes": [ + "decoded from grounded real 0x4e9a row framing", + "ordinary Current Cash threshold lowers condition-relative company scope at import time" + ] + } + ] + }, + "notes": [ + "real ordinary company-finance threshold sample" + ], + "company_roster": { + "source_kind": "tracked-save-slice-company-roster", + "semantic_family": "save-slice-runtime-company-context", + "observed_entry_count": 2, + "selected_company_id": 1, + "entries": [ + { + "company_id": 1, + "active": true, + "controller_kind": "human", + "current_cash": 150, + "debt": 80, + "credit_rating_score": 650, + "prime_rate": 5, + "available_track_laying_capacity": 6, + "track_piece_counts": { + "total": 20, + "single": 5, + "double": 8, + "transition": 1, + "electric": 3, + "non_electric": 17 + }, + "linked_chairman_profile_id": 1, + "book_value_per_share": 2620, + "investor_confidence": 37, + "management_attitude": 58, + "takeover_cooldown_year": 1839, + "merger_cooldown_year": 1838 + }, + { + "company_id": 2, + "active": true, + "controller_kind": "ai", + "current_cash": 90, + "debt": 40, + "credit_rating_score": 480, + "prime_rate": 6, + "available_track_laying_capacity": 2, + "track_piece_counts": { + "total": 8, + "single": 2, + "double": 2, + "transition": 0, + "electric": 1, + "non_electric": 7 + }, + "linked_chairman_profile_id": 2, + "book_value_per_share": 1400, + "investor_confidence": 22, + "management_attitude": 31, + "takeover_cooldown_year": null, + "merger_cooldown_year": null + } + ] + }, + "chairman_profile_table": { + "source_kind": "tracked-save-slice-chairman-profile-table", + "semantic_family": "save-slice-runtime-chairman-context", + "observed_entry_count": 2, + "selected_chairman_profile_id": 1, + "entries": [ + { + "profile_id": 1, + "name": "Chairman One", + "active": true, + "current_cash": 500, + "linked_company_id": 1, + "company_holdings": { + "1": 1000 + }, + "holdings_value_total": 700, + "net_worth_total": 1200, + "purchasing_power_total": 1500 + }, + { + "profile_id": 2, + "name": "Chairman Two", + "active": true, + "current_cash": 250, + "linked_company_id": 2, + "company_holdings": { + "2": 900 + }, + "holdings_value_total": 600, + "net_worth_total": 900, + "purchasing_power_total": 1100 + } + ] + } + } +} diff --git a/fixtures/runtime/packed-event-ordinary-company-finance-save-slice.json b/fixtures/runtime/packed-event-ordinary-company-finance-save-slice.json index ca3498a..e362829 100644 --- a/fixtures/runtime/packed-event-ordinary-company-finance-save-slice.json +++ b/fixtures/runtime/packed-event-ordinary-company-finance-save-slice.json @@ -32,7 +32,9 @@ "packed_state_version_hex": "0x000003e9", "live_id_bound": 41, "live_record_count": 1, - "live_entry_ids": [41], + "live_entry_ids": [ + 41 + ], "decoded_record_count": 1, "imported_runtime_record_count": 1, "records": [ @@ -52,10 +54,25 @@ "one_shot_header_0x7f5": 0, "modifier_flag_0x7f9": 2, "modifier_flag_0x7fa": 0, - "grouped_target_scope_ordinals_0x7fb": [0, 1, 1, 1], - "grouped_scope_checkboxes_0x7ff": [1, 0, 0, 0], + "grouped_target_scope_ordinals_0x7fb": [ + 0, + 1, + 1, + 1 + ], + "grouped_scope_checkboxes_0x7ff": [ + 1, + 0, + 0, + 0 + ], "summary_toggle_0x800": 1, - "grouped_territory_selectors_0x80f": [-1, -1, -1, -1] + "grouped_territory_selectors_0x80f": [ + -1, + -1, + -1, + -1 + ] }, "text_bands": [], "standalone_condition_row_count": 1, @@ -64,7 +81,33 @@ "row_index": 0, "raw_condition_id": 1802, "subtype": 0, - "flag_bytes": [100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "flag_bytes": [ + 100, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], "candidate_name": null, "comparator": "ge", "metric": "Current Cash", @@ -78,9 +121,16 @@ "company_test_scope": "selected_company_only", "player_test_scope": "disabled", "territory_scope_selector_is_0x63": false, - "source_row_indexes": [0] + "source_row_indexes": [ + 0 + ] }, - "grouped_effect_row_counts": [1, 0, 0, 0], + "grouped_effect_row_counts": [ + 1, + 0, + 0, + 0 + ], "grouped_effect_rows": [ { "group_index": 0, diff --git a/fixtures/runtime/packed-event-track-capacity-context-save-slice.json b/fixtures/runtime/packed-event-track-capacity-context-save-slice.json new file mode 100644 index 0000000..4987141 --- /dev/null +++ b/fixtures/runtime/packed-event-track-capacity-context-save-slice.json @@ -0,0 +1,219 @@ +{ + "format_version": 1, + "save_slice_id": "packed-event-track-capacity-save-slice", + "source": { + "description": "Tracked save-slice document with a real packed-event row for Company Track Pieces Buildable.", + "original_save_filename": "captured-track-capacity.gms", + "original_save_sha256": "track-capacity-sample-sha256", + "notes": [ + "tracked as JSON save-slice document rather than raw .smp", + "locks executable import for real descriptor 16" + ] + }, + "save_slice": { + "file_extension_hint": "gms", + "container_profile_family": "rt3-classic-save-container-v1", + "mechanism_family": "classic-save-rehydrate-v1", + "mechanism_confidence": "grounded", + "trailer_family": null, + "bridge_family": null, + "profile": null, + "candidate_availability_table": null, + "special_conditions_table": null, + "event_runtime_collection": { + "source_kind": "packed-event-runtime-collection", + "mechanism_family": "classic-save-rehydrate-v1", + "mechanism_confidence": "grounded", + "container_profile_family": "rt3-classic-save-container-v1", + "metadata_tag_offset": 28928, + "records_tag_offset": 29184, + "close_tag_offset": 29696, + "packed_state_version": 1001, + "packed_state_version_hex": "0x000003e9", + "live_id_bound": 32, + "live_record_count": 1, + "live_entry_ids": [ + 32 + ], + "decoded_record_count": 1, + "imported_runtime_record_count": 1, + "records": [ + { + "record_index": 0, + "live_entry_id": 32, + "payload_offset": 29186, + "payload_len": 120, + "decode_status": "parity_only", + "payload_family": "real_packed_v1", + "trigger_kind": 7, + "one_shot": false, + "compact_control": { + "mode_byte_0x7ef": 7, + "primary_selector_0x7f0": 99, + "grouped_mode_0x7f4": 2, + "one_shot_header_0x7f5": 0, + "modifier_flag_0x7f9": 1, + "modifier_flag_0x7fa": 0, + "grouped_target_scope_ordinals_0x7fb": [ + 1, + 1, + 1, + 1 + ], + "grouped_scope_checkboxes_0x7ff": [ + 1, + 0, + 0, + 0 + ], + "summary_toggle_0x800": 1, + "grouped_territory_selectors_0x80f": [ + -1, + -1, + -1, + -1 + ] + }, + "text_bands": [], + "standalone_condition_row_count": 0, + "standalone_condition_rows": [], + "grouped_effect_row_counts": [ + 1, + 0, + 0, + 0 + ], + "grouped_effect_rows": [ + { + "group_index": 0, + "row_index": 0, + "descriptor_id": 16, + "descriptor_label": "Company Track Pieces Buildable", + "target_mask_bits": 1, + "parameter_family": "company_build_limit_scalar", + "opcode": 3, + "raw_scalar_value": 18, + "value_byte_0x09": 0, + "value_dword_0x0d": 0, + "value_byte_0x11": 0, + "value_byte_0x12": 0, + "value_word_0x14": 0, + "value_word_0x16": 0, + "row_shape": "scalar_assignment", + "semantic_family": "scalar_assignment", + "semantic_preview": "Set Company Track Pieces Buildable to 18", + "locomotive_name": null, + "notes": [] + } + ], + "decoded_actions": [ + { + "kind": "set_company_track_laying_capacity", + "target": { + "kind": "selected_company" + }, + "value": 18 + } + ], + "executable_import_ready": true, + "notes": [ + "decoded from grounded real 0x4e9a row framing" + ] + } + ] + }, + "notes": [ + "real descriptor 16 sample" + ], + "company_roster": { + "source_kind": "tracked-save-slice-company-roster", + "semantic_family": "save-slice-runtime-company-context", + "observed_entry_count": 2, + "selected_company_id": 1, + "entries": [ + { + "company_id": 1, + "active": true, + "controller_kind": "human", + "current_cash": 150, + "debt": 80, + "credit_rating_score": 650, + "prime_rate": 5, + "available_track_laying_capacity": 6, + "track_piece_counts": { + "total": 20, + "single": 5, + "double": 8, + "transition": 1, + "electric": 3, + "non_electric": 17 + }, + "linked_chairman_profile_id": 1, + "book_value_per_share": 2620, + "investor_confidence": 37, + "management_attitude": 58, + "takeover_cooldown_year": 1839, + "merger_cooldown_year": 1838 + }, + { + "company_id": 2, + "active": true, + "controller_kind": "ai", + "current_cash": 90, + "debt": 40, + "credit_rating_score": 480, + "prime_rate": 6, + "available_track_laying_capacity": 2, + "track_piece_counts": { + "total": 8, + "single": 2, + "double": 2, + "transition": 0, + "electric": 1, + "non_electric": 7 + }, + "linked_chairman_profile_id": 2, + "book_value_per_share": 1400, + "investor_confidence": 22, + "management_attitude": 31, + "takeover_cooldown_year": null, + "merger_cooldown_year": null + } + ] + }, + "chairman_profile_table": { + "source_kind": "tracked-save-slice-chairman-profile-table", + "semantic_family": "save-slice-runtime-chairman-context", + "observed_entry_count": 2, + "selected_chairman_profile_id": 1, + "entries": [ + { + "profile_id": 1, + "name": "Chairman One", + "active": true, + "current_cash": 500, + "linked_company_id": 1, + "company_holdings": { + "1": 1000 + }, + "holdings_value_total": 700, + "net_worth_total": 1200, + "purchasing_power_total": 1500 + }, + { + "profile_id": 2, + "name": "Chairman Two", + "active": true, + "current_cash": 250, + "linked_company_id": 2, + "company_holdings": { + "2": 900 + }, + "holdings_value_total": 600, + "net_worth_total": 900, + "purchasing_power_total": 1100 + } + ] + } + } +} diff --git a/fixtures/runtime/packed-event-track-capacity-save-slice-fixture.json b/fixtures/runtime/packed-event-track-capacity-save-slice-fixture.json new file mode 100644 index 0000000..8c506eb --- /dev/null +++ b/fixtures/runtime/packed-event-track-capacity-save-slice-fixture.json @@ -0,0 +1,55 @@ +{ + "format_version": 1, + "fixture_id": "packed-event-track-capacity-save-slice-fixture", + "source": { + "kind": "captured-runtime", + "description": "Fixture proving descriptor 16 executes from save-slice-backed company context." + }, + "state_save_slice_path": "packed-event-track-capacity-context-save-slice.json", + "commands": [ + { + "kind": "service_trigger_kind", + "trigger_kind": 7 + } + ], + "expected_summary": { + "calendar_projection_source": "default-1830-placeholder", + "calendar_projection_is_placeholder": true, + "company_count": 2, + "active_company_count": 2, + "chairman_profile_count": 2, + "packed_event_collection_present": true, + "packed_event_record_count": 1, + "packed_event_decoded_record_count": 1, + "packed_event_imported_runtime_record_count": 1, + "event_runtime_record_count": 1, + "total_event_record_service_count": 1, + "total_trigger_dispatch_count": 1 + }, + "expected_state_fragment": { + "selected_company_id": 1, + "companies": [ + { + "company_id": 1, + "available_track_laying_capacity": 18 + }, + { + "company_id": 2, + "available_track_laying_capacity": 2 + } + ], + "packed_event_collection": { + "records": [ + { + "import_outcome": "imported" + } + ] + }, + "event_runtime_records": [ + { + "record_id": 32, + "service_count": 1 + } + ] + } +} diff --git a/fixtures/runtime/packed-event-track-capacity-save-slice.json b/fixtures/runtime/packed-event-track-capacity-save-slice.json index f2347d5..060ea05 100644 --- a/fixtures/runtime/packed-event-track-capacity-save-slice.json +++ b/fixtures/runtime/packed-event-track-capacity-save-slice.json @@ -32,7 +32,9 @@ "packed_state_version_hex": "0x000003e9", "live_id_bound": 32, "live_record_count": 1, - "live_entry_ids": [32], + "live_entry_ids": [ + 32 + ], "decoded_record_count": 1, "imported_runtime_record_count": 1, "records": [ @@ -52,15 +54,35 @@ "one_shot_header_0x7f5": 0, "modifier_flag_0x7f9": 1, "modifier_flag_0x7fa": 0, - "grouped_target_scope_ordinals_0x7fb": [1, 1, 1, 1], - "grouped_scope_checkboxes_0x7ff": [1, 0, 0, 0], + "grouped_target_scope_ordinals_0x7fb": [ + 1, + 1, + 1, + 1 + ], + "grouped_scope_checkboxes_0x7ff": [ + 1, + 0, + 0, + 0 + ], "summary_toggle_0x800": 1, - "grouped_territory_selectors_0x80f": [-1, -1, -1, -1] + "grouped_territory_selectors_0x80f": [ + -1, + -1, + -1, + -1 + ] }, "text_bands": [], "standalone_condition_row_count": 0, "standalone_condition_rows": [], - "grouped_effect_row_counts": [1, 0, 0, 0], + "grouped_effect_row_counts": [ + 1, + 0, + 0, + 0 + ], "grouped_effect_rows": [ { "group_index": 0,