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.
101 lines
6.0 KiB
Python
101 lines
6.0 KiB
Python
"""Bind atomic conditions to current static leads without promoting them to PASS.
|
|
|
|
Old group evidence supplies search leads only. Presence and unchanged bytes are
|
|
not proof of normal operation, complete content, or accepted release behavior.
|
|
"""
|
|
from datetime import datetime
|
|
import hashlib
|
|
import json
|
|
from pathlib import Path
|
|
import re
|
|
from zoneinfo import ZoneInfo
|
|
|
|
ROOT = Path(__file__).resolve().parents[4]
|
|
PLAN = ROOT / "docs/plans/original-completion-2026-10-02"
|
|
|
|
|
|
def sha(path):
|
|
return hashlib.sha256(path.read_bytes()).hexdigest() if path.is_file() else None
|
|
|
|
|
|
def main():
|
|
atomic = json.loads((PLAN / "atomic_requirements.json").read_text())
|
|
groups = {r["id"]: r for r in json.loads((ROOT / "docs/traceability/original/requirements.json").read_text())}
|
|
baseline = json.loads((ROOT / "artifacts/facility-need-pricing-production-scale-adoption-2026-10-01-r01/after.json").read_text())
|
|
definitions = {}
|
|
for path in sorted((ROOT / "data/facilities").rglob("*.tres")):
|
|
match = re.search(r'^id = &"([^"]+)"$', path.read_text(), re.MULTILINE)
|
|
if match:
|
|
definitions[match.group(1)] = path
|
|
catalog = (ROOT / "scripts/data/facility_catalog.gd").read_text()
|
|
characters = {r["id"] for r in json.loads((ROOT / "data/characters/mvp_unique_characters.json").read_text())["entries"]}
|
|
locators = {}
|
|
rows = []
|
|
|
|
def locate(name, symbol=None):
|
|
key = (name, symbol)
|
|
if key not in locators:
|
|
path = ROOT / name
|
|
entry = {"path": name, "exists": path.is_file(), "sha256": sha(path),
|
|
"matches_retained_baseline": sha(path) == baseline.get(name) if name in baseline else None,
|
|
"semantic_acceptance": "not_verified"}
|
|
if symbol and path.is_file():
|
|
lines = [i for i, line in enumerate(path.read_text().splitlines(), 1) if symbol in line]
|
|
entry.update(symbol=symbol, current_matching_lines=lines, symbol_present=bool(lines))
|
|
locators[key] = entry
|
|
return locators[key]
|
|
|
|
for requirement in atomic["requirements"]:
|
|
source_refs, test_refs = {}, set()
|
|
for group_id in requirement["source_group_ids"]:
|
|
group = groups[group_id]
|
|
for ref in group.get("source_evidence", []):
|
|
source_refs[(ref["path"], ref.get("symbol"))] = locate(ref["path"], ref.get("symbol"))
|
|
test_refs.update(group.get("related_component_tests", []))
|
|
item = {"requirement_id": requirement["id"], "source_group_ids": requirement["source_group_ids"],
|
|
"primary_package": requirement["primary_package"], "planned_normal_entry": requirement["normal_entry"],
|
|
"normal_entry_verified": False, "static_source_leads": list(source_refs.values()),
|
|
"component_test_leads": [locate(t) for t in sorted(test_refs)],
|
|
"save_contract_leads": [locate("scripts/core/save_service.gd"), locate("scripts/core/simulation_snapshot.gd"), locate("autoload/simulation_runtime.gd")],
|
|
"boundary_evidence": "group tests require condition-specific review",
|
|
"implementation_state": "not_reaudited_at_all_required_views", "acceptance_state": "unverified",
|
|
"reviewer": "root static provenance audit"}
|
|
if requirement["id"].startswith("AR.facility."):
|
|
facility_id = requirement["id"].split(".")[2]
|
|
path = definitions.get(facility_id)
|
|
if path:
|
|
name = str(path.relative_to(ROOT))
|
|
item["definition"] = dict(locate(name), catalog_literal_present=("res://" + name) in catalog,
|
|
source_value_approval="requires condition-specific review")
|
|
field = requirement["id"].split(".")[3]
|
|
aliases = {"footprint": "footprint", "layer": "layer", "staff_min": "staff_min", "staff_max": "staff_max",
|
|
"customer_capacity": "customer_capacity", "service_attribute": "service_attribute", "service_price": "base_price",
|
|
"upkeep_gold": "maintenance_gold", "upkeep_mana": "maintenance_mana"}
|
|
if field in aliases:
|
|
prefix = aliases[field] + " = "
|
|
values = [(i, line[len(prefix):]) for i, line in enumerate(path.read_text().splitlines(), 1) if line.startswith(prefix)]
|
|
item["implementation_field"] = {"field": aliases[field], "explicit_lines": values,
|
|
"state": "explicit_implementation_not_yet_source_approved" if values else "inherited_default_not_explicit_approval"}
|
|
else:
|
|
item["definition"] = {"state": "missing_definition", "canonical_audit_id": facility_id}
|
|
if requirement["id"].startswith("AR.heroine."):
|
|
person_id = "heroine_" + requirement["id"].split(".")[2]
|
|
item["character_catalog"] = dict(locate("data/characters/mvp_unique_characters.json"),
|
|
canonical_audit_id=person_id, entry_present=person_id in characters,
|
|
effect_or_route_verified=False)
|
|
if requirement["id"].startswith(("AR.asset.", "AR.art.")):
|
|
item["finished_asset_acceptance"] = {"state": "missing_acceptance", "audit": "assets_platform_audit.json",
|
|
"fallback_counts_as_complete": False}
|
|
rows.append(item)
|
|
report = {"scope": "current static bindings and missing definitions; no group-to-atom PASS promotion",
|
|
"audited_at_jst": datetime.now(ZoneInfo("Asia/Tokyo")).isoformat(), "atomic_register_sha256": sha(PLAN / "atomic_requirements.json"),
|
|
"known_condition_denominator": len(atomic["denominator_ids"]), "rows": rows,
|
|
"unique_source_locators": len(locators), "whole_atom_acceptance_claimed": False,
|
|
"complete_runtime_ui_save_review": False}
|
|
(PLAN / "current_evidence_links.json").write_text(json.dumps(report, ensure_ascii=False, indent=2) + "\n")
|
|
print(json.dumps({k:v for k,v in report.items() if k != "rows"}, ensure_ascii=False))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|