P04-01: 同時発生の更新規約

This commit is contained in:
Agent Control Runner
2026-10-18 12:00:07 +09:00
parent 27b18b75c9
commit 8e25213e91
5 changed files with 323 additions and 8 deletions
@@ -0,0 +1,41 @@
{
"py_compile_ast": [
{
"path": "docs/plans/original-completion-2026-10-02/execution/p04-01/s5/run_s5_native.py",
"sha256": "e96b2793d7352ac52e16505c9c4cde3d151497763be3cb47926338df070b05e5",
"py_compile": "passed",
"ast": "passed",
"top_level_functions": [
"r17_relocation_guard",
"probe_guard",
"module",
"pin",
"load_uid_helper",
"make_uid_policy",
"engine_pin",
"select_mode",
"fresh_q_guard",
"main"
]
},
{
"path": "docs/plans/original-completion-2026-10-02/execution/p04-01/s5/s5_uid_controls.py",
"sha256": "17069b87b98c385e1298152c9c5c2f23c8710b79eb19aef073c64ce215f6c902",
"py_compile": "passed",
"ast": "passed",
"top_level_functions": [
"module",
"main"
]
},
{
"path": "docs/plans/original-completion-2026-10-02/execution/p04-01/s5/s5_wrapper_fixtures.py",
"sha256": "1a4daebf46051e975a9cc740660c4672371ea6a9e6cb04cbc1d458ece5f0151d",
"py_compile": "passed",
"ast": "passed",
"top_level_functions": [
"main"
]
}
]
}
@@ -0,0 +1,28 @@
# REPAIR36 — bounded preparation submitted, no acceptance credit
Changes are limited to the S5 wrapper, new pure UID controls and these documents.
Actual-Q AST helper loading, finite derived UID planning, import sealing,
private-globals phase instrumentation, phase receipts and cleanup rechecks
supplement the existing expected inventory. Historical selection, existing
require gates, ownership/PID, engine, cache and formal mirror rules remain.
The helper is loaded from real Q before controls construct synthetic refs.
Only py_compile and AST checks are executed and recorded in
REPAIR36_STATIC_CHECKS.json. Wrapper fixtures, UID controls, check-only plans,
Git negatives and every native diagnostic are unexecuted. No functional pass,
full regression, 15+EV batch, original credit or completion is claimed.
No Git, engine, Runner or other agent operations were performed. A shell
heredoc edit failed before Python execution; edits then used apply_patch.
Context gap: Q runner API was read from
build/owner-handoff/p04-after-p26-closure-r01/q35-uid-diagnostic/run_all_tests.py.reference;
Root must confirm the actual Q runner matches that mirror (320ca668…)
at runtime. Helper implementation was read from the adjacent P13 reference;
runtime loading uses only the actual pinned Q, never either mirror.
Pending: S5 destruction/midnight/exit drivers; S1–S4/collector fresh Q;
derived 184 suites / 329 parse; truthful index; Root exact-candidate qualification.
Root order is py_compile → wrapper fixtures → UID controls with explicit scratch
→ fresh check-only plan → exactly one new-name diagnostic. The failed r35
diagnostic is preserved. All 7 domains + EV, formal 16/88, original 30/88,
P04 credit 0, all six D05 approvals pending, M c0ea009 and allowed_paths stay fixed.
@@ -15,13 +15,13 @@ all three full lowercase HEX40 inputs. R17 MANIFEST and repair22 power-functions
JSON are historical_not_inputs in fresh-Q plans, never fresh-Q fixed pins. JSON are historical_not_inputs in fresh-Q plans, never fresh-Q fixed pins.
No old S1–S4 record is renamed or reused as fresh proof. No old S1–S4 record is renamed or reused as fresh proof.
REPAIR35 is check-only only; no native/batch admission until S5 REPAIR36 supplies a bounded UID diagnostic, not native/batch admission. Full admission still awaits S5
destruction/midnight/exit, S1–S4/collector fresh Q, 184 suites / 329 parse and the destruction/midnight/exit, S1–S4/collector fresh Q, 184 suites / 329 parse and the
truthful index are ready. Root run order and exact-candidate qualification also truthful index are ready. Root run order and exact-candidate qualification also
remain pending. The native implementation is retained for later Root admission; remain pending. The native implementation is retained for later Root admission;
this change and a check-only plan give no admission or acceptance credit. this change and a check-only plan give no admission or acceptance credit.
After final S35, Root alone performs these steps (not performed by the worker): After the final submission, Root alone prepares Q using these steps (not performed by the worker):
1. Set S to the final submission and M to 1. Set S to the final submission and M to
`c0ea009b28a7649aca6a433a1a24dc0be5e7ab81`; derive Qt with `c0ea009b28a7649aca6a433a1a24dc0be5e7ab81`; derive Qt with
@@ -31,15 +31,15 @@ After final S35, Root alone performs these steps (not performed by the worker):
checkout carrier of Q, never normal Runner C. R34 and Root normal_c_join checkout carrier of Q, never normal Runner C. R34 and Root normal_c_join
remain unchanged. remain unchanged.
3. Stage the s5 directory under Root's own B, the registered BUILD directory. 3. Stage the s5 directory under Root's own B, the registered BUILD directory.
4. Run only the check-only path, with fresh output and plan paths: 4. Follow the REPAIR36 order below, with fresh output and plan paths:
```sh ```sh
BUILD_OUTPUT_DIR="$B" python3 "$B/.../run_s5_native.py" \ BUILD_OUTPUT_DIR="$B" python3 "$B/.../run_s5_native.py" \
--project-root "$wt" --main "$M" --submission "$S" --tested-tree "$Qt" \ --project-root "$wt" --main "$M" --submission "$S" --tested-tree "$Qt" \
--check-only --plan "$B/p04-s5-plan-r35.json" --output "$B/p04-s5-native-r35" --check-only --plan "$B/p04-s5-plan-r36.json" --output "$B/p04-s5-DIAG-r36"
``` ```
5. Run `s5_wrapper_fixtures.py` separately. Its JSON always has accepted=false. 5. Pure fixtures and controls follow the order below. Their JSON has accepted=false.
6. In separate controlled check-only cases, require rejection for: a dirty file; 6. In separate controlled check-only cases, require rejection for: a dirty file;
an untracked file; HEAD tree unequal to --tested-tree; wrong --submission; an untracked file; HEAD tree unequal to --tested-tree; wrong --submission;
--main unequal to the frozen anchor. Preserve each actual rejection receipt --main unequal to the frozen anchor. Preserve each actual rejection receipt
@@ -55,4 +55,34 @@ S5 destruction, midnight and exit cases remain unimplemented. The preserved
`PENDING.md` is historical partial31 text; this document records only the added, `PENDING.md` is historical partial31 text; this document records only the added,
unexecuted power pair. D05 six approvals, A01, frozen M, 16/88 and P04 credit 0 unexecuted power pair. D05 six approvals, A01, frozen M, 16/88 and P04 credit 0
are unchanged. All 7 domains + EV and original 30/88 remain fixed. Root alone are unchanged. All 7 domains + EV and original 30/88 remain fixed. Root alone
performs later qualification; no engine is authorized by REPAIR35. performs later qualification; no engine is authorized for this worker.
## REPAIR36 UID diagnostic protocol and Root order
Protocol `p04-s5-fresh-q-uid-diagnostic-v1` is a diagnostic composite with
standard_execute_phase_context=false, native_admissible=false and
fresh_q_evidence=false. The wrapper extracts only uid_plan and uid_snapshot
from the actual pinned Q helper using AST, binding shared to the actual Q
runner. It does not execute the helper module. Plans derive finite UID owners
from staged refs; import alone seals exact UID bytes. Private function globals
replace declared_reports while preserving the execute_phase code object.
All four phase UID receipts and the post-cleanup seal are required.
Historical mode has no UID instrumentation and remains read-only.
Root order, all unexecuted by this worker:
1. py_compile the wrapper and both pure control files.
2. Run s5_wrapper_fixtures.py.
3. Run `python3 "$B/.../s5_uid_controls.py" --project-root "$wt" --scratch "$B/p04-s5-uid-controls-r36"`.
Scratch must be absolute, absent, outside Q, with an existing parent in BUILD.
4. Produce a fresh check-only plan with the command above.
5. Perform exactly one fresh diagnostic with the identical command and paths,
removing only --check-only. Use a new output name; preserve
`p04-s5-DIAG-r35` as FAILED. This is a bounded diagnostic, not full admission.
Root must confirm the actual Q run_all_tests.py matches the supplied reference
(sha256 prefix 320ca668); the worker read only the mirror for Q API context.
Runtime helper fingerprints and source/provenance guards bind the actual Q.
No full regression, 15+EV batch or original credit is claimed. The S5
destruction/midnight/exit drivers, S1–S4/collector fresh Q, derived 184 suites /
329 parse, truthful index and Root exact-candidate qualification remain pending.
@@ -2,6 +2,10 @@
"""S5-only native entry. --check-only never loads ownership helpers or starts Godot.""" """S5-only native entry. --check-only never loads ownership helpers or starts Godot."""
from pathlib import Path from pathlib import Path
import argparse import argparse
import ast
import builtins
import inspect
import types
import copy import copy
import hashlib import hashlib
import importlib.util import importlib.util
@@ -74,6 +78,74 @@ def pin(path):
data = path.read_bytes() data = path.read_bytes()
return dict(path=str(path), bytes=len(data), sha256=hashlib.sha256(data).hexdigest()) return dict(path=str(path), bytes=len(data), sha256=hashlib.sha256(data).hexdigest())
def load_uid_helper(root, r, refs):
hp = root / "tools/run_p13_reference_tests.py"
descriptor = pin(hp)
r.require(all(descriptor[k] == refs["tools/run_p13_reference_tests.py"][k]
for k in ("bytes", "sha256")), "actual Q UID helper pin")
src = hp.read_bytes()
r.require(len(src) == descriptor["bytes"] and
hashlib.sha256(src).hexdigest() == descriptor["sha256"], "stable helper read")
tree = ast.parse(src, filename=str(hp))
nodes = []
for name in ("uid_plan", "uid_snapshot"):
matches = [n for n in tree.body if isinstance(n, ast.FunctionDef) and n.name == name]
r.require(len(matches) == 1, "exactly one UID helper: " + name)
nodes.append(matches[0])
ns = {"__builtins__": builtins, "shared": r, "re": re, "stat": stat}
exec(compile(ast.Module(body=nodes, type_ignores=[]), str(hp), "exec"), ns)
binding = dict(helper_path="tools/run_p13_reference_tests.py",
helper_sha256=descriptor["sha256"], helper_bytes=descriptor["bytes"],
functions={n.name: hashlib.sha256(ast.get_source_segment(src.decode(), n).encode()).hexdigest()
for n in nodes}, shared_module="tools/run_all_tests.py",
shared_sha256=r.sha(root / "tools/run_all_tests.py"))
return ns["uid_plan"], ns["uid_snapshot"], binding
def make_uid_policy(r, uid_snapshot, source, plan, out):
state = dict(source=source, plan=plan, accepted=None, phase=None)
def reports(stage, exp, previous, requested):
r.require(not previous and not requested, "S5 has no generated reports")
snap = uid_snapshot(stage, source, plan)
if state["accepted"] is None:
r.require(state["phase"] == "import", "UID generation only during import")
state["accepted"] = snap
exp.update({n: {k: p[k] for k in ("bytes", "sha256")} for n, p in snap.items()})
r.write(out / "accepted-uids.json", snap)
r.require(snap == state["accepted"], "sealed UID bytes unchanged")
return r.declared_reports(stage, exp, previous, requested)
execute = types.FunctionType(r.execute_phase.__code__, dict(vars(r), declared_reports=reports),
"execute_phase", r.execute_phase.__defaults__, r.execute_phase.__closure__)
r.require(execute.__code__ is r.execute_phase.__code__, "unchanged execute_phase code object")
def phase_call(*args):
stage, phase_out, phase = args[1:4]
r.require(phase_out == out, "UID receipt output binding")
state["phase"] = phase
before, after = None, None
try:
if phase == "import":
r.require(state["accepted"] is None and not (out / "uid-plan.json").exists(), "single UID import")
r.require(r.inventory(stage, stage=True) == source, "original stage before import")
before = {}
r.write(out / "uid-plan.json", plan)
else:
before = uid_snapshot(stage, source, plan)
r.require(before == state["accepted"], "UID set before phase unchanged")
row = execute(*args)
if row["passed"]:
snap = uid_snapshot(stage, source, plan)
r.require(snap == state["accepted"], "UID set after phase unchanged")
after = snap
return row
finally:
r.write(out / (phase + "-uids.json"), dict(before=before, after=after))
return reports, phase_call, state
def engine_pin(path, expected=None): def engine_pin(path, expected=None):
path = Path(path) path = Path(path)
if path != ENGINE or any(p.is_symlink() for p in (path, *path.parents)): if path != ENGINE or any(p.is_symlink() for p in (path, *path.parents)):
@@ -206,6 +278,7 @@ def main():
r17_relocation_guard(root) r17_relocation_guard(root)
probe_guard(root) probe_guard(root)
expected = {n: dict(bytes=p["bytes"], sha256=p["sha256"]) for n, p in refs.items()} expected = {n: dict(bytes=p["bytes"], sha256=p["sha256"]) for n, p in refs.items()}
uid_source = copy.deepcopy(expected)
contracts_path = root / C_REL if mode == "fresh-q" else CONTRACTS contracts_path = root / C_REL if mode == "fresh-q" else CONTRACTS
fixed = [pin(p) for p in ([] if mode == "fresh-q" else MATERIALS) + [ fixed = [pin(p) for p in ([] if mode == "fresh-q" else MATERIALS) + [
QA, Path(__file__), HERE / "S5_ROOT_RUN.md", QA, Path(__file__), HERE / "S5_ROOT_RUN.md",
@@ -241,6 +314,19 @@ def main():
cache_receipts=cache_receipts, cache_access=cache_note, cache_receipts=cache_receipts, cache_access=cache_note,
phases=["import", "parse", "writer", "reader"], phases=["import", "parse", "writer", "reader"],
native_engine_launches=0, whole_goal_accepted=False, unit_accepted=False) native_engine_launches=0, whole_goal_accepted=False, unit_accepted=False)
if mode == "fresh-q":
uid_plan, uid_snapshot, binding = load_uid_helper(root, r, source_before)
uid_plan_map = uid_plan(refs)
r.require(len(uid_plan_map) > 0, "nonempty derived UID plan")
r.require(all(p["owner"] in refs and p["owner_sha256"] == refs[p["owner"]]["sha256"]
for p in uid_plan_map.values()), "UID plan owner bindings")
plan.update(protocol="p04-s5-fresh-q-uid-diagnostic-v1", diagnostic_composite=True,
standard_execute_phase_context=False, uid_plan=uid_plan_map,
uid_plan_count=len(uid_plan_map), instrumentation=dict(
wrapper_sha256=r.sha(__file__),
execute_phase_source_sha256=hashlib.sha256(inspect.getsource(r.execute_phase).encode()).hexdigest(),
declared_reports_source_sha256=hashlib.sha256(inspect.getsource(r.declared_reports).encode()).hexdigest(),
callback="private-globals declared_reports + phase wrapper", uid_helper=binding))
# Check-only only reads source/materials and writes the plan in task build. # Check-only only reads source/materials and writes the plan in task build.
# Reads engine identity; never launches Godot or inspects players/processes. # Reads engine identity; never launches Godot or inspects players/processes.
if args.check_only: if args.check_only:
@@ -254,6 +340,7 @@ def main():
raise ValueError("historical R17 is read-only") raise ValueError("historical R17 is read-only")
r.require(len(source_before) == provenance["selected_file_count"], "fresh-q selected count") r.require(len(source_before) == provenance["selected_file_count"], "fresh-q selected count")
r.require(args.plan.is_file() and r.read(args.plan) == plan, "run exact check-only plan first") r.require(args.plan.is_file() and r.read(args.plan) == plan, "run exact check-only plan first")
reports, phase_call, uid_state = make_uid_policy(r, uid_snapshot, uid_source, plan["uid_plan"], out)
engine_observations = [] engine_observations = []
engine_identity = dict(before=engine_descriptor, during=[], after=None) engine_identity = dict(before=engine_descriptor, during=[], after=None)
def repin(label): def repin(label):
@@ -272,6 +359,9 @@ def main():
r.require(fresh_q_guard(root, args.main, args.submission, args.tested_tree) == provenance, r.require(fresh_q_guard(root, args.main, args.submission, args.tested_tree) == provenance,
"fresh-q provenance changed") "fresh-q provenance changed")
probe_guard(root) probe_guard(root)
hp = pin(root / binding["helper_path"])
r.require(hp["bytes"] == binding["helper_bytes"] and hp["sha256"] == binding["helper_sha256"],
"UID helper unchanged")
for value in fixed + cache_receipts: for value in fixed + cache_receipts:
r.require(pin(value["path"]) == value, "fixed input changed: " + value["path"]) r.require(pin(value["path"]) == value, "fixed input changed: " + value["path"])
fixed_guard() fixed_guard()
@@ -361,6 +451,7 @@ def main():
engine_identity_before=engine_descriptor, engine_identity_initial=copy.deepcopy(engine_identity), engine_identity_before=engine_descriptor, engine_identity_initial=copy.deepcopy(engine_identity),
runner_sha256=r.sha(root / "tools/run_all_tests.py"), runner_sha256=r.sha(root / "tools/run_all_tests.py"),
default_player_before=protected, fixed_input_pins=fixed, default_player_before=protected, fixed_input_pins=fixed,
uid_helper=binding, uid_plan=plan["uid_plan"], uid_source_count=len(uid_source),
functional_watchdog_seconds=1200, source_adoption=False)) functional_watchdog_seconds=1200, source_adoption=False))
diagnostics = module("s5_diagnostics", r.SUPPORT / "diagnostic_gate.py") diagnostics = module("s5_diagnostics", r.SUPPORT / "diagnostic_gate.py")
owners = module("s5_owners", r.SUPPORT / "ordinary_proof_gate.py") owners = module("s5_owners", r.SUPPORT / "ordinary_proof_gate.py")
@@ -377,7 +468,7 @@ def main():
repin("before-" + phase) repin("before-" + phase)
r.write(out / ("engine-identity-before-" + phase + ".json"), r.write(out / ("engine-identity-before-" + phase + ".json"),
dict(engine_observations[-1], observation_index=len(engine_observations)-1)) dict(engine_observations[-1], observation_index=len(engine_observations)-1))
row = r.execute_phase(str(engine), stage, out, phase, test, selected, expected, row = phase_call(str(engine), stage, out, phase, test, selected, expected,
previous, policy, contracts, paths, public, protected, root, previous, policy, contracts, paths, public, protected, root,
outer, markers, diagnostics, owners, audio) outer, markers, diagnostics, owners, audio)
phases.append(row) phases.append(row)
@@ -424,6 +515,9 @@ def main():
# Fixed guard always follows ownership cleanup, even if setup or an engine failed. # Fixed guard always follows ownership cleanup, even if setup or an engine failed.
try: try:
fixed_guard() fixed_guard()
if uid_state["accepted"] is not None:
r.require(uid_snapshot(stage, uid_source, plan["uid_plan"]) == uid_state["accepted"],
"UID seal after cleanup")
after = r.source_refs(root) after = r.source_refs(root)
r.write(out / "source_after.json", after) r.write(out / "source_after.json", after)
r.require(after == source_before, "whole product source unchanged") r.require(after == source_before, "whole product source unchanged")
@@ -441,7 +535,10 @@ def main():
pids = [p.pid for p in outer.OWNED] pids = [p.pid for p in outer.OWNED]
passed = (error is None and not guards and not cleanup_errors and len(phases) == 4 passed = (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["passed"] for p in phases) and len(pids) == len(set(pids)) == 4
and all(p["engine_ended"] for p in cleanup)) and all(p["engine_ended"] for p in cleanup)
and uid_state["accepted"] is not None
and set(uid_state["accepted"]) == set(plan["uid_plan"])
and all((out / (phase + "-uids.json")).is_file() for phase in plan["phases"]))
execution = dict(passed=passed, error=error, guard_errors=guards, phases=phases, execution = dict(passed=passed, error=error, guard_errors=guards, phases=phases,
actual_captured_PIDs=pids, cleanup=cleanup, cleanup_errors=cleanup_errors, actual_captured_PIDs=pids, cleanup=cleanup, cleanup_errors=cleanup_errors,
formal_before=formal_before, formal_after=formal_after, formal_before=formal_before, formal_after=formal_after,
@@ -0,0 +1,119 @@
#!/usr/bin/env python3
"""Pure Root-only UID controls; no engine or environment access."""
import argparse
import copy
import importlib.util
import json
import os
from pathlib import Path
import sys
sys.dont_write_bytecode = True
def module(name, path):
spec = importlib.util.spec_from_file_location(name, path)
value = importlib.util.module_from_spec(spec)
spec.loader.exec_module(value)
return value
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--project-root', required=True, type=Path)
parser.add_argument('--scratch', required=True, type=Path)
args = parser.parse_args()
root = args.project_root.resolve(strict=True)
r = module('s5_uid_q_runner', root / 'tools/run_all_tests.py')
w = module('s5_uid_wrapper', Path(__file__).with_name('run_s5_native.py'))
# Actual Q pins precede all synthetic data. No synthetic refs enter the loader.
uid_plan, uid_snapshot, binding = w.load_uid_helper(root, r, r.source_refs(root))
scratch = args.scratch
r.require(scratch.is_absolute() and not scratch.exists() and not scratch.is_symlink(),
'absolute fresh scratch')
parent = scratch.parent.resolve(strict=True)
r.require(parent.is_dir() and parent.is_relative_to(w.BUILD.resolve())
and not (parent / scratch.name).is_relative_to(root), 'scratch parent inside BUILD outside Q')
scratch = parent / scratch.name
scratch.mkdir()
results = []
def fixture(label):
stage = scratch / label
stage.mkdir()
files = {'project.godot': b'config_version=5\n',
'scripts/special/peeping_room_service.gd': b'extends Node\n',
'tests/special/test_a.gd': b'extends SceneTree\n',
'scripts/other.gd': b'extends RefCounted\n',
'scripts/other.gd.uid': b'uid://existing\n'}
for name, data in files.items():
path = stage / name
path.parent.mkdir(parents=True, exist_ok=True)
path.write_bytes(data)
source = r.inventory(stage, stage=True)
refs = {n: dict(p, path=str(stage / n)) for n, p in source.items()}
plan = uid_plan(refs)
r.require(bool(plan) and all(p['owner_sha256'] == refs[p['owner']]['sha256']
for p in plan.values()), 'derived synthetic plan')
for i, name in enumerate(plan):
(stage / name).write_bytes(('uid://generated' + str(i) + '\n').encode())
return stage, source, plan
stage, source, plan = fixture('positive')
snap = uid_snapshot(stage, source, plan)
r.require(set(snap) == set(plan), 'exact positive planned UID set')
results.append('positive')
def negative(label, mutate):
stage, source, plan = fixture(label)
names = list(plan)
mutate(stage, source, plan, names)
try:
uid_snapshot(stage, source, plan)
except AssertionError:
results.append(label)
else:
raise AssertionError('control did not reject: ' + label)
negative('extra', lambda s, a, p, n: (s / 'extra.uid').write_bytes(b'uid://extra\n'))
negative('original', lambda s, a, p, n: (s / 'project.godot').write_bytes(b'changed\n'))
negative('owner', lambda s, a, p, n: (s / p[n[0]]['owner']).write_bytes(b'changed\n'))
negative('existing-collision', lambda s, a, p, n: (s / n[0]).write_bytes(b'uid://existing\n'))
negative('generated-collision', lambda s, a, p, n: (s / n[0]).write_bytes((s / n[1]).read_bytes()))
for label, raw in [('no-newline', b'uid://abc'), ('crlf', b'uid://abc\r\n'),
('uppercase', b'uid://ABC\n'), ('too-long', b'uid://abcdefghijklmn\n')]:
negative(label, lambda s, a, p, n, raw=raw: (s / n[0]).write_bytes(raw))
def hardlink(stage, source, plan, names):
os.link(stage / names[0], scratch / 'hardlink-peer')
def symlink(stage, source, plan, names):
path = stage / names[0]
path.unlink()
path.symlink_to(stage / names[1])
negative('hardlink', hardlink)
negative('symlink', symlink)
negative('missing', lambda s, a, p, n: (s / n[0]).unlink())
stage, source, plan = fixture('post-seal')
out = scratch / 'policy-receipts'
out.mkdir()
reports, phase_call, state = w.make_uid_policy(r, uid_snapshot, source, plan, out)
expected = copy.deepcopy(source)
state['phase'] = 'import'
reports(stage, expected, {}, [])
r.require(state['accepted'] == uid_snapshot(stage, source, plan), 'import sealed')
state['phase'] = 'parse'
(stage / next(iter(plan))).write_bytes(b'uid://mutated\n')
try:
reports(stage, expected, {}, [])
except AssertionError:
results.append('post-seal-reports')
else:
raise AssertionError('post-seal mutation accepted')
print(json.dumps({'accepted': False, 'Root-only': True, 'controls': results,
'uid_helper': binding, 'scratch': str(scratch)}))
if __name__ == '__main__':
main()