Record original-alignment implementation and traceability checkpoint

Capture current source, content data, tests, asset licenses, and original-specification traceability. Original implementation remains incomplete. The accepted matching UI generation passed 154 suites and 12,253 checks, with eight rendered staff-contract screens reviewed. Latest native Windows and full-original acceptance remain outstanding.
This commit is contained in:
Takeshi
2026-09-30 23:52:24 +09:00
parent 6077e02ebe
commit 5dde0c5ec2
490 changed files with 54051 additions and 809 deletions
@@ -0,0 +1,113 @@
extends SceneTree
# Regression for the observed midpoint restore order difference. No environment variables required.
# Full Runtime saved domain-event history preservation must be verified separately by strict whole-state replay.
const GuestDefinitionType = preload("res://scripts/guest/guest_definition.gd")
const GuestRuntimeType = preload("res://scripts/guest/guest_runtime.gd")
const GuestServiceType = preload("res://scripts/guest/guest_service.gd")
const EXPECTED_NEEDS: Array[StringName] = [
&"hunger", &"sleep", &"hygiene", &"medical", &"leisure", &"intimacy",
]
const VALUES := {&"hunger": 90, &"sleep": 90, &"hygiene": 10, &"medical": 20,
&"leisure": 90, &"intimacy": 90}
var checks := 0
var failures := 0
func _initialize() -> void:
call_deferred("_run")
func _run() -> void:
print("Guest observation restore-order regression")
var reversed_order := EXPECTED_NEEDS.duplicate()
reversed_order.reverse()
var reference_observation := PackedByteArray()
var reference_decision := PackedByteArray()
for index: int in range(2):
var order: Array = EXPECTED_NEEDS if index == 0 else reversed_order
var input: Dictionary = {}
for position: int in range(order.size()):
var need: StringName = order[position]
var key: Variant = String(need) if index == 1 and position % 2 == 0 else need
input[key] = VALUES[need]
var service := _service(input)
var guest := service.get_guest(&"observation_guest")
if guest == null:
_expect(false, "valid guest fixture registers")
continue
var raw_before := var_to_bytes(guest.needs)
var snapshot := service.create_snapshot()
var snapshot_bytes := var_to_bytes(snapshot)
var observation := service.get_observation(guest.guest_id)
_expect(observation[&"needs"].keys() == EXPECTED_NEEDS, "public needs order is stable for input %d" % index)
for need: Variant in observation[&"needs"]:
_expect(typeof(need) == TYPE_STRING_NAME and typeof(observation[&"needs"][need]) == TYPE_INT and observation[&"needs"][need] == VALUES[need],
"public need preserves StringName key, int type and exact value")
_expect(var_to_bytes(guest.needs) == raw_before, "observation preserves model input order and values")
_expect(var_to_bytes(service.create_snapshot()) == snapshot_bytes, "observation preserves complete service snapshot")
_expect(observation[&"primary_needs"] == [&"hunger", &"sleep", &"leisure", &"intimacy"], "all maximum ties retain PRIMARY_NEEDS order")
var observation_bytes := var_to_bytes(observation)
if index == 0:
reference_observation = observation_bytes
_expect(observation_bytes == reference_observation, "typed observation agrees across source order and key types")
observation[&"needs"][&"hunger"] = 0
observation[&"primary_needs"].clear()
_expect(var_to_bytes(guest.needs) == raw_before and var_to_bytes(service.create_snapshot()) == snapshot_bytes,
"caller mutation cannot change live model or saved state")
var restored := GuestServiceType.new()
_expect(restored.restore_snapshot(snapshot), "complete service snapshot restores")
var resumed := restored.get_guest(guest.guest_id)
if resumed == null:
_expect(false, "restored guest remains present")
continue
var saved_model: Dictionary = snapshot[&"guests"][0][&"needs"]
var restored_order: Array[StringName] = []
for key: Variant in saved_model:
restored_order.append(StringName(key))
_expect(resumed.needs.keys() == restored_order, "restore retains the snapshot input order, without model normalization")
var resumed_before := var_to_bytes(resumed.needs)
_expect(var_to_bytes(restored.get_observation(guest.guest_id)) == observation_bytes, "before/after restore typed observation is exact")
_expect(var_to_bytes(resumed.needs) == resumed_before and var_to_bytes(restored.create_snapshot()) == snapshot_bytes,
"restored observation does not mutate model or save serialization")
var food := _candidate(&"aa_food", &"hunger")
var room := _candidate(&"zz_room", &"sleep")
var food_score := service.evaluate_candidate(guest.guest_id, food)
var room_score := service.evaluate_candidate(guest.guest_id, room)
for field: StringName in [&"need_priority", &"utility", &"urgency", &"travel_minutes"]:
_expect(food_score[field] == room_score[field], "fixture reaches the final facility ID tie break: " + String(field))
var uninterrupted := service.decide(guest.guest_id, [room, food], 1)
var replay := restored.decide(guest.guest_id, [food, room], 1)
_expect(bool(uninterrupted.get(&"ok", false)) and uninterrupted.get(&"candidate", {}).get(&"facility_id", &"") == &"aa_food",
"equal need scores use the stable lexical facility ID")
_expect(var_to_bytes(uninterrupted) == var_to_bytes(replay), "restored decision and reversed candidates agree with all typed result fields")
_expect(var_to_bytes(service.create_snapshot()) == var_to_bytes(restored.create_snapshot()), "complete post-decision service snapshots agree")
if index == 0:
reference_decision = var_to_bytes(uninterrupted)
_expect(var_to_bytes(uninterrupted) == reference_decision, "all source orders and key types preserve the full decision")
print("Guest observation restore-order diagnostic: %d checks, %d failures" % [checks, failures])
quit(0 if failures == 0 else 1)
func _service(needs: Dictionary) -> GuestService:
var service := GuestServiceType.new()
var definition := GuestDefinitionType.new().configure(&"observation_type", {
&"wealth_min": 1000, &"wealth_max": 1000, &"minimum_quality": 0,
&"risk_tolerance": 100, &"legal_sensitivity": 0,
})
_expect(service.register_definition(definition), "valid definition registers")
var guest := service.spawn_guest(&"observation_guest", &"observation_type", 0, {
&"state": GuestRuntimeType.State.DECIDING, &"wallet_gold": 1000,
&"planned_exit_at": 1000, &"needs": needs,
})
_expect(guest != null, "valid guest spawns")
return service
func _candidate(id: StringName, need: StringName) -> Dictionary:
return {&"facility_id": id, &"is_open": true, &"reachable": true,
&"price_gold": 10, &"wait_minutes": 0, &"travel_minutes": 5,
&"risk_level": 0, &"illegal_level": 0, &"expected_quality": 100,
&"need_relief": {need: 80}}
func _expect(condition: bool, label: String) -> void:
checks += 1
if not condition:
failures += 1
push_error(label)
@@ -0,0 +1 @@
uid://tdsph6wcj85t
+52
View File
@@ -21,6 +21,7 @@ func _run() -> void:
_test_batched_need_updates_match_individual_api()
_test_candidate_filtering()
_test_integer_utility_and_stable_tie_break()
_test_primary_need_priority()
_test_state_machine_and_loop_guard()
_test_atomic_queue_abandonment()
_test_service_interruption_is_idempotent()
@@ -776,3 +777,54 @@ func _expect(condition: bool, label: String) -> void:
return
_failures += 1
push_error(" ✗ %s" % label)
func _test_primary_need_priority() -> void:
var service := _service_with_definitions()
var guest := service.spawn_guest(&"need_priority", &"adventurer", 0, {
&"wallet_gold": 1000, &"planned_exit_at": 1000,
&"state": GuestRuntime.State.DECIDING,
&"needs": {&"hunger": 90, &"sleep": 70},
})
var food := _candidate(&"food", {&"need_relief": {&"hunger": 80}, &"expected_quality": 40})
var room := _candidate(&"room", {&"need_relief": {&"sleep": 90}, &"expected_quality": 100, &"preference": 100})
_expect(service.evaluate_candidate(guest.guest_id, room)[&"utility"] > service.evaluate_candidate(guest.guest_id, food)[&"utility"], "regression scenario has a tempting lower-need facility")
_expect(service.select_best_candidate(guest.guest_id, [room,food])[&"facility_id"] == &"food", "highest need precedes quality and preference bonuses")
var near_food := food.duplicate(true)
near_food[&"facility_id"] = &"near_food"
near_food[&"travel_minutes"] = 1
food[&"travel_minutes"] = 20
_expect(service.select_best_candidate(guest.guest_id, [food,near_food])[&"facility_id"] == &"near_food", "same need still compares distance")
for field: StringName in [&"wait_minutes", &"price_burden"]:
var costly := near_food.duplicate(true)
costly[&"facility_id"] = &"costly"
costly[field] = 100
_expect(service.select_best_candidate(guest.guest_id, [costly,near_food])[&"facility_id"] == &"near_food", "same need still compares queue or price")
var unavailable := food.duplicate(true)
unavailable[&"reachable"] = false
var accepted := service.extract_candidates(guest.guest_id, [unavailable,room])
_expect(service.select_best_candidate(guest.guest_id, accepted)[&"facility_id"] == &"room", "unreachable highest-need facility does not block a usable alternative")
unavailable[&"reachable"] = true
unavailable[&"price_gold"] = 100000
accepted = service.extract_candidates(guest.guest_id, [unavailable,room])
_expect(service.select_best_candidate(guest.guest_id, accepted)[&"facility_id"] == &"room", "highest need does not bypass affordability")
var unattractive := food.duplicate(true)
unattractive[&"travel_minutes"] = 10000
_expect(service.select_best_candidate(guest.guest_id, [unattractive,room])[&"facility_id"] == &"room", "below-threshold high-need candidate does not stop fallback search")
guest.needs[&"sleep"] = 90
_expect(service.select_best_candidate(guest.guest_id, [food,room])[&"facility_id"] == &"room", "equal highest needs use the existing utility comparison")
guest.needs[&"sleep"] = 70
var before := service.create_snapshot()
var observed := service.get_observation(guest.guest_id)
observed[&"needs"][&"hunger"] = 0
_expect(guest.needs[&"hunger"] == 90 and service.create_snapshot() == before, "observation is read-only and owns its dictionaries")
_expect(service.restore_snapshot(before), "pre-decision save restores")
var replay := service.decide(guest.guest_id, [room,food], 1)
_expect(replay[&"candidate"][&"facility_id"] == &"food", "restored runtime uses the same highest-need decision")
var after := service.create_snapshot()
_expect(service.restore_snapshot(before), "decision can be replayed from snapshot")
service.decide(guest.guest_id, [food,room], 1)
_expect(service.create_snapshot() == after, "candidate insertion order cannot change saved decision state")
_expect(service.restore_snapshot(before), "reservation retry starts at the same state")
var reserved := service.decide(guest.guest_id, [food,room], 1, {&"reserve_callback": func(_id: StringName, facility: StringName, _candidate: Dictionary) -> bool: return facility != &"food"})
_expect(reserved[&"candidate"][&"facility_id"] == &"room", "failed reservation tries the next usable candidate")
+7 -6
View File
@@ -150,12 +150,12 @@ func _test_congestion_credit_and_alternate_route() -> void:
var after_one: Array[Vector3i] = _guest_cells_with_prefix("slow_")
_expect(after_one.all(func(cell: Vector3i) -> bool: return cell == origin), "over-capacity speed credit prevents a first-minute burst")
_expect(
int(_runtime.get_actor_movement_credit(&"guest:slow_00").get(&"credit", -1)) == 250,
int(_runtime.get_actor_movement_credit(&"guest:slow_00").get(&"credit", -1)) == 500,
"Path speed multiplier is stored as deterministic fixed-point credit"
)
_clock.advance_minutes(3)
var after_four: Array[Vector3i] = _guest_cells_with_prefix("slow_")
_expect(after_four.all(func(cell: Vector3i) -> bool: return cell != origin), "minimum speed guarantees progress by the fourth congested minute")
_clock.advance_minutes(1)
var after_two: Array[Vector3i] = _guest_cells_with_prefix("slow_")
_expect(after_two.all(func(cell: Vector3i) -> bool: return cell != origin), "half speed guarantees progress by the second congested minute")
_expect(_runtime.path_service.get_current_density(origin) == 0, "sequential committed movement lowers source density exactly")
_reset_runtime(8_103)
@@ -318,7 +318,7 @@ func _test_current_snapshot_crosslinks_and_legacy_v2() -> void:
_clock.advance_one_minute()
var snapshot: Dictionary = _runtime.create_snapshot()
var runtime_data: Dictionary = snapshot[&"systems"][&"runtime"]
_expect(int(runtime_data[&"runtime_schema_version"]) == 9, "Runtime snapshot advertises schema v9")
_expect(int(runtime_data[&"runtime_schema_version"]) == 13, "Runtime snapshot advertises schema v13")
_expect(not runtime_data[&"movement_credits"].is_empty(), "mid-move snapshot persists fixed-point movement credits")
var digest := SimulationDigest.compute(snapshot)
_expect(_runtime.restore_snapshot(snapshot), "valid mid-move v9 snapshot restores")
@@ -358,6 +358,7 @@ func _test_current_snapshot_crosslinks_and_legacy_v2() -> void:
var legacy_data: Dictionary = legacy_v2[&"systems"][&"runtime"]
legacy_data[&"runtime_schema_version"] = 2
_strip_post_v2_runtime_state(legacy_data)
preload("res://tests/fixtures/pre_upkeep_runtime.gd").strip_empty_upkeep(legacy_data)
legacy_data[&"path"][&"schema_version"] = 3
legacy_data[&"path"].erase(&"vertical_walk_blockers")
legacy_data[&"path"].erase(&"vertical_walk_requires_connector")
@@ -375,7 +376,7 @@ func _test_current_snapshot_crosslinks_and_legacy_v2() -> void:
_expect(_runtime.restore_snapshot(legacy_v2), "legacy Runtime v2 deterministically rebuilds Path actors and credits")
var migrated: Dictionary = _runtime.create_snapshot()
_expect(
int(migrated[&"systems"][&"runtime"][&"runtime_schema_version"]) == 9
int(migrated[&"systems"][&"runtime"][&"runtime_schema_version"]) == 13
and migrated[&"systems"][&"runtime"][&"path"][&"actor_cells"].size() == 2
and migrated[&"systems"][&"runtime"][&"movement_credits"].size() == 2
and bool(_runtime.path_service.get_cell_traffic(origin)[&"temporary_block"]),
+24 -2
View File
@@ -29,6 +29,7 @@ func _run() -> void:
_test_automatic_task_progression_once_per_tick()
_test_employment_and_daily_payroll_contract()
_test_retirement_preserves_unpaid_wages()
_test_unique_employment_protection()
_test_daily_payroll_settlement_lifecycle()
_test_payroll_validation_and_idempotency()
_test_payroll_snapshot_migration_and_tamper()
@@ -384,11 +385,11 @@ func _test_employment_and_daily_payroll_contract() -> void:
)
var expected_rows: Array[Dictionary] = [
{&"staff_id": &"staff_a", &"employment_kind": &"ADULT_CONTRACT", &"daily_wage": 240},
{&"staff_id": &"staff_m", &"employment_kind": &"UNIQUE", &"daily_wage": 75},
{&"staff_id": &"staff_m", &"employment_kind": &"UNIQUE", &"daily_wage": 0},
{&"staff_id": &"staff_z", &"employment_kind": &"FREE_HIRE", &"daily_wage": 0},
]
_expect(service.get_daily_payroll_rows() == expected_rows, "daily payroll rows have an exact shape and lexical Staff order")
_expect(service.get_daily_payroll_total() == 315, "daily payroll total is the exact sum of active Staff wages")
_expect(service.get_daily_payroll_total() == 240, "daily payroll total is the exact sum of active Staff wages")
var invalid_service := StaffServiceType.new()
_expect(
@@ -828,3 +829,24 @@ func _expect(condition: bool, label: String) -> void:
return
_failures += 1
push_error(" ✗ %s" % label)
func _test_unique_employment_protection() -> void:
var service := StaffServiceType.new()
var unique := _staff(&"original_unique", 10, {&"employment_kind": &"UNIQUE", &"daily_wage": 75, &"unpaid_wages": 25})
_expect(service.register_staff(unique).is_success(), "legacy unique with stored wage remains loadable")
var before := service.create_snapshot()
for reason: StringName in [&"DISMISSED", &"SOLD", &"REMOVED"]:
_expect(not service.remove_staff(unique.staff_id, reason).is_success() and service.create_snapshot() == before, "unique removal is rejected atomically for %s" % reason)
_expect(not service.retire_staff(unique.staff_id).is_success() and not unique.is_retiring and service.create_snapshot() == before, "unique retirement rejects before setting retirement flag")
var preview := service.preview_daily_payroll(1)
_expect(preview[&"ok"] and preview[&"new_wages_total"] == 0 and preview[&"prior_arrears_total"] == 25 and preview[&"total_due"] == 25, "unique accrues zero wages without silently deleting historical liabilities")
_expect(service.get_daily_payroll_total() == 0 and service.get_payroll_obligations()[0][&"daily_wage"] == 0, "all payroll views use unique zero upkeep")
var restored := StaffServiceType.new()
_expect(restored.restore_snapshot(before) and restored.create_snapshot() == before and restored.get_daily_payroll_total() == 0, "unique zero-upkeep rule survives exact save round trip")
_expect(not restored.retire_staff(unique.staff_id).is_success() and restored.create_snapshot() == before, "restored unique remains protected against removal")
_expect(restored.apply_daily_payroll_settlement(&"unique_day1", 1, {unique.staff_id: 25}).is_success(), "unique settlement pays only preserved historical arrears")
_expect(restored.get_staff(unique.staff_id).unpaid_wages == 0 and restored.get_payroll_settlement(&"unique_day1")[&"new_wages_total"] == 0, "unique settlement adds no new upkeep")
var settled := restored.create_snapshot()
_expect(restored.apply_daily_payroll_settlement(&"unique_day1", 1, {unique.staff_id: 25}).is_success() and restored.create_snapshot() == settled, "unique settlement retry is idempotent")
_expect(restored.preview_daily_payroll(2)[&"total_due"] == 0, "following day keeps unique upkeep free")