From 5c2156bcbf7192eb7ee26853dbabba0c55129a46 Mon Sep 17 00:00:00 2001 From: Jan Petykiewicz Date: Thu, 16 Apr 2026 17:30:42 -0700 Subject: [PATCH] Implement governance issue packed event conditions --- README.md | 8 +- crates/rrt-cli/src/main.rs | 16 + crates/rrt-runtime/src/import.rs | 256 ++++++++++++++++ crates/rrt-runtime/src/smp.rs | 108 ++++++- docs/README.md | 6 +- docs/runtime-rehost-plan.md | 5 +- ...nfidence-condition-context-save-slice.json | 280 ++++++++++++++++++ ...nfidence-condition-save-slice-fixture.json | 51 ++++ ...attitude-condition-context-save-slice.json | 280 ++++++++++++++++++ ...attitude-condition-save-slice-fixture.json | 51 ++++ 10 files changed, 1048 insertions(+), 13 deletions(-) create mode 100644 fixtures/runtime/packed-event-investor-confidence-condition-context-save-slice.json create mode 100644 fixtures/runtime/packed-event-investor-confidence-condition-save-slice-fixture.json create mode 100644 fixtures/runtime/packed-event-management-attitude-condition-context-save-slice.json create mode 100644 fixtures/runtime/packed-event-management-attitude-condition-save-slice-fixture.json diff --git a/README.md b/README.md index b651aaa..cd9b21b 100644 --- a/README.md +++ b/README.md @@ -21,10 +21,10 @@ still exercise the same runtime without a parallel packed executor. The first gr chairman-profile runtime slice now exists too: overlay-backed selected-chairman context plus the hidden grouped target-subject lane let those same real descriptors `1` and `14` execute on selected-chairman scope, while wider chairman target scopes remain explicit parity. The first grounded -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. Checked-in save-slice +chairman and governance condition batch is broader now: selected-chairman cash / holdings / net +worth / purchasing-power thresholds and company book-value-per-share / investor-confidence / +management-attitude thresholds now import through the normal event-service path, while wider +chairman target scopes 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 diff --git a/crates/rrt-cli/src/main.rs b/crates/rrt-cli/src/main.rs index 1bb8cf2..e93ed16 100644 --- a/crates/rrt-cli/src/main.rs +++ b/crates/rrt-cli/src/main.rs @@ -4523,6 +4523,18 @@ mod tests { .join( "../../fixtures/runtime/packed-event-company-governance-condition-save-slice-fixture.json", ); + let investor_confidence_condition_save_fixture = PathBuf::from(env!( + "CARGO_MANIFEST_DIR" + )) + .join( + "../../fixtures/runtime/packed-event-investor-confidence-condition-save-slice-fixture.json", + ); + let management_attitude_condition_save_fixture = PathBuf::from(env!( + "CARGO_MANIFEST_DIR" + )) + .join( + "../../fixtures/runtime/packed-event-management-attitude-condition-save-slice-fixture.json", + ); run_runtime_summarize_fixture(&parity_fixture) .expect("save-slice-backed parity fixture should summarize"); @@ -4590,6 +4602,10 @@ mod tests { .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"); + run_runtime_summarize_fixture(&investor_confidence_condition_save_fixture) + .expect("save-slice-backed investor-confidence condition fixture should summarize"); + run_runtime_summarize_fixture(&management_attitude_condition_save_fixture) + .expect("save-slice-backed management-attitude condition fixture should summarize"); } #[test] diff --git a/crates/rrt-runtime/src/import.rs b/crates/rrt-runtime/src/import.rs index 9bd6587..df70379 100644 --- a/crates/rrt-runtime/src/import.rs +++ b/crates/rrt-runtime/src/import.rs @@ -9661,6 +9661,262 @@ mod tests { ); } + #[test] + fn imports_investor_confidence_condition_from_save_slice_company_context() { + 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: Some(crate::SmpLoadedEventRuntimeCollectionSummary { + source_kind: "packed-event-runtime-collection".to_string(), + mechanism_family: "classic-save-rehydrate-v1".to_string(), + mechanism_confidence: "grounded".to_string(), + container_profile_family: Some("rt3-classic-save-container-v1".to_string()), + metadata_tag_offset: 0x7100, + records_tag_offset: 0x7200, + close_tag_offset: 0x7600, + packed_state_version: 0x3e9, + packed_state_version_hex: "0x000003e9".to_string(), + live_id_bound: 73, + live_record_count: 1, + live_entry_ids: vec![73], + decoded_record_count: 1, + imported_runtime_record_count: 0, + records: vec![crate::SmpLoadedPackedEventRecordSummary { + record_index: 0, + live_entry_id: 73, + payload_offset: Some(0x7202), + payload_len: Some(136), + decode_status: "parity_only".to_string(), + payload_family: "real_packed_v1".to_string(), + trigger_kind: Some(7), + active: None, + marks_collection_dirty: None, + one_shot: Some(false), + compact_control: Some(real_compact_control()), + text_bands: vec![], + standalone_condition_row_count: 1, + standalone_condition_rows: vec![ + crate::SmpLoadedPackedEventConditionRowSummary { + row_index: 0, + raw_condition_id: 2366, + subtype: 4, + flag_bytes: { + let mut bytes = vec![0; 25]; + bytes[0..4].copy_from_slice(&37_i32.to_le_bytes()); + bytes + }, + candidate_name: None, + comparator: Some("eq".to_string()), + metric: Some("Investor Confidence".to_string()), + semantic_family: Some("numeric_threshold".to_string()), + semantic_preview: Some("Test Investor Confidence == 37".to_string()), + recovered_cargo_slot: None, + recovered_cargo_class: None, + requires_candidate_name_binding: false, + notes: vec![], + }, + ], + negative_sentinel_scope: Some(company_negative_sentinel_scope( + RuntimeCompanyConditionTestScope::SelectedCompanyOnly, + )), + grouped_effect_row_counts: vec![1, 0, 0, 0], + grouped_effect_rows: vec![real_world_flag_row( + 110, + "Disable Stock Buying and Selling", + true, + )], + decoded_conditions: vec![RuntimeCondition::CompanyNumericThreshold { + target: RuntimeCompanyTarget::ConditionTrueCompany, + metric: crate::RuntimeCompanyMetric::InvestorConfidence, + comparator: RuntimeConditionComparator::Eq, + value: 37, + }], + decoded_actions: vec![RuntimeEffect::SetWorldFlag { + key: "world.investor_confidence_condition_imported".to_string(), + value: true, + }], + executable_import_ready: true, + notes: vec![ + "investor confidence condition gates a world-side effect".to_string(), + ], + }], + }), + notes: vec![], + }; + + let mut import = project_save_slice_to_runtime_state_import( + &save_slice, + "company-investor-confidence-condition", + None, + ) + .expect("save-slice import should project"); + + assert_eq!(import.state.event_runtime_records.len(), 1); + assert_eq!( + import.state.event_runtime_records[0].conditions, + vec![RuntimeCondition::CompanyNumericThreshold { + target: RuntimeCompanyTarget::SelectedCompany, + metric: crate::RuntimeCompanyMetric::InvestorConfidence, + comparator: RuntimeConditionComparator::Eq, + value: 37, + }] + ); + + crate::execute_step_command( + &mut import.state, + &crate::StepCommand::ServiceTriggerKind { trigger_kind: 7 }, + ) + .expect("investor-confidence trigger should execute"); + + assert_eq!( + import + .state + .world_flags + .get("world.investor_confidence_condition_imported"), + Some(&true) + ); + } + + #[test] + fn imports_management_attitude_condition_from_save_slice_company_context() { + 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: Some(crate::SmpLoadedEventRuntimeCollectionSummary { + source_kind: "packed-event-runtime-collection".to_string(), + mechanism_family: "classic-save-rehydrate-v1".to_string(), + mechanism_confidence: "grounded".to_string(), + container_profile_family: Some("rt3-classic-save-container-v1".to_string()), + metadata_tag_offset: 0x7100, + records_tag_offset: 0x7200, + close_tag_offset: 0x7600, + packed_state_version: 0x3e9, + packed_state_version_hex: "0x000003e9".to_string(), + live_id_bound: 74, + live_record_count: 1, + live_entry_ids: vec![74], + decoded_record_count: 1, + imported_runtime_record_count: 0, + records: vec![crate::SmpLoadedPackedEventRecordSummary { + record_index: 0, + live_entry_id: 74, + payload_offset: Some(0x7202), + payload_len: Some(136), + decode_status: "parity_only".to_string(), + payload_family: "real_packed_v1".to_string(), + trigger_kind: Some(7), + active: None, + marks_collection_dirty: None, + one_shot: Some(false), + compact_control: Some(real_compact_control()), + text_bands: vec![], + standalone_condition_row_count: 1, + standalone_condition_rows: vec![ + crate::SmpLoadedPackedEventConditionRowSummary { + row_index: 0, + raw_condition_id: 2369, + subtype: 4, + flag_bytes: { + let mut bytes = vec![0; 25]; + bytes[0..4].copy_from_slice(&58_i32.to_le_bytes()); + bytes + }, + candidate_name: None, + comparator: Some("eq".to_string()), + metric: Some("Management Attitude".to_string()), + semantic_family: Some("numeric_threshold".to_string()), + semantic_preview: Some("Test Management Attitude == 58".to_string()), + recovered_cargo_slot: None, + recovered_cargo_class: None, + requires_candidate_name_binding: false, + notes: vec![], + }, + ], + negative_sentinel_scope: Some(company_negative_sentinel_scope( + RuntimeCompanyConditionTestScope::SelectedCompanyOnly, + )), + grouped_effect_row_counts: vec![1, 0, 0, 0], + grouped_effect_rows: vec![real_world_flag_row( + 110, + "Disable Stock Buying and Selling", + true, + )], + decoded_conditions: vec![RuntimeCondition::CompanyNumericThreshold { + target: RuntimeCompanyTarget::ConditionTrueCompany, + metric: crate::RuntimeCompanyMetric::ManagementAttitude, + comparator: RuntimeConditionComparator::Eq, + value: 58, + }], + decoded_actions: vec![RuntimeEffect::SetWorldFlag { + key: "world.management_attitude_condition_imported".to_string(), + value: true, + }], + executable_import_ready: true, + notes: vec![ + "management attitude condition gates a world-side effect".to_string(), + ], + }], + }), + notes: vec![], + }; + + let mut import = project_save_slice_to_runtime_state_import( + &save_slice, + "company-management-attitude-condition", + None, + ) + .expect("save-slice import should project"); + + assert_eq!(import.state.event_runtime_records.len(), 1); + assert_eq!( + import.state.event_runtime_records[0].conditions, + vec![RuntimeCondition::CompanyNumericThreshold { + target: RuntimeCompanyTarget::SelectedCompany, + metric: crate::RuntimeCompanyMetric::ManagementAttitude, + comparator: RuntimeConditionComparator::Eq, + value: 58, + }] + ); + + crate::execute_step_command( + &mut import.state, + &crate::StepCommand::ServiceTriggerKind { trigger_kind: 7 }, + ) + .expect("management-attitude trigger should execute"); + + assert_eq!( + import + .state + .world_flags + .get("world.management_attitude_condition_imported"), + Some(&true) + ); + } + #[test] fn overlays_recovered_world_toggle_batch_into_executable_runtime_record() { let base_state = state(); diff --git a/crates/rrt-runtime/src/smp.rs b/crates/rrt-runtime/src/smp.rs index 1b4fb5b..1313608 100644 --- a/crates/rrt-runtime/src/smp.rs +++ b/crates/rrt-runtime/src/smp.rs @@ -350,6 +350,10 @@ const REAL_CHAIRMAN_CASH_CONDITION_ID: i32 = 2218; const REAL_CHAIRMAN_HOLDINGS_TOTAL_CONDITION_ID: i32 = 2239; const REAL_CHAIRMAN_NET_WORTH_CONDITION_ID: i32 = 2240; const REAL_CHAIRMAN_PURCHASING_POWER_CONDITION_ID: i32 = 1247; +const REAL_INVESTOR_CONFIDENCE_CONDITION_ID: i32 = 2366; +const REAL_CREDIT_RATING_CONDITION_ID: i32 = 2367; +const REAL_PRIME_RATE_CONDITION_ID: i32 = 2368; +const REAL_MANAGEMENT_ATTITUDE_CONDITION_ID: i32 = 2369; const REAL_BOOK_VALUE_PER_SHARE_CONDITION_ID: i32 = 2620; const REAL_CARGO_PRODUCTION_CONDITION_TEMPLATE_ID: i32 = 200; const REAL_NAMED_LOCOMOTIVE_AVAILABILITY_CONDITION_ID: i32 = 2422; @@ -361,7 +365,7 @@ const REAL_OTHER_CARGO_PRODUCTION_TOTAL_CONDITION_ID: i32 = 2421; const REAL_LIMITED_TRACK_BUILDING_AMOUNT_CONDITION_ID: i32 = 2547; const REAL_TERRITORY_ACCESS_COST_CONDITION_ID: i32 = 1516; -const REAL_ORDINARY_CONDITION_METADATA: [RealOrdinaryConditionMetadata; 38] = [ +const REAL_ORDINARY_CONDITION_METADATA: [RealOrdinaryConditionMetadata; 40] = [ RealOrdinaryConditionMetadata { raw_condition_id: 1802, label: "Current Cash", @@ -405,19 +409,33 @@ const REAL_ORDINARY_CONDITION_METADATA: [RealOrdinaryConditionMetadata; 38] = [ )), }, RealOrdinaryConditionMetadata { - raw_condition_id: 2366, + raw_condition_id: REAL_INVESTOR_CONFIDENCE_CONDITION_ID, + label: "Investor Confidence", + kind: RealOrdinaryConditionKind::Numeric(RealOrdinaryConditionMetric::Company( + RuntimeCompanyMetric::InvestorConfidence, + )), + }, + RealOrdinaryConditionMetadata { + raw_condition_id: REAL_CREDIT_RATING_CONDITION_ID, label: "Credit Rating", kind: RealOrdinaryConditionKind::Numeric(RealOrdinaryConditionMetric::Company( RuntimeCompanyMetric::CreditRating, )), }, RealOrdinaryConditionMetadata { - raw_condition_id: 2368, + raw_condition_id: REAL_PRIME_RATE_CONDITION_ID, label: "Prime Rate", kind: RealOrdinaryConditionKind::Numeric(RealOrdinaryConditionMetric::Company( RuntimeCompanyMetric::PrimeRate, )), }, + RealOrdinaryConditionMetadata { + raw_condition_id: REAL_MANAGEMENT_ATTITUDE_CONDITION_ID, + label: "Management Attitude", + kind: RealOrdinaryConditionKind::Numeric(RealOrdinaryConditionMetric::Company( + RuntimeCompanyMetric::ManagementAttitude, + )), + }, RealOrdinaryConditionMetadata { raw_condition_id: REAL_BOOK_VALUE_PER_SHARE_CONDITION_ID, label: "Book Value Per Share", @@ -10559,6 +10577,24 @@ mod tests { .expect("chairman purchasing-power condition metadata should exist"); assert_eq!(purchasing_power.label, "Purchasing Power"); + let investor_confidence = + real_ordinary_condition_metadata(REAL_INVESTOR_CONFIDENCE_CONDITION_ID) + .expect("investor-confidence condition metadata should exist"); + assert_eq!(investor_confidence.label, "Investor Confidence"); + + let credit_rating = real_ordinary_condition_metadata(REAL_CREDIT_RATING_CONDITION_ID) + .expect("credit-rating condition metadata should exist"); + assert_eq!(credit_rating.label, "Credit Rating"); + + let prime_rate = real_ordinary_condition_metadata(REAL_PRIME_RATE_CONDITION_ID) + .expect("prime-rate condition metadata should exist"); + assert_eq!(prime_rate.label, "Prime Rate"); + + let management_attitude = + real_ordinary_condition_metadata(REAL_MANAGEMENT_ATTITUDE_CONDITION_ID) + .expect("management-attitude condition metadata should exist"); + assert_eq!(management_attitude.label, "Management Attitude"); + let book_value = real_ordinary_condition_metadata(REAL_BOOK_VALUE_PER_SHARE_CONDITION_ID) .expect("book value condition metadata should exist"); assert_eq!(book_value.label, "Book Value Per Share"); @@ -10636,6 +10672,72 @@ mod tests { ); } + #[test] + fn decodes_investor_confidence_condition_to_company_metric() { + let row = SmpLoadedPackedEventConditionRowSummary { + row_index: 0, + raw_condition_id: REAL_INVESTOR_CONFIDENCE_CONDITION_ID, + subtype: 4, + flag_bytes: { + let mut bytes = vec![0; 25]; + bytes[0..4].copy_from_slice(&37_i32.to_le_bytes()); + bytes + }, + candidate_name: None, + comparator: Some("eq".to_string()), + metric: Some("Investor Confidence".to_string()), + semantic_family: Some("numeric_threshold".to_string()), + semantic_preview: Some("Test Investor Confidence == 37".to_string()), + recovered_cargo_slot: None, + recovered_cargo_class: None, + requires_candidate_name_binding: false, + notes: vec![], + }; + + assert_eq!( + decode_real_condition_row(&row, None), + Some(RuntimeCondition::CompanyNumericThreshold { + target: RuntimeCompanyTarget::ConditionTrueCompany, + metric: RuntimeCompanyMetric::InvestorConfidence, + comparator: RuntimeConditionComparator::Eq, + value: 37, + }) + ); + } + + #[test] + fn decodes_management_attitude_condition_to_company_metric() { + let row = SmpLoadedPackedEventConditionRowSummary { + row_index: 0, + raw_condition_id: REAL_MANAGEMENT_ATTITUDE_CONDITION_ID, + subtype: 4, + flag_bytes: { + let mut bytes = vec![0; 25]; + bytes[0..4].copy_from_slice(&58_i32.to_le_bytes()); + bytes + }, + candidate_name: None, + comparator: Some("eq".to_string()), + metric: Some("Management Attitude".to_string()), + semantic_family: Some("numeric_threshold".to_string()), + semantic_preview: Some("Test Management Attitude == 58".to_string()), + recovered_cargo_slot: None, + recovered_cargo_class: None, + requires_candidate_name_binding: false, + notes: vec![], + }; + + assert_eq!( + decode_real_condition_row(&row, None), + Some(RuntimeCondition::CompanyNumericThreshold { + target: RuntimeCompanyTarget::ConditionTrueCompany, + metric: RuntimeCompanyMetric::ManagementAttitude, + comparator: RuntimeConditionComparator::Eq, + value: 58, + }) + ); + } + #[test] fn looks_up_checked_in_world_flag_descriptor_metadata() { let metadata = diff --git a/docs/README.md b/docs/README.md index 22ff281..f734b39 100644 --- a/docs/README.md +++ b/docs/README.md @@ -89,9 +89,9 @@ The highest-value next passes are now: scopes stay parity-only under `blocked_chairman_target_scope` - chairman runtime ownership is broader now too: selected-chairman condition rows for chairman cash, holdings value, net worth, and purchasing power import through the same service path, and - 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 + the first grounded company governance issue batch now executes too via book-value-per-share, + investor-confidence, and management-attitude thresholds; wider chairman target ordinals 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 diff --git a/docs/runtime-rehost-plan.md b/docs/runtime-rehost-plan.md index de1a789..db2ca6c 100644 --- a/docs/runtime-rehost-plan.md +++ b/docs/runtime-rehost-plan.md @@ -50,9 +50,8 @@ Implemented today: book-value-per-share, investor-confidence, management-attitude, and takeover/merger cooldown lanes, and the first grounded chairman/control-transfer ordinary-condition batch now imports and executes through the same path for selected-chairman cash / holdings / net-worth / - 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 + purchasing-power thresholds plus company book-value-per-share / investor-confidence / + management-attitude thresholds; wider chairman target ordinals 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 diff --git a/fixtures/runtime/packed-event-investor-confidence-condition-context-save-slice.json b/fixtures/runtime/packed-event-investor-confidence-condition-context-save-slice.json new file mode 100644 index 0000000..817e5af --- /dev/null +++ b/fixtures/runtime/packed-event-investor-confidence-condition-context-save-slice.json @@ -0,0 +1,280 @@ +{ + "format_version": 1, + "save_slice_id": "packed-event-investor-confidence-condition-save-slice", + "source": { + "description": "Tracked save-slice document proving grounded investor-confidence conditions import and execute from save-native company context.", + "original_save_filename": "captured-investor-confidence-condition.gms", + "original_save_sha256": "investor-confidence-condition-sample-sha256", + "notes": [ + "tracked as JSON save-slice document rather than raw .smp", + "pins the grounded governance issue-0x37 condition lane" + ] + }, + "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": 73, + "live_record_count": 1, + "live_entry_ids": [ + 73 + ], + "decoded_record_count": 1, + "imported_runtime_record_count": 0, + "records": [ + { + "record_index": 0, + "live_entry_id": 73, + "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": 2366, + "subtype": 4, + "flag_bytes": [ + 37, + 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": "eq", + "metric": "Investor Confidence", + "semantic_family": "numeric_threshold", + "semantic_preview": "Test Investor Confidence == 37", + "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": "investor_confidence", + "comparator": "eq", + "value": 37 + } + ], + "decoded_actions": [ + { + "kind": "set_world_flag", + "key": "world.investor_confidence_condition_imported", + "value": true + } + ], + "executable_import_ready": true, + "notes": [ + "investor confidence condition gates a world-side effect" + ] + } + ] + }, + "notes": [ + "real company-governance ordinary-condition sample for investor confidence" + ], + "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-investor-confidence-condition-save-slice-fixture.json b/fixtures/runtime/packed-event-investor-confidence-condition-save-slice-fixture.json new file mode 100644 index 0000000..6a5b51b --- /dev/null +++ b/fixtures/runtime/packed-event-investor-confidence-condition-save-slice-fixture.json @@ -0,0 +1,51 @@ +{ + "format_version": 1, + "fixture_id": "packed-event-investor-confidence-condition-save-slice-fixture", + "source": { + "kind": "captured-runtime", + "description": "Fixture proving grounded investor-confidence conditions import and execute from save-slice-backed context." + }, + "state_save_slice_path": "packed-event-investor-confidence-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.investor_confidence_condition_imported": true + }, + "packed_event_collection": { + "records": [ + { + "import_outcome": "imported" + } + ] + }, + "event_runtime_records": [ + { + "record_id": 73, + "service_count": 1 + } + ] + } +} diff --git a/fixtures/runtime/packed-event-management-attitude-condition-context-save-slice.json b/fixtures/runtime/packed-event-management-attitude-condition-context-save-slice.json new file mode 100644 index 0000000..95d79b4 --- /dev/null +++ b/fixtures/runtime/packed-event-management-attitude-condition-context-save-slice.json @@ -0,0 +1,280 @@ +{ + "format_version": 1, + "save_slice_id": "packed-event-management-attitude-condition-save-slice", + "source": { + "description": "Tracked save-slice document proving grounded management-attitude conditions import and execute from save-native company context.", + "original_save_filename": "captured-management-attitude-condition.gms", + "original_save_sha256": "management-attitude-condition-sample-sha256", + "notes": [ + "tracked as JSON save-slice document rather than raw .smp", + "pins the grounded governance issue-0x3a condition lane" + ] + }, + "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": 74, + "live_record_count": 1, + "live_entry_ids": [ + 74 + ], + "decoded_record_count": 1, + "imported_runtime_record_count": 0, + "records": [ + { + "record_index": 0, + "live_entry_id": 74, + "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": 2369, + "subtype": 4, + "flag_bytes": [ + 58, + 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": "eq", + "metric": "Management Attitude", + "semantic_family": "numeric_threshold", + "semantic_preview": "Test Management Attitude == 58", + "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": "management_attitude", + "comparator": "eq", + "value": 58 + } + ], + "decoded_actions": [ + { + "kind": "set_world_flag", + "key": "world.management_attitude_condition_imported", + "value": true + } + ], + "executable_import_ready": true, + "notes": [ + "management attitude condition gates a world-side effect" + ] + } + ] + }, + "notes": [ + "real company-governance ordinary-condition sample for management attitude" + ], + "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-management-attitude-condition-save-slice-fixture.json b/fixtures/runtime/packed-event-management-attitude-condition-save-slice-fixture.json new file mode 100644 index 0000000..ed723ca --- /dev/null +++ b/fixtures/runtime/packed-event-management-attitude-condition-save-slice-fixture.json @@ -0,0 +1,51 @@ +{ + "format_version": 1, + "fixture_id": "packed-event-management-attitude-condition-save-slice-fixture", + "source": { + "kind": "captured-runtime", + "description": "Fixture proving grounded management-attitude conditions import and execute from save-slice-backed context." + }, + "state_save_slice_path": "packed-event-management-attitude-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.management_attitude_condition_imported": true + }, + "packed_event_collection": { + "records": [ + { + "import_outcome": "imported" + } + ] + }, + "event_runtime_records": [ + { + "record_id": 74, + "service_count": 1 + } + ] + } +}