# P24-03 code-role 提出 要件・受入ID: P24-03。基準commit: 286730f88ce430a1cbe1501d40361188f832d235。 固定仕様: `docs/spec/acceptance/P24-03-code-r02.json`。 提出状態は submitted。元88成果の1件の完了はRunnerと独立レビューが確定する。 ## 変更と再利用 - Mainの施設・客・職員metadataのversion判定に数値型を要求。Godot JSONが返す数値1.0は互換性のため許可し、bool/string/非整数値を拒否。 - 客panelの空選択時にOptionButtonを明示的に未選択にする。既存在館一覧・退館状態表示・履歴分離を維持。 - 新局所suiteは実GuestServiceのLEAVING→despawn、一般職員remove、給与履歴保持、Unique拒否、UI収集時の全Runtime digest不変性、metadata型境界を確認する。関数呼出しはnative局所検証でありOS証拠には数えない。 - ROOT_REVIEW_LOCAL_FAILUREを反映し、実離脱後は離脱IDの除外と在館客への正常fallbackを確認。残る在館客をserviceの正式離脱で除去した別境界で空一覧・表示値消去を確認する。建設は既存lifecycle suiteの有効な受付座標(-8,0,0)と120分完成を再利用し、実command結果を失敗messageへ記録する。 - 新suiteだけのraw SHAをpolicy/markerへ更新。理由は上記fixture不備の修正であり、既存suiteのSHAやmarkerは変更しない。正式Runner再実行はpending。 - 新suiteだけにpolicyとstrict markerを追加。既存suiteのSHA・assert・cleanup・marker条件は変更しない。 - レイヤーは既存GameState snapshot、施設表示/地図強調は既存Main、職員一覧は既存service report、正式保存/失敗読込は既存契約を再利用。経済・Clock・人物・旧保存係数の変更なし。 - 新検証器は読取専用。限定suite機能、見た目、素材、Runner操作、外部worktree入力は追加しない。 ## 条件matrix(全項目未実行) | condition ID | 根拠source / Runnerで必要な検証 | 状態 | | --- | --- | --- | | facility_lifecycle | test_selection_lifecycle + test_selection_departure、実撤去後ID/detail/highlight、別process有効施設復元 | pending | | guest_lifecycle | test_actor_selection + test_selection_departure、退館中表示・実despawn・履歴保持、別process画面値 | pending | | staff_lifecycle | test_actor_selection + test_selection_departure、一般職員remove・給与履歴・Unique拒否、別process画面値 | pending | | layer_and_values | test_selection_autosave + test_actor_selection + 新suite、正式GameState layer、UI収集時全Runtime不変、別process通常Main | pending | | invalid_and_failed_load | test_selection_lifecycle + test_actor_selection + 新suite、不在/不正型/過大ID/旧metadata/読込失敗時保持 | pending | | normal_os_input | 同候補sourceの通常Mainで施設/客/職員/レイヤー選択、正式保存、別PID再開、OS collector trace + PNG + log | pending | | final_validation_review | 最終候補全roster/import/全script parse、正式独立Claudeレビュー、別Windows条件 | pending | ## Runner実行計画 作成者は試験を実行していない。局所4suiteを確認した後、影響範囲(guest observation、staff management、layer skin、save/recovery)と最終候補の全回帰を正式実行する。全回帰には既存 `tools/run_all_tests.py` を指定なしで使用し、新suiteを含む全rosterとparse範囲を維持する。新suiteのcontrol labelはsingleであり、Runnerが渡すcontrol.jsonへ既存ordinary cleanupを出力する。 通常OS確認はRunnerが所有する新規profileで行う。個人profileや外部PIDを操作しない。Producerとconsumerの通常Main・同じ保存を保持し、別PIDで復元を観察する。OS未実行やWindows未実行は提出を妨げないが受入済みにはしない。修正後は同候補sourceの証拠を再取得し、過去結果を転用しない。 ## 証拠index protocol v1 Runnerが `BUILD_OUTPUT_DIR/p24-evidence/index.json` を作成する。検証は `python3 tools/check_p24_selection_evidence.py --verify-only`。検証器は証拠を生成せず、欠損/pending/候補違い/失敗を非0で返す。通過も `formal_acceptance=false`。 indexのキー: - `schema_version`: 1。 - `source_map`: `tools/run_all_tests.py` のsource_refsに含まれる**全source**について相対repo path→raw bytes SHA256。各条件・cross-process観察・OS collector・レビューでも同じmapを保持する。 - `artifacts`: artifact名→`{path,sha256}`。pathはp24-evidence内相対path。空ファイル・symlink・上位参照は禁止。Runnerは元の正式証拠を変更せずコピーして登録する。 - `conditions`: 上表の全ID→`{status:"executed",source_map,artifacts:[artifact名,...]}`。未実行はpending。局所条件には検証器指定の実suite raw logを含める。`final_validation_review`だけは全回帰実行済み・正式レビュー待ちを`pending_review`で表す。全回帰input/ended/rowsを必須とし、machine validation後にRunnerが正式独立レビューを実行する。元単位はレビュー終了まで未完了。 - `native`: `{suites:["tests/ui/test_actor_selection.gd","tests/ui/test_selection_lifecycle.gd","tests/ui/test_selection_autosave.gd","tests/ui/test_selection_departure.gd"]}`。全回帰内の実行と照合する。 - `full_regression`: `{input,ended,rows,logs}`。input/ended/rowsはrunner-input.json、runner-ended.json、all-tests.jsonのartifact名。logsは全rosterのsuite path→元の実raw logのartifact名。所有PID・source・run_id・全roster・marker・全phaseを突合する。 - `cross_process`: `{producer,consumer,manifest,world}`。正式保存のmanifest.json/world.binと両観察JSONのartifact名。観察JSONは `{source_map,scene:"res://scenes/main/main.tscn",pid,manifest_sha256,world_sha256,log,observation}`。両processで同一save SHA・別PIDが必要。 - `observation`: `{interface_selection,layer,facility,guest,staff}`。interface_selectionは正式manifestの値、layerはGameStateの値。各対象は `{id,model_values,screen_values}`。facilityにはhighlight_idも必要。model_values/screen_valuesは空でない同形辞書で、実model値と画面に実表示された値を独立に収集する。表示のname/金額/状態/need等を単なるID確認に置き換えない。 - cross-process `log` は通常Mainの実行・観察を採取したcollector raw logのartifact名。`P24_PROCESS pid=<実PID> scene=res://scenes/main/main.tscn` および `P24_OBSERVATION ` を収録する。作成者はこのログを生成していない。Runner collectorが実processと実画面を確認して収録する必要がある。 - `os_input`: OS collector JSONのartifact名。JSONは `{source_map,collector,events}`。collectorはmacOS-CGEventTap、Windows-RawInput、またはCUA-native-app。各eventは `{action,pid,monotonic_ns,native_type,delivery:"native_os",injected,screenshot,raw_trace}`。actionはselect_facility/select_guest/select_staff/select_layer/save/resumeを全て含む。saveはproducer PID、resumeはconsumer PID。native_typeはmouseDown/keyDown。PNGとtrace(eventのsort_keys=True,ensure_ascii=False JSON行)を登録し、normal_os_input条件のartifactsにも含める。OS配信された自動操作は許可し、injectedで由来を開示する。pressed.emit、ゲーム関数呼出し、engine内部注入だけはOS証拠にならない。 - CUA-native-appは`trace_provenance`(original_tool_receiptsまたはfaithful_transcription)と非空の`limitations`を報告し、各eventに`injected:true`、`tool_step` artifactを持つ。step JSONは`{pid,action,monotonic_ns,api:"native_app",operation:"click"または"key",arguments,screenshot,source_map}`。argumentsは実呼出し引数、screenshotは実返却画面。stepも条件artifactに含める。書き起こしの限界とtool生成OS入力を明記し、実CUA呼出し・観察に基づくことをRunnerが照合する。新InputMonitoring許可や物理入力のみという条件は課さない。 - `independent_review`: 最終別セッションClaudeレビューJSONのartifact名。`{source_map,reviewer:"Claude",independent_session,verdict:"pass",condition_ids:[全ID]}`。machine validationより後段のRunner正式レビュー。pending_reviewでは未要求、executedへ更新する場合はこのartifactと全条件coverageを検証する。Runnerは実レビューと突合して保存する。コード作者の自己承認で代用しない。 このprotocolは証拠の整合性を検査する。artifactが実観察/正式レビュー由来であることの責任と元成果の判断はRunnerにあり、任意JSONやログを捏造して正式証拠に扱うことはできない。Windows結果は別に保存し、Mac結果から推測しない。 ## 今回の提出で残る実行 別process fixtureとして `tests/ui/fixtures/selection_cross_process.gd` を追加した。通常Mainをinstantiateする受動観察器であり、選択・保存・読込・Clock変更・command・入力注入を行わない。局所suiteはOS入力の代用にしない。source_mapと正式manifest/worldのSHAを添えた観察、CUA stepと画面、全回帰、正式レビューはいずれも未取得でpending。作成者はgit書込み、Runner操作、試験実行を行っていない。 ## SECOND_LOCAL記録に対する修正(正式再実行pending) 実建設/撤去をguest/staff離脱境界より前へ移動した。意図的に43Gの離職給与債務を保持した後の建設は正規債務ガードに阻まれるためであり、経済ルールは変更しない。assertは維持し、建設失敗messageは `CommandResult.to_dictionary()` を表示する。変更した新suiteだけのSHAをpolicy/markerへ更新した。これは追加のfixture修正であり、既存suiteのSHA/marker/cleanupは変更しない。 ### 受動別process collectorの実行契約 Runnerは同候補project、別PID、専用private user-data環境で `--script res://tests/ui/fixtures/selection_cross_process.gd` をGUI起動する。`P24_OBSERVER_OUTPUT` はそのprocess専用の既存絶対ディレクトリ、`P24_OBSERVER_SOURCE_MAP` は現候補のpath→raw SHA256 map JSONの絶対パス。別worktreeは入力にしない。入力とsource guardは既存Runner側で照合する。 通常Mainの画面操作で必要対象の準備・選択・pause・正式保存・別process読込を行う。observerは1秒間隔で変化した観察を、実PID/連番付きJSONとPNG、stdout `P24_PROCESS` / `P24_RAW_OBSERVATION` として保存し、既存artifactの上書きを拒否する。不要なprocessの終了は通常MainのOSウィンドウcloseに従い、終了強制や外部PID操作を追加しない。追加のtest suiteではなく、roster/成果分母を増やさない。 JSONの `raw_observation` はモデル側facility snapshot、guest observation、staff management reportを、実Labelのheading/detail/priority/decision・need bar・editor可視性・地図highlightとは独立に採取する。表示を再生成してscreen値と称しない。未選択/不存在は空modelとして残し、成功とは判定しない。PNGとJSONはraw証拠であり正式save SHAやOS traceを自己申告しない。 Runner collectorはこのraw証拠と実画面・正式packageを突合し、既存index protocolの `model_values` / `screen_values` を独立に抽出する。表示されていないモデル値をscreen側へコピーしてはならない。`P24_RAW_OBSERVATION` は既存検証器が要求する正規化済み `P24_OBSERVATION` と区別する。正式manifest/worldのSHA、元raw report/frame、OS入力traceへの由来を保持し、未取得はpending。collectorのparseと同一package別PID復元はRunnerの局所/影響範囲検証に含める。 読取専用の静的確認としてPython検証器のAST parseと、新suiteのraw SHAがpolicy/markerの両方と一致することを確認した。Godot parse、局所suite、証拠検証器そのものの実行結果は未取得であり、静的確認を正式試験の合格として扱わない。