Compare commits

...
10 Commits
34 changed files with 3012 additions and 55 deletions
@@ -1,3 +1,7 @@
## 現在の優先対象(2026-10-14 更新)
P08-02は原6条件・独立Opus・登録統合/最終検証・c675bed9のmain統合を満たし正式完了。原30/88・部分点なしを維持し、正式11/着手25/予定52。次は実Opusの訂正済み判断によるP08-03の原受入/source監査。通常UI撤去入口が未実装で、必要UI追加と正常/拒否・pan/zoom・別PID保存再開の証拠が必要。P08-01はplannedのままで全30施設の受入済みとしない。P08全体と同一Windows配布版実機は未完。新規worker・重複回帰はまだ起動していない。以下は過去履歴。
## 現在の優先対象(2026-10-13 更新)
現在はP08-02。候補d1c7ce27のnative全8実行と通常OS4操作の証拠取得済み。最終全174スイート回帰→登録検証→独立Opus→統合後確認の順に1件を閉じる。原30パッケージ/88成果単位・部分点なしを保持し、正式完了件数は増やさない。個別修正/累積推論回数と固定レビュー資料容量の旧上限はユーザー指示で撤廃済み。以下は過去の実行順序の履歴で、現在の停止条件ではない。
@@ -3668,6 +3668,17 @@
"text": "\tprint(\"TOMARI_FLOOR_TROUBLE checks=%d failures=%d\" % [checks,failures])"
}
]
},
{
"test": "tests/s1/test_p08_combined_migration.gd",
"template": "P08 combined migration: <checks> checks, <failures> failures",
"required": true,
"fixed_check_count_used": false,
"source_sha256_at_schema_audit": "9284a8cfb478b4c8d69f6d8166eec6c41107e3902029289b3c0e9ba48c370855",
"authority": {
"path": "docs/spec/acceptance/P08-02.json",
"scope": "new standalone mixed suite; native execution pending"
}
}
],
"unknown_roster_suite_policy": "refuse, explicitly review its source/schema before accepting",
@@ -1,7 +1,7 @@
{
"candidate": "bf559632ddd938085702529d9dd6b7c878f4ebc7",
"original_unit_completed": false,
"next": "actual independent Opus then integration/current applicable final verification",
"original_unit_completed": true,
"next": "P08-03 acceptance and existing evidence audit; no duplicate worker started",
"fixed_material_limit": null,
"file_count_limit": null,
"original_30_88_unchanged": true,
@@ -24,10 +24,12 @@
"registered_final_regression_files_whole_verified": 5612,
"registered_validation": "bf559632 integrity verified, deficits0, original acceptance pending",
"independent_review": {
"state": "running",
"session": 85138,
"state": "passed",
"model": "claude-opus-5-5",
"earlier_review": "changes requested; retained in audit-r07"
"candidate": "bf559632ddd938085702529d9dd6b7c878f4ebc7",
"high_medium_critical": 0,
"low_deferred": 3,
"record": "../p08-02-audit-r07/ACTUAL_OPUS_GAME_REVIEW_BF559.json"
},
"repair": {
"state": "submitted",
@@ -38,5 +40,7 @@
"scope": "restore exact r04 data and implementation local test provenance; no tested source changes authorized",
"local_checker": "4 tests55.197s OK, actual transcript verified"
},
"reused_native_os_regression_provenance": "d1c7ce27, exact all1316 selected source/spec/input/marker equality; original receipts not relabelled"
"reused_native_os_regression_provenance": "d1c7ce27, exact all1316 selected source/spec/input/marker equality; original receipts not relabelled",
"integration_commit": "c675bed91d694a18abbddac85013eb5b443bdca1",
"runner_state": "completed"
}
@@ -0,0 +1,29 @@
{
"review": {
"task_id": "P08-02",
"commit": "bf559632ddd938085702529d9dd6b7c878f4ebc7",
"status": "pass",
"summary": "I checked candidate bf55963 against the P08-02 spec, the diff, the checked-out sources and the .review-material receipts. The commit fixes both blocking findings from the d1c7ce2 review.\n\n(1) ROOT_REPAIR_INPUT-r04.json is restored, and the `actual_readonly_diagnostics` key is present again (confirmed by Grep). This file is the input that tools/test_p08_migration_evidence.py reads when it loads. It is listed at the preserved raw SHA 23ef44a0…, which matches the bytes recorded in r07.\n(2) The checker tests were rerun on the final frozen files. The actual-local-checker-032c5c transcript checks the SHAs of r04 (23ef44a0), the test file (fd9ef7ec) and the checker (928353…) first, then shows \"Ran 4 tests in 55.197s OK\". implementation.json now reports that same run and marks the earlier runs as historical, not current.\n\nThe registered p08-evidence validator ran `check_p08_migration_evidence.py --verify-only` against this candidate's tree and passed: integrity \"verified\", deficits=[], exit 0. The checker recomputes `source_refs()` from the checked-out tree. It also verifies:\n- the frozen spec, input and marker-contract SHAs, and every production source pin;\n- the four ON/OFF positive/refusal pairs, each with distinct writer/reader native PIDs;\n- raw lifecycle, strict markers and guarded fresh profiles;\n- whole typed and raw-Variant equality across the two processes at all 162 labels;\n- the semantic checks for no overlap, orphan or loss in occupancy, rescue, cargo and EV;\n- that in refusal cases live state, formal members and backup members are unchanged, with no partial batch;\n- the normal-menu native-OS sequence (preview, cancel, confirm, changed-source rejection);\n- the full-roster final regression.\n\nThe evidence index was collected at d1c7ce2. Reusing it is justified because the selected source map, which excludes docs, is byte-identical: the validator recomputes it at bf55963, and EXACT_EVIDENCE_REUSE_APPLICABILITY lists no changed paths. This commit changes only docs and metadata.\n\nHow each condition is covered:\n- **mixed_construction:** a progressing paid job, a zero-progress paid job and a completed dorm are migrated in one batch.\n- **occupancy_change:** cell ownership and disjointness are checked, with only explicitly allowed geometry deltas and a support epoch justified from source.\n- **actual_actor_positions:** the checker allows no actor, credit, route or money delta.\n- **combined_rescue_logistics_ev:** a rescue in flight, carried cargo plus a reserved request, and 4 boarded EV passengers plus 1 waiting are all in the same save. The patient ends treated, the original cargo request completes, and each EV request arrives exactly once.\n- **no_overlap_orphan_loss:** ON and OFF are both run, with the reader in a separate PID.\n- **unsolvable_preservation:** a late refusal at the dorm rolls back with the original save and the pre-existing backup preserved, and the separate-PID continuation keeps the old shape.\n\nNo production files are changed, all edits are within allowed_paths, and no tests are removed or disabled. This pass covers the review gate only. Windows coverage, main integration, current final verification and ledger closure are still Root conditions and stay pending.",
"acceptance_ids": [
"P08-02"
],
"findings": [
{
"severity": "low",
"message": "The checker only checks that the index commit is 40 hex characters. It never confirms that the commit equals the submitted candidate (the index and OS proof say d1c7ce2, the candidate is bf55963). Reuse is still sound, because the full source map is recomputed and must match exactly. But commit provenance is not machine-bound to the candidate; it rests on the reuse-applicability record."
},
{
"severity": "low",
"message": "Some metadata in implementation.json is stale. `metadata_sync.review_material_context_gap` says there is no .review-material, but it is now present. `scope` still says 'Metadata-only synchronization against Git 1545bd42'. This is documentation only and changes no claims."
},
{
"severity": "low",
"message": "Still open from the previous review: in tests/s1/test_p08_combined_migration.gd, `break` only leaves the writer/reader loop, so the remaining combinations keep running after a failure. Failures are still counted, so this cannot produce a false pass."
}
]
},
"passed": true,
"actual_record": "/Users/korizatou114/Library/Application Support/agent-control/the-tree-p08-02/runs/48d7a4379d5246278f74bc5b5839a09e/result.json",
"sha256": "11626cc11d05b07decc2063307399e393b8820d1ab65006456000ceae538bd1b",
"original_unit_completed": false
}
@@ -0,0 +1,10 @@
{
"proposal": {
"action": "wait",
"task_id": "P08-02",
"reason": "P08-02はcompletedで、c675bed9へ採用済みです。再実行・試験・新workerは開始せずwaitとします。次に正式閉鎖する元成果単位としてP08-03(配置の通常操作受入)を推奨します。\n\n【他候補を見送る理由】\n- P04-01: D05未確定規約についてオーナー判断が要ります。7領域の生証拠と、後続契約の承認も未了です。\n- P18-01: 未設定本番値の承認待ちです。旧alias再保存・退店客参照・旧Reader互換・UNIQUEのreview指摘も残っています。\n- P22-02: 614用途の選定が0件です。D08/D09が未確定で、技術reviewのhighも残っています。\n- P24-02: 保持済み証拠は単一scenario・復元直後phaseに限られます。8条件の大半が残り、自然NTR・決闘・防衛はP18-01/02、P19-01、P21-01の受入に依存します。実盾0/NTR文言、全modal、Windows実機も未了です。既存成果の再利用量は多いものの、今すぐ閉じられる単位ではありません。\n\n上記4件は、いずれも未承認値または他単位の完了待ちです。\n\n【P08-03の利点】\n- planned状態で、remaining_gapsは空です。\n- 直前に閉じたP08-02と同じ配置・保存領域で、資産を直接再利用できます。\n- 未確定値への依存がありません。\n\n【P08-03の全受入条件(原本の分母1単位、部分加点なし)】\n1. 通常パレットから支持・接続・不正位置・撤去・再建築を操作する。\n2. 拒否理由の表示と実判定が一致する。\n3. パン後・ズーム後・別PIDでの保存再開後も、同じセル位置を扱う。\n\n【再利用できる証拠・資産】\n- P08-01: 30施設の配置条件。\n- P08-02(c675bed9): 保存再開・旧配置移行の証拠形式、mixed fixture、check_p08_migration_evidenceの構成。\n- tools/run_all_tests.py: execute_phase、profile guard、owned_outer、strict marker、completion_marker_contracts.json。\n- 既存のtests/ui/test_dimension_migration_ui.gd、およびsave/path/ownership suite。\n- scenes/main/world_preview.gd: set_zoom、canvas_to_cell、cell_to_canvas、_clamp_pan、HOME(reset_view)。\n\n【手動ジェスチャー保留との関係】\n- 延期中の操作はCtrl押下wheelと左押下dragです。world_preview.gdの_gui_inputを確認したところ、Ctrlなしwheel(pan_modeでない時はズーム)、中ボタンdrag、pan_mode時のwheel(縦パン)という別経路があります。\n- パンとズームはこの別経路で実証すること。延期中ジェスチャーの成立を推定・代用してはいけません。\n- Windows全機器の受入は明示的に未了のまま残します。\n\n【具体指示(新規登録時)】\n- 実装として許可する範囲: 新規のfixture、test_p08_normal_placement_ops suite、Root用driver、checker(--verify-only)、test、CONDITION_MATRIX、implementation.json、およびmarker契約へのentry 1件の追加だけ。\n- 本番のruntime/UIは初期範囲で編集しません。実際の欠陥を示せた場合に限り、最小patchを提案として返します。\n- 条件ごとに必要な実証:\n - 支持・接続(不正位置を含む)の各拒否について、通常パレットで操作した時のUI拒否理由とWorldService/建設判定の実結果を、同一セルで照合します。\n - 撤去→再建築では、占有・support・予約・資金の差分を確認します。\n - 同一セルの位置一致は、ズーム0.5/1/4倍、中ボタンdragによるパン後、clampの境界、別PIDでの保存再開後のそれぞれで、canvas_to_cell→cell_to_canvasが往復一致することで示します。\n- 正例が実際に到達できることを示します。\n- 負例: 理由不一致、位置ずれ、stale source、偽OS signal、再開後の不一致、撤去残骸を検出させます。\n- 実OS入力・画面・状態の収集とnative実行はRootが行います。\n- 閉鎖の要件: 全条件の別Opus独立review、main統合、最終検証、台帳反映。\n\n【不足と残工数】\n- 正規の受入spec JSONは未作成で、Runnerへの登録が必要です(オーナー/Root)。\n- 実OS入力の証拠収集はRootが行います。\n- 残工数は中程度です。新規fixture・driver・checkerが必要ですが、P08-02の型を流用できます。\n- 依存は完了済みのP08-01/02だけで、未確定値には依存しません。\n- 価値: 配置系パッケージP08の最後の単位で、閉じればP08全体を閉鎖できます。",
"codex_model": "gpt-6-astra",
"codex_model_reason": "gpt-6-astraを選びます。理由は次のとおりです。\n- 同系統のP08-02は修正7回を要しました。\n- P08-03では、UI拒否理由と実判定の対応付け、ズーム・パン・clamp・別PID再開をまたぐ座標往復の照合、実OS入力と偽signalの区別、到達可能な正例と意味のある負例を備えたchecker設計を、一度に正しく作る必要があります。\n- 延期ジェスチャーを避ける入力経路の選別も、仕様を理解したうえでの判断が要ります。\n\n修正の往復を減らせば、時間と総使用量の点でも既定のsolより有利と判断します。"
},
"root_correction_required": "P08-01 is not completed; no P08 whole-package closure may be inferred. Native middle-drag must not be assumed available; use observed supported native wheel-pan route and keep deferred gestures pending."
}
@@ -0,0 +1,19 @@
{
"candidate": "bf559632ddd938085702529d9dd6b7c878f4ebc7",
"findings": [
{
"severity": "low",
"message": "The checker only checks that the index commit is 40 hex characters. It never confirms that the commit equals the submitted candidate (the index and OS proof say d1c7ce2, the candidate is bf55963). Reuse is still sound, because the full source map is recomputed and must match exactly. But commit provenance is not machine-bound to the candidate; it rests on the reuse-applicability record."
},
{
"severity": "low",
"message": "Some metadata in implementation.json is stale. `metadata_sync.review_material_context_gap` says there is no .review-material, but it is now present. `scope` still says 'Metadata-only synchronization against Git 1545bd42'. This is documentation only and changes no claims."
},
{
"severity": "low",
"message": "Still open from the previous review: in tests/s1/test_p08_combined_migration.gd, `break` only leaves the writer/reader loop, so the remaining combinations keep running after a failure. Failures are still counted, so this cannot produce a false pass."
}
],
"disposition": "independent review classified all low; no acceptance waiver, product change or repeated regression; preserve for later relevant work",
"original_unit_completed": false
}
@@ -0,0 +1,78 @@
{
"plan_id": "P08-02",
"original_work": "混合建設、占有変更、役者の実位置、救護・物流・EVをまとめて移行する。",
"original_acceptance": "重複、孤立、消失がない。解消不能時は元配置とセーブを保つ。",
"state": "completed",
"completed_at_jst": "2026-10-14T00:38:01.089905+09:00",
"implementation_commit": "bf559632ddd938085702529d9dd6b7c878f4ebc7",
"integration_commit": "c675bed91d694a18abbddac85013eb5b443bdca1",
"native_os_regression_collected_commit": "d1c7ce27d21a77be87081e12d20e7c8dd6ffa353",
"all_selected_source_files": 1316,
"real_main_source_map_matches_tested_source": true,
"required_conditions_accepted": [
"mixed_construction",
"occupancy_change",
"actual_actor_positions",
"combined_rescue_logistics_ev",
"no_overlap_orphan_loss",
"unsolvable_preservation"
],
"registered_validation_review_integration_final_records": [
{
"kind": "validation",
"commit_sha": "d1c7ce27d21a77be87081e12d20e7c8dd6ffa353",
"artifact": "/Users/korizatou114/Library/Application Support/agent-control/the-tree-p08-02/runs/11b6c33568fe4876849d701f6c783cfb-validation.json",
"passed": 1,
"artifact_sha256": "f3b7929470d22feb7bed7634dc68f5675163ab967632341ff0ce03dfc2822330"
},
{
"kind": "validation",
"commit_sha": "bf559632ddd938085702529d9dd6b7c878f4ebc7",
"artifact": "/Users/korizatou114/Library/Application Support/agent-control/the-tree-p08-02/runs/473aac189bb644448cb69156ba16b944-validation.json",
"passed": 1,
"artifact_sha256": "9e1d7faa9b4d6d82595eb19e3025fdce88b5a10023aa623d21be777ee7a82c70"
},
{
"kind": "review",
"commit_sha": "bf559632ddd938085702529d9dd6b7c878f4ebc7",
"artifact": "/Users/korizatou114/Library/Application Support/agent-control/the-tree-p08-02/runs/48d7a4379d5246278f74bc5b5839a09e/result.json",
"passed": 1,
"artifact_sha256": "11626cc11d05b07decc2063307399e393b8820d1ab65006456000ceae538bd1b"
},
{
"kind": "integration",
"commit_sha": "c675bed91d694a18abbddac85013eb5b443bdca1",
"artifact": "/Users/korizatou114/Library/Application Support/agent-control/the-tree-p08-02/runs/b8de4d2308634eb9b9396cf8dc97a0e3-integration.json",
"passed": 1,
"artifact_sha256": "1b3a57331c902be22ad269a3993e622c6f3b7d2bbc1bc6300bbdb1c24225faac"
},
{
"kind": "final",
"commit_sha": "c675bed91d694a18abbddac85013eb5b443bdca1",
"artifact": "/Users/korizatou114/Library/Application Support/agent-control/the-tree-p08-02/runs/f7b8b0d7360e475c85702cc989e943ba-final.json",
"passed": 1,
"artifact_sha256": "1f329e0c492e93d9a3440bc7298e6a46c674a30d0aa25580b37b0b35cac3b13c"
}
],
"native_on_off_success_refusal_writer_reader": 8,
"normal_os_actions": [
"preview",
"cancel",
"confirm",
"changed_source_rejection"
],
"full_final_regression_suites": 174,
"actual_local_checker_tests": 4,
"independent_reviewer_model": "claude-opus-5-5",
"main_owner_authorization": "Explicit user main-update authorization recorded by Runner",
"low_findings_deferred": "DEFERRED_LOW_FINDINGS.json",
"checkout_text_alignment": "REAL_MAIN_CHECKOUT_BYTE_ALIGNMENT.json; original7 files fully retained",
"windows_same_release_device_acceptance": "not performed; remains required in global distribution/platform acceptance",
"whole_P08_package_completed": false,
"whole_game_completed": false,
"original_denominator": {
"packages": 30,
"delivery_units": 88,
"partial_credit": false
}
}
@@ -0,0 +1,38 @@
{
"task": {
"id": "P08-02",
"state": "approval_pending",
"submitted": "bf559632ddd938085702529d9dd6b7c878f4ebc7",
"candidate": "c675bed91d694a18abbddac85013eb5b443bdca1",
"main_base": "80771caf9af5ff4542ea17fe9a7da6773e9b328f",
"repairs": 7
},
"integration_checkout": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p08-02/P08-02-integration-cd1274dc",
"actual_integration_source_map_equal": true,
"frozen_spec_equal": true,
"changed_paths": [
"docs/plans/original-completion-2026-10-02/execution/completion_marker_contracts.json",
"docs/plans/original-completion-2026-10-02/execution/p08-02/CONDITION_MATRIX.md",
"docs/plans/original-completion-2026-10-02/execution/p08-02/ROOT_REPAIR_INPUT-r03.json",
"docs/plans/original-completion-2026-10-02/execution/p08-02/ROOT_REPAIR_INPUT-r04.json",
"docs/plans/original-completion-2026-10-02/execution/p08-02/ROOT_REPAIR_INPUT-r07.json",
"docs/plans/original-completion-2026-10-02/execution/p08-02/implementation-historical-6c7c724.json",
"docs/plans/original-completion-2026-10-02/execution/p08-02/implementation.json",
"tests/fixtures/p08-02/README.md",
"tests/fixtures/p08-02/mixed_world.gd",
"tests/fixtures/p08-02/mixed_world.gd.uid",
"tests/fixtures/p08-02/reader.gd",
"tests/fixtures/p08-02/reader.gd.uid",
"tests/fixtures/p08-02/writer.gd",
"tests/fixtures/p08-02/writer.gd.uid",
"tests/s1/test_p08_combined_migration.gd",
"tests/s1/test_p08_combined_migration.gd.uid",
"tools/check_p08_migration_evidence.py",
"tools/run_p08_mixed_migration.py",
"tools/test_p08_migration_evidence.py"
],
"owner_authorization": "User explicitly authorized main updates, committing and pushing in this thread; no new scope or product values changed",
"independent_review": "actual Opus bf559632 pass, high/medium/critical0",
"Windows_global_acceptance": "still pending, no inference",
"original_unit_completed": false
}
@@ -0,0 +1,65 @@
{
"integrated_commit": "c675bed91d694a18abbddac85013eb5b443bdca1",
"all1316_real_main_source_bytes_now_equal_to_tested_source_map": true,
"alignment": [
{
"path": "assets/kenney/tiny_dungeon/Tiled/sampleMap.tmx",
"original_raw_sha256": "fc545787837e2655c9d2078cc1b167df0d9ea2755f6ec3912c7987e8501339e3",
"canonical_tested_sha256": "3849e083e3d4f6a71dbf725d8473e93fa6ef8cdc9d314368eee15c980cf41775",
"original_archive": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p08-02-checkout-byte-alignment/original/assets/kenney/tiny_dungeon/Tiled/sampleMap.tmx",
"only_CRLF_to_LF": true,
"original_whole_bytes_preserved": true
},
{
"path": "assets/kenney/tiny_dungeon/Tiled/sampleSheet.tsx",
"original_raw_sha256": "02f1b90cfdb37bcccddc83d074954272aaffd297ed4fabce7bb670f2f3f4be71",
"canonical_tested_sha256": "a2cca2c5e50b14023ce00f5d4112fb0b8264bfff9407d7a5198656e28d67fa16",
"original_archive": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p08-02-checkout-byte-alignment/original/assets/kenney/tiny_dungeon/Tiled/sampleSheet.tsx",
"only_CRLF_to_LF": true,
"original_whole_bytes_preserved": true
},
{
"path": "assets/kenney/tiny_dungeon/Visit Kenney.url",
"original_raw_sha256": "0dd1a0b295582cd3185547f0c1d92b4d5392c7782b90a428e192944a496052e0",
"canonical_tested_sha256": "6787defa3ecb6118622e1903b65802c0200628fae5164b51b4fd467f92f3f284",
"original_archive": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p08-02-checkout-byte-alignment/original/assets/kenney/tiny_dungeon/Visit Kenney.url",
"only_CRLF_to_LF": true,
"original_whole_bytes_preserved": true
},
{
"path": "assets/kenney/tiny_dungeon/Visit Patreon.url",
"original_raw_sha256": "84be5ef26b07905fa7e196e943c9807bf84138c3a71d87f51c6fd57b85c48c34",
"canonical_tested_sha256": "2fcba31333935f4aa35e9de2e74e2b7ba1b1a8011540e08016ff6d81e9dd7490",
"original_archive": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p08-02-checkout-byte-alignment/original/assets/kenney/tiny_dungeon/Visit Patreon.url",
"only_CRLF_to_LF": true,
"original_whole_bytes_preserved": true
},
{
"path": "assets/kenney/tiny_town/Tiny Dungeon (base pack).url",
"original_raw_sha256": "6cf442be20ad3364ba87183461744da9e979b5d4f243c83e2404f2cf884500d9",
"canonical_tested_sha256": "6d93bb958f9b7d5f21ceb8cbd24c184dc5c9f87aee7c680b336ecba7a89823d8",
"original_archive": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p08-02-checkout-byte-alignment/original/assets/kenney/tiny_town/Tiny Dungeon (base pack).url",
"only_CRLF_to_LF": true,
"original_whole_bytes_preserved": true
},
{
"path": "assets/kenney/tiny_town/Visit Kenney.url",
"original_raw_sha256": "0dd1a0b295582cd3185547f0c1d92b4d5392c7782b90a428e192944a496052e0",
"canonical_tested_sha256": "6787defa3ecb6118622e1903b65802c0200628fae5164b51b4fd467f92f3f284",
"original_archive": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p08-02-checkout-byte-alignment/original/assets/kenney/tiny_town/Visit Kenney.url",
"only_CRLF_to_LF": true,
"original_whole_bytes_preserved": true
},
{
"path": "assets/kenney/tiny_town/Visit Patreon.url",
"original_raw_sha256": "84be5ef26b07905fa7e196e943c9807bf84138c3a71d87f51c6fd57b85c48c34",
"canonical_tested_sha256": "2fcba31333935f4aa35e9de2e74e2b7ba1b1a8011540e08016ff6d81e9dd7490",
"original_archive": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p08-02-checkout-byte-alignment/original/assets/kenney/tiny_town/Visit Patreon.url",
"only_CRLF_to_LF": true,
"original_whole_bytes_preserved": true
}
],
"product_or_art_body_changed": false,
"git_source_tree_changed": false,
"previous_raw_versions_deleted": false
}
@@ -0,0 +1,131 @@
{
"scope": "read-only registry status for Opus next single target selection; no new implementation",
"tasks": [
{
"project": "the-tree-mana-proposal",
"id": "MP-01",
"state": "blocked",
"submitted": null,
"candidate": null,
"repairs": 0,
"running_records": 0
},
{
"project": "the-tree-mana-proposal-r02",
"id": "MP-01-r02",
"state": "completed",
"submitted": "6b78f8fd71131e61ba695939f4629fec9f51d7a9",
"candidate": "65a4fe2bb8e99812a8e8ad7f7a7addf489fe5067",
"repairs": 2,
"running_records": 0
},
{
"project": "the-tree-p04-01",
"id": "P04-01",
"state": "repair_pending",
"submitted": "a19737b1606ba360a18c8fe0914594f038034924",
"candidate": null,
"repairs": 2,
"running_records": 0
},
{
"project": "the-tree-p06-01",
"id": "P06-01",
"state": "blocked",
"submitted": null,
"candidate": null,
"repairs": 0,
"running_records": 0
},
{
"project": "the-tree-p08-02",
"id": "P08-02",
"state": "completed",
"submitted": "bf559632ddd938085702529d9dd6b7c878f4ebc7",
"candidate": "c675bed91d694a18abbddac85013eb5b443bdca1",
"repairs": 7,
"running_records": 0
},
{
"project": "the-tree-p13-03",
"id": "P13-03",
"state": "blocked",
"submitted": "7645c55149d3bebf3ed602cf3039b15b28fa376f",
"candidate": null,
"repairs": 2,
"running_records": 0
},
{
"project": "the-tree-p18-01-model",
"id": "P18-01-CODE",
"state": "repair_pending",
"submitted": "0084760ee05a97adfcbd783a71161491f3629918",
"candidate": null,
"repairs": 2,
"running_records": 0
},
{
"project": "the-tree-p22-02-contract",
"id": "P22-02",
"state": "blocked",
"submitted": "c6ccc5a6ab4b1670f1ccf813937edf339ca19139",
"candidate": null,
"repairs": 3,
"running_records": 0
},
{
"project": "the-tree-p24-02-operations",
"id": "P24-02",
"state": "submitted",
"submitted": "9641ed52def2ff8e5b0222449a4a83a1191e1d37",
"candidate": null,
"repairs": 3,
"running_records": 0
},
{
"project": "the-tree-p24-03",
"id": "P24-03",
"state": "blocked",
"submitted": null,
"candidate": null,
"repairs": 0,
"running_records": 0
},
{
"project": "the-tree-p24-03-code",
"id": "P24-03",
"state": "completed",
"submitted": "4cefcff849d4dc1211caa5066e24bfae666cc2f4",
"candidate": "0a759f13aed03c05fd4a25ab4a2c26eefec94e3c",
"repairs": 2,
"running_records": 0
},
{
"project": "the-tree-runner-agy-execution",
"id": "RP24-02",
"state": "repair_pending",
"submitted": "09262f37c14397118d51b6b43c35ddbee14fcfa2",
"candidate": null,
"repairs": 2,
"running_records": 0
},
{
"project": "the-tree-runner-p13-recovery",
"id": "RP13-01",
"state": "repair_pending",
"submitted": "1398aa2de9f4ca0fd57f7db9d640e829b425553b",
"candidate": null,
"repairs": 2,
"running_records": 0
},
{
"project": "the-tree-runner-p24-review-packet",
"id": "RP24-01",
"state": "completed",
"submitted": "053f391bf35482c0996292de263f2c39e88d96f0",
"candidate": "ba238177d33310fe8b4095998a178464488ed5e4",
"repairs": 2,
"running_records": 0
}
]
}
@@ -0,0 +1,128 @@
{
"contract": {
"id": "P08-02",
"title": "旧配置の安全な変更",
"requirement_ids": [
"P08-02"
],
"acceptance_ids": [
"P08-02"
],
"spec_ref": "docs/spec/acceptance/P08-02.json",
"base_commit": "e196578c1a4ad2fdf84642565bd102e524be386f",
"worker": "codex",
"allowed_paths": [
"docs/plans/original-completion-2026-10-02/execution/p08-02/**",
"docs/plans/original-completion-2026-10-02/execution/completion_marker_contracts.json",
"tests/s1/test_p08_combined_migration.gd",
"tests/s1/test_p08_combined_migration.gd.uid",
"tests/fixtures/p08-02/**",
"tools/run_p08_mixed_migration.py",
"tools/check_p08_migration_evidence.py",
"tools/test_p08_migration_evidence.py"
],
"depends_on": [],
"resource_locks": [
"p08-combined-migration",
"save-placement-final-proof"
],
"validation_ids": [
"p08-evidence"
],
"max_repair_attempts": null,
"spec_sha256": "19f02bb7912a4d7354e565186f02366fc1d4dd698468d26142e8204fd14ebfb0"
},
"implementation_commit": "bf559632ddd938085702529d9dd6b7c878f4ebc7",
"integration_commit": "c675bed91d694a18abbddac85013eb5b443bdca1",
"owner": "korizatou114: explicit main-update authorization in this thread",
"evidence": [
{
"id": 1,
"task_id": "P08-02",
"kind": "validation",
"commit_sha": "6c7c724410c350afe3d49fa8ec52defe20e78041",
"artifact": "/Users/korizatou114/Library/Application Support/agent-control/the-tree-p08-02/runs/5aa48d041fc8408cbefad45858061c1b-validation.json",
"passed": 0
},
{
"id": 2,
"task_id": "P08-02",
"kind": "validation",
"commit_sha": "e59206b9b2578ddb4a1ec023f836d413a7a8fbfb",
"artifact": "/Users/korizatou114/Library/Application Support/agent-control/the-tree-p08-02/runs/5efce8a8e90646df90b4203792880cd0-validation.json",
"passed": 0
},
{
"id": 3,
"task_id": "P08-02",
"kind": "validation",
"commit_sha": "bb34f443c4645a56d7798a142f1e2d8ddf615cae",
"artifact": "/Users/korizatou114/Library/Application Support/agent-control/the-tree-p08-02/runs/a796dc1c9e534a6c8741e416ee5833fa-validation.json",
"passed": 0
},
{
"id": 4,
"task_id": "P08-02",
"kind": "validation",
"commit_sha": "592809bfdaf6a1bbc5ec9cbaeff71a7bb072add9",
"artifact": "/Users/korizatou114/Library/Application Support/agent-control/the-tree-p08-02/runs/5b41bc58b7aa4a47966f3d0911a2e7af-validation.json",
"passed": 0
},
{
"id": 5,
"task_id": "P08-02",
"kind": "validation",
"commit_sha": "1545bd42d689a9a6382e2b003ee0550fa197f6e4",
"artifact": "/Users/korizatou114/Library/Application Support/agent-control/the-tree-p08-02/runs/db010bb7e1304f82b57490b5cdb6cae5-validation.json",
"passed": 0
},
{
"id": 6,
"task_id": "P08-02",
"kind": "validation",
"commit_sha": "d1c7ce27d21a77be87081e12d20e7c8dd6ffa353",
"artifact": "/Users/korizatou114/Library/Application Support/agent-control/the-tree-p08-02/runs/11b6c33568fe4876849d701f6c783cfb-validation.json",
"passed": 1
},
{
"id": 7,
"task_id": "P08-02",
"kind": "review",
"commit_sha": "d1c7ce27d21a77be87081e12d20e7c8dd6ffa353",
"artifact": "/Users/korizatou114/Library/Application Support/agent-control/the-tree-p08-02/runs/da13e081d6c74d55bcb70a69f6f5fbab/result.json",
"passed": 0
},
{
"id": 8,
"task_id": "P08-02",
"kind": "validation",
"commit_sha": "bf559632ddd938085702529d9dd6b7c878f4ebc7",
"artifact": "/Users/korizatou114/Library/Application Support/agent-control/the-tree-p08-02/runs/473aac189bb644448cb69156ba16b944-validation.json",
"passed": 1
},
{
"id": 9,
"task_id": "P08-02",
"kind": "review",
"commit_sha": "bf559632ddd938085702529d9dd6b7c878f4ebc7",
"artifact": "/Users/korizatou114/Library/Application Support/agent-control/the-tree-p08-02/runs/48d7a4379d5246278f74bc5b5839a09e/result.json",
"passed": 1
},
{
"id": 10,
"task_id": "P08-02",
"kind": "integration",
"commit_sha": "c675bed91d694a18abbddac85013eb5b443bdca1",
"artifact": "/Users/korizatou114/Library/Application Support/agent-control/the-tree-p08-02/runs/b8de4d2308634eb9b9396cf8dc97a0e3-integration.json",
"passed": 1
},
{
"id": 11,
"task_id": "P08-02",
"kind": "final",
"commit_sha": "c675bed91d694a18abbddac85013eb5b443bdca1",
"artifact": "/Users/korizatou114/Library/Application Support/agent-control/the-tree-p08-02/runs/f7b8b0d7360e475c85702cc989e943ba-final.json",
"passed": 1
}
]
}
@@ -0,0 +1,44 @@
# P08-02 retained implementation condition matrix
Status: submitted for Root verification; original P08-02 acceptance remains pending.
Frozen spec: `docs/spec/acceptance/P08-02.json`, stripped UTF-8 SHA-256
`19f02bb7912a4d7354e565186f02366fc1d4dd698468d26142e8204fd14ebfb0`.
The raw file has a trailing newline. The six rows are facets of one existing unit, not six units.
All rows use `tests/fixtures/p08-02/mixed_world.gd` through `writer.gd` and
`reader.gd`, and the standalone `tests/s1/test_p08_combined_migration.gd`.
Driver phases are `off-positive`, `off-refusal`, `on-positive`, `on-refusal`,
each with `-writer` then `-reader`; import/parse precede them.
| Required condition | Retained fixture/test coverage | Driver phase | Checker rule (`tools/check_p08_migration_evidence.py`) | Negative mutation (`tools/test_p08_migration_evidence.py`) | Pending evidence |
|---|---|---|---|---|---|
| mixed_construction | `setup`: paid zero-progress old-size premium job, progressing premium job, completed dorm in the same save; `run`: full progress/payment/reservation/completion fields | All four pairs; positive applies batch, refusal continues old shape | `semantics` checks starting/progressing paid jobs, completed dorm and diagnostic budget; `case_gate` permits only explicit typed geometry deltas and requires four-cell positive jobs | `missing_start_stage`, `resource_delta_mismatch`, `partial_batch`; unapproved typed changes are compared without dropping fields | Native runtime/save and distinct-PID continuation; normal OS flow; Root final verification pending |
| occupancy_change | `invariant`: restore validation of ownership/support; migrated occupied/reserved cells captured in whole snapshots | All four pairs | `semantics`: disjoint cells, exact construction/world ownership and operational facility cells; `GEOMETRY` finite allowlist | `orphan_occupancy` | Native added/released cells and support validation; OS model/formal records; Root review pending |
| actual_actor_positions | Mid-route walker, fractional credit, real staff/rescue/cargo and EV positions; no route changes approved | All four pairs, checkpoint and minutes 001–160 | `typed_differences` forbids actor/credit/route/money deltas; full typed and raw Variant writer/reader equality | `duplicate_actor`, `unequal_cross_pid` | Native actual positions/credit/routes and cross-PID equality; OS state captures; Root review pending |
| combined_rescue_logistics_ev | `setup`: actual in-flight rescue, purchased carried food with original requests, four EV boarded plus one waiting; `run`: patient treated, original cargo completed, each EV arrival once | All four pairs and uncapped events | `semantics`: IDs, endpoints, reservations and EV actors; `case_gate`: final patient health, original cargo completion and exactly one arrival per original EV request | `lost_patient`, `lost_cargo`, `lost_ev` | Native coherent same-save mixed state and continuation; OS save/model attribution; Root review pending |
| no_overlap_orphan_loss | Whole typed snapshots/raw Variant files and uncapped events; runtime/cargo invariants | ON and OFF positive/refusal pairs | Ordered four-case roster, actual mode, distinct lifecycle PIDs, strict markers, all 162 labels compared, semantic ownership/reference checks | `duplicate_actor`, `orphan_occupancy`, `unequal_cross_pid`, `missing_on`, `missing_phase`, `duplicate_pid`, `wrong_source`, `stale_source` | Native ON/OFF and separate writer/reader PIDs; normal-menu OS proof; final regression and Root verification pending |
| unsolvable_preservation | Real pre-existing migration backup, late maintenance obstruction at dorm, independently migratable first job; refusal rollback and unchanged live/formal/backup | `off-refusal`, `on-refusal` writer/reader | Live equality; original equals refusal checkpoint; before/after member hash maps equal; raw four-member original/result/backup hashes bound | `partial_batch`, `overwritten_original`, `overwritten_backup` | Native late refusal and separate-PID original continuation; OS cancel/changed-source preservation; Root review pending |
The standalone suite executes both roles in one process and does not establish distinct-PID proof.
Only the Root collector launches separate phases through existing `execute_phase`/owned-outer
and fresh guarded profiles. Exactly one public suite marker exists:
`P08 combined migration: <checks> checks, <failures> failures`.
The driver privately owns the writer/reader marker templates; no second public entry is added.
Local Python tests are synthetic checker fixtures, including synthetic lifecycle/OS/regression
records; their success establishes checker reachability and rejection tests only.
Native Godot/OS execution, normal production menu preview/cancel/confirm/changed-source rejection,
final full regression, final submitted reviewer-packet measurement, applicable Windows coverage,
independent Opus review, integration/current verification and ledger closure remain Root conditions.
Controlled old-save setup must be labelled controlled, never natural production.
Checker integrity success cannot close the original unit. No production defect or product fix
was demonstrated by the authorized local checks; retained code and marker contract are reused.
Repair r04: seed 42588; existing definition-derived construction total gold 7110 /
materials 88, signing 150, food eight units 24. Initial gold 5000 / materials 50
and previous added resources zero leave a deficit of gold 2284 / materials 38.
The controlled fixture records and supplies only this derived deficit.
Historical full metadata is now referenced by
`implementation-historical-6c7c724.json`: both fixed Git versions were SHA-verified
before replacement. Root's verified gzip roundtrip SHA is provenance only;
no external archive is a checker/runtime dependency. Historical failure logs remain preserved.
@@ -0,0 +1,101 @@
{
"classification": "Root coordinator supplied repair input, not worker implementation or acceptance proof",
"measured_UIDs": {
"tests/fixtures/p08-02/mixed_world.gd.uid": {
"text": "uid://dg5n4yme6rk4p\n",
"raw_sha256": "d7549f933b74f5e807cd2d3b3adcdd083af4a3bd331614314ff7bfd7b0903f31"
},
"tests/fixtures/p08-02/reader.gd.uid": {
"text": "uid://741t47oxl3ct\n",
"raw_sha256": "3e68ce192d5770e3823df9699c5c99ebb618fe0a480b4d56913624941900b08a"
},
"tests/fixtures/p08-02/writer.gd.uid": {
"text": "uid://csw2850g6gjct\n",
"raw_sha256": "8f150654767de0c66329d7d9e84d306c4fa5a65c918e04fb520b626b39f68334"
}
},
"replacement_example": {
"classification": "Synthetic machine-readable complete index from retained Proof; diagnostic ONLY, never native/OS/regression acceptance evidence.",
"construction": "tools/test_p08_migration_evidence.py Proof creates all linked bytes and reachable whole-check positive. Embedded documents illustrate receipts/lifecycle/OS/regression/typed records. Digests belong to the disposable synthetic fixture, not delivered acceptance artifacts; reproduce with Proof in a worktree-local disposable directory.",
"complete_example_generator": {
"source": "tools/test_p08_migration_evidence.py",
"source_raw_sha256": "9924f4cb4f55b15caf9f9733d91f5095553abcf2861e4b335755531480b534a9",
"class": "Proof",
"constructor": "Proof(Path(fresh_temporary_directory))",
"project_root_binding": "module ROOT resolved from unchanged generator inside this exact candidate source tree",
"generated_full_index": "proof.index",
"generated_representative_documents": "{path: json.loads((proof.path / path).read_text()) for path in representative_artifact_document_paths}",
"native_or_os_runs": 0
},
"index_top_level_fields": [
"schema",
"commit",
"source_map",
"spec_sha256",
"marker_contract_sha256",
"inputs",
"cases",
"conditions",
"artifacts",
"acceptance",
"collection_error",
"phases",
"os_proof",
"regression"
],
"representative_artifact_document_paths": [
"runs/off-positive-writer/off-positive-writer-receipt.json",
"runs/off-positive-reader/off-positive-reader-receipt.json",
"runs/off-positive-writer/off-positive-writer/started.json",
"runs/off-positive-writer/off-positive-writer/ended.json",
"runs/off-positive-writer/off-positive-writer/outer-owned-finally.json",
"os.json",
"os/preview/input.json",
"regression.json",
"regression/input.json",
"regression/ended.json",
"pairs/off-positive/identity.json",
"pairs/off-positive/writer-process.json",
"pairs/off-positive/before-members.json"
],
"fixture_config_inputs": {
"fixture_sources": {
"tests/s1/test_p08_combined_migration.gd": "9284a8cfb478b4c8d69f6d8166eec6c41107e3902029289b3c0e9ba48c370855",
"tests/s1/test_p08_combined_migration.gd.uid": "8c3a70d0ce619b8cb98dc003eb6c53a31f167a686179a3ffc105f7cd4d856da5",
"tests/fixtures/p08-02/README.md": "bc76975e49e7761c2a3540a1e907ab2215ec315653a1d87df6919d1cebd779e0",
"tests/fixtures/p08-02/mixed_world.gd": "889bc895888b8c6ad50659a3b23a3ee45e9edf8dde9168f5560792c292070d26",
"tests/fixtures/p08-02/reader.gd": "a760d0e45979d747dbd1f8710033bdce13287b00eb879d947d8378ff920ed1be",
"tests/fixtures/p08-02/writer.gd": "1a918b5509773b4b07a27d47ee44583b0eb5288138f7bf896088a7913773c260",
"tools/run_p08_mixed_migration.py": "7e86737e6354a4734726ba8d3171ad5f58d6c0380aba5a0fa3c57879d580e579",
"tools/check_p08_migration_evidence.py": "8d697c8e9a606bcff6a0a8c6ec55e0e9c434ca9682b7ce6915b5bcb1ea4ff3fd",
"tools/test_p08_migration_evidence.py": "9924f4cb4f55b15caf9f9733d91f5095553abcf2861e4b335755531480b534a9"
},
"native_runner_input_shape": {
"protocol": "p08-mixed-v1",
"commit": "<actual final commit>",
"selected_source_map": "<exact source map>",
"engine": "<actual executable>",
"engine_sha256": "<raw SHA>",
"owner_pid": "<actual collector PID>",
"default_player": "<protected profile record>",
"diagnostic_seed": 42588
},
"case_environment": {
"P08_PAIR_ROOT": "<absolute guarded pair output>",
"P08_OPERATIONS": "off|on",
"P08_CASE": "positive|refusal"
},
"timeouts": "unchanged: collection 900s, phase maximum 180s",
"formal_validation": "Root copies actual evidence into allocated build directory; --verify-only reads BUILD_OUTPUT_DIR/p08-evidence/index.json"
},
"exact_reconstruction_verification": {
"entire_index_equal": true,
"entire_representative_documents_equal": true,
"index_canonical_sha256": "456c67833dc6d6d905a1c0543f7a3e6b1ead715b8e88a5fe816dbcb77072efc0",
"representative_canonical_sha256": "5727797a0ec11363d1463406be4f1979e279a9c77fff02c284ff7fff60bc32e6",
"canonical_encoding": "json.dumps(value,sort_keys=True,ensure_ascii=False).encode()"
},
"purpose": "Lossless complete synthetic example regeneration from retained code, not a real native/OS acceptance index. Explicit index_schema above remains authoritative. Root proved equality of all original fields before this proposal. Full prior implementation preserved in commit6c7c7244 and byte-verified gzip evidence."
},
"instructions": "Read this compact input first. Do not cat the entire 1MB old example into model context. Parse implementation.json with stdlib, replace example field, keep all other fields/schema/source logic. Add exact supplied UIDs; update outputs; after source map changes recompute current synthetic example digests with unchanged Proof class. Historical exact old reconstruction remains tied to6c. This input is within allowed scope, not an external path."
}
@@ -0,0 +1,306 @@
{
"purpose": "Same retained candidate; diagnose checker against real native outputs. Original native bytes and candidate preserved; not game acceptance.",
"actual_candidate": "592809bfdaf6a1bbc5ec9cbaeff71a7bb072add9",
"all8_native_phases_pass": true,
"defects": [
"actual Vector3i constructor scalar format rejected by decoder",
"logistics lazy destination inventory treated as orphan although canonical live facility exists",
"RESERVED queued request has no assigned carrier by domain contract",
"support revision is global world revision epoch, not independent +1 counter; actual changed142→150 alongside world144→150 after occupancy rewrites"
],
"actual_readonly_diagnostics": {
"ACTUAL_NATIVE_CHECKER.json": {
"candidate": "592809bfdaf6a1bbc5ec9cbaeff71a7bb072add9",
"elapsed_seconds": 16.212463750038296,
"actual_readonly_checker_deficits": [
"OS proof: unsafe artifact path",
"case off-positive: invalid literal for int() with base 10: 'Vector3i(0'",
"case off-refusal: invalid literal for int() with base 10: 'Vector3i(0'",
"case on-positive: invalid literal for int() with base 10: 'Vector3i(6'",
"case on-refusal: invalid literal for int() with base 10: 'Vector3i(-12'",
"final regression: unsafe artifact path"
],
"full_game_acceptance": false,
"original_unit_completed": false,
"index": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p08-02-native-mixed-r05/index.json"
},
"VECTOR_DECODER_READONLY_DIAGNOSTIC.json": {
"candidate": "592809bfdaf6a1bbc5ec9cbaeff71a7bb072add9",
"scope": "Root readonly decoder prototype diagnostic; no candidate code or actual evidence altered; no acceptance",
"observations": [
{
"case": "off-positive",
"jobs": [
{
"id": "construction_00000015",
"state": "BUILDING",
"progress": 1266
},
{
"id": "construction_00000016",
"state": "PLANNED",
"progress": 0
}
],
"starting_job": "construction_00000016"
},
{
"case": "off-refusal",
"jobs": [
{
"id": "construction_00000015",
"state": "BUILDING",
"progress": 1266
},
{
"id": "construction_00000016",
"state": "PLANNED",
"progress": 0
}
],
"starting_job": "construction_00000016"
},
{
"case": "on-positive",
"jobs": [
{
"id": "construction_00000015",
"state": "BUILDING",
"progress": 1266
},
{
"id": "construction_00000016",
"state": "PLANNED",
"progress": 0
}
],
"starting_job": "construction_00000016"
},
{
"case": "on-refusal",
"jobs": [
{
"id": "construction_00000015",
"state": "BUILDING",
"progress": 1266
},
{
"id": "construction_00000016",
"state": "PLANNED",
"progress": 0
}
],
"starting_job": "construction_00000016"
}
],
"remaining_deficits": [
"OS proof: unsafe artifact path",
"case off-positive: orphan cargo endpoint",
"case off-refusal: orphan cargo endpoint",
"case on-positive: orphan cargo endpoint",
"case on-refusal: orphan cargo endpoint",
"final regression: unsafe artifact path"
],
"elapsed_seconds": 16.21374141704291
},
"CARGO_ENDPOINT_READONLY_DIAGNOSTIC.json": [
{
"first_label": "original",
"original_requests": [
"supply.logistics_request.000000000001",
"supply.logistics_request.000000000002"
],
"active_inventory_ids": [
"cargo:staff_gina",
"facility.inventory:facility_00000005"
],
"requests": [
{
"request_id": "supply.logistics_request.000000000001",
"source_inventory_id": "facility.inventory:facility_00000005",
"destination_inventory_id": "facility.inventory:facility_00000006",
"item_requirements": {
"ingredient/raw_food": 4
},
"priority": 50,
"created_at": 728,
"deadline": -1,
"total_weight": 4,
"reserved_stack_ids": [
"stack_00000001"
],
"reservation_ids": [
"reservation_00000001"
],
"assigned_carrier_id": "staff_gina",
"state": "DELIVERING",
"retry_count": 0,
"state_reason": "",
"state_changed_at": 735
},
{
"request_id": "supply.logistics_request.000000000002",
"source_inventory_id": "facility.inventory:facility_00000005",
"destination_inventory_id": "facility.inventory:facility_00000006",
"item_requirements": {
"ingredient/raw_food": 4
},
"priority": 50,
"created_at": 729,
"deadline": -1,
"total_weight": 4,
"reserved_stack_ids": [
"stack_00000001"
],
"reservation_ids": [
"reservation_00000002"
],
"assigned_carrier_id": "",
"state": "RESERVED",
"retry_count": 0,
"state_reason": "NO_AVAILABLE_PORTER_OR_ROUTE",
"state_changed_at": 729
}
]
}
],
"CARGO_RULE_READONLY_DIAGNOSTIC.json": {
"candidate": "592809bfdaf6a1bbc5ec9cbaeff71a7bb072add9",
"scope": "Root readonly prototype only. Candidate/checker/evidence files unchanged, no formal acceptance.",
"basis": "Authoritative SupplyLogisticsBridge.validate_crosslinks lines508-554 resolves facility inventory endpoints by facility ownership and allows unassigned RESERVED request with valid reservation; destination inventory materializes upon delivery.",
"remaining_deficits": [
"OS proof: unsafe artifact path",
"final regression: unsafe artifact path",
"unapproved typed migration delta off-positive/systems/runtime/world/revisions/support",
"unapproved typed migration delta on-positive/systems/runtime/world/revisions/support"
],
"elapsed_seconds": 78.40071395831183
},
"ACTUAL_WORLD_REVISION_DELTAS.json": [
{
"case": "off-positive",
"original_world_revisions": {
"world": 144,
"occupancy": 144,
"walkability": 99,
"excavation": 0,
"support": 142
},
"checkpoint_world_revisions": {
"world": 150,
"occupancy": 150,
"walkability": 99,
"excavation": 0,
"support": 150
}
},
{
"case": "on-positive",
"original_world_revisions": {
"world": 144,
"occupancy": 144,
"walkability": 99,
"excavation": 0,
"support": 142
},
"checkpoint_world_revisions": {
"world": 150,
"occupancy": 150,
"walkability": 99,
"excavation": 0,
"support": 150
}
},
{
"case": "off-refusal",
"original_world_revisions": {
"world": 144,
"occupancy": 144,
"walkability": 99,
"excavation": 0,
"support": 142
},
"checkpoint_world_revisions": {
"world": 144,
"occupancy": 144,
"walkability": 99,
"excavation": 0,
"support": 142
}
},
{
"case": "on-refusal",
"original_world_revisions": {
"world": 144,
"occupancy": 144,
"walkability": 99,
"excavation": 0,
"support": 142
},
"checkpoint_world_revisions": {
"world": 144,
"occupancy": 144,
"walkability": 99,
"excavation": 0,
"support": 142
}
}
]
},
"source_basis": {
"scripts/supply/supply_logistics_bridge.gd:508": [
"static func validate_crosslinks(requests: Dictionary, staff: StaffService, inventory: InventoryService, facilities: FacilityService) -> bool:",
"\tvar carrier_owners: Dictionary = {}",
"\tvar active_task_ids: Dictionary = {}",
"\tfor id: StringName in _request_ids(requests):",
"\t\tvar request: LogisticsRequest = requests[id]",
"\t\tvar source := _facility_for_inventory(facilities, request.source_inventory_id)",
"\t\tvar destination := _facility_for_inventory(facilities, request.destination_inventory_id)",
"\t\tif not String(request.source_inventory_id).begins_with(\"facility.inventory:\") or not String(request.destination_inventory_id).begins_with(\"facility.inventory:\"):",
"\t\t\treturn false",
"\t\tif not request.is_terminal() and (source == null or destination == null):",
"\t\t\treturn false",
"\t\tvar task := _active_task(staff, id)",
"\t\tif request.state in [LogisticsRequest.State.RESERVED, LogisticsRequest.State.BLOCKED] or request.is_terminal():",
"\t\t\tif task != null:",
"\t\t\t\treturn false",
"\t\t\tif request.state == LogisticsRequest.State.RESERVED and not _reservation_quantities_valid(request, inventory, true):",
"\t\t\t\treturn false",
"\t\t\tcontinue",
"\t\tif request.state not in [LogisticsRequest.State.ASSIGNED, LogisticsRequest.State.PICKING_UP, LogisticsRequest.State.DELIVERING]:",
"\t\t\treturn false",
"\t\tvar worker := staff.get_staff(request.assigned_carrier_id)",
"\t\tif worker == null or worker.role_id != &\"porter\" or carrier_owners.has(worker.staff_id) \\",
"\t\t\tor task == null or task.assigned_staff_id != worker.staff_id or worker.current_task_id != task.task_id \\"
],
"scripts/world/world_service.gd:652": [
"func _mark_dirty(",
"\tcells: Array,",
"\toccupancy_changed: bool,",
"\twalkability_changed: bool,",
"\texcavation_changed: bool,",
"\tsupport_changed: bool",
") -> void:",
"\trevision += 1",
"\tif occupancy_changed:",
"\t\toccupancy_revision = revision",
"\tif walkability_changed:",
"\t\twalkability_revision = revision",
"\tif excavation_changed:",
"\t\texcavation_revision = revision",
"\tif support_changed:",
"\t\tsupport_revision = revision",
"\tfor cell: Variant in cells:",
"\t\tif cell is Vector3i and is_in_bounds(cell):",
"\t\t\t_dirty_cells[cell] = true"
]
},
"instructions": [
"Read only this compact file first; no broad history or full evidence dump.",
"Do not modify fixture/runtime/collector/native semantics already passed. Fix checker decoding/crosslink/counter checks, realistic targeted tests and metadata together. Original6conditions and30/88 unchanged.",
"Native bytes must stay immutable. Decide whether tested runtime inputs exactly match final after tooling-only changes; do not silently re-label old tested SHA. If final validator requires exact full source-map, execute final native once after all tooling fixes consolidated.",
"Freeze all source edits before running checker tests; prior README mutation during tests caused preventable stale proof retry.",
"Root external native collector should check first-writer actual scalar/crosslink semantics before running all other phases to avoid repeated whole collection.",
"Independent review and OS/final regression remain mandatory."
]
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,16 @@
{
"classification": "Historical full record preserved; compact provenance reference",
"original_raw_sha256": "ab1fcf46ef73f2157f16f69394b4039a562c031fae8d407adca013a452226e2f",
"original_raw_bytes": 1082602,
"git_reference": {
"commit": "6c7c724410c350afe3d49fa8ec52defe20e78041",
"path": "docs/plans/original-completion-2026-10-02/execution/p08-02/implementation.json"
},
"second_full_copy_git_reference": {
"commit": "e59206b9b2578ddb4a1ec023f836d413a7a8fbfb",
"path": "docs/plans/original-completion-2026-10-02/execution/p08-02/implementation-historical-6c7c724.json"
},
"root_lossless_archive": "artifacts/original-completion-2026-10-02/p08-02-preserved-r01/full-submitted-implementation.json.gz",
"raw_archive_roundtrip_verified": true,
"current_acceptance_claimed": false
}
@@ -0,0 +1,330 @@
{
"task_id": "P08-02",
"status": "submitted",
"acceptance": "pending",
"base_commit": "e196578c1a4ad2fdf84642565bd102e524be386f",
"spec_sha256_stripped_utf8": "19f02bb7912a4d7354e565186f02366fc1d4dd698468d26142e8204fd14ebfb0",
"spec_sha256_raw": "01b3600e8815b514ffd5c4d341d77a6a3e8341064796c1dae706062b746ba6aa",
"scope": "Metadata-only synchronization against Git 1545bd42; no code, fixture, runtime, marker or acceptance changes.",
"outputs": [
{
"path": "docs/plans/original-completion-2026-10-02/execution/completion_marker_contracts.json",
"sha256": "c4c6dbea08a92682c692a280dbc90702ccbe63702a4f2624519b18d42930e18f",
"hash_scope": "raw bytes",
"disposition": "r04 current source; retained paths and UID/marker entries"
},
{
"path": "tests/s1/test_p08_combined_migration.gd",
"sha256": "9284a8cfb478b4c8d69f6d8166eec6c41107e3902029289b3c0e9ba48c370855",
"hash_scope": "raw bytes",
"disposition": "r04 current source; retained paths and UID/marker entries"
},
{
"path": "tests/s1/test_p08_combined_migration.gd.uid",
"sha256": "8c3a70d0ce619b8cb98dc003eb6c53a31f167a686179a3ffc105f7cd4d856da5",
"hash_scope": "raw bytes",
"disposition": "r04 current source; retained paths and UID/marker entries"
},
{
"path": "tests/fixtures/p08-02/README.md",
"sha256": "e88ca33fdb4e96602d1fb108d71a9c35b6fa054619ecf6f1396e9a6c5e0ebd98",
"hash_scope": "raw bytes",
"disposition": "r04 current source; retained paths and UID/marker entries"
},
{
"path": "tests/fixtures/p08-02/mixed_world.gd",
"sha256": "a23f8a686be1d77e4874b9956eef89be4756f6e5eb01cc62454c3845acc62c25",
"hash_scope": "raw bytes",
"disposition": "r04 current source; retained paths and UID/marker entries"
},
{
"path": "tests/fixtures/p08-02/reader.gd",
"sha256": "a760d0e45979d747dbd1f8710033bdce13287b00eb879d947d8378ff920ed1be",
"hash_scope": "raw bytes",
"disposition": "r04 current source; retained paths and UID/marker entries"
},
{
"path": "tests/fixtures/p08-02/writer.gd",
"sha256": "1a918b5509773b4b07a27d47ee44583b0eb5288138f7bf896088a7913773c260",
"hash_scope": "raw bytes",
"disposition": "r04 current source; retained paths and UID/marker entries"
},
{
"path": "tools/run_p08_mixed_migration.py",
"sha256": "7e86737e6354a4734726ba8d3171ad5f58d6c0380aba5a0fa3c57879d580e579",
"hash_scope": "raw bytes",
"disposition": "r04 current source; retained paths and UID/marker entries"
},
{
"path": "tools/check_p08_migration_evidence.py",
"sha256": "928353233bf85436a5aaf8c4f77f3f82472d94b8ad2646cb1b030baf92b3b5dc",
"hash_scope": "raw bytes",
"disposition": "r04 current source; retained paths and UID/marker entries"
},
{
"path": "tools/test_p08_migration_evidence.py",
"sha256": "fd9ef7ec63f53dfd5e04e261606c9303d01a2e6590e22a35fef2e35df1429280",
"hash_scope": "raw bytes",
"disposition": "r04 current source; retained paths and UID/marker entries"
},
{
"path": "docs/plans/original-completion-2026-10-02/execution/p08-02/CONDITION_MATRIX.md",
"sha256": "6673051df9ae10f2df9b1812828e71ad9f5f24c433572defeef4e0978962a4e8",
"hash_scope": "raw bytes",
"disposition": "r04 current source; retained paths and UID/marker entries"
},
{
"path": "docs/plans/original-completion-2026-10-02/execution/p08-02/implementation.json",
"sha256": "fee85e6f4bb2824fc64bdfa275302f503a3234d83ab6c473c5e3ae6fdf91a3a6",
"hash_scope": "canonical normalized self record: replace this sha256 with null, UTF-8 json.dumps(ensure_ascii=False,sort_keys=True,separators=(comma,colon)), no newline",
"disposition": "r04 current source; retained paths and UID/marker entries"
},
{
"path": "tests/fixtures/p08-02/mixed_world.gd.uid",
"sha256": "d7549f933b74f5e807cd2d3b3adcdd083af4a3bd331614314ff7bfd7b0903f31",
"hash_scope": "raw bytes",
"disposition": "r04 current source; retained paths and UID/marker entries"
},
{
"path": "tests/fixtures/p08-02/reader.gd.uid",
"sha256": "3e68ce192d5770e3823df9699c5c99ebb618fe0a480b4d56913624941900b08a",
"hash_scope": "raw bytes",
"disposition": "r04 current source; retained paths and UID/marker entries"
},
{
"path": "tests/fixtures/p08-02/writer.gd.uid",
"sha256": "8f150654767de0c66329d7d9e84d306c4fa5a65c918e04fb520b626b39f68334",
"hash_scope": "raw bytes",
"disposition": "retained unchanged UID"
}
],
"self_hash_note": "A raw self-containing SHA cannot be embedded in itself. This explicit normalized hash covers implementation.json; Root must separately measure its raw SHA and the final full packet on actual submitted SHA. No final packet measurement claimed.",
"commands_actually_run": [
{
"command": "python3 -B AST parse of three P08 Python tools",
"exit_code": 0,
"result": "3 parses passed"
},
{
"command": "python3 -B tools/test_p08_migration_evidence.py (first run)",
"exit_code": 1,
"result": "2 tests; positive stale source map because worker changed README during test"
},
{
"command": "python3 -B tools/test_p08_migration_evidence.py (stable-source rerun)",
"exit_code": 0,
"result": "2 tests in 33.523s, OK; synthetic only",
"classification": "Historical worker run; superseded as current local-check metadata, preserved without relabeling."
},
{
"command": "python3 -B tools/test_p08_migration_evidence.py (Repair 7, final frozen sources)",
"exit_code": 0,
"result": "4 tests in 55.197s, OK; synthetic only"
}
],
"local_checks": {
"ast_parse": "passed, three Python sources",
"checker_tests": {
"command": "python3 -B tools/test_p08_migration_evidence.py",
"tests_run": 4,
"elapsed_seconds": 55.197,
"result": "OK",
"exit_code": 0,
"scope": "Synthetic local checker tests only; source edits frozen before this single run. Not native, OS, full regression or acceptance evidence.",
"final_raw_sha256": {
"tools/test_p08_migration_evidence.py": "fd9ef7ec63f53dfd5e04e261606c9303d01a2e6590e22a35fef2e35df1429280",
"tools/check_p08_migration_evidence.py": "928353233bf85436a5aaf8c4f77f3f82472d94b8ad2646cb1b030baf92b3b5dc",
"docs/plans/original-completion-2026-10-02/execution/p08-02/ROOT_REPAIR_INPUT-r04.json": "23ef44a0775ca53f1f67d6d64fcc96cd33eae935478768e9ce9431796eaa12ef"
}
},
"native_or_full_regression_run": false,
"evidence_reuse_pending": "Reuse of earlier native 8, OS and final 174 regression evidence is pending Root confirmation of exact source_map, input, config and environment matches. If restored r04 is in the selected source map, Root must decide whether to re-collect. Independent review and integration remain pending; no unconfirmed evidence counts asserted."
},
"pending_root_conditions": [
"mixed_construction",
"occupancy_change",
"actual_actor_positions",
"combined_rescue_logistics_ev",
"no_overlap_orphan_loss",
"unsolvable_preservation",
"native_Godot_and_OS_execution",
"separate_PID_writer_reader",
"normal_menu_OS_proof",
"final_full_regression",
"final_submitted_packet_measurement",
"applicable_Windows_coverage",
"independent_Opus_review",
"main_integration_current_final_verification",
"ledger_reflection_and_original_unit_closure"
],
"product_fix_proposal": null,
"index_schema": {
"name": "p08-evidence-v1",
"location": "BUILD_OUTPUT_DIR/p08-evidence/index.json",
"authority": "tools/check_p08_migration_evidence.py check() and tools/run_p08_mixed_migration.py collect()",
"top_level": {
"schema": "literal p08-evidence-v1",
"commit": "40 lowercase hex actual submitted commit; collector checks HEAD",
"source_map": "exact runner.source_refs(root) path -> raw SHA-256 including fixture/suite/tool sources",
"inputs": "exact frozen docs/spec/inputs/p08-02 immediate file path -> raw SHA-256",
"spec_sha256": "stripped UTF-8 frozen spec SHA",
"marker_contract_sha256": "raw marker contract SHA",
"cases": "ordered off-positive, off-refusal, on-positive, on-refusal",
"phases": "collector import/parse and case receipt paths",
"conditions": "all six IDs -> all four cases, except unsolvable_preservation -> both refusal cases",
"artifacts": "relative path -> {bytes: integer, sha256: raw digest}; no absolute/traversal/symlink; index itself excluded",
"os_proof": "relative OS proof JSON path; initially null in collector",
"regression": "relative final regression proof JSON path; initially null in collector",
"acceptance": "literal pending, including after integrity verification",
"collection_error": "null for integrity gate"
},
"case": {
"id": "operations-kind",
"operations": "off|on",
"kind": "positive|refusal",
"directory": "relative pair directory",
"phases": "writer then reader receipt paths (two)",
"files": "collector inventory path -> bytes/sha256; checker artifacts is content authority"
},
"phase_receipt": "actual_pid unique positive integer; phase, command argv, test, source_sha256, log relative to receipt parent; exit_code=0, engine_ended=true; native_process exit_code/helper_exit_code=0,timed_out=false,lifecycle_error=null; actual_private_profile.report fresh_before_parent_initialize=true,profile_writes_before_guard=0,actual_user_data_dir=expected_user_data_dir",
"raw_native_lifecycle": "receipt parent/phase/{started.json,ended.json,outer-owned-finally.json}. Start/end actual_pid and command match receipt. Start live_identity_exact or tracked_child_ended_before_initial_probe. End exit_code=0,engine_ended=true. Outer actual_captured_pids=[actual_pid],all_captured_ended=true,no cleanup errors or foreign signals. Raw version/argv/lifecycle must be actual Root capture.",
"strict_logs": "receipt parent/log: native version banner and exact role completion template, current source_sha256; full regression checks existing strict contracts for every current roster suite",
"typed_state": "Every .var raw Variant has .json typed tree: Dictionary entries=[typed key,typed value], Array items plus element_type/element_class, scalar type and exact var_to_str text. Required identity,original,after-live,before-members,after-members,writer/reader-process,writer/reader-checkpoint,writer/reader-minute-001 through 160,writer/reader-events. Preserve all fields and uncapped events. Driver also retains first-candidate,preview,migration diagnostics.",
"formal_members": "original/result/backup formal/{world.bin,manifest.json,thumbnail.png,journal.log}; raw artifact hashes bound to before/after typed member maps. Refusal preserves full original and pre-existing backup.",
"normal_OS_proof": "commit and exact source_map; input_method=native_os,setup=controlled_old_save; ordered preview,cancel,confirm,changed_source_rejection. Each action links input_receipt (method=native_os,event_type mouse|keyboard,target_pid positive int,timestamp_ns positive),screen_before/after,model_before/after,formal_before/after. Non-confirm formal JSON maps equal. Root independently assesses actual OS input/screens/state; signal-emitted UI is handler evidence only.",
"final_regression": "commit,directory,input,ended artifact paths. Input selected_source_map exact and roster runner.roster(root). Ended error null,cleanup_errors/guard_errors empty,ordered phases full roster each strict raw log,exit_code=0,engine_ended=true.",
"limits": "This documents implemented gates, not an acceptance reducer. Import/parse and config/environment runner-input are retained and hashed by driver; checker explicitly gates case phases. Root independently checks native version/config/environment, normal OS behavior and original conditions. Synthetic metadata cannot prove actual execution."
},
"example": {
"classification": "Synthetic machine-readable complete index from retained Proof; diagnostic ONLY, never native/OS/regression acceptance evidence.",
"construction": "tools/test_p08_migration_evidence.py Proof creates all linked bytes and reachable whole-check positive. Embedded documents illustrate receipts/lifecycle/OS/regression/typed records. Digests belong to the disposable synthetic fixture, not delivered acceptance artifacts; reproduce with Proof in a worktree-local disposable directory.",
"complete_example_generator": {
"source": "tools/test_p08_migration_evidence.py",
"source_raw_sha256": "fd9ef7ec63f53dfd5e04e261606c9303d01a2e6590e22a35fef2e35df1429280",
"class": "Proof",
"constructor": "Proof(Path(fresh_temporary_directory))",
"project_root_binding": "module ROOT resolved from unchanged generator inside this exact candidate source tree",
"generated_full_index": "proof.index",
"generated_representative_documents": "{path: json.loads((proof.path / path).read_text()) for path in representative_artifact_document_paths}",
"native_or_os_runs": 0
},
"index_top_level_fields": [
"schema",
"commit",
"source_map",
"spec_sha256",
"marker_contract_sha256",
"inputs",
"cases",
"conditions",
"artifacts",
"acceptance",
"collection_error",
"phases",
"os_proof",
"regression"
],
"representative_artifact_document_paths": [
"runs/off-positive-writer/off-positive-writer-receipt.json",
"runs/off-positive-reader/off-positive-reader-receipt.json",
"runs/off-positive-writer/off-positive-writer/started.json",
"runs/off-positive-writer/off-positive-writer/ended.json",
"runs/off-positive-writer/off-positive-writer/outer-owned-finally.json",
"os.json",
"os/preview/input.json",
"regression.json",
"regression/input.json",
"regression/ended.json",
"pairs/off-positive/identity.json",
"pairs/off-positive/writer-process.json",
"pairs/off-positive/before-members.json"
],
"fixture_config_inputs": {
"fixture_sources": {
"tests/s1/test_p08_combined_migration.gd": "9284a8cfb478b4c8d69f6d8166eec6c41107e3902029289b3c0e9ba48c370855",
"tests/s1/test_p08_combined_migration.gd.uid": "8c3a70d0ce619b8cb98dc003eb6c53a31f167a686179a3ffc105f7cd4d856da5",
"tests/fixtures/p08-02/README.md": "e88ca33fdb4e96602d1fb108d71a9c35b6fa054619ecf6f1396e9a6c5e0ebd98",
"tests/fixtures/p08-02/mixed_world.gd": "a23f8a686be1d77e4874b9956eef89be4756f6e5eb01cc62454c3845acc62c25",
"tests/fixtures/p08-02/reader.gd": "a760d0e45979d747dbd1f8710033bdce13287b00eb879d947d8378ff920ed1be",
"tests/fixtures/p08-02/writer.gd": "1a918b5509773b4b07a27d47ee44583b0eb5288138f7bf896088a7913773c260",
"tools/run_p08_mixed_migration.py": "7e86737e6354a4734726ba8d3171ad5f58d6c0380aba5a0fa3c57879d580e579",
"tools/check_p08_migration_evidence.py": "928353233bf85436a5aaf8c4f77f3f82472d94b8ad2646cb1b030baf92b3b5dc",
"tools/test_p08_migration_evidence.py": "fd9ef7ec63f53dfd5e04e261606c9303d01a2e6590e22a35fef2e35df1429280"
},
"native_runner_input_shape": {
"protocol": "p08-mixed-v1",
"commit": "<actual final commit>",
"selected_source_map": "<exact source map>",
"engine": "<actual executable>",
"engine_sha256": "<raw SHA>",
"owner_pid": "<actual collector PID>",
"default_player": "<protected profile record>",
"diagnostic_seed": 42588
},
"case_environment": {
"P08_PAIR_ROOT": "<absolute guarded pair output>",
"P08_OPERATIONS": "off|on",
"P08_CASE": "positive|refusal"
},
"timeouts": "unchanged: collection 900s, phase maximum 180s",
"formal_validation": "Root copies actual evidence into allocated build directory; --verify-only reads BUILD_OUTPUT_DIR/p08-evidence/index.json"
},
"purpose": "Synthetic Proof generator documents current schema. Historical reconstruction measurements are preserved in Git, not asserted for changed fixture.",
"previous_full_inline_record": {
"commit": "1545bd42d689a9a6382e2b003ee0550fa197f6e4",
"path": "docs/plans/original-completion-2026-10-02/execution/p08-02/implementation.json",
"sha256": "ae4a9f11c4e10a2be31d8fc6429577ff5f14f6097fae4f2d5a6a321937fefdac",
"bytes": 16946,
"hash_scope": "Git raw bytes",
"preservation": "Full previous metadata/example remains byte-preserved in Git; historical links and SHA values unchanged."
}
},
"historical_record": {
"path": "docs/plans/original-completion-2026-10-02/execution/p08-02/implementation-historical-6c7c724.json",
"sha256": "94321c2e924ef509738c8c4302c9e68854b9ce305830352d2dbb51d43f9ff34c",
"original_full_raw_sha256": "ab1fcf46ef73f2157f16f69394b4039a562c031fae8d407adca013a452226e2f",
"classification": "Reference to byte-preserved original full historical record in fixed Git commits and Root archive; not current canonical evidence"
},
"repair_r04": {
"seed": 42588,
"construction_cost": {
"gold": 7110,
"materials": 88
},
"signing_gold": 150,
"food_quantity": 8,
"food_gold": 24,
"initial": {
"gold": 5000,
"materials": 50
},
"previous_change_resources": {},
"derived_delta": {
"gold": 2284,
"materials": 38
},
"mismatch": "Previous zero added resources insufficient; no acceptance narrowed.",
"git_history_verification": "Both fixed Git references raw SHA matched ab1fcf46ef73f2157f16f69394b4039a562c031fae8d407adca013a452226e2f, 1082602 bytes",
"archive_verification": "Reuse Root supplied roundtrip evidence; archive not opened or executed."
},
"landing_repair": {
"input": "ROOT_REPAIR_INPUT-r04.json",
"ground": "initialized world paths within rank 1 bounds",
"upper": "complete each stair pair before ordering next floor, using maximum registered build_minutes",
"nearby_preflight": "rank bounds, registered stair definitions and existing completed logistics endpoints checked locally",
"acceptance_sources": "all 18 retained; no omissions",
"packet_limit_bytes": null,
"packet_measurement": "Final actual submitted Runner packet measurement remains Root responsibility; obsolete byte cap removed; no source omission or compression.",
"collection_timeout_seconds": 900
},
"metadata_sync": {
"source_commit": "1545bd42d689a9a6382e2b003ee0550fa197f6e4",
"current_tool_raw_sha256": {
"tools/check_p08_migration_evidence.py": "928353233bf85436a5aaf8c4f77f3f82472d94b8ad2646cb1b030baf92b3b5dc",
"tools/test_p08_migration_evidence.py": "fd9ef7ec63f53dfd5e04e261606c9303d01a2e6590e22a35fef2e35df1429280"
},
"source_map": "run_all_tests.py source_refs enumerates autoload/scripts/scenes/data/tests/assets/tools plus project.godot/export_presets.cfg/Makefile/AGENTS.md, excluding docs. Only docs changed, so source refs unchanged.",
"worker_validation": "JSON parse, Git raw SHA equality, generator Proof reference existence; no checker/native/Godot/full regression execution.",
"review_material_context_gap": "No .review-material or explicit complete 18-source Runner packet manifest provided in this checkout. Exact packet bytes cannot be claimed without Runner operation (prohibited); Root must measure complete actual submitted packet. No required source was removed."
}
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,47 @@
{
"plan_id": "P08-03",
"original_work": "通常パレットから支持・接続・不正位置・撤去・再建築を操作する。",
"original_acceptance": "拒否理由と実判定が一致し、パン・ズーム・保存再開後も同じ位置を扱う。",
"base_game_source": "c675bed91d694a18abbddac85013eb5b443bdca1",
"state": "audit_started",
"all_original_conditions": [
"normal palette support and connection positive/rejection",
"invalid-position rejection text equals actual domain result",
"normal palette demolition and rebuilding",
"world-cell identity after ordinary pan and zoom",
"same world cell, instance and judgement after formal save and separate process resume"
],
"actual_gap": "No normal production demolition command entry found in scenes/main; only runtime executor and test direct submit_command found. Add required normal UI entry before acceptance.",
"confirmed_existing_paths": {
"pan": "world_preview.gd436-440 pan_mode+non-Ctrl wheel vertical pan",
"zoom": "world_preview.gd441-442 non-pan-mode wheel, existing set_zoom clamp0.5..4.0",
"demolition_runtime": "simulation_runtime.gd register_command_executor demolish_facility plus occupancy/landing refusals",
"handler_test_example": "tests/ui/test_selection_departure.gd42 direct submit_command is not native OS evidence"
},
"coordinate_semantics": "same WORLD cell identity at its transformed screen coordinates; pixels intentionally move during pan/zoom. Do not require identical pixel coordinate to map to identical world cell across camera transforms.",
"reuse_candidates": [
"original current-source normal construction/placement rules for demonstrably original-matched existing facility types",
"P08-02 writer/reader/profile/strict-marker protocol and full retained source evidence",
"existing world_preview projection and pan-mode routines; existing UI tests remain handler-only evidence"
],
"not_reusable_as_acceptance": [
"P08-01 planned; all30 definition/placement acceptance not completed",
"unmapped13, black market, unresolved VIP high-floor/exterior turret semantics",
"deferred Ctrl-wheel and left-drag input",
"Windows same-release device evidence"
],
"necessary_next_work": [
"freeze true original spec/condition and allowed source paths",
"assign required normal UI change with plugin roles and Opus model decisions",
"implement necessary fixture/checker/negative cases and actual normal UI inputs",
"required affected/full final verification, independent review, exact integration, ledger closure"
],
"selected_codex_model": "gpt-6.1-sol",
"worker_started": false,
"denominator": {
"packages": 30,
"units": 88,
"partial_credit": false
},
"P08_package_completed": false
}
@@ -244,7 +244,7 @@
"facility_value_contracts_validation.json": "bf490a9ca585c48fc318e76c4a069ef244827d828d46e6415399f7710590dd16",
"performance_audit.json": "0b630b15a392c3e0366f1362bfe4ddacb968f915f54549f82e4d6fa315384762",
"progress_contract.json": "ccbdfce8c8365d5c13f59531955708834cce45acd0e136561c95295dfdb5df77",
"progress_snapshot.json": "5cbc33775c8782aa0208958e4516771f52fccbd172ad28272c92079fa788087e",
"progress_snapshot.json": "5a295402f314c81a2e93ed47a421832c6163de1de455c3023062b8e9dc6506bc",
"progress_validator_guard_checks.json": "72ee513fcf1cad85c24bfd0a4b472f425f6acf117928ece0f6b41e29018da627",
"progress_validator_guard_checks.r01.json": "14c26adffa5a1938241db4912e50ea54b660641ee6fee2e412d467dce14d0519",
"requirement_coverage.json": "8b5788b22ae8f49ea7e5cf048a5f0d82b54f6f193623465e0b70496b5aadd09d",
@@ -254,6 +254,6 @@
"validate_facility_value_contracts.py": "91640e2a76cd6cc9186f7b85c0bf379b24b6cac0d48962815235ee628e7ae43e",
"validate_plan.py": "23678227d9b3c556f1bd903f4b5b3147c4a82ce5085e10055481026803451b80",
"validator_update_checks.json": "f997d0f3de2cea29550840b1d5cb23647d64f81329de46758551e2b6c8fecc27",
"work_packages.json": "a1fea09afa85f58a1b1e2db8389c18b3601246c29faac315f712c0d8777bea98"
"work_packages.json": "cdf3807e6afdfe66d35f8fe12fa7b7677cdee1b21bf6aa88c6f6a46bcf554d30"
}
}
@@ -1,9 +1,9 @@
{
"schema_version": 1,
"integrated_at_jst": "2026-10-13T09:40:31.868894+09:00",
"scope": "P24-03 formally completed with exact submitted independent review and current main integration/final evidence; next P24-02 resumed, whole game incomplete",
"source_head": "a0f556e13512c868890726267483ec133bb54d7a",
"source_authority_note": "Production HEAD before this documentation checkpoint; P24 candidate9641ed52 and P18 candidate0084760e remain isolated and unadopted.",
"integrated_at_jst": "2026-10-14T00:38:01.089905+09:00",
"scope": "P08-02 formally completed; whole game and same-Windows release acceptance remain incomplete",
"source_head": "c675bed91d694a18abbddac85013eb5b443bdca1",
"source_authority_note": "Actual c675bed9 integrated source equals all1316 tested sources. Original d1c7 native/OS/full174 receipts reused only with exact source/spec/input/settings/marker applicability, not relabelled. Later docs are not new product validation.",
"immutable_history": {
"baseline.json": {
"sha256": "750bb3d313cc5e2ce0d4c79e563a995abd7a78f991dee1dd75c627877b02cd7b",
@@ -15,28 +15,21 @@
}
},
"latest_regression_at_evidence_time": {
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-final-candidate-r32-combined-root-acceptance-r01.json",
"bytes": 155964,
"sha256": "95f1cbecca2d3c6b341e806ab2ac4c77c2db20f4016f128dc9d5e722fd85c5ee",
"suites": 172,
"checks": 14769,
"parse_checks": 303,
"actual_native_phases": 174,
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p08-02-final-full174-native-r01/runner-ended.json",
"bytes": 4807811,
"sha256": "a0f1ae08f14101bbca16b723f544455c47079e7261e857c25235e76b58ed6d53",
"suites": 174,
"checks": 20184,
"parse_checks": 309,
"actual_native_phases": 176,
"failures": 0,
"source_map": {
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-final-candidate-r32-source-adoption-r03/source-after.json",
"bytes": 152598,
"sha256": "396df12825ae1addfa0bb099953f06bcd9bc8f1bb0c5f34f887e3b695209833e"
},
"source_map_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-final-candidate-r32-source-adoption-r03/source-after.json",
"source_map_sha256": "396df12825ae1addfa0bb099953f06bcd9bc8f1bb0c5f34f887e3b695209833e",
"source_map_entries": 1299,
"source_map_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p08-02-final-full174-native-r01/source-start.json",
"source_map_sha256": "0ccdada1710e4a508fe9488eab66f794dc6db478e117a16fb07c19abe7f7d3fd",
"source_map_entries": 1316,
"future_source_changes_auto_accepted": false,
"supplementary_union": true,
"old_failed_run_preserved": true,
"original_full_acceptance": false,
"windows_acceptance": false,
"Windows_acceptance": false,
"windows_acceptance": false,
"performance_acceptance": false
},
"known_condition_snapshot": {
@@ -150,13 +143,13 @@
},
"current_package_state_counts": {
"completed": 1,
"in_progress": 26,
"planned": 3
"in_progress": 27,
"planned": 2
},
"current_delivery_state_counts": {
"completed": 10,
"in_progress": 22,
"planned": 56
"completed": 11,
"in_progress": 25,
"planned": 52
},
"completed_current_deliveries": [
"P00-01",
@@ -165,6 +158,7 @@
"P04-02",
"P04-03",
"P05-01",
"P08-02",
"P14-01",
"P22-01",
"P23-01",
@@ -179,8 +173,8 @@
"同一Windows配布版の実機通常操作/保存再開",
"全施設/人物/ルート/エンド/図鑑/完成素材/実プレイ時間"
],
"new_engine_runs_by_this_integration": 2,
"production_game_source_edits_by_this_integration": 2,
"new_engine_runs_by_this_integration": 0,
"production_game_source_edits_by_this_integration": 0,
"save_preservation_adoption": {
"merge_path": "artifacts/original-completion-2026-10-02/p03-save-preservation-r02/merge.json",
"merge_sha256": "f6cc6e6590113e4d14bda1f5b8a1253672de1d8ac77ce91841c46c080a5eb068",
@@ -9708,14 +9702,163 @@
"execution": "the-tree-p06-01 Runner; recorded Claude decision, one Codex implementer",
"current_gate_status": "not implemented or executed; formal completion not accepted"
},
"next_closure_plan_id": "P24-02",
"next_closure_plan_id": "P08-03",
"p24_03_formal_closure": "docs/plans/original-completion-2026-10-02/execution/p24-03-formal-closure-r01/closure.json",
"new_engine_run_scope": "Supplemental positive metadata diagnostic r01 failed cleanup preparation/log isolation; r02 passed17checks unchanged source and entire default profile. No duplicated full game regression.",
"current_closure_targets": {
"current": "P24-02",
"candidate": "9641ed52def2ff8e5b0222449a4a83a1191e1d37",
"next_dependency": "P18-01",
"dependency_candidate": "0084760ee05a97adfcbd783a71161491f3629918",
"new_formally_completed_delivery_units": 0
"current": "P08-03",
"previous_formally_completed": "P08-02",
"previous_integration_commit": "c675bed91d694a18abbddac85013eb5b443bdca1",
"next_state": "P08-03 original/source audit started; missing normal demolition entry confirmed; no worker started"
},
"historical_regression_before_P08_02_formal_closure": {
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-final-candidate-r32-combined-root-acceptance-r01.json",
"bytes": 155964,
"sha256": "95f1cbecca2d3c6b341e806ab2ac4c77c2db20f4016f128dc9d5e722fd85c5ee",
"suites": 172,
"checks": 14769,
"parse_checks": 303,
"actual_native_phases": 174,
"failures": 0,
"source_map": {
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-final-candidate-r32-source-adoption-r03/source-after.json",
"bytes": 152598,
"sha256": "396df12825ae1addfa0bb099953f06bcd9bc8f1bb0c5f34f887e3b695209833e"
},
"source_map_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-final-candidate-r32-source-adoption-r03/source-after.json",
"source_map_sha256": "396df12825ae1addfa0bb099953f06bcd9bc8f1bb0c5f34f887e3b695209833e",
"source_map_entries": 1299,
"future_source_changes_auto_accepted": false,
"supplementary_union": true,
"old_failed_run_preserved": true,
"original_full_acceptance": false,
"windows_acceptance": false,
"Windows_acceptance": false,
"performance_acceptance": false
},
"current_P08_02_formal_completion": {
"plan_id": "P08-02",
"original_work": "混合建設、占有変更、役者の実位置、救護・物流・EVをまとめて移行する。",
"original_acceptance": "重複、孤立、消失がない。解消不能時は元配置とセーブを保つ。",
"state": "completed",
"completed_at_jst": "2026-10-14T00:38:01.089905+09:00",
"implementation_commit": "bf559632ddd938085702529d9dd6b7c878f4ebc7",
"integration_commit": "c675bed91d694a18abbddac85013eb5b443bdca1",
"native_os_regression_collected_commit": "d1c7ce27d21a77be87081e12d20e7c8dd6ffa353",
"all_selected_source_files": 1316,
"real_main_source_map_matches_tested_source": true,
"required_conditions_accepted": [
"mixed_construction",
"occupancy_change",
"actual_actor_positions",
"combined_rescue_logistics_ev",
"no_overlap_orphan_loss",
"unsolvable_preservation"
],
"registered_validation_review_integration_final_records": [
{
"kind": "validation",
"commit_sha": "d1c7ce27d21a77be87081e12d20e7c8dd6ffa353",
"artifact": "/Users/korizatou114/Library/Application Support/agent-control/the-tree-p08-02/runs/11b6c33568fe4876849d701f6c783cfb-validation.json",
"passed": 1,
"artifact_sha256": "f3b7929470d22feb7bed7634dc68f5675163ab967632341ff0ce03dfc2822330"
},
{
"kind": "validation",
"commit_sha": "bf559632ddd938085702529d9dd6b7c878f4ebc7",
"artifact": "/Users/korizatou114/Library/Application Support/agent-control/the-tree-p08-02/runs/473aac189bb644448cb69156ba16b944-validation.json",
"passed": 1,
"artifact_sha256": "9e1d7faa9b4d6d82595eb19e3025fdce88b5a10023aa623d21be777ee7a82c70"
},
{
"kind": "review",
"commit_sha": "bf559632ddd938085702529d9dd6b7c878f4ebc7",
"artifact": "/Users/korizatou114/Library/Application Support/agent-control/the-tree-p08-02/runs/48d7a4379d5246278f74bc5b5839a09e/result.json",
"passed": 1,
"artifact_sha256": "11626cc11d05b07decc2063307399e393b8820d1ab65006456000ceae538bd1b"
},
{
"kind": "integration",
"commit_sha": "c675bed91d694a18abbddac85013eb5b443bdca1",
"artifact": "/Users/korizatou114/Library/Application Support/agent-control/the-tree-p08-02/runs/b8de4d2308634eb9b9396cf8dc97a0e3-integration.json",
"passed": 1,
"artifact_sha256": "1b3a57331c902be22ad269a3993e622c6f3b7d2bbc1bc6300bbdb1c24225faac"
},
{
"kind": "final",
"commit_sha": "c675bed91d694a18abbddac85013eb5b443bdca1",
"artifact": "/Users/korizatou114/Library/Application Support/agent-control/the-tree-p08-02/runs/f7b8b0d7360e475c85702cc989e943ba-final.json",
"passed": 1,
"artifact_sha256": "1f329e0c492e93d9a3440bc7298e6a46c674a30d0aa25580b37b0b35cac3b13c"
}
],
"native_on_off_success_refusal_writer_reader": 8,
"normal_os_actions": [
"preview",
"cancel",
"confirm",
"changed_source_rejection"
],
"full_final_regression_suites": 174,
"actual_local_checker_tests": 4,
"independent_reviewer_model": "claude-opus-5-5",
"main_owner_authorization": "Explicit user main-update authorization recorded by Runner",
"low_findings_deferred": "DEFERRED_LOW_FINDINGS.json",
"checkout_text_alignment": "REAL_MAIN_CHECKOUT_BYTE_ALIGNMENT.json; original7 files fully retained",
"windows_same_release_device_acceptance": "not performed; remains required in global distribution/platform acceptance",
"whole_P08_package_completed": false,
"whole_game_completed": false,
"original_denominator": {
"packages": 30,
"delivery_units": 88,
"partial_credit": false
}
},
"current_P08_03_acceptance_audit": {
"plan_id": "P08-03",
"original_work": "通常パレットから支持・接続・不正位置・撤去・再建築を操作する。",
"original_acceptance": "拒否理由と実判定が一致し、パン・ズーム・保存再開後も同じ位置を扱う。",
"base_game_source": "c675bed91d694a18abbddac85013eb5b443bdca1",
"state": "audit_started",
"all_original_conditions": [
"normal palette support and connection positive/rejection",
"invalid-position rejection text equals actual domain result",
"normal palette demolition and rebuilding",
"world-cell identity after ordinary pan and zoom",
"same world cell, instance and judgement after formal save and separate process resume"
],
"actual_gap": "No normal production demolition command entry found in scenes/main; only runtime executor and test direct submit_command found. Add required normal UI entry before acceptance.",
"confirmed_existing_paths": {
"pan": "world_preview.gd436-440 pan_mode+non-Ctrl wheel vertical pan",
"zoom": "world_preview.gd441-442 non-pan-mode wheel, existing set_zoom clamp0.5..4.0",
"demolition_runtime": "simulation_runtime.gd register_command_executor demolish_facility plus occupancy/landing refusals",
"handler_test_example": "tests/ui/test_selection_departure.gd42 direct submit_command is not native OS evidence"
},
"coordinate_semantics": "same WORLD cell identity at its transformed screen coordinates; pixels intentionally move during pan/zoom. Do not require identical pixel coordinate to map to identical world cell across camera transforms.",
"reuse_candidates": [
"original current-source normal construction/placement rules for demonstrably original-matched existing facility types",
"P08-02 writer/reader/profile/strict-marker protocol and full retained source evidence",
"existing world_preview projection and pan-mode routines; existing UI tests remain handler-only evidence"
],
"not_reusable_as_acceptance": [
"P08-01 planned; all30 definition/placement acceptance not completed",
"unmapped13, black market, unresolved VIP high-floor/exterior turret semantics",
"deferred Ctrl-wheel and left-drag input",
"Windows same-release device evidence"
],
"necessary_next_work": [
"freeze true original spec/condition and allowed source paths",
"assign required normal UI change with plugin roles and Opus model decisions",
"implement necessary fixture/checker/negative cases and actual normal UI inputs",
"required affected/full final verification, independent review, exact integration, ledger closure"
],
"selected_codex_model": "gpt-6.1-sol",
"worker_started": false,
"denominator": {
"packages": 30,
"units": 88,
"partial_credit": false
},
"P08_package_completed": false
}
}
@@ -6742,7 +6742,7 @@
},
"legacy_state": "in_progress",
"state_scope": "package-level; completed means whole package accepted; partial implementation is not completion",
"current_summary": "P08-02候補bf559632で欠損診断fixtureと古い試験記録を修正。局所4試験・登録検証PASS。ソース一致でd1c7 native/OS/174回帰を再利用。独立Opus再レビュー中、統合未完。",
"current_summary": "P08-02を原6条件・独立Opus・登録統合/最終検証・main統合の証拠付きで正式完了。P08-01/P08-03が残るためP08全体はin_progress。",
"remaining_deliverables": [
{
"id": "P08-01",
@@ -6766,7 +6766,7 @@
"title": "旧配置の安全な変更",
"work": "混合建設、占有変更、役者の実位置、救護・物流・EVをまとめて移行する。",
"acceptance": "重複、孤立、消失がない。解消不能時は元配置とセーブを保つ。",
"state": "in_progress",
"state": "completed",
"evidence": [
{
"path": "docs/plans/original-completion-2026-10-02/execution/p08-02-audit-r06/NATIVE_STORAGE_COLLECTION_TRACE.json",
@@ -6831,24 +6831,58 @@
"candidate": "bf559632ddd938085702529d9dd6b7c878f4ebc7",
"linked_at_jst": "2026-10-14T00:24:08.968133+09:00",
"current_game_acceptance_inferred": false
},
{
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/execution/p08-02-audit-r07/FORMAL_COMPLETION.json",
"sha256_at_integration": "cefb4b200393872ee232fb338b904a33eefe2d839acf51ca8a4490debbf63f18",
"scope": "All original P08-02 conditions, independent review, exact main integration and final verification completed",
"candidate": "c675bed91d694a18abbddac85013eb5b443bdca1",
"linked_at_jst": "2026-10-14T00:38:01.089905+09:00",
"current_game_acceptance_inferred": false
},
{
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/execution/p08-02-audit-r07/RUNNER_FINAL_TRACEABILITY.json",
"sha256_at_integration": "253343356e75f4940e28a166066508bf6e37222686123ba8309520728343a8b4",
"scope": "Actual Runner contract, approval, implementation/integration SHA and passed evidence chain",
"candidate": "c675bed91d694a18abbddac85013eb5b443bdca1",
"linked_at_jst": "2026-10-14T00:38:01.089905+09:00",
"current_game_acceptance_inferred": false
},
{
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/execution/p08-02-audit-r07/REAL_MAIN_CHECKOUT_BYTE_ALIGNMENT.json",
"sha256_at_integration": "05c9ec5cb7be7a1c45adf705b555f124dcc0c673d24e3e9344feff4e2005cb99",
"scope": "Actual local main whole source map exact; original7 Kenney CRLF files fully archived",
"candidate": "c675bed91d694a18abbddac85013eb5b443bdca1",
"linked_at_jst": "2026-10-14T00:38:01.089905+09:00",
"current_game_acceptance_inferred": false
}
],
"progress_summary": "候補bf559632で診断fixture欠損と古い試験記録を修正。Opusの実レビューhigh1/medium1とRoot KeyError再現を根拠に、Opus指示でSolがr04を元12KB/SHA一致で復元し4Python試験55.197秒OKを生ログで確認した。製品等の選択ソース1316件・仕様・入力・marker完全一致に基づきd1c7ce27のnative全8/通常OS/最終174回帰を元の版記録を保持して再利用。bf559632登録検証integrity verified/不足0。別Opus5.5読取専用再レビュー中。正式完了・統合・Windows受入は未認定。修正7/上限なし。",
"remaining_gaps": [
"独立Opusが全6条件・通常OS・対象版適用性をレビューする。",
"統合候補を作成し、実際の統合版source map/spec/settingsと既存証拠の適用性を確認して登録統合検証を実行する。",
"許可済みmain統合と統合後最終確認・台帳反映まで完結する。",
"同一Windows配布版の実機条件は引き続き全体の未達。macOS証拠から認定しない。"
],
"updated_at_jst": "2026-10-14T00:24:08.968133+09:00"
"progress_summary": "候補bf559632の原6条件を実Opus5.5が独立受入。d1c7ce27のnative全8・通常OS4操作・最終174回帰は選択ソース1316件/仕様/入力/marker完全一致で再利用し、元版の記録を保持。試験入力欠損と旧PASS記載はSolが修正、実4Python試験55.197秒OKを生ログで確認。登録検証・統合検証・最終検証すべてPASS、c675bed9を許可済みmainへ統合。実mainの全ソース一致を確認、Kenney附属7資料の旧CRLF bytesを全文保全して検証済みGit版へ整合。Runner completed、P08-02正式完了。low3は記録し延期。P08全体・Windows同一配布版実機・ゲーム全体の完了は認定しない。",
"remaining_gaps": [],
"updated_at_jst": "2026-10-14T00:38:01.089905+09:00"
},
{
"id": "P08-03",
"title": "配置の通常操作受入",
"work": "通常パレットから支持・接続・不正位置・撤去・再建築を操作する。",
"acceptance": "拒否理由と実判定が一致し、パン・ズーム・保存再開後も同じ位置を扱う。",
"state": "planned",
"evidence": []
"state": "in_progress",
"evidence": [
{
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/execution/p08-03/CURRENT_ACCEPTANCE_AUDIT.json",
"sha256_at_integration": "1cfe0824e6e9889d8a086e3bf089718a785bff3230bfd311d7175181f759bf19",
"scope": "read-only original acceptance/source gap audit; not functional acceptance",
"current_game_acceptance_inferred": false
}
],
"progress_summary": "P08-02完了後の次1件として実Opusが選定。原work/acceptanceを保持して読取監査に着手し、通常UIの撤去入口欠損を現ソースで確認。pan_mode+Ctrlなしwheel、通常wheel zoomの実装経路を確認、延期ジェスチャーとは区別。P08-01完了/30施設受入という初回Opusの誤前提は真正台帳で訂正し撤回済み。配置契約が原本と一致する通常施設を現ソースから選ぶ。契約・担当確定、必要UI追加、fixture/checker・OS入力・独立レビュー・統合は未完、新規workerは未起動。",
"remaining_gaps": [
"freeze true original spec/condition and allowed source paths",
"assign required normal UI change with plugin roles and Opus model decisions",
"implement necessary fixture/checker/negative cases and actual normal UI inputs",
"required affected/full final verification, independent review, exact integration, ledger closure"
],
"updated_at_jst": "2026-10-14T00:50:37.842980+09:00"
}
],
"estimate_person_days_historical_2026_09_29": [
+23
View File
@@ -0,0 +1,23 @@
# P08-02 diagnostic fixture
Controlled fixture inputs are diagnostic, not production balance values.
Native collection and acceptance remain pending.
Seed: 42588. Registered construction costs for the 16 planned builds total
gold 7110 / materials 88; Gina signing costs 150 and eight raw food units cost
24. Initial resources are gold 5000 / materials 50. The previous fixture had
no change_resources delta (zero), short by gold 2284 / materials 38.
The fixture derives and records this deficit from the actual registry/catalogs
in identity.diagnostic_budget before using the existing change_resources command.
No price or production coefficient is changed.
Stair preparation proceeds from floor 1 through floor 3. Each pair finishes
using the maximum registered stair build_minutes before the next floor is
ordered. Ground landings use initialized world paths; upper landings are
created by completed stairs through build_facility, with a local path check
before each pair. Failed commands include kind, payload and result details.
The first legacy premium job progresses while the six actor/transport facets
are prepared. The second is paid and reserved immediately before saving, with
zero progress; the dormitory is already complete. All three stages share the
same migration batch and whole-state writer/reader comparisons.
+241
View File
@@ -0,0 +1,241 @@
extends RefCounted
## All seeds, actor IDs, positions, food quantities and schedules are diagnostic inputs.
var checks := 0
var failures := 0
var runtime: Variant
var clock: Variant
var state: Variant
var directory: String
var mode: String
var slot: String
var serial := 0
var events: Array = []
var identity: Dictionary = {}
const MEMBERS := [SaveService.WORLD_FILE, SaveService.MANIFEST_FILE, SaveService.THUMBNAIL_FILE, SaveService.JOURNAL_FILE]
func expect(ok: bool, label: String) -> bool:
checks += 1
if not ok:
failures += 1
push_error("P08 mixed: " + label)
return ok
func command(kind: StringName, payload: Dictionary) -> bool:
serial += 1
var result: CommandResult = runtime.submit_command(kind, payload, &"player", &"", 0, -1, StringName("p08.%d" % serial))
var label := String(kind) + ": " + result.message
if not result.is_success(): label += " payload=" + var_to_str(payload) + " details=" + var_to_str(result.details)
return expect(result.is_success(), label)
func registry(old: bool) -> void:
var paths: Array[String] = FacilityCatalog.FACILITY_PATHS + FacilityCatalog.INFRASTRUCTURE_FACILITY_PATHS + FacilityCatalog.RESCUE_FACILITY_PATHS
paths.append_array(["res://tests/fixtures/legacy_premium_room.tres", "res://tests/fixtures/legacy_staff_dormitory.tres"] if old else ["res://data/facilities/expansion/premium_room.tres", "res://data/facilities/expansion/staff_dormitory.tres"])
expect(runtime.definition_registry.rebuild_from_paths(paths)[&"valid"], "definition registry")
func build(id: StringName, cell: Vector3i, complete := true) -> bool:
if not command(&"build_facility", {&"definition_id":id, &"origin":cell}): return false
if complete: clock.advance_minutes(runtime.definition_registry.get_facility(id).build_minutes)
return true
func instance(id: StringName) -> FacilityInstance:
for room: FacilityInstance in runtime.facility_service.get_instances():
if room.definition_id == id: return room
return null
## Scalar text avoids loss of integer precision; raw Variant bytes accompany JSON.
func typed(value: Variant) -> Dictionary:
var result := {"type":type_string(typeof(value))}
if value is Dictionary:
result["entries"] = []
for key: Variant in value: result["entries"].append([typed(key),typed(value[key])])
elif value is Array:
result["element_type"] = value.get_typed_builtin()
result["element_class"] = String(value.get_typed_class_name())
result["items"] = []
for item: Variant in value: result["items"].append(typed(item))
else: result["text"] = var_to_str(value)
return result
func put(name: String, value: Variant) -> void:
var path := directory.path_join(name)
if not expect(not FileAccess.file_exists(path+".var") and not FileAccess.file_exists(path+".json"), "fresh proof "+name): return
var file := FileAccess.open(path+".var",FileAccess.WRITE)
if not expect(file != null,"Variant output"): return
file.store_buffer(var_to_bytes(value)); file.close()
file = FileAccess.open(path+".json",FileAccess.WRITE)
if not expect(file != null,"typed output"): return
file.store_string(JSON.stringify(typed(value))); file.close()
func get_proof(name: String) -> Variant:
return bytes_to_var(FileAccess.get_file_as_bytes(directory.path_join(name+".var")))
func capture(name: String, value: Variant) -> void:
put(mode+"-"+name,value)
if mode == "reader": expect(var_to_bytes(value) == var_to_bytes(get_proof("writer-"+name)),"whole cross-PID "+name)
func copy_package(source: String, destination: String) -> void:
expect(DirAccess.make_dir_recursive_absolute(destination) == OK,"package directory")
for member: String in MEMBERS:
var data := FileAccess.get_file_as_bytes(source.path_join(member))
if not expect(not data.is_empty() and not FileAccess.file_exists(destination.path_join(member)),"fresh complete member "+member): continue
var file := FileAccess.open(destination.path_join(member),FileAccess.WRITE)
if not expect(file != null,"member writable"): continue
file.store_buffer(data); file.close()
expect(data == FileAccess.get_file_as_bytes(destination.path_join(member)),"whole member copy verified")
func packages() -> Dictionary:
var hashes := {}
for suffix: String in ["",SaveService.MIGRATION_BACKUP_SUFFIX]:
for member: String in MEMBERS: hashes[suffix+"/"+member] = FileAccess.get_sha256(ProjectSettings.globalize_path(slot+suffix).path_join(member))
return hashes
func observe(event: SimulationDomainEvent) -> void: events.append(event.to_dictionary())
## Controlled diagnostic input; costs come only from registered domain definitions.
func prepare_diagnostic_budget() -> bool:
var planned: Array[StringName] = [&"warehouse",&"kitchen",&"infirmary",&"staff_door",&"reception",&"reception",&"guest_elevator",&"staff_dormitory",&"premium_room",&"premium_room",&"service_stairs",&"service_stairs",&"service_stairs",&"guest_stairs",&"guest_stairs",&"guest_stairs"]
var needed := {&"gold":0,&"materials":0}
var costs: Array = []
for id: StringName in planned:
var definition: FacilityDefinition = runtime.definition_registry.get_facility(id)
if not expect(definition != null,"budget definition "+String(id)): return false
costs.append({&"definition_id":id,&"cost":definition.construction_cost.duplicate(true)})
for resource: StringName in needed: needed[resource] += int(definition.construction_cost.get(resource,0))
var signing := int(runtime.mvp_content_catalog.staff_hire_payload(&"staff_gina").get(&"signing_cost",0))
var food := 8 * int(SupplyCatalog.get_item(SupplyCatalog.RAW_FOOD)[&"unit_price"])
needed[&"gold"] += signing + food
var deltas := {}
for resource: StringName in needed:
var deficit: int = maxi(0,int(needed[resource])-state.get_resource(resource))
if deficit > 0: deltas[resource] = deficit
identity[&"diagnostic_budget"] = {&"seed":42588,&"costs":costs,&"signing":signing,&"food_quantity":8,&"food_cost":food,&"needed":needed,&"initial":state.resources.duplicate(true),&"previous_change_resources":{},&"deltas":deltas}
return deltas.is_empty() or command(&"change_resources",{&"deltas":deltas})
func setup(operations: bool) -> bool:
registry(true)
if not prepare_diagnostic_budget(): return false
if operations and not expect(runtime.enable_production_operations().get(&"ok",false),"Operations enabled at Day 1 06:00"): return false
for row: Array in [[&"warehouse",Vector3i(-8,0,1)],[&"kitchen",Vector3i(2,0,1)],[&"infirmary",Vector3i(6,0,1)],[&"staff_door",Vector3i(0,0,1)],[&"reception",Vector3i(-6,0,0)],[&"reception",Vector3i(5,0,0)],[&"guest_elevator",Vector3i.ZERO]]:
if not build(row[0],row[1],false): return false
clock.advance_minutes(180)
# Completed stairs supply the next floor's landing through the domain projector.
# Ground-floor landings come from the initialized world; never inject path cells.
var stair_minutes: int = maxi(runtime.definition_registry.get_facility(&"service_stairs").build_minutes,runtime.definition_registry.get_facility(&"guest_stairs").build_minutes)
for y: int in [1,2,3]:
if not expect(runtime.path_service.has_cell(Vector3i(-9,y-1,1)) and runtime.path_service.has_cell(Vector3i(4,y-1,0)),"completed lower stair landings for floor %d" % y): return false
if not build(&"service_stairs",Vector3i(-9,y,1),false) or not build(&"guest_stairs",Vector3i(4,y,0),false): return false
clock.advance_minutes(stair_minutes)
if not build(&"staff_dormitory",Vector3i(-8,2,1)): return false
identity[&"dorm"] = instance(&"staff_dormitory").instance_id
if not build(&"premium_room",Vector3i(-6,2,0),false): return false
clock.advance_minutes(7)
identity[&"jobs"] = []
for job: ConstructionJob in runtime.construction_service.get_jobs():
if not job.is_terminal(): identity[&"jobs"].append(job.job_id)
if not expect(identity[&"jobs"].size() == 1,"one paid progressing job"): return false
var warehouse := instance(&"warehouse")
var kitchen := instance(&"kitchen")
if not expect(warehouse != null and kitchen != null,"completed logistics endpoints"): return false
if not command(&"hire_staff_candidate",{&"candidate_id":&"staff_gina"}): return false
if not command(&"set_staff_work_assignment",{&"staff_id":&"staff_gina",&"facility_id":warehouse.instance_id,&"template_id":&"DAY"}): return false
if not command(&"purchase_supplies",{&"warehouse_id":warehouse.instance_id,&"item_id":SupplyCatalog.RAW_FOOD,&"quantity":8}): return false
if not command(&"set_kitchen_production",{&"facility_id":kitchen.instance_id,&"enabled":true,&"target_stock":4}): return false
var cargo_ready := false
for minute: int in range(60):
clock.advance_minutes(1)
if not runtime.staff_service.get_staff(&"staff_gina").carried_inventory_id.is_empty(): cargo_ready = true; break
if not expect(cargo_ready,"real purchased cargo picked up"): return false
for id: StringName in [&"patient",&"carrier"]:
if not command(&"register_staff",{&"staff_id":id,&"role_id":&"porter",&"options":{&"current_cell":Vector3i(-3,0,1) if id == &"patient" else Vector3i(-1,0,1),&"health":0 if id == &"patient" else 100,&"state":StaffRuntime.State.AVAILABLE,&"role_tags":[&"medic"],&"permitted_task_tags":[&"rescue"]}}): return false
var carrying := false
for minute: int in range(6):
clock.advance_minutes(1)
for task: StaffTask in runtime.staff_service.get_tasks():
if task.task_type == &"rescue_transport" and task.state == StaffTask.State.MOVING:
carrying = true; identity[&"rescue_task"] = task.task_id
if carrying: break
if not expect(carrying,"actual rescue transport"): return false
for index: int in range(5):
if not command(&"spawn_guest",{&"guest_id":StringName("p08.passenger.%d" % index),&"guest_type_id":&"traveler",&"gold":100,&"options":{&"current_cell":Vector3i.ZERO,&"state":GuestRuntime.State.MOVING,&"state_entered_at":clock.absolute_minute-1,&"planned_exit_at":clock.absolute_minute+2000,&"path_handle":{&"target_cell":Vector3i(0,1,0)}}}): return false
clock.advance_minutes(1)
if not command(&"spawn_guest",{&"guest_id":&"p08.walker",&"guest_type_id":&"traveler",&"gold":100,&"options":{&"current_cell":Vector3i(4,0,0),&"state":GuestRuntime.State.MOVING,&"state_entered_at":clock.absolute_minute-1,&"planned_exit_at":clock.absolute_minute+2000,&"path_handle":{&"target_cell":Vector3i(4,3,0)}}}): return false
clock.advance_minutes(1)
identity[&"ev_requests"] = []
for trip: Dictionary in runtime.elevators.get_report()[&"trips"]: identity[&"ev_requests"].append(trip[&"request_id"])
identity[&"logistics_requests"] = []
for request: LogisticsRequest in runtime.logistics_requests.values():
if not request.is_terminal(): identity[&"logistics_requests"].append(request.request_id)
expect(not runtime.staff_service.get_staff(&"staff_gina").carried_inventory_id.is_empty(),"cargo in SAME save as patient and EV")
expect(runtime.staff_service.get_staff(&"patient").health == 0,"patient remains untreated")
var car: Dictionary = runtime.elevators.get_report()[&"shafts"][0]
expect(car[&"passenger_count"] == 4 and car[&"waiting_count"] == 1,"passengers and queue coexist")
expect(runtime.create_snapshot()[&"systems"][&"runtime"][&"movement_credits"].size() > 0,"fractional movement credit")
if not build(&"premium_room",Vector3i(5,2,0),false): return false
for candidate: ConstructionJob in runtime.construction_service.get_jobs():
if not candidate.is_terminal() and not identity[&"jobs"].has(candidate.job_id): identity[&"jobs"].append(candidate.job_id)
if not expect(identity[&"jobs"].size() == 2,"two paid active jobs"): return false
identity[&"starting_job"] = identity[&"jobs"][1]
for id: StringName in identity[&"jobs"]:
var job: ConstructionJob = runtime.construction_service.get_job(id)
expect(not job.is_terminal() and (job.progress == 0 if id == identity[&"starting_job"] else job.progress > 0) and not job.construction_cost.is_empty() and job.reserved_cells.size() == 6,"old-size paid starting/progressing jobs remain active")
return failures == 0
func invariant() -> void:
expect(runtime.staff_service.validate_invariants()[&"ok"],"staff ownership")
expect(SupplyLogisticsBridge.validate_crosslinks(runtime.logistics_requests,runtime.staff_service,runtime.inventory_service,runtime.facility_service),"cargo crosslinks")
var snap: Dictionary = runtime.create_snapshot()
expect(runtime.restore_snapshot(snap),"whole Runtime ownership/support/transport validation")
expect(var_to_bytes(snap) == var_to_bytes(runtime.create_snapshot()),"whole canonical typed state")
func run(tree: SceneTree, output: String, role: String, operations: bool, refusal: bool) -> Dictionary:
directory = output; mode = role
slot = "user://p08-%d/formal" % Time.get_ticks_usec()
tree.root.get_node("GameClock").set_paused(true); tree.root.get_node("GameClock").set_process(false)
tree.root.get_node("SimulationRuntime").configure_save_policy({&"enabled":false,&"daily_checkpoint_enabled":false})
runtime = load("res://autoload/simulation_runtime.gd").new()
clock = load("res://autoload/game_clock.gd").new(); state = load("res://autoload/game_state.gd").new()
clock.reset(1,6,0); state.reset(); expect(runtime.initialize(clock,state,42588)[&"valid"],"current initialization")
clock.set_paused(true); runtime.configure_save_policy({&"enabled":false,&"daily_checkpoint_enabled":false,&"auto_migrate":false})
if mode == "writer":
expect(DirAccess.make_dir_recursive_absolute(directory) == OK,"proof directory")
if not setup(operations): return finish()
registry(false)
var baseline: Dictionary = runtime.create_snapshot()
expect(SaveService.save_snapshot(slot,baseline)[&"ok"],"formal original saved")
if refusal:
var initial: Dictionary = runtime.migrate_facility_dimensions_at_path(slot)
expect(initial.get(&"ok",false) and initial.get(&"backup_created",false),"real prior migration backup")
expect(runtime.staff_service.create_task(&"maintenance",10,clock.absolute_minute,{&"target_entity_id":identity[&"dorm"],&"target_cell":Vector3i(-9,3,1),&"estimated_minutes":30},&"p08.late").is_success(),"later old entrance task")
if not command(&"register_staff",{&"staff_id":&"maintainer",&"role_id":&"porter",&"options":{&"current_cell":Vector3i(-9,1,1),&"state":StaffRuntime.State.AVAILABLE}}): return finish()
expect(runtime.staff_service.assign_task_to_staff(&"p08.late",&"maintainer",clock.absolute_minute).is_success(),"real task ownership")
expect(SaveService.save_snapshot(slot,runtime.create_snapshot())[&"ok"],"obstructed source saved")
put("identity",identity); put("original",runtime.create_snapshot())
copy_package(ProjectSettings.globalize_path(slot),directory.path_join("original/formal"))
var live: Dictionary = runtime.create_snapshot()
var before := packages(); put("before-members",before)
var first: Dictionary = runtime.prepare_facility_dimension_snapshot(identity[&"jobs"][0])
expect(first.get(&"ok",false),"earlier candidate independently migratable")
put("first-candidate",first)
var preview: Dictionary = runtime.preview_facility_dimensions_at_path(slot); put("preview",preview)
var result: Dictionary = runtime.migrate_facility_dimensions_at_path(slot,&"",String(preview.get(&"source_digest",""))); put("migration",result)
expect(var_to_bytes(live) == var_to_bytes(runtime.create_snapshot()),"live unchanged")
put("after-live",runtime.create_snapshot())
if refusal:
expect(not result.get(&"ok",true) and result.get(&"details",{}).get(&"rolled_back",false) and result.get(&"details",{}).get(&"facility_id",&"") == identity[&"dorm"],"later refusal rolls back earlier candidates")
expect(before == packages(),"original and existing backup unchanged")
else: expect(preview.get(&"ok",false) and result.get(&"ok",false) and result.get(&"backup_created",false),"positive whole batch")
put("after-members",packages())
copy_package(ProjectSettings.globalize_path(slot),directory.path_join("result/formal"))
copy_package(ProjectSettings.globalize_path(slot+SaveService.MIGRATION_BACKUP_SUFFIX),directory.path_join("backup/formal"))
else:
registry(false); identity = get_proof("identity")
copy_package(directory.path_join("result/formal"),ProjectSettings.globalize_path(slot))
copy_package(directory.path_join("backup/formal"),ProjectSettings.globalize_path(slot+SaveService.MIGRATION_BACKUP_SUFFIX))
var loaded := SaveService.load_snapshot(slot)
expect(loaded.get(&"ok",false) and runtime.restore_snapshot(loaded.get(&"snapshot",{})),"formal continuation restore")
expect(runtime.get_operations_report().get(&"enabled",false) == operations,"actual Operations mode")
invariant(); capture("checkpoint",runtime.create_snapshot())
expect(runtime.domain_events.subscribe(&"*",&"p08.uncapped",Callable(self,"observe")),"uncapped events")
for minute: int in range(160):
clock.advance_minutes(1); capture("minute-%03d" % (minute+1),runtime.create_snapshot())
capture("events",events)
for id: StringName in identity[&"jobs"]:
var job: ConstructionJob = runtime.construction_service.get_job(id)
expect(job.state == ConstructionJob.State.COMPLETED and runtime.facility_service.get_instance(job.facility_instance_id).occupied_cells.size() == (6 if refusal else 4),"paid job completes once with expected shape")
expect(runtime.staff_service.get_staff(&"patient").health == 100,"patient treated")
for id: StringName in identity[&"logistics_requests"]: expect(runtime.logistics_requests[id].state == LogisticsRequest.State.COMPLETED,"original cargo delivered")
for id: StringName in identity[&"ev_requests"]:
var count := 0
for event: Dictionary in events:
if event["event_type"] == "ELEVATOR_ARRIVED" and event["payload"].get(&"request_id",&"") == id: count += 1
expect(count == 1,"original EV request completes exactly once")
invariant()
put(mode+"-process",{&"pid":OS.get_process_id(),&"operations":operations,&"refusal":refusal,&"checks":checks,&"failures":failures})
return finish()
func finish() -> Dictionary:
runtime.free(); clock.free(); state.free()
return {"checks":checks,"failures":failures}
+1
View File
@@ -0,0 +1 @@
uid://dg5n4yme6rk4p
+7
View File
@@ -0,0 +1,7 @@
extends SceneTree
func _initialize() -> void: call_deferred("run")
func run() -> void:
var fixture := preload("res://tests/fixtures/p08-02/mixed_world.gd").new()
var result: Dictionary = fixture.run(self,OS.get_environment("P08_PAIR_ROOT"),"reader",OS.get_environment("P08_OPERATIONS") == "on",OS.get_environment("P08_CASE") == "refusal")
print("P08 mixed reader: %d checks, %d failures" % [result.checks,result.failures])
quit(0 if result.failures == 0 else 1)
+1
View File
@@ -0,0 +1 @@
uid://741t47oxl3ct
+7
View File
@@ -0,0 +1,7 @@
extends SceneTree
func _initialize() -> void: call_deferred("run")
func run() -> void:
var fixture := preload("res://tests/fixtures/p08-02/mixed_world.gd").new()
var result: Dictionary = fixture.run(self,OS.get_environment("P08_PAIR_ROOT"),"writer",OS.get_environment("P08_OPERATIONS") == "on",OS.get_environment("P08_CASE") == "refusal")
print("P08 mixed writer: %d checks, %d failures" % [result.checks,result.failures])
quit(0 if result.failures == 0 else 1)
+1
View File
@@ -0,0 +1 @@
uid://csw2850g6gjct
+15
View File
@@ -0,0 +1,15 @@
extends SceneTree
func _initialize() -> void: call_deferred("run")
func run() -> void:
var checks := 0
var failures := 0
for operations: bool in [false,true]:
for refusal: bool in [false,true]:
var output := ProjectSettings.globalize_path("user://p08-suite-%d-%s-%s" % [Time.get_ticks_usec(),operations,refusal])
for role: String in ["writer","reader"]:
var fixture := preload("res://tests/fixtures/p08-02/mixed_world.gd").new()
var result: Dictionary = fixture.run(self,output,role,operations,refusal)
checks += result.checks; failures += result.failures
if result.failures > 0: break
print("P08 combined migration: %d checks, %d failures" % [checks,failures])
quit(0 if failures == 0 else 1)
@@ -0,0 +1 @@
uid://bq08mixed02wld
+369
View File
@@ -0,0 +1,369 @@
#!/usr/bin/env python3
"""Read-only artifact integrity gate. Success NEVER accepts original P08-02."""
import argparse
import hashlib
import importlib.util
import json
import math
import os
from pathlib import Path
import re
import sys
sys.dont_write_bytecode = True
HERE = Path(__file__).resolve().parent
CONTRACT = 'docs/plans/original-completion-2026-10-02/execution/completion_marker_contracts.json'
SPEC_SHA = '19f02bb7912a4d7354e565186f02366fc1d4dd698468d26142e8204fd14ebfb0'
CONDITIONS = ('mixed_construction','occupancy_change','actual_actor_positions',
'combined_rescue_logistics_ev','no_overlap_orphan_loss','unsolvable_preservation')
MEMBERS = ('world.bin','manifest.json','thumbnail.png','journal.log')
CASES = ('off-positive','off-refusal','on-positive','on-refusal')
LABELS = ['checkpoint'] + ['minute-%03d' % n for n in range(1,161)] + ['events']
def sha(path): return hashlib.sha256(Path(path).read_bytes()).hexdigest()
def load(path): return json.loads(Path(path).read_bytes())
def module(name, path):
spec = importlib.util.spec_from_file_location(name,path)
obj = importlib.util.module_from_spec(spec); spec.loader.exec_module(obj); return obj
def decode(node):
"""Only decode for semantic checks; whole typed nodes remain comparison authority."""
t = node['type']
if t == 'Dictionary':
pairs = [(decode(k),decode(v)) for k,v in node['entries']]
keys = [json.dumps(k,sort_keys=True) for k,v in pairs]
if len(keys) != len(set(keys)): raise ValueError('duplicate typed dictionary key')
return {k:v for k,v in pairs}
if t == 'Array': return [decode(n) for n in node['items']]
text = node['text']
if t in ('String','StringName'): return json.loads(text.removeprefix('&'))
if t == 'int': return int(text)
if t == 'float': return float(text)
if t == 'bool':
if text not in ('true','false'): raise ValueError('invalid bool')
return text == 'true'
if t == 'Nil': return None
if t in ('Vector2i','Vector3i','Vector2','Vector3'):
match = re.fullmatch(re.escape(t)+r'\(([^()]*)\)',text)
parts = match.group(1).split(',') if match else []
integer = t.endswith('i')
number = r'[+-]?[0-9]+' if integer else r'[+-]?(?:[0-9]+(?:\.[0-9]*)?|\.[0-9]+)(?:[eE][+-]?[0-9]+)?'
if len(parts) != int(t[6]) or any(not re.fullmatch(number,x.strip()) for x in parts):
raise ValueError('invalid typed vector '+t)
values = [(int if integer else float)(x.strip()) for x in parts]
if not integer and not all(math.isfinite(x) for x in values):
raise ValueError('invalid typed vector '+t)
return values
# Preserve unfamiliar scalar types verbatim; never silently drop them.
return (t,text)
def indexed(rows, key):
result = {row[key]:row for row in rows}
if len(result) != len(rows): raise ValueError('duplicate '+key)
return result
def semantics(snapshot, identity, initial=False):
"""Independent ID/cell/reference checks on actual serialized Runtime state."""
r = snapshot['systems']['runtime']
guests = indexed(r['guests']['guests'],'guest_id')
staff = indexed(r['staff']['staff'],'staff_id')
if set(guests) & set(staff): raise ValueError('duplicate actor across domains')
jobs = indexed(r['construction']['jobs'],'job_id')
facilities = indexed(r['construction']['facilities'],'instance_id')
operational = indexed(r['facilities']['instances'],'instance_id')
owners = {k:v['occupied_cells'] for k,v in facilities.items()}
owners.update({k:v['reserved_cells'] for k,v in jobs.items() if v['state'] not in ('COMPLETED','CANCELLED')})
occupied = indexed(r['world']['occupancies'],'entity_id')
cells = set()
for owner,row in occupied.items():
actual = {tuple(c) for c in row['cells']}
if len(actual) != len(row['cells']) or cells & actual: raise ValueError('overlap occupancy')
cells |= actual
if owner not in owners or actual != {tuple(c) for c in owners[owner]}: raise ValueError('orphan occupancy/ownership')
if set(owners) != set(occupied): raise ValueError('lost occupancy owner')
for fid,facility in operational.items():
if fid not in facilities or facility['occupied_cells'] != facilities[fid]['occupied_cells']:
raise ValueError('operational/construction ownership mismatch')
for jid in identity['jobs']:
if jid not in jobs: raise ValueError('lost paid job')
starting = jid == identity['starting_job']
stage_ok = (jobs[jid]['progress'] == 0 and jobs[jid]['state'] == 'PLANNED') if starting else (jobs[jid]['progress'] > 0 and jobs[jid]['state'] == 'BUILDING')
if initial and (not stage_ok or not jobs[jid]['construction_cost'] or len(jobs[jid]['reserved_cells']) != 6):
raise ValueError('missing paid old-size progress/reservation')
if identity['starting_job'] not in identity['jobs']: raise ValueError('missing starting stage')
budget = identity['diagnostic_budget']
total = {key:sum(row['cost'].get(key,0) for row in budget['costs']) for key in ('gold','materials')}
total['gold'] += budget['signing'] + budget['food_cost']
deficit = {key:max(0,value-budget['initial'][key]) for key,value in total.items() if value > budget['initial'][key]}
if budget['seed'] != 42588 or budget['food_quantity'] != 8 or total != budget['needed'] or deficit != budget['deltas']:
raise ValueError('diagnostic resource derivation mismatch')
if len(identity['jobs']) < 2 or identity['dorm'] not in facilities: raise ValueError('mixed jobs/completed facility missing')
tasks = indexed(r['staff']['tasks'],'task_id')
if 'patient' not in staff or 'carrier' not in staff: raise ValueError('lost patient/carrier')
rescue = tasks[identity['rescue_task']]
if rescue['target_entity_id'] != 'patient' or rescue['rescue_facility_id'] not in facilities:
raise ValueError('rescue patient/destination reference')
if initial and (rescue['state'] != 'MOVING' or rescue['assigned_staff_id'] != 'carrier' or staff['patient']['health'] != 0):
raise ValueError('rescue is not actually in flight')
inventories = indexed(r['inventory']['inventories'],'owner_inventory_id')
requests = indexed(r['logistics_requests'],'request_id')
reservations = indexed(r['inventory']['reservations'],'reservation_id')
if not identity['logistics_requests']: raise ValueError('missing original food request')
for rid in identity['logistics_requests']:
req = requests[rid]
for endpoint in ('source_inventory_id','destination_inventory_id'):
value = req[endpoint]
if not value.startswith('facility.inventory:') or value.removeprefix('facility.inventory:') not in operational:
raise ValueError('orphan cargo endpoint')
state = req['state']
carrier_id = req['assigned_carrier_id']
if state == 'RESERVED' and carrier_id:
raise ValueError('RESERVED carrier contradiction')
if state in ('RESERVED','DELIVERING'):
ids = req['reservation_ids']
if not ids or len(ids) != len(set(ids)) or any(x not in reservations for x in ids):
raise ValueError(state+' missing/duplicate reservation')
totals = {}
for reservation_id in ids:
row = reservations[reservation_id]
if (row['requester_id'] != rid or row['owner_inventory_id'] != req['source_inventory_id']
or row['stack_id'] not in req['reserved_stack_ids']
or row['state'] != ('ACTIVE' if state == 'RESERVED' else 'CONSUMED')
or type(row['quantity']) is not int or row['quantity'] <= 0):
raise ValueError(state+' reservation crosslink mismatch')
totals[row['item_id']] = totals.get(row['item_id'],0)+row['quantity']
if totals != req['item_requirements'] or set(req['reserved_stack_ids']) != {reservations[x]['stack_id'] for x in ids}:
raise ValueError(state+' reservation quantity mismatch')
if state == 'RESERVED':
source_stacks = indexed(inventories.get(req['source_inventory_id'],{}).get('stacks',[]),'stack_id')
for reservation_id in ids:
row = reservations[reservation_id]; stack = source_stacks.get(row['stack_id'],{})
if (stack.get('item_id') != row['item_id'] or stack.get('quantity',0) < row['quantity']
or stack.get('reserved_quantity',0) < row['quantity']):
raise ValueError('RESERVED cargo/reservation mismatch')
else:
carrier = staff.get(carrier_id,{})
cargo = inventories.get(carrier.get('carried_inventory_id'),{})
cargo_totals = {}
for stack in cargo.get('stacks',[]):
cargo_totals[stack['item_id']] = cargo_totals.get(stack['item_id'],0)+stack['quantity']
if not carrier or cargo_totals != totals:
raise ValueError('DELIVERING carrier/cargo mismatch')
trips = indexed(r['elevators']['trips'],'request_id')
actors = set(guests) | set(staff)
for trip in trips.values():
actor = trip['actor_id']
if actor not in actors and actor.removeprefix('guest:').removeprefix('staff:') not in actors:
raise ValueError('orphan EV actor')
if initial:
if len(identity['ev_requests']) != 5 or not set(identity['ev_requests']) <= set(trips): raise ValueError('lost EV request')
if sum(len(c['boarded']) for c in r['elevators']['shafts']) != 4: raise ValueError('EV passengers/queue absent')
if 'p08.walker' not in guests or not r['movement_credits']: raise ValueError('mid-route guest/credit absent')
return r
def typed_differences(a, b, path=()):
if a == b: return []
if a.get('type') != b.get('type'): return [path]
if a['type'] == 'Dictionary':
aa = {str(decode(k)):(k,v) for k,v in a['entries']}; bb = {str(decode(k)):(k,v) for k,v in b['entries']}
if aa.keys() != bb.keys(): return [path]
differences = []
for k in aa:
if aa[k][0] != bb[k][0]: differences.append(path+(k,'@key-type'))
differences += typed_differences(aa[k][1],bb[k][1],path+(k,))
return differences
if a['type'] == 'Array' and a.get('element_type') == b.get('element_type') and a.get('element_class') == b.get('element_class'):
if len(a['items']) != len(b['items']): return [path]
return [p for i,(x,y) in enumerate(zip(a['items'],b['items'])) for p in typed_differences(x,y,path+(str(i),))]
return [path]
def migration_revisions(before, after, refusal):
"""WorldService._mark_dirty assigns domain counters the global epoch.
r04: (world, occupancy, support) (144,144,142) -> (150,150,150).
Only an actual occupancy rewrite can justify the support epoch delta.
Whole typed comparison still rejects every other unapproved field.
"""
old, new = before['world']['revisions'], after['world']['revisions']
keys = ('world','occupancy','support')
if any(type(row[k]) is not int or row[k] < 0 for row in (old,new) for k in keys):
raise ValueError('invalid revision epoch')
if refusal:
if any(old[k] != new[k] for k in keys):
raise ValueError('refusal revision changed')
return
changed = before['world']['occupancies'] != after['world']['occupancies']
if (not changed or not old['support'] <= old['world'] or not old['occupancy'] <= old['world']
or new['world'] <= old['world'] or new['occupancy'] != new['world']
or new['support'] != new['world'] or new['support'] < old['support']):
raise ValueError('support epoch/occupancy mismatch')
# Explicit geometry changes only. No actor, economy, request, event or route wildcard.
# This fixture deliberately places actors away from removed cells: NO route changes approved.
GEOMETRY = [
r'systems/runtime/world/occupancies/\d+/cells(?:/.*)?',
r'systems/runtime/world/dirty_cells(?:/.*)?',
r'systems/runtime/world/revisions/(world|occupancy)',
r'systems/runtime/construction/jobs/\d+/reserved_cells(?:/.*)?',
r'systems/runtime/construction/facilities/\d+/occupied_cells(?:/.*)?',
r'systems/runtime/facilities/instances/\d+/occupied_cells(?:/.*)?',
]
def check(project_root, evidence_dir):
root, evidence = Path(project_root).resolve(), Path(evidence_dir).resolve()
deficits = []
def need(ok, reason):
if not ok: deficits.append(reason)
def guarded(label, fn):
try: return fn()
except (KeyError,ValueError,TypeError,OSError,IndexError,AttributeError) as exc:
deficits.append(label+': '+str(exc)); return None
index = guarded('index',lambda:load(evidence/'index.json'))
if not isinstance(index,dict): return deficits or ['index is not an object']
def artifact(name):
if not isinstance(name,str) or Path(name).is_absolute() or '..' in Path(name).parts: raise ValueError('unsafe artifact path')
path = evidence/name
if not path.is_file() or any(p.is_symlink() for p in [path,*path.parents] if p != evidence.parent): raise ValueError('missing/aliased artifact '+name)
pin = index['artifacts'][name]
if pin != {'bytes':path.stat().st_size,'sha256':sha(path)}: raise ValueError('artifact hash '+name)
return path
def document(name): return load(artifact(name))
need(index.get('schema') == 'p08-evidence-v1','schema')
need(index.get('acceptance') == 'pending','integrity is not unit acceptance')
need(index.get('collection_error') is None,'collection failure')
def source_gate():
runner = module('p08_readonly_source',root/'tools/run_all_tests.py')
actual = {n:p['sha256'] for n,p in runner.source_refs(root).items()}
need(index['source_map'] == actual,'wrong/stale/incomplete final source map')
spec = load(root/'docs/spec/acceptance/P08-02.json')
need(index['spec_sha256'] == SPEC_SHA == hashlib.sha256((root/'docs/spec/acceptance/P08-02.json').read_text().strip().encode()).hexdigest(),'frozen spec SHA')
for name,pin in spec['current_source_pins'].items(): need(actual.get(name) == pin,'frozen production source '+name)
inputs = {str(p.relative_to(root)):sha(p) for p in (root/'docs/spec/inputs/p08-02').iterdir() if p.is_file()}
need(index['inputs'] == inputs,'frozen input map')
need(index['marker_contract_sha256'] == sha(root/CONTRACT),'marker contract source')
need(re.fullmatch('[0-9a-f]{40}',index['commit']) is not None,'submitted commit identity')
guarded('source',source_gate)
for name in index.get('artifacts',{}): guarded('artifact '+name,lambda name=name:artifact(name))
markers = module('p08_evidence_markers',root/'tools/strict_test_markers.py')
contracts = markers.load_contracts(root/CONTRACT)
pids = set()
def phase(name, role):
receipt = document(name); pid = receipt['actual_pid']
need(type(pid) is int and pid > 0 and pid not in pids,'distinct native PID '+name); pids.add(pid)
parent = str(Path(name).parent)
prefix = '' if parent == '.' else parent+'/'
folder = prefix+receipt['phase']+'/'
start,end,outer = [document(folder+n) for n in ('started.json','ended.json','outer-owned-finally.json')]
for row in (start,end):
need(row['actual_pid'] == pid and row['command'] == receipt['command'],'raw lifecycle PID/argv '+name)
need(end.get('exit_code') == 0 and end.get('engine_ended') is True,'ended exit '+name)
need(start.get('live_identity_exact') is True or start.get('tracked_child_ended_before_initial_probe') is True,'native Popen identity '+name)
need(outer['actual_captured_pids'] == [pid] and outer['all_captured_ended'] is True and not outer['outer_cleanup_errors'] and outer['foreign_process_or_group_signals'] == 0,'owned cleanup '+name)
native = receipt['native_process']
need(native['exit_code'] == 0 and native['helper_exit_code'] == 0 and native['timed_out'] is False and native['lifecycle_error'] is None,'native exit/errors '+name)
need(receipt['exit_code'] == 0 and receipt['engine_ended'] is True,'phase ended '+name)
if role:
test = 'tests/fixtures/p08-02/'+role+'.gd'
need(receipt['test'] == test and receipt['source_sha256'] == index['source_map'][test],'phase source '+name)
raw = artifact(prefix+receipt['log']).read_text()
parsed = markers.parse_raw(test,raw,{test:{'template':'P08 mixed '+role+': <checks> checks, <failures> failures'}},receipt['source_sha256'])
need(not parsed['errors'],'strict completion '+name+': '+str(parsed['errors']))
profile = receipt['actual_private_profile']['report']
need(profile['fresh_before_parent_initialize'] is True and profile['profile_writes_before_guard'] == 0 and profile['actual_user_data_dir'] == profile['expected_user_data_dir'],'guarded fresh profile '+name)
return receipt
def case_gate(case):
name = case['id']; prefix = case['directory']+'/'
need(name == case['operations']+'-'+case['kind'],'case identity '+name)
need(len(case['phases']) == 2,'writer and reader phases '+name)
receipts = [phase(n,r) for n,r in zip(case['phases'],('writer','reader'))]
def typed(name):
artifact(prefix+name+'.var')
return document(prefix+name+'.json')
identity = decode(typed('identity'))
original = typed('original'); after_live = typed('after-live')
need(original == after_live,'live partial batch '+name)
before_members,after_members = [decode(typed(n)) for n in ('before-members','after-members')]
for package in ('original','result','backup'):
for member in MEMBERS: artifact(prefix+package+'/formal/'+member)
for member in MEMBERS:
need(before_members['/'+member] == sha(artifact(prefix+'original/formal/'+member)),'original overwritten '+name+'/'+member)
need(after_members['/'+member] == sha(artifact(prefix+'result/formal/'+member)),'result member '+name+'/'+member)
need(after_members['.pre_migration.bak/'+member] == sha(artifact(prefix+'backup/formal/'+member)),'backup overwritten '+name+'/'+member)
refusal = case['kind'] == 'refusal'
if refusal: need(before_members == after_members,'refusal original/backup overwritten '+name)
source = semantics(decode(original),identity,True)
need(source['operations']['enabled'] == (case['operations']=='on'),'missing actual Operations mode '+name)
for role,receipt in zip(('writer','reader'),receipts):
proc = decode(typed(role+'-process'))
need(proc['pid'] == receipt['actual_pid'] and proc['failures'] == 0 and proc['operations'] == (case['operations']=='on') and proc['refusal'] == refusal,'fixture/native binding '+name+'/'+role)
checkpoint = typed('writer-checkpoint')
migrated = decode(checkpoint)['systems']['runtime']
migration_revisions(source,migrated,refusal)
if refusal: need(original == checkpoint,'partial earlier candidate '+name)
else:
for path in typed_differences(original,checkpoint):
support_epoch = path == ('systems','runtime','world','revisions','support')
need(support_epoch or any(re.fullmatch(pattern,'/'.join(path)) for pattern in GEOMETRY),'unapproved typed migration delta '+name+'/'+ '/'.join(path))
migrated = decode(checkpoint)['systems']['runtime']
jobs = indexed(migrated['construction']['jobs'],'job_id')
need(all(len(jobs[j]['reserved_cells']) == 4 for j in identity['jobs']),'positive batch not applied '+name)
for label in LABELS:
writer,reader = typed('writer-'+label),typed('reader-'+label)
need(writer == reader,'cross-PID full typed state/events '+name+'/'+label)
need(sha(artifact(prefix+'writer-'+label+'.var')) == sha(artifact(prefix+'reader-'+label+'.var')),'cross-PID raw Variant '+name+'/'+label)
if label != 'events': semantics(decode(writer),identity)
final = decode(typed('writer-minute-160'))['systems']['runtime']
need(indexed(final['staff']['staff'],'staff_id')['patient']['health'] == 100,'patient lost/untreated '+name)
final_requests = indexed(final['logistics_requests'],'request_id')
need(all(final_requests[i]['state']=='COMPLETED' for i in identity['logistics_requests']),'original cargo completion '+name)
events = decode(typed('writer-events'))
for rid in identity['ev_requests']:
need(sum(e['event_type']=='ELEVATOR_ARRIVED' and e['payload'].get('request_id')==rid for e in events)==1,'EV original request exactly once '+name+'/'+rid)
cases = index.get('cases',[])
need([c.get('id') for c in cases] == list(CASES),'missing/duplicate ON/OFF positive/refusal case')
for case in cases: guarded('case '+str(case.get('id')),lambda case=case:case_gate(case))
for condition in CONDITIONS:
expected = [c for c in CASES if condition != 'unsolvable_preservation' or c.endswith('refusal')]
need(index.get('conditions',{}).get(condition) == expected,'condition mapping '+condition)
def os_gate():
proof = document(index['os_proof'])
need(proof['commit'] == index['commit'] and proof['source_map'] == index['source_map'],'OS current candidate')
need(proof['input_method'] == 'native_os' and proof['setup'] == 'controlled_old_save','OS input provenance/setup')
actions = proof['actions']
need([a['action'] for a in actions] == ['preview','cancel','confirm','changed_source_rejection'],'OS actions missing')
for action in actions:
raw = document(action['input_receipt'])
need(raw['method'] == 'native_os' and raw['event_type'] in ('mouse','keyboard') and type(raw['target_pid']) is int and raw['target_pid'] > 0 and raw['timestamp_ns'] > 0,'fake OS signal')
for key in ('screen_before','screen_after','model_before','model_after','formal_before','formal_after'): artifact(action[key])
if action['action'] in ('preview','cancel','changed_source_rejection'):
need(document(action['formal_before']) == document(action['formal_after']),'OS formal preservation '+action['action'])
guarded('OS proof',os_gate)
def regression_gate():
proof = document(index['regression']); run_input = document(proof['input']); ended = document(proof['ended'])
need(run_input['selected_source_map'] == index['source_map'],'final regression source map')
need(proof['commit'] == index['commit'],'final regression commit')
need(not ended['error'] and not ended['cleanup_errors'] and not ended['guard_errors'],'regression failure')
runner = module('p08_regression_roster',root/'tools/run_all_tests.py')
roster = runner.roster(root)
need(run_input['roster'] == roster,'full final roster')
rows = [x for x in ended['phases'] if x.get('test')]
need([x['test'] for x in rows] == roster,'full final regression receipt')
for row in rows:
raw = artifact(proof['directory']+'/'+row['log']).read_text()
need(not markers.parse_raw(row['test'],raw,contracts,index['source_map'][row['test']])['errors'],'regression strict '+row['test'])
need(row['exit_code'] == 0 and row['engine_ended'] is True,'regression native exit '+row['test'])
guarded('final regression',regression_gate)
return sorted(set(deficits))
def main(argv=None):
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--verify-only',action='store_true',required=True)
parser.add_argument('--project-root',type=Path,default=HERE.parent)
args = parser.parse_args(argv)
build = os.environ.get('BUILD_OUTPUT_DIR')
deficits = ['BUILD_OUTPUT_DIR missing'] if not build else check(args.project_root,Path(build)/'p08-evidence')
print(json.dumps({'integrity':'deficient' if deficits else 'verified','deficits':deficits,
'acceptance':'pending','conditions':{c:'pending' for c in CONDITIONS}},ensure_ascii=False,indent=2))
return 1 if deficits else 0
if __name__ == '__main__': raise SystemExit(main())
+141
View File
@@ -0,0 +1,141 @@
#!/usr/bin/env python3
"""Root-only native collection. Does not run regression or claim acceptance."""
import argparse
import hashlib
import importlib.util
import json
import os
from pathlib import Path
import shutil
import subprocess
import sys
import time
sys.dont_write_bytecode = True
HERE = Path(__file__).resolve().parent
CONTRACT = 'docs/plans/original-completion-2026-10-02/execution/completion_marker_contracts.json'
CONDITIONS = ('mixed_construction', 'occupancy_change', 'actual_actor_positions',
'combined_rescue_logistics_ev', 'no_overlap_orphan_loss', 'unsolvable_preservation')
def module(name, path):
spec = importlib.util.spec_from_file_location(name, path)
obj = importlib.util.module_from_spec(spec)
spec.loader.exec_module(obj)
return obj
def absolute(value):
path = Path(value)
if not path.is_absolute():
raise argparse.ArgumentTypeError('absolute path required')
return path.resolve()
def collect(args):
root, out = args.project_root, args.output
r = module('p08_standard_runner', root/'tools/run_all_tests.py')
commit = subprocess.check_output(['git', '-C', str(root), 'rev-parse', 'HEAD'], text=True).strip()
r.require(commit == args.commit, 'actual final submitted commit required')
r.require(not out.exists(), 'fresh output; never overwrite earlier proof')
refs = r.source_refs(root)
outer = r.module('p08_owned_outer', r.SUPPORT/'owned_outer.py')
r.require(not outer.native.helper['live_engines'](), 'one native engine')
engine = shutil.which(args.godot)
r.require(engine is not None, 'native engine exists')
engine = str(Path(engine).resolve())
out.mkdir(parents=True)
stage = out/'stage'; stage.mkdir()
(out/'starters').mkdir(); (out/'bootstrap').mkdir()
for name, pin in r.read(r.SUPPORT/'bootstrap-scripts.json').items():
data = pin['text'].encode()
r.require(hashlib.sha256(data).hexdigest() == pin['sha256'], 'bootstrap pin')
(out/'bootstrap'/name).write_bytes(data)
for name, pin in refs.items():
target = stage/name; target.parent.mkdir(parents=True, exist_ok=True)
r.copy_source(Path(pin['path']), target)
r.require(r.sha(target) == pin['sha256'], 'whole copied source '+name)
expected = {n: {'bytes':v['bytes'], 'sha256':v['sha256']} for n,v in refs.items()}
selected = {'root_before':refs, 'map':{n:v['sha256'] for n,v in refs.items()}, 'timeout':180}
r.require(r.inventory(stage, stage=True) == expected, 'complete private source')
protected = r.default_player(root); public = (stage/'project.godot').read_bytes()
paths = ['res://'+n for n in sorted(refs) if n.endswith('.gd')]
r.write(out/'parse-paths.json', paths)
markers = r.module('p08_strict_markers', root/'tools/strict_test_markers.py')
contracts = markers.load_contracts(root/CONTRACT)
for role in ('writer','reader'):
name = 'tests/fixtures/p08-02/'+role+'.gd'
contracts[name] = {'test':name, 'template':'P08 mixed '+role+': <checks> checks, <failures> failures', 'required':True}
policy = r.read(r.SUPPORT/'suite-policy.json')
diagnostics = r.module('p08_diagnostics', r.SUPPORT/'diagnostic_gate.py')
owners = r.module('p08_owners', r.SUPPORT/'ordinary_proof_gate.py')
audio = r.module('p08_audio', r.SUPPORT/'audio_evidence_gate.py')
r.write(out/'runner-input.json', {'protocol':'p08-mixed-v1', 'commit':commit,
'selected_source_map':selected['map'], 'engine':engine, 'engine_sha256':r.sha(engine),
'owner_pid':os.getpid(), 'default_player':protected, 'diagnostic_seed':42588})
phases = []; previous = {}; cases = []; error = None
deadline = time.monotonic()+900
saved_env = {k:os.environ.get(k) for k in ('P08_PAIR_ROOT','P08_OPERATIONS','P08_CASE')}
def phase(label, test):
remaining = int(deadline-time.monotonic())
r.require(remaining >= (180 if label == 'import' else 1), '900s collection deadline')
selected['timeout'] = min(180,remaining)
phase_out = out/'runs'/label
phase_out.mkdir(parents=True)
(phase_out/'starters').mkdir(); (phase_out/'bootstrap').mkdir()
for original in (out/'bootstrap').iterdir():
r.copy_source(original,phase_out/'bootstrap'/original.name)
r.require(r.sha(original)==r.sha(phase_out/'bootstrap'/original.name),'bootstrap full copy')
r.write(phase_out/'parse-paths.json',paths)
row = r.execute_phase(engine, stage, phase_out, label, test, selected, expected, previous,
policy, contracts, paths, public, protected, root, outer, markers, diagnostics, owners, audio)
phases.append('runs/'+label+'/'+label+'-receipt.json')
r.require(not row['failed'], 'strict phase failed: '+label)
try:
phase('import', None); phase('parse', None)
for operations in ('off','on'):
for case in ('positive','refusal'):
name = operations+'-'+case; pair = out/'pairs'/name
os.environ.update(P08_PAIR_ROOT=str(pair), P08_OPERATIONS=operations, P08_CASE=case)
case_phases = []
preserved = {}
for role in ('writer','reader'):
label = name+'-'+role
test = 'tests/fixtures/p08-02/'+role+'.gd'
phase(label, test)
actual = r.inventory(pair)
r.require(all(actual.get(n) == pin for n,pin in preserved.items()), 'reader preserved every writer byte')
preserved = actual
case_phases.append(phases[-1])
cases.append({'id':name, 'operations':operations, 'kind':case,
'directory':'pairs/'+name, 'phases':case_phases, 'files':preserved})
except BaseException as caught:
error = type(caught).__name__+': '+str(caught)
finally:
cleanup, cleanup_errors = outer.finish_captured(outer.OWNED)
for key,value in saved_env.items():
if value is None: os.environ.pop(key, None)
else: os.environ[key] = value
r.require(r.source_refs(root) == refs and r.default_player(root) == protected, 'protected root/profile unchanged')
r.write(out/'runner-ended.json', {'error':error, 'cleanup':cleanup, 'cleanup_errors':cleanup_errors,
'phases':phases, 'formal_acceptance':False, 'native_Windows':'pending'})
inputs = {str(p.relative_to(root)):r.sha(p) for p in (root/'docs/spec/inputs/p08-02').iterdir() if p.is_file()}
# The collector is intentionally incomplete until Root supplies OS and regression artifacts.
r.write(out/'index.json', {'schema':'p08-evidence-v1', 'commit':commit,
'source_map':selected['map'], 'inputs':inputs, 'marker_contract_sha256':r.sha(root/CONTRACT),
'spec_sha256':hashlib.sha256((root/'docs/spec/acceptance/P08-02.json').read_text().strip().encode()).hexdigest(),
'cases':cases, 'phases':phases, 'conditions':{c:[x['id'] for x in cases if c != 'unsolvable_preservation' or x['kind']=='refusal'] for c in CONDITIONS},
'artifacts':{str(p.relative_to(out)):{'bytes':p.stat().st_size,'sha256':r.sha(p)}
for p in out.rglob('*') if p.is_file() and 'stage' not in p.relative_to(out).parts},
'os_proof':None, 'regression':None,
'acceptance':'pending', 'collection_error':error})
return 1 if error or cleanup_errors else 0
def main(argv=None):
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--project-root', type=absolute, required=True)
parser.add_argument('--output', type=absolute, required=True)
parser.add_argument('--commit', required=True)
parser.add_argument('--godot', default='godot')
parser.add_argument('--collect', action='store_true', required=True)
return collect(parser.parse_args(argv))
if __name__ == '__main__':
raise SystemExit(main())
+264
View File
@@ -0,0 +1,264 @@
#!/usr/bin/env python3
"""Synthetic evidence ONLY: disposable end-to-end check() positives and corruptions.
No Godot/OS execution, no actual acceptance proof. Mutations update hashes so the
semantic gate, not merely a stale digest, must reject invalid state.
"""
import copy
import hashlib
import json
from pathlib import Path
import tempfile
import unittest
import check_p08_migration_evidence as c
ROOT = Path(__file__).resolve().parent.parent
BANNER = 'Godot Engine v4.7.2.stable.official.ed1daf0bf - https://godotengine.org\n'
R04 = json.loads((ROOT/'docs/plans/original-completion-2026-10-02/execution/p08-02/ROOT_REPAIR_INPUT-r04.json').read_text())
ACTUAL = R04['actual_readonly_diagnostics']
REQUESTS = ACTUAL['CARGO_ENDPOINT_READONLY_DIAGNOSTIC.json'][0]['requests']
REVISIONS = ACTUAL['ACTUAL_WORLD_REVISION_DELTAS.json'][0]
def typed(value):
if isinstance(value,tuple): return {'type':'Vector3i','text':'Vector3i('+', '.join(map(str,value))+')'}
if isinstance(value,dict): return {'type':'Dictionary','entries':[[typed(k),typed(v)] for k,v in value.items()]}
if isinstance(value,list): return {'type':'Array','element_type':0,'element_class':'','items':[typed(x) for x in value]}
kind = 'Nil' if value is None else 'bool' if type(value) is bool else 'int' if type(value) is int else 'String'
return {'type':kind,'text':json.dumps(value)}
class Proof:
def __init__(self, path):
self.path = path
runner = c.module('p08_synthetic_source',ROOT/'tools/run_all_tests.py')
self.runner = runner
source = {n:p['sha256'] for n,p in runner.source_refs(ROOT).items()}
self.index = {'schema':'p08-evidence-v1','commit':'e196578c1a4ad2fdf84642565bd102e524be386f',
'source_map':source,'spec_sha256':c.SPEC_SHA,'marker_contract_sha256':c.sha(ROOT/c.CONTRACT),
'inputs':{str(p.relative_to(ROOT)):c.sha(p) for p in (ROOT/'docs/spec/inputs/p08-02').iterdir() if p.is_file()},
'cases':[],'conditions':{k:[x for x in c.CASES if k!='unsolvable_preservation' or x.endswith('refusal')] for k in c.CONDITIONS},
'artifacts':{},'acceptance':'pending','collection_error':None,'phases':[],
'os_proof':'os.json','regression':'regression.json'}
for number,name in enumerate(c.CASES): self.case(name,number)
self.os(); self.regression(); self.save()
def put(self,name,value):
path = self.path/name; path.parent.mkdir(parents=True,exist_ok=True)
path.write_bytes(value if isinstance(value,bytes) else json.dumps(value).encode())
self.index['artifacts'][name] = {'bytes':path.stat().st_size,'sha256':c.sha(path)}
def variant(self,prefix,name,value):
node = typed(value)
self.put(prefix+name+'.json',node)
# Deliberately not a native Variant: this is an isolated Python proof fixture.
self.put(prefix+name+'.var',json.dumps(node).encode())
def save(self): (self.path/'index.json').write_text(json.dumps(self.index))
def state(self,operations):
jobs = [{'job_id':j,'state':'PLANNED' if j=='j2' else 'BUILDING','progress':0 if j=='j2' else 1266,'reserved_cells':[(x,2,0) for x in range(offset,offset+6)],'construction_cost':{'gold':1}}
for j,offset in [('j1',0),('j2',10)]]
facilities = [{'instance_id':'dorm','occupied_cells':[[30,0,1]]},{'instance_id':'clinic','occupied_cells':[[31,0,1]]}]
facilities += [{'instance_id':'facility_00000005','occupied_cells':[(32,0,1)]},
{'instance_id':'facility_00000006','occupied_cells':[(33,0,1)]}]
guests = [{'guest_id':g} for g in ['p08.walker']+['g'+str(n) for n in range(5)]]
staff = [{'staff_id':'patient','health':0},{'staff_id':'carrier'},{'staff_id':'staff_gina','carried_inventory_id':'cargo:staff_gina'}]
r = {'operations':{'enabled':operations},'guests':{'guests':guests},'staff':{'staff':staff,'tasks':[
{'task_id':'rescue','target_entity_id':'patient','rescue_facility_id':'clinic','state':'MOVING','assigned_staff_id':'carrier'}]},
'construction':{'jobs':jobs,'facilities':facilities},'facilities':{'instances':copy.deepcopy(facilities)},
'world':{'revisions':copy.deepcopy(REVISIONS['original_world_revisions']),'occupancies':[{'entity_id':j['job_id'],'cells':copy.deepcopy(j['reserved_cells'])} for j in jobs]+
[{'entity_id':f['instance_id'],'cells':copy.deepcopy(f['occupied_cells'])} for f in facilities]},
'inventory':{'inventories':[{'owner_inventory_id':owner,'stacks':[{'stack_id':stack,'item_id':'ingredient/raw_food','quantity':4,'reserved_quantity':reserved}]} for owner,stack,reserved in
[('facility.inventory:facility_00000005','stack_00000001',4),('cargo:staff_gina','stack_00000002',0)]],
'reservations':[{'reservation_id':req['reservation_ids'][0],'requester_id':req['request_id'],
'owner_inventory_id':req['source_inventory_id'],'stack_id':'stack_00000001','item_id':'ingredient/raw_food',
'quantity':4,'state':'CONSUMED' if req['state']=='DELIVERING' else 'ACTIVE'} for req in REQUESTS]},
'logistics_requests':copy.deepcopy(REQUESTS),
'movement_credits':[{'credit':1000}],
'elevators':{'trips':[{'request_id':'ev'+str(n),'actor_id':'g'+str(n)} for n in range(5)],'shafts':[{'boarded':['g0','g1','g2','g3']}]}}
return {'systems':{'runtime':r}}
def phase(self,name,role,pid):
folder = 'runs/'+name+'/'; test = 'tests/fixtures/p08-02/'+role+'.gd'
command = ['synthetic-native','--script',test]
start = {'actual_pid':pid,'command':command,'live_identity_exact':True,'event':'ENGINE_STARTED','owner_pid':1,'monotonic_ns':1}
end = dict(start,event='ENGINE_ENDED',monotonic_ns=2,exit_code=0,engine_ended=True)
self.put(folder+name+'/started.json',start); self.put(folder+name+'/ended.json',end)
self.put(folder+name+'/outer-owned-finally.json',{'actual_captured_pids':[pid],'all_captured_ended':True,'outer_cleanup_errors':[],'foreign_process_or_group_signals':0})
self.put(folder+'raw.log',(BANNER+'P08 mixed '+role+': 1 checks, 0 failures\n').encode())
receipt = {'phase':name,'actual_pid':pid,'command':command,'exit_code':0,'engine_ended':True,'test':test,
'source_sha256':self.index['source_map'][test],'log':'raw.log',
'native_process':{'exit_code':0,'helper_exit_code':0,'timed_out':False,'lifecycle_error':None},
'actual_private_profile':{'report':{'fresh_before_parent_initialize':True,'profile_writes_before_guard':0,'actual_user_data_dir':'diagnostic-private-'+name,'expected_user_data_dir':'diagnostic-private-'+name}}}
self.put(folder+name+'-receipt.json',receipt)
return folder+name+'-receipt.json'
def case(self,name,number):
operations = name.startswith('on-'); refusal = name.endswith('refusal'); prefix = 'pairs/'+name+'/'
phases = [self.phase(name+'-'+role,role,100+2*number+i) for i,role in enumerate(('writer','reader'))]
self.index['cases'].append({'id':name,'operations':'on' if operations else 'off','kind':'refusal' if refusal else 'positive','directory':prefix[:-1],'phases':phases})
self.index['phases'] += phases
identity = {'starting_job':'j2','diagnostic_budget':{'seed':42588,'food_quantity':8,'food_cost':24,'signing':1,'costs':[{'cost':{'gold':2,'materials':1}}],'initial':{'gold':0,'materials':0},'needed':{'gold':27,'materials':1},'deltas':{'gold':27,'materials':1}},'jobs':['j1','j2'],'dorm':'dorm','rescue_task':'rescue','logistics_requests':['food'],'ev_requests':['ev'+str(n) for n in range(5)]}
identity['logistics_requests'] = [req['request_id'] for req in REQUESTS]
original = self.state(operations)
self.variant(prefix,'identity',identity); self.variant(prefix,'original',original); self.variant(prefix,'after-live',original)
before = {}; after = {}
for member in c.MEMBERS:
raw = ('synthetic '+member).encode()
for package in ('original','result','backup'): self.put(prefix+package+'/formal/'+member,raw)
before['/'+member] = after['/'+member] = hashlib.sha256(raw).hexdigest()
before['.pre_migration.bak/'+member] = after['.pre_migration.bak/'+member] = hashlib.sha256(raw).hexdigest()
self.variant(prefix,'before-members',before); self.variant(prefix,'after-members',after)
checkpoint = copy.deepcopy(original)
if not refusal:
r = checkpoint['systems']['runtime']
r['world']['revisions'] = copy.deepcopy(REVISIONS['checkpoint_world_revisions'])
for job in r['construction']['jobs']: job['reserved_cells'] = job['reserved_cells'][:4]
for row in r['world']['occupancies'][:2]: row['cells'] = row['cells'][:4]
events = [{'event_type':'ELEVATOR_ARRIVED','payload':{'request_id':rid}} for rid in identity['ev_requests']]
for i,role in enumerate(('writer','reader')):
self.variant(prefix,role+'-process',{'pid':100+2*number+i,'failures':0,'checks':1,'operations':operations,'refusal':refusal})
for label in c.LABELS:
state = copy.deepcopy(checkpoint)
if label == 'minute-160':
state['systems']['runtime']['staff']['staff'][0]['health'] = 100
for req in state['systems']['runtime']['logistics_requests']: req['state'] = 'COMPLETED'
self.variant(prefix,role+'-'+label,events if label=='events' else state)
def os(self):
proof = {'commit':self.index['commit'],'source_map':self.index['source_map'],'input_method':'native_os','setup':'controlled_old_save','actions':[]}
for name in ('preview','cancel','confirm','changed_source_rejection'):
row = {'action':name,'input_receipt':'os/'+name+'/input.json'}
self.put(row['input_receipt'],{'method':'native_os','event_type':'mouse','target_pid':500,'timestamp_ns':1})
for field in ('screen_before','screen_after','model_before','model_after','formal_before','formal_after'):
row[field] = 'os/'+name+'/'+field+'.json'; self.put(row[field],{'synthetic':'diagnostic'})
proof['actions'].append(row)
self.put('os.json',proof)
def regression(self):
contracts = c.module('p08_synthetic_markers',ROOT/'tools/strict_test_markers.py').load_contracts(ROOT/c.CONTRACT)
roster = self.runner.roster(ROOT); rows = []
for i,test in enumerate(roster):
contract = contracts[test]
def marker(template):
for key in ('checks','passed'): template = template.replace('<'+key+'>','1')
for key in ('failures','failed','skipped'): template = template.replace('<'+key+'>','0')
return template+'\n'
raw = BANNER+marker(contract['template'])
for auxiliary in contract.get('auxiliary',[]): raw += marker(auxiliary['template'])
if contract.get('json_report'):
raw += contract['json_report']['prefix']+json.dumps({'check_summary':{'total':1,'passed':1,'failed':0,'skipped':0},'status':'PASS','runtime_errors':[],'unmet_fixture_fields':[]})+'\n'
log = str(i)+'.log'; self.put('regression/'+log,raw.encode())
rows.append({'test':test,'log':log,'exit_code':0,'engine_ended':True})
self.put('regression/input.json',{'selected_source_map':self.index['source_map'],'roster':roster})
self.put('regression/ended.json',{'error':None,'cleanup_errors':[],'guard_errors':[],'phases':rows})
self.put('regression.json',{'commit':self.index['commit'],'directory':'regression','input':'regression/input.json','ended':'regression/ended.json'})
class EvidenceTests(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.temp = tempfile.TemporaryDirectory(prefix='p08-checker-')
cls.proof = Proof(Path(cls.temp.name))
cls.baseline = copy.deepcopy(cls.proof.index)
@classmethod
def tearDownClass(cls): cls.temp.cleanup()
def test_positive_reaches_whole_check(self):
self.assertEqual(c.check(ROOT,self.proof.path),[])
def test_strict_native_vectors(self):
for kind,good,expected in (
('Vector3i','Vector3i(0, -12, 6)',[0,-12,6]),
('Vector2i','Vector2i(-2, 3)',[-2,3]),
('Vector3','Vector3(1.5, -2e1, .25)',[1.5,-20,.25]),
('Vector2','Vector2(0, 1e-3)',[0,.001])):
with self.subTest(kind=kind):
self.assertEqual(c.decode({'type':kind,'text':good}),expected)
invalid = [good.replace(kind,'WrongVector'),good+'tail',good.replace(',',',,',1),
good[:good.rfind(',')]+')',good.replace(')',', 4)')]
if kind.endswith('i'): invalid += [good.replace('(', '(1.0,',1), kind+'(1.0, '+', '.join(['2']*(len(expected)-1))+')']
for text in invalid:
with self.subTest(text=text), self.assertRaisesRegex(ValueError,'invalid typed vector'):
c.decode({'type':kind,'text':text})
def test_r04_local_deficits_through_whole_check(self):
p = self.proof
def mutate_state(node, change):
state = c.decode(node); change(state['systems']['runtime']); return typed(state)
def bad_vector(node):
if node['type'] == 'Vector3i':
node['text'] = 'Vector3i(0, , 1)'; return True
children = ([n for pair in node['entries'] for n in pair] if node['type']=='Dictionary'
else node.get('items',[]))
return any(bad_vector(child) for child in children)
corruptions = [
('original','invalid typed vector',None),
('original','orphan cargo endpoint',lambda r:r['logistics_requests'][0].update(destination_inventory_id='facility.inventory:absent')),
('original','RESERVED missing/duplicate reservation',lambda r:r['inventory']['reservations'].pop()),
('original','DELIVERING carrier/cargo mismatch',lambda r:r['logistics_requests'][0].update(assigned_carrier_id='patient')),
('original','RESERVED carrier contradiction',lambda r:r['logistics_requests'][1].update(assigned_carrier_id='staff_gina')),
('original','DELIVERING reservation quantity mismatch',lambda r:r['inventory']['reservations'][0].update(quantity=3)),
('writer-checkpoint','support epoch/occupancy mismatch',lambda r:r['world']['revisions'].update(support=143)),
]
for label,message,change in corruptions:
path = 'pairs/off-positive/'+label+'.json'
original = (p.path/path).read_bytes()
try:
node = json.loads(original)
if change: node = mutate_state(node,change)
else: self.assertTrue(bad_vector(node))
p.put(path,node); p.save()
with self.subTest(message=message):
self.assertTrue(any(message in deficit for deficit in c.check(ROOT,p.path)),message)
finally:
p.put(path,original); p.index = copy.deepcopy(self.baseline); p.save()
for key in ('world','occupancy','support'):
path = 'pairs/off-refusal/writer-checkpoint.json'
original = (p.path/path).read_bytes()
try:
node = c.decode(json.loads(original)); revisions = node['systems']['runtime']['world']['revisions']
revisions[key] += 1
p.put(path,typed(node)); p.save()
with self.subTest(refusal_revision=key):
self.assertTrue(any('refusal revision changed' in deficit for deficit in c.check(ROOT,p.path)))
finally:
p.put(path,original); p.index = copy.deepcopy(self.baseline); p.save()
def test_corruptions_cannot_be_accepted(self):
p = self.proof
mutations = {
'duplicate_actor':lambda r:r['guests']['guests'].append(copy.deepcopy(r['guests']['guests'][0])),
'orphan_occupancy':lambda r:r['world']['occupancies'][0].update(entity_id='orphan'),
'lost_patient':lambda r:r['staff']['staff'].pop(0),
'lost_cargo':lambda r:r['inventory']['inventories'].pop(),
'lost_ev':lambda r:r['elevators']['trips'].pop(),
'missing_start_stage':lambda r:r['construction']['jobs'][1].update(state='BUILDING',progress=1),
}
path = 'pairs/off-positive/original.json'
original = (p.path/path).read_bytes()
for label,mutate in mutations.items():
with self.subTest(label=label):
node = c.decode(json.loads(original)); mutate(node['systems']['runtime'])
p.put(path,typed(node)); p.save()
self.assertTrue(c.check(ROOT,p.path),label)
p.put(path,original); p.index = copy.deepcopy(self.baseline); p.save()
path = 'pairs/off-positive/identity.json'
original = (p.path/path).read_bytes()
node = c.decode(json.loads(original)); node['diagnostic_budget']['deltas']['gold'] += 1
p.put(path,typed(node)); p.save()
self.assertTrue(c.check(ROOT,p.path),'resource_delta_mismatch')
p.put(path,original); p.index = copy.deepcopy(self.baseline); p.save()
paths = [('partial_batch','pairs/off-refusal/after-live.json'),('unequal_cross_pid','pairs/on-positive/reader-checkpoint.json'),
('overwritten_original','pairs/off-refusal/original/formal/world.bin'),('overwritten_backup','pairs/off-refusal/backup/formal/world.bin')]
for label,path in paths:
with self.subTest(label=label):
original = (p.path/path).read_bytes()
p.put(path,b'{}'); p.save(); self.assertTrue(c.check(ROOT,p.path),label)
p.put(path,original); p.index = copy.deepcopy(self.baseline); p.save()
for label in ('missing_on','wrong_source','stale_source','fake_os_signal','missing_phase','duplicate_pid'):
with self.subTest(label=label):
changed = None
if label=='missing_on': p.index['cases'] = p.index['cases'][:2]
elif label=='wrong_source': p.index['source_map']['autoload/simulation_runtime.gd'] = '0'*64
elif label=='stale_source': del p.index['source_map']['tools/check_p08_migration_evidence.py']
elif label=='missing_phase': p.index['cases'][0]['phases'].pop()
elif label=='fake_os_signal':
changed = 'os/preview/input.json'; original = (p.path/changed).read_bytes()
row = json.loads(original); row['method'] = 'signal_emitted'; p.put(changed,row)
else:
changed = p.index['cases'][0]['phases'][1]; original = (p.path/changed).read_bytes()
row = json.loads(original); row['actual_pid'] = 100; p.put(changed,row)
p.save(); self.assertTrue(c.check(ROOT,p.path),label)
if changed: p.put(changed,original)
p.index = copy.deepcopy(self.baseline); p.save()
if __name__ == '__main__': unittest.main()