extends SceneTree var _checks := 0 var _failures := 0 var _clock: Variant var _state: Variant var _runtime: Variant var _facility_id: StringName var _facility_inventory_id: StringName var _kitchen_fixture_gold := 0 func _initialize() -> void: call_deferred("_run") func _run() -> void: print("S3: integrated Guest and Staff runtime cycle") _reset_runtime() _build_cafeteria() _register_staff_and_run_task() _run_autonomous_guest_service_with_replay() _run_long_horizon_replay() _cleanup() if _failures == 0: print("PASS: %d checks" % _checks) else: push_error("FAIL: %d of %d checks failed" % [_failures, _checks]) quit(_failures) func _reset_runtime() -> void: _cleanup() _clock = load("res://autoload/game_clock.gd").new() _state = load("res://autoload/game_state.gd").new() _runtime = load("res://autoload/simulation_runtime.gd").new() _clock.reset(1, 6, 0) _state.reset() var report: Dictionary = _runtime.initialize(_clock, _state, 3303) _kitchen_fixture_gold = 0 _clock.set_paused(true) _expect(report[&"valid"], "runtime initializes S3 actor services") _expect(_runtime.guest_service.get_definitions().size() == 35, "runtime preserves three legacy archetypes and registers 32 MVP catalog archetypes") _expect(_runtime.guest_service.current_minute == _clock.absolute_minute, "Guest cadence starts aligned to the kernel") _expect(_runtime.staff_service.current_minute == _clock.absolute_minute, "Staff cadence starts aligned to the kernel") func _cleanup() -> void: if _runtime != null: _runtime.free() if _clock != null: _clock.free() if _state != null: _state.free() _runtime = null _clock = null _state = null func _build_cafeteria() -> void: var build = _runtime.submit_command( &"build_facility", {&"definition_id": &"cafeteria", &"origin": Vector3i(-5, 0, WorldService.LAYER_FRONT)}, &"player", &"", 50, -1, &"s3.runtime.build" ) _expect(build.is_success(), "cafeteria construction command succeeds") _clock.advance_minutes(180) var facilities: Array[Dictionary] = _runtime.construction_service.get_facilities() _expect(facilities.size() == 1, "construction completes before actor integration") _facility_id = StringName(facilities[0][&"instance_id"]) var facility = _runtime.facility_service.get_instance(_facility_id) _facility_inventory_id = facility.local_inventory_id _expect(facility.state == FacilityInstance.State.NO_STAFF, "unassigned S3 facility starts in NO_STAFF") var kitchen_setup: Dictionary = load("res://tests/fixtures/required_kitchen_setup.gd").ensure(_runtime, _clock, _facility_id) _expect(bool(kitchen_setup.get(&"ok", false)), "public paid kitchen setup/link with actual FLEX shift for S3") _kitchen_fixture_gold = int(kitchen_setup.get(&"gold_cost", -1)) _expect(_kitchen_fixture_gold > 0 and _runtime.economy_service.get_balance(&"CONSTRUCTION_EXPENSE") == 800 + _kitchen_fixture_gold and _runtime.economy_service.get_balance(&"PLAYER_CASH") == 4200 - _kitchen_fixture_gold and _state.get_resource(&"gold") == 4200 - _kitchen_fixture_gold, "actual additional paid kitchen/door cost matches both ledger accounts and Gold mirror") func _register_staff_and_run_task() -> void: var common_options := { &"current_cell": Vector3i(0, 0, WorldService.LAYER_FRONT), &"state": StaffRuntime.State.OFF_DUTY, &"permitted_task_tags": [&"service", &"work"], &"equipment_tags": [&"uniform"], } var cook_options: Dictionary = common_options.duplicate(true) cook_options[&"role_tags"] = [&"cook"] cook_options[&"skills"] = {&"cooking": 80, &"operation": 30} var server_options: Dictionary = common_options.duplicate(true) server_options[&"role_tags"] = [&"server"] server_options[&"skills"] = {&"service": 75, &"operation": 20} var cook = _runtime.submit_command( &"register_staff", {&"staff_id": &"cook_aya", &"role_id": &"cook", &"options": cook_options}, &"manager", &"cook_aya", 20, -1, &"s3.runtime.staff.cook" ) var server = _runtime.submit_command( &"register_staff", {&"staff_id": &"server_ren", &"role_id": &"server", &"options": server_options}, &"manager", &"server_ren", 20, -1, &"s3.runtime.staff.server" ) _expect(cook.is_success() and server.is_success(), "two StaffRuntime records register through commands") var start_minute := posmod(_clock.absolute_minute, 1_440) for staff_id: StringName in [&"cook_aya", &"server_ren"]: var shift = _runtime.submit_command( &"create_staff_shift", { &"staff_id": staff_id, &"template_id": &"FLEX", &"start_day": _clock.absolute_minute / 1_440, &"start_minute_of_day": start_minute, &"end_minute_of_day": start_minute + 600, &"facility_id": _facility_id, }, &"manager", staff_id, 20, -1, StringName("s3.runtime.shift.%s" % staff_id) ) _expect(shift.is_success(), "Flex Shift registers for %s" % staff_id) _clock.advance_one_minute() var facility = _runtime.facility_service.get_instance(_facility_id) _expect(facility.active_staff_ids == [&"cook_aya", &"server_ren"], "on-duty Staff project into FacilityService in stable ID order") _expect(facility.state == FacilityInstance.State.OPEN, "required S3 staffing opens the cafeteria") var tool = _runtime.submit_command( &"add_inventory_stack", { &"owner_inventory_id": _facility_inventory_id, &"item_id": &"tool/cleaning_kit", &"quantity": 1, }, &"manager", _facility_id, 10, -1, &"s3.runtime.tool" ) _expect(tool.is_success(), "facility receives a reservable Staff task tool") var task_result = _runtime.submit_command( &"create_staff_task", { &"task_id": &"clean_cafeteria", &"task_type": &"clean", &"priority": 70, &"options": { &"target_entity_id": _facility_id, &"target_cell": Vector3i(-1, 0, WorldService.LAYER_FRONT), &"required_role_tags": [&"server"], &"required_skill_min": {&"service": 10}, &"required_items": {&"tool/cleaning_kit": 1}, &"task_tags": [&"service"], &"estimated_minutes": 2, }, }, &"manager", _facility_id, 10, -1, &"s3.runtime.task" ) _expect(task_result.is_success(), "Staff task enters the runtime dispatcher") _clock.advance_minutes(8) var task = _runtime.staff_service.get_task(&"clean_cafeteria") _expect(task.state == StaffTask.State.COMPLETED, "runtime automatically dispatches, begins and completes the Staff task") _expect(_runtime.inventory_service.available_quantity(_facility_inventory_id, &"tool/cleaning_kit") == 1, "completed task releases its atomic tool Reservation") _expect(_runtime.staff_service.validate_invariants()[&"ok"], "integrated Staff task graph preserves bidirectional invariants") func _run_autonomous_guest_service_with_replay() -> void: var ingredient = _runtime.submit_command( &"add_inventory_stack", { &"owner_inventory_id": _facility_inventory_id, &"item_id": &"ingredient/basic_meal", &"quantity": 1, &"quality": 80, }, &"manager", _facility_id, 10, -1, &"s3.runtime.ingredient" ) _expect(ingredient.is_success(), "one service recipe is stocked") var spawn = _runtime.submit_command( &"spawn_guest", { &"guest_id": &"guest_mio", &"guest_type_id": &"traveler", &"gold": 150, &"options": { &"current_cell": Vector3i(0, 0, WorldService.LAYER_FRONT), &"needs": {&"hunger": 90, &"sleep": 20, &"hygiene": 20, &"medical": 0, &"leisure": 20, &"intimacy": 0}, &"planned_exit_at": _clock.absolute_minute + 240, }, }, &"world", &"guest_mio", 10, -1, &"s3.runtime.guest" ) _expect(spawn.is_success(), "spawn_guest atomically creates GuestRuntime and ledger wallet") _expect(_runtime.economy_service.get_balance(&"GUEST_WALLET:guest_mio") == 150, "Guest wallet is authoritative in EconomyService") var active_service: ServiceInstance = null for _minute in range(10): _clock.advance_one_minute() var active: Array = _runtime.facility_service.get_active_services(_facility_id) if not active.is_empty(): active_service = active[0] break _expect(active_service != null, "autonomous Guest reaches the facility queue and starts service") if active_service == null: return var guest = _runtime.guest_service.get_guest(&"guest_mio") _expect(guest.state == GuestRuntime.State.RECEIVING_SERVICE, "Facility service start atomically updates Guest state") _expect(guest.current_service_id == active_service.service_id, "Guest and Facility reference the same active service") var mid_snapshot: Dictionary = _runtime.create_snapshot() var mid_digest := SimulationDigest.compute(mid_snapshot) var duration := active_service.duration_minutes _clock.advance_minutes(duration) var completed = _runtime.facility_service.get_service(active_service.service_id) guest = _runtime.guest_service.get_guest(&"guest_mio") _expect(completed != null and completed.state == ServiceInstance.State.COMPLETED, "service completes after its immutable duration") _expect(guest != null and guest.satisfaction_samples == 1, "completion records exactly one Guest satisfaction sample") _expect(guest != null and int(guest.needs[&"hunger"]) < 40, "cafeteria completion applies its Need relief") _expect(_runtime.economy_service.get_balance(&"GUEST_WALLET:guest_mio") == 125, "Guest pays the quoted service price once") _expect(_runtime.economy_service.get_balance(&"PLAYER_CASH") == 4225 - _kitchen_fixture_gold, "service revenue reaches authoritative player cash") _expect(_runtime.inventory_service.total_quantity(_facility_inventory_id, &"ingredient/basic_meal") == 0, "service consumes exactly one reserved recipe input") var final_digest: String = _runtime.latest_digest _expect(_runtime.restore_snapshot(mid_snapshot), "mid-service S3 snapshot restores") _expect(_runtime.latest_digest == mid_digest, "S3 restore reproduces the exact mid-service digest") _clock.advance_minutes(duration) _expect(_runtime.latest_digest == final_digest, "replayed Guest, Staff, ledger and event transitions reproduce exactly") _expect(_runtime.economy_service.get_entries().filter( func(entry: LedgerEntry) -> bool: return entry.category == &"SERVICE_SALE" ).size() == 1, "replay records the service sale exactly once") func _run_long_horizon_replay() -> void: var horizon_snapshot: Dictionary = _runtime.create_snapshot() _clock.advance_minutes(1_440) var first_digest: String = _runtime.latest_digest var first_snapshot: Dictionary = _runtime.create_snapshot() _expect(_runtime.guest_service.validate_invariants()[&"valid"], "24-hour Guest graph has no orphan or illegal state") _expect(_runtime.staff_service.validate_invariants()[&"ok"], "24-hour Staff graph has no orphan reservation") _expect(_runtime.inventory_service.validate_invariants()[&"ok"], "24-hour actor simulation preserves Inventory invariants") _expect(_runtime.economy_service.validate_ledger()[&"ok"], "24-hour actor simulation keeps the ledger balanced") _expect(_runtime.restore_snapshot(horizon_snapshot), "long-horizon starting point restores") _clock.advance_minutes(1_440) _expect(_runtime.latest_digest == first_digest, "24-hour actor simulation is deterministic after restore") _expect(_runtime.create_snapshot() == first_snapshot, "24-hour replay reproduces the complete authoritative snapshot") func _expect(condition: bool, label: String) -> void: _checks += 1 if condition: print(" ✓ %s" % label) return _failures += 1 push_error(" ✗ %s" % label)