# P28-01-RESTART 仕様(spec_ref) - 状態: 登録用の確定版です。この文書を Git で追跡し、それを含む commit を base にします。 - 元の草案: 同じディレクトリの `DRAFT.md`(SHA `a4a8261bcc14d38de8df8d9024321dd8fdb6c6356964ff43472d2bf84eff1334`。Control handoff の `RESTART_DRAFT.md` とバイト一致)。§番号は草案と同じです。この仕様は草案を契約の形にしたもので、規約を広げてはいません。 ## 1. 原本との対応(変更しない) - 対象は原 P28 の横断条件6件のうち、「途中保存・再起動で再現」です(`work_packages.json` P28.cross_cutting_acceptance[2])。 - 成果単位は P28-01「現HEADの性能基準」です。work と acceptance は collector の SPEC §1 と同じです。 - 分母は原30/88で、部分点はありません。この task が完了しても、原本は加算0です。P28-01 の加算(22→23)には、次の4つがすべて必要です。 1. collector の final(完了済み、Q `0f53a672…`) 2. 統合版で全9 phase を実測すること(完了済み。実際の commit `db9d6132a8349928560dc4a4a99306d27a81e332`、`artifacts/original-completion-2026-10-02/p28-01-runner-preflight-r01/full-measurement-db9d613-r01/run/execution.json` SHA `a4d10e9b1a75a17b981792265338d64fac61178cb6f87dd646c5b486292db73c`、Root の結合 `ROOT_RAW_ACCEPTANCE_JOIN.json` SHA `a76082f767e0a0d52cb70e2f66fa371b62a88754e9be319da3c08d4b48e78ba0`) 3. この RESTART の final と、Root の実測4 PID の pair の PASS 4. 証拠ゲート - 次のものは、未達のまま残します。 - 予算の未達 - 200客での Operations ON(製品の上限100) - Windows - 予算値、製品の値、停止契約は変更しません。 ## 2. 成果物(worker、allowed_paths `docs/plans/original-completion-2026-10-02/execution/p28-01/restart/probe/**`) | ファイル | 役割 | |---|---| | `restart_pair.py` | Root が実行する driver です。統合済みの collector から、`no_live_engine`、`source_map`、`run_private_engine`、`run_engine` と、guard、private profile、owned phase の仕組みを、読取専用で import して使います。import してよい外部ファイルは `tools/run_all_tests.py`、`tools/regression/owned_outer.py`、統合済みの `execution/p28-01/collector/collect_p28_01.py` だけです。`--check` は計画だけを出力し、`--run` で4 PID を実行します。 | | `restart_probe.gd` | writer と reader の probe(extends SceneTree)です。草案 §1〜§5 を実装します。 | | `check_restart.py` | report と receipt の checker です。§4 の拒否をすべて実装します。 | | `test_restart.py` | engine を使わない unittest です。 | ## 3. 受入グループ(baseline。有限で、草案の各節に対応する) - **RS1(草案§1〜2)保存・読込の成否** - 保存は main の `_save_manual_at_path`(bool)、読込は `_load_manual_at_path(path, true)`(void)で行います。 - 成否は、`save_operation_completed` の signal、`latest_save_operation_result`、実際の状態の3つで判定します。 - 保存の bool と signal の ok は一致しなければなりません。 - **RS2(§3.2、3.3 a〜c)IO の厳密な対応** - a: P が保存直前の状態と完全一致すること。 - b: 保存後の状態が X(P, ev_save) と完全一致すること。 - c: 読込後の状態が X(P, ev_load) と完全一致すること。 - X の構成は §3.2 のとおりで、counter+1、published_ids への E の sort 挿入、recent_events(上限256、溢れたら先頭を1件落として記録)です。 - **RS3(§3.3 d、§4)継続の一致** - 実際に進んだ K(=30)分の各分で、writer と reader が全状態で完全一致すること。 - 置き換えてよいのは、窓の中にある event_id E の要素1件だけです。 - K は実際に進んだ分の数で数えます。 - **RS4(§4)Operations の境界** - O は、実際の arrival(>0)が起きた後に保存します。 - 120分までに arrival が無ければ、null と理由にします。 - 境界に到達しただけで、arrival を処理したことにはしません。 - **RS5(§5)異常と境界** - 改ざんした保存の原子的な拒否(reader の PID 内で、正しい保存の前に試します)。 - R の止まった状態での保存と、読込後も止まっていること。 - O の次の arrival の境界に、重複も欠落もないこと。 - **RS6(§6)区間の静的検査** - UI 区間と決定性区間の、それぞれの禁止と許可を守ること。 - 性能値を一切出さないこと。 - **RS7(§7、collector C6/C7 と同じ)分離** - private user://、owned PID、guard、cleanup、通常 player の保全、全 raw と SHA の結合。 - source map が1407件のまま前後で一致すること。 - collector の4ファイルが Q と一致すること。 - **RS8 横断条件の記録** - 6件の横断条件それぞれについて、適用するかどうかと理由を記録します。 - 「途中保存・再起動で再現」は、RS1〜RS5 で適用します。 - それ以外の5件は、collector 側の既存の受入を参照し、適用外の理由を記録します。 ## 4. checker が必ず拒否するもの(すべて test_restart.py に拒否試験を置く) 1. 読込の void 戻り値、または保存の bool の true だけで、成功とすること。保存の bool と signal の ok の食い違いを見逃すこと。signal が無いのに成功とすること。 2. X(P, ev) 以外の差を許すこと。たとえば次のものです。 - 2件以上のイベントの差 - E 以外の ID - counter が+1でない - published_ids の欠落や重複 - recent の上限での先頭の落とし方の違い - 規約の外のパスの除外や置き換え - 「末尾1件の除外」として扱うこと 3. 継続で、E 以外の要素を置き換えること。窓から落ちた後も置き換えること。digest の一致だけで比較の代わりにすること。 4. advance の呼出し回数で K を数えること。writer と reader で実際の K が違うのに合格とすること。 5. 境界に到達しただけで arrival を処理したとみなすこと。arrival が0なのに RS4 を合格とすること。 6. 改ざんした読込のあとで状態が変わっているのに合格とすること。止まった状態での保存のあとに backlog を消費すること。 7. 決定性区間の外での `advance_minutes`。決定性区間の中の `Time.get_ticks_usec` や `*_us`。UI 区間の禁止 token。 8. PID、raw、source map、通常 player、guard の不一致。owned folder への書込み。 ## 5. 依存と前提 - 登録済みの task への depends_on はありません。collector は別 project なので、前提は追跡済みの記録として SHA で固定します。 - collector の final の receipt(Q) - 統合版の全9 phase の実測の receipt(上の §1 の2つの SHA) - collector の baseline C1〜C9 は凍結されているので、追加しません。RESTART は別 project として登録します。