13 KiB
13 KiB
P16-01-DISMISS 実装の記録(実 Opus の実装担当、2026-10-24)
- 仕様: 同じフォルダの
SPEC.md(登録版 r04。main0b59d7cに固定。Runner のspec_sha256は14efffd9…e6b)。出典はPROVENANCE.json。 - 原本への加算は 0。原単位 P16-01・P16-03、
AR.staff.dismissal_severanceの package P05 の原 work・原 AC は閉じない(SPEC §8)。 - 管理の記録は
artifacts/original-completion-2026-10-02/p16-01-dismiss-control-r01/にある(git の外)。 - 変えた製品のファイル:
autoload/simulation_runtime.gd・scripts/economy/finance_policy.gd・scripts/ui/staff_management_panel.gd。scripts/staff/staff_service.gdとscenes/main/main.gdは変えていない(§1・§4)。
1. 命令と判定の順(SPEC §4.1)
SimulationRuntimeに通常の commanddismiss_staff(payloadstaff_id)を足した(_execute_dismiss_staff)。- (a) 運営の終了(
BANKRUPT)と (b) 同じ key の再送(DUPLICATE_IDEMPOTENCY_KEY)は、今のsubmit_commandとCommandQueue.enqueueのまま受付の前・受付で止まる(R5・R6、5.b)。 - (c) executor は、状態を変える前に次の順で確かめる。どれかに当たれば、その理由で失敗の結果を返す(5.c)。
- payload に
staff_idが無い →INVALID_PAYLOAD - 職員が居ない →
NOT_FOUND(R4) UNIQUE→UNIQUE(R1。今のremove_staffと同じ code と文)FREE_HIREでない(ADULT_CONTRACT)→NOT_GENERAL_EMPLOYEE(R7)- 外部が持つ作業(仕入れの物流)→
EXTERNAL_TASK(R2。今のremove_staffと同じ code と文) - 終わっていない襲撃の防衛者 →
DEFENSE_LOCKED(R9。Root の一時の境界) - 救護の組が一緒に昇降機に乗っている →
RESCUE_PAIR_ABOARD(§3 の決め) - 表金と裏金の合計が退職金に足りない →
INSUFFICIENT_FUNDS(R8)
- payload に
- (d) 全て通れば、次を1つの操作として行う。
- 既存の削除の契約
StaffService.remove_staff(staff_id, &"DISMISSED", true, 分)。作業の予約を解けない時(R3)は、この契約が何も変えずに拒む(在庫の解放は自分で巻き戻す)。理由はRESERVATION_RELEASE_FAILED、文は今の契約のまま。 - 退職金の記帳(§2)。
- 救護の後始末(§3)、施設の人員の投影(
_sync_facility_staffing)、出来事の欠けた職員の扱い(event_service.audit_actor_availability)。
- 既存の削除の契約
- 1 の後で失敗すれば、命令の前の写し(staff・inventory・path・elevators・移動の残り・出来事・ID・帳簿・Gold の写し)に全て戻して、
TRANSACTION_APPLY_FAILEDを返す。試験は、退職金の記帳の key を先に使っておく fixture でこの経路を通し、5.c の比べ方で何も変わらないことを確かめる。 - 画面と試験のための読むだけの関数
get_staff_dismissal_preview(staff_id)を足した(解雇できるか・理由・退職金・未払い・開き直す作業・表金・資金の合計)。get_staff_management_reportの各行にdismissalとして載る。R3 は前もって分からないので、押した後に命令が拒み、理由を出す。
2. 退職金(SPEC §3.5・§3.6、A14)
FinancePolicyにSEVERANCE_EXPENSE(口座STAFF_SEVERANCE_EXPENSE)・SEVERANCE_CATEGORY(区分STAFF_SEVERANCE)・SEVERANCE_DAYS(3)・severance(日給)を足した。額はget_effective_daily_wage() × 3。- 記帳は命令の時刻に、1つの取引(idempotency key
staff.severance.<command の ID>)で行う。- 表金で足りない分: 裏金 → 表金の補填(区分
BACK_FUND_TOP_UP、P05-02 の返済と同じ形)。 - 退職金: 表金 →
STAFF_SEVERANCE_EXPENSE(区分STAFF_SEVERANCE、source は職員の ID)。
- 表金で足りない分: 裏金 → 表金の補填(区分
- 日次決算の照合では
cost_of_goods(画面「運営費(仕入れ・契約金等)」)に入れる。写した表は_build_operations_daily_financialsと_operations_expected_category_totalsの2つ。施設ごとの表は、施設でない source を読まないので変えていない。補填は fund report v2 のback_top_up(その日の全ての補填)に入る。 - 旧セーブ:
FinancePolicy.prepare_accountsの最後で、退職金の口座が無ければ空の口座として足す(A12 の5つの口座とは別に判定する。P05-02 の後・P16 の前のセーブにも足す)。口座があって負を許す設定なら拒む。 - 解雇の前に貯まった未払いの給与は、今の契約のまま
_departed_payrollに保持され、次の 00:00 の締めで払われる(A09 の補填を含む)。解雇の日の日給は今の給与の契約のまま(締めの時に雇用中の職員だけ)。
3. 後始末(SPEC §6.2・§6.2.1)
- 勤務・予定・配置は
remove_staff、経路の actor・昇降機の予約・移動の残り・STAFF_REMOVED(reasonDISMISSED)は今の_on_staff_removedが行う。 - 施設の人員の投影は命令の中で
_sync_facility_staffingをすぐ行う。サービスの途中の職員が抜けて人数がstaff_minを欠けると、次の施設の更新から今の規則で職員を待ち(5 分)、代わりが来なければ失敗する(A4 の試験)。 - 救護(
_interrupt_dismissed_staff_rescue): 次の時刻の救護の確認(_advance_staff_rescueの最初の段)と同じ規則を、命令の中で、解雇した職員に関わる作業にだけ当てる。- 患者を解雇した時: その患者を目標にした終わっていない救護の作業を
RESCUE_INTERRUPTEDで取り消し、患者と運搬者の昇降機の予約を取り消す。運搬者が1人で昇降機に乗っている時は、今の規則(乗っている間は保つ)どおり予約を取り消さず、運搬者は本物の階に着く。作業は取り消すので、解雇した患者への参照は残らない。 - 運搬者を解雇した時:
remove_staffが開き直した搬送(rescue_transport)は運搬者が居ないので取り消す(今の規則と同じ)。迎え(rescue_pickup)は開き直ったまま、別の医療職を待つ(今の規則でも有効な作業)。患者は次の時刻に今の規則で救護をやり直す。 - 運搬者と患者が一緒に昇降機に乗っている時(決め): どちらの解雇も
RESCUE_PAIR_ABOARDで拒む(5.c)。着くまで保つ今の規則(ElevatorService.cancel_actorも乗っている組の取り消しを拒む)と、命令の直後の保存の照合の両方が成り立つのはこの形だけである。決めた範囲(Runtime とStaffService)の外のElevatorServiceを変えずに、乗っている1人だけを消すと、昇降機に持ち主の居ない予約が残る。これは R2 と同じ「着くまで待つ」の一時の拒否で、許可の行の全面の拒否ではない。A6・A7 は他の全ての段階(歩いている・昇降機を待つ・1人で乗っている・組で待つ・降りた後・治療中)で解雇でき、着いた後は同じ職員を解雇できる(試験)。退却や戦闘のような新しい規則は作っていない。
- 患者を解雇した時: その患者を目標にした終わっていない救護の作業を
- 出来事: 命令の中で公開の
event_service.audit_actor_availabilityを呼び、進行中・選択待ち・中断の出来事の欠けた職員を今のmissing_actor_policyで扱う(CANCEL と CONTINUE_WITHOUT を試験)。予約した費用は今の規則で1回だけ戻る。この audit は他の欠けた actor も今の規則で扱う(次の時刻と同じ処理が早く行われるだけ)。 - 命令の直後に保存し、同じ process(写しの復元と、ディスクへの保存と読み込み)と別の process(再開の2段)で読み込んでも、欠けた職員への生きた参照(終わっていない作業の患者と運搬者、昇降機の予約と相方、経路の actor、施設の人員、出来事の拘束と actor)が残らず、保存の照合が通る。
- 履歴として残るもの: 終わった作業の記録の
target_entity_id、サービスのstaff_ids(始めた時の記録)、給与の締めの行、雇った候補の記録(同じ候補は二度雇えない今の規則のまま)。
4. 画面(SPEC §4.3)
StaffManagementPanelに「解雇する…」と確定の欄(「解雇を確定」「やめる」)を足した。判定は Runtime の preview に従う。- 押す前に、退職金の額(日給の3日分)、裏金からの補填、未払いの給与、開き直す作業を出す。
- 拒否の行ではボタンを無効にし、理由を出す。
UNIQUEは今の「ユニーク:雇用・維持費無料 / 解雇・売却不可」、それ以外は「解雇不可:…」。無効のボタンを無理に押しても命令を送らない(5.a)。 - 確定の時に名簿を読み直し、読み込みや変化の後の古い確認では送らない。
- 時間が止まっている時はすぐに、進んでいる時は次の時刻に命令が処理され、結果(払った退職金・補填・保持した未払い・開き直した作業、または拒否の理由)を出し、名簿と選択を更新する。解雇の受理を待つ間、その職員の配属の変更とドラッグは止める。
Mainの職員の管理の画面は、今の部品と送り手(_audio_feedback.submit_command)のままで使えるので、scenes/main/main.gdは変えていない。UI は今の部品のままで、完成の見た目ではない。
5. 見つけた既存の不具合と直し
- 締めの後に税・利息の未払いが残ったゲームの保存が読めなかった(P05-02 からの不具合)。
- 保存を読む時の Operations の照合(
_parse_operations_runtime_snapshot)が、締めた未払いを「給与 + 維持費」だけで数え、実行中の照合(_operations_closed_arrears_total)が足している税・利息の未払い(_finance_arrears_through)を数えていなかった。 - 見つけた経路: 帳簿の日の流れの試験で、退職金の補填で裏金が減り、2日目の締めで世界樹ランク税 70 のうち 30 が未払いになった。その後の保存を復元できなかった(診断の記録は管理のフォルダ)。退職金の無い同じ流れでは税を払いきれるので起きない。
- 直し: 読む時の照合を実行中と同じ式(給与 + 維持費 + 税・利息の未払い)にそろえた。照合を緩めたのではなく、実行中の照合と同じにした。
- 試験:
test_general_dismissal.gdの帳簿の日の流れが、税の未払い 30 を確かめてから、締めの後の保存を復元する。再開の2段も締めの後の保存を別の process で読む。
- 保存を読む時の Operations の照合(
6. 範囲の外として残すもの(主張しない)
- 予約つきの作業を開き直した後、別の職員がその作業を取る時に、在庫の予約の操作 ID(
staff.task.reserve.<作業>.<品目>)が前の予約と同じなのでIDEMPOTENCY_CONFLICTで止まる(BLOCKED)。解雇でも今のremove_staffでも同じ結果になる(試験は、解雇の後の作業と在庫が今のremove_staffの結果と同じことを確かめる)。開き直しの全般の問題なので、別の単位として提案する。 - まだ始まっていない(待ち行列の)出来事の actor の ID は、拘束を持たず、始まる時に今の規則(
start_next_eventの欠けた actor の扱い)で扱われる。命令の中では変えない。 - 進行中の襲撃の防衛者の解雇(R9)は、原本の要件として未達のまま(SPEC §6.3・§8)。
- 解雇した職員が歩いて出る描写は作らない。UI は今の部品のまま。Windows 実機は後。
- 原単位 P16-01・P16-03 の残り(求人募集、奴隷市場・破産客からの獲得、人身売買、勤務・休息・気絶・救護の横断、解雇の経路の外の退職時の参照の除去)は未達のまま(SPEC §8)。
7. 試験
- 新しい suite:
tests/staff/test_general_dismissal.gd(F1〜F9。§6 の全ての行。共通の部品はtests/helpers/p16_dismissal_fixture.gd)。最後の場面がゲームの Main を使うので、suite-policy で ordinary の音の後片付けの証明(single)を持つ。- 再開の2段
tests/staff/test_general_dismissal_restart_1_write.gd(唯一の生成ファイルはartifacts/p16-01-dismiss/restart-handoff.json)と..._2_read.gd。
- validation
p16-dismiss:tools/run_p16_dismiss_tests.py。tools/run_p07_weather_tests.pyから、名前・名簿・再開の段・handoff・protocol 名だけを明示の置き換えで変えた(段の手順・厳密な照合・ordinary と old_bounded の分類は同じ)。実 12 段(新しい suite 1 + 既存 9 + 再開 2)と import・parse。 - suite-policy と marker contract に新しい3本の行を足し、今の source の SHA-256 で固定した。
- 既存の試験の期待値の変更は
EXPECTATION_CHANGES.json(kitchen の旧セーブの写しに退職金の口座を足す1件)。