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

This commit is contained in:
Agent Control Runner
2026-10-18 20:16:38 +09:00
parent 2cd734062a
commit 13aefdd3dd
22 changed files with 1392 additions and 35 deletions
@@ -1,3 +1,54 @@
## REPAIR49 normal-gate handoff
Required materials: exact B/native-first-current and fresh-run registry; each
runner-input/ended/source/UID/formal/raw/lifecycle receipt; original recorded Q
and engine context; B/p04-evidence/runner-materials and RELOCATION.json; matching
collection/MANIFEST and separate dependency invocation; original full run and
full_suite binding/raw receipts; final index and invocation receipt; immutable
authorities in frozen checkout. No raw or historical receipt is rewritten.
Two-placement identity requires the explicit closure in repair48_identity_controls.py,
missing-file rejection, and original/A/B complete path/bytes/SHA tables and tree
hash equality before and after positive execution. See REPAIR49_STATUS.md.
Submission is followed by new Q freeze, affected pure controls (complete_B included),
clean exact-Q check-only, capacity/PID checks, one fresh native lease for
S1/S2a/S2b/S3/S4 and all ten S5 cases, readers/adapters, 15EV collector, full
verification/binding under the conditions below (or one final full184 if any
condition fails), index generation, p04-acceptance once, separate Opus whole-unit
review, normal prepare/C/integration/final/Root DB join/ledger/main push.
If order-typed fails, preserve its result and stop before heavy execution.
Only whole-unit acceptance grants credit.
## REPAIR49 full184 conditional reuse candidate — all conditions UNVERIFIED
Native reuse is forbidden: all six series require fresh M/S/Q_tree provenance
(p04_native_series.py:1287; checker:370). Full uses the existing separate binding
(checker:1175-1186); no adopter or checker change is authorized.
The following are requirements, not results or approval:
1. New S5 source_before must equal old full selected_source_map: all 1369 keys
and SHA values, not counts alone.
2. Old project_root must remain unchanged: source-start == current source_refs
== post-verification source_refs (full_suite_verifier.py:115).
3. selected_source_map, roster184, parse329, settings, runner/marker module,
marker contract, suite-policy and UID plan/stage must all match (116-152,225).
4. inputs.engine must match current engine_pin (124-125).
5. Revalidate every phase PID, cleanup, marker and diagnostics (154-228).
6. Current s5/run_s5_native.py and full_suite_verifier.py SHA must equal the
Root rehearsal versions.
7. Never relabel old S/oldQ/project_root/PIDs/time. Describe reuse only as
revalidating the exact-source-identical old full through the existing
full_suite route; never claim full ran on new S.
8. A separate Opus whole-unit review must independently confirm applicability.
Conditions 1–6 require actual checks after final freeze. If any predicate is
unproved or differs, reject reuse and execute full184 once on the final version.
SourceRefs (tools/run_all_tests.py:40-45) excludes docs/private package, but that
fact is no substitute for complete source equality. No reuse is approved here.
REPAIR48 current source status: see [REPAIR48_STATUS.md](../REPAIR48_STATUS.md). Earlier run directions and successes below are historical; they grant no P04 credit.
# REPAIR45 handoff
## REPAIR45 — implementation ready for submission
@@ -5,11 +5,41 @@ import importlib.util
import json
from pathlib import Path
PACKAGE_ROOT = Path(__file__).absolute().parents[1]
DEPENDENCIES = {}
DEPENDENCY_OBSERVATIONS = {}
_EXECUTED_DEPENDENCIES = {}
_EXECUTED_OBSERVATIONS = {}
def module(name, path):
path = Path(path).absolute()
if '..' in path.parts or any(p.is_symlink() for p in (path, *path.parents)):
raise ValueError('dependency traversal/symlink')
if not path.resolve(strict=True).is_relative_to(PACKAGE_ROOT.resolve(strict=True)):
raise ValueError('dependency outside package')
relative = path.relative_to(PACKAGE_ROOT).as_posix()
data = path.read_bytes()
spec = importlib.util.spec_from_file_location(name, path)
value = importlib.util.module_from_spec(spec)
spec.loader.exec_module(value)
exec(compile(data, str(path), 'exec'), value.__dict__)
DEPENDENCIES[relative] = hashlib.sha256(data).hexdigest()
DEPENDENCY_OBSERVATIONS[relative] = str(path)
for key, digest in getattr(value, 'DEPENDENCIES', {}).items():
dependency = Path(key)
if dependency.is_absolute() or '..' in dependency.parts:
raise ValueError('dependency key must be package relative')
observed = Path(value.DEPENDENCY_OBSERVATIONS[key])
if (observed != PACKAGE_ROOT / dependency
or any(p.is_symlink() for p in (observed, *observed.parents))
or not observed.resolve(strict=True).is_relative_to(PACKAGE_ROOT.resolve(strict=True))):
raise ValueError('dependency mapping outside package/symlink')
if key in DEPENDENCIES and DEPENDENCIES[key] != digest:
raise ValueError('dependency mapping conflict')
DEPENDENCIES[key] = digest
DEPENDENCY_OBSERVATIONS[key] = value.DEPENDENCY_OBSERVATIONS[key]
_EXECUTED_DEPENDENCIES.update(DEPENDENCIES)
_EXECUTED_OBSERVATIONS.update(DEPENDENCY_OBSERVATIONS)
return value
@@ -17,11 +47,11 @@ POWER_PATH = Path(__file__).with_name('s5_power_adapter.py')
power = module('s5_order_power', POWER_PATH)
Raw, staff_check, duplicate_check = power.Raw, power.staff_check, power.duplicate_check
series, require = power.series, power.require
DEPENDENCIES = {str(p): hashlib.sha256(p.read_bytes()).hexdigest()
for p in (POWER_PATH, power.SERIES_PATH)}
GUARD_PATH = Path(__file__).with_name('s5_guard_oracle.py')
guard_oracle = module('s5_guard_oracle', GUARD_PATH)
DEPENDENCIES[str(GUARD_PATH)] = hashlib.sha256(GUARD_PATH.read_bytes()).hexdigest()
if (set(DEPENDENCIES) != {'s5/s5_power_adapter.py', 'p04_native_series.py', 's5/s5_guard_oracle.py'}
or power.DEPENDENCIES != {'p04_native_series.py': power.SERIES_SHA256}):
raise ValueError('loaded dependency roster mismatch')
GUEST, REQUEST = power.GUEST, power.REQUEST
SECOND, SECOND_REQUEST = 'p04.s5.guest.b', 'p04.s5.request.b'
@@ -415,7 +445,10 @@ DERIVERS = {'S5C_DESTRUCTION_COMMAND': destruction_command, 'S5D_DESTRUCTION_RAI
def derive(root, writer_sha, reader_sha):
root = Path(root)
require(DEPENDENCIES == _EXECUTED_DEPENDENCIES
and DEPENDENCY_OBSERVATIONS == _EXECUTED_OBSERVATIONS,
'dependency identity differs from executed module roster')
root = Path(root).resolve(strict=True)
raw = Raw(root)
writer = json.loads(raw.pin(root / 'writer.json', writer_sha), object_pairs_hook=power.unique)
reader = json.loads(raw.pin(root / 'reader.json', reader_sha), object_pairs_hook=power.unique)
@@ -11,11 +11,20 @@ import struct
import json
from pathlib import Path
SERIES_PATH = Path(__file__).resolve().parents[1] / 'p04_native_series.py'
SERIES_SHA256 = hashlib.sha256(SERIES_PATH.read_bytes()).hexdigest()
PACKAGE_ROOT = Path(__file__).absolute().parents[1]
SERIES_PATH = PACKAGE_ROOT / 'p04_native_series.py'
for _path in (SERIES_PATH, *SERIES_PATH.parents):
if _path.is_symlink():
raise ValueError('dependency symlink')
if not SERIES_PATH.resolve(strict=True).is_relative_to(PACKAGE_ROOT.resolve(strict=True)):
raise ValueError('dependency outside package')
_series_bytes = SERIES_PATH.read_bytes()
SERIES_SHA256 = hashlib.sha256(_series_bytes).hexdigest()
_spec = importlib.util.spec_from_file_location('s5_power_series', SERIES_PATH)
series = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(series)
exec(compile(_series_bytes, str(SERIES_PATH), 'exec'), series.__dict__)
DEPENDENCIES = {'p04_native_series.py': SERIES_SHA256}
DEPENDENCY_OBSERVATIONS = {'p04_native_series.py': str(SERIES_PATH)}
CASES = ("S5A_PURE", "S5B_DEPENDENCY")
GUEST = "p04.s5.guest.a"
@@ -96,6 +105,7 @@ def duplicate_check(replay_node, recorded):
def derive(root, writer_sha, reader_sha):
root = Path(root).resolve(strict=True)
raw = Raw(root)
writer = json.loads(raw.pin(root / "writer.json", writer_sha), object_pairs_hook=unique)
reader = json.loads(raw.pin(root / "reader.json", reader_sha), object_pairs_hook=unique)