diff --git a/docs/plans/original-completion-2026-10-02/execution/p04-01/CHECKER_PROTOCOL.md b/docs/plans/original-completion-2026-10-02/execution/p04-01/CHECKER_PROTOCOL.md new file mode 100644 index 0000000..c0e025b --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p04-01/CHECKER_PROTOCOL.md @@ -0,0 +1,20 @@ +# 初期監査の検証器 + +`python3 tools/check_p04_order_evidence.py --verify-only` は環境変数 `BUILD_OUTPUT_DIR` の `p04-evidence/index.json` を読み、書込み・試験・Runner操作をしない。欠落時は非0。原30/88の受入・完了を確定しない。 + +このdispatchではD05が未承認であるため、検証器は常に非0で終了する。indexのapproved/pass宣言で解除できない。これは初期監査の制限であり、全条件を機械的に検証できる完成版gateではない。承認済み原規約と生証跡が供給された後、別契約でsemantic coverageとnative provenanceの検証を追加する必要がある。 + +内部JSON形式は `P04_ORDER_EVIDENCE_PROTOCOL.json` を基に次の有限サブセットを実装した。重複JSONキー、NaN/Infinity、絶対・親参照・symlink・重複artifact pathを拒否する。全ハッシュは生バイトSHA256。indexに合格booleanや試験数があっても判定には使用しない。 + +- `schema_version: 1`, `task_id: P04-01`, checkout HEADと一致する `candidate_commit`, `formal_acceptance: false`。 +- `source_map`: repository相対パス→SHA256。specの6不変pinと旧map内autoload/scriptsの全GDScript依存を必須とする。追加sourceも実ファイルと照合する。 +- `environment`: 非空 `os` と `engine`, `configuration`, `inputs` の証拠ディレクトリ相対パス→SHA256 map。engineは実行バイナリのコピー。OSの自己申告だけではnative証明にならない。 +- `artifacts`: ID→`path`, `bytes`(整数), `sha256`, `type`。typeは observation/state/receipt/stdout/native_log/save/authority のいずれか。 +- `authority`: ref→`status`(original/approved), `artifact_id`。raw文書の存在を確認するが内容の原規約適合は独立レビューを要する。pendingは失敗。 +- `domains`: 正確な7領域名→`source_refs`, `authority_refs`, `cases`, `invariants`, `applicability`。source_refは `path/function/sha256`。applicabilityはindexと同じ `source_map/environment`。 +- 各caseは一意な `id` とartifact IDの `input/before/operation/after/receipt`。receipt JSONは正整数 `start_pid`、同じ `end_pid`、整数 `exit_code: 0`、`engine_ended: true`、一致する `source_map/environment`、raw `stdout/native_log` artifact IDを要求する。自己申告receiptとrawログの意味的結合、別PID保存member一致は未対応であり合格扱いしない。 +- 各invariantは `artifact_id/json_pointer/operator/authority_ref/raw_origin`。raw_originはengineのみ。root derivationはformula検証未対応のため拒否する。RFC6901 pointerでraw JSONから値を読む。eqはexpectedとの型を含むliteral一致、nonnegativeはboolean以外の数値が0以上、count_eqは配列/辞書長と整数expectedの一致。same_literal/distinctは `paired_artifact_id/paired_json_pointer` の値との型を含む比較。未知operatorは失敗。 + +期待値の承認根拠、停止中帳簿不変、決算再送/再開一回、予約とlive targetの対応、payment identity重複なし、必須case coverageを構造チェックだけで証明しない。最後にD05とsemantic/native証明の不足を明示して失敗させる。 + +Runner向け最小確認: index欠落、重複キー、symlink/traversal、hash/size不一致、stale source、未実行receipt、未知predicate、pending authority、7領域欠落が非0になること。その後、D05が未承認の完全形indexでも非0であること。正式境界試験は監査の有限計画に沿い、不適用の旧証拠だけを置き換える。workerはこれらを実行していない。 diff --git a/docs/plans/original-completion-2026-10-02/execution/p04-01/ORDER_AUDIT.md b/docs/plans/original-completion-2026-10-02/execution/p04-01/ORDER_AUDIT.md new file mode 100644 index 0000000..9aceedf --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p04-01/ORDER_AUDIT.md @@ -0,0 +1,38 @@ +# P04-01 監査状態 + +原単位は未完了。D05の閉店後開始済サービスと18:00最終勤務区間は未承認であり、現実装の観測を承認済み規約に置き換えない。A01の00:00保有時間按分維持費は承認済み。 + +正式試験はRunnerが実行する。旧証跡参照は来歴であり、現版の生証跡・ソース・設定・入力・環境の適用性確認なしに合格として再利用しない。 + +## 現行ソースの観測 + +`scripts/core/simulation_kernel.gd:123-153` の順序は APPLY_COMMANDS → 時計増分・日境界signal → TIME_BOUNDARIES → MANA → CONSTRUCTION → LOGISTICS → FACILITY_COMPLETION → VITALS_AND_ENVIRONMENT → INCIDENTS_AND_EVENTS → FACILITY_QUEUES → AI_DECISIONS → PUBLISH_SNAPSHOT。同phase内はhandler IDの辞書順(242行)。Runtimeの登録は364-427行。時計や製品ロジックは変更していない。 + +| 領域 | 現行呼出しと先後 | 原本・承認・不足 | +| --- | --- | --- | +| 閉店 | `_advance_facilities` の後、`_advance_guest_queues` が `_release_closed_business_queues` を実行し、patienceより先に予約解放を試みる。 | 閉店後開始済サービスはD05保留。旧business試験は部分候補。open serviceの00:00証拠を代用しない。 | +| 停電 | `_advance_mana` → `mana_power_projection.apply` → FacilityService `_prepare_service_for_tick`。NO_POWERはpause、復電はresume。 | 草案の961停止/962復電/963不変は生証跡未確認。進捗・予約・帳簿・通知を現版で確認する必要がある。 | +| 破壊 | commandはAPPLY_COMMANDSで先行。`_advance_defense` は完了後のINCIDENTS。BROKENはサービス準備時に失敗。 | 先行破壊44と後段完了45を区別。失敗診断も保持し、原本適合と断定しない。 | +| 退出 | 公開queue leave → 完了 → INCIDENTS → queue patience解放 → AI再計画/予定退出。LEAVINGのdespawnは入状態分より後。 | 公開leave・自動patience・overdue退出の正式保存/別PID証跡は参照のみ。孤立0を現版で証明する必要がある。 | +| 課金 | `_complete_service` callback → `_complete_service_transaction` → `_apply_service_transaction`。予約消費後、service IDによるpayment keyで記帳し、通知scopeを終了。 | 原価格・時間を変えない。静的なidempotency keyの存在や試験数だけで二重課金・二重生成なしとしない。 | +| シフト交代 | 完了後の `_advance_staff_ai` 内でstaff更新・commute・staffing投影。 | 原本64/67行の18:00交代を保持。最終区間の解釈はD05保留。1080診断を承認規約に格上げしない。 | +| 00:00決算 | TIME_BOUNDARIESのweather/upkeep/operationsが完了より先。OperationsCoordinatorのdaily closeと同分service売上は別区間。 | 原本71/72行、承認済A01を保持。1440一回/1441不変の生証跡と適用性が必要。給与0fixtureを非ゼロ給与証拠に数えない。 | + +## 再利用の制限 + +詳細ハッシュ・7領域の不足は `order-audit.json` に記録した。ローカル旧mapはSHA256 `df8328ea8b6a7bc400caad8a52f6ead710c01942a726e5a6b530b82411c55da5`、1299件、欠落0件。主要6ソースの指定pinは一致。旧mapとの差は14件で、契約記載のRuntime/main/preview/performance/path/2試験の7件に加え、Kenney同梱サンプル/URL7件がバイト不一致だった。追加7件は後述のRunner支援入力で分類し、素材を編集していない。 + +修正入力で旧Runtimeのローカルrawコピーを受領し、SHA256 `2d7e2cea5424585e9aa4302ab66d1fc4dbaefe743ce4328fccc1efa2f19b82e4` を確認した。`git diff --no-index` による現Runtimeとの差分は4箇所で、客候補経路batch、施設入口の経路費用比較、客/スタッフの移動時間推定、connector credit helper抽出に関わる。Runtime内のphase登録・施設完了順序はこの差分では変わらないが、変更されたPathServiceと到達性・選択・到着・勤務見積りへの影響を個別確認する必要がある。追加7素材差分はRunner supportがCRLF→LFのみと報告し、現raw hashを照合した。旧raw素材は未供給のため正規化一致を独立再現したとは扱わない。 + +ローカル入力は旧summary/map/draftであり、生の保存package・stdout・engineログ・開始終了記録・設定・入力・環境証拠は提供されていない。外部worktreeのartifactパスは来歴に留め、読んでいない。正式保存8境界27状態、fresh Reader A/B、P04-02/fullの成功記載は未検証参照で、P04-01受入を意味しない。 + +## 提出状態と有限検証計画 + +修正入力は内部index形式の設計を許可した。`tools/check_p04_order_evidence.py` と `CHECKER_PROTOCOL.md` を作成した。構造・pin・artifact hash・receipt項目・有限JSON比較を検証するが、native provenance、全必須境界coverage、原規約への意味的適合は未対応であり、このdispatchのD05未承認とともに必ず非0になる。初期監査をsubmittedとして提出し、machine gate利用可能・原成果完了とは扱わない。 + +1. RunnerがCHECKER_PROTOCOL.mdの負ケースでfailclosed動作を正式確認する。workerは試験未実行。 +2. 生証跡・設定・入力・環境が揃う有限証拠だけ再利用する。Runtime/PathService変更に影響される到達性・勤務・退出境界を確認する。 +3. D05承認後に閉店/18:00の依存境界だけ補完し、停止復電・先行後段破壊・公開/自動退出・00:00・再送/復元の不足分を絞る。A01を再確認しない。 +4. semantic/native検証の不足を別契約で解消し、Runnerがp04-acceptanceと全条件の独立レビュー・統合を実施する。native Windows限定条件が必要なら個別保留とする。 + +試験・Runner操作・Git書込み・他エージェント起動は行っていない。原30パッケージ/88成果の既存1単位内の準備であり、成果追加0、正式完了0。 diff --git a/docs/plans/original-completion-2026-10-02/execution/p04-01/P04_ORDER_EVIDENCE_PROTOCOL.json b/docs/plans/original-completion-2026-10-02/execution/p04-01/P04_ORDER_EVIDENCE_PROTOCOL.json new file mode 100644 index 0000000..85b84d9 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p04-01/P04_ORDER_EVIDENCE_PROTOCOL.json @@ -0,0 +1,65 @@ +{ + "schema_version": 1, + "scope": "Internal evidence-format design within P04-01 checker work, not a new game rule or acceptance waiver. Missing or unsupported semantic proof must fail.", + "input_path": "BUILD_OUTPUT_DIR/p04-evidence/index.json", + "required_index_fields": { + "schema_version": 1, + "task_id": "P04-01", + "candidate_commit": "exact candidate Git SHA", + "source_map": "repository-relative file to raw SHA256; all observed runtime/kernel/affected service sources required", + "environment": "engine path/hash, OS, configuration and inputs raw pins", + "artifacts": "unique artifact id to build-relative path/bytes/sha256/type; resolve safely within evidence dir; reject missing, duplicate, symlink, traversal", + "domains": "exact7 required domain objects", + "authority": "original file raw pin + applicable approved decision refs; pending mandatory rules are errors", + "review_status": "pending_review or approved; pending review may pass mechanical stage only if every original evidence predicate passed", + "formal_acceptance": false + }, + "required_domains": [ + "閉店", + "停電", + "破壊", + "退出", + "課金", + "シフト交代", + "00:00決算" + ], + "domain_fields": { + "source_refs": "actual current functions/phase order source pins", + "authority_refs": "original/approved refs; implementation observations alone do not authorize a missing rule", + "cases": "finite scenario IDs and artifact IDs binding input, before state, delivered operation/clock boundary, after state, producer/consumer PID and unchanged raw save package where applicable", + "invariants": "supported predicate descriptors on actual raw JSON observation/state data; not boolean pass claims or test counts", + "applicability": "exact source/config/input/environment bindings; old mismatch cannot auto-pass" + }, + "native_receipt_predicates": [ + "actual owned PID>0; start/end PID identical; exit0 and engine_ended; receipt bound to pinned rawstdout/native logs", + "source pins in observation and phase receipt match index and checkout; config/input pins are verified", + "where cross-process evidence is claimed, PIDs differ and exact formal save members match producer and consumer pins" + ], + "invariant_predicate_format": { + "artifact_id": "existing pinned raw observation or state artifact", + "json_pointer": "RFC6901 JSON pointer into artifact JSON", + "operator": "one of eq, nonnegative, distinct, same_literal, count_eq; reject unknown", + "expected": "only applicable original/approved rule values or independently computed actual state relationships, never unapproved numeric policy", + "paired_artifact_id": "when comparing before/after or restart, required paired pinned raw artifact", + "paired_json_pointer": "comparison source if needed", + "authority_ref": "original/approved authority for this condition", + "raw_origin": "actual engine-produced source or explicit root derivation with each raw input hash and documented formula; unsupported derivation rejected" + }, + "original_invariant_mapping": [ + "停止が有効な区間のactual service/payment/accounting before-after差が許可されない売上を含まない。停止が未確定D05ならfail。", + "同じ00:00境界の精算receiptが1回、同境界再送と再開で資金/台帳が不変。A01時点は承認済み。", + "閉店/破壊/退出でlive reservationsとactive targetの対応が一致し、除去/復元後の孤立が0。", + "課金の再送/再開で同じservice/payment identityが重複反映されない。", + "閉店後serviceとシフト最終区間等の未承認解釈を実装観測だけでpassしない。" + ], + "fail_closed": [ + "missing index or mandatory fields", + "duplicate keys/IDs, invalid field types or paths", + "unknown predicate or unsupported proof source", + "raw file hash/size, source/config/input/environment mismatch", + "mandatory D05 rule pending or authority missing", + "unexecuted proof, incomplete7domain or required boundary coverage", + "selfreported pass/test count as substitute for actual state invariants" + ], + "implementation_note": "Implement this finite mechanical protocol and document exact supported predicates. If evidence is absent, output actual missing IDs and exit nonzero. No requirement to create fake pass evidence. Do not change source/Clock/game numbers; no engine/test run by worker." +} diff --git a/docs/plans/original-completion-2026-10-02/execution/p04-01/P04_ORDER_REPAIR_INPUT.md b/docs/plans/original-completion-2026-10-02/execution/p04-01/P04_ORDER_REPAIR_INPUT.md new file mode 100644 index 0000000..ff91bfa --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p04-01/P04_ORDER_REPAIR_INPUT.md @@ -0,0 +1,23 @@ +# Runner実行担当からの第1修正入力 + +これは原ゲーム仕様の変更ではありません。旧Runtimeと差分診断を追加試験入力として供給します。既存監査を再実装せず、技術的な証拠index形式とfailclosed checkerを作成してください。原7領域とD05 pendingを維持します。原条件の証拠欠損は検証失敗です。rootは検証器のsourceを変更していません。 + +読取専用入力(Runner allocation.build_dir内): +- /Users/korizatou114/Projects/TheTree-managed-worktrees/p04-01/.runtime/P04-01/build/audit-support/support.json +- /Users/korizatou114/Projects/TheTree-managed-worktrees/p04-01/.runtime/P04-01/build/audit-support/historical-runtime.txt + +旧Runtime SHA256: 2d7e2cea5424585e9aa4302ab66d1fc4dbaefe743ce4328fccc1efa2f19b82e4。入力を検証してからdiffしてください。 + +内部indexの形式設計はspecの検証器作成指示に含まれる技術判断であり、原ゲーム規則の補完ではありません。欠損/古いソース/不正hash/未実行/未定義必須規則は必ず非0にしてください。全証拠が揃わないまま元成果を完了扱いにしないでください。エンジン・全回帰・製品source編集は0。 + +実際のClaude commanderの記録済み判断: + +{ + "action": "request-repair", + "task_id": "P04-01", + "reason": "初回Codex blockedの原因は、検証器tools/check_p04_order_evidence.pyが未作成だったこと(missing gate schemaで仕様補完を避けて停止)。これは内部証拠formatの実装判断で、原ゲーム仕様の不足ではない。既存specの検証器作成指示が、元要件を守るfailclosed形式の設計を許可している。repairs=0で、第1repairは残2/2以内。入力は再起動に十分: input.json等のlocal copy、current source pins、14差分(production7とmanaged14を区別、追加7はroot対managedでCRLF→LFのみbyte検証済み、rawSHA差は隠さない)、正確な旧Runtime(SHA 2d7e2cea完全一致)をbuild_dir/audit-support/historical-runtime.txtへraw保存済み。support.jsonとこのtxtを読取専用の追加試験入力として使う(Git変更scopeなし)。repair範囲: (1) 既存のorder-audit.jsonとORDER_AUDIT.mdは保持し、重複作成しない。必要なら最小の追記・訂正のみ。(2) --verify-onlyのcheckerを作成する。BUILD_OUTPUT_DIR/p04-evidence/index.jsonを必須とし、7領域、不変のsource pin、raw proof hash、適用性を検証する。欠損、D05 pending、stale source、未実行proof、自己申告pass、test count単独のpassは非0で終了する。raw証拠が全て不足していてもcheckerは作成する。生証拠を作ったことにはしない。D05は未承認のまま、その不足がある受入をpassにしない。(3) 全回帰・engine実行、ゲームsource変更、Clock・値の変更は0。原7領域/元30/88/部分点なしの受入分母は維持し、仕様変更・分母変更・予算拡大・main統合は含めない。allowed_pathsは検証器と実行ディレクトリ配下に限る。" +} + +追加技術入力: 同じaudit-support内のruntime-diff.patchは旧SHA確認済みRuntimeと現Runtimeのdiff -u出力です。原ソース2件と突合して利用できます。 + +前回shellのhere-documentは/tmp作成制限で失敗しています。sandbox/権限を変更せず、既存のpython -c等の一時ファイル不要の方式、または許可scopeへのapply_patchを使ってください。前回未読だったこの文書とP04_ORDER_EVIDENCE_PROTOCOL.jsonを最初に読んでください。index形式は技術設計であり、未知ゲーム規則の確定ではありません。D05や証拠不足は非0を維持し、検証器と設計書をsubmittedとして提出することは元成果acceptedではありません。 diff --git a/docs/plans/original-completion-2026-10-02/execution/p04-01/ROOT_REPAIR_INPUT.md b/docs/plans/original-completion-2026-10-02/execution/p04-01/ROOT_REPAIR_INPUT.md new file mode 100644 index 0000000..2ddb35d --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p04-01/ROOT_REPAIR_INPUT.md @@ -0,0 +1,19 @@ +# Runner実行担当からの第1修正入力 + +これは原ゲーム仕様の変更ではありません。旧Runtimeと差分診断を追加試験入力として供給します。既存監査を再実装せず、技術的な証拠index形式とfailclosed checkerを作成してください。原7領域とD05 pendingを維持します。原条件の証拠欠損は検証失敗です。rootは検証器のsourceを変更していません。 + +読取専用入力(Runner allocation.build_dir内): +- /Users/korizatou114/Projects/TheTree-managed-worktrees/p04-01/.runtime/P04-01/build/audit-support/support.json +- /Users/korizatou114/Projects/TheTree-managed-worktrees/p04-01/.runtime/P04-01/build/audit-support/historical-runtime.txt + +旧Runtime SHA256: 2d7e2cea5424585e9aa4302ab66d1fc4dbaefe743ce4328fccc1efa2f19b82e4。入力を検証してからdiffしてください。 + +内部indexの形式設計はspecの検証器作成指示に含まれる技術判断であり、原ゲーム規則の補完ではありません。欠損/古いソース/不正hash/未実行/未定義必須規則は必ず非0にしてください。全証拠が揃わないまま元成果を完了扱いにしないでください。エンジン・全回帰・製品source編集は0。 + +実際のClaude commanderの記録済み判断: + +{ + "action": "request-repair", + "task_id": "P04-01", + "reason": "初回Codex blockedの原因は、検証器tools/check_p04_order_evidence.pyが未作成だったこと(missing gate schemaで仕様補完を避けて停止)。これは内部証拠formatの実装判断で、原ゲーム仕様の不足ではない。既存specの検証器作成指示が、元要件を守るfailclosed形式の設計を許可している。repairs=0で、第1repairは残2/2以内。入力は再起動に十分: input.json等のlocal copy、current source pins、14差分(production7とmanaged14を区別、追加7はroot対managedでCRLF→LFのみbyte検証済み、rawSHA差は隠さない)、正確な旧Runtime(SHA 2d7e2cea完全一致)をbuild_dir/audit-support/historical-runtime.txtへraw保存済み。support.jsonとこのtxtを読取専用の追加試験入力として使う(Git変更scopeなし)。repair範囲: (1) 既存のorder-audit.jsonとORDER_AUDIT.mdは保持し、重複作成しない。必要なら最小の追記・訂正のみ。(2) --verify-onlyのcheckerを作成する。BUILD_OUTPUT_DIR/p04-evidence/index.jsonを必須とし、7領域、不変のsource pin、raw proof hash、適用性を検証する。欠損、D05 pending、stale source、未実行proof、自己申告pass、test count単独のpassは非0で終了する。raw証拠が全て不足していてもcheckerは作成する。生証拠を作ったことにはしない。D05は未承認のまま、その不足がある受入をpassにしない。(3) 全回帰・engine実行、ゲームsource変更、Clock・値の変更は0。原7領域/元30/88/部分点なしの受入分母は維持し、仕様変更・分母変更・予算拡大・main統合は含めない。allowed_pathsは検証器と実行ディレクトリ配下に限る。" +} diff --git a/docs/plans/original-completion-2026-10-02/execution/p04-01/dispatch-confirmation.json b/docs/plans/original-completion-2026-10-02/execution/p04-01/dispatch-confirmation.json new file mode 100644 index 0000000..57012a8 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p04-01/dispatch-confirmation.json @@ -0,0 +1,21 @@ +{ + "task_id": "P04-01", + "base_commit": "deb1bcb2374eb378b840ca345db952bd8572cb6e", + "status": "blocked", + "preexisting_files": ["order-audit.json", "ORDER_AUDIT.md"], + "verifier_created": false, + "blockers": [ + "Local inputs specify no evidence index schema, mandatory proof identifiers, raw-proof predicates or authority binding. Implementing an accepting verifier would supplement unspecified requirements.", + "D05 remains pending; approved A01 is retained without reconfirmation.", + "Verified local historical raw proofs and exact old Runtime source are required for reuse and exact diff. Artifact paths are provenance only." + ], + "read_only_observations": [ + "Current kernel lines 123-153 and Runtime registrations 364-427 confirm the phase sequence recorded in the preexisting audit.", + "Git read-only path history lists ten Runtime revisions; this turn has not scanned their content hashes." + ], + "hash_reconfirmation": "Not completed: shell rejected temporary-file creation for the Python here-document before execution. Preexisting hash claims are not new verification results.", + "tests_executed": false, + "original_unit_complete": false, + "counted_units_added": 0, + "next_step": "Supply evidence protocol and verified local historical source/raw proofs; Runner performs formal validation and independent review." +} diff --git a/docs/plans/original-completion-2026-10-02/execution/p04-01/order-audit.json b/docs/plans/original-completion-2026-10-02/execution/p04-01/order-audit.json new file mode 100644 index 0000000..5c8952e --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p04-01/order-audit.json @@ -0,0 +1,244 @@ +{ + "input_hashes": { + "docs/plans/original-completion-2026-10-02/execution/p04-01-input-r01/ORDER_CONTRACT_DRAFT.md": "c4dd8b907321b8859ba0744b9ae3d1447615d98fbe548983f9bb9fcad2d9d989", + "docs/plans/original-completion-2026-10-02/execution/p04-01-input-r01/input.json": "1286f865656aafb6146c7bcd95c92c53c00b6c706f3f690d96e998d5e45e2b79", + "docs/plans/original-completion-2026-10-02/execution/p04-01-input-r01/historical-audit.json": "90d2dbd3c04aed7ab409afa4f05f884832a4661cc506d28b818c72aadc352950", + "docs/plans/original-completion-2026-10-02/execution/p04-01-input-r01/historical-source-map.json": "df8328ea8b6a7bc400caad8a52f6ead710c01942a726e5a6b530b82411c55da5" + }, + "source_pins": { + "autoload/simulation_runtime.gd": { + "expected": "d52a995ae715542bbc550f68d35889540658275d12e04ae0b21ac276f5843f39", + "actual": "d52a995ae715542bbc550f68d35889540658275d12e04ae0b21ac276f5843f39", + "matches": true + }, + "scripts/facility/facility_service.gd": { + "expected": "ceb4a3e9224587423f273cdb2b56e6843ab176ac1fc4fe79dd498b5ed5c33b77", + "actual": "ceb4a3e9224587423f273cdb2b56e6843ab176ac1fc4fe79dd498b5ed5c33b77", + "matches": true + }, + "scripts/economy/economy_service.gd": { + "expected": "95aedd0a0421c93e8fa39f0f76fa890cd0a46905d9a25c88c8b17c4d6d47728e", + "actual": "95aedd0a0421c93e8fa39f0f76fa890cd0a46905d9a25c88c8b17c4d6d47728e", + "matches": true + }, + "scripts/guest/guest_service.gd": { + "expected": "56880410e9a00816f9a95d30821982955532de8dd976980934e12016a9f2b21e", + "actual": "56880410e9a00816f9a95d30821982955532de8dd976980934e12016a9f2b21e", + "matches": true + }, + "scripts/staff/staff_service.gd": { + "expected": "355ad5c3c9f85dc4d4ffc3bc4293e36f81078c403d1662512a735b2c8d815fb3", + "actual": "355ad5c3c9f85dc4d4ffc3bc4293e36f81078c403d1662512a735b2c8d815fb3", + "matches": true + }, + "scripts/mana/mana_network_service.gd": { + "expected": "96f195cf2a28b0966d12cd7c6fab86d13eae97c8342d07d70f52e598fbf49af9", + "actual": "96f195cf2a28b0966d12cd7c6fab86d13eae97c8342d07d70f52e598fbf49af9", + "matches": true + } + }, + "historical_map_entries": 1299, + "differences": [ + { + "path": "assets/kenney/tiny_dungeon/Tiled/sampleMap.tmx", + "old_sha256": "fc545787837e2655c9d2078cc1b167df0d9ea2755f6ec3912c7987e8501339e3", + "current_sha256": "3849e083e3d4f6a71dbf725d8473e93fa6ef8cdc9d314368eee15c980cf41775" + }, + { + "path": "assets/kenney/tiny_dungeon/Tiled/sampleSheet.tsx", + "old_sha256": "02f1b90cfdb37bcccddc83d074954272aaffd297ed4fabce7bb670f2f3f4be71", + "current_sha256": "a2cca2c5e50b14023ce00f5d4112fb0b8264bfff9407d7a5198656e28d67fa16" + }, + { + "path": "assets/kenney/tiny_dungeon/Visit Kenney.url", + "old_sha256": "0dd1a0b295582cd3185547f0c1d92b4d5392c7782b90a428e192944a496052e0", + "current_sha256": "6787defa3ecb6118622e1903b65802c0200628fae5164b51b4fd467f92f3f284" + }, + { + "path": "assets/kenney/tiny_dungeon/Visit Patreon.url", + "old_sha256": "84be5ef26b07905fa7e196e943c9807bf84138c3a71d87f51c6fd57b85c48c34", + "current_sha256": "2fcba31333935f4aa35e9de2e74e2b7ba1b1a8011540e08016ff6d81e9dd7490" + }, + { + "path": "assets/kenney/tiny_town/Tiny Dungeon (base pack).url", + "old_sha256": "6cf442be20ad3364ba87183461744da9e979b5d4f243c83e2404f2cf884500d9", + "current_sha256": "6d93bb958f9b7d5f21ceb8cbd24c184dc5c9f87aee7c680b336ecba7a89823d8" + }, + { + "path": "assets/kenney/tiny_town/Visit Kenney.url", + "old_sha256": "0dd1a0b295582cd3185547f0c1d92b4d5392c7782b90a428e192944a496052e0", + "current_sha256": "6787defa3ecb6118622e1903b65802c0200628fae5164b51b4fd467f92f3f284" + }, + { + "path": "assets/kenney/tiny_town/Visit Patreon.url", + "old_sha256": "84be5ef26b07905fa7e196e943c9807bf84138c3a71d87f51c6fd57b85c48c34", + "current_sha256": "2fcba31333935f4aa35e9de2e74e2b7ba1b1a8011540e08016ff6d81e9dd7490" + }, + { + "path": "autoload/simulation_runtime.gd", + "old_sha256": "2d7e2cea5424585e9aa4302ab66d1fc4dbaefe743ce4328fccc1efa2f19b82e4", + "current_sha256": "d52a995ae715542bbc550f68d35889540658275d12e04ae0b21ac276f5843f39" + }, + { + "path": "scenes/main/main.gd", + "old_sha256": "a7ae44c680eb9b70a117ddc8c6cbf0ca290b8e8d485eac41b4122698fde2a620", + "current_sha256": "a3d7d7ddd08a8df1f987806e60accf51792d728cf71c06e6b822f5a31d8ed3e3" + }, + { + "path": "scenes/main/world_preview.gd", + "old_sha256": "3df29be32d3a016d8fb9dc1ee2bd32e2360ac8fad9810293f6be9b58d26046e0", + "current_sha256": "75d5b0bd23204f5a485540512e44b89e1d2a4596b368f70177a238ba078ff42d" + }, + { + "path": "scripts/core/performance_budget.gd", + "old_sha256": "79d18e8f0dcc3932801cd02ea8a8ba037af02ef57665387cba8dbe3b3e9af917", + "current_sha256": "0e2278f88d29919a0634fc1b527328a0d0c12d87e2cd612f3eee1526aabdb073" + }, + { + "path": "scripts/world/path_service.gd", + "old_sha256": "2e68653e4898387cb5a76402813a10595bd5ca7d5fb841c7ed8c55af77d7a918", + "current_sha256": "447135729a1106639a6eee6754af3195c8a8b458ca26980ae91fa39d80dcfbd4" + }, + { + "path": "tests/s1/test_path_service.gd", + "old_sha256": "0f48bb44c27e32f08477b9aed61a0db5c8808219490928f734c3570a07efb251", + "current_sha256": "17d9fd42b35004376bf96e435f53d6bce41e79258ec7f6daf3ab04ae5d8c3e1d" + }, + { + "path": "tests/ui/test_pixel_tower.gd", + "old_sha256": "93bdbb195f2ceec07dbe052e0d0a3017d84b56f1e8ec46b87be8d98105ec0f88", + "current_sha256": "f149f4b5507247dadf623e777e90b9bdb81f54324b406a8f55adaf89b649866a" + } + ], + "missing_map_paths": [], + "task_id": "P04-01", + "base_commit": "deb1bcb2374eb378b840ca345db952bd8572cb6e", + "status": "blocked", + "original_unit_complete": false, + "counted_units_added": 0, + "tests_executed": false, + "authority": { + "original": "docs/traceability/original/BASELINE.txt:64,67,71,72", + "approved": "A01: ownership-time apportioned upkeep at midnight; retained without reconfirmation", + "pending": "D05: started service after closure, final shift interval at 18:00, unresolved EV/transport stopping/cost/day crossing rules; no invented policy" + }, + "phase_order": "scripts/core/simulation_kernel.gd:123-153: APPLY_COMMANDS, clock increment/calendar boundary signals, TIME_BOUNDARIES, MANA, CONSTRUCTION, LOGISTICS, FACILITY_COMPLETION, VITALS_AND_ENVIRONMENT, INCIDENTS_AND_EVENTS, FACILITY_QUEUES, AI_DECISIONS, PUBLISH_SNAPSHOT. Handler IDs sorted lexically within phase at line242.", + "domains": [ + { + "domain": "閉店", + "current_functions": [ + "simulation_runtime._advance_facilities", + "simulation_runtime._advance_guest_queues", + "simulation_runtime._release_closed_business_queues", + "simulation_runtime._release_closed_business_request" + ], + "order": "Facility completion precedes queue closure release; release occurs before patience spending. Started-service closure semantics remain D05 pending.", + "old_evidence": "Historical phases 001/002: business closure/operations; midnight open-service proof cannot establish closure behavior.", + "missing": "Approved started-service closure rule and exact-version boundary raw proof." + }, + { + "domain": "停電", + "current_functions": [ + "simulation_runtime._advance_mana", + "mana_power_projection.apply", + "FacilityService._prepare_service_for_tick", + "FacilityService._complete_service" + ], + "order": "Commands precede MANA power projection, then facility completion. NO_POWER pauses active service and power recovery resumes it.", + "old_evidence": "Draft reports formal 961 stop/962 recovery, fresh Reader A/B, one consume/notification and unchanged economy at 963; raw not supplied.", + "missing": "Exact-source/config/input/environment raw stop/recovery proofs including same reservations and all ledgers." + }, + { + "domain": "破壊", + "current_functions": [ + "simulation_runtime._process_tick_commands", + "simulation_runtime._advance_defense", + "FacilityService._prepare_service_for_tick", + "FacilityService._fail_service" + ], + "order": "Command destruction precedes facility processing; INCIDENTS_AND_EVENTS destruction follows completion. BROKEN fails during service preparation.", + "old_evidence": "Draft reports early failure44/charge0/release once, late destruction after completion45 and next-minute failure for incomplete service.", + "missing": "Verified raw early/late destruction and failed diagnostic history; current infrastructure/path applicability." + }, + { + "domain": "退出", + "current_functions": [ + "simulation_runtime._execute_leave_facility_queue", + "simulation_runtime._leave_guest_queue_boundary", + "simulation_runtime._advance_guest_queues", + "simulation_runtime._advance_guest_ai_decisions" + ], + "order": "Public leave command precedes completion; patience release occurs in queues; AI replanning/planned exit follows. LEAVING despawns only after state-entered minute.", + "old_evidence": "Draft reports public reservation release, automatic45-minute patience and completion-before-exit boundaries.", + "missing": "Exact-version leave/patience and overdue-LEAVING reload proofs, no orphan reservations and replay generation checks." + }, + { + "domain": "課金", + "current_functions": [ + "FacilityService._complete_service", + "simulation_runtime._complete_service_transaction", + "simulation_runtime._apply_service_transaction", + "EconomyService.post" + ], + "order": "Completion callback consumes reservations then posts service.payment.; notification scope ends after transaction effects. Static code alone does not prove all boundary rollback paths.", + "old_evidence": "P04-02 and historical full are references only; test counts do not establish P04-01 original acceptance.", + "missing": "Raw ledger/inventory/notification proof for stopped, failed, replay and paid completion paths; closure/shift rule dependent proof." + }, + { + "domain": "シフト交代", + "current_functions": [ + "simulation_runtime._advance_facilities", + "simulation_runtime._advance_staff_ai", + "StaffService.advance_one_minute", + "simulation_runtime._sync_facility_staffing" + ], + "order": "Facility completion precedes staff AI, commute and staffing projection. Final18:00 interval design meaning is D05 pending.", + "old_evidence": "Historical phase083 hardening includes shift-end interruption; draft retains diagnostic1080 predicate failure without claiming original violation.", + "missing": "Approved final-interval rule then exact-version1080 boundary including nonzero cost where required." + }, + { + "domain": "00:00決算", + "current_functions": [ + "simulation_runtime._advance_facility_upkeep", + "simulation_runtime._advance_operations_time", + "OperationsCoordinator._process_minute_boundaries", + "OperationsCoordinator._process_daily_close", + "simulation_runtime._complete_service_transaction" + ], + "order": "TIME_BOUNDARIES weather/upkeep/operations precedes facility completion; prior day[0,1440) accounting differs from sale at1440. A01 upkeep already approved.", + "old_evidence": "Draft reports real settlement/payroll/upkeep once, service25 once, unchanged ledgers/history1441; zero payroll fixture is not proof of nonzero payroll.", + "missing": "Current raw midnight/retry/reload idempotency proof and applicable nonzero payroll boundary; full original conformity review." + } + ], + "old_evidence_applicability": { + "raw_available_for_reuse": false, + "assessment": "Only local summaries/maps/draft read; original artifact paths remain provenance. No approved reuse asserted.", + "source": "14 byte differences, zero missing mapped paths; six immutable current pins match.", + "config_input_environment": "Not established by raw local evidence; each required proof must pin these independently.", + "runtime_git": "Verified supplied old SHA2d7e2cea; git diff --no-index compared exact raw old/current Runtime. Four hunks affect _project_guest_candidates batching, _find_facility_access_path cost selection, _estimated_actor_path_minutes and extracted connector-credit helper. Completion/phase registration unchanged in this file; callees PathService changed, therefore reachability, choice, arrival and staff estimates require finite applicability evidence.", + "known_difference_impact": "Runtime/PathService may alter infrastructure, movement, staffing, guest selection and recovery boundary reachability; UI/main/preview and performance budget changes prevent blanket whole-full reuse. Two changed tests cannot supply old exact-version evidence. Seven additional Kenney metadata/sample byte differences require applicability classification, not product edits." + }, + "blockers": [ + "D05 closure service and final shift interval remain unapproved.", + "Raw historical boundary proofs/config/input/environment not supplied; summary pass claims cannot establish original acceptance.", + "Initial checker validates structural/hash predicates but intentionally rejects unsupported semantic coverage/native provenance; passing machine gate unavailable in pending-D05 dispatch." + ], + "validation_plan": [ + "Runner supplies exact-version raw boundary evidence using CHECKER_PROTOCOL.md; no worker engine/test execution.", + "Confirm finite reachability/arrival/staff path impacts for affected Runtime and PathService; retain 14 raw differences and classify 7 metadata-only differences separately.", + "After D05 approval verify only affected closure/18:00 boundaries; retain failed diagnostics and approved A01.", + "Verify applicable stop/recovery, early/late destruction, public/patience/overdue exit, midnight/replay/reload evidence with raw hashes and source/config/input/environment pins; request fresh finite proofs only where reuse fails.", + "Runner executes p04-acceptance and independent all-condition review/integration; native Windows conditions individually pending only if applicable. No engine/all-regression run here." + ], + "repair_support": { + "hashes": { + "support.json": "36f7443daabf37070ecc331e708a6749816630bf0466ebb2a814aaf647a84410", + "runtime-diff.patch": "7ba08537c5e86d0505f2b4df56d29877064c70acc4fa9f12089fefa09e78b707", + "historical-runtime.txt": "2d7e2cea5424585e9aa4302ab66d1fc4dbaefe743ce4328fccc1efa2f19b82e4" + }, + "historical_runtime_verified": true, + "production_differences": 7, + "managed_differences": 14, + "additional7_classification": "Runner support reports CRLF to LF only; current raw hashes checked. Old raw metadata absent, normalization not independently reproduced; no acceptance equivalence claim." + } +} diff --git a/tools/check_p04_order_evidence.py b/tools/check_p04_order_evidence.py new file mode 100644 index 0000000..dbfbcce --- /dev/null +++ b/tools/check_p04_order_evidence.py @@ -0,0 +1,183 @@ +#!/usr/bin/env python3 +"""Read-only P04 evidence preflight. Never grants original acceptance. + +This initial-phase verifier deliberately rejects unsupported semantic evidence: +D05 is pending in the dispatch, irrespective of declarations in an index. +See execution/p04-01/CHECKER_PROTOCOL.md for the supported input subset. +""" +import argparse +import hashlib +import json +import os +from pathlib import Path +import re +import subprocess +import sys + +ROOT = Path(__file__).resolve().parents[1] +SPEC = ROOT / 'docs/spec/acceptance/P04-01.json' +SPEC_HASH = '9ec722e7dfb0bee178d291624a026420c08412574e238bba1fde012c7a6f7881' +DOMAINS = {'閉店', '停電', '破壊', '退出', '課金', 'シフト交代', '00:00決算'} + + +def require(condition, message): + if not condition: + raise ValueError(message) + + +def sha(path): + return hashlib.sha256(path.read_bytes()).hexdigest() + + +def unique(pairs): + result = {} + for key, value in pairs: + require(key not in result, 'duplicate JSON key: ' + key) + result[key] = value + return result + + +def load(path): + return json.loads(path.read_text(encoding='utf-8'), object_pairs_hook=unique, + parse_constant=lambda x: require(False, 'nonfinite JSON: ' + x)) + + +def safe(base, relative): + require(isinstance(relative, str) and relative, 'invalid path') + p = Path(relative) + require(not p.is_absolute() and all(x not in {'.', '..'} for x in relative.split('/')), + 'unsafe path: ' + relative) + current = base + for part in p.parts: + current = current / part + require(not current.is_symlink(), 'symlink: ' + relative) + require(current.resolve().is_relative_to(base.resolve()) and current.is_file(), + 'missing/outside file: ' + relative) + return current + + +def pins(mapping, base): + require(isinstance(mapping, dict) and mapping, 'missing pin map') + for name, digest in mapping.items(): + require(isinstance(digest, str) and re.fullmatch('[0-9a-f]{64}', digest), 'invalid hash: ' + name) + require(sha(safe(base, name)) == digest, 'stale pin: ' + name) + + +def pointer(value, path): + require(isinstance(path, str) and (path == '' or path.startswith('/')), 'invalid JSON pointer') + for token in path.split('/')[1:]: + require(not re.search('~(?![01])', token), 'invalid pointer escape') + token = token.replace('~1', '/').replace('~0', '~') + if isinstance(value, list): + require(re.fullmatch('0|[1-9][0-9]*', token) is not None, 'invalid array index') + value = value[int(token)] + else: + require(isinstance(value, dict) and token in value, 'missing pointer: ' + path) + value = value[token] + return value + + +def literal(a, b): + return type(a) is type(b) and json.dumps(a, sort_keys=True) == json.dumps(b, sort_keys=True) + + +def verify(directory): + require(sha(SPEC) == SPEC_HASH, 'dispatch spec pin mismatch') + spec = load(SPEC) + evidence = directory / 'p04-evidence' + require(not evidence.is_symlink(), 'symlink evidence directory') + index = load(safe(evidence, 'index.json')) + require(type(index.get('schema_version')) is int and index['schema_version'] == 1, 'schema_version') + require(index.get('task_id') == 'P04-01' and index.get('formal_acceptance') is False, 'task/acceptance') + head = subprocess.check_output(['git', 'rev-parse', 'HEAD'], cwd=ROOT, text=True).strip() + require(index.get('candidate_commit') == head, 'candidate_commit mismatch') + source = index.get('source_map') + pins(source, ROOT) + for name, digest in spec['current_source_pins'].items(): + require(source.get(name) == digest, 'immutable source pin: ' + name) + oldmap = load(ROOT / 'docs/plans/original-completion-2026-10-02/execution/p04-01-input-r01/historical-source-map.json') + required = {p for p in oldmap if p.endswith('.gd') and p.startswith(('autoload/', 'scripts/'))} + require(required <= source.keys(), 'missing runtime/service dependency source pins') + environment = index.get('environment') + require(isinstance(environment, dict) and isinstance(environment.get('os'), str) and environment['os'], 'environment OS') + for kind in ('engine', 'configuration', 'inputs'): + pins(environment.get(kind), evidence) + artifacts = index.get('artifacts') + require(isinstance(artifacts, dict) and artifacts, 'missing artifacts') + paths, raw = set(), {} + for aid, item in artifacts.items(): + require(isinstance(aid, str) and aid and isinstance(item, dict), 'invalid artifact') + path = safe(evidence, item['path']) + require(path not in paths, 'duplicate artifact path') + paths.add(path) + require(type(item.get('bytes')) is int and item['bytes'] == path.stat().st_size, 'artifact size: ' + aid) + require(sha(path) == item.get('sha256'), 'artifact hash: ' + aid) + require(item.get('type') in {'observation', 'state', 'receipt', 'stdout', 'native_log', 'save', 'authority'}, 'artifact type') + raw[aid] = path + authority = index.get('authority') + require(isinstance(authority, dict) and authority, 'missing authority') + domains = index.get('domains') + require(isinstance(domains, dict) and set(domains) == DOMAINS, 'required seven domains') + for name, domain in domains.items(): + require(isinstance(domain, dict), 'invalid domain: ' + name) + for field in ('source_refs', 'authority_refs', 'cases', 'invariants'): + require(isinstance(domain.get(field), list) and domain[field], name + ': missing ' + field) + require(domain.get('applicability') == {'source_map': source, 'environment': environment}, name + ': applicability mismatch') + for ref in domain['source_refs']: + require(isinstance(ref, dict) and ref.get('path') in source and isinstance(ref.get('function'), str) and ref['function'], 'invalid source ref') + require(ref.get('sha256') == source[ref['path']], 'source ref hash') + for ref in domain['authority_refs']: + require(ref in authority and authority[ref].get('status') in {'original', 'approved'}, 'pending/missing authority') + require(authority[ref].get('artifact_id') in raw, 'missing raw authority') + case_ids = set() + for case in domain['cases']: + require(isinstance(case, dict) and isinstance(case.get('id'), str) and case['id'] not in case_ids, 'duplicate/invalid case') + case_ids.add(case['id']) + for field in ('input', 'before', 'operation', 'after', 'receipt'): + require(case.get(field) in raw, name + ': missing case artifact ' + field) + receipt = load(raw[case['receipt']]) + pid = receipt.get('start_pid') + require(type(pid) is int and pid > 0 and receipt.get('end_pid') == pid and type(receipt.get('exit_code')) is int and receipt['exit_code'] == 0 and receipt.get('engine_ended') is True, 'unexecuted/incomplete receipt') + require(receipt.get('source_map') == source and receipt.get('environment') == environment, 'receipt applicability') + for field in ('stdout', 'native_log'): + require(receipt.get(field) in raw, 'receipt missing raw ' + field) + for pred in domain['invariants']: + require(isinstance(pred, dict) and pred.get('artifact_id') in raw, 'missing predicate artifact') + require(pred.get('authority_ref') in domain['authority_refs'], 'predicate authority') + require(pred.get('raw_origin') == 'engine', 'unsupported derivation/origin') + value = pointer(load(raw[pred['artifact_id']]), pred['json_pointer']) + op = pred.get('operator') + if op in {'same_literal', 'distinct'}: + require(pred.get('paired_artifact_id') in raw, 'missing paired artifact') + other = pointer(load(raw[pred['paired_artifact_id']]), pred['paired_json_pointer']) + result = literal(value, other) if op == 'same_literal' else not literal(value, other) + elif op == 'eq': + result = literal(value, pred['expected']) + elif op == 'nonnegative': + result = type(value) in (int, float) and value >= 0 + elif op == 'count_eq': + result = isinstance(value, (list, dict)) and type(pred.get('expected')) is int and len(value) == pred['expected'] + else: + raise ValueError('unsupported predicate: ' + str(op)) + require(result, name + ': predicate failed') + require(index.get('review_status') in {'pending_review', 'approved'}, 'review status') + # Raw observation claims cannot establish production provenance, mandatory + # scenario coverage or an approval absent from this immutable dispatch. + raise ValueError('D05 pending: closure service / final shift interval; semantic coverage and native provenance require independent raw-evidence review. Machine gate unavailable; original acceptance not granted.') + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--verify-only', action='store_true', required=True) + parser.parse_args() + try: + require(bool(os.environ.get('BUILD_OUTPUT_DIR')), 'BUILD_OUTPUT_DIR required') + verify(Path(os.environ['BUILD_OUTPUT_DIR'])) + except (ValueError, OSError, KeyError, TypeError, IndexError, subprocess.SubprocessError) as exc: + print(json.dumps({'task_id': 'P04-01', 'machine_verified': False, 'formal_acceptance': False, 'error': str(exc)}, ensure_ascii=False)) + return 1 + return 1 + + +if __name__ == '__main__': + sys.exit(main())