P24-03: 選択と保存の受入

This commit is contained in:
Agent Control Runner
2026-10-13 01:14:19 +09:00
parent 9c711860a8
commit c2b8772e23
7 changed files with 108 additions and 17 deletions
@@ -7,7 +7,7 @@
"template": "Selection departure: <checks> checks, <failures> failures", "template": "Selection departure: <checks> checks, <failures> failures",
"required": true, "required": true,
"fixed_check_count_used": false, "fixed_check_count_used": false,
"source_sha256_at_schema_audit": "b43f3fa05e5ab0320e94e317ae75e880746d8557a69ea43bb6a40e93827a4eaf", "source_sha256_at_schema_audit": "a9a2ec8dbcb096da7356e8ea29f6bdb6e014e4d9f95e645c84bfea1e4f423701",
"authority": { "authority": {
"path": "docs/spec/acceptance/P24-03-code-r02.json", "path": "docs/spec/acceptance/P24-03-code-r02.json",
"scope": "new local suite source marker; actual execution pending" "scope": "new local suite source marker; actual execution pending"
@@ -0,0 +1,27 @@
{
"read_only_review_report": true,
"root_product_source_edits": 0,
"findings": [
{
"severity": "high",
"file": "tools/check_p24_selection_evidence.py",
"issue": "gate requires independent_review verdict pass before Runner.validate, while Runner.review requires validation pass. This creates a cycle or an unnecessary second review.",
"required_behavior": "Machine validation must validate actual native/cross-PID/OS/full-regression evidence; Runner formal independent review is the downstream completion gate. Keep original final_validation_review requirement and original-unit incomplete until formal review, but do not fabricate review or require a prior duplicate review to execute validation."
},
{
"severity": "medium",
"file": "tools/check_p24_selection_evidence.py",
"issue": "collector limited to CGEventTap/Windows-RawInput and injected=false adds a hardware-only condition absent from original acceptance. CUA normal OS delivered input is synthesized at OS level, distinct from Godot pressed.emit/Input.parse_input_event. Requirement forbids treating function/emit alone as OS evidence, not all native OS automation.",
"required_behavior": "Permit actual CUA native app calls with faithful step records and observed screens, preferably corroborated by passive Godot _input/GUI input receipts and exact candidate/PID/save/source. Clearly disclose tool-generated OS events and trace limitations. Do not require new InputMonitoring permission or physical hardware only. Direct Godot function/emit or synthetic engine-only fixture must remain insufficient."
}
],
"reused_method_context": "Existing P05-01 accepted finite OS evidence explicitly used root actual CUA calls and returned screens, with the stated limitation that external trace was faithful transcription rather than independently instrumented original tool receipt. This is a method reference only, not a reused current pass.",
"keep_conditions": [
"all 7 condition IDs and no partial original completion",
"exact whole candidate source map",
"real producer/consumer distinct processes and immutable formal package",
"strict full regression and exact raw evidence",
"independent Claude formal review after validation"
],
"implementation_scope": "Comments for implementation owner only; root has not changed gate code or worker source."
}
@@ -0,0 +1,21 @@
{
"read_only_review_report": true,
"candidate": "9c711860a82d597a48dab595a49d4f23c5f3c370",
"evidence_root": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p24-03-local-native-r01",
"import_parse": "pass; 304 scripts",
"local_suite": "test_selection_departure.gd failed, 31 checks, four errors",
"failures": [
"departed guest is absent from selection and dropdown (line42)",
"departed guest leaves no stale current detail values (line43)",
"real facility construction starts (line69)",
"real facility construction completes (line72)"
],
"repair_instructions": [
"Inspect actual guest roster and refresh fallback. Valid other guests can remain and may be selected; do not change correct normal first-row behavior merely to satisfy an incorrect empty-roster fixture. Prove departed ID not referenced; create genuine empty-roster case separately if needed.",
"Use valid real construction coordinates/unlock/payment prerequisites based on existing lifecycle test, record real command result, then prove actual demolition and cleared inspector. Do not bypass services or weaken acceptance.",
"Read ROOT_REVIEW_EVIDENCE_GATE.json and resolve validation/review cycle and over-restrictive OS collector.",
"Implement distinct-process save/restart passive fixture/protocol within allowed paths if needed to enable real remaining acceptance, not fake evidence.",
"Coalesce related changes, update strict source marker SHA/contracts, avoid full regression until local pass. Root will run owned guarded native phases."
],
"root_product_source_edits": 0
}
@@ -9,6 +9,8 @@
- Mainの施設・客・職員metadataのversion判定に数値型を要求。Godot JSONが返す数値1.0は互換性のため許可し、bool/string/非整数値を拒否。 - Mainの施設・客・職員metadataのversion判定に数値型を要求。Godot JSONが返す数値1.0は互換性のため許可し、bool/string/非整数値を拒否。
- 客panelの空選択時にOptionButtonを明示的に未選択にする。既存在館一覧・退館状態表示・履歴分離を維持。 - 客panelの空選択時にOptionButtonを明示的に未選択にする。既存在館一覧・退館状態表示・履歴分離を維持。
- 新局所suiteは実GuestServiceのLEAVING→despawn、一般職員remove、給与履歴保持、Unique拒否、UI収集時の全Runtime digest不変性、metadata型境界を確認する。関数呼出しはnative局所検証でありOS証拠には数えない。 - 新局所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条件は変更しない。 - 新suiteだけにpolicyとstrict markerを追加。既存suiteのSHA・assert・cleanup・marker条件は変更しない。
- レイヤーは既存GameState snapshot、施設表示/地図強調は既存Main、職員一覧は既存service report、正式保存/失敗読込は既存契約を再利用。経済・Clock・人物・旧保存係数の変更なし。 - レイヤーは既存GameState snapshot、施設表示/地図強調は既存Main、職員一覧は既存service report、正式保存/失敗読込は既存契約を再利用。経済・Clock・人物・旧保存係数の変更なし。
- 新検証器は読取専用。限定suite機能、見た目、素材、Runner操作、外部worktree入力は追加しない。 - 新検証器は読取専用。限定suite機能、見た目、素材、Runner操作、外部worktree入力は追加しない。
@@ -40,13 +42,20 @@ indexのキー:
- `schema_version`: 1。 - `schema_version`: 1。
- `source_map`: `tools/run_all_tests.py` のsource_refsに含まれる**全source**について相対repo path→raw bytes SHA256。各条件・cross-process観察・OS collector・レビューでも同じmapを保持する。 - `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は元の正式証拠を変更せずコピーして登録する。 - `artifacts`: artifact名→`{path,sha256}`。pathはp24-evidence内相対path。空ファイル・symlink・上位参照は禁止。Runnerは元の正式証拠を変更せずコピーして登録する。
- `conditions`: 上表の全ID→`{status:"executed",source_map,artifacts:[artifact名,...]}`。未実行はpending。局所条件には検証器指定の実suite raw logを含める。 - `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"]}`。全回帰内の実行と照合する。 - `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を突合する。 - `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が必要。 - `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確認に置き換えない。 - `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 <observationをsort_keys=True,ensure_ascii=Falseのjson.dumpsで表現>` を収録する。作成者はこのログを生成していない。Runner collectorが実processと実画面を確認して収録する必要がある。 - cross-process `log` は通常Mainの実行・観察を採取したcollector raw logのartifact名。`P24_PROCESS pid=<実PID> scene=res://scenes/main/main.tscn` および `P24_OBSERVATION <observationをsort_keys=True,ensure_ascii=Falseのjson.dumpsで表現>` を収録する。作成者はこのログを生成していない。Runner collectorが実processと実画面を確認して収録する必要がある。
- `os_input`: OS collector JSONのartifact名。JSONは `{source_map,collector,events}`。collectorはmacOS-CGEventTapまたはWindows-RawInput。各eventは `{action,pid,monotonic_ns,native_type,injected:false,screenshot,raw_trace}`。actionはselect_facility/select_guest/select_staff/select_layer/save/resumeを全て含む。native_typeはmouseDown/keyDown。PNGとcollectorの生trace(eventのsort_keys=True,ensure_ascii=False JSON行)を登録する。pressed.emit、関数呼出し、注入イベント、自己申告trueだけをOS証拠にしない。 - `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証拠にならない。
- `independent_review`: 最終別セッションClaudeレビューJSONのartifact名。`{source_map,reviewer:"Claude",independent_session,verdict:"pass",condition_ids:[全ID]}`。Runnerは実レビューと突合して保存する。コード作者の自己承認で代用しない。 - 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結果から推測しない。 このprotocolは証拠の整合性を検査する。artifactが実観察/正式レビュー由来であることの責任と元成果の判断はRunnerにあり、任意JSONやログを捏造して正式証拠に扱うことはできない。Windows結果は別に保存し、Mac結果から推測しない。
## 今回の提出で残る実行
別process fixtureは追加しない。既存通常Mainの正式save/loadとRunner所有の実OS観察を使用し、上記producer/consumer protocolで同一package・別PID・実画面値を採取する。局所suiteはOS入力の代用にしない。source_mapと正式manifest/worldのSHAを添えた観察、CUA stepと画面、全回帰、正式レビューはいずれも未取得でpending。作成者はgit書込み、Runner操作、試験実行を行っていない。
読取専用の静的確認としてPython検証器のAST parseと、新suiteのraw SHAがpolicy/markerの両方と一致することを確認した。Godot parse、局所suite、証拠検証器そのものの実行結果は未取得であり、静的確認を正式試験の合格として扱わない。
+13 -3
View File
@@ -39,7 +39,16 @@ func _run() -> void:
_expect(runtime.guest_service.despawn_guest(&"departure_guest", clock.absolute_minute + 2).get(&"ok", false), "actual guest despawn") _expect(runtime.guest_service.despawn_guest(&"departure_guest", clock.absolute_minute + 2).get(&"ok", false), "actual guest despawn")
guest.refresh() guest.refresh()
_expect(not runtime.guest_service.has_guest(&"departure_guest") and not runtime.guest_service.get_persistent_record(&"departure_guest").is_empty(), "history survives without a currently selectable guest") _expect(not runtime.guest_service.has_guest(&"departure_guest") and not runtime.guest_service.get_persistent_record(&"departure_guest").is_empty(), "history survives without a currently selectable guest")
_expect(guest.selected_guest_id.is_empty() and guest.guests.selected == -1 and guest.guests.disabled, "departed guest is absent from selection and dropdown") _expect(guest.selected_guest_id != &"departure_guest" and not guest.get("_ids").has(&"departure_guest"), "departed ID is absent while live roster fallback remains valid")
if not guest.selected_guest_id.is_empty():
var live_report: Dictionary = runtime.guest_service.get_observation(guest.selected_guest_id)
_expect(not live_report.is_empty() and ("%dG" % int(live_report[&"wallet_gold"])) in guest.details.text, "fallback displays the live guest wallet")
# Create an empty-roster boundary through real departures, never array erasure.
for live: GuestRuntime in runtime.guest_service.get_guests():
_expect(runtime.guest_service.begin_leaving(live.guest_id, clock.absolute_minute + 3, &"TEST_EXIT").get(&"ok", false), "empty-roster fixture begins departure")
_expect(runtime.guest_service.despawn_guest(live.guest_id, clock.absolute_minute + 4).get(&"ok", false), "empty-roster fixture completes departure")
guest.refresh()
_expect(guest.selected_guest_id.is_empty() and guest.guests.selected == -1 and guest.guests.disabled, "empty roster has no current selection or dropdown target")
_expect(guest.priority_label.text.is_empty() and guest.decision_label.text.is_empty(), "departed guest leaves no stale current detail values") _expect(guest.priority_label.text.is_empty() and guest.decision_label.text.is_empty(), "departed guest leaves no stale current detail values")
for need: StringName in guest.bars: for need: StringName in guest.bars:
_expect(guest.bars[need].value == 0, "departed guest clears current need " + String(need)) _expect(guest.bars[need].value == 0, "departed guest clears current need " + String(need))
@@ -66,8 +75,9 @@ func _run() -> void:
for version: Variant in [true, 1.5, "1", 0, 2]: for version: Variant in [true, 1.5, "1", 0, 2]:
main.call("_restore_actor_interface_selection", {"interface_selection": {"version": version, "staff_id": "departure_unique", "staff_open": true}}) main.call("_restore_actor_interface_selection", {"interface_selection": {"version": version, "staff_id": "departure_unique", "staff_open": true}})
_expect(staff.selected_staff_id.is_empty() and not staff.visible, "wrong/old metadata version is ignored: " + str(version)) _expect(staff.selected_staff_id.is_empty() and not staff.visible, "wrong/old metadata version is ignored: " + str(version))
_expect(runtime.submit_command(&"build_facility", {&"definition_id": &"guest_corridor", &"origin": Vector3i(4, 1, 0)}).is_success(), "real facility construction starts") var build_result: Variant = runtime.submit_command(&"build_facility", {&"definition_id": &"reception", &"origin": Vector3i(-8, 0, 0)})
clock.advance_minutes(100) _expect(build_result.is_success(), "real facility construction starts: " + str(build_result))
clock.advance_minutes(120)
var facilities: Array = runtime.construction_service.get_facilities() var facilities: Array = runtime.construction_service.get_facilities()
_expect(not facilities.is_empty(), "real facility construction completes") _expect(not facilities.is_empty(), "real facility construction completes")
if not facilities.is_empty(): if not facilities.is_empty():
+33 -9
View File
@@ -63,7 +63,12 @@ def verify(base):
for name in CONDITIONS: for name in CONDITIONS:
row = matrix[name] row = matrix[name]
require(row.get('source_map') == current, 'condition candidate mismatch: ' + name) require(row.get('source_map') == current, 'condition candidate mismatch: ' + name)
require(row.get('status') == 'executed' and row.get('artifacts'), 'pending condition: ' + name) # Formal independent review follows machine validation in Runner.
# Keep its condition explicit without requiring a prior duplicate review.
if name == 'final_validation_review':
require(row.get('status') in ('pending_review', 'executed') and row.get('artifacts'), 'final regression evidence missing')
else:
require(row.get('status') == 'executed' and row.get('artifacts'), 'pending condition: ' + name)
for reference in row['artifacts']: for reference in row['artifacts']:
artifact(reference) artifact(reference)
@@ -140,23 +145,42 @@ def verify(base):
# OS collector events must identify actual input, target process and captured frames. # OS collector events must identify actual input, target process and captured frames.
os_report = read(artifact(index['os_input'])) os_report = read(artifact(index['os_input']))
require(index['os_input'] in matrix['normal_os_input']['artifacts'], 'OS condition lacks collector artifact') require(index['os_input'] in matrix['normal_os_input']['artifacts'], 'OS condition lacks collector artifact')
require(os_report.get('source_map') == current and os_report.get('collector') in ('macOS-CGEventTap', 'Windows-RawInput'), 'OS collector/source mismatch') require(os_report.get('source_map') == current and os_report.get('collector') in ('macOS-CGEventTap', 'Windows-RawInput', 'CUA-native-app'), 'OS collector/source mismatch')
cua = os_report.get('collector') == 'CUA-native-app'
if cua:
require(os_report.get('trace_provenance') in ('original_tool_receipts', 'faithful_transcription') and isinstance(os_report.get('limitations'), str) and os_report['limitations'].strip(), 'CUA trace provenance/limitations required')
events = os_report.get('events', []) events = os_report.get('events', [])
required_actions = {'select_facility', 'select_guest', 'select_staff', 'select_layer', 'save', 'resume'} required_actions = {'select_facility', 'select_guest', 'select_staff', 'select_layer', 'save', 'resume'}
require({e.get('action') for e in events} >= required_actions, 'OS action coverage missing') require({e.get('action') for e in events} >= required_actions, 'OS action coverage missing')
require(any(e.get('action') == 'save' and e.get('pid') == observations[0]['pid'] for e in events) and any(e.get('action') == 'resume' and e.get('pid') == observations[1]['pid'] for e in events), 'OS save/resume must target producer/consumer respectively')
for event in events: for event in events:
require(event.get('pid') in [r['pid'] for r in observations] and type(event.get('monotonic_ns')) is int, 'OS target/time mismatch') require(type(event.get('pid')) is int and event['pid'] in [r['pid'] for r in observations] and type(event.get('monotonic_ns')) is int and event['monotonic_ns'] > 0, 'OS target/time mismatch')
require(event.get('native_type') in ('mouseDown', 'keyDown') and event.get('injected') is False, 'function/emit/synthetic event is not OS input') require(event.get('native_type') in ('mouseDown', 'keyDown'), 'engine function/emit is not OS input')
if cua:
require(event.get('delivery') == 'native_os' and event.get('injected') is True, 'CUA must disclose tool-generated native OS delivery')
step = read(artifact(event['tool_step']))
require(step.get('pid') == event['pid'] and step.get('action') == event['action'] and step.get('monotonic_ns') == event['monotonic_ns'], 'CUA step target/action/time mismatch')
require(step.get('api') == 'native_app' and step.get('operation') in ('click', 'key') and isinstance(step.get('arguments'), dict) and step['arguments'], 'actual native app call arguments missing')
require(step.get('screenshot') == event['screenshot'] and step.get('source_map') == current, 'CUA returned screen/source mismatch')
else:
require(type(event.get('injected')) is bool and event.get('delivery') == 'native_os', 'OS delivery/origin disclosure required')
frame = artifact(event['screenshot']) frame = artifact(event['screenshot'])
require({event['screenshot'], event['raw_trace']} <= set(matrix['normal_os_input']['artifacts']), 'OS condition lacks actual frame/trace artifacts')
if cua:
require(event['tool_step'] in matrix['normal_os_input']['artifacts'], 'OS condition lacks native app step artifact')
require(frame.read_bytes().startswith(b'\x89PNG\r\n\x1a\n'), 'OS screenshot missing/invalid') require(frame.read_bytes().startswith(b'\x89PNG\r\n\x1a\n'), 'OS screenshot missing/invalid')
trace = artifact(event['raw_trace']).read_text() trace = artifact(event['raw_trace']).read_text()
require(json.dumps(event, sort_keys=True, ensure_ascii=False) in trace, 'OS event missing in collector trace') require(json.dumps(event, sort_keys=True, ensure_ascii=False) in trace, 'OS event missing in collector trace')
review = read(artifact(index['independent_review'])) require(set(matrix['final_validation_review']['artifacts']) >= {regression['input'], regression['ended'], regression['rows']}, 'final condition lacks full regression artifacts')
require(set(matrix['final_validation_review']['artifacts']) >= {regression['input'], regression['ended'], regression['rows'], index['independent_review']}, 'final condition lacks full regression/review artifacts') review_status = 'pending'
require(review.get('source_map') == current and review.get('reviewer') == 'Claude' and review.get('independent_session') and review.get('verdict') == 'pass', 'independent final Claude review missing') if matrix['final_validation_review']['status'] == 'executed':
require(set(review.get('condition_ids', [])) == set(CONDITIONS), 'independent review coverage missing') review = read(artifact(index['independent_review']))
return {'machine_validation': True, 'formal_acceptance': False, 'conditions': list(CONDITIONS)} require(index['independent_review'] in matrix['final_validation_review']['artifacts'], 'final condition lacks review artifact')
require(review.get('source_map') == current and review.get('reviewer') == 'Claude' and review.get('independent_session') and review.get('verdict') == 'pass', 'independent final Claude review missing')
require(set(review.get('condition_ids', [])) == set(CONDITIONS), 'independent review coverage missing')
review_status = 'executed'
return {'machine_validation': True, 'formal_acceptance': False, 'conditions': list(CONDITIONS), 'independent_review': review_status}
def main(): def main():
+1 -1
View File
@@ -2,7 +2,7 @@
"schema_version": 1, "schema_version": 1,
"suite_policies": { "suite_policies": {
"tests/ui/test_selection_departure.gd": { "tests/ui/test_selection_departure.gd": {
"source_sha256": "b43f3fa05e5ab0320e94e317ae75e880746d8557a69ea43bb6a40e93827a4eaf", "source_sha256": "a9a2ec8dbcb096da7356e8ea29f6bdb6e014e4d9f95e645c84bfea1e4f423701",
"ordinary_cleanup_prepared": true, "ordinary_cleanup_prepared": true,
"ordinary_control_labels": ["single"], "ordinary_control_labels": ["single"],
"old_bounded_teardown": false, "old_bounded_teardown": false,