Record P28-02 EQ S1 evidence and S2 continuation
This commit is contained in:
+1
@@ -0,0 +1 @@
|
||||
{"action":"run","task_id":"P28-02-EQ","reason":"Use only after Root verifies through the normal gates: repair_ready, repairs 4, no S submitted, no active run, and the S1 files still present unchanged in the W. Run repair 4 of P28-02-EQ once on the same W from base 2549cf7d6992560b850bbd11934e3c14b39a1988 with the single worker codex gpt-6-astra, doing only stage S2 of EQ_STAGED_IMPLEMENTATION_PLAN r01 and r02. Start by reading eq/PROGRESS.md and eq/IMPLEMENTATION.md, and reuse the internal types, paths, record schema and API recorded there and in compare_versions.py without redesign. Do not delete or rewrite S1 code, except for fixes a failing test requires. Keep the S1 unit failure history in PROGRESS.md and UNIT_OUTPUT. S2 scope: (1) eq_probe.gd startup per the six-stage lifecycle reused from DIAG; (2) the r02 A1 typed tree encode/decode; (3) the A2 Godot roundtrip proof recording raw_bytes_sha, tree_sha and roundtrip_ok per checkpoint; (4) A3 export of the full B1 tree and exact per-tick diff operations for S and latest_snapshot to private user:// evidence/; (5) the B event record, with to_dictionary trees, original_field_types, start counter and published_ids count; (6) binding of the profile root to the guard actual_user_data_dir, with the value read live and never assumed; and (7) the single-line P28_02_EQ_REPORT plus close_requested.emit(), with the report fields matching what compare_versions.compare_reports already consumes. Also add the check_eq.py format, contradiction and static probe checks: no autoload class_name reference, no state-changing call outside the allowed preparation and stepping, no := inference from a Variant, textual StringName ordering, no SimulationDigest-only judgment. Add synthetic tests for these to test_eq.py. The E3/E4/E5 scenarios are S3 and must not be started now. Run the engine-free python3 test_eq.py until every existing test passes, save the raw output, update PROGRESS.md, and end S2 with formal status blocked and the finding 'stage S2 complete (not a failure; next is S3)'. Do not submit. Deliver as the one supplementary key the full texts of both plans and this decision; clarifications r01, r02 and r03 stay read-only in build/eq-staged-readonly-r04 with path and SHA. No engine, no git write or commit, no product change, no full regression; SPEC, TASK, eq/references and eq/registration stay unchanged. Ordinary implementation choices are recorded without stopping; block only for undecided matters affecting original product spec, values, permissions, billing or original acceptance. After S3 and S4, Root runs native on the frozen S_eq in 7 phases and builds the bundle; then both validations are mandatory, followed by a fresh independent Opus review of all 6 conditions and the normal integration and final. No original credit (23/88, 4/30). Quota fallback only on structured provider quota, once, same role, Antigravity claude-opus-5-5-high; any other failure is blocked. Decided by Claude Opus 5.5 in the Desktop control session (message 324); not a CLI commander result."}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"action":"run","task_id":"P28-02-EQ","reason":"Supersedes DESKTOP_EQ_STAGED_RUN_DECISION.json, which is kept unchanged as history. The request-repair decision DESKTOP_EQ_STAGED_REPAIR_DECISION.json stays valid as written. Use only after Root verifies through the normal gates: repair_ready, repairs 3, no S submitted, and no active run. Run repair 3 of P28-02-EQ once on the same W from base 2549cf7d6992560b850bbd11934e3c14b39a1988 with the single worker codex gpt-6-astra, doing only stage S1. Follow EQ_STAGED_IMPLEMENTATION_PLAN.txt (process G1-G6 and stages S1-S4) as replaced in part by EQ_STAGED_IMPLEMENTATION_PLAN_R02.txt. R02 fixes the typed tree transport: every node is [typeof, payload]; floats as IEEE754 hex; dictionaries in insertion order with typed info; typed arrays with typed info; String and StringName distinct. The probe will prove the transport lossless in Godot by an encode/decode roundtrip with matching var_to_bytes and record raw_bytes_sha, tree_sha and roundtrip_ok per checkpoint; Python recomputes tree_sha. The full B1 tree plus exact per-tick path diff operations reconstruct every checkpoint of S and latest_snapshot with no depth limit. E2 events are carried as typed trees of the product to_dictionary output plus original field types. Comparison is exact typed tree equality first, then a textual-key fallback that records every dict-order-only path. normalize_events and normalize_tree return exactly (normalized, sidecar), where sidecar has the fixed keys entries, violations and profile_root. Violations outside the r03 closed list are kept unnormalized and do not fail by mere existence; trying to normalize them is rejected, and a real cross-side difference in them is a failure. S1 implements compare_versions.py (comparison, the four normalize/restore functions, diff reconstruction, tree_sha recomputation, check_source_closure) with synthetic-tree tests in test_eq.py, plus PROGRESS.md and IMPLEMENTATION.md. Never delete created files. Run the engine-free python3 test_eq.py until every existing test passes, save the raw output to UNIT_OUTPUT.txt, and end S1 with formal status blocked and the finding 'stage S1 complete (not a failure; next is S2)'; only S4 submits. Deliver as the one supplementary key the full texts of both plans and this decision; clarifications r01, r02 and r03 are placed read-only in build/ with path and SHA, and eq/references are read from the W. No engine, no git write or commit, no product change, no full regression; SPEC, TASK, eq/references and eq/registration stay unchanged. Ordinary implementation choices are recorded without stopping; block only for undecided matters affecting original product spec, values, permissions, billing or original acceptance. After S4, Root runs native on the frozen S_eq in 7 phases and builds the bundle; then both validations are mandatory, followed by a fresh independent Opus review and the normal integration and final. All 6 conditions are kept; no original credit (23/88, 4/30). Quota fallback only on structured provider quota, once, same role, Antigravity claude-opus-5-5-high; any other failure is blocked. Decided by Claude Opus 5.5 in the Desktop control session (message 320); not a CLI commander result."}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
EQ_ENVIRONMENT_FIELDS_CLARIFICATION r03(P28-02-EQ repair 2。base 2549cf7d6992560b850bbd11934e3c14b39a1988。EQ_S_TIMING_CLARIFICATION r01 と r02 の全文は、そのまま有効で、書き換えない。r02 の T1(閉じた対象)を、ここで閉じた一覧の F1〜F3 に広げて確定する。SPEC、TASK、6条件、eq/references、eq/registration、製品、原本の 30/88、権限、課金は変更しない)
|
||||
|
||||
範囲(静的に一括して点検したもの)
|
||||
- Runtime: restore_snapshot(:587)、load_from_path(:4223)→ _finish_load_operation(:4683-4733)→ _complete_save_operation(:4734)→ _save_event_payload(:4745-4768)→ _publish_actor_event → domain_events(S の systems.runtime.domain_events.recent_events、E2 の記録)。
|
||||
- SimulationSnapshot.validate。
|
||||
- SaveService: save_snapshot(:29)、load_snapshot(:49)、_resolve_safe_save_path(:1684-1706)、_load_snapshot_absolute_v1(:946-1042)、_write_package_directory の manifest(:901-917)、_complete_timed_operation(:1751-1761)、_failure(:1956)。
|
||||
|
||||
根拠表(源泉 → 返却 → payload → S/E2)
|
||||
|
||||
| 欄 | 源泉 | S/E2 に入るか | 決定性 | 扱い |
|
||||
|---|---|---|---|---|
|
||||
| duration_us | SaveService._complete_timed_operation(:1756-1760) | 入る(payload.duration_us) | 実時間 | F1 |
|
||||
| runtime_duration_us | Runtime._finish_load_operation(:4717) | 入る(payload.runtime_duration_us) | 実時間 | F2 |
|
||||
| message(失敗の場合) | SaveService._failure(code, message)。target_path・world_path・manifest_path(:957、:963、:1011 ほか)と、"symbolic link at package read boundary: %s" などに、_resolve_safe_save_path が globalize した private profile の絶対 path が入る | 入る(payload.message) | PID ごとに profile の root が違う | F3 |
|
||||
| message(その他) | error_string(...)、検証の errors の結合、format_version の文言、Runtime の RESTORE_FAILED の message(= 渡した save_path) | 入る | 決定的(path を固定すれば) | 正規化しない |
|
||||
| save_path | Runtime の _with_operation_context の save_path(渡した user:// の文字列) | 入る | 決定的(下の D1) | 正規化しない |
|
||||
| save_id | manifest の save_id = metadata.save_id か logical_name(:905) | 入る(load の成功の場合) | 決定的(下の D1・D2) | 正規化しない |
|
||||
| saved_absolute_minute | manifest の absolute_minute | 入る | 決定的 | 正規化しない |
|
||||
| ok、code、operation、reason、request_id、checkpoint_absolute_minute、loaded_clock_paused、preload_pause_restored | Runtime と SaveService の戻り値 | 入る(一部は payload の外の result だけ) | 決定的 | 正規化しない |
|
||||
| created_at_real、updated_at_real | manifest の now = Time.get_datetime_string_from_system(:901、:907-908) | **入らない**(_save_event_payload は manifest から save_id と absolute_minute だけを取る) | 実時刻 | S/E2 の比較の対象外。package のファイルの記録として保持する |
|
||||
| manifest の他の欄、thumbnail、journal | package のファイル | 入らない | — | S/E2 の比較の対象外。E3 の改ざんのファイルとして SHA を記録する |
|
||||
| SaveService._performance_budget | 静的な診断 | 入らない(S/K/C の外。DIAG の low の注記) | 実時間 | PID ごとの前後の値を記録し、比べない |
|
||||
| latest_save_operation_result | Runtime の変数 | 入らない(create_snapshot の外) | F1〜F3 を含む | 同じ PID の中で payload との一致を確かめる |
|
||||
|
||||
閉じた一覧(r02 の T1 を置き換える。これ以外は正規化しない)
|
||||
- 対象の event: source_service が "save_service" で、event_type が9種(SAVE_CHECKPOINT_SUCCEEDED、SAVE_CHECKPOINT_FAILED、SAVE_LOADED、SAVE_LOAD_FAILED、SAVE_MIGRATION_SUCCEEDED、SAVE_MIGRATION_FAILED、SAVE_RECOVERY_LOADED、SAVE_RECOVERY_CANDIDATE_LOADED、SAVE_RECOVERY_FAILED)のいずれか。その payload の中だけ。
|
||||
- F1 duration_us、F2 runtime_duration_us: r02 の T2 のとおり、typed の marker に置き換えて、sidecar に値を記録する。
|
||||
- F3 message(文字列)の中の、private profile の絶対 root:
|
||||
- root は、その PID の ProjectSettings.globalize_path("user://").simplify_path() の値。これが、その PID の guard の receipt の actual_user_data_dir と一致することを確かめる。一致しなければ失敗にする。
|
||||
- message の中の、その root の文字列(末尾の "/" を含む prefix として現れる箇所すべて)を、固定の token "{PRIVATE_USER_ROOT}/" に置き換える。元の message の全体を、sidecar に記録する。
|
||||
- 逆の復元: token をその PID の root に戻すと、元の message と完全一致すること。
|
||||
- 置き換えた後の message は、PID の間・版の間で完全一致すること。
|
||||
- root 以外の部分(相対 path、code、文言)は、変更しない。
|
||||
|
||||
決定性の前提(harness の側で守ること。製品は変えない)
|
||||
- D1: E3/E4/E5 が使う user:// の path は、全て固定の相対名にする(例: user://p28_eq/r/good、user://p28_eq/r/tampered_world)。uuid、時刻、PID、乱数を名前に入れない。
|
||||
- D2: save に渡す metadata は、固定の値か空にする(save_id、display_name、created_at_real を時刻や乱数から作らない)。
|
||||
- D3: 改ざんの方法は、固定の規則にする(RESTART と同じく、world.bin の offset len//2 の1バイトを XOR 0x01)。
|
||||
|
||||
検査と試験
|
||||
- 同じ PID の中: F1〜F3 の正規化の前後で可逆であること。正規化の対象が、閉じた一覧の中だけであること。
|
||||
- PID の間と版の間: 正規化の後の S、latest_snapshot、E2 の全イベントが完全一致すること。F1・F2 の値と、F3 の元の root は比べない(理由と各側の実際の値を記録する)。
|
||||
- 閉じた一覧の外で PID の間に差があった場合は、正規化を広げない。失敗として、その path・型・両側の値を全て記録し、判断に戻す(native の実測で初めて分かる場合も、同じ扱い)。
|
||||
- 試験(test_eq.py)を加える:
|
||||
- F3 の正常(root の置き換えと復元)
|
||||
- root が guard の actual_user_data_dir と一致しない場合の拒否
|
||||
- root 以外の部分を置き換える場合の拒否
|
||||
- 閉じた一覧の外の欄や event の正規化の拒否
|
||||
- D1 の違反(uuid や時刻を使った path)の拒否
|
||||
- manifest の時刻を S の比較に入れる場合の拒否
|
||||
- 復元できない sidecar の拒否
|
||||
- 製品の状態、RNG、ID の counter、意味のある値は、正規化しない。
|
||||
|
||||
worker への手順
|
||||
- 前回までは実装0なので、SPEC・TASK・r01・r02・この r03 に従い、eq/** に6ファイルを実装する。SPEC、TASK、eq/registration、eq/references は変更しない。
|
||||
- 静的に分かる環境由来の差は、この表で閉じている。新しい欄に気づいた場合も、短く止めずに、上の「閉じた一覧の外」の規則(失敗として記録して判断に戻す)を harness に実装して進める。blocked にしてよいのは、原本の仕様・値・権限・課金・受入に影響する未確定事項がある場合だけ。
|
||||
- engine を使わない test_eq.py の全件 PASS を局所で確かめ、生出力を報告し、正式な JSON で提出する。engine の起動、git への書込み、製品の変更、全回帰はしない。
|
||||
+329
@@ -0,0 +1,329 @@
|
||||
{
|
||||
"at_jst": "2026-10-21T08:11:37.415587+09:00",
|
||||
"plan_id": "P28-02",
|
||||
"support_project": "the-tree-p28-02-eq",
|
||||
"support_task": "P28-02-EQ",
|
||||
"base": "2549cf7d6992560b850bbd11934e3c14b39a1988",
|
||||
"actual_run": "3325e7da9d064d2792fd178f400bc492",
|
||||
"actual_PID": 6380,
|
||||
"PID_ended": true,
|
||||
"stage": "S1 local readiness only",
|
||||
"retained_stage_return": {
|
||||
"path": "artifacts/original-completion-2026-10-02/p28-02-root-control-r01/retained-s1-3325e7d-r01/RETURN.json",
|
||||
"bytes": 19341,
|
||||
"sha256": "6d39676231b899c8e82bbe2643f14ee99d1605b2ced71cb249218ff99ddaf03f"
|
||||
},
|
||||
"root_raw_unit_join": {
|
||||
"path": "artifacts/original-completion-2026-10-02/p28-02-root-control-r01/ROOT_S1_LOCAL_JOIN_3325E7D.json",
|
||||
"bytes": 779,
|
||||
"sha256": "ed4c2d0e3d84d22b85e1377ebc19a238a6bb2b4f4f2ff99c9ea4440aa0f9256f"
|
||||
},
|
||||
"local_unit": {
|
||||
"at_jst": "2026-10-21T08:08:55.750391+09:00",
|
||||
"stage": "S1",
|
||||
"actual_run": "3325e7da9d064d2792fd178f400bc492",
|
||||
"same_base": "2549cf7d6992560b850bbd11934e3c14b39a1988",
|
||||
"retained_return_sha256": "6d39676231b899c8e82bbe2643f14ee99d1605b2ced71cb249218ff99ddaf03f",
|
||||
"unit_output_sha256": "cdca0cdd551ce76c6100c4dd90e04559551f9d88c054a19a2bc6a77e6572ae15",
|
||||
"executed_unit_exit_codes": [
|
||||
1,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"final_unit_checks": 43,
|
||||
"original_failed_unit_preserved": true,
|
||||
"all_changes_in_allowed_scope": true,
|
||||
"all_tracked_source_unchanged": true,
|
||||
"formal_EQ_accepted": false,
|
||||
"all6_acceptance_pending": true,
|
||||
"original_credit": 0,
|
||||
"scope": "Local S1 readiness evidence only; no test rerun, no engine, no formal independent review substituted."
|
||||
},
|
||||
"actual_Opus_materials": [
|
||||
{
|
||||
"path": "docs/plans/original-completion-2026-10-02/execution/p28-02/EQ_ENVIRONMENT_FIELDS_CLARIFICATION_R03.txt",
|
||||
"bytes": 7637,
|
||||
"sha256": "12b27f984ef5843d98327200ad261dccaf64968402192b08ad55b15ed5454ea2"
|
||||
},
|
||||
{
|
||||
"path": "docs/plans/original-completion-2026-10-02/execution/p28-02/EQ_STAGED_IMPLEMENTATION_PLAN.txt",
|
||||
"bytes": 6779,
|
||||
"sha256": "eb7b4831e2164c6fc983fa6f9825e7f3e2993b4c0ebf2f90aac8ad10662666d2"
|
||||
},
|
||||
{
|
||||
"path": "docs/plans/original-completion-2026-10-02/execution/p28-02/EQ_STAGED_IMPLEMENTATION_PLAN_R02.txt",
|
||||
"bytes": 7768,
|
||||
"sha256": "128f42f18e168e9299995296ac7ad119f47d1647799d472663282e47e8ac9fdd"
|
||||
},
|
||||
{
|
||||
"path": "docs/plans/original-completion-2026-10-02/execution/p28-02/DESKTOP_EQ_STAGED_RUN_DECISION_R02.json",
|
||||
"bytes": 3238,
|
||||
"sha256": "12b3b425638946920fa04867ba67d7a78c4e948ffba130c43bab55014b1989dc"
|
||||
}
|
||||
],
|
||||
"source_files": [
|
||||
{
|
||||
"relative": "IMPLEMENTATION.md",
|
||||
"source": {
|
||||
"path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/IMPLEMENTATION.md",
|
||||
"bytes": 9822,
|
||||
"sha256": "1bb87ce220648545ffd3bb72b0fc5d47ed83031c896946bb2a93d858c629b3da"
|
||||
},
|
||||
"retained": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p28-02-root-control-r01/retained-s1-3325e7d-r01/eq/IMPLEMENTATION.md",
|
||||
"bytes": 9822,
|
||||
"sha256": "1bb87ce220648545ffd3bb72b0fc5d47ed83031c896946bb2a93d858c629b3da"
|
||||
}
|
||||
},
|
||||
{
|
||||
"relative": "PROGRESS.md",
|
||||
"source": {
|
||||
"path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/PROGRESS.md",
|
||||
"bytes": 2210,
|
||||
"sha256": "aeb0d96bb909bdff2130b0ef0985bc691e9ddab76ea528b7b2ba05ff3e694e3d"
|
||||
},
|
||||
"retained": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p28-02-root-control-r01/retained-s1-3325e7d-r01/eq/PROGRESS.md",
|
||||
"bytes": 2210,
|
||||
"sha256": "aeb0d96bb909bdff2130b0ef0985bc691e9ddab76ea528b7b2ba05ff3e694e3d"
|
||||
}
|
||||
},
|
||||
{
|
||||
"relative": "SPEC.md",
|
||||
"source": {
|
||||
"path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/SPEC.md",
|
||||
"bytes": 10693,
|
||||
"sha256": "3791ccdcb87e8d71fe9205e1e692ebca9e0f974ea3b5fbc4fbb3943882131f1c"
|
||||
},
|
||||
"retained": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p28-02-root-control-r01/retained-s1-3325e7d-r01/eq/SPEC.md",
|
||||
"bytes": 10693,
|
||||
"sha256": "3791ccdcb87e8d71fe9205e1e692ebca9e0f974ea3b5fbc4fbb3943882131f1c"
|
||||
}
|
||||
},
|
||||
{
|
||||
"relative": "TASK_INSTRUCTIONS.md",
|
||||
"source": {
|
||||
"path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/TASK_INSTRUCTIONS.md",
|
||||
"bytes": 2961,
|
||||
"sha256": "f9937c3c7dff5a25ada453365d26c87fecf009d29518724f0c1e67d2b18afff3"
|
||||
},
|
||||
"retained": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p28-02-root-control-r01/retained-s1-3325e7d-r01/eq/TASK_INSTRUCTIONS.md",
|
||||
"bytes": 2961,
|
||||
"sha256": "f9937c3c7dff5a25ada453365d26c87fecf009d29518724f0c1e67d2b18afff3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"relative": "UNIT_OUTPUT.sha256",
|
||||
"source": {
|
||||
"path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT.sha256",
|
||||
"bytes": 82,
|
||||
"sha256": "87e22105a54771c30fca8e520c87dfabb216dc101dd471c088a5cdf8625751d4"
|
||||
},
|
||||
"retained": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p28-02-root-control-r01/retained-s1-3325e7d-r01/eq/UNIT_OUTPUT.sha256",
|
||||
"bytes": 82,
|
||||
"sha256": "87e22105a54771c30fca8e520c87dfabb216dc101dd471c088a5cdf8625751d4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"relative": "UNIT_OUTPUT.txt",
|
||||
"source": {
|
||||
"path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT.txt",
|
||||
"bytes": 2839,
|
||||
"sha256": "cdca0cdd551ce76c6100c4dd90e04559551f9d88c054a19a2bc6a77e6572ae15"
|
||||
},
|
||||
"retained": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p28-02-root-control-r01/retained-s1-3325e7d-r01/eq/UNIT_OUTPUT.txt",
|
||||
"bytes": 2839,
|
||||
"sha256": "cdca0cdd551ce76c6100c4dd90e04559551f9d88c054a19a2bc6a77e6572ae15"
|
||||
}
|
||||
},
|
||||
{
|
||||
"relative": "UNIT_OUTPUT_ATTEMPT_01.sha256",
|
||||
"source": {
|
||||
"path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_ATTEMPT_01.sha256",
|
||||
"bytes": 93,
|
||||
"sha256": "eed78af7775a79838e65ea3cb07e9fe09822d2d7a23007f294cbf0a0c98d1c7c"
|
||||
},
|
||||
"retained": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p28-02-root-control-r01/retained-s1-3325e7d-r01/eq/UNIT_OUTPUT_ATTEMPT_01.sha256",
|
||||
"bytes": 93,
|
||||
"sha256": "eed78af7775a79838e65ea3cb07e9fe09822d2d7a23007f294cbf0a0c98d1c7c"
|
||||
}
|
||||
},
|
||||
{
|
||||
"relative": "UNIT_OUTPUT_ATTEMPT_01.txt",
|
||||
"source": {
|
||||
"path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_ATTEMPT_01.txt",
|
||||
"bytes": 3368,
|
||||
"sha256": "307486177b76602cbe68acae24c9560d501b3b866136d8e69802ec24c28e8be8"
|
||||
},
|
||||
"retained": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p28-02-root-control-r01/retained-s1-3325e7d-r01/eq/UNIT_OUTPUT_ATTEMPT_01.txt",
|
||||
"bytes": 3368,
|
||||
"sha256": "307486177b76602cbe68acae24c9560d501b3b866136d8e69802ec24c28e8be8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"relative": "UNIT_OUTPUT_ATTEMPT_02.sha256",
|
||||
"source": {
|
||||
"path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_ATTEMPT_02.sha256",
|
||||
"bytes": 93,
|
||||
"sha256": "1de0c0052e66cc60668690bf43e29eb01808afd023525e517ba94beaab0db669"
|
||||
},
|
||||
"retained": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p28-02-root-control-r01/retained-s1-3325e7d-r01/eq/UNIT_OUTPUT_ATTEMPT_02.sha256",
|
||||
"bytes": 93,
|
||||
"sha256": "1de0c0052e66cc60668690bf43e29eb01808afd023525e517ba94beaab0db669"
|
||||
}
|
||||
},
|
||||
{
|
||||
"relative": "UNIT_OUTPUT_ATTEMPT_02.txt",
|
||||
"source": {
|
||||
"path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_ATTEMPT_02.txt",
|
||||
"bytes": 2699,
|
||||
"sha256": "07144a7f1941162227f54fefd1961ed0f209e97282432723bbda534079582e4e"
|
||||
},
|
||||
"retained": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p28-02-root-control-r01/retained-s1-3325e7d-r01/eq/UNIT_OUTPUT_ATTEMPT_02.txt",
|
||||
"bytes": 2699,
|
||||
"sha256": "07144a7f1941162227f54fefd1961ed0f209e97282432723bbda534079582e4e"
|
||||
}
|
||||
},
|
||||
{
|
||||
"relative": "compare_versions.py",
|
||||
"source": {
|
||||
"path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py",
|
||||
"bytes": 32313,
|
||||
"sha256": "058f3fef57c2ebe6951a48d85d570a110b982e08a13c805c244fec7d5e9a0fe8"
|
||||
},
|
||||
"retained": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p28-02-root-control-r01/retained-s1-3325e7d-r01/eq/compare_versions.py",
|
||||
"bytes": 32313,
|
||||
"sha256": "058f3fef57c2ebe6951a48d85d570a110b982e08a13c805c244fec7d5e9a0fe8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"relative": "references/OPT_CONTRACT_T1.md",
|
||||
"source": {
|
||||
"path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/references/OPT_CONTRACT_T1.md",
|
||||
"bytes": 13952,
|
||||
"sha256": "ad9f3d76f3500b39263fb898d7c64588b4b47c9e11b456f938195261fd054d16"
|
||||
},
|
||||
"retained": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p28-02-root-control-r01/retained-s1-3325e7d-r01/eq/references/OPT_CONTRACT_T1.md",
|
||||
"bytes": 13952,
|
||||
"sha256": "ad9f3d76f3500b39263fb898d7c64588b4b47c9e11b456f938195261fd054d16"
|
||||
}
|
||||
},
|
||||
{
|
||||
"relative": "references/OPUS_D2_SCOPE_CLARIFICATION.txt",
|
||||
"source": {
|
||||
"path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/references/OPUS_D2_SCOPE_CLARIFICATION.txt",
|
||||
"bytes": 5598,
|
||||
"sha256": "5775e7b512d9e90dbcfbcb181f5b64dc0fa8207e0947c0a4a6a5c9195565f9bd"
|
||||
},
|
||||
"retained": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p28-02-root-control-r01/retained-s1-3325e7d-r01/eq/references/OPUS_D2_SCOPE_CLARIFICATION.txt",
|
||||
"bytes": 5598,
|
||||
"sha256": "5775e7b512d9e90dbcfbcb181f5b64dc0fa8207e0947c0a4a6a5c9195565f9bd"
|
||||
}
|
||||
},
|
||||
{
|
||||
"relative": "references/OPUS_STARTUP_LIFECYCLE_CLARIFICATION.txt",
|
||||
"source": {
|
||||
"path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/references/OPUS_STARTUP_LIFECYCLE_CLARIFICATION.txt",
|
||||
"bytes": 5996,
|
||||
"sha256": "967aebf27ff412f7a16ce771ef7d68abf8cfde0bb76ed19cf6dbf2817ca7acc6"
|
||||
},
|
||||
"retained": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p28-02-root-control-r01/retained-s1-3325e7d-r01/eq/references/OPUS_STARTUP_LIFECYCLE_CLARIFICATION.txt",
|
||||
"bytes": 5996,
|
||||
"sha256": "967aebf27ff412f7a16ce771ef7d68abf8cfde0bb76ed19cf6dbf2817ca7acc6"
|
||||
}
|
||||
},
|
||||
{
|
||||
"relative": "registration/ACCEPTANCE_BASELINE.json",
|
||||
"source": {
|
||||
"path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/registration/ACCEPTANCE_BASELINE.json",
|
||||
"bytes": 2981,
|
||||
"sha256": "84628bc21205387f8a7143031bdc50c9f68a767d350e6c34b32e0ba1c7059337"
|
||||
},
|
||||
"retained": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p28-02-root-control-r01/retained-s1-3325e7d-r01/eq/registration/ACCEPTANCE_BASELINE.json",
|
||||
"bytes": 2981,
|
||||
"sha256": "84628bc21205387f8a7143031bdc50c9f68a767d350e6c34b32e0ba1c7059337"
|
||||
}
|
||||
},
|
||||
{
|
||||
"relative": "registration/CONFIG_PROPOSAL.json",
|
||||
"source": {
|
||||
"path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/registration/CONFIG_PROPOSAL.json",
|
||||
"bytes": 821,
|
||||
"sha256": "775fbbb97cda8b4d4991defdf7871b0fc79f489f4dea34c1733d4830426cf1df"
|
||||
},
|
||||
"retained": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p28-02-root-control-r01/retained-s1-3325e7d-r01/eq/registration/CONFIG_PROPOSAL.json",
|
||||
"bytes": 821,
|
||||
"sha256": "775fbbb97cda8b4d4991defdf7871b0fc79f489f4dea34c1733d4830426cf1df"
|
||||
}
|
||||
},
|
||||
{
|
||||
"relative": "registration/REGISTRATION_PROPOSAL.json",
|
||||
"source": {
|
||||
"path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/registration/REGISTRATION_PROPOSAL.json",
|
||||
"bytes": 4733,
|
||||
"sha256": "9590fc853a4df8d50cc0d269d23bd9c844dc6931590ff6f24ebf95bb54a8d135"
|
||||
},
|
||||
"retained": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p28-02-root-control-r01/retained-s1-3325e7d-r01/eq/registration/REGISTRATION_PROPOSAL.json",
|
||||
"bytes": 4733,
|
||||
"sha256": "9590fc853a4df8d50cc0d269d23bd9c844dc6931590ff6f24ebf95bb54a8d135"
|
||||
}
|
||||
},
|
||||
{
|
||||
"relative": "registration/ROOT_PROPOSAL_BYTE_TRANSFER.json",
|
||||
"source": {
|
||||
"path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/registration/ROOT_PROPOSAL_BYTE_TRANSFER.json",
|
||||
"bytes": 4778,
|
||||
"sha256": "63197f650849084f769e487a76458361886a37090042f1e351851c75b0384da2"
|
||||
},
|
||||
"retained": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p28-02-root-control-r01/retained-s1-3325e7d-r01/eq/registration/ROOT_PROPOSAL_BYTE_TRANSFER.json",
|
||||
"bytes": 4778,
|
||||
"sha256": "63197f650849084f769e487a76458361886a37090042f1e351851c75b0384da2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"relative": "test_eq.py",
|
||||
"source": {
|
||||
"path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py",
|
||||
"bytes": 21350,
|
||||
"sha256": "f1ff2a7aa99161527e68c0ebaea0f0db275fde219320b74874f8675c075ad2b1"
|
||||
},
|
||||
"retained": {
|
||||
"path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p28-02-root-control-r01/retained-s1-3325e7d-r01/eq/test_eq.py",
|
||||
"bytes": 21350,
|
||||
"sha256": "f1ff2a7aa99161527e68c0ebaea0f0db275fde219320b74874f8675c075ad2b1"
|
||||
}
|
||||
}
|
||||
],
|
||||
"stage_implementation_committed": false,
|
||||
"formal_EQ_accepted": false,
|
||||
"all6_registered_acceptance_pending": true,
|
||||
"remaining": [
|
||||
"S2 Godot typed encode/decode/roundtrip, all checkpoints/events and actual guard binding, checker",
|
||||
"S3 rejection/cache/ownership scenarios and absolute checks",
|
||||
"S4 native driver and bundle verifier, full local units and formal submission",
|
||||
"Frozen S native7, both registered validations, fresh independent Opus all6, normal candidate qualification/integration/final",
|
||||
"Original P28-02 T1 optimization, repeat comparison, restart, exact final full roster, whole-unit review/final and ledger"
|
||||
],
|
||||
"original_completed": 23,
|
||||
"original_total": 88,
|
||||
"packages_completed": 4,
|
||||
"packages_total": 30,
|
||||
"original_credit": 0,
|
||||
"partial_credit": false
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"observed_at_jst": "2026-10-21T08:14:09.397302+09:00",
|
||||
"project": "the-tree-p28-02-eq",
|
||||
"task": "P28-02-EQ",
|
||||
"base": "2549cf7d6992560b850bbd11934e3c14b39a1988",
|
||||
"stage": "S2",
|
||||
"state_at_observation": "implementing",
|
||||
"repairs": 4,
|
||||
"submitted": null,
|
||||
"actual_run": {
|
||||
"id": "558b96b3fe5e462296e85bc591622d1c",
|
||||
"task_id": "P28-02-EQ",
|
||||
"role": "implementer",
|
||||
"service": "codex",
|
||||
"status": "running",
|
||||
"pid": 12205,
|
||||
"started": 1792537978.637717,
|
||||
"finished": null,
|
||||
"exit_code": null,
|
||||
"artifact": "/Users/korizatou114/Library/Application Support/agent-control/the-tree-p28-02-eq/runs/558b96b3fe5e462296e85bc591622d1c"
|
||||
},
|
||||
"actual_process_observation": "12205 12176 01:11 Ss /Applications/ChatGPT.app/Contents/Resources/codex-cli/bin/../CodexCLI.app/Contents/MacOS/codex",
|
||||
"root_exec_session": 85980,
|
||||
"actual_Opus_RUN": {
|
||||
"path": "docs/plans/original-completion-2026-10-02/execution/p28-02/DESKTOP_EQ_S2_RUN_DECISION.json",
|
||||
"bytes": 3061,
|
||||
"sha256": "e24256ce751de9d2c9cad528c3a1b44a9adf1f5ae81c325ed040d501c22f1f89"
|
||||
},
|
||||
"actual_Opus_session": "local_a7f85421-3eed-4482-8030-c0dca669573a",
|
||||
"normal_repair_job": "0cc4be6d7c264cb18dab2a4424d22231",
|
||||
"normal_repair_succeeded": true,
|
||||
"normal_input_record": {
|
||||
"path": "artifacts/original-completion-2026-10-02/p28-02-root-control-r01/actual-desktop-EQ-S2-RUN-input-r05/RECORDED.json",
|
||||
"bytes": 242,
|
||||
"sha256": "e9cce03fdc35bb488c6f204ccc2d8f25f8658481b109fd3fdfd6981d525bb095"
|
||||
},
|
||||
"actual_context": {
|
||||
"path": "artifacts/original-completion-2026-10-02/p28-02-root-control-r01/eq-staged-s2-owner-run-input-r05/RUN_STARTED.json",
|
||||
"bytes": 795,
|
||||
"sha256": "2ee4df7e24f699c85a45a030f6d71d847e6bdb830a0ab893c9f770446cf024bb"
|
||||
},
|
||||
"all19_retained_S1_files_verified_before_and_after_repair": true,
|
||||
"S1_local_readiness": {
|
||||
"path": "docs/plans/original-completion-2026-10-02/execution/p28-02/EQ_S1_LOCAL_READINESS_3325E7D.json",
|
||||
"bytes": 17330,
|
||||
"sha256": "c1188d655a69a32b06ac9ea508bfaf4c7145c80b779083da71ed5433cff403f8"
|
||||
},
|
||||
"formal_EQ_accepted": false,
|
||||
"original_credit": 0,
|
||||
"original_completed": 23,
|
||||
"original_total": 88,
|
||||
"packages_completed": 4,
|
||||
"packages_total": 30,
|
||||
"next": "Follow this exact run/PID/exec. S2 return, S3 and S4 remain; native7, both validations, fresh independent all6 review and normal integration/final remain. No stage receives original credit."
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
EQ_STAGED_IMPLEMENTATION_PLAN(P28-02-EQ repair 3 以降。base 2549cf7d6992560b850bbd11934e3c14b39a1988。SPEC、TASK、6条件、eq/references、eq/registration、EQ_S_TIMING_CLARIFICATION r01/r02、EQ_ENVIRONMENT_FIELDS_CLARIFICATION r03 は全てそのまま有効。変えるのは、工程と、成果物の内部の設計の固定だけ)
|
||||
|
||||
前回までの事実
|
||||
- repair 2(run 84ca0ff8…)は、IMPLEMENTATION.md と compare_versions.py などを作った後、item_30 で全てを削除し、「6ファイルと unit の PASS を提供できない」として、自分から終了した。仕様の不足の指摘ではない。packet は 94 KB あった。
|
||||
- この失敗は失敗のまま保持する。削除したことを成功として扱わない。
|
||||
|
||||
工程の変更(必須)
|
||||
- G1: **作ったファイルは、削除しない**。完成していなくても、W の eq/ に残す。各 run の最後に、eq/PROGRESS.md に、終わった段階・残りの作業・現在の試験の結果を書く。
|
||||
- G2: 1回の run では、下の**1つの段階だけ**を行う。始める前に eq/PROGRESS.md を読み、次の段階から再開する。前の段階のコードは作り直さない。
|
||||
- G3: 各段階の終わりに、engine を使わない python3 test_eq.py を実行する。その時点で存在する試験が、全件 PASS になるまで直す。生出力を eq/UNIT_OUTPUT.txt に保存する。
|
||||
- G4: 段階1〜3の終わりには、正式な JSON の status を blocked にし、findings に「段階 Sx 完了(失敗ではない。次は Sx+1)」と PROGRESS.md の要点を書いて返す。段階4の終わりにだけ、提出する(status を submitted 相当の正式な提出にする)。
|
||||
- G5: 通常の実装上の判断(関数の分け方、名前、試験データ、記録の書式)は、IMPLEMENTATION.md に記録して進める。blocked にしてよいのは、原本の仕様・値・権限・課金・受入に影響する未確定事項がある場合だけ。
|
||||
- G6: engine の起動、git への書込み、製品の変更、全回帰はしない。SPEC、TASK、eq/references、eq/registration は変更しない。
|
||||
|
||||
固定するインターフェース(6ファイル。SPEC §2)
|
||||
|
||||
1. compare_versions.py(Python のみ。engine を使わない)
|
||||
- normalize_events(events, profile_root) -> (normalized, sidecar):
|
||||
- r03 の F1〜F3 を、JSON の event の一覧に適用する。
|
||||
- 閉じた一覧の外の *_us / *_ms / profile_root を含む文字列は、正規化せず、violations として返す。
|
||||
- restore_events(normalized, sidecar, profile_root) -> events: 逆の復元(完全一致の確認に使う)。
|
||||
- compare_reports(a, b) -> dict: 2つの report(同じ版の別 PID、または前後の版)を比べる。
|
||||
- 毎分の checkpoint の S_norm_sha と latest_norm_sha の一致
|
||||
- digest の規則(r02 の T3)
|
||||
- K と C の、SPEC §3.2 に列挙した欄
|
||||
- E2 の正規化した全イベント(開始の counter の一致が前提)
|
||||
- E3/E4/E5 の scenario の結果の一致
|
||||
- 比べない欄は、理由と両側の値を記録する
|
||||
- 差は path ごとに返す
|
||||
- check_source_closure(before_map, after_map, allowed_changed) -> dict: SPEC §2 と OPT r02 §2。追加・欠落・登録されていない差分を拒否する。
|
||||
2. eq_probe.gd(GDScript):
|
||||
- 起動の6段階は、DIAG の diag_probe.gd の構成をそのまま参考にする。
|
||||
- 役割は R と O(env の THE_TREE_EQ_ROLE)。
|
||||
- 観測の checkpoint は B1 と、30分の各 tick の最後(31個)。各 checkpoint に、次のものを置く:
|
||||
- minute
|
||||
- S_raw_sha、S_norm_sha(GDScript の中で F1〜F3 の typed の marker を使って正規化した後の var_to_bytes の SHA)
|
||||
- 正規化した S の path の hash の表(depth ≤ 4)
|
||||
- latest_norm_sha
|
||||
- digest の情報
|
||||
- K と C の全体
|
||||
- sidecar
|
||||
- E2 は subscribe('*') で、全イベントの JSON(正規化の前)を記録する。正規化は compare_versions.py で行う(GDScript と Python で、同じ規則の二重実装をしない)。
|
||||
- E3/E4/E5 の scenario は、SPEC §3.3 の専用の区間で行う。各区間について、開始と終了、操作、code、前後の S/K/C、件数(r02 の T4)を記録する。
|
||||
- stdout には、P28_02_EQ_REPORT=<json> をちょうど1行出す。終了は close_requested.emit()。
|
||||
3. check_eq.py: report 1つを検査する。
|
||||
- 形式、必須の欄、矛盾
|
||||
- 閉じた一覧の外の差
|
||||
- probe の静的な禁止(autoload の class_name の参照、状態を変える呼出しの区間の外での使用、Variant からの := の推論)
|
||||
- SimulationDigest だけでの判定
|
||||
4. run_eq.py: Root が実行する driver。
|
||||
- diag_p28_02.py の構成をそのまま参考にする(--check / --run、依存の SHA、1407 の source、凍結した S の照合、owned phase、guard、private profile、cleanup)。
|
||||
- phase は import、parse-base、parse-wrapper、R-A、R-B、O-A、O-B。
|
||||
- 成功したら、execution.json と bundle.json を作る。
|
||||
5. verify_eq.py: --project-root . で、$BUILD_OUTPUT_DIR/p28-02-eq-evidence の bundle を結合する。bundle が無ければ失敗する。
|
||||
- 各 report に check_eq を行う。
|
||||
- R-A と R-B、O-A と O-B に compare_reports を行い、差が0であること(harness の正しさ)。
|
||||
- E3/E5 の、前の版での製品の失敗は、「既存の不具合」の一覧として出力する。harness の不合格とは区別する。
|
||||
- SPEC、TASK、eq/references、eq/registration の SHA を固定して照合する。
|
||||
6. test_eq.py: 合成した入力だけで動く。各段階で、その段階の試験を足していく。
|
||||
|
||||
段階(1回の run で1つ)
|
||||
- S1: compare_versions.py の全体と、その試験(F1〜F3 の正常と拒否、可逆性、比較、source の閉包)。PROGRESS.md と IMPLEMENTATION.md を作る。
|
||||
- S2: eq_probe.gd の、起動・観測の checkpoint・E2 の記録・報告。check_eq.py の静的な検査と形式の検査、それぞれの試験。
|
||||
- S3: eq_probe.gd の E3/E4/E5 の scenario、check_eq.py のそれに対する検査、試験。
|
||||
- S4: run_eq.py と verify_eq.py、bundle の試験。全件 PASS を確かめて、正式に提出する。
|
||||
|
||||
Root への依頼(packet を小さくするため)
|
||||
- actual_commander_context の key には、この計画の全文と RUN の判断だけを入れる。r01・r02・r03 の全文は、build/ に読取専用で置き、その path と SHA だけを渡す。eq/references は W の中にあるので、path だけで足りる。
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
EQ_STAGED_IMPLEMENTATION_PLAN r02(P28-02-EQ repair 3 以降。EQ_STAGED_IMPLEMENTATION_PLAN(r01)の工程 G1〜G6、段階 S1〜S4、Root への依頼は、そのまま有効。この r02 は、固定インターフェースのうち、状態とイベントの運搬の表現と、normalize_events の返り値を置き換えて確定する。SPEC、TASK、6条件、eq/references、eq/registration、補足 r01/r02/r03 は変更しない)
|
||||
|
||||
A. 型を保つ運搬の表現(typed tree。JSON は運び方であって、型の情報は落とさない)
|
||||
|
||||
A1 node の形式(JSON の配列)
|
||||
- 各値は [type_code, payload]。type_code は Godot の typeof() の値。
|
||||
- null: [0]
|
||||
- bool: [1, 0|1]
|
||||
- int: [2, 整数]
|
||||
- float: [3, "<8 byte little-endian IEEE754 の hex>"](10進の文字列にしない)
|
||||
- String: [4, "文字列"]
|
||||
- StringName: [21, "文字列"]
|
||||
- Vector2/Vector2i/Vector3/Vector3i/Rect2/Rect2i/Color など: [type_code, [各成分の node]](成分は int か float の node)
|
||||
- Dictionary: [27, [[key_node, value_node], …], typed_info]。**元の挿入の順序のまま**並べる。typed_info は、型つきの Dictionary なら key と value の builtin 型・class 名・script、それ以外は null。
|
||||
- Array: [28, [element_node, …], typed_info]。typed_info は get_typed_builtin()・get_typed_class_name()・get_typed_script() の値、型の無い Array なら null。
|
||||
- PackedByteArray: [29, "<base64>"]。他の Packed*Array も、要素ごとの node の列にする(float は hex)。
|
||||
- Object、Callable、Signal、RID が現れたら、運搬せずに失敗にする(snapshot と event の dict には、本来現れないもの)。
|
||||
|
||||
A2 無損失の証明(Godot の中で行う。probe の必須の処理)
|
||||
- tree = encode(value) を作った後、decode(tree) で Variant を作り直す。var_to_bytes(decode(tree)) == var_to_bytes(value) であることを確かめる。一致しなければ失敗にする。
|
||||
- report には、checkpoint ごとに、次の3つを記録する。
|
||||
- raw_bytes_sha = sha256(var_to_bytes(value))
|
||||
- tree_sha = sha256(tree を key の順序を変えずに JSON.stringify した UTF-8)
|
||||
- roundtrip_ok
|
||||
- Python は、受け取った tree から tree_sha を計算し直して結合する。これで、Python で比べる tree が、Godot の元の bytes と無損失に対応することが保証される。
|
||||
|
||||
A3 保存の場所と大きさ(深さの制限は設けない。全体を再構成できるようにする)
|
||||
- 各 PID は、checkpoint の列(B1 と、30分の各 tick の最後)について、S 層と latest_snapshot を、次の形で、private user:// の evidence/ に書き出す。driver は、それを RESTART の copy_states と同じ方式で out へ複製し、SHA を結合する。
|
||||
- checkpoint 0(B1): tree の全体(JSON、zstd で圧縮してよい。圧縮した場合は、圧縮の前後の SHA を両方記録する)。
|
||||
- checkpoint k(k≥1): checkpoint k−1 の tree に対する、path を指定した差分の操作の列。操作は set(path, node)、dict_insert(path, index, key_node, value_node)、dict_remove(path, key_node)、array_splice(path, start, delete_count, [node…])。順序つきで、再構成すると、checkpoint k の tree と完全一致すること。
|
||||
- latest_snapshot は、各 checkpoint で、var_to_bytes が S 層と同じなら same_as_S=true とし、違えば、その tree(または S に対する差分)を保存する。
|
||||
- Python は、checkpoint 0 から差分を順に適用して、全ての checkpoint を再構成する。checkpoint ごとに tree_sha と一致することを確かめる。
|
||||
|
||||
A4 比較(compare_versions.py。全て tree の上で行い、深さの制限は無い)
|
||||
- 第一の比較は、tree の完全一致(型、key、順序、値。全ての node)。
|
||||
- 一致しない場合に限り、正規化した比較を行う。dict の key を文字で並べ(同じ文字の key が2つあれば拒否)、それ以外の型・値・配列の順序を保ったまま比べる。それで一致すれば「dict の列挙の順序だけの差」として、その全ての path を記録する。それ以外の差は、全ての path と両側の node を記録して、不一致にする。
|
||||
- F1〜F3(r03)の正規化は、tree の node の上で行う。sidecar から、元の tree へ完全に戻せること(tree_sha が一致すること)を確かめる。
|
||||
|
||||
B. E2 のイベントの運搬
|
||||
- 各 event について、event.to_dictionary()(製品の直列化。scripts/core/domain_event.gd:47-59)の tree を記録する。あわせて、元の object の欄の型(event_id と event_type が StringName であるか、entity_ids の型、payload の dict の typed_info)を、original_field_types として記録する。
|
||||
- 受け取りの順序で番号をつけ、開始の時点の counter と、published_ids の数を記録する。
|
||||
- イベントの列は、A3 と同じく evidence/ に書き出し(tree の列。圧縮してよい)、SHA を結合する。Godot の中で、各 event について A2 の roundtrip を確かめる。
|
||||
- compare_reports は、この tree の列を受け取り、全ての欄と event_id を**そのまま**比べる(ID の付け替えはしない)。F1〜F3 は、payload の該当する node にだけ適用する。
|
||||
|
||||
C. normalize_events とその仲間の返り値(固定)
|
||||
- normalize_events(events, profile_root) -> (normalized, sidecar)。返り値は2つの要素のまま。
|
||||
- normalized: tree の列。閉じた一覧(r03)の node だけを marker に置き換えたもの。
|
||||
- sidecar: dict で、key は次の3つに固定。
|
||||
- "entries": [{"event_index", "path", "key", "original_node"}…]。F1〜F3 で置き換えた全ての node の元の値。F3 の場合は original_node に元の message の文字列を入れ、"root" に、置き換えた root を入れる。
|
||||
- "violations": [{"event_index", "path", "kind", "node"}…]。閉じた一覧の外にあった、*_us / *_ms の key、profile_root を含む文字列など。**存在しただけでは不合格にしない**。正規化はせずに、そのまま保持して記録する。
|
||||
- "profile_root": 使った root の文字列と、guard の actual_user_data_dir との一致の結果。
|
||||
- restore_events(normalized, sidecar, profile_root) -> events: entries から元に戻す。violations の node は、もともと変えていないので、そのまま。
|
||||
- 状態の tree にも、同じ形の normalize_tree(tree, profile_root) -> (normalized, sidecar) と restore_tree を用意する。
|
||||
- r03 の規則は、そのまま。violations にあるものを正規化しようとしたら拒否する。violations にあるものが、比べる2つの側で実際に異なれば、その差は不一致(失敗)として、path と両側の値を記録する。
|
||||
|
||||
D. 段階への影響
|
||||
- S1(今回): compare_versions.py に、A4 の比較、C の4つの関数、A3 の差分の再構成、tree_sha の再計算、check_source_closure を実装する。試験は合成の tree で行い、次のものを確かめる。
|
||||
- 型の違い(int と float、String と StringName、型つきの配列)を区別すること
|
||||
- dict の順序だけの差の path
|
||||
- 差分の再構成の完全一致
|
||||
- sidecar からの逆の復元
|
||||
- violations の扱い(存在だけでは不合格にしない、正規化しようとしたら拒否、差があれば不一致)
|
||||
- S2: eq_probe.gd に、A1 の encode と decode、A2 の roundtrip、A3 の書き出し、B の記録を実装する。
|
||||
- S3 と S4 は、r01 のとおり。
|
||||
Reference in New Issue
Block a user