Preserve reviewed current phase diagnostic and correct P23-02 bottleneck scope
This commit is contained in:
@@ -1,5 +1,11 @@
|
||||
# 原本全実装に向けた作業計画 2026年10月改訂
|
||||
|
||||
## 現在版のフェーズ診断 r338-r02 / r339
|
||||
|
||||
r338-r02で現在未選定r333/library334の包含診断1回を独立有限受理。17/0、after647全11487732bytes原oracle一致、stage/source/default保持。enum再照合により旧phase3は建設・4は物流・5は施設完了と訂正。現在包含construction118776us/crosslinks118334us、logistics88107us/tick87311us、Guest候補投影564197us、publish76085us。次の修正対象は整合検証と物流実行。施設決済0calls・在庫期限348usを根拠なく優先しない。純CPU・改善比較・性能受入・採用・単位完成ではない。 正式9/着手19/予定60、30パッケージ/88成果、部分点なし、原9横断8すべて未受入。Windows C08/X8だけblock、手動操作延期非免除。
|
||||
|
||||
詳細:[CURRENT_PHASE_DIAGNOSTIC_R338_R339.md](execution/CURRENT_PHASE_DIAGNOSTIC_R338_R339.md)
|
||||
|
||||
## P23-02 現着手・次に閉じる1件(r337、2026-10-12)
|
||||
|
||||
P23-02着手中。制作r32と選定済み実装親r274/library275は保持。最新未選定・未採用候補r333/library334は、親r326の在庫入力キー整列と経路コピーだけをnative化。未捕捉std確保例外をビルド前に修復。bridge1/link1、SDKcompile0、既存stage再利用。局所4工程404/0、Runtime150候補105808bytes・評価後11411840bytes原golden全文一致。S6 24/0、両whole15/0、after647全11487732bytes原oracle全文一致を独立有限受理。単一隣接観測1037100→1010883us(約2.5279%短縮)だが約1.01秒停止が残り安定性能・50ms/P95/D10は未受入。r204再構築は既非採用のため再実装なし。原9横断8はすべて未受入、Windows C08/X8のみblock、手動Ctrl保持wheel/左ボタン保持dragは延期・未達・非免除。正式9/着手19/予定60、30パッケージ/88成果、部分点なし、今回正式完了追加0。
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# P00〜P03 進捗台帳への証拠統合
|
||||
|
||||
## 現在版のフェーズ診断 r338-r02 / r339
|
||||
|
||||
r338-r02で現在未選定r333/library334の包含診断1回を独立有限受理。17/0、after647全11487732bytes原oracle一致、stage/source/default保持。enum再照合により旧phase3は建設・4は物流・5は施設完了と訂正。現在包含construction118776us/crosslinks118334us、logistics88107us/tick87311us、Guest候補投影564197us、publish76085us。次の修正対象は整合検証と物流実行。施設決済0calls・在庫期限348usを根拠なく優先しない。純CPU・改善比較・性能受入・採用・単位完成ではない。 正式9/着手19/予定60、30パッケージ/88成果、部分点なし、原9横断8すべて未受入。Windows C08/X8だけblock、手動操作延期非免除。
|
||||
|
||||
詳細:[CURRENT_PHASE_DIAGNOSTIC_R338_R339.md](execution/CURRENT_PHASE_DIAGNOSTIC_R338_R339.md)
|
||||
|
||||
## P23-02 現着手・次に閉じる1件(r337、2026-10-12)
|
||||
|
||||
P23-02着手中。制作r32と選定済み実装親r274/library275は保持。最新未選定・未採用候補r333/library334は、親r326の在庫入力キー整列と経路コピーだけをnative化。未捕捉std確保例外をビルド前に修復。bridge1/link1、SDKcompile0、既存stage再利用。局所4工程404/0、Runtime150候補105808bytes・評価後11411840bytes原golden全文一致。S6 24/0、両whole15/0、after647全11487732bytes原oracle全文一致を独立有限受理。単一隣接観測1037100→1010883us(約2.5279%短縮)だが約1.01秒停止が残り安定性能・50ms/P95/D10は未受入。r204再構築は既非採用のため再実装なし。原9横断8はすべて未受入、Windows C08/X8のみblock、手動Ctrl保持wheel/左ボタン保持dragは延期・未達・非免除。正式9/着手19/予定60、30パッケージ/88成果、部分点なし、今回正式完了追加0。
|
||||
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
extends "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-build-preview-monitor-compressed-r06.gd"
|
||||
# One instrumented current r333/library334 tick; nested inclusive timing only.
|
||||
func run() -> void:
|
||||
output = OS.get_environment("THE_TREE_RUNTIME_MONITOR_OUTPUT")
|
||||
var input_path := OS.get_environment("THE_TREE_REPLAY_SNAPSHOT")
|
||||
var candidate := OS.get_environment("THE_TREE_PAIRED_CANDIDATE")
|
||||
if not output.is_absolute_path() or not input_path.is_absolute_path() or candidate != "r333-diagnostic": quit(98); return
|
||||
var original := FileAccess.get_file_as_bytes(input_path).decompress(11411840, FileAccess.COMPRESSION_ZSTD)
|
||||
var initial: Dictionary = bytes_to_var(original)
|
||||
runtime = root.get_node("SimulationRuntime")
|
||||
clock = root.get_node("GameClock")
|
||||
runtime.initialize(clock, root.get_node("GameState"), int(initial[&"systems"][&"runtime"][&"world_seed"]))
|
||||
check(runtime.restore_snapshot(initial), "fixed646 public restore")
|
||||
check(var_to_bytes(runtime.create_snapshot()) == original, "complete input bytes identical")
|
||||
check(clock.absolute_minute == 646 and clock.paused and clock.speed == 1, "same paused646 speed1")
|
||||
var path_listeners: Array = runtime.path_service.get_signal_connection_list(&"path_query_measured")
|
||||
check(path_listeners.size() == 1 and path_listeners[0]["callable"] == Callable(runtime, "_on_path_query_measured") and int(path_listeners[0]["flags"]) == 0, "only builtin path listener")
|
||||
check(clock.performance_budget.get_signal_connection_list(&"budget_exceeded").is_empty(), "no external budget listener")
|
||||
check(clock.get_signal_connection_list(&"tick_phase_started").is_empty() and clock.get_signal_connection_list(&"tick_completed").is_empty(), "no phase or completion instrumentation")
|
||||
check(runtime.path_service.cache_hits == 0 and runtime.path_service.cache_misses == 0 and runtime.path_service.cached_path_count() == 0, "same cold derived cache")
|
||||
check(runtime.path_service._query_batch.is_empty() and runtime.path_service._guest_tree_workspace.is_empty() and runtime.path_service._guest_step_connector_memo.is_empty(), "same cold tree/native-edge/step workspace")
|
||||
check(runtime._guest_access_batch_can_select(), "both candidates active fast guard")
|
||||
check(runtime.path_service.get_script().get_source_code().sha256_text() == OS.get_environment("THE_TREE_EXPECTED_PATH_SHA") and FileAccess.get_sha256("res://scripts/core/performance_budget.gd") == OS.get_environment("THE_TREE_EXPECTED_BUDGET_SHA"), "actual loaded original Path and same candidate Budget sources")
|
||||
var declared: Dictionary = {"runtime": ["_advance_construction", "_preflight_proxy_completions", "_validate_infrastructure_crosslinks", "_advance_inventory_and_logistics", "_advance_facilities", "_advance_staff_ai", "_advance_guest_ai_decisions", "_project_guest_candidates", "_decide_guest_with_log", "_publish_snapshot", "_execute_create_logistics_request", "_validate_service_start", "_complete_service_transaction", "_apply_service_transaction"], "inventory": ["process_expired", "create_snapshot", "_find_stack", "reserve_item"], "facility": ["advance_one_minute", "refresh_operating_dependencies", "start_next_service", "_complete_service"], "supply": ["advance_auto_purchases", "ensure_deliveries", "_connection_distance", "_purchase_paid"], "logistics": ["tick"], "kitchen": ["advance_one_minute"], "kernel_phases": ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]}
|
||||
var targets: Dictionary = {"runtime":runtime, "inventory":runtime.inventory_service, "facility":runtime.facility_service, "supply":runtime.supply_management, "logistics":runtime.supply_logistics, "kitchen":runtime.kitchen_production, "kernel_phases":clock}
|
||||
for group: String in declared:
|
||||
targets[group]._p23r338_metrics.clear()
|
||||
for key: String in declared[group]: targets[group]._p23r338_metrics[key] = {"calls":0,"inclusive_us":0,"max_us":0}
|
||||
var started := Time.get_ticks_usec()
|
||||
clock.advance_minutes(1)
|
||||
var elapsed := Time.get_ticks_usec() - started
|
||||
var metrics: Dictionary = {}
|
||||
for group: String in declared: metrics[group] = targets[group]._p23r338_metrics.duplicate(true)
|
||||
check(clock.absolute_minute == 647 and clock.paused, "tick returns at paused647")
|
||||
var after: Dictionary = runtime.create_snapshot()
|
||||
var oracle := FileAccess.get_file_as_bytes(OS.get_environment("THE_TREE_CANDIDATE_ORACLE")).decompress(11487732, FileAccess.COMPRESSION_ZSTD)
|
||||
check(var_to_bytes(after) == oracle, "complete after647 equals pinned r32 oracle")
|
||||
var after_pin := typed("after647", after)
|
||||
check(after_pin["uncompressed_sha256"] == "9df3c1b6f65dfd8be944cd5cab8c631f7533530dfef3820d9fa5d74a5b1ac30f", "complete output digest identical")
|
||||
var metrics_valid := true
|
||||
for group: String in declared:
|
||||
metrics_valid = metrics_valid and metrics[group].size() == declared[group].size()
|
||||
for key: String in declared[group]:
|
||||
var row: Dictionary = metrics[group][key]
|
||||
metrics_valid = metrics_valid and int(row["calls"]) >= 0 and int(row["inclusive_us"]) >= int(row["max_us"]) and int(row["max_us"]) >= 0
|
||||
if int(row["calls"]) == 0: metrics_valid = metrics_valid and int(row["inclusive_us"]) == 0 and int(row["max_us"]) == 0
|
||||
for key: String in declared["kernel_phases"]: metrics_valid = metrics_valid and int(metrics["kernel_phases"][key]["calls"]) == 1
|
||||
check(metrics_valid, "finite nested metric schema and one call per kernel phase")
|
||||
var metrics_pin := typed("metrics",metrics)
|
||||
var decoded := FileAccess.open(output.path_join("metrics.json"),FileAccess.WRITE)
|
||||
if decoded == null: quit(98); return
|
||||
decoded.store_string(JSON.stringify(metrics,"\t")); decoded.close()
|
||||
var report := {"plan_id":"P23-02", "candidate":candidate, "sample":OS.get_environment("THE_TREE_PAIRED_SAMPLE"), "pid":OS.get_process_id(), "manual_tick_us":elapsed,"metrics":metrics_pin,"diagnostic_only":true, "after647":after_pin, "cache_hits":runtime.path_service.cache_hits, "cache_misses":runtime.path_service.cache_misses, "checks":checks, "failures":failures, "passed":failures.is_empty(), "unit_accepted":false, "performance_budget_accepted":false, "normal_OS_accepted":false, "Windows_accepted":false, "candidate_adopted":false, "limits":["One instrumented r333/library334 cold646 tick; nested inclusive metrics, no sums or subtraction as pure CPU, no uninstrumented speed comparison or acceptance.", "No Main, rendering, OS input or realtime x3. Timed interval contains builtin production callbacks; snapshot verification and compression occur after timing."]}
|
||||
var file := FileAccess.open(output.path_join("report.json"), FileAccess.WRITE)
|
||||
if file == null: quit(98); return
|
||||
file.store_string(JSON.stringify(report, "\t")); file.close()
|
||||
print("Phase diagnostic whole647: %d checks, %d failures" % [checks, failures.size()])
|
||||
quit(0 if failures.is_empty() else 1)
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
extends "/Users/korizatou114/Projects/\u3068\u308a\u306b\u304f\u5de5\u623f\u30b2\u30fc\u30e0\u5236\u4f5c\u90e8/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/diagnostic.gd"
|
||||
const Guard := preload("/Users/korizatou114/Projects/\u3068\u308a\u306b\u304f\u5de5\u623f\u30b2\u30fc\u30e0\u5236\u4f5c\u90e8/artifacts/original-completion-2026-10-02/p23-02-native-cache-public-mutations-r144/profile_guard.gd")
|
||||
func _initialize() -> void:
|
||||
if not Guard.activate(): quit(97); return
|
||||
super._initialize()
|
||||
func run() -> void:
|
||||
var loaded := GDExtensionManager.load_extension("/Users/korizatou114/Projects/\u3068\u308a\u306b\u304f\u5de5\u623f\u30b2\u30fc\u30e0\u5236\u4f5c\u90e8/artifacts/original-completion-2026-10-02/p23-02-native-input-copy-local-r335/candidate.gdextension")
|
||||
var exact_api := false
|
||||
if loaded == GDExtensionManager.LOAD_STATUS_OK and ClassDB.class_exists(&"TheTreeNumericCore"):
|
||||
var probe: Variant = ClassDB.instantiate(&"TheTreeNumericCore")
|
||||
exact_api = probe != null and probe.has_method(&"guest_tree_edge_rows") == true
|
||||
probe = null
|
||||
check(loaded == GDExtensionManager.LOAD_STATUS_OK and ClassDB.class_exists(&"TheTreeNumericCore") and exact_api, "exact native extension registered before diagnostic")
|
||||
if loaded != GDExtensionManager.LOAD_STATUS_OK or not ClassDB.class_exists(&"TheTreeNumericCore") or not exact_api: quit(96); return
|
||||
print("NATIVE_ADAPTER_LIBRARY_REGISTERED")
|
||||
super.run()
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
+276
@@ -0,0 +1,276 @@
|
||||
class_name SimulationKernel
|
||||
extends Node
|
||||
|
||||
signal time_changed(day: int, hour: int, minute: int)
|
||||
signal day_started(day: int)
|
||||
signal settlement_requested(day: int)
|
||||
signal tick_started(absolute_minute: int)
|
||||
signal tick_phase_started(phase: TickPhase, absolute_minute: int)
|
||||
signal tick_completed(absolute_minute: int)
|
||||
signal simulation_overloaded(backlog_minutes: int)
|
||||
|
||||
enum TickPhase {
|
||||
APPLY_COMMANDS,
|
||||
TIME_BOUNDARIES,
|
||||
MANA,
|
||||
CONSTRUCTION,
|
||||
LOGISTICS,
|
||||
FACILITY_COMPLETION,
|
||||
VITALS_AND_ENVIRONMENT,
|
||||
INCIDENTS_AND_EVENTS,
|
||||
FACILITY_QUEUES,
|
||||
AI_DECISIONS,
|
||||
PUBLISH_SNAPSHOT,
|
||||
}
|
||||
|
||||
const MINUTES_PER_DAY := 24 * 60
|
||||
const START_ABSOLUTE_MINUTE := 6 * 60
|
||||
const REAL_SECONDS_PER_GAME_HOUR := 10.0
|
||||
const REAL_SECONDS_PER_GAME_MINUTE := REAL_SECONDS_PER_GAME_HOUR / 60.0
|
||||
const MAX_TICKS_PER_FRAME := 8
|
||||
const MAX_BACKLOG_MINUTES := 120
|
||||
|
||||
var absolute_minute := START_ABSOLUTE_MINUTE
|
||||
var day := 1
|
||||
var minute_of_day := START_ABSOLUTE_MINUTE
|
||||
var speed := 1
|
||||
var paused := false
|
||||
var snapshot_version := 0
|
||||
var performance_budget := SimulationPerformanceBudget.new()
|
||||
|
||||
var _accumulator := 0.0
|
||||
var _skip_next_process := false
|
||||
var _phase_handlers: Dictionary = {}
|
||||
var _pause_request_serial := 0
|
||||
var _abort_current_tick_requested := false
|
||||
var _last_tick_advanced := false
|
||||
|
||||
func _ready() -> void:
|
||||
_emit_current_time()
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
process_real_delta(delta)
|
||||
|
||||
func process_real_delta(delta: float) -> int:
|
||||
if _skip_next_process:
|
||||
_skip_next_process = false
|
||||
return 0
|
||||
if paused or speed <= 0 or delta <= 0.0:
|
||||
return 0
|
||||
|
||||
var frame_started_at_us := Time.get_ticks_usec()
|
||||
_accumulator += delta * speed
|
||||
var due_ticks := int(_accumulator / REAL_SECONDS_PER_GAME_MINUTE)
|
||||
var tick_budget := mini(due_ticks, MAX_TICKS_PER_FRAME)
|
||||
var ticks_run := 0
|
||||
for _index in range(tick_budget):
|
||||
if paused:
|
||||
break
|
||||
advance_one_minute()
|
||||
if not _last_tick_advanced:
|
||||
break
|
||||
_accumulator -= REAL_SECONDS_PER_GAME_MINUTE
|
||||
ticks_run += 1
|
||||
# A boundary handler may pause in the middle of a catch-up frame. Never
|
||||
# consume another queued minute after that decision.
|
||||
if paused:
|
||||
break
|
||||
if ticks_run > 0:
|
||||
performance_budget.record_simulation_frame(
|
||||
int(Time.get_ticks_usec() - frame_started_at_us),
|
||||
speed,
|
||||
ticks_run
|
||||
)
|
||||
|
||||
var backlog_minutes := get_backlog_minutes()
|
||||
if backlog_minutes > MAX_BACKLOG_MINUTES:
|
||||
paused = true
|
||||
simulation_overloaded.emit(backlog_minutes)
|
||||
return ticks_run
|
||||
|
||||
func reset(start_day := 1, start_hour := 6, start_minute := 0) -> void:
|
||||
var safe_day := maxi(start_day, 1)
|
||||
var safe_minute := posmod(start_hour * 60 + start_minute, MINUTES_PER_DAY)
|
||||
absolute_minute = (safe_day - 1) * MINUTES_PER_DAY + safe_minute
|
||||
_sync_calendar_fields()
|
||||
_accumulator = 0.0
|
||||
paused = false
|
||||
snapshot_version = 0
|
||||
performance_budget.clear()
|
||||
_abort_current_tick_requested = false
|
||||
_last_tick_advanced = false
|
||||
_emit_current_time()
|
||||
|
||||
func advance_minutes(amount: int) -> void:
|
||||
if amount <= 0:
|
||||
return
|
||||
# Tests and deterministic tooling historically use an already-paused clock as
|
||||
# an explicit manual stepping mode. Preserve that contract, while a pause
|
||||
# raised during an initially-running batch is a hard boundary stop.
|
||||
var manual_paused_stepping := paused
|
||||
var pause_serial_before := _pause_request_serial
|
||||
for _index in range(amount):
|
||||
if not manual_paused_stepping and paused:
|
||||
break
|
||||
advance_one_minute()
|
||||
if not _last_tick_advanced:
|
||||
break
|
||||
if _pause_request_serial != pause_serial_before \
|
||||
or (not manual_paused_stepping and paused):
|
||||
break
|
||||
|
||||
func advance_one_minute() -> void:
|
||||
_abort_current_tick_requested = false
|
||||
_last_tick_advanced = false
|
||||
tick_started.emit(absolute_minute)
|
||||
_run_phase(TickPhase.APPLY_COMMANDS)
|
||||
# A Runtime gate can reject the tick before the Clock changes. This is
|
||||
# distinct from an ordinary pause raised by a command that already committed
|
||||
# for the upcoming minute.
|
||||
if _abort_current_tick_requested:
|
||||
_abort_current_tick_requested = false
|
||||
return
|
||||
|
||||
var previous_absolute_minute := absolute_minute
|
||||
absolute_minute += 1
|
||||
_sync_calendar_fields()
|
||||
_handle_time_boundaries(previous_absolute_minute)
|
||||
_run_phase(TickPhase.TIME_BOUNDARIES)
|
||||
|
||||
for phase in [
|
||||
TickPhase.MANA,
|
||||
TickPhase.CONSTRUCTION,
|
||||
TickPhase.LOGISTICS,
|
||||
TickPhase.FACILITY_COMPLETION,
|
||||
TickPhase.VITALS_AND_ENVIRONMENT,
|
||||
TickPhase.INCIDENTS_AND_EVENTS,
|
||||
TickPhase.FACILITY_QUEUES,
|
||||
TickPhase.AI_DECISIONS,
|
||||
TickPhase.PUBLISH_SNAPSHOT,
|
||||
]:
|
||||
_run_phase(phase)
|
||||
|
||||
snapshot_version += 1
|
||||
tick_completed.emit(absolute_minute)
|
||||
_emit_current_time()
|
||||
_abort_current_tick_requested = false
|
||||
_last_tick_advanced = true
|
||||
|
||||
func request_current_tick_abort() -> void:
|
||||
_abort_current_tick_requested = true
|
||||
|
||||
func set_speed(value: int) -> bool:
|
||||
if value not in [1, 2, 3]:
|
||||
return false
|
||||
speed = value
|
||||
paused = false
|
||||
return true
|
||||
|
||||
func toggle_pause() -> bool:
|
||||
paused = not paused
|
||||
if paused:
|
||||
_pause_request_serial += 1
|
||||
return paused
|
||||
|
||||
func set_paused(value: bool) -> void:
|
||||
paused = value
|
||||
if value:
|
||||
_pause_request_serial += 1
|
||||
|
||||
func get_hour() -> int:
|
||||
return minute_of_day / 60
|
||||
|
||||
func get_minute() -> int:
|
||||
return minute_of_day % 60
|
||||
|
||||
func get_backlog_minutes() -> int:
|
||||
return int(_accumulator / REAL_SECONDS_PER_GAME_MINUTE)
|
||||
|
||||
func get_performance_reports() -> Array[Dictionary]:
|
||||
return performance_budget.get_all_reports()
|
||||
|
||||
func register_tick_handler(phase: TickPhase, handler_id: StringName, callback: Callable) -> bool:
|
||||
if handler_id.is_empty() or not callback.is_valid():
|
||||
return false
|
||||
if not _phase_handlers.has(phase):
|
||||
_phase_handlers[phase] = {}
|
||||
var handlers: Dictionary = _phase_handlers[phase]
|
||||
if handlers.has(handler_id):
|
||||
return false
|
||||
handlers[handler_id] = callback
|
||||
return true
|
||||
|
||||
func unregister_tick_handler(phase: TickPhase, handler_id: StringName) -> void:
|
||||
if not _phase_handlers.has(phase):
|
||||
return
|
||||
var handlers: Dictionary = _phase_handlers[phase]
|
||||
handlers.erase(handler_id)
|
||||
|
||||
func clock_snapshot() -> Dictionary:
|
||||
return {
|
||||
&"absolute_minute": absolute_minute,
|
||||
&"speed": speed,
|
||||
&"paused": paused,
|
||||
&"snapshot_version": snapshot_version,
|
||||
}
|
||||
|
||||
func restore_clock(snapshot: Dictionary) -> bool:
|
||||
if not snapshot.has(&"absolute_minute"):
|
||||
return false
|
||||
var restored_speed := int(snapshot.get(&"speed", 1))
|
||||
# Legacy x4 saves resume at the original specification maximum, x3.
|
||||
if restored_speed == 4:
|
||||
restored_speed = 3
|
||||
if restored_speed not in [1, 2, 3]:
|
||||
return false
|
||||
absolute_minute = maxi(int(snapshot[&"absolute_minute"]), 0)
|
||||
speed = restored_speed
|
||||
paused = bool(snapshot.get(&"paused", true))
|
||||
snapshot_version = maxi(int(snapshot.get(&"snapshot_version", 0)), 0)
|
||||
_accumulator = 0.0
|
||||
_skip_next_process = true
|
||||
_sync_calendar_fields()
|
||||
_emit_current_time()
|
||||
return true
|
||||
|
||||
func _p23r338_original_run_phase(phase: TickPhase) -> void:
|
||||
tick_phase_started.emit(phase, absolute_minute)
|
||||
if not _phase_handlers.has(phase):
|
||||
return
|
||||
var handlers: Dictionary = _phase_handlers[phase]
|
||||
var handler_ids: Array = handlers.keys()
|
||||
handler_ids.sort_custom(func(left: Variant, right: Variant) -> bool:
|
||||
return String(left) < String(right)
|
||||
)
|
||||
for handler_id: Variant in handler_ids:
|
||||
var callback: Callable = handlers[handler_id]
|
||||
if callback.is_valid():
|
||||
callback.call(absolute_minute)
|
||||
|
||||
func _sync_calendar_fields() -> void:
|
||||
day = absolute_minute / MINUTES_PER_DAY + 1
|
||||
minute_of_day = absolute_minute % MINUTES_PER_DAY
|
||||
|
||||
func _handle_time_boundaries(previous_absolute_minute: int) -> void:
|
||||
if minute_of_day == 0:
|
||||
var completed_day := previous_absolute_minute / MINUTES_PER_DAY + 1
|
||||
settlement_requested.emit(completed_day)
|
||||
day_started.emit(day)
|
||||
|
||||
func _emit_current_time() -> void:
|
||||
time_changed.emit(day, get_hour(), get_minute())
|
||||
|
||||
# Private r338 diagnostic fields; not persisted. Nested inclusive timings only.
|
||||
var _p23r338_metrics: Dictionary = {}
|
||||
|
||||
func _run_phase(phase: TickPhase) -> void:
|
||||
var p23_started := Time.get_ticks_usec()
|
||||
_p23r338_original_run_phase(phase)
|
||||
var p23_elapsed := Time.get_ticks_usec() - p23_started
|
||||
var p23_key: String = str(phase)
|
||||
var p23_row: Dictionary = _p23r338_metrics.get(p23_key, {"calls":0,"inclusive_us":0,"max_us":0})
|
||||
p23_row["calls"] = int(p23_row["calls"]) + 1
|
||||
p23_row["inclusive_us"] = int(p23_row["inclusive_us"]) + p23_elapsed
|
||||
p23_row["max_us"] = maxi(int(p23_row["max_us"]),p23_elapsed)
|
||||
_p23r338_metrics[p23_key] = p23_row
|
||||
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
+434
@@ -0,0 +1,434 @@
|
||||
class_name KitchenProductionService
|
||||
extends RefCounted
|
||||
|
||||
const Catalog = preload("res://scripts/supply/supply_catalog.gd")
|
||||
const SNAPSHOT_VERSION := 1
|
||||
|
||||
var current_minute := 0
|
||||
var last_error := ""
|
||||
var last_restore_error := ""
|
||||
|
||||
var _inventory: InventoryService
|
||||
var _facilities: FacilityService
|
||||
var _registry: DefinitionRegistry
|
||||
var _plans: Dictionary = {}
|
||||
var _active_batches: Dictionary = {}
|
||||
var _next_batch_sequence := 1
|
||||
|
||||
|
||||
func configure(
|
||||
inventory: InventoryService,
|
||||
facilities: FacilityService,
|
||||
registry: DefinitionRegistry,
|
||||
minute: int
|
||||
) -> void:
|
||||
_inventory = inventory
|
||||
_facilities = facilities
|
||||
_registry = registry
|
||||
current_minute = maxi(minute, 0)
|
||||
|
||||
|
||||
func set_plan(facility_id: StringName, enabled: bool, target_stock: int = Catalog.KITCHEN_TARGET_DEFAULT) -> Dictionary:
|
||||
if _kitchen(facility_id) == null:
|
||||
return _failure(&"INVALID_FACILITY", "Production plans require an existing kitchen.")
|
||||
if not _valid_target(target_stock):
|
||||
return _failure(&"INVALID_TARGET", "Target must be 4, 8, 12, or 16 meals.")
|
||||
_plans[facility_id] = {
|
||||
&"facility_id": String(facility_id), &"enabled": enabled, &"target_stock": target_stock,
|
||||
}
|
||||
last_error = ""
|
||||
return {&"ok": true, &"plan": get_plan(facility_id)}
|
||||
|
||||
|
||||
func get_plan(facility_id: StringName) -> Dictionary:
|
||||
if _plans.has(facility_id):
|
||||
return (_plans[facility_id] as Dictionary).duplicate(true)
|
||||
if _kitchen(facility_id) == null:
|
||||
return {}
|
||||
return {&"facility_id": String(facility_id), &"enabled": false, &"target_stock": Catalog.KITCHEN_TARGET_DEFAULT}
|
||||
|
||||
|
||||
func get_plans() -> Array[Dictionary]:
|
||||
var result: Array[Dictionary] = []
|
||||
for facility_id: StringName in _sorted_ids(_plans):
|
||||
result.append(get_plan(facility_id))
|
||||
return result
|
||||
|
||||
|
||||
## Also works after a successful facility removal, when the instance no longer
|
||||
## exists. Runtime checks enabled plans and batches before authorizing removal.
|
||||
func remove_plan(facility_id: StringName) -> Dictionary:
|
||||
if _active_batches.has(facility_id):
|
||||
return {&"ok": false, &"reason": &"ACTIVE_BATCH"}
|
||||
if _plans.has(facility_id) and bool(_plans[facility_id][&"enabled"]):
|
||||
return {&"ok": false, &"reason": &"PLAN_ENABLED"}
|
||||
var existed := _plans.erase(facility_id)
|
||||
return {&"ok": true, &"reason": &"REMOVED" if existed else &"NO_PLAN"}
|
||||
|
||||
|
||||
func get_report(facility_id: StringName) -> Dictionary:
|
||||
var facility := _kitchen(facility_id)
|
||||
if facility == null:
|
||||
return {}
|
||||
var plan := get_plan(facility_id)
|
||||
var batch: Dictionary = _active_batches.get(facility_id, {})
|
||||
var state := _production_state(facility, plan, batch, current_minute)
|
||||
return {
|
||||
&"facility_id": String(facility_id), &"inventory_id": String(facility.local_inventory_id),
|
||||
&"enabled": plan[&"enabled"], &"target_stock": plan[&"target_stock"],
|
||||
&"state": state, &"status": state,
|
||||
&"raw_stock": _inventory.available_quantity(facility.local_inventory_id, Catalog.RAW_FOOD, current_minute),
|
||||
&"meal_stock": _usable_quantity(facility.local_inventory_id, Catalog.BASIC_MEAL, current_minute),
|
||||
&"progress_minutes": int(batch.get(&"progress_minutes", 0)),
|
||||
&"duration_minutes": Catalog.PRODUCTION_MINUTES,
|
||||
&"active_batch": batch.duplicate(true),
|
||||
}
|
||||
|
||||
|
||||
## Runtime calls this after projecting current staffing/power/access. A batch
|
||||
## started at t first earns work at t+1; interruptions retain earned work.
|
||||
func _p23r338_originaladvance_one_minute(minute: int) -> Dictionary:
|
||||
if not _configured():
|
||||
return _failure(&"NOT_CONFIGURED", "Inventory, facilities, and registry must be configured.")
|
||||
if minute == current_minute:
|
||||
return {&"ok": true, &"replay": true, &"events": []}
|
||||
if minute != current_minute + 1:
|
||||
return _failure(&"INVALID_MINUTE", "Production must advance one minute at a time.")
|
||||
current_minute = minute
|
||||
var events: Array[Dictionary] = []
|
||||
for facility_id: StringName in _sorted_ids(_plans):
|
||||
var facility := _kitchen(facility_id)
|
||||
var batch: Dictionary = _active_batches.get(facility_id, {})
|
||||
if facility == null:
|
||||
if not batch.is_empty():
|
||||
_release_batch(batch)
|
||||
_active_batches.erase(facility_id)
|
||||
events.append(_event(&"BATCH_FAILED", facility_id, batch, &"FACILITY_REMOVED"))
|
||||
_plans.erase(facility_id)
|
||||
continue
|
||||
# Expiry also closes reservations while a plan or facility is paused.
|
||||
if not batch.is_empty() and not _batch_links_valid(batch, minute):
|
||||
_release_batch(batch)
|
||||
_active_batches.erase(facility_id)
|
||||
events.append(_event(&"BATCH_FAILED", facility_id, batch, &"INPUT_UNAVAILABLE"))
|
||||
continue
|
||||
var plan: Dictionary = _plans[facility_id]
|
||||
var state := _production_state(facility, plan, batch, minute)
|
||||
if batch.is_empty():
|
||||
if state == &"READY":
|
||||
var result := _start_batch(facility, minute)
|
||||
if bool(result[&"ok"]):
|
||||
events.append(_event(&"BATCH_STARTED", facility_id, _active_batches[facility_id]))
|
||||
continue
|
||||
if state != &"PRODUCING":
|
||||
continue
|
||||
batch[&"progress_minutes"] = mini(int(batch[&"progress_minutes"]) + 1, Catalog.PRODUCTION_MINUTES)
|
||||
if int(batch[&"progress_minutes"]) == Catalog.PRODUCTION_MINUTES:
|
||||
var result := _complete_batch(batch, minute)
|
||||
if bool(result[&"ok"]):
|
||||
_active_batches.erase(facility_id)
|
||||
events.append(_event(&"BATCH_COMPLETED", facility_id, batch))
|
||||
else:
|
||||
# Atomic inventory failure keeps the reservation and full progress.
|
||||
events.append(_event(&"BATCH_WAITING", facility_id, batch, result.get(&"code", &"INVENTORY_ERROR")))
|
||||
last_error = ""
|
||||
return {&"ok": true, &"events": events}
|
||||
|
||||
|
||||
func create_snapshot() -> Dictionary:
|
||||
var batches: Array[Dictionary] = []
|
||||
for facility_id: StringName in _sorted_ids(_active_batches):
|
||||
batches.append((_active_batches[facility_id] as Dictionary).duplicate(true))
|
||||
return {
|
||||
&"version": SNAPSHOT_VERSION, &"current_minute": current_minute,
|
||||
&"next_batch_sequence": _next_batch_sequence,
|
||||
&"plans": get_plans(), &"active_batches": batches,
|
||||
}
|
||||
|
||||
|
||||
## Restore is transactional and read-only with respect to inventory. Inventory
|
||||
## and FacilityService must already contain their restored state.
|
||||
func restore_snapshot(snapshot: Dictionary) -> bool:
|
||||
last_restore_error = ""
|
||||
if not _configured() or not _keys_match(snapshot, [&"version", &"current_minute", &"next_batch_sequence", &"plans", &"active_batches"]):
|
||||
return _restore_failure("Missing dependencies or invalid snapshot fields.")
|
||||
if not _integer(snapshot[&"version"], SNAPSHOT_VERSION, SNAPSHOT_VERSION) \
|
||||
or not _integer(snapshot[&"current_minute"], 0) \
|
||||
or not _integer(snapshot[&"next_batch_sequence"], 1) \
|
||||
or not snapshot[&"plans"] is Array or not snapshot[&"active_batches"] is Array:
|
||||
return _restore_failure("Invalid snapshot version, clock, sequence, or collections.")
|
||||
var candidate_plans: Dictionary = {}
|
||||
for value: Variant in snapshot[&"plans"]:
|
||||
if not value is Dictionary or not _keys_match(value, [&"facility_id", &"enabled", &"target_stock"]):
|
||||
return _restore_failure("Invalid production plan fields.")
|
||||
var plan: Dictionary = value
|
||||
if not _text(plan[&"facility_id"]) or not plan[&"enabled"] is bool \
|
||||
or not _integer(plan[&"target_stock"], 4, Catalog.KITCHEN_TARGET_MAX) \
|
||||
or not _valid_target(int(plan[&"target_stock"])):
|
||||
return _restore_failure("Invalid production plan values.")
|
||||
var facility_id := StringName(plan[&"facility_id"])
|
||||
if candidate_plans.has(facility_id) or _kitchen(facility_id) == null:
|
||||
return _restore_failure("Duplicate plan or unknown kitchen.")
|
||||
candidate_plans[facility_id] = plan.duplicate(true)
|
||||
var candidate_batches: Dictionary = {}
|
||||
var seen_batches: Dictionary = {}
|
||||
for value: Variant in snapshot[&"active_batches"]:
|
||||
if not value is Dictionary or not _valid_batch_shape(value, int(snapshot[&"current_minute"]), int(snapshot[&"next_batch_sequence"])):
|
||||
return _restore_failure("Invalid active batch.")
|
||||
var batch: Dictionary = value
|
||||
var facility_id := StringName(batch[&"facility_id"])
|
||||
if not candidate_plans.has(facility_id) or candidate_batches.has(facility_id) or seen_batches.has(batch[&"batch_id"]):
|
||||
return _restore_failure("Duplicate batch or missing production plan.")
|
||||
seen_batches[batch[&"batch_id"]] = true
|
||||
candidate_batches[facility_id] = batch.duplicate(true)
|
||||
if not _crosslinks_valid(candidate_batches, int(snapshot[&"current_minute"]), int(snapshot[&"next_batch_sequence"])):
|
||||
return _restore_failure("Kitchen input reservations do not match the restored inventory.")
|
||||
_plans = candidate_plans
|
||||
_active_batches = candidate_batches
|
||||
_next_batch_sequence = int(snapshot[&"next_batch_sequence"])
|
||||
current_minute = int(snapshot[&"current_minute"])
|
||||
last_error = ""
|
||||
return true
|
||||
|
||||
|
||||
func validate_crosslinks() -> bool:
|
||||
return _configured() and _crosslinks_valid(_active_batches, current_minute, _next_batch_sequence)
|
||||
|
||||
|
||||
func _start_batch(facility: FacilityInstance, minute: int) -> Dictionary:
|
||||
var batch_id := StringName("kitchen.batch:%08d" % _next_batch_sequence)
|
||||
var reserved := _inventory.reserve_item(
|
||||
facility.local_inventory_id, Catalog.RAW_FOOD, Catalog.BATCH_INPUT,
|
||||
batch_id, Catalog.PRODUCTION_PURPOSE, minute
|
||||
)
|
||||
if not bool(reserved[&"ok"]):
|
||||
return reserved
|
||||
_next_batch_sequence += 1
|
||||
var reservation_ids: Array[String] = []
|
||||
for reservation_id: StringName in reserved[&"reservation_ids"]:
|
||||
reservation_ids.append(String(reservation_id))
|
||||
var definition := _registry.get_facility(facility.definition_id)
|
||||
_active_batches[facility.instance_id] = {
|
||||
&"batch_id": String(batch_id), &"facility_id": String(facility.instance_id),
|
||||
&"inventory_id": String(facility.local_inventory_id), &"started_at": minute,
|
||||
&"progress_minutes": 0, &"quality": clampi(definition.base_quality, 0, 100),
|
||||
&"reservation_ids": reservation_ids,
|
||||
}
|
||||
return {&"ok": true}
|
||||
|
||||
|
||||
func _complete_batch(batch: Dictionary, minute: int) -> Dictionary:
|
||||
if not _has_output_space(batch):
|
||||
return {&"ok": false, &"code": &"OUTPUT_FULL"}
|
||||
var before := _inventory.create_snapshot()
|
||||
var consumed := _inventory.consume_reservations(_reservation_ids(batch), &"", minute)
|
||||
if not bool(consumed[&"ok"]):
|
||||
return consumed
|
||||
var item := Catalog.get_item(Catalog.BASIC_MEAL)
|
||||
var produced := _inventory.add_stack(
|
||||
StringName(batch[&"inventory_id"]), Catalog.BASIC_MEAL, Catalog.BATCH_OUTPUT,
|
||||
int(batch[&"quality"]), minute + int(item[&"shelf_life_minutes"]), minute, int(item[&"unit_weight"])
|
||||
)
|
||||
if not bool(produced[&"ok"]):
|
||||
_inventory.restore_snapshot(before)
|
||||
return produced
|
||||
|
||||
|
||||
func _production_state(facility: FacilityInstance, plan: Dictionary, batch: Dictionary, minute: int) -> StringName:
|
||||
if not bool(plan[&"enabled"]): return &"DISABLED"
|
||||
if facility.durability <= 0: return &"BROKEN"
|
||||
if not facility.suspension_reason.is_empty(): return &"SUSPENDED"
|
||||
if not facility.related_facility_operating: return &"RELATED_FACILITY_INACTIVE"
|
||||
if not facility.access_available: return &"NO_ACCESS"
|
||||
if not facility.power_available: return &"NO_POWER"
|
||||
if facility.active_staff_ids.size() < maxi(facility.staff_min, 1): return &"NO_STAFF"
|
||||
if not facility.operator_open or not facility.is_within_opening_hours(minute): return &"CLOSED"
|
||||
if not batch.is_empty():
|
||||
if not _batch_links_valid(batch, minute): return &"INPUT_UNAVAILABLE"
|
||||
if int(batch[&"progress_minutes"]) >= Catalog.PRODUCTION_MINUTES and not _has_output_space(batch):
|
||||
return &"OUTPUT_FULL"
|
||||
return &"PRODUCING"
|
||||
if _usable_quantity(facility.local_inventory_id, Catalog.BASIC_MEAL, minute) + Catalog.BATCH_OUTPUT > int(plan[&"target_stock"]):
|
||||
return &"TARGET_REACHED"
|
||||
if _inventory.available_quantity(facility.local_inventory_id, Catalog.RAW_FOOD, minute) < Catalog.BATCH_INPUT:
|
||||
return &"NO_INPUT"
|
||||
return &"READY"
|
||||
|
||||
|
||||
func _has_output_space(batch: Dictionary) -> bool:
|
||||
var consumed_weight := 0
|
||||
for reservation_id: StringName in _reservation_ids(batch):
|
||||
var reservation := _inventory.get_reservation(reservation_id)
|
||||
if reservation == null: return false
|
||||
var stack := _inventory.get_stack(reservation.stack_id)
|
||||
if stack.is_empty(): return false
|
||||
consumed_weight += reservation.quantity * int(stack[&"unit_weight"])
|
||||
var after_weight := Catalog.inventory_weight(_inventory, StringName(batch[&"inventory_id"])) - consumed_weight + Catalog.BATCH_OUTPUT
|
||||
return after_weight <= Catalog.storage_capacity(&"kitchen")
|
||||
|
||||
|
||||
func _batch_links_valid(batch: Dictionary, minute: int) -> bool:
|
||||
var facility := _kitchen(StringName(batch[&"facility_id"]))
|
||||
if facility == null or facility.local_inventory_id != StringName(batch[&"inventory_id"]): return false
|
||||
var quantity := 0
|
||||
var allocated_by_stack: Dictionary = {}
|
||||
for reservation_id: StringName in _reservation_ids(batch):
|
||||
var reservation := _inventory.get_reservation(reservation_id)
|
||||
if reservation == null or not reservation.is_active() or reservation.is_expired(minute) or reservation.quantity <= 0: return false
|
||||
if reservation.owner_inventory_id != facility.local_inventory_id \
|
||||
or reservation.item_id != Catalog.RAW_FOOD or reservation.requester_id != StringName(batch[&"batch_id"]) \
|
||||
or reservation.purpose != Catalog.PRODUCTION_PURPOSE or reservation.created_at != int(batch[&"started_at"]): return false
|
||||
var stack := _inventory.get_stack(reservation.stack_id)
|
||||
if stack.is_empty() or StringName(stack[&"owner_inventory_id"]) != facility.local_inventory_id \
|
||||
or StringName(stack[&"item_id"]) != Catalog.RAW_FOOD \
|
||||
or int(stack[&"reserved_quantity"]) < reservation.quantity or int(stack[&"quantity"]) < reservation.quantity: return false
|
||||
if int(stack[&"expires_at"]) >= 0 and int(stack[&"expires_at"]) <= minute: return false
|
||||
allocated_by_stack[reservation.stack_id] = int(allocated_by_stack.get(reservation.stack_id, 0)) + reservation.quantity
|
||||
if int(allocated_by_stack[reservation.stack_id]) > int(stack[&"reserved_quantity"]): return false
|
||||
quantity += reservation.quantity
|
||||
return quantity == Catalog.BATCH_INPUT
|
||||
|
||||
|
||||
func _crosslinks_valid(batches: Dictionary, minute: int, next_sequence: int) -> bool:
|
||||
var linked: Dictionary = {}
|
||||
for batch: Dictionary in batches.values():
|
||||
if not _batch_links_valid(batch, minute): return false
|
||||
for reservation_id: StringName in _reservation_ids(batch):
|
||||
if linked.has(reservation_id): return false
|
||||
linked[reservation_id] = true
|
||||
# Inventory retains terminal reservations. Their requester IDs are durable
|
||||
# evidence that a batch number was already used, even after completion,
|
||||
# failure, or removal of the kitchen's plan.
|
||||
for reservation: InventoryReservation in _inventory.get_reservations():
|
||||
if reservation.purpose != Catalog.PRODUCTION_PURPOSE:
|
||||
continue
|
||||
var sequence := _batch_sequence(reservation.requester_id)
|
||||
if sequence < 1 or sequence >= next_sequence:
|
||||
return false
|
||||
if reservation.is_active() and not linked.has(reservation.reservation_id):
|
||||
return false
|
||||
return true
|
||||
|
||||
|
||||
func _release_batch(batch: Dictionary) -> void:
|
||||
for reservation_id: StringName in _reservation_ids(batch):
|
||||
var reservation := _inventory.get_reservation(reservation_id)
|
||||
# Only release this batch's own holds if external state was corrupted.
|
||||
if reservation != null and reservation.requester_id == StringName(batch[&"batch_id"]) \
|
||||
and reservation.purpose == Catalog.PRODUCTION_PURPOSE:
|
||||
_inventory.release_reservation(reservation_id, &"", current_minute)
|
||||
|
||||
|
||||
func _kitchen(facility_id: StringName) -> FacilityInstance:
|
||||
if not _configured(): return null
|
||||
var facility := _facilities.get_instance(facility_id)
|
||||
if facility == null or facility.definition_id != &"kitchen" or facility.local_inventory_id == &"": return null
|
||||
if _registry.get_facility(facility.definition_id) == null: return null
|
||||
return facility
|
||||
|
||||
|
||||
func _configured() -> bool:
|
||||
return _inventory != null and _facilities != null and _registry != null
|
||||
|
||||
|
||||
func _usable_quantity(inventory_id: StringName, item_id: StringName, minute: int) -> int:
|
||||
var quantity := 0
|
||||
for stack: Dictionary in _inventory.get_stacks(inventory_id):
|
||||
if StringName(stack[&"item_id"]) == item_id and (int(stack[&"expires_at"]) < 0 or int(stack[&"expires_at"]) > minute):
|
||||
quantity += int(stack[&"quantity"])
|
||||
return quantity
|
||||
|
||||
|
||||
func _valid_batch_shape(batch: Dictionary, minute: int, next_sequence: int) -> bool:
|
||||
if not _keys_match(batch, [&"batch_id", &"facility_id", &"inventory_id", &"started_at", &"progress_minutes", &"quality", &"reservation_ids"]): return false
|
||||
for key: StringName in [&"batch_id", &"facility_id", &"inventory_id"]:
|
||||
if not _text(batch[key]): return false
|
||||
if not _integer(batch[&"started_at"], 0, minute) \
|
||||
or not _integer(batch[&"progress_minutes"], 0, Catalog.PRODUCTION_MINUTES) \
|
||||
or int(batch[&"progress_minutes"]) > minute - int(batch[&"started_at"]) \
|
||||
or not _integer(batch[&"quality"], 0, 100) or not batch[&"reservation_ids"] is Array:
|
||||
return false
|
||||
var sequence := _batch_sequence(batch[&"batch_id"])
|
||||
if sequence < 1 or sequence >= next_sequence: return false
|
||||
var seen: Dictionary = {}
|
||||
for reservation_id: Variant in batch[&"reservation_ids"]:
|
||||
if not _text(reservation_id) or seen.has(StringName(reservation_id)): return false
|
||||
seen[StringName(reservation_id)] = true
|
||||
return not seen.is_empty()
|
||||
|
||||
|
||||
func _batch_sequence(value: Variant) -> int:
|
||||
if not _text(value): return -1
|
||||
var batch_id := String(value)
|
||||
var sequence_text := batch_id.trim_prefix("kitchen.batch:")
|
||||
if not sequence_text.is_valid_int(): return -1
|
||||
var sequence := sequence_text.to_int()
|
||||
if sequence < 1 or batch_id != "kitchen.batch:%08d" % sequence: return -1
|
||||
return sequence
|
||||
|
||||
|
||||
func _reservation_ids(batch: Dictionary) -> Array[StringName]:
|
||||
var ids: Array[StringName] = []
|
||||
for value: Variant in batch[&"reservation_ids"]:
|
||||
ids.append(StringName(value))
|
||||
return ids
|
||||
|
||||
|
||||
func _valid_target(target: int) -> bool:
|
||||
return target >= Catalog.BATCH_OUTPUT and target <= Catalog.KITCHEN_TARGET_MAX and target % Catalog.BATCH_OUTPUT == 0
|
||||
|
||||
|
||||
func _integer(value: Variant, minimum: int, maximum: int = 9223372036854775807) -> bool:
|
||||
return typeof(value) == TYPE_INT and value >= minimum and value <= maximum
|
||||
|
||||
|
||||
func _text(value: Variant) -> bool:
|
||||
return typeof(value) in [TYPE_STRING, TYPE_STRING_NAME] and not String(value).strip_edges().is_empty()
|
||||
|
||||
|
||||
func _keys_match(value: Dictionary, expected: Array) -> bool:
|
||||
if value.size() != expected.size(): return false
|
||||
for key: StringName in expected:
|
||||
if not value.has(key): return false
|
||||
return true
|
||||
|
||||
|
||||
func _sorted_ids(values: Dictionary) -> Array[StringName]:
|
||||
var ids: Array[StringName] = []
|
||||
for value: Variant in values.keys(): ids.append(StringName(value))
|
||||
ids.sort()
|
||||
return ids
|
||||
|
||||
|
||||
func _event(kind: StringName, facility_id: StringName, batch: Dictionary, reason: StringName = &"") -> Dictionary:
|
||||
return {
|
||||
&"type": kind, &"facility_id": String(facility_id), &"batch_id": batch[&"batch_id"],
|
||||
&"minute": current_minute, &"reason": reason,
|
||||
&"output_quantity": Catalog.BATCH_OUTPUT if kind == &"BATCH_COMPLETED" else 0,
|
||||
}
|
||||
|
||||
|
||||
func _failure(code: StringName, message: String) -> Dictionary:
|
||||
last_error = message
|
||||
return {&"ok": false, &"code": code, &"message": message, &"events": []}
|
||||
|
||||
|
||||
func _restore_failure(message: String) -> bool:
|
||||
last_restore_error = message
|
||||
return false
|
||||
|
||||
# Private r338 diagnostic fields; not persisted. Nested inclusive timings only.
|
||||
var _p23r338_metrics: Dictionary = {}
|
||||
|
||||
func advance_one_minute(minute: int) -> Dictionary:
|
||||
var p23_started := Time.get_ticks_usec()
|
||||
var p23_result: Dictionary = _p23r338_originaladvance_one_minute(minute)
|
||||
var p23_elapsed := Time.get_ticks_usec() - p23_started
|
||||
var p23_key: String = "advance_one_minute"
|
||||
var p23_row: Dictionary = _p23r338_metrics.get(p23_key, {"calls":0,"inclusive_us":0,"max_us":0})
|
||||
p23_row["calls"] = int(p23_row["calls"]) + 1
|
||||
p23_row["inclusive_us"] = int(p23_row["inclusive_us"]) + p23_elapsed
|
||||
p23_row["max_us"] = maxi(int(p23_row["max_us"]),p23_elapsed)
|
||||
_p23r338_metrics[p23_key] = p23_row
|
||||
return p23_result
|
||||
|
||||
+581
@@ -0,0 +1,581 @@
|
||||
class_name SupplyLogisticsBridge
|
||||
extends RefCounted
|
||||
|
||||
## Execution state lives in LogisticsRequest, StaffTask, and InventoryService.
|
||||
## This adapter owns no additional save payload and never moves an actor itself.
|
||||
const REQUEST_PREFIX := "supply."
|
||||
const PICKUP_TYPE := &"supply_pickup"
|
||||
const DELIVERY_TYPE := &"supply_delivery"
|
||||
const RETURN_TYPE := &"supply_return"
|
||||
const RETRY_MINUTES := 5
|
||||
const RETURNING := "RETURNING_EXPIRED_CARGO"
|
||||
|
||||
var _runtime: Variant
|
||||
var last_report: Dictionary = {}
|
||||
|
||||
|
||||
func configure(runtime: Variant) -> SupplyLogisticsBridge:
|
||||
_runtime = runtime
|
||||
_runtime.staff_service.configure_external_task_driver(Callable(self, "owns_task"))
|
||||
return self
|
||||
|
||||
|
||||
func owns_task(task_id: StringName) -> bool:
|
||||
if _runtime == null:
|
||||
return false
|
||||
var task: StaffTask = _runtime.staff_service.get_task(task_id)
|
||||
return task != null and task.task_type in [PICKUP_TYPE, DELIVERY_TYPE, RETURN_TYPE] \
|
||||
and String(task.target_entity_id).begins_with(REQUEST_PREFIX)
|
||||
|
||||
|
||||
func can_move_task(task_id: StringName) -> bool:
|
||||
if not owns_task(task_id):
|
||||
return true
|
||||
var task: StaffTask = _runtime.staff_service.get_task(task_id)
|
||||
var staff: StaffRuntime = _runtime.staff_service.get_staff(task.assigned_staff_id)
|
||||
if staff == null or not staff.can_take_shift():
|
||||
return false
|
||||
# Partial spoilage is a return obligation. Do not keep walking to the
|
||||
# customer while the bridge is still searching for a safe return route.
|
||||
return task.task_type != DELIVERY_TYPE or not is_returning(task.target_entity_id)
|
||||
|
||||
|
||||
func _p23r338_originaltick(absolute_minute: int) -> Dictionary:
|
||||
if _runtime == null:
|
||||
return {&"ok": false, &"reason": &"NOT_CONFIGURED"}
|
||||
var actions: Array[Dictionary] = []
|
||||
for request_id: StringName in _request_ids(_runtime.logistics_requests):
|
||||
var request: LogisticsRequest = _runtime.logistics_requests[request_id]
|
||||
if request.is_terminal():
|
||||
continue
|
||||
if request.state == LogisticsRequest.State.BLOCKED:
|
||||
if absolute_minute >= request.state_changed_at + RETRY_MINUTES:
|
||||
_rearm(request, absolute_minute)
|
||||
continue
|
||||
if request.state == LogisticsRequest.State.RESERVED:
|
||||
if not _reserved_stock_valid(request):
|
||||
_block_before_pickup(request, "SOURCE_STOCK_EXPIRED", absolute_minute)
|
||||
else:
|
||||
_dispatch(request, absolute_minute)
|
||||
continue
|
||||
var task := _active_task(_runtime.staff_service, request.request_id)
|
||||
var staff: StaffRuntime = _runtime.staff_service.get_staff(request.assigned_carrier_id)
|
||||
if task == null or staff == null or staff.current_task_id != task.task_id:
|
||||
request.state_reason = "CARRIER_TASK_MISSING"
|
||||
continue
|
||||
if request.state == LogisticsRequest.State.DELIVERING and _cargo_quantities(_runtime.inventory_service, _cargo_id(staff.staff_id)).is_empty():
|
||||
_cancel_empty_cargo(request, staff, task, "CARGO_EXPIRED", absolute_minute)
|
||||
continue
|
||||
if not staff.can_take_shift():
|
||||
if request.state in [LogisticsRequest.State.ASSIGNED, LogisticsRequest.State.PICKING_UP]:
|
||||
_block_before_pickup(request, "CARRIER_UNAVAILABLE", absolute_minute)
|
||||
else:
|
||||
request.state_reason = "CARRIER_UNAVAILABLE"
|
||||
continue
|
||||
if request.state in [LogisticsRequest.State.ASSIGNED, LogisticsRequest.State.PICKING_UP]:
|
||||
if not _reserved_stock_valid(request):
|
||||
_block_before_pickup(request, "SOURCE_STOCK_EXPIRED", absolute_minute)
|
||||
elif _arrived_for_work(staff, task, absolute_minute):
|
||||
if _pickup(request, staff, task, absolute_minute):
|
||||
actions.append({&"request_id": request_id, &"action": &"PICKED_UP"})
|
||||
elif request.state == LogisticsRequest.State.DELIVERING:
|
||||
var cargo := _cargo_quantities(_runtime.inventory_service, _cargo_id(staff.staff_id))
|
||||
if cargo.is_empty():
|
||||
_cancel_empty_cargo(request, staff, task, "CARGO_EXPIRED", absolute_minute)
|
||||
continue
|
||||
if not _quantities_cover(cargo, request.item_requirements) and task.task_type != RETURN_TYPE:
|
||||
var source := _facility_for_inventory(_runtime.facility_service, request.source_inventory_id)
|
||||
var route := _access_path(staff.current_cell, source)
|
||||
if not bool(route.get(&"reachable", false)):
|
||||
request.state_reason = "EXPIRED_CARGO_RETURN_BLOCKED"
|
||||
continue
|
||||
if not _runtime.staff_service.retarget_external_task(task.task_id, route[&"cell"], absolute_minute).is_success():
|
||||
continue
|
||||
task.task_type = RETURN_TYPE
|
||||
request.state_reason = RETURNING
|
||||
continue
|
||||
if _arrived_for_work(staff, task, absolute_minute):
|
||||
if _deliver(request, staff, task, absolute_minute):
|
||||
actions.append({&"request_id": request_id, &"action": &"DELIVERED"})
|
||||
last_report = {&"ok": true, &"actions": actions}
|
||||
return last_report.duplicate(true)
|
||||
|
||||
|
||||
func handle_path_stuck(task_id: StringName, absolute_minute: int) -> Dictionary:
|
||||
if not owns_task(task_id):
|
||||
return {&"ok": false, &"action": &"NOT_SUPPLY_TASK"}
|
||||
var task: StaffTask = _runtime.staff_service.get_task(task_id)
|
||||
var request: LogisticsRequest = _runtime.logistics_requests.get(task.target_entity_id)
|
||||
if request == null:
|
||||
return {&"ok": false, &"action": &"REQUEST_MISSING"}
|
||||
if request.state == LogisticsRequest.State.DELIVERING:
|
||||
# Loaded cargo stays with its actor, even when no safe return route exists.
|
||||
# The normal Path loop retries after topology is repaired.
|
||||
request.retry_count += 1
|
||||
if task.task_type != RETURN_TYPE:
|
||||
request.state_reason = "ROUTE_BLOCKED"
|
||||
task.state_reason = &"ROUTE_BLOCKED"
|
||||
return {&"ok": true, &"action": &"SUPPLY_CARGO_HELD"}
|
||||
return {&"ok": _block_before_pickup(request, "ROUTE_BLOCKED", absolute_minute), &"action": &"SUPPLY_PICKUP_RETRY"}
|
||||
|
||||
|
||||
func get_report() -> Dictionary:
|
||||
var rows: Array[Dictionary] = []
|
||||
if _runtime == null:
|
||||
return {&"requests": rows, &"deliveries": rows.duplicate(true)}
|
||||
for request_id: StringName in _request_ids(_runtime.logistics_requests):
|
||||
var request: LogisticsRequest = _runtime.logistics_requests[request_id]
|
||||
var task := _active_task(_runtime.staff_service, request_id)
|
||||
var source := _facility_for_inventory(_runtime.facility_service, request.source_inventory_id)
|
||||
var destination := _facility_for_inventory(_runtime.facility_service, request.destination_inventory_id)
|
||||
var worker: StaffRuntime = _runtime.staff_service.get_staff(request.assigned_carrier_id)
|
||||
rows.append({
|
||||
&"source_facility_id": source.instance_id if source != null else &"",
|
||||
&"destination_facility_id": destination.instance_id if destination != null else &"",
|
||||
&"carrier_name": String(_runtime.mvp_content_catalog.get_entry(&"staff_candidates", worker.staff_id).get(&"display_name", worker.staff_id)) if worker != null else "",
|
||||
&"reason_codes": [] if request.state_reason.is_empty() else [StringName(request.state_reason)],
|
||||
&"request_id": request_id, &"state": LogisticsRequest.State.keys()[request.state],
|
||||
&"reason": request.state_reason, &"carrier_id": request.assigned_carrier_id,
|
||||
&"source_inventory_id": request.source_inventory_id,
|
||||
&"destination_inventory_id": request.destination_inventory_id,
|
||||
&"item_requirements": request.item_requirements.duplicate(true), &"weight": request.total_weight,
|
||||
&"retry_count": request.retry_count, &"task_id": task.task_id if task != null else &"",
|
||||
})
|
||||
var active: Array[Dictionary] = []
|
||||
var recent: Array[Dictionary] = []
|
||||
for row: Dictionary in rows:
|
||||
var request: LogisticsRequest = _runtime.logistics_requests[row[&"request_id"]]
|
||||
if request.is_terminal(): recent.append(row)
|
||||
else: active.append(row)
|
||||
recent.sort_custom(func(a: Dictionary, b: Dictionary) -> bool:
|
||||
var left: LogisticsRequest = _runtime.logistics_requests[a[&"request_id"]]
|
||||
var right: LogisticsRequest = _runtime.logistics_requests[b[&"request_id"]]
|
||||
if left.state_changed_at != right.state_changed_at: return left.state_changed_at > right.state_changed_at
|
||||
return String(left.request_id) > String(right.request_id))
|
||||
active.append_array(recent.slice(0, 10))
|
||||
return {&"requests": rows, &"deliveries": active}
|
||||
|
||||
|
||||
func is_returning(request_id: StringName) -> bool:
|
||||
if _runtime == null:
|
||||
return false
|
||||
var request: LogisticsRequest = _runtime.logistics_requests.get(request_id)
|
||||
if request == null or request.state != LogisticsRequest.State.DELIVERING:
|
||||
return false
|
||||
var task := _active_task(_runtime.staff_service, request_id)
|
||||
if task != null and task.task_type == RETURN_TYPE:
|
||||
return true
|
||||
return not _quantities_cover(_cargo_quantities(_runtime.inventory_service, _cargo_id(request.assigned_carrier_id)), request.item_requirements)
|
||||
|
||||
|
||||
func _dispatch(request: LogisticsRequest, minute: int) -> void:
|
||||
var source := _facility_for_inventory(_runtime.facility_service, request.source_inventory_id)
|
||||
var destination := _facility_for_inventory(_runtime.facility_service, request.destination_inventory_id)
|
||||
if source == null or destination == null or not source.allows_logistics() or not destination.allows_logistics():
|
||||
request.state_reason = "FACILITY_UNAVAILABLE"
|
||||
return
|
||||
if not _has_storage_space(destination, request.total_weight):
|
||||
request.state_reason = "DESTINATION_FULL"
|
||||
return
|
||||
var carriers: Dictionary = {}
|
||||
var source_cells: Dictionary = {}
|
||||
for staff: StaffRuntime in _runtime.staff_service.get_staff_members():
|
||||
var shift: ShiftInstance = _runtime.staff_service.get_shift(staff.shift_id)
|
||||
if staff.role_id != &"porter" or not staff.is_available_for_dispatch() \
|
||||
or shift == null or not shift.contains_minute(minute) \
|
||||
or _runtime.logistics_dispatcher.get_reserved_load(staff.staff_id) > 0 \
|
||||
or not _cargo_quantities(_runtime.inventory_service, _cargo_id(staff.staff_id)).is_empty():
|
||||
continue
|
||||
var access := _access_path(staff.current_cell, source)
|
||||
if not bool(access.get(&"reachable", false)):
|
||||
continue
|
||||
var onward := _access_path(access[&"cell"], destination)
|
||||
if not bool(onward.get(&"reachable", false)):
|
||||
continue
|
||||
carriers[staff.staff_id] = {&"capacity": mini(20, 10 + int(staff.skills.get(&"operation", 0)) / 10),
|
||||
&"current_load": 0, &"path_minutes": int(access[&"steps"]), &"position": staff.current_cell, &"role": &"logistics"}
|
||||
source_cells[staff.staff_id] = access[&"cell"]
|
||||
if carriers.is_empty():
|
||||
request.state_reason = "NO_AVAILABLE_PORTER_OR_ROUTE"
|
||||
return
|
||||
var before := _capture(request)
|
||||
var assigned: Array = _runtime.logistics_dispatcher.dispatch([request], carriers, minute)
|
||||
if assigned.is_empty():
|
||||
request.state_reason = "CARRIER_CAPACITY_EXCEEDED"
|
||||
return
|
||||
var staff_id := request.assigned_carrier_id
|
||||
var task := _create_task(request, PICKUP_TYPE, source_cells[staff_id], minute)
|
||||
if task == null or not _runtime.staff_service.assign_task_to_staff(task.task_id, staff_id, minute).is_success():
|
||||
_rollback(request, before)
|
||||
request.state_reason = "TASK_ASSIGNMENT_FAILED"
|
||||
return
|
||||
request.state_reason = ""
|
||||
|
||||
|
||||
func _pickup(request: LogisticsRequest, staff: StaffRuntime, task: StaffTask, minute: int) -> bool:
|
||||
var source := _facility_for_inventory(_runtime.facility_service, request.source_inventory_id)
|
||||
if source == null or not _cell_touches_facility(staff.current_cell, source):
|
||||
return _block_before_pickup(request, "INVALID_PICKUP_ACCESS", minute) and false
|
||||
if not source.allows_logistics():
|
||||
return _block_before_pickup(request, "SOURCE_CLOSED", minute) and false
|
||||
var destination := _facility_for_inventory(_runtime.facility_service, request.destination_inventory_id)
|
||||
if destination == null or not destination.allows_logistics() or not _has_storage_space(destination, request.total_weight):
|
||||
return _block_before_pickup(request, "DESTINATION_FULL_OR_CLOSED", minute) and false
|
||||
var route := _access_path(staff.current_cell, destination)
|
||||
if not bool(route.get(&"reachable", false)):
|
||||
return _block_before_pickup(request, "NO_DELIVERY_ROUTE", minute) and false
|
||||
var before := _capture(request)
|
||||
if request.state == LogisticsRequest.State.ASSIGNED and not _advance_request(request, minute):
|
||||
_rollback(request, before)
|
||||
return false
|
||||
if not _advance_request(request, minute):
|
||||
_rollback(request, before)
|
||||
return _block_before_pickup(request, "PICKUP_FAILED", minute) and false
|
||||
if not _runtime.staff_service.progress_task(task.task_id, 1, minute, true).is_success():
|
||||
_rollback(request, before)
|
||||
return false
|
||||
staff.carried_inventory_id = _cargo_id(staff.staff_id)
|
||||
var delivery := _create_task(request, DELIVERY_TYPE, route[&"cell"], minute)
|
||||
if delivery == null or not _runtime.staff_service.assign_task_to_staff(delivery.task_id, staff.staff_id, minute).is_success():
|
||||
_rollback(request, before)
|
||||
return false
|
||||
request.state_reason = ""
|
||||
return true
|
||||
|
||||
|
||||
func _deliver(request: LogisticsRequest, staff: StaffRuntime, task: StaffTask, minute: int) -> bool:
|
||||
var returning := task.task_type == RETURN_TYPE
|
||||
var destination_id := request.source_inventory_id if returning else request.destination_inventory_id
|
||||
var destination := _facility_for_inventory(_runtime.facility_service, destination_id)
|
||||
if destination == null or not _cell_touches_facility(staff.current_cell, destination):
|
||||
request.state_reason = "INVALID_DELIVERY_ACCESS"
|
||||
return false
|
||||
var quantities := _cargo_quantities(_runtime.inventory_service, _cargo_id(staff.staff_id))
|
||||
if destination == null or not destination.allows_logistics() or not _has_storage_space(destination, SupplyCatalog.inventory_weight(_runtime.inventory_service, _cargo_id(staff.staff_id))):
|
||||
if not returning:
|
||||
request.state_reason = "DESTINATION_FULL"
|
||||
return false
|
||||
var before := _capture(request)
|
||||
if returning:
|
||||
var transfers: Array[Dictionary] = []
|
||||
for item_id: StringName in _sorted_keys(quantities):
|
||||
transfers.append({&"source_inventory_id": _cargo_id(staff.staff_id), &"destination_inventory_id": destination_id,
|
||||
&"item_id": item_id, &"quantity": int(quantities[item_id]), &"operation_id": StringName("supply.return.%s.%s" % [request.request_id, item_id])})
|
||||
if not _runtime.inventory_service.transfer_available_batch(transfers, minute)[&"ok"] \
|
||||
or not _runtime.logistics_dispatcher.release_assignment_for_request(request.request_id, staff.staff_id, request.total_weight):
|
||||
_rollback(request, before)
|
||||
return false
|
||||
request.cancel("CARGO_EXPIRED_RETURNED", minute)
|
||||
else:
|
||||
if not _advance_request(request, minute):
|
||||
_rollback(request, before)
|
||||
request.state_reason = "DELIVERY_RETRY"
|
||||
return false
|
||||
if not _runtime.staff_service.progress_task(task.task_id, 1, minute, true).is_success():
|
||||
_rollback(request, before)
|
||||
return false
|
||||
staff.carried_inventory_id = &""
|
||||
return true
|
||||
|
||||
|
||||
func _block_before_pickup(request: LogisticsRequest, reason: String, minute: int) -> bool:
|
||||
var before := _capture(request)
|
||||
var task := _active_task(_runtime.staff_service, request.request_id)
|
||||
var carrier_id := request.assigned_carrier_id
|
||||
var worker: StaffRuntime = _runtime.staff_service.get_staff(carrier_id)
|
||||
var unavailable_state := worker.state if worker != null and not worker.can_take_shift() else -1
|
||||
for reservation_id: StringName in request.reservation_ids:
|
||||
var reservation: InventoryReservation = _runtime.inventory_service.get_reservation(reservation_id)
|
||||
if reservation != null and reservation.is_active() \
|
||||
and not _runtime.inventory_service.release_reservation(reservation_id, &"", minute)[&"ok"]:
|
||||
_rollback(request, before)
|
||||
return false
|
||||
if not carrier_id.is_empty() and not _runtime.logistics_dispatcher.release_assignment_for_request(request.request_id, carrier_id, request.total_weight):
|
||||
_rollback(request, before)
|
||||
return false
|
||||
if task != null and not _runtime.staff_service.cancel_task(task.task_id, StringName(reason), minute, true).is_success():
|
||||
_rollback(request, before)
|
||||
return false
|
||||
if unavailable_state >= 0:
|
||||
worker.transition_to(unavailable_state, StringName(reason), minute)
|
||||
request.mark_blocked(reason, minute)
|
||||
return true
|
||||
|
||||
|
||||
func _rearm(request: LogisticsRequest, minute: int) -> void:
|
||||
if request.deadline >= 0 and request.deadline <= minute:
|
||||
request.cancel("DEADLINE_EXPIRED", minute)
|
||||
return
|
||||
var before := _capture(request)
|
||||
var ids: Array[StringName] = []
|
||||
var stacks: Array[StringName] = []
|
||||
var weight := 0
|
||||
for item_id: StringName in _sorted_keys(request.item_requirements):
|
||||
var result: Dictionary = _runtime.inventory_service.reserve_item(request.source_inventory_id, item_id,
|
||||
int(request.item_requirements[item_id]), request.request_id, &"logistics", minute, request.deadline,
|
||||
StringName("supply.retry.%s.%d.%s" % [request.request_id, minute, item_id]))
|
||||
if not bool(result.get(&"ok", false)):
|
||||
_rollback(request, before)
|
||||
request.state_changed_at = minute
|
||||
request.state_reason = "WAITING_FOR_SOURCE_STOCK"
|
||||
return
|
||||
for id: StringName in result[&"reservation_ids"]:
|
||||
ids.append(id)
|
||||
var reservation: InventoryReservation = _runtime.inventory_service.get_reservation(id)
|
||||
stacks.append(reservation.stack_id)
|
||||
weight += reservation.quantity * int(_runtime.inventory_service.get_stack(reservation.stack_id)[&"unit_weight"])
|
||||
if weight != request.total_weight or not request.mark_reserved(ids, stacks, minute):
|
||||
_rollback(request, before)
|
||||
request.state_changed_at = minute
|
||||
request.state_reason = "SOURCE_WEIGHT_CHANGED"
|
||||
|
||||
|
||||
func _cancel_empty_cargo(request: LogisticsRequest, staff: StaffRuntime, task: StaffTask, reason: String, minute: int) -> void:
|
||||
var before := _capture(request)
|
||||
var unavailable_state := staff.state if not staff.can_take_shift() else -1
|
||||
if not _runtime.logistics_dispatcher.release_assignment_for_request(request.request_id, staff.staff_id, request.total_weight) \
|
||||
or not _runtime.staff_service.cancel_task(task.task_id, StringName(reason), minute, true).is_success():
|
||||
_rollback(request, before)
|
||||
return
|
||||
staff.carried_inventory_id = &""
|
||||
if unavailable_state >= 0:
|
||||
staff.transition_to(unavailable_state, StringName(reason), minute)
|
||||
request.cancel(reason, minute)
|
||||
|
||||
|
||||
func _create_task(request: LogisticsRequest, type: StringName, cell: Vector3i, minute: int) -> StaffTask:
|
||||
var leg := "pickup" if type == PICKUP_TYPE else "delivery"
|
||||
var task_id := StringName("supply.%s.%s.%d" % [leg, request.request_id, request.retry_count])
|
||||
var result: CommandResult = _runtime.staff_service.create_task(type, request.priority, minute, {
|
||||
&"target_entity_id": request.request_id, &"target_cell": cell, &"required_role_tags": [&"porter"],
|
||||
&"task_tags": [&"logistics"], &"estimated_minutes": 1, &"interrupt_level": 0,
|
||||
}, task_id)
|
||||
return _runtime.staff_service.get_task(task_id) if result.is_success() else null
|
||||
|
||||
|
||||
func _advance_request(request: LogisticsRequest, minute: int) -> bool:
|
||||
var command := SimulationCommand.new()
|
||||
command.command_id = 0
|
||||
command.command_type = &"advance_logistics_request"
|
||||
command.payload = {&"request_id": request.request_id}
|
||||
command.issued_tick = minute
|
||||
command.execute_tick = minute
|
||||
return _runtime._execute_advance_logistics_request(command).is_success()
|
||||
|
||||
|
||||
func _capture(request: LogisticsRequest) -> Dictionary:
|
||||
return {&"request": request.create_snapshot(), &"staff": _runtime.staff_service.create_snapshot(),
|
||||
&"inventory": _runtime.inventory_service.create_snapshot(), &"dispatcher": _runtime.logistics_dispatcher.create_snapshot(),
|
||||
&"events": _runtime.domain_events.create_snapshot(), &"ids": _runtime.id_generator.create_snapshot()}
|
||||
|
||||
|
||||
func _rollback(request: LogisticsRequest, before: Dictionary) -> void:
|
||||
_runtime.staff_service.restore_snapshot(before[&"staff"])
|
||||
_runtime.inventory_service.restore_snapshot(before[&"inventory"])
|
||||
_runtime.logistics_dispatcher.restore_snapshot(before[&"dispatcher"])
|
||||
_runtime.domain_events.restore_snapshot(before[&"events"])
|
||||
_runtime.id_generator.restore_snapshot(before[&"ids"])
|
||||
var restored := LogisticsRequest.from_snapshot(before[&"request"])
|
||||
# Keep the Request identity while callers finish handling this transition.
|
||||
for property: Dictionary in restored.get_property_list():
|
||||
var name := StringName(property[&"name"])
|
||||
if name in [&"RefCounted", &"script"] or not (int(property[&"usage"]) & PROPERTY_USAGE_SCRIPT_VARIABLE):
|
||||
continue
|
||||
request.set(name, restored.get(name))
|
||||
_runtime.logistics_requests[request.request_id] = request
|
||||
|
||||
|
||||
func _reserved_stock_valid(request: LogisticsRequest) -> bool:
|
||||
return _reservation_quantities_valid(request, _runtime.inventory_service, true)
|
||||
|
||||
|
||||
func _has_storage_space(facility: FacilityInstance, incoming_weight: int) -> bool:
|
||||
var capacity := SupplyCatalog.storage_capacity(facility.definition_id)
|
||||
return capacity > 0 and SupplyCatalog.inventory_weight(_runtime.inventory_service, facility.local_inventory_id) + incoming_weight <= capacity
|
||||
|
||||
|
||||
func find_facility_access_path(start: Vector3i, facility: FacilityInstance) -> Dictionary:
|
||||
return _access_path(start, facility)
|
||||
|
||||
|
||||
func _access_path(start: Vector3i, facility: FacilityInstance) -> Dictionary:
|
||||
if facility == null:
|
||||
return {&"reachable": false}
|
||||
var cells: Dictionary = {}
|
||||
for cell: Vector3i in facility.occupied_cells:
|
||||
for delta: Vector3i in [Vector3i.ZERO, Vector3i.LEFT, Vector3i.RIGHT]:
|
||||
if _runtime.path_service.has_cell(cell + delta):
|
||||
cells[cell + delta] = true
|
||||
if cells.is_empty() and _runtime.path_service.has_cell(facility.origin):
|
||||
cells[facility.origin] = true
|
||||
var ordered: Array = cells.keys()
|
||||
ordered.sort_custom(func(a: Vector3i, b: Vector3i) -> bool:
|
||||
if a.z != b.z: return a.z < b.z
|
||||
if a.y != b.y: return a.y < b.y
|
||||
return a.x < b.x)
|
||||
var best: Array[Vector3i] = []
|
||||
var best_cost := 9223372036854775807
|
||||
for cell: Vector3i in ordered:
|
||||
var path: Array[Vector3i] = _runtime.path_service.find_path(start, cell, [WorldService.LAYER_FRONT, WorldService.LAYER_BACK], [&"staff"])
|
||||
var cost: int = _runtime.path_service.calculate_path_cost(path, [&"staff"]) if not path.is_empty() else -1
|
||||
if cost >= 0 and (best.is_empty() or cost < best_cost):
|
||||
best = path
|
||||
best_cost = cost
|
||||
return {&"reachable": not best.is_empty(), &"cell": best[-1] if not best.is_empty() else facility.origin, &"steps": maxi(0, best.size() - 1)}
|
||||
|
||||
|
||||
static func _arrived_for_work(staff: StaffRuntime, task: StaffTask, minute: int) -> bool:
|
||||
return task.state == StaffTask.State.WORKING and task.state_changed_at < minute and staff.current_cell == task.target_cell
|
||||
|
||||
|
||||
static func _cargo_id(staff_id: StringName) -> StringName:
|
||||
return StringName("cargo:%s" % staff_id)
|
||||
|
||||
|
||||
static func _request_ids(requests: Dictionary) -> Array[StringName]:
|
||||
var ids: Array[StringName] = []
|
||||
for id: StringName in _sorted_keys(requests):
|
||||
if String(id).begins_with(REQUEST_PREFIX):
|
||||
ids.append(id)
|
||||
return ids
|
||||
|
||||
|
||||
static func _sorted_keys(source: Dictionary) -> Array[StringName]:
|
||||
var ids: Array[StringName] = []
|
||||
for key: Variant in source:
|
||||
ids.append(StringName(key))
|
||||
ids.sort_custom(func(a: StringName, b: StringName) -> bool: return String(a) < String(b))
|
||||
return ids
|
||||
|
||||
|
||||
static func _active_task(staff: StaffService, request_id: StringName) -> StaffTask:
|
||||
for task: StaffTask in staff.get_tasks():
|
||||
if task.target_entity_id == request_id and task.task_type in [PICKUP_TYPE, DELIVERY_TYPE, RETURN_TYPE] and not task.is_terminal():
|
||||
return task
|
||||
return null
|
||||
|
||||
|
||||
static func _facility_for_inventory(facilities: FacilityService, inventory_id: StringName) -> FacilityInstance:
|
||||
for facility: FacilityInstance in facilities.get_instances():
|
||||
if facility.local_inventory_id == inventory_id:
|
||||
return facility
|
||||
return null
|
||||
|
||||
|
||||
static func _cargo_quantities(inventory: InventoryService, cargo_id: StringName) -> Dictionary:
|
||||
var quantities: Dictionary = {}
|
||||
for stack: Dictionary in inventory.get_stacks(cargo_id):
|
||||
var item_id := StringName(stack[&"item_id"])
|
||||
quantities[item_id] = int(quantities.get(item_id, 0)) + int(stack[&"quantity"])
|
||||
return quantities
|
||||
|
||||
|
||||
static func _quantities_cover(actual: Dictionary, requested: Dictionary) -> bool:
|
||||
for item_id: StringName in _sorted_keys(requested):
|
||||
if int(actual.get(item_id, 0)) < int(requested[item_id]):
|
||||
return false
|
||||
return true
|
||||
|
||||
|
||||
static func _reservation_quantities_valid(request: LogisticsRequest, inventory: InventoryService, active: bool) -> bool:
|
||||
var totals: Dictionary = {}
|
||||
var weight := 0
|
||||
var seen: Dictionary = {}
|
||||
if request.reservation_ids.is_empty():
|
||||
return false
|
||||
for id: StringName in request.reservation_ids:
|
||||
if seen.has(id):
|
||||
return false
|
||||
seen[id] = true
|
||||
var reservation := inventory.get_reservation(id)
|
||||
if reservation == null or reservation.requester_id != request.request_id \
|
||||
or reservation.owner_inventory_id != request.source_inventory_id:
|
||||
return false
|
||||
if active and (not reservation.is_active() or reservation.is_expired(inventory.current_minute) \
|
||||
or inventory.is_stack_expired(reservation.stack_id, inventory.current_minute)):
|
||||
return false
|
||||
if not active and reservation.state != InventoryReservation.State.CONSUMED:
|
||||
return false
|
||||
totals[reservation.item_id] = int(totals.get(reservation.item_id, 0)) + reservation.quantity
|
||||
if active:
|
||||
var stack := inventory.get_stack(reservation.stack_id)
|
||||
if stack.is_empty():
|
||||
return false
|
||||
weight += reservation.quantity * int(stack[&"unit_weight"])
|
||||
return totals == request.item_requirements and (not active or weight == request.total_weight)
|
||||
|
||||
|
||||
static func validate_crosslinks(requests: Dictionary, staff: StaffService, inventory: InventoryService, facilities: FacilityService) -> bool:
|
||||
var carrier_owners: Dictionary = {}
|
||||
var active_task_ids: Dictionary = {}
|
||||
for id: StringName in _request_ids(requests):
|
||||
var request: LogisticsRequest = requests[id]
|
||||
var source := _facility_for_inventory(facilities, request.source_inventory_id)
|
||||
var destination := _facility_for_inventory(facilities, request.destination_inventory_id)
|
||||
if not String(request.source_inventory_id).begins_with("facility.inventory:") or not String(request.destination_inventory_id).begins_with("facility.inventory:"):
|
||||
return false
|
||||
if not request.is_terminal() and (source == null or destination == null):
|
||||
return false
|
||||
var task := _active_task(staff, id)
|
||||
if request.state in [LogisticsRequest.State.RESERVED, LogisticsRequest.State.BLOCKED] or request.is_terminal():
|
||||
if task != null:
|
||||
return false
|
||||
if request.state == LogisticsRequest.State.RESERVED and not _reservation_quantities_valid(request, inventory, true):
|
||||
return false
|
||||
continue
|
||||
if request.state not in [LogisticsRequest.State.ASSIGNED, LogisticsRequest.State.PICKING_UP, LogisticsRequest.State.DELIVERING]:
|
||||
return false
|
||||
var worker := staff.get_staff(request.assigned_carrier_id)
|
||||
if worker == null or worker.role_id != &"porter" or carrier_owners.has(worker.staff_id) \
|
||||
or task == null or task.assigned_staff_id != worker.staff_id or worker.current_task_id != task.task_id \
|
||||
or task.state not in [StaffTask.State.RESERVED, StaffTask.State.MOVING, StaffTask.State.WORKING] \
|
||||
or task.interrupt_level != 0 or not task.required_items.is_empty() or not task.reservation_ids.is_empty():
|
||||
return false
|
||||
carrier_owners[worker.staff_id] = id
|
||||
active_task_ids[task.task_id] = true
|
||||
var loaded := request.state == LogisticsRequest.State.DELIVERING
|
||||
var endpoint := source if not loaded or task.task_type == RETURN_TYPE else destination
|
||||
if not _cell_touches_facility(task.target_cell, endpoint):
|
||||
return false
|
||||
if (loaded and task.task_type not in [DELIVERY_TYPE, RETURN_TYPE]) or (not loaded and task.task_type != PICKUP_TYPE) \
|
||||
or not String(task.task_id).begins_with("supply.%s.%s." % ["delivery" if loaded else "pickup", id]):
|
||||
return false
|
||||
if not _reservation_quantities_valid(request, inventory, not loaded):
|
||||
return false
|
||||
var cargo := _cargo_quantities(inventory, _cargo_id(worker.staff_id))
|
||||
if loaded:
|
||||
if worker.carried_inventory_id != _cargo_id(worker.staff_id) or cargo.is_empty():
|
||||
return false
|
||||
for item_id: StringName in _sorted_keys(cargo):
|
||||
if int(cargo[item_id]) > int(request.item_requirements.get(item_id, 0)):
|
||||
return false
|
||||
elif not cargo.is_empty() or not worker.carried_inventory_id.is_empty():
|
||||
return false
|
||||
for task: StaffTask in staff.get_tasks():
|
||||
if task.task_type in [PICKUP_TYPE, DELIVERY_TYPE, RETURN_TYPE] and not task.is_terminal() \
|
||||
and (not requests.has(task.target_entity_id) or not active_task_ids.has(task.task_id)):
|
||||
return false
|
||||
return true
|
||||
|
||||
|
||||
static func _cell_touches_facility(cell: Vector3i, facility: FacilityInstance) -> bool:
|
||||
for occupied: Vector3i in facility.occupied_cells:
|
||||
if cell.z == occupied.z and cell.y == occupied.y and absi(cell.x - occupied.x) <= 1:
|
||||
return true
|
||||
return cell == facility.origin
|
||||
|
||||
# Private r338 diagnostic fields; not persisted. Nested inclusive timings only.
|
||||
var _p23r338_metrics: Dictionary = {}
|
||||
|
||||
func tick(absolute_minute: int) -> Dictionary:
|
||||
var p23_started := Time.get_ticks_usec()
|
||||
var p23_result: Dictionary = _p23r338_originaltick(absolute_minute)
|
||||
var p23_elapsed := Time.get_ticks_usec() - p23_started
|
||||
var p23_key: String = "tick"
|
||||
var p23_row: Dictionary = _p23r338_metrics.get(p23_key, {"calls":0,"inclusive_us":0,"max_us":0})
|
||||
p23_row["calls"] = int(p23_row["calls"]) + 1
|
||||
p23_row["inclusive_us"] = int(p23_row["inclusive_us"]) + p23_elapsed
|
||||
p23_row["max_us"] = maxi(int(p23_row["max_us"]),p23_elapsed)
|
||||
_p23r338_metrics[p23_key] = p23_row
|
||||
return p23_result
|
||||
|
||||
+476
@@ -0,0 +1,476 @@
|
||||
class_name SupplyManagementService
|
||||
extends RefCounted
|
||||
|
||||
const PurchaseQuoteV2 := preload("res://scripts/supply/supply_purchase_quote_v2.gd")
|
||||
|
||||
## Player commands and deterministic replenishment. Vendor purchases arrive in
|
||||
## the selected warehouse; all transfers inside the tree use real porter tasks.
|
||||
|
||||
func preview_purchase(runtime: Variant, warehouse_id: StringName, item_id: StringName, quantity: int) -> Dictionary:
|
||||
# Keep the entire ordinary branch literal; only placed UNIQUE Mimi
|
||||
# selects the explicit total-order quote. No attendance/role/floor condition.
|
||||
if not PurchaseQuoteV2.eligible(runtime):
|
||||
return _preview_purchase_v1(runtime, warehouse_id, item_id, quantity)
|
||||
var quote := _preview_purchase_v1(runtime, warehouse_id, item_id, quantity)
|
||||
var item := SupplyCatalog.get_item(item_id)
|
||||
var facility: FacilityInstance = runtime.facility_service.get_instance(warehouse_id)
|
||||
if facility == null or facility.definition_id != &"warehouse" or item.is_empty() \
|
||||
or not bool(item.get(&"purchasable", false)) or quantity <= 0 or quantity > 10000: return quote
|
||||
var frozen := PurchaseQuoteV2.make(item_id, quantity, int(item[&"unit_price"]))
|
||||
if frozen.is_empty(): return quote
|
||||
var cash: int = runtime.economy_service.get_balance(&"PLAYER_CASH")
|
||||
var space: int = maxi(SupplyCatalog.storage_capacity(facility.definition_id) - SupplyCatalog.inventory_weight(runtime.inventory_service, facility.local_inventory_id) - _incoming_weight(runtime, facility.local_inventory_id), 0)
|
||||
@warning_ignore("integer_division")
|
||||
var slots := space / int(item[&"unit_weight"])
|
||||
quote[&"purchase_quote"] = frozen
|
||||
quote[&"total_cost"] = frozen[&"effective_total"]
|
||||
quote[&"cash_after"] = cash - int(frozen[&"effective_total"])
|
||||
quote[&"max_quantity"] = PurchaseQuoteV2.affordable_quantity(cash, slots, int(item[&"unit_price"]))
|
||||
quote[&"ok"] = false
|
||||
quote[&"reason"] = &""
|
||||
if not facility.allows_logistics():
|
||||
quote[&"reason"] = &"FACILITY_CLOSED"
|
||||
elif int(frozen[&"effective_total"]) > cash:
|
||||
quote[&"reason"] = &"INSUFFICIENT_FUNDS"
|
||||
elif quantity * int(item[&"unit_weight"]) > space:
|
||||
quote[&"reason"] = &"STORAGE_FULL"
|
||||
else:
|
||||
quote[&"ok"] = true
|
||||
return quote
|
||||
|
||||
|
||||
func _preview_purchase_v1(runtime: Variant, warehouse_id: StringName, item_id: StringName, quantity: int) -> Dictionary:
|
||||
var cash: int = runtime.economy_service.get_balance(&"PLAYER_CASH")
|
||||
var item := SupplyCatalog.get_item(item_id)
|
||||
var facility: FacilityInstance = runtime.facility_service.get_instance(warehouse_id)
|
||||
var quote := {&"ok": false, &"reason": &"", &"total_cost": 0, &"cash_after": cash, &"quantity_after": 0, &"max_quantity": 0}
|
||||
if facility == null or facility.definition_id != &"warehouse":
|
||||
quote[&"reason"] = &"NOT_WAREHOUSE"
|
||||
return quote
|
||||
if item.is_empty() or not bool(item.get(&"purchasable", false)):
|
||||
quote[&"reason"] = &"ITEM_NOT_PURCHASABLE"
|
||||
return quote
|
||||
var price := int(item[&"unit_price"])
|
||||
var space: int = maxi(SupplyCatalog.storage_capacity(facility.definition_id) - SupplyCatalog.inventory_weight(runtime.inventory_service, facility.local_inventory_id) - _incoming_weight(runtime, facility.local_inventory_id), 0)
|
||||
quote[&"max_quantity"] = mini(space / int(item[&"unit_weight"]), maxi(cash, 0) / price)
|
||||
quote[&"quantity_after"] = runtime.inventory_service.total_quantity(facility.local_inventory_id, item_id) + maxi(quantity, 0)
|
||||
quote[&"total_cost"] = maxi(quantity, 0) * price
|
||||
quote[&"cash_after"] = cash - int(quote[&"total_cost"])
|
||||
if quantity <= 0 or quantity > 10000:
|
||||
quote[&"reason"] = &"INVALID_QUANTITY"
|
||||
elif not facility.allows_logistics():
|
||||
quote[&"reason"] = &"FACILITY_CLOSED"
|
||||
elif int(quote[&"total_cost"]) > cash:
|
||||
quote[&"reason"] = &"INSUFFICIENT_FUNDS"
|
||||
elif quantity * int(item[&"unit_weight"]) > space:
|
||||
quote[&"reason"] = &"STORAGE_FULL"
|
||||
else:
|
||||
quote[&"ok"] = true
|
||||
return quote
|
||||
|
||||
|
||||
func purchase(runtime: Variant, command: SimulationCommand) -> CommandResult:
|
||||
var payload := command.payload
|
||||
if not _text(payload.get(&"warehouse_id")) or not _text(payload.get(&"item_id")) or not _integer(payload.get(&"quantity")):
|
||||
return _failure(command, &"INVALID_PAYLOAD")
|
||||
var warehouse_id := StringName(payload[&"warehouse_id"])
|
||||
var item_id := StringName(payload[&"item_id"])
|
||||
var quantity := int(payload[&"quantity"])
|
||||
return _purchase_paid(runtime, warehouse_id, item_id, quantity,
|
||||
runtime._runtime_event_minute(), StringName("supply.purchase.%d" % command.command_id), command.command_id)
|
||||
|
||||
|
||||
func _p23r338_original_purchase_paid(runtime: Variant, warehouse_id: StringName, item_id: StringName,
|
||||
quantity: int, minute: int, ledger_key: StringName, command_id: int = 0, record_auto_attempt: bool = false) -> CommandResult:
|
||||
# Shared transaction only; internal replenishment does not enqueue a command.
|
||||
var quote := preview_purchase(runtime, warehouse_id, item_id, quantity)
|
||||
if not bool(quote[&"ok"]):
|
||||
return _purchase_failure(command_id, StringName(quote[&"reason"]), quote)
|
||||
var facility: FacilityInstance = runtime.facility_service.get_instance(warehouse_id)
|
||||
var item := SupplyCatalog.get_item(item_id)
|
||||
var inventory_before: Dictionary = runtime.inventory_service.create_snapshot()
|
||||
var economy_before: Dictionary = runtime.economy_service.create_snapshot()
|
||||
var plans_before: Dictionary = runtime.auto_purchase_plans.create_snapshot() if record_auto_attempt else {}
|
||||
var stocked: Dictionary = runtime.inventory_service.add_stack(facility.local_inventory_id, item_id, quantity, 100, minute + int(item[&"shelf_life_minutes"]), minute, int(item[&"unit_weight"]))
|
||||
if not bool(stocked.get(&"ok", false)):
|
||||
runtime.inventory_service.restore_snapshot(inventory_before)
|
||||
runtime.economy_service.restore_snapshot(economy_before)
|
||||
return _purchase_failure(command_id, &"INVENTORY_ERROR")
|
||||
var memo: StringName = SupplyAutoPurchasePlans.receipt_memo(item_id, quantity, int(item[&"unit_price"]), int(quote[&"total_cost"])) if record_auto_attempt else &"supply_purchase"
|
||||
if quote.has(&"purchase_quote"):
|
||||
memo = PurchaseQuoteV2.receipt_memo(quote[&"purchase_quote"])
|
||||
var paid: CommandResult = runtime.economy_service.transfer(&"PLAYER_CASH", runtime.OPERATING_EXPENSE_ACCOUNT, int(quote[&"total_cost"]), minute, &"OPERATING_EXPENSE", warehouse_id, ledger_key, memo, &"", false)
|
||||
if not paid.is_success():
|
||||
runtime.inventory_service.restore_snapshot(inventory_before)
|
||||
runtime.economy_service.restore_snapshot(economy_before)
|
||||
return _purchase_failure(command_id, &"PAYMENT_FAILED")
|
||||
var recorded := true
|
||||
if record_auto_attempt:
|
||||
if quote.has(&"purchase_quote"):
|
||||
recorded = runtime.auto_purchase_plans.record_attempt(warehouse_id, item_id, minute, CommandResult.succeeded(0, {&"transaction_id": paid.details[&"transaction_id"], &"quantity": quantity, &"purchase_quote": quote[&"purchase_quote"], &"total_cost": quote[&"total_cost"]}), runtime.economy_service)
|
||||
else:
|
||||
recorded = runtime.auto_purchase_plans.record_attempt(warehouse_id, item_id, minute, CommandResult.succeeded(0, {&"transaction_id": paid.details[&"transaction_id"], &"quantity": quantity, &"unit_price": item[&"unit_price"], &"total_cost": quote[&"total_cost"]}), runtime.economy_service)
|
||||
if not recorded:
|
||||
runtime.inventory_service.restore_snapshot(inventory_before)
|
||||
runtime.economy_service.restore_snapshot(economy_before)
|
||||
return _purchase_failure(command_id, &"PAYMENT_FAILED")
|
||||
if not runtime.economy_service.commit_transaction_notification(StringName(paid.details[&"transaction_id"])):
|
||||
runtime.inventory_service.restore_snapshot(inventory_before)
|
||||
runtime.economy_service.restore_snapshot(economy_before)
|
||||
if record_auto_attempt:
|
||||
runtime.auto_purchase_plans.restore_snapshot(plans_before, runtime.facility_service, runtime.economy_service, minute)
|
||||
return _purchase_failure(command_id, &"PAYMENT_FAILED")
|
||||
quote.merge({&"warehouse_id": warehouse_id, &"item_id": item_id, &"quantity": quantity, &"transaction_id": paid.details[&"transaction_id"]})
|
||||
return CommandResult.succeeded(command_id, quote)
|
||||
|
||||
|
||||
func set_auto_purchase(runtime: Variant, command: SimulationCommand) -> CommandResult:
|
||||
var payload := command.payload
|
||||
if not _exact_keys(payload, [&"warehouse_id", &"item_id", &"enabled", &"target_stock"]) \
|
||||
or not _text(payload[&"warehouse_id"]) or not _text(payload[&"item_id"]) \
|
||||
or typeof(payload[&"enabled"]) != TYPE_BOOL or typeof(payload[&"target_stock"]) != TYPE_INT:
|
||||
return _failure(command, &"INVALID_PAYLOAD")
|
||||
var changed: Dictionary = runtime.auto_purchase_plans.set_plan(
|
||||
StringName(payload[&"warehouse_id"]), StringName(payload[&"item_id"]),
|
||||
payload[&"enabled"], payload[&"target_stock"], runtime.facility_service)
|
||||
if not bool(changed.get(&"ok", false)):
|
||||
return _failure(command, StringName(changed.get(&"reason", &"INVALID_TARGET")), changed)
|
||||
return CommandResult.succeeded(command.command_id, changed[&"plan"])
|
||||
|
||||
|
||||
func auto_purchase_report(runtime: Variant, warehouse_id: StringName, item_id: StringName) -> Dictionary:
|
||||
var row: Dictionary = runtime.auto_purchase_plans.get_plan(warehouse_id, item_id)
|
||||
var facility: FacilityInstance = runtime.facility_service.get_instance(warehouse_id)
|
||||
row[&"maximum_target"] = SupplyAutoPurchasePlans.maximum_target(warehouse_id, item_id, runtime.facility_service)
|
||||
row[&"physical_quantity"] = runtime.inventory_service.total_quantity(facility.local_inventory_id, item_id) if facility != null else 0
|
||||
row[&"incoming_quantity"] = _incoming_quantity(runtime, facility.local_inventory_id, item_id) if facility != null else 0
|
||||
row[&"deficit"] = maxi(int(row[&"target_stock"]) - int(row[&"physical_quantity"]) - int(row[&"incoming_quantity"]), 0)
|
||||
row[&"quote"] = preview_purchase(runtime, warehouse_id, item_id, int(row[&"deficit"])) if int(row[&"deficit"]) > 0 else {}
|
||||
row[&"reason"] = &""
|
||||
if not bool(row[&"enabled"]):
|
||||
row[&"state"] = &"DISABLED"
|
||||
elif bool(runtime.get_operations_report().get(&"tick_blocked", false)):
|
||||
row[&"state"] = &"BLOCKED"
|
||||
row[&"reason"] = &"OPERATIONS_BLOCKED"
|
||||
elif int(runtime._state.get_resource(&"mana")) <= 0:
|
||||
row[&"state"] = &"BLOCKED"
|
||||
row[&"reason"] = &"NO_POWER"
|
||||
elif _receiver_will_close(facility, runtime._clock.absolute_minute):
|
||||
row[&"state"] = &"BLOCKED"
|
||||
row[&"reason"] = &"FACILITY_CLOSED"
|
||||
elif int(row[&"last_attempt_minute"]) == runtime._clock.absolute_minute:
|
||||
row[&"state"] = &"ORDERED_THIS_MINUTE" if row[&"last_result"] == SupplyAutoPurchasePlans.RESULT_PURCHASED else &"BLOCKED"
|
||||
if row[&"state"] == &"BLOCKED": row[&"reason"] = row[&"last_result"]
|
||||
elif int(row[&"deficit"]) == 0:
|
||||
row[&"state"] = &"TARGET_REACHED"
|
||||
elif bool((row[&"quote"] as Dictionary).get(&"ok", false)):
|
||||
row[&"state"] = &"READY"
|
||||
else:
|
||||
row[&"state"] = &"BLOCKED"
|
||||
row[&"reason"] = (row[&"quote"] as Dictionary).get(&"reason", &"UNAVAILABLE")
|
||||
return row
|
||||
|
||||
|
||||
func _p23r338_originaladvance_auto_purchases(runtime: Variant, minute: int) -> Array[Dictionary]:
|
||||
var results: Array[Dictionary] = []
|
||||
if bool(runtime.get_operations_report().get(&"tick_blocked", false)) or int(runtime._state.get_resource(&"mana")) <= 0:
|
||||
return results
|
||||
for plan: Dictionary in runtime.auto_purchase_plans.get_plans():
|
||||
if not bool(plan[&"enabled"]) or int(plan[&"last_attempt_minute"]) >= minute:
|
||||
continue
|
||||
var warehouse_id := StringName(plan[&"warehouse_id"])
|
||||
var item_id := StringName(plan[&"item_id"])
|
||||
var row := auto_purchase_report(runtime, warehouse_id, item_id)
|
||||
var facility: FacilityInstance = runtime.facility_service.get_instance(warehouse_id)
|
||||
if int(row[&"deficit"]) <= 0 or facility == null or not facility.allows_logistics() or _receiver_will_close(facility, minute):
|
||||
continue
|
||||
var ledger_key := SupplyAutoPurchasePlans.order_key(warehouse_id, item_id, minute)
|
||||
var prior_id: StringName = runtime.economy_service.get_transaction_id_for_idempotency_key(ledger_key)
|
||||
var result: CommandResult
|
||||
if prior_id.is_empty():
|
||||
if row[&"state"] != &"READY" or not bool((row[&"quote"] as Dictionary).get(&"ok", false)):
|
||||
continue
|
||||
result = _purchase_paid(runtime, warehouse_id, item_id, int(row[&"deficit"]), minute, ledger_key, 0, true)
|
||||
else:
|
||||
# A committed key replays its original item/quantity/price, even if
|
||||
# today's quote is unaffordable. It never stocks, charges or notifies.
|
||||
var receipt := SupplyAutoPurchasePlans.receipt_from_ledger(runtime.economy_service, warehouse_id, item_id, minute, prior_id)
|
||||
if receipt.is_empty():
|
||||
var frozen := PurchaseQuoteV2.receipt_from_ledger(runtime.economy_service, warehouse_id, item_id, minute, prior_id)
|
||||
if frozen.is_empty():
|
||||
result = _purchase_failure(0, &"REPLAY_MISMATCH")
|
||||
else:
|
||||
result = CommandResult.succeeded(0, {&"transaction_id": prior_id, &"quantity": frozen[&"quantity"], &"purchase_quote": frozen, &"total_cost": frozen[&"effective_total"], &"replayed": true})
|
||||
else:
|
||||
result = CommandResult.succeeded(0, {&"transaction_id": prior_id, &"quantity": receipt[&"quantity"], &"unit_price": receipt[&"unit_price"], &"total_cost": receipt[&"total_cost"], &"replayed": true})
|
||||
if (not result.is_success() or not prior_id.is_empty()) and not runtime.auto_purchase_plans.record_attempt(warehouse_id, item_id, minute, result, runtime.economy_service):
|
||||
push_error("Automatic purchase could not record its committed attempt.")
|
||||
return results
|
||||
results.append({&"warehouse_id": warehouse_id, &"item_id": item_id,
|
||||
&"minute": minute, &"result": result.to_dictionary()})
|
||||
return results
|
||||
|
||||
|
||||
func _receiver_will_close(facility: FacilityInstance, minute: int) -> bool:
|
||||
# LOGISTICS precedes FACILITY_COMPLETION. Honor an already scheduled close
|
||||
# without applying policy early or changing manual purchase/phase ordering.
|
||||
return facility != null and facility.policy_pending_effective_at >= 0 \
|
||||
and facility.policy_pending_effective_at <= minute \
|
||||
and facility.policy_pending.has(&"business_open") \
|
||||
and not bool(facility.policy_pending[&"business_open"])
|
||||
|
||||
|
||||
func _purchase_failure(command_id: int, reason: StringName, details: Dictionary = {}) -> CommandResult:
|
||||
var result := details.duplicate(true)
|
||||
result[&"reason"] = reason
|
||||
return CommandResult.failed(CommandResult.Code.VALIDATION_FAILED, command_id, "Supply command rejected: %s" % reason, result)
|
||||
|
||||
|
||||
func _exact_keys(value: Dictionary, expected: Array[StringName]) -> bool:
|
||||
if value.size() != expected.size(): return false
|
||||
for key: Variant in value:
|
||||
if typeof(key) not in [TYPE_STRING, TYPE_STRING_NAME] or StringName(key) not in expected: return false
|
||||
return true
|
||||
|
||||
|
||||
func set_production(runtime: Variant, command: SimulationCommand) -> CommandResult:
|
||||
var payload := command.payload
|
||||
if not _text(payload.get(&"facility_id")) or not payload.get(&"enabled") is bool or not _integer(payload.get(&"target_stock")):
|
||||
return _failure(command, &"INVALID_PAYLOAD")
|
||||
var facility_id := StringName(payload[&"facility_id"])
|
||||
var facility: FacilityInstance = runtime.facility_service.get_instance(facility_id)
|
||||
if facility == null or facility.definition_id != &"kitchen":
|
||||
return _failure(command, &"NOT_KITCHEN")
|
||||
var result: Dictionary = runtime.kitchen_production.set_plan(facility_id, bool(payload[&"enabled"]), int(payload[&"target_stock"]))
|
||||
if not bool(result.get(&"ok", false)):
|
||||
return _failure(command, StringName(result.get(&"code", &"INVALID_TARGET")), result)
|
||||
return CommandResult.succeeded(command.command_id, result)
|
||||
|
||||
|
||||
func get_report(runtime: Variant) -> Dictionary:
|
||||
var warehouses: Array[Dictionary] = []
|
||||
var kitchens: Array[Dictionary] = []
|
||||
var destinations: Array[Dictionary] = []
|
||||
for facility: FacilityInstance in _facilities(runtime):
|
||||
var row := _facility_row(runtime, facility)
|
||||
match facility.definition_id:
|
||||
&"warehouse":
|
||||
var quote := preview_purchase(runtime, facility.instance_id, SupplyCatalog.RAW_FOOD, 1)
|
||||
row[&"can_receive"] = bool(quote[&"ok"])
|
||||
row[&"reason_codes"] = [] if bool(quote[&"ok"]) else [quote[&"reason"]]
|
||||
row[&"auto_purchase_plans"] = []
|
||||
for item: Dictionary in SupplyCatalog.get_purchase_items():
|
||||
(row[&"auto_purchase_plans"] as Array).append(auto_purchase_report(runtime, facility.instance_id, StringName(item[&"item_id"])))
|
||||
warehouses.append(row)
|
||||
&"kitchen":
|
||||
row.merge(runtime.kitchen_production.get_report(facility.instance_id), true)
|
||||
row.merge({&"target_min": 4, &"target_step": 4, &"target_max": SupplyCatalog.KITCHEN_TARGET_MAX, &"inputs": {SupplyCatalog.RAW_FOOD: 4}, &"outputs": {SupplyCatalog.BASIC_MEAL: 4}}, true)
|
||||
row[&"reason_codes"] = [] if row[&"state"] in [&"PRODUCING", &"READY", &"TARGET_REACHED"] else [row[&"state"]]
|
||||
kitchens.append(row)
|
||||
&"cafeteria":
|
||||
row[&"missing_items"] = {SupplyCatalog.BASIC_MEAL: maxi(12 - runtime.inventory_service.available_quantity(facility.local_inventory_id, SupplyCatalog.BASIC_MEAL), 0)}
|
||||
row[&"reason_codes"] = facility.state_reasons.duplicate()
|
||||
if runtime.inventory_service.available_quantity(facility.local_inventory_id, SupplyCatalog.BASIC_MEAL) <= 0:
|
||||
row[&"reason_codes"].append(&"NO_INPUT")
|
||||
destinations.append(row)
|
||||
var bridge_report: Dictionary = runtime.supply_logistics.get_report()
|
||||
return {&"cash": runtime.economy_service.get_balance(&"PLAYER_CASH"), &"catalog": SupplyCatalog.get_purchase_items(), &"warehouses": warehouses, &"kitchens": kitchens, &"destinations": destinations, &"deliveries": bridge_report.get(&"deliveries", [])}
|
||||
|
||||
|
||||
func _p23r338_originalensure_deliveries(runtime: Variant, minute: int) -> void:
|
||||
var facilities := _facilities(runtime)
|
||||
for destination: FacilityInstance in facilities:
|
||||
if not destination.allows_logistics():
|
||||
continue
|
||||
var source_type: StringName
|
||||
var item_id: StringName
|
||||
var target := 0
|
||||
if destination.definition_id == &"kitchen" and bool(runtime.kitchen_production.get_plan(destination.instance_id).get(&"enabled", false)):
|
||||
source_type = &"warehouse"
|
||||
item_id = SupplyCatalog.RAW_FOOD
|
||||
target = SupplyCatalog.RAW_TARGET
|
||||
elif destination.definition_id == &"cafeteria":
|
||||
source_type = &"kitchen"
|
||||
item_id = SupplyCatalog.BASIC_MEAL
|
||||
target = 12
|
||||
else:
|
||||
continue
|
||||
var deficit: int = target - runtime.inventory_service.total_quantity(destination.local_inventory_id, item_id) - _incoming_quantity(runtime, destination.local_inventory_id, item_id)
|
||||
var space: int = SupplyCatalog.storage_capacity(destination.definition_id) - SupplyCatalog.inventory_weight(runtime.inventory_service, destination.local_inventory_id) - _incoming_weight(runtime, destination.local_inventory_id)
|
||||
var needed: int = mini(mini(deficit, space), 4)
|
||||
if needed <= 0:
|
||||
continue
|
||||
var sources: Array[Dictionary] = []
|
||||
for source: FacilityInstance in facilities:
|
||||
if source.definition_id != source_type or not source.allows_logistics():
|
||||
continue
|
||||
if source_type == &"kitchen" and not _has_production_plan(runtime, source.instance_id):
|
||||
continue
|
||||
var available: int = runtime.inventory_service.available_quantity(source.local_inventory_id, item_id, minute)
|
||||
if available <= 0:
|
||||
continue
|
||||
sources.append({&"facility": source, &"available": available, &"distance": _connection_distance(runtime, source, destination)})
|
||||
# Prefer a connected nearby supplier; IDs resolve equal routes stably.
|
||||
# If none is connected, retain one visible request for route repair.
|
||||
sources.sort_custom(func(a: Dictionary, b: Dictionary) -> bool:
|
||||
if a[&"distance"] != b[&"distance"]: return a[&"distance"] < b[&"distance"]
|
||||
return String(a[&"facility"].instance_id) < String(b[&"facility"].instance_id))
|
||||
for source_row: Dictionary in sources:
|
||||
var source: FacilityInstance = source_row[&"facility"]
|
||||
var available := int(source_row[&"available"])
|
||||
var ids_before: Dictionary = runtime.id_generator.create_snapshot()
|
||||
var request_id := StringName("supply.%s" % runtime.id_generator.next_id(&"logistics_request"))
|
||||
var result: CommandResult = runtime._execute_create_logistics_request(SimulationCommand.new(0, minute, minute, 50, &"create_logistics_request", &"supply", destination.instance_id, {&"request_id": request_id, &"source_inventory_id": source.local_inventory_id, &"destination_inventory_id": destination.local_inventory_id, &"item_requirements": {item_id: mini(needed, available)}, &"priority": 50}))
|
||||
if not result.is_success():
|
||||
runtime.id_generator.restore_snapshot(ids_before)
|
||||
break
|
||||
|
||||
|
||||
func validate_demolition(runtime: Variant, facility_id: StringName) -> Dictionary:
|
||||
var facility: FacilityInstance = runtime.facility_service.get_instance(facility_id)
|
||||
if facility == null:
|
||||
return {&"ok": true}
|
||||
if SupplyCatalog.inventory_weight(runtime.inventory_service, facility.local_inventory_id) > 0:
|
||||
return {&"ok": false, &"reason": &"STOCK_REMAINS"}
|
||||
for request: LogisticsRequest in runtime.logistics_requests.values():
|
||||
if not request.is_terminal() and facility.local_inventory_id in [request.source_inventory_id, request.destination_inventory_id]:
|
||||
return {&"ok": false, &"reason": &"DELIVERY_ACTIVE"}
|
||||
if facility.definition_id == &"kitchen":
|
||||
var report: Dictionary = runtime.kitchen_production.get_report(facility_id)
|
||||
if bool(report.get(&"enabled", false)) or not report.get(&"active_batch", {}).is_empty():
|
||||
return {&"ok": false, &"reason": &"PRODUCTION_ACTIVE"}
|
||||
return {&"ok": true}
|
||||
|
||||
|
||||
func _facility_row(runtime: Variant, facility: FacilityInstance) -> Dictionary:
|
||||
var definition: FacilityDefinition = runtime.definition_registry.get_facility(facility.definition_id)
|
||||
return {&"facility_id": facility.instance_id, &"display_name": definition.display_name, &"origin": facility.origin, &"layer": facility.origin.z, &"used": SupplyCatalog.inventory_weight(runtime.inventory_service, facility.local_inventory_id), &"capacity": SupplyCatalog.storage_capacity(facility.definition_id), &"stock": _stock(runtime, facility.local_inventory_id)}
|
||||
|
||||
|
||||
func _stock(runtime: Variant, inventory_id: StringName) -> Array[Dictionary]:
|
||||
var rows: Array[Dictionary] = []
|
||||
for item_id: StringName in [SupplyCatalog.RAW_FOOD, SupplyCatalog.BASIC_MEAL]:
|
||||
var total: int = runtime.inventory_service.total_quantity(inventory_id, item_id)
|
||||
var available: int = runtime.inventory_service.available_quantity(inventory_id, item_id)
|
||||
rows.append({&"item_id": item_id, &"total": total, &"available": available, &"reserved": total - available, &"in_transit": _incoming_quantity(runtime, inventory_id, item_id)})
|
||||
return rows
|
||||
|
||||
|
||||
func _incoming_quantity(runtime: Variant, inventory_id: StringName, item_id: StringName) -> int:
|
||||
var quantity := 0
|
||||
for request: LogisticsRequest in runtime.logistics_requests.values():
|
||||
if request.is_terminal():
|
||||
continue
|
||||
if runtime.supply_logistics.is_returning(request.request_id):
|
||||
if request.source_inventory_id == inventory_id:
|
||||
quantity += runtime.inventory_service.total_quantity(StringName("cargo:%s" % request.assigned_carrier_id), item_id)
|
||||
elif request.destination_inventory_id == inventory_id:
|
||||
quantity += int(request.item_requirements.get(item_id, 0))
|
||||
return quantity
|
||||
|
||||
|
||||
func _incoming_weight(runtime: Variant, inventory_id: StringName) -> int:
|
||||
var weight := 0
|
||||
for request: LogisticsRequest in runtime.logistics_requests.values():
|
||||
if request.is_terminal():
|
||||
continue
|
||||
if runtime.supply_logistics.is_returning(request.request_id):
|
||||
if request.source_inventory_id == inventory_id:
|
||||
weight += SupplyCatalog.inventory_weight(runtime.inventory_service, StringName("cargo:%s" % request.assigned_carrier_id))
|
||||
elif request.destination_inventory_id == inventory_id:
|
||||
weight += request.total_weight
|
||||
return weight
|
||||
|
||||
|
||||
func _facilities(runtime: Variant) -> Array[FacilityInstance]:
|
||||
var rows: Array[FacilityInstance] = runtime.facility_service.get_instances()
|
||||
rows.sort_custom(func(a: FacilityInstance, b: FacilityInstance) -> bool: return String(a.instance_id) < String(b.instance_id))
|
||||
return rows
|
||||
|
||||
|
||||
func _failure(command: SimulationCommand, reason: StringName, details: Dictionary = {}) -> CommandResult:
|
||||
var result := details.duplicate(true)
|
||||
result[&"reason"] = reason
|
||||
return CommandResult.failed(CommandResult.Code.VALIDATION_FAILED, command.command_id, "Supply command rejected: %s" % reason, result)
|
||||
|
||||
|
||||
func _text(value: Variant) -> bool:
|
||||
return (value is String or value is StringName) and not String(value).is_empty()
|
||||
|
||||
|
||||
func _integer(value: Variant) -> bool:
|
||||
return value is int or (value is float and is_finite(value) and value == floor(value) and absf(value) <= 1000000.0)
|
||||
|
||||
|
||||
func _has_production_plan(runtime: Variant, facility_id: StringName) -> bool:
|
||||
for plan: Dictionary in runtime.kitchen_production.get_plans():
|
||||
if StringName(plan[&"facility_id"]) == facility_id:
|
||||
return true
|
||||
return false
|
||||
|
||||
|
||||
func _p23r338_original_connection_distance(runtime: Variant, source: FacilityInstance, destination: FacilityInstance) -> int:
|
||||
var distance := 1000000
|
||||
var seen: Dictionary = {}
|
||||
for cell: Vector3i in source.occupied_cells:
|
||||
for delta: Vector3i in [Vector3i.ZERO, Vector3i.LEFT, Vector3i.RIGHT, Vector3i.UP, Vector3i.DOWN]:
|
||||
var start := cell + delta
|
||||
if seen.has(start) or not runtime.path_service.has_cell(start):
|
||||
continue
|
||||
seen[start] = true
|
||||
var route: Dictionary = runtime.supply_logistics.find_facility_access_path(start, destination)
|
||||
if bool(route.get(&"reachable", false)):
|
||||
distance = mini(distance, int(route[&"steps"]))
|
||||
return distance
|
||||
|
||||
# Private r338 diagnostic fields; not persisted. Nested inclusive timings only.
|
||||
var _p23r338_metrics: Dictionary = {}
|
||||
|
||||
func advance_auto_purchases(runtime: Variant, minute: int) -> Array[Dictionary]:
|
||||
var p23_started := Time.get_ticks_usec()
|
||||
var p23_result: Array[Dictionary] = _p23r338_originaladvance_auto_purchases(runtime, minute)
|
||||
var p23_elapsed := Time.get_ticks_usec() - p23_started
|
||||
var p23_key: String = "advance_auto_purchases"
|
||||
var p23_row: Dictionary = _p23r338_metrics.get(p23_key, {"calls":0,"inclusive_us":0,"max_us":0})
|
||||
p23_row["calls"] = int(p23_row["calls"]) + 1
|
||||
p23_row["inclusive_us"] = int(p23_row["inclusive_us"]) + p23_elapsed
|
||||
p23_row["max_us"] = maxi(int(p23_row["max_us"]),p23_elapsed)
|
||||
_p23r338_metrics[p23_key] = p23_row
|
||||
return p23_result
|
||||
|
||||
func ensure_deliveries(runtime: Variant, minute: int) -> void:
|
||||
var p23_started := Time.get_ticks_usec()
|
||||
_p23r338_originalensure_deliveries(runtime, minute)
|
||||
var p23_elapsed := Time.get_ticks_usec() - p23_started
|
||||
var p23_key: String = "ensure_deliveries"
|
||||
var p23_row: Dictionary = _p23r338_metrics.get(p23_key, {"calls":0,"inclusive_us":0,"max_us":0})
|
||||
p23_row["calls"] = int(p23_row["calls"]) + 1
|
||||
p23_row["inclusive_us"] = int(p23_row["inclusive_us"]) + p23_elapsed
|
||||
p23_row["max_us"] = maxi(int(p23_row["max_us"]),p23_elapsed)
|
||||
_p23r338_metrics[p23_key] = p23_row
|
||||
|
||||
func _connection_distance(runtime: Variant, source: FacilityInstance, destination: FacilityInstance) -> int:
|
||||
var p23_started := Time.get_ticks_usec()
|
||||
var p23_result: int = _p23r338_original_connection_distance(runtime, source, destination)
|
||||
var p23_elapsed := Time.get_ticks_usec() - p23_started
|
||||
var p23_key: String = "_connection_distance"
|
||||
var p23_row: Dictionary = _p23r338_metrics.get(p23_key, {"calls":0,"inclusive_us":0,"max_us":0})
|
||||
p23_row["calls"] = int(p23_row["calls"]) + 1
|
||||
p23_row["inclusive_us"] = int(p23_row["inclusive_us"]) + p23_elapsed
|
||||
p23_row["max_us"] = maxi(int(p23_row["max_us"]),p23_elapsed)
|
||||
_p23r338_metrics[p23_key] = p23_row
|
||||
return p23_result
|
||||
|
||||
func _purchase_paid(runtime: Variant, warehouse_id: StringName, item_id: StringName,
|
||||
quantity: int, minute: int, ledger_key: StringName, command_id: int = 0, record_auto_attempt: bool = false) -> CommandResult:
|
||||
var p23_started := Time.get_ticks_usec()
|
||||
var p23_result: CommandResult = _p23r338_original_purchase_paid(runtime, warehouse_id, item_id, quantity, minute, ledger_key, command_id, record_auto_attempt)
|
||||
var p23_elapsed := Time.get_ticks_usec() - p23_started
|
||||
var p23_key: String = "_purchase_paid"
|
||||
var p23_row: Dictionary = _p23r338_metrics.get(p23_key, {"calls":0,"inclusive_us":0,"max_us":0})
|
||||
p23_row["calls"] = int(p23_row["calls"]) + 1
|
||||
p23_row["inclusive_us"] = int(p23_row["inclusive_us"]) + p23_elapsed
|
||||
p23_row["max_us"] = maxi(int(p23_row["max_us"]),p23_elapsed)
|
||||
_p23r338_metrics[p23_key] = p23_row
|
||||
return p23_result
|
||||
|
||||
BIN
Binary file not shown.
+261
@@ -0,0 +1,261 @@
|
||||
class_name SimulationKernel
|
||||
extends Node
|
||||
|
||||
signal time_changed(day: int, hour: int, minute: int)
|
||||
signal day_started(day: int)
|
||||
signal settlement_requested(day: int)
|
||||
signal tick_started(absolute_minute: int)
|
||||
signal tick_phase_started(phase: TickPhase, absolute_minute: int)
|
||||
signal tick_completed(absolute_minute: int)
|
||||
signal simulation_overloaded(backlog_minutes: int)
|
||||
|
||||
enum TickPhase {
|
||||
APPLY_COMMANDS,
|
||||
TIME_BOUNDARIES,
|
||||
MANA,
|
||||
CONSTRUCTION,
|
||||
LOGISTICS,
|
||||
FACILITY_COMPLETION,
|
||||
VITALS_AND_ENVIRONMENT,
|
||||
INCIDENTS_AND_EVENTS,
|
||||
FACILITY_QUEUES,
|
||||
AI_DECISIONS,
|
||||
PUBLISH_SNAPSHOT,
|
||||
}
|
||||
|
||||
const MINUTES_PER_DAY := 24 * 60
|
||||
const START_ABSOLUTE_MINUTE := 6 * 60
|
||||
const REAL_SECONDS_PER_GAME_HOUR := 10.0
|
||||
const REAL_SECONDS_PER_GAME_MINUTE := REAL_SECONDS_PER_GAME_HOUR / 60.0
|
||||
const MAX_TICKS_PER_FRAME := 8
|
||||
const MAX_BACKLOG_MINUTES := 120
|
||||
|
||||
var absolute_minute := START_ABSOLUTE_MINUTE
|
||||
var day := 1
|
||||
var minute_of_day := START_ABSOLUTE_MINUTE
|
||||
var speed := 1
|
||||
var paused := false
|
||||
var snapshot_version := 0
|
||||
var performance_budget := SimulationPerformanceBudget.new()
|
||||
|
||||
var _accumulator := 0.0
|
||||
var _skip_next_process := false
|
||||
var _phase_handlers: Dictionary = {}
|
||||
var _pause_request_serial := 0
|
||||
var _abort_current_tick_requested := false
|
||||
var _last_tick_advanced := false
|
||||
|
||||
func _ready() -> void:
|
||||
_emit_current_time()
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
process_real_delta(delta)
|
||||
|
||||
func process_real_delta(delta: float) -> int:
|
||||
if _skip_next_process:
|
||||
_skip_next_process = false
|
||||
return 0
|
||||
if paused or speed <= 0 or delta <= 0.0:
|
||||
return 0
|
||||
|
||||
var frame_started_at_us := Time.get_ticks_usec()
|
||||
_accumulator += delta * speed
|
||||
var due_ticks := int(_accumulator / REAL_SECONDS_PER_GAME_MINUTE)
|
||||
var tick_budget := mini(due_ticks, MAX_TICKS_PER_FRAME)
|
||||
var ticks_run := 0
|
||||
for _index in range(tick_budget):
|
||||
if paused:
|
||||
break
|
||||
advance_one_minute()
|
||||
if not _last_tick_advanced:
|
||||
break
|
||||
_accumulator -= REAL_SECONDS_PER_GAME_MINUTE
|
||||
ticks_run += 1
|
||||
# A boundary handler may pause in the middle of a catch-up frame. Never
|
||||
# consume another queued minute after that decision.
|
||||
if paused:
|
||||
break
|
||||
if ticks_run > 0:
|
||||
performance_budget.record_simulation_frame(
|
||||
int(Time.get_ticks_usec() - frame_started_at_us),
|
||||
speed,
|
||||
ticks_run
|
||||
)
|
||||
|
||||
var backlog_minutes := get_backlog_minutes()
|
||||
if backlog_minutes > MAX_BACKLOG_MINUTES:
|
||||
paused = true
|
||||
simulation_overloaded.emit(backlog_minutes)
|
||||
return ticks_run
|
||||
|
||||
func reset(start_day := 1, start_hour := 6, start_minute := 0) -> void:
|
||||
var safe_day := maxi(start_day, 1)
|
||||
var safe_minute := posmod(start_hour * 60 + start_minute, MINUTES_PER_DAY)
|
||||
absolute_minute = (safe_day - 1) * MINUTES_PER_DAY + safe_minute
|
||||
_sync_calendar_fields()
|
||||
_accumulator = 0.0
|
||||
paused = false
|
||||
snapshot_version = 0
|
||||
performance_budget.clear()
|
||||
_abort_current_tick_requested = false
|
||||
_last_tick_advanced = false
|
||||
_emit_current_time()
|
||||
|
||||
func advance_minutes(amount: int) -> void:
|
||||
if amount <= 0:
|
||||
return
|
||||
# Tests and deterministic tooling historically use an already-paused clock as
|
||||
# an explicit manual stepping mode. Preserve that contract, while a pause
|
||||
# raised during an initially-running batch is a hard boundary stop.
|
||||
var manual_paused_stepping := paused
|
||||
var pause_serial_before := _pause_request_serial
|
||||
for _index in range(amount):
|
||||
if not manual_paused_stepping and paused:
|
||||
break
|
||||
advance_one_minute()
|
||||
if not _last_tick_advanced:
|
||||
break
|
||||
if _pause_request_serial != pause_serial_before \
|
||||
or (not manual_paused_stepping and paused):
|
||||
break
|
||||
|
||||
func advance_one_minute() -> void:
|
||||
_abort_current_tick_requested = false
|
||||
_last_tick_advanced = false
|
||||
tick_started.emit(absolute_minute)
|
||||
_run_phase(TickPhase.APPLY_COMMANDS)
|
||||
# A Runtime gate can reject the tick before the Clock changes. This is
|
||||
# distinct from an ordinary pause raised by a command that already committed
|
||||
# for the upcoming minute.
|
||||
if _abort_current_tick_requested:
|
||||
_abort_current_tick_requested = false
|
||||
return
|
||||
|
||||
var previous_absolute_minute := absolute_minute
|
||||
absolute_minute += 1
|
||||
_sync_calendar_fields()
|
||||
_handle_time_boundaries(previous_absolute_minute)
|
||||
_run_phase(TickPhase.TIME_BOUNDARIES)
|
||||
|
||||
for phase in [
|
||||
TickPhase.MANA,
|
||||
TickPhase.CONSTRUCTION,
|
||||
TickPhase.LOGISTICS,
|
||||
TickPhase.FACILITY_COMPLETION,
|
||||
TickPhase.VITALS_AND_ENVIRONMENT,
|
||||
TickPhase.INCIDENTS_AND_EVENTS,
|
||||
TickPhase.FACILITY_QUEUES,
|
||||
TickPhase.AI_DECISIONS,
|
||||
TickPhase.PUBLISH_SNAPSHOT,
|
||||
]:
|
||||
_run_phase(phase)
|
||||
|
||||
snapshot_version += 1
|
||||
tick_completed.emit(absolute_minute)
|
||||
_emit_current_time()
|
||||
_abort_current_tick_requested = false
|
||||
_last_tick_advanced = true
|
||||
|
||||
func request_current_tick_abort() -> void:
|
||||
_abort_current_tick_requested = true
|
||||
|
||||
func set_speed(value: int) -> bool:
|
||||
if value not in [1, 2, 3]:
|
||||
return false
|
||||
speed = value
|
||||
paused = false
|
||||
return true
|
||||
|
||||
func toggle_pause() -> bool:
|
||||
paused = not paused
|
||||
if paused:
|
||||
_pause_request_serial += 1
|
||||
return paused
|
||||
|
||||
func set_paused(value: bool) -> void:
|
||||
paused = value
|
||||
if value:
|
||||
_pause_request_serial += 1
|
||||
|
||||
func get_hour() -> int:
|
||||
return minute_of_day / 60
|
||||
|
||||
func get_minute() -> int:
|
||||
return minute_of_day % 60
|
||||
|
||||
func get_backlog_minutes() -> int:
|
||||
return int(_accumulator / REAL_SECONDS_PER_GAME_MINUTE)
|
||||
|
||||
func get_performance_reports() -> Array[Dictionary]:
|
||||
return performance_budget.get_all_reports()
|
||||
|
||||
func register_tick_handler(phase: TickPhase, handler_id: StringName, callback: Callable) -> bool:
|
||||
if handler_id.is_empty() or not callback.is_valid():
|
||||
return false
|
||||
if not _phase_handlers.has(phase):
|
||||
_phase_handlers[phase] = {}
|
||||
var handlers: Dictionary = _phase_handlers[phase]
|
||||
if handlers.has(handler_id):
|
||||
return false
|
||||
handlers[handler_id] = callback
|
||||
return true
|
||||
|
||||
func unregister_tick_handler(phase: TickPhase, handler_id: StringName) -> void:
|
||||
if not _phase_handlers.has(phase):
|
||||
return
|
||||
var handlers: Dictionary = _phase_handlers[phase]
|
||||
handlers.erase(handler_id)
|
||||
|
||||
func clock_snapshot() -> Dictionary:
|
||||
return {
|
||||
&"absolute_minute": absolute_minute,
|
||||
&"speed": speed,
|
||||
&"paused": paused,
|
||||
&"snapshot_version": snapshot_version,
|
||||
}
|
||||
|
||||
func restore_clock(snapshot: Dictionary) -> bool:
|
||||
if not snapshot.has(&"absolute_minute"):
|
||||
return false
|
||||
var restored_speed := int(snapshot.get(&"speed", 1))
|
||||
# Legacy x4 saves resume at the original specification maximum, x3.
|
||||
if restored_speed == 4:
|
||||
restored_speed = 3
|
||||
if restored_speed not in [1, 2, 3]:
|
||||
return false
|
||||
absolute_minute = maxi(int(snapshot[&"absolute_minute"]), 0)
|
||||
speed = restored_speed
|
||||
paused = bool(snapshot.get(&"paused", true))
|
||||
snapshot_version = maxi(int(snapshot.get(&"snapshot_version", 0)), 0)
|
||||
_accumulator = 0.0
|
||||
_skip_next_process = true
|
||||
_sync_calendar_fields()
|
||||
_emit_current_time()
|
||||
return true
|
||||
|
||||
func _run_phase(phase: TickPhase) -> void:
|
||||
tick_phase_started.emit(phase, absolute_minute)
|
||||
if not _phase_handlers.has(phase):
|
||||
return
|
||||
var handlers: Dictionary = _phase_handlers[phase]
|
||||
var handler_ids: Array = handlers.keys()
|
||||
handler_ids.sort_custom(func(left: Variant, right: Variant) -> bool:
|
||||
return String(left) < String(right)
|
||||
)
|
||||
for handler_id: Variant in handler_ids:
|
||||
var callback: Callable = handlers[handler_id]
|
||||
if callback.is_valid():
|
||||
callback.call(absolute_minute)
|
||||
|
||||
func _sync_calendar_fields() -> void:
|
||||
day = absolute_minute / MINUTES_PER_DAY + 1
|
||||
minute_of_day = absolute_minute % MINUTES_PER_DAY
|
||||
|
||||
func _handle_time_boundaries(previous_absolute_minute: int) -> void:
|
||||
if minute_of_day == 0:
|
||||
var completed_day := previous_absolute_minute / MINUTES_PER_DAY + 1
|
||||
settlement_requested.emit(completed_day)
|
||||
day_started.emit(day)
|
||||
|
||||
func _emit_current_time() -> void:
|
||||
time_changed.emit(day, get_hour(), get_minute())
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
+418
@@ -0,0 +1,418 @@
|
||||
class_name KitchenProductionService
|
||||
extends RefCounted
|
||||
|
||||
const Catalog = preload("res://scripts/supply/supply_catalog.gd")
|
||||
const SNAPSHOT_VERSION := 1
|
||||
|
||||
var current_minute := 0
|
||||
var last_error := ""
|
||||
var last_restore_error := ""
|
||||
|
||||
var _inventory: InventoryService
|
||||
var _facilities: FacilityService
|
||||
var _registry: DefinitionRegistry
|
||||
var _plans: Dictionary = {}
|
||||
var _active_batches: Dictionary = {}
|
||||
var _next_batch_sequence := 1
|
||||
|
||||
|
||||
func configure(
|
||||
inventory: InventoryService,
|
||||
facilities: FacilityService,
|
||||
registry: DefinitionRegistry,
|
||||
minute: int
|
||||
) -> void:
|
||||
_inventory = inventory
|
||||
_facilities = facilities
|
||||
_registry = registry
|
||||
current_minute = maxi(minute, 0)
|
||||
|
||||
|
||||
func set_plan(facility_id: StringName, enabled: bool, target_stock: int = Catalog.KITCHEN_TARGET_DEFAULT) -> Dictionary:
|
||||
if _kitchen(facility_id) == null:
|
||||
return _failure(&"INVALID_FACILITY", "Production plans require an existing kitchen.")
|
||||
if not _valid_target(target_stock):
|
||||
return _failure(&"INVALID_TARGET", "Target must be 4, 8, 12, or 16 meals.")
|
||||
_plans[facility_id] = {
|
||||
&"facility_id": String(facility_id), &"enabled": enabled, &"target_stock": target_stock,
|
||||
}
|
||||
last_error = ""
|
||||
return {&"ok": true, &"plan": get_plan(facility_id)}
|
||||
|
||||
|
||||
func get_plan(facility_id: StringName) -> Dictionary:
|
||||
if _plans.has(facility_id):
|
||||
return (_plans[facility_id] as Dictionary).duplicate(true)
|
||||
if _kitchen(facility_id) == null:
|
||||
return {}
|
||||
return {&"facility_id": String(facility_id), &"enabled": false, &"target_stock": Catalog.KITCHEN_TARGET_DEFAULT}
|
||||
|
||||
|
||||
func get_plans() -> Array[Dictionary]:
|
||||
var result: Array[Dictionary] = []
|
||||
for facility_id: StringName in _sorted_ids(_plans):
|
||||
result.append(get_plan(facility_id))
|
||||
return result
|
||||
|
||||
|
||||
## Also works after a successful facility removal, when the instance no longer
|
||||
## exists. Runtime checks enabled plans and batches before authorizing removal.
|
||||
func remove_plan(facility_id: StringName) -> Dictionary:
|
||||
if _active_batches.has(facility_id):
|
||||
return {&"ok": false, &"reason": &"ACTIVE_BATCH"}
|
||||
if _plans.has(facility_id) and bool(_plans[facility_id][&"enabled"]):
|
||||
return {&"ok": false, &"reason": &"PLAN_ENABLED"}
|
||||
var existed := _plans.erase(facility_id)
|
||||
return {&"ok": true, &"reason": &"REMOVED" if existed else &"NO_PLAN"}
|
||||
|
||||
|
||||
func get_report(facility_id: StringName) -> Dictionary:
|
||||
var facility := _kitchen(facility_id)
|
||||
if facility == null:
|
||||
return {}
|
||||
var plan := get_plan(facility_id)
|
||||
var batch: Dictionary = _active_batches.get(facility_id, {})
|
||||
var state := _production_state(facility, plan, batch, current_minute)
|
||||
return {
|
||||
&"facility_id": String(facility_id), &"inventory_id": String(facility.local_inventory_id),
|
||||
&"enabled": plan[&"enabled"], &"target_stock": plan[&"target_stock"],
|
||||
&"state": state, &"status": state,
|
||||
&"raw_stock": _inventory.available_quantity(facility.local_inventory_id, Catalog.RAW_FOOD, current_minute),
|
||||
&"meal_stock": _usable_quantity(facility.local_inventory_id, Catalog.BASIC_MEAL, current_minute),
|
||||
&"progress_minutes": int(batch.get(&"progress_minutes", 0)),
|
||||
&"duration_minutes": Catalog.PRODUCTION_MINUTES,
|
||||
&"active_batch": batch.duplicate(true),
|
||||
}
|
||||
|
||||
|
||||
## Runtime calls this after projecting current staffing/power/access. A batch
|
||||
## started at t first earns work at t+1; interruptions retain earned work.
|
||||
func advance_one_minute(minute: int) -> Dictionary:
|
||||
if not _configured():
|
||||
return _failure(&"NOT_CONFIGURED", "Inventory, facilities, and registry must be configured.")
|
||||
if minute == current_minute:
|
||||
return {&"ok": true, &"replay": true, &"events": []}
|
||||
if minute != current_minute + 1:
|
||||
return _failure(&"INVALID_MINUTE", "Production must advance one minute at a time.")
|
||||
current_minute = minute
|
||||
var events: Array[Dictionary] = []
|
||||
for facility_id: StringName in _sorted_ids(_plans):
|
||||
var facility := _kitchen(facility_id)
|
||||
var batch: Dictionary = _active_batches.get(facility_id, {})
|
||||
if facility == null:
|
||||
if not batch.is_empty():
|
||||
_release_batch(batch)
|
||||
_active_batches.erase(facility_id)
|
||||
events.append(_event(&"BATCH_FAILED", facility_id, batch, &"FACILITY_REMOVED"))
|
||||
_plans.erase(facility_id)
|
||||
continue
|
||||
# Expiry also closes reservations while a plan or facility is paused.
|
||||
if not batch.is_empty() and not _batch_links_valid(batch, minute):
|
||||
_release_batch(batch)
|
||||
_active_batches.erase(facility_id)
|
||||
events.append(_event(&"BATCH_FAILED", facility_id, batch, &"INPUT_UNAVAILABLE"))
|
||||
continue
|
||||
var plan: Dictionary = _plans[facility_id]
|
||||
var state := _production_state(facility, plan, batch, minute)
|
||||
if batch.is_empty():
|
||||
if state == &"READY":
|
||||
var result := _start_batch(facility, minute)
|
||||
if bool(result[&"ok"]):
|
||||
events.append(_event(&"BATCH_STARTED", facility_id, _active_batches[facility_id]))
|
||||
continue
|
||||
if state != &"PRODUCING":
|
||||
continue
|
||||
batch[&"progress_minutes"] = mini(int(batch[&"progress_minutes"]) + 1, Catalog.PRODUCTION_MINUTES)
|
||||
if int(batch[&"progress_minutes"]) == Catalog.PRODUCTION_MINUTES:
|
||||
var result := _complete_batch(batch, minute)
|
||||
if bool(result[&"ok"]):
|
||||
_active_batches.erase(facility_id)
|
||||
events.append(_event(&"BATCH_COMPLETED", facility_id, batch))
|
||||
else:
|
||||
# Atomic inventory failure keeps the reservation and full progress.
|
||||
events.append(_event(&"BATCH_WAITING", facility_id, batch, result.get(&"code", &"INVENTORY_ERROR")))
|
||||
last_error = ""
|
||||
return {&"ok": true, &"events": events}
|
||||
|
||||
|
||||
func create_snapshot() -> Dictionary:
|
||||
var batches: Array[Dictionary] = []
|
||||
for facility_id: StringName in _sorted_ids(_active_batches):
|
||||
batches.append((_active_batches[facility_id] as Dictionary).duplicate(true))
|
||||
return {
|
||||
&"version": SNAPSHOT_VERSION, &"current_minute": current_minute,
|
||||
&"next_batch_sequence": _next_batch_sequence,
|
||||
&"plans": get_plans(), &"active_batches": batches,
|
||||
}
|
||||
|
||||
|
||||
## Restore is transactional and read-only with respect to inventory. Inventory
|
||||
## and FacilityService must already contain their restored state.
|
||||
func restore_snapshot(snapshot: Dictionary) -> bool:
|
||||
last_restore_error = ""
|
||||
if not _configured() or not _keys_match(snapshot, [&"version", &"current_minute", &"next_batch_sequence", &"plans", &"active_batches"]):
|
||||
return _restore_failure("Missing dependencies or invalid snapshot fields.")
|
||||
if not _integer(snapshot[&"version"], SNAPSHOT_VERSION, SNAPSHOT_VERSION) \
|
||||
or not _integer(snapshot[&"current_minute"], 0) \
|
||||
or not _integer(snapshot[&"next_batch_sequence"], 1) \
|
||||
or not snapshot[&"plans"] is Array or not snapshot[&"active_batches"] is Array:
|
||||
return _restore_failure("Invalid snapshot version, clock, sequence, or collections.")
|
||||
var candidate_plans: Dictionary = {}
|
||||
for value: Variant in snapshot[&"plans"]:
|
||||
if not value is Dictionary or not _keys_match(value, [&"facility_id", &"enabled", &"target_stock"]):
|
||||
return _restore_failure("Invalid production plan fields.")
|
||||
var plan: Dictionary = value
|
||||
if not _text(plan[&"facility_id"]) or not plan[&"enabled"] is bool \
|
||||
or not _integer(plan[&"target_stock"], 4, Catalog.KITCHEN_TARGET_MAX) \
|
||||
or not _valid_target(int(plan[&"target_stock"])):
|
||||
return _restore_failure("Invalid production plan values.")
|
||||
var facility_id := StringName(plan[&"facility_id"])
|
||||
if candidate_plans.has(facility_id) or _kitchen(facility_id) == null:
|
||||
return _restore_failure("Duplicate plan or unknown kitchen.")
|
||||
candidate_plans[facility_id] = plan.duplicate(true)
|
||||
var candidate_batches: Dictionary = {}
|
||||
var seen_batches: Dictionary = {}
|
||||
for value: Variant in snapshot[&"active_batches"]:
|
||||
if not value is Dictionary or not _valid_batch_shape(value, int(snapshot[&"current_minute"]), int(snapshot[&"next_batch_sequence"])):
|
||||
return _restore_failure("Invalid active batch.")
|
||||
var batch: Dictionary = value
|
||||
var facility_id := StringName(batch[&"facility_id"])
|
||||
if not candidate_plans.has(facility_id) or candidate_batches.has(facility_id) or seen_batches.has(batch[&"batch_id"]):
|
||||
return _restore_failure("Duplicate batch or missing production plan.")
|
||||
seen_batches[batch[&"batch_id"]] = true
|
||||
candidate_batches[facility_id] = batch.duplicate(true)
|
||||
if not _crosslinks_valid(candidate_batches, int(snapshot[&"current_minute"]), int(snapshot[&"next_batch_sequence"])):
|
||||
return _restore_failure("Kitchen input reservations do not match the restored inventory.")
|
||||
_plans = candidate_plans
|
||||
_active_batches = candidate_batches
|
||||
_next_batch_sequence = int(snapshot[&"next_batch_sequence"])
|
||||
current_minute = int(snapshot[&"current_minute"])
|
||||
last_error = ""
|
||||
return true
|
||||
|
||||
|
||||
func validate_crosslinks() -> bool:
|
||||
return _configured() and _crosslinks_valid(_active_batches, current_minute, _next_batch_sequence)
|
||||
|
||||
|
||||
func _start_batch(facility: FacilityInstance, minute: int) -> Dictionary:
|
||||
var batch_id := StringName("kitchen.batch:%08d" % _next_batch_sequence)
|
||||
var reserved := _inventory.reserve_item(
|
||||
facility.local_inventory_id, Catalog.RAW_FOOD, Catalog.BATCH_INPUT,
|
||||
batch_id, Catalog.PRODUCTION_PURPOSE, minute
|
||||
)
|
||||
if not bool(reserved[&"ok"]):
|
||||
return reserved
|
||||
_next_batch_sequence += 1
|
||||
var reservation_ids: Array[String] = []
|
||||
for reservation_id: StringName in reserved[&"reservation_ids"]:
|
||||
reservation_ids.append(String(reservation_id))
|
||||
var definition := _registry.get_facility(facility.definition_id)
|
||||
_active_batches[facility.instance_id] = {
|
||||
&"batch_id": String(batch_id), &"facility_id": String(facility.instance_id),
|
||||
&"inventory_id": String(facility.local_inventory_id), &"started_at": minute,
|
||||
&"progress_minutes": 0, &"quality": clampi(definition.base_quality, 0, 100),
|
||||
&"reservation_ids": reservation_ids,
|
||||
}
|
||||
return {&"ok": true}
|
||||
|
||||
|
||||
func _complete_batch(batch: Dictionary, minute: int) -> Dictionary:
|
||||
if not _has_output_space(batch):
|
||||
return {&"ok": false, &"code": &"OUTPUT_FULL"}
|
||||
var before := _inventory.create_snapshot()
|
||||
var consumed := _inventory.consume_reservations(_reservation_ids(batch), &"", minute)
|
||||
if not bool(consumed[&"ok"]):
|
||||
return consumed
|
||||
var item := Catalog.get_item(Catalog.BASIC_MEAL)
|
||||
var produced := _inventory.add_stack(
|
||||
StringName(batch[&"inventory_id"]), Catalog.BASIC_MEAL, Catalog.BATCH_OUTPUT,
|
||||
int(batch[&"quality"]), minute + int(item[&"shelf_life_minutes"]), minute, int(item[&"unit_weight"])
|
||||
)
|
||||
if not bool(produced[&"ok"]):
|
||||
_inventory.restore_snapshot(before)
|
||||
return produced
|
||||
|
||||
|
||||
func _production_state(facility: FacilityInstance, plan: Dictionary, batch: Dictionary, minute: int) -> StringName:
|
||||
if not bool(plan[&"enabled"]): return &"DISABLED"
|
||||
if facility.durability <= 0: return &"BROKEN"
|
||||
if not facility.suspension_reason.is_empty(): return &"SUSPENDED"
|
||||
if not facility.related_facility_operating: return &"RELATED_FACILITY_INACTIVE"
|
||||
if not facility.access_available: return &"NO_ACCESS"
|
||||
if not facility.power_available: return &"NO_POWER"
|
||||
if facility.active_staff_ids.size() < maxi(facility.staff_min, 1): return &"NO_STAFF"
|
||||
if not facility.operator_open or not facility.is_within_opening_hours(minute): return &"CLOSED"
|
||||
if not batch.is_empty():
|
||||
if not _batch_links_valid(batch, minute): return &"INPUT_UNAVAILABLE"
|
||||
if int(batch[&"progress_minutes"]) >= Catalog.PRODUCTION_MINUTES and not _has_output_space(batch):
|
||||
return &"OUTPUT_FULL"
|
||||
return &"PRODUCING"
|
||||
if _usable_quantity(facility.local_inventory_id, Catalog.BASIC_MEAL, minute) + Catalog.BATCH_OUTPUT > int(plan[&"target_stock"]):
|
||||
return &"TARGET_REACHED"
|
||||
if _inventory.available_quantity(facility.local_inventory_id, Catalog.RAW_FOOD, minute) < Catalog.BATCH_INPUT:
|
||||
return &"NO_INPUT"
|
||||
return &"READY"
|
||||
|
||||
|
||||
func _has_output_space(batch: Dictionary) -> bool:
|
||||
var consumed_weight := 0
|
||||
for reservation_id: StringName in _reservation_ids(batch):
|
||||
var reservation := _inventory.get_reservation(reservation_id)
|
||||
if reservation == null: return false
|
||||
var stack := _inventory.get_stack(reservation.stack_id)
|
||||
if stack.is_empty(): return false
|
||||
consumed_weight += reservation.quantity * int(stack[&"unit_weight"])
|
||||
var after_weight := Catalog.inventory_weight(_inventory, StringName(batch[&"inventory_id"])) - consumed_weight + Catalog.BATCH_OUTPUT
|
||||
return after_weight <= Catalog.storage_capacity(&"kitchen")
|
||||
|
||||
|
||||
func _batch_links_valid(batch: Dictionary, minute: int) -> bool:
|
||||
var facility := _kitchen(StringName(batch[&"facility_id"]))
|
||||
if facility == null or facility.local_inventory_id != StringName(batch[&"inventory_id"]): return false
|
||||
var quantity := 0
|
||||
var allocated_by_stack: Dictionary = {}
|
||||
for reservation_id: StringName in _reservation_ids(batch):
|
||||
var reservation := _inventory.get_reservation(reservation_id)
|
||||
if reservation == null or not reservation.is_active() or reservation.is_expired(minute) or reservation.quantity <= 0: return false
|
||||
if reservation.owner_inventory_id != facility.local_inventory_id \
|
||||
or reservation.item_id != Catalog.RAW_FOOD or reservation.requester_id != StringName(batch[&"batch_id"]) \
|
||||
or reservation.purpose != Catalog.PRODUCTION_PURPOSE or reservation.created_at != int(batch[&"started_at"]): return false
|
||||
var stack := _inventory.get_stack(reservation.stack_id)
|
||||
if stack.is_empty() or StringName(stack[&"owner_inventory_id"]) != facility.local_inventory_id \
|
||||
or StringName(stack[&"item_id"]) != Catalog.RAW_FOOD \
|
||||
or int(stack[&"reserved_quantity"]) < reservation.quantity or int(stack[&"quantity"]) < reservation.quantity: return false
|
||||
if int(stack[&"expires_at"]) >= 0 and int(stack[&"expires_at"]) <= minute: return false
|
||||
allocated_by_stack[reservation.stack_id] = int(allocated_by_stack.get(reservation.stack_id, 0)) + reservation.quantity
|
||||
if int(allocated_by_stack[reservation.stack_id]) > int(stack[&"reserved_quantity"]): return false
|
||||
quantity += reservation.quantity
|
||||
return quantity == Catalog.BATCH_INPUT
|
||||
|
||||
|
||||
func _crosslinks_valid(batches: Dictionary, minute: int, next_sequence: int) -> bool:
|
||||
var linked: Dictionary = {}
|
||||
for batch: Dictionary in batches.values():
|
||||
if not _batch_links_valid(batch, minute): return false
|
||||
for reservation_id: StringName in _reservation_ids(batch):
|
||||
if linked.has(reservation_id): return false
|
||||
linked[reservation_id] = true
|
||||
# Inventory retains terminal reservations. Their requester IDs are durable
|
||||
# evidence that a batch number was already used, even after completion,
|
||||
# failure, or removal of the kitchen's plan.
|
||||
for reservation: InventoryReservation in _inventory.get_reservations():
|
||||
if reservation.purpose != Catalog.PRODUCTION_PURPOSE:
|
||||
continue
|
||||
var sequence := _batch_sequence(reservation.requester_id)
|
||||
if sequence < 1 or sequence >= next_sequence:
|
||||
return false
|
||||
if reservation.is_active() and not linked.has(reservation.reservation_id):
|
||||
return false
|
||||
return true
|
||||
|
||||
|
||||
func _release_batch(batch: Dictionary) -> void:
|
||||
for reservation_id: StringName in _reservation_ids(batch):
|
||||
var reservation := _inventory.get_reservation(reservation_id)
|
||||
# Only release this batch's own holds if external state was corrupted.
|
||||
if reservation != null and reservation.requester_id == StringName(batch[&"batch_id"]) \
|
||||
and reservation.purpose == Catalog.PRODUCTION_PURPOSE:
|
||||
_inventory.release_reservation(reservation_id, &"", current_minute)
|
||||
|
||||
|
||||
func _kitchen(facility_id: StringName) -> FacilityInstance:
|
||||
if not _configured(): return null
|
||||
var facility := _facilities.get_instance(facility_id)
|
||||
if facility == null or facility.definition_id != &"kitchen" or facility.local_inventory_id == &"": return null
|
||||
if _registry.get_facility(facility.definition_id) == null: return null
|
||||
return facility
|
||||
|
||||
|
||||
func _configured() -> bool:
|
||||
return _inventory != null and _facilities != null and _registry != null
|
||||
|
||||
|
||||
func _usable_quantity(inventory_id: StringName, item_id: StringName, minute: int) -> int:
|
||||
var quantity := 0
|
||||
for stack: Dictionary in _inventory.get_stacks(inventory_id):
|
||||
if StringName(stack[&"item_id"]) == item_id and (int(stack[&"expires_at"]) < 0 or int(stack[&"expires_at"]) > minute):
|
||||
quantity += int(stack[&"quantity"])
|
||||
return quantity
|
||||
|
||||
|
||||
func _valid_batch_shape(batch: Dictionary, minute: int, next_sequence: int) -> bool:
|
||||
if not _keys_match(batch, [&"batch_id", &"facility_id", &"inventory_id", &"started_at", &"progress_minutes", &"quality", &"reservation_ids"]): return false
|
||||
for key: StringName in [&"batch_id", &"facility_id", &"inventory_id"]:
|
||||
if not _text(batch[key]): return false
|
||||
if not _integer(batch[&"started_at"], 0, minute) \
|
||||
or not _integer(batch[&"progress_minutes"], 0, Catalog.PRODUCTION_MINUTES) \
|
||||
or int(batch[&"progress_minutes"]) > minute - int(batch[&"started_at"]) \
|
||||
or not _integer(batch[&"quality"], 0, 100) or not batch[&"reservation_ids"] is Array:
|
||||
return false
|
||||
var sequence := _batch_sequence(batch[&"batch_id"])
|
||||
if sequence < 1 or sequence >= next_sequence: return false
|
||||
var seen: Dictionary = {}
|
||||
for reservation_id: Variant in batch[&"reservation_ids"]:
|
||||
if not _text(reservation_id) or seen.has(StringName(reservation_id)): return false
|
||||
seen[StringName(reservation_id)] = true
|
||||
return not seen.is_empty()
|
||||
|
||||
|
||||
func _batch_sequence(value: Variant) -> int:
|
||||
if not _text(value): return -1
|
||||
var batch_id := String(value)
|
||||
var sequence_text := batch_id.trim_prefix("kitchen.batch:")
|
||||
if not sequence_text.is_valid_int(): return -1
|
||||
var sequence := sequence_text.to_int()
|
||||
if sequence < 1 or batch_id != "kitchen.batch:%08d" % sequence: return -1
|
||||
return sequence
|
||||
|
||||
|
||||
func _reservation_ids(batch: Dictionary) -> Array[StringName]:
|
||||
var ids: Array[StringName] = []
|
||||
for value: Variant in batch[&"reservation_ids"]:
|
||||
ids.append(StringName(value))
|
||||
return ids
|
||||
|
||||
|
||||
func _valid_target(target: int) -> bool:
|
||||
return target >= Catalog.BATCH_OUTPUT and target <= Catalog.KITCHEN_TARGET_MAX and target % Catalog.BATCH_OUTPUT == 0
|
||||
|
||||
|
||||
func _integer(value: Variant, minimum: int, maximum: int = 9223372036854775807) -> bool:
|
||||
return typeof(value) == TYPE_INT and value >= minimum and value <= maximum
|
||||
|
||||
|
||||
func _text(value: Variant) -> bool:
|
||||
return typeof(value) in [TYPE_STRING, TYPE_STRING_NAME] and not String(value).strip_edges().is_empty()
|
||||
|
||||
|
||||
func _keys_match(value: Dictionary, expected: Array) -> bool:
|
||||
if value.size() != expected.size(): return false
|
||||
for key: StringName in expected:
|
||||
if not value.has(key): return false
|
||||
return true
|
||||
|
||||
|
||||
func _sorted_ids(values: Dictionary) -> Array[StringName]:
|
||||
var ids: Array[StringName] = []
|
||||
for value: Variant in values.keys(): ids.append(StringName(value))
|
||||
ids.sort()
|
||||
return ids
|
||||
|
||||
|
||||
func _event(kind: StringName, facility_id: StringName, batch: Dictionary, reason: StringName = &"") -> Dictionary:
|
||||
return {
|
||||
&"type": kind, &"facility_id": String(facility_id), &"batch_id": batch[&"batch_id"],
|
||||
&"minute": current_minute, &"reason": reason,
|
||||
&"output_quantity": Catalog.BATCH_OUTPUT if kind == &"BATCH_COMPLETED" else 0,
|
||||
}
|
||||
|
||||
|
||||
func _failure(code: StringName, message: String) -> Dictionary:
|
||||
last_error = message
|
||||
return {&"ok": false, &"code": code, &"message": message, &"events": []}
|
||||
|
||||
|
||||
func _restore_failure(message: String) -> bool:
|
||||
last_restore_error = message
|
||||
return false
|
||||
+565
@@ -0,0 +1,565 @@
|
||||
class_name SupplyLogisticsBridge
|
||||
extends RefCounted
|
||||
|
||||
## Execution state lives in LogisticsRequest, StaffTask, and InventoryService.
|
||||
## This adapter owns no additional save payload and never moves an actor itself.
|
||||
const REQUEST_PREFIX := "supply."
|
||||
const PICKUP_TYPE := &"supply_pickup"
|
||||
const DELIVERY_TYPE := &"supply_delivery"
|
||||
const RETURN_TYPE := &"supply_return"
|
||||
const RETRY_MINUTES := 5
|
||||
const RETURNING := "RETURNING_EXPIRED_CARGO"
|
||||
|
||||
var _runtime: Variant
|
||||
var last_report: Dictionary = {}
|
||||
|
||||
|
||||
func configure(runtime: Variant) -> SupplyLogisticsBridge:
|
||||
_runtime = runtime
|
||||
_runtime.staff_service.configure_external_task_driver(Callable(self, "owns_task"))
|
||||
return self
|
||||
|
||||
|
||||
func owns_task(task_id: StringName) -> bool:
|
||||
if _runtime == null:
|
||||
return false
|
||||
var task: StaffTask = _runtime.staff_service.get_task(task_id)
|
||||
return task != null and task.task_type in [PICKUP_TYPE, DELIVERY_TYPE, RETURN_TYPE] \
|
||||
and String(task.target_entity_id).begins_with(REQUEST_PREFIX)
|
||||
|
||||
|
||||
func can_move_task(task_id: StringName) -> bool:
|
||||
if not owns_task(task_id):
|
||||
return true
|
||||
var task: StaffTask = _runtime.staff_service.get_task(task_id)
|
||||
var staff: StaffRuntime = _runtime.staff_service.get_staff(task.assigned_staff_id)
|
||||
if staff == null or not staff.can_take_shift():
|
||||
return false
|
||||
# Partial spoilage is a return obligation. Do not keep walking to the
|
||||
# customer while the bridge is still searching for a safe return route.
|
||||
return task.task_type != DELIVERY_TYPE or not is_returning(task.target_entity_id)
|
||||
|
||||
|
||||
func tick(absolute_minute: int) -> Dictionary:
|
||||
if _runtime == null:
|
||||
return {&"ok": false, &"reason": &"NOT_CONFIGURED"}
|
||||
var actions: Array[Dictionary] = []
|
||||
for request_id: StringName in _request_ids(_runtime.logistics_requests):
|
||||
var request: LogisticsRequest = _runtime.logistics_requests[request_id]
|
||||
if request.is_terminal():
|
||||
continue
|
||||
if request.state == LogisticsRequest.State.BLOCKED:
|
||||
if absolute_minute >= request.state_changed_at + RETRY_MINUTES:
|
||||
_rearm(request, absolute_minute)
|
||||
continue
|
||||
if request.state == LogisticsRequest.State.RESERVED:
|
||||
if not _reserved_stock_valid(request):
|
||||
_block_before_pickup(request, "SOURCE_STOCK_EXPIRED", absolute_minute)
|
||||
else:
|
||||
_dispatch(request, absolute_minute)
|
||||
continue
|
||||
var task := _active_task(_runtime.staff_service, request.request_id)
|
||||
var staff: StaffRuntime = _runtime.staff_service.get_staff(request.assigned_carrier_id)
|
||||
if task == null or staff == null or staff.current_task_id != task.task_id:
|
||||
request.state_reason = "CARRIER_TASK_MISSING"
|
||||
continue
|
||||
if request.state == LogisticsRequest.State.DELIVERING and _cargo_quantities(_runtime.inventory_service, _cargo_id(staff.staff_id)).is_empty():
|
||||
_cancel_empty_cargo(request, staff, task, "CARGO_EXPIRED", absolute_minute)
|
||||
continue
|
||||
if not staff.can_take_shift():
|
||||
if request.state in [LogisticsRequest.State.ASSIGNED, LogisticsRequest.State.PICKING_UP]:
|
||||
_block_before_pickup(request, "CARRIER_UNAVAILABLE", absolute_minute)
|
||||
else:
|
||||
request.state_reason = "CARRIER_UNAVAILABLE"
|
||||
continue
|
||||
if request.state in [LogisticsRequest.State.ASSIGNED, LogisticsRequest.State.PICKING_UP]:
|
||||
if not _reserved_stock_valid(request):
|
||||
_block_before_pickup(request, "SOURCE_STOCK_EXPIRED", absolute_minute)
|
||||
elif _arrived_for_work(staff, task, absolute_minute):
|
||||
if _pickup(request, staff, task, absolute_minute):
|
||||
actions.append({&"request_id": request_id, &"action": &"PICKED_UP"})
|
||||
elif request.state == LogisticsRequest.State.DELIVERING:
|
||||
var cargo := _cargo_quantities(_runtime.inventory_service, _cargo_id(staff.staff_id))
|
||||
if cargo.is_empty():
|
||||
_cancel_empty_cargo(request, staff, task, "CARGO_EXPIRED", absolute_minute)
|
||||
continue
|
||||
if not _quantities_cover(cargo, request.item_requirements) and task.task_type != RETURN_TYPE:
|
||||
var source := _facility_for_inventory(_runtime.facility_service, request.source_inventory_id)
|
||||
var route := _access_path(staff.current_cell, source)
|
||||
if not bool(route.get(&"reachable", false)):
|
||||
request.state_reason = "EXPIRED_CARGO_RETURN_BLOCKED"
|
||||
continue
|
||||
if not _runtime.staff_service.retarget_external_task(task.task_id, route[&"cell"], absolute_minute).is_success():
|
||||
continue
|
||||
task.task_type = RETURN_TYPE
|
||||
request.state_reason = RETURNING
|
||||
continue
|
||||
if _arrived_for_work(staff, task, absolute_minute):
|
||||
if _deliver(request, staff, task, absolute_minute):
|
||||
actions.append({&"request_id": request_id, &"action": &"DELIVERED"})
|
||||
last_report = {&"ok": true, &"actions": actions}
|
||||
return last_report.duplicate(true)
|
||||
|
||||
|
||||
func handle_path_stuck(task_id: StringName, absolute_minute: int) -> Dictionary:
|
||||
if not owns_task(task_id):
|
||||
return {&"ok": false, &"action": &"NOT_SUPPLY_TASK"}
|
||||
var task: StaffTask = _runtime.staff_service.get_task(task_id)
|
||||
var request: LogisticsRequest = _runtime.logistics_requests.get(task.target_entity_id)
|
||||
if request == null:
|
||||
return {&"ok": false, &"action": &"REQUEST_MISSING"}
|
||||
if request.state == LogisticsRequest.State.DELIVERING:
|
||||
# Loaded cargo stays with its actor, even when no safe return route exists.
|
||||
# The normal Path loop retries after topology is repaired.
|
||||
request.retry_count += 1
|
||||
if task.task_type != RETURN_TYPE:
|
||||
request.state_reason = "ROUTE_BLOCKED"
|
||||
task.state_reason = &"ROUTE_BLOCKED"
|
||||
return {&"ok": true, &"action": &"SUPPLY_CARGO_HELD"}
|
||||
return {&"ok": _block_before_pickup(request, "ROUTE_BLOCKED", absolute_minute), &"action": &"SUPPLY_PICKUP_RETRY"}
|
||||
|
||||
|
||||
func get_report() -> Dictionary:
|
||||
var rows: Array[Dictionary] = []
|
||||
if _runtime == null:
|
||||
return {&"requests": rows, &"deliveries": rows.duplicate(true)}
|
||||
for request_id: StringName in _request_ids(_runtime.logistics_requests):
|
||||
var request: LogisticsRequest = _runtime.logistics_requests[request_id]
|
||||
var task := _active_task(_runtime.staff_service, request_id)
|
||||
var source := _facility_for_inventory(_runtime.facility_service, request.source_inventory_id)
|
||||
var destination := _facility_for_inventory(_runtime.facility_service, request.destination_inventory_id)
|
||||
var worker: StaffRuntime = _runtime.staff_service.get_staff(request.assigned_carrier_id)
|
||||
rows.append({
|
||||
&"source_facility_id": source.instance_id if source != null else &"",
|
||||
&"destination_facility_id": destination.instance_id if destination != null else &"",
|
||||
&"carrier_name": String(_runtime.mvp_content_catalog.get_entry(&"staff_candidates", worker.staff_id).get(&"display_name", worker.staff_id)) if worker != null else "",
|
||||
&"reason_codes": [] if request.state_reason.is_empty() else [StringName(request.state_reason)],
|
||||
&"request_id": request_id, &"state": LogisticsRequest.State.keys()[request.state],
|
||||
&"reason": request.state_reason, &"carrier_id": request.assigned_carrier_id,
|
||||
&"source_inventory_id": request.source_inventory_id,
|
||||
&"destination_inventory_id": request.destination_inventory_id,
|
||||
&"item_requirements": request.item_requirements.duplicate(true), &"weight": request.total_weight,
|
||||
&"retry_count": request.retry_count, &"task_id": task.task_id if task != null else &"",
|
||||
})
|
||||
var active: Array[Dictionary] = []
|
||||
var recent: Array[Dictionary] = []
|
||||
for row: Dictionary in rows:
|
||||
var request: LogisticsRequest = _runtime.logistics_requests[row[&"request_id"]]
|
||||
if request.is_terminal(): recent.append(row)
|
||||
else: active.append(row)
|
||||
recent.sort_custom(func(a: Dictionary, b: Dictionary) -> bool:
|
||||
var left: LogisticsRequest = _runtime.logistics_requests[a[&"request_id"]]
|
||||
var right: LogisticsRequest = _runtime.logistics_requests[b[&"request_id"]]
|
||||
if left.state_changed_at != right.state_changed_at: return left.state_changed_at > right.state_changed_at
|
||||
return String(left.request_id) > String(right.request_id))
|
||||
active.append_array(recent.slice(0, 10))
|
||||
return {&"requests": rows, &"deliveries": active}
|
||||
|
||||
|
||||
func is_returning(request_id: StringName) -> bool:
|
||||
if _runtime == null:
|
||||
return false
|
||||
var request: LogisticsRequest = _runtime.logistics_requests.get(request_id)
|
||||
if request == null or request.state != LogisticsRequest.State.DELIVERING:
|
||||
return false
|
||||
var task := _active_task(_runtime.staff_service, request_id)
|
||||
if task != null and task.task_type == RETURN_TYPE:
|
||||
return true
|
||||
return not _quantities_cover(_cargo_quantities(_runtime.inventory_service, _cargo_id(request.assigned_carrier_id)), request.item_requirements)
|
||||
|
||||
|
||||
func _dispatch(request: LogisticsRequest, minute: int) -> void:
|
||||
var source := _facility_for_inventory(_runtime.facility_service, request.source_inventory_id)
|
||||
var destination := _facility_for_inventory(_runtime.facility_service, request.destination_inventory_id)
|
||||
if source == null or destination == null or not source.allows_logistics() or not destination.allows_logistics():
|
||||
request.state_reason = "FACILITY_UNAVAILABLE"
|
||||
return
|
||||
if not _has_storage_space(destination, request.total_weight):
|
||||
request.state_reason = "DESTINATION_FULL"
|
||||
return
|
||||
var carriers: Dictionary = {}
|
||||
var source_cells: Dictionary = {}
|
||||
for staff: StaffRuntime in _runtime.staff_service.get_staff_members():
|
||||
var shift: ShiftInstance = _runtime.staff_service.get_shift(staff.shift_id)
|
||||
if staff.role_id != &"porter" or not staff.is_available_for_dispatch() \
|
||||
or shift == null or not shift.contains_minute(minute) \
|
||||
or _runtime.logistics_dispatcher.get_reserved_load(staff.staff_id) > 0 \
|
||||
or not _cargo_quantities(_runtime.inventory_service, _cargo_id(staff.staff_id)).is_empty():
|
||||
continue
|
||||
var access := _access_path(staff.current_cell, source)
|
||||
if not bool(access.get(&"reachable", false)):
|
||||
continue
|
||||
var onward := _access_path(access[&"cell"], destination)
|
||||
if not bool(onward.get(&"reachable", false)):
|
||||
continue
|
||||
carriers[staff.staff_id] = {&"capacity": mini(20, 10 + int(staff.skills.get(&"operation", 0)) / 10),
|
||||
&"current_load": 0, &"path_minutes": int(access[&"steps"]), &"position": staff.current_cell, &"role": &"logistics"}
|
||||
source_cells[staff.staff_id] = access[&"cell"]
|
||||
if carriers.is_empty():
|
||||
request.state_reason = "NO_AVAILABLE_PORTER_OR_ROUTE"
|
||||
return
|
||||
var before := _capture(request)
|
||||
var assigned: Array = _runtime.logistics_dispatcher.dispatch([request], carriers, minute)
|
||||
if assigned.is_empty():
|
||||
request.state_reason = "CARRIER_CAPACITY_EXCEEDED"
|
||||
return
|
||||
var staff_id := request.assigned_carrier_id
|
||||
var task := _create_task(request, PICKUP_TYPE, source_cells[staff_id], minute)
|
||||
if task == null or not _runtime.staff_service.assign_task_to_staff(task.task_id, staff_id, minute).is_success():
|
||||
_rollback(request, before)
|
||||
request.state_reason = "TASK_ASSIGNMENT_FAILED"
|
||||
return
|
||||
request.state_reason = ""
|
||||
|
||||
|
||||
func _pickup(request: LogisticsRequest, staff: StaffRuntime, task: StaffTask, minute: int) -> bool:
|
||||
var source := _facility_for_inventory(_runtime.facility_service, request.source_inventory_id)
|
||||
if source == null or not _cell_touches_facility(staff.current_cell, source):
|
||||
return _block_before_pickup(request, "INVALID_PICKUP_ACCESS", minute) and false
|
||||
if not source.allows_logistics():
|
||||
return _block_before_pickup(request, "SOURCE_CLOSED", minute) and false
|
||||
var destination := _facility_for_inventory(_runtime.facility_service, request.destination_inventory_id)
|
||||
if destination == null or not destination.allows_logistics() or not _has_storage_space(destination, request.total_weight):
|
||||
return _block_before_pickup(request, "DESTINATION_FULL_OR_CLOSED", minute) and false
|
||||
var route := _access_path(staff.current_cell, destination)
|
||||
if not bool(route.get(&"reachable", false)):
|
||||
return _block_before_pickup(request, "NO_DELIVERY_ROUTE", minute) and false
|
||||
var before := _capture(request)
|
||||
if request.state == LogisticsRequest.State.ASSIGNED and not _advance_request(request, minute):
|
||||
_rollback(request, before)
|
||||
return false
|
||||
if not _advance_request(request, minute):
|
||||
_rollback(request, before)
|
||||
return _block_before_pickup(request, "PICKUP_FAILED", minute) and false
|
||||
if not _runtime.staff_service.progress_task(task.task_id, 1, minute, true).is_success():
|
||||
_rollback(request, before)
|
||||
return false
|
||||
staff.carried_inventory_id = _cargo_id(staff.staff_id)
|
||||
var delivery := _create_task(request, DELIVERY_TYPE, route[&"cell"], minute)
|
||||
if delivery == null or not _runtime.staff_service.assign_task_to_staff(delivery.task_id, staff.staff_id, minute).is_success():
|
||||
_rollback(request, before)
|
||||
return false
|
||||
request.state_reason = ""
|
||||
return true
|
||||
|
||||
|
||||
func _deliver(request: LogisticsRequest, staff: StaffRuntime, task: StaffTask, minute: int) -> bool:
|
||||
var returning := task.task_type == RETURN_TYPE
|
||||
var destination_id := request.source_inventory_id if returning else request.destination_inventory_id
|
||||
var destination := _facility_for_inventory(_runtime.facility_service, destination_id)
|
||||
if destination == null or not _cell_touches_facility(staff.current_cell, destination):
|
||||
request.state_reason = "INVALID_DELIVERY_ACCESS"
|
||||
return false
|
||||
var quantities := _cargo_quantities(_runtime.inventory_service, _cargo_id(staff.staff_id))
|
||||
if destination == null or not destination.allows_logistics() or not _has_storage_space(destination, SupplyCatalog.inventory_weight(_runtime.inventory_service, _cargo_id(staff.staff_id))):
|
||||
if not returning:
|
||||
request.state_reason = "DESTINATION_FULL"
|
||||
return false
|
||||
var before := _capture(request)
|
||||
if returning:
|
||||
var transfers: Array[Dictionary] = []
|
||||
for item_id: StringName in _sorted_keys(quantities):
|
||||
transfers.append({&"source_inventory_id": _cargo_id(staff.staff_id), &"destination_inventory_id": destination_id,
|
||||
&"item_id": item_id, &"quantity": int(quantities[item_id]), &"operation_id": StringName("supply.return.%s.%s" % [request.request_id, item_id])})
|
||||
if not _runtime.inventory_service.transfer_available_batch(transfers, minute)[&"ok"] \
|
||||
or not _runtime.logistics_dispatcher.release_assignment_for_request(request.request_id, staff.staff_id, request.total_weight):
|
||||
_rollback(request, before)
|
||||
return false
|
||||
request.cancel("CARGO_EXPIRED_RETURNED", minute)
|
||||
else:
|
||||
if not _advance_request(request, minute):
|
||||
_rollback(request, before)
|
||||
request.state_reason = "DELIVERY_RETRY"
|
||||
return false
|
||||
if not _runtime.staff_service.progress_task(task.task_id, 1, minute, true).is_success():
|
||||
_rollback(request, before)
|
||||
return false
|
||||
staff.carried_inventory_id = &""
|
||||
return true
|
||||
|
||||
|
||||
func _block_before_pickup(request: LogisticsRequest, reason: String, minute: int) -> bool:
|
||||
var before := _capture(request)
|
||||
var task := _active_task(_runtime.staff_service, request.request_id)
|
||||
var carrier_id := request.assigned_carrier_id
|
||||
var worker: StaffRuntime = _runtime.staff_service.get_staff(carrier_id)
|
||||
var unavailable_state := worker.state if worker != null and not worker.can_take_shift() else -1
|
||||
for reservation_id: StringName in request.reservation_ids:
|
||||
var reservation: InventoryReservation = _runtime.inventory_service.get_reservation(reservation_id)
|
||||
if reservation != null and reservation.is_active() \
|
||||
and not _runtime.inventory_service.release_reservation(reservation_id, &"", minute)[&"ok"]:
|
||||
_rollback(request, before)
|
||||
return false
|
||||
if not carrier_id.is_empty() and not _runtime.logistics_dispatcher.release_assignment_for_request(request.request_id, carrier_id, request.total_weight):
|
||||
_rollback(request, before)
|
||||
return false
|
||||
if task != null and not _runtime.staff_service.cancel_task(task.task_id, StringName(reason), minute, true).is_success():
|
||||
_rollback(request, before)
|
||||
return false
|
||||
if unavailable_state >= 0:
|
||||
worker.transition_to(unavailable_state, StringName(reason), minute)
|
||||
request.mark_blocked(reason, minute)
|
||||
return true
|
||||
|
||||
|
||||
func _rearm(request: LogisticsRequest, minute: int) -> void:
|
||||
if request.deadline >= 0 and request.deadline <= minute:
|
||||
request.cancel("DEADLINE_EXPIRED", minute)
|
||||
return
|
||||
var before := _capture(request)
|
||||
var ids: Array[StringName] = []
|
||||
var stacks: Array[StringName] = []
|
||||
var weight := 0
|
||||
for item_id: StringName in _sorted_keys(request.item_requirements):
|
||||
var result: Dictionary = _runtime.inventory_service.reserve_item(request.source_inventory_id, item_id,
|
||||
int(request.item_requirements[item_id]), request.request_id, &"logistics", minute, request.deadline,
|
||||
StringName("supply.retry.%s.%d.%s" % [request.request_id, minute, item_id]))
|
||||
if not bool(result.get(&"ok", false)):
|
||||
_rollback(request, before)
|
||||
request.state_changed_at = minute
|
||||
request.state_reason = "WAITING_FOR_SOURCE_STOCK"
|
||||
return
|
||||
for id: StringName in result[&"reservation_ids"]:
|
||||
ids.append(id)
|
||||
var reservation: InventoryReservation = _runtime.inventory_service.get_reservation(id)
|
||||
stacks.append(reservation.stack_id)
|
||||
weight += reservation.quantity * int(_runtime.inventory_service.get_stack(reservation.stack_id)[&"unit_weight"])
|
||||
if weight != request.total_weight or not request.mark_reserved(ids, stacks, minute):
|
||||
_rollback(request, before)
|
||||
request.state_changed_at = minute
|
||||
request.state_reason = "SOURCE_WEIGHT_CHANGED"
|
||||
|
||||
|
||||
func _cancel_empty_cargo(request: LogisticsRequest, staff: StaffRuntime, task: StaffTask, reason: String, minute: int) -> void:
|
||||
var before := _capture(request)
|
||||
var unavailable_state := staff.state if not staff.can_take_shift() else -1
|
||||
if not _runtime.logistics_dispatcher.release_assignment_for_request(request.request_id, staff.staff_id, request.total_weight) \
|
||||
or not _runtime.staff_service.cancel_task(task.task_id, StringName(reason), minute, true).is_success():
|
||||
_rollback(request, before)
|
||||
return
|
||||
staff.carried_inventory_id = &""
|
||||
if unavailable_state >= 0:
|
||||
staff.transition_to(unavailable_state, StringName(reason), minute)
|
||||
request.cancel(reason, minute)
|
||||
|
||||
|
||||
func _create_task(request: LogisticsRequest, type: StringName, cell: Vector3i, minute: int) -> StaffTask:
|
||||
var leg := "pickup" if type == PICKUP_TYPE else "delivery"
|
||||
var task_id := StringName("supply.%s.%s.%d" % [leg, request.request_id, request.retry_count])
|
||||
var result: CommandResult = _runtime.staff_service.create_task(type, request.priority, minute, {
|
||||
&"target_entity_id": request.request_id, &"target_cell": cell, &"required_role_tags": [&"porter"],
|
||||
&"task_tags": [&"logistics"], &"estimated_minutes": 1, &"interrupt_level": 0,
|
||||
}, task_id)
|
||||
return _runtime.staff_service.get_task(task_id) if result.is_success() else null
|
||||
|
||||
|
||||
func _advance_request(request: LogisticsRequest, minute: int) -> bool:
|
||||
var command := SimulationCommand.new()
|
||||
command.command_id = 0
|
||||
command.command_type = &"advance_logistics_request"
|
||||
command.payload = {&"request_id": request.request_id}
|
||||
command.issued_tick = minute
|
||||
command.execute_tick = minute
|
||||
return _runtime._execute_advance_logistics_request(command).is_success()
|
||||
|
||||
|
||||
func _capture(request: LogisticsRequest) -> Dictionary:
|
||||
return {&"request": request.create_snapshot(), &"staff": _runtime.staff_service.create_snapshot(),
|
||||
&"inventory": _runtime.inventory_service.create_snapshot(), &"dispatcher": _runtime.logistics_dispatcher.create_snapshot(),
|
||||
&"events": _runtime.domain_events.create_snapshot(), &"ids": _runtime.id_generator.create_snapshot()}
|
||||
|
||||
|
||||
func _rollback(request: LogisticsRequest, before: Dictionary) -> void:
|
||||
_runtime.staff_service.restore_snapshot(before[&"staff"])
|
||||
_runtime.inventory_service.restore_snapshot(before[&"inventory"])
|
||||
_runtime.logistics_dispatcher.restore_snapshot(before[&"dispatcher"])
|
||||
_runtime.domain_events.restore_snapshot(before[&"events"])
|
||||
_runtime.id_generator.restore_snapshot(before[&"ids"])
|
||||
var restored := LogisticsRequest.from_snapshot(before[&"request"])
|
||||
# Keep the Request identity while callers finish handling this transition.
|
||||
for property: Dictionary in restored.get_property_list():
|
||||
var name := StringName(property[&"name"])
|
||||
if name in [&"RefCounted", &"script"] or not (int(property[&"usage"]) & PROPERTY_USAGE_SCRIPT_VARIABLE):
|
||||
continue
|
||||
request.set(name, restored.get(name))
|
||||
_runtime.logistics_requests[request.request_id] = request
|
||||
|
||||
|
||||
func _reserved_stock_valid(request: LogisticsRequest) -> bool:
|
||||
return _reservation_quantities_valid(request, _runtime.inventory_service, true)
|
||||
|
||||
|
||||
func _has_storage_space(facility: FacilityInstance, incoming_weight: int) -> bool:
|
||||
var capacity := SupplyCatalog.storage_capacity(facility.definition_id)
|
||||
return capacity > 0 and SupplyCatalog.inventory_weight(_runtime.inventory_service, facility.local_inventory_id) + incoming_weight <= capacity
|
||||
|
||||
|
||||
func find_facility_access_path(start: Vector3i, facility: FacilityInstance) -> Dictionary:
|
||||
return _access_path(start, facility)
|
||||
|
||||
|
||||
func _access_path(start: Vector3i, facility: FacilityInstance) -> Dictionary:
|
||||
if facility == null:
|
||||
return {&"reachable": false}
|
||||
var cells: Dictionary = {}
|
||||
for cell: Vector3i in facility.occupied_cells:
|
||||
for delta: Vector3i in [Vector3i.ZERO, Vector3i.LEFT, Vector3i.RIGHT]:
|
||||
if _runtime.path_service.has_cell(cell + delta):
|
||||
cells[cell + delta] = true
|
||||
if cells.is_empty() and _runtime.path_service.has_cell(facility.origin):
|
||||
cells[facility.origin] = true
|
||||
var ordered: Array = cells.keys()
|
||||
ordered.sort_custom(func(a: Vector3i, b: Vector3i) -> bool:
|
||||
if a.z != b.z: return a.z < b.z
|
||||
if a.y != b.y: return a.y < b.y
|
||||
return a.x < b.x)
|
||||
var best: Array[Vector3i] = []
|
||||
var best_cost := 9223372036854775807
|
||||
for cell: Vector3i in ordered:
|
||||
var path: Array[Vector3i] = _runtime.path_service.find_path(start, cell, [WorldService.LAYER_FRONT, WorldService.LAYER_BACK], [&"staff"])
|
||||
var cost: int = _runtime.path_service.calculate_path_cost(path, [&"staff"]) if not path.is_empty() else -1
|
||||
if cost >= 0 and (best.is_empty() or cost < best_cost):
|
||||
best = path
|
||||
best_cost = cost
|
||||
return {&"reachable": not best.is_empty(), &"cell": best[-1] if not best.is_empty() else facility.origin, &"steps": maxi(0, best.size() - 1)}
|
||||
|
||||
|
||||
static func _arrived_for_work(staff: StaffRuntime, task: StaffTask, minute: int) -> bool:
|
||||
return task.state == StaffTask.State.WORKING and task.state_changed_at < minute and staff.current_cell == task.target_cell
|
||||
|
||||
|
||||
static func _cargo_id(staff_id: StringName) -> StringName:
|
||||
return StringName("cargo:%s" % staff_id)
|
||||
|
||||
|
||||
static func _request_ids(requests: Dictionary) -> Array[StringName]:
|
||||
var ids: Array[StringName] = []
|
||||
for id: StringName in _sorted_keys(requests):
|
||||
if String(id).begins_with(REQUEST_PREFIX):
|
||||
ids.append(id)
|
||||
return ids
|
||||
|
||||
|
||||
static func _sorted_keys(source: Dictionary) -> Array[StringName]:
|
||||
var ids: Array[StringName] = []
|
||||
for key: Variant in source:
|
||||
ids.append(StringName(key))
|
||||
ids.sort_custom(func(a: StringName, b: StringName) -> bool: return String(a) < String(b))
|
||||
return ids
|
||||
|
||||
|
||||
static func _active_task(staff: StaffService, request_id: StringName) -> StaffTask:
|
||||
for task: StaffTask in staff.get_tasks():
|
||||
if task.target_entity_id == request_id and task.task_type in [PICKUP_TYPE, DELIVERY_TYPE, RETURN_TYPE] and not task.is_terminal():
|
||||
return task
|
||||
return null
|
||||
|
||||
|
||||
static func _facility_for_inventory(facilities: FacilityService, inventory_id: StringName) -> FacilityInstance:
|
||||
for facility: FacilityInstance in facilities.get_instances():
|
||||
if facility.local_inventory_id == inventory_id:
|
||||
return facility
|
||||
return null
|
||||
|
||||
|
||||
static func _cargo_quantities(inventory: InventoryService, cargo_id: StringName) -> Dictionary:
|
||||
var quantities: Dictionary = {}
|
||||
for stack: Dictionary in inventory.get_stacks(cargo_id):
|
||||
var item_id := StringName(stack[&"item_id"])
|
||||
quantities[item_id] = int(quantities.get(item_id, 0)) + int(stack[&"quantity"])
|
||||
return quantities
|
||||
|
||||
|
||||
static func _quantities_cover(actual: Dictionary, requested: Dictionary) -> bool:
|
||||
for item_id: StringName in _sorted_keys(requested):
|
||||
if int(actual.get(item_id, 0)) < int(requested[item_id]):
|
||||
return false
|
||||
return true
|
||||
|
||||
|
||||
static func _reservation_quantities_valid(request: LogisticsRequest, inventory: InventoryService, active: bool) -> bool:
|
||||
var totals: Dictionary = {}
|
||||
var weight := 0
|
||||
var seen: Dictionary = {}
|
||||
if request.reservation_ids.is_empty():
|
||||
return false
|
||||
for id: StringName in request.reservation_ids:
|
||||
if seen.has(id):
|
||||
return false
|
||||
seen[id] = true
|
||||
var reservation := inventory.get_reservation(id)
|
||||
if reservation == null or reservation.requester_id != request.request_id \
|
||||
or reservation.owner_inventory_id != request.source_inventory_id:
|
||||
return false
|
||||
if active and (not reservation.is_active() or reservation.is_expired(inventory.current_minute) \
|
||||
or inventory.is_stack_expired(reservation.stack_id, inventory.current_minute)):
|
||||
return false
|
||||
if not active and reservation.state != InventoryReservation.State.CONSUMED:
|
||||
return false
|
||||
totals[reservation.item_id] = int(totals.get(reservation.item_id, 0)) + reservation.quantity
|
||||
if active:
|
||||
var stack := inventory.get_stack(reservation.stack_id)
|
||||
if stack.is_empty():
|
||||
return false
|
||||
weight += reservation.quantity * int(stack[&"unit_weight"])
|
||||
return totals == request.item_requirements and (not active or weight == request.total_weight)
|
||||
|
||||
|
||||
static func validate_crosslinks(requests: Dictionary, staff: StaffService, inventory: InventoryService, facilities: FacilityService) -> bool:
|
||||
var carrier_owners: Dictionary = {}
|
||||
var active_task_ids: Dictionary = {}
|
||||
for id: StringName in _request_ids(requests):
|
||||
var request: LogisticsRequest = requests[id]
|
||||
var source := _facility_for_inventory(facilities, request.source_inventory_id)
|
||||
var destination := _facility_for_inventory(facilities, request.destination_inventory_id)
|
||||
if not String(request.source_inventory_id).begins_with("facility.inventory:") or not String(request.destination_inventory_id).begins_with("facility.inventory:"):
|
||||
return false
|
||||
if not request.is_terminal() and (source == null or destination == null):
|
||||
return false
|
||||
var task := _active_task(staff, id)
|
||||
if request.state in [LogisticsRequest.State.RESERVED, LogisticsRequest.State.BLOCKED] or request.is_terminal():
|
||||
if task != null:
|
||||
return false
|
||||
if request.state == LogisticsRequest.State.RESERVED and not _reservation_quantities_valid(request, inventory, true):
|
||||
return false
|
||||
continue
|
||||
if request.state not in [LogisticsRequest.State.ASSIGNED, LogisticsRequest.State.PICKING_UP, LogisticsRequest.State.DELIVERING]:
|
||||
return false
|
||||
var worker := staff.get_staff(request.assigned_carrier_id)
|
||||
if worker == null or worker.role_id != &"porter" or carrier_owners.has(worker.staff_id) \
|
||||
or task == null or task.assigned_staff_id != worker.staff_id or worker.current_task_id != task.task_id \
|
||||
or task.state not in [StaffTask.State.RESERVED, StaffTask.State.MOVING, StaffTask.State.WORKING] \
|
||||
or task.interrupt_level != 0 or not task.required_items.is_empty() or not task.reservation_ids.is_empty():
|
||||
return false
|
||||
carrier_owners[worker.staff_id] = id
|
||||
active_task_ids[task.task_id] = true
|
||||
var loaded := request.state == LogisticsRequest.State.DELIVERING
|
||||
var endpoint := source if not loaded or task.task_type == RETURN_TYPE else destination
|
||||
if not _cell_touches_facility(task.target_cell, endpoint):
|
||||
return false
|
||||
if (loaded and task.task_type not in [DELIVERY_TYPE, RETURN_TYPE]) or (not loaded and task.task_type != PICKUP_TYPE) \
|
||||
or not String(task.task_id).begins_with("supply.%s.%s." % ["delivery" if loaded else "pickup", id]):
|
||||
return false
|
||||
if not _reservation_quantities_valid(request, inventory, not loaded):
|
||||
return false
|
||||
var cargo := _cargo_quantities(inventory, _cargo_id(worker.staff_id))
|
||||
if loaded:
|
||||
if worker.carried_inventory_id != _cargo_id(worker.staff_id) or cargo.is_empty():
|
||||
return false
|
||||
for item_id: StringName in _sorted_keys(cargo):
|
||||
if int(cargo[item_id]) > int(request.item_requirements.get(item_id, 0)):
|
||||
return false
|
||||
elif not cargo.is_empty() or not worker.carried_inventory_id.is_empty():
|
||||
return false
|
||||
for task: StaffTask in staff.get_tasks():
|
||||
if task.task_type in [PICKUP_TYPE, DELIVERY_TYPE, RETURN_TYPE] and not task.is_terminal() \
|
||||
and (not requests.has(task.target_entity_id) or not active_task_ids.has(task.task_id)):
|
||||
return false
|
||||
return true
|
||||
|
||||
|
||||
static func _cell_touches_facility(cell: Vector3i, facility: FacilityInstance) -> bool:
|
||||
for occupied: Vector3i in facility.occupied_cells:
|
||||
if cell.z == occupied.z and cell.y == occupied.y and absi(cell.x - occupied.x) <= 1:
|
||||
return true
|
||||
return cell == facility.origin
|
||||
+424
@@ -0,0 +1,424 @@
|
||||
class_name SupplyManagementService
|
||||
extends RefCounted
|
||||
|
||||
const PurchaseQuoteV2 := preload("res://scripts/supply/supply_purchase_quote_v2.gd")
|
||||
|
||||
## Player commands and deterministic replenishment. Vendor purchases arrive in
|
||||
## the selected warehouse; all transfers inside the tree use real porter tasks.
|
||||
|
||||
func preview_purchase(runtime: Variant, warehouse_id: StringName, item_id: StringName, quantity: int) -> Dictionary:
|
||||
# Keep the entire ordinary branch literal; only placed UNIQUE Mimi
|
||||
# selects the explicit total-order quote. No attendance/role/floor condition.
|
||||
if not PurchaseQuoteV2.eligible(runtime):
|
||||
return _preview_purchase_v1(runtime, warehouse_id, item_id, quantity)
|
||||
var quote := _preview_purchase_v1(runtime, warehouse_id, item_id, quantity)
|
||||
var item := SupplyCatalog.get_item(item_id)
|
||||
var facility: FacilityInstance = runtime.facility_service.get_instance(warehouse_id)
|
||||
if facility == null or facility.definition_id != &"warehouse" or item.is_empty() \
|
||||
or not bool(item.get(&"purchasable", false)) or quantity <= 0 or quantity > 10000: return quote
|
||||
var frozen := PurchaseQuoteV2.make(item_id, quantity, int(item[&"unit_price"]))
|
||||
if frozen.is_empty(): return quote
|
||||
var cash: int = runtime.economy_service.get_balance(&"PLAYER_CASH")
|
||||
var space: int = maxi(SupplyCatalog.storage_capacity(facility.definition_id) - SupplyCatalog.inventory_weight(runtime.inventory_service, facility.local_inventory_id) - _incoming_weight(runtime, facility.local_inventory_id), 0)
|
||||
@warning_ignore("integer_division")
|
||||
var slots := space / int(item[&"unit_weight"])
|
||||
quote[&"purchase_quote"] = frozen
|
||||
quote[&"total_cost"] = frozen[&"effective_total"]
|
||||
quote[&"cash_after"] = cash - int(frozen[&"effective_total"])
|
||||
quote[&"max_quantity"] = PurchaseQuoteV2.affordable_quantity(cash, slots, int(item[&"unit_price"]))
|
||||
quote[&"ok"] = false
|
||||
quote[&"reason"] = &""
|
||||
if not facility.allows_logistics():
|
||||
quote[&"reason"] = &"FACILITY_CLOSED"
|
||||
elif int(frozen[&"effective_total"]) > cash:
|
||||
quote[&"reason"] = &"INSUFFICIENT_FUNDS"
|
||||
elif quantity * int(item[&"unit_weight"]) > space:
|
||||
quote[&"reason"] = &"STORAGE_FULL"
|
||||
else:
|
||||
quote[&"ok"] = true
|
||||
return quote
|
||||
|
||||
|
||||
func _preview_purchase_v1(runtime: Variant, warehouse_id: StringName, item_id: StringName, quantity: int) -> Dictionary:
|
||||
var cash: int = runtime.economy_service.get_balance(&"PLAYER_CASH")
|
||||
var item := SupplyCatalog.get_item(item_id)
|
||||
var facility: FacilityInstance = runtime.facility_service.get_instance(warehouse_id)
|
||||
var quote := {&"ok": false, &"reason": &"", &"total_cost": 0, &"cash_after": cash, &"quantity_after": 0, &"max_quantity": 0}
|
||||
if facility == null or facility.definition_id != &"warehouse":
|
||||
quote[&"reason"] = &"NOT_WAREHOUSE"
|
||||
return quote
|
||||
if item.is_empty() or not bool(item.get(&"purchasable", false)):
|
||||
quote[&"reason"] = &"ITEM_NOT_PURCHASABLE"
|
||||
return quote
|
||||
var price := int(item[&"unit_price"])
|
||||
var space: int = maxi(SupplyCatalog.storage_capacity(facility.definition_id) - SupplyCatalog.inventory_weight(runtime.inventory_service, facility.local_inventory_id) - _incoming_weight(runtime, facility.local_inventory_id), 0)
|
||||
quote[&"max_quantity"] = mini(space / int(item[&"unit_weight"]), maxi(cash, 0) / price)
|
||||
quote[&"quantity_after"] = runtime.inventory_service.total_quantity(facility.local_inventory_id, item_id) + maxi(quantity, 0)
|
||||
quote[&"total_cost"] = maxi(quantity, 0) * price
|
||||
quote[&"cash_after"] = cash - int(quote[&"total_cost"])
|
||||
if quantity <= 0 or quantity > 10000:
|
||||
quote[&"reason"] = &"INVALID_QUANTITY"
|
||||
elif not facility.allows_logistics():
|
||||
quote[&"reason"] = &"FACILITY_CLOSED"
|
||||
elif int(quote[&"total_cost"]) > cash:
|
||||
quote[&"reason"] = &"INSUFFICIENT_FUNDS"
|
||||
elif quantity * int(item[&"unit_weight"]) > space:
|
||||
quote[&"reason"] = &"STORAGE_FULL"
|
||||
else:
|
||||
quote[&"ok"] = true
|
||||
return quote
|
||||
|
||||
|
||||
func purchase(runtime: Variant, command: SimulationCommand) -> CommandResult:
|
||||
var payload := command.payload
|
||||
if not _text(payload.get(&"warehouse_id")) or not _text(payload.get(&"item_id")) or not _integer(payload.get(&"quantity")):
|
||||
return _failure(command, &"INVALID_PAYLOAD")
|
||||
var warehouse_id := StringName(payload[&"warehouse_id"])
|
||||
var item_id := StringName(payload[&"item_id"])
|
||||
var quantity := int(payload[&"quantity"])
|
||||
return _purchase_paid(runtime, warehouse_id, item_id, quantity,
|
||||
runtime._runtime_event_minute(), StringName("supply.purchase.%d" % command.command_id), command.command_id)
|
||||
|
||||
|
||||
func _purchase_paid(runtime: Variant, warehouse_id: StringName, item_id: StringName,
|
||||
quantity: int, minute: int, ledger_key: StringName, command_id: int = 0, record_auto_attempt: bool = false) -> CommandResult:
|
||||
# Shared transaction only; internal replenishment does not enqueue a command.
|
||||
var quote := preview_purchase(runtime, warehouse_id, item_id, quantity)
|
||||
if not bool(quote[&"ok"]):
|
||||
return _purchase_failure(command_id, StringName(quote[&"reason"]), quote)
|
||||
var facility: FacilityInstance = runtime.facility_service.get_instance(warehouse_id)
|
||||
var item := SupplyCatalog.get_item(item_id)
|
||||
var inventory_before: Dictionary = runtime.inventory_service.create_snapshot()
|
||||
var economy_before: Dictionary = runtime.economy_service.create_snapshot()
|
||||
var plans_before: Dictionary = runtime.auto_purchase_plans.create_snapshot() if record_auto_attempt else {}
|
||||
var stocked: Dictionary = runtime.inventory_service.add_stack(facility.local_inventory_id, item_id, quantity, 100, minute + int(item[&"shelf_life_minutes"]), minute, int(item[&"unit_weight"]))
|
||||
if not bool(stocked.get(&"ok", false)):
|
||||
runtime.inventory_service.restore_snapshot(inventory_before)
|
||||
runtime.economy_service.restore_snapshot(economy_before)
|
||||
return _purchase_failure(command_id, &"INVENTORY_ERROR")
|
||||
var memo: StringName = SupplyAutoPurchasePlans.receipt_memo(item_id, quantity, int(item[&"unit_price"]), int(quote[&"total_cost"])) if record_auto_attempt else &"supply_purchase"
|
||||
if quote.has(&"purchase_quote"):
|
||||
memo = PurchaseQuoteV2.receipt_memo(quote[&"purchase_quote"])
|
||||
var paid: CommandResult = runtime.economy_service.transfer(&"PLAYER_CASH", runtime.OPERATING_EXPENSE_ACCOUNT, int(quote[&"total_cost"]), minute, &"OPERATING_EXPENSE", warehouse_id, ledger_key, memo, &"", false)
|
||||
if not paid.is_success():
|
||||
runtime.inventory_service.restore_snapshot(inventory_before)
|
||||
runtime.economy_service.restore_snapshot(economy_before)
|
||||
return _purchase_failure(command_id, &"PAYMENT_FAILED")
|
||||
var recorded := true
|
||||
if record_auto_attempt:
|
||||
if quote.has(&"purchase_quote"):
|
||||
recorded = runtime.auto_purchase_plans.record_attempt(warehouse_id, item_id, minute, CommandResult.succeeded(0, {&"transaction_id": paid.details[&"transaction_id"], &"quantity": quantity, &"purchase_quote": quote[&"purchase_quote"], &"total_cost": quote[&"total_cost"]}), runtime.economy_service)
|
||||
else:
|
||||
recorded = runtime.auto_purchase_plans.record_attempt(warehouse_id, item_id, minute, CommandResult.succeeded(0, {&"transaction_id": paid.details[&"transaction_id"], &"quantity": quantity, &"unit_price": item[&"unit_price"], &"total_cost": quote[&"total_cost"]}), runtime.economy_service)
|
||||
if not recorded:
|
||||
runtime.inventory_service.restore_snapshot(inventory_before)
|
||||
runtime.economy_service.restore_snapshot(economy_before)
|
||||
return _purchase_failure(command_id, &"PAYMENT_FAILED")
|
||||
if not runtime.economy_service.commit_transaction_notification(StringName(paid.details[&"transaction_id"])):
|
||||
runtime.inventory_service.restore_snapshot(inventory_before)
|
||||
runtime.economy_service.restore_snapshot(economy_before)
|
||||
if record_auto_attempt:
|
||||
runtime.auto_purchase_plans.restore_snapshot(plans_before, runtime.facility_service, runtime.economy_service, minute)
|
||||
return _purchase_failure(command_id, &"PAYMENT_FAILED")
|
||||
quote.merge({&"warehouse_id": warehouse_id, &"item_id": item_id, &"quantity": quantity, &"transaction_id": paid.details[&"transaction_id"]})
|
||||
return CommandResult.succeeded(command_id, quote)
|
||||
|
||||
|
||||
func set_auto_purchase(runtime: Variant, command: SimulationCommand) -> CommandResult:
|
||||
var payload := command.payload
|
||||
if not _exact_keys(payload, [&"warehouse_id", &"item_id", &"enabled", &"target_stock"]) \
|
||||
or not _text(payload[&"warehouse_id"]) or not _text(payload[&"item_id"]) \
|
||||
or typeof(payload[&"enabled"]) != TYPE_BOOL or typeof(payload[&"target_stock"]) != TYPE_INT:
|
||||
return _failure(command, &"INVALID_PAYLOAD")
|
||||
var changed: Dictionary = runtime.auto_purchase_plans.set_plan(
|
||||
StringName(payload[&"warehouse_id"]), StringName(payload[&"item_id"]),
|
||||
payload[&"enabled"], payload[&"target_stock"], runtime.facility_service)
|
||||
if not bool(changed.get(&"ok", false)):
|
||||
return _failure(command, StringName(changed.get(&"reason", &"INVALID_TARGET")), changed)
|
||||
return CommandResult.succeeded(command.command_id, changed[&"plan"])
|
||||
|
||||
|
||||
func auto_purchase_report(runtime: Variant, warehouse_id: StringName, item_id: StringName) -> Dictionary:
|
||||
var row: Dictionary = runtime.auto_purchase_plans.get_plan(warehouse_id, item_id)
|
||||
var facility: FacilityInstance = runtime.facility_service.get_instance(warehouse_id)
|
||||
row[&"maximum_target"] = SupplyAutoPurchasePlans.maximum_target(warehouse_id, item_id, runtime.facility_service)
|
||||
row[&"physical_quantity"] = runtime.inventory_service.total_quantity(facility.local_inventory_id, item_id) if facility != null else 0
|
||||
row[&"incoming_quantity"] = _incoming_quantity(runtime, facility.local_inventory_id, item_id) if facility != null else 0
|
||||
row[&"deficit"] = maxi(int(row[&"target_stock"]) - int(row[&"physical_quantity"]) - int(row[&"incoming_quantity"]), 0)
|
||||
row[&"quote"] = preview_purchase(runtime, warehouse_id, item_id, int(row[&"deficit"])) if int(row[&"deficit"]) > 0 else {}
|
||||
row[&"reason"] = &""
|
||||
if not bool(row[&"enabled"]):
|
||||
row[&"state"] = &"DISABLED"
|
||||
elif bool(runtime.get_operations_report().get(&"tick_blocked", false)):
|
||||
row[&"state"] = &"BLOCKED"
|
||||
row[&"reason"] = &"OPERATIONS_BLOCKED"
|
||||
elif int(runtime._state.get_resource(&"mana")) <= 0:
|
||||
row[&"state"] = &"BLOCKED"
|
||||
row[&"reason"] = &"NO_POWER"
|
||||
elif _receiver_will_close(facility, runtime._clock.absolute_minute):
|
||||
row[&"state"] = &"BLOCKED"
|
||||
row[&"reason"] = &"FACILITY_CLOSED"
|
||||
elif int(row[&"last_attempt_minute"]) == runtime._clock.absolute_minute:
|
||||
row[&"state"] = &"ORDERED_THIS_MINUTE" if row[&"last_result"] == SupplyAutoPurchasePlans.RESULT_PURCHASED else &"BLOCKED"
|
||||
if row[&"state"] == &"BLOCKED": row[&"reason"] = row[&"last_result"]
|
||||
elif int(row[&"deficit"]) == 0:
|
||||
row[&"state"] = &"TARGET_REACHED"
|
||||
elif bool((row[&"quote"] as Dictionary).get(&"ok", false)):
|
||||
row[&"state"] = &"READY"
|
||||
else:
|
||||
row[&"state"] = &"BLOCKED"
|
||||
row[&"reason"] = (row[&"quote"] as Dictionary).get(&"reason", &"UNAVAILABLE")
|
||||
return row
|
||||
|
||||
|
||||
func advance_auto_purchases(runtime: Variant, minute: int) -> Array[Dictionary]:
|
||||
var results: Array[Dictionary] = []
|
||||
if bool(runtime.get_operations_report().get(&"tick_blocked", false)) or int(runtime._state.get_resource(&"mana")) <= 0:
|
||||
return results
|
||||
for plan: Dictionary in runtime.auto_purchase_plans.get_plans():
|
||||
if not bool(plan[&"enabled"]) or int(plan[&"last_attempt_minute"]) >= minute:
|
||||
continue
|
||||
var warehouse_id := StringName(plan[&"warehouse_id"])
|
||||
var item_id := StringName(plan[&"item_id"])
|
||||
var row := auto_purchase_report(runtime, warehouse_id, item_id)
|
||||
var facility: FacilityInstance = runtime.facility_service.get_instance(warehouse_id)
|
||||
if int(row[&"deficit"]) <= 0 or facility == null or not facility.allows_logistics() or _receiver_will_close(facility, minute):
|
||||
continue
|
||||
var ledger_key := SupplyAutoPurchasePlans.order_key(warehouse_id, item_id, minute)
|
||||
var prior_id: StringName = runtime.economy_service.get_transaction_id_for_idempotency_key(ledger_key)
|
||||
var result: CommandResult
|
||||
if prior_id.is_empty():
|
||||
if row[&"state"] != &"READY" or not bool((row[&"quote"] as Dictionary).get(&"ok", false)):
|
||||
continue
|
||||
result = _purchase_paid(runtime, warehouse_id, item_id, int(row[&"deficit"]), minute, ledger_key, 0, true)
|
||||
else:
|
||||
# A committed key replays its original item/quantity/price, even if
|
||||
# today's quote is unaffordable. It never stocks, charges or notifies.
|
||||
var receipt := SupplyAutoPurchasePlans.receipt_from_ledger(runtime.economy_service, warehouse_id, item_id, minute, prior_id)
|
||||
if receipt.is_empty():
|
||||
var frozen := PurchaseQuoteV2.receipt_from_ledger(runtime.economy_service, warehouse_id, item_id, minute, prior_id)
|
||||
if frozen.is_empty():
|
||||
result = _purchase_failure(0, &"REPLAY_MISMATCH")
|
||||
else:
|
||||
result = CommandResult.succeeded(0, {&"transaction_id": prior_id, &"quantity": frozen[&"quantity"], &"purchase_quote": frozen, &"total_cost": frozen[&"effective_total"], &"replayed": true})
|
||||
else:
|
||||
result = CommandResult.succeeded(0, {&"transaction_id": prior_id, &"quantity": receipt[&"quantity"], &"unit_price": receipt[&"unit_price"], &"total_cost": receipt[&"total_cost"], &"replayed": true})
|
||||
if (not result.is_success() or not prior_id.is_empty()) and not runtime.auto_purchase_plans.record_attempt(warehouse_id, item_id, minute, result, runtime.economy_service):
|
||||
push_error("Automatic purchase could not record its committed attempt.")
|
||||
return results
|
||||
results.append({&"warehouse_id": warehouse_id, &"item_id": item_id,
|
||||
&"minute": minute, &"result": result.to_dictionary()})
|
||||
return results
|
||||
|
||||
|
||||
func _receiver_will_close(facility: FacilityInstance, minute: int) -> bool:
|
||||
# LOGISTICS precedes FACILITY_COMPLETION. Honor an already scheduled close
|
||||
# without applying policy early or changing manual purchase/phase ordering.
|
||||
return facility != null and facility.policy_pending_effective_at >= 0 \
|
||||
and facility.policy_pending_effective_at <= minute \
|
||||
and facility.policy_pending.has(&"business_open") \
|
||||
and not bool(facility.policy_pending[&"business_open"])
|
||||
|
||||
|
||||
func _purchase_failure(command_id: int, reason: StringName, details: Dictionary = {}) -> CommandResult:
|
||||
var result := details.duplicate(true)
|
||||
result[&"reason"] = reason
|
||||
return CommandResult.failed(CommandResult.Code.VALIDATION_FAILED, command_id, "Supply command rejected: %s" % reason, result)
|
||||
|
||||
|
||||
func _exact_keys(value: Dictionary, expected: Array[StringName]) -> bool:
|
||||
if value.size() != expected.size(): return false
|
||||
for key: Variant in value:
|
||||
if typeof(key) not in [TYPE_STRING, TYPE_STRING_NAME] or StringName(key) not in expected: return false
|
||||
return true
|
||||
|
||||
|
||||
func set_production(runtime: Variant, command: SimulationCommand) -> CommandResult:
|
||||
var payload := command.payload
|
||||
if not _text(payload.get(&"facility_id")) or not payload.get(&"enabled") is bool or not _integer(payload.get(&"target_stock")):
|
||||
return _failure(command, &"INVALID_PAYLOAD")
|
||||
var facility_id := StringName(payload[&"facility_id"])
|
||||
var facility: FacilityInstance = runtime.facility_service.get_instance(facility_id)
|
||||
if facility == null or facility.definition_id != &"kitchen":
|
||||
return _failure(command, &"NOT_KITCHEN")
|
||||
var result: Dictionary = runtime.kitchen_production.set_plan(facility_id, bool(payload[&"enabled"]), int(payload[&"target_stock"]))
|
||||
if not bool(result.get(&"ok", false)):
|
||||
return _failure(command, StringName(result.get(&"code", &"INVALID_TARGET")), result)
|
||||
return CommandResult.succeeded(command.command_id, result)
|
||||
|
||||
|
||||
func get_report(runtime: Variant) -> Dictionary:
|
||||
var warehouses: Array[Dictionary] = []
|
||||
var kitchens: Array[Dictionary] = []
|
||||
var destinations: Array[Dictionary] = []
|
||||
for facility: FacilityInstance in _facilities(runtime):
|
||||
var row := _facility_row(runtime, facility)
|
||||
match facility.definition_id:
|
||||
&"warehouse":
|
||||
var quote := preview_purchase(runtime, facility.instance_id, SupplyCatalog.RAW_FOOD, 1)
|
||||
row[&"can_receive"] = bool(quote[&"ok"])
|
||||
row[&"reason_codes"] = [] if bool(quote[&"ok"]) else [quote[&"reason"]]
|
||||
row[&"auto_purchase_plans"] = []
|
||||
for item: Dictionary in SupplyCatalog.get_purchase_items():
|
||||
(row[&"auto_purchase_plans"] as Array).append(auto_purchase_report(runtime, facility.instance_id, StringName(item[&"item_id"])))
|
||||
warehouses.append(row)
|
||||
&"kitchen":
|
||||
row.merge(runtime.kitchen_production.get_report(facility.instance_id), true)
|
||||
row.merge({&"target_min": 4, &"target_step": 4, &"target_max": SupplyCatalog.KITCHEN_TARGET_MAX, &"inputs": {SupplyCatalog.RAW_FOOD: 4}, &"outputs": {SupplyCatalog.BASIC_MEAL: 4}}, true)
|
||||
row[&"reason_codes"] = [] if row[&"state"] in [&"PRODUCING", &"READY", &"TARGET_REACHED"] else [row[&"state"]]
|
||||
kitchens.append(row)
|
||||
&"cafeteria":
|
||||
row[&"missing_items"] = {SupplyCatalog.BASIC_MEAL: maxi(12 - runtime.inventory_service.available_quantity(facility.local_inventory_id, SupplyCatalog.BASIC_MEAL), 0)}
|
||||
row[&"reason_codes"] = facility.state_reasons.duplicate()
|
||||
if runtime.inventory_service.available_quantity(facility.local_inventory_id, SupplyCatalog.BASIC_MEAL) <= 0:
|
||||
row[&"reason_codes"].append(&"NO_INPUT")
|
||||
destinations.append(row)
|
||||
var bridge_report: Dictionary = runtime.supply_logistics.get_report()
|
||||
return {&"cash": runtime.economy_service.get_balance(&"PLAYER_CASH"), &"catalog": SupplyCatalog.get_purchase_items(), &"warehouses": warehouses, &"kitchens": kitchens, &"destinations": destinations, &"deliveries": bridge_report.get(&"deliveries", [])}
|
||||
|
||||
|
||||
func ensure_deliveries(runtime: Variant, minute: int) -> void:
|
||||
var facilities := _facilities(runtime)
|
||||
for destination: FacilityInstance in facilities:
|
||||
if not destination.allows_logistics():
|
||||
continue
|
||||
var source_type: StringName
|
||||
var item_id: StringName
|
||||
var target := 0
|
||||
if destination.definition_id == &"kitchen" and bool(runtime.kitchen_production.get_plan(destination.instance_id).get(&"enabled", false)):
|
||||
source_type = &"warehouse"
|
||||
item_id = SupplyCatalog.RAW_FOOD
|
||||
target = SupplyCatalog.RAW_TARGET
|
||||
elif destination.definition_id == &"cafeteria":
|
||||
source_type = &"kitchen"
|
||||
item_id = SupplyCatalog.BASIC_MEAL
|
||||
target = 12
|
||||
else:
|
||||
continue
|
||||
var deficit: int = target - runtime.inventory_service.total_quantity(destination.local_inventory_id, item_id) - _incoming_quantity(runtime, destination.local_inventory_id, item_id)
|
||||
var space: int = SupplyCatalog.storage_capacity(destination.definition_id) - SupplyCatalog.inventory_weight(runtime.inventory_service, destination.local_inventory_id) - _incoming_weight(runtime, destination.local_inventory_id)
|
||||
var needed: int = mini(mini(deficit, space), 4)
|
||||
if needed <= 0:
|
||||
continue
|
||||
var sources: Array[Dictionary] = []
|
||||
for source: FacilityInstance in facilities:
|
||||
if source.definition_id != source_type or not source.allows_logistics():
|
||||
continue
|
||||
if source_type == &"kitchen" and not _has_production_plan(runtime, source.instance_id):
|
||||
continue
|
||||
var available: int = runtime.inventory_service.available_quantity(source.local_inventory_id, item_id, minute)
|
||||
if available <= 0:
|
||||
continue
|
||||
sources.append({&"facility": source, &"available": available, &"distance": _connection_distance(runtime, source, destination)})
|
||||
# Prefer a connected nearby supplier; IDs resolve equal routes stably.
|
||||
# If none is connected, retain one visible request for route repair.
|
||||
sources.sort_custom(func(a: Dictionary, b: Dictionary) -> bool:
|
||||
if a[&"distance"] != b[&"distance"]: return a[&"distance"] < b[&"distance"]
|
||||
return String(a[&"facility"].instance_id) < String(b[&"facility"].instance_id))
|
||||
for source_row: Dictionary in sources:
|
||||
var source: FacilityInstance = source_row[&"facility"]
|
||||
var available := int(source_row[&"available"])
|
||||
var ids_before: Dictionary = runtime.id_generator.create_snapshot()
|
||||
var request_id := StringName("supply.%s" % runtime.id_generator.next_id(&"logistics_request"))
|
||||
var result: CommandResult = runtime._execute_create_logistics_request(SimulationCommand.new(0, minute, minute, 50, &"create_logistics_request", &"supply", destination.instance_id, {&"request_id": request_id, &"source_inventory_id": source.local_inventory_id, &"destination_inventory_id": destination.local_inventory_id, &"item_requirements": {item_id: mini(needed, available)}, &"priority": 50}))
|
||||
if not result.is_success():
|
||||
runtime.id_generator.restore_snapshot(ids_before)
|
||||
break
|
||||
|
||||
|
||||
func validate_demolition(runtime: Variant, facility_id: StringName) -> Dictionary:
|
||||
var facility: FacilityInstance = runtime.facility_service.get_instance(facility_id)
|
||||
if facility == null:
|
||||
return {&"ok": true}
|
||||
if SupplyCatalog.inventory_weight(runtime.inventory_service, facility.local_inventory_id) > 0:
|
||||
return {&"ok": false, &"reason": &"STOCK_REMAINS"}
|
||||
for request: LogisticsRequest in runtime.logistics_requests.values():
|
||||
if not request.is_terminal() and facility.local_inventory_id in [request.source_inventory_id, request.destination_inventory_id]:
|
||||
return {&"ok": false, &"reason": &"DELIVERY_ACTIVE"}
|
||||
if facility.definition_id == &"kitchen":
|
||||
var report: Dictionary = runtime.kitchen_production.get_report(facility_id)
|
||||
if bool(report.get(&"enabled", false)) or not report.get(&"active_batch", {}).is_empty():
|
||||
return {&"ok": false, &"reason": &"PRODUCTION_ACTIVE"}
|
||||
return {&"ok": true}
|
||||
|
||||
|
||||
func _facility_row(runtime: Variant, facility: FacilityInstance) -> Dictionary:
|
||||
var definition: FacilityDefinition = runtime.definition_registry.get_facility(facility.definition_id)
|
||||
return {&"facility_id": facility.instance_id, &"display_name": definition.display_name, &"origin": facility.origin, &"layer": facility.origin.z, &"used": SupplyCatalog.inventory_weight(runtime.inventory_service, facility.local_inventory_id), &"capacity": SupplyCatalog.storage_capacity(facility.definition_id), &"stock": _stock(runtime, facility.local_inventory_id)}
|
||||
|
||||
|
||||
func _stock(runtime: Variant, inventory_id: StringName) -> Array[Dictionary]:
|
||||
var rows: Array[Dictionary] = []
|
||||
for item_id: StringName in [SupplyCatalog.RAW_FOOD, SupplyCatalog.BASIC_MEAL]:
|
||||
var total: int = runtime.inventory_service.total_quantity(inventory_id, item_id)
|
||||
var available: int = runtime.inventory_service.available_quantity(inventory_id, item_id)
|
||||
rows.append({&"item_id": item_id, &"total": total, &"available": available, &"reserved": total - available, &"in_transit": _incoming_quantity(runtime, inventory_id, item_id)})
|
||||
return rows
|
||||
|
||||
|
||||
func _incoming_quantity(runtime: Variant, inventory_id: StringName, item_id: StringName) -> int:
|
||||
var quantity := 0
|
||||
for request: LogisticsRequest in runtime.logistics_requests.values():
|
||||
if request.is_terminal():
|
||||
continue
|
||||
if runtime.supply_logistics.is_returning(request.request_id):
|
||||
if request.source_inventory_id == inventory_id:
|
||||
quantity += runtime.inventory_service.total_quantity(StringName("cargo:%s" % request.assigned_carrier_id), item_id)
|
||||
elif request.destination_inventory_id == inventory_id:
|
||||
quantity += int(request.item_requirements.get(item_id, 0))
|
||||
return quantity
|
||||
|
||||
|
||||
func _incoming_weight(runtime: Variant, inventory_id: StringName) -> int:
|
||||
var weight := 0
|
||||
for request: LogisticsRequest in runtime.logistics_requests.values():
|
||||
if request.is_terminal():
|
||||
continue
|
||||
if runtime.supply_logistics.is_returning(request.request_id):
|
||||
if request.source_inventory_id == inventory_id:
|
||||
weight += SupplyCatalog.inventory_weight(runtime.inventory_service, StringName("cargo:%s" % request.assigned_carrier_id))
|
||||
elif request.destination_inventory_id == inventory_id:
|
||||
weight += request.total_weight
|
||||
return weight
|
||||
|
||||
|
||||
func _facilities(runtime: Variant) -> Array[FacilityInstance]:
|
||||
var rows: Array[FacilityInstance] = runtime.facility_service.get_instances()
|
||||
rows.sort_custom(func(a: FacilityInstance, b: FacilityInstance) -> bool: return String(a.instance_id) < String(b.instance_id))
|
||||
return rows
|
||||
|
||||
|
||||
func _failure(command: SimulationCommand, reason: StringName, details: Dictionary = {}) -> CommandResult:
|
||||
var result := details.duplicate(true)
|
||||
result[&"reason"] = reason
|
||||
return CommandResult.failed(CommandResult.Code.VALIDATION_FAILED, command.command_id, "Supply command rejected: %s" % reason, result)
|
||||
|
||||
|
||||
func _text(value: Variant) -> bool:
|
||||
return (value is String or value is StringName) and not String(value).is_empty()
|
||||
|
||||
|
||||
func _integer(value: Variant) -> bool:
|
||||
return value is int or (value is float and is_finite(value) and value == floor(value) and absf(value) <= 1000000.0)
|
||||
|
||||
|
||||
func _has_production_plan(runtime: Variant, facility_id: StringName) -> bool:
|
||||
for plan: Dictionary in runtime.kitchen_production.get_plans():
|
||||
if StringName(plan[&"facility_id"]) == facility_id:
|
||||
return true
|
||||
return false
|
||||
|
||||
|
||||
func _connection_distance(runtime: Variant, source: FacilityInstance, destination: FacilityInstance) -> int:
|
||||
var distance := 1000000
|
||||
var seen: Dictionary = {}
|
||||
for cell: Vector3i in source.occupied_cells:
|
||||
for delta: Vector3i in [Vector3i.ZERO, Vector3i.LEFT, Vector3i.RIGHT, Vector3i.UP, Vector3i.DOWN]:
|
||||
var start := cell + delta
|
||||
if seen.has(start) or not runtime.path_service.has_cell(start):
|
||||
continue
|
||||
seen[start] = true
|
||||
var route: Dictionary = runtime.supply_logistics.find_facility_access_path(start, destination)
|
||||
if bool(route.get(&"reachable", false)):
|
||||
distance = mini(distance, int(route[&"steps"]))
|
||||
return distance
|
||||
+243
@@ -0,0 +1,243 @@
|
||||
{
|
||||
"passed": true,
|
||||
"review_sha256": "25d15928c713cb1608490bae5ea10d6374b21a764c87ae19ba2ce32a2d20ba39",
|
||||
"verified_entries": [
|
||||
{
|
||||
"path": "/Applications/Godot.app/Contents/MacOS/Godot",
|
||||
"bytes": 351312912,
|
||||
"sha256": "c7cccbf8fb143e34e02fd6521e09be2c2b974f0d5db080b19071c9c570718ccf"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-walk-edges-candidate-r265-r03/performance_budget.candidate.gd",
|
||||
"bytes": 11250,
|
||||
"sha256": "1010129d3124c3aec037c840a5766a7cdabe60c654999dfb6f23b224140a73f8"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-local-names-candidate-r239/stage/scripts/world/path_service.gd",
|
||||
"bytes": 132925,
|
||||
"sha256": "6b7f4e989ea9b09495f814d8ecb294028d10794005966414bf52640e122b0d17"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-single-actor-path-native-r03/diagnostic-measurement/checkpoint646.varbytes.zst",
|
||||
"bytes": 240032,
|
||||
"sha256": "1a88f7ed27d1d32102c6fe3a9533221d2565191712ed15b631190479d1d41505"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-report-window-trusted-report-whole647-native-r02/diagnostic-measurement/after647.varbytes.zst",
|
||||
"bytes": 246720,
|
||||
"sha256": "684ba40e9f649b7dd4bfc620185d7cd18bae3111c3b4038e48aaad5a9168d880"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd",
|
||||
"bytes": 1441,
|
||||
"sha256": "3dd8e4f3590fd5b274811c5fffdd49e12e69803b5385c409f786245b9fed1b62"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/diagnostic.gd",
|
||||
"bytes": 6807,
|
||||
"sha256": "f076e93357b521c0add060a262a725637daf9fa39c9bdb8ccb156f20bfcba9a1"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-input-copy-local-r335/candidate.gdextension",
|
||||
"bytes": 214,
|
||||
"sha256": "a51d6bbbef6a00b82ded03a0d637c057b6b70d13025d4c3042f2984d0cb7152a"
|
||||
},
|
||||
{
|
||||
"path": "/private/tmp/TheTree-input-copy-r335-3afabc8ef9ee42d0be34994471a451b5/candidate.dylib",
|
||||
"bytes": 433744,
|
||||
"sha256": "39f8ed73f077d15037d85b9cb53f38389c032a36dea7ff04348e5ef05c736907"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/autoload/simulation_runtime.gd",
|
||||
"bytes": 612068,
|
||||
"sha256": "7eb24adbf91fe53cde14954dda12abd5efb05130de7d356d8df281ee99065e86"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/autoload/simulation_runtime.gd",
|
||||
"bytes": 621773,
|
||||
"sha256": "ce260f1158adfb8d9adda1ea00fa29b3c76bc4968c9f7996fdcf62193e28b540"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/autoload/simulation_runtime.gd",
|
||||
"bytes": 612068,
|
||||
"sha256": "7eb24adbf91fe53cde14954dda12abd5efb05130de7d356d8df281ee99065e86"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/inventory/inventory_service.gd",
|
||||
"bytes": 57923,
|
||||
"sha256": "7ee83b335864385119ca757037c3cdb912957aa4478a6312a0898a734e41f31a"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/inventory/inventory_service.gd",
|
||||
"bytes": 60808,
|
||||
"sha256": "a93e7486fab66938ce7356b16202dddf0d4dd2f9c30e6b9312ec4ee98878480e"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/inventory/inventory_service.gd",
|
||||
"bytes": 57923,
|
||||
"sha256": "7ee83b335864385119ca757037c3cdb912957aa4478a6312a0898a734e41f31a"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/facility/facility_service.gd",
|
||||
"bytes": 44951,
|
||||
"sha256": "ceb4a3e9224587423f273cdb2b56e6843ab176ac1fc4fe79dd498b5ed5c33b77"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/facility/facility_service.gd",
|
||||
"bytes": 47788,
|
||||
"sha256": "c24d9b475c66046dc7342401a74fdc084ca6698506fdb9284afbadd6c5e68cfa"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/facility/facility_service.gd",
|
||||
"bytes": 44951,
|
||||
"sha256": "ceb4a3e9224587423f273cdb2b56e6843ab176ac1fc4fe79dd498b5ed5c33b77"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/supply/supply_management_service.gd",
|
||||
"bytes": 25019,
|
||||
"sha256": "e4ad420191020485c027004f64bb00fad9da195fe956ef10dc0c787412018f7f"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/supply/supply_management_service.gd",
|
||||
"bytes": 27952,
|
||||
"sha256": "87f2a3c36ef8b4569d17191f0c376fc957462dd7fe33a832c7284fdceb4a5b3c"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/supply/supply_management_service.gd",
|
||||
"bytes": 25019,
|
||||
"sha256": "e4ad420191020485c027004f64bb00fad9da195fe956ef10dc0c787412018f7f"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/supply/supply_logistics_bridge.gd",
|
||||
"bytes": 28100,
|
||||
"sha256": "b9e394af788595d2744b71f1907c8e7c3d762d38ff49992b1ee74e63b9639e80"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/supply/supply_logistics_bridge.gd",
|
||||
"bytes": 28814,
|
||||
"sha256": "6887a702c1eb6f9e91f689fd734f9bbc386a9cce55a68b1682c3a18be620976a"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/supply/supply_logistics_bridge.gd",
|
||||
"bytes": 28100,
|
||||
"sha256": "b9e394af788595d2744b71f1907c8e7c3d762d38ff49992b1ee74e63b9639e80"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/supply/kitchen_production_service.gd",
|
||||
"bytes": 18872,
|
||||
"sha256": "f3bc6bdc1a0ba278e9411108172ceceb7eb06520b4e33f93f35684da1f103c62"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/supply/kitchen_production_service.gd",
|
||||
"bytes": 19610,
|
||||
"sha256": "b751511484258edb471567639f150d8dcfb69ff4245a2273718cfcb3de04ca51"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/supply/kitchen_production_service.gd",
|
||||
"bytes": 18872,
|
||||
"sha256": "f3bc6bdc1a0ba278e9411108172ceceb7eb06520b4e33f93f35684da1f103c62"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/core/simulation_kernel.gd",
|
||||
"bytes": 7602,
|
||||
"sha256": "341c0c878c4894adbac628d0db6362ff69fc3347bdd9e61e50936e15dc2d1edb"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/core/simulation_kernel.gd",
|
||||
"bytes": 8264,
|
||||
"sha256": "9c67f2b22a38ab396e9d84522b3d54edb7be85878eb6a745deecb9ca2bde8692"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/core/simulation_kernel.gd",
|
||||
"bytes": 7602,
|
||||
"sha256": "341c0c878c4894adbac628d0db6362ff69fc3347bdd9e61e50936e15dc2d1edb"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/input.json",
|
||||
"bytes": 1023880,
|
||||
"sha256": "43f57b58c7533dae7965b71a739dd256219e264b1f2b3bb8639c8bf1a625696e"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338.py",
|
||||
"bytes": 6430,
|
||||
"sha256": "df468edfdc85ec9f445206ad005254d0472d1f8cc2f2c3fbea41db05dbd53b9a"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/tools/run_all_tests.py",
|
||||
"bytes": 26296,
|
||||
"sha256": "320ca668732b4ff72fc4449998af2327d4e5c527b06896740806aaf0487282b4"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/tools/regression/owned_outer.py",
|
||||
"bytes": 4177,
|
||||
"sha256": "c2e3483b76db1a3ff940f23f88ea0083fc78736e874ebcdb385d766dde8866e7"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-build-preview-monitor-compressed-r06.gd",
|
||||
"bytes": 17582,
|
||||
"sha256": "92d5e1956f4e613e12555d756de4f71fef03678cde159ac68fac3188ce3f336e"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-cache-public-mutations-r144/profile_guard.gd",
|
||||
"bytes": 2276,
|
||||
"sha256": "597696c705cc8f0e79a35265ca3ef8df55f7fc3c4e0e5a2ce9a4e20e29e29a6f"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/core/performance_budget.gd",
|
||||
"bytes": 10355,
|
||||
"sha256": "742c464d16ab417cbc3c2930d43e508faf5c9f7688da416324ca1150bdb9b6b9"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/project.godot",
|
||||
"bytes": 1294,
|
||||
"sha256": "686f3da7f6b592cd95d84e71a83374a28173914b377eafa4a6e005d70062d00d"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-input-copy-build-actual-independent-review-r334.json",
|
||||
"bytes": 40719,
|
||||
"sha256": "991e093110a35df5742e4b6bbd9254d664f20c280056fa6dd19e35be0bdcd871"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-input-copy-whole-actual-independent-review-r336.json",
|
||||
"bytes": 40888,
|
||||
"sha256": "671fedcbd0d48a42809aa6ca19d91c5ed4d22f4e6201ad1a00b3d3be18f291b8"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/input-before-phase-mapping-correction.json",
|
||||
"bytes": 1017508,
|
||||
"sha256": "fe9c06fd72ccd6bb88557082b5015bd8ad8386eee44371fdb4bd9dc8beb658db"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/input-before-transaction-method-correction.json",
|
||||
"bytes": 1011383,
|
||||
"sha256": "ca1c57a6c3266df161f8832842bc61c1305ecd2ecd77b7527533dcb44123f639"
|
||||
},
|
||||
{
|
||||
"path": "/private/tmp/thetree-prepare-residual-r338.py",
|
||||
"bytes": 9527,
|
||||
"sha256": "ff0e7c5fcb572b900585b334890612e19894f347ea57a6e1541935c7df6f3468"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/IMPLEMENTATION_PLAN.md",
|
||||
"bytes": 492489,
|
||||
"sha256": "4e9748ca579001e5673f83568d64bbe45b6bad7420ee6481901496f0fd7e9f28"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/PROGRESS_INTEGRATION.md",
|
||||
"bytes": 410553,
|
||||
"sha256": "b5617405aaa913cef5f5e23bbc5141bfb746de88926116c02ea2d33bd5ea7a22"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/work_packages.json",
|
||||
"bytes": 1188101,
|
||||
"sha256": "e7e8d40e9a9a85095d6e4ad96ab305fa1bf83f10f754b3c541e27cb78b1f6f67"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/progress_snapshot.json",
|
||||
"bytes": 591756,
|
||||
"sha256": "db411f761cc2e64d9ae7859ebdc085bfacc1b649dd4c7241c34a96fd28e07b97"
|
||||
}
|
||||
],
|
||||
"unit_accepted": false,
|
||||
"performance_accepted": false
|
||||
}
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
{
|
||||
"plan_id": "P23-02",
|
||||
"candidate": "r333/library334",
|
||||
"selected_parent": "r274/library275",
|
||||
"production": "r32",
|
||||
"source_audit_only": true,
|
||||
"pins": {
|
||||
"kernel_before": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/core/simulation_kernel.gd",
|
||||
"bytes": 7602,
|
||||
"sha256": "341c0c878c4894adbac628d0db6362ff69fc3347bdd9e61e50936e15dc2d1edb"
|
||||
},
|
||||
"runtime_before": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/autoload/simulation_runtime.gd",
|
||||
"bytes": 612068,
|
||||
"sha256": "7eb24adbf91fe53cde14954dda12abd5efb05130de7d356d8df281ee99065e86"
|
||||
},
|
||||
"old_metrics": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-residual-diagnostic-r311-r02/metrics-root-decoded.json",
|
||||
"bytes": 4566,
|
||||
"sha256": "54e2e7aa9c6304b8d1ead5853eb78eafaad4cdeffb2dd3e4784643992a4d319f"
|
||||
}
|
||||
},
|
||||
"phase_mapping": [
|
||||
{
|
||||
"index": 0,
|
||||
"name": "APPLY_COMMANDS",
|
||||
"old_r274_inclusive_us": 13
|
||||
},
|
||||
{
|
||||
"index": 1,
|
||||
"name": "TIME_BOUNDARIES",
|
||||
"old_r274_inclusive_us": 1121
|
||||
},
|
||||
{
|
||||
"index": 2,
|
||||
"name": "MANA",
|
||||
"old_r274_inclusive_us": 340
|
||||
},
|
||||
{
|
||||
"index": 3,
|
||||
"name": "CONSTRUCTION",
|
||||
"old_r274_inclusive_us": 118618
|
||||
},
|
||||
{
|
||||
"index": 4,
|
||||
"name": "LOGISTICS",
|
||||
"old_r274_inclusive_us": 89293
|
||||
},
|
||||
{
|
||||
"index": 5,
|
||||
"name": "FACILITY_COMPLETION",
|
||||
"old_r274_inclusive_us": 970
|
||||
},
|
||||
{
|
||||
"index": 6,
|
||||
"name": "VITALS_AND_ENVIRONMENT",
|
||||
"old_r274_inclusive_us": 1063
|
||||
},
|
||||
{
|
||||
"index": 7,
|
||||
"name": "INCIDENTS_AND_EVENTS",
|
||||
"old_r274_inclusive_us": 218
|
||||
},
|
||||
{
|
||||
"index": 8,
|
||||
"name": "FACILITY_QUEUES",
|
||||
"old_r274_inclusive_us": 180
|
||||
},
|
||||
{
|
||||
"index": 9,
|
||||
"name": "AI_DECISIONS",
|
||||
"old_r274_inclusive_us": 979790
|
||||
},
|
||||
{
|
||||
"index": 10,
|
||||
"name": "PUBLISH_SNAPSHOT",
|
||||
"old_r274_inclusive_us": 76865
|
||||
}
|
||||
],
|
||||
"correction": "Old 311 phase3 118618us is construction, phase4 89293us logistics, phase5 970us facility completion. Earlier inventory/facility attribution was incorrect. Old timings are instrumented and not current r333 performance.",
|
||||
"next_decision": "Use the current single phase/submethod measurement to group meaningful related corrections. Do not repeat rejected r204 or tiny input-copy pair experiments. Preserve rollback, callbacks, full oracle state, and original requirements.",
|
||||
"unit_accepted": false,
|
||||
"performance_accepted": false
|
||||
}
|
||||
+358
@@ -0,0 +1,358 @@
|
||||
{
|
||||
"passed": true,
|
||||
"review_sha256": "c0fcbaf02f18618a7f833c70f0f0cd3c1e517f5318061cca0158c9c288a6503a",
|
||||
"verified_entries": [
|
||||
{
|
||||
"path": "/Applications/Godot.app/Contents/MacOS/Godot",
|
||||
"bytes": 351312912,
|
||||
"sha256": "c7cccbf8fb143e34e02fd6521e09be2c2b974f0d5db080b19071c9c570718ccf"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-walk-edges-candidate-r265-r03/performance_budget.candidate.gd",
|
||||
"bytes": 11250,
|
||||
"sha256": "1010129d3124c3aec037c840a5766a7cdabe60c654999dfb6f23b224140a73f8"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-local-names-candidate-r239/stage/scripts/world/path_service.gd",
|
||||
"bytes": 132925,
|
||||
"sha256": "6b7f4e989ea9b09495f814d8ecb294028d10794005966414bf52640e122b0d17"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-single-actor-path-native-r03/diagnostic-measurement/checkpoint646.varbytes.zst",
|
||||
"bytes": 240032,
|
||||
"sha256": "1a88f7ed27d1d32102c6fe3a9533221d2565191712ed15b631190479d1d41505"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-report-window-trusted-report-whole647-native-r02/diagnostic-measurement/after647.varbytes.zst",
|
||||
"bytes": 246720,
|
||||
"sha256": "684ba40e9f649b7dd4bfc620185d7cd18bae3111c3b4038e48aaad5a9168d880"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd",
|
||||
"bytes": 1441,
|
||||
"sha256": "3dd8e4f3590fd5b274811c5fffdd49e12e69803b5385c409f786245b9fed1b62"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/diagnostic.gd",
|
||||
"bytes": 6807,
|
||||
"sha256": "f076e93357b521c0add060a262a725637daf9fa39c9bdb8ccb156f20bfcba9a1"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-input-copy-local-r335/candidate.gdextension",
|
||||
"bytes": 214,
|
||||
"sha256": "a51d6bbbef6a00b82ded03a0d637c057b6b70d13025d4c3042f2984d0cb7152a"
|
||||
},
|
||||
{
|
||||
"path": "/private/tmp/TheTree-input-copy-r335-3afabc8ef9ee42d0be34994471a451b5/candidate.dylib",
|
||||
"bytes": 433744,
|
||||
"sha256": "39f8ed73f077d15037d85b9cb53f38389c032a36dea7ff04348e5ef05c736907"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/autoload/simulation_runtime.gd",
|
||||
"bytes": 612068,
|
||||
"sha256": "7eb24adbf91fe53cde14954dda12abd5efb05130de7d356d8df281ee99065e86"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/autoload/simulation_runtime.gd",
|
||||
"bytes": 621773,
|
||||
"sha256": "ce260f1158adfb8d9adda1ea00fa29b3c76bc4968c9f7996fdcf62193e28b540"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/autoload/simulation_runtime.gd",
|
||||
"bytes": 612068,
|
||||
"sha256": "7eb24adbf91fe53cde14954dda12abd5efb05130de7d356d8df281ee99065e86"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/inventory/inventory_service.gd",
|
||||
"bytes": 57923,
|
||||
"sha256": "7ee83b335864385119ca757037c3cdb912957aa4478a6312a0898a734e41f31a"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/inventory/inventory_service.gd",
|
||||
"bytes": 60808,
|
||||
"sha256": "a93e7486fab66938ce7356b16202dddf0d4dd2f9c30e6b9312ec4ee98878480e"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/inventory/inventory_service.gd",
|
||||
"bytes": 57923,
|
||||
"sha256": "7ee83b335864385119ca757037c3cdb912957aa4478a6312a0898a734e41f31a"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/facility/facility_service.gd",
|
||||
"bytes": 44951,
|
||||
"sha256": "ceb4a3e9224587423f273cdb2b56e6843ab176ac1fc4fe79dd498b5ed5c33b77"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/facility/facility_service.gd",
|
||||
"bytes": 47788,
|
||||
"sha256": "c24d9b475c66046dc7342401a74fdc084ca6698506fdb9284afbadd6c5e68cfa"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/facility/facility_service.gd",
|
||||
"bytes": 44951,
|
||||
"sha256": "ceb4a3e9224587423f273cdb2b56e6843ab176ac1fc4fe79dd498b5ed5c33b77"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/supply/supply_management_service.gd",
|
||||
"bytes": 25019,
|
||||
"sha256": "e4ad420191020485c027004f64bb00fad9da195fe956ef10dc0c787412018f7f"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/supply/supply_management_service.gd",
|
||||
"bytes": 27952,
|
||||
"sha256": "87f2a3c36ef8b4569d17191f0c376fc957462dd7fe33a832c7284fdceb4a5b3c"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/supply/supply_management_service.gd",
|
||||
"bytes": 25019,
|
||||
"sha256": "e4ad420191020485c027004f64bb00fad9da195fe956ef10dc0c787412018f7f"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/supply/supply_logistics_bridge.gd",
|
||||
"bytes": 28100,
|
||||
"sha256": "b9e394af788595d2744b71f1907c8e7c3d762d38ff49992b1ee74e63b9639e80"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/supply/supply_logistics_bridge.gd",
|
||||
"bytes": 28814,
|
||||
"sha256": "6887a702c1eb6f9e91f689fd734f9bbc386a9cce55a68b1682c3a18be620976a"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/supply/supply_logistics_bridge.gd",
|
||||
"bytes": 28100,
|
||||
"sha256": "b9e394af788595d2744b71f1907c8e7c3d762d38ff49992b1ee74e63b9639e80"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/supply/kitchen_production_service.gd",
|
||||
"bytes": 18872,
|
||||
"sha256": "f3bc6bdc1a0ba278e9411108172ceceb7eb06520b4e33f93f35684da1f103c62"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/supply/kitchen_production_service.gd",
|
||||
"bytes": 19610,
|
||||
"sha256": "b751511484258edb471567639f150d8dcfb69ff4245a2273718cfcb3de04ca51"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/supply/kitchen_production_service.gd",
|
||||
"bytes": 18872,
|
||||
"sha256": "f3bc6bdc1a0ba278e9411108172ceceb7eb06520b4e33f93f35684da1f103c62"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/core/simulation_kernel.gd",
|
||||
"bytes": 7602,
|
||||
"sha256": "341c0c878c4894adbac628d0db6362ff69fc3347bdd9e61e50936e15dc2d1edb"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/core/simulation_kernel.gd",
|
||||
"bytes": 8264,
|
||||
"sha256": "9c67f2b22a38ab396e9d84522b3d54edb7be85878eb6a745deecb9ca2bde8692"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/core/simulation_kernel.gd",
|
||||
"bytes": 7602,
|
||||
"sha256": "341c0c878c4894adbac628d0db6362ff69fc3347bdd9e61e50936e15dc2d1edb"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/input.json",
|
||||
"bytes": 1023880,
|
||||
"sha256": "43f57b58c7533dae7965b71a739dd256219e264b1f2b3bb8639c8bf1a625696e"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338.py",
|
||||
"bytes": 6430,
|
||||
"sha256": "df468edfdc85ec9f445206ad005254d0472d1f8cc2f2c3fbea41db05dbd53b9a"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/tools/run_all_tests.py",
|
||||
"bytes": 26296,
|
||||
"sha256": "320ca668732b4ff72fc4449998af2327d4e5c527b06896740806aaf0487282b4"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/tools/regression/owned_outer.py",
|
||||
"bytes": 4177,
|
||||
"sha256": "c2e3483b76db1a3ff940f23f88ea0083fc78736e874ebcdb385d766dde8866e7"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-build-preview-monitor-compressed-r06.gd",
|
||||
"bytes": 17582,
|
||||
"sha256": "92d5e1956f4e613e12555d756de4f71fef03678cde159ac68fac3188ce3f336e"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-cache-public-mutations-r144/profile_guard.gd",
|
||||
"bytes": 2276,
|
||||
"sha256": "597696c705cc8f0e79a35265ca3ef8df55f7fc3c4e0e5a2ce9a4e20e29e29a6f"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/core/performance_budget.gd",
|
||||
"bytes": 10355,
|
||||
"sha256": "742c464d16ab417cbc3c2930d43e508faf5c9f7688da416324ca1150bdb9b6b9"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/project.godot",
|
||||
"bytes": 1294,
|
||||
"sha256": "686f3da7f6b592cd95d84e71a83374a28173914b377eafa4a6e005d70062d00d"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-input-copy-build-actual-independent-review-r334.json",
|
||||
"bytes": 40719,
|
||||
"sha256": "991e093110a35df5742e4b6bbd9254d664f20c280056fa6dd19e35be0bdcd871"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-input-copy-whole-actual-independent-review-r336.json",
|
||||
"bytes": 40888,
|
||||
"sha256": "671fedcbd0d48a42809aa6ca19d91c5ed4d22f4e6201ad1a00b3d3be18f291b8"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/input-before-phase-mapping-correction.json",
|
||||
"bytes": 1017508,
|
||||
"sha256": "fe9c06fd72ccd6bb88557082b5015bd8ad8386eee44371fdb4bd9dc8beb658db"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/input-before-transaction-method-correction.json",
|
||||
"bytes": 1011383,
|
||||
"sha256": "ca1c57a6c3266df161f8832842bc61c1305ecd2ecd77b7527533dcb44123f639"
|
||||
},
|
||||
{
|
||||
"path": "/private/tmp/thetree-prepare-residual-r338.py",
|
||||
"bytes": 9527,
|
||||
"sha256": "ff0e7c5fcb572b900585b334890612e19894f347ea57a6e1541935c7df6f3468"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-preexecution-independent-review-r338.json",
|
||||
"bytes": 26442,
|
||||
"sha256": "25d15928c713cb1608490bae5ea10d6374b21a764c87ae19ba2ce32a2d20ba39"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02.py",
|
||||
"bytes": 6438,
|
||||
"sha256": "97e994c336ae44f78581e0885321b572d002635c39e36ae62aa1e84feb6fd011"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/input.json",
|
||||
"bytes": 1024228,
|
||||
"sha256": "95f7929f2a8d78593d18285d2c1581ef7a303dae6fae331c8312e15b700b5d91"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-preexecution-independent-review-r338-r02.json",
|
||||
"bytes": 26503,
|
||||
"sha256": "ad50e109577313f7626e931cfc6943a944fee2f9912adb4d60e706659ae0c23d"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p28-ai-r03-typed-difference-independent-review-r01/finite_variant_codec.py",
|
||||
"bytes": 5438,
|
||||
"sha256": "8c7077b53e28da4054bdf7dd88e82de02a51149269a8fce59bae0e74f95b4734"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-residual-diagnostic-actual-independent-review-r238.json",
|
||||
"bytes": 36734,
|
||||
"sha256": "e41634755f116006c91ad251b48eb8b71286a53a6a687d6f371366f3140cc66d"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/source-audit.json",
|
||||
"bytes": 2842,
|
||||
"sha256": "2bc5d3993faff852eb8c5eed383011c1f9d28dc71842c371631e918981b50cdf"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/preexecution-root-verification.json",
|
||||
"bytes": 15310,
|
||||
"sha256": "3b0b88c9983ef376bf56428f2a6cc00819dc4880d0e407b3ffd2f98e2ba89f4b"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/execution.json",
|
||||
"bytes": 11232,
|
||||
"sha256": "3b33b742d9557b050a8337fbf0c865a765d9bd803effe50d420932a4495cc6b8"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/profile.json",
|
||||
"bytes": 932,
|
||||
"sha256": "19ac44fca90fd6bf47be1ab8027e1cebda05f511cccccfe5f077e86f6b8f7c39"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/phase.json",
|
||||
"bytes": 8031,
|
||||
"sha256": "13e5517e87e14ff8363df207da016fd79a4de7945458bbc7ae1b2c76c5463ce5"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/measurement/metrics.json",
|
||||
"bytes": 3451,
|
||||
"sha256": "9bf882e017b0476642f386bfa57eaf7c8b09b4c2d40f51e977b969ccedfc9835"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/measurement/report.json",
|
||||
"bytes": 1799,
|
||||
"sha256": "e6b2e22bc91d31de10ca3fcdd1df96fd633714aec5c50309a48bc4fafc57ea81"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/measurement/metrics.varbytes.zst",
|
||||
"bytes": 887,
|
||||
"sha256": "4cb3c0f5b12a1de658d8afc293eace99650f05d17dc9f18037ed676207e9de3c"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/measurement/after647.varbytes.zst",
|
||||
"bytes": 246720,
|
||||
"sha256": "684ba40e9f649b7dd4bfc620185d7cd18bae3111c3b4038e48aaad5a9168d880"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/stderr.log",
|
||||
"bytes": 0,
|
||||
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/ended.json",
|
||||
"bytes": 1748,
|
||||
"sha256": "e2aa0217a04f8a13c1f342099a7115c80939912e80fba67b2c4b484f48a923f3"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/adapter-owned-cleanup.json",
|
||||
"bytes": 351,
|
||||
"sha256": "c1f3d289b362cc61b9be169a3994be27df39f35e6221881b4a9678ce3c72ba54"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/engine-native.log",
|
||||
"bytes": 13430,
|
||||
"sha256": "d55b7f7471e3b111ba534f95e52285eab62b6d8790eb93371f9af64a8965b9a4"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/stdout.log",
|
||||
"bytes": 13580,
|
||||
"sha256": "2b66eb5a87fc2d25389c79ef66882ad54c0f845fc970b6a0acda57b0f412f651"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/started.json",
|
||||
"bytes": 2356,
|
||||
"sha256": "e1753fb09042deb721b20343330f5c2bbeab13bfd2b8d59e26e5459215def818"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/process.json",
|
||||
"bytes": 6595,
|
||||
"sha256": "af54e1491e10a4795bd138ce09d48b46f4046795f31fcbd4c339911521eec3b9"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/outer-owned-finally.json",
|
||||
"bytes": 964,
|
||||
"sha256": "0602848d465ace99eb2889a8ab58e27867b3318b504512e127adf297e237d18d"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/IMPLEMENTATION_PLAN.md",
|
||||
"bytes": 492489,
|
||||
"sha256": "4e9748ca579001e5673f83568d64bbe45b6bad7420ee6481901496f0fd7e9f28"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/PROGRESS_INTEGRATION.md",
|
||||
"bytes": 410553,
|
||||
"sha256": "b5617405aaa913cef5f5e23bbc5141bfb746de88926116c02ea2d33bd5ea7a22"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/work_packages.json",
|
||||
"bytes": 1188101,
|
||||
"sha256": "e7e8d40e9a9a85095d6e4ad96ab305fa1bf83f10f754b3c541e27cb78b1f6f67"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/progress_snapshot.json",
|
||||
"bytes": 591756,
|
||||
"sha256": "db411f761cc2e64d9ae7859ebdc085bfacc1b649dd4c7241c34a96fd28e07b97"
|
||||
}
|
||||
],
|
||||
"unit_accepted": false,
|
||||
"performance_accepted": false
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"owned_child_created": true,
|
||||
"engine_ended": true,
|
||||
"actual_process_exit_code": 0,
|
||||
"attempts": [
|
||||
{
|
||||
"attempt": 1,
|
||||
"kill_attempted": false,
|
||||
"wait_timeout_seconds": 5,
|
||||
"wait_completed": true,
|
||||
"errors": [],
|
||||
"poll_before": 0,
|
||||
"wait_returned_code": 0,
|
||||
"poll_after": 0
|
||||
}
|
||||
],
|
||||
"errors": []
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"scope": "isolated diagnostic owned child",
|
||||
"event": "ENGINE_ENDED",
|
||||
"actual_pid": 60890,
|
||||
"owner_pid": 60865,
|
||||
"command": [
|
||||
"/Applications/Godot.app/Contents/MacOS/Godot",
|
||||
"--headless",
|
||||
"--path",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage",
|
||||
"--script",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd",
|
||||
"--verbose",
|
||||
"--log-file",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/engine-native.log"
|
||||
],
|
||||
"monotonic_ns": 8123426000,
|
||||
"exit_code": 0,
|
||||
"actual_process_exit_code": 0,
|
||||
"engine_ended": true,
|
||||
"timed_out": false,
|
||||
"lifecycle_error": null,
|
||||
"start_receipt_written": true,
|
||||
"pid": 60890,
|
||||
"argv": [
|
||||
"/Applications/Godot.app/Contents/MacOS/Godot",
|
||||
"--headless",
|
||||
"--path",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage",
|
||||
"--script",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd",
|
||||
"--verbose",
|
||||
"--log-file",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/engine-native.log"
|
||||
],
|
||||
"ended_utc": "2026-10-12T05:06:15.811628+00:00",
|
||||
"signal_scope": "tracked Popen child only; no external group signal"
|
||||
}
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
Godot Engine v4.7.2.stable.official.ed1daf0bf - https://godotengine.org
|
||||
TextServer: Added interface "Dummy"
|
||||
TextServer: Added interface "ICU / HarfBuzz / Graphite (Built-in)"
|
||||
SDL: Init OK!
|
||||
Using "default" pen tablet driver...
|
||||
|
||||
TextServer: Primary interface set to: "ICU / HarfBuzz / Graphite (Built-in)".
|
||||
CORE API HASH: 2004498165
|
||||
EDITOR API HASH: 1696660745
|
||||
Loading resource: /Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd remapped: /Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd
|
||||
Completed load for: '/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd' remapped '/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd' at thread -1
|
||||
SceneTreeFTI: traversal method DEFAULT
|
||||
Loading resource: res://autoload/event_bus.gd remapped: res://autoload/event_bus.gd
|
||||
Completed load for: 'res://autoload/event_bus.gd' remapped 'res://autoload/event_bus.gd' at thread -1
|
||||
Loading resource: res://autoload/game_clock.gd remapped: res://autoload/game_clock.gd
|
||||
Completed load for: 'res://autoload/game_clock.gd' remapped 'res://autoload/game_clock.gd' at thread -1
|
||||
Loading resource: res://autoload/game_state.gd remapped: res://autoload/game_state.gd
|
||||
Completed load for: 'res://autoload/game_state.gd' remapped 'res://autoload/game_state.gd' at thread -1
|
||||
Loading resource: res://autoload/simulation_runtime.gd remapped: res://autoload/simulation_runtime.gd
|
||||
Completed load for: 'res://autoload/simulation_runtime.gd' remapped 'res://autoload/simulation_runtime.gd' at thread -1
|
||||
Loaded system CA certificates
|
||||
PACK_PROFILE_GUARD verified=true
|
||||
Loading resource: res://data/facilities/adult_private_room.tres remapped: res://data/facilities/adult_private_room.tres
|
||||
Completed load for: 'res://data/facilities/adult_private_room.tres' remapped 'res://data/facilities/adult_private_room.tres' at thread -1
|
||||
Loading resource: res://data/facilities/cafeteria.tres remapped: res://data/facilities/cafeteria.tres
|
||||
Completed load for: 'res://data/facilities/cafeteria.tres' remapped 'res://data/facilities/cafeteria.tres' at thread -1
|
||||
Loading resource: res://data/facilities/expansion/chapel.tres remapped: res://data/facilities/expansion/chapel.tres
|
||||
Completed load for: 'res://data/facilities/expansion/chapel.tres' remapped 'res://data/facilities/expansion/chapel.tres' at thread -1
|
||||
Loading resource: res://data/facilities/expansion/cleaning_room.tres remapped: res://data/facilities/expansion/cleaning_room.tres
|
||||
Completed load for: 'res://data/facilities/expansion/cleaning_room.tres' remapped 'res://data/facilities/expansion/cleaning_room.tres' at thread -1
|
||||
Loading resource: res://data/facilities/expansion/premium_room.tres remapped: res://data/facilities/expansion/premium_room.tres
|
||||
Completed load for: 'res://data/facilities/expansion/premium_room.tres' remapped 'res://data/facilities/expansion/premium_room.tres' at thread -1
|
||||
Loading resource: res://data/facilities/expansion/staff_dormitory.tres remapped: res://data/facilities/expansion/staff_dormitory.tres
|
||||
Completed load for: 'res://data/facilities/expansion/staff_dormitory.tres' remapped 'res://data/facilities/expansion/staff_dormitory.tres' at thread -1
|
||||
Loading resource: res://data/facilities/guest_corridor.tres remapped: res://data/facilities/guest_corridor.tres
|
||||
Completed load for: 'res://data/facilities/guest_corridor.tres' remapped 'res://data/facilities/guest_corridor.tres' at thread -1
|
||||
Loading resource: res://data/facilities/guest_elevator.tres remapped: res://data/facilities/guest_elevator.tres
|
||||
Completed load for: 'res://data/facilities/guest_elevator.tres' remapped 'res://data/facilities/guest_elevator.tres' at thread -1
|
||||
Loading resource: res://data/facilities/infrastructure/guest_stairs.tres remapped: res://data/facilities/infrastructure/guest_stairs.tres
|
||||
Completed load for: 'res://data/facilities/infrastructure/guest_stairs.tres' remapped 'res://data/facilities/infrastructure/guest_stairs.tres' at thread -1
|
||||
Loading resource: res://data/facilities/infrastructure/service_stairs.tres remapped: res://data/facilities/infrastructure/service_stairs.tres
|
||||
Completed load for: 'res://data/facilities/infrastructure/service_stairs.tres' remapped 'res://data/facilities/infrastructure/service_stairs.tres' at thread -1
|
||||
Loading resource: res://data/facilities/kitchen.tres remapped: res://data/facilities/kitchen.tres
|
||||
Completed load for: 'res://data/facilities/kitchen.tres' remapped 'res://data/facilities/kitchen.tres' at thread -1
|
||||
Loading resource: res://data/facilities/massage_room.tres remapped: res://data/facilities/massage_room.tres
|
||||
Completed load for: 'res://data/facilities/massage_room.tres' remapped 'res://data/facilities/massage_room.tres' at thread -1
|
||||
Loading resource: res://data/facilities/public_bath.tres remapped: res://data/facilities/public_bath.tres
|
||||
Completed load for: 'res://data/facilities/public_bath.tres' remapped 'res://data/facilities/public_bath.tres' at thread -1
|
||||
Loading resource: res://data/facilities/reception.tres remapped: res://data/facilities/reception.tres
|
||||
Completed load for: 'res://data/facilities/reception.tres' remapped 'res://data/facilities/reception.tres' at thread -1
|
||||
Loading resource: res://data/facilities/rescue/infirmary.tres remapped: res://data/facilities/rescue/infirmary.tres
|
||||
Completed load for: 'res://data/facilities/rescue/infirmary.tres' remapped 'res://data/facilities/rescue/infirmary.tres' at thread -1
|
||||
Loading resource: res://data/facilities/security_station.tres remapped: res://data/facilities/security_station.tres
|
||||
Completed load for: 'res://data/facilities/security_station.tres' remapped 'res://data/facilities/security_station.tres' at thread -1
|
||||
Loading resource: res://data/facilities/service_corridor.tres remapped: res://data/facilities/service_corridor.tres
|
||||
Completed load for: 'res://data/facilities/service_corridor.tres' remapped 'res://data/facilities/service_corridor.tres' at thread -1
|
||||
Loading resource: res://data/facilities/service_elevator.tres remapped: res://data/facilities/service_elevator.tres
|
||||
Completed load for: 'res://data/facilities/service_elevator.tres' remapped 'res://data/facilities/service_elevator.tres' at thread -1
|
||||
Loading resource: res://data/facilities/staff_door.tres remapped: res://data/facilities/staff_door.tres
|
||||
Completed load for: 'res://data/facilities/staff_door.tres' remapped 'res://data/facilities/staff_door.tres' at thread -1
|
||||
Loading resource: res://data/facilities/staff_waiting_room.tres remapped: res://data/facilities/staff_waiting_room.tres
|
||||
Completed load for: 'res://data/facilities/staff_waiting_room.tres' remapped 'res://data/facilities/staff_waiting_room.tres' at thread -1
|
||||
Loading resource: res://data/facilities/standard_room.tres remapped: res://data/facilities/standard_room.tres
|
||||
Completed load for: 'res://data/facilities/standard_room.tres' remapped 'res://data/facilities/standard_room.tres' at thread -1
|
||||
Loading resource: res://data/facilities/tavern.tres remapped: res://data/facilities/tavern.tres
|
||||
Completed load for: 'res://data/facilities/tavern.tres' remapped 'res://data/facilities/tavern.tres' at thread -1
|
||||
Loading resource: res://data/facilities/warehouse.tres remapped: res://data/facilities/warehouse.tres
|
||||
Completed load for: 'res://data/facilities/warehouse.tres' remapped 'res://data/facilities/warehouse.tres' at thread -1
|
||||
NATIVE_ADAPTER_LIBRARY_REGISTERED
|
||||
Loading resource: res://data/facilities/adult_private_room.tres remapped: res://data/facilities/adult_private_room.tres
|
||||
Completed load for: 'res://data/facilities/adult_private_room.tres' remapped 'res://data/facilities/adult_private_room.tres' at thread -1
|
||||
Loading resource: res://data/facilities/cafeteria.tres remapped: res://data/facilities/cafeteria.tres
|
||||
Completed load for: 'res://data/facilities/cafeteria.tres' remapped 'res://data/facilities/cafeteria.tres' at thread -1
|
||||
Loading resource: res://data/facilities/expansion/chapel.tres remapped: res://data/facilities/expansion/chapel.tres
|
||||
Completed load for: 'res://data/facilities/expansion/chapel.tres' remapped 'res://data/facilities/expansion/chapel.tres' at thread -1
|
||||
Loading resource: res://data/facilities/expansion/cleaning_room.tres remapped: res://data/facilities/expansion/cleaning_room.tres
|
||||
Completed load for: 'res://data/facilities/expansion/cleaning_room.tres' remapped 'res://data/facilities/expansion/cleaning_room.tres' at thread -1
|
||||
Loading resource: res://data/facilities/expansion/premium_room.tres remapped: res://data/facilities/expansion/premium_room.tres
|
||||
Completed load for: 'res://data/facilities/expansion/premium_room.tres' remapped 'res://data/facilities/expansion/premium_room.tres' at thread -1
|
||||
Loading resource: res://data/facilities/expansion/staff_dormitory.tres remapped: res://data/facilities/expansion/staff_dormitory.tres
|
||||
Completed load for: 'res://data/facilities/expansion/staff_dormitory.tres' remapped 'res://data/facilities/expansion/staff_dormitory.tres' at thread -1
|
||||
Loading resource: res://data/facilities/guest_corridor.tres remapped: res://data/facilities/guest_corridor.tres
|
||||
Completed load for: 'res://data/facilities/guest_corridor.tres' remapped 'res://data/facilities/guest_corridor.tres' at thread -1
|
||||
Loading resource: res://data/facilities/guest_elevator.tres remapped: res://data/facilities/guest_elevator.tres
|
||||
Completed load for: 'res://data/facilities/guest_elevator.tres' remapped 'res://data/facilities/guest_elevator.tres' at thread -1
|
||||
Loading resource: res://data/facilities/infrastructure/guest_stairs.tres remapped: res://data/facilities/infrastructure/guest_stairs.tres
|
||||
Completed load for: 'res://data/facilities/infrastructure/guest_stairs.tres' remapped 'res://data/facilities/infrastructure/guest_stairs.tres' at thread -1
|
||||
Loading resource: res://data/facilities/infrastructure/service_stairs.tres remapped: res://data/facilities/infrastructure/service_stairs.tres
|
||||
Completed load for: 'res://data/facilities/infrastructure/service_stairs.tres' remapped 'res://data/facilities/infrastructure/service_stairs.tres' at thread -1
|
||||
Loading resource: res://data/facilities/kitchen.tres remapped: res://data/facilities/kitchen.tres
|
||||
Completed load for: 'res://data/facilities/kitchen.tres' remapped 'res://data/facilities/kitchen.tres' at thread -1
|
||||
Loading resource: res://data/facilities/massage_room.tres remapped: res://data/facilities/massage_room.tres
|
||||
Completed load for: 'res://data/facilities/massage_room.tres' remapped 'res://data/facilities/massage_room.tres' at thread -1
|
||||
Loading resource: res://data/facilities/public_bath.tres remapped: res://data/facilities/public_bath.tres
|
||||
Completed load for: 'res://data/facilities/public_bath.tres' remapped 'res://data/facilities/public_bath.tres' at thread -1
|
||||
Loading resource: res://data/facilities/reception.tres remapped: res://data/facilities/reception.tres
|
||||
Completed load for: 'res://data/facilities/reception.tres' remapped 'res://data/facilities/reception.tres' at thread -1
|
||||
Loading resource: res://data/facilities/rescue/infirmary.tres remapped: res://data/facilities/rescue/infirmary.tres
|
||||
Completed load for: 'res://data/facilities/rescue/infirmary.tres' remapped 'res://data/facilities/rescue/infirmary.tres' at thread -1
|
||||
Loading resource: res://data/facilities/security_station.tres remapped: res://data/facilities/security_station.tres
|
||||
Completed load for: 'res://data/facilities/security_station.tres' remapped 'res://data/facilities/security_station.tres' at thread -1
|
||||
Loading resource: res://data/facilities/service_corridor.tres remapped: res://data/facilities/service_corridor.tres
|
||||
Completed load for: 'res://data/facilities/service_corridor.tres' remapped 'res://data/facilities/service_corridor.tres' at thread -1
|
||||
Loading resource: res://data/facilities/service_elevator.tres remapped: res://data/facilities/service_elevator.tres
|
||||
Completed load for: 'res://data/facilities/service_elevator.tres' remapped 'res://data/facilities/service_elevator.tres' at thread -1
|
||||
Loading resource: res://data/facilities/staff_door.tres remapped: res://data/facilities/staff_door.tres
|
||||
Completed load for: 'res://data/facilities/staff_door.tres' remapped 'res://data/facilities/staff_door.tres' at thread -1
|
||||
Loading resource: res://data/facilities/staff_waiting_room.tres remapped: res://data/facilities/staff_waiting_room.tres
|
||||
Completed load for: 'res://data/facilities/staff_waiting_room.tres' remapped 'res://data/facilities/staff_waiting_room.tres' at thread -1
|
||||
Loading resource: res://data/facilities/standard_room.tres remapped: res://data/facilities/standard_room.tres
|
||||
Completed load for: 'res://data/facilities/standard_room.tres' remapped 'res://data/facilities/standard_room.tres' at thread -1
|
||||
Loading resource: res://data/facilities/tavern.tres remapped: res://data/facilities/tavern.tres
|
||||
Completed load for: 'res://data/facilities/tavern.tres' remapped 'res://data/facilities/tavern.tres' at thread -1
|
||||
Loading resource: res://data/facilities/warehouse.tres remapped: res://data/facilities/warehouse.tres
|
||||
Completed load for: 'res://data/facilities/warehouse.tres' remapped 'res://data/facilities/warehouse.tres' at thread -1
|
||||
Phase diagnostic whole647: 17 checks, 0 failures
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"actual_captured_pids": [
|
||||
60890
|
||||
],
|
||||
"cleanup": [
|
||||
{
|
||||
"pid": 60890,
|
||||
"cleanup": {
|
||||
"owned_child_created": true,
|
||||
"engine_ended": true,
|
||||
"actual_process_exit_code": 0,
|
||||
"attempts": [
|
||||
{
|
||||
"attempt": 1,
|
||||
"kill_attempted": false,
|
||||
"wait_timeout_seconds": 5,
|
||||
"wait_completed": true,
|
||||
"errors": [],
|
||||
"poll_before": 0,
|
||||
"wait_returned_code": 0,
|
||||
"poll_after": 0
|
||||
}
|
||||
],
|
||||
"errors": []
|
||||
},
|
||||
"outer_cleanup_errors": [],
|
||||
"engine_ended": true,
|
||||
"outer_maximum_helper_invocations": 3,
|
||||
"helper_maximum_waits": 3,
|
||||
"per_wait_timeout_seconds": 5,
|
||||
"foreign_process_or_group_signals": 0
|
||||
}
|
||||
],
|
||||
"adapter_exception": null,
|
||||
"all_captured_ended": true,
|
||||
"outer_cleanup_errors": [],
|
||||
"foreign_process_or_group_signals": 0,
|
||||
"all_cleanup_before_outer_receipt": true
|
||||
}
|
||||
+140
@@ -0,0 +1,140 @@
|
||||
{
|
||||
"argv": [
|
||||
"/Applications/Godot.app/Contents/MacOS/Godot",
|
||||
"--headless",
|
||||
"--path",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage",
|
||||
"--script",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd",
|
||||
"--verbose",
|
||||
"--log-file",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/engine-native.log"
|
||||
],
|
||||
"pid": 60890,
|
||||
"started_utc": "2026-10-12T05:06:10.173663+00:00",
|
||||
"ended_utc": "2026-10-12T05:06:15.814823+00:00",
|
||||
"wall_seconds": 5.640924999999999,
|
||||
"exit_code": 0,
|
||||
"helper_exit_code": 0,
|
||||
"timed_out": false,
|
||||
"stdout_sha256": "2b66eb5a87fc2d25389c79ef66882ad54c0f845fc970b6a0acda57b0f412f651",
|
||||
"stderr_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
||||
"error_lines": [],
|
||||
"owned_popen_ended": true,
|
||||
"old_helper_engine_ended": true,
|
||||
"start_receipt_written": true,
|
||||
"end_receipt_written": true,
|
||||
"lifecycle_error": null,
|
||||
"old_helper_lifecycle_error": null,
|
||||
"actual_start_binding": {
|
||||
"scope": "isolated diagnostic owned child",
|
||||
"event": "ENGINE_STARTED",
|
||||
"actual_pid": 60890,
|
||||
"owner_pid": 60865,
|
||||
"command": [
|
||||
"/Applications/Godot.app/Contents/MacOS/Godot",
|
||||
"--headless",
|
||||
"--path",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage",
|
||||
"--script",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd",
|
||||
"--verbose",
|
||||
"--log-file",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/engine-native.log"
|
||||
],
|
||||
"monotonic_ns": 2490331791,
|
||||
"pid": 60890,
|
||||
"argv": [
|
||||
"/Applications/Godot.app/Contents/MacOS/Godot",
|
||||
"--headless",
|
||||
"--path",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage",
|
||||
"--script",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd",
|
||||
"--verbose",
|
||||
"--log-file",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/engine-native.log"
|
||||
],
|
||||
"started_utc": "2026-10-12T05:06:10.173663+00:00",
|
||||
"current_process_identity": {
|
||||
"pid": 60890,
|
||||
"ppid": 60865,
|
||||
"pgid": 60890,
|
||||
"args": "/Applications/Godot.app/Contents/MacOS/Godot --headless --path /Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage --script /Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd --verbose --log-file /Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/engine-native.log"
|
||||
},
|
||||
"live_identity_exact": true,
|
||||
"tracked_child_ended_before_initial_probe": false,
|
||||
"signal_scope": "tracked Popen child only; no external group signal"
|
||||
},
|
||||
"actual_end_binding": {
|
||||
"scope": "isolated diagnostic owned child",
|
||||
"event": "ENGINE_ENDED",
|
||||
"actual_pid": 60890,
|
||||
"owner_pid": 60865,
|
||||
"command": [
|
||||
"/Applications/Godot.app/Contents/MacOS/Godot",
|
||||
"--headless",
|
||||
"--path",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage",
|
||||
"--script",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd",
|
||||
"--verbose",
|
||||
"--log-file",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/engine-native.log"
|
||||
],
|
||||
"monotonic_ns": 8123426000,
|
||||
"exit_code": 0,
|
||||
"actual_process_exit_code": 0,
|
||||
"engine_ended": true,
|
||||
"timed_out": false,
|
||||
"lifecycle_error": null,
|
||||
"start_receipt_written": true,
|
||||
"pid": 60890,
|
||||
"argv": [
|
||||
"/Applications/Godot.app/Contents/MacOS/Godot",
|
||||
"--headless",
|
||||
"--path",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage",
|
||||
"--script",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd",
|
||||
"--verbose",
|
||||
"--log-file",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/engine-native.log"
|
||||
],
|
||||
"ended_utc": "2026-10-12T05:06:15.811628+00:00",
|
||||
"signal_scope": "tracked Popen child only; no external group signal"
|
||||
},
|
||||
"strict_native_diagnostics": {
|
||||
"errors": [],
|
||||
"banner_count": 1,
|
||||
"known_unicode_diagnostic_count": 0,
|
||||
"unrecognized_unicode_diagnostic_count": 0,
|
||||
"exit_leak_diagnostic_lines": []
|
||||
},
|
||||
"external_process_or_group_signals": 0,
|
||||
"owned_child_process_helper_sha256": "c007e712c281573254faa1233c2ac92e100ab87393256a6dc096b35283e43037",
|
||||
"adapter_owned_cleanup": {
|
||||
"owned_child_created": true,
|
||||
"engine_ended": true,
|
||||
"actual_process_exit_code": 0,
|
||||
"attempts": [
|
||||
{
|
||||
"attempt": 1,
|
||||
"kill_attempted": false,
|
||||
"wait_timeout_seconds": 5,
|
||||
"wait_completed": true,
|
||||
"errors": [],
|
||||
"poll_before": 0,
|
||||
"wait_returned_code": 0,
|
||||
"poll_after": 0
|
||||
}
|
||||
],
|
||||
"errors": []
|
||||
},
|
||||
"adapter_error": null,
|
||||
"old_helper_bytes_preserved": true,
|
||||
"helper_wait_None_maps_to_actual_timeout_seconds": 5,
|
||||
"explicit_helper_wait_timeouts_preserved": true,
|
||||
"additional_cleanup_wait_timeout_seconds": 5,
|
||||
"additional_cleanup_max_attempts": 3
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"scope": "isolated diagnostic owned child",
|
||||
"event": "ENGINE_STARTED",
|
||||
"actual_pid": 60890,
|
||||
"owner_pid": 60865,
|
||||
"command": [
|
||||
"/Applications/Godot.app/Contents/MacOS/Godot",
|
||||
"--headless",
|
||||
"--path",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage",
|
||||
"--script",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd",
|
||||
"--verbose",
|
||||
"--log-file",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/engine-native.log"
|
||||
],
|
||||
"monotonic_ns": 2490331791,
|
||||
"pid": 60890,
|
||||
"argv": [
|
||||
"/Applications/Godot.app/Contents/MacOS/Godot",
|
||||
"--headless",
|
||||
"--path",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage",
|
||||
"--script",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd",
|
||||
"--verbose",
|
||||
"--log-file",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/engine-native.log"
|
||||
],
|
||||
"started_utc": "2026-10-12T05:06:10.173663+00:00",
|
||||
"current_process_identity": {
|
||||
"pid": 60890,
|
||||
"ppid": 60865,
|
||||
"pgid": 60890,
|
||||
"args": "/Applications/Godot.app/Contents/MacOS/Godot --headless --path /Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage --script /Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd --verbose --log-file /Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/engine-native.log"
|
||||
},
|
||||
"live_identity_exact": true,
|
||||
"tracked_child_ended_before_initial_probe": false,
|
||||
"signal_scope": "tracked Popen child only; no external group signal"
|
||||
}
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
WorkerThreadPool: 10 threads, 3 max low-priority.
|
||||
Godot Engine v4.7.2.stable.official.ed1daf0bf - https://godotengine.org
|
||||
TextServer: Added interface "Dummy"
|
||||
TextServer: Added interface "ICU / HarfBuzz / Graphite (Built-in)"
|
||||
SDL: Init OK!
|
||||
Using "default" pen tablet driver...
|
||||
|
||||
TextServer: Primary interface set to: "ICU / HarfBuzz / Graphite (Built-in)".
|
||||
CORE API HASH: 2004498165
|
||||
EDITOR API HASH: 1696660745
|
||||
Loading resource: /Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd remapped: /Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd
|
||||
Completed load for: '/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd' remapped '/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd' at thread -1
|
||||
SceneTreeFTI: traversal method DEFAULT
|
||||
Loading resource: res://autoload/event_bus.gd remapped: res://autoload/event_bus.gd
|
||||
Completed load for: 'res://autoload/event_bus.gd' remapped 'res://autoload/event_bus.gd' at thread -1
|
||||
Loading resource: res://autoload/game_clock.gd remapped: res://autoload/game_clock.gd
|
||||
Completed load for: 'res://autoload/game_clock.gd' remapped 'res://autoload/game_clock.gd' at thread -1
|
||||
Loading resource: res://autoload/game_state.gd remapped: res://autoload/game_state.gd
|
||||
Completed load for: 'res://autoload/game_state.gd' remapped 'res://autoload/game_state.gd' at thread -1
|
||||
Loading resource: res://autoload/simulation_runtime.gd remapped: res://autoload/simulation_runtime.gd
|
||||
Completed load for: 'res://autoload/simulation_runtime.gd' remapped 'res://autoload/simulation_runtime.gd' at thread -1
|
||||
Loaded system CA certificates
|
||||
PACK_PROFILE_GUARD verified=true
|
||||
Loading resource: res://data/facilities/adult_private_room.tres remapped: res://data/facilities/adult_private_room.tres
|
||||
Completed load for: 'res://data/facilities/adult_private_room.tres' remapped 'res://data/facilities/adult_private_room.tres' at thread -1
|
||||
Loading resource: res://data/facilities/cafeteria.tres remapped: res://data/facilities/cafeteria.tres
|
||||
Completed load for: 'res://data/facilities/cafeteria.tres' remapped 'res://data/facilities/cafeteria.tres' at thread -1
|
||||
Loading resource: res://data/facilities/expansion/chapel.tres remapped: res://data/facilities/expansion/chapel.tres
|
||||
Completed load for: 'res://data/facilities/expansion/chapel.tres' remapped 'res://data/facilities/expansion/chapel.tres' at thread -1
|
||||
Loading resource: res://data/facilities/expansion/cleaning_room.tres remapped: res://data/facilities/expansion/cleaning_room.tres
|
||||
Completed load for: 'res://data/facilities/expansion/cleaning_room.tres' remapped 'res://data/facilities/expansion/cleaning_room.tres' at thread -1
|
||||
Loading resource: res://data/facilities/expansion/premium_room.tres remapped: res://data/facilities/expansion/premium_room.tres
|
||||
Completed load for: 'res://data/facilities/expansion/premium_room.tres' remapped 'res://data/facilities/expansion/premium_room.tres' at thread -1
|
||||
Loading resource: res://data/facilities/expansion/staff_dormitory.tres remapped: res://data/facilities/expansion/staff_dormitory.tres
|
||||
Completed load for: 'res://data/facilities/expansion/staff_dormitory.tres' remapped 'res://data/facilities/expansion/staff_dormitory.tres' at thread -1
|
||||
Loading resource: res://data/facilities/guest_corridor.tres remapped: res://data/facilities/guest_corridor.tres
|
||||
Completed load for: 'res://data/facilities/guest_corridor.tres' remapped 'res://data/facilities/guest_corridor.tres' at thread -1
|
||||
Loading resource: res://data/facilities/guest_elevator.tres remapped: res://data/facilities/guest_elevator.tres
|
||||
Completed load for: 'res://data/facilities/guest_elevator.tres' remapped 'res://data/facilities/guest_elevator.tres' at thread -1
|
||||
Loading resource: res://data/facilities/infrastructure/guest_stairs.tres remapped: res://data/facilities/infrastructure/guest_stairs.tres
|
||||
Completed load for: 'res://data/facilities/infrastructure/guest_stairs.tres' remapped 'res://data/facilities/infrastructure/guest_stairs.tres' at thread -1
|
||||
Loading resource: res://data/facilities/infrastructure/service_stairs.tres remapped: res://data/facilities/infrastructure/service_stairs.tres
|
||||
Completed load for: 'res://data/facilities/infrastructure/service_stairs.tres' remapped 'res://data/facilities/infrastructure/service_stairs.tres' at thread -1
|
||||
Loading resource: res://data/facilities/kitchen.tres remapped: res://data/facilities/kitchen.tres
|
||||
Completed load for: 'res://data/facilities/kitchen.tres' remapped 'res://data/facilities/kitchen.tres' at thread -1
|
||||
Loading resource: res://data/facilities/massage_room.tres remapped: res://data/facilities/massage_room.tres
|
||||
Completed load for: 'res://data/facilities/massage_room.tres' remapped 'res://data/facilities/massage_room.tres' at thread -1
|
||||
Loading resource: res://data/facilities/public_bath.tres remapped: res://data/facilities/public_bath.tres
|
||||
Completed load for: 'res://data/facilities/public_bath.tres' remapped 'res://data/facilities/public_bath.tres' at thread -1
|
||||
Loading resource: res://data/facilities/reception.tres remapped: res://data/facilities/reception.tres
|
||||
Completed load for: 'res://data/facilities/reception.tres' remapped 'res://data/facilities/reception.tres' at thread -1
|
||||
Loading resource: res://data/facilities/rescue/infirmary.tres remapped: res://data/facilities/rescue/infirmary.tres
|
||||
Completed load for: 'res://data/facilities/rescue/infirmary.tres' remapped 'res://data/facilities/rescue/infirmary.tres' at thread -1
|
||||
Loading resource: res://data/facilities/security_station.tres remapped: res://data/facilities/security_station.tres
|
||||
Completed load for: 'res://data/facilities/security_station.tres' remapped 'res://data/facilities/security_station.tres' at thread -1
|
||||
Loading resource: res://data/facilities/service_corridor.tres remapped: res://data/facilities/service_corridor.tres
|
||||
Completed load for: 'res://data/facilities/service_corridor.tres' remapped 'res://data/facilities/service_corridor.tres' at thread -1
|
||||
Loading resource: res://data/facilities/service_elevator.tres remapped: res://data/facilities/service_elevator.tres
|
||||
Completed load for: 'res://data/facilities/service_elevator.tres' remapped 'res://data/facilities/service_elevator.tres' at thread -1
|
||||
Loading resource: res://data/facilities/staff_door.tres remapped: res://data/facilities/staff_door.tres
|
||||
Completed load for: 'res://data/facilities/staff_door.tres' remapped 'res://data/facilities/staff_door.tres' at thread -1
|
||||
Loading resource: res://data/facilities/staff_waiting_room.tres remapped: res://data/facilities/staff_waiting_room.tres
|
||||
Completed load for: 'res://data/facilities/staff_waiting_room.tres' remapped 'res://data/facilities/staff_waiting_room.tres' at thread -1
|
||||
Loading resource: res://data/facilities/standard_room.tres remapped: res://data/facilities/standard_room.tres
|
||||
Completed load for: 'res://data/facilities/standard_room.tres' remapped 'res://data/facilities/standard_room.tres' at thread -1
|
||||
Loading resource: res://data/facilities/tavern.tres remapped: res://data/facilities/tavern.tres
|
||||
Completed load for: 'res://data/facilities/tavern.tres' remapped 'res://data/facilities/tavern.tres' at thread -1
|
||||
Loading resource: res://data/facilities/warehouse.tres remapped: res://data/facilities/warehouse.tres
|
||||
Completed load for: 'res://data/facilities/warehouse.tres' remapped 'res://data/facilities/warehouse.tres' at thread -1
|
||||
NATIVE_ADAPTER_LIBRARY_REGISTERED
|
||||
Loading resource: res://data/facilities/adult_private_room.tres remapped: res://data/facilities/adult_private_room.tres
|
||||
Completed load for: 'res://data/facilities/adult_private_room.tres' remapped 'res://data/facilities/adult_private_room.tres' at thread -1
|
||||
Loading resource: res://data/facilities/cafeteria.tres remapped: res://data/facilities/cafeteria.tres
|
||||
Completed load for: 'res://data/facilities/cafeteria.tres' remapped 'res://data/facilities/cafeteria.tres' at thread -1
|
||||
Loading resource: res://data/facilities/expansion/chapel.tres remapped: res://data/facilities/expansion/chapel.tres
|
||||
Completed load for: 'res://data/facilities/expansion/chapel.tres' remapped 'res://data/facilities/expansion/chapel.tres' at thread -1
|
||||
Loading resource: res://data/facilities/expansion/cleaning_room.tres remapped: res://data/facilities/expansion/cleaning_room.tres
|
||||
Completed load for: 'res://data/facilities/expansion/cleaning_room.tres' remapped 'res://data/facilities/expansion/cleaning_room.tres' at thread -1
|
||||
Loading resource: res://data/facilities/expansion/premium_room.tres remapped: res://data/facilities/expansion/premium_room.tres
|
||||
Completed load for: 'res://data/facilities/expansion/premium_room.tres' remapped 'res://data/facilities/expansion/premium_room.tres' at thread -1
|
||||
Loading resource: res://data/facilities/expansion/staff_dormitory.tres remapped: res://data/facilities/expansion/staff_dormitory.tres
|
||||
Completed load for: 'res://data/facilities/expansion/staff_dormitory.tres' remapped 'res://data/facilities/expansion/staff_dormitory.tres' at thread -1
|
||||
Loading resource: res://data/facilities/guest_corridor.tres remapped: res://data/facilities/guest_corridor.tres
|
||||
Completed load for: 'res://data/facilities/guest_corridor.tres' remapped 'res://data/facilities/guest_corridor.tres' at thread -1
|
||||
Loading resource: res://data/facilities/guest_elevator.tres remapped: res://data/facilities/guest_elevator.tres
|
||||
Completed load for: 'res://data/facilities/guest_elevator.tres' remapped 'res://data/facilities/guest_elevator.tres' at thread -1
|
||||
Loading resource: res://data/facilities/infrastructure/guest_stairs.tres remapped: res://data/facilities/infrastructure/guest_stairs.tres
|
||||
Completed load for: 'res://data/facilities/infrastructure/guest_stairs.tres' remapped 'res://data/facilities/infrastructure/guest_stairs.tres' at thread -1
|
||||
Loading resource: res://data/facilities/infrastructure/service_stairs.tres remapped: res://data/facilities/infrastructure/service_stairs.tres
|
||||
Completed load for: 'res://data/facilities/infrastructure/service_stairs.tres' remapped 'res://data/facilities/infrastructure/service_stairs.tres' at thread -1
|
||||
Loading resource: res://data/facilities/kitchen.tres remapped: res://data/facilities/kitchen.tres
|
||||
Completed load for: 'res://data/facilities/kitchen.tres' remapped 'res://data/facilities/kitchen.tres' at thread -1
|
||||
Loading resource: res://data/facilities/massage_room.tres remapped: res://data/facilities/massage_room.tres
|
||||
Completed load for: 'res://data/facilities/massage_room.tres' remapped 'res://data/facilities/massage_room.tres' at thread -1
|
||||
Loading resource: res://data/facilities/public_bath.tres remapped: res://data/facilities/public_bath.tres
|
||||
Completed load for: 'res://data/facilities/public_bath.tres' remapped 'res://data/facilities/public_bath.tres' at thread -1
|
||||
Loading resource: res://data/facilities/reception.tres remapped: res://data/facilities/reception.tres
|
||||
Completed load for: 'res://data/facilities/reception.tres' remapped 'res://data/facilities/reception.tres' at thread -1
|
||||
Loading resource: res://data/facilities/rescue/infirmary.tres remapped: res://data/facilities/rescue/infirmary.tres
|
||||
Completed load for: 'res://data/facilities/rescue/infirmary.tres' remapped 'res://data/facilities/rescue/infirmary.tres' at thread -1
|
||||
Loading resource: res://data/facilities/security_station.tres remapped: res://data/facilities/security_station.tres
|
||||
Completed load for: 'res://data/facilities/security_station.tres' remapped 'res://data/facilities/security_station.tres' at thread -1
|
||||
Loading resource: res://data/facilities/service_corridor.tres remapped: res://data/facilities/service_corridor.tres
|
||||
Completed load for: 'res://data/facilities/service_corridor.tres' remapped 'res://data/facilities/service_corridor.tres' at thread -1
|
||||
Loading resource: res://data/facilities/service_elevator.tres remapped: res://data/facilities/service_elevator.tres
|
||||
Completed load for: 'res://data/facilities/service_elevator.tres' remapped 'res://data/facilities/service_elevator.tres' at thread -1
|
||||
Loading resource: res://data/facilities/staff_door.tres remapped: res://data/facilities/staff_door.tres
|
||||
Completed load for: 'res://data/facilities/staff_door.tres' remapped 'res://data/facilities/staff_door.tres' at thread -1
|
||||
Loading resource: res://data/facilities/staff_waiting_room.tres remapped: res://data/facilities/staff_waiting_room.tres
|
||||
Completed load for: 'res://data/facilities/staff_waiting_room.tres' remapped 'res://data/facilities/staff_waiting_room.tres' at thread -1
|
||||
Loading resource: res://data/facilities/standard_room.tres remapped: res://data/facilities/standard_room.tres
|
||||
Completed load for: 'res://data/facilities/standard_room.tres' remapped 'res://data/facilities/standard_room.tres' at thread -1
|
||||
Loading resource: res://data/facilities/tavern.tres remapped: res://data/facilities/tavern.tres
|
||||
Completed load for: 'res://data/facilities/tavern.tres' remapped 'res://data/facilities/tavern.tres' at thread -1
|
||||
Loading resource: res://data/facilities/warehouse.tres remapped: res://data/facilities/warehouse.tres
|
||||
Completed load for: 'res://data/facilities/warehouse.tres' remapped 'res://data/facilities/warehouse.tres' at thread -1
|
||||
Phase diagnostic whole647: 17 checks, 0 failures
|
||||
XR: Clearing primary interface
|
||||
XR: Removed interface "Native mobile"
|
||||
XR: Removed interface "OpenXR"
|
||||
+268
@@ -0,0 +1,268 @@
|
||||
{
|
||||
"passed": true,
|
||||
"error": null,
|
||||
"guard_errors": [],
|
||||
"result": {
|
||||
"argv": [
|
||||
"/Applications/Godot.app/Contents/MacOS/Godot",
|
||||
"--headless",
|
||||
"--path",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage",
|
||||
"--script",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd",
|
||||
"--verbose",
|
||||
"--log-file",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/engine-native.log"
|
||||
],
|
||||
"pid": 60890,
|
||||
"started_utc": "2026-10-12T05:06:10.173663+00:00",
|
||||
"ended_utc": "2026-10-12T05:06:15.814823+00:00",
|
||||
"wall_seconds": 5.640924999999999,
|
||||
"exit_code": 0,
|
||||
"helper_exit_code": 0,
|
||||
"timed_out": false,
|
||||
"stdout_sha256": "2b66eb5a87fc2d25389c79ef66882ad54c0f845fc970b6a0acda57b0f412f651",
|
||||
"stderr_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
||||
"error_lines": [],
|
||||
"owned_popen_ended": true,
|
||||
"old_helper_engine_ended": true,
|
||||
"start_receipt_written": true,
|
||||
"end_receipt_written": true,
|
||||
"lifecycle_error": null,
|
||||
"old_helper_lifecycle_error": null,
|
||||
"actual_start_binding": {
|
||||
"scope": "isolated diagnostic owned child",
|
||||
"event": "ENGINE_STARTED",
|
||||
"actual_pid": 60890,
|
||||
"owner_pid": 60865,
|
||||
"command": [
|
||||
"/Applications/Godot.app/Contents/MacOS/Godot",
|
||||
"--headless",
|
||||
"--path",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage",
|
||||
"--script",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd",
|
||||
"--verbose",
|
||||
"--log-file",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/engine-native.log"
|
||||
],
|
||||
"monotonic_ns": 2490331791,
|
||||
"pid": 60890,
|
||||
"argv": [
|
||||
"/Applications/Godot.app/Contents/MacOS/Godot",
|
||||
"--headless",
|
||||
"--path",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage",
|
||||
"--script",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd",
|
||||
"--verbose",
|
||||
"--log-file",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/engine-native.log"
|
||||
],
|
||||
"started_utc": "2026-10-12T05:06:10.173663+00:00",
|
||||
"current_process_identity": {
|
||||
"pid": 60890,
|
||||
"ppid": 60865,
|
||||
"pgid": 60890,
|
||||
"args": "/Applications/Godot.app/Contents/MacOS/Godot --headless --path /Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage --script /Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd --verbose --log-file /Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/engine-native.log"
|
||||
},
|
||||
"live_identity_exact": true,
|
||||
"tracked_child_ended_before_initial_probe": false,
|
||||
"signal_scope": "tracked Popen child only; no external group signal"
|
||||
},
|
||||
"actual_end_binding": {
|
||||
"scope": "isolated diagnostic owned child",
|
||||
"event": "ENGINE_ENDED",
|
||||
"actual_pid": 60890,
|
||||
"owner_pid": 60865,
|
||||
"command": [
|
||||
"/Applications/Godot.app/Contents/MacOS/Godot",
|
||||
"--headless",
|
||||
"--path",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage",
|
||||
"--script",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd",
|
||||
"--verbose",
|
||||
"--log-file",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/engine-native.log"
|
||||
],
|
||||
"monotonic_ns": 8123426000,
|
||||
"exit_code": 0,
|
||||
"actual_process_exit_code": 0,
|
||||
"engine_ended": true,
|
||||
"timed_out": false,
|
||||
"lifecycle_error": null,
|
||||
"start_receipt_written": true,
|
||||
"pid": 60890,
|
||||
"argv": [
|
||||
"/Applications/Godot.app/Contents/MacOS/Godot",
|
||||
"--headless",
|
||||
"--path",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage",
|
||||
"--script",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd",
|
||||
"--verbose",
|
||||
"--log-file",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/engine-native.log"
|
||||
],
|
||||
"ended_utc": "2026-10-12T05:06:15.811628+00:00",
|
||||
"signal_scope": "tracked Popen child only; no external group signal"
|
||||
},
|
||||
"strict_native_diagnostics": {
|
||||
"errors": [],
|
||||
"banner_count": 1,
|
||||
"known_unicode_diagnostic_count": 0,
|
||||
"unrecognized_unicode_diagnostic_count": 0,
|
||||
"exit_leak_diagnostic_lines": []
|
||||
},
|
||||
"external_process_or_group_signals": 0,
|
||||
"owned_child_process_helper_sha256": "c007e712c281573254faa1233c2ac92e100ab87393256a6dc096b35283e43037",
|
||||
"adapter_owned_cleanup": {
|
||||
"owned_child_created": true,
|
||||
"engine_ended": true,
|
||||
"actual_process_exit_code": 0,
|
||||
"attempts": [
|
||||
{
|
||||
"attempt": 1,
|
||||
"kill_attempted": false,
|
||||
"wait_timeout_seconds": 5,
|
||||
"wait_completed": true,
|
||||
"errors": [],
|
||||
"poll_before": 0,
|
||||
"wait_returned_code": 0,
|
||||
"poll_after": 0
|
||||
}
|
||||
],
|
||||
"errors": []
|
||||
},
|
||||
"adapter_error": null,
|
||||
"old_helper_bytes_preserved": true,
|
||||
"helper_wait_None_maps_to_actual_timeout_seconds": 5,
|
||||
"explicit_helper_wait_timeouts_preserved": true,
|
||||
"additional_cleanup_wait_timeout_seconds": 5,
|
||||
"additional_cleanup_max_attempts": 3
|
||||
},
|
||||
"capture": {
|
||||
"actual_captured_pids": [
|
||||
60890
|
||||
],
|
||||
"cleanup": [
|
||||
{
|
||||
"pid": 60890,
|
||||
"cleanup": {
|
||||
"owned_child_created": true,
|
||||
"engine_ended": true,
|
||||
"actual_process_exit_code": 0,
|
||||
"attempts": [
|
||||
{
|
||||
"attempt": 1,
|
||||
"kill_attempted": false,
|
||||
"wait_timeout_seconds": 5,
|
||||
"wait_completed": true,
|
||||
"errors": [],
|
||||
"poll_before": 0,
|
||||
"wait_returned_code": 0,
|
||||
"poll_after": 0
|
||||
}
|
||||
],
|
||||
"errors": []
|
||||
},
|
||||
"outer_cleanup_errors": [],
|
||||
"engine_ended": true,
|
||||
"outer_maximum_helper_invocations": 3,
|
||||
"helper_maximum_waits": 3,
|
||||
"per_wait_timeout_seconds": 5,
|
||||
"foreign_process_or_group_signals": 0
|
||||
}
|
||||
],
|
||||
"adapter_exception": null,
|
||||
"all_captured_ended": true,
|
||||
"outer_cleanup_errors": [],
|
||||
"foreign_process_or_group_signals": 0,
|
||||
"all_cleanup_before_outer_receipt": true,
|
||||
"outer_receipt_written": true,
|
||||
"outer_receipt_error": null,
|
||||
"passed": true
|
||||
},
|
||||
"report": {
|
||||
"Windows_accepted": false,
|
||||
"after647": {
|
||||
"bytes": 246720,
|
||||
"codec": "zstd",
|
||||
"field_deletions": 0,
|
||||
"file_envelope": false,
|
||||
"full_bytes_roundtrip": true,
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/measurement/after647.varbytes.zst",
|
||||
"sha256": "684ba40e9f649b7dd4bfc620185d7cd18bae3111c3b4038e48aaad5a9168d880",
|
||||
"uncompressed_bytes": 11487732,
|
||||
"uncompressed_sha256": "9df3c1b6f65dfd8be944cd5cab8c631f7533530dfef3820d9fa5d74a5b1ac30f"
|
||||
},
|
||||
"cache_hits": 0,
|
||||
"cache_misses": 9311,
|
||||
"candidate": "r333-diagnostic",
|
||||
"candidate_adopted": false,
|
||||
"checks": 17,
|
||||
"diagnostic_only": true,
|
||||
"failures": [],
|
||||
"limits": [
|
||||
"One instrumented r333/library334 cold646 tick; nested inclusive metrics, no sums or subtraction as pure CPU, no uninstrumented speed comparison or acceptance.",
|
||||
"No Main, rendering, OS input or realtime x3. Timed interval contains builtin production callbacks; snapshot verification and compression occur after timing."
|
||||
],
|
||||
"manual_tick_us": 1016169,
|
||||
"metrics": {
|
||||
"bytes": 887,
|
||||
"codec": "zstd",
|
||||
"field_deletions": 0,
|
||||
"file_envelope": false,
|
||||
"full_bytes_roundtrip": true,
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/measurement/metrics.varbytes.zst",
|
||||
"sha256": "4cb3c0f5b12a1de658d8afc293eace99650f05d17dc9f18037ed676207e9de3c",
|
||||
"uncompressed_bytes": 4456,
|
||||
"uncompressed_sha256": "129473a8a3951768bb3f4bb3a0773abf9a138e51ef189341acaba45b14cbf5ec"
|
||||
},
|
||||
"normal_OS_accepted": false,
|
||||
"passed": true,
|
||||
"performance_budget_accepted": false,
|
||||
"pid": 60890,
|
||||
"plan_id": "P23-02",
|
||||
"sample": "r338",
|
||||
"unit_accepted": false
|
||||
},
|
||||
"cleanup": [
|
||||
{
|
||||
"pid": 60890,
|
||||
"cleanup": {
|
||||
"owned_child_created": true,
|
||||
"engine_ended": true,
|
||||
"actual_process_exit_code": 0,
|
||||
"attempts": [
|
||||
{
|
||||
"attempt": 1,
|
||||
"kill_attempted": false,
|
||||
"wait_timeout_seconds": 5,
|
||||
"wait_completed": true,
|
||||
"errors": [],
|
||||
"poll_before": 0,
|
||||
"wait_returned_code": 0,
|
||||
"poll_after": 0
|
||||
}
|
||||
],
|
||||
"errors": []
|
||||
},
|
||||
"outer_cleanup_errors": [],
|
||||
"engine_ended": true,
|
||||
"outer_maximum_helper_invocations": 3,
|
||||
"helper_maximum_waits": 3,
|
||||
"per_wait_timeout_seconds": 5,
|
||||
"foreign_process_or_group_signals": 0
|
||||
}
|
||||
],
|
||||
"cleanup_errors": [],
|
||||
"source_default_doc4_support_stage_preserved": true,
|
||||
"unit_accepted": false,
|
||||
"performance_accepted": false,
|
||||
"candidate_adopted": false,
|
||||
"limits": [
|
||||
"One instrumented current r333/library334 cold646 tick. Nested inclusive measurements overlap and include instrumentation. No CPU sums/subtraction, uninstrumented comparisons, stable gain/P95/budget/final regression/Main/x3/OS/Windows acceptance."
|
||||
]
|
||||
}
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
+211
@@ -0,0 +1,211 @@
|
||||
{
|
||||
"facility": {
|
||||
"_complete_service": {
|
||||
"calls": 0,
|
||||
"inclusive_us": 0,
|
||||
"max_us": 0
|
||||
},
|
||||
"advance_one_minute": {
|
||||
"calls": 1,
|
||||
"inclusive_us": 952,
|
||||
"max_us": 952
|
||||
},
|
||||
"refresh_operating_dependencies": {
|
||||
"calls": 1,
|
||||
"inclusive_us": 402,
|
||||
"max_us": 402
|
||||
},
|
||||
"start_next_service": {
|
||||
"calls": 0,
|
||||
"inclusive_us": 0,
|
||||
"max_us": 0
|
||||
}
|
||||
},
|
||||
"inventory": {
|
||||
"_find_stack": {
|
||||
"calls": 438,
|
||||
"inclusive_us": 471,
|
||||
"max_us": 2
|
||||
},
|
||||
"create_snapshot": {
|
||||
"calls": 10,
|
||||
"inclusive_us": 10037,
|
||||
"max_us": 1226
|
||||
},
|
||||
"process_expired": {
|
||||
"calls": 1,
|
||||
"inclusive_us": 348,
|
||||
"max_us": 348
|
||||
},
|
||||
"reserve_item": {
|
||||
"calls": 0,
|
||||
"inclusive_us": 0,
|
||||
"max_us": 0
|
||||
}
|
||||
},
|
||||
"kernel_phases": {
|
||||
"0": {
|
||||
"calls": 1,
|
||||
"inclusive_us": 15,
|
||||
"max_us": 15
|
||||
},
|
||||
"1": {
|
||||
"calls": 1,
|
||||
"inclusive_us": 1140,
|
||||
"max_us": 1140
|
||||
},
|
||||
"10": {
|
||||
"calls": 1,
|
||||
"inclusive_us": 76085,
|
||||
"max_us": 76085
|
||||
},
|
||||
"2": {
|
||||
"calls": 1,
|
||||
"inclusive_us": 395,
|
||||
"max_us": 395
|
||||
},
|
||||
"3": {
|
||||
"calls": 1,
|
||||
"inclusive_us": 118776,
|
||||
"max_us": 118776
|
||||
},
|
||||
"4": {
|
||||
"calls": 1,
|
||||
"inclusive_us": 88107,
|
||||
"max_us": 88107
|
||||
},
|
||||
"5": {
|
||||
"calls": 1,
|
||||
"inclusive_us": 964,
|
||||
"max_us": 964
|
||||
},
|
||||
"6": {
|
||||
"calls": 1,
|
||||
"inclusive_us": 1043,
|
||||
"max_us": 1043
|
||||
},
|
||||
"7": {
|
||||
"calls": 1,
|
||||
"inclusive_us": 236,
|
||||
"max_us": 236
|
||||
},
|
||||
"8": {
|
||||
"calls": 1,
|
||||
"inclusive_us": 174,
|
||||
"max_us": 174
|
||||
},
|
||||
"9": {
|
||||
"calls": 1,
|
||||
"inclusive_us": 729195,
|
||||
"max_us": 729195
|
||||
}
|
||||
},
|
||||
"kitchen": {
|
||||
"advance_one_minute": {
|
||||
"calls": 1,
|
||||
"inclusive_us": 4,
|
||||
"max_us": 4
|
||||
}
|
||||
},
|
||||
"logistics": {
|
||||
"tick": {
|
||||
"calls": 1,
|
||||
"inclusive_us": 87311,
|
||||
"max_us": 87311
|
||||
}
|
||||
},
|
||||
"runtime": {
|
||||
"_advance_construction": {
|
||||
"calls": 1,
|
||||
"inclusive_us": 118770,
|
||||
"max_us": 118770
|
||||
},
|
||||
"_advance_facilities": {
|
||||
"calls": 1,
|
||||
"inclusive_us": 960,
|
||||
"max_us": 960
|
||||
},
|
||||
"_advance_guest_ai_decisions": {
|
||||
"calls": 1,
|
||||
"inclusive_us": 717924,
|
||||
"max_us": 717924
|
||||
},
|
||||
"_advance_inventory_and_logistics": {
|
||||
"calls": 1,
|
||||
"inclusive_us": 88101,
|
||||
"max_us": 88101
|
||||
},
|
||||
"_advance_staff_ai": {
|
||||
"calls": 1,
|
||||
"inclusive_us": 729191,
|
||||
"max_us": 729191
|
||||
},
|
||||
"_apply_service_transaction": {
|
||||
"calls": 0,
|
||||
"inclusive_us": 0,
|
||||
"max_us": 0
|
||||
},
|
||||
"_complete_service_transaction": {
|
||||
"calls": 0,
|
||||
"inclusive_us": 0,
|
||||
"max_us": 0
|
||||
},
|
||||
"_decide_guest_with_log": {
|
||||
"calls": 50,
|
||||
"inclusive_us": 79192,
|
||||
"max_us": 1848
|
||||
},
|
||||
"_execute_create_logistics_request": {
|
||||
"calls": 0,
|
||||
"inclusive_us": 0,
|
||||
"max_us": 0
|
||||
},
|
||||
"_preflight_proxy_completions": {
|
||||
"calls": 2,
|
||||
"inclusive_us": 345,
|
||||
"max_us": 174
|
||||
},
|
||||
"_project_guest_candidates": {
|
||||
"calls": 50,
|
||||
"inclusive_us": 564197,
|
||||
"max_us": 44219
|
||||
},
|
||||
"_publish_snapshot": {
|
||||
"calls": 1,
|
||||
"inclusive_us": 76063,
|
||||
"max_us": 76063
|
||||
},
|
||||
"_validate_infrastructure_crosslinks": {
|
||||
"calls": 1,
|
||||
"inclusive_us": 118334,
|
||||
"max_us": 118334
|
||||
},
|
||||
"_validate_service_start": {
|
||||
"calls": 0,
|
||||
"inclusive_us": 0,
|
||||
"max_us": 0
|
||||
}
|
||||
},
|
||||
"supply": {
|
||||
"_connection_distance": {
|
||||
"calls": 0,
|
||||
"inclusive_us": 0,
|
||||
"max_us": 0
|
||||
},
|
||||
"_purchase_paid": {
|
||||
"calls": 0,
|
||||
"inclusive_us": 0,
|
||||
"max_us": 0
|
||||
},
|
||||
"advance_auto_purchases": {
|
||||
"calls": 1,
|
||||
"inclusive_us": 140,
|
||||
"max_us": 140
|
||||
},
|
||||
"ensure_deliveries": {
|
||||
"calls": 1,
|
||||
"inclusive_us": 272,
|
||||
"max_us": 272
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
Binary file not shown.
+44
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"Windows_accepted": false,
|
||||
"after647": {
|
||||
"bytes": 246720,
|
||||
"codec": "zstd",
|
||||
"field_deletions": 0,
|
||||
"file_envelope": false,
|
||||
"full_bytes_roundtrip": true,
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/measurement/after647.varbytes.zst",
|
||||
"sha256": "684ba40e9f649b7dd4bfc620185d7cd18bae3111c3b4038e48aaad5a9168d880",
|
||||
"uncompressed_bytes": 11487732,
|
||||
"uncompressed_sha256": "9df3c1b6f65dfd8be944cd5cab8c631f7533530dfef3820d9fa5d74a5b1ac30f"
|
||||
},
|
||||
"cache_hits": 0,
|
||||
"cache_misses": 9311,
|
||||
"candidate": "r333-diagnostic",
|
||||
"candidate_adopted": false,
|
||||
"checks": 17,
|
||||
"diagnostic_only": true,
|
||||
"failures": [],
|
||||
"limits": [
|
||||
"One instrumented r333/library334 cold646 tick; nested inclusive metrics, no sums or subtraction as pure CPU, no uninstrumented speed comparison or acceptance.",
|
||||
"No Main, rendering, OS input or realtime x3. Timed interval contains builtin production callbacks; snapshot verification and compression occur after timing."
|
||||
],
|
||||
"manual_tick_us": 1016169,
|
||||
"metrics": {
|
||||
"bytes": 887,
|
||||
"codec": "zstd",
|
||||
"field_deletions": 0,
|
||||
"file_envelope": false,
|
||||
"full_bytes_roundtrip": true,
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/measurement/metrics.varbytes.zst",
|
||||
"sha256": "4cb3c0f5b12a1de658d8afc293eace99650f05d17dc9f18037ed676207e9de3c",
|
||||
"uncompressed_bytes": 4456,
|
||||
"uncompressed_sha256": "129473a8a3951768bb3f4bb3a0773abf9a138e51ef189341acaba45b14cbf5ec"
|
||||
},
|
||||
"normal_OS_accepted": false,
|
||||
"passed": true,
|
||||
"performance_budget_accepted": false,
|
||||
"pid": 60890,
|
||||
"plan_id": "P23-02",
|
||||
"sample": "r338",
|
||||
"unit_accepted": false
|
||||
}
|
||||
+184
@@ -0,0 +1,184 @@
|
||||
{
|
||||
"result": {
|
||||
"argv": [
|
||||
"/Applications/Godot.app/Contents/MacOS/Godot",
|
||||
"--headless",
|
||||
"--path",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage",
|
||||
"--script",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd",
|
||||
"--verbose",
|
||||
"--log-file",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/engine-native.log"
|
||||
],
|
||||
"pid": 60890,
|
||||
"started_utc": "2026-10-12T05:06:10.173663+00:00",
|
||||
"ended_utc": "2026-10-12T05:06:15.814823+00:00",
|
||||
"wall_seconds": 5.640924999999999,
|
||||
"exit_code": 0,
|
||||
"helper_exit_code": 0,
|
||||
"timed_out": false,
|
||||
"stdout_sha256": "2b66eb5a87fc2d25389c79ef66882ad54c0f845fc970b6a0acda57b0f412f651",
|
||||
"stderr_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
||||
"error_lines": [],
|
||||
"owned_popen_ended": true,
|
||||
"old_helper_engine_ended": true,
|
||||
"start_receipt_written": true,
|
||||
"end_receipt_written": true,
|
||||
"lifecycle_error": null,
|
||||
"old_helper_lifecycle_error": null,
|
||||
"actual_start_binding": {
|
||||
"scope": "isolated diagnostic owned child",
|
||||
"event": "ENGINE_STARTED",
|
||||
"actual_pid": 60890,
|
||||
"owner_pid": 60865,
|
||||
"command": [
|
||||
"/Applications/Godot.app/Contents/MacOS/Godot",
|
||||
"--headless",
|
||||
"--path",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage",
|
||||
"--script",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd",
|
||||
"--verbose",
|
||||
"--log-file",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/engine-native.log"
|
||||
],
|
||||
"monotonic_ns": 2490331791,
|
||||
"pid": 60890,
|
||||
"argv": [
|
||||
"/Applications/Godot.app/Contents/MacOS/Godot",
|
||||
"--headless",
|
||||
"--path",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage",
|
||||
"--script",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd",
|
||||
"--verbose",
|
||||
"--log-file",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/engine-native.log"
|
||||
],
|
||||
"started_utc": "2026-10-12T05:06:10.173663+00:00",
|
||||
"current_process_identity": {
|
||||
"pid": 60890,
|
||||
"ppid": 60865,
|
||||
"pgid": 60890,
|
||||
"args": "/Applications/Godot.app/Contents/MacOS/Godot --headless --path /Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage --script /Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd --verbose --log-file /Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/engine-native.log"
|
||||
},
|
||||
"live_identity_exact": true,
|
||||
"tracked_child_ended_before_initial_probe": false,
|
||||
"signal_scope": "tracked Popen child only; no external group signal"
|
||||
},
|
||||
"actual_end_binding": {
|
||||
"scope": "isolated diagnostic owned child",
|
||||
"event": "ENGINE_ENDED",
|
||||
"actual_pid": 60890,
|
||||
"owner_pid": 60865,
|
||||
"command": [
|
||||
"/Applications/Godot.app/Contents/MacOS/Godot",
|
||||
"--headless",
|
||||
"--path",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage",
|
||||
"--script",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd",
|
||||
"--verbose",
|
||||
"--log-file",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/engine-native.log"
|
||||
],
|
||||
"monotonic_ns": 8123426000,
|
||||
"exit_code": 0,
|
||||
"actual_process_exit_code": 0,
|
||||
"engine_ended": true,
|
||||
"timed_out": false,
|
||||
"lifecycle_error": null,
|
||||
"start_receipt_written": true,
|
||||
"pid": 60890,
|
||||
"argv": [
|
||||
"/Applications/Godot.app/Contents/MacOS/Godot",
|
||||
"--headless",
|
||||
"--path",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage",
|
||||
"--script",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd",
|
||||
"--verbose",
|
||||
"--log-file",
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/engine-native.log"
|
||||
],
|
||||
"ended_utc": "2026-10-12T05:06:15.811628+00:00",
|
||||
"signal_scope": "tracked Popen child only; no external group signal"
|
||||
},
|
||||
"strict_native_diagnostics": {
|
||||
"errors": [],
|
||||
"banner_count": 1,
|
||||
"known_unicode_diagnostic_count": 0,
|
||||
"unrecognized_unicode_diagnostic_count": 0,
|
||||
"exit_leak_diagnostic_lines": []
|
||||
},
|
||||
"external_process_or_group_signals": 0,
|
||||
"owned_child_process_helper_sha256": "c007e712c281573254faa1233c2ac92e100ab87393256a6dc096b35283e43037",
|
||||
"adapter_owned_cleanup": {
|
||||
"owned_child_created": true,
|
||||
"engine_ended": true,
|
||||
"actual_process_exit_code": 0,
|
||||
"attempts": [
|
||||
{
|
||||
"attempt": 1,
|
||||
"kill_attempted": false,
|
||||
"wait_timeout_seconds": 5,
|
||||
"wait_completed": true,
|
||||
"errors": [],
|
||||
"poll_before": 0,
|
||||
"wait_returned_code": 0,
|
||||
"poll_after": 0
|
||||
}
|
||||
],
|
||||
"errors": []
|
||||
},
|
||||
"adapter_error": null,
|
||||
"old_helper_bytes_preserved": true,
|
||||
"helper_wait_None_maps_to_actual_timeout_seconds": 5,
|
||||
"explicit_helper_wait_timeouts_preserved": true,
|
||||
"additional_cleanup_wait_timeout_seconds": 5,
|
||||
"additional_cleanup_max_attempts": 3
|
||||
},
|
||||
"capture": {
|
||||
"actual_captured_pids": [
|
||||
60890
|
||||
],
|
||||
"cleanup": [
|
||||
{
|
||||
"pid": 60890,
|
||||
"cleanup": {
|
||||
"owned_child_created": true,
|
||||
"engine_ended": true,
|
||||
"actual_process_exit_code": 0,
|
||||
"attempts": [
|
||||
{
|
||||
"attempt": 1,
|
||||
"kill_attempted": false,
|
||||
"wait_timeout_seconds": 5,
|
||||
"wait_completed": true,
|
||||
"errors": [],
|
||||
"poll_before": 0,
|
||||
"wait_returned_code": 0,
|
||||
"poll_after": 0
|
||||
}
|
||||
],
|
||||
"errors": []
|
||||
},
|
||||
"outer_cleanup_errors": [],
|
||||
"engine_ended": true,
|
||||
"outer_maximum_helper_invocations": 3,
|
||||
"helper_maximum_waits": 3,
|
||||
"per_wait_timeout_seconds": 5,
|
||||
"foreign_process_or_group_signals": 0
|
||||
}
|
||||
],
|
||||
"adapter_exception": null,
|
||||
"all_captured_ended": true,
|
||||
"outer_cleanup_errors": [],
|
||||
"foreign_process_or_group_signals": 0,
|
||||
"all_cleanup_before_outer_receipt": true,
|
||||
"outer_receipt_written": true,
|
||||
"outer_receipt_error": null,
|
||||
"passed": true
|
||||
}
|
||||
}
|
||||
+258
@@ -0,0 +1,258 @@
|
||||
{
|
||||
"passed": true,
|
||||
"review_sha256": "ad50e109577313f7626e931cfc6943a944fee2f9912adb4d60e706659ae0c23d",
|
||||
"verified_entries": [
|
||||
{
|
||||
"path": "/Applications/Godot.app/Contents/MacOS/Godot",
|
||||
"bytes": 351312912,
|
||||
"sha256": "c7cccbf8fb143e34e02fd6521e09be2c2b974f0d5db080b19071c9c570718ccf"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-walk-edges-candidate-r265-r03/performance_budget.candidate.gd",
|
||||
"bytes": 11250,
|
||||
"sha256": "1010129d3124c3aec037c840a5766a7cdabe60c654999dfb6f23b224140a73f8"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-local-names-candidate-r239/stage/scripts/world/path_service.gd",
|
||||
"bytes": 132925,
|
||||
"sha256": "6b7f4e989ea9b09495f814d8ecb294028d10794005966414bf52640e122b0d17"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-single-actor-path-native-r03/diagnostic-measurement/checkpoint646.varbytes.zst",
|
||||
"bytes": 240032,
|
||||
"sha256": "1a88f7ed27d1d32102c6fe3a9533221d2565191712ed15b631190479d1d41505"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-report-window-trusted-report-whole647-native-r02/diagnostic-measurement/after647.varbytes.zst",
|
||||
"bytes": 246720,
|
||||
"sha256": "684ba40e9f649b7dd4bfc620185d7cd18bae3111c3b4038e48aaad5a9168d880"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd",
|
||||
"bytes": 1441,
|
||||
"sha256": "3dd8e4f3590fd5b274811c5fffdd49e12e69803b5385c409f786245b9fed1b62"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/diagnostic.gd",
|
||||
"bytes": 6807,
|
||||
"sha256": "f076e93357b521c0add060a262a725637daf9fa39c9bdb8ccb156f20bfcba9a1"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-input-copy-local-r335/candidate.gdextension",
|
||||
"bytes": 214,
|
||||
"sha256": "a51d6bbbef6a00b82ded03a0d637c057b6b70d13025d4c3042f2984d0cb7152a"
|
||||
},
|
||||
{
|
||||
"path": "/private/tmp/TheTree-input-copy-r335-3afabc8ef9ee42d0be34994471a451b5/candidate.dylib",
|
||||
"bytes": 433744,
|
||||
"sha256": "39f8ed73f077d15037d85b9cb53f38389c032a36dea7ff04348e5ef05c736907"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/autoload/simulation_runtime.gd",
|
||||
"bytes": 612068,
|
||||
"sha256": "7eb24adbf91fe53cde14954dda12abd5efb05130de7d356d8df281ee99065e86"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/autoload/simulation_runtime.gd",
|
||||
"bytes": 621773,
|
||||
"sha256": "ce260f1158adfb8d9adda1ea00fa29b3c76bc4968c9f7996fdcf62193e28b540"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/autoload/simulation_runtime.gd",
|
||||
"bytes": 612068,
|
||||
"sha256": "7eb24adbf91fe53cde14954dda12abd5efb05130de7d356d8df281ee99065e86"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/inventory/inventory_service.gd",
|
||||
"bytes": 57923,
|
||||
"sha256": "7ee83b335864385119ca757037c3cdb912957aa4478a6312a0898a734e41f31a"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/inventory/inventory_service.gd",
|
||||
"bytes": 60808,
|
||||
"sha256": "a93e7486fab66938ce7356b16202dddf0d4dd2f9c30e6b9312ec4ee98878480e"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/inventory/inventory_service.gd",
|
||||
"bytes": 57923,
|
||||
"sha256": "7ee83b335864385119ca757037c3cdb912957aa4478a6312a0898a734e41f31a"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/facility/facility_service.gd",
|
||||
"bytes": 44951,
|
||||
"sha256": "ceb4a3e9224587423f273cdb2b56e6843ab176ac1fc4fe79dd498b5ed5c33b77"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/facility/facility_service.gd",
|
||||
"bytes": 47788,
|
||||
"sha256": "c24d9b475c66046dc7342401a74fdc084ca6698506fdb9284afbadd6c5e68cfa"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/facility/facility_service.gd",
|
||||
"bytes": 44951,
|
||||
"sha256": "ceb4a3e9224587423f273cdb2b56e6843ab176ac1fc4fe79dd498b5ed5c33b77"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/supply/supply_management_service.gd",
|
||||
"bytes": 25019,
|
||||
"sha256": "e4ad420191020485c027004f64bb00fad9da195fe956ef10dc0c787412018f7f"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/supply/supply_management_service.gd",
|
||||
"bytes": 27952,
|
||||
"sha256": "87f2a3c36ef8b4569d17191f0c376fc957462dd7fe33a832c7284fdceb4a5b3c"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/supply/supply_management_service.gd",
|
||||
"bytes": 25019,
|
||||
"sha256": "e4ad420191020485c027004f64bb00fad9da195fe956ef10dc0c787412018f7f"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/supply/supply_logistics_bridge.gd",
|
||||
"bytes": 28100,
|
||||
"sha256": "b9e394af788595d2744b71f1907c8e7c3d762d38ff49992b1ee74e63b9639e80"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/supply/supply_logistics_bridge.gd",
|
||||
"bytes": 28814,
|
||||
"sha256": "6887a702c1eb6f9e91f689fd734f9bbc386a9cce55a68b1682c3a18be620976a"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/supply/supply_logistics_bridge.gd",
|
||||
"bytes": 28100,
|
||||
"sha256": "b9e394af788595d2744b71f1907c8e7c3d762d38ff49992b1ee74e63b9639e80"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/supply/kitchen_production_service.gd",
|
||||
"bytes": 18872,
|
||||
"sha256": "f3bc6bdc1a0ba278e9411108172ceceb7eb06520b4e33f93f35684da1f103c62"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/supply/kitchen_production_service.gd",
|
||||
"bytes": 19610,
|
||||
"sha256": "b751511484258edb471567639f150d8dcfb69ff4245a2273718cfcb3de04ca51"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/supply/kitchen_production_service.gd",
|
||||
"bytes": 18872,
|
||||
"sha256": "f3bc6bdc1a0ba278e9411108172ceceb7eb06520b4e33f93f35684da1f103c62"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/core/simulation_kernel.gd",
|
||||
"bytes": 7602,
|
||||
"sha256": "341c0c878c4894adbac628d0db6362ff69fc3347bdd9e61e50936e15dc2d1edb"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/core/simulation_kernel.gd",
|
||||
"bytes": 8264,
|
||||
"sha256": "9c67f2b22a38ab396e9d84522b3d54edb7be85878eb6a745deecb9ca2bde8692"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/core/simulation_kernel.gd",
|
||||
"bytes": 7602,
|
||||
"sha256": "341c0c878c4894adbac628d0db6362ff69fc3347bdd9e61e50936e15dc2d1edb"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/input.json",
|
||||
"bytes": 1023880,
|
||||
"sha256": "43f57b58c7533dae7965b71a739dd256219e264b1f2b3bb8639c8bf1a625696e"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338.py",
|
||||
"bytes": 6430,
|
||||
"sha256": "df468edfdc85ec9f445206ad005254d0472d1f8cc2f2c3fbea41db05dbd53b9a"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/tools/run_all_tests.py",
|
||||
"bytes": 26296,
|
||||
"sha256": "320ca668732b4ff72fc4449998af2327d4e5c527b06896740806aaf0487282b4"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/tools/regression/owned_outer.py",
|
||||
"bytes": 4177,
|
||||
"sha256": "c2e3483b76db1a3ff940f23f88ea0083fc78736e874ebcdb385d766dde8866e7"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-build-preview-monitor-compressed-r06.gd",
|
||||
"bytes": 17582,
|
||||
"sha256": "92d5e1956f4e613e12555d756de4f71fef03678cde159ac68fac3188ce3f336e"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-cache-public-mutations-r144/profile_guard.gd",
|
||||
"bytes": 2276,
|
||||
"sha256": "597696c705cc8f0e79a35265ca3ef8df55f7fc3c4e0e5a2ce9a4e20e29e29a6f"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/core/performance_budget.gd",
|
||||
"bytes": 10355,
|
||||
"sha256": "742c464d16ab417cbc3c2930d43e508faf5c9f7688da416324ca1150bdb9b6b9"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/project.godot",
|
||||
"bytes": 1294,
|
||||
"sha256": "686f3da7f6b592cd95d84e71a83374a28173914b377eafa4a6e005d70062d00d"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-input-copy-build-actual-independent-review-r334.json",
|
||||
"bytes": 40719,
|
||||
"sha256": "991e093110a35df5742e4b6bbd9254d664f20c280056fa6dd19e35be0bdcd871"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-input-copy-whole-actual-independent-review-r336.json",
|
||||
"bytes": 40888,
|
||||
"sha256": "671fedcbd0d48a42809aa6ca19d91c5ed4d22f4e6201ad1a00b3d3be18f291b8"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/input-before-phase-mapping-correction.json",
|
||||
"bytes": 1017508,
|
||||
"sha256": "fe9c06fd72ccd6bb88557082b5015bd8ad8386eee44371fdb4bd9dc8beb658db"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/input-before-transaction-method-correction.json",
|
||||
"bytes": 1011383,
|
||||
"sha256": "ca1c57a6c3266df161f8832842bc61c1305ecd2ecd77b7527533dcb44123f639"
|
||||
},
|
||||
{
|
||||
"path": "/private/tmp/thetree-prepare-residual-r338.py",
|
||||
"bytes": 9527,
|
||||
"sha256": "ff0e7c5fcb572b900585b334890612e19894f347ea57a6e1541935c7df6f3468"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-preexecution-independent-review-r338.json",
|
||||
"bytes": 26442,
|
||||
"sha256": "25d15928c713cb1608490bae5ea10d6374b21a764c87ae19ba2ce32a2d20ba39"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02.py",
|
||||
"bytes": 6438,
|
||||
"sha256": "97e994c336ae44f78581e0885321b572d002635c39e36ae62aa1e84feb6fd011"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/input.json",
|
||||
"bytes": 1024228,
|
||||
"sha256": "95f7929f2a8d78593d18285d2c1581ef7a303dae6fae331c8312e15b700b5d91"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/IMPLEMENTATION_PLAN.md",
|
||||
"bytes": 492489,
|
||||
"sha256": "4e9748ca579001e5673f83568d64bbe45b6bad7420ee6481901496f0fd7e9f28"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/PROGRESS_INTEGRATION.md",
|
||||
"bytes": 410553,
|
||||
"sha256": "b5617405aaa913cef5f5e23bbc5141bfb746de88926116c02ea2d33bd5ea7a22"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/work_packages.json",
|
||||
"bytes": 1188101,
|
||||
"sha256": "e7e8d40e9a9a85095d6e4ad96ab305fa1bf83f10f754b3c541e27cb78b1f6f67"
|
||||
},
|
||||
{
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/progress_snapshot.json",
|
||||
"bytes": 591756,
|
||||
"sha256": "db411f761cc2e64d9ae7859ebdc085bfacc1b649dd4c7241c34a96fd28e07b97"
|
||||
}
|
||||
],
|
||||
"unit_accepted": false,
|
||||
"performance_accepted": false
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"actual_user_data_dir": "/Users/korizatou114/Library/Application Support/TheTree-PCK-tests-ac61124b83b44a65a0eb28434ae3fdf2-diagnostic-runtime",
|
||||
"before": "/Users/korizatou114/Library/Application Support/TheTree-PCK-tests-ac61124b83b44a65a0eb28434ae3fdf2-diagnostic-startup",
|
||||
"conditions": [
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true
|
||||
],
|
||||
"conditions_checked": 5,
|
||||
"custom_user_dir_name": "TheTree-PCK-tests-ac61124b83b44a65a0eb28434ae3fdf2-diagnostic-runtime",
|
||||
"expected_user_data_dir": "/Users/korizatou114/Library/Application Support/TheTree-PCK-tests-ac61124b83b44a65a0eb28434ae3fdf2-diagnostic-runtime",
|
||||
"fresh_before_parent_initialize": true,
|
||||
"globalized_probe": "/Users/korizatou114/Library/Application Support/TheTree-PCK-tests-ac61124b83b44a65a0eb28434ae3fdf2-diagnostic-runtime/guard-probe",
|
||||
"profile_writes_before_guard": 0,
|
||||
"project_settings_persisted": false,
|
||||
"runtime_settings_only": true,
|
||||
"verified": true
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
# coding: utf-8
|
||||
from pathlib import Path
|
||||
import importlib.util,json,hashlib,os,uuid,shutil,subprocess,traceback,sys
|
||||
sys.dont_write_bytecode=True
|
||||
R=Path(__file__).resolve().parents[2]; A=R/'artifacts/original-completion-2026-10-02';D=R/'docs/plans/original-completion-2026-10-02';O=A/'p23-02-current-phase-diagnostic-r338'
|
||||
def mod(n,p):
|
||||
s=importlib.util.spec_from_file_location(n,p);m=importlib.util.module_from_spec(s);s.loader.exec_module(m);return m
|
||||
def unpack(p):return subprocess.run(['/opt/homebrew/bin/zstd','-d','-q','-c',str(p)],check=True,capture_output=True,timeout=10).stdout
|
||||
def main():
|
||||
r=mod('r338',R/'tools/run_all_tests.py');outer=mod('o338',r.SUPPORT/'owned_outer.py');p=r.read(O/'input.json');assert not (O/'execution.json').exists()
|
||||
prepath=A/'p23-02-current-phase-diagnostic-preexecution-independent-review-r338.json';pre=r.read(prepath);assert pre['execution_allowed'] and not pre['blockers']
|
||||
for group in ['evidence_sha256','canonical_doc4_context_pins']:
|
||||
for key,q in pre[group].items():
|
||||
f=Path(q.get('path',key));assert f.stat().st_size==q['bytes'] and r.sha(f)==q['sha256']
|
||||
root=r.read(O/'preexecution-root-verification.json');assert root['passed'] and root['review_sha256']==r.sha(prepath)
|
||||
stage=Path(p['stage']);public=(stage/'project.godot').read_bytes();budget=stage/'scripts/core/performance_budget.gd';budget_before=budget.read_bytes();patched=False
|
||||
fixed=p['pins'];source=r.source_refs(R);default=r.default_player(R);docs={n:r.sha(D/n) for n in p['doc4_before']};assert source==p['source_before'] and default==p['default_before'] and docs==p['doc4_before']
|
||||
def protect():
|
||||
assert r.source_refs(R)==source and r.default_player(R)==default and {n:r.sha(D/n) for n in docs}==docs and r.inventory(r.SUPPORT)==p['support_inventory']
|
||||
assert r.inventory(stage,stage=True)==(p['patched_stage'] if patched else p['expected_stage'])
|
||||
for q in fixed.values():
|
||||
f=Path(q['path']);assert f.stat().st_size==q['bytes'] and r.sha(f)==q['sha256']
|
||||
for row in p['manifest'].values():
|
||||
for key in ['before','after']:
|
||||
q=row[key];f=Path(q['path']);assert f.stat().st_size==q['bytes'] and r.sha(f)==q['sha256']
|
||||
protect();error=None;guard_errors=[];cleanup=[];cleanup_errors=[];result=None;capture=None;report=None
|
||||
try:
|
||||
assert not outer.native.helper['live_engines']() and shutil.disk_usage(A).free>=p['capacity_floor_bytes']
|
||||
for rel,row in p['manifest'].items():(stage/rel).write_bytes(Path(row['after']['path']).read_bytes())
|
||||
budget.write_bytes(Path(fixed['modified_budget']['path']).read_bytes());patched=True;protect()
|
||||
output=O/'measurement';output.mkdir();ident=uuid.uuid4().hex;startup='TheTree-PCK-tests-'+ident+'-diagnostic-startup';profile='TheTree-PCK-tests-'+ident+'-diagnostic-runtime';assert not r.profile_path(startup).exists() and not r.profile_path(profile).exists()
|
||||
env=r.fresh_environment(os.environ);env.update(THE_TREE_PACK_PROFILE_NAME=profile,THE_TREE_PACK_PROFILE_EXPECTED=str(r.profile_path(profile)),THE_TREE_PACK_PROFILE_REPORT=str(O/'profile.json'),THE_TREE_RUNTIME_MONITOR_OUTPUT=str(output),THE_TREE_REPLAY_SNAPSHOT=fixed['fixture']['path'],THE_TREE_CANDIDATE_ORACLE=fixed['oracle']['path'],THE_TREE_PAIRED_CANDIDATE='r333-diagnostic',THE_TREE_PAIRED_SAMPLE='r338',THE_TREE_EXPECTED_PATH_SHA=fixed['original_path']['sha256'],THE_TREE_EXPECTED_BUDGET_SHA=fixed['modified_budget']['sha256'])
|
||||
(stage/'project.godot').write_bytes(r.private_project(public,startup));phase=O/'engine';argv=[fixed['engine']['path'],'--headless','--path',str(stage),'--script',fixed['starter']['path'],'--verbose','--log-file',str(phase/'engine-native.log')]
|
||||
result,capture=outer.run_phase(argv,phase,90,env,now_fn=r.now,dump_fn=r.write,sha_fn=r.sha,live_engines_fn=outer.native.helper['live_engines']);r.write(O/'phase.json',dict(result=result,capture=capture))
|
||||
assert result and result['exit_code']==0 and not result['error_lines'] and not result['timed_out'] and capture['passed']
|
||||
logs=''.join((phase/n).read_text() for n in ['stdout.log','stderr.log','engine-native.log']);assert 'Orphan StringName:' not in logs and 'unclaimed string names' not in logs and (phase/'stdout.log').read_text().count('NATIVE_ADAPTER_LIBRARY_REGISTERED')==1
|
||||
report=r.read(output/'report.json');assert report['passed'] and not report['failures'] and report['pid']==result['pid'] and report['checks']==16 and report['candidate']=='r333-diagnostic' and report['sample']=='r338'
|
||||
assert (phase/'stdout.log').read_text().count('Phase diagnostic whole647: 16 checks, 0 failures')==1
|
||||
after=unpack(report['after647']['path']);oracle=unpack(fixed['oracle']['path']);assert after==oracle and len(after)==11487732 and hashlib.sha256(after).hexdigest()==report['after647']['uncompressed_sha256']
|
||||
raw=unpack(report['metrics']['path']);assert len(raw)==report['metrics']['uncompressed_bytes'] and hashlib.sha256(raw).hexdigest()==report['metrics']['uncompressed_sha256']
|
||||
r.profile_gate(r.profile_path(profile),O/'profile.json',profile);assert sum(f.stat().st_size for f in O.rglob('*') if f.is_file())<=p['measurement_cap_bytes']
|
||||
except BaseException:error=traceback.format_exc()
|
||||
finally:
|
||||
cleanup,cleanup_errors=outer.finish_captured(outer.OWNED)
|
||||
if all(q['engine_ended'] is True for q in cleanup):
|
||||
for rel,row in p['manifest'].items():(stage/rel).write_bytes(Path(row['before']['path']).read_bytes())
|
||||
budget.write_bytes(budget_before);(stage/'project.godot').write_bytes(public);patched=False
|
||||
else:cleanup_errors.append('Restoration refused while captured owned child remains live')
|
||||
try:assert not patched;protect()
|
||||
except BaseException:guard_errors.append(traceback.format_exc())
|
||||
passed=error is None and not guard_errors and not cleanup_errors
|
||||
r.write(O/'execution.json',dict(passed=passed,error=error,guard_errors=guard_errors,result=result,capture=capture,report=report,cleanup=cleanup,cleanup_errors=cleanup_errors,source_default_doc4_support_stage_preserved=not guard_errors,unit_accepted=False,performance_accepted=False,candidate_adopted=False,limits=['One instrumented current r333/library334 cold646 tick. Nested inclusive measurements overlap and include instrumentation. No CPU sums/subtraction, uninstrumented comparisons, stable gain/P95/budget/final regression/Main/x3/OS/Windows acceptance.']))
|
||||
print(json.dumps(dict(passed=passed,error=error,guard_errors=guard_errors)),flush=True);return 0 if passed else 1
|
||||
if __name__=='__main__':raise SystemExit(main())
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
# coding: utf-8
|
||||
from pathlib import Path
|
||||
import importlib.util,json,hashlib,os,uuid,shutil,subprocess,traceback,sys
|
||||
sys.dont_write_bytecode=True
|
||||
R=Path(__file__).resolve().parents[2]; A=R/'artifacts/original-completion-2026-10-02';D=R/'docs/plans/original-completion-2026-10-02';O=A/'p23-02-current-phase-diagnostic-r338-r02'
|
||||
def mod(n,p):
|
||||
s=importlib.util.spec_from_file_location(n,p);m=importlib.util.module_from_spec(s);s.loader.exec_module(m);return m
|
||||
def unpack(p):return subprocess.run(['/opt/homebrew/bin/zstd','-d','-q','-c',str(p)],check=True,capture_output=True,timeout=10).stdout
|
||||
def main():
|
||||
r=mod('r338',R/'tools/run_all_tests.py');outer=mod('o338',r.SUPPORT/'owned_outer.py');p=r.read(O/'input.json');assert not (O/'execution.json').exists()
|
||||
prepath=A/'p23-02-current-phase-diagnostic-preexecution-independent-review-r338-r02.json';pre=r.read(prepath);assert pre['execution_allowed'] and not pre['blockers']
|
||||
for group in ['evidence_sha256','canonical_doc4_context_pins']:
|
||||
for key,q in pre[group].items():
|
||||
f=Path(q.get('path',key));assert f.stat().st_size==q['bytes'] and r.sha(f)==q['sha256']
|
||||
root=r.read(O/'preexecution-root-verification.json');assert root['passed'] and root['review_sha256']==r.sha(prepath)
|
||||
stage=Path(p['stage']);public=(stage/'project.godot').read_bytes();budget=stage/'scripts/core/performance_budget.gd';budget_before=budget.read_bytes();patched=False
|
||||
fixed=p['pins'];source=r.source_refs(R);default=r.default_player(R);docs={n:r.sha(D/n) for n in p['doc4_before']};assert source==p['source_before'] and default==p['default_before'] and docs==p['doc4_before']
|
||||
def protect():
|
||||
assert r.source_refs(R)==source and r.default_player(R)==default and {n:r.sha(D/n) for n in docs}==docs and r.inventory(r.SUPPORT)==p['support_inventory']
|
||||
assert r.inventory(stage,stage=True)==(p['patched_stage'] if patched else p['expected_stage'])
|
||||
for q in fixed.values():
|
||||
f=Path(q['path']);assert f.stat().st_size==q['bytes'] and r.sha(f)==q['sha256']
|
||||
for row in p['manifest'].values():
|
||||
for key in ['before','after']:
|
||||
q=row[key];f=Path(q['path']);assert f.stat().st_size==q['bytes'] and r.sha(f)==q['sha256']
|
||||
protect();error=None;guard_errors=[];cleanup=[];cleanup_errors=[];result=None;capture=None;report=None
|
||||
try:
|
||||
assert not outer.native.helper['live_engines']() and shutil.disk_usage(A).free>=p['capacity_floor_bytes']
|
||||
for rel,row in p['manifest'].items():(stage/rel).write_bytes(Path(row['after']['path']).read_bytes())
|
||||
budget.write_bytes(Path(fixed['modified_budget']['path']).read_bytes());patched=True;protect()
|
||||
output=O/'measurement';output.mkdir();ident=uuid.uuid4().hex;startup='TheTree-PCK-tests-'+ident+'-diagnostic-startup';profile='TheTree-PCK-tests-'+ident+'-diagnostic-runtime';assert not r.profile_path(startup).exists() and not r.profile_path(profile).exists()
|
||||
env=r.fresh_environment(os.environ);env.update(THE_TREE_PACK_PROFILE_NAME=profile,THE_TREE_PACK_PROFILE_EXPECTED=str(r.profile_path(profile)),THE_TREE_PACK_PROFILE_REPORT=str(O/'profile.json'),THE_TREE_RUNTIME_MONITOR_OUTPUT=str(output),THE_TREE_REPLAY_SNAPSHOT=fixed['fixture']['path'],THE_TREE_CANDIDATE_ORACLE=fixed['oracle']['path'],THE_TREE_PAIRED_CANDIDATE='r333-diagnostic',THE_TREE_PAIRED_SAMPLE='r338',THE_TREE_EXPECTED_PATH_SHA=fixed['original_path']['sha256'],THE_TREE_EXPECTED_BUDGET_SHA=fixed['modified_budget']['sha256'])
|
||||
(stage/'project.godot').write_bytes(r.private_project(public,startup));phase=O/'engine';argv=[fixed['engine']['path'],'--headless','--path',str(stage),'--script',fixed['starter']['path'],'--verbose','--log-file',str(phase/'engine-native.log')]
|
||||
result,capture=outer.run_phase(argv,phase,90,env,now_fn=r.now,dump_fn=r.write,sha_fn=r.sha,live_engines_fn=outer.native.helper['live_engines']);r.write(O/'phase.json',dict(result=result,capture=capture))
|
||||
assert result and result['exit_code']==0 and not result['error_lines'] and not result['timed_out'] and capture['passed']
|
||||
logs=''.join((phase/n).read_text() for n in ['stdout.log','stderr.log','engine-native.log']);assert 'Orphan StringName:' not in logs and 'unclaimed string names' not in logs and (phase/'stdout.log').read_text().count('NATIVE_ADAPTER_LIBRARY_REGISTERED')==1
|
||||
report=r.read(output/'report.json');assert report['passed'] and not report['failures'] and report['pid']==result['pid'] and report['checks']==17 and report['candidate']=='r333-diagnostic' and report['sample']=='r338'
|
||||
assert (phase/'stdout.log').read_text().count('Phase diagnostic whole647: 17 checks, 0 failures')==1
|
||||
after=unpack(report['after647']['path']);oracle=unpack(fixed['oracle']['path']);assert after==oracle and len(after)==11487732 and hashlib.sha256(after).hexdigest()==report['after647']['uncompressed_sha256']
|
||||
raw=unpack(report['metrics']['path']);assert len(raw)==report['metrics']['uncompressed_bytes'] and hashlib.sha256(raw).hexdigest()==report['metrics']['uncompressed_sha256']
|
||||
r.profile_gate(r.profile_path(profile),O/'profile.json',profile);assert sum(f.stat().st_size for f in O.rglob('*') if f.is_file())<=p['measurement_cap_bytes']
|
||||
except BaseException:error=traceback.format_exc()
|
||||
finally:
|
||||
cleanup,cleanup_errors=outer.finish_captured(outer.OWNED)
|
||||
if all(q['engine_ended'] is True for q in cleanup):
|
||||
for rel,row in p['manifest'].items():(stage/rel).write_bytes(Path(row['before']['path']).read_bytes())
|
||||
budget.write_bytes(budget_before);(stage/'project.godot').write_bytes(public);patched=False
|
||||
else:cleanup_errors.append('Restoration refused while captured owned child remains live')
|
||||
try:assert not patched;protect()
|
||||
except BaseException:guard_errors.append(traceback.format_exc())
|
||||
passed=error is None and not guard_errors and not cleanup_errors
|
||||
r.write(O/'execution.json',dict(passed=passed,error=error,guard_errors=guard_errors,result=result,capture=capture,report=report,cleanup=cleanup,cleanup_errors=cleanup_errors,source_default_doc4_support_stage_preserved=not guard_errors,unit_accepted=False,performance_accepted=False,candidate_adopted=False,limits=['One instrumented current r333/library334 cold646 tick. Nested inclusive measurements overlap and include instrumentation. No CPU sums/subtraction, uninstrumented comparisons, stable gain/P95/budget/final regression/Main/x3/OS/Windows acceptance.']))
|
||||
print(json.dumps(dict(passed=passed,error=error,guard_errors=guard_errors)),flush=True);return 0 if passed else 1
|
||||
if __name__=='__main__':raise SystemExit(main())
|
||||
+336
@@ -0,0 +1,336 @@
|
||||
{
|
||||
"plan_id": "P23-02",
|
||||
"review_kind": "bounded_read_only_preexecution",
|
||||
"revision": "r338",
|
||||
"execution_allowed": false,
|
||||
"blockers": [
|
||||
{
|
||||
"id": "EXPECTED_CHECK_COUNT_MISMATCH",
|
||||
"location": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338.py",
|
||||
"reason": "Final diagnostic run has 14 ordinary checks, typed(after647) and typed(metrics) each contribute one exclusive-file check, and guarded registration contributes one check: 17 total. Driver requires report.checks == 16 and a 16-check stdout summary, so a fully successful run would be rejected after the engine ends.",
|
||||
"required_repair": "Preserve unexecuted r338 and prepare a version with both expected report and stdout counts set to 17; keep QA assertions and validation criteria unchanged."
|
||||
}
|
||||
],
|
||||
"independent_check_count": {
|
||||
"ordinary_qa": 14,
|
||||
"typed_exclusive": 2,
|
||||
"guarded_registration": 1,
|
||||
"total": 17,
|
||||
"driver_expected": 16
|
||||
},
|
||||
"bounded_static_findings": {
|
||||
"seven_file_inverse": [
|
||||
{
|
||||
"path": "autoload/simulation_runtime.gd",
|
||||
"original_body_inverse_exact": true,
|
||||
"wrapper_count": 14
|
||||
},
|
||||
{
|
||||
"path": "scripts/inventory/inventory_service.gd",
|
||||
"original_body_inverse_exact": true,
|
||||
"wrapper_count": 4
|
||||
},
|
||||
{
|
||||
"path": "scripts/facility/facility_service.gd",
|
||||
"original_body_inverse_exact": true,
|
||||
"wrapper_count": 4
|
||||
},
|
||||
{
|
||||
"path": "scripts/supply/supply_management_service.gd",
|
||||
"original_body_inverse_exact": true,
|
||||
"wrapper_count": 4
|
||||
},
|
||||
{
|
||||
"path": "scripts/supply/supply_logistics_bridge.gd",
|
||||
"original_body_inverse_exact": true,
|
||||
"wrapper_count": 1
|
||||
},
|
||||
{
|
||||
"path": "scripts/supply/kitchen_production_service.gd",
|
||||
"original_body_inverse_exact": true,
|
||||
"wrapper_count": 1
|
||||
},
|
||||
{
|
||||
"path": "scripts/core/simulation_kernel.gd",
|
||||
"original_body_inverse_exact": true,
|
||||
"wrapper_count": 1
|
||||
}
|
||||
],
|
||||
"original_stage_files": 1299,
|
||||
"patched_virtual_inventory_exact": true,
|
||||
"wrapper_methods": 29,
|
||||
"declared_metric_rows": 39,
|
||||
"kernel_phase_rows": 11,
|
||||
"missing_methods": [],
|
||||
"original_parameter_defaults_return_types_and_function_bodies_preserved": true,
|
||||
"timing_snapshot_freeze_before_after647_snapshot": true,
|
||||
"qa_loaded_Path_and_Budget_source_guards": true,
|
||||
"same_exact_r333_library334_and_config": true,
|
||||
"current_source_default_support_stage_and_doc4_authenticated": true,
|
||||
"no_foreign_engine_and_floor_gate_before_stage_write": true,
|
||||
"owned_capture_end_required_before_all_seven_files_Budget_project_restoration": true,
|
||||
"strict_three_logs_orphan_guard_unique_stdout_registration_profile5": true,
|
||||
"original_646_and_full647_oracle_required": true,
|
||||
"engine_limit_seconds": 90,
|
||||
"capacity_floor_bytes": 553648128,
|
||||
"measurement_cap_bytes": 16777216,
|
||||
"fresh_free_bytes": 909316096,
|
||||
"output_cap_scope": "post-phase total recorded bytes, not a live peak cap"
|
||||
},
|
||||
"limitations": [
|
||||
"Static inspection only; no engine, compiler, tests, validator, author, or decoder execution was performed.",
|
||||
"Remaining GDScript parsing, actual declared counters and full-save preservation require the separately authorized single owned diagnostic run after count repair.",
|
||||
"Metric values are nested inclusive wall-time observations with added clock/dictionary instrumentation; no sum, subtraction, pure CPU, causal attribution, uninstrumented comparison, stable performance, P95/D10 or 50ms acceptance.",
|
||||
"No final172, normal OS, Windows, selected/adopted candidate, unit acceptance or original17 completion is granted.",
|
||||
"No additional blocker was found in the bounded inverse/input/driver-protection pass."
|
||||
],
|
||||
"evidence_sha256": {
|
||||
"/Applications/Godot.app/Contents/MacOS/Godot": {
|
||||
"path": "/Applications/Godot.app/Contents/MacOS/Godot",
|
||||
"bytes": 351312912,
|
||||
"sha256": "c7cccbf8fb143e34e02fd6521e09be2c2b974f0d5db080b19071c9c570718ccf"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-walk-edges-candidate-r265-r03/performance_budget.candidate.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-walk-edges-candidate-r265-r03/performance_budget.candidate.gd",
|
||||
"bytes": 11250,
|
||||
"sha256": "1010129d3124c3aec037c840a5766a7cdabe60c654999dfb6f23b224140a73f8"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-local-names-candidate-r239/stage/scripts/world/path_service.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-local-names-candidate-r239/stage/scripts/world/path_service.gd",
|
||||
"bytes": 132925,
|
||||
"sha256": "6b7f4e989ea9b09495f814d8ecb294028d10794005966414bf52640e122b0d17"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-single-actor-path-native-r03/diagnostic-measurement/checkpoint646.varbytes.zst": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-single-actor-path-native-r03/diagnostic-measurement/checkpoint646.varbytes.zst",
|
||||
"bytes": 240032,
|
||||
"sha256": "1a88f7ed27d1d32102c6fe3a9533221d2565191712ed15b631190479d1d41505"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-report-window-trusted-report-whole647-native-r02/diagnostic-measurement/after647.varbytes.zst": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-report-window-trusted-report-whole647-native-r02/diagnostic-measurement/after647.varbytes.zst",
|
||||
"bytes": 246720,
|
||||
"sha256": "684ba40e9f649b7dd4bfc620185d7cd18bae3111c3b4038e48aaad5a9168d880"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd",
|
||||
"bytes": 1441,
|
||||
"sha256": "3dd8e4f3590fd5b274811c5fffdd49e12e69803b5385c409f786245b9fed1b62"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/diagnostic.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/diagnostic.gd",
|
||||
"bytes": 6807,
|
||||
"sha256": "f076e93357b521c0add060a262a725637daf9fa39c9bdb8ccb156f20bfcba9a1"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-input-copy-local-r335/candidate.gdextension": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-input-copy-local-r335/candidate.gdextension",
|
||||
"bytes": 214,
|
||||
"sha256": "a51d6bbbef6a00b82ded03a0d637c057b6b70d13025d4c3042f2984d0cb7152a"
|
||||
},
|
||||
"/private/tmp/TheTree-input-copy-r335-3afabc8ef9ee42d0be34994471a451b5/candidate.dylib": {
|
||||
"path": "/private/tmp/TheTree-input-copy-r335-3afabc8ef9ee42d0be34994471a451b5/candidate.dylib",
|
||||
"bytes": 433744,
|
||||
"sha256": "39f8ed73f077d15037d85b9cb53f38389c032a36dea7ff04348e5ef05c736907"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/autoload/simulation_runtime.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/autoload/simulation_runtime.gd",
|
||||
"bytes": 612068,
|
||||
"sha256": "7eb24adbf91fe53cde14954dda12abd5efb05130de7d356d8df281ee99065e86"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/autoload/simulation_runtime.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/autoload/simulation_runtime.gd",
|
||||
"bytes": 621773,
|
||||
"sha256": "ce260f1158adfb8d9adda1ea00fa29b3c76bc4968c9f7996fdcf62193e28b540"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/autoload/simulation_runtime.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/autoload/simulation_runtime.gd",
|
||||
"bytes": 612068,
|
||||
"sha256": "7eb24adbf91fe53cde14954dda12abd5efb05130de7d356d8df281ee99065e86"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/inventory/inventory_service.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/inventory/inventory_service.gd",
|
||||
"bytes": 57923,
|
||||
"sha256": "7ee83b335864385119ca757037c3cdb912957aa4478a6312a0898a734e41f31a"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/inventory/inventory_service.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/inventory/inventory_service.gd",
|
||||
"bytes": 60808,
|
||||
"sha256": "a93e7486fab66938ce7356b16202dddf0d4dd2f9c30e6b9312ec4ee98878480e"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/inventory/inventory_service.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/inventory/inventory_service.gd",
|
||||
"bytes": 57923,
|
||||
"sha256": "7ee83b335864385119ca757037c3cdb912957aa4478a6312a0898a734e41f31a"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/facility/facility_service.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/facility/facility_service.gd",
|
||||
"bytes": 44951,
|
||||
"sha256": "ceb4a3e9224587423f273cdb2b56e6843ab176ac1fc4fe79dd498b5ed5c33b77"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/facility/facility_service.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/facility/facility_service.gd",
|
||||
"bytes": 47788,
|
||||
"sha256": "c24d9b475c66046dc7342401a74fdc084ca6698506fdb9284afbadd6c5e68cfa"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/facility/facility_service.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/facility/facility_service.gd",
|
||||
"bytes": 44951,
|
||||
"sha256": "ceb4a3e9224587423f273cdb2b56e6843ab176ac1fc4fe79dd498b5ed5c33b77"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/supply/supply_management_service.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/supply/supply_management_service.gd",
|
||||
"bytes": 25019,
|
||||
"sha256": "e4ad420191020485c027004f64bb00fad9da195fe956ef10dc0c787412018f7f"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/supply/supply_management_service.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/supply/supply_management_service.gd",
|
||||
"bytes": 27952,
|
||||
"sha256": "87f2a3c36ef8b4569d17191f0c376fc957462dd7fe33a832c7284fdceb4a5b3c"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/supply/supply_management_service.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/supply/supply_management_service.gd",
|
||||
"bytes": 25019,
|
||||
"sha256": "e4ad420191020485c027004f64bb00fad9da195fe956ef10dc0c787412018f7f"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/supply/supply_logistics_bridge.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/supply/supply_logistics_bridge.gd",
|
||||
"bytes": 28100,
|
||||
"sha256": "b9e394af788595d2744b71f1907c8e7c3d762d38ff49992b1ee74e63b9639e80"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/supply/supply_logistics_bridge.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/supply/supply_logistics_bridge.gd",
|
||||
"bytes": 28814,
|
||||
"sha256": "6887a702c1eb6f9e91f689fd734f9bbc386a9cce55a68b1682c3a18be620976a"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/supply/supply_logistics_bridge.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/supply/supply_logistics_bridge.gd",
|
||||
"bytes": 28100,
|
||||
"sha256": "b9e394af788595d2744b71f1907c8e7c3d762d38ff49992b1ee74e63b9639e80"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/supply/kitchen_production_service.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/supply/kitchen_production_service.gd",
|
||||
"bytes": 18872,
|
||||
"sha256": "f3bc6bdc1a0ba278e9411108172ceceb7eb06520b4e33f93f35684da1f103c62"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/supply/kitchen_production_service.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/supply/kitchen_production_service.gd",
|
||||
"bytes": 19610,
|
||||
"sha256": "b751511484258edb471567639f150d8dcfb69ff4245a2273718cfcb3de04ca51"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/supply/kitchen_production_service.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/supply/kitchen_production_service.gd",
|
||||
"bytes": 18872,
|
||||
"sha256": "f3bc6bdc1a0ba278e9411108172ceceb7eb06520b4e33f93f35684da1f103c62"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/core/simulation_kernel.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/core/simulation_kernel.gd",
|
||||
"bytes": 7602,
|
||||
"sha256": "341c0c878c4894adbac628d0db6362ff69fc3347bdd9e61e50936e15dc2d1edb"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/core/simulation_kernel.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/core/simulation_kernel.gd",
|
||||
"bytes": 8264,
|
||||
"sha256": "9c67f2b22a38ab396e9d84522b3d54edb7be85878eb6a745deecb9ca2bde8692"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/core/simulation_kernel.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/core/simulation_kernel.gd",
|
||||
"bytes": 7602,
|
||||
"sha256": "341c0c878c4894adbac628d0db6362ff69fc3347bdd9e61e50936e15dc2d1edb"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/input.json": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/input.json",
|
||||
"bytes": 1023880,
|
||||
"sha256": "43f57b58c7533dae7965b71a739dd256219e264b1f2b3bb8639c8bf1a625696e"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338.py": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338.py",
|
||||
"bytes": 6430,
|
||||
"sha256": "df468edfdc85ec9f445206ad005254d0472d1f8cc2f2c3fbea41db05dbd53b9a"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/tools/run_all_tests.py": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/tools/run_all_tests.py",
|
||||
"bytes": 26296,
|
||||
"sha256": "320ca668732b4ff72fc4449998af2327d4e5c527b06896740806aaf0487282b4"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/tools/regression/owned_outer.py": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/tools/regression/owned_outer.py",
|
||||
"bytes": 4177,
|
||||
"sha256": "c2e3483b76db1a3ff940f23f88ea0083fc78736e874ebcdb385d766dde8866e7"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-build-preview-monitor-compressed-r06.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-build-preview-monitor-compressed-r06.gd",
|
||||
"bytes": 17582,
|
||||
"sha256": "92d5e1956f4e613e12555d756de4f71fef03678cde159ac68fac3188ce3f336e"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-cache-public-mutations-r144/profile_guard.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-cache-public-mutations-r144/profile_guard.gd",
|
||||
"bytes": 2276,
|
||||
"sha256": "597696c705cc8f0e79a35265ca3ef8df55f7fc3c4e0e5a2ce9a4e20e29e29a6f"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/core/performance_budget.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/core/performance_budget.gd",
|
||||
"bytes": 10355,
|
||||
"sha256": "742c464d16ab417cbc3c2930d43e508faf5c9f7688da416324ca1150bdb9b6b9"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/project.godot": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/project.godot",
|
||||
"bytes": 1294,
|
||||
"sha256": "686f3da7f6b592cd95d84e71a83374a28173914b377eafa4a6e005d70062d00d"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-input-copy-build-actual-independent-review-r334.json": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-input-copy-build-actual-independent-review-r334.json",
|
||||
"bytes": 40719,
|
||||
"sha256": "991e093110a35df5742e4b6bbd9254d664f20c280056fa6dd19e35be0bdcd871"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-input-copy-whole-actual-independent-review-r336.json": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-input-copy-whole-actual-independent-review-r336.json",
|
||||
"bytes": 40888,
|
||||
"sha256": "671fedcbd0d48a42809aa6ca19d91c5ed4d22f4e6201ad1a00b3d3be18f291b8"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/input-before-phase-mapping-correction.json": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/input-before-phase-mapping-correction.json",
|
||||
"bytes": 1017508,
|
||||
"sha256": "fe9c06fd72ccd6bb88557082b5015bd8ad8386eee44371fdb4bd9dc8beb658db"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/input-before-transaction-method-correction.json": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/input-before-transaction-method-correction.json",
|
||||
"bytes": 1011383,
|
||||
"sha256": "ca1c57a6c3266df161f8832842bc61c1305ecd2ecd77b7527533dcb44123f639"
|
||||
},
|
||||
"/private/tmp/thetree-prepare-residual-r338.py": {
|
||||
"path": "/private/tmp/thetree-prepare-residual-r338.py",
|
||||
"bytes": 9527,
|
||||
"sha256": "ff0e7c5fcb572b900585b334890612e19894f347ea57a6e1541935c7df6f3468"
|
||||
}
|
||||
},
|
||||
"canonical_doc4_context_pins": {
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/IMPLEMENTATION_PLAN.md": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/IMPLEMENTATION_PLAN.md",
|
||||
"bytes": 492489,
|
||||
"sha256": "4e9748ca579001e5673f83568d64bbe45b6bad7420ee6481901496f0fd7e9f28"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/PROGRESS_INTEGRATION.md": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/PROGRESS_INTEGRATION.md",
|
||||
"bytes": 410553,
|
||||
"sha256": "b5617405aaa913cef5f5e23bbc5141bfb746de88926116c02ea2d33bd5ea7a22"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/work_packages.json": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/work_packages.json",
|
||||
"bytes": 1188101,
|
||||
"sha256": "e7e8d40e9a9a85095d6e4ad96ab305fa1bf83f10f754b3c541e27cb78b1f6f67"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/progress_snapshot.json": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/progress_snapshot.json",
|
||||
"bytes": 591756,
|
||||
"sha256": "db411f761cc2e64d9ae7859ebdc085bfacc1b649dd4c7241c34a96fd28e07b97"
|
||||
}
|
||||
},
|
||||
"pin_group_counts": {
|
||||
"evidence_sha256": 43,
|
||||
"canonical_doc4_context_pins": 4,
|
||||
"total": 47
|
||||
},
|
||||
"engine_runs": 0,
|
||||
"compiler_runs": 0,
|
||||
"test_runs": 0,
|
||||
"validator_runs": 0,
|
||||
"existing_file_edits": 0
|
||||
}
|
||||
+311
@@ -0,0 +1,311 @@
|
||||
{
|
||||
"plan_id": "P23-02",
|
||||
"revision": "r338-r02",
|
||||
"review_kind": "bounded_count_only_repair_preexecution",
|
||||
"execution_allowed": true,
|
||||
"blockers": [],
|
||||
"expected_qa_checks": 17,
|
||||
"count_basis": {
|
||||
"ordinary_qa": 14,
|
||||
"typed_exclusive": 2,
|
||||
"guarded_registration": 1,
|
||||
"total": 17
|
||||
},
|
||||
"repair_verification": {
|
||||
"input_original_fields_all_exact": true,
|
||||
"driver_full_reverse_exact": true,
|
||||
"driver_semantic_changes": "O directory and consumed pre-review path are fresh r338-r02; report and stdout conditions16->17 only. Sample and wrappers retain r338 identifiers.",
|
||||
"qa_starter_29_wrappers_39_rows_and_all_inputs_unchanged": true,
|
||||
"original_r338_rejected_unexecuted_retained": true,
|
||||
"prior_bounded_inverse_and_protection_findings_reused": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-preexecution-independent-review-r338.json",
|
||||
"current_stage_1299_source_default_support_doc4_match": true
|
||||
},
|
||||
"execution_scope": {
|
||||
"owned_fresh_engines": 1,
|
||||
"deadline_seconds": 90,
|
||||
"capacity_floor_bytes": 553648128,
|
||||
"fresh_free_bytes": 906731520,
|
||||
"execution_time_floor_and_no_foreign_check_required": true,
|
||||
"measurement_cap_bytes": 16777216,
|
||||
"cap_scope": "post-phase recorded total, not live peak",
|
||||
"compiler_runs": 0,
|
||||
"clones": 0,
|
||||
"full_regression": 0,
|
||||
"candidate": "r333/library334",
|
||||
"whole_after647_original_oracle_bytes": 11487732,
|
||||
"restoration": "all seven original script files, Budget and project only after all captured owned engines ended"
|
||||
},
|
||||
"limitations": [
|
||||
"Static inspection only; no engine, compiler, tests, validator, author, or decoder execution was performed.",
|
||||
"Remaining GDScript parsing, actual declared counters and full-save preservation require the separately authorized single owned diagnostic run after count repair.",
|
||||
"Metric values are nested inclusive wall-time observations with added clock/dictionary instrumentation; no sum, subtraction, pure CPU, causal attribution, uninstrumented comparison, stable performance, P95/D10 or 50ms acceptance.",
|
||||
"No final172, normal OS, Windows, selected/adopted candidate, unit acceptance or original17 completion is granted.",
|
||||
"This separate repaired gate authorizes only the bounded diagnostic attempt; actual engine parsing, metrics, full-save oracle and cleanup still require an actual independent review."
|
||||
],
|
||||
"unit_accepted": false,
|
||||
"performance_accepted": false,
|
||||
"candidate_adopted": false,
|
||||
"reviewer_engine_runs": 0,
|
||||
"reviewer_compiler_runs": 0,
|
||||
"reviewer_tests_validator_author_runs": 0,
|
||||
"existing_file_edits": 0,
|
||||
"evidence_sha256": {
|
||||
"/Applications/Godot.app/Contents/MacOS/Godot": {
|
||||
"path": "/Applications/Godot.app/Contents/MacOS/Godot",
|
||||
"bytes": 351312912,
|
||||
"sha256": "c7cccbf8fb143e34e02fd6521e09be2c2b974f0d5db080b19071c9c570718ccf"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-walk-edges-candidate-r265-r03/performance_budget.candidate.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-walk-edges-candidate-r265-r03/performance_budget.candidate.gd",
|
||||
"bytes": 11250,
|
||||
"sha256": "1010129d3124c3aec037c840a5766a7cdabe60c654999dfb6f23b224140a73f8"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-local-names-candidate-r239/stage/scripts/world/path_service.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-local-names-candidate-r239/stage/scripts/world/path_service.gd",
|
||||
"bytes": 132925,
|
||||
"sha256": "6b7f4e989ea9b09495f814d8ecb294028d10794005966414bf52640e122b0d17"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-single-actor-path-native-r03/diagnostic-measurement/checkpoint646.varbytes.zst": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-single-actor-path-native-r03/diagnostic-measurement/checkpoint646.varbytes.zst",
|
||||
"bytes": 240032,
|
||||
"sha256": "1a88f7ed27d1d32102c6fe3a9533221d2565191712ed15b631190479d1d41505"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-report-window-trusted-report-whole647-native-r02/diagnostic-measurement/after647.varbytes.zst": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-report-window-trusted-report-whole647-native-r02/diagnostic-measurement/after647.varbytes.zst",
|
||||
"bytes": 246720,
|
||||
"sha256": "684ba40e9f649b7dd4bfc620185d7cd18bae3111c3b4038e48aaad5a9168d880"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd",
|
||||
"bytes": 1441,
|
||||
"sha256": "3dd8e4f3590fd5b274811c5fffdd49e12e69803b5385c409f786245b9fed1b62"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/diagnostic.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/diagnostic.gd",
|
||||
"bytes": 6807,
|
||||
"sha256": "f076e93357b521c0add060a262a725637daf9fa39c9bdb8ccb156f20bfcba9a1"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-input-copy-local-r335/candidate.gdextension": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-input-copy-local-r335/candidate.gdextension",
|
||||
"bytes": 214,
|
||||
"sha256": "a51d6bbbef6a00b82ded03a0d637c057b6b70d13025d4c3042f2984d0cb7152a"
|
||||
},
|
||||
"/private/tmp/TheTree-input-copy-r335-3afabc8ef9ee42d0be34994471a451b5/candidate.dylib": {
|
||||
"path": "/private/tmp/TheTree-input-copy-r335-3afabc8ef9ee42d0be34994471a451b5/candidate.dylib",
|
||||
"bytes": 433744,
|
||||
"sha256": "39f8ed73f077d15037d85b9cb53f38389c032a36dea7ff04348e5ef05c736907"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/autoload/simulation_runtime.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/autoload/simulation_runtime.gd",
|
||||
"bytes": 612068,
|
||||
"sha256": "7eb24adbf91fe53cde14954dda12abd5efb05130de7d356d8df281ee99065e86"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/autoload/simulation_runtime.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/autoload/simulation_runtime.gd",
|
||||
"bytes": 621773,
|
||||
"sha256": "ce260f1158adfb8d9adda1ea00fa29b3c76bc4968c9f7996fdcf62193e28b540"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/autoload/simulation_runtime.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/autoload/simulation_runtime.gd",
|
||||
"bytes": 612068,
|
||||
"sha256": "7eb24adbf91fe53cde14954dda12abd5efb05130de7d356d8df281ee99065e86"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/inventory/inventory_service.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/inventory/inventory_service.gd",
|
||||
"bytes": 57923,
|
||||
"sha256": "7ee83b335864385119ca757037c3cdb912957aa4478a6312a0898a734e41f31a"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/inventory/inventory_service.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/inventory/inventory_service.gd",
|
||||
"bytes": 60808,
|
||||
"sha256": "a93e7486fab66938ce7356b16202dddf0d4dd2f9c30e6b9312ec4ee98878480e"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/inventory/inventory_service.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/inventory/inventory_service.gd",
|
||||
"bytes": 57923,
|
||||
"sha256": "7ee83b335864385119ca757037c3cdb912957aa4478a6312a0898a734e41f31a"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/facility/facility_service.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/facility/facility_service.gd",
|
||||
"bytes": 44951,
|
||||
"sha256": "ceb4a3e9224587423f273cdb2b56e6843ab176ac1fc4fe79dd498b5ed5c33b77"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/facility/facility_service.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/facility/facility_service.gd",
|
||||
"bytes": 47788,
|
||||
"sha256": "c24d9b475c66046dc7342401a74fdc084ca6698506fdb9284afbadd6c5e68cfa"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/facility/facility_service.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/facility/facility_service.gd",
|
||||
"bytes": 44951,
|
||||
"sha256": "ceb4a3e9224587423f273cdb2b56e6843ab176ac1fc4fe79dd498b5ed5c33b77"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/supply/supply_management_service.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/supply/supply_management_service.gd",
|
||||
"bytes": 25019,
|
||||
"sha256": "e4ad420191020485c027004f64bb00fad9da195fe956ef10dc0c787412018f7f"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/supply/supply_management_service.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/supply/supply_management_service.gd",
|
||||
"bytes": 27952,
|
||||
"sha256": "87f2a3c36ef8b4569d17191f0c376fc957462dd7fe33a832c7284fdceb4a5b3c"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/supply/supply_management_service.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/supply/supply_management_service.gd",
|
||||
"bytes": 25019,
|
||||
"sha256": "e4ad420191020485c027004f64bb00fad9da195fe956ef10dc0c787412018f7f"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/supply/supply_logistics_bridge.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/supply/supply_logistics_bridge.gd",
|
||||
"bytes": 28100,
|
||||
"sha256": "b9e394af788595d2744b71f1907c8e7c3d762d38ff49992b1ee74e63b9639e80"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/supply/supply_logistics_bridge.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/supply/supply_logistics_bridge.gd",
|
||||
"bytes": 28814,
|
||||
"sha256": "6887a702c1eb6f9e91f689fd734f9bbc386a9cce55a68b1682c3a18be620976a"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/supply/supply_logistics_bridge.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/supply/supply_logistics_bridge.gd",
|
||||
"bytes": 28100,
|
||||
"sha256": "b9e394af788595d2744b71f1907c8e7c3d762d38ff49992b1ee74e63b9639e80"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/supply/kitchen_production_service.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/supply/kitchen_production_service.gd",
|
||||
"bytes": 18872,
|
||||
"sha256": "f3bc6bdc1a0ba278e9411108172ceceb7eb06520b4e33f93f35684da1f103c62"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/supply/kitchen_production_service.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/supply/kitchen_production_service.gd",
|
||||
"bytes": 19610,
|
||||
"sha256": "b751511484258edb471567639f150d8dcfb69ff4245a2273718cfcb3de04ca51"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/supply/kitchen_production_service.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/supply/kitchen_production_service.gd",
|
||||
"bytes": 18872,
|
||||
"sha256": "f3bc6bdc1a0ba278e9411108172ceceb7eb06520b4e33f93f35684da1f103c62"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/core/simulation_kernel.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/core/simulation_kernel.gd",
|
||||
"bytes": 7602,
|
||||
"sha256": "341c0c878c4894adbac628d0db6362ff69fc3347bdd9e61e50936e15dc2d1edb"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/core/simulation_kernel.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/core/simulation_kernel.gd",
|
||||
"bytes": 8264,
|
||||
"sha256": "9c67f2b22a38ab396e9d84522b3d54edb7be85878eb6a745deecb9ca2bde8692"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/core/simulation_kernel.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/core/simulation_kernel.gd",
|
||||
"bytes": 7602,
|
||||
"sha256": "341c0c878c4894adbac628d0db6362ff69fc3347bdd9e61e50936e15dc2d1edb"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/input.json": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/input.json",
|
||||
"bytes": 1023880,
|
||||
"sha256": "43f57b58c7533dae7965b71a739dd256219e264b1f2b3bb8639c8bf1a625696e"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338.py": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338.py",
|
||||
"bytes": 6430,
|
||||
"sha256": "df468edfdc85ec9f445206ad005254d0472d1f8cc2f2c3fbea41db05dbd53b9a"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/tools/run_all_tests.py": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/tools/run_all_tests.py",
|
||||
"bytes": 26296,
|
||||
"sha256": "320ca668732b4ff72fc4449998af2327d4e5c527b06896740806aaf0487282b4"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/tools/regression/owned_outer.py": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/tools/regression/owned_outer.py",
|
||||
"bytes": 4177,
|
||||
"sha256": "c2e3483b76db1a3ff940f23f88ea0083fc78736e874ebcdb385d766dde8866e7"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-build-preview-monitor-compressed-r06.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-build-preview-monitor-compressed-r06.gd",
|
||||
"bytes": 17582,
|
||||
"sha256": "92d5e1956f4e613e12555d756de4f71fef03678cde159ac68fac3188ce3f336e"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-cache-public-mutations-r144/profile_guard.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-cache-public-mutations-r144/profile_guard.gd",
|
||||
"bytes": 2276,
|
||||
"sha256": "597696c705cc8f0e79a35265ca3ef8df55f7fc3c4e0e5a2ce9a4e20e29e29a6f"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/core/performance_budget.gd": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/scripts/core/performance_budget.gd",
|
||||
"bytes": 10355,
|
||||
"sha256": "742c464d16ab417cbc3c2930d43e508faf5c9f7688da416324ca1150bdb9b6b9"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/project.godot": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-guest-bulk-local-r315/stage/project.godot",
|
||||
"bytes": 1294,
|
||||
"sha256": "686f3da7f6b592cd95d84e71a83374a28173914b377eafa4a6e005d70062d00d"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-input-copy-build-actual-independent-review-r334.json": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-input-copy-build-actual-independent-review-r334.json",
|
||||
"bytes": 40719,
|
||||
"sha256": "991e093110a35df5742e4b6bbd9254d664f20c280056fa6dd19e35be0bdcd871"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-input-copy-whole-actual-independent-review-r336.json": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-input-copy-whole-actual-independent-review-r336.json",
|
||||
"bytes": 40888,
|
||||
"sha256": "671fedcbd0d48a42809aa6ca19d91c5ed4d22f4e6201ad1a00b3d3be18f291b8"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/input-before-phase-mapping-correction.json": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/input-before-phase-mapping-correction.json",
|
||||
"bytes": 1017508,
|
||||
"sha256": "fe9c06fd72ccd6bb88557082b5015bd8ad8386eee44371fdb4bd9dc8beb658db"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/input-before-transaction-method-correction.json": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/input-before-transaction-method-correction.json",
|
||||
"bytes": 1011383,
|
||||
"sha256": "ca1c57a6c3266df161f8832842bc61c1305ecd2ecd77b7527533dcb44123f639"
|
||||
},
|
||||
"/private/tmp/thetree-prepare-residual-r338.py": {
|
||||
"path": "/private/tmp/thetree-prepare-residual-r338.py",
|
||||
"bytes": 9527,
|
||||
"sha256": "ff0e7c5fcb572b900585b334890612e19894f347ea57a6e1541935c7df6f3468"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-preexecution-independent-review-r338.json": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-preexecution-independent-review-r338.json",
|
||||
"bytes": 26442,
|
||||
"sha256": "25d15928c713cb1608490bae5ea10d6374b21a764c87ae19ba2ce32a2d20ba39"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02.py": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02.py",
|
||||
"bytes": 6438,
|
||||
"sha256": "97e994c336ae44f78581e0885321b572d002635c39e36ae62aa1e84feb6fd011"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/input.json": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/input.json",
|
||||
"bytes": 1024228,
|
||||
"sha256": "95f7929f2a8d78593d18285d2c1581ef7a303dae6fae331c8312e15b700b5d91"
|
||||
}
|
||||
},
|
||||
"canonical_doc4_context_pins": {
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/IMPLEMENTATION_PLAN.md": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/IMPLEMENTATION_PLAN.md",
|
||||
"bytes": 492489,
|
||||
"sha256": "4e9748ca579001e5673f83568d64bbe45b6bad7420ee6481901496f0fd7e9f28"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/PROGRESS_INTEGRATION.md": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/PROGRESS_INTEGRATION.md",
|
||||
"bytes": 410553,
|
||||
"sha256": "b5617405aaa913cef5f5e23bbc5141bfb746de88926116c02ea2d33bd5ea7a22"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/work_packages.json": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/work_packages.json",
|
||||
"bytes": 1188101,
|
||||
"sha256": "e7e8d40e9a9a85095d6e4ad96ab305fa1bf83f10f754b3c541e27cb78b1f6f67"
|
||||
},
|
||||
"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/progress_snapshot.json": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/progress_snapshot.json",
|
||||
"bytes": 591756,
|
||||
"sha256": "db411f761cc2e64d9ae7859ebdc085bfacc1b649dd4c7241c34a96fd28e07b97"
|
||||
}
|
||||
},
|
||||
"pin_group_counts": {
|
||||
"evidence_sha256": 46,
|
||||
"canonical_doc4_context_pins": 4,
|
||||
"total": 50
|
||||
}
|
||||
}
|
||||
BIN
Binary file not shown.
+75
@@ -0,0 +1,75 @@
|
||||
# coding: utf-8
|
||||
from pathlib import Path
|
||||
import importlib.util,json,hashlib,re,shutil
|
||||
R=Path('/Users/korizatou114/Projects/とりにく工房ゲーム制作部'); A=R/'artifacts/original-completion-2026-10-02'; D=R/'docs/plans/original-completion-2026-10-02'; O=A/'p23-02-current-phase-diagnostic-r338'; stage=A/'p23-02-native-guest-bulk-local-r315/stage'
|
||||
s=importlib.util.spec_from_file_location('r',R/'tools/run_all_tests.py');r=importlib.util.module_from_spec(s);s.loader.exec_module(r)
|
||||
O.mkdir(exist_ok=True);(O/'originals').mkdir(exist_ok=True);(O/'instrumented').mkdir(exist_ok=True)
|
||||
def pin(p):return dict(path=str(p),bytes=p.stat().st_size,sha256=r.sha(p))
|
||||
groups={
|
||||
'runtime':('autoload/simulation_runtime.gd','runtime',['_advance_construction','_preflight_proxy_completions','_validate_infrastructure_crosslinks','_advance_inventory_and_logistics','_advance_facilities','_advance_staff_ai','_advance_guest_ai_decisions','_project_guest_candidates','_decide_guest_with_log','_publish_snapshot','_execute_create_logistics_request','_validate_service_start','_complete_service_transaction','_apply_service_transaction']),
|
||||
'inventory':('scripts/inventory/inventory_service.gd','runtime.inventory_service',['process_expired','create_snapshot','_find_stack','reserve_item']),
|
||||
'facility':('scripts/facility/facility_service.gd','runtime.facility_service',['advance_one_minute','refresh_operating_dependencies','start_next_service','_complete_service']),
|
||||
'supply':('scripts/supply/supply_management_service.gd','runtime.supply_management',['advance_auto_purchases','ensure_deliveries','_connection_distance','_purchase_paid']),
|
||||
'logistics':('scripts/supply/supply_logistics_bridge.gd','runtime.supply_logistics',['tick']),
|
||||
'kitchen':('scripts/supply/kitchen_production_service.gd','runtime.kitchen_production',['advance_one_minute']),
|
||||
'kernel_phases':('scripts/core/simulation_kernel.gd','clock',['_run_phase'])}
|
||||
# Filter unavailable guessed transaction names, retaining explicit omission record.
|
||||
missing=[];manifest={};declared={};targets={}
|
||||
for group,(rel,target,names) in groups.items():
|
||||
original=(stage/rel).read_text();text=original;wrappers=[];declared[group]=[];targets[group]=target
|
||||
for name in names:
|
||||
m=re.search(r'^func '+re.escape(name)+r'\((.*?)\)(?:\s*->\s*([^:]+))?:\n',original,re.M|re.S)
|
||||
if not m:missing.append(group+'.'+name);continue
|
||||
sig=m.group(0);params=m.group(1);typ=(m.group(2) or 'Variant').strip()
|
||||
# Each selected signature has only commas between parameters; default expressions checked here.
|
||||
args=[]
|
||||
for p in params.split(','):
|
||||
p=p.strip()
|
||||
if p:args.append(p.split(':')[0].split('=')[0].strip())
|
||||
assert all(re.fullmatch(r'[a-zA-Z_][a-zA-Z_0-9]*',a) for a in args),(name,args)
|
||||
renamed='_p23r338_original'+name;new=sig.replace('func '+name+'(','func '+renamed+'(',1);assert text.count(sig)==1;text=text.replace(sig,new,1)
|
||||
call=renamed+'('+', '.join(args)+')';key='str(phase)' if group=='kernel_phases' else json.dumps(name)
|
||||
body=sig+'\tvar p23_started := Time.get_ticks_usec()\n'
|
||||
body+=('\t'+call+'\n') if typ=='void' else ('\tvar p23_result: '+typ+' = '+call+'\n')
|
||||
body+='\tvar p23_elapsed := Time.get_ticks_usec() - p23_started\n\tvar p23_key: String = '+key+'\n\tvar p23_row: Dictionary = _p23r338_metrics.get(p23_key, {"calls":0,"inclusive_us":0,"max_us":0})\n\tp23_row["calls"] = int(p23_row["calls"]) + 1\n\tp23_row["inclusive_us"] = int(p23_row["inclusive_us"]) + p23_elapsed\n\tp23_row["max_us"] = maxi(int(p23_row["max_us"]),p23_elapsed)\n\t_p23r338_metrics[p23_key] = p23_row\n'
|
||||
if typ!='void':body+='\treturn p23_result\n'
|
||||
wrappers.append(dict(name=name,signature=sig,renamed_signature=new,wrapper=body))
|
||||
if group!='kernel_phases':declared[group].append(name)
|
||||
if group=='kernel_phases':declared[group]=[str(i) for i in range(11)]
|
||||
suffix='\n# Private r338 diagnostic fields; not persisted. Nested inclusive timings only.\nvar _p23r338_metrics: Dictionary = {}\n\n'+'\n'.join(w['wrapper'] for w in wrappers)+'\n';text+=suffix
|
||||
inverse=text[:-len(suffix)]
|
||||
for w in wrappers:inverse=inverse.replace(w['renamed_signature'],w['signature'],1)
|
||||
assert inverse==original
|
||||
for sub,content in [('originals',original),('instrumented',text)]:
|
||||
p=O/sub/rel;p.parent.mkdir(parents=True,exist_ok=True);p.write_text(content)
|
||||
manifest[rel]=dict(before=pin(O/'originals'/rel),after=pin(O/'instrumented'/rel),wrappers=wrappers,suffix=suffix,inverse_equal=True)
|
||||
qa=(A/'p23-02-native-input-copy-whole-r336/whole.gd').read_text()
|
||||
qa=qa.replace('# One sample of an adjacent hot-loop r326/library327 versus input-copy r333/library334 pair. Only the synchronous tick is timed.','# One instrumented current r333/library334 tick; nested inclusive timing only.')
|
||||
qa=qa.replace('candidate not in ["baseline","candidate"]','candidate != "r333-diagnostic"')
|
||||
# No added external listeners. Counters are read and frozen immediately after tick.
|
||||
init='\tvar declared: Dictionary = '+json.dumps(declared)+'\n\tvar targets: Dictionary = {'+', '.join(json.dumps(k)+':'+v for k,v in targets.items())+'}\n\tfor group: String in declared:\n\t\ttargets[group]._p23r338_metrics.clear()\n\t\tfor key: String in declared[group]: targets[group]._p23r338_metrics[key] = {"calls":0,"inclusive_us":0,"max_us":0}\n'
|
||||
qa=qa.replace('\tvar started := Time.get_ticks_usec()',init+'\tvar started := Time.get_ticks_usec()')
|
||||
qa=qa.replace('\tcheck(clock.absolute_minute == 647','\tvar metrics: Dictionary = {}\n\tfor group: String in declared: metrics[group] = targets[group]._p23r338_metrics.duplicate(true)\n\tcheck(clock.absolute_minute == 647',1)
|
||||
validation='\tvar metrics_valid := true\n\tfor group: String in declared:\n\t\tmetrics_valid = metrics_valid and metrics[group].size() == declared[group].size()\n\t\tfor key: String in declared[group]:\n\t\t\tvar row: Dictionary = metrics[group][key]\n\t\t\tmetrics_valid = metrics_valid and int(row["calls"]) >= 0 and int(row["inclusive_us"]) >= int(row["max_us"]) and int(row["max_us"]) >= 0\n\t\t\tif int(row["calls"]) == 0: metrics_valid = metrics_valid and int(row["inclusive_us"]) == 0 and int(row["max_us"]) == 0\n\tfor key: String in declared["kernel_phases"]: metrics_valid = metrics_valid and int(metrics["kernel_phases"][key]["calls"]) == 1\n\tcheck(metrics_valid, "finite nested metric schema and one call per kernel phase")\n\tvar metrics_pin := typed("metrics",metrics)\n\tvar decoded := FileAccess.open(output.path_join("metrics.json"),FileAccess.WRITE)\n\tif decoded == null: quit(98); return\n\tdecoded.store_string(JSON.stringify(metrics,"\\t")); decoded.close()\n'
|
||||
qa=qa.replace('\tvar report :=',validation+'\tvar report :=',1).replace('"manual_tick_us":elapsed','"manual_tick_us":elapsed,"metrics":metrics_pin,"diagnostic_only":true')
|
||||
qa=qa.replace('SDK whole647:', 'Phase diagnostic whole647:')
|
||||
qa=qa.replace('One sample from an adjacent baseline hot-loop r326/library327 versus input-copy r333/library334 pair; fixed cold restored646. Only exploratory pair observation, no stable speedup, percentile or budget acceptance.','One instrumented r333/library334 cold646 tick; nested inclusive metrics, no sums or subtraction as pure CPU, no uninstrumented speed comparison or acceptance.')
|
||||
(O/'diagnostic.gd').write_text(qa)
|
||||
wrapper=(A/'p23-02-native-input-copy-whole-r336/guarded-candidate.gd').read_text() if (A/'p23-02-native-input-copy-whole-r336/guarded-candidate.gd').exists() else ''
|
||||
if not wrapper:
|
||||
x=r.read(A/'p23-02-native-input-copy-whole-r336/input.json');wrapper=Path(x['pins']['starter_candidate']['path']).read_text()
|
||||
wrapper=re.sub(r'^extends .*$', lambda m: 'extends '+json.dumps(str(O/'diagnostic.gd')),wrapper,count=1,flags=re.M)
|
||||
(O/'guarded.gd').write_text(wrapper)
|
||||
old=r.read(A/'p23-02-native-input-copy-whole-r336/input.json');fixed={k:v for k,v in old['pins'].items() if k in ['engine','fixture','oracle','modified_budget','original_path']}
|
||||
fixed.update(starter=pin(O/'guarded.gd'),qa=pin(O/'diagnostic.gd'),extension=pin(A/'p23-02-native-input-copy-local-r335/candidate.gdextension'))
|
||||
for line in Path(fixed['extension']['path']).read_text().splitlines():
|
||||
if line.startswith('macos.arm64'):
|
||||
lib=Path(line.split('=',1)[1].strip().strip('"'));fixed['library']=pin(lib)
|
||||
expected=r.inventory(stage,stage=True);patched=dict(expected)
|
||||
for rel,row in manifest.items():
|
||||
# inventory values include SHA/bytes shape; inspect and preserve value layout.
|
||||
v=expected[rel];patched[rel]={**v,'bytes':row['after']['bytes'],'sha256':row['after']['sha256']} if isinstance(v,dict) else row['after']['sha256']
|
||||
patched['scripts/core/performance_budget.gd']=old['patched_stage']['scripts/core/performance_budget.gd']
|
||||
plan=dict(plan_id='P23-02',purpose='one current r333/library334 phase/submethod diagnostic; no new implementation or acceptance',stage=str(stage),pins=fixed,source_before=r.source_refs(R),default_before=r.default_player(R),doc4_before={n:r.sha(D/n) for n in ['IMPLEMENTATION_PLAN.md','PROGRESS_INTEGRATION.md','work_packages.json','progress_snapshot.json']},support_inventory=r.inventory(r.SUPPORT),expected_stage=expected,patched_stage=patched,manifest=manifest,declared=declared,targets=targets,missing_methods=missing,capacity_floor_bytes=528*1048576,measurement_cap_bytes=16*1048576,owned_deadline_seconds=90,estimated_seconds=15,stage_clone_count=0,compile_count=0,unit_accepted=False,performance_accepted=False)
|
||||
r.write(O/'input.json',plan)
|
||||
print(json.dumps(dict(output=str(O),missing=missing,stage_files=len(manifest),free_bytes=shutil.disk_usage(A).free,inventory_example=next(iter(expected.items())))))
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
+15
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"passed": true,
|
||||
"packages": 30,
|
||||
"units": 88,
|
||||
"counts": {
|
||||
"completed": 9,
|
||||
"in_progress": 19,
|
||||
"planned": 60
|
||||
},
|
||||
"other_29_packages_87_units_exact": true,
|
||||
"all_original_work_acceptance_state_preserved": true,
|
||||
"formal_completed_added": 0,
|
||||
"new_game_execution_count": 1,
|
||||
"new_full_regression_count": 0
|
||||
}
|
||||
+259
@@ -0,0 +1,259 @@
|
||||
{
|
||||
"plan_date_jst": "2026-10-02",
|
||||
"scope": "planning consistency and static baseline reconciliation; not game acceptance",
|
||||
"passed": true,
|
||||
"checks": [
|
||||
{
|
||||
"name": "all30_unique_package_ids",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "unique_delivery_ids",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "delivery_scope_and_acceptance",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "valid_delivery_states",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "completed_delivery_requires_evidence",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "linked_delivery_evidence_exists",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "known_dependency_ids",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "dependency_graph_acyclic",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "all75_original_groups_once",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "feature71_schedule4",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "coverage_known_packages",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "coverage_known_delivery_ids",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "coverage_exact_package_deliveries",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "package_and_requirement_mapping_agree",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "source_lines_preserved",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "old_status_not_promoted",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "all10_facility_supplements",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "P09_owns10_supplements",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "all10_pending_decision_groups",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "known_decision_references",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "all5_confirmed_decisions",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "confirmed_decision_references_exist",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "valid_package_states",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "new_completed_packages_require_evidence",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "acceptance_conditions_not_claimed_results",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "initial_revision_history_preserved",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "progress_contract8_views",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "progress_no_partial_credit",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "frozen_denominator_has_register",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "known_denominator_matches_frozen_register",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "progress_register_pin_matches",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "evidence_index_register_pin_matches",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "progress_index_pin_matches",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "known_counts_match_freeze",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "unresolved_final_denominator_not_reported_as_total",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "static_leads_not_whole_atom_acceptance",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "declared_limited_views_whole_atoms_unreviewed",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "regression_evidence_pin_matches",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "regression_source_time_scope_preserved",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "P01_P03_not_whole_package_completed",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "progress_schedule_excluded",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "baseline_materials_exist",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "retained_regression155_12310",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "new_game_tests_not_claimed",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "all_package_headings",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "all_group_rows",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "all_delivery_ids_in_document",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "encyclopedia_and_hero_rival_scope",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"name": "current_native_and_longplay_not_claimed",
|
||||
"passed": true
|
||||
}
|
||||
],
|
||||
"failed_checks": [],
|
||||
"packages": 30,
|
||||
"remaining_delivery_units": 88,
|
||||
"current_package_state_counts": {
|
||||
"completed": 1,
|
||||
"in_progress": 25,
|
||||
"planned": 4
|
||||
},
|
||||
"initial_snapshot_checked": false,
|
||||
"historical_source_bytes_compared": false,
|
||||
"covered_original_groups": 75,
|
||||
"missing_original_group_ids": [],
|
||||
"facility_supplements": 10,
|
||||
"atomic_denominator": null,
|
||||
"known_condition_denominator": 1291,
|
||||
"final_denominator_established": false,
|
||||
"total_game_implementation_percent": null,
|
||||
"total_game_acceptance_percent": null,
|
||||
"new_game_execution_count": 0,
|
||||
"document_sha256": {
|
||||
"ASSETS_PLATFORM_AUDIT.md": "a3a4b8ca0fb39a9abf88692285d26aa879815e092352ba304ef2758e71da50bd",
|
||||
"ATOMIC_REGISTER.md": "6070143b85b7c3b9b73d7c9768d88d2dae4d20407ad54a563cb6ffd74f2373ae",
|
||||
"ATOMIC_SEMANTIC_REVIEW.md": "c156b1fb57c2b4a900f27a19049510f3e9616e723d5edb3417f50d733de5be48",
|
||||
"IMPLEMENTATION_PLAN.md": "cdcb5567806d95aea6eacaf9c9fbe003a93523b6eb30a4d05890c6a63a911596",
|
||||
"IMPORT_UNICODE_AUDIT.md": "88b2382bfbb3411fece8be7e6004ba21d8bf6a47e9d1f3cf573ea6638f79c12f",
|
||||
"P09_VALUE_CONTRACTS.md": "c5abdc4543e54033b1fcfd0943cba266f664d8c10968965fd36ade40da488a25",
|
||||
"PERFORMANCE_AUDIT.md": "c75e806acf825fc4a61f773a2cce7e71be335a1e25dbb15d98091097e8dc47c1",
|
||||
"PROGRESS_INTEGRATION.md": "25b2a0a3587f51aec10033314f5a1b256c96b80909d7c3660ac5c9f65968022a",
|
||||
"REVIEW.md": "6665259dfd53be86e113aee502818104dbdb5497da9c817790a24338a4689316",
|
||||
"RUNTIME_SAVE_AUDIT.md": "e88ae014c6154c7aaade5835afc2113f79ee4a4ca5a015c28a4976f8ead68883",
|
||||
"assets_platform_audit.json": "a9fabd989d03071c6af6dc828fff4f021e1ece9638857c54115997923af68d77",
|
||||
"atomic_denominator_freeze.json": "467e960eb0fe47241edb217f5fa2044f2de304441daf9e51a7b0cb46ffa9194d",
|
||||
"atomic_requirements.json": "44530bb929fcc8c68c06d0d94da66dd04b8db7680af731b5037cd44677502938",
|
||||
"atomic_requirements_validation.json": "8dc300b099cfd90fda862f138b6a528d01e9c488a2c67fe07a00a92a70f99175",
|
||||
"atomic_semantic_review.json": "e300b57f22ab86aa8029ce97231fcff0d7530fd4a9134988f113a46498ada7ad",
|
||||
"baseline.json": "750bb3d313cc5e2ce0d4c79e563a995abd7a78f991dee1dd75c627877b02cd7b",
|
||||
"build_atomic_requirements.py": "6d6ea9e4216372dbd0f9fed3f885a4481b21a3f539a26f64cf98a6830af984c5",
|
||||
"build_facility_value_contracts.py": "35027b23ce75ce9e4e0cdfc5132fd2eb771ba9f598d97750d7ecf9ecb257f769",
|
||||
"current_evidence_links.json": "db1837bcc8497201134297e312f4b266a297102285307ec3075d4e23632e26c2",
|
||||
"decisions.json": "ad0673051b0fa601e525f05128e0b11e2dddd9d4bae6a3e0170bbf47da35efe9",
|
||||
"facility_value_contracts.json": "447388ba03a29bfac25f2bcd068665aedbb07ba7641ce86f2db93d44f4c9f326",
|
||||
"facility_value_contracts_validation.json": "bf490a9ca585c48fc318e76c4a069ef244827d828d46e6415399f7710590dd16",
|
||||
"performance_audit.json": "0b630b15a392c3e0366f1362bfe4ddacb968f915f54549f82e4d6fa315384762",
|
||||
"progress_contract.json": "ccbdfce8c8365d5c13f59531955708834cce45acd0e136561c95295dfdb5df77",
|
||||
"progress_snapshot.json": "4fd3692451924ae73c02142c7428ac9241c63d93c0660462470bdf355c58bc26",
|
||||
"progress_validator_guard_checks.json": "72ee513fcf1cad85c24bfd0a4b472f425f6acf117928ece0f6b41e29018da627",
|
||||
"progress_validator_guard_checks.r01.json": "14c26adffa5a1938241db4912e50ea54b660641ee6fee2e412d467dce14d0519",
|
||||
"requirement_coverage.json": "8b5788b22ae8f49ea7e5cf048a5f0d82b54f6f193623465e0b70496b5aadd09d",
|
||||
"runtime_save_audit.json": "0c0c3724371c99bc9a2a80378b30d51fec7d3d9499da02e0d6dfeaf99f01de00",
|
||||
"source_atomic_coverage.json": "2ab7b9e6a2536ef248d4f7ccd695bf75a082b47018aca7a5a1b6b706fe1907bc",
|
||||
"validate_atomic_requirements.py": "5b2d0b7d72cb124830fbb0a12d1434e6db698148cc5263d33fd5bd7c2953a1e0",
|
||||
"validate_facility_value_contracts.py": "91640e2a76cd6cc9186f7b85c0bf379b24b6cac0d48962815235ee628e7ae43e",
|
||||
"validate_plan.py": "23678227d9b3c556f1bd903f4b5b3147c4a82ce5085e10055481026803451b80",
|
||||
"validator_update_checks.json": "f997d0f3de2cea29550840b1d5cb23647d64f81329de46758551e2b6c8fecc27",
|
||||
"work_packages.json": "f0ab4aac2df6c8317354b906379da9f23f416943d0950c7b88bc5a0999a13f13"
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
# coding: utf-8
|
||||
from pathlib import Path
|
||||
import json,hashlib,shutil,datetime
|
||||
R=Path('/Users/korizatou114/Projects/とりにく工房ゲーム制作部');A=R/'artifacts/original-completion-2026-10-02';D=R/'docs/plans/original-completion-2026-10-02';O=A/'p23-02-current-phase-integration-r339';(O/'before').mkdir(parents=True)
|
||||
N=['IMPLEMENTATION_PLAN.md','PROGRESS_INTEGRATION.md','work_packages.json','progress_snapshot.json']
|
||||
for n in N:shutil.copyfile(D/n,O/'before'/n)
|
||||
review=A/'p23-02-current-phase-diagnostic-actual-independent-review-r338-r02.json';v=json.loads(review.read_text());assert v['finite_diagnostic_accepted'] and not v['blockers']
|
||||
report=json.loads((A/'p23-02-current-phase-diagnostic-r338-r02/measurement/report.json').read_text());assert report['passed'] and report['checks']==17
|
||||
ts=datetime.datetime.now(datetime.timezone(datetime.timedelta(hours=9))).isoformat()
|
||||
summary='r338-r02で現在未選定r333/library334の包含診断1回を独立有限受理。17/0、after647全11487732bytes原oracle一致、stage/source/default保持。enum再照合により旧phase3は建設・4は物流・5は施設完了と訂正。現在包含construction118776us/crosslinks118334us、logistics88107us/tick87311us、Guest候補投影564197us、publish76085us。次の修正対象は整合検証と物流実行。施設決済0calls・在庫期限348usを根拠なく優先しない。純CPU・改善比較・性能受入・採用・単位完成ではない。'
|
||||
work=json.loads((D/'work_packages.json').read_text());before=json.loads(json.dumps(work));p=next(p for p in work if p['id']=='P23');u=next(u for u in p['remaining_deliverables'] if u['id']=='P23-02')
|
||||
p['current_summary']+='\n'+summary;p['updated_at_jst']=ts;u['progress_summary']+='\n'+summary;u['updated_at_jst']=ts
|
||||
u['current_phase_diagnostic_r339']={'review':str(review.relative_to(R)),'sha256':hashlib.sha256(review.read_bytes()).hexdigest(),'scope':'finite current instrumented whole647 only; no acceptance','next_scope':'construction infrastructure crosslink validation and supply logistics tick','unit_accepted':False,'performance_accepted':False}
|
||||
u['evidence'].append({'path':str(review.relative_to(R)),'sha256_at_integration':hashlib.sha256(review.read_bytes()).hexdigest(),'scope':'P23-02 finite current r333/library334 phase diagnostic only; no performance/adoption/unit/Windows acceptance','linked_at_jst':ts})
|
||||
(D/'work_packages.json').write_text(json.dumps(work,ensure_ascii=False,indent=2)+'\n')
|
||||
snap=json.loads((D/'progress_snapshot.json').read_text());snap['current_phase_diagnostic_r339']={'plan_id':'P23-02','candidate':'r333/library334','summary':summary,'report':str((A/'p23-02-current-phase-diagnostic-r338-r02/measurement/report.json').relative_to(R)),'review':str(review.relative_to(R)),'checkpoint':'docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/manifest.json','formally_completed_added':0,'all_original17_unaccepted':True,'production_r32_preserved':True,'selected_parent_r274_library275_preserved':True,'manual_modifier_wheel_drag_deferred_not_waived':True,'only_windows_C08_X8_blocked':True,'updated_at_jst':ts};(D/'progress_snapshot.json').write_text(json.dumps(snap,ensure_ascii=False,indent=2)+'\n')
|
||||
for n in N[:2]:
|
||||
text=(D/n).read_text();heading,rest=text.split('\n',1);(D/n).write_text(heading+'\n\n## 現在版のフェーズ診断 r338-r02 / r339\n\n'+summary+' 正式9/着手19/予定60、30パッケージ/88成果、部分点なし、原9横断8すべて未受入。Windows C08/X8だけblock、手動操作延期非免除。\n\n詳細:[CURRENT_PHASE_DIAGNOSTIC_R338_R339.md](execution/CURRENT_PHASE_DIAGNOSTIC_R338_R339.md)\n'+rest)
|
||||
# Exact original scope and all non-target units/packages invariant.
|
||||
for old,new in zip(before,work):
|
||||
assert old['id']==new['id']
|
||||
if old['id']!='P23':assert old==new
|
||||
for a,b in zip(old['remaining_deliverables'],new['remaining_deliverables']):
|
||||
for k in ['id','work','acceptance','state']:assert a[k]==b[k]
|
||||
if a['id']!='P23-02':assert a==b
|
||||
units=[u for p in work for u in p['remaining_deliverables']];counts={s:sum(u['state']==s for u in units) for s in ['completed','in_progress','planned']};assert len(work)==30 and len(units)==88 and counts=={'completed':9,'in_progress':19,'planned':60}
|
||||
(O/'author-scope-invariants.json').write_text(json.dumps({'passed':True,'packages':30,'units':88,'counts':counts,'other_29_packages_87_units_exact':True,'all_original_work_acceptance_state_preserved':True,'formal_completed_added':0,'new_game_execution_count':1,'new_full_regression_count':0},indent=2)+'\n')
|
||||
print(json.dumps(counts))
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
# coding: utf-8
|
||||
from pathlib import Path
|
||||
import json,gzip,hashlib
|
||||
R=Path('/Users/korizatou114/Projects/とりにく工房ゲーム制作部');A=R/'artifacts/original-completion-2026-10-02';D=R/'docs/plans/original-completion-2026-10-02';O=D/'checkpoints/current-phase-diagnostic-r338-r02';O.mkdir();(O/'.gdignore').write_bytes(b'')
|
||||
paths=[]
|
||||
for name in ['p23-02-current-phase-diagnostic-r338','p23-02-current-phase-diagnostic-r338-r02']:paths+=sorted((A/name).rglob('*'))
|
||||
paths=[p for p in paths if p.is_file()]
|
||||
paths += [A/n for n in ['p23-02-current-phase-diagnostic-r338.py','p23-02-current-phase-diagnostic-r338-r02.py','p23-02-current-phase-diagnostic-preexecution-independent-review-r338.json','p23-02-current-phase-diagnostic-preexecution-independent-review-r338-r02.json','p23-02-current-phase-diagnostic-actual-independent-review-r338-r02.json']]
|
||||
paths += [Path('/private/tmp/thetree-prepare-residual-r338.py')]
|
||||
rows=[]
|
||||
for i,p in enumerate(paths):
|
||||
raw=p.read_bytes();compress=len(raw)>32768 and p.suffix!='.zst';packed=gzip.compress(raw,mtime=0) if compress else raw;name='%03d-%s%s'%(i,p.name,'.gz' if compress else '');out=O/name
|
||||
with out.open('xb') as f:f.write(packed)
|
||||
assert (gzip.decompress(out.read_bytes()) if compress else out.read_bytes())==raw
|
||||
rows.append(dict(original_path=str(p),stored_path=str(out),original_bytes=len(raw),original_sha256=hashlib.sha256(raw).hexdigest(),stored_bytes=len(packed),stored_sha256=hashlib.sha256(packed).hexdigest(),codec='gzip' if compress else 'identity',full_roundtrip_verified=True))
|
||||
manifest=dict(plan_id='P23-02',candidate='r333/library334',files=rows,originals_retained=True,unit_accepted=False,performance_accepted=False,candidate_adopted=False)
|
||||
(O/'manifest.json').write_text(json.dumps(manifest,ensure_ascii=False,indent=2)+'\n');(O/'README.md').write_text('# r338-r02 current phase diagnostic\n\nOne reviewed instrumented cold646 tick. All copies restore byte-for-byte; originals retained. This checkpoint preserves finite evidence and the rejected unexecuted16-check driver, not performance or unit acceptance.\n')
|
||||
print(json.dumps(dict(files=len(rows),raw_bytes=sum(x['original_bytes'] for x in rows),stored_bytes=sum(x['stored_bytes'] for x in rows))))
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
# r338-r02 current phase diagnostic
|
||||
|
||||
One reviewed instrumented cold646 tick. All copies restore byte-for-byte; originals retained. This checkpoint preserves finite evidence and the rejected unexecuted16-check driver, not performance or unit acceptance.
|
||||
+540
@@ -0,0 +1,540 @@
|
||||
{
|
||||
"plan_id": "P23-02",
|
||||
"candidate": "r333/library334",
|
||||
"files": [
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/diagnostic.gd",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/000-diagnostic.gd",
|
||||
"original_bytes": 6807,
|
||||
"original_sha256": "f076e93357b521c0add060a262a725637daf9fa39c9bdb8ccb156f20bfcba9a1",
|
||||
"stored_bytes": 6807,
|
||||
"stored_sha256": "f076e93357b521c0add060a262a725637daf9fa39c9bdb8ccb156f20bfcba9a1",
|
||||
"codec": "identity",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/guarded.gd",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/001-guarded.gd",
|
||||
"original_bytes": 1441,
|
||||
"original_sha256": "3dd8e4f3590fd5b274811c5fffdd49e12e69803b5385c409f786245b9fed1b62",
|
||||
"stored_bytes": 1441,
|
||||
"stored_sha256": "3dd8e4f3590fd5b274811c5fffdd49e12e69803b5385c409f786245b9fed1b62",
|
||||
"codec": "identity",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/input-before-phase-mapping-correction.json",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/002-input-before-phase-mapping-correction.json.gz",
|
||||
"original_bytes": 1017508,
|
||||
"original_sha256": "fe9c06fd72ccd6bb88557082b5015bd8ad8386eee44371fdb4bd9dc8beb658db",
|
||||
"stored_bytes": 230351,
|
||||
"stored_sha256": "deb3767c9f0f6e716cd0a14a1a47ebc2d61941750cdb2c70c532b00b2695d455",
|
||||
"codec": "gzip",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/input-before-transaction-method-correction.json",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/003-input-before-transaction-method-correction.json.gz",
|
||||
"original_bytes": 1011383,
|
||||
"original_sha256": "ca1c57a6c3266df161f8832842bc61c1305ecd2ecd77b7527533dcb44123f639",
|
||||
"stored_bytes": 230131,
|
||||
"stored_sha256": "7f8f417d6191e7643d2903dc133c3735dc091d0ccf0ce1d53941e677612ed6ca",
|
||||
"codec": "gzip",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/input.json",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/004-input.json.gz",
|
||||
"original_bytes": 1023880,
|
||||
"original_sha256": "43f57b58c7533dae7965b71a739dd256219e264b1f2b3bb8639c8bf1a625696e",
|
||||
"stored_bytes": 230747,
|
||||
"stored_sha256": "b83cb5aed610d86284f63eabdbdc11466aa82f7afd6ebba5e21a1f5e5ce8fe57",
|
||||
"codec": "gzip",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/autoload/simulation_runtime.gd",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/005-simulation_runtime.gd.gz",
|
||||
"original_bytes": 621773,
|
||||
"original_sha256": "ce260f1158adfb8d9adda1ea00fa29b3c76bc4968c9f7996fdcf62193e28b540",
|
||||
"stored_bytes": 122288,
|
||||
"stored_sha256": "9bd7bc4c266525b7cd4ad379723d07214e1ff5a3b81e6c7ec3dae6e5c3a0650d",
|
||||
"codec": "gzip",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/core/simulation_kernel.gd",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/006-simulation_kernel.gd",
|
||||
"original_bytes": 8264,
|
||||
"original_sha256": "9c67f2b22a38ab396e9d84522b3d54edb7be85878eb6a745deecb9ca2bde8692",
|
||||
"stored_bytes": 8264,
|
||||
"stored_sha256": "9c67f2b22a38ab396e9d84522b3d54edb7be85878eb6a745deecb9ca2bde8692",
|
||||
"codec": "identity",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/facility/facility_service.gd",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/007-facility_service.gd.gz",
|
||||
"original_bytes": 47788,
|
||||
"original_sha256": "c24d9b475c66046dc7342401a74fdc084ca6698506fdb9284afbadd6c5e68cfa",
|
||||
"stored_bytes": 9450,
|
||||
"stored_sha256": "2b3bd36010dc5d2ba0c3b34866a60315d8df3dc6174183711967bf752060f62f",
|
||||
"codec": "gzip",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/inventory/inventory_service.gd",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/008-inventory_service.gd.gz",
|
||||
"original_bytes": 60808,
|
||||
"original_sha256": "a93e7486fab66938ce7356b16202dddf0d4dd2f9c30e6b9312ec4ee98878480e",
|
||||
"stored_bytes": 10589,
|
||||
"stored_sha256": "c92bf04ddc85d5c4581bcd5107ca37f0e838f74ac9b4c62cd95afea0c932b077",
|
||||
"codec": "gzip",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/supply/kitchen_production_service.gd",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/009-kitchen_production_service.gd",
|
||||
"original_bytes": 19610,
|
||||
"original_sha256": "b751511484258edb471567639f150d8dcfb69ff4245a2273718cfcb3de04ca51",
|
||||
"stored_bytes": 19610,
|
||||
"stored_sha256": "b751511484258edb471567639f150d8dcfb69ff4245a2273718cfcb3de04ca51",
|
||||
"codec": "identity",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/supply/supply_logistics_bridge.gd",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/010-supply_logistics_bridge.gd",
|
||||
"original_bytes": 28814,
|
||||
"original_sha256": "6887a702c1eb6f9e91f689fd734f9bbc386a9cce55a68b1682c3a18be620976a",
|
||||
"stored_bytes": 28814,
|
||||
"stored_sha256": "6887a702c1eb6f9e91f689fd734f9bbc386a9cce55a68b1682c3a18be620976a",
|
||||
"codec": "identity",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/instrumented/scripts/supply/supply_management_service.gd",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/011-supply_management_service.gd",
|
||||
"original_bytes": 27952,
|
||||
"original_sha256": "87f2a3c36ef8b4569d17191f0c376fc957462dd7fe33a832c7284fdceb4a5b3c",
|
||||
"stored_bytes": 27952,
|
||||
"stored_sha256": "87f2a3c36ef8b4569d17191f0c376fc957462dd7fe33a832c7284fdceb4a5b3c",
|
||||
"codec": "identity",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/autoload/simulation_runtime.gd",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/012-simulation_runtime.gd.gz",
|
||||
"original_bytes": 612068,
|
||||
"original_sha256": "7eb24adbf91fe53cde14954dda12abd5efb05130de7d356d8df281ee99065e86",
|
||||
"stored_bytes": 121377,
|
||||
"stored_sha256": "6db6e28f4852a1616dd532e5bc7fb328e43633c20e1acf50dd9c0ca3fe54cbd6",
|
||||
"codec": "gzip",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/core/simulation_kernel.gd",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/013-simulation_kernel.gd",
|
||||
"original_bytes": 7602,
|
||||
"original_sha256": "341c0c878c4894adbac628d0db6362ff69fc3347bdd9e61e50936e15dc2d1edb",
|
||||
"stored_bytes": 7602,
|
||||
"stored_sha256": "341c0c878c4894adbac628d0db6362ff69fc3347bdd9e61e50936e15dc2d1edb",
|
||||
"codec": "identity",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/facility/facility_service.gd",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/014-facility_service.gd.gz",
|
||||
"original_bytes": 44951,
|
||||
"original_sha256": "ceb4a3e9224587423f273cdb2b56e6843ab176ac1fc4fe79dd498b5ed5c33b77",
|
||||
"stored_bytes": 9139,
|
||||
"stored_sha256": "ba972a12dcb8bf6ec23bf127eb13c113d71f2ddeb1c1798fdf6e806ff79df1d8",
|
||||
"codec": "gzip",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/inventory/inventory_service.gd",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/015-inventory_service.gd.gz",
|
||||
"original_bytes": 57923,
|
||||
"original_sha256": "7ee83b335864385119ca757037c3cdb912957aa4478a6312a0898a734e41f31a",
|
||||
"stored_bytes": 10204,
|
||||
"stored_sha256": "c9ced67d59e1c4e3e3132665e2f9ed8bc8328ddd4f0f206c6156d2972e174e75",
|
||||
"codec": "gzip",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/supply/kitchen_production_service.gd",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/016-kitchen_production_service.gd",
|
||||
"original_bytes": 18872,
|
||||
"original_sha256": "f3bc6bdc1a0ba278e9411108172ceceb7eb06520b4e33f93f35684da1f103c62",
|
||||
"stored_bytes": 18872,
|
||||
"stored_sha256": "f3bc6bdc1a0ba278e9411108172ceceb7eb06520b4e33f93f35684da1f103c62",
|
||||
"codec": "identity",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/supply/supply_logistics_bridge.gd",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/017-supply_logistics_bridge.gd",
|
||||
"original_bytes": 28100,
|
||||
"original_sha256": "b9e394af788595d2744b71f1907c8e7c3d762d38ff49992b1ee74e63b9639e80",
|
||||
"stored_bytes": 28100,
|
||||
"stored_sha256": "b9e394af788595d2744b71f1907c8e7c3d762d38ff49992b1ee74e63b9639e80",
|
||||
"codec": "identity",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/originals/scripts/supply/supply_management_service.gd",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/018-supply_management_service.gd",
|
||||
"original_bytes": 25019,
|
||||
"original_sha256": "e4ad420191020485c027004f64bb00fad9da195fe956ef10dc0c787412018f7f",
|
||||
"stored_bytes": 25019,
|
||||
"stored_sha256": "e4ad420191020485c027004f64bb00fad9da195fe956ef10dc0c787412018f7f",
|
||||
"codec": "identity",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/preexecution-rejected-root-verification.json",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/019-preexecution-rejected-root-verification.json",
|
||||
"original_bytes": 14413,
|
||||
"original_sha256": "c86abdc88a052600d3771d796a51284c9fe0e2ceea3bd5b60ed5e45a66e33fbe",
|
||||
"stored_bytes": 14413,
|
||||
"stored_sha256": "c86abdc88a052600d3771d796a51284c9fe0e2ceea3bd5b60ed5e45a66e33fbe",
|
||||
"codec": "identity",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338/source-audit.json",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/020-source-audit.json",
|
||||
"original_bytes": 2842,
|
||||
"original_sha256": "2bc5d3993faff852eb8c5eed383011c1f9d28dc71842c371631e918981b50cdf",
|
||||
"stored_bytes": 2842,
|
||||
"stored_sha256": "2bc5d3993faff852eb8c5eed383011c1f9d28dc71842c371631e918981b50cdf",
|
||||
"codec": "identity",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/actual-root-verification.json",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/021-actual-root-verification.json",
|
||||
"original_bytes": 21442,
|
||||
"original_sha256": "14d28472c32490d50e3fde951f7c0f6e8b541171b01fbb850f5069b2e7993e4c",
|
||||
"stored_bytes": 21442,
|
||||
"stored_sha256": "14d28472c32490d50e3fde951f7c0f6e8b541171b01fbb850f5069b2e7993e4c",
|
||||
"codec": "identity",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/adapter-owned-cleanup.json",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/022-adapter-owned-cleanup.json",
|
||||
"original_bytes": 351,
|
||||
"original_sha256": "c1f3d289b362cc61b9be169a3994be27df39f35e6221881b4a9678ce3c72ba54",
|
||||
"stored_bytes": 351,
|
||||
"stored_sha256": "c1f3d289b362cc61b9be169a3994be27df39f35e6221881b4a9678ce3c72ba54",
|
||||
"codec": "identity",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/ended.json",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/023-ended.json",
|
||||
"original_bytes": 1748,
|
||||
"original_sha256": "e2aa0217a04f8a13c1f342099a7115c80939912e80fba67b2c4b484f48a923f3",
|
||||
"stored_bytes": 1748,
|
||||
"stored_sha256": "e2aa0217a04f8a13c1f342099a7115c80939912e80fba67b2c4b484f48a923f3",
|
||||
"codec": "identity",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/engine-native.log",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/024-engine-native.log",
|
||||
"original_bytes": 13430,
|
||||
"original_sha256": "d55b7f7471e3b111ba534f95e52285eab62b6d8790eb93371f9af64a8965b9a4",
|
||||
"stored_bytes": 13430,
|
||||
"stored_sha256": "d55b7f7471e3b111ba534f95e52285eab62b6d8790eb93371f9af64a8965b9a4",
|
||||
"codec": "identity",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/outer-owned-finally.json",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/025-outer-owned-finally.json",
|
||||
"original_bytes": 964,
|
||||
"original_sha256": "0602848d465ace99eb2889a8ab58e27867b3318b504512e127adf297e237d18d",
|
||||
"stored_bytes": 964,
|
||||
"stored_sha256": "0602848d465ace99eb2889a8ab58e27867b3318b504512e127adf297e237d18d",
|
||||
"codec": "identity",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/process.json",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/026-process.json",
|
||||
"original_bytes": 6595,
|
||||
"original_sha256": "af54e1491e10a4795bd138ce09d48b46f4046795f31fcbd4c339911521eec3b9",
|
||||
"stored_bytes": 6595,
|
||||
"stored_sha256": "af54e1491e10a4795bd138ce09d48b46f4046795f31fcbd4c339911521eec3b9",
|
||||
"codec": "identity",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/started.json",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/027-started.json",
|
||||
"original_bytes": 2356,
|
||||
"original_sha256": "e1753fb09042deb721b20343330f5c2bbeab13bfd2b8d59e26e5459215def818",
|
||||
"stored_bytes": 2356,
|
||||
"stored_sha256": "e1753fb09042deb721b20343330f5c2bbeab13bfd2b8d59e26e5459215def818",
|
||||
"codec": "identity",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/stderr.log",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/028-stderr.log",
|
||||
"original_bytes": 0,
|
||||
"original_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
||||
"stored_bytes": 0,
|
||||
"stored_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
||||
"codec": "identity",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/engine/stdout.log",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/029-stdout.log",
|
||||
"original_bytes": 13580,
|
||||
"original_sha256": "2b66eb5a87fc2d25389c79ef66882ad54c0f845fc970b6a0acda57b0f412f651",
|
||||
"stored_bytes": 13580,
|
||||
"stored_sha256": "2b66eb5a87fc2d25389c79ef66882ad54c0f845fc970b6a0acda57b0f412f651",
|
||||
"codec": "identity",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/execution.json",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/030-execution.json",
|
||||
"original_bytes": 11232,
|
||||
"original_sha256": "3b33b742d9557b050a8337fbf0c865a765d9bd803effe50d420932a4495cc6b8",
|
||||
"stored_bytes": 11232,
|
||||
"stored_sha256": "3b33b742d9557b050a8337fbf0c865a765d9bd803effe50d420932a4495cc6b8",
|
||||
"codec": "identity",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/input.json",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/031-input.json.gz",
|
||||
"original_bytes": 1024228,
|
||||
"original_sha256": "95f7929f2a8d78593d18285d2c1581ef7a303dae6fae331c8312e15b700b5d91",
|
||||
"stored_bytes": 230872,
|
||||
"stored_sha256": "7541f3e7e938277f0bd48ef7d1eb45f19f1a6cd0223aba0f229a6fbe51445111",
|
||||
"codec": "gzip",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/measurement/after647.varbytes.zst",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/032-after647.varbytes.zst",
|
||||
"original_bytes": 246720,
|
||||
"original_sha256": "684ba40e9f649b7dd4bfc620185d7cd18bae3111c3b4038e48aaad5a9168d880",
|
||||
"stored_bytes": 246720,
|
||||
"stored_sha256": "684ba40e9f649b7dd4bfc620185d7cd18bae3111c3b4038e48aaad5a9168d880",
|
||||
"codec": "identity",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/measurement/metrics.json",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/033-metrics.json",
|
||||
"original_bytes": 3451,
|
||||
"original_sha256": "9bf882e017b0476642f386bfa57eaf7c8b09b4c2d40f51e977b969ccedfc9835",
|
||||
"stored_bytes": 3451,
|
||||
"stored_sha256": "9bf882e017b0476642f386bfa57eaf7c8b09b4c2d40f51e977b969ccedfc9835",
|
||||
"codec": "identity",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/measurement/metrics.varbytes.zst",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/034-metrics.varbytes.zst",
|
||||
"original_bytes": 887,
|
||||
"original_sha256": "4cb3c0f5b12a1de658d8afc293eace99650f05d17dc9f18037ed676207e9de3c",
|
||||
"stored_bytes": 887,
|
||||
"stored_sha256": "4cb3c0f5b12a1de658d8afc293eace99650f05d17dc9f18037ed676207e9de3c",
|
||||
"codec": "identity",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/measurement/report.json",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/035-report.json",
|
||||
"original_bytes": 1799,
|
||||
"original_sha256": "e6b2e22bc91d31de10ca3fcdd1df96fd633714aec5c50309a48bc4fafc57ea81",
|
||||
"stored_bytes": 1799,
|
||||
"stored_sha256": "e6b2e22bc91d31de10ca3fcdd1df96fd633714aec5c50309a48bc4fafc57ea81",
|
||||
"codec": "identity",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/phase.json",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/036-phase.json",
|
||||
"original_bytes": 8031,
|
||||
"original_sha256": "13e5517e87e14ff8363df207da016fd79a4de7945458bbc7ae1b2c76c5463ce5",
|
||||
"stored_bytes": 8031,
|
||||
"stored_sha256": "13e5517e87e14ff8363df207da016fd79a4de7945458bbc7ae1b2c76c5463ce5",
|
||||
"codec": "identity",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/preexecution-root-verification.json",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/037-preexecution-root-verification.json",
|
||||
"original_bytes": 15310,
|
||||
"original_sha256": "3b0b88c9983ef376bf56428f2a6cc00819dc4880d0e407b3ffd2f98e2ba89f4b",
|
||||
"stored_bytes": 15310,
|
||||
"stored_sha256": "3b0b88c9983ef376bf56428f2a6cc00819dc4880d0e407b3ffd2f98e2ba89f4b",
|
||||
"codec": "identity",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/profile.json",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/038-profile.json",
|
||||
"original_bytes": 932,
|
||||
"original_sha256": "19ac44fca90fd6bf47be1ab8027e1cebda05f511cccccfe5f077e86f6b8f7c39",
|
||||
"stored_bytes": 932,
|
||||
"stored_sha256": "19ac44fca90fd6bf47be1ab8027e1cebda05f511cccccfe5f077e86f6b8f7c39",
|
||||
"codec": "identity",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338.py",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/039-p23-02-current-phase-diagnostic-r338.py",
|
||||
"original_bytes": 6430,
|
||||
"original_sha256": "df468edfdc85ec9f445206ad005254d0472d1f8cc2f2c3fbea41db05dbd53b9a",
|
||||
"stored_bytes": 6430,
|
||||
"stored_sha256": "df468edfdc85ec9f445206ad005254d0472d1f8cc2f2c3fbea41db05dbd53b9a",
|
||||
"codec": "identity",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02.py",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/040-p23-02-current-phase-diagnostic-r338-r02.py",
|
||||
"original_bytes": 6438,
|
||||
"original_sha256": "97e994c336ae44f78581e0885321b572d002635c39e36ae62aa1e84feb6fd011",
|
||||
"stored_bytes": 6438,
|
||||
"stored_sha256": "97e994c336ae44f78581e0885321b572d002635c39e36ae62aa1e84feb6fd011",
|
||||
"codec": "identity",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-preexecution-independent-review-r338.json",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/041-p23-02-current-phase-diagnostic-preexecution-independent-review-r338.json",
|
||||
"original_bytes": 26442,
|
||||
"original_sha256": "25d15928c713cb1608490bae5ea10d6374b21a764c87ae19ba2ce32a2d20ba39",
|
||||
"stored_bytes": 26442,
|
||||
"stored_sha256": "25d15928c713cb1608490bae5ea10d6374b21a764c87ae19ba2ce32a2d20ba39",
|
||||
"codec": "identity",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-preexecution-independent-review-r338-r02.json",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/042-p23-02-current-phase-diagnostic-preexecution-independent-review-r338-r02.json",
|
||||
"original_bytes": 26503,
|
||||
"original_sha256": "ad50e109577313f7626e931cfc6943a944fee2f9912adb4d60e706659ae0c23d",
|
||||
"stored_bytes": 26503,
|
||||
"stored_sha256": "ad50e109577313f7626e931cfc6943a944fee2f9912adb4d60e706659ae0c23d",
|
||||
"codec": "identity",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-actual-independent-review-r338-r02.json",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/043-p23-02-current-phase-diagnostic-actual-independent-review-r338-r02.json.gz",
|
||||
"original_bytes": 42937,
|
||||
"original_sha256": "c0fcbaf02f18618a7f833c70f0f0cd3c1e517f5318061cca0158c9c288a6503a",
|
||||
"stored_bytes": 7163,
|
||||
"stored_sha256": "ddbc70baed70694e6fa6d2992a65b6545f000003102632d2b2c2325dc272a9ef",
|
||||
"codec": "gzip",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/private/tmp/thetree-prepare-residual-r338.py",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/044-thetree-prepare-residual-r338.py",
|
||||
"original_bytes": 9527,
|
||||
"original_sha256": "ff0e7c5fcb572b900585b334890612e19894f347ea57a6e1541935c7df6f3468",
|
||||
"stored_bytes": 9527,
|
||||
"stored_sha256": "ff0e7c5fcb572b900585b334890612e19894f347ea57a6e1541935c7df6f3468",
|
||||
"codec": "identity",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-integration-r339/before/IMPLEMENTATION_PLAN.md",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/045-IMPLEMENTATION_PLAN.md.gz",
|
||||
"original_bytes": 492489,
|
||||
"original_sha256": "4e9748ca579001e5673f83568d64bbe45b6bad7420ee6481901496f0fd7e9f28",
|
||||
"stored_bytes": 143785,
|
||||
"stored_sha256": "d3e05d1bd4cc71fd6cf0c2e907908a9a368a1f4b021f2e6296eeac1e9580df2a",
|
||||
"codec": "gzip",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-integration-r339/before/PROGRESS_INTEGRATION.md",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/046-PROGRESS_INTEGRATION.md.gz",
|
||||
"original_bytes": 410553,
|
||||
"original_sha256": "b5617405aaa913cef5f5e23bbc5141bfb746de88926116c02ea2d33bd5ea7a22",
|
||||
"stored_bytes": 113672,
|
||||
"stored_sha256": "ed4e9f12ef96d3de1897407b0e68b1c2ca6d8cf1236665805904702471a6574d",
|
||||
"codec": "gzip",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-integration-r339/before/progress_snapshot.json",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/047-progress_snapshot.json.gz",
|
||||
"original_bytes": 591756,
|
||||
"original_sha256": "db411f761cc2e64d9ae7859ebdc085bfacc1b649dd4c7241c34a96fd28e07b97",
|
||||
"stored_bytes": 108032,
|
||||
"stored_sha256": "932763cb3295ad71aec349e9d587fcd41d04128fed8df03516cb27839ff63f45",
|
||||
"codec": "gzip",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-integration-r339/before/work_packages.json",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/048-work_packages.json.gz",
|
||||
"original_bytes": 1188101,
|
||||
"original_sha256": "e7e8d40e9a9a85095d6e4ad96ab305fa1bf83f10f754b3c541e27cb78b1f6f67",
|
||||
"stored_bytes": 200823,
|
||||
"stored_sha256": "97546ce8bc695857a9f9754a069892304df82d26c09855184a9488e2ab2479b7",
|
||||
"codec": "gzip",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-integration-r339/author-scope-invariants.json",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/049-author-scope-invariants.json",
|
||||
"original_bytes": 332,
|
||||
"original_sha256": "a400e7cc3af786e842a8fd7076342609aa4b657d6d7bbe0af0024400c59005b5",
|
||||
"stored_bytes": 332,
|
||||
"stored_sha256": "a400e7cc3af786e842a8fd7076342609aa4b657d6d7bbe0af0024400c59005b5",
|
||||
"codec": "identity",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/plan_validation.json",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/050-plan_validation.json",
|
||||
"original_bytes": 8285,
|
||||
"original_sha256": "16ae4834351d720e6ce92fde0fc191e4c222377d0d00289fd2cf8f7be5ee9c45",
|
||||
"stored_bytes": 8285,
|
||||
"stored_sha256": "16ae4834351d720e6ce92fde0fc191e4c222377d0d00289fd2cf8f7be5ee9c45",
|
||||
"codec": "identity",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/private/tmp/thetree-integrate-phase-r339.py",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/051-thetree-integrate-phase-r339.py",
|
||||
"original_bytes": 4611,
|
||||
"original_sha256": "ffc67c0e8ec7d24efccd2abc2f3b532cd4ad76a5b80413699873b6dbfca23ce7",
|
||||
"stored_bytes": 4611,
|
||||
"stored_sha256": "ffc67c0e8ec7d24efccd2abc2f3b532cd4ad76a5b80413699873b6dbfca23ce7",
|
||||
"codec": "identity",
|
||||
"full_roundtrip_verified": true
|
||||
},
|
||||
{
|
||||
"original_path": "/private/tmp/thetree-checkpoint-phase-r339.py",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/052-thetree-checkpoint-phase-r339.py",
|
||||
"original_bytes": 2225,
|
||||
"original_sha256": "0e1bf1f8c3a5930bf50df7326caccebb0a6efe5dfe0210c0a805c646e91220b1",
|
||||
"stored_bytes": 2225,
|
||||
"stored_sha256": "0e1bf1f8c3a5930bf50df7326caccebb0a6efe5dfe0210c0a805c646e91220b1",
|
||||
"codec": "identity",
|
||||
"full_roundtrip_verified": true
|
||||
}
|
||||
],
|
||||
"originals_retained": true,
|
||||
"unit_accepted": false,
|
||||
"performance_accepted": false,
|
||||
"candidate_adopted": false
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
# P23-02 現在版のフェーズ診断 r338-r02 / r339
|
||||
|
||||
次に閉じる成果単位はP23-02。制作r32、選定済み実装親r274/library275、未選定・未採用候補r333/library334を保持する。今回は新実装の採用なし、正式完了追加0。30パッケージ/88成果単位、正式9/着手19/予定60、部分点なし。
|
||||
|
||||
受入条件・依存P08/P22・対象版・既存証拠・不足条件は[r337の全17条件](CURRENT_NATIVE_INPUT_COPY_R332_R337.md)と原current r337 matrixを保持する。C01–C09/X1–X8すべて未受入。Windows C08/X8だけ実機block、Ctrl保持wheel/左ボタン保持dragは延期・未達・非免除。最終受入対象版と同一Windows配布版は未確定。
|
||||
|
||||
今回の証拠はr333/library334での単一cold646→647包含診断。共有stage315を再利用、7scriptsとBudget257を一時変更、projectをprivate profile化し、所有エンジンの終了後に元バイトへ完全復元した。新compile0/stageclone0/全回帰0、所有PID60890正常exit0、17checks/0fail、strict3logs/private5/cleanup確認済み。after647の全11,487,732バイトは原oracleと全文一致しraw SHA256は `9df3c1b6f65dfd8be944cd5cab8c631f7533530dfef3820d9fa5d74a5b1ac30f`。metrics全4,456バイトは独立decode/reencodeで完全復元し39行がJSONと一致。source/default/SUPPORT/stage1299/D4の保全を確認した。
|
||||
|
||||
旧r311のphase3を在庫、phase4を施設と見た初期の解釈は誤り。Kernel enumとRuntime handlerを直接再照合し、phase3=建設/4=物流/5=施設完了へ訂正した。旧計測は原r274の包含観測で、現在版の性能や純CPU時間へ換算しない。
|
||||
|
||||
| 現在版の計測対象 | 呼出回数 | 包含時間us | 次の判断 |
|
||||
|---|---:|---:|---|
|
||||
| 建設phase3 | 1 | 118776 | crosslink検証を調査 |
|
||||
| `_validate_infrastructure_crosslinks` | 1 | 118334 | 建設phaseに包含、加算しない |
|
||||
| 物流phase4 | 1 | 88107 | supply logistics実行を調査 |
|
||||
| `SupplyLogisticsBridge.tick` | 1 | 87311 | 物流phaseに包含、加算しない |
|
||||
| 施設完了phase5 | 1 | 964 | 今回の主対象から外す |
|
||||
| 施設決済 `_apply_service_transaction` | 0 | 0 | この入力で未呼出、一般の費用ゼロを証明しない |
|
||||
| 在庫期限処理 | 1 | 348 | 根拠なく優先しない |
|
||||
| AI phase9 | 1 | 729195 | Guest側既存候補を保持 |
|
||||
| Guest候補投影 | 50 | 564197 | AI phaseに包含、加算しない |
|
||||
| 公開phase10 | 1 | 76085 | 既存snapshot契約を保持 |
|
||||
|
||||
同期tick全体の観測は1,016,169us。すべて計測オーバーヘッドを含む単一の包含wall timeであり、加減算した純CPU時間、安定改善率、P95/D10、50ms性能受入には使わない。通常Main描画、x3追随、OS操作、最終172全回帰、Windows、候補採用、単位完成は未受入。
|
||||
|
||||
実行前レビューでdriverの期待数16が誤りと分かったため、未実行r338を保持し、期待report/stdoutだけ17へ修復したr338-r02を実行。QAのassertionや受入基準を減らしていない。原版拒否47pins/修正版事前50pins/実結果70pinsをRootでfresh照合。読取専用の独立レビュー1名による有限診断・全文状態一致・終了観測の受理のみ。
|
||||
|
||||
保存コピーは `../checkpoints/current-phase-diagnostic-r338-r02/manifest.json`。identity/gzipを全文復元照合し、原本を保持する。台帳更新前D4を保存し、旧レビューの文書contextは歴史証拠として対応させる。
|
||||
|
||||
次の修正は、建設の整合検証と物流実行の必要な関連処理をまとめて扱う。外部改変検出、異常・境界、決済・配送のロールバック、イベント通知順、途中保存・再開、原oracle全文状態を維持する。未知の仕様・数値は決めず、r204の既不採用再構築や微小pairを再実行しない。静的確認→必要な局所・影響試験→独立レビュー→正確な最終版の必須回帰・受入の順を維持する。
|
||||
BIN
Binary file not shown.
+24
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"files": [
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-integration-independent-review-r339.json",
|
||||
"original_bytes": 61147,
|
||||
"original_sha256": "01a7e21d87fcf6b34d15f45c600ff09ff58535b4533fd176e28ca5c7ab8beb22",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/execution/current-phase-r339-review/p23-02-current-phase-integration-independent-review-r339.json.gz",
|
||||
"stored_bytes": 6856,
|
||||
"stored_sha256": "e2f57e4bb9114140539b9451a3a1e68b5ae59631053fed04d7ff38164cfc9502",
|
||||
"full_roundtrip": true
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-phase-integration-r339/final-root-verification.json",
|
||||
"original_bytes": 37480,
|
||||
"original_sha256": "9e67d6a386688bd8d28cb3864be53992ec55141a12ee34f0c07f0d73ea001927",
|
||||
"stored_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/execution/current-phase-r339-review/final-root-verification.json.gz",
|
||||
"stored_bytes": 5127,
|
||||
"stored_sha256": "41529e3fac06b90e382c322d5ec4e71fbc92345524ecb9ccaad77ddf22175d2f",
|
||||
"full_roundtrip": true
|
||||
}
|
||||
],
|
||||
"unit_accepted": false,
|
||||
"performance_accepted": false
|
||||
}
|
||||
BIN
Binary file not shown.
@@ -223,11 +223,11 @@
|
||||
"ASSETS_PLATFORM_AUDIT.md": "a3a4b8ca0fb39a9abf88692285d26aa879815e092352ba304ef2758e71da50bd",
|
||||
"ATOMIC_REGISTER.md": "6070143b85b7c3b9b73d7c9768d88d2dae4d20407ad54a563cb6ffd74f2373ae",
|
||||
"ATOMIC_SEMANTIC_REVIEW.md": "c156b1fb57c2b4a900f27a19049510f3e9616e723d5edb3417f50d733de5be48",
|
||||
"IMPLEMENTATION_PLAN.md": "4e9748ca579001e5673f83568d64bbe45b6bad7420ee6481901496f0fd7e9f28",
|
||||
"IMPLEMENTATION_PLAN.md": "cdcb5567806d95aea6eacaf9c9fbe003a93523b6eb30a4d05890c6a63a911596",
|
||||
"IMPORT_UNICODE_AUDIT.md": "88b2382bfbb3411fece8be7e6004ba21d8bf6a47e9d1f3cf573ea6638f79c12f",
|
||||
"P09_VALUE_CONTRACTS.md": "c5abdc4543e54033b1fcfd0943cba266f664d8c10968965fd36ade40da488a25",
|
||||
"PERFORMANCE_AUDIT.md": "c75e806acf825fc4a61f773a2cce7e71be335a1e25dbb15d98091097e8dc47c1",
|
||||
"PROGRESS_INTEGRATION.md": "b5617405aaa913cef5f5e23bbc5141bfb746de88926116c02ea2d33bd5ea7a22",
|
||||
"PROGRESS_INTEGRATION.md": "25b2a0a3587f51aec10033314f5a1b256c96b80909d7c3660ac5c9f65968022a",
|
||||
"REVIEW.md": "6665259dfd53be86e113aee502818104dbdb5497da9c817790a24338a4689316",
|
||||
"RUNTIME_SAVE_AUDIT.md": "e88ae014c6154c7aaade5835afc2113f79ee4a4ca5a015c28a4976f8ead68883",
|
||||
"assets_platform_audit.json": "a9fabd989d03071c6af6dc828fff4f021e1ece9638857c54115997923af68d77",
|
||||
@@ -244,7 +244,7 @@
|
||||
"facility_value_contracts_validation.json": "bf490a9ca585c48fc318e76c4a069ef244827d828d46e6415399f7710590dd16",
|
||||
"performance_audit.json": "0b630b15a392c3e0366f1362bfe4ddacb968f915f54549f82e4d6fa315384762",
|
||||
"progress_contract.json": "ccbdfce8c8365d5c13f59531955708834cce45acd0e136561c95295dfdb5df77",
|
||||
"progress_snapshot.json": "db411f761cc2e64d9ae7859ebdc085bfacc1b649dd4c7241c34a96fd28e07b97",
|
||||
"progress_snapshot.json": "4fd3692451924ae73c02142c7428ac9241c63d93c0660462470bdf355c58bc26",
|
||||
"progress_validator_guard_checks.json": "72ee513fcf1cad85c24bfd0a4b472f425f6acf117928ece0f6b41e29018da627",
|
||||
"progress_validator_guard_checks.r01.json": "14c26adffa5a1938241db4912e50ea54b660641ee6fee2e412d467dce14d0519",
|
||||
"requirement_coverage.json": "8b5788b22ae8f49ea7e5cf048a5f0d82b54f6f193623465e0b70496b5aadd09d",
|
||||
@@ -254,6 +254,6 @@
|
||||
"validate_facility_value_contracts.py": "91640e2a76cd6cc9186f7b85c0bf379b24b6cac0d48962815235ee628e7ae43e",
|
||||
"validate_plan.py": "23678227d9b3c556f1bd903f4b5b3147c4a82ce5085e10055481026803451b80",
|
||||
"validator_update_checks.json": "f997d0f3de2cea29550840b1d5cb23647d64f81329de46758551e2b6c8fecc27",
|
||||
"work_packages.json": "e7e8d40e9a9a85095d6e4ad96ab305fa1bf83f10f754b3c541e27cb78b1f6f67"
|
||||
"work_packages.json": "f0ab4aac2df6c8317354b906379da9f23f416943d0950c7b88bc5a0999a13f13"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9413,5 +9413,20 @@
|
||||
"unit_accepted": false,
|
||||
"candidate_selected": false,
|
||||
"candidate_adopted": false
|
||||
},
|
||||
"current_phase_diagnostic_r339": {
|
||||
"plan_id": "P23-02",
|
||||
"candidate": "r333/library334",
|
||||
"summary": "r338-r02で現在未選定r333/library334の包含診断1回を独立有限受理。17/0、after647全11487732bytes原oracle一致、stage/source/default保持。enum再照合により旧phase3は建設・4は物流・5は施設完了と訂正。現在包含construction118776us/crosslinks118334us、logistics88107us/tick87311us、Guest候補投影564197us、publish76085us。次の修正対象は整合検証と物流実行。施設決済0calls・在庫期限348usを根拠なく優先しない。純CPU・改善比較・性能受入・採用・単位完成ではない。",
|
||||
"report": "artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-r338-r02/measurement/report.json",
|
||||
"review": "artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-actual-independent-review-r338-r02.json",
|
||||
"checkpoint": "docs/plans/original-completion-2026-10-02/checkpoints/current-phase-diagnostic-r338-r02/manifest.json",
|
||||
"formally_completed_added": 0,
|
||||
"all_original17_unaccepted": true,
|
||||
"production_r32_preserved": true,
|
||||
"selected_parent_r274_library275_preserved": true,
|
||||
"manual_modifier_wheel_drag_deferred_not_waived": true,
|
||||
"only_windows_C08_X8_blocked": true,
|
||||
"updated_at_jst": "2026-10-12T14:09:47.603420+09:00"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9405,7 +9405,7 @@
|
||||
},
|
||||
"legacy_state": "planned",
|
||||
"state_scope": "package-level; completed means whole package accepted; partial implementation is not completion",
|
||||
"current_summary": "P23-02着手中。制作r32と選定済み実装親r274/library275は保持。最新未選定・未採用候補r333/library334は、親r326の在庫入力キー整列と経路コピーだけをnative化。未捕捉std確保例外をビルド前に修復。bridge1/link1、SDKcompile0、既存stage再利用。局所4工程404/0、Runtime150候補105808bytes・評価後11411840bytes原golden全文一致。S6 24/0、両whole15/0、after647全11487732bytes原oracle全文一致を独立有限受理。単一隣接観測1037100→1010883us(約2.5279%短縮)だが約1.01秒停止が残り安定性能・50ms/P95/D10は未受入。r204再構築は既非採用のため再実装なし。原9横断8はすべて未受入、Windows C08/X8のみblock、手動Ctrl保持wheel/左ボタン保持dragは延期・未達・非免除。正式9/着手19/予定60、30パッケージ/88成果、部分点なし、今回正式完了追加0。",
|
||||
"current_summary": "P23-02着手中。制作r32と選定済み実装親r274/library275は保持。最新未選定・未採用候補r333/library334は、親r326の在庫入力キー整列と経路コピーだけをnative化。未捕捉std確保例外をビルド前に修復。bridge1/link1、SDKcompile0、既存stage再利用。局所4工程404/0、Runtime150候補105808bytes・評価後11411840bytes原golden全文一致。S6 24/0、両whole15/0、after647全11487732bytes原oracle全文一致を独立有限受理。単一隣接観測1037100→1010883us(約2.5279%短縮)だが約1.01秒停止が残り安定性能・50ms/P95/D10は未受入。r204再構築は既非採用のため再実装なし。原9横断8はすべて未受入、Windows C08/X8のみblock、手動Ctrl保持wheel/左ボタン保持dragは延期・未達・非免除。正式9/着手19/予定60、30パッケージ/88成果、部分点なし、今回正式完了追加0。\nr338-r02で現在未選定r333/library334の包含診断1回を独立有限受理。17/0、after647全11487732bytes原oracle一致、stage/source/default保持。enum再照合により旧phase3は建設・4は物流・5は施設完了と訂正。現在包含construction118776us/crosslinks118334us、logistics88107us/tick87311us、Guest候補投影564197us、publish76085us。次の修正対象は整合検証と物流実行。施設決済0calls・在庫期限348usを根拠なく優先しない。純CPU・改善比較・性能受入・採用・単位完成ではない。",
|
||||
"remaining_deliverables": [
|
||||
{
|
||||
"id": "P23-01",
|
||||
@@ -15304,9 +15304,15 @@
|
||||
"bytes": 3820,
|
||||
"sha256": "9cc0b2bf9a24301fea02283b4f7cc0501fedc6201f635a79b38f5dcef0cddf8b",
|
||||
"scope": "Finite evidence; no unit acceptance"
|
||||
},
|
||||
{
|
||||
"path": "artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-actual-independent-review-r338-r02.json",
|
||||
"sha256_at_integration": "c0fcbaf02f18618a7f833c70f0f0cd3c1e517f5318061cca0158c9c288a6503a",
|
||||
"scope": "P23-02 finite current r333/library334 phase diagnostic only; no performance/adoption/unit/Windows acceptance",
|
||||
"linked_at_jst": "2026-10-12T14:09:47.603420+09:00"
|
||||
}
|
||||
],
|
||||
"progress_summary": "P23-02着手中。制作r32と選定済み実装親r274/library275は保持。最新未選定・未採用候補r333/library334は、親r326の在庫入力キー整列と経路コピーだけをnative化。未捕捉std確保例外をビルド前に修復。bridge1/link1、SDKcompile0、既存stage再利用。局所4工程404/0、Runtime150候補105808bytes・評価後11411840bytes原golden全文一致。S6 24/0、両whole15/0、after647全11487732bytes原oracle全文一致を独立有限受理。単一隣接観測1037100→1010883us(約2.5279%短縮)だが約1.01秒停止が残り安定性能・50ms/P95/D10は未受入。r204再構築は既非採用のため再実装なし。原9横断8はすべて未受入、Windows C08/X8のみblock、手動Ctrl保持wheel/左ボタン保持dragは延期・未達・非免除。正式9/着手19/予定60、30パッケージ/88成果、部分点なし、今回正式完了追加0。",
|
||||
"progress_summary": "P23-02着手中。制作r32と選定済み実装親r274/library275は保持。最新未選定・未採用候補r333/library334は、親r326の在庫入力キー整列と経路コピーだけをnative化。未捕捉std確保例外をビルド前に修復。bridge1/link1、SDKcompile0、既存stage再利用。局所4工程404/0、Runtime150候補105808bytes・評価後11411840bytes原golden全文一致。S6 24/0、両whole15/0、after647全11487732bytes原oracle全文一致を独立有限受理。単一隣接観測1037100→1010883us(約2.5279%短縮)だが約1.01秒停止が残り安定性能・50ms/P95/D10は未受入。r204再構築は既非採用のため再実装なし。原9横断8はすべて未受入、Windows C08/X8のみblock、手動Ctrl保持wheel/左ボタン保持dragは延期・未達・非免除。正式9/着手19/予定60、30パッケージ/88成果、部分点なし、今回正式完了追加0。\nr338-r02で現在未選定r333/library334の包含診断1回を独立有限受理。17/0、after647全11487732bytes原oracle一致、stage/source/default保持。enum再照合により旧phase3は建設・4は物流・5は施設完了と訂正。現在包含construction118776us/crosslinks118334us、logistics88107us/tick87311us、Guest候補投影564197us、publish76085us。次の修正対象は整合検証と物流実行。施設決済0calls・在庫期限348usを根拠なく優先しない。純CPU・改善比較・性能受入・採用・単位完成ではない。",
|
||||
"remaining_gaps": [
|
||||
"原9条件C01-C09と横断8条件X1-X8は全未受入。版付き全文条件はcurrent r337 matrixを参照。",
|
||||
"性能:候補約1.01秒同期停止。安定利益・50ms・P95・D10・実時間x3・通常OS操作追随は未達。",
|
||||
@@ -15315,8 +15321,16 @@
|
||||
"手動Ctrl保持wheelと左ボタン保持dragは延期、免除しない。",
|
||||
"未選定/未採用候補の有限成功を成果単位完了へ拡張しない。"
|
||||
],
|
||||
"updated_at_jst": "2026-10-12",
|
||||
"acceptance_matrix_reference": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-progress-disposition-r337.json"
|
||||
"updated_at_jst": "2026-10-12T14:09:47.603420+09:00",
|
||||
"acceptance_matrix_reference": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-current-progress-disposition-r337.json",
|
||||
"current_phase_diagnostic_r339": {
|
||||
"review": "artifacts/original-completion-2026-10-02/p23-02-current-phase-diagnostic-actual-independent-review-r338-r02.json",
|
||||
"sha256": "c0fcbaf02f18618a7f833c70f0f0cd3c1e517f5318061cca0158c9c288a6503a",
|
||||
"scope": "finite current instrumented whole647 only; no acceptance",
|
||||
"next_scope": "construction infrastructure crosslink validation and supply logistics tick",
|
||||
"unit_accepted": false,
|
||||
"performance_accepted": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "P23-03",
|
||||
@@ -15399,7 +15413,7 @@
|
||||
],
|
||||
"cross_cutting_acceptance_scope": "Completion requirements only, not achieved results. Apply each to relevant slices; non-applicable views require a recorded reason.",
|
||||
"initial_revision_state": "in_progress",
|
||||
"updated_at_jst": "2026-10-12"
|
||||
"updated_at_jst": "2026-10-12T14:09:47.603420+09:00"
|
||||
},
|
||||
{
|
||||
"id": "P24",
|
||||
|
||||
Reference in New Issue
Block a user