extends GutTest func test_daily_rollups_group_by_day_location_item_and_type_deterministically() -> void: var events: Array[WorldEventRecord] = [ _transaction(9, &"storage_deposited", 5, &"village_pantry", &"food", 2.0), _transaction(2, &"storage_deposited", 4, &"village_pantry", &"food", 1.0), _transaction(4, &"storage_deposited", 8, &"village_pantry", &"wood", 3.0), _transaction(5, &"storage_deposited", 15, &"village_pantry", &"food", 4.0), _transaction(6, &"storage_deposited", 15, &"lower_town", &"food", 5.0), _transaction(7, &"resource_extracted", 15, &"forest_edge", &"food", 6.0), _transaction(8, &"storage_deposited", 25, &"village_pantry", &"food", 7.0), ] var source := _store_from_events(events) var source_before := source.to_dictionary() var planner := WorldEventRetentionPlanner.new() var retention_plan := planner.plan(source, 35, 10, 1, [&"storage_deposited"]) assert_not_null(retention_plan) assert_eq(retention_plan.get_retained_event_ids(), [7, 8]) assert_eq(retention_plan.get_rolled_up_event_ids(), [2, 4, 5, 6, 9]) assert_eq(source.to_dictionary(), source_before) var rollups := retention_plan.get_rollup_store() assert_eq(rollups.size(), 4) var day_zero_food := rollups.get_by_key( 0, &"world_core", &"village_pantry", &"storage_deposited", &"food" ) assert_not_null(day_zero_food) assert_eq(day_zero_food.get_event_count(), 2) assert_eq(day_zero_food.get_total_amount(), 3.0) assert_eq(day_zero_food.get_minimum_tick(), 4) assert_eq(day_zero_food.get_maximum_tick(), 5) assert_eq(day_zero_food.get_minimum_event_id(), 2) assert_eq(day_zero_food.get_maximum_event_id(), 9) assert_eq(day_zero_food.get_source_event_ids_checksum(), JSON.stringify([2, 9]).sha256_text()) assert_eq(rollups.get_for_day(0).size(), 2) assert_eq(rollups.get_for_location(&"world_core", &"village_pantry").size(), 3) assert_eq(rollups.get_for_item(&"food").size(), 3) assert_eq(rollups.get_for_event_type(&"storage_deposited").size(), 4) assert_eq(retention_plan.get_reason_trace(7)["reasons"], ["not_rollup_eligible"]) assert_eq(retention_plan.get_reason_trace(8)["reasons"], ["within_raw_retention"]) var telemetry := retention_plan.get_telemetry() assert_eq(telemetry["input_event_count"], 7) assert_eq(telemetry["retained_event_count"], 2) assert_eq(telemetry["rolled_up_event_count"], 5) assert_eq(telemetry["rollup_record_count"], 4) assert_eq(telemetry["rollup_contribution_count"], 5) assert_true(telemetry["source_unchanged"]) assert_eq(planner.get_last_telemetry(), telemetry) var reversed_events := events.duplicate() reversed_events.reverse() var reversed_plan := WorldEventRetentionPlanner.new().plan( _store_from_events(reversed_events), 35, 10, 1, [&"storage_deposited"] ) assert_not_null(reversed_plan) assert_eq(reversed_plan.to_dictionary(), retention_plan.to_dictionary()) assert_eq(reversed_plan.checksum(), retention_plan.checksum()) func test_pinned_external_and_payload_causal_facts_remain_exact_raw_events() -> void: var source := WorldEventStore.new() assert_true(source.append(_causal_transaction(1, 1, -1))) assert_true(source.append(_causal_transaction(2, 2, 1))) assert_true( source.append( WorldEventRecord.create( 3, &"situation_opened", 3, {}, _address(&"village_pantry"), {"cause_event_id": 2} ) ) ) assert_true(source.append(_causal_transaction(4, 4, -1))) assert_true(source.append(_causal_transaction(5, 5, -1))) assert_true(source.append(_causal_transaction(6, 6, -1))) var planner := WorldEventRetentionPlanner.new() var retention_plan := planner.plan(source, 50, 10, 0, [&"storage_deposited"], [4], [5]) assert_not_null(retention_plan) assert_eq(retention_plan.get_retained_event_ids(), [1, 2, 3, 4, 5]) assert_eq(retention_plan.get_rolled_up_event_ids(), [6]) assert_has(retention_plan.get_reason_trace(1)["reasons"], "causal_ancestor") assert_eq(retention_plan.get_reason_trace(1)["required_by_event_ids"], [2]) assert_has(retention_plan.get_reason_trace(2)["reasons"], "causal_ancestor") assert_eq(retention_plan.get_reason_trace(2)["required_by_event_ids"], [3]) assert_has(retention_plan.get_reason_trace(3)["reasons"], "not_rollup_eligible") assert_has(retention_plan.get_reason_trace(4)["reasons"], "pinned_fact") assert_has(retention_plan.get_reason_trace(5)["reasons"], "explicit_causal_fact") assert_eq(retention_plan.get_reason_trace(6)["decision"], "rolled_up") assert_eq(retention_plan.get_telemetry()["causal_ancestor_count"], 2) var missing_causal_trace := retention_plan.to_dictionary() missing_causal_trace["reason_traces"][0]["reasons"].erase("causal_ancestor") assert_null(WorldEventRetentionPlan.from_dictionary(missing_causal_trace)) var missing_pin_trace := retention_plan.to_dictionary() missing_pin_trace["reason_traces"][3]["reasons"].erase("pinned_fact") assert_null(WorldEventRetentionPlan.from_dictionary(missing_pin_trace)) var before_missing_pin := source.to_dictionary() assert_null(planner.plan(source, 50, 10, 0, [&"storage_deposited"], [404])) assert_string_contains(planner.get_last_error(), "pinned fact ID 404 is missing") assert_false(planner.get_last_telemetry()["succeeded"]) assert_eq(source.to_dictionary(), before_missing_pin) func test_cargo_ledger_rolls_up_each_item_and_invalid_transactions_stay_raw() -> void: var source := WorldEventStore.new() assert_true( source.append( WorldEventRecord.create( 10, &"caravan_cargo_deposited", 1, {}, _address(&"river_port"), {"cargo_ledger": {"wood": 1.0, "food": 2.5}, "cause_event_id": -1} ) ) ) assert_true( source.append( WorldEventRecord.create( 11, &"caravan_cargo_deposited", 2, {}, _address(&"river_port"), {"cargo_ledger": {"food": 1.0}, "item_id": "food", "amount": 1.0} ) ) ) assert_true( source.append( WorldEventRecord.create( 12, &"caravan_cargo_deposited", 2, {}, _address(&"river_port"), {"cargo_ledger": {"food": 0.0}} ) ) ) assert_true( source.append( WorldEventRecord.create( 13, &"caravan_cargo_deposited", 2, {}, null, {"cargo_ledger": {"food": 1.0}} ) ) ) var retention_plan := WorldEventRetentionPlanner.new().plan( source, 30, 10, 0, [&"caravan_cargo_deposited"] ) assert_not_null(retention_plan) assert_eq(retention_plan.get_rolled_up_event_ids(), [10]) assert_eq(retention_plan.get_retained_event_ids(), [11, 12, 13]) var rollups := retention_plan.get_rollup_store() assert_eq(rollups.size(), 2) assert_eq( ( rollups . get_by_key(0, &"world_core", &"river_port", &"caravan_cargo_deposited", &"food") . get_total_amount() ), 2.5 ) assert_eq( ( rollups . get_by_key(0, &"world_core", &"river_port", &"caravan_cargo_deposited", &"wood") . get_total_amount() ), 1.0 ) assert_eq(retention_plan.get_reason_trace(10)["rollup_keys"].size(), 2) for event_id in [11, 12, 13]: assert_has(retention_plan.get_reason_trace(event_id)["reasons"], "rollup_payload_invalid") assert_eq(retention_plan.get_telemetry()["invalid_rollup_event_count"], 3) assert_eq(retention_plan.get_telemetry()["rollup_contribution_count"], 2) func test_record_store_and_plan_are_canonical_primitive_and_round_trippable() -> void: var source := _store_from_events( [ _transaction(3, &"storage_deposited", 1, &"pantry", &"food", 2.0), _transaction(4, &"storage_deposited", 2, &"pantry", &"food", 3.0), ] ) var retention_plan := WorldEventRetentionPlanner.new().plan( source, 20, 10, 0, [&"storage_deposited"] ) var serialized := retention_plan.to_dictionary() var restored := WorldEventRetentionPlan.from_dictionary(serialized) assert_not_null(restored) assert_true(_is_primitive_tree(serialized)) assert_eq(restored.to_dictionary(), serialized) assert_eq(JSON.stringify(restored.to_dictionary()), JSON.stringify(serialized)) assert_eq(restored.checksum(), retention_plan.checksum()) var rollup := restored.get_rollup_store().get_all()[0] assert_has(rollup.get_reason_trace(), &"daily_transaction_rollup") assert_true(String(rollup.get_reason_trace()[-1]).begins_with("source_event_ids_sha256_")) assert_eq( WorldEventDailyRollupRecord.from_dictionary(rollup.to_dictionary()).to_dictionary(), rollup.to_dictionary() ) var store := restored.get_rollup_store() var store_before := store.to_dictionary() var duplicated_store := store_before.duplicate(true) duplicated_store["rollups"].append(store_before["rollups"][0].duplicate(true)) assert_false(store.restore_from_dictionary(duplicated_store)) assert_eq(store.to_dictionary(), store_before) var noncanonical_plan := serialized.duplicate(true) noncanonical_plan["reason_traces"].reverse() assert_null(WorldEventRetentionPlan.from_dictionary(noncanonical_plan)) var invalid_record := rollup.to_dictionary() invalid_record["total_amount"] = -1.0 assert_null(WorldEventDailyRollupRecord.from_dictionary(invalid_record)) var false_source_checksum := serialized.duplicate(true) false_source_checksum["rollup_store"]["rollups"][0]["source_event_ids_checksum"] = ( JSON.stringify([3]).sha256_text() ) assert_null(WorldEventRetentionPlan.from_dictionary(false_source_checksum)) func test_planner_rejects_dangling_and_non_prior_causal_facts_without_mutation() -> void: var dangling := WorldEventStore.new() assert_true(dangling.append(_causal_transaction(1, 1, 99))) var dangling_before := dangling.to_dictionary() var planner := WorldEventRetentionPlanner.new() assert_null(planner.plan(dangling, 20, 10, 0, [&"storage_deposited"] as Array)) assert_string_contains(planner.get_last_error(), "missing causal fact 99") assert_eq(dangling.to_dictionary(), dangling_before) var forward := WorldEventStore.new() assert_true(forward.append(_causal_transaction(1, 5, 2))) assert_true(forward.append(_causal_transaction(2, 5, -1))) var forward_before := forward.to_dictionary() assert_null(planner.plan(forward, 20, 10, 0, [&"storage_deposited"] as Array)) assert_string_contains(planner.get_last_error(), "non-prior causal fact 2") assert_eq(forward.to_dictionary(), forward_before) func _transaction( event_id: int, event_type: StringName, tick: int, location_id: StringName, item_id: StringName, amount: float ) -> WorldEventRecord: return WorldEventRecord.create( event_id, event_type, tick, {}, _address(location_id), {"item_id": String(item_id), "amount": amount} ) func _causal_transaction(event_id: int, tick: int, cause_event_id: int) -> WorldEventRecord: return WorldEventRecord.create( event_id, &"storage_deposited", tick, {}, _address(&"village_pantry"), {"item_id": "food", "amount": 1.0, "cause_event_id": cause_event_id} ) func _address(location_id: StringName) -> SpatialAddress: return SpatialAddress.create(&"world_core", location_id, Vector3.ZERO) func _store_from_events(events: Array[WorldEventRecord]) -> WorldEventStore: var store := WorldEventStore.new() for event: WorldEventRecord in events: assert_true(store.append(event)) return store func _is_primitive_tree(value: Variant) -> bool: if value == null or value is bool or value is int or value is String: return true if value is float: return is_finite(value) if value is Array: for item: Variant in value: if not _is_primitive_tree(item): return false return true if value is Dictionary: for key: Variant in value: if not key is String or not _is_primitive_tree(value[key]): return false return true return false