Fix regressions in roster-only suites from A06/A07/P14-03
The formal collector's roster includes 46 suites the Makefile never ran; the first formal attempt stopped on test_required_kitchen and a sweep found: - v15 MIMI purchase saves could not be written once Runtime saves carried mana_reserve (P06-01): the format detector now validates that section and excludes it before the unchanged v15 allowlist, like special_peeping_rooms. - test_required_kitchen's legacy14 exact-load comparison now maps the two approved migrations (fresh A06 reserve at the restored boundary, elevator snapshot v1->v2) after checking each against its contract, in Runtime key order; every other byte must still match. - test_runtime_defense_autonomy allowed Mana to change only by the A06 flow. - test_p08_normal_placement_ops expects 25 palette slots (two warps); its suite-policy pin is updated with flags unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
40364345ab
commit
83b170a4c7
@@ -274,6 +274,42 @@ func _legacy_controls(writer: Dictionary, reader: Dictionary) -> void:
|
||||
_legacy_control(writer, reader, "byte-identical deep copy", "copy")
|
||||
_proof("legacy14-migration-controls", {"attempts": 17, "writer_sha256": _typed_sha(writer), "reader_sha256": _typed_sha(reader), "failures": failures})
|
||||
|
||||
## Approved later save migrations applied when an older save is loaded, each
|
||||
## checked against its own contract and then mapped into `expected` in place:
|
||||
## A06 starts a fresh finite Mana reserve at the restored boundary, and P14-03
|
||||
## raises the elevator snapshot from v1 to v2 with every other field unchanged.
|
||||
func _approved_runtime_migrations(expected: Dictionary, reader: Dictionary) -> Dictionary:
|
||||
var old: Dictionary = expected[&"systems"][&"runtime"]
|
||||
var now: Dictionary = reader[&"systems"][&"runtime"]
|
||||
var fields: Array = []
|
||||
var proof := {}
|
||||
var ok := true
|
||||
if not old.has(&"mana_reserve") and now.has(&"mana_reserve"):
|
||||
var minute := int(expected[&"clock"][&"absolute_minute"])
|
||||
var fresh := {&"version": 1, &"policy_id": &"MP-01-r02", &"capacity": 300, &"generation": 20,
|
||||
&"interval_minutes": 10, &"minute": minute - minute % 10, &"last_flow": {}}
|
||||
ok = ok and now[&"mana_reserve"] == fresh
|
||||
old[&"mana_reserve"] = now[&"mana_reserve"].duplicate(true)
|
||||
fields.append("mana_reserve_absent_to_A06_fresh_start")
|
||||
proof["mana_reserve"] = {"fresh_start_minute": minute - minute % 10, "matches_contract": ok}
|
||||
if old.get(&"elevators", {}).get(&"version") == 1 and now.get(&"elevators", {}).get(&"version") == 2:
|
||||
var raised: Dictionary = old[&"elevators"].duplicate(true)
|
||||
raised[&"version"] = 2
|
||||
var same_otherwise: bool = raised == now[&"elevators"]
|
||||
ok = ok and same_otherwise
|
||||
old[&"elevators"] = raised
|
||||
fields.append("elevators_v1_to_v2")
|
||||
proof["elevators"] = {"only_version_changed": same_otherwise}
|
||||
if not fields.is_empty():
|
||||
# Saves keep the Runtime's own key order, so the mapped tree follows it.
|
||||
ok = ok and old.size() == now.size()
|
||||
var ordered := {}
|
||||
for key: Variant in now:
|
||||
ok = ok and old.has(key)
|
||||
ordered[key] = old.get(key)
|
||||
expected[&"systems"][&"runtime"] = ordered
|
||||
return {"ok": ok, "fields": fields, "proof": proof}
|
||||
|
||||
func _compare_loaded(writer: Dictionary, write_path: String, read_path: String, label: String, migrate_relationships_v1: bool = false) -> void:
|
||||
var reader: Dictionary = runtime.create_snapshot()
|
||||
var old: Dictionary = writer[&"systems"][&"runtime"][&"domain_events"]["recent_events"].back().duplicate(true)
|
||||
@@ -286,6 +322,8 @@ func _compare_loaded(writer: Dictionary, write_path: String, read_path: String,
|
||||
valid = valid and var_to_bytes(event) == var_to_bytes(old)
|
||||
event["event_type"] = actual["event_type"]; event["payload"] = actual["payload"].duplicate(true); replaced += 1
|
||||
var migration_proof := {}
|
||||
var runtime_migrations := _approved_runtime_migrations(expected, reader)
|
||||
valid = valid and runtime_migrations["ok"]
|
||||
if migrate_relationships_v1:
|
||||
_legacy_controls(expected, reader)
|
||||
var migration := _legacy_checkpoint(expected, reader)
|
||||
@@ -300,6 +338,8 @@ func _compare_loaded(writer: Dictionary, write_path: String, read_path: String,
|
||||
if migrate_relationships_v1:
|
||||
binding["mapped_fields"].append("relationships_v1_to_v2")
|
||||
binding["relationships_v1_to_v2"] = migration_proof
|
||||
binding["mapped_fields"].append_array(runtime_migrations["fields"])
|
||||
binding["approved_runtime_migrations"] = runtime_migrations["proof"]
|
||||
_proof(label + "-io1-binding", binding)
|
||||
expect(valid, "whole typed loaded state unchanged except complete identity/saveID-bound IO1: " + label)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user