Save The Tree implementation and acceptance work in progress

Preserve production code, regression fixtures, audio assets and provenance, test infrastructure, and the original-completion plan and progress ledger. Final game and Windows acceptance remain pending; excluded local artifacts and native experiments are not part of this snapshot.
This commit is contained in:
Takeshi
2026-10-11 15:58:00 +09:00
parent 39f6068461
commit b84bade045
235 changed files with 495831 additions and 312 deletions
@@ -0,0 +1,562 @@
# 原本全実装に向けた作業計画 2026年10月改訂
作成日: 2026-10-02。基準ソース: `285528b7a3b1b46a2a67af5aa90d9085539b42f4`。作業対象: ローカル制作コピー `/Users/korizatou114/Projects/とりにく工房ゲーム制作部`。
この計画は、指定された基本仕様書の全実装と会話で追加された施設仕様を、通常操作、保存復元、画面、内容資産、Windows配布版の受入まで進めるための改訂版である。既存成果を再利用し、未接続・未検証・未制作を残作業として追跡する。最初に原子要件と現在の証拠を再監査し、その後は通常操作から保存まで通る小さな変更として実装を進める。
2026-09-29版を作業順と進捗管理の面で更新する。旧計画と旧証拠は履歴として保持する。この文書の作成は、残件の実装やゲームの合格を示すものではない。
## 原本と目標
原本は指定Driveファイルの[保存済み読取版](../../traceability/original/BASELINE.txt)と[取得情報](../../traceability/original/baseline_metadata.json)を用いる。会話での明示追加・承認を適用し、別冊Aは既存全パラメータの参照資料として扱う。派生仕様書、古い実装、都合のよい仮値を原本に優先させない。今回の計画作成ではDriveを新規再取得していないため、保存版を「最新取得済み」とは表記しない。
全75要件群を対応表に保持する。機能・内容71群と過去工程4群を分け、原本30施設、施設主要10項目、7ヒロイン、ライバル、全エンド、図鑑、素材と音、Windows、20〜30時間の本編と50時間以上の全要素クリアを含める。原本の完全クリアには図鑑コンプが含まれ、物語の終了だけで代用しない。
The Towerの参考資料は、動きのあるドット断面、行列、EV、職員の仕事、混雑と改善を観察できる操作体験の参考とする。専用素材の制作、既存素材の出典、原本との対応を個別に管理する。
## 現在地
| 確認項目 | 現在の確認値 | 完了として認定していないこと |
|---|---|---|
| 最新本体 | 採用後マップ1396ファイルのSHAを再照合し差分0 | 候補コード、旧版の配布物を現本体として扱わない |
| 全自動回帰 | 155スイート、12,310チェック、失敗0 | 原本全実装、全資産、操作感、Windowsの合格 |
| 原本30施設 | 通常登録16、定義のみ1、未定義13 | 16件の全機能・全レベルの受入 |
| 施設主要10項目 | 人数や状態の基盤と料金未設定表示は部分採用 | 欲求一致加算の実徴収、全施設の必須値 |
| 人物 | アンリの通常加入と一部固有効果等を接続 | 7ヒロイン全員の通常加入、技能、成長、全ルート |
| Windows | 旧1394版の開発配布物あり | 現1396版の書出しと同一EXEでの実機受入 |
| 性能と長期プレイ | 限定的な軽量化と試験あり | Runtime全体の予算達成、本編・全要素の実プレイ受入 |
施設監査時の37定義、カタログ、定義スキーマ、施設対応表の40ファイルは現本体でもSHAが一致したため、16/1/13は現在の静的登録状態として使える。通常登録率16/30=53.33%は施設機能の完成率ではない。最新回帰の100%も全実装率とは別である。[基準と照合結果](baseline.json)
旧台帳は完了1、着手中17、予定12であった。部分実装の記録があるP09、P14、P15、P16、P20、P23、P25、P28を着手中へ修正し、新台帳は完了1、着手中25、予定4とする。新たに完了へ昇格した項目はない。唯一の完了P00は基準固定であり、1/30=3.33%をゲーム全体の実装率として表示しない。旧台帳の各証拠は過去記録として保持する。
## 完了条件と進捗率
各原子要件には、原本条件、定義、実行処理、通常UI入口、保存・移行、境界試験、完成資産と配布環境、証拠の8観点を割り当てる。適用外は理由と確認者を記録し、未実装や未制作を適用外に置き換えない。候補作成、モデル試験、定義登録、通常プレイ受入を別状態で扱う。
P01で分母を固定するまでは総合実装率と総合受入率を未算出にする。75複合群、30作業パッケージ、テスト件数、ファイル数を代用の分母にしない。以下は原子要件の件数割合であり、労力の割合ではない。
- 実装率 = 必須の定義・実行処理・通常UI・保存条件をすべて満たした原子要件数 ÷ 対象原子要件総数 × 100。
- 受入率 = すべての適用完了条件と現版の証拠がそろった原子要件数 ÷ 同じ対象原子要件総数 × 100。
- 部分実装は達成済み観点を別表示し、総合割合へ一律50%として加えない。未設定・未検証・未制作も分母に残す。
- 工程4群は機能の分母から除き、工程達成として別記する。過去の納期達成を後日の実装でPASSに変更しない。
- 原本と追加仕様の重複条件は一度だけ数える。分母の変更時は追加・削除・統合したIDと理由を履歴に残す。
- 報告には基準HEAD、分母、分子、保留数、差異数、集計時刻を付け、未丸め値から小数点2桁へ表示する。工数割合が必要なら別途残作業量を見積もり、件数割合と混ぜない。
本計画の残作業単位は実行順を管理するための区切りであり、まだ原子要件の分母ではない。[75群の対応表](requirement_coverage.json)は網羅性を維持するもので、各群の現在合否を保証するものではない。
## 承認済み仕様と未確定項目
承認済みの維持費方式、0.5%初期値、アンリ、礼拝堂、清掃員室と清掃の試験値は再確認せず使用する。これらを原本由来の数値と混同せず、個別承認値として管理する。
| ID | 承認済み事項 |
|---|---|
| A01 | 完成から撤去までの保有時間で日額按分。閉店・休止中も計上し00:00に精算。不足を翌日へ繰越。 |
| A02 | 建築費の0.5%/日を初期試験値として試験・調整する。既存の整数処理を保ち、礼拝堂・清掃員室は個別承認値を使う。 |
| A03 | 従業員画面で無料加入を選ぶ。配置フロアの利用料金を20%増やし客の支払額と施設収入を一致させる。 |
| A04 | 4×3・表層。建築1200G、資材12、工期180分、同時8人、聖職者最低1人/上限2人、礼拝60分、寄付20G、完了時信仰+1、維持費6G/日。 |
| A05 | 2×1・裏層。建築350G、資材4、工期60分、清掃員最低1人/上限2人、顧客0人・利用料なし、維持費2G/日。清潔0〜100・初期100、75以下で予約、現地8分で25回復。定義済み汚れ量を使い未定義値を補完しない。 |
施設追加仕様では、capacityは保管量・生産量等にも使うため顧客人数へ転記しない。staff_maxは必要最低人数と別にする。関連施設は配置の有無ではなく稼働を判定し、条件回復だけで破壊・摘発後の休止を解除しない。欲求一致は料金加算条件であり、不一致利用を禁止しない。
欲求一致の額・率、不足基準、施設別属性と必須人数などは局所的な未確定として扱う。複数属性、重複加算、複数関連施設のAND/OR、休止復帰条件は現指定では未設定を維持し、追加仕様を発明しない。待ちがある項目と独立した作業を続ける。
| ID | 未確定事項 | 固定が必要な地点 | 先に進める作業 |
|---|---|---|---|
| D01 | 不足基準、加算額/率、施設の属性割当。複数属性・重複加算は採用しない限り明示未設定を維持。 | P09の本番課金 | 計算契約、未設定表示、非一致利用、財布・台帳の試験枠を進める。 |
| D02 | 原本や個別承認にない人数専用上限、staff_max、Lv別変更を整理。capacityから推測転記しない。 | 各施設の通常営業 | 明示値がある施設から進め、未設定の一覧と超過拒否を作る。 |
| D03 | 休止復帰条件と複数関連施設AND/ORはユーザー指定により未設定。解除なし・単一依存の現仕様を維持。 | 新たな復帰/複数条件を追加する場合 | 現仕様を接続して試験する。回答待ちで現実装を止めない。 |
| D04 | 税・利息・マナ・天候・環境・役割・成長等の必須値。A01〜A05は決定済み。 | 各機能の本番値固定 | 原本明示値、契約、候補比較を先行する。 |
| D05 | EV/搬送停止、費用時点、日跨ぎ順序の未確定部分。承認済み維持費時点を再確認しない。 | 更新規約の凍結 | 原状保持と重複防止、具体的な境界事例を作る。 |
| D06 | 占有衝突や移動中の状態の扱い。旧セーブの拒否時原状保持は必須。 | 旧配置に不可逆な変更を適用する前 | 読み取り移行プレビュー、バックアップ、拒否時の復帰を進める。 |
| D07 | 旧5値と原本3値の意味対応、既存ルートの扱い。 | 旧進行の変換 | 旧値を保全し、新規ゲームの原本モデルを実装する。 |
| D08 | 章、人物ごとの分岐、全エンド、図鑑対象、未制作内容の範囲。 | 内容の凍結と最終受入 | 非露骨な状態・分岐・中立テストで構造を検証する。未制作は原本差異として残す。 |
| D09 | 完成素材の品質、必要量、担当、予算、権利。The Towerの提供ファイルは体験の参考とする。 | 完成素材受入や発注 | Kenney優先の調査、ライセンス台帳、差替契約、既存資産の確認を進める。 |
| D10 | 対象機スペック、表示倍率、解像度、描画目標、評価担当。 | Windowsでの性能合否 | 利用できる対象機を記録し、機能検証と手元の実測を進める。 |
## 実装順と到達点
大きなパッケージ全体の完了を待ってすべての着手を止めない。各変更に必要な保存・更新・会計・交通の契約が受入済みなら、その施設や人物の縦断実装を始める。全体統合と最終認定では依存パッケージ全体を受け入れる。
| 段階 | 作業と主な担当パッケージ | 到達点と次の条件 |
|---|---|---|
| 0 | P00〜P02。基準固定、原子台帳、証拠と通常操作の再監査 | 分母と残件が確定し、現版と過去版・候補が区別される |
| 1 | P03〜P09、P22、P28の先行測定。保存、更新順、仕入れ、マナ、施設共通契約 | 通常営業の財布・台帳・停止・人数が一貫し、新規機能の保存条件が明確 |
| 2 | P08〜P14、P23。原本30施設、特殊設備、交通、断面表示 | 全施設を通常建設・運用でき、依存喪失・移動・保存の境界を通る |
| 3 | P15〜P19、P24。客、職員、7ヒロイン、関係、イベント、通常操作 | 各人物と分岐へ通常到達でき、業務・料金・効果が保存再開で一致する |
| 4 | P20〜P26。ランク、章、エンド、図鑑、防衛、完成素材と音 | 新規から本編と全要素へ到達でき、必要内容と完成資産がそろう |
| 5 | P27〜P29。要件別受入、通しデバッグ、性能、長期プレイ、Windows最終監査 | 同じ候補版で全必須要件と配布版を受け入れる |
素材の必要量整理と制作、Windowsの部分確認、負荷測定は早期から続ける。P28の測定を最後まで先送りしない。P27〜P29の最終合格には機能と内容の全体完了が必要である。
## 直近の着手順
| 順番 | 次に行う変更 | 必要な前提 | 終了条件 |
|---|---|---|---|
| 1 | P01の台帳分割と現在証拠の再監査 | 保存版原本と現HEADの固定 | 原子分母、現合否、未設定と未制作が再計算可能 |
| 2 | 未採用Pathの不正transit部分成功ガードを受入 | 現HEADへ限定リベース、基準経路の契約 | 異常時全拒否、正常互換、保存、1200Tickの全状態・全イベント比較、関連回帰 |
| 3 | P05有料自動仕入れの補正候補を受入 | 現HEADへ限定リベース、手動購入と領収書契約 | 二重課金・数量単価・資金不足・返送・停止・再起動の試験、通常UI、全回帰、限定採用 |
| 4 | P09の10項目対応と施設別必須値の整理 | 人数・状態・料金の契約と既承認値 | 未確定の局所一覧、価格合成の比較案。確定した範囲から通常課金へ接続 |
| 5 | P10〜P14の施設を一件ずつ通常営業まで完成 | 当該施設が使う共通契約と値 | 定義だけで止めず建設・職員・客・会計・保存・画面を通す |
| 6 | 初回の最新Windows確認と性能測定 | 採用済み最新版、記録した対象機 | 旧1394配布物から更新し、同一EXEの操作と現Runtimeの性能を記録 |
候補の受入に失敗したら本体へ採用せず、再現条件を固定して修正する。上記2と3は安全性・会計の独立した変更として検証する。性能探索と新機能の意味を同時に変更せず、比較できる基準を残す。
## 作業パッケージの残件
P00〜P29のIDを維持して過去記録との対応を保つ。各項目には現在地、統合前提、実装単位、追加受入を記載する。下記の作業単位はいずれも本改訂で完了を宣言していない。P00の継続照合は既存基準の維持作業である。
### P00 原本 作業対象の固定
現在地: 基準固定済み。指定原本の保存版を使用。
統合前提: なし。原本対応: B-1.1, B-14.1, B-14.2, B-14.3, B-14.4。
- P00-01 原本と基準ソースの継続照合。指定原本の読取保存版と別冊AのSHA、HEAD、採用済みマップを固定し、更新時だけ影響要件を再監査する。 受入: 原本の優先順位と差分履歴が再現できる。最新Drive再取得を今回実施したとは表示しない。
### P01 原子要件と受入台帳
現在地: 75群の対応は存在するが、原子要件と現在の受入状態は未確定。
統合前提: P00。原本対応: B-1.1, B-1.2, B-1.3, B-1.4, B-1.5, B-1.6, B-14.1, B-14.2, B-14.3, B-14.4。
- P01-01 原子要件への分割。原本文の複数条件を分割し、施設30件、追加10項目、7人物、図鑑、全エンド、工程4件を漏れなく対応付ける。 受入: 各原本文に対応先があり、同じ条件を重複加点しない。
- P01-02 現在の実装と証拠の再監査。実装、未接続、未検証、未設定、未制作を分け、現在HEADに適用できる証拠と過去証拠を識別する。 受入: 通常入口・Runtime・保存・試験・資産の対応が存在し、候補コードを採用済みとして数えない。
- P01-03 集計基準の固定。原子要件の分母、適用する完了条件、理由付き適用外、判定者を版管理して初回進捗を集計する。 受入: 分母と分子のID一覧から他者が再計算できる。テスト件数や部分実装への一律半点を使用しない。
### P02 既存機能の回帰基準
現在地: 最新本体の155スイートと12,310チェックは合格。全原本受入とは別。
統合前提: P00。原本対応: B-3.1a, B-3.1b, B-3.3, B-3.4a, B-3.4b, B-4.2, B-4.3c, B-5.4。
- P02-01 回帰と代表セーブの固定。最新全回帰のソース一致を確認し、初期・営業中・移動中・日付境界・防衛中の代表セーブを選ぶ。 受入: ログ、入力、シード、保存版、チェック数が対応し、失敗を含む履歴が追える。
- P02-02 通常操作の基準シナリオ。開業、雇用、配置、仕入れ、建設、保存終了再開を通常画面で通す。 受入: デバッグ値投入の試験と自然営業の試験を区別し、画面と実状態が一致する。
- P02-03 Windows基準環境の記録。利用できるWindows機のOS、CPU、GPU、RAM、表示倍率、解像度、検証するビルドを記録する。 受入: 過去の実機確認を現ビルドへ転用せず、同一EXEの起動と保存再開を確認する。
### P03 保存形式と移行契約
現在地: 保存・移行の基盤と複数の復元試験はある。全原本の追加状態は未完。
統合前提: P01, P02。原本対応: B-2.1, B-4.1, B-5.2, B-6.3, B-7.2, B-8.1, B-9.1。
- P03-01 機能別の保存契約。会計、施設状態、人数、欲求属性、マナ、人物、図鑑、物語に新規項目を追加する前に保存条件を固定する。 受入: 新旧版・欠損・未知版・破損を検証し、失敗時に原データが変わらない。
- P03-02 配置と関係値の旧版移行。寸法変更、動線喪失、旧関係値の意味を個別に確認し、移行プレビューと拒否時の復帰を用意する。 受入: 移動中、EV乗車中、搬送中、同時建設中の参照が孤立しない。推測による関係値変換をしない。
- P03-03 プロセスを跨ぐ再開。営業・配送・清掃・防衛・人物進行の途中で保存、終了、再起動して比較する。 受入: 同じ操作列の施設・財布・台帳・人物・イベントが一致し、二重効果がない。
### P04 更新順序 責務の整理
現在地: 更新順と分離サービスの改善は部分採用済み。全機能の順序契約は継続。
統合前提: P03。原本対応: B-1.3, B-1.4, B-3.2, B-9.2。
- P04-01 同時発生の更新規約。閉店、停電、破壊、退出、課金、シフト交代、00:00決算の順序を明記する。 受入: 順序境界で停止中課金、二重決算、予約の孤立がない。
- P04-02 トランザクションと再送。課金・補給・依存判定・イベント効果の失敗時原状保持と再送時の一回反映を接続する。 受入: 途中失敗後の状態・帳簿・再試行結果が一致する。
- P04-03 Runtimeの負荷監視。新サービス導入ごとにTick・snapshot・経路・描画更新を同一条件で測る。 受入: 状態や乱数を変える軽量化を受け入れず、性能結果と意味的同等性を別に判定する。
### P05 全収支 維持費 税 借入
現在地: 承認済み維持費は接続済み。有料自動仕入れの修正候補は未採用。
統合前提: P04。原本対応: B-3.4a, B-3.4b, B-9.1, B-9.2, B-9.3。
- P05-01 自動仕入れ候補の受入。1394基準の補正候補を現1396基準へ限定リベースし、見積・数量・単価・領収書・配送と通常UIへ接続する。 受入: 手動購入互換、資金不足、二重課金、返送、停電、隔離、途中再起動を検証してから採用する。
- P05-02 全費目と資金区分。表金・裏金、維持費未払い、仕入れ、人件費、元本、利息、税を帳簿へ接続する。 受入: 3営業日で資金増減と台帳が一致し、借入元本を売上に含めない。
- P05-03 金庫と銀行の通常営業。金庫容量、購買窓口、借入、返済、滞納を通常画面から操作する。 受入: 上限・不足・期限・保存・赤字終了と、滞納から脅威への接続を確認する。
### P06 マナ枯渇と全館停止
現在地: 停電、厨房、救護の停止復帰は部分実装。有限マナ供給の契約が残る。
統合前提: P04。原本対応: B-2.6, B-9.1, B-10.6, B-10.7。
- P06-01 供給と蓄積の契約。世界樹、マナ炉、消費施設の生成・蓄積・消費と旧ゼロ値保存の意味を整理する。 受入: 初期値や係数の根拠を区別し、旧版移行と残量境界で矛盾がない。
- P06-02 全館停止の統合。利用中、EV、ワープ、物流、救護、清掃、入館へ同じ停止判定を接続する。 受入: 停電中の無条件売上・生産がなく、乗客と搬送対象が消えない。
- P06-03 復帰と表示。供給復帰時の予約・在庫・運行を再開し、HUDへ供給、消費、蓄積を表示する。 受入: 破壊・摘発の休止を停電復旧で解除しない。途中保存後も復帰結果が一致する。
### P07 天候 流行 環境
現在地: 嵐の境界と天候保存、清潔度基盤は部分接続済み。
統合前提: P04。原本対応: B-2.3, B-2.6, B-3.2, B-3.5, B-4.5, B-11.1。
- P07-01 雨と霧と自然天候。雨の来客減・滞在延長、マナ霧、自然変化を実営業へ接続する。 受入: 天候切替直前後、途中保存、自然来客の差を同条件で説明できる。
- P07-02 環境と客反応。景観・清潔・騒音、採光・遮音・隠蔽を満足度、客特性、売上へ接続する。 受入: 異なる環境で実際の選択と満足度が変化し、清潔伝播も保存される。
- P07-03 流行ニュースと可視化。流行の効果、期限、通知、将来需要の説明を通常画面へ出す。 受入: 通知文と需要変化が一致し、再読込でニュースや効果が重複しない。
### P08 施設寸法 既存配置の整合
現在地: 原本に対応する17定義の寸法・層は整合。全30の配置運用は未完。
統合前提: P03, P01。原本対応: B-2.1, B-8.1, B-10.1, B-10.2, B-10.3, B-10.4, B-10.5, B-10.6, B-10.7。
- P08-01 全30施設の配置条件。未定義13件と闇市場を含め、正規ID・寸法・層・地上地下・高層・背面条件を固定する。 受入: 30件の原本対応と個別建設条件が一致し、類似施設で代用しない。
- P08-02 旧配置の安全な変更。混合建設、占有変更、役者の実位置、救護・物流・EVをまとめて移行する。 受入: 重複、孤立、消失がない。解消不能時は元配置とセーブを保つ。
- P08-03 配置の通常操作受入。通常パレットから支持・接続・不正位置・撤去・再建築を操作する。 受入: 拒否理由と実判定が一致し、パン・ズーム・保存再開後も同じ位置を扱う。
### P09 施設共通契約と追加10項目
現在地: 人数・稼働状態等の基盤と料金未設定表示は採用済み。欲求加算の実徴収は未接続。
統合前提: P05, P06, P08。原本対応: B-8.1, B-8.2, B-8.3, B-8.5, B-9.2。
- P09-01 施設10項目の統合。人数専用上限とcapacity、職員上限と最低人数、単一関連施設と稼働フラグ、3状態を区別して全定義へ適用する。 受入: 待機者を利用人数に数えず、関連施設が配置だけで稼働扱いにならず、休止は自動復帰しない。
- P09-02 欲求一致加算の接続。不足基準、料金加算、施設属性の必須未確定値を整理し、確定後に見積から実徴収・台帳までつなぐ。 受入: 一致時のみ指定加算、不一致でも利用可。財布減額と収入が一致し、アンリ補正との順序と丸めを確認する。
- P09-03 施設レベルと営業設定。Lv1からLv3の価格、人数、解放条件、営業Policyと説明を接続する。 受入: 通常操作、利用中変更、人数超過、停止、日跨ぎ、途中保存で契約が一致する。
### P10 宿泊 飲食施設の完成
現在地: 一般・上級客室等は部分営業済み。VIP・ドミトリー・レストラン・屋台が未定義。
統合前提: P09。原本対応: B-8.2, B-10.1, B-10.2。
- P10-01 宿泊4種類の完了。VIPスイートとドミトリーを追加し、一般・上級を含む宿泊条件、精算、景観、人数をそろえる。 受入: 4種類を通常建設し自然客が利用、前払い・退店・停止・保存を検証する。
- P10-02 飲食4種類の完了。レストラン、屋台を追加し、食堂、酒場と厨房、食材、職種、物流を統合する。 受入: 厨房の稼働喪失・在庫不足・届く前の利用拒否・営業収支を確認する。
- P10-03 営業と中期収支。通常初期資金で新設施設を運用し、複数シードと序盤・中盤の需要で試す。 受入: 施設別売上と費用、依存、人数、移動、保存が一致する。
### P11 衛生 娯楽 礼拝施設
現在地: 大浴場と礼拝堂は部分接続済み。カジノと闘技場が未定義。
統合前提: P09, P07。原本対応: B-8.2, B-10.3。
- P11-01 娯楽2施設の営業。カジノと闘技場の定義、従業員、利用、会計、解放、設定を接続する。 受入: 通常建設から利用、収益、退出、停止、保存再開まで成立する。
- P11-02 浴場と礼拝の統合。浴場と承認済み礼拝堂を人数・清潔・職種・信仰・ランクへ接続する。 受入: 寄付、信仰、人物補正、営業停止が一回だけ反映される。
- P11-03 4施設の境界受入。同時利用限界、職員離席、停電、破壊、関連条件喪失を試す。 受入: 表示された稼働理由・利用可否と実状態が一致する。
### P12 バックヤード施設完成
現在地: 宿舎・清掃員室・実清掃・救護等は部分接続済み。全業務と特殊設備は残る。
統合前提: P09。原本対応: B-2.4, B-5.3, B-5.4, B-8.3, B-10.5, B-3.3。
- P12-01 裏方7施設の完成。厨房・倉庫・待機・宿舎・清掃・警備・医務の配置、職種、仕事、停止をそろえる。 受入: 客侵入を防ぎ、実出勤から実作業・休息・帰宅まで成立する。
- P12-02 専用動線と設備。リネンシュート、隠し扉、従業員ドアを物流、清掃、救護経路へ接続する。 受入: 孤立入口、経路喪失、交代、撤去で人員・物資・救護対象が消えない。
- P12-03 全シフトの運用。昼夜の交代、休息、清掃、配送、救護が重なる通常一日を操作する。 受入: 人数と予約が上限内で、停止・保存再開を跨いでも重複業務がない。
### P13 特殊 地下施設の非描写システム接続
現在地: 一部関連基盤はあるが原本の特殊施設接続は未着手。
統合前提: P09, P12。原本対応: B-1.6, B-2.5, B-8.2, B-8.3, B-10.4, B-10.6。
- P13-01 特殊施設とアクセス。原本の特殊・地下施設を配置、職員アクセス、役割、会計の非描写状態として接続する。 受入: 特殊条件の建設時・運用時判定が一致し、無効配置が通らない。
- P13-02 背面条件と対象参照。覗き部屋の対象背面、通路寸断、対象喪失と証拠IDを状態として実装する。 受入: 対象撤去、重複収集、停止、途中保存で状態と参照が整合する。
- P13-03 内容差異の記録。地下牢、マナ炉等のイベント接続と未制作の表現資産を別に管理する。 受入: 状態処理の完成を内容制作の完成として加点しない。
### P14 垂直交通 ワープ完成
現在地: EV・階段と救護同伴等の基盤あり。ワープと全経路受入が残る。
統合前提: P06, P09。原本対応: B-2.4, B-4.3a, B-4.3b, B-4.3c, B-8.4, B-10.7。
- P14-01 交通の失敗時契約。不正transitキーでsnapshot全体を拒否する未採用候補を現基準で検証する。 受入: 部分成功を返さず、正常順序・型・所有権・保存・経路が基準と一致する。
- P14-02 ワープの通常接続。マナワープの建設、対象、待ち時間、消費、停止、実移動を接続する。 受入: 途中保存、マナ不足、到着不能時に移動や費用が二重反映されない。
- P14-03 混雑と経路選択。客用・業務用EV、階段、ワープの待ち時間をA*費用へ反映する。 受入: ラッシュ、相乗り、50%減速、救護同伴、経路喪失を実位置と人数で検証する。
### P15 客の全パラメータ 時間帯AI
現在地: 欲求選択と候補拒否ログ等は部分実装。全客特性は未完。
統合前提: P07, P10, P11, P14, P13。原本対応: B-3.2, B-4.1, B-4.2, B-4.4, B-4.5, B-9.4。
- P15-01 時間帯と欲求。朝の下り、夕の上り、夜の目的地を四欲求、距離、行列、価格へ接続する。 受入: 最大欲求を維持し、日付・天候・施設変化で目的地分布が説明できる。
- P15-02 種族と環境。クラス・種族、忍耐、清潔、汚染伝播、戦利品を実来客モデルへ接続する。 受入: 原本の客種ごとに反応が異なり、再読込で属性が再抽選されない。
- P15-03 依存と信用の状態。依存、装備処分、信用超過、退店判断、破産を非描写状態として処理する。 受入: 金額と所持品を保全し、途中中断・再送・保存でも一回だけ遷移する。
### P16 雇用 職種 労務完成
現在地: 一般求人・配置・清掃等の基盤あり。全雇用区分と特性・費用は残る。
統合前提: P12, P15, P13。原本対応: B-5.1, B-5.2, B-5.3, B-5.4, B-5.5, B-3.3。
- P16-01 獲得と費用の区分。求人、市場、原本の雇用区分ごとの費用と獲得・退職を非描写状態として整理する。 受入: 求人から配置・精算・退職まで通常操作でき、ユニーク禁止操作を維持する。
- P16-02 特性と全職種。生成時特性、体力、ストレス、忠誠、技能と全職種の仕事を接続する。 受入: 同一保存で特性が固定され、配置しても仕事内容がない職種を残さない。
- P16-03 労務と交代。勤務、休息、給与、気絶、救護、退職時参照除去を横断検証する。 受入: 人員上限、未払い、交代中の予約・移動が整合し、消失や二重精算がない。
### P17 ユニーク7名 固有効果 成長
現在地: アンリの通常無料加入と料金補正等を部分接続。7ヒロイン全体は未完。ライはライバルとして別集計。
統合前提: P16, P05, P11。原本対応: B-1.5, B-6.1, B-6.2, B-6.3, B-6.4, B-6.5。
- P17-01 7名の加入と固有効果。アンリ、フィーネ、トマリ、アメリア、リズ、ミミ、サツキとライバルを区別し、加入と固有効果を通常営業へ接続する。 受入: 7名それぞれ配置前後・同時配置・配置変更の効果を確認し、無料・削除禁止を維持する。
- P17-02 業務成長と技能。実業務EXP、Lv99、基礎技能、パッシブ、能動スキル、ルート別解放を接続する。 受入: 上限と取得条件、財布や台帳への補正、保存再開で効果が一致する。
- P17-03 衣装と勤務と離脱。24時間警告、継続・中止、衣装補正、限定的離脱と復帰を通常UIへ接続する。 受入: 警告を操作でき、原本外の恒久ロストを起こさず、未設定加入条件は捏造しない。
### P18 関係パラメータ 盾 確定遷移
現在地: 原本の関係3値と盾の全面接続は未着手。
統合前提: P03, P17。原本対応: B-7.1, B-7.2, B-7.3。
- P18-01 関係モデルと保存。原本の3値と盾を専用モデルへ接続し、旧関係値を保全する。 受入: 表示と状態が一致し、意味不明な値の一対一変換を行わない。
- P18-02 接触と境界。同配置、別配置、軽減、盾上限、盾破壊、閾値を非描写状態遷移として接続する。 受入: 閾値前後と反復更新で効果が一回だけ適用される。
- P18-03 不可逆な分岐。原本のルート確定と旧進行の扱いを保存・履歴へつなぐ。 受入: 確定後のロードでルートが逆転せず、未決状態を勝手に固定しない。
### P19 イベント 決闘 行動 履歴基盤
現在地: 一般イベント基盤はあるが原本の決闘・人物行動の全接続は未着手。
統合前提: P18, P05。原本対応: B-7.1, B-7.4, B-7.5, B-7.6, B-11.3。
- P19-01 人物行動と決闘。原本の行動入口、3種決闘、勝敗、費用、結果を非描写イベントへ接続する。 受入: 通常入口から到達し、勝敗の盾・状態・台帳が一回だけ変化する。
- P19-02 観察と履歴。専用観察画面、証拠ID、操作介入、対象状態、履歴を中立テスト内容でつなぐ。 受入: 対象不在、停止、取消、離脱、保存再開で参照と履歴が一致する。
- P19-03 分岐の到達性。人物ごとの3ルートに必要なイベント・条件・中断処理を列挙する。 受入: 7名×3ルートの到達表があり、未制作内容は欠損として残る。
### P20 ランク 信仰 物語進行
現在地: ランク表示等の部分実装あり。章・エンド・図鑑の通常到達は未完。
統合前提: P05, P11, P15, P19。原本対応: B-1.1, B-1.2, B-1.3, B-1.4, B-1.5, B-6.4, B-6.5, B-8.1, B-8.5。
- P20-01 ランクと解放。信仰・評判・裏影響、ランク条件、領域、施設レベル、Policy、スキル解放を接続する。 受入: 通常営業から条件を達成でき、未達理由を表示する。
- P20-02 章と全エンド。物語の開始、章、人物進行、最終ランク、終点を通常操作へ接続する。 受入: 条件値を直接注入せず新規から本編終点へ到達し、各エンドを保存再開できる。
- P20-03 図鑑の完成。対象一覧、発見・登録条件、閲覧、達成状況、保存、コンプリート判定を実装する。 受入: 図鑑コンプを通常到達で検証し、本編クリアと全要素クリアを区別する。
### P21 防衛 監査 銀行 砲台
現在地: 防衛の準備・表示・結果・イベント橋渡しは部分接続。自然脅威等が残る。
統合前提: P05, P13, P14, P17。原本対応: B-1.3, B-6.4, B-6.5, B-9.3, B-10.7, B-11.4。
- P21-01 自然脅威と監査。自然営業のHeat、滞納、原本の脅威から警告と防衛準備へつなぐ。 受入: サービス直呼びだけでなく通常営業から発生し、通知と状態が一致する。
- P21-02 砲台と能動技能。魔法砲台の建設、マナ、職員、人物の任意技能、戦闘結果を接続する。 受入: 発動可否、費用、クールダウン、勝敗、中断を保存再開まで検証する。
- P21-03 破壊と摘発と休止。施設損傷、摘発、人物の限定離脱、台帳と営業停止を統合する。 受入: 意図しない恒久ロストや自動休止解除がなく、利用中の状態を保全する。
### P22 素材台帳 量産仕様の先行確定
現在地: 施設・人物・素材枠の初期台帳あり。必要数と完成資産の受入は未完。
統合前提: P01。原本対応: B-12.1, B-12.3, B-12.4, B-13.1, B-13.2, B-13.3, B-13.4, B-13.5。
- P22-01 必要素材の確定。全30施設のLv1〜3と表裏、7人物、ライバル、状態、背景、UI、音の必要枠を列挙する。 受入: 仮素材、コード描画、完成素材の区分と利用条件が分かり、枠数を素材枚数と混同しない。
- P22-02 素材契約と権利。Kenneyを優先して適合素材を選び、解像度、命名、差替、出典とライセンスを記録する。 受入: 完成枠には使用可能な資産と権利記録があり、欠損を代替表示で隠さない。
- P22-03 制作量と担当。未制作の絵、モーション、音、声、脚本を必要量と担当・予算候補へ分ける。 受入: 未割当、未承認、制作待ちが明示され、技術工数と内容制作工数を分ける。
### P23 タワー画面 レイヤー演出
現在地: ドット断面、レイヤー表示、複数UIスキンは部分実装。原本全演出の受入は残る。
統合前提: P08, P22。原本対応: B-2.2, B-11.1, B-11.4, B-12.1, B-12.2, B-12.4。
- P23-01 レイヤーと波紋。表時の裏半透明、裏時の表ワイヤー、魔法レンズ風の波紋を原本どおり接続する。 受入: 連続切替でも座標・選択・対象が一致し、描画層と操作対象を取り違えない。
- P23-02 断面の操作性。パン、上下スクロール、ズーム、建設グリッド、接続警告、HUD配置を整える。 受入: 小画面とWindows表示倍率で読めて押せる。x3時にも操作が追随する。
- P23-03 生活の観察。部屋、行列、EV、職員、物資、営業状態が断面上で理解できる表示へ調整する。 受入: 人物や設備の表示が実状態に対応し、同需要の動線改善を観察できる。
### P24 インスペクター 通知 操作完成
現在地: ドラッグ配置、選択復元、営業人数、料金未設定表示等は部分採用。
統合前提: P09, P15, P16, P18, P23, P19。原本対応: B-11.1, B-11.2, B-11.3, B-11.4, B-13.4。
- P24-01 全インスペクター。欲求、思考、感情、盾、料金内訳、稼働理由、上限、人物効果を通常画面へつなぐ。 受入: 表示値が実計算・台帳と一致し、未設定をゼロ確定に見せない。
- P24-02 操作と通知。配置、無効ドロップ、モーダル、停止、再開、フキダシ、ログ、カットインを整える。 受入: 無効操作を説明し、クリック代替と日本語入力・表示倍率を確認する。
- P24-03 選択と保存の受入。施設・客・職員・レイヤーの選択を撤去、離脱、保存再起動に跨がせる。 受入: 不在対象を参照せず、有効な選択と画面値が復元される。
### P25 ドット人物 施設差分 音響接続
現在地: 歩行・清掃等の一部モーションとコード描画あり。全差分・音響は未受入。
統合前提: P22, P23, P12, P17。原本対応: B-12.1, B-12.3, B-12.4, B-13.2, B-13.3, B-13.4, B-13.5。
- P25-01 実状態に沿うドット動作。歩行、接客、食事、搬送、救護、清掃、休息、気絶と設備動作をそろえる。 受入: 停止中に仕事が進まず、人物位置と搬送・作業状態が一致する。
- P25-02 施設と人物の差分。施設Lv、表裏、人物状態、破損・汚れ等の必要差分を完成素材へ置換する。 受入: 全枠の読込、見切れ、欠損、状態変化とライセンスを確認する。
- P25-03 音の接続。表裏BGMクロスフェード、環境音、操作音、必要な声を音量設定へ接続する。 受入: 切替、停止、ロードで二重再生せず、Windows出力と設定保存を確認する。
### P26 シナリオ 立ち絵 内容資産の制作受入
現在地: 全章・人物別内容と完成資産の制作受入は未着手。
統合前提: P19, P20, P22。原本対応: B-1.1, B-1.5, B-1.6, B-7.5, B-7.6, B-12.1, B-12.3, B-13.1, B-13.5。
- P26-01 全必要内容の台帳。全章、7名の3ルート、全エンド、台詞、立ち絵、音声の必要枠と条件を確定する。 受入: 原本で要求された未制作内容を欠損として記録し、架空の完成数を置かない。
- P26-02 内容と状態の接続。制作可能な非露骨内容をイベント・章・閲覧・人物状態へ接続し、仮素材を区別する。 受入: 全必要分岐に内容IDがあり、欠損と未制作をスキップPASSしない。
- P26-03 制作受入と差異。完成内容の品質、権利、表示、保存と原本との差異を受入する。 受入: 原本必須内容の未制作が残る場合は原本全実装未完として報告する。
### P27 統合 境界 障害復旧試験
現在地: 最新全回帰合格。原本75群全体の受入と通しデバッグは未完。
統合前提: P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P24, P25, P26。原本対応: B-1.1, B-1.3, B-14.4。
- P27-01 要件別の合否。原子台帳へ部品、通常Runtime、画面、保存、資産の証拠を結び付ける。 受入: 全必須要件の判定があり、未設定や欠損を試験省略でPASSにしない。
- P27-02 横断シナリオ。開業、決算、天候、停電、ラッシュ、救護、破産、防衛、人物、ランクを横断する。 受入: 中断と保存再起動を挟んでも財布・台帳・人員・参照が一致する。
- P27-03 通しデバッグの完了。要件別全件合格後に新規から本編・全要素の通し確認を行い、欠陥を再現ケースで修正する。 受入: 重大不具合0、未解決差異0。修正後の関連回帰と影響した通し経路を再確認する。
### P28 性能 操作感 長期バランス
現在地: 複数の軽量化は採用済み。Runtime全体の性能予算は未達。
統合前提: P27。原本対応: B-1.1, B-3.1a, B-4.3a, B-4.3c, B-11.1, B-12.1, B-14.4。
- P28-01 現HEADの性能基準。実Runtimeの20,000マス・200客・50職員・150施設を基準にTick、経路、snapshot、描画、保存を測る。 受入: 機種、ビルド、シード、速度、測定区間、平均・P95・最大を残す。
- P28-02 意味を保つ軽量化。失敗時拒否を含む同等性を先に固定し、snapshot変換・検証・コピー・経路接続の実測上位から改善する。 受入: 同条件の反復比較と全状態・全イベント一致を確認し、キャッシュの古さ・所有権・不正入力を検証する。
- P28-03 操作感と長期バランス。Windows描画、初見操作、ラッシュ、長期収支、本編20〜30時間・全要素50時間以上を実プレイで確認する。 受入: 性能予算と対象Windows描画目標を満たし、時間の早送りだけで操作感やプレイ時間を合格にしない。
### P29 Windows実機 配布版 最終監査
現在地: 旧1394版Windows配布物のZIP・PCK検査とmacOSでのPCK実行は合格。現1396版のWindows実機受入は未完。
統合前提: P28。原本対応: B-1.1, B-14.1, B-14.2, B-14.3, B-14.4。
- P29-01 最新候補の書き出し。採用済みソースだけからWindows EXE/PCKを再生成し、同梱データとZIPを確認する。 受入: ソース・PCK・EXE・ZIPのハッシュ、同梱マニフェスト、CRCが対応する。
- P29-02 Windows同一版の操作。日本語パス、新規、建設、営業、表示倍率、音、入力、保存終了再起動を実EXEで確認する。 受入: macOS PCK実行と区別し、同一Windows版の操作記録・ログ・画面・性能を残す。
- P29-03 最終監査と引渡し。原本75群、追加10項目、全施設、人物、資産、図鑑、全エンドを再監査して配布証拠をまとめる。 受入: 同じリリース候補で必須未実装0・未承認差異0・未制作0・重大不具合0。工程4件の過去納期達成は別判定。
## 原本施設の残件
未定義13施設はVIPスイート、ドミトリー、レストラン、屋台、カジノ、闘技場、高級ソープ、SM拷問室、覗き部屋、地下牢、マナ炉、ワープ、魔法砲台。定義のみの闇市場は通常登録と運用を追加する。原本外の通路等7件を不足施設の代替として数えない。
各施設を「原本の位置と寸法確認 → 定義と必要値 → 通常パレット → 稼働と依存 → 職員と客の実行 → 会計 → 途中保存 → 境界 → 実描画 → Windows」の順で閉じる。機能未完成のまま施設登録数だけを増やさない。既存16施設も同じ受入表で不足を確認する。
## 人物と進行の受入
ヒロインはアンリ、フィーネ、トマリ、アメリア、リズ、ミミ、サツキの7名。ライ、リーゼンバルト、ソウ等のライバルは別集合とし、アンリとライの加入を2/7ヒロイン実装と数えない。
7名×3ルートの到達表をP19とP26で持つ。これは21組の到達性を調べる義務であり、21本の完成脚本が存在するという意味ではない。固有効果、EXP、Lv99、衣装、24時間警告、技能、限定離脱を人物別に検証する。
物語と図鑑は通常プレイの解放・取得・閲覧・保存を検証する。値を直接書き換えた条件API試験は部品試験として残し、自然な本編到達の証拠として使わない。未制作の必須内容や制作できない表現は原本との差異として残し、全実装の完了に数えない。
## 検証と通しデバッグ
| 検証段階 | 確認する内容 | 保存する証拠 |
|---|---|---|
| 仕様とデータ | 原本条件、全施設、値、属性、素材枠、未確定 | 原子台帳と出典、データ検査、差異一覧 |
| 部品と境界 | 金額、人数、状態、更新順、経路、効果、異常時原状保持 | 入力、期待、実値、失敗を含むログ |
| 通常Runtime | 自然来客、勤務、物流、清掃、課金、決算、防衛 | シード、実Tick、状態、イベント、台帳 |
| 保存と移行 | 旧版、未知版、破損、途中処理、別プロセス再開 | 元データの保全、前後比較、再実行手順 |
| 実描画と入力 | パン、ズーム、層、配置、選択、説明、画面サイズ | 操作列、画面、対象IDと実状態 |
| 配布版 | 同梱データ、PCKとEXE、ZIP、Windows操作 | ハッシュ、マニフェスト、実機ログ |
| 長期と全要素 | 本編、全エンド、全人物、図鑑、経済、性能 | 到達表、実プレイ記録、不具合と再確認 |
横断シナリオは、A新規から3営業日決算、B雨・嵐・霧と復帰、C停電とEV・救護・物流、D昼夜交代とラッシュ・休息、E関連施設停止・破壊・摘発、F欲求・価格・行列・人数、G返済滞納と襲撃結果、Hランク解放と全施設、I7人物と全分岐、J旧版移行と配布、K図鑑と全要素完了とする。各重要地点で保存、終了、再起動を挟む。
各変更は関連試験と必要な境界から始め、統合点で標準全体回帰を行う。全要件別受入がそろった段階で通しデバッグを開始し、重大不具合と未解決差異を解消して完了する。修正後は該当回帰と影響を受けた通し経路を再確認し、ソースが変わっていない検証を理由なく全件反復しない。
## 性能の基準
| 対象 | 継続する予算 |
|---|---:|
| simulation x1 平均 | 4ms以下 |
| simulation x3 P95 | 12ms以下 |
| path query P95 | 2ms以下 |
| 主スレッド停滞 最大 | 50ms以下 |
| 保存 最大 | 5秒以下 |
| 読込 最大 | 8秒以下 |
代表負荷は20,000マス、顧客200、従業員50、施設150とし、行列・物流・イベントも付与する。原本の最終到達規模がこれを超えるなら負荷条件を追加する。単独モデルの小規模成功を実RuntimeやGPUの成功としない。
9月30日に計測したPath候補の小規模4反復値はx1平均9.575ms、x3 P95 45.541ms、最大停滞67.434msであり、予算未達である。これは現1396HEADを新測定した値ではない。P28で最新版を同条件と混合負荷の両方で測り直す。Windows描画目標はD10で別に定め、シミュレーション予算をFPS保証としない。
snapshotの検証・変換・コピー、経路接続、更新回数を実測上位から改善する。同じ入力、乱数、全状態、全イベントの比較、正常・異常入力、所有権、キャッシュ失効を先に確認する。メモリは反復ロードと長時間運転で持続増加を調べる。
## 工数と日程と担当
旧計画の180〜390人日は9月29日時点の全体粗見積であり、現在の残工数へ転用しない。既存成果、未検証部分、脚本・絵・音・声の必要量をP01とP22で確定した後、残作業ごとに実績から見積もる。技術作業、内容制作、外部待ち、実プレイ20〜30時間と50時間以上を分離する。
固定発売日は本改訂では置かない。原本の2027年12月マスターアップは比較する目標として保持し、達成可能と断定しない。段階0終了時に初回残工数、段階2終了時に人物・素材・進行の再見積、段階4終了時に通しデバッグとWindowsの見通しを更新する。実装単位の完了ごとに状態と証拠を更新し、段階終了時に計画と割合を再集計する。
実装担当はコード・データ・通常操作・保存の証拠を作成する。受入担当は原本条件と証拠を確認する。素材とシナリオの制作担当は必要量とともに割り当てる。本計画作成時の別担当による読み取り監査は実施済みだが、今後すべての制作や実機試験に独立担当が確保されたとは扱わない。
## 最終完了の判定
同じリリース候補について、必須未実装0、未承認の原本差異0、現仕様の必須値未設定0、未制作必須資産0、重大不具合0、原子要件の受入証拠欠損0を満たす。明示的に未設定の追加拡張仕様は、その理由を残したまま現仕様の適用範囲として扱う。
通常新規ゲームから本編終点、全エンド、全ヒロイン、図鑑コンプへ到達し、指定プレイ時間、性能、保存移行、音、画面、Windows同一版を受け入れる。内容を変更して差異を解消する場合は承認履歴を残し、原本準拠と改訂仕様準拠を区別する。未達が残る限り目標全体を完了にしない。
## 計画の資料と更新方法
- [基準と静的照合](baseline.json): 原本、採用ソース、証拠、施設数、割合の未算出状態。
- [作業台帳](work_packages.json): 全30パッケージ、現在地、残作業単位、受入、依存、旧進捗。
- [原本対応表](requirement_coverage.json): 全75群と残作業単位の対応。現在の原子合否は再監査前。
- [割合の集計契約](progress_contract.json): 分母固定前は未算出とし、将来の原子台帳に必要な項目を定義。
- [承認と未確定事項](decisions.json): 再確認不要の回答と局所的な未確定。
- [計画検証結果](plan_validation.json): 対応漏れ、ID、依存循環、資料ハッシュを検査した結果。
- [改訂とレビュー](REVIEW.md): 前計画からの修正と残る不確実性。
変更時は `python3 docs/plans/original-completion-2026-10-02/validate_plan.py` を実行して計画を再検証する。通常検査は着手・保留・証拠付き完了への更新を認め、初期状態の履歴を保持する。初期版を再確認するときだけ `--initial-snapshot --verify-baseline` を付ける。後者は履歴時点のソースを比較するため、将来の本体変更で不一致が出た場合は旧合格の適用範囲を再評価する。この検査はゲームを実行せず、計画の整合性だけを確認する。
## 全75群の作業対応
以下は原本の網羅性を確認するための対応表である。9月29日の群別状態を現在の全受入として再利用していない。機能と内容の現在判定はP01で原子要件へ分解して更新する。
| 原本ID | 要件 | 担当パッケージ |
|---|---|---|
| B-1.1 | 基本情報・Windows・2D・20〜30時間/50時間以上 | P00, P01, P20, P26, P27, P28, P29 |
| B-1.2 | 地上/地下の二面性経営・観察介入・権威/富 | P01, P20 |
| B-1.3 | 建設→集客→収益→管理→拡張防衛 | P01, P04, P20, P21, P27 |
| B-1.4 | 二層・自律AI・渋滞・信仰と依存 | P01, P04, P20 |
| B-1.5 | 世界観・主人公・7ヒロイン3運命 | P01, P17, P20, P26 |
| B-1.6 | 成人向けルートと経営的搾取 | P01, P13, P26 |
| B-2.1 | グリッド・Y正負・支持・領域拡張 | P03, P08 |
| B-2.2 | 同座標Front/Back・半透明/ワイヤー表示 | P23 |
| B-2.3 | 客エリアと景観/清潔/騒音の満足度効果 | P07 |
| B-2.4 | バックヤード・職員ドア・客通行禁止 | P12, P14 |
| B-2.5 | 覗き部屋の配置制約・通路寸断・証拠収集 | P13 |
| B-2.6 | 地上/地下の採光・マナ・遮音・隠蔽ボーナス | P06, P07 |
| B-3.1a | 10秒=1時間、Pause/x1/x2/x3 | P02, P28 |
| B-3.1b | アクティブポーズ中も建設・指示 | P02 |
| B-3.2 | 4時間帯と朝下り/夕上り/夜行動 | P04, P07, P15 |
| B-3.3 | 昼夜シフト・体力0気絶・救護・通勤混雑 | P02, P12, P16 |
| B-3.4a | 毎日00:00に決算レポート | P02, P05 |
| B-3.4b | 3回連続赤字でゲームオーバー | P02, P05 |
| B-3.5 | 雨・嵐・マナの霧・流行ニュース | P07 |
| B-4.1 | 所持金/戦利品・四欲求・忍耐/清潔/依存 | P03, P15 |
| B-4.2 | 最大欲求優先と距離/行列/価格選択 | P02, P15 |
| B-4.3a | A*とエレベーター待ち時間コスト | P14, P28 |
| B-4.3b | 4種垂直移動のゲーム内利用 | P14 |
| B-4.3c | 重なり時速度50%低下 | P02, P14, P28 |
| B-4.4 | 依存Lv3退店拒否・装備売却・性別別破産 | P15 |
| B-4.5 | 貴族/聖職者/エルフ/魔族のAI特性 | P07, P15 |
| B-5.1 | 一般雇用と奴隷の費用/耐性/売却区別 | P16 |
| B-5.2 | 体力/ストレス/忠誠/技能/ランダム特性 | P03, P16 |
| B-5.3 | 接客/裏方/救護/防衛等の職種 | P12, P16 |
| B-5.4 | シフト休息と気絶回収 | P02, P12, P16 |
| B-5.5 | 求人/市場/破産捕獲・退職金/売買価格 | P16 |
| B-6.1 | ユニーク無料・高成長・解雇売却不可 | P17 |
| B-6.2 | 7ヒロインの指定固有効果とライバル | P17 |
| B-6.3 | 基礎技能と業務EXP・Lv99 | P03, P17 |
| B-6.4 | 配置パッシブ・任意発動・ルート別スキル | P17, P20, P21 |
| B-6.5 | 24時間勤務警告・衣装補正・限定離脱 | P17, P20, P21 |
| B-7.1 | 三感情・盾・決闘の3ルート運命 | P18, P19 |
| B-7.2 | 好感/淫乱/NTR・好感度=盾最大・淫乱軽減 | P03, P18 |
| B-7.3 | 同配置接触→盾破壊→NTR上昇→不可逆陥落 | P18 |
| B-7.4 | 3種決闘・勝利追放/隷属/盾回復・敗北確定 | P19 |
| B-7.5 | 会話/デート/隔離・覗き・薬による各ルート | P19, P26 |
| B-7.6 | 履歴・妊娠/父親・刻印立ち絵 | P19, P26 |
| B-8.1 | 隣接/通路必須とLv拡張 | P03, P08, P09, P20 |
| B-8.2 | 表層全施設・飲食と厨房セット | P09, P10, P11, P13 |
| B-8.3 | 裏層全施設と特殊設備 | P09, P12, P13 |
| B-8.4 | EV/階段/ワープ/通路/職員ドア | P14 |
| B-8.5 | Lv解放の価格/食材/混浴/ハード/イカサマ設定 | P09, P20 |
| B-9.1 | 表金/裏金・マナ全館停止・資材 | P03, P05, P06 |
| B-9.2 | 全収益/人件費/維持/仕入/借金/ランク税 | P04, P05, P09 |
| B-9.3 | 受付/金庫/購買/闇銀行 | P05, P21 |
| B-9.4 | 依存客の娯楽優先・信用超過の破産拘束 | P15 |
| B-10.1 | 宿泊施設の寸法/層/ゾーン | P08, P10 |
| B-10.2 | 飲食施設の寸法/層/ゾーン | P08, P10 |
| B-10.3 | 衛生/娯楽施設の寸法/層/ゾーン | P08, P11 |
| B-10.4 | アングラ施設の寸法/層/ゾーン | P08, P13 |
| B-10.5 | バックヤード施設の寸法/層/ゾーン | P08, P12 |
| B-10.6 | 特殊施設の寸法/層/ゾーン | P06, P08, P13 |
| B-10.7 | インフラ/防衛施設の寸法/層/ゾーン | P06, P08, P14, P21 |
| B-11.1 | 資源/時間/天候/Rank・下部切替・スクロールズーム | P07, P23, P24, P28 |
| B-11.2 | Policy/ドラッグ配置・欲求/思考/感情グラフ/盾 | P24 |
| B-11.3 | カメラ入口・覗きアングル/撮影/介入 | P19, P24 |
| B-11.4 | グリッド/接続警告・フキダシ/ログ・カットイン | P21, P23, P24 |
| B-12.1 | 二面性・高精細ドットとアニメ立ち絵 | P22, P23, P25, P26, P28 |
| B-12.2 | 魔法レンズ風の波紋切替 | P23 |
| B-12.3 | SD各モーション・立ち絵破損/汚れ/刻印差分 | P22, P25, P26 |
| B-12.4 | 表裏UIスキン・BGMクロスフェード・環境音/SE | P22, P23, P25 |
| B-13.1 | 立ち絵/CG/差分 | P22, P26 |
| B-13.2 | SDモーション/エフェクト | P22, P25 |
| B-13.3 | Lv1〜3表裏タイル/背景 | P22, P25 |
| B-13.4 | 表裏スキン/感情/覗き素材 | P22, P24, P25 |
| B-13.5 | BGM/環境/操作/成人向けSE/声 | P22, P25, P26 |
| B-14.1 | 2026/03〜08 プロトタイプ | P00, P01, P29 |
| B-14.2 | 2026/09〜2027/02 アルファ | P00, P01, P29 |
| B-14.3 | 2027/03〜08 ベータ/成人向け | P00, P01, P29 |
| B-14.4 | 2027/09〜12 ポリッシュ | P00, P01, P27, P28, P29 |
@@ -0,0 +1,16 @@
{
"copied_before_first_progress_update_at_jst": "2026-10-02T01:41:59.589881+09:00",
"scope": "Initial planning data retained before mutable progress integration; no new game or source evidence.",
"initial_package_counts": {
"completed": 1,
"in_progress": 25,
"planned": 4
},
"initial_delivery_count": 88,
"sha256": {
"baseline.json": "750bb3d313cc5e2ce0d4c79e563a995abd7a78f991dee1dd75c627877b02cd7b",
"execution/IMPLEMENTATION_PLAN.initial.md": "f9cb3f61e4cb020e37f792c615dfbd4794763884a8ec528de14c3469cf4e5248",
"execution/work_packages.initial.json": "c4bd86eb4b0b4b8ff93cfd9e1c06de376dd0039a68db26a9f104b3fc0632a511",
"execution/progress_contract.initial.json": "5e67310e29c7fe91b984a5b510619f3505c2b31711253850787f164a73758151"
}
}
@@ -0,0 +1,59 @@
# P03 保存プリフライト修正の独立レビュー
2026-10-02。本体の変更・Godotの追加実行は行わず、save_service / simulation_snapshot / Runtime previewの差分、test_save_preflight、焦点7本485チェックのログを監査した。
新しい`inspect_snapshot`と寸法previewの接続、manifest/clock envelopeの厳格型検証、既知サイズの読取前制限について、差分が原因の重大不具合は見つからなかった。ただし**既存の復旧経路にP01/P03受入を妨げる原状保持の不足2件**がある。485チェックの合格だけで未知版や全APIの読取専用保証を受け入れられない。
| 判定 | 対象 | 結果 |
|---|---|---|
| 確認済み | inspect_snapshot / 寸法preview | 通常loadのtransaction reconcileを通らず正式packageを読む。formalなしでもtmp/bakへ昇格しない。previewは隔離Runtimeで検証し、本Runtimeと全ディスクSHAを保つ試験がある。計測カウンタの更新は発生するため全メモリが不変という意味ではない。 |
| 確認済み | manifest型 | versionはunsigned範囲の有限整数数値だけを許可。文字列・bool・分数・nullを拒否。JSON由来の厳密な整数floatは許可する。checksumは64桁hex文字列、重複sizeは存在する場合に正の整数かつheaderと一致が必須。 |
| 確認済み | clock envelope型 | schema/minute/speed/versionのcoerceを避け、present pausedはbool必須。省略paused/versionのlegacy defaultとx4→x3互換を維持。generic envelopeの整数float互換であり、現Runtimeのbinary schemaは従来通りstrict TYPE_INTを要求する。 |
| 確認済み | サイズ | worldの圧縮payload/展開予定値は各256 MiB以下・正数、manifestは4 MiB以下としてbulk read/decompress前に検査する。writerも出力blob/manifestを拒否して正式保存を保持する。 |
| 不足 | 未知版+transaction artifact | 下記SFR-01。正式保存の版を識別する前にreconcileして未知版を古いbakへ置換し得る。 |
| 不足 | 明示backup選択のread_only | 下記SFR-02。候補選択前のformal reconcileでtmp/marker等が変化し得る。 |
## SFR-01: 未知の正式保存を旧backupで置換する [P1]
`save_service.gd:932`の`_reconcile_interrupted_formal_save`は、`target_status.current_loadable == false`のとき、未知形式と壊れた現形式を区別していない。formalが存在し有効transaction markerがあると、現版tmp/bakを選び、formalを削除して置換する(同関数のinvalid formal replacement分岐)。`load_snapshot`、`migrate_save`、`inspect_recovery_candidates`、`load_with_recovery`、明示`load_recovery_candidate`がこの経路を先に通る。
再現条件は、正式保存のmanifestとTTWB headerをformat2へ変え、圧縮payload/checksumを保ったまま、現format1のbak/tmpと有効`.save_transaction`を残すこと。通常loadが正式保存を古い状態へ置換して成功する静的経路を確認した。checksumを破損したfuture版、manifestだけfuture、headerだけfutureでも、識別できる未知版を破損現版として消してよい根拠にはならない。
現128チェックの未知版試験は`inspect_snapshot`での拒否と、transaction markerなしでの未登録migrate拒否を確認する。上の複合条件を覆っていない。レビューではGodotを実行していないので、実再現の結果は未取得と明示する。
## SFR-02: 明示候補読取のread_onlyと実処理が不一致 [P2]
`save_service.gd:313〜336`は明示候補読取をread-onlyと説明し、結果にも`read_only=true`を付けるが、候補pathの選択前に`_reconcile_interrupted_formal_save`を呼ぶ。
formalが正常、有効markerとtmpがある場合、backupを選ぶだけでもtmp/markerを削除する。formalが欠損しtmpがある場合、backupを読むだけでもtmpが正式名へ昇格する。明示候補読取は指定packageだけを検証し、通常load/通常recoveryが復旧を所有する契約へ分ける必要がある。
## 候補と受入の範囲
`artifacts/original-completion-2026-10-02/p03-recovery-readonly-candidate/combined.diff`、完全候補、原因別diff、fixture driver、receiptを作成した。本体変更0、Godot実行0で、候補は未採用・未検証である。rootが既存全回帰の終了後に別stageで、元本体の実再現→候補修正後試験→保存/復旧/移行の関連回帰を行う。
候補はbounded manifestと固定TTWB prefixのいずれでも未知版を先に識別し、checksum成功を前提にしない。通常load/recoveryの未知版は全artifactを変えず拒否する。migrateは明示登録された過去版→現版の全隣接stepだけを認め、その場合もsourceの検証前に既存artifactを整理しない。既知現版の壊れたtransaction復旧は維持する。明示候補読取からreconcileを除く。
`inspect_recovery_candidates`は既存の説明通り通常復旧を含む一覧APIであり、全体をread-onlyとは呼ばない。formalが未知と識別できた場合の不変拒否を先行する。
485ログは7本すべてexit0・実チェック数とcompletion markerが一致し、4修正/試験ファイルSHAは現在と一致した。source-startの318パスは317一致で、差分は今回焦点外の`tests/performance/test_digest_performance.gd`だけだった。初回失敗ログも保存されており、後続r02と混同しない。全157回帰の終了結果はこのレビューに含めていない。
サイズ上限はserialized world blobの制限であり、総ピークメモリ256 MiB以下の証明ではない。256 MiB一致の試験はmanifest/header不一致でdecompress前に拒否し、巨大な正常full Runtimeを実際に展開した受入ではない。20,000セルはworld-onlyのサイズ測定で、full Runtime受入ではない。これらはP28の性能/規模受入として引き続き未検証にする。
## 既存移行・復旧契約との照合
`test_save_operations.gd`の349〜450行と`test_runtime_save_lifecycle.gd`の170〜200/230〜380行を候補と照合した。以下は静的整合の確認で、候補の再実行合格ではない。
| 既存契約 | 候補との整合 |
|---|---|
| registryの1→2→3隣接step・入力コピー・欠損step監査 | registry自体を変更しないため維持。 |
| current formatだが不正snapshotの通常load/no-op migrate拒否 | guardは現formatを通し、既存schema検証へ到達するため維持。 |
| 明示0→1 package移行、step ID、manifest注記、完全pre_migration.bak | 過去版→現版の全step確認後に既存移行本体へ入る。callbackとbackup/promotion処理は変更しない。 |
| 登録済みstepが途中失敗したときformalのworld/manifest不変、backup未作成 | sourceのdecode/registry成功前にreconcileを実行しないため、stale普通saveのtmp/bak/markerも不変になる。追加driverでこの複合条件を要求する。 |
| 移行後のtorn pre_migration.bakをdurable .oldから修復 | formalが現formatになった状態では従来のinspect/reconcile枝を維持。 |
| `.migration.original`のhold、完成candidateのpromotion、candidateなしrollback | formal欠損では未知版guardに識別値がなく、従来のmigration reconcileへ進む。現format持ちの既存fixtureを維持。 |
| 壊れたcurrent formalからbackup/autosaveへ通常復旧 | current版識別は通すため従来の復旧を維持。識別可能な未知formalだけをfallbackの対象から外す。 |
| 明示backup/autosave選択がpackageを昇格しない | 候補選択にreconcileが不要。formalなしのbak選択は成功でき、tmp/markerは通常loadに残す。 |
登録0→1の成功時は、formalと専用migration artifactだけを既存手順で更新する。stale普通saveのtmp/bak/markerは前処理で片付けず保持する。次の通常loadは新しい現formalを優先し、marker/tmpの既存cleanupを実行できる。これを未知formalの拒否や明示backupの純読取と混同しない。
追加driverは8入口×5未知形、formal有無のbackup選択、既知現版破損復旧、登録legacy成功の普通artifact保持、登録legacy失敗の全SHA保持を含む。rootによる別stageでの実再現・候補検証待ちである。
@@ -0,0 +1,100 @@
"""Bind atomic conditions to current static leads without promoting them to PASS.
Old group evidence supplies search leads only. Presence and unchanged bytes are
not proof of normal operation, complete content, or accepted release behavior.
"""
from datetime import datetime
import hashlib
import json
from pathlib import Path
import re
from zoneinfo import ZoneInfo
ROOT = Path(__file__).resolve().parents[4]
PLAN = ROOT / "docs/plans/original-completion-2026-10-02"
def sha(path):
return hashlib.sha256(path.read_bytes()).hexdigest() if path.is_file() else None
def main():
atomic = json.loads((PLAN / "atomic_requirements.json").read_text())
groups = {r["id"]: r for r in json.loads((ROOT / "docs/traceability/original/requirements.json").read_text())}
baseline = json.loads((ROOT / "artifacts/facility-need-pricing-production-scale-adoption-2026-10-01-r01/after.json").read_text())
definitions = {}
for path in sorted((ROOT / "data/facilities").rglob("*.tres")):
match = re.search(r'^id = &"([^"]+)"$', path.read_text(), re.MULTILINE)
if match:
definitions[match.group(1)] = path
catalog = (ROOT / "scripts/data/facility_catalog.gd").read_text()
characters = {r["id"] for r in json.loads((ROOT / "data/characters/mvp_unique_characters.json").read_text())["entries"]}
locators = {}
rows = []
def locate(name, symbol=None):
key = (name, symbol)
if key not in locators:
path = ROOT / name
entry = {"path": name, "exists": path.is_file(), "sha256": sha(path),
"matches_retained_baseline": sha(path) == baseline.get(name) if name in baseline else None,
"semantic_acceptance": "not_verified"}
if symbol and path.is_file():
lines = [i for i, line in enumerate(path.read_text().splitlines(), 1) if symbol in line]
entry.update(symbol=symbol, current_matching_lines=lines, symbol_present=bool(lines))
locators[key] = entry
return locators[key]
for requirement in atomic["requirements"]:
source_refs, test_refs = {}, set()
for group_id in requirement["source_group_ids"]:
group = groups[group_id]
for ref in group.get("source_evidence", []):
source_refs[(ref["path"], ref.get("symbol"))] = locate(ref["path"], ref.get("symbol"))
test_refs.update(group.get("related_component_tests", []))
item = {"requirement_id": requirement["id"], "source_group_ids": requirement["source_group_ids"],
"primary_package": requirement["primary_package"], "planned_normal_entry": requirement["normal_entry"],
"normal_entry_verified": False, "static_source_leads": list(source_refs.values()),
"component_test_leads": [locate(t) for t in sorted(test_refs)],
"save_contract_leads": [locate("scripts/core/save_service.gd"), locate("scripts/core/simulation_snapshot.gd"), locate("autoload/simulation_runtime.gd")],
"boundary_evidence": "group tests require condition-specific review",
"implementation_state": "not_reaudited_at_all_required_views", "acceptance_state": "unverified",
"reviewer": "root static provenance audit"}
if requirement["id"].startswith("AR.facility."):
facility_id = requirement["id"].split(".")[2]
path = definitions.get(facility_id)
if path:
name = str(path.relative_to(ROOT))
item["definition"] = dict(locate(name), catalog_literal_present=("res://" + name) in catalog,
source_value_approval="requires condition-specific review")
field = requirement["id"].split(".")[3]
aliases = {"footprint": "footprint", "layer": "layer", "staff_min": "staff_min", "staff_max": "staff_max",
"customer_capacity": "customer_capacity", "service_attribute": "service_attribute", "service_price": "base_price",
"upkeep_gold": "maintenance_gold", "upkeep_mana": "maintenance_mana"}
if field in aliases:
prefix = aliases[field] + " = "
values = [(i, line[len(prefix):]) for i, line in enumerate(path.read_text().splitlines(), 1) if line.startswith(prefix)]
item["implementation_field"] = {"field": aliases[field], "explicit_lines": values,
"state": "explicit_implementation_not_yet_source_approved" if values else "inherited_default_not_explicit_approval"}
else:
item["definition"] = {"state": "missing_definition", "canonical_audit_id": facility_id}
if requirement["id"].startswith("AR.heroine."):
person_id = "heroine_" + requirement["id"].split(".")[2]
item["character_catalog"] = dict(locate("data/characters/mvp_unique_characters.json"),
canonical_audit_id=person_id, entry_present=person_id in characters,
effect_or_route_verified=False)
if requirement["id"].startswith(("AR.asset.", "AR.art.")):
item["finished_asset_acceptance"] = {"state": "missing_acceptance", "audit": "assets_platform_audit.json",
"fallback_counts_as_complete": False}
rows.append(item)
report = {"scope": "current static bindings and missing definitions; no group-to-atom PASS promotion",
"audited_at_jst": datetime.now(ZoneInfo("Asia/Tokyo")).isoformat(), "atomic_register_sha256": sha(PLAN / "atomic_requirements.json"),
"known_condition_denominator": len(atomic["denominator_ids"]), "rows": rows,
"unique_source_locators": len(locators), "whole_atom_acceptance_claimed": False,
"complete_runtime_ui_save_review": False}
(PLAN / "current_evidence_links.json").write_text(json.dumps(report, ensure_ascii=False, indent=2) + "\n")
print(json.dumps({k:v for k,v in report.items() if k != "rows"}, ensure_ascii=False))
if __name__ == "__main__":
main()
@@ -0,0 +1,72 @@
"""Build source-only P05 stages from the current, preservation-fixed production."""
import hashlib
import importlib.util
import json
from pathlib import Path
import shutil
import uuid
ROOT = Path(__file__).resolve().parents[4]
OUT = ROOT / "artifacts/original-completion-2026-10-02/p05-current-stage-input-r01"
PACKET = ROOT / "artifacts/original-completion-2026-10-02/p05-auto-purchase-rebase"
SAVE_SHA = "79a8c3654868c81d3e623a429d8fdfe51f15d098cef8d5b60be091d5200b285d"
def sha(path):
return hashlib.sha256(path.read_bytes()).hexdigest()
def write(path, value):
path.write_text(json.dumps(value, ensure_ascii=False, indent=2) + "\n")
def main():
OUT.mkdir(parents=True, exist_ok=False)
spec = importlib.util.spec_from_file_location("regression_inputs", Path(__file__).with_name("run_current_regression.py"))
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
baseline_map = module.source_map()
assert baseline_map["scripts/core/save_service.gd"] == SAVE_SHA
targets = json.loads((PACKET / "overlay-targets.json").read_text())["targets"]
assert len(targets) == 20
stages = Path("/private/tmp") / ("thetree-p05-current-" + uuid.uuid4().hex[:12])
maps = {}
for variant in ("baseline", "candidate"):
stage = stages / variant
stage.mkdir(parents=True)
for name, expected in baseline_map.items():
target = stage / name
target.parent.mkdir(parents=True, exist_ok=True)
shutil.copyfile(ROOT / name, target)
assert sha(target) == expected
maps[variant] = dict(baseline_map)
if variant == "candidate":
for row in targets:
name = row["target"]
candidate = PACKET / "candidates" / name
assert sha(candidate) == row["rebased_candidate_sha256"], name
if row["kind"] == "new":
assert name not in baseline_map, name
else:
assert baseline_map[name] == sha(PACKET / "base-current" / name), name
(stage / name).parent.mkdir(parents=True, exist_ok=True)
shutil.copyfile(candidate, stage / name)
maps[variant][name] = sha(candidate)
write(OUT / (variant + "-source.json"), maps[variant])
after = module.source_map()
assert after == baseline_map
def roster(variant):
return ["tests/run_tests.gd"] + sorted(p for p in maps[variant] if p.startswith("tests/") and
Path(p).name.startswith("test") and p.endswith(".gd") and "export" not in Path(p).parts and Path(p).name != "test_kernel_and_save.gd")
result = {"baseline_stage": str(stages / "baseline"), "candidate_stage": str(stages / "candidate"),
"baseline_source_map": str(OUT / "baseline-source.json"), "candidate_source_map": str(OUT / "candidate-source.json"),
"baseline_suites": len(roster("baseline")), "candidate_suites": len(roster("candidate")),
"save_preservation_sha256": SAVE_SHA, "source_changes": [], "engine_runs": 0,
"packet_integration_guards_are_historical_references_only": True,
"candidate_acceptance": False, "production_applied": False}
write(OUT / "preparation.json", result)
print(json.dumps(result, ensure_ascii=False), flush=True)
if __name__ == "__main__":
main()
@@ -0,0 +1,24 @@
{
"scope": "Counting contract for P01 atomic requirements, not a populated acceptance register",
"denominator_frozen": false,
"atomic_register": null,
"excluded_from_function_denominator": ["B-14.1", "B-14.2", "B-14.3", "B-14.4"],
"counting_unit": "one unique independently judgeable specification condition",
"completion_views": ["source_condition", "definition", "runtime", "normal_ui", "save_migration", "boundary_verification", "assets_platform", "evidence"],
"implementation_required_views": ["source_condition", "definition", "runtime", "normal_ui", "save_migration"],
"acceptance_required_views": "all applicable completion views",
"view_states": ["not_started", "partial", "blocked", "pass", "fail", "not_applicable"],
"not_applicable_requires": ["reason", "source_or_explicit_user_decision", "reviewer"],
"partial_credit": false,
"equal_count_weight": 1,
"implementation_percent": "100 * fully_implemented_atomic_count / frozen_atomic_denominator",
"acceptance_percent": "100 * fully_accepted_atomic_count / frozen_atomic_denominator",
"unknown_before_freeze": null,
"rounding": "Calculate from integer counts, display to two decimal places, retain counts",
"atomic_record_required_fields": ["id", "source_anchors", "source_sha256", "user_amendment_refs", "condition", "normal_entry", "implementation_paths", "save_contract", "applicable_completion_views", "view_results", "evidence_refs", "source_head", "primary_package", "responsible_role", "reviewer", "status", "updated_at"],
"published_snapshot_required_fields": ["source_head", "denominator_version", "denominator_ids", "implemented_ids", "accepted_ids", "blocked_ids", "partial_ids", "missing_evidence_ids", "difference_ids", "calculated_at"],
"denominator_change_requires": ["added_ids", "removed_ids", "merged_ids", "reason", "previous_version", "new_version"],
"must_remain_in_denominator": ["mandatory_unimplemented", "mandatory_unverified", "mandatory_undefined_values", "mandatory_unproduced_content"],
"must_not_count_as_current_acceptance": ["test_count", "file_count", "package_count", "unadopted_candidate", "old_source_evidence_without_current_applicability", "fallback_asset", "accelerated_replay_as_human_playtime"],
"effort_weighted_progress": "Separate future estimate; never relabel atomic count as effort percentage"
}
@@ -0,0 +1,87 @@
"""Recheck retained source and raw regression evidence without rerunning it.
This accepts only the source regression baseline, never original-game acceptance.
The original plan's immutable baseline remains a historical record.
"""
from datetime import datetime
from hashlib import sha256
import json
from pathlib import Path
import re
import subprocess
from zoneinfo import ZoneInfo
ROOT = Path(__file__).resolve().parents[4]
PLAN = ROOT / "docs/plans/original-completion-2026-10-02"
OUTPUT = ROOT / "artifacts/original-completion-2026-10-02/p00-p02-baseline"
def digest(path):
return sha256(path.read_bytes()).hexdigest() if path.is_file() else None
def main():
OUTPUT.mkdir(parents=True, exist_ok=True)
baseline = json.loads((PLAN / "baseline.json").read_text())
map_path = ROOT / "artifacts/facility-need-pricing-production-scale-adoption-2026-10-01-r01/after.json"
adopted = json.loads(map_path.read_text())
current = {path: digest(ROOT / path) for path in adopted}
changes = [path for path in adopted if current[path] != adopted[path]]
pins = {path: {"expected": expected, "actual": digest(ROOT / path),
"passed": digest(ROOT / path) == expected}
for path, expected in baseline["source_pins"].items()}
review_path = ROOT / "artifacts/facility-need-pricing-r02-full155-independent-review-2026-10-01-r01/actual155-source-marker-review.json"
review = json.loads(review_path.read_text())
rows = []
for previous in review["rows"]:
path = ROOT / previous["test"]
log = Path(previous["actual_log"])
content = log.read_text() if log.is_file() else ""
marker = previous["actual_marker"]
match = re.search(r"checks=(\d+)|(\d+)(?: [A-Za-z]+)* checks", marker)
observed_count = int(next(g for g in match.groups() if g is not None)) if match else None
source_matches = digest(path) == previous["actual_source_sha256"]
log_matches = digest(log) == previous["actual_log_sha256"]
marker_matches = bool(content) and content.count(marker) == 1
diagnostics_clear = bool(content) and not any(s in content for s in ("SCRIPT ERROR:", "\nERROR:", "FAIL:"))
passed = (source_matches and log_matches and marker_matches and diagnostics_clear
and observed_count == previous["actual_checks"]
and previous["exit_code"] == 0 and previous["failed"] is False)
rows.append({"test": previous["test"], "source_matches": source_matches,
"retained_log": str(log), "log_matches": log_matches,
"unique_completion_marker": marker_matches,
"diagnostics_clear": diagnostics_clear,
"actual_checks": observed_count, "passed": passed})
discovered = {"tests/run_tests.gd"} | {
str(p.relative_to(ROOT)) for p in (ROOT / "tests").rglob("test*.gd")
if "export" not in p.relative_to(ROOT).parts
and str(p.relative_to(ROOT)) != "tests/s0/test_kernel_and_save.gd"}
recorded = {r["test"] for r in rows}
actual_checks = sum(r["actual_checks"] or 0 for r in rows)
head = subprocess.check_output(["git", "rev-parse", "HEAD"], cwd=ROOT, text=True).strip()
result = {
"scope": "retained regression applicability, not full original acceptance",
"audited_at_jst": datetime.now(ZoneInfo("Asia/Tokyo")).isoformat(),
"source_head": head, "baseline_head_matches": head == baseline["source_head"],
"source_map": str(map_path.relative_to(ROOT)), "source_map_sha256": digest(map_path),
"adopted_files": len(adopted), "changed_paths": changes, "source_pins": pins,
"retained_review": str(review_path.relative_to(ROOT)), "retained_review_sha256": digest(review_path),
"suites": len(rows), "actual_checks": actual_checks,
"uncovered_discovered_tests": sorted(discovered - recorded),
"stale_recorded_tests": sorted(recorded - discovered),
"duplicate_tests": len(rows) != len(recorded),
"rows": rows, "new_engine_runs": 0,
"retained_regression_applicable": (head == baseline["source_head"] and not changes
and all(p["passed"] for p in pins.values()) and recorded == discovered
and len(rows) == len(recorded) == 155 and actual_checks == 12310
and all(row["passed"] for row in rows)),
"original_full_acceptance": False,
}
(OUTPUT / "source-current.json").write_text(json.dumps(current, ensure_ascii=False, indent=2) + "\n")
(OUTPUT / "verification.json").write_text(json.dumps(result, ensure_ascii=False, indent=2) + "\n")
print(json.dumps({k: v for k, v in result.items() if k not in ("rows", "source_pins")}, ensure_ascii=False))
return 0 if result["retained_regression_applicable"] else 1
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,109 @@
"""Re-audit immutable r03 logs; retain original marker-collector rejection."""
from pathlib import Path
import hashlib
import importlib.util
import json
import re
import shutil
ROOT = Path(__file__).resolve().parents[4]
BASE = ROOT / 'artifacts/original-completion-2026-10-02'
INPUT = BASE / 'full-regression-r03'
OUTPUT = BASE / 'full-regression-r03-review-r01'
def sha(p):
return hashlib.sha256(p.read_bytes()).hexdigest()
def read(p):
return json.loads(p.read_text())
def write(p, value):
with p.open('x') as f:
f.write(json.dumps(value, ensure_ascii=False, indent=2) + '\n')
def require(ok, label):
if not ok:
raise ValueError(label)
def module(path, name):
spec = importlib.util.spec_from_file_location(name, path)
result = importlib.util.module_from_spec(spec)
spec.loader.exec_module(result)
return result
def completion(test, text, previous):
# Only the two rejected schemas change. All other retained exact markers
# and every engine/exit/source/raw-byte gate remain in force.
if test == 'tests/performance/test_snapshot_ownership.gd':
matches = re.findall(r'^Snapshot ownership: (\d+) checks, 0 failures\n', text, re.M)
require(len(matches) == 1, 'Unique ownership completion')
return int(matches[0]), f'Snapshot ownership: {matches[0]} checks, 0 failures\n'
if test == 'tests/ui/test_supply_auto_purchase_ui.gd':
matches = re.findall(r'^SUPPLY_AUTO_PURCHASE_UI checks=(\d+) failures=0\n', text, re.M)
require(len(matches) == 1, 'Unique auto UI completion')
return int(matches[0]), f'SUPPLY_AUTO_PURCHASE_UI checks={matches[0]} failures=0\n'
require(previous['passed'] and text.count(previous['completion_marker']) == 1, 'Retained exact marker')
return previous['actual_checks'], previous['completion_marker']
def main():
require(not OUTPUT.exists(), 'Fresh output only')
original = read(INPUT / 'verification.json')
require(not original['passed'] and original['runner_exit_code'] == 0 and original['changed_paths'] == [], 'Expected collector-only rejection')
changed = ['tests/performance/test_snapshot_ownership.gd', 'tests/ui/test_supply_auto_purchase_ui.gd']
require(original['failed_tests'] == changed, 'Only expected marker rejections')
pins = read(INPUT / 'source-start.json')
require(pins == read(INPUT / 'source-end.json') and sha(INPUT / 'source-start.json') == sha(INPUT / 'source-end.json') == original['source_map_sha256'], 'Stable full input bytes')
require(original['wrapper_unchanged'] and sha(INPUT / 'wrapper-input.py') == original['wrapper_sha256'] == original['wrapper_sha256_after'], 'Execution wrapper unchanged')
require(sha(INPUT / 'suites/all-tests.json') == original['all_results_sha256'], 'Raw runner result SHA')
wrapper = module(INPUT / 'wrapper-input.py', 'execution_wrapper')
wrapper.ROOT = ROOT
require(wrapper.source_map() == pins, 'Current production equals execution source')
roster = read(INPUT / 'expected-tests.json')
rows = read(INPUT / 'suites/all-tests.json')
require(roster == [r['test'] for r in rows] == [r['test'] for r in original['rows']] and len(set(roster)) == len(roster), 'Unique ordered actual roster')
adapter_path = BASE / 'windows-current-release-adapter-prep-r01/windows_adapter.py'
independent = module(adapter_path, 'independent_completion')
independent.SPECIAL_MARKERS['tests/ui/test_supply_auto_purchase_ui.gd'] = r'SUPPLY_AUTO_PURCHASE_UI checks=(\d+) failures=0'
reviewed = []
for raw, old in zip(rows, original['rows']):
test = raw['test']
require(raw['exit_code'] == 0 and raw['failed'] is False and old['source_sha256'] == pins[test], 'Actual pass and test source')
log = INPUT / 'suites' / raw['log']
require(raw['log'] == old['log'] and Path(raw['log']).name == raw['log'] and sha(log) == old['log_sha256'], 'Exact ordinary raw log')
text = log.read_text()
require('Godot Engine v4.7.2' in text and not re.search(r'(?m)^\s*(?:SCRIPT ERROR|ERROR|Parse Error):', text), 'Clean engine completion')
count, marker = completion(test, text, old)
other_count, other_marker = independent.completion(test, text)
require((count, marker.rstrip('\n')) == (other_count, other_marker) and count > 0, 'Independent parser agreement')
reviewed.append(dict(old, actual_checks=count, completion_marker=marker, passed=True))
# The ownership source is unchanged and enumerates every runtime section
# in both the new-game and populated captures. Added auto_purchase_plans
# accounts for two additional checks, with no weakened assertion.
old_map = read(BASE / 'full-regression-r02/source-end.json')
ownership = 'tests/performance/test_snapshot_ownership.gd'
require(old_map[ownership] == pins[ownership], 'Ownership test source unchanged')
ownership_text = (ROOT / ownership).read_text()
require('for section: Variant in expected[&"systems"][&"runtime"]:' in ownership_text and 'verify_detached(runtime, "new game")' in ownership_text and 'verify_detached(runtime, "populated game")' in ownership_text, 'Dynamic section count, two captures')
require('SUPPLY_AUTO_PURCHASE_UI checks=%d failures=%d' in (ROOT / changed[1]).read_text(), 'UI literal summary source')
negatives = []
for test, good in [(changed[0], 'Snapshot ownership: 91 checks, 0 failures\n'), (changed[1], 'SUPPLY_AUTO_PURCHASE_UI checks=28 failures=0\n')]:
for name, value in [('duplicate', good + good), ('failure', good.replace('0 failures', '1 failures').replace('failures=0', 'failures=1')), ('missing', '')]:
try:
completion(test, value, {})
except ValueError:
negatives.append({'test': test, 'case': name, 'rejected': True})
else:
raise ValueError('Negative marker accepted')
before = {str(p.relative_to(INPUT)): sha(p) for p in INPUT.rglob('*') if p.is_file()}
shutil.copytree(INPUT, OUTPUT)
(OUTPUT / 'verification.json').rename(OUTPUT / 'original-collector-verification.json')
shutil.copyfile(Path(__file__), OUTPUT / 'review-input.py')
report = dict(original, passed=True, checks=sum(r['actual_checks'] for r in reviewed), failed_tests=[], rows=reviewed, wrapper_copy_path=str(OUTPUT / 'wrapper-input.py'))
report['reaudit'] = {'scope': 'immutable actual r03 logs; engine not rerun', 'original_collector_passed': False, 'original_collector_verification_sha256': sha(INPUT / 'verification.json'), 'original_execution_directory': str(INPUT), 'review_sha256': sha(Path(__file__)), 'independent_parser_source_sha256': sha(adapter_path), 'narrow_marker_schema_corrections': changed, 'negative_controls': negatives, 'no_engine_execution': True, 'source_test_assertions_changed': False, 'original_full_acceptance': False, 'windows_acceptance': False}
write(OUTPUT / 'verification.json', report)
require(before == {str(p.relative_to(INPUT)): sha(p) for p in INPUT.rglob('*') if p.is_file()} and wrapper.source_map() == pins, 'Original evidence and production unchanged')
write(OUTPUT / 'review-integrity.json', {'original_files_unchanged': True, 'original_files': before, 'actual_suites':len(reviewed), 'actual_checks':report['checks'], 'source_changes': [], 'negative_controls_rejected': len(negatives), 'execution_wrapper_unchanged':True,'game_complete':False})
print(json.dumps({k: report[k] for k in ['passed','suites','checks','failed_tests','changed_paths']}, ensure_ascii=False))
if __name__ == '__main__':
main()
@@ -0,0 +1,61 @@
"""Reclaim only two ended, isolated failed-formal r01 Godot caches."""
from pathlib import Path
import hashlib
import json
import subprocess
ROOT = Path(__file__).resolve().parents[4]
ART = ROOT / "artifacts/original-completion-2026-10-02"
PACKET = ART / "p03-formal13-ui-to14-final-r01"
CACHES = [PACKET / "stages" / name / ".godot" for name in ("old", "new")]
RECEIPT = ART / "ended-private-test-cache-reclaim-r04.json"
def require(value, message):
if not value:
raise AssertionError(message)
def sha(path):
return hashlib.sha256(path.read_bytes()).hexdigest()
def preserved():
values = {}
for p in PACKET.rglob("*"):
require(not p.is_symlink(), "Symlink refused")
if p.is_file() and ".godot" not in p.relative_to(PACKET).parts:
values[p.relative_to(PACKET).as_posix()] = sha(p)
return values
def main():
require(not RECEIPT.exists(), "Fresh reclaim receipt required")
before = preserved()
require(len(before) > 2400, "Complete retained two-stage packet expected")
rows = []
for cache in CACHES:
require(cache.is_dir() and cache.resolve() == cache, "Exact owned cache directory required")
handles = subprocess.run(["lsof", "+D", str(cache)], text=True, capture_output=True)
require(handles.returncode == 1 and not handles.stdout and not handles.stderr, "Active/unverified cache handles")
processes = subprocess.run(["ps", "-axo", "pid=,command="], text=True, capture_output=True, check=True).stdout
require(not any(str(cache.parent) in line and ("Godot --" in line or "/godot --" in line) for line in processes.splitlines()), "Live owned Godot stage")
entries = list(cache.rglob("*"))
require(entries and not any(p.is_symlink() for p in entries), "Unsafe/empty cache inventory")
files = [p for p in entries if p.is_file()]
require(all(p.is_file() or p.is_dir() for p in entries), "Nonregular cache entry")
rows.append({"path": cache.relative_to(ROOT).as_posix(), "logical_bytes": sum(p.stat().st_size for p in files), "file_count": len(files), "lsof_exit_code": handles.returncode, "active_handles": 0, "live_owned_Godot": 0, "cache_SHA_before": {p.relative_to(cache).as_posix(): sha(p) for p in files}})
require(preserved() == before, "Preserved packet changed before removal")
for cache in CACHES:
for p in sorted(cache.rglob("*"), key=lambda p: len(p.parts), reverse=True):
p.unlink() if p.is_file() else p.rmdir()
cache.rmdir()
require(preserved() == before and all(not p.exists() for p in CACHES), "Noncache/QA UID/raw bytes changed")
receipt = {"passed": True, "scope": "regenerable .godot only from ended failed isolated formal r01, all source/QA UID/raw/profile packet entries retained", "rows": rows, "logical_bytes_reclaimed": sum(r["logical_bytes"] for r in rows), "preserved_noncache_files": len(before), "preserved_noncache_SHA": before, "preserved_SHA_changes": [], "production_source_edits": 0, "player_profile_cleanup": False, "new_engine_runs": 0}
with RECEIPT.open("x") as stream:
stream.write(json.dumps(receipt, ensure_ascii=False, indent=2) + "\n")
print(json.dumps({k: receipt[k] for k in ("passed", "logical_bytes_reclaimed", "preserved_noncache_files", "preserved_SHA_changes")}, ensure_ascii=False))
if __name__ == "__main__":
main()
@@ -0,0 +1,70 @@
# -*- coding: utf-8 -*-
"""Reclaim exact ended test-stage caches, preserving source, UID, and raw proof."""
from pathlib import Path
import hashlib
import json
import subprocess
ROOT = Path(__file__).resolve().parents[4]
ART = ROOT / "artifacts/original-completion-2026-10-02"
STAGES = [
ART / "ui-audio-lifecycle-diagnostic-r01/stage",
ART / "ui-audio-lifecycle-diagnostic-r02/stage",
ART / "ui-audio-and-presentation-candidate-r04/focused-run-r01/stage",
ART / "runtime-scale-diagnostic-max20000-r02/stage",
ART / "p03-cleaning-day-boundary-paired-r01/stages/day_boundary",
Path("/private/tmp/thetree-p03-rescue-96db3161ccdb/stage"),
]
RECEIPT = ART / "ended-private-probe-cache-reclaim-r01.json"
def require(value, label):
if not value:
raise AssertionError(label)
def sha(path):
return hashlib.sha256(path.read_bytes()).hexdigest()
def preserved(stage):
result = {}
for path in stage.rglob("*"):
require(not path.is_symlink(), "Stage symlink refused")
if path.is_file() and ".godot" not in path.relative_to(stage).parts:
result[path.relative_to(stage).as_posix()] = sha(path)
require(len(result) >= 1224, "Full stage noncache source expected")
return result
def main():
require(not RECEIPT.exists(), "Fresh receipt required")
processes = subprocess.run(["ps", "-axo", "pid=,comm="], capture_output=True, text=True)
require(processes.returncode == 0 and not processes.stderr, "Readable executable inventory before cleanup")
live_engines = [line for line in processes.stdout.splitlines() if "godot" in line.lower()]
require(not live_engines, "No live Godot before cleanup, including lowercase executable names")
rows = []
for stage in STAGES:
cache = stage / ".godot"
require(stage.resolve() == stage and cache.is_dir() and cache.resolve() == cache, "Exact ended stage/cache required")
handles = subprocess.run(["lsof", "+D", str(cache)], capture_output=True, text=True)
require(handles.returncode == 1 and not handles.stdout and not handles.stderr, "No active cache handles")
entries = list(cache.rglob("*"))
require(entries and all(not p.is_symlink() and (p.is_file() or p.is_dir()) for p in entries), "Regular owned cache entries only")
files = [p for p in entries if p.is_file()]
rows.append({"stage": str(stage), "cache": str(cache), "logical_bytes": sum(p.stat().st_size for p in files), "cache_files": len(files), "cache_sha_before": {p.relative_to(cache).as_posix():sha(p) for p in files}, "noncache_sha_before": preserved(stage), "lsof_exit_code": 1, "active_handles": 0})
require(all(preserved(stage) == row["noncache_sha_before"] for stage,row in zip(STAGES,rows)), "Noncache stable before removal")
for stage in STAGES:
cache = stage / ".godot"
for path in sorted(cache.rglob("*"), key=lambda p:len(p.parts), reverse=True):
path.unlink() if path.is_file() else path.rmdir()
cache.rmdir()
require(all(preserved(stage) == row["noncache_sha_before"] and not (stage/".godot").exists() for stage,row in zip(STAGES,rows)), "All noncache/source/QA UID bytes retained")
with RECEIPT.open("x", encoding="utf-8") as file:
json.dump({"passed": True, "scope": "Exact declared ended private test-stage .godot caches only; all source/actual QA UID/outer raw/typed/formal evidence retained", "declared_stage_count": len(STAGES), "rows": rows, "logical_bytes_reclaimed": sum(r["logical_bytes"] for r in rows), "preserved_noncache_files": sum(len(r["noncache_sha_before"]) for r in rows), "noncache_SHA_changes": [], "production_source_edits": 0, "player_profile_cleanup": False, "engine_runs": 0}, file, ensure_ascii=False, indent=2)
file.write("\n")
print(json.dumps({"passed": True, "logical_bytes_reclaimed": sum(r["logical_bytes"] for r in rows), "noncache_files_preserved": sum(len(r["noncache_sha_before"]) for r in rows)}))
if __name__ == "__main__":
main()
@@ -0,0 +1,70 @@
# -*- coding: utf-8 -*-
"""Independent raw review of the preserved Staff failure/geometry contrast."""
from pathlib import Path
import hashlib
import json
import re
import subprocess
ROOT = Path(__file__).resolve().parents[4]
ART = ROOT / "artifacts/original-completion-2026-10-02"
BASE = ART / "ui-audio-staff-repeat-r01/run-r01"
FIX = ART / "ui-audio-staff-geometry-repeat-prep-r01/run-r01"
OUT = ART / "ui-audio-staff-geometry-root-review-r01.json"
def require(ok, message):
if not ok:
raise AssertionError(message)
def sha(p):
return hashlib.sha256(p.read_bytes()).hexdigest()
def read(p):
return json.loads(p.read_text(encoding="utf-8"))
def main():
require(not OUT.exists(), "Fresh root review")
counts = {}; rows = []; all_pids = []
for name, folder, failure in (("baseline", BASE, 1), ("geometry", FIX, 0)):
receipt = read(folder / "execution.json")
require(receipt["source_changes"] == receipt["input_changes"] == [] and receipt["engine_unchanged"] and receipt["source_files"] == 1246, "Same isolated stage input")
require(receipt["original_expectations_unchanged"] and receipt["observer_added"] is False and receipt["formal_acceptance"] is False, "Limited unchanged expectations")
require(len(receipt["rows"]) == 3 and receipt["actual_checks"] == 393 and receipt["strict_pass"] is (failure == 0), "Honest contrast result")
total = 0
for row in receipt["rows"]:
n = row["repeat"]
raw = folder / "logs" / ("repeat-%d.log" % n)
text = raw.read_text(encoding="utf-8")
profile = folder / ("profile-%d.json" % n)
require(sha(raw) == row["log_sha256"] and sha(profile) == row["profile_report_sha256"], "Actual raw/profile pins")
require(re.findall(r"^Staff management UI: (\d+) checks, (\d+) failures$", text, re.M) == [("131", str(failure))], "Unique raw actual marker")
require("Godot Engine v4.7.2.stable.official.ed1daf0bf" in text and "SCRIPT ERROR" not in text and "Parse Error" not in text and "resources still in use" not in text and "leaked at exit" not in text, "Actual engine/no script/resource errors")
errors = [line for line in text.splitlines() if line.startswith("ERROR:")]
require(errors == (["ERROR: unreachable drag preserves staff and explains route failure"] if failure else []), "Only exact preserved baseline failure")
guard = read(profile)
require(guard == row["actual_profile"] and guard["verified"] and guard["conditions"] == [True]*5 and guard["conditions_checked"] == 5 and guard["fresh_before_parent_initialize"] and guard["profile_writes_before_guard"] == 0, "Actual five private guards")
require(row["checks"] == 131 and row["failures"] == failure and row["exit_code"] == failure and row["engine_ended"], "Actual process/count/exit binding")
all_pids.append(row["owned_engine_pid"]); total += 131
rows.append({"case": name, "pid": row["owned_engine_pid"], "checks": 131, "failures": failure, "raw_sha256": sha(raw), "profile_sha256": sha(profile)})
counts[name] = {"checks": total, "failures": failure*3, "execution_sha256": sha(folder / "execution.json")}
require(len(set(all_pids)) == 6, "Six actual distinct owned processes")
status = subprocess.run(["ps", "-p", ",".join(map(str,all_pids)), "-o", "pid=,comm="], capture_output=True, text=True)
require(status.returncode == 1 and status.stdout == status.stderr == "", "All six owned PIDs ended")
source = ROOT / "tests/ui/test_staff_management.gd"
geometry = ART / "ui-audio-and-presentation-candidate-r07/candidate/tests/ui/test_staff_management.gd"
original = source.read_text(encoding="utf-8")
token = "func _drag_staff_to(target: Vector2, cell: Variant = null, before_release := Callable()) -> void:\n"
require(original.count(token) == 1 and geometry.read_text(encoding="utf-8") == original.replace(token, token + "\t# Let restored roster layout finish before reading the card to press.\n\tawait process_frame\n"), "Only layout-frame synchronization before reading geometry")
require(sha(source) == "6bd701cf3ac2386768db34b59d6298bed3f59a3aed0795e0854134051cdcf2e0" and sha(geometry) == "42595c39a933bfceffaab54d5169bbacfaca1d593cc3bcd099e72a354b77c428", "Source/script pins")
historical = ART / "ui-audio-and-presentation-candidate-r06/focused-run-r01/execution.json"
require(sha(historical) == "cb8ace997b3e22fff39a5fdb62cbd5f75a1c6a097b180486edbdcdebb1216011", "r06 failed execution retained")
OUT.write_text(json.dumps({"passed": True, "scope": "Limited QA geometry contrast; no production adoption/full9/game acceptance", "cases": counts, "rows": rows, "all_owned_PIDs_ended": True, "source_expectations_and_input_API_unchanged": True, "geometry_difference": "one process_frame before card/start geometry is read", "detailed_deferred_layout_cause_confirmed": False, "r06_failed_execution_SHA_retained": sha(historical), "production_game_changes": [], "engine_runs_by_root_review": 0, "full9_focused_accepted": False, "whole_P03_accepted": False, "normal_human_play_accepted": False, "native_Windows_accepted": False}, ensure_ascii=False, indent=2)+"\n", encoding="utf-8")
print("Root geometry contrast PASS: original393/3 retained, synchronized393/0;all6PIDs ended;input/expectations unchanged")
if __name__ == "__main__":
main()
@@ -0,0 +1,74 @@
#!/usr/bin/env python3
"""Root readonly review; this never imports or starts the game engine."""
import hashlib
import json
import subprocess
from pathlib import Path
ROOT = Path('/Users/korizatou114/Projects/とりにく工房ゲーム制作部')
ART = ROOT / 'artifacts/original-completion-2026-10-02'
def sha(path):
return hashlib.sha256(path.read_bytes()).hexdigest()
def verify_seal(name):
folder = ART / name
seal = folder / 'input-seal.json'
pins = json.loads(seal.read_text())['files']
actual = {str(p.relative_to(folder)) for p in folder.rglob('*') if p.is_file()}
assert actual == set(pins) | {'input-seal.json'}, (name, actual ^ (set(pins) | {'input-seal.json'}))
assert all(sha(folder / key) == value for key, value in pins.items()), name
return {'seal_sha256': sha(seal), 'pinned_files': len(pins), 'exact_set': True, 'byte_mismatches': 0}
def main():
close_name = 'ui-audio-graceful-close-candidate-r01'
merge_name = 'ui-audio-kitchen-business-merge-prep-r01'
close = ART / close_name
merge = ART / merge_name
reviewed = {close_name: verify_seal(close_name), merge_name: verify_seal(merge_name)}
source_file = ART / 'p05-current-stage-input-r04/candidate-source.json'
source = json.loads(source_file.read_text())
differences = [key for key, expected in source.items() if not (ROOT / key).is_file() or sha(ROOT / key) != expected]
assert len(source) == 1224 and not differences, differences
# Reproduce the actual three-way merge independently, then apply its sole
# kitchen submission routing addition. All old bytes are preserved.
merged = subprocess.run(['git', 'merge-file', '-p', str(merge / 'originals/audio-r07.gd'), str(merge / 'originals/base.gd'), str(merge / 'originals/kitchen-r08.gd')], capture_output=True, check=False)
assert merged.returncode == 0 and not merged.stderr, merged.stderr
old = b'_runtime.call(&"submit_command", KITCHEN_COMMAND, payload, &"player", selected_facility_id, 75, -1, key)'
new = b'_submit_ui_command(KITCHEN_COMMAND, payload, &"player", selected_facility_id, 75, -1, key)'
assert merged.stdout.count(old) == 1
combined_file = merge / 'candidate/scripts/ui/business_management_panel.gd'
assert merged.stdout.replace(old, new, 1) == combined_file.read_bytes()
combined = combined_file.read_text()
kitchen = (merge / 'originals/kitchen-r08.gd').read_text()
strip = combined.replace('var _audio_submitter := Callable()\n', '', 1)
strip = strip.replace('_submit_ui_command(KITCHEN_COMMAND, payload, &"player", selected_facility_id, 75, -1, key)', '_runtime.call(&"submit_command", KITCHEN_COMMAND, payload, &"player", selected_facility_id, 75, -1, key)', 1)
strip = strip.replace('_submit_ui_command(COMMAND, payload, &"player", selected_facility_id, 75, -1, key)', '_runtime.call(&"submit_command", COMMAND, payload, &"player", selected_facility_id, 75, -1, key)', 1)
strip = strip.split('\n\nfunc configure_audio(submitter: Callable) -> void:', 1)[0]
assert strip == kitchen
proof = {
'scope': 'Root independent static review only; engine execution and adoption pending',
'sealed_packets': reviewed,
'source_files': len(source), 'source_mismatches': differences,
'three_way_merge_actual_exit': merged.returncode,
'additional_kitchen_submission_routing_occurrences': 1,
'combined_business_sha256': sha(combined_file),
'kitchen_exact_reconstruction_without_audio_hook': True,
'close_candidate_full_diff_and_helper_read_by_root': True,
'required_actual_checks': ['running Clock whole typed Runtime/config invariance', 'active/inactive real root close', 'modal/root/owned Window GUI input suppression', 'multi Main removal and late registration', 'all owned WeakRefs dead within deadline before one quit', 'normal last owner removal restores original auto_accept_quit', 'all Main dependent fixtures and fresh full roster'],
'game_engine_processes_started': 0,
'production_game_changes': 0,
'formal_acceptance': False,
'native_Windows': 'pending'
}
output = ART / 'ui-audio-kitchen-static-root-review-r01.json'
assert not output.exists(), output
output.write_text(json.dumps(proof, ensure_ascii=False, indent=2) + '\n')
print(json.dumps({'receipt': str(output), 'sha256': sha(output), 'source_files': len(source), 'pinned_files': sum(x['pinned_files'] for x in reviewed.values()), 'engine_processes': 0, 'production_changes': 0}))
if __name__ == '__main__':
main()
@@ -0,0 +1,126 @@
"""Read-only root review of current distribution and macOS same-PCK proofs."""
from pathlib import Path
import hashlib
import importlib.util
import json
import re
import zipfile
ROOT = Path(__file__).resolve().parents[4]
ART = ROOT / "artifacts/original-completion-2026-10-02"
OUT = ART / "windows-current-release-root-review-r01"
PACKAGE = ART / "windows-current-release-candidate-r03"
PROOF = ART / "windows-current-release-same-pck-r01"
KIT = ART / "native-windows-current-release-kit-r01"
def sha(path):
value = hashlib.sha256()
with path.open("rb") as stream:
for block in iter(lambda: stream.read(1024 * 1024), b""):
value.update(block)
return value.hexdigest()
def read(path):
return json.loads(path.read_text())
def require(value, message):
if not value:
raise AssertionError(message)
def main():
require(not OUT.exists(), "Fresh review output required")
adapter_path = ART / "windows-current-release-adapter-prep-r04/windows_adapter.py"
require(sha(adapter_path) == "fbc11778be400204922d69599e873d06d75adca28d9cf94d171b2fbac211ff74", "Adapter bytes changed")
spec = importlib.util.spec_from_file_location("reviewed_windows_adapter", adapter_path)
adapter = importlib.util.module_from_spec(spec)
spec.loader.exec_module(adapter)
pins = read(PACKAGE / "source-start.json")
require(len(pins) == 1224 and adapter.inventory(ROOT) == pins, "Current source map differs")
tracked = {}
def pin(path, expected=None):
actual = sha(path)
require(expected is None or actual == expected, f"Evidence SHA differs: {path}")
tracked[path.relative_to(ROOT).as_posix()] = actual
return actual
verification = read(PROOF / "verification.json")
require(verification["passed"] and verification["actual_checks"] == 626 and len(verification["rows"]) == 5, "Five actual suites required")
require(verification["Godot_processes_started"] == 5 and verification["source_changes"] == [], "Actual process/source receipt differs")
require(verification["native_Windows"] == "pending" and not verification["formal_acceptance"] and not verification["visual_acceptance"], "Scope was promoted")
pin(PROOF / "verification.json")
pin(PROOF / "root-source-after-verification.json")
integrity = read(PACKAGE / "package-integrity.json")
pin(PACKAGE / "package-integrity.json")
export = read(PACKAGE / "export-validation.json")
pin(PACKAGE / "export-validation.json")
require(export["export_passed"] and export["runtime_inputs"] == 852 and export["source_changes"] == [] and export["clone_import_changes"] == [], "Export/source gate differs")
require(export["import"]["exit_code"] == export["export"]["exit_code"] == 0, "Export process failed")
require(export["diagnostic_preset"]["modify_resources"] is False and not export["diagnostic_preset"]["exe_resource_presentation_acceptance"], "Unmodified EXE scope missing")
for phase in ("import", "export"):
pin(PACKAGE / (phase + ".stdout.log"), export[phase]["stdout_sha256"])
pin(PACKAGE / (phase + ".engine.log"), export[phase]["engine_log_sha256"])
archive = PACKAGE / "TheTree-Windows-current-source-release-candidate.zip"
pin(archive, "736cbc4809266fb34143e7c1b41e928912bec4d35ccf6818095d502b53fdbc14")
require(archive.stat().st_size == integrity["zip_bytes"] and integrity["CRC_pass"] and integrity["each_member_SHA_pass"], "ZIP receipt differs")
with zipfile.ZipFile(archive) as z:
require(z.testzip() is None and sorted(z.namelist()) == sorted(integrity["members"]), "ZIP CRC/members failed")
for member, expected in integrity["members"].items():
value = hashlib.sha256()
with z.open(member) as stream:
for block in iter(lambda: stream.read(1024 * 1024), b""):
value.update(block)
require(value.hexdigest() == expected, f"ZIP member SHA differs: {member}")
pin(PACKAGE / "distribution" / member, expected)
require(read(PACKAGE / "distribution/TheTree/SOURCE_MANIFEST.json") == pins, "Distributed source inventory differs")
for kind in ("EXE", "PCK", "ZIP"):
require(verification[kind + "_sha256"] == (integrity["zip_sha256"] if kind == "ZIP" else export[kind + "_sha256"]), f"Subset used different {kind}")
rows = []
for row in verification["rows"]:
name = row["name"]
require(row["passed"] and row["exit_code"] == 0 and row["actual_checks"] == row["expected_checks"] and row["error"] is None, f"Suite failed: {name}")
require(row["PCK_sha256"] == verification["PCK_sha256"], f"Different PCK: {name}")
driver = Path(row["argv"][row["argv"].index("--script") + 1])
pin(driver, row["driver_sha256"])
profile_path = PROOF / (name + "-actual-profile.json")
pin(profile_path, row["profile_report_sha256"])
guard = read(profile_path)
require(guard["verified"] and guard["conditions_checked"] == 5 and guard["conditions"] == [True] * 5, f"Profile guard failed: {name}")
require(guard["actual_user_data_dir"] == guard["expected_user_data_dir"] == row["fresh_actual_profile"], f"Actual profile differs: {name}")
require(guard["globalized_probe"] == row["fresh_actual_profile"] + "/guard-probe" and guard["fresh_before_parent_initialize"] and guard["profile_writes_before_guard"] == 0 and guard["runtime_settings_only"] and not guard["project_settings_persisted"], f"Profile safety differs: {name}")
for suffix, key in (("stdout.log", "stdout_sha256"), ("engine.log", "engine_log_sha256")):
raw = PROOF / (name + "." + suffix)
pin(raw, row[key])
text = raw.read_text()
require("Godot Engine v4.7.2.stable.official.ed1daf0bf" in text and not re.search(r"(?m)^\s*(?:SCRIPT ERROR|ERROR|Parse Error):", text) and "Unicode parsing error" not in text, f"Engine diagnostic: {name}")
require(text.splitlines().count(row["completion_marker"]) == 1, f"Completion marker not unique: {name}")
count, marker = adapter.completion(row["test"], text)
require(count == row["actual_checks"] and marker == row["completion_marker"], f"Raw count differs: {name}")
rows.append({"test": row["test"], "actual_checks": row["actual_checks"], "exit_code": row["exit_code"], "profile_conditions": 5})
manifest = read(KIT / "kit-manifest.json")
pin(KIT / "kit-manifest.json", "2126a2bddc5003ee5e71a4f4c660a9414b69babe2726442229180953028d713c")
actual_kit = {p.relative_to(KIT).as_posix() for p in KIT.rglob("*") if p.is_file()}
require(actual_kit == set(manifest["files"]) | {"kit-manifest.json"}, "Unexpected kit files")
for name, expected in manifest["files"].items():
pin(KIT / name, expected)
expected = read(KIT / "expected.json")
require(expected["source_files"] == 1224 and expected["full_actual_suites"] == 164 and expected["full_actual_checks"] == 13248, "Kit context differs")
require(expected["Godot_processes_started"] == expected["Windows_launches"] == 0 and expected["native_Windows"] == "pending" and expected["PowerShell_syntax_parse"] == "unverified" and expected["final_acceptance_rate"] is None, "Kit execution was promoted")
require(sum(x["expected_checks_from_actual_current_full"] for x in expected["drivers"]) == 626, "Kit expected subset count differs")
for driver in expected["drivers"]:
marker = next(x["completion_marker"] for x in verification["rows"] if x["test"] == driver["test"])
hits = [m for pattern in driver["completion_patterns"] if (m := re.fullmatch(pattern, marker))]
require(len(hits) == 1 and int(hits[0][1]) == driver["expected_checks_from_actual_current_full"], "Kit regex differs from actual retained marker")
require(adapter.inventory(ROOT) == pins and all(sha(ROOT / name) == digest for name, digest in tracked.items()), "Inputs changed during root review")
OUT.mkdir()
result = {"passed": True, "scope": "root raw/SHA review of current export, package, macOS same-PCK626 and artifact-only native kit", "source_files": 1224, "runtime_export_inputs": 852, "source_changes": [], "same_PCK_actual_checks": 626, "same_PCK_suites": rows, "reviewed_pins": tracked, "kit_files": len(manifest["files"]), "ZIP_CRC_and_member_SHA_pass": True, "engine_runs_by_review": 0, "native_Windows": "pending", "PowerShell_parser": "unverified", "CSharp_compile": "unverified", "visual_acceptance": False, "performance_acceptance": False, "finished_EXE_resources_acceptance": False, "whole_original_acceptance": False, "final_acceptance_rate": None}
(OUT / "review.json").write_text(json.dumps(result, ensure_ascii=False, indent=2) + "\n")
print(json.dumps({k: v for k, v in result.items() if k not in ("reviewed_pins", "same_PCK_suites")}, ensure_ascii=False))
if __name__ == "__main__":
main()
@@ -0,0 +1,74 @@
# -*- coding: utf-8 -*-
"""Recheck immutable rendered day-boundary paired-save subset evidence."""
from pathlib import Path
import importlib.util
import json
import re
import struct
import sys
sys.dont_write_bytecode = True
ROOT = Path(__file__).resolve().parents[4]
ART = ROOT / "artifacts/original-completion-2026-10-02"
P = ART / "p03-cleaning-day-boundary-paired-r02"
OUT = ART / "p03-day-boundary-root-review-r01.json"
spec = importlib.util.spec_from_file_location("day_boundary_source_guard", ROOT / "docs/plans/original-completion-2026-10-02/execution/review_rescue_scale_checkpoint.py")
guard = importlib.util.module_from_spec(spec)
spec.loader.exec_module(guard)
sha, read, require = guard.sha, guard.read, guard.require
def main():
require(not OUT.exists(), "Fresh review required")
seal = read(P / "evidence-seal.json")
require(len(seal["nonstage_files"]) == 131 and all(sha(P / n) == h for n,h in seal["nonstage_files"].items()), "All131 immutable raw proof pins")
receipt = read(P / "acceptance-subset-receipt.json")
pins = read(P / "supplied-source-map.json")
require(len(pins) == 1224 and pins == read(P / "input-source-before.json") == read(P / "input-source-end.json") == guard.source() and read(P / "input-source-change.json") == [], "Actual current adopted source exact before/end")
summary = read(P / "summary.json")
counts = {}
require(summary["error"] is None and len(summary["phases"]) == 6 and len({r["pid"] for r in summary["phases"]}) == 6, "Actual six distinct phases")
for row in summary["phases"]:
log = P / "phases" / row["name"] / "raw.log"
text = log.read_text()
require(sha(log) == row["raw_log_sha256"] and row["passed"] and row["exit_code"] == 0 and not any(s in text for s in ("SCRIPT ERROR", "Parse Error", "ERROR:")), "Actual raw/clean exit")
role = row["name"].removeprefix("day_boundary-")
if role in ("write", "read"):
markers = re.findall(r"^P03_MIDPOINT_COMPLETE scenario=day_boundary phase=" + role + r" nonce=([^ ]+) checks=(\d+) failures=(\d+)$", text, re.M)
require(len(markers) == 1 and markers[0][2] == "0" and int(markers[0][1]) == row["checks"], "Unique actual completion count")
profile = read(P / ("evidence/day_boundary/" + role + "-profile-before-parent.json"))
require(profile["pid"] == row["pid"] and profile["nonce"] == markers[0][0] and profile["verified"] and profile["conditions"] == [True]*6 and profile["conditions_checked"] == 6 and profile["phase"] == role, "Actual private6 conditions before parent")
result = read(P / ("evidence/day_boundary/" + role + "-result.json"))
counts[role] = row["checks"]
require(counts == {"write": 83, "read": 100}, "Actual183/0 counts")
comparisons = read(P / "whole-typed-comparisons.json")
require(comparisons["actual_pairs"] == 12 and comparisons["all_passed"] and len(comparisons["pairs"]) == 12, "Twelve full typed pairs")
for pair in comparisons["pairs"]:
left, right = P / pair["left"], P / pair["right"]
require(left.read_bytes() == right.read_bytes() and sha(left) == pair["left_sha256"] and sha(right) == pair["right_sha256"] and pair["field_exclusions"] == [] and pair["event_deletion_count"] == 0, "Independent entire typed bytes, no exclusions/deletions")
if "writer_raw_event" in pair:
w,r = pair["writer_raw_event"], pair["reader_raw_event"]
require({k:v for k,v in w.items() if k not in ("event_type", "payload")} == {k:v for k,v in r.items() if k not in ("event_type", "payload")}, "Exact IO identity/envelope")
require(pair["writer_event_replaced_count"] == pair["reader_event_count"] == 1 and w["event_type"] == "SAVE_CHECKPOINT_SUCCEEDED" and r["event_type"] == "SAVE_RECOVERY_LOADED", "One actual manual save to normal UI formal recovery IO")
require(w["absolute_minute"] == r["absolute_minute"] == 2879 and w["payload"]["save_id"] == r["payload"]["save_id"] == "manual" and w["payload"]["save_path"] == r["payload"]["save_path"], "Bound actual checkpoint and save")
require(r["payload"]["selected_candidate_id"] == r["payload"]["selected_candidate_kind"] == "formal" and r["payload"]["selected_generation"] == -1 and r["payload"]["operation"] == "recovery" and r["payload"]["ok"] is True, "Formal chosen by actual normal recovery")
package = Path(receipt["formal_package_retained_path"])
require({f.relative_to(package).as_posix():sha(f) for f in package.rglob("*") if f.is_file()} == receipt["formal_4files_SHA_unchanged"] and len(receipt["formal_4files_SHA_unchanged"]) == 4, "Live original formal4 entries unchanged at root review")
evidence = P / "evidence/day_boundary"
require(read(evidence / "write-package-end.json") == read(evidence / "read-package-end.json"), "Writer/reader formal proof equality")
pngs = []
direct = {"write-checkpoint.png", "read-checkpoint.png", "read-final.png", "read-followup.png"}
for name,h in receipt["rendered_PNG"].items():
path = P / name
require(sha(path) == h and path.read_bytes()[:8] == b"\x89PNG\r\n\x1a\n" and struct.unpack(">II",path.read_bytes()[16:24]) == (1280,720), "Actual1280x720 pinned PNG")
pngs.append({"path": path.relative_to(ROOT).as_posix(), "sha256": h, "review": "direct_pixels" if path.name in direct else "same_bytes_as_reviewed_reader"})
require(sha(evidence / "write-final.png") == sha(evidence / "read-final.png") and sha(evidence / "write-followup.png") == sha(evidence / "read-followup.png"), "Other2 captures exactly reviewed pixels")
settled = read(evidence / "read-boundary-summary.json")
require(settled["closed_at"] == 2880 and settled["day"] == 2 and settled["category_totals"]["maintenance"] == 2 and settled["reconciliation_difference"] == 0 and settled["net_profit"] == -2 and settled["balanced"], "Actual full day2G settlement reconciles")
require(guard.source() == pins, "Source unchanged at review end")
guard.write(OUT, {"passed": True, "scope": "Normal Main Save/Load handlers and rendered closed-cleaning day boundary, public construction/resources fixture; not whole normal play", "actual_checks": 183, "failures": 0, "source_files": 1224, "source_changes": [], "evidence_seal_sha256": sha(P / "evidence-seal.json"), "raw131_pins_rechecked": True, "whole_typed_pairs": comparisons["pairs"], "formal4_entries": receipt["formal_4files_SHA_unchanged"], "actual_IO": "SAVE_CHECKPOINT_SUCCEEDED to SAVE_RECOVERY_LOADED/formal; event_type/payload only, same identity/envelope/save_id", "uncapped_branch_events_each": 15, "same_process_future_events_each": 6, "pngs": pngs, "visual_review": {"direct": 4, "same_bytes": 2, "ledger_values": "23:59 gold4649/prior1G;00:00 gold4647/maintenance2G;00:01 same gold4647", "labels": "closed cleaning/no customer fees; ledger balance/no arrears displayed", "read_checkpoint_vs_write": "reader ledger selected by scenario; writer business panel", "finished_art_accepted": False}, "root_rendered_review_pending": False, "whole_P03_accepted": False, "whole_A05_accepted": False, "whole_normal_UI_accepted": False, "native_Windows_accepted": False, "performance_accepted": False, "engine_runs_by_review": 0})
print("Root183/0 review PASS:131 pins,12typed pairs,formal4 unchanged,6PNG reviewed4direct+2same")
if __name__ == "__main__":
main()
@@ -0,0 +1,148 @@
# -*- coding: utf-8 -*-
"""Root read-only review of two actual, limited Runtime/save boundaries."""
from pathlib import Path
import copy
import hashlib
import json
import re
import subprocess
ROOT = Path(__file__).resolve().parents[4]
ART = ROOT / 'artifacts/original-completion-2026-10-02'
OUT = ART / 'kitchen-and-rescue-power-root-review-r01.json'
def sha(path):
return hashlib.sha256(path.read_bytes()).hexdigest()
def read(path):
return json.loads(path.read_text(encoding='utf-8'))
def require(value, reason):
if not value:
raise AssertionError(reason)
def pin_rows(base, rows):
for row in rows:
path = base / row['path']
require(path.is_file() and not path.is_symlink(), 'Regular proof ' + str(path))
require(sha(path) == row['sha256'] and path.stat().st_size == row['bytes'], 'Proof SHA/size ' + str(path))
def io1(folder, labels):
rows = []
for label in labels:
proof = read(folder / ('read-' + label + '-io-comparison.json'))
require(proof['bound_identity_saveid'] and proof['whole_typed_bytes_equal'], 'Whole typed comparison')
require(proof['event_deletion_count'] == 0 and proof['mapped_fields'] == ['event_type', 'payload'], 'IO1 fields only')
require(proof['writer_replaced'] == proof['reader_count'] and proof['writer_replaced'] in [0, 1], 'One exact IO event')
writer, reader = proof['writer_io'], proof['reader_io']
envelope = copy.deepcopy(writer)
envelope['event_type'], envelope['payload'] = reader['event_type'], reader['payload']
require(envelope == reader and writer['payload']['save_id'] == reader['payload']['save_id'], 'All envelope fields/save identity')
require(writer['event_type'] == 'SAVE_CHECKPOINT_SUCCEEDED' and reader['event_type'] == 'SAVE_LOADED', 'Actual save/load event types')
for event, operation, reason in [(writer, 'save', 'manual'), (reader, 'load', '')]:
payload = event['payload']
require(event['source_service'] == 'save_service' and event['causation_command_id'] == 0 and event['entity_ids'] == [], 'Actual IO provenance')
require(payload['operation'] == operation and payload['reason'] == reason and payload['request_id'] == 0, 'Actual IO reason/request')
require(payload['ok'] is True and payload['code'] == 'OK' and payload['save_id'] and payload['save_path'].startswith('user://tests/'), 'Actual successful private slot')
require(payload['saved_absolute_minute'] == payload['checkpoint_absolute_minute'] == event['absolute_minute'], 'Exact saved minute')
require(all(type(payload[k]) is int and payload[k] >= 0 for k in ['duration_us', 'runtime_duration_us']), 'Actual typed durations')
actual = folder / ('read-' + label + '.var')
expected = folder / ('read-' + label + '-expected-reader-io.var')
require(actual.read_bytes() == expected.read_bytes() and actual.stat().st_size > 0, 'Complete actual typed buffers equal')
# Independently check every JSON field as well as the actual typed buffers.
writer_json = read(folder / ('write-' + label + '.json'))
reader_json = read(folder / ('read-' + label + '.json'))
events = writer_json['systems']['runtime']['domain_events']['recent_events']
actual_replacements = 0
for event in events:
if event['event_id'] == writer['event_id']:
require(event == writer, 'Exact original event before substitution')
event['event_type'], event['payload'] = reader['event_type'], reader['payload']
actual_replacements += 1
require(actual_replacements == proof['writer_replaced'] and writer_json == reader_json, 'Independent entire JSON field equality')
rows.append({'label': label, 'typed_sha256': sha(actual), 'IO1_sha256': sha(folder / ('read-' + label + '-io-comparison.json')), 'replacements': actual_replacements})
return rows
def formal(folder):
files = {str(p.relative_to(folder / 'formal-package')): sha(p) for p in sorted((folder / 'formal-package').rglob('*')) if p.is_file()}
require(set(files) == {'world.bin', 'manifest.json', 'journal.log', 'thumbnail.png'}, 'Exactly four formal files')
require(files == read(folder / 'write-package-end.json') == read(folder / 'read-package-end.json'), 'Formal source SHA immutable')
return files
def raw_phase(raw, checks, title):
text = raw.read_text(encoding='utf-8')
require(re.findall(r'^' + re.escape(title) + r': (\d+) checks, (\d+) failures$', text, re.M) == [(str(checks), '0')], 'Unique actual count marker')
require(len(re.findall(r'^ ✓ ', text, re.M)) == checks, 'Actual successful assertion count')
require('Godot Engine v4.7.2.stable.official.ed1daf0bf' in text, 'Pinned engine banner')
require(not re.search(r'(?m)^(?:ERROR:|SCRIPT ERROR:|WARNING:.*[Ll]eak)|Parse Error|Unicode parsing error|resources still in use|leaked at exit| ✗ ', text), 'No raw functional/script/resource errors')
def main():
require(not OUT.exists(), 'Fresh root review outside sealed candidates')
kitchen = ART / 'p09-kitchen-single-link-candidate-r08'
result = read(kitchen / 'execution/result.json')
require(result['passed'] and result['production_changes'] == [] and len(result['phases']) == 10, 'Actual narrow phases')
seal = ART / 'p09-kitchen-r08-narrow-actual-seal-r01'
inventory = read(seal / 'immutable-narrow-proof-inventory.json')
pin_rows(kitchen, inventory)
pids = []
for phase in result['phases']:
raw = kitchen / 'execution/phases' / phase['phase'] / 'raw.log'
require(sha(raw) == phase['raw_sha256'] and phase['passed'], 'Actual phase raw binding')
require(phase['exit_code'] == (91 if phase['expected_guard_rejection91'] else 0), 'Actual phase exit')
pids.append(phase['pid'])
actual_runs = [p for p in result['phases'] if p['checks'] is not None]
require([p['checks'] for p in actual_runs] == [41, 49, 116, 72], 'Four actual narrow counts')
for phase in actual_runs:
raw_phase(kitchen / 'execution/phases' / phase['phase'] / 'raw.log', phase['checks'], 'Kitchen single link')
kitchen_states = {}
for case, labels in [('legacy', ['checkpoint']), ('new', ['checkpoint', 'relinked-next1', 'minute44', 'final', 'tail5'])]:
folder = kitchen / 'execution/proofs' / case
kitchen_states[case] = {'states': io1(folder, labels), 'formal_files': formal(folder)}
branch = read(kitchen / 'execution/proofs/new/read-branch-comparison.json')
require(branch['writer_count'] == branch['reader_count'] == 5 and branch['event_deletion_count'] == 0 and branch['uncapped_full_typed_equal'], 'Five uncapped new branch events')
require((kitchen / 'execution/proofs/new/read-branch-events.var').read_bytes() == (kitchen / 'execution/proofs/new/read-branch-events-expected-reader-io.var').read_bytes(), 'Whole branch typed bytes')
power = ART / 'p06-rescue-power-paired-r03'
r = read(power / 'result.json')
require(r['passed'] and r['source_files'] == 1224 and r['production_source_changes'] == 0 and r['source_equals_current1224'] and r['actual_checks'] == 691 and len(r['phases']) == 6, 'Actual P06 phases/source')
for phase in r['phases']:
folder = power / 'phases' / phase['name']
require(sha(folder / 'stdout.log') == phase['stdout_sha256'] and sha(folder / 'stderr.log') == phase['stderr_sha256'], 'Actual P06 raw pins')
require(phase['passed'] and phase['exit_code'] == 0 and not phase['timed_out'] and phase['error_lines'] == [], 'Actual P06 phase passed')
start = read(folder / 'started.json')
require(start['pid'] == phase['pid'] and start['argv'] == phase['argv'] and start['started_utc'] == phase['started_utc'] and phase['ended_utc'] > phase['started_utc'], 'Actual process timing/command binding')
pids.append(phase['pid'])
if phase['name'] in ['write', 'read']:
raw_phase(folder / 'stdout.log', phase['checks'], 'P06 rescue power restart')
require([p['checks'] for p in r['phases'] if 'checks' in p] == [336, 355], 'Fresh P06 writer/reader counts')
labels = ['checkpoint', 'outage-next1', 'outage-next3', 'power-restore-command', 'power-restored-next1', 'next1', 'treatment-progress', 'pre-completion', 'final', 'tail5']
power_states = io1(power / 'proofs/ev', labels)
power_formal = formal(power / 'proofs/ev')
power_branch = read(power / 'proofs/ev/read-branch-comparison.json')
require(power_branch['writer_count'] == power_branch['reader_count'] == 9 and power_branch['event_deletion_count'] == 0 and power_branch['uncapped_full_typed_equal'], 'Nine uncapped P06 branch events')
require((power / 'proofs/ev/read-branch-events.var').read_bytes() == (power / 'proofs/ev/read-branch-events-expected-reader-io.var').read_bytes(), 'Whole P06 branch typed bytes')
require(read(power / 'production-before.json') == read(power / 'production-end.json'), 'Production pins unchanged')
require(len(set(pids)) == 16, 'Sixteen distinct owned processes')
ended = subprocess.run(['ps', '-p', ','.join(map(str, pids)), '-o', 'pid=,comm='], capture_output=True, text=True)
require(ended.returncode == 1 and ended.stdout == ended.stderr == '', 'All owned PIDs actually ended')
fee = ART / 'p09-kitchen-s3-cost-fixture-candidate-r01'
v = read(fee / 'verification.json')
require(sha(fee / 'candidates/tests/s3/test_runtime_actor_cycle.gd') == v['candidate_sha256'] == '955cca90ee1be985e37ef166eaedb5c49f7001993afa38011fe3bf20ddb4a9b3', 'Reviewed fee candidate pin')
require(v['production_changes'] == [] and v['engine_runs'] == 0 and v['old_assertions_preserved_except_explicit_paid_cost'] and not v['core_changed'], 'Fee fixture only, actual independent accounts')
affected = ART / 'p09-kitchen-r08-affected9-r01/execution/result.json'
require(sha(affected) == v['failed_affected9_result_sha256'] and not read(affected)['passed'], 'Failed affected9 evidence preserved')
output = {'passed': True, 'scope': 'Limited actual kitchen and held rescue/EV outage save boundaries; candidate kitchen unadopted', 'kitchen': {'checks': 278, 'failures': 0, 'result_sha256': sha(kitchen / 'execution/result.json'), 'proof_files_rehashed': len(inventory), 'states': kitchen_states, 'uncapped_branch_events': 5, 'affected9_accepted': False, 'S3_actual_paid_cost_fixture_static_reviewed': True}, 'rescue_power': {'checks': 691, 'failures': 0, 'result_sha256': sha(power / 'result.json'), 'states': power_states, 'formal_files': power_formal, 'uncapped_branch_events': 9}, 'owned_PIDs': pids, 'all_owned_PIDs_ended': True, 'production_game_changes': [], 'engine_processes_by_root_review': 0, 'all8views_changed': False, 'denominator_changed': False, 'strict_behind_geometry_accepted': False, 'normal_human_play_accepted': False, 'emergency_safe_alighting_accepted': False, 'whole_P06_accepted': False, 'whole_P09_accepted': False, 'native_Windows_accepted': False, 'whole_game_accepted': False}
with OUT.open('x', encoding='utf-8') as stream:
stream.write(json.dumps(output, ensure_ascii=False, indent=2) + '\n')
print('Root actual review PASS: kitchen278/0, rescue-power691/0, 16 ended PIDs; typed/formal/IO1 pins exact; affected9 and whole acceptance pending')
if __name__ == '__main__':
main()
@@ -0,0 +1,232 @@
# -*- coding: utf-8 -*-
"""Root-only immutable raw review and limited four-document checkpoint."""
from pathlib import Path
import argparse
import collections
import datetime
import difflib
import hashlib
import importlib.util
import json
import re
import sys
sys.dont_write_bytecode = True
ROOT = Path(__file__).resolve().parents[4]
PLAN = ROOT / "docs/plans/original-completion-2026-10-02"
ART = ROOT / "artifacts/original-completion-2026-10-02"
REVIEW = ART / "p03-rescue-and-p28-root-review-r01"
OUT = ART / "checkpoint-rescue-and-p28-root-r03"
NAMES = ("IMPLEMENTATION_PLAN.md", "PROGRESS_INTEGRATION.md", "work_packages.json", "progress_snapshot.json")
def require(value, message):
if not value:
raise AssertionError(message)
def sha(path):
return hashlib.sha256(path.read_bytes()).hexdigest()
def read(path):
return json.loads(path.read_text(encoding="utf-8"))
def write(path, value):
require(not path.exists(), "Receipt overwrite refused: " + str(path))
path.write_text(json.dumps(value, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
def source():
path = ART / "windows-current-release-adapter-prep-r04/windows_adapter.py"
require(sha(path) == "fbc11778be400204922d69599e873d06d75adca28d9cf94d171b2fbac211ff74", "Source inventory adapter pin")
spec = importlib.util.spec_from_file_location("rescue_checkpoint_inventory", path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module.inventory(ROOT)
def protected():
return {n: sha(PLAN / n) for n in ("atomic_requirements.json", "progress_contract.json", "current_evidence_links.json", "atomic_denominator_freeze.json", "source_atomic_coverage.json", "baseline.json", "decisions.json")}
def io_check(q, case, label):
require(q["whole_typed_bytes_equal"] and q["bound_identity_saveid"] and q["event_deletion_count"] == 0, "Whole typed IO proof: " + case + "/" + label)
require(q["mapped_fields"] == ["event_type", "payload"] and q["writer_replaced"] == q["reader_count"] and q["writer_replaced"] in (0, 1), "Exact IO replacement cardinality")
if label == "checkpoint":
require(q["writer_replaced"] == 1, "Actual checkpoint IO1")
w, r = q["writer_io"], q["reader_io"]
require(set(w) == set(r) and {k:v for k,v in w.items() if k not in ("event_type", "payload")} == {k:v for k,v in r.items() if k not in ("event_type", "payload")}, "All IO envelope fields retained")
require(w["event_type"] == "SAVE_CHECKPOINT_SUCCEEDED" and r["event_type"] == "SAVE_LOADED" and w["source_service"] == "save_service" and w["entity_ids"] == [] and w["causation_command_id"] == 0, "IO provenance")
for event, operation in ((w, "save"), (r, "load")):
p = event["payload"]
require(p["ok"] is True and p["code"] == "OK" and p["operation"] == operation and p["request_id"] == 0 and p["save_id"] == "manual", "Actual successful manual save/load")
require(p["saved_absolute_minute"] == p["checkpoint_absolute_minute"] == event["absolute_minute"], "Actual checkpoint minute")
require(p["reason"] == ("manual" if operation == "save" else ""), "Exact save/load reason")
require(all(type(p[k]) is int and p[k] >= 0 for k in ("duration_us", "runtime_duration_us")), "Observed integer IO timings")
require(w["payload"]["save_path"] == r["payload"]["save_path"] and w["payload"]["save_id"] == r["payload"]["save_id"], "Bound same formal package")
def review():
require(not REVIEW.exists(), "Fresh root review required")
baseline = read(ART / "p05-current-stage-input-r04/candidate-source.json")
require(len(baseline) == 1224 and source() == baseline, "Current adopted source1224 exact")
packet = ART / "p03-rescue-paired-candidate-r02"
execution = packet / "execution"
data = read(execution / "result.json")
require(data["passed"] and data["failure"] is None, "Actual execution passed")
prep = read(execution / "preparation.json")
phases = data["phases"]
require(len(phases) == 12 and len({r["pid"] for r in phases}) == 12, "Import/parse/4 guard negatives/6 actual distinct processes")
counts = {}
for row in phases:
raw_path = execution / "phases" / row["phase"] / "raw.log"
require(sha(raw_path) == row["raw_sha256"], "Actual raw phase pin")
raw = raw_path.read_text()
markers = re.findall(r"^Staff rescue midpoint: (\d+) checks, (\d+) failures$", raw, re.M)
require("Godot Engine v4.7.2" in raw and row["passed"], "Actual engine header/phase success")
require("SCRIPT ERROR" not in raw and "Parse Error" not in raw, "No script/parse diagnostic")
if row["expected_guard_rejection91"]:
require(row["exit_code"] == 91 and not markers and "P03_RESCUE exact mode/profile/resource/nonce/formal/fresh output guards failed" in raw, "Expected guard rejection91")
else:
require(row["exit_code"] == 0 and "ERROR:" not in raw, "Clean actual phase exit")
if row["checks"] is not None:
require(markers == [(str(row["checks"]), "0")] and row["failures"] == 0, "Unique actual completion/count")
counts[row["phase"]] = row["checks"]
require(sum(counts.values()) == 650 and len(counts) == 6, "Six actual rescue phases650/0")
require(read(execution / "production-before.json") == read(execution / "production-end.json") == baseline and read(execution / "production-change.json") == [], "All production source unchanged")
actual_uid = read(execution / "actual-uid.json")
require(sha(packet / "candidates" / (actual_uid["target"] + ".uid")) == actual_uid["sha256"], "Actual imported QA UID retained")
pairs = []
journals = {}
cases = {}
for case in ("transport", "ev", "treatment"):
proof = execution / "proofs" / case
w = next(r for r in phases if r["phase"] == case + "-write")
r = next(r for r in phases if r["phase"] == case + "-read")
for role, phase in (("write", w), ("read", r)):
context = read(proof / (role + "-context.json"))
result = read(proof / (role + "-result.json"))
require(context["pid"] == result["pid"] == phase["pid"] and context["case"] == result["case"] == case and result["failures"] == 0, "Actual process/context binding")
require(context["profile"] == prep["profiles"][case] and context["user_dir"] == prep["user_dirs"][case] and Path(context["res_dir"]).resolve() == Path(prep["stage"]).resolve(), "Actual private profile and resource path")
require(result["normal_ui_accepted"] is False and result["rendered_accepted"] is False and result["whole_game_accepted"] is False, "Scope preserved")
package = read(proof / "write-package-end.json")
require(package == read(proof / "read-package-end.json") and len(package) == 4, "Four formal entries unchanged")
package_copy = {p.relative_to(proof / "formal-package").as_posix(): sha(p) for p in (proof / "formal-package").rglob("*") if p.is_file()}
require(package_copy == package, "Artifact retains exact original formal package")
live = Path(prep["user_dirs"][case]) / "tests" / ("p03_rescue_" + context["nonce"] + "_" + case) / "manual"
require({p.relative_to(live).as_posix(): sha(p) for p in live.rglob("*") if p.is_file()} == package, "Live private formal package unchanged at root review")
for label in ("checkpoint", "next1", "treatment-progress", "pre-completion", "final", "tail5"):
left = proof / ("read-" + label + "-expected-reader-io.var")
right = proof / ("read-" + label + ".var")
require(left.read_bytes() == right.read_bytes(), "Independent full typed byte comparison")
io_check(read(proof / ("read-" + label + "-io-comparison.json")), case, label)
pairs.append({"case": case, "label": label, "bytes": left.stat().st_size, "sha256": sha(left)})
q = read(proof / "read-branch-comparison.json")
left = proof / "read-branch-events-expected-reader-io.var"
right = proof / "read-branch-events.var"
require(left.read_bytes() == right.read_bytes() and q["uncapped_full_typed_equal"] and q["event_deletion_count"] == 0 and q["mapped_index"] == 0 and q["reader_count"] == q["writer_count"], "Independent uncapped branch comparison")
journals[case] = {"events": q["reader_count"], "sha256": sha(left)}
cases[case] = {"writer_pid": w["pid"], "reader_pid": r["pid"], "actual_checks": w["checks"] + r["checks"], "checkpoint_minute": result["checkpoint_minute"], "formal_entries": package}
span = ART / "runtime-scale-diagnostic-setup-span-candidate-r01"
manifest = read(span / "packet-manifest.json")
require(all(sha(span / name) == expected for name, expected in manifest["files"].items()), "Setup span packet all19 SHA")
driver = (span / "runtime_scale_driver.gd").read_text()
stripped = re.sub(r"(?ms)^[ \t]*# QA_SETUP_SPAN_BEGIN\n.*?^[ \t]*# QA_SETUP_SPAN_END\n", "", driver).replace("_setup_observed_rebuild()", "_runtime.rebuild_path_graph_from_world()").replace("\n\n\nfunc _observe", "\n\nfunc _observe")
require(stripped == (span / "instrumentation-base-r02.gd").read_text(), "Exact executed r02 driver after removing QA spans only")
failed_path = ART / "p28-maxscale-timeout-root-review-r01.json"
failed = read(failed_path)
require(failed["evidence_integrity_passed"] and not failed["execution_passed"], "Retained failed execution root evidence")
# Read the actual timeout result independently of the prior review.
scale = read(ART / "runtime-scale-diagnostic-max20000-r02/execution.json")
build = next(s for s in scale["steps"] if s["name"] == "build")
require(build["timed_out"] and build["exit_code"] == -15 and 900 <= build["wall_seconds"] < 901 and scale["measurements"] is None and scale["P28_accepted"] is False, "Actual900s timeout remains a failure; no measurements")
require(source() == baseline, "Source unchanged at root review end")
REVIEW.mkdir()
pins = {p.relative_to(ROOT).as_posix(): sha(p) for p in sorted(execution.rglob("*")) if p.is_file()}
write(REVIEW / "review.json", {"passed": True, "scope": "Limited actual rescue paired-state evidence plus integrity of failed maxscale preparation; no whole acceptance", "source_files": 1224, "source_map_sha256": sha(ART / "p05-current-stage-input-r04/candidate-source.json"), "rescue_execution_sha256": sha(execution / "result.json"), "raw_file_sha256": pins, "actual_rescue_checks": 650, "failures": 0, "cases": cases, "whole_typed_pairs": pairs, "uncapped_journals": journals, "event_deletions": 0, "IO_mapped_fields": ["event_type", "payload"], "scale_timeout_review_sha256": sha(failed_path), "setup_span_manifest_sha256": sha(span / "packet-manifest.json"), "setup_span_static_files": len(manifest["files"]), "setup_span_executed": False, "scale_execution_passed": False, "measurements": None, "normal_UI_accepted": False, "natural_collapse_accepted": False, "P03_accepted": False, "P28_accepted": False, "native_Windows_accepted": False, "whole_original_accepted": False, "source_changes": [], "engine_runs_by_root_review": 0})
print("Root review passed: rescue650/0,18 whole pairs; maxscale900s execution remains failed")
def prepare():
require(not OUT.exists(), "Fresh document checkpoint")
proof_path = REVIEW / "review.json"
proof = read(proof_path)
require(proof["passed"] and proof["actual_rescue_checks"] == 650 and not proof["P03_accepted"] and not proof["P28_accepted"], "Root limited evidence")
pins = read(ART / "p05-current-stage-input-r04/candidate-source.json")
require(source() == pins, "Current source matches review")
at = datetime.datetime.now(datetime.timezone(datetime.timedelta(hours=9))).isoformat()
OUT.mkdir(); (OUT / "before").mkdir(); (OUT / "reviewed").mkdir()
before = {n: sha(PLAN / n) for n in NAMES}; guard = protected()
for n in NAMES:
(OUT / "before" / n).write_bytes((PLAN / n).read_bytes())
def ref(path, scope):
return {"path": path.relative_to(ROOT).as_posix(), "sha256_at_integration": sha(path), "scope": scope, "linked_at_jst": at, "current_game_acceptance_inferred": False}
rescue = ref(proof_path, "Actual rescue650/0,3 distinct-PID pairs/18whole typed states/uncapped7+7+3events/formal4entries unchanged; controlled patient/Operations disabled")
scale = ref(ART / "p28-maxscale-timeout-root-review-r01.json", "Actual BUILD900.024s/-15 timeout; evidence integrity only, target counts and all measurements null")
span = ref(ART / "runtime-scale-diagnostic-setup-span-candidate-r01/packet-manifest.json", "19-file sealed setup-span candidate; exact executed r02 after removing QA progress, actual run pending")
packages = read(PLAN / "work_packages.json")
p03 = next(p for p in packages if p["id"] == "P03")
previous = p03["current_summary"]
status = "現本体164回帰と正式13→14/配送/清掃460に加え、制御した救護搬送/EV乗車/治療の3別processペア650 checks/0をroot照合。全人物/全施設/旧関係意味変換・正常UI全体は未完。"
p03["current_summary"] = status; p03["updated_at_jst"] = at
for task in p03["remaining_deliverables"]:
task["evidence"].append(rescue); task["updated_at_jst"] = at
if task["id"] != "P03-02": task["progress_summary"] = status
else: task["progress_summary"] += " 同一14救護3pair650/0も限定照合。旧配置変換の受入へ転用しない。"
if task["id"] == "P03-03":
task["remaining_gaps"][0] = "全人物/全施設と救護の自然気絶・停止・経路喪失等の全途中paired受入は未完。今回3checkpointの制御救護に限定。"
p28 = next(p for p in packages if p["id"] == "P28")
target = next(t for t in p28["remaining_deliverables"] if t["id"] == "P28-01")
require(target["state"] == "planned", "P28-01 was planned before actual attempt")
target["state"] = "in_progress"
target["evidence"] += [scale, span]; target["updated_at_jst"] = at
target["progress_summary"] = "実Runtime最大負荷診断は準備BUILDで900.024秒timeout(-15)。目標実数/保存/別process/計測に未到達。setup span候補を準備し原因特定を継続。"
p28["current_summary"] += " 最大負荷実診断は準備900秒timeoutで失敗。全性能値は未測定。"
snapshot = read(PLAN / "progress_snapshot.json")
snapshot["integrated_at_jst"] = at
snapshot["current_rescue_and_scale_checkpoint"] = {"root_review": rescue, "source_files": 1224, "actual_rescue_checks": 650, "paired_cases": 3, "whole_typed_state_pairs": 18, "uncapped_event_counts": [7,7,3], "scale_timeout": scale, "scale_setup_span_candidate": span, "scale_measurements": None, "P03_accepted": False, "P28_accepted": False, "native_Windows_accepted": False, "whole_original_accepted": False, "source_changes_by_integration": 0, "adoption_receipt": OUT.relative_to(ROOT).as_posix() + "/adoption.json"}
counts = dict(collections.Counter(t["state"] for p in packages for t in p["remaining_deliverables"]))
require(counts["completed"] == snapshot["current_delivery_state_counts"]["completed"], "No deliverable completions added")
require(counts["in_progress"] == snapshot["current_delivery_state_counts"]["in_progress"] + 1 and counts["planned"] == snapshot["current_delivery_state_counts"]["planned"] - 1, "Only P28-01 planned to in_progress")
snapshot["current_delivery_state_counts"] = counts
section = "\n\n### 救護3地点の再開と最大負荷準備の失敗\n\n[Root再照合](../../../artifacts/original-completion-2026-10-02/p03-rescue-and-p28-root-review-r01/review.json)で、搬送/EV乗車/治療の3地点を別PIDで正式保存・再開し、650 checks/0、18全状態typed pairs、無制限event journal各7/7/3、元formal4ファイルの不変を確認した。save/loadのIO1件は同じID・時刻・全envelope・save_idに拘束しevent_type/payloadのみ代替、event削除0。実カタログTessaの雇用/DAY/移動/救護と公開health0患者fixture、Operations無効、headlessの限定証拠で、自然気絶・通常UI・全P03・Windowsの受入へ転用しない。既存の正式13→14/配送/清掃460と異なる実行で、全8観点原子の完了数は増やさない。\n\n[最大負荷失敗の証拠](../../../artifacts/original-completion-2026-10-02/p28-maxscale-timeout-root-review-r01.json)は、実BUILD900.024秒でtimeout/-15を保持する。目標実数、正式保存、別process照合、x1/x3、FPS/保存時間の値は未取得/null。証拠の整合合格を実行合格へ変換しない。元対象を減らさず準備の区間を観測する[sealed候補](../../../artifacts/original-completion-2026-10-02/runtime-scale-diagnostic-setup-span-candidate-r01/packet-manifest.json)は未実行。通常Operationsの人口cap100は変更していない。\n\n[文書採用記録](../../../artifacts/original-completion-2026-10-02/checkpoint-rescue-and-p28-root-r01/adoption.json)に旧/採用後4文書SHAとsource/protected不変を保持する。全体率と最終分母はnull、P03/P28は着手中を維持する。\n"
section = section.replace("checkpoint-rescue-and-p28-root-r01/adoption.json", OUT.name + "/adoption.json")
text = (PLAN / "IMPLEMENTATION_PLAN.md").read_text()
require(text.count(previous) == 3, "Expected P03 package/two task current statements")
text = text.replace(previous, status)
p28_before = "現在地: 複数の軽量化は採用済み。Runtime全体の性能予算は未達。"
require(text.count(p28_before) == 1, "Exact previous P28 current statement")
text = text.replace(p28_before, "現在地: " + p28["current_summary"])
text = re.sub(r"(?m)^(- P28-01 .*保存を測る。 受入: .*を残す。)$", r"\1 状態: 着手中。実準備900秒timeoutで測定未到達、setup区間観測候補を準備。", text)
text = text.replace("| 性能と長期プレイ | 既存ハーネスを再監査。通常Operations cap100、200客の診断案を作成 |", "| 性能と長期プレイ | 最大負荷実診断は準備900秒timeout。通常Operations cap100を保持しsetup区間の観測候補を準備 |")
contents = {"IMPLEMENTATION_PLAN.md": text + section, "PROGRESS_INTEGRATION.md": (PLAN / "PROGRESS_INTEGRATION.md").read_text() + section, "work_packages.json": json.dumps(packages, ensure_ascii=False, indent=2) + "\n", "progress_snapshot.json": json.dumps(snapshot, ensure_ascii=False, indent=2) + "\n"}
for n, value in contents.items():
(OUT / "reviewed" / n).write_text(value, encoding="utf-8")
diff = difflib.unified_diff((OUT / "before" / n).read_text().splitlines(True), value.splitlines(True), fromfile="before/"+n, tofile="reviewed/"+n)
(OUT / (n + ".diff")).write_text("".join(diff), encoding="utf-8")
require(source() == pins and protected() == guard and all(sha(PLAN / n) == v for n,v in before.items()), "No production changes during preparation")
write(OUT / "preparation.json", {"before": before, "reviewed": {n:sha(OUT / "reviewed" / n) for n in NAMES}, "protected": guard, "source_map": pins, "root_review_sha256": sha(proof_path), "production_document_writes": 0, "prepared_at_jst": at})
print("Prepared four documents: whole acceptance and completions unchanged")
def adopt():
data = read(OUT / "preparation.json")
require(not (OUT / "adoption.json").exists(), "Fresh adoption receipt")
require(source() == data["source_map"] and protected() == data["protected"], "Protected/source unchanged")
require(sha(REVIEW / "review.json") == data["root_review_sha256"], "Root evidence unchanged")
require(all(sha(PLAN / n) == v for n,v in data["before"].items()) and all(sha(OUT / "reviewed" / n) == v for n,v in data["reviewed"].items()), "Before/reviewed document pins")
for n in NAMES:
temp = PLAN / (n + ".rescue-checkpoint-tmp")
require(not temp.exists(), "No unexpected temp")
temp.write_bytes((OUT / "reviewed" / n).read_bytes()); temp.replace(PLAN / n)
require(source() == data["source_map"] and protected() == data["protected"] and all(sha(PLAN/n) == v for n,v in data["reviewed"].items()), "Exact adopted documents/source")
write(OUT / "adoption.json", {"passed": True, "before": data["before"], "adopted": data["reviewed"], "root_review_sha256": data["root_review_sha256"], "source_files": len(data["source_map"]), "source_changes": [], "protected_unchanged": data["protected"], "diff_reviewed_by_root": True, "engine_runs": 0, "completed_deliveries_added": 0, "P03_accepted": False, "P28_accepted": False, "whole_original_accepted": False})
print("Adopted four documents; source changes0; P03/P28 remain in progress")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("mode", choices=("review", "prepare", "adopt"))
globals()[parser.parse_args().mode]()
@@ -0,0 +1,8 @@
{
"scope": "future collector exact two marker schemas, no game/test edits",
"before_sha256": "2244e215d3fd30dc2c771ceb9dfc1c54b452520937a29dcdb9b61e1b96e2f104",
"after_sha256": "9e94acde149624bebce59855206e5eb32541086b0f1217c155a90f47d3da7766",
"actual_r03_not_rerun": true,
"actual_immutable_review": "artifacts/original-completion-2026-10-02/full-regression-r03-review-r01/verification.json",
"test_conditions_changed": false
}
@@ -0,0 +1,68 @@
"""Guarded standard collector: logical original suites and actual native argv.
Run the canonical runner function in this same owned Python process so an
abruptly killed wrapper cannot strand a separate runner's unobserved children.
Actual native Popen objects remain owned by the runner's unchanged inner/outer
finally adapters. The wrapper never signals groups or discovered processes.
"""
from datetime import datetime
from zoneinfo import ZoneInfo
from pathlib import Path
import argparse,contextlib,hashlib,importlib.util,json,os,shutil,sys
sys.dont_write_bytecode=True
ROOT=Path(__file__).resolve().parents[4]
def sha(p):return hashlib.sha256(Path(p).read_bytes()).hexdigest()
def load(name,path):
spec=importlib.util.spec_from_file_location(name,path);m=importlib.util.module_from_spec(spec);spec.loader.exec_module(m);return m
def write(p,value):
with p.open('x',encoding='utf-8')as stream:stream.write(json.dumps(value,ensure_ascii=False,indent=2)+'\n')
def expected_roster():
return ['tests/run_tests.gd']+sorted(str(p.relative_to(ROOT))for p in(ROOT/'tests').rglob('test*.gd')if 'export'not in p.relative_to(ROOT).parts and str(p.relative_to(ROOT))!='tests/s0/test_kernel_and_save.gd')
def main(argv=None):
parser=argparse.ArgumentParser(description=__doc__)
parser.add_argument('--project-root',type=Path,default=ROOT);parser.add_argument('--output',type=Path,required=True)
parser.add_argument('--godot',default='godot');parser.add_argument('--timeout',type=int,default=1200)
parser.add_argument('--standard-runner',type=Path);parser.add_argument('--source-input-refs',type=Path)
parser.add_argument('--marker-contracts',type=Path)
args=parser.parse_args(argv);root=args.project_root.resolve();out=args.output.resolve()
runner_path=(args.standard_runner or root/'tools/run_all_tests.py').resolve()
runner=load('actual_guarded_standard_runner',runner_path);protocol=load('actual_guarded_standard_reader',runner_path.parent/'regression/review_protocol.py')
marker_path=runner_path.parent/'strict_test_markers.py';module=load('guarded_original_marker',marker_path)
contract_path=(args.marker_contracts or root/'docs/plans/original-completion-2026-10-02/execution/completion_marker_contracts.json').resolve();contracts=module.load_contracts(contract_path)
before=runner.source_refs(root);selected=runner.read(args.source_input_refs)if args.source_input_refs else before
expected={n:r['sha256']for n,r in selected.items()};wrapper_sha=sha(Path(__file__));marker_sha=sha(marker_path);contract_sha=sha(contract_path)
out.mkdir(parents=True,exist_ok=False)
for source,name in [(Path(__file__),'wrapper-input.py'),(marker_path,'marker-module-input.py'),(contract_path,'marker-contract-input.json'),(runner_path,'standard-runner-input.py')]:shutil.copyfile(source,out/name)
write(out/'source-start.json',expected);write(out/'protected-current-source-start.json',before)
logical=['tests/run_tests.gd']+sorted(n for n in expected if n.startswith('tests/')and n.endswith('.gd')and Path(n).name.startswith('test')and'export'not in Path(n).parts and n!='tests/s0/test_kernel_and_save.gd')
write(out/'expected-tests.json',logical);started=datetime.now(ZoneInfo('Asia/Tokyo')).isoformat()
command=[str(runner_path),'--project-root',str(root),'--output',str(out/'suites'),'--godot',args.godot,'--timeout',str(args.timeout),'--marker-contracts',str(contract_path)]
if args.source_input_refs:command+=['--source-input-refs',str(args.source_input_refs.resolve())]
write(out/'standard-driver-start.json',{'event':'OWNED_IN_PROCESS_STANDARD_CALL','actual_python_pid':os.getpid(),'owner_wrapper_pid':os.getpid(),'native_PID_is_not_wrapper_PID':True,'logical_arguments':command,'runner_sha256':sha(runner_path)})
code=1;call_error=None
try:
with(out/'standard-driver.raw.log').open('x',encoding='utf-8')as stream,contextlib.redirect_stdout(stream),contextlib.redirect_stderr(stream):code=runner.main(command[1:])
except BaseException as caught:call_error=type(caught).__name__+': '+str(caught)
write(out/'standard-driver-end.json',{'event':'OWNED_IN_PROCESS_STANDARD_RETURN','actual_python_pid':os.getpid(),'owner_wrapper_pid':os.getpid(),'exit_code':code,'call_error':call_error,'raw_sha256':sha(out/'standard-driver.raw.log')})
after=runner.source_refs(root);write(out/'protected-current-source-end.json',after)
write(out/'source-end.json',{n:sha(r['path'])for n,r in selected.items()})
changes=sorted(n for n in set(before)|set(after)if before.get(n)!=after.get(n));errors=[];review=None
try:review=protocol.review(out/'suites',root,expected,contracts,os.getpid())
except BaseException as caught:errors.append(type(caught).__name__+': '+str(caught))
unchanged=sha(Path(__file__))==wrapper_sha and sha(marker_path)==marker_sha and sha(contract_path)==contract_sha
passed=code==0 and call_error is None and not changes and unchanged and not errors and review is not None and review['passed']
results=out/'suites/all-tests.json';rows=review['rows']if review else []
report={'scope':'current pinned-source guarded standard regression; no original/native/full-game acceptance','passed':passed,
'protocol':'guarded-standard-v1','wrapper_sha256':wrapper_sha,'wrapper_sha256_after':sha(Path(__file__)),
'wrapper_copy_path':str(out/'wrapper-input.py'),'wrapper_unchanged':unchanged,'all_results_sha256':sha(results)if results.exists()else None,
'marker_module_sha256':marker_sha,'marker_contract_sha256':contract_sha,'standard_runner_sha256':expected['tools/run_all_tests.py'],
'source_map_sha256':sha(out/'source-start.json'),'source_files':len(expected),'started_at_jst':started,
'finished_at_jst':datetime.now(ZoneInfo('Asia/Tokyo')).isoformat(),'runner_exit_code':code,'standard_runner_pid':os.getpid(),
'standard_runner_execution_kind':'same owned Python process; distinct actual native PID receipts per phase',
'suites':len(rows),'checks':review['actual_all_roster_checks']if review else None,'count_from_raw_only':True,
'failed_tests':[r['test']for r in rows if not r['passed']],'changed_paths':changes,'collector_errors':errors+(review['collector_errors']if review else []),
'call_error':call_error,'rows':rows,'actual_review':review,'original_full_acceptance':False,'windows_acceptance':False,
'P28_maximum_scene_performance_acceptance':False}
write(out/'verification.json',report);print(json.dumps({k:v for k,v in report.items()if k not in ['rows','actual_review']},ensure_ascii=False),flush=True)
return 0 if passed else 1
if __name__=='__main__':raise SystemExit(main())
@@ -0,0 +1,82 @@
"""Run the standard source regression and bind every result to exact inputs."""
from datetime import datetime
import argparse
import hashlib
import json
from pathlib import Path
import re
import subprocess
from zoneinfo import ZoneInfo
ROOT = Path(__file__).resolve().parents[4]
OUT = ROOT / "artifacts/original-completion-2026-10-02/full-regression-r01"
def sha(path):
return hashlib.sha256(path.read_bytes()).hexdigest()
def source_map():
paths = [p for folder in ("autoload", "scripts", "scenes", "data", "tests", "assets", "tools")
for p in (ROOT / folder).rglob("*") if p.is_file() and p.name != ".DS_Store"]
paths += [ROOT / p for p in ("project.godot", "export_presets.cfg", "Makefile", "AGENTS.md")]
return {str(p.relative_to(ROOT)): sha(p) for p in sorted(paths)}
def write(name, data):
(OUT / name).write_text(json.dumps(data, ensure_ascii=False, indent=2) + "\n")
def main():
global OUT
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--output", type=Path, default=OUT)
args = parser.parse_args()
OUT = args.output.resolve()
OUT.mkdir(parents=True, exist_ok=False)
before = source_map()
roster = ["tests/run_tests.gd"] + sorted(str(p.relative_to(ROOT)) for p in (ROOT / "tests").rglob("test*.gd")
if "export" not in p.relative_to(ROOT).parts and p.name != "test_kernel_and_save.gd")
assert len(roster) == len(set(roster))
write("source-start.json", before)
write("expected-tests.json", roster)
started_at = datetime.now(ZoneInfo("Asia/Tokyo")).isoformat()
code = subprocess.run(["python3", "tools/run_all_tests.py", "--output", str(OUT / "suites")], cwd=ROOT).returncode
after = source_map()
write("source-end.json", after)
changes = sorted(path for path in set(before) | set(after) if before.get(path) != after.get(path))
retained = json.loads((ROOT / "artifacts/facility-need-pricing-r02-full155-independent-review-2026-10-01-r01/actual155-source-marker-review.json").read_text())
old_markers = {row["test"]: row["actual_marker"] for row in retained["rows"]}
results = json.loads((OUT / "suites/all-tests.json").read_text())
reviewed = []
for row in results:
log = OUT / "suites" / row["log"]
content = log.read_text()
if row["test"] in old_markers:
marker = old_markers[row["test"]]
matches = [marker] if content.count(marker) == 1 else []
else:
matches = re.findall(r"^.*?: \d+ checks, 0 failures\n", content, re.MULTILINE)
match = re.search(r"checks=(\d+)|(\d+)(?: [A-Za-z]+)* checks", matches[0]) if len(matches) == 1 else None
count = int(next(g for g in match.groups() if g is not None)) if match else None
passed = row["exit_code"] == 0 and not row["failed"] and count is not None and "Godot Engine v4.7.2" in content
reviewed.append(dict(test=row["test"], actual_checks=count, passed=passed,
source_sha256=before.get(row["test"]), log_sha256=sha(log),
log=row["log"], completion_marker=matches[0] if len(matches) == 1 else None,
unicode_diagnostic_lines=content.count("Unicode parsing error")))
actual_names = [r["test"] for r in reviewed]
verified = code == 0 and not changes and actual_names == roster and all(r["passed"] for r in reviewed)
report = dict(scope="current source regression, not original full-game acceptance", passed=verified,
source_head=subprocess.check_output(["git", "rev-parse", "HEAD"], cwd=ROOT, text=True).strip(),
source_map_sha256=sha(OUT / "source-start.json"), source_files=len(before),
started_at_jst=started_at, finished_at_jst=datetime.now(ZoneInfo("Asia/Tokyo")).isoformat(),
runner_exit_code=code, suites=len(reviewed), checks=sum(r["actual_checks"] or 0 for r in reviewed),
failed_tests=[r["test"] for r in reviewed if not r["passed"]], changed_paths=changes,
rows=reviewed, original_full_acceptance=False, windows_acceptance=False)
write("verification.json", report)
print(json.dumps({k:v for k,v in report.items() if k != "rows"}, ensure_ascii=False), flush=True)
return 0 if verified else 1
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,96 @@
"""Run the standard source regression and bind every result to exact inputs."""
from datetime import datetime
import argparse
import hashlib
import json
from pathlib import Path
import re
import shutil
import subprocess
from zoneinfo import ZoneInfo
ROOT = Path(__file__).resolve().parents[4]
OUT = ROOT / "artifacts/original-completion-2026-10-02/full-regression-r01"
def sha(path):
return hashlib.sha256(path.read_bytes()).hexdigest()
def source_map():
paths = [p for folder in ("autoload", "scripts", "scenes", "data", "tests", "assets", "tools")
for p in (ROOT / folder).rglob("*") if p.is_file() and p.name != ".DS_Store"]
paths += [ROOT / p for p in ("project.godot", "export_presets.cfg", "Makefile", "AGENTS.md")]
return {str(p.relative_to(ROOT)): sha(p) for p in sorted(paths)}
def write(name, data):
(OUT / name).write_text(json.dumps(data, ensure_ascii=False, indent=2) + "\n")
def main():
global OUT
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--output", type=Path, default=OUT)
args = parser.parse_args()
OUT = args.output.resolve()
OUT.mkdir(parents=True, exist_ok=False)
wrapper_sha = sha(Path(__file__))
shutil.copyfile(Path(__file__), OUT / "wrapper-input.py")
before = source_map()
roster = ["tests/run_tests.gd"] + sorted(str(p.relative_to(ROOT)) for p in (ROOT / "tests").rglob("test*.gd")
if "export" not in p.relative_to(ROOT).parts and p.name != "test_kernel_and_save.gd")
assert len(roster) == len(set(roster))
write("source-start.json", before)
write("expected-tests.json", roster)
started_at = datetime.now(ZoneInfo("Asia/Tokyo")).isoformat()
code = subprocess.run(["python3", "tools/run_all_tests.py", "--output", str(OUT / "suites")], cwd=ROOT).returncode
after = source_map()
write("source-end.json", after)
changes = sorted(path for path in set(before) | set(after) if before.get(path) != after.get(path))
retained = json.loads((ROOT / "artifacts/facility-need-pricing-r02-full155-independent-review-2026-10-01-r01/actual155-source-marker-review.json").read_text())
old_markers = {row["test"]: row["actual_marker"] for row in retained["rows"]}
results = json.loads((OUT / "suites/all-tests.json").read_text())
reviewed = []
for row in results:
log = OUT / "suites" / row["log"]
content = log.read_text()
if row["test"] == "tests/supply/test_supply_auto_purchase.gd":
# This new suite publishes a key/value summary, not the colon
# form used by the other newly adopted regression suites.
matches = re.findall(r"^SUPPLY_AUTO_PURCHASE checks=\d+ failures=0\n", content, re.MULTILINE)
elif row["test"] in old_markers:
marker = old_markers[row["test"]]
matches = [marker] if content.count(marker) == 1 else []
else:
matches = re.findall(r"^.*?: \d+ checks, 0 failures\n", content, re.MULTILINE)
match = re.search(r"checks=(\d+)|(\d+)(?: [A-Za-z]+)* checks", matches[0]) if len(matches) == 1 else None
count = int(next(g for g in match.groups() if g is not None)) if match else None
passed = row["exit_code"] == 0 and not row["failed"] and count is not None and "Godot Engine v4.7.2" in content
reviewed.append(dict(test=row["test"], actual_checks=count, passed=passed,
source_sha256=before.get(row["test"]), log_sha256=sha(log),
log=row["log"], completion_marker=matches[0] if len(matches) == 1 else None,
unicode_diagnostic_lines=content.count("Unicode parsing error")))
actual_names = [r["test"] for r in reviewed]
wrapper_unchanged = sha(Path(__file__)) == wrapper_sha
verified = code == 0 and not changes and wrapper_unchanged and actual_names == roster and all(r["passed"] for r in reviewed)
report = dict(scope="current source regression, not original full-game acceptance", passed=verified,
wrapper_sha256=wrapper_sha,
wrapper_unchanged=wrapper_unchanged,
wrapper_sha256_after=sha(Path(__file__)),
wrapper_copy_path=str(OUT / "wrapper-input.py"),
all_results_sha256=sha(OUT / "suites/all-tests.json"),
standard_runner_sha256=before["tools/run_all_tests.py"],
source_head=subprocess.check_output(["git", "rev-parse", "HEAD"], cwd=ROOT, text=True).strip(),
source_map_sha256=sha(OUT / "source-start.json"), source_files=len(before),
started_at_jst=started_at, finished_at_jst=datetime.now(ZoneInfo("Asia/Tokyo")).isoformat(),
runner_exit_code=code, suites=len(reviewed), checks=sum(r["actual_checks"] or 0 for r in reviewed),
failed_tests=[r["test"] for r in reviewed if not r["passed"]], changed_paths=changes,
rows=reviewed, original_full_acceptance=False, windows_acceptance=False)
write("verification.json", report)
print(json.dumps({k:v for k,v in report.items() if k != "rows"}, ensure_ascii=False), flush=True)
return 0 if verified else 1
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,196 @@
{
"review_date_jst": "2026-10-02",
"reviewer": "atomic_requirements independent task",
"review_mode": "read-only code and retained evidence audit",
"production_edits": 0,
"new_godot_runs": 0,
"source_head": "285528b7a3b1b46a2a67af5aa90d9085539b42f4",
"reviewed_source_sha256": {
"scripts/core/save_service.gd": "7c107a509b3afccb478ba89d051fbaa9a8c93165326fac8e4cef2249c05879d0",
"scripts/core/simulation_snapshot.gd": "fc528a3d1db1f439c10f70d6cba2f72bd65abc0d3866eb8b582df60918af0adf",
"autoload/simulation_runtime.gd": "d3ad4aab6ded19eb137c5494481cc7333e846746a25b18dbad3c8b663e9f6b72",
"tests/s6/test_save_preflight.gd": "49e24247649839b6f50d19b2284368efb7f8f8b189c5010491ad428e97c1c8b9"
},
"focused_evidence": {
"checks": 485,
"suites": 7,
"all_passed_verified": true,
"logs": [
{
"test": "tests/s6/test_save_preflight.gd",
"exit_code": 0,
"passed": true,
"checks": 128,
"seconds": 3.15,
"log": "tests__s6__test_save_preflight.gd-r02.log",
"log_sha256": "171e2af4cdd6c9d00928110642f20de6d678f300947d16b53e4485f4988206c9",
"completion_check_counts": [
128
],
"completion_matches": true,
"passed_verified": true
},
{
"test": "tests/s6/test_save_operations.gd",
"exit_code": 0,
"passed": true,
"checks": 127,
"seconds": 2.79,
"log": "tests__s6__test_save_operations.gd-r02.log",
"log_sha256": "c353636c82f54e49a88ab56ca000c14a78687921e5cc5ceeea8982a2275ed2c9",
"completion_check_counts": [
127
],
"completion_matches": true,
"passed_verified": true
},
{
"test": "tests/s6/test_runtime_save_lifecycle.gd",
"exit_code": 0,
"passed": true,
"checks": 96,
"seconds": 6.68,
"log": "tests__s6__test_runtime_save_lifecycle.gd-r02.log",
"log_sha256": "6ab68137561c286f85cfb1b7f970023207659cb061f8ba1db41e3ed1f1a33157",
"completion_check_counts": [
96
],
"completion_matches": true,
"passed_verified": true
},
{
"test": "tests/run_tests.gd",
"exit_code": 0,
"passed": true,
"checks": 73,
"seconds": 1.13,
"log": "tests__run_tests.gd-r02.log",
"log_sha256": "91ecdbe39f081ef6124499b9cec042600e7154d72c89f029298966aa560606ab",
"completion_check_counts": [
73
],
"completion_matches": true,
"passed_verified": true
},
{
"test": "tests/transport/test_transport_save.gd",
"exit_code": 0,
"passed": true,
"checks": 29,
"seconds": 1.7,
"log": "tests__transport__test_transport_save.gd-r02.log",
"log_sha256": "f0d51dfd583cd9b08d19790a39fedc9169c8802cab72f7817d9ecfa40fe93306",
"completion_check_counts": [
29
],
"completion_matches": true,
"passed_verified": true
},
{
"test": "tests/ui/test_dimension_migration_ui.gd",
"exit_code": 0,
"passed": true,
"checks": 12,
"seconds": 2.33,
"log": "tests__ui__test_dimension_migration_ui.gd-r02.log",
"log_sha256": "db9f3e78c7670558b9871c1c78abbad8be27bb45fd8d3c79e7535df4d3adfe4d",
"completion_check_counts": [
12
],
"completion_matches": true,
"passed_verified": true
},
{
"test": "tests/supply/test_supply_save_migration.gd",
"exit_code": 0,
"passed": true,
"checks": 20,
"seconds": 1.18,
"log": "tests__supply__test_supply_save_migration.gd-r02.log",
"log_sha256": "b26de7e09b864e70fc36822dec40851ef08a056404e25373a9c1d6e26d45211d",
"completion_check_counts": [
20
],
"completion_matches": true,
"passed_verified": true
}
],
"source_map_count": 318,
"source_map_drift_paths": [
"tests/performance/test_digest_performance.gd"
],
"changed_files_pins_match": true
},
"new_difference_induced_major_findings": 0,
"findings": [
{
"id": "SFR-01",
"priority": 1,
"state": "candidate_only_static_reproduction_path",
"preexisting": true,
"file": "scripts/core/save_service.gd",
"line": 932,
"symbol": "_reconcile_interrupted_formal_save",
"condition": "identifiable unsupported formal version + valid transaction marker + current tmp/bak",
"effect": "formal package deleted/replaced by old backup before unsupported-version rejection",
"affected_entries": [
"load_snapshot",
"load_with_recovery",
"inspect_recovery_candidates",
"migrate_save",
"load_recovery_candidate"
]
},
{
"id": "SFR-02",
"priority": 2,
"state": "candidate_only_static_reproduction_path",
"preexisting": true,
"file": "scripts/core/save_service.gd",
"line": 334,
"symbol": "_load_recovery_candidate_impl",
"condition": "explicit backup selection + stale marker/tmp, formal either present or missing",
"effect": "reconcile may delete tmp/marker or promote tmp before nominal read_only result"
}
],
"candidate_artifact": "artifacts/original-completion-2026-10-02/p03-recovery-readonly-candidate/candidate_receipt.json",
"adoption_recommendation": "Reproduce and verify both preservation defects in an isolated candidate stage before claiming P03 acceptance; no main edits during ongoing full regression.",
"all_p03_accepted": false,
"full157_regression_result_included": false,
"limitations": [
"128 preflight does not combine unknown formal with valid marker/current backup",
"256 MiB is a serialized world limit, not total peak memory",
"inclusive upper-size test stops at manifest mismatch, not successful full-size decompression",
"20000-cell measurement is world-only, not full Runtime acceptance",
"new candidate has not been executed"
],
"report_sha256": "57de52db51a6b0b3dcbcf20f6df3a825b83ba2d9a9a7707e9bab7026cb3fc6c6",
"existing_contract_static_review": {
"save_operations_lines": [
349,
450
],
"runtime_save_lifecycle_lines": [
170,
200,
230,
380
],
"preserved": [
"registry continuity and purity",
"current schema rejection",
"registered legacy migration and exact original backup",
"failed migration original preservation",
"current-format interrupted migration backup/promotion/rollback",
"current-format normal recovery"
],
"strengthened": [
"unsupported recognizable formal never replaced before rejection",
"explicit candidate read does not reconcile",
"registered legacy failed source keeps normal stale artifacts"
],
"candidate_execution_verified": false,
"candidate_driver_operations": 8,
"candidate_foreign_shapes": 5
}
}
@@ -0,0 +1,104 @@
"""Integrate the preservation-fixed full regression without promoting game acceptance."""
from collections import Counter
from datetime import datetime
import hashlib
import json
from pathlib import Path
from zoneinfo import ZoneInfo
ROOT = Path(__file__).resolve().parents[4]
PLAN = ROOT / "docs/plans/original-completion-2026-10-02"
PREFIX = "artifacts/original-completion-2026-10-02/"
NOW = datetime.now(ZoneInfo("Asia/Tokyo")).isoformat()
def read(path):
return json.loads((ROOT / path).read_text())
def sha(path):
return hashlib.sha256((ROOT / path).read_bytes()).hexdigest()
def write(path, value):
(ROOT / path).write_text(json.dumps(value, ensure_ascii=False, indent=2) + "\n")
def evidence(path, scope):
return {"path": path, "sha256_at_integration": sha(path), "scope": scope,
"linked_at_jst": NOW, "current_game_acceptance_inferred": False}
def main():
regression_path = PREFIX + "full-regression-r02/verification.json"
regression = read(regression_path)
assert regression["passed"] and regression["suites"] == 158 and regression["checks"] == 12707 and not regression["changed_paths"]
opening = PREFIX + "p02-opening-restart-r02/"
assert all(r["passed"] for r in read(opening + "result.json")) and read(opening + "source-change.json") == []
full_map = read(PREFIX + "full-regression-r02/source-end.json")
opening_map = read(opening + "source-start.json")
assert all(full_map.get(p) == digest for p, digest in opening_map.items())
assert all(sha(p) == digest for p, digest in full_map.items())
acceptance_path = PREFIX + "p03-save-preservation-r02/adoption-acceptance.json"
assert not (ROOT / acceptance_path).exists(), "Keep prior checkpoint generations"
write(acceptance_path, {"scope": "limited SaveService preservation fix adoption, not full P03/game acceptance", "source_map": PREFIX + "full-regression-r02/source-end.json", "source_map_sha256": sha(PREFIX + "full-regression-r02/source-end.json"), "current_source_matches": True,
"merged_regression": evidence(regression_path, "158 suites/12707 checks/0 failures/source changes0"),
"opening_restart": evidence(opening + "result.json", "rendered normal UI signals; 83 writer+20 reader checks"),
"merge_receipt": evidence(PREFIX + "p03-save-preservation-r02/merge.json", "immutable focused acceptance/merge receipt"),
"standard_full_regression_after_merge_completed": True, "normal_pointer_human_play": False, "windows_acceptance": False, "original_full_acceptance": False, "accepted_at_jst": NOW})
plan_rel = "docs/plans/original-completion-2026-10-02/"
snapshot = read(plan_rel + "progress_snapshot.json")
snapshot.setdefault("regression_history", []).append(snapshot["latest_regression_at_evidence_time"])
snapshot["latest_regression_at_evidence_time"] = {"path": regression_path, "sha256": sha(regression_path),
"started_at_jst": regression["started_at_jst"], "finished_at_jst": regression["finished_at_jst"],
"suites": 158, "checks": 12707, "failures": 0, "source_changes_during_run": [],
"source_map_path": PREFIX + "full-regression-r02/source-end.json", "source_map_sha256": sha(PREFIX + "full-regression-r02/source-end.json"), "source_map_entries": len(full_map),
"current_source_delta_observed_after_run": [], "future_source_changes_auto_accepted": False,
"original_full_acceptance": False, "windows_acceptance": False,
"current_applicability": "current production source matches all 1208 input paths at checkpoint; P05 unadopted candidate excluded"}
snapshot["save_preservation_adoption"].update(state="merged_full_regression_and_limited_restart_verified", standard_full_regression_after_merge_completed=True, acceptance_path=acceptance_path, acceptance_sha256=sha(acceptance_path))
snapshot["opening_restart_current"] = evidence(opening + "result.json", "103 checks/source change0; current mapped game source319 matches full input1208")
snapshot["remaining_acceptance"] = [s for s in snapshot["remaining_acceptance"] if not s.startswith("未知版/明示候補読取の本体採用後")]
snapshot["integrated_at_jst"] = NOW
packages = read(plan_rel + "work_packages.json")
by_id = {p["id"]: p for p in packages}
by_id["P02"]["current_summary"] = "保存修正後の現版158 suites/12707 checks/失敗0/source差分0、限定通常UI103再開checks。全代表保存・同一Windows実機・全通常操作は未受入。"
by_id["P03"]["current_summary"] = "保存preflight/原状保持/Path guardを本体採用し、現版158回帰12707 checksと通常宿屋103再開checksを確認。全機能保存/移行/再開は未完。"
for pid, did in [("P02", "P02-01"), ("P03", "P03-01"), ("P03", "P03-02")]:
row = next(d for d in by_id[pid]["remaining_deliverables"] if d["id"] == did)
row["evidence"].append(evidence(regression_path, "現保存修正版の標準158回帰、12707 checks/source差分0"))
row["updated_at_jst"] = NOW
row = next(d for d in by_id["P03"]["remaining_deliverables"] if d["id"] == "P03-01")
row["evidence"].append(evidence(acceptance_path, "保存原状保持限定修正の統合受入"))
row["progress_summary"] = "保存preflight、未知/未来formal保護、明示backup純読取を本体採用し現版158回帰12707 checksが合格。限定宿屋の同版保存再開103 checksも確認。全機能保存契約は未完。"
row["remaining_gaps"] = [g for g in row["remaining_gaps"] if not g.startswith("採用SaveService SHA")]
for pid, did in [("P02", "P02-02"), ("P03", "P03-03")]:
row = next(d for d in by_id[pid]["remaining_deliverables"] if d["id"] == did)
row["evidence"].append(evidence(opening + "result.json", "保存修正後の描画付き通常UI/宿屋営業の83+20再開checks、human pointer受入ではない"))
row["evidence"].append(evidence(opening + "source-change.json", "再開実行中のソース差分0"))
row["progress_summary"] = "保存修正後の同版で通常UIから宿屋開業/3日決算/保存/別process再開を103 checks確認。全機能途中再開は未完。"
row["remaining_gaps"] = [g for g in row.get("remaining_gaps", []) if "今後のSAVE採用後" not in g]
row["updated_at_jst"] = NOW
p05 = next(d for d in by_id["P05"]["remaining_deliverables"] if d["id"] == "P05-01")
p05.update(state="in_progress", progress_summary="現版158からcanonical20overlayの候補161を構築。partial受入のr01環境guard誤判定/r02旧manual helper契約誤期待を保持、QA修正/追加境界/最終全回帰は未完。", updated_at_jst=NOW,
remaining_gaps=["旧QA helperの重複キー契約を正しい現本体の拒否契約へ補正し再検証。", "enabled-auto5境界、標準新testのfixture整合、PNG目視、最終同一source全回帰、本体採用が未完。"])
p05.setdefault("evidence", []).extend([evidence(PREFIX + "p05-current-stage-input-r01/preparation.json", "current base158/candidate161 isolated inputs, engine0"), evidence(PREFIX + "p05-acceptance-partial-r01/result.json", "失敗履歴:engine objectdb_snapshotsを既存セーブと誤判定"), evidence(PREFIX + "p05-acceptance-partial-r02/result.json", "失敗履歴:旧manual driverはduplicate成功を誤要求;本体未採用")])
snapshot["current_delivery_state_counts"] = dict(Counter(d["state"] for p in packages for d in p["remaining_deliverables"]))
snapshot["p05_partial_rejected"] = evidence(PREFIX + "p05-acceptance-partial-r02/result.json", "QA contract correction pending; does not prove candidate regression failure")
write(plan_rel + "work_packages.json", packages)
write(plan_rel + "progress_snapshot.json", snapshot)
main_plan = PLAN / "IMPLEMENTATION_PLAN.md"
body = main_plan.read_text()
body = body.replace("今回157回帰の実行版は別の1206対象ソース地図で固定", "今回158回帰の実行版は別の1208対象ソース地図で固定")
body = body.replace("SAVE追加採用前の01:14:41〜01:26:28 JST、157スイート、12,473チェック、失敗0、実行中ソース差分0", "保存追加採用後の01:41:43〜01:53:50 JST、158スイート、12,707チェック、失敗0、実行中ソース差分0")
body = body.replace("SAVE追加採用後全回帰、原本全実装、全資産、操作感、Windows", "原本全実装、全資産、全通常操作、Windows")
body = body.replace("SAVE追加修正前の157 suites/12473 checks/失敗0/source差分0を保持。採用後全回帰、代表保存、通常操作、同一Windows配布実機は未受入。", by_id["P02"]["current_summary"])
body = body.replace("preflightとPath guardの限定修正後157回帰あり。追加の未知版原状保持修正を741 focused checksで本体採用、採用後全回帰pending。全機能保存/移行/再開は未完。", by_id["P03"]["current_summary"])
body = body.replace("修正後の全回帰は未完。", "現版158回帰12707 checks/source差分0を確認。")
body += "\n### 実行追記 01:53以降\n\n保存修正後の[158回帰](../../../artifacts/original-completion-2026-10-02/full-regression-r02/verification.json)は12,707 checks、失敗0、source差分0。同版の[通常UI開業/再開](../../../artifacts/original-completion-2026-10-02/p02-opening-restart-r02/result.json)は83+20 checks。以前の157回帰は履歴として保持する。\n\nP05はbase158/candidate161を隔離構築し部分検証に着手したが、runner環境判定と旧QA helperの重複キー契約不一致で停止した。失敗履歴を保持して検証を補正中。候補を本体採用済みとは数えない。全施設/人物/ルート/エンド/図鑑/完成資産/長期プレイ/最大Runtime性能/同一Windows実機は未達を保持する。\n"
main_plan.write_text(body)
print("Checkpoint linked: current158/12707, limited103 restart, P05 partial rejected; game incomplete.")
if __name__ == "__main__":
main()
@@ -0,0 +1,105 @@
# -*- coding: utf-8 -*-
"""Integrate root-reviewed day-boundary evidence without promoting acceptance."""
from pathlib import Path
import argparse
import collections
import datetime
import difflib
import importlib.util
import json
import sys
sys.dont_write_bytecode = True
HERE = Path(__file__).resolve().parent
spec = importlib.util.spec_from_file_location("checkpoint_guard", HERE / "review_rescue_scale_checkpoint.py")
guard = importlib.util.module_from_spec(spec)
spec.loader.exec_module(guard)
ROOT, PLAN, ART = guard.ROOT, guard.PLAN, guard.ART
OUT = ART / "checkpoint-day-boundary-root-r01"
PROOF = ART / "p03-day-boundary-root-review-r01.json"
NAMES = guard.NAMES
read, sha, require, write = guard.read, guard.sha, guard.require, guard.write
def proof_guard():
p = read(PROOF)
require(p["passed"] and p["actual_checks"] == 183 and p["failures"] == 0, "Actual183/0 root proof")
require(len(p["whole_typed_pairs"]) == 12 and p["raw131_pins_rechecked"], "Full typed/raw coverage")
require(p["root_rendered_review_pending"] is False and len(p["pngs"]) == 6, "Root reviewed rendered proof")
require(all(p[k] is False for k in ("whole_P03_accepted", "whole_A05_accepted", "whole_normal_UI_accepted", "native_Windows_accepted", "performance_accepted")), "Limited scope")
seal = ART / "p03-cleaning-day-boundary-paired-r02/evidence-seal.json"
require(sha(seal) == p["evidence_seal_sha256"], "Immutable underlying seal")
return p
def states(packages):
return {p["id"]: {"state": p["state"], "deliveries": {t["id"]: t["state"] for t in p["remaining_deliverables"]}} for p in packages}
def prepare():
require(not OUT.exists(), "Fresh checkpoint required")
p = proof_guard()
source = guard.source()
require(source == read(ART / "p05-current-stage-input-r04/candidate-source.json") and len(source) == 1224, "Reviewed source1224")
protected = guard.protected()
before = {n: sha(PLAN / n) for n in NAMES}
packages = read(PLAN / "work_packages.json")
original_states = states(packages)
snapshot = read(PLAN / "progress_snapshot.json")
at = datetime.datetime.now(datetime.timezone(datetime.timedelta(hours=9))).isoformat()
evidence = {"path": PROOF.relative_to(ROOT).as_posix(), "sha256_at_integration": sha(PROOF), "scope": "Controlled public closed-cleaning day-boundary Main Save/Load183/0;12 whole typed pairs,IO1 actual formal recovery,uncapped15events,6PNG; not whole normal play", "linked_at_jst": at, "current_game_acceptance_inferred": False}
addition = " 制御した閉店清掃の日跨ぎMain保存/再開183/0・12全状態pair・描画6枚も限定照合。"
old_p03 = next(x for x in packages if x["id"] == "P03")["current_summary"]
old_p09 = next(x for x in packages if x["id"] == "P09")["current_summary"]
for pkg in packages:
if pkg["id"] not in ("P03", "P09"):
continue
pkg["current_summary"] += addition
pkg["updated_at_jst"] = at
for task in pkg["remaining_deliverables"]:
if task["id"] not in ("P03-01", "P03-03", "P09-01"):
continue
require(not any(x["path"] == evidence["path"] for x in task["evidence"]), "No duplicate evidence")
task["evidence"].append(evidence)
task["progress_summary"] += addition
task["updated_at_jst"] = at
require(states(packages) == original_states, "All package/delivery states unchanged")
require(dict(collections.Counter(t["state"] for pkg in packages for t in pkg["remaining_deliverables"])) == snapshot["current_delivery_state_counts"], "Delivery counts unchanged")
snapshot["integrated_at_jst"] = at
snapshot["current_day_boundary_checkpoint"] = {"root_review": evidence, "source_files": 1224, "actual_checks": 183, "failures": 0, "whole_typed_pairs": 12, "uncapped_branch_events_each": 15, "same_process_future_events_each": 6, "rendered_PNG": 6, "actual_IO": p["actual_IO"], "whole_P03_accepted": False, "whole_A05_accepted": False, "whole_normal_UI_accepted": False, "native_Windows_accepted": False, "performance_accepted": False, "source_changes_by_integration": 0, "adoption_receipt": OUT.relative_to(ROOT).as_posix() + "/adoption.json"}
section = "\n\n### 閉店清掃の日跨ぎ保存と決算の限定照合\n\n[Root証拠](../../../artifacts/original-completion-2026-10-02/p03-day-boundary-root-review-r01.json)で、Mainの保存/読込handlerから別PID再開を通し183 checks/0、131 raw pins、12全状態typed pairs、元formal4ファイル不変を確認した。公開建設と資源fixtureで用意した閉店清掃施設を23:59(2879分)に保存し、00:00(2880分)の全保有日2G維持費と00:01の再徴収なしを描画6枚(root直接4枚・同一bytes2枚)で照合した。実Loadは通常UIのformal候補を選ぶSAVE_RECOVERY_LOADEDで、Save IO1件のevent_type/payloadだけを同じID/時刻/envelope/save_idに拘束して比較し、event削除・field除外は0。無制限branch journal各15件、同process future各6件も全量照合した。\n\n公開fixtureと制御した時刻進行を含む限定証拠である。全A05、全P03、全通常操作、完成素材、性能、Windowsの受入は未完のまま保持する。既存460/650/249や164回帰と別実行であり、件数を全体受入率へ加算しない。[文書採用記録](../../../artifacts/original-completion-2026-10-02/checkpoint-day-boundary-root-r01/adoption.json)に旧/採用4文書SHAとsource/protected不変を保存する。パッケージ/作業状態、全原子8観点、最終分母と全体率は変更しない。\n"
text = (PLAN / "IMPLEMENTATION_PLAN.md").read_text(encoding="utf-8")
require(text.count(old_p03) == 3 and text.count(old_p09) == 2, "Exact package/task current statements")
text = text.replace(old_p03, old_p03 + addition).replace(old_p09, old_p09 + addition)
contents = {"IMPLEMENTATION_PLAN.md": text + section, "PROGRESS_INTEGRATION.md": (PLAN / "PROGRESS_INTEGRATION.md").read_text(encoding="utf-8") + section, "work_packages.json": json.dumps(packages, ensure_ascii=False, indent=2) + "\n", "progress_snapshot.json": json.dumps(snapshot, ensure_ascii=False, indent=2) + "\n"}
OUT.mkdir(); (OUT / "before").mkdir(); (OUT / "reviewed").mkdir()
for name, value in contents.items():
(OUT / "before" / name).write_bytes((PLAN / name).read_bytes())
(OUT / "reviewed" / name).write_text(value, encoding="utf-8")
diff = difflib.unified_diff((OUT / "before" / name).read_text(encoding="utf-8").splitlines(True), value.splitlines(True), fromfile="before/"+name, tofile="reviewed/"+name)
(OUT / (name + ".diff")).write_text("".join(diff), encoding="utf-8")
require(guard.source() == source and guard.protected() == protected and all(sha(PLAN / n) == h for n,h in before.items()), "Preparation has no production changes")
write(OUT / "preparation.json", {"before": before, "reviewed": {n: sha(OUT / "reviewed" / n) for n in NAMES}, "source": source, "protected": protected, "root_proof_sha256": sha(PROOF), "all_states": original_states, "prepared_at_jst": at, "production_document_writes": 0})
print("Prepared day boundary four-document checkpoint; all states/counts unchanged")
def adopt():
data = read(OUT / "preparation.json")
require(not (OUT / "adoption.json").exists(), "Fresh adoption receipt")
proof_guard()
require(sha(PROOF) == data["root_proof_sha256"] and guard.source() == data["source"] and guard.protected() == data["protected"], "Root evidence/source/protected pins")
require(all(sha(PLAN / n) == h for n,h in data["before"].items()) and all(sha(OUT / "reviewed" / n) == h for n,h in data["reviewed"].items()), "Reviewed document pins")
require(states(read(OUT / "reviewed/work_packages.json")) == data["all_states"], "No status promotions")
for name in NAMES:
temp = PLAN / (name + ".day-boundary-checkpoint-tmp")
require(not temp.exists(), "Unexpected temporary file")
temp.write_bytes((OUT / "reviewed" / name).read_bytes()); temp.replace(PLAN / name)
require(guard.source() == data["source"] and guard.protected() == data["protected"] and all(sha(PLAN / n) == h for n,h in data["reviewed"].items()), "Exact adopted documents/source")
write(OUT / "adoption.json", {"passed": True, "before": data["before"], "adopted": data["reviewed"], "root_proof_sha256": sha(PROOF), "source_files": 1224, "source_changes": [], "protected_unchanged": data["protected"], "all_states_unchanged": True, "diff_reviewed_by_root": True, "engine_runs": 0, "completed_deliveries_added": 0, "whole_P03_accepted": False, "whole_A05_accepted": False, "whole_original_accepted": False})
print("Adopted day boundary evidence; source0/all states unchanged")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("mode", choices=("prepare", "adopt"))
getattr(sys.modules[__name__], parser.parse_args().mode)()
@@ -0,0 +1,96 @@
"""Record the root-reviewed failed setup diagnostic without accepting P28."""
from pathlib import Path
import argparse
import datetime
import difflib
import importlib.util
import json
import sys
sys.dont_write_bytecode = True
HERE = Path(__file__).resolve().parent
spec = importlib.util.spec_from_file_location('setup_checkpoint_guard', HERE / 'review_rescue_scale_checkpoint.py')
guard = importlib.util.module_from_spec(spec)
spec.loader.exec_module(guard)
ROOT, PLAN, ART = guard.ROOT, guard.PLAN, guard.ART
OUT = ART / 'checkpoint-p28-setupspan-root-r01'
PROOF = ART / 'p28-setupspan-timeout-root-review-r03.json'
NAMES = guard.NAMES
def states(packages):
return {p['id']: {'state': p['state'], 'deliveries': {t['id']: t['state'] for t in p['remaining_deliverables']}} for p in packages}
def verify_proof():
p = guard.read(PROOF)
assert p['actual_timeout_exit'] == -15 and p['strict_timeout_seconds'] == 900.018546084
assert p['completed_public_tick_spans'] == 241 and p['whole_tick429_to430_seconds'] == 268.722914
assert p['final_target_counts'] is None and p['measurement'] is None and not p['formal_Save_Load']
assert not p['P28_accepted'] and not p['whole_game_accepted'] and not p['internal_hotspot_identified']
assert guard.sha(ART / 'p28-setupspan-timeout-r03/receipt.json') == p['receipt_sha256']
assert guard.sha(ART / 'p28-setupspan-timeout-r03/evidence-seal.json') == p['seal_sha256']
return p
def prepare():
assert not OUT.exists()
proof = verify_proof()
source, protected = guard.source(), guard.protected()
assert source == guard.read(ART / 'p05-current-stage-input-r04/candidate-source.json') and len(source) == 1224
before = {n: guard.sha(PLAN / n) for n in NAMES}
packages, snapshot = guard.read(PLAN / 'work_packages.json'), guard.read(PLAN / 'progress_snapshot.json')
original_states = states(packages)
at = datetime.datetime.now(datetime.timezone(datetime.timedelta(hours=9))).isoformat()
evidence = {'path': PROOF.relative_to(ROOT).as_posix(), 'sha256_at_integration': guard.sha(PROOF), 'scope': 'Actual BUILD900.018546084s/-15 timeout; 241 completed public ticks; whole tick429→430 took268.722914s; last601→602 incomplete; final targets/Save/measurements absent', 'linked_at_jst': at, 'current_game_acceptance_inferred': False}
addition = ' setup区間観測の別実行も900.018秒timeout。429→430分の公開tickは268.723秒、601→602分は未完。内部hotspot・最終target数・保存・性能測定は未確定。'
pkg = next(p for p in packages if p['id'] == 'P28')
old_summary = pkg['current_summary']
pkg['current_summary'] += addition
pkg['updated_at_jst'] = at
task = next(t for t in pkg['remaining_deliverables'] if t['id'] == 'P28-01')
assert not any(x['path'] == evidence['path'] for x in task['evidence'])
task['evidence'].append(evidence)
task['progress_summary'] += addition
task['updated_at_jst'] = at
assert states(packages) == original_states
snapshot['integrated_at_jst'] = at
snapshot['current_p28_setupspan_checkpoint'] = {'root_review': evidence, 'source_files': 1224, 'strict_timeout_seconds': proof['strict_timeout_seconds'], 'actual_exit': -15, 'progress_raw_records': 4484, 'completed_public_tick_spans': 241, 'completed_command_spans': 1974, 'whole_tick429_to430_seconds': proof['whole_tick429_to430_seconds'], 'last_public_tick601_to602_completed': False, 'internal_hotspot_identified': False, 'final_target_counts': None, 'formal_Save_Load': False, 'measurements': None, 'population_cap_changed': False, 'P28_accepted': False, 'native_Windows_accepted': False, 'whole_game_accepted': False, 'adoption_receipt': OUT.relative_to(ROOT).as_posix() + '/adoption.json'}
section = '\n\n### 最大負荷の準備区間観測と未完の更新\n\n[Root再照合](../../../artifacts/original-completion-2026-10-02/p28-setupspan-timeout-root-review-r03.json)は、同じ現source1224と元の負荷量・900秒制限を保持した別実行の失敗記録である。実BUILDは900.018546084秒でtimeout/-15。28 raw pins、1226 stage noncache pins、実5PID終了、4484進捗行、241完了tick区間を照合した。初期の公開経路グラフrebuildは0.487650秒、429→430分の公開tick全体は268.722914秒。施設建設・客と物流の投入後、601→602分のtickに入って終了せず、最終target数・保存・再読込・x1/x3測定には到達していない。内部関数の実profileは未取得で、hotspotを断定しない。\n\n正式保存とraw証拠を保全したまま、終了済みprivate stageの再生成可能なcacheだけを回収した。通常Operationsのcap100、最大負荷目標、制限時間は変更していない。次は公開Kernel phase境界の観測候補を用意する。P28と全体は未受入、全原子8観点・最終分母・全体率・全package/delivery状態は変更しない。[文書採用記録](../../../artifacts/original-completion-2026-10-02/checkpoint-p28-setupspan-root-r01/adoption.json)に4文書の旧/採用SHAを保持する。\n'
body = (PLAN / 'IMPLEMENTATION_PLAN.md').read_text()
assert old_summary in body
body = body.replace(old_summary, old_summary + addition)
body = body.replace('通常Operations cap100を保持しsetup区間の観測候補を準備', '通常Operations cap100を保持。setup別実行も900.018秒timeout、公開tick429→430が268.723秒')
values = {'IMPLEMENTATION_PLAN.md': body + section, 'PROGRESS_INTEGRATION.md': (PLAN / 'PROGRESS_INTEGRATION.md').read_text() + section, 'work_packages.json': json.dumps(packages, ensure_ascii=False, indent=2) + '\n', 'progress_snapshot.json': json.dumps(snapshot, ensure_ascii=False, indent=2) + '\n'}
OUT.mkdir(); (OUT / 'before').mkdir(); (OUT / 'reviewed').mkdir()
for name, value in values.items():
(OUT / 'before' / name).write_bytes((PLAN / name).read_bytes())
(OUT / 'reviewed' / name).write_text(value)
(OUT / (name + '.diff')).write_text(''.join(difflib.unified_diff((PLAN / name).read_text().splitlines(True), value.splitlines(True), fromfile='before/'+name, tofile='reviewed/'+name)))
assert guard.source() == source and guard.protected() == protected and all(guard.sha(PLAN / n) == h for n, h in before.items())
guard.write(OUT / 'preparation.json', {'before': before, 'reviewed': {n: guard.sha(OUT / 'reviewed' / n) for n in NAMES}, 'source': source, 'protected': protected, 'all_states': original_states, 'root_proof_sha256': guard.sha(PROOF), 'prepared_at_jst': at, 'production_document_writes': 0})
print('Prepared failed P28 setup checkpoint; no acceptance or state changes')
def adopt():
d = guard.read(OUT / 'preparation.json')
verify_proof()
assert not (OUT / 'adoption.json').exists()
assert guard.sha(PROOF) == d['root_proof_sha256'] and guard.source() == d['source'] and guard.protected() == d['protected']
assert all(guard.sha(PLAN / n) == h for n, h in d['before'].items())
assert all(guard.sha(OUT / 'reviewed' / n) == h for n, h in d['reviewed'].items())
assert states(guard.read(OUT / 'reviewed/work_packages.json')) == d['all_states']
for name in NAMES:
temp = PLAN / (name + '.p28-setup-checkpoint-tmp')
assert not temp.exists()
temp.write_bytes((OUT / 'reviewed' / name).read_bytes()); temp.replace(PLAN / name)
assert guard.source() == d['source'] and guard.protected() == d['protected']
assert all(guard.sha(PLAN / n) == h for n, h in d['reviewed'].items())
guard.write(OUT / 'adoption.json', {'passed': True, 'before': d['before'], 'adopted': d['reviewed'], 'root_proof_sha256': guard.sha(PROOF), 'source_files': 1224, 'source_changes': [], 'protected_unchanged': d['protected'], 'all_states_unchanged': True, 'diff_reviewed_by_root': True, 'engine_runs': 0, 'completed_deliveries_added': 0, 'P28_accepted': False, 'whole_original_accepted': False})
print('Adopted failed P28 setup evidence; source/state/denominator unchanged')
if __name__ == '__main__':
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('mode', choices=['prepare', 'adopt'])
getattr(sys.modules[__name__], parser.parse_args().mode)()
@@ -0,0 +1,110 @@
# -*- coding: utf-8 -*-
"""Integrate controlled P06 proof; retain all mandatory unfinished acceptance."""
from pathlib import Path
import argparse
import collections
import datetime
import difflib
import importlib.util
import json
import sys
sys.dont_write_bytecode = True
HERE = Path(__file__).resolve().parent
spec = importlib.util.spec_from_file_location('checkpoint_guard', HERE / 'review_rescue_scale_checkpoint.py')
guard = importlib.util.module_from_spec(spec)
spec.loader.exec_module(guard)
ROOT, PLAN, ART = guard.ROOT, guard.PLAN, guard.ART
OUT = ART / 'checkpoint-rescue-power-root-r01'
PROOF = ART / 'p06-rescue-power-final-root-review-r01.json'
NAMES = guard.NAMES
read, sha, require, write = guard.read, guard.sha, guard.require, guard.write
def states(packages):
return {p['id']: {'state': p['state'], 'deliveries': {t['id']: t['state'] for t in p['remaining_deliverables']}} for p in packages}
def proof_guard():
p = read(PROOF)
require(p['passed'] and p['actual_checks'] == 691 and p['failures'] == 0 and p['whole_typed_pairs'] == 10 and p['files_rehashed'] == 187, 'Root actual P06 proof')
require(all(x['conditions'] == [True]*6 for x in p['private_profile_guards']), 'Actual six private guards')
require(all(p[k] is False for k in ['natural_outage_accepted', 'valid_landing_emergency_alighting_accepted', 'whole_P06_accepted', 'normal_UI_accepted', 'native_Windows_accepted', 'whole_game_accepted']), 'Limited scope')
require(sha(ART / 'p06-rescue-power-paired-r03/evidence-seal.json') == p['evidence_seal_sha256'], 'Immutable actual seal')
require(sha(ART / 'kitchen-and-rescue-power-root-review-r01.json') == p['whole_raw_typed_formal_root_review_sha256'], 'Underlying root typed/raw proof')
return p
def prepare():
require(not OUT.exists(), 'Fresh checkpoint')
p = proof_guard(); source = guard.source(); protected = guard.protected()
require(len(source) == 1224 and source == read(ART / 'p05-current-stage-input-r04/candidate-source.json'), 'Current adopted input1224')
before = {n: sha(PLAN / n) for n in NAMES}
packages = read(PLAN / 'work_packages.json'); old_states = states(packages)
snapshot = read(PLAN / 'progress_snapshot.json')
at = datetime.datetime.now(datetime.timezone(datetime.timedelta(hours=9))).isoformat()
evidence = {'path': PROOF.relative_to(ROOT).as_posix(), 'sha256_at_integration': sha(PROOF), 'scope': 'Controlled held boarded EV/rescue outage Runtime14 save pair691/0,10 complete typed states,uncapped9events,formal4immutable; emergency alighting/natural outage/UI/native pending', 'linked_at_jst': at, 'current_game_acceptance_inferred': False}
addition = ' 制御したEV乗車中救護の停電保存/再開691/0・10全状態pair・無制限journal各9件を限定照合。安全階での緊急降車・自然停電・全館停止・通常UIは未受入。'
old_p03 = next(x for x in packages if x['id'] == 'P03')['current_summary']
old_p06 = next(x for x in packages if x['id'] == 'P06')['current_summary']
for package in packages:
if package['id'] not in ['P03', 'P06']: continue
package['current_summary'] += addition; package['updated_at_jst'] = at
for task in package['remaining_deliverables']:
if task['id'] not in ['P03-01', 'P03-03', 'P06-02', 'P06-03']: continue
require(not any(x['path'] == evidence['path'] for x in task['evidence']), 'No duplicate evidence')
task['evidence'].append(evidence)
task['progress_summary'] = (task.get('progress_summary') or '') + addition
task['updated_at_jst'] = at
if task['id'] in ['P06-02', 'P06-03']:
require(task['state'] == 'planned', 'Exact prior planned state')
task['state'] = 'in_progress'
new_states = states(packages)
for pkg in old_states:
require(old_states[pkg]['state'] == new_states[pkg]['state'], 'No package state change')
for task, old in old_states[pkg]['deliveries'].items():
require(new_states[pkg]['deliveries'][task] == ('in_progress' if task in ['P06-02', 'P06-03'] else old), 'Only two actual initiated deliveries')
counts = dict(collections.Counter(t['state'] for p in packages for t in p['remaining_deliverables']))
require(counts == {'completed': 1, 'in_progress': 15, 'planned': 72}, 'Exact88 delivery counts; no completion added')
snapshot['integrated_at_jst'] = at; snapshot['current_delivery_state_counts'] = counts
snapshot['current_rescue_power_checkpoint'] = {'root_review': evidence, 'source_files': 1224, 'actual_checks': 691, 'failures': 0, 'whole_typed_pairs': 10, 'uncapped_future_events_each': 9, 'actual_private_guard_conditions_each': 6, 'formal_source_files_immutable': 4, 'source_changes_by_integration': 0, 'state_changes': {'P06-02': 'planned -> in_progress', 'P06-03': 'planned -> in_progress'}, 'whole_P06_accepted': False, 'natural_outage_accepted': False, 'valid_landing_emergency_alighting_accepted': False, 'normal_UI_accepted': False, 'native_Windows_accepted': False, 'adoption_receipt': OUT.relative_to(ROOT).as_posix() + '/adoption.json'}
section = '\n\n### EV乗車中救護の停電保存・復帰の限定照合\n\n[Root証拠](../../../artifacts/original-completion-2026-10-02/p06-rescue-power-final-root-review-r01.json)で、現採用Runtime14・source1224のwriter336+別PIDreader355=691 checks/0、187 raw/proof pins、実6条件Guard、10全状態typed pairs、元formal4ファイル不変を確認した。救護搬送中のEV乗車を公開操作で用意し、全停車階の一時閉鎖と実マナ量の差額操作で停止枝を制御している。停止中の同じTask・trip・seat・countdown・人物参照を保持し、元Trafficの全設定と実マナ量を戻した後の最初のtickから、治療29/30分・完了・追加5分まで比較した。IO差は実Save/Loadの同じID・時刻・envelope・save_idに拘束したevent_type/payloadの完全代替だけで、field除外・event削除は0。無制限未来journal各9件もtyped全量一致。\n\n安全な停車階がある場合の緊急降車、自然なマナ枯渇、全館停止、通常UI、描画、Windowsと全P06は未受入。候補r01の証拠名衝突によるwriter282/1・reader未実行も保持した。厨房候補278/0と影響9のS3費用fixture失敗は別証拠として保持し、本体採用や全回帰へ転用しない。P06-02/P06-03のみ実着手に合わせて予定から着手中へ変更し、30パッケージの状態・認定済み完了数・全原子8観点・最終分母と全体率は変更しない。\n'
text = (PLAN / 'IMPLEMENTATION_PLAN.md').read_text(encoding='utf-8')
require(text.count(old_p03) == 3 and text.count(old_p06) == 1, 'Exact prior summary occurrence counts')
text = text.replace(old_p03, old_p03 + addition).replace(old_p06, old_p06 + addition)
for task_id in ['P06-02', 'P06-03']:
lines = text.splitlines(True)
matches = [i for i, line in enumerate(lines) if line.startswith('- ' + task_id + ' ')]
require(len(matches) == 1, 'Exact P06 delivery paragraph')
i = matches[0]; lines[i] = lines[i].rstrip('\n') + ' 状態: 着手中。' + addition + '\n'
text = ''.join(lines)
contents = {'IMPLEMENTATION_PLAN.md': text + section, 'PROGRESS_INTEGRATION.md': (PLAN / 'PROGRESS_INTEGRATION.md').read_text(encoding='utf-8') + section, 'work_packages.json': json.dumps(packages, ensure_ascii=False, indent=2) + '\n', 'progress_snapshot.json': json.dumps(snapshot, ensure_ascii=False, indent=2) + '\n'}
OUT.mkdir(); (OUT / 'before').mkdir(); (OUT / 'reviewed').mkdir()
for name, value in contents.items():
(OUT / 'before' / name).write_bytes((PLAN / name).read_bytes())
(OUT / 'reviewed' / name).write_text(value, encoding='utf-8')
diff = difflib.unified_diff((OUT / 'before' / name).read_text(encoding='utf-8').splitlines(True), value.splitlines(True), fromfile='before/'+name, tofile='reviewed/'+name)
(OUT / (name + '.diff')).write_text(''.join(diff), encoding='utf-8')
require(guard.source() == source and guard.protected() == protected and all(sha(PLAN / n) == h for n, h in before.items()), 'Preparation no changes')
write(OUT / 'preparation.json', {'before': before, 'reviewed': {n: sha(OUT / 'reviewed' / n) for n in NAMES}, 'source': source, 'protected': protected, 'root_proof_sha256': sha(PROOF), 'old_states': old_states, 'new_states': new_states, 'production_document_writes': 0})
print('Prepared P06 four-document checkpoint; only planned2 -> in_progress2; no acceptance added')
def adopt():
data = read(OUT / 'preparation.json'); proof_guard()
require(not (OUT / 'adoption.json').exists(), 'Fresh adoption')
require(sha(PROOF) == data['root_proof_sha256'] and guard.source() == data['source'] and guard.protected() == data['protected'], 'Evidence/source/protected pins')
require(all(sha(PLAN / n) == h for n, h in data['before'].items()) and all(sha(OUT / 'reviewed' / n) == h for n, h in data['reviewed'].items()), 'Reviewed four documents unchanged')
require(states(read(OUT / 'reviewed/work_packages.json')) == data['new_states'], 'Exact reviewed state changes')
for name in NAMES:
temp = PLAN / (name + '.rescue-power-tmp'); require(not temp.exists(), 'Fresh temporary file')
temp.write_bytes((OUT / 'reviewed' / name).read_bytes()); temp.replace(PLAN / name)
require(guard.source() == data['source'] and guard.protected() == data['protected'] and all(sha(PLAN / n) == h for n, h in data['reviewed'].items()), 'Exact adopted docs/source')
write(OUT / 'adoption.json', {'passed': True, 'before': data['before'], 'adopted': data['reviewed'], 'root_proof_sha256': sha(PROOF), 'source_files': 1224, 'source_changes': [], 'protected_unchanged': data['protected'], 'states_changed_only': ['P06-02', 'P06-03'], 'completed_deliveries_added': 0, 'diff_reviewed_by_root': True, 'engine_runs': 0, 'whole_P06_accepted': False, 'whole_original_accepted': False})
print('Adopted P06 controlled evidence; source0/completions0;15 inprogress/72planned')
if __name__ == '__main__':
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('mode', choices=['prepare', 'adopt'])
getattr(sys.modules[__name__], parser.parse_args().mode)()
@@ -0,0 +1,140 @@
# -*- coding: utf-8 -*-
"""Prepare/adopt four plan documents for the reviewed current Windows subset."""
from pathlib import Path
import argparse
import collections
import datetime
import difflib
import hashlib
import importlib.util
import json
ROOT = Path(__file__).resolve().parents[4]
PLAN = ROOT / "docs/plans/original-completion-2026-10-02"
ART = ROOT / "artifacts/original-completion-2026-10-02"
OUT = ART / "checkpoint-windows-current-root-r01"
NAMES = ("IMPLEMENTATION_PLAN.md", "PROGRESS_INTEGRATION.md", "work_packages.json", "progress_snapshot.json")
def sha(path):
return hashlib.sha256(path.read_bytes()).hexdigest()
def read(path):
return json.loads(path.read_text())
def dump(value):
return json.dumps(value, ensure_ascii=False, indent=2) + "\n"
def require(value, message):
if not value:
raise AssertionError(message)
def source():
path = ART / "windows-current-release-adapter-prep-r04/windows_adapter.py"
spec = importlib.util.spec_from_file_location("windows_checkpoint_adapter", path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module.inventory(ROOT)
def protected():
names = ("atomic_requirements.json", "progress_contract.json", "current_evidence_links.json", "atomic_denominator_freeze.json", "source_atomic_coverage.json", "baseline.json", "decisions.json")
return {name: sha(PLAN / name) for name in names}
def prepare():
require(not OUT.exists(), "Fresh checkpoint required")
proof_path = ART / "windows-current-release-root-review-r01/review.json"
proof = read(proof_path)
require(proof["passed"] and proof["native_Windows"] == "pending" and not proof["whole_original_acceptance"], "Reviewed limited evidence required")
pins = read(ART / "windows-current-release-candidate-r03/source-start.json")
require(source() == pins, "Source changed after Windows review")
at = datetime.datetime.now(datetime.timezone(datetime.timedelta(hours=9))).isoformat()
OUT.mkdir()
(OUT / "before").mkdir()
(OUT / "reviewed").mkdir()
before = {name: sha(PLAN / name) for name in NAMES}
guard = protected()
for name in NAMES:
(OUT / "before" / name).write_bytes((PLAN / name).read_bytes())
def ref(relative, scope):
return {"path": relative, "sha256_at_integration": sha(ROOT / relative), "scope": scope, "linked_at_jst": at, "current_game_acceptance_inferred": False}
review = ref(proof_path.relative_to(ROOT).as_posix(), "Current1224/852-runtime export/ZIP10memberCRC+SHA, macOS samePCK626 raw+5profiles,195kitpins; native Windows pending")
paired = ref("artifacts/original-completion-2026-10-02/windows-current-release-same-pck-r01/verification.json", "Actual macOS samePCK5 suites626/0; not native Windows/OS normal operations/performance")
package = ref("artifacts/original-completion-2026-10-02/windows-current-release-candidate-r03/package-integrity.json", "Actual release ZIP CRC/all10memberSHA; unmodified official EXE template, finished EXE resources unaccepted")
kit = ref("artifacts/original-completion-2026-10-02/native-windows-current-release-kit-r01/kit-manifest.json", "195-file artifact-only native kit; PowerShell parsing/C#compile/native launches remain unverified/0")
status = "現Runtime14・1224入力のWindows release候補とZIP全10メンバーのCRC/SHAを照合。macOS上の同一PCK5 suites/626 checks失敗0。Windows実機・完成EXE資産は未受入。"
packages = read(PLAN / "work_packages.json")
p02 = next(p for p in packages if p["id"] == "P02")
p29 = next(p for p in packages if p["id"] == "P29")
task = next(t for t in p02["remaining_deliverables"] if t["id"] == "P02-03")
task["evidence"] += [review, paired, kit]
task["progress_summary"] = status + " native kitは準備済みで、実機機種情報/PowerShell解析/起動は未確認。"
task["remaining_gaps"] = ["Windows機の到達性/OS/CPU/GPU/RAM/倍率/解像度と同一配布物の実機起動未確認。", "通常操作/保存終了再起動/日本語パス/音の実聴/Windows描画と性能は未受入。", "候補はapplication/modify_resources=false。完成製品のEXEアイコン等の受入と後続変更後の再書出しが必要。"]
task["updated_at_jst"] = at
p02["current_summary"] += " 現配布候補の書出し/ZIPとmacOS同一PCK626は限定照合済み。"
p29["current_summary"] = status
task29 = next(t for t in p29["remaining_deliverables"] if t["id"] == "P29-01")
task29["state"] = "in_progress"
task29["evidence"] += [review, package]
task29["progress_summary"] = status
task29["remaining_gaps"] = ["完成EXE資産/全ゲームの最終同一候補受入/後続ゲーム変更後の再書出しは未完。"]
task29["updated_at_jst"] = at
p29["updated_at_jst"] = at
(OUT / "reviewed/work_packages.json").write_text(dump(packages))
snapshot = read(PLAN / "progress_snapshot.json")
snapshot["integrated_at_jst"] = at
snapshot["current_delivery_state_counts"] = dict(collections.Counter(t["state"] for p in packages for t in p["remaining_deliverables"]))
snapshot["current_windows_limited_checkpoint"] = {"root_review": review, "same_PCK": paired, "package": package, "native_kit": kit, "source_files": 1224, "runtime_export_inputs": 852, "actual_macOS_same_PCK_suites": 5, "actual_macOS_same_PCK_checks": 626, "native_Windows": "pending", "native_windows_launches": 0, "PowerShell_parser": "unverified", "CSharp_compile": "unverified", "finished_EXE_resources_accepted": False, "full_original_accepted": False, "source_changes_by_integration": 0, "adoption_receipt": "artifacts/original-completion-2026-10-02/checkpoint-windows-current-root-r01/adoption.json"}
(OUT / "reviewed/progress_snapshot.json").write_text(dump(snapshot))
section = "\n\n### 現版Windows候補の限定照合\n\n[Root照合](../../../artifacts/original-completion-2026-10-02/windows-current-release-root-review-r01/review.json)は、現Runtime14・1224 sourceと852 runtime入力からのrelease EXE/PCK、ZIP全10メンバーCRC/SHAを確認した。EXE `d34d36f3…`、PCK `6445885a…`、ZIP `736cbc48…` の同じ配布パックを用いたmacOS上5 suites/626 checksは失敗0で、各専用profileの実5条件とraw logを照合した。これはWindows実機の起動・通常操作・性能の受入ではない。\n\n195-file native kitは同じ配布SHAと実機情報/profile/rawを記録する準備物。PowerShell解析・C#compile・Windows起動は未確認、実機0を保持する。現候補はclone-only `application/modify_resources=false` で公式template EXEを使うため、完成EXEアイコン等の受入は未完。ENOSPCの部分ZIPと前回0B EXEの失敗履歴を保持し、成功へ書換えていない。P29-01は着手中へ更新し、全体・P02/P29・原子8観点の完了は増やさない。\n\n[文書採用記録](../../../artifacts/original-completion-2026-10-02/checkpoint-windows-current-root-r01/adoption.json)に旧/採用後4文書SHAと変更0のsource/protected台帳を保持する。後続ゲーム変更には別source・配布候補・回帰が必要。\n"
text = (PLAN / "IMPLEMENTATION_PLAN.md").read_text()
replacements = {
"| Windows | 旧1394配布物のCRCと9ファイルmanifestを再確認 | 現採用版の書出し、機種情報、同一EXEでの実機操作・保存再開 |": "| Windows | 現1224 sourceのrelease候補・ZIP全10member CRC/SHA、macOS同一PCK626/0をroot照合 | Windows機種情報・同一EXE実機操作/保存再開・完成EXE資産 |",
"状態: 着手中。旧1394配布物の整合確認のみ。同一現版Windows実機・スペック・表示環境は未確認。": "状態: 着手中。現1224 release候補/ZIPをroot照合、macOS同一PCK626/0。native kit準備済み。Windows実機/機種情報/完成EXE資産は未受入。",
"現在地: 旧1394版Windows配布物のZIP・PCK検査とmacOSでのPCK実行は合格。現採用版のWindows書出し・同一配布実機受入は未完。": "現在地: " + status,
"- P29-01 最新候補の書き出し。採用済みソースだけからWindows EXE/PCKを再生成し、同梱データとZIPを確認する。 受入: ソース・PCK・EXE・ZIPのハッシュ、同梱マニフェスト、CRCが対応する。": "- P29-01 最新候補の書き出し。採用済みソースだけからWindows EXE/PCKを再生成し、同梱データとZIPを確認する。 受入: ソース・PCK・EXE・ZIPのハッシュ、同梱マニフェスト、CRCが対応する。 状態: 着手中。現1224候補/ZIPと同一PCK626/0を限定照合。完成EXE資産・後続変更後の最終候補は未受入。",
}
for before_text, after_text in replacements.items():
require(text.count(before_text) == 1, "Expected plan text missing: " + before_text)
text = text.replace(before_text, after_text)
(OUT / "reviewed/IMPLEMENTATION_PLAN.md").write_text(text + section)
(OUT / "reviewed/PROGRESS_INTEGRATION.md").write_text((PLAN / "PROGRESS_INTEGRATION.md").read_text() + section)
after = {name: sha(OUT / "reviewed" / name) for name in NAMES}
for name in NAMES:
delta = difflib.unified_diff((OUT / "before" / name).read_text().splitlines(True), (OUT / "reviewed" / name).read_text().splitlines(True), fromfile="before/" + name, tofile="reviewed/" + name)
(OUT / (name + ".diff")).write_text("".join(delta))
require(source() == pins and protected() == guard and all(sha(PLAN / n) == v for n, v in before.items()), "Production changed while preparing")
(OUT / "preparation.json").write_text(dump({"before": before, "reviewed": after, "protected": guard, "source_map": pins, "root_review_sha256": sha(proof_path), "prepared_at_jst": at, "production_document_writes": 0, "game_source_changes": [], "completed_deliveries_added": 0}))
print("Prepared four reviewed documents; production writes=0")
def adopt():
data = read(OUT / "preparation.json")
require(not (OUT / "adoption.json").exists(), "Already adopted")
require(source() == data["source_map"] and protected() == data["protected"], "Protected/current source changed")
require(all(sha(PLAN / n) == v for n, v in data["before"].items()), "Production document changed")
require(all(sha(OUT / "reviewed" / n) == v for n, v in data["reviewed"].items()), "Reviewed candidate changed")
require(sha(ART / "windows-current-release-root-review-r01/review.json") == data["root_review_sha256"], "Root evidence changed")
for name in NAMES:
temp = PLAN / (name + ".windows-checkpoint-tmp")
require(not temp.exists(), "Unexpected staging file")
temp.write_bytes((OUT / "reviewed" / name).read_bytes())
temp.replace(PLAN / name)
require(source() == data["source_map"] and protected() == data["protected"], "Source/protected changed during adoption")
require(all(sha(PLAN / n) == v for n, v in data["reviewed"].items()), "Adopted document SHA differs")
(OUT / "adoption.json").write_text(dump({"passed": True, "before": data["before"], "adopted": data["reviewed"], "root_review_sha256": data["root_review_sha256"], "protected_unchanged": data["protected"], "source_files": len(data["source_map"]), "source_changes": [], "document_diff_reviewed_by_root": True, "engine_runs": 0, "new_completed_deliveries": 0, "native_Windows": "pending", "whole_original_acceptance": False}))
print("Adopted four plan documents; source/protected changes=0")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("mode", choices=("prepare", "adopt"))
args = parser.parse_args()
(prepare if args.mode == "prepare" else adopt)()
@@ -0,0 +1,81 @@
"""Exercise plan-validator rejection guards in temporary planning copies only."""
from contextlib import redirect_stdout
from datetime import datetime
import importlib.util
import io
import json
from pathlib import Path
import shutil
import tempfile
from zoneinfo import ZoneInfo
PLAN = Path(__file__).resolve().parents[1]
ROOT = PLAN.parents[2]
INPUTS = [
"work_packages.json", "requirement_coverage.json", "baseline.json", "decisions.json",
"progress_contract.json", "atomic_requirements.json", "atomic_denominator_freeze.json",
"current_evidence_links.json", "progress_snapshot.json", "IMPLEMENTATION_PLAN.md",
]
def exercise(case, filename, mutate, expected):
with tempfile.TemporaryDirectory(prefix="thetree-progress-guard-") as directory:
stage = Path(directory) / "docs/plans/original-completion-2026-10-02"
stage.mkdir(parents=True)
for name in INPUTS:
shutil.copyfile(PLAN / name, stage / name)
decisions = json.loads((PLAN / "decisions.json").read_text())
for decision in decisions["confirmed"]:
if "reference" in decision:
destination = stage / decision["reference"]
destination.parent.mkdir(parents=True, exist_ok=True)
shutil.copyfile(PLAN / decision["reference"], destination)
data = json.loads((stage / filename).read_text())
mutate(data)
(stage / filename).write_text(json.dumps(data, ensure_ascii=False, indent=2) + "\n")
spec = importlib.util.spec_from_file_location("isolated_plan_validation", PLAN / "validate_plan.py")
validator = importlib.util.module_from_spec(spec)
spec.loader.exec_module(validator)
validator.PLAN = stage
validator.ROOT = ROOT
exit_code = 0
with redirect_stdout(io.StringIO()):
try:
validator.main()
except SystemExit as exc:
exit_code = exc.code
result = json.loads((stage / "plan_validation.json").read_text())
expected_result = (exit_code == 1 and expected in result["failed_checks"]) if expected else (exit_code == 0 and not result["failed_checks"])
return {"case": case, "exit_code": exit_code, "expected_guard": expected,
"expected_result": expected_result,
"failed_checks": result["failed_checks"]}
def main():
rows = [
exercise("unmodified_control", "progress_contract.json", lambda data: None, None),
exercise("unresolved_final_percentage", "progress_contract.json",
lambda data: data.update(total_game_acceptance_percent=1.0),
"unresolved_final_denominator_not_reported_as_total"),
exercise("stale_static_index_register", "current_evidence_links.json",
lambda data: data.update(atomic_register_sha256="0" * 64),
"evidence_index_register_pin_matches"),
exercise("unreviewed_atom_promoted_to_pass", "atomic_requirements.json",
lambda data: data["requirements"][0]["view_results"]["runtime"].update(state="pass"),
"unreviewed_atomic_views_remain_unverified"),
exercise("P03_whole_package_completed", "work_packages.json",
lambda data: next(row for row in data if row["id"] == "P03").update(state="completed"),
"P01_P03_not_whole_package_completed"),
]
report = {"scope": "plan-validator negative guards; isolated document copies, no game execution",
"checked_at_jst": datetime.now(ZoneInfo("Asia/Tokyo")).isoformat(),
"passed": all(row["expected_result"] for row in rows), "rows": rows,
"production_game_source_edits": 0, "new_engine_runs": 0}
(PLAN / "progress_validator_guard_checks.json").write_text(json.dumps(report, ensure_ascii=False, indent=2) + "\n")
print(json.dumps(report, ensure_ascii=False))
if not report["passed"]:
raise SystemExit(1)
if __name__ == "__main__":
main()
@@ -0,0 +1,116 @@
"""Reproduce preservation defects, then verify an isolated SaveService fix."""
import hashlib
import importlib.util
import json
import os
from pathlib import Path
import re
import shutil
import subprocess
import time
import uuid
ROOT = Path(__file__).resolve().parents[4]
OUT = ROOT / "artifacts/original-completion-2026-10-02/p03-save-preservation-r02"
PACKET = ROOT / "artifacts/original-completion-2026-10-02/p03-recovery-readonly-candidate"
TARGET = "scripts/core/save_service.gd"
def sha(path):
return hashlib.sha256(path.read_bytes()).hexdigest()
def write(path, value):
path.write_text(json.dumps(value, ensure_ascii=False, indent=2) + "\n")
def main():
OUT.mkdir(parents=True, exist_ok=False)
spec = importlib.util.spec_from_file_location("source_regression", Path(__file__).with_name("run_current_regression.py"))
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
source = module.source_map()
assert sha(ROOT / TARGET) == sha(PACKET / "save_service.base.gd")
write(OUT / "source-start.json", source)
run_id = uuid.uuid4().hex[:12]
stages = Path("/private/tmp") / ("thetree-save-preservation-" + run_id)
driver_sha = sha(PACKET / "test_recovery_readonly_candidate.gd")
report = {"scope": "identified foreign format preservation and explicit read-only recovery", "stages": {}, "rows": [], "production_applied": False, "driver_sha256": driver_sha}
for variant in ("base", "candidate"):
stage = stages / variant
stage.mkdir(parents=True)
for name, expected in source.items():
dest = stage / name
dest.parent.mkdir(parents=True, exist_ok=True)
shutil.copyfile(ROOT / name, dest)
assert sha(dest) == expected
profile = "TheTreeSavePreservation-" + run_id + "-" + variant
config = (stage / "project.godot").read_text()
(stage / "project.godot").write_text(config.replace("[application]", '[application]\nconfig/use_custom_user_dir=true\nconfig/custom_user_dir_name="' + profile + '"', 1))
qa = stage / "tests/diagnostic/save_preservation"
qa.mkdir(parents=True)
shutil.copyfile(PACKET / "test_recovery_readonly_candidate.gd", qa / "acceptance.gd")
assert sha(qa / "acceptance.gd") == driver_sha
if variant == "candidate":
shutil.copyfile(PACKET / "save_service.candidate.gd", stage / TARGET)
report["stages"][variant] = {"path": str(stage), "profile": profile, "target_sha256": sha(stage / TARGET)}
write(OUT / "execution.json", report)
def run(variant, label, script=None, reproduction=False):
stage = Path(report["stages"][variant]["path"])
command = ["godot", "--headless", "--path", str(stage)]
command += ["--script", "res://" + script] if script else ["--editor", "--import"]
log = OUT / (label + ".log")
started = time.monotonic()
with log.open("w") as stream:
try:
code = subprocess.run(command, cwd=stage, env=dict(os.environ), stdout=stream, stderr=subprocess.STDOUT, timeout=900).returncode
except subprocess.TimeoutExpired:
code = 124
content = log.read_text()
counts = re.findall(r"^Recovery read-only candidate: (\d+) checks, (\d+) failures$", content, re.MULTILINE)
actual_checks = int(counts[0][0]) if len(counts) == 1 else None
if script and not reproduction and actual_checks is None:
old_report = json.loads((ROOT / "artifacts/facility-need-pricing-r02-full155-independent-review-2026-10-01-r01/actual155-source-marker-review.json").read_text())
old_markers = {row["test"]: row["actual_marker"] for row in old_report["rows"]}
marker = old_markers.get(script)
if marker is None:
matches = re.findall(r"^.*?: \d+ checks, 0 failures\n", content, re.MULTILINE)
marker = matches[0] if len(matches) == 1 else None
assert marker is not None and content.count(marker) == 1, label
match = re.search(r"checks=(\d+)|(\d+)(?: [A-Za-z]+)* checks", marker)
assert match is not None
actual_checks = int(next(g for g in match.groups() if g is not None))
failures = int(counts[0][1]) if len(counts) == 1 else None
if reproduction:
passed = code != 0 and failures is not None and failures > 0 and "SCRIPT ERROR:" not in content
else:
passed = code == 0 and "SCRIPT ERROR:" not in content and "\nERROR:" not in content and "Unicode parsing error" not in content
row = {"variant": variant, "label": label, "exit_code": code, "passed": passed,
"expected_defect_reproduction": reproduction, "checks": actual_checks,
"failures": failures, "seconds": round(time.monotonic() - started, 3), "log": log.name, "log_sha256": sha(log)}
report["rows"].append(row)
write(OUT / "execution.json", report)
print(json.dumps(row), flush=True)
assert passed, label
run("base", "base-import")
run("candidate", "candidate-import")
run("base", "base-defects", "tests/diagnostic/save_preservation/acceptance.gd", True)
run("candidate", "candidate-acceptance", "tests/diagnostic/save_preservation/acceptance.gd")
for script in ("tests/s6/test_save_preflight.gd", "tests/s6/test_save_operations.gd", "tests/s6/test_runtime_save_lifecycle.gd", "tests/run_tests.gd", "tests/transport/test_transport_save.gd", "tests/ui/test_dimension_migration_ui.gd", "tests/ui/test_supply_management.gd"):
if not (Path(report["stages"]["candidate"]["path"]) / script).is_file():
# Resolve only exact repository test filenames, never silently skip.
raise AssertionError("missing required suite " + script)
run("candidate", script.replace("/", "__").replace(".gd", ""), script)
after = module.source_map()
changes = [p for p in sorted(set(source) | set(after)) if source.get(p) != after.get(p)]
write(OUT / "source-end.json", after)
report.update(focused_acceptance_passed=True, source_changes=changes, full_merged_regression_pending=True, original_full_acceptance=False)
write(OUT / "execution.json", report)
assert not changes
print("Save preservation focused acceptance passed; production merge and full regression remain pending.")
if __name__ == "__main__":
main()
@@ -0,0 +1,143 @@
"""Accept the retained one-file transit guard against the 1396 source baseline.
Only disposable stages are changed. Whole-state/event oracle comparisons and
transport regressions are new runs; full regression follows the merged changes.
"""
from datetime import datetime
import argparse
import hashlib
import json
import os
from pathlib import Path
import shutil
import subprocess
import time
import uuid
from zoneinfo import ZoneInfo
ROOT = Path(__file__).resolve().parents[4]
OUT = ROOT / "artifacts/original-completion-2026-10-02/p03-transit-guard"
PACKET = ROOT / "artifacts/path-transit-snapshot-partial-success-guard-candidate-2026-10-01"
PATH_TARGET = "scripts/world/path_service.gd"
def sha(path):
return hashlib.sha256(path.read_bytes()).hexdigest()
def write(path, data):
path.write_text(json.dumps(data, ensure_ascii=False, indent=2) + "\n")
def main():
global OUT
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--output", type=Path, default=OUT)
args = parser.parse_args()
OUT = args.output.resolve()
OUT.mkdir(parents=True, exist_ok=False)
baseline_map = json.loads((ROOT / "artifacts/facility-need-pricing-production-scale-adoption-2026-10-01-r01/after.json").read_text())
pins = json.loads((PACKET / "source-pins.json").read_text())
assert baseline_map[PATH_TARGET] == pins["target_base"][PATH_TARGET]
assert sha(PACKET / "candidate" / PATH_TARGET) == pins["target_candidate"][PATH_TARGET]
assert sha(ROOT / "scripts/world/facility_infrastructure_projector.gd") == pins["unchanged_projector_sha256"]
run_id = uuid.uuid4().hex[:12]
stage_root = Path("/private/tmp") / ("thetree-original-guard-" + run_id)
stage_root.mkdir()
assert shutil.disk_usage(stage_root).free > 3 * 1024**3
info = {"source_head": subprocess.check_output(["git", "rev-parse", "HEAD"], cwd=ROOT, text=True).strip(),
"started_at_jst": datetime.now(ZoneInfo("Asia/Tokyo")).isoformat(),
"baseline_files": len(baseline_map), "stages": {}, "rows": [], "production_applied": False}
write(OUT / "source-baseline.json", baseline_map)
for variant in ("reference", "candidate"):
stage = stage_root / variant
stage.mkdir()
for name, expected in baseline_map.items():
source = ROOT / name
destination = stage / name
destination.parent.mkdir(parents=True, exist_ok=True)
if source.is_file() and sha(source) == expected:
shutil.copyfile(source, destination)
else:
# A parallel save fix may already change production; recover
# only the exact committed baseline, never mix generations.
payload = subprocess.check_output(["git", "show", "HEAD:" + name], cwd=ROOT)
assert hashlib.sha256(payload).hexdigest() == expected, name
destination.write_bytes(payload)
profile_name = "TheTreeGoalGuard-" + run_id + "-" + variant
profile = Path.home() / "Library/Application Support" / profile_name
project = stage / "project.godot"
config = project.read_text()
project.write_text(config.replace("[application]", '[application]\nconfig/use_custom_user_dir=true\nconfig/custom_user_dir_name="' + profile_name + '"', 1))
qa = stage / "tests/diagnostic/transit_snapshot_guard"
qa.mkdir(parents=True)
for name in ("frozen_full_snapshot_path.gd", "transit_snapshot_guard_boundary.gd"):
shutil.copyfile(PACKET / "qa" / name, qa / name)
shutil.copyfile(ROOT / "artifacts/path-snapshot-lazy-default-storage-budget-prep-2026-09-30/drivers/profile_current_whole.gd", qa / "whole.gd")
if variant == "candidate":
shutil.copyfile(PACKET / "candidate" / PATH_TARGET, stage / PATH_TARGET)
info["stages"][variant] = {"path": str(stage), "profile": str(profile), "path_sha256": sha(stage / PATH_TARGET)}
write(OUT / "execution.json", info)
def run(variant, label, script=None, extra=None):
stage = Path(info["stages"][variant]["path"])
env = dict(os.environ)
env.update(THE_TREE_TRANSIT_SNAPSHOT_GUARD_STAGE=str(stage),
THE_TREE_TRANSIT_SNAPSHOT_GUARD_PROFILE=info["stages"][variant]["profile"])
if extra:
env.update(extra)
command = ["godot", "--headless", "--path", str(stage)]
command += ["--script", "res://" + script] if script else ["--editor", "--import"]
start = time.monotonic()
log = OUT / (label + ".log")
with log.open("w") as stream:
try:
code = subprocess.run(command, cwd=stage, env=env, stdout=stream,
stderr=subprocess.STDOUT, timeout=1200).returncode
except subprocess.TimeoutExpired:
code = 124
content = log.read_text()
unicode_lines = [line for line in content.splitlines() if "Unicode parsing error" in line]
passed = code == 0 and "Godot Engine v4.7.2" in content and not any(t in content for t in ("SCRIPT ERROR:", "\nERROR:"))
# The historical importer emits two known NUL diagnostics. Retain and
# expose them, while requiring clean script execution for this fix.
if script and unicode_lines:
passed = False
row = {"variant": variant, "label": label, "script": script, "exit_code": code,
"seconds": round(time.monotonic() - start, 3), "passed": passed,
"unicode_diagnostics": unicode_lines, "diagnostics_clear": not unicode_lines,
"log": log.name, "log_sha256": sha(log)}
info["rows"].append(row)
write(OUT / "execution.json", info)
print(json.dumps(row), flush=True)
assert passed, label
return content
run("reference", "reference-import")
run("candidate", "candidate-import")
boundary = run("candidate", "boundary", "tests/diagnostic/transit_snapshot_guard/transit_snapshot_guard_boundary.gd")
assert "failures=0" in boundary and boundary.count("TRANSIT_SNAPSHOT_GUARD checks=") == 1
oracle = str(stage_root / "whole-oracle.var")
for variant, mode in (("reference", "oracle"), ("candidate", "check")):
report = OUT / (variant + "-whole.json")
run(variant, variant + "-whole", "tests/diagnostic/transit_snapshot_guard/whole.gd",
{"THE_TREE_WHOLE_MODE": mode, "THE_TREE_WHOLE_REPORT": str(report),
"THE_TREE_WHOLE_ORACLE": oracle, "THE_TREE_PROFILE_VARIANT": variant,
"THE_TREE_PROFILE_SOURCE_SHA": hashlib.sha256(json.dumps(baseline_map, sort_keys=True).encode()).hexdigest()})
data = json.loads(report.read_text())
assert data["failures"] == 0 and data["checked_ticks_including_midpoint_replay"] == 1200
assert data["uncompared_delivered_event_count"] == 0
for test in ("tests/s1/test_path_service.gd", "tests/s1/test_path_congestion.gd",
"tests/transport/test_transport_save.gd", "tests/s1/test_runtime_infrastructure_integration.gd",
"tests/s6/test_runtime_save_lifecycle.gd"):
run("candidate", test.replace("/", "__"), test)
info.update(finished_at_jst=datetime.now(ZoneInfo("Asia/Tokyo")).isoformat(),
focused_acceptance_passed=True, full_merged_regression_pending=True,
original_full_acceptance=False, performance_acceptance=False,
unresolved_import_diagnostics=any(not r["diagnostics_clear"] for r in info["rows"]))
write(OUT / "execution.json", info)
print("Transit guard focused acceptance passed; merged full regression remains required.")
if __name__ == "__main__":
main()
File diff suppressed because it is too large Load Diff