"""Reproduce preservation defects, then verify an isolated SaveService fix.""" import hashlib import importlib.util import json import os from pathlib import Path import re import shutil import subprocess import time import uuid ROOT = Path(__file__).resolve().parents[4] OUT = ROOT / "artifacts/original-completion-2026-10-02/p03-save-preservation-r02" PACKET = ROOT / "artifacts/original-completion-2026-10-02/p03-recovery-readonly-candidate" TARGET = "scripts/core/save_service.gd" def sha(path): return hashlib.sha256(path.read_bytes()).hexdigest() def write(path, value): path.write_text(json.dumps(value, ensure_ascii=False, indent=2) + "\n") def main(): OUT.mkdir(parents=True, exist_ok=False) spec = importlib.util.spec_from_file_location("source_regression", Path(__file__).with_name("run_current_regression.py")) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) source = module.source_map() assert sha(ROOT / TARGET) == sha(PACKET / "save_service.base.gd") write(OUT / "source-start.json", source) run_id = uuid.uuid4().hex[:12] stages = Path("/private/tmp") / ("thetree-save-preservation-" + run_id) driver_sha = sha(PACKET / "test_recovery_readonly_candidate.gd") report = {"scope": "identified foreign format preservation and explicit read-only recovery", "stages": {}, "rows": [], "production_applied": False, "driver_sha256": driver_sha} for variant in ("base", "candidate"): stage = stages / variant stage.mkdir(parents=True) for name, expected in source.items(): dest = stage / name dest.parent.mkdir(parents=True, exist_ok=True) shutil.copyfile(ROOT / name, dest) assert sha(dest) == expected profile = "TheTreeSavePreservation-" + run_id + "-" + variant config = (stage / "project.godot").read_text() (stage / "project.godot").write_text(config.replace("[application]", '[application]\nconfig/use_custom_user_dir=true\nconfig/custom_user_dir_name="' + profile + '"', 1)) qa = stage / "tests/diagnostic/save_preservation" qa.mkdir(parents=True) shutil.copyfile(PACKET / "test_recovery_readonly_candidate.gd", qa / "acceptance.gd") assert sha(qa / "acceptance.gd") == driver_sha if variant == "candidate": shutil.copyfile(PACKET / "save_service.candidate.gd", stage / TARGET) report["stages"][variant] = {"path": str(stage), "profile": profile, "target_sha256": sha(stage / TARGET)} write(OUT / "execution.json", report) def run(variant, label, script=None, reproduction=False): stage = Path(report["stages"][variant]["path"]) command = ["godot", "--headless", "--path", str(stage)] command += ["--script", "res://" + script] if script else ["--editor", "--import"] log = OUT / (label + ".log") started = time.monotonic() with log.open("w") as stream: try: code = subprocess.run(command, cwd=stage, env=dict(os.environ), stdout=stream, stderr=subprocess.STDOUT, timeout=900).returncode except subprocess.TimeoutExpired: code = 124 content = log.read_text() counts = re.findall(r"^Recovery read-only candidate: (\d+) checks, (\d+) failures$", content, re.MULTILINE) actual_checks = int(counts[0][0]) if len(counts) == 1 else None if script and not reproduction and actual_checks is None: old_report = json.loads((ROOT / "artifacts/facility-need-pricing-r02-full155-independent-review-2026-10-01-r01/actual155-source-marker-review.json").read_text()) old_markers = {row["test"]: row["actual_marker"] for row in old_report["rows"]} marker = old_markers.get(script) if marker is None: matches = re.findall(r"^.*?: \d+ checks, 0 failures\n", content, re.MULTILINE) marker = matches[0] if len(matches) == 1 else None assert marker is not None and content.count(marker) == 1, label match = re.search(r"checks=(\d+)|(\d+)(?: [A-Za-z]+)* checks", marker) assert match is not None actual_checks = int(next(g for g in match.groups() if g is not None)) failures = int(counts[0][1]) if len(counts) == 1 else None if reproduction: passed = code != 0 and failures is not None and failures > 0 and "SCRIPT ERROR:" not in content else: passed = code == 0 and "SCRIPT ERROR:" not in content and "\nERROR:" not in content and "Unicode parsing error" not in content row = {"variant": variant, "label": label, "exit_code": code, "passed": passed, "expected_defect_reproduction": reproduction, "checks": actual_checks, "failures": failures, "seconds": round(time.monotonic() - started, 3), "log": log.name, "log_sha256": sha(log)} report["rows"].append(row) write(OUT / "execution.json", report) print(json.dumps(row), flush=True) assert passed, label run("base", "base-import") run("candidate", "candidate-import") run("base", "base-defects", "tests/diagnostic/save_preservation/acceptance.gd", True) run("candidate", "candidate-acceptance", "tests/diagnostic/save_preservation/acceptance.gd") for script in ("tests/s6/test_save_preflight.gd", "tests/s6/test_save_operations.gd", "tests/s6/test_runtime_save_lifecycle.gd", "tests/run_tests.gd", "tests/transport/test_transport_save.gd", "tests/ui/test_dimension_migration_ui.gd", "tests/ui/test_supply_management.gd"): if not (Path(report["stages"]["candidate"]["path"]) / script).is_file(): # Resolve only exact repository test filenames, never silently skip. raise AssertionError("missing required suite " + script) run("candidate", script.replace("/", "__").replace(".gd", ""), script) after = module.source_map() changes = [p for p in sorted(set(source) | set(after)) if source.get(p) != after.get(p)] write(OUT / "source-end.json", after) report.update(focused_acceptance_passed=True, source_changes=changes, full_merged_regression_pending=True, original_full_acceptance=False) write(OUT / "execution.json", report) assert not changes print("Save preservation focused acceptance passed; production merge and full regression remain pending.") if __name__ == "__main__": main()