extends SceneTree const StaffRuntimeType = preload("res://scripts/staff/staff_runtime.gd") const ShiftInstanceType = preload("res://scripts/staff/shift_instance.gd") const StaffTaskType = preload("res://scripts/staff/staff_task.gd") const TaskDispatcherType = preload("res://scripts/staff/task_dispatcher.gd") const StaffServiceType = preload("res://scripts/staff/staff_service.gd") var _checks := 0 var _failures := 0 func _initialize() -> void: call_deferred("_run") func _run() -> void: print("S3: Staff Shift and Task Dispatcher") _test_night_shift_crosses_midnight() _test_shift_state_machine_and_override() _test_multiple_future_shifts_and_strict_overlap() _test_deterministic_dispatch_and_pair_reservation() _test_skill_score_and_tie_break() _test_item_reservation_failure_is_atomic() _test_interrupt_levels() _test_fatigue_blocks_dangerous_tasks() _test_missing_staff_reopens_task() _test_task_progression() _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() _test_remove_staff_cleans_schedule_graph() _test_snapshot_round_trip_and_atomic_restore() _test_orphan_recovery_is_atomic() if _failures == 0: print("PASS: %d checks" % _checks) else: push_error("FAIL: %d of %d checks failed" % [_failures, _checks]) quit(_failures) func _test_night_shift_crosses_midnight() -> void: var shift := ShiftInstanceType.create_standard( &"night_d2", &"staff_night", &"NIGHT", 2, &"warehouse" ) _expect(shift != null and shift.is_valid(), "standard NIGHT Shift is valid") _expect(shift.start_day == 2 and shift.shift_instance_id == &"night_d2", "overnight Shift keeps its start-day identity") _expect(shift.start_at == 3_960 and shift.end_at == 4_680, "NIGHT uses exact absolute-minute bounds") _expect(shift.crosses_midnight(), "NIGHT is marked as crossing midnight") _expect(shift.contains_minute(4_379), "same Shift contains time before calendar midnight") _expect(shift.contains_minute(4_380), "same Shift contains time after calendar midnight") _expect(not shift.contains_minute(4_680), "Shift end minute is exclusive") shift.record_duty_minute(4_379) shift.record_duty_minute(4_380) _expect(shift.worked_minutes == 2, "work on both calendar dates aggregates into one Shift") var restored := ShiftInstanceType.from_snapshot(shift.create_snapshot()) _expect(restored != null and restored.create_snapshot() == shift.create_snapshot(), "overnight Shift snapshot round trip is exact") func _test_shift_state_machine_and_override() -> void: var service := StaffServiceType.new() var staff := _staff( &"shift_worker", 0, {&"state": StaffRuntimeType.State.OFF_DUTY} ) _expect(service.register_staff(staff).is_success(), "Staff registers before scheduling") _expect( service.set_schedule_override( staff.staff_id, 1, {&"start_minute_of_day": 420, &"end_minute_of_day": 900} ).is_success(), "one-day ScheduleOverride is stored separately" ) _expect( service.create_standard_shift(staff.staff_id, &"DAY", 1, &"reception", &"shift_override").is_success(), "standard Shift instance accepts a one-day override" ) var shift := service.get_shift(&"shift_override") _expect(shift.start_minute_of_day == 420 and shift.end_minute_of_day == 900, "override changes only the concrete Shift times") _expect(shift.template_id == &"DAY", "ScheduleOverride does not rewrite the base template ID") service.advance_one_minute(1_830) _expect(staff.state == StaffRuntimeType.State.COMMUTING, "Staff starts commuting exactly 30 minutes before Shift") service.advance_one_minute(1_860) _expect(staff.state == StaffRuntimeType.State.AVAILABLE, "Staff becomes available at Shift start") _expect(staff.assigned_facility_id == &"reception", "Shift assigns the work facility") service.advance_one_minute(2_340) _expect(staff.state == StaffRuntimeType.State.OFF_DUTY and staff.shift_id.is_empty(), "Staff goes off duty at Shift end") _expect(shift.actual_ended_at == 2_340, "Shift records its exact end transition") func _test_multiple_future_shifts_and_strict_overlap() -> void: var service := StaffServiceType.new() var staff := _staff(&"multi_shift_worker", 10, {&"state": StaffRuntimeType.State.OFF_DUTY}) _expect(service.register_staff(staff).is_success(), "Staff registers for multiple future Shifts") _expect( service.create_flex_shift(staff.staff_id, 1, 540, 600, &"workshop", &"shift_second").is_success(), "later future Shift can be registered first" ) _expect( service.create_flex_shift(staff.staff_id, 1, 420, 480, &"reception", &"shift_first").is_success(), "earlier non-overlapping Shift can be registered second" ) _expect(staff.shift_id.is_empty(), "future Shift registration does not overwrite the active Shift pointer") service.advance_one_minute(1_830) _expect( staff.shift_id == &"shift_first" and staff.state == StaffRuntimeType.State.COMMUTING, "chronologically first Shift enters COMMUTING at its commute boundary" ) service.advance_one_minute(1_860) var first := service.get_shift(&"shift_first") _expect( staff.shift_id == first.shift_instance_id and staff.state == StaffRuntimeType.State.AVAILABLE, "chronologically first Shift becomes ACTIVE at start" ) _expect(first.actual_started_at == 1_860 and staff.assigned_facility_id == &"reception", "first Shift records start and facility") service.advance_one_minute(1_920) _expect( first.actual_ended_at == 1_920 and staff.shift_id.is_empty() and staff.state == StaffRuntimeType.State.OFF_DUTY, "first Shift becomes COMPLETED and releases its active pointer" ) service.advance_one_minute(1_950) _expect( staff.shift_id == &"shift_second" and staff.state == StaffRuntimeType.State.COMMUTING, "second future Shift becomes the active commute after the first completes" ) service.advance_one_minute(1_980) var second := service.get_shift(&"shift_second") _expect( staff.shift_id == second.shift_instance_id and staff.state == StaffRuntimeType.State.AVAILABLE, "second Shift becomes ACTIVE in sequence" ) service.advance_one_minute(2_040) _expect( second.actual_ended_at == 2_040 and staff.shift_id.is_empty() and staff.state == StaffRuntimeType.State.OFF_DUTY, "second Shift becomes COMPLETED in sequence" ) _expect(service.validate_invariants()[&"ok"], "multiple completed Shift records preserve invariants") var overlap_service := StaffServiceType.new() var overlap_staff := _staff(&"overlap_worker", 10, {&"state": StaffRuntimeType.State.OFF_DUTY}) overlap_service.register_staff(overlap_staff) overlap_service.create_flex_shift(overlap_staff.staff_id, 2, 420, 480, &"a", &"base_shift") _expect( not overlap_service.create_flex_shift(overlap_staff.staff_id, 2, 400, 430, &"b", &"overlap_left").is_success(), "overlap is rejected when the proposed Shift starts before the existing Shift" ) _expect( not overlap_service.create_flex_shift(overlap_staff.staff_id, 2, 470, 500, &"b", &"overlap_right").is_success(), "overlap is rejected when the proposed Shift starts inside the existing Shift" ) _expect( not overlap_service.create_flex_shift(overlap_staff.staff_id, 2, 400, 500, &"b", &"overlap_enclosing").is_success(), "overlap is rejected when the proposed Shift encloses the existing Shift" ) _expect( overlap_service.create_flex_shift(overlap_staff.staff_id, 2, 480, 510, &"b", &"adjacent_shift").is_success(), "exactly adjacent half-open Shift intervals are accepted" ) func _test_deterministic_dispatch_and_pair_reservation() -> void: var service := StaffServiceType.new() service.register_staff(_staff(&"staff_b", 10)) service.register_staff(_staff(&"staff_a", 10)) service.register_task(_task(&"task_b", 50, 100)) service.register_task(_task(&"task_a", 50, 100)) var report: Dictionary = service.dispatch_now(100) _expect(report[&"assigned"].size() == 2, "dispatcher fills two eligible Staff reservations") _expect(report[&"assigned"][0][&"task_id"] == &"task_a", "Task tie breaks lexically after priority and deadline") _expect(report[&"assigned"][0][&"staff_id"] == &"staff_a", "Staff score tie breaks lexically") _expect(report[&"assigned"][1][&"task_id"] == &"task_b", "second Task remains in deterministic order") _expect(report[&"assigned"][1][&"staff_id"] == &"staff_b", "one Staff is not assigned twice in one dispatch pass") var task_a := service.get_task(&"task_a") var staff_a := service.get_staff(&"staff_a") _expect(task_a.assigned_staff_id == staff_a.staff_id, "Task points to its reserved Staff") _expect(staff_a.current_task_id == task_a.task_id, "Staff points back to its reserved Task") _expect(service.validate_invariants()[&"ok"], "dispatcher preserves Task/Staff bidirectional invariant") func _test_skill_score_and_tie_break() -> void: var dispatcher := TaskDispatcherType.new() var task := _task(&"skill_task", 40, 0, { &"required_skill_min": {&"operation": 5}, }) var novice := _staff(&"novice", 5) var expert := _staff(&"expert", 30) var novice_score := dispatcher.score_candidate(task, novice, 2) var expert_score := dispatcher.score_candidate(task, expert, 2) _expect(expert_score > novice_score, "higher matching Skill raises StaffTaskScore") _expect( dispatcher.score_candidate(task, expert, 5) < dispatcher.score_candidate(task, expert, 2), "longer travel lowers StaffTaskScore with integer-minute penalty" ) expert.is_overtime = true _expect(dispatcher.score_candidate(task, expert, 2) < expert_score, "overtime applies a deterministic score penalty") func _test_item_reservation_failure_is_atomic() -> void: var service := StaffServiceType.new() var reserve_calls := [0] service.configure_callbacks( func(_task_value: StaffTask, _minute: int) -> Dictionary: reserve_calls[0] += 1 return {&"ok": false, &"reason": &"NO_STOCK"}, func(_ids: Array[StringName], _task_value: StaffTask, _minute: int) -> bool: return true ) var staff := _staff(&"stock_worker", 10) service.register_staff(staff) var task := _task(&"stock_task", 80, 0, {&"required_items": {&"meal": 2}}) service.register_task(task) var report: Dictionary = service.dispatch_now(0) _expect(reserve_calls[0] == 1 and report[&"blocked"].size() == 1, "required items are reserved before Staff mutation") _expect(task.state == StaffTaskType.State.BLOCKED and task.assigned_staff_id.is_empty(), "stock failure sends Task to BLOCKED without half reservation") _expect(staff.state == StaffRuntimeType.State.AVAILABLE and staff.current_task_id.is_empty(), "stock failure leaves Staff fully available") _expect(service.validate_invariants()[&"ok"], "failed item transaction preserves Staff invariants") func _test_interrupt_levels() -> void: var protected_service := StaffServiceType.new() var protected_staff := _staff(&"protected_worker", 10) protected_service.register_staff(protected_staff) var protected_task := _task(&"protected_task", 20, 0, {&"interrupt_level": 0}) protected_service.register_task(protected_task) protected_service.dispatch_now(0) protected_service.begin_task(protected_task.task_id, 0) var replacement := _task(&"replacement", 100, 1, {&"emergency": true}) protected_service.register_task(replacement) var protected_report: Dictionary = protected_service.dispatch_now(1) _expect(protected_report[&"assigned"].is_empty(), "interrupt level 0 rejects even emergency replacement") _expect(protected_task.state == StaffTaskType.State.WORKING and protected_staff.current_task_id == protected_task.task_id, "non-interruptible Task/Staff pair remains untouched") var emergency_service := StaffServiceType.new() var emergency_staff := _staff(&"response_worker", 10) emergency_service.register_staff(emergency_staff) var level_one := _task(&"level_one", 20, 0, {&"interrupt_level": 1}) emergency_service.register_task(level_one) emergency_service.dispatch_now(0) emergency_service.begin_task(level_one.task_id, 0) var normal := _task(&"normal_high", 100, 1, {&"emergency": false}) var emergency := _task(&"emergency", 99, 1, {&"emergency": true}) emergency_service.register_task(normal) emergency_service.register_task(emergency) var emergency_report: Dictionary = emergency_service.dispatch_now(1) _expect(emergency_report[&"assigned"].size() == 1 and emergency_report[&"assigned"][0][&"task_id"] == &"emergency", "interrupt level 1 accepts only emergency Task") _expect(level_one.state == StaffTaskType.State.OPEN and level_one.assigned_staff_id.is_empty(), "interrupted Task returns atomically to OPEN") _expect(emergency_staff.current_task_id == emergency.task_id and emergency.assigned_staff_id == emergency_staff.staff_id, "replacement Task and Staff reserve together") _expect(emergency_service.validate_invariants()[&"ok"], "interrupt transaction preserves pair invariants") func _test_fatigue_blocks_dangerous_tasks() -> void: var service := StaffServiceType.new() var exhausted := _staff(&"exhausted", 20, {&"fatigue": 90}) service.register_staff(exhausted) var dangerous := _task(&"dangerous", 100, 0, {&"dangerous": true}) var safe := _task(&"rest_break", 90, 0, {&"dangerous": false, &"task_tags": [&"rest"]}) service.register_task(dangerous) service.register_task(safe) var report: Dictionary = service.dispatch_now(0) _expect(dangerous.state == StaffTaskType.State.OPEN and dangerous.assigned_staff_id.is_empty(), "fatigue 90 forbids dangerous Task assignment") _expect(report[&"assigned"].size() == 1 and safe.assigned_staff_id == exhausted.staff_id, "fatigued Staff can still receive a safe rest Task") _expect(exhausted.current_task_id == safe.task_id, "safe Task reserves the fatigued Staff atomically") func _test_missing_staff_reopens_task() -> void: var service := StaffServiceType.new() var released_ids: Array[StringName] = [] service.configure_callbacks( func(task: StaffTask, _minute: int) -> Dictionary: return {&"ok": true, &"reservation_ids": [StringName("reserve_%s" % task.task_id)]}, func(ids: Array[StringName], _task_value: StaffTask, _minute: int) -> bool: for reservation_id: StringName in ids: released_ids.append(reservation_id) return true ) var staff := _staff(&"vanishing_staff", 10) var task := _task(&"orphan_task", 60, 0, {&"required_items": {&"tool": 1}}) service.register_staff(staff) service.register_task(task) service.dispatch_now(0) _expect(task.state == StaffTaskType.State.RESERVED and task.reservation_ids.size() == 1, "Task owns item Reservation after successful dispatch") service._staff.erase(staff.staff_id) var audit: Dictionary = service.audit_orphan_tasks(1) _expect(audit[&"reopened_task_ids"] == [&"orphan_task"], "orphan audit reports vanished Staff Task") _expect(task.state == StaffTaskType.State.OPEN and task.assigned_staff_id.is_empty(), "vanished Staff Task returns to OPEN") _expect(task.reservation_ids.is_empty() and released_ids == [&"reserve_orphan_task"], "orphan recovery releases every item Reservation") _expect(service.validate_invariants()[&"ok"], "orphan recovery restores all Staff invariants") func _test_task_progression() -> void: var service := StaffServiceType.new() var staff := _staff(&"progress_worker", 10) var task := _task(&"progress_task", 50, 0, {&"estimated_minutes": 2}) service.register_staff(staff) service.register_task(task) service.dispatch_now(0) _expect(service.begin_task(task.task_id, 1).is_success(), "reserved Task enters WORKING with its Staff") var first = service.progress_task(task.task_id, 1, 2) _expect(first.is_success() and not first.details[&"completed"], "Task remains WORKING before estimated duration") var second = service.progress_task(task.task_id, 1, 3) _expect(second.is_success() and second.details[&"completed"], "Task completes exactly at estimated duration") _expect(task.state == StaffTaskType.State.COMPLETED and staff.current_task_id.is_empty(), "completion releases Staff while Task becomes terminal") _expect(staff.state == StaffRuntimeType.State.AVAILABLE, "completed Task returns on-duty Staff to AVAILABLE") func _test_automatic_task_progression_once_per_tick() -> void: var service := StaffServiceType.new() var staff := _staff(&"auto_worker", 10) var task := _task(&"auto_task", 50, 0, {&"estimated_minutes": 2}) service.register_staff(staff) service.register_task(task) service.dispatch_now(0) var begin_tick: Dictionary = service.advance_one_minute(1) _expect( begin_tick[&"task_actions"].size() == 1 and begin_tick[&"task_actions"][0][&"action"] == &"BEGAN_WORK", "automatic cadence begins a RESERVED Task after its assignment minute" ) _expect(task.state == StaffTaskType.State.WORKING and task.progress_minutes == 0, "begin tick does not also consume a work minute") _expect(not service.progress_task(task.task_id, 1, 1).is_success(), "explicit same-minute progress cannot double apply after automatic begin") _expect(not service.advance_one_minute(1)[&"ok"], "the same StaffService minute cannot run twice") _expect(task.progress_minutes == 0, "duplicate tick rejection preserves Task progress") var progress_tick: Dictionary = service.advance_one_minute(2) _expect( progress_tick[&"task_actions"][0][&"action"] == &"PROGRESSED" and task.progress_minutes == 1, "the following tick applies exactly one work minute" ) _expect(not service.progress_task(task.task_id, 1, 2).is_success(), "automatic progress blocks a second same-minute write") service.advance_one_minute(3) _expect(task.state == StaffTaskType.State.COMPLETED and task.progress_minutes == 2, "automatic cadence completes at the exact estimated duration") _expect(staff.state == StaffRuntimeType.State.AVAILABLE and staff.current_task_id.is_empty(), "automatic completion releases Staff exactly once") var travel_service := StaffServiceType.new() var traveler := _staff(&"travel_worker", 10, {&"current_cell": Vector3i.ZERO}) var remote := _task(&"remote_task", 50, 0, { &"target_cell": Vector3i(2, 0, 0), &"estimated_minutes": 1, }) travel_service.register_staff(traveler) travel_service.register_task(remote) travel_service.dispatch_now(0) travel_service.advance_one_minute(1) _expect(remote.state == StaffTaskType.State.MOVING and remote.progress_minutes == 0, "non-arrived Staff enters MOVING without phantom work") traveler.current_cell = remote.target_cell travel_service.advance_one_minute(2) _expect(remote.state == StaffTaskType.State.WORKING and remote.progress_minutes == 0, "arrival begins work without same-tick progress") travel_service.advance_one_minute(3) _expect(remote.state == StaffTaskType.State.COMPLETED, "arrived Staff completes through the same deterministic cadence") func _test_employment_and_daily_payroll_contract() -> void: var ordinary := _staff(&"staff_z", 10) _expect( ordinary.daily_wage == 0 and ordinary.employment_kind == StaffRuntimeType.EmploymentKind.FREE_HIRE, "legacy generic Staff defaults to a zero-wage FREE_HIRE employment row" ) var service := StaffServiceType.new() _expect(service.register_staff(ordinary).is_success(), "generic Staff remains registrable without adult-content fields") _expect( service.register_staff(_staff(&"staff_a", 10, { &"daily_wage": 240, &"employment_kind": &"ADULT_CONTRACT", })).is_success(), "ADULT_CONTRACT is accepted as a commercial kind without duplicating the catalog gate" ) _expect( service.register_staff(_staff(&"staff_m", 10, { &"daily_wage": 75, &"employment_kind": StaffRuntimeType.EmploymentKind.UNIQUE, })).is_success(), "UNIQUE employment accepts the strict enum value" ) 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": 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() == 240, "daily payroll total is the exact sum of active Staff wages") var invalid_service := StaffServiceType.new() _expect( not invalid_service.register_staff(_staff(&"string_wage", 10, {&"daily_wage": "100"})).is_success(), "string daily wage is rejected rather than coerced" ) _expect( not invalid_service.register_staff(_staff(&"float_wage", 10, {&"daily_wage": 10.0})).is_success(), "floating-point daily wage is rejected rather than truncated" ) _expect( not invalid_service.register_staff(_staff(&"negative_wage", 10, {&"daily_wage": -1})).is_success(), "negative daily wage is rejected" ) _expect( not invalid_service.register_staff(_staff(&"unknown_kind", 10, {&"employment_kind": &"CONTRACT"})).is_success(), "unknown employment kind is rejected" ) _expect(invalid_service.get_staff_members().is_empty(), "invalid employment rows never partially register") var current_snapshot := service.create_snapshot() var exact := StaffServiceType.new() _expect(exact.restore_snapshot(current_snapshot), "current payroll snapshot restores") _expect(exact.create_snapshot() == current_snapshot, "current payroll snapshot round trip is exact") var legacy_snapshot: Dictionary = current_snapshot.duplicate(true) for staff_snapshot: Dictionary in legacy_snapshot[&"staff"]: staff_snapshot.erase(&"daily_wage") staff_snapshot.erase(&"employment_kind") var migrated := StaffServiceType.new() _expect(migrated.restore_snapshot(legacy_snapshot), "pre-payroll Staff snapshot restores through deterministic defaults") _expect( migrated.get_daily_payroll_total() == 0 and migrated.get_staff(&"staff_a").employment_kind == StaffRuntimeType.EmploymentKind.FREE_HIRE, "legacy payroll migration defaults every existing Staff to zero-wage FREE_HIRE" ) var atomic_before := exact.create_snapshot() var negative_snapshot: Dictionary = current_snapshot.duplicate(true) negative_snapshot[&"staff"][0][&"daily_wage"] = -1 _expect(not exact.restore_snapshot(negative_snapshot), "negative wage snapshot corruption is rejected") _expect(exact.create_snapshot() == atomic_before, "negative wage restore failure is atomic") var typed_snapshot: Dictionary = current_snapshot.duplicate(true) typed_snapshot[&"staff"][0][&"daily_wage"] = "240" _expect(not exact.restore_snapshot(typed_snapshot), "malformed wage snapshot type is rejected") _expect(exact.create_snapshot() == atomic_before, "malformed wage restore failure is atomic") var kind_snapshot: Dictionary = current_snapshot.duplicate(true) kind_snapshot[&"staff"][0][&"employment_kind"] = "UNKNOWN" _expect(not exact.restore_snapshot(kind_snapshot), "unknown employment snapshot kind is rejected") _expect(exact.create_snapshot() == atomic_before, "unknown kind restore failure is atomic") var unpaid_type_snapshot: Dictionary = current_snapshot.duplicate(true) unpaid_type_snapshot[&"staff"][0][&"unpaid_wages"] = "0" _expect(not exact.restore_snapshot(unpaid_type_snapshot), "malformed active unpaid-wage type is rejected") _expect(exact.create_snapshot() == atomic_before, "malformed active liability restore failure is atomic") var invalid_runtime := service.get_staff(&"staff_a") invalid_runtime.daily_wage = -1 _expect(not service.validate_invariants()[&"ok"], "Staff invariants detect a corrupted live daily wage") invalid_runtime.daily_wage = 240 service._departed_payroll[&"former_staff"] = -5 _expect(not service.validate_invariants()[&"ok"], "Staff invariants detect a corrupted departed wage liability") service._departed_payroll.erase(&"former_staff") _expect(service.validate_invariants()[&"ok"], "valid employment and payroll state satisfies all Staff invariants") func _test_retirement_preserves_unpaid_wages() -> void: var service := StaffServiceType.new() var staff := _staff(&"retiring_staff", 10, { &"daily_wage": 125, &"employment_kind": &"ADULT_CONTRACT", &"unpaid_wages": 375, }) service.register_staff(staff) var result = service.retire_staff(staff.staff_id, 50) _expect(result.is_success() and not service.has_staff(staff.staff_id), "retirement removes active Staff after cleanup") _expect(service.get_departed_unpaid_wages(staff.staff_id) == 375, "retirement preserves unpaid wages by former Staff ID") _expect(service.get_daily_payroll_rows().is_empty() and service.get_daily_payroll_total() == 0, "departed Staff is removed from future daily wage expense") var snapshot: Dictionary = service.create_snapshot() _expect(snapshot[&"departed_payroll"][0][&"unpaid_wages"] == 375, "departed payroll liability is included in Save snapshot") var restored := StaffServiceType.new() _expect(restored.restore_snapshot(snapshot), "departed payroll snapshot restores exactly") var before_corruption := restored.create_snapshot() var malformed: Dictionary = snapshot.duplicate(true) malformed[&"departed_payroll"][0][&"unpaid_wages"] = "375" _expect(not restored.restore_snapshot(malformed), "malformed departed payroll amount is rejected") _expect(restored.create_snapshot() == before_corruption, "departed payroll corruption rejection is atomic") func _test_daily_payroll_settlement_lifecycle() -> void: var service := StaffServiceType.new() service.register_staff(_staff(&"staff_z", 10, {&"daily_wage": 40})) service.register_staff(_staff(&"staff_a", 10, { &"daily_wage": 100, &"employment_kind": &"ADULT_CONTRACT", &"unpaid_wages": 50, })) service.register_staff(_staff(&"former", 10, { &"daily_wage": 80, &"unpaid_wages": 90, })) service.remove_staff(&"former", &"CONTRACT_ENDED", true, 0) var preview: Dictionary = service.preview_daily_payroll(1) var expected_rows: Array[Dictionary] = [ { &"staff_id": &"former", &"payroll_status": &"DEPARTED", &"employment_kind": &"", &"daily_wage": 0, &"prior_arrears": 90, &"new_wages": 0, &"total_due": 90, }, { &"staff_id": &"staff_a", &"payroll_status": &"ACTIVE", &"employment_kind": &"ADULT_CONTRACT", &"daily_wage": 100, &"prior_arrears": 50, &"new_wages": 100, &"total_due": 150, }, { &"staff_id": &"staff_z", &"payroll_status": &"ACTIVE", &"employment_kind": &"FREE_HIRE", &"daily_wage": 40, &"prior_arrears": 0, &"new_wages": 40, &"total_due": 40, }, ] _expect(preview[&"ok"] and preview[&"rows"] == expected_rows, "payroll preview has an exact uniform shape and lexical Staff order") _expect( preview[&"new_wages_total"] == 140 and preview[&"prior_arrears_total"] == 140 and preview[&"total_due"] == 280, "payroll preview strictly separates new wages, prior arrears and total due" ) preview[&"rows"][0][&"total_due"] = 999 _expect(service.get_departed_unpaid_wages(&"former") == 90, "payroll preview is a defensive copy") var first = service.apply_daily_payroll_settlement( &"payroll.day.1", 1, {&"staff_a": 150, &"former": 30, &"staff_z": 0} ) _expect(first.is_success() and not first.details[&"replayed"], "first payroll settlement commits once") _expect( first.details[&"paid_total"] == 180 and first.details[&"unpaid_after_total"] == 100, "full, partial and zero payments settle in one atomic batch" ) _expect(service.get_staff(&"staff_a").unpaid_wages == 0, "fully paid active Staff has no arrears") _expect(service.get_staff(&"staff_z").unpaid_wages == 40, "zero payment carries the new active wage forward") _expect(service.get_departed_unpaid_wages(&"former") == 60, "partial departed payment reduces only preserved debt") _expect(not service.preview_daily_payroll(1)[&"ok"], "settled day cannot be previewed as a second accrual") var obligations := service.get_payroll_obligations() _expect( obligations.map(func(row: Dictionary) -> StringName: return row[&"staff_id"]) == [&"former", &"staff_a", &"staff_z"], "Operations obligation query is ordered across active and departed Staff" ) obligations[0][&"unpaid_wages"] = 999 _expect(service.get_departed_unpaid_wages(&"former") == 60, "obligation query returns defensive row copies") var second_preview := service.preview_daily_payroll(2) _expect( second_preview[&"new_wages_total"] == 140 and second_preview[&"prior_arrears_total"] == 100 and second_preview[&"total_due"] == 240, "next day accrues active wages once while retaining all arrears" ) var second = service.apply_daily_payroll_settlement( &"payroll.day.2", 2, {&"former": 60, &"staff_a": 50, &"staff_z": 80} ) _expect(second.is_success() and second.details[&"paid_total"] == 190, "next-day partial allocation commits") _expect(service.get_departed_staff_ids().is_empty(), "full departed paydown removes the departed liability row") _expect( service.get_staff(&"staff_a").unpaid_wages == 50 and service.get_staff(&"staff_z").unpaid_wages == 0, "active Staff carry only their exact post-payment balances" ) service.remove_staff(&"staff_a", &"CONTRACT_ENDED", true, 10) _expect(service.get_departed_unpaid_wages(&"staff_a") == 50, "removal after settlement preserves remaining active arrears") var third_preview := service.preview_daily_payroll(3) _expect( third_preview[&"rows"][0][&"staff_id"] == &"staff_a" and third_preview[&"rows"][0][&"new_wages"] == 0 and third_preview[&"rows"][0][&"total_due"] == 50, "departed Staff never accrue another daily wage" ) _expect( service.apply_daily_payroll_settlement(&"payroll.day.3", 3, {&"staff_a": 50, &"staff_z": 40}).is_success(), "later settlement can fully clear active and departed obligations" ) _expect(service.get_departed_staff_ids().is_empty() and service.get_staff(&"staff_z").unpaid_wages == 0, "full settlement clears every liability") func _test_payroll_validation_and_idempotency() -> void: var service := StaffServiceType.new() service.register_staff(_staff(&"paid_staff", 10, {&"daily_wage": 100})) var pristine := service.create_snapshot() _expect(not service.preview_daily_payroll(0)[&"ok"], "zero payroll day is rejected") _expect(not service.preview_daily_payroll("1")[&"ok"], "string payroll day is rejected rather than coerced") _expect(not service.apply_daily_payroll_settlement(&"bad id", 1, {}).is_success(), "unstable settlement ID is rejected") _expect(not service.apply_daily_payroll_settlement(&"bad_payments", 1, []).is_success(), "non-Dictionary payments are rejected") _expect(not service.apply_daily_payroll_settlement(&"typed", 1, {&"paid_staff": "100"}).is_success(), "string payment is rejected") _expect(not service.apply_daily_payroll_settlement(&"float", 1, {&"paid_staff": 100.0}).is_success(), "floating payment is rejected") _expect(not service.apply_daily_payroll_settlement(&"negative", 1, {&"paid_staff": -1}).is_success(), "negative payment is rejected") _expect(not service.apply_daily_payroll_settlement(&"unknown", 1, {&"missing": 0}).is_success(), "unknown Staff payment is rejected even when zero") _expect(not service.apply_daily_payroll_settlement(&"overpay", 1, {&"paid_staff": 101}).is_success(), "payment above exact obligation is rejected") _expect(service.create_snapshot() == pristine, "all malformed and overpayment requests are atomic") var committed = service.apply_daily_payroll_settlement(&"stable.day.1", 1, {&"paid_staff": 25}) _expect(committed.is_success() and service.get_staff(&"paid_staff").unpaid_wages == 75, "valid partial settlement commits exact arrears") var committed_snapshot := service.create_snapshot() var replay = service.apply_daily_payroll_settlement(&"stable.day.1", 1, {&"paid_staff": 25}) _expect(replay.is_success() and replay.details[&"replayed"], "same settlement ID and fingerprint replays successfully") _expect(service.create_snapshot() == committed_snapshot, "idempotent replay performs no second wage accrual or payment") _expect(not service.apply_daily_payroll_settlement(&"stable.day.1", 1, {&"paid_staff": 24}).is_success(), "same settlement ID rejects a conflicting payment fingerprint") _expect(not service.apply_daily_payroll_settlement(&"stable.day.1", 2, {&"paid_staff": 25}).is_success(), "same settlement ID rejects a conflicting day") _expect(not service.apply_daily_payroll_settlement(&"other.day.1", 1, {}).is_success(), "different settlement ID cannot accrue the same day twice") _expect(service.create_snapshot() == committed_snapshot, "all idempotency conflicts preserve committed state") func _test_payroll_snapshot_migration_and_tamper() -> void: var legacy_source := StaffServiceType.new() legacy_source.register_staff(_staff(&"active_debt", 10, {&"daily_wage": 75, &"unpaid_wages": 125})) legacy_source.register_staff(_staff(&"departed_debt", 10, {&"daily_wage": 50, &"unpaid_wages": 200})) legacy_source.remove_staff(&"departed_debt", &"LEFT", true, 0) var legacy: Dictionary = legacy_source.create_snapshot() legacy[&"version"] = 1 legacy.erase(&"work_assignments") legacy.erase(&"last_advanced_minute") legacy.erase(&"payroll_settlements") for staff_snapshot: Dictionary in legacy[&"staff"]: staff_snapshot.erase(&"snapshot_version") staff_snapshot.erase(&"employment_effective_minute") var migrated := StaffServiceType.new() _expect(migrated.restore_snapshot(legacy), "v1 StaffService snapshot migrates to empty settlement history") _expect( migrated.get_staff(&"active_debt").unpaid_wages == 125 and migrated.get_departed_unpaid_wages(&"departed_debt") == 200, "v1 migration preserves active and departed unpaid wages" ) var migrated_snapshot := migrated.create_snapshot() _expect(migrated_snapshot[&"version"] == StaffServiceType.SNAPSHOT_VERSION and migrated_snapshot[&"payroll_settlements"].is_empty(), "v1 migration emits canonical current schema with empty history") var service := StaffServiceType.new() service.register_staff(_staff(&"staff_a", 10, {&"daily_wage": 100, &"unpaid_wages": 20})) service.register_staff(_staff(&"staff_b", 10, {&"daily_wage": 50})) service.apply_daily_payroll_settlement(&"snapshot.day.1", 1, {&"staff_a": 30, &"staff_b": 0}) service.apply_daily_payroll_settlement(&"snapshot.day.2", 2, {&"staff_a": 50, &"staff_b": 100}) var snapshot: Dictionary = service.create_snapshot() var restored := StaffServiceType.new() _expect(restored.restore_snapshot(snapshot), "canonical current schema payroll history restores") _expect(restored.create_snapshot() == snapshot, "current payroll settlement history round trip is exact") var v2_snapshot: Dictionary = snapshot.duplicate(true) v2_snapshot[&"version"] = 2 v2_snapshot.erase(&"work_assignments") for staff_snapshot: Dictionary in v2_snapshot[&"staff"]: staff_snapshot.erase(&"snapshot_version") staff_snapshot.erase(&"employment_effective_minute") var v2_migrated := StaffServiceType.new() _expect(v2_migrated.restore_snapshot(v2_snapshot), "pre-effective-minute v2 payroll history migrates") _expect( v2_migrated.create_snapshot()[&"version"] == StaffServiceType.SNAPSHOT_VERSION and v2_migrated.get_staff(&"staff_a").employment_effective_minute == 0, "v2 migration emits canonical current schema Staff rows at effective minute zero" ) var before_tamper := restored.create_snapshot() var fingerprint_tamper: Dictionary = snapshot.duplicate(true) fingerprint_tamper[&"payroll_settlements"][0][&"fingerprint"] = "0".repeat(64) _expect(not restored.restore_snapshot(fingerprint_tamper), "tampered payroll fingerprint is rejected") _expect(restored.create_snapshot() == before_tamper, "fingerprint rejection is atomic") var total_tamper: Dictionary = snapshot.duplicate(true) total_tamper[&"payroll_settlements"][0][&"total_due"] += 1 _expect(not restored.restore_snapshot(total_tamper), "tampered payroll derived total is rejected") _expect(restored.create_snapshot() == before_tamper, "derived total rejection is atomic") var amount_tamper: Dictionary = snapshot.duplicate(true) amount_tamper[&"payroll_settlements"][0][&"rows"][0][&"payment"] = -1 _expect(not restored.restore_snapshot(amount_tamper), "negative historical payment is rejected") _expect(restored.create_snapshot() == before_tamper, "negative history rejection is atomic") var order_tamper: Dictionary = snapshot.duplicate(true) order_tamper[&"payroll_settlements"].reverse() _expect(not restored.restore_snapshot(order_tamper), "unordered settlement days are rejected") _expect(restored.create_snapshot() == before_tamper, "history order rejection is atomic") var duplicate_day: Dictionary = snapshot.duplicate(true) duplicate_day[&"payroll_settlements"][1][&"day"] = 1 _expect(not restored.restore_snapshot(duplicate_day), "duplicate settlement day is rejected") _expect(restored.create_snapshot() == before_tamper, "duplicate day rejection is atomic") var extra_field: Dictionary = snapshot.duplicate(true) extra_field[&"payroll_settlements"][0][&"unexpected"] = true _expect(not restored.restore_snapshot(extra_field), "unknown current payroll history field is rejected") _expect(restored.create_snapshot() == before_tamper, "unknown field rejection is atomic") var typed_day: Dictionary = snapshot.duplicate(true) typed_day[&"payroll_settlements"][0][&"day"] = "1" _expect(not restored.restore_snapshot(typed_day), "string historical day is rejected rather than coerced") _expect(restored.create_snapshot() == before_tamper, "historical type rejection is atomic") func _test_remove_staff_cleans_schedule_graph() -> void: var service := StaffServiceType.new() var staff := _staff(&"scheduled_departure", 10, {&"state": StaffRuntimeType.State.OFF_DUTY}) service.register_staff(staff) service.set_schedule_override(staff.staff_id, 3, {&"start_minute_of_day": 420}) service.set_schedule_override(staff.staff_id, 4, {&"assigned_facility_id": &"remote"}) service.create_standard_shift(staff.staff_id, &"DAY", 3, &"reception", &"departure_day_3") service.create_standard_shift(staff.staff_id, &"DAY", 4, &"warehouse", &"departure_day_4") var removal = service.remove_staff(staff.staff_id, &"CONTRACT_ENDED", true, 100) _expect(removal.is_success() and not service.has_staff(staff.staff_id), "Staff removal succeeds with future schedule records") _expect(service.get_shifts().is_empty(), "Staff removal deletes every related Shift instance") _expect( service.get_schedule_override(staff.staff_id, 3).is_empty() and service.get_schedule_override(staff.staff_id, 4).is_empty(), "Staff removal deletes every related ScheduleOverride" ) _expect( removal.details[&"removed_shift_ids"] == [&"departure_day_3", &"departure_day_4"] and removal.details[&"removed_override_days"] == [3, 4], "Staff removal reports deterministic schedule cleanup" ) _expect(service.validate_invariants()[&"ok"], "Staff removal leaves no orphan schedule graph") var snapshot := service.create_snapshot() var restored := StaffServiceType.new() _expect(restored.restore_snapshot(snapshot), "post-removal StaffService snapshot restores") _expect(restored.create_snapshot() == snapshot, "post-removal snapshot round trip is exact") func _test_snapshot_round_trip_and_atomic_restore() -> void: var original := StaffServiceType.new() var staff := _staff(&"snapshot_staff", 20) original.register_staff(staff) original.create_standard_shift(staff.staff_id, &"NIGHT", 0, &"warehouse", &"snapshot_shift") original.advance_one_minute(1_080) var task := _task(&"snapshot_task", 70, 1_080) original.register_task(task) original.dispatch_now(1_080) var snapshot: Dictionary = original.create_snapshot() var restored := StaffServiceType.new() _expect(restored.restore_snapshot(snapshot), "valid StaffService snapshot restores") _expect(restored.create_snapshot() == snapshot, "Staff, Shift, Task and Dispatcher round trip exactly") _expect(restored.validate_invariants()[&"ok"], "restored Staff graph satisfies pair invariants") var before_invalid: Dictionary = restored.create_snapshot() var invalid: Dictionary = snapshot.duplicate(true) invalid[&"tasks"][0][&"assigned_staff_id"] = "missing_staff" _expect(not restored.restore_snapshot(invalid), "snapshot with orphan Task is rejected") _expect(restored.create_snapshot() == before_invalid, "failed restore leaves live Staff state untouched") func _test_orphan_recovery_is_atomic() -> void: var release_outcome := {&"ok": false} var release_calls: Array = [] var service := StaffServiceType.new() service.configure_callbacks( Callable(), func(ids: Array[StringName], _task_value: StaffTask, _minute: int) -> Dictionary: release_calls.append(ids.duplicate()) return {&"ok": bool(release_outcome[&"ok"])} ) service.register_staff(_staff(&"live_staff", 10)) var live_before: Dictionary = service.create_snapshot() var reopened_signals: Array[StringName] = [] service.task_reopened.connect( func(task_id: StringName, _reason: StringName) -> void: reopened_signals.append(task_id) ) var candidate := StaffServiceType.new().create_snapshot() var orphan_a := _task(&"orphan_a", 50, 0, { &"required_items": {&"tool": 1}, &"state": StaffTaskType.State.RESERVED, &"assigned_staff_id": &"missing_a", &"reservation_ids": [&"reservation_a"], }) var orphan_b := _task(&"orphan_b", 40, 0, { &"required_items": {&"tool": 1}, &"state": StaffTaskType.State.RESERVED, &"assigned_staff_id": &"missing_b", &"reservation_ids": [&"reservation_b"], }) candidate[&"tasks"] = [orphan_a.create_snapshot(), orphan_b.create_snapshot()] _expect(not service.restore_snapshot_with_orphan_recovery(candidate), "failed external Reservation release rejects orphan recovery") _expect(service.create_snapshot() == live_before and reopened_signals.is_empty(), "failed orphan recovery preserves live Staff snapshot and emits no repair signals") _expect(release_calls == [[&"reservation_a", &"reservation_b"]], "all orphan Reservations use one external release transaction") _expect(service.last_recovery_repair_report[&"release_failed_task_ids"] == [&"orphan_a", &"orphan_b"], "failed transaction reports every unrepaired Task exactly") release_outcome[&"ok"] = true release_calls.clear() _expect(service.restore_snapshot_with_orphan_recovery(candidate), "successful external release commits the isolated repaired candidate") _expect(release_calls == [[&"reservation_a", &"reservation_b"]], "successful recovery still performs exactly one Reservation transaction") _expect(service.get_task(&"orphan_a").state == StaffTaskType.State.OPEN and service.get_task(&"orphan_b").state == StaffTaskType.State.OPEN, "committed recovery reopens only the two orphan Tasks") _expect(reopened_signals == [&"orphan_a", &"orphan_b"] and service.validate_invariants()[&"ok"], "repair signals publish only after the valid candidate commits") var committed_before: Dictionary = service.create_snapshot() var signal_count_before := reopened_signals.size() var unrelated_damage: Dictionary = candidate.duplicate(true) var missing_staff_shift := ShiftInstanceType.create_standard(&"invalid_shift", &"missing_shift_staff", &"DAY", 0) unrelated_damage[&"shifts"] = [missing_staff_shift.create_snapshot()] release_calls.clear() _expect(not service.restore_snapshot_with_orphan_recovery(unrelated_damage), "recovery rejects non-orphan Shift corruption mixed with repairable Tasks") _expect(release_calls.is_empty(), "non-repairable damage is rejected before any external Reservation release") _expect(service.create_snapshot() == committed_before and reopened_signals.size() == signal_count_before, "non-repairable recovery failure preserves live snapshot and signals atomically") var exact := StaffServiceType.new() _expect(exact.restore_snapshot_with_orphan_recovery(committed_before), "ordinary valid snapshot also restores through the recovery boundary") _expect(exact.create_snapshot() == committed_before, "ordinary recovery-boundary round trip remains exact") func _staff( staff_id: StringName, operation_skill: int, options: Dictionary = {} ) -> StaffRuntime: var configuration := { &"state": StaffRuntimeType.State.AVAILABLE, &"role_tags": [&"worker"], &"permitted_task_tags": [&"work", &"rest"], &"skills": {&"operation": operation_skill}, } for key: Variant in options: configuration[key] = options[key] return StaffRuntimeType.new().configure(staff_id, &"worker", configuration) func _task( task_id: StringName, priority: int, created_at: int, options: Dictionary = {} ) -> StaffTask: var configuration := { &"required_role_tags": [&"worker"], &"required_skill_min": {&"operation": 1}, &"task_tags": [&"work"], &"estimated_minutes": 5, &"interrupt_level": 3, } for key: Variant in options: configuration[key] = options[key] return StaffTaskType.new().configure(task_id, &"work", priority, created_at, configuration) func _expect(condition: bool, label: String) -> void: _checks += 1 if condition: print(" ✓ %s" % label) 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")