From 13aefdd3dd6f9d0a656114283954b0716eeed6d7 Mon Sep 17 00:00:00 2001 From: Agent Control Runner Date: Sun, 18 Oct 2026 20:16:38 +0900 Subject: [PATCH] =?UTF-8?q?P04-01:=20=E5=90=8C=E6=99=82=E7=99=BA=E7=94=9F?= =?UTF-8?q?=E3=81=AE=E6=9B=B4=E6=96=B0=E8=A6=8F=E7=B4=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../execution/p04-01/CURRENT_STATUS.md | 22 +- .../execution/p04-01/ORDER_AUDIT.md | 71 +++++- ...RICAL_ROOT_Q47_ACTUAL_INDEX_GENERATION.log | 14 ++ ...Q47_ACTUAL_MATERIAL_ADMISSION_FAILURE.json | 53 +++++ .../p04-01/REPAIR48_STATIC_INSPECTION.json | 88 +++++++ .../execution/p04-01/REPAIR48_STATUS.md | 160 +++++++++++++ .../p04-01/REPAIR49_PROTECTED_SHA.json | 41 ++++ .../execution/p04-01/REPAIR49_STATUS.md | 225 ++++++++++++++++++ .../execution/p04-01/build_p04_index.py | 190 +++++++++++++-- .../execution/p04-01/collect_p04_native.py | 3 + .../execution/p04-01/full_suite_verifier.py | 6 +- .../execution/p04-01/p04_native_series.py | 17 +- .../p04-01/repair48_identity_controls.py | 153 ++++++++++++ .../p04-01/repair48_transport_controls.py | 159 +++++++++++++ .../execution/p04-01/s1/S1_ROOT_RUN.md | 23 ++ .../execution/p04-01/s2/S2_ROOT_RUN.md | 23 ++ .../execution/p04-01/s2b/S2B_ROOT_RUN.md | 23 ++ .../execution/p04-01/s3/S3_ROOT_RUN.md | 23 ++ .../execution/p04-01/s4/S4_ROOT_RUN.md | 23 ++ .../execution/p04-01/s5/S5_ROOT_RUN.md | 51 ++++ .../execution/p04-01/s5/s5_order_adapter.py | 43 +++- .../execution/p04-01/s5/s5_power_adapter.py | 16 +- 22 files changed, 1392 insertions(+), 35 deletions(-) create mode 100644 docs/plans/original-completion-2026-10-02/execution/p04-01/REPAIR48_HISTORICAL_ROOT_Q47_ACTUAL_INDEX_GENERATION.log create mode 100644 docs/plans/original-completion-2026-10-02/execution/p04-01/REPAIR48_HISTORICAL_ROOT_Q47_ACTUAL_MATERIAL_ADMISSION_FAILURE.json create mode 100644 docs/plans/original-completion-2026-10-02/execution/p04-01/REPAIR48_STATIC_INSPECTION.json create mode 100644 docs/plans/original-completion-2026-10-02/execution/p04-01/REPAIR48_STATUS.md create mode 100644 docs/plans/original-completion-2026-10-02/execution/p04-01/REPAIR49_PROTECTED_SHA.json create mode 100644 docs/plans/original-completion-2026-10-02/execution/p04-01/REPAIR49_STATUS.md create mode 100644 docs/plans/original-completion-2026-10-02/execution/p04-01/repair48_identity_controls.py create mode 100644 docs/plans/original-completion-2026-10-02/execution/p04-01/repair48_transport_controls.py diff --git a/docs/plans/original-completion-2026-10-02/execution/p04-01/CURRENT_STATUS.md b/docs/plans/original-completion-2026-10-02/execution/p04-01/CURRENT_STATUS.md index 125a8f2..c21e716 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p04-01/CURRENT_STATUS.md +++ b/docs/plans/original-completion-2026-10-02/execution/p04-01/CURRENT_STATUS.md @@ -1,6 +1,26 @@ +## REPAIR49 current correction + +Source-ready only; original 30/88, formal 16, P04=0, no partial credit. +REPAIR48's specification-mismatch blocker below is historical and corrected: +the immutable 7000-byte original has SHA256 +d28aadb044633f7d804de5a92c8d4c4a7438dfbf44c3243dca978951f4def25f; +removing its single EOF LF gives +9ec722e7dfb0bee178d291624a026420c08412574e238bba1fde012c7a6f7881. +This is the existing Git/Runner strip/checker one-EOF-LF pin contract. +No specification, approval or normalization change. Older contradictory wording +below is superseded history, including blanket full-reuse prohibitions and +all-controls-unexecuted wording. Q47 admission/index failures remain failures. +See REPAIR49_STATUS.md for closure audit and verbatim complete_B FileNotFoundError. +Root handoff reports payload(B), all53, series/join/power PASS; order-typed remains +UNDETERMINED. Worker did not rerun them. Corrected complete_B remains unexecuted. +Old native/full successes confer no new-S acceptance or credit. + + +REPAIR48 current source status: see [REPAIR48_STATUS.md](REPAIR48_STATUS.md). Earlier run directions and successes below are historical; they grant no P04 credit. + RUN47 current harness status: see REPAIR47_STATUS.md, REPAIR47_PLAN.json and REPAIR47_VALIDATION.json. Original unit remains unaccepted; earlier status below is historical. -# P04-01 current status — repair31 +# Historical P04-01 status — repair31 **BLOCKED: partial implementation; do not start the once-only native/full run.** Formal completed status is **16/88**, with **zero P04 credit**. diff --git a/docs/plans/original-completion-2026-10-02/execution/p04-01/ORDER_AUDIT.md b/docs/plans/original-completion-2026-10-02/execution/p04-01/ORDER_AUDIT.md index a4d8601..23e199d 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p04-01/ORDER_AUDIT.md +++ b/docs/plans/original-completion-2026-10-02/execution/p04-01/ORDER_AUDIT.md @@ -1,3 +1,72 @@ +## REPAIR49 normal-gate handoff + +Required materials: exact B/native-first-current and fresh-run registry; each +runner-input/ended/source/UID/formal/raw/lifecycle receipt; original recorded Q +and engine context; B/p04-evidence/runner-materials and RELOCATION.json; matching +collection/MANIFEST and separate dependency invocation; original full run and +full_suite binding/raw receipts; final index and invocation receipt; immutable +authorities in frozen checkout. No raw or historical receipt is rewritten. +Two-placement identity requires the explicit closure in repair48_identity_controls.py, +missing-file rejection, and original/A/B complete path/bytes/SHA tables and tree +hash equality before and after positive execution. See REPAIR49_STATUS.md. +Submission is followed by new Q freeze, affected pure controls (complete_B included), +clean exact-Q check-only, capacity/PID checks, one fresh native lease for +S1/S2a/S2b/S3/S4 and all ten S5 cases, readers/adapters, 15EV collector, full +verification/binding under the conditions below (or one final full184 if any +condition fails), index generation, p04-acceptance once, separate Opus whole-unit +review, normal prepare/C/integration/final/Root DB join/ledger/main push. +If order-typed fails, preserve its result and stop before heavy execution. +Only whole-unit acceptance grants credit. + + +## REPAIR49 full184 conditional reuse candidate — all conditions UNVERIFIED + +Native reuse is forbidden: all six series require fresh M/S/Q_tree provenance +(p04_native_series.py:1287; checker:370). Full uses the existing separate binding +(checker:1175-1186); no adopter or checker change is authorized. +The following are requirements, not results or approval: + +1. New S5 source_before must equal old full selected_source_map: all 1369 keys + and SHA values, not counts alone. +2. Old project_root must remain unchanged: source-start == current source_refs + == post-verification source_refs (full_suite_verifier.py:115). +3. selected_source_map, roster184, parse329, settings, runner/marker module, + marker contract, suite-policy and UID plan/stage must all match (116-152,225). +4. inputs.engine must match current engine_pin (124-125). +5. Revalidate every phase PID, cleanup, marker and diagnostics (154-228). +6. Current s5/run_s5_native.py and full_suite_verifier.py SHA must equal the + Root rehearsal versions. +7. Never relabel old S/oldQ/project_root/PIDs/time. Describe reuse only as + revalidating the exact-source-identical old full through the existing + full_suite route; never claim full ran on new S. +8. A separate Opus whole-unit review must independently confirm applicability. + +Conditions 1–6 require actual checks after final freeze. If any predicate is +unproved or differs, reject reuse and execute full184 once on the final version. +SourceRefs (tools/run_all_tests.py:40-45) excludes docs/private package, but that +fact is no substitute for complete source equality. No reuse is approved here. + + +## REPAIR49 current correction + +Source-ready only; original 30/88, formal 16, P04=0, no partial credit. +REPAIR48's specification-mismatch blocker below is historical and corrected: +the immutable 7000-byte original has SHA256 +d28aadb044633f7d804de5a92c8d4c4a7438dfbf44c3243dca978951f4def25f; +removing its single EOF LF gives +9ec722e7dfb0bee178d291624a026420c08412574e238bba1fde012c7a6f7881. +This is the existing Git/Runner strip/checker one-EOF-LF pin contract. +No specification, approval or normalization change. Older contradictory wording +below is superseded history, including blanket full-reuse prohibitions and +all-controls-unexecuted wording. Q47 admission/index failures remain failures. +See REPAIR49_STATUS.md for closure audit and verbatim complete_B FileNotFoundError. +Root handoff reports payload(B), all53, series/join/power PASS; order-typed remains +UNDETERMINED. Worker did not rerun them. Corrected complete_B remains unexecuted. +Old native/full successes confer no new-S acceptance or credit. + + +REPAIR48 current source status: see [REPAIR48_STATUS.md](REPAIR48_STATUS.md). Earlier run directions and successes below are historical; they grant no P04 credit. + ## RUN47 harness repair; original unit remains unaccepted Q46 S4 failed before engine startup: `AssertionError: complete 316-script parse roster`. @@ -11,7 +80,7 @@ reuse instructions. Immutable spec, REQUIRED/REACH_REFS, product, caps, denomina permissions and historical raw are unchanged. Option B: Root freezes new final Q, then fresh all-series runs once; no receipt rewriting or reuse adopter. -# P04-01 order audit — repair31 +# Historical P04-01 order audit — repair31 Formal status is **16/88, P04 credit 0**. Policy approvals are recorded; implementation and exact-Q evidence remain incomplete. No original-unit completion is claimed. diff --git a/docs/plans/original-completion-2026-10-02/execution/p04-01/REPAIR48_HISTORICAL_ROOT_Q47_ACTUAL_INDEX_GENERATION.log b/docs/plans/original-completion-2026-10-02/execution/p04-01/REPAIR48_HISTORICAL_ROOT_Q47_ACTUAL_INDEX_GENERATION.log new file mode 100644 index 0000000..96d9009 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p04-01/REPAIR48_HISTORICAL_ROOT_Q47_ACTUAL_INDEX_GENERATION.log @@ -0,0 +1,14 @@ +Traceback (most recent call last): + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p04-01/P04-01-implement/docs/plans/original-completion-2026-10-02/execution/p04-01/build_p04_index.py", line 159, in + main() + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p04-01/P04-01-implement/docs/plans/original-completion-2026-10-02/execution/p04-01/build_p04_index.py", line 141, in main + index = payload(args.build, gate) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p04-01/P04-01-implement/docs/plans/original-completion-2026-10-02/execution/p04-01/build_p04_index.py", line 37, in payload + raw = gate.combine_native_series(build, c) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p04-01/P04-01-implement/tools/check_p04_order_evidence.py", line 1150, in combine_native_series + require({k: v for k, v in recorded.items() if k != 'verifier_sha256'} == actual, 'fresh raw recomputation drift') + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p04-01/P04-01-implement/tools/check_p04_order_evidence.py", line 97, in require + raise ValueError(message) +ValueError: fresh raw recomputation drift diff --git a/docs/plans/original-completion-2026-10-02/execution/p04-01/REPAIR48_HISTORICAL_ROOT_Q47_ACTUAL_MATERIAL_ADMISSION_FAILURE.json b/docs/plans/original-completion-2026-10-02/execution/p04-01/REPAIR48_HISTORICAL_ROOT_Q47_ACTUAL_MATERIAL_ADMISSION_FAILURE.json new file mode 100644 index 0000000..5331267 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p04-01/REPAIR48_HISTORICAL_ROOT_Q47_ACTUAL_MATERIAL_ADMISSION_FAILURE.json @@ -0,0 +1,53 @@ +{ + "S": "2cd734062a2226b5006bbecf96e6024a26982665", + "checker_sha256": "3bb0cde776bc295f6f18e74f1e23bf3d832d8e4f71aed260601c82d287c655fd", + "actual_function": "supplied_file", + "source_call_site": "build_p04_index.payload lines 50-55 calls descriptor of actual runner fixed paths then supplied_file on all those paths", + "scope": "narrow pure actual material admission only; NOT complete checker/index or engine execution", + "rows": [ + { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p04-01/.runtime/P04-01/build/audit-support/p04-fresh-context-r47/docs/plans/original-completion-2026-10-02/execution/p04-01/s4/p04_s4_power_probe.gd", + "admitted": false, + "error": "unsupplied external material: /Users/korizatou114/Projects/TheTree-managed-worktrees/p04-01/.runtime/P04-01/build/audit-support/p04-fresh-context-r47/docs/plans/original-completion-2026-10-02/execution/p04-01/s4/p04_s4_power_probe.gd" + }, + { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p04-01/.runtime/P04-01/build/audit-support/p04-fresh-context-r47/docs/plans/original-completion-2026-10-02/execution/p04-01/s4/run_s4_native.py", + "admitted": false, + "error": "unsupplied external material: /Users/korizatou114/Projects/TheTree-managed-worktrees/p04-01/.runtime/P04-01/build/audit-support/p04-fresh-context-r47/docs/plans/original-completion-2026-10-02/execution/p04-01/s4/run_s4_native.py" + }, + { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p04-01/.runtime/P04-01/build/audit-support/p04-fresh-context-r47/docs/plans/original-completion-2026-10-02/execution/p04-01/s4/S4_ROOT_RUN.md", + "admitted": false, + "error": "unsupplied external material: /Users/korizatou114/Projects/TheTree-managed-worktrees/p04-01/.runtime/P04-01/build/audit-support/p04-fresh-context-r47/docs/plans/original-completion-2026-10-02/execution/p04-01/s4/S4_ROOT_RUN.md" + }, + { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p04-01/P04-01-root-q-r47-2cd73406/tests/transport/test_runtime_transport.gd", + "admitted": false, + "error": "unsupplied external material: /Users/korizatou114/Projects/TheTree-managed-worktrees/p04-01/P04-01-root-q-r47-2cd73406/tests/transport/test_runtime_transport.gd" + }, + { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p04-01/P04-01-root-q-r47-2cd73406/tests/staff/test_rescue_elevator.gd", + "admitted": false, + "error": "unsupplied external material: /Users/korizatou114/Projects/TheTree-managed-worktrees/p04-01/P04-01-root-q-r47-2cd73406/tests/staff/test_rescue_elevator.gd" + }, + { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p04-01/P04-01-root-q-r47-2cd73406/docs/plans/original-completion-2026-10-02/execution/completion_marker_contracts.json", + "admitted": false, + "error": "unsupplied external material: /Users/korizatou114/Projects/TheTree-managed-worktrees/p04-01/P04-01-root-q-r47-2cd73406/docs/plans/original-completion-2026-10-02/execution/completion_marker_contracts.json" + }, + { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p04-01/.runtime/P04-01/build/audit-support/p04-fresh-context-r47/docs/plans/original-completion-2026-10-02/execution/p04-01/s5/run_s5_native.py", + "admitted": false, + "error": "unsupplied external material: /Users/korizatou114/Projects/TheTree-managed-worktrees/p04-01/.runtime/P04-01/build/audit-support/p04-fresh-context-r47/docs/plans/original-completion-2026-10-02/execution/p04-01/s5/run_s5_native.py" + }, + { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p04-01/.runtime/P04-01/build/audit-support/p04-fresh-context-r47/docs/plans/original-completion-2026-10-02/execution/p04-01/s4/p04_s4_power_probe.gd", + "admitted": false, + "error": "unsupplied external material: /Users/korizatou114/Projects/TheTree-managed-worktrees/p04-01/.runtime/P04-01/build/audit-support/p04-fresh-context-r47/docs/plans/original-completion-2026-10-02/execution/p04-01/s4/p04_s4_power_probe.gd" + } + ], + "rejected": 8, + "full184_status": "still running; retain without restarting", + "formal_acceptance": false, + "at_unix_ns": 1792318056557763000 +} diff --git a/docs/plans/original-completion-2026-10-02/execution/p04-01/REPAIR48_STATIC_INSPECTION.json b/docs/plans/original-completion-2026-10-02/execution/p04-01/REPAIR48_STATIC_INSPECTION.json new file mode 100644 index 0000000..50bafee --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p04-01/REPAIR48_STATIC_INSPECTION.json @@ -0,0 +1,88 @@ +{ + "task_id": "P04-01", + "kind": "static inspection only; no tests executed", + "syntax": [ + "build_p04_index.py", + "p04_native_series.py", + "full_suite_verifier.py", + "collect_p04_native.py", + "s5/s5_order_adapter.py", + "s5/s5_power_adapter.py", + "repair48_transport_controls.py", + "repair48_identity_controls.py" + ], + "source_sha256": { + "build_p04_index.py": "35b1b35f94e64f0f8c93ad5de17b35a16c2a81ca802691ba77251ad4256ca515", + "p04_native_series.py": "c33f8abb7f4ad143f75a1b761447a84afddb2dd0ac67b782e4cf9a8a67b67e4a", + "full_suite_verifier.py": "779ab0c0b5be31dcee462f04cbd6b765d44f9bef95fb52b03d3b676ec9f80c9c", + "collect_p04_native.py": "70a12149c770ef4dca97d3d5aa0b59270cf1547efde79ee7346ba340e1bebca6", + "s5/s5_order_adapter.py": "91344410b3441049fbce316cef9c227c9355747ae56890b45fcf348dac401d7e", + "s5/s5_power_adapter.py": "41d33e8d6b4e986611bdf7a0eedbde3f0b92f724ea37d3b2502ba4965a298462", + "repair48_transport_controls.py": "b2df097bc20bde89a7a738d4c1fe855bfa0bd1ac82a12936aa2b106980685628", + "repair48_identity_controls.py": "1c4f81e13715a2ab4b73b633265d3279772a3a8a90115e78098f0ecbd895d9ef" + }, + "engine_runs": 0, + "git_writes": 0, + "runner_actions": 0, + "immutable": [ + { + "path": "tools/check_p04_order_evidence.py", + "sha256": "3bb0cde776bc295f6f18e74f1e23bf3d832d8e4f71aed260601c82d287c655fd", + "matches_repair47_record": true + }, + { + "path": "docs/spec/acceptance/P04-01.json", + "sha256": "d28aadb044633f7d804de5a92c8d4c4a7438dfbf44c3243dca978951f4def25f", + "matches_repair47_record": true + }, + { + "path": "docs/plans/original-completion-2026-10-02/execution/p04-01/s4/historical/run_s4_native_r28.py.reference", + "sha256": "2d3be39d2b310abac058e27336ac816c234043a0a1dd7b2c52d84994907dd31b", + "matches_repair47_record": true + } + ], + "historical_failure_copies": [ + { + "name": "ROOT_Q47_ACTUAL_INDEX_GENERATION.log", + "byte_identical": true, + "sha256": "0250e523aeeecde5d81d298e30cd7e4e18a5415ac4e762401697256be6d514f9" + }, + { + "name": "ROOT_Q47_ACTUAL_MATERIAL_ADMISSION_FAILURE.json", + "byte_identical": true, + "sha256": "a86b93150c33620854938c040f57db49e5627171f8f0633b399c527b7c08ec55" + } + ], + "status": "blocked", + "specification_version_gap": { + "contract_sha256": "9ec722e7dfb0bee178d291624a026420c08412574e238bba1fde012c7a6f7881", + "actual_sha256": "d28aadb044633f7d804de5a92c8d4c4a7438dfbf44c3243dca978951f4def25f", + "specification_modified": false + }, + "tests_executed": [], + "historical_test_results_reused": [], + "changed_source_files": [ + "build_p04_index.py", + "p04_native_series.py", + "full_suite_verifier.py", + "collect_p04_native.py", + "s5/s5_order_adapter.py", + "s5/s5_power_adapter.py", + "repair48_transport_controls.py", + "repair48_identity_controls.py" + ], + "changed_documentation": [ + "REPAIR48_STATUS.md", + "REPAIR48_STATIC_INSPECTION.json", + "REPAIR48_HISTORICAL_ROOT_Q47_ACTUAL_INDEX_GENERATION.log", + "REPAIR48_HISTORICAL_ROOT_Q47_ACTUAL_MATERIAL_ADMISSION_FAILURE.json", + "ORDER_AUDIT.md", + "CURRENT_STATUS.md", + "s1/S1_ROOT_RUN.md", + "s2/S2_ROOT_RUN.md", + "s2b/S2B_ROOT_RUN.md", + "s3/S3_ROOT_RUN.md", + "s4/S4_ROOT_RUN.md", + "s5/S5_ROOT_RUN.md" + ] +} diff --git a/docs/plans/original-completion-2026-10-02/execution/p04-01/REPAIR48_STATUS.md b/docs/plans/original-completion-2026-10-02/execution/p04-01/REPAIR48_STATUS.md new file mode 100644 index 0000000..e5901cd --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p04-01/REPAIR48_STATUS.md @@ -0,0 +1,160 @@ +## REPAIR49 current correction + +Source-ready only; original 30/88, formal 16, P04=0, no partial credit. +REPAIR48's specification-mismatch blocker below is historical and corrected: +the immutable 7000-byte original has SHA256 +d28aadb044633f7d804de5a92c8d4c4a7438dfbf44c3243dca978951f4def25f; +removing its single EOF LF gives +9ec722e7dfb0bee178d291624a026420c08412574e238bba1fde012c7a6f7881. +This is the existing Git/Runner strip/checker one-EOF-LF pin contract. +No specification, approval or normalization change. Older contradictory wording +below is superseded history, including blanket full-reuse prohibitions and +all-controls-unexecuted wording. Q47 admission/index failures remain failures. +See REPAIR49_STATUS.md for closure audit and verbatim complete_B FileNotFoundError. +Root handoff reports payload(B), all53, series/join/power PASS; order-typed remains +UNDETERMINED. Worker did not rerun them. Corrected complete_B remains unexecuted. +Old native/full successes confer no new-S acceptance or credit. + + +# REPAIR48 implementation status + +BLOCKED on exact specification-version context; source changes are retained for +review. No acceptance or new credit is claimed. +Original scope remains 30/88; formal credit is 16; P04 credit is 0. +Engine runs, Git writes, Runner actions and delegation are prohibited. + +The supplied task contract declares spec_sha256 +`9ec722e7dfb0bee178d291624a026420c08412574e238bba1fde012c7a6f7881`. +The actual immutable docs/spec/acceptance/P04-01.json hashes to +`d28aadb044633f7d804de5a92c8d4c4a7438dfbf44c3243dca978951f4def25f`. +That local hash agrees with REPAIR47_STATIC_CHECKS.json. This worker has not +changed the specification or selected a replacement authority. Root must resolve +which exact specification bytes govern the retained repair before gate use. +This is an exact-version context gap, not a proposed acceptance change. + +## Current changes + +`build_p04_index.py` separates exclusive generation (`relocate_materials`) from +read-only `payload`. The exact output is resolved B/p04-evidence, with no existing +output, traversal or parent symlinks. Fixed pins plus QA are checked for exact +duplicates and conflicting identities, including across series. Copies are +content-addressed under the first referencing series, created exclusively, and +rehashed. Exact (original path, bytes, SHA) identities share one copy across all +series; different original paths are never silently merged. RELOCATION.json +keeps original pin paths as keys. Raw inputs are never rewritten. Every payload +call checks map membership, declared relative form, hashes, unmapped files and +exactly one wrapper candidate. Materials and wrapper descriptors are relative; +the relocation-map SHA is included in the index. The obsolete absolute material +admission pre-check is removed. Main relocates, derives, checks refs and roles, +then writes index and the separate invocation receipt. Failure leaves a failed +output attempt without a usable index; an existing output cannot be resumed. + +S5 dependency identity uses the package-relative power, series and guard module +paths. Each module is read once and those same bytes are compiled and executed, +without cached bytecode. Symlinks, outside dependencies and mismatched mappings +are rejected. The roster is checked against the modules loaded. Dependency maps +are checked against the executed roster before deriving facts. Absolute observed +paths and checkout are retained in collection/dependency-invocation.json, outside +the compared s5.json and the collection manifest's series mapping. The adapter's +own observed path and executed-byte SHA are also retained there. + +## Static path audit + +| Value | Result and required context | +| --- | --- | +| fixed pins and QA | Source placement is free-form. Generation reads original pinned paths; verification admits relocated relative copies under B/p04-evidence. | +| wrapper | Exactly one distinct original pin path must match wrapper_sha256; descriptor uses that relocated copy. | +| runner-input row | Absolute path is constructed from the current B and the registered series run. supplied_file admits each registered run root. No earlier Root B is embedded by the builder. | +| C references | Constructed under current B/audit-support/native-first-current, one of supplied_file's fixed roots. | +| native_bundle | Same fixed native-first-current root under the supplied B. | +| authorities | ROOT-relative source paths, resolved against the invocation's gate.ROOT. | +| native and full raw references | Relative to each retained run/B, with original provenance retained. No analysis checkout is used as a payload identity. | +| S1–S4 / verify_fresh_* | Shared implementations in p04_native_series.py; no separate checkout-keyed dependency maps. Current metadata modules are found via __file__; that path is not returned as a fresh fact. Fresh wrapper loading now executes source bytes directly. | +| S5 adapters | Checkout-keyed dependency map corrected. Raw hash keys refer to the immutable raw input, not the analysis checkout. Explicit raw root is resolved before writer/reader references are formed. | +| readers | Independent Reader data is validated from raw run-relative references and recorded original provenance. bulk_reader_equivalence.py is a fixture using explicit scratch checkouts, not a production payload producer. | +| full_suite_verifier | Explicit Q root and retained run are inputs. Its reference map uses run-relative names. Metadata module loading now executes source bytes directly. | +| scratch_fixture_adapter | Explicit scratch routing only; no production compared payload. | + +Transport does not make the entire B portable by itself. FreshSeries still +requires original Q source paths/project_root, the retained stage/formal copies, +and the exact engine file for identity reads (no engine launch). full-suite +verification also reads its recorded actual Q. If a later invocation changes B, +the registry/run hierarchy and these original-source contexts must still be +supplied. Missing context is a blocker; do not rewrite raw pins or the checker +to conceal it. Static supplied_file inspection found no additional absolute +descriptor admission gap in the builder's rows above. Runtime admission has +not been claimed. + +## Historical failures and successes + +The Q47 material admission failure is preserved verbatim in +REPAIR48_HISTORICAL_ROOT_Q47_ACTUAL_MATERIAL_ADMISSION_FAILURE.json. +All eight recorded attempts failed with their original `unsupplied external +material: ...` messages. The index generation traceback is preserved verbatim +in REPAIR48_HISTORICAL_ROOT_Q47_ACTUAL_INDEX_GENERATION.log, ending: + +```text +ValueError: fresh raw recomputation drift +``` + +These are failures, not passing receipts. Original raw and historical receipts +remain unchanged. Their retained source is +build/owner-handoff/p04-after-p26-closure-r01/repair48-final-index-transport. + +Root actually staged the S47 context under p04-fresh-context-r47, deviating from +the fixed p04-fresh-context name in the pre-REPAIR48 S5_ROOT_RUN.md line 167. +The old direction is retained as history. Material placement is now free-form +for builder relocation; no historical receipt is renamed or adopted. + +Q47 native successes and the historical full 184 result (21903 checks, zero +reported failures, 329 parse paths, 186 ended PIDs, no guard/cleanup failures) +remain historical only. They are not C and cannot be reused under the new S. +The immutable checker still binds M/S/Q_tree; no adopter is introduced. + +## Verification handoff + +The worker performed syntax parsing and static source/path inspection only. +Per the final worker instruction that tests are formally executed by Runner, +no pure control, check-only plan, registered checker or engine was executed. +No result is inferred from a historical test count. No unaffected pure result +is reused without a complete code/dependency SHA proof; none is claimed here. + +Runner controls added: + +- repair48_transport_controls.py --retained + checks the real immutable S47 inputs/copies, r47 context and out-of-B Q pins, + relocation repeatability, duplicate/conflict rules, material adversaries, + wrapper failures, and the actual checker's old-S/new-S binding rejection + using simulated Git observations without Git writes. +- repair48_identity_controls.py --raw --writer-sha + --reader-sha --build checks independent + same-byte complete analysis directories (S5 results and builder payload), + dependency mutations and mappings, symlinks, + outside paths, two read-only payload calls and unchanged B tree, index drift, + and external absolute descriptor rejection. The optional B section must be + supplied for the complete control, not omitted as an implicit pass. + +All these controls remain UNEXECUTED. Required affected existing controls and +fresh check-only S1/S2a/S2b/S3/S4/S5 plans also remain Runner work. A dirty-only +failure has not been observed and is not invented. Source-ready is not a gate +pass. Runner must verify full negative coverage, including exclusive output, +pin-SHA mismatch and ambiguous wrapper bindings, before the native lease. + +## Normal-gate material roster and Root order + +Supply the exact B with native-first-current, historical relocation inputs, +fresh-run registry, every fresh run's runner-input/ended/source/UID/formal/raw +and lifecycle receipts, the exact recorded Q source and engine identity context; +B/p04-evidence/runner-materials with all pin copies and RELOCATION.json; +the matching fresh collection including MANIFEST and separate dependency +invocation record; and the matching full 184 run and its binding/raw receipts. +The final index and generation-invocation receipt belong to this same attempt. +Required original authorities and sources must exist in the frozen checkout. + +Root's next order is unchanged: freeze new Q; affected pure controls; clean +exact-Q check-only; capacity/PID-end checks; one heavy native lease for +S1/S2a/S2b/S3/S4 and all ten S5 cases; readers/adapters; collect 15 EV and all +subclauses; full 184 once; index generation with relocation; registered +p04-acceptance once (no duplicate Root --verify-only); separate Opus whole-unit +review; normal prepare/C/integration/final/Root DB join/ledger/main push. +Only whole-unit acceptance can grant credit. diff --git a/docs/plans/original-completion-2026-10-02/execution/p04-01/REPAIR49_PROTECTED_SHA.json b/docs/plans/original-completion-2026-10-02/execution/p04-01/REPAIR49_PROTECTED_SHA.json new file mode 100644 index 0000000..37bfa7e --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p04-01/REPAIR49_PROTECTED_SHA.json @@ -0,0 +1,41 @@ +{ + "before": { + "build_p04_index.py": "35b1b35f94e64f0f8c93ad5de17b35a16c2a81ca802691ba77251ad4256ca515", + "p04_native_series.py": "c33f8abb7f4ad143f75a1b761447a84afddb2dd0ac67b782e4cf9a8a67b67e4a", + "full_suite_verifier.py": "779ab0c0b5be31dcee462f04cbd6b765d44f9bef95fb52b03d3b676ec9f80c9c", + "collect_p04_native.py": "70a12149c770ef4dca97d3d5aa0b59270cf1547efde79ee7346ba340e1bebca6", + "s5/s5_order_adapter.py": "91344410b3441049fbce316cef9c227c9355747ae56890b45fcf348dac401d7e", + "s5/s5_power_adapter.py": "41d33e8d6b4e986611bdf7a0eedbde3f0b92f724ea37d3b2502ba4965a298462", + "s5/s5_guard_oracle.py": "b58ee46f5c8a82de796bffd88ff8cab89f1f9e7e5c9417414310a1b649dc6c1c", + "s5/s5_order_adapter_controls.py": "f1f90b9847830c6505a176bf78442e619b1d297c818ec561c92c498a4db74b53", + "s5/s5_power_adapter_controls.py": "32d71db80994052b905829e6a2da38448ae789825c44570a901e67fe2d07fd33" + }, + "root_expected": { + "build_p04_index.py": "35b1b35f94e64f0f8c93ad5de17b35a16c2a81ca802691ba77251ad4256ca515", + "p04_native_series.py": "c33f8abb7f4ad143f75a1b761447a84afddb2dd0ac67b782e4cf9a8a67b67e4a", + "full_suite_verifier.py": "779ab0c0b5be31dcee462f04cbd6b765d44f9bef95fb52b03d3b676ec9f80c9c", + "collect_p04_native.py": "70a12149c770ef4dca97d3d5aa0b59270cf1547efde79ee7346ba340e1bebca6", + "s5/s5_order_adapter.py": "91344410b3441049fbce316cef9c227c9355747ae56890b45fcf348dac401d7e", + "s5/s5_power_adapter.py": "41d33e8d6b4e986611bdf7a0eedbde3f0b92f724ea37d3b2502ba4965a298462", + "s5/s5_guard_oracle.py": "b58ee46f5c8a82de796bffd88ff8cab89f1f9e7e5c9417414310a1b649dc6c1c", + "s5/s5_order_adapter_controls.py": "f1f90b9847830c6505a176bf78442e619b1d297c818ec561c92c498a4db74b53", + "s5/s5_power_adapter_controls.py": "32d71db80994052b905829e6a2da38448ae789825c44570a901e67fe2d07fd33" + }, + "after": { + "build_p04_index.py": "35b1b35f94e64f0f8c93ad5de17b35a16c2a81ca802691ba77251ad4256ca515", + "p04_native_series.py": "c33f8abb7f4ad143f75a1b761447a84afddb2dd0ac67b782e4cf9a8a67b67e4a", + "full_suite_verifier.py": "779ab0c0b5be31dcee462f04cbd6b765d44f9bef95fb52b03d3b676ec9f80c9c", + "collect_p04_native.py": "70a12149c770ef4dca97d3d5aa0b59270cf1547efde79ee7346ba340e1bebca6", + "s5/s5_order_adapter.py": "91344410b3441049fbce316cef9c227c9355747ae56890b45fcf348dac401d7e", + "s5/s5_power_adapter.py": "41d33e8d6b4e986611bdf7a0eedbde3f0b92f724ea37d3b2502ba4965a298462", + "s5/s5_guard_oracle.py": "b58ee46f5c8a82de796bffd88ff8cab89f1f9e7e5c9417414310a1b649dc6c1c", + "s5/s5_order_adapter_controls.py": "f1f90b9847830c6505a176bf78442e619b1d297c818ec561c92c498a4db74b53", + "s5/s5_power_adapter_controls.py": "32d71db80994052b905829e6a2da38448ae789825c44570a901e67fe2d07fd33" + }, + "unchanged": true, + "parse": "pass", + "tests_run": false, + "additional_protected": { + "s5/run_s5_native.py": "28d54f061a9a07ee7ab12e043170ae43760bb686354b1c682166e82d04ec35b3" + } +} diff --git a/docs/plans/original-completion-2026-10-02/execution/p04-01/REPAIR49_STATUS.md b/docs/plans/original-completion-2026-10-02/execution/p04-01/REPAIR49_STATUS.md new file mode 100644 index 0000000..28b1881 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p04-01/REPAIR49_STATUS.md @@ -0,0 +1,225 @@ +## REPAIR49 current correction + +Source-ready only; original 30/88, formal 16, P04=0, no partial credit. +REPAIR48's specification-mismatch blocker below is historical and corrected: +the immutable 7000-byte original has SHA256 +d28aadb044633f7d804de5a92c8d4c4a7438dfbf44c3243dca978951f4def25f; +removing its single EOF LF gives +9ec722e7dfb0bee178d291624a026420c08412574e238bba1fde012c7a6f7881. +This is the existing Git/Runner strip/checker one-EOF-LF pin contract. +No specification, approval or normalization change. Older contradictory wording +below is superseded history, including blanket full-reuse prohibitions and +all-controls-unexecuted wording. Q47 admission/index failures remain failures. +See REPAIR49_STATUS.md for closure audit and verbatim complete_B FileNotFoundError. +Root handoff reports payload(B), all53, series/join/power PASS; order-typed remains +UNDETERMINED. Worker did not rerun them. Corrected complete_B remains unexecuted. +Old native/full successes confer no new-S acceptance or credit. + + +## REPAIR49 full184 conditional reuse candidate — all conditions UNVERIFIED + +Native reuse is forbidden: all six series require fresh M/S/Q_tree provenance +(p04_native_series.py:1287; checker:370). Full uses the existing separate binding +(checker:1175-1186); no adopter or checker change is authorized. +The following are requirements, not results or approval: + +1. New S5 source_before must equal old full selected_source_map: all 1369 keys + and SHA values, not counts alone. +2. Old project_root must remain unchanged: source-start == current source_refs + == post-verification source_refs (full_suite_verifier.py:115). +3. selected_source_map, roster184, parse329, settings, runner/marker module, + marker contract, suite-policy and UID plan/stage must all match (116-152,225). +4. inputs.engine must match current engine_pin (124-125). +5. Revalidate every phase PID, cleanup, marker and diagnostics (154-228). +6. Current s5/run_s5_native.py and full_suite_verifier.py SHA must equal the + Root rehearsal versions. +7. Never relabel old S/oldQ/project_root/PIDs/time. Describe reuse only as + revalidating the exact-source-identical old full through the existing + full_suite route; never claim full ran on new S. +8. A separate Opus whole-unit review must independently confirm applicability. + +Conditions 1–6 require actual checks after final freeze. If any predicate is +unproved or differs, reject reuse and execute full184 once on the final version. +SourceRefs (tools/run_all_tests.py:40-45) excludes docs/private package, but that +fact is no substitute for complete source equality. No reuse is approved here. + + +# REPAIR49 source-ready status + +Original 30/88, formal 16, P04=0; no partial credit or whole-unit acceptance. +Worker static audit/parse only; all new controls remain Runner work. + +## Explicit closure audit + +All .py files are explicitly enumerated in CLOSURE, plus the six probe .gd files +and six ROOT_RUN documents used by package-local runner material references. +The list is fixed in source; a missing member cannot vanish through globbing. +No package-local JSON is read by the identity execution path: JSON inputs are +supplied B/raw/recorded Q. These external contexts remain required, not rewritten. +The original checker is loaded from the original checkout and supplied to both builders. + +- `build_p04_index.py:46`: `path = Path(__file__).with_name('p04_native_series.py')` +- `build_p04_index.py:184`: `series_spec = importlib.util.spec_from_file_location('p04_index_series', Path(__file__).with_name('p04_native_series.py'))` +- `checker_join_fixtures.py:111`: `current_wrapper = series.digest((series.HERE / 's4/run_s4_native.py').read_bytes())` +- `full_suite_verifier.py:111`: `wrapper = module('p04_full_uid', Path(__file__).parent / 's5/run_s5_native.py')` +- `normal_c_join_fixtures.py:12`: `spec = importlib.util.spec_from_file_location("normal_c_join", HERE / "normal_c_join.py")` +- `p04_native_series.py:1001`: `S4_HISTORICAL_WRAPPER = HERE / 's4/historical/run_s4_native_r28.py.reference'` +- `p04_native_series.py:1013`: `require(receipt_sha256 == digest((HERE / 's4/run_s4_native.py').read_bytes()),` +- `p04_native_series.py:1035`: `qa = HERE / 's4/p04_s4_power_probe.gd'` +- `p04_native_series.py:1332`: `wrapper_path = Path(__file__).parent / 's5/run_s5_native.py'` +- `p04_native_series.py:1340`: `admission = wrapper.module('fresh_s4_admission', HERE / 's4/run_s4_native.py')` +- `p04_native_series.py:1432`: `path = Path(__file__).parent / 's5/s5_order_adapter.py'` +- `repair48_identity_controls.py:38`: `CLOSURE = ('build_p04_index.py', 'bulk_reader_equivalence.py', 'checker_applicability_fixtures.py', 'checker_approval_fixtures.py', 'checker_candidate_fixtures.py', 'checker_encoder_fixtures.py', 'checker_join_fixtures.py', 'checker_native_fixtures.py', 'checker_negative_fixtures.py', 'checker_role_fixtures.py', 'checker_series_fixtures.py', 'collect_p04_native.py', 'full_suite_verifier.py', 'normal_c_join.py', 'normal_c_join_fixtures.py', 'p04_native_series.py', 'repair48_identity_controls.py', 'repair48_transport_controls.py', 's1/S1_ROOT_RUN.md', 's1/p04_s1_ev_power_probe.gd', 's1/run_s1_native.py', 's2/S2_ROOT_RUN.md', 's2/p04_s2a_midnight_probe.gd', 's2/run_s2a_native.py', 's2b/S2B_ROOT_RUN.md', 's2b/p04_s2b_shift_probe.gd', 's2b/run_s2b_native.py', 's3/S3_ROOT_RUN.md', 's3/p04_s3_closure_probe.gd', 's3/run_s3_native.py', 's4/S4_ROOT_RUN.md', 's4/admission_controls.py', 's4/engine_identity_negative_fixtures.py', 's4/p04_s4_power_probe.gd', 's4/phase_cut_regression.py', 's4/receipt_lifecycle_fixtures.py', 's4/run_s4_native.py', 's5/S5_ROOT_RUN.md', 's5/p04_s5_power_probe.gd', 's5/repair44_controls.py', 's5/run_s5_native.py', 's5/s5_guard_oracle.py', 's5/s5_order_adapter.py', 's5/s5_order_adapter_controls.py', 's5/s5_power_adapter.py', 's5/s5_power_adapter_controls.py', 's5/s5_uid_controls.py', 's5/s5_wrapper_fixtures.py', 'scratch_fixture_adapter.py')` +- `repair48_identity_controls.py:71`: `shutil.copyfile(HERE / relative, target)` +- `repair48_identity_controls.py:86`: `original_builder = load(HERE / 'build_p04_index.py', 'original_builder')` +- `repair48_identity_controls.py:125`: `rejects(lambda: a.module('outside_identity', HERE / 's5/s5_guard_oracle.py'))` +- `repair48_identity_controls.py:128`: `builder = load(HERE / 'build_p04_index.py', 'identity_builder')` +- `repair48_transport_controls.py:14`: `spec = importlib.util.spec_from_file_location('transport', Path(__file__).with_name('build_p04_index.py'))` +- `s1/run_s1_native.py:20`: `QA = HERE / "p04_s1_ev_power_probe.gd"` +- `s1/run_s1_native.py:61`: `shared = module("fresh_q_shared", HERE.parent / "s5/run_s5_native.py")` +- `s1/run_s1_native.py:89`: `QA, Path(__file__), HERE / "S1_ROOT_RUN.md",` +- `s1/run_s1_native.py:119`: `fixed.append(pin(HERE.parent / "s5/run_s5_native.py"))` +- `s2/run_s2a_native.py:20`: `QA = HERE / "p04_s2a_midnight_probe.gd"` +- `s2/run_s2a_native.py:33`: `]] + [HERE.parent / "s1" / n for n in ["run_s1_native.py", "p04_s1_ev_power_probe.gd", "S1_ROOT_RUN.md"]]` +- `s2/run_s2a_native.py:82`: `shared = module("fresh_q_shared", HERE.parent / "s5/run_s5_native.py")` +- `s2/run_s2a_native.py:111`: `QA, Path(__file__), HERE / "S2_ROOT_RUN.md",` +- `s2/run_s2a_native.py:141`: `fixed.append(pin(HERE.parent / "s5/run_s5_native.py"))` +- `s2b/run_s2b_native.py:20`: `QA = HERE / "p04_s2b_shift_probe.gd"` +- `s2b/run_s2b_native.py:25`: `HERE.parent / folder / name for folder, name in [` +- `s2b/run_s2b_native.py:26`: `("s1", "run_s1_native.py"), ("s1", "S1_ROOT_RUN.md"),` +- `s2b/run_s2b_native.py:28`: `("s2", "S2_ROOT_RUN.md"),` +- `s2b/run_s2b_native.py:71`: `shared = module("fresh_q_shared", HERE.parent / "s5/run_s5_native.py")` +- `s2b/run_s2b_native.py:102`: `QA, Path(__file__), HERE / "S2B_ROOT_RUN.md",` +- `s2b/run_s2b_native.py:132`: `fixed.append(pin(HERE.parent / "s5/run_s5_native.py"))` +- `s3/run_s3_native.py:20`: `QA = HERE / "p04_s3_closure_probe.gd"` +- `s3/run_s3_native.py:31`: `MATERIALS = [MANIFEST, AUDIT, HERE.parent / "s2b/run_s2b_native.py",` +- `s3/run_s3_native.py:32`: `HERE.parent / "s2b/p04_s2b_shift_probe.gd", HERE.parent / "s2b/S2B_ROOT_RUN.md"]` +- `s3/run_s3_native.py:90`: `shared = module("fresh_q_shared", HERE.parent / "s5/run_s5_native.py")` +- `s3/run_s3_native.py:121`: `QA, Path(__file__), HERE / "S3_ROOT_RUN.md",` +- `s3/run_s3_native.py:151`: `fixed.append(pin(HERE.parent / "s5/run_s5_native.py"))` +- `s4/admission_controls.py:99`: `series = s4.module('admission_series', s4.HERE.parent / 'p04_native_series.py')` +- `s4/admission_controls.py:100`: `series_tree = ast.parse((s4.HERE.parent / 'p04_native_series.py').read_text())` +- `s4/admission_controls.py:105`: `wrapper = s4.module('admission_fresh_wrapper', s4.HERE.parent / 's5/run_s5_native.py')` +- `s4/admission_controls.py:124`: `historical = s4.HERE / 'historical/run_s4_native_r28.py.reference'` +- `s4/admission_controls.py:134`: `uid_plan, snapshot, _ = s4.module('admission_uid', s4.HERE.parent / 's5/run_s5_native.py').load_uid_helper(root, r, selected)` +- `s4/engine_identity_negative_fixtures.py:12`: `spec = importlib.util.spec_from_file_location("series", HERE.parent / "p04_native_series.py")` +- `s4/engine_identity_negative_fixtures.py:15`: `spec = importlib.util.spec_from_file_location("s4", HERE / "run_s4_native.py")` +- `s4/receipt_lifecycle_fixtures.py:36`: `s4 = load('receipt_s4_historical', HERE / 'historical/run_s4_native_r28.py.reference')` +- `s4/receipt_lifecycle_fixtures.py:38`: `series = load('receipt_series', HERE.parent / 'p04_native_series.py')` +- `s4/receipt_lifecycle_fixtures.py:42`: `tree = ast.parse((HERE.parent / 'p04_native_series.py').read_text())` +- `s4/receipt_lifecycle_fixtures.py:97`: `put(staged / 'run_s4_native.py', (HERE / 'historical/run_s4_native_r28.py.reference').read_bytes())` +- `s4/receipt_lifecycle_fixtures.py:98`: `put(staged / 'S4_ROOT_RUN.md', b'synthetic fixture material\n')` +- `s4/run_s4_native.py:21`: `QA = HERE / "p04_s4_power_probe.gd"` +- `s4/run_s4_native.py:136`: `shared = module("fresh_q_shared", HERE.parent / "s5/run_s5_native.py")` +- `s4/run_s4_native.py:177`: `QA, Path(__file__), HERE / "S4_ROOT_RUN.md",` +- `s4/run_s4_native.py:214`: `fixed.append(pin(HERE.parent / "s5/run_s5_native.py"))` +- `s4/run_s4_native.py:365`: `# The shared runner log is not write-once; see S4_ROOT_RUN.md.` +- `s5/repair44_controls.py:148`: `for name in ('S5_ROOT_RUN.md', 'PENDING.md'):` +- `s5/run_s5_native.py:26`: `QA = HERE / "p04_s5_power_probe.gd"` +- `s5/run_s5_native.py:33`: `matches = re.findall(r"^const CASE_TABLE: Dictionary = (\{.*?^\})", Path(path).read_text(), re.M | re.S)` +- `s5/run_s5_native.py:45`: `CASE_TABLE = case_table(QA)` +- `s5/run_s5_native.py:77`: `if len(seeds) != 1 or sorted(json.loads(seeds[0])) != CASES or sorted(case_table(QA)) != CASES:` +- `s5/run_s5_native.py:334`: `QA, Path(__file__), HERE / "S5_ROOT_RUN.md",` +- `s5/run_s5_native.py:527`: `# The shared runner log is not write-once; see S5_ROOT_RUN.md.` +- `s5/s5_order_adapter.py:46`: `POWER_PATH = Path(__file__).with_name('s5_power_adapter.py')` +- `s5/s5_order_adapter.py:50`: `GUARD_PATH = Path(__file__).with_name('s5_guard_oracle.py')` +- `s5/s5_order_adapter_controls.py:12`: `mutation = a.module('order_typed_mutation', Path(__file__).with_name('s5_power_adapter_controls.py'))` +- `s5/s5_power_adapter_controls.py:12`: `spec = importlib.util.spec_from_file_location("s5_power_adapter", Path(__file__).with_name("s5_power_adapter.py"))` +- `s5/s5_uid_controls.py:28`: `w = module('s5_uid_wrapper', Path(__file__).with_name('run_s5_native.py'))` +- `s5/s5_wrapper_fixtures.py:13`: `path = Path(__file__).parent / "run_s5_native.py"` +- `scratch_fixture_adapter.py:43`: `source = HERE / (args.fixture + ".py")` + +Explicit closure membership: + +- `build_p04_index.py` +- `bulk_reader_equivalence.py` +- `checker_applicability_fixtures.py` +- `checker_approval_fixtures.py` +- `checker_candidate_fixtures.py` +- `checker_encoder_fixtures.py` +- `checker_join_fixtures.py` +- `checker_native_fixtures.py` +- `checker_negative_fixtures.py` +- `checker_role_fixtures.py` +- `checker_series_fixtures.py` +- `collect_p04_native.py` +- `full_suite_verifier.py` +- `normal_c_join.py` +- `normal_c_join_fixtures.py` +- `p04_native_series.py` +- `repair48_identity_controls.py` +- `repair48_transport_controls.py` +- `s1/S1_ROOT_RUN.md` +- `s1/p04_s1_ev_power_probe.gd` +- `s1/run_s1_native.py` +- `s2/S2_ROOT_RUN.md` +- `s2/p04_s2a_midnight_probe.gd` +- `s2/run_s2a_native.py` +- `s2b/S2B_ROOT_RUN.md` +- `s2b/p04_s2b_shift_probe.gd` +- `s2b/run_s2b_native.py` +- `s3/S3_ROOT_RUN.md` +- `s3/p04_s3_closure_probe.gd` +- `s3/run_s3_native.py` +- `s4/S4_ROOT_RUN.md` +- `s4/admission_controls.py` +- `s4/engine_identity_negative_fixtures.py` +- `s4/p04_s4_power_probe.gd` +- `s4/phase_cut_regression.py` +- `s4/receipt_lifecycle_fixtures.py` +- `s4/run_s4_native.py` +- `s5/S5_ROOT_RUN.md` +- `s5/p04_s5_power_probe.gd` +- `s5/repair44_controls.py` +- `s5/run_s5_native.py` +- `s5/s5_guard_oracle.py` +- `s5/s5_order_adapter.py` +- `s5/s5_order_adapter_controls.py` +- `s5/s5_power_adapter.py` +- `s5/s5_power_adapter_controls.py` +- `s5/s5_uid_controls.py` +- `s5/s5_wrapper_fixtures.py` +- `scratch_fixture_adapter.py` + +The fixture compares complete relative-path/bytes/SHA tables and canonical table +tree hashes for original/A/B before execution and after positive identity work. +Missing, traversal, outside paths and symlinks reject. Negative mutation phase is +separate; existing byte/missing/extra/mapping/symlink/outside cases remain. +A missing S5 .gd negative is added. complete_B_controls=true requires both +placements' S5 facts and entire payload equality. No raw or compared fields are +excluded or normalized. Actual three-placement proof is UNEXECUTED by worker; +Runner must retain the emitted before/after tables. + +## Root handoff + +Read ROOT_REPAIR49_CURRENT_EVIDENCE_AND_INDEPENDENT_SCOPE.json directly: +payload(B), all53, series/join/power PASS per Root report, engine0, no acceptance. +order-typed is UNDETERMINED and is not pass. Transport/raw-only/synthetic and +q4801 six-series collection are historical S47 successes, not new-S evidence. +Only the observed complete_B closure failure is repaired. + +## Historical complete_B failure (verbatim) + +```text +Traceback (most recent call last): + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p04-01/P04-01-implement/docs/plans/original-completion-2026-10-02/execution/p04-01/repair48_identity_controls.py", line 115, in + run(parser.parse_args()) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p04-01/P04-01-implement/docs/plans/original-completion-2026-10-02/execution/p04-01/repair48_identity_controls.py", line 60, in run + assert native[0].verify_fresh_s5(build) == native[1].verify_fresh_s5(build) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/private/var/folders/41/j8fq6vqj2993cmyprl6p76pw0000gn/T/p04-r48-identity-8veppaza/first/docs/plans/original-completion-2026-10-02/execution/p04-01/p04_native_series.py", line 1430, in verify_fresh_s5 + s = FreshSeries(build, 's5') + ^^^^^^^^^^^^^^^^^^^^^^^^ + File "/private/var/folders/41/j8fq6vqj2993cmyprl6p76pw0000gn/T/p04-r48-identity-8veppaza/first/docs/plans/original-completion-2026-10-02/execution/p04-01/p04_native_series.py", line 1338, in __init__ + exec(compile(wrapper_path.read_bytes(), str(wrapper_path), 'exec'), wrapper.__dict__) + File "/private/var/folders/41/j8fq6vqj2993cmyprl6p76pw0000gn/T/p04-r48-identity-8veppaza/first/docs/plans/original-completion-2026-10-02/execution/p04-01/s5/run_s5_native.py", line 45, in + File "/private/var/folders/41/j8fq6vqj2993cmyprl6p76pw0000gn/T/p04-r48-identity-8veppaza/first/docs/plans/original-completion-2026-10-02/execution/p04-01/s5/run_s5_native.py", line 33, in case_table + File "/opt/homebrew/Cellar/python@3.12/3.12.13_2/Frameworks/Python.framework/Versions/3.12/lib/python3.12/pathlib.py", line 1027, in read_text + with self.open(mode='r', encoding=encoding, errors=errors) as f: + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/opt/homebrew/Cellar/python@3.12/3.12.13_2/Frameworks/Python.framework/Versions/3.12/lib/python3.12/pathlib.py", line 1013, in open + return io.open(self, mode, buffering, encoding, errors, newline) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +FileNotFoundError: [Errno 2] No such file or directory: '/private/var/folders/41/j8fq6vqj2993cmyprl6p76pw0000gn/T/p04-r48-identity-8veppaza/first/docs/plans/original-completion-2026-10-02/execution/p04-01/s5/p04_s5_power_probe.gd' + +``` diff --git a/docs/plans/original-completion-2026-10-02/execution/p04-01/build_p04_index.py b/docs/plans/original-completion-2026-10-02/execution/p04-01/build_p04_index.py index 64a8e13..2437f65 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p04-01/build_p04_index.py +++ b/docs/plans/original-completion-2026-10-02/execution/p04-01/build_p04_index.py @@ -29,9 +29,155 @@ def descriptor(path): return {'path': str(path.absolute()), 'bytes': len(data), 'sha256': hashlib.sha256(data).hexdigest()} +def require(value, message): + if not value: + raise ValueError(message) + + +def ordinary(path): + path = Path(path) + require('..' not in path.parts, 'parent traversal') + require(not any(p.is_symlink() for p in (path, *path.parents)), 'symlink path') + return path + + +def series_inputs(build): + registry = json.loads(ordinary(build / 'audit-support/p04-fresh-runs.json').read_bytes()) + path = Path(__file__).with_name('p04_native_series.py') + spec = importlib.util.spec_from_file_location('transport_series', path) + module = importlib.util.module_from_spec(spec) + exec(compile(path.read_bytes(), str(path), 'exec'), module.__dict__) + require(set(registry['series']) == set(module.FRESH_RUNS), 'fresh series roster') + result = {} + for name in module.FRESH_RUNS: + run = Path(registry['series'][name]['run']) + require(not run.is_absolute() and '..' not in run.parts, 'fresh run path') + result[name] = json.loads(ordinary(build / run / 'runner-input.json').read_bytes()) + return result + + +def pin_roster(inputs): + result = {} + for pin in inputs['fixed_input_pins'] + [inputs['QA']]: + path = pin['path'] + ordinary(path) + require(Path(path).is_absolute(), 'pin source must be absolute') + require(type(pin['bytes']) is int and pin['bytes'] >= 0, 'pin bytes') + digest = pin['sha256'] + require(isinstance(digest, str) and len(digest) == 64 + and all(c in '0123456789abcdef' for c in digest), 'pin SHA') + identity = {'bytes': pin['bytes'], 'sha256': digest} + require(path not in result or result[path] == identity, 'conflicting duplicate pin') + result[path] = identity + return result + + +def relative_material(series, original, pin): + return f"runner-materials/{series}/{pin['sha256']}/{Path(original).name}" + + +def all_rosters(inputs): + rosters, seen = {}, {} + for name, raw in inputs.items(): + rosters[name] = pin_roster(raw) + for original, pin in rosters[name].items(): + require(original not in seen or seen[original] == pin, 'conflicting duplicate pin across series') + seen[original] = pin + return rosters + + +def material_layout(inputs): + rosters = all_rosters(inputs) + layout, seen, destinations = {}, {}, {} + for name, roster in rosters.items(): + layout[name] = {} + for original, pin in roster.items(): + identity = (original, pin['bytes'], pin['sha256']) + relative = seen.setdefault(identity, relative_material(name, original, pin)) + require(relative not in destinations or destinations[relative] == identity, + 'distinct pins collide at material destination') + destinations[relative] = identity + layout[name][original] = relative + return rosters, layout + + +def checked_material(path, pin): + data = ordinary(path).read_bytes() + require(len(data) == pin['bytes'] and hashlib.sha256(data).hexdigest() == pin['sha256'], + 'material pin mismatch') + return data + + +def relocate_materials(build, output): + build = ordinary(Path(build).absolute()).resolve(strict=True) + output = ordinary(Path(output).absolute()) + require(output == build / 'p04-evidence', 'output must be B/p04-evidence') + output.mkdir() + mapping = {} + inputs = series_inputs(build) + rosters, layout = material_layout(inputs) + written = set() + for name, roster in rosters.items(): + mapping[name] = {} + for original, pin in roster.items(): + relative = layout[name][original] + target = output / relative + if relative not in written: + data = checked_material(original, pin) + target.parent.mkdir(parents=True, exist_ok=True) + with target.open('xb') as stream: + stream.write(data) + written.add(relative) + checked_material(target, pin) + mapping[name][original] = {'relative': relative, **pin} + with (output / 'runner-materials/RELOCATION.json').open('x') as stream: + json.dump(mapping, stream, sort_keys=True, indent=2) + stream.write('\n') + return mapping + + +def relocated_materials(build): + output = ordinary(build / 'p04-evidence') + map_path = ordinary(output / 'runner-materials/RELOCATION.json') + def unique(pairs): + result = {} + for key, value in pairs: + require(key not in result, 'duplicate relocation key') + result[key] = value + return result + mapping = json.loads(map_path.read_bytes(), object_pairs_hook=unique) + inputs = series_inputs(build) + rosters, layout = material_layout(inputs) + require(set(mapping) == set(inputs), 'relocation series roster') + descriptors = {} + expected_files = {'runner-materials/RELOCATION.json'} + for name, raw in inputs.items(): + roster = rosters[name] + require(set(mapping[name]) == set(roster), 'relocation material roster') + descriptors[name] = {} + for original, pin in roster.items(): + relative = layout[name][original] + require(mapping[name][original] == {'relative': relative, **pin}, 'relocation mapping mismatch') + checked_material(output / relative, pin) + expected_files.add(relative) + descriptors[name][original] = {'path': relative, **pin} + wrappers = [path for path, pin in roster.items() if pin['sha256'] == raw['wrapper_sha256']] + require(len(wrappers) == 1, 'exactly one wrapper pin required') + actual_files = set() + for path in (output / 'runner-materials').rglob('*'): + ordinary(path) + if path.is_file(): + actual_files.add(path.relative_to(output).as_posix()) + require(actual_files == expected_files, 'unmapped material') + return inputs, descriptors, {'path': 'runner-materials/RELOCATION.json', + 'bytes': map_path.stat().st_size, + 'sha256': hashlib.sha256(map_path.read_bytes()).hexdigest()} + + def payload(build, gate=None): gate = gate or checker() - build = Path(build).resolve(strict=True) + build = ordinary(Path(build).absolute()).resolve(strict=True) + inputs_by_series, materials_by_series, relocation_descriptor = relocated_materials(build) native = build / 'audit-support/native-first-current' c = gate.verify_native(native) raw = gate.combine_native_series(build, c) @@ -48,16 +194,12 @@ def payload(build, gate=None): path = gate.safe(build, run_binding['run'] + '/runner-input.json') inputs = gate.load(path) row = descriptor(path) - row['materials'] = {} - for pin in inputs.get('fixed_input_pins', []) + [inputs['QA']]: - material = descriptor(Path(pin['path'])) - gate.require(material['bytes'] == pin['bytes'] and material['sha256'] == pin['sha256'], - 'fresh material changed') - gate.supplied_file(build, material) - row['materials'][pin['path']] = material - wrapper = next(p for p in inputs['fixed_input_pins'] - if p['sha256'] == inputs['wrapper_sha256']) - row['wrapper'] = descriptor(Path(wrapper['path'])) + require(inputs == inputs_by_series[name], 'runner input changed during payload') + row['materials'] = materials_by_series[name] + wrappers = [p for p in row['materials'] + if row['materials'][p]['sha256'] == inputs['wrapper_sha256']] + require(len(wrappers) == 1, 'exactly one wrapper pin required') + row['wrapper'] = row['materials'][wrappers[0]] runners.append(row) # C references retain every lifecycle, raw phase, source, environment and # formal member mapping; Stage R retains its complete original->relocated map. @@ -102,7 +244,8 @@ def payload(build, gate=None): reachability[name] = {'reach': name == 'EV', 'case_id': 'EV' if name == 'EV' else None, 'source_refs': refs, 'raw_verified': 'EV' in raw['verified_conditions'] if name == 'EV' else None} delta = gate.source_delta(gate.REGISTERED_COMMIT, tested) - index = {'schema_version': 2, 'task_id': 'P04-01', 'formal_acceptance': False, + index = {'runner_material_relocation': relocation_descriptor, + 'schema_version': 2, 'task_id': 'P04-01', 'formal_acceptance': False, 'versions': {'registered': gate.REGISTERED_COMMIT, 'execution_origin': gate.EXECUTION_ORIGIN, 'tested': tested}, 'product_binding': {'tested_product': tested, 'runner_inputs': runners}, @@ -127,17 +270,16 @@ def payload(build, gate=None): def main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('--build', required=True, type=Path) - parser.add_argument('--output', required=True, type=Path, help='fresh directory; exclusive creation') + parser.add_argument('--output', type=Path, help='exact B/p04-evidence; exclusive creation') parser.add_argument('--invocation', required=True, choices=('validate', 'prepare-integration', 'final')) parser.add_argument('--registered-ref', required=True) parser.add_argument('--tested-ref', required=True) args = parser.parse_args() gate = checker() os.environ['BUILD_OUTPUT_DIR'] = str(args.build.resolve(strict=True)) - output = args.output.absolute() - gate.require(not output.exists() and not output.is_symlink(), 'output must be fresh') - for path in output.parents: - gate.require(not path.is_symlink(), 'output parent symlink') + output = args.output or Path(os.environ.get('P04_EVIDENCE_DIR', str(args.build.resolve() / 'p04-evidence'))) + output = output.absolute() + relocate_materials(args.build, output) index = payload(args.build, gate) gate.require(args.registered_ref == gate.REGISTERED_COMMIT and args.tested_ref == index['versions']['tested'], @@ -147,11 +289,15 @@ def main(): # The historical invocation is separate from the reusable evidence index. receipt = {'invocation': args.invocation, 'actual_head': role['actual_head'], 'actual_tree': role['actual_tree'], 'role': role['role'], 'formal_acceptance': False} - output.mkdir(parents=False) - for name, value in (('index.json', index), ('generation-invocation.json', receipt)): - with (output / name).open('x', encoding='utf-8') as stream: - json.dump(value, stream, ensure_ascii=False, sort_keys=True, indent=2) - stream.write('\n') + try: + for name, value in (('index.json', index), ('generation-invocation.json', receipt)): + with (output / name).open('x', encoding='utf-8') as stream: + json.dump(value, stream, ensure_ascii=False, sort_keys=True, indent=2) + stream.write('\n') + except BaseException: + # The exclusively created directory is a failed attempt, never evidence. + (output / 'index.json').unlink(missing_ok=True) + raise print(json.dumps({'evidence_directory': str(output), **receipt})) diff --git a/docs/plans/original-completion-2026-10-02/execution/p04-01/collect_p04_native.py b/docs/plans/original-completion-2026-10-02/execution/p04-01/collect_p04_native.py index 949e917..dd1ffd5 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p04-01/collect_p04_native.py +++ b/docs/plans/original-completion-2026-10-02/execution/p04-01/collect_p04_native.py @@ -45,6 +45,9 @@ def collect(build, fresh=None): 'collector_sha256': series.digest(Path(__file__).read_bytes()), 'historical_merged': False, 'large_payloads_copied': 0} payloads['MANIFEST.json'] = encoded(manifest) + if fresh: + # This is an invocation/transport record, never compared as S5 facts. + payloads['dependency-invocation.json'] = encoded(series.S5_DEPENDENCY_INVOCATION) estimate = sum(len(v) for v in payloads.values()) # The estimate precedes all writes. Reserve extra directory/allocation space. print(json.dumps({'estimated_payload_bytes': estimate, 'files': len(payloads), diff --git a/docs/plans/original-completion-2026-10-02/execution/p04-01/full_suite_verifier.py b/docs/plans/original-completion-2026-10-02/execution/p04-01/full_suite_verifier.py index 2ca490c..d4dd097 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p04-01/full_suite_verifier.py +++ b/docs/plans/original-completion-2026-10-02/execution/p04-01/full_suite_verifier.py @@ -12,9 +12,13 @@ def require(value, message): def module(name, path): + path = Path(path).absolute() + require('..' not in path.parts and all(not p.is_symlink() for p in (path, *path.parents)), + 'module ordinary path') + data = path.read_bytes() spec = importlib.util.spec_from_file_location(name, path) result = importlib.util.module_from_spec(spec) - spec.loader.exec_module(result) + exec(compile(data, str(path), 'exec'), result.__dict__) return result diff --git a/docs/plans/original-completion-2026-10-02/execution/p04-01/p04_native_series.py b/docs/plans/original-completion-2026-10-02/execution/p04-01/p04_native_series.py index e80d52f..acccb28 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p04-01/p04_native_series.py +++ b/docs/plans/original-completion-2026-10-02/execution/p04-01/p04_native_series.py @@ -1333,7 +1333,9 @@ class FreshSeries(Series): import importlib.util spec = importlib.util.spec_from_file_location('fresh_series_wrapper', wrapper_path) wrapper = importlib.util.module_from_spec(spec) - spec.loader.exec_module(wrapper) + require(all(not p.is_symlink() for p in (wrapper_path, *wrapper_path.parents)), + 'fresh wrapper ordinary path') + exec(compile(wrapper_path.read_bytes(), str(wrapper_path), 'exec'), wrapper.__dict__) if self.name == 's4': admission = wrapper.module('fresh_s4_admission', HERE / 's4/run_s4_native.py') product = {n: p for n, p in selected.items() if n != admission.CHECKER} @@ -1430,7 +1432,18 @@ def verify_fresh_s5(build): path = Path(__file__).parent / 's5/s5_order_adapter.py' spec = importlib.util.spec_from_file_location('fresh_order_adapter', path) adapter = importlib.util.module_from_spec(spec) - spec.loader.exec_module(adapter) + require('..' not in path.parts and all(not p.is_symlink() for p in (path, *path.parents)), + 'S5 adapter ordinary package path') + adapter_bytes = path.read_bytes() + exec(compile(adapter_bytes, str(path), 'exec'), adapter.__dict__) + # Transport-only observations are retained by collect(), outside s5.json. + global S5_DEPENDENCY_INVOCATION + S5_DEPENDENCY_INVOCATION = { + 'checkout': str(HERE.parents[4]), + 'adapter': {'path': str(path.absolute()), 'sha256': digest(adapter_bytes)}, + 'dependencies': dict(adapter.DEPENDENCY_OBSERVATIONS), + 'dependency_sha256': dict(adapter.DEPENDENCIES), + } arguments = (s.base / 'raw', s.inventory['writer.json']['sha256'], s.inventory['reader.json']['sha256']) power = adapter.power.derive(*arguments) order = adapter.derive(*arguments) diff --git a/docs/plans/original-completion-2026-10-02/execution/p04-01/repair48_identity_controls.py b/docs/plans/original-completion-2026-10-02/execution/p04-01/repair48_identity_controls.py new file mode 100644 index 0000000..2fed753 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p04-01/repair48_identity_controls.py @@ -0,0 +1,153 @@ +#!/usr/bin/env python3 +"""Runner-only retained-raw identity controls; no engine or acceptance run.""" +import argparse +import copy +import hashlib +import importlib.util +import json +from pathlib import Path +import shutil +import sys +import tempfile + +sys.dont_write_bytecode = True +HERE = Path(__file__).resolve().parent + + +def load(path, name): + spec = importlib.util.spec_from_file_location(name, path) + value = importlib.util.module_from_spec(spec) + exec(compile(path.read_bytes(), str(path), 'exec'), value.__dict__) + return value + + +def rejects(call): + try: + call() + except (ValueError, OSError, KeyError, TypeError): + return + raise AssertionError('negative admitted') + + +def tree(root): + return {p.relative_to(root).as_posix(): hashlib.sha256(p.read_bytes()).hexdigest() + for p in root.rglob('*') if p.is_file()} + + +# Explicit audited package-local closure; see REPAIR49_STATUS.md. +CLOSURE = ('build_p04_index.py', 'bulk_reader_equivalence.py', 'checker_applicability_fixtures.py', 'checker_approval_fixtures.py', 'checker_candidate_fixtures.py', 'checker_encoder_fixtures.py', 'checker_join_fixtures.py', 'checker_native_fixtures.py', 'checker_negative_fixtures.py', 'checker_role_fixtures.py', 'checker_series_fixtures.py', 'collect_p04_native.py', 'full_suite_verifier.py', 'normal_c_join.py', 'normal_c_join_fixtures.py', 'p04_native_series.py', 'repair48_identity_controls.py', 'repair48_transport_controls.py', 's1/S1_ROOT_RUN.md', 's1/p04_s1_ev_power_probe.gd', 's1/run_s1_native.py', 's2/S2_ROOT_RUN.md', 's2/p04_s2a_midnight_probe.gd', 's2/run_s2a_native.py', 's2b/S2B_ROOT_RUN.md', 's2b/p04_s2b_shift_probe.gd', 's2b/run_s2b_native.py', 's3/S3_ROOT_RUN.md', 's3/p04_s3_closure_probe.gd', 's3/run_s3_native.py', 's4/S4_ROOT_RUN.md', 's4/admission_controls.py', 's4/engine_identity_negative_fixtures.py', 's4/p04_s4_power_probe.gd', 's4/phase_cut_regression.py', 's4/receipt_lifecycle_fixtures.py', 's4/run_s4_native.py', 's5/S5_ROOT_RUN.md', 's5/p04_s5_power_probe.gd', 's5/repair44_controls.py', 's5/run_s5_native.py', 's5/s5_guard_oracle.py', 's5/s5_order_adapter.py', 's5/s5_order_adapter_controls.py', 's5/s5_power_adapter.py', 's5/s5_power_adapter_controls.py', 's5/s5_uid_controls.py', 's5/s5_wrapper_fixtures.py', 'scratch_fixture_adapter.py') + + +def package_snapshot(root): + root = Path(root).absolute() + rows = {} + for name in CLOSURE: + relative = Path(name) + if relative.is_absolute() or '..' in relative.parts: + raise ValueError('closure traversal/outside') + path = root / relative + if (any(p.is_symlink() for p in (path, *path.parents)) + or not path.resolve(strict=True).is_relative_to(root.resolve(strict=True)) + or not path.is_file()): + raise ValueError('closure missing/symlink/outside: ' + name) + data = path.read_bytes() + rows[name] = {'bytes': len(data), 'sha256': hashlib.sha256(data).hexdigest()} + encoded = json.dumps(rows, sort_keys=True, separators=(',', ':')).encode() + return {'files': rows, 'tree_sha256': hashlib.sha256(encoded).hexdigest()} + + +def run(args): + raw = args.raw.resolve(strict=True) + with tempfile.TemporaryDirectory(prefix='p04-r48-identity-') as directory: + base = Path(directory).resolve() + suffix = Path('docs/plans/original-completion-2026-10-02/execution/p04-01') + packages = [base / name / suffix for name in ('first', 'second')] + original_package = package_snapshot(HERE) + names = [Path(name) for name in CLOSURE] + for package in packages: + for relative in names: + target = package / relative + target.parent.mkdir(parents=True, exist_ok=True) + shutil.copyfile(HERE / relative, target) + snapshots_before = [package_snapshot(root) for root in (HERE, *packages)] + assert all(row == original_package for row in snapshots_before) + a, b = [load(p / 's5/s5_order_adapter.py', 'identity_' + str(i)) + for i, p in enumerate(packages)] + first = a.derive(raw, args.writer_sha, args.reader_sha) + assert b.derive(raw, args.writer_sha, args.reader_sha) == first + assert a.DEPENDENCY_OBSERVATIONS != b.DEPENDENCY_OBSERVATIONS + if args.build: + build = args.build.resolve(strict=True) + before = tree(build) + # These independent packages execute the same complete analysis bytes. + native = [load(p / 'p04_native_series.py', 'native_' + str(i)) + for i, p in enumerate(packages)] + assert native[0].verify_fresh_s5(build) == native[1].verify_fresh_s5(build) + original_builder = load(HERE / 'build_p04_index.py', 'original_builder') + gate = original_builder.checker() + builders = [load(p / 'build_p04_index.py', 'builder_' + str(i)) + for i, p in enumerate(packages)] + assert builders[0].payload(build, gate) == builders[1].payload(build, gate) + assert tree(build) == before + snapshots_after = [package_snapshot(root) for root in (HERE, *packages)] + assert snapshots_after == snapshots_before + missing = packages[1] / 's5/p04_s5_power_probe.gd' + saved = missing.read_bytes() + missing.unlink() + rejects(lambda: package_snapshot(packages[1])) + missing.write_bytes(saved) + assert package_snapshot(packages[1]) == original_package + for kind in ('byte', 'missing', 'extra', 'mapping'): + original = copy.deepcopy(a.DEPENDENCIES) + key = next(iter(original)) + if kind == 'byte': + a.DEPENDENCIES[key] = '0' * 64 + elif kind == 'missing': + del a.DEPENDENCIES[key] + elif kind == 'extra': + a.DEPENDENCIES['extra.py'] = '0' * 64 + else: + a.DEPENDENCY_OBSERVATIONS[key] = '/outside-package.py' + rejects(lambda: a.derive(raw, args.writer_sha, args.reader_sha)) + a.DEPENDENCIES.clear() + a.DEPENDENCIES.update(original) + a.DEPENDENCY_OBSERVATIONS.update(a._EXECUTED_OBSERVATIONS) + target = packages[1] / 's5/s5_guard_oracle.py' + target.write_bytes(target.read_bytes() + b'\n') + changed = load(packages[1] / 's5/s5_order_adapter.py', 'changed_identity') + assert changed.DEPENDENCIES != a.DEPENDENCIES + # Reject the changed payload at the same equality boundary used for recomputation. + rejects(lambda: a.require(changed.derive(raw, args.writer_sha, args.reader_sha) == first, + 'fresh raw recomputation drift')) + target.unlink() + target.symlink_to(packages[0] / 's5/s5_guard_oracle.py') + rejects(lambda: load(packages[1] / 's5/s5_order_adapter.py', 'symlink_identity')) + rejects(lambda: a.module('outside_identity', HERE / 's5/s5_guard_oracle.py')) + target.unlink() + target.write_bytes((HERE / 's5/s5_guard_oracle.py').read_bytes()) + assert [package_snapshot(root) for root in (HERE, *packages)] == snapshots_before + if args.build: + # A retained complete B is required. Never call the registered checker main(). + builder = load(HERE / 'build_p04_index.py', 'identity_builder') + build = args.build.resolve(strict=True) + before = tree(build) + first = builder.payload(build) + assert builder.payload(build) == first and tree(build) == before + changed = copy.deepcopy(first) + changed['runner_material_relocation']['sha256'] = '0' * 64 + rejects(lambda: builder.require(changed == builder.payload(build), 'index recomputation mismatch')) + rejects(lambda: builder.checker().supplied_file(build, { + 'path': '/outside-B/material', 'bytes': 0, 'sha256': '0' * 64})) + assert package_snapshot(HERE) == original_package + print(json.dumps({'identity_controls': 'pass', 'complete_B_controls': bool(args.build), + 'formal_acceptance': False, + 'closure_before': snapshots_before, 'closure_after': snapshots_after})) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--raw', type=Path, required=True) + parser.add_argument('--writer-sha', required=True) + parser.add_argument('--reader-sha', required=True) + parser.add_argument('--build', type=Path) + run(parser.parse_args()) diff --git a/docs/plans/original-completion-2026-10-02/execution/p04-01/repair48_transport_controls.py b/docs/plans/original-completion-2026-10-02/execution/p04-01/repair48_transport_controls.py new file mode 100644 index 0000000..67d81cf --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p04-01/repair48_transport_controls.py @@ -0,0 +1,159 @@ +#!/usr/bin/env python3 +"""Runner-only, engine-free retained-copy transport controls. No acceptance.""" +import argparse +import copy +import hashlib +import importlib.util +import json +from pathlib import Path +import tempfile +from unittest.mock import patch +import sys + +sys.dont_write_bytecode = True +spec = importlib.util.spec_from_file_location('transport', Path(__file__).with_name('build_p04_index.py')) +builder = importlib.util.module_from_spec(spec) +spec.loader.exec_module(builder) + + +def sha(data): + return hashlib.sha256(data).hexdigest() + + +def tree(root): + return {p.relative_to(root).as_posix(): sha(p.read_bytes()) + for p in root.rglob('*') if p.is_file()} + + +def rejects(call): + try: + call() + except (ValueError, OSError, KeyError, TypeError): + return + raise AssertionError('negative admitted') + + +def run(retained): + manifest = json.loads((retained / 'REAL_S47_PINNED_MATERIAL_COPIES.json').read_bytes()) + inputs, sources = {}, {} + for name, row in manifest['series'].items(): + data = (retained / row['raw_input']).read_bytes() + assert len(data) == row['bytes'] and sha(data) == row['sha256'] + inputs[name] = json.loads(data) + for original, row in manifest['materials'].items(): + data = (retained / row['retained_copy']).read_bytes() + assert len(data) == row['bytes'] and sha(data) == row['sha256'] + sources[original] = data + assert any('p04-fresh-context-r47' in p for p in sources) + assert any('P04-01-root-q-r47' in p for p in sources) + original_checked = builder.checked_material + + def retained_checked(path, pin): + if str(path) in sources: + data = sources[str(path)] + builder.require(len(data) == pin['bytes'] and sha(data) == pin['sha256'], 'retained pin') + return data + return original_checked(path, pin) + + with tempfile.TemporaryDirectory(prefix='p04-repair48-') as directory: + build = Path(directory).resolve() + with patch.object(builder, 'series_inputs', return_value=inputs), \ + patch.object(builder, 'checked_material', side_effect=retained_checked): + output = build / 'p04-evidence' + rejects(lambda: builder.relocate_materials(build, build / 'wrong')) + assert not output.exists() + builder.relocate_materials(build, output) + rejects(lambda: builder.relocate_materials(build, output)) + before = tree(build) + first = builder.relocated_materials(build) + assert builder.relocated_materials(build) == first and tree(build) == before + map_path = output / 'runner-materials/RELOCATION.json' + map_bytes = map_path.read_bytes() + mapping = json.loads(map_bytes) + identities = {(pin['path'], pin['bytes'], pin['sha256']) + for raw in inputs.values() for pin in raw['fixed_input_pins'] + [raw['QA']]} + assert len({row['relative'] for rows in mapping.values() for row in rows.values()}) == len(identities) + series = next(iter(inputs)) + original = next(iter(mapping[series])) + target = output / mapping[series][original]['relative'] + data = target.read_bytes() + target.write_bytes(data + b'x') + rejects(lambda: builder.relocated_materials(build)) + target.write_bytes(data) + target.unlink() + target.symlink_to(map_path) + rejects(lambda: builder.relocated_materials(build)) + target.unlink() + target.write_bytes(data) + for kind in ('missing', 'extra', 'mapping', 'traversal', 'external'): + changed = copy.deepcopy(mapping) + if kind == 'missing': + del changed[series][original] + elif kind == 'extra': + changed[series]['/extra'] = changed[series][original] + else: + changed[series][original]['relative'] = { + 'mapping': 'runner-materials/wrong', 'traversal': '../outside', + 'external': '/outside-B'}[kind] + map_path.write_text(json.dumps(changed)) + rejects(lambda: builder.relocated_materials(build)) + map_path.write_bytes(map_bytes) + extra = output / 'runner-materials/unmapped' + extra.write_bytes(b'extra') + rejects(lambda: builder.relocated_materials(build)) + extra.unlink() + for digest in ('0' * 64, None): + altered = copy.deepcopy(inputs) + altered[series]['wrapper_sha256'] = digest + with patch.object(builder, 'series_inputs', return_value=altered): + rejects(lambda: builder.relocated_materials(build)) + # A second distinct pin carrying wrapper bytes is ambiguous. + altered = copy.deepcopy(inputs) + wrapper = next(p for p in altered[series]['fixed_input_pins'] + if p['sha256'] == altered[series]['wrapper_sha256']) + altered[series]['fixed_input_pins'].append(dict(wrapper, path='/different-wrapper')) + with patch.object(builder, 'series_inputs', return_value=altered): + rejects(lambda: builder.relocated_materials(build)) + assert tree(build) == before + raw = copy.deepcopy(next(iter(inputs.values()))) + pin = copy.deepcopy(raw['QA']) + raw['fixed_input_pins'].append(pin) + assert len(builder.pin_roster(raw)) == len({p['path'] for p in raw['fixed_input_pins'] + [raw['QA']]}) + with tempfile.TemporaryDirectory(prefix='p04-r48-dedup-') as directory: + build = Path(directory).resolve() + with patch.object(builder, 'series_inputs', return_value={'s1': raw}), \ + patch.object(builder, 'checked_material', side_effect=retained_checked): + mapping = builder.relocate_materials(build, build / 'p04-evidence') + assert len(mapping['s1']) == len(builder.pin_roster(raw)) + builder.relocated_materials(build) + raw['fixed_input_pins'].append(dict(pin, bytes=pin['bytes'] + 1)) + rejects(lambda: builder.pin_roster(raw)) + rejects(lambda: builder.ordinary('/a/../b')) + changed = copy.deepcopy(inputs) + series = next(iter(changed)) + changed[series]['QA']['sha256'] = '0' * 64 + rejects(lambda: builder.all_rosters(changed)) + # Exercise the actual immutable checker's role binding predicate, with + # simulated Git observations only. No objects, refs or checkouts are written. + gate = builder.checker() + old = next(iter(inputs.values()))['provenance'] + new_submission, composed = 'f' * 40, 'e' * 40 + assert old['S'] != new_submission + with patch.object(gate, 'actual_checkout', return_value=(new_submission, composed, {})), \ + patch.object(gate, '_GIT_ENV', {}), \ + patch.object(gate, 'ancestor', return_value=False), \ + patch.object(gate, 'submission_role'), \ + patch.object(gate, 'git_bytes', return_value=composed.encode()): + try: + gate.verify_roles({'fresh_run_bindings': old}, Path('/retained-B')) + except ValueError as error: + assert str(error) == 'fresh evidence does not bind recomputed Q' + else: + raise AssertionError('old S47 bindings admitted under new S') + print(json.dumps({'retained_S47_transport_controls': 'pass', 'formal_acceptance': False})) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--retained', type=Path, required=True) + run(parser.parse_args().retained.resolve(strict=True)) diff --git a/docs/plans/original-completion-2026-10-02/execution/p04-01/s1/S1_ROOT_RUN.md b/docs/plans/original-completion-2026-10-02/execution/p04-01/s1/S1_ROOT_RUN.md index 0223e53..c855431 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p04-01/s1/S1_ROOT_RUN.md +++ b/docs/plans/original-completion-2026-10-02/execution/p04-01/s1/S1_ROOT_RUN.md @@ -1,3 +1,26 @@ +## REPAIR49 normal-gate handoff + +Required materials: exact B/native-first-current and fresh-run registry; each +runner-input/ended/source/UID/formal/raw/lifecycle receipt; original recorded Q +and engine context; B/p04-evidence/runner-materials and RELOCATION.json; matching +collection/MANIFEST and separate dependency invocation; original full run and +full_suite binding/raw receipts; final index and invocation receipt; immutable +authorities in frozen checkout. No raw or historical receipt is rewritten. +Two-placement identity requires the explicit closure in repair48_identity_controls.py, +missing-file rejection, and original/A/B complete path/bytes/SHA tables and tree +hash equality before and after positive execution. See REPAIR49_STATUS.md. +Submission is followed by new Q freeze, affected pure controls (complete_B included), +clean exact-Q check-only, capacity/PID checks, one fresh native lease for +S1/S2a/S2b/S3/S4 and all ten S5 cases, readers/adapters, 15EV collector, full +verification/binding under the conditions below (or one final full184 if any +condition fails), index generation, p04-acceptance once, separate Opus whole-unit +review, normal prepare/C/integration/final/Root DB join/ledger/main push. +If order-typed fails, preserve its result and stop before heavy execution. +Only whole-unit acceptance grants credit. + + +REPAIR48 current source status: see [REPAIR48_STATUS.md](../REPAIR48_STATUS.md). Earlier run directions and successes below are historical; they grant no P04 credit. + # S1 Root run(コード準備のみ) S1コード準備完了・未実測・原P04 whole未達。D05 pending、A未検証。 diff --git a/docs/plans/original-completion-2026-10-02/execution/p04-01/s2/S2_ROOT_RUN.md b/docs/plans/original-completion-2026-10-02/execution/p04-01/s2/S2_ROOT_RUN.md index 2648493..5559731 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p04-01/s2/S2_ROOT_RUN.md +++ b/docs/plans/original-completion-2026-10-02/execution/p04-01/s2/S2_ROOT_RUN.md @@ -1,3 +1,26 @@ +## REPAIR49 normal-gate handoff + +Required materials: exact B/native-first-current and fresh-run registry; each +runner-input/ended/source/UID/formal/raw/lifecycle receipt; original recorded Q +and engine context; B/p04-evidence/runner-materials and RELOCATION.json; matching +collection/MANIFEST and separate dependency invocation; original full run and +full_suite binding/raw receipts; final index and invocation receipt; immutable +authorities in frozen checkout. No raw or historical receipt is rewritten. +Two-placement identity requires the explicit closure in repair48_identity_controls.py, +missing-file rejection, and original/A/B complete path/bytes/SHA tables and tree +hash equality before and after positive execution. See REPAIR49_STATUS.md. +Submission is followed by new Q freeze, affected pure controls (complete_B included), +clean exact-Q check-only, capacity/PID checks, one fresh native lease for +S1/S2a/S2b/S3/S4 and all ten S5 cases, readers/adapters, 15EV collector, full +verification/binding under the conditions below (or one final full184 if any +condition fails), index generation, p04-acceptance once, separate Opus whole-unit +review, normal prepare/C/integration/final/Root DB join/ledger/main push. +If order-typed fails, preserve its result and stop before heavy execution. +Only whole-unit acceptance grants credit. + + +REPAIR48 current source status: see [REPAIR48_STATUS.md](../REPAIR48_STATUS.md). Earlier run directions and successes below are historical; they grant no P04 credit. + # P04-01 S2a Root run(code-ready提出用・実測未実施) repair12確認: worktreeのoperations_coordinator.gd SHA256は diff --git a/docs/plans/original-completion-2026-10-02/execution/p04-01/s2b/S2B_ROOT_RUN.md b/docs/plans/original-completion-2026-10-02/execution/p04-01/s2b/S2B_ROOT_RUN.md index a7fa657..3a77b44 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p04-01/s2b/S2B_ROOT_RUN.md +++ b/docs/plans/original-completion-2026-10-02/execution/p04-01/s2b/S2B_ROOT_RUN.md @@ -1,3 +1,26 @@ +## REPAIR49 normal-gate handoff + +Required materials: exact B/native-first-current and fresh-run registry; each +runner-input/ended/source/UID/formal/raw/lifecycle receipt; original recorded Q +and engine context; B/p04-evidence/runner-materials and RELOCATION.json; matching +collection/MANIFEST and separate dependency invocation; original full run and +full_suite binding/raw receipts; final index and invocation receipt; immutable +authorities in frozen checkout. No raw or historical receipt is rewritten. +Two-placement identity requires the explicit closure in repair48_identity_controls.py, +missing-file rejection, and original/A/B complete path/bytes/SHA tables and tree +hash equality before and after positive execution. See REPAIR49_STATUS.md. +Submission is followed by new Q freeze, affected pure controls (complete_B included), +clean exact-Q check-only, capacity/PID checks, one fresh native lease for +S1/S2a/S2b/S3/S4 and all ten S5 cases, readers/adapters, 15EV collector, full +verification/binding under the conditions below (or one final full184 if any +condition fails), index generation, p04-acceptance once, separate Opus whole-unit +review, normal prepare/C/integration/final/Root DB join/ledger/main push. +If order-typed fails, preserve its result and stop before heavy execution. +Only whole-unit acceptance grants credit. + + +REPAIR48 current source status: see [REPAIR48_STATUS.md](../REPAIR48_STATUS.md). Earlier run directions and successes below are historical; they grant no P04 credit. + RUN47 note: Earlier 1338-source native instructions below describe the historical relocation. Current fresh-Q selection uses exact source/manifest equality, never a literal file count. See ../REPAIR47_PLAN.json. # P04-01 S2b code preparation diff --git a/docs/plans/original-completion-2026-10-02/execution/p04-01/s3/S3_ROOT_RUN.md b/docs/plans/original-completion-2026-10-02/execution/p04-01/s3/S3_ROOT_RUN.md index 78ef4a0..6d5796a 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p04-01/s3/S3_ROOT_RUN.md +++ b/docs/plans/original-completion-2026-10-02/execution/p04-01/s3/S3_ROOT_RUN.md @@ -1,3 +1,26 @@ +## REPAIR49 normal-gate handoff + +Required materials: exact B/native-first-current and fresh-run registry; each +runner-input/ended/source/UID/formal/raw/lifecycle receipt; original recorded Q +and engine context; B/p04-evidence/runner-materials and RELOCATION.json; matching +collection/MANIFEST and separate dependency invocation; original full run and +full_suite binding/raw receipts; final index and invocation receipt; immutable +authorities in frozen checkout. No raw or historical receipt is rewritten. +Two-placement identity requires the explicit closure in repair48_identity_controls.py, +missing-file rejection, and original/A/B complete path/bytes/SHA tables and tree +hash equality before and after positive execution. See REPAIR49_STATUS.md. +Submission is followed by new Q freeze, affected pure controls (complete_B included), +clean exact-Q check-only, capacity/PID checks, one fresh native lease for +S1/S2a/S2b/S3/S4 and all ten S5 cases, readers/adapters, 15EV collector, full +verification/binding under the conditions below (or one final full184 if any +condition fails), index generation, p04-acceptance once, separate Opus whole-unit +review, normal prepare/C/integration/final/Root DB join/ledger/main push. +If order-typed fails, preserve its result and stop before heavy execution. +Only whole-unit acceptance grants credit. + + +REPAIR48 current source status: see [REPAIR48_STATUS.md](../REPAIR48_STATUS.md). Earlier run directions and successes below are historical; they grant no P04 credit. + RUN47 note: Earlier 1338-source native instructions below describe the historical relocation. Current fresh-Q selection uses exact source/manifest equality, never a literal file count. See ../REPAIR47_PLAN.json. # P04-01 S3 code-ready preparation diff --git a/docs/plans/original-completion-2026-10-02/execution/p04-01/s4/S4_ROOT_RUN.md b/docs/plans/original-completion-2026-10-02/execution/p04-01/s4/S4_ROOT_RUN.md index 78b068a..f664fae 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p04-01/s4/S4_ROOT_RUN.md +++ b/docs/plans/original-completion-2026-10-02/execution/p04-01/s4/S4_ROOT_RUN.md @@ -1,3 +1,26 @@ +## REPAIR49 normal-gate handoff + +Required materials: exact B/native-first-current and fresh-run registry; each +runner-input/ended/source/UID/formal/raw/lifecycle receipt; original recorded Q +and engine context; B/p04-evidence/runner-materials and RELOCATION.json; matching +collection/MANIFEST and separate dependency invocation; original full run and +full_suite binding/raw receipts; final index and invocation receipt; immutable +authorities in frozen checkout. No raw or historical receipt is rewritten. +Two-placement identity requires the explicit closure in repair48_identity_controls.py, +missing-file rejection, and original/A/B complete path/bytes/SHA tables and tree +hash equality before and after positive execution. See REPAIR49_STATUS.md. +Submission is followed by new Q freeze, affected pure controls (complete_B included), +clean exact-Q check-only, capacity/PID checks, one fresh native lease for +S1/S2a/S2b/S3/S4 and all ten S5 cases, readers/adapters, 15EV collector, full +verification/binding under the conditions below (or one final full184 if any +condition fails), index generation, p04-acceptance once, separate Opus whole-unit +review, normal prepare/C/integration/final/Root DB join/ledger/main push. +If order-typed fails, preserve its result and stop before heavy execution. +Only whole-unit acceptance grants credit. + + +REPAIR48 current source status: see [REPAIR48_STATUS.md](../REPAIR48_STATUS.md). Earlier run directions and successes below are historical; they grant no P04 credit. + ## RUN47 current admission (supersedes earlier execution instructions) Current S4 check-only and native call the same engine-free `admission` function. diff --git a/docs/plans/original-completion-2026-10-02/execution/p04-01/s5/S5_ROOT_RUN.md b/docs/plans/original-completion-2026-10-02/execution/p04-01/s5/S5_ROOT_RUN.md index e309fdd..69a9154 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p04-01/s5/S5_ROOT_RUN.md +++ b/docs/plans/original-completion-2026-10-02/execution/p04-01/s5/S5_ROOT_RUN.md @@ -1,3 +1,54 @@ +## REPAIR49 normal-gate handoff + +Required materials: exact B/native-first-current and fresh-run registry; each +runner-input/ended/source/UID/formal/raw/lifecycle receipt; original recorded Q +and engine context; B/p04-evidence/runner-materials and RELOCATION.json; matching +collection/MANIFEST and separate dependency invocation; original full run and +full_suite binding/raw receipts; final index and invocation receipt; immutable +authorities in frozen checkout. No raw or historical receipt is rewritten. +Two-placement identity requires the explicit closure in repair48_identity_controls.py, +missing-file rejection, and original/A/B complete path/bytes/SHA tables and tree +hash equality before and after positive execution. See REPAIR49_STATUS.md. +Submission is followed by new Q freeze, affected pure controls (complete_B included), +clean exact-Q check-only, capacity/PID checks, one fresh native lease for +S1/S2a/S2b/S3/S4 and all ten S5 cases, readers/adapters, 15EV collector, full +verification/binding under the conditions below (or one final full184 if any +condition fails), index generation, p04-acceptance once, separate Opus whole-unit +review, normal prepare/C/integration/final/Root DB join/ledger/main push. +If order-typed fails, preserve its result and stop before heavy execution. +Only whole-unit acceptance grants credit. + + +## REPAIR49 full184 conditional reuse candidate — all conditions UNVERIFIED + +Native reuse is forbidden: all six series require fresh M/S/Q_tree provenance +(p04_native_series.py:1287; checker:370). Full uses the existing separate binding +(checker:1175-1186); no adopter or checker change is authorized. +The following are requirements, not results or approval: + +1. New S5 source_before must equal old full selected_source_map: all 1369 keys + and SHA values, not counts alone. +2. Old project_root must remain unchanged: source-start == current source_refs + == post-verification source_refs (full_suite_verifier.py:115). +3. selected_source_map, roster184, parse329, settings, runner/marker module, + marker contract, suite-policy and UID plan/stage must all match (116-152,225). +4. inputs.engine must match current engine_pin (124-125). +5. Revalidate every phase PID, cleanup, marker and diagnostics (154-228). +6. Current s5/run_s5_native.py and full_suite_verifier.py SHA must equal the + Root rehearsal versions. +7. Never relabel old S/oldQ/project_root/PIDs/time. Describe reuse only as + revalidating the exact-source-identical old full through the existing + full_suite route; never claim full ran on new S. +8. A separate Opus whole-unit review must independently confirm applicability. + +Conditions 1–6 require actual checks after final freeze. If any predicate is +unproved or differs, reject reuse and execute full184 once on the final version. +SourceRefs (tools/run_all_tests.py:40-45) excludes docs/private package, but that +fact is no substitute for complete source equality. No reuse is approved here. + + +REPAIR48 current source status: see [REPAIR48_STATUS.md](../REPAIR48_STATUS.md). Earlier run directions and successes below are historical; they grant no P04 credit. + # REPAIR45 handoff ## REPAIR45 — implementation ready for submission diff --git a/docs/plans/original-completion-2026-10-02/execution/p04-01/s5/s5_order_adapter.py b/docs/plans/original-completion-2026-10-02/execution/p04-01/s5/s5_order_adapter.py index a7787b5..b132f80 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p04-01/s5/s5_order_adapter.py +++ b/docs/plans/original-completion-2026-10-02/execution/p04-01/s5/s5_order_adapter.py @@ -5,11 +5,41 @@ import importlib.util import json from pathlib import Path +PACKAGE_ROOT = Path(__file__).absolute().parents[1] +DEPENDENCIES = {} +DEPENDENCY_OBSERVATIONS = {} +_EXECUTED_DEPENDENCIES = {} +_EXECUTED_OBSERVATIONS = {} + def module(name, path): + path = Path(path).absolute() + if '..' in path.parts or any(p.is_symlink() for p in (path, *path.parents)): + raise ValueError('dependency traversal/symlink') + if not path.resolve(strict=True).is_relative_to(PACKAGE_ROOT.resolve(strict=True)): + raise ValueError('dependency outside package') + relative = path.relative_to(PACKAGE_ROOT).as_posix() + data = path.read_bytes() spec = importlib.util.spec_from_file_location(name, path) value = importlib.util.module_from_spec(spec) - spec.loader.exec_module(value) + exec(compile(data, str(path), 'exec'), value.__dict__) + DEPENDENCIES[relative] = hashlib.sha256(data).hexdigest() + DEPENDENCY_OBSERVATIONS[relative] = str(path) + for key, digest in getattr(value, 'DEPENDENCIES', {}).items(): + dependency = Path(key) + if dependency.is_absolute() or '..' in dependency.parts: + raise ValueError('dependency key must be package relative') + observed = Path(value.DEPENDENCY_OBSERVATIONS[key]) + if (observed != PACKAGE_ROOT / dependency + or any(p.is_symlink() for p in (observed, *observed.parents)) + or not observed.resolve(strict=True).is_relative_to(PACKAGE_ROOT.resolve(strict=True))): + raise ValueError('dependency mapping outside package/symlink') + if key in DEPENDENCIES and DEPENDENCIES[key] != digest: + raise ValueError('dependency mapping conflict') + DEPENDENCIES[key] = digest + DEPENDENCY_OBSERVATIONS[key] = value.DEPENDENCY_OBSERVATIONS[key] + _EXECUTED_DEPENDENCIES.update(DEPENDENCIES) + _EXECUTED_OBSERVATIONS.update(DEPENDENCY_OBSERVATIONS) return value @@ -17,11 +47,11 @@ POWER_PATH = Path(__file__).with_name('s5_power_adapter.py') power = module('s5_order_power', POWER_PATH) Raw, staff_check, duplicate_check = power.Raw, power.staff_check, power.duplicate_check series, require = power.series, power.require -DEPENDENCIES = {str(p): hashlib.sha256(p.read_bytes()).hexdigest() - for p in (POWER_PATH, power.SERIES_PATH)} GUARD_PATH = Path(__file__).with_name('s5_guard_oracle.py') guard_oracle = module('s5_guard_oracle', GUARD_PATH) -DEPENDENCIES[str(GUARD_PATH)] = hashlib.sha256(GUARD_PATH.read_bytes()).hexdigest() +if (set(DEPENDENCIES) != {'s5/s5_power_adapter.py', 'p04_native_series.py', 's5/s5_guard_oracle.py'} + or power.DEPENDENCIES != {'p04_native_series.py': power.SERIES_SHA256}): + raise ValueError('loaded dependency roster mismatch') GUEST, REQUEST = power.GUEST, power.REQUEST SECOND, SECOND_REQUEST = 'p04.s5.guest.b', 'p04.s5.request.b' @@ -415,7 +445,10 @@ DERIVERS = {'S5C_DESTRUCTION_COMMAND': destruction_command, 'S5D_DESTRUCTION_RAI def derive(root, writer_sha, reader_sha): - root = Path(root) + require(DEPENDENCIES == _EXECUTED_DEPENDENCIES + and DEPENDENCY_OBSERVATIONS == _EXECUTED_OBSERVATIONS, + 'dependency identity differs from executed module roster') + root = Path(root).resolve(strict=True) raw = Raw(root) writer = json.loads(raw.pin(root / 'writer.json', writer_sha), object_pairs_hook=power.unique) reader = json.loads(raw.pin(root / 'reader.json', reader_sha), object_pairs_hook=power.unique) diff --git a/docs/plans/original-completion-2026-10-02/execution/p04-01/s5/s5_power_adapter.py b/docs/plans/original-completion-2026-10-02/execution/p04-01/s5/s5_power_adapter.py index 8d2d87b..98144a3 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p04-01/s5/s5_power_adapter.py +++ b/docs/plans/original-completion-2026-10-02/execution/p04-01/s5/s5_power_adapter.py @@ -11,11 +11,20 @@ import struct import json from pathlib import Path -SERIES_PATH = Path(__file__).resolve().parents[1] / 'p04_native_series.py' -SERIES_SHA256 = hashlib.sha256(SERIES_PATH.read_bytes()).hexdigest() +PACKAGE_ROOT = Path(__file__).absolute().parents[1] +SERIES_PATH = PACKAGE_ROOT / 'p04_native_series.py' +for _path in (SERIES_PATH, *SERIES_PATH.parents): + if _path.is_symlink(): + raise ValueError('dependency symlink') +if not SERIES_PATH.resolve(strict=True).is_relative_to(PACKAGE_ROOT.resolve(strict=True)): + raise ValueError('dependency outside package') +_series_bytes = SERIES_PATH.read_bytes() +SERIES_SHA256 = hashlib.sha256(_series_bytes).hexdigest() _spec = importlib.util.spec_from_file_location('s5_power_series', SERIES_PATH) series = importlib.util.module_from_spec(_spec) -_spec.loader.exec_module(series) +exec(compile(_series_bytes, str(SERIES_PATH), 'exec'), series.__dict__) +DEPENDENCIES = {'p04_native_series.py': SERIES_SHA256} +DEPENDENCY_OBSERVATIONS = {'p04_native_series.py': str(SERIES_PATH)} CASES = ("S5A_PURE", "S5B_DEPENDENCY") GUEST = "p04.s5.guest.a" @@ -96,6 +105,7 @@ def duplicate_check(replay_node, recorded): def derive(root, writer_sha, reader_sha): + root = Path(root).resolve(strict=True) raw = Raw(root) writer = json.loads(raw.pin(root / "writer.json", writer_sha), object_pairs_hook=unique) reader = json.loads(raw.pin(root / "reader.json", reader_sha), object_pairs_hook=unique)