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:
@@ -0,0 +1,82 @@
|
||||
"""Run the standard source regression and bind every result to exact inputs."""
|
||||
from datetime import datetime
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
from pathlib import Path
|
||||
import re
|
||||
import subprocess
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[4]
|
||||
OUT = ROOT / "artifacts/original-completion-2026-10-02/full-regression-r01"
|
||||
|
||||
|
||||
def sha(path):
|
||||
return hashlib.sha256(path.read_bytes()).hexdigest()
|
||||
|
||||
|
||||
def source_map():
|
||||
paths = [p for folder in ("autoload", "scripts", "scenes", "data", "tests", "assets", "tools")
|
||||
for p in (ROOT / folder).rglob("*") if p.is_file() and p.name != ".DS_Store"]
|
||||
paths += [ROOT / p for p in ("project.godot", "export_presets.cfg", "Makefile", "AGENTS.md")]
|
||||
return {str(p.relative_to(ROOT)): sha(p) for p in sorted(paths)}
|
||||
|
||||
|
||||
def write(name, data):
|
||||
(OUT / name).write_text(json.dumps(data, ensure_ascii=False, indent=2) + "\n")
|
||||
|
||||
|
||||
def main():
|
||||
global OUT
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--output", type=Path, default=OUT)
|
||||
args = parser.parse_args()
|
||||
OUT = args.output.resolve()
|
||||
OUT.mkdir(parents=True, exist_ok=False)
|
||||
before = source_map()
|
||||
roster = ["tests/run_tests.gd"] + sorted(str(p.relative_to(ROOT)) for p in (ROOT / "tests").rglob("test*.gd")
|
||||
if "export" not in p.relative_to(ROOT).parts and p.name != "test_kernel_and_save.gd")
|
||||
assert len(roster) == len(set(roster))
|
||||
write("source-start.json", before)
|
||||
write("expected-tests.json", roster)
|
||||
started_at = datetime.now(ZoneInfo("Asia/Tokyo")).isoformat()
|
||||
code = subprocess.run(["python3", "tools/run_all_tests.py", "--output", str(OUT / "suites")], cwd=ROOT).returncode
|
||||
after = source_map()
|
||||
write("source-end.json", after)
|
||||
changes = sorted(path for path in set(before) | set(after) if before.get(path) != after.get(path))
|
||||
retained = 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 retained["rows"]}
|
||||
results = json.loads((OUT / "suites/all-tests.json").read_text())
|
||||
reviewed = []
|
||||
for row in results:
|
||||
log = OUT / "suites" / row["log"]
|
||||
content = log.read_text()
|
||||
if row["test"] in old_markers:
|
||||
marker = old_markers[row["test"]]
|
||||
matches = [marker] if content.count(marker) == 1 else []
|
||||
else:
|
||||
matches = re.findall(r"^.*?: \d+ checks, 0 failures\n", content, re.MULTILINE)
|
||||
match = re.search(r"checks=(\d+)|(\d+)(?: [A-Za-z]+)* checks", matches[0]) if len(matches) == 1 else None
|
||||
count = int(next(g for g in match.groups() if g is not None)) if match else None
|
||||
passed = row["exit_code"] == 0 and not row["failed"] and count is not None and "Godot Engine v4.7.2" in content
|
||||
reviewed.append(dict(test=row["test"], actual_checks=count, passed=passed,
|
||||
source_sha256=before.get(row["test"]), log_sha256=sha(log),
|
||||
log=row["log"], completion_marker=matches[0] if len(matches) == 1 else None,
|
||||
unicode_diagnostic_lines=content.count("Unicode parsing error")))
|
||||
actual_names = [r["test"] for r in reviewed]
|
||||
verified = code == 0 and not changes and actual_names == roster and all(r["passed"] for r in reviewed)
|
||||
report = dict(scope="current source regression, not original full-game acceptance", passed=verified,
|
||||
source_head=subprocess.check_output(["git", "rev-parse", "HEAD"], cwd=ROOT, text=True).strip(),
|
||||
source_map_sha256=sha(OUT / "source-start.json"), source_files=len(before),
|
||||
started_at_jst=started_at, finished_at_jst=datetime.now(ZoneInfo("Asia/Tokyo")).isoformat(),
|
||||
runner_exit_code=code, suites=len(reviewed), checks=sum(r["actual_checks"] or 0 for r in reviewed),
|
||||
failed_tests=[r["test"] for r in reviewed if not r["passed"]], changed_paths=changes,
|
||||
rows=reviewed, original_full_acceptance=False, windows_acceptance=False)
|
||||
write("verification.json", report)
|
||||
print(json.dumps({k:v for k,v in report.items() if k != "rows"}, ensure_ascii=False), flush=True)
|
||||
return 0 if verified else 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user