Record P24 normal placement and modal preservation evidence
This commit is contained in:
+4
-2
@@ -4,8 +4,8 @@
|
||||
|
||||
| 条件ID | 現証拠と不足・依存 |
|
||||
|---|---|
|
||||
| placement_and_invalid_drop | 既存666cの原本配置/スタッフ局所証拠はsource/config/input一致を確認した範囲のみ再利用。通常有効1回、無効説明・台帳/選択保全とclick代替の現候補証拠を揃える。 |
|
||||
| modal_and_pause_resume | 9641の操作通知局所58PASSと実OS保存dialogのblock解除を取得。全modal取消確定/背後操作/保留command/実時間停止再開を条件別に照合。 |
|
||||
| placement_and_invalid_drop | 既存666cの原本配置/スタッフ局所証拠はsource/config/input一致を確認した範囲のみ再利用。追加native49041で有効1command/job/chargeと重複拒否text、全Runtime/台帳/選択保全を確認し限定reviewPASS。無効配属/dropと全click代替の証拠は残る。 |
|
||||
| modal_and_pause_resume | 9641の操作通知局所58PASSと実OS保存dialogのblock解除を取得。追加native49041で通常menu id3/modal開閉/取消/全Runtimeと選択保全を記録。全modal取消確定/背後操作/保留command/実時間停止再開を条件別に照合。 |
|
||||
| unit_bubbles | 666cからproduct bindingは今回未変更。全対象実状態/切替/除去の現候補適用根拠を追加、fixtureのみで完了にしない。 |
|
||||
| event_log | 9641局所34PASS。既完了P24-03のログ256件は一致する範囲で再利用。自然event順序/時刻/理由/保存再開重複の通し証拠を追加。 |
|
||||
| important_warning_cutin | 原本通り盾positive→0でNTR侵食開始の表示文へ修正し独立限定reviewPASS。自然生成のP18-01/02、3決闘/結果保存P19-01、自然防衛P21-01が依存。synthetic signalは通常実証に替えない。 |
|
||||
@@ -20,3 +20,5 @@
|
||||
対象外の改善は独立レビューfindingsに記録。旧commentのvanishing表現などは現許可差分へ混ぜず、通常入力feedback/保存破損等の必須性を優先する。未確定の関係値・数値・仕様は作らない。
|
||||
|
||||
追補証拠: native-os-input-r01/ordinary-save-preservation-observations-r03.json、preservation-provenance-supplement-r04.json、independent-preservation-evidence-review-r04.json。最初の資料不足reviewを保持し、既存dataの補完で解消。menu/pointer/resumeはCUA観測の適用限界を保持、単位全受入には未転用。
|
||||
|
||||
追補r05 controls: Root記録器の施設id参照エラーr04はFAIL保持、修正とJSON/PNG/操作後capture追加r05でnative49041/実menu3/有効1回/重複拒否/取消全状態保全を取得。別Opus限定text reviewPASS、PNGはRoot確認。元MainのSceneTree観測起動であり、通常main_scene起動/全操作/全platformの受入を代替しない。
|
||||
|
||||
@@ -21,3 +21,5 @@ Claude Opus5.5の記録済み判断で、同じ登録タスク/既存worktreeを
|
||||
限定差分の別Opus5.5 reviewはPASS(実argv検証)。全条件正式reviewには未代替。レビュー残件に既存manual_uiの前後hash、全world digest、実NTR文言/実発生、invalid label feedbackとDELを記録。今回consumerはid2の通常一覧から選択。
|
||||
|
||||
追補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既存承認候補案は同一コピーを再利用できるが個別cap1使用1、追加修正質問中でworkerは未起動。
|
||||
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"path": "/Users/korizatou114/Library/Application Support/TheTree-PCK-tests-3dad784a3a94422ca8c0a8767253a76e-p24-02-os",
|
||||
"saves_directory_exists": false,
|
||||
"owned_files": [
|
||||
"logs/godot.log"
|
||||
],
|
||||
"capture_time_utc": "2026-10-13T07:27:12.025081+00:00"
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"candidate": "9641ed52def2ff8e5b0222449a4a83a1191e1d37",
|
||||
"actual_review_model_argv_verified": "claude-opus-5-5",
|
||||
"limited_review": "passed",
|
||||
"whole_unit_accepted": false,
|
||||
"collector_r04_failed": true,
|
||||
"collector_r05_changes": [
|
||||
"Correct real FacilityDefinition.id instead of nonexistent definition_id",
|
||||
"Add full JSON companion to each raw Runtime snapshot",
|
||||
"Add deferred capture after root mouse dispatch with status text/selection and bounded viewport PNG"
|
||||
],
|
||||
"game_code_changed": false,
|
||||
"native_main_scene_boot_note": "This development probe uses SceneTree script instantiating real main.tscn; ordinary project main_scene boot was not separately observed. Existing pass must not cover that boot condition.",
|
||||
"observer_timing_note": "First selection click capture precedes release/deferred UI updates. Selection precondition is native CUA-observed; after actual valid placement captures record reception selected.",
|
||||
"visual_review_note": "Root actually viewed pinned PNG003 and PNG006. Separate text-only reviewer did not inspect pixels or recompute artifact hashes. Formal full-unit independent review still required.",
|
||||
"background_click_note": "Native CUA attempted map click while dialog open. No Root InputEvent receipt for that exclusive dialog click, so exhaustive behind-input acceptance remains unclaimed.",
|
||||
"counter_correction": "MP-01-r02 global default2 is not individual task cap1; Root corrected statement and no worker/cap change executed."
|
||||
}
|
||||
+6077
File diff suppressed because it is too large
Load Diff
+33
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"candidate": "9641ed52def2ff8e5b0222449a4a83a1191e1d37",
|
||||
"scope": "Limited normal click placement rejection and menu/modal-cancel evidence; not formal P24 whole review",
|
||||
"result": {
|
||||
"status": "passed",
|
||||
"summary": "The supplied data supports the narrow observation on candidate 9641ed5, macOS, pid 49041. It covers one native valid reception placement, one overlap-invalid click, opening production SaveLoadMenu id 3 and cancelling the dialog. Exactly one command, job and cost charge occurred. The real overlap rejection text appeared and the reception selection stayed in place. The modal guard went false→true→true→false. Runtime snapshot bytes were identical from the valid placement through the cancel. The controller recorded exit 0, no ERROR lines and clean source, stage and default-player guards. My review covers only the supplied JSON, the supplied method excerpts and the collector/controller source. I did not recompute any hash, read events.jsonl or engine-native.log, or view any image. This is not whole-unit acceptance.",
|
||||
"findings": [
|
||||
"SUPPORTED – snapshot equality: ui-snapshot-000 and 001 share bin sha dfea68…/json ec054c…; 002 through 007 share bin sha 17399e…/json 07cebb…. The only state change is at 002, after the valid click. This is consistent with both valid_to_invalid_full_runtime_bytes_identical and all_full_runtime_bytes_identical_after_valid_through_modal_cancel. These are pin comparisons as supplied; I did not recompute them.",
|
||||
"SUPPORTED – exactly one command, job and cost: after_valid_full_json has one accepted/processed command (command_id 1, key ui.build.00000001, code OK), one PLANNED job construction_00000001 (reception, origin [-5,0,0], 8 reserved cells), next_command_id 2, next_job_sequence 2, one new ledger entry ledger_00000004 (500 gold CONSTRUCTION) and resources 5000/50→4500/42, matching total_cost {gold 500, materials 8}. Because 003–007 are byte-identical to 002, no second command, job or charge was added later in the observed window.",
|
||||
"SUPPORTED – actual status-text rejection: capture 003 status_text is exactly '配置不可: ほかの施設または工事と重なります', and the runtime bytes are unchanged. This matches the _on_map_cell_clicked path, which calls get_build_preview_report and then _set_status(_preview_failure_message(...), false) and returns before _submit_ui_command. The body of _preview_failure_message was not supplied, so I accept the mapping only from the observed text.",
|
||||
"SUPPORTED – selection preserved: build_definition_id 'reception' and palette_open true appear in every capture from 002 to 007, including after the invalid click and after cancel. This agrees with _on_map_cell_clicked, whose failure path does not clear _selected_definition.",
|
||||
"SUPPORTED – modal guard: modal_blocked is false at 004, true at 005 (menu_3) and 006 (dialog_visibility_true), and false at 007 (dialog_visibility_false). This matches modal_guard_states [false,true,true,false]. It is consistent with the source: _ensure_manual_save_slots connects visibility_changed to _update_modal_input_guard, and world_preview._gui_input calls accept_event() and returns when the guard is set. The actual_menu_item row (id 3, pid 49041, ticks 116393) comes from the production PopupMenu's id_pressed signal.",
|
||||
"SUPPORTED (narrow) – no save on cancel: snapshot bytes are unchanged across open and cancel, save_path stays 'user://saves/manual_ui', and the supplied rows contain no save_operation_completed receipt. Limit: the supplied data does not include a directory listing of the private profile's saves folder or the full events.jsonl, so 'no file created' rests on the root claim plus the absent receipt.",
|
||||
"SUPPORTED – observer/controller read-only (source level): PassiveRecorder only connects to signals, calls runtime.create_snapshot() and reads properties. Its _input logs events without calling accept_event and does not inject any input. Repeated create_snapshot calls across 002–007 produced identical bytes, which shows no observable mutation. The controller swaps project.godot to a private profile and restores it, then checks that the source refs, stage inventory and default player are unchanged; guard_errors and cleanup_errors are both empty.",
|
||||
"SUPPORTED – no-error end: controller_guards.passed is true, there is one row with exit_code 0 and engine_ended true, and the log is pinned at 4f94d5…. The log was checked to contain neither 'ERROR:' nor 'SCRIPT ERROR:', but the log text itself was not supplied.",
|
||||
"LIMIT – how reception got selected is not evidenced here. Capture 001 (a mouse press) shows palette_open false, and the next captured press, 002, already shows the placement succeeded with reception selected. No captured press covers palette opening or reception selection. Button release-mode activation and/or keyboard input would explain this, but the key rows in events.jsonl were not supplied. Treat the precondition path as unreviewed.",
|
||||
"LIMIT – launch path: the collector runs `--script passive_os.gd` (a SceneTree subclass), instantiates main.tscn by hand and sets root.title. This is close to the production main scene but is not the project's ordinary main_scene boot.",
|
||||
"LIMIT – the clock was paused (paused true, minute 360) for the whole session. Byte equality therefore shows no command or side effect, but says nothing about behaviour while time is running.",
|
||||
"LIMIT – the background click behind the dialog (native CUA at 988,566) produced no root InputEvent receipt. Only open/cancel snapshot equality is supported. Do not claim acceptance of exhaustive behind-dialog input blocking or a native behind-click receipt.",
|
||||
"LIMIT – the cancel click on the dialog's own Window viewport is not logged by the root observer; cancel is inferred from dialog_visibility_false plus snapshot equality.",
|
||||
"LIMIT – visual: frame PNG pins are supplied, but I did not inspect any pixels. The checks of frame003 (invalid explanation, display 4500/42) and frame006 (dialog body and buttons) are the root reviewer's claims only. Dialog frames exclude native window chrome.",
|
||||
"LIMIT – full-file review: whole_unchanged_file_review is false for main.gd and world_preview.gd. Only the listed methods were reviewed; _preview_failure_message, _submit_ui_command, the SaveLoadMenu id 3 handler, the cancel handler and ManualSaveSlotsDialog were not supplied.",
|
||||
"RETAINED – the r04 run that failed (collector used definition_id instead of FacilityDefinition.id; ended.json sha 31346f…) stays recorded as failed. In r05 only the collector field was corrected, and the source-ref guards in the supplied controller show the product is unchanged.",
|
||||
"SCOPE – this is one macOS session only. It does not complete all 8 P24 conditions, all modal, pointer or staff-assignment conditions, or Windows. independent_review in the proof data is false, and whole_unit_accepted stays false."
|
||||
],
|
||||
"whole_unit_accepted": false
|
||||
},
|
||||
"artifact": "/Users/korizatou114/Library/Application Support/agent-control/the-tree-p24-02-operations/runs/1a197ec2abff40eca265f71baa4d621e",
|
||||
"model": "claude-opus-5-5",
|
||||
"whole_unit_accepted": false,
|
||||
"formal_runner_review": false,
|
||||
"proof_sha256": "56d5e47139841f40d7fed0d053fb9eb87956e07240a208355a77a94a7dd0a094"
|
||||
}
|
||||
+624
@@ -0,0 +1,624 @@
|
||||
{
|
||||
"candidate": "9641ed52def2ff8e5b0222449a4a83a1191e1d37",
|
||||
"scope": "One normal macOS click valid/overlap-invalid reception placement and named-save modal open/behind-click/cancel; not all P24 conditions",
|
||||
"pid": 49041,
|
||||
"initial_resources": {
|
||||
"faith": 0,
|
||||
"gold": 5000,
|
||||
"mana": 100,
|
||||
"materials": 50
|
||||
},
|
||||
"after_valid_resources": {
|
||||
"faith": 0,
|
||||
"gold": 4500,
|
||||
"mana": 100,
|
||||
"materials": 42
|
||||
},
|
||||
"actual_single_construction_job": {
|
||||
"assigned_builder_ids": [],
|
||||
"build_minutes": 120,
|
||||
"cancelled_at": -1,
|
||||
"completed_at": -1,
|
||||
"construction_cost": {
|
||||
"gold": 500,
|
||||
"materials": 8
|
||||
},
|
||||
"created_at": 360,
|
||||
"definition_id": "reception",
|
||||
"facility_instance_id": "",
|
||||
"job_id": "construction_00000001",
|
||||
"last_progress_at": -1,
|
||||
"layer": 0,
|
||||
"origin": [
|
||||
-5,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"progress": 0,
|
||||
"reserved_cells": [
|
||||
[
|
||||
-5,
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
-4,
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
-3,
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
-2,
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
-5,
|
||||
1,
|
||||
0
|
||||
],
|
||||
[
|
||||
-4,
|
||||
1,
|
||||
0
|
||||
],
|
||||
[
|
||||
-3,
|
||||
1,
|
||||
0
|
||||
],
|
||||
[
|
||||
-2,
|
||||
1,
|
||||
0
|
||||
]
|
||||
],
|
||||
"rotation": 0,
|
||||
"started_at": -1,
|
||||
"state": "PLANNED",
|
||||
"state_reason": "",
|
||||
"work_units_done": 0
|
||||
},
|
||||
"actual_processed_commands": [
|
||||
{
|
||||
"code": "OK",
|
||||
"command_id": 1,
|
||||
"details": {
|
||||
"job_id": "construction_00000001",
|
||||
"placement_report": {
|
||||
"access_points": [],
|
||||
"build_time": 120,
|
||||
"can_build": true,
|
||||
"cells": [
|
||||
[
|
||||
-5,
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
-4,
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
-3,
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
-2,
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
-5,
|
||||
1,
|
||||
0
|
||||
],
|
||||
[
|
||||
-4,
|
||||
1,
|
||||
0
|
||||
],
|
||||
[
|
||||
-3,
|
||||
1,
|
||||
0
|
||||
],
|
||||
[
|
||||
-2,
|
||||
1,
|
||||
0
|
||||
]
|
||||
],
|
||||
"error_codes": [],
|
||||
"layer_mismatch_cells": [],
|
||||
"mana_connection": false,
|
||||
"missing_resources": {},
|
||||
"occupied_cells": [],
|
||||
"out_of_bounds_cells": [],
|
||||
"predicted_environment_delta": {},
|
||||
"predicted_heat": 0,
|
||||
"predicted_operating_cost": {},
|
||||
"reasons": [],
|
||||
"total_cost": {
|
||||
"gold": 500,
|
||||
"materials": 8
|
||||
},
|
||||
"unexcavated_cells": [],
|
||||
"unsupported_cells": [],
|
||||
"zone_mismatch_cells": []
|
||||
}
|
||||
},
|
||||
"is_replay": false,
|
||||
"message": "",
|
||||
"resolution_hints": [],
|
||||
"target_id": ""
|
||||
}
|
||||
],
|
||||
"valid_to_invalid_full_runtime_bytes_identical": true,
|
||||
"invalid_text": "配置不可: ほかの施設または工事と重なります",
|
||||
"all_full_runtime_bytes_identical_after_valid_through_modal_cancel": true,
|
||||
"actual_menu_item_rows": [
|
||||
{
|
||||
"kind": "actual_menu_item",
|
||||
"pid": 49041,
|
||||
"ticks_msec": 116393,
|
||||
"value": {
|
||||
"id": 3,
|
||||
"source": "production PopupMenu id_pressed; native input only"
|
||||
}
|
||||
}
|
||||
],
|
||||
"capture_rows": [
|
||||
{
|
||||
"kind": "ui_model_capture",
|
||||
"pid": 49041,
|
||||
"ticks_msec": 2545,
|
||||
"value": {
|
||||
"build_definition_id": "",
|
||||
"filename": "ui-snapshot-000.bin",
|
||||
"json_filename": "ui-snapshot-000.json",
|
||||
"json_sha256": "ec054c36513cf2bc19b4743862b99a6d56ae0cffebe413d731c9ebb6ab53f237",
|
||||
"modal_blocked": false,
|
||||
"palette_open": false,
|
||||
"reason": "dialog_visibility_false",
|
||||
"save_path": "user://saves/manual_ui",
|
||||
"sha256": "dfea6817f87a9c79cc970f65e19991e60741277244106f770341d71185321fd4",
|
||||
"status_text": "B 建築 / H 雇用 / I 運営 ホイール 拡大縮小・中ボタン 移動・Home 全体表示"
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": "ui_model_capture",
|
||||
"pid": 49041,
|
||||
"ticks_msec": 35222,
|
||||
"value": {
|
||||
"build_definition_id": "",
|
||||
"filename": "ui-snapshot-001.bin",
|
||||
"json_filename": "ui-snapshot-001.json",
|
||||
"json_sha256": "ec054c36513cf2bc19b4743862b99a6d56ae0cffebe413d731c9ebb6ab53f237",
|
||||
"modal_blocked": false,
|
||||
"palette_open": false,
|
||||
"reason": "native_mouse_after_dispatch",
|
||||
"save_path": "user://saves/manual_ui",
|
||||
"sha256": "dfea6817f87a9c79cc970f65e19991e60741277244106f770341d71185321fd4",
|
||||
"status_text": "B 建築 / H 雇用 / I 運営 ホイール 拡大縮小・中ボタン 移動・Home 全体表示"
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": "ui_model_capture",
|
||||
"pid": 49041,
|
||||
"ticks_msec": 51252,
|
||||
"value": {
|
||||
"build_definition_id": "reception",
|
||||
"filename": "ui-snapshot-002.bin",
|
||||
"json_filename": "ui-snapshot-002.json",
|
||||
"json_sha256": "07cebb2a71ff0c63608f8a218a03618e9504fd171d8c7059b15bcf901dc5f8ec",
|
||||
"modal_blocked": false,
|
||||
"palette_open": true,
|
||||
"reason": "native_mouse_after_dispatch",
|
||||
"save_path": "user://saves/manual_ui",
|
||||
"sha256": "17399e4292ef33b29079f361bf91d853f0a1b036066e4e23707840d30deac4a3",
|
||||
"status_text": "受付の建設を開始しました(-5, 0 / 0°)。"
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": "ui_model_capture",
|
||||
"pid": 49041,
|
||||
"ticks_msec": 67041,
|
||||
"value": {
|
||||
"build_definition_id": "reception",
|
||||
"filename": "ui-snapshot-003.bin",
|
||||
"json_filename": "ui-snapshot-003.json",
|
||||
"json_sha256": "07cebb2a71ff0c63608f8a218a03618e9504fd171d8c7059b15bcf901dc5f8ec",
|
||||
"modal_blocked": false,
|
||||
"palette_open": true,
|
||||
"reason": "native_mouse_after_dispatch",
|
||||
"save_path": "user://saves/manual_ui",
|
||||
"sha256": "17399e4292ef33b29079f361bf91d853f0a1b036066e4e23707840d30deac4a3",
|
||||
"status_text": "配置不可: ほかの施設または工事と重なります"
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": "ui_model_capture",
|
||||
"pid": 49041,
|
||||
"ticks_msec": 102108,
|
||||
"value": {
|
||||
"build_definition_id": "reception",
|
||||
"filename": "ui-snapshot-004.bin",
|
||||
"json_filename": "ui-snapshot-004.json",
|
||||
"json_sha256": "07cebb2a71ff0c63608f8a218a03618e9504fd171d8c7059b15bcf901dc5f8ec",
|
||||
"modal_blocked": false,
|
||||
"palette_open": true,
|
||||
"reason": "native_mouse_after_dispatch",
|
||||
"save_path": "user://saves/manual_ui",
|
||||
"sha256": "17399e4292ef33b29079f361bf91d853f0a1b036066e4e23707840d30deac4a3",
|
||||
"status_text": "配置不可: ほかの施設または工事と重なります"
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": "ui_model_capture",
|
||||
"pid": 49041,
|
||||
"ticks_msec": 116401,
|
||||
"value": {
|
||||
"build_definition_id": "reception",
|
||||
"filename": "ui-snapshot-005.bin",
|
||||
"json_filename": "ui-snapshot-005.json",
|
||||
"json_sha256": "07cebb2a71ff0c63608f8a218a03618e9504fd171d8c7059b15bcf901dc5f8ec",
|
||||
"modal_blocked": true,
|
||||
"palette_open": true,
|
||||
"reason": "menu_3",
|
||||
"save_path": "user://saves/manual_ui",
|
||||
"sha256": "17399e4292ef33b29079f361bf91d853f0a1b036066e4e23707840d30deac4a3",
|
||||
"status_text": "配置不可: ほかの施設または工事と重なります"
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": "ui_model_capture",
|
||||
"pid": 49041,
|
||||
"ticks_msec": 116437,
|
||||
"value": {
|
||||
"build_definition_id": "reception",
|
||||
"filename": "ui-snapshot-006.bin",
|
||||
"json_filename": "ui-snapshot-006.json",
|
||||
"json_sha256": "07cebb2a71ff0c63608f8a218a03618e9504fd171d8c7059b15bcf901dc5f8ec",
|
||||
"modal_blocked": true,
|
||||
"palette_open": true,
|
||||
"reason": "dialog_visibility_true",
|
||||
"save_path": "user://saves/manual_ui",
|
||||
"sha256": "17399e4292ef33b29079f361bf91d853f0a1b036066e4e23707840d30deac4a3",
|
||||
"status_text": "配置不可: ほかの施設または工事と重なります"
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": "ui_model_capture",
|
||||
"pid": 49041,
|
||||
"ticks_msec": 160193,
|
||||
"value": {
|
||||
"build_definition_id": "reception",
|
||||
"filename": "ui-snapshot-007.bin",
|
||||
"json_filename": "ui-snapshot-007.json",
|
||||
"json_sha256": "07cebb2a71ff0c63608f8a218a03618e9504fd171d8c7059b15bcf901dc5f8ec",
|
||||
"modal_blocked": false,
|
||||
"palette_open": true,
|
||||
"reason": "dialog_visibility_false",
|
||||
"save_path": "user://saves/manual_ui",
|
||||
"sha256": "17399e4292ef33b29079f361bf91d853f0a1b036066e4e23707840d30deac4a3",
|
||||
"status_text": "配置不可: ほかの施設または工事と重なります"
|
||||
}
|
||||
}
|
||||
],
|
||||
"frame_rows": [
|
||||
{
|
||||
"kind": "frame_capture",
|
||||
"pid": 49041,
|
||||
"ticks_msec": 2590,
|
||||
"value": {
|
||||
"error": 0,
|
||||
"filename": "frame-000.png",
|
||||
"reason": "dialog_visibility_false",
|
||||
"sha256": "4516abb706e829094c19632e6c8005ad68877c7856af4ccfdf346e98b8dabe95",
|
||||
"size": [
|
||||
1280,
|
||||
720
|
||||
],
|
||||
"target": "root"
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": "frame_capture",
|
||||
"pid": 49041,
|
||||
"ticks_msec": 35250,
|
||||
"value": {
|
||||
"error": 0,
|
||||
"filename": "frame-001.png",
|
||||
"reason": "native_mouse_after_dispatch",
|
||||
"sha256": "9d61efee38fee61447a3ae10e95e07381f9560254388cc4ce38a79f7a0a21e6d",
|
||||
"size": [
|
||||
1280,
|
||||
720
|
||||
],
|
||||
"target": "root"
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": "frame_capture",
|
||||
"pid": 49041,
|
||||
"ticks_msec": 51290,
|
||||
"value": {
|
||||
"error": 0,
|
||||
"filename": "frame-002.png",
|
||||
"reason": "native_mouse_after_dispatch",
|
||||
"sha256": "4f53747098468b37bc23078d70d091a8b1d8c78ae44547476df70d40c153d03e",
|
||||
"size": [
|
||||
1280,
|
||||
720
|
||||
],
|
||||
"target": "root"
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": "frame_capture",
|
||||
"pid": 49041,
|
||||
"ticks_msec": 67077,
|
||||
"value": {
|
||||
"error": 0,
|
||||
"filename": "frame-003.png",
|
||||
"reason": "native_mouse_after_dispatch",
|
||||
"sha256": "dd60776d2370d79814e874a3944f7bce9152d6d3640bee434c624940f6e000e8",
|
||||
"size": [
|
||||
1280,
|
||||
720
|
||||
],
|
||||
"target": "root"
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": "frame_capture",
|
||||
"pid": 49041,
|
||||
"ticks_msec": 102142,
|
||||
"value": {
|
||||
"error": 0,
|
||||
"filename": "frame-004.png",
|
||||
"reason": "native_mouse_after_dispatch",
|
||||
"sha256": "e8c2b8027767cd26850f02a2d87d2e594bab4c3d6ebcc5f288ec6140f332146d",
|
||||
"size": [
|
||||
1280,
|
||||
720
|
||||
],
|
||||
"target": "root"
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": "frame_capture",
|
||||
"pid": 49041,
|
||||
"ticks_msec": 116416,
|
||||
"value": {
|
||||
"error": 0,
|
||||
"filename": "frame-005.png",
|
||||
"reason": "menu_3",
|
||||
"sha256": "7795cc8c2ee590c673f7bcd16d83e8fbfb85a8fef0af913282e9aa1df54e54c8",
|
||||
"size": [
|
||||
463,
|
||||
285
|
||||
],
|
||||
"target": "dialog"
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": "frame_capture",
|
||||
"pid": 49041,
|
||||
"ticks_msec": 116448,
|
||||
"value": {
|
||||
"error": 0,
|
||||
"filename": "frame-006.png",
|
||||
"reason": "dialog_visibility_true",
|
||||
"sha256": "7795cc8c2ee590c673f7bcd16d83e8fbfb85a8fef0af913282e9aa1df54e54c8",
|
||||
"size": [
|
||||
463,
|
||||
285
|
||||
],
|
||||
"target": "dialog"
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": "frame_capture",
|
||||
"pid": 49041,
|
||||
"ticks_msec": 160222,
|
||||
"value": {
|
||||
"error": 0,
|
||||
"filename": "frame-007.png",
|
||||
"reason": "dialog_visibility_false",
|
||||
"sha256": "0854ba41fd73e5b092d71e7d11e99fe3efb7b25ee04c2b0c8750b5d9de6d84b3",
|
||||
"size": [
|
||||
1280,
|
||||
720
|
||||
],
|
||||
"target": "root"
|
||||
}
|
||||
}
|
||||
],
|
||||
"no_save_created_on_cancel": true,
|
||||
"palette_and_reception_selection_retained_after_valid": true,
|
||||
"modal_guard_states": [
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
false
|
||||
],
|
||||
"background_click_scope": "Actual native CUA click outside dialog at map position988,566; native exclusive/modal handling did not deliver that click to the root recorder. Open/cancel snapshots are byte-identical. Separate native behind-click receipt is not claimed.",
|
||||
"root_visual_check": "Root viewed frame003 actual invalid explanation/unchanged displayed4500/42 and frame006 dialog body/buttons. Dialog PNG excludes native window chrome by viewport design.",
|
||||
"controller_guards": {
|
||||
"passed": true,
|
||||
"error": null,
|
||||
"guard_errors": [],
|
||||
"cleanup_errors": [],
|
||||
"rows": [
|
||||
{
|
||||
"actual_pid": 49041,
|
||||
"exit_code": 0,
|
||||
"engine_ended": true,
|
||||
"log_sha256": "4f94d50fe2500a312baac896c7314f26816c544b2305a62796e98e5ed4538809"
|
||||
}
|
||||
]
|
||||
},
|
||||
"old_failed_recording": {
|
||||
"path": "artifacts/original-completion-2026-10-02/p24-02-native-os-controls-r04/ended.json",
|
||||
"sha256": "31346f8bde2eca1bae2202e746733dec4a5e65917ecb54aa2975e88e815069e2",
|
||||
"reason": "Root collector used definition_id instead of real FacilityDefinition.id; product unchanged; failed pass false retained"
|
||||
},
|
||||
"whole_unit_accepted": false,
|
||||
"independent_review": false,
|
||||
"Windows": false,
|
||||
"evidence": [
|
||||
{
|
||||
"path": "artifacts/original-completion-2026-10-02/p24-02-native-os-controls-r05/started.json",
|
||||
"sha256": "64397b2e4b9cf67faf78bd02848492895111ac0b0b32c9d4fd629e481103b094",
|
||||
"bytes": 726638
|
||||
},
|
||||
{
|
||||
"path": "artifacts/original-completion-2026-10-02/p24-02-native-os-controls-r05/process-started.json",
|
||||
"sha256": "3b73172fa0124a5ef47f7004d5ae4144b057279b7246e8dd4eb84cc5a1097c17",
|
||||
"bytes": 727110
|
||||
},
|
||||
{
|
||||
"path": "artifacts/original-completion-2026-10-02/p24-02-native-os-controls-r05/ended.json",
|
||||
"sha256": "9bbdf3d512b5f5ae4a8f9595da1cac52587a5f05009869ec7e0d7c8099c4ed8a",
|
||||
"bytes": 727662
|
||||
},
|
||||
{
|
||||
"path": "artifacts/original-completion-2026-10-02/p24-02-native-os-controls-r05/events.jsonl",
|
||||
"sha256": "f456f8013343264573c6cab8c7be99807210cb889a78f0a1db1461989d46a3dc",
|
||||
"bytes": 9985
|
||||
},
|
||||
{
|
||||
"path": "artifacts/original-completion-2026-10-02/p24-02-native-os-controls-r05/passive_os.gd",
|
||||
"sha256": "552f9bb40770f1a88bbfb41586782e4f8ba8dff29776336ab83ba64dbd2f4767",
|
||||
"bytes": 8021
|
||||
},
|
||||
{
|
||||
"path": "artifacts/original-completion-2026-10-02/p24-02-native-os-controls-r05/ui-snapshot-000.bin",
|
||||
"sha256": "dfea6817f87a9c79cc970f65e19991e60741277244106f770341d71185321fd4",
|
||||
"bytes": 80292
|
||||
},
|
||||
{
|
||||
"path": "artifacts/original-completion-2026-10-02/p24-02-native-os-controls-r05/ui-snapshot-001.bin",
|
||||
"sha256": "dfea6817f87a9c79cc970f65e19991e60741277244106f770341d71185321fd4",
|
||||
"bytes": 80292
|
||||
},
|
||||
{
|
||||
"path": "artifacts/original-completion-2026-10-02/p24-02-native-os-controls-r05/ui-snapshot-002.bin",
|
||||
"sha256": "17399e4292ef33b29079f361bf91d853f0a1b036066e4e23707840d30deac4a3",
|
||||
"bytes": 84828
|
||||
},
|
||||
{
|
||||
"path": "artifacts/original-completion-2026-10-02/p24-02-native-os-controls-r05/ui-snapshot-003.bin",
|
||||
"sha256": "17399e4292ef33b29079f361bf91d853f0a1b036066e4e23707840d30deac4a3",
|
||||
"bytes": 84828
|
||||
},
|
||||
{
|
||||
"path": "artifacts/original-completion-2026-10-02/p24-02-native-os-controls-r05/ui-snapshot-004.bin",
|
||||
"sha256": "17399e4292ef33b29079f361bf91d853f0a1b036066e4e23707840d30deac4a3",
|
||||
"bytes": 84828
|
||||
},
|
||||
{
|
||||
"path": "artifacts/original-completion-2026-10-02/p24-02-native-os-controls-r05/ui-snapshot-005.bin",
|
||||
"sha256": "17399e4292ef33b29079f361bf91d853f0a1b036066e4e23707840d30deac4a3",
|
||||
"bytes": 84828
|
||||
},
|
||||
{
|
||||
"path": "artifacts/original-completion-2026-10-02/p24-02-native-os-controls-r05/ui-snapshot-006.bin",
|
||||
"sha256": "17399e4292ef33b29079f361bf91d853f0a1b036066e4e23707840d30deac4a3",
|
||||
"bytes": 84828
|
||||
},
|
||||
{
|
||||
"path": "artifacts/original-completion-2026-10-02/p24-02-native-os-controls-r05/ui-snapshot-007.bin",
|
||||
"sha256": "17399e4292ef33b29079f361bf91d853f0a1b036066e4e23707840d30deac4a3",
|
||||
"bytes": 84828
|
||||
},
|
||||
{
|
||||
"path": "artifacts/original-completion-2026-10-02/p24-02-native-os-controls-r05/ui-snapshot-000.json",
|
||||
"sha256": "ec054c36513cf2bc19b4743862b99a6d56ae0cffebe413d731c9ebb6ab53f237",
|
||||
"bytes": 49113
|
||||
},
|
||||
{
|
||||
"path": "artifacts/original-completion-2026-10-02/p24-02-native-os-controls-r05/ui-snapshot-001.json",
|
||||
"sha256": "ec054c36513cf2bc19b4743862b99a6d56ae0cffebe413d731c9ebb6ab53f237",
|
||||
"bytes": 49113
|
||||
},
|
||||
{
|
||||
"path": "artifacts/original-completion-2026-10-02/p24-02-native-os-controls-r05/ui-snapshot-002.json",
|
||||
"sha256": "07cebb2a71ff0c63608f8a218a03618e9504fd171d8c7059b15bcf901dc5f8ec",
|
||||
"bytes": 51681
|
||||
},
|
||||
{
|
||||
"path": "artifacts/original-completion-2026-10-02/p24-02-native-os-controls-r05/ui-snapshot-003.json",
|
||||
"sha256": "07cebb2a71ff0c63608f8a218a03618e9504fd171d8c7059b15bcf901dc5f8ec",
|
||||
"bytes": 51681
|
||||
},
|
||||
{
|
||||
"path": "artifacts/original-completion-2026-10-02/p24-02-native-os-controls-r05/ui-snapshot-004.json",
|
||||
"sha256": "07cebb2a71ff0c63608f8a218a03618e9504fd171d8c7059b15bcf901dc5f8ec",
|
||||
"bytes": 51681
|
||||
},
|
||||
{
|
||||
"path": "artifacts/original-completion-2026-10-02/p24-02-native-os-controls-r05/ui-snapshot-005.json",
|
||||
"sha256": "07cebb2a71ff0c63608f8a218a03618e9504fd171d8c7059b15bcf901dc5f8ec",
|
||||
"bytes": 51681
|
||||
},
|
||||
{
|
||||
"path": "artifacts/original-completion-2026-10-02/p24-02-native-os-controls-r05/ui-snapshot-006.json",
|
||||
"sha256": "07cebb2a71ff0c63608f8a218a03618e9504fd171d8c7059b15bcf901dc5f8ec",
|
||||
"bytes": 51681
|
||||
},
|
||||
{
|
||||
"path": "artifacts/original-completion-2026-10-02/p24-02-native-os-controls-r05/ui-snapshot-007.json",
|
||||
"sha256": "07cebb2a71ff0c63608f8a218a03618e9504fd171d8c7059b15bcf901dc5f8ec",
|
||||
"bytes": 51681
|
||||
},
|
||||
{
|
||||
"path": "artifacts/original-completion-2026-10-02/p24-02-native-os-controls-r05/frame-000.png",
|
||||
"sha256": "4516abb706e829094c19632e6c8005ad68877c7856af4ccfdf346e98b8dabe95",
|
||||
"bytes": 82965
|
||||
},
|
||||
{
|
||||
"path": "artifacts/original-completion-2026-10-02/p24-02-native-os-controls-r05/frame-001.png",
|
||||
"sha256": "9d61efee38fee61447a3ae10e95e07381f9560254388cc4ce38a79f7a0a21e6d",
|
||||
"bytes": 82953
|
||||
},
|
||||
{
|
||||
"path": "artifacts/original-completion-2026-10-02/p24-02-native-os-controls-r05/frame-002.png",
|
||||
"sha256": "4f53747098468b37bc23078d70d091a8b1d8c78ae44547476df70d40c153d03e",
|
||||
"bytes": 111921
|
||||
},
|
||||
{
|
||||
"path": "artifacts/original-completion-2026-10-02/p24-02-native-os-controls-r05/frame-003.png",
|
||||
"sha256": "dd60776d2370d79814e874a3944f7bce9152d6d3640bee434c624940f6e000e8",
|
||||
"bytes": 112437
|
||||
},
|
||||
{
|
||||
"path": "artifacts/original-completion-2026-10-02/p24-02-native-os-controls-r05/frame-004.png",
|
||||
"sha256": "e8c2b8027767cd26850f02a2d87d2e594bab4c3d6ebcc5f288ec6140f332146d",
|
||||
"bytes": 119749
|
||||
},
|
||||
{
|
||||
"path": "artifacts/original-completion-2026-10-02/p24-02-native-os-controls-r05/frame-005.png",
|
||||
"sha256": "7795cc8c2ee590c673f7bcd16d83e8fbfb85a8fef0af913282e9aa1df54e54c8",
|
||||
"bytes": 31302
|
||||
},
|
||||
{
|
||||
"path": "artifacts/original-completion-2026-10-02/p24-02-native-os-controls-r05/frame-006.png",
|
||||
"sha256": "7795cc8c2ee590c673f7bcd16d83e8fbfb85a8fef0af913282e9aa1df54e54c8",
|
||||
"bytes": 31302
|
||||
},
|
||||
{
|
||||
"path": "artifacts/original-completion-2026-10-02/p24-02-native-os-controls-r05/frame-007.png",
|
||||
"sha256": "0854ba41fd73e5b092d71e7d11e99fe3efb7b25ee04c2b0c8750b5d9de6d84b3",
|
||||
"bytes": 109431
|
||||
}
|
||||
]
|
||||
}
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
extends SceneTree
|
||||
var main: Control
|
||||
var observer: Node
|
||||
func _initialize() -> void:
|
||||
call_deferred("_start")
|
||||
func _start() -> void:
|
||||
var scene: PackedScene = load("res://scenes/main/main.tscn")
|
||||
main = scene.instantiate()
|
||||
root.add_child(main)
|
||||
observer = PassiveRecorder.new()
|
||||
observer.main = main
|
||||
observer.out_dir = OS.get_environment("P24_OS_OUTPUT")
|
||||
root.add_child(observer)
|
||||
root.title = "The Tree P24-02 OS candidate 9641ed5"
|
||||
|
||||
class PassiveRecorder extends Node:
|
||||
var main: Control
|
||||
var out_dir: String
|
||||
var log: FileAccess
|
||||
var previous: Dictionary = {}
|
||||
var elapsed := 0.0
|
||||
var rows := 0
|
||||
var runtime: Node
|
||||
var snapshot_count := 0
|
||||
var ui_count := 0
|
||||
var frame_count := 0
|
||||
var latest_restore_snapshot: Dictionary = {}
|
||||
func _ready() -> void:
|
||||
log = FileAccess.open(out_dir.path_join("events.jsonl"), FileAccess.WRITE)
|
||||
runtime = main.get_node("/root/SimulationRuntime")
|
||||
var menu: MenuButton = main.find_child("SaveLoadMenu", true, false)
|
||||
menu.get_popup().id_pressed.connect(_on_menu_item)
|
||||
runtime.snapshot_published.connect(_on_snapshot_published)
|
||||
runtime.save_operation_completed.connect(_on_save_completed)
|
||||
emit_record("started", {"pid": OS.get_process_id(), "platform": OS.get_name(), "candidate": "9641ed52def2ff8e5b0222449a4a83a1191e1d37", "source": "passive_root_normal_menu_observation_not_whole_acceptance"})
|
||||
func _on_menu_item(id: int) -> void:
|
||||
emit_record("actual_menu_item", {"id": id, "source": "production PopupMenu id_pressed; native input only"})
|
||||
_capture_ui("menu_%d" % id)
|
||||
func _capture_ui(reason: String) -> void:
|
||||
if ui_count >= 40:
|
||||
return
|
||||
var snapshot: Dictionary = runtime.create_snapshot()
|
||||
var data := var_to_bytes(snapshot)
|
||||
var name := "ui-snapshot-%03d.bin" % ui_count
|
||||
var file := FileAccess.open(out_dir.path_join(name), FileAccess.WRITE)
|
||||
file.store_buffer(data)
|
||||
file.close()
|
||||
var view: Node = main.get("world_preview")
|
||||
var definition: Variant = view.get("build_definition")
|
||||
emit_record("ui_model_capture", {"reason": reason, "filename": name, "sha256": _sha(data), "build_definition_id": str(definition.definition_id) if definition != null else "", "palette_open": bool(main.get("_build_palette_open")), "modal_blocked": bool(view.get("modal_input_blocked")), "save_path": str(main.get("manual_save_path"))})
|
||||
ui_count += 1
|
||||
_capture_frame.call_deferred(reason)
|
||||
func _capture_frame(reason: String) -> void:
|
||||
if frame_count >= 40:
|
||||
return
|
||||
await RenderingServer.frame_post_draw
|
||||
var dialog: Window = main.get("manual_save_slots_dialog")
|
||||
var target: Viewport = dialog if dialog != null and dialog.visible else get_tree().root
|
||||
var img := target.get_texture().get_image()
|
||||
if img == null or img.is_empty():
|
||||
emit_record("frame_capture_failed", {"reason": reason})
|
||||
return
|
||||
var name := "frame-%03d.png" % frame_count
|
||||
var error := img.save_png(out_dir.path_join(name))
|
||||
emit_record("frame_capture", {"reason": reason, "filename": name, "error": error, "sha256": _sha(FileAccess.get_file_as_bytes(out_dir.path_join(name))) if error == OK else "", "size": [img.get_width(), img.get_height()], "target": "dialog" if target == dialog else "root"})
|
||||
frame_count += 1
|
||||
func _sha(data: PackedByteArray) -> String:
|
||||
var context := HashingContext.new()
|
||||
context.start(HashingContext.HASH_SHA256)
|
||||
context.update(data)
|
||||
return context.finish().hex_encode()
|
||||
func _on_snapshot_published(_view: Dictionary, _digest: String) -> void:
|
||||
if snapshot_count >= 200:
|
||||
return
|
||||
latest_restore_snapshot = runtime.create_snapshot()
|
||||
var data := var_to_bytes(latest_restore_snapshot)
|
||||
var filename := "snapshot-%03d.bin" % snapshot_count
|
||||
var file := FileAccess.open(out_dir.path_join(filename), FileAccess.WRITE)
|
||||
file.store_buffer(data)
|
||||
file.close()
|
||||
emit_record("snapshot_published_capture", {"filename": filename, "sha256": _sha(data), "absolute_minute": latest_restore_snapshot[&"clock"][&"absolute_minute"], "observer_reads_only": true})
|
||||
snapshot_count += 1
|
||||
func _on_save_completed(result: Dictionary) -> void:
|
||||
var path: String = str(result.get(&"save_path", ""))
|
||||
var operation: String = str(result.get(&"operation", ""))
|
||||
var receipt := {"path": path, "operation": operation, "ok": bool(result.get(&"ok", false)), "code": str(result.get(&"code", "")), "observer_reads_only": true}
|
||||
if bool(result.get(&"ok", false)) and operation in ["load", "recovery", "recovery_candidate"]:
|
||||
var disk := SaveService.inspect_snapshot(path)
|
||||
var stored: Dictionary = disk.get(&"snapshot", {})
|
||||
var observed := var_to_bytes(latest_restore_snapshot)
|
||||
var expected := var_to_bytes(stored)
|
||||
receipt["disk_read_only_ok"] = bool(disk.get(&"ok", false))
|
||||
receipt["latest_published_full_snapshot_semantic_equal"] = latest_restore_snapshot == stored
|
||||
receipt["observed_full_snapshot_sha256"] = _sha(observed)
|
||||
receipt["stored_full_snapshot_sha256"] = _sha(expected)
|
||||
receipt["snapshot_index"] = snapshot_count - 1
|
||||
var file := FileAccess.open(out_dir.path_join("loaded-stored-snapshot.bin"), FileAccess.WRITE)
|
||||
file.store_buffer(expected)
|
||||
file.close()
|
||||
receipt["restore_safety_report"] = result.get(&"restore_safety_report", {})
|
||||
emit_record("save_operation_completed", receipt)
|
||||
func emit_record(kind: String, value: Dictionary) -> void:
|
||||
if rows >= 10000 or log == null:
|
||||
return
|
||||
var record := {"kind": kind, "pid": OS.get_process_id(), "ticks_msec": Time.get_ticks_msec(), "value": value}
|
||||
log.store_line(JSON.stringify(record))
|
||||
log.flush()
|
||||
rows += 1
|
||||
func _input(event: InputEvent) -> void:
|
||||
if event is InputEventKey:
|
||||
emit_record("key", {"keycode": event.keycode, "physical_keycode": event.physical_keycode, "unicode": event.unicode, "pressed": event.pressed, "echo": event.echo, "shift": event.shift_pressed, "ctrl": event.ctrl_pressed, "alt": event.alt_pressed, "meta": event.meta_pressed})
|
||||
elif event is InputEventMouseButton:
|
||||
emit_record("mouse_button", {"button": event.button_index, "pressed": event.pressed, "position": [event.position.x, event.position.y]})
|
||||
func _process(delta: float) -> void:
|
||||
elapsed += delta
|
||||
if elapsed < 0.1:
|
||||
return
|
||||
elapsed = 0.0
|
||||
var dialog: Variant = main.get("manual_save_slots_dialog")
|
||||
var label: Variant = dialog.get("_label_edit") if dialog != null else null
|
||||
var focus: Control = get_viewport().gui_get_focus_owner()
|
||||
var window: Window = get_tree().root
|
||||
var state := {"ime_text": DisplayServer.ime_get_text(), "ime_selection": [DisplayServer.ime_get_selection().x, DisplayServer.ime_get_selection().y], "label_text": String(label.text) if label != null else "", "label_rect": [label.get_global_rect().position.x, label.get_global_rect().position.y, label.size.x, label.size.y] if label != null else [], "label_focused": label.has_focus() if label != null else false, "dialog_visible": dialog.visible if dialog != null else false, "window_size": [window.size.x, window.size.y], "window_position": [window.position.x, window.position.y], "content_scale_factor": window.content_scale_factor, "screen_scale": DisplayServer.screen_get_scale(window.current_screen), "focus_name": String(focus.name) if focus != null else "", "save_path": String(main.get("manual_save_path")), "modal_input_blocked": bool(main.get("world_preview").get("modal_input_blocked"))}
|
||||
if state != previous:
|
||||
emit_record("state", state)
|
||||
if state.get("dialog_visible") != previous.get("dialog_visible"):
|
||||
_capture_ui("dialog_visibility_%s" % str(state.get("dialog_visible")))
|
||||
previous = state.duplicate(true)
|
||||
func _exit_tree() -> void:
|
||||
if log != null:
|
||||
emit_record("observer_exit", {"rows": rows})
|
||||
log.close()
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
extends SceneTree
|
||||
var main: Control
|
||||
var observer: Node
|
||||
func _initialize() -> void:
|
||||
call_deferred("_start")
|
||||
func _start() -> void:
|
||||
var scene: PackedScene = load("res://scenes/main/main.tscn")
|
||||
main = scene.instantiate()
|
||||
root.add_child(main)
|
||||
observer = PassiveRecorder.new()
|
||||
observer.main = main
|
||||
observer.out_dir = OS.get_environment("P24_OS_OUTPUT")
|
||||
root.add_child(observer)
|
||||
root.title = "The Tree P24-02 OS candidate 9641ed5"
|
||||
|
||||
class PassiveRecorder extends Node:
|
||||
var main: Control
|
||||
var out_dir: String
|
||||
var log: FileAccess
|
||||
var previous: Dictionary = {}
|
||||
var elapsed := 0.0
|
||||
var rows := 0
|
||||
var runtime: Node
|
||||
var snapshot_count := 0
|
||||
var ui_count := 0
|
||||
var frame_count := 0
|
||||
var latest_restore_snapshot: Dictionary = {}
|
||||
func _ready() -> void:
|
||||
log = FileAccess.open(out_dir.path_join("events.jsonl"), FileAccess.WRITE)
|
||||
runtime = main.get_node("/root/SimulationRuntime")
|
||||
var menu: MenuButton = main.find_child("SaveLoadMenu", true, false)
|
||||
menu.get_popup().id_pressed.connect(_on_menu_item)
|
||||
runtime.snapshot_published.connect(_on_snapshot_published)
|
||||
runtime.save_operation_completed.connect(_on_save_completed)
|
||||
emit_record("started", {"pid": OS.get_process_id(), "platform": OS.get_name(), "candidate": "9641ed52def2ff8e5b0222449a4a83a1191e1d37", "source": "passive_root_normal_menu_observation_not_whole_acceptance"})
|
||||
func _on_menu_item(id: int) -> void:
|
||||
emit_record("actual_menu_item", {"id": id, "source": "production PopupMenu id_pressed; native input only"})
|
||||
_capture_ui("menu_%d" % id)
|
||||
func _capture_ui(reason: String) -> void:
|
||||
if ui_count >= 40:
|
||||
return
|
||||
var snapshot: Dictionary = runtime.create_snapshot()
|
||||
var data := var_to_bytes(snapshot)
|
||||
var name := "ui-snapshot-%03d.bin" % ui_count
|
||||
var file := FileAccess.open(out_dir.path_join(name), FileAccess.WRITE)
|
||||
file.store_buffer(data)
|
||||
file.close()
|
||||
var json_name := "ui-snapshot-%03d.json" % ui_count
|
||||
var json_file := FileAccess.open(out_dir.path_join(json_name), FileAccess.WRITE)
|
||||
json_file.store_string(JSON.stringify(snapshot))
|
||||
json_file.close()
|
||||
var view: Node = main.get("world_preview")
|
||||
var definition: Variant = view.get("build_definition")
|
||||
emit_record("ui_model_capture", {"reason": reason, "filename": name, "sha256": _sha(data), "json_filename": json_name, "json_sha256": _sha(FileAccess.get_file_as_bytes(out_dir.path_join(json_name))), "status_text": str(main.get("build_status_label").text), "build_definition_id": str(definition.id) if definition != null else "", "palette_open": bool(main.get("_build_palette_open")), "modal_blocked": bool(view.get("modal_input_blocked")), "save_path": str(main.get("manual_save_path"))})
|
||||
ui_count += 1
|
||||
_capture_frame.call_deferred(reason)
|
||||
func _capture_frame(reason: String) -> void:
|
||||
if frame_count >= 40:
|
||||
return
|
||||
await RenderingServer.frame_post_draw
|
||||
var dialog: Window = main.get("manual_save_slots_dialog")
|
||||
var target: Viewport = dialog if dialog != null and dialog.visible else get_tree().root
|
||||
var img := target.get_texture().get_image()
|
||||
if img == null or img.is_empty():
|
||||
emit_record("frame_capture_failed", {"reason": reason})
|
||||
return
|
||||
var name := "frame-%03d.png" % frame_count
|
||||
var error := img.save_png(out_dir.path_join(name))
|
||||
emit_record("frame_capture", {"reason": reason, "filename": name, "error": error, "sha256": _sha(FileAccess.get_file_as_bytes(out_dir.path_join(name))) if error == OK else "", "size": [img.get_width(), img.get_height()], "target": "dialog" if target == dialog else "root"})
|
||||
frame_count += 1
|
||||
func _sha(data: PackedByteArray) -> String:
|
||||
var context := HashingContext.new()
|
||||
context.start(HashingContext.HASH_SHA256)
|
||||
context.update(data)
|
||||
return context.finish().hex_encode()
|
||||
func _on_snapshot_published(_view: Dictionary, _digest: String) -> void:
|
||||
if snapshot_count >= 200:
|
||||
return
|
||||
latest_restore_snapshot = runtime.create_snapshot()
|
||||
var data := var_to_bytes(latest_restore_snapshot)
|
||||
var filename := "snapshot-%03d.bin" % snapshot_count
|
||||
var file := FileAccess.open(out_dir.path_join(filename), FileAccess.WRITE)
|
||||
file.store_buffer(data)
|
||||
file.close()
|
||||
emit_record("snapshot_published_capture", {"filename": filename, "sha256": _sha(data), "absolute_minute": latest_restore_snapshot[&"clock"][&"absolute_minute"], "observer_reads_only": true})
|
||||
snapshot_count += 1
|
||||
func _on_save_completed(result: Dictionary) -> void:
|
||||
var path: String = str(result.get(&"save_path", ""))
|
||||
var operation: String = str(result.get(&"operation", ""))
|
||||
var receipt := {"path": path, "operation": operation, "ok": bool(result.get(&"ok", false)), "code": str(result.get(&"code", "")), "observer_reads_only": true}
|
||||
if bool(result.get(&"ok", false)) and operation in ["load", "recovery", "recovery_candidate"]:
|
||||
var disk := SaveService.inspect_snapshot(path)
|
||||
var stored: Dictionary = disk.get(&"snapshot", {})
|
||||
var observed := var_to_bytes(latest_restore_snapshot)
|
||||
var expected := var_to_bytes(stored)
|
||||
receipt["disk_read_only_ok"] = bool(disk.get(&"ok", false))
|
||||
receipt["latest_published_full_snapshot_semantic_equal"] = latest_restore_snapshot == stored
|
||||
receipt["observed_full_snapshot_sha256"] = _sha(observed)
|
||||
receipt["stored_full_snapshot_sha256"] = _sha(expected)
|
||||
receipt["snapshot_index"] = snapshot_count - 1
|
||||
var file := FileAccess.open(out_dir.path_join("loaded-stored-snapshot.bin"), FileAccess.WRITE)
|
||||
file.store_buffer(expected)
|
||||
file.close()
|
||||
receipt["restore_safety_report"] = result.get(&"restore_safety_report", {})
|
||||
emit_record("save_operation_completed", receipt)
|
||||
func emit_record(kind: String, value: Dictionary) -> void:
|
||||
if rows >= 10000 or log == null:
|
||||
return
|
||||
var record := {"kind": kind, "pid": OS.get_process_id(), "ticks_msec": Time.get_ticks_msec(), "value": value}
|
||||
log.store_line(JSON.stringify(record))
|
||||
log.flush()
|
||||
rows += 1
|
||||
func _input(event: InputEvent) -> void:
|
||||
if event is InputEventKey:
|
||||
emit_record("key", {"keycode": event.keycode, "physical_keycode": event.physical_keycode, "unicode": event.unicode, "pressed": event.pressed, "echo": event.echo, "shift": event.shift_pressed, "ctrl": event.ctrl_pressed, "alt": event.alt_pressed, "meta": event.meta_pressed})
|
||||
elif event is InputEventMouseButton:
|
||||
if event.pressed:
|
||||
_capture_ui.call_deferred("native_mouse_after_dispatch")
|
||||
emit_record("mouse_button", {"button": event.button_index, "pressed": event.pressed, "position": [event.position.x, event.position.y]})
|
||||
func _process(delta: float) -> void:
|
||||
elapsed += delta
|
||||
if elapsed < 0.1:
|
||||
return
|
||||
elapsed = 0.0
|
||||
var dialog: Variant = main.get("manual_save_slots_dialog")
|
||||
var label: Variant = dialog.get("_label_edit") if dialog != null else null
|
||||
var focus: Control = get_viewport().gui_get_focus_owner()
|
||||
var window: Window = get_tree().root
|
||||
var state := {"ime_text": DisplayServer.ime_get_text(), "ime_selection": [DisplayServer.ime_get_selection().x, DisplayServer.ime_get_selection().y], "label_text": String(label.text) if label != null else "", "label_rect": [label.get_global_rect().position.x, label.get_global_rect().position.y, label.size.x, label.size.y] if label != null else [], "label_focused": label.has_focus() if label != null else false, "dialog_visible": dialog.visible if dialog != null else false, "window_size": [window.size.x, window.size.y], "window_position": [window.position.x, window.position.y], "content_scale_factor": window.content_scale_factor, "screen_scale": DisplayServer.screen_get_scale(window.current_screen), "focus_name": String(focus.name) if focus != null else "", "save_path": String(main.get("manual_save_path")), "modal_input_blocked": bool(main.get("world_preview").get("modal_input_blocked"))}
|
||||
if state != previous:
|
||||
emit_record("state", state)
|
||||
if state.get("dialog_visible") != previous.get("dialog_visible"):
|
||||
_capture_ui("dialog_visibility_%s" % str(state.get("dialog_visible")))
|
||||
previous = state.duplicate(true)
|
||||
func _exit_tree() -> void:
|
||||
if log != null:
|
||||
emit_record("observer_exit", {"rows": rows})
|
||||
log.close()
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
import os,sys,uuid,json,hashlib,importlib.util,subprocess,time
|
||||
from pathlib import Path
|
||||
sys.dont_write_bytecode=True
|
||||
R=Path('/Users/korizatou114/Projects/TheTree-managed-worktrees/p24-02-operations/P24-02-implement')
|
||||
A=Path('/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02')
|
||||
OUT=A/'p24-02-native-os-controls-r04';stage=A/'p24-02-local-native-preflight-r06/stage'
|
||||
s=importlib.util.spec_from_file_location('p24_os_runner',R/'tools/run_all_tests.py');r=importlib.util.module_from_spec(s);s.loader.exec_module(r)
|
||||
outer=r.module('p24_os_owned',R/'tools/regression/owned_outer.py');r.require(not outer.native.helper['live_engines'](),'external engine present')
|
||||
r.require(r.read(stage.parent/'local-ended.json')['passed'],'affected local3 passed before OS')
|
||||
r.require(subprocess.check_output(['git','rev-parse','HEAD'],cwd=R,text=True).strip()=='9641ed52def2ff8e5b0222449a4a83a1191e1d37','exact immutable candidate')
|
||||
r.require(not subprocess.check_output(['git','status','--porcelain'],cwd=R,text=True),'candidate clean')
|
||||
refs=r.source_refs(R);before=r.inventory(stage,stage=True);protected=r.default_player(R);public=(stage/'project.godot').read_bytes()
|
||||
for n,pin in refs.items():r.require(r.sha(stage/n)==pin['sha256'],'tested stage source exact '+n)
|
||||
nonce=uuid.uuid4().hex;profile_name='TheTree-PCK-tests-'+nonce+'-p24-02-os';profile=r.profile_path(profile_name);r.require(not profile.exists(),'fresh private profile');profile.mkdir()
|
||||
r.require(__import__('shutil').disk_usage(OUT).free>=500*1024*1024,'disk admission')
|
||||
base={'candidate':'9641ed52def2ff8e5b0222449a4a83a1191e1d37','source_map':{n:v['sha256'] for n,v in refs.items()},'stage':str(stage),'profile':str(profile),'owner_pid':os.getpid(),'default_before':protected,'source_before':refs,'formal_acceptance':False,'no_injected_gameplay_or_input':True,'controller_sha256':r.sha(Path(__file__)),'recorder_sha256':r.sha(OUT/'passive_os.gd')}
|
||||
r.write(OUT/'started.json',base);error=None;children=[];rows=[]
|
||||
try:
|
||||
(stage/'project.godot').write_bytes(r.private_project(public,profile_name));env=r.fresh_environment(dict(os.environ));env['P24_OS_OUTPUT']=str(OUT)
|
||||
argv=['/Applications/Godot.app/Contents/MacOS/Godot','--path',str(stage),'--script',str(OUT/'passive_os.gd')]
|
||||
with (OUT/'engine-native.log').open('w') as log:
|
||||
p=subprocess.Popen(argv,cwd=stage,env=env,stdout=log,stderr=subprocess.STDOUT);children.append(p)
|
||||
r.write(OUT/'process-started.json',dict(base,actual_pid=p.pid,command=argv,monotonic_ns=time.monotonic_ns()))
|
||||
print(json.dumps({'actual_pid':p.pid,'profile':str(profile),'events':str(OUT/'events.jsonl')}),flush=True)
|
||||
p.wait(timeout=900)
|
||||
r.require(p.returncode==0,'ordinary native exit0');raw=(OUT/'engine-native.log').read_text();r.require('ERROR:' not in raw and 'SCRIPT ERROR:' not in raw,'native diagnostics failed')
|
||||
rows.append({'actual_pid':p.pid,'exit_code':p.returncode,'engine_ended':True,'log_sha256':r.sha(OUT/'engine-native.log')})
|
||||
except BaseException as e:error=type(e).__name__+': '+str(e)
|
||||
finally:
|
||||
cleanup,cleanup_errors=outer.finish_captured(children);(stage/'project.godot').write_bytes(public)
|
||||
guards=[]
|
||||
try:
|
||||
r.require(r.source_refs(R)==refs,'candidate whole source unchanged');r.require(r.inventory(stage,stage=True)==before,'whole stage source unchanged');r.require(r.default_player(R)==protected,'default player unchanged')
|
||||
except BaseException as e:guards.append(type(e).__name__+': '+str(e))
|
||||
r.write(OUT/'ended.json',dict(base,rows=rows,error=error,guard_errors=guards,cleanup_errors=cleanup_errors,owned_cleanup=cleanup,passed=not(error or guards or cleanup_errors) and len(rows)==1,formal_acceptance=False))
|
||||
print(json.dumps({'ended':True,'error':error,'guards':guards,'rows':rows}),flush=True)
|
||||
sys.exit(1 if error or guards or cleanup_errors else 0)
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
import os,sys,uuid,json,hashlib,importlib.util,subprocess,time
|
||||
from pathlib import Path
|
||||
sys.dont_write_bytecode=True
|
||||
R=Path('/Users/korizatou114/Projects/TheTree-managed-worktrees/p24-02-operations/P24-02-implement')
|
||||
A=Path('/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02')
|
||||
OUT=A/'p24-02-native-os-controls-r05';stage=A/'p24-02-local-native-preflight-r06/stage'
|
||||
s=importlib.util.spec_from_file_location('p24_os_runner',R/'tools/run_all_tests.py');r=importlib.util.module_from_spec(s);s.loader.exec_module(r)
|
||||
outer=r.module('p24_os_owned',R/'tools/regression/owned_outer.py');r.require(not outer.native.helper['live_engines'](),'external engine present')
|
||||
r.require(r.read(stage.parent/'local-ended.json')['passed'],'affected local3 passed before OS')
|
||||
r.require(subprocess.check_output(['git','rev-parse','HEAD'],cwd=R,text=True).strip()=='9641ed52def2ff8e5b0222449a4a83a1191e1d37','exact immutable candidate')
|
||||
r.require(not subprocess.check_output(['git','status','--porcelain'],cwd=R,text=True),'candidate clean')
|
||||
refs=r.source_refs(R);before=r.inventory(stage,stage=True);protected=r.default_player(R);public=(stage/'project.godot').read_bytes()
|
||||
for n,pin in refs.items():r.require(r.sha(stage/n)==pin['sha256'],'tested stage source exact '+n)
|
||||
nonce=uuid.uuid4().hex;profile_name='TheTree-PCK-tests-'+nonce+'-p24-02-os';profile=r.profile_path(profile_name);r.require(not profile.exists(),'fresh private profile');profile.mkdir()
|
||||
r.require(__import__('shutil').disk_usage(OUT).free>=500*1024*1024,'disk admission')
|
||||
base={'candidate':'9641ed52def2ff8e5b0222449a4a83a1191e1d37','source_map':{n:v['sha256'] for n,v in refs.items()},'stage':str(stage),'profile':str(profile),'owner_pid':os.getpid(),'default_before':protected,'source_before':refs,'formal_acceptance':False,'no_injected_gameplay_or_input':True,'controller_sha256':r.sha(Path(__file__)),'recorder_sha256':r.sha(OUT/'passive_os.gd')}
|
||||
r.write(OUT/'started.json',base);error=None;children=[];rows=[]
|
||||
try:
|
||||
(stage/'project.godot').write_bytes(r.private_project(public,profile_name));env=r.fresh_environment(dict(os.environ));env['P24_OS_OUTPUT']=str(OUT)
|
||||
argv=['/Applications/Godot.app/Contents/MacOS/Godot','--path',str(stage),'--script',str(OUT/'passive_os.gd')]
|
||||
with (OUT/'engine-native.log').open('w') as log:
|
||||
p=subprocess.Popen(argv,cwd=stage,env=env,stdout=log,stderr=subprocess.STDOUT);children.append(p)
|
||||
r.write(OUT/'process-started.json',dict(base,actual_pid=p.pid,command=argv,monotonic_ns=time.monotonic_ns()))
|
||||
print(json.dumps({'actual_pid':p.pid,'profile':str(profile),'events':str(OUT/'events.jsonl')}),flush=True)
|
||||
p.wait(timeout=900)
|
||||
r.require(p.returncode==0,'ordinary native exit0');raw=(OUT/'engine-native.log').read_text();r.require('ERROR:' not in raw and 'SCRIPT ERROR:' not in raw,'native diagnostics failed')
|
||||
rows.append({'actual_pid':p.pid,'exit_code':p.returncode,'engine_ended':True,'log_sha256':r.sha(OUT/'engine-native.log')})
|
||||
except BaseException as e:error=type(e).__name__+': '+str(e)
|
||||
finally:
|
||||
cleanup,cleanup_errors=outer.finish_captured(children);(stage/'project.godot').write_bytes(public)
|
||||
guards=[]
|
||||
try:
|
||||
r.require(r.source_refs(R)==refs,'candidate whole source unchanged');r.require(r.inventory(stage,stage=True)==before,'whole stage source unchanged');r.require(r.default_player(R)==protected,'default player unchanged')
|
||||
except BaseException as e:guards.append(type(e).__name__+': '+str(e))
|
||||
r.write(OUT/'ended.json',dict(base,rows=rows,error=error,guard_errors=guards,cleanup_errors=cleanup_errors,owned_cleanup=cleanup,passed=not(error or guards or cleanup_errors) and len(rows)==1,formal_acceptance=False))
|
||||
print(json.dumps({'ended':True,'error':error,'guards':guards,'rows':rows}),flush=True)
|
||||
sys.exit(1 if error or guards or cleanup_errors else 0)
|
||||
Reference in New Issue
Block a user