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

This commit is contained in:
Agent Control Runner
2026-10-18 15:41:18 +09:00
parent acab529c8d
commit eb94e1d7db
24 changed files with 4092 additions and 28 deletions
@@ -1,4 +1,39 @@
# REPAIR40 implementation supersession; native evidence remains pending
# REPAIR43 — native evidence and formal acceptance pending
The R42/R43 implementation batch now includes the public-restored G1/G2
journal shadows, independent typed adapter oracle, exact-N idle OBJECTIVE
breach, S5D_IN_FLIGHT event destruction, S5G_SHIFT_1080, S5H_PAUSED_MIDNIGHT,
and S5E public same-minute advance_to after formal restore. See
`../REPAIR41_STATUS.md` and `../REPAIR43_SOURCE_FACTS.json` for source bodies,
lines, hashes and the spec EOF protocol. The closed-field/file-freeze blockers
are superseded. The spec passes its existing checker protocol without edits.
Implementation is not native proof. Root must run the fresh nine-case S5
Writer/Reader and adapters alongside fresh S1–S4 in the prescribed single
batch. The new shift/paused/replay keys are emitted only after fresh typed raw
derivation; paused_midnight is then removed from the adapter pending list.
patience_release remains pending unless fresh S3 independently supplies it.
Future-raw positives and mutations are Root-only. No historical run supplies
these new keys. All 15+EV requirements and thresholds remain mandatory.
Pure results are in `../REPAIR43_PURE_RESULTS.json`; static results are in
`../REPAIR41_STATIC_CHECKS.json`. r35/r36/R40 native remain FAILED, Q37 is only
its own-version local PASS, and P04 credit remains 0. Registered validation
precedes formal independent whole-unit review. No native/full run was performed
by this worker; no completion claim or new counted unit is made.
## Historical REPAIR41 partial repair (superseded implementation status)
See `../REPAIR41_STATUS.md`: M serializes an additional `command_queue.accepted`
metadata row for both guard failures, outside the explicitly enumerated G1/G2
queue deltas. Its inclusion needs clarification before claiming exact equality.
Only the mandatory-condition diagnostic and historical/fresh S4 wrapper
separation are implemented and supersede their earlier repair-pending entries.
S5D re-scope/G1/G2/breach, S5G/S5H, same-minute replay, adapter derivations and
fresh-condition wiring remain pending. R40 native S5D remains FAILED; its prior
source implementation below is not an accepted fixture. No P04 credit is earned.
## Historical REPAIR40 implementation supersession
The implementation-pending statements below are superseded only for S5A/S5B
power, S5C command destruction, S5D automatic raid destruction, S5E paid midnight
@@ -1,3 +1,76 @@
# REPAIR43 submission — Root verification required
The R41 closed journal-field restriction and R42 raw-only spec stop are
superseded. The spec passes the existing one-final-LF checker condition.
`../REPAIR41_STATUS.md` describes the complete R42/R43 implementation and
`../REPAIR43_SOURCE_FACTS.json` contains full current-M source bodies/hashes.
This is a QA submission, not admission, native PASS or formal completion.
The case table now includes S5A/B/C, S5D_DESTRUCTION_RAID (idle OBJECTIVE plus
G1), S5D_IN_FLIGHT (event path plus G2), S5E/F, S5G_SHIFT_1080 and
S5H_PAUSED_MIDNIGHT. The wrapper already derives CASES/LABELS/SLOTS from this
table. Preserve the table-driven full roster. G1/G2 use public paused immediate
submission with detached public-restored shadows; business state is identical
and the whole typed journal is independently recomputed by the adapter.
Stage the entire QA hierarchy, including new `s5_guard_oracle.py`, with the
selected exact Q. Worker static/pure outputs do not establish Q applicability.
Run `s5_order_adapter_controls.py --pure-only` among affected pure controls.
After fresh Reader raw exists, run its ordinary explicit
`--raw-root/--writer-sha256/--reader-sha256/--scratch` mode as well; this executes
the actual-data derivations and all typed order/guard mutations. Preserve the
failed R40 native result and never reuse its missing Reader as a positive.
Authoritative corrected Root order:
1. Affected pure controls.
2. Check-only S1–S5 plans.
3. Capacity check under existing permissions, with no unapproved deletion.
4. One heavy lease for fresh native S1–S5 including S5D/G/H, PID/cleanup checks
and complete restore manifests.
5. Reader and adapter on actual raw, including the fresh-raw mutation controls.
6. Fresh collect.
7. Full suite once, after source and controls are ready.
8. Index.
9. --verify-only.
10. Registered validation.
11. Formal independent whole-unit Opus review.
12. Prepare / exact-C standing authorization / integration / final / DB join /
ledger / push under the existing Root workflow.
No heavy tests while the worker is active. A second batch is only for defects
revealed by observed native raw. The obsolete 500000-byte review-material cap
does not apply; do not omit source/evidence or compress merely to meet it.
## Historical REPAIR41 direction (superseded by the order above)
The exact G1/G2 oracle has a source-contract conflict documented in
`../REPAIR41_STATUS.md`. M also serializes one new `command_queue.accepted` row.
Only the mandatory-condition diagnostic and historical/fresh S4 wrapper pin
separation are repaired. S5D/G/H and adapter/fresh wiring remain unimplemented.
Do not treat the partial pure-check results as worker success or native evidence.
After a complete submission, the recorded Root order remains:
1. Affected pure controls.
2. Check-only S1–S5 plan.
3. Capacity check before the single heavy lease (about 3 GB free; OS swap is
separate from evidence); only verified compression or approved cold-drive
offload if needed, with no unapproved deletion.
4. One heavy lease for fresh native S1–S5 including S5D/G/H, PID/cleanup checks,
complete Git restore manifest and reuse of the ended Q.
5. Reader and S5 order adapter on actual raw.
6. Fresh collect.
7. Full suite 184/329 once on final Q.
8. Index.
9. --verify-only.
10. Independent Opus review of the whole unit.
11. Registered validation.
12. Normal prepare/final, exact-C approval, integration, Root DB join, ledger
and main push.
This list preserves the latest recorded order over the earlier condensed list
below. A second batch is only for defects revealed by observed native raw.
# REPAIR40 A–F source batch — Root verification required
This section supersedes earlier implementation-pending directions below only
@@ -4,11 +4,14 @@ const CASE_TABLE: Dictionary = {
"S5A_PURE": {"expected_reserved_ids": 0, "labels": ["boundary", "held", "recovered", "duplicate_guard"], "prepare": "_prepare", "advance": "_advance", "stop": "_assert_stopped", "assert": "_assert_outcome"},
"S5B_DEPENDENCY": {"expected_reserved_ids": 1, "labels": ["boundary", "held", "recovered", "duplicate_guard"], "prepare": "_prepare", "advance": "_advance", "stop": "_assert_stopped", "assert": "_assert_outcome"},
"S5C_DESTRUCTION_COMMAND": {"expected_reserved_ids": 1, "labels": ["boundary", "held"], "prepare": "_prepare_order", "advance": "_advance_order", "stop": "_assert_order_stop", "assert": "_assert_order"},
"S5D_DESTRUCTION_RAID": {"expected_reserved_ids": 1, "labels": ["boundary", "held"], "prepare": "_prepare_order", "advance": "_advance_order", "stop": "_assert_order_stop", "assert": "_assert_order"},
"S5D_DESTRUCTION_RAID": {"expected_reserved_ids": 0, "labels": ["boundary", "held"], "prepare": "_prepare_idle_breach", "advance": "_advance_order", "stop": "_assert_idle_breach", "assert": "_assert_idle_order"},
"S5D_IN_FLIGHT": {"expected_reserved_ids": 1, "labels": ["boundary", "held"], "prepare": "_prepare_order", "advance": "_advance_order", "stop": "_assert_in_flight", "assert": "_assert_in_flight_order"},
"S5G_SHIFT_1080": {"expected_reserved_ids": 1, "labels": ["boundary", "held"], "prepare": "_prepare_order", "advance": "_advance_order", "stop": "_assert_order_stop", "assert": "_assert_order"},
"S5H_PAUSED_MIDNIGHT": {"expected_reserved_ids": 1, "labels": ["boundary", "held", "recovered"], "prepare": "_prepare_order", "advance": "_advance_paused_midnight", "stop": "_assert_paused_midnight", "assert": "_assert_paused_midnight_order"},
"S5E_MIDNIGHT": {"expected_reserved_ids": 1, "labels": ["boundary", "recalled"], "prepare": "_prepare_order", "advance": "_advance_order", "stop": "_assert_order_stop", "assert": "_assert_order"},
"S5F_EXIT": {"expected_reserved_ids": 1, "labels": ["boundary", "held"], "prepare": "_prepare_order", "advance": "_advance_order", "stop": "_assert_order_stop", "assert": "_assert_order"}
}
const SEEDS: Dictionary = {"S5A_PURE": 420550, "S5B_DEPENDENCY": 420551, "S5C_DESTRUCTION_COMMAND": 420552, "S5D_DESTRUCTION_RAID": 420553, "S5E_MIDNIGHT": 424242, "S5F_EXIT": 420555}
const SEEDS: Dictionary = {"S5A_PURE": 420550, "S5B_DEPENDENCY": 420551, "S5C_DESTRUCTION_COMMAND": 420552, "S5D_DESTRUCTION_RAID": 420553, "S5D_IN_FLIGHT": 420553, "S5E_MIDNIGHT": 424242, "S5F_EXIT": 420555, "S5G_SHIFT_1080": 420556, "S5H_PAUSED_MIDNIGHT": 424242}
const GUEST: StringName = &"p04.s5.guest.a"
const REQUEST: StringName = &"p04.s5.request.a"
const QUEUED_GUEST: StringName = &"p04.s5.guest.b"
@@ -36,6 +39,9 @@ var _points: Dictionary = {}
var _branches: Dictionary = {}
var _slots: Dictionary = {}
var _replay_reference: Dictionary = {}
var _guard_references: Dictionary = {}
var _expected_failure: Dictionary = {}
var _observed_phase: String = ""
func _run() -> void:
_evidence_dir = OS.get_environment("THE_TREE_S5_EVIDENCE")
@@ -69,6 +75,9 @@ func _fresh() -> void:
_resource_command = {}
_recovery = {}
_replay_reference = {}
_guard_references = {}
_expected_failure = {}
_observed_phase = ""
_commands = []
_results = []
_receipts = []
@@ -78,7 +87,10 @@ func _fresh() -> void:
_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))
if not _expected_failure.is_empty() and result.command_id == _expected_failure["command_id"]:
_expect(var_to_bytes(result.to_dictionary()) == var_to_bytes(_expected_failure), "independently bound expected guard failure")
else:
_expect(result.is_success(), "actual public command completion " + str(result.command_id))
)
func _cmd(kind: StringName, payload: Dictionary, at: int = -1) -> CommandResult:
@@ -157,7 +169,8 @@ func _prepare() -> bool:
func _prepare_order() -> bool:
_fresh()
var midnight: bool = _case == "S5E_MIDNIGHT"
var midnight: bool = _case in ["S5E_MIDNIGHT", "S5H_PAUSED_MIDNIGHT"]
if _case == "S5G_SHIFT_1080": _boundary = 1080
if midnight:
_boundary = 1440
var enabled: Dictionary = _runtime.enable_production_operations()
@@ -180,6 +193,7 @@ func _prepare_order() -> bool:
_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": &"NIGHT" if midnight else &"DAY", &"facility_id": _facility_id})
var queue_at: int = _boundary - _duration - 1
if _case == "S5D_IN_FLIGHT": queue_at += 1
_expect(_price > 0 and _duration > 1 and queue_at > _clock.absolute_minute, "natural paid service before boundary")
if queue_at <= _clock.absolute_minute or _duration <= 1: return false
if _case == "S5D_DESTRUCTION_RAID":
@@ -196,17 +210,28 @@ func _prepare_order() -> bool:
if active.size() != 1: return false
var service: ServiceInstance = active[0]
_service_id = service.service_id
_expect(service.started_at + _duration == _boundary, "natural N completion")
_expect(service.started_at + _duration == _boundary + (1 if _case == "S5D_IN_FLIGHT" else 0), "natural completion from snapshot duration")
_price = service.price_snapshot
_duration = service.duration_minutes
if _case == "S5D_DESTRUCTION_RAID":
_clock.advance_minutes(_boundary - 5 - _clock.absolute_minute)
_prepare_breach()
_clock.advance_minutes(_boundary - 2 - _clock.absolute_minute)
_queue(QUEUED_GUEST, QUEUED_REQUEST, _boundary + _duration + 1)
if _case == "S5H_PAUSED_MIDNIGHT":
_expect(_duration > 11, "pause begins before last pre-midnight MANA evaluation")
_clock.advance_minutes(_boundary - 11 - _clock.absolute_minute)
_reserve = _state.get_resource(&"mana")
_cmd(&"spend_resources", {&"cost": {&"mana": _reserve}})
_clock.advance_minutes(_boundary - 1 - _clock.absolute_minute)
if _case == "S5F_EXIT": _queue(QUEUED_GUEST, QUEUED_REQUEST, _boundary + _duration + 1)
_reserve = _state.get_resource(&"mana")
if _case != "S5H_PAUSED_MIDNIGHT": _reserve = _state.get_resource(&"mana")
_recovery = {&"staff_ids": staff_ids, &"resume_minute": _boundary}
_expect(service.elapsed_minutes == _duration - 1, "duration minus one at N-1")
if _case == "S5D_IN_FLIGHT":
_guard_failure("G2", &"register_defense_asset", {&"raid_id": &"p04.s5.guard.raid", &"asset_id": _facility_id, &"kind": &"OBJECTIVE", &"max_integrity": 10000}, "A busy Facility cannot become a Defense asset.", {})
_cmd(&"register_event_definition", {&"definition": {&"event_id": &"p04.s5.break", &"category": &"FLAVOR", &"priority": 100, &"foreground": false, &"transaction_policy": &"ROLLBACK_ALL", &"automatic_actions": [{&"action_id": &"break", &"type": &"SET_FACILITY_STATE", &"payload": {&"facility_id": _facility_id, &"conditions": {&"durability": 0, &"suspension_reason": &"DESTROYED"}}}]}})
if _case not in ["S5D_IN_FLIGHT", "S5H_PAUSED_MIDNIGHT"]:
_expect(service.elapsed_minutes == _duration - 1, "duration minus one at N-1")
return _clock.absolute_minute == _boundary - 1
func _prepare_paid_reception() -> void:
@@ -240,9 +265,112 @@ func _prepare_breach() -> void:
_cmd(&"start_defense_raid", {&"raid_id": &"p04.s5.raid"})
var due: Array[Dictionary] = _runtime.defense_service.get_due_rounds(_boundary)
_expect(due.size() == 1 and due[0][&"earliest_minute"] == _boundary and due[0][&"raid_id"] == &"p04.s5.raid", "automatic breach due at exactly N; no substitute")
_recovery[&"due_rounds"] = due.duplicate(true)
func _guard_failure(label: String, kind: StringName, payload: Dictionary, message: String, details: Dictionary) -> void:
# Paused immediate public execution: no tick/business transition is permitted.
_clock.set_paused(true)
var before: Dictionary = _runtime.create_snapshot().duplicate(true)
var expected: Dictionary = before.duplicate(true)
var journal: Dictionary = expected[&"systems"][&"runtime"]
_expect(journal[&"command_queue"]["pending"].is_empty() and journal[&"command_queue"]["in_flight"].is_empty(), "isolated guard command")
_expect(not journal[&"operations"][&"enabled"], "guard has no population synchronization")
var queue: CommandQueue = CommandQueue.new()
var ids: StableIdGenerator = StableIdGenerator.new()
var events: DomainEventStream = DomainEventStream.new()
_expect(queue.restore_snapshot(journal[&"command_queue"]), "shadow queue public restore")
_expect(ids.restore_snapshot(journal[&"id_generator"]), "shadow ID public restore")
_expect(events.restore_snapshot(journal[&"domain_events"]), "shadow stream public restore")
_serial += 1
var key: StringName = StringName("p04.s5.%s.command.%d" % [_case, _serial])
var command: SimulationCommand = SimulationCommand.new(journal[&"next_command_id"], _clock.absolute_minute, _clock.absolute_minute, 10, kind, &"player", &"", payload, key)
var failure: CommandResult = CommandResult.failed(CommandResult.Code.VALIDATION_FAILED, command.command_id, message, details)
_expected_failure = failure.to_dictionary()
_expect(queue.enqueue(command).is_success(), "shadow enqueue")
var completed: Array[CommandResult] = queue.execute_ready(_clock.absolute_minute, func(_command: SimulationCommand) -> CommandResult: return failure.copy())
_expect(completed.size() == 1, "one shadow failure")
var entities: Array[StringName] = []
var event: SimulationDomainEvent = SimulationDomainEvent.new(ids.next_id(&"domain_event"), &"COMMAND_FAILED", _clock.absolute_minute, &"simulation_runtime", entities, failure.to_dictionary(), command.command_id)
_expect(events.publish(event), "exact M failed-result event")
journal[&"next_command_id"] += 1
journal[&"command_queue"] = queue.create_snapshot()
journal[&"id_generator"] = ids.create_snapshot()
journal[&"domain_events"] = events.create_snapshot()
# EXPECTED is complete before submit, never read back from AFTER.
var expected_bytes: PackedByteArray = var_to_bytes(expected)
var actual: CommandResult = _runtime.submit_command(kind, payload, &"player", &"", 10, -1, key)
var after: Dictionary = _runtime.create_snapshot()
_expect(var_to_bytes(actual.to_dictionary()) == var_to_bytes(failure.to_dictionary()), "guard exact failed result")
_expect(expected_bytes == var_to_bytes(after), "whole typed guard equality with no masks")
var callbacks: int = 0
for row: Dictionary in _results:
if row[&"result"]["command_id"] == command.command_id: callbacks += 1
_expect(callbacks == 1, "one failed command_completed callback")
_guard_references[label] = _write(label, {&"before": before, &"expected": expected, &"after": after, &"command": command.to_dictionary(), &"result": actual.to_dictionary(), &"guard": label})
_expected_failure = {}
func _prepare_idle_breach() -> bool:
_fresh()
var facility: FacilityInstance = _build_cafeteria(true)
if facility == null: return false
_facility_id = facility.instance_id
_recovery = {&"staff_ids": [], &"resume_minute": _boundary}
_clock.advance_minutes(_boundary - 5 - _clock.absolute_minute)
_prepare_breach()
_guard_failure("G1", &"create_service_request", {&"facility_id": _facility_id, &"request_id": REQUEST, &"guest_ids": [GUEST]}, "A Facility assigned to a non-terminal Defense Raid cannot accept service requests.", {&"raid_id": &"p04.s5.raid"})
_clock.advance_minutes(_boundary - 1 - _clock.absolute_minute)
return _clock.absolute_minute == _boundary - 1
func _assert_idle_breach(point: Dictionary) -> void:
_expect(point[&"facility"][&"durability"] == 0 and point[&"facility"][&"state"] == "BROKEN" and point[&"facility"][&"suspension_reason"] == "DESTROYED", "idle OBJECTIVE automatically destroyed")
_expect(point[&"active_services"] == 0 and point[&"service"].is_empty() and point[&"reservations"].is_empty(), "idle breach has no services or reservations")
for request: Dictionary in point[&"requests"].values(): _expect(request.is_empty(), "idle breach no request/orphan")
for entry: Dictionary in point[&"ledger"]: _expect(entry[&"category"] != "SERVICE_SALE", "idle breach no sale")
func _assert_idle_order(_before: Dictionary, point: Dictionary) -> void:
_assert_idle_breach(point)
func _assert_in_flight(point: Dictionary) -> void:
_expect(point[&"facility"][&"durability"] == 0 and point[&"facility"][&"state"] == "BROKEN", "event destroys active facility")
_expect(point[&"service"][&"state"] == ("ACTIVE" if point[&"minute"] == _boundary else "FAILED"), "N active then N+1 failure")
func _assert_in_flight_order(before: Dictionary, point: Dictionary) -> void:
_assert_in_flight(point)
_expect(point[&"wallets"] == before[&"wallets"], "in-flight destruction zero charge")
if point[&"minute"] > _boundary: _assert_reservation(before, point, REQUEST, "RELEASED", _boundary + 1)
else: _assert_reservation(before, point, REQUEST, "ACTIVE", -1)
func _advance_paused_midnight(label: String) -> void:
if label != "recovered":
_clock.advance_one_minute()
return
_cmd(&"change_resources", {&"deltas": {&"mana": _reserve}})
_recovery[&"resume_minute"] = -1
while _clock.absolute_minute < _boundary + _duration + 20:
_clock.advance_one_minute()
if _runtime.facility_service.get_service(_service_id).state == ServiceInstance.State.COMPLETED:
_recovery[&"resume_minute"] = _clock.absolute_minute
break
_expect(_recovery[&"resume_minute"] > _boundary, "bounded new-day completion")
func _assert_paused_midnight(point: Dictionary) -> void:
_expect(point[&"service"][&"state"] == "PAUSED" and point[&"service"][&"interruption_reason"] == "RELATED_FACILITY_INACTIVE", "legitimate dependency pause across DAILY_CLOSE")
_expect(point[&"operations_enabled"] and not point[&"actual_coordinator_absent"], "real DAILY_CLOSE coordinator")
func _assert_paused_midnight_order(before: Dictionary, point: Dictionary) -> void:
if point[&"minute"] <= _boundary + 1:
_assert_paused_midnight(point)
_expect(point[&"service"][&"elapsed_minutes"] == before[&"service"][&"elapsed_minutes"], "paused elapsed unchanged")
_expect(point[&"wallets"] == before[&"wallets"], "no paused payment")
_assert_reservation(before, point, REQUEST, "ACTIVE", -1)
else:
_expect(point[&"service"][&"state"] == "COMPLETED", "new-day recovered completion")
_expect(point[&"wallets"][String(GUEST)] == before[&"wallets"][String(GUEST)] - _price, "one recovered price snapshot debit")
_assert_reservation(before, point, REQUEST, "CONSUMED", point[&"minute"])
func _advance_order(label: String) -> void:
if label == "boundary":
if _case == "S5D_IN_FLIGHT": _cmd(&"enqueue_event", {&"event_id": &"p04.s5.break", &"actor_ids": [&"player"]}, _boundary)
if _case == "S5C_DESTRUCTION_COMMAND": _cmd(&"set_facility_conditions", {&"facility_id": _facility_id, &"conditions": {&"durability": 0}}, _boundary)
if _case == "S5F_EXIT": _cmd(&"leave_facility_queue", {&"facility_id": _facility_id, &"request_id": QUEUED_REQUEST}, _boundary)
if label == "recalled":
@@ -251,6 +379,7 @@ func _advance_order(label: String) -> void:
_expect(replay.is_success() and replay.is_replay, "same midnight is a replay")
_expect(var_to_bytes(before) == var_to_bytes(_runtime.create_snapshot()), "same-minute replay changes no typed state")
_recovery[&"midnight_replay"] = replay.to_dictionary()
_replay_reference = _write("same-minute-replay", {&"before": before, &"after": _runtime.create_snapshot(), &"result": replay.to_dictionary(), &"minute": _boundary})
else:
_clock.advance_one_minute()
@@ -281,12 +410,19 @@ 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})
var staff_at_receipt: Array = []
for staff_id: StringName in _recovery.get(&"staff_ids", []):
staff_at_receipt.append(_runtime.staff_service.get_staff(staff_id).create_snapshot())
_receipts.append({&"id": id, &"minute": _clock.absolute_minute, &"phase": _observed_phase, &"entries": rows, &"staff_at_receipt": staff_at_receipt})
)
_clock.tick_phase_started.connect(func(phase: int, minute: int) -> void:
_observed_phase = SimulationKernel.TickPhase.keys()[phase]
var label: String = "phase-%d-%s" % [minute, SimulationKernel.TickPhase.keys()[phase]]
var row: Dictionary = _capture()
row[&"phase"] = SimulationKernel.TickPhase.keys()[phase]
if _case == "S5G_SHIFT_1080" and minute == 1080:
var historical: Dictionary = {SimulationKernel.TickPhase.FACILITY_COMPLETION: "first-18-00-before-facility", SimulationKernel.TickPhase.VITALS_AND_ENVIRONMENT: "first-18-00-after-facility", SimulationKernel.TickPhase.PUBLISH_SNAPSHOT: "first-18-00-after-staff"}
row[&"order_label"] = historical.get(phase, "")
_assert_phase(row)
_phases.append(_write(label, row))
)
@@ -316,6 +452,7 @@ func _capture() -> Dictionary:
var ledger: Array = []
for entry: LedgerEntry in _runtime.economy_service.get_entries(): ledger.append(entry.to_dictionary())
return {&"snapshot": snapshot, &"minute": _clock.absolute_minute,
&"order_label": ({1079: "first-before-17-59", 1080: "first-18-00-tick-complete", 1081: "first-18-01-tick-complete"}.get(_clock.absolute_minute, "") if _case == "S5G_SHIFT_1080" else ""),
&"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"},
@@ -397,7 +534,7 @@ func _writer_case() -> void:
var guard: Dictionary = _capture()
_assert_outcome(before, guard)
_points["duplicate_guard"] = _write("duplicate_guard", guard)
_branches[_case] = _write("case", {&"resource_replay": _replay_reference, &"points": _points.duplicate(true), &"phases": _phases.duplicate(true),
_branches[_case] = _write("case", {&"resource_replay": _replay_reference, &"guards": _guard_references, &"points": _points.duplicate(true), &"phases": _phases.duplicate(true),
&"commands": _write("commands", {&"submitted": _commands, &"completed_including_fixture": _results})})
func _assert_before(point: Dictionary) -> void:
@@ -554,6 +691,7 @@ func _assert_expected_phase_roster(references: Array) -> void:
var expected_pairs: Array = []
var end: int = int(_recovery[&"resume_minute"]) + 1
if _case == "S5E_MIDNIGHT": end = _boundary
if _case == "S5H_PAUSED_MIDNIGHT": end = int(_recovery[&"resume_minute"])
for minute: int in range(_boundary, end):
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]])
@@ -0,0 +1,127 @@
"""Engine-free mirror of M journal serialization; EXPECTED never accepts AFTER.
The native probe uses detached public restores. This independent derivation
binds that recorded EXPECTED to BEFORE and the fixed guard command, so copying
AFTER into EXPECTED cannot turn a mutation into evidence.
"""
import struct
MESSAGES = {
'G1': 'A Facility assigned to a non-terminal Defense Raid cannot accept service requests.',
'G2': 'A busy Facility cannot become a Defense asset.',
}
def atom(kind, value):
if kind in (4, 21):
data = value.encode()
return struct.pack('<II', kind, len(data)) + data + b'\0' * (-len(data) % 4)
if kind == 2 and not -(2**31) <= value < 2**31:
return struct.pack('<Iq', kind | 65536, value)
return struct.pack('<Ii', kind, value)
def dictionary(pairs):
return struct.pack('<II', 27, len(pairs)) + b''.join(k + v for k, v in pairs)
def strings_dict(pairs):
return dictionary([(atom(4, k), v) for k, v in pairs])
def array(rows, element=None):
header = struct.pack('<II', 28, len(rows)) if element is None else struct.pack('<III', 65564, element, len(rows))
return header + b''.join(rows)
def update(node, changes):
"""Retain all untouched typed keys, values and order, with no field masks."""
if node.kind != 27 or set(changes) - {k.value for k, _ in node.value}:
raise ValueError('journal dictionary keys')
return dictionary([(k.raw, changes.get(k.value, v.raw)) for k, v in node.value])
def expected(before, command, guard, parse, require):
require(guard in MESSAGES, 'fixed guard')
rt = before.at('systems').at('runtime')
q = rt.at('command_queue')
require(q.at('version').kind == 2 and q.at('version').value == 2, 'M queue version')
require(rt.at('next_command_id').kind == 2, 'typed next_command_id')
for name in ('pending', 'in_flight', 'processed', 'accepted'):
require(q.at(name).raw[:8] == struct.pack('<II', 65564, 27), 'M typed queue array: ' + name)
prior_ids = {}
for name in ('accepted', 'processed'):
members = q.at(name).value
require(all(r.at('command_id').kind == 2 for r in members), 'typed prior command IDs')
numbers = [r.at('command_id').value for r in members]
require(numbers == sorted(set(numbers)) and all(i > 0 for i in numbers), 'sorted unique ' + name)
prior_ids[name] = numbers
require(prior_ids['accepted'] == prior_ids['processed'], 'complete isolated prior journal')
mapping = q.at('idempotency')
require(all(k.kind == 4 and v.kind == 2 for k, v in mapping.value), 'typed idempotency mapping')
require([k.value for k, _ in mapping.value] == sorted(k.value for k, _ in mapping.value), 'sorted idempotency')
require(not q.at('pending').value and not q.at('in_flight').value, 'isolated guard queue')
require(rt.at('operations').at('enabled').value is False, 'guard operations disabled')
ident = rt.at('next_command_id').value
minute = command.at('issued_tick').value
key = command.at('idempotency_key').value
kind = 'create_service_request' if guard == 'G1' else 'register_defense_asset'
require(command.at('command_id').kind == 2 and command.at('command_id').value == ident
and command.at('execute_tick').value == minute
and command.at('priority').value == 10 and command.at('command_type').value == kind
and command.at('actor_id').value == 'player' and command.at('target_id').value == ''
and key.startswith('p04.s5.') and key not in q.at('idempotency').plain(), 'fixed guard command binding')
payload = command.at('payload').plain()
if guard == 'G1':
require(set(payload) == {'facility_id', 'request_id', 'guest_ids'}
and payload['request_id'] == 'p04.s5.request.a'
and payload['guest_ids'] == ['p04.s5.guest.a'], 'G1 payload')
else:
require(set(payload) == {'raid_id', 'asset_id', 'kind', 'max_integrity'}
and payload['raid_id'] == 'p04.s5.guard.raid' and payload['kind'] == 'OBJECTIVE'
and payload['max_integrity'] == 10000, 'G2 payload')
details = dictionary([(atom(21, 'raid_id'), atom(21, 'p04.s5.raid'))]) if guard == 'G1' else dictionary([])
result = strings_dict([
('code', atom(4, 'VALIDATION_FAILED')), ('command_id', atom(2, ident)),
('target_id', atom(4, '')), ('message', atom(4, MESSAGES[guard])),
('resolution_hints', array([], 4)), ('details', details), ('is_replay', atom(1, 0))])
accepted = q.at('accepted').value
processed = q.at('processed').value
for row in accepted:
old_key = row.at('idempotency_key')
require(old_key.kind == 4, 'accepted String key')
if old_key.value:
require(mapping.at(old_key.value).value == row.at('command_id').value, 'prior accepted/idempotency join')
require(all(r.at('command_id').value < ident for r in accepted + processed), 'prior journal IDs')
metadata = strings_dict([('command_id', atom(2, ident)), ('idempotency_key', atom(4, key))])
idem = [(k.value, v.raw) for k, v in q.at('idempotency').value] + [(key, atom(2, ident))]
queue = update(q, {'accepted': array([r.raw for r in accepted] + [metadata], 27),
'processed': array([r.raw for r in processed] + [result], 27),
'idempotency': strings_dict(sorted(idem))})
generator = rt.at('id_generator')
counters = generator.at('counters').plain()
require(all(k.kind == 4 and v.kind == 2 for k, v in generator.at('counters').value), 'typed counters')
counters['domain_event'] = counters.get('domain_event', 0) + 1
eid = 'domain_event.%012d' % counters['domain_event']
ids = update(generator, {'counters': strings_dict([(k, atom(2, v)) for k, v in sorted(counters.items())])})
event = strings_dict([('event_id', atom(4, eid)), ('event_type', atom(4, 'COMMAND_FAILED')),
('absolute_minute', atom(2, minute)), ('source_service', atom(4, 'simulation_runtime')),
('entity_ids', array([], 4)), ('payload', result), ('causation_command_id', atom(2, ident))])
stream = rt.at('domain_events')
published = stream.at('published_ids').plain()
require(eid not in published, 'new event ID')
events = update(stream, {'published_ids': array([atom(4, k) for k in sorted(published + [eid])], 4),
'recent_events': array(([r.raw for r in stream.at('recent_events').value] + [event])[-256:], 27)})
runtime = update(rt, {'next_command_id': atom(2, ident + 1), 'command_queue': queue,
'id_generator': ids, 'domain_events': events})
envelope = update(before, {'systems': update(before.at('systems'), {'runtime': runtime})})
return parse(envelope), parse(result)
def verify(record, parse, require):
before, command = record.at('before'), record.at('command')
tree, result = expected(before, command, record.at('guard').value, parse, require)
require(record.at('expected').raw == tree.raw, 'EXPECTED must independently derive from BEFORE; AFTER-copy forbidden')
require(record.at('after').raw == tree.raw, 'whole typed guard Runtime; no business or journal masks')
require(record.at('result').raw == result.raw, 'independent exact failed result')
return True
@@ -19,6 +19,9 @@ Raw, staff_check, duplicate_check = power.Raw, power.staff_check, power.duplicat
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()
GUEST, REQUEST = power.GUEST, power.REQUEST
SECOND, SECOND_REQUEST = 'p04.s5.guest.b', 'p04.s5.request.b'
@@ -73,6 +76,9 @@ def payment(before, after, minute):
sale = sales(after)
require(not sales(before) and len(sale) == 1, 'exactly one new sale')
price = scalar(before, 'inputs', 'price')
require(price == scalar(before, 'service', 'price_snapshot')
and scalar(before, 'inputs', 'duration') == scalar(before, 'service', 'duration_minutes'),
'values derived from service snapshot')
require(price > 0 and scalar(sale[0], 'amount') == price
and scalar(sale[0], 'absolute_minute') == minute
and scalar(sale[0], 'source_entity_id') == scalar(after, 'inputs', 'facility_id'),
@@ -82,6 +88,11 @@ def payment(before, after, minute):
require(scalar(after, 'service', 'state') == 'COMPLETED'
and scalar(after, 'service', 'completed_at') == minute, 'completed before payment')
runtime = field(after, 'snapshot', 'systems', 'runtime')
history = [r for r in rows(runtime, 'facilities', 'service_history')
if scalar(r, 'service_id') == scalar(after, 'service', 'service_id')]
require(len(history) == 1 and history[0].raw == field(after, 'service').raw, 'completed service joins typed Runtime')
require(sum(r.raw == sale[0].raw for r in rows(runtime, 'economy', 'entries')) == 1,
'sale joins typed Runtime ledger once')
key = 'service.payment.' + scalar(after, 'service', 'service_id')
idem = [r for r in rows(runtime, 'economy', 'idempotency') if scalar(r, 'key') == key]
require(len(idem) == 1 and scalar(idem[0], 'transaction_id') == scalar(sale[0], 'transaction_id'),
@@ -106,7 +117,7 @@ def destruction_command(points, phases):
return {'destruction_stop': {'charges': 0}, 'command_destruction_before_completion': True}
def destruction_raid(points, phases):
def destruction_raid_r40(points, phases):
before, end = points['before'], points['held']
n = scalar(before, 'inputs', 'boundary')
pre = phase(phases, 'INCIDENTS_AND_EVENTS', n)
@@ -127,6 +138,138 @@ def destruction_raid(points, phases):
return {'raid_sale_before_destruction': True, 'raid_unfinished_release': True}
def destruction_raid(points, phases):
before = points['before']
n = scalar(before, 'inputs', 'boundary')
due = rows(before, 'inputs', 'recovery', 'due_rounds')
require(len(due) == 1 and scalar(due[0], 'earliest_minute') == n
and scalar(due[0], 'raid_id') == 'p04.s5.raid', 'idle OBJECTIVE due exactly N')
pre = phase(phases, 'INCIDENTS_AND_EVENTS', n)
require(scalar(pre, 'facility', 'durability') > 0, 'idle breach not before incidents')
for point in (phase(phases, 'FACILITY_QUEUES', n), points['boundary'], points['held']):
require(scalar(point, 'facility', 'durability') == 0 and scalar(point, 'facility', 'state') == 'BROKEN'
and scalar(point, 'facility', 'suspension_reason') == 'DESTROYED', 'automatic idle destruction in INCIDENTS_AND_EVENTS')
require(not rows(point, 'reservations') and field(point, 'service').plain() == {}
and scalar(point, 'active_services') == 0
and not rows(point, 'snapshot', 'systems', 'runtime', 'facilities', 'requests')
and all(v.plain() == {} for _, v in field(point, 'requests').value), 'idle no requests/reservations/orphans')
require(not any(scalar(r, 'category') == 'SERVICE_SALE' for r in rows(point, 'ledger')),
'idle raid zero SERVICE_SALE')
return {'idle_objective_breach': True, 'destruction_stop': {'charges': 0}}
def destruction_in_flight(points, phases):
before, boundary, end = points['before'], points['boundary'], points['held']
n = scalar(before, 'inputs', 'boundary')
pre = phase(phases, 'INCIDENTS_AND_EVENTS', n)
post = phase(phases, 'FACILITY_QUEUES', n)
require(scalar(pre, 'facility', 'durability') > 0 and scalar(pre, 'service', 'state') == 'ACTIVE'
and scalar(pre, 'service', 'elapsed_minutes') < scalar(pre, 'service', 'duration_minutes'),
'in-flight completion phase precedes destruction')
require(scalar(post, 'facility', 'durability') == 0 and scalar(post, 'facility', 'state') == 'BROKEN'
and scalar(boundary, 'service', 'state') == 'ACTIVE', 'event breaks active service at N')
require(scalar(end, 'minute') == n + 1 and scalar(end, 'service', 'state') == 'FAILED'
and scalar(end, 'service', 'failure_reason') == 'BROKEN', 'N+1 in-flight failure')
for p in (boundary, end):
require(not sales(p) and field(p, 'wallets').raw == field(before, 'wallets').raw, 'in-flight zero charge')
release(before, end, REQUEST, n + 1)
return {'in_flight_destruction': True, 'destruction_stop': {'charges': 0}}
def shift_completion(points, phases):
before, end, held = points['before'], points['boundary'], points['held']
require(scalar(before, 'inputs', 'boundary') == 1080, 'DAY end exactly 1080')
require(scalar(before, 'minute') == 1079 and scalar(before, 'service', 'state') == 'ACTIVE'
and scalar(before, 'service', 'started_at') + scalar(before, 'service', 'duration_minutes') == 1080
and scalar(before, 'service', 'elapsed_minutes') == scalar(before, 'service', 'duration_minutes') - 1,
'natural snapshot duration aligns completion to 1080')
for point, label in [(before, 'first-before-17-59'), (end, 'first-18-00-tick-complete'),
(held, 'first-18-01-tick-complete'),
(phase(phases, 'FACILITY_COMPLETION', 1080), 'first-18-00-before-facility'),
(phase(phases, 'VITALS_AND_ENVIRONMENT', 1080), 'first-18-00-after-facility'),
(phase(phases, 'PUBLISH_SNAPSHOT', 1080), 'first-18-00-after-staff')]:
require(scalar(point, 'order_label') == label, 'historical shift observation label: ' + label)
require(not sales(phase(phases, 'FACILITY_COMPLETION', 1080)), 'not charged before FACILITY_COMPLETION')
sale = payment(before, phase(phases, 'VITALS_AND_ENVIRONMENT', 1080), 1080)
payment(before, end, 1080)
payment(before, held, 1080)
require(scalar(held, 'minute') == 1081 and field(end, 'service').raw == field(held, 'service').raw,
'1081 no second completion')
receipts = [r for r in rows(end, 'receipts') if scalar(r, 'id') == scalar(sale, 'transaction_id')]
require(len(receipts) == 1 and scalar(receipts[0], 'phase') == 'FACILITY_COMPLETION', 'sale before handover')
staff = rows(receipts[0], 'staff_at_receipt')
ids = field(before, 'service', 'staff_ids').plain()
require(ids and [scalar(r, 'staff_id') for r in staff] == ids, 'DAY staff captured at receipt')
shifts = rows(before, 'snapshot', 'systems', 'runtime', 'staff', 'shifts')
final_shifts = rows(end, 'snapshot', 'systems', 'runtime', 'staff', 'shifts')
final_staff = rows(end, 'snapshot', 'systems', 'runtime', 'staff', 'staff')
for worker in staff:
ident = scalar(worker, 'staff_id')
shift = [s for s in shifts if scalar(s, 'shift_instance_id') == scalar(worker, 'shift_id')]
require(len(shift) == 1 and scalar(shift[0], 'end_at') == 1080 and scalar(shift[0], 'template_id') == 'DAY'
and scalar(worker, 'state') != 'OFF_DUTY', 'DAY not NIGHT staff before handover')
after = [s for s in final_shifts if scalar(s, 'shift_instance_id') == scalar(worker, 'shift_id')]
require(len(after) == 1 and scalar(after[0], 'actual_ended_at') == scalar(after[0], 'end_at') == 1080,
'DAY shift ended after receipt')
workers = [s for s in final_staff if scalar(s, 'staff_id') == ident]
require(len(workers) == 1 and scalar(workers[0], 'state') == 'OFF_DUTY', 'DAY now OFF_DUTY')
return {'shift_completion': {'minute': 1080, 'completions': 1, 'charges': 1, 'completion_before_shift': True}}
def paused_midnight(points, phases):
before, end = points['before'], points['recovered']
n = scalar(before, 'inputs', 'boundary')
require(n > 0 and n % 1440 == 0, 'paused midnight multiple')
for p in (before, phase(phases, 'TIME_BOUNDARIES', n), phase(phases, 'MANA', n), points['boundary'], points['held']):
require(scalar(p, 'service', 'state') == 'PAUSED'
and scalar(p, 'service', 'interruption_reason') == 'RELATED_FACILITY_INACTIVE'
and scalar(p, 'service', 'elapsed_minutes') == scalar(before, 'service', 'elapsed_minutes'),
'legitimate pause unchanged through DAILY_CLOSE')
require(field(p, 'reservations').raw == field(before, 'reservations').raw
and field(p, 'requests', REQUEST).raw == field(before, 'requests', REQUEST).raw,
'identical active reservations and preserved request')
require(not sales(p) and field(p, 'wallets').raw == field(before, 'wallets').raw, 'no paused sale')
active = rows(before, 'reservations')
require(len(active) == 1 and scalar(active[0], 'state') == 'ACTIVE', 'one active meal reservation')
post = phase(phases, 'MANA', n)
summaries = rows(post, 'snapshot', 'systems', 'runtime', 'operations', 'coordinator', 'day_summaries')
summaries = [s for s in summaries if scalar(s, 'closed_at') == n]
require(len(summaries) == 1, 'one DAILY_CLOSE during TIME_BOUNDARIES')
settlement_rows = [r for r in rows(post, 'ledger') if scalar(r, 'absolute_minute') == n]
upkeep = [r for r in settlement_rows if scalar(r, 'category') == 'MAINTENANCE_PAYMENT']
require(upkeep and len({scalar(r, 'transaction_id') for r in upkeep}) == 1, 'one paused upkeep settlement')
require(len({scalar(r, 'source_entity_id') for r in upkeep}) == len(upkeep), 'one upkeep row per owned facility')
for row in upkeep:
accrual = [r for r in rows(post, 'ledger') if scalar(r, 'category') == 'MAINTENANCE_ACCRUAL'
and scalar(r, 'transaction_id') == scalar(row, 'transaction_id')
and scalar(r, 'source_entity_id') == scalar(row, 'source_entity_id')
and scalar(r, 'amount') == scalar(row, 'amount') and scalar(r, 'absolute_minute') == n - 1]
require(len(accrual) == 1, 'paused upkeep accrual joined once')
wages = [r for r in settlement_rows if scalar(r, 'category') == 'WAGE']
require(len(wages) == 1, 'one paused payroll transaction')
payroll = [r for r in rows(post, 'snapshot', 'systems', 'runtime', 'staff', 'payroll_settlements')
if scalar(r, 'settlement_id') == scalar(wages[0], 'source_entity_id')]
require(len(payroll) == 1 and scalar(payroll[0], 'day') == n // 1440, 'paused payroll day/ledger join')
paid = [r for r in rows(payroll[0], 'rows') if scalar(r, 'payment') > 0]
require(paid and len({scalar(r, 'staff_id') for r in paid}) == len(paid)
and sum(scalar(r, 'payment') for r in paid) == scalar(wages[0], 'amount'), 'paused payroll paid once')
for p in (points['boundary'], points['held'], end):
require([r.raw for r in rows(p, 'ledger') if scalar(r, 'absolute_minute') == n] == [r.raw for r in settlement_rows],
'no double settlement or midnight sale')
current = [s for s in rows(p, 'snapshot', 'systems', 'runtime', 'operations', 'coordinator', 'day_summaries')
if scalar(s, 'closed_at') == n]
require([s.raw for s in current] == [s.raw for s in summaries], 'settlement summary posted once')
completion = scalar(end, 'service', 'completed_at')
require(n < completion < n + 1440, 'recovery in new day')
payment(before, end, completion)
consumed = rows(end, 'reservations')
require(len(consumed) == 1 and scalar(consumed[0], 'reservation_id') == scalar(active[0], 'reservation_id')
and scalar(consumed[0], 'state') == 'CONSUMED' and field(end, 'requests', REQUEST).plain() == {},
'consumed original reservation no orphan')
return {'paused_midnight': {'orphan_reservations': 0, 'crossed_midnight_while_paused': True,
'stopped_charges': 0, 'completions': 1, 'charges': 1}}
def midnight_day(points, phases):
before, end, replay = points['before'], points['boundary'], points['recalled']
n = scalar(before, 'inputs', 'boundary')
@@ -190,7 +333,8 @@ def exit_order(points, phases):
DERIVERS = {'S5C_DESTRUCTION_COMMAND': destruction_command, 'S5D_DESTRUCTION_RAID': destruction_raid,
'S5E_MIDNIGHT': midnight_day, 'S5F_EXIT': exit_order}
'S5D_IN_FLIGHT': destruction_in_flight, 'S5G_SHIFT_1080': shift_completion,
'S5H_PAUSED_MIDNIGHT': paused_midnight, 'S5E_MIDNIGHT': midnight_day, 'S5F_EXIT': exit_order}
def derive(root, writer_sha, reader_sha):
@@ -209,8 +353,31 @@ def derive(root, writer_sha, reader_sha):
phases = [raw.typed(r) for r in branch['phases']]
raw.typed(branch['commands'])
for p in points.values():
staff_check(p, field(p, 'inputs', 'recovery'))
if case not in ('S5D_DESTRUCTION_RAID', 'S5G_SHIFT_1080'):
staff_check(p, field(p, 'inputs', 'recovery'))
if case == 'S5G_SHIFT_1080':
staff_check(points['before'], field(points['before'], 'inputs', 'recovery'))
result[case] = function(points, phases)
expected_guards = {'G1'} if case == 'S5D_DESTRUCTION_RAID' else {'G2'} if case == 'S5D_IN_FLIGHT' else set()
require(set(branch['guards']) == expected_guards, 'complete fixed guard roster')
for label, ref in branch['guards'].items():
guard = raw.typed(ref)
require(scalar(guard, 'guard') == label, 'guard label binding')
facility_id = scalar(points['before'], 'inputs', 'facility_id')
payload_field = 'facility_id' if label == 'G1' else 'asset_id'
require(scalar(guard, 'command', 'payload', payload_field) == facility_id, 'guard binds case facility')
facilities = rows(guard, 'before', 'systems', 'runtime', 'facilities', 'instances')
facility = [f for f in facilities if scalar(f, 'instance_id') == facility_id]
require(len(facility) == 1, 'guard facility exists in BEFORE')
if label == 'G2':
require(rows(facility[0], 'active_services'), 'G2 independently busy BEFORE')
else:
raids = rows(guard, 'before', 'systems', 'runtime', 'defense', 'raids')
raid = [r for r in raids if scalar(r, 'raid_id') == 'p04.s5.raid']
require(len(raid) == 1 and scalar(raid[0], 'state') in ('PREPARING', 'ACTIVE', 'BETWEEN_WAVES')
and any(scalar(asset, 'asset_id') == facility_id for asset in rows(raid[0], 'assets')),
'G1 independently non-terminal Defense ownership')
result[case][label] = guard_oracle.verify(guard, series.variant, require)
for label, ref in replay['restored'].items():
require(field(raw.typed(ref), 'snapshot').raw == field(points[label], 'snapshot').raw,
'whole typed formal restore')
@@ -224,6 +391,12 @@ def derive(root, writer_sha, reader_sha):
require([raw.typed(r).raw for r in replay['phases']] == expected_phases, 'complete phase replay')
result[case]['formal_restore_verified'] = True
if case == 'S5E_MIDNIGHT':
for reference in (branch['resource_replay'], replay['resource_replay']):
record = raw.typed(reference)
require(field(record, 'before').raw == field(record, 'after').raw == field(points['boundary'], 'snapshot').raw
and scalar(record, 'result', 'is_replay') is True and scalar(record, 'result', 'code') == 'OK'
and scalar(record, 'minute') == n, 'public advance_to after formal boundary restore')
result[case]['same_minute_replay'] = {'completions': 1, 'charges': 1, 'duplicate_generations': 0, 'same_minute_replayed': True}
result[case]['save_restore'] = {'settlements': 1, 'duplicate_payments': 0, 'formal_save_restored': True}
return {'cases': result, 'dependency_sha256': DEPENDENCIES, 'raw_sha256': raw.hashes,
'pending': ['patience_release', 'paused_midnight'], 'formal_acceptance': False}
'pending': ['patience_release'], 'formal_acceptance': False}
@@ -13,13 +13,110 @@ mutation = a.module('order_typed_mutation', Path(__file__).with_name('s5_power_a
BUILD = Path('/Users/korizatou114/Projects/TheTree-managed-worktrees/p04-01/.runtime/P04-01/build')
def guard_mutations(record):
"""All typed AFTER nodes are tested, including every changed journal field.
Also copy each corrupted AFTER into EXPECTED: the independent derivation
must still reject it. No native evidence is produced by these controls.
"""
oracle = a.guard_oracle
a.require(oracle.verify(record, a.series.variant, a.require), 'guard control prerequisite')
checks = []
after = record.at('after')
def visit(node, path):
replacements = []
if node.kind in (4, 21):
replacements = [('value', oracle.atom(node.kind, node.value + '.mutated')),
('string-type', oracle.atom(21 if node.kind == 4 else 4, node.value))]
elif node.kind == 2:
replacements = [('value', oracle.atom(2, node.value + 1)),
('int-float', struct.pack('<If', 3, float(node.value)))]
elif node.kind == 1:
replacements = [('bool', oracle.atom(1, not node.value))]
elif node.kind == 28:
start = 12 if node.raw[:4] == struct.pack('<I', 65564) else 8
if node.value:
replacements.append(('extra-row', node.raw[:start-4] + struct.pack('<I', len(node.value)+1)
+ node.raw[start:] + node.value[-1].raw))
if len(node.value) > 1:
replacements.append(('unsorted', node.raw[:start] + b''.join(r.raw for r in reversed(node.value))))
for i, child in enumerate(node.value):
visit(child, path + '/' + str(i))
elif node.kind == 27:
if len(node.value) > 1:
replacements.append(('unsorted', oracle.dictionary([(k.raw, v.raw) for k, v in reversed(node.value)])))
for key, child in node.value:
visit(key, path + '/key:' + str(key.value))
visit(child, path + '/' + str(key.value))
for label, encoded in replacements:
changed_after = mutation.replace(after, node, encoded)
for copied in (False, True):
changed_record = mutation.replace(record, after, changed_after)
try:
changed = a.series.variant(changed_record)
if copied:
changed_record = mutation.replace(changed, changed.at('expected'), changed_after)
oracle.verify(a.series.variant(changed_record), a.series.variant, a.require)
except ValueError:
checks.append(path + ':' + label + (':AFTER-copy' if copied else ''))
continue
raise ValueError('guard mutation accepted: ' + path + ':' + label)
visit(after, 'after')
return checks
def pure_controls():
"""Source-shaped synthetic serializer units, never Writer/Reader positives."""
o = a.guard_oracle
atom, d, arr = o.atom, o.strings_dict, o.array
prior = lambda ident: d([('code', atom(4, 'OK')), ('command_id', atom(2, ident)),
('target_id', atom(4, '')), ('message', atom(4, '')),
('resolution_hints', arr([], 4)), ('details', d([])), ('is_replay', atom(1, 0))])
q = d([('version', atom(2, 2)), ('pending', arr([], 27)), ('in_flight', arr([], 27)),
('processed', arr([prior(1), prior(2)], 27)),
('idempotency', d([('a', atom(2, 1)), ('b', atom(2, 2))])),
('accepted', arr([d([('command_id', atom(2, i)), ('idempotency_key', atom(4, k))])
for i, k in [(1, 'a'), (2, 'b')]], 27))])
runtime = d([('next_command_id', atom(2, 3)), ('command_queue', q),
('id_generator', d([('version', atom(2, 1)), ('counters', d([('domain_event', atom(2, 2))]))])),
('domain_events', d([('version', atom(2, 1)), ('published_ids', arr([atom(4, 'domain_event.000000000001'), atom(4, 'domain_event.000000000002')], 4)), ('recent_events', arr([], 27))])),
('operations', d([('enabled', atom(1, 0))])),
('business', d([('wallet', atom(2, 100)), ('reservations', arr([], 27))]))])
before = a.series.variant(d([('systems', d([('runtime', runtime)]))]))
results = {}
for guard in ('G1', 'G2'):
payload = (o.dictionary([(atom(21, 'facility_id'), atom(21, 'facility.1')),
(atom(21, 'request_id'), atom(21, a.REQUEST)),
(atom(21, 'guest_ids'), arr([atom(21, a.GUEST)]))]) if guard == 'G1' else
o.dictionary([(atom(21, 'raid_id'), atom(21, 'p04.s5.guard.raid')),
(atom(21, 'asset_id'), atom(21, 'facility.1')),
(atom(21, 'kind'), atom(21, 'OBJECTIVE')),
(atom(21, 'max_integrity'), atom(2, 10000))]))
command = a.series.variant(d([('command_id', atom(2, 3)), ('issued_tick', atom(2, 959)),
('execute_tick', atom(2, 959)), ('priority', atom(2, 10)),
('command_type', atom(4, 'create_service_request' if guard == 'G1' else 'register_defense_asset')),
('actor_id', atom(4, 'player')), ('target_id', atom(4, '')),
('payload', payload), ('idempotency_key', atom(4, 'p04.s5.unit.3'))]))
expected, result = o.expected(before, command, guard, a.series.variant, a.require)
record = a.series.variant(d([('before', before.raw), ('command', command.raw), ('guard', atom(4, guard)),
('expected', expected.raw), ('after', expected.raw), ('result', result.raw)]))
results[guard] = guard_mutations(record)
return {'synthetic_serializer_controls_only': True, 'negative_controls': results, 'formal_acceptance': False}
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--raw-root', type=Path, required=True)
parser.add_argument('--writer-sha256', required=True)
parser.add_argument('--reader-sha256', required=True)
parser.add_argument('--scratch', type=Path, required=True)
parser.add_argument('--pure-only', action='store_true')
parser.add_argument('--raw-root', type=Path)
parser.add_argument('--writer-sha256')
parser.add_argument('--reader-sha256')
parser.add_argument('--scratch', type=Path)
args = parser.parse_args()
if args.pure_only:
print(json.dumps(pure_controls(), sort_keys=True))
return
a.require(all((args.raw_root, args.writer_sha256, args.reader_sha256, args.scratch)), 'explicit fresh raw arguments')
scratch = args.scratch
a.require(scratch.is_absolute() and not scratch.exists() and not scratch.is_symlink(), 'explicit absent scratch')
a.require(scratch.parent.resolve(strict=True).is_relative_to(BUILD.resolve(strict=True)), 'scratch inside BUILD')
@@ -66,7 +163,11 @@ def main():
raid = 'S5D_DESTRUCTION_RAID'
points, phases = cases[raid]
pre = a.phase(phases, 'INCIDENTS_AND_EVENTS', a.scalar(points['before'], 'inputs', 'boundary'))
negative('raid-sale-missing', raid, pre, a.field(a.sales(pre)[0], 'category'), mutation.scalar(4, 'REMOVED_SALE'))
negative('idle-breach-too-early', raid, pre, a.field(pre, 'facility', 'durability'), mutation.scalar(2, 0))
for case in ('S5D_DESTRUCTION_RAID', 'S5D_IN_FLIGHT'):
branch = raw.reference(writer['branches'][case])
for label, reference in branch['guards'].items():
checks.extend(label + ':' + name for name in guard_mutations(raw.typed(reference)))
command = 'S5C_DESTRUCTION_COMMAND'
points, phases = cases[command]
end = points['held']
@@ -83,6 +184,37 @@ def main():
pre = a.phase(phases, 'FACILITY_COMPLETION', n)
reservation = next(r for r in a.rows(pre, 'reservations') if a.scalar(r, 'requester_id') == a.SECOND_REQUEST)
negative('command-exit-after-start', exit_case, pre, a.field(reservation, 'terminal_at'), mutation.scalar(2, n + 1))
shift = 'S5G_SHIFT_1080'
points, phases = cases[shift]
end = points['boundary']
receipt = next(r for r in a.rows(end, 'receipts') if a.scalar(r, 'id') == a.scalar(a.sales(end)[0], 'transaction_id'))
negative('sale-after-handover', shift, end, a.field(receipt, 'phase'), mutation.scalar(4, 'AI_DECISIONS'))
staff = a.field(receipt, 'staff_at_receipt')
negative('empty-staff-at-receipt', shift, end, staff, a.guard_oracle.array([]))
negative('night-staff-at-receipt', shift, end, a.field(staff.value[0], 'shift_id'), mutation.scalar(4, 'NIGHT'))
paused = 'S5H_PAUSED_MIDNIGHT'
points, phases = cases[paused]
end = points['boundary']
reservation = a.rows(end, 'reservations')[0]
negative('reservation-released-at-midnight', paused, end, a.field(reservation, 'state'), mutation.scalar(4, 'RELEASED'))
negative('reservation-changed-at-midnight', paused, end, a.field(reservation, 'quantity'), mutation.scalar(2, a.scalar(reservation, 'quantity') + 1))
negative('paused-elapsed-typed-different', paused, end, a.field(end, 'service', 'elapsed_minutes'), struct.pack('<If', 3, float(a.scalar(end, 'service', 'elapsed_minutes'))))
ledger = a.field(end, 'ledger')
sale = a.sales(points['recovered'])[0]
start = 12 if ledger.raw[:4] == struct.pack('<I', 65564) else 8
def appended(row):
return ledger.raw[:start-4] + struct.pack('<I', len(ledger.value)+1) + ledger.raw[start:] + row.raw
negative('sale-while-paused', paused, end, ledger, appended(sale))
settlement = next(r for r in ledger.value if a.scalar(r, 'absolute_minute') == a.scalar(end, 'inputs', 'boundary'))
negative('double-paused-settlement', paused, end, ledger, appended(settlement))
points, phases = cases[midnight]
replay = points['recalled']
counter = a.field(replay, 'snapshot', 'systems', 'runtime', 'next_command_id')
negative('replay-extra-id', midnight, replay, counter, mutation.scalar(2, counter.value + 1))
negative('replay-json-equal-type-difference', midnight, replay, counter, struct.pack('<If', 3, float(counter.value)))
ledger = a.field(replay, 'snapshot', 'systems', 'runtime', 'economy', 'entries')
start = 12 if ledger.raw[:4] == struct.pack('<I', 65564) else 8
negative('replay-extra-row', midnight, replay, ledger, ledger.raw[:start-4] + struct.pack('<I', len(ledger.value)+1) + ledger.raw[start:] + ledger.value[-1].raw)
print(json.dumps({'positive_cases': list(positive['cases']), 'negative_controls': checks,
'formal_acceptance': False}, sort_keys=True))
@@ -100,9 +100,10 @@ def derive(root, writer_sha, reader_sha):
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)
require(writer["pid"] != reader["pid"] and writer["profile"] != reader["profile"], "independent reader required")
expected = set(CASES) | {"S5C_DESTRUCTION_COMMAND", "S5D_DESTRUCTION_RAID", "S5E_MIDNIGHT", "S5F_EXIT"}
expected = set(CASES) | {"S5C_DESTRUCTION_COMMAND", "S5D_DESTRUCTION_RAID", "S5D_IN_FLIGHT", "S5E_MIDNIGHT", "S5F_EXIT", "S5G_SHIFT_1080", "S5H_PAUSED_MIDNIGHT"}
historical_roster = set(CASES) | {"S5C_DESTRUCTION_COMMAND", "S5D_DESTRUCTION_RAID", "S5E_MIDNIGHT", "S5F_EXIT"}
require(set(writer["branches"]) == set(reader["branches"]) and
set(writer["branches"]) in (set(CASES), expected), "exact pair or full case table roster")
set(writer["branches"]) in (set(CASES), historical_roster, expected), "exact pair or full case table roster")
output = {}
for case in CASES:
branch = raw.reference(writer["branches"][case])