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

This commit is contained in:
Agent Control Runner
2026-10-16 09:33:00 +09:00
parent 55f1fb49aa
commit fb8b7919db
7 changed files with 203 additions and 17 deletions
@@ -17,7 +17,7 @@ MANIFEST_SHA256 = 'a15f29fa12537f6d8aaf7cabea390922a9f16e3eb9c10981e5742aafc8c4c
MANIFEST_BYTES = 1244135
PRODUCT = '5f6bc11d6bb6e92d22d787989b219fef3a435bc1'
RUNS = {'s1': 'p04-s1-native-r02', 's2a': 'p04-s2a-native-r03',
's2b': 'p04-s2b-native-r02', 's3': 'p04-s3-native-r01', 's4': 'p04-s4-native-r27'}
's2b': 'p04-s2b-native-r02', 's3': 'p04-s3-native-r01', 's4': 'p04-s4-native-r28'}
# Native descriptors pinned from literal files, never ROOT result passed fields.
NATIVE_PINS = {
's1': ('1e26d9585396da9415747d87d77b70f23425a3ee0714e4fca114748f9479fd4e', '01372beb0ffec181c892d3b4e88bce32001e08fb2007938d7bf19135511a7acc', '0b6d11eb34d8af64b22cb806caeb06eed4ec521fa9ee24d1204ea185345e655c'),
@@ -0,0 +1,38 @@
{
"status": "NOTRUN",
"task_id": "P04-01",
"starting_submission": "55f1fb49aaefa5c1b86de1c3eda72392ef6b58f2",
"source": "audit-support/p04-s4-source-r28",
"plan": "p04-s4-plan-r28.json",
"native": "p04-s4-native-r28",
"regression_status": "NOTRUN",
"native_status": "NOTRUN",
"unit_complete": false,
"D05": "pending",
"files": {
"s4/p04_s4_power_probe.gd": {
"bytes": 26912,
"sha256": "56f8e2786e3aff82097baa06afb4cd13e6e7c06c3d1afa43b9ee35c78a25a999"
},
"s4/run_s4_native.py": {
"bytes": 23233,
"sha256": "2d3be39d2b310abac058e27336ac816c234043a0a1dd7b2c52d84994907dd31b"
},
"s4/S4_ROOT_RUN.md": {
"bytes": 21862,
"sha256": "ff463e1e6ce8847f658eddc91f1cec3eab3bb8bcadd9a75272138e06083116a2"
},
"s4/phase_cut_regression.py": {
"bytes": 3919,
"sha256": "1362078fdd819d057f1f1bab369b9629a11e089a3453da8af4ce21cec251dbad"
},
"s4/receipt_lifecycle_fixtures.py": {
"bytes": 12340,
"sha256": "629571495787fdcda82a6a74d98649d4ea424d6fc9c27c5cafa55d4b2881c71f"
},
"p04_native_series.py": {
"bytes": 75900,
"sha256": "c1cc5d49dbf4c8422a2208297c665fde8abd569e2c9f8239603d8218ae1ed8fb"
}
}
}
@@ -1,4 +1,4 @@
# S4 finite Root collection — NOT RUN
# S4 finite Root collection r28 — NOT RUN
This adds only the existing `power_stop` evidence obligation. It adds no counted
condition, product change, acceptance or priority approval. Run once after this
@@ -16,15 +16,15 @@ export E=docs/plans/original-completion-2026-10-02/execution/p04-01
export PYTHONDONTWRITEBYTECODE=1
python3 "$E/s4/engine_identity_negative_fixtures.py"
python3 "$E/s4/receipt_lifecycle_fixtures.py"
mkdir "$B/audit-support/p04-s4-source-r27"
cp "$E/s4/run_s4_native.py" "$E/s4/p04_s4_power_probe.gd" "$E/s4/S4_ROOT_RUN.md" "$B/audit-support/p04-s4-source-r27/"
python3 "$B/audit-support/p04-s4-source-r27/run_s4_native.py" \
mkdir "$B/audit-support/p04-s4-source-r28"
cp "$E/s4/run_s4_native.py" "$E/s4/p04_s4_power_probe.gd" "$E/s4/S4_ROOT_RUN.md" "$B/audit-support/p04-s4-source-r28/"
python3 "$B/audit-support/p04-s4-source-r28/run_s4_native.py" \
--project-root "$B/audit-support/p04-r17-full-inputs-r01/product" \
--output "$B/p04-s4-native-r27" --plan "$B/p04-s4-plan-r27.json" \
--output "$B/p04-s4-native-r28" --plan "$B/p04-s4-plan-r28.json" \
--godot /Applications/Godot.app/Contents/MacOS/Godot --check-only
python3 "$B/audit-support/p04-s4-source-r27/run_s4_native.py" \
python3 "$B/audit-support/p04-s4-source-r28/run_s4_native.py" \
--project-root "$B/audit-support/p04-r17-full-inputs-r01/product" \
--output "$B/p04-s4-native-r27" --plan "$B/p04-s4-plan-r27.json" \
--output "$B/p04-s4-native-r28" --plan "$B/p04-s4-plan-r28.json" \
--godot /Applications/Godot.app/Contents/MacOS/Godot
```
@@ -69,8 +69,8 @@ Exact input footprints:
proof and remains ineligible. Its diagnostics are at
`audit-support/p04-root-d393-s4-r01/ENGINE_STAGING_DIAGNOSTICS.json`.
Exact output footprints are `B/p04-s4-plan-r27.json` and the fresh
`B/p04-s4-native-r27/**`: private selected source stage, complete phase receipts
Exact output footprints are `B/p04-s4-plan-r28.json` and the fresh
`B/p04-s4-native-r28/**`: private selected source stage, complete phase receipts
and logs, raw JSON/Variant points and all phase observations, full source maps,
PID and cleanup receipts. `formal/{writer,reader}/S4-{boundary,held,recovered}/`
mirrors all four formal members (`journal.log`, `manifest.json`, `thumbnail.png`,
@@ -112,8 +112,8 @@ restore and is not part of Runtime snapshot equality. The derived
`related_facility_operating` flag is measured separately and checked after restore.
This source-only dispatch authorizes no worker execution. Root stages the three
files, creates the r27 plan with --check-only, then collects once to the fresh
r27 output. Do not read or write r24 outputs, cleanup, stages or plans.
files, creates the r28 plan with --check-only, then collects once to the fresh
r28 output. Do not read or write r24 outputs, cleanup, stages or plans.
Do not rerun S1-S3, C or full178. No engine copy, signing, xattr,
codesign call or security-setting change is part of this procedure.
Native evidence, registered validation, independent review, support53cb rebind
@@ -258,3 +258,48 @@ Root re-runs only the fresh S4 collection and any needed fixture validation,
using the r27 commands above. Exact-version evidence, registered validation,
independent review, D05 and original acceptance remain pending; this is
submitted preparation, not completion.
## REPAIR28 phase cut (source-only; NOTRUN)
Root's supplied r27 own-B diagnosis is preserved as history: import, parse and
Writer passed (934 checks, zero failures); Reader ran 1445 checks with exactly
one failure, complete phase count. ACTUAL_TYPED_PHASE_DIAGNOSIS.json reports
all 121 actual Reader phase .var files byte-identical to matching Writer files.
This worker did not open or rerun those raw materials. Keep all r27 failed raw,
formals, logs, source stages, plans and diagnosis unchanged.
The kernel applies commands at the old minute, advances absolute_minute, then
emits TIME_BOUNDARIES and the remaining phases. The new helper includes minute
960 APPLY_COMMANDS using the enum key expression used by the Writer. It also
includes all later rows. Before byte comparison the probe asserts the exact
121-entry kernel roster, uniqueness, and Writer order. Both existing complete
phase count and complete typed var_to_bytes equality checks remain unchanged.
Writer row data, typed staff fix, runtime SERVERS, Clock and raw format stay
unchanged.
The current RUNS s4 binding, wrapper defaults and disposable lifecycle fixture
path names use r28. Only these path strings change in the wrapper and lifecycle
fixture; their engine/lifecycle behavior is unchanged. Stage the three current
files using the commands at the top to create fresh source-r28, plan-r28 and
native-r28 paths. Do not reuse r27 as passing evidence.
Regression control status: NOTRUN. Root supplies full paths to ALL 132 actual
r27 Writer phase .var files and ALL 121 actual Reader phase .var files:
python3 "$E/s4/phase_cut_regression.py" --writer <full Writer phase paths...> --reader <full Reader phase paths...>
Use actual own-B raw paths supplied by Root, not fabricated fixtures or old
external provenance paths. Paths may be in any argument order; the control
reconstructs kernel order from typed minute/phase, checks the complete Writer
and Reader rosters, then compares unchanged full bytes. It requires old cut
120/rejected, new cut 121/equal, deleted boundary APPLY_COMMANDS/rejected and
duplicate/rejected. Mutations are in-memory lists only. Its result is a raw
regression control, never an engine/native/acceptance PASS. Missing raw paths
remain a Root execution input, not a worker-generated substitute.
Worker made source edits and calculated bindings only; no tests, fixtures,
Git, engine, Runner, agents or commits. The normal validation on submitted
55f1fb49aaefa5c1b86de1c3eda72392ef6b58f2 ran once and exited 2 because the current
MANIFEST is missing (Root-supplied history). The gate, checker a61, 1338 inputs,
C/S1-3/full178 artifacts, five carried formal review findings, and frozen
original 13/88 main 9b remain unchanged. D05, independent review, exact-version
native proof and original unit acceptance remain pending. This repair does
not complete the unit.
@@ -366,6 +366,25 @@ func _load_point(path: String, expected: Dictionary) -> bool:
_expect(var_to_bytes(_runtime.create_snapshot()) == var_to_bytes(expected[&"snapshot"]), "all restored typed fields equal Writer")
return restored
func _is_replayed_phase(row: Dictionary) -> bool:
return int(row[&"minute"]) > _boundary or (int(row[&"minute"]) == _boundary and row[&"phase"] == SimulationKernel.TickPhase.keys()[SimulationKernel.TickPhase.APPLY_COMMANDS])
func _assert_expected_phase_roster(references: Array) -> void:
var expected_pairs: Array = []
for minute: int in range(_boundary, _boundary + 11):
for phase: int in range(SimulationKernel.TickPhase.size()):
expected_pairs.append([minute if phase == SimulationKernel.TickPhase.APPLY_COMMANDS else minute + 1, SimulationKernel.TickPhase.keys()[phase]])
var actual_pairs: Array = []
var seen: Dictionary = {}
for reference: Dictionary in references:
var row: Dictionary = _read(reference)
var pair: Array = [int(row[&"minute"]), row[&"phase"]]
_expect(not seen.has(pair), "expected phase roster has no duplicate minute/phase")
seen[pair] = true
actual_pairs.append(pair)
_expect(references.size() == 121 and expected_pairs.size() == 121, "expected phase roster exactly 11 phases x 11 replayed minutes")
_expect(actual_pairs == expected_pairs, "expected phase roster in Writer/kernel order with no missing minute/phase")
func _reader() -> void:
var file: FileAccess = FileAccess.open(_evidence_dir.path_join("writer.json"), FileAccess.READ)
_expect(file != null, "Writer receipt")
@@ -416,7 +435,8 @@ func _reader() -> void:
replay_refs[label] = _write(label + "-replay", actual)
var expected_phases: Array = []
for reference: Dictionary in writer_case[&"phases"]:
if int(_read(reference)[&"minute"]) > _boundary: expected_phases.append(reference)
if _is_replayed_phase(_read(reference)): expected_phases.append(reference)
_assert_expected_phase_roster(expected_phases)
_expect(_phases.size() == expected_phases.size(), "complete phase count")
if _phases.size() == expected_phases.size():
for index: int in range(_phases.size()):
@@ -0,0 +1,83 @@
"""Read actual r27 phase .var paths only; no engine, fixtures or acceptance claim.
Root supplies every Writer and Reader phase file via --writer and --reader.
Argument order is immaterial: observation order is reconstructed from kernel
phase/minute keys, never from lexicographic filenames. Typed bytes stay intact.
"""
import argparse
import hashlib
import json
from pathlib import Path
import sys
sys.dont_write_bytecode = True
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from p04_native_series import require, variant
PHASES = ('APPLY_COMMANDS', 'TIME_BOUNDARIES', 'MANA', 'CONSTRUCTION',
'LOGISTICS', 'FACILITY_COMPLETION', 'VITALS_AND_ENVIRONMENT',
'INCIDENTS_AND_EVENTS', 'FACILITY_QUEUES', 'AI_DECISIONS', 'PUBLISH_SNAPSHOT')
BOUNDARY = 960
ROSTER = [(minute if phase == PHASES[0] else minute + 1, phase)
for minute in range(BOUNDARY, BOUNDARY + 11) for phase in PHASES]
def load(paths, role):
rows, pins = [], []
for path in paths:
require(path.is_absolute() and path.is_file() and not path.is_symlink(), 'full regular raw path required')
require(path.name.startswith(role + '-S4-phase-') and path.suffix == '.var', 'actual role phase .var required')
raw = path.read_bytes()
node = variant(raw)
minute, phase = node.at('minute'), node.at('phase')
require(minute.kind == 2 and phase.kind == 4 and phase.value in PHASES, 'typed minute/phase')
rows.append(((minute.value, phase.value), raw))
pins.append(dict(path=str(path), bytes=len(raw), sha256=hashlib.sha256(raw).hexdigest()))
rows.sort(key=lambda row: (row[0][0] + (row[0][1] == PHASES[0]), PHASES.index(row[0][1])))
return rows, pins
def validate(expected, reader):
require(len(expected) == len(reader) == 121, 'complete phase count')
require([key for key, _ in expected] == ROSTER, 'Writer roster missing/duplicate/order')
require([key for key, _ in reader] == ROSTER, 'Reader roster missing/duplicate/order')
require(all(a == b for a, b in zip(expected, reader)), 'same phase order and all typed phase bytes')
def rejected(expected, reader):
try:
validate(expected, reader)
except ValueError:
return True
raise ValueError('negative control unexpectedly accepted')
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--writer', nargs='+', type=Path, required=True)
parser.add_argument('--reader', nargs='+', type=Path, required=True)
args = parser.parse_args()
writer, wpins = load(args.writer, 'writer')
reader, rpins = load(args.reader, 'reader')
require(len(writer) == 132 and len({key for key, _ in writer}) == 132, 'complete unique actual Writer input')
require([key for key, _ in writer] ==
[(minute if phase == PHASES[0] else minute + 1, phase)
for minute in range(BOUNDARY - 1, BOUNDARY + 11) for phase in PHASES],
'full Writer kernel roster')
old = [row for row in writer if row[0][0] > BOUNDARY]
new = [row for row in writer if row[0][0] > BOUNDARY or
(row[0][0] == BOUNDARY and row[0][1] == PHASES[0])]
require(len(old) == 120, 'old cut must produce 120')
old_rejected = rejected(old, reader)
validate(new, reader)
require(new[0][0] == (BOUNDARY, PHASES[0]), 'boundary APPLY_COMMANDS first')
deleted_rejected = rejected(new[1:], reader)
duplicated_rejected = rejected([new[0], *new], reader)
print(json.dumps(dict(status='CONTROL_CONFIRMED', engine_run=False, acceptance=False,
old_count=len(old), old_rejected=old_rejected, new_count=len(new),
all_typed_bytes_in_order=True, deleted_apply_rejected=deleted_rejected,
duplicate_rejected=duplicated_rejected, writer=wpins, reader=rpins), indent=2))
if __name__ == '__main__':
main()
@@ -107,8 +107,8 @@ def case(base, failure=None):
descriptor = dict(path=str(engine), resolved_path=str(engine), bytes=st.st_size,
sha256=r.sha(engine), mtime_ns=st.st_mtime_ns, mode=st.st_mode,
device=st.st_dev, inode=st.st_ino, ctime_ns=st.st_ctime_ns)
out = base / 'p04-s4-native-r27'
plan = base / 'p04-s4-plan-r27.json'
out = base / 'p04-s4-native-r28'
plan = base / 'p04-s4-plan-r28.json'
attempts, created, phases = Counter(), {}, []
cleanup_calls = []
real_write, real_inventory = r.write, r.inventory
@@ -99,8 +99,8 @@ def engine_pin(path, expected=None):
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--project-root", type=Path, default=PRODUCT)
parser.add_argument("--output", type=Path, default=BUILD / "p04-s4-native-r27")
parser.add_argument("--plan", type=Path, default=BUILD / "p04-s4-plan-r27.json")
parser.add_argument("--output", type=Path, default=BUILD / "p04-s4-native-r28")
parser.add_argument("--plan", type=Path, default=BUILD / "p04-s4-plan-r28.json")
parser.add_argument("--cache-run", type=Path, default=None,
help="optional passed registered cache; default is fresh, without cache access")
parser.add_argument("--godot", type=Path, default=ENGINE)