Save The Tree implementation and acceptance work in progress

Preserve production code, regression fixtures, audio assets and provenance, test infrastructure, and the original-completion plan and progress ledger. Final game and Windows acceptance remain pending; excluded local artifacts and native experiments are not part of this snapshot.
This commit is contained in:
Takeshi
2026-10-11 15:58:00 +09:00
parent 39f6068461
commit b84bade045
235 changed files with 495831 additions and 312 deletions
+27
View File
@@ -28,6 +28,7 @@ func _run() -> void:
_test_service_need_effect_schema()
_test_path_failure_safe_recovery()
_test_exit_persistence_boundary()
_test_overdue_departure_snapshot()
_test_snapshot_round_trip_and_atomic_rejection()
_test_v1_need_migration_and_schema_rejection()
_test_deterministic_decision_snapshot()
@@ -583,6 +584,32 @@ func _test_exit_persistence_boundary() -> void:
_expect(not record.has(&"wallet_gold") and not record.has(&"needs") and not record.has(&"satisfaction_total"), "ordinary transient guest state does not survive despawn")
func _test_overdue_departure_snapshot() -> void:
for replan: bool in [false, true]:
var service := _service_with_definitions()
var guest := service.spawn_guest(&"overdue_deadline", &"adventurer", 0, {
&"state": GuestRuntimeType.State.DECIDING, &"planned_exit_at": 4,
})
_expect(guest != null, "overdue deadline fixture spawns through public GuestService")
if guest == null: continue
if replan:
_expect(bool(service.enter_queue(guest.guest_id, &"meal_room", &"overdue_request", 4, 1).get(&"ok", false)), "public queue entry before final patience")
_expect(bool(service.tick_queue_patience(guest.guest_id, 5, 0, func(_guest: StringName, _facility: StringName, _request: StringName): return true).get(&"ok", false)), "ordinary patience exhaustion after original deadline")
_expect(bool(service.transition_guest(guest.guest_id, GuestRuntimeType.State.DECIDING, 5, &"REPLAN_AFTER_INTERRUPTION").get(&"ok", false)), "public overdue replan retains deadline")
else:
_expect(bool(service.begin_leaving(guest.guest_id, 5, &"PLANNED_EXIT").get(&"ok", false)), "public leaving can occur after original deadline")
_expect(guest.planned_exit_at == 4 and guest.state_entered_at == 5 and guest.is_valid(), "deadline preserved independently of actual later state timestamp")
var snapshot := service.create_snapshot()
var restored := GuestServiceType.new()
_expect(restored.restore_snapshot(snapshot), "overdue ordinary state accepts complete restore")
_expect(var_to_bytes(restored.create_snapshot()) == var_to_bytes(snapshot), "overdue entire typed state roundtrip preserves original deadline")
for field: StringName in [&"planned_exit_at", &"state_entered_at"]:
var corrupt := snapshot.duplicate(true)
corrupt[&"guests"][0][field] = -1
_expect(not restored.restore_snapshot(corrupt), "negative departure/state timestamp remains rejected " + String(field))
_expect(var_to_bytes(restored.create_snapshot()) == var_to_bytes(snapshot), "negative timestamp rejection remains atomic " + String(field))
func _test_snapshot_round_trip_and_atomic_rejection() -> void:
var original := _service_with_definitions()
var moving := _moving_guest(original, &"guest_saved_moving")
+7 -1
View File
@@ -7,6 +7,7 @@ var _state: Variant
var _runtime: Variant
var _facility_id: StringName
var _facility_inventory_id: StringName
var _kitchen_fixture_gold := 0
func _initialize() -> void:
@@ -36,6 +37,7 @@ func _reset_runtime() -> void:
_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")
@@ -69,6 +71,10 @@ func _build_cafeteria() -> void:
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:
@@ -203,7 +209,7 @@ func _run_autonomous_guest_service_with_replay() -> void:
_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, "service revenue reaches authoritative player cash")
_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
+5 -2
View File
@@ -220,7 +220,7 @@ func _test_unreachable_staff_task_is_not_assigned() -> void:
func _test_shift_end_interrupts_and_fails_service() -> void:
_reset_runtime(3314)
var facility: FacilityInstance = _build_cafeteria()
var facility: FacilityInstance = _build_cafeteria(true)
if facility == null:
return
for staff_id: StringName in [&"short_cook", &"short_server"]:
@@ -356,7 +356,7 @@ func _test_corrupt_cross_domain_snapshots_are_atomic() -> void:
_expect(SimulationDigest.compute(_runtime.create_snapshot()) == before_digest, "dangling-Reservation rejection preserves the live digest")
func _build_cafeteria() -> FacilityInstance:
func _build_cafeteria(physical_kitchen_staff: bool = false) -> FacilityInstance:
var build = _runtime.submit_command(
&"build_facility",
{&"definition_id": &"cafeteria", &"origin": Vector3i(-5, 0, WorldService.LAYER_FRONT)},
@@ -371,6 +371,9 @@ func _build_cafeteria() -> FacilityInstance:
var facility_id := StringName(facilities[0].get(&"instance_id", ""))
var facility: FacilityInstance = _runtime.facility_service.get_instance(facility_id)
_expect(facility != null, "completed cafeteria registers with FacilityService")
if facility != null:
var kitchen_setup: Dictionary = load("res://tests/fixtures/required_kitchen_setup.gd").ensure(_runtime, _clock, facility.instance_id, physical_kitchen_staff)
_expect(bool(kitchen_setup.get(&"ok", false)), "public paid kitchen link uses scenario-selected physical or logical attendance")
return facility