diff --git a/docs/plans/original-completion-2026-10-02/execution/p04-01/s2b/S2B_ROOT_RUN.md b/docs/plans/original-completion-2026-10-02/execution/p04-01/s2b/S2B_ROOT_RUN.md index c879446..7c3242c 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p04-01/s2b/S2B_ROOT_RUN.md +++ b/docs/plans/original-completion-2026-10-02/execution/p04-01/s2b/S2B_ROOT_RUN.md @@ -50,7 +50,9 @@ Readerは別PID/profileで各slotのjournal.log/manifest.json/thumbnail.png/worl Readerはさらに各1079 slotをfresh loadして通常clockの2tickを再現し、1080/1081全Runtimeと勤務差分、 同分guardを検査する。FACILITY_COMPLETION前後とAI_DECISIONS後のphase順と全snapshotもWriterに一致させる。 overtimeはunblock後のCOMPLETED/OFF_DUTYまで全Runtime一致を追加確認する。 -raw Dictionary getterと保存用canonical Operationsは別々に保存する。getter joinだけStringName/Stringとkey順差を明示し、 +実coordinatorの有効性/実nullと、Runtime保存Operationsのenabled/coordinator値を別々に記録する。 +実coordinator不在時はgetter適用外・raw getter未呼出しを明示し、架空のday summaryや診断結果を記録しない。 +実coordinatorが存在する場合だけraw Dictionary getterと保存用canonical Operationsを別々に保存する。getter joinだけStringName/Stringとkey順差を明示し、 型・値・欠落・配列順を検査する。全Runtime typed条件は緩和しない。 ## Rootの正式実行 @@ -96,3 +98,13 @@ worker実施記録: Python py_compile成功。GD grepは `:=` と禁止された private/default profileの読取りは0。製品1338のcheck-only成功・native成功を主張しない。 最初のworker planは `build/p04-s2b-worker-check-r01.json`。その後の本書/GD調整を含む最終pin確認には fresh `build/p04-s2b-worker-check-r02.json` を使用し、r01を上書きしない。 + +## repair15 nullable診断修正 + +`_capture`でOperationsCoordinatorをis_instance_validで分岐し、実nullと正式保存値`coordinator: {}`を区別する。 +全Runtime snapshotは無加工で保持する。fixtureでOperationsをenableせず、既存の境界・保存・replay判定を維持する。 +同GD全体を静的確認し、OperationsCoordinatorの直接呼出しはこの分岐内の2件のみ。 +reservation/request/task/shift、FileAccess、DirAccessには既存のnullガードがある。 +facility/definition/service/guest/worker、_inventory/_request/_worker/_taskの直接参照は既存fixtureの生成・取得成立が前提である。 +これらの前提が崩れた場合のnullリスクは残るが、任意機能Operationsの無効化による同種の無条件アクセスは他にない。 +本修正版のRoot fresh r02 nativeは未実測。workerはcode-ready提出のみで受入・readinessを確定しない。 diff --git a/docs/plans/original-completion-2026-10-02/execution/p04-01/s2b/p04_s2b_shift_probe.gd b/docs/plans/original-completion-2026-10-02/execution/p04-01/s2b/p04_s2b_shift_probe.gd index 69e1094..4d94cad 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p04-01/s2b/p04_s2b_shift_probe.gd +++ b/docs/plans/original-completion-2026-10-02/execution/p04-01/s2b/p04_s2b_shift_probe.gd @@ -221,16 +221,33 @@ func _writer_branch(branch: String) -> void: func _capture() -> Dictionary: var snapshot: Dictionary = _runtime.create_snapshot() - var raw_day: Dictionary = _runtime.operations_coordinator.get_day_summary(1) - var canonical_operations: Dictionary = _runtime.operations_coordinator.create_snapshot() - var canonical_day: Dictionary = {} - var day_count: int = 0 - for day: Dictionary in canonical_operations["day_summaries"]: - if int(day["day"]) == 1: - canonical_day = day - day_count += 1 - var getter_differences: Array = [] - _expect(_getter_join(raw_day, canonical_day, "$", getter_differences) and day_count == (0 if raw_day.is_empty() else 1), "raw getter joins canonical save contract without relaxing Runtime equality") + var saved_operations: Dictionary = snapshot[&"systems"][&"runtime"][&"operations"] + var coordinator: OperationsCoordinator = _runtime.operations_coordinator + var coordinator_present: bool = is_instance_valid(coordinator) + var getter_diagnostics: Dictionary = { + &"operations_enabled": saved_operations[&"enabled"], + &"saved_coordinator": saved_operations[&"coordinator"], + &"actual_coordinator_present": coordinator_present, + &"actual_coordinator_is_null": coordinator == null, + &"getter_applicable": coordinator_present, + &"raw_getter_called": false, + &"getter_status": "not_applicable: actual coordinator absent; raw getter not called", + } + if coordinator_present: + var raw_day: Dictionary = coordinator.get_day_summary(1) + var canonical_operations: Dictionary = coordinator.create_snapshot() + var canonical_day: Dictionary = {} + var day_count: int = 0 + for day: Dictionary in canonical_operations["day_summaries"]: + if int(day["day"]) == 1: + canonical_day = day + day_count += 1 + var getter_differences: Array = [] + _expect(_getter_join(raw_day, canonical_day, "$", getter_differences) and day_count == (0 if raw_day.is_empty() else 1), "raw getter joins canonical save contract without relaxing Runtime equality") + getter_diagnostics.merge({&"raw_getter_called": true, &"getter_status": "executed", + &"raw_day_getter": raw_day, &"canonical_operations": canonical_operations, + &"canonical_day1": canonical_day, &"getter_differences": getter_differences, + &"getter_bytes_equal": var_to_bytes(raw_day) == var_to_bytes(canonical_day)}, true) var ledger: Array = [] for entry: LedgerEntry in _runtime.economy_service.get_entries(): ledger.append(entry.to_dictionary()) var row: Dictionary = {&"seed": _seed, &"minute": _clock.absolute_minute, &"snapshot": snapshot, @@ -238,10 +255,9 @@ func _capture() -> Dictionary: &"source": _source, &"destination": _destination, &"task_id": _task_id, &"shift_id": _shift_id, &"target": _target, &"request_id": _request_id, &"guest_id": _guest_id, &"boundary": ShiftInstance.DAY_END}, - &"ledger": ledger, &"raw_day_getter": raw_day, - &"canonical_operations": canonical_operations, &"canonical_day1": canonical_day, - &"getter_differences": getter_differences, &"getter_bytes_equal": var_to_bytes(raw_day) == var_to_bytes(canonical_day), + &"ledger": ledger, &"commands": _commands.duplicate(true), &"command_results": _command_results.duplicate(true)} + row.merge(getter_diagnostics) # Raw getters retain their actual StringName keys and insertion order. They # are diagnostics, never substituted for the entire canonical Runtime save. if _case == "night_absent":