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
+135 -1
View File
@@ -103,6 +103,30 @@ func get_raid_ids() -> Array[StringName]:
return _sorted_keys(_raids)
## Explicit IDs in valid older saves need not have advanced Runtime's allocator.
## Query the existing history without exposing or copying its mutable payloads.
func has_resolution(raid_id: StringName, resolution_id: StringName) -> bool:
return _raids.has(raid_id) and (_raids[raid_id][&"resolved_rounds"] as Dictionary).has(resolution_id)
## Detached primitives only; ordinary ticks must not clone growing round history.
## The interval is already part of each persisted raid, not a new balance value.
func get_due_rounds(absolute_minute: int) -> Array[Dictionary]:
var result: Array[Dictionary] = []
for raid_id: StringName in _sorted_keys(_raids):
var raid: Dictionary = _raids[raid_id]
if int(raid[&"state"]) != RaidState.ACTIVE:
continue
var earliest := int(raid[&"state_changed_at"]) + int(raid[&"round_minutes"])
if earliest <= absolute_minute:
result.append({
&"raid_id": raid_id,
&"earliest_minute": earliest,
&"round_number": int(raid[&"current_round"]) + 1,
})
return result
func get_active_raid_ids() -> Array[StringName]:
var result: Array[StringName] = []
for raid_id: StringName in _sorted_keys(_raids):
@@ -112,6 +136,75 @@ func get_active_raid_ids() -> Array[StringName]:
return result
## Compact, owned projection: never copy combatants or accumulated round history
## just to display the current threats. Preparing raids also lock employees.
func get_threat_summary() -> Dictionary:
var counts := {&"preparing": 0, &"active": 0, &"between_waves": 0, &"total": 0}
for raid: Dictionary in _raids.values():
match int(raid[&"state"]):
RaidState.PREPARING:
counts[&"preparing"] += 1
RaidState.ACTIVE:
counts[&"active"] += 1
RaidState.BETWEEN_WAVES:
counts[&"between_waves"] += 1
counts[&"total"] = counts[&"preparing"] + counts[&"active"] + counts[&"between_waves"]
return counts
## Owned UI projections. Deliberately omit resolved rounds and skill history.
func get_management_rows() -> Array[Dictionary]:
var rows: Array[Dictionary] = []
for raid_id: StringName in _sorted_keys(_raids):
var raid: Dictionary = _raids[raid_id]
var missing: Array[StringName] = []
for objective_id: StringName in raid[&"objective_ids"]:
if not (raid[&"assets"] as Dictionary).has(objective_id):
missing.append(objective_id)
var defender_ids: Array[StringName] = []
for actor_id: StringName in _sorted_keys(raid[&"combatants"]):
if raid[&"combatants"][actor_id][&"side"] == &"DEFENDER": defender_ids.append(actor_id)
rows.append({
&"raid_id": raid_id, &"state": int(raid[&"state"]),
&"source_id": raid[&"source_id"], &"current_round": int(raid[&"current_round"]),
&"source_kind": String((raid.get(&"event_source", {}) as Dictionary).get("source_kind", "")),
&"created_at": int(raid[&"created_at"]),
&"current_wave": int(raid[&"current_wave_index"]) + 1,
&"wave_count": (raid[&"waves"] as Array).size(),
&"retreat_policy": raid[&"retreat_policy"],
&"defender_retreat_threshold": int(raid[&"defender_retreat_threshold"]),
&"objective_ids": (raid[&"objective_ids"] as Array).duplicate(),
&"missing_objectives": missing,
&"defender_ids": defender_ids, &"asset_ids": _sorted_keys(raid[&"assets"]),
&"result": raid[&"result"], &"result_reason": raid[&"result_reason"],
})
return rows
func get_management_detail(raid_id: StringName) -> Dictionary:
if not _raids.has(raid_id):
return {}
var raid: Dictionary = _raids[raid_id]
var defenders: Array[Dictionary] = []
for actor_id: StringName in _sorted_keys(raid[&"combatants"]):
var actor: Dictionary = raid[&"combatants"][actor_id]
if actor[&"side"] == &"DEFENDER":
defenders.append({
&"actor_id": actor_id, &"health": actor[&"health"],
&"max_health": actor[&"max_health"], &"combat": actor[&"combat"],
&"fatigue": actor[&"fatigue"], &"state": actor[&"state"],
})
var assets: Array[Dictionary] = []
for asset_id: StringName in _sorted_keys(raid[&"assets"]):
var asset: Dictionary = raid[&"assets"][asset_id]
assets.append({
&"asset_id": asset_id, &"kind": asset[&"kind"],
&"integrity": asset[&"integrity"], &"max_integrity": asset[&"max_integrity"],
&"defense": asset[&"defense"],
})
return {&"defenders": defenders, &"assets": assets}
func create_raid(
raid_id: StringName,
absolute_minute: int,
@@ -124,6 +217,11 @@ func create_raid(
if _raids.has(raid_id):
return _duplicate("Raid", raid_id)
var event_source_value: Variant = _value(definition, &"event_source", {})
if not _is_valid_event_source(event_source_value):
return _invalid("Event threat provenance is malformed.")
var event_source: Dictionary = event_source_value.duplicate(true)
var entry_points := _sorted_unique_names(_value(definition, &"entry_points", []))
var objective_ids := _sorted_unique_names(_value(definition, &"objective_ids", []))
if entry_points.is_empty() or objective_ids.is_empty():
@@ -146,6 +244,7 @@ func create_raid(
var raid := {
&"raid_id": raid_id,
&"source_id": StringName(_value(definition, &"source_id", &"")),
&"event_source": event_source,
&"state": RaidState.PREPARING,
&"created_at": absolute_minute,
&"started_at": -1,
@@ -1372,6 +1471,7 @@ func _raid_to_snapshot(raid: Dictionary) -> Dictionary:
var snapshot := {
&"raid_id": String(raid[&"raid_id"]),
&"source_id": String(raid[&"source_id"]),
&"event_source": _canonical_snapshot_value(raid.get(&"event_source", {})),
&"state": RaidState.keys()[int(raid[&"state"])],
&"created_at": raid[&"created_at"],
&"started_at": raid[&"started_at"],
@@ -1432,6 +1532,9 @@ func _raid_to_snapshot(raid: Dictionary) -> Dictionary:
func _raid_from_snapshot(raw: Dictionary) -> Dictionary:
var event_source_value: Variant = _value(raw, &"event_source", {})
if not _is_valid_event_source(event_source_value):
return {&"ok": false, &"error": "Event threat provenance snapshot is malformed."}
for collection_key: StringName in [&"waves", &"combatants", &"assets", &"queued_skills", &"applied_skill_ids", &"resolved_rounds"]:
if not _value(raw, collection_key, null) is Array:
return {&"ok": false, &"error": "Malformed Raid collection: %s" % collection_key}
@@ -1442,6 +1545,7 @@ func _raid_from_snapshot(raw: Dictionary) -> Dictionary:
var raid := {
&"raid_id": raid_id,
&"source_id": StringName(_value(raw, &"source_id", &"")),
&"event_source": event_source_value.duplicate(true),
&"state": state_index,
&"created_at": int(_value(raw, &"created_at", -1)),
&"started_at": int(_value(raw, &"started_at", -1)),
@@ -1563,6 +1667,8 @@ func _raid_from_snapshot(raw: Dictionary) -> Dictionary:
func _validate_raid(raid: Dictionary) -> Dictionary:
var errors: Array[String] = []
if not _is_valid_event_source(raid.get(&"event_source", {})):
errors.append("Event threat provenance is invalid.")
var raid_id := StringName(raid.get(&"raid_id", &""))
var state := int(raid.get(&"state", -1))
var created_at := int(raid.get(&"created_at", -1))
@@ -1749,7 +1855,10 @@ func _validate_raid(raid: Dictionary) -> Dictionary:
var listed_objective: bool = objective_ids is Array and objective_ids.has(asset_id)
if listed_objective != (kind == AssetKind.OBJECTIVE):
errors.append("Defense objective registration mismatch: %s" % asset_id)
if state != RaidState.PREPARING and assets is Dictionary and objective_ids is Array:
# Preparation may be cancelled before all objective assets are registered.
# A raid that actually started must retain those assets even after cancellation.
var cancelled_before_start := state == RaidState.CANCELLED and started_at == -1
if state != RaidState.PREPARING and not cancelled_before_start and assets is Dictionary and objective_ids is Array:
for objective_id: StringName in objective_ids:
if not assets.has(objective_id):
errors.append("Started Raid is missing objective asset: %s" % objective_id)
@@ -2127,3 +2236,28 @@ func _not_found(kind: String, value_id: StringName) -> CommandResult:
last_error,
{&"id": value_id}
)
## Optional provenance is absent in legacy/manual raids. Configured event raids
## retain it so a replay cannot silently replace an already-running incident.
func _is_valid_event_source(raw: Variant) -> bool:
if not raw is Dictionary:
return false
if raw.is_empty():
return true
var keys := ["event_instance_id", "event_action_id", "template_id", "template_digest", "source_kind"]
if raw.size() != keys.size():
return false
for key: String in keys:
var value: Variant = _value(raw, StringName(key), null)
if typeof(value) not in [TYPE_STRING, TYPE_STRING_NAME] or String(value).is_empty():
return false
if String(_value(raw, &"source_kind", "")) not in ["THIEF", "BANKRUPTCY_RIOT", "BANK_DELINQUENCY", "AUTHORITY_ESCALATION"]:
return false
var digest := String(_value(raw, &"template_digest", ""))
if digest.length() != 64:
return false
for character: String in digest:
if character not in "0123456789abcdef":
return false
return true