P04-01: 同時発生の更新規約
This commit is contained in:
@@ -29,19 +29,20 @@ LABELS = {"S4": ["boundary", "held", "recovered"]}
|
||||
SLOTS = ["S4-" + label for label in sorted(LABELS["S4"])]
|
||||
MATERIALS = [MANIFEST, BUILD / "audit-support/p04-review-repair22-r01/ACTUAL_CURRENT_PUBLIC_POWER_FUNCTIONS.json"]
|
||||
|
||||
def template_guard(root):
|
||||
if root != PRODUCT.resolve() or not HERE.is_relative_to(BUILD.resolve()):
|
||||
raise ValueError("Root must stage this exact QA/wrapper/plan inside own B")
|
||||
if pin(MANIFEST)["sha256"] != MANIFEST_SHA:
|
||||
raise ValueError("immutable full R17 relocation manifest")
|
||||
manifest = json.loads(MANIFEST.read_text())
|
||||
for name, source in manifest["product_source"].items():
|
||||
# Old absolute paths are lookup keys only. Never open them.
|
||||
row = manifest["original_to_relocated"][source["path"]]
|
||||
actual = pin(root / name)
|
||||
if Path(row["relocated"]).resolve() != root / name or any(
|
||||
actual[k] != source[k] or actual[k] != row[k] for k in ("bytes", "sha256")):
|
||||
raise ValueError("relocated product differs: " + name)
|
||||
def template_guard(root, historical=True):
|
||||
if historical:
|
||||
if root != PRODUCT.resolve() or not HERE.is_relative_to(BUILD.resolve()):
|
||||
raise ValueError("Root must stage this exact QA/wrapper/plan inside own B")
|
||||
if pin(MANIFEST)["sha256"] != MANIFEST_SHA:
|
||||
raise ValueError("immutable full R17 relocation manifest")
|
||||
manifest = json.loads(MANIFEST.read_text())
|
||||
for name, source in manifest["product_source"].items():
|
||||
# Old absolute paths are lookup keys only. Never open them.
|
||||
row = manifest["original_to_relocated"][source["path"]]
|
||||
actual = pin(root / name)
|
||||
if Path(row["relocated"]).resolve() != root / name or any(
|
||||
actual[k] != source[k] or actual[k] != row[k] for k in ("bytes", "sha256")):
|
||||
raise ValueError("relocated product differs: " + name)
|
||||
probe = QA.read_text()
|
||||
import re
|
||||
if ":=" in probe or re.search(r"\bvar\s+\w+\s*=", probe) or re.search(r"\bfor\s+\w+\s+in\b", probe):
|
||||
@@ -105,12 +106,33 @@ def main():
|
||||
help="optional passed registered cache; default is fresh, without cache access")
|
||||
parser.add_argument("--godot", type=Path, default=ENGINE)
|
||||
parser.add_argument("--check-only", action="store_true")
|
||||
parser.add_argument("--main")
|
||||
parser.add_argument("--submission")
|
||||
parser.add_argument("--tested-tree")
|
||||
parser.add_argument("--historical-r17", action="store_true")
|
||||
args = parser.parse_args()
|
||||
shared = module("fresh_q_shared", HERE.parent / "s5/run_s5_native.py")
|
||||
mode = shared.select_mode(args)
|
||||
fresh = mode == "fresh-q"
|
||||
if fresh and "--project-root" not in sys.argv:
|
||||
raise ValueError("fresh-q requires explicit --project-root")
|
||||
if fresh and "--cache-run" not in sys.argv:
|
||||
args.cache_run = None
|
||||
engine_descriptor = shared.engine_pin(args.godot) if fresh else None
|
||||
provenance = None
|
||||
|
||||
engine_descriptor = engine_pin(args.godot)
|
||||
if args.cache_run is not None and args.cache_run.resolve() != CACHE_RUN.resolve():
|
||||
raise ValueError("only registered own-B full-run cache")
|
||||
if args.project_root.is_symlink():
|
||||
raise ValueError("project root symlink")
|
||||
root = args.project_root.resolve()
|
||||
out = args.output.resolve()
|
||||
if fresh:
|
||||
if not out.is_relative_to(BUILD.resolve()) or not args.plan.resolve().is_relative_to(BUILD.resolve()):
|
||||
raise ValueError("fresh plan/output must stay inside BUILD")
|
||||
if out.exists() or out.is_symlink() or (args.check_only and args.plan.exists()):
|
||||
raise ValueError("fresh output and plan required")
|
||||
if not out.is_relative_to(BUILD.resolve()) or not args.plan.resolve().is_relative_to(BUILD.resolve()):
|
||||
raise ValueError("plan/output must stay in task build")
|
||||
if out.exists() or out.is_symlink():
|
||||
@@ -120,15 +142,17 @@ def main():
|
||||
r = module("s4_standard_runner", root / "tools/run_all_tests.py")
|
||||
# Preserve the reviewed source_refs -> exactly one QA override order.
|
||||
source_before = r.source_refs(root)
|
||||
if fresh:
|
||||
provenance = shared.fresh_q_guard(root, args.main, args.submission, args.tested_tree)
|
||||
refs = dict(source_before)
|
||||
refs[TEST] = pin(QA)
|
||||
template_guard(root)
|
||||
template_guard(root, historical=not fresh)
|
||||
expected = {n: dict(bytes=p["bytes"], sha256=p["sha256"]) for n, p in refs.items()}
|
||||
fixed = [pin(p) for p in MATERIALS + [
|
||||
fixed = [pin(p) for p in ([] if fresh else MATERIALS) + [
|
||||
QA, Path(__file__), HERE / "S4_ROOT_RUN.md",
|
||||
root / "tests/transport/test_runtime_transport.gd",
|
||||
root / "tests/staff/test_rescue_elevator.gd",
|
||||
CONTRACTS,
|
||||
root / shared.C_REL if fresh else CONTRACTS,
|
||||
]]
|
||||
selected = dict(root_before=source_before, map={n: p["sha256"] for n, p in refs.items()}, timeout=1200)
|
||||
cache_note = None
|
||||
@@ -154,6 +178,16 @@ def main():
|
||||
cache_receipts=cache_receipts, cache_access=cache_note,
|
||||
phases=["import", "parse", "writer", "reader"],
|
||||
native_engine_launches=0, whole_goal_accepted=False, unit_accepted=False)
|
||||
if fresh:
|
||||
uid_plan, uid_snapshot, uid_binding = shared.load_uid_helper(root, r, source_before)
|
||||
uid_source = copy.deepcopy(expected)
|
||||
uid_plan_map = uid_plan(refs)
|
||||
plan.update(protocol="p04-s4-fresh-q-v1", mode=mode, provenance=provenance, engine=engine_descriptor,
|
||||
engine_sha256=engine_descriptor["sha256"], uid_helper=uid_binding,
|
||||
uid_plan=uid_plan_map, import_mode="fresh" if args.cache_run is None else "cache",
|
||||
historical_r17=False, fresh_q_evidence=False)
|
||||
fixed.append(pin(HERE.parent / "s5/run_s5_native.py"))
|
||||
# No historical execution is admitted.
|
||||
# Check-only only reads source/materials and writes the plan in task build.
|
||||
# Reads engine identity; never launches Godot or inspects players/processes.
|
||||
if args.check_only:
|
||||
@@ -163,7 +197,7 @@ def main():
|
||||
QA_overrides=[TEST], fixed_pins=len(fixed), plan=str(args.plan),
|
||||
plan_sha256=r.sha(args.plan), cache_access=cache_note), ensure_ascii=False))
|
||||
return 0
|
||||
r.require(root == PRODUCT.resolve() and len(source_before) == 1338, "Root native requires product 1338; worker plan is not native evidence")
|
||||
r.require(fresh, "historical mode is read-only")
|
||||
r.require(args.plan.is_file() and r.read(args.plan) == plan, "run exact check-only plan first")
|
||||
engine_observations = []
|
||||
engine_identity = dict(before=engine_descriptor, during=[], after=None)
|
||||
@@ -178,9 +212,19 @@ def main():
|
||||
except BaseException as caught:
|
||||
engine_observations.append(dict(stage=label, error=str(caught)))
|
||||
raise
|
||||
reports, phase_call, uid_state = shared.make_uid_policy(r, uid_snapshot, uid_source, uid_plan_map, out)
|
||||
engine_checks = []
|
||||
def fresh_engine_check(label):
|
||||
value = shared.engine_pin(args.godot, engine_descriptor)
|
||||
engine_checks.append(dict(label=label, descriptor=value))
|
||||
def fixed_guard():
|
||||
fresh_engine_check("fixed")
|
||||
r.require(shared.fresh_q_guard(root, args.main, args.submission, args.tested_tree) == provenance,
|
||||
"fresh Q provenance changed")
|
||||
r.require(pin(root / uid_binding["helper_path"])["sha256"] == uid_binding["helper_sha256"],
|
||||
"UID helper changed")
|
||||
repin("cleanup-fixed-guard")
|
||||
template_guard(root)
|
||||
template_guard(root, historical=not fresh)
|
||||
for value in fixed + cache_receipts:
|
||||
r.require(pin(value["path"]) == value, "fixed input changed: " + value["path"])
|
||||
fixed_guard()
|
||||
@@ -257,7 +301,7 @@ def main():
|
||||
r.require(len(paths) == 316, "complete 316-script parse roster")
|
||||
r.write(out / "parse-paths.json", paths)
|
||||
markers = module("s4_markers", root / "tools/strict_test_markers.py")
|
||||
contracts = markers.load_contracts(CONTRACTS)
|
||||
contracts = markers.load_contracts(root / shared.C_REL if fresh else CONTRACTS)
|
||||
contracts[TEST] = dict(test=TEST, template="S4 power: <checks> checks, <failures> failures", required=True)
|
||||
policy = r.read(r.SUPPORT / "suite-policy.json")
|
||||
r.require(TEST not in policy["suite_policies"], "no normal suite watchdog/policy override")
|
||||
@@ -283,7 +327,10 @@ def main():
|
||||
repin("before-" + phase)
|
||||
r.write(out / ("engine-identity-before-" + phase + ".json"),
|
||||
dict(engine_observations[-1], observation_index=len(engine_observations)-1))
|
||||
row = r.execute_phase(str(engine), stage, out, phase, test, selected, expected,
|
||||
fresh_engine_check("before-" + phase)
|
||||
if phase == "import" and old is None:
|
||||
r.require(not (stage / ".godot").exists(), "fresh import cache absent")
|
||||
row = phase_call(str(engine), stage, out, phase, test, selected, expected,
|
||||
previous, policy, contracts, paths, public, protected, root,
|
||||
outer, markers, diagnostics, owners, audio)
|
||||
phases.append(row)
|
||||
@@ -330,6 +377,8 @@ def main():
|
||||
# Fixed guard always follows ownership cleanup, even if setup or an engine failed.
|
||||
try:
|
||||
fixed_guard()
|
||||
r.require(uid_snapshot(stage, uid_source, uid_plan_map) == uid_state["accepted"], "UID seal after cleanup")
|
||||
r.write(out / "fresh-engine-checks.json", engine_checks)
|
||||
after = r.source_refs(root)
|
||||
r.write(out / "source_after.json", after)
|
||||
r.require(after == source_before, "whole product source unchanged")
|
||||
@@ -345,7 +394,7 @@ def main():
|
||||
except BaseException as caught:
|
||||
guards.append(type(caught).__name__ + ": " + str(caught))
|
||||
pids = [p.pid for p in outer.OWNED]
|
||||
passed = (error is None and not guards and not cleanup_errors and len(phases) == 4
|
||||
passed = (uid_state["accepted"] is not None and error is None and not guards and not cleanup_errors and len(phases) == 4
|
||||
and all(p["passed"] for p in phases) and len(pids) == len(set(pids)) == 4
|
||||
and all(p["engine_ended"] for p in cleanup))
|
||||
execution = dict(passed=passed, error=error, guard_errors=guards, phases=phases,
|
||||
|
||||
Reference in New Issue
Block a user