Compare commits

..
45 changed files with 60314 additions and 21 deletions
@@ -1,3 +1,11 @@
## 現在の対象(2026-10-13・現版監査更新)
原30パッケージ/88成果、部分点なし。現在は正式10/着手24/予定54。P24-03は正式完了、MP-01-r02承認用資料は正式統合済みだが原88へ加点しない。P13-03既存最終修正は全7施設/84スロット/6分類が保全済み。P13/RP13の限定追加修正と正式host自己試験は直接許可待ちで、重複実装や無断上限変更をしない。
独立作業としてOpus判断に基づきP22-02の権利・形式契約へ着手。受入済614利用記録を再利用し、公式Kenney2packの全283同梱files、UI4音/Licenseをraw byte照合。現物296media中276の配布元権利を検証し、20の最終権利/creator条件を明示。BGMの内部recipe起源は見つかったが実聴/最終品質へ換算しない。全枠の選定/契約/欠損開示/実利用/必要検証/独立レビュー/統合が残る。完成素材欄0、全ゲーム未完を維持する。
証拠は[現版素材契約](checkpoints/p22-02-current-contract-r01/README.md)、[P13継続案](checkpoints/runner-p13-continuation-r03/CONTINUATION_PROPOSAL.md)。完了済MP作業場所の105filesを内容/属性保持で圧縮・共有化し、実空き約313MiBを回収した。以下の「現在」は各記録時点の履歴として保持する。
## 現在の成果と次対象(2026-10-13・P24-03完了→P24-02)
P24-03「選択と保存の受入」は提出4cefcff849d4dc1211caa5066e24bfae666cc2f4、最新main統合0a759f13aed03c05fd4a25ab4a2c26eefec94e3cで全7条件を正式完了。既存局所/全回帰/通常OS/同一保存の別プロセス再開証拠を再利用し、JSON版番号の正例17checksを追加。別Claude独立レビュー、最新main統合検証、最終検証、Runnercompleted/traceabilityまで成立。原30パッケージ/88成果単位、部分点なし。現在は正式10/着手22/予定56。全回帰173suite/14810checkやRunner支援の1件を成果数へ加算しない。
@@ -0,0 +1,17 @@
# P22-02 素材契約・権利の現版証拠
原workとacceptanceは変更しない。これは権利・形式・差替契約の現版実証であり、完成素材/原P22-02の受入ではない。原30パッケージ/88成果、部分点なしを維持する。
| 原条件 | 現在の証拠 | 不足 |
|---|---|---|
| Kenneyを先に確認して適合素材を選ぶ | 公式Tiny Town/Tiny Dungeon/Interface Sounds、既存2アトラスと4音の原配布byte一致 | 全利用枠の適合・選定と実際の利用 |
| 解像度・命名・差替契約 | packed192×176、16px/12×11/間隔0、nearest/mipmap無効、Theme/描画の現source SHA、provider名保持を記録 | 未制作枠の契約、レイアウト変更時の全参照・実表示証拠 |
| 出典とLicense | 2pack全283同梱files、UI4音/Licenseを既存manifestのZIP SHAとも一致確認。現media296中276はpublisher CC0証拠 | 20mediaの最終rights/creator記録。BGM2の内部合成recipeと同byte出力は発見したが最終権利/品質とは区別 |
| 完成枠は使用可能な資産と権利を持つ | 受入済614利用記録を正確に再利用し、完成資産欄0を維持 | 全完成枠の実利用・画面/聴感・独立受入。空集合でPASSしない |
| 欠損を代替表示で隠さない | provisional/code/fallbackを完成へ昇格しない。current-media-rightsで未知を明記 | 各原利用条件の実画面で欠損/未制作を把握し、必要な完成制作と接続を行う |
614は360施設利用枠+176人物利用枠+2状態群+76その他利用枠であり、614画像ではない。P22-01のhistorical source SHAと現sourceの適用性を混同しない。D08/D09の最終数量/内容はunknownのまま。
OpusはP22-02を独立候補に選定した。提案中のCC0限定は原条件ではないため採用しない。自己制作/別許諾も実際の証拠があれば対象とし、未知の権利を推測で成立させない。614の全枠を同数の完成画像へ変換する案も採用しない。全Godotの新しい禁止は設けず、容量と必要な検証範囲で実行を管理する。
新しいimplementation taskをまだ登録/起動しない。既存成果と条件不足を確認せず、必ず失敗すると分かるgateや重複workerを作らない。次の具体作業は各利用枠のsource/rights/形式の選定契約を固め、実制作が必要な未達を同じ原条件のまま実装・受入へ進める。P13/RP13の追加回数/限定正式host試験は別の直接許可を待ち、勝手に転用しない。
@@ -0,0 +1,10 @@
{
"decision": {
"action": "wait",
"task_id": "MP-01-r02",
"reason": "MP-01-r02は完了済みです。再実装・再開・repairはしません。現projectの受入1/1は完了済みで、実行できる登録タスクがないためwaitとします。\n\n【次の原成果の選定】P22-02(素材契約と権利)を推奨します。P22-02は未登録なので、オーナー/rootによる契約登録が必要です。登録まではwaitを続けます。\n\n【P07-01を選ばない理由】\n- D04係数とD05更新順序が未確定です。\n- 自然来客差、切替前後、途中保存の受入には新しいengine試験が必要です。空き約368MiBで重いGodot実行が禁止されているため、今は閉じられません。\n- P13/RP13とP18は個別cap追加の回答待ちです。この待ちを別タスクへ流用しません。\n- P24は上流が未実装で、手動保持操作は延期中です。\n\n【P22-02が原work全体を満たすかの判断】\n既存の権利/適合/サイズ/命名/差替の監査と契約記録だけでは不足です。原acceptanceの「完成枠に使用可能な資産と権利記録、欠損を代替表示で隠さない」を満たすには、次の両方が必要です。\n- 枠ごとに資産を選び、適用sourceの証拠を示すこと\n- 残った不足をすべて開示すること\n\n【完成枠が空集合のままPASSになるのを防ぐ方法(分母の追加・緩和はしません)】\n1. 枠集合は、独立受入済みのP22-01利用枠台帳(614利用記録)をSHA256で固定して使います。素材数を分母にはしません。記録数が614と一致しなければFAILです。\n2. 614記録のそれぞれに、次のどちらか一方だけを必ず付けます。\n - (a) 選定資産: path、出典pack、license、解像度、命名、差替手順、適用source参照(file:line)\n - (b) 不足: 理由と依存先(D08/D09、P24など)\n 空欄や重複があればFAILです。(a)が0件の場合もFAILです。\n3. 判定の上限: (b)の不足が1件でもあれば、P22-02の原成果はPASSにせず「部分/blocked」として報告します。不足を除外して分母を減らすこと、プレースホルダ表示を充足として数えることは禁止します。\n4. 権利: Kenneyのtiny_town、tiny_dungeon、input、UI音(CC0)について、同梱のlicense原文と元asset一覧を生バイトSHAでpinし、使用ファイルごとに突き合わせます。CC0でない資産や出典不明の資産はFAILです。\n5. D08/D09で数量が未確定の枠は(b)とし、確定済みとして扱いません。\n\n【製品変更の必要性】\n- 既存参照がすでに適合する枠は、監査と記録だけで閉じられます。\n- プレースホルダや未接続の枠は、Kenney素材の配置と参照差替えという製品変更が必要です。allowed_pathsは、登録時にオーナーが素材dirと該当参照に限定して定めてください。\n- 内容保持の圧縮は許可済みです。新しいGodot実行は禁止のため、検証はPNGヘッダ寸法、存在、命名規則、.tscn/.tres参照解決の静的検証にします。実行時の描画証明が必要な枠はblockedとし、PASS扱いにしません。\n\n【手順】1件の実装 → 正式な静的検証 → 別セッションの独立review → 台帳。完了の自己確定はしません。原30/88の順序変更はユーザー許可の範囲内です。範囲・受入・予算・capは変更しません。",
"codex_model": "gpt-6.1-sol",
"codex_model_reason": "今回の判断はwaitなので、workerは起動しません。登録後のP22-02も、固定した614記録の機械的な対応付け、license原文の照合、静的な寸法/参照検証が中心で、決定的に処理できる作業です。新しい数値設計、engine試験、高度な推論は不要です。厳格さは受入側のFAIL条件と独立reviewで担保します。そのため既定のSolで十分で、Astraを使う時間・使用量の上積みは正当化できません。"
},
"artifact": "/Users/korizatou114/Library/Application Support/agent-control/the-tree-mana-proposal-r02/runs/7262a1eb1ca84ec48ae9c5f8a2aa566e"
}
@@ -0,0 +1,52 @@
{
"recorded_at": "2026-10-13T08:40:24.862418+00:00",
"scope": "Located internal composition/code provenance; does not infer final rights or usability acceptance",
"bgm": [
{
"path": "assets/audio/bgm/tree_theme_front_candidate.wav",
"raw_sha256": "6df0a7af307327f703c9325f5ca2ac456888102d50ef1fa76bf4cdf19d2b86cb",
"same_as_recorded_composition_output": true,
"format_observed": {
"channels": 2,
"sample_rate": 44100,
"sample_width_bytes": 2,
"frames": 1881600
},
"origin_record": "artifacts/original-completion-2026-10-02/p22-original-paired-bgm-composition-candidate-r02/composition.json",
"origin_declaration": "Original score and additive synthesis in compose.py; no external sound recordings or quoted melodies",
"third_party_cc0_license_assigned": false,
"rights_display_final_accepted": false,
"hearing_final_accepted": false
},
{
"path": "assets/audio/bgm/tree_theme_back_candidate.wav",
"raw_sha256": "efe4cc1aa588661d73376720e4278427f7220ce93a5d446f198c5af607c141ca",
"same_as_recorded_composition_output": true,
"format_observed": {
"channels": 2,
"sample_rate": 44100,
"sample_width_bytes": 2,
"frames": 1881600
},
"origin_record": "artifacts/original-completion-2026-10-02/p22-original-paired-bgm-composition-candidate-r02/composition.json",
"origin_declaration": "Original score and additive synthesis in compose.py; no external sound recordings or quoted melodies",
"third_party_cc0_license_assigned": false,
"rights_display_final_accepted": false,
"hearing_final_accepted": false
}
],
"recipe_sha256": "ef03b3169e6a531cbb688e439854d3b981bb99164527f7a5617905c1c1908f81",
"score_sha256": "a544f12063dcb9faa26f00585a1619f18badb483f6fd6e24477d29268835458b",
"composition_readme_sha256": "e437ada7615dca54f017128192b8e931eb27b0f227354338f206d6da6767cc0c",
"icon": {
"path": "assets/icons/project_icon.svg",
"sha256": "25cc327f9d3bec159a48a11b85dddcbb614f1b673dfb975dc8ddc130f248a86b",
"width": "256",
"height": "256",
"external_embedded_image_or_href": false,
"first_observed_baseline_commit": "423fd6dd2e75da926e38b35ac8c435e462b168d9",
"creator_declaration_or_final_quality_accepted": false
},
"product_changed": false,
"original_completed_added": 0
}
@@ -0,0 +1,80 @@
{
"scope": "Observed contracts for existing selected candidates; derived source evidence, no new original spec or finished-asset acceptance",
"source_pins": {
"docs/ART_ASSET_PRODUCTION_SPECIFICATION.md": "8387c3fa94e9eef459a6de2638d0c065123f5654835c92ed87707f9f20928342",
"assets/kenney/README.md": "aaf2b3f1ba7b747709d5910389acaaca2beda2a1ca8eed12b0abfd81ddb3f1da",
"assets/kenney/tiny_town/Tilemap/tilemap_packed.png.import": "77e09885d6c47ddf6b08efc8530bc0e8d1a109a48474ea928f3fd905fa167aa3",
"assets/kenney/tiny_dungeon/Tilemap/tilemap_packed.png.import": "a9f6dea88271040a123f8dadc1e117c67084ccc855ef09ebc77b54ff8c0a693f",
"assets/themes/japanese_fantasy/visual-theme-v1.tres": "42e968ba5e35c228d3ff372f92a8e249ec3a743045be0a3ec158556944c0bc18",
"scripts/ui/visual_theme_profile.gd": "2a251a94d4a18c2ddd9e307cb810d1f327c12f2f15cd3bed91e65aa499258ceb",
"scripts/ui/pixel_tower_art.gd": "71df9b8400cb883a5bb1c89729f80c77e734df503fc54154be3e486adb8391df",
"scenes/main/world_preview.gd": "75d5b0bd23204f5a485540512e44b89e1d2a4596b368f70177a238ba078ff42d",
"scripts/ui/paired_bgm.gd": "a7fe9311f348975a380feced102702ad3ee91439b9511006f0ff6d29540f5836"
},
"pixel_atlas": {
"physical_dimensions": [
192,
176
],
"columns": 12,
"rows": 11,
"cell": [
16,
16
],
"gap": 0,
"filter_source": "scenes/main/world_preview.gd:94 TEXTURE_FILTER_NEAREST",
"mipmaps_generated": false,
"vendor_paths_preserved": [
"assets/kenney/tiny_town/Tilemap/tilemap_packed.png",
"assets/kenney/tiny_dungeon/Tilemap/tilemap_packed.png"
],
"selection_reason": "Existing 16px packs match current renderer density; generic props/units are candidates, not dedicated complete facility/character variants",
"replacement_dependencies": [
"VisualThemeProfile pixel_town_tiles/pixel_dungeon_tiles -> visual-theme-v1.tres ext_resources",
"PixelTowerArt.tile fixed 12 columns and 16px regions",
"Keep real transparency/import settings; changed atlas layout requires all affected mapping references and usability evidence",
"Game positions/actor IDs and save semantic identity must not be replaced by image file or atlas coordinates (existing derived art specification)"
],
"remaining": [
"Per-required-use suitability and completed visuals",
"Runtime/display/small-screen acceptance where applicable"
]
},
"ui_sounds": {
"source_manifest": "assets/audio/ui/source_manifest.json",
"existing_roles": [
"click",
"success",
"refusal",
"notification"
],
"files_preserve_provider_names": true,
"publisher_and_bytes_verified": true,
"replacement_requires": [
"Equivalent declared action role and updated manifest/raw license evidence",
"Committed action/foreground notification semantics and actual hearing proof"
],
"hearing_accepted": false
},
"paired_bgm": {
"source_recipe": "artifacts/original-completion-2026-10-02/p22-original-paired-bgm-composition-candidate-r02/compose.py",
"file_names": [
"tree_theme_front_candidate.wav",
"tree_theme_back_candidate.wav"
],
"format_observed": "44100Hz, 16-bit stereo PCM, same frame count; original recipe declaration located",
"candidate_suffix_not_removed": true,
"composition_or_source_proof_is_not_hearing_quality": true,
"pending": [
"Final rights/creator presentation",
"Actual listening, loop/crossfade/volume/lifecycle/device acceptance"
]
},
"unmade_slots": {
"finished_asset_from_accepted_inventory": 0,
"missing_not_hidden": true,
"no_provisional_asset_promoted": true,
"D08_D09_scope_quantity_unknown": true
}
}
@@ -0,0 +1,41 @@
{
"recorded_at": "2026-10-13T08:36:31.394324+00:00",
"scope": "Exact publisher provenance of 4 existing UI sounds and included License; not real hearing or whole P22-02 acceptance",
"official_page": "https://kenney.nl/assets/interface-sounds",
"official_archive_url": "https://kenney.nl/media/pages/assets/interface-sounds/fa43c1dd4d-1677589452/kenney_interface-sounds.zip",
"archive_bytes": 834536,
"archive_sha256": "f2193d072726d6758a5f7871b2dcc54dcce0d5c35c6f0a62f92549b327c81232",
"source_manifest_archive_sha_matches": true,
"license_byte_equal": true,
"assets": [
{
"repo_path": "assets/audio/ui/click_001.ogg",
"archive_member": "Audio/click_001.ogg",
"bytes": 4876,
"raw_sha256": "ccfb7fa0cccdd9faec0eb16033c732b1e308d139d80f799161495d58f7adcdb9",
"equal": true
},
{
"repo_path": "assets/audio/ui/confirmation_001.ogg",
"archive_member": "Audio/confirmation_001.ogg",
"bytes": 8968,
"raw_sha256": "063564703b6094d70718a3e787a55cc9141611e4ecd6b6637f8828f79b4a8c3a",
"equal": true
},
{
"repo_path": "assets/audio/ui/error_008.ogg",
"archive_member": "Audio/error_008.ogg",
"bytes": 9215,
"raw_sha256": "eba17ecb2a426bfd4a8a6acff5f8a86202b6424a77af0fd842e37809a1ab6d81",
"equal": true
},
{
"repo_path": "assets/audio/ui/bong_001.ogg",
"archive_member": "Audio/bong_001.ogg",
"bytes": 4848,
"raw_sha256": "d21d0f0b782445db579d11e2506b24cd1ac9d664ee33aeaf807761aa7b6fd710",
"equal": true
}
],
"product_modified": false
}
@@ -0,0 +1,12 @@
# RP13-01継続の限定変更案(未承認・未適用)
対象は既存RP13-01のみ。P13-03最終修正は保存済みで新しいゲーム実装を起動しない。
1. 個別修正上限2→3、使用済み2を保持し、追加1回を同一登録タスクの試験fixture修正に使う。差分案はproposed-isolated-rejection-fixture.patch。既存のAC-001重複登録で意図した負例に到達できない問題だけを直す。別fixtureプロジェクトを使い、P13-01/02拒否、回数・状態保持、提出なしを実際に検証する。Root prototype r02の当該1試験はPASS、元workerの2ファイルは未変更。
2. 正式runner-unitをRP13-01だけ信頼ホスト自己試験で実行する。登録argv(python -B -m unittest discover -s tests -p test_runner.py -v)、全55件以上、SHA/clean/scope/spec、実ログ・exit、独立レビュー、統合/最終を保持。外側Runner Seatbeltだけをこの試験で外し、試験内の実Seatbeltと実装workerのSeatbeltは保持する。providerや任意コマンドへの適用は禁止。親Runnerの通常verify/processを使い、config/contract/phase/candidateへの限定ガードとprovenanceを記録する。完成前にアダプター全文と制約を独立レビューへ渡す。
正式sandbox試験は55件中4 failure/11 error、通常ホスト診断ではfixtureに起因する2 errorだけが残る。ホスト診断を正式passedへ変換しない。現在の正式失敗receiptは保存し、認証・課金・並列・500000・ゲーム30/88・製品値を変更しない。
これは権限の一般化ではなく、上記project/task/validator/候補phaseだけの正式自己試験実行環境変更。既存のHOST_SELF_TEST_PROPOSAL.mdはこの範囲について未承認と明記している。既存許可は提出復旧と資料重複削減だけで、cap増加とホスト正式試験変更は含まれない。
承認後の順序: Opus開始判断→同じSol workerの限定修正→通常submit→限定ホスト正式validate→別Opusレビュー→Runner候補の統合/最終→P13既存submitted結果から復旧→P13正式validator/18負例→exact packet容量→別Opusレビュー→統合/最終→原成果台帳。
@@ -0,0 +1,9 @@
# P13-03 現行source適用性の更新案(未承認・未適用)
P13既存最終修正の共有参照を全展開し、旧提出7645c551と7施設/84スロット/6カテゴリの全記録が一致した。現在のproduction main c4cbc5feに対して53sourceを再照合し、scenes/main/main.gdだけが不一致。差分は既受入の選択manifest version型判定helperで、P13が検索する施設・通常入口・施設外内容観測は、SHAを除き全件一致する。原本/資産/ゲーム内容に新しい仕様や実装は不要。
提案はP13-03だけ個別修正上限2→3、使用済み2を保持し、追加1回で同じSol workerが台帳と読みやすい文書のmain.gd raw SHAを現版へ更新し、validation.jsonの出力hashを同期する。checker仕様や元分母は変更しない。差分案proposed-current-main-source-refresh.patch、照合結果current-main-refresh-proposal-metadata.jsonを参照。JSONは既存の一行直列化を維持するためpatchは大きく見えるが、論理変更はSHA1件のみ。
前提: RP13復旧候補が正式検証/独立レビュー/統合を満たした後、既存最終submitted結果を通常復旧提出し、このsource更新だけを同一タスクの追加repairとして実施する。新規登録、回数リセット、重複実装、ゲームsource変更、原本値決定は行わない。正式--verify-only/18負例、exact reviewer packet容量、別Opus独立レビュー、統合/最終、台帳反映は保持する。
状態処理の完成を内容制作の完成へ加点しない原P13-03の受入条件、全7施設/84スロット/6分類、unknown、全source証拠を維持する。現状は未提出・未受入で、権限や候補を勝手に変更しない。
@@ -0,0 +1,37 @@
{
"argv": [
"/opt/homebrew/Cellar/python@3.12/3.12.13_2/Frameworks/Python.framework/Versions/3.12/bin/python3.12",
"-B",
"-m",
"unittest",
"discover",
"-s",
"tests",
"-p",
"test_runner.py",
"-v"
],
"cwd": "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109",
"env_names": [
"AGY_CLI_DISABLE_AUTO_UPDATE",
"BROWSER_PROFILE_DIR",
"BUILD_OUTPUT_DIR",
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC",
"GIT_TERMINAL_PROMPT",
"HOME",
"LANG",
"LC_ALL",
"LOGNAME",
"MAC_CHROMIUM_TMPDIR",
"PATH",
"PORT",
"PYTHONDONTWRITEBYTECODE",
"TEMP",
"TERM",
"TEST_DATABASE_PATH",
"TMP",
"TMPDIR",
"USER"
],
"execution": "sandbox"
}
@@ -0,0 +1,265 @@
test_actual_sandbox_control_read_denied (test_runner.RunnerTests.test_actual_sandbox_control_read_denied) ... ok
test_actual_sandbox_write_boundary (test_runner.RunnerTests.test_actual_sandbox_write_boundary) ... FAIL
test_agy_pty_without_keychain_access (test_runner.RunnerTests.test_agy_pty_without_keychain_access) ... FAIL
test_approval_required (test_runner.RunnerTests.test_approval_required) ... ERROR
test_claude_broker_expiry_fails_closed (test_runner.RunnerTests.test_claude_broker_expiry_fails_closed) ... ok
test_claude_broker_never_returns_refresh_token (test_runner.RunnerTests.test_claude_broker_never_returns_refresh_token) ... ok
test_claude_profile_keeps_personal_keychain_denied (test_runner.RunnerTests.test_claude_profile_keeps_personal_keychain_denied) ... ok
test_dependency_gate (test_runner.RunnerTests.test_dependency_gate) ... ok
test_duplicate_acceptance_denied (test_runner.RunnerTests.test_duplicate_acceptance_denied) ... ok
test_failed_test_blocks_review (test_runner.RunnerTests.test_failed_test_blocks_review) ... ok
test_fixed_denominator_tamper_denied (test_runner.RunnerTests.test_fixed_denominator_tamper_denied) ... ok
test_full_deterministic_flow_with_simulated_review (test_runner.RunnerTests.test_full_deterministic_flow_with_simulated_review) ... ERROR
test_git_metadata_write_denied (test_runner.RunnerTests.test_git_metadata_write_denied) ... ok
test_integration_environment_retry_requires_existing_review (test_runner.RunnerTests.test_integration_environment_retry_requires_existing_review) ... ERROR
test_llm_budget_limit (test_runner.RunnerTests.test_llm_budget_limit) ... ok
test_llm_concurrency_limit (test_runner.RunnerTests.test_llm_concurrency_limit) ... ok
test_main_change_invalidates_approval (test_runner.RunnerTests.test_main_change_invalidates_approval) ... ERROR
test_missing_acceptance_test_denied (test_runner.RunnerTests.test_missing_acceptance_test_denied) ... ok
test_no_zero_cost_assumption (test_runner.RunnerTests.test_no_zero_cost_assumption) ... ok
test_node_output_drained_to_protected_logs (test_runner.RunnerTests.test_node_output_drained_to_protected_logs) ... FAIL
test_out_of_scope_edit_denied (test_runner.RunnerTests.test_out_of_scope_edit_denied) ... ok
test_overlapping_file_scope (test_runner.RunnerTests.test_overlapping_file_scope) ... ok
test_p13_document_dedup_leaves_existing_code_binary_and_other_paths (test_runner.RunnerTests.test_p13_document_dedup_leaves_existing_code_binary_and_other_paths) ... ok
test_p13_document_dedup_preserves_raw_source_and_other_diffs (test_runner.RunnerTests.test_p13_document_dedup_preserves_raw_source_and_other_diffs) ... ok
test_p13_document_dedup_rejects_missing_inconsistent_snapshots (test_runner.RunnerTests.test_p13_document_dedup_rejects_missing_inconsistent_snapshots) ... ok
test_p13_recovery_accepts_matching_forward_hashes (test_runner.RunnerTests.test_p13_recovery_accepts_matching_forward_hashes) ... ok
test_p13_recovery_rejects_bad_records_and_states (test_runner.RunnerTests.test_p13_recovery_rejects_bad_records_and_states) ... ok
test_p13_recovery_rejects_other_p13_tasks (test_runner.RunnerTests.test_p13_recovery_rejects_other_p13_tasks) ...
test_p13_recovery_rejects_other_p13_tasks (test_runner.RunnerTests.test_p13_recovery_rejects_other_p13_tasks) (task_id='P13-01') ... ERROR
test_p13_recovery_rejects_other_p13_tasks (test_runner.RunnerTests.test_p13_recovery_rejects_other_p13_tasks) (task_id='P13-02') ... ERROR
test_p13_recovery_rejects_source_pin_failure (test_runner.RunnerTests.test_p13_recovery_rejects_source_pin_failure) ... ok
test_p13_recovery_uses_normal_submission_and_downstream_gates (test_runner.RunnerTests.test_p13_recovery_uses_normal_submission_and_downstream_gates) ... ok
test_packet_capacity_guard_remains (test_runner.RunnerTests.test_packet_capacity_guard_remains) ... ok
test_path_traversal_denied (test_runner.RunnerTests.test_path_traversal_denied) ... ok
test_policy_tamper_denied (test_runner.RunnerTests.test_policy_tamper_denied) ... ok
test_provider_credentials_are_not_inherited (test_runner.RunnerTests.test_provider_credentials_are_not_inherited) ... ok
test_recover_releases_operation_not_task_locks (test_runner.RunnerTests.test_recover_releases_operation_not_task_locks) ... ok
test_repair_cannot_bypass_counter (test_runner.RunnerTests.test_repair_cannot_bypass_counter) ... ok
test_repair_limit (test_runner.RunnerTests.test_repair_limit) ... ok
test_resource_lock (test_runner.RunnerTests.test_resource_lock) ... ok
test_review_changes_blocks_candidate (test_runner.RunnerTests.test_review_changes_blocks_candidate) ... ERROR
test_review_refresh_requires_new_candidate (test_runner.RunnerTests.test_review_refresh_requires_new_candidate) ... ERROR
test_reviewer_packet_deduplicates_only_p13_03 (test_runner.RunnerTests.test_reviewer_packet_deduplicates_only_p13_03) ... ok
test_reviewer_sees_committed_tests_outside_worker_scope (test_runner.RunnerTests.test_reviewer_sees_committed_tests_outside_worker_scope) ... ERROR
test_runtime_isolation (test_runner.RunnerTests.test_runtime_isolation) ... ok
test_schema_rejects_false_success (test_runner.RunnerTests.test_schema_rejects_false_success) ... ok
test_secret_file_read_denied (test_runner.RunnerTests.test_secret_file_read_denied) ... ok
test_secret_scope_denied (test_runner.RunnerTests.test_secret_scope_denied) ... ok
test_spec_writes_denied (test_runner.RunnerTests.test_spec_writes_denied) ... ok
test_symlink_denied (test_runner.RunnerTests.test_symlink_denied) ... ok
test_timeout_is_not_pass (test_runner.RunnerTests.test_timeout_is_not_pass) ... FAIL
test_untracked_out_of_scope_denied (test_runner.RunnerTests.test_untracked_out_of_scope_denied) ... ok
test_validation_before_submission_denied (test_runner.RunnerTests.test_validation_before_submission_denied) ... ok
test_validation_python_does_not_depend_on_shell_path (test_runner.RunnerTests.test_validation_python_does_not_depend_on_shell_path) ... ERROR
test_worker_commit_denied (test_runner.RunnerTests.test_worker_commit_denied) ... ok
test_worker_has_mandatory_outer_sandbox (test_runner.RunnerTests.test_worker_has_mandatory_outer_sandbox) ... ok
test_wrong_candidate_denied (test_runner.RunnerTests.test_wrong_candidate_denied) ... ERROR
======================================================================
ERROR: test_approval_required (test_runner.RunnerTests.test_approval_required)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/tests/test_runner.py", line 302, in test_approval_required
self.candidate()
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/tests/test_runner.py", line 268, in candidate
self.submit(); self.r.validate("T001")
^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/runner/core.py", line 920, in validate
self.verify(task_id,wt,task["submitted"],"validation")
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/runner/core.py", line 905, in verify
require(passed,f"test_failed: {report}")
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/runner/core.py", line 50, in require
raise GateError(message)
runner.core.GateError: test_failed: /Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/.runtime/RP13-01/tmp/agent-control-test-7j4lj471/state/test/runs/13abf23717bc46d6af102cd7a7509787-validation.json
======================================================================
ERROR: test_full_deterministic_flow_with_simulated_review (test_runner.RunnerTests.test_full_deterministic_flow_with_simulated_review)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/tests/test_runner.py", line 292, in test_full_deterministic_flow_with_simulated_review
t=self.candidate()
^^^^^^^^^^^^^^^^
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/tests/test_runner.py", line 268, in candidate
self.submit(); self.r.validate("T001")
^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/runner/core.py", line 920, in validate
self.verify(task_id,wt,task["submitted"],"validation")
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/runner/core.py", line 905, in verify
require(passed,f"test_failed: {report}")
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/runner/core.py", line 50, in require
raise GateError(message)
runner.core.GateError: test_failed: /Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/.runtime/RP13-01/tmp/agent-control-test-et0phhsl/state/test/runs/cc9dc8f4ef9a45eba0d3a2b67abdf0df-validation.json
======================================================================
ERROR: test_integration_environment_retry_requires_existing_review (test_runner.RunnerTests.test_integration_environment_retry_requires_existing_review)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/tests/test_runner.py", line 306, in test_integration_environment_retry_requires_existing_review
self.submit(); self.r.validate("T001")
^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/runner/core.py", line 920, in validate
self.verify(task_id,wt,task["submitted"],"validation")
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/runner/core.py", line 905, in verify
require(passed,f"test_failed: {report}")
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/runner/core.py", line 50, in require
raise GateError(message)
runner.core.GateError: test_failed: /Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/.runtime/RP13-01/tmp/agent-control-test-ale6gvtj/state/test/runs/3a0f8b8706ad41889d250bd46152a27d-validation.json
======================================================================
ERROR: test_main_change_invalidates_approval (test_runner.RunnerTests.test_main_change_invalidates_approval)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/tests/test_runner.py", line 374, in test_main_change_invalidates_approval
t=self.candidate(); self.r.approve("T001",t["candidate"],t["main_base"],"owner")
^^^^^^^^^^^^^^^^
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/tests/test_runner.py", line 268, in candidate
self.submit(); self.r.validate("T001")
^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/runner/core.py", line 920, in validate
self.verify(task_id,wt,task["submitted"],"validation")
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/runner/core.py", line 905, in verify
require(passed,f"test_failed: {report}")
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/runner/core.py", line 50, in require
raise GateError(message)
runner.core.GateError: test_failed: /Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/.runtime/RP13-01/tmp/agent-control-test-qp92ql5k/state/test/runs/f2b55e7065dc45bab577059b9b2a0631-validation.json
======================================================================
ERROR: test_p13_recovery_rejects_other_p13_tasks (test_runner.RunnerTests.test_p13_recovery_rejects_other_p13_tasks) (task_id='P13-01')
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/tests/test_runner.py", line 136, in test_p13_recovery_rejects_other_p13_tasks
self.r.add(dict(self.contract, id=task_id))
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/runner/core.py", line 456, in add
require(not any(set(c["acceptance_ids"]) & set(contract["acceptance_ids"]) for c in existing), "同一受入項目の重複タスクは禁止")
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/runner/core.py", line 50, in require
raise GateError(message)
runner.core.GateError: 同一受入項目の重複タスクは禁止
======================================================================
ERROR: test_p13_recovery_rejects_other_p13_tasks (test_runner.RunnerTests.test_p13_recovery_rejects_other_p13_tasks) (task_id='P13-02')
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/tests/test_runner.py", line 136, in test_p13_recovery_rejects_other_p13_tasks
self.r.add(dict(self.contract, id=task_id))
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/runner/core.py", line 456, in add
require(not any(set(c["acceptance_ids"]) & set(contract["acceptance_ids"]) for c in existing), "同一受入項目の重複タスクは禁止")
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/runner/core.py", line 50, in require
raise GateError(message)
runner.core.GateError: 同一受入項目の重複タスクは禁止
======================================================================
ERROR: test_review_changes_blocks_candidate (test_runner.RunnerTests.test_review_changes_blocks_candidate)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/tests/test_runner.py", line 387, in test_review_changes_blocks_candidate
self.submit(); self.r.validate("T001")
^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/runner/core.py", line 920, in validate
self.verify(task_id,wt,task["submitted"],"validation")
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/runner/core.py", line 905, in verify
require(passed,f"test_failed: {report}")
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/runner/core.py", line 50, in require
raise GateError(message)
runner.core.GateError: test_failed: /Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/.runtime/RP13-01/tmp/agent-control-test-ek5j0rrq/state/test/runs/ccbdbadd674d471790b58dfccc000502-validation.json
======================================================================
ERROR: test_review_refresh_requires_new_candidate (test_runner.RunnerTests.test_review_refresh_requires_new_candidate)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/tests/test_runner.py", line 355, in test_review_refresh_requires_new_candidate
self.candidate()
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/tests/test_runner.py", line 268, in candidate
self.submit(); self.r.validate("T001")
^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/runner/core.py", line 920, in validate
self.verify(task_id,wt,task["submitted"],"validation")
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/runner/core.py", line 905, in verify
require(passed,f"test_failed: {report}")
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/runner/core.py", line 50, in require
raise GateError(message)
runner.core.GateError: test_failed: /Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/.runtime/RP13-01/tmp/agent-control-test-9gx5fk5x/state/test/runs/fbd882e8b90a4176bdc634ffbc2b8610-validation.json
======================================================================
ERROR: test_reviewer_sees_committed_tests_outside_worker_scope (test_runner.RunnerTests.test_reviewer_sees_committed_tests_outside_worker_scope)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/tests/test_runner.py", line 347, in test_reviewer_sees_committed_tests_outside_worker_scope
self.r.validate("T001")
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/runner/core.py", line 920, in validate
self.verify(task_id,wt,task["submitted"],"validation")
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/runner/core.py", line 905, in verify
require(passed,f"test_failed: {report}")
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/runner/core.py", line 50, in require
raise GateError(message)
runner.core.GateError: test_failed: /Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/.runtime/RP13-01/tmp/agent-control-test-klgcd5r6/state/test/runs/5240f0471f874dbbb4e4b6e4e93e49dd-validation.json
======================================================================
ERROR: test_validation_python_does_not_depend_on_shell_path (test_runner.RunnerTests.test_validation_python_does_not_depend_on_shell_path)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/tests/test_runner.py", line 319, in test_validation_python_does_not_depend_on_shell_path
self.r.validate("T001")
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/runner/core.py", line 920, in validate
self.verify(task_id,wt,task["submitted"],"validation")
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/runner/core.py", line 905, in verify
require(passed,f"test_failed: {report}")
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/runner/core.py", line 50, in require
raise GateError(message)
runner.core.GateError: test_failed: /Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/.runtime/RP13-01/tmp/agent-control-test-i2v7e5pu/state/test/runs/11dd6edca7c147729690e768086ed4ce-validation.json
======================================================================
ERROR: test_wrong_candidate_denied (test_runner.RunnerTests.test_wrong_candidate_denied)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/tests/test_runner.py", line 370, in test_wrong_candidate_denied
t=self.candidate()
^^^^^^^^^^^^^^^^
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/tests/test_runner.py", line 268, in candidate
self.submit(); self.r.validate("T001")
^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/runner/core.py", line 920, in validate
self.verify(task_id,wt,task["submitted"],"validation")
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/runner/core.py", line 905, in verify
require(passed,f"test_failed: {report}")
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/runner/core.py", line 50, in require
raise GateError(message)
runner.core.GateError: test_failed: /Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/.runtime/RP13-01/tmp/agent-control-test-p6512mu6/state/test/runs/261f9be981534152b1a1673f67d84a72-validation.json
======================================================================
FAIL: test_actual_sandbox_write_boundary (test_runner.RunnerTests.test_actual_sandbox_write_boundary)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/tests/test_runner.py", line 472, in test_actual_sandbox_write_boundary
self.assertEqual(permitted.returncode,0,permitted.stderr)
AssertionError: 71 != 0 : b'sandbox-exec: sandbox_apply: Operation not permitted\n'
======================================================================
FAIL: test_agy_pty_without_keychain_access (test_runner.RunnerTests.test_agy_pty_without_keychain_access)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/tests/test_runner.py", line 288, in test_agy_pty_without_keychain_access
self.assertEqual(result.returncode,0,result.stderr)
AssertionError: 71 != 0 : sandbox-exec: sandbox_apply: Operation not permitted
======================================================================
FAIL: test_node_output_drained_to_protected_logs (test_runner.RunnerTests.test_node_output_drained_to_protected_logs)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/tests/test_runner.py", line 278, in test_node_output_drained_to_protected_logs
self.assertEqual(code,0)
AssertionError: 71 != 0
======================================================================
FAIL: test_timeout_is_not_pass (test_runner.RunnerTests.test_timeout_is_not_pass)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-validation-704ed109/tests/test_runner.py", line 482, in test_timeout_is_not_pass
self.assertEqual(code,124)
AssertionError: 71 != 124
----------------------------------------------------------------------
Ran 55 tests in 17.264s
FAILED (failures=4, errors=11)
@@ -0,0 +1,14 @@
{
"task_id": "RP13-01",
"commit": "1398aa2de9f4ca0fd57f7db9d640e829b425553b",
"kind": "validation",
"checks": [
{
"id": "runner-unit",
"exit_code": 1,
"artifact": "/Users/korizatou114/Library/Application Support/agent-control/the-tree-runner-p13-recovery/runs/12a5a6d58b7c4c03a4e2f25dc04d4b89",
"passed": false
}
],
"passed": false
}
@@ -0,0 +1,10 @@
{
"decision": {
"action": "validate",
"task_id": "RP13-01",
"reason": "RP13-01 is submitted at 1398aa2de9f4ca0fd57f7db9d640e829b425553b with candidate=null and repairs at the 2/2 cap. Per the rules, completion comes only from the Runner's tests, a separate-session review, approval and integration, so the next step is the formal validate using the registered argv `python -B -m unittest discover -s tests -p test_runner.py -v` (validation_id runner-unit). Validate checks the submitted revision as-is. It does not change state, launch new workers, add repairs, edit the cap or relax any gate. If it passes, an independent review comes next, then integration (main integration needs owner approval). If it fails, repairs are already at 2/2, so I will stop and report to the owner rather than request another repair. Accepting this Runner fix does not complete P13-03. P13 recovery should go ahead only after integration, using just the approved limited recovery feature from the existing submission (worker e80646369ea746f196073e6539622218). The real packet must be recomputed, and the 318302-byte prototype is not a formal result.",
"codex_model": "gpt-6.1-sol",
"codex_model_reason": "This step is a fixed validation run: one unittest command against an already-submitted revision. It needs no new implementation or design reasoning, and the result is decided by the test outcome, not the model. Sol is the default and is good enough here while costing less time and usage. Astra would add no quality for this step. If the independent review later shows it is needed, I will consider Astra separately for that review."
},
"artifact": "/Users/korizatou114/Library/Application Support/agent-control/the-tree-runner-p13-recovery/runs/6c1a85449ec2491586d34d678cadeb9b"
}
@@ -0,0 +1,17 @@
{
"existing_candidate": "7645c55149d3bebf3ed602cf3039b15b28fa376f",
"current_main": "c4cbc5feb25862433b5532df794958183af66aba",
"changed_game_source": "scenes/main/main.gd",
"actual_delta": "Accepted interface-selection version typing helper; +5 lines before restored actor selection, no changes to original special-facility catalog/entry searches",
"all_facility_records_except_source_sha_equal": true,
"nonfacility_records_except_source_sha_equal": true,
"refresh_patch_bytes": 304749,
"proposal_documents_hashes": {
"difference-ledger.json": "bd9d5789eb4479479c256257a9d8022ab44496a8267d7322e0e4741b42b3544f",
"DIFFERENCE_LEDGER.md": "bffb96b8613c96e5444f861e9d8dcd4acdd0a403eed819a3eefc5241e5783f7c"
},
"remaining_on_approved_worker_run": "Refresh validation.json output hashes with same checker; formal validation/review/integration still mandatory",
"worker_source_modified": false,
"proposal_only": true,
"method": "Only replace old source raw SHA with current main raw SHA, preserving serialization and all existing data; canonical full scan proved exact equality of facility/nonfacility observations except this SHA."
}
@@ -0,0 +1,30 @@
{
"source_candidate": "1398aa2de9f4ca0fd57f7db9d640e829b425553b",
"host_diagnostic_command": [
"python3",
"-B",
"-m",
"unittest",
"discover",
"-s",
"tests",
"-p",
"test_runner.py",
"-v"
],
"host_diagnostic_exit": 1,
"host_tests": 55,
"host_failures": 0,
"host_errors": 2,
"host_error_scope": "Both subtests in test_p13_recovery_rejects_other_p13_tasks register existing AC-001 before reaching intended recovery rejection; duplicate acceptance guard correctly rejects them",
"host_result_is_formal_acceptance": false,
"prototype_r02_single_method_exit": 0,
"prototype_r02_scope": "P13-01 and P13-02 each rejected by blocked-reason recovery guard; counters/state unchanged, no submission; distinct isolated test projects with same baseline and policy",
"actual_candidate_modified": false,
"formal_receipt_overwritten": false,
"p13_readonly_preflight": {
"exit": 0,
"negative_mutations_rejected": 18,
"acceptance": false
}
}
@@ -0,0 +1,9 @@
{
"source_candidate": "1398aa2de9f4ca0fd57f7db9d640e829b425553b",
"actual_file_sha256": "ede1e8fec604bf3894f02a2cca7cb6e8c3a2985b83fee0bbf3ac2e436287a187",
"proposed_file_sha256": "16b34a090552f80b73ab8b8903d162418926949494cdf472f7dbbb529e665c87",
"scope": "one negative test fixture method; isolated baseline prevents unrelated duplicate acceptance registration error; actual P13-01/02 rejection, unchanged repairs/state and no submission remain asserted",
"product_or_worker_files_modified": false,
"proposal_only": true,
"prototype_r01": "Failed: mocked CONTROL fixture has no default policy file; r02 explicitly reuses unchanged test policy"
}
@@ -0,0 +1,289 @@
{
"recorded_at": "2026-10-13T08:19:33.359914+00:00",
"scope": "Read-only reuse/content-preservation and current applicability preflight; not formal acceptance",
"existing_submitted_commit": "7645c55149d3bebf3ed602cf3039b15b28fa376f",
"current_worktree_unsubmitted_ledger_sha256": "b7edd7fc8f5fa5602edc540a3eb8c4150b0268e7551c97a5c5ccc725ea5bb341",
"full_shared_reference_expansion_matches_all_prior_facility_records": true,
"full_shared_reference_expansion_matches_all_prior_nonfacility_records": true,
"facilities": 7,
"slots": 84,
"categories": 6,
"applicable_sources": 53,
"stale_applicable_sources": [
{
"path": "scenes/main/main.gd",
"applicability": "current_checkout",
"matches_current_applicable_source": false
}
],
"source_checks": [
{
"path": "docs/traceability/original/BASELINE.txt",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "docs/plans/original-completion-2026-10-02/work_packages.json",
"applicability": "base_git_blob",
"matches_current_applicable_source": true
},
{
"path": "docs/plans/original-completion-2026-09-29/execution/original_facility_mapping.json",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "docs/plans/original-completion-2026-10-02/asset_inventory_reaudit/facility_usage_slots.json",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "docs/plans/original-completion-2026-10-02/asset_inventory_reaudit/inventory_summary.json",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "docs/plans/original-completion-2026-10-02/decisions.json",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "autoload/simulation_runtime.gd",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "data/facilities/adult_private_room.tres",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "data/facilities/cafeteria.tres",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "data/facilities/expansion/black_market.tres",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "data/facilities/expansion/chapel.tres",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "data/facilities/expansion/cleaning_room.tres",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "data/facilities/expansion/clinic.tres",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "data/facilities/expansion/cold_storage.tres",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "data/facilities/expansion/general_store.tres",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "data/facilities/expansion/guild_counter.tres",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "data/facilities/expansion/laundry.tres",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "data/facilities/expansion/maintenance_workshop.tres",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "data/facilities/expansion/mana_control_room.tres",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "data/facilities/expansion/premium_room.tres",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "data/facilities/expansion/private_bath.tres",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "data/facilities/expansion/secret_tavern.tres",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "data/facilities/expansion/staff_dormitory.tres",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "data/facilities/expansion/tea_lounge.tres",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "data/facilities/expansion/underground_guest_room.tres",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "data/facilities/expansion/vip_private_salon.tres",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "data/facilities/expansion/waste_processing.tres",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "data/facilities/guest_corridor.tres",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "data/facilities/guest_elevator.tres",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "data/facilities/infrastructure/guest_stairs.tres",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "data/facilities/infrastructure/service_stairs.tres",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "data/facilities/kitchen.tres",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "data/facilities/massage_room.tres",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "data/facilities/public_bath.tres",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "data/facilities/reception.tres",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "data/facilities/rescue/infirmary.tres",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "data/facilities/security_station.tres",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "data/facilities/service_corridor.tres",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "data/facilities/service_elevator.tres",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "data/facilities/staff_door.tres",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "data/facilities/staff_waiting_room.tres",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "data/facilities/standard_room.tres",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "data/facilities/tavern.tres",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "data/facilities/warehouse.tres",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "scenes/main/main.gd",
"applicability": "current_checkout",
"matches_current_applicable_source": false
},
{
"path": "scripts/core/save_service.gd",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "scripts/data/facility_catalog.gd",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "scripts/events/event_definition.gd",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "scripts/events/event_service.gd",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "scripts/ui/event_log_dialog.gd",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "tests/s2/test_facility_service.gd",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "tests/s4/test_runtime_relationship_events.gd",
"applicability": "current_checkout",
"matches_current_applicable_source": true
},
{
"path": "tests/s6/test_runtime_snapshot_serialization.gd",
"applicability": "current_checkout",
"matches_current_applicable_source": true
}
],
"new_worker_started": false,
"worker_source_modified": false,
"formal_acceptance_claimed": false
}
@@ -0,0 +1,28 @@
--- a/tests/test_runner.py
+++ b/tests/test_runner.py
@@ -133,12 +133,19 @@
self.recovery_fixture()
for task_id in ("P13-01", "P13-02"):
with self.subTest(task_id=task_id):
- self.r.add(dict(self.contract, id=task_id))
- self.r.state(task_id, "blocked", "scope_violation: fixture.txt")
- with self.assertRaisesRegex(GateError, "blocked reason"):
- self.r.submit(task_id)
- self.assertEqual(self.r.task(task_id)["repairs"], 0)
- self.assertEqual(self.r.task(task_id)["state"], "blocked")
+ isolated = Runner.init("reject-" + task_id, self.repo,
+ self.r.baseline, self.r.config["validations"],
+ policy=self.r.config["policy"], state_root=self.root / "rejection-state")
+ try:
+ isolated.add(dict(self.contract, id=task_id))
+ isolated.state(task_id, "blocked", "scope_violation: fixture.txt")
+ with self.assertRaisesRegex(GateError, "blocked reason"):
+ isolated.submit(task_id)
+ self.assertEqual(isolated.task(task_id)["repairs"], 0)
+ self.assertEqual(isolated.task(task_id)["state"], "blocked")
+ self.assertIsNone(isolated.task(task_id)["submitted"])
+ finally:
+ isolated.db.close()
def test_p13_recovery_accepts_matching_forward_hashes(self):
_, artifact, _ = self.recovery_fixture()
@@ -0,0 +1,7 @@
{
"chunk_id": "3dc1b2",
"wall_time_seconds": 0.000010458,
"exit_code": 1,
"original_token_count": 919,
"output": "\n======================================================================\nERROR: test_p13_recovery_rejects_other_p13_tasks (test_runner_proposed.RunnerTests) (task_id='P13-01')\n----------------------------------------------------------------------\nTraceback (most recent call last):\n File \"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/runner-p13-test-fixture-prototype-r03/test_runner_proposed.py\", line 136, in test_p13_recovery_rejects_other_p13_tasks\n isolated = Runner.init(\"reject-\" + task_id, self.repo,\n File \"/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-implement/runner/core.py\", line 385, in init\n p = policy or read_json(CONTROL / \"policies/default.json\")\n File \"/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-implement/runner/core.py\", line 54, in read_json\n return json.loads(Path(path).read_text(encoding=\"utf-8\"))\n File \"/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/pathlib.py\", line 1256, in read_text\n with self.open(mode='r', encoding=encoding, errors=errors) as f:\n File \"/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/pathlib.py\", line 1242, in open\n return io.open(self, mode, buffering, encoding, errors, newline,\n File \"/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/pathlib.py\", line 1110, in _opener\n return self._accessor.open(self, flags, mode)\nFileNotFoundError: [Errno 2] No such file or directory: '/private/var/folders/41/j8fq6vqj2993cmyprl6p76pw0000gn/T/agent-control-test-er6_6cw3/repo/policies/default.json'\n\n======================================================================\nERROR: test_p13_recovery_rejects_other_p13_tasks (test_runner_proposed.RunnerTests) (task_id='P13-02')\n----------------------------------------------------------------------\nTraceback (most recent call last):\n File \"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/runner-p13-test-fixture-prototype-r03/test_runner_proposed.py\", line 136, in test_p13_recovery_rejects_other_p13_tasks\n isolated = Runner.init(\"reject-\" + task_id, self.repo,\n File \"/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-implement/runner/core.py\", line 385, in init\n p = policy or read_json(CONTROL / \"policies/default.json\")\n File \"/Users/korizatou114/Projects/TheTree-managed-worktrees/runner-p13-recovery/RP13-01-implement/runner/core.py\", line 54, in read_json\n return json.loads(Path(path).read_text(encoding=\"utf-8\"))\n File \"/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/pathlib.py\", line 1256, in read_text\n with self.open(mode='r', encoding=encoding, errors=errors) as f:\n File \"/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/pathlib.py\", line 1242, in open\n return io.open(self, mode, buffering, encoding, errors, newline,\n File \"/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/pathlib.py\", line 1110, in _opener\n return self._accessor.open(self, flags, mode)\nFileNotFoundError: [Errno 2] No such file or directory: '/private/var/folders/41/j8fq6vqj2993cmyprl6p76pw0000gn/T/agent-control-test-er6_6cw3/repo/policies/default.json'\n\n----------------------------------------------------------------------\nRan 1 test in 3.412s\n\nFAILED (errors=2)\n"
}
@@ -0,0 +1,81 @@
{
"actual_tasks": [
{
"id": "RP13-01",
"state": "repair_pending",
"submitted": "1398aa2de9f4ca0fd57f7db9d640e829b425553b",
"repairs": 2,
"reason": "test_failed: /Users/korizatou114/Library/Application Support/agent-control/the-tree-runner-p13-recovery/runs/6fc5dc653f934a01ad5d455c54a6143f-validation.json",
"contract": {
"id": "RP13-01",
"title": "P13限定の提出復旧と新規文書資料削減",
"requirement_ids": [
"RP13-01"
],
"acceptance_ids": [
"RP13-01"
],
"spec_ref": "docs/spec/RP13-01.json",
"base_commit": "c88e2afbea3e1091a4cb048f49bd9891a6bdb869",
"worker": "codex",
"allowed_paths": [
"runner/core.py",
"tests/test_runner.py"
],
"depends_on": [],
"resource_locks": [
"runner-p13-code-isolated"
],
"validation_ids": [
"runner-unit"
],
"max_repair_attempts": 2,
"spec_sha256": "c7ce1e08eefe0bc48afb17dcfec014221102f88072f8d9a3ef9f95b4a2c6664a"
},
"project": "the-tree-runner-p13-recovery"
},
{
"id": "P13-03",
"state": "blocked",
"submitted": "7645c55149d3bebf3ed602cf3039b15b28fa376f",
"repairs": 2,
"reason": "scope_violation: tools/__pycache__/check_p13_content_difference.cpython-314.pyc",
"contract": {
"id": "P13-03",
"title": "内容差異の記録",
"requirement_ids": [
"P13-03"
],
"acceptance_ids": [
"P13-03"
],
"spec_ref": "docs/spec/acceptance/P13-03.json",
"base_commit": "e1a1651e15bbc9a0526ef31d0b2786feb20d8cd1",
"worker": "codex",
"allowed_paths": [
"tools/check_p13_content_difference.py",
"docs/plans/original-completion-2026-10-02/execution/p13-03/**"
],
"depends_on": [],
"resource_locks": [
"p13-content-difference-record"
],
"validation_ids": [
"p13-difference"
],
"max_repair_attempts": 2,
"spec_sha256": "e1255835c1227e02bac42eb99b026b0fcbe69c272f9ed0b36199a2daf8d55c53"
},
"project": "the-tree-p13-03"
}
],
"caps_or_worker_sources_changed": false,
"goal_completed": false,
"human_questions_pending": [
"RP13-01 cap2→3 plus RP13-only trusted formal host self-test",
"P13-03 cap2→3 for exact current source applicability refresh"
],
"formal_original_completed_count": 10,
"original_total": 88,
"no_partial_credit": true
}
@@ -0,0 +1,23 @@
{
"task": "MP-01-r02",
"state": "completed",
"scope": "requested approval proposal artifact only; not original P06-01 acceptance",
"implementation_commit": "6b78f8fd71131e61ba695939f4629fec9f51d7a9",
"integration_commit": "65a4fe2bb8e99812a8e8ad7f7a7addf489fe5067",
"product_values_applied": false,
"original_88_completed_added": 0,
"governing_spec": "docs/spec/acceptance/P06-mana-proposal-r02.json",
"governing_spec_sha256_runner_strip": "f8cf1753e7ab400130c761570828640c03e0d51073a03f887a9085cbe6be77c6",
"low_findings": [
{
"issue": "Reused proposal id MP-01 and historical base_commit retained",
"disposition": "Retain historical draft provenance; current task/base/commit are fixed by formal-traceability-r02.json. No new repair needed for accepted artifact."
},
{
"issue": "Proposal source_pins includes old proposal spec, omits current r02 governing spec",
"disposition": "Current r02 spec SHA and path are pinned in immutable Runner contract and preserved traceability. Low-level follow-up recorded; no acceptance weakening."
}
],
"next_original_target": "P13-03",
"next_action": "Read-only reconciliation of existing second repair, failed validation and scope before any same-task continuation; no duplicate implementation, no cap increase."
}
@@ -0,0 +1,63 @@
{
"recorded_at": "2026-10-13T08:10:27.851257+00:00",
"next_original_target": "P13-03",
"priority_reason": "Existing final repair of records/checker; no Windows device or unapproved production numeric choice is required; avoid duplicate implementation",
"actual_existing_task": {
"id": "P13-03",
"state": "blocked",
"submitted": "7645c55149d3bebf3ed602cf3039b15b28fa376f",
"reason": "scope_violation: tools/__pycache__/check_p13_content_difference.cpython-314.pyc",
"repairs": 2,
"contract": {
"id": "P13-03",
"title": "内容差異の記録",
"requirement_ids": [
"P13-03"
],
"acceptance_ids": [
"P13-03"
],
"spec_ref": "docs/spec/acceptance/P13-03.json",
"base_commit": "e1a1651e15bbc9a0526ef31d0b2786feb20d8cd1",
"worker": "codex",
"allowed_paths": [
"tools/check_p13_content_difference.py",
"docs/plans/original-completion-2026-10-02/execution/p13-03/**"
],
"depends_on": [],
"resource_locks": [
"p13-content-difference-record"
],
"validation_ids": [
"p13-difference"
],
"max_repair_attempts": 2,
"spec_sha256": "e1255835c1227e02bac42eb99b026b0fcbe69c272f9ed0b36199a2daf8d55c53"
}
},
"latest_recorded_commander": {
"decision": {
"action": "run",
"task_id": "P13-03",
"reason": "P13-03 は repair_ready(repairs=2、上限2/2内)で、オーナーが3件の検証済み欠陥について最終修理を承認しています。同じCodex workerを、許可されたexecution/p13-03/P13_ORDER_FINAL_REPAIR_INPUT.mdを入力に再開してください。元の7施設・84スロット・6カテゴリ・unknown・source evidenceは維持します。不変のspec、cap、contractは変更しません。core、assets、gameの編集と新規タスクは行いません。run後も、exact --verify-only の正式検証と必須ネガティブ、reviewer本文のexact preflight、別セッションの正式Claudeレビュー、統合は必須です。ローカルの13チェックだけでは完了とみなしません。"
},
"artifact": "/Users/korizatou114/Library/Application Support/agent-control/the-tree-p13-03/runs/c3ae83b855a24966b051a2a296c3b64f"
},
"all_acceptance_reference": "docs/spec/acceptance/P13-03.json",
"reuse_candidate": "7645c55149d3bebf3ed602cf3039b15b28fa376f",
"remaining_conditions": [
"Reconcile existing final repair output and exact source version; no second worker",
"Resolve generated out-of-scope cache without deleting unapproved content or widening allowed_paths",
"Actual registered --verify-only validation and mandatory negative coverage",
"Exact complete reviewer packet within unchanged 500000 guard",
"Separate formal Opus review, integration and final validation, ledger completion"
],
"dependencies": {
"registered_depends_on": [],
"windows_device_required_for_this_records_only_unit": false,
"mana_numeric_approval_required_for_this_unit": false
},
"new_worker_started": false,
"task_state_or_cap_changed": false,
"formal_acceptance_claimed": false
}
@@ -0,0 +1,14 @@
{
"task_id": "MP-01-r02",
"commit": "65a4fe2bb8e99812a8e8ad7f7a7addf489fe5067",
"kind": "final",
"checks": [
{
"id": "proposal-consistency",
"exit_code": 0,
"artifact": "/Users/korizatou114/Library/Application Support/agent-control/the-tree-mana-proposal-r02/runs/c0c18ffb7abf484b9f9ecf8149ce65b0",
"passed": true
}
],
"passed": true
}
@@ -0,0 +1,14 @@
{
"task_id": "MP-01-r02",
"commit": "65a4fe2bb8e99812a8e8ad7f7a7addf489fe5067",
"kind": "integration",
"checks": [
{
"id": "proposal-consistency",
"exit_code": 0,
"artifact": "/Users/korizatou114/Library/Application Support/agent-control/the-tree-mana-proposal-r02/runs/3872bfd9219f461c8d8f116a1a57b493",
"passed": true
}
],
"passed": true
}
@@ -0,0 +1,19 @@
{
"task_id": "MP-01-r02",
"commit": "6b78f8fd71131e61ba695939f4629fec9f51d7a9",
"status": "pass",
"summary": "I checked acceptance item MP-01-r02 (P06-01) against the spec, the diff, the target sources and the Runner results. All requirements are met, so the status is pass.\n\nScope:\n- Only the two files inside allowed_paths were changed: PROPOSAL.md and proposal.json.\n- No product source, original spec, ledger, Runner config or test files were touched.\n- No tests were deleted or disabled.\n- The Runner reports product_changed=false and original_completed_units_added=0.\n\nSpec checks:\n1. proposal.json has status=proposed_unapproved and applied_to_product=false. All 8 required top-level keys are present.\n2. recommended has all 4 numeric fields (100/300/20/10) as integers, with initial amount ≤ capacity.\n3. The furnace candidate states input and output (1 eligible generic slave → 100 Mana), eligibility, timing, atomicity, history and interruption handling. It sets actual_actor_consumption=false. It keeps the original constraints (6×3, back underground, slave consumption) and excludes irreplaceable, unsellable and unique people.\n4. demand_catalog lists all 37 definitions with the 3 required fields. I re-added the values myself: one of each definition totals 63, and the normal mix totals 16. The 4 facilities that omit maintenance_mana are recorded as 0 based on the FacilityDefinition default. The 13 original facilities with no definition are kept as unknown, not treated as 0.\n5. source_pins is now a repo-relative path → raw-file SHA256 dictionary. The Runner matched all 53 pins against the current files. Provenance is kept separately in source_provenance and the provenance section, which keeps original, current implementation, fixture and candidate values distinct.\n6. Each of these is described separately with its basis: initial mana=100 as a stock amount vs. STARTER_MANA_OUTPUT=100 as network supply capacity, the current use of maintenance_mana, and the fact that the conversion is only a proposal.\n7. There are 21 comparison series covering low load, normal, demand excess, zero stock, capacity limit, supply loss and return, and same-boundary resend. The Runner independently recomputed all 126 rows. My spot checks also matched: recommended excess 100→57→14→0 with shortage 29; generous case at 16 after interval 8 and first zero at interval 9; overflow 16/18/38. Both furnace headroom policies also matched (96/100/0 and 80/84/0).\n8. D05 is marked as unapproved, with a recommended order inside the MANA phase. A legacy 0 is kept as 0 (stopped) and is never silently converted to full or unlimited. Open decisions and their approval scope are listed.\n9. PROPOSAL.md states at the top that the proposal is unapproved and not applied to the product. It claims neither completion of the original 88 deliveries nor acceptance of P06-01. The proposal-consistency check passed (exit 0).\n\nThe only problems are leftover metadata, listed as low findings.",
"acceptance_ids": [
"MP-01-r02"
],
"findings": [
{
"severity": "low",
"message": "Leftover metadata in proposal.json: id is still \"MP-01\" and base_commit still points to an older commit (0bdc4886…) instead of this contract's base (5536bc04…). The r02 traceability would be clearer if these were updated. The values and source pins match the current files, so this does not affect substance."
},
{
"severity": "low",
"message": "source_pins points to the old spec docs/spec/acceptance/P06-mana-proposal.json and does not include the spec that governs this round (P06-mana-proposal-r02.json). Adding the governing spec would make traceability easier. This does not affect acceptance."
}
]
}
@@ -0,0 +1,72 @@
{
"contract": {
"id": "MP-01-r02",
"title": "承認用マナ契約候補の作成(原88成果の完了ではない)",
"requirement_ids": [
"P06-01"
],
"acceptance_ids": [
"MP-01-r02"
],
"spec_ref": "docs/spec/acceptance/P06-mana-proposal-r02.json",
"base_commit": "5536bc041188d53229d18f33f08b17d4d83b7590",
"worker": "codex",
"allowed_paths": [
"docs/plans/original-completion-2026-10-02/execution/mana-proposal/**"
],
"depends_on": [],
"resource_locks": [
"mana-proposal-draft"
],
"validation_ids": [
"proposal-consistency"
],
"max_repair_attempts": 2,
"spec_sha256": "f8cf1753e7ab400130c761570828640c03e0d51073a03f887a9085cbe6be77c6"
},
"implementation_commit": "6b78f8fd71131e61ba695939f4629fec9f51d7a9",
"integration_commit": "65a4fe2bb8e99812a8e8ad7f7a7addf489fe5067",
"owner": "Human standing instruction: mainの更新を明示的に許可します; コミットすべき内容をコミットして。その上でpushして; applicable only to requested unapproved proposal-document integration, not product numeric adoption",
"evidence": [
{
"id": 1,
"task_id": "MP-01-r02",
"kind": "validation",
"commit_sha": "6b78f8fd71131e61ba695939f4629fec9f51d7a9",
"artifact": "/Users/korizatou114/Library/Application Support/agent-control/the-tree-mana-proposal-r02/runs/e2f43a7c8ae74ed88eff644e163d81ff-validation.json",
"passed": 1,
"preserved_copy": "docs/plans/original-completion-2026-10-02/execution/mana-proposal-continuation-r03/formal-validation-r02.json",
"sha256": "a8373b86ab41e33c54d1cbea5a9dbe4c083589d512a8e95087306ba3af06bb3b"
},
{
"id": 2,
"task_id": "MP-01-r02",
"kind": "review",
"commit_sha": "6b78f8fd71131e61ba695939f4629fec9f51d7a9",
"artifact": "/Users/korizatou114/Library/Application Support/agent-control/the-tree-mana-proposal-r02/runs/d84ae79eb6a843548013c4fdf676513f/result.json",
"passed": 1,
"preserved_copy": "docs/plans/original-completion-2026-10-02/execution/mana-proposal-continuation-r03/formal-review-r02.json",
"sha256": "60ca677ca0cba71579fc0fc0658348739009565f04c3018ae5f315cff8f5a72a"
},
{
"id": 3,
"task_id": "MP-01-r02",
"kind": "integration",
"commit_sha": "65a4fe2bb8e99812a8e8ad7f7a7addf489fe5067",
"artifact": "/Users/korizatou114/Library/Application Support/agent-control/the-tree-mana-proposal-r02/runs/e1a1ce778b484c33975770bb643fd4aa-integration.json",
"passed": 1,
"preserved_copy": "docs/plans/original-completion-2026-10-02/execution/mana-proposal-continuation-r03/formal-integration-r02.json",
"sha256": "71edaef3231ebcc19b90d1f40d29b99a3067e70985eaab7cf2ff5987092fb234"
},
{
"id": 4,
"task_id": "MP-01-r02",
"kind": "final",
"commit_sha": "65a4fe2bb8e99812a8e8ad7f7a7addf489fe5067",
"artifact": "/Users/korizatou114/Library/Application Support/agent-control/the-tree-mana-proposal-r02/runs/712ab0b9065f4bd4b7a97384fee58f5e-final.json",
"passed": 1,
"preserved_copy": "docs/plans/original-completion-2026-10-02/execution/mana-proposal-continuation-r03/formal-final-r02.json",
"sha256": "6543513845d535e6bde610581af23904449134409a4016e87df6b2061f41f0ab"
}
]
}
@@ -0,0 +1,14 @@
{
"task_id": "MP-01-r02",
"commit": "6b78f8fd71131e61ba695939f4629fec9f51d7a9",
"kind": "validation",
"checks": [
{
"id": "proposal-consistency",
"exit_code": 0,
"artifact": "/Users/korizatou114/Library/Application Support/agent-control/the-tree-mana-proposal-r02/runs/f8299dafca1945618ff5d2c6cdf8bcd4",
"passed": true
}
],
"passed": true
}
@@ -0,0 +1,25 @@
# P22-02 素材契約(原成果未完了)
原30パッケージ/88成果・部分点なしを維持する。614 identityは360施設、176人物、2状態群、76その他であり、614画像ではない。495 candidate、119 missing、19 sourceを全て保持する。選定済完成資産は0。D08/D09の最終内容・数量はunknown。
asset-contracts.jsonはp22-reference-contract-v2形式。immutable accepted input/current/evidenceをpathとraw SHAで参照し、全フィールドを損失なく再構成する。accepted inputのd/l/s/rをdecodeし、歴史的契約と現selections/source_pins/unit_proofsを分離する。missingをcode/file/fallbackで充足しない。最終の解像度・frame/layout・命名・差替参照は未確定。
Kenney Tiny Town/Tiny Dungeon/Interface Soundsのpublisher/member/license/manifest証拠はevidence_pinsの文書を完全再利用する。配布元URLとCC0記録はcandidate_poolおよび既存ライセンス証拠を参照。内部BGM合成recipeは内部由来であり、第三者CC0や最終聴感・権利受入へ昇格しない。自己制作・別許諾を排除しない。未知creator/rightsを推測しない。
checkerの通常0終了は記録整合性のみ。validation_readyには全exact useの使用可能選定資産・権利・必要な画面/聴感証拠とmandatory_scope/disclosure証拠が必要。独立レビュー・統合・最終受入を技術的readinessの事前ゲートにはしない。原成果受入には別途Root正式検証・意味のあるnegative・独立Opusレビュー・統合・finalが必要。
ローカル限定確認: python3 -Bで13テスト合格、ordinary exit 0、require-ready exit 2。614 pending、0 selected、19 candidate sources、disclosure/mandatory_scope不足。record_integrity=true、validation_ready=false、acceptance_claimed=false。正式試験・原成果受入は主張しない。
契約spec SHAはstdout.stripのUTF-8に対するf252de3c5cff7ebfa62322ae2f2df09fb80a44bc59eb286b76d4acb4c12ca875。raw SHA c26c0b12cf7e7a7c46e671acde2e00762904732c1cd6381a53836e3d7b3f9824との差は末尾改行のみ。
完全パケットの最終実測は未確認。指定patchと計測evidence/proposalがこのworktreeに存在せず、通常制作ディレクトリはアクセス拒否。487283はprospective値であり実測値として扱わない。500000未満の確認は未充足。
## 次の製品変更提案(この実装では適用しない)
- scripts/ui/pixel_tower_art.gd、standard_room_art.gd、infirmary_room_art.gd: 各施設Lv1–3/表裏/外観内装のidから選定representationへ明示対応を追加。共有atlasや専用一部装飾を全施設に流用して完成扱いしない。最小差分は選定されたidの参照と該当描画分岐のみ。実画面で各対応と未制作開示を確認する。
- scripts/ui/pixel_people.gd: character条件ごとの選定と必要variant参照を明示し、2状態群は状態表現として接続する。数量は承認されるまでunknown。該当人物・状態の画面確認が必要。
- assets/themes/japanese_fantasy/visual-theme-v1.tres、scenes/main/world_preview.gd、scenes/main/main.gd: 世界/skin候補のcreator/rightsを解決してから選定素材への参照のみ差替。サイズ、alpha、atlas region、nearest/mipmapと全参照整合を確認し実表示で確認する。
- scripts/ui/paired_bgm.gdと2 candidate WAV: internal-origin-observationsのrecipeとbyte証拠を保持し、creator/権利の承認と両contextの聴感を取得してから最終選定。UI4音もpublisher証拠だけで最終聴感を代用しない。
- missing_candidateの119 identityは各契約のsource_anchors/usage_conditionを制作依頼に渡し、Kenney適合候補を先に確認する。最小asset/reference差分は選定後にのみ確定できる。未確定の絵や数量を捏造しない。
Runnerの検証対象: 全614 coverage、全decoded semantic hash、raw input/source/evidence pins、historical適用性、PNG寸法、参照・source omission、duplicate、cycle/bad index/key/type、unknown rights/false finished、数量変更。negativeはledgerの該当値の改変・削除、source/寸法・reference変更を含める。完全packetを500000 bytes未満で確認し、欠落・切捨てで縮小しない。その後に必要な製品実装・usability・独立レビュー・統合・finalを行う。
@@ -0,0 +1,11 @@
# Root actual preflight and final bounded repair
{
"action": "request-repair",
"task_id": "P22-02",
"reason": "The Root preflight of c6ccc5a6 found three required defects (recorded in checkpoints/p22-02-slot-contract-r02/actual-checker-and-packet-preflight-r02.json). This uses the last ordinary repair (1 used, limit 2). Fix only within allowed_paths: execution/p22-02/** and tools/check_p22_asset_contracts.py. Do not change the spec, inputs, Root checkpoint, cap, contracts, registered validation argv, permissions, or Core.\n\n(1) The checker exits 2 on the exact registered argv `--verify-only --accepted-input docs/spec/inputs/P22-02-accepted-usage.json --require-ready`. Add argparse support for `--verify-only` and `--accepted-input` without changing the registration. Keep it read-only.\n\n(2) Readiness is hardcoded to always fail, which the spec forbids. The check forces selected_assets==[], asserts all 8 original_conditions are False before computing ready with all(values), and forces ledger.current to equal the frozen all-unmet snapshot. Remove these. Keep every field of the frozen accepted input, all 614 original identities and the source observations. Verify the new current, selection and actual evidence separately, and derive ready from that real data. Reject fake booleans, file-presence-only proof and promoted fallbacks. The current ledger is genuinely short of 614, so the real P22 run must still return a nonzero readiness exit.\n\nKeep validation-ready separate from original-completed. Formal validate covers the technical readiness of function, assets, rights and the required usability. Original acceptance comes later, through a separate review, then integration, then final. Remove the cycle that puts independent review or integration completion as a gate before validation. Do not record original acceptance ahead of time.\n\nProve reachability with pure functions: one isolated positive readiness case, plus negatives for wrong proof, wrong quantity and wrong pin. Apply meaningful negatives to: missing, duplicate and stale sources; dimension, layout, license and rights mismatches; counterfeit final; quantity; codec bool-as-index; cycles; duplicate keys; NaN/Inf; and path escape. Don't reject only sample mutations, and don't use a gate that requires the whole checkpoint to equal a mirror.\n\n(3) The exact unchanged Runner packet is actually 1,350,690 bytes; the worker's 472,408 figure was wrong. It must be under 500,000 bytes, counting the full diff, all sources, the registered validation_sources (the checker plus the 217 KiB accepted input) and the tests. Don't re-embed the whole accepted_input or the roughly 1.5 MB current data in the ledger. Rebuild losslessly from the existing immutable inputs, referenced by raw SHA, decoded semantic hash, or file plus identity. Keep all 19 candidate sources, each of the 614 selections, and every gap and required field. Cut the output down with shared profiles, text and contracts. Don't extend the Core's P13-only dedup to P22.\n\nRun python -B with ast.parse only; no engine or full regression. Return submitted with the exact list of incomplete original-unit conditions. Do not claim P22-02 acceptance. No duplicate worker and no new registration.",
"codex_model": "gpt-6-astra",
"codex_model_reason": "This is the last ordinary repair, so a failure leaves no fallback. The work is hard: three defects at once, redesigning the readiness logic so it is reachable but still fails nonzero on the real data, untangling the validate/review/integration cycle, and a lossless decoder rebuild that shrinks the packet from 1.35 MB to under 500 KB. It also needs many meaningful negatives. The previous worker misreported the packet size and shipped always-fail logic, which suggests the default model underestimates this task. Astra's quality is worth its extra time and usage."
}
No spec/input/core/cap changes. Preserve every accepted input field through immutable references, not a second embedded mirror. Exact Root packet body is in artifacts as diagnostic only; normal Runner packet uses full diff and source with validation sources, no P22 added-doc dedup. Current real readiness remains nonzero, but valid future proof must be able to reach readiness without assuming prior final integration. Root will check the exact body again before any reviewer launch.
@@ -0,0 +1,19 @@
# Root context: fixed spec hash representation
This is coordination input, not a spec change or acceptance.
{
"task": "P22-02",
"base_commit": "10c62e1fa7b71576598583f434824b59816d4705",
"spec_ref": "docs/spec/acceptance/P22-02.json",
"contract_spec_sha256": "f252de3c5cff7ebfa62322ae2f2df09fb80a44bc59eb286b76d4acb4c12ca875",
"raw_spec_sha256": "c26c0b12cf7e7a7c46e671acde2e00762904732c1cd6381a53836e3d7b3f9824",
"runner_strip_spec_sha256": "f252de3c5cff7ebfa62322ae2f2df09fb80a44bc59eb286b76d4acb4c12ca875",
"raw_worktree_equals_base_git_blob": true,
"spec_changed": false,
"contract_changed": false,
"root_normalized_hash_verification_passed": true,
"reason": "Runner git helper uses stdout.strip(), then UTF8; source_pins and accepted input raw SHA remain raw bytes, not stripped"
}
Compare contract spec via git show base:spec, stdout.strip(), encode UTF8 and SHA256. Raw spec includes terminal newline and has a different raw-byte SHA. This is expected. It is not permission to edit/normalize any file. For source_pins and accepted input, use the full raw bytes as before. Read accepted input only with targeted Python. Do not block for a terminal newline difference when the Runner hash and exact base raw blob are both proven equal. Preserve all original conditions and current unmade gaps.
@@ -0,0 +1,654 @@
{
"schema": "p22-reference-contract-v2",
"references": {
"docs/spec/inputs/P22-02-accepted-usage.json": "45fa52acf0c8bd4dd58c3b40b681cb92066f05d617df157fc18370a5e8816281",
"docs/plans/original-completion-2026-10-02/checkpoints/p22-02-slot-contract-r02/all-slot-current-candidate-contracts.json": "5cf93b6b3fd9d0cc060075878804f65195c0d90711c969cc36e2f58f3a1917fd",
"docs/plans/original-completion-2026-10-02/checkpoints/p22-02-current-contract-r01/README.md": "b65a7a94f4088139efb186a2a3f4ba9079e7bfd0664b39effa46d101eee3cdaa",
"docs/plans/original-completion-2026-10-02/checkpoints/p22-02-current-contract-r01/actual-opus-next-target-decision.json": "d03f1b4f60d5eff85936e3b4f77c4971b9ed19132547f090ed0dce30ba3f7905",
"docs/plans/original-completion-2026-10-02/checkpoints/p22-02-current-contract-r01/current-media-rights.json": "da24fc40b62af5c75b6e6732cebb3a6ca7475d3713176d4e70a57ecba87fc59a",
"docs/plans/original-completion-2026-10-02/checkpoints/p22-02-current-contract-r01/internal-origin-observations.json": "8b72f9a24f5f1670116fdfb41995491ce42f44bab38a9f9c7206e0aaaefbb08a",
"docs/plans/original-completion-2026-10-02/checkpoints/p22-02-current-contract-r01/observed-existing-asset-contracts.json": "ff985e94892554873aea76148fc555eb9b007fd9622dc01e91917ba2cceb51d6",
"docs/plans/original-completion-2026-10-02/checkpoints/p22-02-current-contract-r01/publisher-archive-byte-verification.json": "ef5d4ee78c80d2f9439646b86a0c781b685ad94dcc93d41d629f0ca148fcc061",
"docs/plans/original-completion-2026-10-02/checkpoints/p22-02-current-contract-r01/reuse-rights-preflight.json": "204184c5f52305d76a25a8868569649aa541337de0405c6d799eb20f7246081b",
"docs/plans/original-completion-2026-10-02/checkpoints/p22-02-current-contract-r01/ui-audio-publisher-verification.json": "bfebed0270e756530c69b434ca5a302b80287b586a261fb7c33718984e133fb8"
},
"reconstruction": "All accepted codec fields and snapshot fields retained by raw SHA; selections inherit entire snapshot contracts by identity, including every unmade condition.",
"selections": {
"standard_room.lv1.front.exterior": "candidate",
"standard_room.lv1.front.interior": "candidate",
"standard_room.lv1.back.exterior": "candidate",
"standard_room.lv1.back.interior": "candidate",
"standard_room.lv2.front.exterior": "candidate",
"standard_room.lv2.front.interior": "candidate",
"standard_room.lv2.back.exterior": "candidate",
"standard_room.lv2.back.interior": "candidate",
"standard_room.lv3.front.exterior": "candidate",
"standard_room.lv3.front.interior": "candidate",
"standard_room.lv3.back.exterior": "candidate",
"standard_room.lv3.back.interior": "candidate",
"premium_room.lv1.front.exterior": "candidate",
"premium_room.lv1.front.interior": "candidate",
"premium_room.lv1.back.exterior": "candidate",
"premium_room.lv1.back.interior": "candidate",
"premium_room.lv2.front.exterior": "candidate",
"premium_room.lv2.front.interior": "candidate",
"premium_room.lv2.back.exterior": "candidate",
"premium_room.lv2.back.interior": "candidate",
"premium_room.lv3.front.exterior": "candidate",
"premium_room.lv3.front.interior": "candidate",
"premium_room.lv3.back.exterior": "candidate",
"premium_room.lv3.back.interior": "candidate",
"original_facility_03.lv1.front.exterior": "candidate",
"original_facility_03.lv1.front.interior": "candidate",
"original_facility_03.lv1.back.exterior": "candidate",
"original_facility_03.lv1.back.interior": "candidate",
"original_facility_03.lv2.front.exterior": "candidate",
"original_facility_03.lv2.front.interior": "candidate",
"original_facility_03.lv2.back.exterior": "candidate",
"original_facility_03.lv2.back.interior": "candidate",
"original_facility_03.lv3.front.exterior": "candidate",
"original_facility_03.lv3.front.interior": "candidate",
"original_facility_03.lv3.back.exterior": "candidate",
"original_facility_03.lv3.back.interior": "candidate",
"original_facility_04.lv1.front.exterior": "candidate",
"original_facility_04.lv1.front.interior": "candidate",
"original_facility_04.lv1.back.exterior": "candidate",
"original_facility_04.lv1.back.interior": "candidate",
"original_facility_04.lv2.front.exterior": "candidate",
"original_facility_04.lv2.front.interior": "candidate",
"original_facility_04.lv2.back.exterior": "candidate",
"original_facility_04.lv2.back.interior": "candidate",
"original_facility_04.lv3.front.exterior": "candidate",
"original_facility_04.lv3.front.interior": "candidate",
"original_facility_04.lv3.back.exterior": "candidate",
"original_facility_04.lv3.back.interior": "candidate",
"cafeteria.lv1.front.exterior": "candidate",
"cafeteria.lv1.front.interior": "candidate",
"cafeteria.lv1.back.exterior": "candidate",
"cafeteria.lv1.back.interior": "candidate",
"cafeteria.lv2.front.exterior": "candidate",
"cafeteria.lv2.front.interior": "candidate",
"cafeteria.lv2.back.exterior": "candidate",
"cafeteria.lv2.back.interior": "candidate",
"cafeteria.lv3.front.exterior": "candidate",
"cafeteria.lv3.front.interior": "candidate",
"cafeteria.lv3.back.exterior": "candidate",
"cafeteria.lv3.back.interior": "candidate",
"original_facility_06.lv1.front.exterior": "candidate",
"original_facility_06.lv1.front.interior": "candidate",
"original_facility_06.lv1.back.exterior": "candidate",
"original_facility_06.lv1.back.interior": "candidate",
"original_facility_06.lv2.front.exterior": "candidate",
"original_facility_06.lv2.front.interior": "candidate",
"original_facility_06.lv2.back.exterior": "candidate",
"original_facility_06.lv2.back.interior": "candidate",
"original_facility_06.lv3.front.exterior": "candidate",
"original_facility_06.lv3.front.interior": "candidate",
"original_facility_06.lv3.back.exterior": "candidate",
"original_facility_06.lv3.back.interior": "candidate",
"tavern.lv1.front.exterior": "candidate",
"tavern.lv1.front.interior": "candidate",
"tavern.lv1.back.exterior": "candidate",
"tavern.lv1.back.interior": "candidate",
"tavern.lv2.front.exterior": "candidate",
"tavern.lv2.front.interior": "candidate",
"tavern.lv2.back.exterior": "candidate",
"tavern.lv2.back.interior": "candidate",
"tavern.lv3.front.exterior": "candidate",
"tavern.lv3.front.interior": "candidate",
"tavern.lv3.back.exterior": "candidate",
"tavern.lv3.back.interior": "candidate",
"original_facility_08.lv1.front.exterior": "candidate",
"original_facility_08.lv1.front.interior": "candidate",
"original_facility_08.lv1.back.exterior": "candidate",
"original_facility_08.lv1.back.interior": "candidate",
"original_facility_08.lv2.front.exterior": "candidate",
"original_facility_08.lv2.front.interior": "candidate",
"original_facility_08.lv2.back.exterior": "candidate",
"original_facility_08.lv2.back.interior": "candidate",
"original_facility_08.lv3.front.exterior": "candidate",
"original_facility_08.lv3.front.interior": "candidate",
"original_facility_08.lv3.back.exterior": "candidate",
"original_facility_08.lv3.back.interior": "candidate",
"public_bath.lv1.front.exterior": "candidate",
"public_bath.lv1.front.interior": "candidate",
"public_bath.lv1.back.exterior": "candidate",
"public_bath.lv1.back.interior": "candidate",
"public_bath.lv2.front.exterior": "candidate",
"public_bath.lv2.front.interior": "candidate",
"public_bath.lv2.back.exterior": "candidate",
"public_bath.lv2.back.interior": "candidate",
"public_bath.lv3.front.exterior": "candidate",
"public_bath.lv3.front.interior": "candidate",
"public_bath.lv3.back.exterior": "candidate",
"public_bath.lv3.back.interior": "candidate",
"original_facility_10.lv1.front.exterior": "candidate",
"original_facility_10.lv1.front.interior": "candidate",
"original_facility_10.lv1.back.exterior": "candidate",
"original_facility_10.lv1.back.interior": "candidate",
"original_facility_10.lv2.front.exterior": "candidate",
"original_facility_10.lv2.front.interior": "candidate",
"original_facility_10.lv2.back.exterior": "candidate",
"original_facility_10.lv2.back.interior": "candidate",
"original_facility_10.lv3.front.exterior": "candidate",
"original_facility_10.lv3.front.interior": "candidate",
"original_facility_10.lv3.back.exterior": "candidate",
"original_facility_10.lv3.back.interior": "candidate",
"original_facility_11.lv1.front.exterior": "candidate",
"original_facility_11.lv1.front.interior": "candidate",
"original_facility_11.lv1.back.exterior": "candidate",
"original_facility_11.lv1.back.interior": "candidate",
"original_facility_11.lv2.front.exterior": "candidate",
"original_facility_11.lv2.front.interior": "candidate",
"original_facility_11.lv2.back.exterior": "candidate",
"original_facility_11.lv2.back.interior": "candidate",
"original_facility_11.lv3.front.exterior": "candidate",
"original_facility_11.lv3.front.interior": "candidate",
"original_facility_11.lv3.back.exterior": "candidate",
"original_facility_11.lv3.back.interior": "candidate",
"chapel.lv1.front.exterior": "candidate",
"chapel.lv1.front.interior": "candidate",
"chapel.lv1.back.exterior": "candidate",
"chapel.lv1.back.interior": "candidate",
"chapel.lv2.front.exterior": "candidate",
"chapel.lv2.front.interior": "candidate",
"chapel.lv2.back.exterior": "candidate",
"chapel.lv2.back.interior": "candidate",
"chapel.lv3.front.exterior": "candidate",
"chapel.lv3.front.interior": "candidate",
"chapel.lv3.back.exterior": "candidate",
"chapel.lv3.back.interior": "candidate",
"adult_private_room.lv1.front.exterior": "candidate",
"adult_private_room.lv1.front.interior": "candidate",
"adult_private_room.lv1.back.exterior": "candidate",
"adult_private_room.lv1.back.interior": "candidate",
"adult_private_room.lv2.front.exterior": "candidate",
"adult_private_room.lv2.front.interior": "candidate",
"adult_private_room.lv2.back.exterior": "candidate",
"adult_private_room.lv2.back.interior": "candidate",
"adult_private_room.lv3.front.exterior": "candidate",
"adult_private_room.lv3.front.interior": "candidate",
"adult_private_room.lv3.back.exterior": "candidate",
"adult_private_room.lv3.back.interior": "candidate",
"original_facility_14.lv1.front.exterior": "candidate",
"original_facility_14.lv1.front.interior": "candidate",
"original_facility_14.lv1.back.exterior": "candidate",
"original_facility_14.lv1.back.interior": "candidate",
"original_facility_14.lv2.front.exterior": "candidate",
"original_facility_14.lv2.front.interior": "candidate",
"original_facility_14.lv2.back.exterior": "candidate",
"original_facility_14.lv2.back.interior": "candidate",
"original_facility_14.lv3.front.exterior": "candidate",
"original_facility_14.lv3.front.interior": "candidate",
"original_facility_14.lv3.back.exterior": "candidate",
"original_facility_14.lv3.back.interior": "candidate",
"original_facility_15.lv1.front.exterior": "candidate",
"original_facility_15.lv1.front.interior": "candidate",
"original_facility_15.lv1.back.exterior": "candidate",
"original_facility_15.lv1.back.interior": "candidate",
"original_facility_15.lv2.front.exterior": "candidate",
"original_facility_15.lv2.front.interior": "candidate",
"original_facility_15.lv2.back.exterior": "candidate",
"original_facility_15.lv2.back.interior": "candidate",
"original_facility_15.lv3.front.exterior": "candidate",
"original_facility_15.lv3.front.interior": "candidate",
"original_facility_15.lv3.back.exterior": "candidate",
"original_facility_15.lv3.back.interior": "candidate",
"black_market.lv1.front.exterior": "candidate",
"black_market.lv1.front.interior": "candidate",
"black_market.lv1.back.exterior": "candidate",
"black_market.lv1.back.interior": "candidate",
"black_market.lv2.front.exterior": "candidate",
"black_market.lv2.front.interior": "candidate",
"black_market.lv2.back.exterior": "candidate",
"black_market.lv2.back.interior": "candidate",
"black_market.lv3.front.exterior": "candidate",
"black_market.lv3.front.interior": "candidate",
"black_market.lv3.back.exterior": "candidate",
"black_market.lv3.back.interior": "candidate",
"kitchen.lv1.front.exterior": "candidate",
"kitchen.lv1.front.interior": "candidate",
"kitchen.lv1.back.exterior": "candidate",
"kitchen.lv1.back.interior": "candidate",
"kitchen.lv2.front.exterior": "candidate",
"kitchen.lv2.front.interior": "candidate",
"kitchen.lv2.back.exterior": "candidate",
"kitchen.lv2.back.interior": "candidate",
"kitchen.lv3.front.exterior": "candidate",
"kitchen.lv3.front.interior": "candidate",
"kitchen.lv3.back.exterior": "candidate",
"kitchen.lv3.back.interior": "candidate",
"warehouse.lv1.front.exterior": "candidate",
"warehouse.lv1.front.interior": "candidate",
"warehouse.lv1.back.exterior": "candidate",
"warehouse.lv1.back.interior": "candidate",
"warehouse.lv2.front.exterior": "candidate",
"warehouse.lv2.front.interior": "candidate",
"warehouse.lv2.back.exterior": "candidate",
"warehouse.lv2.back.interior": "candidate",
"warehouse.lv3.front.exterior": "candidate",
"warehouse.lv3.front.interior": "candidate",
"warehouse.lv3.back.exterior": "candidate",
"warehouse.lv3.back.interior": "candidate",
"staff_waiting_room.lv1.front.exterior": "candidate",
"staff_waiting_room.lv1.front.interior": "candidate",
"staff_waiting_room.lv1.back.exterior": "candidate",
"staff_waiting_room.lv1.back.interior": "candidate",
"staff_waiting_room.lv2.front.exterior": "candidate",
"staff_waiting_room.lv2.front.interior": "candidate",
"staff_waiting_room.lv2.back.exterior": "candidate",
"staff_waiting_room.lv2.back.interior": "candidate",
"staff_waiting_room.lv3.front.exterior": "candidate",
"staff_waiting_room.lv3.front.interior": "candidate",
"staff_waiting_room.lv3.back.exterior": "candidate",
"staff_waiting_room.lv3.back.interior": "candidate",
"staff_dormitory.lv1.front.exterior": "candidate",
"staff_dormitory.lv1.front.interior": "candidate",
"staff_dormitory.lv1.back.exterior": "candidate",
"staff_dormitory.lv1.back.interior": "candidate",
"staff_dormitory.lv2.front.exterior": "candidate",
"staff_dormitory.lv2.front.interior": "candidate",
"staff_dormitory.lv2.back.exterior": "candidate",
"staff_dormitory.lv2.back.interior": "candidate",
"staff_dormitory.lv3.front.exterior": "candidate",
"staff_dormitory.lv3.front.interior": "candidate",
"staff_dormitory.lv3.back.exterior": "candidate",
"staff_dormitory.lv3.back.interior": "candidate",
"security_station.lv1.front.exterior": "candidate",
"security_station.lv1.front.interior": "candidate",
"security_station.lv1.back.exterior": "candidate",
"security_station.lv1.back.interior": "candidate",
"security_station.lv2.front.exterior": "candidate",
"security_station.lv2.front.interior": "candidate",
"security_station.lv2.back.exterior": "candidate",
"security_station.lv2.back.interior": "candidate",
"security_station.lv3.front.exterior": "candidate",
"security_station.lv3.front.interior": "candidate",
"security_station.lv3.back.exterior": "candidate",
"security_station.lv3.back.interior": "candidate",
"cleaning_room.lv1.front.exterior": "candidate",
"cleaning_room.lv1.front.interior": "candidate",
"cleaning_room.lv1.back.exterior": "candidate",
"cleaning_room.lv1.back.interior": "candidate",
"cleaning_room.lv2.front.exterior": "candidate",
"cleaning_room.lv2.front.interior": "candidate",
"cleaning_room.lv2.back.exterior": "candidate",
"cleaning_room.lv2.back.interior": "candidate",
"cleaning_room.lv3.front.exterior": "candidate",
"cleaning_room.lv3.front.interior": "candidate",
"cleaning_room.lv3.back.exterior": "candidate",
"cleaning_room.lv3.back.interior": "candidate",
"infirmary.lv1.front.exterior": "candidate",
"infirmary.lv1.front.interior": "candidate",
"infirmary.lv1.back.exterior": "candidate",
"infirmary.lv1.back.interior": "candidate",
"infirmary.lv2.front.exterior": "candidate",
"infirmary.lv2.front.interior": "candidate",
"infirmary.lv2.back.exterior": "candidate",
"infirmary.lv2.back.interior": "candidate",
"infirmary.lv3.front.exterior": "candidate",
"infirmary.lv3.front.interior": "candidate",
"infirmary.lv3.back.exterior": "candidate",
"infirmary.lv3.back.interior": "candidate",
"original_facility_24.lv1.front.exterior": "candidate",
"original_facility_24.lv1.front.interior": "candidate",
"original_facility_24.lv1.back.exterior": "candidate",
"original_facility_24.lv1.back.interior": "candidate",
"original_facility_24.lv2.front.exterior": "candidate",
"original_facility_24.lv2.front.interior": "candidate",
"original_facility_24.lv2.back.exterior": "candidate",
"original_facility_24.lv2.back.interior": "candidate",
"original_facility_24.lv3.front.exterior": "candidate",
"original_facility_24.lv3.front.interior": "candidate",
"original_facility_24.lv3.back.exterior": "candidate",
"original_facility_24.lv3.back.interior": "candidate",
"original_facility_25.lv1.front.exterior": "candidate",
"original_facility_25.lv1.front.interior": "candidate",
"original_facility_25.lv1.back.exterior": "candidate",
"original_facility_25.lv1.back.interior": "candidate",
"original_facility_25.lv2.front.exterior": "candidate",
"original_facility_25.lv2.front.interior": "candidate",
"original_facility_25.lv2.back.exterior": "candidate",
"original_facility_25.lv2.back.interior": "candidate",
"original_facility_25.lv3.front.exterior": "candidate",
"original_facility_25.lv3.front.interior": "candidate",
"original_facility_25.lv3.back.exterior": "candidate",
"original_facility_25.lv3.back.interior": "candidate",
"original_facility_26.lv1.front.exterior": "candidate",
"original_facility_26.lv1.front.interior": "candidate",
"original_facility_26.lv1.back.exterior": "candidate",
"original_facility_26.lv1.back.interior": "candidate",
"original_facility_26.lv2.front.exterior": "candidate",
"original_facility_26.lv2.front.interior": "candidate",
"original_facility_26.lv2.back.exterior": "candidate",
"original_facility_26.lv2.back.interior": "candidate",
"original_facility_26.lv3.front.exterior": "candidate",
"original_facility_26.lv3.front.interior": "candidate",
"original_facility_26.lv3.back.exterior": "candidate",
"original_facility_26.lv3.back.interior": "candidate",
"guest_elevator.lv1.front.exterior": "candidate",
"guest_elevator.lv1.front.interior": "candidate",
"guest_elevator.lv1.back.exterior": "candidate",
"guest_elevator.lv1.back.interior": "candidate",
"guest_elevator.lv2.front.exterior": "candidate",
"guest_elevator.lv2.front.interior": "candidate",
"guest_elevator.lv2.back.exterior": "candidate",
"guest_elevator.lv2.back.interior": "candidate",
"guest_elevator.lv3.front.exterior": "candidate",
"guest_elevator.lv3.front.interior": "candidate",
"guest_elevator.lv3.back.exterior": "candidate",
"guest_elevator.lv3.back.interior": "candidate",
"service_elevator.lv1.front.exterior": "candidate",
"service_elevator.lv1.front.interior": "candidate",
"service_elevator.lv1.back.exterior": "candidate",
"service_elevator.lv1.back.interior": "candidate",
"service_elevator.lv2.front.exterior": "candidate",
"service_elevator.lv2.front.interior": "candidate",
"service_elevator.lv2.back.exterior": "candidate",
"service_elevator.lv2.back.interior": "candidate",
"service_elevator.lv3.front.exterior": "candidate",
"service_elevator.lv3.front.interior": "candidate",
"service_elevator.lv3.back.exterior": "candidate",
"service_elevator.lv3.back.interior": "candidate",
"original_facility_29.lv1.front.exterior": "candidate",
"original_facility_29.lv1.front.interior": "candidate",
"original_facility_29.lv1.back.exterior": "candidate",
"original_facility_29.lv1.back.interior": "candidate",
"original_facility_29.lv2.front.exterior": "candidate",
"original_facility_29.lv2.front.interior": "candidate",
"original_facility_29.lv2.back.exterior": "candidate",
"original_facility_29.lv2.back.interior": "candidate",
"original_facility_29.lv3.front.exterior": "candidate",
"original_facility_29.lv3.front.interior": "candidate",
"original_facility_29.lv3.back.exterior": "candidate",
"original_facility_29.lv3.back.interior": "candidate",
"original_facility_30.lv1.front.exterior": "candidate",
"original_facility_30.lv1.front.interior": "candidate",
"original_facility_30.lv1.back.exterior": "candidate",
"original_facility_30.lv1.back.interior": "candidate",
"original_facility_30.lv2.front.exterior": "candidate",
"original_facility_30.lv2.front.interior": "candidate",
"original_facility_30.lv2.back.exterior": "candidate",
"original_facility_30.lv2.back.interior": "candidate",
"original_facility_30.lv3.front.exterior": "candidate",
"original_facility_30.lv3.front.interior": "candidate",
"original_facility_30.lv3.back.exterior": "candidate",
"original_facility_30.lv3.back.interior": "candidate",
"heroine.anri.portrait_base": "missing",
"heroine.anri.portrait_expression": "missing",
"heroine.anri.portrait_costume": "missing",
"heroine.anri.portrait_damage": "missing",
"heroine.anri.portrait_dirt": "missing",
"heroine.anri.portrait_marks": "missing",
"heroine.anri.sd_idle": "candidate",
"heroine.anri.sd_walk": "candidate",
"heroine.anri.sd_work": "candidate",
"heroine.anri.sd_collapsed": "candidate",
"heroine.anri.sd_carry": "candidate",
"heroine.anri.sd_rescue": "candidate",
"heroine.anri.sd_rest": "candidate",
"heroine.anri.sd_breath": "candidate",
"heroine.anri.sd_secondary_motion": "candidate",
"heroine.anri.portrait_pregnancy": "missing",
"heroine.anri.portrait_route_style": "missing",
"heroine.anri.sd_restricted_loop": "candidate",
"heroine.anri.voice": "missing",
"heroine.fine.portrait_base": "missing",
"heroine.fine.portrait_expression": "missing",
"heroine.fine.portrait_costume": "missing",
"heroine.fine.portrait_damage": "missing",
"heroine.fine.portrait_dirt": "missing",
"heroine.fine.portrait_marks": "missing",
"heroine.fine.sd_idle": "candidate",
"heroine.fine.sd_walk": "candidate",
"heroine.fine.sd_work": "candidate",
"heroine.fine.sd_collapsed": "candidate",
"heroine.fine.sd_carry": "candidate",
"heroine.fine.sd_rescue": "candidate",
"heroine.fine.sd_rest": "candidate",
"heroine.fine.sd_breath": "candidate",
"heroine.fine.sd_secondary_motion": "candidate",
"heroine.fine.portrait_pregnancy": "missing",
"heroine.fine.portrait_route_style": "missing",
"heroine.fine.sd_restricted_loop": "candidate",
"heroine.fine.voice": "missing",
"heroine.tomari.portrait_base": "missing",
"heroine.tomari.portrait_expression": "missing",
"heroine.tomari.portrait_costume": "missing",
"heroine.tomari.portrait_damage": "missing",
"heroine.tomari.portrait_dirt": "missing",
"heroine.tomari.portrait_marks": "missing",
"heroine.tomari.sd_idle": "candidate",
"heroine.tomari.sd_walk": "candidate",
"heroine.tomari.sd_work": "candidate",
"heroine.tomari.sd_collapsed": "candidate",
"heroine.tomari.sd_carry": "candidate",
"heroine.tomari.sd_rescue": "candidate",
"heroine.tomari.sd_rest": "candidate",
"heroine.tomari.sd_breath": "candidate",
"heroine.tomari.sd_secondary_motion": "candidate",
"heroine.tomari.portrait_pregnancy": "missing",
"heroine.tomari.portrait_route_style": "missing",
"heroine.tomari.sd_restricted_loop": "candidate",
"heroine.tomari.voice": "missing",
"heroine.amelia.portrait_base": "missing",
"heroine.amelia.portrait_expression": "missing",
"heroine.amelia.portrait_costume": "missing",
"heroine.amelia.portrait_damage": "missing",
"heroine.amelia.portrait_dirt": "missing",
"heroine.amelia.portrait_marks": "missing",
"heroine.amelia.sd_idle": "candidate",
"heroine.amelia.sd_walk": "candidate",
"heroine.amelia.sd_work": "candidate",
"heroine.amelia.sd_collapsed": "candidate",
"heroine.amelia.sd_carry": "candidate",
"heroine.amelia.sd_rescue": "candidate",
"heroine.amelia.sd_rest": "candidate",
"heroine.amelia.sd_breath": "candidate",
"heroine.amelia.sd_secondary_motion": "candidate",
"heroine.amelia.portrait_pregnancy": "missing",
"heroine.amelia.portrait_route_style": "missing",
"heroine.amelia.sd_restricted_loop": "candidate",
"heroine.amelia.voice": "missing",
"heroine.liz.portrait_base": "missing",
"heroine.liz.portrait_expression": "missing",
"heroine.liz.portrait_costume": "missing",
"heroine.liz.portrait_damage": "missing",
"heroine.liz.portrait_dirt": "missing",
"heroine.liz.portrait_marks": "missing",
"heroine.liz.sd_idle": "candidate",
"heroine.liz.sd_walk": "candidate",
"heroine.liz.sd_work": "candidate",
"heroine.liz.sd_collapsed": "candidate",
"heroine.liz.sd_carry": "candidate",
"heroine.liz.sd_rescue": "candidate",
"heroine.liz.sd_rest": "candidate",
"heroine.liz.sd_breath": "candidate",
"heroine.liz.sd_secondary_motion": "candidate",
"heroine.liz.portrait_pregnancy": "missing",
"heroine.liz.portrait_route_style": "missing",
"heroine.liz.sd_restricted_loop": "candidate",
"heroine.liz.voice": "missing",
"heroine.mimi.portrait_base": "missing",
"heroine.mimi.portrait_expression": "missing",
"heroine.mimi.portrait_costume": "missing",
"heroine.mimi.portrait_damage": "missing",
"heroine.mimi.portrait_dirt": "missing",
"heroine.mimi.portrait_marks": "missing",
"heroine.mimi.sd_idle": "candidate",
"heroine.mimi.sd_walk": "candidate",
"heroine.mimi.sd_work": "candidate",
"heroine.mimi.sd_collapsed": "candidate",
"heroine.mimi.sd_carry": "candidate",
"heroine.mimi.sd_rescue": "candidate",
"heroine.mimi.sd_rest": "candidate",
"heroine.mimi.sd_breath": "candidate",
"heroine.mimi.sd_secondary_motion": "candidate",
"heroine.mimi.portrait_pregnancy": "missing",
"heroine.mimi.portrait_route_style": "missing",
"heroine.mimi.sd_restricted_loop": "candidate",
"heroine.mimi.voice": "missing",
"heroine.satsuki.portrait_base": "missing",
"heroine.satsuki.portrait_expression": "missing",
"heroine.satsuki.portrait_costume": "missing",
"heroine.satsuki.portrait_damage": "missing",
"heroine.satsuki.portrait_dirt": "missing",
"heroine.satsuki.portrait_marks": "missing",
"heroine.satsuki.sd_idle": "candidate",
"heroine.satsuki.sd_walk": "candidate",
"heroine.satsuki.sd_work": "candidate",
"heroine.satsuki.sd_collapsed": "candidate",
"heroine.satsuki.sd_carry": "candidate",
"heroine.satsuki.sd_rescue": "candidate",
"heroine.satsuki.sd_rest": "candidate",
"heroine.satsuki.sd_breath": "candidate",
"heroine.satsuki.sd_secondary_motion": "candidate",
"heroine.satsuki.portrait_pregnancy": "missing",
"heroine.satsuki.portrait_route_style": "missing",
"heroine.satsuki.sd_restricted_loop": "candidate",
"heroine.satsuki.voice": "missing",
"rival.rai.portrait_base": "missing",
"rival.rai.portrait_expression": "missing",
"rival.rai.portrait_costume": "missing",
"rival.rai.portrait_damage": "missing",
"rival.rai.portrait_dirt": "missing",
"rival.rai.sd_idle": "candidate",
"rival.rai.sd_walk": "candidate",
"rival.rai.sd_work": "candidate",
"rival.rai.sd_collapsed": "candidate",
"rival.rai.sd_carry": "candidate",
"rival.rai.sd_rescue": "candidate",
"rival.rai.sd_rest": "candidate",
"rival.rai.sd_breath": "candidate",
"rival.rai.voice": "missing",
"rival.riesenbalt.portrait_base": "missing",
"rival.riesenbalt.portrait_expression": "missing",
"rival.riesenbalt.portrait_costume": "missing",
"rival.riesenbalt.portrait_damage": "missing",
"rival.riesenbalt.portrait_dirt": "missing",
"rival.riesenbalt.sd_idle": "candidate",
"rival.riesenbalt.sd_walk": "candidate",
"rival.riesenbalt.sd_work": "candidate",
"rival.riesenbalt.sd_collapsed": "candidate",
"rival.riesenbalt.sd_carry": "candidate",
"rival.riesenbalt.sd_rescue": "candidate",
"rival.riesenbalt.sd_rest": "candidate",
"rival.riesenbalt.sd_breath": "candidate",
"rival.riesenbalt.voice": "missing",
"rival.sou.portrait_base": "missing",
"rival.sou.portrait_expression": "missing",
"rival.sou.portrait_costume": "missing",
"rival.sou.portrait_damage": "missing",
"rival.sou.portrait_dirt": "missing",
"rival.sou.sd_idle": "candidate",
"rival.sou.sd_walk": "candidate",
"rival.sou.sd_work": "candidate",
"rival.sou.sd_collapsed": "candidate",
"rival.sou.sd_carry": "candidate",
"rival.sou.sd_rescue": "candidate",
"rival.sou.sd_rest": "candidate",
"rival.sou.sd_breath": "candidate",
"rival.sou.voice": "missing",
"rival.additional_unfixed": "missing",
"facility.visual_states": "candidate",
"unit.visual_states": "candidate",
"background.front": "candidate",
"background.back": "candidate",
"ui.front_skin": "candidate",
"ui.back_skin": "candidate",
"ui.emotion_graph": "missing",
"ui.shield_gauge": "missing",
"ui.camera_overlay": "missing",
"ui.camera_icon": "missing",
"ui.grid_connection": "candidate",
"ui.bubbles": "candidate",
"ui.event_log": "candidate",
"ui.cut_in": "missing",
"ui.resource_hud": "candidate",
"ui.layer_controls": "candidate",
"effect.layer_ripple": "missing",
"effect.shield": "missing",
"effect.smoke": "missing",
"effect.mana_light": "missing",
"audio.front_ambience": "missing",
"audio.back_ambience": "missing",
"audio.restricted_se": "missing",
"audio.character_voice": "missing",
"content.mob_restricted_still": "missing",
"audio.front_bgm": "candidate",
"audio.back_bgm": "candidate",
"audio.ui": "candidate",
"content.anri.pure_love.event_cg": "missing",
"content.anri.ntr.event_cg": "missing",
"content.anri.fall.event_cg": "missing",
"content.fine.pure_love.event_cg": "missing",
"content.fine.ntr.event_cg": "missing",
"content.fine.fall.event_cg": "missing",
"content.tomari.pure_love.event_cg": "missing",
"content.tomari.ntr.event_cg": "missing",
"content.tomari.fall.event_cg": "missing",
"content.amelia.pure_love.event_cg": "missing",
"content.amelia.ntr.event_cg": "missing",
"content.amelia.fall.event_cg": "missing",
"content.liz.pure_love.event_cg": "missing",
"content.liz.ntr.event_cg": "missing",
"content.liz.fall.event_cg": "missing",
"content.mimi.pure_love.event_cg": "missing",
"content.mimi.ntr.event_cg": "missing",
"content.mimi.fall.event_cg": "missing",
"content.satsuki.pure_love.event_cg": "missing",
"content.satsuki.ntr.event_cg": "missing",
"content.satsuki.fall.event_cg": "missing",
"characters.mob_guests": "candidate",
"characters.mob_staff": "candidate",
"characters.mob_employment": "candidate",
"characters.other_sub": "missing",
"content.end_states": "missing",
"characters.staff_role.ウェイター": "candidate",
"characters.staff_role.受付係": "candidate",
"characters.staff_role.バニー": "candidate",
"characters.staff_role.シェフ": "candidate",
"characters.staff_role.清掃員": "candidate",
"characters.staff_role.運搬員": "candidate",
"characters.staff_role.救護班": "candidate",
"characters.staff_role.娼婦": "candidate",
"characters.staff_role.警備員": "candidate",
"characters.staff_role.調教係": "candidate",
"characters.guest_group.貴族": "candidate",
"characters.guest_group.聖職者": "candidate",
"characters.guest_group.エルフ": "candidate",
"characters.guest_group.魔族/亜人": "candidate",
"ancillary.客用通路": "candidate",
"ancillary.裏通路": "candidate",
"ancillary.従業員ドア": "candidate",
"ancillary.階段": "candidate",
"ancillary.リネンシュート": "candidate",
"ancillary.隠し扉": "candidate",
"ancillary.受付/精算所": "candidate",
"ancillary.金庫室": "candidate",
"ancillary.購買部": "candidate",
"ancillary.闇銀行": "candidate"
},
"source_pins": {
"scripts/ui/pixel_tower_art.gd": "71df9b8400cb883a5bb1c89729f80c77e734df503fc54154be3e486adb8391df",
"scripts/ui/standard_room_art.gd": "8f0f2af2a3903fc1debc760037dc8fab92e4fff1e49803fcb56a56ab1f04defa",
"scripts/ui/infirmary_room_art.gd": "f8333f7915fe453eaee6f00ff1b1539b2ae67fecd508566292bf9ea986531a75",
"assets/kenney/tiny_town/Tilemap/tilemap_packed.png": "3a54d99ecde790d4fdea207a3644cf130fc56fa838f1beb1507c185a95b8e902",
"assets/kenney/tiny_dungeon/Tilemap/tilemap_packed.png": "d24e60a41e4ac7a745c0304dfde121143688557f40215f23221c29cfe683825f",
"scripts/ui/pixel_people.gd": "a171703083aa2d00f8be2b63e1daef9c41717c8fe59d8056878bc4b7df1e0b0c",
"assets/themes/japanese_fantasy/world-front-v1.png": "02b52ea05bdb4bbe78b8c905374052505bb73411eb7f2b0578e9b1a82994cde5",
"scenes/main/world_preview.gd": "75d5b0bd23204f5a485540512e44b89e1d2a4596b368f70177a238ba078ff42d",
"assets/themes/japanese_fantasy/world-back-v1.png": "2b0dbf07c17e677ed023c56b1e90f013c40362f46c427950033868b042508c7c",
"assets/themes/japanese_fantasy/ui-skin-v1.png": "4b4906cc9c6ed3fdb5330bfc11177376e5fec10afa3f2dac9318dbaf71833ff2",
"assets/themes/japanese_fantasy/visual-theme-v1.tres": "42e968ba5e35c228d3ff372f92a8e249ec3a743045be0a3ec158556944c0bc18",
"scenes/main/main.gd": "41df8857f9658c17b01361350979caa942b9326c82c9f176517972c2a9692f55",
"scripts/ui/paired_bgm.gd": "a7fe9311f348975a380feced102702ad3ee91439b9511006f0ff6d29540f5836",
"assets/audio/bgm/tree_theme_front_candidate.wav": "6df0a7af307327f703c9325f5ca2ac456888102d50ef1fa76bf4cdf19d2b86cb",
"assets/audio/bgm/tree_theme_back_candidate.wav": "efe4cc1aa588661d73376720e4278427f7220ce93a5d446f198c5af607c141ca",
"assets/audio/ui/click_001.ogg": "ccfb7fa0cccdd9faec0eb16033c732b1e308d139d80f799161495d58f7adcdb9",
"assets/audio/ui/confirmation_001.ogg": "063564703b6094d70718a3e787a55cc9141611e4ecd6b6637f8828f79b4a8c3a",
"assets/audio/ui/error_008.ogg": "eba17ecb2a426bfd4a8a6acff5f8a86202b6424a77af0fd842e37809a1ab6d81",
"assets/audio/ui/bong_001.ogg": "d21d0f0b782445db579d11e2506b24cd1ac9d664ee33aeaf807761aa7b6fd710"
},
"unit_proofs": {}
}
@@ -0,0 +1,33 @@
"""Initialize a compact ledger. Not invoked by read-only verification.
All historic fields are retained by raw-SHA references. This initializer
replaces selection work; never use it to refresh pins after a source change.
"""
import hashlib
import json
from pathlib import Path
ROOT = Path(__file__).resolve().parents[5]
HERE = Path(__file__).resolve().parent
INPUT = 'docs/spec/inputs/P22-02-accepted-usage.json'
CURRENT = 'docs/plans/original-completion-2026-10-02/checkpoints/p22-02-slot-contract-r02/all-slot-current-candidate-contracts.json'
EVIDENCE = 'docs/plans/original-completion-2026-10-02/checkpoints/p22-02-current-contract-r01'
def build():
paths = [INPUT, CURRENT] + [str(p.relative_to(ROOT)) for p in sorted((ROOT / EVIDENCE).iterdir()) if p.is_file()]
pins = {p: hashlib.sha256((ROOT / p).read_bytes()).hexdigest() for p in paths}
current = json.loads((ROOT / CURRENT).read_text())
ledger = {
'schema': 'p22-reference-contract-v2',
'references': pins,
'reconstruction': 'All accepted codec fields and snapshot fields retained by raw SHA; selections inherit entire snapshot contracts by identity, including every unmade condition.',
'selections': {c['id']: ('candidate' if c['candidate_refs'] else 'missing') for c in current['contracts']},
'source_pins': {p: f['current_raw_sha256'] for p, f in current['candidate_pool'].items()},
'unit_proofs': {},
}
(HERE / 'asset-contracts.json').write_text(json.dumps(ledger, ensure_ascii=False, indent=2) + '\n')
if __name__ == '__main__':
build()
@@ -0,0 +1,195 @@
"""Runner-owned tests. No file writes, product execution, or real PASS from fixtures."""
import copy
import importlib.util
import io
import json
from pathlib import Path
import sys
import unittest
from unittest import mock
sys.dont_write_bytecode = True
ROOT = Path(__file__).resolve().parents[5]
spec = importlib.util.spec_from_file_location('p22_checker', ROOT / 'tools/check_p22_asset_contracts.py')
m = importlib.util.module_from_spec(spec)
spec.loader.exec_module(m)
class ContractTests(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.ledger = m.read(m.OUT + 'asset-contracts.json')
cls.accepted = m.read(m.INPUT)
_, cls.records = m.accepted_records(cls.accepted)
cls.snapshot = m.read(m.CURRENT)
def rejected(self, function, *args):
with self.assertRaises((ValueError, OSError, KeyError, TypeError)):
function(*args)
def proof(self, kind, subject):
return {'kind': kind, 'subject': copy.deepcopy(subject), 'result': 'accepted',
'issuer': {'role': 'root', 'name': 'isolated fixture; never P22 evidence'},
'observations': [{'explanation': 'Synthetic pure-function observation only',
'anchors': [{'path': 'synthetic.txt', 'sha256': 'a' * 64,
'line': 1, 'text': 'synthetic'}]}]}
def fixture(self):
row = {'slot_id': 'isolated', 'usage_condition': 'isolated pure function only',
'required_file_count': 1}
fmt = {'png_width': 16, 'png_height': 16}
sources = {'synthetic.png': {'sha256': 'a' * 64, 'format': fmt}}
asset = {'path': 'synthetic.png', 'sha256': 'a' * 64, 'format': copy.deepcopy(fmt),
'region': [0, 0, 16, 16], 'code_anchor': None, 'kind': 'image'}
return row, sources, asset
def test_isolated_reachable_and_wrong_proof_quantity_pin(self):
row, sources, asset = self.fixture()
m.asset_matches(asset, row, sources)
quantities = dict.fromkeys(m.QUANTITIES)
quantities['required_file_count'] = 1
m.quantities_valid(quantities, row)
subject = {'asset': asset, 'quantities': quantities, 'record_sha': m.semantic(row)}
fit = self.proof('fit', subject)
selected = {'isolated': m.proof_matches(fit, 'fit', subject)}
unit = {kind: self.proof(kind, subject) for kind in ('mandatory_scope', 'disclosure')}
self.assertTrue(m.technical_readiness(['isolated'], selected, unit, subject))
# Never run check() against these fixtures or count them as real assets.
bad = copy.deepcopy(fit)
bad['subject']['asset']['sha256'] = 'b' * 64
self.rejected(m.proof_matches, bad, 'fit', subject)
bad_quantity = dict(quantities, required_file_count=2)
self.rejected(m.quantities_valid, bad_quantity, row)
bad_asset = dict(asset, sha256='b' * 64)
self.rejected(m.asset_matches, bad_asset, row, sources)
self.rejected(m.proof_matches, True, 'fit', subject)
def test_nonvacuous_and_unmade_denominator(self):
self.rejected(m.technical_readiness, [], {}, {}, {})
self.rejected(m.technical_readiness, ['made', 'unmade'], {'made': True}, {}, {})
self.assertFalse(m.technical_readiness(['made', 'unmade'], {'made': True, 'unmade': False}, {}, {}))
self.rejected(m.technical_readiness, ['x'], {'x': 'true'}, {}, {})
def test_format_layout_state_and_quantity(self):
row, sources, asset = self.fixture()
for bad in (dict(asset, format={'png_width': 17, 'png_height': 16}),
dict(asset, region=[0, 0, 17, 16]),
dict(asset, region=[True, 0, 16, 16]),
dict(asset, kind='placeholder_media')):
self.rejected(m.asset_matches, bad, row, sources)
self.rejected(m.asset_matches, asset, {'group_id': 'state'}, sources)
self.rejected(m.quantities_valid, dict.fromkeys(m.QUANTITIES, True), row)
def test_codec_and_strict_json(self):
doc = {'keys': ['x'], 'strings': ['s'], 'pool': [], 'files': ['d', 0, 1]}
self.assertEqual(m.decode(doc), {'x': 1})
for files in (['s', True], ['s', -1], ['d', 0, 1, 0, 2],
['unknown'], ['r', 0], float('nan'), float('inf')):
self.rejected(m.decode, dict(doc, files=files))
self.rejected(m.decode, dict(doc, pool=[['l', ['r', 0]]], files=['r', 0]))
self.rejected(m.decode, dict(doc, pool=[['s', 0]], files=['r', 0]))
for text in ('{"x":1,"x":2}', '{"x":NaN}', '{"x":Infinity}', '{"x":1e999}'):
self.rejected(m.loads, text)
def test_path_escape(self):
for path in ('../escape', '/tmp/escape', 'assets/../../escape'):
self.rejected(m.safe_path, path)
def test_real_coverage_and_source_omission(self):
for action in ('omit_identity', 'duplicate_identity', 'omit_source', 'duplicate_source'):
d = copy.deepcopy(self.snapshot)
if action == 'omit_identity':
d['contracts'].pop()
elif action == 'duplicate_identity':
d['contracts'].append(d['contracts'][0])
elif action == 'omit_source':
d['candidate_pool'].pop(next(iter(d['candidate_pool'])))
else:
d['contracts'][0]['candidate_refs'].append(d['contracts'][0]['candidate_refs'][0])
self.rejected(m.reference_contracts, d, self.records)
def test_real_source_missing_and_stale(self):
path, digest = next(iter(self.ledger['source_pins'].items()))
self.rejected(m.pinned, path, '0' * 64)
self.rejected(m.pinned, m.OUT + 'nonexistent-proof.json', digest)
def test_real_png_crc_and_layout(self):
path = 'assets/kenney/tiny_town/Tilemap/tilemap_packed.png'
data = m.raw(path)
fmt = m.png_format(data)
self.assertEqual((fmt['png_width'], fmt['png_height']), (192, 176))
damaged = bytearray(data)
damaged[20] ^= 1
self.rejected(m.png_format, bytes(damaged))
sources = {path: {'sha256': m.sha(data), 'format': fmt}}
asset = {'path': path, 'sha256': m.sha(data), 'format': fmt,
'region': [191, 0, 16, 16], 'code_anchor': None, 'kind': 'image'}
self.rejected(m.asset_matches, asset, {}, sources)
def test_real_reference_mismatch(self):
a = copy.deepcopy(self.snapshot['contracts'][0]['source_anchors'][0])
a['text'] += 'not the actual reference'
self.rejected(m.anchor, a)
def test_real_license_bytes_and_rights_subject(self):
pack = m.read(m.EVIDENCE + 'publisher-archive-byte-verification.json')['packs'][0]
license_row = next(x for x in pack['members'] if x['archive_member'] == 'License.txt')
path, digest = license_row['repo_path'], license_row['raw_sha256']
original_raw = m.raw
with mock.patch.object(m, 'raw', side_effect=lambda p: b'fake license' if p == path else original_raw(p)):
self.rejected(m.pinned, path, digest)
subject = {'source': next(iter(self.ledger['source_pins'])),
'rights': {'creator': 'unknown', 'license': 'unknown'}}
proof = self.proof('rights', subject)
changed = copy.deepcopy(subject)
changed['rights']['license'] = 'CC0'
self.rejected(m.proof_matches, proof, 'rights', changed)
def test_real_false_finished_and_fake_booleans(self):
c = self.snapshot['contracts'][0]
row = self.records[c['id']][1]
for value in (True, False, [], {'state': 'finished'}, 'selected'):
self.rejected(m.selection_ready, c['id'], row, c, value, {})
self.rejected(m.receipt, {'path': m.OUT + 'validation.json', 'sha256': '0' * 64, 'index': 0}, 'fit', {})
self.rejected(m.receipt, True, 'fit', {})
def test_real_selected_contract_unknown_rights_and_forged_proof(self):
c = self.snapshot['contracts'][0]
row = self.records[c['id']][1]
path = 'assets/kenney/tiny_town/Tilemap/tilemap_packed.png'
data = m.raw(path)
sources = {path: {'sha256': m.sha(data), 'format': m.png_format(data)}}
product = 'scripts/ui/pixel_tower_art.gd'
product_data = m.raw(product)
ref = {'path': product, 'sha256': m.sha(product_data), 'line': 1,
'text': product_data.decode().splitlines()[0]}
rights_path = 'assets/kenney/tiny_town/License.txt'
s = {'asset': {'path': path, 'sha256': m.sha(data), 'format': sources[path]['format'],
'region': [0, 0, 16, 16], 'code_anchor': None, 'kind': 'image'},
'creator': 'Fixture declaration, not a real attribution',
'rights': {'license': 'unknown', 'origin': 'fixture only',
'documents': [{'path': rights_path, 'sha256': m.sha(m.raw(rights_path))}]},
'name': Path(path).name, 'replacement_chain': [c['id'], path], 'references': [ref],
'quantities': dict.fromkeys(m.QUANTITIES), 'quantity_basis': 'Fixture, no final count',
'usability': {'display': 'Requires actual exact-use display', 'hearing': 'Fixture image'}}
choice = {'state': 'selected', 'contract': s, 'proofs': dict.fromkeys(m.PROOF_KINDS, True)}
with self.assertRaisesRegex(ValueError, 'unknown license'):
m.selection_ready(c['id'], row, c, choice, sources)
s['rights']['license'] = 'CC0'
with self.assertRaisesRegex(ValueError, 'proof reference schema'):
m.selection_ready(c['id'], row, c, choice, sources)
def test_registered_cli_real_data_is_not_ready(self):
argv = ['checker', '--verify-only', '--accepted-input', m.INPUT, '--require-ready']
with mock.patch.object(sys, 'argv', argv), mock.patch('sys.stdout', new_callable=io.StringIO) as output:
code = m.main()
result = json.loads(output.getvalue())
self.assertEqual(code, 2, result)
self.assertTrue(result['record_integrity'])
self.assertFalse(result['validation_ready'])
self.assertEqual(result['pending_identity_count'], 614)
self.assertFalse(result['acceptance_claimed'])
if __name__ == '__main__':
unittest.main()
@@ -0,0 +1,62 @@
{
"task_id": "P22-02",
"formal_tests": "not_run; Runner owns execution",
"original_unit_ready": false,
"acceptance_claimed": false,
"spec_comparison": "SHA256 of UTF-8 stdout.strip; raw file differs only by trailing newline",
"spec_sha256": "f252de3c5cff7ebfa62322ae2f2df09fb80a44bc59eb286b76d4acb4c12ca875",
"spec_raw_sha256": "c26c0b12cf7e7a7c46e671acde2e00762904732c1cd6381a53836e3d7b3f9824",
"accepted_input_raw_sha256": "45fa52acf0c8bd4dd58c3b40b681cb92066f05d617df157fc18370a5e8816281",
"ledger_bytes": 35441,
"complete_packet_bytes": null,
"complete_packet_verified_under_limit": false,
"packet_measurement_blocker": "Required patch and packet evidence/proposal absent from this worktree; normal project reference access denied. 487283 is prospective, not measured.",
"syntax_ast_parse": "passed; not formal validation",
"complete_packet_limit": 500000,
"runner_required": [
"exact static validation",
"meaningful negatives",
"packet byte total",
"applicable display and hearing",
"independent Opus review",
"integration and final original acceptance"
],
"expected_exit_codes": {
"record_integrity_if_valid": 0,
"require_ready_with_current_unmet_conditions": 2,
"integrity_error": 1
},
"original_incomplete": [
"614 exact uses lack completed selected usable assets; 495 candidates and 119 missing are not completion",
"final per-use naming/resolution/frame/layout/replacement references",
"creator and rights gaps including 20 media; internal BGM origin is not final approval",
"mandatory unmade/disclosure gaps; D08/D09 content and quantities unknown",
"applicable display/hearing evidence",
"Root static validation and meaningful negatives",
"independent Opus review",
"integration and final original 30 packages/88 delivery units acceptance"
],
"local_bounded_checks": {
"interpreter": "python3 -B (python unavailable)",
"ast_parse": "passed: checker, build_contract.py, test_contract.py",
"test_count": 13,
"test_exit_code": 0,
"ordinary_exit_code": 0,
"require_ready_exit_code": 2,
"formal_runner_execution": false
},
"checker_output": {
"acceptance_claimed": false,
"accepted_identity_count": 614,
"candidate_source_count": 19,
"original_completion": "not_claimed; requires formal validate, independent review, integration, final",
"pending_identity_count": 614,
"record_integrity": true,
"selected_usable_count": 0,
"unit_proofs_missing": [
"disclosure",
"mandatory_scope"
],
"validation_ready": false
}
}
@@ -23,3 +23,5 @@ Claude Opus5.5の記録済み判断で、同じ登録タスク/既存worktreeを
追補r07(コード候補不変9641ed52): 実配置受付の工事70percent/min444を通常quick save→通常別名slot、既存manual_ui全4filesの内容保全、別PID39701→40866の復元直後全snapshot118528B byte一致を取得。通常再開で工事完成をCUA観測、後者の独立正式pointer/resumeは未達として保持。最初のOpus reviewは採取provenance資料不足でchanges_requested、実行済みRoot before/after全文/方法/日時とnative tick、全4live rehashを補い再review限定PASS、新engine再実行0。全88正式完了増加0。
追補r08: 同一9641でnative49041の通常有効受付1command/job/charge→重複拒否text→menu3/modal→取消の全Runtime・選択・path保全、PNG8とraw/JSON snapshotsを固定、別Opus限定PASS。Rootcollectorのr04 field誤りFAILを保持しr05のみ有効。全modal/配属/背後入力/正常main_scene起動/上流/最終review/Windowsを未達として維持。MP01承認用候補案は追加1回の直接許可(call_de866e18b25942ee8992263aa0189278)を受け、個別cap2・使用済み2を保持。同一SHAの既存2文書を再利用し、実Opus5.5のaction run/Sol選択に基づく同一登録ワーカーを起動。追加許可待ちは解消し、正式検証・独立レビュー・統合はまだ未了。製品数値・P06-01受入・30/88は不変。
追補r09: MP-01-r02は同じ登録タスクで修正2/2→提出6b78f8fd→正式資料検証/別Opus独立review→統合/最終65a4fe2bを完了。成果は未承認の数値・更新順序・移行候補の2文書で、P06-01/P24-02の正式受入を代用しない。旧「資料検証・レビュー・統合未了」は現版について解消。次の原成果候補はP13-03の既存修正・証拠再照合。
@@ -223,7 +223,7 @@
"ASSETS_PLATFORM_AUDIT.md": "a3a4b8ca0fb39a9abf88692285d26aa879815e092352ba304ef2758e71da50bd",
"ATOMIC_REGISTER.md": "6070143b85b7c3b9b73d7c9768d88d2dae4d20407ad54a563cb6ffd74f2373ae",
"ATOMIC_SEMANTIC_REVIEW.md": "c156b1fb57c2b4a900f27a19049510f3e9616e723d5edb3417f50d733de5be48",
"IMPLEMENTATION_PLAN.md": "2f1a933d1f47966b66945efc2d44747d7b9ea63cd223271fad0fad010f080ba3",
"IMPLEMENTATION_PLAN.md": "e3d5a83b65207a402f8b36a06f9893ab969adcbb5b97915930af1358b15749e1",
"IMPORT_UNICODE_AUDIT.md": "88b2382bfbb3411fece8be7e6004ba21d8bf6a47e9d1f3cf573ea6638f79c12f",
"P09_VALUE_CONTRACTS.md": "c5abdc4543e54033b1fcfd0943cba266f664d8c10968965fd36ade40da488a25",
"PERFORMANCE_AUDIT.md": "c75e806acf825fc4a61f773a2cce7e71be335a1e25dbb15d98091097e8dc47c1",
@@ -254,6 +254,6 @@
"validate_facility_value_contracts.py": "91640e2a76cd6cc9186f7b85c0bf379b24b6cac0d48962815235ee628e7ae43e",
"validate_plan.py": "23678227d9b3c556f1bd903f4b5b3147c4a82ce5085e10055481026803451b80",
"validator_update_checks.json": "f997d0f3de2cea29550840b1d5cb23647d64f81329de46758551e2b6c8fecc27",
"work_packages.json": "1d2e35b9c38e8fc18ac256620aabcf576221562dc3178548c77d5cdac2a14b9f"
"work_packages.json": "af340d1897186cf20f21e5c441929156bcdba41d21d1a4806977da7a5511fea8"
}
}
@@ -6170,7 +6170,7 @@
},
"legacy_state": "in_progress",
"state_scope": "package-level; completed means whole package accepted; partial implementation is not completion",
"current_summary": "停電、厨房、救護の停止復帰は部分実装。有限マナ供給の契約が残る。 制御したEV乗車中救護の停電保存/再開691/0・10全状態pair・無制限journal各9件を限定照合。安全階での緊急降車・自然停電・全館停止・通常UIは未受入。 最新現1299参照で通常建設からの物流/厨房の制御停電・復旧、2正式保存/別PID全状態一致を460/0で限定受入。利用中サービス0件なので途中販売/中断は未受入。全P06未完。 現版の自然入館客の食事/宿泊の制御停電・復旧・一回請求、既存RAIDED休止時の安全終了と正式保存別PID全状態一致を1906/0で限定受入。再開の不具合仮説は反証、ゲーム変更0。全P06未完。 2026-10-12: 旧限定停電証拠から現Runtime等13sourceが変化しており現受入へ自動適用しない。P06-01の原契約監査をRunner経由で開始。正式完了なし。 MP-01-r02継続: 追加1回を直接承認(call_de866e18b25942ee8992263aa0189278)、個別cap2/使用2を保持。同一SHAの旧案2文書を再利用し、実Opus5.5のrun判断/Sol選択で同一登録ワーカーを起動。資料の正式検証・独立レビュー・統合は未了。製品値/P06-01受入/30・88分母は未変更。",
"current_summary": "停電、厨房、救護の停止復帰は部分実装。有限マナ供給の契約が残る。 制御したEV乗車中救護の停電保存/再開691/0・10全状態pair・無制限journal各9件を限定照合。安全階での緊急降車・自然停電・全館停止・通常UIは未受入。 最新現1299参照で通常建設からの物流/厨房の制御停電・復旧、2正式保存/別PID全状態一致を460/0で限定受入。利用中サービス0件なので途中販売/中断は未受入。全P06未完。 現版の自然入館客の食事/宿泊の制御停電・復旧・一回請求、既存RAIDED休止時の安全終了と正式保存別PID全状態一致を1906/0で限定受入。再開の不具合仮説は反証、ゲーム変更0。全P06未完。 2026-10-12: 旧限定停電証拠から現Runtime等13sourceが変化しており現受入へ自動適用しない。P06-01の原契約監査をRunner経由で開始。正式完了なし。 MP-01-r02承認用資料は追加許可後に同じSol担当で修正し、提出6b78f8fd・正式検証・別Opus5.5独立review PASS・最新main統合/最終検証65a4fe2bを完了。修正2/2保持。全37需要・53source pin・21候補比較・炉の容量判定・旧0/再送/D05を整理。数値/人物分類/更新順序/保存移行は未承認、製品未反映。P06-01はin_progress、原88正式完了増加0。",
"remaining_deliverables": [
{
"id": "P06-01",
@@ -6197,17 +6197,23 @@
{
"path": "docs/plans/original-completion-2026-10-02/execution/mana-proposal-continuation-r03/counter-and-reuse-verification.json",
"sha256_at_integration": "933df166de1e249756e3f91e0a55ea86c0b14b1761de00b052713aa4a5096c0e",
"scope": "Actual task cap1/used1 and same-worktree original proposal byte equality; no worker or new values applied",
"scope": "Historical pre-approval cap1/used1 and byte-equal reuse check; superseded current state is formal-traceability-r02.json; no game acceptance",
"current_game_acceptance_inferred": false
},
{
"path": "docs/plans/original-completion-2026-10-02/execution/mana-proposal-continuation-r03/formal-traceability-r02.json",
"sha256_at_integration": "21eb3136124ed76f7cc9f063e78eea74a773412dd22976535bc54a02fd23db66",
"scope": "Completed owner-requested unapproved proposal artifact; validation, independent review, integration and final all pinned. Not P06-01 game acceptance.",
"current_game_acceptance_inferred": false
}
],
"progress_summary": "停電、厨房、救護の停止復帰は部分実装。有限マナ供給の契約が残る。 制御したEV乗車中救護の停電保存/再開691/0・10全状態pair・無制限journal各9件を限定照合。安全階での緊急降車・自然停電・全館停止・通常UIは未受入。 最新現1299参照で通常建設からの物流/厨房の制御停電・復旧、2正式保存/別PID全状態一致を460/0で限定受入。利用中サービス0件なので途中販売/中断は未受入。全P06未完。 現版の自然入館客の食事/宿泊の制御停電・復旧・一回請求、既存RAIDED休止時の安全終了と正式保存別PID全状態一致を1906/0で限定受入。再開の不具合仮説は反証、ゲーム変更0。全P06未完。 2026-10-12: 旧限定停電証拠から現Runtime等13sourceが変化しており現受入へ自動適用しない。P06-01の原契約監査をRunner経由で開始。正式完了なし。 MP-01-r02継続: 追加1回を直接承認(call_de866e18b25942ee8992263aa0189278)、個別cap2/使用2を保持。同一SHAの旧案2文書を再利用し、実Opus5.5のrun判断/Sol選択で同一登録ワーカーを起動。資料の正式検証・独立レビュー・統合は未了。製品値/P06-01受入/30・88分母は未変更。",
"progress_summary": "停電、厨房、救護の停止復帰は部分実装。有限マナ供給の契約が残る。 制御したEV乗車中救護の停電保存/再開691/0・10全状態pair・無制限journal各9件を限定照合。安全階での緊急降車・自然停電・全館停止・通常UIは未受入。 最新現1299参照で通常建設からの物流/厨房の制御停電・復旧、2正式保存/別PID全状態一致を460/0で限定受入。利用中サービス0件なので途中販売/中断は未受入。全P06未完。 現版の自然入館客の食事/宿泊の制御停電・復旧・一回請求、既存RAIDED休止時の安全終了と正式保存別PID全状態一致を1906/0で限定受入。再開の不具合仮説は反証、ゲーム変更0。全P06未完。 2026-10-12: 旧限定停電証拠から現Runtime等13sourceが変化しており現受入へ自動適用しない。P06-01の原契約監査をRunner経由で開始。正式完了なし。 MP-01-r02承認用資料は追加許可後に同じSol担当で修正し、提出6b78f8fd・正式検証・別Opus5.5独立review PASS・最新main統合/最終検証65a4fe2bを完了。修正2/2保持。全37需要・53source pin・21候補比較・炉の容量判定・旧0/再送/D05を整理。数値/人物分類/更新順序/保存移行は未承認、製品未反映。P06-01はin_progress、原88正式完了増加0。",
"remaining_gaps": [
"生成・蓄積・消費と初期値/係数の原本・承認・実装・試験用値の根拠対応。",
"旧ゼロ保存の意味、移行、残量境界の現版証拠と矛盾の有無。",
"13source差分を含む既存証拠の適用性、必要検証、独立レビューと全条件台帳反映。"
"承認用数値・炉対象分類・需要換算・D05更新順序・保存domain/移行元適用条件のオーナー判断。",
"承認後の生成・蓄積・消費接続、旧ゼロ保存の実移行・残量境界・原条件全体の現版証拠。",
"原P06-01の必要検証・独立レビュー・統合/最終を含む全条件完了。候補資料の完了を代用しない。"
],
"updated_at_jst": "2026-10-13T16:27:12.029767+09:00"
"updated_at_jst": "2026-10-13T17:09:33.500243+09:00"
},
{
"id": "P06-02",
@@ -6303,7 +6309,7 @@
],
"cross_cutting_acceptance_scope": "Completion requirements only, not achieved results. Apply each to relevant slices; non-applicable views require a recorded reason.",
"initial_revision_state": "in_progress",
"updated_at_jst": "2026-10-02T07:25:10.042304+09:00",
"updated_at_jst": "2026-10-13T17:09:33.500243+09:00",
"current_controlled_supply_outage_checkpoint": {
"issued_by": "/root",
"linked_at_jst": "2026-10-09T10:37:43.610273+09:00",
@@ -7712,7 +7718,7 @@
},
"legacy_state": "planned",
"state_scope": "package-level; completed means whole package accepted; partial implementation is not completion",
"current_summary": "P13-03最終ゲーム記録は保存・未採用。許可済み支援RP13-01は修正2/2、最終1398aa2dに配置依存と負例fixture不良が残り未合格。追加修正を起動せず保留し、次候補P24-03へ順序変更。P13-01/P13-02未着手、内容資産の完成は未認定。",
"current_summary": "P13-03既存最終修正を読取再監査。共有参照の全展開で旧提出7645c551と7施設/84スロット/施設外6分類が完全一致。現production53sourceのうちmain.gd1件のみSHA差、現版再検索の全観測はSHA以外一致。通常--verify-onlyは18負例を拒否するが未提出/未受入。支援RP13-01最終1398aa2dの正式55試験は入れ子Seatbeltで4failure/11error、通常ホスト診断でも負例fixtureの重複受入登録2errorが残る。隔離fixture差分案の該当試作1試験のみPASS、候補本体未変更。RP13の追加1回+限定ホスト正式試験、P13のsource更新追加1回を別々に確認中。全30/88、P13-03の全条件と2/2の現回数を維持。",
"remaining_deliverables": [
{
"id": "P13-01",
@@ -7746,15 +7752,27 @@
"path": "docs/plans/original-completion-2026-10-02/checkpoints/p13-03-start-r01/commander.json",
"sha256_at_integration": "ed5ea26576d3ed48428a645df31de4d9d824269873f58b9880b014bafa70bd87",
"scope": "Actual Claude run decision, not completion."
},
{
"path": "docs/plans/original-completion-2026-10-02/checkpoints/runner-p13-continuation-r03/p13-existing-repair-preservation-r03.json",
"sha256_at_integration": "a17f7fdfe6290a0598a1e689d1bd51ebd1fc3a7382e5aefbd24f0f2fd20e2bb6",
"scope": "Full prior 7/84/6 semantic preservation and current applicable source pin check; detects main.gd mismatch, not unit acceptance",
"current_game_acceptance_inferred": false
},
{
"path": "docs/plans/original-completion-2026-10-02/checkpoints/runner-p13-continuation-r03/diagnostic-disposition-r03.json",
"sha256_at_integration": "f04230ab52d8cefbc4bcd7b9957f86b5131c9e5cd85b985a99952155410f69eb",
"scope": "Formal RP13 failure, host diagnostic fixture errors, limited proposed-fixture test result; no production changes or formal acceptance",
"current_game_acceptance_inferred": false
}
],
"progress_summary": "原P13最終5ファイルは7施設・84使用枠・施設外6分類の証拠を内容保持保存し、未採用。root生成cache隔離後check_scopeはPASS、原P13はblocked再提出不可・修正2/2。限定復旧と全文保持の文書重複削減はユーザー承認済み。Claude認証回復後、同一支援RP13-01を実装。初回blockedの照合基準をCommander判断で具体化して隔離promptへ渡した。修正1の01fec4ffは正式Runner試験でnested Seatbelt拒否(4failures/9errors)、通常ホスト54PASSは診断のみ。修正2の最終1398aa2dは通常ホスト55試験に2サブケースエラー(負例fixtureの重複受入登録)。実本番CONTROLでrecovery_source_pinsを読取実行するとsnapshot_missing runner/core.py、隔離Git object依存が残る。支援修正上限2/2、正式独立レビュー・統合未実施。追加ワーカー/上限変更/本番適用なし。P13は保留し正式検証済みP24-03を次候補に選定。全体9/88のまま。",
"progress_summary": "P13-03既存最終修正を読取再監査。共有参照の全展開で旧提出7645c551と7施設/84スロット/施設外6分類が完全一致。現production53sourceのうちmain.gd1件のみSHA差、現版再検索の全観測はSHA以外一致。通常--verify-onlyは18負例を拒否するが未提出/未受入。支援RP13-01最終1398aa2dの正式55試験は入れ子Seatbeltで4failure/11error、通常ホスト診断でも負例fixtureの重複受入登録2errorが残る。隔離fixture差分案の該当試作1試験のみPASS、候補本体未変更。RP13の追加1回+限定ホスト正式試験、P13のsource更新追加1回を別々に確認中。全30/88、P13-03の全条件と2/2の現回数を維持。",
"remaining_gaps": [
"RP13最終1398aa2dの本番配置依存を除去し、実際の欠落Git objectとpin不一致を検証する。負例fixtureの重複受入登録を修正。支援修正2/2のため追加実装は禁止範囲として保留。",
"Runner自己試験は入れ子Seatbeltで正式失敗。信頼ホスト実行案は別途未承認。正式試験・別Claude独立レビュー・限定適用は未実施。",
"原P13保存済み最終成果の限定復旧再提出、正確な提出SHAで正式検証・exact資料容量確認・独立レビュー・統合。原P13修正2/2と全条件を維持。"
"RP13限定の正式ホスト自己試験環境と追加1回の直接許可後、fixture修正/全正式試験/別独立レビュー/統合・最終。現live CONTROLに凍結Git objectが欠落する配置条件は、実際に使用する受入済みCONTROLでsource pinsを実照合する。",
"P13既存最終submitted結果の限定復旧提出。追加source更新1回の直接許可後、現在main.gd SHA/全出力receiptを同期。未許可で回数/state/sourceを変更しない。",
"P13正確な提出SHAの正式--verify-onlyと全18負例、全資料のexact500000容量、別Opus独立レビュー、統合/最終、全条件台帳反映。"
],
"updated_at_jst": "2026-10-13T08:53:13.197406+09:00"
"updated_at_jst": "2026-10-13T17:23:50.608597+09:00"
}
],
"estimate_person_days_historical_2026_09_29": [
@@ -7774,7 +7792,8 @@
"要件別ログとソースハッシュを保存"
],
"cross_cutting_acceptance_scope": "Completion requirements only, not achieved results. Apply each to relevant slices; non-applicable views require a recorded reason.",
"initial_revision_state": "planned"
"initial_revision_state": "planned",
"updated_at_jst": "2026-10-13T17:23:50.608597+09:00"
},
{
"id": "P14",
@@ -9093,7 +9112,7 @@
"remaining": "差分数・制作担当・品質受入と利用画面の確定。既存ファイルの存在を完成認定しない。",
"legacy_state": "in_progress",
"state_scope": "package-level; completed means whole package accepted; partial implementation is not completion",
"current_summary": "P22-01「必要素材の確定」を原work/acceptanceそのままで独立受入。現採用1299に固定し、既存30施設360利用枠を引継ぎ、Lv1〜3×表裏描画文脈×外観内装の用途・配置条件を列挙。7人物、名前のあるライバル3名と未確定の等、人物/施設状態、背景・UI・音・未制作原本必須内容をsource行/SHAと現参照先へ対応付けた。現media296件のSHAを確認し、仮media/コード描画/完成素材を区別。使用枠/用途群数は素材枚数・フレーム数・原子分母へ換算しない。D08/D09の未確定枚数・音声・内容ID・追加人物/制作担当はnullと未割当を維持。製品編集0/engine追加0/素材完成追加0、Runtime/通常UI/保存変更のない一覧成果に限定した横断適用を独立確認。P22-01本成果単位の不足0。現在の全計画の正式完了は9。素材制作・品質・権利受入・全内容/原子/Windowsは未完。 P22-02素材契約と権利は未完。P22-03は制作計画の下書きに着手、必要数量・具体的見積が残り未完。",
"current_summary": "P22-01「必要素材の確定」を原work/acceptanceそのままで独立受入。現採用1299に固定し、既存30施設360利用枠を引継ぎ、Lv1〜3×表裏描画文脈×外観内装の用途・配置条件を列挙。7人物、名前のあるライバル3名と未確定の等、人物/施設状態、背景・UI・音・未制作原本必須内容をsource行/SHAと現参照先へ対応付けた。現media296件のSHAを確認し、仮media/コード描画/完成素材を区別。使用枠/用途群数は素材枚数・フレーム数・原子分母へ換算しない。D08/D09の未確定枚数・音声・内容ID・追加人物/制作担当はnullと未割当を維持。製品編集0/engine追加0/素材完成追加0、Runtime/通常UI/保存変更のない一覧成果に限定した横断適用を独立確認。P22-01本成果単位の不足0。現在の全計画の正式完了は9。素材制作・品質・権利受入・全内容/原子/Windowsは未完。 P22-02素材契約と権利は未完。P22-03は制作計画の下書きに着手、必要数量・具体的見積が残り未完。 2026-10-13: P22-02権利・形式契約に着手。公式archive2pack全同梱+UI音4/Licenseをbyte照合、現物296中276mediaの配布元権利を検証。旧theme/mockup/BGM/iconの20は最終権利未検証、BGMの内部recipe/同byte起源は確認。614用途と完成資産数を区別し、全完了は認定しない。",
"remaining_deliverables": [
{
"id": "P22-01",
@@ -9202,7 +9221,7 @@
"title": "素材契約と権利",
"work": "Kenneyを優先して適合素材を選び、解像度、命名、差替、出典とライセンスを記録する。",
"acceptance": "完成枠には使用可能な資産と権利記録があり、欠損を代替表示で隠さない。",
"state": "planned",
"state": "in_progress",
"evidence": [
{
"path": "artifacts/original-completion-2026-10-02/canonical-full170-actual-root-review-r01/review.json",
@@ -9231,9 +9250,51 @@
"scope": "Limited code-native standard-room Lv1-3/sleep6refs; focused3020/full17013961; no all finished assets/normal upgrade/human/nativeWindows acceptance",
"linked_at_jst": "2026-10-08T02:27:24.318350+09:00",
"current_game_acceptance_inferred": false
},
{
"path": "docs/plans/original-completion-2026-10-02/checkpoints/p22-02-current-contract-r01/reuse-rights-preflight.json",
"sha256_at_integration": "204184c5f52305d76a25a8868569649aa541337de0405c6d799eb20f7246081b",
"scope": "Exact accepted P22-01 usage records and provenance/required conditions; no finished-asset acceptance",
"current_game_acceptance_inferred": false
},
{
"path": "docs/plans/original-completion-2026-10-02/checkpoints/p22-02-current-contract-r01/publisher-archive-byte-verification.json",
"sha256_at_integration": "ef5d4ee78c80d2f9439646b86a0c781b685ad94dcc93d41d629f0ca148fcc061",
"scope": "Two official Kenney ZIPs and every existing member raw-byte equality",
"current_game_acceptance_inferred": false
},
{
"path": "docs/plans/original-completion-2026-10-02/checkpoints/p22-02-current-contract-r01/ui-audio-publisher-verification.json",
"sha256_at_integration": "bfebed0270e756530c69b434ca5a302b80287b586a261fb7c33718984e133fb8",
"scope": "Four existing UI sounds and included license exact publisher archive equality",
"current_game_acceptance_inferred": false
},
{
"path": "docs/plans/original-completion-2026-10-02/checkpoints/p22-02-current-contract-r01/current-media-rights.json",
"sha256_at_integration": "da24fc40b62af5c75b6e6732cebb3a6ca7475d3713176d4e70a57ecba87fc59a",
"scope": "Current 296 physical media dimensions/CRC and distinct verified/unknown rights status",
"current_game_acceptance_inferred": false
},
{
"path": "docs/plans/original-completion-2026-10-02/checkpoints/p22-02-current-contract-r01/observed-existing-asset-contracts.json",
"sha256_at_integration": "ff985e94892554873aea76148fc555eb9b007fd9622dc01e91917ba2cceb51d6",
"scope": "Existing atlas/import/naming/Theme replacement source observations; no new specs or finished assets",
"current_game_acceptance_inferred": false
},
{
"path": "docs/plans/original-completion-2026-10-02/checkpoints/p22-02-current-contract-r01/internal-origin-observations.json",
"sha256_at_integration": "8b72f9a24f5f1670116fdfb41995491ce42f44bab38a9f9c7206e0aaaefbb08a",
"scope": "Located original BGM recipe/output and code SVG provenance, no final rights/quality inference",
"current_game_acceptance_inferred": false
}
],
"progress_summary": "Kenney CC0 UI音4件とLicense/出典SHAを限定採用。初期施設・人物・素材枠の台帳、必要量未確定、全完成素材受入0と実聴未受入を維持。全168回帰は素材全制作の証拠ではない。"
"progress_summary": "P22-01の614利用記録(360施設/176人物/2状態群/76その他)をSHA付きで引継ぎ。現物296mediaを再監査し、Kenney2packの283同梱files、UI音4とLicenseが公式archiveとbyte一致。276mediaに配布元CC0の権利証拠を結合、20mediaの最終権利は未検証。BGM2は既存original合成recipeと同byte出力を発見、SVGはbaseline codeを確認するが完成/最終権利へ昇格しない。2packed atlas192x176/16px/12x11、既存nearest/mipmap/Theme差替接続を記録。全利用枠適合/欠損開示/実表示・実聴/正式独立review/統合は未達。製品変更・新規素材導入・原成果完了増加0。",
"remaining_gaps": [
"614利用記録の候補選定/適合、解像度・命名・差替・現source・権利の全対応。状態群は素材枚数へ変換しない。",
"旧theme/mockup/BGM/iconの残る最終権利・creator記録と、完成枠の実利用・表示/聴感・欠損の非隠蔽。276の配布元権利検証は完成素材受入ではない。",
"原条件の全証拠を固めた最終版で必要検証・別Opus独立レビュー・統合/最終・台帳完了。D08/D09未確定数量・内容を捏造しない。"
],
"updated_at_jst": "2026-10-13T17:42:48.624114+09:00"
},
{
"id": "P22-03",
@@ -9498,7 +9559,7 @@
"controlled_injury_fixture": true,
"medical_values_approved": false
},
"updated_at_jst": "2026-10-10T15:04:48.162471+09:00"
"updated_at_jst": "2026-10-13T17:42:48.624114+09:00"
},
{
"id": "P23",
+41
View File
@@ -0,0 +1,41 @@
{
"id": "P22-02",
"title": "素材契約と権利",
"work": "Kenneyを優先して適合素材を選び、解像度、命名、差替、出典とライセンスを記録する。",
"acceptance": "完成枠には使用可能な資産と権利記録があり、欠損を代替表示で隠さない。",
"original_denominator": {
"packages": 30,
"delivery_units": 88,
"no_partial_credit": true
},
"authority": "docs/traceability/original/BASELINE.txt",
"accepted_inputs": "docs/spec/inputs/P22-02-accepted-usage.json",
"accepted_input_raw_sha256": "45fa52acf0c8bd4dd58c3b40b681cb92066f05d617df157fc18370a5e8816281",
"current_preflight": "docs/plans/original-completion-2026-10-02/checkpoints/p22-02-current-contract-r01/",
"current_slot_preflight": "docs/plans/original-completion-2026-10-02/checkpoints/p22-02-slot-contract-r02/all-slot-current-candidate-contracts.json",
"required_outcomes": [
"Preserve every accepted 614 usage identity and all decoded input/provenance fields. 2 state groups are not images. No invented final quantities.",
"For each required use, explicitly record selection/candidate/missing status, actual applicable source hash, dimensions or code representation, naming, replacement chain, creator and rights provenance. Missing is never satisfied by file/code token or fallback.",
"Reuse exact verified publisher/member/license/manifest evidence for existing Kenney packs and UI sound; retain internal composition origin distinct from third-party license and final hearing/rights acceptance.",
"Meaningful read-only checker: exact accepted coverage, decode/hash/source applicability, duplicate/source omission, dimension/layout/reference mismatch, missing/unknown rights, false finished/provisional promotions, invented quantities. Use current real source facts, not hardcoded always-fail or accepting only sample mutations.",
"Machine ledger and readable contract must separate record integrity from original-unit readiness. Completion must be nonvacuous and require exact usable selected assets/right evidence for completed frames, all mandatory unmade/disclosure gaps and applicable display/hearing/independent evidence. A structural pass never claims P22-02 accepted.",
"Do not invent original artist/rights/quantities, source approval or tests. D08/D09 remain explicit unknown. No CC0-only restriction for properly proven internal/other licensed work.",
"If product changes or actual usability evidence are needed, provide concrete source/minimal asset/reference diff and necessary checks. Never quietly shrink acceptance to records-only completion.",
"Root performs exact static validation and meaningful negatives first, then applicable usability and independent Opus review, integration and final before original acceptance. Pending mandatory conditions produce nonzero readiness and no completion."
],
"outputs": [
"docs/plans/original-completion-2026-10-02/execution/p22-02/asset-contracts.json",
"docs/plans/original-completion-2026-10-02/execution/p22-02/ASSET_CONTRACTS.md",
"docs/plans/original-completion-2026-10-02/execution/p22-02/validation.json",
"tools/check_p22_asset_contracts.py"
],
"worker_instructions": [
"Reuse all existing inputs. Python stdlib only. Avoid artifacts-wide scans; inputs and verified evidence are already inside repo. Source paths in historic input may be stale; recheck current source.",
"Initial bounded implementation scope is contracts/checker; no product/assets/values/spec/Runner/policy/DB edits or git writes. Original unit remains incomplete until ALL conditions proven; implement current authorized contract work and preserve concrete next product/usability gaps.",
"Use JSON shared references to retain every source field while avoiding duplicate evidence. Preflight complete unchanged reviewer packet under500000; no truncation/omission/core/cap changes.",
"Use python -B, ast.parse rather than py_compile; avoid generated caches outside scope. Never run engine/full regression for contract-only changes.",
"When bounded implementation is written, return submitted with exact incomplete original-unit conditions. Root must not treat this as original acceptance or run known-unmet readiness as fake pass."
],
"input_encoding": "Lossless JSON: d=flat key-id/value object; l=list; s=shared string; r=shared complete object/list",
"input_integrity": "Decode all fields then validate original semantic SHA256 per file, exact 614 identities, cycle/bad-index/duplicate-key/wrong-type rejects; no opaque compression"
}
File diff suppressed because one or more lines are too long
+513
View File
@@ -0,0 +1,513 @@
#!/usr/bin/env python3
"""Read-only P22 record integrity; exit 2 for unmet technical readiness."""
import argparse
import hashlib
import json
import io
import math
import wave
import zlib
from pathlib import Path
import struct
import sys
ROOT = Path(__file__).resolve().parents[1]
OUT = 'docs/plans/original-completion-2026-10-02/execution/p22-02/'
INPUT = 'docs/spec/inputs/P22-02-accepted-usage.json'
CURRENT = 'docs/plans/original-completion-2026-10-02/checkpoints/p22-02-slot-contract-r02/all-slot-current-candidate-contracts.json'
SPEC_SHA = 'f252de3c5cff7ebfa62322ae2f2df09fb80a44bc59eb286b76d4acb4c12ca875'
INPUT_SHA = '45fa52acf0c8bd4dd58c3b40b681cb92066f05d617df157fc18370a5e8816281'
def need(ok, message):
if not ok:
raise ValueError(message)
def sha(raw):
return hashlib.sha256(raw).hexdigest()
def semantic(value):
return sha(json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(',', ':'), allow_nan=False).encode())
def pairs(items):
result = {}
for key, value in items:
need(key not in result, 'duplicate JSON key: ' + key)
result[key] = value
return result
def invalid_constant(value):
raise ValueError('nonfinite JSON number: ' + value)
def finite_float(value):
number = float(value)
need(math.isfinite(number), 'nonfinite JSON number')
return number
def loads(value):
return json.loads(value, object_pairs_hook=pairs, parse_constant=invalid_constant, parse_float=finite_float)
def read(path):
return loads(raw(path))
def decode(doc, node=None):
need(type(doc) is dict and all(type(doc.get(k)) is list for k in ('keys', 'strings', 'pool')), 'wrong codec tables')
need(all(type(k) is str for k in doc['keys']) and len(set(doc['keys'])) == len(doc['keys']), 'duplicate/wrong key table')
need(all(type(s) is str for s in doc['strings']), 'wrong string table')
active = set()
def index(values, i):
need(type(i) is int and 0 <= i < len(values), 'bad reference index')
return values[i]
def walk(n):
if not isinstance(n, list):
need(n is None or type(n) in (str, int, float, bool), 'wrong scalar type')
need(type(n) is not float or math.isfinite(n), 'nonfinite codec scalar')
return n
need(bool(n) and type(n[0]) is str, 'wrong node type')
tag = n[0]
if tag == 'l':
return [walk(x) for x in n[1:]]
if tag == 'd':
need(len(n) % 2 == 1, 'malformed flat dictionary')
result = {}
for i in range(1, len(n), 2):
key = index(doc['keys'], n[i])
need(type(key) is str and key not in result, 'duplicate or invalid decoded key')
result[key] = walk(n[i + 1])
return result
need(tag in ('s', 'r') and len(n) == 2, 'unknown node')
if tag == 's':
value = index(doc['strings'], n[1])
need(type(value) is str, 'wrong shared string type')
return value
i = n[1]
value = index(doc['pool'], i)
need(i not in active and isinstance(value, list) and value and value[0] in ('d', 'l'), 'cycle or wrong shared object type')
active.add(i)
result = walk(value)
active.remove(i)
return result
result = walk(doc['files'] if node is None else node)
for i in range(len(doc['pool'])):
walk(['r', i])
return result
# A pinned historical observation is retained, never treated as current readiness.
EVIDENCE = 'docs/plans/original-completion-2026-10-02/checkpoints/p22-02-current-contract-r01/'
CHECKPOINTS = 'docs/plans/original-completion-2026-10-02/checkpoints/'
CURRENT_SHA = '5cf93b6b3fd9d0cc060075878804f65195c0d90711c969cc36e2f58f3a1917fd'
QUANTITIES = ('required_file_count', 'required_frame_count', 'required_variant_count')
PROOF_KINDS = ('fit', 'rights', 'layout', 'quantity', 'gaps', 'usability')
def safe_path(path):
need(type(path) is str and path and not Path(path).is_absolute(), 'invalid relative path')
need('..' not in Path(path).parts, 'path escape')
resolved = (ROOT / path).resolve()
need(resolved != ROOT and ROOT in resolved.parents, 'path escape or symlink escape')
return resolved
def raw(path):
return safe_path(path).read_bytes()
def pinned(path, digest):
need(type(digest) is str and len(digest) == 64 and all(c in '0123456789abcdef' for c in digest), 'invalid SHA')
value = raw(path)
need(sha(value) == digest, 'raw SHA mismatch: ' + path)
return value
def exact(a, b):
# Python equality would otherwise equate True and 1.
return semantic(a) == semantic(b)
def anchor(a):
need(type(a) is dict and set(a) == {'path', 'sha256', 'line', 'text'}, 'anchor schema')
lines = pinned(a['path'], a['sha256']).decode('utf-8').splitlines()
need(type(a['line']) is int and 1 <= a['line'] <= len(lines), 'anchor line')
need(type(a['text']) is str and a['text'].strip() and lines[a['line'] - 1] == a['text'], 'reference mismatch')
def png_format(data):
need(data[:8] == b'\x89PNG\r\n\x1a\n', 'PNG signature')
pos, chunks, payload, palette, transparent = 8, [], bytearray(), False, False
width = height = depth = color = interlace = None
while pos < len(data):
need(pos + 12 <= len(data), 'PNG truncated chunk')
size = struct.unpack('>I', data[pos:pos + 4])[0]
kind = data[pos + 4:pos + 8]
end = pos + size + 12
need(end <= len(data), 'PNG chunk length')
body = data[pos + 8:end - 4]
crc = struct.unpack('>I', data[end - 4:end])[0]
need(zlib.crc32(kind + body) & 0xffffffff == crc, 'PNG CRC')
if not chunks:
need(kind == b'IHDR' and size == 13, 'PNG IHDR')
width, height, depth, color, comp, filt, interlace = struct.unpack('>IIBBBBB', body)
need(width > 0 and height > 0 and comp == filt == 0 and interlace in (0, 1), 'PNG dimensions/encoding')
depths = {0: (1, 2, 4, 8, 16), 2: (8, 16), 3: (1, 2, 4, 8), 4: (8, 16), 6: (8, 16)}
need(color in depths and depth in depths[color], 'PNG color/depth')
else:
need(kind != b'IHDR', 'duplicate PNG IHDR')
if kind == b'PLTE':
need(not payload and size > 0 and size % 3 == 0 and size <= 768, 'PNG palette')
palette = True
if kind == b'tRNS':
transparent = True
if kind == b'IDAT':
need(not payload or chunks[-1] == b'IDAT', 'PNG noncontiguous image data')
payload.extend(body)
chunks.append(kind)
pos = end
if kind == b'IEND':
need(size == 0 and pos == len(data), 'PNG trailing bytes')
break
need(chunks[-1:] == [b'IEND'] and payload and (color != 3 or palette), 'PNG missing image/palette/end')
# Bound decoded length by IHDR; validate scanline sizes and filter tags.
channels = {0: 1, 2: 3, 3: 1, 4: 2, 6: 4}[color]
passes = [(0, 0, 1, 1)] if interlace == 0 else [(0, 0, 8, 8), (4, 0, 8, 8), (0, 4, 4, 8), (2, 0, 4, 4), (0, 2, 2, 4), (1, 0, 2, 2), (0, 1, 1, 2)]
rows = []
for x, y, dx, dy in passes:
w, h = max(0, (width - x + dx - 1) // dx), max(0, (height - y + dy - 1) // dy)
if w and h:
rows.extend([1 + (w * channels * depth + 7) // 8] * h)
expected = sum(rows)
need(expected <= 268435456, 'PNG exceeds verification memory bound')
decoder = zlib.decompressobj()
pixels = decoder.decompress(bytes(payload), expected + 1)
need(decoder.eof and not decoder.unused_data and len(pixels) == expected, 'PNG scanline length')
offset = 0
for length in rows:
need(pixels[offset] <= 4, 'PNG scanline filter')
offset += length
return {'png_width': width, 'png_height': height, 'png_color_type': color,
'png_crc_verified': True, 'png_alpha_encoding_present': color in (4, 6) or transparent}
def observe(path, data):
if path.endswith('.png'):
return png_format(data)
if path.endswith('.wav'):
with wave.open(io.BytesIO(data), 'rb') as w:
need(w.getcomptype() == 'NONE', 'WAV compression')
return {'channels': w.getnchannels(), 'sample_rate': w.getframerate(),
'sample_width_bytes': w.getsampwidth(), 'frames': w.getnframes()}
if path.endswith('.ogg'):
need(data[:4] == b'OggS' and b'\x01vorbis' in data[:128], 'Ogg/Vorbis representation')
return {'encoding': 'ogg-vorbis', 'bytes': len(data)}
data.decode('utf-8')
return {'representation': 'code', 'bytes': len(data)}
def accepted_records(accepted):
original = decode(accepted)
need(set(original) == set(accepted['source_files']), 'accepted file coverage')
records = {}
for name, rows in original.items():
need(type(rows) is list, 'decoded file must be list')
pin = accepted['source_files'][name]
need(type(pin['records']) is int and len(rows) == pin['records'] and semantic(rows) == pin['semantic_sha256'], 'decoded semantic mismatch: ' + name)
for row in rows:
need(type(row) is dict, 'accepted row type')
identity = row.get('slot_id', row.get('group_id'))
need(type(identity) is str and identity not in records, 'duplicate/invalid identity')
records[identity] = (name, row)
need(len(records) == 614 and accepted['decoded_record_count'] == 614, 'accepted coverage')
need(sum('group_id' in row for _, row in records.values()) == 2, 'state groups')
return original, records
def proof_matches(proof, kind, subject):
"""Pure proof predicate; callers supply a pinned Root/owner receipt, not booleans."""
need(type(proof) is dict and set(proof) == {'kind', 'subject', 'result', 'issuer', 'observations'}, 'proof schema')
need(proof['kind'] == kind and exact(proof['subject'], subject), 'wrong proof binding')
need(proof['result'] == 'accepted', 'proof is not accepted')
issuer = proof['issuer']
need(type(issuer) is dict and set(issuer) == {'role', 'name'}, 'proof issuer schema')
need(issuer['role'] in ('root', 'owner') and type(issuer['name']) is str and issuer['name'].strip(), 'proof authority')
need(type(proof['observations']) is list and proof['observations'], 'proof has no observations')
for observation in proof['observations']:
need(type(observation) is dict and set(observation) == {'explanation', 'anchors'}, 'observation schema')
need(type(observation['explanation']) is str and observation['explanation'].strip(), 'empty observation')
need(type(observation['anchors']) is list and observation['anchors'], 'no observation anchors')
return True
def receipt(ref, kind, subject):
# Workers cannot manufacture approval inside their own output directory.
need(type(ref) is dict and set(ref) == {'path', 'sha256', 'index'}, 'proof reference schema')
need(ref['path'].startswith(CHECKPOINTS), 'proof must be a Root/owner checkpoint')
resolved = safe_path(ref['path'])
need((ROOT / CHECKPOINTS).resolve() in resolved.parents, 'proof symlink outside checkpoints')
document = loads(pinned(ref['path'], ref['sha256']))
need(type(document) is dict and document.get('schema') == 'p22-evidence-v1', 'receipt schema')
proofs = document['proofs']
need(type(proofs) is list and type(ref['index']) is int and 0 <= ref['index'] < len(proofs), 'proof index')
proof = proofs[ref['index']]
proof_matches(proof, kind, subject)
for observation in proof['observations']:
for a in observation['anchors']:
anchor(a)
return proof
def reference_contracts(snapshot, records):
contracts, used = {}, set()
for c in snapshot['contracts']:
identity = c['id']
need(identity in records and identity not in contracts, 'contract coverage/duplicate')
name, row = records[identity]
need(c['source_file'] == name and c['accepted_record_semantic_sha256'] == semantic(row), 'contract accepted record')
need(exact(c['source_anchors'], row['source_anchors']) and exact(c['usage_condition'], row['usage_condition']), 'accepted anchors/usage omitted')
for a in c['source_anchors']:
anchor(a)
refs = c['candidate_refs']
need(len({r['candidate_ref'] for r in refs}) == len(refs), 'duplicate candidate')
need({r['candidate_ref'] for r in refs} == {r['path'] for r in row['representations']}, 'source omission')
historical = {r['path']: r for r in row['representations']}
for ref in refs:
source = ref['candidate_ref']
need(source in snapshot['candidate_pool'], 'source absent from pool')
used.add(source)
need(ref['prior_raw_sha256'] == historical[source]['sha256'], 'historical pin mismatch')
need(type(ref['prior_source_still_equal']) is bool and ref['prior_source_still_equal'] == (ref['prior_raw_sha256'] == snapshot['candidate_pool'][source]['current_raw_sha256']), 'historical applicability')
contracts[identity] = c
need(set(contracts) == set(records), 'missing accepted use')
need(used == set(snapshot['candidate_pool']) and len(used) == 19, '19-source coverage')
return contracts
def quantities_valid(values, row):
need(type(values) is dict and set(values) == set(QUANTITIES), 'quantity schema')
for key, value in values.items():
need(value is None or type(value) is int and value > 0, 'invalid quantity')
# Unknown may only be resolved by the separate bound quantity receipt.
if row.get(key) is not None:
need(exact(value, row[key]), 'required quantity mismatch')
def selection_subject(identity, row, c, selection, pins):
return {'id': identity, 'accepted_record_semantic_sha256': semantic(row),
'usage_condition': row['usage_condition'], 'source_pins': pins,
'selection': selection,
# Includes every original unmade/provisional/disclosure field, not
# just c.missing_conditions. No empty-gap denominator is possible.
'original_record': row, 'missing_conditions': c['missing_conditions']}
def asset_matches(a, row, sources):
"""Pure source/format/layout binding, shared by real and isolated tests."""
need(type(a) is dict and set(a) == {'path', 'sha256', 'format', 'region', 'code_anchor', 'kind'}, 'asset schema')
need(a['path'] in sources and a['sha256'] == sources[a['path']]['sha256'], 'selected source pin')
need(exact(a['format'], sources[a['path']]['format']), 'selected dimension/representation mismatch')
need(a['kind'] in ('image', 'audio', 'code', 'state_group'), 'fallback/provisional kind')
if 'group_id' in row:
need(a['kind'] == 'state_group', 'state group promoted to image')
if a['path'].endswith('.png'):
need(a['kind'] in ('image', 'state_group'), 'image kind mismatch')
region = a['region']
need(type(region) is list and len(region) == 4 and all(type(x) is int for x in region), 'region schema')
x, y, w, h = region
need(x >= 0 and y >= 0 and w > 0 and h > 0 and x + w <= a['format']['png_width'] and y + h <= a['format']['png_height'], 'layout region outside source')
need(a['code_anchor'] is None, 'image code representation')
elif a['path'].endswith(('.wav', '.ogg')):
need(a['kind'] == 'audio' and a['region'] is None and a['code_anchor'] is None, 'audio representation')
else:
need(a['kind'] in ('code', 'state_group') and a['region'] is None, 'code representation')
need(type(a['code_anchor']) is dict, 'missing code anchor')
need(a['code_anchor']['path'] == a['path'] and a['code_anchor']['sha256'] == a['sha256'], 'wrong code anchor')
def selection_ready(identity, row, c, choice, sources):
if type(choice) is str:
need(choice == ('candidate' if c['candidate_refs'] else 'missing'), 'candidate/missing status mismatch')
return False
need(type(choice) is dict and set(choice) == {'state', 'contract', 'proofs'}, 'selection schema')
need(choice['state'] == 'selected', 'counterfeit final state')
s = choice['contract']
fields = {'asset', 'creator', 'rights', 'name', 'replacement_chain', 'references', 'quantities', 'quantity_basis', 'usability'}
need(type(s) is dict and set(s) == fields, 'selected contract fields')
a = s['asset']
asset_matches(a, row, sources)
if a['code_anchor'] is not None:
anchor(a['code_anchor'])
need(type(s['creator']) is str and s['creator'].strip().lower() not in ('', 'unknown', 'unassigned'), 'unknown creator')
need(type(s['name']) is str and s['name'] == Path(a['path']).name, 'naming mismatch')
need(type(s['quantity_basis']) is str and s['quantity_basis'].strip(), 'quantity basis missing')
quantities_valid(s['quantities'], row)
chain = s['replacement_chain']
need(type(chain) is list and len(chain) >= 2 and chain[-1] == a['path'], 'replacement chain')
need(chain[0] == identity and all(type(x) is str and x for x in chain), 'replacement identity')
need(type(s['references']) is list and s['references'], 'missing product reference')
pins = {a['path']: a['sha256']}
for ref in s['references']:
anchor(ref)
need(ref['path'].startswith(('scripts/', 'scenes/', 'assets/')), 'product reference must be in product')
pins[ref['path']] = ref['sha256']
rights = s['rights']
need(type(rights) is dict and set(rights) == {'license', 'origin', 'documents'}, 'rights schema')
need(type(rights['license']) is str and rights['license'].strip().lower() not in ('', 'unknown', 'unassigned'), 'unknown license')
need(type(rights['origin']) is str and rights['origin'].strip(), 'rights origin')
need(type(rights['documents']) is list and rights['documents'], 'missing rights evidence')
for doc in rights['documents']:
need(type(doc) is dict and set(doc) == {'path', 'sha256'}, 'rights document schema')
pinned(doc['path'], doc['sha256'])
pins[doc['path']] = doc['sha256']
need(type(s['usability']) is dict and set(s['usability']) == {'display', 'hearing'}, 'usability schema')
for mode, explanation in s['usability'].items():
need(type(explanation) is str and explanation.strip(), 'applicability needs explanation, not boolean')
need(type(choice['proofs']) is dict and set(choice['proofs']) == set(PROOF_KINDS), 'missing required proof')
subject = selection_subject(identity, row, c, s, pins)
for kind in PROOF_KINDS:
receipt(choice['proofs'][kind], kind, subject)
return True
def technical_readiness(required, selected, unit_proofs, subject):
"""Pure reducer. No review/integration/final, no global all-false gate."""
need(type(required) is list and required and len(set(required)) == len(required), 'nonempty unique denominator')
need(type(selected) is dict and set(selected) == set(required), 'readiness exact coverage')
need(all(type(v) is bool for v in selected.values()), 'readiness booleans must be derived')
need(type(unit_proofs) is dict and set(unit_proofs) <= {'mandatory_scope', 'disclosure'}, 'unit proof schema')
for kind, proof in unit_proofs.items():
proof_matches(proof, kind, subject)
return all(selected.values()) and set(unit_proofs) == {'mandatory_scope', 'disclosure'}
def reconstruct(ledger):
"""Lossless public expansion; references are data, never omitted fields.
The caller can inspect every input/provenance field and every historical
contract. Selection is a separate plane and cannot overwrite that history.
This function performs no writes and confers no readiness.
"""
documents = {}
for source, digest in ledger['references'].items():
data = pinned(source, digest)
documents[source] = loads(data) if source.endswith('.json') else data.decode('utf-8')
return {'reference_documents': documents,
'accepted_files': decode(documents[INPUT]),
'historical_contracts': documents[CURRENT],
'selections': ledger['selections'], 'source_pins': ledger['source_pins'],
'unit_proofs': ledger['unit_proofs']}
def check(path, accepted_input=INPUT):
need(accepted_input == INPUT, 'accepted input path must match fixed contract')
spec = raw('docs/spec/acceptance/P22-02.json')
need(sha(spec.decode().strip().encode()) == SPEC_SHA, 'contract strip spec SHA')
need(sha(spec) == 'c26c0b12cf7e7a7c46e671acde2e00762904732c1cd6381a53836e3d7b3f9824', 'raw spec SHA')
accepted = loads(pinned(INPUT, INPUT_SHA))
original, records = accepted_records(accepted)
ledger = read(path)
need(type(ledger) is dict and set(ledger) == {'schema', 'references', 'reconstruction', 'selections', 'source_pins', 'unit_proofs'}, 'ledger schema')
need(ledger['schema'] == 'p22-reference-contract-v2', 'ledger version')
expected = {INPUT, CURRENT} | {str(p.relative_to(ROOT)) for p in safe_path(EVIDENCE).iterdir() if p.is_file()}
need(set(ledger['references']) == expected, 'reference omission/extra')
need(ledger['references'][INPUT] == INPUT_SHA and ledger['references'][CURRENT] == CURRENT_SHA, 'immutable reference pin')
expanded = reconstruct(ledger)
snapshot = expanded['historical_contracts']
contracts = reference_contracts(snapshot, records)
selections = ledger['selections']
need(type(selections) is dict and set(selections) == set(records), 'selection exact 614 coverage')
required_sources = set(snapshot['candidate_pool'])
for choice in selections.values():
if type(choice) is dict:
required_sources.add(choice['contract']['asset']['path'])
need(type(ledger['source_pins']) is dict and set(ledger['source_pins']) == required_sources, 'current source omission/extra')
sources = {}
for source, digest in ledger['source_pins'].items():
data = pinned(source, digest)
sources[source] = {'sha256': digest, 'format': observe(source, data)}
historic = snapshot['candidate_pool'].get(source)
if historic:
need(historic['path'] == source, 'source path mismatch')
if digest == historic['current_raw_sha256'] and source.endswith('.png'):
need(exact(sources[source]['format'], historic['observed_format']), 'observed dimension mismatch')
verify_existing_evidence(sources)
selected = {i: selection_ready(i, records[i][1], contracts[i], selections[i], sources) for i in records}
subject = {'accepted_input_raw_sha256': INPUT_SHA, 'source_pins': ledger['source_pins'],
'selection_sha256': semantic(selections), 'required_ids': sorted(records),
'original_denominator': {'packages': 30, 'delivery_units': 88, 'no_partial_credit': True},
'unresolved_scope_requires_owner_evidence': ['D08', 'D09']}
need(type(ledger['unit_proofs']) is dict, 'unit proofs type')
unit_proofs = {kind: receipt(ref, kind, subject) for kind, ref in ledger['unit_proofs'].items()}
ready = technical_readiness(list(records), selected, unit_proofs, subject)
return {'record_integrity': True, 'validation_ready': ready,
'pending_identity_count': sum(not v for v in selected.values()),
'selected_usable_count': sum(selected.values()), 'accepted_identity_count': len(records),
'candidate_source_count': len(snapshot['candidate_pool']),
'unit_proofs_missing': sorted({'mandatory_scope', 'disclosure'} - set(unit_proofs)),
'original_completion': 'not_claimed; requires formal validate, independent review, integration, final',
'acceptance_claimed': False}
def verify_existing_evidence(sources):
"""Rebind existing publisher/member/license/manifest and layout to bytes."""
packs = read(EVIDENCE + 'publisher-archive-byte-verification.json')
manifests = read('assets/kenney/sources.json')
need(sha(raw('assets/kenney/sources.json')) == packs['source_manifest_sha256'], 'Kenney manifest pin')
for pack in packs['packs']:
matching = [m for m in manifests if m['slug'] == pack['slug']]
need(len(matching) == 1, 'publisher manifest coverage')
m = matching[0]
need(m['page'] == pack['official_page'] and m['zip_sha256'] == pack['archive_sha256'] and m['download_url'] == pack['official_archive_url'], 'publisher mismatch')
for member in pack['members']:
# Publisher facts only apply to exactly equal bytes. A changed
# selection needs its own new rights evidence, never inherited CC0.
if member['repo_path'] in sources and sources[member['repo_path']]['sha256'] == member['raw_sha256']:
pinned(member['repo_path'], member['raw_sha256'])
licenses = [x for x in pack['members'] if x['archive_member'].lower() == 'license.txt']
need(len(licenses) == 1, 'publisher license member')
pinned(licenses[0]['repo_path'], licenses[0]['raw_sha256'])
ui = read(EVIDENCE + 'ui-audio-publisher-verification.json')
manifest = loads(pinned('assets/audio/ui/source_manifest.json',
'f981c2ce12ed364010217dee996908f037d2abfcc3b21b8cf501dd591f7744c9'))
need(manifest['official_page'] == ui['official_page'] and manifest['official_archive_sha256'] == ui['archive_sha256'], 'UI publisher mismatch')
pinned(manifest['license']['path'], manifest['license']['sha256'])
need(manifest['license']['name'] == 'Creative Commons Zero, CC0', 'UI license mismatch')
need(len(manifest['assets']) == len(ui['assets']) == 4, 'UI asset coverage')
for member in ui['assets']:
matches = [a for a in manifest['assets'] if a['path'] == member['repo_path']]
need(len(matches) == 1 and matches[0]['sha256'] == member['raw_sha256'] and matches[0]['bytes'] == member['bytes'], 'UI member manifest mismatch')
observed = read(EVIDENCE + 'observed-existing-asset-contracts.json')
# These layout/reference observations are valid only with their exact
# dependency pins. Changes require a refreshed external observation.
for source, digest in observed['source_pins'].items():
pinned(source, digest)
atlas = observed['pixel_atlas']
need(atlas['columns'] * atlas['cell'][0] == atlas['physical_dimensions'][0] and atlas['rows'] * atlas['cell'][1] == atlas['physical_dimensions'][1] and atlas['gap'] == 0, 'atlas layout')
for source in atlas['vendor_paths_preserved']:
fmt = sources[source]['format']
need([fmt['png_width'], fmt['png_height']] == atlas['physical_dimensions'], 'atlas dimensions/layout mismatch')
internal = read(EVIDENCE + 'internal-origin-observations.json')
for bgm in internal['bgm']:
source = sources[bgm['path']]
if source['sha256'] == bgm['raw_sha256']:
need(exact(source['format'], bgm['format_observed']), 'BGM representation mismatch')
# Origin declarations remain historical facts. They never create proof.
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--ledger', default=OUT + 'asset-contracts.json')
parser.add_argument('--verify-only', action='store_true', help='Read-only verification (also the default)')
parser.add_argument('--accepted-input', default=INPUT)
parser.add_argument('--require-ready', action='store_true')
args = parser.parse_args()
try:
result = check(args.ledger, args.accepted_input)
print(json.dumps(result, ensure_ascii=False, sort_keys=True))
return 2 if args.require_ready and not result['validation_ready'] else 0
except (ValueError, KeyError, TypeError, IndexError, OSError, RecursionError, struct.error, zlib.error, wave.Error, UnicodeError) as exc:
print(json.dumps({'record_integrity': False, 'error': str(exc), 'acceptance_claimed': False}))
return 1
if __name__ == '__main__':
sys.exit(main())