P04-01: 同時発生の更新規約
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
# S4 finite Root collection — 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
|
||||
source batch is auto-submitted. Do not rerun C/S1/S2a/S2b/S3. Do not run the full
|
||||
product suite now. Preserve all existing raw and REPAIR17–21 history.
|
||||
|
||||
From the clean auto-submitted checkout, stage these three exact reviewed files
|
||||
in the fresh own-B source directory. Copy the installed engine executable there as an independently pinned native input. This staging is a Root action, not a worker
|
||||
execution. The wrapper refuses QA outside own B. All input/QA/source footprints
|
||||
below are within the registered B; external manifest paths are lookup keys and
|
||||
provenance only. Never open their original production locations.
|
||||
|
||||
```sh
|
||||
export B=/Users/korizatou114/Projects/TheTree-managed-worktrees/p04-01/.runtime/P04-01/build
|
||||
export E=docs/plans/original-completion-2026-10-02/execution/p04-01
|
||||
export PYTHONDONTWRITEBYTECODE=1
|
||||
mkdir "$B/audit-support/p04-s4-source-r22"
|
||||
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-r22/"
|
||||
cp /Applications/Godot.app/Contents/MacOS/Godot "$B/audit-support/p04-s4-source-r22/Godot"
|
||||
python3 "$B/audit-support/p04-s4-source-r22/run_s4_native.py" \
|
||||
--project-root "$B/audit-support/p04-r17-full-inputs-r01/product" \
|
||||
--output "$B/p04-s4-native-r22" --plan "$B/p04-s4-plan-r22.json" \
|
||||
--cache-run "$B/p04-final-product-full-r01" \
|
||||
--godot "$B/audit-support/p04-s4-source-r22/Godot" --check-only
|
||||
python3 "$B/audit-support/p04-s4-source-r22/run_s4_native.py" \
|
||||
--project-root "$B/audit-support/p04-r17-full-inputs-r01/product" \
|
||||
--output "$B/p04-s4-native-r22" --plan "$B/p04-s4-plan-r22.json" \
|
||||
--cache-run "$B/p04-final-product-full-r01" \
|
||||
--godot "$B/audit-support/p04-s4-source-r22/Godot"
|
||||
```
|
||||
|
||||
The first invocation only prepares the pinned plan: zero engine launches. The
|
||||
second is one collection, exactly four sequential owned processes: import,
|
||||
parse, Writer, Reader. Each retains the framework's native diagnostics,
|
||||
ownership, exit/end checks, full stream SHA, default-player protection, private
|
||||
profiles, source-before/after guards and cleanup. Failure stops the collection;
|
||||
do not overwrite or silently repeat it. The ordinary framework creates its
|
||||
normal private user profiles; these are process outputs, not external source
|
||||
inputs. Reader uses only the existing IO1 formal package mapping.
|
||||
|
||||
Exact input footprints:
|
||||
|
||||
- `B/audit-support/p04-r17-full-inputs-r01/MANIFEST.json`, SHA256
|
||||
`a15f29fa12537f6d8aaf7cabea390922a9f16e3eb9c10981e5742aafc8c4c8a8`.
|
||||
- All 1338 files below that relocation's `product/`, each matched to the
|
||||
manifest by bytes/SHA. No source is omitted and no old path is followed.
|
||||
- Its `fixed/6ce6b28c5985e8a4f13b78bfeb1f1e09f6216d874fb01e0656ec1633bfa01cd7/completion_marker_contracts.json`.
|
||||
- `B/audit-support/p04-review-repair22-r01/ACTUAL_CURRENT_PUBLIC_POWER_FUNCTIONS.json`.
|
||||
- The three staged S4 files above, pinned by the plan, and the staged native
|
||||
executable at B/audit-support/p04-s4-source-r22/Godot, pinned before native
|
||||
admission and checked unchanged after collection. The only stage override
|
||||
is `tests/s3/test_runtime_staff_assignment.gd` with the S4 probe. Harness and
|
||||
kitchen fixture are the unchanged product files; inherited sources are
|
||||
included in the full1338 map. The parse roster is all316 `.gd` inputs.
|
||||
- `B/p04-final-product-full-r01/{runner-input.json,runner-ended.json,stage/.godot/**}`:
|
||||
immutable ended cache. Its selected1339 map equals the complete product1338
|
||||
plus the checker. Cache cloning uses separate inodes; normal import and parse
|
||||
still run. The checker is not a `.gd` parse input or a product-suite dependency.
|
||||
|
||||
Exact output footprints are `B/p04-s4-plan-r22.json` and the fresh
|
||||
`B/p04-s4-native-r22/**`: 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`,
|
||||
`world.bin`) with a provenance-only `formal-relocation.json`. R reads these
|
||||
own-B mirrors, never profile paths from old manifests.
|
||||
|
||||
Scenario and source-derived timing:
|
||||
|
||||
1. Use the existing public cafeteria + physical FLEX kitchen fixture and normal
|
||||
DAY server commute. Queue using the definition's original price and duration;
|
||||
advance naturally to duration−1 at959. Derive the cafeteria's sole neighbour
|
||||
from the actual graph and call public `disconnect_nodes` on exactly that edge.
|
||||
2. Advance normally to960. The source's modulo10 evaluation finds an isolated
|
||||
consumer with zero generation/storage. Normal `mana_power_projection.apply`
|
||||
makes only the cafeteria unpowered; preparation reaches `NO_POWER` with its
|
||||
dependency operating. Save **boundary** at960, then **held** at961. Mana stays
|
||||
positive; operator stays open; linked kitchen is Facility `OPEN` and network
|
||||
consumer `ACTIVE`. No closure, damage, shift or exit triggers accompany outage.
|
||||
3. At961 reconnect the same edge. Verify the complete original edge set and
|
||||
graph invariants. Advance each minute, retaining full phase raw. The saved
|
||||
hold deadline is960+10=970; the next permitted normal evaluation is970.
|
||||
Progress, reservation and sale stay held through969. Save **recovered** at970
|
||||
after one completion/payment. Resend connect_nodes on the same edge at970,
|
||||
comparing the complete Runtime before/after;971 is the duplicate guard. Ordinary guest
|
||||
redecision/despawn after completed service is retained in raw, never forced
|
||||
or suppressed; the outage and held service have no exit confound.
|
||||
4. A distinct Reader copies all four members at each point. Normal SaveService
|
||||
load and Runtime restore must reproduce the full typed snapshot, including
|
||||
graph and all unrelated fields. No canonicalization, dropped fields, forced
|
||||
evaluation or hold bypass. Replay from the960 formal boundary through961,
|
||||
reconnect,970 and971; compare complete typed points and phase states. No
|
||||
additional condition is credited for this formal preservation check.
|
||||
|
||||
`REPAIR22_SOURCE_FACTS.json` contains full actual source bodies and graph restore
|
||||
invariants. The source normalizes saved node IDs/reasons, checks valid endpoints,
|
||||
rebuilds symmetric edges, preserves revision/evaluation time and checks storage
|
||||
capacity and consumer allocation. Transient `_last_report` is cleared on normal
|
||||
restore and is not part of Runtime snapshot equality. The derived
|
||||
`related_facility_operating` flag is measured separately and checked after restore.
|
||||
|
||||
After successful S4, Root can perform the eight local suites and fresh read-only
|
||||
R collection described in EVIDENCE_COLLECTION.md. S4 is missing until the actual
|
||||
collection succeeds. Subsequent index/cross-gate work is not a source-preparation
|
||||
blocker. Rebind support53cb through its normal registered task against the new
|
||||
source. Preserve the21615-check proof. Only if exact final1339 evidence is
|
||||
required, perform one full run after all fixes, S4, local checks, eight suites
|
||||
and rebind are bundled. Never splice different-version raw or claim1339 identity.
|
||||
@@ -0,0 +1,431 @@
|
||||
extends "res://tests/s3/test_runtime_actor_hardening.gd"
|
||||
|
||||
const CASES: Array[String] = ["S4"]
|
||||
const SEEDS: Dictionary = {"S4": 420440}
|
||||
const GUEST: StringName = &"p04.s4.guest.a"
|
||||
const REQUEST: StringName = &"p04.s4.request.a"
|
||||
const QUEUED_GUEST: StringName = &"p04.s4.guest.b"
|
||||
const QUEUED_REQUEST: StringName = &"p04.s4.request.b"
|
||||
const SERVERS: Array[StringName] = [&"p04.order.server.a", &"p04.order.server.b"]
|
||||
var _evidence_dir: String = ""
|
||||
var _mode: String = ""
|
||||
var _case: String = ""
|
||||
var _serial: int = 0
|
||||
var _facility_id: StringName = &""
|
||||
var _service_id: StringName = &""
|
||||
var _boundary: int = 960
|
||||
var _price: int = 0
|
||||
var _duration: int = 0
|
||||
var _patience: int = 0
|
||||
var _reserve: int = 0
|
||||
var _recovery: Dictionary = {}
|
||||
var _commands: Array = []
|
||||
var _results: Array = []
|
||||
var _receipts: Array = []
|
||||
var _phases: Array = []
|
||||
var _points: Dictionary = {}
|
||||
var _branches: Dictionary = {}
|
||||
var _slots: Dictionary = {}
|
||||
|
||||
func _run() -> void:
|
||||
_evidence_dir = OS.get_environment("THE_TREE_S4_EVIDENCE")
|
||||
_mode = OS.get_environment("THE_TREE_S4_MODE")
|
||||
if _evidence_dir.is_empty() or _mode not in ["writer", "reader"]:
|
||||
quit(2)
|
||||
return
|
||||
_expect(DirAccess.make_dir_recursive_absolute(_evidence_dir) == OK, "external evidence directory")
|
||||
if _mode == "writer":
|
||||
for branch: String in CASES:
|
||||
_case = branch
|
||||
_writer_case()
|
||||
else:
|
||||
_reader()
|
||||
_write(_mode, {&"pid": OS.get_process_id(), &"profile": OS.get_user_data_dir(), &"slots": _slots,
|
||||
&"branches": _branches, &"checks": _checks, &"failures": _failures,
|
||||
&"whole_goal_accepted": false, &"unit_accepted": false}, true)
|
||||
_cleanup()
|
||||
print("S4 power: %d checks, %d failures" % [_checks, _failures])
|
||||
quit(1 if _failures else 0)
|
||||
|
||||
func _fresh() -> void:
|
||||
_serial = 0
|
||||
_facility_id = &""
|
||||
_service_id = &""
|
||||
_boundary = 960
|
||||
_price = 0
|
||||
_duration = 0
|
||||
_patience = 0
|
||||
_reserve = 0
|
||||
_recovery = {}
|
||||
_commands = []
|
||||
_results = []
|
||||
_receipts = []
|
||||
_phases = []
|
||||
_points = {}
|
||||
_reset_runtime(SEEDS[_case])
|
||||
_runtime.configure_save_policy({&"enabled": false, &"daily_checkpoint_enabled": false})
|
||||
_runtime.command_completed.connect(func(result: CommandResult) -> void:
|
||||
_results.append({&"minute": _clock.absolute_minute, &"result": result.to_dictionary()})
|
||||
_expect(result.is_success(), "actual public command completion " + str(result.command_id))
|
||||
)
|
||||
|
||||
func _cmd(kind: StringName, payload: Dictionary, at: int = -1) -> CommandResult:
|
||||
_serial += 1
|
||||
var key: StringName = StringName("p04.s4.%s.command.%d" % [_case, _serial])
|
||||
var result: CommandResult = _runtime.submit_command(kind, payload, &"player", &"", 10, at, key)
|
||||
_commands.append({&"serial": _serial, &"kind": kind, &"payload": payload.duplicate(true),
|
||||
&"at": at, &"issued_at": _clock.absolute_minute, &"idempotency_key": key, &"result": result.to_dictionary()})
|
||||
_expect(result.is_success(), "public command " + String(kind))
|
||||
return result
|
||||
|
||||
func _queue(guest_id: StringName, request_id: StringName, exit_at: int) -> void:
|
||||
_cmd(&"spawn_guest", {&"guest_id": guest_id, &"guest_type_id": &"traveler", &"gold": _price * 2,
|
||||
&"options": {&"state": GuestRuntime.State.DECIDING, &"current_cell": Vector3i.ZERO, &"planned_exit_at": exit_at}})
|
||||
_cmd(&"create_service_request", {&"facility_id": _facility_id, &"request_id": request_id, &"guest_ids": [guest_id]})
|
||||
var guest: GuestRuntime = _runtime.guest_service.get_guest(guest_id)
|
||||
var request: ServiceRequest = _runtime.facility_service.get_request(request_id)
|
||||
_expect(guest != null and request != null, "actual Guest and request exist")
|
||||
if guest == null or request == null: return
|
||||
_expect(guest.state == GuestRuntime.State.QUEUING and guest.queue_request_id == request_id, "actual queued ownership before advancing clock")
|
||||
_expect(request.quoted_price == _price and request.service_minutes == _duration and request.reserved_inventory_ids.size() == 1, "definition price/duration and one meal reservation")
|
||||
for id: StringName in request.reserved_inventory_ids:
|
||||
var reservation: InventoryReservation = _runtime.inventory_service.get_reservation(id)
|
||||
_expect(reservation != null and reservation.is_active() and reservation.requester_id == request_id, "public queue actually reserves meal")
|
||||
|
||||
func _prepare() -> bool:
|
||||
_fresh()
|
||||
var facility: FacilityInstance = _build_cafeteria(true)
|
||||
if facility == null: return false
|
||||
_facility_id = facility.instance_id
|
||||
var definition: FacilityDefinition = _runtime.definition_registry.get_facility(facility.definition_id)
|
||||
_price = definition.base_price
|
||||
_duration = definition.base_service_minutes
|
||||
_patience = _runtime.guest_service.get_definition(&"traveler").base_patience
|
||||
for id: StringName in SERVERS:
|
||||
_cmd(&"register_staff", {&"staff_id": id, &"role_id": &"server", &"options": {&"state": StaffRuntime.State.OFF_DUTY, &"current_cell": Vector3i.ZERO}})
|
||||
_cmd(&"set_staff_work_assignment", {&"staff_id": id, &"template_id": &"DAY", &"facility_id": _facility_id})
|
||||
_clock.advance_minutes(_boundary - _duration - 1 - _clock.absolute_minute)
|
||||
_expect(facility.active_staff_ids == SERVERS, "normal public staff attendance")
|
||||
_expect(_stock(facility.local_inventory_id, &"ingredient/basic_meal", 1, &"p04.s4.stock"), "one actual meal")
|
||||
_queue(GUEST, REQUEST, _boundary + _duration)
|
||||
_clock.advance_one_minute()
|
||||
var active: Array = _runtime.facility_service.get_active_services(_facility_id)
|
||||
_expect(active.size() == 1, "one started service")
|
||||
if active.size() != 1: return false
|
||||
var service: ServiceInstance = active[0]
|
||||
_service_id = service.service_id
|
||||
_expect(service.started_at + _duration == _boundary, "source definition duration aligns completion")
|
||||
_clock.advance_minutes(_boundary - 1 - _clock.absolute_minute)
|
||||
var graph: Dictionary = _runtime.mana_network_service.create_snapshot()
|
||||
var adjacent: Array = []
|
||||
for edge: Array in graph[&"edges"]:
|
||||
if edge.has(String(_facility_id)):
|
||||
adjacent.append(edge[1] if edge[0] == String(_facility_id) else edge[0])
|
||||
_expect(adjacent.size() == 1, "actual sole cafeteria neighbour")
|
||||
if adjacent.size() != 1: return false
|
||||
_recovery = {&"neighbour": StringName(adjacent[0]), &"original_graph": graph,
|
||||
&"interval": ManaNetworkService.EVALUATION_INTERVAL_MINUTES,
|
||||
&"hold": ManaNetworkService.MINIMUM_OFF_HOLD_MINUTES}
|
||||
_expect(_boundary % int(_recovery[&"interval"]) == 0, "boundary is normal evaluation")
|
||||
_expect(_runtime.mana_network_service.disconnect_nodes(_facility_id, _recovery[&"neighbour"]), "public disconnect exact existing edge")
|
||||
_expect(_runtime.mana_network_service.validate_invariants()[&"valid"], "symmetric cut graph invariants")
|
||||
_reserve = _state.get_resource(&"mana")
|
||||
_expect(_reserve > 0 and service.elapsed_minutes == _duration - 1, "positive mana and natural duration-1 progress")
|
||||
return _clock.absolute_minute == _boundary - 1
|
||||
|
||||
func _connect_observations() -> void:
|
||||
_runtime.economy_service.transaction_posted.connect(func(id: StringName, entries: Array) -> void:
|
||||
var rows: Array = []
|
||||
for entry: LedgerEntry in entries: rows.append(entry.to_dictionary())
|
||||
_receipts.append({&"id": id, &"minute": _clock.absolute_minute, &"entries": rows})
|
||||
)
|
||||
_clock.tick_phase_started.connect(func(phase: int, minute: int) -> void:
|
||||
var label: String = "phase-%d-%s" % [minute, SimulationKernel.TickPhase.keys()[phase]]
|
||||
var row: Dictionary = _capture()
|
||||
row[&"phase"] = SimulationKernel.TickPhase.keys()[phase]
|
||||
_assert_phase(row)
|
||||
_phases.append(_write(label, row))
|
||||
)
|
||||
|
||||
func _assert_phase(point: Dictionary) -> void:
|
||||
# Every phase is retained as complete typed raw; semantics are checked at points.
|
||||
_expect(point[&"snapshot"][&"game_state"][&"resources"][&"mana"] > 0, "no global depletion")
|
||||
|
||||
func _capture() -> Dictionary:
|
||||
var snapshot: Dictionary = _runtime.create_snapshot()
|
||||
var operations: Dictionary = snapshot[&"systems"][&"runtime"][&"operations"]
|
||||
var facility: FacilityInstance = _runtime.facility_service.get_instance(_facility_id)
|
||||
var service: ServiceInstance = _runtime.facility_service.get_service(_service_id)
|
||||
var event: EventInstance = _runtime.event_service.get_instance(&"p04.destroy.instance")
|
||||
var kitchen: FacilityInstance = _runtime.facility_service.get_instance(facility.related_facility_id)
|
||||
var actors: Dictionary = {}
|
||||
var requests: Dictionary = {}
|
||||
var wallets: Dictionary = {}
|
||||
for id: StringName in [GUEST, QUEUED_GUEST]:
|
||||
var guest: GuestRuntime = _runtime.guest_service.get_guest(id)
|
||||
actors[String(id)] = guest.create_snapshot() if guest != null else {}
|
||||
wallets[String(id)] = _runtime.economy_service.get_balance(StringName("GUEST_WALLET:" + String(id)))
|
||||
for id: StringName in [REQUEST, QUEUED_REQUEST]:
|
||||
var request: ServiceRequest = _runtime.facility_service.get_request(id)
|
||||
requests[String(id)] = request.create_snapshot() if request != null else {}
|
||||
var reservations: Array = []
|
||||
for reservation: InventoryReservation in _runtime.inventory_service.get_reservations(false): reservations.append(reservation.create_snapshot())
|
||||
var ledger: Array = []
|
||||
for entry: LedgerEntry in _runtime.economy_service.get_entries(): ledger.append(entry.to_dictionary())
|
||||
return {&"snapshot": snapshot, &"minute": _clock.absolute_minute,
|
||||
&"inputs": {&"case": _case, &"seed": SEEDS[_case], &"serial": _serial, &"facility_id": _facility_id, &"service_id": _service_id,
|
||||
&"boundary": _boundary, &"price": _price, &"duration": _duration, &"patience": _patience, &"reserve": _reserve, &"recovery": _recovery.duplicate(true),
|
||||
&"kitchen_premise": "ActorHardening physical FLEX fixture; not natural hire/unlock"},
|
||||
&"related_facility_operating": facility.related_facility_operating, &"kitchen": kitchen.create_snapshot(), &"graph_invariants": _runtime.mana_network_service.validate_invariants(),
|
||||
&"facility": facility.create_snapshot(), &"service": service.create_snapshot() if service != null else {},
|
||||
&"event": event.create_snapshot() if event != null else {}, &"guests": actors, &"requests": requests, &"wallets": wallets,
|
||||
&"reservations": reservations, &"ledger": ledger, &"receipts": _receipts.duplicate(true),
|
||||
&"player_cash": _runtime.economy_service.get_balance(_runtime.PLAYER_CASH_ACCOUNT),
|
||||
&"available_meals": _runtime.inventory_service.available_quantity(facility.local_inventory_id, &"ingredient/basic_meal"),
|
||||
&"active_services": _runtime.facility_service.get_active_services(_facility_id).size(),
|
||||
&"operations_enabled": operations[&"enabled"], &"saved_coordinator": operations[&"coordinator"],
|
||||
&"actual_coordinator_absent": _runtime.operations_coordinator == null, &"unrelated_getters_called": false}
|
||||
|
||||
func _labels() -> Array[String]:
|
||||
return ["boundary", "held", "recovered"]
|
||||
|
||||
func _advance(label: String) -> void:
|
||||
if label == "duplicate_guard":
|
||||
var before_replay: Dictionary = _runtime.create_snapshot()
|
||||
var accepted: bool = _runtime.mana_network_service.connect_nodes(_facility_id, _recovery[&"neighbour"])
|
||||
var after_replay: Dictionary = _runtime.create_snapshot()
|
||||
_expect(accepted and var_to_bytes(before_replay) == var_to_bytes(after_replay), "public reconnect replay changes no Runtime field")
|
||||
_write("reconnect-replay", {&"before": before_replay, &"after": after_replay, &"accepted": accepted})
|
||||
if label == "recovered":
|
||||
_expect(_clock.absolute_minute == _boundary + 1, "reconnect only after held observation")
|
||||
_expect(_runtime.mana_network_service.connect_nodes(_facility_id, _recovery[&"neighbour"]), "reconnect exact cut edge")
|
||||
var graph: Dictionary = _runtime.mana_network_service.create_snapshot()
|
||||
_expect(var_to_bytes(graph[&"edges"]) == var_to_bytes(_recovery[&"original_graph"][&"edges"]), "all original edges restored")
|
||||
_expect(_runtime.mana_network_service.validate_invariants()[&"valid"], "reconnected graph invariants")
|
||||
var node: Dictionary = _runtime.mana_network_service.get_node(_facility_id)
|
||||
var resume_at: int = int(node[&"hold_until"])
|
||||
var interval: int = int(_recovery[&"interval"])
|
||||
while resume_at % interval != 0: resume_at += 1
|
||||
_expect(resume_at > _clock.absolute_minute and resume_at < _boundary + _duration, "finite normal hold/evaluation recovery before exit")
|
||||
while _clock.absolute_minute < resume_at:
|
||||
_clock.advance_one_minute()
|
||||
if _clock.absolute_minute < resume_at: _assert_stopped(_capture())
|
||||
else:
|
||||
_clock.advance_one_minute()
|
||||
|
||||
func _writer_case() -> void:
|
||||
if not _prepare(): return
|
||||
var before: Dictionary = _capture()
|
||||
_assert_before(before)
|
||||
_points["before"] = _write("before", before)
|
||||
_connect_observations()
|
||||
for label: String in _labels():
|
||||
_advance(label)
|
||||
var actual: Dictionary = _capture()
|
||||
_assert_outcome(before, actual)
|
||||
_save_point(label, actual)
|
||||
_advance("duplicate_guard")
|
||||
var guard: Dictionary = _capture()
|
||||
_assert_outcome(before, guard)
|
||||
_points["duplicate_guard"] = _write("duplicate_guard", guard)
|
||||
_branches[_case] = _write("case", {&"points": _points.duplicate(true), &"phases": _phases.duplicate(true),
|
||||
&"commands": _write("commands", {&"submitted": _commands, &"completed_including_fixture": _results})})
|
||||
|
||||
func _assert_before(point: Dictionary) -> void:
|
||||
_assert_unconfounded(point)
|
||||
_expect(point[&"service"][&"state"] == "ACTIVE" and point[&"facility"][&"power_available"], "before normal projection remains powered")
|
||||
_expect(point[&"service"][&"elapsed_minutes"] == _duration - 1 and point[&"reservations"].size() == 1, "natural duration-1 and one reservation")
|
||||
|
||||
func _assert_unconfounded(point: Dictionary) -> void:
|
||||
_expect(not point[&"operations_enabled"] and point[&"actual_coordinator_absent"], "existing isolated fixture")
|
||||
_expect(point[&"facility"][&"operator_open"] and point[&"related_facility_operating"], "open operator and operating dependency")
|
||||
_expect(point[&"facility"][&"durability"] > 0 and point[&"event"].is_empty(), "no destruction event")
|
||||
_expect(point[&"kitchen"][&"power_available"] and point[&"kitchen"][&"state"] == "OPEN", "kitchen stays active/powered")
|
||||
_expect(point[&"snapshot"][&"game_state"][&"resources"][&"mana"] > 0, "positive global reserve")
|
||||
_expect(point[&"facility"][&"active_staff_ids"] == SERVERS, "no shift confound")
|
||||
if point[&"service"][&"state"] != "COMPLETED":
|
||||
_expect(point[&"guests"][String(GUEST)][&"planned_exit_at"] > point[&"minute"] and point[&"guests"][String(GUEST)][&"state"] == "RECEIVING_SERVICE", "no exit at outage/hold")
|
||||
_expect(point[&"graph_invariants"][&"valid"], "graph allocation/storage/symmetry valid")
|
||||
_expect(_runtime.mana_network_service.get_consumer_state(StringName(point[&"kitchen"][&"instance_id"])) == ManaNetworkService.ConsumerState.ACTIVE, "kitchen network consumer ACTIVE")
|
||||
|
||||
func _assert_stopped(point: Dictionary) -> void:
|
||||
_assert_unconfounded(point)
|
||||
_expect(not point[&"facility"][&"power_available"] and point[&"service"][&"state"] == "PAUSED" and point[&"service"][&"interruption_reason"] == "NO_POWER", "actual isolated NO_POWER path")
|
||||
_expect(point[&"service"][&"elapsed_minutes"] == _duration - 1 and point[&"receipts"].is_empty(), "stopped progress held and no payment")
|
||||
|
||||
func _assert_reservation(before: Dictionary, point: Dictionary, request_id: StringName, state: String, terminal: int) -> void:
|
||||
var prior: Array = []
|
||||
var current: Array = []
|
||||
for row: Dictionary in before[&"reservations"]:
|
||||
if row[&"requester_id"] == String(request_id): prior.append(row)
|
||||
for row: Dictionary in point[&"reservations"]:
|
||||
if row[&"requester_id"] == String(request_id): current.append(row)
|
||||
_expect(prior.size() == 1 and current.size() == 1, "one original reservation per request")
|
||||
if prior.size() != 1 or current.size() != 1: return
|
||||
_expect(prior[0][&"reservation_id"] == current[0][&"reservation_id"] and current[0][&"state"] == state and current[0][&"terminal_at"] == terminal, "same reservation ID/state/terminal time; no second release")
|
||||
if state == "ACTIVE":
|
||||
_expect(var_to_bytes(prior[0]) == var_to_bytes(current[0]), "entire held reservation unchanged")
|
||||
var request: Dictionary = point[&"requests"][String(request_id)]
|
||||
_expect(not request.is_empty() and request[&"reserved_inventory_ids"].has(current[0][&"reservation_id"]), "active reservation has live request owner")
|
||||
else:
|
||||
_expect(point[&"requests"][String(request_id)].is_empty(), "terminal reservation has no orphan request")
|
||||
if state == "RELEASED":
|
||||
var release_count: int = 0
|
||||
var inventory: Dictionary = point[&"snapshot"][&"systems"][&"runtime"][&"inventory"]
|
||||
for operation: Dictionary in inventory[&"idempotency_results"]:
|
||||
var result: Dictionary = operation[&"result"]
|
||||
if operation[&"action"] == "release" and String(result.get(&"reservation_id", "")) == current[0][&"reservation_id"]:
|
||||
release_count += 1
|
||||
_expect(bool(result.get(&"ok", false)) and result.get(&"quantity", 0) == current[0][&"quantity"], "release returned actual reserved quantity, not an orphan repair/retry")
|
||||
_expect(release_count == 1, "one raw inventory release operation for original reservation")
|
||||
|
||||
func _assert_outcome(before: Dictionary, point: Dictionary) -> void:
|
||||
_assert_unconfounded(point)
|
||||
var service: Dictionary = point[&"service"]
|
||||
_expect(service[&"service_id"] == before[&"service"][&"service_id"], "same service ID")
|
||||
var paid: bool = service[&"state"] == "COMPLETED"
|
||||
if not paid:
|
||||
_assert_stopped(point)
|
||||
_expect(var_to_bytes(point[&"ledger"]) == var_to_bytes(before[&"ledger"]), "zero stopped ledger delta")
|
||||
_assert_reservation(before, point, REQUEST, "ACTIVE", -1)
|
||||
else:
|
||||
var node: Dictionary = _runtime.mana_network_service.get_node(_facility_id)
|
||||
_expect(point[&"facility"][&"power_available"] and service[&"elapsed_minutes"] == _duration and service[&"completed_at"] >= int(node[&"hold_until"]), "resume and complete after hold")
|
||||
_expect(point[&"receipts"].size() == 1, "one payment only")
|
||||
var expected: Array = before[&"ledger"].duplicate(true)
|
||||
for receipt: Dictionary in point[&"receipts"]: expected.append_array(receipt[&"entries"])
|
||||
_expect(var_to_bytes(expected) == var_to_bytes(point[&"ledger"]), "whole ledger exactly one receipt")
|
||||
_assert_reservation(before, point, REQUEST, "CONSUMED", service[&"completed_at"])
|
||||
_expect(point[&"wallets"][String(GUEST)] == _price * (1 if paid else 2) and point[&"player_cash"] == before[&"player_cash"] + (_price if paid else 0), "exact one price or zero")
|
||||
|
||||
func _save_point(label: String, point: Dictionary) -> void:
|
||||
_points[label] = _write(label, point)
|
||||
var path: String = "user://saves/p04_s4/" + _case + "-" + label
|
||||
var saved: Dictionary = SaveService.save_snapshot(path, point[&"snapshot"])
|
||||
var inspected: Dictionary = SaveService.inspect_snapshot(path)
|
||||
_expect(bool(saved.get(&"ok", false)) and bool(inspected.get(&"ok", false)) and bool(inspected.get(&"read_only", false)), "public formal save/inspect")
|
||||
_expect(var_to_bytes(inspected.get(&"snapshot", {})) == var_to_bytes(point[&"snapshot"]), "all typed fields preserved by formal package")
|
||||
_expect(var_to_bytes(_runtime.create_snapshot()) == var_to_bytes(point[&"snapshot"]), "formal saving leaves Runtime unchanged")
|
||||
_slots[_case + "-" + label] = ProjectSettings.globalize_path(path)
|
||||
# Snapshot bytes exist once in point raw and once in the required formal
|
||||
# package; indexes do not embed inspection/load copies of those bytes.
|
||||
|
||||
func _write(label: String, value: Variant, global_name: bool = false) -> Dictionary:
|
||||
var name: String = label if global_name else _mode + "-" + _case + "-" + label
|
||||
var reference: Dictionary = {}
|
||||
for extension: String in ["var", "json"]:
|
||||
var path: String = _evidence_dir.path_join(name + "." + extension)
|
||||
_expect(not FileAccess.file_exists(path), "raw point written exactly once " + name)
|
||||
var file: FileAccess = FileAccess.open(path, FileAccess.WRITE)
|
||||
_expect(file != null, "raw file " + name)
|
||||
if file == null: continue
|
||||
if extension == "var": file.store_buffer(var_to_bytes(value))
|
||||
else: file.store_string(JSON.stringify(value, "\t"))
|
||||
file.flush()
|
||||
file.close()
|
||||
reference[extension] = {&"path": path, &"sha256": FileAccess.get_sha256(path)}
|
||||
return reference
|
||||
|
||||
func _read(reference: Dictionary) -> Dictionary:
|
||||
var item: Dictionary = reference["var"]
|
||||
var path: String = item["path"]
|
||||
_expect(FileAccess.get_sha256(path) == item["sha256"], "raw typed SHA")
|
||||
var json_ref: Dictionary = reference["json"]
|
||||
_expect(FileAccess.get_sha256(json_ref["path"]) == json_ref["sha256"], "raw JSON SHA")
|
||||
var file: FileAccess = FileAccess.open(path, FileAccess.READ)
|
||||
_expect(file != null, "typed input readable")
|
||||
if file == null: return {}
|
||||
var value: Variant = bytes_to_var(file.get_buffer(file.get_length()))
|
||||
file.close()
|
||||
_expect(value is Dictionary, "typed input dictionary")
|
||||
return value if value is Dictionary else {}
|
||||
|
||||
func _restore_inputs(point: Dictionary) -> void:
|
||||
var inputs: Dictionary = point[&"inputs"]
|
||||
_expect(_serial == 0, "Reader starts with serial zero before importing external inputs")
|
||||
_serial = inputs[&"serial"]
|
||||
_facility_id = inputs[&"facility_id"]
|
||||
_service_id = inputs[&"service_id"]
|
||||
_boundary = inputs[&"boundary"]
|
||||
_price = inputs[&"price"]
|
||||
_duration = inputs[&"duration"]
|
||||
_patience = inputs[&"patience"]
|
||||
_reserve = inputs[&"reserve"]
|
||||
_recovery = inputs[&"recovery"].duplicate(true)
|
||||
|
||||
func _load_point(path: String, expected: Dictionary) -> bool:
|
||||
_fresh()
|
||||
_restore_inputs(expected)
|
||||
var loaded: Dictionary = SaveService.load_snapshot(path)
|
||||
_expect(bool(loaded.get(&"ok", false)), "public formal load")
|
||||
if not bool(loaded.get(&"ok", false)): return false
|
||||
_expect(var_to_bytes(loaded[&"snapshot"]) == var_to_bytes(expected[&"snapshot"]), "all saved typed fields equal Writer")
|
||||
var restored: bool = _runtime.restore_snapshot(loaded[&"snapshot"])
|
||||
_expect(restored, "public Runtime restore")
|
||||
_expect(var_to_bytes(_runtime.create_snapshot()) == var_to_bytes(expected[&"snapshot"]), "all restored typed fields equal Writer")
|
||||
return restored
|
||||
|
||||
func _reader() -> void:
|
||||
var file: FileAccess = FileAccess.open(_evidence_dir.path_join("writer.json"), FileAccess.READ)
|
||||
_expect(file != null, "Writer receipt")
|
||||
if file == null: return
|
||||
var writer: Dictionary = JSON.parse_string(file.get_as_text())
|
||||
file.close()
|
||||
_expect(int(writer["pid"]) != OS.get_process_id() and writer["profile"] != OS.get_user_data_dir(), "independent Reader PID/profile")
|
||||
for branch: String in CASES:
|
||||
_case = branch
|
||||
var writer_case: Dictionary = _read(writer["branches"][branch])
|
||||
var hashes: Dictionary = {}
|
||||
var restored_refs: Dictionary = {}
|
||||
for label: String in _labels():
|
||||
var key: String = branch + "-" + label
|
||||
var original: String = writer["slots"][key]
|
||||
var target: String = ProjectSettings.globalize_path("user://saves/p04_s4/" + key)
|
||||
_expect(DirAccess.make_dir_recursive_absolute(target) == OK, "private Reader formal slot")
|
||||
var directory: DirAccess = DirAccess.open(original)
|
||||
_expect(directory != null, "Writer formal slot readable")
|
||||
if directory == null: return
|
||||
var members: PackedStringArray = directory.get_files()
|
||||
members.sort()
|
||||
_expect(directory.get_directories().is_empty() and members == PackedStringArray(["journal.log", "manifest.json", "thumbnail.png", "world.bin"]), "all formal members enumerated")
|
||||
var member_hashes: Dictionary = {}
|
||||
for member: String in members:
|
||||
var sha: String = FileAccess.get_sha256(original.path_join(member))
|
||||
_expect(DirAccess.copy_absolute(original.path_join(member), target.path_join(member)) == OK, "copy every formal member")
|
||||
var copied_sha: String = FileAccess.get_sha256(target.path_join(member))
|
||||
_expect(not sha.is_empty() and sha == copied_sha, "original/copy member SHA equality")
|
||||
member_hashes[member] = {&"original_before": sha, &"copy_before": copied_sha}
|
||||
hashes[key] = {&"original": original, &"copy": target, &"members": member_hashes}
|
||||
_slots[key] = target
|
||||
var expected: Dictionary = _read(writer_case[&"points"][label])
|
||||
if not _load_point(target, expected): return
|
||||
restored_refs[label] = _write(label + "-restored", _capture())
|
||||
var before: Dictionary = _read(writer_case[&"points"]["before"])
|
||||
var boundary: Dictionary = _read(writer_case[&"points"]["boundary"])
|
||||
if not _load_point(_slots[branch + "-boundary"], boundary): return
|
||||
_assert_stopped(_capture())
|
||||
_connect_observations()
|
||||
var replay_refs: Dictionary = {}
|
||||
for label: String in ["held", "recovered", "duplicate_guard"]:
|
||||
_advance(label)
|
||||
var actual: Dictionary = _capture()
|
||||
var expected: Dictionary = _read(writer_case[&"points"][label])
|
||||
_expect(var_to_bytes(actual) == var_to_bytes(expected), "replay complete typed point including Runtime, inputs, receipts " + label)
|
||||
_assert_outcome(before, actual)
|
||||
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)
|
||||
_expect(_phases.size() == expected_phases.size(), "complete phase count")
|
||||
if _phases.size() == expected_phases.size():
|
||||
for index: int in range(_phases.size()):
|
||||
_expect(var_to_bytes(_read(_phases[index])) == var_to_bytes(_read(expected_phases[index])), "same phase order and all typed phase state")
|
||||
for key: String in hashes:
|
||||
var row: Dictionary = hashes[key]
|
||||
for member: String in row[&"members"]:
|
||||
var item: Dictionary = row[&"members"][member]
|
||||
item[&"original_after"] = FileAccess.get_sha256(String(row[&"original"]).path_join(member))
|
||||
item[&"copy_after"] = FileAccess.get_sha256(String(row[&"copy"]).path_join(member))
|
||||
_expect(item[&"original_before"] == item[&"original_after"] and item[&"copy_before"] == item[&"copy_after"], "original/copy unchanged after all loads and replay")
|
||||
_branches[branch] = _write("case", {&"restored": restored_refs, &"replay": replay_refs, &"phases": _phases,
|
||||
&"member_hashes": hashes, &"recovery_commands": _commands, &"replay_completed_commands": _results})
|
||||
@@ -0,0 +1,317 @@
|
||||
#!/usr/bin/env python3
|
||||
"""S4-only native entry. --check-only never loads ownership helpers or starts Godot."""
|
||||
from pathlib import Path
|
||||
import argparse
|
||||
import hashlib
|
||||
import importlib.util
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
sys.dont_write_bytecode = True
|
||||
|
||||
HERE = Path(__file__).resolve().parent
|
||||
BUILD = Path("/Users/korizatou114/Projects/TheTree-managed-worktrees/p04-01/.runtime/P04-01/build")
|
||||
PRODUCT = BUILD / "audit-support/p04-r17-full-inputs-r01/product"
|
||||
CACHE_RUN = BUILD / "p04-final-product-full-r01"
|
||||
TEST = "tests/s3/test_runtime_staff_assignment.gd"
|
||||
QA = HERE / "p04_s4_power_probe.gd"
|
||||
ENGINE = HERE / "Godot"
|
||||
MANIFEST = BUILD / "audit-support/p04-r17-full-inputs-r01/MANIFEST.json"
|
||||
MANIFEST_SHA = "a15f29fa12537f6d8aaf7cabea390922a9f16e3eb9c10981e5742aafc8c4c8a8"
|
||||
CONTRACTS = BUILD / "audit-support/p04-r17-full-inputs-r01/fixed/6ce6b28c5985e8a4f13b78bfeb1f1e09f6216d874fb01e0656ec1633bfa01cd7/completion_marker_contracts.json"
|
||||
CASES = ["S4"]
|
||||
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)
|
||||
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):
|
||||
raise ValueError("explicit typed declarations/loops required")
|
||||
if re.search(r"\.(?:patience_remaining|elapsed_minutes|power_available|capacity|hold_until)\s*=(?!=)", probe):
|
||||
raise ValueError("forbidden direct state mutation")
|
||||
for forbidden in ["evaluate_now(", "configure_operations(", "._update_shift_states(", ".record_duty_minute("]:
|
||||
if forbidden in probe:
|
||||
raise ValueError("forbidden bypass: " + forbidden)
|
||||
# Constants and public bodies are read from the actual selected source, not a memo.
|
||||
mana = (root / "scripts/mana/mana_network_service.gd").read_text()
|
||||
for key in ("EVALUATION_INTERVAL_MINUTES", "MINIMUM_OFF_HOLD_MINUTES"):
|
||||
if not re.search(r"const " + key + r" := 10\b", mana):
|
||||
raise ValueError("source timing changed: " + key)
|
||||
|
||||
|
||||
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 pin(path):
|
||||
path = Path(path)
|
||||
if path.is_symlink() or not path.is_file():
|
||||
raise ValueError("missing exact input: " + str(path))
|
||||
data = path.read_bytes()
|
||||
return dict(path=str(path), bytes=len(data), sha256=hashlib.sha256(data).hexdigest())
|
||||
|
||||
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-r22")
|
||||
parser.add_argument("--plan", type=Path, default=BUILD / "p04-s4-plan-r22.json")
|
||||
parser.add_argument("--cache-run", type=Path, default=CACHE_RUN)
|
||||
parser.add_argument("--godot", type=Path, default=ENGINE)
|
||||
parser.add_argument("--check-only", action="store_true")
|
||||
args = parser.parse_args()
|
||||
if args.godot.resolve() != ENGINE.resolve():
|
||||
raise ValueError("use the exact own-B staged engine")
|
||||
if args.cache_run.resolve() != CACHE_RUN.resolve():
|
||||
raise ValueError("only registered own-B full-run cache")
|
||||
root = args.project_root.resolve()
|
||||
out = args.output.resolve()
|
||||
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")
|
||||
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)
|
||||
refs = dict(source_before)
|
||||
refs[TEST] = pin(QA)
|
||||
template_guard(root)
|
||||
expected = {n: dict(bytes=p["bytes"], sha256=p["sha256"]) for n, p in refs.items()}
|
||||
fixed = [pin(p) for p in MATERIALS + [
|
||||
QA, Path(__file__), HERE / "S4_ROOT_RUN.md",
|
||||
root / "tests/transport/test_runtime_transport.gd",
|
||||
root / "tests/staff/test_rescue_elevator.gd",
|
||||
CONTRACTS,
|
||||
]]
|
||||
selected = dict(root_before=source_before, map={n: p["sha256"] for n, p in refs.items()}, timeout=1200)
|
||||
cache_note = None
|
||||
cache_receipts = []
|
||||
for leaf in ["runner-ended.json", "runner-input.json"]:
|
||||
path = args.cache_run / leaf
|
||||
try:
|
||||
cache_receipts.append(pin(path))
|
||||
except OSError as caught:
|
||||
cache_note = dict(path=str(path), error=type(caught).__name__ + ": " + str(caught),
|
||||
required_before_native=True)
|
||||
break
|
||||
plan = dict(protocol="p04-s4-preparation-v1", project_root=str(root), output=str(out), engine_path=str(args.godot.resolve()),
|
||||
source_before=source_before, selected_source_map=selected["map"],
|
||||
QA_overrides=[TEST], fixed_input_pins=fixed, cache_run=str(args.cache_run),
|
||||
cache_receipts=cache_receipts, cache_access=cache_note,
|
||||
phases=["import", "parse", "writer", "reader"],
|
||||
native_engine_launches=0, whole_goal_accepted=False, unit_accepted=False)
|
||||
# Check-only only reads source/materials and writes the plan in task build.
|
||||
# It deliberately does not read default-player data, inspect processes or stat Godot.
|
||||
if args.check_only:
|
||||
args.plan.parent.mkdir(parents=True, exist_ok=True)
|
||||
if args.plan.exists():
|
||||
r.require(r.read(args.plan) == plan, "existing plan differs; use a fresh plan path")
|
||||
else:
|
||||
r.write(args.plan, plan)
|
||||
print(json.dumps(dict(check_only=True, engines=0, source_files=len(source_before),
|
||||
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(args.plan.is_file() and r.read(args.plan) == plan, "run exact check-only plan first")
|
||||
engine_descriptor = None
|
||||
def fixed_guard():
|
||||
template_guard(root)
|
||||
if engine_descriptor is not None:
|
||||
r.require(pin(engine_descriptor["path"]) == engine_descriptor, "engine changed during collection")
|
||||
for value in fixed + cache_receipts:
|
||||
r.require(pin(value["path"]) == value, "fixed input changed: " + value["path"])
|
||||
fixed_guard()
|
||||
# Native admission is Root-only and fails closed on unreadable cache.
|
||||
r.require(cache_note is None, "Root must read exact cache receipts: " + str(cache_note))
|
||||
old = args.cache_run
|
||||
r.require(r.read(old / "runner-ended.json")["passed"], "ended cache run must have passed")
|
||||
old_map = r.read(old / "runner-input.json")["selected_source_map"]
|
||||
current_map = {n: p["sha256"] for n, p in source_before.items()}
|
||||
r.require({k: v for k, v in old_map.items() if k != "tools/check_p04_order_evidence.py"} == current_map and len(old_map) == 1339, "immutable full cache: all 1338 product inputs equal; checker is not parsed/executed by product suites")
|
||||
protected = r.default_player(root)
|
||||
outer = module("s4_owned_outer", r.SUPPORT / "owned_outer.py")
|
||||
r.require(not outer.native.helper["live_engines"](), "another Godot owns CPU")
|
||||
engine = args.godot.resolve()
|
||||
r.require(engine.is_file(), "Root native Godot path")
|
||||
engine_descriptor = pin(engine)
|
||||
r.require(engine_descriptor["sha256"] == r.read(old / "runner-input.json")["engine_sha256"],
|
||||
"staged engine matches preserved full proof; no environment substitution")
|
||||
r.require(shutil.disk_usage(out.parent).free >= 1024**3 + engine.stat().st_size + 136*1024**2,
|
||||
"reviewed native disk admission")
|
||||
r.require(not out.exists(), "fresh output required; preserve previous attempts")
|
||||
out.mkdir()
|
||||
stage = out / "stage"
|
||||
stage.mkdir()
|
||||
(out / "starters").mkdir()
|
||||
(out / "bootstrap").mkdir()
|
||||
phases = []
|
||||
previous = {}
|
||||
error = None
|
||||
guards = []
|
||||
cleanup = []
|
||||
cleanup_errors = []
|
||||
cache_before = None
|
||||
formal_before = None
|
||||
formal_after = None
|
||||
original_phase = outer.run_phase
|
||||
def run_phase(argv, folder, timeout, env, **kwargs):
|
||||
env = dict(env)
|
||||
if folder.name in ["writer", "reader"]:
|
||||
env.update(THE_TREE_S4_EVIDENCE=str(out / "raw"), THE_TREE_S4_MODE=folder.name)
|
||||
return original_phase(argv, folder, timeout, env, **kwargs)
|
||||
outer.run_phase = run_phase
|
||||
r.write(out / "runner-started.json", dict(started=r.now(), owner_runner_pid=os.getpid(),
|
||||
plan=pin(args.plan), engines_launched=0))
|
||||
try:
|
||||
r.write(out / "source_before.json", source_before)
|
||||
r.write(out / "selected-source-map.json", refs)
|
||||
# Private source stage first, then literal reviewed bootstrap.
|
||||
for name, value in refs.items():
|
||||
target = stage / name
|
||||
target.parent.mkdir(parents=True, exist_ok=True)
|
||||
r.copy_source(Path(value["path"]), target)
|
||||
r.require(r.inventory(stage, stage=True) == expected, "whole private source")
|
||||
for name, value in r.read(r.SUPPORT / "bootstrap-scripts.json").items():
|
||||
data = value["text"].encode()
|
||||
r.require(hashlib.sha256(data).hexdigest() == value["sha256"], "bootstrap pin")
|
||||
(out / "bootstrap" / name).write_bytes(data)
|
||||
cache = old / "stage/.godot"
|
||||
cache_before = r.inventory(cache)
|
||||
r.require(bool(cache_before), "nonempty ended cache")
|
||||
for name in cache_before:
|
||||
src = cache / name
|
||||
dst = stage / ".godot" / name
|
||||
dst.parent.mkdir(parents=True, exist_ok=True)
|
||||
subprocess.run(["/bin/cp", "-c", str(src), str(dst)], check=True)
|
||||
r.require((src.stat().st_dev, src.stat().st_ino) != (dst.stat().st_dev, dst.stat().st_ino),
|
||||
"cache clone is a separate inode")
|
||||
r.require(r.inventory(stage / ".godot") == cache_before, "whole cache clone hashes")
|
||||
r.write(out / "cache-reuse.json", dict(ended_run=str(old), receipts=cache_receipts,
|
||||
whole_cache=cache_before, independent_inode=True,
|
||||
ordinary_import_required=True, ordinary_parse_required=True))
|
||||
paths = ["res://" + n for n in sorted(refs) if n.endswith(".gd")]
|
||||
r.write(out / "parse-paths.json", paths)
|
||||
markers = module("s4_markers", root / "tools/strict_test_markers.py")
|
||||
contracts = markers.load_contracts(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")
|
||||
r.write(out / "contracts.json", contracts)
|
||||
r.write(out / "runner-input.json", dict(plan, owner_runner_pid=os.getpid(),
|
||||
wrapper_sha256=r.sha(__file__), QA=pin(QA), engine=engine_descriptor, runner_sha256=r.sha(root / "tools/run_all_tests.py"),
|
||||
default_player_before=protected, fixed_input_pins=fixed,
|
||||
functional_watchdog_seconds=1200, source_adoption=False))
|
||||
diagnostics = module("s4_diagnostics", r.SUPPORT / "diagnostic_gate.py")
|
||||
owners = module("s4_owners", r.SUPPORT / "ordinary_proof_gate.py")
|
||||
audio = module("s4_audio", r.SUPPORT / "audio_evidence_gate.py")
|
||||
public = (stage / "project.godot").read_bytes()
|
||||
for phase, test in [("import", None), ("parse", None), ("writer", TEST), ("reader", TEST)]:
|
||||
if phase == "reader":
|
||||
writer = r.read(out / "raw/writer.json")
|
||||
formal_before = {n: r.inventory(Path(p)) for n, p in writer["slots"].items()}
|
||||
r.require(sorted(formal_before) == SLOTS, "exact three formal points for isolated power case")
|
||||
row = r.execute_phase(str(engine), stage, out, phase, test, selected, expected,
|
||||
previous, policy, contracts, paths, public, protected, root,
|
||||
outer, markers, diagnostics, owners, audio)
|
||||
phases.append(row)
|
||||
# execute_phase uses the same test log name; retain each phase's exact log too.
|
||||
if test and row.get("log"):
|
||||
(out / (phase + "-combined-raw.log")).write_bytes((out / row["log"]).read_bytes())
|
||||
row["strict_runner_log_path"] = row["log"]
|
||||
row["log"] = phase + "-combined-raw.log"
|
||||
r.write(out / (phase + "-actual-phase.json"), row)
|
||||
print(json.dumps(dict(phase=phase, passed=row["passed"], error=row.get("validation_error"))), flush=True)
|
||||
r.require(row["passed"], "first strict phase failure: " + phase)
|
||||
if phase in ["writer", "reader"]:
|
||||
receipt = r.read(out / ("raw/" + phase + ".json"))
|
||||
r.require(receipt["checks"] > 0 and receipt["failures"] == 0,
|
||||
"S4 actual outcome receipt")
|
||||
r.require(sorted(receipt["branches"]) == CASES,
|
||||
"exact one independent Writer/Reader case")
|
||||
r.require(sorted(receipt["slots"]) == SLOTS, "all formal point slots")
|
||||
r.require(receipt["pid"] == row["actual_pid"], "actual native PID/receipt")
|
||||
writer = r.read(out / "raw/writer.json")
|
||||
reader = r.read(out / "raw/reader.json")
|
||||
r.require(writer["pid"] != reader["pid"] and writer["profile"] != reader["profile"], "distinct formal processes")
|
||||
formal_after = {n: r.inventory(Path(p)) for n, p in writer["slots"].items()}
|
||||
r.require(formal_before == formal_after, "Reader leaves Writer packages unchanged")
|
||||
except BaseException as caught:
|
||||
error = type(caught).__name__ + ": " + str(caught)
|
||||
finally:
|
||||
cleanup, cleanup_errors = outer.finish_captured(outer.OWNED)
|
||||
try:
|
||||
r.write(out / "outer-owned-finally.json", dict(cleanup=cleanup, errors=cleanup_errors))
|
||||
except BaseException as caught:
|
||||
guards.append("finally receipt: " + type(caught).__name__ + ": " + str(caught))
|
||||
# Fixed guard always follows ownership cleanup, even if setup or an engine failed.
|
||||
try:
|
||||
fixed_guard()
|
||||
after = r.source_refs(root)
|
||||
r.write(out / "source_after.json", after)
|
||||
r.require(after == source_before, "whole product source unchanged")
|
||||
r.require(r.default_player(root) == protected, "default player unchanged")
|
||||
if (stage / "project.godot").exists():
|
||||
r.require(r.inventory(stage, stage=True) == dict(expected, **previous), "whole private source unchanged")
|
||||
if cache_before is not None:
|
||||
r.require(r.inventory(old / "stage/.godot") == cache_before, "original cache unchanged")
|
||||
if formal_before is not None:
|
||||
writer = r.read(out / "raw/writer.json")
|
||||
formal_after = {n: r.inventory(Path(p)) for n, p in writer["slots"].items()}
|
||||
r.require(formal_before == formal_after, "Writer formal packages unchanged after Reader, including failure")
|
||||
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
|
||||
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,
|
||||
actual_captured_PIDs=pids, cleanup=cleanup, cleanup_errors=cleanup_errors,
|
||||
formal_before=formal_before, formal_after=formal_after,
|
||||
whole_goal_accepted=False, unit_accepted=False)
|
||||
# IO1 has already copied all four members into a separate Reader profile.
|
||||
# Mirror those exact complete directories to own B for read-only R verification.
|
||||
# Original profile paths are provenance after this step, never verifier inputs.
|
||||
if passed:
|
||||
relocated = {}
|
||||
for role in ("writer", "reader"):
|
||||
receipt = r.read(out / ("raw/" + role + ".json"))
|
||||
relocated[role] = {}
|
||||
for slot, original in receipt["slots"].items():
|
||||
target = out / "formal" / role / slot
|
||||
target.mkdir(parents=True)
|
||||
members = r.inventory(Path(original))
|
||||
r.require(set(members) == {"journal.log", "manifest.json", "thumbnail.png", "world.bin"}, "all formal members")
|
||||
for member in members:
|
||||
shutil.copyfile(Path(original) / member, target / member)
|
||||
r.require(r.inventory(target) == members == formal_before[slot], "whole formal mirror")
|
||||
relocated[role][slot] = dict(provenance=original, relative=str(target.relative_to(out)), members=members)
|
||||
r.write(out / "formal-relocation.json", relocated)
|
||||
r.write(out / "raw-inventory.json", r.inventory(out / "raw"))
|
||||
r.write(out / "PID-set.json", dict(owner_runner_pid=os.getpid(), engine_PIDs=pids))
|
||||
r.write(out / "execution.json", execution)
|
||||
r.write(out / "runner-ended.json", dict(execution, ended=r.now()))
|
||||
print(json.dumps(dict(passed=passed, error=error, guard_errors=guards, output=str(out))))
|
||||
return 0 if passed else 1
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
raise SystemExit(main())
|
||||
except Exception as caught:
|
||||
print(type(caught).__name__ + ": " + str(caught), file=sys.stderr)
|
||||
raise SystemExit(2)
|
||||
Reference in New Issue
Block a user