From 52ee6bec9e813607a33e21a1a743566dba706c12 Mon Sep 17 00:00:00 2001 From: Takeshi Date: Tue, 13 Oct 2026 03:14:47 +0900 Subject: [PATCH] docs: pin D05 daily boundary and paired elevator observations --- .../d05-decision-draft-r01/PROPOSAL.md | 8 ++ .../boundary-followup-r02.json | 89 +++++++++++++++++++ .../review-disposition-r01.json | 14 ++- 3 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 docs/plans/original-completion-2026-10-02/checkpoints/d05-decision-draft-r01/boundary-followup-r02.json diff --git a/docs/plans/original-completion-2026-10-02/checkpoints/d05-decision-draft-r01/PROPOSAL.md b/docs/plans/original-completion-2026-10-02/checkpoints/d05-decision-draft-r01/PROPOSAL.md index 5693bd1..9c41b6b 100644 --- a/docs/plans/original-completion-2026-10-02/checkpoints/d05-decision-draft-r01/PROPOSAL.md +++ b/docs/plans/original-completion-2026-10-02/checkpoints/d05-decision-draft-r01/PROPOSAL.md @@ -48,3 +48,11 @@ scope-audit.jsonに全施設定義と現default/明示値の区別を保存し EV: ElevatorService287以降の停止は安全な降車先の有無で分岐する。降車先ありなら乗車中人物をemergency arrivalとしてそこへ返し、未乗車要求は取消。降車先なしなら乗車中は車内保持し待機要求を取消する。これを原本の承認済み安全規則とはしない。判断候補は「現安全降車分岐を保持」と「停電時は常に車内保持」の比較になり、乗客/救護同伴/搬送荷物への反映を確認する必要がある。枯渇時全館停止に安全降車例外を許すかは未承認の論点である。 00:00: OperationsCoordinator1125のpayloadは終了期間をend-exclusive、日別精算IDをdaily-close:とする。TIME_BOUNDARIESが施設完了より先なのは現在の順序であり、帳簿帰属の全producer適合を証明していない。 + +## 境界処理の追加照合 r02 + +boundary-followup-r02.jsonに対象版のSHAと8関数の原文を固定した。決算APPLYは給与・維持費精算と期間財務の生成を行い、その関数本体には施設サービスの強制完了呼出しがない。FINALIZEという段階名だけから強制完了を推定しない。 + +確定財務は[start,end)を集計する。当日UIはcoordinatorの開始時刻から現在時刻までを含む現金流を表示し、確定日のsummaryは別に選択する。従って00:00ちょうどの完了売上の帰属は現順序と承認規約を区別して決める必要がある。給与は決算境界で現金記帳する一方、確定損益はnew_wages_totalを用いWAGE現金行を除外するため、UI現金支出と損益の数値を機械的に同値条件にしない。 + +EVのcancel_actorは乗車中の同伴組の単独取消を拒否する。停止時は同一の安全降車先について人物ごとのarrivalを生成し、Runtimeは人物ごとに位置を反映する。反映前提の欠損による分離は未再現であり、重大不具合として確定していない。通常操作・保存再開の受入を静的照合で代用しない。未承認・not_approval_ready・9/88は維持する。 diff --git a/docs/plans/original-completion-2026-10-02/checkpoints/d05-decision-draft-r01/boundary-followup-r02.json b/docs/plans/original-completion-2026-10-02/checkpoints/d05-decision-draft-r01/boundary-followup-r02.json new file mode 100644 index 0000000..f20b9c2 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/checkpoints/d05-decision-draft-r01/boundary-followup-r02.json @@ -0,0 +1,89 @@ +{ + "status": "static_observation_only", + "source_head": "3170e9c28a594fffc74be4f0f86ba7f96cbf8b12", + "product_modified": false, + "formal_acceptance_review": false, + "excerpts": [ + { + "path": "autoload/simulation_runtime.gd", + "function": "_apply_operations_daily_close", + "start_line": 2463, + "end_line": 2569, + "source_sha256": "d52a995ae715542bbc550f68d35889540658275d12e04ae0b21ac276f5843f39", + "excerpt": "func _apply_operations_daily_close(payload: Dictionary, token: Variant) -> Dictionary:\n\tif not token is Dictionary or token.is_empty() \\\n\t\t\tor not _operations_daily_payload_is_valid(payload):\n\t\treturn {&\"ok\": false, &\"reason\": &\"DAILY_CLOSE_PRECONDITION_FAILED\"}\n\tvar prepare_hook := _run_operations_test_boundary_hook(\n\t\t&\"DAILY_CLOSE\", payload, OPERATIONS_TEST_PREPARE_PHASE, token\n\t)\n\tif not bool(prepare_hook.get(&\"ok\", false)):\n\t\treturn prepare_hook\n\tvar day := int(payload[&\"day\"])\n\tvar preview := staff_service.preview_daily_payroll(day)\n\tif not bool(preview.get(&\"ok\", false)) \\\n\t\t\tor not preview.get(&\"rows\", null) is Array:\n\t\treturn {&\"ok\": false, &\"reason\": &\"PAYROLL_PREVIEW_FAILED\"}\n\tvar available_gold := economy_service.get_balance(PLAYER_CASH_ACCOUNT)\n\tvar remaining_gold := available_gold\n\tvar payments: Dictionary = {}\n\tvar expected_paid_total := 0\n\tvar previous_staff_id := \"\"\n\tfor raw_row: Variant in preview[&\"rows\"]:\n\t\tif not raw_row is Dictionary:\n\t\t\treturn {&\"ok\": false, &\"reason\": &\"PAYROLL_PREVIEW_INVALID\"}\n\t\tvar row: Dictionary = raw_row\n\t\tvar staff_id_value: Variant = row.get(&\"staff_id\", null)\n\t\tvar total_due_value: Variant = row.get(&\"total_due\", null)\n\t\tif typeof(staff_id_value) not in [TYPE_STRING, TYPE_STRING_NAME] \\\n\t\t\t\tor StringName(staff_id_value).is_empty() \\\n\t\t\t\tor typeof(total_due_value) != TYPE_INT or int(total_due_value) < 0:\n\t\t\treturn {&\"ok\": false, &\"reason\": &\"PAYROLL_PREVIEW_INVALID\"}\n\t\tvar staff_text := String(staff_id_value)\n\t\tif not previous_staff_id.is_empty() and staff_text <= previous_staff_id:\n\t\t\treturn {&\"ok\": false, &\"reason\": &\"PAYROLL_ORDER_INVALID\"}\n\t\tprevious_staff_id = staff_text\n\t\tvar payment := mini(int(total_due_value), remaining_gold)\n\t\tpayments[StringName(staff_id_value)] = payment\n\t\tremaining_gold -= payment\n\t\texpected_paid_total += payment\n\n\tvar settlement_id := StringName(\"payroll-day-%08d\" % day)\n\tvar settlement := staff_service.apply_daily_payroll_settlement(\n\t\tsettlement_id, day, payments\n\t)\n\tif not settlement.is_success() \\\n\t\t\tor int(settlement.details.get(&\"paid_total\", -1)) != expected_paid_total:\n\t\treturn {\n\t\t\t&\"ok\": false,\n\t\t\t&\"reason\": &\"PAYROLL_SETTLEMENT_FAILED\",\n\t\t\t&\"result\": settlement.to_dictionary(),\n\t\t}\n\tif expected_paid_total > 0:\n\t\tvar wage_payment := economy_service.transfer(\n\t\t\tPLAYER_CASH_ACCOUNT,\n\t\t\tWAGE_EXPENSE_ACCOUNT,\n\t\t\texpected_paid_total,\n\t\t\tint(payload[&\"boundary_minute\"]),\n\t\t\t&\"WAGE\",\n\t\t\tsettlement_id,\n\t\t\tStringName(\"operations.wage.day.%08d\" % day),\n\t\t\t&\"operations.payroll.settlement\",\n\t\t\t&\"\",\n\t\t\tfalse\n\t\t)\n\t\tif not wage_payment.is_success():\n\t\t\treturn {\n\t\t\t\t&\"ok\": false,\n\t\t\t\t&\"reason\": &\"WAGE_LEDGER_POST_FAILED\",\n\t\t\t\t&\"result\": wage_payment.to_dictionary(),\n\t\t\t}\n\t\tif not _stage_operations_economy_notification(wage_payment):\n\t\t\treturn {\n\t\t\t\t&\"ok\": false,\n\t\t\t\t&\"reason\": &\"WAGE_NOTIFICATION_STAGE_FAILED\",\n\t\t\t\t&\"result\": wage_payment.to_dictionary(),\n\t\t\t}\n\tvar upkeep_result := _settle_upkeep_through(int(payload[&\"boundary_minute\"]))\n\tif not bool(upkeep_result[&\"ok\"]):\n\t\treturn upkeep_result\n\tvar upkeep_paid := int(upkeep_result[&\"paid_total\"])\n\tvar financials := _build_operations_daily_financials(\n\t\tint(payload[&\"period_start_minute\"]),\n\t\tint(payload[&\"period_end_minute_exclusive\"]),\n\t\tint(preview.get(&\"new_wages_total\", -1)),\n\t\tpreview[&\"rows\"]\n\t)\n\tif not bool(financials.get(&\"ok\", false)):\n\t\treturn financials\n\tvar arrears_total := int(settlement.details.get(&\"unpaid_after_total\", -1))\n\tif arrears_total < 0 \\\n\t\t\tor arrears_total != _staff_payroll_arrears_total(staff_service) \\\n\t\t\tor economy_service.get_balance(PLAYER_CASH_ACCOUNT) != available_gold - expected_paid_total - upkeep_paid \\\n\t\t\tor int(_state.get_resource(&\"gold\")) != economy_service.get_balance(PLAYER_CASH_ACCOUNT) \\\n\t\t\tor not bool(economy_service.validate_ledger().get(&\"ok\", false)) \\\n\t\t\tor not bool(staff_service.validate_invariants().get(&\"ok\", false)):\n\t\treturn {&\"ok\": false, &\"reason\": &\"DAILY_CLOSE_POSTCONDITION_FAILED\"}\n\tvar settlement_report := settlement.details.duplicate(true)\n\tsettlement_report[&\"upkeep_arrears_total\"] = upkeep_settlement.get_arrears_total()\n\tsettlement_report[&\"arrears_total\"] = arrears_total + int(settlement_report[&\"upkeep_arrears_total\"])\n\treturn {\n\t\t&\"ok\": true,\n\t\t&\"category_totals\": financials[&\"category_totals\"],\n\t\t&\"reconciliation_difference\": financials[&\"reconciliation_difference\"],\n\t\t&\"facility_profit_loss\": financials[&\"facility_profit_loss\"],\n\t\t&\"anomalies\": financials[&\"anomalies\"],\n\t\t&\"settlement\": settlement_report,\n\t}\n\n\n" + }, + { + "path": "autoload/simulation_runtime.gd", + "function": "_build_operations_daily_financials", + "start_line": 2570, + "end_line": 2715, + "source_sha256": "d52a995ae715542bbc550f68d35889540658275d12e04ae0b21ac276f5843f39", + "excerpt": "func _build_operations_daily_financials(\n\tperiod_start: int,\n\tperiod_end_exclusive: int,\n\tnew_wages_total: int,\n\tpayroll_rows: Array\n) -> Dictionary:\n\tif period_start < 0 or period_end_exclusive <= period_start or new_wages_total < 0:\n\t\treturn {&\"ok\": false, &\"reason\": &\"DAILY_FINANCIAL_PERIOD_INVALID\"}\n\tif not _loan_principal_ledger_is_valid(economy_service):\n\t\treturn {&\"ok\": false, &\"reason\": &\"INVALID_LOAN_PRINCIPAL_LEDGER\"}\n\tvar category_totals := {\n\t\t&\"revenue\": 0,\n\t\t&\"refunds\": 0,\n\t\t&\"cost_of_goods\": 0,\n\t\t&\"wages\": new_wages_total,\n\t\t&\"maintenance\": 0,\n\t\t&\"utilities\": 0,\n\t\t&\"taxes_and_interest\": 0,\n\t\t&\"fines\": 0,\n\t\t&\"construction_cash_flow\": 0,\n\t}\n\tvar facility_rows: Dictionary = {}\n\tvar excluded_categories: Array[StringName] = [\n\t\t&\"EVENT_COST_RESERVED\", &\"EVENT_COST_RELEASED\", &\"INITIALIZATION\",\n\t\t&\"TRANSFER\", &\"GENERATION\", &\"DESTRUCTION\", &\"MIGRATION\",\n\t\t&\"SERVICE_CASH_SWEEP\", &\"WAGE\", &\"MAINTENANCE_PAYMENT\",\n\t]\n\tvar category_mapping := {\n\t\t&\"SERVICE_SALE\": &\"revenue\",\n\t\t&\"REFUND\": &\"refunds\",\n\t\t&\"CONSTRUCTION\": &\"construction_cash_flow\",\n\t\t&\"CONSTRUCTION_REFUND\": &\"construction_cash_flow\",\n\t\t&\"AUTHORITY_FINE\": &\"fines\",\n\t\t&\"OPERATING_EXPENSE\": &\"cost_of_goods\",\n\t\t&\"STAFF_SIGNING_COST\": &\"cost_of_goods\",\n\t\t&\"EVENT_ACTION\": &\"cost_of_goods\",\n\t\t&\"EVENT_COST_COMMITTED\": &\"cost_of_goods\",\n\t\t&\"DEFENSE_SKILL_COST\": &\"cost_of_goods\",\n\t\t&\"MAINTENANCE_ACCRUAL\": &\"maintenance\",\n\t\t&\"LOAN_PRINCIPAL_BORROWED\": &\"financing_principal_inflows\",\n\t\t&\"LOAN_PRINCIPAL_REPAID\": &\"financing_principal_outflows\",\n\t}\n\tvar operating_refund_total := 0\n\tfor entry: LedgerEntry in economy_service.get_entries():\n\t\tif entry.absolute_minute < period_start \\\n\t\t\t\tor entry.absolute_minute >= period_end_exclusive:\n\t\t\tcontinue\n\t\tif entry.category in excluded_categories:\n\t\t\tcontinue\n\t\tif entry.category == &\"OPERATING_REFUND\":\n\t\t\toperating_refund_total += entry.amount\n\t\t\tcontinue\n\t\tif not category_mapping.has(entry.category):\n\t\t\treturn {\n\t\t\t\t&\"ok\": false,\n\t\t\t\t&\"reason\": &\"UNKNOWN_LEDGER_CATEGORY\",\n\t\t\t\t&\"category\": entry.category,\n\t\t\t\t&\"transaction_id\": entry.transaction_id,\n\t\t\t}\n\t\tvar category: StringName = category_mapping[entry.category]\n\t\tcategory_totals[category] = int(category_totals.get(category, 0)) + entry.amount\n\t\tif not entry.source_entity_id.is_empty() \\\n\t\t\t\tand (facility_service.has_instance(entry.source_entity_id) or entry.category == &\"MAINTENANCE_ACCRUAL\") \\\n\t\t\t\tand category not in [&\"construction_cash_flow\", &\"financing_principal_inflows\", &\"financing_principal_outflows\"]:\n\t\t\tif not facility_rows.has(entry.source_entity_id):\n\t\t\t\tfacility_rows[entry.source_entity_id] = {\n\t\t\t\t\t&\"revenue\": 0, &\"expenses\": 0, &\"net_profit\": 0,\n\t\t\t\t}\n\t\t\tvar facility_row: Dictionary = facility_rows[entry.source_entity_id]\n\t\t\tif category == &\"revenue\":\n\t\t\t\tfacility_row[&\"revenue\"] = int(facility_row[&\"revenue\"]) + entry.amount\n\t\t\telse:\n\t\t\t\tfacility_row[&\"expenses\"] = int(facility_row[&\"expenses\"]) + entry.amount\n\tvar anomalies: Array[Dictionary] = []\n\tvar wage_allocation := _allocate_operations_wages_to_facilities(\n\t\tperiod_start,\n\t\tperiod_end_exclusive,\n\t\tnew_wages_total,\n\t\tpayroll_rows,\n\t\tfacility_rows\n\t)\n\tif not bool(wage_allocation.get(&\"ok\", false)):\n\t\treturn wage_allocation\n\tanomalies.append_array(wage_allocation[&\"anomalies\"])\n\tvar operating_refund_offset := mini(\n\t\toperating_refund_total,\n\t\tint(category_totals[&\"cost_of_goods\"])\n\t)\n\tcategory_totals[&\"cost_of_goods\"] = int(category_totals[&\"cost_of_goods\"]) \\\n\t\t- operating_refund_offset\n\tvar excess_operating_refund := operating_refund_total - operating_refund_offset\n\tif excess_operating_refund > 0:\n\t\tcategory_totals[&\"revenue\"] = int(category_totals[&\"revenue\"]) \\\n\t\t\t+ excess_operating_refund\n\t\tanomalies.append({\n\t\t\t&\"code\": &\"OPERATING_REFUND_EXCEEDS_PERIOD_COST\",\n\t\t\t&\"refund_total\": operating_refund_total,\n\t\t\t&\"cost_offset\": operating_refund_offset,\n\t\t\t&\"excess_revenue\": excess_operating_refund,\n\t\t})\n\tfor facility_id: StringName in _sorted_name_keys(facility_rows):\n\t\tvar row: Dictionary = facility_rows[facility_id]\n\t\trow[&\"net_profit\"] = int(row[&\"revenue\"]) - int(row[&\"expenses\"])\n\tvar allocation_rows: Array[Dictionary] = []\n\tfor facility_id: StringName in _sorted_name_keys(\n\t\twage_allocation[&\"allocated_by_facility\"]\n\t):\n\t\tallocation_rows.append({\n\t\t\t&\"facility_id\": String(facility_id),\n\t\t\t&\"amount\": int(wage_allocation[&\"allocated_by_facility\"][facility_id]),\n\t\t})\n\tvar unallocated_rows: Array[Dictionary] = []\n\tfor staff_id: StringName in _sorted_name_keys(\n\t\twage_allocation[&\"unallocated_by_staff\"]\n\t):\n\t\tunallocated_rows.append({\n\t\t\t&\"staff_id\": String(staff_id),\n\t\t\t&\"amount\": int(wage_allocation[&\"unallocated_by_staff\"][staff_id]),\n\t\t})\n\tvar profit_loss_facility_ids: Array[String] = []\n\tfor facility_id: StringName in _sorted_name_keys(facility_rows):\n\t\tprofit_loss_facility_ids.append(String(facility_id))\n\tanomalies.append({\n\t\t&\"code\": &\"WAGE_ALLOCATION_EVIDENCE\",\n\t\t&\"version\": 1,\n\t\t&\"new_wages_total\": new_wages_total,\n\t\t&\"allocated_total\": int(wage_allocation[&\"allocated_total\"]),\n\t\t&\"unallocated_total\": int(wage_allocation[&\"unallocated_total\"]),\n\t\t&\"allocations\": allocation_rows,\n\t\t&\"unallocated_by_staff\": unallocated_rows,\n\t\t&\"facility_ids\": profit_loss_facility_ids,\n\t})\n\tvar daily_summary := economy_service.get_daily_summary(period_start / 1_440 + 1)\n\tif daily_summary.is_empty():\n\t\treturn {&\"ok\": false, &\"reason\": &\"LEDGER_PERIOD_SUMMARY_MISSING\"}\n\tvar difference := int(daily_summary.get(&\"total_debit\", 0)) \\\n\t\t- int(daily_summary.get(&\"total_credit\", 0))\n\treturn {\n\t\t&\"ok\": true,\n\t\t&\"category_totals\": category_totals,\n\t\t&\"reconciliation_difference\": difference,\n\t\t&\"facility_profit_loss\": facility_rows,\n\t\t&\"anomalies\": anomalies,\n\t}\n\n\n" + }, + { + "path": "scripts/ui/operating_ledger_panel.gd", + "function": "get_report", + "start_line": 65, + "end_line": 111, + "source_sha256": "652b3c98c4cdc707831a19ba1e91e23f21895f0fbf3ece40826e03df3b656a1d", + "excerpt": "func get_report() -> Dictionary:\n\tif _runtime == null:\n\t\treturn {}\n\tvar minute: int = _clock.absolute_minute\n\tvar business_day := minute / 1440 + 1\n\tvar start := (business_day - 1) * 1440\n\tif _runtime.operations_coordinator != null:\n\t\tbusiness_day = _runtime.operations_coordinator.get_open_financial_day()\n\t\tstart = _runtime.operations_coordinator.get_financial_period_start(business_day)\n\tvar inflow := 0\n\tvar outflow := 0\n\tvar construction_outflow := 0\n\tvar wage_outflow := 0\n\tvar upkeep_outflow := 0\n\tfor entry: LedgerEntry in _runtime.economy_service.get_entries():\n\t\tif entry.absolute_minute < start or entry.absolute_minute > minute or entry.category == &\"INITIALIZATION\":\n\t\t\tcontinue\n\t\tif entry.debit_account == &\"PLAYER_CASH\":\n\t\t\tinflow += entry.amount\n\t\tif entry.credit_account == &\"PLAYER_CASH\":\n\t\t\toutflow += entry.amount\n\t\t\tif entry.category == &\"CONSTRUCTION\":\n\t\t\t\tconstruction_outflow += entry.amount\n\t\t\telif entry.category == &\"MAINTENANCE_PAYMENT\":\n\t\t\t\tupkeep_outflow += entry.amount\n\t\t\telif entry.category == &\"WAGE\":\n\t\t\t\twage_outflow += entry.amount\n\tvar summaries: Array[Dictionary] = []\n\tif _runtime.operations_coordinator != null:\n\t\tsummaries = _runtime.operations_coordinator.get_day_summaries()\n\tvar selected: Dictionary = {}\n\tfor summary: Dictionary in summaries:\n\t\tif int(summary.get(&\"day\", -1)) == _selected_day:\n\t\t\tselected = summary\n\tif selected.is_empty() and not summaries.is_empty():\n\t\tselected = summaries.back()\n\treturn {\n\t\t&\"business_day\": business_day, &\"period_start\": start,\n\t\t&\"cash\": _runtime.economy_service.get_balance(&\"PLAYER_CASH\"),\n\t\t&\"cash_in\": inflow, &\"cash_out\": outflow, &\"cash_net\": inflow - outflow,\n\t\t&\"construction_cash_out\": construction_outflow, &\"wage_cash_out\": wage_outflow,\n\t\t&\"upkeep_cash_out\": upkeep_outflow,\n\t\t&\"upkeep_arrears\": _runtime.upkeep_settlement.get_arrears_total(),\n\t\t&\"closed_days\": summaries, &\"selected_close\": selected.duplicate(true),\n\t}\n\n\n" + }, + { + "path": "scripts/transport/elevator_service.gd", + "function": "cancel_actor", + "start_line": 236, + "end_line": 251, + "source_sha256": "cea09dd9204551c26b31b30cd3aa847cc77e3b75fdac31662b9694a95fb3580c", + "excerpt": "func cancel_actor(actor_id: StringName) -> bool:\n\tvar partner: StringName = _trips.get(actor_id, {}).get(&\"companion_id\", &\"\")\n\tif not partner.is_empty():\n\t\tif _trips[actor_id][&\"state\"] == PathService.ELEVATOR_REQUEST_BOARDED:\n\t\t\tlast_error = \"An onboard pair must alight together at a real landing.\"\n\t\t\treturn false\n\t\tvar path_before := _path.create_snapshot()\n\t\tvar trips_before := _trips.duplicate(true)\n\t\tif not _cancel_single(actor_id) or not _cancel_single(partner):\n\t\t\t_path.restore_snapshot(path_before)\n\t\t\t_trips = trips_before\n\t\t\treturn false\n\t\treturn true\n\treturn _cancel_single(actor_id)\n\n\n" + }, + { + "path": "scripts/transport/elevator_service.gd", + "function": "_apply_operational", + "start_line": 291, + "end_line": 333, + "source_sha256": "cea09dd9204551c26b31b30cd3aa847cc77e3b75fdac31662b9694a95fb3580c", + "excerpt": "func _apply_operational(shaft_id: StringName, operational: bool, minute: int) -> Array[Dictionary]:\n\tvar arrivals: Array[Dictionary] = []\n\tif not _shafts.has(shaft_id) or minute < _minute or minute > _minute + 1:\n\t\tlast_error = \"Unknown shaft or invalid operational change time.\"\n\t\treturn arrivals\n\tvar car: Dictionary = _shafts[shaft_id]\n\tif car[&\"operational\"] == operational: return arrivals\n\tif not operational:\n\t\tvar landing: Variant = _nearest_valid_stop(car)\n\t\tif landing == null and not (car[&\"boarded\"] as Array).is_empty():\n\t\t\tlast_error = \"Occupied elevator has no safe landing; cabin remains held.\"\n\t\t\t# No legal teleportation destination exists. The caller must repair a\n\t\t\t# landing; movement remains held and requests remain owned.\n\t\t\tcar[&\"operational\"] = false\n\t\t\tfor actor_id: StringName in _names(_trips):\n\t\t\t\tif not _trips.has(actor_id): continue\n\t\t\t\tvar waiting: Dictionary = _trips[actor_id]\n\t\t\t\tif waiting[&\"shaft_id\"] == shaft_id and waiting[&\"state\"] == PathService.ELEVATOR_REQUEST_QUEUED and _cancel_single(actor_id):\n\t\t\t\t\tarrivals.append({&\"actor_id\": actor_id, &\"request_id\": waiting[&\"request_id\"], &\"cell\": waiting[&\"from\"], &\"emergency\": false, &\"cancelled\": true})\n\t\t\t_publish_cabin(car)\n\t\t\treturn arrivals\n\t\tfor actor_id: StringName in _names(_trips):\n\t\t\tvar trip: Dictionary = _trips[actor_id]\n\t\t\tif trip[&\"shaft_id\"] != shaft_id: continue\n\t\t\tvar boarded: bool = trip[&\"state\"] == PathService.ELEVATOR_REQUEST_BOARDED\n\t\t\tif boarded:\n\t\t\t\tif not _path.complete_elevator_request(trip[&\"connector_id\"], trip[&\"request_id\"]): continue\n\t\t\telse:\n\t\t\t\tif not _path.cancel_elevator_request(trip[&\"connector_id\"], trip[&\"request_id\"]): continue\n\t\t\tarrivals.append({&\"actor_id\": actor_id, &\"request_id\": trip[&\"request_id\"],\n\t\t\t\t&\"cell\": landing if boarded else trip[&\"from\"], &\"emergency\": boarded, &\"cancelled\": not boarded})\n\t\t\t_trips.erase(actor_id)\n\t\tcar[&\"boarded\"] = []\n\t\tif landing != null: car[&\"current_floor\"] = (landing as Vector3i).y\n\t\t_idle(car)\n\tif operational and car[&\"phase\"] != &\"IDLE\":\n\t\tcar[&\"phase_started_at\"] = _minute - (int(car[&\"phase_total_minutes\"]) - int(car[&\"remaining_minutes\"]))\n\tcar[&\"operational\"] = operational\n\t_publish_cabin(car)\n\tlast_error = \"\"\n\treturn arrivals\n\n\n" + }, + { + "path": "autoload/simulation_runtime.gd", + "function": "_apply_elevator_arrivals", + "start_line": 12700, + "end_line": 12723, + "source_sha256": "d52a995ae715542bbc550f68d35889540658275d12e04ae0b21ac276f5843f39", + "excerpt": "func _apply_elevator_arrivals(arrivals: Array[Dictionary], minute: int) -> void:\n\tfor arrival: Dictionary in arrivals:\n\t\tvar actor_id := StringName(arrival[&\"actor_id\"])\n\t\tif not path_service.has_actor_projection(actor_id):\n\t\t\tcontinue\n\t\tvar previous: Vector3i = path_service.get_actor_projected_cell(actor_id)\n\t\tvar cell: Vector3i = arrival[&\"cell\"]\n\t\tvar entity_id := StringName(String(actor_id).trim_prefix(\"guest:\").trim_prefix(\"staff:\"))\n\t\tvar guest := guest_service.get_guest(entity_id) if String(actor_id).begins_with(\"guest:\") else null\n\t\tvar staff := staff_service.get_staff(entity_id) if String(actor_id).begins_with(\"staff:\") else null\n\t\tif guest == null and staff == null:\n\t\t\t_report_path_integration_failure(actor_id, entity_id, &\"elevator\", previous)\n\t\t\tcontinue\n\t\tif not path_service.project_actor_position(actor_id, cell, minute):\n\t\t\t_report_path_integration_failure(actor_id, entity_id, &\"elevator\", previous)\n\t\t\tcontinue\n\t\tif guest != null:\n\t\t\tguest_service.record_path_success(guest.guest_id, cell, minute)\n\t\telse:\n\t\t\tstaff.current_cell = cell\n\t\t_movement_credits[actor_id] = {&\"credit\": 0, &\"updated_at\": minute}\n\t\t_publish_actor_event(&\"ELEVATOR_ARRIVED\", &\"elevators\", [actor_id, entity_id], arrival)\n\n\n" + }, + { + "path": "scripts/economy/economy_service.gd", + "function": "aggregate_categories", + "start_line": 506, + "end_line": 514, + "source_sha256": "95aedd0a0421c93e8fa39f0f76fa890cd0a46905d9a25c88c8b17c4d6d47728e", + "excerpt": "func aggregate_categories(from_minute: int, to_minute_exclusive: int) -> Dictionary:\n\tvar totals: Dictionary = {}\n\tfor entry: LedgerEntry in _ledger:\n\t\tif entry.absolute_minute < from_minute or entry.absolute_minute >= to_minute_exclusive:\n\t\t\tcontinue\n\t\ttotals[entry.category] = int(totals.get(entry.category, 0)) + entry.amount\n\treturn _sorted_dictionary(totals)\n\n\n" + }, + { + "path": "scripts/operations/operations_coordinator.gd", + "function": "create_snapshot", + "start_line": 620, + "end_line": 712, + "source_sha256": "871a248ee101b6df543fd5cf0440b5d4b0f02c21fa145a99f0687888c1bc6f90", + "excerpt": "func create_snapshot() -> Dictionary:\n\tif not _initialization_valid:\n\t\tlast_error = \"Operations coordinator initialization is invalid.\"\n\t\treturn {}\n\tif _notification_delivery_deferred or not _notification_queue.is_empty():\n\t\tlast_error = \"Deferred Operations notifications must be resolved before snapshotting.\"\n\t\treturn {}\n\tvar field_cache: Dictionary = {}\n\tvar internal_report := _snapshot_root_report({\n\t\t&\"config\": _config,\n\t\t&\"demand_profiles\": _demand_profiles,\n\t\t&\"arrival_carry\": _arrival_carry,\n\t\t&\"demand_history\": _demand_history,\n\t\t&\"arrival_reports\": _arrival_reports,\n\t\t&\"day_summaries\": _day_summaries,\n\t\t&\"morning_reports\": _morning_reports,\n\t\t&\"alerts\": _alerts,\n\t\t&\"quarantine_report\": _quarantine_report,\n\t}, field_cache, true)\n\tvar shape_error := _internal_snapshot_shape_error()\n\tif not bool(internal_report[&\"ok\"]) or not shape_error.is_empty():\n\t\tlast_error = \"Operations state cannot be serialized: %s\" % [\n\t\t\tinternal_report[&\"code\"] if not bool(internal_report[&\"ok\"]) else shape_error\n\t\t]\n\t\treturn {}\n\tvar saved_profiles: Array[Dictionary] = []\n\tvar saved_carry: Array[Dictionary] = []\n\tfor key: String in _sorted_string_keys(_demand_profiles):\n\t\tvar profile: Dictionary = _demand_profiles[key]\n\t\tsaved_profiles.append({\n\t\t\t&\"facility_tag\": String(profile[&\"facility_tag\"]),\n\t\t\t&\"guest_class\": String(profile[&\"guest_class\"]),\n\t\t\t&\"time_band\": String(profile[&\"time_band\"]),\n\t\t\t&\"components\": _string_key_dictionary(profile[&\"components\"]),\n\t\t\t&\"demand_index\": int(profile[&\"demand_index\"]),\n\t\t\t&\"last_evaluated_at\": int(profile[&\"last_evaluated_at\"]),\n\t\t})\n\t\tsaved_carry.append({\n\t\t\t&\"facility_tag\": String(profile[&\"facility_tag\"]),\n\t\t\t&\"guest_class\": String(profile[&\"guest_class\"]),\n\t\t\t&\"time_band\": String(profile[&\"time_band\"]),\n\t\t\t&\"numerator\": int(_arrival_carry.get(key, 0)),\n\t\t})\n\n\tvar saved_mornings: Array[Dictionary] = []\n\tfor day: int in _sorted_int_keys(_morning_reports):\n\t\tsaved_mornings.append(_morning_reports[day])\n\tvar saved_days: Array[Dictionary] = []\n\tfor day: int in _sorted_int_keys(_day_summaries):\n\t\tsaved_days.append(_day_summaries[day])\n\n\t# These borrowed containers never leave this synchronous method. The final\n\t# canonical conversion recursively creates owned dictionaries and arrays.\n\tvar raw_snapshot := {\n\t\t&\"schema_version\": SNAPSHOT_VERSION,\n\t\t&\"legacy_calendar_last_day\": _legacy_calendar_last_day,\n\t\t&\"legacy_history_last_day\": _legacy_history_last_day,\n\t\t&\"legacy_principal_profit_last_day\": _legacy_principal_profit_last_day,\n\t\t&\"origin_minute\": _origin_minute,\n\t\t&\"current_minute\": current_minute,\n\t\t&\"config\": _string_key_dictionary(_config),\n\t\t&\"demand_profiles\": saved_profiles,\n\t\t&\"arrival_carry\": saved_carry,\n\t\t&\"demand_history\": _demand_history,\n\t\t&\"arrival_reports\": _arrival_reports,\n\t\t&\"day_summaries\": saved_days,\n\t\t&\"morning_reports\": saved_mornings,\n\t\t&\"alerts\": _alerts,\n\t\t&\"processed_demand_minutes\": _sorted_int_keys(_processed_demand_minutes),\n\t\t&\"processed_arrival_minutes\": _sorted_int_keys(_processed_arrival_minutes),\n\t\t&\"population_count\": _population_count,\n\t\t&\"arrears_total\": _arrears_total,\n\t\t&\"consecutive_insolvency_count\": _consecutive_insolvency_count,\n\t\t&\"terminal_state\": String(_terminal_state),\n\t\t&\"pause_requested\": pause_requested,\n\t\t&\"next_arrival_plan_sequence\": _next_arrival_plan_sequence,\n\t\t&\"next_guest_sequence\": _next_guest_sequence,\n\t\t&\"arrival_plan_high_water\": _arrival_plan_high_water,\n\t\t&\"guest_high_water\": _guest_high_water,\n\t\t&\"fair_rotation_counter\": _fair_rotation_counter,\n\t\t&\"pending_boundary_minute\": _pending_boundary_minute,\n\t\t&\"deferred_boundary_minute\": _deferred_boundary_minute,\n\t\t&\"pause_reason\": String(_pause_reason),\n\t\t&\"external_quarantined\": _external_quarantined,\n\t\t&\"quarantine_report\": _quarantine_report,\n\t}\n\tvar tree_report := _snapshot_root_report(raw_snapshot, field_cache, false)\n\tif not bool(tree_report[&\"ok\"]):\n\t\tlast_error = \"Operations state cannot be serialized: %s\" % tree_report[&\"code\"]\n\t\treturn {}\n\treturn tree_report[&\"value\"]\n\n\n" + } + ], + "findings": [ + { + "id": "daily-close-label", + "observation": "The runtime APPLY callback settles payroll and upkeep and builds financials. No direct pending facility service completion is called in that function.", + "limit": "Static direct-body observation; not a native same-minute acceptance result." + }, + { + "id": "period-boundary", + "observation": "Economy aggregation and runtime closed financials exclude period_end. Open-day UI includes the current minute and obtains start from the coordinator.", + "limit": "Current behavior; same-minute sale attribution remains an unapproved D05 policy choice." + }, + { + "id": "elevator-pair", + "observation": "cancel_actor rejects cancelling a boarded companion pair. Operational stop emits per-actor arrivals at one chosen landing; runtime applies arrivals per actor and can skip missing projections.", + "limit": "Pair separation or missing projections have not been reproduced. A per-actor failure remains a hypothesis; no defect is declared." + } + ] +} diff --git a/docs/plans/original-completion-2026-10-02/checkpoints/d05-decision-draft-r01/review-disposition-r01.json b/docs/plans/original-completion-2026-10-02/checkpoints/d05-decision-draft-r01/review-disposition-r01.json index 9c1295a..8b1be9a 100644 --- a/docs/plans/original-completion-2026-10-02/checkpoints/d05-decision-draft-r01/review-disposition-r01.json +++ b/docs/plans/original-completion-2026-10-02/checkpoints/d05-decision-draft-r01/review-disposition-r01.json @@ -12,5 +12,17 @@ "rescue pair separation on emergency landing", "missing actor projection on elevator arrival" ], - "product_changed": false + "product_changed": false, + "boundary_followup": "boundary-followup-r02.json", + "boundary_followup_sha256": "3f45ddad5adb8e3a5db5cecbc686267b31be85f0bd76283c97e382bf2ec49e88", + "resolved_static_questions": [ + "Actual daily-close callback has no direct facility completion call.", + "Closed financial period excludes its end; current open-day UI includes current minute.", + "Boarded paired cancellation is explicitly rejected." + ], + "remaining_followup": [ + "Verify persisted day/ledger identity and same-candidate resume behavior.", + "Map all fee producers to approved authority rather than treating implementation as approval.", + "Complete service-kind/manual closure and logistics scopes, then review finite decision alternatives." + ] }