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:
@@ -76,13 +76,14 @@ func drain_ready(current_tick: int) -> Array[SimulationCommand]:
|
||||
break
|
||||
_pending.pop_front()
|
||||
_in_flight[command.command_id] = command
|
||||
ready.append(command)
|
||||
ready.append(command.copy())
|
||||
return ready
|
||||
|
||||
|
||||
func execute_ready(current_tick: int, executor: Callable) -> Array[CommandResult]:
|
||||
var results: Array[CommandResult] = []
|
||||
for command in drain_ready(current_tick):
|
||||
var accepted_command_id := command.command_id
|
||||
var result: CommandResult
|
||||
if not executor.is_valid():
|
||||
result = CommandResult.failed(
|
||||
@@ -103,10 +104,8 @@ func execute_ready(current_tick: int, executor: Callable) -> Array[CommandResult
|
||||
"Executor did not return a successful CommandResult."
|
||||
)
|
||||
|
||||
if result.command_id == 0:
|
||||
result.command_id = command.command_id
|
||||
complete(command.command_id, result)
|
||||
results.append(result.copy())
|
||||
var completed_result := complete(accepted_command_id, result)
|
||||
results.append(completed_result)
|
||||
return results
|
||||
|
||||
|
||||
@@ -164,6 +163,14 @@ func processed_count() -> int:
|
||||
return _processed_results.size()
|
||||
|
||||
|
||||
## Read only pending commands, without serializing the processed history.
|
||||
func get_pending_commands() -> Array[SimulationCommand]:
|
||||
var result: Array[SimulationCommand] = []
|
||||
for command: SimulationCommand in _pending:
|
||||
result.append(command.copy())
|
||||
return result
|
||||
|
||||
|
||||
func get_accepted_command_metadata() -> Array[Dictionary]:
|
||||
var result: Array[Dictionary] = []
|
||||
var command_ids: Array = _accepted_metadata.keys()
|
||||
|
||||
@@ -26,6 +26,9 @@ const DEFAULT_BUDGETS := {
|
||||
var sample_capacity := DEFAULT_SAMPLE_CAPACITY
|
||||
var _budgets: Dictionary = {}
|
||||
var _samples: Dictionary = {}
|
||||
# Derived diagnostic index; never part of game Save snapshots.
|
||||
var _ordered_samples: Dictionary = {}
|
||||
var _ordered_sample_bytes: Dictionary = {}
|
||||
var _totals: Dictionary = {}
|
||||
var _sample_counts: Dictionary = {}
|
||||
|
||||
@@ -59,12 +62,22 @@ func record_sample(metric_id: StringName, duration_us: int) -> Dictionary:
|
||||
if not _samples.has(metric_id):
|
||||
_samples[metric_id] = []
|
||||
var values: Array = _samples[metric_id]
|
||||
var use_index: bool = get_script().resource_path == "res://scripts/core/performance_budget.gd" and _integer_window(values)
|
||||
var ordered: Array[int] = []
|
||||
if use_index: ordered = _validated_sample_order(metric_id, values)
|
||||
values.append(duration_us)
|
||||
if use_index: ordered.insert(ordered.bsearch(duration_us), duration_us)
|
||||
if values.size() > sample_capacity:
|
||||
values.pop_front()
|
||||
var removed: Variant = values.pop_front()
|
||||
if use_index: ordered.remove_at(ordered.bsearch(int(removed)))
|
||||
if use_index:
|
||||
_ordered_sample_bytes[metric_id] = var_to_bytes(values)
|
||||
else:
|
||||
_ordered_samples.erase(metric_id)
|
||||
_ordered_sample_bytes.erase(metric_id)
|
||||
_totals[metric_id] = int(_totals.get(metric_id, 0)) + duration_us
|
||||
_sample_counts[metric_id] = int(_sample_counts.get(metric_id, 0)) + 1
|
||||
var report := get_report(metric_id)
|
||||
var report: Dictionary = _indexed_report(metric_id, values, ordered) if use_index else get_report(metric_id)
|
||||
if bool(report.get(&"budget_exceeded", false)):
|
||||
budget_exceeded.emit(metric_id, report.duplicate(true))
|
||||
return {&"ok": true, &"report": report}
|
||||
@@ -92,15 +105,25 @@ func record_simulation_frame(duration_us: int, speed: int, ticks_run: int) -> Di
|
||||
|
||||
|
||||
func get_report(metric_id: StringName) -> Dictionary:
|
||||
var values: Array = _samples.get(metric_id, [])
|
||||
var raw: Array = _samples.get(metric_id, [])
|
||||
if get_script().resource_path != "res://scripts/core/performance_budget.gd" or not _integer_window(raw):
|
||||
return SimulationPerformanceBudget._legacy_report(self, metric_id)
|
||||
var ordered: Array[int] = []
|
||||
return _indexed_report(metric_id, raw, ordered, true)
|
||||
|
||||
|
||||
func _indexed_report(metric_id: StringName, values: Array, ordered: Array[int], validate_order: bool = false) -> Dictionary:
|
||||
var count := values.size()
|
||||
var lifetime_count := int(_sample_counts.get(metric_id, 0))
|
||||
var lifetime_total := int(_totals.get(metric_id, 0))
|
||||
var average_us := lifetime_total / lifetime_count if lifetime_count > 0 else 0
|
||||
var maximum_us := 0
|
||||
for raw_value: Variant in values:
|
||||
maximum_us = maxi(maximum_us, int(raw_value))
|
||||
var p95_us := _percentile(values, 95)
|
||||
if validate_order: ordered = _validated_sample_order(metric_id, values)
|
||||
var maximum_us := maxi(0, ordered[-1]) if not ordered.is_empty() else 0
|
||||
var p95_us := 0
|
||||
if not ordered.is_empty():
|
||||
var rank_numerator := 95 * ordered.size()
|
||||
var index := maxi((rank_numerator + 99) / 100 - 1, 0)
|
||||
p95_us = ordered[mini(index, ordered.size() - 1)]
|
||||
var budget: Dictionary = _budgets.get(metric_id, {})
|
||||
var aggregation := int(budget.get(&"aggregation", Aggregation.P95))
|
||||
var measured_us := _aggregated_value(aggregation, average_us, p95_us, maximum_us)
|
||||
@@ -139,10 +162,14 @@ func get_all_reports() -> Array[Dictionary]:
|
||||
func clear(metric_id: StringName = &"") -> void:
|
||||
if metric_id.is_empty():
|
||||
_samples.clear()
|
||||
_ordered_samples.clear()
|
||||
_ordered_sample_bytes.clear()
|
||||
_totals.clear()
|
||||
_sample_counts.clear()
|
||||
return
|
||||
_samples.erase(metric_id)
|
||||
_ordered_samples.erase(metric_id)
|
||||
_ordered_sample_bytes.erase(metric_id)
|
||||
_totals.erase(metric_id)
|
||||
_sample_counts.erase(metric_id)
|
||||
|
||||
@@ -172,3 +199,55 @@ func _percentile(raw_values: Array, percentile: int) -> int:
|
||||
var rank_numerator := clampi(percentile, 0, 100) * values.size()
|
||||
var index := maxi((rank_numerator + 99) / 100 - 1, 0)
|
||||
return values[mini(index, values.size() - 1)]
|
||||
|
||||
|
||||
static func _integer_window(values: Array) -> bool:
|
||||
for raw_value: Variant in values:
|
||||
if typeof(raw_value) != TYPE_INT: return false
|
||||
return true
|
||||
|
||||
|
||||
func _validated_sample_order(metric_id: StringName, values: Array) -> Array[int]:
|
||||
# No retained state for unknown metrics; raw dictionary removal also drops its index.
|
||||
if not _samples.has(metric_id):
|
||||
_ordered_samples.erase(metric_id)
|
||||
_ordered_sample_bytes.erase(metric_id)
|
||||
return []
|
||||
# Complete immutable raw bytes detect in-place/replaced windows, not just length.
|
||||
var current_bytes := var_to_bytes(values)
|
||||
if not _ordered_samples.has(metric_id) or _ordered_sample_bytes.get(metric_id, PackedByteArray()) != current_bytes:
|
||||
var ordered: Array[int] = []
|
||||
for raw_value: Variant in values: ordered.append(int(raw_value))
|
||||
ordered.sort()
|
||||
_ordered_samples[metric_id] = ordered
|
||||
_ordered_sample_bytes[metric_id] = current_bytes
|
||||
return _ordered_samples[metric_id]
|
||||
|
||||
|
||||
static func _legacy_report(owner: SimulationPerformanceBudget, metric_id: StringName) -> Dictionary:
|
||||
var values: Array = owner._samples.get(metric_id, [])
|
||||
var count := values.size()
|
||||
var lifetime_count := int(owner._sample_counts.get(metric_id, 0))
|
||||
var lifetime_total := int(owner._totals.get(metric_id, 0))
|
||||
var average_us := lifetime_total / lifetime_count if lifetime_count > 0 else 0
|
||||
var maximum_us := 0
|
||||
for raw_value: Variant in values:
|
||||
maximum_us = maxi(maximum_us, int(raw_value))
|
||||
var p95_us := owner._percentile(values, 95)
|
||||
var budget: Dictionary = owner._budgets.get(metric_id, {})
|
||||
var aggregation := int(budget.get(&"aggregation", Aggregation.P95))
|
||||
var measured_us := owner._aggregated_value(aggregation, average_us, p95_us, maximum_us)
|
||||
var limit_us := int(budget.get(&"limit_us", 0))
|
||||
return {
|
||||
&"metric_id": metric_id,
|
||||
&"window_sample_count": count,
|
||||
&"lifetime_sample_count": lifetime_count,
|
||||
&"average_us": average_us,
|
||||
&"p95_us": p95_us,
|
||||
&"maximum_us": maximum_us,
|
||||
&"aggregation": aggregation,
|
||||
&"measured_us": measured_us,
|
||||
&"limit_us": limit_us,
|
||||
&"budget_exceeded": limit_us > 0 and measured_us > limit_us,
|
||||
}
|
||||
|
||||
|
||||
+205
-11
@@ -2,6 +2,10 @@ class_name SaveService
|
||||
extends RefCounted
|
||||
|
||||
const FORMAT_VERSION := 1
|
||||
const MIMI_PURCHASE_FORMAT_VERSION := 2
|
||||
const SUPPORTED_CURRENT_FORMAT := -2
|
||||
const PurchaseQuoteV2 := preload("res://scripts/supply/supply_purchase_quote_v2.gd")
|
||||
const PurchaseQuotePlansV2 := preload("res://scripts/supply/supply_auto_purchase_quote_plans.gd")
|
||||
const MAGIC := "TTWB"
|
||||
const WORLD_FILE := "world.bin"
|
||||
const MANIFEST_FILE := "manifest.json"
|
||||
@@ -27,12 +31,15 @@ static func save_snapshot(save_path: String, snapshot: Dictionary, metadata := {
|
||||
var resolved := _resolve_safe_save_path(save_path)
|
||||
if not resolved[&"ok"]:
|
||||
return _complete_timed_operation(resolved, &"save", started_at_us)
|
||||
var selected_format := _snapshot_package_format(snapshot)
|
||||
if selected_format < 0:
|
||||
return _complete_timed_operation(_failure(&"INVALID_SNAPSHOT", "unsupported purchase Runtime/domain"), &"save", started_at_us)
|
||||
var result := _save_snapshot_absolute(
|
||||
resolved[&"path"],
|
||||
save_path,
|
||||
snapshot,
|
||||
metadata,
|
||||
FORMAT_VERSION,
|
||||
selected_format,
|
||||
resolved[&"path"],
|
||||
resolved[&"path"]
|
||||
)
|
||||
@@ -47,7 +54,7 @@ static func load_snapshot(save_path: String) -> Dictionary:
|
||||
var reconcile := _reconcile_interrupted_formal_save(resolved[&"path"])
|
||||
if not reconcile[&"ok"]:
|
||||
return _complete_timed_operation(reconcile, &"load", started_at_us)
|
||||
var result := _load_snapshot_absolute(resolved[&"path"], FORMAT_VERSION)
|
||||
var result := _load_snapshot_absolute(resolved[&"path"], SUPPORTED_CURRENT_FORMAT)
|
||||
result[&"interrupted_save_reconciled"] = bool(reconcile.get(&"reconciled", false))
|
||||
return _complete_timed_operation(result, &"load", started_at_us)
|
||||
|
||||
@@ -60,7 +67,7 @@ static func inspect_snapshot(save_path: String) -> Dictionary:
|
||||
var resolved := _resolve_safe_save_path(save_path)
|
||||
var result: Dictionary = resolved
|
||||
if resolved[&"ok"]:
|
||||
result = _load_snapshot_absolute(resolved[&"path"], FORMAT_VERSION)
|
||||
result = _load_snapshot_absolute(resolved[&"path"], SUPPORTED_CURRENT_FORMAT)
|
||||
result[&"read_only"] = true
|
||||
return _complete_timed_operation(result, &"load", started_at_us)
|
||||
|
||||
@@ -98,6 +105,9 @@ static func save_autosave(
|
||||
if not resolved[&"ok"]:
|
||||
return _complete_timed_operation(resolved, &"save", started_at_us)
|
||||
var target_path: String = resolved[&"path"]
|
||||
var selected_format := _snapshot_package_format(snapshot)
|
||||
if selected_format < 0:
|
||||
return _complete_timed_operation(_failure(&"INVALID_SNAPSHOT", "unsupported purchase Runtime/domain"), &"save", started_at_us)
|
||||
var pending_path := target_path + ".autosave.pending"
|
||||
var reconcile := _reconcile_autosave_rotation(target_path, pending_path, generation_count)
|
||||
if not reconcile[&"ok"]:
|
||||
@@ -137,7 +147,7 @@ static func save_autosave(
|
||||
get_autosave_path(save_path, 0),
|
||||
snapshot,
|
||||
candidate_metadata,
|
||||
FORMAT_VERSION,
|
||||
selected_format,
|
||||
target_path + AUTOSAVE_SUFFIX + "0",
|
||||
target_path,
|
||||
false
|
||||
@@ -201,7 +211,11 @@ static func inspect_recovery_candidates(
|
||||
var formal_reconcile := _reconcile_interrupted_formal_save(target_path)
|
||||
if not formal_reconcile[&"ok"]:
|
||||
return formal_reconcile
|
||||
var migration_reconcile := _reconcile_interrupted_migration(target_path)
|
||||
var migration_reconcile: Dictionary = (
|
||||
formal_reconcile[&"migration_reconciliation"]
|
||||
if formal_reconcile.has(&"migration_reconciliation")
|
||||
else _reconcile_interrupted_migration(target_path)
|
||||
)
|
||||
if not migration_reconcile[&"ok"]:
|
||||
return migration_reconcile
|
||||
var autosave_reconcile := _reconcile_autosave_rotation(
|
||||
@@ -235,7 +249,7 @@ static func inspect_recovery_candidates(
|
||||
var current_schema_valid := false
|
||||
var current_format := false
|
||||
if package_valid:
|
||||
current_format = int(loaded[&"manifest"].get("format_version", -1)) == FORMAT_VERSION
|
||||
current_format = _package_domain_matches(loaded)
|
||||
current_schema_valid = bool(SimulationSnapshot.validate(loaded[&"snapshot"])[&"ok"])
|
||||
var loadable := package_valid and current_format and current_schema_valid
|
||||
var candidate_code: StringName = StringName(loaded[&"code"])
|
||||
@@ -359,7 +373,7 @@ static func _load_recovery_candidate_impl(
|
||||
candidate_path = target_path + AUTOSAVE_SUFFIX + str(generation)
|
||||
else:
|
||||
return _failure(&"UNKNOWN_RECOVERY_CANDIDATE", str(candidate_id))
|
||||
var result := _load_snapshot_absolute(candidate_path, FORMAT_VERSION)
|
||||
var result := _load_snapshot_absolute(candidate_path, SUPPORTED_CURRENT_FORMAT)
|
||||
if not result[&"ok"]:
|
||||
return result
|
||||
result[&"candidate_id"] = candidate_id
|
||||
@@ -396,7 +410,9 @@ static func replace_snapshot_with_backup(save_path: String, expected: Dictionary
|
||||
if not validation[&"ok"]:
|
||||
return _failure(&"MIGRATION_INVALID_SNAPSHOT", ", ".join(validation[&"errors"]))
|
||||
var started := Time.get_ticks_usec()
|
||||
return _complete_timed_operation(_migrate_save_impl(save_path, null, FORMAT_VERSION, expected, candidate), &"save", started)
|
||||
var selected_format := _snapshot_package_format(candidate)
|
||||
if selected_format < 0: return _failure(&"MIGRATION_INVALID_SNAPSHOT", "unsupported purchase Runtime/domain")
|
||||
return _complete_timed_operation(_migrate_save_impl(save_path, null, selected_format, expected, candidate), &"save", started)
|
||||
|
||||
|
||||
static func _migrate_save_impl(
|
||||
@@ -664,6 +680,8 @@ static func _save_snapshot_absolute(
|
||||
identity_source_path := "",
|
||||
use_transaction_marker := true
|
||||
) -> Dictionary:
|
||||
if _snapshot_package_format(snapshot) != format_version:
|
||||
return _failure(&"INVALID_SNAPSHOT", "package/domain format differs")
|
||||
var validation := SimulationSnapshot.validate(snapshot)
|
||||
if not validation[&"ok"]:
|
||||
return _failure(&"INVALID_SNAPSHOT", ", ".join(validation[&"errors"]))
|
||||
@@ -674,6 +692,9 @@ static func _save_snapshot_absolute(
|
||||
return _failure(&"UNSAFE_PATH", "save path contains a symbolic link")
|
||||
var interrupted_reconcile := {&"ok": true, &"reconciled": false, &"action": &"none"}
|
||||
if use_transaction_marker:
|
||||
var format_guard := _guard_ordinary_save_format(target_path, format_version)
|
||||
if not format_guard[&"ok"]:
|
||||
return format_guard
|
||||
interrupted_reconcile = _reconcile_interrupted_formal_save(target_path)
|
||||
if not interrupted_reconcile[&"ok"]:
|
||||
return interrupted_reconcile
|
||||
@@ -754,6 +775,85 @@ static func _save_snapshot_absolute(
|
||||
}
|
||||
|
||||
|
||||
## Ordinary Save must not act as an implicit physical-format migration.
|
||||
## This preflight only reads the formal package and the candidate which the
|
||||
## existing normal-save reconciliation rules could promote. Explicit migration
|
||||
## APIs and autosave rotation keep their own unchanged contracts.
|
||||
static func _guard_ordinary_save_format(target_path: String, requested_format: int) -> Dictionary:
|
||||
var formal_guard := _guard_identified_formal_format(target_path)
|
||||
if not formal_guard[&"ok"]:
|
||||
return formal_guard
|
||||
var marker_path := target_path + SAVE_TRANSACTION_SUFFIX
|
||||
var marker_exists := FileAccess.file_exists(marker_path) or DirAccess.dir_exists_absolute(marker_path)
|
||||
if marker_exists and not _formal_transaction_marker_is_valid(marker_path):
|
||||
return _failure(&"TRANSACTION_MARKER_CONFLICT", marker_path)
|
||||
var identified := _inspect_identified_save_formats(target_path)
|
||||
if not identified[&"ok"]:
|
||||
return identified
|
||||
for existing_format: int in identified[&"format_versions"]:
|
||||
if existing_format != requested_format:
|
||||
return _ordinary_format_migration_required(target_path, existing_format, requested_format)
|
||||
var target_status := _package_status(target_path)
|
||||
if target_status[&"current_loadable"] or (target_status[&"exists"] and not marker_exists):
|
||||
return {&"ok": true, &"code": &"OK"}
|
||||
if target_status[&"exists"] and not _looks_like_save_package(target_path):
|
||||
return _failure(&"FORMAL_RECOVERY_TARGET_CONFLICT", target_path)
|
||||
# Reconciliation chooses a verified .tmp first, then a verified .bak. A
|
||||
# missing/invalid formal does not make a retained old-format source a new slot.
|
||||
for candidate_path: String in [target_path + ".tmp", target_path + ".bak"]:
|
||||
var status := _package_status(candidate_path)
|
||||
if not status[&"current_loadable"]:
|
||||
continue
|
||||
var existing_format := int(status[&"format_version"])
|
||||
if existing_format != requested_format:
|
||||
return _ordinary_format_migration_required(candidate_path, existing_format, requested_format)
|
||||
break
|
||||
return {&"ok": true, &"code": &"OK"}
|
||||
|
||||
|
||||
## A corrupt format1 checksum/manifest still identifies a retained format when
|
||||
## either its bounded manifest number or fixed TTWB header says so. Never use a
|
||||
## schema-looking nested string or coerce a non-integral manifest value.
|
||||
static func _inspect_identified_save_formats(target_path: String) -> Dictionary:
|
||||
var versions: Array[int] = []
|
||||
var manifest_path := target_path.path_join(MANIFEST_FILE)
|
||||
if FileAccess.file_exists(manifest_path):
|
||||
if not _package_file_is_safe_for_read(manifest_path):
|
||||
return _failure(&"UNSAFE_PATH", manifest_path)
|
||||
var manifest_file := FileAccess.open(manifest_path, FileAccess.READ)
|
||||
if manifest_file == null:
|
||||
return _failure(&"INVALID_MANIFEST", error_string(FileAccess.get_open_error()))
|
||||
if manifest_file.get_length() <= MAX_MANIFEST_BYTES:
|
||||
var parser := JSON.new()
|
||||
if parser.parse(manifest_file.get_as_text()) == OK and parser.data is Dictionary:
|
||||
var value: Variant = parser.data.get("format_version", null)
|
||||
if _is_integral_json_number(value, 0, 0xffffffff):
|
||||
versions.append(int(value))
|
||||
manifest_file = null
|
||||
var world_path := target_path.path_join(WORLD_FILE)
|
||||
if FileAccess.file_exists(world_path):
|
||||
if not _package_file_is_safe_for_read(world_path):
|
||||
return _failure(&"UNSAFE_PATH", world_path)
|
||||
var world_file := FileAccess.open(world_path, FileAccess.READ)
|
||||
if world_file == null:
|
||||
return _failure(&"READ_WORLD_FAILED", error_string(FileAccess.get_open_error()))
|
||||
if world_file.get_length() >= 8 and world_file.get_buffer(4).get_string_from_ascii() == MAGIC:
|
||||
var version := world_file.get_32()
|
||||
if version not in versions:
|
||||
versions.append(version)
|
||||
world_file = null
|
||||
return {&"ok": true, &"code": &"OK", &"format_versions": versions}
|
||||
|
||||
|
||||
static func _ordinary_format_migration_required(source_path: String, existing_format: int, requested_format: int) -> Dictionary:
|
||||
return _with_context(_failure(&"FORMAT_MIGRATION_REQUIRED", "%d -> %d requires explicit migration or a new slot" % [existing_format, requested_format]), {
|
||||
&"existing_format_version": existing_format,
|
||||
&"requested_format_version": requested_format,
|
||||
&"migration_source_path": source_path,
|
||||
&"formal_and_artifacts_preserved": true,
|
||||
})
|
||||
|
||||
|
||||
static func _write_package_directory(
|
||||
package_path: String,
|
||||
snapshot: Dictionary,
|
||||
@@ -761,6 +861,8 @@ static func _write_package_directory(
|
||||
format_version: int,
|
||||
logical_target_path := ""
|
||||
) -> Dictionary:
|
||||
if format_version in [FORMAT_VERSION, MIMI_PURCHASE_FORMAT_VERSION] and _snapshot_package_format(snapshot) != format_version:
|
||||
return _failure(&"INVALID_SNAPSHOT", "package/domain format differs")
|
||||
if not _operation_paths_are_safe([package_path]):
|
||||
return _failure(&"UNSAFE_PATH", "package path contains a symbolic link")
|
||||
if not _path_is_missing_or_package(package_path):
|
||||
@@ -812,6 +914,8 @@ static func _write_package_directory(
|
||||
&"checksum_world": checksum,
|
||||
&"uncompressed_size": raw_world.size(),
|
||||
}
|
||||
if format_version == MIMI_PURCHASE_FORMAT_VERSION:
|
||||
manifest[&"runtime_schema_version"] = 15
|
||||
for key: Variant in metadata:
|
||||
if key in [&"thumbnail_png", &"thumbnail_path", &"_thumbnail_png"]:
|
||||
continue
|
||||
@@ -839,7 +943,7 @@ static func _write_package_directory(
|
||||
return {&"ok": true, &"code": &"OK", &"manifest": manifest}
|
||||
|
||||
|
||||
static func _load_snapshot_absolute(
|
||||
static func _load_snapshot_absolute_v1(
|
||||
target_path: String,
|
||||
expected_format_version: int,
|
||||
validate_snapshot := true
|
||||
@@ -932,6 +1036,87 @@ static func _load_snapshot_absolute(
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
## Format choice comes only from the decoded owned Runtime, never from a
|
||||
## recursively found schema-looking string or the duplicate manifest field.
|
||||
static func _snapshot_package_format(snapshot: Dictionary) -> int:
|
||||
var systems: Variant = snapshot.get(&"systems", {})
|
||||
if not systems is Dictionary: return FORMAT_VERSION # existing generic extra payload
|
||||
var runtime_data: Variant = systems.get(&"runtime", null)
|
||||
if runtime_data == null: return FORMAT_VERSION # existing generic envelope
|
||||
if not runtime_data is Dictionary: return FORMAT_VERSION # no owned Runtime authority
|
||||
var version: Variant = runtime_data.get(&"runtime_schema_version", 1)
|
||||
if typeof(version) != TYPE_INT: return -1
|
||||
if version >= 1 and version <= 14:
|
||||
return -1 if PurchaseQuoteV2.has_history(runtime_data) else FORMAT_VERSION
|
||||
if version != 15: return -1
|
||||
if not _canonical_owned_key(snapshot, &"systems") or not _canonical_owned_key(systems, &"runtime"): return -1
|
||||
var clock: Variant = snapshot.get(&"clock")
|
||||
if not clock is Dictionary or typeof(clock.get(&"absolute_minute")) != TYPE_INT: return -1
|
||||
return MIMI_PURCHASE_FORMAT_VERSION if PurchaseQuotePlansV2.valid_runtime_format(runtime_data, clock[&"absolute_minute"]) else -1
|
||||
|
||||
|
||||
static func _canonical_owned_key(owner: Dictionary, key: StringName) -> bool:
|
||||
for raw: Variant in owner:
|
||||
if raw == key: return typeof(raw) == TYPE_STRING_NAME
|
||||
return false
|
||||
|
||||
|
||||
static func _package_domain_matches(loaded: Dictionary) -> bool:
|
||||
if not bool(loaded.get(&"ok", false)): return false
|
||||
var manifest: Dictionary = loaded[&"manifest"]
|
||||
var format_version := int(manifest.get("format_version", -1))
|
||||
if format_version not in [FORMAT_VERSION, MIMI_PURCHASE_FORMAT_VERSION]: return false
|
||||
if format_version != _snapshot_package_format(loaded[&"snapshot"]): return false
|
||||
if format_version == MIMI_PURCHASE_FORMAT_VERSION:
|
||||
var duplicate_version: Variant = manifest.get("runtime_schema_version")
|
||||
return _is_integral_json_number(duplicate_version, 15, 15)
|
||||
return true
|
||||
|
||||
|
||||
static func _load_snapshot_absolute(target_path: String, expected_format_version: int,
|
||||
validate_snapshot := true) -> Dictionary:
|
||||
# -2 means either supported current format; -1 still decodes historical
|
||||
# physical packages for explicit migration/reporting. Positive verification
|
||||
# requests keep their exact original physical-format check.
|
||||
if expected_format_version == SUPPORTED_CURRENT_FORMAT:
|
||||
var guard := _guard_identified_formal_format(target_path)
|
||||
if not guard[&"ok"]: return guard
|
||||
var expected := -1 if expected_format_version == SUPPORTED_CURRENT_FORMAT else expected_format_version
|
||||
var loaded := _load_snapshot_absolute_v1(target_path, expected, validate_snapshot)
|
||||
if not loaded[&"ok"]: return loaded
|
||||
var version := int(loaded[&"manifest"].get("format_version", -1))
|
||||
if version in [FORMAT_VERSION, MIMI_PURCHASE_FORMAT_VERSION]:
|
||||
if not _package_domain_matches(loaded):
|
||||
return _with_context(_failure(&"UNSUPPORTED_FORMAT", "package/domain crosslink differs"), {&"formal_and_artifacts_preserved": true})
|
||||
elif expected_format_version == SUPPORTED_CURRENT_FORMAT:
|
||||
return _failure(&"UNSUPPORTED_FORMAT", str(version))
|
||||
return loaded
|
||||
|
||||
|
||||
static func _guard_identified_formal_format(target_path: String) -> Dictionary:
|
||||
var original := _guard_identified_formal_format_v1(target_path)
|
||||
if not original[&"ok"]:
|
||||
# A checksum-damaged future format remains protected by the original
|
||||
# prefix/manifest probe. Only one coherent, fully decoded known2 passes.
|
||||
if original[&"code"] != &"UNSUPPORTED_FORMAT" \
|
||||
or original.get(&"identified_format_version") != MIMI_PURCHASE_FORMAT_VERSION \
|
||||
or original.get(&"identified_format_versions") != [MIMI_PURCHASE_FORMAT_VERSION]: return original
|
||||
var known := _load_snapshot_absolute_v1(target_path, MIMI_PURCHASE_FORMAT_VERSION, true)
|
||||
return {&"ok": true, &"code": &"OK"} if _package_domain_matches(known) else original
|
||||
# Existing malformed/checksum-broken format1 recovery remains allowed. A
|
||||
# successfully decoded Runtime15 hidden in format1 may not be overwritten.
|
||||
var known := _load_snapshot_absolute_v1(target_path, FORMAT_VERSION, false)
|
||||
if known[&"ok"] and not _package_domain_matches(known):
|
||||
var invalid := _failure(&"UNSUPPORTED_FORMAT", "format1 contains reserved/unsupported Runtime history")
|
||||
invalid[&"identified_format_version"] = FORMAT_VERSION
|
||||
invalid[&"identified_format_versions"] = [FORMAT_VERSION]
|
||||
invalid[&"formal_and_artifacts_preserved"] = true
|
||||
return invalid
|
||||
return original
|
||||
|
||||
|
||||
static func _is_integral_json_number(value: Variant, minimum: int, maximum: int) -> bool:
|
||||
if typeof(value) == TYPE_INT:
|
||||
return value >= minimum and value <= maximum
|
||||
@@ -947,7 +1132,7 @@ static func _world_size_is_supported(size: int) -> bool:
|
||||
## Probe only bounded metadata and the fixed binary prefix. An identifiable
|
||||
## unsupported formal format must be rejected before any transaction artifact
|
||||
## is reconciled, even when its compressed payload/checksum is damaged.
|
||||
static func _guard_identified_formal_format(target_path: String) -> Dictionary:
|
||||
static func _guard_identified_formal_format_v1(target_path: String) -> Dictionary:
|
||||
var versions: Array[int] = []
|
||||
var manifest_path := target_path.path_join(MANIFEST_FILE)
|
||||
if FileAccess.file_exists(manifest_path):
|
||||
@@ -1001,6 +1186,15 @@ static func _reconcile_interrupted_formal_save(target_path: String) -> Dictionar
|
||||
if marker_exists and not _formal_transaction_marker_is_valid(marker_path):
|
||||
return _failure(&"TRANSACTION_MARKER_CONFLICT", marker_path)
|
||||
|
||||
# A held migration source owns the absent/formally promoted target. Normal
|
||||
# .bak is an older ordinary-save generation and must not take that name.
|
||||
# Verify migration artifacts before allowing normal-save reconciliation.
|
||||
if DirAccess.dir_exists_absolute(target_path + ".migration.original"):
|
||||
if marker_exists:
|
||||
return _failure(&"MIGRATION_FORMAL_TRANSACTION_CONFLICT", target_path)
|
||||
var migration := _reconcile_interrupted_migration(target_path)
|
||||
return _with_context(migration, {&"migration_reconciliation": migration.duplicate(true)})
|
||||
|
||||
var target_status := _package_status(target_path)
|
||||
var temporary_status := _package_status(temporary_path)
|
||||
var backup_status := _package_status(backup_path)
|
||||
@@ -1425,7 +1619,7 @@ static func _package_status(path: String) -> Dictionary:
|
||||
&"current_loadable": false,
|
||||
&"code": loaded[&"code"],
|
||||
}
|
||||
var current_format := int(loaded[&"manifest"].get("format_version", -1)) == FORMAT_VERSION
|
||||
var current_format := _package_domain_matches(loaded)
|
||||
var schema_valid := bool(SimulationSnapshot.validate(loaded[&"snapshot"])[&"ok"])
|
||||
return {
|
||||
&"exists": true,
|
||||
|
||||
@@ -62,7 +62,7 @@ func stage_dictionary_set(
|
||||
return true,
|
||||
func() -> void:
|
||||
if had_key:
|
||||
target[key] = original_value
|
||||
target[key] = _copy_value(original_snapshot)
|
||||
else:
|
||||
target.erase(key)
|
||||
)
|
||||
@@ -94,7 +94,7 @@ func stage_dictionary_erase(
|
||||
return true,
|
||||
func() -> void:
|
||||
if had_key:
|
||||
target[key] = original_value
|
||||
target[key] = _copy_value(original_snapshot)
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user