Files
TheTree_mock/docs/plans/original-completion-2026-10-02/execution/verify_progress_guards.py
T
Takeshi b84bade045 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.
2026-10-11 15:58:00 +09:00

82 lines
3.9 KiB
Python

"""Exercise plan-validator rejection guards in temporary planning copies only."""
from contextlib import redirect_stdout
from datetime import datetime
import importlib.util
import io
import json
from pathlib import Path
import shutil
import tempfile
from zoneinfo import ZoneInfo
PLAN = Path(__file__).resolve().parents[1]
ROOT = PLAN.parents[2]
INPUTS = [
"work_packages.json", "requirement_coverage.json", "baseline.json", "decisions.json",
"progress_contract.json", "atomic_requirements.json", "atomic_denominator_freeze.json",
"current_evidence_links.json", "progress_snapshot.json", "IMPLEMENTATION_PLAN.md",
]
def exercise(case, filename, mutate, expected):
with tempfile.TemporaryDirectory(prefix="thetree-progress-guard-") as directory:
stage = Path(directory) / "docs/plans/original-completion-2026-10-02"
stage.mkdir(parents=True)
for name in INPUTS:
shutil.copyfile(PLAN / name, stage / name)
decisions = json.loads((PLAN / "decisions.json").read_text())
for decision in decisions["confirmed"]:
if "reference" in decision:
destination = stage / decision["reference"]
destination.parent.mkdir(parents=True, exist_ok=True)
shutil.copyfile(PLAN / decision["reference"], destination)
data = json.loads((stage / filename).read_text())
mutate(data)
(stage / filename).write_text(json.dumps(data, ensure_ascii=False, indent=2) + "\n")
spec = importlib.util.spec_from_file_location("isolated_plan_validation", PLAN / "validate_plan.py")
validator = importlib.util.module_from_spec(spec)
spec.loader.exec_module(validator)
validator.PLAN = stage
validator.ROOT = ROOT
exit_code = 0
with redirect_stdout(io.StringIO()):
try:
validator.main()
except SystemExit as exc:
exit_code = exc.code
result = json.loads((stage / "plan_validation.json").read_text())
expected_result = (exit_code == 1 and expected in result["failed_checks"]) if expected else (exit_code == 0 and not result["failed_checks"])
return {"case": case, "exit_code": exit_code, "expected_guard": expected,
"expected_result": expected_result,
"failed_checks": result["failed_checks"]}
def main():
rows = [
exercise("unmodified_control", "progress_contract.json", lambda data: None, None),
exercise("unresolved_final_percentage", "progress_contract.json",
lambda data: data.update(total_game_acceptance_percent=1.0),
"unresolved_final_denominator_not_reported_as_total"),
exercise("stale_static_index_register", "current_evidence_links.json",
lambda data: data.update(atomic_register_sha256="0" * 64),
"evidence_index_register_pin_matches"),
exercise("unreviewed_atom_promoted_to_pass", "atomic_requirements.json",
lambda data: data["requirements"][0]["view_results"]["runtime"].update(state="pass"),
"unreviewed_atomic_views_remain_unverified"),
exercise("P03_whole_package_completed", "work_packages.json",
lambda data: next(row for row in data if row["id"] == "P03").update(state="completed"),
"P01_P03_not_whole_package_completed"),
]
report = {"scope": "plan-validator negative guards; isolated document copies, no game execution",
"checked_at_jst": datetime.now(ZoneInfo("Asia/Tokyo")).isoformat(),
"passed": all(row["expected_result"] for row in rows), "rows": rows,
"production_game_source_edits": 0, "new_engine_runs": 0}
(PLAN / "progress_validator_guard_checks.json").write_text(json.dumps(report, ensure_ascii=False, indent=2) + "\n")
print(json.dumps(report, ensure_ascii=False))
if not report["passed"]:
raise SystemExit(1)
if __name__ == "__main__":
main()