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:
@@ -140,10 +140,10 @@ func _test_all_commands_multiwave_and_terminal_replay() -> void:
|
||||
&"raid_id": &"raid.multi", &"resolution_id": &"round.multi.early",
|
||||
})
|
||||
_expect(not early.is_success(), "a round before its configured interval is rejected")
|
||||
_advance(5)
|
||||
var first_round := _submit(&"resolve_defense_round", {
|
||||
var first_round_attempt := _submit_round_at_due({
|
||||
&"raid_id": &"raid.multi", &"resolution_id": &"round.multi.1",
|
||||
})
|
||||
var first_round: CommandResult = first_round_attempt[&"result"]
|
||||
var after_first: Dictionary = _runtime.defense_service.get_raid(&"raid.multi")
|
||||
_expect(
|
||||
first_round.is_success()
|
||||
@@ -165,10 +165,10 @@ func _test_all_commands_multiwave_and_terminal_replay() -> void:
|
||||
&"raid_id": &"raid.multi", &"resolution_id": &"round.multi.same-minute",
|
||||
})
|
||||
_expect(not same_minute.is_success(), "a different round ID cannot resolve again in the same minute")
|
||||
_advance(5)
|
||||
var terminal := _submit(&"resolve_defense_round", {
|
||||
var terminal_attempt := _submit_round_at_due({
|
||||
&"raid_id": &"raid.multi", &"resolution_id": &"round.multi.2",
|
||||
})
|
||||
var terminal: CommandResult = terminal_attempt[&"result"]
|
||||
var terminal_raid: Dictionary = _runtime.defense_service.get_raid(&"raid.multi")
|
||||
var linked_staff: StaffRuntime = _runtime.staff_service.get_staff(&"guard.multi")
|
||||
var linked_facility: FacilityInstance = _runtime.facility_service.get_instance(&"objective.multi")
|
||||
@@ -243,10 +243,10 @@ func _test_manual_retreat_cancel_and_long_horizon() -> void:
|
||||
0,
|
||||
{&"target_order": 1}
|
||||
)
|
||||
_advance(5)
|
||||
var partial := _submit(&"resolve_defense_round", {
|
||||
var partial_attempt := _submit_round_at_due({
|
||||
&"raid_id": &"raid.cancel", &"resolution_id": &"round.cancel.partial",
|
||||
})
|
||||
var partial: CommandResult = partial_attempt[&"result"]
|
||||
var partial_raid: Dictionary = _runtime.defense_service.get_raid(&"raid.cancel")
|
||||
_expect(
|
||||
partial.is_success()
|
||||
@@ -289,23 +289,20 @@ func _test_manual_retreat_cancel_and_long_horizon() -> void:
|
||||
var long_raid: Dictionary = _runtime.defense_service.get_raid(&"raid.long")
|
||||
_expect(
|
||||
_runtime.defense_service.current_minute == _clock.absolute_minute
|
||||
and int(long_raid[&"current_round"]) == 0
|
||||
and int(long_raid[&"state"]) == DefenseService.RaidState.ACTIVE,
|
||||
"24-hour ticking advances Defense time without automatically resolving rounds"
|
||||
and int(long_raid[&"current_round"]) == 1
|
||||
and int(long_raid[&"state"]) == DefenseService.RaidState.DEFENDED
|
||||
and int(long_raid[&"elapsed_minutes"]) == 5,
|
||||
"ordinary ticking automatically reaches the existing max-duration boundary once"
|
||||
)
|
||||
_expect(
|
||||
_runtime.get_rng_stream(&"defense").snapshot() == long_rng_before,
|
||||
"Defense ticking alone consumes no round RNG"
|
||||
_runtime.get_rng_stream(&"defense").snapshot() != long_rng_before
|
||||
and int(long_raid[&"finished_at"]) == int(long_raid[&"started_at"]) + 5,
|
||||
"long horizon consumes combat RNG only for the configured due round"
|
||||
)
|
||||
var duration_terminal := _submit(&"resolve_defense_round", {
|
||||
&"raid_id": &"raid.long", &"resolution_id": &"round.long.duration",
|
||||
})
|
||||
var duration_payload: Dictionary = (long_raid[&"resolved_rounds"] as Dictionary).values()[0]
|
||||
_expect(
|
||||
duration_terminal.is_success()
|
||||
and int(_runtime.defense_service.get_raid(&"raid.long")[&"state"])
|
||||
== DefenseService.RaidState.DEFENDED
|
||||
and duration_terminal.details.get(&"reason", &"") == &"RAID_DURATION_EXHAUSTED",
|
||||
"the next explicit round applies max-duration terminal behavior"
|
||||
duration_payload.get(&"reason", &"") == &"RAID_DURATION_EXHAUSTED",
|
||||
"the automatic round applies the same max-duration outcome as the command API"
|
||||
)
|
||||
|
||||
_create_staff_and_facility(&"guard.breach", &"objective.breach", 100, 0, 1)
|
||||
@@ -317,10 +314,10 @@ func _test_manual_retreat_cancel_and_long_horizon() -> void:
|
||||
{&"target_order": 1},
|
||||
1_000
|
||||
)
|
||||
_advance(5)
|
||||
var breached := _submit(&"resolve_defense_round", {
|
||||
var breached_attempt := _submit_round_at_due({
|
||||
&"raid_id": &"raid.breach", &"resolution_id": &"round.breach.terminal",
|
||||
})
|
||||
var breached: CommandResult = breached_attempt[&"result"]
|
||||
_expect(
|
||||
breached.is_success()
|
||||
and int(_runtime.defense_service.get_raid(&"raid.breach")[&"state"])
|
||||
@@ -427,7 +424,6 @@ func _test_rng_skill_and_outcome_atomicity() -> void:
|
||||
and String(queued.details.get(&"action_id", "")).begins_with("defense_skill_action."),
|
||||
"queued skill receives a stable generated action namespace"
|
||||
)
|
||||
_advance(5)
|
||||
var defense_before: Dictionary = _runtime.defense_service.create_snapshot()
|
||||
var defense_rng_before: Dictionary = _runtime.get_rng_stream(&"defense").snapshot()
|
||||
var authority_rng_before: Dictionary = _runtime.get_rng_stream(&"authority").snapshot()
|
||||
@@ -456,25 +452,36 @@ func _test_rng_skill_and_outcome_atomicity() -> void:
|
||||
failing_outcome,
|
||||
Callable(_runtime, "_apply_defense_rng_boundary")
|
||||
)
|
||||
var failed := _submit(&"resolve_defense_round", {
|
||||
var failed_attempt := _submit_round_at_due({
|
||||
&"raid_id": &"raid.atomic", &"resolution_id": &"round.atomic.retry",
|
||||
})
|
||||
var failed: CommandResult = failed_attempt[&"result"]
|
||||
var atomic_before: Dictionary = failed_attempt[&"before"]
|
||||
var atomic_after: Dictionary = failed_attempt[&"after"]
|
||||
defense_before = atomic_before[&"defense"]
|
||||
defense_rng_before = atomic_before[&"defense_rng"]
|
||||
authority_rng_before = atomic_before[&"authority_rng"]
|
||||
economy_before = atomic_before[&"economy"]
|
||||
state_before = atomic_before[&"state"]
|
||||
inventory_before = atomic_before[&"inventory"]
|
||||
staff_before = atomic_before[&"staff"]
|
||||
facilities_before = atomic_before[&"facilities"]
|
||||
_expect(not failed.is_success(), "an injected post-apply terminal failure rejects the round")
|
||||
_expect(
|
||||
_runtime.defense_service.create_snapshot() == defense_before
|
||||
and _runtime.get_rng_stream(&"defense").snapshot() == defense_rng_before
|
||||
and _runtime.get_rng_stream(&"authority").snapshot() == authority_rng_before,
|
||||
atomic_after[&"defense"] == defense_before
|
||||
and atomic_after[&"defense_rng"] == defense_rng_before
|
||||
and atomic_after[&"authority_rng"] == authority_rng_before,
|
||||
"failed outcome restores Defense state and its RNG without touching other streams"
|
||||
)
|
||||
_expect(
|
||||
_runtime.economy_service.create_snapshot() == economy_before
|
||||
and _state.create_snapshot() == state_before
|
||||
and _runtime.inventory_service.create_snapshot() == inventory_before,
|
||||
atomic_after[&"economy"] == economy_before
|
||||
and atomic_after[&"state"] == state_before
|
||||
and atomic_after[&"inventory"] == inventory_before,
|
||||
"failed outcome restores Gold, Mana, item reservations and consumption"
|
||||
)
|
||||
_expect(
|
||||
_runtime.staff_service.create_snapshot() == staff_before
|
||||
and _runtime.facility_service.create_snapshot() == facilities_before,
|
||||
atomic_after[&"staff"] == staff_before
|
||||
and atomic_after[&"facilities"] == facilities_before,
|
||||
"failed outcome restores Staff and Facility changes atomically"
|
||||
)
|
||||
_expect(
|
||||
@@ -531,25 +538,32 @@ func _test_rng_skill_and_outcome_atomicity() -> void:
|
||||
]}}},
|
||||
})
|
||||
_expect(reservation_skill.is_success(), "multi-item skill cost queues before boundary validation")
|
||||
_advance(5)
|
||||
var reserve_defense_before: Dictionary = _runtime.defense_service.create_snapshot()
|
||||
var reserve_rng_before: Dictionary = _runtime.get_rng_stream(&"defense").snapshot()
|
||||
var reserve_inventory_before: Dictionary = _runtime.inventory_service.create_snapshot()
|
||||
var reserve_economy_before: Dictionary = _runtime.economy_service.create_snapshot()
|
||||
var reserve_state_before: Dictionary = _state.create_snapshot()
|
||||
var reservation_failed := _submit(&"resolve_defense_round", {
|
||||
var reservation_attempt := _submit_round_at_due({
|
||||
&"raid_id": &"raid.reserve", &"resolution_id": &"round.reserve.failed",
|
||||
})
|
||||
var reservation_failed: CommandResult = reservation_attempt[&"result"]
|
||||
var reserve_before: Dictionary = reservation_attempt[&"before"]
|
||||
var reserve_after: Dictionary = reservation_attempt[&"after"]
|
||||
reserve_defense_before = reserve_before[&"defense"]
|
||||
reserve_rng_before = reserve_before[&"defense_rng"]
|
||||
reserve_inventory_before = reserve_before[&"inventory"]
|
||||
reserve_economy_before = reserve_before[&"economy"]
|
||||
reserve_state_before = reserve_before[&"state"]
|
||||
_expect(not reservation_failed.is_success(), "a later unavailable item rejects the whole skill-cost batch")
|
||||
_expect(
|
||||
_runtime.inventory_service.create_snapshot() == reserve_inventory_before
|
||||
and _runtime.economy_service.create_snapshot() == reserve_economy_before
|
||||
and _state.create_snapshot() == reserve_state_before,
|
||||
reserve_after[&"inventory"] == reserve_inventory_before
|
||||
and reserve_after[&"economy"] == reserve_economy_before
|
||||
and reserve_after[&"state"] == reserve_state_before,
|
||||
"partial item reservation failure rolls every external resource back"
|
||||
)
|
||||
_expect(
|
||||
_runtime.defense_service.create_snapshot() == reserve_defense_before
|
||||
and _runtime.get_rng_stream(&"defense").snapshot() == reserve_rng_before,
|
||||
reserve_after[&"defense"] == reserve_defense_before
|
||||
and reserve_after[&"defense_rng"] == reserve_rng_before,
|
||||
"skill validation failure leaves Defense and round RNG untouched"
|
||||
)
|
||||
|
||||
@@ -676,10 +690,10 @@ func _test_snapshot_replay_corruption_and_legacy_migration() -> void:
|
||||
0,
|
||||
{&"target_order": 1}
|
||||
)
|
||||
_advance(5)
|
||||
var first := _submit(&"resolve_defense_round", {
|
||||
var first_attempt := _submit_round_at_due({
|
||||
&"raid_id": &"raid.save", &"resolution_id": &"round.save.1",
|
||||
})
|
||||
var first: CommandResult = first_attempt[&"result"]
|
||||
_expect(
|
||||
first.is_success()
|
||||
and int(_runtime.defense_service.get_raid(&"raid.save")[&"state"])
|
||||
@@ -699,17 +713,17 @@ func _test_snapshot_replay_corruption_and_legacy_migration() -> void:
|
||||
})
|
||||
_expect(queued.is_success(), "queued next-round skill is included in the mid-Raid snapshot")
|
||||
var origin: Dictionary = _runtime.create_snapshot()
|
||||
_advance(5)
|
||||
var first_branch := _submit_with_key(&"resolve_defense_round", {
|
||||
var first_branch_attempt := _submit_round_at_due({
|
||||
&"raid_id": &"raid.save", &"resolution_id": &"round.save.2",
|
||||
}, &"runtime.defense.save.resolve")
|
||||
var first_branch: CommandResult = first_branch_attempt[&"result"]
|
||||
var branch_snapshot: Dictionary = _runtime.create_snapshot()
|
||||
_expect(first_branch.is_success(), "first post-save Defense branch resolves")
|
||||
_expect(_runtime.restore_snapshot(origin), "mid-round Runtime snapshot restores atomically")
|
||||
_advance(5)
|
||||
var replay_branch := _submit_with_key(&"resolve_defense_round", {
|
||||
var replay_branch_attempt := _submit_round_at_due({
|
||||
&"raid_id": &"raid.save", &"resolution_id": &"round.save.2",
|
||||
}, &"runtime.defense.save.resolve")
|
||||
var replay_branch: CommandResult = replay_branch_attempt[&"result"]
|
||||
_expect(
|
||||
replay_branch.is_success() and replay_branch.details == first_branch.details,
|
||||
"restored mid-round branch reproduces the exact Defense resolution"
|
||||
@@ -796,6 +810,7 @@ func _test_snapshot_replay_corruption_and_legacy_migration() -> void:
|
||||
legacy[&"systems"][&"runtime"].erase(&"kitchen_production")
|
||||
legacy[&"systems"][&"runtime"].erase(&"elevators")
|
||||
legacy[&"systems"][&"runtime"].erase(&"legacy_stairs")
|
||||
preload("res://tests/fixtures/pre_upkeep_runtime.gd").strip_empty_upkeep(legacy[&"systems"][&"runtime"])
|
||||
legacy[&"systems"][&"runtime"][&"path"][&"schema_version"] = 3
|
||||
legacy[&"systems"][&"runtime"][&"path"].erase(&"vertical_walk_blockers")
|
||||
legacy[&"systems"][&"runtime"][&"path"].erase(&"vertical_walk_requires_connector")
|
||||
@@ -1029,3 +1044,64 @@ func _expect(condition: bool, label: String) -> void:
|
||||
return
|
||||
_failures += 1
|
||||
push_error(" ✗ %s" % label)
|
||||
|
||||
|
||||
## Explicit API coverage schedules the command at its actual deadline. The
|
||||
## normal kernel executes APPLY_COMMANDS before automatic defense progression.
|
||||
## Captures bracket that actual handler, excluding later unrelated tick phases.
|
||||
func _submit_round_at_due(
|
||||
payload: Dictionary,
|
||||
idempotency_key: StringName = &""
|
||||
) -> Dictionary:
|
||||
var raid_id := StringName(payload[&"raid_id"])
|
||||
var raid: Dictionary = _runtime.defense_service.get_raid(raid_id)
|
||||
var due := int(raid[&"state_changed_at"]) + int(raid[&"round_minutes"])
|
||||
_expect(due > _clock.absolute_minute, "manual deadline helper receives a future configured deadline")
|
||||
if due <= _clock.absolute_minute:
|
||||
return {&"result": _submit(&"resolve_defense_round", payload), &"before": {}, &"after": {}}
|
||||
if idempotency_key.is_empty():
|
||||
_command_sequence += 1
|
||||
idempotency_key = StringName("runtime.defense.%04d" % _command_sequence)
|
||||
var captures := {&"before": {}, &"after": {}, &"signals": []}
|
||||
var executors: Dictionary = _runtime.get("_executors")
|
||||
var original: Callable = executors[&"resolve_defense_round"]
|
||||
executors[&"resolve_defense_round"] = func(command: SimulationCommand) -> CommandResult:
|
||||
captures[&"before"] = _capture_defense_views()
|
||||
var result: CommandResult = original.call(command)
|
||||
captures[&"after"] = _capture_defense_views()
|
||||
return result
|
||||
var accepted: CommandResult = _runtime.submit_command(
|
||||
&"resolve_defense_round", payload, &"defense_controller", raid_id,
|
||||
80, due, idempotency_key
|
||||
)
|
||||
var capture_completed := func(result: CommandResult) -> void:
|
||||
if result.command_id == accepted.command_id:
|
||||
(captures[&"signals"] as Array).append(result.copy())
|
||||
_runtime.command_completed.connect(capture_completed)
|
||||
_clock.advance_minutes(due - _clock.absolute_minute)
|
||||
_clock.set_paused(true)
|
||||
_runtime.command_completed.disconnect(capture_completed)
|
||||
executors[&"resolve_defense_round"] = original
|
||||
var completed: CommandResult = _runtime.command_queue.get_processed_result(accepted.command_id)
|
||||
_expect(accepted.is_success() and completed != null, "manual defense command is genuinely processed at its scheduled tick")
|
||||
_expect(
|
||||
(captures[&"signals"] as Array).size() == 1
|
||||
and completed != null
|
||||
and (captures[&"signals"][0] as CommandResult).to_dictionary() == completed.to_dictionary(),
|
||||
"command_completed emits the actual persisted result, including failures"
|
||||
)
|
||||
captures[&"result"] = completed
|
||||
return captures
|
||||
|
||||
|
||||
func _capture_defense_views() -> Dictionary:
|
||||
return {
|
||||
&"defense": _runtime.defense_service.create_snapshot(),
|
||||
&"defense_rng": _runtime.get_rng_stream(&"defense").snapshot(),
|
||||
&"authority_rng": _runtime.get_rng_stream(&"authority").snapshot(),
|
||||
&"economy": _runtime.economy_service.create_snapshot(),
|
||||
&"state": _state.create_snapshot(),
|
||||
&"inventory": _runtime.inventory_service.create_snapshot(),
|
||||
&"staff": _runtime.staff_service.create_snapshot(),
|
||||
&"facilities": _runtime.facility_service.create_snapshot(),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user