From 6f75c9a0513aafe5bd6ae7ed46b0ffda6386ac50 Mon Sep 17 00:00:00 2001 From: Agent Control Runner Date: Wed, 21 Oct 2026 10:10:39 +0900 Subject: [PATCH 1/4] =?UTF-8?q?P28-02-EQ:=20=E6=84=8F=E5=91=B3=E3=82=92?= =?UTF-8?q?=E4=BF=9D=E3=81=A4=E8=BB=BD=E9=87=8F=E5=8C=96=EF=BC=9A=E5=90=8C?= =?UTF-8?q?=E7=AD=89=E6=80=A7=E3=81=AE=E5=85=88=E8=A1=8C=E5=9B=BA=E5=AE=9A?= =?UTF-8?q?=EF=BC=88harness=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../execution/p28-02/eq/IMPLEMENTATION.md | 579 ++++++ .../execution/p28-02/eq/PROGRESS.md | 236 +++ .../execution/p28-02/eq/S2_SUPPLEMENTARY.json | 33 + .../p28-02/eq/S3A_SUPPLEMENTARY.json | 41 + .../p28-02/eq/S3B_SUPPLEMENTARY.json | 49 + .../execution/p28-02/eq/S4_SUPPLEMENTARY.json | 549 ++++++ .../execution/p28-02/eq/UNIT_OUTPUT.sha256 | 1 + .../execution/p28-02/eq/UNIT_OUTPUT.txt | 154 ++ .../p28-02/eq/UNIT_OUTPUT_ATTEMPT_01.sha256 | 1 + .../p28-02/eq/UNIT_OUTPUT_ATTEMPT_01.txt | 48 + .../p28-02/eq/UNIT_OUTPUT_ATTEMPT_02.sha256 | 1 + .../p28-02/eq/UNIT_OUTPUT_ATTEMPT_02.txt | 46 + .../p28-02/eq/UNIT_OUTPUT_S1_FINAL.sha256 | 1 + .../p28-02/eq/UNIT_OUTPUT_S1_FINAL.txt | 48 + .../eq/UNIT_OUTPUT_S2_ATTEMPT_01.sha256 | 1 + .../p28-02/eq/UNIT_OUTPUT_S2_ATTEMPT_01.txt | 73 + .../eq/UNIT_OUTPUT_S2_ATTEMPT_02.sha256 | 1 + .../p28-02/eq/UNIT_OUTPUT_S2_ATTEMPT_02.txt | 76 + .../eq/UNIT_OUTPUT_S2_ATTEMPT_03.sha256 | 1 + .../p28-02/eq/UNIT_OUTPUT_S2_ATTEMPT_03.txt | 77 + .../eq/UNIT_OUTPUT_S3A_ATTEMPT_01.sha256 | 1 + .../p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_01.txt | 77 + .../eq/UNIT_OUTPUT_S3A_ATTEMPT_02.sha256 | 1 + .../p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_02.txt | 90 + .../eq/UNIT_OUTPUT_S3A_ATTEMPT_03.sha256 | 1 + .../p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_03.txt | 96 + .../eq/UNIT_OUTPUT_S3A_ATTEMPT_04.sha256 | 1 + .../p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_04.txt | 96 + .../eq/UNIT_OUTPUT_S3B_ATTEMPT_01.sha256 | 1 + .../p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_01.txt | 96 + .../eq/UNIT_OUTPUT_S3B_ATTEMPT_02.sha256 | 1 + .../p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_02.txt | 4 + .../eq/UNIT_OUTPUT_S3B_ATTEMPT_03.sha256 | 1 + .../p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_03.txt | 127 ++ .../eq/UNIT_OUTPUT_S3B_ATTEMPT_04.sha256 | 1 + .../p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_04.txt | 119 ++ .../eq/UNIT_OUTPUT_S3B_ATTEMPT_05.sha256 | 1 + .../p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_05.txt | 119 ++ .../eq/UNIT_OUTPUT_S3B_ATTEMPT_06.sha256 | 1 + .../p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_06.txt | 123 ++ .../eq/UNIT_OUTPUT_S3B_ATTEMPT_07.sha256 | 1 + .../p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_07.txt | 14 + .../eq/UNIT_OUTPUT_S3B_ATTEMPT_08.sha256 | 1 + .../p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_08.txt | 132 ++ .../eq/UNIT_OUTPUT_S3B_ATTEMPT_09.sha256 | 1 + .../p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_09.txt | 124 ++ .../eq/UNIT_OUTPUT_S4_ATTEMPT_01.sha256 | 1 + .../p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_01.txt | 10 + .../eq/UNIT_OUTPUT_S4_ATTEMPT_02.sha256 | 1 + .../p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_02.txt | 328 ++++ .../eq/UNIT_OUTPUT_S4_ATTEMPT_03.sha256 | 1 + .../p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_03.txt | 14 + .../eq/UNIT_OUTPUT_S4_ATTEMPT_04.sha256 | 1 + .../p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_04.txt | 21 + .../eq/UNIT_OUTPUT_S4_ATTEMPT_05.sha256 | 1 + .../p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_05.txt | 137 ++ .../eq/UNIT_OUTPUT_S4_ATTEMPT_06.sha256 | 1 + .../p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_06.txt | 139 ++ .../eq/UNIT_OUTPUT_S4_ATTEMPT_07.sha256 | 1 + .../p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_07.txt | 28 + .../eq/UNIT_OUTPUT_S4_ATTEMPT_08.sha256 | 1 + .../p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_08.txt | 17 + .../eq/UNIT_OUTPUT_S4_ATTEMPT_09.sha256 | 1 + .../p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_09.txt | 11 + .../eq/UNIT_OUTPUT_S4_ATTEMPT_10.sha256 | 1 + .../p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_10.txt | 154 ++ .../execution/p28-02/eq/check_eq.py | 873 +++++++++ .../execution/p28-02/eq/compare_versions.py | 651 +++++++ .../execution/p28-02/eq/eq_probe.gd | 808 ++++++++ .../execution/p28-02/eq/run_eq.py | 273 +++ .../execution/p28-02/eq/test_eq.py | 1702 +++++++++++++++++ .../execution/p28-02/eq/verify_eq.py | 254 +++ 72 files changed, 8676 insertions(+) create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/IMPLEMENTATION.md create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/PROGRESS.md create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/S2_SUPPLEMENTARY.json create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/S3A_SUPPLEMENTARY.json create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/S3B_SUPPLEMENTARY.json create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/S4_SUPPLEMENTARY.json create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT.txt create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_ATTEMPT_01.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_ATTEMPT_01.txt create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_ATTEMPT_02.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_ATTEMPT_02.txt create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S1_FINAL.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S1_FINAL.txt create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S2_ATTEMPT_01.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S2_ATTEMPT_01.txt create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S2_ATTEMPT_02.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S2_ATTEMPT_02.txt create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S2_ATTEMPT_03.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S2_ATTEMPT_03.txt create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_01.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_01.txt create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_02.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_02.txt create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_03.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_03.txt create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_04.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_04.txt create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_01.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_01.txt create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_02.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_02.txt create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_03.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_03.txt create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_04.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_04.txt create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_05.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_05.txt create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_06.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_06.txt create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_07.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_07.txt create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_08.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_08.txt create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_09.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_09.txt create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_01.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_01.txt create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_02.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_02.txt create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_03.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_03.txt create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_04.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_04.txt create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_05.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_05.txt create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_06.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_06.txt create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_07.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_07.txt create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_08.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_08.txt create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_09.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_09.txt create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_10.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_10.txt create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/check_eq.py create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/eq_probe.gd create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/run_eq.py create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/verify_eq.py diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/IMPLEMENTATION.md b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/IMPLEMENTATION.md new file mode 100644 index 0000000..a46d108 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/IMPLEMENTATION.md @@ -0,0 +1,579 @@ +# P28-02-EQ S4 implementation — retained completion r03 + +S4 retains the existing driver/verifier and all 134 prior test bodies (including +the original 119). The only production-code correction in this completion is +to require `check_probe(...)["ok"]` in driver admission and verifier recompute, +with every error included in the rejection. `--check` and `--run` share the same +admission gate. Unit tests mock the run boundary; no engine is launched. + +The call-site check was limited to run_eq.py and verify_eq.py as instructed. +Other calls to check_python_imports, check_observation and check_lifecycle raise +on rejection and return True on success; check_report already requires `ok`. +DIAG check_imports/bound_raw and collector stage_gate/guard_gate reject by +exception. In particular, the collector gates' successful None is not false. +No further ignored verdict-dictionary call was found in these two files. + +## Complete S4 requirement-to-code and test map + +The following is the current S4 map. Earlier stage notes below are preserved +historical records, including statements of work that was pending at that time. +All tests cited here are engine-free, synthetic evidence tests, not native proof. + +| Retained requirement (S4 must / binding / r01-r03) | Code | Unit coverage | +| --- | --- | --- | +| S1: pin full source map, EQ and allowed dependencies, engine, fixture, admission | run_eq.DEPENDENCIES/FROZEN, load_dependencies, actual_pins, frozen_commit; verify_eq.verify repeats actual pins | SourcesAndMetrics source closure/pin tests; S4Bundle.test_import_closure_rejections; S4NativeBundleLogic.test_receipt_and_source_rejection_matrix | +| S2: independently bind lifecycle and audio SHA; reject missing/error even with stdout | verify_eq.NAMES, phase_evidence, check_audio; lifecycle inventory excludes only lifecycle/audio | S4Bundle.test_missing_private_evidence_and_extra_rejected, test_phase_role_pid_audio_and_guard_rejected, test_rebound_lifecycle_and_scenario_contradictions | +| S2: retain raw and joined separately with normalization evidence; join before compare | phase_evidence calls check.join_report; run writes raw/joined/proofs/checker JSON; seal hashes all; recompute compares joined reports | S4Bundle.test_synthetic_phase_all_real_checkers_not_native_proof; S4RemainingBindings.test_nonzero_determinism_rejected_after_real_join; Normalization sidecar rejection tests | +| S2: full observation bytes/SHA and lifecycle guard/preparation/cleanup | phase_evidence calls check_observation for all 31 checkpoints and check_lifecycle(raw, life, guard) | S2Format observation/lifecycle tests; S4Bundle positive and contradiction tests | +| S3a: strict_json, measurement passed, all private files SHA bound | verify_eq.read, check.read_report_stdout, phase_evidence exact inventory and check_report(raw, life.measurement, life.e3, life.e3_b1, life.e45) | S3a.test_duplicate_JSON_key_rejected; S4Bundle positive, missing evidence and contradictions | +| S3a: lifecycle.e3/e3_b1, all 18 e3 files, full package evidence and checker outcomes | phase_evidence binds each e3 row to lifecycle and raw; package bytes remain inside e3 evidence; copy_profile also retains all package/log/config files | S3a package/NA/code/event rejection tests; S4Bundle scenario/b1 rejection matrix | +| S3b: lifecycle.e45, all 21 e45 files, 39 ordered scenarios, continuous intervals | NAMES, phase_evidence count/copy checks; existing check_report/check_e45 continuity checks | S4Bundle contradictions; S3b scenario ordering/continuity and ownership tests | +| S3b: join_facts sidecars/proofs and checker results with raw facts | check.join_report/check.join_facts reused unchanged; phase_evidence returns raw/joined/proofs/checker; verify compares their stored copies with recomputation | S3b facts/normalization tests; S4Bundle positive; S4NativeBundleLogic.test_synthetic_full_bundle_positive_not_native_evidence | +| S3b: separate R-A/R-B and O-A/O-B comparisons; zero differences required | verify_eq.recompute explicit role loop, requires ok and empty differences | S4NativeBundleLogic positive and cross-role rejection; S4RemainingBindings determinism rejection | +| S3b: preserve existing-defect, aliasing, cached digest facts, never manufacture PASS | phase_evidence preserves existing checker outcomes and raw facts | S4Bundle positive explicitly asserts existing-defect; S3b.test_aliasing_cannot_be_PASS, test_aliasing_missing_record and digest tests | +| r01: seven owned phases in exact order, parse --check-only, headless runtime | run_eq.plan/run; verify_eq.PHASES/recompute validates commands, phase, role, PID and timestamps | S4NativeBundleLogic positive and receipt matrix; S4RemainingBindings owned lifecycle matrix | +| r01: guard before parent, unique fresh startup/runtime profiles, env/role/fixture bindings | wrapper_text, plan, run_private_engine, guard_gate; recompute validates wrapper, 14 distinct profiles and 7 PIDs | S4Bundle guard/role/audio matrix; S4NativeBundleLogic startup-name rejection; S4RemainingBindings profile-reuse rejection | +| r01: gates return None; absent profile empty inventory is not export success | run uses gates directly; copy_evidence requires exact existing inventory; copy_profile records exists separately | S4NativeBundleLogic.test_gate_none_success_not_boolean; S4Bundle.test_missing_profile_not_export_success | +| r01: original absolute input destinations, never substitute copied root | actual_pins invokes collector.inputs on original readonly and checks nine unique destinations | S4NativeBundleLogic.test_copied_manifest_root_and_destination_count_rejected; S4RemainingBindings.test_nine_original_destinations_required | +| r01: finally cleanup, source/project/default-player preservation; failures retained without seal | run finally captures cleanup/errors, profiles, pins and execution; recompute validates preservation/cleanup; seal only on success | S4NativeBundleLogic.test_failure_keeps_raw_and_no_bundle_without_starting_engine and cleanup/source matrix | +| r01: complete copies, exact evidence inventory, final manifest/seal, no overwrite | copy_evidence/copy_profile verify before/after copy; inventory/pin; seal writes manifest then seal; write uses x mode | S4Bundle seal/missing/changed/extra/existing-output tests; S4NativeBundleLogic full synthetic bundle | +| r01: verifier reads bundle at BUILD_OUTPUT_DIR/p28-02-eq-evidence, recomputes raw checks and stored results | verify_eq.main/verify/check_seal/recompute; no writes in verification | S4Bundle missing bundle/seal/manifest tests; S4NativeBundleLogic full verify positive | +| r02: collector read-only import in closed D1+DIAG+EQ set; never import restart_pair | load_dependencies pins all 11 external files, checks loaded module closure and Python imports; copying implemented in EQ | S4Bundle.test_import_closure_rejections explicitly rejects restart_pair and other unapproved imports | +| r02: exact raw3 stdout.log, stderr.log, engine-native.log; exit comes from owned process.json, not raw3 | collector.run_private_engine and DIAG.bound_raw reused; recompute checks owned JSON/diagnostics | S4NativeBundleLogic receipt matrix missing native log/owned/exit-in-raw; S4RemainingBindings exit/start/end/diagnostic rejection | +| r02: exact private names and API arguments | NAMES = checkpoint 00..30, observation 00..30, e3 00..17, e45 00..20, events/report/lifecycle/audio-close; phase_evidence passes all five check_report args and guard to check_lifecycle | S4Bundle positive, missing/extra evidence and scenario matrix | +| r02: synthetic writes outside checkout; verifier read-only | test_eq.synthetic_directory uses BUILD_OUTPUT_DIR or tempfile.gettempdir and rejects checkout descendants; verify outputs only stdout | S4Bundle.test_checkout_temp_destination_rejected; full synthetic verify test | +| r03: enforce false static verdict, include all errors, both driver modes and verifier | run_eq.main and verify_eq.recompute require static.ok | S4ProbeAdmission four tests; S4RemainingBindings verifier false/true tests | +| r03: preserve original context bytes and all plans; retain old failures and test bodies | S4_SUPPLEMENTARY.json loads Root original JSON unchanged, records five source pins and eight verified plan hashes; retained test prefix reconstructs original SHA | Source/plan assertions recorded in supplementary; final unit output and SHA recorded separately | +| r01-r03: S_eq native is not Q; no acceptance/credit from units; exact submitted/base | admission/recompute carry S_eq-native-not-Q, candidate_Q_measured false, formal_acceptance false, original_credit 0 | S4NativeBundleLogic Q-label rejection and positive; final worker JSON uses submitted only after full local PASS | + +## Completion evidence and limits + +The original 134-test file can be recovered by removing only the newly appended +classes and retaining its original unittest main; its SHA is +cb742b252dbc278113b3c11c2431adac35b0c2e201a762a8ea1ac926e4af414b, +matching Root's retained record. This also preserves all 119 earlier bodies. +S4_SUPPLEMENTARY preserves all eight plans/API notes/clarification references +directly from the supplied r09 JSON, plus the exact r03 text and decision. +All five source SHA checks and all eight plan SHA checks succeeded. + +Attempt 07 exposed a newly added test's overbroad comparator mock: it injected a +difference into the report's self-check before the intended cross-PID gate. +Only that new test was corrected to retain the real identity self-comparison. +Attempt 07 raw/exit/SHA remain a failure. Attempt 08 rechecks the added classes +(9 tests, 86.276 seconds, OK, exit 0). Attempt 09 covers the three added +S4StoredResultBindings tests (0.025 seconds, OK, exit 0): verify must reject a +cached verdict differing from recomputation, missing sidecars, and raw/joined +substitution even when the supplied files have a valid seal. These isolate the +stored-result equality gate with a recomputation mock; full real recomputation +remains covered by the existing and new native-bundle-logic classes. +Prior attempt 01 syntax, 02 unit, 04 recompute and supplementary assert failures +remain historical failures. Attempt 05's 132 PASS and late attempt 06's 134 OK +do not prove this version; the latter has no provider completion/exit receipt. +Final full local evidence: attempt 10 ran all 146 tests in 293.277 seconds, +OK, exit 0 (outer wall time 293.5742515 seconds). Raw is retained in +UNIT_OUTPUT_S4_ATTEMPT_10.txt and UNIT_OUTPUT.txt, SHA-256 +ff6fc0065772434f9ca35a1267e24d199057e339869a868942a41829327503bb. +This was the single final full run after the targeted fixes and all additions. + +An attempted read of Root's external retained test copy returned PermissionError. +No permission change was attempted; exact retained-prefix SHA verification +provided the same preservation check inside the allowed workspace. A shell +heredoc read also failed before execution; subsequent reads used python -c. + +Root still must run the exact submitted S in seven native phases, place the +bundle, run p28-02-eq-unit and p28-02-eq-native-verify, obtain fresh independent +Opus review of all six conditions, and complete qualification/approval/ +integration/final before OPT and whole-unit gates. Original credit is zero; +23/88 and 4/30 are unchanged. No native, accepted S, Q or product PASS is claimed. + +## Retained S1-S3b implementation history + +# P28-02-EQ S1 implementation + +## Scope and authority + +This run implements only staged plan r02 S1: `compare_versions.py`, synthetic +`test_eq.py`, progress and unit evidence. No product, SPEC, TASK, references, +registration, git, engine, Runner, or other worker operations are performed. +S2–S4 and all six formal acceptance gates remain pending. A successful comparison +is not a product E3/E5 PASS and does not establish native harness acceptance. + +Read-only clarification SHA-256 checks matched the supplied values: + +- r01: `25d323fd562d29e80782b6f075fc7a0e8b49457a6c4fbd7c30e74b31a6b6a126` +- r02: `777accdd652f85db6b9014d85e3c8b3b60ca94b20768e6173b36bc769d360fd9` +- r03: `12b27f984ef5843d98327200ad261dccaf64968402192b08ad55b15ed5454ea2` + +SPEC file bytes SHA is `3791ccdcb87e8d71fe9205e1e692ebca9e0f974ea3b5fbc4fbb3943882131f1c`, +matching `registration/ROOT_PROPOSAL_BYTE_TRANSFER.json`. Removing the final LF +gives the supplied contract text SHA `cf75af22a803bf492e30f8a04a39f5187ece5b94cd54207aad8ece1683d4bc93`. +Neither representation was rewritten. + +## Internal transport choices for S2 + +- Standard-library-only Python; no product or unapproved dependency imports. +- Nodes follow plan r02 A1. Scalars retain their Variant codes. Float payloads + are 16 lowercase hex digits for little-endian f64, including signed zero and + NaN bit patterns. Strings are never coerced to StringName. NodePath uses type + 22 with its string payload. RID/Object/Callable/Signal are rejected. +- Composite math types use flat scalar components (AABB: 6, Basis: 9, + Transform3D: 12, Projection: 16). Packed arrays retain their type code. +- Array `typed_info` is null or `[builtin_int_node, class_StringName_node, + script_null_node]`. Dictionary metadata is null or `[key_info, value_info]` + using that same triple. Object/script-bearing values are not transported. +- A path is a list of `["key", key_node]` or `["index", integer]` segments. + Dictionary keys retain types and insertion order; indexes address Arrays. + Empty path addresses the root. Mutations operate on deep copies, validate + bounds and duplicate keys, and reject unknown operation fields. +- `array_splice` uses `nodes` for the inserted list; `dict_insert` uses `index`, + `key_node`, `value_node`. Other operation names/fields follow A3. +- A transport record has exactly `tree` or `diff`, `tree_sha`, + `raw_bytes_sha`, `roundtrip_ok`. Checkpoint S diffs apply to the previous S; + latest diffs apply to current S. latest may instead have `same_as_S: true` + and the three proof fields, with matching S raw-byte SHA. +- `tree_sha` is SHA-256 of compact, insertion-order UTF-8 JSON, no ASCII escaping, + no whitespace, no terminal newline. S2 must produce this representation and + prove Godot byte roundtrip. Python never claims it can independently recreate + Godot's var_to_bytes from a reported SHA or boolean. +- There is no application depth cutoff or depth-4 hash summary. Entire trees + are reconstructed and checked at each checkpoint. Resource/JSON parser limits + remain ordinary process limits; malformed evidence is not a PASS. +- Exact tree equality comes first. Text-key dictionary fallback preserves every + key's type, every typed-info value, and array order, records all changed + dictionary orders, and rejects duplicate textual keys. Scalar key spellings + use their string/integer/bool/null text; float and compound keys use lossless + compact typed JSON spelling, without decimal conversion. Original key nodes + are always compared as well, so this sorting cannot erase key type or bits. + +## F1–F3 and restoration + +The required four functions return/consume `(normalized, sidecar)` with precisely +`entries`, `violations`, `profile_root` as sidecar keys. `profile_root` input is +`{"root": , "actual_user_data_dir": }`. +The sidecar adds `matches_guard: true` inside this object after checking equality. + +Only top-level E2 event payloads, or elements of snapshot +`systems.runtime.domain_events.recent_events`, qualify. Nested event-shaped +payload data and lookalike events elsewhere do not qualify. The nine event types +and `save_service` source are closed. Both timing fields must exist and be +nonnegative ints. Their markers are typed Dictionary nodes representing the +r02 marker, not numeric substitutes. F3 preserves the whole original String +node and root, and replaces every exact root-plus-slash occurrence. A preexisting +reserved token is rejected to avoid ambiguous inversion. + +Entries retain event index (null for snapshot trees), typed path, key and original +node; F3 also retains root. Tree paths preserve event position, while comparison +separately checks the actual event_id without remapping. Unknown timing/profile +values remain unchanged and recorded as violations. Violation presence alone is +not failure. Their actual differences are ordinary full-tree differences. + +Restoration re-applies the closed normalization policy to reject missing, +duplicate, forged or unauthorized entries. The independent original tree SHA +must also match after restoration: changing a timing value in a sidecar to +another valid timing cannot be detected from the marker alone. The comparator +performs this SHA check against retained raw transport trees; unit tests include +this forgery. A sidecar is not an independent authority for its own integrity. + +`validate_scenario_paths` accepts only fixed `user://p28_eq/{r,o}/` names: +good, tampered_world, missing_key, wrong_type, out_of_range, duplicate_id. +S3 must use these names and deterministic metadata/tamper rules. + +## Joined comparison report interface + +Report keys are closed: `schema` (`p28-02-eq/typed-v1`), `role` (R/O), +`profile_root`, `checkpoints`, `events`, `event_start`, `event_end`, `signal_order`, +`scenarios`. No missing value is defaulted to zero. Manifest/package records +belong to the bundle, not the S comparison report. + +- Main checkpoints: 31 records, consecutive minutes. Each contains `minute`, S + and latest transports, `latest_digest`, `computed_latest_digest`, + `harness_normalized_digest`, K, C, and `observation`. +- Observation has `before`/`after`, each with complete S/K/C bytes SHA values. + Equality is mandatory before environment normalization. S2 must obtain these + from the complete raw layers, including telemetry and instance IDs. +- Digest self-consistency is mandatory in each PID. If latest has F1–F3 entries, + compare the explicitly labeled harness normalized digest and preserve both + product digests with an exclusion reason. Otherwise compare product digests. + Full S and latest comparison is mandatory in either case. +- K uses the SPEC names, `_accumulator` as f64 hex, `_phase_handlers` as phase + string to handler-ID list (compared as sets), and `performance_budget` with + `_sample_counts`, `_samples`, `_totals`. Unknown/missing fields are rejected. +- C has `_mvp_manifest_cache_generation`, `catalog_is_current`, + `_mvp_manifest_cache_bytes` (complete base64 var_to_bytes), + `catalog_instance_id`, `current_catalog_instance_id`. +- Each excluded telemetry/instance-ID field retains a reason and both raw values. +- `event_start` has counter and published_ids_count. A mismatch invalidates + correspondence. Event rows have sequence (zero-based receive order), transport, + and original_field_types. All original types and all tree fields are compared; + no cap is applied. S2's checker must enforce the exact product event shape and + required original type observations. `event_end` and signal order also compare. +- Scenarios have id, operation, result, checkpoints and events (raw typed event + trees). Result retains actual codes, ownership results, changed paths/values, + boundaries and event counts defined by S3. State checkpoints use the same + full-state machinery. Matching existing product failures remain matching + failures, never rewritten as PASS. S3's checker must enforce scenario coverage, + allowed operations and absolute product acceptance separately. + +`compare_reports` reports differences with both actual values, dictionary-order +paths, exclusions, violations and digest mode. Evidence errors yield `ok: false`. +It does not replace `check_eq` or native/source admission: empty synthetic +scenario lists can be compared in S1 tests; they cannot satisfy S3 acceptance. + +## Source closure and performance + +`check_source_closure` hard-pins the collector's sorted compact JSON map digest +`651f703621c8ed06a724709f75d8bc05b1eef2988c3b3d5d3466096a3f759bf0` and 1407 entries. +Each row is bytes plus SHA-256. Added/missing paths fail. The exact changed set +must equal the supplied registered set, which must be a subset of the six OPT +paths. The caller cannot replace the before pin. S4 must separately pin all +EQ/DIAG/RESTART/collector bytes, engine, fixture and admission metadata. + +Source closure unit tests inject a synthetic map pin *only within unittest mock* +to exercise positive closure mechanics; a separate test proves the real function +rejects that synthetic map with the production pin. No product hooks are replaced. + +`classify_improvement` implements SPEC §4 strict disjoint ranges of three finite, +nonnegative measurements; markers and absent samples are rejected. Actual metric +collection and the combined OPT adoption decision remain later native work. + +## Validation and preservation + +Only `python3 test_eq.py` is executed, with synthetic inputs and bytecode disabled. +The first run's missing-F3-sidecar failure is preserved unchanged in +`UNIT_OUTPUT_ATTEMPT_01.txt` with SHA. The implementation now rejects the leftover +reserved token after restoration. The intermediate successful run is also kept. +`UNIT_OUTPUT.txt` is the latest complete raw output, with a separate SHA file. +These are local unit results, not Runner/native validation or Q measurements. + +## S2 implementation (repair 4) + +S2 only is complete. S1 compare_versions.py is byte-identical to its supplied +058f3fef... pin. The original 43 test bodies are retained; S2 adds 29 tests. +E3/E4/E5 execution and S4 driver/verification are deliberately not implemented +by this run. All six formal acceptance conditions remain pending. + +### Probe and evidence + +- eq_probe.gd follows the six DIAG lifecycle stages: public paused preparation; + main with two deferred frames; 30 warm steps; 30 observed steps; outside-tick + observations; observer teardown and close_requested.emit(). R uses the pinned + fixture and starts B0 at 602/B1 at 632. O keeps the new 360-minute state, lets + main enable Ops, and uses the same warm sequence (B1 390). The actual Ops + result and all preparation/frame/B0/B1 values are retained, never substituted. +- THE_TREE_EQ_ROLE is R or O. THE_TREE_P28_FIXTURE supplies R. The fixture SHA + is pinned in the probe. The existing guard wrapper supplies + THE_TREE_PACK_PROFILE_REPORT. No separate profile root from environment is + trusted: bind_profile reads the receipt, reads the live globalized user root, + checks OS.get_user_data_dir too, and records the receipt and SHA. +- Every supported Variant is encoded using the S1 A1 representation. All math + components, packed arrays, StringName/NodePath and typed container metadata + retain their types. Unsupported object-bearing nodes append an error and + fail transport/proof; they are not silently stringified. Full bytes roundtrip + is performed by encode -> decode -> var_to_bytes in Godot. Python's synthetic + tests do not establish that Godot execution succeeded. +- Diff production uses exact recursive set operations and array_splice. Changed + Dictionary key lists/order/metadata replace the whole affected subtree using + set; unchanged key lists recurse into every value. This is a valid subset of + A3 operations and has no depth limit. The emitted operations are replayed in + Godot and checked before export, then replayed independently by the existing + Python comparator. No S1 diff interface changes. +- evidence/checkpoint-00.json holds the full B1 S tree; checkpoint-01..30.json + hold S diffs from the previous checkpoint. Latest uses same_as_S only for + equal bytes; otherwise it holds a diff from that checkpoint's S. +- evidence/observation-00..30.json retain complete before/after S/K/C bytes + (base64) plus hashes, K/C actual values. K includes all telemetry and C includes + actual instance IDs. Reading a state witness also checks that create_snapshot + did not change K or C. Cache filling is an explicit recorded preparation. +- Domain events are captured through wildcard subscription after B1 and through + the last tick/frame, without a cap. to_dictionary() transport includes its own + byte roundtrip proof and receive-order sequence. original_field_types observes + all seven object fields; entity_ids and payload include typed_info. +- evidence/events.json, report.json, lifecycle.json and audio-close.json retain + the run data. lifecycle has preparation, Ops/save policy, raw baseline/frame + values, warm signals, guard binding, observer inventories, error list, and + file hashes. File writes refuse overwrites. The lifecycle inventory excludes + its own hash and the later audio receipt; S4 must bind both independently. + S4 must reject missing lifecycle/audio or errors even if a stdout report exists. +- stdout emits exactly one P28_02_EQ_REPORT= line with the unchanged S1 closed + schema. Report also contains full transports; private files are independently + bound copies, not substitutes for raw output. + +### Python joining and checking + +- S1 calls this a *joined comparison report*. The raw probe leaves + harness_normalized_digest null because F1-F3 has one implementation, in Python. + check_eq.join_report(raw) reconstructs all trees, checks their proof hashes, + normalizes/restores using S1, and returns a copy plus complete sidecars. It + fills that existing field with a harness-only typed canonical SHA, not a + product SimulationDigest. Only Dictionary enumeration order is canonicalized; + key node types, scalar bits, metadata and Array order remain exact. This avoids + turning an allowed Dictionary-order fallback into a spurious digest failure. + normalized_tree_sha remains insertion-order sensitive for transport binding. + S4 must preserve and hash raw and joined outputs separately, call this join + before compare_reports, and retain normalization evidence. Product latest_digest + and computed_latest_digest always remain the actual Godot values. +- check_report is explicitly an S2 format/contradiction check with + formal_acceptance=false. It enforces 31 checkpoints, minute/counter coherence, + full S/latest/K/C, observation proof, actual event field types, unaltered event + IDs, and event coverage against endpoint published_ids. Empty or unknown + transport fields do not pass as a digest-only comparison. +- check_observation binds full raw bytes to SHA witnesses. check_lifecycle binds + the separately collected guard receipt and checks actual preparation/teardown + evidence. These functions must be called by S4 when copied evidence is joined. +- check_probe is a conservative static screen, not a Godot parser or proof of + arbitrary GDScript safety. It rejects inferred declarations, static autoload + references/imports, live writes, unlisted/dynamic live dispatch, mutation calls + outside preparation/stepping, nontextual sort, event truncation, and missing + full-state/roundtrip/guard operations. Native parse-base/parse-wrapper and + independent source review remain mandatory. +- E3/E4/E5 scenarios are absent and check_report explicitly rejects nonempty + scenario lists at this stage. S3 must extend coverage/absolute product-outcome + checking and static allowed scenario boundaries without weakening S2 checks. + +### Local validation and preserved history + +Engine-free command: python3 -B test_eq.py. S2 attempts 01/02/03 passed +68/71/72 tests respectively. Each complete raw output and SHA is retained. +The final 72 include all 43 S1 tests and 29 S2 tests. +UNIT_OUTPUT.txt is the final raw output; UNIT_OUTPUT_S1_FINAL.txt preserves the +previous 43-test final output. Original UNIT_OUTPUT_ATTEMPT_01 (failure) and +ATTEMPT_02 remain unchanged with their hashes. No failure was rewritten. + +The first attempted shell heredoc was refused by the environment before it wrote +a file (temporary-file creation denied). apply_patch and direct Python writes +inside eq/ succeeded; no engine or Runner operation was attempted. + +S2_SUPPLEMENTARY.json contains one actual_commander_context key with the full +unedited r01/r02 plans, the full supplied RUN decision, and the read-only +clarification paths/SHA. Both full plan texts reproduce their supplied hashes. +This is a preserved instruction packet, not a new commander decision. + +## S3a implementation (repair 5) + +Only the two specified S2 checker fixes and E3 are implemented. S3b (E4/E5), +S4, all native phases, both formal validations and all six acceptance conditions +remain pending. No product/engine/Runner/git-write/other-agent operation occurred. +The S1 comparator is unchanged (058f3fef57c2ebe6951a48d85d570a110b982e08a13c805c244fec7d5e9a0fe8). +Existing test bodies remain, except the S2 format helpers now provide the +required measurement inventory and full 30-minute pairs; S1 fixtures are unchanged. + +### Measurement binding + +check_report(raw, measurement=None, e3_evidence=None, b1_record=None) requires +the separately retained lifecycle.measurement. This keeps process object IDs +out of the unchanged joined-report schema and of cross-PID comparisons. +The inventory contains probe_object (actual instance ID), start_minute and the +full get_connections inventory. Both observer methods must belong to that +probe object exactly once. Every measured checkpoint after B1 must have exactly +snapshot_published then state_updated. Missing inventory never downgrades the +expectation. The exact string phase keys are 0 through 10; aliases such as 00 +fail. strict_json rejects duplicate object keys before they can be discarded. +S4 must use strict_json for raw JSON, pass measurement to check_report, and +bind lifecycle and all private files by SHA. The CLI now requires --lifecycle. + +### E3 intervals and raw evidence + +The measured stream closes before run_e3. There are 18 ordered entries: +restore_snapshot, validate, load_from_path, each with missing_key, wrong_type, +out_of_range, duplicate_published_ids, duplicate_facility, tampered_world. +Every entry retains applied/NA, its reason, invocation fact, actual B1 facility +count, code/null and API reason, bool/errors, migration fact and actual event +count. Dictionary-only world cases are NA. Envelope duplicate checks are invoked +and their whole return is retained, but remain NA, never an acceptance or defect +claim. O's zero-facility cases do not construct, substitute R or invent instances. + +B1 is decoded from its already observed lossless transport. Inputs are deep +copies with the specified fixed mutations. The unsupported manifest format is +the fixed integer 2147483647. Save metadata is empty. Duplicate packages share +the allowed fixed duplicate_id path sequentially; each original, modified and +post-operation package file is copied into that interval's evidence before any +later overwrite. The four-file inventory retains complete base64 bytes and SHA, +including absent files as null. world.bin uses offset len//2 XOR 1. Package +preparation uses SaveService.save_snapshot only inside the active E3 interval; +its actual return and exact input are retained. A refused duplicate save makes +load NA; a refused mandatory nonduplicate preparation fails the harness. + +Each scenario retains two full S/latest/K/C checkpoints in the existing S1 +schema. lifecycle.e3 and evidence/e3-NN.json additionally bind full raw layer +bytes, layer typed transports, observation witnesses, invocation boundary, +whole typed API return, all scenario event transports, separate signal records, +latest_save_operation_result and SaveService diagnostic budgets before/after. +check_e3 checks full byte witnesses, binds report to raw evidence and requires +continuity between intervals (starting at the last measured checkpoint). +No scenario reset or state repair is performed: later intervals use the actual +new baseline, including any unexpected product changes. + +join_report now derives the existing normalized digest field for scenario +checkpoints as well as measured checkpoints, using the unchanged S1 policy. +E3 report result summaries contain deterministic API facts; whole returns and +package diagnostics remain in SHA-bound raw evidence, not silently discarded. +Package timestamps and SaveService static diagnostic budgets have explicit +exclusion reasons and actual values in checker output. S1 continues to compare +the full normalized scenario state/events and deterministic results. + +### Product outcomes versus malformed evidence + +check_e3 derives source-backed expectations and outputs actual results, +expected event counts, typed path/value differences, dropped recent event, +normalization sidecars and existing-defect-candidate entries. It does not accept +a caller's PASS/defect label. Wrong counts, accepted invalid inputs or changed +state are recorded product candidates; a forged count versus the retained event +list is malformed harness evidence and fails admission. Missing load code, +invented restore/validate code, false NA/applicability, missing raw evidence or +unrecorded interval gaps also fail admission. + +For failed loads, X(B, ev_fail) increments the counter, sort-inserts the actual +unchanged ID and appends the event, retaining the dropped head at the 256 limit. +The full normalized state must match this expected tree. The checker also binds +payload to latest_save_operation_result and return facts, checks pause/restore +outcomes, and retains full K/C differences. Such differences are not suppressed +even when caused by the product's load accounting. Envelope duplicate acceptance +alone is explicitly not a defect. + +### Handoff and validation boundary + +The static screen admits the listed calls only in run_e3's active interval and +the sole package-preparation helper; it remains a conservative screen, not a +Godot parser. S3b extends scenario dispatch/coverage and the static count policy +for its own authorized operations. S4 must bind lifecycle.e3/e3_b1/measurement, +all e3-NN files, package evidence, raw/joined outputs and checker outcomes, and +call check_report and check_lifecycle. The current S2 synthetic empty-scenario +fixture remains useful for historical format tests; a S3a lifecycle requires +the complete 18-entry table and cannot pass with an empty scenario list. + +S3A_SUPPLEMENTARY.json has the single actual_commander_context key, containing +both unmodified staged plans, both S3 plans and the full effective RUN decision. +All four plan hashes match the supplied pins; read-only r01/r02/r03 paths remain +in eq-staged-readonly-r04. This is preserved authority, not a new decision. + +The local tests use synthetic bytes for Godot proof fields. Their PASS does not +prove native parsing, Godot roundtrip, fixture behavior or product acceptance. +Native execution is deliberately left to Root after S4, followed by Runner +validation and the fresh independent review. + +## S3b implementation (repair 7; E4-1 r02) + +S3b reuses the S1 transport/comparison, S2 measurement, and S3a observations. +E3's implementation and the original 91 test bodies remain unchanged. Rebuilding +the original test file from its retained prefix plus its original unittest main +reproduces f81185e506954964bb96b31a569233202a1a7e7c78b2121aba6ab3f2e24d7e1e. +The previous run 7da027a85548460bb008b562a79a52ae remains historical evidence: +its blocked enumeration question was resolved by the supplied S3b r02, not +retroactively labeled an implementation success. + +### Native scenario producer and raw binding + +- E4 runs after all 18 E3 intervals: build_facility, tick, restore_snapshot, + load_from_path, rejected_command. The next interval starts from the actual + previous end. All observations reuse e3_observation's complete immutable + S/K/C, bytes, typed proof, latest and both digest values. +- Registry IDs come from that PID's definition_registry.get_facility_ids(). + Both registered order and textual sorted order retain Array[StringName]. + Bounds come from world_service.get_bounds(); x and y are inclusive. + WorldService's public FRONT/BACK layers are 0 and 1. ID is the outer loop, + then x/y/z lexical order, rotation 0. Every tried candidate and complete + public preview dictionary is transported without truncation. The whole + read-only search has complete before/after observations; it does not repeat + large snapshots per candidate. Empty registry is a harness error; NA requires + exhausting a nonempty registry's entire nonempty world range. +- Chosen payload is passed to the ordinary submit_command API. Product source + :505-515 processes ready commands immediately when paused, and may publish + there. The harness records this actual submit boundary, then exactly one + advance_minutes(1), then the processed command result. It does not force + delayed command execution, unpause, or replace any executor. +- E4 load uses the already allowed fixed user://p28_eq/{r,o}/good path and empty + metadata. Complete package bytes/SHA, whole returns, static SaveService + diagnostic budgets and latest_save_operation_result are retained. Restore + requires zero events; load requires one SAVE_LOADED and the existing e3_x + implementation of X(P,event). Payload is bound to latest_save_operation_result. +- E4 rejected command records the full submit and tick deltas separately: + bookkeeping, clock and any other actual changed path/value remain visible. + No current-run cache-staleness verdict is invented from publication timing. +- E5 covers all four targets, both fixed nested locations and both directions. + Signal handlers only retain references and record signals. Mutations occur + after the handler has returned. Each interval has start, preparation-tick + baseline, immediate operation result, and reset-tick end observations. + Deep copies and original returned values have complete transport proofs. + Each next baseline follows a recorded publication, with no direct repair. +- lifecycle.e45 and evidence/e45-00..20.json bind these 21 intervals. + report.scenarios contains the original 18 E3 rows followed by these 21 rows. + Scenario events are uncapped typed transports. All scenario signals remain + separate from measured signals, and are also bound into comparison facts. + +### Checker, comparison and existing defects + +check_report retains its original first four parameters and adds optional +e45_evidence. S3a-only callers continue to work; S3b lifecycle admission requires +all 39 scenarios and all raw evidence. check_e3 itself is unchanged; its caller +passes exactly the retained first 18 rows for S3b. + +check_e45 rejects missing/reordered paths/combinations, interval gaps, false NA, +wrong registry/order/bounds/rotation, missing trials/previews, unmatched chosen +candidates, event count/identity coverage gaps, malformed signals, missing +ownership mutation/proof, and caller-supplied PASS or cache-staleness verdicts. +Outcome status is derived: recorded, NA, or existing-defect. Actual full typed +differences and both digest values are retained per scenario. + +Raw result.facts is bound exactly to detail before joining. join_facts transports +all deterministic selection/command/signal facts and normalizes only snapshot +transports (input/held_before/held_after) using S1's unchanged closed F1-F3 policy. +Full inverse proofs and raw facts are retained. Package/API diagnostics remain +in raw evidence with explicit exclusion reasons/values, never discarded. +Search raw S/K/C stays in lifecycle evidence; its immutability is checked, and +the enclosing scenario checkpoints retain cross-PID K/C comparison. + +Two failing added tests justified narrow S1 comparator extensions: +1. Only checkpoint index 2 of one of the eight named E5 outside_in intervals + (four checkpoints, matching operation) can record a cached/computed digest + mismatch as a product fact. Other checkpoint/self-consistency checks remain. + Both sides' consistency outcomes compare, and digest exclusions follow the + same F1-F3 rule. check_e45 reports cached_digest_aliasing as an existing defect. +2. Joined S3b result facts contain typed trees; they use the existing full + compare_trees dictionary-order-only fallback, preserving type/value/array + differences and recording every dictionary-order path. +Neither exception turns product ownership failures into PASS. + +The static checker extends only the listed E4/E5 operations and active intervals, +checks selection-source proof snippets, forbids handler mutation and extra +dispatches, and retains all previous checks. It remains a conservative screen; +native parse and independent source review are still required. + +### S4 binding requirements (additional to the retained S3a requirements) + +S4 must copy/hash lifecycle.e45 and every e45-NN.json, bind them to the stdout/raw +report, call check_report with lifecycle.e45, and call check_lifecycle for S3b. +Join raw reports before compare_reports; retain join_facts sidecars/proofs and +checker outcomes with the raw values. Compare R-A/R-B and O-A/O-B separately. +Preserve existing-defect outcomes, including aliasing, in the final bundle. +Do not call unit evidence a native run, accepted S, Q measurement, or product PASS. + +S3B_SUPPLEMENTARY.json has one actual_commander_context key with all six full +plans, the full effective RUN decision, and read-only clarification references. +All six plan content hashes match the user-provided pins. SPEC, TASK, references, +registration and prior supplementary files are unchanged. No engine, Runner, +git write, other agent, product edit or full regression has run. + + +Final S3b local validation: python3 -B test_eq.py, 119 tests, OK, exit 0. +Raw: UNIT_OUTPUT_S3B_ATTEMPT_09.txt and UNIT_OUTPUT.txt. SHA-256: 8360a2065b303099d5c546b3e4aecc0cc0ab0c2c1e5120b8034b6a1a64317030. +Attempts 02/03/07/08 retain the syntax, digest, dictionary-order and fixture +failures respectively; all earlier evidence remains unchanged. + +## S4 binding map (implementation in progress) + +| Retained requirement | Implementation / additional unit coverage | +| --- | --- | +| Full raw observations and checkpoint SHA | verify_eq: evidence inventory, check_observation, altered/missing witness rejection | +| Lifecycle and audio independently bound | verify_eq: exact evidence names, lifecycle.files, audio/PID checks | +| Measurement, E3, B1, E45 supplied explicitly | verify_eq: check_report with all five arguments; 39 scenarios and raw file equality | +| Guard before parent and fresh profiles | run_eq: collector guard_gate and run_private_engine; distinct startup/runtime bindings | +| Raw versus joined state, join_facts proofs | verify_eq: recompute join_report, preserve separate joined/proof/checker files | +| Same-role determinism and existing defects | verify_eq: R-A/R-B and O-A/O-B only, preserve checker outcomes | +| Seven owned phases and complete raw3/owned5 | run_eq/verify_eq: ordered phases, collector receipts, strict diagnostic recheck | +| Closure, source 1407, frozen S and pins | run_eq: checked dependency import and full inventories; verifier repeats actual-file checks | +| Original absolute input destinations | run_eq: collector.inputs on original readonly; no copied-root substitution | +| Finally cleanup and failure preservation | run_eq: collector owned cleanup, failure receipt, seal only after successful checks | +| Manifest/seal and read-only verification | verify_eq: full relative inventory and final seal; synthetic units outside checkout | + +This table records the required implementation targets, not completed validation. +No native or formal validation is authorized for this worker. diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/PROGRESS.md b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/PROGRESS.md new file mode 100644 index 0000000..2e0d117 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/PROGRESS.md @@ -0,0 +1,236 @@ +# P28-02-EQ progress — S4 retained completion r03 + +S4 の保持済み実装に対する残作業を完了し、局所unitの証拠として提出する。 +正式受入は保留、原本加算0。 +以下の旧段階の記録は履歴であり、現在の提出状態を表すものではない。 + +- run_eq.main と verify_eq.recompute の check_probe 戻り値を検査し、 + ok:false を全 errors 付きで拒否する。driver の両モードで共通。 + 両ファイル内の他の checker 呼出しも戻り値契約を確認済み。 +- 既存134件(元119件を含む)の試験本体を変更せず、12件を追加。 + driver/verifier の false/true、owned start/end/exit/diagnostic、profile、 + nine destinations、join 後の決定性不一致、保存済み結果・sidecar・ + raw/joined 入替えの拒否を対象とする。engine は全て不使用。 +- 対象クラス attempt 07: 8件中1件失敗。追加試験の模擬不一致が自己比較にも + 作用したため、試験だけを修正。失敗の raw/exit/SHA を保存。 +- attempt 08: 9件、86.276秒、OK、exit 0。 +- attempt 09: 保存済み結果の結合試験3件、0.025秒、OK、exit 0。 +- 最後の全件試験 attempt 10: `python3 -B test_eq.py`、146件、 + 293.277秒、OK、exit 0(外側の所要時間293.5742515秒)。 + 生出力は UNIT_OUTPUT_S4_ATTEMPT_10.txt と UNIT_OUTPUT.txt に保存。 + SHA-256: ff6fc0065772434f9ca35a1267e24d199057e339869a868942a41829327503bb。 + 開始は01:05:07 UTCまで、期限まで300秒以上を確保した。全件実行は今回1回。 +- S4_SUPPLEMENTARY.json は Root の r09 JSON を直接読み、内容を変えず + actual_commander_context に保存。追加 r03 と判断も提供ファイルから読む。 + 5資料、過去8計画、API notes の SHA を照合済み。 + 134件の元ファイル再構成SHAは cb742b252dbc278113b3c11c2431adac35b0c2e201a762a8ea1ac926e4af414b。 +- IMPLEMENTATION.md 冒頭に、全 S4 must、S4 binding、r01/r02/r03 の + 要件・コード・試験の対応表を記録した。旧文書と全失敗履歴は保持。 +- 外部 retained copy の読取りは PermissionError となったため、権限を変えず、 + W 内の保持prefixと元mainから元ファイルSHAを再現して確認した。 + 読取り用heredocも実行前に失敗し、その後は python -c を使用した。 + +過去のS4 attempt 01/02/04と補足生成assertは失敗のまま保持。 +attempt 05 の132件PASSはその版だけの事実。遅着した attempt 06 は +134件/206.531秒/OKだが、provider exit124・完了通知/exit受領なし・未提出の +事実は変更しない。今回の全件結果とは区別する。 + +提出後は Root の正確な S の native 7 phase → bundle 配置 → +p28-02-eq-unit と p28-02-eq-native-verify → fresh 独立 Opus の全6条件レビュー → +通常の資格確認・承認・統合・final → OPT/whole-unit。23/88、4/30は不変。 +worker は engine、正式validation、Runner、git書込み、他agent、製品変更、 +全回帰を実行していない。局所unitをnative、受入済みS、Q測定、製品PASSとは呼ばない。 + +## Retained prior progress (unchanged) + +# P28-02-EQ progress — current S3b (repair 7) + +stage S3b complete (not a failure; next is S4) + +段階 S3b 完了(失敗ではない。次は S4)。指定に従い正式 status は blocked。 +S_eq は未提出。全6受入条件の正式判定は保留、原本加算0。 + +- E4: 両 role に共通の5経路を実装。E4-1 はその PID の + definition_registry.get_facility_ids() を使い、登録順/文字順/件数、 + 公開 bounds、全候補の preview、最初の配置可能候補、submit/処理結果を保持。 + 空 registry、誤った列挙元、欠落した試行、false NA は拒否する。 +- E5: 4対象×dict/array×2方向の16組。handler 外で操作し、 + 完全な前後 S/K/C、返却値、digest、全イベント、別区間の signal を保持。 + aliasing は changed path/value 付きの existing-defect として出力し、PASS にしない。 +- checker: 39 scenario(既存E3の18 + E4の5 + E5の16)の結合、 + 区間連続、全イベント、restore 0/load 1、X(P,event)、所有権を検査。 + caller の PASS や、publish 時点だけによる cache_stale 判定は拒否する。 +- 比較器の局所修正は、追加試験の失敗で確認した2点だけ: + E5外から内の直後の cached digest 不整合を既存不具合として保持すること、 + 返却値の typed facts にも辞書順だけの fallback を適用すること。 +- 既存91件の試験ソースを元の構成に再結合した SHA は + f81185e506954964bb96b31a569233202a1a7e7c78b2121aba6ab3f2e24d7e1e と一致。 + E3本体、過去の進捗と全試験履歴は保持した。 +- 最終局所 unit: python3 -B test_eq.py、119 tests、OK、終了コード0。 + 既存91 + S3b追加28。Godot/native・正式validationは未実行。 + 生出力は UNIT_OUTPUT_S3B_ATTEMPT_09.txt と UNIT_OUTPUT.txt、対応SHAを保存。 +- S3b試行履歴(すべて生出力/SHAを保存): + 01=91件PASS、02=追加試験の構文エラー、 + 03=114件中digest既存不具合の比較試験1件失敗、 + 04/05=114件PASS、06=118件PASS、 + 07=辞書順fallbackの単独試験1件失敗、 + 08=119件中そのfixtureのcheckpoint欠落で1件失敗、 + 09=119件PASS。失敗を成功で上書きしていない。 +- S3B_SUPPLEMENTARY.json の単一 actual_commander_context key に + 両S3b計画、両S3計画、両段階計画、今回のRUN判断全文を保持。 + 計画6件のSHA、SPEC/TASK、references/registration、読取専用補足、 + S2/S3a補足、既存出力のSHAを照合した。 + +次はS4(driver・verify・bundleと提出)。IMPLEMENTATION.md末尾に、 +lifecycle.e45、e45-NN、raw/joined facts、sidecar、既存不具合の結合を追記。 +その後にRootの凍結Sで7 native phase、両validation、独立Opusレビュー、 +通常の資格確認・承認・統合・final。S3bのunit結果をnative/Qの結果とは呼ばない。 + +engine、Runner、git書込み、他agent、製品変更、全回帰は実行していない。 + +## Retained prior S3b-blocked/S3a/S2/S1 history (unchanged) + +Final S3b unit SHA-256: 8360a2065b303099d5c546b3e4aecc0cc0ab0c2c1e5120b8034b6a1a64317030 + +# P28-02-EQ progress — S3b blocked before implementation + +S3b is not complete. S_eq is not submitted. All six acceptance gates remain +pending; original credit remains 0. The retained S3a history follows unchanged. + +## Specification/API mismatch affecting E4-1 coverage + +EQ_S3B_STAGE_PLAN.txt E4-1 explicitly chooses the facility definition list from +`mvp_content_catalog`. The product's `scripts/data/mvp_content_catalog.gd:26-31` +DEFAULT_PATHS contains only guest_classes, species, staff_candidates and +unique_characters. Its get_ids(content_type) at :217-223 returns an empty list +for an absent content type. It supplies no facility definition enumeration. + +Facility definitions instead belong to `definition_registry`: +`scripts/core/definition_registry.gd:64-75` exposes get_facility, +get_facility_ids and get_all_facilities. Runtime initializes this registry from +FacilityCatalog paths at `autoload/simulation_runtime.gd:446-447`, and the +public preview_build_facility at :7660-7668 looks up that registry. + +Using an absent catalog type and reporting NA would not prove that no facility +is placeable. Replacing the explicitly fixed enumeration source with the +registry changes the candidates used by the required E4-1 acceptance scenario. +Per the instruction not to supplement missing specifications, this needs an +explicit correction of E4-1 to authorize the actual definition source. Proposed +correction: enumerate runtime.definition_registry.get_facility_ids() in textual +ID order, retaining the specified cell scan and public placement check. This is +a proposal only, not an implemented or approved change. + +Only this progress note changed. No implementation or tests were changed or +removed. The supplied SHA values for IMPLEMENTATION.md, eq_probe.gd, check_eq.py, +compare_versions.py, test_eq.py and UNIT_OUTPUT.txt matched before this note. +The 91-test result below is retained S3a evidence, not a test execution in this +run. No new unit test, engine, Runner, git write, agent, or product operation ran. +The first progress-note write attempt failed before writing because zsh could +not create a heredoc temporary file; this note was then written by apply_patch. +S3b E4/E5 and then S4 remain pending. Do not label this run S3b complete. + +## Retained S3a/S2/S1 progress (unchanged historical text) + +# P28-02-EQ progress — current S3a + +stage S3a complete (not a failure; next is S3b) + +段階 S3a 完了(失敗ではない。次は S3b)。計画に従い正式 status は blocked。 +S_eq は未提出。6受入条件はすべて保留、原本加算0。 + +- checker: phase key は正確に0..10。重複JSON keyも拒否。 + 30分各checkpointにsnapshot_published → state_updatedがちょうど1組必要。 + 測定開始の接続一覧にprobe自身の接続がなければ失敗。 +- probe/checker: E3の3 API × 6分類を、適用/NAの18行で記録・検査。 + B1の固定変異、実際のAPI戻り値、package全bytes/SHA、完全S/K/C、 + 全イベント差、scenario signal、区間の連続性、X(B, ev_fail)を保持。 + codeを創作せず、期待外の製品結果は既存不具合候補として残す。 +- S1 comparatorは元のSHAのまま。S1/S2の試験本体を保持 + (指定checker修正に必要なS2 fixture/呼出しの変更のみ)。 +- 最終局所試験: python3 -B test_eq.py、**91 tests, OK**、終了コード0。 + S3a追加19件。Godot/native/正式validationは未実行。 +- 生出力: UNIT_OUTPUT.txt と UNIT_OUTPUT_S3A_ATTEMPT_04.txt。 + SHA-256: 02221ae41e5dd40ecdac0ec0d7ffc657f265d3194c3817583c2b88ad375f132b。 + S3aの01/02/03/04試行(72/85/91/91件、全件PASS)を個別に保存。 + 既存のS1失敗出力・S2出力とSHAは変更せず保持。 +- S3A_SUPPLEMENTARY.json: 単一actual_commander_context keyに + 両S3計画・両段階計画・今回のRUN判断全文を保存。4計画のSHA一致。 +- SPEC/TASK/references/registration、read-only補足3件、S2補足、 + S1 comparatorと全ての既存UNIT_OUTPUT履歴のSHA一致を確認。 + +次はS3b(E4/E5)だけ。その後S4(driver/bundleと提出)、 +Rootの7 native phase、両validation、新しい独立Opusレビュー、 +通常の承認・統合・final。S4でlifecycle.measurement/e3/e3_b1と +private evidenceを結合する必要がある。詳細はIMPLEMENTATION.md末尾。 + +engine、Runner、git書込み、他agent、製品変更、全回帰は実行していない。 + +## Retained S2/S1 progress (unchanged historical text) + +# P28-02-EQ progress — current S2 + +stage S2 complete (not a failure; next is S3) + +段階 S2 完了(失敗ではない。次は S3)。計画 G4 に従い status は blocked。 +正式提出はしていない。6受入条件はすべて保留、原本加算0。 + +- eq_probe.gd: DIAG の6段階起動、A1 encode/decode、A2 bytes roundtrip、 + A3 全 B1/毎 tick 差分、31 checkpoint、B の全イベント記録、 + guard 実値照合、private evidence、単一 report 行、close_requested を実装。 +- check_eq.py: S1 schema の形式/矛盾、正規化の結合、raw 観測/起動証跡、 + 静的禁止の検査を追加。S3 の scenario は未着手。 +- test_eq.py: S1 43件を保持し、S2 29件を追加。最終 **72 tests, OK**。 + 実行は python3 -B test_eq.py のみ。native・正式 validation は未実行。 +- 生出力: UNIT_OUTPUT.txt。SHA-256: 9d323abda9bfffa02faf3a9d5cb56aa87e647017c991eb55b4807cf734386698。 + S2 の3試行も UNIT_OUTPUT_S2_ATTEMPT_01/02/03.txt と SHA に保存。 + S1 の最終出力は UNIT_OUTPUT_S1_FINAL.txt に保存。下記の失敗履歴と + UNIT_OUTPUT_ATTEMPT_01/02 は変更せず保持。 +- S2_SUPPLEMENTARY.json: 単一 actual_commander_context key に両計画全文、 + RUN判断全文、read-only 補足の path/SHA を保持。両計画の SHA 一致を確認。 + +次は S3 の E3/E4/E5 操作・結果・検査。その後 S4 の driver/bundle を実装し、 +Root/Runner の7 native phase、両 validation、新しい独立レビュー、承認・統合・final。 +engine、Runner、git 書込み、他 agent、製品変更、全回帰は実行していない。 + +## Retained S1 progress (unchanged historical text) + +# P28-02-EQ progress + +## Current stage + +stage S1 complete (not a failure; next is S2) + +段階 S1 完了(失敗ではない。次は S2)。正式な返却 status は計画 G4 に従い blocked。 +S_eq の提出、受入の自己確定、原本への加算はしていない。 + +## Completed + +- compare_versions.py: typed tree 比較、F1–F3 の4つの normalize/restore 関数、 + 全 checkpoint の差分再構成と tree SHA 再計算、report の S/latest/K/C/E2/ + scenario 比較、source map 1407件の固定と許可された変更集合の完全一致検査。 +- test_eq.py: 合成入力のみの43試験。型・挿入順・深い tree・可逆性・guard・ + violations・sidecar 改ざん・全イベント・比較除外・source 閉包の正常/拒否を検査。 +- IMPLEMENTATION.md: S2 向けの内部データ形式と、後続 checker/native の責任を記録。 + +## Unit evidence + +実行: `python3 test_eq.py`(engine 不使用)。最新結果: **43 tests, OK**、終了コード0。 +生出力: `UNIT_OUTPUT.txt`。 +SHA-256: `cdca0cdd551ce76c6100c4dd90e04559551f9d88c054a19a2bc6a77e6572ae15`。 + +初回の36試験中1失敗(F3 sidecar の欠落を見逃した)は +`UNIT_OUTPUT_ATTEMPT_01.txt` と `.sha256` にそのまま保持した。 +予約 token の復元漏れを拒否する修正後、41試験 PASS の中間出力も +`UNIT_OUTPUT_ATTEMPT_02.txt` と `.sha256` に保持した。 +失敗を成功に書き換えていない。作成したファイルは削除していない。 + +## Remaining stages and gates + +- S2: eq_probe.gd の6段階起動、Godot encode/decode と bytes roundtrip、31 checkpoint + と E2 の evidence 書出し、check_eq.py の形式/静的検査、対応 unit。 +- S3: E3/E4/E5 専用区間、全ての場面/入力の実行と実値の保存、絶対条件の checker。 +- S4: run_eq.py と verify_eq.py、全依存 SHA の固定、bundle 結合/拒否試験、正式提出。 +- Root/Runner: 凍結した S_eq で7 native phase、両正式 validation、独立レビュー、 + 通常の承認・統合・final。6受入条件は全て保留。 + +engine、Runner、git 書込み、他 agent、製品変更、全回帰は実行していない。 diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/S2_SUPPLEMENTARY.json b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/S2_SUPPLEMENTARY.json new file mode 100644 index 0000000..f62a4d1 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/S2_SUPPLEMENTARY.json @@ -0,0 +1,33 @@ +{ + "actual_commander_context": { + "actual_run_decision": { + "action": "run", + "task_id": "P28-02-EQ", + "reason": "Use only after Root verifies through the normal gates: repair_ready, repairs 4, no S submitted, no active run, and the S1 files still present unchanged in the W. Run repair 4 of P28-02-EQ once on the same W from base 2549cf7d6992560b850bbd11934e3c14b39a1988 with the single worker codex gpt-6-astra, doing only stage S2 of EQ_STAGED_IMPLEMENTATION_PLAN r01 and r02. Start by reading eq/PROGRESS.md and eq/IMPLEMENTATION.md, and reuse the internal types, paths, record schema and API recorded there and in compare_versions.py without redesign. Do not delete or rewrite S1 code, except for fixes a failing test requires. Keep the S1 unit failure history in PROGRESS.md and UNIT_OUTPUT. S2 scope: (1) eq_probe.gd startup per the six-stage lifecycle reused from DIAG; (2) the r02 A1 typed tree encode/decode; (3) the A2 Godot roundtrip proof recording raw_bytes_sha, tree_sha and roundtrip_ok per checkpoint; (4) A3 export of the full B1 tree and exact per-tick diff operations for S and latest_snapshot to private user:// evidence/; (5) the B event record, with to_dictionary trees, original_field_types, start counter and published_ids count; (6) binding of the profile root to the guard actual_user_data_dir, with the value read live and never assumed; and (7) the single-line P28_02_EQ_REPORT plus close_requested.emit(), with the report fields matching what compare_versions.compare_reports already consumes. Also add the check_eq.py format, contradiction and static probe checks: no autoload class_name reference, no state-changing call outside the allowed preparation and stepping, no := inference from a Variant, textual StringName ordering, no SimulationDigest-only judgment. Add synthetic tests for these to test_eq.py. The E3/E4/E5 scenarios are S3 and must not be started now. Run the engine-free python3 test_eq.py until every existing test passes, save the raw output, update PROGRESS.md, and end S2 with formal status blocked and the finding 'stage S2 complete (not a failure; next is S3)'. Do not submit. Deliver as the one supplementary key the full texts of both plans and this decision; clarifications r01, r02 and r03 stay read-only in build/eq-staged-readonly-r04 with path and SHA. No engine, no git write or commit, no product change, no full regression; SPEC, TASK, eq/references and eq/registration stay unchanged. Ordinary implementation choices are recorded without stopping; block only for undecided matters affecting original product spec, values, permissions, billing or original acceptance. After S3 and S4, Root runs native on the frozen S_eq in 7 phases and builds the bundle; then both validations are mandatory, followed by a fresh independent Opus review of all 6 conditions and the normal integration and final. No original credit (23/88, 4/30). Quota fallback only on structured provider quota, once, same role, Antigravity claude-opus-5-5-high; any other failure is blocked. Decided by Claude Opus 5.5 in the Desktop control session (message 324); not a CLI commander result." + }, + "actual_full_plans": { + "EQ_STAGED_IMPLEMENTATION_PLAN.txt": { + "sha256": "eb7b4831e2164c6fc983fa6f9825e7f3e2993b4c0ebf2f90aac8ad10662666d2", + "full_unedited": "EQ_STAGED_IMPLEMENTATION_PLAN(P28-02-EQ repair 3 以降。base 2549cf7d6992560b850bbd11934e3c14b39a1988。SPEC、TASK、6条件、eq/references、eq/registration、EQ_S_TIMING_CLARIFICATION r01/r02、EQ_ENVIRONMENT_FIELDS_CLARIFICATION r03 は全てそのまま有効。変えるのは、工程と、成果物の内部の設計の固定だけ)\n\n前回までの事実\n- repair 2(run 84ca0ff8…)は、IMPLEMENTATION.md と compare_versions.py などを作った後、item_30 で全てを削除し、「6ファイルと unit の PASS を提供できない」として、自分から終了した。仕様の不足の指摘ではない。packet は 94 KB あった。\n- この失敗は失敗のまま保持する。削除したことを成功として扱わない。\n\n工程の変更(必須)\n- G1: **作ったファイルは、削除しない**。完成していなくても、W の eq/ に残す。各 run の最後に、eq/PROGRESS.md に、終わった段階・残りの作業・現在の試験の結果を書く。\n- G2: 1回の run では、下の**1つの段階だけ**を行う。始める前に eq/PROGRESS.md を読み、次の段階から再開する。前の段階のコードは作り直さない。\n- G3: 各段階の終わりに、engine を使わない python3 test_eq.py を実行する。その時点で存在する試験が、全件 PASS になるまで直す。生出力を eq/UNIT_OUTPUT.txt に保存する。\n- G4: 段階1〜3の終わりには、正式な JSON の status を blocked にし、findings に「段階 Sx 完了(失敗ではない。次は Sx+1)」と PROGRESS.md の要点を書いて返す。段階4の終わりにだけ、提出する(status を submitted 相当の正式な提出にする)。\n- G5: 通常の実装上の判断(関数の分け方、名前、試験データ、記録の書式)は、IMPLEMENTATION.md に記録して進める。blocked にしてよいのは、原本の仕様・値・権限・課金・受入に影響する未確定事項がある場合だけ。\n- G6: engine の起動、git への書込み、製品の変更、全回帰はしない。SPEC、TASK、eq/references、eq/registration は変更しない。\n\n固定するインターフェース(6ファイル。SPEC §2)\n\n1. compare_versions.py(Python のみ。engine を使わない)\n - normalize_events(events, profile_root) -> (normalized, sidecar):\n - r03 の F1〜F3 を、JSON の event の一覧に適用する。\n - 閉じた一覧の外の *_us / *_ms / profile_root を含む文字列は、正規化せず、violations として返す。\n - restore_events(normalized, sidecar, profile_root) -> events: 逆の復元(完全一致の確認に使う)。\n - compare_reports(a, b) -> dict: 2つの report(同じ版の別 PID、または前後の版)を比べる。\n - 毎分の checkpoint の S_norm_sha と latest_norm_sha の一致\n - digest の規則(r02 の T3)\n - K と C の、SPEC §3.2 に列挙した欄\n - E2 の正規化した全イベント(開始の counter の一致が前提)\n - E3/E4/E5 の scenario の結果の一致\n - 比べない欄は、理由と両側の値を記録する\n - 差は path ごとに返す\n - check_source_closure(before_map, after_map, allowed_changed) -> dict: SPEC §2 と OPT r02 §2。追加・欠落・登録されていない差分を拒否する。\n2. eq_probe.gd(GDScript):\n - 起動の6段階は、DIAG の diag_probe.gd の構成をそのまま参考にする。\n - 役割は R と O(env の THE_TREE_EQ_ROLE)。\n - 観測の checkpoint は B1 と、30分の各 tick の最後(31個)。各 checkpoint に、次のものを置く:\n - minute\n - S_raw_sha、S_norm_sha(GDScript の中で F1〜F3 の typed の marker を使って正規化した後の var_to_bytes の SHA)\n - 正規化した S の path の hash の表(depth ≤ 4)\n - latest_norm_sha\n - digest の情報\n - K と C の全体\n - sidecar\n - E2 は subscribe('*') で、全イベントの JSON(正規化の前)を記録する。正規化は compare_versions.py で行う(GDScript と Python で、同じ規則の二重実装をしない)。\n - E3/E4/E5 の scenario は、SPEC §3.3 の専用の区間で行う。各区間について、開始と終了、操作、code、前後の S/K/C、件数(r02 の T4)を記録する。\n - stdout には、P28_02_EQ_REPORT= をちょうど1行出す。終了は close_requested.emit()。\n3. check_eq.py: report 1つを検査する。\n - 形式、必須の欄、矛盾\n - 閉じた一覧の外の差\n - probe の静的な禁止(autoload の class_name の参照、状態を変える呼出しの区間の外での使用、Variant からの := の推論)\n - SimulationDigest だけでの判定\n4. run_eq.py: Root が実行する driver。\n - diag_p28_02.py の構成をそのまま参考にする(--check / --run、依存の SHA、1407 の source、凍結した S の照合、owned phase、guard、private profile、cleanup)。\n - phase は import、parse-base、parse-wrapper、R-A、R-B、O-A、O-B。\n - 成功したら、execution.json と bundle.json を作る。\n5. verify_eq.py: --project-root . で、$BUILD_OUTPUT_DIR/p28-02-eq-evidence の bundle を結合する。bundle が無ければ失敗する。\n - 各 report に check_eq を行う。\n - R-A と R-B、O-A と O-B に compare_reports を行い、差が0であること(harness の正しさ)。\n - E3/E5 の、前の版での製品の失敗は、「既存の不具合」の一覧として出力する。harness の不合格とは区別する。\n - SPEC、TASK、eq/references、eq/registration の SHA を固定して照合する。\n6. test_eq.py: 合成した入力だけで動く。各段階で、その段階の試験を足していく。\n\n段階(1回の run で1つ)\n- S1: compare_versions.py の全体と、その試験(F1〜F3 の正常と拒否、可逆性、比較、source の閉包)。PROGRESS.md と IMPLEMENTATION.md を作る。\n- S2: eq_probe.gd の、起動・観測の checkpoint・E2 の記録・報告。check_eq.py の静的な検査と形式の検査、それぞれの試験。\n- S3: eq_probe.gd の E3/E4/E5 の scenario、check_eq.py のそれに対する検査、試験。\n- S4: run_eq.py と verify_eq.py、bundle の試験。全件 PASS を確かめて、正式に提出する。\n\nRoot への依頼(packet を小さくするため)\n- actual_commander_context の key には、この計画の全文と RUN の判断だけを入れる。r01・r02・r03 の全文は、build/ に読取専用で置き、その path と SHA だけを渡す。eq/references は W の中にあるので、path だけで足りる。\n" + }, + "EQ_STAGED_IMPLEMENTATION_PLAN_R02.txt": { + "sha256": "128f42f18e168e9299995296ac7ad119f47d1647799d472663282e47e8ac9fdd", + "full_unedited": "EQ_STAGED_IMPLEMENTATION_PLAN r02(P28-02-EQ repair 3 以降。EQ_STAGED_IMPLEMENTATION_PLAN(r01)の工程 G1〜G6、段階 S1〜S4、Root への依頼は、そのまま有効。この r02 は、固定インターフェースのうち、状態とイベントの運搬の表現と、normalize_events の返り値を置き換えて確定する。SPEC、TASK、6条件、eq/references、eq/registration、補足 r01/r02/r03 は変更しない)\n\nA. 型を保つ運搬の表現(typed tree。JSON は運び方であって、型の情報は落とさない)\n\nA1 node の形式(JSON の配列)\n- 各値は [type_code, payload]。type_code は Godot の typeof() の値。\n - null: [0]\n - bool: [1, 0|1]\n - int: [2, 整数]\n - float: [3, \"<8 byte little-endian IEEE754 の hex>\"](10進の文字列にしない)\n - String: [4, \"文字列\"]\n - StringName: [21, \"文字列\"]\n - Vector2/Vector2i/Vector3/Vector3i/Rect2/Rect2i/Color など: [type_code, [各成分の node]](成分は int か float の node)\n - Dictionary: [27, [[key_node, value_node], …], typed_info]。**元の挿入の順序のまま**並べる。typed_info は、型つきの Dictionary なら key と value の builtin 型・class 名・script、それ以外は null。\n - Array: [28, [element_node, …], typed_info]。typed_info は get_typed_builtin()・get_typed_class_name()・get_typed_script() の値、型の無い Array なら null。\n - PackedByteArray: [29, \"\"]。他の Packed*Array も、要素ごとの node の列にする(float は hex)。\n- Object、Callable、Signal、RID が現れたら、運搬せずに失敗にする(snapshot と event の dict には、本来現れないもの)。\n\nA2 無損失の証明(Godot の中で行う。probe の必須の処理)\n- tree = encode(value) を作った後、decode(tree) で Variant を作り直す。var_to_bytes(decode(tree)) == var_to_bytes(value) であることを確かめる。一致しなければ失敗にする。\n- report には、checkpoint ごとに、次の3つを記録する。\n - raw_bytes_sha = sha256(var_to_bytes(value))\n - tree_sha = sha256(tree を key の順序を変えずに JSON.stringify した UTF-8)\n - roundtrip_ok\n- Python は、受け取った tree から tree_sha を計算し直して結合する。これで、Python で比べる tree が、Godot の元の bytes と無損失に対応することが保証される。\n\nA3 保存の場所と大きさ(深さの制限は設けない。全体を再構成できるようにする)\n- 各 PID は、checkpoint の列(B1 と、30分の各 tick の最後)について、S 層と latest_snapshot を、次の形で、private user:// の evidence/ に書き出す。driver は、それを RESTART の copy_states と同じ方式で out へ複製し、SHA を結合する。\n - checkpoint 0(B1): tree の全体(JSON、zstd で圧縮してよい。圧縮した場合は、圧縮の前後の SHA を両方記録する)。\n - checkpoint k(k≥1): checkpoint k−1 の tree に対する、path を指定した差分の操作の列。操作は set(path, node)、dict_insert(path, index, key_node, value_node)、dict_remove(path, key_node)、array_splice(path, start, delete_count, [node…])。順序つきで、再構成すると、checkpoint k の tree と完全一致すること。\n - latest_snapshot は、各 checkpoint で、var_to_bytes が S 層と同じなら same_as_S=true とし、違えば、その tree(または S に対する差分)を保存する。\n- Python は、checkpoint 0 から差分を順に適用して、全ての checkpoint を再構成する。checkpoint ごとに tree_sha と一致することを確かめる。\n\nA4 比較(compare_versions.py。全て tree の上で行い、深さの制限は無い)\n- 第一の比較は、tree の完全一致(型、key、順序、値。全ての node)。\n- 一致しない場合に限り、正規化した比較を行う。dict の key を文字で並べ(同じ文字の key が2つあれば拒否)、それ以外の型・値・配列の順序を保ったまま比べる。それで一致すれば「dict の列挙の順序だけの差」として、その全ての path を記録する。それ以外の差は、全ての path と両側の node を記録して、不一致にする。\n- F1〜F3(r03)の正規化は、tree の node の上で行う。sidecar から、元の tree へ完全に戻せること(tree_sha が一致すること)を確かめる。\n\nB. E2 のイベントの運搬\n- 各 event について、event.to_dictionary()(製品の直列化。scripts/core/domain_event.gd:47-59)の tree を記録する。あわせて、元の object の欄の型(event_id と event_type が StringName であるか、entity_ids の型、payload の dict の typed_info)を、original_field_types として記録する。\n- 受け取りの順序で番号をつけ、開始の時点の counter と、published_ids の数を記録する。\n- イベントの列は、A3 と同じく evidence/ に書き出し(tree の列。圧縮してよい)、SHA を結合する。Godot の中で、各 event について A2 の roundtrip を確かめる。\n- compare_reports は、この tree の列を受け取り、全ての欄と event_id を**そのまま**比べる(ID の付け替えはしない)。F1〜F3 は、payload の該当する node にだけ適用する。\n\nC. normalize_events とその仲間の返り値(固定)\n- normalize_events(events, profile_root) -> (normalized, sidecar)。返り値は2つの要素のまま。\n - normalized: tree の列。閉じた一覧(r03)の node だけを marker に置き換えたもの。\n - sidecar: dict で、key は次の3つに固定。\n - \"entries\": [{\"event_index\", \"path\", \"key\", \"original_node\"}…]。F1〜F3 で置き換えた全ての node の元の値。F3 の場合は original_node に元の message の文字列を入れ、\"root\" に、置き換えた root を入れる。\n - \"violations\": [{\"event_index\", \"path\", \"kind\", \"node\"}…]。閉じた一覧の外にあった、*_us / *_ms の key、profile_root を含む文字列など。**存在しただけでは不合格にしない**。正規化はせずに、そのまま保持して記録する。\n - \"profile_root\": 使った root の文字列と、guard の actual_user_data_dir との一致の結果。\n- restore_events(normalized, sidecar, profile_root) -> events: entries から元に戻す。violations の node は、もともと変えていないので、そのまま。\n- 状態の tree にも、同じ形の normalize_tree(tree, profile_root) -> (normalized, sidecar) と restore_tree を用意する。\n- r03 の規則は、そのまま。violations にあるものを正規化しようとしたら拒否する。violations にあるものが、比べる2つの側で実際に異なれば、その差は不一致(失敗)として、path と両側の値を記録する。\n\nD. 段階への影響\n- S1(今回): compare_versions.py に、A4 の比較、C の4つの関数、A3 の差分の再構成、tree_sha の再計算、check_source_closure を実装する。試験は合成の tree で行い、次のものを確かめる。\n - 型の違い(int と float、String と StringName、型つきの配列)を区別すること\n - dict の順序だけの差の path\n - 差分の再構成の完全一致\n - sidecar からの逆の復元\n - violations の扱い(存在だけでは不合格にしない、正規化しようとしたら拒否、差があれば不一致)\n- S2: eq_probe.gd に、A1 の encode と decode、A2 の roundtrip、A3 の書き出し、B の記録を実装する。\n- S3 と S4 は、r01 のとおり。\n" + } + }, + "read_only_clarifications": { + "EQ_S_TIMING_CLARIFICATION.txt": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/.runtime/P28-02-EQ/build/eq-staged-readonly-r04/EQ_S_TIMING_CLARIFICATION.txt", + "sha256": "25d323fd562d29e80782b6f075fc7a0e8b49457a6c4fbd7c30e74b31a6b6a126" + }, + "EQ_S_TIMING_CLARIFICATION_R02.txt": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/.runtime/P28-02-EQ/build/eq-staged-readonly-r04/EQ_S_TIMING_CLARIFICATION_R02.txt", + "sha256": "777accdd652f85db6b9014d85e3c8b3b60ca94b20768e6173b36bc769d360fd9" + }, + "EQ_ENVIRONMENT_FIELDS_CLARIFICATION_R03.txt": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/.runtime/P28-02-EQ/build/eq-staged-readonly-r04/EQ_ENVIRONMENT_FIELDS_CLARIFICATION_R03.txt", + "sha256": "12b27f984ef5843d98327200ad261dccaf64968402192b08ad55b15ed5454ea2" + } + } + } +} diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/S3A_SUPPLEMENTARY.json b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/S3A_SUPPLEMENTARY.json new file mode 100644 index 0000000..05faf50 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/S3A_SUPPLEMENTARY.json @@ -0,0 +1,41 @@ +{ + "actual_commander_context": { + "actual_run_decision": { + "action": "run", + "task_id": "P28-02-EQ", + "reason": "Supersedes DESKTOP_EQ_S3A_RUN_DECISION.json, which is kept unchanged as history. DESKTOP_EQ_S3A_REPAIR_DECISION.json stays valid as written: its facts (S2 checkpoint, the two checker defects, the S3a/S3b split) are unchanged by this correction. Use only after Root verifies through the normal gates: repair_ready, repairs 5, no S submitted, no active run, and the S1 and S2 files still present unchanged in the W. Run repair 5 of P28-02-EQ once on the same W from base 2549cf7d6992560b850bbd11934e3c14b39a1988 with the single worker codex gpt-6-astra, doing only stage S3a as defined in EQ_S3_STAGE_PLAN.txt and replaced in part by EQ_S3_STAGE_PLAN_R02.txt, under EQ_STAGED_IMPLEMENTATION_PLAN r01 and r02. Start by reading eq/PROGRESS.md and eq/IMPLEMENTATION.md and reuse the S1/S2 types, paths, schema, API and notes without redesign. Do not delete or rewrite S1/S2 code or test bodies, except for the two checker fixes and fixes a failing test requires. Keep the failure history. S3a scope: (1) check_eq.py:109 must require the exact phase-key set {0..10}. (2) check_eq.py:147-150 must require exactly one snapshot_published then state_updated pair for each of the 30 measured minutes, bound to the checkpoint minute and to a recorded connection inventory that contains the probe's own snapshot_published connection. A missing probe connection fails; it is never downgraded to a state-only expectation. The product's unconnected case is out of this interval's scope, and scenario signals are kept separate. (3) E3 uses the source-backed table. restore_snapshot returns its bool with code null and reason 'API returns bool only'. validate returns its full {ok, errors} with code null and reason 'API returns ok/errors only'. load_from_path returns a real code, and a missing code there is a failure. Missing key, wrong type and out-of-range are applied to all three APIs by fixed rules (clock removal, string absolute_minute and speed 9 for the Dictionary APIs; checksum_world removal, string format_version and an unsupported format_version for the package). Duplicate published_ids is applied to restore and, if SaveService.save_snapshot accepts it, to load; it is NA for envelope validate. Duplicate facility is applied in R and is NA in O when B1 actually has 0 facilities, recorded with the count and with no construction, no R substitution and no invented values. world.bin tamper is load only, by r03 D3. Record full before/after S/K/C, the event difference and count (0 for restore and validate; exactly 1 SAVE_LOAD_FAILED equal to X(B, ev_fail) for failed loads), and the applied/NA table. Mismatches are kept as existing-defect candidates; envelope validate accepting an internal duplicate is not called a product defect. Add the listed checker rules and negative tests. State-changing calls are allowed only inside the listed scenario interval. Run the engine-free python3 test_eq.py until every existing test passes, save the raw output, update PROGRESS.md, and end S3a with formal status blocked and the finding 'stage S3a complete (not a failure; next is S3b)'. Do not submit. Deliver as the one supplementary key both S3 plans, both staged plans and this decision; clarifications r01, r02 and r03 stay read-only in build/eq-staged-readonly-r04. No engine, no git write or commit, no product change, no full regression; SPEC, TASK, eq/references and eq/registration stay unchanged. Ordinary implementation choices are recorded without stopping; block only for undecided matters affecting original product spec, values, permissions, billing or original acceptance. The remaining order is S3b, then S4 and submission, then Root native in 7 phases, then both validations, then a fresh independent Opus review of all 6 conditions, then the normal integration and final. No original credit (23/88, 4/30); the 900-second timeout is unchanged. Quota fallback only on structured provider quota, once, same role, Antigravity claude-opus-5-5-high; any other failure is blocked. Decided by Claude Opus 5.5 in the Desktop control session (message 330); not a CLI commander result." + }, + "actual_full_plans": { + "EQ_STAGED_IMPLEMENTATION_PLAN.txt": { + "sha256": "eb7b4831e2164c6fc983fa6f9825e7f3e2993b4c0ebf2f90aac8ad10662666d2", + "full_unedited": "EQ_STAGED_IMPLEMENTATION_PLAN(P28-02-EQ repair 3 以降。base 2549cf7d6992560b850bbd11934e3c14b39a1988。SPEC、TASK、6条件、eq/references、eq/registration、EQ_S_TIMING_CLARIFICATION r01/r02、EQ_ENVIRONMENT_FIELDS_CLARIFICATION r03 は全てそのまま有効。変えるのは、工程と、成果物の内部の設計の固定だけ)\n\n前回までの事実\n- repair 2(run 84ca0ff8…)は、IMPLEMENTATION.md と compare_versions.py などを作った後、item_30 で全てを削除し、「6ファイルと unit の PASS を提供できない」として、自分から終了した。仕様の不足の指摘ではない。packet は 94 KB あった。\n- この失敗は失敗のまま保持する。削除したことを成功として扱わない。\n\n工程の変更(必須)\n- G1: **作ったファイルは、削除しない**。完成していなくても、W の eq/ に残す。各 run の最後に、eq/PROGRESS.md に、終わった段階・残りの作業・現在の試験の結果を書く。\n- G2: 1回の run では、下の**1つの段階だけ**を行う。始める前に eq/PROGRESS.md を読み、次の段階から再開する。前の段階のコードは作り直さない。\n- G3: 各段階の終わりに、engine を使わない python3 test_eq.py を実行する。その時点で存在する試験が、全件 PASS になるまで直す。生出力を eq/UNIT_OUTPUT.txt に保存する。\n- G4: 段階1〜3の終わりには、正式な JSON の status を blocked にし、findings に「段階 Sx 完了(失敗ではない。次は Sx+1)」と PROGRESS.md の要点を書いて返す。段階4の終わりにだけ、提出する(status を submitted 相当の正式な提出にする)。\n- G5: 通常の実装上の判断(関数の分け方、名前、試験データ、記録の書式)は、IMPLEMENTATION.md に記録して進める。blocked にしてよいのは、原本の仕様・値・権限・課金・受入に影響する未確定事項がある場合だけ。\n- G6: engine の起動、git への書込み、製品の変更、全回帰はしない。SPEC、TASK、eq/references、eq/registration は変更しない。\n\n固定するインターフェース(6ファイル。SPEC §2)\n\n1. compare_versions.py(Python のみ。engine を使わない)\n - normalize_events(events, profile_root) -> (normalized, sidecar):\n - r03 の F1〜F3 を、JSON の event の一覧に適用する。\n - 閉じた一覧の外の *_us / *_ms / profile_root を含む文字列は、正規化せず、violations として返す。\n - restore_events(normalized, sidecar, profile_root) -> events: 逆の復元(完全一致の確認に使う)。\n - compare_reports(a, b) -> dict: 2つの report(同じ版の別 PID、または前後の版)を比べる。\n - 毎分の checkpoint の S_norm_sha と latest_norm_sha の一致\n - digest の規則(r02 の T3)\n - K と C の、SPEC §3.2 に列挙した欄\n - E2 の正規化した全イベント(開始の counter の一致が前提)\n - E3/E4/E5 の scenario の結果の一致\n - 比べない欄は、理由と両側の値を記録する\n - 差は path ごとに返す\n - check_source_closure(before_map, after_map, allowed_changed) -> dict: SPEC §2 と OPT r02 §2。追加・欠落・登録されていない差分を拒否する。\n2. eq_probe.gd(GDScript):\n - 起動の6段階は、DIAG の diag_probe.gd の構成をそのまま参考にする。\n - 役割は R と O(env の THE_TREE_EQ_ROLE)。\n - 観測の checkpoint は B1 と、30分の各 tick の最後(31個)。各 checkpoint に、次のものを置く:\n - minute\n - S_raw_sha、S_norm_sha(GDScript の中で F1〜F3 の typed の marker を使って正規化した後の var_to_bytes の SHA)\n - 正規化した S の path の hash の表(depth ≤ 4)\n - latest_norm_sha\n - digest の情報\n - K と C の全体\n - sidecar\n - E2 は subscribe('*') で、全イベントの JSON(正規化の前)を記録する。正規化は compare_versions.py で行う(GDScript と Python で、同じ規則の二重実装をしない)。\n - E3/E4/E5 の scenario は、SPEC §3.3 の専用の区間で行う。各区間について、開始と終了、操作、code、前後の S/K/C、件数(r02 の T4)を記録する。\n - stdout には、P28_02_EQ_REPORT= をちょうど1行出す。終了は close_requested.emit()。\n3. check_eq.py: report 1つを検査する。\n - 形式、必須の欄、矛盾\n - 閉じた一覧の外の差\n - probe の静的な禁止(autoload の class_name の参照、状態を変える呼出しの区間の外での使用、Variant からの := の推論)\n - SimulationDigest だけでの判定\n4. run_eq.py: Root が実行する driver。\n - diag_p28_02.py の構成をそのまま参考にする(--check / --run、依存の SHA、1407 の source、凍結した S の照合、owned phase、guard、private profile、cleanup)。\n - phase は import、parse-base、parse-wrapper、R-A、R-B、O-A、O-B。\n - 成功したら、execution.json と bundle.json を作る。\n5. verify_eq.py: --project-root . で、$BUILD_OUTPUT_DIR/p28-02-eq-evidence の bundle を結合する。bundle が無ければ失敗する。\n - 各 report に check_eq を行う。\n - R-A と R-B、O-A と O-B に compare_reports を行い、差が0であること(harness の正しさ)。\n - E3/E5 の、前の版での製品の失敗は、「既存の不具合」の一覧として出力する。harness の不合格とは区別する。\n - SPEC、TASK、eq/references、eq/registration の SHA を固定して照合する。\n6. test_eq.py: 合成した入力だけで動く。各段階で、その段階の試験を足していく。\n\n段階(1回の run で1つ)\n- S1: compare_versions.py の全体と、その試験(F1〜F3 の正常と拒否、可逆性、比較、source の閉包)。PROGRESS.md と IMPLEMENTATION.md を作る。\n- S2: eq_probe.gd の、起動・観測の checkpoint・E2 の記録・報告。check_eq.py の静的な検査と形式の検査、それぞれの試験。\n- S3: eq_probe.gd の E3/E4/E5 の scenario、check_eq.py のそれに対する検査、試験。\n- S4: run_eq.py と verify_eq.py、bundle の試験。全件 PASS を確かめて、正式に提出する。\n\nRoot への依頼(packet を小さくするため)\n- actual_commander_context の key には、この計画の全文と RUN の判断だけを入れる。r01・r02・r03 の全文は、build/ に読取専用で置き、その path と SHA だけを渡す。eq/references は W の中にあるので、path だけで足りる。\n" + }, + "EQ_STAGED_IMPLEMENTATION_PLAN_R02.txt": { + "sha256": "128f42f18e168e9299995296ac7ad119f47d1647799d472663282e47e8ac9fdd", + "full_unedited": "EQ_STAGED_IMPLEMENTATION_PLAN r02(P28-02-EQ repair 3 以降。EQ_STAGED_IMPLEMENTATION_PLAN(r01)の工程 G1〜G6、段階 S1〜S4、Root への依頼は、そのまま有効。この r02 は、固定インターフェースのうち、状態とイベントの運搬の表現と、normalize_events の返り値を置き換えて確定する。SPEC、TASK、6条件、eq/references、eq/registration、補足 r01/r02/r03 は変更しない)\n\nA. 型を保つ運搬の表現(typed tree。JSON は運び方であって、型の情報は落とさない)\n\nA1 node の形式(JSON の配列)\n- 各値は [type_code, payload]。type_code は Godot の typeof() の値。\n - null: [0]\n - bool: [1, 0|1]\n - int: [2, 整数]\n - float: [3, \"<8 byte little-endian IEEE754 の hex>\"](10進の文字列にしない)\n - String: [4, \"文字列\"]\n - StringName: [21, \"文字列\"]\n - Vector2/Vector2i/Vector3/Vector3i/Rect2/Rect2i/Color など: [type_code, [各成分の node]](成分は int か float の node)\n - Dictionary: [27, [[key_node, value_node], …], typed_info]。**元の挿入の順序のまま**並べる。typed_info は、型つきの Dictionary なら key と value の builtin 型・class 名・script、それ以外は null。\n - Array: [28, [element_node, …], typed_info]。typed_info は get_typed_builtin()・get_typed_class_name()・get_typed_script() の値、型の無い Array なら null。\n - PackedByteArray: [29, \"\"]。他の Packed*Array も、要素ごとの node の列にする(float は hex)。\n- Object、Callable、Signal、RID が現れたら、運搬せずに失敗にする(snapshot と event の dict には、本来現れないもの)。\n\nA2 無損失の証明(Godot の中で行う。probe の必須の処理)\n- tree = encode(value) を作った後、decode(tree) で Variant を作り直す。var_to_bytes(decode(tree)) == var_to_bytes(value) であることを確かめる。一致しなければ失敗にする。\n- report には、checkpoint ごとに、次の3つを記録する。\n - raw_bytes_sha = sha256(var_to_bytes(value))\n - tree_sha = sha256(tree を key の順序を変えずに JSON.stringify した UTF-8)\n - roundtrip_ok\n- Python は、受け取った tree から tree_sha を計算し直して結合する。これで、Python で比べる tree が、Godot の元の bytes と無損失に対応することが保証される。\n\nA3 保存の場所と大きさ(深さの制限は設けない。全体を再構成できるようにする)\n- 各 PID は、checkpoint の列(B1 と、30分の各 tick の最後)について、S 層と latest_snapshot を、次の形で、private user:// の evidence/ に書き出す。driver は、それを RESTART の copy_states と同じ方式で out へ複製し、SHA を結合する。\n - checkpoint 0(B1): tree の全体(JSON、zstd で圧縮してよい。圧縮した場合は、圧縮の前後の SHA を両方記録する)。\n - checkpoint k(k≥1): checkpoint k−1 の tree に対する、path を指定した差分の操作の列。操作は set(path, node)、dict_insert(path, index, key_node, value_node)、dict_remove(path, key_node)、array_splice(path, start, delete_count, [node…])。順序つきで、再構成すると、checkpoint k の tree と完全一致すること。\n - latest_snapshot は、各 checkpoint で、var_to_bytes が S 層と同じなら same_as_S=true とし、違えば、その tree(または S に対する差分)を保存する。\n- Python は、checkpoint 0 から差分を順に適用して、全ての checkpoint を再構成する。checkpoint ごとに tree_sha と一致することを確かめる。\n\nA4 比較(compare_versions.py。全て tree の上で行い、深さの制限は無い)\n- 第一の比較は、tree の完全一致(型、key、順序、値。全ての node)。\n- 一致しない場合に限り、正規化した比較を行う。dict の key を文字で並べ(同じ文字の key が2つあれば拒否)、それ以外の型・値・配列の順序を保ったまま比べる。それで一致すれば「dict の列挙の順序だけの差」として、その全ての path を記録する。それ以外の差は、全ての path と両側の node を記録して、不一致にする。\n- F1〜F3(r03)の正規化は、tree の node の上で行う。sidecar から、元の tree へ完全に戻せること(tree_sha が一致すること)を確かめる。\n\nB. E2 のイベントの運搬\n- 各 event について、event.to_dictionary()(製品の直列化。scripts/core/domain_event.gd:47-59)の tree を記録する。あわせて、元の object の欄の型(event_id と event_type が StringName であるか、entity_ids の型、payload の dict の typed_info)を、original_field_types として記録する。\n- 受け取りの順序で番号をつけ、開始の時点の counter と、published_ids の数を記録する。\n- イベントの列は、A3 と同じく evidence/ に書き出し(tree の列。圧縮してよい)、SHA を結合する。Godot の中で、各 event について A2 の roundtrip を確かめる。\n- compare_reports は、この tree の列を受け取り、全ての欄と event_id を**そのまま**比べる(ID の付け替えはしない)。F1〜F3 は、payload の該当する node にだけ適用する。\n\nC. normalize_events とその仲間の返り値(固定)\n- normalize_events(events, profile_root) -> (normalized, sidecar)。返り値は2つの要素のまま。\n - normalized: tree の列。閉じた一覧(r03)の node だけを marker に置き換えたもの。\n - sidecar: dict で、key は次の3つに固定。\n - \"entries\": [{\"event_index\", \"path\", \"key\", \"original_node\"}…]。F1〜F3 で置き換えた全ての node の元の値。F3 の場合は original_node に元の message の文字列を入れ、\"root\" に、置き換えた root を入れる。\n - \"violations\": [{\"event_index\", \"path\", \"kind\", \"node\"}…]。閉じた一覧の外にあった、*_us / *_ms の key、profile_root を含む文字列など。**存在しただけでは不合格にしない**。正規化はせずに、そのまま保持して記録する。\n - \"profile_root\": 使った root の文字列と、guard の actual_user_data_dir との一致の結果。\n- restore_events(normalized, sidecar, profile_root) -> events: entries から元に戻す。violations の node は、もともと変えていないので、そのまま。\n- 状態の tree にも、同じ形の normalize_tree(tree, profile_root) -> (normalized, sidecar) と restore_tree を用意する。\n- r03 の規則は、そのまま。violations にあるものを正規化しようとしたら拒否する。violations にあるものが、比べる2つの側で実際に異なれば、その差は不一致(失敗)として、path と両側の値を記録する。\n\nD. 段階への影響\n- S1(今回): compare_versions.py に、A4 の比較、C の4つの関数、A3 の差分の再構成、tree_sha の再計算、check_source_closure を実装する。試験は合成の tree で行い、次のものを確かめる。\n - 型の違い(int と float、String と StringName、型つきの配列)を区別すること\n - dict の順序だけの差の path\n - 差分の再構成の完全一致\n - sidecar からの逆の復元\n - violations の扱い(存在だけでは不合格にしない、正規化しようとしたら拒否、差があれば不一致)\n- S2: eq_probe.gd に、A1 の encode と decode、A2 の roundtrip、A3 の書き出し、B の記録を実装する。\n- S3 と S4 は、r01 のとおり。\n" + }, + "EQ_S3_STAGE_PLAN.txt": { + "sha256": "ecbfb00691017fbd35027df8fa9ca6f82c761a5a3389568fe44b1babcfca308a", + "full_unedited": "EQ_S3_STAGE_PLAN(P28-02-EQ。EQ_STAGED_IMPLEMENTATION_PLAN r01/r02 の段階 S3 を、S3a と S3b に分ける。理由: S2 は 846.159 秒で、Runner の900秒の上限に近かったため。要求の範囲は変えない。SPEC、TASK、6条件、eq/references、eq/registration、補足 r01/r02/r03 は変更しない)\n\n共通\n- 最初に eq/PROGRESS.md と eq/IMPLEMENTATION.md を読み、S1/S2 の型・path・record schema・API・notes を再利用する。再設計しない。\n- S1/S2 のコードと試験の本体を消さない。書き直さない(S3 で直すと決めた checker の2点と、失敗した試験が求める修正を除く)。\n- 失敗の履歴は、PROGRESS.md と UNIT_OUTPUT に残す。各段階の終わりに、engine を使わない python3 test_eq.py の全件 PASS まで直し、生出力を保存する。\n- 状態を変える呼出しは、SPEC §3.3 (b) の、列挙した scenario の専用の区間の中でだけ許可する。check_eq.py の静的な許可も、その区間と列挙した操作に限る。\n- engine の起動、git への書込み、製品の変更、全回帰はしない。SPEC、TASK、eq/references、eq/registration は変更しない。\n\nS3a(次の run)\n1. checker の修正 1(eq/check_eq.py:109)\n - 各 checkpoint の immutable snapshot の phase の key の集合が、正確に {0,…,10} であることを要求する(空の dict や、一部の欠落を拒否する)。\n - 負の試験を加える: 空、1つの欠落、範囲外の key、重複した key の表現。\n2. checker の修正 2(eq/check_eq.py:147-150)\n - 測定の区間の30 tick の各分について、製品の _publish_snapshot(autoload/simulation_runtime.gd:12616-12621)が出す snapshot_published → state_updated を、実際の回数と順序で記録したものを、その分の checkpoint と結びつけて検査する。\n - 各分に、ちょうど1組であること(snapshot_published に接続した受け手が無い場合は、製品の条件 :12619 のとおり state_updated だけになるので、probe の側で接続を記録し、期待値をその実際の接続の状態から決める)。\n - 順序は snapshot_published が先。\n - 分の番号は、checkpoint の minute と一致すること。\n - scenario の区間で出た追加の signal は、別の区間の記録に入れる。測定の区間の記録には混ぜない。\n - 負の試験を加える: 欠落、一部の分だけ、重複、順序の改ざん、分のずれ、scenario の signal の混入。\n3. E3 失敗時の拒否(専用の scenario の区間。R と O の両方)\n - restore_snapshot、SimulationSnapshot.validate、load_from_path の3つの API に、次の不正な入力を、それぞれ1件以上与える:\n - 欠けた key\n - 違う型\n - 範囲外の値\n - 重複した ID(published_ids、facility の ID)\n - world.bin の改ざん(r03 の D3 の固定の規則)\n - 不正な入力は、B1 の snapshot の deep copy から、固定の規則で作る。乱数や時刻を使わない。\n - 記録すること:\n - 戻り値と code\n - 前後の S/K/C 層(同じ PID の中で完全に比べる)\n - 全イベントの差分と、その件数(r02 の T4: 直接の restore は0件、load の失敗は SAVE_LOAD_FAILED がちょうど1件で、X(B, ev_fail) と r03 の正規化の後で完全一致すること)\n - check_eq.py: E3 の記録の形式と矛盾の検査を加える。製品の失敗(不正な入力が受理された、状態が変わった、など)は、「既存の不具合」として記録する。PASS で補わない。\n - 試験を加える: E3 の正常の記録と、拒否の場合(code の欠落、件数の不一致、拒否の前後の状態の変化を見逃すこと)。\n4. 終わり: PROGRESS.md を更新し、正式な JSON の status を blocked にし、findings を「段階 S3a 完了(失敗ではない。次は S3b)」とする。\n\nS3b(S3a の後の run)\n1. E4 キャッシュの古さ(専用の区間。R と O)\n - 場面: 状態を変えるコマンド(建設のコマンドを1件、通常の command queue を通す)、tick(advance_minutes(1))、restore_snapshot、load_from_path、状態を変えないコマンド。\n - 各場面の直後の create_snapshot() と latest_snapshot を、完全な typed tree(r02 の A)で記録する。版の間の比較は compare_versions.py で行う。\n - 件数: 直接の restore は SAVE_* が0件、load の成功は SAVE_LOADED がちょうど1件(X(P, ev_load))。\n2. E5 所有権(専用の区間)\n - 対象: create_snapshot() の戻り値、latest_snapshot、snapshot_published と state_updated の引数。\n - 外から内: 入れ子の dict と配列を変更した後に、内部の状態、次の create_snapshot()、latest_digest が変わっていないかを、完全な typed tree で確かめる。\n - 内から外: 次の tick の後に、既に返した値が変わっていないかを確かめる。\n - 予想される aliasing(latest_snapshot と signal の引数が同じ object であること)による live の変化は、「既存の不具合」として、変わった path と値を全て記録する。その後の検査は、新しい baseline から始める。harness による無断の変更とは区別する。\n3. check_eq.py と試験: E4/E5 の記録の検査と、正常と拒否の試験を加える。\n4. 終わり: PROGRESS.md を更新し、正式な JSON の status を blocked にし、findings を「段階 S3b 完了(失敗ではない。次は S4)」とする。\n\nその後\n- S4: run_eq.py と verify_eq.py、bundle の試験、全件 PASS の後に正式に提出する。\n- その後に、Root の native(7 phase)→ 両方の validation → 別の新しい Opus による全6条件のレビュー → 通常の統合と final、の順序で進める。\n" + }, + "EQ_S3_STAGE_PLAN_R02.txt": { + "sha256": "566e3ad98f9d47136ff4d4932f81c0a7f9fc96321a6f08ba944a9f1e736e6caa", + "full_unedited": "EQ_S3_STAGE_PLAN r02(P28-02-EQ。EQ_S3_STAGE_PLAN(r01)の分け方(S3a = checker の2点の修正 + E3、S3b = E4/E5)、共通の規則、S3b、その後の順序は、そのまま有効。この r02 は、実際の API に合わせて、S3a の「checker の修正 2」と「E3」を置き換えて確定する。SPEC、TASK、6条件、eq/references、eq/registration、補足 r01/r02/r03、段階の計画 r01/r02 は変更しない)\n\n1. checker の修正 1(eq/check_eq.py:109): r01 のとおり(phase の key の集合が正確に {0..10}、負の試験)。\n\n2. checker の修正 2(eq/check_eq.py:147-150。r01 を置き換える)\n- probe は、自分の observer を snapshot_published に接続している。そのため、製品の _publish_snapshot(autoload/simulation_runtime.gd:12616-12621)は、毎 tick、snapshot_published を出してから state_updated を出す(:12619 の条件が真になる)。\n- 測定の区間の30 tick の各分について、**ちょうど1組の snapshot_published → state_updated** を要求し、その分の checkpoint の minute と結びつける。\n- 測定の開始の時点で、snapshot_published と state_updated の接続の一覧(get_connections() の、接続先の object と method)を記録し、その中に probe 自身の接続があることを要求する。probe の接続が無い場合は、期待を「state_updated だけ」に下げることはせず、失敗にする。\n- 製品で受け手が接続されていない場合の動作(state_updated だけ)は、この区間の対象の外とする。試験もしない。\n- scenario の区間で出た signal は、別の区間の記録に入れ、測定の区間には混ぜない。\n- 負の試験を加える:\n - 欠落、一部の分だけ、重複、順序の改ざん、分のずれ\n - scenario の signal の混入\n - probe の接続が一覧に無いのに合格にすること\n - 期待を state_updated だけに下げること\n\n3. E3 失敗時の拒否(専用の scenario の区間。r01 を置き換える)\n\n3.1 各 API の実際の戻り値(架空の code は作らない)\n- SimulationRuntime.restore_snapshot(Dictionary) -> bool(:587): 戻り値の bool を、そのまま記録する。code は null とし、理由を \"API returns bool only\" とする。\n- SimulationSnapshot.validate(Dictionary) -> {ok, errors}(scripts/core/simulation_snapshot.gd:16-43): 返った dict の全体(ok と、errors の全件)を、そのまま記録する。code は null とし、理由を \"API returns ok/errors only\" とする。\n- load_from_path(String) -> Dictionary(:4223): 実際の code を記録する。この API で code が欠けていれば、それは失敗として拒否する(上の2つの「API に code が無い」とは区別する)。\n\n3.2 不正の分類と、それを適用する API(source に基づく表。適用しないものは、理由つきの NA として記録し、PASS に補わない)\n\n| 分類 | restore_snapshot(Dictionary) | validate(Dictionary。envelope の外形だけを検査) | load_from_path(package) |\n|---|---|---|---|\n| 欠けた key | 適用: B1 の deep copy から clock を削除 → false を期待 | 適用: clock を削除 → errors に missing_clock を期待 | 適用: package の manifest.json から checksum_world を削除 → INVALID_MANIFEST を期待 |\n| 違う型 | 適用: clock.absolute_minute を文字列 \"x\" に → false | 適用: 同じ → errors に invalid_absolute_minute | 適用: manifest.json の format_version を文字列に → INVALID_MANIFEST |\n| 範囲外の値 | 適用: clock.speed を 9 に → false | 適用: 同じ → errors に invalid_speed | 適用: manifest.json の format_version を、対応していない大きな整数に → UNSUPPORTED_FORMAT(自動の migration を試みた場合は、その実際の code と、migration_attempted を記録) |\n| 重複した ID(published_ids) | 適用: systems.runtime.domain_events.published_ids に、既存の ID を1つ追加 → false(DomainEventStream.restore_snapshot、scripts/core/domain_event_stream.gd:113-140 が拒否) | NA: validate は envelope の外形だけで、runtime の内部を検査しない(:16-43)。実際の戻り値(ok:true を予想)は記録するが、不具合とはしない | 適用(公開の API で作れる場合): 重複を入れた snapshot を SaveService.save_snapshot で、固定の user:// の path に保存し、load_from_path で読む。save が拒否した場合は、その実際の code を記録し、load の側は理由つきの NA にする |\n| 重複した ID(facility) | R で適用: 施設の instance の配列で、最初の entry を複製 → false(FacilityService.restore_snapshot、scripts/facility/facility_service.gd:701-703 が拒否)。O で NA: B1 の施設の件数が実際に0のとき、複製する既存の entry が無いため(件数を記録する)。施設を建設すること、R の B1 で代用すること、製品の値を作ることはしない | NA: 上と同じ理由 | R で、published_ids と同じ方法で適用。O で NA(理由は同じ) |\n| world.bin の改ざん | NA: Dictionary の API は package を読まない | NA: 同じ | 適用: r03 の D3 の固定の規則 → CHECKSUM_MISMATCH を期待 |\n\n- 不正な入力は、B1 の deep copy と、固定の user:// の相対 path と、固定の規則だけで作る。乱数・時刻・PID を使わない(r03 の D1〜D3)。\n- 期待の結果は、上の source に基づくものとして記録する。実際の結果が期待と違う場合(たとえば、不正な入力が受理された)は、「既存の不具合の候補」として、全ての記録とともに残す。ただし、envelope の validate が runtime の内部の重複を受理することは、その API の範囲の外なので、不具合とは断定しない。\n\n3.3 各操作で記録し、検査すること\n- 前後の S/K/C 層(同じ PID の中で、完全に比べる)。拒否された場合は、変化が無いこと。\n- 全イベントの差分と、その件数。restore_snapshot と validate は0件。load_from_path の失敗は SAVE_LOAD_FAILED がちょうど1件で、X(B, ev_fail) と、r03 の正規化の後で完全一致すること。\n- 適用と NA の表を、そのまま report に入れる。fresh の whole-unit レビューが、適用の条件を判定できるようにする。\n\n3.4 試験(test_eq.py)\n- 正常の記録。\n- 拒否の場合:\n - restore と validate の架空の code\n - load の code の欠落を合格にすること\n - NA を PASS として数えること\n - O の施設の重複を、件数が0なのに適用したと記録すること\n - 拒否の前後の状態の変化を見逃すこと\n - 件数の不一致\n - envelope の validate が重複を受理したことを、製品の不具合と断定すること\n\n4. 終わり: r01 のとおり(PROGRESS.md を更新し、正式な JSON の status を blocked にし、findings を「段階 S3a 完了(失敗ではない。次は S3b)」とする)。\n" + } + }, + "read_only_clarifications": { + "EQ_S_TIMING_CLARIFICATION.txt": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/.runtime/P28-02-EQ/build/eq-staged-readonly-r04/EQ_S_TIMING_CLARIFICATION.txt", + "sha256": "25d323fd562d29e80782b6f075fc7a0e8b49457a6c4fbd7c30e74b31a6b6a126" + }, + "EQ_S_TIMING_CLARIFICATION_R02.txt": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/.runtime/P28-02-EQ/build/eq-staged-readonly-r04/EQ_S_TIMING_CLARIFICATION_R02.txt", + "sha256": "777accdd652f85db6b9014d85e3c8b3b60ca94b20768e6173b36bc769d360fd9" + }, + "EQ_ENVIRONMENT_FIELDS_CLARIFICATION_R03.txt": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/.runtime/P28-02-EQ/build/eq-staged-readonly-r04/EQ_ENVIRONMENT_FIELDS_CLARIFICATION_R03.txt", + "sha256": "12b27f984ef5843d98327200ad261dccaf64968402192b08ad55b15ed5454ea2" + } + } + } +} diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/S3B_SUPPLEMENTARY.json b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/S3B_SUPPLEMENTARY.json new file mode 100644 index 0000000..4b7803c --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/S3B_SUPPLEMENTARY.json @@ -0,0 +1,49 @@ +{ + "actual_commander_context": { + "actual_run_decision": { + "action": "run", + "task_id": "P28-02-EQ", + "reason": "Supersedes DESKTOP_EQ_S3B_RUN_DECISION.json, which is kept unchanged as history. Use only after Root verifies through the normal gates: repair_ready, repairs 7, no S submitted, no active run, and the S1, S2 and S3a files still present unchanged in the W. Run repair 7 of P28-02-EQ once on the same W from base 2549cf7d6992560b850bbd11934e3c14b39a1988 with the single worker codex gpt-6-astra, doing only stage S3b as defined in EQ_S3B_STAGE_PLAN.txt and corrected in E4-1 only by EQ_S3B_STAGE_PLAN_R02.txt. Deliver both S3b plans in full as part of the one supplementary key, together with both S3 plans, both staged plans and this decision; clarifications r01, r02 and r03 stay read-only in build/eq-staged-readonly-r04. Start by reading eq/PROGRESS.md, including the run 7da027a entry, and eq/IMPLEMENTATION.md, including the S4 binding requirements, and reuse the S1/S2/S3a types, paths, schema, API and code without redesign. E4-1 correction: in both R and O, take candidates from that PID's runtime.definition_registry.get_facility_ids(), sorted by text ID, scan cells in (x, y, z) lexical order with rotation 0, judge each pair only with the public preview_build_facility, and submit the first placeable pair through submit_command(&\"build_facility\", {definition_id, origin, rotation}). Save the raw enumerated list and count, the sorted list and rule, the cell range rule, every tried candidate with its full preview result, the chosen candidate with its submit and command result, and any non-application reason. NA is allowed only when the real list is non-empty and every pair is not placeable; an empty list is a failure, and a false NA from an empty or wrong source is forbidden. NA is never PASS, no facility values are invented, and nothing is built outside this path. Everything else in S3b is unchanged: E4 paths 2 to 5, E5 over all 4 targets by 2 locations by 2 directions, full typed state and event records, the latest_snapshot aliasing (:12617-12621) recorded as an existing defect and never as PASS, the listed check_eq.py rules and negative tests plus the r02 E4-1 rejections, and keeping E3, the 91 existing test bodies and the failure history except for fixes a failing test requires. Run the engine-free python3 test_eq.py until every test passes, save the raw output, update PROGRESS.md, and end S3b with formal status blocked and the finding 'stage S3b complete (not a failure; next is S4)'. Do not submit. No engine, no git write or commit, no product change, no full regression; SPEC, TASK, eq/references and eq/registration stay unchanged. Ordinary implementation choices are recorded without stopping; block only for undecided matters affecting original product spec, values, permissions, billing or original acceptance. The remaining order is S4 (driver and verify) and submission, then Root native on the exact S in 7 phases, then both validations, then a fresh independent Opus review of all 6 conditions, then the normal prepare, candidate qualification, approval, integration and final; the OPT whole-unit gate follows later. No original credit (23/88, 4/30); the 900-second timeout is unchanged. Quota fallback only on structured provider quota, once, same role, Antigravity claude-opus-5-5-high; any other failure is blocked. Decided by Claude Opus 5.5 in the Desktop control session (message 336); not a CLI commander result." + }, + "actual_full_plans": { + "EQ_STAGED_IMPLEMENTATION_PLAN.txt": { + "sha256": "eb7b4831e2164c6fc983fa6f9825e7f3e2993b4c0ebf2f90aac8ad10662666d2", + "full_unedited": "EQ_STAGED_IMPLEMENTATION_PLAN(P28-02-EQ repair 3 以降。base 2549cf7d6992560b850bbd11934e3c14b39a1988。SPEC、TASK、6条件、eq/references、eq/registration、EQ_S_TIMING_CLARIFICATION r01/r02、EQ_ENVIRONMENT_FIELDS_CLARIFICATION r03 は全てそのまま有効。変えるのは、工程と、成果物の内部の設計の固定だけ)\n\n前回までの事実\n- repair 2(run 84ca0ff8…)は、IMPLEMENTATION.md と compare_versions.py などを作った後、item_30 で全てを削除し、「6ファイルと unit の PASS を提供できない」として、自分から終了した。仕様の不足の指摘ではない。packet は 94 KB あった。\n- この失敗は失敗のまま保持する。削除したことを成功として扱わない。\n\n工程の変更(必須)\n- G1: **作ったファイルは、削除しない**。完成していなくても、W の eq/ に残す。各 run の最後に、eq/PROGRESS.md に、終わった段階・残りの作業・現在の試験の結果を書く。\n- G2: 1回の run では、下の**1つの段階だけ**を行う。始める前に eq/PROGRESS.md を読み、次の段階から再開する。前の段階のコードは作り直さない。\n- G3: 各段階の終わりに、engine を使わない python3 test_eq.py を実行する。その時点で存在する試験が、全件 PASS になるまで直す。生出力を eq/UNIT_OUTPUT.txt に保存する。\n- G4: 段階1〜3の終わりには、正式な JSON の status を blocked にし、findings に「段階 Sx 完了(失敗ではない。次は Sx+1)」と PROGRESS.md の要点を書いて返す。段階4の終わりにだけ、提出する(status を submitted 相当の正式な提出にする)。\n- G5: 通常の実装上の判断(関数の分け方、名前、試験データ、記録の書式)は、IMPLEMENTATION.md に記録して進める。blocked にしてよいのは、原本の仕様・値・権限・課金・受入に影響する未確定事項がある場合だけ。\n- G6: engine の起動、git への書込み、製品の変更、全回帰はしない。SPEC、TASK、eq/references、eq/registration は変更しない。\n\n固定するインターフェース(6ファイル。SPEC §2)\n\n1. compare_versions.py(Python のみ。engine を使わない)\n - normalize_events(events, profile_root) -> (normalized, sidecar):\n - r03 の F1〜F3 を、JSON の event の一覧に適用する。\n - 閉じた一覧の外の *_us / *_ms / profile_root を含む文字列は、正規化せず、violations として返す。\n - restore_events(normalized, sidecar, profile_root) -> events: 逆の復元(完全一致の確認に使う)。\n - compare_reports(a, b) -> dict: 2つの report(同じ版の別 PID、または前後の版)を比べる。\n - 毎分の checkpoint の S_norm_sha と latest_norm_sha の一致\n - digest の規則(r02 の T3)\n - K と C の、SPEC §3.2 に列挙した欄\n - E2 の正規化した全イベント(開始の counter の一致が前提)\n - E3/E4/E5 の scenario の結果の一致\n - 比べない欄は、理由と両側の値を記録する\n - 差は path ごとに返す\n - check_source_closure(before_map, after_map, allowed_changed) -> dict: SPEC §2 と OPT r02 §2。追加・欠落・登録されていない差分を拒否する。\n2. eq_probe.gd(GDScript):\n - 起動の6段階は、DIAG の diag_probe.gd の構成をそのまま参考にする。\n - 役割は R と O(env の THE_TREE_EQ_ROLE)。\n - 観測の checkpoint は B1 と、30分の各 tick の最後(31個)。各 checkpoint に、次のものを置く:\n - minute\n - S_raw_sha、S_norm_sha(GDScript の中で F1〜F3 の typed の marker を使って正規化した後の var_to_bytes の SHA)\n - 正規化した S の path の hash の表(depth ≤ 4)\n - latest_norm_sha\n - digest の情報\n - K と C の全体\n - sidecar\n - E2 は subscribe('*') で、全イベントの JSON(正規化の前)を記録する。正規化は compare_versions.py で行う(GDScript と Python で、同じ規則の二重実装をしない)。\n - E3/E4/E5 の scenario は、SPEC §3.3 の専用の区間で行う。各区間について、開始と終了、操作、code、前後の S/K/C、件数(r02 の T4)を記録する。\n - stdout には、P28_02_EQ_REPORT= をちょうど1行出す。終了は close_requested.emit()。\n3. check_eq.py: report 1つを検査する。\n - 形式、必須の欄、矛盾\n - 閉じた一覧の外の差\n - probe の静的な禁止(autoload の class_name の参照、状態を変える呼出しの区間の外での使用、Variant からの := の推論)\n - SimulationDigest だけでの判定\n4. run_eq.py: Root が実行する driver。\n - diag_p28_02.py の構成をそのまま参考にする(--check / --run、依存の SHA、1407 の source、凍結した S の照合、owned phase、guard、private profile、cleanup)。\n - phase は import、parse-base、parse-wrapper、R-A、R-B、O-A、O-B。\n - 成功したら、execution.json と bundle.json を作る。\n5. verify_eq.py: --project-root . で、$BUILD_OUTPUT_DIR/p28-02-eq-evidence の bundle を結合する。bundle が無ければ失敗する。\n - 各 report に check_eq を行う。\n - R-A と R-B、O-A と O-B に compare_reports を行い、差が0であること(harness の正しさ)。\n - E3/E5 の、前の版での製品の失敗は、「既存の不具合」の一覧として出力する。harness の不合格とは区別する。\n - SPEC、TASK、eq/references、eq/registration の SHA を固定して照合する。\n6. test_eq.py: 合成した入力だけで動く。各段階で、その段階の試験を足していく。\n\n段階(1回の run で1つ)\n- S1: compare_versions.py の全体と、その試験(F1〜F3 の正常と拒否、可逆性、比較、source の閉包)。PROGRESS.md と IMPLEMENTATION.md を作る。\n- S2: eq_probe.gd の、起動・観測の checkpoint・E2 の記録・報告。check_eq.py の静的な検査と形式の検査、それぞれの試験。\n- S3: eq_probe.gd の E3/E4/E5 の scenario、check_eq.py のそれに対する検査、試験。\n- S4: run_eq.py と verify_eq.py、bundle の試験。全件 PASS を確かめて、正式に提出する。\n\nRoot への依頼(packet を小さくするため)\n- actual_commander_context の key には、この計画の全文と RUN の判断だけを入れる。r01・r02・r03 の全文は、build/ に読取専用で置き、その path と SHA だけを渡す。eq/references は W の中にあるので、path だけで足りる。\n" + }, + "EQ_STAGED_IMPLEMENTATION_PLAN_R02.txt": { + "sha256": "128f42f18e168e9299995296ac7ad119f47d1647799d472663282e47e8ac9fdd", + "full_unedited": "EQ_STAGED_IMPLEMENTATION_PLAN r02(P28-02-EQ repair 3 以降。EQ_STAGED_IMPLEMENTATION_PLAN(r01)の工程 G1〜G6、段階 S1〜S4、Root への依頼は、そのまま有効。この r02 は、固定インターフェースのうち、状態とイベントの運搬の表現と、normalize_events の返り値を置き換えて確定する。SPEC、TASK、6条件、eq/references、eq/registration、補足 r01/r02/r03 は変更しない)\n\nA. 型を保つ運搬の表現(typed tree。JSON は運び方であって、型の情報は落とさない)\n\nA1 node の形式(JSON の配列)\n- 各値は [type_code, payload]。type_code は Godot の typeof() の値。\n - null: [0]\n - bool: [1, 0|1]\n - int: [2, 整数]\n - float: [3, \"<8 byte little-endian IEEE754 の hex>\"](10進の文字列にしない)\n - String: [4, \"文字列\"]\n - StringName: [21, \"文字列\"]\n - Vector2/Vector2i/Vector3/Vector3i/Rect2/Rect2i/Color など: [type_code, [各成分の node]](成分は int か float の node)\n - Dictionary: [27, [[key_node, value_node], …], typed_info]。**元の挿入の順序のまま**並べる。typed_info は、型つきの Dictionary なら key と value の builtin 型・class 名・script、それ以外は null。\n - Array: [28, [element_node, …], typed_info]。typed_info は get_typed_builtin()・get_typed_class_name()・get_typed_script() の値、型の無い Array なら null。\n - PackedByteArray: [29, \"\"]。他の Packed*Array も、要素ごとの node の列にする(float は hex)。\n- Object、Callable、Signal、RID が現れたら、運搬せずに失敗にする(snapshot と event の dict には、本来現れないもの)。\n\nA2 無損失の証明(Godot の中で行う。probe の必須の処理)\n- tree = encode(value) を作った後、decode(tree) で Variant を作り直す。var_to_bytes(decode(tree)) == var_to_bytes(value) であることを確かめる。一致しなければ失敗にする。\n- report には、checkpoint ごとに、次の3つを記録する。\n - raw_bytes_sha = sha256(var_to_bytes(value))\n - tree_sha = sha256(tree を key の順序を変えずに JSON.stringify した UTF-8)\n - roundtrip_ok\n- Python は、受け取った tree から tree_sha を計算し直して結合する。これで、Python で比べる tree が、Godot の元の bytes と無損失に対応することが保証される。\n\nA3 保存の場所と大きさ(深さの制限は設けない。全体を再構成できるようにする)\n- 各 PID は、checkpoint の列(B1 と、30分の各 tick の最後)について、S 層と latest_snapshot を、次の形で、private user:// の evidence/ に書き出す。driver は、それを RESTART の copy_states と同じ方式で out へ複製し、SHA を結合する。\n - checkpoint 0(B1): tree の全体(JSON、zstd で圧縮してよい。圧縮した場合は、圧縮の前後の SHA を両方記録する)。\n - checkpoint k(k≥1): checkpoint k−1 の tree に対する、path を指定した差分の操作の列。操作は set(path, node)、dict_insert(path, index, key_node, value_node)、dict_remove(path, key_node)、array_splice(path, start, delete_count, [node…])。順序つきで、再構成すると、checkpoint k の tree と完全一致すること。\n - latest_snapshot は、各 checkpoint で、var_to_bytes が S 層と同じなら same_as_S=true とし、違えば、その tree(または S に対する差分)を保存する。\n- Python は、checkpoint 0 から差分を順に適用して、全ての checkpoint を再構成する。checkpoint ごとに tree_sha と一致することを確かめる。\n\nA4 比較(compare_versions.py。全て tree の上で行い、深さの制限は無い)\n- 第一の比較は、tree の完全一致(型、key、順序、値。全ての node)。\n- 一致しない場合に限り、正規化した比較を行う。dict の key を文字で並べ(同じ文字の key が2つあれば拒否)、それ以外の型・値・配列の順序を保ったまま比べる。それで一致すれば「dict の列挙の順序だけの差」として、その全ての path を記録する。それ以外の差は、全ての path と両側の node を記録して、不一致にする。\n- F1〜F3(r03)の正規化は、tree の node の上で行う。sidecar から、元の tree へ完全に戻せること(tree_sha が一致すること)を確かめる。\n\nB. E2 のイベントの運搬\n- 各 event について、event.to_dictionary()(製品の直列化。scripts/core/domain_event.gd:47-59)の tree を記録する。あわせて、元の object の欄の型(event_id と event_type が StringName であるか、entity_ids の型、payload の dict の typed_info)を、original_field_types として記録する。\n- 受け取りの順序で番号をつけ、開始の時点の counter と、published_ids の数を記録する。\n- イベントの列は、A3 と同じく evidence/ に書き出し(tree の列。圧縮してよい)、SHA を結合する。Godot の中で、各 event について A2 の roundtrip を確かめる。\n- compare_reports は、この tree の列を受け取り、全ての欄と event_id を**そのまま**比べる(ID の付け替えはしない)。F1〜F3 は、payload の該当する node にだけ適用する。\n\nC. normalize_events とその仲間の返り値(固定)\n- normalize_events(events, profile_root) -> (normalized, sidecar)。返り値は2つの要素のまま。\n - normalized: tree の列。閉じた一覧(r03)の node だけを marker に置き換えたもの。\n - sidecar: dict で、key は次の3つに固定。\n - \"entries\": [{\"event_index\", \"path\", \"key\", \"original_node\"}…]。F1〜F3 で置き換えた全ての node の元の値。F3 の場合は original_node に元の message の文字列を入れ、\"root\" に、置き換えた root を入れる。\n - \"violations\": [{\"event_index\", \"path\", \"kind\", \"node\"}…]。閉じた一覧の外にあった、*_us / *_ms の key、profile_root を含む文字列など。**存在しただけでは不合格にしない**。正規化はせずに、そのまま保持して記録する。\n - \"profile_root\": 使った root の文字列と、guard の actual_user_data_dir との一致の結果。\n- restore_events(normalized, sidecar, profile_root) -> events: entries から元に戻す。violations の node は、もともと変えていないので、そのまま。\n- 状態の tree にも、同じ形の normalize_tree(tree, profile_root) -> (normalized, sidecar) と restore_tree を用意する。\n- r03 の規則は、そのまま。violations にあるものを正規化しようとしたら拒否する。violations にあるものが、比べる2つの側で実際に異なれば、その差は不一致(失敗)として、path と両側の値を記録する。\n\nD. 段階への影響\n- S1(今回): compare_versions.py に、A4 の比較、C の4つの関数、A3 の差分の再構成、tree_sha の再計算、check_source_closure を実装する。試験は合成の tree で行い、次のものを確かめる。\n - 型の違い(int と float、String と StringName、型つきの配列)を区別すること\n - dict の順序だけの差の path\n - 差分の再構成の完全一致\n - sidecar からの逆の復元\n - violations の扱い(存在だけでは不合格にしない、正規化しようとしたら拒否、差があれば不一致)\n- S2: eq_probe.gd に、A1 の encode と decode、A2 の roundtrip、A3 の書き出し、B の記録を実装する。\n- S3 と S4 は、r01 のとおり。\n" + }, + "EQ_S3_STAGE_PLAN.txt": { + "sha256": "ecbfb00691017fbd35027df8fa9ca6f82c761a5a3389568fe44b1babcfca308a", + "full_unedited": "EQ_S3_STAGE_PLAN(P28-02-EQ。EQ_STAGED_IMPLEMENTATION_PLAN r01/r02 の段階 S3 を、S3a と S3b に分ける。理由: S2 は 846.159 秒で、Runner の900秒の上限に近かったため。要求の範囲は変えない。SPEC、TASK、6条件、eq/references、eq/registration、補足 r01/r02/r03 は変更しない)\n\n共通\n- 最初に eq/PROGRESS.md と eq/IMPLEMENTATION.md を読み、S1/S2 の型・path・record schema・API・notes を再利用する。再設計しない。\n- S1/S2 のコードと試験の本体を消さない。書き直さない(S3 で直すと決めた checker の2点と、失敗した試験が求める修正を除く)。\n- 失敗の履歴は、PROGRESS.md と UNIT_OUTPUT に残す。各段階の終わりに、engine を使わない python3 test_eq.py の全件 PASS まで直し、生出力を保存する。\n- 状態を変える呼出しは、SPEC §3.3 (b) の、列挙した scenario の専用の区間の中でだけ許可する。check_eq.py の静的な許可も、その区間と列挙した操作に限る。\n- engine の起動、git への書込み、製品の変更、全回帰はしない。SPEC、TASK、eq/references、eq/registration は変更しない。\n\nS3a(次の run)\n1. checker の修正 1(eq/check_eq.py:109)\n - 各 checkpoint の immutable snapshot の phase の key の集合が、正確に {0,…,10} であることを要求する(空の dict や、一部の欠落を拒否する)。\n - 負の試験を加える: 空、1つの欠落、範囲外の key、重複した key の表現。\n2. checker の修正 2(eq/check_eq.py:147-150)\n - 測定の区間の30 tick の各分について、製品の _publish_snapshot(autoload/simulation_runtime.gd:12616-12621)が出す snapshot_published → state_updated を、実際の回数と順序で記録したものを、その分の checkpoint と結びつけて検査する。\n - 各分に、ちょうど1組であること(snapshot_published に接続した受け手が無い場合は、製品の条件 :12619 のとおり state_updated だけになるので、probe の側で接続を記録し、期待値をその実際の接続の状態から決める)。\n - 順序は snapshot_published が先。\n - 分の番号は、checkpoint の minute と一致すること。\n - scenario の区間で出た追加の signal は、別の区間の記録に入れる。測定の区間の記録には混ぜない。\n - 負の試験を加える: 欠落、一部の分だけ、重複、順序の改ざん、分のずれ、scenario の signal の混入。\n3. E3 失敗時の拒否(専用の scenario の区間。R と O の両方)\n - restore_snapshot、SimulationSnapshot.validate、load_from_path の3つの API に、次の不正な入力を、それぞれ1件以上与える:\n - 欠けた key\n - 違う型\n - 範囲外の値\n - 重複した ID(published_ids、facility の ID)\n - world.bin の改ざん(r03 の D3 の固定の規則)\n - 不正な入力は、B1 の snapshot の deep copy から、固定の規則で作る。乱数や時刻を使わない。\n - 記録すること:\n - 戻り値と code\n - 前後の S/K/C 層(同じ PID の中で完全に比べる)\n - 全イベントの差分と、その件数(r02 の T4: 直接の restore は0件、load の失敗は SAVE_LOAD_FAILED がちょうど1件で、X(B, ev_fail) と r03 の正規化の後で完全一致すること)\n - check_eq.py: E3 の記録の形式と矛盾の検査を加える。製品の失敗(不正な入力が受理された、状態が変わった、など)は、「既存の不具合」として記録する。PASS で補わない。\n - 試験を加える: E3 の正常の記録と、拒否の場合(code の欠落、件数の不一致、拒否の前後の状態の変化を見逃すこと)。\n4. 終わり: PROGRESS.md を更新し、正式な JSON の status を blocked にし、findings を「段階 S3a 完了(失敗ではない。次は S3b)」とする。\n\nS3b(S3a の後の run)\n1. E4 キャッシュの古さ(専用の区間。R と O)\n - 場面: 状態を変えるコマンド(建設のコマンドを1件、通常の command queue を通す)、tick(advance_minutes(1))、restore_snapshot、load_from_path、状態を変えないコマンド。\n - 各場面の直後の create_snapshot() と latest_snapshot を、完全な typed tree(r02 の A)で記録する。版の間の比較は compare_versions.py で行う。\n - 件数: 直接の restore は SAVE_* が0件、load の成功は SAVE_LOADED がちょうど1件(X(P, ev_load))。\n2. E5 所有権(専用の区間)\n - 対象: create_snapshot() の戻り値、latest_snapshot、snapshot_published と state_updated の引数。\n - 外から内: 入れ子の dict と配列を変更した後に、内部の状態、次の create_snapshot()、latest_digest が変わっていないかを、完全な typed tree で確かめる。\n - 内から外: 次の tick の後に、既に返した値が変わっていないかを確かめる。\n - 予想される aliasing(latest_snapshot と signal の引数が同じ object であること)による live の変化は、「既存の不具合」として、変わった path と値を全て記録する。その後の検査は、新しい baseline から始める。harness による無断の変更とは区別する。\n3. check_eq.py と試験: E4/E5 の記録の検査と、正常と拒否の試験を加える。\n4. 終わり: PROGRESS.md を更新し、正式な JSON の status を blocked にし、findings を「段階 S3b 完了(失敗ではない。次は S4)」とする。\n\nその後\n- S4: run_eq.py と verify_eq.py、bundle の試験、全件 PASS の後に正式に提出する。\n- その後に、Root の native(7 phase)→ 両方の validation → 別の新しい Opus による全6条件のレビュー → 通常の統合と final、の順序で進める。\n" + }, + "EQ_S3_STAGE_PLAN_R02.txt": { + "sha256": "566e3ad98f9d47136ff4d4932f81c0a7f9fc96321a6f08ba944a9f1e736e6caa", + "full_unedited": "EQ_S3_STAGE_PLAN r02(P28-02-EQ。EQ_S3_STAGE_PLAN(r01)の分け方(S3a = checker の2点の修正 + E3、S3b = E4/E5)、共通の規則、S3b、その後の順序は、そのまま有効。この r02 は、実際の API に合わせて、S3a の「checker の修正 2」と「E3」を置き換えて確定する。SPEC、TASK、6条件、eq/references、eq/registration、補足 r01/r02/r03、段階の計画 r01/r02 は変更しない)\n\n1. checker の修正 1(eq/check_eq.py:109): r01 のとおり(phase の key の集合が正確に {0..10}、負の試験)。\n\n2. checker の修正 2(eq/check_eq.py:147-150。r01 を置き換える)\n- probe は、自分の observer を snapshot_published に接続している。そのため、製品の _publish_snapshot(autoload/simulation_runtime.gd:12616-12621)は、毎 tick、snapshot_published を出してから state_updated を出す(:12619 の条件が真になる)。\n- 測定の区間の30 tick の各分について、**ちょうど1組の snapshot_published → state_updated** を要求し、その分の checkpoint の minute と結びつける。\n- 測定の開始の時点で、snapshot_published と state_updated の接続の一覧(get_connections() の、接続先の object と method)を記録し、その中に probe 自身の接続があることを要求する。probe の接続が無い場合は、期待を「state_updated だけ」に下げることはせず、失敗にする。\n- 製品で受け手が接続されていない場合の動作(state_updated だけ)は、この区間の対象の外とする。試験もしない。\n- scenario の区間で出た signal は、別の区間の記録に入れ、測定の区間には混ぜない。\n- 負の試験を加える:\n - 欠落、一部の分だけ、重複、順序の改ざん、分のずれ\n - scenario の signal の混入\n - probe の接続が一覧に無いのに合格にすること\n - 期待を state_updated だけに下げること\n\n3. E3 失敗時の拒否(専用の scenario の区間。r01 を置き換える)\n\n3.1 各 API の実際の戻り値(架空の code は作らない)\n- SimulationRuntime.restore_snapshot(Dictionary) -> bool(:587): 戻り値の bool を、そのまま記録する。code は null とし、理由を \"API returns bool only\" とする。\n- SimulationSnapshot.validate(Dictionary) -> {ok, errors}(scripts/core/simulation_snapshot.gd:16-43): 返った dict の全体(ok と、errors の全件)を、そのまま記録する。code は null とし、理由を \"API returns ok/errors only\" とする。\n- load_from_path(String) -> Dictionary(:4223): 実際の code を記録する。この API で code が欠けていれば、それは失敗として拒否する(上の2つの「API に code が無い」とは区別する)。\n\n3.2 不正の分類と、それを適用する API(source に基づく表。適用しないものは、理由つきの NA として記録し、PASS に補わない)\n\n| 分類 | restore_snapshot(Dictionary) | validate(Dictionary。envelope の外形だけを検査) | load_from_path(package) |\n|---|---|---|---|\n| 欠けた key | 適用: B1 の deep copy から clock を削除 → false を期待 | 適用: clock を削除 → errors に missing_clock を期待 | 適用: package の manifest.json から checksum_world を削除 → INVALID_MANIFEST を期待 |\n| 違う型 | 適用: clock.absolute_minute を文字列 \"x\" に → false | 適用: 同じ → errors に invalid_absolute_minute | 適用: manifest.json の format_version を文字列に → INVALID_MANIFEST |\n| 範囲外の値 | 適用: clock.speed を 9 に → false | 適用: 同じ → errors に invalid_speed | 適用: manifest.json の format_version を、対応していない大きな整数に → UNSUPPORTED_FORMAT(自動の migration を試みた場合は、その実際の code と、migration_attempted を記録) |\n| 重複した ID(published_ids) | 適用: systems.runtime.domain_events.published_ids に、既存の ID を1つ追加 → false(DomainEventStream.restore_snapshot、scripts/core/domain_event_stream.gd:113-140 が拒否) | NA: validate は envelope の外形だけで、runtime の内部を検査しない(:16-43)。実際の戻り値(ok:true を予想)は記録するが、不具合とはしない | 適用(公開の API で作れる場合): 重複を入れた snapshot を SaveService.save_snapshot で、固定の user:// の path に保存し、load_from_path で読む。save が拒否した場合は、その実際の code を記録し、load の側は理由つきの NA にする |\n| 重複した ID(facility) | R で適用: 施設の instance の配列で、最初の entry を複製 → false(FacilityService.restore_snapshot、scripts/facility/facility_service.gd:701-703 が拒否)。O で NA: B1 の施設の件数が実際に0のとき、複製する既存の entry が無いため(件数を記録する)。施設を建設すること、R の B1 で代用すること、製品の値を作ることはしない | NA: 上と同じ理由 | R で、published_ids と同じ方法で適用。O で NA(理由は同じ) |\n| world.bin の改ざん | NA: Dictionary の API は package を読まない | NA: 同じ | 適用: r03 の D3 の固定の規則 → CHECKSUM_MISMATCH を期待 |\n\n- 不正な入力は、B1 の deep copy と、固定の user:// の相対 path と、固定の規則だけで作る。乱数・時刻・PID を使わない(r03 の D1〜D3)。\n- 期待の結果は、上の source に基づくものとして記録する。実際の結果が期待と違う場合(たとえば、不正な入力が受理された)は、「既存の不具合の候補」として、全ての記録とともに残す。ただし、envelope の validate が runtime の内部の重複を受理することは、その API の範囲の外なので、不具合とは断定しない。\n\n3.3 各操作で記録し、検査すること\n- 前後の S/K/C 層(同じ PID の中で、完全に比べる)。拒否された場合は、変化が無いこと。\n- 全イベントの差分と、その件数。restore_snapshot と validate は0件。load_from_path の失敗は SAVE_LOAD_FAILED がちょうど1件で、X(B, ev_fail) と、r03 の正規化の後で完全一致すること。\n- 適用と NA の表を、そのまま report に入れる。fresh の whole-unit レビューが、適用の条件を判定できるようにする。\n\n3.4 試験(test_eq.py)\n- 正常の記録。\n- 拒否の場合:\n - restore と validate の架空の code\n - load の code の欠落を合格にすること\n - NA を PASS として数えること\n - O の施設の重複を、件数が0なのに適用したと記録すること\n - 拒否の前後の状態の変化を見逃すこと\n - 件数の不一致\n - envelope の validate が重複を受理したことを、製品の不具合と断定すること\n\n4. 終わり: r01 のとおり(PROGRESS.md を更新し、正式な JSON の status を blocked にし、findings を「段階 S3a 完了(失敗ではない。次は S3b)」とする)。\n" + }, + "EQ_S3B_STAGE_PLAN.txt": { + "sha256": "d14fe474ae4626719d8ff9be6cef1423f076bff0829060ded77b1520ac7bd88d", + "full_unedited": "EQ_S3B_STAGE_PLAN(P28-02-EQ 段階 S3b。EQ_S3_STAGE_PLAN r01/r02 の S3b を、実際の API に合わせて具体化する。SPEC、TASK、6条件、eq/references、eq/registration、補足 r01/r02/r03、段階の計画 r01/r02 は変更しない)\n\n共通\n- 最初に eq/PROGRESS.md と eq/IMPLEMENTATION.md(末尾の S4 の結合の要件を含む)を読み、S1/S2/S3a の型・path・record schema・API・notes を再利用する。再設計しない。\n- E3、既存の91件の試験の本体、失敗の履歴は、消さない。書き直さない(失敗した試験が求める修正を除く)。\n- E4/E5 の操作は、SPEC §3.3 (b) の専用の scenario の区間でだけ行う。各区間には開始と終了の記録を付ける。check_eq.py の静的な許可は、この区間と、下に列挙した操作に限る。\n- 状態は全て r02 の A の typed tree で記録する(深さの制限なし、可逆)。正規化は r03 の閉じた一覧だけを使う。\n- 各操作について、前後の S/K/C 層の tree と、全イベントの差分と件数と、scenario の中で出た signal(測定の区間とは別の記録)を記録する。\n\nE4 キャッシュの古さ(R と O。5つの経路を、この順序で行う。各経路の後の状態を、次の経路の開始の状態として記録する)\n1. 状態を変えるコマンド(通常の command queue を通す)\n - SimulationRuntime.submit_command(&\"build_facility\", {definition_id, origin, rotation})(autoload/simulation_runtime.gd:476、:305、:7717-7720)。\n - 引数は固定の規則で選ぶ。定義の一覧(mvp_content_catalog)を ID の文字の順序で、cell を (x, y, z) の辞書順で走査し、製品の公開の配置の判定で、最初に配置できる組を選ぶ。選んだ規則と結果を記録する。施設の値を作らない。配置できる組が無い場合(たとえば O の小さな世界)は、理由つきの NA にする。\n - 記録の時点: submit の直後(queue の状態、command の ID の counter)と、advance_minutes(1) を1回行った後(APPLY_COMMANDS で実行された後)。両方で、create_snapshot() と latest_snapshot の tree を記録する。\n2. tick: advance_minutes(1) を1回。直後の create_snapshot() と latest_snapshot を記録する。\n3. 直接の restore_snapshot(P)。P は、この経路の開始の時点の create_snapshot() の deep copy。\n - 直後の S が、P を規則どおりに復元したものと、正規化の後で完全一致すること。\n - SAVE_* の event は0件。\n4. load_from_path の成功\n - この経路の開始の時点の snapshot を、SaveService.save_snapshot で、固定の user:// の path(例: user://p28_eq//e4_good)に、固定の metadata で保存する。save は静的な API で、Runtime の event を出さない。\n - その path を、Runtime の load_from_path で読む。\n - 直後の状態が X(P, ev_load) と、正規化の後で完全一致すること。SAVE_LOADED はちょうど1件。\n5. 状態を変えないコマンド(製品が検証の段階で拒否するコマンド)\n - submit_command(&\"build_facility\", {definition_id: \"\"}) を submit して、advance_minutes(1) を1回行う。\n - 戻り値と、command の結果(拒否の code)を記録する。\n - 製品の状態の変化が、command の記帳(次の command の ID、処理済みの結果の記録)と tick の進行の分に限られることを、全ての path の差分で記録する。それ以外の変化があれば、事実として記録する。\n- 各経路の後に、create_snapshot() と latest_snapshot を記録する。latest_snapshot は publish(tick)の時にだけ更新される製品の仕様なので、tick を含まない経路の直後に latest_snapshot が以前の値のままであっても、それは記録する事実であって、cache の古さとは呼ばない。古さの判定は、OPT の後の版との、同じ場面での比較(compare_versions.py)で行う。\n- この段階での検査: 同じ版の2 PID の間で、5つの経路の記録が、正規化の後で一致すること(harness の決定性)。\n\nE5 所有権(R と O。4つの対象 × 入れ子の dict と配列 × 2つの向き)\n- 対象:\n - (1) create_snapshot() の戻り値\n - (2) SimulationRuntime.latest_snapshot\n - (3) snapshot_published の引数\n - (4) state_updated の引数\n - (3) と (4) は、probe の既存の接続で受け取った参照を、handler の外で保持して使う。handler の中で変更しない(他の受け手への影響を避けるため)。\n- 変更の場所(固定。R と O の両方に存在するもの):\n - 入れ子の dict: systems.runtime.id_generator.counters に、key \"__p28_eq_probe\" と値 1 を追加する。\n - 入れ子の配列: systems.runtime.domain_events.published_ids に、文字列 \"__p28_eq_probe\" を追加する。\n- 外から内:\n - 変更の直前に、内部の create_snapshot() の tree と、latest_snapshot の tree と、latest_digest の文字列を記録する。latest_digest は遅延して計算されるので、変更の前に一度読んで確定させ、その事実を記録する。\n - 変更の直後に、同じ3つを取り直して比べる。\n - 変化があれば、変わった path と値を全て記録する。\n- 内から外:\n - 返された値の deep copy を保持する。advance_minutes(1) を1回行った後に、返された値そのものが、保持した deep copy と同じであることを確かめる。\n- 予想される既存の不具合:\n - latest_snapshot と、signal の引数 (3)(4) は同じ object である(:12617-12621)。そのため、(2)〜(4) の外から内の変更は、latest_snapshot を変え、まだ計算していない digest にも影響しうる。\n - これは「既存の不具合」として、対象・向き・変わった path・値・digest への影響を全て記録する。PASS で補わない。harness による無断の変更とは区別する(どの scenario の、どの操作かを結びつける)。\n - その後の検査は、advance_minutes(1) を1回行って新しい latest_snapshot が publish された後の状態を、新しい baseline として始める。\n- (1) が deep copy であれば、影響が無いことを予想する。影響があれば、同じく事実として記録する。\n\ncheck_eq.py と試験\n- E4 と E5 の記録の形式・必須の欄・矛盾の検査を加える:\n - 経路の順序\n - 区間の連続\n - 件数(restore は0、load の成功は1)\n - X(P, ev_load)\n - 4×2×2 の全ての組の存在\n - NA の理由\n- 拒否の試験を加える:\n - 経路の欠落\n - 件数の不一致\n - 既存の aliasing を PASS として扱うこと\n - aliasing の記録の欠落\n - handler の中での変更\n - 区間の外での状態の変更\n - tick を含まない経路の latest_snapshot の据え置きを cache の古さと誤判定すること\n - NA を PASS として数えること\n\n終わり\n- engine を使わない python3 test_eq.py の全件 PASS まで直し、生出力を保存する。PROGRESS.md を更新する。正式な JSON の status を blocked にし、findings を「段階 S3b 完了(失敗ではない。次は S4)」とする。提出しない。\n- engine の起動、git への書込み、製品の変更、全回帰はしない。通常の実装上の判断は、記録して進める。\n" + }, + "EQ_S3B_STAGE_PLAN_R02.txt": { + "sha256": "9a26f47012e51ed23eb03e539fc5c4734e4d41c09ce37a21a18b4ac8a77a5f4c", + "full_unedited": "EQ_S3B_STAGE_PLAN r02(P28-02-EQ 段階 S3b。EQ_S3B_STAGE_PLAN(r01)は、そのまま有効。この r02 は、r01 の E4 の経路 1 の「引数の選び方」(施設の定義の列挙元)だけを置き換える。SPEC、TASK、6条件、eq/references、eq/registration、補足 r01/r02/r03、段階の計画 r01/r02、S3 の計画 r01/r02 は変更しない)\n\n0. 訂正の理由(計画の参照の誤り。製品・仕様の変更ではない)\n- r01 は、施設の定義の一覧を mvp_content_catalog から取るとしていた。しかし scripts/data/mvp_content_catalog.gd:26-31 の DEFAULT_PATHS は人物の4種だけで、施設を含まない。そこから列挙すると一覧が空になり、「配置できる組が無い」という NA が誤って成立してしまう。\n- 施設の定義は、autoload/simulation_runtime.gd:446-447 で、FacilityCatalog の FACILITY_PATHS、INFRASTRUCTURE_FACILITY_PATHS、RESCUE_FACILITY_PATHS、ORIGINAL_FACILITY_PATHS、TRANSPORT_FACILITY_PATHS から runtime.definition_registry に登録される。preview_build_facility(:7660)も、同じ definition_registry.get_facility を使う。\n- run 7da027a85548460bb008b562a79a52ae の worker は、この誤りを指摘し、空の一覧を NA にせず blocked で返した。これは正しい判断であり、失敗ではない。\n\n1. E4 の経路 1 の引数の選び方(r01 の該当の箇条を置き換える)\n- 列挙元: R と O のそれぞれで、その PID の runtime の definition_registry.get_facility_ids()(scripts/core/definition_registry.gd:68-69。Array[StringName])。R と O の両方とも、元の実際の施設の registry から候補を取る。別の catalog、固定の ID の一覧、R の結果での O の代用は使わない。\n- 順序: 取得した ID を、文字列としての ID の順序(String(id) の昇順。Python 側の記録は Unicode の code point の順序)に並べる。registry の登録の順序は、取得した生の一覧として別に記録する。\n- cell の走査: r01 のとおり、(x, y, z) の辞書順。走査の範囲は、その版の世界の公開の寸法から、固定の規則で決め、その規則と範囲を記録する。rotation は 0 に固定する(他の値は試さない)。\n- 判定: 製品の公開の SimulationRuntime.preview_build_facility(definition_id, origin, rotation) だけを使う。ID の順序の外側のループ、cell の順序の内側のループで、最初に配置できると返った組を選ぶ。\n- 実行: 選んだ組で submit_command(&\"build_facility\", {definition_id, origin, rotation})(:476、:305、:7717-7720)を submit する。記録の時点(submit の直後と、advance_minutes(1) の後)は r01 のとおり。\n\n2. 保存する記録(R と O のそれぞれ)\n- get_facility_ids() の生の一覧(登録の順序)と、その件数。\n- 並べた後の一覧と、並べ方の規則。\n- cell の走査の規則と範囲。\n- 試した各候補(definition_id、origin、rotation)と、preview_build_facility の戻り値の全体(typed tree)。試行の件数が多い場合も、全件を記録する(省略しない)。\n- 選んだ候補と、その submit の戻り値と、command の結果。\n- 適用しなかった場合の理由。\n\n3. NA の条件\n- NA にしてよいのは、get_facility_ids() の実際の一覧が空でなく、走査の範囲の全ての組で preview_build_facility が配置できないと返した場合だけ。そのときは、上の 2 の全ての記録とともに、理由つきの NA とする。\n- 一覧が空の場合は NA にせず、registry の取得の誤りとして失敗にし、その事実を記録する。間違った列挙元や空の一覧からの NA(false NA)は禁止する。\n- NA を PASS として数えない。施設の値を作らない。この経路の外で建設しない。\n- check_eq.py に、次の拒否を加える: 列挙元が definition_registry.get_facility_ids() 以外であること、空の一覧での NA、preview の記録が無い候補の選択、試行の記録の欠落、並べ方の規則の違反、R と O で列挙元が違うこと。\n\n4. 変更しないこと\n- E4 の経路 2〜5、E5 の 4×2×2、全ての状態とイベントの typed tree での記録、既存の aliasing の不具合としての記録、S1/S2/S3a の型・path・schema・API・code の再利用、E3 と既存の91件の試験の本体と失敗の履歴(失敗した試験が求める修正を除く)、engine を使わない python3 test_eq.py の全件 PASS と生出力の保存、PROGRESS.md の更新、正式な JSON の status を blocked にし findings を「段階 S3b 完了(失敗ではない。次は S4)」とすること、提出しないこと、engine・git の書込み・製品の変更・全回帰をしないこと。いずれも r01 のとおり。\n- 通常の実装上の判断は、記録して進める。\n" + } + }, + "read_only_clarifications": { + "EQ_S_TIMING_CLARIFICATION.txt": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/.runtime/P28-02-EQ/build/eq-staged-readonly-r04/EQ_S_TIMING_CLARIFICATION.txt", + "sha256": "25d323fd562d29e80782b6f075fc7a0e8b49457a6c4fbd7c30e74b31a6b6a126" + }, + "EQ_S_TIMING_CLARIFICATION_R02.txt": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/.runtime/P28-02-EQ/build/eq-staged-readonly-r04/EQ_S_TIMING_CLARIFICATION_R02.txt", + "sha256": "777accdd652f85db6b9014d85e3c8b3b60ca94b20768e6173b36bc769d360fd9" + }, + "EQ_ENVIRONMENT_FIELDS_CLARIFICATION_R03.txt": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/.runtime/P28-02-EQ/build/eq-staged-readonly-r04/EQ_ENVIRONMENT_FIELDS_CLARIFICATION_R03.txt", + "sha256": "12b27f984ef5843d98327200ad261dccaf64968402192b08ad55b15ed5454ea2" + } + } + } +} diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/S4_SUPPLEMENTARY.json b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/S4_SUPPLEMENTARY.json new file mode 100644 index 0000000..cc437f1 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/S4_SUPPLEMENTARY.json @@ -0,0 +1,549 @@ +{ + "actual_commander_context": { + "actual_run_decision": { + "action": "run", + "task_id": "P28-02-EQ", + "reason": "Supersedes DESKTOP_EQ_S4_RUN_DECISION.json, which was never dispatched and is kept unchanged as history. DESKTOP_EQ_S4_REPAIR_DECISION.json stays valid and usable as written: its facts (the S3b r02 checkpoint, the retained evidence and the S4 continuation) are unchanged by this correction. Use only after Root verifies through the normal gates: repair_ready, repairs 8, no S submitted, no active run, and all 58 current S1 to S3b files still present unchanged in the W. Run repair 8 of P28-02-EQ once on the same W from base 2549cf7d6992560b850bbd11934e3c14b39a1988 with the single worker codex gpt-6-astra, doing the whole final stage S4 as defined in EQ_S4_STAGE_PLAN.txt and corrected by EQ_S4_STAGE_PLAN_R02.txt: run_eq.py, verify_eq.py, bundle normal and rejection unit tests, full local PASS and the formal submission, in this one run, with no reduction to a smaller deliverable. Deliver both S4 plans in full as part of the one supplementary key, together with both S3b plans, both S3 plans, both staged plans, S4_FROZEN_DEPENDENCY_API_NOTES_R01.json and this decision; clarifications r01, r02 and r03 stay read-only in build/eq-staged-readonly-r04. The r02 corrections are as follows. Import the collector read-only inside the frozen SPEC §1 closure only; restart_pair.py belongs to the RESTART task, is not imported, and copy_states is read as reference only. EQ implements its own evidence copy and inventory in eq/ and rejects out-of-closure imports. raw3 is the collector's actual stdout.log, stderr.log and engine-native.log (collect_p28_01.py:217,225). The exit code is read from the owned receipts (for example process.json), never from raw3, and engine-native.log is required. Call check_report(raw, measurement, e3_evidence, b1_record, e45_evidence) with lifecycle.measurement, e3, e3_b1 and e45, and call check_lifecycle(raw, lifecycle, guard). The exact evidence names are checkpoint-00..30, observation-00..30, e3-00..17, e45-00..20, events, report, lifecycle and audio-close, all .json, plus the existing package evidence. The final worker JSON status must be exactly 'submitted' (core.py:1015), not pass or blocked, with commit set to the base. The worker writes no git, and Runner.submit commits normally. Formal validation runs with a read-only checkout (core.py:1064 writable=()) and BUILD_OUTPUT_DIR assigned to the runtime build area (core.py:827), so bundle-synthesis unit tests write only under that BUILD_OUTPUT_DIR or tempfile.gettempdir(), and verify_eq.py only reads. Nothing writes into the source tree, and environment and permissions are unchanged. Everything else in S4 r01 is unchanged: all S4 bindings, raw recomputation in verify, the 7 phases, pins and the 1407-file source map, seal only on success, the S_eq-native-not-Q label, all 119 test bodies and the full failure history, raw outputs with SHAs, and PROGRESS and IMPLEMENTATION updates. No engine, no run_eq.py --run, no trial formal validation, no git write, no product change, no full regression; SPEC, TASK, eq/references and eq/registration stay unchanged. Ordinary implementation choices are recorded without stopping; block only for undecided matters affecting original product spec, values, permissions, billing or original acceptance. After submission: Root native on the exact S in 7 phases, the bundle placed at $BUILD_OUTPUT_DIR/p28-02-eq-evidence, both validations, a fresh independent Opus review of all 6 conditions, then the normal prepare, candidate qualification, approval, integration and final, then the OPT and whole-unit gates. No original credit (23/88, 4/30); the 900-second timeout is unchanged. Quota fallback only on structured provider quota, once, same role, Antigravity claude-opus-5-5-high; any other failure is blocked. Decided by Claude Opus 5.5 in the Desktop control session (message 342); not a CLI commander result." + }, + "actual_Opus_session": "local_a7f85421-3eed-4482-8030-c0dca669573a", + "actual_Opus_model": "claude-opus-5-5", + "stage": "S4 only: run_eq.py, verify_eq.py, synthetic bundle positive/negative units, final local fullPASS and worker JSON status submitted with commit equal to base; Runner commits normally. Read PROGRESS/IMPLEMENTATION and map every S4 binding first. Preserve all119 prior test bodies and every failed raw. No worker engine/git/product/fullregression; exact S native7, both validations, fresh independent Opus all6 and normal final remain pending", + "retained_S1_to_S3b_files": { + "IMPLEMENTATION.md": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/IMPLEMENTATION.md", + "bytes": 30148, + "sha256": "4b023cb03fd86bc2afb4dc1c2d9808e716ea3d1714cdda875c0050bcb8fff93f" + }, + "PROGRESS.md": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/PROGRESS.md", + "bytes": 11587, + "sha256": "de05c86683daceca83f11205049035da25bbe874bac5da35843755e7f1a6e658" + }, + "S2_SUPPLEMENTARY.json": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/S2_SUPPLEMENTARY.json", + "bytes": 19208, + "sha256": "26f23bd8650a2495fd93f4364cbb17cc34f9eb1568758d406bec12ae2dab83a7" + }, + "S3A_SUPPLEMENTARY.json": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/S3A_SUPPLEMENTARY.json", + "bytes": 33965, + "sha256": "9e9d420b01a0030919d2e49245e975a81bf3f561a7fa9fdf7cdc1efb8f02560e" + }, + "S3B_SUPPLEMENTARY.json": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/S3B_SUPPLEMENTARY.json", + "bytes": 46293, + "sha256": "ec89b263b3a94ee3d4c2e6946c1f781138bbab822bbdd77f84f84b250064fc9b" + }, + "SPEC.md": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/SPEC.md", + "bytes": 10693, + "sha256": "3791ccdcb87e8d71fe9205e1e692ebca9e0f974ea3b5fbc4fbb3943882131f1c" + }, + "TASK_INSTRUCTIONS.md": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/TASK_INSTRUCTIONS.md", + "bytes": 2961, + "sha256": "f9937c3c7dff5a25ada453365d26c87fecf009d29518724f0c1e67d2b18afff3" + }, + "UNIT_OUTPUT.sha256": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT.sha256", + "bytes": 82, + "sha256": "a26c3765d7e4d3471c55d741c76170fa82834453ad0d59ff245867e643d42ee7" + }, + "UNIT_OUTPUT.txt": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT.txt", + "bytes": 7291, + "sha256": "8360a2065b303099d5c546b3e4aecc0cc0ab0c2c1e5120b8034b6a1a64317030" + }, + "UNIT_OUTPUT_ATTEMPT_01.sha256": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_ATTEMPT_01.sha256", + "bytes": 93, + "sha256": "eed78af7775a79838e65ea3cb07e9fe09822d2d7a23007f294cbf0a0c98d1c7c" + }, + "UNIT_OUTPUT_ATTEMPT_01.txt": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_ATTEMPT_01.txt", + "bytes": 3368, + "sha256": "307486177b76602cbe68acae24c9560d501b3b866136d8e69802ec24c28e8be8" + }, + "UNIT_OUTPUT_ATTEMPT_02.sha256": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_ATTEMPT_02.sha256", + "bytes": 93, + "sha256": "1de0c0052e66cc60668690bf43e29eb01808afd023525e517ba94beaab0db669" + }, + "UNIT_OUTPUT_ATTEMPT_02.txt": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_ATTEMPT_02.txt", + "bytes": 2699, + "sha256": "07144a7f1941162227f54fefd1961ed0f209e97282432723bbda534079582e4e" + }, + "UNIT_OUTPUT_S1_FINAL.sha256": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S1_FINAL.sha256", + "bytes": 91, + "sha256": "91d9d408ed8d012f38ff892fa6712d129f4849d0ce0b579eaeb7cb1a3f84b704" + }, + "UNIT_OUTPUT_S1_FINAL.txt": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S1_FINAL.txt", + "bytes": 2839, + "sha256": "cdca0cdd551ce76c6100c4dd90e04559551f9d88c054a19a2bc6a77e6572ae15" + }, + "UNIT_OUTPUT_S2_ATTEMPT_01.sha256": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S2_ATTEMPT_01.sha256", + "bytes": 96, + "sha256": "579254585137adf932f5e4a0eaa2b0ecd67d275ece6c7199bdafbee4b48f4f5d" + }, + "UNIT_OUTPUT_S2_ATTEMPT_01.txt": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S2_ATTEMPT_01.txt", + "bytes": 4395, + "sha256": "25953dfc5f8bc3759ae66f6403b162100fb0217c4476f308616b8ab78a2cc67e" + }, + "UNIT_OUTPUT_S2_ATTEMPT_02.sha256": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S2_ATTEMPT_02.sha256", + "bytes": 96, + "sha256": "f4094cc3a8924b79316f473b8b4027a4743036d9d9cf8b2ad0c492ff7b581756" + }, + "UNIT_OUTPUT_S2_ATTEMPT_02.txt": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S2_ATTEMPT_02.txt", + "bytes": 4617, + "sha256": "e26c986dda41b83143723e4c1c5b2ff1051a36b9a947b319341a2239cc3188de" + }, + "UNIT_OUTPUT_S2_ATTEMPT_03.sha256": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S2_ATTEMPT_03.sha256", + "bytes": 96, + "sha256": "d8f8f7a9be6b2fb1618a1ff03f9af5aa0e397373c5e8f9716dc47befa6e3bb83" + }, + "UNIT_OUTPUT_S2_ATTEMPT_03.txt": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S2_ATTEMPT_03.txt", + "bytes": 4693, + "sha256": "9d323abda9bfffa02faf3a9d5cb56aa87e647017c991eb55b4807cf734386698" + }, + "UNIT_OUTPUT_S3A_ATTEMPT_01.sha256": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_01.sha256", + "bytes": 97, + "sha256": "303396536b67929fca0fcb4617578bc546c4f65a674e5dcd2b485bb27c060082" + }, + "UNIT_OUTPUT_S3A_ATTEMPT_01.txt": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_01.txt", + "bytes": 4693, + "sha256": "5cf84b792b5f87cd4183f41cf3a846962a53dc0aa33049c3c55f290356584641" + }, + "UNIT_OUTPUT_S3A_ATTEMPT_02.sha256": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_02.sha256", + "bytes": 97, + "sha256": "76d72513d22720cb0c6fd2bb43ac5000b80144a680a64f635276de8fca47ca97" + }, + "UNIT_OUTPUT_S3A_ATTEMPT_02.txt": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_02.txt", + "bytes": 5457, + "sha256": "000152e51d23db3d4397583b3f4540f5ed0ae469010c993fa1d122fd51537431" + }, + "UNIT_OUTPUT_S3A_ATTEMPT_03.sha256": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_03.sha256", + "bytes": 97, + "sha256": "9625ff44edb36f93ffac168208b148f7f49b247bc4f641d2b35e7c03f4f10ce0" + }, + "UNIT_OUTPUT_S3A_ATTEMPT_03.txt": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_03.txt", + "bytes": 5810, + "sha256": "7c14e8ecf4540e412467408cad267d53358940c86f87a0c8e519b305153f3cb8" + }, + "UNIT_OUTPUT_S3A_ATTEMPT_04.sha256": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_04.sha256", + "bytes": 97, + "sha256": "caab1a3e97878fd0c273e818bc3cf481f0f5f5d3def557da2c5c51981b6dbd0f" + }, + "UNIT_OUTPUT_S3A_ATTEMPT_04.txt": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_04.txt", + "bytes": 5810, + "sha256": "02221ae41e5dd40ecdac0ec0d7ffc657f265d3194c3817583c2b88ad375f132b" + }, + "UNIT_OUTPUT_S3B_ATTEMPT_01.sha256": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_01.sha256", + "bytes": 97, + "sha256": "3af8110cac13104df8e85851491d781d3edff527bb168a626c9c0d3285fcc093" + }, + "UNIT_OUTPUT_S3B_ATTEMPT_01.txt": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_01.txt", + "bytes": 5810, + "sha256": "c89f4f1ca1ea9b985079cd236ffff4193fa5c76d9bfa28fa65ac08cfc93b569c" + }, + "UNIT_OUTPUT_S3B_ATTEMPT_02.sha256": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_02.sha256", + "bytes": 97, + "sha256": "8f5edcdb522ab51606374403d6bcec508029aa32260430ac715a4b5bbb610da2" + }, + "UNIT_OUTPUT_S3B_ATTEMPT_02.txt": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_02.txt", + "bytes": 375, + "sha256": "7bd19a6a3c84385f754261d51779f05b6e39c116459086d5aad3a83afa7225c0" + }, + "UNIT_OUTPUT_S3B_ATTEMPT_03.sha256": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_03.sha256", + "bytes": 97, + "sha256": "a9f4348d6fdbe4bcbed3f19831a88131fb365107411d452a2237f14038e88e6b" + }, + "UNIT_OUTPUT_S3B_ATTEMPT_03.txt": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_03.txt", + "bytes": 30717, + "sha256": "0872061bbc2c1403d2cd04877b8456f3fead35236be008b1a07f02ae5d85b11a" + }, + "UNIT_OUTPUT_S3B_ATTEMPT_04.sha256": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_04.sha256", + "bytes": 97, + "sha256": "950e32a41ebfd325c86eb6810148d726316a1a455203e5c806692dcce82e017a" + }, + "UNIT_OUTPUT_S3B_ATTEMPT_04.txt": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_04.txt", + "bytes": 6983, + "sha256": "63204c3415c9b1719fa6aa596b714077a57f530896f979d12b89a15eb2d827e9" + }, + "UNIT_OUTPUT_S3B_ATTEMPT_05.sha256": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_05.sha256", + "bytes": 97, + "sha256": "4293e250807be76a74c0b743b6ed550f5038d50a34ac5f9e743c68b8c15e5564" + }, + "UNIT_OUTPUT_S3B_ATTEMPT_05.txt": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_05.txt", + "bytes": 6983, + "sha256": "bfcb263bf6d7f284fb2b20ee229d96b7c4a9bd7cd5e7b513df1d3ea32580ed6e" + }, + "UNIT_OUTPUT_S3B_ATTEMPT_06.sha256": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_06.sha256", + "bytes": 97, + "sha256": "e0b6b770ded4ead6f785d64f4f866916b3a8392ba5d330ed5820755e3c6497f0" + }, + "UNIT_OUTPUT_S3B_ATTEMPT_06.txt": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_06.txt", + "bytes": 7223, + "sha256": "7d9bf9c602a93aca06d03eb06025beeea35603d453e293c07e7a6f81ca9ca000" + }, + "UNIT_OUTPUT_S3B_ATTEMPT_07.sha256": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_07.sha256", + "bytes": 97, + "sha256": "d38c2f6c05976e05a553b80917d4bede994425a76cbcaaba274fd36836101a64" + }, + "UNIT_OUTPUT_S3B_ATTEMPT_07.txt": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_07.txt", + "bytes": 963, + "sha256": "f7c7c045ea98a366810b7c309fc1a87a77ccc5d8e823750eebaa742c9529e2ca" + }, + "UNIT_OUTPUT_S3B_ATTEMPT_08.sha256": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_08.sha256", + "bytes": 97, + "sha256": "7b252056637268e05f3eaa28a6f75f64c9345e4e95031bdba93c33048e8807a6" + }, + "UNIT_OUTPUT_S3B_ATTEMPT_08.txt": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_08.txt", + "bytes": 7879, + "sha256": "19c3f115d6a73bf91413877878f5d5f9d78a3e253dae3ddba7dfec9b5d46eaba" + }, + "UNIT_OUTPUT_S3B_ATTEMPT_09.sha256": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_09.sha256", + "bytes": 97, + "sha256": "f603c6d559184e68909e2409114659a263af5d18a684be332cebffaf816b6bd0" + }, + "UNIT_OUTPUT_S3B_ATTEMPT_09.txt": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_09.txt", + "bytes": 7291, + "sha256": "8360a2065b303099d5c546b3e4aecc0cc0ab0c2c1e5120b8034b6a1a64317030" + }, + "check_eq.py": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/check_eq.py", + "bytes": 57523, + "sha256": "e22602c5961d53ce98247fb014bbd91549b5cc0cf34a370102d3acf575a8d498" + }, + "compare_versions.py": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py", + "bytes": 34690, + "sha256": "1324e9e689a2885bd85f58a54f974d8a198e09fd3542123c6f597442e1437263" + }, + "eq_probe.gd": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/eq_probe.gd", + "bytes": 41542, + "sha256": "f933cad2a7ad4905fec15228ceb75ecb0ed100c64200a41feb80ba9702cf88fb" + }, + "references/OPT_CONTRACT_T1.md": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/references/OPT_CONTRACT_T1.md", + "bytes": 13952, + "sha256": "ad9f3d76f3500b39263fb898d7c64588b4b47c9e11b456f938195261fd054d16" + }, + "references/OPUS_D2_SCOPE_CLARIFICATION.txt": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/references/OPUS_D2_SCOPE_CLARIFICATION.txt", + "bytes": 5598, + "sha256": "5775e7b512d9e90dbcfbcb181f5b64dc0fa8207e0947c0a4a6a5c9195565f9bd" + }, + "references/OPUS_STARTUP_LIFECYCLE_CLARIFICATION.txt": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/references/OPUS_STARTUP_LIFECYCLE_CLARIFICATION.txt", + "bytes": 5996, + "sha256": "967aebf27ff412f7a16ce771ef7d68abf8cfde0bb76ed19cf6dbf2817ca7acc6" + }, + "registration/ACCEPTANCE_BASELINE.json": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/registration/ACCEPTANCE_BASELINE.json", + "bytes": 2981, + "sha256": "84628bc21205387f8a7143031bdc50c9f68a767d350e6c34b32e0ba1c7059337" + }, + "registration/CONFIG_PROPOSAL.json": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/registration/CONFIG_PROPOSAL.json", + "bytes": 821, + "sha256": "775fbbb97cda8b4d4991defdf7871b0fc79f489f4dea34c1733d4830426cf1df" + }, + "registration/REGISTRATION_PROPOSAL.json": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/registration/REGISTRATION_PROPOSAL.json", + "bytes": 4733, + "sha256": "9590fc853a4df8d50cc0d269d23bd9c844dc6931590ff6f24ebf95bb54a8d135" + }, + "registration/ROOT_PROPOSAL_BYTE_TRANSFER.json": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/registration/ROOT_PROPOSAL_BYTE_TRANSFER.json", + "bytes": 4778, + "sha256": "63197f650849084f769e487a76458361886a37090042f1e351851c75b0384da2" + }, + "test_eq.py": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", + "bytes": 67839, + "sha256": "7f65b1dec6f68800cba4415b9afa3c11f0a0e58fd970f5582268cfd2123f9c19" + } + }, + "actual_full_plans": { + "EQ_STAGED_IMPLEMENTATION_PLAN.txt": { + "sha256": "eb7b4831e2164c6fc983fa6f9825e7f3e2993b4c0ebf2f90aac8ad10662666d2", + "full_unedited": "EQ_STAGED_IMPLEMENTATION_PLAN(P28-02-EQ repair 3 以降。base 2549cf7d6992560b850bbd11934e3c14b39a1988。SPEC、TASK、6条件、eq/references、eq/registration、EQ_S_TIMING_CLARIFICATION r01/r02、EQ_ENVIRONMENT_FIELDS_CLARIFICATION r03 は全てそのまま有効。変えるのは、工程と、成果物の内部の設計の固定だけ)\n\n前回までの事実\n- repair 2(run 84ca0ff8…)は、IMPLEMENTATION.md と compare_versions.py などを作った後、item_30 で全てを削除し、「6ファイルと unit の PASS を提供できない」として、自分から終了した。仕様の不足の指摘ではない。packet は 94 KB あった。\n- この失敗は失敗のまま保持する。削除したことを成功として扱わない。\n\n工程の変更(必須)\n- G1: **作ったファイルは、削除しない**。完成していなくても、W の eq/ に残す。各 run の最後に、eq/PROGRESS.md に、終わった段階・残りの作業・現在の試験の結果を書く。\n- G2: 1回の run では、下の**1つの段階だけ**を行う。始める前に eq/PROGRESS.md を読み、次の段階から再開する。前の段階のコードは作り直さない。\n- G3: 各段階の終わりに、engine を使わない python3 test_eq.py を実行する。その時点で存在する試験が、全件 PASS になるまで直す。生出力を eq/UNIT_OUTPUT.txt に保存する。\n- G4: 段階1〜3の終わりには、正式な JSON の status を blocked にし、findings に「段階 Sx 完了(失敗ではない。次は Sx+1)」と PROGRESS.md の要点を書いて返す。段階4の終わりにだけ、提出する(status を submitted 相当の正式な提出にする)。\n- G5: 通常の実装上の判断(関数の分け方、名前、試験データ、記録の書式)は、IMPLEMENTATION.md に記録して進める。blocked にしてよいのは、原本の仕様・値・権限・課金・受入に影響する未確定事項がある場合だけ。\n- G6: engine の起動、git への書込み、製品の変更、全回帰はしない。SPEC、TASK、eq/references、eq/registration は変更しない。\n\n固定するインターフェース(6ファイル。SPEC §2)\n\n1. compare_versions.py(Python のみ。engine を使わない)\n - normalize_events(events, profile_root) -> (normalized, sidecar):\n - r03 の F1〜F3 を、JSON の event の一覧に適用する。\n - 閉じた一覧の外の *_us / *_ms / profile_root を含む文字列は、正規化せず、violations として返す。\n - restore_events(normalized, sidecar, profile_root) -> events: 逆の復元(完全一致の確認に使う)。\n - compare_reports(a, b) -> dict: 2つの report(同じ版の別 PID、または前後の版)を比べる。\n - 毎分の checkpoint の S_norm_sha と latest_norm_sha の一致\n - digest の規則(r02 の T3)\n - K と C の、SPEC §3.2 に列挙した欄\n - E2 の正規化した全イベント(開始の counter の一致が前提)\n - E3/E4/E5 の scenario の結果の一致\n - 比べない欄は、理由と両側の値を記録する\n - 差は path ごとに返す\n - check_source_closure(before_map, after_map, allowed_changed) -> dict: SPEC §2 と OPT r02 §2。追加・欠落・登録されていない差分を拒否する。\n2. eq_probe.gd(GDScript):\n - 起動の6段階は、DIAG の diag_probe.gd の構成をそのまま参考にする。\n - 役割は R と O(env の THE_TREE_EQ_ROLE)。\n - 観測の checkpoint は B1 と、30分の各 tick の最後(31個)。各 checkpoint に、次のものを置く:\n - minute\n - S_raw_sha、S_norm_sha(GDScript の中で F1〜F3 の typed の marker を使って正規化した後の var_to_bytes の SHA)\n - 正規化した S の path の hash の表(depth ≤ 4)\n - latest_norm_sha\n - digest の情報\n - K と C の全体\n - sidecar\n - E2 は subscribe('*') で、全イベントの JSON(正規化の前)を記録する。正規化は compare_versions.py で行う(GDScript と Python で、同じ規則の二重実装をしない)。\n - E3/E4/E5 の scenario は、SPEC §3.3 の専用の区間で行う。各区間について、開始と終了、操作、code、前後の S/K/C、件数(r02 の T4)を記録する。\n - stdout には、P28_02_EQ_REPORT= をちょうど1行出す。終了は close_requested.emit()。\n3. check_eq.py: report 1つを検査する。\n - 形式、必須の欄、矛盾\n - 閉じた一覧の外の差\n - probe の静的な禁止(autoload の class_name の参照、状態を変える呼出しの区間の外での使用、Variant からの := の推論)\n - SimulationDigest だけでの判定\n4. run_eq.py: Root が実行する driver。\n - diag_p28_02.py の構成をそのまま参考にする(--check / --run、依存の SHA、1407 の source、凍結した S の照合、owned phase、guard、private profile、cleanup)。\n - phase は import、parse-base、parse-wrapper、R-A、R-B、O-A、O-B。\n - 成功したら、execution.json と bundle.json を作る。\n5. verify_eq.py: --project-root . で、$BUILD_OUTPUT_DIR/p28-02-eq-evidence の bundle を結合する。bundle が無ければ失敗する。\n - 各 report に check_eq を行う。\n - R-A と R-B、O-A と O-B に compare_reports を行い、差が0であること(harness の正しさ)。\n - E3/E5 の、前の版での製品の失敗は、「既存の不具合」の一覧として出力する。harness の不合格とは区別する。\n - SPEC、TASK、eq/references、eq/registration の SHA を固定して照合する。\n6. test_eq.py: 合成した入力だけで動く。各段階で、その段階の試験を足していく。\n\n段階(1回の run で1つ)\n- S1: compare_versions.py の全体と、その試験(F1〜F3 の正常と拒否、可逆性、比較、source の閉包)。PROGRESS.md と IMPLEMENTATION.md を作る。\n- S2: eq_probe.gd の、起動・観測の checkpoint・E2 の記録・報告。check_eq.py の静的な検査と形式の検査、それぞれの試験。\n- S3: eq_probe.gd の E3/E4/E5 の scenario、check_eq.py のそれに対する検査、試験。\n- S4: run_eq.py と verify_eq.py、bundle の試験。全件 PASS を確かめて、正式に提出する。\n\nRoot への依頼(packet を小さくするため)\n- actual_commander_context の key には、この計画の全文と RUN の判断だけを入れる。r01・r02・r03 の全文は、build/ に読取専用で置き、その path と SHA だけを渡す。eq/references は W の中にあるので、path だけで足りる。\n" + }, + "EQ_STAGED_IMPLEMENTATION_PLAN_R02.txt": { + "sha256": "128f42f18e168e9299995296ac7ad119f47d1647799d472663282e47e8ac9fdd", + "full_unedited": "EQ_STAGED_IMPLEMENTATION_PLAN r02(P28-02-EQ repair 3 以降。EQ_STAGED_IMPLEMENTATION_PLAN(r01)の工程 G1〜G6、段階 S1〜S4、Root への依頼は、そのまま有効。この r02 は、固定インターフェースのうち、状態とイベントの運搬の表現と、normalize_events の返り値を置き換えて確定する。SPEC、TASK、6条件、eq/references、eq/registration、補足 r01/r02/r03 は変更しない)\n\nA. 型を保つ運搬の表現(typed tree。JSON は運び方であって、型の情報は落とさない)\n\nA1 node の形式(JSON の配列)\n- 各値は [type_code, payload]。type_code は Godot の typeof() の値。\n - null: [0]\n - bool: [1, 0|1]\n - int: [2, 整数]\n - float: [3, \"<8 byte little-endian IEEE754 の hex>\"](10進の文字列にしない)\n - String: [4, \"文字列\"]\n - StringName: [21, \"文字列\"]\n - Vector2/Vector2i/Vector3/Vector3i/Rect2/Rect2i/Color など: [type_code, [各成分の node]](成分は int か float の node)\n - Dictionary: [27, [[key_node, value_node], …], typed_info]。**元の挿入の順序のまま**並べる。typed_info は、型つきの Dictionary なら key と value の builtin 型・class 名・script、それ以外は null。\n - Array: [28, [element_node, …], typed_info]。typed_info は get_typed_builtin()・get_typed_class_name()・get_typed_script() の値、型の無い Array なら null。\n - PackedByteArray: [29, \"\"]。他の Packed*Array も、要素ごとの node の列にする(float は hex)。\n- Object、Callable、Signal、RID が現れたら、運搬せずに失敗にする(snapshot と event の dict には、本来現れないもの)。\n\nA2 無損失の証明(Godot の中で行う。probe の必須の処理)\n- tree = encode(value) を作った後、decode(tree) で Variant を作り直す。var_to_bytes(decode(tree)) == var_to_bytes(value) であることを確かめる。一致しなければ失敗にする。\n- report には、checkpoint ごとに、次の3つを記録する。\n - raw_bytes_sha = sha256(var_to_bytes(value))\n - tree_sha = sha256(tree を key の順序を変えずに JSON.stringify した UTF-8)\n - roundtrip_ok\n- Python は、受け取った tree から tree_sha を計算し直して結合する。これで、Python で比べる tree が、Godot の元の bytes と無損失に対応することが保証される。\n\nA3 保存の場所と大きさ(深さの制限は設けない。全体を再構成できるようにする)\n- 各 PID は、checkpoint の列(B1 と、30分の各 tick の最後)について、S 層と latest_snapshot を、次の形で、private user:// の evidence/ に書き出す。driver は、それを RESTART の copy_states と同じ方式で out へ複製し、SHA を結合する。\n - checkpoint 0(B1): tree の全体(JSON、zstd で圧縮してよい。圧縮した場合は、圧縮の前後の SHA を両方記録する)。\n - checkpoint k(k≥1): checkpoint k−1 の tree に対する、path を指定した差分の操作の列。操作は set(path, node)、dict_insert(path, index, key_node, value_node)、dict_remove(path, key_node)、array_splice(path, start, delete_count, [node…])。順序つきで、再構成すると、checkpoint k の tree と完全一致すること。\n - latest_snapshot は、各 checkpoint で、var_to_bytes が S 層と同じなら same_as_S=true とし、違えば、その tree(または S に対する差分)を保存する。\n- Python は、checkpoint 0 から差分を順に適用して、全ての checkpoint を再構成する。checkpoint ごとに tree_sha と一致することを確かめる。\n\nA4 比較(compare_versions.py。全て tree の上で行い、深さの制限は無い)\n- 第一の比較は、tree の完全一致(型、key、順序、値。全ての node)。\n- 一致しない場合に限り、正規化した比較を行う。dict の key を文字で並べ(同じ文字の key が2つあれば拒否)、それ以外の型・値・配列の順序を保ったまま比べる。それで一致すれば「dict の列挙の順序だけの差」として、その全ての path を記録する。それ以外の差は、全ての path と両側の node を記録して、不一致にする。\n- F1〜F3(r03)の正規化は、tree の node の上で行う。sidecar から、元の tree へ完全に戻せること(tree_sha が一致すること)を確かめる。\n\nB. E2 のイベントの運搬\n- 各 event について、event.to_dictionary()(製品の直列化。scripts/core/domain_event.gd:47-59)の tree を記録する。あわせて、元の object の欄の型(event_id と event_type が StringName であるか、entity_ids の型、payload の dict の typed_info)を、original_field_types として記録する。\n- 受け取りの順序で番号をつけ、開始の時点の counter と、published_ids の数を記録する。\n- イベントの列は、A3 と同じく evidence/ に書き出し(tree の列。圧縮してよい)、SHA を結合する。Godot の中で、各 event について A2 の roundtrip を確かめる。\n- compare_reports は、この tree の列を受け取り、全ての欄と event_id を**そのまま**比べる(ID の付け替えはしない)。F1〜F3 は、payload の該当する node にだけ適用する。\n\nC. normalize_events とその仲間の返り値(固定)\n- normalize_events(events, profile_root) -> (normalized, sidecar)。返り値は2つの要素のまま。\n - normalized: tree の列。閉じた一覧(r03)の node だけを marker に置き換えたもの。\n - sidecar: dict で、key は次の3つに固定。\n - \"entries\": [{\"event_index\", \"path\", \"key\", \"original_node\"}…]。F1〜F3 で置き換えた全ての node の元の値。F3 の場合は original_node に元の message の文字列を入れ、\"root\" に、置き換えた root を入れる。\n - \"violations\": [{\"event_index\", \"path\", \"kind\", \"node\"}…]。閉じた一覧の外にあった、*_us / *_ms の key、profile_root を含む文字列など。**存在しただけでは不合格にしない**。正規化はせずに、そのまま保持して記録する。\n - \"profile_root\": 使った root の文字列と、guard の actual_user_data_dir との一致の結果。\n- restore_events(normalized, sidecar, profile_root) -> events: entries から元に戻す。violations の node は、もともと変えていないので、そのまま。\n- 状態の tree にも、同じ形の normalize_tree(tree, profile_root) -> (normalized, sidecar) と restore_tree を用意する。\n- r03 の規則は、そのまま。violations にあるものを正規化しようとしたら拒否する。violations にあるものが、比べる2つの側で実際に異なれば、その差は不一致(失敗)として、path と両側の値を記録する。\n\nD. 段階への影響\n- S1(今回): compare_versions.py に、A4 の比較、C の4つの関数、A3 の差分の再構成、tree_sha の再計算、check_source_closure を実装する。試験は合成の tree で行い、次のものを確かめる。\n - 型の違い(int と float、String と StringName、型つきの配列)を区別すること\n - dict の順序だけの差の path\n - 差分の再構成の完全一致\n - sidecar からの逆の復元\n - violations の扱い(存在だけでは不合格にしない、正規化しようとしたら拒否、差があれば不一致)\n- S2: eq_probe.gd に、A1 の encode と decode、A2 の roundtrip、A3 の書き出し、B の記録を実装する。\n- S3 と S4 は、r01 のとおり。\n" + }, + "EQ_S3_STAGE_PLAN.txt": { + "sha256": "ecbfb00691017fbd35027df8fa9ca6f82c761a5a3389568fe44b1babcfca308a", + "full_unedited": "EQ_S3_STAGE_PLAN(P28-02-EQ。EQ_STAGED_IMPLEMENTATION_PLAN r01/r02 の段階 S3 を、S3a と S3b に分ける。理由: S2 は 846.159 秒で、Runner の900秒の上限に近かったため。要求の範囲は変えない。SPEC、TASK、6条件、eq/references、eq/registration、補足 r01/r02/r03 は変更しない)\n\n共通\n- 最初に eq/PROGRESS.md と eq/IMPLEMENTATION.md を読み、S1/S2 の型・path・record schema・API・notes を再利用する。再設計しない。\n- S1/S2 のコードと試験の本体を消さない。書き直さない(S3 で直すと決めた checker の2点と、失敗した試験が求める修正を除く)。\n- 失敗の履歴は、PROGRESS.md と UNIT_OUTPUT に残す。各段階の終わりに、engine を使わない python3 test_eq.py の全件 PASS まで直し、生出力を保存する。\n- 状態を変える呼出しは、SPEC §3.3 (b) の、列挙した scenario の専用の区間の中でだけ許可する。check_eq.py の静的な許可も、その区間と列挙した操作に限る。\n- engine の起動、git への書込み、製品の変更、全回帰はしない。SPEC、TASK、eq/references、eq/registration は変更しない。\n\nS3a(次の run)\n1. checker の修正 1(eq/check_eq.py:109)\n - 各 checkpoint の immutable snapshot の phase の key の集合が、正確に {0,…,10} であることを要求する(空の dict や、一部の欠落を拒否する)。\n - 負の試験を加える: 空、1つの欠落、範囲外の key、重複した key の表現。\n2. checker の修正 2(eq/check_eq.py:147-150)\n - 測定の区間の30 tick の各分について、製品の _publish_snapshot(autoload/simulation_runtime.gd:12616-12621)が出す snapshot_published → state_updated を、実際の回数と順序で記録したものを、その分の checkpoint と結びつけて検査する。\n - 各分に、ちょうど1組であること(snapshot_published に接続した受け手が無い場合は、製品の条件 :12619 のとおり state_updated だけになるので、probe の側で接続を記録し、期待値をその実際の接続の状態から決める)。\n - 順序は snapshot_published が先。\n - 分の番号は、checkpoint の minute と一致すること。\n - scenario の区間で出た追加の signal は、別の区間の記録に入れる。測定の区間の記録には混ぜない。\n - 負の試験を加える: 欠落、一部の分だけ、重複、順序の改ざん、分のずれ、scenario の signal の混入。\n3. E3 失敗時の拒否(専用の scenario の区間。R と O の両方)\n - restore_snapshot、SimulationSnapshot.validate、load_from_path の3つの API に、次の不正な入力を、それぞれ1件以上与える:\n - 欠けた key\n - 違う型\n - 範囲外の値\n - 重複した ID(published_ids、facility の ID)\n - world.bin の改ざん(r03 の D3 の固定の規則)\n - 不正な入力は、B1 の snapshot の deep copy から、固定の規則で作る。乱数や時刻を使わない。\n - 記録すること:\n - 戻り値と code\n - 前後の S/K/C 層(同じ PID の中で完全に比べる)\n - 全イベントの差分と、その件数(r02 の T4: 直接の restore は0件、load の失敗は SAVE_LOAD_FAILED がちょうど1件で、X(B, ev_fail) と r03 の正規化の後で完全一致すること)\n - check_eq.py: E3 の記録の形式と矛盾の検査を加える。製品の失敗(不正な入力が受理された、状態が変わった、など)は、「既存の不具合」として記録する。PASS で補わない。\n - 試験を加える: E3 の正常の記録と、拒否の場合(code の欠落、件数の不一致、拒否の前後の状態の変化を見逃すこと)。\n4. 終わり: PROGRESS.md を更新し、正式な JSON の status を blocked にし、findings を「段階 S3a 完了(失敗ではない。次は S3b)」とする。\n\nS3b(S3a の後の run)\n1. E4 キャッシュの古さ(専用の区間。R と O)\n - 場面: 状態を変えるコマンド(建設のコマンドを1件、通常の command queue を通す)、tick(advance_minutes(1))、restore_snapshot、load_from_path、状態を変えないコマンド。\n - 各場面の直後の create_snapshot() と latest_snapshot を、完全な typed tree(r02 の A)で記録する。版の間の比較は compare_versions.py で行う。\n - 件数: 直接の restore は SAVE_* が0件、load の成功は SAVE_LOADED がちょうど1件(X(P, ev_load))。\n2. E5 所有権(専用の区間)\n - 対象: create_snapshot() の戻り値、latest_snapshot、snapshot_published と state_updated の引数。\n - 外から内: 入れ子の dict と配列を変更した後に、内部の状態、次の create_snapshot()、latest_digest が変わっていないかを、完全な typed tree で確かめる。\n - 内から外: 次の tick の後に、既に返した値が変わっていないかを確かめる。\n - 予想される aliasing(latest_snapshot と signal の引数が同じ object であること)による live の変化は、「既存の不具合」として、変わった path と値を全て記録する。その後の検査は、新しい baseline から始める。harness による無断の変更とは区別する。\n3. check_eq.py と試験: E4/E5 の記録の検査と、正常と拒否の試験を加える。\n4. 終わり: PROGRESS.md を更新し、正式な JSON の status を blocked にし、findings を「段階 S3b 完了(失敗ではない。次は S4)」とする。\n\nその後\n- S4: run_eq.py と verify_eq.py、bundle の試験、全件 PASS の後に正式に提出する。\n- その後に、Root の native(7 phase)→ 両方の validation → 別の新しい Opus による全6条件のレビュー → 通常の統合と final、の順序で進める。\n" + }, + "EQ_S3_STAGE_PLAN_R02.txt": { + "sha256": "566e3ad98f9d47136ff4d4932f81c0a7f9fc96321a6f08ba944a9f1e736e6caa", + "full_unedited": "EQ_S3_STAGE_PLAN r02(P28-02-EQ。EQ_S3_STAGE_PLAN(r01)の分け方(S3a = checker の2点の修正 + E3、S3b = E4/E5)、共通の規則、S3b、その後の順序は、そのまま有効。この r02 は、実際の API に合わせて、S3a の「checker の修正 2」と「E3」を置き換えて確定する。SPEC、TASK、6条件、eq/references、eq/registration、補足 r01/r02/r03、段階の計画 r01/r02 は変更しない)\n\n1. checker の修正 1(eq/check_eq.py:109): r01 のとおり(phase の key の集合が正確に {0..10}、負の試験)。\n\n2. checker の修正 2(eq/check_eq.py:147-150。r01 を置き換える)\n- probe は、自分の observer を snapshot_published に接続している。そのため、製品の _publish_snapshot(autoload/simulation_runtime.gd:12616-12621)は、毎 tick、snapshot_published を出してから state_updated を出す(:12619 の条件が真になる)。\n- 測定の区間の30 tick の各分について、**ちょうど1組の snapshot_published → state_updated** を要求し、その分の checkpoint の minute と結びつける。\n- 測定の開始の時点で、snapshot_published と state_updated の接続の一覧(get_connections() の、接続先の object と method)を記録し、その中に probe 自身の接続があることを要求する。probe の接続が無い場合は、期待を「state_updated だけ」に下げることはせず、失敗にする。\n- 製品で受け手が接続されていない場合の動作(state_updated だけ)は、この区間の対象の外とする。試験もしない。\n- scenario の区間で出た signal は、別の区間の記録に入れ、測定の区間には混ぜない。\n- 負の試験を加える:\n - 欠落、一部の分だけ、重複、順序の改ざん、分のずれ\n - scenario の signal の混入\n - probe の接続が一覧に無いのに合格にすること\n - 期待を state_updated だけに下げること\n\n3. E3 失敗時の拒否(専用の scenario の区間。r01 を置き換える)\n\n3.1 各 API の実際の戻り値(架空の code は作らない)\n- SimulationRuntime.restore_snapshot(Dictionary) -> bool(:587): 戻り値の bool を、そのまま記録する。code は null とし、理由を \"API returns bool only\" とする。\n- SimulationSnapshot.validate(Dictionary) -> {ok, errors}(scripts/core/simulation_snapshot.gd:16-43): 返った dict の全体(ok と、errors の全件)を、そのまま記録する。code は null とし、理由を \"API returns ok/errors only\" とする。\n- load_from_path(String) -> Dictionary(:4223): 実際の code を記録する。この API で code が欠けていれば、それは失敗として拒否する(上の2つの「API に code が無い」とは区別する)。\n\n3.2 不正の分類と、それを適用する API(source に基づく表。適用しないものは、理由つきの NA として記録し、PASS に補わない)\n\n| 分類 | restore_snapshot(Dictionary) | validate(Dictionary。envelope の外形だけを検査) | load_from_path(package) |\n|---|---|---|---|\n| 欠けた key | 適用: B1 の deep copy から clock を削除 → false を期待 | 適用: clock を削除 → errors に missing_clock を期待 | 適用: package の manifest.json から checksum_world を削除 → INVALID_MANIFEST を期待 |\n| 違う型 | 適用: clock.absolute_minute を文字列 \"x\" に → false | 適用: 同じ → errors に invalid_absolute_minute | 適用: manifest.json の format_version を文字列に → INVALID_MANIFEST |\n| 範囲外の値 | 適用: clock.speed を 9 に → false | 適用: 同じ → errors に invalid_speed | 適用: manifest.json の format_version を、対応していない大きな整数に → UNSUPPORTED_FORMAT(自動の migration を試みた場合は、その実際の code と、migration_attempted を記録) |\n| 重複した ID(published_ids) | 適用: systems.runtime.domain_events.published_ids に、既存の ID を1つ追加 → false(DomainEventStream.restore_snapshot、scripts/core/domain_event_stream.gd:113-140 が拒否) | NA: validate は envelope の外形だけで、runtime の内部を検査しない(:16-43)。実際の戻り値(ok:true を予想)は記録するが、不具合とはしない | 適用(公開の API で作れる場合): 重複を入れた snapshot を SaveService.save_snapshot で、固定の user:// の path に保存し、load_from_path で読む。save が拒否した場合は、その実際の code を記録し、load の側は理由つきの NA にする |\n| 重複した ID(facility) | R で適用: 施設の instance の配列で、最初の entry を複製 → false(FacilityService.restore_snapshot、scripts/facility/facility_service.gd:701-703 が拒否)。O で NA: B1 の施設の件数が実際に0のとき、複製する既存の entry が無いため(件数を記録する)。施設を建設すること、R の B1 で代用すること、製品の値を作ることはしない | NA: 上と同じ理由 | R で、published_ids と同じ方法で適用。O で NA(理由は同じ) |\n| world.bin の改ざん | NA: Dictionary の API は package を読まない | NA: 同じ | 適用: r03 の D3 の固定の規則 → CHECKSUM_MISMATCH を期待 |\n\n- 不正な入力は、B1 の deep copy と、固定の user:// の相対 path と、固定の規則だけで作る。乱数・時刻・PID を使わない(r03 の D1〜D3)。\n- 期待の結果は、上の source に基づくものとして記録する。実際の結果が期待と違う場合(たとえば、不正な入力が受理された)は、「既存の不具合の候補」として、全ての記録とともに残す。ただし、envelope の validate が runtime の内部の重複を受理することは、その API の範囲の外なので、不具合とは断定しない。\n\n3.3 各操作で記録し、検査すること\n- 前後の S/K/C 層(同じ PID の中で、完全に比べる)。拒否された場合は、変化が無いこと。\n- 全イベントの差分と、その件数。restore_snapshot と validate は0件。load_from_path の失敗は SAVE_LOAD_FAILED がちょうど1件で、X(B, ev_fail) と、r03 の正規化の後で完全一致すること。\n- 適用と NA の表を、そのまま report に入れる。fresh の whole-unit レビューが、適用の条件を判定できるようにする。\n\n3.4 試験(test_eq.py)\n- 正常の記録。\n- 拒否の場合:\n - restore と validate の架空の code\n - load の code の欠落を合格にすること\n - NA を PASS として数えること\n - O の施設の重複を、件数が0なのに適用したと記録すること\n - 拒否の前後の状態の変化を見逃すこと\n - 件数の不一致\n - envelope の validate が重複を受理したことを、製品の不具合と断定すること\n\n4. 終わり: r01 のとおり(PROGRESS.md を更新し、正式な JSON の status を blocked にし、findings を「段階 S3a 完了(失敗ではない。次は S3b)」とする)。\n" + }, + "EQ_S3B_STAGE_PLAN.txt": { + "sha256": "d14fe474ae4626719d8ff9be6cef1423f076bff0829060ded77b1520ac7bd88d", + "full_unedited": "EQ_S3B_STAGE_PLAN(P28-02-EQ 段階 S3b。EQ_S3_STAGE_PLAN r01/r02 の S3b を、実際の API に合わせて具体化する。SPEC、TASK、6条件、eq/references、eq/registration、補足 r01/r02/r03、段階の計画 r01/r02 は変更しない)\n\n共通\n- 最初に eq/PROGRESS.md と eq/IMPLEMENTATION.md(末尾の S4 の結合の要件を含む)を読み、S1/S2/S3a の型・path・record schema・API・notes を再利用する。再設計しない。\n- E3、既存の91件の試験の本体、失敗の履歴は、消さない。書き直さない(失敗した試験が求める修正を除く)。\n- E4/E5 の操作は、SPEC §3.3 (b) の専用の scenario の区間でだけ行う。各区間には開始と終了の記録を付ける。check_eq.py の静的な許可は、この区間と、下に列挙した操作に限る。\n- 状態は全て r02 の A の typed tree で記録する(深さの制限なし、可逆)。正規化は r03 の閉じた一覧だけを使う。\n- 各操作について、前後の S/K/C 層の tree と、全イベントの差分と件数と、scenario の中で出た signal(測定の区間とは別の記録)を記録する。\n\nE4 キャッシュの古さ(R と O。5つの経路を、この順序で行う。各経路の後の状態を、次の経路の開始の状態として記録する)\n1. 状態を変えるコマンド(通常の command queue を通す)\n - SimulationRuntime.submit_command(&\"build_facility\", {definition_id, origin, rotation})(autoload/simulation_runtime.gd:476、:305、:7717-7720)。\n - 引数は固定の規則で選ぶ。定義の一覧(mvp_content_catalog)を ID の文字の順序で、cell を (x, y, z) の辞書順で走査し、製品の公開の配置の判定で、最初に配置できる組を選ぶ。選んだ規則と結果を記録する。施設の値を作らない。配置できる組が無い場合(たとえば O の小さな世界)は、理由つきの NA にする。\n - 記録の時点: submit の直後(queue の状態、command の ID の counter)と、advance_minutes(1) を1回行った後(APPLY_COMMANDS で実行された後)。両方で、create_snapshot() と latest_snapshot の tree を記録する。\n2. tick: advance_minutes(1) を1回。直後の create_snapshot() と latest_snapshot を記録する。\n3. 直接の restore_snapshot(P)。P は、この経路の開始の時点の create_snapshot() の deep copy。\n - 直後の S が、P を規則どおりに復元したものと、正規化の後で完全一致すること。\n - SAVE_* の event は0件。\n4. load_from_path の成功\n - この経路の開始の時点の snapshot を、SaveService.save_snapshot で、固定の user:// の path(例: user://p28_eq//e4_good)に、固定の metadata で保存する。save は静的な API で、Runtime の event を出さない。\n - その path を、Runtime の load_from_path で読む。\n - 直後の状態が X(P, ev_load) と、正規化の後で完全一致すること。SAVE_LOADED はちょうど1件。\n5. 状態を変えないコマンド(製品が検証の段階で拒否するコマンド)\n - submit_command(&\"build_facility\", {definition_id: \"\"}) を submit して、advance_minutes(1) を1回行う。\n - 戻り値と、command の結果(拒否の code)を記録する。\n - 製品の状態の変化が、command の記帳(次の command の ID、処理済みの結果の記録)と tick の進行の分に限られることを、全ての path の差分で記録する。それ以外の変化があれば、事実として記録する。\n- 各経路の後に、create_snapshot() と latest_snapshot を記録する。latest_snapshot は publish(tick)の時にだけ更新される製品の仕様なので、tick を含まない経路の直後に latest_snapshot が以前の値のままであっても、それは記録する事実であって、cache の古さとは呼ばない。古さの判定は、OPT の後の版との、同じ場面での比較(compare_versions.py)で行う。\n- この段階での検査: 同じ版の2 PID の間で、5つの経路の記録が、正規化の後で一致すること(harness の決定性)。\n\nE5 所有権(R と O。4つの対象 × 入れ子の dict と配列 × 2つの向き)\n- 対象:\n - (1) create_snapshot() の戻り値\n - (2) SimulationRuntime.latest_snapshot\n - (3) snapshot_published の引数\n - (4) state_updated の引数\n - (3) と (4) は、probe の既存の接続で受け取った参照を、handler の外で保持して使う。handler の中で変更しない(他の受け手への影響を避けるため)。\n- 変更の場所(固定。R と O の両方に存在するもの):\n - 入れ子の dict: systems.runtime.id_generator.counters に、key \"__p28_eq_probe\" と値 1 を追加する。\n - 入れ子の配列: systems.runtime.domain_events.published_ids に、文字列 \"__p28_eq_probe\" を追加する。\n- 外から内:\n - 変更の直前に、内部の create_snapshot() の tree と、latest_snapshot の tree と、latest_digest の文字列を記録する。latest_digest は遅延して計算されるので、変更の前に一度読んで確定させ、その事実を記録する。\n - 変更の直後に、同じ3つを取り直して比べる。\n - 変化があれば、変わった path と値を全て記録する。\n- 内から外:\n - 返された値の deep copy を保持する。advance_minutes(1) を1回行った後に、返された値そのものが、保持した deep copy と同じであることを確かめる。\n- 予想される既存の不具合:\n - latest_snapshot と、signal の引数 (3)(4) は同じ object である(:12617-12621)。そのため、(2)〜(4) の外から内の変更は、latest_snapshot を変え、まだ計算していない digest にも影響しうる。\n - これは「既存の不具合」として、対象・向き・変わった path・値・digest への影響を全て記録する。PASS で補わない。harness による無断の変更とは区別する(どの scenario の、どの操作かを結びつける)。\n - その後の検査は、advance_minutes(1) を1回行って新しい latest_snapshot が publish された後の状態を、新しい baseline として始める。\n- (1) が deep copy であれば、影響が無いことを予想する。影響があれば、同じく事実として記録する。\n\ncheck_eq.py と試験\n- E4 と E5 の記録の形式・必須の欄・矛盾の検査を加える:\n - 経路の順序\n - 区間の連続\n - 件数(restore は0、load の成功は1)\n - X(P, ev_load)\n - 4×2×2 の全ての組の存在\n - NA の理由\n- 拒否の試験を加える:\n - 経路の欠落\n - 件数の不一致\n - 既存の aliasing を PASS として扱うこと\n - aliasing の記録の欠落\n - handler の中での変更\n - 区間の外での状態の変更\n - tick を含まない経路の latest_snapshot の据え置きを cache の古さと誤判定すること\n - NA を PASS として数えること\n\n終わり\n- engine を使わない python3 test_eq.py の全件 PASS まで直し、生出力を保存する。PROGRESS.md を更新する。正式な JSON の status を blocked にし、findings を「段階 S3b 完了(失敗ではない。次は S4)」とする。提出しない。\n- engine の起動、git への書込み、製品の変更、全回帰はしない。通常の実装上の判断は、記録して進める。\n" + }, + "EQ_S3B_STAGE_PLAN_R02.txt": { + "sha256": "9a26f47012e51ed23eb03e539fc5c4734e4d41c09ce37a21a18b4ac8a77a5f4c", + "full_unedited": "EQ_S3B_STAGE_PLAN r02(P28-02-EQ 段階 S3b。EQ_S3B_STAGE_PLAN(r01)は、そのまま有効。この r02 は、r01 の E4 の経路 1 の「引数の選び方」(施設の定義の列挙元)だけを置き換える。SPEC、TASK、6条件、eq/references、eq/registration、補足 r01/r02/r03、段階の計画 r01/r02、S3 の計画 r01/r02 は変更しない)\n\n0. 訂正の理由(計画の参照の誤り。製品・仕様の変更ではない)\n- r01 は、施設の定義の一覧を mvp_content_catalog から取るとしていた。しかし scripts/data/mvp_content_catalog.gd:26-31 の DEFAULT_PATHS は人物の4種だけで、施設を含まない。そこから列挙すると一覧が空になり、「配置できる組が無い」という NA が誤って成立してしまう。\n- 施設の定義は、autoload/simulation_runtime.gd:446-447 で、FacilityCatalog の FACILITY_PATHS、INFRASTRUCTURE_FACILITY_PATHS、RESCUE_FACILITY_PATHS、ORIGINAL_FACILITY_PATHS、TRANSPORT_FACILITY_PATHS から runtime.definition_registry に登録される。preview_build_facility(:7660)も、同じ definition_registry.get_facility を使う。\n- run 7da027a85548460bb008b562a79a52ae の worker は、この誤りを指摘し、空の一覧を NA にせず blocked で返した。これは正しい判断であり、失敗ではない。\n\n1. E4 の経路 1 の引数の選び方(r01 の該当の箇条を置き換える)\n- 列挙元: R と O のそれぞれで、その PID の runtime の definition_registry.get_facility_ids()(scripts/core/definition_registry.gd:68-69。Array[StringName])。R と O の両方とも、元の実際の施設の registry から候補を取る。別の catalog、固定の ID の一覧、R の結果での O の代用は使わない。\n- 順序: 取得した ID を、文字列としての ID の順序(String(id) の昇順。Python 側の記録は Unicode の code point の順序)に並べる。registry の登録の順序は、取得した生の一覧として別に記録する。\n- cell の走査: r01 のとおり、(x, y, z) の辞書順。走査の範囲は、その版の世界の公開の寸法から、固定の規則で決め、その規則と範囲を記録する。rotation は 0 に固定する(他の値は試さない)。\n- 判定: 製品の公開の SimulationRuntime.preview_build_facility(definition_id, origin, rotation) だけを使う。ID の順序の外側のループ、cell の順序の内側のループで、最初に配置できると返った組を選ぶ。\n- 実行: 選んだ組で submit_command(&\"build_facility\", {definition_id, origin, rotation})(:476、:305、:7717-7720)を submit する。記録の時点(submit の直後と、advance_minutes(1) の後)は r01 のとおり。\n\n2. 保存する記録(R と O のそれぞれ)\n- get_facility_ids() の生の一覧(登録の順序)と、その件数。\n- 並べた後の一覧と、並べ方の規則。\n- cell の走査の規則と範囲。\n- 試した各候補(definition_id、origin、rotation)と、preview_build_facility の戻り値の全体(typed tree)。試行の件数が多い場合も、全件を記録する(省略しない)。\n- 選んだ候補と、その submit の戻り値と、command の結果。\n- 適用しなかった場合の理由。\n\n3. NA の条件\n- NA にしてよいのは、get_facility_ids() の実際の一覧が空でなく、走査の範囲の全ての組で preview_build_facility が配置できないと返した場合だけ。そのときは、上の 2 の全ての記録とともに、理由つきの NA とする。\n- 一覧が空の場合は NA にせず、registry の取得の誤りとして失敗にし、その事実を記録する。間違った列挙元や空の一覧からの NA(false NA)は禁止する。\n- NA を PASS として数えない。施設の値を作らない。この経路の外で建設しない。\n- check_eq.py に、次の拒否を加える: 列挙元が definition_registry.get_facility_ids() 以外であること、空の一覧での NA、preview の記録が無い候補の選択、試行の記録の欠落、並べ方の規則の違反、R と O で列挙元が違うこと。\n\n4. 変更しないこと\n- E4 の経路 2〜5、E5 の 4×2×2、全ての状態とイベントの typed tree での記録、既存の aliasing の不具合としての記録、S1/S2/S3a の型・path・schema・API・code の再利用、E3 と既存の91件の試験の本体と失敗の履歴(失敗した試験が求める修正を除く)、engine を使わない python3 test_eq.py の全件 PASS と生出力の保存、PROGRESS.md の更新、正式な JSON の status を blocked にし findings を「段階 S3b 完了(失敗ではない。次は S4)」とすること、提出しないこと、engine・git の書込み・製品の変更・全回帰をしないこと。いずれも r01 のとおり。\n- 通常の実装上の判断は、記録して進める。\n" + }, + "EQ_S4_STAGE_PLAN.txt": { + "sha256": "4448602b1542f003282c9572765c71046800a1e2a92e1755792f0ba39caa56d5", + "full_unedited": "EQ_S4_STAGE_PLAN(P28-02-EQ 段階 S4。最後の段階。EQ_STAGED_IMPLEMENTATION_PLAN r01/r02 の S4 を、実際の API と S1〜S3b の結合の要件に合わせて具体化する。SPEC、TASK、6条件、eq/references、eq/registration、補足 r01/r02/r03、段階の計画 r01/r02、S3 の計画 r01/r02、S3b の計画 r01/r02 は変更しない)\n\n0. 共通\n- 最初に eq/PROGRESS.md と eq/IMPLEMENTATION.md を読む。特に、S2 と S3a の「S4 must ...」の全ての箇条と、末尾の「S4 binding requirements」を、S4 の要件の一覧として最初に書き出し、各要件をどのコードと試験で満たしたかを IMPLEMENTATION.md に対応表で記録する。\n- S1〜S3b の型・path・record schema・API・コード(check_eq.join_report、check_report、check_observation、check_lifecycle、strict_json、compare_versions.compare_reports など)を、そのまま使う。再設計しない。S4 が新しく作るのは eq/run_eq.py と eq/verify_eq.py と、その試験。\n- 既存の119件の試験の本体、全ての失敗の履歴(S3b の attempt 02/03/07/08 を含む)、旧 run 7da027a の指示の誤りの記録は、消さない。書き直さない(失敗した試験が求める修正を除く)。\n- 凍結した依存の API は、RootB/S4_FROZEN_DEPENDENCY_API_NOTES_R01.json(SHA 682a0d9a04978411691e9a8291b46a9ddc6eeb621d38c0f699a756e47be0084b)の要約に従う。collector(execution/p28-01/collector/collect_p28_01.py、SHA a43e1f96…)と restart_pair.py(SHA 538302ee…)は、読取専用で import して使う。複製や書き換えはしない。\n\n1. eq/run_eq.py(Root が実行する driver。SPEC §2 の argv のまま)\n1.1 --check(engine を起動しない)\n- 引数と pin を検証して、実行の計画(7つの phase の argv、環境変数、出力の path、profile の名前)を JSON で出す。process は起動しない。\n- 検証する pin: fixture の SHA(eb4f7700…)、engine の SHA(c7cccbf8…)、製品の source map の SHA(651f7036…、1407件の全ての相対 path・bytes・SHA を source_map(standard, root) で取る。件数だけにしない)、machine、EQ のファイル(6つ)の SHA、project.godot の元の bytes の SHA、設定・marker・policy の SHA。\n- inputs(readonly) で、元の manifest の SHA と、元の絶対の destination の9件を検証する。複製した manifest の root で代用しない。\n- --output の dir が既に存在すれば拒否する(上書きしない)。\n\n1.2 --run の phase(この順序で、それぞれ1回)\n- import: argv_for(engine, stage, wrapper, importing=True)。stage_gate(before, after, importing=True)。\n- parse-base、parse-wrapper: parse_argv(engine, stage, target) の --check-only。stage_gate(before, after)。\n- R-A、R-B、O-A、O-B: S1〜S3b で決まった R と O の起動の規則で、測定の wrapper を headless で起動する。\n- 各 phase は run_private_engine(standard, outer, command, folder, environment, stage, public, name) で行う。public は project.godot の元の bytes、name は startup の profile の名前、folder は未作成の新しい dir。戻り値の owned row の全体を記録する。\n- guard: parent の initialize の前に有効になること。startup と runtime の profile は、phase ごとに新しく一意の名前にする。環境変数 THE_TREE_PACK_PROFILE_NAME / EXPECTED / REPORT と、role(R/O)、fixture の path と SHA を結びつける。guard_gate(value, runtime: Path, name) の name は runtime の profile の名前。\n- stage_gate と guard_gate は、成功で None、失敗で例外。戻り値を bool として扱わない(試験で拒否する)。\n- profile_files(directory) は、存在しない dir で空の dict を返すが、それを fresh であることや、証拠の保存の成功の証明にしない。fresh であることは guard の受領で、保存の成功は下の 1.3 の複製と inventory で証明する。\n- 各 phase で、collector の raw3(stdout、stderr、exit)と owned5 の受領、実際の PID と開始・終了の時刻、strict diagnostic(collector の規則のまま)を保存する。\n- report の role(R/O)と、native の phase(R-A など)と、実際の PID を、driver が明示的に結びつけて記録する(role を phase 名から推測しない)。\n- finally: 既定の player の設定・source・project.godot・guard・PID の後始末を、collector の既存の処理のまま保持し、後始末の結果(残った process 0、残った profile の扱い)を記録する。\n\n1.3 証拠の複製と結合(owned の process の終了の後)\n- R-A〜O-B の各 phase で、private profile の全ての証拠を複製し、全件の bytes と SHA を記録する: report(stdout の P28_02_EQ_REPORT= の1行)、lifecycle.json(measurement、e3、e3_b1、e45 を含む)、audio-close.json、events.json、observation、全ての e3-NN.json(00〜17)、全ての e45-NN.json(00〜20)、package の証拠。restart.copy_states は参考とし、EQ 自身の正確な名前の inventory で結びつける。欠けた・余分な・変わったファイルは拒否する。\n- lifecycle の inventory が自分の hash と audio の受領を含まないことに従い、lifecycle.json と audio-close.json の SHA を、それぞれ独立に結びつける。lifecycle か audio が欠けている、または error を含む場合は、stdout の report があっても失敗にする。\n- raw の JSON は strict_json で読む。各 phase で:\n - check_observation(raw の全 bytes と SHA の witness)\n - check_lifecycle(guard の受領、準備と後始末、S3a と S3b の分)\n - check_report(raw, measurement=lifecycle.measurement, e3_evidence=…, b1_record=…) に lifecycle.e45 を渡す\n - report.scenarios が E3 の18件 + E4/E5 の21件(E4 の5件 + E5 の16件)= 39件で、順序と区間の連続が正しいこと\n- check_eq.join_report で raw を結合してから、compare_versions.compare_reports を呼ぶ。raw と、結合した出力と、join_facts の sidecar と proof と、checker の結果を、別々のファイルとして、それぞれの SHA とともに保持する。\n- 同じ版の決定性: R-A と R-B、O-A と O-B を、それぞれ別に比べ、SPEC §3.2 の版の間の比較の差が0であることを確かめる。R と O を互いに比べない。\n- 既存の不具合(latest_snapshot の aliasing、cached_digest_aliasing を含む)は、その結果のまま bundle に入れる。PASS に補わない。\n- 全ての複製と結合の後に、bundle の manifest(全ファイルの相対 path・bytes・SHA)を書き、最後に seal(manifest の SHA)を書く。seal の後に書き込みをしない。\n\n1.4 bundle の配置と失敗\n- 7つの phase と 1.3 の全ての検査が成功した場合だけ、bundle を --output の下に作る。Root がそれを $BUILD_OUTPUT_DIR/p28-02-eq-evidence に、bytes をそのまま置く(verify_eq.py は場所を変えない)。\n- 失敗した場合は、bundle を作らず、raw と失敗の記録(どの phase の、どの検査か)を --output に残し、0 以外の終了コードで終わる。失敗を成功に書き換えない。\n- 表記: この記録は「S_eq の native」であって、Q で測ったものではない。source・設定・入力・marker・policy・engine・環境・EQ の同一性が証明された場合だけ、Q_eq での再利用ができる(SPEC §5)。bundle にこの区別を書く。\n\n2. eq/verify_eq.py(正式の validation p28-02-eq-native-verify)\n- --project-root . で、$BUILD_OUTPUT_DIR/p28-02-eq-evidence の bundle を読む。BUILD_OUTPUT_DIR が無い、bundle が無い、seal が無い場合は失敗にする。\n- seal と manifest を検証し、欠けた・余分な・変わったファイルを拒否する。\n- 結合した出力を信用せず、raw から 1.3 の全ての検査(strict_json、check_observation、check_lifecycle、check_report、join_report、compare_reports、39件、R と O の別々の決定性、既存の不具合の保持)をやり直し、bundle の記録と一致することを確かめる。\n- pin(fixture、engine、source map 1407 の全件、machine、EQ のファイルの SHA、project・設定・marker・policy)が、--project-root の実際のファイルと一致することを確かめる。EQ のファイルの SHA は、検証の時点の W の実際のファイルと比べる。\n- 7つの phase の全てで、raw3、owned5、PID の開始と終了、strict diagnostic、guard、後始末(残り0)がそろっていることを確かめる。\n- 結果を1つの JSON で出し、成功だけ終了コード 0。\n\n3. 試験(test_eq.py に追加。engine を使わない)\n- bundle の正常(合成の bytes で作った bundle が verify の論理で通ること。これは native の証明ではないと試験の名前と出力に書く)。\n- 拒否:\n - bundle・seal・manifest の欠落、余分なファイル、変わったファイル、seal の後の書込み\n - lifecycle・audio・e3-NN・e45-NN の欠落、error を含む lifecycle\n - 39件でない scenario、順序の違い、E4/E5 の21件の欠落\n - guard_gate・stage_gate の戻り値の bool としての扱い\n - 存在しない profile の空の dict を fresh や保存の成功とすること\n - 複製した manifest の root での代用、destination の9件の不一致\n - startup と runtime の profile の名前の取り違え、profile の再利用\n - role と phase と PID の結びつきの欠落や矛盾\n - raw3・owned5・PID の開始と終了の欠落、strict diagnostic の違反、後始末の残り\n - R と O の交差の比較、決定性の差が0でないのに合格にすること\n - join の前の compare、raw と結合した出力の混同、sidecar の欠落\n - 既存の不具合を PASS にすること、aliasing の記録の欠落\n - source map の件数だけの検査、1407件の1つの不一致、pin の不一致\n - Q で測ったという表記\n - --output の既存の dir への上書き、失敗の時の bundle の作成\n- 既存の119件を含めて、python3 -B test_eq.py の全件 PASS まで直し、生出力と SHA を保存する。失敗した試行の生出力も残す。\n\n4. 終わり(正式な提出)\n- PROGRESS.md と IMPLEMENTATION.md(S4 の要件の対応表を含む)を更新する。\n- 局所の全件 PASS を確かめた後、正式な JSON で提出する(status は blocked にしない)。提出は局所の unit の証拠であり、native の実行・受け入れた S・Q での測定・製品の PASS とは表記しない。6条件は、Root の native と両方の validation と fresh の独立した Opus のレビューまで保留のまま。\n- worker は、engine の起動、run_eq.py --run の実行、git への書込み、製品の変更、全回帰をしない。正式の validation(bundle の無い状態の verify_eq.py を含む)を、試しに実行して失敗させない。commit と gate は Runner が通常どおり行う。\n- 通常の実装上の判断は、記録して進める。\n\n5. 提出の後の順序(Root と Runner。worker の範囲の外)\n- Root が、凍結した S で native の7つの phase(import、parse-base、parse-wrapper、R-A、R-B、O-A、O-B)を run_eq.py --run で1回行い、成功した bundle を $BUILD_OUTPUT_DIR/p28-02-eq-evidence に置く。\n- 両方の validation(p28-02-eq-unit、p28-02-eq-native-verify)。\n- fresh の、別の Opus のセッションによる、6条件の全てのレビュー。\n- 通常の prepare、候補の資格の確認、承認、integration、final。その後に OPT と whole-unit の gate。\n- 原本の 23/88・4/30、原本の条件、課金、権限、900秒は変えない。\n" + }, + "EQ_S4_STAGE_PLAN_R02.txt": { + "sha256": "f736fb819c8d0ee6e94822896aa995e448a203ba8395743838f1cbf2a6c72660", + "full_unedited": "EQ_S4_STAGE_PLAN r02(P28-02-EQ 段階 S4。EQ_S4_STAGE_PLAN(r01)は、ここで置き換える箇所を除いて、そのまま有効。この r02 は、r01 の §0 の import の範囲、§1.2 の raw3 の名前、実際の API の引数、正式な提出の status、validation の書込みの場所だけを、実際の source に合わせて訂正し、具体化する。S4 の範囲(run_eq.py、verify_eq.py、bundle の正常と拒否の unit、局所の全件 PASS、正式な提出)は小さくしない。SPEC、TASK、6条件、eq/references、eq/registration、補足 r01/r02/r03、段階の計画 r01/r02、S3 の計画 r01/r02、S3b の計画 r01/r02 は変更しない)\n\n1. import の範囲(r01 §0 の4つ目の箇条を置き換える)\n- 凍結した EQ SPEC §1 の読取の閉包(RESTART D1 の6つ + DIAG の5つ + EQ 自身)の中のものだけを使う。閉包と権限は広げない。\n- collector(execution/p28-01/collector/collect_p28_01.py、SHA a43e1f963ef8505ddd5acf8bf747d9bfac22a028cbb805c0b964ee11b9b40a14)は、閉包の中で、読取専用で import する。\n- restart_pair.py(SHA 538302ee…)は RESTART の task の所有物で、EQ の閉包に入らない。import しない。copy_states は、読んで参考にするだけとする。証拠の複製と inventory は、EQ が自分のコードとして eq/ の中に実装する(r01 §1.3 の正確な名前の一覧で)。\n- check_eq.py の静的な検査と試験に、restart_pair の import と、閉包の外の import を拒否するものを加える。\n\n2. raw3 の名前(r01 §1.2 の「raw3(stdout、stderr、exit)」を置き換える)\n- raw3 は、collector の run_engine(collect_p28_01.py:217、:225)が実際に作る3つのファイル: stdout.log、stderr.log、engine-native.log。engine-native.log(--log-file、--verbose)を落とさない。\n- 終了コードは raw3 ではない。owned の受領(process.json など、owned5 の中)にある実際の値を、そこから読んで記録し、結びつける。\n- 各 phase で、raw3 の3つのファイルの存在・bytes・SHA と、owned5 の5つの受領を、全て要求する。どれかが欠ければ失敗にする。試験で、engine-native.log の欠落と、終了コードを raw3 から読もうとすることを拒否する。\n\n3. 実際の API の引数(r01 §1.3 と §2 を具体化する)\n- check_report(raw, measurement=None, e3_evidence=None, b1_record=None, e45_evidence=None): measurement に lifecycle.measurement、e3_evidence に lifecycle.e3、b1_record に lifecycle.e3_b1、e45_evidence に lifecycle.e45 を渡す。どれかを None のまま呼ばない。\n- check_lifecycle(raw, lifecycle, guard): guard は、その phase の guard の受領。\n- 各 R/O の phase の private profile の証拠の正確な名前の一覧: checkpoint-00.json〜checkpoint-30.json(31件)、observation-00.json〜observation-30.json(31件)、e3-00.json〜e3-17.json(18件)、e45-00.json〜e45-20.json(21件)、events.json、report.json、lifecycle.json、audio-close.json。これに package の証拠を加える(S3a/S3b で決まった名前のまま)。この一覧と比べて、欠けた・余分な・変わったファイルを拒否する。\n\n4. 正式な提出の status(r01 §4 を具体化する)\n- Runner は、worker の JSON の status が \"submitted\" であることを要求する(core.py:1015)。schema には \"pass\" もあるが、実装の run では submitted でないと止まる。S4 の最後の JSON の status は、ちょうど \"submitted\" にする。\"pass\" や \"blocked\" にしない。\n- commit の欄は、base の 2549cf7d6992560b850bbd11934e3c14b39a1988 とする。worker は git に書き込まない。通常の git commit は Runner.submit が行う。\n\n5. validation の書込みの場所(r01 §2 と §3 を具体化する)\n- 正式の validation は、checkout を読取専用にして実行される(core.py:1064 の writable=())。BUILD_OUTPUT_DIR は、Runner が runtime の build の領域に割り当てる(core.py:827)。\n- test_eq.py(p28-02-eq-unit)の bundle の合成の試験は、一時の生成物を、その割り当てられた BUILD_OUTPUT_DIR の下(無い場合は tempfile.gettempdir() の下)の新しい dir にだけ作る。source の tree(eq/ を含む)に書き込む設計にしない。\n- verify_eq.py は、bundle を読むだけで、checkout に書き込まない。結果は stdout の JSON で出す。\n- 試験で、checkout の中への書込みを検出して拒否する(たとえば、合成の bundle の dir が source の tree の中にあること)。\n- 環境・権限・writable の設定は変えない。\n\n6. 変更しないこと\n- r01 のそれ以外の全て: 既存の「S4 must」の要件の対応表、7つの phase、guard と profile の規則、gate の None/例外、profile_files の扱い、全証拠の複製と SHA、strict_json と check_observation と check_lifecycle と check_report、39件の scenario、join_report の後の compare_reports、raw と結合した出力と sidecar の分離、R-A/R-B と O-A/O-B の別々の決定性、既存の不具合の保持、source map 1407 と全ての pin、finally の後始末、成功の時だけの seal、「S_eq の native であって Q の測定ではない」の表記、失敗の時の bundle の不作成、verify_eq.py の raw からの再計算、bundle の正常と拒否の試験、119件の本体と全ての失敗の履歴の保持、局所の全件 PASS と生出力の保存。\n- worker は、engine の起動、run_eq.py --run の実行、正式の validation の試しの実行、git への書込み、製品の変更、全回帰をしない。\n- 提出の後の順序(Root の正確な S の native の7つの phase、bundle の配置、両方の validation、fresh の別の Opus による6条件の全てのレビュー、通常の prepare・資格・承認・integration・final、その後の OPT と whole-unit)と、原本の 23/88・4/30・原本の条件・課金・権限・900秒は変えない。\n- 通常の実装上の判断は、記録して進める。\n" + } + }, + "effective_S4_correction": "EQ_S4_STAGE_PLAN_R02.txt replaces S4 import/raw3/argument/protocol/validation-writable details only. restart_pair is read-only reference, never imported; raw3 stdout/stderr/engine-native; worker status submitted and commit base. All S4 r01 other requirements and prior retained stages remain effective", + "actual_Opus_response_origin": "Desktop response344 to request343; the unmodified actual decision reason labels previous message342", + "actual_frozen_dependency_API_notes": { + "sha256": "682a0d9a04978411691e9a8291b46a9ddc6eeb621d38c0f699a756e47be0084b", + "full_unedited": "{\n \"at_jst\": \"2026-10-21T09:22:58.012059+09:00\",\n \"scope\": \"Read-only frozen dependency API preparation for actual Opus S4 plan; no live worker inspection, tests, engine, edits, or acceptance credit\",\n \"sources\": [\n {\n \"path\": \"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/execution/p28-01/collector/collect_p28_01.py\",\n \"bytes\": 23306,\n \"sha256\": \"a43e1f963ef8505ddd5acf8bf747d9bfac22a028cbb805c0b964ee11b9b40a14\"\n },\n {\n \"path\": \"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/execution/p28-01/restart/probe/restart_pair.py\",\n \"bytes\": 17486,\n \"sha256\": \"538302eea55b033157446363c0787ea2dda5fbd31d4181ea5e39824609560d31\"\n },\n {\n \"path\": \"/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-01-perf-baseline/.runtime/P28-01-COLLECTOR/build/p28-01-readonly/run-r02/profile_guard.gd\",\n \"bytes\": 2276,\n \"sha256\": \"597696c705cc8f0e79a35265ca3ef8df55f7fc3c4e0e5a2ce9a4e20e29e29a6f\"\n }\n ],\n \"APIs\": {\n \"inputs(readonly)\": \"Verifies fixed manifest SHA and original absolute destinations, returns manifest_sha256/files. Do not substitute a copied manifest root.\",\n \"source_map(standard,root)\": \"Full relative path to bytes/sha256 map, not count-only.\",\n \"argv_for(engine,stage,wrapper,importing=True)\": \"Import argv; parse_argv(engine,stage,target) gives check-only argv. Measured EQ wrapper argv is explicitly headless.\",\n \"run_private_engine(standard,outer,command,folder,environment,stage,public,name)\": \"Returns owned row dict. public is original project.godot bytes; name is startup profile name. Folder must not yet exist; startup evidence is written beside it. finally restores project bytes.\",\n \"stage_gate(before,after,importing=False)\": \"Raises on failure, returns None on success; import allows only corresponding new gd.uid/import support files.\",\n \"guard_gate(value,runtime,name)\": \"Raises on failure, returns None on success. runtime is Path, name is runtime profile name, not startup profile name; binds exact actual user dir/fresh/5 conditions.\",\n \"profile_files(directory)\": \"Complete relative file SHA/byte inventory, rejects symlinks. Nonexistent gives empty dict but is not proof of freshness or successful evidence export.\",\n \"restart.copy_states(out,row)\": \"Reference for copying private typed evidence after owned process end; EQ must bind its own exact evidence names/inventory.\"\n },\n \"binding_requirements\": [\n \"Seven phases import,parse-base,parse-wrapper,R-A,R-B,O-A,O-B; report role R/O is distinct from native phase and actual PID; bind explicitly.\",\n \"Preserve raw3 and owned5 receipts, actual captured PID lifecycle, strict diagnostics, original project/source/default-player preservation and finally cleanup.\",\n \"Guard activates before parent initialize. Each startup and runtime profile is fresh and unique. Bind env THE_TREE_PACK_PROFILE_NAME/EXPECTED/REPORT plus role/fixture path/SHA.\",\n \"After owned end copy all profile evidence and bind checkpoint/observation/event/scenario/lifecycle/audio to raw report SHA. Seal after copy; reject missing,extra,changed evidence.\",\n \"Only actual successful bundle goes to BUILD_OUTPUT_DIR/p28-02-eq-evidence before both registered unit and native-verify. Exact-S native is not Q measurement unless source/settings/input/marker/policy/engine/environment/EQ identity proves reuse.\",\n \"All original conditions and fresh independent Opus all6 review and normal integration/final remain.\"\n ],\n \"original_credit\": 0\n}\n" + }, + "read_only_clarifications": { + "EQ_S_TIMING_CLARIFICATION.txt": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/.runtime/P28-02-EQ/build/eq-staged-readonly-r04/EQ_S_TIMING_CLARIFICATION.txt", + "bytes": 5792, + "sha256": "25d323fd562d29e80782b6f075fc7a0e8b49457a6c4fbd7c30e74b31a6b6a126" + }, + "EQ_S_TIMING_CLARIFICATION_R02.txt": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/.runtime/P28-02-EQ/build/eq-staged-readonly-r04/EQ_S_TIMING_CLARIFICATION_R02.txt", + "bytes": 7347, + "sha256": "777accdd652f85db6b9014d85e3c8b3b60ca94b20768e6173b36bc769d360fd9" + }, + "EQ_ENVIRONMENT_FIELDS_CLARIFICATION_R03.txt": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/.runtime/P28-02-EQ/build/eq-staged-readonly-r04/EQ_ENVIRONMENT_FIELDS_CLARIFICATION_R03.txt", + "bytes": 7637, + "sha256": "12b27f984ef5843d98327200ad261dccaf64968402192b08ad55b15ed5454ea2" + } + }, + "full_frozen_references_in_W": { + "docs/plans/original-completion-2026-10-02/execution/p28-02/eq/references/OPUS_D2_SCOPE_CLARIFICATION.txt": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/references/OPUS_D2_SCOPE_CLARIFICATION.txt", + "bytes": 5598, + "sha256": "5775e7b512d9e90dbcfbcb181f5b64dc0fa8207e0947c0a4a6a5c9195565f9bd" + }, + "docs/plans/original-completion-2026-10-02/execution/p28-02/eq/references/OPUS_STARTUP_LIFECYCLE_CLARIFICATION.txt": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/references/OPUS_STARTUP_LIFECYCLE_CLARIFICATION.txt", + "bytes": 5996, + "sha256": "967aebf27ff412f7a16ce771ef7d68abf8cfde0bb76ed19cf6dbf2817ca7acc6" + }, + "docs/plans/original-completion-2026-10-02/execution/p28-02/eq/references/OPT_CONTRACT_T1.md": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/references/OPT_CONTRACT_T1.md", + "bytes": 13952, + "sha256": "ad9f3d76f3500b39263fb898d7c64588b4b47c9e11b456f938195261fd054d16" + }, + "docs/plans/original-completion-2026-10-02/execution/p28-02/eq/TASK_INSTRUCTIONS.md": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/TASK_INSTRUCTIONS.md", + "bytes": 2961, + "sha256": "f9937c3c7dff5a25ada453365d26c87fecf009d29518724f0c1e67d2b18afff3" + }, + "docs/plans/original-completion-2026-10-02/execution/p28-01/restart/SPEC_CLARIFICATION_01.md": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-01/restart/SPEC_CLARIFICATION_01.md", + "bytes": 3613, + "sha256": "4aa50206f662e2939824aa8da2e9e330956d64061f6244e0c3e0244452978920" + }, + "docs/plans/original-completion-2026-10-02/execution/p28-01/restart/SPEC_CLARIFICATION_02.md": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-01/restart/SPEC_CLARIFICATION_02.md", + "bytes": 12278, + "sha256": "b4ab43445a818fd01068a6c948beffff6d9dee15f8276f5a20aabaf0a3c0640a" + } + }, + "original_credit": 0, + "original_denominator": [ + 30, + 88 + ] + }, + "current_stage_plan_r03": { + "full_unedited": "EQ_S4_STAGE_PLAN r03(P28-02-EQ 段階 S4 の完了。EQ_S4_STAGE_PLAN r01 と r02 は、全てそのまま有効。この r03 は、run 20dc4135cc3041dbb82fcc2b2a6b0cbe(900秒の期限で exit 124)で保持された実装を引き継いで、正式な submitted まで閉じるための残りの作業だけを決める。S4 の範囲は小さくしない。SPEC、TASK、6条件、eq/references、eq/registration、補足 r01/r02/r03、全ての段階の計画は変更しない)\n\n0. 引き継ぐもの(再実装しない、再監査しない)\n- W の中の現在の70件のファイル(RootB/retained-s4-20dc413-r01、RETURN の SHA a2c0d5ffd42b67ef340d5624dd299e294b867168bd1270933aec458a9cde1dc5 と一致するもの)。実装済みの run_eq.py と verify_eq.py、現在の134件の試験。\n- 既存の119件の試験の本体と、全ての unit の生出力(S4 の attempt 01 の構文、02 の追加の unit、04 の recompute の不一致の失敗、S4_SUPPLEMENTARY の作成の assert の失敗を含む)。消さない、書き直さない。\n- attempt 05 の 132件の PASS(194.460秒、embedded exit 0)は、その版だけの事実。その後に2件が加わり、attempt 06 は出力なしで期限に達した。現在の134件の PASS は、まだ証明されていない。134件が通ったとは書かない。\n\n1. medium の修正(必須)\n- eq/run_eq.py:257 と eq/verify_eq.py:144 は、check.check_probe(...) の戻り値を捨てている。check_probe は例外ではなく {ok, errors} を返す(eq/check_eq.py:384)。\n- 両方の箇所を、static = check.check_probe(...) にして、require(static['ok'], ) で拒否するように直す。戻り値を使わない他の check の呼出しが無いかを、run_eq.py と verify_eq.py の中だけで確かめ、同じ形のものがあれば同じく直して記録する。\n- 拒否の試験を加える: check_probe が {ok: false, errors: [...]} を返すとき、run_eq.py の driver(--check と、--run の probe の検査の段階)と verify_eq.py の両方が拒否すること。ok: true のときに通ること。\n\n2. 残りの文書と context\n- PROGRESS.md と IMPLEMENTATION.md を S4 の内容に更新する(今は S3b の記述のまま)。r01 §0 の「S4 must」の要件と、末尾の S4 binding requirements の全ての項目について、満たしたコードと試験の対応表を書く。r02 の訂正(collector だけの読取専用の import、restart_pair を import しない、raw3 の正確な名前、exit を owned の受領から読む、check_report と check_lifecycle の引数、証拠の名前の一覧、validation の書込みの場所)を、どのコードで満たしたかも書く。\n- S4_SUPPLEMENTARY.json: plan の全文を手で再構築しない。Root が同じ W の runtime に、元の bytes の読取専用の JSON として置いた r09 の ACTUAL_OPUS_TASK_CONTEXT.json(RootB/eq-staged-s4-owner-run-input-r09/ACTUAL_OPUS_TASK_CONTEXT.json と同じ bytes。W の中の path は Root の packet が示す)を読み込み、その内容を変えずに、1つの key actual_commander_context として保存する。元のファイルの SHA と、各 plan の SHA が一致することを確かめて記録する。この r03 と RUN r03 は、Root がその後に追加で配置するものを、同じ方法で保存する。\n- 以前の手での再構築の assert の失敗は、失敗の記録として残す。\n\n3. 時間の配分(900秒の期限は変えない)\n- 全件の unit は約200秒かかる(attempt 05 で 194.460秒)。修正の確認は、関係する試験の class だけを指定した部分の実行(python3 -B test_eq.py ...)で行い、その生出力も保存する。\n- 全件の実行は、全ての修正と追加の後に、最後に1回だけ行う。開始は、期限まで少なくとも300秒が残っている時点までとする。不具合の修正が必要になった場合は、記録して、関係する部分の再確認と、もう1回の全件の実行を行ってよい。\n- 時間が足りない場合は、それまでの成果と生出力を残して、通常の blocked で返す。全件の PASS を推定で書かない。\n\n4. 最終の確認と提出\n- 最後の全件の実行は、134件 + この r03 で加えた試験の全て。全件 PASS の生出力と SHA と件数と時間を、UNIT_OUTPUT.txt と、新しい attempt のファイルに保存する。\n- 正式な JSON: status はちょうど \"submitted\"、commit は 2549cf7d6992560b850bbd11934e3c14b39a1988。局所の unit の証拠であり、native の実行・受け入れた S・Q での測定・製品の PASS とは表記しない。\n- worker は、engine の起動、run_eq.py --run の実行、正式の validation の試しの実行、git への書込み、製品の変更、全回帰をしない。API の fallback は使わない(設定のまま)。\n- 通常の実装上の判断は、記録して進める。\n\n5. 提出の後(worker の範囲の外。変更しない)\n- Root の正確な S の native の7つの phase → bundle の配置 → 両方の validation → fresh の独立した Opus による6条件の全てのレビュー → 通常の資格・承認・integration・final → OPT と whole-unit。\n- 原本の 23/88・4/30 への加算は0。原本の条件・課金・権限・900秒は変えない。\n", + "sha256": "6c1ca5dbed18ddb355b285fa85e0d80fd83d7f56e2a79aac3d07664456bd7a63" + }, + "current_run_decision_r03": { + "action": "run", + "task_id": "P28-02-EQ", + "reason": "Use only after Root verifies through the normal gates: repair_ready, repairs 9, no S submitted, no active run, all 70 retained files present unchanged in the W (RETURN SHA a2c0d5ffd42b67ef340d5624dd299e294b867168bd1270933aec458a9cde1dc5), and the r09 ACTUAL_OPUS_TASK_CONTEXT.json placed read-only with its original bytes. Run repair 9 of P28-02-EQ once on the same W from base 2549cf7d6992560b850bbd11934e3c14b39a1988 with the single worker codex gpt-6-astra, finishing stage S4 on the retained implementation as defined in EQ_S4_STAGE_PLAN_R03.txt, with EQ_S4_STAGE_PLAN.txt and EQ_S4_STAGE_PLAN_R02.txt still in force. Do not reimplement, re-audit or reduce S4 to a smaller deliverable. Remaining work, all in this one run: (1) fix the medium false PASS at run_eq.py:257 and verify_eq.py:144 to static = check.check_probe(...) and require(static['ok'], message with all errors), fix any other ignored check return in those two files the same way, and add rejection tests proving that both the driver and the verifier reject ok:false and accept ok:true; (2) add any remaining S4 tests; (3) update PROGRESS.md and IMPLEMENTATION.md to S4, with the requirement-to-code table covering every 'S4 must' item, the S4 binding requirements and the r02 corrections; (4) write S4_SUPPLEMENTARY.json by loading Root's read-only r09 ACTUAL_OPUS_TASK_CONTEXT.json, plus this r03 plan and decision as Root places them, without hand reconstruction, recording and checking the source and per-plan SHAs, and keep the earlier assert failure; (5) check fixes with targeted class runs, saving their raw, then run the full python3 -B test_eq.py once at the end over all 134 tests plus every test added in r03, starting with at least 300 seconds left. Attempt 05's 132 PASS covers that version only, so the final full PASS must include every later test. A further fix with related rechecks and one more full run is allowed if recorded. If time runs short, return a normal blocked status with all raw kept, and never claim an unproven PASS. (6) Submit the formal JSON with status exactly 'submitted' and commit 2549cf7d6992560b850bbd11934e3c14b39a1988, as local unit evidence only, not native, accepted S, Q measurement or product PASS. Keep the 119 earlier test bodies, all raw outputs and failures, every S4 r01 and r02 binding and raw recomputation, the 6 conditions and both validations. No engine, no run_eq.py --run, no trial formal validation, no git write, no product change, no full regression, and no API fallback. SPEC, TASK, eq/references and eq/registration stay unchanged. Ordinary implementation choices are recorded without stopping; block only for undecided matters affecting original product spec, values, permissions, billing or original acceptance. After submission: Root native on the exact S in 7 phases, the bundle at $BUILD_OUTPUT_DIR/p28-02-eq-evidence, both validations, a fresh independent Opus review of all 6 conditions, then the normal qualification, approval, integration and final, then the OPT and whole-unit gates. No original credit (23/88, 4/30); the 900-second timeout and permissions are unchanged. Quota fallback only on structured provider quota, once, same role, Antigravity claude-opus-5-5-high; any other failure is blocked. Decided by Claude Opus 5.5 in the Desktop control session (message 346); not a CLI commander result." + }, + "source_pins": { + "PRIOR_ACTUAL_OPUS_CONTEXT_R09.json": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/.runtime/P28-02-EQ/build/eq-s4-retained-r10/PRIOR_ACTUAL_OPUS_CONTEXT_R09.json", + "bytes": 92871, + "sha256": "c3beadcc6e9e4b144bd1449d082a335948833dbf37351f9f3e0b0e7de5425c1e" + }, + "RETAINED_S4_RETURN.json": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/.runtime/P28-02-EQ/build/eq-s4-retained-r10/RETAINED_S4_RETURN.json", + "bytes": 60561, + "sha256": "a2c0d5ffd42b67ef340d5624dd299e294b867168bd1270933aec458a9cde1dc5" + }, + "ROOT_S4_TIMEOUT_JOIN.json": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/.runtime/P28-02-EQ/build/eq-s4-retained-r10/ROOT_S4_TIMEOUT_JOIN.json", + "bytes": 9703, + "sha256": "945fec6bcfa431d794ac74513219cce8eab8dccade517c6a6faeb391f86e05d7" + }, + "EQ_S4_STAGE_PLAN_R03.txt": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/.runtime/P28-02-EQ/build/eq-s4-retained-r10/EQ_S4_STAGE_PLAN_R03.txt", + "bytes": 5501, + "sha256": "6c1ca5dbed18ddb355b285fa85e0d80fd83d7f56e2a79aac3d07664456bd7a63" + }, + "DESKTOP_EQ_S4_RUN_DECISION_R03.json": { + "path": "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/.runtime/P28-02-EQ/build/eq-s4-retained-r10/DESKTOP_EQ_S4_RUN_DECISION_R03.json", + "bytes": 3398, + "sha256": "c854a9b0f232ecce9985bcf1988caba886e4b6b484631e00db1bc4d51a28098c" + } + }, + "verified_prior_plan_sha256": { + "EQ_STAGED_IMPLEMENTATION_PLAN.txt": "eb7b4831e2164c6fc983fa6f9825e7f3e2993b4c0ebf2f90aac8ad10662666d2", + "EQ_STAGED_IMPLEMENTATION_PLAN_R02.txt": "128f42f18e168e9299995296ac7ad119f47d1647799d472663282e47e8ac9fdd", + "EQ_S3_STAGE_PLAN.txt": "ecbfb00691017fbd35027df8fa9ca6f82c761a5a3389568fe44b1babcfca308a", + "EQ_S3_STAGE_PLAN_R02.txt": "566e3ad98f9d47136ff4d4932f81c0a7f9fc96321a6f08ba944a9f1e736e6caa", + "EQ_S3B_STAGE_PLAN.txt": "d14fe474ae4626719d8ff9be6cef1423f076bff0829060ded77b1520ac7bd88d", + "EQ_S3B_STAGE_PLAN_R02.txt": "9a26f47012e51ed23eb03e539fc5c4734e4d41c09ce37a21a18b4ac8a77a5f4c", + "EQ_S4_STAGE_PLAN.txt": "4448602b1542f003282c9572765c71046800a1e2a92e1755792f0ba39caa56d5", + "EQ_S4_STAGE_PLAN_R02.txt": "f736fb819c8d0ee6e94822896aa995e448a203ba8395743838f1cbf2a6c72660" + }, + "verified_api_notes_sha256": "682a0d9a04978411691e9a8291b46a9ddc6eeb621d38c0f699a756e47be0084b", + "retained_unchanged_sha256": { + "S2_SUPPLEMENTARY.json": "26f23bd8650a2495fd93f4364cbb17cc34f9eb1568758d406bec12ae2dab83a7", + "S3A_SUPPLEMENTARY.json": "9e9d420b01a0030919d2e49245e975a81bf3f561a7fa9fdf7cdc1efb8f02560e", + "S3B_SUPPLEMENTARY.json": "ec89b263b3a94ee3d4c2e6946c1f781138bbab822bbdd77f84f84b250064fc9b", + "SPEC.md": "3791ccdcb87e8d71fe9205e1e692ebca9e0f974ea3b5fbc4fbb3943882131f1c", + "TASK_INSTRUCTIONS.md": "f9937c3c7dff5a25ada453365d26c87fecf009d29518724f0c1e67d2b18afff3", + "UNIT_OUTPUT_ATTEMPT_01.sha256": "eed78af7775a79838e65ea3cb07e9fe09822d2d7a23007f294cbf0a0c98d1c7c", + "UNIT_OUTPUT_ATTEMPT_01.txt": "307486177b76602cbe68acae24c9560d501b3b866136d8e69802ec24c28e8be8", + "UNIT_OUTPUT_ATTEMPT_02.sha256": "1de0c0052e66cc60668690bf43e29eb01808afd023525e517ba94beaab0db669", + "UNIT_OUTPUT_ATTEMPT_02.txt": "07144a7f1941162227f54fefd1961ed0f209e97282432723bbda534079582e4e", + "UNIT_OUTPUT_S1_FINAL.sha256": "91d9d408ed8d012f38ff892fa6712d129f4849d0ce0b579eaeb7cb1a3f84b704", + "UNIT_OUTPUT_S1_FINAL.txt": "cdca0cdd551ce76c6100c4dd90e04559551f9d88c054a19a2bc6a77e6572ae15", + "UNIT_OUTPUT_S2_ATTEMPT_01.sha256": "579254585137adf932f5e4a0eaa2b0ecd67d275ece6c7199bdafbee4b48f4f5d", + "UNIT_OUTPUT_S2_ATTEMPT_01.txt": "25953dfc5f8bc3759ae66f6403b162100fb0217c4476f308616b8ab78a2cc67e", + "UNIT_OUTPUT_S2_ATTEMPT_02.sha256": "f4094cc3a8924b79316f473b8b4027a4743036d9d9cf8b2ad0c492ff7b581756", + "UNIT_OUTPUT_S2_ATTEMPT_02.txt": "e26c986dda41b83143723e4c1c5b2ff1051a36b9a947b319341a2239cc3188de", + "UNIT_OUTPUT_S2_ATTEMPT_03.sha256": "d8f8f7a9be6b2fb1618a1ff03f9af5aa0e397373c5e8f9716dc47befa6e3bb83", + "UNIT_OUTPUT_S2_ATTEMPT_03.txt": "9d323abda9bfffa02faf3a9d5cb56aa87e647017c991eb55b4807cf734386698", + "UNIT_OUTPUT_S3A_ATTEMPT_01.sha256": "303396536b67929fca0fcb4617578bc546c4f65a674e5dcd2b485bb27c060082", + "UNIT_OUTPUT_S3A_ATTEMPT_01.txt": "5cf84b792b5f87cd4183f41cf3a846962a53dc0aa33049c3c55f290356584641", + "UNIT_OUTPUT_S3A_ATTEMPT_02.sha256": "76d72513d22720cb0c6fd2bb43ac5000b80144a680a64f635276de8fca47ca97", + "UNIT_OUTPUT_S3A_ATTEMPT_02.txt": "000152e51d23db3d4397583b3f4540f5ed0ae469010c993fa1d122fd51537431", + "UNIT_OUTPUT_S3A_ATTEMPT_03.sha256": "9625ff44edb36f93ffac168208b148f7f49b247bc4f641d2b35e7c03f4f10ce0", + "UNIT_OUTPUT_S3A_ATTEMPT_03.txt": "7c14e8ecf4540e412467408cad267d53358940c86f87a0c8e519b305153f3cb8", + "UNIT_OUTPUT_S3A_ATTEMPT_04.sha256": "caab1a3e97878fd0c273e818bc3cf481f0f5f5d3def557da2c5c51981b6dbd0f", + "UNIT_OUTPUT_S3A_ATTEMPT_04.txt": "02221ae41e5dd40ecdac0ec0d7ffc657f265d3194c3817583c2b88ad375f132b", + "UNIT_OUTPUT_S3B_ATTEMPT_01.sha256": "3af8110cac13104df8e85851491d781d3edff527bb168a626c9c0d3285fcc093", + "UNIT_OUTPUT_S3B_ATTEMPT_01.txt": "c89f4f1ca1ea9b985079cd236ffff4193fa5c76d9bfa28fa65ac08cfc93b569c", + "UNIT_OUTPUT_S3B_ATTEMPT_02.sha256": "8f5edcdb522ab51606374403d6bcec508029aa32260430ac715a4b5bbb610da2", + "UNIT_OUTPUT_S3B_ATTEMPT_02.txt": "7bd19a6a3c84385f754261d51779f05b6e39c116459086d5aad3a83afa7225c0", + "UNIT_OUTPUT_S3B_ATTEMPT_03.sha256": "a9f4348d6fdbe4bcbed3f19831a88131fb365107411d452a2237f14038e88e6b", + "UNIT_OUTPUT_S3B_ATTEMPT_03.txt": "0872061bbc2c1403d2cd04877b8456f3fead35236be008b1a07f02ae5d85b11a", + "UNIT_OUTPUT_S3B_ATTEMPT_04.sha256": "950e32a41ebfd325c86eb6810148d726316a1a455203e5c806692dcce82e017a", + "UNIT_OUTPUT_S3B_ATTEMPT_04.txt": "63204c3415c9b1719fa6aa596b714077a57f530896f979d12b89a15eb2d827e9", + "UNIT_OUTPUT_S3B_ATTEMPT_05.sha256": "4293e250807be76a74c0b743b6ed550f5038d50a34ac5f9e743c68b8c15e5564", + "UNIT_OUTPUT_S3B_ATTEMPT_05.txt": "bfcb263bf6d7f284fb2b20ee229d96b7c4a9bd7cd5e7b513df1d3ea32580ed6e", + "UNIT_OUTPUT_S3B_ATTEMPT_06.sha256": "e0b6b770ded4ead6f785d64f4f866916b3a8392ba5d330ed5820755e3c6497f0", + "UNIT_OUTPUT_S3B_ATTEMPT_06.txt": "7d9bf9c602a93aca06d03eb06025beeea35603d453e293c07e7a6f81ca9ca000", + "UNIT_OUTPUT_S3B_ATTEMPT_07.sha256": "d38c2f6c05976e05a553b80917d4bede994425a76cbcaaba274fd36836101a64", + "UNIT_OUTPUT_S3B_ATTEMPT_07.txt": "f7c7c045ea98a366810b7c309fc1a87a77ccc5d8e823750eebaa742c9529e2ca", + "UNIT_OUTPUT_S3B_ATTEMPT_08.sha256": "7b252056637268e05f3eaa28a6f75f64c9345e4e95031bdba93c33048e8807a6", + "UNIT_OUTPUT_S3B_ATTEMPT_08.txt": "19c3f115d6a73bf91413877878f5d5f9d78a3e253dae3ddba7dfec9b5d46eaba", + "UNIT_OUTPUT_S3B_ATTEMPT_09.sha256": "f603c6d559184e68909e2409114659a263af5d18a684be332cebffaf816b6bd0", + "UNIT_OUTPUT_S3B_ATTEMPT_09.txt": "8360a2065b303099d5c546b3e4aecc0cc0ab0c2c1e5120b8034b6a1a64317030", + "UNIT_OUTPUT_S4_ATTEMPT_01.sha256": "59f15ed56cd9e56efbd40fd22b2d76ba53b86fc890cc0f094a8913ab5471b854", + "UNIT_OUTPUT_S4_ATTEMPT_01.txt": "ff9620ce295f2f2edc25e9b0014ac4db221e1b26e8ba1b0f20c20e7e5d045ce9", + "UNIT_OUTPUT_S4_ATTEMPT_02.sha256": "be7112d1386315b7a86c570122c21972e4650c7cf0f84c69ab647b25649a5172", + "UNIT_OUTPUT_S4_ATTEMPT_02.txt": "140d2c270f7c15297bed638c23dd38295381eebacc123fccdc112d32162dcefe", + "UNIT_OUTPUT_S4_ATTEMPT_03.sha256": "9debd9e5bea0735ca49935e5b3e410ba8546248ab64e93941cdfcfe23ee39aa0", + "UNIT_OUTPUT_S4_ATTEMPT_03.txt": "9f27f201325809a590375b7842101ef6b7d08c7de0aa4e66b4de2b7f7fd673d1", + "UNIT_OUTPUT_S4_ATTEMPT_04.sha256": "831b0269c0e99cb380be82f66bf262885fee1059a2ac130a0d5f764516d6fe29", + "UNIT_OUTPUT_S4_ATTEMPT_04.txt": "76738bb4138955e5fec02a93358c55446183492e99fd4d4360ac7fad58caacf9", + "UNIT_OUTPUT_S4_ATTEMPT_05.sha256": "923da4ffe041c211522a495f1f3b8493034e50fa728e9193af53f0323acef7cd", + "UNIT_OUTPUT_S4_ATTEMPT_05.txt": "aa13731a56337065e1a74acbfb640d56655cb4f774c9780dc265c40cf097101e", + "check_eq.py": "30682d2b462fd09de470bff52198303b7e86bb25c92e372103bcade11c3a7418", + "compare_versions.py": "1324e9e689a2885bd85f58a54f974d8a198e09fd3542123c6f597442e1437263", + "eq_probe.gd": "f933cad2a7ad4905fec15228ceb75ecb0ed100c64200a41feb80ba9702cf88fb", + "references/OPT_CONTRACT_T1.md": "ad9f3d76f3500b39263fb898d7c64588b4b47c9e11b456f938195261fd054d16", + "references/OPUS_D2_SCOPE_CLARIFICATION.txt": "5775e7b512d9e90dbcfbcb181f5b64dc0fa8207e0947c0a4a6a5c9195565f9bd", + "references/OPUS_STARTUP_LIFECYCLE_CLARIFICATION.txt": "967aebf27ff412f7a16ce771ef7d68abf8cfde0bb76ed19cf6dbf2817ca7acc6", + "registration/ACCEPTANCE_BASELINE.json": "84628bc21205387f8a7143031bdc50c9f68a767d350e6c34b32e0ba1c7059337", + "registration/CONFIG_PROPOSAL.json": "775fbbb97cda8b4d4991defdf7871b0fc79f489f4dea34c1733d4830426cf1df", + "registration/REGISTRATION_PROPOSAL.json": "9590fc853a4df8d50cc0d269d23bd9c844dc6931590ff6f24ebf95bb54a8d135", + "registration/ROOT_PROPOSAL_BYTE_TRANSFER.json": "63197f650849084f769e487a76458361886a37090042f1e351851c75b0384da2" + }, + "retained_test_bodies": { + "count": 134, + "all_AST_unchanged": true, + "original_file_sha256": "cb742b252dbc278113b3c11c2431adac35b0c2e201a762a8ea1ac926e4af414b", + "method": "Retained prefix plus original unittest main reproduces exact original file SHA; no external retained tree access needed." + }, + "history": { + "prior_provider_exit": 124, + "prior_run_submitted": false, + "supplementary_assert_failure": "Retained in original raw stdout referenced by RETAINED_S4_RETURN.json; not relabeled successful.", + "late_unit06": "134 tests, 206.531 seconds, OK; no process exit receipt; final after-fix full run still required.", + "current_read_failure": "PermissionError reading external retained test file; no file changed. Replaced verification with exact prefix reconstruction checked against Root original SHA." + }, + "original_credit": 0, + "formal_acceptance": false, + "completion_evidence": { + "scope": "local unit only; no native, accepted S, Q measurement or product PASS", + "tests": 146, + "retained_tests": 134, + "added_tests": 12, + "command": "python3 -B test_eq.py", + "raw": "UNIT_OUTPUT_S4_ATTEMPT_10.txt", + "sha256": "ff6fc0065772434f9ca35a1267e24d199057e339869a868942a41829327503bb", + "unittest_seconds": 293.277, + "wall_seconds": 293.5742515, + "exit_code": 0, + "full_runs_after_changes": 1, + "targeted_attempts": { + "07": "8 tests; one new mock failure, retained unchanged", + "08": "9 tests, OK, exit 0", + "09": "3 tests, OK, exit 0" + }, + "late_unit06_hashes_preserved": true, + "formal_validations_pending": [ + "p28-02-eq-unit", + "p28-02-eq-native-verify" + ], + "all_six_acceptance_conditions_pending": true + } +} diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT.sha256 new file mode 100644 index 0000000..5f5577b --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT.sha256 @@ -0,0 +1 @@ +ff6fc0065772434f9ca35a1267e24d199057e339869a868942a41829327503bb UNIT_OUTPUT.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT.txt new file mode 100644 index 0000000..ee7919a --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT.txt @@ -0,0 +1,154 @@ +test_all_operations (__main__.Diffs) ... ok +test_invalid_operations (__main__.Diffs) ... ok +test_reconstruction_and_proofs (__main__.Diffs) ... ok +test_attempt_to_normalize_violation_rejected (__main__.Normalization) ... ok +test_environment_values_differ_but_normal_form_equal (__main__.Normalization) ... ok +test_every_save_event_reversible (__main__.Normalization) ... ok +test_f3_keeps_relative_paths_and_words (__main__.Normalization) ... ok +test_guard_mismatch (__main__.Normalization) ... ok +test_nested_lookalike_is_not_eligible (__main__.Normalization) ... ok +test_original_transport_sha_detects_forged_timing (__main__.Normalization) ... ok +test_partial_timing_payload_rejected (__main__.Normalization) ... ok +test_prefix_boundary_and_reserved_token (__main__.Normalization) ... ok +test_sidecar_missing_duplicate_and_forged_paths (__main__.Normalization) ... ok +test_snapshot_and_latest_reversible (__main__.Normalization) ... ok +test_snapshot_event_outside_recent_is_not_eligible (__main__.Normalization) ... ok +test_wrong_event_and_source_are_preserved (__main__.Normalization) ... ok +test_wrong_timing_type_and_negative (__main__.Normalization) ... ok +test_all_events_beyond_recent_window (__main__.Reports) ... ok +test_all_semantic_layers_compared (__main__.Reports) ... ok +test_digest_alone_is_not_enough (__main__.Reports) ... ok +test_event_original_types_and_order (__main__.Reports) ... ok +test_event_start_and_ids (__main__.Reports) ... ok +test_exclusions_keep_actual_values (__main__.Reports) ... ok +test_handler_sets_and_counts (__main__.Reports) ... ok +test_observation_full_layers (__main__.Reports) ... ok +test_product_digest_self_consistency (__main__.Reports) ... ok +test_same_report (__main__.Reports) ... ok +test_scenario_existing_failures_preserved (__main__.Reports) ... ok +test_timing_digest_rule (__main__.Reports) ... ok +test_unknown_or_missing_fields_rejected (__main__.Reports) ... ok +test_violation_presence_and_difference (__main__.Reports) ... ok +test_O_cadence (__main__.S2Format) ... ok +test_counter_and_published_ids_binding (__main__.S2Format) ... ok +test_diff_and_same_as_S_transport (__main__.S2Format) ... ok +test_digest_and_scenario_contradiction (__main__.S2Format) ... ok +test_event_no_drop_duplicate_remap (__main__.S2Format) ... ok +test_event_original_field_types_mandatory (__main__.S2Format) ... ok +test_guard_actual_not_assumed (__main__.S2Format) ... ok +test_harness_digest_allows_only_dictionary_order (__main__.S2Format) ... ok +test_join_is_copy_and_retains_normalization_proof (__main__.S2Format) ... ok +test_kernel_cache_contradictions (__main__.S2Format) ... ok +test_lifecycle_guard_errors_and_boundaries (__main__.S2Format) ... ok +test_missing_full_state_not_digest_only (__main__.S2Format) ... ok +test_normalized_digest_and_raw_tree_are_both_bound (__main__.S2Format) ... ok +test_product_event_shape_and_typed_array (__main__.S2Format) ... ok +test_raw_observation_binding (__main__.S2Format) ... ok +test_roundtrip_tree_sha_and_raw_sha (__main__.S2Format) ... ok +test_s2_valid_and_not_formal_acceptance (__main__.S2Format) ... ok +test_state_witness_and_observation_mutation (__main__.S2Format) ... ok +test_stdout_exactly_one_line (__main__.S2Format) ... ok +test_autoload_class_and_script_import (__main__.S2Static) ... ok +test_comment_does_not_supply_proof (__main__.S2Static) ... ok +test_current_probe (__main__.S2Static) ... ok +test_full_state_and_godot_roundtrip_required (__main__.S2Static) ... ok +test_no_changes_outside_preparation_or_step (__main__.S2Static) ... ok +test_no_event_cap_or_duplicate_report (__main__.S2Static) ... ok +test_pause_and_step_arguments (__main__.S2Static) ... ok +test_textual_stringname_ordering (__main__.S2Static) ... ok +test_unlisted_live_method_and_late_preparation (__main__.S2Static) ... ok +test_variant_inference (__main__.S2Static) ... ok +test_X_recent_limit_and_counter (__main__.S3a) ... ok +test_duplicate_JSON_key_rejected (__main__.S3a) ... ok +test_e3_NA_cannot_be_PASS_or_applied (__main__.S3a) ... ok +test_e3_coverage_input_and_event_count_binding (__main__.S3a) ... ok +test_e3_invented_codes_and_missing_load_code (__main__.S3a) ... ok +test_e3_valid_R_and_O_records (__main__.S3a) ... ok +test_envelope_duplicates_not_defect (__main__.S3a) ... ok +test_event_count_defect_not_silently_accepted (__main__.S3a) ... ok +test_exact_phase_keys (__main__.S3a) ... ok +test_interval_gap_rejected (__main__.S3a) ... ok +test_invalid_input_accepted_is_not_PASS (__main__.S3a) ... ok +test_load_payload_and_pause_outcome (__main__.S3a) ... ok +test_operation_moved_outside_scenario_rejected (__main__.S3a) ... ok +test_package_fixed_mutations_and_hashes (__main__.S3a) ... ok +test_probe_connection_required (__main__.S3a) ... ok +test_rejection_mutation_retained_as_defect (__main__.S3a) ... ok +test_save_refusal_makes_load_NA (__main__.S3a) ... ok +test_scenario_mutation_static_boundary (__main__.S3a) ... ok +test_signals_all_minutes_and_order (__main__.S3a) ... ok +test_E5_cached_digest_defect_is_comparable (__main__.S3b) ... ok +test_NA_not_PASS (__main__.S3b) ... ok +test_aliasing_cannot_be_PASS (__main__.S3b) ... ok +test_aliasing_missing_record (__main__.S3b) ... ok +test_all_paths_and_ownership_R_O (__main__.S3b) ... ok +test_digest_defect_other_checkpoint_still_rejected (__main__.S3b) ... ok +test_digest_materialization_required (__main__.S3b) ... ok +test_empty_registry_not_NA (__main__.S3b) ... ok +test_event_count_mismatch (__main__.S3b) ... ok +test_facts_normalization_is_reversible (__main__.S3b) ... ok +test_first_placeable_choice (__main__.S3b) ... ok +test_interval_gap (__main__.S3b) ... ok +test_joined_s3b_self_comparison (__main__.S3b) ... ok +test_load_X_not_digest_only (__main__.S3b) ... ok +test_load_extra_event (__main__.S3b) ... ok +test_missing_path_and_combination (__main__.S3b) ... ok +test_missing_preview_observation (__main__.S3b) ... ok +test_missing_trial (__main__.S3b) ... ok +test_nested_mutation_required (__main__.S3b) ... ok +test_no_staleness_assertion_for_non_tick (__main__.S3b) ... ok +test_ownership_fact_dictionary_order_fallback (__main__.S3b) ... ok +test_path_order (__main__.S3b) ... ok +test_restore_extra_event (__main__.S3b) ... ok +test_signal_facts_cannot_be_dropped (__main__.S3b) ... ok +test_sort_rule_rejected (__main__.S3b) ... ok +test_static_handler_and_outside_mutations (__main__.S3b) ... ok +test_unpreviewed_choice (__main__.S3b) ... ok +test_wrong_registry_in_either_role (__main__.S3b) ... ok +test_checkout_temp_destination_rejected (__main__.S4Bundle) ... ok +test_existing_output_never_overwritten (__main__.S4Bundle) ... ok +test_import_closure_rejections (__main__.S4Bundle) ... ok +test_missing_bundle_manifest_seal_and_changed_bytes (__main__.S4Bundle) ... ok +test_missing_private_evidence_and_extra_rejected (__main__.S4Bundle) ... ok +test_missing_profile_not_export_success (__main__.S4Bundle) ... ok +test_phase_role_pid_audio_and_guard_rejected (__main__.S4Bundle) ... ok +test_rebound_lifecycle_and_scenario_contradictions (__main__.S4Bundle) ... ok +test_seal_normal_and_changes_not_native_proof (__main__.S4Bundle) ... ok +test_synthetic_phase_all_real_checkers_not_native_proof (__main__.S4Bundle) ... ok +test_copied_manifest_root_and_destination_count_rejected (__main__.S4NativeBundleLogic) ... ok +test_failure_keeps_raw_and_no_bundle_without_starting_engine (__main__.S4NativeBundleLogic) ... ok +test_gate_none_success_not_boolean (__main__.S4NativeBundleLogic) ... ok +test_receipt_and_source_rejection_matrix (__main__.S4NativeBundleLogic) ... ok +test_synthetic_full_bundle_positive_not_native_evidence (__main__.S4NativeBundleLogic) ... ok +test_check_accepts_true (__main__.S4ProbeAdmission) ... ok +test_check_rejects_false_all_errors (__main__.S4ProbeAdmission) ... ok +test_run_admission_accepts_true_mock_launch_only (__main__.S4ProbeAdmission) ... ok +test_run_admission_rejects_false_without_engine (__main__.S4ProbeAdmission) ... ok +test_nine_original_destinations_required (__main__.S4RemainingBindings) ... ok +test_nonzero_determinism_rejected_after_real_join (__main__.S4RemainingBindings) ... ok +test_owned_lifecycle_exit_diagnostic_and_profile_rejections (__main__.S4RemainingBindings) ... ok +test_verifier_accepts_true_recomputes_raw (__main__.S4RemainingBindings) ... ok +test_verifier_rejects_false_with_every_error (__main__.S4RemainingBindings) ... ok +test_cached_verdict_not_trusted (__main__.S4StoredResultBindings) ... ok +test_missing_sidecar_rejected_after_seal (__main__.S4StoredResultBindings) ... ok +test_raw_joined_substitution_rejected_after_seal (__main__.S4StoredResultBindings) ... ok +test_fixed_scenario_paths (__main__.SourcesAndMetrics) ... ok +test_metric_ranges (__main__.SourcesAndMetrics) ... ok +test_source_closure_synthetic_registered_map (__main__.SourcesAndMetrics) ... ok +test_source_pin_is_not_caller_controlled (__main__.SourcesAndMetrics) ... ok +test_array_order_and_all_differences (__main__.TypedTrees) ... ok +test_components_and_sha (__main__.TypedTrees) ... ok +test_deep_state_not_truncated (__main__.TypedTrees) ... ok +test_duplicate_textual_keys_rejected (__main__.TypedTrees) ... ok +test_exact_and_types (__main__.TypedTrees) ... ok +test_nested_order_all_paths (__main__.TypedTrees) ... ok +test_nonstring_keys_keep_types_and_values (__main__.TypedTrees) ... ok +test_unsupported_and_malformed (__main__.TypedTrees) ... ok + +---------------------------------------------------------------------- +Ran 146 tests in 293.277s + +OK + +exit_code=0 +wall_seconds=293.5742515 diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_ATTEMPT_01.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_ATTEMPT_01.sha256 new file mode 100644 index 0000000..2f0dce4 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_ATTEMPT_01.sha256 @@ -0,0 +1 @@ +307486177b76602cbe68acae24c9560d501b3b866136d8e69802ec24c28e8be8 UNIT_OUTPUT_ATTEMPT_01.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_ATTEMPT_01.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_ATTEMPT_01.txt new file mode 100644 index 0000000..84d2586 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_ATTEMPT_01.txt @@ -0,0 +1,48 @@ +test_all_operations (__main__.Diffs) ... ok +test_invalid_operations (__main__.Diffs) ... ok +test_reconstruction_and_proofs (__main__.Diffs) ... ok +test_attempt_to_normalize_violation_rejected (__main__.Normalization) ... ok +test_environment_values_differ_but_normal_form_equal (__main__.Normalization) ... ok +test_every_save_event_reversible (__main__.Normalization) ... ok +test_guard_mismatch (__main__.Normalization) ... ok +test_nested_lookalike_is_not_eligible (__main__.Normalization) ... ok +test_original_transport_sha_detects_forged_timing (__main__.Normalization) ... ok +test_sidecar_missing_duplicate_and_forged_paths (__main__.Normalization) ... test_snapshot_and_latest_reversible (__main__.Normalization) ... ok +test_snapshot_event_outside_recent_is_not_eligible (__main__.Normalization) ... ok +test_wrong_event_and_source_are_preserved (__main__.Normalization) ... ok +test_wrong_timing_type_and_negative (__main__.Normalization) ... ok +test_all_semantic_layers_compared (__main__.Reports) ... ok +test_digest_alone_is_not_enough (__main__.Reports) ... ok +test_event_start_and_ids (__main__.Reports) ... ok +test_exclusions_keep_actual_values (__main__.Reports) ... ok +test_handler_sets_and_counts (__main__.Reports) ... ok +test_observation_full_layers (__main__.Reports) ... ok +test_product_digest_self_consistency (__main__.Reports) ... ok +test_same_report (__main__.Reports) ... ok +test_scenario_existing_failures_preserved (__main__.Reports) ... ok +test_timing_digest_rule (__main__.Reports) ... ok +test_unknown_or_missing_fields_rejected (__main__.Reports) ... ok +test_violation_presence_and_difference (__main__.Reports) ... ok +test_metric_ranges (__main__.SourcesAndMetrics) ... ok +test_source_closure_synthetic_registered_map (__main__.SourcesAndMetrics) ... ok +test_source_pin_is_not_caller_controlled (__main__.SourcesAndMetrics) ... ok +test_array_order_and_all_differences (__main__.TypedTrees) ... ok +test_components_and_sha (__main__.TypedTrees) ... ok +test_deep_state_not_truncated (__main__.TypedTrees) ... ok +test_duplicate_textual_keys_rejected (__main__.TypedTrees) ... ok +test_exact_and_types (__main__.TypedTrees) ... ok +test_nested_order_all_paths (__main__.TypedTrees) ... ok +test_unsupported_and_malformed (__main__.TypedTrees) ... ok + +====================================================================== +FAIL: test_sidecar_missing_duplicate_and_forged_paths (__main__.Normalization) (bad={'entries': [{'event_index': 0, 'path': [['key', [4, 'payload']], ['key', [4, 'duration_us']]], 'key': 'duration_us', 'original_node': [2, 7]}, {'event_index': 0, 'path': [['key', [4, 'payload']], ['key', [4, 'runtime_duration_us']]], 'key': 'runtime_duration_us', 'original_node': [2, 8]}], 'violations': [], 'profile_root': {'root': '/private/a', 'actual_user_data_dir': '/private/a', 'matches_guard': True}}) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 218, in test_sidecar_missing_duplicate_and_forged_paths + eq.restore_events(n, bad, profile()) +AssertionError: EvidenceError not raised + +---------------------------------------------------------------------- +Ran 36 tests in 0.847s + +FAILED (failures=1) diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_ATTEMPT_02.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_ATTEMPT_02.sha256 new file mode 100644 index 0000000..537ecd1 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_ATTEMPT_02.sha256 @@ -0,0 +1 @@ +07144a7f1941162227f54fefd1961ed0f209e97282432723bbda534079582e4e UNIT_OUTPUT_ATTEMPT_02.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_ATTEMPT_02.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_ATTEMPT_02.txt new file mode 100644 index 0000000..f3f8f1e --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_ATTEMPT_02.txt @@ -0,0 +1,46 @@ +test_all_operations (__main__.Diffs) ... ok +test_invalid_operations (__main__.Diffs) ... ok +test_reconstruction_and_proofs (__main__.Diffs) ... ok +test_attempt_to_normalize_violation_rejected (__main__.Normalization) ... ok +test_environment_values_differ_but_normal_form_equal (__main__.Normalization) ... ok +test_every_save_event_reversible (__main__.Normalization) ... ok +test_f3_keeps_relative_paths_and_words (__main__.Normalization) ... ok +test_guard_mismatch (__main__.Normalization) ... ok +test_nested_lookalike_is_not_eligible (__main__.Normalization) ... ok +test_original_transport_sha_detects_forged_timing (__main__.Normalization) ... ok +test_prefix_boundary_and_reserved_token (__main__.Normalization) ... ok +test_sidecar_missing_duplicate_and_forged_paths (__main__.Normalization) ... ok +test_snapshot_and_latest_reversible (__main__.Normalization) ... ok +test_snapshot_event_outside_recent_is_not_eligible (__main__.Normalization) ... ok +test_wrong_event_and_source_are_preserved (__main__.Normalization) ... ok +test_wrong_timing_type_and_negative (__main__.Normalization) ... ok +test_all_events_beyond_recent_window (__main__.Reports) ... ok +test_all_semantic_layers_compared (__main__.Reports) ... ok +test_digest_alone_is_not_enough (__main__.Reports) ... ok +test_event_original_types_and_order (__main__.Reports) ... ok +test_event_start_and_ids (__main__.Reports) ... ok +test_exclusions_keep_actual_values (__main__.Reports) ... ok +test_handler_sets_and_counts (__main__.Reports) ... ok +test_observation_full_layers (__main__.Reports) ... ok +test_product_digest_self_consistency (__main__.Reports) ... ok +test_same_report (__main__.Reports) ... ok +test_scenario_existing_failures_preserved (__main__.Reports) ... ok +test_timing_digest_rule (__main__.Reports) ... ok +test_unknown_or_missing_fields_rejected (__main__.Reports) ... ok +test_violation_presence_and_difference (__main__.Reports) ... ok +test_fixed_scenario_paths (__main__.SourcesAndMetrics) ... ok +test_metric_ranges (__main__.SourcesAndMetrics) ... ok +test_source_closure_synthetic_registered_map (__main__.SourcesAndMetrics) ... ok +test_source_pin_is_not_caller_controlled (__main__.SourcesAndMetrics) ... ok +test_array_order_and_all_differences (__main__.TypedTrees) ... ok +test_components_and_sha (__main__.TypedTrees) ... ok +test_deep_state_not_truncated (__main__.TypedTrees) ... ok +test_duplicate_textual_keys_rejected (__main__.TypedTrees) ... ok +test_exact_and_types (__main__.TypedTrees) ... ok +test_nested_order_all_paths (__main__.TypedTrees) ... ok +test_unsupported_and_malformed (__main__.TypedTrees) ... ok + +---------------------------------------------------------------------- +Ran 41 tests in 1.382s + +OK diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S1_FINAL.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S1_FINAL.sha256 new file mode 100644 index 0000000..4c0d38a --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S1_FINAL.sha256 @@ -0,0 +1 @@ +cdca0cdd551ce76c6100c4dd90e04559551f9d88c054a19a2bc6a77e6572ae15 UNIT_OUTPUT_S1_FINAL.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S1_FINAL.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S1_FINAL.txt new file mode 100644 index 0000000..b66df1a --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S1_FINAL.txt @@ -0,0 +1,48 @@ +test_all_operations (__main__.Diffs) ... ok +test_invalid_operations (__main__.Diffs) ... ok +test_reconstruction_and_proofs (__main__.Diffs) ... ok +test_attempt_to_normalize_violation_rejected (__main__.Normalization) ... ok +test_environment_values_differ_but_normal_form_equal (__main__.Normalization) ... ok +test_every_save_event_reversible (__main__.Normalization) ... ok +test_f3_keeps_relative_paths_and_words (__main__.Normalization) ... ok +test_guard_mismatch (__main__.Normalization) ... ok +test_nested_lookalike_is_not_eligible (__main__.Normalization) ... ok +test_original_transport_sha_detects_forged_timing (__main__.Normalization) ... ok +test_partial_timing_payload_rejected (__main__.Normalization) ... ok +test_prefix_boundary_and_reserved_token (__main__.Normalization) ... ok +test_sidecar_missing_duplicate_and_forged_paths (__main__.Normalization) ... ok +test_snapshot_and_latest_reversible (__main__.Normalization) ... ok +test_snapshot_event_outside_recent_is_not_eligible (__main__.Normalization) ... ok +test_wrong_event_and_source_are_preserved (__main__.Normalization) ... ok +test_wrong_timing_type_and_negative (__main__.Normalization) ... ok +test_all_events_beyond_recent_window (__main__.Reports) ... ok +test_all_semantic_layers_compared (__main__.Reports) ... ok +test_digest_alone_is_not_enough (__main__.Reports) ... ok +test_event_original_types_and_order (__main__.Reports) ... ok +test_event_start_and_ids (__main__.Reports) ... ok +test_exclusions_keep_actual_values (__main__.Reports) ... ok +test_handler_sets_and_counts (__main__.Reports) ... ok +test_observation_full_layers (__main__.Reports) ... ok +test_product_digest_self_consistency (__main__.Reports) ... ok +test_same_report (__main__.Reports) ... ok +test_scenario_existing_failures_preserved (__main__.Reports) ... ok +test_timing_digest_rule (__main__.Reports) ... ok +test_unknown_or_missing_fields_rejected (__main__.Reports) ... ok +test_violation_presence_and_difference (__main__.Reports) ... ok +test_fixed_scenario_paths (__main__.SourcesAndMetrics) ... ok +test_metric_ranges (__main__.SourcesAndMetrics) ... ok +test_source_closure_synthetic_registered_map (__main__.SourcesAndMetrics) ... ok +test_source_pin_is_not_caller_controlled (__main__.SourcesAndMetrics) ... ok +test_array_order_and_all_differences (__main__.TypedTrees) ... ok +test_components_and_sha (__main__.TypedTrees) ... ok +test_deep_state_not_truncated (__main__.TypedTrees) ... ok +test_duplicate_textual_keys_rejected (__main__.TypedTrees) ... ok +test_exact_and_types (__main__.TypedTrees) ... ok +test_nested_order_all_paths (__main__.TypedTrees) ... ok +test_nonstring_keys_keep_types_and_values (__main__.TypedTrees) ... ok +test_unsupported_and_malformed (__main__.TypedTrees) ... ok + +---------------------------------------------------------------------- +Ran 43 tests in 1.432s + +OK diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S2_ATTEMPT_01.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S2_ATTEMPT_01.sha256 new file mode 100644 index 0000000..9f36d0d --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S2_ATTEMPT_01.sha256 @@ -0,0 +1 @@ +25953dfc5f8bc3759ae66f6403b162100fb0217c4476f308616b8ab78a2cc67e UNIT_OUTPUT_S2_ATTEMPT_01.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S2_ATTEMPT_01.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S2_ATTEMPT_01.txt new file mode 100644 index 0000000..5a727e7 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S2_ATTEMPT_01.txt @@ -0,0 +1,73 @@ +test_all_operations (__main__.Diffs) ... ok +test_invalid_operations (__main__.Diffs) ... ok +test_reconstruction_and_proofs (__main__.Diffs) ... ok +test_attempt_to_normalize_violation_rejected (__main__.Normalization) ... ok +test_environment_values_differ_but_normal_form_equal (__main__.Normalization) ... ok +test_every_save_event_reversible (__main__.Normalization) ... ok +test_f3_keeps_relative_paths_and_words (__main__.Normalization) ... ok +test_guard_mismatch (__main__.Normalization) ... ok +test_nested_lookalike_is_not_eligible (__main__.Normalization) ... ok +test_original_transport_sha_detects_forged_timing (__main__.Normalization) ... ok +test_partial_timing_payload_rejected (__main__.Normalization) ... ok +test_prefix_boundary_and_reserved_token (__main__.Normalization) ... ok +test_sidecar_missing_duplicate_and_forged_paths (__main__.Normalization) ... ok +test_snapshot_and_latest_reversible (__main__.Normalization) ... ok +test_snapshot_event_outside_recent_is_not_eligible (__main__.Normalization) ... ok +test_wrong_event_and_source_are_preserved (__main__.Normalization) ... ok +test_wrong_timing_type_and_negative (__main__.Normalization) ... ok +test_all_events_beyond_recent_window (__main__.Reports) ... ok +test_all_semantic_layers_compared (__main__.Reports) ... ok +test_digest_alone_is_not_enough (__main__.Reports) ... ok +test_event_original_types_and_order (__main__.Reports) ... ok +test_event_start_and_ids (__main__.Reports) ... ok +test_exclusions_keep_actual_values (__main__.Reports) ... ok +test_handler_sets_and_counts (__main__.Reports) ... ok +test_observation_full_layers (__main__.Reports) ... ok +test_product_digest_self_consistency (__main__.Reports) ... ok +test_same_report (__main__.Reports) ... ok +test_scenario_existing_failures_preserved (__main__.Reports) ... ok +test_timing_digest_rule (__main__.Reports) ... ok +test_unknown_or_missing_fields_rejected (__main__.Reports) ... ok +test_violation_presence_and_difference (__main__.Reports) ... ok +test_O_cadence (__main__.S2Format) ... ok +test_counter_and_published_ids_binding (__main__.S2Format) ... ok +test_diff_and_same_as_S_transport (__main__.S2Format) ... ok +test_digest_and_scenario_contradiction (__main__.S2Format) ... ok +test_event_no_drop_duplicate_remap (__main__.S2Format) ... ok +test_event_original_field_types_mandatory (__main__.S2Format) ... ok +test_guard_actual_not_assumed (__main__.S2Format) ... ok +test_join_is_copy_and_retains_normalization_proof (__main__.S2Format) ... ok +test_kernel_cache_contradictions (__main__.S2Format) ... ok +test_missing_full_state_not_digest_only (__main__.S2Format) ... ok +test_product_event_shape_and_typed_array (__main__.S2Format) ... ok +test_raw_observation_binding (__main__.S2Format) ... ok +test_roundtrip_tree_sha_and_raw_sha (__main__.S2Format) ... ok +test_s2_valid_and_not_formal_acceptance (__main__.S2Format) ... ok +test_state_witness_and_observation_mutation (__main__.S2Format) ... ok +test_stdout_exactly_one_line (__main__.S2Format) ... ok +test_autoload_class_and_script_import (__main__.S2Static) ... ok +test_comment_does_not_supply_proof (__main__.S2Static) ... ok +test_current_probe (__main__.S2Static) ... ok +test_full_state_and_godot_roundtrip_required (__main__.S2Static) ... ok +test_no_changes_outside_preparation_or_step (__main__.S2Static) ... ok +test_no_event_cap_or_duplicate_report (__main__.S2Static) ... ok +test_pause_and_step_arguments (__main__.S2Static) ... ok +test_textual_stringname_ordering (__main__.S2Static) ... ok +test_variant_inference (__main__.S2Static) ... ok +test_fixed_scenario_paths (__main__.SourcesAndMetrics) ... ok +test_metric_ranges (__main__.SourcesAndMetrics) ... ok +test_source_closure_synthetic_registered_map (__main__.SourcesAndMetrics) ... ok +test_source_pin_is_not_caller_controlled (__main__.SourcesAndMetrics) ... ok +test_array_order_and_all_differences (__main__.TypedTrees) ... ok +test_components_and_sha (__main__.TypedTrees) ... ok +test_deep_state_not_truncated (__main__.TypedTrees) ... ok +test_duplicate_textual_keys_rejected (__main__.TypedTrees) ... ok +test_exact_and_types (__main__.TypedTrees) ... ok +test_nested_order_all_paths (__main__.TypedTrees) ... ok +test_nonstring_keys_keep_types_and_values (__main__.TypedTrees) ... ok +test_unsupported_and_malformed (__main__.TypedTrees) ... ok + +---------------------------------------------------------------------- +Ran 68 tests in 4.042s + +OK diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S2_ATTEMPT_02.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S2_ATTEMPT_02.sha256 new file mode 100644 index 0000000..72de66f --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S2_ATTEMPT_02.sha256 @@ -0,0 +1 @@ +e26c986dda41b83143723e4c1c5b2ff1051a36b9a947b319341a2239cc3188de UNIT_OUTPUT_S2_ATTEMPT_02.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S2_ATTEMPT_02.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S2_ATTEMPT_02.txt new file mode 100644 index 0000000..58f25c9 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S2_ATTEMPT_02.txt @@ -0,0 +1,76 @@ +test_all_operations (__main__.Diffs) ... ok +test_invalid_operations (__main__.Diffs) ... ok +test_reconstruction_and_proofs (__main__.Diffs) ... ok +test_attempt_to_normalize_violation_rejected (__main__.Normalization) ... ok +test_environment_values_differ_but_normal_form_equal (__main__.Normalization) ... ok +test_every_save_event_reversible (__main__.Normalization) ... ok +test_f3_keeps_relative_paths_and_words (__main__.Normalization) ... ok +test_guard_mismatch (__main__.Normalization) ... ok +test_nested_lookalike_is_not_eligible (__main__.Normalization) ... ok +test_original_transport_sha_detects_forged_timing (__main__.Normalization) ... ok +test_partial_timing_payload_rejected (__main__.Normalization) ... ok +test_prefix_boundary_and_reserved_token (__main__.Normalization) ... ok +test_sidecar_missing_duplicate_and_forged_paths (__main__.Normalization) ... ok +test_snapshot_and_latest_reversible (__main__.Normalization) ... ok +test_snapshot_event_outside_recent_is_not_eligible (__main__.Normalization) ... ok +test_wrong_event_and_source_are_preserved (__main__.Normalization) ... ok +test_wrong_timing_type_and_negative (__main__.Normalization) ... ok +test_all_events_beyond_recent_window (__main__.Reports) ... ok +test_all_semantic_layers_compared (__main__.Reports) ... ok +test_digest_alone_is_not_enough (__main__.Reports) ... ok +test_event_original_types_and_order (__main__.Reports) ... ok +test_event_start_and_ids (__main__.Reports) ... ok +test_exclusions_keep_actual_values (__main__.Reports) ... ok +test_handler_sets_and_counts (__main__.Reports) ... ok +test_observation_full_layers (__main__.Reports) ... ok +test_product_digest_self_consistency (__main__.Reports) ... ok +test_same_report (__main__.Reports) ... ok +test_scenario_existing_failures_preserved (__main__.Reports) ... ok +test_timing_digest_rule (__main__.Reports) ... ok +test_unknown_or_missing_fields_rejected (__main__.Reports) ... ok +test_violation_presence_and_difference (__main__.Reports) ... ok +test_O_cadence (__main__.S2Format) ... ok +test_counter_and_published_ids_binding (__main__.S2Format) ... ok +test_diff_and_same_as_S_transport (__main__.S2Format) ... ok +test_digest_and_scenario_contradiction (__main__.S2Format) ... ok +test_event_no_drop_duplicate_remap (__main__.S2Format) ... ok +test_event_original_field_types_mandatory (__main__.S2Format) ... ok +test_guard_actual_not_assumed (__main__.S2Format) ... ok +test_join_is_copy_and_retains_normalization_proof (__main__.S2Format) ... ok +test_kernel_cache_contradictions (__main__.S2Format) ... ok +test_lifecycle_guard_errors_and_boundaries (__main__.S2Format) ... ok +test_missing_full_state_not_digest_only (__main__.S2Format) ... ok +test_normalized_digest_and_raw_tree_are_both_bound (__main__.S2Format) ... ok +test_product_event_shape_and_typed_array (__main__.S2Format) ... ok +test_raw_observation_binding (__main__.S2Format) ... ok +test_roundtrip_tree_sha_and_raw_sha (__main__.S2Format) ... ok +test_s2_valid_and_not_formal_acceptance (__main__.S2Format) ... ok +test_state_witness_and_observation_mutation (__main__.S2Format) ... ok +test_stdout_exactly_one_line (__main__.S2Format) ... ok +test_autoload_class_and_script_import (__main__.S2Static) ... ok +test_comment_does_not_supply_proof (__main__.S2Static) ... ok +test_current_probe (__main__.S2Static) ... ok +test_full_state_and_godot_roundtrip_required (__main__.S2Static) ... ok +test_no_changes_outside_preparation_or_step (__main__.S2Static) ... ok +test_no_event_cap_or_duplicate_report (__main__.S2Static) ... ok +test_pause_and_step_arguments (__main__.S2Static) ... ok +test_textual_stringname_ordering (__main__.S2Static) ... ok +test_unlisted_live_method_and_late_preparation (__main__.S2Static) ... ok +test_variant_inference (__main__.S2Static) ... ok +test_fixed_scenario_paths (__main__.SourcesAndMetrics) ... ok +test_metric_ranges (__main__.SourcesAndMetrics) ... ok +test_source_closure_synthetic_registered_map (__main__.SourcesAndMetrics) ... ok +test_source_pin_is_not_caller_controlled (__main__.SourcesAndMetrics) ... ok +test_array_order_and_all_differences (__main__.TypedTrees) ... ok +test_components_and_sha (__main__.TypedTrees) ... ok +test_deep_state_not_truncated (__main__.TypedTrees) ... ok +test_duplicate_textual_keys_rejected (__main__.TypedTrees) ... ok +test_exact_and_types (__main__.TypedTrees) ... ok +test_nested_order_all_paths (__main__.TypedTrees) ... ok +test_nonstring_keys_keep_types_and_values (__main__.TypedTrees) ... ok +test_unsupported_and_malformed (__main__.TypedTrees) ... ok + +---------------------------------------------------------------------- +Ran 71 tests in 4.371s + +OK diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S2_ATTEMPT_03.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S2_ATTEMPT_03.sha256 new file mode 100644 index 0000000..b794fcd --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S2_ATTEMPT_03.sha256 @@ -0,0 +1 @@ +9d323abda9bfffa02faf3a9d5cb56aa87e647017c991eb55b4807cf734386698 UNIT_OUTPUT_S2_ATTEMPT_03.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S2_ATTEMPT_03.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S2_ATTEMPT_03.txt new file mode 100644 index 0000000..6ae46c1 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S2_ATTEMPT_03.txt @@ -0,0 +1,77 @@ +test_all_operations (__main__.Diffs) ... ok +test_invalid_operations (__main__.Diffs) ... ok +test_reconstruction_and_proofs (__main__.Diffs) ... ok +test_attempt_to_normalize_violation_rejected (__main__.Normalization) ... ok +test_environment_values_differ_but_normal_form_equal (__main__.Normalization) ... ok +test_every_save_event_reversible (__main__.Normalization) ... ok +test_f3_keeps_relative_paths_and_words (__main__.Normalization) ... ok +test_guard_mismatch (__main__.Normalization) ... ok +test_nested_lookalike_is_not_eligible (__main__.Normalization) ... ok +test_original_transport_sha_detects_forged_timing (__main__.Normalization) ... ok +test_partial_timing_payload_rejected (__main__.Normalization) ... ok +test_prefix_boundary_and_reserved_token (__main__.Normalization) ... ok +test_sidecar_missing_duplicate_and_forged_paths (__main__.Normalization) ... ok +test_snapshot_and_latest_reversible (__main__.Normalization) ... ok +test_snapshot_event_outside_recent_is_not_eligible (__main__.Normalization) ... ok +test_wrong_event_and_source_are_preserved (__main__.Normalization) ... ok +test_wrong_timing_type_and_negative (__main__.Normalization) ... ok +test_all_events_beyond_recent_window (__main__.Reports) ... ok +test_all_semantic_layers_compared (__main__.Reports) ... ok +test_digest_alone_is_not_enough (__main__.Reports) ... ok +test_event_original_types_and_order (__main__.Reports) ... ok +test_event_start_and_ids (__main__.Reports) ... ok +test_exclusions_keep_actual_values (__main__.Reports) ... ok +test_handler_sets_and_counts (__main__.Reports) ... ok +test_observation_full_layers (__main__.Reports) ... ok +test_product_digest_self_consistency (__main__.Reports) ... ok +test_same_report (__main__.Reports) ... ok +test_scenario_existing_failures_preserved (__main__.Reports) ... ok +test_timing_digest_rule (__main__.Reports) ... ok +test_unknown_or_missing_fields_rejected (__main__.Reports) ... ok +test_violation_presence_and_difference (__main__.Reports) ... ok +test_O_cadence (__main__.S2Format) ... ok +test_counter_and_published_ids_binding (__main__.S2Format) ... ok +test_diff_and_same_as_S_transport (__main__.S2Format) ... ok +test_digest_and_scenario_contradiction (__main__.S2Format) ... ok +test_event_no_drop_duplicate_remap (__main__.S2Format) ... ok +test_event_original_field_types_mandatory (__main__.S2Format) ... ok +test_guard_actual_not_assumed (__main__.S2Format) ... ok +test_harness_digest_allows_only_dictionary_order (__main__.S2Format) ... ok +test_join_is_copy_and_retains_normalization_proof (__main__.S2Format) ... ok +test_kernel_cache_contradictions (__main__.S2Format) ... ok +test_lifecycle_guard_errors_and_boundaries (__main__.S2Format) ... ok +test_missing_full_state_not_digest_only (__main__.S2Format) ... ok +test_normalized_digest_and_raw_tree_are_both_bound (__main__.S2Format) ... ok +test_product_event_shape_and_typed_array (__main__.S2Format) ... ok +test_raw_observation_binding (__main__.S2Format) ... ok +test_roundtrip_tree_sha_and_raw_sha (__main__.S2Format) ... ok +test_s2_valid_and_not_formal_acceptance (__main__.S2Format) ... ok +test_state_witness_and_observation_mutation (__main__.S2Format) ... ok +test_stdout_exactly_one_line (__main__.S2Format) ... ok +test_autoload_class_and_script_import (__main__.S2Static) ... ok +test_comment_does_not_supply_proof (__main__.S2Static) ... ok +test_current_probe (__main__.S2Static) ... ok +test_full_state_and_godot_roundtrip_required (__main__.S2Static) ... ok +test_no_changes_outside_preparation_or_step (__main__.S2Static) ... ok +test_no_event_cap_or_duplicate_report (__main__.S2Static) ... ok +test_pause_and_step_arguments (__main__.S2Static) ... ok +test_textual_stringname_ordering (__main__.S2Static) ... ok +test_unlisted_live_method_and_late_preparation (__main__.S2Static) ... ok +test_variant_inference (__main__.S2Static) ... ok +test_fixed_scenario_paths (__main__.SourcesAndMetrics) ... ok +test_metric_ranges (__main__.SourcesAndMetrics) ... ok +test_source_closure_synthetic_registered_map (__main__.SourcesAndMetrics) ... ok +test_source_pin_is_not_caller_controlled (__main__.SourcesAndMetrics) ... ok +test_array_order_and_all_differences (__main__.TypedTrees) ... ok +test_components_and_sha (__main__.TypedTrees) ... ok +test_deep_state_not_truncated (__main__.TypedTrees) ... ok +test_duplicate_textual_keys_rejected (__main__.TypedTrees) ... ok +test_exact_and_types (__main__.TypedTrees) ... ok +test_nested_order_all_paths (__main__.TypedTrees) ... ok +test_nonstring_keys_keep_types_and_values (__main__.TypedTrees) ... ok +test_unsupported_and_malformed (__main__.TypedTrees) ... ok + +---------------------------------------------------------------------- +Ran 72 tests in 4.753s + +OK diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_01.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_01.sha256 new file mode 100644 index 0000000..44251a7 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_01.sha256 @@ -0,0 +1 @@ +5cf84b792b5f87cd4183f41cf3a846962a53dc0aa33049c3c55f290356584641 UNIT_OUTPUT_S3A_ATTEMPT_01.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_01.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_01.txt new file mode 100644 index 0000000..fc55009 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_01.txt @@ -0,0 +1,77 @@ +test_all_operations (__main__.Diffs) ... ok +test_invalid_operations (__main__.Diffs) ... ok +test_reconstruction_and_proofs (__main__.Diffs) ... ok +test_attempt_to_normalize_violation_rejected (__main__.Normalization) ... ok +test_environment_values_differ_but_normal_form_equal (__main__.Normalization) ... ok +test_every_save_event_reversible (__main__.Normalization) ... ok +test_f3_keeps_relative_paths_and_words (__main__.Normalization) ... ok +test_guard_mismatch (__main__.Normalization) ... ok +test_nested_lookalike_is_not_eligible (__main__.Normalization) ... ok +test_original_transport_sha_detects_forged_timing (__main__.Normalization) ... ok +test_partial_timing_payload_rejected (__main__.Normalization) ... ok +test_prefix_boundary_and_reserved_token (__main__.Normalization) ... ok +test_sidecar_missing_duplicate_and_forged_paths (__main__.Normalization) ... ok +test_snapshot_and_latest_reversible (__main__.Normalization) ... ok +test_snapshot_event_outside_recent_is_not_eligible (__main__.Normalization) ... ok +test_wrong_event_and_source_are_preserved (__main__.Normalization) ... ok +test_wrong_timing_type_and_negative (__main__.Normalization) ... ok +test_all_events_beyond_recent_window (__main__.Reports) ... ok +test_all_semantic_layers_compared (__main__.Reports) ... ok +test_digest_alone_is_not_enough (__main__.Reports) ... ok +test_event_original_types_and_order (__main__.Reports) ... ok +test_event_start_and_ids (__main__.Reports) ... ok +test_exclusions_keep_actual_values (__main__.Reports) ... ok +test_handler_sets_and_counts (__main__.Reports) ... ok +test_observation_full_layers (__main__.Reports) ... ok +test_product_digest_self_consistency (__main__.Reports) ... ok +test_same_report (__main__.Reports) ... ok +test_scenario_existing_failures_preserved (__main__.Reports) ... ok +test_timing_digest_rule (__main__.Reports) ... ok +test_unknown_or_missing_fields_rejected (__main__.Reports) ... ok +test_violation_presence_and_difference (__main__.Reports) ... ok +test_O_cadence (__main__.S2Format) ... ok +test_counter_and_published_ids_binding (__main__.S2Format) ... ok +test_diff_and_same_as_S_transport (__main__.S2Format) ... ok +test_digest_and_scenario_contradiction (__main__.S2Format) ... ok +test_event_no_drop_duplicate_remap (__main__.S2Format) ... ok +test_event_original_field_types_mandatory (__main__.S2Format) ... ok +test_guard_actual_not_assumed (__main__.S2Format) ... ok +test_harness_digest_allows_only_dictionary_order (__main__.S2Format) ... ok +test_join_is_copy_and_retains_normalization_proof (__main__.S2Format) ... ok +test_kernel_cache_contradictions (__main__.S2Format) ... ok +test_lifecycle_guard_errors_and_boundaries (__main__.S2Format) ... ok +test_missing_full_state_not_digest_only (__main__.S2Format) ... ok +test_normalized_digest_and_raw_tree_are_both_bound (__main__.S2Format) ... ok +test_product_event_shape_and_typed_array (__main__.S2Format) ... ok +test_raw_observation_binding (__main__.S2Format) ... ok +test_roundtrip_tree_sha_and_raw_sha (__main__.S2Format) ... ok +test_s2_valid_and_not_formal_acceptance (__main__.S2Format) ... ok +test_state_witness_and_observation_mutation (__main__.S2Format) ... ok +test_stdout_exactly_one_line (__main__.S2Format) ... ok +test_autoload_class_and_script_import (__main__.S2Static) ... ok +test_comment_does_not_supply_proof (__main__.S2Static) ... ok +test_current_probe (__main__.S2Static) ... ok +test_full_state_and_godot_roundtrip_required (__main__.S2Static) ... ok +test_no_changes_outside_preparation_or_step (__main__.S2Static) ... ok +test_no_event_cap_or_duplicate_report (__main__.S2Static) ... ok +test_pause_and_step_arguments (__main__.S2Static) ... ok +test_textual_stringname_ordering (__main__.S2Static) ... ok +test_unlisted_live_method_and_late_preparation (__main__.S2Static) ... ok +test_variant_inference (__main__.S2Static) ... ok +test_fixed_scenario_paths (__main__.SourcesAndMetrics) ... ok +test_metric_ranges (__main__.SourcesAndMetrics) ... ok +test_source_closure_synthetic_registered_map (__main__.SourcesAndMetrics) ... ok +test_source_pin_is_not_caller_controlled (__main__.SourcesAndMetrics) ... ok +test_array_order_and_all_differences (__main__.TypedTrees) ... ok +test_components_and_sha (__main__.TypedTrees) ... ok +test_deep_state_not_truncated (__main__.TypedTrees) ... ok +test_duplicate_textual_keys_rejected (__main__.TypedTrees) ... ok +test_exact_and_types (__main__.TypedTrees) ... ok +test_nested_order_all_paths (__main__.TypedTrees) ... ok +test_nonstring_keys_keep_types_and_values (__main__.TypedTrees) ... ok +test_unsupported_and_malformed (__main__.TypedTrees) ... ok + +---------------------------------------------------------------------- +Ran 72 tests in 4.846s + +OK diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_02.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_02.sha256 new file mode 100644 index 0000000..85fa1cd --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_02.sha256 @@ -0,0 +1 @@ +000152e51d23db3d4397583b3f4540f5ed0ae469010c993fa1d122fd51537431 UNIT_OUTPUT_S3A_ATTEMPT_02.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_02.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_02.txt new file mode 100644 index 0000000..2f58f57 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_02.txt @@ -0,0 +1,90 @@ +test_all_operations (__main__.Diffs) ... ok +test_invalid_operations (__main__.Diffs) ... ok +test_reconstruction_and_proofs (__main__.Diffs) ... ok +test_attempt_to_normalize_violation_rejected (__main__.Normalization) ... ok +test_environment_values_differ_but_normal_form_equal (__main__.Normalization) ... ok +test_every_save_event_reversible (__main__.Normalization) ... ok +test_f3_keeps_relative_paths_and_words (__main__.Normalization) ... ok +test_guard_mismatch (__main__.Normalization) ... ok +test_nested_lookalike_is_not_eligible (__main__.Normalization) ... ok +test_original_transport_sha_detects_forged_timing (__main__.Normalization) ... ok +test_partial_timing_payload_rejected (__main__.Normalization) ... ok +test_prefix_boundary_and_reserved_token (__main__.Normalization) ... ok +test_sidecar_missing_duplicate_and_forged_paths (__main__.Normalization) ... ok +test_snapshot_and_latest_reversible (__main__.Normalization) ... ok +test_snapshot_event_outside_recent_is_not_eligible (__main__.Normalization) ... ok +test_wrong_event_and_source_are_preserved (__main__.Normalization) ... ok +test_wrong_timing_type_and_negative (__main__.Normalization) ... ok +test_all_events_beyond_recent_window (__main__.Reports) ... ok +test_all_semantic_layers_compared (__main__.Reports) ... ok +test_digest_alone_is_not_enough (__main__.Reports) ... ok +test_event_original_types_and_order (__main__.Reports) ... ok +test_event_start_and_ids (__main__.Reports) ... ok +test_exclusions_keep_actual_values (__main__.Reports) ... ok +test_handler_sets_and_counts (__main__.Reports) ... ok +test_observation_full_layers (__main__.Reports) ... ok +test_product_digest_self_consistency (__main__.Reports) ... ok +test_same_report (__main__.Reports) ... ok +test_scenario_existing_failures_preserved (__main__.Reports) ... ok +test_timing_digest_rule (__main__.Reports) ... ok +test_unknown_or_missing_fields_rejected (__main__.Reports) ... ok +test_violation_presence_and_difference (__main__.Reports) ... ok +test_O_cadence (__main__.S2Format) ... ok +test_counter_and_published_ids_binding (__main__.S2Format) ... ok +test_diff_and_same_as_S_transport (__main__.S2Format) ... ok +test_digest_and_scenario_contradiction (__main__.S2Format) ... ok +test_event_no_drop_duplicate_remap (__main__.S2Format) ... ok +test_event_original_field_types_mandatory (__main__.S2Format) ... ok +test_guard_actual_not_assumed (__main__.S2Format) ... ok +test_harness_digest_allows_only_dictionary_order (__main__.S2Format) ... ok +test_join_is_copy_and_retains_normalization_proof (__main__.S2Format) ... ok +test_kernel_cache_contradictions (__main__.S2Format) ... ok +test_lifecycle_guard_errors_and_boundaries (__main__.S2Format) ... ok +test_missing_full_state_not_digest_only (__main__.S2Format) ... ok +test_normalized_digest_and_raw_tree_are_both_bound (__main__.S2Format) ... ok +test_product_event_shape_and_typed_array (__main__.S2Format) ... ok +test_raw_observation_binding (__main__.S2Format) ... ok +test_roundtrip_tree_sha_and_raw_sha (__main__.S2Format) ... ok +test_s2_valid_and_not_formal_acceptance (__main__.S2Format) ... ok +test_state_witness_and_observation_mutation (__main__.S2Format) ... ok +test_stdout_exactly_one_line (__main__.S2Format) ... ok +test_autoload_class_and_script_import (__main__.S2Static) ... ok +test_comment_does_not_supply_proof (__main__.S2Static) ... ok +test_current_probe (__main__.S2Static) ... ok +test_full_state_and_godot_roundtrip_required (__main__.S2Static) ... ok +test_no_changes_outside_preparation_or_step (__main__.S2Static) ... ok +test_no_event_cap_or_duplicate_report (__main__.S2Static) ... ok +test_pause_and_step_arguments (__main__.S2Static) ... ok +test_textual_stringname_ordering (__main__.S2Static) ... ok +test_unlisted_live_method_and_late_preparation (__main__.S2Static) ... ok +test_variant_inference (__main__.S2Static) ... ok +test_X_recent_limit_and_counter (__main__.S3a) ... ok +test_e3_NA_cannot_be_PASS_or_applied (__main__.S3a) ... ok +test_e3_coverage_input_and_event_count_binding (__main__.S3a) ... ok +test_e3_invented_codes_and_missing_load_code (__main__.S3a) ... ok +test_e3_valid_R_and_O_records (__main__.S3a) ... ok +test_envelope_duplicates_not_defect (__main__.S3a) ... ok +test_exact_phase_keys (__main__.S3a) ... ok +test_invalid_input_accepted_is_not_PASS (__main__.S3a) ... ok +test_package_fixed_mutations_and_hashes (__main__.S3a) ... ok +test_probe_connection_required (__main__.S3a) ... ok +test_rejection_mutation_retained_as_defect (__main__.S3a) ... ok +test_scenario_mutation_static_boundary (__main__.S3a) ... ok +test_signals_all_minutes_and_order (__main__.S3a) ... ok +test_fixed_scenario_paths (__main__.SourcesAndMetrics) ... ok +test_metric_ranges (__main__.SourcesAndMetrics) ... ok +test_source_closure_synthetic_registered_map (__main__.SourcesAndMetrics) ... ok +test_source_pin_is_not_caller_controlled (__main__.SourcesAndMetrics) ... ok +test_array_order_and_all_differences (__main__.TypedTrees) ... ok +test_components_and_sha (__main__.TypedTrees) ... ok +test_deep_state_not_truncated (__main__.TypedTrees) ... ok +test_duplicate_textual_keys_rejected (__main__.TypedTrees) ... ok +test_exact_and_types (__main__.TypedTrees) ... ok +test_nested_order_all_paths (__main__.TypedTrees) ... ok +test_nonstring_keys_keep_types_and_values (__main__.TypedTrees) ... ok +test_unsupported_and_malformed (__main__.TypedTrees) ... ok + +---------------------------------------------------------------------- +Ran 85 tests in 15.941s + +OK diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_03.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_03.sha256 new file mode 100644 index 0000000..0b1c557 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_03.sha256 @@ -0,0 +1 @@ +7c14e8ecf4540e412467408cad267d53358940c86f87a0c8e519b305153f3cb8 UNIT_OUTPUT_S3A_ATTEMPT_03.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_03.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_03.txt new file mode 100644 index 0000000..270ef31 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_03.txt @@ -0,0 +1,96 @@ +test_all_operations (__main__.Diffs) ... ok +test_invalid_operations (__main__.Diffs) ... ok +test_reconstruction_and_proofs (__main__.Diffs) ... ok +test_attempt_to_normalize_violation_rejected (__main__.Normalization) ... ok +test_environment_values_differ_but_normal_form_equal (__main__.Normalization) ... ok +test_every_save_event_reversible (__main__.Normalization) ... ok +test_f3_keeps_relative_paths_and_words (__main__.Normalization) ... ok +test_guard_mismatch (__main__.Normalization) ... ok +test_nested_lookalike_is_not_eligible (__main__.Normalization) ... ok +test_original_transport_sha_detects_forged_timing (__main__.Normalization) ... ok +test_partial_timing_payload_rejected (__main__.Normalization) ... ok +test_prefix_boundary_and_reserved_token (__main__.Normalization) ... ok +test_sidecar_missing_duplicate_and_forged_paths (__main__.Normalization) ... ok +test_snapshot_and_latest_reversible (__main__.Normalization) ... ok +test_snapshot_event_outside_recent_is_not_eligible (__main__.Normalization) ... ok +test_wrong_event_and_source_are_preserved (__main__.Normalization) ... ok +test_wrong_timing_type_and_negative (__main__.Normalization) ... ok +test_all_events_beyond_recent_window (__main__.Reports) ... ok +test_all_semantic_layers_compared (__main__.Reports) ... ok +test_digest_alone_is_not_enough (__main__.Reports) ... ok +test_event_original_types_and_order (__main__.Reports) ... ok +test_event_start_and_ids (__main__.Reports) ... ok +test_exclusions_keep_actual_values (__main__.Reports) ... ok +test_handler_sets_and_counts (__main__.Reports) ... ok +test_observation_full_layers (__main__.Reports) ... ok +test_product_digest_self_consistency (__main__.Reports) ... ok +test_same_report (__main__.Reports) ... ok +test_scenario_existing_failures_preserved (__main__.Reports) ... ok +test_timing_digest_rule (__main__.Reports) ... ok +test_unknown_or_missing_fields_rejected (__main__.Reports) ... ok +test_violation_presence_and_difference (__main__.Reports) ... ok +test_O_cadence (__main__.S2Format) ... ok +test_counter_and_published_ids_binding (__main__.S2Format) ... ok +test_diff_and_same_as_S_transport (__main__.S2Format) ... ok +test_digest_and_scenario_contradiction (__main__.S2Format) ... ok +test_event_no_drop_duplicate_remap (__main__.S2Format) ... ok +test_event_original_field_types_mandatory (__main__.S2Format) ... ok +test_guard_actual_not_assumed (__main__.S2Format) ... ok +test_harness_digest_allows_only_dictionary_order (__main__.S2Format) ... ok +test_join_is_copy_and_retains_normalization_proof (__main__.S2Format) ... ok +test_kernel_cache_contradictions (__main__.S2Format) ... ok +test_lifecycle_guard_errors_and_boundaries (__main__.S2Format) ... ok +test_missing_full_state_not_digest_only (__main__.S2Format) ... ok +test_normalized_digest_and_raw_tree_are_both_bound (__main__.S2Format) ... ok +test_product_event_shape_and_typed_array (__main__.S2Format) ... ok +test_raw_observation_binding (__main__.S2Format) ... ok +test_roundtrip_tree_sha_and_raw_sha (__main__.S2Format) ... ok +test_s2_valid_and_not_formal_acceptance (__main__.S2Format) ... ok +test_state_witness_and_observation_mutation (__main__.S2Format) ... ok +test_stdout_exactly_one_line (__main__.S2Format) ... ok +test_autoload_class_and_script_import (__main__.S2Static) ... ok +test_comment_does_not_supply_proof (__main__.S2Static) ... ok +test_current_probe (__main__.S2Static) ... ok +test_full_state_and_godot_roundtrip_required (__main__.S2Static) ... ok +test_no_changes_outside_preparation_or_step (__main__.S2Static) ... ok +test_no_event_cap_or_duplicate_report (__main__.S2Static) ... ok +test_pause_and_step_arguments (__main__.S2Static) ... ok +test_textual_stringname_ordering (__main__.S2Static) ... ok +test_unlisted_live_method_and_late_preparation (__main__.S2Static) ... ok +test_variant_inference (__main__.S2Static) ... ok +test_X_recent_limit_and_counter (__main__.S3a) ... ok +test_duplicate_JSON_key_rejected (__main__.S3a) ... ok +test_e3_NA_cannot_be_PASS_or_applied (__main__.S3a) ... ok +test_e3_coverage_input_and_event_count_binding (__main__.S3a) ... ok +test_e3_invented_codes_and_missing_load_code (__main__.S3a) ... ok +test_e3_valid_R_and_O_records (__main__.S3a) ... ok +test_envelope_duplicates_not_defect (__main__.S3a) ... ok +test_event_count_defect_not_silently_accepted (__main__.S3a) ... ok +test_exact_phase_keys (__main__.S3a) ... ok +test_interval_gap_rejected (__main__.S3a) ... ok +test_invalid_input_accepted_is_not_PASS (__main__.S3a) ... ok +test_load_payload_and_pause_outcome (__main__.S3a) ... ok +test_operation_moved_outside_scenario_rejected (__main__.S3a) ... ok +test_package_fixed_mutations_and_hashes (__main__.S3a) ... ok +test_probe_connection_required (__main__.S3a) ... ok +test_rejection_mutation_retained_as_defect (__main__.S3a) ... ok +test_save_refusal_makes_load_NA (__main__.S3a) ... ok +test_scenario_mutation_static_boundary (__main__.S3a) ... ok +test_signals_all_minutes_and_order (__main__.S3a) ... ok +test_fixed_scenario_paths (__main__.SourcesAndMetrics) ... ok +test_metric_ranges (__main__.SourcesAndMetrics) ... ok +test_source_closure_synthetic_registered_map (__main__.SourcesAndMetrics) ... ok +test_source_pin_is_not_caller_controlled (__main__.SourcesAndMetrics) ... ok +test_array_order_and_all_differences (__main__.TypedTrees) ... ok +test_components_and_sha (__main__.TypedTrees) ... ok +test_deep_state_not_truncated (__main__.TypedTrees) ... ok +test_duplicate_textual_keys_rejected (__main__.TypedTrees) ... ok +test_exact_and_types (__main__.TypedTrees) ... ok +test_nested_order_all_paths (__main__.TypedTrees) ... ok +test_nonstring_keys_keep_types_and_values (__main__.TypedTrees) ... ok +test_unsupported_and_malformed (__main__.TypedTrees) ... ok + +---------------------------------------------------------------------- +Ran 91 tests in 18.225s + +OK diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_04.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_04.sha256 new file mode 100644 index 0000000..961b119 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_04.sha256 @@ -0,0 +1 @@ +02221ae41e5dd40ecdac0ec0d7ffc657f265d3194c3817583c2b88ad375f132b UNIT_OUTPUT_S3A_ATTEMPT_04.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_04.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_04.txt new file mode 100644 index 0000000..04bcab5 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3A_ATTEMPT_04.txt @@ -0,0 +1,96 @@ +test_all_operations (__main__.Diffs) ... ok +test_invalid_operations (__main__.Diffs) ... ok +test_reconstruction_and_proofs (__main__.Diffs) ... ok +test_attempt_to_normalize_violation_rejected (__main__.Normalization) ... ok +test_environment_values_differ_but_normal_form_equal (__main__.Normalization) ... ok +test_every_save_event_reversible (__main__.Normalization) ... ok +test_f3_keeps_relative_paths_and_words (__main__.Normalization) ... ok +test_guard_mismatch (__main__.Normalization) ... ok +test_nested_lookalike_is_not_eligible (__main__.Normalization) ... ok +test_original_transport_sha_detects_forged_timing (__main__.Normalization) ... ok +test_partial_timing_payload_rejected (__main__.Normalization) ... ok +test_prefix_boundary_and_reserved_token (__main__.Normalization) ... ok +test_sidecar_missing_duplicate_and_forged_paths (__main__.Normalization) ... ok +test_snapshot_and_latest_reversible (__main__.Normalization) ... ok +test_snapshot_event_outside_recent_is_not_eligible (__main__.Normalization) ... ok +test_wrong_event_and_source_are_preserved (__main__.Normalization) ... ok +test_wrong_timing_type_and_negative (__main__.Normalization) ... ok +test_all_events_beyond_recent_window (__main__.Reports) ... ok +test_all_semantic_layers_compared (__main__.Reports) ... ok +test_digest_alone_is_not_enough (__main__.Reports) ... ok +test_event_original_types_and_order (__main__.Reports) ... ok +test_event_start_and_ids (__main__.Reports) ... ok +test_exclusions_keep_actual_values (__main__.Reports) ... ok +test_handler_sets_and_counts (__main__.Reports) ... ok +test_observation_full_layers (__main__.Reports) ... ok +test_product_digest_self_consistency (__main__.Reports) ... ok +test_same_report (__main__.Reports) ... ok +test_scenario_existing_failures_preserved (__main__.Reports) ... ok +test_timing_digest_rule (__main__.Reports) ... ok +test_unknown_or_missing_fields_rejected (__main__.Reports) ... ok +test_violation_presence_and_difference (__main__.Reports) ... ok +test_O_cadence (__main__.S2Format) ... ok +test_counter_and_published_ids_binding (__main__.S2Format) ... ok +test_diff_and_same_as_S_transport (__main__.S2Format) ... ok +test_digest_and_scenario_contradiction (__main__.S2Format) ... ok +test_event_no_drop_duplicate_remap (__main__.S2Format) ... ok +test_event_original_field_types_mandatory (__main__.S2Format) ... ok +test_guard_actual_not_assumed (__main__.S2Format) ... ok +test_harness_digest_allows_only_dictionary_order (__main__.S2Format) ... ok +test_join_is_copy_and_retains_normalization_proof (__main__.S2Format) ... ok +test_kernel_cache_contradictions (__main__.S2Format) ... ok +test_lifecycle_guard_errors_and_boundaries (__main__.S2Format) ... ok +test_missing_full_state_not_digest_only (__main__.S2Format) ... ok +test_normalized_digest_and_raw_tree_are_both_bound (__main__.S2Format) ... ok +test_product_event_shape_and_typed_array (__main__.S2Format) ... ok +test_raw_observation_binding (__main__.S2Format) ... ok +test_roundtrip_tree_sha_and_raw_sha (__main__.S2Format) ... ok +test_s2_valid_and_not_formal_acceptance (__main__.S2Format) ... ok +test_state_witness_and_observation_mutation (__main__.S2Format) ... ok +test_stdout_exactly_one_line (__main__.S2Format) ... ok +test_autoload_class_and_script_import (__main__.S2Static) ... ok +test_comment_does_not_supply_proof (__main__.S2Static) ... ok +test_current_probe (__main__.S2Static) ... ok +test_full_state_and_godot_roundtrip_required (__main__.S2Static) ... ok +test_no_changes_outside_preparation_or_step (__main__.S2Static) ... ok +test_no_event_cap_or_duplicate_report (__main__.S2Static) ... ok +test_pause_and_step_arguments (__main__.S2Static) ... ok +test_textual_stringname_ordering (__main__.S2Static) ... ok +test_unlisted_live_method_and_late_preparation (__main__.S2Static) ... ok +test_variant_inference (__main__.S2Static) ... ok +test_X_recent_limit_and_counter (__main__.S3a) ... ok +test_duplicate_JSON_key_rejected (__main__.S3a) ... ok +test_e3_NA_cannot_be_PASS_or_applied (__main__.S3a) ... ok +test_e3_coverage_input_and_event_count_binding (__main__.S3a) ... ok +test_e3_invented_codes_and_missing_load_code (__main__.S3a) ... ok +test_e3_valid_R_and_O_records (__main__.S3a) ... ok +test_envelope_duplicates_not_defect (__main__.S3a) ... ok +test_event_count_defect_not_silently_accepted (__main__.S3a) ... ok +test_exact_phase_keys (__main__.S3a) ... ok +test_interval_gap_rejected (__main__.S3a) ... ok +test_invalid_input_accepted_is_not_PASS (__main__.S3a) ... ok +test_load_payload_and_pause_outcome (__main__.S3a) ... ok +test_operation_moved_outside_scenario_rejected (__main__.S3a) ... ok +test_package_fixed_mutations_and_hashes (__main__.S3a) ... ok +test_probe_connection_required (__main__.S3a) ... ok +test_rejection_mutation_retained_as_defect (__main__.S3a) ... ok +test_save_refusal_makes_load_NA (__main__.S3a) ... ok +test_scenario_mutation_static_boundary (__main__.S3a) ... ok +test_signals_all_minutes_and_order (__main__.S3a) ... ok +test_fixed_scenario_paths (__main__.SourcesAndMetrics) ... ok +test_metric_ranges (__main__.SourcesAndMetrics) ... ok +test_source_closure_synthetic_registered_map (__main__.SourcesAndMetrics) ... ok +test_source_pin_is_not_caller_controlled (__main__.SourcesAndMetrics) ... ok +test_array_order_and_all_differences (__main__.TypedTrees) ... ok +test_components_and_sha (__main__.TypedTrees) ... ok +test_deep_state_not_truncated (__main__.TypedTrees) ... ok +test_duplicate_textual_keys_rejected (__main__.TypedTrees) ... ok +test_exact_and_types (__main__.TypedTrees) ... ok +test_nested_order_all_paths (__main__.TypedTrees) ... ok +test_nonstring_keys_keep_types_and_values (__main__.TypedTrees) ... ok +test_unsupported_and_malformed (__main__.TypedTrees) ... ok + +---------------------------------------------------------------------- +Ran 91 tests in 18.329s + +OK diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_01.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_01.sha256 new file mode 100644 index 0000000..d924846 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_01.sha256 @@ -0,0 +1 @@ +c89f4f1ca1ea9b985079cd236ffff4193fa5c76d9bfa28fa65ac08cfc93b569c UNIT_OUTPUT_S3B_ATTEMPT_01.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_01.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_01.txt new file mode 100644 index 0000000..8a2e138 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_01.txt @@ -0,0 +1,96 @@ +test_all_operations (__main__.Diffs) ... ok +test_invalid_operations (__main__.Diffs) ... ok +test_reconstruction_and_proofs (__main__.Diffs) ... ok +test_attempt_to_normalize_violation_rejected (__main__.Normalization) ... ok +test_environment_values_differ_but_normal_form_equal (__main__.Normalization) ... ok +test_every_save_event_reversible (__main__.Normalization) ... ok +test_f3_keeps_relative_paths_and_words (__main__.Normalization) ... ok +test_guard_mismatch (__main__.Normalization) ... ok +test_nested_lookalike_is_not_eligible (__main__.Normalization) ... ok +test_original_transport_sha_detects_forged_timing (__main__.Normalization) ... ok +test_partial_timing_payload_rejected (__main__.Normalization) ... ok +test_prefix_boundary_and_reserved_token (__main__.Normalization) ... ok +test_sidecar_missing_duplicate_and_forged_paths (__main__.Normalization) ... ok +test_snapshot_and_latest_reversible (__main__.Normalization) ... ok +test_snapshot_event_outside_recent_is_not_eligible (__main__.Normalization) ... ok +test_wrong_event_and_source_are_preserved (__main__.Normalization) ... ok +test_wrong_timing_type_and_negative (__main__.Normalization) ... ok +test_all_events_beyond_recent_window (__main__.Reports) ... ok +test_all_semantic_layers_compared (__main__.Reports) ... ok +test_digest_alone_is_not_enough (__main__.Reports) ... ok +test_event_original_types_and_order (__main__.Reports) ... ok +test_event_start_and_ids (__main__.Reports) ... ok +test_exclusions_keep_actual_values (__main__.Reports) ... ok +test_handler_sets_and_counts (__main__.Reports) ... ok +test_observation_full_layers (__main__.Reports) ... ok +test_product_digest_self_consistency (__main__.Reports) ... ok +test_same_report (__main__.Reports) ... ok +test_scenario_existing_failures_preserved (__main__.Reports) ... ok +test_timing_digest_rule (__main__.Reports) ... ok +test_unknown_or_missing_fields_rejected (__main__.Reports) ... ok +test_violation_presence_and_difference (__main__.Reports) ... ok +test_O_cadence (__main__.S2Format) ... ok +test_counter_and_published_ids_binding (__main__.S2Format) ... ok +test_diff_and_same_as_S_transport (__main__.S2Format) ... ok +test_digest_and_scenario_contradiction (__main__.S2Format) ... ok +test_event_no_drop_duplicate_remap (__main__.S2Format) ... ok +test_event_original_field_types_mandatory (__main__.S2Format) ... ok +test_guard_actual_not_assumed (__main__.S2Format) ... ok +test_harness_digest_allows_only_dictionary_order (__main__.S2Format) ... ok +test_join_is_copy_and_retains_normalization_proof (__main__.S2Format) ... ok +test_kernel_cache_contradictions (__main__.S2Format) ... ok +test_lifecycle_guard_errors_and_boundaries (__main__.S2Format) ... ok +test_missing_full_state_not_digest_only (__main__.S2Format) ... ok +test_normalized_digest_and_raw_tree_are_both_bound (__main__.S2Format) ... ok +test_product_event_shape_and_typed_array (__main__.S2Format) ... ok +test_raw_observation_binding (__main__.S2Format) ... ok +test_roundtrip_tree_sha_and_raw_sha (__main__.S2Format) ... ok +test_s2_valid_and_not_formal_acceptance (__main__.S2Format) ... ok +test_state_witness_and_observation_mutation (__main__.S2Format) ... ok +test_stdout_exactly_one_line (__main__.S2Format) ... ok +test_autoload_class_and_script_import (__main__.S2Static) ... ok +test_comment_does_not_supply_proof (__main__.S2Static) ... ok +test_current_probe (__main__.S2Static) ... ok +test_full_state_and_godot_roundtrip_required (__main__.S2Static) ... ok +test_no_changes_outside_preparation_or_step (__main__.S2Static) ... ok +test_no_event_cap_or_duplicate_report (__main__.S2Static) ... ok +test_pause_and_step_arguments (__main__.S2Static) ... ok +test_textual_stringname_ordering (__main__.S2Static) ... ok +test_unlisted_live_method_and_late_preparation (__main__.S2Static) ... ok +test_variant_inference (__main__.S2Static) ... ok +test_X_recent_limit_and_counter (__main__.S3a) ... ok +test_duplicate_JSON_key_rejected (__main__.S3a) ... ok +test_e3_NA_cannot_be_PASS_or_applied (__main__.S3a) ... ok +test_e3_coverage_input_and_event_count_binding (__main__.S3a) ... ok +test_e3_invented_codes_and_missing_load_code (__main__.S3a) ... ok +test_e3_valid_R_and_O_records (__main__.S3a) ... ok +test_envelope_duplicates_not_defect (__main__.S3a) ... ok +test_event_count_defect_not_silently_accepted (__main__.S3a) ... ok +test_exact_phase_keys (__main__.S3a) ... ok +test_interval_gap_rejected (__main__.S3a) ... ok +test_invalid_input_accepted_is_not_PASS (__main__.S3a) ... ok +test_load_payload_and_pause_outcome (__main__.S3a) ... ok +test_operation_moved_outside_scenario_rejected (__main__.S3a) ... ok +test_package_fixed_mutations_and_hashes (__main__.S3a) ... ok +test_probe_connection_required (__main__.S3a) ... ok +test_rejection_mutation_retained_as_defect (__main__.S3a) ... ok +test_save_refusal_makes_load_NA (__main__.S3a) ... ok +test_scenario_mutation_static_boundary (__main__.S3a) ... ok +test_signals_all_minutes_and_order (__main__.S3a) ... ok +test_fixed_scenario_paths (__main__.SourcesAndMetrics) ... ok +test_metric_ranges (__main__.SourcesAndMetrics) ... ok +test_source_closure_synthetic_registered_map (__main__.SourcesAndMetrics) ... ok +test_source_pin_is_not_caller_controlled (__main__.SourcesAndMetrics) ... ok +test_array_order_and_all_differences (__main__.TypedTrees) ... ok +test_components_and_sha (__main__.TypedTrees) ... ok +test_deep_state_not_truncated (__main__.TypedTrees) ... ok +test_duplicate_textual_keys_rejected (__main__.TypedTrees) ... ok +test_exact_and_types (__main__.TypedTrees) ... ok +test_nested_order_all_paths (__main__.TypedTrees) ... ok +test_nonstring_keys_keep_types_and_values (__main__.TypedTrees) ... ok +test_unsupported_and_malformed (__main__.TypedTrees) ... ok + +---------------------------------------------------------------------- +Ran 91 tests in 18.303s + +OK diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_02.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_02.sha256 new file mode 100644 index 0000000..33c049e --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_02.sha256 @@ -0,0 +1 @@ +7bd19a6a3c84385f754261d51779f05b6e39c116459086d5aad3a83afa7225c0 UNIT_OUTPUT_S3B_ATTEMPT_02.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_02.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_02.txt new file mode 100644 index 0000000..10125dc --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_02.txt @@ -0,0 +1,4 @@ + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1108 + self.reject(lambda r, e, p: e[3]['detail'].update(input=transport(snapshot())))) + ^ +SyntaxError: unmatched ')' diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_03.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_03.sha256 new file mode 100644 index 0000000..86bd0d5 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_03.sha256 @@ -0,0 +1 @@ +0872061bbc2c1403d2cd04877b8456f3fead35236be008b1a07f02ae5d85b11a UNIT_OUTPUT_S3B_ATTEMPT_03.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_03.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_03.txt new file mode 100644 index 0000000..b01023c --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_03.txt @@ -0,0 +1,127 @@ +test_all_operations (__main__.Diffs) ... ok +test_invalid_operations (__main__.Diffs) ... ok +test_reconstruction_and_proofs (__main__.Diffs) ... ok +test_attempt_to_normalize_violation_rejected (__main__.Normalization) ... ok +test_environment_values_differ_but_normal_form_equal (__main__.Normalization) ... ok +test_every_save_event_reversible (__main__.Normalization) ... ok +test_f3_keeps_relative_paths_and_words (__main__.Normalization) ... ok +test_guard_mismatch (__main__.Normalization) ... ok +test_nested_lookalike_is_not_eligible (__main__.Normalization) ... ok +test_original_transport_sha_detects_forged_timing (__main__.Normalization) ... ok +test_partial_timing_payload_rejected (__main__.Normalization) ... ok +test_prefix_boundary_and_reserved_token (__main__.Normalization) ... ok +test_sidecar_missing_duplicate_and_forged_paths (__main__.Normalization) ... ok +test_snapshot_and_latest_reversible (__main__.Normalization) ... ok +test_snapshot_event_outside_recent_is_not_eligible (__main__.Normalization) ... ok +test_wrong_event_and_source_are_preserved (__main__.Normalization) ... ok +test_wrong_timing_type_and_negative (__main__.Normalization) ... ok +test_all_events_beyond_recent_window (__main__.Reports) ... ok +test_all_semantic_layers_compared (__main__.Reports) ... ok +test_digest_alone_is_not_enough (__main__.Reports) ... ok +test_event_original_types_and_order (__main__.Reports) ... ok +test_event_start_and_ids (__main__.Reports) ... ok +test_exclusions_keep_actual_values (__main__.Reports) ... ok +test_handler_sets_and_counts (__main__.Reports) ... ok +test_observation_full_layers (__main__.Reports) ... ok +test_product_digest_self_consistency (__main__.Reports) ... ok +test_same_report (__main__.Reports) ... ok +test_scenario_existing_failures_preserved (__main__.Reports) ... ok +test_timing_digest_rule (__main__.Reports) ... ok +test_unknown_or_missing_fields_rejected (__main__.Reports) ... ok +test_violation_presence_and_difference (__main__.Reports) ... ok +test_O_cadence (__main__.S2Format) ... ok +test_counter_and_published_ids_binding (__main__.S2Format) ... ok +test_diff_and_same_as_S_transport (__main__.S2Format) ... ok +test_digest_and_scenario_contradiction (__main__.S2Format) ... ok +test_event_no_drop_duplicate_remap (__main__.S2Format) ... ok +test_event_original_field_types_mandatory (__main__.S2Format) ... ok +test_guard_actual_not_assumed (__main__.S2Format) ... ok +test_harness_digest_allows_only_dictionary_order (__main__.S2Format) ... ok +test_join_is_copy_and_retains_normalization_proof (__main__.S2Format) ... ok +test_kernel_cache_contradictions (__main__.S2Format) ... ok +test_lifecycle_guard_errors_and_boundaries (__main__.S2Format) ... ok +test_missing_full_state_not_digest_only (__main__.S2Format) ... ok +test_normalized_digest_and_raw_tree_are_both_bound (__main__.S2Format) ... ok +test_product_event_shape_and_typed_array (__main__.S2Format) ... ok +test_raw_observation_binding (__main__.S2Format) ... ok +test_roundtrip_tree_sha_and_raw_sha (__main__.S2Format) ... ok +test_s2_valid_and_not_formal_acceptance (__main__.S2Format) ... ok +test_state_witness_and_observation_mutation (__main__.S2Format) ... ok +test_stdout_exactly_one_line (__main__.S2Format) ... ok +test_autoload_class_and_script_import (__main__.S2Static) ... ok +test_comment_does_not_supply_proof (__main__.S2Static) ... ok +test_current_probe (__main__.S2Static) ... ok +test_full_state_and_godot_roundtrip_required (__main__.S2Static) ... ok +test_no_changes_outside_preparation_or_step (__main__.S2Static) ... ok +test_no_event_cap_or_duplicate_report (__main__.S2Static) ... ok +test_pause_and_step_arguments (__main__.S2Static) ... ok +test_textual_stringname_ordering (__main__.S2Static) ... ok +test_unlisted_live_method_and_late_preparation (__main__.S2Static) ... ok +test_variant_inference (__main__.S2Static) ... ok +test_X_recent_limit_and_counter (__main__.S3a) ... ok +test_duplicate_JSON_key_rejected (__main__.S3a) ... ok +test_e3_NA_cannot_be_PASS_or_applied (__main__.S3a) ... ok +test_e3_coverage_input_and_event_count_binding (__main__.S3a) ... ok +test_e3_invented_codes_and_missing_load_code (__main__.S3a) ... ok +test_e3_valid_R_and_O_records (__main__.S3a) ... ok +test_envelope_duplicates_not_defect (__main__.S3a) ... ok +test_event_count_defect_not_silently_accepted (__main__.S3a) ... ok +test_exact_phase_keys (__main__.S3a) ... ok +test_interval_gap_rejected (__main__.S3a) ... ok +test_invalid_input_accepted_is_not_PASS (__main__.S3a) ... ok +test_load_payload_and_pause_outcome (__main__.S3a) ... ok +test_operation_moved_outside_scenario_rejected (__main__.S3a) ... ok +test_package_fixed_mutations_and_hashes (__main__.S3a) ... ok +test_probe_connection_required (__main__.S3a) ... ok +test_rejection_mutation_retained_as_defect (__main__.S3a) ... ok +test_save_refusal_makes_load_NA (__main__.S3a) ... ok +test_scenario_mutation_static_boundary (__main__.S3a) ... ok +test_signals_all_minutes_and_order (__main__.S3a) ... ok +test_E5_cached_digest_defect_is_comparable (__main__.S3b) ... FAIL +test_NA_not_PASS (__main__.S3b) ... ok +test_aliasing_cannot_be_PASS (__main__.S3b) ... ok +test_aliasing_missing_record (__main__.S3b) ... ok +test_all_paths_and_ownership_R_O (__main__.S3b) ... ok +test_digest_materialization_required (__main__.S3b) ... ok +test_empty_registry_not_NA (__main__.S3b) ... ok +test_event_count_mismatch (__main__.S3b) ... ok +test_facts_normalization_is_reversible (__main__.S3b) ... ok +test_first_placeable_choice (__main__.S3b) ... ok +test_interval_gap (__main__.S3b) ... ok +test_load_X_not_digest_only (__main__.S3b) ... ok +test_load_extra_event (__main__.S3b) ... ok +test_missing_path_and_combination (__main__.S3b) ... ok +test_missing_trial (__main__.S3b) ... ok +test_nested_mutation_required (__main__.S3b) ... ok +test_no_staleness_assertion_for_non_tick (__main__.S3b) ... ok +test_path_order (__main__.S3b) ... ok +test_restore_extra_event (__main__.S3b) ... ok +test_sort_rule_rejected (__main__.S3b) ... ok +test_static_handler_and_outside_mutations (__main__.S3b) ... ok +test_unpreviewed_choice (__main__.S3b) ... ok +test_wrong_registry_in_either_role (__main__.S3b) ... ok +test_fixed_scenario_paths (__main__.SourcesAndMetrics) ... ok +test_metric_ranges (__main__.SourcesAndMetrics) ... ok +test_source_closure_synthetic_registered_map (__main__.SourcesAndMetrics) ... ok +test_source_pin_is_not_caller_controlled (__main__.SourcesAndMetrics) ... ok +test_array_order_and_all_differences (__main__.TypedTrees) ... ok +test_components_and_sha (__main__.TypedTrees) ... ok +test_deep_state_not_truncated (__main__.TypedTrees) ... ok +test_duplicate_textual_keys_rejected (__main__.TypedTrees) ... ok +test_exact_and_types (__main__.TypedTrees) ... ok +test_nested_order_all_paths (__main__.TypedTrees) ... ok +test_nonstring_keys_keep_types_and_values (__main__.TypedTrees) ... ok +test_unsupported_and_malformed (__main__.TypedTrees) ... ok + +====================================================================== +FAIL: test_E5_cached_digest_defect_is_comparable (__main__.S3b) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1193, in test_E5_cached_digest_defect_is_comparable + self.assertTrue(checked['ok'], checked) +AssertionError: False is not true : {'ok': False, 'differences': [], 'dict_order_paths': [], 'excluded': [{'path': ['checkpoints', 0, 'K', 'performance_budget', '_samples'], 'reason': 'wall-clock telemetry', 'a': {'x': [1]}, 'b': {'x': [1]}}, {'path': ['checkpoints', 0, 'K', 'performance_budget', '_totals'], 'reason': 'wall-clock telemetry', 'a': {'x': 1}, 'b': {'x': 1}}, {'path': ['checkpoints', 0, 'C', 'catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 0, 'C', 'current_catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 1, 'K', 'performance_budget', '_samples'], 'reason': 'wall-clock telemetry', 'a': {'x': [1]}, 'b': {'x': [1]}}, {'path': ['checkpoints', 1, 'K', 'performance_budget', '_totals'], 'reason': 'wall-clock telemetry', 'a': {'x': 1}, 'b': {'x': 1}}, {'path': ['checkpoints', 1, 'C', 'catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 1, 'C', 'current_catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 2, 'K', 'performance_budget', '_samples'], 'reason': 'wall-clock telemetry', 'a': {'x': [1]}, 'b': {'x': [1]}}, {'path': ['checkpoints', 2, 'K', 'performance_budget', '_totals'], 'reason': 'wall-clock telemetry', 'a': {'x': 1}, 'b': {'x': 1}}, {'path': ['checkpoints', 2, 'C', 'catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 2, 'C', 'current_catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 3, 'K', 'performance_budget', '_samples'], 'reason': 'wall-clock telemetry', 'a': {'x': [1]}, 'b': {'x': [1]}}, {'path': ['checkpoints', 3, 'K', 'performance_budget', '_totals'], 'reason': 'wall-clock telemetry', 'a': {'x': 1}, 'b': {'x': 1}}, {'path': ['checkpoints', 3, 'C', 'catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 3, 'C', 'current_catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 4, 'K', 'performance_budget', '_samples'], 'reason': 'wall-clock telemetry', 'a': {'x': [1]}, 'b': {'x': [1]}}, {'path': ['checkpoints', 4, 'K', 'performance_budget', '_totals'], 'reason': 'wall-clock telemetry', 'a': {'x': 1}, 'b': {'x': 1}}, {'path': ['checkpoints', 4, 'C', 'catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 4, 'C', 'current_catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 5, 'K', 'performance_budget', '_samples'], 'reason': 'wall-clock telemetry', 'a': {'x': [1]}, 'b': {'x': [1]}}, {'path': ['checkpoints', 5, 'K', 'performance_budget', '_totals'], 'reason': 'wall-clock telemetry', 'a': {'x': 1}, 'b': {'x': 1}}, {'path': ['checkpoints', 5, 'C', 'catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 5, 'C', 'current_catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 6, 'K', 'performance_budget', '_samples'], 'reason': 'wall-clock telemetry', 'a': {'x': [1]}, 'b': {'x': [1]}}, {'path': ['checkpoints', 6, 'K', 'performance_budget', '_totals'], 'reason': 'wall-clock telemetry', 'a': {'x': 1}, 'b': {'x': 1}}, {'path': ['checkpoints', 6, 'C', 'catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 6, 'C', 'current_catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 7, 'K', 'performance_budget', '_samples'], 'reason': 'wall-clock telemetry', 'a': {'x': [1]}, 'b': {'x': [1]}}, {'path': ['checkpoints', 7, 'K', 'performance_budget', '_totals'], 'reason': 'wall-clock telemetry', 'a': {'x': 1}, 'b': {'x': 1}}, {'path': ['checkpoints', 7, 'C', 'catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 7, 'C', 'current_catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 8, 'K', 'performance_budget', '_samples'], 'reason': 'wall-clock telemetry', 'a': {'x': [1]}, 'b': {'x': [1]}}, {'path': ['checkpoints', 8, 'K', 'performance_budget', '_totals'], 'reason': 'wall-clock telemetry', 'a': {'x': 1}, 'b': {'x': 1}}, {'path': ['checkpoints', 8, 'C', 'catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 8, 'C', 'current_catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 9, 'K', 'performance_budget', '_samples'], 'reason': 'wall-clock telemetry', 'a': {'x': [1]}, 'b': {'x': [1]}}, {'path': ['checkpoints', 9, 'K', 'performance_budget', '_totals'], 'reason': 'wall-clock telemetry', 'a': {'x': 1}, 'b': {'x': 1}}, {'path': ['checkpoints', 9, 'C', 'catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 9, 'C', 'current_catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 10, 'K', 'performance_budget', '_samples'], 'reason': 'wall-clock telemetry', 'a': {'x': [1]}, 'b': {'x': [1]}}, {'path': ['checkpoints', 10, 'K', 'performance_budget', '_totals'], 'reason': 'wall-clock telemetry', 'a': {'x': 1}, 'b': {'x': 1}}, {'path': ['checkpoints', 10, 'C', 'catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 10, 'C', 'current_catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 11, 'K', 'performance_budget', '_samples'], 'reason': 'wall-clock telemetry', 'a': {'x': [1]}, 'b': {'x': [1]}}, {'path': ['checkpoints', 11, 'K', 'performance_budget', '_totals'], 'reason': 'wall-clock telemetry', 'a': {'x': 1}, 'b': {'x': 1}}, {'path': ['checkpoints', 11, 'C', 'catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 11, 'C', 'current_catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 12, 'K', 'performance_budget', '_samples'], 'reason': 'wall-clock telemetry', 'a': {'x': [1]}, 'b': {'x': [1]}}, {'path': ['checkpoints', 12, 'K', 'performance_budget', '_totals'], 'reason': 'wall-clock telemetry', 'a': {'x': 1}, 'b': {'x': 1}}, {'path': ['checkpoints', 12, 'C', 'catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 12, 'C', 'current_catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 13, 'K', 'performance_budget', '_samples'], 'reason': 'wall-clock telemetry', 'a': {'x': [1]}, 'b': {'x': [1]}}, {'path': ['checkpoints', 13, 'K', 'performance_budget', '_totals'], 'reason': 'wall-clock telemetry', 'a': {'x': 1}, 'b': {'x': 1}}, {'path': ['checkpoints', 13, 'C', 'catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 13, 'C', 'current_catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 14, 'K', 'performance_budget', '_samples'], 'reason': 'wall-clock telemetry', 'a': {'x': [1]}, 'b': {'x': [1]}}, {'path': ['checkpoints', 14, 'K', 'performance_budget', '_totals'], 'reason': 'wall-clock telemetry', 'a': {'x': 1}, 'b': {'x': 1}}, {'path': ['checkpoints', 14, 'C', 'catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 14, 'C', 'current_catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 15, 'K', 'performance_budget', '_samples'], 'reason': 'wall-clock telemetry', 'a': {'x': [1]}, 'b': {'x': [1]}}, {'path': ['checkpoints', 15, 'K', 'performance_budget', '_totals'], 'reason': 'wall-clock telemetry', 'a': {'x': 1}, 'b': {'x': 1}}, {'path': ['checkpoints', 15, 'C', 'catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 15, 'C', 'current_catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 16, 'K', 'performance_budget', '_samples'], 'reason': 'wall-clock telemetry', 'a': {'x': [1]}, 'b': {'x': [1]}}, {'path': ['checkpoints', 16, 'K', 'performance_budget', '_totals'], 'reason': 'wall-clock telemetry', 'a': {'x': 1}, 'b': {'x': 1}}, {'path': ['checkpoints', 16, 'C', 'catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 16, 'C', 'current_catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 17, 'K', 'performance_budget', '_samples'], 'reason': 'wall-clock telemetry', 'a': {'x': [1]}, 'b': {'x': [1]}}, {'path': ['checkpoints', 17, 'K', 'performance_budget', '_totals'], 'reason': 'wall-clock telemetry', 'a': {'x': 1}, 'b': {'x': 1}}, {'path': ['checkpoints', 17, 'C', 'catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 17, 'C', 'current_catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 18, 'K', 'performance_budget', '_samples'], 'reason': 'wall-clock telemetry', 'a': {'x': [1]}, 'b': {'x': [1]}}, {'path': ['checkpoints', 18, 'K', 'performance_budget', '_totals'], 'reason': 'wall-clock telemetry', 'a': {'x': 1}, 'b': {'x': 1}}, {'path': ['checkpoints', 18, 'C', 'catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 18, 'C', 'current_catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 19, 'K', 'performance_budget', '_samples'], 'reason': 'wall-clock telemetry', 'a': {'x': [1]}, 'b': {'x': [1]}}, {'path': ['checkpoints', 19, 'K', 'performance_budget', '_totals'], 'reason': 'wall-clock telemetry', 'a': {'x': 1}, 'b': {'x': 1}}, {'path': ['checkpoints', 19, 'C', 'catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 19, 'C', 'current_catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 20, 'K', 'performance_budget', '_samples'], 'reason': 'wall-clock telemetry', 'a': {'x': [1]}, 'b': {'x': [1]}}, {'path': ['checkpoints', 20, 'K', 'performance_budget', '_totals'], 'reason': 'wall-clock telemetry', 'a': {'x': 1}, 'b': {'x': 1}}, {'path': ['checkpoints', 20, 'C', 'catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 20, 'C', 'current_catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 21, 'K', 'performance_budget', '_samples'], 'reason': 'wall-clock telemetry', 'a': {'x': [1]}, 'b': {'x': [1]}}, {'path': ['checkpoints', 21, 'K', 'performance_budget', '_totals'], 'reason': 'wall-clock telemetry', 'a': {'x': 1}, 'b': {'x': 1}}, {'path': ['checkpoints', 21, 'C', 'catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 21, 'C', 'current_catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 22, 'K', 'performance_budget', '_samples'], 'reason': 'wall-clock telemetry', 'a': {'x': [1]}, 'b': {'x': [1]}}, {'path': ['checkpoints', 22, 'K', 'performance_budget', '_totals'], 'reason': 'wall-clock telemetry', 'a': {'x': 1}, 'b': {'x': 1}}, {'path': ['checkpoints', 22, 'C', 'catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 22, 'C', 'current_catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 23, 'K', 'performance_budget', '_samples'], 'reason': 'wall-clock telemetry', 'a': {'x': [1]}, 'b': {'x': [1]}}, {'path': ['checkpoints', 23, 'K', 'performance_budget', '_totals'], 'reason': 'wall-clock telemetry', 'a': {'x': 1}, 'b': {'x': 1}}, {'path': ['checkpoints', 23, 'C', 'catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 23, 'C', 'current_catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 24, 'K', 'performance_budget', '_samples'], 'reason': 'wall-clock telemetry', 'a': {'x': [1]}, 'b': {'x': [1]}}, {'path': ['checkpoints', 24, 'K', 'performance_budget', '_totals'], 'reason': 'wall-clock telemetry', 'a': {'x': 1}, 'b': {'x': 1}}, {'path': ['checkpoints', 24, 'C', 'catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 24, 'C', 'current_catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 25, 'K', 'performance_budget', '_samples'], 'reason': 'wall-clock telemetry', 'a': {'x': [1]}, 'b': {'x': [1]}}, {'path': ['checkpoints', 25, 'K', 'performance_budget', '_totals'], 'reason': 'wall-clock telemetry', 'a': {'x': 1}, 'b': {'x': 1}}, {'path': ['checkpoints', 25, 'C', 'catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 25, 'C', 'current_catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 26, 'K', 'performance_budget', '_samples'], 'reason': 'wall-clock telemetry', 'a': {'x': [1]}, 'b': {'x': [1]}}, {'path': ['checkpoints', 26, 'K', 'performance_budget', '_totals'], 'reason': 'wall-clock telemetry', 'a': {'x': 1}, 'b': {'x': 1}}, {'path': ['checkpoints', 26, 'C', 'catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 26, 'C', 'current_catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 27, 'K', 'performance_budget', '_samples'], 'reason': 'wall-clock telemetry', 'a': {'x': [1]}, 'b': {'x': [1]}}, {'path': ['checkpoints', 27, 'K', 'performance_budget', '_totals'], 'reason': 'wall-clock telemetry', 'a': {'x': 1}, 'b': {'x': 1}}, {'path': ['checkpoints', 27, 'C', 'catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 27, 'C', 'current_catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 28, 'K', 'performance_budget', '_samples'], 'reason': 'wall-clock telemetry', 'a': {'x': [1]}, 'b': {'x': [1]}}, {'path': ['checkpoints', 28, 'K', 'performance_budget', '_totals'], 'reason': 'wall-clock telemetry', 'a': {'x': 1}, 'b': {'x': 1}}, {'path': ['checkpoints', 28, 'C', 'catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 28, 'C', 'current_catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 29, 'K', 'performance_budget', '_samples'], 'reason': 'wall-clock telemetry', 'a': {'x': [1]}, 'b': {'x': [1]}}, {'path': ['checkpoints', 29, 'K', 'performance_budget', '_totals'], 'reason': 'wall-clock telemetry', 'a': {'x': 1}, 'b': {'x': 1}}, {'path': ['checkpoints', 29, 'C', 'catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 29, 'C', 'current_catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 30, 'K', 'performance_budget', '_samples'], 'reason': 'wall-clock telemetry', 'a': {'x': [1]}, 'b': {'x': [1]}}, {'path': ['checkpoints', 30, 'K', 'performance_budget', '_totals'], 'reason': 'wall-clock telemetry', 'a': {'x': 1}, 'b': {'x': 1}}, {'path': ['checkpoints', 30, 'C', 'catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['checkpoints', 30, 'C', 'current_catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['scenarios', 0, 'checkpoints', 0, 'K', 'performance_budget', '_samples'], 'reason': 'wall-clock telemetry', 'a': {'x': [1]}, 'b': {'x': [1]}}, {'path': ['scenarios', 0, 'checkpoints', 0, 'K', 'performance_budget', '_totals'], 'reason': 'wall-clock telemetry', 'a': {'x': 1}, 'b': {'x': 1}}, {'path': ['scenarios', 0, 'checkpoints', 0, 'C', 'catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['scenarios', 0, 'checkpoints', 0, 'C', 'current_catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['scenarios', 0, 'checkpoints', 1, 'K', 'performance_budget', '_samples'], 'reason': 'wall-clock telemetry', 'a': {'x': [1]}, 'b': {'x': [1]}}, {'path': ['scenarios', 0, 'checkpoints', 1, 'K', 'performance_budget', '_totals'], 'reason': 'wall-clock telemetry', 'a': {'x': 1}, 'b': {'x': 1}}, {'path': ['scenarios', 0, 'checkpoints', 1, 'C', 'catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}, {'path': ['scenarios', 0, 'checkpoints', 1, 'C', 'current_catalog_instance_id'], 'reason': 'process-local instance ID', 'a': 123, 'b': 123}], 'violations': [{'path': ['checkpoints', 0, 'S'], 'a': [], 'b': []}, {'path': ['checkpoints', 0, 'latest'], 'a': [], 'b': []}, {'path': ['checkpoints', 1, 'S'], 'a': [], 'b': []}, {'path': ['checkpoints', 1, 'latest'], 'a': [], 'b': []}, {'path': ['checkpoints', 2, 'S'], 'a': [], 'b': []}, {'path': ['checkpoints', 2, 'latest'], 'a': [], 'b': []}, {'path': ['checkpoints', 3, 'S'], 'a': [], 'b': []}, {'path': ['checkpoints', 3, 'latest'], 'a': [], 'b': []}, {'path': ['checkpoints', 4, 'S'], 'a': [], 'b': []}, {'path': ['checkpoints', 4, 'latest'], 'a': [], 'b': []}, {'path': ['checkpoints', 5, 'S'], 'a': [], 'b': []}, {'path': ['checkpoints', 5, 'latest'], 'a': [], 'b': []}, {'path': ['checkpoints', 6, 'S'], 'a': [], 'b': []}, {'path': ['checkpoints', 6, 'latest'], 'a': [], 'b': []}, {'path': ['checkpoints', 7, 'S'], 'a': [], 'b': []}, {'path': ['checkpoints', 7, 'latest'], 'a': [], 'b': []}, {'path': ['checkpoints', 8, 'S'], 'a': [], 'b': []}, {'path': ['checkpoints', 8, 'latest'], 'a': [], 'b': []}, {'path': ['checkpoints', 9, 'S'], 'a': [], 'b': []}, {'path': ['checkpoints', 9, 'latest'], 'a': [], 'b': []}, {'path': ['checkpoints', 10, 'S'], 'a': [], 'b': []}, {'path': ['checkpoints', 10, 'latest'], 'a': [], 'b': []}, {'path': ['checkpoints', 11, 'S'], 'a': [], 'b': []}, {'path': ['checkpoints', 11, 'latest'], 'a': [], 'b': []}, {'path': ['checkpoints', 12, 'S'], 'a': [], 'b': []}, {'path': ['checkpoints', 12, 'latest'], 'a': [], 'b': []}, {'path': ['checkpoints', 13, 'S'], 'a': [], 'b': []}, {'path': ['checkpoints', 13, 'latest'], 'a': [], 'b': []}, {'path': ['checkpoints', 14, 'S'], 'a': [], 'b': []}, {'path': ['checkpoints', 14, 'latest'], 'a': [], 'b': []}, {'path': ['checkpoints', 15, 'S'], 'a': [], 'b': []}, {'path': ['checkpoints', 15, 'latest'], 'a': [], 'b': []}, {'path': ['checkpoints', 16, 'S'], 'a': [], 'b': []}, {'path': ['checkpoints', 16, 'latest'], 'a': [], 'b': []}, {'path': ['checkpoints', 17, 'S'], 'a': [], 'b': []}, {'path': ['checkpoints', 17, 'latest'], 'a': [], 'b': []}, {'path': ['checkpoints', 18, 'S'], 'a': [], 'b': []}, {'path': ['checkpoints', 18, 'latest'], 'a': [], 'b': []}, {'path': ['checkpoints', 19, 'S'], 'a': [], 'b': []}, {'path': ['checkpoints', 19, 'latest'], 'a': [], 'b': []}, {'path': ['checkpoints', 20, 'S'], 'a': [], 'b': []}, {'path': ['checkpoints', 20, 'latest'], 'a': [], 'b': []}, {'path': ['checkpoints', 21, 'S'], 'a': [], 'b': []}, {'path': ['checkpoints', 21, 'latest'], 'a': [], 'b': []}, {'path': ['checkpoints', 22, 'S'], 'a': [], 'b': []}, {'path': ['checkpoints', 22, 'latest'], 'a': [], 'b': []}, {'path': ['checkpoints', 23, 'S'], 'a': [], 'b': []}, {'path': ['checkpoints', 23, 'latest'], 'a': [], 'b': []}, {'path': ['checkpoints', 24, 'S'], 'a': [], 'b': []}, {'path': ['checkpoints', 24, 'latest'], 'a': [], 'b': []}, {'path': ['checkpoints', 25, 'S'], 'a': [], 'b': []}, {'path': ['checkpoints', 25, 'latest'], 'a': [], 'b': []}, {'path': ['checkpoints', 26, 'S'], 'a': [], 'b': []}, {'path': ['checkpoints', 26, 'latest'], 'a': [], 'b': []}, {'path': ['checkpoints', 27, 'S'], 'a': [], 'b': []}, {'path': ['checkpoints', 27, 'latest'], 'a': [], 'b': []}, {'path': ['checkpoints', 28, 'S'], 'a': [], 'b': []}, {'path': ['checkpoints', 28, 'latest'], 'a': [], 'b': []}, {'path': ['checkpoints', 29, 'S'], 'a': [], 'b': []}, {'path': ['checkpoints', 29, 'latest'], 'a': [], 'b': []}, {'path': ['checkpoints', 30, 'S'], 'a': [], 'b': []}, {'path': ['checkpoints', 30, 'latest'], 'a': [], 'b': []}, {'path': ['events'], 'a': [], 'b': []}, {'path': ['scenarios', 0, 'checkpoints', 0, 'S'], 'a': [], 'b': []}, {'path': ['scenarios', 0, 'checkpoints', 0, 'latest'], 'a': [], 'b': []}, {'path': ['scenarios', 0, 'checkpoints', 1, 'S'], 'a': [], 'b': []}, {'path': ['scenarios', 0, 'checkpoints', 1, 'latest'], 'a': [], 'b': []}], 'digest_modes': [{'path': ['checkpoints', 0], 'mode': 'product latest_digest'}, {'path': ['checkpoints', 1], 'mode': 'product latest_digest'}, {'path': ['checkpoints', 2], 'mode': 'product latest_digest'}, {'path': ['checkpoints', 3], 'mode': 'product latest_digest'}, {'path': ['checkpoints', 4], 'mode': 'product latest_digest'}, {'path': ['checkpoints', 5], 'mode': 'product latest_digest'}, {'path': ['checkpoints', 6], 'mode': 'product latest_digest'}, {'path': ['checkpoints', 7], 'mode': 'product latest_digest'}, {'path': ['checkpoints', 8], 'mode': 'product latest_digest'}, {'path': ['checkpoints', 9], 'mode': 'product latest_digest'}, {'path': ['checkpoints', 10], 'mode': 'product latest_digest'}, {'path': ['checkpoints', 11], 'mode': 'product latest_digest'}, {'path': ['checkpoints', 12], 'mode': 'product latest_digest'}, {'path': ['checkpoints', 13], 'mode': 'product latest_digest'}, {'path': ['checkpoints', 14], 'mode': 'product latest_digest'}, {'path': ['checkpoints', 15], 'mode': 'product latest_digest'}, {'path': ['checkpoints', 16], 'mode': 'product latest_digest'}, {'path': ['checkpoints', 17], 'mode': 'product latest_digest'}, {'path': ['checkpoints', 18], 'mode': 'product latest_digest'}, {'path': ['checkpoints', 19], 'mode': 'product latest_digest'}, {'path': ['checkpoints', 20], 'mode': 'product latest_digest'}, {'path': ['checkpoints', 21], 'mode': 'product latest_digest'}, {'path': ['checkpoints', 22], 'mode': 'product latest_digest'}, {'path': ['checkpoints', 23], 'mode': 'product latest_digest'}, {'path': ['checkpoints', 24], 'mode': 'product latest_digest'}, {'path': ['checkpoints', 25], 'mode': 'product latest_digest'}, {'path': ['checkpoints', 26], 'mode': 'product latest_digest'}, {'path': ['checkpoints', 27], 'mode': 'product latest_digest'}, {'path': ['checkpoints', 28], 'mode': 'product latest_digest'}, {'path': ['checkpoints', 29], 'mode': 'product latest_digest'}, {'path': ['checkpoints', 30], 'mode': 'product latest_digest'}, {'path': ['scenarios', 0, 'checkpoints', 0], 'mode': 'product latest_digest'}, {'path': ['scenarios', 0, 'checkpoints', 1], 'mode': 'product latest_digest'}], 'errors': ['product digest self-consistency']} + +---------------------------------------------------------------------- +Ran 114 tests in 26.564s + +FAILED (failures=1) diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_04.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_04.sha256 new file mode 100644 index 0000000..376be76 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_04.sha256 @@ -0,0 +1 @@ +63204c3415c9b1719fa6aa596b714077a57f530896f979d12b89a15eb2d827e9 UNIT_OUTPUT_S3B_ATTEMPT_04.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_04.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_04.txt new file mode 100644 index 0000000..a05a087 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_04.txt @@ -0,0 +1,119 @@ +test_all_operations (__main__.Diffs) ... ok +test_invalid_operations (__main__.Diffs) ... ok +test_reconstruction_and_proofs (__main__.Diffs) ... ok +test_attempt_to_normalize_violation_rejected (__main__.Normalization) ... ok +test_environment_values_differ_but_normal_form_equal (__main__.Normalization) ... ok +test_every_save_event_reversible (__main__.Normalization) ... ok +test_f3_keeps_relative_paths_and_words (__main__.Normalization) ... ok +test_guard_mismatch (__main__.Normalization) ... ok +test_nested_lookalike_is_not_eligible (__main__.Normalization) ... ok +test_original_transport_sha_detects_forged_timing (__main__.Normalization) ... ok +test_partial_timing_payload_rejected (__main__.Normalization) ... ok +test_prefix_boundary_and_reserved_token (__main__.Normalization) ... ok +test_sidecar_missing_duplicate_and_forged_paths (__main__.Normalization) ... ok +test_snapshot_and_latest_reversible (__main__.Normalization) ... ok +test_snapshot_event_outside_recent_is_not_eligible (__main__.Normalization) ... ok +test_wrong_event_and_source_are_preserved (__main__.Normalization) ... ok +test_wrong_timing_type_and_negative (__main__.Normalization) ... ok +test_all_events_beyond_recent_window (__main__.Reports) ... ok +test_all_semantic_layers_compared (__main__.Reports) ... ok +test_digest_alone_is_not_enough (__main__.Reports) ... ok +test_event_original_types_and_order (__main__.Reports) ... ok +test_event_start_and_ids (__main__.Reports) ... ok +test_exclusions_keep_actual_values (__main__.Reports) ... ok +test_handler_sets_and_counts (__main__.Reports) ... ok +test_observation_full_layers (__main__.Reports) ... ok +test_product_digest_self_consistency (__main__.Reports) ... ok +test_same_report (__main__.Reports) ... ok +test_scenario_existing_failures_preserved (__main__.Reports) ... ok +test_timing_digest_rule (__main__.Reports) ... ok +test_unknown_or_missing_fields_rejected (__main__.Reports) ... ok +test_violation_presence_and_difference (__main__.Reports) ... ok +test_O_cadence (__main__.S2Format) ... ok +test_counter_and_published_ids_binding (__main__.S2Format) ... ok +test_diff_and_same_as_S_transport (__main__.S2Format) ... ok +test_digest_and_scenario_contradiction (__main__.S2Format) ... ok +test_event_no_drop_duplicate_remap (__main__.S2Format) ... ok +test_event_original_field_types_mandatory (__main__.S2Format) ... ok +test_guard_actual_not_assumed (__main__.S2Format) ... ok +test_harness_digest_allows_only_dictionary_order (__main__.S2Format) ... ok +test_join_is_copy_and_retains_normalization_proof (__main__.S2Format) ... ok +test_kernel_cache_contradictions (__main__.S2Format) ... ok +test_lifecycle_guard_errors_and_boundaries (__main__.S2Format) ... ok +test_missing_full_state_not_digest_only (__main__.S2Format) ... ok +test_normalized_digest_and_raw_tree_are_both_bound (__main__.S2Format) ... ok +test_product_event_shape_and_typed_array (__main__.S2Format) ... ok +test_raw_observation_binding (__main__.S2Format) ... ok +test_roundtrip_tree_sha_and_raw_sha (__main__.S2Format) ... ok +test_s2_valid_and_not_formal_acceptance (__main__.S2Format) ... ok +test_state_witness_and_observation_mutation (__main__.S2Format) ... ok +test_stdout_exactly_one_line (__main__.S2Format) ... ok +test_autoload_class_and_script_import (__main__.S2Static) ... ok +test_comment_does_not_supply_proof (__main__.S2Static) ... ok +test_current_probe (__main__.S2Static) ... ok +test_full_state_and_godot_roundtrip_required (__main__.S2Static) ... ok +test_no_changes_outside_preparation_or_step (__main__.S2Static) ... ok +test_no_event_cap_or_duplicate_report (__main__.S2Static) ... ok +test_pause_and_step_arguments (__main__.S2Static) ... ok +test_textual_stringname_ordering (__main__.S2Static) ... ok +test_unlisted_live_method_and_late_preparation (__main__.S2Static) ... ok +test_variant_inference (__main__.S2Static) ... ok +test_X_recent_limit_and_counter (__main__.S3a) ... ok +test_duplicate_JSON_key_rejected (__main__.S3a) ... ok +test_e3_NA_cannot_be_PASS_or_applied (__main__.S3a) ... ok +test_e3_coverage_input_and_event_count_binding (__main__.S3a) ... ok +test_e3_invented_codes_and_missing_load_code (__main__.S3a) ... ok +test_e3_valid_R_and_O_records (__main__.S3a) ... ok +test_envelope_duplicates_not_defect (__main__.S3a) ... ok +test_event_count_defect_not_silently_accepted (__main__.S3a) ... ok +test_exact_phase_keys (__main__.S3a) ... ok +test_interval_gap_rejected (__main__.S3a) ... ok +test_invalid_input_accepted_is_not_PASS (__main__.S3a) ... ok +test_load_payload_and_pause_outcome (__main__.S3a) ... ok +test_operation_moved_outside_scenario_rejected (__main__.S3a) ... ok +test_package_fixed_mutations_and_hashes (__main__.S3a) ... ok +test_probe_connection_required (__main__.S3a) ... ok +test_rejection_mutation_retained_as_defect (__main__.S3a) ... ok +test_save_refusal_makes_load_NA (__main__.S3a) ... ok +test_scenario_mutation_static_boundary (__main__.S3a) ... ok +test_signals_all_minutes_and_order (__main__.S3a) ... ok +test_E5_cached_digest_defect_is_comparable (__main__.S3b) ... ok +test_NA_not_PASS (__main__.S3b) ... ok +test_aliasing_cannot_be_PASS (__main__.S3b) ... ok +test_aliasing_missing_record (__main__.S3b) ... ok +test_all_paths_and_ownership_R_O (__main__.S3b) ... ok +test_digest_materialization_required (__main__.S3b) ... ok +test_empty_registry_not_NA (__main__.S3b) ... ok +test_event_count_mismatch (__main__.S3b) ... ok +test_facts_normalization_is_reversible (__main__.S3b) ... ok +test_first_placeable_choice (__main__.S3b) ... ok +test_interval_gap (__main__.S3b) ... ok +test_load_X_not_digest_only (__main__.S3b) ... ok +test_load_extra_event (__main__.S3b) ... ok +test_missing_path_and_combination (__main__.S3b) ... ok +test_missing_trial (__main__.S3b) ... ok +test_nested_mutation_required (__main__.S3b) ... ok +test_no_staleness_assertion_for_non_tick (__main__.S3b) ... ok +test_path_order (__main__.S3b) ... ok +test_restore_extra_event (__main__.S3b) ... ok +test_sort_rule_rejected (__main__.S3b) ... ok +test_static_handler_and_outside_mutations (__main__.S3b) ... ok +test_unpreviewed_choice (__main__.S3b) ... ok +test_wrong_registry_in_either_role (__main__.S3b) ... ok +test_fixed_scenario_paths (__main__.SourcesAndMetrics) ... ok +test_metric_ranges (__main__.SourcesAndMetrics) ... ok +test_source_closure_synthetic_registered_map (__main__.SourcesAndMetrics) ... ok +test_source_pin_is_not_caller_controlled (__main__.SourcesAndMetrics) ... ok +test_array_order_and_all_differences (__main__.TypedTrees) ... ok +test_components_and_sha (__main__.TypedTrees) ... ok +test_deep_state_not_truncated (__main__.TypedTrees) ... ok +test_duplicate_textual_keys_rejected (__main__.TypedTrees) ... ok +test_exact_and_types (__main__.TypedTrees) ... ok +test_nested_order_all_paths (__main__.TypedTrees) ... ok +test_nonstring_keys_keep_types_and_values (__main__.TypedTrees) ... ok +test_unsupported_and_malformed (__main__.TypedTrees) ... ok + +---------------------------------------------------------------------- +Ran 114 tests in 26.408s + +OK diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_05.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_05.sha256 new file mode 100644 index 0000000..cd2d881 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_05.sha256 @@ -0,0 +1 @@ +bfcb263bf6d7f284fb2b20ee229d96b7c4a9bd7cd5e7b513df1d3ea32580ed6e UNIT_OUTPUT_S3B_ATTEMPT_05.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_05.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_05.txt new file mode 100644 index 0000000..258e106 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_05.txt @@ -0,0 +1,119 @@ +test_all_operations (__main__.Diffs) ... ok +test_invalid_operations (__main__.Diffs) ... ok +test_reconstruction_and_proofs (__main__.Diffs) ... ok +test_attempt_to_normalize_violation_rejected (__main__.Normalization) ... ok +test_environment_values_differ_but_normal_form_equal (__main__.Normalization) ... ok +test_every_save_event_reversible (__main__.Normalization) ... ok +test_f3_keeps_relative_paths_and_words (__main__.Normalization) ... ok +test_guard_mismatch (__main__.Normalization) ... ok +test_nested_lookalike_is_not_eligible (__main__.Normalization) ... ok +test_original_transport_sha_detects_forged_timing (__main__.Normalization) ... ok +test_partial_timing_payload_rejected (__main__.Normalization) ... ok +test_prefix_boundary_and_reserved_token (__main__.Normalization) ... ok +test_sidecar_missing_duplicate_and_forged_paths (__main__.Normalization) ... ok +test_snapshot_and_latest_reversible (__main__.Normalization) ... ok +test_snapshot_event_outside_recent_is_not_eligible (__main__.Normalization) ... ok +test_wrong_event_and_source_are_preserved (__main__.Normalization) ... ok +test_wrong_timing_type_and_negative (__main__.Normalization) ... ok +test_all_events_beyond_recent_window (__main__.Reports) ... ok +test_all_semantic_layers_compared (__main__.Reports) ... ok +test_digest_alone_is_not_enough (__main__.Reports) ... ok +test_event_original_types_and_order (__main__.Reports) ... ok +test_event_start_and_ids (__main__.Reports) ... ok +test_exclusions_keep_actual_values (__main__.Reports) ... ok +test_handler_sets_and_counts (__main__.Reports) ... ok +test_observation_full_layers (__main__.Reports) ... ok +test_product_digest_self_consistency (__main__.Reports) ... ok +test_same_report (__main__.Reports) ... ok +test_scenario_existing_failures_preserved (__main__.Reports) ... ok +test_timing_digest_rule (__main__.Reports) ... ok +test_unknown_or_missing_fields_rejected (__main__.Reports) ... ok +test_violation_presence_and_difference (__main__.Reports) ... ok +test_O_cadence (__main__.S2Format) ... ok +test_counter_and_published_ids_binding (__main__.S2Format) ... ok +test_diff_and_same_as_S_transport (__main__.S2Format) ... ok +test_digest_and_scenario_contradiction (__main__.S2Format) ... ok +test_event_no_drop_duplicate_remap (__main__.S2Format) ... ok +test_event_original_field_types_mandatory (__main__.S2Format) ... ok +test_guard_actual_not_assumed (__main__.S2Format) ... ok +test_harness_digest_allows_only_dictionary_order (__main__.S2Format) ... ok +test_join_is_copy_and_retains_normalization_proof (__main__.S2Format) ... ok +test_kernel_cache_contradictions (__main__.S2Format) ... ok +test_lifecycle_guard_errors_and_boundaries (__main__.S2Format) ... ok +test_missing_full_state_not_digest_only (__main__.S2Format) ... ok +test_normalized_digest_and_raw_tree_are_both_bound (__main__.S2Format) ... ok +test_product_event_shape_and_typed_array (__main__.S2Format) ... ok +test_raw_observation_binding (__main__.S2Format) ... ok +test_roundtrip_tree_sha_and_raw_sha (__main__.S2Format) ... ok +test_s2_valid_and_not_formal_acceptance (__main__.S2Format) ... ok +test_state_witness_and_observation_mutation (__main__.S2Format) ... ok +test_stdout_exactly_one_line (__main__.S2Format) ... ok +test_autoload_class_and_script_import (__main__.S2Static) ... ok +test_comment_does_not_supply_proof (__main__.S2Static) ... ok +test_current_probe (__main__.S2Static) ... ok +test_full_state_and_godot_roundtrip_required (__main__.S2Static) ... ok +test_no_changes_outside_preparation_or_step (__main__.S2Static) ... ok +test_no_event_cap_or_duplicate_report (__main__.S2Static) ... ok +test_pause_and_step_arguments (__main__.S2Static) ... ok +test_textual_stringname_ordering (__main__.S2Static) ... ok +test_unlisted_live_method_and_late_preparation (__main__.S2Static) ... ok +test_variant_inference (__main__.S2Static) ... ok +test_X_recent_limit_and_counter (__main__.S3a) ... ok +test_duplicate_JSON_key_rejected (__main__.S3a) ... ok +test_e3_NA_cannot_be_PASS_or_applied (__main__.S3a) ... ok +test_e3_coverage_input_and_event_count_binding (__main__.S3a) ... ok +test_e3_invented_codes_and_missing_load_code (__main__.S3a) ... ok +test_e3_valid_R_and_O_records (__main__.S3a) ... ok +test_envelope_duplicates_not_defect (__main__.S3a) ... ok +test_event_count_defect_not_silently_accepted (__main__.S3a) ... ok +test_exact_phase_keys (__main__.S3a) ... ok +test_interval_gap_rejected (__main__.S3a) ... ok +test_invalid_input_accepted_is_not_PASS (__main__.S3a) ... ok +test_load_payload_and_pause_outcome (__main__.S3a) ... ok +test_operation_moved_outside_scenario_rejected (__main__.S3a) ... ok +test_package_fixed_mutations_and_hashes (__main__.S3a) ... ok +test_probe_connection_required (__main__.S3a) ... ok +test_rejection_mutation_retained_as_defect (__main__.S3a) ... ok +test_save_refusal_makes_load_NA (__main__.S3a) ... ok +test_scenario_mutation_static_boundary (__main__.S3a) ... ok +test_signals_all_minutes_and_order (__main__.S3a) ... ok +test_E5_cached_digest_defect_is_comparable (__main__.S3b) ... ok +test_NA_not_PASS (__main__.S3b) ... ok +test_aliasing_cannot_be_PASS (__main__.S3b) ... ok +test_aliasing_missing_record (__main__.S3b) ... ok +test_all_paths_and_ownership_R_O (__main__.S3b) ... ok +test_digest_materialization_required (__main__.S3b) ... ok +test_empty_registry_not_NA (__main__.S3b) ... ok +test_event_count_mismatch (__main__.S3b) ... ok +test_facts_normalization_is_reversible (__main__.S3b) ... ok +test_first_placeable_choice (__main__.S3b) ... ok +test_interval_gap (__main__.S3b) ... ok +test_load_X_not_digest_only (__main__.S3b) ... ok +test_load_extra_event (__main__.S3b) ... ok +test_missing_path_and_combination (__main__.S3b) ... ok +test_missing_trial (__main__.S3b) ... ok +test_nested_mutation_required (__main__.S3b) ... ok +test_no_staleness_assertion_for_non_tick (__main__.S3b) ... ok +test_path_order (__main__.S3b) ... ok +test_restore_extra_event (__main__.S3b) ... ok +test_sort_rule_rejected (__main__.S3b) ... ok +test_static_handler_and_outside_mutations (__main__.S3b) ... ok +test_unpreviewed_choice (__main__.S3b) ... ok +test_wrong_registry_in_either_role (__main__.S3b) ... ok +test_fixed_scenario_paths (__main__.SourcesAndMetrics) ... ok +test_metric_ranges (__main__.SourcesAndMetrics) ... ok +test_source_closure_synthetic_registered_map (__main__.SourcesAndMetrics) ... ok +test_source_pin_is_not_caller_controlled (__main__.SourcesAndMetrics) ... ok +test_array_order_and_all_differences (__main__.TypedTrees) ... ok +test_components_and_sha (__main__.TypedTrees) ... ok +test_deep_state_not_truncated (__main__.TypedTrees) ... ok +test_duplicate_textual_keys_rejected (__main__.TypedTrees) ... ok +test_exact_and_types (__main__.TypedTrees) ... ok +test_nested_order_all_paths (__main__.TypedTrees) ... ok +test_nonstring_keys_keep_types_and_values (__main__.TypedTrees) ... ok +test_unsupported_and_malformed (__main__.TypedTrees) ... ok + +---------------------------------------------------------------------- +Ran 114 tests in 26.528s + +OK diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_06.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_06.sha256 new file mode 100644 index 0000000..0e0afae --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_06.sha256 @@ -0,0 +1 @@ +7d9bf9c602a93aca06d03eb06025beeea35603d453e293c07e7a6f81ca9ca000 UNIT_OUTPUT_S3B_ATTEMPT_06.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_06.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_06.txt new file mode 100644 index 0000000..7ad54c3 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_06.txt @@ -0,0 +1,123 @@ +test_all_operations (__main__.Diffs) ... ok +test_invalid_operations (__main__.Diffs) ... ok +test_reconstruction_and_proofs (__main__.Diffs) ... ok +test_attempt_to_normalize_violation_rejected (__main__.Normalization) ... ok +test_environment_values_differ_but_normal_form_equal (__main__.Normalization) ... ok +test_every_save_event_reversible (__main__.Normalization) ... ok +test_f3_keeps_relative_paths_and_words (__main__.Normalization) ... ok +test_guard_mismatch (__main__.Normalization) ... ok +test_nested_lookalike_is_not_eligible (__main__.Normalization) ... ok +test_original_transport_sha_detects_forged_timing (__main__.Normalization) ... ok +test_partial_timing_payload_rejected (__main__.Normalization) ... ok +test_prefix_boundary_and_reserved_token (__main__.Normalization) ... ok +test_sidecar_missing_duplicate_and_forged_paths (__main__.Normalization) ... ok +test_snapshot_and_latest_reversible (__main__.Normalization) ... ok +test_snapshot_event_outside_recent_is_not_eligible (__main__.Normalization) ... ok +test_wrong_event_and_source_are_preserved (__main__.Normalization) ... ok +test_wrong_timing_type_and_negative (__main__.Normalization) ... ok +test_all_events_beyond_recent_window (__main__.Reports) ... ok +test_all_semantic_layers_compared (__main__.Reports) ... ok +test_digest_alone_is_not_enough (__main__.Reports) ... ok +test_event_original_types_and_order (__main__.Reports) ... ok +test_event_start_and_ids (__main__.Reports) ... ok +test_exclusions_keep_actual_values (__main__.Reports) ... ok +test_handler_sets_and_counts (__main__.Reports) ... ok +test_observation_full_layers (__main__.Reports) ... ok +test_product_digest_self_consistency (__main__.Reports) ... ok +test_same_report (__main__.Reports) ... ok +test_scenario_existing_failures_preserved (__main__.Reports) ... ok +test_timing_digest_rule (__main__.Reports) ... ok +test_unknown_or_missing_fields_rejected (__main__.Reports) ... ok +test_violation_presence_and_difference (__main__.Reports) ... ok +test_O_cadence (__main__.S2Format) ... ok +test_counter_and_published_ids_binding (__main__.S2Format) ... ok +test_diff_and_same_as_S_transport (__main__.S2Format) ... ok +test_digest_and_scenario_contradiction (__main__.S2Format) ... ok +test_event_no_drop_duplicate_remap (__main__.S2Format) ... ok +test_event_original_field_types_mandatory (__main__.S2Format) ... ok +test_guard_actual_not_assumed (__main__.S2Format) ... ok +test_harness_digest_allows_only_dictionary_order (__main__.S2Format) ... ok +test_join_is_copy_and_retains_normalization_proof (__main__.S2Format) ... ok +test_kernel_cache_contradictions (__main__.S2Format) ... ok +test_lifecycle_guard_errors_and_boundaries (__main__.S2Format) ... ok +test_missing_full_state_not_digest_only (__main__.S2Format) ... ok +test_normalized_digest_and_raw_tree_are_both_bound (__main__.S2Format) ... ok +test_product_event_shape_and_typed_array (__main__.S2Format) ... ok +test_raw_observation_binding (__main__.S2Format) ... ok +test_roundtrip_tree_sha_and_raw_sha (__main__.S2Format) ... ok +test_s2_valid_and_not_formal_acceptance (__main__.S2Format) ... ok +test_state_witness_and_observation_mutation (__main__.S2Format) ... ok +test_stdout_exactly_one_line (__main__.S2Format) ... ok +test_autoload_class_and_script_import (__main__.S2Static) ... ok +test_comment_does_not_supply_proof (__main__.S2Static) ... ok +test_current_probe (__main__.S2Static) ... ok +test_full_state_and_godot_roundtrip_required (__main__.S2Static) ... ok +test_no_changes_outside_preparation_or_step (__main__.S2Static) ... ok +test_no_event_cap_or_duplicate_report (__main__.S2Static) ... ok +test_pause_and_step_arguments (__main__.S2Static) ... ok +test_textual_stringname_ordering (__main__.S2Static) ... ok +test_unlisted_live_method_and_late_preparation (__main__.S2Static) ... ok +test_variant_inference (__main__.S2Static) ... ok +test_X_recent_limit_and_counter (__main__.S3a) ... ok +test_duplicate_JSON_key_rejected (__main__.S3a) ... ok +test_e3_NA_cannot_be_PASS_or_applied (__main__.S3a) ... ok +test_e3_coverage_input_and_event_count_binding (__main__.S3a) ... ok +test_e3_invented_codes_and_missing_load_code (__main__.S3a) ... ok +test_e3_valid_R_and_O_records (__main__.S3a) ... ok +test_envelope_duplicates_not_defect (__main__.S3a) ... ok +test_event_count_defect_not_silently_accepted (__main__.S3a) ... ok +test_exact_phase_keys (__main__.S3a) ... ok +test_interval_gap_rejected (__main__.S3a) ... ok +test_invalid_input_accepted_is_not_PASS (__main__.S3a) ... ok +test_load_payload_and_pause_outcome (__main__.S3a) ... ok +test_operation_moved_outside_scenario_rejected (__main__.S3a) ... ok +test_package_fixed_mutations_and_hashes (__main__.S3a) ... ok +test_probe_connection_required (__main__.S3a) ... ok +test_rejection_mutation_retained_as_defect (__main__.S3a) ... ok +test_save_refusal_makes_load_NA (__main__.S3a) ... ok +test_scenario_mutation_static_boundary (__main__.S3a) ... ok +test_signals_all_minutes_and_order (__main__.S3a) ... ok +test_E5_cached_digest_defect_is_comparable (__main__.S3b) ... ok +test_NA_not_PASS (__main__.S3b) ... ok +test_aliasing_cannot_be_PASS (__main__.S3b) ... ok +test_aliasing_missing_record (__main__.S3b) ... ok +test_all_paths_and_ownership_R_O (__main__.S3b) ... ok +test_digest_defect_other_checkpoint_still_rejected (__main__.S3b) ... ok +test_digest_materialization_required (__main__.S3b) ... ok +test_empty_registry_not_NA (__main__.S3b) ... ok +test_event_count_mismatch (__main__.S3b) ... ok +test_facts_normalization_is_reversible (__main__.S3b) ... ok +test_first_placeable_choice (__main__.S3b) ... ok +test_interval_gap (__main__.S3b) ... ok +test_joined_s3b_self_comparison (__main__.S3b) ... ok +test_load_X_not_digest_only (__main__.S3b) ... ok +test_load_extra_event (__main__.S3b) ... ok +test_missing_path_and_combination (__main__.S3b) ... ok +test_missing_preview_observation (__main__.S3b) ... ok +test_missing_trial (__main__.S3b) ... ok +test_nested_mutation_required (__main__.S3b) ... ok +test_no_staleness_assertion_for_non_tick (__main__.S3b) ... ok +test_path_order (__main__.S3b) ... ok +test_restore_extra_event (__main__.S3b) ... ok +test_signal_facts_cannot_be_dropped (__main__.S3b) ... ok +test_sort_rule_rejected (__main__.S3b) ... ok +test_static_handler_and_outside_mutations (__main__.S3b) ... ok +test_unpreviewed_choice (__main__.S3b) ... ok +test_wrong_registry_in_either_role (__main__.S3b) ... ok +test_fixed_scenario_paths (__main__.SourcesAndMetrics) ... ok +test_metric_ranges (__main__.SourcesAndMetrics) ... ok +test_source_closure_synthetic_registered_map (__main__.SourcesAndMetrics) ... ok +test_source_pin_is_not_caller_controlled (__main__.SourcesAndMetrics) ... ok +test_array_order_and_all_differences (__main__.TypedTrees) ... ok +test_components_and_sha (__main__.TypedTrees) ... ok +test_deep_state_not_truncated (__main__.TypedTrees) ... ok +test_duplicate_textual_keys_rejected (__main__.TypedTrees) ... ok +test_exact_and_types (__main__.TypedTrees) ... ok +test_nested_order_all_paths (__main__.TypedTrees) ... ok +test_nonstring_keys_keep_types_and_values (__main__.TypedTrees) ... ok +test_unsupported_and_malformed (__main__.TypedTrees) ... ok + +---------------------------------------------------------------------- +Ran 118 tests in 31.744s + +OK diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_07.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_07.sha256 new file mode 100644 index 0000000..68e3e3e --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_07.sha256 @@ -0,0 +1 @@ +f7c7c045ea98a366810b7c309fc1a87a77ccc5d8e823750eebaa742c9529e2ca UNIT_OUTPUT_S3B_ATTEMPT_07.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_07.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_07.txt new file mode 100644 index 0000000..ed83d4f --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_07.txt @@ -0,0 +1,14 @@ +test_ownership_fact_dictionary_order_fallback (__main__.S3b) ... FAIL + +====================================================================== +FAIL: test_ownership_fact_dictionary_order_fallback (__main__.S3b) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1233, in test_ownership_fact_dictionary_order_fallback + self.assertTrue(result['ok'], result['differences']) +AssertionError: False is not true : [{'path': ['scenarios', 0, 'result'], 'a': {'facts': {'held_before': [27, [[[4, 'a'], [2, 1]], [[4, 'b'], [2, 2]]], None]}}, 'b': {'facts': {'held_before': [27, [[[4, 'b'], [2, 2]], [[4, 'a'], [2, 1]]], None]}}}] + +---------------------------------------------------------------------- +Ran 1 test in 0.036s + +FAILED (failures=1) diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_08.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_08.sha256 new file mode 100644 index 0000000..96aeb35 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_08.sha256 @@ -0,0 +1 @@ +19c3f115d6a73bf91413877878f5d5f9d78a3e253dae3ddba7dfec9b5d46eaba UNIT_OUTPUT_S3B_ATTEMPT_08.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_08.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_08.txt new file mode 100644 index 0000000..4783bfd --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_08.txt @@ -0,0 +1,132 @@ +test_all_operations (__main__.Diffs) ... ok +test_invalid_operations (__main__.Diffs) ... ok +test_reconstruction_and_proofs (__main__.Diffs) ... ok +test_attempt_to_normalize_violation_rejected (__main__.Normalization) ... ok +test_environment_values_differ_but_normal_form_equal (__main__.Normalization) ... ok +test_every_save_event_reversible (__main__.Normalization) ... ok +test_f3_keeps_relative_paths_and_words (__main__.Normalization) ... ok +test_guard_mismatch (__main__.Normalization) ... ok +test_nested_lookalike_is_not_eligible (__main__.Normalization) ... ok +test_original_transport_sha_detects_forged_timing (__main__.Normalization) ... ok +test_partial_timing_payload_rejected (__main__.Normalization) ... ok +test_prefix_boundary_and_reserved_token (__main__.Normalization) ... ok +test_sidecar_missing_duplicate_and_forged_paths (__main__.Normalization) ... ok +test_snapshot_and_latest_reversible (__main__.Normalization) ... ok +test_snapshot_event_outside_recent_is_not_eligible (__main__.Normalization) ... ok +test_wrong_event_and_source_are_preserved (__main__.Normalization) ... ok +test_wrong_timing_type_and_negative (__main__.Normalization) ... ok +test_all_events_beyond_recent_window (__main__.Reports) ... ok +test_all_semantic_layers_compared (__main__.Reports) ... ok +test_digest_alone_is_not_enough (__main__.Reports) ... ok +test_event_original_types_and_order (__main__.Reports) ... ok +test_event_start_and_ids (__main__.Reports) ... ok +test_exclusions_keep_actual_values (__main__.Reports) ... ok +test_handler_sets_and_counts (__main__.Reports) ... ok +test_observation_full_layers (__main__.Reports) ... ok +test_product_digest_self_consistency (__main__.Reports) ... ok +test_same_report (__main__.Reports) ... ok +test_scenario_existing_failures_preserved (__main__.Reports) ... ok +test_timing_digest_rule (__main__.Reports) ... ok +test_unknown_or_missing_fields_rejected (__main__.Reports) ... ok +test_violation_presence_and_difference (__main__.Reports) ... ok +test_O_cadence (__main__.S2Format) ... ok +test_counter_and_published_ids_binding (__main__.S2Format) ... ok +test_diff_and_same_as_S_transport (__main__.S2Format) ... ok +test_digest_and_scenario_contradiction (__main__.S2Format) ... ok +test_event_no_drop_duplicate_remap (__main__.S2Format) ... ok +test_event_original_field_types_mandatory (__main__.S2Format) ... ok +test_guard_actual_not_assumed (__main__.S2Format) ... ok +test_harness_digest_allows_only_dictionary_order (__main__.S2Format) ... ok +test_join_is_copy_and_retains_normalization_proof (__main__.S2Format) ... ok +test_kernel_cache_contradictions (__main__.S2Format) ... ok +test_lifecycle_guard_errors_and_boundaries (__main__.S2Format) ... ok +test_missing_full_state_not_digest_only (__main__.S2Format) ... ok +test_normalized_digest_and_raw_tree_are_both_bound (__main__.S2Format) ... ok +test_product_event_shape_and_typed_array (__main__.S2Format) ... ok +test_raw_observation_binding (__main__.S2Format) ... ok +test_roundtrip_tree_sha_and_raw_sha (__main__.S2Format) ... ok +test_s2_valid_and_not_formal_acceptance (__main__.S2Format) ... ok +test_state_witness_and_observation_mutation (__main__.S2Format) ... ok +test_stdout_exactly_one_line (__main__.S2Format) ... ok +test_autoload_class_and_script_import (__main__.S2Static) ... ok +test_comment_does_not_supply_proof (__main__.S2Static) ... ok +test_current_probe (__main__.S2Static) ... ok +test_full_state_and_godot_roundtrip_required (__main__.S2Static) ... ok +test_no_changes_outside_preparation_or_step (__main__.S2Static) ... ok +test_no_event_cap_or_duplicate_report (__main__.S2Static) ... ok +test_pause_and_step_arguments (__main__.S2Static) ... ok +test_textual_stringname_ordering (__main__.S2Static) ... ok +test_unlisted_live_method_and_late_preparation (__main__.S2Static) ... ok +test_variant_inference (__main__.S2Static) ... ok +test_X_recent_limit_and_counter (__main__.S3a) ... ok +test_duplicate_JSON_key_rejected (__main__.S3a) ... ok +test_e3_NA_cannot_be_PASS_or_applied (__main__.S3a) ... ok +test_e3_coverage_input_and_event_count_binding (__main__.S3a) ... ok +test_e3_invented_codes_and_missing_load_code (__main__.S3a) ... ok +test_e3_valid_R_and_O_records (__main__.S3a) ... ok +test_envelope_duplicates_not_defect (__main__.S3a) ... ok +test_event_count_defect_not_silently_accepted (__main__.S3a) ... ok +test_exact_phase_keys (__main__.S3a) ... ok +test_interval_gap_rejected (__main__.S3a) ... ok +test_invalid_input_accepted_is_not_PASS (__main__.S3a) ... ok +test_load_payload_and_pause_outcome (__main__.S3a) ... ok +test_operation_moved_outside_scenario_rejected (__main__.S3a) ... ok +test_package_fixed_mutations_and_hashes (__main__.S3a) ... ok +test_probe_connection_required (__main__.S3a) ... ok +test_rejection_mutation_retained_as_defect (__main__.S3a) ... ok +test_save_refusal_makes_load_NA (__main__.S3a) ... ok +test_scenario_mutation_static_boundary (__main__.S3a) ... ok +test_signals_all_minutes_and_order (__main__.S3a) ... ok +test_E5_cached_digest_defect_is_comparable (__main__.S3b) ... ok +test_NA_not_PASS (__main__.S3b) ... ok +test_aliasing_cannot_be_PASS (__main__.S3b) ... ok +test_aliasing_missing_record (__main__.S3b) ... ok +test_all_paths_and_ownership_R_O (__main__.S3b) ... ok +test_digest_defect_other_checkpoint_still_rejected (__main__.S3b) ... ok +test_digest_materialization_required (__main__.S3b) ... ok +test_empty_registry_not_NA (__main__.S3b) ... ok +test_event_count_mismatch (__main__.S3b) ... ok +test_facts_normalization_is_reversible (__main__.S3b) ... ok +test_first_placeable_choice (__main__.S3b) ... ok +test_interval_gap (__main__.S3b) ... ok +test_joined_s3b_self_comparison (__main__.S3b) ... ok +test_load_X_not_digest_only (__main__.S3b) ... ok +test_load_extra_event (__main__.S3b) ... ok +test_missing_path_and_combination (__main__.S3b) ... ok +test_missing_preview_observation (__main__.S3b) ... ok +test_missing_trial (__main__.S3b) ... ok +test_nested_mutation_required (__main__.S3b) ... ok +test_no_staleness_assertion_for_non_tick (__main__.S3b) ... ok +test_ownership_fact_dictionary_order_fallback (__main__.S3b) ... FAIL +test_path_order (__main__.S3b) ... ok +test_restore_extra_event (__main__.S3b) ... ok +test_signal_facts_cannot_be_dropped (__main__.S3b) ... ok +test_sort_rule_rejected (__main__.S3b) ... ok +test_static_handler_and_outside_mutations (__main__.S3b) ... ok +test_unpreviewed_choice (__main__.S3b) ... ok +test_wrong_registry_in_either_role (__main__.S3b) ... ok +test_fixed_scenario_paths (__main__.SourcesAndMetrics) ... ok +test_metric_ranges (__main__.SourcesAndMetrics) ... ok +test_source_closure_synthetic_registered_map (__main__.SourcesAndMetrics) ... ok +test_source_pin_is_not_caller_controlled (__main__.SourcesAndMetrics) ... ok +test_array_order_and_all_differences (__main__.TypedTrees) ... ok +test_components_and_sha (__main__.TypedTrees) ... ok +test_deep_state_not_truncated (__main__.TypedTrees) ... ok +test_duplicate_textual_keys_rejected (__main__.TypedTrees) ... ok +test_exact_and_types (__main__.TypedTrees) ... ok +test_nested_order_all_paths (__main__.TypedTrees) ... ok +test_nonstring_keys_keep_types_and_values (__main__.TypedTrees) ... ok +test_unsupported_and_malformed (__main__.TypedTrees) ... ok + +====================================================================== +FAIL: test_ownership_fact_dictionary_order_fallback (__main__.S3b) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1233, in test_ownership_fact_dictionary_order_fallback + self.assertTrue(result['ok'], result['differences']) +AssertionError: False is not true : [] + +---------------------------------------------------------------------- +Ran 119 tests in 31.877s + +FAILED (failures=1) diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_09.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_09.sha256 new file mode 100644 index 0000000..540c2dd --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_09.sha256 @@ -0,0 +1 @@ +8360a2065b303099d5c546b3e4aecc0cc0ab0c2c1e5120b8034b6a1a64317030 UNIT_OUTPUT_S3B_ATTEMPT_09.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_09.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_09.txt new file mode 100644 index 0000000..69b6013 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S3B_ATTEMPT_09.txt @@ -0,0 +1,124 @@ +test_all_operations (__main__.Diffs) ... ok +test_invalid_operations (__main__.Diffs) ... ok +test_reconstruction_and_proofs (__main__.Diffs) ... ok +test_attempt_to_normalize_violation_rejected (__main__.Normalization) ... ok +test_environment_values_differ_but_normal_form_equal (__main__.Normalization) ... ok +test_every_save_event_reversible (__main__.Normalization) ... ok +test_f3_keeps_relative_paths_and_words (__main__.Normalization) ... ok +test_guard_mismatch (__main__.Normalization) ... ok +test_nested_lookalike_is_not_eligible (__main__.Normalization) ... ok +test_original_transport_sha_detects_forged_timing (__main__.Normalization) ... ok +test_partial_timing_payload_rejected (__main__.Normalization) ... ok +test_prefix_boundary_and_reserved_token (__main__.Normalization) ... ok +test_sidecar_missing_duplicate_and_forged_paths (__main__.Normalization) ... ok +test_snapshot_and_latest_reversible (__main__.Normalization) ... ok +test_snapshot_event_outside_recent_is_not_eligible (__main__.Normalization) ... ok +test_wrong_event_and_source_are_preserved (__main__.Normalization) ... ok +test_wrong_timing_type_and_negative (__main__.Normalization) ... ok +test_all_events_beyond_recent_window (__main__.Reports) ... ok +test_all_semantic_layers_compared (__main__.Reports) ... ok +test_digest_alone_is_not_enough (__main__.Reports) ... ok +test_event_original_types_and_order (__main__.Reports) ... ok +test_event_start_and_ids (__main__.Reports) ... ok +test_exclusions_keep_actual_values (__main__.Reports) ... ok +test_handler_sets_and_counts (__main__.Reports) ... ok +test_observation_full_layers (__main__.Reports) ... ok +test_product_digest_self_consistency (__main__.Reports) ... ok +test_same_report (__main__.Reports) ... ok +test_scenario_existing_failures_preserved (__main__.Reports) ... ok +test_timing_digest_rule (__main__.Reports) ... ok +test_unknown_or_missing_fields_rejected (__main__.Reports) ... ok +test_violation_presence_and_difference (__main__.Reports) ... ok +test_O_cadence (__main__.S2Format) ... ok +test_counter_and_published_ids_binding (__main__.S2Format) ... ok +test_diff_and_same_as_S_transport (__main__.S2Format) ... ok +test_digest_and_scenario_contradiction (__main__.S2Format) ... ok +test_event_no_drop_duplicate_remap (__main__.S2Format) ... ok +test_event_original_field_types_mandatory (__main__.S2Format) ... ok +test_guard_actual_not_assumed (__main__.S2Format) ... ok +test_harness_digest_allows_only_dictionary_order (__main__.S2Format) ... ok +test_join_is_copy_and_retains_normalization_proof (__main__.S2Format) ... ok +test_kernel_cache_contradictions (__main__.S2Format) ... ok +test_lifecycle_guard_errors_and_boundaries (__main__.S2Format) ... ok +test_missing_full_state_not_digest_only (__main__.S2Format) ... ok +test_normalized_digest_and_raw_tree_are_both_bound (__main__.S2Format) ... ok +test_product_event_shape_and_typed_array (__main__.S2Format) ... ok +test_raw_observation_binding (__main__.S2Format) ... ok +test_roundtrip_tree_sha_and_raw_sha (__main__.S2Format) ... ok +test_s2_valid_and_not_formal_acceptance (__main__.S2Format) ... ok +test_state_witness_and_observation_mutation (__main__.S2Format) ... ok +test_stdout_exactly_one_line (__main__.S2Format) ... ok +test_autoload_class_and_script_import (__main__.S2Static) ... ok +test_comment_does_not_supply_proof (__main__.S2Static) ... ok +test_current_probe (__main__.S2Static) ... ok +test_full_state_and_godot_roundtrip_required (__main__.S2Static) ... ok +test_no_changes_outside_preparation_or_step (__main__.S2Static) ... ok +test_no_event_cap_or_duplicate_report (__main__.S2Static) ... ok +test_pause_and_step_arguments (__main__.S2Static) ... ok +test_textual_stringname_ordering (__main__.S2Static) ... ok +test_unlisted_live_method_and_late_preparation (__main__.S2Static) ... ok +test_variant_inference (__main__.S2Static) ... ok +test_X_recent_limit_and_counter (__main__.S3a) ... ok +test_duplicate_JSON_key_rejected (__main__.S3a) ... ok +test_e3_NA_cannot_be_PASS_or_applied (__main__.S3a) ... ok +test_e3_coverage_input_and_event_count_binding (__main__.S3a) ... ok +test_e3_invented_codes_and_missing_load_code (__main__.S3a) ... ok +test_e3_valid_R_and_O_records (__main__.S3a) ... ok +test_envelope_duplicates_not_defect (__main__.S3a) ... ok +test_event_count_defect_not_silently_accepted (__main__.S3a) ... ok +test_exact_phase_keys (__main__.S3a) ... ok +test_interval_gap_rejected (__main__.S3a) ... ok +test_invalid_input_accepted_is_not_PASS (__main__.S3a) ... ok +test_load_payload_and_pause_outcome (__main__.S3a) ... ok +test_operation_moved_outside_scenario_rejected (__main__.S3a) ... ok +test_package_fixed_mutations_and_hashes (__main__.S3a) ... ok +test_probe_connection_required (__main__.S3a) ... ok +test_rejection_mutation_retained_as_defect (__main__.S3a) ... ok +test_save_refusal_makes_load_NA (__main__.S3a) ... ok +test_scenario_mutation_static_boundary (__main__.S3a) ... ok +test_signals_all_minutes_and_order (__main__.S3a) ... ok +test_E5_cached_digest_defect_is_comparable (__main__.S3b) ... ok +test_NA_not_PASS (__main__.S3b) ... ok +test_aliasing_cannot_be_PASS (__main__.S3b) ... ok +test_aliasing_missing_record (__main__.S3b) ... ok +test_all_paths_and_ownership_R_O (__main__.S3b) ... ok +test_digest_defect_other_checkpoint_still_rejected (__main__.S3b) ... ok +test_digest_materialization_required (__main__.S3b) ... ok +test_empty_registry_not_NA (__main__.S3b) ... ok +test_event_count_mismatch (__main__.S3b) ... ok +test_facts_normalization_is_reversible (__main__.S3b) ... ok +test_first_placeable_choice (__main__.S3b) ... ok +test_interval_gap (__main__.S3b) ... ok +test_joined_s3b_self_comparison (__main__.S3b) ... ok +test_load_X_not_digest_only (__main__.S3b) ... ok +test_load_extra_event (__main__.S3b) ... ok +test_missing_path_and_combination (__main__.S3b) ... ok +test_missing_preview_observation (__main__.S3b) ... ok +test_missing_trial (__main__.S3b) ... ok +test_nested_mutation_required (__main__.S3b) ... ok +test_no_staleness_assertion_for_non_tick (__main__.S3b) ... ok +test_ownership_fact_dictionary_order_fallback (__main__.S3b) ... ok +test_path_order (__main__.S3b) ... ok +test_restore_extra_event (__main__.S3b) ... ok +test_signal_facts_cannot_be_dropped (__main__.S3b) ... ok +test_sort_rule_rejected (__main__.S3b) ... ok +test_static_handler_and_outside_mutations (__main__.S3b) ... ok +test_unpreviewed_choice (__main__.S3b) ... ok +test_wrong_registry_in_either_role (__main__.S3b) ... ok +test_fixed_scenario_paths (__main__.SourcesAndMetrics) ... ok +test_metric_ranges (__main__.SourcesAndMetrics) ... ok +test_source_closure_synthetic_registered_map (__main__.SourcesAndMetrics) ... ok +test_source_pin_is_not_caller_controlled (__main__.SourcesAndMetrics) ... ok +test_array_order_and_all_differences (__main__.TypedTrees) ... ok +test_components_and_sha (__main__.TypedTrees) ... ok +test_deep_state_not_truncated (__main__.TypedTrees) ... ok +test_duplicate_textual_keys_rejected (__main__.TypedTrees) ... ok +test_exact_and_types (__main__.TypedTrees) ... ok +test_nested_order_all_paths (__main__.TypedTrees) ... ok +test_nonstring_keys_keep_types_and_values (__main__.TypedTrees) ... ok +test_unsupported_and_malformed (__main__.TypedTrees) ... ok + +---------------------------------------------------------------------- +Ran 119 tests in 32.034s + +OK diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_01.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_01.sha256 new file mode 100644 index 0000000..e777270 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_01.sha256 @@ -0,0 +1 @@ +ff9620ce295f2f2edc25e9b0014ac4db221e1b26e8ba1b0f20c20e7e5d045ce9 UNIT_OUTPUT_S4_ATTEMPT_01.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_01.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_01.txt new file mode 100644 index 0000000..509fc91 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_01.txt @@ -0,0 +1,10 @@ +Traceback (most recent call last): + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1241, in + import run_eq as driver + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/run_eq.py", line 16, in + import verify_eq as verify + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/verify_eq.py", line 18, in + NAMES = {f'{prefix}-{i:02d}.json' for prefix, count in + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/verify_eq.py", line 18, in + NAMES = {f'{prefix}-{i:02d}.json' for prefix, count in +NameError: name 'i' is not defined diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_02.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_02.sha256 new file mode 100644 index 0000000..e62cf93 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_02.sha256 @@ -0,0 +1 @@ +140d2c270f7c15297bed638c23dd38295381eebacc123fccdc112d32162dcefe UNIT_OUTPUT_S4_ATTEMPT_02.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_02.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_02.txt new file mode 100644 index 0000000..dd3afc6 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_02.txt @@ -0,0 +1,328 @@ +test_all_operations (__main__.Diffs) ... ok +test_invalid_operations (__main__.Diffs) ... ok +test_reconstruction_and_proofs (__main__.Diffs) ... ok +test_attempt_to_normalize_violation_rejected (__main__.Normalization) ... ok +test_environment_values_differ_but_normal_form_equal (__main__.Normalization) ... ok +test_every_save_event_reversible (__main__.Normalization) ... ok +test_f3_keeps_relative_paths_and_words (__main__.Normalization) ... ok +test_guard_mismatch (__main__.Normalization) ... ok +test_nested_lookalike_is_not_eligible (__main__.Normalization) ... ok +test_original_transport_sha_detects_forged_timing (__main__.Normalization) ... ok +test_partial_timing_payload_rejected (__main__.Normalization) ... ok +test_prefix_boundary_and_reserved_token (__main__.Normalization) ... ok +test_sidecar_missing_duplicate_and_forged_paths (__main__.Normalization) ... ok +test_snapshot_and_latest_reversible (__main__.Normalization) ... ok +test_snapshot_event_outside_recent_is_not_eligible (__main__.Normalization) ... ok +test_wrong_event_and_source_are_preserved (__main__.Normalization) ... ok +test_wrong_timing_type_and_negative (__main__.Normalization) ... ok +test_all_events_beyond_recent_window (__main__.Reports) ... ok +test_all_semantic_layers_compared (__main__.Reports) ... ok +test_digest_alone_is_not_enough (__main__.Reports) ... ok +test_event_original_types_and_order (__main__.Reports) ... ok +test_event_start_and_ids (__main__.Reports) ... ok +test_exclusions_keep_actual_values (__main__.Reports) ... ok +test_handler_sets_and_counts (__main__.Reports) ... ok +test_observation_full_layers (__main__.Reports) ... ok +test_product_digest_self_consistency (__main__.Reports) ... ok +test_same_report (__main__.Reports) ... ok +test_scenario_existing_failures_preserved (__main__.Reports) ... ok +test_timing_digest_rule (__main__.Reports) ... ok +test_unknown_or_missing_fields_rejected (__main__.Reports) ... ok +test_violation_presence_and_difference (__main__.Reports) ... ok +test_O_cadence (__main__.S2Format) ... ok +test_counter_and_published_ids_binding (__main__.S2Format) ... ok +test_diff_and_same_as_S_transport (__main__.S2Format) ... ok +test_digest_and_scenario_contradiction (__main__.S2Format) ... ok +test_event_no_drop_duplicate_remap (__main__.S2Format) ... ok +test_event_original_field_types_mandatory (__main__.S2Format) ... ok +test_guard_actual_not_assumed (__main__.S2Format) ... ok +test_harness_digest_allows_only_dictionary_order (__main__.S2Format) ... ok +test_join_is_copy_and_retains_normalization_proof (__main__.S2Format) ... ok +test_kernel_cache_contradictions (__main__.S2Format) ... ok +test_lifecycle_guard_errors_and_boundaries (__main__.S2Format) ... ok +test_missing_full_state_not_digest_only (__main__.S2Format) ... ok +test_normalized_digest_and_raw_tree_are_both_bound (__main__.S2Format) ... ok +test_product_event_shape_and_typed_array (__main__.S2Format) ... ok +test_raw_observation_binding (__main__.S2Format) ... ok +test_roundtrip_tree_sha_and_raw_sha (__main__.S2Format) ... ok +test_s2_valid_and_not_formal_acceptance (__main__.S2Format) ... ok +test_state_witness_and_observation_mutation (__main__.S2Format) ... ok +test_stdout_exactly_one_line (__main__.S2Format) ... ok +test_autoload_class_and_script_import (__main__.S2Static) ... ok +test_comment_does_not_supply_proof (__main__.S2Static) ... ok +test_current_probe (__main__.S2Static) ... ok +test_full_state_and_godot_roundtrip_required (__main__.S2Static) ... ok +test_no_changes_outside_preparation_or_step (__main__.S2Static) ... ok +test_no_event_cap_or_duplicate_report (__main__.S2Static) ... ok +test_pause_and_step_arguments (__main__.S2Static) ... ok +test_textual_stringname_ordering (__main__.S2Static) ... ok +test_unlisted_live_method_and_late_preparation (__main__.S2Static) ... ok +test_variant_inference (__main__.S2Static) ... ok +test_X_recent_limit_and_counter (__main__.S3a) ... ok +test_duplicate_JSON_key_rejected (__main__.S3a) ... ok +test_e3_NA_cannot_be_PASS_or_applied (__main__.S3a) ... ok +test_e3_coverage_input_and_event_count_binding (__main__.S3a) ... ok +test_e3_invented_codes_and_missing_load_code (__main__.S3a) ... ok +test_e3_valid_R_and_O_records (__main__.S3a) ... ok +test_envelope_duplicates_not_defect (__main__.S3a) ... ok +test_event_count_defect_not_silently_accepted (__main__.S3a) ... ok +test_exact_phase_keys (__main__.S3a) ... ok +test_interval_gap_rejected (__main__.S3a) ... ok +test_invalid_input_accepted_is_not_PASS (__main__.S3a) ... ok +test_load_payload_and_pause_outcome (__main__.S3a) ... ok +test_operation_moved_outside_scenario_rejected (__main__.S3a) ... ok +test_package_fixed_mutations_and_hashes (__main__.S3a) ... ok +test_probe_connection_required (__main__.S3a) ... ok +test_rejection_mutation_retained_as_defect (__main__.S3a) ... ok +test_save_refusal_makes_load_NA (__main__.S3a) ... ok +test_scenario_mutation_static_boundary (__main__.S3a) ... ok +test_signals_all_minutes_and_order (__main__.S3a) ... ok +test_E5_cached_digest_defect_is_comparable (__main__.S3b) ... ok +test_NA_not_PASS (__main__.S3b) ... ok +test_aliasing_cannot_be_PASS (__main__.S3b) ... ok +test_aliasing_missing_record (__main__.S3b) ... ok +test_all_paths_and_ownership_R_O (__main__.S3b) ... ok +test_digest_defect_other_checkpoint_still_rejected (__main__.S3b) ... ok +test_digest_materialization_required (__main__.S3b) ... ok +test_empty_registry_not_NA (__main__.S3b) ... ok +test_event_count_mismatch (__main__.S3b) ... ok +test_facts_normalization_is_reversible (__main__.S3b) ... ok +test_first_placeable_choice (__main__.S3b) ... ok +test_interval_gap (__main__.S3b) ... ok +test_joined_s3b_self_comparison (__main__.S3b) ... ok +test_load_X_not_digest_only (__main__.S3b) ... ok +test_load_extra_event (__main__.S3b) ... ok +test_missing_path_and_combination (__main__.S3b) ... ok +test_missing_preview_observation (__main__.S3b) ... ok +test_missing_trial (__main__.S3b) ... ok +test_nested_mutation_required (__main__.S3b) ... ok +test_no_staleness_assertion_for_non_tick (__main__.S3b) ... ok +test_ownership_fact_dictionary_order_fallback (__main__.S3b) ... ok +test_path_order (__main__.S3b) ... ok +test_restore_extra_event (__main__.S3b) ... ok +test_signal_facts_cannot_be_dropped (__main__.S3b) ... ok +test_sort_rule_rejected (__main__.S3b) ... ok +test_static_handler_and_outside_mutations (__main__.S3b) ... ok +test_unpreviewed_choice (__main__.S3b) ... ok +test_wrong_registry_in_either_role (__main__.S3b) ... ok +test_checkout_temp_destination_rejected (__main__.S4Bundle) ... ok +test_existing_output_never_overwritten (__main__.S4Bundle) ... ok +test_import_closure_rejections (__main__.S4Bundle) ... ok +test_missing_bundle_manifest_seal_and_changed_bytes (__main__.S4Bundle) ... ok +test_missing_private_evidence_and_extra_rejected (__main__.S4Bundle) ... test_missing_profile_not_export_success (__main__.S4Bundle) ... ok +test_phase_role_pid_audio_and_guard_rejected (__main__.S4Bundle) ... ERROR +test_seal_normal_and_changes_not_native_proof (__main__.S4Bundle) ... ok +test_synthetic_phase_all_real_checkers_not_native_proof (__main__.S4Bundle) ... ERROR +test_fixed_scenario_paths (__main__.SourcesAndMetrics) ... ok +test_metric_ranges (__main__.SourcesAndMetrics) ... ok +test_source_closure_synthetic_registered_map (__main__.SourcesAndMetrics) ... ok +test_source_pin_is_not_caller_controlled (__main__.SourcesAndMetrics) ... ok +test_array_order_and_all_differences (__main__.TypedTrees) ... ok +test_components_and_sha (__main__.TypedTrees) ... ok +test_deep_state_not_truncated (__main__.TypedTrees) ... ok +test_duplicate_textual_keys_rejected (__main__.TypedTrees) ... ok +test_exact_and_types (__main__.TypedTrees) ... ok +test_nested_order_all_paths (__main__.TypedTrees) ... ok +test_nonstring_keys_keep_types_and_values (__main__.TypedTrees) ... ok +test_unsupported_and_malformed (__main__.TypedTrees) ... ok + +====================================================================== +ERROR: test_missing_private_evidence_and_extra_rejected (__main__.S4Bundle) (filename='lifecycle.json') +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1365, in test_missing_private_evidence_and_extra_rejected + directory = Path(name); row = s4_phase_fixture(directory) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1285, in s4_phase_fixture + raw, e3, b1, e45 = s4_report_fixture(role) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1270, in s4_report_fixture + add_world(e3raw); add_world(e3); add_world(b1) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1269, in add_world + for child in value: add_world(child) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1267, in add_world + for child in value.values(): add_world(child) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1267, in add_world + for child in value.values(): add_world(child) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1267, in add_world + for child in value.values(): add_world(child) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1266, in add_world + value['tree_sha'] = eq.tree_sha(tree) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py", line 109, in tree_sha + validate_tree(tree) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py", line 70, in validate_tree + require(key not in seen, 'duplicate dictionary key') + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py", line 29, in require + raise EvidenceError(message) +compare_versions.EvidenceError: duplicate dictionary key + +====================================================================== +ERROR: test_missing_private_evidence_and_extra_rejected (__main__.S4Bundle) (filename='audio-close.json') +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1365, in test_missing_private_evidence_and_extra_rejected + directory = Path(name); row = s4_phase_fixture(directory) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1285, in s4_phase_fixture + raw, e3, b1, e45 = s4_report_fixture(role) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1270, in s4_report_fixture + add_world(e3raw); add_world(e3); add_world(b1) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1269, in add_world + for child in value: add_world(child) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1267, in add_world + for child in value.values(): add_world(child) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1267, in add_world + for child in value.values(): add_world(child) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1267, in add_world + for child in value.values(): add_world(child) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1266, in add_world + value['tree_sha'] = eq.tree_sha(tree) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py", line 109, in tree_sha + validate_tree(tree) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py", line 70, in validate_tree + require(key not in seen, 'duplicate dictionary key') + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py", line 29, in require + raise EvidenceError(message) +compare_versions.EvidenceError: duplicate dictionary key + +====================================================================== +ERROR: test_missing_private_evidence_and_extra_rejected (__main__.S4Bundle) (filename='e3-17.json') +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1365, in test_missing_private_evidence_and_extra_rejected + directory = Path(name); row = s4_phase_fixture(directory) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1285, in s4_phase_fixture + raw, e3, b1, e45 = s4_report_fixture(role) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1270, in s4_report_fixture + add_world(e3raw); add_world(e3); add_world(b1) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1269, in add_world + for child in value: add_world(child) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1267, in add_world + for child in value.values(): add_world(child) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1267, in add_world + for child in value.values(): add_world(child) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1267, in add_world + for child in value.values(): add_world(child) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1266, in add_world + value['tree_sha'] = eq.tree_sha(tree) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py", line 109, in tree_sha + validate_tree(tree) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py", line 70, in validate_tree + require(key not in seen, 'duplicate dictionary key') + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py", line 29, in require + raise EvidenceError(message) +compare_versions.EvidenceError: duplicate dictionary key + +====================================================================== +ERROR: test_missing_private_evidence_and_extra_rejected (__main__.S4Bundle) (filename='e45-20.json') +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1365, in test_missing_private_evidence_and_extra_rejected + directory = Path(name); row = s4_phase_fixture(directory) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1285, in s4_phase_fixture + raw, e3, b1, e45 = s4_report_fixture(role) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1270, in s4_report_fixture + add_world(e3raw); add_world(e3); add_world(b1) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1269, in add_world + for child in value: add_world(child) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1267, in add_world + for child in value.values(): add_world(child) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1267, in add_world + for child in value.values(): add_world(child) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1267, in add_world + for child in value.values(): add_world(child) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1266, in add_world + value['tree_sha'] = eq.tree_sha(tree) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py", line 109, in tree_sha + validate_tree(tree) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py", line 70, in validate_tree + require(key not in seen, 'duplicate dictionary key') + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py", line 29, in require + raise EvidenceError(message) +compare_versions.EvidenceError: duplicate dictionary key + +====================================================================== +ERROR: test_missing_private_evidence_and_extra_rejected (__main__.S4Bundle) (filename='extra.json') +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1365, in test_missing_private_evidence_and_extra_rejected + directory = Path(name); row = s4_phase_fixture(directory) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1285, in s4_phase_fixture + raw, e3, b1, e45 = s4_report_fixture(role) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1270, in s4_report_fixture + add_world(e3raw); add_world(e3); add_world(b1) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1269, in add_world + for child in value: add_world(child) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1267, in add_world + for child in value.values(): add_world(child) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1267, in add_world + for child in value.values(): add_world(child) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1267, in add_world + for child in value.values(): add_world(child) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1266, in add_world + value['tree_sha'] = eq.tree_sha(tree) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py", line 109, in tree_sha + validate_tree(tree) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py", line 70, in validate_tree + require(key not in seen, 'duplicate dictionary key') + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py", line 29, in require + raise EvidenceError(message) +compare_versions.EvidenceError: duplicate dictionary key + +====================================================================== +ERROR: test_phase_role_pid_audio_and_guard_rejected (__main__.S4Bundle) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1373, in test_phase_role_pid_audio_and_guard_rejected + directory = Path(name); row = s4_phase_fixture(directory) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1285, in s4_phase_fixture + raw, e3, b1, e45 = s4_report_fixture(role) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1270, in s4_report_fixture + add_world(e3raw); add_world(e3); add_world(b1) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1269, in add_world + for child in value: add_world(child) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1267, in add_world + for child in value.values(): add_world(child) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1267, in add_world + for child in value.values(): add_world(child) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1267, in add_world + for child in value.values(): add_world(child) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1266, in add_world + value['tree_sha'] = eq.tree_sha(tree) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py", line 109, in tree_sha + validate_tree(tree) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py", line 70, in validate_tree + require(key not in seen, 'duplicate dictionary key') + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py", line 29, in require + raise EvidenceError(message) +compare_versions.EvidenceError: duplicate dictionary key + +====================================================================== +ERROR: test_synthetic_phase_all_real_checkers_not_native_proof (__main__.S4Bundle) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1336, in test_synthetic_phase_all_real_checkers_not_native_proof + row = s4_phase_fixture(directory) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1285, in s4_phase_fixture + raw, e3, b1, e45 = s4_report_fixture(role) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1270, in s4_report_fixture + add_world(e3raw); add_world(e3); add_world(b1) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1269, in add_world + for child in value: add_world(child) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1267, in add_world + for child in value.values(): add_world(child) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1267, in add_world + for child in value.values(): add_world(child) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1267, in add_world + for child in value.values(): add_world(child) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1266, in add_world + value['tree_sha'] = eq.tree_sha(tree) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py", line 109, in tree_sha + validate_tree(tree) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py", line 70, in validate_tree + require(key not in seen, 'duplicate dictionary key') + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py", line 29, in require + raise EvidenceError(message) +compare_versions.EvidenceError: duplicate dictionary key + +---------------------------------------------------------------------- +Ran 128 tests in 34.518s + +FAILED (errors=7) diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_03.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_03.sha256 new file mode 100644 index 0000000..ccd78c0 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_03.sha256 @@ -0,0 +1 @@ +9f27f201325809a590375b7842101ef6b7d08c7de0aa4e66b4de2b7f7fd673d1 UNIT_OUTPUT_S4_ATTEMPT_03.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_03.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_03.txt new file mode 100644 index 0000000..42ebf1f --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_03.txt @@ -0,0 +1,14 @@ +test_checkout_temp_destination_rejected (__main__.S4Bundle) ... ok +test_existing_output_never_overwritten (__main__.S4Bundle) ... ok +test_import_closure_rejections (__main__.S4Bundle) ... ok +test_missing_bundle_manifest_seal_and_changed_bytes (__main__.S4Bundle) ... ok +test_missing_private_evidence_and_extra_rejected (__main__.S4Bundle) ... ok +test_missing_profile_not_export_success (__main__.S4Bundle) ... ok +test_phase_role_pid_audio_and_guard_rejected (__main__.S4Bundle) ... ok +test_seal_normal_and_changes_not_native_proof (__main__.S4Bundle) ... ok +test_synthetic_phase_all_real_checkers_not_native_proof (__main__.S4Bundle) ... ok + +---------------------------------------------------------------------- +Ran 9 tests in 19.447s + +OK diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_04.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_04.sha256 new file mode 100644 index 0000000..111afef --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_04.sha256 @@ -0,0 +1 @@ +76738bb4138955e5fec02a93358c55446183492e99fd4d4360ac7fad58caacf9 UNIT_OUTPUT_S4_ATTEMPT_04.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_04.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_04.txt new file mode 100644 index 0000000..02a3989 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_04.txt @@ -0,0 +1,21 @@ +test_copied_manifest_root_and_destination_count_rejected (__main__.S4NativeBundleLogic) ... ok +test_gate_none_success_not_boolean (__main__.S4NativeBundleLogic) ... ok +test_receipt_and_source_rejection_matrix (__main__.S4NativeBundleLogic) ... ok +test_synthetic_full_bundle_positive_not_native_evidence (__main__.S4NativeBundleLogic) ... ERROR + +====================================================================== +ERROR: test_synthetic_full_bundle_positive_not_native_evidence (__main__.S4NativeBundleLogic) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1506, in test_synthetic_full_bundle_positive_not_native_evidence + patch.object(driver, 'load_dependencies', return_value=(self.collector, self.standard, self.outer, self.diag)): + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/verify_eq.py", line 217, in verify + from run_eq import load_dependencies, actual_pins + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py", line 29, in require + raise EvidenceError(message) +compare_versions.EvidenceError: recomputed results differ + +---------------------------------------------------------------------- +Ran 4 tests in 124.325s + +FAILED (errors=1) diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_05.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_05.sha256 new file mode 100644 index 0000000..7706bd3 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_05.sha256 @@ -0,0 +1 @@ +aa13731a56337065e1a74acbfb640d56655cb4f774c9780dc265c40cf097101e UNIT_OUTPUT_S4_ATTEMPT_05.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_05.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_05.txt new file mode 100644 index 0000000..d8804e7 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_05.txt @@ -0,0 +1,137 @@ +test_all_operations (__main__.Diffs) ... ok +test_invalid_operations (__main__.Diffs) ... ok +test_reconstruction_and_proofs (__main__.Diffs) ... ok +test_attempt_to_normalize_violation_rejected (__main__.Normalization) ... ok +test_environment_values_differ_but_normal_form_equal (__main__.Normalization) ... ok +test_every_save_event_reversible (__main__.Normalization) ... ok +test_f3_keeps_relative_paths_and_words (__main__.Normalization) ... ok +test_guard_mismatch (__main__.Normalization) ... ok +test_nested_lookalike_is_not_eligible (__main__.Normalization) ... ok +test_original_transport_sha_detects_forged_timing (__main__.Normalization) ... ok +test_partial_timing_payload_rejected (__main__.Normalization) ... ok +test_prefix_boundary_and_reserved_token (__main__.Normalization) ... ok +test_sidecar_missing_duplicate_and_forged_paths (__main__.Normalization) ... ok +test_snapshot_and_latest_reversible (__main__.Normalization) ... ok +test_snapshot_event_outside_recent_is_not_eligible (__main__.Normalization) ... ok +test_wrong_event_and_source_are_preserved (__main__.Normalization) ... ok +test_wrong_timing_type_and_negative (__main__.Normalization) ... ok +test_all_events_beyond_recent_window (__main__.Reports) ... ok +test_all_semantic_layers_compared (__main__.Reports) ... ok +test_digest_alone_is_not_enough (__main__.Reports) ... ok +test_event_original_types_and_order (__main__.Reports) ... ok +test_event_start_and_ids (__main__.Reports) ... ok +test_exclusions_keep_actual_values (__main__.Reports) ... ok +test_handler_sets_and_counts (__main__.Reports) ... ok +test_observation_full_layers (__main__.Reports) ... ok +test_product_digest_self_consistency (__main__.Reports) ... ok +test_same_report (__main__.Reports) ... ok +test_scenario_existing_failures_preserved (__main__.Reports) ... ok +test_timing_digest_rule (__main__.Reports) ... ok +test_unknown_or_missing_fields_rejected (__main__.Reports) ... ok +test_violation_presence_and_difference (__main__.Reports) ... ok +test_O_cadence (__main__.S2Format) ... ok +test_counter_and_published_ids_binding (__main__.S2Format) ... ok +test_diff_and_same_as_S_transport (__main__.S2Format) ... ok +test_digest_and_scenario_contradiction (__main__.S2Format) ... ok +test_event_no_drop_duplicate_remap (__main__.S2Format) ... ok +test_event_original_field_types_mandatory (__main__.S2Format) ... ok +test_guard_actual_not_assumed (__main__.S2Format) ... ok +test_harness_digest_allows_only_dictionary_order (__main__.S2Format) ... ok +test_join_is_copy_and_retains_normalization_proof (__main__.S2Format) ... ok +test_kernel_cache_contradictions (__main__.S2Format) ... ok +test_lifecycle_guard_errors_and_boundaries (__main__.S2Format) ... ok +test_missing_full_state_not_digest_only (__main__.S2Format) ... ok +test_normalized_digest_and_raw_tree_are_both_bound (__main__.S2Format) ... ok +test_product_event_shape_and_typed_array (__main__.S2Format) ... ok +test_raw_observation_binding (__main__.S2Format) ... ok +test_roundtrip_tree_sha_and_raw_sha (__main__.S2Format) ... ok +test_s2_valid_and_not_formal_acceptance (__main__.S2Format) ... ok +test_state_witness_and_observation_mutation (__main__.S2Format) ... ok +test_stdout_exactly_one_line (__main__.S2Format) ... ok +test_autoload_class_and_script_import (__main__.S2Static) ... ok +test_comment_does_not_supply_proof (__main__.S2Static) ... ok +test_current_probe (__main__.S2Static) ... ok +test_full_state_and_godot_roundtrip_required (__main__.S2Static) ... ok +test_no_changes_outside_preparation_or_step (__main__.S2Static) ... ok +test_no_event_cap_or_duplicate_report (__main__.S2Static) ... ok +test_pause_and_step_arguments (__main__.S2Static) ... ok +test_textual_stringname_ordering (__main__.S2Static) ... ok +test_unlisted_live_method_and_late_preparation (__main__.S2Static) ... ok +test_variant_inference (__main__.S2Static) ... ok +test_X_recent_limit_and_counter (__main__.S3a) ... ok +test_duplicate_JSON_key_rejected (__main__.S3a) ... ok +test_e3_NA_cannot_be_PASS_or_applied (__main__.S3a) ... ok +test_e3_coverage_input_and_event_count_binding (__main__.S3a) ... ok +test_e3_invented_codes_and_missing_load_code (__main__.S3a) ... ok +test_e3_valid_R_and_O_records (__main__.S3a) ... ok +test_envelope_duplicates_not_defect (__main__.S3a) ... ok +test_event_count_defect_not_silently_accepted (__main__.S3a) ... ok +test_exact_phase_keys (__main__.S3a) ... ok +test_interval_gap_rejected (__main__.S3a) ... ok +test_invalid_input_accepted_is_not_PASS (__main__.S3a) ... ok +test_load_payload_and_pause_outcome (__main__.S3a) ... ok +test_operation_moved_outside_scenario_rejected (__main__.S3a) ... ok +test_package_fixed_mutations_and_hashes (__main__.S3a) ... ok +test_probe_connection_required (__main__.S3a) ... ok +test_rejection_mutation_retained_as_defect (__main__.S3a) ... ok +test_save_refusal_makes_load_NA (__main__.S3a) ... ok +test_scenario_mutation_static_boundary (__main__.S3a) ... ok +test_signals_all_minutes_and_order (__main__.S3a) ... ok +test_E5_cached_digest_defect_is_comparable (__main__.S3b) ... ok +test_NA_not_PASS (__main__.S3b) ... ok +test_aliasing_cannot_be_PASS (__main__.S3b) ... ok +test_aliasing_missing_record (__main__.S3b) ... ok +test_all_paths_and_ownership_R_O (__main__.S3b) ... ok +test_digest_defect_other_checkpoint_still_rejected (__main__.S3b) ... ok +test_digest_materialization_required (__main__.S3b) ... ok +test_empty_registry_not_NA (__main__.S3b) ... ok +test_event_count_mismatch (__main__.S3b) ... ok +test_facts_normalization_is_reversible (__main__.S3b) ... ok +test_first_placeable_choice (__main__.S3b) ... ok +test_interval_gap (__main__.S3b) ... ok +test_joined_s3b_self_comparison (__main__.S3b) ... ok +test_load_X_not_digest_only (__main__.S3b) ... ok +test_load_extra_event (__main__.S3b) ... ok +test_missing_path_and_combination (__main__.S3b) ... ok +test_missing_preview_observation (__main__.S3b) ... ok +test_missing_trial (__main__.S3b) ... ok +test_nested_mutation_required (__main__.S3b) ... ok +test_no_staleness_assertion_for_non_tick (__main__.S3b) ... ok +test_ownership_fact_dictionary_order_fallback (__main__.S3b) ... ok +test_path_order (__main__.S3b) ... ok +test_restore_extra_event (__main__.S3b) ... ok +test_signal_facts_cannot_be_dropped (__main__.S3b) ... ok +test_sort_rule_rejected (__main__.S3b) ... ok +test_static_handler_and_outside_mutations (__main__.S3b) ... ok +test_unpreviewed_choice (__main__.S3b) ... ok +test_wrong_registry_in_either_role (__main__.S3b) ... ok +test_checkout_temp_destination_rejected (__main__.S4Bundle) ... ok +test_existing_output_never_overwritten (__main__.S4Bundle) ... ok +test_import_closure_rejections (__main__.S4Bundle) ... ok +test_missing_bundle_manifest_seal_and_changed_bytes (__main__.S4Bundle) ... ok +test_missing_private_evidence_and_extra_rejected (__main__.S4Bundle) ... ok +test_missing_profile_not_export_success (__main__.S4Bundle) ... ok +test_phase_role_pid_audio_and_guard_rejected (__main__.S4Bundle) ... ok +test_seal_normal_and_changes_not_native_proof (__main__.S4Bundle) ... ok +test_synthetic_phase_all_real_checkers_not_native_proof (__main__.S4Bundle) ... ok +test_copied_manifest_root_and_destination_count_rejected (__main__.S4NativeBundleLogic) ... ok +test_gate_none_success_not_boolean (__main__.S4NativeBundleLogic) ... ok +test_receipt_and_source_rejection_matrix (__main__.S4NativeBundleLogic) ... ok +test_synthetic_full_bundle_positive_not_native_evidence (__main__.S4NativeBundleLogic) ... ok +test_fixed_scenario_paths (__main__.SourcesAndMetrics) ... ok +test_metric_ranges (__main__.SourcesAndMetrics) ... ok +test_source_closure_synthetic_registered_map (__main__.SourcesAndMetrics) ... ok +test_source_pin_is_not_caller_controlled (__main__.SourcesAndMetrics) ... ok +test_array_order_and_all_differences (__main__.TypedTrees) ... ok +test_components_and_sha (__main__.TypedTrees) ... ok +test_deep_state_not_truncated (__main__.TypedTrees) ... ok +test_duplicate_textual_keys_rejected (__main__.TypedTrees) ... ok +test_exact_and_types (__main__.TypedTrees) ... ok +test_nested_order_all_paths (__main__.TypedTrees) ... ok +test_nonstring_keys_keep_types_and_values (__main__.TypedTrees) ... ok +test_unsupported_and_malformed (__main__.TypedTrees) ... ok + +---------------------------------------------------------------------- +Ran 132 tests in 194.460s + +OK diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_06.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_06.sha256 new file mode 100644 index 0000000..f1a198d --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_06.sha256 @@ -0,0 +1 @@ +3c41e4442e2c21315e484fd2c8cdb9de70272af115a618083fca2d2e6428d187 UNIT_OUTPUT_S4_ATTEMPT_06.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_06.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_06.txt new file mode 100644 index 0000000..89a3657 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_06.txt @@ -0,0 +1,139 @@ +test_all_operations (__main__.Diffs) ... ok +test_invalid_operations (__main__.Diffs) ... ok +test_reconstruction_and_proofs (__main__.Diffs) ... ok +test_attempt_to_normalize_violation_rejected (__main__.Normalization) ... ok +test_environment_values_differ_but_normal_form_equal (__main__.Normalization) ... ok +test_every_save_event_reversible (__main__.Normalization) ... ok +test_f3_keeps_relative_paths_and_words (__main__.Normalization) ... ok +test_guard_mismatch (__main__.Normalization) ... ok +test_nested_lookalike_is_not_eligible (__main__.Normalization) ... ok +test_original_transport_sha_detects_forged_timing (__main__.Normalization) ... ok +test_partial_timing_payload_rejected (__main__.Normalization) ... ok +test_prefix_boundary_and_reserved_token (__main__.Normalization) ... ok +test_sidecar_missing_duplicate_and_forged_paths (__main__.Normalization) ... ok +test_snapshot_and_latest_reversible (__main__.Normalization) ... ok +test_snapshot_event_outside_recent_is_not_eligible (__main__.Normalization) ... ok +test_wrong_event_and_source_are_preserved (__main__.Normalization) ... ok +test_wrong_timing_type_and_negative (__main__.Normalization) ... ok +test_all_events_beyond_recent_window (__main__.Reports) ... ok +test_all_semantic_layers_compared (__main__.Reports) ... ok +test_digest_alone_is_not_enough (__main__.Reports) ... ok +test_event_original_types_and_order (__main__.Reports) ... ok +test_event_start_and_ids (__main__.Reports) ... ok +test_exclusions_keep_actual_values (__main__.Reports) ... ok +test_handler_sets_and_counts (__main__.Reports) ... ok +test_observation_full_layers (__main__.Reports) ... ok +test_product_digest_self_consistency (__main__.Reports) ... ok +test_same_report (__main__.Reports) ... ok +test_scenario_existing_failures_preserved (__main__.Reports) ... ok +test_timing_digest_rule (__main__.Reports) ... ok +test_unknown_or_missing_fields_rejected (__main__.Reports) ... ok +test_violation_presence_and_difference (__main__.Reports) ... ok +test_O_cadence (__main__.S2Format) ... ok +test_counter_and_published_ids_binding (__main__.S2Format) ... ok +test_diff_and_same_as_S_transport (__main__.S2Format) ... ok +test_digest_and_scenario_contradiction (__main__.S2Format) ... ok +test_event_no_drop_duplicate_remap (__main__.S2Format) ... ok +test_event_original_field_types_mandatory (__main__.S2Format) ... ok +test_guard_actual_not_assumed (__main__.S2Format) ... ok +test_harness_digest_allows_only_dictionary_order (__main__.S2Format) ... ok +test_join_is_copy_and_retains_normalization_proof (__main__.S2Format) ... ok +test_kernel_cache_contradictions (__main__.S2Format) ... ok +test_lifecycle_guard_errors_and_boundaries (__main__.S2Format) ... ok +test_missing_full_state_not_digest_only (__main__.S2Format) ... ok +test_normalized_digest_and_raw_tree_are_both_bound (__main__.S2Format) ... ok +test_product_event_shape_and_typed_array (__main__.S2Format) ... ok +test_raw_observation_binding (__main__.S2Format) ... ok +test_roundtrip_tree_sha_and_raw_sha (__main__.S2Format) ... ok +test_s2_valid_and_not_formal_acceptance (__main__.S2Format) ... ok +test_state_witness_and_observation_mutation (__main__.S2Format) ... ok +test_stdout_exactly_one_line (__main__.S2Format) ... ok +test_autoload_class_and_script_import (__main__.S2Static) ... ok +test_comment_does_not_supply_proof (__main__.S2Static) ... ok +test_current_probe (__main__.S2Static) ... ok +test_full_state_and_godot_roundtrip_required (__main__.S2Static) ... ok +test_no_changes_outside_preparation_or_step (__main__.S2Static) ... ok +test_no_event_cap_or_duplicate_report (__main__.S2Static) ... ok +test_pause_and_step_arguments (__main__.S2Static) ... ok +test_textual_stringname_ordering (__main__.S2Static) ... ok +test_unlisted_live_method_and_late_preparation (__main__.S2Static) ... ok +test_variant_inference (__main__.S2Static) ... ok +test_X_recent_limit_and_counter (__main__.S3a) ... ok +test_duplicate_JSON_key_rejected (__main__.S3a) ... ok +test_e3_NA_cannot_be_PASS_or_applied (__main__.S3a) ... ok +test_e3_coverage_input_and_event_count_binding (__main__.S3a) ... ok +test_e3_invented_codes_and_missing_load_code (__main__.S3a) ... ok +test_e3_valid_R_and_O_records (__main__.S3a) ... ok +test_envelope_duplicates_not_defect (__main__.S3a) ... ok +test_event_count_defect_not_silently_accepted (__main__.S3a) ... ok +test_exact_phase_keys (__main__.S3a) ... ok +test_interval_gap_rejected (__main__.S3a) ... ok +test_invalid_input_accepted_is_not_PASS (__main__.S3a) ... ok +test_load_payload_and_pause_outcome (__main__.S3a) ... ok +test_operation_moved_outside_scenario_rejected (__main__.S3a) ... ok +test_package_fixed_mutations_and_hashes (__main__.S3a) ... ok +test_probe_connection_required (__main__.S3a) ... ok +test_rejection_mutation_retained_as_defect (__main__.S3a) ... ok +test_save_refusal_makes_load_NA (__main__.S3a) ... ok +test_scenario_mutation_static_boundary (__main__.S3a) ... ok +test_signals_all_minutes_and_order (__main__.S3a) ... ok +test_E5_cached_digest_defect_is_comparable (__main__.S3b) ... ok +test_NA_not_PASS (__main__.S3b) ... ok +test_aliasing_cannot_be_PASS (__main__.S3b) ... ok +test_aliasing_missing_record (__main__.S3b) ... ok +test_all_paths_and_ownership_R_O (__main__.S3b) ... ok +test_digest_defect_other_checkpoint_still_rejected (__main__.S3b) ... ok +test_digest_materialization_required (__main__.S3b) ... ok +test_empty_registry_not_NA (__main__.S3b) ... ok +test_event_count_mismatch (__main__.S3b) ... ok +test_facts_normalization_is_reversible (__main__.S3b) ... ok +test_first_placeable_choice (__main__.S3b) ... ok +test_interval_gap (__main__.S3b) ... ok +test_joined_s3b_self_comparison (__main__.S3b) ... ok +test_load_X_not_digest_only (__main__.S3b) ... ok +test_load_extra_event (__main__.S3b) ... ok +test_missing_path_and_combination (__main__.S3b) ... ok +test_missing_preview_observation (__main__.S3b) ... ok +test_missing_trial (__main__.S3b) ... ok +test_nested_mutation_required (__main__.S3b) ... ok +test_no_staleness_assertion_for_non_tick (__main__.S3b) ... ok +test_ownership_fact_dictionary_order_fallback (__main__.S3b) ... ok +test_path_order (__main__.S3b) ... ok +test_restore_extra_event (__main__.S3b) ... ok +test_signal_facts_cannot_be_dropped (__main__.S3b) ... ok +test_sort_rule_rejected (__main__.S3b) ... ok +test_static_handler_and_outside_mutations (__main__.S3b) ... ok +test_unpreviewed_choice (__main__.S3b) ... ok +test_wrong_registry_in_either_role (__main__.S3b) ... ok +test_checkout_temp_destination_rejected (__main__.S4Bundle) ... ok +test_existing_output_never_overwritten (__main__.S4Bundle) ... ok +test_import_closure_rejections (__main__.S4Bundle) ... ok +test_missing_bundle_manifest_seal_and_changed_bytes (__main__.S4Bundle) ... ok +test_missing_private_evidence_and_extra_rejected (__main__.S4Bundle) ... ok +test_missing_profile_not_export_success (__main__.S4Bundle) ... ok +test_phase_role_pid_audio_and_guard_rejected (__main__.S4Bundle) ... ok +test_rebound_lifecycle_and_scenario_contradictions (__main__.S4Bundle) ... ok +test_seal_normal_and_changes_not_native_proof (__main__.S4Bundle) ... ok +test_synthetic_phase_all_real_checkers_not_native_proof (__main__.S4Bundle) ... ok +test_copied_manifest_root_and_destination_count_rejected (__main__.S4NativeBundleLogic) ... ok +test_failure_keeps_raw_and_no_bundle_without_starting_engine (__main__.S4NativeBundleLogic) ... ok +test_gate_none_success_not_boolean (__main__.S4NativeBundleLogic) ... ok +test_receipt_and_source_rejection_matrix (__main__.S4NativeBundleLogic) ... ok +test_synthetic_full_bundle_positive_not_native_evidence (__main__.S4NativeBundleLogic) ... ok +test_fixed_scenario_paths (__main__.SourcesAndMetrics) ... ok +test_metric_ranges (__main__.SourcesAndMetrics) ... ok +test_source_closure_synthetic_registered_map (__main__.SourcesAndMetrics) ... ok +test_source_pin_is_not_caller_controlled (__main__.SourcesAndMetrics) ... ok +test_array_order_and_all_differences (__main__.TypedTrees) ... ok +test_components_and_sha (__main__.TypedTrees) ... ok +test_deep_state_not_truncated (__main__.TypedTrees) ... ok +test_duplicate_textual_keys_rejected (__main__.TypedTrees) ... ok +test_exact_and_types (__main__.TypedTrees) ... ok +test_nested_order_all_paths (__main__.TypedTrees) ... ok +test_nonstring_keys_keep_types_and_values (__main__.TypedTrees) ... ok +test_unsupported_and_malformed (__main__.TypedTrees) ... ok + +---------------------------------------------------------------------- +Ran 134 tests in 206.531s + +OK diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_07.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_07.sha256 new file mode 100644 index 0000000..b406f89 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_07.sha256 @@ -0,0 +1 @@ +29d1a5dec792ae865725220ec4d11c11bb62d08cba9a614ad7bf2d120948ab97 UNIT_OUTPUT_S4_ATTEMPT_07.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_07.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_07.txt new file mode 100644 index 0000000..de96a5e --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_07.txt @@ -0,0 +1,28 @@ +test_check_accepts_true (__main__.S4ProbeAdmission) ... ok +test_check_rejects_false_all_errors (__main__.S4ProbeAdmission) ... ok +test_run_admission_accepts_true_mock_launch_only (__main__.S4ProbeAdmission) ... ok +test_run_admission_rejects_false_without_engine (__main__.S4ProbeAdmission) ... ok +test_nonzero_determinism_rejected_after_real_join (__main__.S4RemainingBindings) ... FAIL +test_owned_lifecycle_exit_diagnostic_and_profile_rejections (__main__.S4RemainingBindings) ... ok +test_verifier_accepts_true_recomputes_raw (__main__.S4RemainingBindings) ... ok +test_verifier_rejects_false_with_every_error (__main__.S4RemainingBindings) ... ok + +====================================================================== +FAIL: test_nonzero_determinism_rejected_after_real_join (__main__.S4RemainingBindings) +---------------------------------------------------------------------- +compare_versions.EvidenceError: report checker: ['report self-check: []'] + +During handling of the above exception, another exception occurred: + +Traceback (most recent call last): + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1647, in test_nonzero_determinism_rejected_after_real_join + self.recompute(self.execution) +AssertionError: "same-role determinism failed" does not match "report checker: ['report self-check: []']" + +---------------------------------------------------------------------- +Ran 8 tests in 54.265s + +FAILED (failures=1) + +exit_code=1 +wall_seconds=54.554559917 diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_08.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_08.sha256 new file mode 100644 index 0000000..dc00023 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_08.sha256 @@ -0,0 +1 @@ +d470e6ee7a07a3b6d4ad2182b545e8708ae735b0d106c0800a813eb73f7353ce UNIT_OUTPUT_S4_ATTEMPT_08.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_08.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_08.txt new file mode 100644 index 0000000..4ff1fa5 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_08.txt @@ -0,0 +1,17 @@ +test_check_accepts_true (__main__.S4ProbeAdmission) ... ok +test_check_rejects_false_all_errors (__main__.S4ProbeAdmission) ... ok +test_run_admission_accepts_true_mock_launch_only (__main__.S4ProbeAdmission) ... ok +test_run_admission_rejects_false_without_engine (__main__.S4ProbeAdmission) ... ok +test_nine_original_destinations_required (__main__.S4RemainingBindings) ... ok +test_nonzero_determinism_rejected_after_real_join (__main__.S4RemainingBindings) ... ok +test_owned_lifecycle_exit_diagnostic_and_profile_rejections (__main__.S4RemainingBindings) ... ok +test_verifier_accepts_true_recomputes_raw (__main__.S4RemainingBindings) ... ok +test_verifier_rejects_false_with_every_error (__main__.S4RemainingBindings) ... ok + +---------------------------------------------------------------------- +Ran 9 tests in 86.276s + +OK + +exit_code=0 +wall_seconds=86.551909958 diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_09.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_09.sha256 new file mode 100644 index 0000000..9da19e3 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_09.sha256 @@ -0,0 +1 @@ +3f33b134a48cfabd8794329bec69ed0678ad71f06052f4e34a78c5955475c450 UNIT_OUTPUT_S4_ATTEMPT_09.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_09.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_09.txt new file mode 100644 index 0000000..8b99a67 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_09.txt @@ -0,0 +1,11 @@ +test_cached_verdict_not_trusted (__main__.S4StoredResultBindings) ... ok +test_missing_sidecar_rejected_after_seal (__main__.S4StoredResultBindings) ... ok +test_raw_joined_substitution_rejected_after_seal (__main__.S4StoredResultBindings) ... ok + +---------------------------------------------------------------------- +Ran 3 tests in 0.025s + +OK + +exit_code=0 +wall_seconds=0.2951165 diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_10.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_10.sha256 new file mode 100644 index 0000000..222645f --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_10.sha256 @@ -0,0 +1 @@ +ff6fc0065772434f9ca35a1267e24d199057e339869a868942a41829327503bb UNIT_OUTPUT_S4_ATTEMPT_10.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_10.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_10.txt new file mode 100644 index 0000000..ee7919a --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S4_ATTEMPT_10.txt @@ -0,0 +1,154 @@ +test_all_operations (__main__.Diffs) ... ok +test_invalid_operations (__main__.Diffs) ... ok +test_reconstruction_and_proofs (__main__.Diffs) ... ok +test_attempt_to_normalize_violation_rejected (__main__.Normalization) ... ok +test_environment_values_differ_but_normal_form_equal (__main__.Normalization) ... ok +test_every_save_event_reversible (__main__.Normalization) ... ok +test_f3_keeps_relative_paths_and_words (__main__.Normalization) ... ok +test_guard_mismatch (__main__.Normalization) ... ok +test_nested_lookalike_is_not_eligible (__main__.Normalization) ... ok +test_original_transport_sha_detects_forged_timing (__main__.Normalization) ... ok +test_partial_timing_payload_rejected (__main__.Normalization) ... ok +test_prefix_boundary_and_reserved_token (__main__.Normalization) ... ok +test_sidecar_missing_duplicate_and_forged_paths (__main__.Normalization) ... ok +test_snapshot_and_latest_reversible (__main__.Normalization) ... ok +test_snapshot_event_outside_recent_is_not_eligible (__main__.Normalization) ... ok +test_wrong_event_and_source_are_preserved (__main__.Normalization) ... ok +test_wrong_timing_type_and_negative (__main__.Normalization) ... ok +test_all_events_beyond_recent_window (__main__.Reports) ... ok +test_all_semantic_layers_compared (__main__.Reports) ... ok +test_digest_alone_is_not_enough (__main__.Reports) ... ok +test_event_original_types_and_order (__main__.Reports) ... ok +test_event_start_and_ids (__main__.Reports) ... ok +test_exclusions_keep_actual_values (__main__.Reports) ... ok +test_handler_sets_and_counts (__main__.Reports) ... ok +test_observation_full_layers (__main__.Reports) ... ok +test_product_digest_self_consistency (__main__.Reports) ... ok +test_same_report (__main__.Reports) ... ok +test_scenario_existing_failures_preserved (__main__.Reports) ... ok +test_timing_digest_rule (__main__.Reports) ... ok +test_unknown_or_missing_fields_rejected (__main__.Reports) ... ok +test_violation_presence_and_difference (__main__.Reports) ... ok +test_O_cadence (__main__.S2Format) ... ok +test_counter_and_published_ids_binding (__main__.S2Format) ... ok +test_diff_and_same_as_S_transport (__main__.S2Format) ... ok +test_digest_and_scenario_contradiction (__main__.S2Format) ... ok +test_event_no_drop_duplicate_remap (__main__.S2Format) ... ok +test_event_original_field_types_mandatory (__main__.S2Format) ... ok +test_guard_actual_not_assumed (__main__.S2Format) ... ok +test_harness_digest_allows_only_dictionary_order (__main__.S2Format) ... ok +test_join_is_copy_and_retains_normalization_proof (__main__.S2Format) ... ok +test_kernel_cache_contradictions (__main__.S2Format) ... ok +test_lifecycle_guard_errors_and_boundaries (__main__.S2Format) ... ok +test_missing_full_state_not_digest_only (__main__.S2Format) ... ok +test_normalized_digest_and_raw_tree_are_both_bound (__main__.S2Format) ... ok +test_product_event_shape_and_typed_array (__main__.S2Format) ... ok +test_raw_observation_binding (__main__.S2Format) ... ok +test_roundtrip_tree_sha_and_raw_sha (__main__.S2Format) ... ok +test_s2_valid_and_not_formal_acceptance (__main__.S2Format) ... ok +test_state_witness_and_observation_mutation (__main__.S2Format) ... ok +test_stdout_exactly_one_line (__main__.S2Format) ... ok +test_autoload_class_and_script_import (__main__.S2Static) ... ok +test_comment_does_not_supply_proof (__main__.S2Static) ... ok +test_current_probe (__main__.S2Static) ... ok +test_full_state_and_godot_roundtrip_required (__main__.S2Static) ... ok +test_no_changes_outside_preparation_or_step (__main__.S2Static) ... ok +test_no_event_cap_or_duplicate_report (__main__.S2Static) ... ok +test_pause_and_step_arguments (__main__.S2Static) ... ok +test_textual_stringname_ordering (__main__.S2Static) ... ok +test_unlisted_live_method_and_late_preparation (__main__.S2Static) ... ok +test_variant_inference (__main__.S2Static) ... ok +test_X_recent_limit_and_counter (__main__.S3a) ... ok +test_duplicate_JSON_key_rejected (__main__.S3a) ... ok +test_e3_NA_cannot_be_PASS_or_applied (__main__.S3a) ... ok +test_e3_coverage_input_and_event_count_binding (__main__.S3a) ... ok +test_e3_invented_codes_and_missing_load_code (__main__.S3a) ... ok +test_e3_valid_R_and_O_records (__main__.S3a) ... ok +test_envelope_duplicates_not_defect (__main__.S3a) ... ok +test_event_count_defect_not_silently_accepted (__main__.S3a) ... ok +test_exact_phase_keys (__main__.S3a) ... ok +test_interval_gap_rejected (__main__.S3a) ... ok +test_invalid_input_accepted_is_not_PASS (__main__.S3a) ... ok +test_load_payload_and_pause_outcome (__main__.S3a) ... ok +test_operation_moved_outside_scenario_rejected (__main__.S3a) ... ok +test_package_fixed_mutations_and_hashes (__main__.S3a) ... ok +test_probe_connection_required (__main__.S3a) ... ok +test_rejection_mutation_retained_as_defect (__main__.S3a) ... ok +test_save_refusal_makes_load_NA (__main__.S3a) ... ok +test_scenario_mutation_static_boundary (__main__.S3a) ... ok +test_signals_all_minutes_and_order (__main__.S3a) ... ok +test_E5_cached_digest_defect_is_comparable (__main__.S3b) ... ok +test_NA_not_PASS (__main__.S3b) ... ok +test_aliasing_cannot_be_PASS (__main__.S3b) ... ok +test_aliasing_missing_record (__main__.S3b) ... ok +test_all_paths_and_ownership_R_O (__main__.S3b) ... ok +test_digest_defect_other_checkpoint_still_rejected (__main__.S3b) ... ok +test_digest_materialization_required (__main__.S3b) ... ok +test_empty_registry_not_NA (__main__.S3b) ... ok +test_event_count_mismatch (__main__.S3b) ... ok +test_facts_normalization_is_reversible (__main__.S3b) ... ok +test_first_placeable_choice (__main__.S3b) ... ok +test_interval_gap (__main__.S3b) ... ok +test_joined_s3b_self_comparison (__main__.S3b) ... ok +test_load_X_not_digest_only (__main__.S3b) ... ok +test_load_extra_event (__main__.S3b) ... ok +test_missing_path_and_combination (__main__.S3b) ... ok +test_missing_preview_observation (__main__.S3b) ... ok +test_missing_trial (__main__.S3b) ... ok +test_nested_mutation_required (__main__.S3b) ... ok +test_no_staleness_assertion_for_non_tick (__main__.S3b) ... ok +test_ownership_fact_dictionary_order_fallback (__main__.S3b) ... ok +test_path_order (__main__.S3b) ... ok +test_restore_extra_event (__main__.S3b) ... ok +test_signal_facts_cannot_be_dropped (__main__.S3b) ... ok +test_sort_rule_rejected (__main__.S3b) ... ok +test_static_handler_and_outside_mutations (__main__.S3b) ... ok +test_unpreviewed_choice (__main__.S3b) ... ok +test_wrong_registry_in_either_role (__main__.S3b) ... ok +test_checkout_temp_destination_rejected (__main__.S4Bundle) ... ok +test_existing_output_never_overwritten (__main__.S4Bundle) ... ok +test_import_closure_rejections (__main__.S4Bundle) ... ok +test_missing_bundle_manifest_seal_and_changed_bytes (__main__.S4Bundle) ... ok +test_missing_private_evidence_and_extra_rejected (__main__.S4Bundle) ... ok +test_missing_profile_not_export_success (__main__.S4Bundle) ... ok +test_phase_role_pid_audio_and_guard_rejected (__main__.S4Bundle) ... ok +test_rebound_lifecycle_and_scenario_contradictions (__main__.S4Bundle) ... ok +test_seal_normal_and_changes_not_native_proof (__main__.S4Bundle) ... ok +test_synthetic_phase_all_real_checkers_not_native_proof (__main__.S4Bundle) ... ok +test_copied_manifest_root_and_destination_count_rejected (__main__.S4NativeBundleLogic) ... ok +test_failure_keeps_raw_and_no_bundle_without_starting_engine (__main__.S4NativeBundleLogic) ... ok +test_gate_none_success_not_boolean (__main__.S4NativeBundleLogic) ... ok +test_receipt_and_source_rejection_matrix (__main__.S4NativeBundleLogic) ... ok +test_synthetic_full_bundle_positive_not_native_evidence (__main__.S4NativeBundleLogic) ... ok +test_check_accepts_true (__main__.S4ProbeAdmission) ... ok +test_check_rejects_false_all_errors (__main__.S4ProbeAdmission) ... ok +test_run_admission_accepts_true_mock_launch_only (__main__.S4ProbeAdmission) ... ok +test_run_admission_rejects_false_without_engine (__main__.S4ProbeAdmission) ... ok +test_nine_original_destinations_required (__main__.S4RemainingBindings) ... ok +test_nonzero_determinism_rejected_after_real_join (__main__.S4RemainingBindings) ... ok +test_owned_lifecycle_exit_diagnostic_and_profile_rejections (__main__.S4RemainingBindings) ... ok +test_verifier_accepts_true_recomputes_raw (__main__.S4RemainingBindings) ... ok +test_verifier_rejects_false_with_every_error (__main__.S4RemainingBindings) ... ok +test_cached_verdict_not_trusted (__main__.S4StoredResultBindings) ... ok +test_missing_sidecar_rejected_after_seal (__main__.S4StoredResultBindings) ... ok +test_raw_joined_substitution_rejected_after_seal (__main__.S4StoredResultBindings) ... ok +test_fixed_scenario_paths (__main__.SourcesAndMetrics) ... ok +test_metric_ranges (__main__.SourcesAndMetrics) ... ok +test_source_closure_synthetic_registered_map (__main__.SourcesAndMetrics) ... ok +test_source_pin_is_not_caller_controlled (__main__.SourcesAndMetrics) ... ok +test_array_order_and_all_differences (__main__.TypedTrees) ... ok +test_components_and_sha (__main__.TypedTrees) ... ok +test_deep_state_not_truncated (__main__.TypedTrees) ... ok +test_duplicate_textual_keys_rejected (__main__.TypedTrees) ... ok +test_exact_and_types (__main__.TypedTrees) ... ok +test_nested_order_all_paths (__main__.TypedTrees) ... ok +test_nonstring_keys_keep_types_and_values (__main__.TypedTrees) ... ok +test_unsupported_and_malformed (__main__.TypedTrees) ... ok + +---------------------------------------------------------------------- +Ran 146 tests in 293.277s + +OK + +exit_code=0 +wall_seconds=293.5742515 diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/check_eq.py b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/check_eq.py new file mode 100644 index 0000000..cbf535d --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/check_eq.py @@ -0,0 +1,873 @@ +"""S3a format/static and E3 evidence checks. Not native admission or acceptance. + +Raw records remain immutable. join_report derives normalized digests/sidecars on +copies using S1's sole F1-F3 implementation; it does not manufacture Godot proof. +""" +import base64 +import ast +import copy +import hashlib +import json +from pathlib import Path +import re +import sys + +sys.dont_write_bytecode = True +import compare_versions as eq + + +def check_python_imports(text): + """Closed EQ/stdlib import screen; dynamic file loading is separately pinned by run_eq.""" + allowed = {'argparse', 'ast', 'base64', 'copy', 'hashlib', 'importlib', 'json', 'math', + 'os', 'pathlib', 're', 'shutil', 'struct', 'subprocess', 'sys', 'tempfile', + 'unittest', 'uuid', 'check_eq', 'compare_versions', 'run_eq', 'verify_eq'} + tree = ast.parse(text) + for node in ast.walk(tree): + if isinstance(node, (ast.Import, ast.ImportFrom)): + names = [node.module] if isinstance(node, ast.ImportFrom) else [a.name for a in node.names] + eq.require(all(n and n.split('.')[0] in allowed for n in names), 'import outside EQ closure') + eq.require(not isinstance(node, ast.ImportFrom) or node.level == 0, 'relative import outside closure') + if isinstance(node, ast.Call): + name = getattr(node.func, 'id', getattr(node.func, 'attr', '')) + eq.require(name not in ('eval', 'exec', '__import__', 'import_module'), 'unapproved dynamic import/code') + if name == 'spec_from_file_location': + expected = ast.parse('importlib.util.spec_from_file_location(module_name, root / relative)').body[0].value + eq.require(ast.dump(node) == ast.dump(expected) and + "require(relative in DEPENDENCIES and relative.endswith('.py'), 'import outside closure')" in text, + 'unapproved dynamic file loader') + for value in ast.walk(node): + if isinstance(value, ast.Constant) and isinstance(value.value, str): + eq.require(not value.value.endswith('.py'), 'unapproved literal file loader') + return True + + +def sha(value): + return hashlib.sha256(value).hexdigest() + + +def hex_sha(value): + return type(value) is str and re.fullmatch('[0-9a-f]{64}', value) is not None + + +def integer(value): + return type(value) is int and value >= 0 + + +def fields(tree): + eq.require(tree[0] == 27, 'dictionary required') + result = {} + for key, value in tree[1]: + eq.require(key[0] in (4, 21) and key[1] not in result, 'text key collision/type') + result[key[1]] = value + return result + + +def counts(tree): + runtime = fields(fields(fields(tree)['systems'])['runtime']) + counters = fields(fields(runtime['id_generator'])['counters']) + # Product get_counter has an explicit zero default for an absent prefix. + # At B1 the prefix must exist, so absent evidence is never defaulted here. + counter = counters['domain_event'] + ids = fields(runtime['domain_events'])['published_ids'] + eq.require(counter[0] == 2 and integer(counter[1]), 'domain counter type') + eq.require(ids[0] == 28, 'published IDs array') + eq.require(all(n[0] == 4 for n in ids[1]), 'published ID types') + names = [n[1] for n in ids[1]] + eq.require(names == sorted(set(names)), 'published ID order/duplicates') + return {'counter': counter[1], 'published_ids_count': len(names)}, names + + +def normalized_digest(tree): + """Harness-only typed canonical digest; never claim this is a product digest. + + Key nodes remain exact. Only Dictionary enumeration order is canonicalized, + matching S1 fallback; floats, metadata and Array order remain untouched. + """ + def canonical(node): + result = copy.deepcopy(node) + if node[0] == 27: + names = [eq._key_text(k) for k, _ in node[1]] + eq.require(len(set(names)) == len(names), 'digest textual key collision') + result[1] = [[copy.deepcopy(k), canonical(v)] for k, v in sorted(node[1], key=lambda p: eq._key_text(p[0]))] + elif node[0] == 28 or 5 <= node[0] <= 20 or 30 <= node[0] <= 38: + result[1] = [canonical(v) for v in node[1]] + return result + eq.validate_tree(tree) + return eq.tree_sha(canonical(tree)) + + +def join_report(raw): + """Return (joined report, reversible normalization evidence), never edit raw.""" + joined = copy.deepcopy(raw) + proofs = [] + trees = eq.reconstruct_checkpoints(raw['checkpoints']) + for cp, (s, latest) in zip(joined['checkpoints'], trees): + row = {} + for name, tree in (('S', s), ('latest', latest)): + normalized, side = eq.normalize_tree(tree, raw['profile_root']) + restored = eq.restore_tree(normalized, side, raw['profile_root']) + eq.require(eq.tree_sha(restored) == eq.tree_sha(tree), 'normalization restore SHA') + row[name] = {'normalized_tree_sha': eq.tree_sha(normalized), 'normalized_digest': normalized_digest(normalized), 'sidecar': side, + 'restored_tree_sha': eq.tree_sha(restored)} + expected = row['latest']['normalized_digest'] + eq.require(cp['harness_normalized_digest'] in (None, expected), 'forged normalized digest') + cp['harness_normalized_digest'] = expected + proofs.append(row) + for i, scenario in enumerate(raw.get('scenarios', [])): + derived, scenario_proofs = join_report({'profile_root': raw['profile_root'], 'checkpoints': scenario['checkpoints']}) + joined['scenarios'][i]['checkpoints'] = derived['checkpoints'] + proofs.append({'scenario': scenario['id'], 'checkpoints': scenario_proofs}) + if scenario['id'].startswith(('E4/', 'E5/')): + joined['scenarios'][i]['result']['facts'], fact_proofs = join_facts(scenario['result']['facts'], raw['profile_root']) + proofs.append({'scenario': scenario['id'], 'facts': fact_proofs}) + return joined, proofs + + +def check_measurement(raw, measurement): + eq.require(type(measurement) is dict, 'measurement connection inventory missing') + eq.require(set(measurement) == {'probe_object', 'connections', 'start_minute'}, 'measurement inventory fields') + eq.require(measurement['start_minute'] == raw['checkpoints'][0]['minute'], 'inventory B1 minute') + probe = measurement['probe_object'] + eq.require(type(probe) is str and re.fullmatch('[1-9][0-9]*', probe), 'probe object identity') + for signal, method in (('snapshot_published', 'observe_snapshot'), ('state_updated', 'observe_state')): + rows = measurement['connections'][signal] + eq.require(type(rows) is list, 'connection list') + for row in rows: + eq.require(set(row) == {'object', 'method', 'flags'}, 'connection fields') + eq.require(sum(r['object'] == probe and r['method'] == method for r in rows) == 1, + 'missing/duplicate probe connection: ' + signal) + expected = [{'signal': signal, 'minute': cp['minute']} for cp in raw['checkpoints'][1:] + for signal in ('snapshot_published', 'state_updated')] + eq.require(eq.exact(raw['signal_order'], expected), 'exact measured signal pairs/checkpoint minutes required') + + +def check_report(raw, measurement=None, e3_evidence=None, b1_record=None, e45_evidence=None): + out = {'ok': False, 'stage': 'S2', 'formal_acceptance': False, 'errors': []} + try: + report, proofs = join_report(raw) + compared = eq.compare_reports(report, report) + eq.require(compared['ok'], 'report self-check: ' + repr(compared['errors'])) + if raw['scenarios'] or e3_evidence is not None: + eq.require(e3_evidence is not None and b1_record is not None, 'E3 raw evidence missing') + e3_raw = dict(raw, scenarios=raw['scenarios'][:18]) if e45_evidence is not None else raw + out['e3'] = check_e3(e3_raw, e3_evidence, b1_record) + out['stage'] = 'S3a' + if e45_evidence is not None: + out['e45'] = check_e45(raw, e45_evidence, e3_evidence[-1]['end']) + out['stage'] = 'S3b' + cps = raw['checkpoints'] + start_minute = 632 if raw['role'] == 'R' else 390 + eq.require(cps[0]['minute'] == start_minute, 'B1 minute') + for cp in cps: + eq.require(type(cp['minute']) is int, 'minute type') + k, c = cp['K'], cp['C'] + for key in ('absolute_minute', 'speed', 'snapshot_version', '_pause_request_serial'): + eq.require(integer(k[key]), 'K integer: ' + key) + for key in ('paused', '_skip_next_process', '_abort_current_tick_requested', '_last_tick_advanced'): + eq.require(type(k[key]) is bool, 'K boolean: ' + key) + eq.require(k['paused'] and k['absolute_minute'] == cp['minute'], 'clock contradiction') + eq.require(type(k['_phase_handlers']) is dict and set(k['_phase_handlers']) == {str(i) for i in range(11)}, 'exact phase key set 0..10') + for key in ('latest_digest', 'computed_latest_digest'): + eq.require(hex_sha(cp[key]), 'digest format') + eq.require(cp['observation']['before']['S'] == cp['S']['raw_bytes_sha'], 'S witness/transport contradiction') + eq.require(type(c['_mvp_manifest_cache_generation']) is int, 'cache generation') + eq.require(c['catalog_is_current'] is True, 'unfilled checkpoint cache') + ids = [c['catalog_instance_id'], c['current_catalog_instance_id']] + eq.require(all(type(v) is str and re.fullmatch('[1-9][0-9]*', v) for v in ids), 'cache instance IDs') + eq.require(ids[0] == ids[1], 'cache identity contradiction') + eq.validate_tree([29, c['_mvp_manifest_cache_bytes']]) + trees = eq.reconstruct_checkpoints(cps) + begin, begin_ids = counts(trees[0][0]) + end, end_ids = counts(trees[-1][0]) + eq.require(eq.exact(raw['event_start'], begin) and eq.exact(raw['event_end'], end), 'event counter/state contradiction') + event_ids = [] + for row in raw['events']: + tree = eq._transport(row['transport'], None) + data = fields(tree) + expected_keys = {'event_id', 'event_type', 'absolute_minute', 'source_service', 'entity_ids', 'payload', 'causation_command_id'} + eq.require(set(data) == expected_keys and tree[2] is None, 'event to_dictionary shape') + for name in ('event_id', 'event_type', 'source_service'): + eq.require(data[name][0] == 4 and bool(data[name][1]), 'serialized event String: ' + name) + for name in ('absolute_minute', 'causation_command_id'): + eq.require(data[name][0] == 2 and integer(data[name][1]), 'serialized event int: ' + name) + eq.require(start_minute <= data['absolute_minute'][1] <= start_minute + 30, 'event outside measurement') + ids = data['entity_ids'] + eq.require(ids[0] == 28 and ids[2] == [[2, 4], [21, ''], [0]] and all(v[0] == 4 for v in ids[1]), 'serialized entity_ids Array[String]') + eq.require(data['payload'][0] == 27, 'event payload Dictionary') + original = {'event_id': 21, 'event_type': 21, 'absolute_minute': 2, 'source_service': 21, + 'entity_ids': {'type': 28, 'typed_info': [[2, 21], [21, ''], [0]]}, + 'payload': {'type': 27, 'typed_info': data['payload'][2]}, 'causation_command_id': 2} + eq.require(eq.exact(row['original_field_types'], original), 'original event field types') + event_ids.append(data['event_id'][1]) + eq.require(len(set(event_ids)) == len(event_ids) and not set(event_ids).intersection(begin_ids), 'duplicate/reused event ID') + eq.require(set(end_ids) == set(begin_ids) | set(event_ids), 'missing/extra E2 events') + eq.require(end['counter'] - begin['counter'] == len(event_ids), 'event counter delta') + for row in raw['signal_order']: + eq.require(set(row) == {'signal', 'minute'} and row['signal'] in ('snapshot_published', 'state_updated'), 'signal record') + eq.require(type(row['minute']) is int and start_minute <= row['minute'] <= start_minute+30, 'signal minute') + check_measurement(raw, measurement) + out.update(ok=True, normalization=proofs, comparison=compared) + except (eq.EvidenceError, KeyError, TypeError, ValueError, IndexError) as exc: + out['errors'].append(str(exc)) + return out + + +def check_observation(cp, evidence): + """Bind retained full bytes to report SHA, not merely asserted equality.""" + eq.require(set(evidence) == {'before', 'after'}, 'observation evidence fields') + for side in ('before', 'after'): + row = evidence[side] + eq.require(set(row) == {'sha', 'S', 'K', 'C', 'kernel', 'cache'}, 'raw layer fields') + eq.require(eq.exact(row['kernel'], cp['K']) and eq.exact(row['cache'], cp['C']), 'raw layer value contradiction') + for layer in ('S', 'K', 'C'): + eq.validate_tree([29, row[layer]]) + actual = sha(base64.b64decode(row[layer], validate=True)) + eq.require(actual == row['sha'][layer] == cp['observation'][side][layer], 'raw layer SHA mismatch') + eq.require(all(evidence['before'][k] == evidence['after'][k] for k in ('S', 'K', 'C')), 'raw observation bytes differ') + return True + + +def read_report_stdout(stdout): + lines = [line[len('P28_02_EQ_REPORT='):] for line in stdout.splitlines() if line.startswith('P28_02_EQ_REPORT=')] + eq.require(len(lines) == 1, 'exactly one report line required') + return strict_json(lines[0]) + + +def strict_json(text): + def unique(pairs): + result = {} + for key, value in pairs: + eq.require(key not in result, 'duplicate JSON key: ' + key) + result[key] = value + return result + return json.loads(text, object_pairs_hook=unique) + + +def check_lifecycle(raw, lifecycle, guard): + """S2 startup proof; S4 must supply the separately SHA-bound guard receipt.""" + eq.require(lifecycle['stage'] in ('S2', 'S3a', 'S3b') and lifecycle['errors'] == [], 'probe errors/stage') + eq.require(lifecycle['stop_reason'] == {'S2': 'S2_complete_S3_pending', 'S3a': 'S3a_complete_S3b_pending', 'S3b': 'S3b_complete_S4_pending'}[lifecycle['stage']], 'probe did not finish stage') + if lifecycle['stage'] in ('S3a', 'S3b'): + check_measurement(raw, lifecycle['measurement']) + check_e3(dict(raw, scenarios=raw['scenarios'][:18]), lifecycle['e3'], lifecycle['e3_b1']) + if lifecycle['stage'] == 'S3b': + check_e45(raw, lifecycle['e45'], lifecycle['e3'][-1]['end']) + binding = lifecycle['guard'] + eq.require(guard['verified'] is True and eq.exact(binding['receipt'], guard), 'independent guard differs') + root = eq._profile(raw['profile_root']) + eq.require(root == binding['live_root'] == guard['actual_user_data_dir'], 'live/guard profile contradiction') + eq.require(hex_sha(binding['sha256']), 'guard SHA missing') + eq.require(eq.exact(lifecycle['observer_before'], lifecycle['observer_disconnected']), 'observers not restored') + eq.require(not eq.exact(lifecycle['observer_before'], lifecycle['observer_connected']), 'observers never connected') + b0 = 602 if raw['role'] == 'R' else 360 + for label, minute in (('B0', b0), ('B1', b0+30), ('outside', b0+60)): + row = lifecycle[label] + eq.require(row['kernel']['paused'] is True and row['kernel']['absolute_minute'] == minute, 'lifecycle minute: '+label) + for layer in ('S', 'K', 'C'): + eq.validate_tree([29, row[layer]]) + eq.require(sha(base64.b64decode(row[layer], validate=True)) == row['sha'][layer], 'lifecycle raw SHA') + for label in ('before_main', 'after_main', 'frame1', 'frame2'): + eq.require(type(lifecycle[label]) is dict and lifecycle[label]['kernel']['paused'] is True, 'startup frame evidence') + ops = lifecycle['ops'] + eq.require(ops['code'] == 'INVALID_START_TIME' if raw['role'] == 'R' else ops['ok'] is True, 'startup Ops outcome') + if raw['role'] == 'R': + restores = [r for r in lifecycle['preparation'] if r['operation'] == 'fixture_restore'] + eq.require(len(restores) == 1 and restores[0]['ok'] is True and restores[0]['input_sha256'] == + 'eb4f770071eb07cd7e136fe54c3f78768cc8de7a4264e62a9af1f06a8f90f9bd', 'fixture preparation') + return True + + +def _code(text): + # Mask strings/comments while retaining line positions. Tests exercise decoys. + return re.sub(r'"(?:\\.|[^"\\])*"|\'(?:\\.|[^\'\\])*\'|#[^\n]*', + lambda m: ' ' * len(m.group()), text) + + +def check_probe(text): + """Conservative S2 static policy, not a replacement for Godot parse/review.""" + errors = [] + code = _code(text) + if ':=' in code: + errors.append('inferred declarations forbidden; explicitly type Variant reads') + if re.search(r'\b(?:SimulationRuntimeService|GameClock|GameState|SimulationRuntime|EventBus)\s*\.', code): + errors.append('autoload static reference') + if re.search(r'\b(?:preload|load)\s*\(\s*["\']res://autoload/', text): + errors.append('autoload script import') + if re.search(r'\.(?:set_script|set|call|callv|call_deferred|set_deferred)\s*\(', code): + errors.append('dynamic product mutation/hook dispatch') + if re.search(r'\b(?:runtime|clock|main)\s*(?:\.[A-Za-z_]\w*|\[[^\n]*?\])+\s*(?:[+*/-]?=(?!=))', code): + errors.append('direct live assignment') + if re.search(r'\.(?:sort|sort_custom)\(', code): + for line in code.splitlines(): + if '.sort(' in line or ('.sort_custom(' in line and 'str(a) < str(b)' not in line and 'json_text(a) < json_text(b)' not in line): + errors.append('ordering must compare textual keys') + function = None + functions = {} + for line in text.splitlines(): + match = re.match(r'func (\w+)\(', line) + if match: + function = match[1] + functions[function] = [] + if function: functions[function].append(line) + clean = _code(line) + allowed_live = { + 'runtime': {'get', 'create_snapshot', 'restore_snapshot', 'load_from_path', 'get_save_policy', 'get_counter', 'subscribe', 'unsubscribe', 'connect', 'disconnect', 'get_facility_ids', 'get_bounds', 'preview_build_facility', 'submit_command', 'get_processed_result'}, + 'clock': {'get', 'set_paused', 'advance_minutes'}, + 'main': {'get', 'connect'}, + } + for receiver, method in re.findall(r'\b(runtime|clock|main)\s*(?:\.\w+)*\.(\w+)\s*\(', clean): + if method not in allowed_live[receiver]: errors.append('unlisted live method: '+receiver+'.'+method) + for method in re.findall(r'\.(\w+)\s*\(', clean): + if method in ('set_paused', 'restore_snapshot', 'advance_minutes', 'add_child', 'instantiate'): + required = 'step' if method == 'advance_minutes' else 'begin' + if function != required and not (method == 'restore_snapshot' and function in ('run_e3', 'run_e4')) and not (method == 'advance_minutes' and function in ('run_e4', 'run_e5')): errors.append('state-changing call outside preparation/stepping: ' + method) + if method in ('load_from_path', 'save_to_path', 'save_snapshot', 'load_snapshot', 'validate', 'enqueue', 'submit_command', 'enable_production_operations', 'initialize', 'reset', 'publish', 'publish_batch', '_set_speed', '_toggle_pause'): + if not ((method in ('load_from_path', 'validate') and function == 'run_e3') or (method == 'save_snapshot' and function == 'e3_prepare_package') or (method in ('load_from_path', 'save_snapshot', 'submit_command') and function == 'run_e4')): + errors.append('S3/unlisted state-changing call: ' + method) + if '.set_paused(' in clean and not re.search(r'\.set_paused\(true\)', clean): errors.append('only pause true allowed') + if '.advance_minutes(' in clean and not re.search(r'\.advance_minutes\(1\)', clean): errors.append('only one-minute stepping allowed') + # A digest alone, stub proof, or truncated checkpoint producer is not admitted. + required = { + 'transport': ('var_to_bytes(value)', 'var_to_bytes(decode(tree))', 'raw == rebuilt', 'encode(value)', 'hashed(json_text(tree).to_utf8_buffer())'), + 'checkpoint': ('layers()', 'transport(runtime.create_snapshot())', 'transport(latest_value)', 'before.s_bytes == after.s_bytes', 'before.k_bytes == after.k_bytes', 'before.c_bytes == after.c_bytes', 'diff_record(', 'write_evidence('), + 'bind_profile': ('ProjectSettings.globalize_path("user://").simplify_path()', 'receipt.get("actual_user_data_dir")', 'actual == live_root'), + 'observe_event': ('event.to_dictionary()', 'transport(value)', 'typeof(event.event_id)', 'typed_info(event.payload)', 'report.events.append('), + 'begin': ('runtime.domain_events.subscribe(&"*"', 'report.event_start = event_counts()', 'await step()', 'checkpoint()'), + 'finish': ('root.close_requested.emit()', 'runtime.domain_events.unsubscribe(', 'write_evidence("events.json"', 'write_evidence("lifecycle.json"'), + } + for name, snippets in required.items(): + body = '\n'.join(functions.get(name, [])) + # Comments cannot supply a required proof operation. + body = '\n'.join(line for line in body.splitlines() if not line.lstrip().startswith('#')) + for snippet in snippets: + if snippet not in body: errors.append('missing full-state/proof operation: ' + name + ': ' + snippet) + begin = '\n'.join(functions.get('begin', [])) + preparation, separator, rest = begin.partition('initial_inventory = inventory()') + if not separator or re.search(r'\.(?:restore_snapshot|set_paused|instantiate|add_child)\(', _code(rest)): + errors.append('preparation mutation after B0 boundary') + if code.count('.advance_minutes(') != 7 or code.count('.restore_snapshot(') != 3 or code.count('.set_paused(') != 2: + errors.append('unexpected mutation call count') + for name, snippets in { + 'run_e3': ('scenario_active = true', 'scenario_active = false', 'e3_observation()', 'runtime.restore_snapshot(input)', 'SimulationSnapshot.validate(input)', 'runtime.load_from_path(path)'), + 'e3_prepare_package': ('demand(scenario_active,', 'SaveService.save_snapshot(path, input, {})'), + }.items(): + body = '\n'.join(functions.get(name, [])) + for snippet in snippets: + if snippet not in body: errors.append('missing E3 boundary/call: '+name+': '+snippet) + if code.count('run_e3()') != 2 or code.count('e3_prepare_package(') != 2: + errors.append('unexpected scenario dispatch') + scenario_body = '\n'.join(functions.get('run_e3', [])) + prefix, opened, remaining = scenario_body.partition('scenario_active = true') + active, closed, suffix = remaining.partition('scenario_active = false') + if not opened or not closed or re.search(r'(?:restore_snapshot|load_from_path|validate|e3_prepare_package)\(', _code(prefix + suffix)): + errors.append('E3 operation outside active interval') + if text.count('print("P28_02_EQ_REPORT="') != 1: errors.append('single report emission required') + for name in ('run_e4', 'run_e5'): + body = '\n'.join(functions.get(name, [])) + prefix, opened, rest = body.partition('scenario_active = true') + active, closed, suffix = rest.partition('scenario_active = false') + if not opened or not closed or re.search(r'(?:advance_minutes|submit_command|restore_snapshot|load_from_path|save_snapshot|e4_candidates)\(|\breturned\s*\[', _code(prefix + suffix)): + errors.append('E4/E5 operation outside active interval') + if code.count(name+'()') != 2: errors.append('unexpected E4/E5 dispatch') + for name, body in functions.items(): + clean = _code('\n'.join(body)) + if name != 'run_e5' and re.search(r'\breturned\s*\[|__p28_eq_probe', '\n'.join(body)): + errors.append('ownership mutation outside E5') + if name in ('observe_snapshot', 'observe_state') and re.search(r'\[[^\n]*\]\s*=|\.(?:append|erase|clear|merge)\(', clean): + errors.append('signal handler mutation') + if name != 'run_e4' and 'e4_candidates()' in clean and name != 'e4_candidates': errors.append('candidate dispatch outside E4') + if code.count('e4_candidates()') != 2 or code.count('.submit_command(') != 2: errors.append('unexpected E4 command/search dispatch') + candidate_body = '\n'.join(functions.get('e4_candidates', [])) + for snippet in ('runtime.definition_registry.get_facility_ids()', 'runtime.world_service.get_bounds()', 'runtime.preview_build_facility(definition_id, origin, 0)', 'demand(scenario_active,', 'selection.trials.append('): + if snippet not in candidate_body: errors.append('missing E4 selection proof: '+snippet) + if re.search(r'report\.events\.(?:resize|pop_front|pop_back|erase|clear)', code): errors.append('event cap/removal forbidden') + return {'ok': not errors, 'stage': 'S3a', 'errors': errors} + + +# S3a source-backed E3 table; E4/E5 admission remains S3b. +E3_KINDS = ('missing_key', 'wrong_type', 'out_of_range', 'duplicate_published_ids', 'duplicate_facility', 'tampered_world') +E3_APIS = ('restore_snapshot', 'validate', 'load_from_path') + + +def node_at(tree, *names): + for name in names: + tree = fields(tree)[name] + return tree + + +def e3_expected_input(b1, kind): + value = copy.deepcopy(b1) + if kind == 'missing_key': + value[1] = [pair for pair in value[1] if pair[0][1] != 'clock'] + elif kind in ('wrong_type', 'out_of_range'): + node_at(value, 'clock', 'absolute_minute' if kind == 'wrong_type' else 'speed')[:] = ( + [4, 'x'] if kind == 'wrong_type' else [2, 9]) + elif kind in ('duplicate_published_ids', 'duplicate_facility'): + nodes = (node_at(value, 'systems', 'runtime', 'domain_events', 'published_ids') if kind == 'duplicate_published_ids' + else node_at(value, 'systems', 'runtime', 'facilities', 'instances')) + if nodes[1]: + nodes[1].append(copy.deepcopy(nodes[1][0])) + else: + eq.require(kind == 'duplicate_facility', 'no B1 published ID to duplicate') + return value + + +def e3_x(before, event): + value = copy.deepcopy(before) + counter = node_at(value, 'systems', 'runtime', 'id_generator', 'counters', 'domain_event') + counter[1] += 1 + domain = node_at(value, 'systems', 'runtime', 'domain_events') + ids = fields(domain)['published_ids'] + ids[1].append(copy.deepcopy(fields(event)['event_id'])) + ids[1].sort(key=lambda n: n[1]) + recent = fields(domain)['recent_events'] + dropped = copy.deepcopy(recent[1][0]) if len(recent[1]) == 256 else None + recent[1].append(copy.deepcopy(event)) + if len(recent[1]) > 256: + del recent[1][0] + return value, dropped + + +def e3_raw_observation(row): + cp = row['checkpoint'] + check_observation(cp, row['raw']) + s = eq._transport(cp['S'], None) + eq.require(cp['S']['raw_bytes_sha'] == row['raw']['before']['sha']['S'], 'E3 S transport/raw') + for layer in ('K', 'C'): + proof = row[layer+'_tree'] + eq._transport(proof, None) + eq.require(proof['raw_bytes_sha'] == row['raw']['before']['sha'][layer], 'E3 layer transport/raw') + return s + + +def e3_package_check(package, kind): + def files(rows): + eq.require(set(rows) == {'manifest.json', 'world.bin', 'thumbnail.png', 'journal.log'}, 'package inventory') + out = {} + for name, item in rows.items(): + if item is None: + out[name] = None + continue + eq.require(set(item) == {'bytes', 'sha256'}, 'package file fields') + content = base64.b64decode(item['bytes'], validate=True) + eq.require(sha(content) == item['sha256'], 'package file SHA') + out[name] = content + return out + saved = fields(eq._transport(package['save_return'], None)) + eq.require('ok' in saved and 'code' in saved, 'save preparation return') + original, modified = files(package['original']), files(package['modified']) + files(package['after_operation']) + if saved['ok'] == [1, 0]: + eq.require(kind.startswith('duplicate_'), 'required package save refused') + return False + eq.require(saved['ok'] == [1, 1], 'save preparation bool') + eq.require(all(original[n] == modified[n] for n in ('thumbnail.png', 'journal.log')), 'unlisted package mutation') + if kind == 'tampered_world': + expected = bytearray(original['world.bin']) + eq.require(len(expected) > 0, 'empty tamper world') + offset = len(expected)//2 + old = expected[offset] + expected[offset] ^= 1 + eq.require(modified['world.bin'] == bytes(expected) and original['manifest.json'] == modified['manifest.json'], 'D3 tamper rule') + eq.require(package['tamper'] == {'offset': offset, 'before': old, 'after': old ^ 1}, 'tamper evidence') + elif kind in ('missing_key', 'wrong_type', 'out_of_range'): + before, after = json.loads(original['manifest.json']), json.loads(modified['manifest.json']) + expected = copy.deepcopy(before) + if kind == 'missing_key': del expected['checksum_world'] + else: expected['format_version'] = 'x' if kind == 'wrong_type' else 2147483647 + eq.require(eq.exact(after, expected) and original['world.bin'] == modified['world.bin'], 'manifest mutation rule') + else: + eq.require(original == modified, 'duplicate package changed after save') + return True + + +def check_e3(raw, evidence, b1_record): + """Separate malformed evidence from observed existing-defect candidates. + + Returns all actual typed differences. Never promote NA or a defect to PASS. + """ + b1 = eq._transport(b1_record, None) + first = eq.reconstruct_checkpoints(raw['checkpoints'])[0][0] + eq.require(eq.exact(b1, first), 'E3 input is not measured B1') + facilities = node_at(b1, 'systems', 'runtime', 'facilities', 'instances') + count = len(facilities[1]) + eq.require(raw['role'] != 'R' or count > 0, 'R B1 has no facility') + expected_ids = ['E3/'+api+'/'+kind for api in E3_APIS for kind in E3_KINDS] + eq.require([s['id'] for s in raw['scenarios']] == expected_ids, 'complete ordered E3 applied/NA table') + eq.require([e['id'] for e in evidence] == expected_ids, 'E3 raw evidence coverage') + results = [] + previous_sha = raw['checkpoints'][-1]['observation']['after'] + for scenario, ev in zip(raw['scenarios'], evidence): + api, kind = scenario['operation'], scenario['result']['category'] + result = scenario['result'] + eq.require(set(result) == {'category', 'applicability', 'reason', 'invoked', 'facility_count', 'ok', 'errors', 'code', + 'code_reason', 'migration_attempted', 'event_count', 'path'}, 'E3 result fields') + eq.require(scenario['id'] == 'E3/'+api+'/'+kind, 'E3 API/category binding') + eq.require(result['facility_count'] == count, 'B1 facility count') + eq.require(ev['boundaries'] == ['begin', 'operation', 'end'], 'E3 interval boundaries') + expected_input = e3_expected_input(b1, kind) + eq.require(eq.exact(eq._transport(ev['input'], None), expected_input), 'fixed B1 mutation rule') + before, after = e3_raw_observation(ev['begin']), e3_raw_observation(ev['end']) + eq.require(eq.exact(previous_sha, ev['begin']['raw']['before']['sha']), 'unrecorded change between E3 intervals') + previous_sha = ev['end']['raw']['after']['sha'] + e3_raw_observation(ev['invocation_before']) + eq.require(eq.exact(scenario['checkpoints'], [ev['begin']['checkpoint'], ev['end']['checkpoint']]), 'E3 boundary binding') + events = [eq._transport(item, None) for item in ev['events']] + eq.require(eq.exact(events, scenario['events']) and type(result['event_count']) is int and result['event_count'] == len(events), 'E3 event count/evidence binding') + applied, reason, invoked = True, None, True + if kind == 'tampered_world' and api != 'load_from_path': + applied, reason, invoked = False, 'Dictionary API does not read packages', False + elif kind == 'duplicate_facility' and count == 0: + eq.require(raw['role'] == 'O', 'facility NA only for O') + applied, reason, invoked = False, 'B1 has zero facilities', False + elif kind.startswith('duplicate_') and api == 'validate': + applied, reason = False, 'Envelope validation does not inspect runtime internals' + if api == 'load_from_path': + eq.require(result['path'] == 'user://p28_eq/'+raw['role'].lower()+'/'+('duplicate_id' if kind.startswith('duplicate_') else kind), 'fixed scenario path') + if applied: + package_input = expected_input if kind.startswith('duplicate_') else b1 + eq.require(eq.exact(eq._transport(ev['package']['input'], None), package_input), 'package save input not fixed B1 copy') + if not e3_package_check(ev['package'], kind): + applied, reason, invoked = False, 'SaveService.save_snapshot refused duplicate input', False + else: + eq.require(ev['package'] is None, 'NA package unexpectedly prepared') + else: + eq.require(result['path'] is None and ev['package'] is None, 'Dictionary API package') + eq.require(result['applicability'] == ('applied' if applied else 'NA') and result['reason'] == reason and result['invoked'] is invoked, 'E3 applied/NA table contradiction') + actual = eq._transport(ev['return'], None) + eq.require(type(result['migration_attempted']) is bool, 'migration flag type') + if api != 'validate': + eq.require(result['errors'] is None, 'invented validation errors') + if api == 'restore_snapshot': + eq.require(result['code'] is None and result['code_reason'] == 'API returns bool only', 'restore invented code') + eq.require(actual == ([1, int(result['ok'])] if invoked and type(result['ok']) is bool else [0]), 'restore actual bool') + eq.require(not invoked or type(result['ok']) is bool, 'restore bool missing') + elif api == 'validate': + eq.require(result['code'] is None and result['code_reason'] == 'API returns ok/errors only', 'validate invented code') + if invoked: + data = fields(actual) + eq.require(set(data) == {'ok', 'errors'} and data['ok'] == [1, int(result['ok'])] and type(result['ok']) is bool, 'validate full return') + eq.require(data['errors'][0] == 28 and [v[1] for v in data['errors'][1]] == result['errors'] and all(v[0] == 4 for v in data['errors'][1]), 'validate errors full list') + elif invoked: + data = fields(actual) + eq.require('code' in data and data['code'][0] in (4, 21) and bool(data['code'][1]), 'load code missing') + eq.require(result['code'] == data['code'][1] and result['code_reason'] is None, 'load code binding') + eq.require(type(result['ok']) is bool and data['ok'] == [1, int(result['ok'])], 'load actual ok') + eq.require(result['migration_attempted'] is (data.get('migration_attempted', [1, 0]) == [1, 1]), 'migration fact') + if not invoked: + eq.require(actual == [0] and result['ok'] is None and result['code'] is None, 'NA has invented outcome') + defects = [] + expected_code, expected_error = None, None + if applied: + if result['ok'] is not False: defects.append({'kind': 'invalid_input_accepted', 'actual': actual}) + if api == 'validate': + expected_error = {'missing_key': 'missing_clock', 'wrong_type': 'invalid_absolute_minute', 'out_of_range': 'invalid_speed'}[kind] + if expected_error not in result['errors']: defects.append({'kind': 'expected_error_missing', 'expected': expected_error, 'actual': actual}) + if api == 'load_from_path': + expected_code = {'missing_key': 'INVALID_MANIFEST', 'wrong_type': 'INVALID_MANIFEST', 'out_of_range': 'UNSUPPORTED_FORMAT', + 'duplicate_published_ids': 'RESTORE_FAILED', 'duplicate_facility': 'RESTORE_FAILED', 'tampered_world': 'CHECKSUM_MISMATCH'}[kind] + if result['code'] != expected_code and not (kind == 'out_of_range' and result['migration_attempted']): + defects.append({'kind': 'unexpected_code', 'expected': expected_code, 'actual': result['code']}) + expected_count = 1 if api == 'load_from_path' and invoked else 0 + if len(events) != expected_count: + defects.append({'kind': 'event_count', 'expected': expected_count, 'actual': len(events)}) + expected_state, dropped = before, None + if expected_count == 1 and len(events) == 1: + event_data = fields(events[0]) + if event_data['event_type'] != [4, 'SAVE_LOAD_FAILED'] or event_data['source_service'] != [4, 'save_service'] or event_data['entity_ids'][1] != []: + defects.append({'kind': 'failure_event_shape', 'actual': events[0]}) + latest = eq._transport(ev['latest_save_operation_result'], None) + if not eq.exact(latest, event_data['payload']): + defects.append({'kind': 'failure_payload_latest_mismatch', 'latest': latest, 'payload': event_data['payload']}) + data = fields(actual) + payload = fields(event_data['payload']) + for name in ('ok', 'code'): + if not eq.exact(data[name], payload[name]): + defects.append({'kind': 'return_payload_mismatch', 'field': name, 'return': data[name], 'payload': payload[name]}) + for name in ('duration_us', 'runtime_duration_us', 'message', 'save_path'): + if name in data and not eq.exact(data[name], payload[name]): + defects.append({'kind': 'return_payload_mismatch', 'field': name, 'return': data[name], 'payload': payload[name]}) + if data.get('preload_pause_restored') != [1, 1] or data.get('loaded_clock_paused') != [1, int(ev['begin']['checkpoint']['K']['paused'])]: + defects.append({'kind': 'load_pause_outcome', 'actual': actual}) + if 'recovery_report' in data and fields(data['recovery_report']).get('restore_committed') != [1, 0]: + defects.append({'kind': 'load_restore_committed', 'actual': data['recovery_report']}) + expected_state, dropped = e3_x(before, events[0]) + normalized_expected, expected_side = eq.normalize_tree(expected_state, raw['profile_root']) + normalized_after, actual_side = eq.normalize_tree(after, raw['profile_root']) + delta = eq.compare_trees(normalized_expected, normalized_after) + if not delta['equal']: defects.append({'kind': 'S_changes', 'comparison': delta}) + for layer in ('K', 'C'): + left, right = ev['begin']['raw']['before'], ev['end']['raw']['after'] + if left[layer] != right[layer]: + defects.append({'kind': layer+'_changes', 'before': left[layer], 'after': right[layer], + 'comparison': eq.compare_trees(ev['begin'][layer+'_tree']['tree'], ev['end'][layer+'_tree']['tree'])}) + # Dictionary APIs require byte identity, not normalization/order fallback. + if expected_count == 0 and ev['begin']['raw']['before']['S'] != ev['end']['raw']['after']['S']: + defects.append({'kind': 'S_bytes_changed', 'before': ev['begin']['raw']['before']['S'], 'after': ev['end']['raw']['after']['S']}) + results.append({'id': scenario['id'], 'applicability': result['applicability'], 'reason': reason, + 'expected': {'ok': False if applied else None, 'code': expected_code, 'error': expected_error, 'event_count': expected_count}, + 'actual': copy.deepcopy(result), + 'status': 'existing-defect-candidate' if defects else ('recorded' if applied else 'NA'), + 'defects': defects, 'dropped_recent_event': dropped, 'expected_state': expected_state, + 'state_comparison': delta, 'expected_sidecar': expected_side, 'actual_sidecar': actual_side}) + results[-1]['exclusions'] = [{'reason': 'SaveService static diagnostic budget outside S/K/C; wall time', + 'before': eq._transport(ev['save_budget_before'], None), 'after': eq._transport(ev['save_budget_after'], None)}, + {'reason': 'Package manifest/file evidence outside S/E2; includes real timestamps', 'actual': ev['package']}] + return results + + + +# S3b additions. Raw evidence is authoritative; outcome labels are derived. +E4_PATHS = ('build_facility', 'tick', 'restore_snapshot', 'load_from_path', 'rejected_command') +E5_TARGETS = ('create_snapshot', 'latest_snapshot', 'snapshot_published', 'state_updated') +SORT_RULE = 'String(id) ascending Unicode code point' +CELL_RULE = 'inclusive x/y public bounds; z FRONT=0 through BACK=1; x,y,z lexical; ID outer; rotation=0' + + +def join_facts(value, profile_root): + """Normalize only snapshot transports; retain all raw facts in raw report.""" + proofs = [] + def walk(item, path): + if isinstance(item, dict) and {'tree', 'tree_sha', 'raw_bytes_sha', 'roundtrip_ok'} == set(item): + tree = eq._transport(item, None) + if path and path[-1] in ('held_before', 'held_after', 'input'): + normal, side = eq.normalize_tree(tree, profile_root) + eq.require(eq.exact(eq.restore_tree(normal, side, profile_root), tree), 'fact normalization roundtrip') + proofs.append({'path': path, 'sidecar': side, 'raw': item}) + return normal + return tree + if isinstance(item, dict): + return {k: walk(v, path+[k]) for k, v in item.items()} + if isinstance(item, list): + return [walk(v, path+[i]) for i, v in enumerate(item)] + return item + return walk(value, []), proofs + + +def e45_facts(detail): + facts = copy.deepcopy(detail) + for key in ('package_before', 'package_after', 'save_return', 'return', 'save_budget_before', 'save_budget_after', 'latest_save_operation_result', 'observation_before', 'observation_after'): + facts.pop(key, None) + if 'return' in detail: + actual = eq._transport(detail['return'], None) + facts['return_fact'] = ({k: fields(actual)[k][1] if fields(actual)[k][0] != 1 else bool(fields(actual)[k][1]) + for k in ('ok', 'code')} if actual[0] == 27 else bool(actual[1])) + for trial in facts.get('trials', []): + trial.pop('before', None); trial.pop('after', None) + return facts + + +def check_selection(detail, begin): + for key in ('observation_before', 'observation_after'): + eq.require(eq.exact(e3_raw_observation(detail[key]), begin), 'preview search S baseline') + eq.require(eq.exact(detail['observation_before']['raw'], detail['observation_after']['raw']), 'preview search changed full S/K/C') + eq.require(detail['source'] == 'definition_registry.get_facility_ids()', 'E4 registry source') + raw = eq._transport(detail['raw_ids'], None) + ordered = eq._transport(detail['sorted_ids'], None) + eq.require(raw[0] == ordered[0] == 28 and all(n[0] == 21 for n in raw[1]), 'facility ID types') + ids = [n[1] for n in raw[1]] + eq.require(type(detail['count']) is int and detail['count'] == len(ids) and len(ids) > 0 and len(set(ids)) == len(ids), 'empty/invalid facility registry') + eq.require(ordered[2] == raw[2] and ordered[1] == sorted(raw[1], key=lambda n: n[1]) and detail['sort_rule'] == SORT_RULE, 'facility sort rule') + eq.require(detail['cell_rule'] == CELL_RULE, 'cell scan rule') + bounds = eq._transport(detail['bounds'], None) + eq.require(eq.exact(bounds, node_at(begin, 'systems', 'runtime', 'world', 'bounds')), 'public bounds/state binding') + b = fields(bounds) + eq.require(set(b) == {'min_x', 'max_x', 'min_y', 'max_y'} and all(n[0] == 2 for n in b.values()), 'bounds shape') + eq.require(b['min_x'][1] <= b['max_x'][1] and b['min_y'][1] <= b['max_y'][1], 'empty scan bounds') + def candidates(): + for ident in sorted(ids): + for x in range(b['min_x'][1], b['max_x'][1]+1): + for y in range(b['min_y'][1], b['max_y'][1]+1): + for z in (0, 1): + yield ident, x, y, z + expected = candidates() + chosen = None + for trial in detail['trials']: + eq.require(chosen is None, 'trials after first placeable candidate') + wanted = next(expected, None) + eq.require(wanted is not None, 'extra candidate trial') + c = fields(eq._transport(trial['candidate'], None)) + eq.require(set(c) == {'definition_id', 'origin', 'rotation'} and c['definition_id'] == [21, wanted[0]] + and c['origin'] == [10, [[2, v] for v in wanted[1:]]] and c['rotation'] == [2, 0], 'missing/reordered candidate trial') + preview = fields(eq._transport(trial['preview'], None)) + eq.require(preview.get('can_build') in ([1, 0], [1, 1]), 'full preview result required') + eq.require(set(trial) == {'candidate', 'preview'}, 'preview trial fields') + if preview['can_build'] == [1, 1]: chosen = trial['candidate'] + if chosen is None: + eq.require(next(expected, None) is None, 'missing candidate trials') + eq.require(detail['chosen'] is None and detail['applicability'] == 'NA' and detail['reason'] == 'all registry/cell pairs rejected by public preview', 'false NA/reason') + eq.require('submit' not in detail and 'command_result' not in detail, 'NA executed command') + else: + eq.require(eq.exact(detail['chosen'], chosen) and detail['applicability'] == 'applied' and detail['reason'] is None, 'chosen without matching preview') + check_command(detail) + return chosen is not None + + +def check_command(detail): + submitted = fields(eq._transport(detail['submit'], None)) + completed = fields(eq._transport(detail['command_result'], None)) + eq.require(all(k in submitted and k in completed for k in ('command_id', 'code')), 'command result absent') + eq.require(submitted['command_id'] == completed['command_id'] and submitted['command_id'][0] == 2, 'command ID binding') + eq.require(submitted['code'][0] == completed['code'][0] == 4, 'actual command code required') + return completed + + +def check_e45(raw, evidence, previous): + ids = ['E4/'+p for p in E4_PATHS] + ['E5/'+t+'/'+l+'/'+d for t in E5_TARGETS + for l in ('dict', 'array') for d in ('outside_in', 'inside_out')] + scenarios = raw['scenarios'][18:] + eq.require([s['id'] for s in scenarios] == ids and [e['id'] for e in evidence] == ids, 'complete ordered E4/E5 coverage') + outcomes = [] + previous_sha = previous['raw']['after']['sha'] + for scenario, ev in zip(scenarios, evidence): + eq.require(set(ev) == {'id', 'boundaries', 'observations', 'events', 'signals', 'detail'}, 'E4/E5 evidence fields') + eq.require(ev['boundaries'] == ['begin', 'operation', 'end'], 'E4/E5 boundaries') + obs, detail = ev['observations'], ev['detail'] + eq.require(eq.exact(detail['signals'], ev['signals']), 'scenario signals/facts binding') + if scenario['id'].startswith('E5/'): + eq.require(set(detail) == {'target', 'location', 'direction', 'digest_materialized_before', 'held_before', 'held_after', 'signals'}, 'E5 detail fields') + else: + common = {'save_budget_before', 'save_budget_after', 'signals'} + specific = { + 'build_facility': {'source', 'raw_ids', 'count', 'sorted_ids', 'sort_rule', 'bounds', 'cell_rule', 'trials', 'chosen', 'applicability', 'reason', 'observation_before', 'observation_after'}, + 'tick': set(), 'restore_snapshot': {'input', 'return'}, + 'load_from_path': {'input', 'path', 'save_return', 'package_before', 'package_after', 'return', 'latest_save_operation_result'}, + 'rejected_command': {'submit', 'command_result'}, + }[scenario['operation']] + if scenario['operation'] == 'build_facility' and detail.get('chosen') is not None: specific |= {'submit', 'command_result'} + eq.require(set(detail) == common | specific, 'E4 detail fields; no invented staleness verdict') + eq.require(len(obs) >= 2, 'E4/E5 missing observations') + trees = [e3_raw_observation(o) for o in obs] + eq.require(eq.exact(previous_sha, obs[0]['raw']['before']['sha']), 'E4/E5 interval gap') + previous_sha = obs[-1]['raw']['after']['sha'] + eq.require(eq.exact(scenario['checkpoints'], [o['checkpoint'] for o in obs]), 'E4/E5 observation binding') + events = [eq._transport(e, None) for e in ev['events']] + result = scenario['result'] + eq.require(set(result) == {'event_count', 'applicability', 'reason', 'facts'}, 'E4/E5 result fields; caller PASS forbidden') + eq.require(type(result['event_count']) is int and result['event_count'] == len(events) + and eq.exact(events, scenario['events']), 'E4/E5 event count binding') + eq.require(result['applicability'] == detail.get('applicability', 'applied') and result['reason'] == detail.get('reason'), 'E4/E5 applicability binding') + eq.require(eq.exact(result['facts'], e45_facts(detail)), 'E4/E5 facts binding/aliasing record missing') + for signal in ev['signals']: + eq.require(set(signal) == {'signal', 'minute'} and signal['signal'] in ('snapshot_published', 'state_updated') + and obs[0]['checkpoint']['minute'] <= signal['minute'] <= obs[-1]['checkpoint']['minute'], 'scenario signal interval') + eq.require(len(ev['signals']) % 2 == 0, 'scenario signal pair missing') + for i in range(0, len(ev['signals']), 2): + a, b = ev['signals'][i:i+2] + eq.require(a['signal'] == 'snapshot_published' and b == {'signal': 'state_updated', 'minute': a['minute']}, 'scenario signal order') + defects = [] + differences = {} + for name in ('S', 'latest'): + a, b = [eq._transport(o['checkpoint'][name], None) for o in (obs[0], obs[-1])] + differences[name] = eq.compare_trees(a, b) + for name in ('K', 'C'): + differences[name] = eq.compare_trees(obs[0][name+'_tree']['tree'], obs[-1][name+'_tree']['tree']) + op = scenario['operation'] + begin_count, begin_ids = counts(trees[0]) + end_count, end_ids = counts(trees[-1]) + event_ids = [fields(event)['event_id'][1] for event in events] + eq.require(len(set(event_ids)) == len(event_ids) and not set(event_ids).intersection(begin_ids) + and set(end_ids) == set(begin_ids) | set(event_ids) + and end_count['counter'] - begin_count['counter'] == len(events), 'E4/E5 full event coverage') + if scenario['id'].startswith('E4/'): + eq.require(scenario['id'] == 'E4/'+op, 'E4 operation') + for key in ('save_budget_before', 'save_budget_after'): + eq.require(set(fields(eq._transport(detail[key], None))) == {'_samples', '_totals', '_sample_counts'}, 'save diagnostic budget missing') + applied = True + if op == 'build_facility': applied = check_selection(detail, trees[0]) + else: eq.require(result['applicability'] == 'applied' and result['reason'] is None, 'unlisted E4 NA') + count = 3 if op == 'rejected_command' or (op == 'build_facility' and applied) else 2 + eq.require(len(obs) == count, 'submit/immediate E4 checkpoint missing') + tick = op in ('tick', 'rejected_command') or (op == 'build_facility' and applied) + eq.require(obs[-1]['checkpoint']['minute'] == obs[0]['checkpoint']['minute'] + int(tick), 'E4 tick count') + if len(obs) == 3: eq.require(obs[1]['checkpoint']['minute'] == obs[0]['checkpoint']['minute'], 'submit checkpoint delayed') + if op in ('restore_snapshot', 'load_from_path'): + p = eq._transport(detail['input'], None) + eq.require(eq.exact(p, trees[0]), 'E4 input not current deep copy') + actual = eq._transport(detail['return'], None) + expected = p + if op == 'restore_snapshot': + eq.require(actual == [1, 1], 'E4 restore did not succeed') + eq.require(len(events) == 0, 'restore must emit zero events') + else: + eq.require(fields(actual).get('ok') == [1, 1] and 'code' in fields(actual), 'E4 load did not succeed') + eq.require(detail['path'] == 'user://p28_eq/'+raw['role'].lower()+'/good', 'fixed E4 path') + eq.require(len(events) == 1 and fields(events[0])['event_type'] == [4, 'SAVE_LOADED'], 'load must emit one SAVE_LOADED') + eq.require(fields(events[0])['source_service'] == [4, 'save_service'], 'load event source') + eq.require(eq.exact(eq._transport(detail['latest_save_operation_result'], None), fields(events[0])['payload']), 'load payload/latest result mismatch') + expected, dropped = e3_x(p, events[0]) + package = {'save_return': detail['save_return'], 'original': detail['package_before'], + 'modified': detail['package_before'], 'after_operation': detail['package_after']} + e3_package_check(package, 'good') + left, left_side = eq.normalize_tree(expected, raw['profile_root']) + right, right_side = eq.normalize_tree(trees[-1], raw['profile_root']) + delta = eq.compare_trees(left, right) + eq.require(delta['equal'], 'E4 restore/load X(P,event) mismatch') + differences['expected_state'] = {'comparison': delta, 'expected': expected, 'sidecars': [left_side, right_side]} + if op == 'rejected_command': + command = check_command(detail) + eq.require(command['code'] != [4, 'OK'], 'nonchanging command not rejected') + # All paths retained, including tick effects; do not assert equivalence from digest. + differences['submit'] = eq.compare_trees(trees[0], trees[1]) + differences['tick'] = eq.compare_trees(trees[1], trees[2]) + else: + _, target, location, direction = scenario['id'].split('/') + eq.require(op == direction and all(detail[k] == v for k, v in [('target', target), ('location', location), ('direction', direction)]), 'E5 target/direction') + eq.require(result['applicability'] == 'applied' and result['reason'] is None and len(obs) == 4, 'E5 coverage/NA') + eq.require(detail['digest_materialized_before'] is True, 'E5 digest not materialized') + minutes = [o['checkpoint']['minute'] for o in obs] + eq.require(minutes == [minutes[0], minutes[0]+1, minutes[0]+1+int(direction == 'inside_out'), minutes[0]+2+int(direction == 'inside_out')], 'E5 preparation/operation/reset tick sequence') + held = eq._transport(detail['held_before'], None) + after_held = eq._transport(detail['held_after'], None) + baseline = obs[1]['checkpoint'] + expected_held = eq._transport(baseline['S' if target == 'create_snapshot' else 'latest'], None) + eq.require(eq.exact(held, expected_held), 'E5 returned target binding') + if direction == 'outside_in': + expected = copy.deepcopy(held) + if location == 'dict': + n = node_at(expected, 'systems', 'runtime', 'id_generator', 'counters') + eq.require('__p28_eq_probe' not in fields(n), 'E5 marker already present') + n[1].append([[4, '__p28_eq_probe'], [2, 1]]) + else: + node_at(expected, 'systems', 'runtime', 'domain_events', 'published_ids')[1].append([4, '__p28_eq_probe']) + eq.require(eq.exact(expected, after_held), 'E5 fixed nested mutation absent/extra') + for layer in ('S', 'latest'): + delta = eq.compare_trees(eq._transport(obs[1]['checkpoint'][layer], None), eq._transport(obs[2]['checkpoint'][layer], None)) + differences['ownership_'+layer] = delta + if not delta['equal']: defects.append({'kind': 'external_mutation_'+layer, 'comparison': delta}) + old, new = obs[1]['checkpoint'], obs[2]['checkpoint'] + for field in ('latest_digest', 'computed_latest_digest'): + differences[field] = {'before': old[field], 'after': new[field]} + if old[field] != new[field]: defects.append({'kind': field+'_changed', 'before': old[field], 'after': new[field]}) + if new['latest_digest'] != new['computed_latest_digest']: + defects.append({'kind': 'cached_digest_aliasing', 'actual': new['latest_digest'], 'computed': new['computed_latest_digest']}) + else: + delta = eq.compare_trees(held, after_held) + differences['held'] = delta + if not delta['equal']: defects.append({'kind': 'internal_mutation_of_returned_value', 'comparison': delta}) + for layer in ('K', 'C'): + differences['ownership_'+layer] = eq.compare_trees(obs[1][layer+'_tree']['tree'], obs[2][layer+'_tree']['tree']) + eq.require(len(events) == counts(trees[-1])[0]['counter']-counts(trees[0])[0]['counter'], 'E5 uncapped event counter delta') + outcomes.append({'id': scenario['id'], 'status': 'existing-defect' if defects else ('NA' if result['applicability'] == 'NA' else 'recorded'), + 'defects': defects, 'differences': differences, 'signals': ev['signals'], + 'latest_policy': 'record actual value; publication timing is not cache staleness', + 'exclusions': [{'reason': 'Save package wall time and raw API timing; state/event normalization remains closed F1-F3', + 'actual': {k: detail[k] for k in ('save_return', 'return', 'package_before', 'package_after', 'save_budget_before', 'save_budget_after', 'latest_save_operation_result') if k in detail}}]}) + return outcomes + + +def main(): + import argparse + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--report', type=Path, required=True) + parser.add_argument('--lifecycle', type=Path, required=True) + parser.add_argument('--probe', type=Path, default=Path(__file__).with_name('eq_probe.gd')) + args = parser.parse_args() + life = strict_json(args.lifecycle.read_text()) + result = {'format': check_report(strict_json(args.report.read_text()), life['measurement'], life['e3'], life['e3_b1'], life.get('e45')), 'static': check_probe(args.probe.read_text())} + print(json.dumps(result, ensure_ascii=False)) + return 0 if all(item['ok'] for item in result.values()) else 1 + + +if __name__ == '__main__': + raise SystemExit(main()) diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py new file mode 100644 index 0000000..656558c --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py @@ -0,0 +1,651 @@ +"""S1 pure-Python typed transport/comparison. No engine or product imports. + +Paths are lists of ['key', key_node] / ['index', integer] segments. +Transport validation is distinct from product acceptance (see IMPLEMENTATION.md). +""" +import base64 +import copy +import hashlib +import json +import re + + +class EvidenceError(ValueError): + """Malformed, incomplete, or unauthorized evidence transformation.""" + + +SAVE_EVENTS = frozenset('SAVE_CHECKPOINT_SUCCEEDED SAVE_CHECKPOINT_FAILED SAVE_LOADED ' + 'SAVE_LOAD_FAILED SAVE_MIGRATION_SUCCEEDED SAVE_MIGRATION_FAILED SAVE_RECOVERY_LOADED ' + 'SAVE_RECOVERY_CANDIDATE_LOADED SAVE_RECOVERY_FAILED'.split()) +OPT_PATHS = frozenset(('autoload/simulation_runtime.gd', 'scripts/core/simulation_snapshot.gd', + 'scripts/world/world_service.gd', 'scripts/world/route_subslot_path_adapter.gd', + 'scripts/world/path_service.gd', 'scripts/core/command_queue.gd')) +SOURCE_SHA = '651f703621c8ed06a724709f75d8bc05b1eef2988c3b3d5d3466096a3f759bf0' +TOKEN = '{PRIVATE_USER_ROOT}/' + + +def require(ok, message): + if not ok: + raise EvidenceError(message) + + +def json_bytes(value): + return json.dumps(value, ensure_ascii=False, separators=(',', ':'), allow_nan=False).encode('utf-8') + + +def exact(a, b): + return json_bytes(a) == json_bytes(b) + + +def validate_tree(node): + """Validate all nodes; no application depth cutoff or value coercion.""" + pending = [node] + while pending: + n = pending.pop() + require(type(n) is list and n and type(n[0]) is int, 'invalid typed node') + t = n[0] + require(t not in (23, 24, 25, 26) and 0 <= t <= 38, 'unsupported Variant type') + require(len(n) == (1 if t == 0 else 3 if t in (27, 28) else 2), 'node arity') + if t == 0: + continue + p = n[1] + if t in (1, 2): + require(type(p) is int and (p in (0, 1) if t == 1 else -(2**63) <= p < 2**63), 'integer payload') + elif t == 3: + require(type(p) is str and re.fullmatch('[0-9a-f]{16}', p), 'float must be f64 LE hex') + elif t in (4, 21, 22): + require(type(p) is str, 'string payload') + elif t == 29: + require(type(p) is str, 'byte array payload') + try: + require(base64.b64encode(base64.b64decode(p, validate=True)).decode() == p, 'noncanonical base64') + except (ValueError, TypeError) as exc: + raise EvidenceError('invalid base64') from exc + elif t == 27: + require(type(p) is list, 'dictionary entries') + seen = set() + for pair in p: + require(type(pair) is list and len(pair) == 2, 'dictionary pair') + key = json_bytes(pair[0]) + require(key not in seen, 'duplicate dictionary key') + seen.add(key) + pending.extend(pair) + _typed_info(n[2], dictionary=True) + elif t == 28: + require(type(p) is list, 'array elements') + _typed_info(n[2], dictionary=False) + pending.extend(p) + else: + require(type(p) is list, 'component nodes') + sizes = {5: 2, 6: 2, 7: 4, 8: 4, 9: 3, 10: 3, 11: 6, + 12: 4, 13: 4, 14: 4, 15: 4, 16: 6, 17: 9, 18: 12, 19: 16, 20: 4} + if t in sizes: + require(len(p) == sizes[t], 'component count') + integer = t in (6, 8, 10, 13) + require(all(x and x[0] == (2 if integer else 3) for x in p), 'component type') + elif t in (30, 31, 32, 33, 34): + expected = {30: 2, 31: 2, 32: 3, 33: 3, 34: 4}[t] + require(all(x and x[0] == expected for x in p), 'packed element type') + else: + require(all(x and x[0] == {35: 5, 36: 9, 37: 20, 38: 12}[t] for x in p), 'packed vector type') + pending.extend(p) + return node + + +def _typed_info(info, dictionary): + # Metadata uses nodes too: builtin int, class StringName, script null. + if info is None: + return + require(type(info) is list and len(info) == (2 if dictionary else 3), 'typed metadata') + rows = info if dictionary else [info] + for row in rows: + require(type(row) is list and len(row) == 3, 'typed metadata row') + for n in row: + validate_tree(n) + require(row[0][0] == 2 and row[1][0] == 21 and row[2] == [0], 'unsupported typed script metadata') + + +def tree_sha(tree): + validate_tree(tree) + return hashlib.sha256(json_bytes(tree)).hexdigest() + + +def _key_segment(key): + return ['key', copy.deepcopy(key)] + + +def _field(node, name): + if node[0] != 27: + return None + found = [v for k, v in node[1] if k[0] in (4, 21) and k[1] == name] + require(len(found) <= 1, 'ambiguous textual key: ' + name) + return found[0] if found else None + + +def _text(node): + return node[1] if node and node[0] in (4, 21) else None + + +def _at(tree, path): + n = tree + for segment in path: + require(type(segment) is list and len(segment) == 2, 'path segment') + kind, value = segment + if kind == 'key': + require(n[0] == 27, 'key path through non-dictionary') + matches = [v for k, v in n[1] if exact(k, value)] + require(len(matches) == 1, 'missing/ambiguous key path') + n = matches[0] + else: + require(kind == 'index' and n[0] == 28 and type(value) is int and 0 <= value < len(n[1]), 'array path') + n = n[1][value] + return n + + +def _put(tree, path, value): + target = _at(tree, path) + target[:] = copy.deepcopy(value) + + +def apply_diff(tree, operations): + result = copy.deepcopy(validate_tree(tree)) + require(type(operations) is list, 'diff operations') + for op in operations: + require(type(op) is dict and 'op' in op and type(op.get('path')) is list, 'diff operation') + target = _at(result, op['path']) + kind = op['op'] + if kind == 'set': + require(set(op) == {'op', 'path', 'node'}, 'set fields') + _put(result, op['path'], validate_tree(op['node'])) + elif kind == 'dict_insert': + require(set(op) == {'op', 'path', 'index', 'key_node', 'value_node'}, 'insert fields') + require(target[0] == 27 and type(op['index']) is int and 0 <= op['index'] <= len(target[1]), 'insert index') + validate_tree(op['key_node']); validate_tree(op['value_node']) + require(not any(exact(k, op['key_node']) for k, _ in target[1]), 'insert duplicate') + target[1].insert(op['index'], copy.deepcopy([op['key_node'], op['value_node']])) + elif kind == 'dict_remove': + require(set(op) == {'op', 'path', 'key_node'} and target[0] == 27, 'remove fields') + indexes = [i for i, (k, _) in enumerate(target[1]) if exact(k, op['key_node'])] + require(len(indexes) == 1, 'remove missing key') + target[1].pop(indexes[0]) + elif kind == 'array_splice': + require(set(op) == {'op', 'path', 'start', 'delete_count', 'nodes'} and target[0] == 28, 'splice fields') + start, count = op['start'], op['delete_count'] + require(type(start) is int and type(count) is int and 0 <= start <= len(target[1]) and 0 <= count <= len(target[1])-start, 'splice bounds') + require(type(op['nodes']) is list, 'splice nodes') + for n in op['nodes']: + validate_tree(n) + target[1][start:start+count] = copy.deepcopy(op['nodes']) + else: + raise EvidenceError('unknown diff operation') + validate_tree(result) + return result + + +def reconstruct_checkpoints(checkpoints): + """Each checkpoint has S and latest transport records; verify before use.""" + require(type(checkpoints) is list and checkpoints, 'missing checkpoints') + result, previous = [], None + for cp in checkpoints: + s = _transport(cp['S'], previous) + latest = cp['latest'] + if latest.get('same_as_S') is True: + require(set(latest) == {'same_as_S', 'tree_sha', 'raw_bytes_sha', 'roundtrip_ok'}, 'same_as_S fields') + _proof(latest, s) + require(latest['raw_bytes_sha'] == cp['S']['raw_bytes_sha'], 'same_as_S byte mismatch') + l = copy.deepcopy(s) + else: + l = _transport(latest, s) + result.append((s, l)) + previous = s + return result + + +def _proof(record, tree): + require(record.get('roundtrip_ok') is True, 'Godot roundtrip missing/failed') + require(type(record.get('raw_bytes_sha')) is str and re.fullmatch('[0-9a-f]{64}', record['raw_bytes_sha']), 'raw bytes SHA') + require(record.get('tree_sha') == tree_sha(tree), 'tree SHA mismatch') + + +def _transport(record, baseline): + require(('tree' in record) != ('diff' in record), 'tree/diff exclusive') + require(set(record) == {'tree' if 'tree' in record else 'diff', 'tree_sha', 'raw_bytes_sha', 'roundtrip_ok'}, 'transport fields') + if 'tree' in record: + tree = copy.deepcopy(record['tree']) + else: + require(baseline is not None, 'diff without baseline') + tree = apply_diff(baseline, record['diff']) + _proof(record, tree) + return tree + + +def compare_trees(a, b): + validate_tree(a); validate_tree(b) + differences, orders = [], [] + def diff(path, x, y): + differences.append({'path': copy.deepcopy(path), 'a': copy.deepcopy(x), 'b': copy.deepcopy(y)}) + def walk(x, y, path): + if exact(x, y): + return + if x[0] != y[0] or len(x) != len(y): + diff(path, x, y); return + t = x[0] + if t in (27, 28) and not exact(x[2], y[2]): + diff(path + [['metadata', 0]], x[2], y[2]) + if t == 27: + def keyed(n): + d = {} + for k, v in n[1]: + text = _key_text(k) + require(text not in d, 'duplicate textual dictionary key') + d[text] = (k, v) + return d + dx, dy = keyed(x), keyed(y) + if set(dx) == set(dy) and [_key_text(k) for k, _ in x[1]] != [_key_text(k) for k, _ in y[1]]: + orders.append(copy.deepcopy(path)) + for key in sorted(set(dx) | set(dy)): + if key not in dx or key not in dy: + diff(path + [['key', [4, key]]], dx.get(key), dy.get(key)); continue + kx, vx = dx[key]; ky, vy = dy[key] + p = path + [_key_segment(kx)] + if not exact(kx, ky): + diff(p + [['key_type', 0]], kx, ky) + walk(vx, vy, p) + elif t == 28 or t in range(5, 21) or t in range(30, 39): + for i in range(max(len(x[1]), len(y[1]))): + if i >= len(x[1]) or i >= len(y[1]): + diff(path + [['index', i]], x[1][i] if i < len(x[1]) else None, y[1][i] if i < len(y[1]) else None) + else: + walk(x[1][i], y[1][i], path + [['index', i]]) + else: + diff(path, x, y) + walk(a, b, []) + return {'equal': not differences, 'exact': exact(a, b), 'differences': differences, 'dict_order_paths': orders} + + +def _key_text(key): + """Textual ordering never erases the original key node/type. + + Non-string keys use a lossless textual transport spelling, avoiding any + conversion of float bits or compound values to approximate decimal text. + """ + if key[0] in (4, 21, 22): + return key[1] + if key[0] == 2: + return str(key[1]) + if key[0] == 1: + return 'true' if key[1] else 'false' + if key[0] == 0: + return '' + return json_bytes(key).decode('utf-8') + + +def _profile(profile_root): + require(type(profile_root) is dict and set(profile_root) == {'root', 'actual_user_data_dir'}, 'guard-bound profile required') + root = profile_root['root'] + require(type(root) is str and root.startswith('/') and root != '/' and not root.endswith('/') and '/..' not in root and '/./' not in root, 'profile root must be simplified absolute path') + require(root == profile_root['actual_user_data_dir'], 'profile root/guard mismatch') + return root + + +def _marker(key, node): + require(node[0] == 2 and node[1] >= 0, 'timing must be nonnegative int') + return [27, [[[4, 'redacted_timing'], [4, key]], [[4, 'typeof'], [2, node[0]]]], None] + + +def _normalize(trees, profile_root, events): + root = _profile(profile_root) + result = copy.deepcopy(trees) + side = {'entries': [], 'violations': [], 'profile_root': {**profile_root, 'matches_guard': True}} + def visit(n, path, event_index, permitted_payload=False, event_root=False): + if n[0] == 27: + if permitted_payload: + require(_field(n, 'duration_us') is not None and _field(n, 'runtime_duration_us') is not None, 'save payload requires both timing fields') + event_ok = (event_root and _text(_field(n, 'source_service')) == 'save_service' and _text(_field(n, 'event_type')) in SAVE_EVENTS) + for k, v in n[1]: + name = _text(k) + p = path + [_key_segment(k)] + if permitted_payload and name in ('duration_us', 'runtime_duration_us'): + old = copy.deepcopy(v) + v[:] = _marker(name, v) + side['entries'].append({'event_index': event_index, 'path': p, 'key': name, 'original_node': old}) + elif permitted_payload and name == 'message' and v[0] == 4 and root + '/' in v[1]: + require(TOKEN not in v[1], 'ambiguous preexisting root token') + old = copy.deepcopy(v) + v[1] = v[1].replace(root + '/', TOKEN) + side['entries'].append({'event_index': event_index, 'path': p, 'key': name, 'original_node': old, 'root': root}) + else: + if name and (name.endswith('_us') or name.endswith('_ms')): + side['violations'].append({'event_index': event_index, 'path': p, 'kind': 'outside_timing', 'node': copy.deepcopy(v)}) + visit(v, p, event_index, event_ok and name == 'payload') + # Keys are values too; they are never eligible for F1-F3. + if k[0] in (4, 21) and root in k[1]: + side['violations'].append({'event_index': event_index, 'path': p, 'kind': 'profile_in_key', 'node': copy.deepcopy(k)}) + elif n[0] == 28: + for i, child in enumerate(n[1]): + visit(child, path + [['index', i]], event_index) + elif n[0] in (4, 21) and root in n[1]: + side['violations'].append({'event_index': event_index, 'path': path, 'kind': 'outside_profile', 'node': copy.deepcopy(n)}) + for i, t in enumerate(result): + validate_tree(t) + pending = [t] + while pending: + node = pending.pop() + if node[0] in (4, 21, 22): + require(TOKEN not in node[1], 'reserved normalization token in raw/restored tree') + elif node[0] == 27: + for pair in node[1]: + pending.extend(pair) + elif node[0] == 28 or 5 <= node[0] <= 20 or 30 <= node[0] <= 38: + pending.extend(node[1]) + if events: + require(t[0] == 27, 'event dictionary required') + visit(t, [], i, event_root=True) + else: + # Only the product recent_events location is eligible in snapshots. + # Traverse everything for violations, enabling events solely there. + _visit_snapshot(t, root, side, visit) + return result, side + + +def _visit_snapshot(tree, root, side, visit): + permitted = ['systems', 'runtime', 'domain_events', 'recent_events'] + def walk(n, path, names): + if names == permitted: + require(n[0] == 28, 'recent_events array required') + for i, event in enumerate(n[1]): + visit(event, path + [['index', i]], None, event_root=True) + return + if n[0] == 27: + for k, v in n[1]: + name = _text(k) + p = path + [_key_segment(k)] + if name and (name.endswith('_us') or name.endswith('_ms')): + side['violations'].append({'event_index': None, 'path': p, 'kind': 'outside_timing', 'node': copy.deepcopy(v)}) + walk(v, p, names + [name]) + elif n[0] == 28: + for i, child in enumerate(n[1]): + walk(child, path + [['index', i]], names + [i]) + elif n[0] in (4, 21) and root in n[1]: + side['violations'].append({'event_index': None, 'path': path, 'kind': 'outside_profile', 'node': copy.deepcopy(n)}) + walk(tree, [], []) + + +def normalize_events(events, profile_root): + require(type(events) is list, 'event list required') + return _normalize(events, profile_root, True) + + +def normalize_tree(tree, profile_root): + normalized, side = _normalize([tree], profile_root, False) + return normalized[0], side + + +def _restore(normalized, sidecar, profile_root, events): + root = _profile(profile_root) + require(type(sidecar) is dict and set(sidecar) == {'entries', 'violations', 'profile_root'}, 'sidecar fields') + require(sidecar['profile_root'] == {**profile_root, 'matches_guard': True}, 'sidecar profile') + require(type(sidecar['entries']) is list and type(sidecar['violations']) is list, 'sidecar lists') + result = copy.deepcopy(normalized) + seen = set() + for entry in sidecar['entries']: + require(set(entry) == {'event_index', 'path', 'key', 'original_node'} | ({'root'} if entry.get('key') == 'message' else set()), 'entry fields') + index = entry['event_index'] + require((type(index) is int and 0 <= index < len(result)) if events else index is None, 'entry event index') + identity = json_bytes([index, entry['path']]) + require(identity not in seen, 'duplicate sidecar entry') + seen.add(identity) + target = result[index] if events else result + original = validate_tree(entry['original_node']) + if entry['key'] == 'message': + require(entry['root'] == root and original[0] == 4 and root+'/' in original[1] and TOKEN not in original[1], 'message sidecar') + expected = [4, original[1].replace(root+'/', TOKEN)] + else: + require(entry['key'] in ('duration_us', 'runtime_duration_us'), 'outside closed list') + expected = _marker(entry['key'], original) + require(exact(_at(target, entry['path']), expected), 'sidecar does not match normalized node') + _put(target, entry['path'], original) + # Re-running the closed policy rejects missing entries and forged paths, + # including attempts to normalize a violation. Raw tree SHA is also checked + # by the caller against the independently retained transport proof. + normal2, side2 = normalize_events(result, profile_root) if events else normalize_tree(result, profile_root) + require(exact(normal2, normalized) and exact(side2, sidecar), 'non-reversible/unauthorized sidecar') + return result + + +def restore_events(normalized, sidecar, profile_root): + return _restore(normalized, sidecar, profile_root, True) + + +def restore_tree(normalized, sidecar, profile_root): + return _restore(normalized, sidecar, profile_root, False) + + +def check_source_closure(before_map, after_map, allowed_changed): + require(type(before_map) is dict and type(after_map) is dict, 'source maps required') + require(type(allowed_changed) in (list, set, frozenset, tuple), 'registered change set required') + allowed = set(allowed_changed) + errors = [] + for mapping in (before_map, after_map): + for name, row in mapping.items(): + require(type(name) is str and type(row) is dict and set(row) == {'bytes', 'sha256'}, 'source row fields') + require(type(row['bytes']) is int and row['bytes'] >= 0 and type(row['sha256']) is str and re.fullmatch('[0-9a-f]{64}', row['sha256']), 'source row values') + digest = hashlib.sha256(json.dumps(before_map, sort_keys=True, separators=(',', ':')).encode()).hexdigest() + if len(before_map) != 1407 or digest != SOURCE_SHA: + errors.append('before map is not the frozen 1407-source map') + if len(allowed) != len(allowed_changed) or not allowed <= OPT_PATHS: + errors.append('unregistered allowed change set') + added, missing = sorted(after_map.keys()-before_map.keys()), sorted(before_map.keys()-after_map.keys()) + changed = sorted(k for k in before_map.keys() & after_map.keys() if not exact(before_map[k], after_map[k])) + if added or missing or set(changed) != allowed: + errors.append('source closure mismatch') + return {'ok': not errors, 'errors': errors, 'before_sha256': digest, 'added': added, 'missing': missing, 'changed': changed, 'allowed_changed': sorted(allowed)} + + +K_COMPARE = frozenset(('absolute_minute', 'speed', 'paused', 'snapshot_version', + '_accumulator', '_skip_next_process', '_pause_request_serial', + '_abort_current_tick_requested', '_last_tick_advanced', '_phase_handlers')) +C_COMPARE = frozenset(('_mvp_manifest_cache_generation', 'catalog_is_current', '_mvp_manifest_cache_bytes')) + + +def compare_reports(a, b): + """Compare joined reports. Missing evidence fails, never defaults to zero. + + Native admission/source closure is a separate mandatory S4 gate. This + function compares report content, including all scenario outcomes, without + converting an existing product failure into a harness failure or a PASS. + """ + out = {'ok': False, 'differences': [], 'dict_order_paths': [], 'excluded': [], + 'violations': [], 'digest_modes': [], 'errors': []} + + def record(path, x, y): + if not exact(x, y): + out['differences'].append({'path': path, 'a': copy.deepcopy(x), 'b': copy.deepcopy(y)}) + + def excluded(path, reason, x, y): + out['excluded'].append({'path': path, 'reason': reason, 'a': copy.deepcopy(x), 'b': copy.deepcopy(y)}) + + def trees(path, x, y, profiles): + nx, sx = normalize_tree(x, profiles[0]); ny, sy = normalize_tree(y, profiles[1]) + require(tree_sha(restore_tree(nx, sx, profiles[0])) == tree_sha(x), 'a restore SHA') + require(tree_sha(restore_tree(ny, sy, profiles[1])) == tree_sha(y), 'b restore SHA') + sidecars(path, sx, sy) + comparison(path, nx, ny) + return sx, sy + + def comparison(path, x, y): + c = compare_trees(x, y) + for row in c['differences']: + out['differences'].append({**row, 'path': path + row['path']}) + out['dict_order_paths'].extend(path + p for p in c['dict_order_paths']) + + def sidecars(path, x, y): + # Compare semantic paths, not insertion indexes, including event IDs + # in the separately compared event tree. Entry values are never metrics. + identity = lambda e: json_bytes([e['event_index'], e['path'], e['key']]) + mx, my = {identity(e): e for e in x['entries']}, {identity(e): e for e in y['entries']} + record(path + ['normalized_paths'], sorted(k.decode() for k in mx), sorted(k.decode() for k in my)) + for key in sorted(mx.keys() | my.keys()): + ex, ey = mx.get(key), my.get(key) + name = (ex or ey)['key'] + excluded(path + ['sidecar', key.decode()], 'private profile root' if name == 'message' else 'wall-clock timing', ex, ey) + out['violations'].append({'path': path, 'a': x['violations'], 'b': y['violations']}) + + def layers(path, x, y): + for n in (x['K'], y['K']): + require(set(n) == K_COMPARE | {'performance_budget'}, 'K fields missing/unknown') + require(set(n['performance_budget']) == {'_samples', '_totals', '_sample_counts'}, 'budget fields') + require(type(n['_accumulator']) is str and re.fullmatch('[0-9a-f]{16}', n['_accumulator']), 'accumulator f64') + counts = n['performance_budget']['_sample_counts'] + require(type(counts) is dict and all(type(v) is int and v >= 0 for v in counts.values()), 'metric sample counts') + for field in sorted(K_COMPARE): + vx, vy = x['K'][field], y['K'][field] + if field == '_phase_handlers': + require(type(vx) is dict and type(vy) is dict, 'phase handlers') + def handlers(value): + for ids in value.values(): + require(type(ids) is list and all(type(i) is str for i in ids) and len(set(ids)) == len(ids), 'handler IDs') + return {p: sorted(ids) for p, ids in value.items()} + vx, vy = handlers(vx), handlers(vy) + # JSON object order is not semantic; typed state retains its order. + if field == '_phase_handlers': + vx, vy = sorted(vx.items()), sorted(vy.items()) + record(path + ['K', field], vx, vy) + bx, by = x['K']['performance_budget'], y['K']['performance_budget'] + record(path + ['K', 'performance_budget', '_sample_counts'], sorted(bx['_sample_counts'].items()), sorted(by['_sample_counts'].items())) + for field in ('_samples', '_totals'): + excluded(path + ['K', 'performance_budget', field], 'wall-clock telemetry', bx[field], by[field]) + for n in (x['C'], y['C']): + require(set(n) == C_COMPARE | {'catalog_instance_id', 'current_catalog_instance_id'}, 'C fields missing/unknown') + require(type(n['catalog_is_current']) is bool, 'catalog identity flag') + for field in sorted(C_COMPARE): + record(path + ['C', field], x['C'][field], y['C'][field]) + for field in ('catalog_instance_id', 'current_catalog_instance_id'): + excluded(path + ['C', field], 'process-local instance ID', x['C'][field], y['C'][field]) + + def scenario_facts(path, x, y): + # Joined S3b facts carry lossless typed trees as well as JSON metadata. + # Apply the same dictionary-order-only fallback to returned values. + if isinstance(x, list) and isinstance(y, list) and x and y and type(x[0]) is int and type(y[0]) is int: + validate_tree(x); validate_tree(y) + comparison(path, x, y) + elif isinstance(x, dict) and isinstance(y, dict): + record(path + ['keys'], sorted(x), sorted(y)) + for key in sorted(set(x) & set(y)): + scenario_facts(path + [key], x[key], y[key]) + elif isinstance(x, list) and isinstance(y, list): + record(path + ['count'], len(x), len(y)) + for i, (left, right) in enumerate(zip(x, y)): + scenario_facts(path + [i], left, right) + else: + record(path, x, y) + + def checkpoints(path, xs, ys, profiles, main=False, ownership=False): + if main: + require(len(xs) == len(ys) == 31, 'B1 plus 30 ticks required') + record(path + ['count'], len(xs), len(ys)) + tx, ty = reconstruct_checkpoints(xs), reconstruct_checkpoints(ys) + for i, (x, y) in enumerate(zip(xs, ys)): + p = path + [i] + expected = {'minute', 'S', 'latest', 'latest_digest', 'computed_latest_digest', 'harness_normalized_digest', 'K', 'C', 'observation'} + require(set(x) == expected and set(y) == expected, 'checkpoint fields') + for cp in (x, y): + require(type(cp['latest_digest']) is str and type(cp['computed_latest_digest']) is str, 'product digest type') + # Only the immediately observed, intentional external E5 mutation + # may expose cached-digest aliasing. Preserve it as a product fact. + if not (ownership and i == 2): + require(cp['latest_digest'] == cp['computed_latest_digest'], 'product digest self-consistency') + obs = cp['observation'] + require(set(obs) == {'before', 'after'} and set(obs['before']) == set(obs['after']) == {'S', 'K', 'C'}, 'complete observation proof') + require(all(type(v) is str and re.fullmatch('[0-9a-f]{64}', v) for v in list(obs['before'].values())+list(obs['after'].values())), 'observation bytes SHA') + require(exact(obs['before'], obs['after']), 'observation mutated S/K/C') + record(p + ['minute'], x['minute'], y['minute']) + if main: + require(x['minute'] == xs[0]['minute']+i and y['minute'] == ys[0]['minute']+i, 'checkpoint cadence') + trees(p + ['S'], tx[i][0], ty[i][0], profiles) + sx, sy = trees(p + ['latest'], tx[i][1], ty[i][1], profiles) + if ownership and i == 2: + record(p + ['digest_self_consistent'], x['latest_digest'] == x['computed_latest_digest'], y['latest_digest'] == y['computed_latest_digest']) + if sx['entries'] or sy['entries']: + excluded(p + ['computed_latest_digest'], 'E5 latest contains F1-F3; full normalized latest is compared', x['computed_latest_digest'], y['computed_latest_digest']) + else: + record(p + ['computed_latest_digest'], x['computed_latest_digest'], y['computed_latest_digest']) + if sx['entries'] or sy['entries']: + require(type(x['harness_normalized_digest']) is str and type(y['harness_normalized_digest']) is str, 'missing harness normalized digest') + record(p + ['harness_normalized_digest'], x['harness_normalized_digest'], y['harness_normalized_digest']) + excluded(p + ['latest_digest'], 'latest snapshot contains F1-F3 environment values', x['latest_digest'], y['latest_digest']) + out['digest_modes'].append({'path': p, 'mode': 'harness normalized digest'}) + else: + record(p + ['latest_digest'], x['latest_digest'], y['latest_digest']) + out['digest_modes'].append({'path': p, 'mode': 'product latest_digest'}) + layers(p, x, y) + + try: + fields = {'schema', 'role', 'profile_root', 'checkpoints', 'events', 'event_start', 'event_end', 'signal_order', 'scenarios'} + require(type(a) is dict and type(b) is dict and set(a) == fields and set(b) == fields, 'report fields missing/unknown') + require(a['schema'] == b['schema'] == 'p28-02-eq/typed-v1', 'report schema') + require(a['role'] in ('R', 'O') and b['role'] in ('R', 'O'), 'report role') + record(['role'], a['role'], b['role']) + profiles = (a['profile_root'], b['profile_root']) + for profile in profiles: + _profile(profile) + for r in (a, b): + require(set(r['event_start']) == {'counter', 'published_ids_count'}, 'event start fields') + require(all(type(n) is int and n >= 0 for n in r['event_start'].values()), 'event counters') + require(exact(a['event_start'], b['event_start']), 'event start counter/published_ids mismatch: correspondence invalid') + record(['event_end'], a['event_end'], b['event_end']) + record(['signal_order'], a['signal_order'], b['signal_order']) + checkpoints(['checkpoints'], a['checkpoints'], b['checkpoints'], profiles, main=True) + event_trees = [] + for r in (a, b): + ts = [] + for i, e in enumerate(r['events']): + require(set(e) == {'sequence', 'transport', 'original_field_types'} and e['sequence'] == i, 'event sequence/fields') + ts.append(_transport(e['transport'], None)) + event_trees.append(ts) + na, sa = normalize_events(event_trees[0], profiles[0]); nb, sb = normalize_events(event_trees[1], profiles[1]) + require(exact(restore_events(na, sa, profiles[0]), event_trees[0]) and exact(restore_events(nb, sb, profiles[1]), event_trees[1]), 'event restore proof') + sidecars(['events'], sa, sb) + record(['events', 'count'], len(na), len(nb)) + for i, (x, y) in enumerate(zip(na, nb)): + comparison(['events', i], x, y) + record(['events', i, 'original_field_types'], a['events'][i]['original_field_types'], b['events'][i]['original_field_types']) + record(['scenarios', 'count'], len(a['scenarios']), len(b['scenarios'])) + for i, (x, y) in enumerate(zip(a['scenarios'], b['scenarios'])): + require(set(x) == set(y) == {'id', 'operation', 'result', 'checkpoints', 'events'}, 'scenario fields') + for key in ('id', 'operation', 'result', 'events'): + # result preserves failures/path/value/ownership outcomes. + # Scenario events use the same typed normalization below. + if key != 'events': + if key == 'result' and x['id'].startswith(('E4/', 'E5/')) and y['id'].startswith(('E4/', 'E5/')): + scenario_facts(['scenarios', i, key], x[key], y[key]) + else: + record(['scenarios', i, key], x[key], y[key]) + ownership_ids = {'E5/'+t+'/'+loc+'/outside_in' for t in ('create_snapshot', 'latest_snapshot', 'snapshot_published', 'state_updated') for loc in ('dict', 'array')} + ownership = x['id'] == y['id'] and x['id'] in ownership_ids and x['operation'] == y['operation'] == 'outside_in' and len(x['checkpoints']) == len(y['checkpoints']) == 4 + checkpoints(['scenarios', i, 'checkpoints'], x['checkpoints'], y['checkpoints'], profiles, ownership=ownership) + ex, sx = normalize_events(x['events'], profiles[0]); ey, sy = normalize_events(y['events'], profiles[1]) + sidecars(['scenarios', i, 'events'], sx, sy) + record(['scenarios', i, 'events', 'count'], len(ex), len(ey)) + for j, (vx, vy) in enumerate(zip(ex, ey)): + comparison(['scenarios', i, 'events', j], vx, vy) + out['ok'] = not out['differences'] + except (EvidenceError, KeyError, TypeError, IndexError, ValueError) as exc: + out['errors'].append(str(exc)) + return out + + +def classify_improvement(before, after): + """SPEC §4: three actual run/PID values, no substituted markers.""" + import math + require(len(before) == len(after) == 3, 'three values per version required') + require(all(type(v) in (int, float) and math.isfinite(v) and v >= 0 for v in before+after), 'invalid measurement') + return '改善' if max(after) < min(before) else '悪化' if min(after) > max(before) else '差は確認できない' + + +def validate_scenario_paths(paths): + """D1: exact fixed relative names; no UUID/PID/time-generated paths.""" + allowed = {'user://p28_eq/'+role+'/'+name for role in ('r', 'o') + for name in ('good', 'tampered_world', 'missing_key', 'wrong_type', 'out_of_range', 'duplicate_id')} + require(type(paths) is list and all(type(p) is str and p in allowed for p in paths), 'non-fixed scenario path') + return True diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/eq_probe.gd b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/eq_probe.gd new file mode 100644 index 0000000..0fac954 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/eq_probe.gd @@ -0,0 +1,808 @@ +extends SceneTree +## S3b external guarded probe. Native admission remains S4/Root. +const FIXTURE_SHA: String = "eb4f770071eb07cd7e136fe54c3f78768cc8de7a4264e62a9af1f06a8f90f9bd" +const K_FIELDS: Array = ["absolute_minute", "speed", "paused", "snapshot_version", "_skip_next_process", "_pause_request_serial", "_abort_current_tick_requested", "_last_tick_advanced"] +var clock: Variant +var runtime: Variant +var main: Variant +var role: String +var report: Dictionary = {} +var lifecycle: Dictionary = {"stage": "S3b", "errors": [], "preparation": [], "files": []} +var previous_tree: Array = [] +var finished: bool = false +var bound: bool = false +var recording: bool = false +var connected: bool = false +var initial_inventory: Dictionary = {} +var warm_signals: Array = [] +var scenario_active: bool = false +var scenario_events: Array = [] +var scenario_signals: Array = [] +var b1_snapshot: Dictionary = {} +var snapshot_reference: Dictionary = {} +var state_reference: Dictionary = {} + +func _initialize() -> void: + call_deferred("begin") + +func demand(ok: bool, message: String) -> bool: + if not ok: lifecycle.errors.append(message) + return ok + +func hashed(bytes: PackedByteArray) -> String: + var context: HashingContext = HashingContext.new() + context.start(HashingContext.HASH_SHA256) + context.update(bytes) + return context.finish().hex_encode() + +func json_text(value: Variant) -> String: + return JSON.stringify(value, "", false, true) + +func f64(value: float) -> String: + var bytes: PackedByteArray = PackedByteArray() + bytes.resize(8) + bytes.encode_double(0, value) + return bytes.hex_encode() + +func typed_info(value: Variant) -> Variant: + if typeof(value) == TYPE_ARRAY and value.is_typed(): + return [encode(value.get_typed_builtin()), encode(value.get_typed_class_name()), encode(value.get_typed_script())] + if typeof(value) == TYPE_DICTIONARY and value.is_typed(): + return [[encode(value.get_typed_key_builtin()), encode(value.get_typed_key_class_name()), encode(value.get_typed_key_script())], [encode(value.get_typed_value_builtin()), encode(value.get_typed_value_class_name()), encode(value.get_typed_value_script())]] + return null + +func encode(value: Variant) -> Array: + var t: int = typeof(value) + match t: + TYPE_NIL: return [0] + TYPE_BOOL: return [1, 1 if value else 0] + TYPE_INT: return [2, value] + TYPE_FLOAT: return [3, f64(value)] + TYPE_STRING, TYPE_STRING_NAME, TYPE_NODE_PATH: return [t, str(value)] + TYPE_RID, TYPE_OBJECT, TYPE_CALLABLE, TYPE_SIGNAL: + demand(false, "unsupported Variant in transport: " + str(t)) + return [] + TYPE_DICTIONARY: + var pairs: Array = [] + for key: Variant in value: pairs.append([encode(key), encode(value[key])]) + return [27, pairs, typed_info(value)] + TYPE_ARRAY: + var children: Array = [] + for child: Variant in value: children.append(encode(child)) + return [28, children, typed_info(value)] + TYPE_PACKED_BYTE_ARRAY: return [29, Marshalls.raw_to_base64(value)] + var parts: Array = [] + match t: + TYPE_VECTOR2, TYPE_VECTOR2I: parts = [value.x, value.y] + TYPE_RECT2, TYPE_RECT2I: parts = [value.position.x, value.position.y, value.size.x, value.size.y] + TYPE_VECTOR3, TYPE_VECTOR3I: parts = [value.x, value.y, value.z] + TYPE_TRANSFORM2D: parts = [value.x.x, value.x.y, value.y.x, value.y.y, value.origin.x, value.origin.y] + TYPE_VECTOR4, TYPE_VECTOR4I: parts = [value.x, value.y, value.z, value.w] + TYPE_PLANE: parts = [value.normal.x, value.normal.y, value.normal.z, value.d] + TYPE_QUATERNION: parts = [value.x, value.y, value.z, value.w] + TYPE_AABB: parts = [value.position.x, value.position.y, value.position.z, value.size.x, value.size.y, value.size.z] + TYPE_BASIS: parts = basis_parts(value) + TYPE_TRANSFORM3D: parts = basis_parts(value.basis) + [value.origin.x, value.origin.y, value.origin.z] + TYPE_PROJECTION: + for column: int in range(4): + for row: int in range(4): parts.append(value[column][row]) + TYPE_COLOR: parts = [value.r, value.g, value.b, value.a] + _: + if t >= TYPE_PACKED_INT32_ARRAY and t <= TYPE_PACKED_VECTOR4_ARRAY: + for child: Variant in value: parts.append(child) + else: demand(false, "unknown Variant type: " + str(t)) + var nodes: Array = [] + for part: Variant in parts: nodes.append(encode(part)) + return [t, nodes] + +func basis_parts(value: Basis) -> Array: + return [value.x.x, value.x.y, value.x.z, value.y.x, value.y.y, value.y.z, value.z.x, value.z.y, value.z.z] + +func decode(node: Array) -> Variant: + if node.is_empty(): + demand(false, "empty typed node") + return null + var t: int = node[0] + if t == TYPE_NIL: return null + var p: Variant = node[1] + match t: + TYPE_BOOL: return p == 1 + TYPE_INT: return int(p) + TYPE_FLOAT: return String(p).hex_decode().decode_double(0) + TYPE_STRING: return String(p) + TYPE_STRING_NAME: return StringName(p) + TYPE_NODE_PATH: return NodePath(p) + TYPE_PACKED_BYTE_ARRAY: return Marshalls.base64_to_raw(p) + TYPE_DICTIONARY: + var result: Dictionary = {} + if node[2] != null: + var ki: Array = node[2][0] + var vi: Array = node[2][1] + result = Dictionary({}, decode(ki[0]), decode(ki[1]), decode(ki[2]), decode(vi[0]), decode(vi[1]), decode(vi[2])) + for pair: Array in p: result[decode(pair[0])] = decode(pair[1]) + return result + var values: Array = [] + for child: Array in p: values.append(decode(child)) + if t == TYPE_ARRAY: + if node[2] != null: + var info: Array = node[2] + return Array(values, decode(info[0]), decode(info[1]), decode(info[2])) + return values + match t: + TYPE_VECTOR2: return Vector2(values[0], values[1]) + TYPE_VECTOR2I: return Vector2i(values[0], values[1]) + TYPE_RECT2: return Rect2(values[0], values[1], values[2], values[3]) + TYPE_RECT2I: return Rect2i(values[0], values[1], values[2], values[3]) + TYPE_VECTOR3: return Vector3(values[0], values[1], values[2]) + TYPE_VECTOR3I: return Vector3i(values[0], values[1], values[2]) + TYPE_TRANSFORM2D: return Transform2D(Vector2(values[0], values[1]), Vector2(values[2], values[3]), Vector2(values[4], values[5])) + TYPE_VECTOR4: return Vector4(values[0], values[1], values[2], values[3]) + TYPE_VECTOR4I: return Vector4i(values[0], values[1], values[2], values[3]) + TYPE_PLANE: return Plane(Vector3(values[0], values[1], values[2]), values[3]) + TYPE_QUATERNION: return Quaternion(values[0], values[1], values[2], values[3]) + TYPE_AABB: return AABB(Vector3(values[0], values[1], values[2]), Vector3(values[3], values[4], values[5])) + TYPE_BASIS: return decoded_basis(values) + TYPE_TRANSFORM3D: return Transform3D(decoded_basis(values), Vector3(values[9], values[10], values[11])) + TYPE_PROJECTION: return Projection(Vector4(values[0], values[1], values[2], values[3]), Vector4(values[4], values[5], values[6], values[7]), Vector4(values[8], values[9], values[10], values[11]), Vector4(values[12], values[13], values[14], values[15])) + TYPE_COLOR: return Color(values[0], values[1], values[2], values[3]) + TYPE_PACKED_INT32_ARRAY: return PackedInt32Array(values) + TYPE_PACKED_INT64_ARRAY: return PackedInt64Array(values) + TYPE_PACKED_FLOAT32_ARRAY: return PackedFloat32Array(values) + TYPE_PACKED_FLOAT64_ARRAY: return PackedFloat64Array(values) + TYPE_PACKED_STRING_ARRAY: return PackedStringArray(values) + TYPE_PACKED_VECTOR2_ARRAY: return PackedVector2Array(values) + TYPE_PACKED_VECTOR3_ARRAY: return PackedVector3Array(values) + TYPE_PACKED_COLOR_ARRAY: return PackedColorArray(values) + TYPE_PACKED_VECTOR4_ARRAY: return PackedVector4Array(values) + demand(false, "unsupported decode type: " + str(t)) + return null + +func decoded_basis(v: Array) -> Basis: + return Basis(Vector3(v[0], v[1], v[2]), Vector3(v[3], v[4], v[5]), Vector3(v[6], v[7], v[8])) + +func transport(value: Variant) -> Dictionary: + var tree: Array = encode(value) + var raw: PackedByteArray = var_to_bytes(value) + var rebuilt: PackedByteArray = var_to_bytes(decode(tree)) + var ok: bool = raw == rebuilt + demand(ok, "Godot typed tree byte roundtrip failed") + return {"tree": tree, "tree_sha": hashed(json_text(tree).to_utf8_buffer()), "raw_bytes_sha": hashed(raw), "roundtrip_ok": ok} + +func tree_diff(before: Array, after: Array, path: Array = []) -> Array: + if json_text(before) == json_text(after): return [] + # Exact subtree replacement also preserves changes of insertion order and metadata. + if before[0] != after[0] or before[0] not in [TYPE_DICTIONARY, TYPE_ARRAY] or json_text(before[2]) != json_text(after[2]): + return [{"op": "set", "path": path, "node": after}] + var changes: Array = [] + if before[0] == TYPE_DICTIONARY: + var old_keys: Array = [] + var new_keys: Array = [] + for pair: Array in before[1]: old_keys.append(pair[0]) + for pair: Array in after[1]: new_keys.append(pair[0]) + if json_text(old_keys) != json_text(new_keys): return [{"op": "set", "path": path, "node": after}] + for i: int in range(before[1].size()): + changes.append_array(tree_diff(before[1][i][1], after[1][i][1], path + [["key", after[1][i][0]]])) + else: + if before[1].size() != after[1].size(): + return [{"op": "array_splice", "path": path, "start": 0, "delete_count": before[1].size(), "nodes": after[1]}] + for i: int in range(before[1].size()): changes.append_array(tree_diff(before[1][i], after[1][i], path + [["index", i]])) + return changes + +func tree_at(tree: Array, path: Array) -> Array: + var node: Array = tree + for segment: Array in path: + if segment[0] == "index": node = node[1][segment[1]] + else: + var found: bool = false + for pair: Array in node[1]: + if json_text(pair[0]) == json_text(segment[1]): + node = pair[1] + found = true + break + demand(found, "diff path missing") + return node + +func diff_record(record: Dictionary, baseline: Array) -> Dictionary: + var operations: Array = tree_diff(baseline, record.tree) + var replay: Array = baseline.duplicate(true) + for op: Dictionary in operations: + var target: Array = tree_at(replay, op.path) + if op.op == "set": + target.clear() + target.append_array(op.node.duplicate(true)) + elif op.op == "array_splice": + for unused: int in range(op.delete_count): target[1].remove_at(op.start) + for i: int in range(op.nodes.size()): target[1].insert(op.start + i, op.nodes[i].duplicate(true)) + demand(json_text(replay) == json_text(record.tree), "diff roundtrip mismatch") + return {"diff": operations, "tree_sha": record.tree_sha, "raw_bytes_sha": record.raw_bytes_sha, "roundtrip_ok": record.roundtrip_ok} + +func kernel_state() -> Dictionary: + var result: Dictionary = {} + for key: String in K_FIELDS: result[key] = clock.get(key) + result["_accumulator"] = f64(clock.get("_accumulator")) + var ids: Dictionary = {} + var handlers: Dictionary = clock.get("_phase_handlers") + for phase: Variant in handlers: + var names: Array = [] + for key: Variant in handlers[phase]: names.append(str(key)) + names.sort_custom(func(a: Variant, b: Variant) -> bool: return str(a) < str(b)) + ids[str(phase)] = names + result["_phase_handlers"] = ids + var budget: Variant = clock.get("performance_budget") + var metrics: Dictionary = {} + for key: String in ["_samples", "_totals", "_sample_counts"]: metrics[key] = budget.get(key).duplicate(true) + result["performance_budget"] = metrics + return result + +func cache_state() -> Dictionary: + var catalog: Variant = runtime.get("_mvp_manifest_cache_catalog") + var current: Variant = runtime.get("mvp_content_catalog") + return {"_mvp_manifest_cache_generation": runtime.get("_mvp_manifest_cache_generation"), "catalog_is_current": catalog == current, + "_mvp_manifest_cache_bytes": Marshalls.raw_to_base64(var_to_bytes(runtime.get("_mvp_manifest_cache"))), + "catalog_instance_id": str(catalog.get_instance_id()) if catalog != null else null, "current_catalog_instance_id": str(current.get_instance_id())} + +func cache_filled() -> bool: + var current: Variant = runtime.get("mvp_content_catalog") + return runtime.get("_mvp_manifest_cache_catalog") == current and runtime.get("_mvp_manifest_cache_generation") == current.get_manifest_generation() + +func prepare_cache(label: String) -> void: + var before: Dictionary = cache_state() + var filled: bool = cache_filled() + if not filled: runtime.create_snapshot() + lifecycle.preparation.append({"operation": "cache", "label": label, "before": before, "after": cache_state(), "filled_outside_observation": not filled}) + demand(cache_filled(), "cache preparation failed") + +func layers() -> Dictionary: + var k: Dictionary = kernel_state() + var c: Dictionary = cache_state() + var s: Dictionary = runtime.create_snapshot() + var kb: PackedByteArray = var_to_bytes(k) + var cb: PackedByteArray = var_to_bytes(c) + demand(kb == var_to_bytes(kernel_state()), "state witness changed full K") + demand(cb == var_to_bytes(cache_state()), "state witness changed full C") + return {"snapshot": s, "K": k, "C": c, "s_bytes": var_to_bytes(s), "k_bytes": kb, "c_bytes": cb} + +func witness(value: Dictionary) -> Dictionary: + return {"S": hashed(value.s_bytes), "K": hashed(value.k_bytes), "C": hashed(value.c_bytes)} + +func raw_layers(value: Dictionary) -> Dictionary: + return {"sha": witness(value), "S": Marshalls.raw_to_base64(value.s_bytes), "K": Marshalls.raw_to_base64(value.k_bytes), "C": Marshalls.raw_to_base64(value.c_bytes), "kernel": value.K, "cache": value.C} + +func checkpoint() -> void: + var before: Dictionary = layers() + var s: Dictionary = transport(runtime.create_snapshot()) + var latest_value: Dictionary = runtime.get("latest_snapshot") + var latest: Dictionary = transport(latest_value) + var latest_bytes: PackedByteArray = var_to_bytes(latest_value) + var digest: String = runtime.get("latest_digest") + var computed: String = SimulationDigest.compute(latest_value) + var current_tree: Array = s.tree + if not previous_tree.is_empty(): s = diff_record(s, previous_tree) + if latest_bytes == before.s_bytes: + latest = {"same_as_S": true, "tree_sha": latest.tree_sha, "raw_bytes_sha": latest.raw_bytes_sha, "roundtrip_ok": latest.roundtrip_ok} + else: latest = diff_record(latest, current_tree) + var after: Dictionary = layers() + demand(before.s_bytes == after.s_bytes and before.k_bytes == after.k_bytes and before.c_bytes == after.c_bytes, "observation changed full S/K/C") + demand(digest == computed, "latest digest self-consistency") + var cp: Dictionary = {"minute": clock.absolute_minute, "S": s, "latest": latest, "latest_digest": digest, "computed_latest_digest": computed, + "harness_normalized_digest": null, "K": before.K, "C": before.C, "observation": {"before": witness(before), "after": witness(after)}} + # Python joins F1-F3 and the labelled normalized tree digest, retaining this raw record. + var index: int = report.checkpoints.size() + write_evidence("checkpoint-%02d.json" % index, cp) + write_evidence("observation-%02d.json" % index, {"before": raw_layers(before), "after": raw_layers(after)}) + report.checkpoints.append(cp) + previous_tree = current_tree + +func event_counts() -> Dictionary: + return {"counter": runtime.id_generator.get_counter(&"domain_event"), "published_ids_count": runtime.domain_events.get("_published_ids").size()} + +func observe_event(event: Variant) -> void: + if scenario_active: + scenario_events.append(transport(event.to_dictionary())) + return + if not recording: return + var value: Dictionary = event.to_dictionary() + report.events.append({"sequence": report.events.size(), "transport": transport(value), "original_field_types": { + "event_id": typeof(event.event_id), "event_type": typeof(event.event_type), "absolute_minute": typeof(event.absolute_minute), "source_service": typeof(event.source_service), + "entity_ids": {"type": typeof(event.entity_ids), "typed_info": typed_info(event.entity_ids)}, + "payload": {"type": typeof(event.payload), "typed_info": typed_info(event.payload)}, "causation_command_id": typeof(event.causation_command_id)}}) + +func observe_snapshot(_snapshot: Dictionary, _digest: String) -> void: + snapshot_reference = _snapshot + record_signal("snapshot_published") + +func observe_state(_snapshot: Dictionary) -> void: + state_reference = _snapshot + record_signal("state_updated") + +func record_signal(name: String) -> void: + var row: Dictionary = {"signal": name, "minute": clock.absolute_minute} + if scenario_active: scenario_signals.append(row) + elif recording: report.signal_order.append(row) + else: warm_signals.append(row) + +func inventory() -> Dictionary: + var result: Dictionary = {} + for sig: Signal in [runtime.snapshot_published, runtime.state_updated]: + var rows: Array = [] + for connection: Dictionary in sig.get_connections(): + var callback: Callable = connection.callable + rows.append({"object": str(callback.get_object_id()), "method": str(callback.get_method()), "flags": connection.flags}) + rows.sort_custom(func(a: Dictionary, b: Dictionary) -> bool: return json_text(a) < json_text(b)) + result[str(sig.get_name())] = rows + var subscribers: Array = [] + var all_subscribers: Dictionary = runtime.domain_events.get("_subscribers") + for event_type: Variant in all_subscribers: + for id: Variant in all_subscribers[event_type]: + var callback: Callable = all_subscribers[event_type][id] + subscribers.append({"event_type": str(event_type), "id": str(id), "object": str(callback.get_object_id()), "method": str(callback.get_method())}) + subscribers.sort_custom(func(a: Dictionary, b: Dictionary) -> bool: return json_text(a) < json_text(b)) + result["subscribers"] = subscribers + return result + +func step() -> void: + var before: int = clock.absolute_minute + demand(clock.paused, "clock resumed") + clock.advance_minutes(1) + demand(clock.absolute_minute == before + 1 and clock.paused, "manual step failed") + await process_frame + demand(clock.absolute_minute == before + 1 and clock.paused, "inter-tick frame advanced clock") + +func bind_profile() -> bool: + var path: String = OS.get_environment("THE_TREE_PACK_PROFILE_REPORT") + var file: FileAccess = FileAccess.open(path, FileAccess.READ) + if not demand(file != null, "guard receipt missing"): return false + var receipt: Variant = JSON.parse_string(file.get_as_text()) + file.close() + if not demand(receipt is Dictionary and receipt.get("verified") == true, "guard receipt unverified"): return false + var actual: Variant = receipt.get("actual_user_data_dir") + var live_root: String = ProjectSettings.globalize_path("user://").simplify_path() + if not demand(actual is String and actual == live_root and OS.get_user_data_dir() == actual, "live profile differs from guard actual_user_data_dir"): return false + report["profile_root"] = {"root": live_root, "actual_user_data_dir": actual} + lifecycle["guard"] = {"path": path, "sha256": FileAccess.get_sha256(path), "receipt": receipt, "live_root": live_root} + bound = true + return true + +func write_evidence(name: String, value: Variant) -> void: + if not demand(bound, "evidence write before guard binding"): return + var directory: String = "user://evidence" + var mkdir: int = DirAccess.make_dir_recursive_absolute(directory) + if not demand(mkdir == OK, "evidence mkdir failed"): return + var path: String = directory.path_join(name) + if not demand(not FileAccess.file_exists(path), "refuse evidence overwrite: " + name): return + var file: FileAccess = FileAccess.open(path, FileAccess.WRITE) + if not demand(file != null, "evidence open failed: " + name): return + var bytes: PackedByteArray = json_text(value).to_utf8_buffer() + file.store_buffer(bytes) + file.flush() + var error: int = file.get_error() + file.close() + demand(error == OK, "evidence write failed: " + name) + lifecycle.files.append({"path": "evidence/" + name, "bytes": bytes.size(), "sha256": hashed(bytes)}) + +func begin() -> void: + clock = root.get_node("GameClock") + runtime = root.get_node("SimulationRuntime") + role = OS.get_environment("THE_TREE_EQ_ROLE") + report = {"schema": "p28-02-eq/typed-v1", "role": role, "profile_root": null, "checkpoints": [], "events": [], "event_start": null, "event_end": null, "signal_order": [], "scenarios": []} + if not demand(role in ["R", "O"], "unknown EQ role") or not bind_profile(): + finish() + return + # Stage 1: public preparation only. O retains the fresh 360-minute state. + var k0: Dictionary = kernel_state() + clock.set_paused(true) + lifecycle.preparation.append({"operation": "initial_pause", "before": k0, "after": kernel_state()}) + if role == "R": + var path: String = OS.get_environment("THE_TREE_P28_FIXTURE") + if not demand(FileAccess.get_sha256(path) == FIXTURE_SHA, "fixture SHA mismatch"): + finish() + return + var file: FileAccess = FileAccess.open(path, FileAccess.READ) + if not demand(file != null, "fixture open failed"): + finish() + return + var fixture: Variant = file.get_var(false) + file.close() + if not demand(fixture is Dictionary, "fixture is not Dictionary"): + finish() + return + var restored: bool = runtime.restore_snapshot(fixture) + lifecycle.preparation.append({"operation": "fixture_restore", "ok": restored, "input_sha256": FIXTURE_SHA, "K": kernel_state(), "C": cache_state()}) + demand(restored, "fixture restore failed") + prepare_cache("restored") + lifecycle["restored"] = raw_layers(layers()) + k0 = kernel_state() + clock.set_paused(true) + lifecycle.preparation.append({"operation": "restored_pause", "before": k0, "after": kernel_state()}) + prepare_cache("before_main") + # Stage 2: same main and two deferred frames as DIAG, without controls/hooks. + lifecycle["before_main"] = raw_layers(layers()) + main = load("res://scenes/main/main.tscn").instantiate() + root.add_child(main) + lifecycle["after_main"] = raw_layers(layers()) + await process_frame + lifecycle["frame1"] = raw_layers(layers()) + await process_frame + lifecycle["frame2"] = raw_layers(layers()) + var ops: Dictionary = main.get("_operations_start_report").duplicate(true) + lifecycle["ops"] = ops + lifecycle["save_policy"] = runtime.get_save_policy() + demand(ops.get("code") == "INVALID_START_TIME" if role == "R" else ops.get("ok") == true, "unexpected main Ops result") + demand(clock.paused and clock.absolute_minute == (602 if role == "R" else 360), "B0 clock") + lifecycle["B0"] = raw_layers(layers()) + initial_inventory = inventory() + runtime.snapshot_published.connect(observe_snapshot) + runtime.state_updated.connect(observe_state) + demand(runtime.domain_events.subscribe(&"*", &"p28_eq_observer", observe_event), "wildcard subscription failed") + connected = true + lifecycle["observer_before"] = initial_inventory + lifecycle["observer_connected"] = inventory() + # Stage 3: warm, excluded from E2; warm signal order is retained separately. + for unused: int in range(30): + if not lifecycle.errors.is_empty(): break + await step() + prepare_cache("B1") + lifecycle["B1"] = raw_layers(layers()) + demand(clock.absolute_minute == (632 if role == "R" else 390), "B1 clock") + lifecycle["measurement"] = {"probe_object": str(get_instance_id()), "connections": inventory(), "start_minute": clock.absolute_minute} + report.event_start = event_counts() + recording = true + checkpoint() + b1_snapshot = decode(report.checkpoints[0].S.tree).duplicate(true) + # Stage 4: B1 and 30 exact checkpoints, uncapped events through the last frame. + for unused: int in range(30): + if not lifecycle.errors.is_empty(): break + await step() + checkpoint() + report.event_end = event_counts() + recording = false + # Stage 5: E3 dedicated intervals, after measured event/signal closure. + lifecycle["outside"] = raw_layers(layers()) + run_e3() + run_e4() + run_e5() + finish() + +func finish() -> void: + if finished: return + finished = true + # Stage 6: restore observers, preserve every error. + if connected: + runtime.snapshot_published.disconnect(observe_snapshot) + runtime.state_updated.disconnect(observe_state) + runtime.domain_events.unsubscribe(&"*", &"p28_eq_observer") + lifecycle["observer_disconnected"] = inventory() + demand(json_text(initial_inventory) == json_text(lifecycle.observer_disconnected), "observer inventory not restored") + lifecycle["warm_signals"] = warm_signals + lifecycle["stop_reason"] = "S3b_complete_S4_pending" if lifecycle.errors.is_empty() else "failed" + if bound: + write_evidence("events.json", report.events) + write_evidence("report.json", report) + write_evidence("lifecycle.json", lifecycle.duplicate(true)) + print("P28_02_EQ_REPORT=" + json_text(report)) + if is_instance_valid(main): main.ui_audio_window_close_drained.connect(audio_close, CONNECT_ONE_SHOT) + root.close_requested.emit() + +func audio_close(result: Dictionary) -> void: + write_evidence("audio-close.json", result) + +func e3_observation() -> Dictionary: + var before: Dictionary = layers() + var s: Dictionary = transport(runtime.create_snapshot()) + var latest_value: Dictionary = runtime.get("latest_snapshot") + var latest: Dictionary = transport(latest_value) + var digest: String = runtime.get("latest_digest") + var computed: String = SimulationDigest.compute(latest_value) + var after: Dictionary = layers() + demand(before.s_bytes == after.s_bytes and before.k_bytes == after.k_bytes and before.c_bytes == after.c_bytes, "E3 observation changed full S/K/C") + var cp: Dictionary = {"minute": clock.absolute_minute, "S": s, "latest": latest, "latest_digest": digest, "computed_latest_digest": computed, + "harness_normalized_digest": null, "K": before.K, "C": before.C, "observation": {"before": witness(before), "after": witness(after)}} + return {"checkpoint": cp, "raw": {"before": raw_layers(before), "after": raw_layers(after)}, + "K_tree": transport(before.K), "C_tree": transport(before.C)} + +func e3_input(kind: String) -> Dictionary: + var value: Dictionary = b1_snapshot.duplicate(true) + match kind: + "missing_key": value.erase(&"clock") + "wrong_type": value[&"clock"][&"absolute_minute"] = "x" + "out_of_range": value[&"clock"][&"speed"] = 9 + "duplicate_published_ids": + var ids: Array = value[&"systems"][&"runtime"][&"domain_events"]["published_ids"] + if demand(not ids.is_empty(), "B1 has no published ID to duplicate"): ids.append(ids[0]) + "duplicate_facility": + var instances: Array = value[&"systems"][&"runtime"][&"facilities"][&"instances"] + if not instances.is_empty(): instances.append(instances[0].duplicate(true)) + return value + +func e3_package(path: String) -> Dictionary: + var files: Dictionary = {} + for name: String in ["manifest.json", "world.bin", "thumbnail.png", "journal.log"]: + var target: String = path.path_join(name) + if not FileAccess.file_exists(target): + files[name] = null + continue + var file: FileAccess = FileAccess.open(target, FileAccess.READ) + if not demand(file != null, "package evidence open"): continue + var bytes: PackedByteArray = file.get_buffer(file.get_length()) + file.close() + files[name] = {"bytes": Marshalls.raw_to_base64(bytes), "sha256": hashed(bytes)} + return files + +func e3_prepare_package(path: String, input: Dictionary, kind: String) -> Dictionary: + # This helper is called only within run_e3's explicitly opened interval. + demand(scenario_active, "package preparation outside E3") + var budget_before: Dictionary = {} + for key: String in ["_samples", "_totals", "_sample_counts"]: + budget_before[key] = SaveService._performance_budget.get(key).duplicate(true) + var saved: Dictionary = SaveService.save_snapshot(path, input, {}) + var info: Dictionary = {"input": transport(input), "save_return": transport(saved), "original": e3_package(path), "budget_before": transport(budget_before)} + if saved.get(&"ok") == true: + if kind in ["missing_key", "wrong_type", "out_of_range"]: + var manifest_path: String = path.path_join("manifest.json") + var file: FileAccess = FileAccess.open(manifest_path, FileAccess.READ) + if not demand(file != null, "manifest read"): return info + var manifest: Dictionary = JSON.parse_string(file.get_as_text()) + file.close() + match kind: + "missing_key": manifest.erase("checksum_world") + "wrong_type": manifest["format_version"] = "x" + "out_of_range": manifest["format_version"] = 2147483647 + file = FileAccess.open(manifest_path, FileAccess.WRITE) + if not demand(file != null, "manifest write"): return info + file.store_string(json_text(manifest)) + file.close() + elif kind == "tampered_world": + var world_path: String = path.path_join("world.bin") + var file: FileAccess = FileAccess.open(world_path, FileAccess.READ_WRITE) + if not demand(file != null and file.get_length() > 0, "world tamper input"): return info + var offset: int = file.get_length() / 2 + file.seek(offset) + var old: int = file.get_8() + file.seek(offset) + file.store_8(old ^ 0x01) + file.close() + info["tamper"] = {"offset": offset, "before": old, "after": old ^ 0x01} + info["modified"] = e3_package(path) + return info + +func run_e3() -> void: + var facility_count: int = b1_snapshot[&"systems"][&"runtime"][&"facilities"][&"instances"].size() + var kinds: Array = ["missing_key", "wrong_type", "out_of_range", "duplicate_published_ids", "duplicate_facility", "tampered_world"] + lifecycle["e3"] = [] + lifecycle["e3_b1"] = transport(b1_snapshot) + for api: String in ["restore_snapshot", "validate", "load_from_path"]: + for kind: String in kinds: + var id: String = "E3/" + api + "/" + kind + var input: Dictionary = e3_input(kind) + var applicable: bool = true + var reason: Variant = null + if kind == "tampered_world" and api != "load_from_path": + applicable = false + reason = "Dictionary API does not read packages" + elif kind == "duplicate_facility" and facility_count == 0: + demand(role == "O", "R B1 must contain a facility") + applicable = false + reason = "B1 has zero facilities" + elif kind in ["duplicate_published_ids", "duplicate_facility"] and api == "validate": + applicable = false + reason = "Envelope validation does not inspect runtime internals" + var relative: String = "duplicate_id" if kind.begins_with("duplicate_") else kind + var path: String = "user://p28_eq/" + role.to_lower() + "/" + relative + var before: Dictionary = e3_observation() + var budget_before: Dictionary = {} + for key: String in ["_samples", "_totals", "_sample_counts"]: + budget_before[key] = SaveService._performance_budget.get(key).duplicate(true) + scenario_events = [] + scenario_signals = [] + scenario_active = true + var package: Variant = null + var actual: Variant = null + var invoked: bool = applicable or (api == "validate" and reason == "Envelope validation does not inspect runtime internals") + var invocation_before: Dictionary = before + if api == "load_from_path" and applicable: + var package_input: Dictionary = input if kind.begins_with("duplicate_") else b1_snapshot.duplicate(true) + package = e3_prepare_package(path, package_input, kind) + var saved: Dictionary = decode(package.save_return.tree) + if saved.get(&"ok") != true: + demand(kind.begins_with("duplicate_"), "required package preparation refused") + applicable = false + invoked = false + reason = "SaveService.save_snapshot refused duplicate input" + invocation_before = e3_observation() + # These are the only live E3 calls. No reset/repair of product state. + if invoked: + match api: + "restore_snapshot": actual = runtime.restore_snapshot(input) + "validate": actual = SimulationSnapshot.validate(input) + "load_from_path": actual = runtime.load_from_path(path) + if package != null: package["after_operation"] = e3_package(path) + var after: Dictionary = e3_observation() + scenario_active = false + var code: Variant = null + var code_reason: Variant = null + var actual_ok: Variant = null + var errors: Variant = null + var migration: bool = false + if api == "restore_snapshot": + code_reason = "API returns bool only" + actual_ok = actual + elif api == "validate": + code_reason = "API returns ok/errors only" + if invoked: + actual_ok = actual.get(&"ok") + errors = actual.get(&"errors") + elif invoked: + code = actual.get(&"code") + actual_ok = actual.get(&"ok") + migration = actual.get(&"migration_attempted", false) + demand(code != null, "load_from_path missing code") + var event_trees: Array = [] + for event_record: Dictionary in scenario_events: event_trees.append(event_record.tree) + var result: Dictionary = {"category": kind, "applicability": "applied" if applicable else "NA", + "reason": reason, "invoked": invoked, "facility_count": facility_count, "ok": actual_ok, "errors": errors, + "code": str(code) if code != null else null, "code_reason": code_reason, "migration_attempted": migration, + "event_count": scenario_events.size(), "path": path if api == "load_from_path" else null} + var scenario: Dictionary = {"id": id, "operation": api, "result": result, + "checkpoints": [before.checkpoint, after.checkpoint], "events": event_trees} + var budget_after: Dictionary = {} + for key: String in ["_samples", "_totals", "_sample_counts"]: + budget_after[key] = SaveService._performance_budget.get(key).duplicate(true) + var evidence: Dictionary = {"id": id, "begin": before, "invocation_before": invocation_before, "end": after, + "input": transport(input), "return": transport(actual), "package": package, "events": scenario_events, + "signals": scenario_signals.duplicate(true), "latest_save_operation_result": transport(runtime.get("latest_save_operation_result")), + "save_budget_before": transport(budget_before), "save_budget_after": transport(budget_after), "boundaries": ["begin", "operation", "end"]} + report.scenarios.append(scenario) + lifecycle.e3.append(evidence) + write_evidence("e3-%02d.json" % (report.scenarios.size() - 1), evidence) + +# S3b shares S3a's complete observation and transport; no state repair. +func e45_emit(id: String, operation: String, observations: Array, detail: Dictionary) -> void: + detail["signals"] = scenario_signals.duplicate(true) + var cps: Array = [] + for observation: Dictionary in observations: cps.append(observation.checkpoint) + var events: Array = [] + for event: Dictionary in scenario_events: events.append(event.tree) + var result: Dictionary = {"event_count": events.size(), "applicability": detail.get("applicability", "applied"), "reason": detail.get("reason")} + var facts: Dictionary = detail.duplicate(true) + for key: String in ["package_before", "package_after", "save_return", "return", "save_budget_before", "save_budget_after", "latest_save_operation_result", "observation_before", "observation_after"]: facts.erase(key) + if detail.has("return"): + var actual: Variant = decode(detail["return"].tree) + facts["return_fact"] = {"ok": actual.get(&"ok"), "code": actual.get(&"code")} if actual is Dictionary else actual + if facts.has("trials"): + for trial: Dictionary in facts.trials: + trial.erase("before") + trial.erase("after") + result["facts"] = facts + var evidence: Dictionary = {"id": id, "boundaries": ["begin", "operation", "end"], "observations": observations, + "events": scenario_events.duplicate(true), "signals": scenario_signals.duplicate(true), "detail": detail} + report.scenarios.append({"id": id, "operation": operation, "result": result, "checkpoints": cps, "events": events}) + lifecycle.e45.append(evidence) + write_evidence("e45-%02d.json" % (lifecycle.e45.size() - 1), evidence) + +func e4_candidates() -> Dictionary: + demand(scenario_active, "candidate search outside E4") + var before: Dictionary = e3_observation() + var raw_ids: Array = runtime.definition_registry.get_facility_ids() + var ids: Array = raw_ids.duplicate() + ids.sort_custom(func(a: Variant, b: Variant) -> bool: return str(a) < str(b)) + var bounds: Dictionary = runtime.world_service.get_bounds() + var selection: Dictionary = {"source": "definition_registry.get_facility_ids()", "raw_ids": transport(raw_ids), "count": raw_ids.size(), + "sorted_ids": transport(ids), "sort_rule": "String(id) ascending Unicode code point", "bounds": transport(bounds), + "cell_rule": "inclusive x/y public bounds; z FRONT=0 through BACK=1; x,y,z lexical; ID outer; rotation=0", + "trials": [], "chosen": null, "applicability": "applied", "reason": null, "observation_before": before} + if not demand(not ids.is_empty(), "empty facility registry"): + selection.applicability = "failure" + selection.reason = "empty facility registry" + selection["observation_after"] = e3_observation() + return selection + for definition_id: StringName in ids: + for x: int in range(bounds[&"min_x"], bounds[&"max_x"] + 1): + for y: int in range(bounds[&"min_y"], bounds[&"max_y"] + 1): + for z: int in range(0, 2): + var origin: Vector3i = Vector3i(x, y, z) + var preview: Dictionary = runtime.preview_build_facility(definition_id, origin, 0) + var candidate: Dictionary = {"definition_id": definition_id, "origin": origin, "rotation": 0} + selection.trials.append({"candidate": transport(candidate), "preview": transport(preview)}) + if preview.get(&"can_build") == true: + selection.chosen = transport(candidate) + selection["observation_after"] = e3_observation() + demand(json_text(before.raw) == json_text(selection.observation_after.raw), "preview search mutated S/K/C") + return selection + selection.applicability = "NA" + selection.reason = "all registry/cell pairs rejected by public preview" + selection["observation_after"] = e3_observation() + demand(json_text(before.raw) == json_text(selection.observation_after.raw), "preview search mutated S/K/C") + return selection + +func run_e4() -> void: + lifecycle["e45"] = [] + for operation: String in ["build_facility", "tick", "restore_snapshot", "load_from_path", "rejected_command"]: + var observations: Array = [e3_observation()] + var detail: Dictionary = {} + var save_budget_before: Dictionary = e45_save_budget() + scenario_events = [] + scenario_signals = [] + scenario_active = true + if operation == "build_facility": + detail = e4_candidates() + if detail.chosen != null: + var payload: Dictionary = decode(detail.chosen.tree) + var submitted: Variant = runtime.submit_command(&"build_facility", payload) + detail["submit"] = transport(submitted.to_dictionary()) + observations.append(e3_observation()) + clock.advance_minutes(1) + var completed: Variant = runtime.command_queue.get_processed_result(submitted.command_id) + detail["command_result"] = transport(completed.to_dictionary() if completed != null else null) + elif operation == "tick": + clock.advance_minutes(1) + elif operation == "restore_snapshot": + var input: Dictionary = runtime.create_snapshot().duplicate(true) + detail["input"] = transport(input) + detail["return"] = transport(runtime.restore_snapshot(input)) + elif operation == "load_from_path": + var input: Dictionary = runtime.create_snapshot().duplicate(true) + var path: String = "user://p28_eq/" + role.to_lower() + "/good" + detail["input"] = transport(input) + detail["path"] = path + var saved: Dictionary = SaveService.save_snapshot(path, input, {}) + detail["save_return"] = transport(saved) + detail["package_before"] = e3_package(path) + demand(saved.get(&"ok") == true, "E4 good package save failed") + detail["return"] = transport(runtime.load_from_path(path)) + detail["latest_save_operation_result"] = transport(runtime.get("latest_save_operation_result")) + detail["package_after"] = e3_package(path) + elif operation == "rejected_command": + var submitted: Variant = runtime.submit_command(&"build_facility", {&"definition_id": ""}) + detail["submit"] = transport(submitted.to_dictionary()) + observations.append(e3_observation()) + clock.advance_minutes(1) + var completed: Variant = runtime.command_queue.get_processed_result(submitted.command_id) + detail["command_result"] = transport(completed.to_dictionary() if completed != null else null) + detail["save_budget_before"] = save_budget_before + detail["save_budget_after"] = e45_save_budget() + observations.append(e3_observation()) + scenario_active = false + e45_emit("E4/" + operation, operation, observations, detail) + +func e45_save_budget() -> Dictionary: + var budget: Dictionary = {} + for key: String in ["_samples", "_totals", "_sample_counts"]: + budget[key] = SaveService._performance_budget.get(key).duplicate(true) + return transport(budget) + +func run_e5() -> void: + for target: String in ["create_snapshot", "latest_snapshot", "snapshot_published", "state_updated"]: + for location: String in ["dict", "array"]: + for direction: String in ["outside_in", "inside_out"]: + var observations: Array = [e3_observation()] + scenario_events = [] + scenario_signals = [] + scenario_active = true + # Explicit preparation tick refreshes signal references and starts a new baseline. + clock.advance_minutes(1) + var baseline: Dictionary = e3_observation() + observations.append(baseline) + var returned: Dictionary = {} + match target: + "create_snapshot": returned = runtime.create_snapshot() + "latest_snapshot": returned = runtime.get("latest_snapshot") + "snapshot_published": returned = snapshot_reference + "state_updated": returned = state_reference + var held_copy: Dictionary = returned.duplicate(true) + var detail: Dictionary = {"target": target, "location": location, "direction": direction, + "digest_materialized_before": true, "held_before": transport(held_copy)} + if direction == "outside_in": + if location == "dict": + returned[&"systems"][&"runtime"][&"id_generator"][&"counters"]["__p28_eq_probe"] = 1 + else: + returned[&"systems"][&"runtime"][&"domain_events"]["published_ids"].append("__p28_eq_probe") + else: + clock.advance_minutes(1) + observations.append(e3_observation()) + detail["held_after"] = transport(returned) + # Reset only through the authorized next tick, retaining the post-mutation state. + clock.advance_minutes(1) + observations.append(e3_observation()) + scenario_active = false + e45_emit("E5/" + target + "/" + location + "/" + direction, direction, observations, detail) + diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/run_eq.py b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/run_eq.py new file mode 100644 index 0000000..cfb7836 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/run_eq.py @@ -0,0 +1,273 @@ +#!/usr/bin/env python3 +"""Root-only EQ driver. --check neither writes nor starts processes other than read-only host/Git queries.""" +import argparse +import importlib.util +import json +import os +from pathlib import Path +import shutil +import subprocess +import sys +import uuid + +sys.dont_write_bytecode = True +import check_eq as check +import compare_versions as eq +import verify_eq as verify + +HERE, ROOT = verify.HERE, verify.ROOT +BASE = 'docs/plans/original-completion-2026-10-02/execution/' +COLLECTOR = BASE + 'p28-01/collector/collect_p28_01.py' +DEPENDENCIES = { + 'tools/run_all_tests.py': '320ca668732b4ff72fc4449998af2327d4e5c527b06896740806aaf0487282b4', + 'tools/regression/owned_outer.py': 'c2e3483b76db1a3ff940f23f88ea0083fc78736e874ebcdb385d766dde8866e7', + 'tools/regression/owned_diagnostic_process.py': 'e31e93c6e2c5ea46a7d954ef8bc0b4caec1c08b86b8aef19e93b52ef24993087', + 'tools/regression/p09_owned_engine_process.py': 'c007e712c281573254faa1233c2ac92e100ab87393256a6dc096b35283e43037', + COLLECTOR: 'a43e1f963ef8505ddd5acf8bf747d9bfac22a028cbb805c0b964ee11b9b40a14', + BASE + 'p28-01/collector/check_p28_01_report.py': '6c0851d498ca80bdc120fad047b072255f48713f63114521f3d4dfc902b2512b', + BASE + 'p28-02/diag/diag_probe.gd': '4124067d4b193693f696d2b1a1e6eb56731948cfefd5a6e420b5c9a14fb2b11e', + BASE + 'p28-02/diag/verify_diag.py': '829354804f0ebb152a8092486ccadbc6b36143a5c9187dac75c15f90b70d1fb9', + BASE + 'p28-02/diag/test_diag.py': '744b779f4b2452e0c1660c6fd1aa009d26e7315e8a0fddd669a2ac3e261c61b4', + BASE + 'p28-02/diag/diag_p28_02.py': '6b47d08b490ba742ce00e8835a09011c5966d0a8fc7b578498bfc80bc03f14ed', + BASE + 'p28-02/diag/check_diag.py': '96dd9bef220339d6a973215d8db9a73c1bfa44f9e151bcf897641882e831b5ba', +} +FROZEN = { + 'SPEC.md': '3791ccdcb87e8d71fe9205e1e692ebca9e0f974ea3b5fbc4fbb3943882131f1c', + 'TASK_INSTRUCTIONS.md': 'f9937c3c7dff5a25ada453365d26c87fecf009d29518724f0c1e67d2b18afff3', + 'references/OPT_CONTRACT_T1.md': 'ad9f3d76f3500b39263fb898d7c64588b4b47c9e11b456f938195261fd054d16', + 'references/OPUS_D2_SCOPE_CLARIFICATION.txt': '5775e7b512d9e90dbcfbcb181f5b64dc0fa8207e0947c0a4a6a5c9195565f9bd', + 'references/OPUS_STARTUP_LIFECYCLE_CLARIFICATION.txt': '967aebf27ff412f7a16ce771ef7d68abf8cfde0bb76ed19cf6dbf2817ca7acc6', + 'registration/ACCEPTANCE_BASELINE.json': '84628bc21205387f8a7143031bdc50c9f68a767d350e6c34b32e0ba1c7059337', + 'registration/CONFIG_PROPOSAL.json': '775fbbb97cda8b4d4991defdf7871b0fc79f489f4dea34c1733d4830426cf1df', + 'registration/REGISTRATION_PROPOSAL.json': '9590fc853a4df8d50cc0d269d23bd9c844dc6931590ff6f24ebf95bb54a8d135', + 'registration/ROOT_PROPOSAL_BYTE_TRANSFER.json': '63197f650849084f769e487a76458361886a37090042f1e351851c75b0384da2', +} +require, sha, pin, write = verify.require, verify.sha, verify.pin, verify.write + + +def load_dependencies(root=ROOT): + root = Path(root).resolve() + for name, expected in DEPENDENCIES.items(): + require(sha(root / name) == expected, 'dependency pin: ' + name) + local = root / HERE.relative_to(ROOT) + for name in verify.LOCAL_NAMES - {'eq_probe.gd'}: + check.check_python_imports((local / name).read_text()) + def load(relative, module_name): + require(relative in DEPENDENCIES and relative.endswith('.py'), 'import outside closure') + spec = importlib.util.spec_from_file_location(module_name, root / relative) + module = importlib.util.module_from_spec(spec) + sys.modules[module_name] = module + spec.loader.exec_module(module) + return module + # Import sibling dependencies under their real names before the collector. + load(BASE + 'p28-01/collector/check_p28_01_report.py', 'check_p28_01_report') + collector = load(COLLECTOR, 'eq_collector') + diag = load(BASE + 'p28-02/diag/check_diag.py', 'eq_diag_check') + for name in diag.DEPENDENCIES: + diag.check_imports((root / name).read_text(), external=name) + standard = collector.load_tool(collector.EXTERNAL_IMPORTS[0]) + outer = collector.load_tool(collector.EXTERNAL_IMPORTS[1]) + require(Path(outer.native.helper['__file__']).resolve() == root / 'tools/regression/p09_owned_engine_process.py', 'helper closure') + for module in [collector, standard, outer, outer.native, *list(sys.modules.values())]: + name = getattr(module, '__file__', None) + if name: + path = Path(name).resolve() + if path.is_relative_to(root): + require(path.relative_to(root).as_posix() in DEPENDENCIES or path.is_relative_to(local), 'loaded module outside closure') + return collector, standard, outer, diag + + +def actual_pins(root, readonly, fixture, engine, collector, standard): + local = root / HERE.relative_to(ROOT) + dependencies = {n: sha(root / n) for n in DEPENDENCIES} + require(dependencies == DEPENDENCIES, 'dependencies changed') + frozen = {n: sha(local / n) for n in FROZEN} + require(frozen == FROZEN, 'frozen specification changed') + source = collector.source_map(standard, root) + require(len(source) == 1407 and collector.digest(source) == eq.SOURCE_SHA, 'full 1407 source pin') + require(sha(fixture) == collector.FIXTURE_SHA and sha(engine) == collector.ENGINE_SHA, 'fixture/engine pin') + inputs = collector.inputs(readonly) + require(len(inputs['files']) == 9, 'nine original destinations required') + manifest = verify.read(readonly / 'ROOT_INPUT_MANIFEST.json') + require(len(manifest['files']) == 9 and len({r['destination'] for r in manifest['files']}) == 9, 'nine unique destinations') + require(sys.platform == 'darwin', 'native platform') + machine = subprocess.check_output(['sysctl', '-n', 'hw.model'], text=True).strip() + require(machine == 'Mac16,10', 'machine pin') + return {'source': source, 'source_sha256': collector.digest(source), 'dependencies': dependencies, + 'frozen': frozen, 'worker': {n: sha(local / n) for n in sorted(verify.LOCAL_NAMES)}, + 'fixture': pin(fixture), 'engine': pin(engine), 'engine_version': collector.VERSION, + 'project': source['project.godot'], 'readonly': inputs, 'original_manifest': manifest, + 'machine': machine, 'platform': sys.platform} + + +def frozen_commit(source): + commit = subprocess.check_output(['git', '-C', str(ROOT), 'rev-parse', 'HEAD'], text=True).strip() + for name in list(source) + [str((HERE / n).relative_to(ROOT)) for n in verify.LOCAL_NAMES]: + data = subprocess.check_output(['git', '-C', str(ROOT), 'show', commit + ':' + name]) + require(data == (ROOT / name).read_bytes(), 'not frozen S: ' + name) + return commit + + +def wrapper_text(out): + return ('extends ' + json.dumps(str(out / 'eq_probe.gd')) + '\nconst Guard = preload(' + + json.dumps(str(out / 'profile_guard.gd')) + ')\nfunc _initialize() -> void:\n' + '\tif not Guard.activate():\n\t\tquit(97)\n\t\treturn\n\tsuper._initialize()\n') + + +def plan(collector, standard, engine, fixture, out): + stage, wrapper = out / 'stage', out / 'guarded.gd' + commands = [collector.argv_for(engine, stage, wrapper, importing=True), + collector.parse_argv(engine, stage, out / 'eq_probe.gd'), + collector.parse_argv(engine, stage, wrapper)] + [ + [str(engine), '--headless', '--path', str(stage), '--script', str(wrapper)] for _ in range(4)] + rows = [] + for phase, command in zip(verify.PHASES, commands): + startup_name = 'TheTree-PCK-tests-' + uuid.uuid4().hex + '-eq-startup' + runtime_name = 'TheTree-PCK-tests-' + uuid.uuid4().hex + '-eq-runtime' + startup, runtime = standard.profile_path(startup_name), standard.profile_path(runtime_name) + require(not startup.exists() and not runtime.exists(), 'fresh profiles required') + role = verify.ROLES.get(phase) + env = {'THE_TREE_PACK_PROFILE_NAME': runtime_name, 'THE_TREE_PACK_PROFILE_EXPECTED': str(runtime), + 'THE_TREE_PACK_PROFILE_REPORT': str(out / (phase + '-guard.json')), + 'THE_TREE_EQ_ROLE': role or '', 'THE_TREE_P28_FIXTURE': str(fixture), + 'THE_TREE_P28_FIXTURE_SHA': collector.FIXTURE_SHA} + rows.append({'phase': phase, 'role': role, 'argv': command, 'environment': env, + 'startup_name': startup_name, 'startup_profile': str(startup), + 'runtime_name': runtime_name, 'runtime_profile': str(runtime), 'folder': str(out / phase)}) + return rows + + +def copy_evidence(runtime, destination): + source = runtime / 'evidence' + before = verify.inventory(source, seals=True) + require(set(before) == verify.NAMES, 'private evidence missing/extra') + destination.mkdir() + for name in sorted(before): + shutil.copyfile(source / name, destination / name) + require(verify.inventory(source, seals=True) == before == verify.inventory(destination, seals=True), 'evidence changed during copy') + return before + + +def copy_profile(source, destination, collector): + """Keep complete private package/log/config bytes, including non-evidence files.""" + exists = source.is_dir() + before = collector.profile_files(source) + if exists: + destination.mkdir() + for name in before: + target = destination / name + target.parent.mkdir(parents=True, exist_ok=True) + shutil.copyfile(source / name, target) + require(verify.inventory(destination, seals=True) == before, 'profile copy mismatch') + require(collector.profile_files(source) == before, 'profile changed during copy') + return {'exists': exists, 'files': before} + + +def run(admission, out, collector, standard, outer, diag): + require(not out.exists(), 'new output required') + collector.no_live_engine() + out.mkdir(parents=True) + write(out / 'admission.json', admission) + rows, profiles, error = [], [], None + source = admission['source_map'] + player = standard.default_player(ROOT) + public = (ROOT / 'project.godot').read_bytes() + stage = out / 'stage' + try: + stage.mkdir() + for name in source: + target = stage / name + target.parent.mkdir(parents=True, exist_ok=True) + standard.copy_source(ROOT / name, target) + expected = standard.inventory(stage, stage=True) + require(expected == source, 'stage source differs') + (out / 'eq_probe.gd').write_bytes((HERE / 'eq_probe.gd').read_bytes()) + (out / 'profile_guard.gd').write_bytes((Path(admission['readonly_path']) / 'run-r02/profile_guard.gd').read_bytes()) + (out / 'guarded.gd').write_text(wrapper_text(out)) + (out / 'root-input-manifest.json').write_bytes((Path(admission['readonly_path']) / 'ROOT_INPUT_MANIFEST.json').read_bytes()) + for item in admission['plan']: + phase = item['phase'] + require(standard.inventory(stage, stage=True) == expected, 'stage changed before phase') + require(collector.source_map(standard, ROOT) == source and standard.default_player(ROOT) == player, 'source/player changed') + for name, expected_sha in admission['pins']['worker'].items(): + require(sha(HERE / name) == expected_sha, 'EQ changed during execution') + profiles.extend([Path(item['startup_profile']), Path(item['runtime_profile'])]) + require(all(not p.exists() for p in profiles[-2:]), 'profile reuse') + row = collector.run_private_engine(standard, outer, item['argv'], out / phase, + item['environment'], stage, public, item['startup_name']) + row.update(phase=phase, role=item['role'], environment=item['environment'], pid=row['process']['pid']) + rows.append(row) + require(row['passed'] is True, 'owned phase failure: ' + phase) + after = standard.inventory(stage, stage=True) + collector.stage_gate(expected, after, importing=phase == 'import') + expected = after + row.update(stage_inventory=after, source_preserved=collector.source_map(standard, ROOT) == source, + player_preserved=standard.default_player(ROOT) == player) + if phase in verify.ROLES: + guard_path = out / (phase + '-guard.json') + guard = verify.read(guard_path) + collector.guard_gate(guard, Path(item['runtime_profile']), item['runtime_name']) + row.update(runtime_profile=item['runtime_profile'], runtime_name=item['runtime_name'], + guard=guard, guard_sha256=sha(guard_path)) + row['evidence_files'] = copy_evidence(Path(item['runtime_profile']), out / phase / 'evidence') + verify.phase_evidence(out, row) + row['profile_copies'] = { + 'startup': copy_profile(Path(item['startup_profile']), out / phase / 'startup-profile', collector), + 'runtime': copy_profile(Path(item['runtime_profile']), out / phase / 'runtime-profile', collector)} + diag.bound_raw(out / phase, row) + except BaseException as caught: + error = repr(caught) + finally: + cleanup, cleanup_errors = outer.finish_captured(outer.OWNED) + execution = {'admission': admission, 'phases': rows, 'passed': error is None, 'error': error, + 'cleanup': cleanup, 'cleanup_errors': cleanup_errors, 'source_after': collector.source_map(standard, ROOT), + 'player_before': player, 'player_after': standard.default_player(ROOT), + 'profiles_retained': {str(p): collector.profile_files(p) for p in profiles}} + try: + execution['pins_after'] = actual_pins(ROOT, Path(admission['readonly_path']), Path(admission['fixture']), + Path(admission['engine']), collector, standard) + require((ROOT / 'project.godot').read_bytes() == public and (stage / 'project.godot').read_bytes() == public, 'project restoration') + if error is None: + result = verify.recompute(out, execution, collector, standard, diag) + write(out / 'results.json', result) + for phase, values in result['phases'].items(): + for name, value in values.items(): + write(out / phase / (name + '.json'), value) + except BaseException as caught: + execution.update(passed=False, error=repr(caught)) + write(out / 'execution.json', execution) + if execution['passed']: + verify.seal(out) + return 0 if execution['passed'] else 1 + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + mode = parser.add_mutually_exclusive_group(required=True) + mode.add_argument('--check', action='store_true') + mode.add_argument('--run', action='store_true') + for name in ('readonly', 'fixture', 'engine', 'output'): + parser.add_argument('--' + name, type=Path, required=True) + args = parser.parse_args() + try: + readonly, fixture, engine, out = [p.resolve() for p in (args.readonly, args.fixture, args.engine, args.output)] + require(not out.exists(), 'new output required') + collector, standard, outer, diag = load_dependencies() + pins = actual_pins(ROOT, readonly, fixture, engine, collector, standard) + static = check.check_probe((HERE / 'eq_probe.gd').read_text()) + require(static['ok'], 'probe checker: ' + repr(static['errors'])) + admission = {'measured_source': 'S_eq-native-not-Q', 'candidate_Q_measured': False, + 'commit': frozen_commit(pins['source']), 'source_map': pins['source'], 'pins': pins, + 'readonly_path': str(readonly), 'fixture': str(fixture), 'engine': str(engine), + 'phases': verify.PHASES, 'plan': plan(collector, standard, engine, fixture, out)} + if args.check: + print(json.dumps(admission, ensure_ascii=False, indent=2)) + return 0 + return run(admission, out, collector, standard, outer, diag) + except (ValueError, OSError, KeyError, TypeError, subprocess.CalledProcessError) as error: + print(json.dumps({'status': 'failed', 'error': str(error)})) + return 1 + + +if __name__ == '__main__': + raise SystemExit(main()) diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py new file mode 100644 index 0000000..9c1fbf4 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py @@ -0,0 +1,1702 @@ +"""Engine-free S1 tests; synthetic typed trees only.""" +import copy +import hashlib +import json +import sys +import unittest +from unittest.mock import patch + +sys.dont_write_bytecode = True +import compare_versions as eq + + +def d(**fields): + return [27, [[[4, k], v] for k, v in fields.items()], None] + + +def arr(*values): + return [28, list(values), None] + + +def profile(root='/private/a'): + return {'root': root, 'actual_user_data_dir': root} + + +def event(root='/private/a', duration=7, kind='SAVE_LOADED', source='save_service'): + return d(event_id=[4, 'event_1'], event_type=[4, kind], source_service=[4, source], + absolute_minute=[2, 1], entity_ids=arr(), causation_command_id=[4, ''], + payload=d(duration_us=[2, duration], runtime_duration_us=[2, duration+1], + message=[4, root+'/p28_eq/r/good: '+root+'/world.bin'], code=[4, 'OK'])) + + +def snapshot(e=None): + return d(systems=d(runtime=d(domain_events=d(recent_events=arr(*(e or []))))), value=arr([2, 1])) + + +def transport(t): + return {'tree': copy.deepcopy(t), 'tree_sha': eq.tree_sha(t), 'raw_bytes_sha': 'a'*64, 'roundtrip_ok': True} + + +def checkpoint(t=None, minute=0): + t = snapshot() if t is None else t + k = {key: 0 for key in eq.K_COMPARE} + k.update(_accumulator='0000000000000000', _phase_handlers={'0': ['h1', 'h2']}, + performance_budget={'_samples': {'x': [1]}, '_totals': {'x': 1}, '_sample_counts': {'x': 1}}) + c = {'_mvp_manifest_cache_generation': 1, 'catalog_is_current': True, + '_mvp_manifest_cache_bytes': 'AA==', 'catalog_instance_id': 123, 'current_catalog_instance_id': 123} + return {'minute': minute, 'S': transport(t), 'latest': transport(t), + 'latest_digest': 'digest', 'computed_latest_digest': 'digest', 'harness_normalized_digest': 'norm', + 'K': k, 'C': c, 'observation': {side: {layer: 'a'*64 for layer in ('S', 'K', 'C')} for side in ('before', 'after')}} + + +def report(t=None): + return {'schema': 'p28-02-eq/typed-v1', 'role': 'R', 'profile_root': profile(), + 'checkpoints': [checkpoint(t, i) for i in range(31)], 'events': [], + 'event_start': {'counter': 3, 'published_ids_count': 3}, 'event_end': 3, + 'signal_order': [], 'scenarios': []} + + +class TypedTrees(unittest.TestCase): + def test_exact_and_types(self): + for a, b in (([2, 1], [3, '000000000000f03f']), ([4, 'x'], [21, 'x']), + (arr([2, 1]), [28, [[2, 1]], [[2, 2], [21, ''], [0]]])): + self.assertFalse(eq.compare_trees(a, b)['equal']) + self.assertTrue(eq.compare_trees(snapshot(), snapshot())['exact']) + + def test_nested_order_all_paths(self): + a = d(a=d(x=[2, 1], y=[2, 2]), b=d(c=[2, 3], d=[2, 4])) + b = copy.deepcopy(a) + b[1].reverse() + for _, n in b[1]: + n[1].reverse() + result = eq.compare_trees(a, b) + self.assertTrue(result['equal']) + self.assertEqual(len(result['dict_order_paths']), 3) + self.assertFalse(result['exact']) + + def test_duplicate_textual_keys_rejected(self): + a = [27, [[[4, 'x'], [2, 1]], [[21, 'x'], [2, 2]]], None] + b = copy.deepcopy(a); b[1].reverse() + with self.assertRaises(eq.EvidenceError): + eq.compare_trees(a, b) + + def test_array_order_and_all_differences(self): + result = eq.compare_trees(arr([2, 1], [2, 2]), arr([2, 2], [2, 1])) + self.assertEqual(len(result['differences']), 2) + + def test_nonstring_keys_keep_types_and_values(self): + a = [27, [[[2, 1], [4, 'one']], [[2, 2], [4, 'two']]], None] + b = copy.deepcopy(a); b[1].reverse() + self.assertTrue(eq.compare_trees(a, b)['equal']) + b[1][0][1] = [4, 'changed'] + self.assertFalse(eq.compare_trees(a, b)['equal']) + a = [27, [[[2, 1], [0]], [[4, '1'], [0]]], None] + b = copy.deepcopy(a); b[1].reverse() + with self.assertRaises(eq.EvidenceError): + eq.compare_trees(a, b) + + def test_deep_state_not_truncated(self): + a, b = [2, 1], [2, 2] + for _ in range(40): + a, b = d(child=a), d(child=b) + self.assertEqual(len(eq.compare_trees(a, b)['differences'][0]['path']), 40) + + def test_unsupported_and_malformed(self): + for n in ([23, 0], [24, 0], [25, 0], [26, 0], [3, '1.0'], [2, True], + [1, 2], [2, 2**63], [27, [], {}], [29, '%%%'], [28, [], [[2, 2], [21, ''], [24, 0]]]): + with self.subTest(n=n), self.assertRaises(eq.EvidenceError): + eq.validate_tree(n) + + def test_components_and_sha(self): + zero = [3, '0000000000000000'] + eq.validate_tree([20, [zero]*4]) + eq.validate_tree([37, [[20, [zero]*4]]]) + eq.validate_tree([29, 'AAEC']) + tree = d(text=[4, '日本語/é\n']) + expected = hashlib.sha256(json.dumps(tree, ensure_ascii=False, separators=(',', ':')).encode()).hexdigest() + self.assertEqual(eq.tree_sha(tree), expected) + self.assertNotEqual(eq.tree_sha([3, '0000000000000000']), eq.tree_sha([3, '0000000000000080'])) + + +class Diffs(unittest.TestCase): + def test_all_operations(self): + a = d(items=arr([2, 1], [2, 2]), gone=[4, 'old']) + path = [['key', [4, 'items']]] + ops = [{'op': 'array_splice', 'path': path, 'start': 1, 'delete_count': 1, 'nodes': [[2, 3], [2, 4]]}, + {'op': 'set', 'path': path+[['index', 0]], 'node': [2, 9]}, + {'op': 'dict_remove', 'path': [], 'key_node': [4, 'gone']}, + {'op': 'dict_insert', 'path': [], 'index': 0, 'key_node': [4, 'new'], 'value_node': [1, 1]}] + result = eq.apply_diff(a, ops) + self.assertEqual(result, d(new=[1, 1], items=arr([2, 9], [2, 3], [2, 4]))) + self.assertEqual(a, d(items=arr([2, 1], [2, 2]), gone=[4, 'old'])) + + def test_invalid_operations(self): + for op in ({'op': 'dict_remove', 'path': [], 'key_node': [4, 'absent']}, + {'op': 'dict_insert', 'path': [], 'index': 0, 'key_node': [4, 'x'], 'value_node': [0]}, + {'op': 'set', 'path': [['key', [4, 'absent']]], 'node': [0]}, + {'op': 'unknown', 'path': []}): + with self.subTest(op=op), self.assertRaises(eq.EvidenceError): + eq.apply_diff(d(x=[2, 1]), [op]) + with self.assertRaises(eq.EvidenceError): + eq.apply_diff(arr(), [{'op': 'array_splice', 'path': [], 'start': -1, 'delete_count': 0, 'nodes': []}]) + + def test_reconstruction_and_proofs(self): + a, b = d(x=[2, 1]), d(x=[2, 2]) + b_record = transport(b) + del b_record['tree'] + b_record['diff'] = [{'op': 'set', 'path': [['key', [4, 'x']]], 'node': [2, 2]}] + same = {k: v for k, v in transport(a).items() if k != 'tree'} + same['same_as_S'] = True + cps = [{'S': transport(a), 'latest': same}, {'S': b_record, 'latest': transport(a)}] + self.assertEqual(eq.reconstruct_checkpoints(cps), [(a, a), (b, a)]) + for key, bad in (('tree_sha', 'b'*64), ('roundtrip_ok', False), ('raw_bytes_sha', 'missing')): + corrupt = copy.deepcopy(cps); corrupt[1]['S'][key] = bad + with self.subTest(key=key), self.assertRaises(eq.EvidenceError): + eq.reconstruct_checkpoints(corrupt) + + +class Normalization(unittest.TestCase): + def test_every_save_event_reversible(self): + for kind in eq.SAVE_EVENTS: + events = [event(kind=kind)] + original = copy.deepcopy(events) + n, side = eq.normalize_events(events, profile()) + self.assertEqual(set(side), {'entries', 'violations', 'profile_root'}) + self.assertEqual(len(side['entries']), 3) + self.assertEqual(eq.restore_events(n, side, profile()), original) + self.assertEqual(events, original) + self.assertIn(eq.TOKEN, json.dumps(n)) + + def test_snapshot_and_latest_reversible(self): + t = snapshot([event()]) + n, side = eq.normalize_tree(t, profile()) + self.assertEqual(len(side['entries']), 3) + self.assertEqual(eq.tree_sha(eq.restore_tree(n, side, profile())), eq.tree_sha(t)) + + def test_environment_values_differ_but_normal_form_equal(self): + a, b = event(), event('/private/b', 999) + x, sx = eq.normalize_events([a], profile()) + y, sy = eq.normalize_events([b], profile('/private/b')) + self.assertEqual(x, y) + self.assertNotEqual(sx, sy) + + def test_guard_mismatch(self): + with self.assertRaises(eq.EvidenceError): + eq.normalize_events([event()], {'root': '/private/a', 'actual_user_data_dir': '/private/b'}) + with self.assertRaises(eq.EvidenceError): + eq.normalize_events([event()], '/private/a') + + def test_wrong_event_and_source_are_preserved(self): + for kwargs in ({'kind': 'UNKNOWN'}, {'source': 'not_save_service'}): + original = [event(**kwargs)] + n, side = eq.normalize_events(original, profile()) + self.assertEqual(n, original) + self.assertEqual(side['entries'], []) + self.assertTrue(side['violations']) + self.assertEqual(eq.restore_events(n, side, profile()), original) + + def test_nested_lookalike_is_not_eligible(self): + e = event() + eq._field(e, 'payload')[1].append([[4, 'nested'], event()]) + n, side = eq.normalize_events([e], profile()) + self.assertEqual(len(side['entries']), 3) + self.assertEqual(eq._field(eq._field(n[0], 'payload'), 'nested'), event()) + + def test_snapshot_event_outside_recent_is_not_eligible(self): + s = d(unrelated=event()) + n, side = eq.normalize_tree(s, profile()) + self.assertEqual(n, s) + self.assertFalse(side['entries']) + self.assertTrue(side['violations']) + + def test_wrong_timing_type_and_negative(self): + for value in ([2, -1], [3, '000000000000f03f'], [4, '7']): + e = event(); eq._field(eq._field(e, 'payload'), 'duration_us')[:] = value + with self.assertRaises(eq.EvidenceError): + eq.normalize_events([e], profile()) + + def test_partial_timing_payload_rejected(self): + e = event() + payload = eq._field(e, 'payload') + payload[1] = [pair for pair in payload[1] if pair[0][1] != 'runtime_duration_us'] + with self.assertRaises(eq.EvidenceError): + eq.normalize_events([e], profile()) + + def test_sidecar_missing_duplicate_and_forged_paths(self): + n, side = eq.normalize_events([event()], profile()) + cases = [] + bad = copy.deepcopy(side); bad['entries'].pop(); cases.append(bad) + bad = copy.deepcopy(side); bad['entries'].append(bad['entries'][0]); cases.append(bad) + bad = copy.deepcopy(side); bad['entries'][0]['key'] = 'other_us'; cases.append(bad) + bad = copy.deepcopy(side); bad['entries'][0]['path'] = [['key', [4, 'event_id']]]; cases.append(bad) + bad = copy.deepcopy(side); bad['entries'][-1]['original_node'][1] += 'changed'; cases.append(bad) + bad = copy.deepcopy(side); bad['entries'][-1]['root'] = '/elsewhere'; cases.append(bad) + for bad in cases: + with self.subTest(bad=bad), self.assertRaises(eq.EvidenceError): + eq.restore_events(n, bad, profile()) + + def test_attempt_to_normalize_violation_rejected(self): + e = event(kind='OTHER') + n, side = eq.normalize_events([e], profile()) + path = [['key', [4, 'payload']], ['key', [4, 'duration_us']]] + eq._put(n[0], path, eq._marker('duration_us', [2, 7])) + side['entries'].append({'event_index': 0, 'path': path, 'key': 'duration_us', 'original_node': [2, 7]}) + with self.assertRaises(eq.EvidenceError): + eq.restore_events(n, side, profile()) + + def test_original_transport_sha_detects_forged_timing(self): + original = snapshot([event()]) + n, side = eq.normalize_tree(original, profile()) + side['entries'][0]['original_node'][1] += 1 + restored = eq.restore_tree(n, side, profile()) + self.assertNotEqual(eq.tree_sha(restored), eq.tree_sha(original)) + + def test_f3_keeps_relative_paths_and_words(self): + a, b = event(), event('/private/b') + eq._field(eq._field(b, 'payload'), 'message')[1] += ' different error' + na, _ = eq.normalize_events([a], profile()) + nb, _ = eq.normalize_events([b], profile('/private/b')) + self.assertFalse(eq.compare_trees(na[0], nb[0])['equal']) + + def test_prefix_boundary_and_reserved_token(self): + e = event() + eq._field(eq._field(e, 'payload'), 'message')[1] = '/private/another/world.bin' + n, side = eq.normalize_events([e], profile()) + self.assertEqual(eq._field(eq._field(n[0], 'payload'), 'message'), [4, '/private/another/world.bin']) + self.assertEqual(len(side['entries']), 2) + eq._field(eq._field(e, 'payload'), 'message')[1] = eq.TOKEN+'world.bin' + with self.assertRaises(eq.EvidenceError): + eq.normalize_events([e], profile()) + + +class Reports(unittest.TestCase): + def test_same_report(self): + a = report() + self.assertTrue(eq.compare_reports(a, copy.deepcopy(a))['ok']) + + def test_exclusions_keep_actual_values(self): + a, b = report(), report() + b['checkpoints'][0]['K']['performance_budget']['_samples'] = {'x': [9]} + b['checkpoints'][0]['C']['catalog_instance_id'] = 456 + result = eq.compare_reports(a, b) + self.assertTrue(result['ok'], result) + self.assertTrue(any(x['a'] != x['b'] for x in result['excluded'])) + + def test_all_semantic_layers_compared(self): + for layer, key, value in (('K', 'speed', 3), ('K', '_accumulator', '000000000000f03f'), + ('C', '_mvp_manifest_cache_generation', 2), ('C', '_mvp_manifest_cache_bytes', 'AQ==')): + a, b = report(), report() + b['checkpoints'][0][layer][key] = value + with self.subTest(key=key): + self.assertFalse(eq.compare_reports(a, b)['ok']) + + def test_unknown_or_missing_fields_rejected(self): + for mutation in ('unknown', 'missing', 'manifest'): + a, b = report(), report() + if mutation == 'unknown': b['checkpoints'][0]['K']['unlisted'] = 1 + if mutation == 'missing': del b['checkpoints'][0]['K']['speed'] + if mutation == 'manifest': b['manifest'] = {'created_at_real': 'now'} + with self.subTest(mutation=mutation): + self.assertFalse(eq.compare_reports(a, b)['ok']) + + def test_digest_alone_is_not_enough(self): + a, b = report(d(value=[2, 1])), report(d(value=[2, 2])) + self.assertFalse(eq.compare_reports(a, b)['ok']) + self.assertFalse(eq.compare_reports({'latest_digest': 'x'}, {'latest_digest': 'x'})['ok']) + + def test_timing_digest_rule(self): + a, b = report(snapshot([event()])), report(snapshot([event('/private/b', 19)])) + b['profile_root'] = profile('/private/b') + for cp in b['checkpoints']: + cp['latest_digest'] = cp['computed_latest_digest'] = 'other raw digest' + result = eq.compare_reports(a, b) + self.assertTrue(result['ok'], result) + self.assertTrue(all(m['mode'] == 'harness normalized digest' for m in result['digest_modes'])) + b['checkpoints'][0]['harness_normalized_digest'] = 'different' + self.assertFalse(eq.compare_reports(a, b)['ok']) + + def test_product_digest_self_consistency(self): + a, b = report(), report() + b['checkpoints'][0]['computed_latest_digest'] = 'bad' + self.assertFalse(eq.compare_reports(a, b)['ok']) + + def test_observation_full_layers(self): + for layer in ('S', 'K', 'C'): + a, b = report(), report() + b['checkpoints'][0]['observation']['after'][layer] = 'b'*64 + self.assertFalse(eq.compare_reports(a, b)['ok']) + + def test_event_start_and_ids(self): + a, b = report(), report() + b['event_start']['counter'] += 1 + self.assertFalse(eq.compare_reports(a, b)['ok']) + b = report(); b['event_start']['published_ids_count'] += 1 + self.assertFalse(eq.compare_reports(a, b)['ok']) + b = report() + ea, eb = event(), event() + eq._field(eb, 'event_id')[1] = 'event_2' + for r, e in ((a, ea), (b, eb)): + r['events'] = [{'sequence': 0, 'transport': transport(e), 'original_field_types': {'event_id': 21}}] + self.assertFalse(eq.compare_reports(a, b)['ok']) + + def test_violation_presence_and_difference(self): + a = report(d(unknown_ms=[2, 7])) + self.assertTrue(eq.compare_reports(a, copy.deepcopy(a))['ok']) + b = report(d(unknown_ms=[2, 8])) + self.assertFalse(eq.compare_reports(a, b)['ok']) + + def test_scenario_existing_failures_preserved(self): + a, b = report(), report() + scenario = {'id': 'E5/latest', 'operation': 'mutate_nested', 'result': {'ownership_ok': False, 'changed_paths': ['x']}, + 'checkpoints': [checkpoint(), checkpoint()], 'events': []} + a['scenarios'] = [copy.deepcopy(scenario)]; b['scenarios'] = [copy.deepcopy(scenario)] + self.assertTrue(eq.compare_reports(a, b)['ok']) + b['scenarios'][0]['result']['ownership_ok'] = True + self.assertFalse(eq.compare_reports(a, b)['ok']) + + def test_handler_sets_and_counts(self): + a, b = report(), report() + b['checkpoints'][0]['K']['_phase_handlers']['0'].reverse() + self.assertTrue(eq.compare_reports(a, b)['ok']) + b['checkpoints'][0]['K']['performance_budget']['_sample_counts']['x'] += 1 + self.assertFalse(eq.compare_reports(a, b)['ok']) + + def test_all_events_beyond_recent_window(self): + a, b = report(), report() + for i in range(300): + e = event(); eq._field(e, 'event_id')[1] = 'event_'+str(i) + a['events'].append({'sequence': i, 'transport': transport(e), 'original_field_types': {'event_id': 21}}) + b['events'] = copy.deepcopy(a['events']) + e = copy.deepcopy(b['events'][-1]['transport']['tree']) + eq._field(e, 'causation_command_id')[1] = 'changed' + b['events'][-1]['transport'] = transport(e) + result = eq.compare_reports(a, b) + self.assertFalse(result['ok']) + self.assertTrue(any(row['path'][:2] == ['events', 299] for row in result['differences'])) + + def test_event_original_types_and_order(self): + a, b = report(), report() + a['events'] = [{'sequence': 0, 'transport': transport(event()), 'original_field_types': {'event_id': 21}}] + b['events'] = copy.deepcopy(a['events']) + b['events'][0]['original_field_types']['event_id'] = 4 + self.assertFalse(eq.compare_reports(a, b)['ok']) + b['events'][0]['sequence'] = 1 + self.assertFalse(eq.compare_reports(a, b)['ok']) + + +class SourcesAndMetrics(unittest.TestCase): + def test_fixed_scenario_paths(self): + self.assertTrue(eq.validate_scenario_paths(['user://p28_eq/r/good', 'user://p28_eq/o/tampered_world'])) + for suffix in ('2026-10-21', '550e8400-e29b-41d4-a716-446655440000', 'pid123', '../good'): + with self.assertRaises(eq.EvidenceError): + eq.validate_scenario_paths(['user://p28_eq/r/'+suffix]) + + def test_source_pin_is_not_caller_controlled(self): + fake = {str(i): {'bytes': 1, 'sha256': 'a'*64} for i in range(1407)} + self.assertFalse(eq.check_source_closure(fake, fake, [])['ok']) + + def test_source_closure_synthetic_registered_map(self): + # Isolate closure logic with a synthetic pin; production constant remains + # fixed and its rejection is separately tested above. + paths = sorted(eq.OPT_PATHS) + ['synthetic/'+str(i) for i in range(1401)] + before = {p: {'bytes': 1, 'sha256': 'a'*64} for p in paths} + digest = hashlib.sha256(json.dumps(before, sort_keys=True, separators=(',', ':')).encode()).hexdigest() + with patch.object(eq, 'SOURCE_SHA', digest): + self.assertTrue(eq.check_source_closure(before, before, [])['ok']) + after = copy.deepcopy(before); after[paths[0]]['sha256'] = 'b'*64 + self.assertTrue(eq.check_source_closure(before, after, [paths[0]])['ok']) + self.assertFalse(eq.check_source_closure(before, after, [])['ok']) + self.assertFalse(eq.check_source_closure(before, before, [paths[0]])['ok']) + self.assertFalse(eq.check_source_closure(before, after, ['not_allowed'])['ok']) + after['added'] = {'bytes': 1, 'sha256': 'c'*64} + self.assertFalse(eq.check_source_closure(before, after, [paths[0]])['ok']) + after = copy.deepcopy(before); del after[paths[0]] + self.assertFalse(eq.check_source_closure(before, after, [])['ok']) + + def test_metric_ranges(self): + self.assertEqual(eq.classify_improvement([10, 11, 12], [1, 2, 3]), '改善') + self.assertEqual(eq.classify_improvement([1, 2, 3], [10, 11, 12]), '悪化') + self.assertEqual(eq.classify_improvement([1, 2, 3], [3, 4, 5]), '差は確認できない') + for bad in ([1, 2], [1, 2, float('nan')], [1, 2, {'redacted_timing': 'duration_us'}]): + with self.assertRaises(eq.EvidenceError): + eq.classify_improvement([1, 2, 3], bad) + + +import check_eq as checker +from pathlib import Path + + +def s2_report(): + value = report() + value['event_end'] = copy.deepcopy(value['event_start']) + state = snapshot() + runtime = eq._field(eq._field(state, 'systems'), 'runtime') + runtime[1].append([[4, 'id_generator'], d(counters=d(domain_event=[2, 3]))]) + events = eq._field(runtime, 'domain_events') + events[1].append([[4, 'published_ids'], arr(*([4, 'domain_event.%012d' % i] for i in range(1, 4)))]) + value['checkpoints'] = [checkpoint(state, 632+i) for i in range(31)] + for cp in value['checkpoints']: + cp['K'].update(absolute_minute=cp['minute'], paused=True, _skip_next_process=False, + _abort_current_tick_requested=False, _last_tick_advanced=True) + cp['K']['_phase_handlers'] = {str(i): [] for i in range(11)} + cp['C'].update(catalog_instance_id='123', current_catalog_instance_id='123') + cp.update(latest_digest='b'*64, computed_latest_digest='b'*64, harness_normalized_digest=None) + value['signal_order'] = [{'signal': sig, 'minute': cp['minute']} for cp in value['checkpoints'][1:] for sig in ('snapshot_published', 'state_updated')] + return value + + +def s2_event_report(): + value = s2_report() + tree = d(event_id=[4, 'domain_event.000000000004'], event_type=[4, 'TICK'], + absolute_minute=[2, 633], source_service=[4, 'world'], + entity_ids=[28, [[4, 'entity']], [[2, 4], [21, ''], [0]]], + payload=d(nested=arr(d(value=[3, '000000000000f03f']))), causation_command_id=[2, 0]) + value['events'] = [{'sequence': 0, 'transport': transport(tree), 'original_field_types': { + 'event_id': 21, 'event_type': 21, 'absolute_minute': 2, 'source_service': 21, + 'entity_ids': {'type': 28, 'typed_info': [[2, 21], [21, ''], [0]]}, + 'payload': {'type': 27, 'typed_info': None}, 'causation_command_id': 2}}] + value['event_end'] = {'counter': 4, 'published_ids_count': 4} + for cp in value['checkpoints'][1:]: + state = cp['S']['tree'] + runtime = eq._field(eq._field(state, 'systems'), 'runtime') + eq._field(eq._field(eq._field(runtime, 'id_generator'), 'counters'), 'domain_event')[1] = 4 + eq._field(eq._field(runtime, 'domain_events'), 'published_ids')[1].append([4, 'domain_event.000000000004']) + cp['S'] = transport(state) + cp['latest'] = transport(state) + return value + + +def measurement(value): + return {'probe_object': '777', 'start_minute': value['checkpoints'][0]['minute'], + 'connections': {sig: [{'object': '777', 'method': method, 'flags': 0}] + for sig, method in (('snapshot_published', 'observe_snapshot'), ('state_updated', 'observe_state'))}} + + +class S2Format(unittest.TestCase): + def valid(self, value): + result = checker.check_report(value, measurement(value)) + self.assertTrue(result['ok'], result['errors']) + self.assertFalse(result['formal_acceptance']) + + def reject(self, value): + self.assertFalse(checker.check_report(value, measurement(value))['ok']) + + def test_s2_valid_and_not_formal_acceptance(self): + self.valid(s2_report()) + self.valid(s2_event_report()) + + def test_O_cadence(self): + value = s2_report(); value['role'] = 'O' + for cp in value['checkpoints']: + cp['minute'] -= 242; cp['K']['absolute_minute'] -= 242 + for row in value['signal_order']: row['minute'] -= 242 + self.valid(value) + + def test_missing_full_state_not_digest_only(self): + for name in ('S', 'latest', 'K', 'C', 'observation'): + value = s2_report(); del value['checkpoints'][4][name] + with self.subTest(name=name): self.reject(value) + + def test_roundtrip_tree_sha_and_raw_sha(self): + for field, bad in (('roundtrip_ok', False), ('tree_sha', 'c'*64), ('raw_bytes_sha', 'bad')): + value = s2_report(); value['checkpoints'][4]['S'][field] = bad + with self.subTest(field=field): self.reject(value) + + def test_state_witness_and_observation_mutation(self): + value = s2_report(); value['checkpoints'][0]['S']['raw_bytes_sha'] = 'c'*64 + self.reject(value) + value = s2_report(); value['checkpoints'][0]['observation']['after']['K'] = 'c'*64 + self.reject(value) + + def test_guard_actual_not_assumed(self): + value = s2_report(); value['profile_root']['actual_user_data_dir'] = '/different' + self.reject(value) + + def test_counter_and_published_ids_binding(self): + for boundary in ('event_start', 'event_end'): + for key in ('counter', 'published_ids_count'): + value = s2_event_report(); value[boundary][key] += 1 + with self.subTest(boundary=boundary, key=key): self.reject(value) + + def test_event_original_field_types_mandatory(self): + for key in ('event_id', 'event_type', 'entity_ids', 'payload'): + value = s2_event_report(); del value['events'][0]['original_field_types'][key] + with self.subTest(key=key): self.reject(value) + value = s2_event_report(); value['events'][0]['original_field_types']['event_id'] = 4 + self.reject(value) + + def test_event_no_drop_duplicate_remap(self): + value = s2_event_report(); value['events'] = []; self.reject(value) + value = s2_event_report(); value['events'].append(copy.deepcopy(value['events'][0])); self.reject(value) + value = s2_event_report(); tree = value['events'][0]['transport']['tree'] + eq._field(tree, 'event_id')[1] = 'renamed' + value['events'][0]['transport'] = transport(tree); self.reject(value) + + def test_product_event_shape_and_typed_array(self): + for key, bad in (('causation_command_id', [4, '']), ('entity_ids', arr()), ('payload', arr())): + value = s2_event_report(); tree = value['events'][0]['transport']['tree'] + eq._field(tree, key)[:] = bad + value['events'][0]['transport'] = transport(tree) + with self.subTest(key=key): self.reject(value) + + def test_kernel_cache_contradictions(self): + for layer, key, bad in (('K', 'paused', 1), ('K', 'absolute_minute', 999), + ('C', 'catalog_instance_id', '456'), ('C', '_mvp_manifest_cache_bytes', '%%%')): + value = s2_report(); value['checkpoints'][0][layer][key] = bad + with self.subTest(key=key): self.reject(value) + + def test_digest_and_scenario_contradiction(self): + value = s2_report(); value['checkpoints'][0]['computed_latest_digest'] = 'c'*64; self.reject(value) + value = s2_report(); value['checkpoints'][0]['harness_normalized_digest'] = 'forged'; self.reject(value) + value = s2_report(); value['scenarios'] = [{'id': 'pretend'}]; self.reject(value) + + def test_join_is_copy_and_retains_normalization_proof(self): + value = s2_report(); original = copy.deepcopy(value) + joined, proof = checker.join_report(value) + self.assertEqual(value, original) + self.assertEqual(joined['checkpoints'][0]['harness_normalized_digest'], proof[0]['latest']['normalized_digest']) + self.assertEqual(set(proof[0]['S']['sidecar']), {'entries', 'violations', 'profile_root'}) + + def test_diff_and_same_as_S_transport(self): + value = s2_report() + for i, cp in enumerate(value['checkpoints']): + cp['latest'] = {key: v for key, v in cp['S'].items() if key != 'tree'} + cp['latest']['same_as_S'] = True + if i: + del cp['S']['tree']; cp['S']['diff'] = [] + self.valid(value) + value['checkpoints'][1]['S']['diff'] = [{'op': 'set', 'path': [], 'node': d(missing=[0])}] + self.reject(value) + + def test_raw_observation_binding(self): + import base64 + cp = s2_report()['checkpoints'][0] + row = {'kernel': cp['K'], 'cache': cp['C'], 'sha': {}} + for layer in ('S', 'K', 'C'): + row[layer] = base64.b64encode(layer.encode()).decode() + row['sha'][layer] = checker.sha(layer.encode()) + cp['observation'] = {side: copy.deepcopy(row['sha']) for side in ('before', 'after')} + evidence = {side: copy.deepcopy(row) for side in ('before', 'after')} + self.assertTrue(checker.check_observation(cp, evidence)) + evidence['after']['K'] = 'WA==' + with self.assertRaises(eq.EvidenceError): checker.check_observation(cp, evidence) + + def test_stdout_exactly_one_line(self): + text = 'guard log\nP28_02_EQ_REPORT='+json.dumps(s2_report())+'\n' + self.assertEqual(checker.read_report_stdout(text), s2_report()) + for bad in ('', text+text, 'P28_02_EQ_REPORT={\n}\n'): + with self.subTest(bad=bad[:25]), self.assertRaises((eq.EvidenceError, ValueError)): + checker.read_report_stdout(bad) + + def test_lifecycle_guard_errors_and_boundaries(self): + import base64 + value = s2_report() + guard = {'verified': True, 'actual_user_data_dir': '/private/a'} + life = {'stage': 'S2', 'errors': [], 'stop_reason': 'S2_complete_S3_pending', + 'guard': {'receipt': guard, 'live_root': '/private/a', 'sha256': 'a'*64}, + 'observer_before': {'signal': []}, 'observer_connected': {'signal': ['observer']}, + 'observer_disconnected': {'signal': []}, 'ops': {'code': 'INVALID_START_TIME'}, + 'preparation': [{'operation': 'fixture_restore', 'ok': True, 'input_sha256': + 'eb4f770071eb07cd7e136fe54c3f78768cc8de7a4264e62a9af1f06a8f90f9bd'}]} + for label, minute in (('B0', 602), ('B1', 632), ('outside', 662), ('before_main', 602), + ('after_main', 602), ('frame1', 602), ('frame2', 602)): + life[label] = {'kernel': {'paused': True, 'absolute_minute': minute}, 'sha': {}} + for layer in ('S', 'K', 'C'): + life[label][layer] = base64.b64encode(layer.encode()).decode() + life[label]['sha'][layer] = checker.sha(layer.encode()) + self.assertTrue(checker.check_lifecycle(value, life, guard)) + for key, bad in (('errors', ['roundtrip failed']), ('stop_reason', 'failed'), + ('observer_disconnected', {}), ('observer_connected', {'signal': []})): + altered = copy.deepcopy(life); altered[key] = bad + with self.subTest(key=key), self.assertRaises(eq.EvidenceError): checker.check_lifecycle(value, altered, guard) + with self.assertRaises(eq.EvidenceError): checker.check_lifecycle(value, life, {'verified': True, 'actual_user_data_dir': '/wrong'}) + + def test_normalized_digest_and_raw_tree_are_both_bound(self): + value = s2_report() + for cp in value['checkpoints']: + tree = cp['S']['tree'] + runtime = eq._field(eq._field(tree, 'systems'), 'runtime') + eq._field(eq._field(runtime, 'domain_events'), 'recent_events')[1].append(event()) + cp['S'] = transport(tree); cp['latest'] = transport(tree) + joined, proofs = checker.join_report(value) + self.assertEqual(len(proofs[0]['latest']['sidecar']['entries']), 3) + self.assertTrue(eq.compare_reports(joined, joined)['ok']) + self.assertIsNone(value['checkpoints'][0]['harness_normalized_digest']) + joined['checkpoints'][0]['harness_normalized_digest'] = 'b'*64 + with self.assertRaises(eq.EvidenceError): checker.join_report(joined) + + def test_harness_digest_allows_only_dictionary_order(self): + a = d(z=arr([3, '000000000000f03f']), a=d(x=[4, 'name'], y=[21, 'name'])) + b = copy.deepcopy(a); b[1].reverse(); b[1][0][1][1].reverse() + self.assertNotEqual(eq.tree_sha(a), eq.tree_sha(b)) + self.assertEqual(checker.normalized_digest(a), checker.normalized_digest(b)) + eq._field(eq._field(b, 'a'), 'x')[0] = 21 + self.assertNotEqual(checker.normalized_digest(a), checker.normalized_digest(b)) + with self.assertRaises(eq.EvidenceError): checker.normalized_digest([27, [[[4, 'x'], [0]], [[21, 'x'], [0]]], None]) + + +class S2Static(unittest.TestCase): + @classmethod + def setUpClass(cls): + cls.probe = Path(__file__).with_name('eq_probe.gd').read_text() + + def reject(self, text): + result = checker.check_probe(text) + self.assertFalse(result['ok'], result) + + def test_current_probe(self): + result = checker.check_probe(self.probe) + self.assertTrue(result['ok'], result['errors']) + + def test_autoload_class_and_script_import(self): + for code in ('SimulationRuntimeService.new()', 'GameClock.set_paused(true)', 'preload("res://autoload/game_state.gd")'): + with self.subTest(code=code): self.reject(self.probe+'\nfunc bad() -> void:\n\t'+code+'\n') + + def test_variant_inference(self): + self.reject(self.probe+'\nfunc bad() -> void:\n\tvar inferred := runtime.get("value")\n') + + def test_no_changes_outside_preparation_or_step(self): + for call in ('clock.set_paused(true)', 'runtime.restore_snapshot({})', 'clock.advance_minutes(1)', 'runtime.load_from_path("x")', 'runtime.reset()', 'runtime.set_script(null)', 'runtime.call("reset")', 'runtime.latest_snapshot = {}'): + with self.subTest(call=call): self.reject(self.probe+'\nfunc bad() -> void:\n\t'+call+'\n') + + def test_pause_and_step_arguments(self): + self.reject(self.probe.replace('clock.set_paused(true)', 'clock.set_paused(false)')) + self.reject(self.probe.replace('clock.advance_minutes(1)', 'clock.advance_minutes(2)')) + + def test_unlisted_live_method_and_late_preparation(self): + self.reject(self.probe+'\nfunc bad() -> void:\n\truntime.configure_something()\n') + self.reject(self.probe.replace('initial_inventory = inventory()', 'initial_inventory = inventory()\n\tclock.set_paused(true)')) + + def test_textual_stringname_ordering(self): + self.reject(self.probe.replace('names.sort_custom(func(a: Variant, b: Variant) -> bool: return str(a) < str(b))', 'names.sort()')) + self.reject(self.probe.replace('return str(a) < str(b)', 'return a < b')) + + def test_full_state_and_godot_roundtrip_required(self): + for required in ('var_to_bytes(decode(tree))', 'transport(runtime.create_snapshot())', 'before.k_bytes == after.k_bytes', 'event.to_dictionary()', 'receipt.get("actual_user_data_dir")'): + with self.subTest(required=required): self.reject(self.probe.replace(required, 'null')) + + def test_no_event_cap_or_duplicate_report(self): + self.reject(self.probe+'\nfunc bad() -> void:\n\treport.events.pop_front()\n') + self.reject(self.probe+'\nfunc bad() -> void:\n\tprint("P28_02_EQ_REPORT=" + "{}")\n') + + def test_comment_does_not_supply_proof(self): + self.reject(self.probe.replace('var rebuilt: PackedByteArray = var_to_bytes(decode(tree))', '# var rebuilt: PackedByteArray = var_to_bytes(decode(tree))')) + self.assertTrue(checker.check_probe(self.probe+'\n# GameClock.reset(); var x := 1\n')['ok']) + + +def e3_observed(tree, template): + import base64 + cp = copy.deepcopy(template) + cp['S'] = transport(tree) + cp['latest'] = transport(tree) + row = {'kernel': cp['K'], 'cache': cp['C'], 'sha': {}} + layer_trees = {'S': tree, 'K': d(value=[4, json.dumps(cp['K'], sort_keys=True)]), + 'C': d(value=[4, json.dumps(cp['C'], sort_keys=True)])} + for layer, value in layer_trees.items(): + content = eq.json_bytes(value) # Synthetic proof bytes; never Godot evidence. + row[layer] = base64.b64encode(content).decode() + row['sha'][layer] = checker.sha(content) + cp['S']['raw_bytes_sha'] = cp['latest']['raw_bytes_sha'] = row['sha']['S'] + cp['observation'] = {side: copy.deepcopy(row['sha']) for side in ('before', 'after')} + result = {'checkpoint': cp, 'raw': {side: copy.deepcopy(row) for side in ('before', 'after')}} + for layer in ('K', 'C'): + result[layer+'_tree'] = transport(layer_trees[layer]) + result[layer+'_tree']['raw_bytes_sha'] = row['sha'][layer] + return result + + +def e3_package_fixture(kind, save_ok=True): + import base64 + def file(content): + return {'bytes': base64.b64encode(content).decode(), 'sha256': checker.sha(content)} + before = {'format_version': 1, 'checksum_world': 'retained'} + after = copy.deepcopy(before) + world = b'world' + new_world = world + if kind == 'missing_key': del after['checksum_world'] + elif kind == 'wrong_type': after['format_version'] = 'x' + elif kind == 'out_of_range': after['format_version'] = 2147483647 + elif kind == 'tampered_world': new_world = world[:2]+bytes([world[2] ^ 1])+world[3:] + original = {'manifest.json': file(eq.json_bytes(before)), 'world.bin': file(world), 'thumbnail.png': None, 'journal.log': None} + modified = {'manifest.json': file(eq.json_bytes(after)), 'world.bin': file(new_world), 'thumbnail.png': None, 'journal.log': None} + result = {'save_return': transport(d(ok=[1, int(save_ok)], code=[21, 'OK' if save_ok else 'INVALID_SNAPSHOT'])), + 'original': original, 'modified': modified, 'after_operation': copy.deepcopy(modified)} + if kind == 'tampered_world': result['tamper'] = {'offset': 2, 'before': world[2], 'after': world[2] ^ 1} + return result + + +def e3_fixture(role='R'): + value = s2_report() + if role == 'O': + value['role'] = 'O' + for cp in value['checkpoints']: + cp['minute'] -= 242 + cp['K']['absolute_minute'] -= 242 + for row in value['signal_order']: row['minute'] -= 242 + b1 = copy.deepcopy(value['checkpoints'][0]['S']['tree']) + b1[1].append([[4, 'clock'], d(absolute_minute=[2, value['checkpoints'][0]['minute']], speed=[2, 1])]) + runtime = checker.node_at(b1, 'systems', 'runtime') + runtime[1].append([[4, 'facilities'], d(instances=arr(d(id=[4, 'f1'])) if role == 'R' else arr())]) + for cp in value['checkpoints']: + cp['S'] = transport(b1); cp['latest'] = transport(b1) + value['checkpoints'][-1] = e3_observed(b1, value['checkpoints'][-1])['checkpoint'] + current = copy.deepcopy(b1) + evidence = [] + for api in checker.E3_APIS: + for kind in checker.E3_KINDS: + applicable, reason, invoked = True, None, True + if kind == 'tampered_world' and api != 'load_from_path': + applicable, reason, invoked = False, 'Dictionary API does not read packages', False + elif kind == 'duplicate_facility' and role == 'O': + applicable, reason, invoked = False, 'B1 has zero facilities', False + elif kind.startswith('duplicate_') and api == 'validate': + applicable, reason = False, 'Envelope validation does not inspect runtime internals' + begin = e3_observed(current, value['checkpoints'][-1]) + actual, code, code_reason, errors, ok = [0], None, None, None, None + events, event_records, package = [], [], None + latest = d() + if api == 'restore_snapshot': + code_reason = 'API returns bool only' + if invoked: actual, ok = [1, 0], False + elif api == 'validate': + code_reason = 'API returns ok/errors only' + if invoked: + ok = not applicable + errors = [] if ok else [{'missing_key': 'missing_clock', 'wrong_type': 'invalid_absolute_minute', 'out_of_range': 'invalid_speed'}[kind]] + actual = d(ok=[1, int(ok)], errors=arr(*([4, e] for e in errors))) + elif invoked: + code = {'missing_key': 'INVALID_MANIFEST', 'wrong_type': 'INVALID_MANIFEST', 'out_of_range': 'UNSUPPORTED_FORMAT', + 'duplicate_published_ids': 'RESTORE_FAILED', 'duplicate_facility': 'RESTORE_FAILED', 'tampered_world': 'CHECKSUM_MISMATCH'}[kind] + ok = False + actual = d(ok=[1, 0], code=[21, code], preload_pause_restored=[1, 1], loaded_clock_paused=[1, 1]) + package = e3_package_fixture(kind) + package['input'] = transport(checker.e3_expected_input(b1, kind) if kind.startswith('duplicate_') else b1) + counter = checker.node_at(current, 'systems', 'runtime', 'id_generator', 'counters', 'domain_event')[1] + path = 'user://p28_eq/'+role.lower()+'/'+('duplicate_id' if kind.startswith('duplicate_') else kind) + latest = d(ok=[1, 0], code=[21, code], duration_us=[2, 1], runtime_duration_us=[2, 2], + message=[4, 'failure'], save_path=[4, path]) + event_tree = d(event_id=[4, 'domain_event.%012d' % (counter+1)], event_type=[4, 'SAVE_LOAD_FAILED'], + source_service=[4, 'save_service'], entity_ids=arr(), absolute_minute=[2, begin['checkpoint']['minute']], + payload=latest, causation_command_id=[2, 0]) + events = [event_tree]; event_records = [transport(event_tree)] + current, _ = checker.e3_x(current, event_tree) + end = e3_observed(current, value['checkpoints'][-1]) + result = {'category': kind, 'applicability': 'applied' if applicable else 'NA', 'reason': reason, 'invoked': invoked, + 'facility_count': 1 if role == 'R' else 0, 'ok': ok, 'errors': errors, 'code': code, 'code_reason': code_reason, + 'migration_attempted': False, 'event_count': len(events), + 'path': 'user://p28_eq/'+role.lower()+'/'+('duplicate_id' if kind.startswith('duplicate_') else kind) if api == 'load_from_path' else None} + id_ = 'E3/'+api+'/'+kind + value['scenarios'].append({'id': id_, 'operation': api, 'result': result, 'checkpoints': [begin['checkpoint'], end['checkpoint']], 'events': events}) + evidence.append({'id': id_, 'begin': begin, 'invocation_before': copy.deepcopy(begin), 'end': end, + 'boundaries': ['begin', 'operation', 'end'], 'input': transport(checker.e3_expected_input(b1, kind)), + 'return': transport(actual), 'package': package, 'events': event_records, 'signals': [], + 'latest_save_operation_result': transport(latest), 'save_budget_before': transport(d()), 'save_budget_after': transport(d())}) + return value, evidence, transport(b1) + + +class S3a(unittest.TestCase): + def check(self, value, evidence, b1): + return checker.check_report(value, measurement(value), evidence, b1) + + def test_exact_phase_keys(self): + for bad in ({}, {str(i): [] for i in range(10)}, {str(i): [] for i in range(12)}, + {'00': [], **{str(i): [] for i in range(11)}}, [['0', []], ['0', []]]): + value = s2_report(); value['checkpoints'][2]['K']['_phase_handlers'] = bad + with self.subTest(bad=bad): + self.assertFalse(checker.check_report(value, measurement(value))['ok']) + + def test_signals_all_minutes_and_order(self): + for mutation in ('missing', 'partial', 'duplicate', 'order', 'minute', 'scenario', 'state_only'): + value = s2_report() + rows = value['signal_order'] + if mutation == 'missing': rows.pop() + elif mutation == 'partial': del rows[2:] + elif mutation == 'duplicate': rows.extend(copy.deepcopy(rows[:2])) + elif mutation == 'order': rows[0], rows[1] = rows[1], rows[0] + elif mutation == 'minute': rows[2]['minute'] += 1 + elif mutation == 'scenario': rows.append({'signal': 'state_updated', 'minute': 662, 'scenario': 'E3'}) + else: value['signal_order'] = [r for r in rows if r['signal'] == 'state_updated'] + with self.subTest(mutation=mutation): + self.assertFalse(checker.check_report(value, measurement(value))['ok']) + + def test_probe_connection_required(self): + value = s2_report() + self.assertFalse(checker.check_report(value)['ok']) + for sig in ('snapshot_published', 'state_updated'): + inventory = measurement(value); inventory['connections'][sig] = [] + self.assertFalse(checker.check_report(value, inventory)['ok']) + inventory = measurement(value); inventory['probe_object'] = '999' + self.assertFalse(checker.check_report(value, inventory)['ok']) + + def test_e3_valid_R_and_O_records(self): + for role in ('R', 'O'): + args = e3_fixture(role) + checked = self.check(*args) + self.assertTrue(checked['ok'], checked['errors']) + self.assertEqual(len(checked['e3']), 18) + self.assertTrue(all(not row['defects'] for row in checked['e3']), checked['e3']) + self.assertFalse(checked['formal_acceptance']) + + def test_e3_invented_codes_and_missing_load_code(self): + for index in (0, 6, 12): + value, evidence, b1 = e3_fixture() + value['scenarios'][index]['result']['code'] = 'INVENTED' if index < 12 else None + self.assertFalse(self.check(value, evidence, b1)['ok']) + value, evidence, b1 = e3_fixture() + actual = evidence[12]['return']['tree'] + actual[1] = [pair for pair in actual[1] if pair[0][1] != 'code'] + evidence[12]['return'] = transport(actual) + self.assertFalse(self.check(value, evidence, b1)['ok']) + + def test_e3_NA_cannot_be_PASS_or_applied(self): + for index in (5, 9, 10): + value, evidence, b1 = e3_fixture() + value['scenarios'][index]['result']['applicability'] = 'PASS' + self.assertFalse(self.check(value, evidence, b1)['ok']) + value, evidence, b1 = e3_fixture('O') + value['scenarios'][4]['result'].update(applicability='applied', invoked=True, reason=None) + self.assertFalse(self.check(value, evidence, b1)['ok']) + + def test_envelope_duplicates_not_defect(self): + args = e3_fixture() + checked = self.check(*args) + self.assertTrue(checked['ok'], checked['errors']) + for index in (9, 10): + self.assertEqual(checked['e3'][index]['status'], 'NA') + self.assertEqual(checked['e3'][index]['defects'], []) + + def test_e3_coverage_input_and_event_count_binding(self): + value, evidence, b1 = e3_fixture() + value['scenarios'].pop() + self.assertFalse(self.check(value, evidence, b1)['ok']) + value, evidence, b1 = e3_fixture() + evidence[0]['input'] = copy.deepcopy(b1) + self.assertFalse(self.check(value, evidence, b1)['ok']) + value, evidence, b1 = e3_fixture() + value['scenarios'][12]['result']['event_count'] = 0 + self.assertFalse(self.check(value, evidence, b1)['ok']) + + def test_rejection_mutation_retained_as_defect(self): + value, evidence, b1 = e3_fixture() + changed = copy.deepcopy(evidence[0]['end']['checkpoint']['S']['tree']) + checker.node_at(changed, 'value')[1].append([4, 'unauthorized']) + end = e3_observed(changed, value['checkpoints'][-1]) + evidence[0]['end'] = end + value['scenarios'][0]['checkpoints'][1] = end['checkpoint'] + evidence[1]['begin'] = copy.deepcopy(end) + value['scenarios'][1]['checkpoints'][0] = copy.deepcopy(end['checkpoint']) + checked = self.check(value, evidence, b1) + self.assertTrue(checked['ok'], checked['errors']) + self.assertEqual(checked['e3'][0]['status'], 'existing-defect-candidate') + self.assertIn('S_changes', [d['kind'] for d in checked['e3'][0]['defects']]) + + def test_invalid_input_accepted_is_not_PASS(self): + value, evidence, b1 = e3_fixture() + value['scenarios'][0]['result']['ok'] = True + evidence[0]['return'] = transport([1, 1]) + checked = self.check(value, evidence, b1) + self.assertTrue(checked['ok'], checked['errors']) + self.assertEqual(checked['e3'][0]['defects'][0]['kind'], 'invalid_input_accepted') + + def test_package_fixed_mutations_and_hashes(self): + for kind in checker.E3_KINDS: + package = e3_package_fixture(kind) + self.assertTrue(checker.e3_package_check(package, kind)) + package['modified']['world.bin']['sha256'] = '0'*64 + with self.assertRaises(eq.EvidenceError): checker.e3_package_check(package, kind) + package = e3_package_fixture('tampered_world'); package['tamper']['offset'] = 0 + with self.assertRaises(eq.EvidenceError): checker.e3_package_check(package, 'tampered_world') + + def test_X_recent_limit_and_counter(self): + value, evidence, b1 = e3_fixture() + before = copy.deepcopy(b1['tree']) + ev = value['scenarios'][12]['events'][0] + recent = checker.node_at(before, 'systems', 'runtime', 'domain_events', 'recent_events') + recent[1] = [copy.deepcopy(ev) for _ in range(256)] + after, dropped = checker.e3_x(before, ev) + self.assertEqual(dropped, ev) + self.assertEqual(len(checker.node_at(after, 'systems', 'runtime', 'domain_events', 'recent_events')[1]), 256) + self.assertEqual(checker.node_at(after, 'systems', 'runtime', 'id_generator', 'counters', 'domain_event'), [2, 4]) + + def test_scenario_mutation_static_boundary(self): + text = Path(__file__).with_name('eq_probe.gd').read_text() + for call in ('SimulationSnapshot.validate({})', 'SaveService.save_snapshot("x", {})', 'run_e3()', 'e3_prepare_package("x", {}, "x")'): + self.assertFalse(checker.check_probe(text+'\nfunc illegal() -> void:\n\t'+call+'\n')['ok']) + + + def test_duplicate_JSON_key_rejected(self): + with self.assertRaises(eq.EvidenceError): + checker.read_report_stdout('P28_02_EQ_REPORT={"_phase_handlers":{"0":[],"0":[]}}') + with self.assertRaises(eq.EvidenceError): + checker.strict_json('{"x":1,"x":2}') + + def test_operation_moved_outside_scenario_rejected(self): + text = Path(__file__).with_name('eq_probe.gd').read_text() + text = text.replace('scenario_active = true', 'scenario_active = false').replace('scenario_active = false\n\t\t\tvar code', 'scenario_active = true\n\t\t\tvar code') + self.assertFalse(checker.check_probe(text)['ok']) + + def test_event_count_defect_not_silently_accepted(self): + value, evidence, b1 = e3_fixture() + scenario = value['scenarios'][12] + scenario['events'] = []; scenario['result']['event_count'] = 0 + evidence[12]['events'] = [] + checked = self.check(value, evidence, b1) + self.assertTrue(checked['ok'], checked['errors']) + self.assertIn('event_count', [d['kind'] for d in checked['e3'][12]['defects']]) + + def test_save_refusal_makes_load_NA(self): + value, evidence, b1 = e3_fixture() + i = 15 + before = copy.deepcopy(evidence[i]['begin']) + result = value['scenarios'][i]['result'] + result.update(applicability='NA', reason='SaveService.save_snapshot refused duplicate input', + invoked=False, ok=None, code=None, event_count=0) + value['scenarios'][i]['events'] = [] + value['scenarios'][i]['checkpoints'][1] = copy.deepcopy(before['checkpoint']) + evidence[i].update(end=copy.deepcopy(before), events=[], **{'return': transport([0])}) + evidence[i]['package'] = e3_package_fixture('duplicate_published_ids', save_ok=False) + evidence[i]['package']['input'] = transport(checker.e3_expected_input(b1['tree'], 'duplicate_published_ids')) + # Keep next baseline explicit; subsequent actual changes remain candidates. + evidence[i+1]['begin'] = copy.deepcopy(before) + value['scenarios'][i+1]['checkpoints'][0] = copy.deepcopy(before['checkpoint']) + checked = self.check(value, evidence, b1) + self.assertTrue(checked['ok'], checked['errors']) + self.assertEqual(checked['e3'][i]['status'], 'NA') + + def test_load_payload_and_pause_outcome(self): + value, evidence, b1 = e3_fixture() + actual = evidence[12]['return']['tree'] + checker.node_at(actual, 'preload_pause_restored')[1] = 0 + evidence[12]['return'] = transport(actual) + checked = self.check(value, evidence, b1) + self.assertTrue(checked['ok'], checked['errors']) + self.assertIn('load_pause_outcome', [d['kind'] for d in checked['e3'][12]['defects']]) + + def test_interval_gap_rejected(self): + value, evidence, b1 = e3_fixture() + evidence[1]['begin'] = copy.deepcopy(evidence[12]['end']) + value['scenarios'][1]['checkpoints'][0] = evidence[1]['begin']['checkpoint'] + self.assertFalse(self.check(value, evidence, b1)['ok']) + + +def e45_fixture(role='R'): + raw, e3, b1 = e3_fixture(role) + tree = copy.deepcopy(e3[-1]['end']['checkpoint']['S']['tree']) + runtime = checker.node_at(tree, 'systems', 'runtime') + runtime[1].append([[4, 'world'], d(bounds=d(min_x=[2, 0], max_x=[2, 0], min_y=[2, 0], max_y=[2, 0]))]) + template = copy.deepcopy(e3[-1]['end']['checkpoint']) + def observed(t, minute): + cp = copy.deepcopy(template) + cp['minute'] = minute; cp['K']['absolute_minute'] = minute + return e3_observed(t, cp) + previous = observed(tree, template['minute']) + current = copy.deepcopy(previous) + evidence = [] + def emit(ident, op, obs, detail, events=()): + detail['signals'] = [] + result = {'event_count': len(events), 'applicability': detail.get('applicability', 'applied'), + 'reason': detail.get('reason'), 'facts': checker.e45_facts(detail)} + raw['scenarios'].append({'id': ident, 'operation': op, 'result': result, + 'checkpoints': [o['checkpoint'] for o in obs], 'events': list(events)}) + evidence.append({'id': ident, 'boundaries': ['begin', 'operation', 'end'], 'observations': obs, + 'detail': detail, 'events': [transport(e) for e in events], 'signals': []}) + for op in checker.E4_PATHS: + begin = copy.deepcopy(current); minute = begin['checkpoint']['minute'] + detail = {}; obs = [begin]; events = [] + if op == 'build_facility': + ids = [28, [[21, 'a']], [[2, 21], [21, ''], [0]]] + detail = {'source': 'definition_registry.get_facility_ids()', 'raw_ids': transport(ids), 'count': 1, + 'sorted_ids': transport(ids), 'sort_rule': checker.SORT_RULE, 'cell_rule': checker.CELL_RULE, + 'bounds': transport(checker.node_at(tree, 'systems', 'runtime', 'world', 'bounds')), + 'chosen': None, 'trials': [], 'applicability': 'NA', + 'reason': 'all registry/cell pairs rejected by public preview', + 'observation_before': copy.deepcopy(begin), 'observation_after': copy.deepcopy(begin)} + for z in (0, 1): + detail['trials'].append({'candidate': transport(d(definition_id=[21, 'a'], origin=[10, [[2, 0], [2, 0], [2, z]]], rotation=[2, 0])), + 'preview': transport(d(can_build=[1, 0], error_codes=arr([4, 'blocked'])))}) + elif op == 'tick': + minute += 1 + elif op == 'restore_snapshot': + detail = {'input': transport(tree), 'return': transport([1, 1])} + elif op == 'load_from_path': + ev = event(raw['profile_root']['root']) + # Match the next identity required by X(P,event). + counter = checker.counts(tree)[0]['counter'] + checker.node_at(ev, 'event_id')[1] = 'event_'+str(counter+1) + detail = {'input': transport(tree), 'return': transport(d(ok=[1, 1], code=[4, 'OK'])), + 'path': 'user://p28_eq/'+role.lower()+'/good'} + package = e3_package_fixture('duplicate_published_ids') + detail.update(save_return=package['save_return'], package_before=package['original'], package_after=package['original'], latest_save_operation_result=transport(checker.node_at(ev, 'payload'))) + tree, _ = checker.e3_x(tree, ev) + events = [ev] + else: + detail = {'submit': transport(d(command_id=[2, 1], code=[4, 'NOT_FOUND'])), + 'command_result': transport(d(command_id=[2, 1], code=[4, 'NOT_FOUND']))} + obs.append(copy.deepcopy(begin)); minute += 1 + detail.update(save_budget_before=transport(d(_samples=d(), _totals=d(), _sample_counts=d())), + save_budget_after=transport(d(_samples=d(), _totals=d(), _sample_counts=d()))) + current = observed(tree, minute); obs.append(copy.deepcopy(current)) + emit('E4/'+op, op, obs, detail, events) + for target in checker.E5_TARGETS: + for location in ('dict', 'array'): + for direction in ('outside_in', 'inside_out'): + begin = copy.deepcopy(current); minute = begin['checkpoint']['minute']+1 + baseline = observed(tree, minute) + held = copy.deepcopy(tree); after_held = copy.deepcopy(held) + if direction == 'outside_in': + if location == 'dict': + checker.node_at(after_held, 'systems', 'runtime', 'id_generator', 'counters')[1].append([[4, '__p28_eq_probe'], [2, 1]]) + else: + checker.node_at(after_held, 'systems', 'runtime', 'domain_events', 'published_ids')[1].append([4, '__p28_eq_probe']) + else: + minute += 1 + post = observed(tree, minute) + if direction == 'outside_in' and target != 'create_snapshot': + post['checkpoint']['latest'] = transport(after_held) + post['checkpoint']['computed_latest_digest'] = 'c'*64 + current = observed(tree, minute+1) + detail = {'target': target, 'location': location, 'direction': direction, 'digest_materialized_before': True, + 'held_before': transport(held), 'held_after': transport(after_held)} + emit('E5/'+target+'/'+location+'/'+direction, direction, [begin, baseline, post, copy.deepcopy(current)], detail) + return raw, evidence, previous + + +class S3b(unittest.TestCase): + def checked(self, value=None): + raw, evidence, previous = e45_fixture() if value is None else value + return checker.check_e45(raw, evidence, previous) + + def reject(self, mutate): + value = e45_fixture() + mutate(*value) + with self.assertRaises((eq.EvidenceError, KeyError, ValueError, TypeError)): + self.checked(value) + + def test_all_paths_and_ownership_R_O(self): + for role in ('R', 'O'): + outcomes = self.checked(e45_fixture(role)) + self.assertEqual(len(outcomes), 21) + self.assertEqual(sum(o['status'] == 'existing-defect' for o in outcomes), 6) + self.assertEqual(outcomes[0]['status'], 'NA') + self.assertNotIn('PASS', str(outcomes)) + + def test_missing_path_and_combination(self): + for i in (0, 4, 5, 20): + self.reject(lambda r, e, p: e.pop(i)) + + def test_path_order(self): + self.reject(lambda r, e, p: e.reverse()) + + def test_interval_gap(self): + self.reject(lambda r, e, p: e[1]['observations'][0]['raw']['before']['sha'].update(S='0'*64)) + + def test_event_count_mismatch(self): + self.reject(lambda r, e, p: r['scenarios'][21]['result'].update(event_count=0)) + + def test_load_extra_event(self): + def mutate(r, e, p): + e[3]['events'].append(copy.deepcopy(e[3]['events'][0])) + r['scenarios'][21]['events'].append(copy.deepcopy(r['scenarios'][21]['events'][0])) + r['scenarios'][21]['result']['event_count'] = 2 + self.reject(mutate) + + def test_restore_extra_event(self): + def mutate(r, e, p): + e[2]['events'] = copy.deepcopy(e[3]['events']) + r['scenarios'][20]['events'] = [e[2]['events'][0]['tree']] + r['scenarios'][20]['result']['event_count'] = 1 + self.reject(mutate) + + def test_load_X_not_digest_only(self): + self.reject(lambda r, e, p: e[3]['detail'].update(input=transport(snapshot()))) + + def test_aliasing_cannot_be_PASS(self): + self.reject(lambda r, e, p: r['scenarios'][27]['result'].update(status='PASS')) + + def test_aliasing_missing_record(self): + self.reject(lambda r, e, p: e[9]['detail'].pop('held_after')) + + def test_nested_mutation_required(self): + self.reject(lambda r, e, p: e[5]['detail'].update(held_after=e[5]['detail']['held_before'])) + + def test_digest_materialization_required(self): + self.reject(lambda r, e, p: e[5]['detail'].update(digest_materialized_before=False)) + + def test_NA_not_PASS(self): + self.reject(lambda r, e, p: r['scenarios'][18]['result'].update(applicability='PASS')) + + def test_wrong_registry_in_either_role(self): + for role in ('R', 'O'): + r, e, p = e45_fixture(role) + e[0]['detail']['source'] = 'mvp_content_catalog' + with self.assertRaises(eq.EvidenceError): + checker.check_selection(e[0]['detail'], p['checkpoint']['S']['tree']) + + def test_empty_registry_not_NA(self): + r, e, p = e45_fixture() + detail = e[0]['detail'] + detail.update(raw_ids=transport(arr()), sorted_ids=transport(arr()), count=0, trials=[]) + with self.assertRaises(eq.EvidenceError): + checker.check_selection(detail, p['checkpoint']['S']['tree']) + + def test_missing_trial(self): + r, e, p = e45_fixture() + e[0]['detail']['trials'].pop() + with self.assertRaises(eq.EvidenceError): + checker.check_selection(e[0]['detail'], p['checkpoint']['S']['tree']) + + def test_sort_rule_rejected(self): + r, e, p = e45_fixture() + e[0]['detail']['sort_rule'] = 'registration order' + with self.assertRaises(eq.EvidenceError): + checker.check_selection(e[0]['detail'], p['checkpoint']['S']['tree']) + + def test_unpreviewed_choice(self): + r, e, p = e45_fixture() + e[0]['detail'].update(chosen=e[0]['detail']['trials'][0]['candidate'], applicability='applied', reason=None) + with self.assertRaises(eq.EvidenceError): + checker.check_selection(e[0]['detail'], p['checkpoint']['S']['tree']) + + def test_first_placeable_choice(self): + r, e, p = e45_fixture() + detail = e[0]['detail']; trial = detail['trials'][0] + trial['preview'] = transport(d(can_build=[1, 1])) + detail.update(trials=[trial], chosen=trial['candidate'], applicability='applied', reason=None, + submit=transport(d(command_id=[2, 1], code=[4, 'OK'])), + command_result=transport(d(command_id=[2, 1], code=[4, 'OK']))) + self.assertTrue(checker.check_selection(detail, p['checkpoint']['S']['tree'])) + + def test_no_staleness_assertion_for_non_tick(self): + out = self.checked() + self.assertIn('publication timing is not cache staleness', out[2]['latest_policy']) + self.reject(lambda r, e, p: e[2]['detail'].update(cache_stale=True)) + + def test_static_handler_and_outside_mutations(self): + text = Path(__file__).with_name('eq_probe.gd').read_text() + for changed in (text.replace('record_signal("state_updated")', '_snapshot["bad"] = 1\n\trecord_signal("state_updated")'), + text+'\nfunc bad() -> void:\n\truntime.submit_command(&"build_facility", {})\n', + text+'\nfunc bad() -> void:\n\te4_candidates()\n', + text.replace('scenario_active = true\n\t\tif operation', 'scenario_active = false\n\t\tif operation')): + self.assertFalse(checker.check_probe(changed)['ok']) + + def test_facts_normalization_is_reversible(self): + r, e, p = e45_fixture() + facts = r['scenarios'][-1]['result']['facts'] + normal, proofs = checker.join_facts(facts, r['profile_root']) + self.assertTrue(proofs) + self.assertEqual(checker.join_facts(copy.deepcopy(facts), r['profile_root'])[0], normal) + self.assertIn('tree_sha', facts['held_before']) + + def test_E5_cached_digest_defect_is_comparable(self): + value = report() + cps = [checkpoint(minute=i) for i in range(4)] + cps[2]['computed_latest_digest'] = 'post-alias' + value['scenarios'] = [{'id': 'E5/latest_snapshot/dict/outside_in', 'operation': 'outside_in', + 'result': {}, 'checkpoints': cps, 'events': []}] + checked = eq.compare_reports(value, copy.deepcopy(value)) + self.assertTrue(checked['ok'], checked) + value['scenarios'][0]['id'] = 'E4/tick' + self.assertFalse(eq.compare_reports(value, value)['ok']) + + + + def test_joined_s3b_self_comparison(self): + raw, evidence, previous = e45_fixture() + joined, proofs = checker.join_report(raw) + result = eq.compare_reports(joined, copy.deepcopy(joined)) + self.assertTrue(result['ok'], result['errors']) + self.assertTrue(any('facts' in p for p in proofs)) + + def test_missing_preview_observation(self): + self.reject(lambda r, e, p: e[0]['detail'].pop('observation_after')) + + def test_signal_facts_cannot_be_dropped(self): + self.reject(lambda r, e, p: e[1]['signals'].append({'signal': 'snapshot_published', 'minute': e[1]['observations'][0]['checkpoint']['minute']})) + + def test_digest_defect_other_checkpoint_still_rejected(self): + value = report() + cps = [checkpoint(minute=i) for i in range(4)] + cps[1]['computed_latest_digest'] = 'bad' + value['scenarios'] = [{'id': 'E5/latest_snapshot/dict/outside_in', 'operation': 'outside_in', + 'result': {}, 'checkpoints': cps, 'events': []}] + self.assertFalse(eq.compare_reports(value, value)['ok']) + + + def test_ownership_fact_dictionary_order_fallback(self): + a = report() + a['scenarios'] = [{'id': 'E5/latest_snapshot/dict/inside_out', 'operation': 'inside_out', + 'result': {'facts': {'held_before': d(a=[2, 1], b=[2, 2])}}, + 'checkpoints': [checkpoint()], 'events': []}] + b = copy.deepcopy(a) + b['scenarios'][0]['result']['facts']['held_before'][1].reverse() + result = eq.compare_reports(a, b) + self.assertTrue(result['ok'], result['differences']) + self.assertTrue(result['dict_order_paths']) + b['scenarios'][0]['result']['facts']['held_before'][1][0][1] = [2, 99] + self.assertFalse(eq.compare_reports(a, b)['ok']) + +import os +import tempfile +import base64 +import run_eq as driver +import verify_eq as verifier + + +def synthetic_directory(): + base = Path(os.environ.get('BUILD_OUTPUT_DIR', tempfile.gettempdir())).resolve() + eq.require(not base.is_relative_to(verifier.ROOT), 'synthetic bundle must be outside checkout') + return tempfile.TemporaryDirectory(prefix='eq-synthetic-not-native-', dir=base) + + +def s4_report_fixture(role): + """Join historical synthetic fixtures, preserving all 119 historical test bodies.""" + raw, e45, previous = e45_fixture(role) + e3raw, e3, b1 = e3_fixture(role) + world = copy.deepcopy(checker.node_at(previous['checkpoint']['S']['tree'], 'systems', 'runtime', 'world')) + def add_world(value): + if isinstance(value, dict): + if 'tree' in value and isinstance(value['tree'], list): + tree = value['tree'] + try: + runtime = checker.node_at(tree, 'systems', 'runtime') + except (eq.EvidenceError, KeyError): + runtime = None + if runtime is not None: + if 'world' not in checker.fields(runtime): + runtime[1].append([[4, 'world'], copy.deepcopy(world)]) + value['tree_sha'] = eq.tree_sha(tree) + for child in value.values(): add_world(child) + elif isinstance(value, list): + for child in value: add_world(child) + add_world(e3raw); add_world(e3); add_world(b1) + for i, cp in enumerate(e3raw['checkpoints']): + e3raw['checkpoints'][i] = e3_observed(cp['S']['tree'], cp)['checkpoint'] + for i, ev in enumerate(e3): + for key in ('begin', 'invocation_before', 'end'): + cp = ev[key]['checkpoint'] + ev[key] = e3_observed(cp['S']['tree'], cp) + e3raw['scenarios'][i]['checkpoints'] = [ev['begin']['checkpoint'], ev['end']['checkpoint']] + raw['checkpoints'] = e3raw['checkpoints'] + raw['scenarios'][:18] = e3raw['scenarios'] + return raw, e3, b1, e45 + + +def s4_phase_fixture(directory, phase='R-A', pid=101): + role = verifier.ROLES[phase] + raw, e3, b1, e45 = s4_report_fixture(role) + runtime_name = phase+'-runtime' + root = '/private/'+runtime_name + raw['profile_root'] = profile(root) + guard = {'verified': True, 'conditions': [True]*5, 'conditions_checked': 5, + 'actual_user_data_dir': root, 'expected_user_data_dir': root, + 'globalized_probe': root+'/guard-probe', 'custom_user_dir_name': runtime_name, + 'fresh_before_parent_initialize': True, 'profile_writes_before_guard': 0, + 'project_settings_persisted': False} + guard_path = directory/(phase+'-guard.json') + verifier.write(guard_path, guard) + life = {'stage': 'S3b', 'errors': [], 'stop_reason': 'S3b_complete_S4_pending', + 'guard': {'receipt': guard, 'live_root': root, 'sha256': verifier.sha(guard_path), 'path': str(guard_path)}, + 'observer_before': {}, 'observer_connected': {'probe': True}, 'observer_disconnected': {}, + 'ops': {'code': 'INVALID_START_TIME'} if role == 'R' else {'ok': True}, + 'preparation': [{'operation': 'fixture_restore', 'ok': True, 'input_sha256': + 'eb4f770071eb07cd7e136fe54c3f78768cc8de7a4264e62a9af1f06a8f90f9bd'}], + 'measurement': measurement(raw), 'e3': e3, 'e3_b1': b1, 'e45': e45} + start = 602 if role == 'R' else 360 + for label, minute in [('B0', start), ('B1', start+30), ('outside', start+60), + ('before_main', start), ('after_main', start), ('frame1', start), ('frame2', start)]: + life[label] = {'kernel': {'paused': True, 'absolute_minute': minute}, 'sha': {}} + for layer in ('S', 'K', 'C'): + life[label][layer] = base64.b64encode(layer.encode()).decode() + life[label]['sha'][layer] = checker.sha(layer.encode()) + folder = directory/phase + folder.mkdir() + evidence = folder/'evidence'; evidence.mkdir() + (folder/'stdout.log').write_text('P28_02_EQ_REPORT='+json.dumps(raw)+'\n') + verifier.write(evidence/'report.json', raw) + verifier.write(evidence/'events.json', raw['events']) + for i, cp in enumerate(raw['checkpoints']): + verifier.write(evidence/f'checkpoint-{i:02d}.json', cp) + verifier.write(evidence/f'observation-{i:02d}.json', e3_observed(cp['S']['tree'], cp)['raw']) + for prefix, values in [('e3', e3), ('e45', e45)]: + for i, value in enumerate(values): verifier.write(evidence/f'{prefix}-{i:02d}.json', value) + life['files'] = [dict(path='evidence/'+n, **p) for n, p in verifier.inventory(evidence).items()] + verifier.write(evidence/'lifecycle.json', life) + audio = {'coordinator': True, 'passed': True, 'owned_engine_pid': pid, 'all_owned_targets_released': True, + 'deadline_reached': False, 'clock_process_held_stopped': True, 'window_input_held_disabled': True, + 'restored_before_quit': False, 'shared_bus_deleted': False, 'settings_mutated': False} + verifier.write(evidence/'audio-close.json', audio) + return {'phase': phase, 'role': role, 'pid': pid, 'runtime_profile': root, 'runtime_name': runtime_name, + 'guard': guard, 'guard_sha256': verifier.sha(guard_path), + 'environment': {'THE_TREE_PACK_PROFILE_REPORT': str(guard_path)}, + 'evidence_files': verifier.inventory(evidence)} + + +def s4_owned_fixture(directory, item, pid): + phase = item['phase']; folder = directory/phase + folder.mkdir(exist_ok=True) + for name in ('stdout.log', 'stderr.log', 'engine-native.log'): + if not (folder/name).exists(): (folder/name).write_text('') + raw = {n: verifier.pin(folder/n) for n in ('stdout.log', 'stderr.log', 'engine-native.log')} + argv = item['argv']+['--log-file', str(folder/'engine-native.log'), '--verbose'] + binding = {'pid': pid, 'actual_pid': pid, 'argv': argv, 'command': argv, 'owner_pid': 10, 'monotonic_ns': 1} + start, end = dict(binding, event='ENGINE_STARTED'), dict(binding, event='ENGINE_ENDED', monotonic_ns=2) + cleanup = {'engine_ended': True, 'errors': []} + process = {'pid': pid, 'argv': argv, 'exit_code': 0, 'helper_exit_code': 0, 'timed_out': False, + 'error_lines': [], 'lifecycle_error': None, 'external_process_or_group_signals': 0, + 'owned_popen_ended': True, 'old_helper_engine_ended': True, 'start_receipt_written': True, + 'end_receipt_written': True, 'actual_start_binding': start, 'actual_end_binding': end, + 'adapter_owned_cleanup': cleanup, 'stdout_sha256': raw['stdout.log']['sha256'], + 'stderr_sha256': raw['stderr.log']['sha256']} + capture = {'passed': True, 'all_captured_ended': True, 'outer_cleanup_errors': [], 'adapter_exception': None, + 'foreign_process_or_group_signals': 0, 'all_cleanup_before_outer_receipt': True, + 'outer_receipt_written': True, 'outer_receipt_error': None, 'actual_captured_pids': [pid]} + for name, value in [('process.json', process), ('started.json', start), ('ended.json', end), + ('adapter-owned-cleanup.json', cleanup), ('outer-owned-finally.json', + {k: v for k, v in capture.items() if k not in ('passed', 'outer_receipt_written', 'outer_receipt_error')})]: + verifier.write(folder/name, value) + return {'passed': True, 'process': process, 'capture': capture, 'raw': raw, 'argv': argv, + 'timeout_seconds': 1800, 'diagnostics': [], 'owned_files': {n: verifier.pin(folder/n) for n in + ('process.json', 'started.json', 'ended.json', 'adapter-owned-cleanup.json', 'outer-owned-finally.json')}} + + +def s4_bundle_fixture(directory, collector, standard): + """Synthetic receipts only. Production validators are real; no Godot claim.""" + source = collector.source_map(standard, verifier.ROOT) + for name in ('eq_probe.gd',): (directory/name).write_bytes((verifier.HERE/name).read_bytes()) + (directory/'profile_guard.gd').write_text('synthetic guard bytes') + (directory/'guarded.gd').write_text(driver.wrapper_text(directory)) + verifier.write(directory/'root-input-manifest.json', {'synthetic_not_native': True}) + pins = {'worker': {'eq_probe.gd': verifier.sha(directory/'eq_probe.gd')}, + 'readonly': {'files': {'run-r02/profile_guard.gd': verifier.sha(directory/'profile_guard.gd')}, + 'manifest_sha256': verifier.sha(directory/'root-input-manifest.json')}} + commands = [collector.argv_for(Path('/synthetic/Godot'), directory/'stage', directory/'guarded.gd', True), + collector.parse_argv(Path('/synthetic/Godot'), directory/'stage', directory/'eq_probe.gd'), + collector.parse_argv(Path('/synthetic/Godot'), directory/'stage', directory/'guarded.gd')] + [ + ['/synthetic/Godot', '--headless', '--path', str(directory/'stage'), '--script', str(directory/'guarded.gd')] + for _ in range(4)] + plan, rows, retained, cleanup = [], [], {}, [] + for i, phase in enumerate(verifier.PHASES): + pid = 100+i; role = verifier.ROLES.get(phase) + item = {'phase': phase, 'role': role, 'argv': commands[i], 'folder': str(directory/phase), + 'startup_name': phase+'-startup', 'startup_profile': '/private/'+phase+'-startup', + 'runtime_name': phase+'-runtime', 'runtime_profile': '/private/'+phase+'-runtime'} + env = {'THE_TREE_PACK_PROFILE_NAME': item['runtime_name'], 'THE_TREE_PACK_PROFILE_EXPECTED': item['runtime_profile'], + 'THE_TREE_PACK_PROFILE_REPORT': str(directory/(phase+'-guard.json')), 'THE_TREE_EQ_ROLE': role or '', + 'THE_TREE_P28_FIXTURE': '/synthetic/fixture', 'THE_TREE_P28_FIXTURE_SHA': collector.FIXTURE_SHA} + item['environment'] = env; plan.append(item) + row = s4_phase_fixture(directory, phase, pid) if role else {'phase': phase, 'role': None, 'pid': pid} + row.update(s4_owned_fixture(directory, item, pid), environment=env, stage_inventory=source, + source_preserved=True, player_preserved=True) + startup = directory/(phase+'-startup-project.godot') + startup.write_bytes(standard.private_project((verifier.ROOT/'project.godot').read_bytes(), item['startup_name'])) + row['startup_project'] = {'name': item['startup_name'], 'profile': item['startup_profile'], 'fresh_before': True, + 'sha256': verifier.sha(startup), 'restored_sha256': source['project.godot']['sha256']} + row['profile_copies'] = {'startup': {'exists': False, 'files': {}}, 'runtime': {'exists': False, 'files': {}}} + if role: + import shutil + target = directory/phase/'runtime-profile'; target.mkdir() + shutil.copytree(directory/phase/'evidence', target/'evidence') + row['profile_copies']['runtime'] = {'exists': True, 'files': verifier.inventory(target)} + for kind in ('startup', 'runtime'): retained[item[kind+'_profile']] = row['profile_copies'][kind]['files'] + rows.append(row) + cleanup.append({'pid': pid, 'engine_ended': True, 'outer_cleanup_errors': [], 'foreign_process_or_group_signals': 0}) + admission = {'source_map': source, 'phases': verifier.PHASES, 'plan': plan, 'pins': pins, + 'measured_source': 'S_eq-native-not-Q', 'candidate_Q_measured': False, + 'readonly_path': '/synthetic/readonly', 'fixture': '/synthetic/fixture', 'engine': '/synthetic/Godot'} + verifier.write(directory/'admission.json', admission) + return {'passed': True, 'error': None, 'cleanup_errors': [], 'cleanup': cleanup, 'admission': admission, + 'source_after': source, 'player_before': {}, 'player_after': {}, 'pins_after': pins, + 'phases': rows, 'profiles_retained': retained} + + +class S4Bundle(unittest.TestCase): + def test_synthetic_phase_all_real_checkers_not_native_proof(self): + with synthetic_directory() as name: + directory = Path(name) + row = s4_phase_fixture(directory) + result = verifier.phase_evidence(directory, row) + self.assertTrue(result['checker']['ok']) + self.assertNotEqual(result['raw'], result['joined']) + self.assertTrue(result['proofs']) + self.assertTrue(any(o['status'] == 'existing-defect' for o in result['checker']['e45'])) + + def test_seal_normal_and_changes_not_native_proof(self): + with synthetic_directory() as name: + directory = Path(name) + verifier.write(directory/'raw.json', {'synthetic_not_native': True}) + verifier.seal(directory); verifier.check_seal(directory) + with self.assertRaises(eq.EvidenceError): verifier.seal(directory) + (directory/'extra').write_text('after seal') + with self.assertRaises(eq.EvidenceError): verifier.check_seal(directory) + + def test_missing_bundle_manifest_seal_and_changed_bytes(self): + for kind in ('bundle.json', 'seal.json', 'raw.json', 'changed'): + with self.subTest(kind=kind), synthetic_directory() as name: + directory = Path(name) + verifier.write(directory/'raw.json', {}) + verifier.seal(directory) + if kind == 'changed': (directory/'raw.json').write_text('changed') + else: (directory/kind).unlink() + with self.assertRaises((OSError, eq.EvidenceError)): verifier.check_seal(directory) + + def test_missing_private_evidence_and_extra_rejected(self): + for filename in ('lifecycle.json', 'audio-close.json', 'e3-17.json', 'e45-20.json', 'extra.json'): + with self.subTest(filename=filename), synthetic_directory() as name: + directory = Path(name); row = s4_phase_fixture(directory) + file = directory/'R-A'/'evidence'/filename + if filename == 'extra.json': file.write_text('{}') + else: file.unlink() + with self.assertRaises(eq.EvidenceError): verifier.phase_evidence(directory, row) + + def test_phase_role_pid_audio_and_guard_rejected(self): + with synthetic_directory() as name: + directory = Path(name); row = s4_phase_fixture(directory) + for key, bad in [('role', 'O'), ('pid', 999), ('runtime_profile', '/wrong'), ('guard_sha256', 'f'*64)]: + altered = copy.deepcopy(row); altered[key] = bad + with self.subTest(key=key), self.assertRaises(eq.EvidenceError): verifier.phase_evidence(directory, altered) + + def test_missing_profile_not_export_success(self): + with synthetic_directory() as name: + with self.assertRaises(eq.EvidenceError): driver.copy_evidence(Path(name)/'absent', Path(name)/'copied') + + def test_existing_output_never_overwritten(self): + with synthetic_directory() as name: + with self.assertRaises(eq.EvidenceError): driver.run({}, Path(name), None, None, None, None) + + def test_checkout_temp_destination_rejected(self): + with patch.dict(os.environ, {'BUILD_OUTPUT_DIR': str(verifier.HERE)}): + with self.assertRaises(eq.EvidenceError): synthetic_directory() + + def test_import_closure_rejections(self): + for text in ('import restart_pair', 'from restart_pair import copy_states', 'import product', + 'importlib.util.spec_from_file_location("bad", "outside.py")', '__import__("outside")'): + with self.subTest(text=text), self.assertRaises(eq.EvidenceError): checker.check_python_imports(text) + for name in verifier.LOCAL_NAMES-{'eq_probe.gd'}: + self.assertTrue(checker.check_python_imports((verifier.HERE/name).read_text())) + + def test_rebound_lifecycle_and_scenario_contradictions(self): + for kind in ('errors', 'scenario_count', 'scenario_order', 'e45_missing', 'b1_missing', 'invented_PASS'): + with self.subTest(kind=kind), synthetic_directory() as name: + directory = Path(name); row = s4_phase_fixture(directory) + folder = directory/'R-A'; evidence = folder/'evidence' + raw = verifier.read(evidence/'report.json'); life = verifier.read(evidence/'lifecycle.json') + if kind == 'errors': life['errors'].append('observed failure') + elif kind == 'scenario_count': raw['scenarios'].pop() + elif kind == 'scenario_order': raw['scenarios'].reverse() + elif kind == 'e45_missing': life['e45'].pop() + elif kind == 'b1_missing': del life['e3_b1'] + else: raw['scenarios'][-1]['result']['status'] = 'PASS' + (evidence/'report.json').write_text(json.dumps(raw)) + (folder/'stdout.log').write_text('P28_02_EQ_REPORT='+json.dumps(raw)+'\n') + life['files'] = [dict(path='evidence/'+n, **p) for n, p in verifier.inventory(evidence).items() + if n not in ('lifecycle.json', 'audio-close.json')] + (evidence/'lifecycle.json').write_text(json.dumps(life)) + row['evidence_files'] = verifier.inventory(evidence) + with self.assertRaises((eq.EvidenceError, KeyError)): verifier.phase_evidence(directory, row) + + +class S4NativeBundleLogic(unittest.TestCase): + @classmethod + def setUpClass(cls): + cls.temp = synthetic_directory(); cls.directory = Path(cls.temp.name) + cls.collector, cls.standard, cls.outer, cls.diag = driver.load_dependencies() + cls.execution = s4_bundle_fixture(cls.directory, cls.collector, cls.standard) + + @classmethod + def tearDownClass(cls): + cls.temp.cleanup() + + def recompute(self, value): + with patch.object(self.standard, 'profile_path', side_effect=lambda name: Path('/private')/name): + return verifier.recompute(self.directory, value, self.collector, self.standard, self.diag) + + def test_synthetic_full_bundle_positive_not_native_evidence(self): + result = self.recompute(self.execution) + self.assertEqual(set(result['comparisons']), {'R', 'O'}) + self.assertFalse(result['formal_acceptance']) + verifier.write(self.directory/'execution.json', self.execution) + verifier.write(self.directory/'results.json', result) + for phase, values in result['phases'].items(): + for name, value in values.items(): verifier.write(self.directory/phase/(name+'.json'), value) + verifier.seal(self.directory) + # Only external admission is synthetic. All bundle, owned, lifecycle, + # observation, scenario, joining and comparison logic executes unchanged. + with patch.object(driver, 'actual_pins', return_value=self.execution['admission']['pins']), \ + patch.object(self.standard, 'profile_path', side_effect=lambda name: Path('/private')/name), \ + patch.object(driver, 'load_dependencies', return_value=(self.collector, self.standard, self.outer, self.diag)): + self.assertEqual(verifier.verify(verifier.ROOT, self.directory), result) + + def test_receipt_and_source_rejection_matrix(self): + mutations = [ + ('Q label', lambda x: x['admission'].update(candidate_Q_measured=True)), + ('source entry', lambda x: x['source_after']['project.godot'].update(bytes=0)), + ('source count only', lambda x: x['admission'].update(source_map={'count': 1407})), + ('pin mismatch', lambda x: x.update(pins_after={})), + ('cleanup remaining', lambda x: x['cleanup'][0].update(engine_ended=False)), + ('phase missing', lambda x: x['phases'].pop()), + ('cross role', lambda x: x['phases'][3].update(role='O')), + ('PID binding', lambda x: x['phases'][0].update(pid=999)), + ('raw native missing', lambda x: x['phases'][0]['raw'].pop('engine-native.log')), + ('owned missing', lambda x: x['phases'][0]['owned_files'].pop('ended.json')), + ('exit in raw', lambda x: x['phases'][0]['raw'].update(exit_code=0)), + ('runtime startup mix', lambda x: x['phases'][0]['startup_project'].update(name='R-A-runtime')), + ] + for name, mutate in mutations: + value = copy.deepcopy(self.execution); mutate(value) + with self.subTest(name=name), self.assertRaises((eq.EvidenceError, ValueError)): self.recompute(value) + + def test_gate_none_success_not_boolean(self): + self.assertIsNone(self.collector.stage_gate({}, {})) + guard = self.execution['phases'][3]['guard'] + self.assertIsNone(self.collector.guard_gate(guard, Path(guard['actual_user_data_dir']), guard['custom_user_dir_name'])) + with self.assertRaises(ValueError): self.collector.stage_gate({'x': 1}, {}) + with self.assertRaises(ValueError): self.collector.guard_gate(guard, Path('/wrong'), guard['custom_user_dir_name']) + + def test_copied_manifest_root_and_destination_count_rejected(self): + with self.assertRaises((OSError, ValueError)): self.collector.inputs(self.directory) + + def test_failure_keeps_raw_and_no_bundle_without_starting_engine(self): + with synthetic_directory() as name: + out = Path(name)/'failure' + admission = {'source_map': {'project.godot': verifier.pin(verifier.ROOT/'project.godot')}, + 'readonly_path': '/synthetic', 'fixture': '/synthetic', 'engine': '/synthetic'} + with patch.object(self.collector, 'no_live_engine'), \ + patch.object(self.standard, 'default_player', return_value={}), \ + patch.object(self.standard, 'copy_source', side_effect=OSError('synthetic copy failure')), \ + patch.object(self.collector, 'source_map', return_value=admission['source_map']), \ + patch.object(self.outer, 'finish_captured', return_value=([], [])), \ + patch.object(driver, 'actual_pins', return_value={}), \ + patch.object(self.collector, 'run_private_engine') as launch: + self.assertEqual(driver.run(admission, out, self.collector, self.standard, self.outer, self.diag), 1) + launch.assert_not_called() + self.assertFalse(verifier.read(out/'execution.json')['passed']) + self.assertFalse((out/'bundle.json').exists()) + self.assertFalse((out/'seal.json').exists()) + + +class S4ProbeAdmission(unittest.TestCase): + def driver_probe(self, mode, ok): + with synthetic_directory() as name: + argv = ['run_eq.py', mode, '--readonly', name, '--fixture', name, + '--engine', name, '--output', str(Path(name)/'new-output')] + errors = [] if ok else ['first static violation', 'second static violation'] + with patch.object(sys, 'argv', argv), \ + patch.object(driver, 'load_dependencies', return_value=(None, None, None, None)), \ + patch.object(driver, 'actual_pins', return_value={'source': {}}), \ + patch.object(checker, 'check_probe', return_value={'ok': ok, 'errors': errors}) as probe, \ + patch.object(driver, 'frozen_commit', return_value='synthetic'), \ + patch.object(driver, 'plan', return_value=[]), \ + patch.object(driver, 'run', return_value=0) as launch, \ + patch('builtins.print') as output: + self.assertEqual(driver.main(), 0 if ok else 1) + probe.assert_called_once() + if ok and mode == '--run': launch.assert_called_once() + else: launch.assert_not_called() + if not ok: + failure = json.loads(output.call_args.args[0]) + for error in errors: self.assertIn(error, failure['error']) + + def test_check_rejects_false_all_errors(self): self.driver_probe('--check', False) + def test_run_admission_rejects_false_without_engine(self): self.driver_probe('--run', False) + def test_check_accepts_true(self): self.driver_probe('--check', True) + def test_run_admission_accepts_true_mock_launch_only(self): self.driver_probe('--run', True) + + +class S4RemainingBindings(unittest.TestCase): + setUpClass = classmethod(S4NativeBundleLogic.setUpClass.__func__) + tearDownClass = classmethod(S4NativeBundleLogic.tearDownClass.__func__) + recompute = S4NativeBundleLogic.recompute + + def test_verifier_rejects_false_with_every_error(self): + errors = ['first static violation', 'second static violation'] + with patch.object(checker, 'check_probe', return_value={'ok': False, 'errors': errors}): + with self.assertRaises(eq.EvidenceError) as caught: self.recompute(self.execution) + for error in errors: self.assertIn(error, str(caught.exception)) + + def test_verifier_accepts_true_recomputes_raw(self): + with patch.object(checker, 'check_probe', return_value={'ok': True, 'errors': []}) as probe: + result = self.recompute(self.execution) + probe.assert_called_once() + self.assertEqual(set(result['comparisons']), {'R', 'O'}) + self.assertTrue(all(r['ok'] for r in result['comparisons'].values())) + + def test_owned_lifecycle_exit_diagnostic_and_profile_rejections(self): + mutations = [ + ('start missing', lambda x: x['phases'][0]['process'].pop('actual_start_binding')), + ('end missing', lambda x: x['phases'][0]['process'].pop('actual_end_binding')), + ('exit failure', lambda x: x['phases'][0]['process'].update(exit_code=3)), + ('diagnostic', lambda x: x['phases'][0].update(diagnostics=['ERROR: synthetic'])), + ('profile reuse', lambda x: x['admission']['plan'][1].update( + runtime_name=x['admission']['plan'][0]['runtime_name'])), + ] + for name, mutate in mutations: + value = copy.deepcopy(self.execution); mutate(value) + with self.subTest(name=name), self.assertRaises((eq.EvidenceError, ValueError, KeyError)): + self.recompute(value) + + def test_nonzero_determinism_rejected_after_real_join(self): + original = eq.compare_reports + def differing(left, right): + if left is right: + return original(left, right) + self.assertIsNotNone(left['checkpoints'][0]['harness_normalized_digest']) + self.assertIsNotNone(right['checkpoints'][0]['harness_normalized_digest']) + result = original(left, right) + result.update(ok=False, differences=[{'synthetic_difference': True}]) + return result + with patch.object(eq, 'compare_reports', side_effect=differing): + with self.assertRaisesRegex(eq.EvidenceError, 'same-role determinism failed'): + self.recompute(self.execution) + + def test_nine_original_destinations_required(self): + original_sha = driver.sha + def synthetic_sha(path): + if Path(path) == Path('/synthetic/fixture'): return self.collector.FIXTURE_SHA + if Path(path) == Path('/synthetic/Godot'): return self.collector.ENGINE_SHA + return original_sha(path) + with synthetic_directory() as name: + root = Path(name) + manifest = root/'ROOT_INPUT_MANIFEST.json' + for count, destinations in ((8, list(range(9))), (9, list(range(8))), (9, [0]*9)): + manifest.write_text(json.dumps({'files': [{'destination': str(n)} for n in destinations]})) + with self.subTest(count=count, destinations=destinations), \ + patch.object(driver, 'sha', side_effect=synthetic_sha), \ + patch.object(self.collector, 'inputs', return_value={'files': {str(n): 'sha' for n in range(count)}}): + with self.assertRaisesRegex(eq.EvidenceError, 'nine'): + driver.actual_pins(verifier.ROOT, root, Path('/synthetic/fixture'), + Path('/synthetic/Godot'), self.collector, self.standard) + + +class S4StoredResultBindings(unittest.TestCase): + def reject_stored_change(self, kind): + # Isolate verify's stored-result binding. The full raw recomputation is + # exercised without a mock by S4NativeBundleLogic and S4RemainingBindings. + with synthetic_directory() as name: + directory = Path(name) + admission = dict(readonly_path=name, fixture=name, engine=name, pins={}) + verifier.write(directory/'execution.json', {'admission': admission}) + result = {'phases': {'R-A': {'raw': {'kind': 'raw'}, 'joined': {'kind': 'joined'}, + 'proofs': [{'sidecar': 'required'}], 'checker': {'ok': True}}}} + stored = copy.deepcopy(result) + if kind == 'cached': stored['phases']['R-A']['checker']['ok'] = False + verifier.write(directory/'results.json', stored) + (directory/'R-A').mkdir() + for key, value in result['phases']['R-A'].items(): + if kind == 'proofs' and key == 'proofs': value = [] + if kind == 'raw_joined' and key == 'raw': value = result['phases']['R-A']['joined'] + verifier.write(directory/'R-A'/(key+'.json'), value) + verifier.seal(directory) + with patch.object(driver, 'load_dependencies', return_value=(None, None, None, None)), \ + patch.object(driver, 'actual_pins', return_value={}), \ + patch.object(verifier, 'recompute', return_value=result) as recompute: + with self.assertRaisesRegex(eq.EvidenceError, 'recomputed results differ|copy differs'): + verifier.verify(verifier.ROOT, directory) + recompute.assert_called_once() + + def test_cached_verdict_not_trusted(self): self.reject_stored_change('cached') + def test_missing_sidecar_rejected_after_seal(self): self.reject_stored_change('proofs') + def test_raw_joined_substitution_rejected_after_seal(self): self.reject_stored_change('raw_joined') + + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/verify_eq.py b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/verify_eq.py new file mode 100644 index 0000000..240eee1 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/verify_eq.py @@ -0,0 +1,254 @@ +#!/usr/bin/env python3 +"""Read-only verification of the exact S_eq native evidence; never launches Godot.""" +import argparse +import hashlib +import json +import os +from pathlib import Path +import sys + +sys.dont_write_bytecode = True +import check_eq as check +import compare_versions as eq + +HERE = Path(__file__).resolve().parent +ROOT = HERE.parents[5] +PHASES = ['import', 'parse-base', 'parse-wrapper', 'R-A', 'R-B', 'O-A', 'O-B'] +ROLES = {'R-A': 'R', 'R-B': 'R', 'O-A': 'O', 'O-B': 'O'} +NAMES = {f'{prefix}-{i:02d}.json' for prefix, count in + [('checkpoint', 31), ('observation', 31), ('e3', 18), ('e45', 21)] for i in range(count)} | { + 'events.json', 'report.json', 'lifecycle.json', 'audio-close.json'} +LOCAL_NAMES = {'run_eq.py', 'verify_eq.py', 'check_eq.py', 'compare_versions.py', 'eq_probe.gd', 'test_eq.py'} +require = eq.require + + +def sha(path): + return hashlib.sha256(Path(path).read_bytes()).hexdigest() + + +def pin(path): + path = Path(path) + require(path.is_file() and not path.is_symlink(), 'missing/symlink: ' + str(path)) + return {'bytes': path.stat().st_size, 'sha256': sha(path)} + + +def read(path): + return check.strict_json(Path(path).read_text(encoding='utf-8')) + + +def write(path, value): + with Path(path).open('x', encoding='utf-8') as stream: + json.dump(value, stream, ensure_ascii=False, allow_nan=False, indent=2) + stream.write('\n') + + +def wire(value): + """Checker diagnostics may contain tuples; bind their exact JSON representation.""" + return check.strict_json(json.dumps(value, ensure_ascii=False, allow_nan=False)) + + +def inventory(directory, seals=False): + directory = Path(directory) + require(directory.is_dir() and not directory.is_symlink(), 'evidence directory missing/symlink') + result = {} + for path in sorted(directory.rglob('*')): + require(not path.is_symlink(), 'evidence symlink') + name = path.relative_to(directory).as_posix() + if path.is_file() and (seals or name not in ('bundle.json', 'seal.json')): + result[name] = pin(path) + return result + + +def seal(directory): + directory = Path(directory) + require(not (directory / 'bundle.json').exists() and not (directory / 'seal.json').exists(), 'already sealed') + write(directory / 'bundle.json', {'schema': 'p28-02-eq-bundle-v1', 'files': inventory(directory)}) + write(directory / 'seal.json', {'bundle': pin(directory / 'bundle.json')}) + + +def check_seal(directory): + directory = Path(directory) + manifest, sealed = read(directory / 'bundle.json'), read(directory / 'seal.json') + require(sealed == {'bundle': pin(directory / 'bundle.json')}, 'seal mismatch') + require(manifest == {'schema': 'p28-02-eq-bundle-v1', 'files': inventory(directory)}, 'manifest/file mismatch') + + +def check_audio(audio, pid): + expected = {'coordinator': True, 'passed': True, 'owned_engine_pid': pid, + 'all_owned_targets_released': True, 'deadline_reached': False, + 'clock_process_held_stopped': True, 'window_input_held_disabled': True, + 'restored_before_quit': False, 'shared_bus_deleted': False, 'settings_mutated': False} + require(all(type(audio.get(k)) is type(v) and audio[k] == v for k, v in expected.items()), 'audio close/PID') + + +def phase_evidence(directory, row): + """Recompute all S1-S3b checks from copied native bytes, with no cached verdicts.""" + directory = Path(directory) + phase, role = row['phase'], row['role'] + require(ROLES.get(phase) == role, 'phase/role binding') + folder = directory / phase + evidence = folder / 'evidence' + files = inventory(evidence, seals=True) + require(set(files) == NAMES and files == row['evidence_files'], 'exact private evidence inventory') + raw = check.read_report_stdout((folder / 'stdout.log').read_text()) + require(raw == read(evidence / 'report.json') and raw['role'] == role, 'raw report/role copy') + require(len(raw['scenarios']) == 39, '39 scenarios required') + life = read(evidence / 'lifecycle.json') + require(life['stage'] == 'S3b', 'S3b lifecycle required') + require(len(life['e3']) == 18 and len(life['e45']) == 21, 'scenario evidence coverage') + declared = {r['path']: {'bytes': r['bytes'], 'sha256': r['sha256']} for r in life['files']} + require(len(declared) == len(life['files']), 'duplicate lifecycle inventory') + expected = {'evidence/' + n: v for n, v in files.items() if n not in ('lifecycle.json', 'audio-close.json')} + require(declared == expected, 'lifecycle inventory differs') + guard_path = directory / (phase + '-guard.json') + guard = read(guard_path) + require(guard == row['guard'] and sha(guard_path) == row['guard_sha256'] == life['guard']['sha256'], 'guard SHA') + require(life['guard']['path'] == row['environment']['THE_TREE_PACK_PROFILE_REPORT'], 'guard path binding') + require(raw['profile_root']['root'] == row['runtime_profile'], 'report profile binding') + check.check_lifecycle(raw, life, guard) + check_audio(read(evidence / 'audio-close.json'), row['pid']) + require(read(evidence / 'events.json') == raw['events'], 'events copy') + for i, cp in enumerate(raw['checkpoints']): + require(read(evidence / f'checkpoint-{i:02d}.json') == cp, 'checkpoint copy') + check.check_observation(cp, read(evidence / f'observation-{i:02d}.json')) + for prefix in ('e3', 'e45'): + for i, value in enumerate(life[prefix]): + require(read(evidence / f'{prefix}-{i:02d}.json') == value, 'scenario copy') + checked = check.check_report(raw, life['measurement'], life['e3'], life['e3_b1'], life['e45']) + require(checked['ok'], 'report checker: ' + repr(checked['errors'])) + joined, proofs = check.join_report(raw) + return wire({'raw': raw, 'joined': joined, 'proofs': proofs, 'checker': checked}) + + +def recompute(directory, execution, collector, standard, diag): + """Validate owned receipts and recompute every comparison from raw evidence.""" + directory = Path(directory) + require(execution['passed'] is True and execution['error'] is None and execution['cleanup_errors'] == [], 'execution failed') + admission = execution['admission'] + require(read(directory / 'admission.json') == admission, 'admission copy') + require(admission['measured_source'] == 'S_eq-native-not-Q' and admission['candidate_Q_measured'] is False, 'Q measurement forbidden') + require(admission['phases'] == PHASES, 'phase plan') + from run_eq import wrapper_text + original_out = Path(admission['plan'][0]['folder']).parent + engine = Path(admission['engine']) + expected_commands = [collector.argv_for(engine, original_out / 'stage', original_out / 'guarded.gd', importing=True), + collector.parse_argv(engine, original_out / 'stage', original_out / 'eq_probe.gd'), + collector.parse_argv(engine, original_out / 'stage', original_out / 'guarded.gd')] + [ + [str(engine), '--headless', '--path', str(original_out / 'stage'), '--script', str(original_out / 'guarded.gd')] + for _ in range(4)] + require([p['argv'] for p in admission['plan']] == expected_commands, 'actual seven-phase command plan') + require((directory / 'guarded.gd').read_text() == wrapper_text(original_out), 'guard before parent wrapper') + require(sha(directory / 'eq_probe.gd') == admission['pins']['worker']['eq_probe.gd'], 'frozen probe') + require(sha(directory / 'profile_guard.gd') == admission['pins']['readonly']['files']['run-r02/profile_guard.gd'], 'guard pin') + require(sha(directory / 'root-input-manifest.json') == admission['pins']['readonly']['manifest_sha256'], 'original manifest copy') + static = check.check_probe((directory / 'eq_probe.gd').read_text()) + require(static['ok'], 'probe checker: ' + repr(static['errors'])) + source = admission['source_map'] + require(len(source) == 1407 and collector.digest(source) == eq.SOURCE_SHA, 'full source map pin') + require(execution['source_after'] == source and execution['player_before'] == execution['player_after'], 'source/player preservation') + require(execution['pins_after'] == admission['pins'], 'pin preservation') + rows = execution['phases'] + require([r['phase'] for r in rows] == PHASES, 'seven phases in order') + pids, profiles, joined, results = [], [], {}, {} + previous = source + for i, row in enumerate(rows): + phase = row['phase'] + # DIAG's shared owned/raw checks return before its DIAG-specific report branch + # for the EQ phase names. Its dependency is frozen; no function is replaced. + diag.bound_raw(directory / phase, row) + for name in row['raw']: + require(not collector.diagnostics((directory / phase / name).read_text()), 'strict diagnostic') + for name in row['owned_files']: + read(directory / phase / name) # reject duplicate JSON keys before any admission + pid = row['process']['pid'] + require(type(pid) is int and pid > 0 and row['pid'] == pid, 'phase PID binding') + pids.append(pid) + start, end = row['process']['actual_start_binding'], row['process']['actual_end_binding'] + require(type(start['monotonic_ns']) is int and end['monotonic_ns'] >= start['monotonic_ns'], 'PID start/end time') + command = admission['plan'][i] + require(command['phase'] == phase and command['role'] == ROLES.get(phase), 'planned role') + environment = {'THE_TREE_PACK_PROFILE_NAME': command['runtime_name'], + 'THE_TREE_PACK_PROFILE_EXPECTED': command['runtime_profile'], + 'THE_TREE_PACK_PROFILE_REPORT': str(original_out / (phase + '-guard.json')), + 'THE_TREE_EQ_ROLE': ROLES.get(phase, ''), 'THE_TREE_P28_FIXTURE': admission['fixture'], + 'THE_TREE_P28_FIXTURE_SHA': collector.FIXTURE_SHA} + require(command['environment'] == environment, 'guard/role/fixture environment') + require(command['startup_profile'] == str(standard.profile_path(command['startup_name'])) and + command['runtime_profile'] == str(standard.profile_path(command['runtime_name'])), 'profile name/path') + require(row['argv'][:-3] == command['argv'] and row['argv'][-3] == '--log-file' and + row['argv'][-1] == '--verbose' and '--headless' in row['argv'], 'phase argv') + require(row['environment'] == command['environment'], 'phase environment') + collector.stage_gate(previous, row['stage_inventory'], importing=phase == 'import') + previous = row['stage_inventory'] + require(row['source_preserved'] is True and row['player_preserved'] is True, 'phase preservation') + startup = row['startup_project'] + require(startup['name'] == command['startup_name'] and startup['profile'] == command['startup_profile'] and + startup['fresh_before'] is True and startup['restored_sha256'] == source['project.godot']['sha256'], 'startup profile') + require(sha(directory / (phase + '-startup-project.godot')) == startup['sha256'], 'startup project bytes') + require((directory / (phase + '-startup-project.godot')).read_bytes() == + standard.private_project((ROOT / 'project.godot').read_bytes(), command['startup_name']), 'private project policy') + profiles.extend([startup['profile'], command['runtime_profile']]) + for kind in ('startup', 'runtime'): + copied = row['profile_copies'][kind] + target = directory / phase / (kind + '-profile') + require(type(copied['exists']) is bool and copied['exists'] == target.is_dir(), 'profile existence/copy') + require((inventory(target, seals=True) if target.is_dir() else {}) == copied['files'], 'complete profile copy') + require(execution['profiles_retained'][command[kind + '_profile']] == copied['files'], 'retained profile changed') + if phase in ROLES: + require(row['profile_copies']['runtime']['exists'] is True, 'missing runtime profile') + require({n[len('evidence/'):]: p for n, p in row['profile_copies']['runtime']['files'].items() + if n.startswith('evidence/')} == row['evidence_files'], 'profile/evidence copy binding') + require(row['role'] == ROLES[phase] and row['runtime_profile'] == command['runtime_profile'] and + row['runtime_name'] == command['runtime_name'], 'runtime/role binding') + collector.guard_gate(row['guard'], Path(row['runtime_profile']), row['runtime_name']) + results[phase] = phase_evidence(directory, row) + joined[phase] = results[phase]['joined'] + else: + require(row['role'] is None, 'parse/import role') + require('P28_02_EQ_REPORT=' not in (directory / phase / 'stdout.log').read_text(), 'parse/import report') + require(len(set(pids)) == 7 and len(set(profiles)) == 14, 'PID/profile reuse') + require({r['pid'] for r in execution['cleanup']} == set(pids) and all( + r['engine_ended'] is True and r['outer_cleanup_errors'] == [] and + r['foreign_process_or_group_signals'] == 0 for r in execution['cleanup']), 'cleanup incomplete') + comparisons = {} + for role in ('R', 'O'): + result = eq.compare_reports(joined[role + '-A'], joined[role + '-B']) + require(result['ok'] and result['differences'] == [], 'same-role determinism failed: ' + role) + comparisons[role] = result + return wire({'phases': results, 'comparisons': comparisons, 'measured_source': 'S_eq-native-not-Q', + 'candidate_Q_measured': False, 'original_credit': 0, 'formal_acceptance': False}) + + +def verify(project_root, directory): + from run_eq import load_dependencies, actual_pins + project_root, directory = Path(project_root).resolve(), Path(directory).resolve() + check_seal(directory) + execution = read(directory / 'execution.json') + collector, standard, outer, diag = load_dependencies(project_root) + admission = execution['admission'] + require(actual_pins(project_root, Path(admission['readonly_path']), Path(admission['fixture']), + Path(admission['engine']), collector, standard) == admission['pins'], 'actual input/source/EQ pins differ') + result = recompute(directory, execution, collector, standard, diag) + require(result == read(directory / 'results.json'), 'recomputed results differ') + for phase, values in result['phases'].items(): + for name, value in values.items(): + require(read(directory / phase / (name + '.json')) == value, 'raw/joined/proof/checker copy differs') + return result + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--project-root', type=Path, required=True) + args = parser.parse_args() + try: + require(os.environ.get('BUILD_OUTPUT_DIR'), 'BUILD_OUTPUT_DIR required') + result = verify(args.project_root, Path(os.environ['BUILD_OUTPUT_DIR']) / 'p28-02-eq-evidence') + print(json.dumps({'status': 'verified', 'result': result}, ensure_ascii=False, allow_nan=False)) + return 0 + except (ValueError, OSError, KeyError, TypeError, IndexError) as error: + print(json.dumps({'status': 'failed', 'error': str(error), 'formal_acceptance': False})) + return 1 + + +if __name__ == '__main__': + raise SystemExit(main()) From b2dbda8c956643a2a972e8bcf7416038a3f70b2c Mon Sep 17 00:00:00 2001 From: Agent Control Runner Date: Thu, 22 Oct 2026 03:38:46 +0900 Subject: [PATCH 2/4] =?UTF-8?q?P28-02-EQ:=20=E6=84=8F=E5=91=B3=E3=82=92?= =?UTF-8?q?=E4=BF=9D=E3=81=A4=E8=BB=BD=E9=87=8F=E5=8C=96=EF=BC=9A=E5=90=8C?= =?UTF-8?q?=E7=AD=89=E6=80=A7=E3=81=AE=E5=85=88=E8=A1=8C=E5=9B=BA=E5=AE=9A?= =?UTF-8?q?=EF=BC=88harness=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../execution/p28-02/eq/IMPLEMENTATION.md | 130 ++++ .../execution/p28-02/eq/PROGRESS.md | 46 +- .../execution/p28-02/eq/S5_SUPPLEMENTARY.json | 40 ++ .../execution/p28-02/eq/UNIT_OUTPUT.sha256 | 2 +- .../execution/p28-02/eq/UNIT_OUTPUT.txt | 313 ++++----- .../eq/UNIT_OUTPUT_S5_ATTEMPT_01.sha256 | 1 + .../p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_01.txt | 316 +++++++++ .../eq/UNIT_OUTPUT_S5_ATTEMPT_02.sha256 | 1 + .../p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_02.txt | 163 +++++ .../eq/UNIT_OUTPUT_S5_ATTEMPT_03.sha256 | 1 + .../p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_03.txt | 167 +++++ .../eq/UNIT_OUTPUT_S5_ATTEMPT_04.sha256 | 1 + .../p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_04.txt | 202 ++++++ .../eq/UNIT_OUTPUT_S5_ATTEMPT_05.sha256 | 1 + .../p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_05.txt | 167 +++++ .../execution/p28-02/eq/check_eq.py | 400 +++++++++--- .../execution/p28-02/eq/compare_versions.py | 540 +++++++++++++-- .../execution/p28-02/eq/eq_probe.gd | 221 ++++--- .../execution/p28-02/eq/run_eq.py | 6 +- .../execution/p28-02/eq/test_eq.py | 613 +++++++++++++++++- .../execution/p28-02/eq/verify_eq.py | 87 ++- 21 files changed, 3038 insertions(+), 380 deletions(-) create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/S5_SUPPLEMENTARY.json create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_01.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_01.txt create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_02.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_02.txt create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_03.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_03.txt create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_04.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_04.txt create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_05.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_05.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/IMPLEMENTATION.md b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/IMPLEMENTATION.md index a46d108..a2166f3 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/IMPLEMENTATION.md +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/IMPLEMENTATION.md @@ -577,3 +577,133 @@ failures respectively; all earlier evidence remains unchanged. This table records the required implementation targets, not completed validation. No native or formal validation is authorized for this worker. + + +## S5 implementation (repair 10; EQ_S5_SCALE_PLAN r01/r02) + +Implemented by Claude Opus 5.5 in the Desktop control session after the user moved +implementation from Codex to Opus. The exact-S native of 6f75c9a failed in R-A and stays a +failure; this stage fixes the harness defects that only the real engine exposed and makes +the full R scope (E1-E5, 39 scenarios) fit the unchanged limits. All earlier text below and +above this section is retained history. + +### Defects found only by the real engine (scratchpad diagnostics, not formal evidence) + +- write_evidence created `user://evidence` with the user:// path. Under the guard's runtime + user-dir switch this fails; the directory is now created from the globalized path, as the + RESTART helpers do. +- typed_info encoded get_typed_script(), a null Object for unscripted typed containers, as an + unsupported Variant 24. It is now transported as NIL ([0], which the Python side already + required); a scripted element type still fails. +- Package manifest mutation re-serialized a JSON-parsed manifest. Godot parses every JSON + number as float, so untouched integers became 390.0, 1.0 and so on. Only the one key line is + now edited as text; the Python rule already rejects any other change (new negative test). +- The guard receipt was recorded after JSON parsing, with the same float problem. The exact + receipt text is now kept beside it; Python parses that text strictly, compares it with the + independently saved guard file and binds its SHA. +- Godot instance IDs are signed 64-bit and RefCounted IDs are negative. The cache identity + check accepts the sign. Raw values stay in raw; only the SPEC 3.2 exclusion (process-local + instance ID) is applied across PIDs, with both values and the reason recorded. +- A large E4 return is a blob; its ok/code facts are taken from the live return value. +- After the first harness error, later scenarios are no longer run (the run already failed). + +### Product behavior recorded as an existing defect, separate from harness capture + +autoload/simulation_runtime.gd:788 and :1346: a successful restore replaces domain_events +with a new DomainEventStream and does not carry subscribers. The probe's wildcard +subscription stayed on the old stream after E4 restore, so SAVE_LOADED and all later events +were not delivered. follow_event_stream() runs after every E3 call and after E4 restore and +load. When the stream changed it records the new stream's subscriber IDs (no instance IDs), +recovers the unobserved events from recent_events() in publication order, and subscribes to +the live stream again. check_e3/check_e45 record event_stream_replaced_subscribers_not_carried +as an existing defect (never PASS). Completeness is still proven only by the counter delta, +the published_ids delta and the actual event IDs; an event outside the 256-entry +recent_events window would remain missing and fail. lifecycle.event_stream_replacements must +equal the per-scenario facts. No event is renumbered, no product file or hook is changed. + +### Evidence representation (complete and reversible) + +- Trees larger than 64 KiB, raw S/K/C bytes and package files are written once as + evidence/blobs/.gz, named by the SHA-256 of the uncompressed bytes; records hold + {"blob": sha}. Small trees stay inline. lifecycle.blobs lists every blob with its size, + compressed size and compressed SHA; verify_eq binds that list to the files exactly and + decompresses every blob to check name and size. +- Godot's JSON text of a tree equals json_bytes(tree) (checked on the R fixture tree), so a + blob name is the tree SHA. var_to_bytes distinguishes typed metadata, String/StringName, + int/float and key order (checked in the engine), so transport reuses the proof for equal + bytes. Every checkpoint carries a complete tree; the diff chain is gone (tree_diff took 5.4 s + per R checkpoint). Report and lifecycle hold references only, which removes the memory and + swap growth seen in the failed native. + +### Python: same results, less work + +- A blob is accepted only when its uncompressed bytes hash to its name, and its tree is used + only after the full validate_tree (types, arity, metadata, keys) has passed on first use; + only then is its SHA recorded as valid. A failed blob is never recorded and fails again. + A matching SHA is never taken as proof of types (Root's repro of [2, true] / [24, 0] in a + correctly named blob is a regression test). Valid blob trees are shared, never mutated; + checkpoints are loaded one at a time. Equal SHA means equal; otherwise Python == decides, which is exact JSON equality for + validated trees (INT/BOOL payloads are int, floats are 16-hex strings). +- Normalization runs the original closed policy unchanged on a skeleton holding only + systems.runtime.domain_events.recent_events, read directly from the tree text. The rest of + the text is proven free of the profile root, the reserved token, _us/_ms names and + save_service; otherwise the original full walk runs. Restore runs the original reversible + check on the skeleton. +- normalized_digest builds the same canonical JSON without per-node copies and is memoized by + SHA (17.4 s to about 1.2 s on an R tree, identical value). +- Expected inputs, X(B, event) and the E5 expectation copy only the dictionaries on the + changed path. Large derived trees are recorded by SHA descriptor in joined facts and checker + results; compare_reports rebuilds them from the blobs when SHAs differ. +- test_eq.S5 proves equivalence against the retained S1-S4 algorithms (compare_trees, + canonical digest, deepcopy builders, original normalization including violations, tokens and + non-array recent_events), that every one of 31 blob checkpoints is verified alone exactly as + inline trees, and the new static requirements (full snapshot transport, blob write, gzip + roundtrip, overwrite refusal, stream following). + +### Snapshot signal rule corrected (EQ_S5_SCALE_PLAN r03) + +The S3a rule "exactly one snapshot_published/state_updated pair per measured minute" was a +harness assumption. Paused submits publish once each after their command events +(simulation_runtime.gd:486-493, :508-512, :5768-5793), besides the tick-end publish (:1745-1749) +and a successful restore (:1473); R minute 648 had 50 commands and 51 pairs (the r2 check +failure on the old rule is retained). The probe now stores, per signal, the domain_event +counter and _next_command_id at emission (read only). check_publishes orders signals and +events together and requires: complete pairs with equal counters; a command publish after +exactly one submit whose command is in its trailing batch; no submit before any other publish +and none left unpublished; every command event covered; and the remaining tick/restore +publishes equal to the operations performed (one per measured minute; E3 successful +restores; E4 1/1/1/1/1 with build only when applied; E5 2 or 3). Missing, extra and reordered +pairs, including a missing publish between adjacent commands, fail. Actual counts stay raw and +signal_order is compared exactly across versions. + +### Python speed, measured on retained R raw (r3, scratchpad diagnostic, not formal) + +One R phase checked in the phase_evidence order (lifecycle, observations, check_report, +join), with full stdout/stderr and Python's own exit kept for every run: +1270.3 s (first S5 code, with concurrent profiling) -> 552.9 s (memo of identical inputs, +copy-free builders) -> 301.8 s (labelled digest, parse-free restore, copy-free diffs) -> +259.7 s (facts derived at first parse) -> 58.3 s (cyclic GC off inside memo_scope; before +the blob validation fix, so not used as a result). With full blob validation, r3 + r4 checked +in one process took 136.5 + 132.0 s and their comparison 4.2 s with 0 differences; with the +validate_tree rewrite (same checks, messages and order; 4000-case differential test against +the S1 version) four phase checks in parallel processes took 131 s wall (R 111.9 / 112.1 s, +O 5.9 / 6.2 s), all ok. verify_eq therefore runs the four phase checks in parallel worker +processes of the same verification and does the same-role comparisons in the parent with the +workers' validated SHAs and normalization facts; the result equals the sequential mode, which +remains the fallback and the mode used by unit tests. The unchanged 300 s native-verify +limit is kept; the Runner configuration is not changed. + +- memo_scope: inside one verification call, identical check inputs (SHA of the exact JSON) + are checked once; check_lifecycle and check_report shared E3/E45/measurement work. It + also turns cyclic GC off for its duration; typed trees are acyclic lists, results do not + depend on GC, and GC is restored on exit. +- The joined harness digest is labelled `normalized-sha256:` (SHA of the exact normalized + JSON, computed by splicing the normalized events into the blob text). compare_reports + compares labelled digests exactly and, only when two differ, compares the canonical + (dictionary-order-insensitive) digests; equal canonical digests are reported as + dictionary-order-only, otherwise the difference is recorded. checker.normalized_digest + remains the canonical digest (same values as S1). +- Normalization facts, counters and next_command_id are derived when a blob tree is first + parsed and memoized by SHA; restore uses the memoized skeleton, so join and comparison do + not parse again. compare_trees records nodes shared with the immutable trees instead of + deep copies; keys use inline text. diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/PROGRESS.md b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/PROGRESS.md index 2e0d117..926e7de 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/PROGRESS.md +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/PROGRESS.md @@ -1,4 +1,48 @@ -# P28-02-EQ progress — S4 retained completion r03 +# P28-02-EQ progress — S5 (repair 10, Claude Opus 5.5 Desktop implementation) + +Implementer: Claude Opus 5.5 in the Desktop control session, by the user's delegation +("Codexの使用量上限いきそうなので、作業をひきとって"; Root relayed 「実装担当含めOpusに委任」). +The registered contract keeps worker codex; no Codex/Astra run was started for this stage. +Submission goes through the normal Runner submit, which makes the commit. 正式受入は保留、原本加算0。 + +- Exact-S native of 6f75c9a failed in R-A (user://evidence mkdir) and stays a failure; the + owner intake recorded it and the normal repair made repairs 10. +- Fixed the harness defects that only the real engine showed (evidence mkdir under the guard, + typed script metadata, manifest/guard JSON floats, signed instance IDs, large E4 returns) and + recorded the product's event-stream replacement on restore as an existing defect while the + probe keeps capturing every event (EQ_S5_SCALE_PLAN r02 §3-4). +- Content-addressed gzip blobs and exact Python fast paths keep R and O at full E1-E5 scope + (39 scenarios each) within the unchanged 1800 s phase and 300 s validation limits. +- Scratchpad diagnostics with the same guard and HOME redirected (not formal evidence): + see the S5 section of IMPLEMENTATION.md for measured times and sizes. +- Unit evidence (engine-free `python3 -B test_eq.py`; full raw outputs with SHA files): + - UNIT_OUTPUT_S5_ATTEMPT_01: 146 tests, 9 failures and 5 errors (the S5 evidence format + against old fixtures and one old static snippet list). Kept as a failure. + - UNIT_OUTPUT_S5_ATTEMPT_02: 156 tests OK in 211.416 s (run beside an R engine run). + - UNIT_OUTPUT_S5_ATTEMPT_03: 160 tests OK in 130.451 s, Python exit 0 (after the parallel + verifier fix). An intermediate full run failed once (160 tests, 1 error: closed worker + stdin); only its single-test rerun output was kept, and the fix is in phase_results. + - Class-targeted runs during development were displayed through tail and are not claimed + as retained raw results. + - UNIT_OUTPUT_S5_ATTEMPT_04: 151 tests, 3 errors, Python exit 1: the new differential test + imported random, outside the closed EQ import list, so the driver's closure check rejected + test_eq.py. The test now uses its own deterministic generator; the list is unchanged. + - UNIT_OUTPUT_S5_ATTEMPT_05 (final, all changes included): 161 tests OK in 121.627 s, + Python exit 0, outer 121.748 s; same bytes as UNIT_OUTPUT.txt, + SHA-256 7372a382cc2f3c090013874d8f28f17cad4cb1b965ad86c86de7a21fc2d851a8. +- Test bodies changed for the S5 format, each recorded here: E3 evidence and E4 restore/load + details carry event_stream; the S4 phase fixture lifecycle is S5; the S2 static list names + transport(snapshot_value) instead of the removed diff-chain snippet; s2_report signals carry + event_counter/command_counter and its runtime next_command_id; the E4/E5 fixture emits the + product's publishes; the accepted-restore E3 test adds the restore publish; the E4 load + fixture event uses a domain_event ID. All other earlier test bodies and raw outputs are + unchanged; 15 S5 tests were added. + +Next: Runner submit → exact-S native 7 phases → bundle → p28-02-eq-unit and +p28-02-eq-native-verify → fresh independent Opus review of all 6 conditions → normal +qualification, approval, integration and final → OPT/whole-unit. 23/88、4/30は不変。 + +## Retained S4 r03 progress (unchanged historical text) S4 の保持済み実装に対する残作業を完了し、局所unitの証拠として提出する。 正式受入は保留、原本加算0。 diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/S5_SUPPLEMENTARY.json b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/S5_SUPPLEMENTARY.json new file mode 100644 index 0000000..bfcccf4 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/S5_SUPPLEMENTARY.json @@ -0,0 +1,40 @@ +{ + "actual_commander_context": { + "implementer": "Claude Opus 5.5 (claude-opus-5-5), Desktop control session local_a7f85421-3eed-4482-8030-c0dca669573a", + "authority": "User delegation: Codexの使用量上限いきそうなので、作業をひきとって; Root relayed 実装担当含めOpusに委任. Contract worker field stays codex as registered; no Codex/Astra run.", + "stage": "S5 (repair 10): real-engine harness defects, content-addressed blob evidence, exact fast Python paths, publish binding, full R and O E1-E5 scope.", + "actual_documents": { + "EQ_S5_SCALE_PLAN.txt": { + "sha256": "4a4d52dd36ae2556e623c77afa17c718411f2161c3c2fec450f2016097b5794f", + "bytes": 6192, + "full_unedited": "EQ_S5_SCALE_PLAN(P28-02-EQ repair 10。実際のエンジンでの診断に基づいて、証拠の表現と R の範囲を確定する。SPEC、TASK、6条件、eq/references、eq/registration、補足 r01/r02/r03 は変更しない。実装は、ユーザーの委任により Claude Opus 5.5 が Desktop で行う)\n\n1. 実際の失敗と診断(全て scratchpad の診断。正式の証拠ではない)\n- 正確な S 6f75c9a の native は R-A で失敗した(user://evidence を作れない)。\n- 修正1: write_evidence は、guard が実行中に切り替えた user dir の下では、user:// のままの mkdir に失敗する(guard の無い普通の環境では成功する)。RESTART の helper と同じく globalize してから作る。\n- 修正2: 型付きの container の get_typed_script() は、script の無いとき null の Object を返す。encode はそれを Variant 24 として拒否していた(R の S の型付きの container 約1.5万個の全て)。Python の側は既に [0] を期待しているので、NIL として運ぶ。script のある型は拒否のまま。\n- 修正3: harness の error が出たら、それ以降の scenario を行わない(失敗は既に確定しているため)。\n- O の診断(HOME を scratchpad に向け、同じ guard で実行): 27秒で完走、lifecycle の error 0件、証拠105件、227MB + stdout 35MB。\n- 規模の実測:\n - R の S は 11.36MB で、O(96KB)の約118倍。O の証拠の量から、R は1回で約30GB、Godot の時間は約50分になる。空き容量(約11〜15GB)と phase の制限1800秒を超える。\n - R の測定区間の診断: checkpoint 1つに約20秒、1 tick の diff は約1MB。空き容量は、Godot の memory(全ての木を report と lifecycle に保持)によって5GB減った。\n - Godot の処理(R の S 1つ): create_snapshot 75ms、var_to_bytes 39ms、gzip 42ms、encode 0.94秒、decode 0.85秒、JSON 化 0.73秒、tree_diff 5.4秒。\n - Python の処理(R の木1つ): 正規化3.8秒、復元5.2秒、正規化 digest 13秒。木1組の比較に約22秒かかり、R-A と R-B の比較だけで数時間かかる。正式の validation の300秒(変えない)に収まらない。\n - 木の JSON は gzip で 13.4MB から 0.54MB になる。Godot の JSON の文字列と Python の json_bytes は、R の木で bytes が完全に一致した。var_to_bytes は、型付きの container の型、String と StringName、int と float、dict の順序の違いを全て区別した。\n - O の木102件で、正規化の entry 1256件は全て systems.runtime.domain_events.recent_events の下にあり、violation は0件だった。\n\n2. 証拠の表現(完全な状態・全イベントを落とさない。可逆)\n- 内容で番地を付けた blob: 大きい木の JSON(64KB を超えるもの)と、S/K/C の var_to_bytes の bytes を、evidence/blobs/<内容の SHA-256>.gz に gzip で1回だけ書く。記録には {\"blob\": SHA} を置く。小さい木(event、戻り値など)は従来どおり inline。\n- 木の SHA は、blob を展開した bytes の SHA-256 と一致する(JSON の bytes が Godot と Python で同じため)。Python は、木を読み込まずに C の速度で検証できる。\n- transport は、var_to_bytes の SHA が同じ値の木の証明を再利用する(var_to_bytes が上の全ての違いを区別するため、同じ bytes は同じ木)。\n- checkpoint の S は、diff ではなく、毎回完全な木の blob 参照にする(tree_diff の5.4秒を除く)。latest の bytes が S と同じときは、従来どおり same_as_S。\n- Godot の memory: report と lifecycle には参照だけを持ち、木を保持しない。\n\n3. Python(同じ意味の結果を、少ない計算で出す)\n- blob の読込は、SHA の検証つきで、同じ SHA を1回だけ読む。読んだ木は変更しない(共有する)。\n- 正規化の対象が無い木(JSON の bytes に profile root、予約の token、_us/_ms で終わる key が無い)は、正規化の結果が入力と同じで、sidecar の entry と violation が空であることが、関数の定義から決まる。その場合は複製せずに同じ木を返す。recent_events が配列であることの検査は残す。それ以外の木は、従来の関数で正規化する。\n- 正規化の digest は、entry がある latest の木だけで計算する(比較で使うのはその場合だけ)。\n- 従来の関数と新しい速い経路の結果が一致することを、試験で確かめる。\n\n4. R と O の範囲\n- R(1299 規模の fixture): E1/E2 の測定区間(B1 と30 tick の完全な S/K/C、全イベント、signal)。規模に依存する同等性は、ここで確かめる。\n- O: E1/E2 と、E3/E4/E5 の全て(39件の scenario)。\n- 理由: E3/E4/E5 は、snapshot の API の拒否・cache・所有権の振る舞いで、世界の大きさに依存しない。同じ code の経路を O で全て通る。R でこれらを行うと、木の比較の量が増え、正式の validation の300秒、phase の1800秒、空き容量のどれにも収まらない(上の実測)。\n- 失うもの: R でだけ適用していた E3 の duplicate_facility(O の B1 は施設0件なので NA)。これは記録し、PASS に補わない。published_ids の重複は O で適用する。\n- SPEC と6条件は、scenario を R で行うことを求めていない(EQ5 は、R と O の同じ版の2 PID の比較の差が0であること)。EQ_S3 / S3b の計画の「R と O」は、この計画で置き換える。\n\n5. 変えないもの\n- SPEC、TASK、6条件、両方の validation と300秒、900秒、権限、課金、API の fallback の無効。\n- 正確な S の native の7つの phase、bundle、両方の validation、fresh で独立した Opus の6条件のレビュー、通常の統合と final。原本の 23/88・4/30 への加算は0。\n- 既存の試験の本体と、全ての失敗の履歴は残す。形式の変更に必要な修正は、記録して行う。\n" + }, + "EQ_S5_SCALE_PLAN_R02.txt": { + "sha256": "ebee0ce76561a677b4454c59a091bafef242a406f7099485a508620dccfbb739", + "bytes": 6569, + "full_unedited": "EQ_S5_SCALE_PLAN r02(P28-02-EQ repair 10。EQ_S5_SCALE_PLAN(r01)の §1、§2、§5 は、そのまま有効。この r02 は、r01 の §3 と §4 を置き換え、実際のエンジンでの診断で見つかった harness の不具合の扱いを加える。r01 の §4(R の E3/E4/E5 を外す案)は取り下げる。SPEC、TASK、6条件、eq/references、eq/registration、補足 r01/r02/r03 は変更しない)\n\n1. 範囲(r01 §4 を置き換える)\n- 凍結した参照 eq/references/OPT_CONTRACT_T1.md の §3 は「同等性 E1〜E5(EQ で凍結する。R と O の両方で行う)」と定める。\n- R と O の両方で、E1/E2(B1 と30 tick の完全な S/K/C、全イベント、signal)と、E3 の18件、E4 の5件、E5 の16件(39件の scenario)を行う。R でだけ適用する E3 の duplicate_facility も、R で適用する。\n- 全ての状態・イベント・所有権の検査を、R と O のそれぞれで行う。O の実行や NA の記録で、R の代わりにしない。\n- 診断の実行は、正式の受入に補わない。\n\n2. Python の計算(r01 §3 を置き換える。結果は従来の関数と同じ)\n- blob の木は、展開した bytes の SHA-256 が名前と一致するものだけを受け付け、内容の SHA を持つ共有のリストとして読む。変更しない。checkpoint の列は、必要な時点で1つずつ読む(R の木を同時に全部 memory に置かない)。\n- 比較: SHA が等しければ等しい。そうでなければ Python の == で比べる。validate_tree は、INT/BOOL の値を int に限り、浮動小数を16桁の hex 文字列に限るので、検証した木では == が JSON の完全一致と同じになる。\n- 正規化: systems.runtime.domain_events.recent_events の部分木を、木の JSON の中から直接読み出し、その4つの辞書だけからなる骨組みの木に入れて、従来の正規化の関数そのものを実行する。それ以外の部分に、profile root、予約の token、_us/_ms で終わる名前、save_service が無いことを、文字列の出現数で証明する(root は印字可能な ASCII で、[ ] \" , \\ { } を含まない場合に限る)。証明できない場合は、従来の全体の走査を行う。復元も、骨組みの上で従来の可逆の検査を行う。\n- 正規化の digest は、要素ごとの deepcopy をやめ、同じ JSON の bytes を作る実装にし、SHA で memo する(R の木で17.4秒が約1.2秒、値は一致)。\n- 組み立てた期待の状態(E3 の入力、X(B, event)、E5 の期待)は、変更する経路の辞書だけを複製して作る(deepcopy の後に変更したものと同じ JSON)。大きいものは SHA つきの木として正規化する。\n- 結合した事実と検査の結果に入れる大きな木は、SHA の記述子(typed_tree_sha、source_tree_sha、normalized)で記録する。内容は raw の blob にある。版の間で SHA が違う場合は、blob から木を作り直して、dict の順序だけの違いを許す比較を行う。\n- 新しい速い経路が従来の関数と同じ結果を出すことを、O の診断の状態の木162件の全てで確かめた(正規化した木、sidecar、正規化した SHA、復元。全て bytes で一致)。局所の試験にも加える。\n\n3. 実際のエンジンで見つかった harness の不具合(合成の試験では出なかったもの)\n- package の manifest の改変: Godot の JSON は数値を全て float として読むので、読み直して書き戻すと、改変しない整数の欄も 390.0 などに変わっていた。改変する key の1行だけを文字列で編集する。\n- guard の受領: 同じ理由で、probe の記録の整数が float になっていた。受領の原文をそのまま記録し、Python はそれを厳密に読んで、独立に保存した guard と照合し、原文の SHA も照合する。\n- instance ID: Godot の instance ID は符号つきの64bit で、RefCounted は負の値になる。検査は符号を受け付ける。実際の値は raw に残す。版の間の比較から除くのは、SPEC §3.2 が許す「instance ID の数値そのもの」(理由: プロセスごとに変わる値)だけで、従来どおり除外の理由と両方の実際の値を記録する。\n- E4 の戻り値: 64KB を超える戻り値は blob になるので、probe の中では戻り値そのものから事実を取る。\n\n4. 製品の既存の挙動と、harness の捕捉の区別\n- 製品の _restore_snapshot_internal は、復元に成功すると domain_events を新しい DomainEventStream に置き換え、購読者を引き継がない(autoload/simulation_runtime.gd:788、:1346)。そのため、E4 の restore の後、probe の購読は古い stream に残り、E4 の load の SAVE_LOADED を含む以後のイベントが届かなかった。\n- harness の捕捉: E3 と E4 の操作の直後に、stream が置き換わったかを確かめる。置き換わっていれば、新しい stream の recent_events() から未観測のイベントを公開の順序で取り戻し、新しい stream に購読し直す。事実(置き換え、新しい stream の購読者の ID の一覧、取り戻したイベントの ID)を記録する。instance ID は入れない。\n- 製品の事実: 購読者が引き継がれなかったことを、その scenario の「既存の不具合」として記録する。PASS にしない。\n- 完全性: 全イベントの網羅は、従来どおり counter の差、published_ids の差、実際のイベントの ID の対応で検証する。recent_events の保持の上限(256件)などで取り戻せないイベントがあれば、省かずに不足として失敗のまま残す。イベントの再採番、製品の変更、hook の差し替えはしない。\n- lifecycle の置き換えの一覧は、各 scenario の記録をつなげたものと完全に一致することを検査する。\n\n5. 実測(診断)\n- O: 約11秒、lifecycle の error 0件、Python の全検査(lifecycle、観測、report、E3、E45、結合、自己比較)が約23秒で通った。\n- R(修正の前の probe): 39件の scenario で exit 0、936秒(phase の制限1800秒の内)、lifecycle の error 0件、証拠154MB(blob の展開後3.3GB、gzip 後141MB)。修正後の R の測定と、Python の検査の時間は、別に記録する。\n" + }, + "EQ_S5_SCALE_PLAN_R03.txt": { + "sha256": "8417c9044f87825453a66bae45f10cdf90428198bd2c5c44c7bce01b18de9f89", + "bytes": 3740, + "full_unedited": "EQ_S5_SCALE_PLAN r03(P28-02-EQ repair 10。r01 と r02 は、そのまま有効。この r03 は、snapshot の signal の検査の規則を訂正する。製品の仕様と値は変えない。誤っていた harness の前提の訂正である)\n\n1. 誤っていた前提\n- EQ_S3_STAGE_PLAN r02 §2 は「測定の区間の各分に、ちょうど1組の snapshot_published → state_updated」を要求した。これは、製品が1 tick に1回だけ公開するという読み取りに基づいていた。\n- 実際の R(r2 の診断、正式の証拠ではない)では、分648に51組が出た。同じ分に COMMAND_COMPLETED が50件あり、他の分はコマンドの完了が0件で1組だった。r2 の検査はこの規則で失敗し、その失敗はそのまま残す。\n\n2. 製品の source に基づく根拠\n- autoload/simulation_runtime.gd:12616-12621: _publish_snapshot は snapshot_published と state_updated を、間にイベントを挟まずに出す。\n- :486-493、:508-512: submit_command は、受け付けると _next_command_id を1つ進める。時刻の指定が無ければ、現在の分に実行する予定になる。clock が止まっていて予定が来ていれば、その場で _process_commands を実行し、公開する(手動の stepping では clock は止まっている)。\n- :5768-5793: _process_commands は、実行したコマンドの COMMAND_COMPLETED / COMMAND_FAILED を出した後に公開する(その場の実行の経路、または保留の公開)。\n- :1745-1749: tick の終わりの公開。:1473: 成功した restore の公開。\n\n3. 検査の規則(check_eq.check_publishes)\n- probe は、各 signal に、発行の時点の domain_event の counter と _next_command_id を記録する(読取りだけ)。これで signal とイベントが1つの順序に並ぶ。\n- 組: snapshot_published の直後に、同じ分・同じ counter の state_updated。順序(分、イベントの counter、コマンドの counter)は単調。区間の counter の範囲の内。\n- 2つの公開の間のイベントは、後の公開に属する。直前のイベントがその分のコマンドの完了である公開は、コマンドによる公開で、末尾に続くコマンドの完了を自分の処理分とする。直前の公開からちょうど1件 submit されていて、その submit のコマンドが処理分に含まれていなければならない。それ以外の公開の前には、submit が0件でなければならない。区間の終わりに、公開されていない submit が残ってはならない。全てのコマンドの完了が、どれかの公開の処理分に含まれていなければならない。\n- 残りの公開(tick の終わりと成功した restore)の数は、実際に行った操作の数と完全に一致しなければならない: 測定の区間は各分ちょうど1。E3 は成功した restore/load の数(不正な入力の受理は既存の不具合として記録)。E4 は build(適用した場合)1、tick 1、restore 1、load 1、rejected_command 1。E5 は outside_in 2、inside_out 3。\n- これで、組の欠落(コマンドの直後の公開も、間にイベントの無い連続したコマンドの公開も、tick の終わりの公開も)、余分な組、順序の誤りは、全て失敗になる。O の全ての scenario と R の全ての scenario の実データ(診断)が、この規則の数え方と一致した。\n- 各分の組の実際の数は raw に残し、版の間では signal_order を完全一致で比べる。\n\n4. 変えないもの\n- r01 §5 のとおり。診断の実行は正式の受入に補わない。\n" + }, + "DESKTOP_EQ_NATIVE_FAILURE_REPAIR_DECISION_6F75C9A.json": { + "sha256": "7716a5ed89c91487b9a9163fc402eb447b51c143909de709c03a8347aa466a82", + "bytes": 2086, + "full_unedited": "{\"action\":\"request-repair\",\"task_id\":\"P28-02-EQ\",\"reason\":\"Exact-S native of S 6f75c9a0513aafe5bd6ae7ed46b0ffda6386ac50 failed and stays a failure. Phases import, parse-base and parse-wrapper passed. R-A (PID 62530) repeated the strict engine error 'Could not create directory: user://evidence' at eq_probe.gd:369 and was cancelled by Root with SIGTERM on the verified owned child only (NATIVE_6F75C9A_OWNED_CANCEL_R01.json SHA ce0fd25ae6d07de7bf895eab1adf1a149121882d34df5ddb428050648deca84b). execution.json SHA d6b060779e36084a87f08bfd0a490d1ec6b7ed68b1096f41104932331a0b02e3 records passed false. All 4 owned PIDs ended, cleanup errors are empty, source, player and pins are preserved, and no successful bundle was created, so formal validation is not invoked without a bundle. Desktop read-only diagnosis found two harness defects that the engine-free unit tests could not reach. (1) write_evidence passes user:// directly to make_dir_recursive_absolute under the runtime-switched guard profile; the working RESTART helpers globalize the path first. (2) typed_info encodes get_typed_script(), which is a null Object for unscripted typed containers, so encode rejects it as an unsupported Variant 24 although the Python side already expects [0]; the live R snapshot has no Object values. Free space fell sharply during R-A, and the evidence volume must be measured and kept complete. The user moved implementation and command to Claude Opus 5.5 because Codex usage is near its limit, so no new Codex or Astra run starts. Request the normal repair (submitted to repair_pending through owner intake of the external native failure, then repair_ready with repairs 10). The fix stays inside eq/**, and S, SPEC, TASK, the 6 conditions and both validations stay unchanged. The exact-S native over 7 phases, both validations, a fresh independent Opus review of all 6 conditions, and normal integration and final remain required. No original credit (23/88, 4/30). Decided by Claude Opus 5.5 in the Desktop control session after the user's takeover instruction; not a CLI commander result.\"}\n" + }, + "OPUS_IMPLEMENTATION_HANDOFF_6F75C9A.json": { + "sha256": "f49b2a68de10aef3a055571c845c49f5b04187137d1a1df6ba7d124aeabb8c22", + "bytes": 2940, + "full_unedited": "{\n \"at_utc\": \"2026-10-21T01:53:30.145584+00:00\",\n \"user_authority\": \"User explicitly delegated implementation and coordination to Claude Opus because Codex usage is near its limit.\",\n \"project\": \"the-tree-p28-02-eq\",\n \"task\": \"P28-02-EQ\",\n \"S\": \"6f75c9a0513aafe5bd6ae7ed46b0ffda6386ac50\",\n \"W\": \"/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement\",\n \"repairs\": 9,\n \"Runner_state\": \"submitted; native Root failure is not yet registered as a formal validation or repair\",\n \"local146_raw_sha256\": \"ff6fc0065772434f9ca35a1267e24d199057e339869a868942a41829327503bb\",\n \"local146_seconds\": 293.277,\n \"native_result\": {\n \"passed\": false,\n \"execution_sha256\": \"d6b060779e36084a87f08bfd0a490d1ec6b7ed68b1096f41104932331a0b02e3\",\n \"output\": \"/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p28-02-root-control-r01/native-6f75c9a-r01\",\n \"completed_phases\": [\n \"import\",\n \"parse-base\",\n \"parse-wrapper\"\n ],\n \"failed_phase\": \"R-A\",\n \"strict_error\": \"Could not create directory user://evidence at eq_probe.gd369\",\n \"guard_all5_true\": true,\n \"runtime_root_created\": true,\n \"runtime_root_contents\": [\n \"p28_eq\"\n ],\n \"source_preserved\": true,\n \"player_preserved\": true,\n \"pins_preserved\": true,\n \"owned4_PIDs_ended\": [\n 62247,\n 62390,\n 62465,\n 62530\n ],\n \"cleanup_errors\": [],\n \"successful_bundle_created\": false,\n \"owned_cancel_receipt\": \"NATIVE_6F75C9A_OWNED_CANCEL_R01.json\"\n },\n \"concrete_readonly_findings\": [\n \"eq_probe write_evidence passes user://evidence directly to DirAccess.make_dir_recursive_absolute; successful RESTART helpers globalize_path first.\",\n \"demand only appends lifecycle.errors and returns false; write_evidence returns but begin/run_e3 continue expensive scenarios after first fatal I/O failure.\",\n \"Free volume fell from3.29GB to about148MB during native, although raw logs were only tensKB; investigate memory/swap and complete evidence representation without dropping full required state/events.\"\n ],\n \"implementation_assignment\": \"Claude Opus5.5, no new Codex worker. Actual production Runner.core register_task currently excludes claude implementer at589. Existing Desktop session named Claude を implementer worker として有効化 may hold authorised support implementation; inspect and reuse it, do not duplicate.\",\n \"conditions\": \"All6 EQ conditions, both validations, independent fresh Opus all6, normal candidate/integration/final, then OPT T1/wholeunit remain mandatory. Native failure stays failure. Original30/88, formal23/88 and4/30, zero partial/original credit; API off/security unchanged.\",\n \"next\": \"Existing Desktop governor handles actual Opus implementation on retained work, storage, registered provider assignment and necessary tests. Root only exact-owner integration when required.\"\n}\n" + }, + "NORMAL_NATIVE_FAILURE_INTAKE_6F75C9A.json": { + "sha256": "38f7947dc4b9808f24cd0d362c8e74761841ca4c3ac50d9b9ab3658f10aa69d7", + "bytes": 1870, + "full_unedited": "{\n \"at\": 1792593136.068461,\n \"submitted\": \"6f75c9a0513aafe5bd6ae7ed46b0ffda6386ac50\",\n \"source\": \"Actual Root exact-S native (driver PID 58916), cancelled on the verified owned child after repeated strict errors; Desktop Opus diagnosis\",\n \"execution_sha256\": \"d6b060779e36084a87f08bfd0a490d1ec6b7ed68b1096f41104932331a0b02e3\",\n \"cancel_sha256\": \"ce0fd25ae6d07de7bf895eab1adf1a149121882d34df5ddb428050648deca84b\",\n \"handoff_sha256\": \"f49b2a68de10aef3a055571c845c49f5b04187137d1a1df6ba7d124aeabb8c22\",\n \"decision_sha256\": \"7716a5ed89c91487b9a9163fc402eb447b51c143909de709c03a8347aa466a82\",\n \"native_passed\": false,\n \"completed_phases\": [\n \"import\",\n \"parse-base\",\n \"parse-wrapper\"\n ],\n \"failed_phase\": \"R-A\",\n \"formal_validation_not_invoked_without_bundle\": true,\n \"old_S_retained\": true,\n \"original_credit\": 0,\n \"state\": \"repair_ready\",\n \"repairs\": 10,\n \"delegation\": {\n \"at\": 1792593136.070688,\n \"implementer_service\": \"claude\",\n \"implementer_model\": \"claude-opus-5-5\",\n \"implementer_session\": \"local_a7f85421-3eed-4482-8030-c0dca669573a (Claude Desktop, Code tab)\",\n \"policy_allowed_services_includes_claude\": true,\n \"user_statement\": \"Codexの使用量上限いきそうなので、作業をひきとって\",\n \"user_statement_relayed_addendum\": \"ユーザーはこのチャットでも『実装担当含めOpusに委任』と明示済み。指揮と実装をOpus5.5で続け、Codex/Astraの新runは開始しない\",\n \"contract_worker_field_unchanged\": \"codex\",\n \"note\": \"Contract is immutable and keeps worker codex as registered; the actual implementer for repair 10 onward is Claude Opus 5.5 in the Desktop session, submitted through the normal Runner.submit gate. The independent review stays a separate fresh Opus session.\",\n \"no_new_codex_run\": true\n },\n \"installed_Runner_and_policy_unchanged\": true\n}\n" + } + }, + "note": "Preserved instruction and decision bytes for review; not a new commander decision." + } +} diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT.sha256 index 5f5577b..f23b81d 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT.sha256 +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT.sha256 @@ -1 +1 @@ -ff6fc0065772434f9ca35a1267e24d199057e339869a868942a41829327503bb UNIT_OUTPUT.txt +7372a382cc2f3c090013874d8f28f17cad4cb1b965ad86c86de7a21fc2d851a8 UNIT_OUTPUT.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT.txt index ee7919a..5cbff21 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT.txt +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT.txt @@ -1,154 +1,167 @@ -test_all_operations (__main__.Diffs) ... ok -test_invalid_operations (__main__.Diffs) ... ok -test_reconstruction_and_proofs (__main__.Diffs) ... ok -test_attempt_to_normalize_violation_rejected (__main__.Normalization) ... ok -test_environment_values_differ_but_normal_form_equal (__main__.Normalization) ... ok -test_every_save_event_reversible (__main__.Normalization) ... ok -test_f3_keeps_relative_paths_and_words (__main__.Normalization) ... ok -test_guard_mismatch (__main__.Normalization) ... ok -test_nested_lookalike_is_not_eligible (__main__.Normalization) ... ok -test_original_transport_sha_detects_forged_timing (__main__.Normalization) ... ok -test_partial_timing_payload_rejected (__main__.Normalization) ... ok -test_prefix_boundary_and_reserved_token (__main__.Normalization) ... ok -test_sidecar_missing_duplicate_and_forged_paths (__main__.Normalization) ... ok -test_snapshot_and_latest_reversible (__main__.Normalization) ... ok -test_snapshot_event_outside_recent_is_not_eligible (__main__.Normalization) ... ok -test_wrong_event_and_source_are_preserved (__main__.Normalization) ... ok -test_wrong_timing_type_and_negative (__main__.Normalization) ... ok -test_all_events_beyond_recent_window (__main__.Reports) ... ok -test_all_semantic_layers_compared (__main__.Reports) ... ok -test_digest_alone_is_not_enough (__main__.Reports) ... ok -test_event_original_types_and_order (__main__.Reports) ... ok -test_event_start_and_ids (__main__.Reports) ... ok -test_exclusions_keep_actual_values (__main__.Reports) ... ok -test_handler_sets_and_counts (__main__.Reports) ... ok -test_observation_full_layers (__main__.Reports) ... ok -test_product_digest_self_consistency (__main__.Reports) ... ok -test_same_report (__main__.Reports) ... ok -test_scenario_existing_failures_preserved (__main__.Reports) ... ok -test_timing_digest_rule (__main__.Reports) ... ok -test_unknown_or_missing_fields_rejected (__main__.Reports) ... ok -test_violation_presence_and_difference (__main__.Reports) ... ok -test_O_cadence (__main__.S2Format) ... ok -test_counter_and_published_ids_binding (__main__.S2Format) ... ok -test_diff_and_same_as_S_transport (__main__.S2Format) ... ok -test_digest_and_scenario_contradiction (__main__.S2Format) ... ok -test_event_no_drop_duplicate_remap (__main__.S2Format) ... ok -test_event_original_field_types_mandatory (__main__.S2Format) ... ok -test_guard_actual_not_assumed (__main__.S2Format) ... ok -test_harness_digest_allows_only_dictionary_order (__main__.S2Format) ... ok -test_join_is_copy_and_retains_normalization_proof (__main__.S2Format) ... ok -test_kernel_cache_contradictions (__main__.S2Format) ... ok -test_lifecycle_guard_errors_and_boundaries (__main__.S2Format) ... ok -test_missing_full_state_not_digest_only (__main__.S2Format) ... ok -test_normalized_digest_and_raw_tree_are_both_bound (__main__.S2Format) ... ok -test_product_event_shape_and_typed_array (__main__.S2Format) ... ok -test_raw_observation_binding (__main__.S2Format) ... ok -test_roundtrip_tree_sha_and_raw_sha (__main__.S2Format) ... ok -test_s2_valid_and_not_formal_acceptance (__main__.S2Format) ... ok -test_state_witness_and_observation_mutation (__main__.S2Format) ... ok -test_stdout_exactly_one_line (__main__.S2Format) ... ok -test_autoload_class_and_script_import (__main__.S2Static) ... ok -test_comment_does_not_supply_proof (__main__.S2Static) ... ok -test_current_probe (__main__.S2Static) ... ok -test_full_state_and_godot_roundtrip_required (__main__.S2Static) ... ok -test_no_changes_outside_preparation_or_step (__main__.S2Static) ... ok -test_no_event_cap_or_duplicate_report (__main__.S2Static) ... ok -test_pause_and_step_arguments (__main__.S2Static) ... ok -test_textual_stringname_ordering (__main__.S2Static) ... ok -test_unlisted_live_method_and_late_preparation (__main__.S2Static) ... ok -test_variant_inference (__main__.S2Static) ... ok -test_X_recent_limit_and_counter (__main__.S3a) ... ok -test_duplicate_JSON_key_rejected (__main__.S3a) ... ok -test_e3_NA_cannot_be_PASS_or_applied (__main__.S3a) ... ok -test_e3_coverage_input_and_event_count_binding (__main__.S3a) ... ok -test_e3_invented_codes_and_missing_load_code (__main__.S3a) ... ok -test_e3_valid_R_and_O_records (__main__.S3a) ... ok -test_envelope_duplicates_not_defect (__main__.S3a) ... ok -test_event_count_defect_not_silently_accepted (__main__.S3a) ... ok -test_exact_phase_keys (__main__.S3a) ... ok -test_interval_gap_rejected (__main__.S3a) ... ok -test_invalid_input_accepted_is_not_PASS (__main__.S3a) ... ok -test_load_payload_and_pause_outcome (__main__.S3a) ... ok -test_operation_moved_outside_scenario_rejected (__main__.S3a) ... ok -test_package_fixed_mutations_and_hashes (__main__.S3a) ... ok -test_probe_connection_required (__main__.S3a) ... ok -test_rejection_mutation_retained_as_defect (__main__.S3a) ... ok -test_save_refusal_makes_load_NA (__main__.S3a) ... ok -test_scenario_mutation_static_boundary (__main__.S3a) ... ok -test_signals_all_minutes_and_order (__main__.S3a) ... ok -test_E5_cached_digest_defect_is_comparable (__main__.S3b) ... ok -test_NA_not_PASS (__main__.S3b) ... ok -test_aliasing_cannot_be_PASS (__main__.S3b) ... ok -test_aliasing_missing_record (__main__.S3b) ... ok -test_all_paths_and_ownership_R_O (__main__.S3b) ... ok -test_digest_defect_other_checkpoint_still_rejected (__main__.S3b) ... ok -test_digest_materialization_required (__main__.S3b) ... ok -test_empty_registry_not_NA (__main__.S3b) ... ok -test_event_count_mismatch (__main__.S3b) ... ok -test_facts_normalization_is_reversible (__main__.S3b) ... ok -test_first_placeable_choice (__main__.S3b) ... ok -test_interval_gap (__main__.S3b) ... ok -test_joined_s3b_self_comparison (__main__.S3b) ... ok -test_load_X_not_digest_only (__main__.S3b) ... ok -test_load_extra_event (__main__.S3b) ... ok -test_missing_path_and_combination (__main__.S3b) ... ok -test_missing_preview_observation (__main__.S3b) ... ok -test_missing_trial (__main__.S3b) ... ok -test_nested_mutation_required (__main__.S3b) ... ok -test_no_staleness_assertion_for_non_tick (__main__.S3b) ... ok -test_ownership_fact_dictionary_order_fallback (__main__.S3b) ... ok -test_path_order (__main__.S3b) ... ok -test_restore_extra_event (__main__.S3b) ... ok -test_signal_facts_cannot_be_dropped (__main__.S3b) ... ok -test_sort_rule_rejected (__main__.S3b) ... ok -test_static_handler_and_outside_mutations (__main__.S3b) ... ok -test_unpreviewed_choice (__main__.S3b) ... ok -test_wrong_registry_in_either_role (__main__.S3b) ... ok -test_checkout_temp_destination_rejected (__main__.S4Bundle) ... ok -test_existing_output_never_overwritten (__main__.S4Bundle) ... ok -test_import_closure_rejections (__main__.S4Bundle) ... ok -test_missing_bundle_manifest_seal_and_changed_bytes (__main__.S4Bundle) ... ok -test_missing_private_evidence_and_extra_rejected (__main__.S4Bundle) ... ok -test_missing_profile_not_export_success (__main__.S4Bundle) ... ok -test_phase_role_pid_audio_and_guard_rejected (__main__.S4Bundle) ... ok -test_rebound_lifecycle_and_scenario_contradictions (__main__.S4Bundle) ... ok -test_seal_normal_and_changes_not_native_proof (__main__.S4Bundle) ... ok -test_synthetic_phase_all_real_checkers_not_native_proof (__main__.S4Bundle) ... ok -test_copied_manifest_root_and_destination_count_rejected (__main__.S4NativeBundleLogic) ... ok -test_failure_keeps_raw_and_no_bundle_without_starting_engine (__main__.S4NativeBundleLogic) ... ok -test_gate_none_success_not_boolean (__main__.S4NativeBundleLogic) ... ok -test_receipt_and_source_rejection_matrix (__main__.S4NativeBundleLogic) ... ok -test_synthetic_full_bundle_positive_not_native_evidence (__main__.S4NativeBundleLogic) ... ok -test_check_accepts_true (__main__.S4ProbeAdmission) ... ok -test_check_rejects_false_all_errors (__main__.S4ProbeAdmission) ... ok -test_run_admission_accepts_true_mock_launch_only (__main__.S4ProbeAdmission) ... ok -test_run_admission_rejects_false_without_engine (__main__.S4ProbeAdmission) ... ok -test_nine_original_destinations_required (__main__.S4RemainingBindings) ... ok -test_nonzero_determinism_rejected_after_real_join (__main__.S4RemainingBindings) ... ok -test_owned_lifecycle_exit_diagnostic_and_profile_rejections (__main__.S4RemainingBindings) ... ok -test_verifier_accepts_true_recomputes_raw (__main__.S4RemainingBindings) ... ok -test_verifier_rejects_false_with_every_error (__main__.S4RemainingBindings) ... ok -test_cached_verdict_not_trusted (__main__.S4StoredResultBindings) ... ok -test_missing_sidecar_rejected_after_seal (__main__.S4StoredResultBindings) ... ok -test_raw_joined_substitution_rejected_after_seal (__main__.S4StoredResultBindings) ... ok -test_fixed_scenario_paths (__main__.SourcesAndMetrics) ... ok -test_metric_ranges (__main__.SourcesAndMetrics) ... ok -test_source_closure_synthetic_registered_map (__main__.SourcesAndMetrics) ... ok -test_source_pin_is_not_caller_controlled (__main__.SourcesAndMetrics) ... ok -test_array_order_and_all_differences (__main__.TypedTrees) ... ok -test_components_and_sha (__main__.TypedTrees) ... ok -test_deep_state_not_truncated (__main__.TypedTrees) ... ok -test_duplicate_textual_keys_rejected (__main__.TypedTrees) ... ok -test_exact_and_types (__main__.TypedTrees) ... ok -test_nested_order_all_paths (__main__.TypedTrees) ... ok -test_nonstring_keys_keep_types_and_values (__main__.TypedTrees) ... ok -test_unsupported_and_malformed (__main__.TypedTrees) ... ok +test_all_operations (__main__.Diffs.test_all_operations) ... ok +test_invalid_operations (__main__.Diffs.test_invalid_operations) ... ok +test_reconstruction_and_proofs (__main__.Diffs.test_reconstruction_and_proofs) ... ok +test_attempt_to_normalize_violation_rejected (__main__.Normalization.test_attempt_to_normalize_violation_rejected) ... ok +test_environment_values_differ_but_normal_form_equal (__main__.Normalization.test_environment_values_differ_but_normal_form_equal) ... ok +test_every_save_event_reversible (__main__.Normalization.test_every_save_event_reversible) ... ok +test_f3_keeps_relative_paths_and_words (__main__.Normalization.test_f3_keeps_relative_paths_and_words) ... ok +test_guard_mismatch (__main__.Normalization.test_guard_mismatch) ... ok +test_nested_lookalike_is_not_eligible (__main__.Normalization.test_nested_lookalike_is_not_eligible) ... ok +test_original_transport_sha_detects_forged_timing (__main__.Normalization.test_original_transport_sha_detects_forged_timing) ... ok +test_partial_timing_payload_rejected (__main__.Normalization.test_partial_timing_payload_rejected) ... ok +test_prefix_boundary_and_reserved_token (__main__.Normalization.test_prefix_boundary_and_reserved_token) ... ok +test_sidecar_missing_duplicate_and_forged_paths (__main__.Normalization.test_sidecar_missing_duplicate_and_forged_paths) ... ok +test_snapshot_and_latest_reversible (__main__.Normalization.test_snapshot_and_latest_reversible) ... ok +test_snapshot_event_outside_recent_is_not_eligible (__main__.Normalization.test_snapshot_event_outside_recent_is_not_eligible) ... ok +test_wrong_event_and_source_are_preserved (__main__.Normalization.test_wrong_event_and_source_are_preserved) ... ok +test_wrong_timing_type_and_negative (__main__.Normalization.test_wrong_timing_type_and_negative) ... ok +test_all_events_beyond_recent_window (__main__.Reports.test_all_events_beyond_recent_window) ... ok +test_all_semantic_layers_compared (__main__.Reports.test_all_semantic_layers_compared) ... ok +test_digest_alone_is_not_enough (__main__.Reports.test_digest_alone_is_not_enough) ... ok +test_event_original_types_and_order (__main__.Reports.test_event_original_types_and_order) ... ok +test_event_start_and_ids (__main__.Reports.test_event_start_and_ids) ... ok +test_exclusions_keep_actual_values (__main__.Reports.test_exclusions_keep_actual_values) ... ok +test_handler_sets_and_counts (__main__.Reports.test_handler_sets_and_counts) ... ok +test_observation_full_layers (__main__.Reports.test_observation_full_layers) ... ok +test_product_digest_self_consistency (__main__.Reports.test_product_digest_self_consistency) ... ok +test_same_report (__main__.Reports.test_same_report) ... ok +test_scenario_existing_failures_preserved (__main__.Reports.test_scenario_existing_failures_preserved) ... ok +test_timing_digest_rule (__main__.Reports.test_timing_digest_rule) ... ok +test_unknown_or_missing_fields_rejected (__main__.Reports.test_unknown_or_missing_fields_rejected) ... ok +test_violation_presence_and_difference (__main__.Reports.test_violation_presence_and_difference) ... ok +test_O_cadence (__main__.S2Format.test_O_cadence) ... ok +test_counter_and_published_ids_binding (__main__.S2Format.test_counter_and_published_ids_binding) ... ok +test_diff_and_same_as_S_transport (__main__.S2Format.test_diff_and_same_as_S_transport) ... ok +test_digest_and_scenario_contradiction (__main__.S2Format.test_digest_and_scenario_contradiction) ... ok +test_event_no_drop_duplicate_remap (__main__.S2Format.test_event_no_drop_duplicate_remap) ... ok +test_event_original_field_types_mandatory (__main__.S2Format.test_event_original_field_types_mandatory) ... ok +test_guard_actual_not_assumed (__main__.S2Format.test_guard_actual_not_assumed) ... ok +test_harness_digest_allows_only_dictionary_order (__main__.S2Format.test_harness_digest_allows_only_dictionary_order) ... ok +test_join_is_copy_and_retains_normalization_proof (__main__.S2Format.test_join_is_copy_and_retains_normalization_proof) ... ok +test_kernel_cache_contradictions (__main__.S2Format.test_kernel_cache_contradictions) ... ok +test_lifecycle_guard_errors_and_boundaries (__main__.S2Format.test_lifecycle_guard_errors_and_boundaries) ... ok +test_missing_full_state_not_digest_only (__main__.S2Format.test_missing_full_state_not_digest_only) ... ok +test_normalized_digest_and_raw_tree_are_both_bound (__main__.S2Format.test_normalized_digest_and_raw_tree_are_both_bound) ... ok +test_product_event_shape_and_typed_array (__main__.S2Format.test_product_event_shape_and_typed_array) ... ok +test_raw_observation_binding (__main__.S2Format.test_raw_observation_binding) ... ok +test_roundtrip_tree_sha_and_raw_sha (__main__.S2Format.test_roundtrip_tree_sha_and_raw_sha) ... ok +test_s2_valid_and_not_formal_acceptance (__main__.S2Format.test_s2_valid_and_not_formal_acceptance) ... ok +test_state_witness_and_observation_mutation (__main__.S2Format.test_state_witness_and_observation_mutation) ... ok +test_stdout_exactly_one_line (__main__.S2Format.test_stdout_exactly_one_line) ... ok +test_autoload_class_and_script_import (__main__.S2Static.test_autoload_class_and_script_import) ... ok +test_comment_does_not_supply_proof (__main__.S2Static.test_comment_does_not_supply_proof) ... ok +test_current_probe (__main__.S2Static.test_current_probe) ... ok +test_full_state_and_godot_roundtrip_required (__main__.S2Static.test_full_state_and_godot_roundtrip_required) ... ok +test_no_changes_outside_preparation_or_step (__main__.S2Static.test_no_changes_outside_preparation_or_step) ... ok +test_no_event_cap_or_duplicate_report (__main__.S2Static.test_no_event_cap_or_duplicate_report) ... ok +test_pause_and_step_arguments (__main__.S2Static.test_pause_and_step_arguments) ... ok +test_textual_stringname_ordering (__main__.S2Static.test_textual_stringname_ordering) ... ok +test_unlisted_live_method_and_late_preparation (__main__.S2Static.test_unlisted_live_method_and_late_preparation) ... ok +test_variant_inference (__main__.S2Static.test_variant_inference) ... ok +test_X_recent_limit_and_counter (__main__.S3a.test_X_recent_limit_and_counter) ... ok +test_duplicate_JSON_key_rejected (__main__.S3a.test_duplicate_JSON_key_rejected) ... ok +test_e3_NA_cannot_be_PASS_or_applied (__main__.S3a.test_e3_NA_cannot_be_PASS_or_applied) ... ok +test_e3_coverage_input_and_event_count_binding (__main__.S3a.test_e3_coverage_input_and_event_count_binding) ... ok +test_e3_invented_codes_and_missing_load_code (__main__.S3a.test_e3_invented_codes_and_missing_load_code) ... ok +test_e3_valid_R_and_O_records (__main__.S3a.test_e3_valid_R_and_O_records) ... ok +test_envelope_duplicates_not_defect (__main__.S3a.test_envelope_duplicates_not_defect) ... ok +test_event_count_defect_not_silently_accepted (__main__.S3a.test_event_count_defect_not_silently_accepted) ... ok +test_exact_phase_keys (__main__.S3a.test_exact_phase_keys) ... ok +test_interval_gap_rejected (__main__.S3a.test_interval_gap_rejected) ... ok +test_invalid_input_accepted_is_not_PASS (__main__.S3a.test_invalid_input_accepted_is_not_PASS) ... ok +test_load_payload_and_pause_outcome (__main__.S3a.test_load_payload_and_pause_outcome) ... ok +test_operation_moved_outside_scenario_rejected (__main__.S3a.test_operation_moved_outside_scenario_rejected) ... ok +test_package_fixed_mutations_and_hashes (__main__.S3a.test_package_fixed_mutations_and_hashes) ... ok +test_probe_connection_required (__main__.S3a.test_probe_connection_required) ... ok +test_rejection_mutation_retained_as_defect (__main__.S3a.test_rejection_mutation_retained_as_defect) ... ok +test_save_refusal_makes_load_NA (__main__.S3a.test_save_refusal_makes_load_NA) ... ok +test_scenario_mutation_static_boundary (__main__.S3a.test_scenario_mutation_static_boundary) ... ok +test_signals_all_minutes_and_order (__main__.S3a.test_signals_all_minutes_and_order) ... ok +test_E5_cached_digest_defect_is_comparable (__main__.S3b.test_E5_cached_digest_defect_is_comparable) ... ok +test_NA_not_PASS (__main__.S3b.test_NA_not_PASS) ... ok +test_aliasing_cannot_be_PASS (__main__.S3b.test_aliasing_cannot_be_PASS) ... ok +test_aliasing_missing_record (__main__.S3b.test_aliasing_missing_record) ... ok +test_all_paths_and_ownership_R_O (__main__.S3b.test_all_paths_and_ownership_R_O) ... ok +test_digest_defect_other_checkpoint_still_rejected (__main__.S3b.test_digest_defect_other_checkpoint_still_rejected) ... ok +test_digest_materialization_required (__main__.S3b.test_digest_materialization_required) ... ok +test_empty_registry_not_NA (__main__.S3b.test_empty_registry_not_NA) ... ok +test_event_count_mismatch (__main__.S3b.test_event_count_mismatch) ... ok +test_facts_normalization_is_reversible (__main__.S3b.test_facts_normalization_is_reversible) ... ok +test_first_placeable_choice (__main__.S3b.test_first_placeable_choice) ... ok +test_interval_gap (__main__.S3b.test_interval_gap) ... ok +test_joined_s3b_self_comparison (__main__.S3b.test_joined_s3b_self_comparison) ... ok +test_load_X_not_digest_only (__main__.S3b.test_load_X_not_digest_only) ... ok +test_load_extra_event (__main__.S3b.test_load_extra_event) ... ok +test_missing_path_and_combination (__main__.S3b.test_missing_path_and_combination) ... ok +test_missing_preview_observation (__main__.S3b.test_missing_preview_observation) ... ok +test_missing_trial (__main__.S3b.test_missing_trial) ... ok +test_nested_mutation_required (__main__.S3b.test_nested_mutation_required) ... ok +test_no_staleness_assertion_for_non_tick (__main__.S3b.test_no_staleness_assertion_for_non_tick) ... ok +test_ownership_fact_dictionary_order_fallback (__main__.S3b.test_ownership_fact_dictionary_order_fallback) ... ok +test_path_order (__main__.S3b.test_path_order) ... ok +test_restore_extra_event (__main__.S3b.test_restore_extra_event) ... ok +test_signal_facts_cannot_be_dropped (__main__.S3b.test_signal_facts_cannot_be_dropped) ... ok +test_sort_rule_rejected (__main__.S3b.test_sort_rule_rejected) ... ok +test_static_handler_and_outside_mutations (__main__.S3b.test_static_handler_and_outside_mutations) ... ok +test_unpreviewed_choice (__main__.S3b.test_unpreviewed_choice) ... ok +test_wrong_registry_in_either_role (__main__.S3b.test_wrong_registry_in_either_role) ... ok +test_checkout_temp_destination_rejected (__main__.S4Bundle.test_checkout_temp_destination_rejected) ... ok +test_existing_output_never_overwritten (__main__.S4Bundle.test_existing_output_never_overwritten) ... ok +test_import_closure_rejections (__main__.S4Bundle.test_import_closure_rejections) ... ok +test_missing_bundle_manifest_seal_and_changed_bytes (__main__.S4Bundle.test_missing_bundle_manifest_seal_and_changed_bytes) ... ok +test_missing_private_evidence_and_extra_rejected (__main__.S4Bundle.test_missing_private_evidence_and_extra_rejected) ... ok +test_missing_profile_not_export_success (__main__.S4Bundle.test_missing_profile_not_export_success) ... ok +test_phase_role_pid_audio_and_guard_rejected (__main__.S4Bundle.test_phase_role_pid_audio_and_guard_rejected) ... ok +test_rebound_lifecycle_and_scenario_contradictions (__main__.S4Bundle.test_rebound_lifecycle_and_scenario_contradictions) ... ok +test_seal_normal_and_changes_not_native_proof (__main__.S4Bundle.test_seal_normal_and_changes_not_native_proof) ... ok +test_synthetic_phase_all_real_checkers_not_native_proof (__main__.S4Bundle.test_synthetic_phase_all_real_checkers_not_native_proof) ... ok +test_copied_manifest_root_and_destination_count_rejected (__main__.S4NativeBundleLogic.test_copied_manifest_root_and_destination_count_rejected) ... ok +test_failure_keeps_raw_and_no_bundle_without_starting_engine (__main__.S4NativeBundleLogic.test_failure_keeps_raw_and_no_bundle_without_starting_engine) ... ok +test_gate_none_success_not_boolean (__main__.S4NativeBundleLogic.test_gate_none_success_not_boolean) ... ok +test_receipt_and_source_rejection_matrix (__main__.S4NativeBundleLogic.test_receipt_and_source_rejection_matrix) ... ok +test_synthetic_full_bundle_positive_not_native_evidence (__main__.S4NativeBundleLogic.test_synthetic_full_bundle_positive_not_native_evidence) ... ok +test_check_accepts_true (__main__.S4ProbeAdmission.test_check_accepts_true) ... ok +test_check_rejects_false_all_errors (__main__.S4ProbeAdmission.test_check_rejects_false_all_errors) ... ok +test_run_admission_accepts_true_mock_launch_only (__main__.S4ProbeAdmission.test_run_admission_accepts_true_mock_launch_only) ... ok +test_run_admission_rejects_false_without_engine (__main__.S4ProbeAdmission.test_run_admission_rejects_false_without_engine) ... ok +test_nine_original_destinations_required (__main__.S4RemainingBindings.test_nine_original_destinations_required) ... ok +test_nonzero_determinism_rejected_after_real_join (__main__.S4RemainingBindings.test_nonzero_determinism_rejected_after_real_join) ... ok +test_owned_lifecycle_exit_diagnostic_and_profile_rejections (__main__.S4RemainingBindings.test_owned_lifecycle_exit_diagnostic_and_profile_rejections) ... ok +test_verifier_accepts_true_recomputes_raw (__main__.S4RemainingBindings.test_verifier_accepts_true_recomputes_raw) ... ok +test_verifier_rejects_false_with_every_error (__main__.S4RemainingBindings.test_verifier_rejects_false_with_every_error) ... ok +test_cached_verdict_not_trusted (__main__.S4StoredResultBindings.test_cached_verdict_not_trusted) ... ok +test_missing_sidecar_rejected_after_seal (__main__.S4StoredResultBindings.test_missing_sidecar_rejected_after_seal) ... ok +test_raw_joined_substitution_rejected_after_seal (__main__.S4StoredResultBindings.test_raw_joined_substitution_rejected_after_seal) ... ok +test_blob_transport_is_verified_and_bound (__main__.S5.test_blob_transport_is_verified_and_bound) ... ok +test_blob_trees_get_the_same_full_validation_as_inline (__main__.S5.test_blob_trees_get_the_same_full_validation_as_inline) ... ok +test_compare_and_digest_equal_s1_reference (__main__.S5.test_compare_and_digest_equal_s1_reference) ... ok +test_event_stream_replacement_is_existing_defect_not_pass (__main__.S5.test_event_stream_replacement_is_existing_defect_not_pass) ... ok +test_every_checkpoint_full_tree_verified_like_inline (__main__.S5.test_every_checkpoint_full_tree_verified_like_inline) +S5 drops the diff chain: each checkpoint carries a complete tree, verified alone. ... ok +test_fast_normalization_equals_original (__main__.S5.test_fast_normalization_equals_original) ... ok +test_labelled_harness_digest_falls_back_to_dictionary_order_only (__main__.S5.test_labelled_harness_digest_falls_back_to_dictionary_order_only) ... ok +test_lifecycle_binds_replacements_guard_text_and_blobs (__main__.S5.test_lifecycle_binds_replacements_guard_text_and_blobs) ... ok +test_manifest_numbers_keep_their_type (__main__.S5.test_manifest_numbers_keep_their_type) ... ok +test_memo_scope_same_results_and_restores_gc (__main__.S5.test_memo_scope_same_results_and_restores_gc) ... ok +test_path_copy_builders_equal_deepcopy_reference (__main__.S5.test_path_copy_builders_equal_deepcopy_reference) ... ok +test_probe_static_full_tree_blob_and_stream_requirements (__main__.S5.test_probe_static_full_tree_blob_and_stream_requirements) ... ok +test_publish_pairs_bound_to_source_causes (__main__.S5.test_publish_pairs_bound_to_source_causes) ... ok +test_signed_instance_ids_raw_kept_and_excluded (__main__.S5.test_signed_instance_ids_raw_kept_and_excluded) ... ok +test_validate_tree_equals_s1_reference_on_mutations (__main__.S5.test_validate_tree_equals_s1_reference_on_mutations) ... ok +test_fixed_scenario_paths (__main__.SourcesAndMetrics.test_fixed_scenario_paths) ... ok +test_metric_ranges (__main__.SourcesAndMetrics.test_metric_ranges) ... ok +test_source_closure_synthetic_registered_map (__main__.SourcesAndMetrics.test_source_closure_synthetic_registered_map) ... ok +test_source_pin_is_not_caller_controlled (__main__.SourcesAndMetrics.test_source_pin_is_not_caller_controlled) ... ok +test_array_order_and_all_differences (__main__.TypedTrees.test_array_order_and_all_differences) ... ok +test_components_and_sha (__main__.TypedTrees.test_components_and_sha) ... ok +test_deep_state_not_truncated (__main__.TypedTrees.test_deep_state_not_truncated) ... ok +test_duplicate_textual_keys_rejected (__main__.TypedTrees.test_duplicate_textual_keys_rejected) ... ok +test_exact_and_types (__main__.TypedTrees.test_exact_and_types) ... ok +test_nested_order_all_paths (__main__.TypedTrees.test_nested_order_all_paths) ... ok +test_nonstring_keys_keep_types_and_values (__main__.TypedTrees.test_nonstring_keys_keep_types_and_values) ... ok +test_unsupported_and_malformed (__main__.TypedTrees.test_unsupported_and_malformed) ... ok ---------------------------------------------------------------------- -Ran 146 tests in 293.277s +Ran 161 tests in 121.627s OK - -exit_code=0 -wall_seconds=293.5742515 diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_01.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_01.sha256 new file mode 100644 index 0000000..4b1d9c8 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_01.sha256 @@ -0,0 +1 @@ +f52106391229dbf46d82e7dd9cdbc290b65f2ae9ed0e2a49d2cd4933c8af4ade UNIT_OUTPUT_S5_ATTEMPT_01.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_01.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_01.txt new file mode 100644 index 0000000..77e10ca --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_01.txt @@ -0,0 +1,316 @@ +test_all_operations (__main__.Diffs.test_all_operations) ... ok +test_invalid_operations (__main__.Diffs.test_invalid_operations) ... ok +test_reconstruction_and_proofs (__main__.Diffs.test_reconstruction_and_proofs) ... ok +test_attempt_to_normalize_violation_rejected (__main__.Normalization.test_attempt_to_normalize_violation_rejected) ... ok +test_environment_values_differ_but_normal_form_equal (__main__.Normalization.test_environment_values_differ_but_normal_form_equal) ... ok +test_every_save_event_reversible (__main__.Normalization.test_every_save_event_reversible) ... ok +test_f3_keeps_relative_paths_and_words (__main__.Normalization.test_f3_keeps_relative_paths_and_words) ... ok +test_guard_mismatch (__main__.Normalization.test_guard_mismatch) ... ok +test_nested_lookalike_is_not_eligible (__main__.Normalization.test_nested_lookalike_is_not_eligible) ... ok +test_original_transport_sha_detects_forged_timing (__main__.Normalization.test_original_transport_sha_detects_forged_timing) ... ok +test_partial_timing_payload_rejected (__main__.Normalization.test_partial_timing_payload_rejected) ... ok +test_prefix_boundary_and_reserved_token (__main__.Normalization.test_prefix_boundary_and_reserved_token) ... ok +test_sidecar_missing_duplicate_and_forged_paths (__main__.Normalization.test_sidecar_missing_duplicate_and_forged_paths) ... ok +test_snapshot_and_latest_reversible (__main__.Normalization.test_snapshot_and_latest_reversible) ... ok +test_snapshot_event_outside_recent_is_not_eligible (__main__.Normalization.test_snapshot_event_outside_recent_is_not_eligible) ... ok +test_wrong_event_and_source_are_preserved (__main__.Normalization.test_wrong_event_and_source_are_preserved) ... ok +test_wrong_timing_type_and_negative (__main__.Normalization.test_wrong_timing_type_and_negative) ... ok +test_all_events_beyond_recent_window (__main__.Reports.test_all_events_beyond_recent_window) ... ok +test_all_semantic_layers_compared (__main__.Reports.test_all_semantic_layers_compared) ... ok +test_digest_alone_is_not_enough (__main__.Reports.test_digest_alone_is_not_enough) ... ok +test_event_original_types_and_order (__main__.Reports.test_event_original_types_and_order) ... ok +test_event_start_and_ids (__main__.Reports.test_event_start_and_ids) ... ok +test_exclusions_keep_actual_values (__main__.Reports.test_exclusions_keep_actual_values) ... ok +test_handler_sets_and_counts (__main__.Reports.test_handler_sets_and_counts) ... ok +test_observation_full_layers (__main__.Reports.test_observation_full_layers) ... ok +test_product_digest_self_consistency (__main__.Reports.test_product_digest_self_consistency) ... ok +test_same_report (__main__.Reports.test_same_report) ... ok +test_scenario_existing_failures_preserved (__main__.Reports.test_scenario_existing_failures_preserved) ... ok +test_timing_digest_rule (__main__.Reports.test_timing_digest_rule) ... ok +test_unknown_or_missing_fields_rejected (__main__.Reports.test_unknown_or_missing_fields_rejected) ... ok +test_violation_presence_and_difference (__main__.Reports.test_violation_presence_and_difference) ... ok +test_O_cadence (__main__.S2Format.test_O_cadence) ... ok +test_counter_and_published_ids_binding (__main__.S2Format.test_counter_and_published_ids_binding) ... ok +test_diff_and_same_as_S_transport (__main__.S2Format.test_diff_and_same_as_S_transport) ... ok +test_digest_and_scenario_contradiction (__main__.S2Format.test_digest_and_scenario_contradiction) ... ok +test_event_no_drop_duplicate_remap (__main__.S2Format.test_event_no_drop_duplicate_remap) ... ok +test_event_original_field_types_mandatory (__main__.S2Format.test_event_original_field_types_mandatory) ... ok +test_guard_actual_not_assumed (__main__.S2Format.test_guard_actual_not_assumed) ... ok +test_harness_digest_allows_only_dictionary_order (__main__.S2Format.test_harness_digest_allows_only_dictionary_order) ... ok +test_join_is_copy_and_retains_normalization_proof (__main__.S2Format.test_join_is_copy_and_retains_normalization_proof) ... ok +test_kernel_cache_contradictions (__main__.S2Format.test_kernel_cache_contradictions) ... ok +test_lifecycle_guard_errors_and_boundaries (__main__.S2Format.test_lifecycle_guard_errors_and_boundaries) ... ok +test_missing_full_state_not_digest_only (__main__.S2Format.test_missing_full_state_not_digest_only) ... ok +test_normalized_digest_and_raw_tree_are_both_bound (__main__.S2Format.test_normalized_digest_and_raw_tree_are_both_bound) ... ok +test_product_event_shape_and_typed_array (__main__.S2Format.test_product_event_shape_and_typed_array) ... ok +test_raw_observation_binding (__main__.S2Format.test_raw_observation_binding) ... ok +test_roundtrip_tree_sha_and_raw_sha (__main__.S2Format.test_roundtrip_tree_sha_and_raw_sha) ... ok +test_s2_valid_and_not_formal_acceptance (__main__.S2Format.test_s2_valid_and_not_formal_acceptance) ... ok +test_state_witness_and_observation_mutation (__main__.S2Format.test_state_witness_and_observation_mutation) ... ok +test_stdout_exactly_one_line (__main__.S2Format.test_stdout_exactly_one_line) ... ok +test_autoload_class_and_script_import (__main__.S2Static.test_autoload_class_and_script_import) ... ok +test_comment_does_not_supply_proof (__main__.S2Static.test_comment_does_not_supply_proof) ... ok +test_current_probe (__main__.S2Static.test_current_probe) ... ok +test_full_state_and_godot_roundtrip_required (__main__.S2Static.test_full_state_and_godot_roundtrip_required) ... + test_full_state_and_godot_roundtrip_required (__main__.S2Static.test_full_state_and_godot_roundtrip_required) (required='transport(runtime.create_snapshot())') ... FAIL +test_no_changes_outside_preparation_or_step (__main__.S2Static.test_no_changes_outside_preparation_or_step) ... ok +test_no_event_cap_or_duplicate_report (__main__.S2Static.test_no_event_cap_or_duplicate_report) ... ok +test_pause_and_step_arguments (__main__.S2Static.test_pause_and_step_arguments) ... ok +test_textual_stringname_ordering (__main__.S2Static.test_textual_stringname_ordering) ... ok +test_unlisted_live_method_and_late_preparation (__main__.S2Static.test_unlisted_live_method_and_late_preparation) ... ok +test_variant_inference (__main__.S2Static.test_variant_inference) ... ok +test_X_recent_limit_and_counter (__main__.S3a.test_X_recent_limit_and_counter) ... ok +test_duplicate_JSON_key_rejected (__main__.S3a.test_duplicate_JSON_key_rejected) ... ok +test_e3_NA_cannot_be_PASS_or_applied (__main__.S3a.test_e3_NA_cannot_be_PASS_or_applied) ... ok +test_e3_coverage_input_and_event_count_binding (__main__.S3a.test_e3_coverage_input_and_event_count_binding) ... ok +test_e3_invented_codes_and_missing_load_code (__main__.S3a.test_e3_invented_codes_and_missing_load_code) ... ok +test_e3_valid_R_and_O_records (__main__.S3a.test_e3_valid_R_and_O_records) ... FAIL +test_envelope_duplicates_not_defect (__main__.S3a.test_envelope_duplicates_not_defect) ... FAIL +test_event_count_defect_not_silently_accepted (__main__.S3a.test_event_count_defect_not_silently_accepted) ... FAIL +test_exact_phase_keys (__main__.S3a.test_exact_phase_keys) ... ok +test_interval_gap_rejected (__main__.S3a.test_interval_gap_rejected) ... ok +test_invalid_input_accepted_is_not_PASS (__main__.S3a.test_invalid_input_accepted_is_not_PASS) ... FAIL +test_load_payload_and_pause_outcome (__main__.S3a.test_load_payload_and_pause_outcome) ... FAIL +test_operation_moved_outside_scenario_rejected (__main__.S3a.test_operation_moved_outside_scenario_rejected) ... ok +test_package_fixed_mutations_and_hashes (__main__.S3a.test_package_fixed_mutations_and_hashes) ... ok +test_probe_connection_required (__main__.S3a.test_probe_connection_required) ... ok +test_rejection_mutation_retained_as_defect (__main__.S3a.test_rejection_mutation_retained_as_defect) ... FAIL +test_save_refusal_makes_load_NA (__main__.S3a.test_save_refusal_makes_load_NA) ... FAIL +test_scenario_mutation_static_boundary (__main__.S3a.test_scenario_mutation_static_boundary) ... ok +test_signals_all_minutes_and_order (__main__.S3a.test_signals_all_minutes_and_order) ... ok +test_E5_cached_digest_defect_is_comparable (__main__.S3b.test_E5_cached_digest_defect_is_comparable) ... ok +test_NA_not_PASS (__main__.S3b.test_NA_not_PASS) ... ok +test_aliasing_cannot_be_PASS (__main__.S3b.test_aliasing_cannot_be_PASS) ... ok +test_aliasing_missing_record (__main__.S3b.test_aliasing_missing_record) ... ok +test_all_paths_and_ownership_R_O (__main__.S3b.test_all_paths_and_ownership_R_O) ... ERROR +test_digest_defect_other_checkpoint_still_rejected (__main__.S3b.test_digest_defect_other_checkpoint_still_rejected) ... ok +test_digest_materialization_required (__main__.S3b.test_digest_materialization_required) ... ok +test_empty_registry_not_NA (__main__.S3b.test_empty_registry_not_NA) ... ok +test_event_count_mismatch (__main__.S3b.test_event_count_mismatch) ... ok +test_facts_normalization_is_reversible (__main__.S3b.test_facts_normalization_is_reversible) ... ok +test_first_placeable_choice (__main__.S3b.test_first_placeable_choice) ... ok +test_interval_gap (__main__.S3b.test_interval_gap) ... ok +test_joined_s3b_self_comparison (__main__.S3b.test_joined_s3b_self_comparison) ... ok +test_load_X_not_digest_only (__main__.S3b.test_load_X_not_digest_only) ... ok +test_load_extra_event (__main__.S3b.test_load_extra_event) ... ok +test_missing_path_and_combination (__main__.S3b.test_missing_path_and_combination) ... ok +test_missing_preview_observation (__main__.S3b.test_missing_preview_observation) ... ok +test_missing_trial (__main__.S3b.test_missing_trial) ... ok +test_nested_mutation_required (__main__.S3b.test_nested_mutation_required) ... ok +test_no_staleness_assertion_for_non_tick (__main__.S3b.test_no_staleness_assertion_for_non_tick) ... ERROR +test_ownership_fact_dictionary_order_fallback (__main__.S3b.test_ownership_fact_dictionary_order_fallback) ... ok +test_path_order (__main__.S3b.test_path_order) ... ok +test_restore_extra_event (__main__.S3b.test_restore_extra_event) ... ok +test_signal_facts_cannot_be_dropped (__main__.S3b.test_signal_facts_cannot_be_dropped) ... ok +test_sort_rule_rejected (__main__.S3b.test_sort_rule_rejected) ... ok +test_static_handler_and_outside_mutations (__main__.S3b.test_static_handler_and_outside_mutations) ... ok +test_unpreviewed_choice (__main__.S3b.test_unpreviewed_choice) ... ok +test_wrong_registry_in_either_role (__main__.S3b.test_wrong_registry_in_either_role) ... ok +test_checkout_temp_destination_rejected (__main__.S4Bundle.test_checkout_temp_destination_rejected) ... ok +test_existing_output_never_overwritten (__main__.S4Bundle.test_existing_output_never_overwritten) ... ok +test_import_closure_rejections (__main__.S4Bundle.test_import_closure_rejections) ... ok +test_missing_bundle_manifest_seal_and_changed_bytes (__main__.S4Bundle.test_missing_bundle_manifest_seal_and_changed_bytes) ... ok +test_missing_private_evidence_and_extra_rejected (__main__.S4Bundle.test_missing_private_evidence_and_extra_rejected) ... ok +test_missing_profile_not_export_success (__main__.S4Bundle.test_missing_profile_not_export_success) ... ok +test_phase_role_pid_audio_and_guard_rejected (__main__.S4Bundle.test_phase_role_pid_audio_and_guard_rejected) ... ok +test_rebound_lifecycle_and_scenario_contradictions (__main__.S4Bundle.test_rebound_lifecycle_and_scenario_contradictions) ... ok +test_seal_normal_and_changes_not_native_proof (__main__.S4Bundle.test_seal_normal_and_changes_not_native_proof) ... ok +test_synthetic_phase_all_real_checkers_not_native_proof (__main__.S4Bundle.test_synthetic_phase_all_real_checkers_not_native_proof) ... ERROR +test_copied_manifest_root_and_destination_count_rejected (__main__.S4NativeBundleLogic.test_copied_manifest_root_and_destination_count_rejected) ... ok +test_failure_keeps_raw_and_no_bundle_without_starting_engine (__main__.S4NativeBundleLogic.test_failure_keeps_raw_and_no_bundle_without_starting_engine) ... ok +test_gate_none_success_not_boolean (__main__.S4NativeBundleLogic.test_gate_none_success_not_boolean) ... ok +test_receipt_and_source_rejection_matrix (__main__.S4NativeBundleLogic.test_receipt_and_source_rejection_matrix) ... ok +test_synthetic_full_bundle_positive_not_native_evidence (__main__.S4NativeBundleLogic.test_synthetic_full_bundle_positive_not_native_evidence) ... ERROR +test_check_accepts_true (__main__.S4ProbeAdmission.test_check_accepts_true) ... ok +test_check_rejects_false_all_errors (__main__.S4ProbeAdmission.test_check_rejects_false_all_errors) ... ok +test_run_admission_accepts_true_mock_launch_only (__main__.S4ProbeAdmission.test_run_admission_accepts_true_mock_launch_only) ... ok +test_run_admission_rejects_false_without_engine (__main__.S4ProbeAdmission.test_run_admission_rejects_false_without_engine) ... ok +test_nine_original_destinations_required (__main__.S4RemainingBindings.test_nine_original_destinations_required) ... ok +test_nonzero_determinism_rejected_after_real_join (__main__.S4RemainingBindings.test_nonzero_determinism_rejected_after_real_join) ... FAIL +test_owned_lifecycle_exit_diagnostic_and_profile_rejections (__main__.S4RemainingBindings.test_owned_lifecycle_exit_diagnostic_and_profile_rejections) ... ok +test_verifier_accepts_true_recomputes_raw (__main__.S4RemainingBindings.test_verifier_accepts_true_recomputes_raw) ... ERROR +test_verifier_rejects_false_with_every_error (__main__.S4RemainingBindings.test_verifier_rejects_false_with_every_error) ... ok +test_cached_verdict_not_trusted (__main__.S4StoredResultBindings.test_cached_verdict_not_trusted) ... ok +test_missing_sidecar_rejected_after_seal (__main__.S4StoredResultBindings.test_missing_sidecar_rejected_after_seal) ... ok +test_raw_joined_substitution_rejected_after_seal (__main__.S4StoredResultBindings.test_raw_joined_substitution_rejected_after_seal) ... ok +test_fixed_scenario_paths (__main__.SourcesAndMetrics.test_fixed_scenario_paths) ... ok +test_metric_ranges (__main__.SourcesAndMetrics.test_metric_ranges) ... ok +test_source_closure_synthetic_registered_map (__main__.SourcesAndMetrics.test_source_closure_synthetic_registered_map) ... ok +test_source_pin_is_not_caller_controlled (__main__.SourcesAndMetrics.test_source_pin_is_not_caller_controlled) ... ok +test_array_order_and_all_differences (__main__.TypedTrees.test_array_order_and_all_differences) ... ok +test_components_and_sha (__main__.TypedTrees.test_components_and_sha) ... ok +test_deep_state_not_truncated (__main__.TypedTrees.test_deep_state_not_truncated) ... ok +test_duplicate_textual_keys_rejected (__main__.TypedTrees.test_duplicate_textual_keys_rejected) ... ok +test_exact_and_types (__main__.TypedTrees.test_exact_and_types) ... ok +test_nested_order_all_paths (__main__.TypedTrees.test_nested_order_all_paths) ... ok +test_nonstring_keys_keep_types_and_values (__main__.TypedTrees.test_nonstring_keys_keep_types_and_values) ... ok +test_unsupported_and_malformed (__main__.TypedTrees.test_unsupported_and_malformed) ... ok + +====================================================================== +ERROR: test_all_paths_and_ownership_R_O (__main__.S3b.test_all_paths_and_ownership_R_O) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1077, in test_all_paths_and_ownership_R_O + outcomes = self.checked(e45_fixture(role)) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1067, in checked + return checker.check_e45(raw, evidence, previous) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/check_eq.py", line 826, in check_e45 + eq.require(set(detail) == common | specific, 'E4 detail fields; no invented staleness verdict') + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py", line 143, in require + raise EvidenceError(message) +compare_versions.EvidenceError: E4 detail fields; no invented staleness verdict + +====================================================================== +ERROR: test_no_staleness_assertion_for_non_tick (__main__.S3b.test_no_staleness_assertion_for_non_tick) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1170, in test_no_staleness_assertion_for_non_tick + out = self.checked() + ^^^^^^^^^^^^^^ + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1067, in checked + return checker.check_e45(raw, evidence, previous) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/check_eq.py", line 826, in check_e45 + eq.require(set(detail) == common | specific, 'E4 detail fields; no invented staleness verdict') + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py", line 143, in require + raise EvidenceError(message) +compare_versions.EvidenceError: E4 detail fields; no invented staleness verdict + +====================================================================== +ERROR: test_synthetic_phase_all_real_checkers_not_native_proof (__main__.S4Bundle.test_synthetic_phase_all_real_checkers_not_native_proof) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1417, in test_synthetic_phase_all_real_checkers_not_native_proof + result = verifier.phase_evidence(directory, row) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/verify_eq.py", line 110, in phase_evidence + require(life['stage'] == 'S5', 'S5 lifecycle required') + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py", line 143, in require + raise EvidenceError(message) +compare_versions.EvidenceError: S5 lifecycle required + +====================================================================== +ERROR: test_synthetic_full_bundle_positive_not_native_evidence (__main__.S4NativeBundleLogic.test_synthetic_full_bundle_positive_not_native_evidence) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1514, in test_synthetic_full_bundle_positive_not_native_evidence + result = self.recompute(self.execution) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1511, in recompute + return verifier.recompute(self.directory, value, self.collector, self.standard, self.diag) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/verify_eq.py", line 222, in recompute + results[phase] = phase_evidence(directory, row) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/verify_eq.py", line 110, in phase_evidence + require(life['stage'] == 'S5', 'S5 lifecycle required') + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py", line 143, in require + raise EvidenceError(message) +compare_versions.EvidenceError: S5 lifecycle required + +====================================================================== +ERROR: test_verifier_accepts_true_recomputes_raw (__main__.S4RemainingBindings.test_verifier_accepts_true_recomputes_raw) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1618, in test_verifier_accepts_true_recomputes_raw + result = self.recompute(self.execution) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1511, in recompute + return verifier.recompute(self.directory, value, self.collector, self.standard, self.diag) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/verify_eq.py", line 222, in recompute + results[phase] = phase_evidence(directory, row) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/verify_eq.py", line 110, in phase_evidence + require(life['stage'] == 'S5', 'S5 lifecycle required') + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py", line 143, in require + raise EvidenceError(message) +compare_versions.EvidenceError: S5 lifecycle required + +====================================================================== +FAIL: test_full_state_and_godot_roundtrip_required (__main__.S2Static.test_full_state_and_godot_roundtrip_required) (required='transport(runtime.create_snapshot())') +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 676, in test_full_state_and_godot_roundtrip_required + with self.subTest(required=required): self.reject(self.probe.replace(required, 'null')) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 645, in reject + self.assertFalse(result['ok'], result) +AssertionError: True is not false : {'ok': True, 'stage': 'S3a', 'errors': []} + +====================================================================== +FAIL: test_e3_valid_R_and_O_records (__main__.S3a.test_e3_valid_R_and_O_records) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 835, in test_e3_valid_R_and_O_records + self.assertTrue(checked['ok'], checked['errors']) +AssertionError: False is not true : ["'event_stream'"] + +====================================================================== +FAIL: test_envelope_duplicates_not_defect (__main__.S3a.test_envelope_duplicates_not_defect) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 863, in test_envelope_duplicates_not_defect + self.assertTrue(checked['ok'], checked['errors']) +AssertionError: False is not true : ["'event_stream'"] + +====================================================================== +FAIL: test_event_count_defect_not_silently_accepted (__main__.S3a.test_event_count_defect_not_silently_accepted) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 944, in test_event_count_defect_not_silently_accepted + self.assertTrue(checked['ok'], checked['errors']) +AssertionError: False is not true : ["'event_stream'"] + +====================================================================== +FAIL: test_invalid_input_accepted_is_not_PASS (__main__.S3a.test_invalid_input_accepted_is_not_PASS) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 898, in test_invalid_input_accepted_is_not_PASS + self.assertTrue(checked['ok'], checked['errors']) +AssertionError: False is not true : ["'event_stream'"] + +====================================================================== +FAIL: test_load_payload_and_pause_outcome (__main__.S3a.test_load_payload_and_pause_outcome) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 972, in test_load_payload_and_pause_outcome + self.assertTrue(checked['ok'], checked['errors']) +AssertionError: False is not true : ["'event_stream'"] + +====================================================================== +FAIL: test_rejection_mutation_retained_as_defect (__main__.S3a.test_rejection_mutation_retained_as_defect) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 889, in test_rejection_mutation_retained_as_defect + self.assertTrue(checked['ok'], checked['errors']) +AssertionError: False is not true : ["'event_stream'"] + +====================================================================== +FAIL: test_save_refusal_makes_load_NA (__main__.S3a.test_save_refusal_makes_load_NA) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 963, in test_save_refusal_makes_load_NA + self.assertTrue(checked['ok'], checked['errors']) +AssertionError: False is not true : ["'event_stream'"] + +====================================================================== +FAIL: test_nonzero_determinism_rejected_after_real_join (__main__.S4RemainingBindings.test_nonzero_determinism_rejected_after_real_join) +---------------------------------------------------------------------- +compare_versions.EvidenceError: S5 lifecycle required + +During handling of the above exception, another exception occurred: + +Traceback (most recent call last): + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1648, in test_nonzero_determinism_rejected_after_real_join + with self.assertRaisesRegex(eq.EvidenceError, 'same-role determinism failed'): + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +AssertionError: "same-role determinism failed" does not match "S5 lifecycle required" + +---------------------------------------------------------------------- +Ran 146 tests in 53.398s + +FAILED (failures=9, errors=5) +exit=1 diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_02.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_02.sha256 new file mode 100644 index 0000000..a790d05 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_02.sha256 @@ -0,0 +1 @@ +67b91e02e30046cefecf260aa2eb284e0bab5ae2d9728f674eea5bd06e38db0c UNIT_OUTPUT_S5_ATTEMPT_02.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_02.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_02.txt new file mode 100644 index 0000000..1b8a7f1 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_02.txt @@ -0,0 +1,163 @@ +test_all_operations (__main__.Diffs.test_all_operations) ... ok +test_invalid_operations (__main__.Diffs.test_invalid_operations) ... ok +test_reconstruction_and_proofs (__main__.Diffs.test_reconstruction_and_proofs) ... ok +test_attempt_to_normalize_violation_rejected (__main__.Normalization.test_attempt_to_normalize_violation_rejected) ... ok +test_environment_values_differ_but_normal_form_equal (__main__.Normalization.test_environment_values_differ_but_normal_form_equal) ... ok +test_every_save_event_reversible (__main__.Normalization.test_every_save_event_reversible) ... ok +test_f3_keeps_relative_paths_and_words (__main__.Normalization.test_f3_keeps_relative_paths_and_words) ... ok +test_guard_mismatch (__main__.Normalization.test_guard_mismatch) ... ok +test_nested_lookalike_is_not_eligible (__main__.Normalization.test_nested_lookalike_is_not_eligible) ... ok +test_original_transport_sha_detects_forged_timing (__main__.Normalization.test_original_transport_sha_detects_forged_timing) ... ok +test_partial_timing_payload_rejected (__main__.Normalization.test_partial_timing_payload_rejected) ... ok +test_prefix_boundary_and_reserved_token (__main__.Normalization.test_prefix_boundary_and_reserved_token) ... ok +test_sidecar_missing_duplicate_and_forged_paths (__main__.Normalization.test_sidecar_missing_duplicate_and_forged_paths) ... ok +test_snapshot_and_latest_reversible (__main__.Normalization.test_snapshot_and_latest_reversible) ... ok +test_snapshot_event_outside_recent_is_not_eligible (__main__.Normalization.test_snapshot_event_outside_recent_is_not_eligible) ... ok +test_wrong_event_and_source_are_preserved (__main__.Normalization.test_wrong_event_and_source_are_preserved) ... ok +test_wrong_timing_type_and_negative (__main__.Normalization.test_wrong_timing_type_and_negative) ... ok +test_all_events_beyond_recent_window (__main__.Reports.test_all_events_beyond_recent_window) ... ok +test_all_semantic_layers_compared (__main__.Reports.test_all_semantic_layers_compared) ... ok +test_digest_alone_is_not_enough (__main__.Reports.test_digest_alone_is_not_enough) ... ok +test_event_original_types_and_order (__main__.Reports.test_event_original_types_and_order) ... ok +test_event_start_and_ids (__main__.Reports.test_event_start_and_ids) ... ok +test_exclusions_keep_actual_values (__main__.Reports.test_exclusions_keep_actual_values) ... ok +test_handler_sets_and_counts (__main__.Reports.test_handler_sets_and_counts) ... ok +test_observation_full_layers (__main__.Reports.test_observation_full_layers) ... ok +test_product_digest_self_consistency (__main__.Reports.test_product_digest_self_consistency) ... ok +test_same_report (__main__.Reports.test_same_report) ... ok +test_scenario_existing_failures_preserved (__main__.Reports.test_scenario_existing_failures_preserved) ... ok +test_timing_digest_rule (__main__.Reports.test_timing_digest_rule) ... ok +test_unknown_or_missing_fields_rejected (__main__.Reports.test_unknown_or_missing_fields_rejected) ... ok +test_violation_presence_and_difference (__main__.Reports.test_violation_presence_and_difference) ... ok +test_O_cadence (__main__.S2Format.test_O_cadence) ... ok +test_counter_and_published_ids_binding (__main__.S2Format.test_counter_and_published_ids_binding) ... ok +test_diff_and_same_as_S_transport (__main__.S2Format.test_diff_and_same_as_S_transport) ... ok +test_digest_and_scenario_contradiction (__main__.S2Format.test_digest_and_scenario_contradiction) ... ok +test_event_no_drop_duplicate_remap (__main__.S2Format.test_event_no_drop_duplicate_remap) ... ok +test_event_original_field_types_mandatory (__main__.S2Format.test_event_original_field_types_mandatory) ... ok +test_guard_actual_not_assumed (__main__.S2Format.test_guard_actual_not_assumed) ... ok +test_harness_digest_allows_only_dictionary_order (__main__.S2Format.test_harness_digest_allows_only_dictionary_order) ... ok +test_join_is_copy_and_retains_normalization_proof (__main__.S2Format.test_join_is_copy_and_retains_normalization_proof) ... ok +test_kernel_cache_contradictions (__main__.S2Format.test_kernel_cache_contradictions) ... ok +test_lifecycle_guard_errors_and_boundaries (__main__.S2Format.test_lifecycle_guard_errors_and_boundaries) ... ok +test_missing_full_state_not_digest_only (__main__.S2Format.test_missing_full_state_not_digest_only) ... ok +test_normalized_digest_and_raw_tree_are_both_bound (__main__.S2Format.test_normalized_digest_and_raw_tree_are_both_bound) ... ok +test_product_event_shape_and_typed_array (__main__.S2Format.test_product_event_shape_and_typed_array) ... ok +test_raw_observation_binding (__main__.S2Format.test_raw_observation_binding) ... ok +test_roundtrip_tree_sha_and_raw_sha (__main__.S2Format.test_roundtrip_tree_sha_and_raw_sha) ... ok +test_s2_valid_and_not_formal_acceptance (__main__.S2Format.test_s2_valid_and_not_formal_acceptance) ... ok +test_state_witness_and_observation_mutation (__main__.S2Format.test_state_witness_and_observation_mutation) ... ok +test_stdout_exactly_one_line (__main__.S2Format.test_stdout_exactly_one_line) ... ok +test_autoload_class_and_script_import (__main__.S2Static.test_autoload_class_and_script_import) ... ok +test_comment_does_not_supply_proof (__main__.S2Static.test_comment_does_not_supply_proof) ... ok +test_current_probe (__main__.S2Static.test_current_probe) ... ok +test_full_state_and_godot_roundtrip_required (__main__.S2Static.test_full_state_and_godot_roundtrip_required) ... ok +test_no_changes_outside_preparation_or_step (__main__.S2Static.test_no_changes_outside_preparation_or_step) ... ok +test_no_event_cap_or_duplicate_report (__main__.S2Static.test_no_event_cap_or_duplicate_report) ... ok +test_pause_and_step_arguments (__main__.S2Static.test_pause_and_step_arguments) ... ok +test_textual_stringname_ordering (__main__.S2Static.test_textual_stringname_ordering) ... ok +test_unlisted_live_method_and_late_preparation (__main__.S2Static.test_unlisted_live_method_and_late_preparation) ... ok +test_variant_inference (__main__.S2Static.test_variant_inference) ... ok +test_X_recent_limit_and_counter (__main__.S3a.test_X_recent_limit_and_counter) ... ok +test_duplicate_JSON_key_rejected (__main__.S3a.test_duplicate_JSON_key_rejected) ... ok +test_e3_NA_cannot_be_PASS_or_applied (__main__.S3a.test_e3_NA_cannot_be_PASS_or_applied) ... ok +test_e3_coverage_input_and_event_count_binding (__main__.S3a.test_e3_coverage_input_and_event_count_binding) ... ok +test_e3_invented_codes_and_missing_load_code (__main__.S3a.test_e3_invented_codes_and_missing_load_code) ... ok +test_e3_valid_R_and_O_records (__main__.S3a.test_e3_valid_R_and_O_records) ... ok +test_envelope_duplicates_not_defect (__main__.S3a.test_envelope_duplicates_not_defect) ... ok +test_event_count_defect_not_silently_accepted (__main__.S3a.test_event_count_defect_not_silently_accepted) ... ok +test_exact_phase_keys (__main__.S3a.test_exact_phase_keys) ... ok +test_interval_gap_rejected (__main__.S3a.test_interval_gap_rejected) ... ok +test_invalid_input_accepted_is_not_PASS (__main__.S3a.test_invalid_input_accepted_is_not_PASS) ... ok +test_load_payload_and_pause_outcome (__main__.S3a.test_load_payload_and_pause_outcome) ... ok +test_operation_moved_outside_scenario_rejected (__main__.S3a.test_operation_moved_outside_scenario_rejected) ... ok +test_package_fixed_mutations_and_hashes (__main__.S3a.test_package_fixed_mutations_and_hashes) ... ok +test_probe_connection_required (__main__.S3a.test_probe_connection_required) ... ok +test_rejection_mutation_retained_as_defect (__main__.S3a.test_rejection_mutation_retained_as_defect) ... ok +test_save_refusal_makes_load_NA (__main__.S3a.test_save_refusal_makes_load_NA) ... ok +test_scenario_mutation_static_boundary (__main__.S3a.test_scenario_mutation_static_boundary) ... ok +test_signals_all_minutes_and_order (__main__.S3a.test_signals_all_minutes_and_order) ... ok +test_E5_cached_digest_defect_is_comparable (__main__.S3b.test_E5_cached_digest_defect_is_comparable) ... ok +test_NA_not_PASS (__main__.S3b.test_NA_not_PASS) ... ok +test_aliasing_cannot_be_PASS (__main__.S3b.test_aliasing_cannot_be_PASS) ... ok +test_aliasing_missing_record (__main__.S3b.test_aliasing_missing_record) ... ok +test_all_paths_and_ownership_R_O (__main__.S3b.test_all_paths_and_ownership_R_O) ... ok +test_digest_defect_other_checkpoint_still_rejected (__main__.S3b.test_digest_defect_other_checkpoint_still_rejected) ... ok +test_digest_materialization_required (__main__.S3b.test_digest_materialization_required) ... ok +test_empty_registry_not_NA (__main__.S3b.test_empty_registry_not_NA) ... ok +test_event_count_mismatch (__main__.S3b.test_event_count_mismatch) ... ok +test_facts_normalization_is_reversible (__main__.S3b.test_facts_normalization_is_reversible) ... ok +test_first_placeable_choice (__main__.S3b.test_first_placeable_choice) ... ok +test_interval_gap (__main__.S3b.test_interval_gap) ... ok +test_joined_s3b_self_comparison (__main__.S3b.test_joined_s3b_self_comparison) ... ok +test_load_X_not_digest_only (__main__.S3b.test_load_X_not_digest_only) ... ok +test_load_extra_event (__main__.S3b.test_load_extra_event) ... ok +test_missing_path_and_combination (__main__.S3b.test_missing_path_and_combination) ... ok +test_missing_preview_observation (__main__.S3b.test_missing_preview_observation) ... ok +test_missing_trial (__main__.S3b.test_missing_trial) ... ok +test_nested_mutation_required (__main__.S3b.test_nested_mutation_required) ... ok +test_no_staleness_assertion_for_non_tick (__main__.S3b.test_no_staleness_assertion_for_non_tick) ... ok +test_ownership_fact_dictionary_order_fallback (__main__.S3b.test_ownership_fact_dictionary_order_fallback) ... ok +test_path_order (__main__.S3b.test_path_order) ... ok +test_restore_extra_event (__main__.S3b.test_restore_extra_event) ... ok +test_signal_facts_cannot_be_dropped (__main__.S3b.test_signal_facts_cannot_be_dropped) ... ok +test_sort_rule_rejected (__main__.S3b.test_sort_rule_rejected) ... ok +test_static_handler_and_outside_mutations (__main__.S3b.test_static_handler_and_outside_mutations) ... ok +test_unpreviewed_choice (__main__.S3b.test_unpreviewed_choice) ... ok +test_wrong_registry_in_either_role (__main__.S3b.test_wrong_registry_in_either_role) ... ok +test_checkout_temp_destination_rejected (__main__.S4Bundle.test_checkout_temp_destination_rejected) ... ok +test_existing_output_never_overwritten (__main__.S4Bundle.test_existing_output_never_overwritten) ... ok +test_import_closure_rejections (__main__.S4Bundle.test_import_closure_rejections) ... ok +test_missing_bundle_manifest_seal_and_changed_bytes (__main__.S4Bundle.test_missing_bundle_manifest_seal_and_changed_bytes) ... ok +test_missing_private_evidence_and_extra_rejected (__main__.S4Bundle.test_missing_private_evidence_and_extra_rejected) ... ok +test_missing_profile_not_export_success (__main__.S4Bundle.test_missing_profile_not_export_success) ... ok +test_phase_role_pid_audio_and_guard_rejected (__main__.S4Bundle.test_phase_role_pid_audio_and_guard_rejected) ... ok +test_rebound_lifecycle_and_scenario_contradictions (__main__.S4Bundle.test_rebound_lifecycle_and_scenario_contradictions) ... ok +test_seal_normal_and_changes_not_native_proof (__main__.S4Bundle.test_seal_normal_and_changes_not_native_proof) ... ok +test_synthetic_phase_all_real_checkers_not_native_proof (__main__.S4Bundle.test_synthetic_phase_all_real_checkers_not_native_proof) ... ok +test_copied_manifest_root_and_destination_count_rejected (__main__.S4NativeBundleLogic.test_copied_manifest_root_and_destination_count_rejected) ... ok +test_failure_keeps_raw_and_no_bundle_without_starting_engine (__main__.S4NativeBundleLogic.test_failure_keeps_raw_and_no_bundle_without_starting_engine) ... ok +test_gate_none_success_not_boolean (__main__.S4NativeBundleLogic.test_gate_none_success_not_boolean) ... ok +test_receipt_and_source_rejection_matrix (__main__.S4NativeBundleLogic.test_receipt_and_source_rejection_matrix) ... ok +test_synthetic_full_bundle_positive_not_native_evidence (__main__.S4NativeBundleLogic.test_synthetic_full_bundle_positive_not_native_evidence) ... ok +test_check_accepts_true (__main__.S4ProbeAdmission.test_check_accepts_true) ... ok +test_check_rejects_false_all_errors (__main__.S4ProbeAdmission.test_check_rejects_false_all_errors) ... ok +test_run_admission_accepts_true_mock_launch_only (__main__.S4ProbeAdmission.test_run_admission_accepts_true_mock_launch_only) ... ok +test_run_admission_rejects_false_without_engine (__main__.S4ProbeAdmission.test_run_admission_rejects_false_without_engine) ... ok +test_nine_original_destinations_required (__main__.S4RemainingBindings.test_nine_original_destinations_required) ... ok +test_nonzero_determinism_rejected_after_real_join (__main__.S4RemainingBindings.test_nonzero_determinism_rejected_after_real_join) ... ok +test_owned_lifecycle_exit_diagnostic_and_profile_rejections (__main__.S4RemainingBindings.test_owned_lifecycle_exit_diagnostic_and_profile_rejections) ... ok +test_verifier_accepts_true_recomputes_raw (__main__.S4RemainingBindings.test_verifier_accepts_true_recomputes_raw) ... ok +test_verifier_rejects_false_with_every_error (__main__.S4RemainingBindings.test_verifier_rejects_false_with_every_error) ... ok +test_cached_verdict_not_trusted (__main__.S4StoredResultBindings.test_cached_verdict_not_trusted) ... ok +test_missing_sidecar_rejected_after_seal (__main__.S4StoredResultBindings.test_missing_sidecar_rejected_after_seal) ... ok +test_raw_joined_substitution_rejected_after_seal (__main__.S4StoredResultBindings.test_raw_joined_substitution_rejected_after_seal) ... ok +test_blob_transport_is_verified_and_bound (__main__.S5.test_blob_transport_is_verified_and_bound) ... ok +test_compare_and_digest_equal_s1_reference (__main__.S5.test_compare_and_digest_equal_s1_reference) ... ok +test_event_stream_replacement_is_existing_defect_not_pass (__main__.S5.test_event_stream_replacement_is_existing_defect_not_pass) ... ok +test_every_checkpoint_full_tree_verified_like_inline (__main__.S5.test_every_checkpoint_full_tree_verified_like_inline) +S5 drops the diff chain: each checkpoint carries a complete tree, verified alone. ... ok +test_fast_normalization_equals_original (__main__.S5.test_fast_normalization_equals_original) ... ok +test_lifecycle_binds_replacements_guard_text_and_blobs (__main__.S5.test_lifecycle_binds_replacements_guard_text_and_blobs) ... ok +test_manifest_numbers_keep_their_type (__main__.S5.test_manifest_numbers_keep_their_type) ... ok +test_path_copy_builders_equal_deepcopy_reference (__main__.S5.test_path_copy_builders_equal_deepcopy_reference) ... ok +test_probe_static_full_tree_blob_and_stream_requirements (__main__.S5.test_probe_static_full_tree_blob_and_stream_requirements) ... ok +test_signed_instance_ids_raw_kept_and_excluded (__main__.S5.test_signed_instance_ids_raw_kept_and_excluded) ... ok +test_fixed_scenario_paths (__main__.SourcesAndMetrics.test_fixed_scenario_paths) ... ok +test_metric_ranges (__main__.SourcesAndMetrics.test_metric_ranges) ... ok +test_source_closure_synthetic_registered_map (__main__.SourcesAndMetrics.test_source_closure_synthetic_registered_map) ... ok +test_source_pin_is_not_caller_controlled (__main__.SourcesAndMetrics.test_source_pin_is_not_caller_controlled) ... ok +test_array_order_and_all_differences (__main__.TypedTrees.test_array_order_and_all_differences) ... ok +test_components_and_sha (__main__.TypedTrees.test_components_and_sha) ... ok +test_deep_state_not_truncated (__main__.TypedTrees.test_deep_state_not_truncated) ... ok +test_duplicate_textual_keys_rejected (__main__.TypedTrees.test_duplicate_textual_keys_rejected) ... ok +test_exact_and_types (__main__.TypedTrees.test_exact_and_types) ... ok +test_nested_order_all_paths (__main__.TypedTrees.test_nested_order_all_paths) ... ok +test_nonstring_keys_keep_types_and_values (__main__.TypedTrees.test_nonstring_keys_keep_types_and_values) ... ok +test_unsupported_and_malformed (__main__.TypedTrees.test_unsupported_and_malformed) ... ok + +---------------------------------------------------------------------- +Ran 156 tests in 211.416s + +OK +exit=0 diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_03.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_03.sha256 new file mode 100644 index 0000000..73d97a1 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_03.sha256 @@ -0,0 +1 @@ +e2833369d98a4cf6600fcd98dcf271c2172e8b4a5fbb366eae4fcebc5ea8921d UNIT_OUTPUT_S5_ATTEMPT_03.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_03.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_03.txt new file mode 100644 index 0000000..22935dd --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_03.txt @@ -0,0 +1,167 @@ +test_all_operations (__main__.Diffs.test_all_operations) ... ok +test_invalid_operations (__main__.Diffs.test_invalid_operations) ... ok +test_reconstruction_and_proofs (__main__.Diffs.test_reconstruction_and_proofs) ... ok +test_attempt_to_normalize_violation_rejected (__main__.Normalization.test_attempt_to_normalize_violation_rejected) ... ok +test_environment_values_differ_but_normal_form_equal (__main__.Normalization.test_environment_values_differ_but_normal_form_equal) ... ok +test_every_save_event_reversible (__main__.Normalization.test_every_save_event_reversible) ... ok +test_f3_keeps_relative_paths_and_words (__main__.Normalization.test_f3_keeps_relative_paths_and_words) ... ok +test_guard_mismatch (__main__.Normalization.test_guard_mismatch) ... ok +test_nested_lookalike_is_not_eligible (__main__.Normalization.test_nested_lookalike_is_not_eligible) ... ok +test_original_transport_sha_detects_forged_timing (__main__.Normalization.test_original_transport_sha_detects_forged_timing) ... ok +test_partial_timing_payload_rejected (__main__.Normalization.test_partial_timing_payload_rejected) ... ok +test_prefix_boundary_and_reserved_token (__main__.Normalization.test_prefix_boundary_and_reserved_token) ... ok +test_sidecar_missing_duplicate_and_forged_paths (__main__.Normalization.test_sidecar_missing_duplicate_and_forged_paths) ... ok +test_snapshot_and_latest_reversible (__main__.Normalization.test_snapshot_and_latest_reversible) ... ok +test_snapshot_event_outside_recent_is_not_eligible (__main__.Normalization.test_snapshot_event_outside_recent_is_not_eligible) ... ok +test_wrong_event_and_source_are_preserved (__main__.Normalization.test_wrong_event_and_source_are_preserved) ... ok +test_wrong_timing_type_and_negative (__main__.Normalization.test_wrong_timing_type_and_negative) ... ok +test_all_events_beyond_recent_window (__main__.Reports.test_all_events_beyond_recent_window) ... ok +test_all_semantic_layers_compared (__main__.Reports.test_all_semantic_layers_compared) ... ok +test_digest_alone_is_not_enough (__main__.Reports.test_digest_alone_is_not_enough) ... ok +test_event_original_types_and_order (__main__.Reports.test_event_original_types_and_order) ... ok +test_event_start_and_ids (__main__.Reports.test_event_start_and_ids) ... ok +test_exclusions_keep_actual_values (__main__.Reports.test_exclusions_keep_actual_values) ... ok +test_handler_sets_and_counts (__main__.Reports.test_handler_sets_and_counts) ... ok +test_observation_full_layers (__main__.Reports.test_observation_full_layers) ... ok +test_product_digest_self_consistency (__main__.Reports.test_product_digest_self_consistency) ... ok +test_same_report (__main__.Reports.test_same_report) ... ok +test_scenario_existing_failures_preserved (__main__.Reports.test_scenario_existing_failures_preserved) ... ok +test_timing_digest_rule (__main__.Reports.test_timing_digest_rule) ... ok +test_unknown_or_missing_fields_rejected (__main__.Reports.test_unknown_or_missing_fields_rejected) ... ok +test_violation_presence_and_difference (__main__.Reports.test_violation_presence_and_difference) ... ok +test_O_cadence (__main__.S2Format.test_O_cadence) ... ok +test_counter_and_published_ids_binding (__main__.S2Format.test_counter_and_published_ids_binding) ... ok +test_diff_and_same_as_S_transport (__main__.S2Format.test_diff_and_same_as_S_transport) ... ok +test_digest_and_scenario_contradiction (__main__.S2Format.test_digest_and_scenario_contradiction) ... ok +test_event_no_drop_duplicate_remap (__main__.S2Format.test_event_no_drop_duplicate_remap) ... ok +test_event_original_field_types_mandatory (__main__.S2Format.test_event_original_field_types_mandatory) ... ok +test_guard_actual_not_assumed (__main__.S2Format.test_guard_actual_not_assumed) ... ok +test_harness_digest_allows_only_dictionary_order (__main__.S2Format.test_harness_digest_allows_only_dictionary_order) ... ok +test_join_is_copy_and_retains_normalization_proof (__main__.S2Format.test_join_is_copy_and_retains_normalization_proof) ... ok +test_kernel_cache_contradictions (__main__.S2Format.test_kernel_cache_contradictions) ... ok +test_lifecycle_guard_errors_and_boundaries (__main__.S2Format.test_lifecycle_guard_errors_and_boundaries) ... ok +test_missing_full_state_not_digest_only (__main__.S2Format.test_missing_full_state_not_digest_only) ... ok +test_normalized_digest_and_raw_tree_are_both_bound (__main__.S2Format.test_normalized_digest_and_raw_tree_are_both_bound) ... ok +test_product_event_shape_and_typed_array (__main__.S2Format.test_product_event_shape_and_typed_array) ... ok +test_raw_observation_binding (__main__.S2Format.test_raw_observation_binding) ... ok +test_roundtrip_tree_sha_and_raw_sha (__main__.S2Format.test_roundtrip_tree_sha_and_raw_sha) ... ok +test_s2_valid_and_not_formal_acceptance (__main__.S2Format.test_s2_valid_and_not_formal_acceptance) ... ok +test_state_witness_and_observation_mutation (__main__.S2Format.test_state_witness_and_observation_mutation) ... ok +test_stdout_exactly_one_line (__main__.S2Format.test_stdout_exactly_one_line) ... ok +test_autoload_class_and_script_import (__main__.S2Static.test_autoload_class_and_script_import) ... ok +test_comment_does_not_supply_proof (__main__.S2Static.test_comment_does_not_supply_proof) ... ok +test_current_probe (__main__.S2Static.test_current_probe) ... ok +test_full_state_and_godot_roundtrip_required (__main__.S2Static.test_full_state_and_godot_roundtrip_required) ... ok +test_no_changes_outside_preparation_or_step (__main__.S2Static.test_no_changes_outside_preparation_or_step) ... ok +test_no_event_cap_or_duplicate_report (__main__.S2Static.test_no_event_cap_or_duplicate_report) ... ok +test_pause_and_step_arguments (__main__.S2Static.test_pause_and_step_arguments) ... ok +test_textual_stringname_ordering (__main__.S2Static.test_textual_stringname_ordering) ... ok +test_unlisted_live_method_and_late_preparation (__main__.S2Static.test_unlisted_live_method_and_late_preparation) ... ok +test_variant_inference (__main__.S2Static.test_variant_inference) ... ok +test_X_recent_limit_and_counter (__main__.S3a.test_X_recent_limit_and_counter) ... ok +test_duplicate_JSON_key_rejected (__main__.S3a.test_duplicate_JSON_key_rejected) ... ok +test_e3_NA_cannot_be_PASS_or_applied (__main__.S3a.test_e3_NA_cannot_be_PASS_or_applied) ... ok +test_e3_coverage_input_and_event_count_binding (__main__.S3a.test_e3_coverage_input_and_event_count_binding) ... ok +test_e3_invented_codes_and_missing_load_code (__main__.S3a.test_e3_invented_codes_and_missing_load_code) ... ok +test_e3_valid_R_and_O_records (__main__.S3a.test_e3_valid_R_and_O_records) ... ok +test_envelope_duplicates_not_defect (__main__.S3a.test_envelope_duplicates_not_defect) ... ok +test_event_count_defect_not_silently_accepted (__main__.S3a.test_event_count_defect_not_silently_accepted) ... ok +test_exact_phase_keys (__main__.S3a.test_exact_phase_keys) ... ok +test_interval_gap_rejected (__main__.S3a.test_interval_gap_rejected) ... ok +test_invalid_input_accepted_is_not_PASS (__main__.S3a.test_invalid_input_accepted_is_not_PASS) ... ok +test_load_payload_and_pause_outcome (__main__.S3a.test_load_payload_and_pause_outcome) ... ok +test_operation_moved_outside_scenario_rejected (__main__.S3a.test_operation_moved_outside_scenario_rejected) ... ok +test_package_fixed_mutations_and_hashes (__main__.S3a.test_package_fixed_mutations_and_hashes) ... ok +test_probe_connection_required (__main__.S3a.test_probe_connection_required) ... ok +test_rejection_mutation_retained_as_defect (__main__.S3a.test_rejection_mutation_retained_as_defect) ... ok +test_save_refusal_makes_load_NA (__main__.S3a.test_save_refusal_makes_load_NA) ... ok +test_scenario_mutation_static_boundary (__main__.S3a.test_scenario_mutation_static_boundary) ... ok +test_signals_all_minutes_and_order (__main__.S3a.test_signals_all_minutes_and_order) ... ok +test_E5_cached_digest_defect_is_comparable (__main__.S3b.test_E5_cached_digest_defect_is_comparable) ... ok +test_NA_not_PASS (__main__.S3b.test_NA_not_PASS) ... ok +test_aliasing_cannot_be_PASS (__main__.S3b.test_aliasing_cannot_be_PASS) ... ok +test_aliasing_missing_record (__main__.S3b.test_aliasing_missing_record) ... ok +test_all_paths_and_ownership_R_O (__main__.S3b.test_all_paths_and_ownership_R_O) ... ok +test_digest_defect_other_checkpoint_still_rejected (__main__.S3b.test_digest_defect_other_checkpoint_still_rejected) ... ok +test_digest_materialization_required (__main__.S3b.test_digest_materialization_required) ... ok +test_empty_registry_not_NA (__main__.S3b.test_empty_registry_not_NA) ... ok +test_event_count_mismatch (__main__.S3b.test_event_count_mismatch) ... ok +test_facts_normalization_is_reversible (__main__.S3b.test_facts_normalization_is_reversible) ... ok +test_first_placeable_choice (__main__.S3b.test_first_placeable_choice) ... ok +test_interval_gap (__main__.S3b.test_interval_gap) ... ok +test_joined_s3b_self_comparison (__main__.S3b.test_joined_s3b_self_comparison) ... ok +test_load_X_not_digest_only (__main__.S3b.test_load_X_not_digest_only) ... ok +test_load_extra_event (__main__.S3b.test_load_extra_event) ... ok +test_missing_path_and_combination (__main__.S3b.test_missing_path_and_combination) ... ok +test_missing_preview_observation (__main__.S3b.test_missing_preview_observation) ... ok +test_missing_trial (__main__.S3b.test_missing_trial) ... ok +test_nested_mutation_required (__main__.S3b.test_nested_mutation_required) ... ok +test_no_staleness_assertion_for_non_tick (__main__.S3b.test_no_staleness_assertion_for_non_tick) ... ok +test_ownership_fact_dictionary_order_fallback (__main__.S3b.test_ownership_fact_dictionary_order_fallback) ... ok +test_path_order (__main__.S3b.test_path_order) ... ok +test_restore_extra_event (__main__.S3b.test_restore_extra_event) ... ok +test_signal_facts_cannot_be_dropped (__main__.S3b.test_signal_facts_cannot_be_dropped) ... ok +test_sort_rule_rejected (__main__.S3b.test_sort_rule_rejected) ... ok +test_static_handler_and_outside_mutations (__main__.S3b.test_static_handler_and_outside_mutations) ... ok +test_unpreviewed_choice (__main__.S3b.test_unpreviewed_choice) ... ok +test_wrong_registry_in_either_role (__main__.S3b.test_wrong_registry_in_either_role) ... ok +test_checkout_temp_destination_rejected (__main__.S4Bundle.test_checkout_temp_destination_rejected) ... ok +test_existing_output_never_overwritten (__main__.S4Bundle.test_existing_output_never_overwritten) ... ok +test_import_closure_rejections (__main__.S4Bundle.test_import_closure_rejections) ... ok +test_missing_bundle_manifest_seal_and_changed_bytes (__main__.S4Bundle.test_missing_bundle_manifest_seal_and_changed_bytes) ... ok +test_missing_private_evidence_and_extra_rejected (__main__.S4Bundle.test_missing_private_evidence_and_extra_rejected) ... ok +test_missing_profile_not_export_success (__main__.S4Bundle.test_missing_profile_not_export_success) ... ok +test_phase_role_pid_audio_and_guard_rejected (__main__.S4Bundle.test_phase_role_pid_audio_and_guard_rejected) ... ok +test_rebound_lifecycle_and_scenario_contradictions (__main__.S4Bundle.test_rebound_lifecycle_and_scenario_contradictions) ... ok +test_seal_normal_and_changes_not_native_proof (__main__.S4Bundle.test_seal_normal_and_changes_not_native_proof) ... ok +test_synthetic_phase_all_real_checkers_not_native_proof (__main__.S4Bundle.test_synthetic_phase_all_real_checkers_not_native_proof) ... ok +test_copied_manifest_root_and_destination_count_rejected (__main__.S4NativeBundleLogic.test_copied_manifest_root_and_destination_count_rejected) ... ok +test_failure_keeps_raw_and_no_bundle_without_starting_engine (__main__.S4NativeBundleLogic.test_failure_keeps_raw_and_no_bundle_without_starting_engine) ... ok +test_gate_none_success_not_boolean (__main__.S4NativeBundleLogic.test_gate_none_success_not_boolean) ... ok +test_receipt_and_source_rejection_matrix (__main__.S4NativeBundleLogic.test_receipt_and_source_rejection_matrix) ... ok +test_synthetic_full_bundle_positive_not_native_evidence (__main__.S4NativeBundleLogic.test_synthetic_full_bundle_positive_not_native_evidence) ... ok +test_check_accepts_true (__main__.S4ProbeAdmission.test_check_accepts_true) ... ok +test_check_rejects_false_all_errors (__main__.S4ProbeAdmission.test_check_rejects_false_all_errors) ... ok +test_run_admission_accepts_true_mock_launch_only (__main__.S4ProbeAdmission.test_run_admission_accepts_true_mock_launch_only) ... ok +test_run_admission_rejects_false_without_engine (__main__.S4ProbeAdmission.test_run_admission_rejects_false_without_engine) ... ok +test_nine_original_destinations_required (__main__.S4RemainingBindings.test_nine_original_destinations_required) ... ok +test_nonzero_determinism_rejected_after_real_join (__main__.S4RemainingBindings.test_nonzero_determinism_rejected_after_real_join) ... ok +test_owned_lifecycle_exit_diagnostic_and_profile_rejections (__main__.S4RemainingBindings.test_owned_lifecycle_exit_diagnostic_and_profile_rejections) ... ok +test_verifier_accepts_true_recomputes_raw (__main__.S4RemainingBindings.test_verifier_accepts_true_recomputes_raw) ... ok +test_verifier_rejects_false_with_every_error (__main__.S4RemainingBindings.test_verifier_rejects_false_with_every_error) ... ok +test_cached_verdict_not_trusted (__main__.S4StoredResultBindings.test_cached_verdict_not_trusted) ... ok +test_missing_sidecar_rejected_after_seal (__main__.S4StoredResultBindings.test_missing_sidecar_rejected_after_seal) ... ok +test_raw_joined_substitution_rejected_after_seal (__main__.S4StoredResultBindings.test_raw_joined_substitution_rejected_after_seal) ... ok +test_blob_transport_is_verified_and_bound (__main__.S5.test_blob_transport_is_verified_and_bound) ... ok +test_blob_trees_get_the_same_full_validation_as_inline (__main__.S5.test_blob_trees_get_the_same_full_validation_as_inline) ... ok +test_compare_and_digest_equal_s1_reference (__main__.S5.test_compare_and_digest_equal_s1_reference) ... ok +test_event_stream_replacement_is_existing_defect_not_pass (__main__.S5.test_event_stream_replacement_is_existing_defect_not_pass) ... ok +test_every_checkpoint_full_tree_verified_like_inline (__main__.S5.test_every_checkpoint_full_tree_verified_like_inline) +S5 drops the diff chain: each checkpoint carries a complete tree, verified alone. ... ok +test_fast_normalization_equals_original (__main__.S5.test_fast_normalization_equals_original) ... ok +test_labelled_harness_digest_falls_back_to_dictionary_order_only (__main__.S5.test_labelled_harness_digest_falls_back_to_dictionary_order_only) ... ok +test_lifecycle_binds_replacements_guard_text_and_blobs (__main__.S5.test_lifecycle_binds_replacements_guard_text_and_blobs) ... ok +test_manifest_numbers_keep_their_type (__main__.S5.test_manifest_numbers_keep_their_type) ... ok +test_memo_scope_same_results_and_restores_gc (__main__.S5.test_memo_scope_same_results_and_restores_gc) ... ok +test_path_copy_builders_equal_deepcopy_reference (__main__.S5.test_path_copy_builders_equal_deepcopy_reference) ... ok +test_probe_static_full_tree_blob_and_stream_requirements (__main__.S5.test_probe_static_full_tree_blob_and_stream_requirements) ... ok +test_publish_pairs_bound_to_source_causes (__main__.S5.test_publish_pairs_bound_to_source_causes) ... ok +test_signed_instance_ids_raw_kept_and_excluded (__main__.S5.test_signed_instance_ids_raw_kept_and_excluded) ... ok +test_fixed_scenario_paths (__main__.SourcesAndMetrics.test_fixed_scenario_paths) ... ok +test_metric_ranges (__main__.SourcesAndMetrics.test_metric_ranges) ... ok +test_source_closure_synthetic_registered_map (__main__.SourcesAndMetrics.test_source_closure_synthetic_registered_map) ... ok +test_source_pin_is_not_caller_controlled (__main__.SourcesAndMetrics.test_source_pin_is_not_caller_controlled) ... ok +test_array_order_and_all_differences (__main__.TypedTrees.test_array_order_and_all_differences) ... ok +test_components_and_sha (__main__.TypedTrees.test_components_and_sha) ... ok +test_deep_state_not_truncated (__main__.TypedTrees.test_deep_state_not_truncated) ... ok +test_duplicate_textual_keys_rejected (__main__.TypedTrees.test_duplicate_textual_keys_rejected) ... ok +test_exact_and_types (__main__.TypedTrees.test_exact_and_types) ... ok +test_nested_order_all_paths (__main__.TypedTrees.test_nested_order_all_paths) ... ok +test_nonstring_keys_keep_types_and_values (__main__.TypedTrees.test_nonstring_keys_keep_types_and_values) ... ok +test_unsupported_and_malformed (__main__.TypedTrees.test_unsupported_and_malformed) ... ok + +---------------------------------------------------------------------- +Ran 160 tests in 130.451s + +OK +python_exit=0 diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_04.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_04.sha256 new file mode 100644 index 0000000..4829024 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_04.sha256 @@ -0,0 +1 @@ +f8b652c4f0cdc52c061cd58f1a1334e755c22d5dc206225a5cf2d4863a780c85 UNIT_OUTPUT_S5_ATTEMPT_04.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_04.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_04.txt new file mode 100644 index 0000000..02099a6 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_04.txt @@ -0,0 +1,202 @@ +test_all_operations (__main__.Diffs.test_all_operations) ... ok +test_invalid_operations (__main__.Diffs.test_invalid_operations) ... ok +test_reconstruction_and_proofs (__main__.Diffs.test_reconstruction_and_proofs) ... ok +test_attempt_to_normalize_violation_rejected (__main__.Normalization.test_attempt_to_normalize_violation_rejected) ... ok +test_environment_values_differ_but_normal_form_equal (__main__.Normalization.test_environment_values_differ_but_normal_form_equal) ... ok +test_every_save_event_reversible (__main__.Normalization.test_every_save_event_reversible) ... ok +test_f3_keeps_relative_paths_and_words (__main__.Normalization.test_f3_keeps_relative_paths_and_words) ... ok +test_guard_mismatch (__main__.Normalization.test_guard_mismatch) ... ok +test_nested_lookalike_is_not_eligible (__main__.Normalization.test_nested_lookalike_is_not_eligible) ... ok +test_original_transport_sha_detects_forged_timing (__main__.Normalization.test_original_transport_sha_detects_forged_timing) ... ok +test_partial_timing_payload_rejected (__main__.Normalization.test_partial_timing_payload_rejected) ... ok +test_prefix_boundary_and_reserved_token (__main__.Normalization.test_prefix_boundary_and_reserved_token) ... ok +test_sidecar_missing_duplicate_and_forged_paths (__main__.Normalization.test_sidecar_missing_duplicate_and_forged_paths) ... ok +test_snapshot_and_latest_reversible (__main__.Normalization.test_snapshot_and_latest_reversible) ... ok +test_snapshot_event_outside_recent_is_not_eligible (__main__.Normalization.test_snapshot_event_outside_recent_is_not_eligible) ... ok +test_wrong_event_and_source_are_preserved (__main__.Normalization.test_wrong_event_and_source_are_preserved) ... ok +test_wrong_timing_type_and_negative (__main__.Normalization.test_wrong_timing_type_and_negative) ... ok +test_all_events_beyond_recent_window (__main__.Reports.test_all_events_beyond_recent_window) ... ok +test_all_semantic_layers_compared (__main__.Reports.test_all_semantic_layers_compared) ... ok +test_digest_alone_is_not_enough (__main__.Reports.test_digest_alone_is_not_enough) ... ok +test_event_original_types_and_order (__main__.Reports.test_event_original_types_and_order) ... ok +test_event_start_and_ids (__main__.Reports.test_event_start_and_ids) ... ok +test_exclusions_keep_actual_values (__main__.Reports.test_exclusions_keep_actual_values) ... ok +test_handler_sets_and_counts (__main__.Reports.test_handler_sets_and_counts) ... ok +test_observation_full_layers (__main__.Reports.test_observation_full_layers) ... ok +test_product_digest_self_consistency (__main__.Reports.test_product_digest_self_consistency) ... ok +test_same_report (__main__.Reports.test_same_report) ... ok +test_scenario_existing_failures_preserved (__main__.Reports.test_scenario_existing_failures_preserved) ... ok +test_timing_digest_rule (__main__.Reports.test_timing_digest_rule) ... ok +test_unknown_or_missing_fields_rejected (__main__.Reports.test_unknown_or_missing_fields_rejected) ... ok +test_violation_presence_and_difference (__main__.Reports.test_violation_presence_and_difference) ... ok +test_O_cadence (__main__.S2Format.test_O_cadence) ... ok +test_counter_and_published_ids_binding (__main__.S2Format.test_counter_and_published_ids_binding) ... ok +test_diff_and_same_as_S_transport (__main__.S2Format.test_diff_and_same_as_S_transport) ... ok +test_digest_and_scenario_contradiction (__main__.S2Format.test_digest_and_scenario_contradiction) ... ok +test_event_no_drop_duplicate_remap (__main__.S2Format.test_event_no_drop_duplicate_remap) ... ok +test_event_original_field_types_mandatory (__main__.S2Format.test_event_original_field_types_mandatory) ... ok +test_guard_actual_not_assumed (__main__.S2Format.test_guard_actual_not_assumed) ... ok +test_harness_digest_allows_only_dictionary_order (__main__.S2Format.test_harness_digest_allows_only_dictionary_order) ... ok +test_join_is_copy_and_retains_normalization_proof (__main__.S2Format.test_join_is_copy_and_retains_normalization_proof) ... ok +test_kernel_cache_contradictions (__main__.S2Format.test_kernel_cache_contradictions) ... ok +test_lifecycle_guard_errors_and_boundaries (__main__.S2Format.test_lifecycle_guard_errors_and_boundaries) ... ok +test_missing_full_state_not_digest_only (__main__.S2Format.test_missing_full_state_not_digest_only) ... ok +test_normalized_digest_and_raw_tree_are_both_bound (__main__.S2Format.test_normalized_digest_and_raw_tree_are_both_bound) ... ok +test_product_event_shape_and_typed_array (__main__.S2Format.test_product_event_shape_and_typed_array) ... ok +test_raw_observation_binding (__main__.S2Format.test_raw_observation_binding) ... ok +test_roundtrip_tree_sha_and_raw_sha (__main__.S2Format.test_roundtrip_tree_sha_and_raw_sha) ... ok +test_s2_valid_and_not_formal_acceptance (__main__.S2Format.test_s2_valid_and_not_formal_acceptance) ... ok +test_state_witness_and_observation_mutation (__main__.S2Format.test_state_witness_and_observation_mutation) ... ok +test_stdout_exactly_one_line (__main__.S2Format.test_stdout_exactly_one_line) ... ok +test_autoload_class_and_script_import (__main__.S2Static.test_autoload_class_and_script_import) ... ok +test_comment_does_not_supply_proof (__main__.S2Static.test_comment_does_not_supply_proof) ... ok +test_current_probe (__main__.S2Static.test_current_probe) ... ok +test_full_state_and_godot_roundtrip_required (__main__.S2Static.test_full_state_and_godot_roundtrip_required) ... ok +test_no_changes_outside_preparation_or_step (__main__.S2Static.test_no_changes_outside_preparation_or_step) ... ok +test_no_event_cap_or_duplicate_report (__main__.S2Static.test_no_event_cap_or_duplicate_report) ... ok +test_pause_and_step_arguments (__main__.S2Static.test_pause_and_step_arguments) ... ok +test_textual_stringname_ordering (__main__.S2Static.test_textual_stringname_ordering) ... ok +test_unlisted_live_method_and_late_preparation (__main__.S2Static.test_unlisted_live_method_and_late_preparation) ... ok +test_variant_inference (__main__.S2Static.test_variant_inference) ... ok +test_X_recent_limit_and_counter (__main__.S3a.test_X_recent_limit_and_counter) ... ok +test_duplicate_JSON_key_rejected (__main__.S3a.test_duplicate_JSON_key_rejected) ... ok +test_e3_NA_cannot_be_PASS_or_applied (__main__.S3a.test_e3_NA_cannot_be_PASS_or_applied) ... ok +test_e3_coverage_input_and_event_count_binding (__main__.S3a.test_e3_coverage_input_and_event_count_binding) ... ok +test_e3_invented_codes_and_missing_load_code (__main__.S3a.test_e3_invented_codes_and_missing_load_code) ... ok +test_e3_valid_R_and_O_records (__main__.S3a.test_e3_valid_R_and_O_records) ... ok +test_envelope_duplicates_not_defect (__main__.S3a.test_envelope_duplicates_not_defect) ... ok +test_event_count_defect_not_silently_accepted (__main__.S3a.test_event_count_defect_not_silently_accepted) ... ok +test_exact_phase_keys (__main__.S3a.test_exact_phase_keys) ... ok +test_interval_gap_rejected (__main__.S3a.test_interval_gap_rejected) ... ok +test_invalid_input_accepted_is_not_PASS (__main__.S3a.test_invalid_input_accepted_is_not_PASS) ... ok +test_load_payload_and_pause_outcome (__main__.S3a.test_load_payload_and_pause_outcome) ... ok +test_operation_moved_outside_scenario_rejected (__main__.S3a.test_operation_moved_outside_scenario_rejected) ... ok +test_package_fixed_mutations_and_hashes (__main__.S3a.test_package_fixed_mutations_and_hashes) ... ok +test_probe_connection_required (__main__.S3a.test_probe_connection_required) ... ok +test_rejection_mutation_retained_as_defect (__main__.S3a.test_rejection_mutation_retained_as_defect) ... ok +test_save_refusal_makes_load_NA (__main__.S3a.test_save_refusal_makes_load_NA) ... ok +test_scenario_mutation_static_boundary (__main__.S3a.test_scenario_mutation_static_boundary) ... ok +test_signals_all_minutes_and_order (__main__.S3a.test_signals_all_minutes_and_order) ... ok +test_E5_cached_digest_defect_is_comparable (__main__.S3b.test_E5_cached_digest_defect_is_comparable) ... ok +test_NA_not_PASS (__main__.S3b.test_NA_not_PASS) ... ok +test_aliasing_cannot_be_PASS (__main__.S3b.test_aliasing_cannot_be_PASS) ... ok +test_aliasing_missing_record (__main__.S3b.test_aliasing_missing_record) ... ok +test_all_paths_and_ownership_R_O (__main__.S3b.test_all_paths_and_ownership_R_O) ... ok +test_digest_defect_other_checkpoint_still_rejected (__main__.S3b.test_digest_defect_other_checkpoint_still_rejected) ... ok +test_digest_materialization_required (__main__.S3b.test_digest_materialization_required) ... ok +test_empty_registry_not_NA (__main__.S3b.test_empty_registry_not_NA) ... ok +test_event_count_mismatch (__main__.S3b.test_event_count_mismatch) ... ok +test_facts_normalization_is_reversible (__main__.S3b.test_facts_normalization_is_reversible) ... ok +test_first_placeable_choice (__main__.S3b.test_first_placeable_choice) ... ok +test_interval_gap (__main__.S3b.test_interval_gap) ... ok +test_joined_s3b_self_comparison (__main__.S3b.test_joined_s3b_self_comparison) ... ok +test_load_X_not_digest_only (__main__.S3b.test_load_X_not_digest_only) ... ok +test_load_extra_event (__main__.S3b.test_load_extra_event) ... ok +test_missing_path_and_combination (__main__.S3b.test_missing_path_and_combination) ... ok +test_missing_preview_observation (__main__.S3b.test_missing_preview_observation) ... ok +test_missing_trial (__main__.S3b.test_missing_trial) ... ok +test_nested_mutation_required (__main__.S3b.test_nested_mutation_required) ... ok +test_no_staleness_assertion_for_non_tick (__main__.S3b.test_no_staleness_assertion_for_non_tick) ... ok +test_ownership_fact_dictionary_order_fallback (__main__.S3b.test_ownership_fact_dictionary_order_fallback) ... ok +test_path_order (__main__.S3b.test_path_order) ... ok +test_restore_extra_event (__main__.S3b.test_restore_extra_event) ... ok +test_signal_facts_cannot_be_dropped (__main__.S3b.test_signal_facts_cannot_be_dropped) ... ok +test_sort_rule_rejected (__main__.S3b.test_sort_rule_rejected) ... ok +test_static_handler_and_outside_mutations (__main__.S3b.test_static_handler_and_outside_mutations) ... ok +test_unpreviewed_choice (__main__.S3b.test_unpreviewed_choice) ... ok +test_wrong_registry_in_either_role (__main__.S3b.test_wrong_registry_in_either_role) ... ok +test_checkout_temp_destination_rejected (__main__.S4Bundle.test_checkout_temp_destination_rejected) ... ok +test_existing_output_never_overwritten (__main__.S4Bundle.test_existing_output_never_overwritten) ... ok +test_import_closure_rejections (__main__.S4Bundle.test_import_closure_rejections) ... ERROR +test_missing_bundle_manifest_seal_and_changed_bytes (__main__.S4Bundle.test_missing_bundle_manifest_seal_and_changed_bytes) ... ok +test_missing_private_evidence_and_extra_rejected (__main__.S4Bundle.test_missing_private_evidence_and_extra_rejected) ... ok +test_missing_profile_not_export_success (__main__.S4Bundle.test_missing_profile_not_export_success) ... ok +test_phase_role_pid_audio_and_guard_rejected (__main__.S4Bundle.test_phase_role_pid_audio_and_guard_rejected) ... ok +test_rebound_lifecycle_and_scenario_contradictions (__main__.S4Bundle.test_rebound_lifecycle_and_scenario_contradictions) ... ok +test_seal_normal_and_changes_not_native_proof (__main__.S4Bundle.test_seal_normal_and_changes_not_native_proof) ... ok +test_synthetic_phase_all_real_checkers_not_native_proof (__main__.S4Bundle.test_synthetic_phase_all_real_checkers_not_native_proof) ... ok +setUpClass (__main__.S4NativeBundleLogic) ... ERROR +test_check_accepts_true (__main__.S4ProbeAdmission.test_check_accepts_true) ... ok +test_check_rejects_false_all_errors (__main__.S4ProbeAdmission.test_check_rejects_false_all_errors) ... ok +test_run_admission_accepts_true_mock_launch_only (__main__.S4ProbeAdmission.test_run_admission_accepts_true_mock_launch_only) ... ok +test_run_admission_rejects_false_without_engine (__main__.S4ProbeAdmission.test_run_admission_rejects_false_without_engine) ... ok +setUpClass (__main__.S4RemainingBindings) ... ERROR +test_cached_verdict_not_trusted (__main__.S4StoredResultBindings.test_cached_verdict_not_trusted) ... ok +test_missing_sidecar_rejected_after_seal (__main__.S4StoredResultBindings.test_missing_sidecar_rejected_after_seal) ... ok +test_raw_joined_substitution_rejected_after_seal (__main__.S4StoredResultBindings.test_raw_joined_substitution_rejected_after_seal) ... ok +test_blob_transport_is_verified_and_bound (__main__.S5.test_blob_transport_is_verified_and_bound) ... ok +test_blob_trees_get_the_same_full_validation_as_inline (__main__.S5.test_blob_trees_get_the_same_full_validation_as_inline) ... ok +test_compare_and_digest_equal_s1_reference (__main__.S5.test_compare_and_digest_equal_s1_reference) ... ok +test_event_stream_replacement_is_existing_defect_not_pass (__main__.S5.test_event_stream_replacement_is_existing_defect_not_pass) ... ok +test_every_checkpoint_full_tree_verified_like_inline (__main__.S5.test_every_checkpoint_full_tree_verified_like_inline) +S5 drops the diff chain: each checkpoint carries a complete tree, verified alone. ... ok +test_fast_normalization_equals_original (__main__.S5.test_fast_normalization_equals_original) ... ok +test_labelled_harness_digest_falls_back_to_dictionary_order_only (__main__.S5.test_labelled_harness_digest_falls_back_to_dictionary_order_only) ... ok +test_lifecycle_binds_replacements_guard_text_and_blobs (__main__.S5.test_lifecycle_binds_replacements_guard_text_and_blobs) ... ok +test_manifest_numbers_keep_their_type (__main__.S5.test_manifest_numbers_keep_their_type) ... ok +test_memo_scope_same_results_and_restores_gc (__main__.S5.test_memo_scope_same_results_and_restores_gc) ... ok +test_path_copy_builders_equal_deepcopy_reference (__main__.S5.test_path_copy_builders_equal_deepcopy_reference) ... ok +test_probe_static_full_tree_blob_and_stream_requirements (__main__.S5.test_probe_static_full_tree_blob_and_stream_requirements) ... ok +test_publish_pairs_bound_to_source_causes (__main__.S5.test_publish_pairs_bound_to_source_causes) ... ok +test_signed_instance_ids_raw_kept_and_excluded (__main__.S5.test_signed_instance_ids_raw_kept_and_excluded) ... ok +test_validate_tree_equals_s1_reference_on_mutations (__main__.S5.test_validate_tree_equals_s1_reference_on_mutations) ... ok +test_fixed_scenario_paths (__main__.SourcesAndMetrics.test_fixed_scenario_paths) ... ok +test_metric_ranges (__main__.SourcesAndMetrics.test_metric_ranges) ... ok +test_source_closure_synthetic_registered_map (__main__.SourcesAndMetrics.test_source_closure_synthetic_registered_map) ... ok +test_source_pin_is_not_caller_controlled (__main__.SourcesAndMetrics.test_source_pin_is_not_caller_controlled) ... ok +test_array_order_and_all_differences (__main__.TypedTrees.test_array_order_and_all_differences) ... ok +test_components_and_sha (__main__.TypedTrees.test_components_and_sha) ... ok +test_deep_state_not_truncated (__main__.TypedTrees.test_deep_state_not_truncated) ... ok +test_duplicate_textual_keys_rejected (__main__.TypedTrees.test_duplicate_textual_keys_rejected) ... ok +test_exact_and_types (__main__.TypedTrees.test_exact_and_types) ... ok +test_nested_order_all_paths (__main__.TypedTrees.test_nested_order_all_paths) ... ok +test_nonstring_keys_keep_types_and_values (__main__.TypedTrees.test_nonstring_keys_keep_types_and_values) ... ok +test_unsupported_and_malformed (__main__.TypedTrees.test_unsupported_and_malformed) ... ok + +====================================================================== +ERROR: test_import_closure_rejections (__main__.S4Bundle.test_import_closure_rejections) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1487, in test_import_closure_rejections + self.assertTrue(checker.check_python_imports((verifier.HERE/name).read_text())) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/check_eq.py", line 29, in check_python_imports + eq.require(all(n and n.split('.')[0] in allowed for n in names), 'import outside EQ closure') + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py", line 168, in require + raise EvidenceError(message) +compare_versions.EvidenceError: import outside EQ closure + +====================================================================== +ERROR: setUpClass (__main__.S4NativeBundleLogic) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1514, in setUpClass + cls.collector, cls.standard, cls.outer, cls.diag = driver.load_dependencies() + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/run_eq.py", line 54, in load_dependencies + check.check_python_imports((local / name).read_text()) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/check_eq.py", line 29, in check_python_imports + eq.require(all(n and n.split('.')[0] in allowed for n in names), 'import outside EQ closure') + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py", line 168, in require + raise EvidenceError(message) +compare_versions.EvidenceError: import outside EQ closure + +====================================================================== +ERROR: setUpClass (__main__.S4RemainingBindings) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py", line 1514, in setUpClass + cls.collector, cls.standard, cls.outer, cls.diag = driver.load_dependencies() + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/run_eq.py", line 54, in load_dependencies + check.check_python_imports((local / name).read_text()) + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/check_eq.py", line 29, in check_python_imports + eq.require(all(n and n.split('.')[0] in allowed for n in names), 'import outside EQ closure') + File "/Users/korizatou114/Projects/TheTree-managed-worktrees/p28-02-eq/P28-02-EQ-implement/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py", line 168, in require + raise EvidenceError(message) +compare_versions.EvidenceError: import outside EQ closure + +---------------------------------------------------------------------- +Ran 151 tests in 42.213s + +FAILED (errors=3) diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_05.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_05.sha256 new file mode 100644 index 0000000..93c569f --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_05.sha256 @@ -0,0 +1 @@ +7372a382cc2f3c090013874d8f28f17cad4cb1b965ad86c86de7a21fc2d851a8 UNIT_OUTPUT_S5_ATTEMPT_05.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_05.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_05.txt new file mode 100644 index 0000000..5cbff21 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_05.txt @@ -0,0 +1,167 @@ +test_all_operations (__main__.Diffs.test_all_operations) ... ok +test_invalid_operations (__main__.Diffs.test_invalid_operations) ... ok +test_reconstruction_and_proofs (__main__.Diffs.test_reconstruction_and_proofs) ... ok +test_attempt_to_normalize_violation_rejected (__main__.Normalization.test_attempt_to_normalize_violation_rejected) ... ok +test_environment_values_differ_but_normal_form_equal (__main__.Normalization.test_environment_values_differ_but_normal_form_equal) ... ok +test_every_save_event_reversible (__main__.Normalization.test_every_save_event_reversible) ... ok +test_f3_keeps_relative_paths_and_words (__main__.Normalization.test_f3_keeps_relative_paths_and_words) ... ok +test_guard_mismatch (__main__.Normalization.test_guard_mismatch) ... ok +test_nested_lookalike_is_not_eligible (__main__.Normalization.test_nested_lookalike_is_not_eligible) ... ok +test_original_transport_sha_detects_forged_timing (__main__.Normalization.test_original_transport_sha_detects_forged_timing) ... ok +test_partial_timing_payload_rejected (__main__.Normalization.test_partial_timing_payload_rejected) ... ok +test_prefix_boundary_and_reserved_token (__main__.Normalization.test_prefix_boundary_and_reserved_token) ... ok +test_sidecar_missing_duplicate_and_forged_paths (__main__.Normalization.test_sidecar_missing_duplicate_and_forged_paths) ... ok +test_snapshot_and_latest_reversible (__main__.Normalization.test_snapshot_and_latest_reversible) ... ok +test_snapshot_event_outside_recent_is_not_eligible (__main__.Normalization.test_snapshot_event_outside_recent_is_not_eligible) ... ok +test_wrong_event_and_source_are_preserved (__main__.Normalization.test_wrong_event_and_source_are_preserved) ... ok +test_wrong_timing_type_and_negative (__main__.Normalization.test_wrong_timing_type_and_negative) ... ok +test_all_events_beyond_recent_window (__main__.Reports.test_all_events_beyond_recent_window) ... ok +test_all_semantic_layers_compared (__main__.Reports.test_all_semantic_layers_compared) ... ok +test_digest_alone_is_not_enough (__main__.Reports.test_digest_alone_is_not_enough) ... ok +test_event_original_types_and_order (__main__.Reports.test_event_original_types_and_order) ... ok +test_event_start_and_ids (__main__.Reports.test_event_start_and_ids) ... ok +test_exclusions_keep_actual_values (__main__.Reports.test_exclusions_keep_actual_values) ... ok +test_handler_sets_and_counts (__main__.Reports.test_handler_sets_and_counts) ... ok +test_observation_full_layers (__main__.Reports.test_observation_full_layers) ... ok +test_product_digest_self_consistency (__main__.Reports.test_product_digest_self_consistency) ... ok +test_same_report (__main__.Reports.test_same_report) ... ok +test_scenario_existing_failures_preserved (__main__.Reports.test_scenario_existing_failures_preserved) ... ok +test_timing_digest_rule (__main__.Reports.test_timing_digest_rule) ... ok +test_unknown_or_missing_fields_rejected (__main__.Reports.test_unknown_or_missing_fields_rejected) ... ok +test_violation_presence_and_difference (__main__.Reports.test_violation_presence_and_difference) ... ok +test_O_cadence (__main__.S2Format.test_O_cadence) ... ok +test_counter_and_published_ids_binding (__main__.S2Format.test_counter_and_published_ids_binding) ... ok +test_diff_and_same_as_S_transport (__main__.S2Format.test_diff_and_same_as_S_transport) ... ok +test_digest_and_scenario_contradiction (__main__.S2Format.test_digest_and_scenario_contradiction) ... ok +test_event_no_drop_duplicate_remap (__main__.S2Format.test_event_no_drop_duplicate_remap) ... ok +test_event_original_field_types_mandatory (__main__.S2Format.test_event_original_field_types_mandatory) ... ok +test_guard_actual_not_assumed (__main__.S2Format.test_guard_actual_not_assumed) ... ok +test_harness_digest_allows_only_dictionary_order (__main__.S2Format.test_harness_digest_allows_only_dictionary_order) ... ok +test_join_is_copy_and_retains_normalization_proof (__main__.S2Format.test_join_is_copy_and_retains_normalization_proof) ... ok +test_kernel_cache_contradictions (__main__.S2Format.test_kernel_cache_contradictions) ... ok +test_lifecycle_guard_errors_and_boundaries (__main__.S2Format.test_lifecycle_guard_errors_and_boundaries) ... ok +test_missing_full_state_not_digest_only (__main__.S2Format.test_missing_full_state_not_digest_only) ... ok +test_normalized_digest_and_raw_tree_are_both_bound (__main__.S2Format.test_normalized_digest_and_raw_tree_are_both_bound) ... ok +test_product_event_shape_and_typed_array (__main__.S2Format.test_product_event_shape_and_typed_array) ... ok +test_raw_observation_binding (__main__.S2Format.test_raw_observation_binding) ... ok +test_roundtrip_tree_sha_and_raw_sha (__main__.S2Format.test_roundtrip_tree_sha_and_raw_sha) ... ok +test_s2_valid_and_not_formal_acceptance (__main__.S2Format.test_s2_valid_and_not_formal_acceptance) ... ok +test_state_witness_and_observation_mutation (__main__.S2Format.test_state_witness_and_observation_mutation) ... ok +test_stdout_exactly_one_line (__main__.S2Format.test_stdout_exactly_one_line) ... ok +test_autoload_class_and_script_import (__main__.S2Static.test_autoload_class_and_script_import) ... ok +test_comment_does_not_supply_proof (__main__.S2Static.test_comment_does_not_supply_proof) ... ok +test_current_probe (__main__.S2Static.test_current_probe) ... ok +test_full_state_and_godot_roundtrip_required (__main__.S2Static.test_full_state_and_godot_roundtrip_required) ... ok +test_no_changes_outside_preparation_or_step (__main__.S2Static.test_no_changes_outside_preparation_or_step) ... ok +test_no_event_cap_or_duplicate_report (__main__.S2Static.test_no_event_cap_or_duplicate_report) ... ok +test_pause_and_step_arguments (__main__.S2Static.test_pause_and_step_arguments) ... ok +test_textual_stringname_ordering (__main__.S2Static.test_textual_stringname_ordering) ... ok +test_unlisted_live_method_and_late_preparation (__main__.S2Static.test_unlisted_live_method_and_late_preparation) ... ok +test_variant_inference (__main__.S2Static.test_variant_inference) ... ok +test_X_recent_limit_and_counter (__main__.S3a.test_X_recent_limit_and_counter) ... ok +test_duplicate_JSON_key_rejected (__main__.S3a.test_duplicate_JSON_key_rejected) ... ok +test_e3_NA_cannot_be_PASS_or_applied (__main__.S3a.test_e3_NA_cannot_be_PASS_or_applied) ... ok +test_e3_coverage_input_and_event_count_binding (__main__.S3a.test_e3_coverage_input_and_event_count_binding) ... ok +test_e3_invented_codes_and_missing_load_code (__main__.S3a.test_e3_invented_codes_and_missing_load_code) ... ok +test_e3_valid_R_and_O_records (__main__.S3a.test_e3_valid_R_and_O_records) ... ok +test_envelope_duplicates_not_defect (__main__.S3a.test_envelope_duplicates_not_defect) ... ok +test_event_count_defect_not_silently_accepted (__main__.S3a.test_event_count_defect_not_silently_accepted) ... ok +test_exact_phase_keys (__main__.S3a.test_exact_phase_keys) ... ok +test_interval_gap_rejected (__main__.S3a.test_interval_gap_rejected) ... ok +test_invalid_input_accepted_is_not_PASS (__main__.S3a.test_invalid_input_accepted_is_not_PASS) ... ok +test_load_payload_and_pause_outcome (__main__.S3a.test_load_payload_and_pause_outcome) ... ok +test_operation_moved_outside_scenario_rejected (__main__.S3a.test_operation_moved_outside_scenario_rejected) ... ok +test_package_fixed_mutations_and_hashes (__main__.S3a.test_package_fixed_mutations_and_hashes) ... ok +test_probe_connection_required (__main__.S3a.test_probe_connection_required) ... ok +test_rejection_mutation_retained_as_defect (__main__.S3a.test_rejection_mutation_retained_as_defect) ... ok +test_save_refusal_makes_load_NA (__main__.S3a.test_save_refusal_makes_load_NA) ... ok +test_scenario_mutation_static_boundary (__main__.S3a.test_scenario_mutation_static_boundary) ... ok +test_signals_all_minutes_and_order (__main__.S3a.test_signals_all_minutes_and_order) ... ok +test_E5_cached_digest_defect_is_comparable (__main__.S3b.test_E5_cached_digest_defect_is_comparable) ... ok +test_NA_not_PASS (__main__.S3b.test_NA_not_PASS) ... ok +test_aliasing_cannot_be_PASS (__main__.S3b.test_aliasing_cannot_be_PASS) ... ok +test_aliasing_missing_record (__main__.S3b.test_aliasing_missing_record) ... ok +test_all_paths_and_ownership_R_O (__main__.S3b.test_all_paths_and_ownership_R_O) ... ok +test_digest_defect_other_checkpoint_still_rejected (__main__.S3b.test_digest_defect_other_checkpoint_still_rejected) ... ok +test_digest_materialization_required (__main__.S3b.test_digest_materialization_required) ... ok +test_empty_registry_not_NA (__main__.S3b.test_empty_registry_not_NA) ... ok +test_event_count_mismatch (__main__.S3b.test_event_count_mismatch) ... ok +test_facts_normalization_is_reversible (__main__.S3b.test_facts_normalization_is_reversible) ... ok +test_first_placeable_choice (__main__.S3b.test_first_placeable_choice) ... ok +test_interval_gap (__main__.S3b.test_interval_gap) ... ok +test_joined_s3b_self_comparison (__main__.S3b.test_joined_s3b_self_comparison) ... ok +test_load_X_not_digest_only (__main__.S3b.test_load_X_not_digest_only) ... ok +test_load_extra_event (__main__.S3b.test_load_extra_event) ... ok +test_missing_path_and_combination (__main__.S3b.test_missing_path_and_combination) ... ok +test_missing_preview_observation (__main__.S3b.test_missing_preview_observation) ... ok +test_missing_trial (__main__.S3b.test_missing_trial) ... ok +test_nested_mutation_required (__main__.S3b.test_nested_mutation_required) ... ok +test_no_staleness_assertion_for_non_tick (__main__.S3b.test_no_staleness_assertion_for_non_tick) ... ok +test_ownership_fact_dictionary_order_fallback (__main__.S3b.test_ownership_fact_dictionary_order_fallback) ... ok +test_path_order (__main__.S3b.test_path_order) ... ok +test_restore_extra_event (__main__.S3b.test_restore_extra_event) ... ok +test_signal_facts_cannot_be_dropped (__main__.S3b.test_signal_facts_cannot_be_dropped) ... ok +test_sort_rule_rejected (__main__.S3b.test_sort_rule_rejected) ... ok +test_static_handler_and_outside_mutations (__main__.S3b.test_static_handler_and_outside_mutations) ... ok +test_unpreviewed_choice (__main__.S3b.test_unpreviewed_choice) ... ok +test_wrong_registry_in_either_role (__main__.S3b.test_wrong_registry_in_either_role) ... ok +test_checkout_temp_destination_rejected (__main__.S4Bundle.test_checkout_temp_destination_rejected) ... ok +test_existing_output_never_overwritten (__main__.S4Bundle.test_existing_output_never_overwritten) ... ok +test_import_closure_rejections (__main__.S4Bundle.test_import_closure_rejections) ... ok +test_missing_bundle_manifest_seal_and_changed_bytes (__main__.S4Bundle.test_missing_bundle_manifest_seal_and_changed_bytes) ... ok +test_missing_private_evidence_and_extra_rejected (__main__.S4Bundle.test_missing_private_evidence_and_extra_rejected) ... ok +test_missing_profile_not_export_success (__main__.S4Bundle.test_missing_profile_not_export_success) ... ok +test_phase_role_pid_audio_and_guard_rejected (__main__.S4Bundle.test_phase_role_pid_audio_and_guard_rejected) ... ok +test_rebound_lifecycle_and_scenario_contradictions (__main__.S4Bundle.test_rebound_lifecycle_and_scenario_contradictions) ... ok +test_seal_normal_and_changes_not_native_proof (__main__.S4Bundle.test_seal_normal_and_changes_not_native_proof) ... ok +test_synthetic_phase_all_real_checkers_not_native_proof (__main__.S4Bundle.test_synthetic_phase_all_real_checkers_not_native_proof) ... ok +test_copied_manifest_root_and_destination_count_rejected (__main__.S4NativeBundleLogic.test_copied_manifest_root_and_destination_count_rejected) ... ok +test_failure_keeps_raw_and_no_bundle_without_starting_engine (__main__.S4NativeBundleLogic.test_failure_keeps_raw_and_no_bundle_without_starting_engine) ... ok +test_gate_none_success_not_boolean (__main__.S4NativeBundleLogic.test_gate_none_success_not_boolean) ... ok +test_receipt_and_source_rejection_matrix (__main__.S4NativeBundleLogic.test_receipt_and_source_rejection_matrix) ... ok +test_synthetic_full_bundle_positive_not_native_evidence (__main__.S4NativeBundleLogic.test_synthetic_full_bundle_positive_not_native_evidence) ... ok +test_check_accepts_true (__main__.S4ProbeAdmission.test_check_accepts_true) ... ok +test_check_rejects_false_all_errors (__main__.S4ProbeAdmission.test_check_rejects_false_all_errors) ... ok +test_run_admission_accepts_true_mock_launch_only (__main__.S4ProbeAdmission.test_run_admission_accepts_true_mock_launch_only) ... ok +test_run_admission_rejects_false_without_engine (__main__.S4ProbeAdmission.test_run_admission_rejects_false_without_engine) ... ok +test_nine_original_destinations_required (__main__.S4RemainingBindings.test_nine_original_destinations_required) ... ok +test_nonzero_determinism_rejected_after_real_join (__main__.S4RemainingBindings.test_nonzero_determinism_rejected_after_real_join) ... ok +test_owned_lifecycle_exit_diagnostic_and_profile_rejections (__main__.S4RemainingBindings.test_owned_lifecycle_exit_diagnostic_and_profile_rejections) ... ok +test_verifier_accepts_true_recomputes_raw (__main__.S4RemainingBindings.test_verifier_accepts_true_recomputes_raw) ... ok +test_verifier_rejects_false_with_every_error (__main__.S4RemainingBindings.test_verifier_rejects_false_with_every_error) ... ok +test_cached_verdict_not_trusted (__main__.S4StoredResultBindings.test_cached_verdict_not_trusted) ... ok +test_missing_sidecar_rejected_after_seal (__main__.S4StoredResultBindings.test_missing_sidecar_rejected_after_seal) ... ok +test_raw_joined_substitution_rejected_after_seal (__main__.S4StoredResultBindings.test_raw_joined_substitution_rejected_after_seal) ... ok +test_blob_transport_is_verified_and_bound (__main__.S5.test_blob_transport_is_verified_and_bound) ... ok +test_blob_trees_get_the_same_full_validation_as_inline (__main__.S5.test_blob_trees_get_the_same_full_validation_as_inline) ... ok +test_compare_and_digest_equal_s1_reference (__main__.S5.test_compare_and_digest_equal_s1_reference) ... ok +test_event_stream_replacement_is_existing_defect_not_pass (__main__.S5.test_event_stream_replacement_is_existing_defect_not_pass) ... ok +test_every_checkpoint_full_tree_verified_like_inline (__main__.S5.test_every_checkpoint_full_tree_verified_like_inline) +S5 drops the diff chain: each checkpoint carries a complete tree, verified alone. ... ok +test_fast_normalization_equals_original (__main__.S5.test_fast_normalization_equals_original) ... ok +test_labelled_harness_digest_falls_back_to_dictionary_order_only (__main__.S5.test_labelled_harness_digest_falls_back_to_dictionary_order_only) ... ok +test_lifecycle_binds_replacements_guard_text_and_blobs (__main__.S5.test_lifecycle_binds_replacements_guard_text_and_blobs) ... ok +test_manifest_numbers_keep_their_type (__main__.S5.test_manifest_numbers_keep_their_type) ... ok +test_memo_scope_same_results_and_restores_gc (__main__.S5.test_memo_scope_same_results_and_restores_gc) ... ok +test_path_copy_builders_equal_deepcopy_reference (__main__.S5.test_path_copy_builders_equal_deepcopy_reference) ... ok +test_probe_static_full_tree_blob_and_stream_requirements (__main__.S5.test_probe_static_full_tree_blob_and_stream_requirements) ... ok +test_publish_pairs_bound_to_source_causes (__main__.S5.test_publish_pairs_bound_to_source_causes) ... ok +test_signed_instance_ids_raw_kept_and_excluded (__main__.S5.test_signed_instance_ids_raw_kept_and_excluded) ... ok +test_validate_tree_equals_s1_reference_on_mutations (__main__.S5.test_validate_tree_equals_s1_reference_on_mutations) ... ok +test_fixed_scenario_paths (__main__.SourcesAndMetrics.test_fixed_scenario_paths) ... ok +test_metric_ranges (__main__.SourcesAndMetrics.test_metric_ranges) ... ok +test_source_closure_synthetic_registered_map (__main__.SourcesAndMetrics.test_source_closure_synthetic_registered_map) ... ok +test_source_pin_is_not_caller_controlled (__main__.SourcesAndMetrics.test_source_pin_is_not_caller_controlled) ... ok +test_array_order_and_all_differences (__main__.TypedTrees.test_array_order_and_all_differences) ... ok +test_components_and_sha (__main__.TypedTrees.test_components_and_sha) ... ok +test_deep_state_not_truncated (__main__.TypedTrees.test_deep_state_not_truncated) ... ok +test_duplicate_textual_keys_rejected (__main__.TypedTrees.test_duplicate_textual_keys_rejected) ... ok +test_exact_and_types (__main__.TypedTrees.test_exact_and_types) ... ok +test_nested_order_all_paths (__main__.TypedTrees.test_nested_order_all_paths) ... ok +test_nonstring_keys_keep_types_and_values (__main__.TypedTrees.test_nonstring_keys_keep_types_and_values) ... ok +test_unsupported_and_malformed (__main__.TypedTrees.test_unsupported_and_malformed) ... ok + +---------------------------------------------------------------------- +Ran 161 tests in 121.627s + +OK diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/check_eq.py b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/check_eq.py index cbf535d..6961ded 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/check_eq.py +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/check_eq.py @@ -6,6 +6,7 @@ copies using S1's sole F1-F3 implementation; it does not manufacture Godot proof import base64 import ast import copy +import gc import hashlib import json from pathlib import Path @@ -18,7 +19,7 @@ import compare_versions as eq def check_python_imports(text): """Closed EQ/stdlib import screen; dynamic file loading is separately pinned by run_eq.""" - allowed = {'argparse', 'ast', 'base64', 'copy', 'hashlib', 'importlib', 'json', 'math', + allowed = {'argparse', 'ast', 'base64', 'collections', 'copy', 'gc', 'gzip', 'hashlib', 'importlib', 'json', 'math', 'os', 'pathlib', 're', 'shutil', 'struct', 'subprocess', 'sys', 'tempfile', 'unittest', 'uuid', 'check_eq', 'compare_versions', 'run_eq', 'verify_eq'} tree = ast.parse(text) @@ -54,6 +55,7 @@ def integer(value): def fields(tree): + tree = eq.materialize(tree) eq.require(tree[0] == 27, 'dictionary required') result = {} for key, value in tree[1]: @@ -62,7 +64,21 @@ def fields(tree): return result +_COUNTS = {} + + def counts(tree): + """Domain-event counter and published IDs; memoized by tree SHA (content-addressed).""" + known = eq.known_sha(tree) + if known is not None and known in _COUNTS: + return _COUNTS[known] + result = _counts(tree) + if known is not None: + _COUNTS[known] = result + return result + + +def _counts(tree): runtime = fields(fields(fields(tree)['systems'])['runtime']) counters = fields(fields(runtime['id_generator'])['counters']) # Product get_counter has an explicit zero default for an absent prefix. @@ -83,38 +99,96 @@ def normalized_digest(tree): Key nodes remain exact. Only Dictionary enumeration order is canonicalized, matching S1 fallback; floats, metadata and Array order remain untouched. """ - def canonical(node): - result = copy.deepcopy(node) - if node[0] == 27: - names = [eq._key_text(k) for k, _ in node[1]] - eq.require(len(set(names)) == len(names), 'digest textual key collision') - result[1] = [[copy.deepcopy(k), canonical(v)] for k, v in sorted(node[1], key=lambda p: eq._key_text(p[0]))] - elif node[0] == 28 or 5 <= node[0] <= 20 or 30 <= node[0] <= 38: - result[1] = [canonical(v) for v in node[1]] - return result - eq.validate_tree(tree) - return eq.tree_sha(canonical(tree)) + return eq.canonical_digest(tree) + + +def edit_at(tree, names, change): + """Copy of tree with the node at the textual path replaced by change(node). + + Only the dictionaries on the path are copied; all other nodes are shared, so the + result has the same JSON as deepcopy-then-mutate. Inputs are never modified.""" + tree = eq.materialize(tree) + if not names: + return change(tree) + data = fields(tree) + eq.require(names[0] in data, 'missing path: ' + names[0]) + pairs = [[k, edit_at(v, names[1:], change)] if k[0] in (4, 21) and k[1] == names[0] else [k, v] for k, v in tree[1]] + return [27, pairs, tree[2]] + + +def describe(tree): + """Large trees in derived results are recorded by SHA; raw blobs keep the content.""" + known = eq.known_sha(tree) + if known is None: + return tree + normalized = isinstance(tree, eq.TreeRef) and tree.base is not None + source = tree.base.sha if normalized else known + return {'typed_tree_sha': known, 'source_tree_sha': source, 'normalized': normalized} + + +class memo_scope: + """Within one verification call, identical check inputs are checked once (S5). + + The keys are SHA-256 of the exact JSON inputs; blobs are content-addressed, so equal + inputs give equal results. Only successful results are reused; outside a scope every + call recomputes.""" + def __enter__(self): + global _MEMO + self.previous, _MEMO = _MEMO, ({} if _MEMO is None else _MEMO) + # Typed trees are acyclic lists; cyclic GC passes over millions of their nodes + # dominated the R time (E45 123 s -> 18 s). Results do not depend on GC. + self.collecting = gc.isenabled() + gc.disable() + return self + + def __exit__(self, *_): + global _MEMO + _MEMO = self.previous + if self.collecting: + gc.enable() + return False + + +_MEMO = None + + +def _memoized(name, function, *args): + if _MEMO is None: + return function(*args) + key = (name, sha(eq.json_bytes(list(args)))) + if key not in _MEMO: + _MEMO[key] = function(*args) + return _MEMO[key] def join_report(raw): """Return (joined report, reversible normalization evidence), never edit raw.""" + return _memoized('join_report', _join_report, raw) + + +def _join_report(raw): joined = copy.deepcopy(raw) proofs = [] trees = eq.reconstruct_checkpoints(raw['checkpoints']) for cp, (s, latest) in zip(joined['checkpoints'], trees): row = {} - for name, tree in (('S', s), ('latest', latest)): + for name, tree in (('latest', latest), ('S', s)): normalized, side = eq.normalize_tree(tree, raw['profile_root']) restored = eq.restore_tree(normalized, side, raw['profile_root']) eq.require(eq.tree_sha(restored) == eq.tree_sha(tree), 'normalization restore SHA') - row[name] = {'normalized_tree_sha': eq.tree_sha(normalized), 'normalized_digest': normalized_digest(normalized), 'sidecar': side, + # The harness digest is the latest's (the only one compared); S records it only + # when S is the same normalized tree, otherwise null. + digest = (eq.harness_digest(normalized) if name == 'latest' else + row['latest']['normalized_digest'] if eq.tree_sha(normalized) == row['latest']['normalized_tree_sha'] else None) + row[name] = {'normalized_tree_sha': eq.tree_sha(normalized), 'normalized_digest': digest, 'sidecar': side, 'restored_tree_sha': eq.tree_sha(restored)} + row = {'S': row['S'], 'latest': row['latest']} expected = row['latest']['normalized_digest'] eq.require(cp['harness_normalized_digest'] in (None, expected), 'forged normalized digest') cp['harness_normalized_digest'] = expected proofs.append(row) for i, scenario in enumerate(raw.get('scenarios', [])): - derived, scenario_proofs = join_report({'profile_root': raw['profile_root'], 'checkpoints': scenario['checkpoints']}) + derived, scenario_proofs = _join_report({'profile_root': raw['profile_root'], 'checkpoints': scenario['checkpoints']}) joined['scenarios'][i]['checkpoints'] = derived['checkpoints'] proofs.append({'scenario': scenario['id'], 'checkpoints': scenario_proofs}) if scenario['id'].startswith(('E4/', 'E5/')): @@ -124,6 +198,10 @@ def join_report(raw): def check_measurement(raw, measurement): + return _memoized('check_measurement', _check_measurement, raw, measurement) + + +def _check_measurement(raw, measurement): eq.require(type(measurement) is dict, 'measurement connection inventory missing') eq.require(set(measurement) == {'probe_object', 'connections', 'start_minute'}, 'measurement inventory fields') eq.require(measurement['start_minute'] == raw['checkpoints'][0]['minute'], 'inventory B1 minute') @@ -136,9 +214,16 @@ def check_measurement(raw, measurement): eq.require(set(row) == {'object', 'method', 'flags'}, 'connection fields') eq.require(sum(r['object'] == probe and r['method'] == method for r in rows) == 1, 'missing/duplicate probe connection: ' + signal) - expected = [{'signal': signal, 'minute': cp['minute']} for cp in raw['checkpoints'][1:] - for signal in ('snapshot_published', 'state_updated')] - eq.require(eq.exact(raw['signal_order'], expected), 'exact measured signal pairs/checkpoint minutes required') + # S5: one tick-end publish per measured minute, plus one publish after each run of + # commands completed by a paused submit (R minute 648: 50 commands, 51 pairs). The + # S3a rule of exactly one pair per minute was a harness assumption, not product behavior. + events = event_numbers([eq._transport(row['transport'], None) for row in raw['events']]) + trees = eq.reconstruct_checkpoints(raw['checkpoints']) + command, other = check_publishes(raw['signal_order'], events, raw['event_start']['counter'], raw['event_end']['counter'], + next_command_id(trees[0][0]), next_command_id(trees[-1][0])) + minutes = [cp['minute'] for cp in raw['checkpoints'][1:]] + eq.require(sorted(m for m, _ in other) == minutes and all(m in minutes for m, _ in command), + 'exact measured signal pairs/checkpoint minutes required') def check_report(raw, measurement=None, e3_evidence=None, b1_record=None, e45_evidence=None): @@ -173,7 +258,8 @@ def check_report(raw, measurement=None, e3_evidence=None, b1_record=None, e45_ev eq.require(type(c['_mvp_manifest_cache_generation']) is int, 'cache generation') eq.require(c['catalog_is_current'] is True, 'unfilled checkpoint cache') ids = [c['catalog_instance_id'], c['current_catalog_instance_id']] - eq.require(all(type(v) is str and re.fullmatch('[1-9][0-9]*', v) for v in ids), 'cache instance IDs') + # Godot instance IDs are signed 64-bit; RefCounted IDs are negative. Raw values are kept. + eq.require(all(type(v) is str and re.fullmatch('-?[1-9][0-9]*', v) for v in ids), 'cache instance IDs') eq.require(ids[0] == ids[1], 'cache identity contradiction') eq.validate_tree([29, c['_mvp_manifest_cache_bytes']]) trees = eq.reconstruct_checkpoints(cps) @@ -203,7 +289,7 @@ def check_report(raw, measurement=None, e3_evidence=None, b1_record=None, e45_ev eq.require(set(end_ids) == set(begin_ids) | set(event_ids), 'missing/extra E2 events') eq.require(end['counter'] - begin['counter'] == len(event_ids), 'event counter delta') for row in raw['signal_order']: - eq.require(set(row) == {'signal', 'minute'} and row['signal'] in ('snapshot_published', 'state_updated'), 'signal record') + eq.require(set(row) == {'signal', 'minute', 'event_counter', 'command_counter'} and row['signal'] in ('snapshot_published', 'state_updated'), 'signal record') eq.require(type(row['minute']) is int and start_minute <= row['minute'] <= start_minute+30, 'signal minute') check_measurement(raw, measurement) out.update(ok=True, normalization=proofs, comparison=compared) @@ -212,6 +298,16 @@ def check_report(raw, measurement=None, e3_evidence=None, b1_record=None, e45_ev return out +def raw_layer_sha(value): + """S/K/C bytes: an S5 blob reference (verified on load) or legacy base64 text.""" + if type(value) is dict: + eq.require(set(value) == {'blob'}, 'raw layer blob fields') + eq.blob_bytes(value['blob']) + return value['blob'] + eq.validate_tree([29, value]) + return sha(base64.b64decode(value, validate=True)) + + def check_observation(cp, evidence): """Bind retained full bytes to report SHA, not merely asserted equality.""" eq.require(set(evidence) == {'before', 'after'}, 'observation evidence fields') @@ -220,8 +316,7 @@ def check_observation(cp, evidence): eq.require(set(row) == {'sha', 'S', 'K', 'C', 'kernel', 'cache'}, 'raw layer fields') eq.require(eq.exact(row['kernel'], cp['K']) and eq.exact(row['cache'], cp['C']), 'raw layer value contradiction') for layer in ('S', 'K', 'C'): - eq.validate_tree([29, row[layer]]) - actual = sha(base64.b64decode(row[layer], validate=True)) + actual = raw_layer_sha(row[layer]) eq.require(actual == row['sha'][layer] == cp['observation'][side][layer], 'raw layer SHA mismatch') eq.require(all(evidence['before'][k] == evidence['after'][k] for k in ('S', 'K', 'C')), 'raw observation bytes differ') return True @@ -245,15 +340,22 @@ def strict_json(text): def check_lifecycle(raw, lifecycle, guard): """S2 startup proof; S4 must supply the separately SHA-bound guard receipt.""" - eq.require(lifecycle['stage'] in ('S2', 'S3a', 'S3b') and lifecycle['errors'] == [], 'probe errors/stage') - eq.require(lifecycle['stop_reason'] == {'S2': 'S2_complete_S3_pending', 'S3a': 'S3a_complete_S3b_pending', 'S3b': 'S3b_complete_S4_pending'}[lifecycle['stage']], 'probe did not finish stage') - if lifecycle['stage'] in ('S3a', 'S3b'): + eq.require(lifecycle['stage'] in ('S2', 'S3a', 'S3b', 'S5') and lifecycle['errors'] == [], 'probe errors/stage') + eq.require(lifecycle['stop_reason'] == {'S2': 'S2_complete_S3_pending', 'S3a': 'S3a_complete_S3b_pending', 'S3b': 'S3b_complete_S4_pending', 'S5': 'S5_complete'}[lifecycle['stage']], 'probe did not finish stage') + if lifecycle['stage'] in ('S3a', 'S3b', 'S5'): check_measurement(raw, lifecycle['measurement']) check_e3(dict(raw, scenarios=raw['scenarios'][:18]), lifecycle['e3'], lifecycle['e3_b1']) - if lifecycle['stage'] == 'S3b': + if lifecycle['stage'] in ('S3b', 'S5'): check_e45(raw, lifecycle['e45'], lifecycle['e3'][-1]['end']) + if lifecycle['stage'] == 'S5': + eq.require(eq.exact(lifecycle['event_stream_replacements'], stream_facts(lifecycle['e3'], lifecycle['e45'])), + 'event stream replacement record differs') binding = lifecycle['guard'] - eq.require(guard['verified'] is True and eq.exact(binding['receipt'], guard), 'independent guard differs') + # The probe's parsed receipt has float numbers (Godot JSON); bind its exact text instead. + receipt = strict_json(binding['receipt_text']) if 'receipt_text' in binding else binding['receipt'] + eq.require(guard['verified'] is True and eq.exact(receipt, guard), 'independent guard differs') + if 'receipt_text' in binding: + eq.require(sha(binding['receipt_text'].encode('utf-8')) == binding['sha256'], 'guard receipt text/SHA differs') root = eq._profile(raw['profile_root']) eq.require(root == binding['live_root'] == guard['actual_user_data_dir'], 'live/guard profile contradiction') eq.require(hex_sha(binding['sha256']), 'guard SHA missing') @@ -264,8 +366,7 @@ def check_lifecycle(raw, lifecycle, guard): row = lifecycle[label] eq.require(row['kernel']['paused'] is True and row['kernel']['absolute_minute'] == minute, 'lifecycle minute: '+label) for layer in ('S', 'K', 'C'): - eq.validate_tree([29, row[layer]]) - eq.require(sha(base64.b64decode(row[layer], validate=True)) == row['sha'][layer], 'lifecycle raw SHA') + eq.require(raw_layer_sha(row[layer]) == row['sha'][layer], 'lifecycle raw SHA') for label in ('before_main', 'after_main', 'frame1', 'frame2'): eq.require(type(lifecycle[label]) is dict and lifecycle[label]['kernel']['paused'] is True, 'startup frame evidence') ops = lifecycle['ops'] @@ -328,10 +429,14 @@ def check_probe(text): if '.advance_minutes(' in clean and not re.search(r'\.advance_minutes\(1\)', clean): errors.append('only one-minute stepping allowed') # A digest alone, stub proof, or truncated checkpoint producer is not admitted. required = { - 'transport': ('var_to_bytes(value)', 'var_to_bytes(decode(tree))', 'raw == rebuilt', 'encode(value)', 'hashed(json_text(tree).to_utf8_buffer())'), - 'checkpoint': ('layers()', 'transport(runtime.create_snapshot())', 'transport(latest_value)', 'before.s_bytes == after.s_bytes', 'before.k_bytes == after.k_bytes', 'before.c_bytes == after.c_bytes', 'diff_record(', 'write_evidence('), + 'transport': ('var_to_bytes(value)', 'var_to_bytes(decode(tree))', 'raw == rebuilt', 'encode(value)', 'json_text(tree).to_utf8_buffer()', '"tree_sha": hashed(text)', 'store_blob(text)'), + 'store_blob': ('hashed(bytes)', 'COMPRESSION_GZIP', 'decompress_dynamic(', 'refuse blob overwrite', 'blob_index[digest]'), + 'checkpoint': ('layers()', 'runtime.create_snapshot()', 'transport(snapshot_value)', 'transport(latest_value)', 'before.s_bytes == after.s_bytes', 'before.k_bytes == after.k_bytes', 'before.c_bytes == after.c_bytes', 'write_evidence('), 'bind_profile': ('ProjectSettings.globalize_path("user://").simplify_path()', 'receipt.get("actual_user_data_dir")', 'actual == live_root'), - 'observe_event': ('event.to_dictionary()', 'transport(value)', 'typeof(event.event_id)', 'typed_info(event.payload)', 'report.events.append('), + 'observe_event': ('event.to_dictionary()', 'transport(value)', 'typeof(event.event_id)', 'typed_info(event.payload)', 'report.events.append(', + 'known_event_ids[str(event.event_id)] = true'), + 'follow_event_stream': ('runtime.domain_events', 'current.recent_events()', 'known_event_ids.has(', 'observe_event(event)', + 'current.subscribe(&"*", &"p28_eq_observer", observe_event)', 'event_stream_replacements.append('), 'begin': ('runtime.domain_events.subscribe(&"*"', 'report.event_start = event_counts()', 'await step()', 'checkpoint()'), 'finish': ('root.close_requested.emit()', 'runtime.domain_events.unsubscribe(', 'write_evidence("events.json"', 'write_evidence("lifecycle.json"'), } @@ -354,6 +459,10 @@ def check_probe(text): body = '\n'.join(functions.get(name, [])) for snippet in snippets: if snippet not in body: errors.append('missing E3 boundary/call: '+name+': '+snippet) + # S5: a successful restore replaces the product event stream; every restore/load is followed. + if ('\n'.join(functions.get('run_e3', [])).count('follow_event_stream()') != 1 or + '\n'.join(functions.get('run_e4', [])).count('follow_event_stream()') != 2): + errors.append('event stream replacement not followed after restore/load') if code.count('run_e3()') != 2 or code.count('e3_prepare_package(') != 2: errors.append('unexpected scenario dispatch') scenario_body = '\n'.join(functions.get('run_e3', [])) @@ -396,42 +505,50 @@ def node_at(tree, *names): def e3_expected_input(b1, kind): - value = copy.deepcopy(b1) + value = eq.materialize(b1) if kind == 'missing_key': - value[1] = [pair for pair in value[1] if pair[0][1] != 'clock'] + value = [value[0], [pair for pair in value[1] if pair[0][1] != 'clock'], value[2]] elif kind in ('wrong_type', 'out_of_range'): - node_at(value, 'clock', 'absolute_minute' if kind == 'wrong_type' else 'speed')[:] = ( - [4, 'x'] if kind == 'wrong_type' else [2, 9]) + value = edit_at(value, ['clock', 'absolute_minute' if kind == 'wrong_type' else 'speed'], + lambda node: [4, 'x'] if kind == 'wrong_type' else [2, 9]) elif kind in ('duplicate_published_ids', 'duplicate_facility'): - nodes = (node_at(value, 'systems', 'runtime', 'domain_events', 'published_ids') if kind == 'duplicate_published_ids' - else node_at(value, 'systems', 'runtime', 'facilities', 'instances')) - if nodes[1]: - nodes[1].append(copy.deepcopy(nodes[1][0])) - else: + names = (['systems', 'runtime', 'domain_events', 'published_ids'] if kind == 'duplicate_published_ids' + else ['systems', 'runtime', 'facilities', 'instances']) + def duplicate(nodes): + if nodes[1]: + return [nodes[0], nodes[1] + [copy.deepcopy(nodes[1][0])]] + nodes[2:] eq.require(kind == 'duplicate_facility', 'no B1 published ID to duplicate') + return nodes + value = edit_at(value, names, duplicate) return value def e3_x(before, event): - value = copy.deepcopy(before) - counter = node_at(value, 'systems', 'runtime', 'id_generator', 'counters', 'domain_event') - counter[1] += 1 + value = edit_at(before, ['systems', 'runtime', 'id_generator', 'counters', 'domain_event'], + lambda counter: [counter[0], counter[1] + 1] + counter[2:]) domain = node_at(value, 'systems', 'runtime', 'domain_events') - ids = fields(domain)['published_ids'] - ids[1].append(copy.deepcopy(fields(event)['event_id'])) - ids[1].sort(key=lambda n: n[1]) + fields(domain)['published_ids'] + event_id = copy.deepcopy(fields(event)['event_id']) recent = fields(domain)['recent_events'] dropped = copy.deepcopy(recent[1][0]) if len(recent[1]) == 256 else None - recent[1].append(copy.deepcopy(event)) - if len(recent[1]) > 256: - del recent[1][0] + def published(ids): + children = ids[1] + [event_id] + children.sort(key=lambda n: n[1]) + return [ids[0], children] + ids[2:] + def appended(events): + children = events[1] + [copy.deepcopy(event)] + if len(children) > 256: + del children[0] + return [events[0], children] + events[2:] + value = edit_at(value, ['systems', 'runtime', 'domain_events', 'published_ids'], published) + value = edit_at(value, ['systems', 'runtime', 'domain_events', 'recent_events'], appended) return value, dropped def e3_raw_observation(row): cp = row['checkpoint'] check_observation(cp, row['raw']) - s = eq._transport(cp['S'], None) + s = eq._transport_ref(cp['S']) eq.require(cp['S']['raw_bytes_sha'] == row['raw']['before']['sha']['S'], 'E3 S transport/raw') for layer in ('K', 'C'): proof = row[layer+'_tree'] @@ -449,7 +566,8 @@ def e3_package_check(package, kind): out[name] = None continue eq.require(set(item) == {'bytes', 'sha256'}, 'package file fields') - content = base64.b64decode(item['bytes'], validate=True) + content = (eq.blob_bytes(item['bytes']['blob']) if type(item['bytes']) is dict and set(item['bytes']) == {'blob'} + else base64.b64decode(item['bytes'], validate=True)) eq.require(sha(content) == item['sha256'], 'package file SHA') out[name] = content return out @@ -482,6 +600,10 @@ def e3_package_check(package, kind): def check_e3(raw, evidence, b1_record): + return _memoized('check_e3', _check_e3, raw, evidence, b1_record) + + +def _check_e3(raw, evidence, b1_record): """Separate malformed evidence from observed existing-defect candidates. Returns all actual typed differences. Never promote NA or a defect to PASS. @@ -568,6 +690,11 @@ def check_e3(raw, evidence, b1_record): 'duplicate_published_ids': 'RESTORE_FAILED', 'duplicate_facility': 'RESTORE_FAILED', 'tampered_world': 'CHECKSUM_MISMATCH'}[kind] if result['code'] != expected_code and not (kind == 'out_of_range' and result['migration_attempted']): defects.append({'kind': 'unexpected_code', 'expected': expected_code, 'actual': result['code']}) + defects.extend(stream_defects(ev['event_stream'], events)) + # Only a successful restore publishes inside E3 (an accepted invalid input is a defect). + _, other = check_publishes(ev['signals'], event_numbers(events), counts(before)[0]['counter'], counts(after)[0]['counter'], + next_command_id(before), next_command_id(after)) + eq.require(len(other) == int(api in ('restore_snapshot', 'load_from_path') and result['ok'] is True), 'E3 publish missing/extra') expected_count = 1 if api == 'load_from_path' and invoked else 0 if len(events) != expected_count: defects.append({'kind': 'event_count', 'expected': expected_count, 'actual': len(events)}) @@ -592,6 +719,8 @@ def check_e3(raw, evidence, b1_record): if 'recovery_report' in data and fields(data['recovery_report']).get('restore_committed') != [1, 0]: defects.append({'kind': 'load_restore_committed', 'actual': data['recovery_report']}) expected_state, dropped = e3_x(before, events[0]) + if expected_state is not before and eq.known_sha(before) is not None: + expected_state = eq.adopt(expected_state) normalized_expected, expected_side = eq.normalize_tree(expected_state, raw['profile_root']) normalized_after, actual_side = eq.normalize_tree(after, raw['profile_root']) delta = eq.compare_trees(normalized_expected, normalized_after) @@ -600,7 +729,7 @@ def check_e3(raw, evidence, b1_record): left, right = ev['begin']['raw']['before'], ev['end']['raw']['after'] if left[layer] != right[layer]: defects.append({'kind': layer+'_changes', 'before': left[layer], 'after': right[layer], - 'comparison': eq.compare_trees(ev['begin'][layer+'_tree']['tree'], ev['end'][layer+'_tree']['tree'])}) + 'comparison': eq.compare_trees(eq._transport(ev['begin'][layer+'_tree'], None), eq._transport(ev['end'][layer+'_tree'], None))}) # Dictionary APIs require byte identity, not normalization/order fallback. if expected_count == 0 and ev['begin']['raw']['before']['S'] != ev['end']['raw']['after']['S']: defects.append({'kind': 'S_bytes_changed', 'before': ev['begin']['raw']['before']['S'], 'after': ev['end']['raw']['after']['S']}) @@ -608,7 +737,7 @@ def check_e3(raw, evidence, b1_record): 'expected': {'ok': False if applied else None, 'code': expected_code, 'error': expected_error, 'event_count': expected_count}, 'actual': copy.deepcopy(result), 'status': 'existing-defect-candidate' if defects else ('recorded' if applied else 'NA'), - 'defects': defects, 'dropped_recent_event': dropped, 'expected_state': expected_state, + 'defects': defects, 'dropped_recent_event': dropped, 'expected_state': describe(expected_state), 'state_comparison': delta, 'expected_sidecar': expected_side, 'actual_sidecar': actual_side}) results[-1]['exclusions'] = [{'reason': 'SaveService static diagnostic budget outside S/K/C; wall time', 'before': eq._transport(ev['save_budget_before'], None), 'after': eq._transport(ev['save_budget_after'], None)}, @@ -617,6 +746,121 @@ def check_e3(raw, evidence, b1_record): +COMMAND_EVENTS = ('COMMAND_COMPLETED', 'COMMAND_FAILED') + + +def event_numbers(trees): + """domain_event.%012d IDs -> (event_type, absolute_minute, command ID or None).""" + result = {} + for tree in trees: + data = fields(tree) + match = re.fullmatch('domain_event[.]([0-9]{12})', data['event_id'][1]) + eq.require(match is not None and int(match[1]) not in result, 'event ID/counter form') + command = None + if data['event_type'][1] in COMMAND_EVENTS: + command = fields(data['payload'])['command_id'] + eq.require(command[0] == 2 and integer(command[1]), 'command event ID') + command = command[1] + result[int(match[1])] = (data['event_type'][1], data['absolute_minute'][1], command) + return result + + +_COMMANDS = {} + + +def next_command_id(tree): + known = eq.known_sha(tree) + if known is not None and known in _COMMANDS: + return _COMMANDS[known] + value = node_at(tree, 'systems', 'runtime', 'next_command_id') + eq.require(value[0] == 2 and integer(value[1]), 'next_command_id') + if known is not None: + _COMMANDS[known] = value[1] + return value[1] + + +def _tree_facts(tree): + """Parse hook: small per-tree facts are taken while the tree is in memory.""" + for function in (counts, next_command_id): + try: + function(tree) + except (eq.EvidenceError, KeyError, TypeError, IndexError): + pass + + +eq.PARSE_HOOKS.append(_tree_facts) + + +def check_publishes(signals, events, start, end, commands_start, commands_end): + """Bind every recorded publish to its source cause; return (command pairs, other pairs). + + _publish_snapshot emits snapshot_published then state_updated with no event between + (simulation_runtime.gd:12616-12621). A submit while paused processes the due command at + once and publishes after the command events of that call (:510-512, :5768-5793). Every + other publish is a tick end (:1748) or a successful restore (:1473). The events between + two publishes belong to the later one; a publish whose last preceding event is a command + event of its minute is that call's command publish and covers the trailing command + events. Every command event must be covered. Each accepted submit advances + _next_command_id once (:508) and, being due at once while paused (:493), publishes once: + a command publish follows exactly one submit, whose command is in its batch; any other + publish follows none, and no submit may remain unpublished. The remaining publishes are + counted by the caller against the ticks and restores actually performed, so missing, + extra or reordered pairs fail. + """ + eq.require(type(signals) is list and len(signals) % 2 == 0, 'signal pair missing') + pairs = [] + for i in range(0, len(signals), 2): + first, second = signals[i], signals[i+1] + eq.require(type(first) is dict and set(first) == {'signal', 'minute', 'event_counter', 'command_counter'}, 'signal record') + eq.require(first['signal'] == 'snapshot_published' and all(type(first[k]) is int for k in ('minute', 'event_counter', 'command_counter')) + and eq.exact(second, dict(first, signal='state_updated')), 'signal pair order') + pairs.append((first['minute'], first['event_counter'], first['command_counter'])) + eq.require(pairs == sorted(pairs) and all([p[i] for p in pairs] == sorted(p[i] for p in pairs) for i in (1, 2)), 'signal order') + eq.require(all(start <= p[1] <= end and commands_start <= p[2] <= commands_end for p in pairs), 'signal outside event interval') + command, other, covered, previous, submitted = [], [], set(), start, commands_start + for minute, counter, commands in pairs: + last = events.get(counter) + if counter > previous and last is not None and last[0] in COMMAND_EVENTS and last[1] == minute: + batch = [] + number = counter + while number > previous and number in events and events[number][0] in COMMAND_EVENTS: + covered.add(number) + batch.append(events[number][2]) + number -= 1 + eq.require(commands == submitted + 1 and commands - 1 in batch, 'command publish missing') + command.append((minute, counter)) + else: + eq.require(commands == submitted, 'command publish missing') + other.append((minute, counter)) + previous, submitted = max(previous, counter), commands + eq.require(submitted == commands_end, 'command publish missing') + eq.require(covered == {n for n, row in events.items() if row[0] in COMMAND_EVENTS}, 'command publish missing') + return command, other + + +def stream_defects(fact, events): + """S5: a successful restore replaces the product's DomainEventStream without carrying its + subscribers. The probe recovers the undelivered events from the live stream and + subscribes again; the dropped subscription is an existing product fact, never a PASS.""" + eq.require(type(fact) is dict and type(fact.get('replaced')) is bool, 'event stream fact missing') + if not fact['replaced']: + eq.require(fact == {'replaced': False}, 'event stream fact fields') + return [] + eq.require(set(fact) == {'replaced', 'new_stream_subscribers_before', 'recovered_event_ids'}, 'event stream fact fields') + ids = [fields(event)['event_id'][1] for event in events] + recovered = fact['recovered_event_ids'] + eq.require(type(recovered) is list and len(set(recovered)) == len(recovered) and set(recovered) <= set(ids), 'recovered events not recorded') + eq.require('*/p28_eq_observer' not in fact['new_stream_subscribers_before'], 'subscription unexpectedly carried') + return [{'kind': 'event_stream_replaced_subscribers_not_carried', 'new_stream_subscribers_before': fact['new_stream_subscribers_before'], + 'undelivered_recovered_event_ids': recovered}] + + +def stream_facts(e3_evidence, e45_evidence): + """Every replacement, in scenario order, as the probe recorded it in lifecycle.""" + facts = [ev['event_stream'] for ev in e3_evidence] + [ev['detail']['event_stream'] for ev in e45_evidence if 'event_stream' in ev['detail']] + return [f for f in facts if f.get('replaced') is True] + + # S3b additions. Raw evidence is authoritative; outcome labels are derived. E4_PATHS = ('build_facility', 'tick', 'restore_snapshot', 'load_from_path', 'rejected_command') E5_TARGETS = ('create_snapshot', 'latest_snapshot', 'snapshot_published', 'state_updated') @@ -634,8 +878,8 @@ def join_facts(value, profile_root): normal, side = eq.normalize_tree(tree, profile_root) eq.require(eq.exact(eq.restore_tree(normal, side, profile_root), tree), 'fact normalization roundtrip') proofs.append({'path': path, 'sidecar': side, 'raw': item}) - return normal - return tree + return describe(normal) + return describe(tree) if isinstance(item, dict): return {k: walk(v, path+[k]) for k, v in item.items()} if isinstance(item, list): @@ -713,6 +957,10 @@ def check_command(detail): def check_e45(raw, evidence, previous): + return _memoized('check_e45', _check_e45, raw, evidence, previous) + + +def _check_e45(raw, evidence, previous): ids = ['E4/'+p for p in E4_PATHS] + ['E5/'+t+'/'+l+'/'+d for t in E5_TARGETS for l in ('dict', 'array') for d in ('outside_in', 'inside_out')] scenarios = raw['scenarios'][18:] @@ -730,8 +978,8 @@ def check_e45(raw, evidence, previous): common = {'save_budget_before', 'save_budget_after', 'signals'} specific = { 'build_facility': {'source', 'raw_ids', 'count', 'sorted_ids', 'sort_rule', 'bounds', 'cell_rule', 'trials', 'chosen', 'applicability', 'reason', 'observation_before', 'observation_after'}, - 'tick': set(), 'restore_snapshot': {'input', 'return'}, - 'load_from_path': {'input', 'path', 'save_return', 'package_before', 'package_after', 'return', 'latest_save_operation_result'}, + 'tick': set(), 'restore_snapshot': {'input', 'return', 'event_stream'}, + 'load_from_path': {'input', 'path', 'save_return', 'package_before', 'package_after', 'return', 'latest_save_operation_result', 'event_stream'}, 'rejected_command': {'submit', 'command_result'}, }[scenario['operation']] if scenario['operation'] == 'build_facility' and detail.get('chosen') is not None: specific |= {'submit', 'command_result'} @@ -748,20 +996,22 @@ def check_e45(raw, evidence, previous): and eq.exact(events, scenario['events']), 'E4/E5 event count binding') eq.require(result['applicability'] == detail.get('applicability', 'applied') and result['reason'] == detail.get('reason'), 'E4/E5 applicability binding') eq.require(eq.exact(result['facts'], e45_facts(detail)), 'E4/E5 facts binding/aliasing record missing') - for signal in ev['signals']: - eq.require(set(signal) == {'signal', 'minute'} and signal['signal'] in ('snapshot_published', 'state_updated') - and obs[0]['checkpoint']['minute'] <= signal['minute'] <= obs[-1]['checkpoint']['minute'], 'scenario signal interval') - eq.require(len(ev['signals']) % 2 == 0, 'scenario signal pair missing') - for i in range(0, len(ev['signals']), 2): - a, b = ev['signals'][i:i+2] - eq.require(a['signal'] == 'snapshot_published' and b == {'signal': 'state_updated', 'minute': a['minute']}, 'scenario signal order') + command, other = check_publishes(ev['signals'], event_numbers(events), counts(trees[0])[0]['counter'], counts(trees[-1])[0]['counter'], + next_command_id(trees[0]), next_command_id(trees[-1])) + eq.require(all(obs[0]['checkpoint']['minute'] <= m <= obs[-1]['checkpoint']['minute'] for m, _ in command + other), 'scenario signal interval') + op = scenario['operation'] + if scenario['id'].startswith('E4/'): + expected_other = int(detail.get('chosen') is not None) if op == 'build_facility' else 1 + else: + expected_other = 2 if op == 'outside_in' else 3 + eq.require(len(other) == expected_other, 'scenario tick/restore publish missing/extra') defects = [] differences = {} for name in ('S', 'latest'): a, b = [eq._transport(o['checkpoint'][name], None) for o in (obs[0], obs[-1])] differences[name] = eq.compare_trees(a, b) for name in ('K', 'C'): - differences[name] = eq.compare_trees(obs[0][name+'_tree']['tree'], obs[-1][name+'_tree']['tree']) + differences[name] = eq.compare_trees(eq._transport(obs[0][name+'_tree'], None), eq._transport(obs[-1][name+'_tree'], None)) op = scenario['operation'] begin_count, begin_ids = counts(trees[0]) end_count, end_ids = counts(trees[-1]) @@ -782,6 +1032,7 @@ def check_e45(raw, evidence, previous): eq.require(obs[-1]['checkpoint']['minute'] == obs[0]['checkpoint']['minute'] + int(tick), 'E4 tick count') if len(obs) == 3: eq.require(obs[1]['checkpoint']['minute'] == obs[0]['checkpoint']['minute'], 'submit checkpoint delayed') if op in ('restore_snapshot', 'load_from_path'): + defects.extend(stream_defects(detail['event_stream'], events)) p = eq._transport(detail['input'], None) eq.require(eq.exact(p, trees[0]), 'E4 input not current deep copy') actual = eq._transport(detail['return'], None) @@ -799,11 +1050,13 @@ def check_e45(raw, evidence, previous): package = {'save_return': detail['save_return'], 'original': detail['package_before'], 'modified': detail['package_before'], 'after_operation': detail['package_after']} e3_package_check(package, 'good') + if expected is not p and eq.known_sha(p) is not None: + expected = eq.adopt(expected) left, left_side = eq.normalize_tree(expected, raw['profile_root']) right, right_side = eq.normalize_tree(trees[-1], raw['profile_root']) delta = eq.compare_trees(left, right) eq.require(delta['equal'], 'E4 restore/load X(P,event) mismatch') - differences['expected_state'] = {'comparison': delta, 'expected': expected, 'sidecars': [left_side, right_side]} + differences['expected_state'] = {'comparison': delta, 'expected': describe(expected), 'sidecars': [left_side, right_side]} if op == 'rejected_command': command = check_command(detail) eq.require(command['code'] != [4, 'OK'], 'nonchanging command not rejected') @@ -823,13 +1076,14 @@ def check_e45(raw, evidence, previous): expected_held = eq._transport(baseline['S' if target == 'create_snapshot' else 'latest'], None) eq.require(eq.exact(held, expected_held), 'E5 returned target binding') if direction == 'outside_in': - expected = copy.deepcopy(held) if location == 'dict': - n = node_at(expected, 'systems', 'runtime', 'id_generator', 'counters') - eq.require('__p28_eq_probe' not in fields(n), 'E5 marker already present') - n[1].append([[4, '__p28_eq_probe'], [2, 1]]) + def marked(n): + eq.require('__p28_eq_probe' not in fields(n), 'E5 marker already present') + return [n[0], n[1] + [[[4, '__p28_eq_probe'], [2, 1]]]] + n[2:] + expected = edit_at(held, ['systems', 'runtime', 'id_generator', 'counters'], marked) else: - node_at(expected, 'systems', 'runtime', 'domain_events', 'published_ids')[1].append([4, '__p28_eq_probe']) + expected = edit_at(held, ['systems', 'runtime', 'domain_events', 'published_ids'], + lambda n: [n[0], n[1] + [[4, '__p28_eq_probe']]] + n[2:]) eq.require(eq.exact(expected, after_held), 'E5 fixed nested mutation absent/extra') for layer in ('S', 'latest'): delta = eq.compare_trees(eq._transport(obs[1]['checkpoint'][layer], None), eq._transport(obs[2]['checkpoint'][layer], None)) @@ -846,7 +1100,7 @@ def check_e45(raw, evidence, previous): differences['held'] = delta if not delta['equal']: defects.append({'kind': 'internal_mutation_of_returned_value', 'comparison': delta}) for layer in ('K', 'C'): - differences['ownership_'+layer] = eq.compare_trees(obs[1][layer+'_tree']['tree'], obs[2][layer+'_tree']['tree']) + differences['ownership_'+layer] = eq.compare_trees(eq._transport(obs[1][layer+'_tree'], None), eq._transport(obs[2][layer+'_tree'], None)) eq.require(len(events) == counts(trees[-1])[0]['counter']-counts(trees[0])[0]['counter'], 'E5 uncapped event counter delta') outcomes.append({'id': scenario['id'], 'status': 'existing-defect' if defects else ('NA' if result['applicability'] == 'NA' else 'recorded'), 'defects': defects, 'differences': differences, 'signals': ev['signals'], diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py index 656558c..982e092 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py @@ -4,9 +4,12 @@ Paths are lists of ['key', key_node] / ['index', integer] segments. Transport validation is distinct from product acceptance (see IMPLEMENTATION.md). """ import base64 +from collections import OrderedDict import copy +import gzip import hashlib import json +from pathlib import Path import re @@ -22,6 +25,142 @@ OPT_PATHS = frozenset(('autoload/simulation_runtime.gd', 'scripts/core/simulatio 'scripts/world/path_service.gd', 'scripts/core/command_queue.gd')) SOURCE_SHA = '651f703621c8ed06a724709f75d8bc05b1eef2988c3b3d5d3466096a3f759bf0' TOKEN = '{PRIVATE_USER_ROOT}/' +PERMITTED_EVENTS = ('systems', 'runtime', 'domain_events', 'recent_events') + + +# S5 content-addressed trees (EQ_S5_SCALE_PLAN). The probe writes each large tree's exact +# JSON text, and raw S/K/C bytes, once as evidence/blobs/.gz; records keep +# {"blob": sha}. A blob is accepted only when its uncompressed bytes hash to its name. +# Godot's JSON text of a tree equals json_bytes(tree) (checked on the R fixture), so the +# blob name is the tree SHA. Trees loaded from blobs are shared and never mutated. +BLOB_ROOTS = [] +_BLOB_BYTES = OrderedDict() +_BLOB_TREES = OrderedDict() +_NORMALIZED = {} +# SHAs of blob trees that passed the full validate_tree. A matching SHA proves only the bytes, +# never the types; nothing from a blob is trusted before it is in this set, and a failed blob +# is never added, so it fails again on every use. +_VALID_BLOBS = set() +BYTES_CACHE, TREE_CACHE = 12, 8 +# S5: while a phase is checked, its profile root is set here so that each blob tree's +# normalization facts are derived once, when the tree is first parsed (no second parse). +ACTIVE_PROFILES = [] +PARSE_HOOKS = [] + + +class BlobList(list): + """A typed tree parsed from a verified blob; `sha` is the SHA of its JSON text.""" + __slots__ = ('sha',) + + def __deepcopy__(self, memo): + return copy.deepcopy(list(self), memo) + + +class TreeRef: + """An unparsed tree known by SHA: a blob, or a normalized blob tree. + + Equal SHA means equal JSON text, hence an equal tree. Content is parsed only on demand. + """ + __slots__ = ('sha', 'base', 'replacement') + + def __init__(self, sha, base=None, replacement=None): + self.sha, self.base, self.replacement = sha, base, replacement + + def __deepcopy__(self, memo): + return self + + def tree(self): + if self.base is None: + return blob_tree(self.sha) + tree = self.base.tree() if isinstance(self.base, TreeRef) else self.base + return _replace_events(tree, self.replacement) if self.replacement is not None else tree + + +def add_blob_root(path): + path = Path(path) + if path not in BLOB_ROOTS: + BLOB_ROOTS.append(path) + + +def reset_blobs(): + BLOB_ROOTS.clear(); _BLOB_BYTES.clear(); _BLOB_TREES.clear(); _NORMALIZED.clear(); _VALID_BLOBS.clear() + + +def blob_bytes(sha): + require(type(sha) is str and re.fullmatch('[0-9a-f]{64}', sha), 'blob SHA') + if sha in _BLOB_BYTES: + _BLOB_BYTES.move_to_end(sha) + return _BLOB_BYTES[sha] + found = [root / (sha + '.gz') for root in BLOB_ROOTS if (root / (sha + '.gz')).is_file()] + require(found, 'missing blob: ' + sha) + require(not found[0].is_symlink(), 'blob symlink') + try: + data = gzip.decompress(found[0].read_bytes()) + except (OSError, EOFError, ValueError) as exc: + raise EvidenceError('invalid blob gzip: ' + sha) from exc + require(hashlib.sha256(data).hexdigest() == sha, 'blob SHA mismatch: ' + sha) + _BLOB_BYTES[sha] = data + while len(_BLOB_BYTES) > BYTES_CACHE: + _BLOB_BYTES.popitem(last=False) + return data + + +def _reject(*_): + raise EvidenceError('typed tree JSON may contain only arrays, integers, strings and null') + + +def blob_tree(sha): + if sha in _BLOB_TREES: + _BLOB_TREES.move_to_end(sha) + return _BLOB_TREES[sha] + try: + value = json.loads(blob_bytes(sha).decode('utf-8'), parse_float=_reject, parse_constant=_reject, + object_pairs_hook=_reject) + except (UnicodeDecodeError, json.JSONDecodeError) as exc: + raise EvidenceError('invalid blob tree JSON: ' + sha) from exc + validate_tree(value) + tree = BlobList(value) + tree.sha = sha + _VALID_BLOBS.add(sha) + _BLOB_TREES[sha] = tree + while len(_BLOB_TREES) > TREE_CACHE: + _BLOB_TREES.popitem(last=False) + for profile_root in ACTIVE_PROFILES: + key = (sha, json_bytes(profile_root)) + if key not in _NORMALIZED: + fast = _fast_normalize(tree, blob_bytes(sha).decode('utf-8'), profile_root) + if fast is not None: + _NORMALIZED[key] = fast + for hook in PARSE_HOOKS: + hook(tree) + return tree + + +def known_sha(tree): + """SHA of a validated blob tree (or of a normalization of one); None otherwise.""" + if isinstance(tree, BlobList): + return tree.sha + if isinstance(tree, TreeRef): + base = tree.base if tree.base is not None else tree + if isinstance(base, TreeRef) and base.sha not in _VALID_BLOBS: + blob_tree(base.sha) + return tree.sha + return None + + +def materialize(tree): + return tree.tree() if isinstance(tree, TreeRef) else tree + + +def same_tree(a, b): + """Exact typed-tree equality. Validated trees hold only lists, ints, strings and None, + so Python equality is JSON equality; equal SHAs are a shortcut, never a requirement.""" + if a is b: + return True + sa, sb = known_sha(a), known_sha(b) + if sa is not None and sa == sb: + return True + return materialize(a) == materialize(b) def require(ok, message): @@ -33,62 +172,138 @@ def json_bytes(value): return json.dumps(value, ensure_ascii=False, separators=(',', ':'), allow_nan=False).encode('utf-8') +def _copy_tree(value): + """Exact copy of nested lists (typed trees hold only lists, ints, strings and None).""" + return [_copy_tree(v) if isinstance(v, list) else v for v in value] if isinstance(value, list) else copy.deepcopy(value) + + def exact(a, b): + if a is b: + return True + if known_sha(a) is not None or known_sha(b) is not None: + for value in (a, b): + if known_sha(value) is None: + try: + validate_tree(value) + except EvidenceError: + return False + return same_tree(a, b) return json_bytes(a) == json_bytes(b) +_BAD_TYPES = frozenset((23, 24, 25, 26)) +_SIZES = {5: 2, 6: 2, 7: 4, 8: 4, 9: 3, 10: 3, 11: 6, 12: 4, 13: 4, 14: 4, 15: 4, 16: 6, 17: 9, 18: 12, 19: 16, 20: 4} +_INTEGER_COMPONENTS = frozenset((6, 8, 10, 13)) +_PACKED = {30: 2, 31: 2, 32: 3, 33: 3, 34: 4} +_PACKED_VECTORS = {35: 5, 36: 9, 37: 20, 38: 12} +_HEX16 = re.compile('[0-9a-f]{16}').fullmatch +_INT_MIN, _INT_MAX = -(2**63), 2**63 + + +def _leaf(x): + """The node checks for an INT/FLOAT/STRING component, exactly as when it is popped.""" + if type(x) is not list or not x or type(x[0]) is not int: + raise EvidenceError('invalid typed node') + t = x[0] + if t in _BAD_TYPES or not 0 <= t <= 38: + raise EvidenceError('unsupported Variant type') + if len(x) != (1 if t == 0 else 3 if t in (27, 28) else 2): + raise EvidenceError('node arity') + p = x[1] + if t == 2: + if type(p) is not int or not _INT_MIN <= p < _INT_MAX: + raise EvidenceError('integer payload') + elif t == 3: + if type(p) is not str or not _HEX16(p): + raise EvidenceError('float must be f64 LE hex') + elif type(p) is not str: + raise EvidenceError('string payload') + + def validate_tree(node): - """Validate all nodes; no application depth cutoff or value coercion.""" + """Validate all nodes; no application depth cutoff or value coercion. + + A blob tree is used only after this full validation (its SHA is then recorded). + S5: the S1 checks, messages and order are kept; components are checked in place in the + same (last-in, first-out) order in which the S1 stack popped them.""" + if known_sha(node) is not None: + return node pending = [node] + pop, extend = pending.pop, pending.extend while pending: - n = pending.pop() - require(type(n) is list and n and type(n[0]) is int, 'invalid typed node') + n = pop() + if type(n) is not list or not n or type(n[0]) is not int: + raise EvidenceError('invalid typed node') t = n[0] - require(t not in (23, 24, 25, 26) and 0 <= t <= 38, 'unsupported Variant type') - require(len(n) == (1 if t == 0 else 3 if t in (27, 28) else 2), 'node arity') + if t in _BAD_TYPES or not 0 <= t <= 38: + raise EvidenceError('unsupported Variant type') + if len(n) != (1 if t == 0 else 3 if t == 27 or t == 28 else 2): + raise EvidenceError('node arity') if t == 0: continue p = n[1] - if t in (1, 2): - require(type(p) is int and (p in (0, 1) if t == 1 else -(2**63) <= p < 2**63), 'integer payload') + if t == 2: + if type(p) is not int or not _INT_MIN <= p < _INT_MAX: + raise EvidenceError('integer payload') + elif t == 27: + if type(p) is not list: + raise EvidenceError('dictionary entries') + seen = set() + for pair in p: + if type(pair) is not list or len(pair) != 2: + raise EvidenceError('dictionary pair') + k = pair[0] + # Simple key nodes compare as (type, payload); validated ints are never bool. + key = (k[0], k[1]) if type(k) is list and len(k) == 2 and type(k[1]) in (str, int) else json_bytes(k) + if key in seen: + raise EvidenceError('duplicate dictionary key') + seen.add(key) + extend(pair) + _typed_info(n[2], dictionary=True) + elif t == 4 or t == 21 or t == 22: + if type(p) is not str: + raise EvidenceError('string payload') + elif t == 28: + if type(p) is not list: + raise EvidenceError('array elements') + _typed_info(n[2], dictionary=False) + extend(p) elif t == 3: - require(type(p) is str and re.fullmatch('[0-9a-f]{16}', p), 'float must be f64 LE hex') - elif t in (4, 21, 22): - require(type(p) is str, 'string payload') + if type(p) is not str or not _HEX16(p): + raise EvidenceError('float must be f64 LE hex') + elif t == 1: + if type(p) is not int or p not in (0, 1): + raise EvidenceError('integer payload') elif t == 29: - require(type(p) is str, 'byte array payload') + if type(p) is not str: + raise EvidenceError('byte array payload') try: require(base64.b64encode(base64.b64decode(p, validate=True)).decode() == p, 'noncanonical base64') except (ValueError, TypeError) as exc: raise EvidenceError('invalid base64') from exc - elif t == 27: - require(type(p) is list, 'dictionary entries') - seen = set() - for pair in p: - require(type(pair) is list and len(pair) == 2, 'dictionary pair') - key = json_bytes(pair[0]) - require(key not in seen, 'duplicate dictionary key') - seen.add(key) - pending.extend(pair) - _typed_info(n[2], dictionary=True) - elif t == 28: - require(type(p) is list, 'array elements') - _typed_info(n[2], dictionary=False) - pending.extend(p) else: - require(type(p) is list, 'component nodes') - sizes = {5: 2, 6: 2, 7: 4, 8: 4, 9: 3, 10: 3, 11: 6, - 12: 4, 13: 4, 14: 4, 15: 4, 16: 6, 17: 9, 18: 12, 19: 16, 20: 4} - if t in sizes: - require(len(p) == sizes[t], 'component count') - integer = t in (6, 8, 10, 13) - require(all(x and x[0] == (2 if integer else 3) for x in p), 'component type') - elif t in (30, 31, 32, 33, 34): - expected = {30: 2, 31: 2, 32: 3, 33: 3, 34: 4}[t] - require(all(x and x[0] == expected for x in p), 'packed element type') + if type(p) is not list: + raise EvidenceError('component nodes') + if t in _SIZES: + if len(p) != _SIZES[t]: + raise EvidenceError('component count') + expected = 2 if t in _INTEGER_COMPONENTS else 3 + if not all(x and x[0] == expected for x in p): + raise EvidenceError('component type') + elif t in _PACKED: + expected = _PACKED[t] + if not all(x and x[0] == expected for x in p): + raise EvidenceError('packed element type') else: - require(all(x and x[0] == {35: 5, 36: 9, 37: 20, 38: 12}[t] for x in p), 'packed vector type') - pending.extend(p) + expected = _PACKED_VECTORS[t] + if not all(x and x[0] == expected for x in p): + raise EvidenceError('packed vector type') + extend(p) + continue + # Leaf components (types 2/3/4 by the check above): the S1 stack popped them + # last-first, before anything else, so they are checked here in that order. + for x in reversed(p): + _leaf(x) return node @@ -106,12 +321,14 @@ def _typed_info(info, dictionary): def tree_sha(tree): + if known_sha(tree) is not None: + return known_sha(tree) validate_tree(tree) return hashlib.sha256(json_bytes(tree)).hexdigest() def _key_segment(key): - return ['key', copy.deepcopy(key)] + return ['key', _copy_tree(key)] def _field(node, name): @@ -182,9 +399,37 @@ def apply_diff(tree, operations): return result +class _Checkpoints: + """S5 checkpoints are complete blob/inline records: verify and load one at a time.""" + def __init__(self, checkpoints): + self.checkpoints = checkpoints + for i in range(len(checkpoints)): + self[i] + + def __len__(self): + return len(self.checkpoints) + + def __getitem__(self, index): + cp = self.checkpoints[index] + s = _transport_ref(cp['S']) + latest = cp['latest'] + if latest.get('same_as_S') is True: + require(set(latest) == {'same_as_S', 'tree_sha', 'raw_bytes_sha', 'roundtrip_ok'}, 'same_as_S fields') + _proof(latest, s) + require(latest['raw_bytes_sha'] == cp['S']['raw_bytes_sha'], 'same_as_S byte mismatch') + return s, (s if known_sha(s) is not None else copy.deepcopy(s)) + return s, _transport_ref(latest) + + def __iter__(self): + for i in range(len(self)): + yield self[i] + + def reconstruct_checkpoints(checkpoints): """Each checkpoint has S and latest transport records; verify before use.""" require(type(checkpoints) is list and checkpoints, 'missing checkpoints') + if not any('diff' in cp[name] for cp in checkpoints for name in ('S', 'latest') if type(cp.get(name)) is dict): + return _Checkpoints(checkpoints) result, previous = [], None for cp in checkpoints: s = _transport(cp['S'], previous) @@ -207,7 +452,29 @@ def _proof(record, tree): require(record.get('tree_sha') == tree_sha(tree), 'tree SHA mismatch') +def _blob_record(record): + require(set(record) == {'tree', 'tree_sha', 'raw_bytes_sha', 'roundtrip_ok'}, 'transport fields') + require(type(record['tree']) is dict and set(record['tree']) == {'blob'}, 'blob reference fields') + require(record['tree']['blob'] == record['tree_sha'], 'blob/tree SHA binding') + require(record.get('roundtrip_ok') is True, 'Godot roundtrip missing/failed') + require(type(record.get('raw_bytes_sha')) is str and re.fullmatch('[0-9a-f]{64}', record['raw_bytes_sha']), 'raw bytes SHA') + blob_bytes(record['tree_sha']) + return record['tree_sha'] + + +def _transport_ref(record): + """Like _transport, but a validated blob tree is kept as a TreeRef (parsed on demand).""" + if type(record) is dict and type(record.get('tree')) is dict: + sha = _blob_record(record) + if sha not in _VALID_BLOBS: + blob_tree(sha) + return TreeRef(sha) + return _transport(record, None) + + def _transport(record, baseline): + if type(record) is dict and type(record.get('tree')) is dict: + return blob_tree(_blob_record(record)) require(('tree' in record) != ('diff' in record), 'tree/diff exclusive') require(set(record) == {'tree' if 'tree' in record else 'diff', 'tree_sha', 'raw_bytes_sha', 'roundtrip_ok'}, 'transport fields') if 'tree' in record: @@ -221,34 +488,39 @@ def _transport(record, baseline): def compare_trees(a, b): validate_tree(a); validate_tree(b) + if same_tree(a, b): + return {'equal': True, 'exact': True, 'differences': [], 'dict_order_paths': []} + a, b = materialize(a), materialize(b) differences, orders = [], [] + # Recorded nodes are shared with the compared trees, which are never mutated. def diff(path, x, y): - differences.append({'path': copy.deepcopy(path), 'a': copy.deepcopy(x), 'b': copy.deepcopy(y)}) + differences.append({'path': path, 'a': x, 'b': y}) def walk(x, y, path): - if exact(x, y): + # Both sides are validated typed trees, so == is exact JSON equality. + if x == y: return if x[0] != y[0] or len(x) != len(y): diff(path, x, y); return t = x[0] - if t in (27, 28) and not exact(x[2], y[2]): + if t in (27, 28) and x[2] != y[2]: diff(path + [['metadata', 0]], x[2], y[2]) if t == 27: def keyed(n): d = {} for k, v in n[1]: - text = _key_text(k) + text = k[1] if k[0] in (4, 21, 22) else _key_text(k) require(text not in d, 'duplicate textual dictionary key') d[text] = (k, v) return d dx, dy = keyed(x), keyed(y) - if set(dx) == set(dy) and [_key_text(k) for k, _ in x[1]] != [_key_text(k) for k, _ in y[1]]: - orders.append(copy.deepcopy(path)) + if set(dx) == set(dy) and list(dx) != list(dy): + orders.append(_copy_tree(path)) for key in sorted(set(dx) | set(dy)): if key not in dx or key not in dy: diff(path + [['key', [4, key]]], dx.get(key), dy.get(key)); continue kx, vx = dx[key]; ky, vy = dy[key] p = path + [_key_segment(kx)] - if not exact(kx, ky): + if kx != ky: diff(p + [['key_type', 0]], kx, ky) walk(vx, vy, p) elif t == 28 or t in range(5, 21) or t in range(30, 39): @@ -260,7 +532,40 @@ def compare_trees(a, b): else: diff(path, x, y) walk(a, b, []) - return {'equal': not differences, 'exact': exact(a, b), 'differences': differences, 'dict_order_paths': orders} + return {'equal': not differences, 'exact': a == b, 'differences': differences, 'dict_order_paths': orders} + + +HARNESS_LABEL = 'normalized-sha256:' +_CANONICAL = {} + + +def harness_digest(normalized): + """Labelled harness digest: SHA-256 of the exact normalized JSON (dict order kept). + compare_reports falls back to canonical_digest when two labelled digests differ.""" + return HARNESS_LABEL + tree_sha(normalized) + + +def canonical_digest(tree): + """Harness-only typed canonical digest; only Dictionary enumeration order is + canonicalized (key nodes, scalars, metadata and Array order stay exact). The JSON is the + S1 form, built without per-node copies; components and packed arrays hold no Dictionary.""" + known = known_sha(tree) + if known is not None and known in _CANONICAL: + return _CANONICAL[known] + validate_tree(tree) + def canonical(node): + t = node[0] + if t == 27: + keyed = sorted([(k[1] if k[0] in (4, 21, 22) else _key_text(k), k, v) for k, v in node[1]], key=lambda row: row[0]) + require(len({row[0] for row in keyed}) == len(keyed), 'digest textual key collision') + return [27, [[k, canonical(v)] for _, k, v in keyed], node[2]] + if t == 28: + return [28, [canonical(v) for v in node[1]], node[2]] + return node + digest = hashlib.sha256(json_bytes(canonical(materialize(tree)))).hexdigest() + if known is not None: + _CANONICAL[known] = digest + return digest def _key_text(key): @@ -295,7 +600,7 @@ def _marker(key, node): def _normalize(trees, profile_root, events): root = _profile(profile_root) - result = copy.deepcopy(trees) + result = _copy_tree(trees) side = {'entries': [], 'violations': [], 'profile_root': {**profile_root, 'matches_guard': True}} def visit(n, path, event_index, permitted_payload=False, event_root=False): if n[0] == 27: @@ -376,17 +681,119 @@ def normalize_events(events, profile_root): return _normalize(events, profile_root, True) +def _path_nodes(tree): + """Return [(key, dict node)] along systems.runtime.domain_events and the events node.""" + nodes, n = [], tree + for name in PERMITTED_EVENTS: + if n[0] != 27: + return None, None + found = [(k, v) for k, v in n[1] if k[0] in (4, 21) and k[1] == name] + if len(found) != 1: + return None, None + nodes.append((found[0][0], n)) + n = found[0][1] + return nodes, n + + +def _skeleton(nodes, events): + """The four permitted dictionaries, each keeping only the permitted key.""" + child = events + for key, node in reversed(nodes): + child = [27, [[key, child]], node[2]] + return child + + +def _replace_events(tree, events): + nodes, _ = _path_nodes(tree) + require(nodes is not None, 'events path missing') + child = events + for key, node in reversed(nodes): + child = [27, [[k, child] if k is key else [k, v] for k, v in node[1]], node[2]] + return child + + +def _fast_normalize(tree, text, profile_root): + """Exact result of normalize_tree when every F1-F3 candidate lies in recent_events. + + The original closed policy runs unchanged on a skeleton holding only the permitted + path; the remaining text is proven free of the profile root, the reserved token, + _us/_ms names and save_service. Returns None to request the full original walk. + """ + root = _profile(profile_root) + if not (root.isascii() and root.isprintable()) or any(c in root for c in '[]",\\{}') or TOKEN in text: + return None + nodes, events = _path_nodes(tree) + tokens = (root, '_us"', '_ms"', 'save_service') + side_profile = {**profile_root, 'matches_guard': True} + if not any(t in text for t in tokens): + if events is not None: + require(events[0] == 28, 'recent_events array required') + return 'identity', None, {'entries': [], 'violations': [], 'profile_root': side_profile}, None, None, None + if events is None or text.count('"recent_events"]') != 1: + return None + marker = '"recent_events"],' + start = text.find(marker) + if start < 0: + return None + start += len(marker) + try: + value, end = json.JSONDecoder().raw_decode(text, start) + except json.JSONDecodeError: + return None + if value != events or any(text.count(t, 0, start) or text.count(t, end) for t in tokens): + return None + normalized, side = _normalize([_skeleton(nodes, events)], profile_root, False) + _, new_events = _path_nodes(normalized[0]) + spliced = (text[:start] + json_bytes(new_events).decode('utf-8') + text[end:]).encode('utf-8') + # The skeleton keys/metadata and the original events let restore run without a parse. + kept = [(key, [27, [], node[2]]) for key, node in nodes] + return 'normalized', new_events, side, hashlib.sha256(spliced).hexdigest(), kept, events + + def normalize_tree(tree, profile_root): - normalized, side = _normalize([tree], profile_root, False) + sha = known_sha(tree) + if sha is not None and not (isinstance(tree, TreeRef) and tree.base is not None): + key = (sha, json_bytes(profile_root)) + if key not in _NORMALIZED: + fast = _fast_normalize(materialize(tree), blob_bytes(sha).decode('utf-8'), profile_root) + if fast is None: + # Candidates outside recent_events: the original full walk, not memoized. + normalized, side = _normalize([materialize(tree)], profile_root, False) + return normalized[0], side + _NORMALIZED[key] = fast + kind, events, side, normalized_sha = _NORMALIZED[key][:4] + base = tree if isinstance(tree, TreeRef) else TreeRef(sha) + if kind == 'identity': + return base, copy.deepcopy(side) + return TreeRef(normalized_sha, base, events), copy.deepcopy(side) + normalized, side = _normalize([materialize(tree)], profile_root, False) return normalized[0], side +def adopt(tree): + """Give a large constructed tree a SHA-backed text so the exact fast paths apply.""" + validate_tree(tree) + text = json_bytes(tree) + sha = hashlib.sha256(text).hexdigest() + if sha not in _BLOB_BYTES: + _BLOB_BYTES[sha] = text + while len(_BLOB_BYTES) > BYTES_CACHE: + _BLOB_BYTES.popitem(last=False) + result = BlobList(tree) + result.sha = sha + _VALID_BLOBS.add(sha) + _BLOB_TREES[sha] = result + while len(_BLOB_TREES) > TREE_CACHE: + _BLOB_TREES.popitem(last=False) + return result + + def _restore(normalized, sidecar, profile_root, events): root = _profile(profile_root) require(type(sidecar) is dict and set(sidecar) == {'entries', 'violations', 'profile_root'}, 'sidecar fields') require(sidecar['profile_root'] == {**profile_root, 'matches_guard': True}, 'sidecar profile') require(type(sidecar['entries']) is list and type(sidecar['violations']) is list, 'sidecar lists') - result = copy.deepcopy(normalized) + result = _copy_tree(normalized) seen = set() for entry in sidecar['entries']: require(set(entry) == {'event_index', 'path', 'key', 'original_node'} | ({'root'} if entry.get('key') == 'message' else set()), 'entry fields') @@ -418,6 +825,20 @@ def restore_events(normalized, sidecar, profile_root): def restore_tree(normalized, sidecar, profile_root): + if isinstance(normalized, TreeRef): + base = normalized.base if normalized.base is not None else normalized + expected, expected_side = normalize_tree(base, profile_root) + require(isinstance(expected, TreeRef) and expected.sha == normalized.sha, 'sidecar does not match normalized node') + if normalized.base is None: + require(exact(sidecar, expected_side) and not sidecar['entries'] and not sidecar['violations'], + 'non-reversible/unauthorized sidecar') + return normalized + # The original reversible restore runs on the skeleton; the rest is shared. + nodes, events = _NORMALIZED[(known_sha(base), json_bytes(profile_root))][4:] + restored = _restore(_skeleton(nodes, normalized.replacement), sidecar, profile_root, False) + _, restored_events = _path_nodes(restored) + require(restored_events == events, 'non-reversible/unauthorized sidecar') + return base return _restore(normalized, sidecar, profile_root, False) @@ -471,7 +892,7 @@ def compare_reports(a, b): require(tree_sha(restore_tree(ny, sy, profiles[1])) == tree_sha(y), 'b restore SHA') sidecars(path, sx, sy) comparison(path, nx, ny) - return sx, sy + return sx, sy, nx, ny def comparison(path, x, y): c = compare_trees(x, y) @@ -523,9 +944,19 @@ def compare_reports(a, b): for field in ('catalog_instance_id', 'current_catalog_instance_id'): excluded(path + ['C', field], 'process-local instance ID', x['C'][field], y['C'][field]) + def described(x, side): + """S5 joined facts record a large tree by SHA; rebuild it from its verified blob.""" + tree = TreeRef(x['source_tree_sha']) + return materialize(normalize_tree(tree, profiles[side])[0] if x['normalized'] else tree) + def scenario_facts(path, x, y): # Joined S3b facts carry lossless typed trees as well as JSON metadata. # Apply the same dictionary-order-only fallback to returned values. + descriptor = {'typed_tree_sha', 'source_tree_sha', 'normalized'} + if isinstance(x, dict) and isinstance(y, dict) and set(x) == set(y) == descriptor: + if x['typed_tree_sha'] != y['typed_tree_sha']: + comparison(path, described(x, 0), described(y, 1)) + return if isinstance(x, list) and isinstance(y, list) and x and y and type(x[0]) is int and type(y[0]) is int: validate_tree(x); validate_tree(y) comparison(path, x, y) @@ -563,7 +994,7 @@ def compare_reports(a, b): if main: require(x['minute'] == xs[0]['minute']+i and y['minute'] == ys[0]['minute']+i, 'checkpoint cadence') trees(p + ['S'], tx[i][0], ty[i][0], profiles) - sx, sy = trees(p + ['latest'], tx[i][1], ty[i][1], profiles) + sx, sy, nlx, nly = trees(p + ['latest'], tx[i][1], ty[i][1], profiles) if ownership and i == 2: record(p + ['digest_self_consistent'], x['latest_digest'] == x['computed_latest_digest'], y['latest_digest'] == y['computed_latest_digest']) if sx['entries'] or sy['entries']: @@ -572,7 +1003,12 @@ def compare_reports(a, b): record(p + ['computed_latest_digest'], x['computed_latest_digest'], y['computed_latest_digest']) if sx['entries'] or sy['entries']: require(type(x['harness_normalized_digest']) is str and type(y['harness_normalized_digest']) is str, 'missing harness normalized digest') - record(p + ['harness_normalized_digest'], x['harness_normalized_digest'], y['harness_normalized_digest']) + hx, hy = x['harness_normalized_digest'], y['harness_normalized_digest'] + if hx != hy and all(h.startswith(HARNESS_LABEL) for h in (hx, hy)) and canonical_digest(nlx) == canonical_digest(nly): + # Exact normalized JSON differs only by Dictionary order (paths recorded above). + out['digest_modes'].append({'path': p, 'mode': 'harness canonical digest (dictionary order only)'}) + else: + record(p + ['harness_normalized_digest'], hx, hy) excluded(p + ['latest_digest'], 'latest snapshot contains F1-F3 environment values', x['latest_digest'], y['latest_digest']) out['digest_modes'].append({'path': p, 'mode': 'harness normalized digest'}) else: diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/eq_probe.gd b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/eq_probe.gd index 0fac954..89a46ba 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/eq_probe.gd +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/eq_probe.gd @@ -1,5 +1,8 @@ extends SceneTree -## S3b external guarded probe. Native admission remains S4/Root. +## S5 external guarded probe. Native admission remains Root. +## Large trees, raw S/K/C bytes and package files are content-addressed gzip blobs +## (evidence/blobs/.gz), written once; records keep {"blob": sha}. R and O both run E1-E5. +const INLINE_LIMIT: int = 65536 const FIXTURE_SHA: String = "eb4f770071eb07cd7e136fe54c3f78768cc8de7a4264e62a9af1f06a8f90f9bd" const K_FIELDS: Array = ["absolute_minute", "speed", "paused", "snapshot_version", "_skip_next_process", "_pause_request_serial", "_abort_current_tick_requested", "_last_tick_advanced"] var clock: Variant @@ -7,8 +10,12 @@ var runtime: Variant var main: Variant var role: String var report: Dictionary = {} -var lifecycle: Dictionary = {"stage": "S3b", "errors": [], "preparation": [], "files": []} -var previous_tree: Array = [] +var lifecycle: Dictionary = {"stage": "S5", "errors": [], "preparation": [], "files": []} +var blob_index: Dictionary = {} +var transport_cache: Dictionary = {} +var last_snapshot_value: Dictionary = {} +var subscribed_stream: Variant = null +var known_event_ids: Dictionary = {} var finished: bool = false var bound: bool = false var recording: bool = false @@ -44,11 +51,18 @@ func f64(value: float) -> String: bytes.encode_double(0, value) return bytes.hex_encode() +# get_typed_script() returns a null Object for unscripted typed containers; it is +# transported as NIL. A scripted element type is not supported and fails loudly. +func typed_script(script: Variant) -> Array: + if script == null: return [0] + demand(false, "unsupported typed script metadata") + return [] + func typed_info(value: Variant) -> Variant: if typeof(value) == TYPE_ARRAY and value.is_typed(): - return [encode(value.get_typed_builtin()), encode(value.get_typed_class_name()), encode(value.get_typed_script())] + return [encode(value.get_typed_builtin()), encode(value.get_typed_class_name()), typed_script(value.get_typed_script())] if typeof(value) == TYPE_DICTIONARY and value.is_typed(): - return [[encode(value.get_typed_key_builtin()), encode(value.get_typed_key_class_name()), encode(value.get_typed_key_script())], [encode(value.get_typed_value_builtin()), encode(value.get_typed_value_class_name()), encode(value.get_typed_value_script())]] + return [[encode(value.get_typed_key_builtin()), encode(value.get_typed_key_class_name()), typed_script(value.get_typed_key_script())], [encode(value.get_typed_value_builtin()), encode(value.get_typed_value_class_name()), typed_script(value.get_typed_value_script())]] return null func encode(value: Variant) -> Array: @@ -160,61 +174,44 @@ func decode(node: Array) -> Variant: func decoded_basis(v: Array) -> Basis: return Basis(Vector3(v[0], v[1], v[2]), Vector3(v[3], v[4], v[5]), Vector3(v[6], v[7], v[8])) +# Write each distinct content once; the name is the SHA-256 of the uncompressed bytes. +func store_blob(bytes: PackedByteArray) -> Dictionary: + var digest: String = hashed(bytes) + if blob_index.has(digest): return {"blob": digest} + if not demand(bound, "blob write before guard binding"): return {"blob": digest} + var directory: String = "user://evidence/blobs" + var mkdir: int = DirAccess.make_dir_recursive_absolute(ProjectSettings.globalize_path(directory)) + if not demand(mkdir == OK, "blob mkdir failed"): return {"blob": digest} + var path: String = directory.path_join(digest + ".gz") + if not demand(not FileAccess.file_exists(path), "refuse blob overwrite: " + digest): return {"blob": digest} + var packed: PackedByteArray = bytes.compress(FileAccess.COMPRESSION_GZIP) + if not demand(packed.decompress_dynamic(-1, FileAccess.COMPRESSION_GZIP) == bytes, "blob gzip roundtrip failed: " + digest): return {"blob": digest} + var file: FileAccess = FileAccess.open(path, FileAccess.WRITE) + if not demand(file != null, "blob open failed: " + digest): return {"blob": digest} + file.store_buffer(packed) + file.flush() + var error: int = file.get_error() + file.close() + if not demand(error == OK, "blob write failed: " + digest): return {"blob": digest} + blob_index[digest] = {"bytes": bytes.size(), "gz_bytes": packed.size(), "gz_sha256": hashed(packed)} + return {"blob": digest} + +# var_to_bytes distinguishes typed metadata, String/StringName, int/float and key order, +# so equal bytes mean an equal value and an equal tree; the proof is reused for them. func transport(value: Variant) -> Dictionary: - var tree: Array = encode(value) var raw: PackedByteArray = var_to_bytes(value) + var raw_sha: String = hashed(raw) + if transport_cache.has(raw_sha): return transport_cache[raw_sha].duplicate(true) + var tree: Array = encode(value) var rebuilt: PackedByteArray = var_to_bytes(decode(tree)) var ok: bool = raw == rebuilt demand(ok, "Godot typed tree byte roundtrip failed") - return {"tree": tree, "tree_sha": hashed(json_text(tree).to_utf8_buffer()), "raw_bytes_sha": hashed(raw), "roundtrip_ok": ok} - -func tree_diff(before: Array, after: Array, path: Array = []) -> Array: - if json_text(before) == json_text(after): return [] - # Exact subtree replacement also preserves changes of insertion order and metadata. - if before[0] != after[0] or before[0] not in [TYPE_DICTIONARY, TYPE_ARRAY] or json_text(before[2]) != json_text(after[2]): - return [{"op": "set", "path": path, "node": after}] - var changes: Array = [] - if before[0] == TYPE_DICTIONARY: - var old_keys: Array = [] - var new_keys: Array = [] - for pair: Array in before[1]: old_keys.append(pair[0]) - for pair: Array in after[1]: new_keys.append(pair[0]) - if json_text(old_keys) != json_text(new_keys): return [{"op": "set", "path": path, "node": after}] - for i: int in range(before[1].size()): - changes.append_array(tree_diff(before[1][i][1], after[1][i][1], path + [["key", after[1][i][0]]])) - else: - if before[1].size() != after[1].size(): - return [{"op": "array_splice", "path": path, "start": 0, "delete_count": before[1].size(), "nodes": after[1]}] - for i: int in range(before[1].size()): changes.append_array(tree_diff(before[1][i], after[1][i], path + [["index", i]])) - return changes - -func tree_at(tree: Array, path: Array) -> Array: - var node: Array = tree - for segment: Array in path: - if segment[0] == "index": node = node[1][segment[1]] - else: - var found: bool = false - for pair: Array in node[1]: - if json_text(pair[0]) == json_text(segment[1]): - node = pair[1] - found = true - break - demand(found, "diff path missing") - return node - -func diff_record(record: Dictionary, baseline: Array) -> Dictionary: - var operations: Array = tree_diff(baseline, record.tree) - var replay: Array = baseline.duplicate(true) - for op: Dictionary in operations: - var target: Array = tree_at(replay, op.path) - if op.op == "set": - target.clear() - target.append_array(op.node.duplicate(true)) - elif op.op == "array_splice": - for unused: int in range(op.delete_count): target[1].remove_at(op.start) - for i: int in range(op.nodes.size()): target[1].insert(op.start + i, op.nodes[i].duplicate(true)) - demand(json_text(replay) == json_text(record.tree), "diff roundtrip mismatch") - return {"diff": operations, "tree_sha": record.tree_sha, "raw_bytes_sha": record.raw_bytes_sha, "roundtrip_ok": record.roundtrip_ok} + var text: PackedByteArray = json_text(tree).to_utf8_buffer() + if text.size() <= INLINE_LIMIT: + return {"tree": tree, "tree_sha": hashed(text), "raw_bytes_sha": raw_sha, "roundtrip_ok": ok} + var record: Dictionary = {"tree": store_blob(text), "tree_sha": hashed(text), "raw_bytes_sha": raw_sha, "roundtrip_ok": ok} + transport_cache[raw_sha] = record + return record.duplicate(true) func kernel_state() -> Dictionary: var result: Dictionary = {} @@ -266,21 +263,21 @@ func witness(value: Dictionary) -> Dictionary: return {"S": hashed(value.s_bytes), "K": hashed(value.k_bytes), "C": hashed(value.c_bytes)} func raw_layers(value: Dictionary) -> Dictionary: - return {"sha": witness(value), "S": Marshalls.raw_to_base64(value.s_bytes), "K": Marshalls.raw_to_base64(value.k_bytes), "C": Marshalls.raw_to_base64(value.c_bytes), "kernel": value.K, "cache": value.C} + return {"sha": witness(value), "S": store_blob(value.s_bytes), "K": store_blob(value.k_bytes), "C": store_blob(value.c_bytes), "kernel": value.K, "cache": value.C} func checkpoint() -> void: var before: Dictionary = layers() - var s: Dictionary = transport(runtime.create_snapshot()) + var snapshot_value: Dictionary = runtime.create_snapshot() + var s: Dictionary = transport(snapshot_value) var latest_value: Dictionary = runtime.get("latest_snapshot") - var latest: Dictionary = transport(latest_value) var latest_bytes: PackedByteArray = var_to_bytes(latest_value) var digest: String = runtime.get("latest_digest") var computed: String = SimulationDigest.compute(latest_value) - var current_tree: Array = s.tree - if not previous_tree.is_empty(): s = diff_record(s, previous_tree) + # Every checkpoint keeps a complete tree (blob reference); no diff chain. + var latest: Dictionary = {} if latest_bytes == before.s_bytes: - latest = {"same_as_S": true, "tree_sha": latest.tree_sha, "raw_bytes_sha": latest.raw_bytes_sha, "roundtrip_ok": latest.roundtrip_ok} - else: latest = diff_record(latest, current_tree) + latest = {"same_as_S": true, "tree_sha": s.tree_sha, "raw_bytes_sha": s.raw_bytes_sha, "roundtrip_ok": s.roundtrip_ok} + else: latest = transport(latest_value) var after: Dictionary = layers() demand(before.s_bytes == after.s_bytes and before.k_bytes == after.k_bytes and before.c_bytes == after.c_bytes, "observation changed full S/K/C") demand(digest == computed, "latest digest self-consistency") @@ -291,12 +288,13 @@ func checkpoint() -> void: write_evidence("checkpoint-%02d.json" % index, cp) write_evidence("observation-%02d.json" % index, {"before": raw_layers(before), "after": raw_layers(after)}) report.checkpoints.append(cp) - previous_tree = current_tree + last_snapshot_value = snapshot_value func event_counts() -> Dictionary: return {"counter": runtime.id_generator.get_counter(&"domain_event"), "published_ids_count": runtime.domain_events.get("_published_ids").size()} func observe_event(event: Variant) -> void: + known_event_ids[str(event.event_id)] = true if scenario_active: scenario_events.append(transport(event.to_dictionary())) return @@ -307,6 +305,28 @@ func observe_event(event: Variant) -> void: "entity_ids": {"type": typeof(event.entity_ids), "typed_info": typed_info(event.entity_ids)}, "payload": {"type": typeof(event.payload), "typed_info": typed_info(event.payload)}, "causation_command_id": typeof(event.causation_command_id)}}) +# A successful product restore replaces runtime.domain_events with a new stream that does +# not carry subscribers. Record that fact, recover from the live stream's recent_events() +# the events the observer could not receive, and subscribe to the live stream again. +func follow_event_stream() -> Dictionary: + var current: Variant = runtime.domain_events + if current == subscribed_stream: return {"replaced": false} + var subscribers: Array = [] + var all_subscribers: Dictionary = current.get("_subscribers") + for event_type: Variant in all_subscribers: + for id: Variant in all_subscribers[event_type]: subscribers.append(str(event_type) + "/" + str(id)) + subscribers.sort_custom(func(a: Variant, b: Variant) -> bool: return str(a) < str(b)) + var recovered: Array = [] + for event: Variant in current.recent_events(): + if known_event_ids.has(str(event.event_id)): continue + recovered.append(str(event.event_id)) + observe_event(event) + demand(current.subscribe(&"*", &"p28_eq_observer", observe_event), "wildcard resubscription failed") + subscribed_stream = current + var fact: Dictionary = {"replaced": true, "new_stream_subscribers_before": subscribers, "recovered_event_ids": recovered} + lifecycle.event_stream_replacements.append(fact.duplicate(true)) + return fact + func observe_snapshot(_snapshot: Dictionary, _digest: String) -> void: snapshot_reference = _snapshot record_signal("snapshot_published") @@ -315,8 +335,11 @@ func observe_state(_snapshot: Dictionary) -> void: state_reference = _snapshot record_signal("state_updated") +# The domain_event counter at emission places each signal in the event order, so every +# publish can be bound to its cause (tick end, successful restore, completed command). func record_signal(name: String) -> void: - var row: Dictionary = {"signal": name, "minute": clock.absolute_minute} + var row: Dictionary = {"signal": name, "minute": clock.absolute_minute, "event_counter": runtime.id_generator.get_counter(&"domain_event"), + "command_counter": runtime.get("_next_command_id")} if scenario_active: scenario_signals.append(row) elif recording: report.signal_order.append(row) else: warm_signals.append(row) @@ -352,21 +375,24 @@ func bind_profile() -> bool: var path: String = OS.get_environment("THE_TREE_PACK_PROFILE_REPORT") var file: FileAccess = FileAccess.open(path, FileAccess.READ) if not demand(file != null, "guard receipt missing"): return false - var receipt: Variant = JSON.parse_string(file.get_as_text()) + # Godot parses JSON numbers as float; the exact receipt text is retained for binding. + var receipt_text: String = file.get_as_text() + var receipt: Variant = JSON.parse_string(receipt_text) file.close() if not demand(receipt is Dictionary and receipt.get("verified") == true, "guard receipt unverified"): return false var actual: Variant = receipt.get("actual_user_data_dir") var live_root: String = ProjectSettings.globalize_path("user://").simplify_path() if not demand(actual is String and actual == live_root and OS.get_user_data_dir() == actual, "live profile differs from guard actual_user_data_dir"): return false report["profile_root"] = {"root": live_root, "actual_user_data_dir": actual} - lifecycle["guard"] = {"path": path, "sha256": FileAccess.get_sha256(path), "receipt": receipt, "live_root": live_root} + lifecycle["guard"] = {"path": path, "sha256": FileAccess.get_sha256(path), "receipt": receipt, "receipt_text": receipt_text, "live_root": live_root} bound = true return true func write_evidence(name: String, value: Variant) -> void: if not demand(bound, "evidence write before guard binding"): return var directory: String = "user://evidence" - var mkdir: int = DirAccess.make_dir_recursive_absolute(directory) + # The guard switches the user dir at runtime; globalize first, as the RESTART helpers do. + var mkdir: int = DirAccess.make_dir_recursive_absolute(ProjectSettings.globalize_path(directory)) if not demand(mkdir == OK, "evidence mkdir failed"): return var path: String = directory.path_join(name) if not demand(not FileAccess.file_exists(path), "refuse evidence overwrite: " + name): return @@ -434,6 +460,8 @@ func begin() -> void: runtime.snapshot_published.connect(observe_snapshot) runtime.state_updated.connect(observe_state) demand(runtime.domain_events.subscribe(&"*", &"p28_eq_observer", observe_event), "wildcard subscription failed") + subscribed_stream = runtime.domain_events + lifecycle["event_stream_replacements"] = [] connected = true lifecycle["observer_before"] = initial_inventory lifecycle["observer_connected"] = inventory() @@ -448,7 +476,9 @@ func begin() -> void: report.event_start = event_counts() recording = true checkpoint() - b1_snapshot = decode(report.checkpoints[0].S.tree).duplicate(true) + # The B1 value itself; its transport proves decode(tree) has the same bytes. + b1_snapshot = last_snapshot_value.duplicate(true) + for event_id: Variant in b1_snapshot[&"systems"][&"runtime"][&"domain_events"]["published_ids"]: known_event_ids[str(event_id)] = true # Stage 4: B1 and 30 exact checkpoints, uncapped events through the last frame. for unused: int in range(30): if not lifecycle.errors.is_empty(): break @@ -458,9 +488,10 @@ func begin() -> void: recording = false # Stage 5: E3 dedicated intervals, after measured event/signal closure. lifecycle["outside"] = raw_layers(layers()) - run_e3() - run_e4() - run_e5() + # Any harness error already fails the run; stop before further expensive scenarios. + if lifecycle.errors.is_empty(): run_e3() + if lifecycle.errors.is_empty(): run_e4() + if lifecycle.errors.is_empty(): run_e5() finish() func finish() -> void: @@ -474,10 +505,11 @@ func finish() -> void: lifecycle["observer_disconnected"] = inventory() demand(json_text(initial_inventory) == json_text(lifecycle.observer_disconnected), "observer inventory not restored") lifecycle["warm_signals"] = warm_signals - lifecycle["stop_reason"] = "S3b_complete_S4_pending" if lifecycle.errors.is_empty() else "failed" + lifecycle["stop_reason"] = "S5_complete" if lifecycle.errors.is_empty() else "failed" if bound: write_evidence("events.json", report.events) write_evidence("report.json", report) + lifecycle["blobs"] = blob_index.duplicate(true) write_evidence("lifecycle.json", lifecycle.duplicate(true)) print("P28_02_EQ_REPORT=" + json_text(report)) if is_instance_valid(main): main.ui_audio_window_close_drained.connect(audio_close, CONNECT_ONE_SHOT) @@ -525,7 +557,7 @@ func e3_package(path: String) -> Dictionary: if not demand(file != null, "package evidence open"): continue var bytes: PackedByteArray = file.get_buffer(file.get_length()) file.close() - files[name] = {"bytes": Marshalls.raw_to_base64(bytes), "sha256": hashed(bytes)} + files[name] = {"bytes": store_blob(bytes), "sha256": hashed(bytes)} return files func e3_prepare_package(path: String, input: Dictionary, kind: String) -> Dictionary: @@ -541,15 +573,27 @@ func e3_prepare_package(path: String, input: Dictionary, kind: String) -> Dictio var manifest_path: String = path.path_join("manifest.json") var file: FileAccess = FileAccess.open(manifest_path, FileAccess.READ) if not demand(file != null, "manifest read"): return info - var manifest: Dictionary = JSON.parse_string(file.get_as_text()) + var text: String = file.get_as_text() file.close() - match kind: - "missing_key": manifest.erase("checksum_world") - "wrong_type": manifest["format_version"] = "x" - "out_of_range": manifest["format_version"] = 2147483647 + # Edit only the one key line. Re-serializing a parsed manifest would turn every + # JSON integer into a float (Godot parses numbers as float), changing other fields. + var key: String = "checksum_world" if kind == "missing_key" else "format_version" + var prefix: String = "\t\"" + key + "\": " + var lines: PackedStringArray = PackedStringArray() + var found: int = 0 + for line: String in text.split("\n"): + if line.begins_with(prefix): + found += 1 + var comma: String = "," if line.ends_with(",") else "" + if kind == "missing_key": + demand(comma == ",", "removed manifest key must not be last") + continue + line = prefix + ("\"x\"" if kind == "wrong_type" else "2147483647") + comma + lines.append(line) + if not demand(found == 1, "manifest key line: " + key): return info file = FileAccess.open(manifest_path, FileAccess.WRITE) if not demand(file != null, "manifest write"): return info - file.store_string(json_text(manifest)) + file.store_string("\n".join(lines)) file.close() elif kind == "tampered_world": var world_path: String = path.path_join("world.bin") @@ -615,6 +659,7 @@ func run_e3() -> void: "restore_snapshot": actual = runtime.restore_snapshot(input) "validate": actual = SimulationSnapshot.validate(input) "load_from_path": actual = runtime.load_from_path(path) + var stream_fact: Dictionary = follow_event_stream() if package != null: package["after_operation"] = e3_package(path) var after: Dictionary = e3_observation() scenario_active = false @@ -650,13 +695,17 @@ func run_e3() -> void: var evidence: Dictionary = {"id": id, "begin": before, "invocation_before": invocation_before, "end": after, "input": transport(input), "return": transport(actual), "package": package, "events": scenario_events, "signals": scenario_signals.duplicate(true), "latest_save_operation_result": transport(runtime.get("latest_save_operation_result")), - "save_budget_before": transport(budget_before), "save_budget_after": transport(budget_after), "boundaries": ["begin", "operation", "end"]} + "save_budget_before": transport(budget_before), "save_budget_after": transport(budget_after), "boundaries": ["begin", "operation", "end"], + "event_stream": stream_fact} report.scenarios.append(scenario) lifecycle.e3.append(evidence) write_evidence("e3-%02d.json" % (report.scenarios.size() - 1), evidence) # S3b shares S3a's complete observation and transport; no state repair. func e45_emit(id: String, operation: String, observations: Array, detail: Dictionary) -> void: + # The returned value itself; a large return is stored as a blob and is not decoded here. + var returned_value: Variant = detail.get("_return_value") + detail.erase("_return_value") detail["signals"] = scenario_signals.duplicate(true) var cps: Array = [] for observation: Dictionary in observations: cps.append(observation.checkpoint) @@ -666,7 +715,7 @@ func e45_emit(id: String, operation: String, observations: Array, detail: Dictio var facts: Dictionary = detail.duplicate(true) for key: String in ["package_before", "package_after", "save_return", "return", "save_budget_before", "save_budget_after", "latest_save_operation_result", "observation_before", "observation_after"]: facts.erase(key) if detail.has("return"): - var actual: Variant = decode(detail["return"].tree) + var actual: Variant = returned_value facts["return_fact"] = {"ok": actual.get(&"ok"), "code": actual.get(&"code")} if actual is Dictionary else actual if facts.has("trials"): for trial: Dictionary in facts.trials: @@ -738,7 +787,10 @@ func run_e4() -> void: elif operation == "restore_snapshot": var input: Dictionary = runtime.create_snapshot().duplicate(true) detail["input"] = transport(input) - detail["return"] = transport(runtime.restore_snapshot(input)) + var restore_return: Variant = runtime.restore_snapshot(input) + detail["event_stream"] = follow_event_stream() + detail["return"] = transport(restore_return) + detail["_return_value"] = restore_return elif operation == "load_from_path": var input: Dictionary = runtime.create_snapshot().duplicate(true) var path: String = "user://p28_eq/" + role.to_lower() + "/good" @@ -748,7 +800,10 @@ func run_e4() -> void: detail["save_return"] = transport(saved) detail["package_before"] = e3_package(path) demand(saved.get(&"ok") == true, "E4 good package save failed") - detail["return"] = transport(runtime.load_from_path(path)) + var load_return: Variant = runtime.load_from_path(path) + detail["event_stream"] = follow_event_stream() + detail["return"] = transport(load_return) + detail["_return_value"] = load_return detail["latest_save_operation_result"] = transport(runtime.get("latest_save_operation_result")) detail["package_after"] = e3_package(path) elif operation == "rejected_command": diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/run_eq.py b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/run_eq.py index cfb7836..df9d392 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/run_eq.py +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/run_eq.py @@ -140,9 +140,10 @@ def plan(collector, standard, engine, fixture, out): def copy_evidence(runtime, destination): source = runtime / 'evidence' before = verify.inventory(source, seals=True) - require(set(before) == verify.NAMES, 'private evidence missing/extra') + require(set(verify.split_evidence(before)[0]) == verify.NAMES, 'private evidence missing/extra') destination.mkdir() for name in sorted(before): + (destination / name).parent.mkdir(parents=True, exist_ok=True) shutil.copyfile(source / name, destination / name) require(verify.inventory(source, seals=True) == before == verify.inventory(destination, seals=True), 'evidence changed during copy') return before @@ -228,7 +229,8 @@ def run(admission, out, collector, standard, outer, diag): Path(admission['engine']), collector, standard) require((ROOT / 'project.godot').read_bytes() == public and (stage / 'project.godot').read_bytes() == public, 'project restoration') if error is None: - result = verify.recompute(out, execution, collector, standard, diag) + with check.memo_scope(): + result = verify.recompute(out, execution, collector, standard, diag, parallel=True) write(out / 'results.json', result) for phase, values in result['phases'].items(): for name, value in values.items(): diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py index 9c1fbf4..d6e2ecb 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py @@ -432,6 +432,7 @@ def s2_report(): state = snapshot() runtime = eq._field(eq._field(state, 'systems'), 'runtime') runtime[1].append([[4, 'id_generator'], d(counters=d(domain_event=[2, 3]))]) + runtime[1].append([[4, 'next_command_id'], [2, 1]]) events = eq._field(runtime, 'domain_events') events[1].append([[4, 'published_ids'], arr(*([4, 'domain_event.%012d' % i] for i in range(1, 4)))]) value['checkpoints'] = [checkpoint(state, 632+i) for i in range(31)] @@ -441,7 +442,7 @@ def s2_report(): cp['K']['_phase_handlers'] = {str(i): [] for i in range(11)} cp['C'].update(catalog_instance_id='123', current_catalog_instance_id='123') cp.update(latest_digest='b'*64, computed_latest_digest='b'*64, harness_normalized_digest=None) - value['signal_order'] = [{'signal': sig, 'minute': cp['minute']} for cp in value['checkpoints'][1:] for sig in ('snapshot_published', 'state_updated')] + value['signal_order'] = [{'signal': sig, 'minute': cp['minute'], 'event_counter': 3, 'command_counter': 1} for cp in value['checkpoints'][1:] for sig in ('snapshot_published', 'state_updated')] return value @@ -672,7 +673,7 @@ class S2Static(unittest.TestCase): self.reject(self.probe.replace('return str(a) < str(b)', 'return a < b')) def test_full_state_and_godot_roundtrip_required(self): - for required in ('var_to_bytes(decode(tree))', 'transport(runtime.create_snapshot())', 'before.k_bytes == after.k_bytes', 'event.to_dictionary()', 'receipt.get("actual_user_data_dir")'): + for required in ('var_to_bytes(decode(tree))', 'transport(snapshot_value)', 'before.k_bytes == after.k_bytes', 'event.to_dictionary()', 'receipt.get("actual_user_data_dir")'): with self.subTest(required=required): self.reject(self.probe.replace(required, 'null')) def test_no_event_cap_or_duplicate_report(self): @@ -790,7 +791,8 @@ def e3_fixture(role='R'): evidence.append({'id': id_, 'begin': begin, 'invocation_before': copy.deepcopy(begin), 'end': end, 'boundaries': ['begin', 'operation', 'end'], 'input': transport(checker.e3_expected_input(b1, kind)), 'return': transport(actual), 'package': package, 'events': event_records, 'signals': [], - 'latest_save_operation_result': transport(latest), 'save_budget_before': transport(d()), 'save_budget_after': transport(d())}) + 'latest_save_operation_result': transport(latest), 'save_budget_before': transport(d()), 'save_budget_after': transport(d()), + 'event_stream': {'replaced': False}}) return value, evidence, transport(b1) @@ -894,6 +896,10 @@ class S3a(unittest.TestCase): value, evidence, b1 = e3_fixture() value['scenarios'][0]['result']['ok'] = True evidence[0]['return'] = transport([1, 1]) + # S5: an accepted restore publishes once (simulation_runtime.gd:1473), as the product does. + state = evidence[0]['begin']['checkpoint']['S']['tree'] + evidence[0]['signals'] = [{'signal': sig, 'minute': evidence[0]['begin']['checkpoint']['minute'], 'event_counter': checker.counts(state)[0]['counter'], + 'command_counter': checker.next_command_id(state)} for sig in ('snapshot_published', 'state_updated')] checked = self.check(value, evidence, b1) self.assertTrue(checked['ok'], checked['errors']) self.assertEqual(checked['e3'][0]['defects'][0]['kind'], 'invalid_input_accepted') @@ -993,13 +999,19 @@ def e45_fixture(role='R'): current = copy.deepcopy(previous) evidence = [] def emit(ident, op, obs, detail, events=()): - detail['signals'] = [] + # Publishes as the product makes them: one per successful restore/load and per tick. + counter = checker.counts(obs[0]['checkpoint']['S']['tree'])[0]['counter'] + commands = checker.next_command_id(obs[0]['checkpoint']['S']['tree']) + minutes = [o['checkpoint']['minute'] for o in obs] + published = ([minutes[0]] if op in ('restore_snapshot', 'load_from_path') else []) + [b for a, b in zip(minutes, minutes[1:]) if b == a+1] + signals = [{'signal': sig, 'minute': m, 'event_counter': counter, 'command_counter': commands} for m in published for sig in ('snapshot_published', 'state_updated')] + detail['signals'] = copy.deepcopy(signals) result = {'event_count': len(events), 'applicability': detail.get('applicability', 'applied'), 'reason': detail.get('reason'), 'facts': checker.e45_facts(detail)} raw['scenarios'].append({'id': ident, 'operation': op, 'result': result, 'checkpoints': [o['checkpoint'] for o in obs], 'events': list(events)}) evidence.append({'id': ident, 'boundaries': ['begin', 'operation', 'end'], 'observations': obs, - 'detail': detail, 'events': [transport(e) for e in events], 'signals': []}) + 'detail': detail, 'events': [transport(e) for e in events], 'signals': signals}) for op in checker.E4_PATHS: begin = copy.deepcopy(current); minute = begin['checkpoint']['minute'] detail = {}; obs = [begin]; events = [] @@ -1017,14 +1029,14 @@ def e45_fixture(role='R'): elif op == 'tick': minute += 1 elif op == 'restore_snapshot': - detail = {'input': transport(tree), 'return': transport([1, 1])} + detail = {'input': transport(tree), 'return': transport([1, 1]), 'event_stream': {'replaced': False}} elif op == 'load_from_path': ev = event(raw['profile_root']['root']) # Match the next identity required by X(P,event). counter = checker.counts(tree)[0]['counter'] - checker.node_at(ev, 'event_id')[1] = 'event_'+str(counter+1) + checker.node_at(ev, 'event_id')[1] = 'domain_event.%012d' % (counter+1) detail = {'input': transport(tree), 'return': transport(d(ok=[1, 1], code=[4, 'OK'])), - 'path': 'user://p28_eq/'+role.lower()+'/good'} + 'path': 'user://p28_eq/'+role.lower()+'/good', 'event_stream': {'replaced': False}} package = e3_package_fixture('duplicate_published_ids') detail.update(save_return=package['save_return'], package_before=package['original'], package_after=package['original'], latest_save_operation_result=transport(checker.node_at(ev, 'payload'))) tree, _ = checker.e3_x(tree, ev) @@ -1294,7 +1306,7 @@ def s4_phase_fixture(directory, phase='R-A', pid=101): 'project_settings_persisted': False} guard_path = directory/(phase+'-guard.json') verifier.write(guard_path, guard) - life = {'stage': 'S3b', 'errors': [], 'stop_reason': 'S3b_complete_S4_pending', + life = {'stage': 'S5', 'errors': [], 'stop_reason': 'S5_complete', 'blobs': {}, 'event_stream_replacements': [], 'guard': {'receipt': guard, 'live_root': root, 'sha256': verifier.sha(guard_path), 'path': str(guard_path)}, 'observer_before': {}, 'observer_connected': {'probe': True}, 'observer_disconnected': {}, 'ops': {'code': 'INVALID_START_TIME'} if role == 'R' else {'ok': True}, @@ -1698,5 +1710,588 @@ class S4StoredResultBindings(unittest.TestCase): def test_raw_joined_substitution_rejected_after_seal(self): self.reject_stored_change('raw_joined') +# S5 (EQ_S5_SCALE_PLAN r01/r02): content-addressed blobs, exact fast paths, event stream. +import gzip +import shutil +import tempfile + + +def s5_root(): + base = os.environ.get('BUILD_OUTPUT_DIR') or tempfile.gettempdir() + return Path(tempfile.mkdtemp(prefix='p28-eq-s5-', dir=base)) + + +def put_blob(root, data): + digest = hashlib.sha256(data).hexdigest() + (root/(digest+'.gz')).write_bytes(gzip.compress(data)) + return digest + + +def as_blobs(value, root): + """Every inline transport record becomes a blob reference to the same tree.""" + if isinstance(value, dict): + if set(value) == {'tree', 'tree_sha', 'raw_bytes_sha', 'roundtrip_ok'} and isinstance(value['tree'], list): + digest = put_blob(root, eq.json_bytes(value['tree'])) + assert digest == value['tree_sha'] + return dict(value, tree={'blob': digest}) + return {k: as_blobs(v, root) for k, v in value.items()} + if isinstance(value, list): + return [as_blobs(v, root) for v in value] + return value + + +def reference_exact(a, b): + return eq.json_bytes(a) == eq.json_bytes(b) + + +def reference_compare_trees(a, b): + """The S1-S4 algorithm (JSON comparison at every level), kept to prove equivalence.""" + eq.validate_tree(a); eq.validate_tree(b) + differences, orders = [], [] + def diff(path, x, y): + differences.append({'path': copy.deepcopy(path), 'a': copy.deepcopy(x), 'b': copy.deepcopy(y)}) + def walk(x, y, path): + if reference_exact(x, y): + return + if x[0] != y[0] or len(x) != len(y): + diff(path, x, y); return + t = x[0] + if t in (27, 28) and not reference_exact(x[2], y[2]): + diff(path + [['metadata', 0]], x[2], y[2]) + if t == 27: + def keyed(n): + result = {} + for k, v in n[1]: + result[eq._key_text(k)] = (k, v) + return result + dx, dy = keyed(x), keyed(y) + if set(dx) == set(dy) and [eq._key_text(k) for k, _ in x[1]] != [eq._key_text(k) for k, _ in y[1]]: + orders.append(copy.deepcopy(path)) + for key in sorted(set(dx) | set(dy)): + if key not in dx or key not in dy: + diff(path + [['key', [4, key]]], dx.get(key), dy.get(key)); continue + kx, vx = dx[key]; ky, vy = dy[key] + p = path + [eq._key_segment(kx)] + if not reference_exact(kx, ky): + diff(p + [['key_type', 0]], kx, ky) + walk(vx, vy, p) + elif t == 28 or t in range(5, 21) or t in range(30, 39): + for i in range(max(len(x[1]), len(y[1]))): + if i >= len(x[1]) or i >= len(y[1]): + diff(path + [['index', i]], x[1][i] if i < len(x[1]) else None, y[1][i] if i < len(y[1]) else None) + else: + walk(x[1][i], y[1][i], path + [['index', i]]) + else: + diff(path, x, y) + walk(a, b, []) + return {'equal': not differences, 'exact': reference_exact(a, b), 'differences': differences, 'dict_order_paths': orders} + + +def reference_digest(tree): + def canonical(node): + result = copy.deepcopy(node) + if node[0] == 27: + names = [eq._key_text(k) for k, _ in node[1]] + eq.require(len(set(names)) == len(names), 'digest textual key collision') + result[1] = [[copy.deepcopy(k), canonical(v)] for k, v in sorted(node[1], key=lambda p: eq._key_text(p[0]))] + elif node[0] == 28 or 5 <= node[0] <= 20 or 30 <= node[0] <= 38: + result[1] = [canonical(v) for v in node[1]] + return result + eq.validate_tree(tree) + return eq.tree_sha(canonical(tree)) + + +def reference_expected_input(b1, kind): + value = copy.deepcopy(b1) + if kind == 'missing_key': + value[1] = [pair for pair in value[1] if pair[0][1] != 'clock'] + elif kind in ('wrong_type', 'out_of_range'): + checker.node_at(value, 'clock', 'absolute_minute' if kind == 'wrong_type' else 'speed')[:] = [4, 'x'] if kind == 'wrong_type' else [2, 9] + elif kind in ('duplicate_published_ids', 'duplicate_facility'): + nodes = (checker.node_at(value, 'systems', 'runtime', 'domain_events', 'published_ids') if kind == 'duplicate_published_ids' + else checker.node_at(value, 'systems', 'runtime', 'facilities', 'instances')) + if nodes[1]: + nodes[1].append(copy.deepcopy(nodes[1][0])) + return value + + +def reference_x(before, event_tree): + value = copy.deepcopy(before) + counter = checker.node_at(value, 'systems', 'runtime', 'id_generator', 'counters', 'domain_event') + counter[1] += 1 + domain = checker.node_at(value, 'systems', 'runtime', 'domain_events') + ids = checker.fields(domain)['published_ids'] + ids[1].append(copy.deepcopy(checker.fields(event_tree)['event_id'])) + ids[1].sort(key=lambda n: n[1]) + recent = checker.fields(domain)['recent_events'] + dropped = copy.deepcopy(recent[1][0]) if len(recent[1]) == 256 else None + recent[1].append(copy.deepcopy(event_tree)) + if len(recent[1]) > 256: + del recent[1][0] + return value, dropped + + +def s5_state(events=(), minute=0, extra=None): + state = d(clock=d(absolute_minute=[2, minute], speed=[2, 1]), + systems=d(runtime=d(id_generator=d(counters=d(domain_event=[2, 3])), + domain_events=d(published_ids=arr(*([4, 'domain_event.%012d' % i] for i in range(1, 4))), + recent_events=arr(*events)), + facilities=d(instances=arr(d(id=[4, 'f1']))), + vectors=arr([9, [[3, '0000000000000000'], [3, '000000000000f03f'], [3, '0000000000000040']]], + [30, [[2, 1], [2, 2]]]))), + value=arr([2, minute])) + if extra is not None: + state[1].append([[4, 'extra'], extra]) + return state + + +def reference_validate(node): + """The S1 validate_tree (JSON key comparison, stack order), kept to prove equivalence.""" + import base64, re + pending = [node] + while pending: + n = pending.pop() + eq.require(type(n) is list and n and type(n[0]) is int, 'invalid typed node') + t = n[0] + eq.require(t not in (23, 24, 25, 26) and 0 <= t <= 38, 'unsupported Variant type') + eq.require(len(n) == (1 if t == 0 else 3 if t in (27, 28) else 2), 'node arity') + if t == 0: + continue + p = n[1] + if t in (1, 2): + eq.require(type(p) is int and (p in (0, 1) if t == 1 else -(2**63) <= p < 2**63), 'integer payload') + elif t == 3: + eq.require(type(p) is str and re.fullmatch('[0-9a-f]{16}', p), 'float must be f64 LE hex') + elif t in (4, 21, 22): + eq.require(type(p) is str, 'string payload') + elif t == 29: + eq.require(type(p) is str, 'byte array payload') + try: + eq.require(base64.b64encode(base64.b64decode(p, validate=True)).decode() == p, 'noncanonical base64') + except (ValueError, TypeError) as exc: + raise eq.EvidenceError('invalid base64') from exc + elif t == 27: + eq.require(type(p) is list, 'dictionary entries') + seen = set() + for pair in p: + eq.require(type(pair) is list and len(pair) == 2, 'dictionary pair') + key = eq.json_bytes(pair[0]) + eq.require(key not in seen, 'duplicate dictionary key') + seen.add(key) + pending.extend(pair) + eq._typed_info(n[2], dictionary=True) + elif t == 28: + eq.require(type(p) is list, 'array elements') + eq._typed_info(n[2], dictionary=False) + pending.extend(p) + else: + eq.require(type(p) is list, 'component nodes') + sizes = {5: 2, 6: 2, 7: 4, 8: 4, 9: 3, 10: 3, 11: 6, 12: 4, 13: 4, 14: 4, 15: 4, 16: 6, 17: 9, 18: 12, 19: 16, 20: 4} + if t in sizes: + eq.require(len(p) == sizes[t], 'component count') + integer = t in (6, 8, 10, 13) + eq.require(all(x and x[0] == (2 if integer else 3) for x in p), 'component type') + elif t in (30, 31, 32, 33, 34): + expected = {30: 2, 31: 2, 32: 3, 33: 3, 34: 4}[t] + eq.require(all(x and x[0] == expected for x in p), 'packed element type') + else: + eq.require(all(x and x[0] == {35: 5, 36: 9, 37: 20, 38: 12}[t] for x in p), 'packed vector type') + pending.extend(p) + return node + + +class S5(unittest.TestCase): + def setUp(self): + eq.reset_blobs() + self.root = s5_root() + eq.add_blob_root(self.root) + + def tearDown(self): + eq.reset_blobs() + shutil.rmtree(self.root) + + def record(self, tree): + return {'tree': {'blob': put_blob(self.root, eq.json_bytes(tree))}, 'tree_sha': eq.tree_sha(tree), + 'raw_bytes_sha': 'a'*64, 'roundtrip_ok': True} + + def test_blob_transport_is_verified_and_bound(self): + tree = s5_state([event()]) + record = self.record(tree) + loaded = eq._transport(record, None) + self.assertEqual(list(loaded), tree) + self.assertEqual(eq.tree_sha(loaded), eq.tree_sha(tree)) + for name, mutate in [('tree_sha', lambda r: r.update(tree_sha='b'*64)), ('roundtrip', lambda r: r.update(roundtrip_ok=False)), + ('raw', lambda r: r.update(raw_bytes_sha='x')), ('extra', lambda r: r.update(diff=[])), + ('ref', lambda r: r['tree'].update(extra=1)), ('missing', lambda r: r['tree'].update(blob='c'*64))]: + bad = copy.deepcopy(record); mutate(bad) + with self.subTest(name=name), self.assertRaises((eq.EvidenceError, KeyError)): + eq._transport(bad, None) + digest = record['tree_sha'] + for name, content in [('changed', gzip.compress(eq.json_bytes(s5_state()))), ('not gzip', b'not gzip'), + ('float', gzip.compress(b'[3,1.5]')), ('object', gzip.compress(b'[27,{"a":1},null]'))]: + eq.reset_blobs(); eq.add_blob_root(self.root) + (self.root/(digest+'.gz')).write_bytes(content) + with self.subTest(name=name), self.assertRaises(eq.EvidenceError): + eq._transport(record, None) + for content in (b'[3,1.5]', b'[27,{"a":1},null]'): + other = put_blob(self.root, content) + with self.subTest(content=content), self.assertRaises(eq.EvidenceError): + eq.blob_tree(other) + + def test_every_checkpoint_full_tree_verified_like_inline(self): + """S5 drops the diff chain: each checkpoint carries a complete tree, verified alone.""" + value = s2_report() + for i, cp in enumerate(value['checkpoints']): + state = cp['S']['tree'] + state[1] = [pair for pair in state[1] if pair[0][1] != 'value'] + [[[4, 'value'], arr([2, i])]] + cp['S'] = transport(state); cp['latest'] = transport(state) + inline_joined, inline_proofs = checker.join_report(value) + self.assertTrue(checker.check_report(value, measurement(value))['ok']) + blobbed = as_blobs(value, self.root) + self.assertEqual(len(list(self.root.iterdir())), 31) + joined, proofs = checker.join_report(blobbed) + self.assertEqual(eq.json_bytes(proofs), eq.json_bytes(inline_proofs)) + self.assertEqual([cp['harness_normalized_digest'] for cp in joined['checkpoints']], + [cp['harness_normalized_digest'] for cp in inline_joined['checkpoints']]) + self.assertTrue(checker.check_report(blobbed, measurement(blobbed))['ok']) + self.assertTrue(eq.compare_reports(joined, inline_joined)['ok']) + for index in range(31): + digest = blobbed['checkpoints'][index]['S']['tree_sha'] + original = (self.root/(digest+'.gz')).read_bytes() + other = copy.deepcopy(value['checkpoints'][index]['S']['tree']); other[1][-1][1][1][0][1] = 999 + (self.root/(digest+'.gz')).write_bytes(gzip.compress(eq.json_bytes(other))) + eq.reset_blobs(); eq.add_blob_root(self.root) + with self.subTest(index=index): + self.assertFalse(checker.check_report(blobbed, measurement(blobbed))['ok']) + (self.root/(digest+'.gz')).write_bytes(original) + eq.reset_blobs(); eq.add_blob_root(self.root) + self.assertTrue(checker.check_report(blobbed, measurement(blobbed))['ok']) + + def test_fast_normalization_equals_original(self): + root = '/private/a' + cases = { + 'identity': s5_state(), + 'events': s5_state([event(root), event(root, kind='SAVE_LOAD_FAILED', duration=9)]), + 'outside timing name': s5_state([event(root)], extra=d(wait_us=[2, 5])), + 'outside profile string': s5_state([event(root)], extra=[4, root+'/x']), + 'profile in key': s5_state([event(root)], extra=d(**{root+'/k': [2, 1]})), + 'save_service elsewhere': s5_state([event(root)], extra=[4, 'save_service']), + 'non-save event': s5_state([event(root, source='other')]), + } + for name, tree in cases.items(): + eq.reset_blobs(); eq.add_blob_root(self.root) + with self.subTest(name=name): + expected, expected_side = eq._normalize([copy.deepcopy(tree)], profile(root), False) + loaded = eq._transport(self.record(tree), None) + normalized, side = eq.normalize_tree(loaded, profile(root)) + self.assertEqual(eq.json_bytes(eq.materialize(normalized)), eq.json_bytes(expected[0])) + self.assertEqual(eq.json_bytes(side), eq.json_bytes(expected_side)) + self.assertEqual(eq.tree_sha(normalized), eq.tree_sha(expected[0])) + restored = eq.restore_tree(normalized, side, profile(root)) + self.assertEqual(eq.tree_sha(restored), eq.tree_sha(tree)) + if side['entries']: + forged = copy.deepcopy(side); forged['entries'].pop() + with self.assertRaises(eq.EvidenceError): eq.restore_tree(normalized, forged, profile(root)) + token = s5_state([event(root)], extra=[4, eq.TOKEN+'x']) + for value in (token, s5_state([event(root)])): + if value is token: + with self.assertRaises(eq.EvidenceError): eq._normalize([copy.deepcopy(value)], profile(root), False) + with self.assertRaises(eq.EvidenceError): eq.normalize_tree(eq._transport(self.record(value), None), profile(root)) + broken = s5_state() + checker.node_at(broken, 'systems', 'runtime', 'domain_events')[1][1][1] = d() + with self.assertRaisesRegex(eq.EvidenceError, 'recent_events array required'): + eq.normalize_tree(eq._transport(self.record(broken), None), profile(root)) + + def test_compare_and_digest_equal_s1_reference(self): + a = s5_state([event()], extra=d(z=[2, 1], y=d(b=[4, 'v'], a=[21, 'v']))) + variants = {'same': copy.deepcopy(a)} + b = copy.deepcopy(a); b[1].reverse(); variants['dict order'] = b + c = copy.deepcopy(a); checker.node_at(c, 'extra', 'y', 'a')[0] = 4; variants['value type'] = c + k = copy.deepcopy(a); checker.node_at(k, 'extra')[1][1][0] = [21, 'y']; variants['key type'] = k + m = copy.deepcopy(a); checker.node_at(m, 'systems', 'runtime', 'vectors')[2] = [[2, 10], [21, ''], [0]]; variants['metadata'] = m + n = copy.deepcopy(a); checker.node_at(n, 'systems', 'runtime', 'vectors')[1].append([2, 3]); variants['array length'] = n + v = copy.deepcopy(a); checker.node_at(v, 'systems', 'runtime', 'vectors')[1][0][1][2] = [3, '0000000000000840']; variants['vector'] = v + for name, other in variants.items(): + with self.subTest(name=name): + expected = reference_compare_trees(a, other) + self.assertEqual(eq.json_bytes(eq.compare_trees(a, other)), eq.json_bytes(expected)) + left, right = eq._transport(self.record(a), None), eq._transport(self.record(other), None) + self.assertEqual(eq.json_bytes(eq.compare_trees(left, right)), eq.json_bytes(expected)) + self.assertEqual(checker.normalized_digest(other), reference_digest(other)) + self.assertEqual(checker.normalized_digest(right), reference_digest(other)) + self.assertEqual(eq.exact(left, right), reference_exact(a, other)) + + def test_path_copy_builders_equal_deepcopy_reference(self): + b1 = s5_state([event()]) + frozen = eq.json_bytes(b1) + for kind in checker.E3_KINDS: + with self.subTest(kind=kind): + self.assertEqual(eq.json_bytes(checker.e3_expected_input(b1, kind)), eq.json_bytes(reference_expected_input(b1, kind))) + loaded = eq._transport(self.record(b1), None) + for kind in checker.E3_KINDS: + self.assertEqual(eq.json_bytes(checker.e3_expected_input(loaded, kind)), eq.json_bytes(reference_expected_input(b1, kind))) + new_event = event(); checker.node_at(new_event, 'event_id')[1] = 'domain_event.000000000004' + for before in (b1, s5_state([event()]*256)): + got, dropped = checker.e3_x(before, new_event) + want, want_dropped = reference_x(before, new_event) + self.assertEqual(eq.json_bytes([got, dropped]), eq.json_bytes([want, want_dropped])) + self.assertEqual(eq.json_bytes(b1), frozen) + self.assertEqual(eq.json_bytes(loaded), frozen) + + def test_event_stream_replacement_is_existing_defect_not_pass(self): + ev = event(); checker.node_at(ev, 'event_id')[1] = 'domain_event.000000000004' + fact = {'replaced': True, 'new_stream_subscribers_before': [], 'recovered_event_ids': ['domain_event.000000000004']} + defects = checker.stream_defects(fact, [ev]) + self.assertEqual([x['kind'] for x in defects], ['event_stream_replaced_subscribers_not_carried']) + self.assertEqual(checker.stream_defects({'replaced': False}, []), []) + for bad in [dict(fact, recovered_event_ids=['missing']), dict(fact, recovered_event_ids=['domain_event.000000000004']*2), + dict(fact, new_stream_subscribers_before=['*/p28_eq_observer']), {'replaced': False, 'extra': 1}, + {'replaced': True}, None, dict(fact, extra=1)]: + with self.subTest(bad=bad), self.assertRaises((eq.EvidenceError, KeyError, TypeError, AttributeError)): + checker.stream_defects(bad, [ev]) + raw, evidence, previous = e45_fixture('O') + index = [e['id'] for e in evidence].index('E4/restore_snapshot') + evidence[index]['detail']['event_stream'] = {'replaced': True, 'new_stream_subscribers_before': [], 'recovered_event_ids': []} + raw['scenarios'][18+index]['result']['facts'] = checker.e45_facts(evidence[index]['detail']) + outcome = checker.check_e45(raw, evidence, previous)[index] + self.assertEqual(outcome['status'], 'existing-defect') + self.assertEqual(outcome['defects'][0]['kind'], 'event_stream_replaced_subscribers_not_carried') + + def test_lifecycle_binds_replacements_guard_text_and_blobs(self): + with synthetic_directory() as name: + directory = Path(name) + row = s4_phase_fixture(directory) + evidence = directory/row['phase']/'evidence' + raw = verifier.read(evidence/'report.json'); life = verifier.read(evidence/'lifecycle.json') + guard = verifier.read(directory/(row['phase']+'-guard.json')) + self.assertTrue(checker.check_lifecycle(raw, life, guard)) + bad = copy.deepcopy(life); bad['event_stream_replacements'] = [{'replaced': True}] + with self.assertRaisesRegex(eq.EvidenceError, 'event stream replacement record differs'): + checker.check_lifecycle(raw, bad, guard) + text = (directory/(row['phase']+'-guard.json')).read_text() + good = copy.deepcopy(life); good['guard']['receipt_text'] = text + good['guard']['receipt'] = json.loads(text.replace('"conditions_checked": 5', '"conditions_checked": 5.0')) + self.assertTrue(checker.check_lifecycle(raw, good, guard)) + for changed in (text.replace('"conditions_checked": 5', '"conditions_checked": 5.0'), text + ' '): + bad = copy.deepcopy(good); bad['guard']['receipt_text'] = changed + with self.subTest(changed=changed[-20:]), self.assertRaises(eq.EvidenceError): + checker.check_lifecycle(raw, bad, guard) + verifier.phase_evidence(directory, row) + blobs = evidence/'blobs'; blobs.mkdir() + extra = put_blob(blobs, b'extra') + moved = dict(row, evidence_files=verifier.inventory(evidence, seals=True)) + with self.assertRaisesRegex(eq.EvidenceError, 'blob inventory differs'): + verifier.phase_evidence(directory, moved) + (blobs/(extra+'.gz')).unlink(); (blobs/'not-a-blob.gz').write_bytes(b'x') + with self.assertRaisesRegex(eq.EvidenceError, 'unexpected evidence blob name'): + verifier.phase_evidence(directory, dict(row, evidence_files=verifier.inventory(evidence, seals=True))) + + def test_manifest_numbers_keep_their_type(self): + package = e3_package_fixture('missing_key') + self.assertTrue(checker.e3_package_check(package, 'missing_key')) + import base64 + changed = b'{"format_version":1.0}' + package['modified']['manifest.json'] = {'bytes': base64.b64encode(changed).decode(), 'sha256': checker.sha(changed)} + with self.assertRaisesRegex(eq.EvidenceError, 'manifest mutation rule'): + checker.e3_package_check(package, 'missing_key') + blobbed = e3_package_fixture('missing_key') + for side in ('original', 'modified', 'after_operation'): + for name, item in blobbed[side].items(): + if item is not None: + content = base64.b64decode(item['bytes']) + item['bytes'] = {'blob': put_blob(self.root, content)} + self.assertTrue(checker.e3_package_check(blobbed, 'missing_key')) + + def test_signed_instance_ids_raw_kept_and_excluded(self): + value = s2_report() + for cp in value['checkpoints']: + cp['C'].update(catalog_instance_id='-9223371962598816238', current_catalog_instance_id='-9223371962598816238') + self.assertTrue(checker.check_report(value, measurement(value))['ok']) + other = copy.deepcopy(value) + for cp in other['checkpoints']: + cp['C'].update(catalog_instance_id='-1', current_catalog_instance_id='-1') + joined_a, _ = checker.join_report(value); joined_b, _ = checker.join_report(other) + result = eq.compare_reports(joined_a, joined_b) + self.assertTrue(result['ok']) + self.assertIn({'path': ['checkpoints', 0, 'C', 'catalog_instance_id'], 'reason': 'process-local instance ID', + 'a': '-9223371962598816238', 'b': '-1'}, result['excluded']) + for cp in value['checkpoints']: + cp['C'].update(catalog_instance_id='-0x1') + self.assertFalse(checker.check_report(value, measurement(value))['ok']) + + def test_publish_pairs_bound_to_source_causes(self): + def pair(minute, counter, commands): + return [{'signal': 'snapshot_published', 'minute': minute, 'event_counter': counter, 'command_counter': commands}, + {'signal': 'state_updated', 'minute': minute, 'event_counter': counter, 'command_counter': commands}] + # R minute 648 shape: paused submits each publish after their command events; tick end last. + events = {4: ('GUEST_STATE_CHANGED', 634, None), 5: ('COMMAND_COMPLETED', 634, 1), 6: ('COMMAND_COMPLETED', 634, 2), + 7: ('GUEST_STATE_CHANGED', 634, None), 8: ('COMMAND_FAILED', 634, 3)} + good = pair(633, 3, 1) + pair(634, 5, 2) + pair(634, 6, 3) + pair(634, 8, 4) + pair(634, 8, 4) + command, other = checker.check_publishes(good, events, 3, 8, 1, 4) + self.assertEqual(command, [(634, 5), (634, 6), (634, 8)]) + self.assertEqual(other, [(633, 3), (634, 8)]) + bad = { + 'missing adjacent command publish': pair(633, 3, 1) + pair(634, 6, 3) + pair(634, 8, 4) + pair(634, 8, 4), + 'missing first command publish': pair(633, 3, 1) + pair(634, 6, 3) + pair(634, 8, 4) + pair(634, 8, 4)[:0] + pair(634, 8, 4), + 'unpublished submit': pair(633, 3, 1) + pair(634, 5, 2) + pair(634, 6, 3), + 'submit without publish before tick': pair(633, 3, 2) + pair(634, 5, 2) + pair(634, 6, 3) + pair(634, 8, 4) + pair(634, 8, 4), + 'odd signal': good[:-1], + 'swapped pair': good[:2] + [good[3], good[2]] + good[4:], + 'pair across minutes': pair(633, 3, 1) + [good[2], dict(good[3], minute=635)] + good[4:], + 'counter mismatch in pair': pair(633, 3, 1) + [good[2], dict(good[3], event_counter=6)] + good[4:], + 'order': pair(634, 5, 2) + pair(633, 3, 1) + good[4:], + 'outside interval': good + pair(634, 9, 4), + 'missing fields': [{'signal': s['signal'], 'minute': s['minute']} for s in good], + } + for name, value in bad.items(): + with self.subTest(name=name): + try: + command, other = checker.check_publishes(value, events, 3, 8, 1, 4) + except (eq.EvidenceError, KeyError, TypeError): + continue + self.fail('accepted: %s -> %r %r' % (name, command, other)) + # A missing tick-end publish leaves the command publishes intact; the caller's count of + # tick/restore publishes (one per measured minute) rejects it. + command, other = checker.check_publishes(pair(633, 3, 1) + pair(634, 5, 2) + pair(634, 6, 3) + pair(634, 8, 4), events, 3, 8, 1, 4) + self.assertEqual((len(command), other), (3, [(633, 3)])) + # In the measurement the remaining publishes are exactly one tick end per minute. + value = s2_report() + self.assertTrue(checker.check_report(value, measurement(value))['ok']) + for name, mutate in [('extra tick publish', lambda rows: rows.__setitem__(slice(2, 2), pair(634, 3, 1))), + ('missing tick publish', lambda rows: rows.__delitem__(slice(2, 4)))]: + broken = s2_report(); mutate(broken['signal_order']) + with self.subTest(name=name): + self.assertFalse(checker.check_report(broken, measurement(broken))['ok']) + + def test_labelled_harness_digest_falls_back_to_dictionary_order_only(self): + def joined(tree): + value = report(tree) + for cp in value['checkpoints']: + cp['harness_normalized_digest'] = None + return checker.join_report(value)[0] + state = snapshot([event()]) + reordered = copy.deepcopy(state); reordered[1].reverse() + a, b = joined(state), joined(reordered) + self.assertTrue(all(cp['harness_normalized_digest'].startswith(eq.HARNESS_LABEL) for cp in a['checkpoints'])) + self.assertNotEqual(a['checkpoints'][0]['harness_normalized_digest'], b['checkpoints'][0]['harness_normalized_digest']) + result = eq.compare_reports(a, b) + self.assertTrue(result['ok'], result['differences'][:2]) + self.assertIn('harness canonical digest (dictionary order only)', [m['mode'] for m in result['digest_modes']]) + self.assertTrue(result['dict_order_paths']) + changed = copy.deepcopy(state); checker.node_at(changed, 'value')[1][0] = [2, 2] + result = eq.compare_reports(a, joined(changed)) + self.assertFalse(result['ok']) + self.assertIn(['checkpoints', 0, 'harness_normalized_digest'], [d['path'] for d in result['differences']]) + + def test_memo_scope_same_results_and_restores_gc(self): + import gc + value, evidence, b1 = e3_fixture() + plain = checker.check_report(value, measurement(value), evidence, b1) + self.assertTrue(gc.isenabled()) + with checker.memo_scope(): + self.assertFalse(gc.isenabled()) + first = checker.check_report(value, measurement(value), evidence, b1) + second = checker.check_report(value, measurement(value), evidence, b1) + self.assertTrue(gc.isenabled()) + self.assertEqual(eq.json_bytes(plain), eq.json_bytes(first)) + self.assertEqual(eq.json_bytes(first), eq.json_bytes(second)) + broken = copy.deepcopy(value); broken['scenarios'][0]['result']['code_reason'] = 'invented' + with checker.memo_scope(): + checker.check_report(value, measurement(value), evidence, b1) + self.assertFalse(checker.check_report(broken, measurement(broken), evidence, b1)['ok']) + + def test_blob_trees_get_the_same_full_validation_as_inline(self): + invalid = { + 'bool as int': [2, True], 'bool payload': [1, True], 'object tag': [24, 0], 'callable tag': [25, 0], + 'nil arity': [0, 1], 'int arity': [2], 'dict arity': [27, []], 'array arity': [28, [], None, None], + 'float text': [3, '1.0'], 'base64': [29, 'not base64!'], 'scripted metadata': [28, [], [[2, 2], [21, ''], [2, 1]]], + 'nested bool': [27, [[[4, 'k'], [2, False]]], None], 'duplicate key': [27, [[[4, 'k'], [0]], [[4, 'k'], [0]]], None], + 'vector component': [9, [[2, 1], [2, 2], [2, 3]]], + } + for name, tree in invalid.items(): + with self.subTest(name=name): + with self.assertRaises(eq.EvidenceError): eq.validate_tree(copy.deepcopy(tree)) + digest = put_blob(self.root, json.dumps(tree, separators=(',', ':')).encode()) + record = {'tree': {'blob': digest}, 'tree_sha': digest, 'raw_bytes_sha': 'a'*64, 'roundtrip_ok': True} + for attempt in range(2): + with self.assertRaises(eq.EvidenceError): eq._transport(record, None) + with self.assertRaises(eq.EvidenceError): eq._transport_ref(record) + with self.assertRaises(eq.EvidenceError): eq.known_sha(eq.TreeRef(digest)) + self.assertNotIn(digest, eq._VALID_BLOBS) + good, fake = [2, 1], [2, True] + good_record = self.record(good) + fake_digest = put_blob(self.root, b'[2,true]') + fake_ref = eq.TreeRef(fake_digest) + with self.assertRaises(eq.EvidenceError): eq.exact(fake_ref, eq._transport(good_record, None)) + with self.assertRaises(eq.EvidenceError): eq.same_tree(fake_ref, eq.TreeRef(fake_digest)) + with self.assertRaises(eq.EvidenceError): eq.validate_tree(fake_ref) + self.assertTrue(eq.exact(eq._transport(good_record, None), eq._transport_ref(good_record))) + + def test_validate_tree_equals_s1_reference_on_mutations(self): + class Lcg: + # Deterministic generator; the EQ import closure has no random module. + def __init__(self, seed): self.state = seed + def randrange(self, n): + self.state = (self.state * 6364136223846793005 + 1442695040888963407) % 2**64 + return (self.state >> 33) % n + def choice(self, values): return values[self.randrange(len(values))] + base = d(a=arr([2, 1], [3, '000000000000f03f'], [4, 's'], [21, 'n']), + b=[9, [[3, '0000000000000000'], [3, '000000000000f03f'], [3, '0000000000000040']]], + c=[10, [[2, 1], [2, 2], [2, 3]]], e=[30, [[2, 1], [2, 2]]], f=[35, [[5, [[3, '0000000000000000'], [3, '0000000000000000']]]]], + g=[28, [[2, 1]], [[2, 2], [21, ''], [0]]], h=[29, 'AA=='], i=[1, 1], j=[0], k=[22, 'np'], + l=[27, [[[2, 1], [0]], [[21, 'x'], [0]]], [[[2, 2], [21, ''], [0]], [[2, 0], [21, ''], [0]]]]) + def outcome(function, value): + try: + function(value) + return 'ok' + except Exception as error: + return type(error).__name__ + ':' + str(error) + def mutate(node): + choice = rng.randrange(9) + if not node: + node.append(rng.choice([0, 2, 'x', None])); return + if choice == 0: node[0] = rng.choice([24, 25, 99, -1, 0, 1, 2, 3, 4, 9, 10, 27, 28, 30, 35, True, '2']) + elif choice == 1: node.append(None) + elif choice == 2: node[-1] = rng.choice([True, False, 1.5, 'zz', [], None, 2**64, [0]]) + elif choice == 3: del node[-1] + elif choice == 4 and len(node) > 1: node[1] = rng.choice([True, 1.5, 'x', [], [[4, 'a']], [[2, 1], [2, 1]], 2**63, 'AA==', '000000000000f03f']) + elif choice == 5: node.clear() + elif choice == 6 and len(node) > 1 and isinstance(node[1], list) and node[1]: node[1].append(copy.deepcopy(node[1][0])) + elif choice == 7 and len(node) > 2: node[2] = rng.choice([[[2, 2], [21, ''], [0]], [[2, 2], [21, ''], [2, 1]], [], 'x', None]) + else: node.insert(0, 3) + rng = Lcg(20261022) + seen = set() + for case in range(4000): + value = copy.deepcopy(base); pool = [] + def collect(n): + if isinstance(n, list): + pool.append(n) + for c in n: collect(c) + collect(value) + for _ in range(rng.choice((1, 1, 2, 3))): + mutate(rng.choice(pool)) + expected = outcome(reference_validate, copy.deepcopy(value)) + seen.add(expected.split(':')[-1]) + self.assertEqual(outcome(eq.validate_tree, value), expected, case) + self.assertGreater(len(seen), 12) + + def test_probe_static_full_tree_blob_and_stream_requirements(self): + probe = (verifier.HERE/'eq_probe.gd').read_text() + self.assertTrue(checker.check_probe(probe)['ok']) + for old, new in [('var snapshot_value: Dictionary = runtime.create_snapshot()', 'var snapshot_value: Dictionary = last_snapshot_value'), + ('var s: Dictionary = transport(snapshot_value)', 'var s: Dictionary = {}'), + ('"tree": store_blob(text)', '"tree": {"blob": hashed(text)}'), + ('refuse blob overwrite', 'blob exists'), + ('packed.decompress_dynamic(-1, FileAccess.COMPRESSION_GZIP) == bytes', 'true'), + ('known_event_ids[str(event.event_id)] = true', 'pass'), + ('if known_event_ids.has(str(event.event_id)): continue', 'pass'), + ('demand(current.subscribe(&"*", &"p28_eq_observer", observe_event), "wildcard resubscription failed")', 'pass'), + (' detail["event_stream"] = follow_event_stream()\n detail["return"] = transport(load_return)', ' detail["return"] = transport(load_return)'), + (' var stream_fact: Dictionary = follow_event_stream()', ' var stream_fact: Dictionary = {"replaced": false}')]: + with self.subTest(old=old[:60]): + self.assertEqual(probe.count(old), 1) + self.assertFalse(checker.check_probe(probe.replace(old, new))['ok']) + + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/verify_eq.py b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/verify_eq.py index 240eee1..d22fe85 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/verify_eq.py +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/verify_eq.py @@ -5,6 +5,8 @@ import hashlib import json import os from pathlib import Path +import re +import subprocess import sys sys.dont_write_bytecode = True @@ -18,6 +20,16 @@ ROLES = {'R-A': 'R', 'R-B': 'R', 'O-A': 'O', 'O-B': 'O'} NAMES = {f'{prefix}-{i:02d}.json' for prefix, count in [('checkpoint', 31), ('observation', 31), ('e3', 18), ('e45', 21)] for i in range(count)} | { 'events.json', 'report.json', 'lifecycle.json', 'audio-close.json'} +BLOB_NAME = re.compile('blobs/[0-9a-f]{64}[.]gz') + + +def split_evidence(files): + """Fixed evidence names, and the S5 content-addressed blobs beside them.""" + blobs = {n: p for n, p in files.items() if n.startswith('blobs/')} + require(all(BLOB_NAME.fullmatch(n) for n in blobs), 'unexpected evidence blob name') + return {n: p for n, p in files.items() if n not in blobs}, blobs + + LOCAL_NAMES = {'run_eq.py', 'verify_eq.py', 'check_eq.py', 'compare_versions.py', 'eq_probe.gd', 'test_eq.py'} require = eq.require @@ -83,22 +95,35 @@ def check_audio(audio, pid): def phase_evidence(directory, row): """Recompute all S1-S3b checks from copied native bytes, with no cached verdicts.""" + with check.memo_scope(): + return _phase_evidence(directory, row) + + +def _phase_evidence(directory, row): directory = Path(directory) phase, role = row['phase'], row['role'] require(ROLES.get(phase) == role, 'phase/role binding') folder = directory / phase evidence = folder / 'evidence' files = inventory(evidence, seals=True) - require(set(files) == NAMES and files == row['evidence_files'], 'exact private evidence inventory') + fixed, blobs = split_evidence(files) + require(set(fixed) == NAMES and files == row['evidence_files'], 'exact private evidence inventory') + eq.add_blob_root(evidence / 'blobs') raw = check.read_report_stdout((folder / 'stdout.log').read_text()) require(raw == read(evidence / 'report.json') and raw['role'] == role, 'raw report/role copy') + eq.ACTIVE_PROFILES[:] = [raw['profile_root']] require(len(raw['scenarios']) == 39, '39 scenarios required') life = read(evidence / 'lifecycle.json') - require(life['stage'] == 'S3b', 'S3b lifecycle required') + require(life['stage'] == 'S5', 'S5 lifecycle required') + declared_blobs = life['blobs'] + require(type(declared_blobs) is dict and {'blobs/' + k + '.gz': {'bytes': b['gz_bytes'], 'sha256': b['gz_sha256']} + for k, b in declared_blobs.items()} == blobs, 'blob inventory differs') + for digest, item in sorted(declared_blobs.items()): + require(len(eq.blob_bytes(digest)) == item['bytes'], 'blob size differs: ' + digest) require(len(life['e3']) == 18 and len(life['e45']) == 21, 'scenario evidence coverage') declared = {r['path']: {'bytes': r['bytes'], 'sha256': r['sha256']} for r in life['files']} require(len(declared) == len(life['files']), 'duplicate lifecycle inventory') - expected = {'evidence/' + n: v for n, v in files.items() if n not in ('lifecycle.json', 'audio-close.json')} + expected = {'evidence/' + n: v for n, v in fixed.items() if n not in ('lifecycle.json', 'audio-close.json')} require(declared == expected, 'lifecycle inventory differs') guard_path = directory / (phase + '-guard.json') guard = read(guard_path) @@ -120,7 +145,47 @@ def phase_evidence(directory, row): return wire({'raw': raw, 'joined': joined, 'proofs': proofs, 'checker': checked}) -def recompute(directory, execution, collector, standard, diag): +def phase_worker(): + """--phase-worker: phase_evidence for one phase (JSON on stdin), result and state on stdout.""" + payload = json.load(sys.stdin) + with check.memo_scope(): + result = phase_evidence(Path(payload['directory']), payload['row']) + state = {'valid_blobs': sorted(eq._VALID_BLOBS), + 'normalized': [[key[0], key[1].decode('utf-8'), value] for key, value in eq._NORMALIZED.items()]} + json.dump({'result': result, 'state': state}, sys.stdout, ensure_ascii=False, allow_nan=False) + return 0 + + +def phase_results(directory, rows, parallel): + """phase_evidence for every role phase. In parallel mode each phase runs in its own + worker process of this same verification; the workers' validated blob SHAs and + normalization facts are then used here for the same-role comparisons, so blobs are + validated once. Results are identical to the sequential mode, which is the fallback.""" + if not parallel: + return {row['phase']: phase_evidence(directory, row) for row in rows} + try: + workers = [(row, subprocess.Popen([sys.executable, '-B', str(HERE / 'verify_eq.py'), '--phase-worker'], cwd=str(HERE), + stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)) for row in rows] + except OSError: + return phase_results(directory, rows, False) + for row, worker in workers: + worker.stdin.write(json.dumps({'directory': str(directory), 'row': row}, ensure_ascii=False).encode('utf-8')) + worker.stdin.close() + worker.stdin = None # every input is sent first, so all workers run at once + results = {} + for row, worker in workers: + out, err = worker.communicate() + require(worker.returncode == 0, 'phase worker failed: ' + row['phase'] + ': ' + err.decode('utf-8', 'replace')[-2000:]) + value = check.strict_json(out.decode('utf-8')) + results[row['phase']] = value['result'] + eq.add_blob_root(Path(directory) / row['phase'] / 'evidence' / 'blobs') + eq._VALID_BLOBS.update(value['state']['valid_blobs']) + for sha_, profile_json, fact in value['state']['normalized']: + eq._NORMALIZED.setdefault((sha_, profile_json.encode('utf-8')), tuple(fact)) + return {row['phase']: results[row['phase']] for row in rows} + + +def recompute(directory, execution, collector, standard, diag, parallel=False): """Validate owned receipts and recompute every comparison from raw evidence.""" directory = Path(directory) require(execution['passed'] is True and execution['error'] is None and execution['cleanup_errors'] == [], 'execution failed') @@ -149,7 +214,7 @@ def recompute(directory, execution, collector, standard, diag): require(execution['pins_after'] == admission['pins'], 'pin preservation') rows = execution['phases'] require([r['phase'] for r in rows] == PHASES, 'seven phases in order') - pids, profiles, joined, results = [], [], {}, {} + pids, profiles, evidence_rows = [], [], [] previous = source for i, row in enumerate(rows): phase = row['phase'] @@ -201,11 +266,12 @@ def recompute(directory, execution, collector, standard, diag): require(row['role'] == ROLES[phase] and row['runtime_profile'] == command['runtime_profile'] and row['runtime_name'] == command['runtime_name'], 'runtime/role binding') collector.guard_gate(row['guard'], Path(row['runtime_profile']), row['runtime_name']) - results[phase] = phase_evidence(directory, row) - joined[phase] = results[phase]['joined'] + evidence_rows.append(row) else: require(row['role'] is None, 'parse/import role') require('P28_02_EQ_REPORT=' not in (directory / phase / 'stdout.log').read_text(), 'parse/import report') + results = phase_results(directory, evidence_rows, parallel) + joined = {phase: value['joined'] for phase, value in results.items()} require(len(set(pids)) == 7 and len(set(profiles)) == 14, 'PID/profile reuse') require({r['pid'] for r in execution['cleanup']} == set(pids) and all( r['engine_ended'] is True and r['outer_cleanup_errors'] == [] and @@ -228,7 +294,7 @@ def verify(project_root, directory): admission = execution['admission'] require(actual_pins(project_root, Path(admission['readonly_path']), Path(admission['fixture']), Path(admission['engine']), collector, standard) == admission['pins'], 'actual input/source/EQ pins differ') - result = recompute(directory, execution, collector, standard, diag) + result = recompute(directory, execution, collector, standard, diag, parallel=True) require(result == read(directory / 'results.json'), 'recomputed results differ') for phase, values in result['phases'].items(): for name, value in values.items(): @@ -237,12 +303,15 @@ def verify(project_root, directory): def main(): + if sys.argv[1:] == ['--phase-worker']: + return phase_worker() parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('--project-root', type=Path, required=True) args = parser.parse_args() try: require(os.environ.get('BUILD_OUTPUT_DIR'), 'BUILD_OUTPUT_DIR required') - result = verify(args.project_root, Path(os.environ['BUILD_OUTPUT_DIR']) / 'p28-02-eq-evidence') + with check.memo_scope(): + result = verify(args.project_root, Path(os.environ['BUILD_OUTPUT_DIR']) / 'p28-02-eq-evidence') print(json.dumps({'status': 'verified', 'result': result}, ensure_ascii=False, allow_nan=False)) return 0 except (ValueError, OSError, KeyError, TypeError, IndexError) as error: From a46418d064ebf8c8e03043bae50c29ac174b5472 Mon Sep 17 00:00:00 2001 From: Agent Control Runner Date: Thu, 22 Oct 2026 04:31:20 +0900 Subject: [PATCH 3/4] =?UTF-8?q?P28-02-EQ:=20=E6=84=8F=E5=91=B3=E3=82=92?= =?UTF-8?q?=E4=BF=9D=E3=81=A4=E8=BB=BD=E9=87=8F=E5=8C=96=EF=BC=9A=E5=90=8C?= =?UTF-8?q?=E7=AD=89=E6=80=A7=E3=81=AE=E5=85=88=E8=A1=8C=E5=9B=BA=E5=AE=9A?= =?UTF-8?q?=EF=BC=88harness=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../execution/p28-02/eq/IMPLEMENTATION.md | 14 ++ .../execution/p28-02/eq/PROGRESS.md | 20 +++ .../execution/p28-02/eq/UNIT_OUTPUT.sha256 | 2 +- .../execution/p28-02/eq/UNIT_OUTPUT.txt | 3 +- .../eq/UNIT_OUTPUT_S5_ATTEMPT_06.sha256 | 1 + .../p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_06.txt | 168 ++++++++++++++++++ .../eq/UNIT_OUTPUT_S5_SEATBELT_06.sha256 | 1 + .../p28-02/eq/UNIT_OUTPUT_S5_SEATBELT_06.txt | 168 ++++++++++++++++++ .../execution/p28-02/eq/run_eq.py | 44 ++++- .../execution/p28-02/eq/test_eq.py | 28 ++- .../execution/p28-02/eq/verify_eq.py | 9 +- 11 files changed, 450 insertions(+), 8 deletions(-) create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_06.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_06.txt create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_SEATBELT_06.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_SEATBELT_06.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/IMPLEMENTATION.md b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/IMPLEMENTATION.md index a2166f3..875f8c1 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/IMPLEMENTATION.md +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/IMPLEMENTATION.md @@ -707,3 +707,17 @@ limit is kept; the Runner configuration is not changed. parsed and memoized by SHA; restore uses the memoized skeleton, so join and comparison do not parse again. compare_trees records nodes shared with the immutable trees instead of deep copies; keys use inline text. + +### Self-contained bundle for the sandboxed native-verify (repair 11) + +The formal p28-02-eq-native-verify runs under the Runner seatbelt, which denies reading data +under the home directory except the validation checkout and the task runtime (the bundle is in +the runtime's BUILD_OUTPUT_DIR). The first S5 validation failed on the fixture for this reason. +run_eq now copies the fixture to inputs/fixture/ and the read-only manifest with its nine +destinations to inputs/readonly/ before any phase, and checks the copies against the admission +pins (bundle_inputs); the seal covers them. verify_eq passes those copies to actual_pins +(bundled_inputs applies collector.inputs' rule: each manifest destination lies in the original +read-only directory and its copy has the recorded bytes and SHA). The engine (/Applications) and +the machine model stay read live. Everything else verify_eq recomputes from the bundle and the +checkout as before. + diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/PROGRESS.md b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/PROGRESS.md index 926e7de..324a62e 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/PROGRESS.md +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/PROGRESS.md @@ -38,6 +38,26 @@ Submission goes through the normal Runner submit, which makes the commit. 正式 fixture event uses a domain_event ID. All other earlier test bodies and raw outputs are unchanged; 15 S5 tests were added. +- Repair 11 (after the first S5 submission b2dbda8c956643a2a972e8bcf7416038a3f70b2c): + - Its exact-S native passed: driver exit 0, execution passed, cleanup errors empty, + R-A/R-B and O-A/O-B compared with 0 differences, sealed (native-b2dbda8-r01, 5954 files). + This exercised the whole S5 driver path on real data. + - Its formal validation (report c02eda130f6c49e6bcf2ec4a7c1e8f69): p28-02-eq-unit passed + (161 tests); p28-02-eq-native-verify failed, exit 1, 'Operation not permitted' on the + fixture. The Runner validation seatbelt cannot read data under the home directory outside + the checkout and the task runtime, and verify_eq read the original fixture and read-only + inputs. Kept as a failure; the b2dbda8 bundle is retained but not reused. + - Fix: run_eq seals copies of the fixture and the nine read-only inputs inside the bundle + after checking them against the admission pins; verify_eq recomputes the pins from the + checkout and those sealed copies by the same rules (bundled_inputs). No permission, + policy, timeout or Runner configuration change. + - Final unit evidence for repair 11: UNIT_OUTPUT_S5_ATTEMPT_06 (162 tests OK in 120.853 s, + Python exit 0, outer 120.983 s; same bytes as UNIT_OUTPUT.txt, SHA-256 + 846ab3b45705f269a81181c818dc5e3b8bc0057863794d59e8d641fe5a4e4c32) and + UNIT_OUTPUT_S5_SEATBELT_06 (the same suite under the Runner validation seatbelt profile, + run locally: 162 tests OK in 120.930 s, Python exit 0). Local runs are not formal + validation. + Next: Runner submit → exact-S native 7 phases → bundle → p28-02-eq-unit and p28-02-eq-native-verify → fresh independent Opus review of all 6 conditions → normal qualification, approval, integration and final → OPT/whole-unit. 23/88、4/30は不変。 diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT.sha256 index f23b81d..f1c3997 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT.sha256 +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT.sha256 @@ -1 +1 @@ -7372a382cc2f3c090013874d8f28f17cad4cb1b965ad86c86de7a21fc2d851a8 UNIT_OUTPUT.txt +846ab3b45705f269a81181c818dc5e3b8bc0057863794d59e8d641fe5a4e4c32 UNIT_OUTPUT.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT.txt index 5cbff21..241027d 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT.txt +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT.txt @@ -134,6 +134,7 @@ test_missing_sidecar_rejected_after_seal (__main__.S4StoredResultBindings.test_m test_raw_joined_substitution_rejected_after_seal (__main__.S4StoredResultBindings.test_raw_joined_substitution_rejected_after_seal) ... ok test_blob_transport_is_verified_and_bound (__main__.S5.test_blob_transport_is_verified_and_bound) ... ok test_blob_trees_get_the_same_full_validation_as_inline (__main__.S5.test_blob_trees_get_the_same_full_validation_as_inline) ... ok +test_bundled_inputs_replace_unreadable_originals (__main__.S5.test_bundled_inputs_replace_unreadable_originals) ... ok test_compare_and_digest_equal_s1_reference (__main__.S5.test_compare_and_digest_equal_s1_reference) ... ok test_event_stream_replacement_is_existing_defect_not_pass (__main__.S5.test_event_stream_replacement_is_existing_defect_not_pass) ... ok test_every_checkpoint_full_tree_verified_like_inline (__main__.S5.test_every_checkpoint_full_tree_verified_like_inline) @@ -162,6 +163,6 @@ test_nonstring_keys_keep_types_and_values (__main__.TypedTrees.test_nonstring_ke test_unsupported_and_malformed (__main__.TypedTrees.test_unsupported_and_malformed) ... ok ---------------------------------------------------------------------- -Ran 161 tests in 121.627s +Ran 162 tests in 120.853s OK diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_06.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_06.sha256 new file mode 100644 index 0000000..690fd1a --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_06.sha256 @@ -0,0 +1 @@ +846ab3b45705f269a81181c818dc5e3b8bc0057863794d59e8d641fe5a4e4c32 UNIT_OUTPUT_S5_ATTEMPT_06.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_06.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_06.txt new file mode 100644 index 0000000..241027d --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_ATTEMPT_06.txt @@ -0,0 +1,168 @@ +test_all_operations (__main__.Diffs.test_all_operations) ... ok +test_invalid_operations (__main__.Diffs.test_invalid_operations) ... ok +test_reconstruction_and_proofs (__main__.Diffs.test_reconstruction_and_proofs) ... ok +test_attempt_to_normalize_violation_rejected (__main__.Normalization.test_attempt_to_normalize_violation_rejected) ... ok +test_environment_values_differ_but_normal_form_equal (__main__.Normalization.test_environment_values_differ_but_normal_form_equal) ... ok +test_every_save_event_reversible (__main__.Normalization.test_every_save_event_reversible) ... ok +test_f3_keeps_relative_paths_and_words (__main__.Normalization.test_f3_keeps_relative_paths_and_words) ... ok +test_guard_mismatch (__main__.Normalization.test_guard_mismatch) ... ok +test_nested_lookalike_is_not_eligible (__main__.Normalization.test_nested_lookalike_is_not_eligible) ... ok +test_original_transport_sha_detects_forged_timing (__main__.Normalization.test_original_transport_sha_detects_forged_timing) ... ok +test_partial_timing_payload_rejected (__main__.Normalization.test_partial_timing_payload_rejected) ... ok +test_prefix_boundary_and_reserved_token (__main__.Normalization.test_prefix_boundary_and_reserved_token) ... ok +test_sidecar_missing_duplicate_and_forged_paths (__main__.Normalization.test_sidecar_missing_duplicate_and_forged_paths) ... ok +test_snapshot_and_latest_reversible (__main__.Normalization.test_snapshot_and_latest_reversible) ... ok +test_snapshot_event_outside_recent_is_not_eligible (__main__.Normalization.test_snapshot_event_outside_recent_is_not_eligible) ... ok +test_wrong_event_and_source_are_preserved (__main__.Normalization.test_wrong_event_and_source_are_preserved) ... ok +test_wrong_timing_type_and_negative (__main__.Normalization.test_wrong_timing_type_and_negative) ... ok +test_all_events_beyond_recent_window (__main__.Reports.test_all_events_beyond_recent_window) ... ok +test_all_semantic_layers_compared (__main__.Reports.test_all_semantic_layers_compared) ... ok +test_digest_alone_is_not_enough (__main__.Reports.test_digest_alone_is_not_enough) ... ok +test_event_original_types_and_order (__main__.Reports.test_event_original_types_and_order) ... ok +test_event_start_and_ids (__main__.Reports.test_event_start_and_ids) ... ok +test_exclusions_keep_actual_values (__main__.Reports.test_exclusions_keep_actual_values) ... ok +test_handler_sets_and_counts (__main__.Reports.test_handler_sets_and_counts) ... ok +test_observation_full_layers (__main__.Reports.test_observation_full_layers) ... ok +test_product_digest_self_consistency (__main__.Reports.test_product_digest_self_consistency) ... ok +test_same_report (__main__.Reports.test_same_report) ... ok +test_scenario_existing_failures_preserved (__main__.Reports.test_scenario_existing_failures_preserved) ... ok +test_timing_digest_rule (__main__.Reports.test_timing_digest_rule) ... ok +test_unknown_or_missing_fields_rejected (__main__.Reports.test_unknown_or_missing_fields_rejected) ... ok +test_violation_presence_and_difference (__main__.Reports.test_violation_presence_and_difference) ... ok +test_O_cadence (__main__.S2Format.test_O_cadence) ... ok +test_counter_and_published_ids_binding (__main__.S2Format.test_counter_and_published_ids_binding) ... ok +test_diff_and_same_as_S_transport (__main__.S2Format.test_diff_and_same_as_S_transport) ... ok +test_digest_and_scenario_contradiction (__main__.S2Format.test_digest_and_scenario_contradiction) ... ok +test_event_no_drop_duplicate_remap (__main__.S2Format.test_event_no_drop_duplicate_remap) ... ok +test_event_original_field_types_mandatory (__main__.S2Format.test_event_original_field_types_mandatory) ... ok +test_guard_actual_not_assumed (__main__.S2Format.test_guard_actual_not_assumed) ... ok +test_harness_digest_allows_only_dictionary_order (__main__.S2Format.test_harness_digest_allows_only_dictionary_order) ... ok +test_join_is_copy_and_retains_normalization_proof (__main__.S2Format.test_join_is_copy_and_retains_normalization_proof) ... ok +test_kernel_cache_contradictions (__main__.S2Format.test_kernel_cache_contradictions) ... ok +test_lifecycle_guard_errors_and_boundaries (__main__.S2Format.test_lifecycle_guard_errors_and_boundaries) ... ok +test_missing_full_state_not_digest_only (__main__.S2Format.test_missing_full_state_not_digest_only) ... ok +test_normalized_digest_and_raw_tree_are_both_bound (__main__.S2Format.test_normalized_digest_and_raw_tree_are_both_bound) ... ok +test_product_event_shape_and_typed_array (__main__.S2Format.test_product_event_shape_and_typed_array) ... ok +test_raw_observation_binding (__main__.S2Format.test_raw_observation_binding) ... ok +test_roundtrip_tree_sha_and_raw_sha (__main__.S2Format.test_roundtrip_tree_sha_and_raw_sha) ... ok +test_s2_valid_and_not_formal_acceptance (__main__.S2Format.test_s2_valid_and_not_formal_acceptance) ... ok +test_state_witness_and_observation_mutation (__main__.S2Format.test_state_witness_and_observation_mutation) ... ok +test_stdout_exactly_one_line (__main__.S2Format.test_stdout_exactly_one_line) ... ok +test_autoload_class_and_script_import (__main__.S2Static.test_autoload_class_and_script_import) ... ok +test_comment_does_not_supply_proof (__main__.S2Static.test_comment_does_not_supply_proof) ... ok +test_current_probe (__main__.S2Static.test_current_probe) ... ok +test_full_state_and_godot_roundtrip_required (__main__.S2Static.test_full_state_and_godot_roundtrip_required) ... ok +test_no_changes_outside_preparation_or_step (__main__.S2Static.test_no_changes_outside_preparation_or_step) ... ok +test_no_event_cap_or_duplicate_report (__main__.S2Static.test_no_event_cap_or_duplicate_report) ... ok +test_pause_and_step_arguments (__main__.S2Static.test_pause_and_step_arguments) ... ok +test_textual_stringname_ordering (__main__.S2Static.test_textual_stringname_ordering) ... ok +test_unlisted_live_method_and_late_preparation (__main__.S2Static.test_unlisted_live_method_and_late_preparation) ... ok +test_variant_inference (__main__.S2Static.test_variant_inference) ... ok +test_X_recent_limit_and_counter (__main__.S3a.test_X_recent_limit_and_counter) ... ok +test_duplicate_JSON_key_rejected (__main__.S3a.test_duplicate_JSON_key_rejected) ... ok +test_e3_NA_cannot_be_PASS_or_applied (__main__.S3a.test_e3_NA_cannot_be_PASS_or_applied) ... ok +test_e3_coverage_input_and_event_count_binding (__main__.S3a.test_e3_coverage_input_and_event_count_binding) ... ok +test_e3_invented_codes_and_missing_load_code (__main__.S3a.test_e3_invented_codes_and_missing_load_code) ... ok +test_e3_valid_R_and_O_records (__main__.S3a.test_e3_valid_R_and_O_records) ... ok +test_envelope_duplicates_not_defect (__main__.S3a.test_envelope_duplicates_not_defect) ... ok +test_event_count_defect_not_silently_accepted (__main__.S3a.test_event_count_defect_not_silently_accepted) ... ok +test_exact_phase_keys (__main__.S3a.test_exact_phase_keys) ... ok +test_interval_gap_rejected (__main__.S3a.test_interval_gap_rejected) ... ok +test_invalid_input_accepted_is_not_PASS (__main__.S3a.test_invalid_input_accepted_is_not_PASS) ... ok +test_load_payload_and_pause_outcome (__main__.S3a.test_load_payload_and_pause_outcome) ... ok +test_operation_moved_outside_scenario_rejected (__main__.S3a.test_operation_moved_outside_scenario_rejected) ... ok +test_package_fixed_mutations_and_hashes (__main__.S3a.test_package_fixed_mutations_and_hashes) ... ok +test_probe_connection_required (__main__.S3a.test_probe_connection_required) ... ok +test_rejection_mutation_retained_as_defect (__main__.S3a.test_rejection_mutation_retained_as_defect) ... ok +test_save_refusal_makes_load_NA (__main__.S3a.test_save_refusal_makes_load_NA) ... ok +test_scenario_mutation_static_boundary (__main__.S3a.test_scenario_mutation_static_boundary) ... ok +test_signals_all_minutes_and_order (__main__.S3a.test_signals_all_minutes_and_order) ... ok +test_E5_cached_digest_defect_is_comparable (__main__.S3b.test_E5_cached_digest_defect_is_comparable) ... ok +test_NA_not_PASS (__main__.S3b.test_NA_not_PASS) ... ok +test_aliasing_cannot_be_PASS (__main__.S3b.test_aliasing_cannot_be_PASS) ... ok +test_aliasing_missing_record (__main__.S3b.test_aliasing_missing_record) ... ok +test_all_paths_and_ownership_R_O (__main__.S3b.test_all_paths_and_ownership_R_O) ... ok +test_digest_defect_other_checkpoint_still_rejected (__main__.S3b.test_digest_defect_other_checkpoint_still_rejected) ... ok +test_digest_materialization_required (__main__.S3b.test_digest_materialization_required) ... ok +test_empty_registry_not_NA (__main__.S3b.test_empty_registry_not_NA) ... ok +test_event_count_mismatch (__main__.S3b.test_event_count_mismatch) ... ok +test_facts_normalization_is_reversible (__main__.S3b.test_facts_normalization_is_reversible) ... ok +test_first_placeable_choice (__main__.S3b.test_first_placeable_choice) ... ok +test_interval_gap (__main__.S3b.test_interval_gap) ... ok +test_joined_s3b_self_comparison (__main__.S3b.test_joined_s3b_self_comparison) ... ok +test_load_X_not_digest_only (__main__.S3b.test_load_X_not_digest_only) ... ok +test_load_extra_event (__main__.S3b.test_load_extra_event) ... ok +test_missing_path_and_combination (__main__.S3b.test_missing_path_and_combination) ... ok +test_missing_preview_observation (__main__.S3b.test_missing_preview_observation) ... ok +test_missing_trial (__main__.S3b.test_missing_trial) ... ok +test_nested_mutation_required (__main__.S3b.test_nested_mutation_required) ... ok +test_no_staleness_assertion_for_non_tick (__main__.S3b.test_no_staleness_assertion_for_non_tick) ... ok +test_ownership_fact_dictionary_order_fallback (__main__.S3b.test_ownership_fact_dictionary_order_fallback) ... ok +test_path_order (__main__.S3b.test_path_order) ... ok +test_restore_extra_event (__main__.S3b.test_restore_extra_event) ... ok +test_signal_facts_cannot_be_dropped (__main__.S3b.test_signal_facts_cannot_be_dropped) ... ok +test_sort_rule_rejected (__main__.S3b.test_sort_rule_rejected) ... ok +test_static_handler_and_outside_mutations (__main__.S3b.test_static_handler_and_outside_mutations) ... ok +test_unpreviewed_choice (__main__.S3b.test_unpreviewed_choice) ... ok +test_wrong_registry_in_either_role (__main__.S3b.test_wrong_registry_in_either_role) ... ok +test_checkout_temp_destination_rejected (__main__.S4Bundle.test_checkout_temp_destination_rejected) ... ok +test_existing_output_never_overwritten (__main__.S4Bundle.test_existing_output_never_overwritten) ... ok +test_import_closure_rejections (__main__.S4Bundle.test_import_closure_rejections) ... ok +test_missing_bundle_manifest_seal_and_changed_bytes (__main__.S4Bundle.test_missing_bundle_manifest_seal_and_changed_bytes) ... ok +test_missing_private_evidence_and_extra_rejected (__main__.S4Bundle.test_missing_private_evidence_and_extra_rejected) ... ok +test_missing_profile_not_export_success (__main__.S4Bundle.test_missing_profile_not_export_success) ... ok +test_phase_role_pid_audio_and_guard_rejected (__main__.S4Bundle.test_phase_role_pid_audio_and_guard_rejected) ... ok +test_rebound_lifecycle_and_scenario_contradictions (__main__.S4Bundle.test_rebound_lifecycle_and_scenario_contradictions) ... ok +test_seal_normal_and_changes_not_native_proof (__main__.S4Bundle.test_seal_normal_and_changes_not_native_proof) ... ok +test_synthetic_phase_all_real_checkers_not_native_proof (__main__.S4Bundle.test_synthetic_phase_all_real_checkers_not_native_proof) ... ok +test_copied_manifest_root_and_destination_count_rejected (__main__.S4NativeBundleLogic.test_copied_manifest_root_and_destination_count_rejected) ... ok +test_failure_keeps_raw_and_no_bundle_without_starting_engine (__main__.S4NativeBundleLogic.test_failure_keeps_raw_and_no_bundle_without_starting_engine) ... ok +test_gate_none_success_not_boolean (__main__.S4NativeBundleLogic.test_gate_none_success_not_boolean) ... ok +test_receipt_and_source_rejection_matrix (__main__.S4NativeBundleLogic.test_receipt_and_source_rejection_matrix) ... ok +test_synthetic_full_bundle_positive_not_native_evidence (__main__.S4NativeBundleLogic.test_synthetic_full_bundle_positive_not_native_evidence) ... ok +test_check_accepts_true (__main__.S4ProbeAdmission.test_check_accepts_true) ... ok +test_check_rejects_false_all_errors (__main__.S4ProbeAdmission.test_check_rejects_false_all_errors) ... ok +test_run_admission_accepts_true_mock_launch_only (__main__.S4ProbeAdmission.test_run_admission_accepts_true_mock_launch_only) ... ok +test_run_admission_rejects_false_without_engine (__main__.S4ProbeAdmission.test_run_admission_rejects_false_without_engine) ... ok +test_nine_original_destinations_required (__main__.S4RemainingBindings.test_nine_original_destinations_required) ... ok +test_nonzero_determinism_rejected_after_real_join (__main__.S4RemainingBindings.test_nonzero_determinism_rejected_after_real_join) ... ok +test_owned_lifecycle_exit_diagnostic_and_profile_rejections (__main__.S4RemainingBindings.test_owned_lifecycle_exit_diagnostic_and_profile_rejections) ... ok +test_verifier_accepts_true_recomputes_raw (__main__.S4RemainingBindings.test_verifier_accepts_true_recomputes_raw) ... ok +test_verifier_rejects_false_with_every_error (__main__.S4RemainingBindings.test_verifier_rejects_false_with_every_error) ... ok +test_cached_verdict_not_trusted (__main__.S4StoredResultBindings.test_cached_verdict_not_trusted) ... ok +test_missing_sidecar_rejected_after_seal (__main__.S4StoredResultBindings.test_missing_sidecar_rejected_after_seal) ... ok +test_raw_joined_substitution_rejected_after_seal (__main__.S4StoredResultBindings.test_raw_joined_substitution_rejected_after_seal) ... ok +test_blob_transport_is_verified_and_bound (__main__.S5.test_blob_transport_is_verified_and_bound) ... ok +test_blob_trees_get_the_same_full_validation_as_inline (__main__.S5.test_blob_trees_get_the_same_full_validation_as_inline) ... ok +test_bundled_inputs_replace_unreadable_originals (__main__.S5.test_bundled_inputs_replace_unreadable_originals) ... ok +test_compare_and_digest_equal_s1_reference (__main__.S5.test_compare_and_digest_equal_s1_reference) ... ok +test_event_stream_replacement_is_existing_defect_not_pass (__main__.S5.test_event_stream_replacement_is_existing_defect_not_pass) ... ok +test_every_checkpoint_full_tree_verified_like_inline (__main__.S5.test_every_checkpoint_full_tree_verified_like_inline) +S5 drops the diff chain: each checkpoint carries a complete tree, verified alone. ... ok +test_fast_normalization_equals_original (__main__.S5.test_fast_normalization_equals_original) ... ok +test_labelled_harness_digest_falls_back_to_dictionary_order_only (__main__.S5.test_labelled_harness_digest_falls_back_to_dictionary_order_only) ... ok +test_lifecycle_binds_replacements_guard_text_and_blobs (__main__.S5.test_lifecycle_binds_replacements_guard_text_and_blobs) ... ok +test_manifest_numbers_keep_their_type (__main__.S5.test_manifest_numbers_keep_their_type) ... ok +test_memo_scope_same_results_and_restores_gc (__main__.S5.test_memo_scope_same_results_and_restores_gc) ... ok +test_path_copy_builders_equal_deepcopy_reference (__main__.S5.test_path_copy_builders_equal_deepcopy_reference) ... ok +test_probe_static_full_tree_blob_and_stream_requirements (__main__.S5.test_probe_static_full_tree_blob_and_stream_requirements) ... ok +test_publish_pairs_bound_to_source_causes (__main__.S5.test_publish_pairs_bound_to_source_causes) ... ok +test_signed_instance_ids_raw_kept_and_excluded (__main__.S5.test_signed_instance_ids_raw_kept_and_excluded) ... ok +test_validate_tree_equals_s1_reference_on_mutations (__main__.S5.test_validate_tree_equals_s1_reference_on_mutations) ... ok +test_fixed_scenario_paths (__main__.SourcesAndMetrics.test_fixed_scenario_paths) ... ok +test_metric_ranges (__main__.SourcesAndMetrics.test_metric_ranges) ... ok +test_source_closure_synthetic_registered_map (__main__.SourcesAndMetrics.test_source_closure_synthetic_registered_map) ... ok +test_source_pin_is_not_caller_controlled (__main__.SourcesAndMetrics.test_source_pin_is_not_caller_controlled) ... ok +test_array_order_and_all_differences (__main__.TypedTrees.test_array_order_and_all_differences) ... ok +test_components_and_sha (__main__.TypedTrees.test_components_and_sha) ... ok +test_deep_state_not_truncated (__main__.TypedTrees.test_deep_state_not_truncated) ... ok +test_duplicate_textual_keys_rejected (__main__.TypedTrees.test_duplicate_textual_keys_rejected) ... ok +test_exact_and_types (__main__.TypedTrees.test_exact_and_types) ... ok +test_nested_order_all_paths (__main__.TypedTrees.test_nested_order_all_paths) ... ok +test_nonstring_keys_keep_types_and_values (__main__.TypedTrees.test_nonstring_keys_keep_types_and_values) ... ok +test_unsupported_and_malformed (__main__.TypedTrees.test_unsupported_and_malformed) ... ok + +---------------------------------------------------------------------- +Ran 162 tests in 120.853s + +OK diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_SEATBELT_06.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_SEATBELT_06.sha256 new file mode 100644 index 0000000..68fa76f --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_SEATBELT_06.sha256 @@ -0,0 +1 @@ +2797169a7c98b0b5d2f578f28a860dc2819294e023e1019ae8243e41631d5e29 UNIT_OUTPUT_S5_SEATBELT_06.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_SEATBELT_06.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_SEATBELT_06.txt new file mode 100644 index 0000000..84bbdd2 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S5_SEATBELT_06.txt @@ -0,0 +1,168 @@ +test_all_operations (__main__.Diffs.test_all_operations) ... ok +test_invalid_operations (__main__.Diffs.test_invalid_operations) ... ok +test_reconstruction_and_proofs (__main__.Diffs.test_reconstruction_and_proofs) ... ok +test_attempt_to_normalize_violation_rejected (__main__.Normalization.test_attempt_to_normalize_violation_rejected) ... ok +test_environment_values_differ_but_normal_form_equal (__main__.Normalization.test_environment_values_differ_but_normal_form_equal) ... ok +test_every_save_event_reversible (__main__.Normalization.test_every_save_event_reversible) ... ok +test_f3_keeps_relative_paths_and_words (__main__.Normalization.test_f3_keeps_relative_paths_and_words) ... ok +test_guard_mismatch (__main__.Normalization.test_guard_mismatch) ... ok +test_nested_lookalike_is_not_eligible (__main__.Normalization.test_nested_lookalike_is_not_eligible) ... ok +test_original_transport_sha_detects_forged_timing (__main__.Normalization.test_original_transport_sha_detects_forged_timing) ... ok +test_partial_timing_payload_rejected (__main__.Normalization.test_partial_timing_payload_rejected) ... ok +test_prefix_boundary_and_reserved_token (__main__.Normalization.test_prefix_boundary_and_reserved_token) ... ok +test_sidecar_missing_duplicate_and_forged_paths (__main__.Normalization.test_sidecar_missing_duplicate_and_forged_paths) ... ok +test_snapshot_and_latest_reversible (__main__.Normalization.test_snapshot_and_latest_reversible) ... ok +test_snapshot_event_outside_recent_is_not_eligible (__main__.Normalization.test_snapshot_event_outside_recent_is_not_eligible) ... ok +test_wrong_event_and_source_are_preserved (__main__.Normalization.test_wrong_event_and_source_are_preserved) ... ok +test_wrong_timing_type_and_negative (__main__.Normalization.test_wrong_timing_type_and_negative) ... ok +test_all_events_beyond_recent_window (__main__.Reports.test_all_events_beyond_recent_window) ... ok +test_all_semantic_layers_compared (__main__.Reports.test_all_semantic_layers_compared) ... ok +test_digest_alone_is_not_enough (__main__.Reports.test_digest_alone_is_not_enough) ... ok +test_event_original_types_and_order (__main__.Reports.test_event_original_types_and_order) ... ok +test_event_start_and_ids (__main__.Reports.test_event_start_and_ids) ... ok +test_exclusions_keep_actual_values (__main__.Reports.test_exclusions_keep_actual_values) ... ok +test_handler_sets_and_counts (__main__.Reports.test_handler_sets_and_counts) ... ok +test_observation_full_layers (__main__.Reports.test_observation_full_layers) ... ok +test_product_digest_self_consistency (__main__.Reports.test_product_digest_self_consistency) ... ok +test_same_report (__main__.Reports.test_same_report) ... ok +test_scenario_existing_failures_preserved (__main__.Reports.test_scenario_existing_failures_preserved) ... ok +test_timing_digest_rule (__main__.Reports.test_timing_digest_rule) ... ok +test_unknown_or_missing_fields_rejected (__main__.Reports.test_unknown_or_missing_fields_rejected) ... ok +test_violation_presence_and_difference (__main__.Reports.test_violation_presence_and_difference) ... ok +test_O_cadence (__main__.S2Format.test_O_cadence) ... ok +test_counter_and_published_ids_binding (__main__.S2Format.test_counter_and_published_ids_binding) ... ok +test_diff_and_same_as_S_transport (__main__.S2Format.test_diff_and_same_as_S_transport) ... ok +test_digest_and_scenario_contradiction (__main__.S2Format.test_digest_and_scenario_contradiction) ... ok +test_event_no_drop_duplicate_remap (__main__.S2Format.test_event_no_drop_duplicate_remap) ... ok +test_event_original_field_types_mandatory (__main__.S2Format.test_event_original_field_types_mandatory) ... ok +test_guard_actual_not_assumed (__main__.S2Format.test_guard_actual_not_assumed) ... ok +test_harness_digest_allows_only_dictionary_order (__main__.S2Format.test_harness_digest_allows_only_dictionary_order) ... ok +test_join_is_copy_and_retains_normalization_proof (__main__.S2Format.test_join_is_copy_and_retains_normalization_proof) ... ok +test_kernel_cache_contradictions (__main__.S2Format.test_kernel_cache_contradictions) ... ok +test_lifecycle_guard_errors_and_boundaries (__main__.S2Format.test_lifecycle_guard_errors_and_boundaries) ... ok +test_missing_full_state_not_digest_only (__main__.S2Format.test_missing_full_state_not_digest_only) ... ok +test_normalized_digest_and_raw_tree_are_both_bound (__main__.S2Format.test_normalized_digest_and_raw_tree_are_both_bound) ... ok +test_product_event_shape_and_typed_array (__main__.S2Format.test_product_event_shape_and_typed_array) ... ok +test_raw_observation_binding (__main__.S2Format.test_raw_observation_binding) ... ok +test_roundtrip_tree_sha_and_raw_sha (__main__.S2Format.test_roundtrip_tree_sha_and_raw_sha) ... ok +test_s2_valid_and_not_formal_acceptance (__main__.S2Format.test_s2_valid_and_not_formal_acceptance) ... ok +test_state_witness_and_observation_mutation (__main__.S2Format.test_state_witness_and_observation_mutation) ... ok +test_stdout_exactly_one_line (__main__.S2Format.test_stdout_exactly_one_line) ... ok +test_autoload_class_and_script_import (__main__.S2Static.test_autoload_class_and_script_import) ... ok +test_comment_does_not_supply_proof (__main__.S2Static.test_comment_does_not_supply_proof) ... ok +test_current_probe (__main__.S2Static.test_current_probe) ... ok +test_full_state_and_godot_roundtrip_required (__main__.S2Static.test_full_state_and_godot_roundtrip_required) ... ok +test_no_changes_outside_preparation_or_step (__main__.S2Static.test_no_changes_outside_preparation_or_step) ... ok +test_no_event_cap_or_duplicate_report (__main__.S2Static.test_no_event_cap_or_duplicate_report) ... ok +test_pause_and_step_arguments (__main__.S2Static.test_pause_and_step_arguments) ... ok +test_textual_stringname_ordering (__main__.S2Static.test_textual_stringname_ordering) ... ok +test_unlisted_live_method_and_late_preparation (__main__.S2Static.test_unlisted_live_method_and_late_preparation) ... ok +test_variant_inference (__main__.S2Static.test_variant_inference) ... ok +test_X_recent_limit_and_counter (__main__.S3a.test_X_recent_limit_and_counter) ... ok +test_duplicate_JSON_key_rejected (__main__.S3a.test_duplicate_JSON_key_rejected) ... ok +test_e3_NA_cannot_be_PASS_or_applied (__main__.S3a.test_e3_NA_cannot_be_PASS_or_applied) ... ok +test_e3_coverage_input_and_event_count_binding (__main__.S3a.test_e3_coverage_input_and_event_count_binding) ... ok +test_e3_invented_codes_and_missing_load_code (__main__.S3a.test_e3_invented_codes_and_missing_load_code) ... ok +test_e3_valid_R_and_O_records (__main__.S3a.test_e3_valid_R_and_O_records) ... ok +test_envelope_duplicates_not_defect (__main__.S3a.test_envelope_duplicates_not_defect) ... ok +test_event_count_defect_not_silently_accepted (__main__.S3a.test_event_count_defect_not_silently_accepted) ... ok +test_exact_phase_keys (__main__.S3a.test_exact_phase_keys) ... ok +test_interval_gap_rejected (__main__.S3a.test_interval_gap_rejected) ... ok +test_invalid_input_accepted_is_not_PASS (__main__.S3a.test_invalid_input_accepted_is_not_PASS) ... ok +test_load_payload_and_pause_outcome (__main__.S3a.test_load_payload_and_pause_outcome) ... ok +test_operation_moved_outside_scenario_rejected (__main__.S3a.test_operation_moved_outside_scenario_rejected) ... ok +test_package_fixed_mutations_and_hashes (__main__.S3a.test_package_fixed_mutations_and_hashes) ... ok +test_probe_connection_required (__main__.S3a.test_probe_connection_required) ... ok +test_rejection_mutation_retained_as_defect (__main__.S3a.test_rejection_mutation_retained_as_defect) ... ok +test_save_refusal_makes_load_NA (__main__.S3a.test_save_refusal_makes_load_NA) ... ok +test_scenario_mutation_static_boundary (__main__.S3a.test_scenario_mutation_static_boundary) ... ok +test_signals_all_minutes_and_order (__main__.S3a.test_signals_all_minutes_and_order) ... ok +test_E5_cached_digest_defect_is_comparable (__main__.S3b.test_E5_cached_digest_defect_is_comparable) ... ok +test_NA_not_PASS (__main__.S3b.test_NA_not_PASS) ... ok +test_aliasing_cannot_be_PASS (__main__.S3b.test_aliasing_cannot_be_PASS) ... ok +test_aliasing_missing_record (__main__.S3b.test_aliasing_missing_record) ... ok +test_all_paths_and_ownership_R_O (__main__.S3b.test_all_paths_and_ownership_R_O) ... ok +test_digest_defect_other_checkpoint_still_rejected (__main__.S3b.test_digest_defect_other_checkpoint_still_rejected) ... ok +test_digest_materialization_required (__main__.S3b.test_digest_materialization_required) ... ok +test_empty_registry_not_NA (__main__.S3b.test_empty_registry_not_NA) ... ok +test_event_count_mismatch (__main__.S3b.test_event_count_mismatch) ... ok +test_facts_normalization_is_reversible (__main__.S3b.test_facts_normalization_is_reversible) ... ok +test_first_placeable_choice (__main__.S3b.test_first_placeable_choice) ... ok +test_interval_gap (__main__.S3b.test_interval_gap) ... ok +test_joined_s3b_self_comparison (__main__.S3b.test_joined_s3b_self_comparison) ... ok +test_load_X_not_digest_only (__main__.S3b.test_load_X_not_digest_only) ... ok +test_load_extra_event (__main__.S3b.test_load_extra_event) ... ok +test_missing_path_and_combination (__main__.S3b.test_missing_path_and_combination) ... ok +test_missing_preview_observation (__main__.S3b.test_missing_preview_observation) ... ok +test_missing_trial (__main__.S3b.test_missing_trial) ... ok +test_nested_mutation_required (__main__.S3b.test_nested_mutation_required) ... ok +test_no_staleness_assertion_for_non_tick (__main__.S3b.test_no_staleness_assertion_for_non_tick) ... ok +test_ownership_fact_dictionary_order_fallback (__main__.S3b.test_ownership_fact_dictionary_order_fallback) ... ok +test_path_order (__main__.S3b.test_path_order) ... ok +test_restore_extra_event (__main__.S3b.test_restore_extra_event) ... ok +test_signal_facts_cannot_be_dropped (__main__.S3b.test_signal_facts_cannot_be_dropped) ... ok +test_sort_rule_rejected (__main__.S3b.test_sort_rule_rejected) ... ok +test_static_handler_and_outside_mutations (__main__.S3b.test_static_handler_and_outside_mutations) ... ok +test_unpreviewed_choice (__main__.S3b.test_unpreviewed_choice) ... ok +test_wrong_registry_in_either_role (__main__.S3b.test_wrong_registry_in_either_role) ... ok +test_checkout_temp_destination_rejected (__main__.S4Bundle.test_checkout_temp_destination_rejected) ... ok +test_existing_output_never_overwritten (__main__.S4Bundle.test_existing_output_never_overwritten) ... ok +test_import_closure_rejections (__main__.S4Bundle.test_import_closure_rejections) ... ok +test_missing_bundle_manifest_seal_and_changed_bytes (__main__.S4Bundle.test_missing_bundle_manifest_seal_and_changed_bytes) ... ok +test_missing_private_evidence_and_extra_rejected (__main__.S4Bundle.test_missing_private_evidence_and_extra_rejected) ... ok +test_missing_profile_not_export_success (__main__.S4Bundle.test_missing_profile_not_export_success) ... ok +test_phase_role_pid_audio_and_guard_rejected (__main__.S4Bundle.test_phase_role_pid_audio_and_guard_rejected) ... ok +test_rebound_lifecycle_and_scenario_contradictions (__main__.S4Bundle.test_rebound_lifecycle_and_scenario_contradictions) ... ok +test_seal_normal_and_changes_not_native_proof (__main__.S4Bundle.test_seal_normal_and_changes_not_native_proof) ... ok +test_synthetic_phase_all_real_checkers_not_native_proof (__main__.S4Bundle.test_synthetic_phase_all_real_checkers_not_native_proof) ... ok +test_copied_manifest_root_and_destination_count_rejected (__main__.S4NativeBundleLogic.test_copied_manifest_root_and_destination_count_rejected) ... ok +test_failure_keeps_raw_and_no_bundle_without_starting_engine (__main__.S4NativeBundleLogic.test_failure_keeps_raw_and_no_bundle_without_starting_engine) ... ok +test_gate_none_success_not_boolean (__main__.S4NativeBundleLogic.test_gate_none_success_not_boolean) ... ok +test_receipt_and_source_rejection_matrix (__main__.S4NativeBundleLogic.test_receipt_and_source_rejection_matrix) ... ok +test_synthetic_full_bundle_positive_not_native_evidence (__main__.S4NativeBundleLogic.test_synthetic_full_bundle_positive_not_native_evidence) ... ok +test_check_accepts_true (__main__.S4ProbeAdmission.test_check_accepts_true) ... ok +test_check_rejects_false_all_errors (__main__.S4ProbeAdmission.test_check_rejects_false_all_errors) ... ok +test_run_admission_accepts_true_mock_launch_only (__main__.S4ProbeAdmission.test_run_admission_accepts_true_mock_launch_only) ... ok +test_run_admission_rejects_false_without_engine (__main__.S4ProbeAdmission.test_run_admission_rejects_false_without_engine) ... ok +test_nine_original_destinations_required (__main__.S4RemainingBindings.test_nine_original_destinations_required) ... ok +test_nonzero_determinism_rejected_after_real_join (__main__.S4RemainingBindings.test_nonzero_determinism_rejected_after_real_join) ... ok +test_owned_lifecycle_exit_diagnostic_and_profile_rejections (__main__.S4RemainingBindings.test_owned_lifecycle_exit_diagnostic_and_profile_rejections) ... ok +test_verifier_accepts_true_recomputes_raw (__main__.S4RemainingBindings.test_verifier_accepts_true_recomputes_raw) ... ok +test_verifier_rejects_false_with_every_error (__main__.S4RemainingBindings.test_verifier_rejects_false_with_every_error) ... ok +test_cached_verdict_not_trusted (__main__.S4StoredResultBindings.test_cached_verdict_not_trusted) ... ok +test_missing_sidecar_rejected_after_seal (__main__.S4StoredResultBindings.test_missing_sidecar_rejected_after_seal) ... ok +test_raw_joined_substitution_rejected_after_seal (__main__.S4StoredResultBindings.test_raw_joined_substitution_rejected_after_seal) ... ok +test_blob_transport_is_verified_and_bound (__main__.S5.test_blob_transport_is_verified_and_bound) ... ok +test_blob_trees_get_the_same_full_validation_as_inline (__main__.S5.test_blob_trees_get_the_same_full_validation_as_inline) ... ok +test_bundled_inputs_replace_unreadable_originals (__main__.S5.test_bundled_inputs_replace_unreadable_originals) ... ok +test_compare_and_digest_equal_s1_reference (__main__.S5.test_compare_and_digest_equal_s1_reference) ... ok +test_event_stream_replacement_is_existing_defect_not_pass (__main__.S5.test_event_stream_replacement_is_existing_defect_not_pass) ... ok +test_every_checkpoint_full_tree_verified_like_inline (__main__.S5.test_every_checkpoint_full_tree_verified_like_inline) +S5 drops the diff chain: each checkpoint carries a complete tree, verified alone. ... ok +test_fast_normalization_equals_original (__main__.S5.test_fast_normalization_equals_original) ... ok +test_labelled_harness_digest_falls_back_to_dictionary_order_only (__main__.S5.test_labelled_harness_digest_falls_back_to_dictionary_order_only) ... ok +test_lifecycle_binds_replacements_guard_text_and_blobs (__main__.S5.test_lifecycle_binds_replacements_guard_text_and_blobs) ... ok +test_manifest_numbers_keep_their_type (__main__.S5.test_manifest_numbers_keep_their_type) ... ok +test_memo_scope_same_results_and_restores_gc (__main__.S5.test_memo_scope_same_results_and_restores_gc) ... ok +test_path_copy_builders_equal_deepcopy_reference (__main__.S5.test_path_copy_builders_equal_deepcopy_reference) ... ok +test_probe_static_full_tree_blob_and_stream_requirements (__main__.S5.test_probe_static_full_tree_blob_and_stream_requirements) ... ok +test_publish_pairs_bound_to_source_causes (__main__.S5.test_publish_pairs_bound_to_source_causes) ... ok +test_signed_instance_ids_raw_kept_and_excluded (__main__.S5.test_signed_instance_ids_raw_kept_and_excluded) ... ok +test_validate_tree_equals_s1_reference_on_mutations (__main__.S5.test_validate_tree_equals_s1_reference_on_mutations) ... ok +test_fixed_scenario_paths (__main__.SourcesAndMetrics.test_fixed_scenario_paths) ... ok +test_metric_ranges (__main__.SourcesAndMetrics.test_metric_ranges) ... ok +test_source_closure_synthetic_registered_map (__main__.SourcesAndMetrics.test_source_closure_synthetic_registered_map) ... ok +test_source_pin_is_not_caller_controlled (__main__.SourcesAndMetrics.test_source_pin_is_not_caller_controlled) ... ok +test_array_order_and_all_differences (__main__.TypedTrees.test_array_order_and_all_differences) ... ok +test_components_and_sha (__main__.TypedTrees.test_components_and_sha) ... ok +test_deep_state_not_truncated (__main__.TypedTrees.test_deep_state_not_truncated) ... ok +test_duplicate_textual_keys_rejected (__main__.TypedTrees.test_duplicate_textual_keys_rejected) ... ok +test_exact_and_types (__main__.TypedTrees.test_exact_and_types) ... ok +test_nested_order_all_paths (__main__.TypedTrees.test_nested_order_all_paths) ... ok +test_nonstring_keys_keep_types_and_values (__main__.TypedTrees.test_nonstring_keys_keep_types_and_values) ... ok +test_unsupported_and_malformed (__main__.TypedTrees.test_unsupported_and_malformed) ... ok + +---------------------------------------------------------------------- +Ran 162 tests in 120.930s + +OK diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/run_eq.py b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/run_eq.py index df9d392..4e4f1b5 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/run_eq.py +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/run_eq.py @@ -77,7 +77,44 @@ def load_dependencies(root=ROOT): return collector, standard, outer, diag -def actual_pins(root, readonly, fixture, engine, collector, standard): +def bundled_inputs(copies, readonly): + """collector.inputs on the read-only input copies sealed in the bundle (S5). + + The formal native-verify runs under the Runner seatbelt, which cannot read the original + read-only directory or the fixture outside the checkout. The same rule applies: every + manifest destination lies in the original read-only directory, and its copy has the + recorded bytes and SHA. The manifest SHA is bound by the caller to the admission pin.""" + manifest_path = copies / 'ROOT_INPUT_MANIFEST.json' + manifest = verify.read(manifest_path) + pins = {} + for row in manifest['files']: + destination = Path(row['destination']) + require(destination.is_absolute() and destination.is_relative_to(readonly), 'input escapes read-only directory') + relative = destination.relative_to(readonly) + copy = copies / relative + require(copy.is_file() and not copy.is_symlink(), 'bundled read-only input missing') + require(sha(copy) == row['sha256'] and copy.stat().st_size == row['bytes'], 'read-only input changed') + pins[str(relative)] = row['sha256'] + return {'manifest_sha256': sha(manifest_path), 'files': pins} + + +def bundle_inputs(out, readonly, fixture, pins): + """Seal copies of the fixture and the read-only inputs in the output (verified first).""" + target = out / 'inputs' + (target / 'fixture').mkdir(parents=True) + shutil.copyfile(fixture, target / 'fixture' / fixture.name) + manifest = verify.read(readonly / 'ROOT_INPUT_MANIFEST.json') + (target / 'readonly').mkdir() + shutil.copyfile(readonly / 'ROOT_INPUT_MANIFEST.json', target / 'readonly' / 'ROOT_INPUT_MANIFEST.json') + for row in manifest['files']: + relative = Path(row['destination']).relative_to(readonly) + (target / 'readonly' / relative).parent.mkdir(parents=True, exist_ok=True) + shutil.copyfile(Path(row['destination']), target / 'readonly' / relative) + require(pin(target / 'fixture' / fixture.name) == pins['fixture'], 'fixture copy differs') + require(bundled_inputs(target / 'readonly', readonly) == pins['readonly'], 'read-only input copies differ') + + +def actual_pins(root, readonly, fixture, engine, collector, standard, copies=None): local = root / HERE.relative_to(ROOT) dependencies = {n: sha(root / n) for n in DEPENDENCIES} require(dependencies == DEPENDENCIES, 'dependencies changed') @@ -86,9 +123,9 @@ def actual_pins(root, readonly, fixture, engine, collector, standard): source = collector.source_map(standard, root) require(len(source) == 1407 and collector.digest(source) == eq.SOURCE_SHA, 'full 1407 source pin') require(sha(fixture) == collector.FIXTURE_SHA and sha(engine) == collector.ENGINE_SHA, 'fixture/engine pin') - inputs = collector.inputs(readonly) + inputs = collector.inputs(readonly) if copies is None else bundled_inputs(copies, readonly) require(len(inputs['files']) == 9, 'nine original destinations required') - manifest = verify.read(readonly / 'ROOT_INPUT_MANIFEST.json') + manifest = verify.read((readonly if copies is None else copies) / 'ROOT_INPUT_MANIFEST.json') require(len(manifest['files']) == 9 and len({r['destination'] for r in manifest['files']}) == 9, 'nine unique destinations') require(sys.platform == 'darwin', 'native platform') machine = subprocess.check_output(['sysctl', '-n', 'hw.model'], text=True).strip() @@ -186,6 +223,7 @@ def run(admission, out, collector, standard, outer, diag): (out / 'profile_guard.gd').write_bytes((Path(admission['readonly_path']) / 'run-r02/profile_guard.gd').read_bytes()) (out / 'guarded.gd').write_text(wrapper_text(out)) (out / 'root-input-manifest.json').write_bytes((Path(admission['readonly_path']) / 'ROOT_INPUT_MANIFEST.json').read_bytes()) + bundle_inputs(out, Path(admission['readonly_path']), Path(admission['fixture']), admission['pins']) for item in admission['plan']: phase = item['phase'] require(standard.inventory(stage, stage=True) == expected, 'stage changed before phase') diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py index d6e2ecb..6f8dd9d 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py @@ -1717,7 +1717,8 @@ import tempfile def s5_root(): - base = os.environ.get('BUILD_OUTPUT_DIR') or tempfile.gettempdir() + base = Path(os.environ.get('BUILD_OUTPUT_DIR') or tempfile.gettempdir()) + base.mkdir(parents=True, exist_ok=True) return Path(tempfile.mkdtemp(prefix='p28-eq-s5-', dir=base)) @@ -2275,6 +2276,31 @@ class S5(unittest.TestCase): self.assertEqual(outcome(eq.validate_tree, value), expected, case) self.assertGreater(len(seen), 12) + def test_bundled_inputs_replace_unreadable_originals(self): + original = self.root / 'readonly'; copies = self.root / 'copies' + rows = [] + for relative, content in (('a.py', b'alpha'), ('run-r02/b.gd', b'beta')): + (original / relative).parent.mkdir(parents=True, exist_ok=True); (original / relative).write_bytes(content) + rows.append({'destination': str(original / relative), 'bytes': len(content), 'sha256': hashlib.sha256(content).hexdigest()}) + original.joinpath('ROOT_INPUT_MANIFEST.json').write_text(json.dumps({'files': rows})) + fixture = self.root / 'reference.variant'; fixture.write_bytes(b'fixture') + pins = {'fixture': verifier.pin(fixture), 'readonly': driver.bundled_inputs(original, original)} + driver.bundle_inputs(self.root, original, fixture, pins) + shutil.move(str(original), str(self.root / 'gone')) + self.assertEqual(driver.bundled_inputs(self.root / 'inputs' / 'readonly', original), pins['readonly']) + self.assertEqual(verifier.pin(self.root / 'inputs' / 'fixture' / 'reference.variant'), pins['fixture']) + (self.root / 'inputs' / 'readonly' / 'a.py').write_bytes(b'changed') + with self.assertRaisesRegex(eq.EvidenceError, 'read-only input changed'): + driver.bundled_inputs(self.root / 'inputs' / 'readonly', original) + (self.root / 'inputs' / 'readonly' / 'a.py').unlink() + with self.assertRaisesRegex(eq.EvidenceError, 'bundled read-only input missing'): + driver.bundled_inputs(self.root / 'inputs' / 'readonly', original) + outside = json.loads((self.root / 'inputs' / 'readonly' / 'ROOT_INPUT_MANIFEST.json').read_text()) + outside['files'][0]['destination'] = '/elsewhere/a.py' + (self.root / 'inputs' / 'readonly' / 'ROOT_INPUT_MANIFEST.json').write_text(json.dumps(outside)) + with self.assertRaisesRegex(eq.EvidenceError, 'input escapes read-only directory'): + driver.bundled_inputs(self.root / 'inputs' / 'readonly', original) + def test_probe_static_full_tree_blob_and_stream_requirements(self): probe = (verifier.HERE/'eq_probe.gd').read_text() self.assertTrue(checker.check_probe(probe)['ok']) diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/verify_eq.py b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/verify_eq.py index d22fe85..99e93f8 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/verify_eq.py +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/verify_eq.py @@ -292,8 +292,13 @@ def verify(project_root, directory): execution = read(directory / 'execution.json') collector, standard, outer, diag = load_dependencies(project_root) admission = execution['admission'] - require(actual_pins(project_root, Path(admission['readonly_path']), Path(admission['fixture']), - Path(admission['engine']), collector, standard) == admission['pins'], 'actual input/source/EQ pins differ') + # S5: inputs outside the checkout are read from the copies sealed in the bundle; the + # sandboxed validation cannot read the originals (seatbelt), and the copies were checked + # against them by run_eq before any phase. + inputs = directory / 'inputs' + require(actual_pins(project_root, Path(admission['readonly_path']), inputs / 'fixture' / Path(admission['fixture']).name, + Path(admission['engine']), collector, standard, copies=inputs / 'readonly') == admission['pins'], + 'actual input/source/EQ pins differ') result = recompute(directory, execution, collector, standard, diag, parallel=True) require(result == read(directory / 'results.json'), 'recomputed results differ') for phase, values in result['phases'].items(): From 9adbbee334548ac36cd49d68efc021abb7acd003 Mon Sep 17 00:00:00 2001 From: Agent Control Runner Date: Thu, 22 Oct 2026 06:42:29 +0900 Subject: [PATCH 4/4] =?UTF-8?q?P28-02-EQ:=20=E6=84=8F=E5=91=B3=E3=82=92?= =?UTF-8?q?=E4=BF=9D=E3=81=A4=E8=BB=BD=E9=87=8F=E5=8C=96=EF=BC=9A=E5=90=8C?= =?UTF-8?q?=E7=AD=89=E6=80=A7=E3=81=AE=E5=85=88=E8=A1=8C=E5=9B=BA=E5=AE=9A?= =?UTF-8?q?=EF=BC=88harness=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../p28-02/eq/BEFORE_SOURCE_MAP.json | 5630 +++++++++++++++++ .../execution/p28-02/eq/IMPLEMENTATION.md | 66 + .../execution/p28-02/eq/PROGRESS.md | 76 +- .../execution/p28-02/eq/S6_SUPPLEMENTARY.json | 31 + .../execution/p28-02/eq/UNIT_OUTPUT.sha256 | 2 +- .../execution/p28-02/eq/UNIT_OUTPUT.txt | 19 +- .../eq/UNIT_OUTPUT_S6_ATTEMPT_01.sha256 | 1 + .../p28-02/eq/UNIT_OUTPUT_S6_ATTEMPT_01.txt | 185 + .../eq/UNIT_OUTPUT_S6_SEATBELT_01.sha256 | 1 + .../p28-02/eq/UNIT_OUTPUT_S6_SEATBELT_01.txt | 185 + .../execution/p28-02/eq/check_eq.py | 6 +- .../execution/p28-02/eq/compare_versions.py | 38 + .../execution/p28-02/eq/eq_probe.gd | 3 +- .../execution/p28-02/eq/run_eq.py | 40 +- .../execution/p28-02/eq/test_eq.py | 333 +- .../execution/p28-02/eq/verify_eq.py | 99 +- 16 files changed, 6682 insertions(+), 33 deletions(-) create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/BEFORE_SOURCE_MAP.json create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/S6_SUPPLEMENTARY.json create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S6_ATTEMPT_01.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S6_ATTEMPT_01.txt create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S6_SEATBELT_01.sha256 create mode 100644 docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S6_SEATBELT_01.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/BEFORE_SOURCE_MAP.json b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/BEFORE_SOURCE_MAP.json new file mode 100644 index 0000000..fae6a8a --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/BEFORE_SOURCE_MAP.json @@ -0,0 +1,5630 @@ +{ + "AGENTS.md": { + "bytes": 605, + "sha256": "8d8dc40211390275f858f322743309a0663c4f2d859780a8b8a08cea1450e8b3" + }, + "Makefile": { + "bytes": 16480, + "sha256": "a008d11c97b0cc655b6b87e0b382c1eefbfcae51848fe4fb434d178cd6815abb" + }, + "assets/audio/bgm/tree_theme_back_candidate.wav": { + "bytes": 7526444, + "sha256": "efe4cc1aa588661d73376720e4278427f7220ce93a5d446f198c5af607c141ca" + }, + "assets/audio/bgm/tree_theme_back_candidate.wav.import": { + "bytes": 549, + "sha256": "aedbbd43ca5ef33eada0aae53191ab9c0e321bb05289e7925c002ccd49c1eb15" + }, + "assets/audio/bgm/tree_theme_front_candidate.wav": { + "bytes": 7526444, + "sha256": "6df0a7af307327f703c9325f5ca2ac456888102d50ef1fa76bf4cdf19d2b86cb" + }, + "assets/audio/bgm/tree_theme_front_candidate.wav.import": { + "bytes": 553, + "sha256": "0f02aa9a0737018164faf573933f25a506c973c3dfe99f4ecb0a90c99ad01f26" + }, + "assets/audio/ui/License.txt": { + "bytes": 574, + "sha256": "f7966c773bbed0eca6a9c75081c44a178b38eae112724dbb5fdfbd4192d118a9" + }, + "assets/audio/ui/bong_001.ogg": { + "bytes": 4848, + "sha256": "d21d0f0b782445db579d11e2506b24cd1ac9d664ee33aeaf807761aa7b6fd710" + }, + "assets/audio/ui/bong_001.ogg.import": { + "bytes": 396, + "sha256": "15f986d02ba57dd4435edf77723b8ea7dee9fdbe629f268f4c3880b8fd4722c3" + }, + "assets/audio/ui/click_001.ogg": { + "bytes": 4876, + "sha256": "ccfb7fa0cccdd9faec0eb16033c732b1e308d139d80f799161495d58f7adcdb9" + }, + "assets/audio/ui/click_001.ogg.import": { + "bytes": 399, + "sha256": "460e5a751e591a61df4a2b3317b2666644934bf3727f8d1c33e84038b64a518a" + }, + "assets/audio/ui/confirmation_001.ogg": { + "bytes": 8968, + "sha256": "063564703b6094d70718a3e787a55cc9141611e4ecd6b6637f8828f79b4a8c3a" + }, + "assets/audio/ui/confirmation_001.ogg.import": { + "bytes": 420, + "sha256": "b03ac42050d89bff458fbb31eec26de3081272edb6406a51098ff5e76a214cf1" + }, + "assets/audio/ui/error_008.ogg": { + "bytes": 9215, + "sha256": "eba17ecb2a426bfd4a8a6acff5f8a86202b6424a77af0fd842e37809a1ab6d81" + }, + "assets/audio/ui/error_008.ogg.import": { + "bytes": 399, + "sha256": "a2ec2bfc2fc3f30f936cb3756e1c752e7d58090ea29cbeebc620a8b06f4f219a" + }, + "assets/audio/ui/source_manifest.json": { + "bytes": 1330, + "sha256": "f981c2ce12ed364010217dee996908f037d2abfcc3b21b8cf501dd591f7744c9" + }, + "assets/icons/project_icon.svg": { + "bytes": 1054, + "sha256": "25cc327f9d3bec159a48a11b85dddcbb614f1b673dfb975dc8ddc130f248a86b" + }, + "assets/icons/project_icon.svg.import": { + "bytes": 1049, + "sha256": "a2e07249a4eb8dd76a0e2f91f5cb5a1197d69d32d3b4fe3dcbc9935017512699" + }, + "assets/kenney/README.md": { + "bytes": 5280, + "sha256": "aaf2b3f1ba7b747709d5910389acaaca2beda2a1ca8eed12b0abfd81ddb3f1da" + }, + "assets/kenney/sources.json": { + "bytes": 724, + "sha256": "708f5980d0e740f6a7bf1e7fbd0d8964292729309c1a3eeafc367fb94f119b76" + }, + "assets/kenney/tiny_dungeon/License.txt": { + "bytes": 570, + "sha256": "9f574a2f1f636a3db8a0665ba90212f34e2b5e61ecb533d77c05237766374111" + }, + "assets/kenney/tiny_dungeon/Preview.png": { + "bytes": 17553, + "sha256": "b6023d3a9504f84bbd128d21680d0899c7a150bce3443d0861590f3f3de1c24b" + }, + "assets/kenney/tiny_dungeon/Preview.png.import": { + "bytes": 952, + "sha256": "2f07b4aa6b1b711dc4993e4b3ae0ac51d73f3b857bd2a81d579a31c3af0efec0" + }, + "assets/kenney/tiny_dungeon/Sample.png": { + "bytes": 26519, + "sha256": "2b922fefcaa5728986e0b5c1fb901a51c3e571c39e6bed1a22fa1ffdf504370f" + }, + "assets/kenney/tiny_dungeon/Sample.png.import": { + "bytes": 949, + "sha256": "b457890599ec46167078c3ae0a2b9eb0ff150f7a200ef572bcfd04a74969425d" + }, + "assets/kenney/tiny_dungeon/Tiled/sampleMap.tmx": { + "bytes": 5514, + "sha256": "3849e083e3d4f6a71dbf725d8473e93fa6ef8cdc9d314368eee15c980cf41775" + }, + "assets/kenney/tiny_dungeon/Tiled/sampleSheet.tsx": { + "bytes": 249, + "sha256": "a2cca2c5e50b14023ce00f5d4112fb0b8264bfff9407d7a5198656e28d67fa16" + }, + "assets/kenney/tiny_dungeon/Tilemap/tilemap.png": { + "bytes": 5533, + "sha256": "5653222ac495d89e942f9b636300759b3f38e85b26e9b888676f2e9ab834095a" + }, + "assets/kenney/tiny_dungeon/Tilemap/tilemap.png.import": { + "bytes": 960, + "sha256": "bf838a715d001bbb137349b609997e313293412bd72c4411457c5fd90bc5b68b" + }, + "assets/kenney/tiny_dungeon/Tilemap/tilemap_packed.png": { + "bytes": 5294, + "sha256": "d24e60a41e4ac7a745c0304dfde121143688557f40215f23221c29cfe683825f" + }, + "assets/kenney/tiny_dungeon/Tilemap/tilemap_packed.png.import": { + "bytes": 980, + "sha256": "a9f6dea88271040a123f8dadc1e117c67084ccc855ef09ebc77b54ff8c0a693f" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0000.png": { + "bytes": 99, + "sha256": "ebf91e6638d484dc6bdaec5f30e91589252125146b70c2911f11fac7ebe17090" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0000.png.import": { + "bytes": 964, + "sha256": "d2ee2725786dca68b1d21e296c2a81fc279c8259a63c15de06b30e56de54ba76" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0001.png": { + "bytes": 126, + "sha256": "cd86d8a06512f6e1bb97110fdefc9dbbd64ea4d50e0c04158860d8420145c346" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0001.png.import": { + "bytes": 964, + "sha256": "5e6379cb6e1b89c2653fe14cd16e4af5751250648bd67d8030bf501178ec88a4" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0002.png": { + "bytes": 150, + "sha256": "1bee42a448291ff9259c6afee8151478238d1c2f49e74f3323577e0110b8fc67" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0002.png.import": { + "bytes": 963, + "sha256": "c5b344b00fe86fcaba2d8c267d32f64a7f43dc92e5264aea340c25228abc445d" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0003.png": { + "bytes": 126, + "sha256": "2c0b45910d964d71112b81f7be17cc9a24169d4942c64ce8b59ea0f3f7490ca8" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0003.png.import": { + "bytes": 964, + "sha256": "264d6dc36cbe30449296f4cef60534a757c3aa52756565037b74edbc981873e3" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0004.png": { + "bytes": 178, + "sha256": "f3ea334d2be859c68ad1d1ff9c3314905ac12030cd65ce093e4ee8ec3c6b202b" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0004.png.import": { + "bytes": 964, + "sha256": "2b84bf3933f098d37f55ef9f24d6b7159da887ee79a6efed315a6c0b6db3abf7" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0005.png": { + "bytes": 181, + "sha256": "7ed587c0ae06d8c8dfb683ff25b7119c6600f21364a253301a3faf230a1eb0e6" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0005.png.import": { + "bytes": 964, + "sha256": "2cc2a4d9c7321618893d1a933f8105b5d92a67e8642413d3d33291442687a82b" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0006.png": { + "bytes": 164, + "sha256": "34fefe03ad9f435a777c81e56e288ead41dc3a0654088d85b51cb36e5579a0d3" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0006.png.import": { + "bytes": 964, + "sha256": "ff1e3aa0414574cf8f5beca3176fd29f1df73ca0600a1402945bb73d23a6a128" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0007.png": { + "bytes": 180, + "sha256": "883ba3a3fb022b373db047b9dd19ae67f2611e584190a82d45d2b8d3f21dfad2" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0007.png.import": { + "bytes": 964, + "sha256": "575137be3664def1c637addd42c607f761264da52e628567d149023cf58ae87e" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0008.png": { + "bytes": 209, + "sha256": "23721149763a8fd6071857c19e01d0967c769e80ae89bbe968bc88a4816fc4f5" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0008.png.import": { + "bytes": 964, + "sha256": "f4a3987f3cb6f585f59c3b98c3f77059b15e99eeb7d4070d6c2a7164a79180d1" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0009.png": { + "bytes": 174, + "sha256": "c8b7b183b0750dca16581173d7de4862ee01e937b1c414de526da5b75574adff" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0009.png.import": { + "bytes": 964, + "sha256": "da2c7eaf041745c0a29f42c6cae66110b530e4fb87908ffd90b8dcb17c5f4893" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0010.png": { + "bytes": 159, + "sha256": "ba622a41d8fac8885d65c9cac01f35f3c6a3e7782c7c5eb375fafa78bafa9868" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0010.png.import": { + "bytes": 963, + "sha256": "2534a51f498cf3d3c8c9296702fe71ea4194caaff6a1658e6f9d5c5d2d7e252a" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0011.png": { + "bytes": 163, + "sha256": "22b9237af31b12ff6cfaa1ed3b520383e93380c4e1582b7feafd76a9e9344426" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0011.png.import": { + "bytes": 963, + "sha256": "b4eeb06a30b61399af5024ae456a1662f2bc5ffbde4bcab81e1236a830d08cd8" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0012.png": { + "bytes": 160, + "sha256": "dddf38ef416861eb38c499eaf8fdeb62051b577d5e33699fd42b46a198bec5f9" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0012.png.import": { + "bytes": 963, + "sha256": "9a1e2c10e21c981b04ca0b691986bf72276aa765ca3219a4a0fcd044e43afc72" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0013.png": { + "bytes": 110, + "sha256": "4eb6fedc53053420bbe92517109c941bc53cd114094ba9f9b8bc20802548d254" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0013.png.import": { + "bytes": 964, + "sha256": "fd0a12cf8b1eec44461d79c80249c1723611011165a5ae79eaad441ff3083f71" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0014.png": { + "bytes": 143, + "sha256": "0d4f0c82ffb4c4158342fc0d7fc95cef22ff509003d711e84ec3b5ba3cee21f6" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0014.png.import": { + "bytes": 963, + "sha256": "a1539b2fa84f3f45d4b466ba0a2c724bd816116c0bc80c4367a4b53d23668c05" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0015.png": { + "bytes": 110, + "sha256": "fdee6e6ccd725ae07348d4da5740b5837bf516a4e519f55cc6b5c566b5f5aa4d" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0015.png.import": { + "bytes": 964, + "sha256": "6d8c2c207a83ebeb1b75afcbc1611df9776049e36969da75e89c4e0359362690" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0016.png": { + "bytes": 147, + "sha256": "62e5de639001c66c44f2aa84e3fd1eee56d99eb234c82f2d5b2f471663592bad" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0016.png.import": { + "bytes": 964, + "sha256": "8446069b21402c666132507fb5545b6a36d83886e943e1a71622be4d04904050" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0017.png": { + "bytes": 152, + "sha256": "714b92d97d613bbcf4d15c553a0c85fa29a2807a2601ac1395b8f45da6575deb" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0017.png.import": { + "bytes": 964, + "sha256": "3c293374b0765f1ae0c1ac6497bf82d8c133cdb1d717bdc094f77d79120aba20" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0018.png": { + "bytes": 176, + "sha256": "b331519c825010a8d061b740a1127e3d711c2b447d6db1fad27f371acd1a1870" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0018.png.import": { + "bytes": 964, + "sha256": "b560d21a34861afe6e1a539c0ee95f36ac8ce70b711529c23b37d3a24b6820f0" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0019.png": { + "bytes": 182, + "sha256": "77031b04b17129b8142c6ca80dc10d265fb94c39a443f17ecfb2e48d9a7c2a16" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0019.png.import": { + "bytes": 964, + "sha256": "189b85909461ed79467e328a7eeabcad81769e1375891327dd1e35cd689a3ca0" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0020.png": { + "bytes": 211, + "sha256": "8ed3c08b77ef4e6ead26858f95efcaa302f5f014aaf3b26b49dd2bea991eecce" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0020.png.import": { + "bytes": 963, + "sha256": "8c917c6c480095a65fdb0c30b80f338c644ddc16538276ce427f8c3f54a77aa8" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0021.png": { + "bytes": 182, + "sha256": "9def7eb7a3b00190148a55367c08ecfd4a03b66096e585b0c07b6f21277bb4fd" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0021.png.import": { + "bytes": 963, + "sha256": "7bc86d56e6da25eaba3101bf3487dd4906e023cbe4b5b0fd4ce2ee765157e796" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0022.png": { + "bytes": 173, + "sha256": "24298faf91a61a57d158435e9fa75ca30ab88bbfddae797e2a268b1064787f45" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0022.png.import": { + "bytes": 964, + "sha256": "644ef16b27b940649902e7b7895f8466bfdb86c0d6b34551d2e694979d6e877b" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0023.png": { + "bytes": 172, + "sha256": "ff3ac631206dd4882134b8719368519644fd26703ea289a7237924e9d622f208" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0023.png.import": { + "bytes": 963, + "sha256": "a9a132ffbfc88d3daf7da99e0275ecb9e1ad5f640b2f353fc0d0a6f5660e2eec" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0024.png": { + "bytes": 175, + "sha256": "3f4d77da84e948836c16d2c81f2812b7805e76147921f0ea9f047705f709a62a" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0024.png.import": { + "bytes": 964, + "sha256": "6b6adb283d924e90c39057fe14b39a69a82de88c5ce41814941e9b774024e6c3" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0025.png": { + "bytes": 139, + "sha256": "5782701dc1d3d19c26f26cf1b147a044ecbc8535766ffa33ed93eee0e8bec2a1" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0025.png.import": { + "bytes": 964, + "sha256": "64f7e8079d8a7f196426358e88b74d260561bfd15bdaf3e0b91c4475435ada3c" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0026.png": { + "bytes": 185, + "sha256": "a18f13529118365c4054f2b6dc7379190c8d99fc70f2f1c374f6e95f532630ce" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0026.png.import": { + "bytes": 964, + "sha256": "cb5a5a3d5bee910a70df0f8e25fbad07be09ac806d492c2c1db62a7aab4544f6" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0027.png": { + "bytes": 139, + "sha256": "c9ddc3f83a9ecb1d340d2925df3f99f34542d8be1514c53e82c71500c5537ced" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0027.png.import": { + "bytes": 963, + "sha256": "4a7597bc2bda6042e10c7b585d2c3fd2e76630a76943df053df180e147b6737d" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0028.png": { + "bytes": 149, + "sha256": "7a67b0ec169f8a967906b2272927f4d4dd34ee60e0e066ad1544deaa9cf86d08" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0028.png.import": { + "bytes": 964, + "sha256": "c29861abdad7b6b8fc8d4b7cdb87bc4c03143f3c2ed8c874d3eaf227fdd0d18c" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0029.png": { + "bytes": 208, + "sha256": "9a448977535c4af375b3db4800112ecde93e0d794b393e0cacf1dd82b4d9f971" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0029.png.import": { + "bytes": 964, + "sha256": "1a3750e0201db636c8f958ee3aeec374fbe67ca6b63554e7747f330891ee924f" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0030.png": { + "bytes": 138, + "sha256": "50ba69228b0185e84fe73b4beec8837e275c7be1b8bde1981484feeecdf02199" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0030.png.import": { + "bytes": 964, + "sha256": "2a9a4bb022675699f2d1ec7e4729f2f7062eb6dea5e5441359010388c293c4bc" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0031.png": { + "bytes": 171, + "sha256": "3cde5a77140e4d8ed160e37cd14789aa9901c4808e2a6b0c109fd1502ca8deb2" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0031.png.import": { + "bytes": 964, + "sha256": "8a20c49664451213ebde427d13a75784714d48c1045667b273c5aa4ae973e956" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0032.png": { + "bytes": 195, + "sha256": "82ee687a8c6b7929ad25f4f9497a2e96b54b00c68cf174c405b77b74b456df33" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0032.png.import": { + "bytes": 964, + "sha256": "6a6465c0f6de7afcbb777b1f683f8b7e51419df028862a2aed0a9b8c931ccbb3" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0033.png": { + "bytes": 202, + "sha256": "928dcac1d9d2df6fa2ac8916edc35f409605e70e387321a7cbd5ba26ffdc3b5e" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0033.png.import": { + "bytes": 964, + "sha256": "e63e0301efe85bc1809dd9f9bdb6600be5d7f86286326db0e0a5a2a83d0f4c1c" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0034.png": { + "bytes": 196, + "sha256": "7e06aac6ac40317d4699b9bad6c5fdcaea4df1aa350878a6c825089db6133f82" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0034.png.import": { + "bytes": 964, + "sha256": "8cf4d9a16f38acfaaaefd476a625680587832b1af7dfff95526e5775991fb0eb" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0035.png": { + "bytes": 198, + "sha256": "9fa58f97f4b8cd794179d8d2110c6180b69aa2030f449d734d69466b58eed2fb" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0035.png.import": { + "bytes": 964, + "sha256": "9db3eab2eee3fd4dd410a9880de037979ebc93513e0bed55f94fda8ffaaaffa7" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0036.png": { + "bytes": 139, + "sha256": "d0be450733fad7bb93599113861381e3caedb8e0fbf30bd4e120024547689582" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0036.png.import": { + "bytes": 964, + "sha256": "89471bffa6dbeac880929017273905e009530c7d8dcaa6dae5e8d160357d6f1b" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0037.png": { + "bytes": 130, + "sha256": "dff77f0cd9bf86fe3f6ee4ebcb4074c2a30ceba18e5966022b0fc74a339e036d" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0037.png.import": { + "bytes": 964, + "sha256": "2b24f7c317aaa8537d10c9fde48001d6b7c826e072e48ceeabf5c6f2207b1bd8" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0038.png": { + "bytes": 145, + "sha256": "0b8d843daedf04706f865ad877e71d2d9ad1ce1dee01073071d286fd5aafdbdb" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0038.png.import": { + "bytes": 964, + "sha256": "2d5859414e107400a02d7264c45c8e755d2b68a12686fb6fe0a043f75d5df38e" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0039.png": { + "bytes": 140, + "sha256": "7dc16b81fa82f7fdd377d68bac398a8358438599d1036c509de913abcde64683" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0039.png.import": { + "bytes": 964, + "sha256": "f735cec3117457d60f3971d8ef1b9396378556bcabdd81b5d94abc5b0a5c6e91" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0040.png": { + "bytes": 128, + "sha256": "7541f8325e46dc4d5f0707819c0b6cbf48dab832727c2bca54a4380991b6cf10" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0040.png.import": { + "bytes": 963, + "sha256": "2d76e4eba2cc90a8147d17bcc02f995ef34775c6b672172def58aab521e9f393" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0041.png": { + "bytes": 178, + "sha256": "0fbb63362251a29d741280e59f5d9cf29c80c0fcff0532cc9c8530936d873994" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0041.png.import": { + "bytes": 963, + "sha256": "0536ea4e95d8bc1c40f64253cd6b8337d7f64605b708aec08ef3f96ba38fbfc9" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0042.png": { + "bytes": 142, + "sha256": "8dc63d1b4fc05e9ef0dc5ad22788e49e4b37477d4e85de2c2e420d22fe4cd958" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0042.png.import": { + "bytes": 964, + "sha256": "772ad95c984a2cdeea252d17c919252198b5812d589a2db8b47d75a24782c1c2" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0043.png": { + "bytes": 155, + "sha256": "77511b6490f69a9f4991ac807a7a53bb946077883d629ae21f935989709067ea" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0043.png.import": { + "bytes": 964, + "sha256": "65b0a6d2713c91c57bc6c723aea7e31b5651d58f22ec2d9c746150fcb1d8d4ac" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0044.png": { + "bytes": 170, + "sha256": "e4deaf3ebddc654a8e3d075e41cc78a29fd5e5635b3d6646e6b36da10d63ea20" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0044.png.import": { + "bytes": 963, + "sha256": "71e96dc704b1ba28110d8a498373612da745fa0416f61bd26186a1adbc6114c0" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0045.png": { + "bytes": 191, + "sha256": "4f5d0fd34c70872b66f2418b6cae9c9c9e3aca133bdec0b0dbf860ce82f9f225" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0045.png.import": { + "bytes": 964, + "sha256": "e8ab3536295cf9430348c596d45fade72dc5588dad3f5ae9c266af418afdcb62" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0046.png": { + "bytes": 180, + "sha256": "acc19c7eee1b0c89dc9bacda260c7678490967389e41cdd8186c2fe82cee78c5" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0046.png.import": { + "bytes": 964, + "sha256": "b7dbd1c9cf4486c44c5776950faaad696ee08a5e626cbfb04b89c71d3f8f220a" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0047.png": { + "bytes": 178, + "sha256": "ec5c217c482cb5921717c5577049846283f689c993b65ca57a9dff5d245ff635" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0047.png.import": { + "bytes": 964, + "sha256": "637fe3dac5a28dfed0968919601b6f41602b6a8b741454c8b72d57f1e09ec6e6" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0048.png": { + "bytes": 99, + "sha256": "63519065228f5f8af6200d979fa54cd7f00650034ceea10a1609203a34b3ff9b" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0048.png.import": { + "bytes": 964, + "sha256": "cba4428600f9f9ba04c2d2ba9f21dac3e5f8f5f46053db20b51cfce0f658a2d0" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0049.png": { + "bytes": 130, + "sha256": "c4257bfa85878e4d293237cd9a50e72b3e883f721e4fe1c48132514bb93668f2" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0049.png.import": { + "bytes": 963, + "sha256": "7fa9a04310b88953632d038b4333316cf7939ae04d1986b5063a82a142031fc9" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0050.png": { + "bytes": 109, + "sha256": "af45eaf5658a481cbf5645ed006ea59072e8bcdbe481b15a55204179d291f5c7" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0050.png.import": { + "bytes": 964, + "sha256": "b8fb7762d3d8f7a785a3950ea7a9f28e39509c55e24efcea4f4fe7a40389ffc0" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0051.png": { + "bytes": 133, + "sha256": "2c10663f36fbfef2638b018d8ed3c11f1e2e3c62fd63300b13e7aeb39273eb97" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0051.png.import": { + "bytes": 964, + "sha256": "3ca6f522182d9ad8221d99e274a40d4dfee264a9b0376fbe645566f7012d4162" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0052.png": { + "bytes": 122, + "sha256": "d380d7941b23178f8a90ff41f977bb459890f3a5f4b29f9c159859221d8f9704" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0052.png.import": { + "bytes": 964, + "sha256": "8197c899da320e49e6940796eb6400b0dc5339cbbc197daa8aa1b2d68c14ad46" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0053.png": { + "bytes": 110, + "sha256": "e3d67fdc99ebea256141127ccfeb4103821db7dca11d099639de32e60b05b47e" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0053.png.import": { + "bytes": 964, + "sha256": "590f9ef3073e542af9f58859d5edfedbf39f5b885216d1e7a645abe2ba8f842b" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0054.png": { + "bytes": 184, + "sha256": "1a9ae3a209decf1f4b8df62d354edd7dfa1f7d4101ab14819f181a8e51b5ce20" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0054.png.import": { + "bytes": 964, + "sha256": "1ce511a1a0e42e861306810bfd465a5ab74ba8edce54f9a8534072e829592ace" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0055.png": { + "bytes": 182, + "sha256": "5a17519655807550ae9a90ae9618772d6bb67e856b9920ec090ccddcc3057e2c" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0055.png.import": { + "bytes": 964, + "sha256": "e777d42f7be968193a63b57a5a1bb7ad6471a998808b2be37d7d3d8f75949090" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0056.png": { + "bytes": 207, + "sha256": "3dce1fb1d0ab8ecc5b168449b9cac11709a221f53d7dc49d31c4c7c96bd5ea2f" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0056.png.import": { + "bytes": 964, + "sha256": "f1db34ff7f4a308ba9e24fb674d29180e7545e0507c4aff8d212fc964a911a0f" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0057.png": { + "bytes": 135, + "sha256": "2d553978f4663e6fde5d5eb8dce1db9fd9aff9823c04c4ac9b5434625910c6c2" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0057.png.import": { + "bytes": 964, + "sha256": "9319f34fb9368987576820d5ab2e4668651f530aeddcf450239cc2f49105f6dc" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0058.png": { + "bytes": 140, + "sha256": "d010f83dc263ca1b3b4788ef380c7ef5695a21493c7db10e423c9891e2eac730" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0058.png.import": { + "bytes": 964, + "sha256": "3b03fde4d5af174fec7e6445f9c0d0a10943b3adf150d643c890c55c2b90c96c" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0059.png": { + "bytes": 134, + "sha256": "78d2be3cc11b4dfcd3bdc6f90a34ff564f8d8216aa3ad7abf11bdd349bba02ee" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0059.png.import": { + "bytes": 964, + "sha256": "0717f7db32e65e3a39165aea886d068f54daea4c2d17820210bfe7bd601c4746" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0060.png": { + "bytes": 140, + "sha256": "c0c9ba7c823d46b2baf1fd4134c36f8e966b840b5f79a95a7585a0b3252a45a8" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0060.png.import": { + "bytes": 964, + "sha256": "7226f7300362db2c7f07da2572214d2feb462cc60ef9d6bffc05e264be379bef" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0061.png": { + "bytes": 149, + "sha256": "c090e00663c0b81ad5769020fc450f1f0d32fb9420072f41ffcc939cbc25acb8" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0061.png.import": { + "bytes": 964, + "sha256": "f0f1191c80e6540708177aa7e9c86c4665fa5cd879be7aa690142dcb237efc7b" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0062.png": { + "bytes": 152, + "sha256": "cf66bddd9f4b4ecea0ac26406e487cf2639d373a2d5f21f1efd3cc6992272399" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0062.png.import": { + "bytes": 964, + "sha256": "8cc140b869b4a89745e4e2ed20f7979c622dbd9ef0a70da892f0dd3620eb8d9a" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0063.png": { + "bytes": 167, + "sha256": "2c7d1a1fdf12a6cd37cfb82f9c38e18cfc8fe28963d1c33ab97379671cdd1aa4" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0063.png.import": { + "bytes": 964, + "sha256": "a89ee8f834325d059e2fc98d324d0549c186bdbde34d37c98d3914c759c48e5f" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0064.png": { + "bytes": 176, + "sha256": "b2ddf6178c613f3725e1e28830514d378649238e695b0d0b74ca5b471f880fa5" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0064.png.import": { + "bytes": 964, + "sha256": "48a2e71c34dc75c397131503c5d081862f8f46fb31e108ca7297a0f22f5fda0d" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0065.png": { + "bytes": 177, + "sha256": "cb304f8bfba830e8213f357e0ad9b255e63aed2574cf5a2b3c351490d28dabf3" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0065.png.import": { + "bytes": 963, + "sha256": "f7dfae80dfe064a164d026c518a4451ee84503595662ddcef2a08fba6a631ce6" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0066.png": { + "bytes": 192, + "sha256": "601f7619c0103424fb76a2fe0ef6f086fbc29a404f2bfba2dd16fa6dc141e9d9" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0066.png.import": { + "bytes": 964, + "sha256": "1d7c9a74514e5079854177371fa1fcaf8e90012dd70d2abe10acb0529d74729c" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0067.png": { + "bytes": 170, + "sha256": "9cbd5a8a7bf7f43eb6a7429698e99e829c57997c5022018a8b60ba9a70e51ccc" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0067.png.import": { + "bytes": 964, + "sha256": "a894d09c07e462ee26569489fe6fe1e17cb7171faa6c5442f89b61e8e039933b" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0068.png": { + "bytes": 181, + "sha256": "f90351394da9efc3b61293c20378f50d30b3dd531a9fd83b4367927e7bf9c144" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0068.png.import": { + "bytes": 964, + "sha256": "79c8232f2fa454e2746ca3616b99a0701f4ccf0471910a878de40c35de0edd17" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0069.png": { + "bytes": 206, + "sha256": "5a09ecf571abb5bb4d2b727b054d7417a0bafc1ac82a4a0ffe7eccc2561ad556" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0069.png.import": { + "bytes": 964, + "sha256": "71ce9ba09dbab8f2cb4925ed4b2d4463a06d76d098294e99c2f8ab628154ae8a" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0070.png": { + "bytes": 170, + "sha256": "56ae1a17ea808d02da78e58b5d6dc58a6ea62287b4addb81b5a6967dc2245a5a" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0070.png.import": { + "bytes": 964, + "sha256": "2dbaafb49240e3b1e9859328c97af6ad7aa2e5906167faed70dbb6472dab5856" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0071.png": { + "bytes": 201, + "sha256": "33589077ca1518bc453aa63bf2f1810d67422bea07ed5db8f486f8257478d154" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0071.png.import": { + "bytes": 963, + "sha256": "9159e76287627a6abd02deb245de79b2ab4907a4f5bc6533be6fa78b341ba310" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0072.png": { + "bytes": 163, + "sha256": "a977172d74aef292a924c867d7d2744ac1c4720f9a9f7120c0dec4ca1b9e9e00" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0072.png.import": { + "bytes": 964, + "sha256": "b31248d4d6f4fb97d5ed8bd20239270f7e4432eb8b28430c1f5b4e7e2479f474" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0073.png": { + "bytes": 161, + "sha256": "138b74609bc477ca5bacc3c8c2b6d80bfc0362c81f163e7b6dcb063526c97f89" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0073.png.import": { + "bytes": 964, + "sha256": "67303e732e3337229f09cef22f60de192f0e52e02f8159568338afa648a1399e" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0074.png": { + "bytes": 201, + "sha256": "cfb675c1dcc7530a41956004471c8ec27cd5ae19a03d8c424074b855395497e8" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0074.png.import": { + "bytes": 963, + "sha256": "902ce403dbab34973fab0647a91a5584764a9ef8574b3732ef88434444aea6cc" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0075.png": { + "bytes": 128, + "sha256": "5fd90e49d9be0c155f1e6a5cb08099fda486ea6fbb266be20b6b97614b96ddd1" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0075.png.import": { + "bytes": 964, + "sha256": "a6bea1993517fcadd5e811c8e952d70ebeb25e5bd624491551354808b6b27f8d" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0076.png": { + "bytes": 165, + "sha256": "349c56fdf06e20fb6a1ee98e2dea1e70833f4f0cf3a96ace0660d32ee0496631" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0076.png.import": { + "bytes": 964, + "sha256": "d94d68afc48704abe6f902cedb2499a2a9c564ea89c698562a44ed87a5c58244" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0077.png": { + "bytes": 165, + "sha256": "be810b6e4b8cd8dfa9dd06af7a5964648a6683c5a3e8da64bc3233b48a636be7" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0077.png.import": { + "bytes": 964, + "sha256": "67fb9daa0fc4e4ab6f4c0c4e093195f6870ebb56dc496456d1733fa6ef903e97" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0078.png": { + "bytes": 165, + "sha256": "62d47ae44908d577c29ff002a2e73ae1bb07602ff4715a85c9743893ef72546d" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0078.png.import": { + "bytes": 963, + "sha256": "612d41c1b9f6d517a6eede7ef6f7c44d712aba353b07ecc7a7fecebe546998d0" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0079.png": { + "bytes": 174, + "sha256": "c8c819b6054e0c231fae5f9f85dc9a34ed828379f5fdb4456ecd360305ca44c6" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0079.png.import": { + "bytes": 964, + "sha256": "40a708f3a427ff196f23ada3c626d7fdf2e4a975ff35430d980d5800ec5fb948" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0080.png": { + "bytes": 180, + "sha256": "0151695f2890361f16ae4ea585e8f5d80fe0b6c2e82593f5e2ad336fbb7360fe" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0080.png.import": { + "bytes": 963, + "sha256": "ba5c2aaef514ae698ad732d8ff9bb1fa7627addc662b21bcdb03a873330fafd9" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0081.png": { + "bytes": 156, + "sha256": "92edb7e7a7b658e00d2c983d9526ffa5f868071b72f98a645f48fac2b33eb377" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0081.png.import": { + "bytes": 964, + "sha256": "bf72b0393ccf3221a2db8abe0a048cbd271e092de0764034cff65f297c389e92" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0082.png": { + "bytes": 207, + "sha256": "2efb31e30cd6f1527329fe5d7704e41c65a8376d498bf93372f46155600420c9" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0082.png.import": { + "bytes": 964, + "sha256": "397120a5362512b7f0bd7833e8387a4a663cffb172dbf5de2356acb2ec9cd2d7" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0083.png": { + "bytes": 156, + "sha256": "92edb7e7a7b658e00d2c983d9526ffa5f868071b72f98a645f48fac2b33eb377" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0083.png.import": { + "bytes": 964, + "sha256": "6c4cce75a77f9a2f60c00ed3f0b2a24d5dc2bcc7a18d858f2bddb1e234d12124" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0084.png": { + "bytes": 232, + "sha256": "b3909f80a29a0f18729f96a90ebe446ecaf26a195da633f2a6c3dd31f660821e" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0084.png.import": { + "bytes": 964, + "sha256": "174366f354ffd256451e63d8c8fdec0f5f1117e8421770a0235f260e1a75553f" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0085.png": { + "bytes": 230, + "sha256": "377b35acbce5129e8167df1f5d1d0420805990962a37a30f5784b88b81a40ec2" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0085.png.import": { + "bytes": 964, + "sha256": "4cf0b8eea76287942a5e077b514b6eccc6d949763879ac5b871fa775e7c4c2f6" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0086.png": { + "bytes": 224, + "sha256": "0606653ad07e177c06c9782c9fff4b1388c7b67865b6ab0e202f76e8e6f6bec8" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0086.png.import": { + "bytes": 964, + "sha256": "ac854975de21105ba6dc595454d64dc441543c41f2750494d34c37b9e9ae3899" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0087.png": { + "bytes": 239, + "sha256": "321ecd683c4e542e09d368709e75821b8b823b7b98b71bebb39d66cead951315" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0087.png.import": { + "bytes": 964, + "sha256": "08c32b45538b5fcb50494fb65ddbd1bc52d91d0d98615906dbbeeceeaf9a047c" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0088.png": { + "bytes": 222, + "sha256": "ad6715e9bcab60faed303260a21adfca2de09a7950b98384065bcc5df05634b2" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0088.png.import": { + "bytes": 963, + "sha256": "f5086263c65f017bd12a57d0106906d2127e5bf1e46a88c9f2bba702cc39567a" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0089.png": { + "bytes": 196, + "sha256": "0b9fa753068061e816246437466d0c9d3100375ff12b77fe9459a801265c83c1" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0089.png.import": { + "bytes": 964, + "sha256": "eb2748a33689be9043ca98236bc3422c568bdc2dd1bcd3b9703a4b71e082c91a" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0090.png": { + "bytes": 209, + "sha256": "fb4aa142cbbba7d9504ed3ff0d989069e8f1974feb76f25906efd9901d4f9ef4" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0090.png.import": { + "bytes": 963, + "sha256": "f74312cf22349a6b729e5f90eeb732e366189013ea50a24798e405c214605207" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0091.png": { + "bytes": 207, + "sha256": "19a75fbb7df761b7373dac310d5e7dd2aa5a65529f81d4ffc80940c89d0538ff" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0091.png.import": { + "bytes": 964, + "sha256": "10dd0ec158e8ae5439ee217399d481e9c074c16470c66209538b27bcfe67b9a3" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0092.png": { + "bytes": 244, + "sha256": "357e08bc52b8dc318ce003681196dce6d2de41298b6253bbcc9bd10283785b37" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0092.png.import": { + "bytes": 964, + "sha256": "738be56be88ce25f5d7c1629fd8f8ea07d1fdd8792a455dab513fc5b7a9eba4d" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0093.png": { + "bytes": 205, + "sha256": "0ce7aabd23d9784f67ad64d461b132f8bd59932d9cc7dddb98c66edf60a6671a" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0093.png.import": { + "bytes": 963, + "sha256": "57ee53ddc2f013686e0bbd779e71d1e3ddfea8a0c3d7092ff52b44271132df7d" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0094.png": { + "bytes": 170, + "sha256": "56ae1a17ea808d02da78e58b5d6dc58a6ea62287b4addb81b5a6967dc2245a5a" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0094.png.import": { + "bytes": 964, + "sha256": "353c738f45367fbb8adf346e32159f1da8494045a5aa1a4bfbd05101cd518bd4" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0095.png": { + "bytes": 203, + "sha256": "f5c2ce5b8e9e36580df27e8287472c662b360e97c4b8bef669ad70eceb9fc7b4" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0095.png.import": { + "bytes": 964, + "sha256": "98a8fdea72067cd04e28a91bf7f3e594e64acaa925a971f0a1e5b320fab3c0d7" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0096.png": { + "bytes": 206, + "sha256": "b8a0a9376c1c3398a059a1e3226e8f8d6839c1d73ac53ea37425340d762055fd" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0096.png.import": { + "bytes": 964, + "sha256": "84e01bdb8330553ceea96159d1f9ab43ff21c1780b0c121a72182f661b37cd8c" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0097.png": { + "bytes": 225, + "sha256": "20915fde756b990f5b0c86fda557a93a6c306373d7c4fc07a1991f4ace3271b4" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0097.png.import": { + "bytes": 964, + "sha256": "cf3ba40a74fc3f15ac5243ed97bb0c53b4a30686675f19b438dd83a2adf9b097" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0098.png": { + "bytes": 238, + "sha256": "39b7c35f414e086b9c7e0cd2b34693ae370e5382a05b4dbb9964cef20f9769c8" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0098.png.import": { + "bytes": 964, + "sha256": "10999bc0c7ac3c95697d6a3e660ddf35f80da4c42a66af45433fc9d56491633e" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0099.png": { + "bytes": 238, + "sha256": "61af4b9f1f67aa761e89e516ac6d60371175875b78b073b7f6a8415517c66181" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0099.png.import": { + "bytes": 963, + "sha256": "6de6e757766f0caa9653d199673008dc6d6335211001573e011e45a2e666e20f" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0100.png": { + "bytes": 240, + "sha256": "e139ab1d56c599af1cea5a955b705ead18a92d41e8e635b550729383cad9de3c" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0100.png.import": { + "bytes": 964, + "sha256": "0a07ccdfe659db10953ff11dc353efcca2e078409638fb76ae7b38b90120e35b" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0101.png": { + "bytes": 159, + "sha256": "03b7f71be1904c72c71f98d31c5f0f7fd8dceffcd40c19c4232746cbf509f5b1" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0101.png.import": { + "bytes": 964, + "sha256": "c88331b1e5bf2525fe371ce551083e5d807fe45e80eccc5a400f970c807e3591" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0102.png": { + "bytes": 154, + "sha256": "35af44a6fc76a09e7fe625c0becfeac809360774c6a845ec8024dd8db6f5fc3f" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0102.png.import": { + "bytes": 963, + "sha256": "26c7b69214e87a32f5eff0cb2cab6c14fa470770ba25d77b702499dbda6c4887" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0103.png": { + "bytes": 164, + "sha256": "38a3ab676d73fe4219930bad3d0294e045269fd153587b0e21c60843fc13d281" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0103.png.import": { + "bytes": 963, + "sha256": "20e4fd705f9ba1b5808113f7b3f9ea75e48f2ab9711150e11ea307bc03f53474" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0104.png": { + "bytes": 166, + "sha256": "3b38808f0c20a49a9923475022041c46e8a04b47d8621e5186fe153b4bbaed48" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0104.png.import": { + "bytes": 964, + "sha256": "6e8f16d87aa8497efcd064f67d2b89b6147b010e692f4f3320d5e9dcbe8321f6" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0105.png": { + "bytes": 181, + "sha256": "e6ce715420b033cc4b0eb6b26255996a919ef721c0081388d3fa6a964047630d" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0105.png.import": { + "bytes": 964, + "sha256": "c4d1645bff32f5348d51b7603e6efde3ae941f1b521de73e5269a576e000fbdc" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0106.png": { + "bytes": 164, + "sha256": "4958c3b09a0d41b3f21741476274855ab2242b3240e5054657dbc0569c881215" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0106.png.import": { + "bytes": 964, + "sha256": "865bee4b2d6ce88ebed0a8580795f7be241526ac2a3fc0a03c5e0123fdffa3c9" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0107.png": { + "bytes": 173, + "sha256": "66d47c25a72a5be74cb8a15c0e4930ee4c8859f5ba5d04837d953d45649d0873" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0107.png.import": { + "bytes": 963, + "sha256": "874603d2c45ed544e1805feeba616c08d3f8a4f03c8e33e304c1dcf8cfd4d147" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0108.png": { + "bytes": 189, + "sha256": "f15c964db469039861f70bdc75cc5b02ba9351eaa5d7421a85d028131eb12f4d" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0108.png.import": { + "bytes": 964, + "sha256": "69a09b26c14e23d9445a07faa54ba3bc6ee461bf10555df20239fa2fd468c0bd" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0109.png": { + "bytes": 219, + "sha256": "f344d22151345f81fe1b95fdb03cf007747042670bda1540192c14853f35b94a" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0109.png.import": { + "bytes": 964, + "sha256": "a0666a19dfa3d44e4bdc009cdb351b3fd63c364ec0f59b2b76604bd7b16a9973" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0110.png": { + "bytes": 217, + "sha256": "ca2d26579be3738be5abfb74cea388634e212fb991b84701deeda65da4780f1c" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0110.png.import": { + "bytes": 963, + "sha256": "1a0b8a2bdd53085efabf093e3f616f367d82f913363cac47c763a96eed70320a" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0111.png": { + "bytes": 228, + "sha256": "8ecfc9b753e676a3cd1fcf2f8f98cc70c8e814f706f41a7e172508fe15156618" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0111.png.import": { + "bytes": 964, + "sha256": "721e24bcbd148f7f4c328fbb64ca62c296c79de65f21573e6b498432fec7b1bd" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0112.png": { + "bytes": 237, + "sha256": "1e82481db9d95d0cec64ba0ea95b8fadf1e3675936e93731d0ff0e3bc72470b0" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0112.png.import": { + "bytes": 964, + "sha256": "59866ffad84bedc11211a55acf7d79b8c852685e2aa3a880f1f50bc077e4ca6c" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0113.png": { + "bytes": 176, + "sha256": "d8b00568696dfc79269a8f47ab8e19ecf6f080140176034cbf8124b4b143d49e" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0113.png.import": { + "bytes": 963, + "sha256": "3b877b063705382d968413a5a9831b38d105f9bf7dfca7f57d863de84b914869" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0114.png": { + "bytes": 182, + "sha256": "486bea807469ea50e471bd9a8e5d60424386b81b0bbef0c84f3cda285d8cf088" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0114.png.import": { + "bytes": 964, + "sha256": "d17c5713760c3b5b816e60b140bb83977dedb1dd4e1087f3f44efb304878f312" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0115.png": { + "bytes": 182, + "sha256": "ad27340925ae7e936788c22cbd0f7d1922ef5bdd21377f916f1be9af6be4312d" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0115.png.import": { + "bytes": 964, + "sha256": "f9323399e4885b0524543782d1f937303d3d72129259d20cd758883cea17f08c" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0116.png": { + "bytes": 182, + "sha256": "610de03ee2d2a7d452159a885707217ccb17c6c18444418d7f21496d76a65f76" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0116.png.import": { + "bytes": 964, + "sha256": "54f80c6bf2dbaaf1d170741dbcb64357f53cd9830016177da2deedfdc54d848c" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0117.png": { + "bytes": 191, + "sha256": "4f75a60e03d46523afba3c52f73c1fcbe06a7566a87eea9fb9b82320718182bf" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0117.png.import": { + "bytes": 964, + "sha256": "2b9613378efb8da10be4a93c1a6a21e176953afa401d357d10fc36d3d2fd0540" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0118.png": { + "bytes": 200, + "sha256": "43679336db4fca6d7c4b47941f707174cdc4476b75af32e0d9f0bd80677831bd" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0118.png.import": { + "bytes": 963, + "sha256": "6fb44bad0d9991ea3ef306e732a95a5e35a47e6821729a75c1dc6861861eb85a" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0119.png": { + "bytes": 184, + "sha256": "c1a5fcc94e0557e04615186966d5ded2a7b590985f03c4a564de6801aeea4acf" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0119.png.import": { + "bytes": 964, + "sha256": "b595356bf2247fad363b679abe1d407f7fa7ae0f3e9dd8c04e74a8fdbcb7327a" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0120.png": { + "bytes": 195, + "sha256": "2ca96264cc5506bb52a5f7b5d278d0fa8e66e26c4b8242e40db6b46acb9df95e" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0120.png.import": { + "bytes": 964, + "sha256": "aaa24e4d6843a5bd70c55413164859600b953d0827fab6fac48bac570346e13e" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0121.png": { + "bytes": 189, + "sha256": "28466ec899a6e0720f40e4f622aee5925d2e5c50b2409856f36ef65c7eedc532" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0121.png.import": { + "bytes": 964, + "sha256": "9dabb9b5f2634bba49650d5ce11a2192a63b5efe9a65734ebf4f155ce876a21e" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0122.png": { + "bytes": 232, + "sha256": "2cb76164d899e3a5eb42d7cd23ffe8defae130f6ce702a35926cbf61d2d1b569" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0122.png.import": { + "bytes": 964, + "sha256": "50c28de7e6c0a19d29d80d3bbb609fce84b4df463e029fc7a2792651a10a07ba" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0123.png": { + "bytes": 201, + "sha256": "16d8f777b329a6516f32d790b389fd5072622195152680c298d2caf8d723ef8b" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0123.png.import": { + "bytes": 964, + "sha256": "f305af0b0435f3051459c24e6248208475a97dde46ea27044a46c996c08ab725" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0124.png": { + "bytes": 203, + "sha256": "cda39a2ba32af6935e106b5c243ba5ca813a8b2566855b94524485463883196a" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0124.png.import": { + "bytes": 964, + "sha256": "a16dd7e7729a0e77c24a09a0e1e5beb166f1f6712955307a464cec0777804505" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0125.png": { + "bytes": 165, + "sha256": "d576af0d95a09721d174c3f57cb51b3c736e3627330a9bfee110e676d37c3cab" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0125.png.import": { + "bytes": 964, + "sha256": "06f563bdd065bb39b65a04d7360dd267ca4d7f53a0ec05ace48c38fa7303c7ec" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0126.png": { + "bytes": 171, + "sha256": "59dd6e934921a327935f8aa35a24cd949bc04541c0adaed2d0ac46b29fe409c2" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0126.png.import": { + "bytes": 964, + "sha256": "f69c9b184375f986920d09b3705e7e948d79b001bfc83c7c3dd5eecd92540fec" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0127.png": { + "bytes": 171, + "sha256": "4ae08fffdd99c4e14a941e664de4cf9ecba0064cd94e5caae9d4a82a10fe120c" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0127.png.import": { + "bytes": 964, + "sha256": "8e55fd648cb1569eecb8137799cb21ad94ed1bf66728fc85691eaf56ed6a20e4" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0128.png": { + "bytes": 171, + "sha256": "f9d1c49865855dece38e496cdb68458040facf8256831751f4b0ab695a193be9" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0128.png.import": { + "bytes": 964, + "sha256": "33e7e0a2fae88e567d97aaad15205962dce8d2cc9b07bae6bbbc6c833632c816" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0129.png": { + "bytes": 173, + "sha256": "1b0a4efa97420e011f08151149c662dbc7c91be0e3c72caa3e8f5718789908fb" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0129.png.import": { + "bytes": 964, + "sha256": "41bca57b41043e5e95a7fed027a6dae4affef6656af1d4fbe516d1f924017b88" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0130.png": { + "bytes": 185, + "sha256": "a61e8a3fe7e1e6f192d6b6452852274a02768c20a45ef6afa48ec80908a39185" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0130.png.import": { + "bytes": 964, + "sha256": "cb97ac0a485400219fe868e479eb7412d3632349fa5a5d01fb3173567e9a1082" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0131.png": { + "bytes": 181, + "sha256": "0fe7c5448902cef52dd8ed8530eda0a986ad0d2cc0c36c2ee1528fe0c6860262" + }, + "assets/kenney/tiny_dungeon/Tiles/tile_0131.png.import": { + "bytes": 964, + "sha256": "db76c372c023c15a841f3c4afe6678d870a0f7063be9dfc2d15e8478e8343730" + }, + "assets/kenney/tiny_dungeon/Tilesheet.txt": { + "bytes": 238, + "sha256": "1b86fae0b27a628f18cfd89c6e148ea1d727f5ef02fc1dbeb5a6e9f9667bea00" + }, + "assets/kenney/tiny_dungeon/Visit Kenney.url": { + "bytes": 44, + "sha256": "6787defa3ecb6118622e1903b65802c0200628fae5164b51b4fd467f92f3f284" + }, + "assets/kenney/tiny_dungeon/Visit Patreon.url": { + "bytes": 54, + "sha256": "2fcba31333935f4aa35e9de2e74e2b7ba1b1a8011540e08016ff6d81e9dd7490" + }, + "assets/kenney/tiny_town/License.txt": { + "bytes": 567, + "sha256": "c483c167cc3bdfe17c15f957ff847d409f64d81b410b28783636cf3b2b7814c5" + }, + "assets/kenney/tiny_town/Preview.png": { + "bytes": 17645, + "sha256": "9a6a773a4e39bc2082b85f0778d8a106f644233b2b3612c5c2a6fd6e4ce2106b" + }, + "assets/kenney/tiny_town/Preview.png.import": { + "bytes": 949, + "sha256": "23c5150de825abb62e9acc8cfbc0155615188fd0d2016ca72bc9c1a19fef8e0d" + }, + "assets/kenney/tiny_town/Sample.png": { + "bytes": 112122, + "sha256": "cb909e46bf51deb2906eeeb14b323aa42e861a738a734f449dc460ad682e4ccc" + }, + "assets/kenney/tiny_town/Sample.png.import": { + "bytes": 946, + "sha256": "166f5fdb87ec5ab6acdd8c00546debd0f3c49fd17bfdea48f79cfe6566f853c5" + }, + "assets/kenney/tiny_town/Tilemap/tilemap.png": { + "bytes": 5392, + "sha256": "b9e9fb80b95d0b90b52f12d914f000cf16f8b22c1faa815aa94500abfa57bc50" + }, + "assets/kenney/tiny_town/Tilemap/tilemap.png.import": { + "bytes": 956, + "sha256": "d49254af66e48299aa37983a825c20a6a8000dd087777ab72311f2e276c32c15" + }, + "assets/kenney/tiny_town/Tilemap/tilemap_packed.png": { + "bytes": 5042, + "sha256": "3a54d99ecde790d4fdea207a3644cf130fc56fa838f1beb1507c185a95b8e902" + }, + "assets/kenney/tiny_town/Tilemap/tilemap_packed.png.import": { + "bytes": 978, + "sha256": "77e09885d6c47ddf6b08efc8530bc0e8d1a109a48474ea928f3fd905fa167aa3" + }, + "assets/kenney/tiny_town/Tiles/tile_0000.png": { + "bytes": 99, + "sha256": "d4c692ef80ee97b3395b885ae07020d42a106683ff3650df240f8e972bd5a041" + }, + "assets/kenney/tiny_town/Tiles/tile_0000.png.import": { + "bytes": 960, + "sha256": "f6968f744c358aa51ab9003d2fcdb5f170e9852cd8889f88d3cc41e29bccf094" + }, + "assets/kenney/tiny_town/Tiles/tile_0001.png": { + "bytes": 144, + "sha256": "cf3b3df8669e621af90944fb3155b15f13adf203dda464e6149d7318f3660713" + }, + "assets/kenney/tiny_town/Tiles/tile_0001.png.import": { + "bytes": 961, + "sha256": "f090ea04d0af56449114f4015acb0c3625e658688ab4517b40d474ca11a5095f" + }, + "assets/kenney/tiny_town/Tiles/tile_0002.png": { + "bytes": 174, + "sha256": "ea524c6974ad6203f46a3e68a360883d0d53dbbdaa237f6cd81ac6fd5be6ea7c" + }, + "assets/kenney/tiny_town/Tiles/tile_0002.png.import": { + "bytes": 960, + "sha256": "b2811ea61975edd62e7b6ace7bd9b0a5daabb6d5528c3b04295e20bfde39fdb9" + }, + "assets/kenney/tiny_town/Tiles/tile_0003.png": { + "bytes": 176, + "sha256": "05ae1d16efd39ec9ec7315d8dba74f3aa85d4a75780f768cbca584dc96e1d2f2" + }, + "assets/kenney/tiny_town/Tiles/tile_0003.png.import": { + "bytes": 961, + "sha256": "dc9254e0b4bfa9b1bdbd9e95dc187ae5874af3af0b6ba1192efd97b6318d4887" + }, + "assets/kenney/tiny_town/Tiles/tile_0004.png": { + "bytes": 175, + "sha256": "5de3dff614fb984dedcbfb7551d13a984f66d5a0a835df3048b51bc7cfddba57" + }, + "assets/kenney/tiny_town/Tiles/tile_0004.png.import": { + "bytes": 961, + "sha256": "db7d2b3eb1ed7c423712e78580925945cc3663451327f6446faac8fa42200c95" + }, + "assets/kenney/tiny_town/Tiles/tile_0005.png": { + "bytes": 197, + "sha256": "5c09569d7e0351146e194d9beb7b573e0869978334cc9e093a57dea8705e81da" + }, + "assets/kenney/tiny_town/Tiles/tile_0005.png.import": { + "bytes": 961, + "sha256": "a89809d6d638bf94d37172feca26415382ab29b2e7256c5e9792640f1af6dc39" + }, + "assets/kenney/tiny_town/Tiles/tile_0006.png": { + "bytes": 180, + "sha256": "d8046421ac4db5a824d642d26e9fc6532f1b3aa52033f569f7e56e0885b2776d" + }, + "assets/kenney/tiny_town/Tiles/tile_0006.png.import": { + "bytes": 961, + "sha256": "3a0a7fe99c84788ad98876b1c5c11c61d9edda3ef1b8a29c106d198b29c4cd2a" + }, + "assets/kenney/tiny_town/Tiles/tile_0007.png": { + "bytes": 157, + "sha256": "741e857eba60e676711e0193f3b252fc70be469ddc55c7d5fb74fa343d6aae6b" + }, + "assets/kenney/tiny_town/Tiles/tile_0007.png.import": { + "bytes": 961, + "sha256": "886b8d32262690341ed9b7150ea193e9ffb36a5cca53fb7a13dbd0c76fa5d5d9" + }, + "assets/kenney/tiny_town/Tiles/tile_0008.png": { + "bytes": 185, + "sha256": "d9c105e1f635e239dd0a87239c528c57406532ae4c4949ec9555d9fae6fc8bbb" + }, + "assets/kenney/tiny_town/Tiles/tile_0008.png.import": { + "bytes": 961, + "sha256": "49325ea2b2825ccb188b91d7ee7adbfcd9ad7d560d6301907dd000ce958bb49c" + }, + "assets/kenney/tiny_town/Tiles/tile_0009.png": { + "bytes": 180, + "sha256": "1120f5a9a24c9dc40d0857885b9008860d17d89764a0621f90bfdb352930a72a" + }, + "assets/kenney/tiny_town/Tiles/tile_0009.png.import": { + "bytes": 960, + "sha256": "07dc54d40811013e2459070e891552a4d4517558e96e77b7bc46aab749c7ee32" + }, + "assets/kenney/tiny_town/Tiles/tile_0010.png": { + "bytes": 157, + "sha256": "5f3aca3ab97afaa731c0a001725d31fd18874c37bb56d386b74b09430bc52d01" + }, + "assets/kenney/tiny_town/Tiles/tile_0010.png.import": { + "bytes": 961, + "sha256": "ac53ef6aa9e651238b45a01d84674ad6b7d02a40e23cbc91a4374cb4e6227d32" + }, + "assets/kenney/tiny_town/Tiles/tile_0011.png": { + "bytes": 185, + "sha256": "69c6e3e76d76356f16086e922d331cd3baf4b18aed2bf07d242b2c61d1c0719c" + }, + "assets/kenney/tiny_town/Tiles/tile_0011.png.import": { + "bytes": 961, + "sha256": "0a66296762f20a71439e725706f13ded29b545848b54e58a2828af3908a7493d" + }, + "assets/kenney/tiny_town/Tiles/tile_0012.png": { + "bytes": 161, + "sha256": "e1b87cceac398679e30d7cd4feecf4f40b8104515c255ed2d8e4fd4f868bb35c" + }, + "assets/kenney/tiny_town/Tiles/tile_0012.png.import": { + "bytes": 961, + "sha256": "a303b8eae26947cf26ebe2af5e486d9afb0ab63ac032a2e75d446e9faf05e5d4" + }, + "assets/kenney/tiny_town/Tiles/tile_0013.png": { + "bytes": 153, + "sha256": "dff7a37b7fa1be3648dcb1d01be3df26eed3ea5dfb8d8b7ffdcc2af06715c1ad" + }, + "assets/kenney/tiny_town/Tiles/tile_0013.png.import": { + "bytes": 961, + "sha256": "fcdd5f7c83e6e0ce1e963ac2fb2c2f5494ddacbfb97f52cb819db6928dcf379b" + }, + "assets/kenney/tiny_town/Tiles/tile_0014.png": { + "bytes": 161, + "sha256": "1209e77e92dc55b0c6aab326ccf714a6f48fdb8ca447c77aea779b1c95e4d41e" + }, + "assets/kenney/tiny_town/Tiles/tile_0014.png.import": { + "bytes": 961, + "sha256": "ff1a835d2558fe7e73ce7c2eda13ff3f83f041c7e527a30dfed85e9d7cc1f039" + }, + "assets/kenney/tiny_town/Tiles/tile_0015.png": { + "bytes": 193, + "sha256": "e1d230db0d9b559d564a5062ea574e8233d5b0c4cd143377756a38cf11f7027c" + }, + "assets/kenney/tiny_town/Tiles/tile_0015.png.import": { + "bytes": 960, + "sha256": "8e864fddb00db67863069515961eee59da22c68008dcf6cf204fcdf4d0effd38" + }, + "assets/kenney/tiny_town/Tiles/tile_0016.png": { + "bytes": 192, + "sha256": "e491cc2d756b0fe14c19c1484fd79fe086621d2a21fd59f3e7a2d74eecaba561" + }, + "assets/kenney/tiny_town/Tiles/tile_0016.png.import": { + "bytes": 961, + "sha256": "e9748911a1b03eb0eff486d1aebe51b78490b5691efd8559781d5d31f91d04bd" + }, + "assets/kenney/tiny_town/Tiles/tile_0017.png": { + "bytes": 177, + "sha256": "6510f793c7dab1b8307dd23e795ce9c680c1ca0b220c9749c37d5705e2aae70e" + }, + "assets/kenney/tiny_town/Tiles/tile_0017.png.import": { + "bytes": 961, + "sha256": "a9dcd7b2a62098ba7cb479d5cefe95cc401b3c53e69df77798d922d9b2ebf3e2" + }, + "assets/kenney/tiny_town/Tiles/tile_0018.png": { + "bytes": 163, + "sha256": "167c8eeccd110c1c41095a7178524c8c6fa127e47098fcdc16e875bc2c8a8d76" + }, + "assets/kenney/tiny_town/Tiles/tile_0018.png.import": { + "bytes": 960, + "sha256": "7e0b478eddde95e2bb6c4815e8e69bf2ec0f3314804bf5432ea33d0c7615c85f" + }, + "assets/kenney/tiny_town/Tiles/tile_0019.png": { + "bytes": 200, + "sha256": "f7617ce7df2660a9d4aca0aaf317be98bc561306b0e3eef02f7e0c17a0072142" + }, + "assets/kenney/tiny_town/Tiles/tile_0019.png.import": { + "bytes": 961, + "sha256": "88cf92bd4af58c8d83e146e48b96c43665daa7f29307c099694c843de493944b" + }, + "assets/kenney/tiny_town/Tiles/tile_0020.png": { + "bytes": 166, + "sha256": "9bbb26692c6a0b7ba00ad27b1a380f3ecec4d680c597204604bd312a154f7c5d" + }, + "assets/kenney/tiny_town/Tiles/tile_0020.png.import": { + "bytes": 960, + "sha256": "138eda065179c4b0e351aae592a7c354e72db87f512ac72cdb8284f6a7df318b" + }, + "assets/kenney/tiny_town/Tiles/tile_0021.png": { + "bytes": 163, + "sha256": "3e7b7419837373bf32542598d46d1328cce966e9dfed35fd852a37d227f5d6a4" + }, + "assets/kenney/tiny_town/Tiles/tile_0021.png.import": { + "bytes": 961, + "sha256": "6ebc06d6d592940e9025a8d9299ce79675f115c2b8199bd98f434ff8a459726e" + }, + "assets/kenney/tiny_town/Tiles/tile_0022.png": { + "bytes": 200, + "sha256": "5a6c92e91e67d3b4a9751250f5ffa73308f2d47bab5642677ea6c8c0448b9df1" + }, + "assets/kenney/tiny_town/Tiles/tile_0022.png.import": { + "bytes": 961, + "sha256": "2dd49f551a743f78d97add14e3fd720eade4bebdb5a93be7e745205ffd4d059f" + }, + "assets/kenney/tiny_town/Tiles/tile_0023.png": { + "bytes": 166, + "sha256": "e2231d052af8e58b280c881962407316a25df85d1baebc0a4c417833c9035d1e" + }, + "assets/kenney/tiny_town/Tiles/tile_0023.png.import": { + "bytes": 960, + "sha256": "8b75554914d8a511544d00dab06474da86bd7c8d83a5795f1b9439a473d63f36" + }, + "assets/kenney/tiny_town/Tiles/tile_0024.png": { + "bytes": 135, + "sha256": "3ffd3954dfb28615d813744ec3b0638d46f0cd9376426329221b70128719282a" + }, + "assets/kenney/tiny_town/Tiles/tile_0024.png.import": { + "bytes": 961, + "sha256": "828ebde3fa65aeb33fb33265221b0f16a838c949a23c7cb0f08528ea2142f8cf" + }, + "assets/kenney/tiny_town/Tiles/tile_0025.png": { + "bytes": 99, + "sha256": "63519065228f5f8af6200d979fa54cd7f00650034ceea10a1609203a34b3ff9b" + }, + "assets/kenney/tiny_town/Tiles/tile_0025.png.import": { + "bytes": 961, + "sha256": "00d1ae6055b72c2e3666d11c57108f2c2e0427b36ae21eda31033085163c854b" + }, + "assets/kenney/tiny_town/Tiles/tile_0026.png": { + "bytes": 140, + "sha256": "1cc4348d99b6ca90b26e9cda7823a68d549fae0a9859ce3f31bfedff5a405bce" + }, + "assets/kenney/tiny_town/Tiles/tile_0026.png.import": { + "bytes": 960, + "sha256": "0d61d6b74cdc8ac2ae51d9f18d373fff5be6b8453e38b69fb62422ee8330504b" + }, + "assets/kenney/tiny_town/Tiles/tile_0027.png": { + "bytes": 191, + "sha256": "57a64b241ad12af171fda9d081a6641c12c51d1a9648e8c5ad50f314e3d660e2" + }, + "assets/kenney/tiny_town/Tiles/tile_0027.png.import": { + "bytes": 961, + "sha256": "374a9c9b167f1e38367a29e446dec4c2cd23c3fd6bc963992d19c1db47a31460" + }, + "assets/kenney/tiny_town/Tiles/tile_0028.png": { + "bytes": 191, + "sha256": "a8b6bdb8954e01dbe6abebaec6d3eedf4fcfeb825b7d982ed488c57a573fdaac" + }, + "assets/kenney/tiny_town/Tiles/tile_0028.png.import": { + "bytes": 961, + "sha256": "2136deffea0eabda9a9bac872f78e2fe20ae5f091817161d753cc69c9868db13" + }, + "assets/kenney/tiny_town/Tiles/tile_0029.png": { + "bytes": 197, + "sha256": "0d55333ffe4c1d3be705978bdf1c176a871c25a6bde232dfba5c359b1a433294" + }, + "assets/kenney/tiny_town/Tiles/tile_0029.png.import": { + "bytes": 961, + "sha256": "93b48e059cbc3ce7819d80aadb203a6fd784080c9021208d61892ab14e1f1a66" + }, + "assets/kenney/tiny_town/Tiles/tile_0030.png": { + "bytes": 181, + "sha256": "e38e6cb14ff961f6e154483a62f963cdf9a310d91e6fd34c61e70653e0fe2713" + }, + "assets/kenney/tiny_town/Tiles/tile_0030.png.import": { + "bytes": 960, + "sha256": "ce17c94bee4b6332a8d1ee97014b3bc48249410df748b1236029eeccf41b0c38" + }, + "assets/kenney/tiny_town/Tiles/tile_0031.png": { + "bytes": 157, + "sha256": "b0330026a4ee1bb5d0895d2f1310d2caff75512522752ed0a30770783f97bb7a" + }, + "assets/kenney/tiny_town/Tiles/tile_0031.png.import": { + "bytes": 961, + "sha256": "e809fae7d6ba0b594fc116c5090e0c5da97c23f3102f472f8d1d6142b9da58fb" + }, + "assets/kenney/tiny_town/Tiles/tile_0032.png": { + "bytes": 181, + "sha256": "6f527b7f7415362b0c0fc98e5e0c5b370db119dd171ccdfd444e64e46ad99055" + }, + "assets/kenney/tiny_town/Tiles/tile_0032.png.import": { + "bytes": 961, + "sha256": "e42f8ece01e720fe2ede08abd4b8fb704deecc6b1cd4c9c212549bf4c0129d8c" + }, + "assets/kenney/tiny_town/Tiles/tile_0033.png": { + "bytes": 181, + "sha256": "5d03ae0b19ab782816f2c9faf809c6c6fb263a236e3afafd757f1e2411710875" + }, + "assets/kenney/tiny_town/Tiles/tile_0033.png.import": { + "bytes": 961, + "sha256": "291338d0796e250408df1d6072a471c831c012fca17ba52325dc12ac312a802a" + }, + "assets/kenney/tiny_town/Tiles/tile_0034.png": { + "bytes": 157, + "sha256": "23d25bce2e95ac64eb36ca34f0b529f7b6be9d2ba04d2dae48dd33138eb67444" + }, + "assets/kenney/tiny_town/Tiles/tile_0034.png.import": { + "bytes": 961, + "sha256": "db0ea5538b3b4623be7131df48ae7005bf8cfee64c3be11ac395252a786dc7df" + }, + "assets/kenney/tiny_town/Tiles/tile_0035.png": { + "bytes": 181, + "sha256": "0c007c5d64b29dc22c3d02fc7ac772efbe3b22cd353abb1b3f34f2d308ec49cd" + }, + "assets/kenney/tiny_town/Tiles/tile_0035.png.import": { + "bytes": 960, + "sha256": "92ac2cfb3065c8be99e6374c96695dc15b4a72423b21b6b93abc29e934e6fcfa" + }, + "assets/kenney/tiny_town/Tiles/tile_0036.png": { + "bytes": 154, + "sha256": "87f81fe427117ff6fcee2cf40c1b30688e7bcea78cc2933c7354c9d985ffffac" + }, + "assets/kenney/tiny_town/Tiles/tile_0036.png.import": { + "bytes": 961, + "sha256": "4ef2f68a455959fc2dd20752f06aafd8e048c4c65fe82082d206df732612d541" + }, + "assets/kenney/tiny_town/Tiles/tile_0037.png": { + "bytes": 134, + "sha256": "ad8ed926be6b53a9a240d18dc332f4140552258d2c625773acbbdfc9b09a825e" + }, + "assets/kenney/tiny_town/Tiles/tile_0037.png.import": { + "bytes": 961, + "sha256": "7a1abae939a053c98328fe6e9be9659b3fd5a3685fb249b081a91d5d8c0b3da6" + }, + "assets/kenney/tiny_town/Tiles/tile_0038.png": { + "bytes": 149, + "sha256": "6bd82dfc79a21d7eeeacaaa9e6094be415b7a5d2190183ae28bc6ad764623255" + }, + "assets/kenney/tiny_town/Tiles/tile_0038.png.import": { + "bytes": 961, + "sha256": "7dc25f6b476a89d915a55f0069f9b2707ed8444bcc6dfe0b03dd58179908c257" + }, + "assets/kenney/tiny_town/Tiles/tile_0039.png": { + "bytes": 129, + "sha256": "fd9127ce420b7e05ba2bb361a82c9301b95d2c55d3eab899198819e9ba78214a" + }, + "assets/kenney/tiny_town/Tiles/tile_0039.png.import": { + "bytes": 960, + "sha256": "0b8f5dcf1257743ee7a03e3ba49dfdee8f00c5a03221399296ca08894c06166f" + }, + "assets/kenney/tiny_town/Tiles/tile_0040.png": { + "bytes": 139, + "sha256": "1ab17e4b24be7eaeb6d8830c0e763b58a66fe2b8f70c15242fbde5138007d334" + }, + "assets/kenney/tiny_town/Tiles/tile_0040.png.import": { + "bytes": 960, + "sha256": "87da01b580590e80b971bd9d5c5fdac18a0d87055dbfd257b7efabe5bef64263" + }, + "assets/kenney/tiny_town/Tiles/tile_0041.png": { + "bytes": 126, + "sha256": "3db01ff694f3d9f1e492d45913c3f85ff5f704ac262a1404d368c9b272a3f42d" + }, + "assets/kenney/tiny_town/Tiles/tile_0041.png.import": { + "bytes": 960, + "sha256": "41e98373d79adf154517ad43f4dca1ac1d3b644d0ce25533dbebdbc89d97aac5" + }, + "assets/kenney/tiny_town/Tiles/tile_0042.png": { + "bytes": 137, + "sha256": "322a22e1567b667f5f5423767412014ac490968e0f6f6fd22f1721234784f9aa" + }, + "assets/kenney/tiny_town/Tiles/tile_0042.png.import": { + "bytes": 958, + "sha256": "cab4308822577db505b42f85c1cd17db64ce04948297f56471fa603153f5a4a7" + }, + "assets/kenney/tiny_town/Tiles/tile_0043.png": { + "bytes": 166, + "sha256": "1e4364629573e4cf27c3ce616e3003cf1a3fd5ba2928bc46b2aa47070b0a0d41" + }, + "assets/kenney/tiny_town/Tiles/tile_0043.png.import": { + "bytes": 961, + "sha256": "022f4ed4a0db1b4c429b7952ef86c093e531bbfef9157b9529c59ff3670f284d" + }, + "assets/kenney/tiny_town/Tiles/tile_0044.png": { + "bytes": 164, + "sha256": "4653e4c38fe71ce96287eca370385c00c857b017eecb8458713f1e5f5a9ce262" + }, + "assets/kenney/tiny_town/Tiles/tile_0044.png.import": { + "bytes": 960, + "sha256": "5983c4ffc08a221387c7ec9d60eb845d3272e3e4880394157264ae48dca6ad2d" + }, + "assets/kenney/tiny_town/Tiles/tile_0045.png": { + "bytes": 178, + "sha256": "4e64ae7ed028b443d8823ccbbb18b1b90b568b8ce34fb24b24bf07e8582853b5" + }, + "assets/kenney/tiny_town/Tiles/tile_0045.png.import": { + "bytes": 961, + "sha256": "a9385247cfbbe4efd4749035fee6916fcd32947890d75db4ad3841e44cafd2e6" + }, + "assets/kenney/tiny_town/Tiles/tile_0046.png": { + "bytes": 164, + "sha256": "4e2ce8474d9106596cd5c1108f157fb77fe98abbd5a0762a58bc9676f0e1d1a4" + }, + "assets/kenney/tiny_town/Tiles/tile_0046.png.import": { + "bytes": 961, + "sha256": "2be26a70791a7239c22d02f7faf8a7f8de5309c93a775c14c10fd7ff9f15df3e" + }, + "assets/kenney/tiny_town/Tiles/tile_0047.png": { + "bytes": 144, + "sha256": "0928b0048900bad8a7d66b55634b099ed810b1dd2fdca7f80739c0ab8374825b" + }, + "assets/kenney/tiny_town/Tiles/tile_0047.png.import": { + "bytes": 961, + "sha256": "a76a280014249d928b578ce3ac0aaf8432ff544aca9d7fbbce6103163d05504c" + }, + "assets/kenney/tiny_town/Tiles/tile_0048.png": { + "bytes": 166, + "sha256": "7362f4df34b78d83fa8960f193bc15a3efc392c9d5ae7b4e308647051353969a" + }, + "assets/kenney/tiny_town/Tiles/tile_0048.png.import": { + "bytes": 961, + "sha256": "62a3305eb67c45bd9015cb5475c12328661abb02718ac7e3422bfa93a3f2f35b" + }, + "assets/kenney/tiny_town/Tiles/tile_0049.png": { + "bytes": 161, + "sha256": "674c9bb782acc6d640332167bbcee82e0d0984f147a1a6c9afaac983a863491c" + }, + "assets/kenney/tiny_town/Tiles/tile_0049.png.import": { + "bytes": 961, + "sha256": "07e107083d4d22f5f9fc0b68e2ad48c8c3ac805dc48b305767ca8f1c892cac02" + }, + "assets/kenney/tiny_town/Tiles/tile_0050.png": { + "bytes": 171, + "sha256": "c1060ed198ba2114f08972723e8af88b0ceae34300c69c6c81f2d7f17df1aba7" + }, + "assets/kenney/tiny_town/Tiles/tile_0050.png.import": { + "bytes": 960, + "sha256": "c77652aabe7040900a2978d80074a75ed02e065e5c0b6d2ee8e9852ce036b575" + }, + "assets/kenney/tiny_town/Tiles/tile_0051.png": { + "bytes": 167, + "sha256": "8b6383707b4648aef99273bab8be3623866cc2781f9793ca8335c61513381eeb" + }, + "assets/kenney/tiny_town/Tiles/tile_0051.png.import": { + "bytes": 961, + "sha256": "fb471dd4b7adcfb3cbcf03df4c67f5417ada490fc90d70857f0781dc3e4541e4" + }, + "assets/kenney/tiny_town/Tiles/tile_0052.png": { + "bytes": 180, + "sha256": "1ef23eadba9701c44658f19569d6f27322d497ef5c03c4b5dd9dfe793091be53" + }, + "assets/kenney/tiny_town/Tiles/tile_0052.png.import": { + "bytes": 961, + "sha256": "1a896dd5cc8af5a3c997723482a1e19f3fa4898fad890c86f533ce49c81b253d" + }, + "assets/kenney/tiny_town/Tiles/tile_0053.png": { + "bytes": 178, + "sha256": "3d2d467efe3e81b6a0cd75d7260efc675a1833ebf31dd404f1a16622c63c62de" + }, + "assets/kenney/tiny_town/Tiles/tile_0053.png.import": { + "bytes": 961, + "sha256": "2e79dc1b925114994044d5f8a37207f7a6752be450484bd0d722e60c8eb035c6" + }, + "assets/kenney/tiny_town/Tiles/tile_0054.png": { + "bytes": 181, + "sha256": "0681770aa287aececae7838587b8305579c6fd655f4bc0951a2027a60ae09c8a" + }, + "assets/kenney/tiny_town/Tiles/tile_0054.png.import": { + "bytes": 961, + "sha256": "154cc8c2717c3f6aaee3aa66e3c32ccb89316baf3bae7e4287b0ee6d5ccd7855" + }, + "assets/kenney/tiny_town/Tiles/tile_0055.png": { + "bytes": 188, + "sha256": "4febdf70ccacf1d1c9235bcb1b90c2f6fc994b3024c14b51326c04951b3a40ec" + }, + "assets/kenney/tiny_town/Tiles/tile_0055.png.import": { + "bytes": 960, + "sha256": "2a8a425359174b400b0563cb84cd401e58f5fd70baacfd5723806e7febffcd41" + }, + "assets/kenney/tiny_town/Tiles/tile_0056.png": { + "bytes": 146, + "sha256": "932bc465b8e63e6aa052cdd3619facd172c757918bd6367791080044e4195987" + }, + "assets/kenney/tiny_town/Tiles/tile_0056.png.import": { + "bytes": 961, + "sha256": "6d944abd077127192cedbd7ae628975fee1ed21d2ee20d7d1bb4669c9a2bec05" + }, + "assets/kenney/tiny_town/Tiles/tile_0057.png": { + "bytes": 213, + "sha256": "b3fc5ffa2c39365a94f0496206a0248f196eacb95f379f25f3235aef6dfb97e4" + }, + "assets/kenney/tiny_town/Tiles/tile_0057.png.import": { + "bytes": 961, + "sha256": "84de84c3702c5d56ea768e26ac4f4d230c1b1445f560de1895c9e19e82ab7b49" + }, + "assets/kenney/tiny_town/Tiles/tile_0058.png": { + "bytes": 147, + "sha256": "784067a35d87df94dd0b4f7064437082e3dec99889f7481419548950ee191987" + }, + "assets/kenney/tiny_town/Tiles/tile_0058.png.import": { + "bytes": 960, + "sha256": "77f6b6612676d04ff24c92fc20188bda46257abb566a0ea950777503729233b3" + }, + "assets/kenney/tiny_town/Tiles/tile_0059.png": { + "bytes": 145, + "sha256": "90f0a1089064abeb9701110ba5c0770ff13b3b1fc90c459e30523ccf4711f507" + }, + "assets/kenney/tiny_town/Tiles/tile_0059.png.import": { + "bytes": 960, + "sha256": "b53ff8404d94ead2d1c77ec9718edfdfd1338bc3e05cbb823559756fc3131e4e" + }, + "assets/kenney/tiny_town/Tiles/tile_0060.png": { + "bytes": 177, + "sha256": "bd3479d2718ef0a19a30760028ecb21903e3e2c885f00df22164ad23adb85a6c" + }, + "assets/kenney/tiny_town/Tiles/tile_0060.png.import": { + "bytes": 961, + "sha256": "da515cdbdb205d652fb3c9768e7fd87437c524fad062bd6a3d9060a0b2bd0237" + }, + "assets/kenney/tiny_town/Tiles/tile_0061.png": { + "bytes": 166, + "sha256": "decb9f96369b248fb55d27282bcaf9d3b77f7dd214dad9a68f29509b09e1e754" + }, + "assets/kenney/tiny_town/Tiles/tile_0061.png.import": { + "bytes": 960, + "sha256": "b8cb12638e3f9f4c0724bf6ee66569bc2f2f054a1dbd2ddc7efe2cdd4147f599" + }, + "assets/kenney/tiny_town/Tiles/tile_0062.png": { + "bytes": 184, + "sha256": "0dd68a4e4894db1829dd68e66976238245dff035bc57feda7ae0be6aaaf53a43" + }, + "assets/kenney/tiny_town/Tiles/tile_0062.png.import": { + "bytes": 960, + "sha256": "39069d6a3bc18126950a058271df29f7ca7ddcb070349f9f25a743c6abc7f5fe" + }, + "assets/kenney/tiny_town/Tiles/tile_0063.png": { + "bytes": 216, + "sha256": "516b1ad058739d1b8fc0872624e58c376f673a06be23ec6b9df4f101a6bced7b" + }, + "assets/kenney/tiny_town/Tiles/tile_0063.png.import": { + "bytes": 961, + "sha256": "00931f71ac7a37ee93b8f03e9b16b7400b29978d5cc7258667b49468605f26e6" + }, + "assets/kenney/tiny_town/Tiles/tile_0064.png": { + "bytes": 177, + "sha256": "79c68a61e262de5f9895e8d82133b01d492acc2ce2037f5fb751a0c8cfbfffe9" + }, + "assets/kenney/tiny_town/Tiles/tile_0064.png.import": { + "bytes": 961, + "sha256": "8e033388b03957ac28a82e86e2be3d8f2076ffe989c3babdda6f32b3ea345e9c" + }, + "assets/kenney/tiny_town/Tiles/tile_0065.png": { + "bytes": 166, + "sha256": "3436ff701d93e7d8c2cdb28e169c8707f544a36c626dd73d8025396cf5988ef0" + }, + "assets/kenney/tiny_town/Tiles/tile_0065.png.import": { + "bytes": 961, + "sha256": "78bca404552066eedf87570f1935b2d8c33f610025cd4575233ba45dc5b0b0cd" + }, + "assets/kenney/tiny_town/Tiles/tile_0066.png": { + "bytes": 184, + "sha256": "8c622e9280a72751ff2131cdbeb4913b83cc723b86580c05b1cb35d64ed7f624" + }, + "assets/kenney/tiny_town/Tiles/tile_0066.png.import": { + "bytes": 961, + "sha256": "1e84d8e04c5c1c5e24780702771126eb7700194467fd4cc936e4cb1cf98d5005" + }, + "assets/kenney/tiny_town/Tiles/tile_0067.png": { + "bytes": 216, + "sha256": "48919b108e67e1601e12b737e026c1c73e6f95fa1f1231483efe23f31e125cec" + }, + "assets/kenney/tiny_town/Tiles/tile_0067.png.import": { + "bytes": 960, + "sha256": "699fd44a78955fb5436928c4245231ab9428501f36fb667a7f967274cb1886c3" + }, + "assets/kenney/tiny_town/Tiles/tile_0068.png": { + "bytes": 164, + "sha256": "5f8175226f03497c12f39cb66780f5cbe58bcecaa4e5a1298de7a547f0bfbc1e" + }, + "assets/kenney/tiny_town/Tiles/tile_0068.png.import": { + "bytes": 961, + "sha256": "5f10b6c64a6bbdf8e9558daa05be63e4237eb7538c3f37c398df56cfb7b8e226" + }, + "assets/kenney/tiny_town/Tiles/tile_0069.png": { + "bytes": 171, + "sha256": "1a3a354c78a2e4a6461f5374b57f104c3270b50812d2565d488663b6f9c1f5a7" + }, + "assets/kenney/tiny_town/Tiles/tile_0069.png.import": { + "bytes": 960, + "sha256": "200f8e5f5e5da2435eeee2d90f7e0388d5156ba45da2870efdc26ad89f62ba23" + }, + "assets/kenney/tiny_town/Tiles/tile_0070.png": { + "bytes": 165, + "sha256": "b207c0fff948c9c2125e6ec44328762004665275c9efad248694f9dc28bebbc8" + }, + "assets/kenney/tiny_town/Tiles/tile_0070.png.import": { + "bytes": 961, + "sha256": "caad2093470efc0ec2aa61203f450dac782caf5cd3b402029ac194a70f71057e" + }, + "assets/kenney/tiny_town/Tiles/tile_0071.png": { + "bytes": 139, + "sha256": "a5e4e4db70672d69648f7d3924918b8202a2df9e88b9fafbcbcb7f7def8e6700" + }, + "assets/kenney/tiny_town/Tiles/tile_0071.png.import": { + "bytes": 961, + "sha256": "907f233ab6d10dcfbd4d1370e231ab54ed95476f257cb75959c26d44b4c5a207" + }, + "assets/kenney/tiny_town/Tiles/tile_0072.png": { + "bytes": 137, + "sha256": "ff633e7a44d17849da050def1d96ebd431aa05147ac96938c3c5e1286d66b646" + }, + "assets/kenney/tiny_town/Tiles/tile_0072.png.import": { + "bytes": 961, + "sha256": "e19a515cc46b736f61a64b950fc841703760003a3924492ecd6f5763584abd87" + }, + "assets/kenney/tiny_town/Tiles/tile_0073.png": { + "bytes": 129, + "sha256": "b20e305ce6c9c9b6e2d0cfec786fa45814d0a635b477d2084e2df0d31273ae8a" + }, + "assets/kenney/tiny_town/Tiles/tile_0073.png.import": { + "bytes": 961, + "sha256": "0ba587a018b2c7a02344a91417afaca3c16cc982530e33a3cfe62341fb98ac50" + }, + "assets/kenney/tiny_town/Tiles/tile_0074.png": { + "bytes": 155, + "sha256": "1cfedee7d389983b950901a197746a7d574b1fdee51840920dde20334eefff54" + }, + "assets/kenney/tiny_town/Tiles/tile_0074.png.import": { + "bytes": 961, + "sha256": "6736c99a43bde5a291d5d72e933efad22b2618699f1bcbb646d69c33dd5f7ff3" + }, + "assets/kenney/tiny_town/Tiles/tile_0075.png": { + "bytes": 143, + "sha256": "5c455ecf2c89e5bf6884cd02f63b3ecef79ea9669092ebfe3ac08933252ed0ff" + }, + "assets/kenney/tiny_town/Tiles/tile_0075.png.import": { + "bytes": 961, + "sha256": "0966b8421041d0da914550a814d080aeaaaab08f0754e46de6887a9f53a6a76c" + }, + "assets/kenney/tiny_town/Tiles/tile_0076.png": { + "bytes": 137, + "sha256": "8d36d3a43d2e9a7b75f4d05874b6c4019b0af6aff44fcab5325048c264c15742" + }, + "assets/kenney/tiny_town/Tiles/tile_0076.png.import": { + "bytes": 960, + "sha256": "7754af9b6fee9ea2269cbb147864e22332cb5860af3f5a0f34c62f68444a48f9" + }, + "assets/kenney/tiny_town/Tiles/tile_0077.png": { + "bytes": 129, + "sha256": "41d237731631ec4179146a19605265169843d5ce923c5f89375041d09ca90a11" + }, + "assets/kenney/tiny_town/Tiles/tile_0077.png.import": { + "bytes": 961, + "sha256": "412ac2e09108673cf00ef45dedde2aa0e9c415523d7891379e1573280309a747" + }, + "assets/kenney/tiny_town/Tiles/tile_0078.png": { + "bytes": 155, + "sha256": "fe06ebf43b8efaec63c05bd9f690f2c36a33bd9eba327fc721d445e4f6745f2e" + }, + "assets/kenney/tiny_town/Tiles/tile_0078.png.import": { + "bytes": 961, + "sha256": "2238193fc35af1e7d14bbbf6689a0475e8a5e222c0dc79cd946d41cd434ff7ff" + }, + "assets/kenney/tiny_town/Tiles/tile_0079.png": { + "bytes": 143, + "sha256": "ea29e62b839d2b6495062c6269f885752ad6932137a5636da599fd216efa9e1e" + }, + "assets/kenney/tiny_town/Tiles/tile_0079.png.import": { + "bytes": 960, + "sha256": "5be87d86ca1f820c32968aa9b435f9484f8fce4e8a83277051950200728e2446" + }, + "assets/kenney/tiny_town/Tiles/tile_0080.png": { + "bytes": 160, + "sha256": "c0270191499831acc29fb3f32eedc436acbc0c7e471c13ea0412ba76657090dd" + }, + "assets/kenney/tiny_town/Tiles/tile_0080.png.import": { + "bytes": 961, + "sha256": "697e871fcd16e8fc0c63198c01204f16a13c58c039bf9d867f5acf1cad76b223" + }, + "assets/kenney/tiny_town/Tiles/tile_0081.png": { + "bytes": 120, + "sha256": "ad179a7fc3d6438202c7f2762ceb13cb6decdd44fcc40e4465bdf763fc6915cc" + }, + "assets/kenney/tiny_town/Tiles/tile_0081.png.import": { + "bytes": 960, + "sha256": "4945a9b4b3baf2f1df805c1d0bf1cf50c82a50667b32603fca7b94a742e79b11" + }, + "assets/kenney/tiny_town/Tiles/tile_0082.png": { + "bytes": 162, + "sha256": "f21b75210f83d5d937ab9fa37a24052222e96d9450b57baa9518d21e4431c8fb" + }, + "assets/kenney/tiny_town/Tiles/tile_0082.png.import": { + "bytes": 960, + "sha256": "fe7f2ba83bce390202f2bee357c19ba66c18a739e8c73085b396f1736f7230cf" + }, + "assets/kenney/tiny_town/Tiles/tile_0083.png": { + "bytes": 189, + "sha256": "07b9cf1d4c066f91979688db542bb7fbca663608c98e596a0882d9c3838324a8" + }, + "assets/kenney/tiny_town/Tiles/tile_0083.png.import": { + "bytes": 961, + "sha256": "12ef99196ca4a9057528d3bc5d2fd543144dd26a148cc8c58b156e7aa8f4cdc1" + }, + "assets/kenney/tiny_town/Tiles/tile_0084.png": { + "bytes": 170, + "sha256": "a652e2b1fbf1cff607f83db9c810a9fa65c794c55bebef5cb07658d960b6b219" + }, + "assets/kenney/tiny_town/Tiles/tile_0084.png.import": { + "bytes": 960, + "sha256": "d9a897eeb6dd0f8b508c91b08d3498f7871057ccb3827b1e5beff68cc0bfaba7" + }, + "assets/kenney/tiny_town/Tiles/tile_0085.png": { + "bytes": 163, + "sha256": "7ca5d76ab45b5aa9be4f19c9953e3bee4b64822642f47a4c9b8bd3f94ab6f737" + }, + "assets/kenney/tiny_town/Tiles/tile_0085.png.import": { + "bytes": 961, + "sha256": "7a328160efa2289d804f9a3d8ee602e2dc7ab735e09b60056c657cde694aba2c" + }, + "assets/kenney/tiny_town/Tiles/tile_0086.png": { + "bytes": 161, + "sha256": "1ed488f6faf0d68facc719882d2a1fd287d1979b8d0a21c07371bfeeb3923566" + }, + "assets/kenney/tiny_town/Tiles/tile_0086.png.import": { + "bytes": 960, + "sha256": "a4e6f6d5afee32d06ad9e85e12ed56a0baa8899a462b4cdbf81b2cb5f5b51b02" + }, + "assets/kenney/tiny_town/Tiles/tile_0087.png": { + "bytes": 161, + "sha256": "547c739a99c8fca12ce585db1ee4ab7ac5a0d9eafdda747dad6536325f5ed0fa" + }, + "assets/kenney/tiny_town/Tiles/tile_0087.png.import": { + "bytes": 961, + "sha256": "26656278121da4bca26aa3f9d27b70ab5b39b6451bd8666506c5f0c9d95ff21c" + }, + "assets/kenney/tiny_town/Tiles/tile_0088.png": { + "bytes": 167, + "sha256": "0230599ad30c0611af993c6f7e026eb752e6033b51209af5c83b234725a8b913" + }, + "assets/kenney/tiny_town/Tiles/tile_0088.png.import": { + "bytes": 961, + "sha256": "7cfe030caff15f29385cf6b0406d917cf84b849b984df9cae89416da00ca6b33" + }, + "assets/kenney/tiny_town/Tiles/tile_0089.png": { + "bytes": 163, + "sha256": "245aefd71d4c720401c6c33181266cc9da920a802cc275ee2da0c39a240bbc2b" + }, + "assets/kenney/tiny_town/Tiles/tile_0089.png.import": { + "bytes": 961, + "sha256": "2f60ce1e1373db581a3462deaf4d6fc2be9ec63b4e890df85672d1c41c70b829" + }, + "assets/kenney/tiny_town/Tiles/tile_0090.png": { + "bytes": 161, + "sha256": "cdb2b297444549e861cb091f0fbd2bc4d7c4b9203a1e0add4a6e7c4809d35cc4" + }, + "assets/kenney/tiny_town/Tiles/tile_0090.png.import": { + "bytes": 961, + "sha256": "99f90fb207c0b22c65a33db19b733c56e5b29bb406f24ce4e88f5f01c2cb82be" + }, + "assets/kenney/tiny_town/Tiles/tile_0091.png": { + "bytes": 162, + "sha256": "d74235f5b7d9d5ef85acdd9d15c0db3d7e0cd52e19029055f483522dc58fd1a9" + }, + "assets/kenney/tiny_town/Tiles/tile_0091.png.import": { + "bytes": 961, + "sha256": "f6d2326f62e7fc34e4bae036c8a967ae455d3a8ea329c57eaa07e33eb7c4adb5" + }, + "assets/kenney/tiny_town/Tiles/tile_0092.png": { + "bytes": 158, + "sha256": "9e8df390488fef72d302553abb57028841b030e4ff91681d8fe8b36ef28b8d81" + }, + "assets/kenney/tiny_town/Tiles/tile_0092.png.import": { + "bytes": 961, + "sha256": "ac51f70444b409ca5442afe48848d9c7f3a4e943f3986336905d68ba55ed0bbf" + }, + "assets/kenney/tiny_town/Tiles/tile_0093.png": { + "bytes": 162, + "sha256": "d432578df64a8e4cc5cefe559129badefd30a9e9ad988eef6e1470bba7eb9fc1" + }, + "assets/kenney/tiny_town/Tiles/tile_0093.png.import": { + "bytes": 961, + "sha256": "d380996a6c507801dbe04d841f47b0522e16d41a09f99ee2dce083155047d627" + }, + "assets/kenney/tiny_town/Tiles/tile_0094.png": { + "bytes": 185, + "sha256": "e513be719af08aa8e365bc6a731b950bb76feed4da04ef41836ffbaa4e387b15" + }, + "assets/kenney/tiny_town/Tiles/tile_0094.png.import": { + "bytes": 961, + "sha256": "6cff2660a7ee61fa068633e05479c201127d318f6e83f181d22e882f6d1b6e7c" + }, + "assets/kenney/tiny_town/Tiles/tile_0095.png": { + "bytes": 195, + "sha256": "4e67c3f041644af772b07705741d68ae4efee4b7ab642b64797b64c9ef1556e7" + }, + "assets/kenney/tiny_town/Tiles/tile_0095.png.import": { + "bytes": 961, + "sha256": "31429e87600fdf3693aef1d5fd51012ef742fd129c12c235f6887ec0735faf16" + }, + "assets/kenney/tiny_town/Tiles/tile_0096.png": { + "bytes": 189, + "sha256": "c62b7cd4a8397dc1d7be794246ee5a05aefef46ae320db1cf1aa9d2e752899ed" + }, + "assets/kenney/tiny_town/Tiles/tile_0096.png.import": { + "bytes": 961, + "sha256": "5b6a0546a1edbff4de281d0dd272807414c7de1309f3c479ce22571f7d2afe6a" + }, + "assets/kenney/tiny_town/Tiles/tile_0097.png": { + "bytes": 139, + "sha256": "93ff83f1b5d2e4485215acefe592bfb02ef735a230ba067d9d4d81f9b6343902" + }, + "assets/kenney/tiny_town/Tiles/tile_0097.png.import": { + "bytes": 961, + "sha256": "685d08e0675a47ea61a84f776381467b696db9ac1ec754e9241f1feeb0331162" + }, + "assets/kenney/tiny_town/Tiles/tile_0098.png": { + "bytes": 181, + "sha256": "61406b531c360228979cc37cb7f31af32aea8c099cc1c7a7e5a7df67a86bfe3f" + }, + "assets/kenney/tiny_town/Tiles/tile_0098.png.import": { + "bytes": 961, + "sha256": "2ca232e6bb0a5d9e2d6f89985bcc0026c9c5cd4907bc05d3734b436383b3acc2" + }, + "assets/kenney/tiny_town/Tiles/tile_0099.png": { + "bytes": 171, + "sha256": "703b8144c0a570d64d9a586d37ed41ff3b4f414aa9dfb042e1a1e54f546eee33" + }, + "assets/kenney/tiny_town/Tiles/tile_0099.png.import": { + "bytes": 961, + "sha256": "855a5c1661ea028960514415091fd90c407f033d3e87df46655c4fe13e8cce18" + }, + "assets/kenney/tiny_town/Tiles/tile_0100.png": { + "bytes": 132, + "sha256": "535aef9ec659d745835aa54be8ed322642f8397183a52af2e9fb902c21a2deed" + }, + "assets/kenney/tiny_town/Tiles/tile_0100.png.import": { + "bytes": 961, + "sha256": "951a74e0dc5a944d9f400d46b16b8d2c7d82022b8d9d26967245c3904e4812a0" + }, + "assets/kenney/tiny_town/Tiles/tile_0101.png": { + "bytes": 174, + "sha256": "b553572407b1587f0ef3b3de1dd0d600a02e6444a957c05d2402fcba2fb16bfa" + }, + "assets/kenney/tiny_town/Tiles/tile_0101.png.import": { + "bytes": 961, + "sha256": "ef8ff0d431d7b3aff15e8eeb3b67898d969ade9b65608f2e4fd569384b3ca92e" + }, + "assets/kenney/tiny_town/Tiles/tile_0102.png": { + "bytes": 175, + "sha256": "13811299a06a324bbb873d4bbac79e5c74c5f19eaaa2176f509f7b9a206a6157" + }, + "assets/kenney/tiny_town/Tiles/tile_0102.png.import": { + "bytes": 961, + "sha256": "cfe7fece18897a4d323fdcca0ab9eafb4598c8acda4a6438b55dbf93c8e17715" + }, + "assets/kenney/tiny_town/Tiles/tile_0103.png": { + "bytes": 196, + "sha256": "af835af3f3f517b324cd363460cef7eeff4f97d6db834627e6c945d2c92d87aa" + }, + "assets/kenney/tiny_town/Tiles/tile_0103.png.import": { + "bytes": 961, + "sha256": "95fc75cc93e94d2e970570dfd1a6b540afdb27a4baa3a31b8fad59e7425f9760" + }, + "assets/kenney/tiny_town/Tiles/tile_0104.png": { + "bytes": 242, + "sha256": "3befce5d6373d4315f35eeed22752bb1cf7a2ab5d008ce26dd6b4aebbb278978" + }, + "assets/kenney/tiny_town/Tiles/tile_0104.png.import": { + "bytes": 961, + "sha256": "daa8e56abf154e0df79e1a4285e6ffd6151778c33c2377f3d54ec576570a3556" + }, + "assets/kenney/tiny_town/Tiles/tile_0105.png": { + "bytes": 198, + "sha256": "6a8405b5a036ca3ca902a500b74a4bfcf8a71eb5b343e45303a6949b0d67d36d" + }, + "assets/kenney/tiny_town/Tiles/tile_0105.png.import": { + "bytes": 960, + "sha256": "9957146790cd7962483c9e255e11eafad16d18671f7db4c8a2777be132a40ca8" + }, + "assets/kenney/tiny_town/Tiles/tile_0106.png": { + "bytes": 178, + "sha256": "f915896f745a28497de7c86602b64b0a3bcabb7821103965926ea768b5476b18" + }, + "assets/kenney/tiny_town/Tiles/tile_0106.png.import": { + "bytes": 960, + "sha256": "6efe39a74ebdd3d51118b9d1b70604d38c27dea591498c9d18207b2b6a2b2ed8" + }, + "assets/kenney/tiny_town/Tiles/tile_0107.png": { + "bytes": 202, + "sha256": "a6783dabf3053b2a00c58fa7a8d7ff27b0ffdd08dcbe695b1ec82d0c2d312154" + }, + "assets/kenney/tiny_town/Tiles/tile_0107.png.import": { + "bytes": 960, + "sha256": "3954067d009d2fcc94111910e44292edd1eb76c251b3ac294755210a19a7c425" + }, + "assets/kenney/tiny_town/Tiles/tile_0108.png": { + "bytes": 122, + "sha256": "462f00726b47e1363d746524d37d9ef53de426b25cb651057c6f19db97cc5acc" + }, + "assets/kenney/tiny_town/Tiles/tile_0108.png.import": { + "bytes": 961, + "sha256": "1ac6904d56af75bfd5ecd84cb59c80103a617d09739293d486b58a3b9ad69db8" + }, + "assets/kenney/tiny_town/Tiles/tile_0109.png": { + "bytes": 99, + "sha256": "d1ff475a1ad0d4fd5d2c2a8b1fe3b96657d10f9c5b87d204138f1d7a58ac9d04" + }, + "assets/kenney/tiny_town/Tiles/tile_0109.png.import": { + "bytes": 961, + "sha256": "78b032d49ccd649cd288045b85f0c74df052dd9ed376bea18b5d546047749a67" + }, + "assets/kenney/tiny_town/Tiles/tile_0110.png": { + "bytes": 121, + "sha256": "0de41607a1269aa7a890461c249528d85b9eeb10745b130e95c8395c8a45b9c1" + }, + "assets/kenney/tiny_town/Tiles/tile_0110.png.import": { + "bytes": 961, + "sha256": "56ab25e375ba37f449c843cee36a51b119958a6b6e53251e3beddac1d77a5493" + }, + "assets/kenney/tiny_town/Tiles/tile_0111.png": { + "bytes": 203, + "sha256": "5af9d32868dfab9ff81d9f23db0d966c899c5942ebf167cb9d09eba052d1ca8c" + }, + "assets/kenney/tiny_town/Tiles/tile_0111.png.import": { + "bytes": 960, + "sha256": "fe4ec25112c130c2ebc023563b7d76a6e8e59fa93796a609397d7424a939aa9b" + }, + "assets/kenney/tiny_town/Tiles/tile_0112.png": { + "bytes": 203, + "sha256": "6b92320e5dadb0062ab8d1fb06dc088a50f5a45660b8feca67a26c9687fe6a0a" + }, + "assets/kenney/tiny_town/Tiles/tile_0112.png.import": { + "bytes": 961, + "sha256": "ffd9a5f6154ef4c4afa34fb5915c307f314eaa1a07b8b4d021fd38fe55581219" + }, + "assets/kenney/tiny_town/Tiles/tile_0113.png": { + "bytes": 200, + "sha256": "3e78c40c8587a279b3ddd896230d8ab39013f38f854e675db69447c2c1b5c002" + }, + "assets/kenney/tiny_town/Tiles/tile_0113.png.import": { + "bytes": 961, + "sha256": "e3b7b4daa7b0eb30cbd12d4354b9961f4f04038ac68e7d151ccaa76d91e2a861" + }, + "assets/kenney/tiny_town/Tiles/tile_0114.png": { + "bytes": 200, + "sha256": "3d89b0b1ebed238aecfa84a251d9eb1bab87a5ae34fac5e91d788176ed523f41" + }, + "assets/kenney/tiny_town/Tiles/tile_0114.png.import": { + "bytes": 961, + "sha256": "f7f9bba33ba916a2f774c38657dd4d453c11a0fceaa7c1c56ff7eb7424eee936" + }, + "assets/kenney/tiny_town/Tiles/tile_0115.png": { + "bytes": 186, + "sha256": "3a2c43fb289410ebbe9a4301a664fdb3694583fc338743e0f9ecdb523db9bad3" + }, + "assets/kenney/tiny_town/Tiles/tile_0115.png.import": { + "bytes": 961, + "sha256": "76dd9dc8bd75d823c9c02b5817247d7678a1ac6ade13252f13670bb186101925" + }, + "assets/kenney/tiny_town/Tiles/tile_0116.png": { + "bytes": 184, + "sha256": "5b5b45a7f2f756fe0251f84281ae5733b4bcff2b7167d432414c638a722fcc36" + }, + "assets/kenney/tiny_town/Tiles/tile_0116.png.import": { + "bytes": 961, + "sha256": "b8a53e6e601ba6703431de2126aa95a08e3242db5b1ea120e3049fb069429b9b" + }, + "assets/kenney/tiny_town/Tiles/tile_0117.png": { + "bytes": 172, + "sha256": "d2be7fbb7b9c2a278dcbe2fc54af0e9f08e0f0c565c5f6f96cf44562deef0665" + }, + "assets/kenney/tiny_town/Tiles/tile_0117.png.import": { + "bytes": 961, + "sha256": "186f8220eca2a2660305cd2c232a7061acd636470251e469040ca807cb0c2ef8" + }, + "assets/kenney/tiny_town/Tiles/tile_0118.png": { + "bytes": 183, + "sha256": "81c5aeea97f62be85676741339089472d44e42cb907f08adb63c47b8db739bc1" + }, + "assets/kenney/tiny_town/Tiles/tile_0118.png.import": { + "bytes": 960, + "sha256": "78511c07c70676b4ca4a8b028470feeb821e0186c9173834364133448e7c8e20" + }, + "assets/kenney/tiny_town/Tiles/tile_0119.png": { + "bytes": 183, + "sha256": "30091d93126c683011d0866c54c755d631af69b97c396c3a6b3e285a9da6a2f8" + }, + "assets/kenney/tiny_town/Tiles/tile_0119.png.import": { + "bytes": 961, + "sha256": "267aa293934aca4e30439150dac471b029391511da59ace9633aa573aabe024e" + }, + "assets/kenney/tiny_town/Tiles/tile_0120.png": { + "bytes": 158, + "sha256": "42c3fe979bb36603b5349f87eb2beb31b29459ef72c5b34e421ea0ae67714fd2" + }, + "assets/kenney/tiny_town/Tiles/tile_0120.png.import": { + "bytes": 961, + "sha256": "cf7e72e5342958150af8bd04bf7468cefe4edba0e656265325a30a203a977e46" + }, + "assets/kenney/tiny_town/Tiles/tile_0121.png": { + "bytes": 141, + "sha256": "c23db7cbd39871a8b57be75f3d4b528b8e787997f96fdf367b350f1241e43305" + }, + "assets/kenney/tiny_town/Tiles/tile_0121.png.import": { + "bytes": 961, + "sha256": "a74e8dad6a0d3cd6d8e3f7772f15a9be76fbb98a7ff07d335ccaabcba6d42441" + }, + "assets/kenney/tiny_town/Tiles/tile_0122.png": { + "bytes": 163, + "sha256": "d8a941d06fd2373157dfcdcc3681ad2f930c044d64870ce5ef8500e9472d8c59" + }, + "assets/kenney/tiny_town/Tiles/tile_0122.png.import": { + "bytes": 961, + "sha256": "bf3dbaf401f99a1150659d912c41fdc59428cf07d4054dfd7ed3eb15a96f3202" + }, + "assets/kenney/tiny_town/Tiles/tile_0123.png": { + "bytes": 145, + "sha256": "e3fd78cfaf7625dcd088a0d870568f1e186f67999ab4849eee4b988f6b796d1c" + }, + "assets/kenney/tiny_town/Tiles/tile_0123.png.import": { + "bytes": 961, + "sha256": "5db42a1bcf830c8341c91b1fa8a536cf9e7d6f6ceff36e91010681529e223358" + }, + "assets/kenney/tiny_town/Tiles/tile_0124.png": { + "bytes": 146, + "sha256": "35195776721b22c59b4e6ac2b36534d5da18bc686ab98049d6466bcfae2ee96e" + }, + "assets/kenney/tiny_town/Tiles/tile_0124.png.import": { + "bytes": 961, + "sha256": "5bdae429cbf30df9f50111462d34bee53182f165d240ac45cf980a17720851e6" + }, + "assets/kenney/tiny_town/Tiles/tile_0125.png": { + "bytes": 186, + "sha256": "fd107e639cb7bde68f84ebd244bc7171a652a9b5b902661fb38a8dd8e2473f69" + }, + "assets/kenney/tiny_town/Tiles/tile_0125.png.import": { + "bytes": 961, + "sha256": "c27dc5eff3274a9697cc15ec8b1a961b3d29cde968f5b3bff9e8b9b40184a8b8" + }, + "assets/kenney/tiny_town/Tiles/tile_0126.png": { + "bytes": 140, + "sha256": "ef91491aabacc8a11c417f5aed4e40817fc0dafd1e772772dca3ea74466ed6b8" + }, + "assets/kenney/tiny_town/Tiles/tile_0126.png.import": { + "bytes": 961, + "sha256": "23eb7ba1905c5c333c02c0e53c60cd0ba0e4de48e87b55f75451e005063f2ed8" + }, + "assets/kenney/tiny_town/Tiles/tile_0127.png": { + "bytes": 184, + "sha256": "22dc3bd37cc7419f14b51f81e7e2b26794a4143b239c35d9d4288d69dc987432" + }, + "assets/kenney/tiny_town/Tiles/tile_0127.png.import": { + "bytes": 961, + "sha256": "dd1a769c7467868eeb8b7fd7ade345cb11c01b951408bc260068ecfcae8abc97" + }, + "assets/kenney/tiny_town/Tiles/tile_0128.png": { + "bytes": 200, + "sha256": "28289aeb6de1a3a8fe051930365cbf9d0fbde24dbc875f96ee45dfcd2f225b28" + }, + "assets/kenney/tiny_town/Tiles/tile_0128.png.import": { + "bytes": 961, + "sha256": "98abd148339516fe6fc772a8ca242381a1c137c1bd457004bf1095b1ef974aa4" + }, + "assets/kenney/tiny_town/Tiles/tile_0129.png": { + "bytes": 200, + "sha256": "0a273e03a72e29f6343647a511a98b14fa3b26e239f3df02a4e2e4da4b4470a4" + }, + "assets/kenney/tiny_town/Tiles/tile_0129.png.import": { + "bytes": 960, + "sha256": "8db359dd68e5e27b2e5d815268952dc583c23c8929e69521fef250bce988225a" + }, + "assets/kenney/tiny_town/Tiles/tile_0130.png": { + "bytes": 206, + "sha256": "1c6b4444519eddc55abe82de5855effc8e9754dc206186712272e8de8e139b26" + }, + "assets/kenney/tiny_town/Tiles/tile_0130.png.import": { + "bytes": 961, + "sha256": "80988ea2c17bc102486196b33d90e8ea1bebd3b0fff8a3fb8e440b32e0208957" + }, + "assets/kenney/tiny_town/Tiles/tile_0131.png": { + "bytes": 220, + "sha256": "a9592d792e563721dc5c38d9d922aad3fdc6c603a7d70822ef4194991ef42452" + }, + "assets/kenney/tiny_town/Tiles/tile_0131.png.import": { + "bytes": 961, + "sha256": "cdd3a65934dbf1a92b085dab7ef02c88879cbca9f0a337341b716b499c3991a0" + }, + "assets/kenney/tiny_town/Tilesheet.txt": { + "bytes": 238, + "sha256": "1b86fae0b27a628f18cfd89c6e148ea1d727f5ef02fc1dbeb5a6e9f9667bea00" + }, + "assets/kenney/tiny_town/Tiny Dungeon (base pack).url": { + "bytes": 131, + "sha256": "6d93bb958f9b7d5f21ceb8cbd24c184dc5c9f87aee7c680b336ecba7a89823d8" + }, + "assets/kenney/tiny_town/Visit Kenney.url": { + "bytes": 44, + "sha256": "6787defa3ecb6118622e1903b65802c0200628fae5164b51b4fd467f92f3f284" + }, + "assets/kenney/tiny_town/Visit Patreon.url": { + "bytes": 54, + "sha256": "2fcba31333935f4aa35e9de2e74e2b7ba1b1a8011540e08016ff6d81e9dd7490" + }, + "assets/mockups/the-tree-main-gameplay-visual-mock-v1.png": { + "bytes": 2722232, + "sha256": "58877bb1afbf0e72af6531cadab01eca82f9bd8cefb0cdb45f81d6d2dbb83717" + }, + "assets/mockups/the-tree-main-gameplay-visual-mock-v1.png.import": { + "bytes": 1029, + "sha256": "ad532d171e4c4b57c7e28000f2abf3948e340bc3ce368e4bd82711d08b8abcf9" + }, + "assets/mockups/the-tree-main-gameplay-visual-mock-v1.prompt.md": { + "bytes": 2899, + "sha256": "7d9ad316086f1256ab8fbcd24e84dc497b117b1c502df1f76d176aa61cedc9d8" + }, + "assets/mockups/the-tree-main-gameplay-visual-mock-v2-japanese-fantasy.png": { + "bytes": 3049138, + "sha256": "1c079ebb8b2b9610df0e79a2750cc5a0db53f26d137b6df511b12cb6884532d0" + }, + "assets/mockups/the-tree-main-gameplay-visual-mock-v2-japanese-fantasy.png.import": { + "bytes": 1080, + "sha256": "fdf307e5147e594cab5acd4e1f8c06d5bb62b1962241de050df06f7879d6aa28" + }, + "assets/mockups/the-tree-main-gameplay-visual-mock-v2-japanese-fantasy.prompt.md": { + "bytes": 3069, + "sha256": "bb0f8ba1350e1fa15be2936139dbbac02a809b9db699b3ae073ce579996ad439" + }, + "assets/mockups/the-tree-main-gameplay-visual-mock-v3-prompt.md": { + "bytes": 1874, + "sha256": "9e938a990e01fe97daebc0405256bf63cb87af6e2b7951568de381f3775db580" + }, + "assets/mockups/the-tree-main-gameplay-visual-mock-v3-tower-style.png": { + "bytes": 3076090, + "sha256": "f802d2b4f275f136fcacc963f7d06228f5d71dbc2399a19f7e04c6bc7531321b" + }, + "assets/mockups/the-tree-main-gameplay-visual-mock-v3-tower-style.png.import": { + "bytes": 1066, + "sha256": "fbdac36124d5aa559038452d70d4e6cbde902ff0bafa3e9f20caf189b2e546d3" + }, + "assets/mockups/the-tree-runtime-ui-v3-assets-front.png": { + "bytes": 1461992, + "sha256": "e54ff252bae66010dc885846acdcdb0117b930e0e3cfc8f5459acc2841eabf0d" + }, + "assets/mockups/the-tree-runtime-ui-v3-assets-front.png.import": { + "bytes": 1023, + "sha256": "9bfe922148dc14bf729b92cc30c67119d1645e0e02d79eb79c175c5415badd0f" + }, + "assets/mockups/the-tree-runtime-ui-v3-first-pass.png": { + "bytes": 434318, + "sha256": "cc7f23ea258d49a8f2bd23735c63196b94ece380eaed934ee6e7f1b6d881cb44" + }, + "assets/mockups/the-tree-runtime-ui-v3-first-pass.png.import": { + "bytes": 1017, + "sha256": "b861b4efc54a95cc3ff0b28b4aa38e1383469b98e6c5eb19bf022330169cefc1" + }, + "assets/mockups/the-tree-runtime-ui-v4-icons.png": { + "bytes": 1317405, + "sha256": "b0826ffce116d96dbe5b901174713f84b55a0e72931f29821e0947b844b9c1b8" + }, + "assets/mockups/the-tree-runtime-ui-v4-icons.png.import": { + "bytes": 1003, + "sha256": "d14ae1dd54a1aab6ab3ead98fbb85153b1530f7ee7ee77efe9c0846dc3eda204" + }, + "assets/mockups/the-tree-runtime-ui-v5-map-icons.png": { + "bytes": 1321334, + "sha256": "aca56c954b209b0a03342c0fde576cef15bfaa2ce2a1f9feedd51744fcfdb42c" + }, + "assets/mockups/the-tree-runtime-ui-v5-map-icons.png.import": { + "bytes": 1015, + "sha256": "b31b085b2e8c0c37cf43ff2d662af75b4a64a9472ab240669a09552f9cfa7969" + }, + "assets/mockups/the-tree-runtime-ui-v6-actors-4k.png": { + "bytes": 6569282, + "sha256": "9b8a1d9e2e4408b7ee99505d1978a44a489eb8b6945d669d1c52e7e220937e79" + }, + "assets/mockups/the-tree-runtime-ui-v6-actors-4k.png.import": { + "bytes": 1015, + "sha256": "62e578057df63b8ac8238f63b91e24e6bb655465b29916888aba7f137cd267ef" + }, + "assets/mockups/the-tree-runtime-ui-v6-actors.png": { + "bytes": 1322150, + "sha256": "8f9ea1b8bbc779e3f401d4cfdc8dcb0d10b95b7f87f37d3737af9bc85aa9dddd" + }, + "assets/mockups/the-tree-runtime-ui-v6-actors.png.import": { + "bytes": 1005, + "sha256": "e0be674acd73182b9c8c48c42afd054c814f00a0d924d023c6810596afefc6be" + }, + "assets/mockups/the-tree-runtime-ui-v7-skins-4k.png": { + "bytes": 8849219, + "sha256": "a32d61772e06b944cf7aeb7a2dd0bd1ccfac7cbb3d8e293a6d7075f780f48904" + }, + "assets/mockups/the-tree-runtime-ui-v7-skins-4k.png.import": { + "bytes": 1012, + "sha256": "b8610cd4424365597cb4bda6c20c161853394016139fd134184e58f96f548b6d" + }, + "assets/mockups/the-tree-runtime-ui-v7-skins.png": { + "bytes": 1778605, + "sha256": "f0dec82c2da661df52124cd3c2f59c3ac94db9cb5d384846d42f1901ada370cf" + }, + "assets/mockups/the-tree-runtime-ui-v7-skins.png.import": { + "bytes": 1003, + "sha256": "af76edcda2da8acbdcf1e61406b91158091591893eea1b85fcd1e3ea45f8261d" + }, + "assets/shaders/layer_lens.gdshader": { + "bytes": 787, + "sha256": "be8b7965b371a1935bec943bb244a32e70471f31a78d22151ee7133931029da1" + }, + "assets/shaders/layer_lens.gdshader.uid": { + "bytes": 20, + "sha256": "1ee97a9c1d31493ea837db26bb001c29c0d8beb63aba6f57a50efdff6fa2361e" + }, + "assets/themes/japanese_fantasy/README.md": { + "bytes": 5544, + "sha256": "edc674a212eeb0cf5a4e40e73e857e8303bf08d1199e96aa8071cba588f33f6d" + }, + "assets/themes/japanese_fantasy/actor-markers-v2.png": { + "bytes": 2165570, + "sha256": "b742c207613d773e47f21c917975a2ba0eec8a2d9485ff655fef37e3ebf4bde4" + }, + "assets/themes/japanese_fantasy/actor-markers-v2.png.import": { + "bytes": 981, + "sha256": "2c5230290f61d8d5846c51de9000c23913855dc5b698c6336b9e0b98bc633b77" + }, + "assets/themes/japanese_fantasy/facility-icons-v2.png": { + "bytes": 1848036, + "sha256": "6fb830fbe3961125fe0f3e640efe63ecba4de5ea6fb758eaf0da2738940fa1b6" + }, + "assets/themes/japanese_fantasy/facility-icons-v2.png.import": { + "bytes": 985, + "sha256": "484caa3dd68dd166a84347ca6297b0228b9b4d6ed7d4e7c3fe3aa70606c2d8fe" + }, + "assets/themes/japanese_fantasy/system-icons-v2.png": { + "bytes": 1786659, + "sha256": "1f1d4f5e20ba4de61e3fb967352b68db435fa36ec5e4bacab2802f132e3b8d40" + }, + "assets/themes/japanese_fantasy/system-icons-v2.png.import": { + "bytes": 978, + "sha256": "103127fbb3a0287421090089a679985109852ba0ff0f6c90ef3ff0beab06e7ba" + }, + "assets/themes/japanese_fantasy/ui-skin-v1.png": { + "bytes": 2492477, + "sha256": "4b4906cc9c6ed3fdb5330bfc11177376e5fec10afa3f2dac9318dbaf71833ff2" + }, + "assets/themes/japanese_fantasy/ui-skin-v1.png.import": { + "bytes": 964, + "sha256": "0f557fe050aaf30226a648f483581201b8805f76e10e0d9b969ce10079707404" + }, + "assets/themes/japanese_fantasy/visual-theme-v1.tres": { + "bytes": 12404, + "sha256": "42e968ba5e35c228d3ff372f92a8e249ec3a743045be0a3ec158556944c0bc18" + }, + "assets/themes/japanese_fantasy/world-back-v1.png": { + "bytes": 2616183, + "sha256": "2b0dbf07c17e677ed023c56b1e90f013c40362f46c427950033868b042508c7c" + }, + "assets/themes/japanese_fantasy/world-back-v1.png.import": { + "bytes": 973, + "sha256": "5ba3cb9af8dddb345abb05be9bbd44240fade14cd9d113de4a6d1f6343e74196" + }, + "assets/themes/japanese_fantasy/world-front-v1.png": { + "bytes": 2774704, + "sha256": "02b52ea05bdb4bbe78b8c905374052505bb73411eb7f2b0578e9b1a82994cde5" + }, + "assets/themes/japanese_fantasy/world-front-v1.png.import": { + "bytes": 976, + "sha256": "186e162d2d5e4567d50768ebf286133031c7dca02954f9b25f3abead0278a7ae" + }, + "autoload/event_bus.gd": { + "bytes": 294, + "sha256": "6950280a5639dd5a3071ffefd034cb443a694739d5bf8c4e2dbcd52aadbab4b2" + }, + "autoload/event_bus.gd.uid": { + "bytes": 20, + "sha256": "4a37ce59be5cafd10106cb3f76addada7aed9ec3ee516583ff95604ffc128671" + }, + "autoload/game_clock.gd": { + "bytes": 841, + "sha256": "39400634a57ccbf8c584b54a15a259048a95da90b1528330151e45667d65f7f7" + }, + "autoload/game_clock.gd.uid": { + "bytes": 20, + "sha256": "4fe213c1953dc7c4d167c9bb109f052f639be08529b6fe652fa911029ba9fe35" + }, + "autoload/game_state.gd": { + "bytes": 3536, + "sha256": "cf0e884910220e54c56b5875983e53de439af9d893be1e1b65c2121d2a30722f" + }, + "autoload/game_state.gd.uid": { + "bytes": 19, + "sha256": "1b73841c770827cd1e86331c153f927283a049176f340ef9aa7028c72cc630da" + }, + "autoload/simulation_runtime.gd": { + "bytes": 623435, + "sha256": "dbde152e4d93a297e1215a281b22ccd97bed994541c3fc89417cb8f56304ad95" + }, + "autoload/simulation_runtime.gd.uid": { + "bytes": 19, + "sha256": "96889c02b810894cc82291955880ed667ad27ad754f1b1531a5456cc186d3d91" + }, + "data/characters/mvp_guest_classes.json": { + "bytes": 4869, + "sha256": "5d55d4a0a10902da747000357ba36be9644bf027f253ea4b200a75f1ee4cc88b" + }, + "data/characters/mvp_species.json": { + "bytes": 1327, + "sha256": "6c7caf52305d76e07a0dee2b225ee92674c45d24cbca7f62bf4029bd3db00915" + }, + "data/characters/mvp_staff_candidates.json": { + "bytes": 10385, + "sha256": "a2d0eecbe0369e9c725ecdfff5fa12749dd99c3aec458fc3412d1045affc7934" + }, + "data/characters/mvp_unique_characters.json": { + "bytes": 1032, + "sha256": "bf83872ae9bacedf4b1d48a8b1eb28479f3c33416303dbbe8ba11b6466c0dde4" + }, + "data/environment/cleaning_policy.json": { + "bytes": 171, + "sha256": "7d378dc2341385945e959782ebcfcd2e6530da3be06bf0f05012e3fe28f76e8d" + }, + "data/facilities/adult_private_room.tres": { + "bytes": 2520, + "sha256": "d8501586416b5c57a8b3b3b2afd1c0143428d8a4fa1df7112e995bd36649df6d" + }, + "data/facilities/cafeteria.tres": { + "bytes": 867, + "sha256": "86d540fe2d78b9dcdbe5a0af6e4a001f4cec54934636ed01deb25a943c79128a" + }, + "data/facilities/expansion/black_market.tres": { + "bytes": 892, + "sha256": "c209d734c82487f6df4c03714618865d6a5f1d2cf991dc0056fe4bbad8f03a42" + }, + "data/facilities/expansion/chapel.tres": { + "bytes": 845, + "sha256": "9b30a7c51712e7bb99c17870d1f03e3429ea9279851d88284545bb2eb5042fcb" + }, + "data/facilities/expansion/cleaning_room.tres": { + "bytes": 707, + "sha256": "ae366cf67cbf117db7989c6b76092eb5a65229b93d35999a40d19b8260f95ad8" + }, + "data/facilities/expansion/clinic.tres": { + "bytes": 863, + "sha256": "339cf22c68d7ab3cb1514b9e8d2ea63dc0772fe93918d70767c11cf7b6ee0e16" + }, + "data/facilities/expansion/cold_storage.tres": { + "bytes": 767, + "sha256": "1aac824147b52b41e124d2ab2ce63c3bac58de2ec7fc447a5806a1cf9fa9ad99" + }, + "data/facilities/expansion/general_store.tres": { + "bytes": 779, + "sha256": "76872e0375648b43f05fdc5581ccabe4aa6a166674c3b523980dd1cf0b6e6dc1" + }, + "data/facilities/expansion/guild_counter.tres": { + "bytes": 833, + "sha256": "93e8736da4aab8a17b1c8e7831c9a7b8de7f32d0ec251aa9aa5c8cf859c8fd7b" + }, + "data/facilities/expansion/laundry.tres": { + "bytes": 913, + "sha256": "2518ea2e5da12cf4f2997502bf50f00dd8145caca153fb3486b44b99881fdab4" + }, + "data/facilities/expansion/maintenance_workshop.tres": { + "bytes": 898, + "sha256": "8bd10332a9f45a252febdc626f22f90507317fb4cff5b18b2526aacd1f1a176b" + }, + "data/facilities/expansion/mana_control_room.tres": { + "bytes": 871, + "sha256": "55e4c52a049ff61ddf3d081ccb990a8572b64bc7cf37d3a0d52ca5a08cc32f25" + }, + "data/facilities/expansion/premium_room.tres": { + "bytes": 789, + "sha256": "6665090e041f36df5809314cd171be228a94bf77d7e93f5b70be648db4705d98" + }, + "data/facilities/expansion/private_bath.tres": { + "bytes": 862, + "sha256": "241b807e7fa3a1b9dc4bda0d2495e637155cdaea89a4234e37a121f00098499c" + }, + "data/facilities/expansion/secret_tavern.tres": { + "bytes": 917, + "sha256": "f0a1372931078fa0f93dd5b9cec6df6b137975479aa706633fdf6a9be4cf1f62" + }, + "data/facilities/expansion/staff_dormitory.tres": { + "bytes": 814, + "sha256": "8d7c7cd6dfe98d137f7fef62e35eb31f82f1ca282216a40df54ac81728101271" + }, + "data/facilities/expansion/tea_lounge.tres": { + "bytes": 864, + "sha256": "77d1ace36c5e84f80c0e6d563ae973c7ff1cd12b56956afd4895cdcdd5771a67" + }, + "data/facilities/expansion/underground_guest_room.tres": { + "bytes": 751, + "sha256": "cdfd0f8cd21812a9972485926dff27daaa6718af16aac1651894728b087bef9e" + }, + "data/facilities/expansion/vip_private_salon.tres": { + "bytes": 909, + "sha256": "1c94a7a70393262fba82112c3f4a0cb67ad22728664f5ca408f450049d3657a7" + }, + "data/facilities/expansion/waste_processing.tres": { + "bytes": 886, + "sha256": "9954855c7a07e425376a220c589989beb6ec95da3c5331316ef3615a60b45f1d" + }, + "data/facilities/guest_corridor.tres": { + "bytes": 814, + "sha256": "d77ccf267e20a26ed70527d29e8d54e6fcab1df213f02d5a4e28ead4f705276b" + }, + "data/facilities/guest_elevator.tres": { + "bytes": 814, + "sha256": "ad4fb3c439ac4ed90fe52f07e29ed7b4ff654c54d1c400c7c8e226da77127af7" + }, + "data/facilities/infrastructure/guest_stairs.tres": { + "bytes": 911, + "sha256": "757c687b1ebe2a3f237fb28092cd5f01591f15b2bcd1b4e639042a24635a92c6" + }, + "data/facilities/infrastructure/mana_warp.tres": { + "bytes": 875, + "sha256": "42f1156e04a4454d8525bf3dd77b214a39e11bb7c5e749af1413fe77cdb1e456" + }, + "data/facilities/infrastructure/service_stairs.tres": { + "bytes": 908, + "sha256": "637217d867bcc99669d27c54b6d2c391c82a4a17356ab9a80c897ccaee38622c" + }, + "data/facilities/infrastructure/service_warp.tres": { + "bytes": 843, + "sha256": "712ae26bf2d9d18c9da6344ee18ef716250e051693bcace586b85f35a794dba2" + }, + "data/facilities/kitchen.tres": { + "bytes": 2013, + "sha256": "38197aa8a3e90c03a82e9ccdc88bb444af4eeb0349c41a39e0bdd7b188e7d5d3" + }, + "data/facilities/massage_room.tres": { + "bytes": 834, + "sha256": "75ecf845fb3cfa8d3150f6b0dc90e901953469af512611384b70cc4878d21e85" + }, + "data/facilities/public_bath.tres": { + "bytes": 823, + "sha256": "8ec259f48ed75c8ab2e5154a1caccf19f6be04331adbe774b877f0a2d8b2f778" + }, + "data/facilities/reception.tres": { + "bytes": 2076, + "sha256": "bed3de120a0e98c539771d1bb189111d095712f8ae25dfdf7cb2983efc0dee9f" + }, + "data/facilities/rescue/infirmary.tres": { + "bytes": 684, + "sha256": "c3e861533971e369068ae9e42f71b660fa4ab3893c7c1f798fc367893befd943" + }, + "data/facilities/security_station.tres": { + "bytes": 844, + "sha256": "69f3f518df7714d00c8e954e9c7405aa44b683dd274181cc3da832cc956815b3" + }, + "data/facilities/service_corridor.tres": { + "bytes": 829, + "sha256": "5d79fbde201d657740efcba924f595bd7075e069b344d708e424dbebbdc2f254" + }, + "data/facilities/service_elevator.tres": { + "bytes": 824, + "sha256": "35d552d5b96065413feccb50847e3cd7173e673896ce65afba238f90abc25132" + }, + "data/facilities/staff_door.tres": { + "bytes": 810, + "sha256": "a993058bfd809ccdbbb9a61b9850259d7bf6e60003e57ccfa3972f6c29170752" + }, + "data/facilities/staff_waiting_room.tres": { + "bytes": 799, + "sha256": "5c7a2f7f7c508102c4ee89401ad6348191b57d1ff65538acb9d450e464a3a46f" + }, + "data/facilities/standard_room.tres": { + "bytes": 689, + "sha256": "89f0a3a861d66afa4c1338ff1ec919685cf338b93b8da9a2387ce85e7e5bc336" + }, + "data/facilities/tavern.tres": { + "bytes": 875, + "sha256": "eb494ae6ab0d1b9e88ae0a38944609702e43c81a370a29cfb030af9ae46f523c" + }, + "data/facilities/warehouse.tres": { + "bytes": 788, + "sha256": "d0fcf0528da66da7b354ab5efaafe2483a7a76e05b324db255700ef73cdfc791" + }, + "export_presets.cfg": { + "bytes": 1538, + "sha256": "2edb12523be96daf8045bbb0fe8f4b1ebccf332a85484a612b90b71caab496ff" + }, + "project.godot": { + "bytes": 1294, + "sha256": "686f3da7f6b592cd95d84e71a83374a28173914b377eafa4a6e005d70062d00d" + }, + "scenes/main/main.gd": { + "bytes": 142398, + "sha256": "e09c361603da85b7a8b1e299a62b0f9b27f2b20b373b511e6450fe281e16614e" + }, + "scenes/main/main.gd.uid": { + "bytes": 19, + "sha256": "9e580841e76ef09876eecfcbb17f274dc369ed9d38b2b778036696ade9f813ad" + }, + "scenes/main/main.tscn": { + "bytes": 287, + "sha256": "dde43688b86251ce617131c362b1054ce8bd59b509c1abe19e831c0481a07319" + }, + "scenes/main/world_preview.gd": { + "bytes": 96883, + "sha256": "4bc49a19a38b9c3b4d6bfc243ddf46f1f25469a8273adb5e812911ef9424a1f2" + }, + "scenes/main/world_preview.gd.uid": { + "bytes": 20, + "sha256": "3a4492c54de0fe091194a34eb838c2ade177258142566d8e5c54e82b415d94ad" + }, + "scripts/authority/authority_service.gd": { + "bytes": 51646, + "sha256": "2979cca4c6a82932fed9babf209a608b8a20bda550c170f83a166db68ce02ab9" + }, + "scripts/authority/authority_service.gd.uid": { + "bytes": 20, + "sha256": "1978784a978315b219f2750e5e48ae13cce403337d9c17f22e9e2b4fbbff5084" + }, + "scripts/authority/evidence.gd": { + "bytes": 5464, + "sha256": "85f1bd83a4ec994c8bb9bce296d8b63fcdb6bb26c1b4c2f47e16864450438649" + }, + "scripts/authority/evidence.gd.uid": { + "bytes": 19, + "sha256": "228ab3da615ba26c1a346e8e7db09e8d5ff655d74d22041984aff7d40de7e266" + }, + "scripts/authority/heat_state.gd": { + "bytes": 10064, + "sha256": "7e507461684c159bed4c17acc939d6a98537d06d73de2dae235a788048f290b2" + }, + "scripts/authority/heat_state.gd.uid": { + "bytes": 20, + "sha256": "bb6b9a28d975635f19ce2a02a288b54ce666bbf6a2251cd57d10a4b19aa7a580" + }, + "scripts/authority/incident.gd": { + "bytes": 7393, + "sha256": "dbb58592746d0055b438fc8259f7c40d09f77076737c47051b732395888df124" + }, + "scripts/authority/incident.gd.uid": { + "bytes": 20, + "sha256": "b57cae193cac0e4b86961c96c74a6e6192b68a2e7700cacc8e065e789fce26e1" + }, + "scripts/authority/inspection.gd": { + "bytes": 14218, + "sha256": "ff523082ec6d918dbc559e04c3c11fd6d30d4f88c5a54ffa57eb3c758e244812" + }, + "scripts/authority/inspection.gd.uid": { + "bytes": 19, + "sha256": "8694d7aa94fc282f98abb1253d0ec88c7c2ec2a993e1a357e350b96fb9189d75" + }, + "scripts/construction/construction_job.gd": { + "bytes": 6841, + "sha256": "6c59af45346c16572f8c4cb111af86c586cec8081302bf67b6ef411a56ac5196" + }, + "scripts/construction/construction_job.gd.uid": { + "bytes": 20, + "sha256": "a3add1462b6502d7817eb284384dd7e5a6e8be71e9ae1e743f697aeb44d850b6" + }, + "scripts/construction/construction_service.gd": { + "bytes": 55891, + "sha256": "c737eb7aa927097da677ac23ad649ef871af1dea54bcb8103348b88c5303ea25" + }, + "scripts/construction/construction_service.gd.uid": { + "bytes": 20, + "sha256": "01246250363f3f5e8ecfb3779f3486a1ba05c1c486b7f65446c71b5d12259f74" + }, + "scripts/construction/excavation_service.gd": { + "bytes": 37019, + "sha256": "337e9e5d07a9eeaf362253fec12cbe5fb2ea8e74e4887de82868748577d4af33" + }, + "scripts/construction/excavation_service.gd.uid": { + "bytes": 20, + "sha256": "5cd5e92edcf31d12c277622eab43c27702a134020e845e4222cddcf6123740a1" + }, + "scripts/construction/facility_resize_preview.gd": { + "bytes": 7268, + "sha256": "d0e8d772a648a297ee0a4625206b073be2668b32c7dba2575ba1295f5b1866ac" + }, + "scripts/construction/facility_resize_preview.gd.uid": { + "bytes": 19, + "sha256": "4f5d08fac326538993e67ef5376e25dc670defdcd9d79b4c2cede983e16c2bc1" + }, + "scripts/construction/facility_resize_routes.gd": { + "bytes": 6534, + "sha256": "05d4aedcc930160eafc2945711f867744f63f5f391e4759f8e2de9211b968201" + }, + "scripts/construction/facility_resize_routes.gd.uid": { + "bytes": 20, + "sha256": "9618cd77ca4f3b90b6efa0733b2bbc3a3928694a5b0cee430e4d3df01a3619a4" + }, + "scripts/construction/placement_report.gd": { + "bytes": 3732, + "sha256": "9f179c9a94a176a126027cf1d53942c0ac73b008ad119ab2480ba93f972b145c" + }, + "scripts/construction/placement_report.gd.uid": { + "bytes": 20, + "sha256": "136f13bc9e9baf53ec320f429678d50583d9dcc23decb1081c1c48c5b90de99d" + }, + "scripts/core/command.gd": { + "bytes": 2188, + "sha256": "9751ff4b40bebdae56b6b3879dd7cbffdc2a36b050a12bda89e1de47eb54145a" + }, + "scripts/core/command.gd.uid": { + "bytes": 20, + "sha256": "2cd0c5e76d77f379846053a6ebd1fb409b31d318ed4684190a096db545cb7c02" + }, + "scripts/core/command_queue.gd": { + "bytes": 14401, + "sha256": "09b22e6212fa3ce1bf08f5d6b52224a2d3362b3bc63f03a8c98e89af1c6f5895" + }, + "scripts/core/command_queue.gd.uid": { + "bytes": 19, + "sha256": "5091aee01c74a94968525287108d9c9b17fa0e9d4be17d29722afc57413a205e" + }, + "scripts/core/command_result.gd": { + "bytes": 2528, + "sha256": "71b45fb50d69951797fe8d39ad5f707b79108eac30de09fa5e8d64ddb2436ae8" + }, + "scripts/core/command_result.gd.uid": { + "bytes": 20, + "sha256": "d4de1ab106696572f756c8a1eb59904b5f9d70039ddbc65e458c9b45cee52cfd" + }, + "scripts/core/definition_registry.gd": { + "bytes": 28800, + "sha256": "e2ce5e0512a92fec6989e1bb5f0e7da1dbb50bd9ee67a07b4624fdc8bc65814f" + }, + "scripts/core/definition_registry.gd.uid": { + "bytes": 20, + "sha256": "1c1fa87f2900dccc19e0169cd33a63ca9f85650d80cf2ca4f13f50bb3ac682c7" + }, + "scripts/core/deterministic_rng.gd": { + "bytes": 4900, + "sha256": "9c12c1b3b212e140b64137fa34d7e8b2494897cad341b3bbcf9f8da215053204" + }, + "scripts/core/deterministic_rng.gd.uid": { + "bytes": 20, + "sha256": "4b1b094351a86b885a3b6ac06a5b33a131c285505fb0378cd4ca48a66e58431f" + }, + "scripts/core/domain_event.gd": { + "bytes": 2212, + "sha256": "cc9a903c366d9f889134561694b0c7fd52da260e97236a7b60830d7a68947bd4" + }, + "scripts/core/domain_event.gd.uid": { + "bytes": 19, + "sha256": "b744f8ed8637e42d010adaf018c17c3dd4f50109ac8dce378359a68bbaaf1d1c" + }, + "scripts/core/domain_event_stream.gd": { + "bytes": 5104, + "sha256": "f9b57a4b4b53cf7d67132a159ea90378c633b4f19d8de28dbe7a33ebce8e3d79" + }, + "scripts/core/domain_event_stream.gd.uid": { + "bytes": 20, + "sha256": "45ebcc38a71aaae376544060ac4f4b737ccbd7de900b1256744724ba321d7dac" + }, + "scripts/core/performance_budget.gd": { + "bytes": 9328, + "sha256": "0e2278f88d29919a0634fc1b527328a0d0c12d87e2cd612f3eee1526aabdb073" + }, + "scripts/core/performance_budget.gd.uid": { + "bytes": 20, + "sha256": "369ce1d51b8dcc1aec1d838e982e5f869dbf387868120e73c56f41c04d4a2ea1" + }, + "scripts/core/save_migration_registry.gd": { + "bytes": 5267, + "sha256": "22ac2cce07a02d1a2a9ac2109e7a0ecf9a0fbe675df4dc9d5249aa9ab3583f98" + }, + "scripts/core/save_migration_registry.gd.uid": { + "bytes": 20, + "sha256": "4f60970aea2158245f2822a73cb5e9d71c067f9e89e933f55011a6c4003deab1" + }, + "scripts/core/save_service.gd": { + "bytes": 85623, + "sha256": "c744ce4f48e665629fd125706cde52afddecac8936a35fb2a9c17887602f7947" + }, + "scripts/core/save_service.gd.uid": { + "bytes": 20, + "sha256": "6e14d474f6da62bf8ba9af8d4a0f3f7f4d49d8e4b8e69063f2d612ed8395d2a5" + }, + "scripts/core/simulation_digest.gd": { + "bytes": 11200, + "sha256": "90b0d1a9632e73680329078f6f19c3b1e4d637c6780e31814769c5e758694f1f" + }, + "scripts/core/simulation_digest.gd.uid": { + "bytes": 20, + "sha256": "6989f1b2667c51b28dce4dd8c78c788922a71ca94f06266a65c4b8bba82f1aed" + }, + "scripts/core/simulation_kernel.gd": { + "bytes": 7602, + "sha256": "341c0c878c4894adbac628d0db6362ff69fc3347bdd9e61e50936e15dc2d1edb" + }, + "scripts/core/simulation_kernel.gd.uid": { + "bytes": 19, + "sha256": "a6af2b8ca039ae48fd69887def2c24b90faa12ed3ab993c87c0ec782bb351d0e" + }, + "scripts/core/simulation_snapshot.gd": { + "bytes": 2571, + "sha256": "fc528a3d1db1f439c10f70d6cba2f72bd65abc0d3866eb8b582df60918af0adf" + }, + "scripts/core/simulation_snapshot.gd.uid": { + "bytes": 20, + "sha256": "9c8d4dbde582a132f42fde0ec764bb131e738f0ef7ba219bf109bc030e607960" + }, + "scripts/core/stable_id_generator.gd": { + "bytes": 1839, + "sha256": "78e0dd691ba18d1f159d9d7abba5894d2e10d36885aa6dc5be02a27f9edd5013" + }, + "scripts/core/stable_id_generator.gd.uid": { + "bytes": 19, + "sha256": "fb04510c99d86370ce5cbf9e19bfe1bee6684809bc688685b9c2c7a7698ddcd0" + }, + "scripts/core/state_transaction.gd": { + "bytes": 7406, + "sha256": "4ac24e41cd16ebb5312ad2b7e8b6c5b8990df14641650e9720081873f9ce55cd" + }, + "scripts/core/state_transaction.gd.uid": { + "bytes": 20, + "sha256": "04980323f275f246cee8e680041514e09122d9ff59c7bcda97b37e000c1a76cb" + }, + "scripts/data/facility_catalog.gd": { + "bytes": 5502, + "sha256": "08a09405a4f07a6b5fd21ba41eff347692f376c50306ccf6ae18e74ed95adacf" + }, + "scripts/data/facility_catalog.gd.uid": { + "bytes": 20, + "sha256": "1da0d592443dde67b261996f58b141ff9cbd98a4ae4c64355518f1c9fca254f9" + }, + "scripts/data/facility_definition.gd": { + "bytes": 5124, + "sha256": "e90d56f7eab69c2a75238de465925c1c6df57ee6d44b3b81e7f6fcfd069af0a1" + }, + "scripts/data/facility_definition.gd.uid": { + "bytes": 20, + "sha256": "c7b5501b827ec2c3fb428352c52b11ffb84c74c4831d968d2f51e1abad0091fc" + }, + "scripts/data/mvp_content_catalog.gd": { + "bytes": 42193, + "sha256": "86770b34c329459592928625ed256eb2cd123587915f63d0db0793127cb63a31" + }, + "scripts/data/mvp_content_catalog.gd.uid": { + "bytes": 19, + "sha256": "bda9d556d8501de20a61d7d70f8e45d4108fb6271b67c9fd1e321f2e19427fe8" + }, + "scripts/defense/defense_service.gd": { + "bytes": 101373, + "sha256": "bdef777e12e7802d02b8441d2815a983960b367fbc2287c5941ca38e1b668caf" + }, + "scripts/defense/defense_service.gd.uid": { + "bytes": 20, + "sha256": "7048f46d3d5f79f79aa066a7c4cdbd4f00dbaa79f2262f9850ed0118424746d2" + }, + "scripts/economy/economy_service.gd": { + "bytes": 30977, + "sha256": "95aedd0a0421c93e8fa39f0f76fa890cd0a46905d9a25c88c8b17c4d6d47728e" + }, + "scripts/economy/economy_service.gd.uid": { + "bytes": 19, + "sha256": "be3264816628a2991dac7e81e0d38f6f5347d94f85b44c5989b938f18e28660d" + }, + "scripts/economy/facility_upkeep_accrual.gd": { + "bytes": 7510, + "sha256": "229655648c67c5a8b2bfa2c5faeb0534984939d4cf6743b7721f5cf271ac108c" + }, + "scripts/economy/facility_upkeep_accrual.gd.uid": { + "bytes": 20, + "sha256": "eb4771fc6557cadaa7690cab57c8acd9516952492ac3dea3802ec8a3c70f59be" + }, + "scripts/economy/facility_upkeep_settlement.gd": { + "bytes": 10396, + "sha256": "26ccebf26b19089557aff1a70c53bc7686d878c75c5d3ded1b0e6df33ece50af" + }, + "scripts/economy/facility_upkeep_settlement.gd.uid": { + "bytes": 20, + "sha256": "9a3c0ea58816c35bee193f504f65a02ab2d82b66a354e5a8cecee2c29ec3fa4b" + }, + "scripts/economy/ledger_backed_resource_state.gd": { + "bytes": 4113, + "sha256": "199442c566185dc0abcc4eea5b4cf59c07330731bb5d5038b605dd801ae0209b" + }, + "scripts/economy/ledger_backed_resource_state.gd.uid": { + "bytes": 20, + "sha256": "cd91d40cb17f9c9996eb83dc2aca540a453eba655b9e9eb88aab416a827fe6d0" + }, + "scripts/economy/ledger_entry.gd": { + "bytes": 3886, + "sha256": "625d709b8d3239ef271dfbd42f189fd3a3fb99bd22d4f39438050c8e3addfe26" + }, + "scripts/economy/ledger_entry.gd.uid": { + "bytes": 19, + "sha256": "d582d239e408ba3f77b18754bb5f0ee837b1d70a8e1e11cd789dfa3ab64017a0" + }, + "scripts/environment/facility_cleaning_bridge.gd": { + "bytes": 7084, + "sha256": "f0abf23351c46b47e33141daea753ab776d71bd68f09ccf7c1a37879fee0d25e" + }, + "scripts/environment/facility_cleaning_bridge.gd.uid": { + "bytes": 20, + "sha256": "6024546933832c23a1844359efb81a190a83d711c80d66bc036419356e644190" + }, + "scripts/environment/facility_cleaning_policy.gd": { + "bytes": 1688, + "sha256": "51478d0915523d0f93be7daebddd672599b5975748b26a6771a63dd0791b11d6" + }, + "scripts/environment/facility_cleaning_policy.gd.uid": { + "bytes": 20, + "sha256": "ca37ebcd32b3f87da72b7dcf74faf85f412d91431ec9c3c9d90e44aaa89979b2" + }, + "scripts/environment/facility_cleanliness_service.gd": { + "bytes": 5788, + "sha256": "38295b414f543249e10d335c62230f9e23c2556a33dd83098f0085e3ed9ad150" + }, + "scripts/environment/facility_cleanliness_service.gd.uid": { + "bytes": 20, + "sha256": "895670f6220b422261bbaf38a21e15e5c347fcd5f321bfa65cb103313433fcb4" + }, + "scripts/environment/weather_timeline.gd": { + "bytes": 3821, + "sha256": "7a5c82061171b803e288c6726991d03a254b78a21face870ca349c493ae393b0" + }, + "scripts/environment/weather_timeline.gd.uid": { + "bytes": 20, + "sha256": "bd828a546604ee793586210eac3fd8135991d9a876d5e561851729493406cf35" + }, + "scripts/events/event_action.gd": { + "bytes": 2321, + "sha256": "993078d08e8b45c7ffe6471280f4144c45bf9a62003ff2edaddf6da9fee92351" + }, + "scripts/events/event_action.gd.uid": { + "bytes": 19, + "sha256": "6414fecb7adb02837ba491d17af59c3918e9d8d676bfb44a28fb22730998c528" + }, + "scripts/events/event_choice.gd": { + "bytes": 3146, + "sha256": "6077cba5d59e500e4df391d58801aa8c10669b17ac36c06e830329ca8e977dd6" + }, + "scripts/events/event_choice.gd.uid": { + "bytes": 20, + "sha256": "17e0101b1272810e3a6a7d1ebb4eef0564ce09c7577f097fafb12ac50e5fa39a" + }, + "scripts/events/event_condition.gd": { + "bytes": 6374, + "sha256": "31d493d68db9b49d8eed0d5adf7a6c4d90f12df0ac3353b1ceafa6259196efd5" + }, + "scripts/events/event_condition.gd.uid": { + "bytes": 19, + "sha256": "80fc11593f68db51201c8ca77979becb7a1de34d22d12dc182d6a379068e9567" + }, + "scripts/events/event_definition.gd": { + "bytes": 9355, + "sha256": "4af68f2e5ec185a750d59aaa24c7cb63fe612cd6a785e7fd39af11f0b5ce74a2" + }, + "scripts/events/event_definition.gd.uid": { + "bytes": 20, + "sha256": "c3b92a671fd79301767f1317c3ca06da04c02d569f3bd036d118302c20c15b5f" + }, + "scripts/events/event_instance.gd": { + "bytes": 4884, + "sha256": "e8ce02a03dcb111d808d3cb3068a752fc5bbd61ba0cb15026f1371615619b974" + }, + "scripts/events/event_instance.gd.uid": { + "bytes": 20, + "sha256": "0487f4d30911bca4621165252db26d6d16a2ba9ce27a6a3be4e0ecaa67b52cc4" + }, + "scripts/events/event_service.gd": { + "bytes": 59196, + "sha256": "d58c416d7a1126b36023fa6ba9f02338678bd54426a3b5d04ce511d9a48c0103" + }, + "scripts/events/event_service.gd.uid": { + "bytes": 20, + "sha256": "270b25260e76afb9bb52b9ab4162664cd6811cbd78df4e667e9342ad9fbc4ac7" + }, + "scripts/facility/facility_instance.gd": { + "bytes": 22815, + "sha256": "0c6aa493f3299611e05dd26aa429dda8cf7b5c479e4d09632036fb862f79a324" + }, + "scripts/facility/facility_instance.gd.uid": { + "bytes": 20, + "sha256": "18bf5e03f757acb0f3cda9bb8dd227c793141001605e92bd9407af968762a0fa" + }, + "scripts/facility/facility_pricing.gd": { + "bytes": 5049, + "sha256": "8d70ca9f8961ba342af787c04e0e2b1a944c772a20b7f11b6346a9d72cc43c57" + }, + "scripts/facility/facility_pricing.gd.uid": { + "bytes": 20, + "sha256": "7c612823e98b597254d23fe12e78be5b465a1a036dd9b17d8463e856a3459d6c" + }, + "scripts/facility/facility_service.gd": { + "bytes": 44951, + "sha256": "ceb4a3e9224587423f273cdb2b56e6843ab176ac1fc4fe79dd498b5ed5c33b77" + }, + "scripts/facility/facility_service.gd.uid": { + "bytes": 19, + "sha256": "b3fb1688378c01e971e0392699c1b7b3835ef658079588921f82790be85255a8" + }, + "scripts/facility/service_instance.gd": { + "bytes": 7320, + "sha256": "629a142f80cbc31b97b6d08483d94e029e448969bb6d39fdc8dd39931654dd35" + }, + "scripts/facility/service_instance.gd.uid": { + "bytes": 20, + "sha256": "56eb407a97b52928b7af7feaee947d77cc4efd06d0cec41a8ebfb89e8800c48f" + }, + "scripts/facility/service_request.gd": { + "bytes": 4744, + "sha256": "767a8c054188c8dde1e446f49d43d9ddc727a215bc9b31d5420650bd44c90024" + }, + "scripts/facility/service_request.gd.uid": { + "bytes": 20, + "sha256": "c25c4baf7fd1ff4181804f67dc60dea87eb0005ceacc563c23b0d06557e80d87" + }, + "scripts/guest/guest_definition.gd": { + "bytes": 9374, + "sha256": "082aa3f33b9cb17daf10a2cf8a1dece7b79dd80c2ae21e1a424d1b2ceb52b918" + }, + "scripts/guest/guest_definition.gd.uid": { + "bytes": 20, + "sha256": "94fedb128c219c83b06b0db2769aa675a08a0924722ab1dcf45eca267496c100" + }, + "scripts/guest/guest_runtime.gd": { + "bytes": 14267, + "sha256": "57ba99e5d977b5302987f4359a19056f1ab09c8fb7e4762ee8d79cbb9316741a" + }, + "scripts/guest/guest_runtime.gd.uid": { + "bytes": 20, + "sha256": "08e9a006febb70fd49c077ed2accaa600058a630d88ae73b9e5ed3f09eee70bf" + }, + "scripts/guest/guest_service.gd": { + "bytes": 61414, + "sha256": "56880410e9a00816f9a95d30821982955532de8dd976980934e12016a9f2b21e" + }, + "scripts/guest/guest_service.gd.uid": { + "bytes": 20, + "sha256": "93acb37fbe09375e5c69b7137e7e6f78224ddecde201071083e64dc9b7e56ab2" + }, + "scripts/inventory/inventory_reservation.gd": { + "bytes": 3315, + "sha256": "2d913d26e5af2ea12842264441d87ee5fce8fe84ef6664297ae2fa971a4ca10b" + }, + "scripts/inventory/inventory_reservation.gd.uid": { + "bytes": 20, + "sha256": "a998ce89bb17858ca9d762cd58c9786ea88bc89d1db94098babf0fa5b7de1459" + }, + "scripts/inventory/inventory_service.gd": { + "bytes": 57923, + "sha256": "7ee83b335864385119ca757037c3cdb912957aa4478a6312a0898a734e41f31a" + }, + "scripts/inventory/inventory_service.gd.uid": { + "bytes": 19, + "sha256": "5111280fbe7407e190ad9629526297e1a125f31a4d64a7ca519eb19e0811e820" + }, + "scripts/inventory/logistics_dispatcher.gd": { + "bytes": 18044, + "sha256": "2313f5ba3154143d5f0b6e1eeb1fbdda37cc81a7a1589515f56dfb53a797f720" + }, + "scripts/inventory/logistics_dispatcher.gd.uid": { + "bytes": 20, + "sha256": "1c6e69e99f2a32f3b61502eb35170119887ee10552948425c92bd71614b358ad" + }, + "scripts/inventory/logistics_request.gd": { + "bytes": 7010, + "sha256": "6dc5565083b8adb2c620fe805d1ba76be01ae09faf3070a9363485f4fc5e171b" + }, + "scripts/inventory/logistics_request.gd.uid": { + "bytes": 20, + "sha256": "1cfee75d9767ffd602cdcf74f44ef364cfce6f432be0bd1c1cf82d908afec8b3" + }, + "scripts/mana/mana_network_service.gd": { + "bytes": 18940, + "sha256": "3f28a9b291cc00efd1495a9adf11a37988ce13e8c8ace01a950fd0075b6d7950" + }, + "scripts/mana/mana_network_service.gd.uid": { + "bytes": 20, + "sha256": "9d3f7f5f28e0a5dec257a469ca9e2c80f5f05f5a6cd38e88f8ba1da07b318ee8" + }, + "scripts/mana/mana_power_projection.gd": { + "bytes": 1991, + "sha256": "2026467960e857349bcb18fb97b7753189be5f2de2be91a17e73e90146eba69e" + }, + "scripts/mana/mana_power_projection.gd.uid": { + "bytes": 20, + "sha256": "3a4ade65c26ed09fb10021fc9199597acf9dcf81ffb88cc3618be0f295120961" + }, + "scripts/mana/mana_reserve_balance.gd": { + "bytes": 4347, + "sha256": "cd462c279d37cc297466b64d9cf3fd71870df9508c1ff5f7189e22ddbdbef4b3" + }, + "scripts/mana/mana_reserve_balance.gd.uid": { + "bytes": 20, + "sha256": "12ea6a3b059a8a56bb8d288933ae4cb6043628cf3ff27dc64b44cb9788067c77" + }, + "scripts/mana/mana_reserve_cycle.gd": { + "bytes": 5975, + "sha256": "7d372d6e944765de5799803a4f5f60babf129741e6de30fe2452f133a4524d9a" + }, + "scripts/mana/mana_reserve_cycle.gd.uid": { + "bytes": 20, + "sha256": "a32339f7c334582628fb446d982cd69a6d475831136a02b14bff8cfdc1c0305a" + }, + "scripts/operations/operations_coordinator.gd": { + "bytes": 130891, + "sha256": "871a248ee101b6df543fd5cf0440b5d4b0f02c21fa145a99f0687888c1bc6f90" + }, + "scripts/operations/operations_coordinator.gd.uid": { + "bytes": 19, + "sha256": "f6df5dbe0667437e02705eb14e73db63da565974d8cce3b9672f699304305037" + }, + "scripts/progression/progression_service.gd": { + "bytes": 33643, + "sha256": "4f4e00fbeab4a4cec49b7912d8e75381b8354791e0a9efdb8414d984e88ca46f" + }, + "scripts/progression/progression_service.gd.uid": { + "bytes": 19, + "sha256": "4ac11552af0b41b564829c027df4c3015f7f9cefbd23160c8b4090c8b903c75a" + }, + "scripts/relationship/original_relationship_state.gd": { + "bytes": 1571, + "sha256": "d1bfabfd205becf6d3cf1d6b6c477393319b26b0e7504fd227c3714761101616" + }, + "scripts/relationship/original_relationship_state.gd.uid": { + "bytes": 20, + "sha256": "3ec8aa060bdf20acba106496c12288ebf8b83b51fc3dc9f7512e9a7b99583a0e" + }, + "scripts/relationship/placement_risk_preview_service.gd": { + "bytes": 47014, + "sha256": "d8e974487b75fbad49ecbbe1da8e36aac23dc4e1a5cf10281a1c567c97dd59f6" + }, + "scripts/relationship/placement_risk_preview_service.gd.uid": { + "bytes": 20, + "sha256": "b8776684db6129d44203785f83543d5f394c05f4d9dbe35903986d5812769281" + }, + "scripts/relationship/relationship_service.gd": { + "bytes": 27526, + "sha256": "d2f6304aa643b98914c5d65bf3eb673ca8cc427476187f43e76b4b941410b1d3" + }, + "scripts/relationship/relationship_service.gd.uid": { + "bytes": 19, + "sha256": "6f76e312d75c684178fc90d93d2099426e79d10dfcf623b62e78f3f5df5cbdb1" + }, + "scripts/relationship/relationship_state.gd": { + "bytes": 7969, + "sha256": "14551398f31ecd899e43a3d07b165d4884e54e83983e433c6de57e3e6a18d083" + }, + "scripts/relationship/relationship_state.gd.uid": { + "bytes": 20, + "sha256": "a14fe331fca5dc3daf21b2b57943978d2a749ce77967ca6f4f197f51f7e959fd" + }, + "scripts/special/peeping_room_service.gd": { + "bytes": 15448, + "sha256": "4dc02bc99f081d63a2518f69c960397d778d577b93d87d57bcac29bc6f108531" + }, + "scripts/special/peeping_room_service.gd.uid": { + "bytes": 20, + "sha256": "3f045afc3c140886c70ec8494d6dcb012e6da645e8a3ff3c6488442ce63a9353" + }, + "scripts/staff/shift_instance.gd": { + "bytes": 6992, + "sha256": "cec2bed5bfb138d4cc9c141bb7cdd9c19d70c034aad304398627ef1f4977ab48" + }, + "scripts/staff/shift_instance.gd.uid": { + "bytes": 19, + "sha256": "b75a34b149013f7020dd1d860b13d7febfc0c31319560ae79d25a7944c06c0f4" + }, + "scripts/staff/staff_commute_service.gd": { + "bytes": 7196, + "sha256": "3a1b816a3a778fc362e950817275fb8464d8562b61527f141787e4b2d2a3eba0" + }, + "scripts/staff/staff_commute_service.gd.uid": { + "bytes": 20, + "sha256": "a927760b03e52eca0aa0f9e187655c039a28f31de220435adce76099dde92224" + }, + "scripts/staff/staff_runtime.gd": { + "bytes": 17831, + "sha256": "807a417bc7866c97cd6d8f5c1368b5480a2d9fd685a2a47a978e81482bf522b5" + }, + "scripts/staff/staff_runtime.gd.uid": { + "bytes": 20, + "sha256": "4f8945347e644d8fd581dd511cc62b3be99f1c997aaeee046a33e1b345da47b4" + }, + "scripts/staff/staff_service.gd": { + "bytes": 86520, + "sha256": "355ad5c3c9f85dc4d4ffc3bc4293e36f81078c403d1662512a735b2c8d815fb3" + }, + "scripts/staff/staff_service.gd.uid": { + "bytes": 19, + "sha256": "6a77587fffd9b2a1189654d6324ae293fb5a2eba8fb4ea0621cd06be1e177552" + }, + "scripts/staff/staff_task.gd": { + "bytes": 12137, + "sha256": "5eeb8862a83e31e36d75e19720597fccf1aa4b25f30193d17ee95aaa94302b8a" + }, + "scripts/staff/staff_task.gd.uid": { + "bytes": 20, + "sha256": "7c741b7e1b55b6684e0d76bf2e3fa5a064286ee48cec556f262f3e7aa39fba62" + }, + "scripts/staff/task_dispatcher.gd": { + "bytes": 14801, + "sha256": "fdf2b6464e4b1089c58cbce972ff6217a0f7c69929b1be425536152d4b8290c7" + }, + "scripts/staff/task_dispatcher.gd.uid": { + "bytes": 19, + "sha256": "accb4d35bcdd6fe18c0ea586365ba7e1e580dea7b428532d4e0135fde9b5d94c" + }, + "scripts/supply/kitchen_production_service.gd": { + "bytes": 18872, + "sha256": "f3bc6bdc1a0ba278e9411108172ceceb7eb06520b4e33f93f35684da1f103c62" + }, + "scripts/supply/kitchen_production_service.gd.uid": { + "bytes": 20, + "sha256": "6ca256315163a3154a79316c78837d28cb0307c27998614afc17600d217c5268" + }, + "scripts/supply/supply_auto_purchase_plans.gd": { + "bytes": 14209, + "sha256": "86219a03efdfce548e923536253b3a4e555c56f2fd74cd9192da9d284bb54094" + }, + "scripts/supply/supply_auto_purchase_plans.gd.uid": { + "bytes": 20, + "sha256": "1ddd38fcd3be362bc97ba7670f354e50120667783d49123c177e246927f221ce" + }, + "scripts/supply/supply_auto_purchase_quote_plans.gd": { + "bytes": 10429, + "sha256": "07dbae60dc4412f4bf9f0cbf7a930d48af7b4f28fb50c177d5e52c30313971b6" + }, + "scripts/supply/supply_auto_purchase_quote_plans.gd.uid": { + "bytes": 20, + "sha256": "8dee556cea8a38256386f0c497589ea540f5d4a726ba5dca49e25a995ec5e232" + }, + "scripts/supply/supply_catalog.gd": { + "bytes": 1918, + "sha256": "93a3f674a953fb0627a38ad0342df31dc5fa77ba8a225780f2250e30ec22dd15" + }, + "scripts/supply/supply_catalog.gd.uid": { + "bytes": 19, + "sha256": "41f34c321e440694fd6e1aa7f71ca4a61386a3c06ef34aa841b037ae747d0d2a" + }, + "scripts/supply/supply_logistics_bridge.gd": { + "bytes": 28100, + "sha256": "b9e394af788595d2744b71f1907c8e7c3d762d38ff49992b1ee74e63b9639e80" + }, + "scripts/supply/supply_logistics_bridge.gd.uid": { + "bytes": 20, + "sha256": "c0a2dcdd8e0f877774fb956ad72a7b9b5144c4d7159a79a94f4c91c9b7d2f187" + }, + "scripts/supply/supply_management_service.gd": { + "bytes": 25019, + "sha256": "e4ad420191020485c027004f64bb00fad9da195fe956ef10dc0c787412018f7f" + }, + "scripts/supply/supply_management_service.gd.uid": { + "bytes": 20, + "sha256": "4094562b95ec4a271b291ef5446f7eb741005f2b740b92d87b63c2b21494116a" + }, + "scripts/supply/supply_purchase_quote_v2.gd": { + "bytes": 15572, + "sha256": "14c11cb3bb91ba5ecf21613c0ac18c54678362341fde367589419b8885c59b41" + }, + "scripts/supply/supply_purchase_quote_v2.gd.uid": { + "bytes": 20, + "sha256": "fb4e3315ae60a3eb881a18aaf6089b6dc4f93d1293db46e9ee0c27040af413a1" + }, + "scripts/transport/elevator_service.gd": { + "bytes": 39381, + "sha256": "6f2b9cac49970b80fbfb0f71da38dee3431d78df3d361c9233e763e1bf6a8cd4" + }, + "scripts/transport/elevator_service.gd.uid": { + "bytes": 20, + "sha256": "8dc89574d1eb5ade839b4989d0b772c2072800d8715829211d7bf515cd10dad9" + }, + "scripts/transport/warp_service.gd": { + "bytes": 5463, + "sha256": "7602c6b8a9672a703bfa98a1424c2cf68cf50184f87f72349d564af6a5ca9d41" + }, + "scripts/transport/warp_service.gd.uid": { + "bytes": 19, + "sha256": "ef4627c03a4a0e358cfc0b8de71fd33ad6d69e24b5a83b492388adec18e5da0d" + }, + "scripts/ui/business_management_panel.gd": { + "bytes": 28271, + "sha256": "e41b95e6d5e118473668b83102091a41df7dd46bd251eb625d3fac17b3733d01" + }, + "scripts/ui/business_management_panel.gd.uid": { + "bytes": 20, + "sha256": "e80feb5642e102e81e8ca348214ccefc1bcc09569869fb0de539b61fd6e9c83f" + }, + "scripts/ui/defense_management_panel.gd": { + "bytes": 21941, + "sha256": "c5d38781e6f73fba121f2274e310b11abd4f7e853250b1ed6c5d72a6d573d011" + }, + "scripts/ui/defense_management_panel.gd.uid": { + "bytes": 19, + "sha256": "8e1ae906531bef51d59cc00453c4af1af52f21a49b89940e4dd4b02b87225f74" + }, + "scripts/ui/event_log_dialog.gd": { + "bytes": 13638, + "sha256": "62000f559c49c3a58b244b991c10c1738add10702bfa66cb7cb40798cb559290" + }, + "scripts/ui/event_log_dialog.gd.uid": { + "bytes": 20, + "sha256": "0f49390449b1c1445b439d29fb9d60265e12cfbf6a7ee2a0328ab138a6a58199" + }, + "scripts/ui/guest_observation_panel.gd": { + "bytes": 7948, + "sha256": "f5de1004fce5445bbfd3ee8d6ec37b325e7a9813d47c19beaeeeb411f27a50a5" + }, + "scripts/ui/guest_observation_panel.gd.uid": { + "bytes": 19, + "sha256": "f4324cbcee9ad7f6ce373fca811b76e0e0e6633ff398b5e8a5adeb9dc615db7b" + }, + "scripts/ui/inactive_layer_rooms.gd": { + "bytes": 734, + "sha256": "1bbda80eb5ca9202de900be152cb18d5d59cb386c1eab5ecec6cdce4e042bad8" + }, + "scripts/ui/inactive_layer_rooms.gd.uid": { + "bytes": 20, + "sha256": "1ff083528b669c285afbd7de48e766eb29029b39c3010eebab11b21dbcd17c82" + }, + "scripts/ui/infirmary_room_art.gd": { + "bytes": 3100, + "sha256": "f8333f7915fe453eaee6f00ff1b1539b2ae67fecd508566292bf9ea986531a75" + }, + "scripts/ui/infirmary_room_art.gd.uid": { + "bytes": 20, + "sha256": "dd0b6f575496131a0cd951ba41785fe657126687623a42e92740eaaa5f8847a6" + }, + "scripts/ui/inn_opening_guide.gd": { + "bytes": 10664, + "sha256": "6a51c98929a6f57f24d309bc027ba68ea818c69f9b280a5cbf085a4ceb33ac1b" + }, + "scripts/ui/inn_opening_guide.gd.uid": { + "bytes": 18, + "sha256": "f74eb7dd42fed3723958d07ad3e85986ca1671f703193aaf86f6bfc940b3ada0" + }, + "scripts/ui/layer_interface_skin.gd": { + "bytes": 3727, + "sha256": "5524422aaee5e0f45f5c1c504e4cb14257ddce5f875d70f32b21333c76c1452d" + }, + "scripts/ui/layer_interface_skin.gd.uid": { + "bytes": 20, + "sha256": "4e931be72a318b3b501e0819f5fa17a805fc95ed15605ffb1416f54637f19708" + }, + "scripts/ui/manual_save_slots_dialog.gd": { + "bytes": 6164, + "sha256": "e903ecfacb425389a47f9e21277eb5f621fe371fff009816d39abcb66b8ed4f1" + }, + "scripts/ui/manual_save_slots_dialog.gd.uid": { + "bytes": 20, + "sha256": "a31f96c32c1769bceb0ec5a00afa06d1a33dda19d90375515610441a39920b90" + }, + "scripts/ui/operating_ledger_panel.gd": { + "bytes": 16054, + "sha256": "652b3c98c4cdc707831a19ba1e91e23f21895f0fbf3ece40826e03df3b656a1d" + }, + "scripts/ui/operating_ledger_panel.gd.uid": { + "bytes": 20, + "sha256": "f0c15f4b61abad6be732b4c6b92b04498841e1aed9c18d396fb7d90b5eedf34b" + }, + "scripts/ui/paired_bgm.gd": { + "bytes": 3826, + "sha256": "a7fe9311f348975a380feced102702ad3ee91439b9511006f0ff6d29540f5836" + }, + "scripts/ui/paired_bgm.gd.uid": { + "bytes": 20, + "sha256": "cf49b2b6404bd0283e11afdb7efa29d191d6ff575e7cb298fb051547cc97118e" + }, + "scripts/ui/pixel_people.gd": { + "bytes": 4270, + "sha256": "a171703083aa2d00f8be2b63e1daef9c41717c8fe59d8056878bc4b7df1e0b0c" + }, + "scripts/ui/pixel_people.gd.uid": { + "bytes": 20, + "sha256": "b63a747b5d8f81d2fcc002fe20ff1204942ad535f691664f6ed7a8575b859c8b" + }, + "scripts/ui/pixel_tower_art.gd": { + "bytes": 15443, + "sha256": "f766b47167db8bd5906b1467fd6f8587af8e9268304c7ba209a9eb157847165e" + }, + "scripts/ui/pixel_tower_art.gd.uid": { + "bytes": 20, + "sha256": "f53c12bb18bbc2122578b3d6d88998c4059e4305557b32cddc1704082d0a4d7b" + }, + "scripts/ui/pixel_tower_demo.gd": { + "bytes": 6178, + "sha256": "dfb1ffa5f7dd239ef84d7f8a2845184884982a8a4f53b002272d4c31af62ea6e" + }, + "scripts/ui/pixel_tower_demo.gd.uid": { + "bytes": 19, + "sha256": "d7a1208e97e5f6497a55607c6f5d51d0d8cc820d9dcc1c0a01319485837d77e9" + }, + "scripts/ui/room_presentation.gd": { + "bytes": 4252, + "sha256": "2eda851534777575298ea005e2e6d0ee90785a81357d5b9c34cfb95f615a8181" + }, + "scripts/ui/room_presentation.gd.uid": { + "bytes": 19, + "sha256": "dfecf526720439bc56673c58b08ac2148a269b274927484e606d1f9e1dacc53d" + }, + "scripts/ui/staff_management_panel.gd": { + "bytes": 23519, + "sha256": "df3120130956b300d1349cb758c0aa30dfd7da5e0774fb7fb9a1f3e4e0786fb2" + }, + "scripts/ui/staff_management_panel.gd.uid": { + "bytes": 20, + "sha256": "3083f1194fd205904b784f5c3c120e5bed770d0feda5fd96be5cc8338e3c7137" + }, + "scripts/ui/standard_room_art.gd": { + "bytes": 2800, + "sha256": "8f0f2af2a3903fc1debc760037dc8fab92e4fff1e49803fcb56a56ab1f04defa" + }, + "scripts/ui/standard_room_art.gd.uid": { + "bytes": 20, + "sha256": "9ea9d28b94349bcf5146c2a9a671922aedcacb1c2983c7d974b5f9eab463585f" + }, + "scripts/ui/supply_management_panel.gd": { + "bytes": 34568, + "sha256": "f122174cc1efc3a964187ef0dcb23abf342d1f8b8ef0305800ae85aab8db003a" + }, + "scripts/ui/supply_management_panel.gd.uid": { + "bytes": 20, + "sha256": "efd5c344b0f3bb6cc786e160aea738f9e8239a613f258fa10e44803da45b96a7" + }, + "scripts/ui/ui_audio_feedback.gd": { + "bytes": 11933, + "sha256": "95078f3c4ed3d58573b93290360e730cf908d8a7e98b5ea72b435dbe35358b30" + }, + "scripts/ui/ui_audio_feedback.gd.uid": { + "bytes": 19, + "sha256": "117146780ab8e9cf6b345a27ce94ae42e5228c8524b0b9f76a14a12cc7bb67b9" + }, + "scripts/ui/ui_audio_owner_shutdown.gd": { + "bytes": 7783, + "sha256": "6ee83bcb5c922363b62847c26ef2139bb7e8847bef4c100d3738c2ef9f024102" + }, + "scripts/ui/ui_audio_owner_shutdown.gd.uid": { + "bytes": 20, + "sha256": "49d08fa773bc6b8f9a6560b47e7d065d2ed272f20b60242cfa64102769a63b17" + }, + "scripts/ui/ui_audio_settings_dialog.gd": { + "bytes": 3405, + "sha256": "c2f7ecd14f3e7856ed0a384922e5aa0843e1e91ac547545a03f51a0fc0675ea1" + }, + "scripts/ui/ui_audio_settings_dialog.gd.uid": { + "bytes": 19, + "sha256": "4078c949c0c90ca45be8130e6b15443004d5831ca31b0c601a0e47d2ce0b234b" + }, + "scripts/ui/visual_theme_profile.gd": { + "bytes": 3110, + "sha256": "2a251a94d4a18c2ddd9e307cb810d1f327c12f2f15cd3bed91e65aa499258ceb" + }, + "scripts/ui/visual_theme_profile.gd.uid": { + "bytes": 20, + "sha256": "1977d023efae6111453f3f8abf9e43e6bb439321e7b3fb483b2de1850680d3a2" + }, + "scripts/ui/world_tree_rank_dialog.gd": { + "bytes": 7103, + "sha256": "fb5ca195c02a3c52cc51b4761fcbf881134fc35c023895a42857f894dd7e22c4" + }, + "scripts/ui/world_tree_rank_dialog.gd.uid": { + "bytes": 19, + "sha256": "06e0d65047929d3d65068ff7a49ce84e216df803908dd47888573e2abcff0abb" + }, + "scripts/world/facility_infrastructure_projector.gd": { + "bytes": 77159, + "sha256": "7903b7aa6a46b50150beeb13dd8675ce34168c044b1b818f0dc6e2f7e1872d51" + }, + "scripts/world/facility_infrastructure_projector.gd.uid": { + "bytes": 19, + "sha256": "0298a54b543c61c6aa57a8ce17e14c224d9f706dcb9957ee000de75eb43876c5" + }, + "scripts/world/legacy_stair_service.gd": { + "bytes": 11482, + "sha256": "e6899ee68894a59af061056ceb8673a772cdcc80a63dab5b4d54309429c33c2c" + }, + "scripts/world/legacy_stair_service.gd.uid": { + "bytes": 20, + "sha256": "bfff32f0080489e82735b055643d4d3eb91fa74d324055590b3b78d15fa11577" + }, + "scripts/world/path_service.gd": { + "bytes": 118514, + "sha256": "d5eb5be7957466fc9f5a63893511692fa55210cc101b217d374863bb03b44dcc" + }, + "scripts/world/path_service.gd.uid": { + "bytes": 19, + "sha256": "ec3066a687f50a7301c96ae6ffc294a6a03abc40a697f5fa80dd7922d959f267" + }, + "scripts/world/route_subslot_path_adapter.gd": { + "bytes": 45317, + "sha256": "df5e6c3eee25b74b1e77aa6d7f6e7e5b516c5a8ad78b0db3b847c9f06a9e631f" + }, + "scripts/world/route_subslot_path_adapter.gd.uid": { + "bytes": 20, + "sha256": "e89a6dfe271e5c0a817f1a6564ff2af642b58962da882fcdffb7b85d149fecf7" + }, + "scripts/world/spatial_subslot_service.gd": { + "bytes": 33197, + "sha256": "6238843f3f53e8fa21e325a8152e9a77aca97aebe495a05fb19d37ee62d549ae" + }, + "scripts/world/spatial_subslot_service.gd.uid": { + "bytes": 20, + "sha256": "c4019cb03891a10e65448347704ebcdaf9a47a3195c48d74ce5ae86c4402ee88" + }, + "scripts/world/world_service.gd": { + "bytes": 25487, + "sha256": "add67a0799f961a7dce1d382ea6dac67022fbd013f8c4c6b11321df96f37944a" + }, + "scripts/world/world_service.gd.uid": { + "bytes": 20, + "sha256": "b55799071888fddf43fc42485a3aed5bd9d63c522fe0f68b7d62f544fa3ea21b" + }, + "tests/business/test_business_closure.gd": { + "bytes": 10795, + "sha256": "de9a36cea18a450bed920ded051d2edd4fa2babedac881be85e2cf2d8ad82363" + }, + "tests/business/test_business_closure.gd.uid": { + "bytes": 20, + "sha256": "0614d0ba4fe9247f0c0afba96705dd6d14ad2a138fbd1dc9b760717f1f15afc2" + }, + "tests/business/test_business_operations.gd": { + "bytes": 11383, + "sha256": "5dfd8f256a191835fd88af1e4dd6151dbfc87b767b443023a04f415eecce0adc" + }, + "tests/business/test_business_operations.gd.uid": { + "bytes": 19, + "sha256": "95ce34e2bd7124cef52a142349d65dc86e4fd5cd5ae1403ed013b12fbd00fa10" + }, + "tests/business/test_required_kitchen.gd": { + "bytes": 40414, + "sha256": "5af5b757dd11285c1bf56155b17b397fe4178f6d86cca119035ae7d11e8ca5bc" + }, + "tests/business/test_required_kitchen.gd.uid": { + "bytes": 20, + "sha256": "8b89c83188edcc5d937faff73c60b83172e8ebf4647aa7eadcf1a15b17a9bda6" + }, + "tests/environment/test_cleaning_access.gd": { + "bytes": 2330, + "sha256": "1382eab9d01dffaa396cb7fb71902538ee649a963ac9e1fd099ea7a147669884" + }, + "tests/environment/test_cleaning_access.gd.uid": { + "bytes": 19, + "sha256": "3dd8599284854c457df1af13f59d2c84b22dc712ef1dc4c2a9ca923152dd85d1" + }, + "tests/environment/test_facility_cleanliness.gd": { + "bytes": 7183, + "sha256": "6dba789489d3e7da8cbd5056f76d7a5eb97c454b087787ccda926682c328a5f5" + }, + "tests/environment/test_facility_cleanliness.gd.uid": { + "bytes": 20, + "sha256": "64b2a8e991a902e81ea08f34e8f5886b67723de3380c9e964783f6ef86fdf540" + }, + "tests/environment/test_runtime_cleanliness.gd": { + "bytes": 6177, + "sha256": "3b5fe92855f17f1551de76fe1570dbf92c697b769721bb87582bc4d4d06e36b4" + }, + "tests/environment/test_runtime_cleanliness.gd.uid": { + "bytes": 20, + "sha256": "e84d2e2c086165371e68da1e216bb2f0dcc36fdad0b8adbf2f96dba57f15620a" + }, + "tests/environment/test_runtime_weather.gd": { + "bytes": 3533, + "sha256": "047bb23573ef6a4c7e2483e3a2bfd244a3e2061fbf65c33fa08a52952a2655a0" + }, + "tests/environment/test_runtime_weather.gd.uid": { + "bytes": 20, + "sha256": "e68d6e9921879f54828b07e77719384b52b145dc4d5052c692a34090466037f2" + }, + "tests/environment/test_weather_recovery.gd": { + "bytes": 2916, + "sha256": "d71bf3fbf1fa1d43eae2c38161a44b18fc6cc34477a1ab9dd12fca54e4ee9089" + }, + "tests/environment/test_weather_recovery.gd.uid": { + "bytes": 20, + "sha256": "c26cceb4eeb2968f4b9226cdf54fdfecec9829a77339741f7500f38f524296e9" + }, + "tests/environment/test_weather_timeline.gd": { + "bytes": 3810, + "sha256": "212dab5036f90ae2eaf1b75e0c0adaea4a572cdbfb31b07d0ef4336def4f4791" + }, + "tests/environment/test_weather_timeline.gd.uid": { + "bytes": 19, + "sha256": "2654cc9a56e546ae0632d3d97897ecab3d818a434b26184787696ae49370e0de" + }, + "tests/export/test_exported_opening.gd": { + "bytes": 7099, + "sha256": "b2d96ce4c40582a61a4b4f042bd38c188ce5351daf1206720b41183d5ba15c51" + }, + "tests/export/test_exported_opening.gd.uid": { + "bytes": 20, + "sha256": "e0d77ae08862e353feec1fe3f5ed9e0093cc281d364befb836be7dfb8a7c9bef" + }, + "tests/fixtures/facilities/invalid_service_profile.tres": { + "bytes": 1077, + "sha256": "8bd02f6ca505a9bd65360a1ce99f961252bc201c5381e0033519ef4952f8f2e6" + }, + "tests/fixtures/legacy_premium_room.tres": { + "bytes": 746, + "sha256": "bf035db5deea3818ab12f029fdf53f65afa2f5c99fec4a236ce7dfb7076f5bb7" + }, + "tests/fixtures/legacy_staff_dormitory.tres": { + "bytes": 771, + "sha256": "84c7a92216300a20f627c7e822219cf188912d9ba3417fa910261d18bdaf69cc" + }, + "tests/fixtures/p08-02/README.md": { + "bytes": 1333, + "sha256": "e88ca33fdb4e96602d1fb108d71a9c35b6fa054619ecf6f1396e9a6c5e0ebd98" + }, + "tests/fixtures/p08-02/mixed_world.gd": { + "bytes": 17942, + "sha256": "a23f8a686be1d77e4874b9956eef89be4756f6e5eb01cc62454c3845acc62c25" + }, + "tests/fixtures/p08-02/mixed_world.gd.uid": { + "bytes": 20, + "sha256": "d7549f933b74f5e807cd2d3b3adcdd083af4a3bd331614314ff7bfd7b0903f31" + }, + "tests/fixtures/p08-02/reader.gd": { + "bytes": 466, + "sha256": "a760d0e45979d747dbd1f8710033bdce13287b00eb879d947d8378ff920ed1be" + }, + "tests/fixtures/p08-02/reader.gd.uid": { + "bytes": 19, + "sha256": "3e68ce192d5770e3823df9699c5c99ebb618fe0a480b4d56913624941900b08a" + }, + "tests/fixtures/p08-02/writer.gd": { + "bytes": 466, + "sha256": "1a918b5509773b4b07a27d47ee44583b0eb5288138f7bf896088a7913773c260" + }, + "tests/fixtures/p08-02/writer.gd.uid": { + "bytes": 20, + "sha256": "8f150654767de0c66329d7d9e84d306c4fa5a65c918e04fb520b626b39f68334" + }, + "tests/fixtures/p08-03/checker_fixture.py": { + "bytes": 32016, + "sha256": "80b9ad74b04b8d235b3ff152ca2cba720085ec420c7dc7cbf07274d534f8fdfb" + }, + "tests/fixtures/p08-03/passive_placement.gd": { + "bytes": 15763, + "sha256": "210c95c4df9ac16197ebaad67f7531d66b841e9d03c05c014a846bb9186bc2d0" + }, + "tests/fixtures/p08-03/passive_placement.gd.uid": { + "bytes": 20, + "sha256": "f75e3f2d9555c30cee3a1de882f32225fc624565a78a7ef3f5c604325c578ce3" + }, + "tests/fixtures/p08-03/placement.gd": { + "bytes": 22208, + "sha256": "c59f08fd232f73d0e06398cd3577aba8f5a5840d18c61ce5c88db9e7dba51923" + }, + "tests/fixtures/p08-03/placement.gd.uid": { + "bytes": 20, + "sha256": "5caca08c1e627e0ca07e2ab7b13bd82b24a22f77513fe87e30b79023568e1987" + }, + "tests/fixtures/p08-03/r05-reader-checkpoint-provenance.json": { + "bytes": 552, + "sha256": "daf034375facf36e9cc8da4ec0001d7c7b017c315a9155680b4b490e582ec5b9" + }, + "tests/fixtures/p08-03/r05-reader-checkpoint.json.gz": { + "bytes": 49774, + "sha256": "27fd3b41834106ccd6a0980dfa2bc91cc19806dd3f552ba04246efb400763233" + }, + "tests/fixtures/p14-03/README.md": { + "bytes": 1651, + "sha256": "a79bce1919fceb43ef95fcf6963731ca94200ea2cbd236c1a3e646fd8a83d1d0" + }, + "tests/fixtures/p14-03/legacy_rush_v1/journal.log": { + "bytes": 35, + "sha256": "978fd98f250ae5a9d3249f22adc3dcf032007dde92ddd10d556e050dd87616d8" + }, + "tests/fixtures/p14-03/legacy_rush_v1/manifest.json": { + "bytes": 441, + "sha256": "80c251341bd3f2a6c4a659f30e477dd856c9fec7961d5b2dfd98d7e9eb5006ab" + }, + "tests/fixtures/p14-03/legacy_rush_v1/thumbnail.png": { + "bytes": 83, + "sha256": "0ef55674eca98b6748ae5ccca85a14b042c1545a143810c9c47b487119895c32" + }, + "tests/fixtures/p14-03/legacy_rush_v1/thumbnail.png.import": { + "bytes": 968, + "sha256": "a4387146724cd29d96797242569f8ab8d24773124a6ff4a00b62564b0522ab33" + }, + "tests/fixtures/p14-03/legacy_rush_v1/world.bin": { + "bytes": 14813, + "sha256": "26171ed8994982ed13fe038d225522044f1049070be53d76a4ed5572a227257d" + }, + "tests/fixtures/p14-03/legacy_rush_writer.gd.txt": { + "bytes": 1967, + "sha256": "be679569f7212f1fa44661a4e59985d8ae837976f2d2a37132a046ebcfec3676" + }, + "tests/fixtures/p23-03/diagnostic_stream.gd": { + "bytes": 7900, + "sha256": "b23500c7e8041e56c1a7845a50e9a7c955da69439f54901b7c00b770f20ae9c7" + }, + "tests/fixtures/p23-03/diagnostic_stream.gd.uid": { + "bytes": 19, + "sha256": "1f3cbee159dc93c7bd7dd7f0a3b9e9103ed43ecb341c3a900c1df59377d8bb20" + }, + "tests/fixtures/p23-03/layout_comparison.gd": { + "bytes": 5625, + "sha256": "fd84165ac031575b92ef6865dd188c017569f894ad65ded29cd37300f01a6553" + }, + "tests/fixtures/p23-03/layout_comparison.gd.uid": { + "bytes": 19, + "sha256": "8a33dd196d801c199de7e4e0607b883baf52ecf67d9b9957b839bbf750928d82" + }, + "tests/fixtures/p23-03/observation.gd": { + "bytes": 11227, + "sha256": "a9a0e611f1262151549ff033eae618436e52f661d52decbab5adb93efc4dcdf5" + }, + "tests/fixtures/p23-03/observation.gd.uid": { + "bytes": 20, + "sha256": "87f8d1b584d37053b76f27e02e06fefd77b2b8bbf42a7d92404d4c4109934988" + }, + "tests/fixtures/p23-03/passive_observation.gd": { + "bytes": 14112, + "sha256": "812c2a3b399b079333e4eae0fbf78946f1c39041e6859e65f8bc7c44aaad6bfc" + }, + "tests/fixtures/p23-03/passive_observation.gd.uid": { + "bytes": 20, + "sha256": "8c4295b0605c6278168e6d57489075c04b75df7c9a7078b91c6b1ff8d9cbd799" + }, + "tests/fixtures/p23-03/passive_os_recorder.gd": { + "bytes": 447, + "sha256": "b90f054faa4fd46e6a30ba12d2ce22cdcfb281351b209650c8a00a7713767e47" + }, + "tests/fixtures/p23-03/passive_os_recorder.gd.uid": { + "bytes": 19, + "sha256": "269ff76c69fd161b0a979cae1dc938e9473dfde562c826a0acbda824004c576a" + }, + "tests/fixtures/p23-03/queued_elevator.json": { + "bytes": 1145, + "sha256": "825a5bc8568cd890e1faf8c7e0122c43958f334711b0602dc2c3231373aa4fef" + }, + "tests/fixtures/p23-03/r13_actor_overlap.json": { + "bytes": 716, + "sha256": "a6b433c56207a172286745b57df72a76bfc2be9ac2adb15d629b4e8ab53d7985" + }, + "tests/fixtures/p23-03/r13_service_region_gap.json": { + "bytes": 1083, + "sha256": "43e82a2a12906f0d0ce917c77b64bff6813b0a4fe5b7b287ee8311f6b3b43750" + }, + "tests/fixtures/p23-03/recorded-badge-negative.json.gz": { + "bytes": 83518, + "sha256": "17b1596fb1dca0436cd656ac21a9dc754c75b4485335a0aebe533f70e1c1b5ac" + }, + "tests/fixtures/p23-03/repair28_frame180_projection.json": { + "bytes": 45466, + "sha256": "95bbd41dcc5db1388e5ecc14557dfafd6bd540d707532588fd6126e8d6843d63" + }, + "tests/fixtures/p23-03/repair28_r15_negative.json": { + "bytes": 1059, + "sha256": "8525cdfbc504583778624ab103efb4642374715be73187e97bdbf18d180a1616" + }, + "tests/fixtures/pre_auto_purchase_runtime.gd": { + "bytes": 353, + "sha256": "04cafc71c3d26ec25e2d9205a4845671c2d6b52c7b5ec5052887beca9748f906" + }, + "tests/fixtures/pre_auto_purchase_runtime.gd.uid": { + "bytes": 20, + "sha256": "dcf584c1243a8503292bb394b9111a19f4ad6dfe1841f3a30ffdc701779bdeb0" + }, + "tests/fixtures/pre_upkeep_runtime.gd": { + "bytes": 1115, + "sha256": "685032e836d7c428dbefaccdbaad098343687b684934e61d1b9d04d7aa5f21a5" + }, + "tests/fixtures/pre_upkeep_runtime.gd.uid": { + "bytes": 20, + "sha256": "8908e29bb5e8834defed1e042eb0b45b26f2812cab94ca5a70547e90f9134331" + }, + "tests/fixtures/required_kitchen_legacy14/formal-package/journal.log": { + "bytes": 35, + "sha256": "defee9e7f3721ca05f4f1ba839fee8dba773a798c1b8408df31327eb19d2a1ad" + }, + "tests/fixtures/required_kitchen_legacy14/formal-package/manifest.json": { + "bytes": 449, + "sha256": "4b276a7b6abad39ecfe2e43114b5637b61640a626580dce4b5871e648a182a7d" + }, + "tests/fixtures/required_kitchen_legacy14/formal-package/thumbnail.png.bytes": { + "bytes": 83, + "sha256": "0ef55674eca98b6748ae5ccca85a14b042c1545a143810c9c47b487119895c32" + }, + "tests/fixtures/required_kitchen_legacy14/formal-package/world.bin": { + "bytes": 15405, + "sha256": "7bd0fe615790b55e09f0bf7c047a19173011f49954403c655644c5865830c13c" + }, + "tests/fixtures/required_kitchen_legacy14/provenance.json": { + "bytes": 3496, + "sha256": "07208464afd903366275e39dc9d09d8ebf936e384bc55d570e0f77a2cad36783" + }, + "tests/fixtures/required_kitchen_legacy14/write-checkpoint.var": { + "bytes": 159576, + "sha256": "a5348a17af34e717108f9ccceb215223ce48f1db1aebbd9024a9ea02c637adaf" + }, + "tests/fixtures/required_kitchen_legacy14/write-contract.var": { + "bytes": 392, + "sha256": "f32e3f3c0ef44f56b4c320206f6507a4ca5074be5f7813e2f5c76a47c152b3cf" + }, + "tests/fixtures/required_kitchen_legacy14/write-persisted-before-io.var": { + "bytes": 158836, + "sha256": "6a0ba26642176c9432ce272e578764b3336731ea9b4d07ac9623f9fcdeed077a" + }, + "tests/fixtures/required_kitchen_setup.gd": { + "bytes": 4874, + "sha256": "30706107c90bbd7ebecb930666426a8ce45d6003cb3a26bb35c7452be4e5fd95" + }, + "tests/fixtures/required_kitchen_setup.gd.uid": { + "bytes": 19, + "sha256": "527436138aa188d58579ebbf54a07f085e355dc15c3a973efcafef2d166bdb6b" + }, + "tests/helpers/mana_outage.gd": { + "bytes": 920, + "sha256": "8df68f67fd023fb3fed4c465acf8227094d0e9403efc1f56ae009685629563e1" + }, + "tests/helpers/mana_outage.gd.uid": { + "bytes": 19, + "sha256": "27c76eb680b27f12c9eb2fa21b4aaa286b2f321ae41f860ab596528b2e25f533" + }, + "tests/helpers/ui_audio_fixture_cleanup.gd": { + "bytes": 4282, + "sha256": "02cd9796d0bf6222c9e9e6ddcb7fb75235bab645c2f10dcb1b4e9f0bc6077260" + }, + "tests/helpers/ui_audio_fixture_cleanup.gd.uid": { + "bytes": 20, + "sha256": "810aad3c800a266d7472103bd953bbce9f29deb976c2a9a3d5cbfa470c0f7750" + }, + "tests/helpers/ui_audio_teardown.gd": { + "bytes": 4913, + "sha256": "8afe4f86b60fa4ddc8752bb5f556f834996c678a022a1035979a801c70b42747" + }, + "tests/helpers/ui_audio_teardown.gd.uid": { + "bytes": 20, + "sha256": "bbcf13097bbcef77448067c5730d02fc8543aa46696d2a43db8247b62f6f5651" + }, + "tests/mvp/fixtures/README.md": { + "bytes": 652, + "sha256": "025dee51e990e3151070e247bb24abb6ed3f3a28cd55d929dd3a0d4788105e63" + }, + "tests/mvp/fixtures/operations_v3_0600.txt": { + "bytes": 26825, + "sha256": "dac35666fe0535a2aa979230ed45b85c9406a7878c9e39a8c7d35dd6c056638b" + }, + "tests/mvp/test_amelia_donations.gd": { + "bytes": 4722, + "sha256": "1bd622a3d88374f01e3d8885a84a816572ed296928f6ce7e3f8134ab15f60793" + }, + "tests/mvp/test_amelia_donations.gd.uid": { + "bytes": 20, + "sha256": "c0a2ea56341817ab29adaed37f83d1407aa3377fa8bb0700e307322ec4e031fb" + }, + "tests/mvp/test_anri_floor_pricing.gd": { + "bytes": 10621, + "sha256": "420cd0b14c0a4921ab3a45e612773f8afd38a31b566d1b95942d3e5defc004b1" + }, + "tests/mvp/test_anri_floor_pricing.gd.uid": { + "bytes": 19, + "sha256": "b86b32be653a78515870510a71ea44e549a09573edcda8c87fa81187abc1ad5f" + }, + "tests/mvp/test_approved_free_unique_arrears.gd": { + "bytes": 15412, + "sha256": "411d7836326f2858b68201bc3e8fec2b1d365291342939249cbf5a40a20d6b0b" + }, + "tests/mvp/test_approved_free_unique_arrears.gd.uid": { + "bytes": 20, + "sha256": "3eeb8425240dfcaff8b6b989d38ea678998ae9f41720465e3e1dfca24d900067" + }, + "tests/mvp/test_chapel_boundaries.gd": { + "bytes": 7252, + "sha256": "a857179fbe5186e27080ef7bae13775edcc821440cd763fd793e03ef7d27ac5c" + }, + "tests/mvp/test_chapel_boundaries.gd.uid": { + "bytes": 20, + "sha256": "e794ed6920599c1f904c3db23a19da62e55ed273c6f32e15285e45e1b0a2dfab" + }, + "tests/mvp/test_chapel_service.gd": { + "bytes": 5348, + "sha256": "b8631e1095ce7714d2ae581a6ee3d8fe47065184b7dd05e9104a2b7c0cacb1c1" + }, + "tests/mvp/test_chapel_service.gd.uid": { + "bytes": 20, + "sha256": "5e48b0e74acac76805e0e9eb492ebd27e0cfffa3a1b7a6ff27c3dac0e1761d82" + }, + "tests/mvp/test_fine_cleaning_effect.gd": { + "bytes": 1164, + "sha256": "7c7df0bac1c072ed4423140e8afe431952ec2a47f76df7dbc24cab62283cae06" + }, + "tests/mvp/test_fine_cleaning_effect.gd.uid": { + "bytes": 20, + "sha256": "800a475b52b5a0a0de6c4fabb7a52b9c5ab44265bc593232039d77e49bca9f22" + }, + "tests/mvp/test_mvp_content_catalog.gd": { + "bytes": 19911, + "sha256": "b663b8790d02acfa836c8a6a6609f337c7991b7b91d271d1b60b76d137bbd62b" + }, + "tests/mvp/test_mvp_content_catalog.gd.uid": { + "bytes": 20, + "sha256": "f5035967a5f68772406f9c7d3c18d4fd881d86ed8fba6e7a0810b76c183b295f" + }, + "tests/mvp/test_operations_coordinator.gd": { + "bytes": 72455, + "sha256": "87499bf5f45a7201cb16082df0ac1031b7b28e9c725950013252d0bb9e5efd6f" + }, + "tests/mvp/test_operations_coordinator.gd.uid": { + "bytes": 20, + "sha256": "06151608ce04773e7644b5c73d0441959ea1f35d756050801183f47ebfc8be7d" + }, + "tests/mvp/test_original_midnight_settlement.gd": { + "bytes": 22752, + "sha256": "2e6d7e907156db36a44b2e3b124b2311ddc79fe45250b8dc312b0a3f543bb7d1" + }, + "tests/mvp/test_original_midnight_settlement.gd.uid": { + "bytes": 20, + "sha256": "f809b227a95ea335913280641921bcbfd4dea6d1718dbd3ca9f3ca75547e2792" + }, + "tests/mvp/test_original_room_zones.gd": { + "bytes": 3123, + "sha256": "6f1b99f2bac0e58eab30fbb061796c88fc93a21e24de7bdcd5ee39a4c02fe8df" + }, + "tests/mvp/test_original_room_zones.gd.uid": { + "bytes": 20, + "sha256": "4749b562451f6f83da92fe4b33cc3c634c1612fc61f9a163b33b51094e897d9e" + }, + "tests/mvp/test_pending_service_pricing_report.gd": { + "bytes": 15155, + "sha256": "50095c41fe76bac7bd9346ce97651d40610fa69b48c3b24f7acc5b371578e753" + }, + "tests/mvp/test_pending_service_pricing_report.gd.uid": { + "bytes": 20, + "sha256": "279793f087419da5ab359f2759c99bd9a0f79e4993aba3df7427f434cf099d5d" + }, + "tests/mvp/test_premium_room.gd": { + "bytes": 3648, + "sha256": "ce79ae9632cd17f84ca52961e098d5015921d81abcf57acc72461a16dd44baff" + }, + "tests/mvp/test_premium_room.gd.uid": { + "bytes": 20, + "sha256": "87e41939d21089899b265a05e12a4a4f1271cf7cb156319fb543e9601831da57" + }, + "tests/mvp/test_premium_room_guest_flow.gd": { + "bytes": 7302, + "sha256": "11bad6a34aec3a252ddf125813812e9b7fab5879d8536dfc904a48df7ff9ef83" + }, + "tests/mvp/test_premium_room_guest_flow.gd.uid": { + "bytes": 20, + "sha256": "2163706f4a8724817328449b3d8276a29fd046f5d219f31eb12c9bd12b3e5f78" + }, + "tests/mvp/test_progression_service.gd": { + "bytes": 24916, + "sha256": "f97895fceacc42fbbe14f3e77972ef980abf8f63ca9a5c8c8d4003900305b0aa" + }, + "tests/mvp/test_progression_service.gd.uid": { + "bytes": 20, + "sha256": "1c2bbbff10ca421c86e343f19b577acb683c1d55bc55b04723d70d7cfc24f119" + }, + "tests/mvp/test_runtime_content_progression.gd": { + "bytes": 28837, + "sha256": "c8f7a107d024693b863feb2c9cc460383b98cf04e5ed872011bcd7024be68d60" + }, + "tests/mvp/test_runtime_content_progression.gd.uid": { + "bytes": 20, + "sha256": "9bc80330a8223b88ae5a4cf13882c866a578ba2af7069d621800116c36732ed4" + }, + "tests/mvp/test_runtime_mana_depletion.gd": { + "bytes": 5452, + "sha256": "5f984af2ca1cb99ecec7c1fa61bfee46317aef2d0abccfa3f317364acbf30c11" + }, + "tests/mvp/test_runtime_mana_depletion.gd.uid": { + "bytes": 20, + "sha256": "1f91a438e41a8336b200d615a971bb261e8e9811f5d57b2c9b60b9e65ed2cdcf" + }, + "tests/mvp/test_runtime_operations_acceptance.gd": { + "bytes": 19115, + "sha256": "a802afdc5786b6690a2c8b81f39eefda9c04624826d5cb90c587cf84190feea3" + }, + "tests/mvp/test_runtime_operations_acceptance.gd.uid": { + "bytes": 20, + "sha256": "1028606ca8681156ea59df3e5426deccbfa0cc5588af043da24510408ec86d7f" + }, + "tests/mvp/test_runtime_operations_integration.gd": { + "bytes": 29023, + "sha256": "8865d8f68c454fe9ebba602bffdfe83f868380f84160bf15aaec22062783fa08" + }, + "tests/mvp/test_runtime_operations_integration.gd.uid": { + "bytes": 19, + "sha256": "912ce232fa77410855edf1dad667117f5493c819c484dfe0a69c5af316396637" + }, + "tests/mvp/test_runtime_upkeep.gd": { + "bytes": 7337, + "sha256": "eae48823d58d78c419d29728e33a5559fbe5131b49e33d04ca4e6fa3a721c29b" + }, + "tests/mvp/test_runtime_upkeep.gd.uid": { + "bytes": 20, + "sha256": "14b8b1294689ba7f5380374590480e781ed8f992d52b1605c83d76212d330ed2" + }, + "tests/mvp/test_staff_unique_contract_report.gd": { + "bytes": 9224, + "sha256": "93d7b00d3b27a85246dad25337a25c0036d562390e584854fe89c958ada76907" + }, + "tests/mvp/test_staff_unique_contract_report.gd.uid": { + "bytes": 20, + "sha256": "8a8eefe8c949649b53ca5002f44ce7c5047642a4e11156510ad97a2ff0873cdc" + }, + "tests/mvp/test_tomari_floor_trouble.gd": { + "bytes": 10699, + "sha256": "09581fbc32b29d2b5773e0859f22ca58c947927d11e6523027ffe277bd7ac303" + }, + "tests/mvp/test_tomari_floor_trouble.gd.uid": { + "bytes": 20, + "sha256": "cb5120adf7650fab66b903a159903ee107ccf7529c1cf0fdcb7ba48051a2ebaf" + }, + "tests/mvp/test_unique_character_validation_policy.gd": { + "bytes": 17457, + "sha256": "2b4c70506e4436e5afe4bf987ff9bba765a02394a4de86e2ed0af6ba5b68c766" + }, + "tests/mvp/test_unique_character_validation_policy.gd.uid": { + "bytes": 20, + "sha256": "7bc8edf74c119a16db928a0ee8f754b421fd8df28d824fd50c6e24f92f857316" + }, + "tests/mvp/test_upkeep_construction_boundaries.gd": { + "bytes": 2324, + "sha256": "266c4f8f240d7508c6c282b08745c1cd813caae384fd46e1ab88f170944ab55e" + }, + "tests/mvp/test_upkeep_construction_boundaries.gd.uid": { + "bytes": 20, + "sha256": "1361112f7ec1bedb8656fe31a0a5cc0bbd181a2cbdc34de4bf024eb3b6274d91" + }, + "tests/mvp/test_upkeep_legacy_midnight.gd": { + "bytes": 6071, + "sha256": "1e4c2f298bf4226b4769bda20328ab1683c4ec8e58afbc2b2b18e329490dd153" + }, + "tests/mvp/test_upkeep_legacy_midnight.gd.uid": { + "bytes": 19, + "sha256": "ec7adb778952c2590aa6ad10ec555269916e4e9730732bbc8e7fe9f025dbdb3f" + }, + "tests/mvp/test_upkeep_loss_streak.gd": { + "bytes": 2865, + "sha256": "b90e6ad96b4a0989b298a62d11c349fcfac53a65cb532f206d8e7ff2223190dc" + }, + "tests/mvp/test_upkeep_loss_streak.gd.uid": { + "bytes": 20, + "sha256": "d3a97e673740b81931f9bf546bf0d6ee98d496d41d50f0f2ae925131e6e59cec" + }, + "tests/mvp/test_whole_tower_outage.gd": { + "bytes": 9695, + "sha256": "dd786e8c7448eeb77d51d7effd9100059ae6febf638ca2c20f3a55683009c9ea" + }, + "tests/mvp/test_whole_tower_outage.gd.uid": { + "bytes": 19, + "sha256": "d54d33c9e4e1f19c848e011d4ebc8f0f6aa54a72be919b5f7dbc4b2bacb43c3b" + }, + "tests/performance/README.md": { + "bytes": 832, + "sha256": "0470e8180c1d2b544cabd94c69fe1e31bc6720a8c5fb641d5a1cec408e437bd6" + }, + "tests/performance/fixtures/linear_path_reference.gd": { + "bytes": 2152, + "sha256": "406b664557e99a8fc9903b9431f708e8e6372c3c56bf1665dd1908485c9bd528" + }, + "tests/performance/fixtures/linear_path_reference.gd.uid": { + "bytes": 20, + "sha256": "db568b490c6e96e513e9f4b176949693578d59d5dd66971bd8650e2507dbe32d" + }, + "tests/performance/fixtures/simulation_digest_v1_reference.gd": { + "bytes": 8031, + "sha256": "64b5c099f8b4ff6e855c80513f150cfdb0e9c6d0f816fd02ec2660d569550928" + }, + "tests/performance/fixtures/simulation_digest_v1_reference.gd.uid": { + "bytes": 20, + "sha256": "d55487d012245ebb1be71247f2512caaf072569d8611df782dbc55d9000eaef2" + }, + "tests/performance/fixtures/uncached_preview_reference.gd": { + "bytes": 2083, + "sha256": "5ba415527f1ecc5cb6d6248ba75014ae91df86d01e7f9c35b8834f378c0c69d1" + }, + "tests/performance/fixtures/uncached_preview_reference.gd.uid": { + "bytes": 19, + "sha256": "dca8700103f3f709ed825af365ed526d147d6896b04e3844e196303dcf363dcf" + }, + "tests/performance/perf_mvp_001_harness.gd": { + "bytes": 38702, + "sha256": "63519cf3723d084fa9c30425e49eb210a54a23fd1987df910621f8d12df9e413" + }, + "tests/performance/perf_mvp_001_harness.gd.uid": { + "bytes": 20, + "sha256": "8069364ba238ee56bd6b722ebcea5e021e463d9a58751bd8e106185d068680bb" + }, + "tests/performance/profile_production_scene.gd": { + "bytes": 6936, + "sha256": "2353f3e42451aaf0b3469deb872ba99ede87efcf3a96b7bf62c7b09bcc8ef67d" + }, + "tests/performance/profile_production_scene.gd.uid": { + "bytes": 20, + "sha256": "e4a435e5f0cb75b07f3ec69eed1872e8ec29b18f8c3d43dd92b034b6319f049c" + }, + "tests/performance/test_digest_performance.gd": { + "bytes": 12490, + "sha256": "363772fc43975f12c9e2056e2b01beb4cd8b2d7544db7528f80c6bd127710c1f" + }, + "tests/performance/test_digest_performance.gd.uid": { + "bytes": 20, + "sha256": "0e2bed5d185228748ba6b616b56ceebc264fa3c35b2c8c5afb2402ca9869a222" + }, + "tests/performance/test_facility_reachability.gd": { + "bytes": 3191, + "sha256": "0b2a39bddc8878ba6190cf4985a543f09039b54840564a9b688f376ea63e96e4" + }, + "tests/performance/test_facility_reachability.gd.uid": { + "bytes": 20, + "sha256": "d52bc87dc72465bba7b762df2efc925638a4ffc8f36df2820d1465117558da6f" + }, + "tests/performance/test_lazy_digest.gd": { + "bytes": 2345, + "sha256": "b1d62d6c83abd514e462ea737baab113c52e76c3b76f7a0672d4a4a119617846" + }, + "tests/performance/test_lazy_digest.gd.uid": { + "bytes": 20, + "sha256": "5a943cf974aec54917085a03461b4da5332c0d34e88551f651e3adb8b8bb43b2" + }, + "tests/performance/test_mvp_manifest_cache.gd": { + "bytes": 12883, + "sha256": "bcf1668f379344447b72483b6923c2eb59a2fdc29237a6cc817a31d3834d2e52" + }, + "tests/performance/test_mvp_manifest_cache.gd.uid": { + "bytes": 20, + "sha256": "80a30061f3ad39a21759c9543ea89ce263e682d001c4531ec5905cffad2944a3" + }, + "tests/performance/test_path_membership.gd": { + "bytes": 1154, + "sha256": "4a0eee95ee39a92eb9f8ec345d46d45f7349e3428454a22bf867b588ecc5bfa6" + }, + "tests/performance/test_path_membership.gd.uid": { + "bytes": 20, + "sha256": "8905b73e45f79910867dc41a1b07da8485bc36d24dc6336e270bebe9b97125bd" + }, + "tests/performance/test_perf_mvp_001.gd": { + "bytes": 2455, + "sha256": "1a4bc20ea4810924e8e64bc5fec1b44fc327f1676200e978a77577d628675e5b" + }, + "tests/performance/test_perf_mvp_001.gd.uid": { + "bytes": 19, + "sha256": "d4f5a7b3092465ce1796b21f700c2b158e68f3eb6eff577e06e64099201efa0c" + }, + "tests/performance/test_snapshot_ownership.gd": { + "bytes": 3341, + "sha256": "96b5d359bf40a8eea2b8acd2e77ce9094b1a4eb70a49a8a9b4ce23a209a7945d" + }, + "tests/performance/test_snapshot_ownership.gd.uid": { + "bytes": 20, + "sha256": "70dcce95041791a79f1a96cf708dc62c237c8e67b04ac1068908db8c5f69e5a8" + }, + "tests/performance/test_system_optimization.gd": { + "bytes": 3403, + "sha256": "374ff4b3ba78b7a724a3620d683db3835fd2a545f1de11606fd4969a3c6ede95" + }, + "tests/performance/test_system_optimization.gd.uid": { + "bytes": 20, + "sha256": "de3ae15ea474f750f3a006aed5e5eba9ab3275456d72c9f7f1c569a5a105c8d5" + }, + "tests/performance/test_world_snapshot_cache.gd": { + "bytes": 2175, + "sha256": "46f25630b30c9cc0f7cddb051a42a0c3edc486f3b81cbfab94d8d2cd0e989935" + }, + "tests/performance/test_world_snapshot_cache.gd.uid": { + "bytes": 20, + "sha256": "8542e90f905da00807df576413467f0495b7d01de6b02d12a496ca02a62dc2fe" + }, + "tests/run_tests.gd": { + "bytes": 2980, + "sha256": "4c8ef388e2349ff975a2af7260da0aa02231a6036ea71b4000f2bb0e6f4083d5" + }, + "tests/run_tests.gd.uid": { + "bytes": 19, + "sha256": "10d91ed020d6a8e18abcdde6c6b85c1e5915a576917d1886daba81dccc9bd6cb" + }, + "tests/s0/test_command_snapshot_key_order.gd": { + "bytes": 8428, + "sha256": "5803a593b0d9dbb35248d79a2d94b5a61668f5bea7687b2cb75366c8b1b33a2b" + }, + "tests/s0/test_command_snapshot_key_order.gd.uid": { + "bytes": 20, + "sha256": "e13b97181e70f07828c64b10570b3cb53b038d54819246be59a25c68627e7e28" + }, + "tests/s0/test_command_transaction.gd": { + "bytes": 13189, + "sha256": "4b6988fd8011b178f03499c368a2417563ba2fc80780e5f0b5ddfce243412522" + }, + "tests/s0/test_command_transaction.gd.uid": { + "bytes": 20, + "sha256": "b213215430d78584694eff8da4a5829407dc8a5107e9e8567481cd2f652f7240" + }, + "tests/s0/test_definition_registry.gd": { + "bytes": 14699, + "sha256": "bf355805e007d99addfb9b963d3566a84602cab40bdb1805ccf3d4e8d851ae17" + }, + "tests/s0/test_definition_registry.gd.uid": { + "bytes": 20, + "sha256": "f4120c70deca131d6053e90c12325719221f85cdaaa62d0e323613480e2fc159" + }, + "tests/s0/test_determinism.gd": { + "bytes": 4896, + "sha256": "a397d2b33a2c8abfae76350d8ee65b967bbc1625186a865dffd776b421cc7520" + }, + "tests/s0/test_determinism.gd.uid": { + "bytes": 19, + "sha256": "58f08c174f50e9405448a11e1d150f2934842b9321d2884244cc37c027d86009" + }, + "tests/s0/test_domain_events.gd": { + "bytes": 7070, + "sha256": "cfb0c5678f9b88ce8594ad06cd122276faa2c7f1287cd204de61c1f777508fbe" + }, + "tests/s0/test_domain_events.gd.uid": { + "bytes": 19, + "sha256": "5036baf806c0d565b733a8d79ab714a4beae8fe0075a205a0b98cd40d9ca1178" + }, + "tests/s0/test_kernel_and_save.gd": { + "bytes": 5988, + "sha256": "6d13f83672f8273ec6ddc47c88de1ce3916f4126af022be8bc562f5dd1d302a7" + }, + "tests/s0/test_kernel_and_save.gd.uid": { + "bytes": 19, + "sha256": "77b866668f5427896a7250a6e80d0b2b127f93dfb13feca0629ea0620d8c5a8a" + }, + "tests/s0/test_runtime_integration.gd": { + "bytes": 7699, + "sha256": "ff13ed6a711e0d8f312c27b5e72a385cf96db75ffe651e17b4c74b1512642a77" + }, + "tests/s0/test_runtime_integration.gd.uid": { + "bytes": 20, + "sha256": "112d151ca9134c8edfeab868eb40c4d2a4d691ca22fcb0ec1ef3e322ec993929" + }, + "tests/s0/test_stable_id_generator.gd": { + "bytes": 1464, + "sha256": "2fac546b4788650b69832b2336d9d46f7b8b343b660d687256d98a64ef4b823c" + }, + "tests/s0/test_stable_id_generator.gd.uid": { + "bytes": 20, + "sha256": "18eee49f41e346611226e97521b751ebb881384b4ebab848b1f2c85289d43c2a" + }, + "tests/s1/test_construction_service.gd": { + "bytes": 34645, + "sha256": "ce63074b84cb75d710eb3650701a9cb2acf920ff607e41be645904fc2395e2c3" + }, + "tests/s1/test_construction_service.gd.uid": { + "bytes": 20, + "sha256": "787ee8a4516613bcb2f4636af3e34b5204413355269b37e8c50f97c42c08f8d7" + }, + "tests/s1/test_dimension_batch_save.gd": { + "bytes": 4896, + "sha256": "ca397c0457996bab637e8be5217b7db2c14579a1b0df54434b4000a69e793bbf" + }, + "tests/s1/test_dimension_batch_save.gd.uid": { + "bytes": 20, + "sha256": "0a228a9ae690e6b2fb33ade627a5a11d1b02a6a3aeeffa2c0fda371e4b9eaa50" + }, + "tests/s1/test_excavation_service.gd": { + "bytes": 15090, + "sha256": "64dacd14dbe0bc94368879daa130e4861ff43cc63fac6bb02e4e64091ee9a750" + }, + "tests/s1/test_excavation_service.gd.uid": { + "bytes": 20, + "sha256": "1125527fb0736715b39c87ddc7dda925a197a90108e8f523d32164ba9e5eff63" + }, + "tests/s1/test_facility_infrastructure_projector.gd": { + "bytes": 38840, + "sha256": "060fc9ab24d123ba91782652e6c9d7ba61c140a5f418854a8a28e07fa0adea8c" + }, + "tests/s1/test_facility_infrastructure_projector.gd.uid": { + "bytes": 20, + "sha256": "9b36d34c508ca890f4952670e378af2f6e95f53021bf81548fe5c6dc1058d2b9" + }, + "tests/s1/test_facility_resize_preview.gd": { + "bytes": 4204, + "sha256": "46339afa52739c6ab626d78ddd298e06f71366ca886954c852549658ff91bc85" + }, + "tests/s1/test_facility_resize_preview.gd.uid": { + "bytes": 20, + "sha256": "dcc10ab40f2c709ee9dfffae6bb30e33a19d6aa2e690b28886190b83d269c71b" + }, + "tests/s1/test_original_facility_dimensions.gd": { + "bytes": 2717, + "sha256": "b56a8bf2bf0d6bea3bb2c45148e60b51de3fd033d1cb997eb71d5ae330a4950b" + }, + "tests/s1/test_original_facility_dimensions.gd.uid": { + "bytes": 20, + "sha256": "57557d6312e56b7cb745d7fc0d1f5348461e3446d266302345a4277c4573ef9c" + }, + "tests/s1/test_p08_combined_migration.gd": { + "bytes": 723, + "sha256": "9284a8cfb478b4c8d69f6d8166eec6c41107e3902029289b3c0e9ba48c370855" + }, + "tests/s1/test_p08_combined_migration.gd.uid": { + "bytes": 21, + "sha256": "8c3a70d0ce619b8cb98dc003eb6c53a31f167a686179a3ffc105f7cd4d856da5" + }, + "tests/s1/test_path_congestion.gd": { + "bytes": 26985, + "sha256": "709bb680f04862fd774644b0b425150977f54346ca76f6223663c414e00f33bd" + }, + "tests/s1/test_path_congestion.gd.uid": { + "bytes": 19, + "sha256": "ee823c0067044415042f5cabb070f714794bdcd295db17a42ce92f83a740bef2" + }, + "tests/s1/test_path_service.gd": { + "bytes": 8577, + "sha256": "17d9fd42b35004376bf96e435f53d6bce41e79258ec7f6daf3ab04ae5d8c3e1d" + }, + "tests/s1/test_path_service.gd.uid": { + "bytes": 20, + "sha256": "9881bc7507d975da2f013574230d554aaae20ac68c801e4cbf4320e1dbe6fe8b" + }, + "tests/s1/test_path_snapshot_transit_guard.gd": { + "bytes": 4922, + "sha256": "1760289e99c80cbc217b98cd96a51fa9b210102340936f89766294e12e394680" + }, + "tests/s1/test_path_snapshot_transit_guard.gd.uid": { + "bytes": 20, + "sha256": "f951d04fb78e074e0e3da4d9220a28f5e7daa470cf1549377cabc5103d0328cb" + }, + "tests/s1/test_route_subslot_path_adapter.gd": { + "bytes": 31308, + "sha256": "a8f712e03776f91899f3311dc3d131d8370faa84032e522092dcc243683487b3" + }, + "tests/s1/test_route_subslot_path_adapter.gd.uid": { + "bytes": 20, + "sha256": "12b6575e3071eb8b9d1ef5bd550413ac43495fb072ac24a796efa77dc800e2e1" + }, + "tests/s1/test_runtime_infrastructure_integration.gd": { + "bytes": 50948, + "sha256": "aaca043097fb31a79e77c77cce1d12e34e5d8630e0ad7337af0d6860f4d45473" + }, + "tests/s1/test_runtime_infrastructure_integration.gd.uid": { + "bytes": 20, + "sha256": "d58219f07c7bc4b15a9525c00599847c8f1cb8e62cbc736ca717ced98369388d" + }, + "tests/s1/test_runtime_world_construction.gd": { + "bytes": 9126, + "sha256": "65924a9b69cd27b5923c5464bd44ab839b26fe39a51b3580e691805d5a9e0e5b" + }, + "tests/s1/test_runtime_world_construction.gd.uid": { + "bytes": 19, + "sha256": "c23784c1ed19734251b4915acb685d3279d57f552ae8395e813f7d741957585f" + }, + "tests/s1/test_spatial_subslot_service.gd": { + "bytes": 18631, + "sha256": "06f4f69438a280ef942bbefdb9caaef1ba59e7dfd0eab71469ca29d090a8ad58" + }, + "tests/s1/test_spatial_subslot_service.gd.uid": { + "bytes": 20, + "sha256": "61f418862ef07477e4f1c4a50e9a99ea4f4fbc15686811fa3015f1d189e986c9" + }, + "tests/s1/test_weighted_resize_runtime.gd": { + "bytes": 18864, + "sha256": "b6d31d5b27b51eae9be36e2b0195e78f5e3f1105af01660b0c5cf13cd233baff" + }, + "tests/s1/test_weighted_resize_runtime.gd.uid": { + "bytes": 20, + "sha256": "89c7821bdda5c7872dfdf12e79057a693db5a8c353c412489743531eaf6c3b6b" + }, + "tests/s1/test_world_service.gd": { + "bytes": 9888, + "sha256": "a5e165886f161b8bc71722ac7facdd17704bc6274c88dfe7fd2229f7f2b3f2b7" + }, + "tests/s1/test_world_service.gd.uid": { + "bytes": 19, + "sha256": "1f3b779a91f50397c8842bda2216b8407cfdda5f242b9ee8bddd39b59f52b645" + }, + "tests/s2/test_economy_service.gd": { + "bytes": 9705, + "sha256": "cfe6196c0da9e39d95ae0e39f0c5404e321f4fa8be3602b58d4bf6cd3fef3969" + }, + "tests/s2/test_economy_service.gd.uid": { + "bytes": 20, + "sha256": "e122b7a55c02e012909c60982facabca27028712e8d987db39f0e78ef252d1c8" + }, + "tests/s2/test_facility_pricing.gd": { + "bytes": 14561, + "sha256": "def0541f123307bd77a898c698292fa881d269788bf17dcd40b546673f10d4d5" + }, + "tests/s2/test_facility_pricing.gd.uid": { + "bytes": 20, + "sha256": "7d3db28d38b93c14b6e85c219a974a71d590a6bac2be692457524904910ace58" + }, + "tests/s2/test_facility_service.gd": { + "bytes": 17403, + "sha256": "4b834f1d9d9ab2ad00cb4a56f5202b70468bfe5f71318dbf816da1e29cc32690" + }, + "tests/s2/test_facility_service.gd.uid": { + "bytes": 20, + "sha256": "bd81957c4ebf75e4fc2e1632f6cfbe5d1b33b7c2b5e5b86eee399dad062dacb5" + }, + "tests/s2/test_facility_upkeep_accrual.gd": { + "bytes": 5260, + "sha256": "2985f565a3e39605965112a2bc17688315e3c0d527dd283913f9416ff0cf0ef3" + }, + "tests/s2/test_facility_upkeep_accrual.gd.uid": { + "bytes": 20, + "sha256": "548684a8f9d2d997eac51606e2be832690b7eb02b57cdb938ed55bf6d28ed4a0" + }, + "tests/s2/test_facility_upkeep_settlement.gd": { + "bytes": 8019, + "sha256": "5a9666e8e044dbe803c33b41cc7cbb344796703665fa9f7b7a7b465020ec9aa9" + }, + "tests/s2/test_facility_upkeep_settlement.gd.uid": { + "bytes": 20, + "sha256": "2a4b395ba551f16316fd26348acbfec66fcb7e9d1dd822cac7477702b4296f86" + }, + "tests/s2/test_inventory_logistics.gd": { + "bytes": 25762, + "sha256": "ef8b87e721f57210da02b8cd0822f58e1a4c1cdaa19fe56301a03a87891e73d6" + }, + "tests/s2/test_inventory_logistics.gd.uid": { + "bytes": 20, + "sha256": "3ffc72051c94edbd162656b32b9909b807aa266b517172d249a115fe2d24b3e0" + }, + "tests/s2/test_kitchen_production.gd": { + "bytes": 21134, + "sha256": "e2aeb1fdbc8d1dfe9400646693a0e97919b3b86cb74a4f000ebeba01bfbee626" + }, + "tests/s2/test_kitchen_production.gd.uid": { + "bytes": 20, + "sha256": "ee6e5a1b0303d6771585c6f3a565e3d86b00a116f8045e7b7caa3325462f58a8" + }, + "tests/s2/test_ledger_backed_resources.gd": { + "bytes": 3356, + "sha256": "26c2c9b883ee1448345d5555ac3e97293c3bf273b42668c11a6bdc23e1184dd3" + }, + "tests/s2/test_ledger_backed_resources.gd.uid": { + "bytes": 20, + "sha256": "139b127207bfc1e847d46bbfa2fd7a918402f942396ab3e5d672be0ee524fbf0" + }, + "tests/s2/test_mana_network_service.gd": { + "bytes": 7192, + "sha256": "b0a21ea663667979c109cf6fd2efff717c284398071948c897b9e99090ce12fc" + }, + "tests/s2/test_mana_network_service.gd.uid": { + "bytes": 20, + "sha256": "6903dc207dd6d28fb6fa71241baf352ca7508eee355fb7b485f9655500969321" + }, + "tests/s2/test_mana_power_projection.gd": { + "bytes": 2976, + "sha256": "e3020534b084b57a8b773967931fd2be34a1de878b4940c8805b99592bbbc46f" + }, + "tests/s2/test_mana_power_projection.gd.uid": { + "bytes": 20, + "sha256": "1283e11ed69d81724764e97d3dd22af4ca7fd8ff33b22e703060fc438ff8c433" + }, + "tests/s2/test_mana_recovery_new_pid.gd": { + "bytes": 6491, + "sha256": "8ef67859db2a31213585fa49dfc687ea69bf215c41c8d1d8cbb3f84d00dd5d17" + }, + "tests/s2/test_mana_recovery_new_pid.gd.uid": { + "bytes": 20, + "sha256": "a0e872cd4958f2a8c86d0dfdb7c276ca6050a721699e74495dac4ed3ffcc8c1b" + }, + "tests/s2/test_mana_reserve_balance.gd": { + "bytes": 3802, + "sha256": "07fe5f10e665cac3c8aa1b12e0c71878ffccc6d4b409250b317135345e3c8a05" + }, + "tests/s2/test_mana_reserve_balance.gd.uid": { + "bytes": 20, + "sha256": "f13ac2a1a1e3646fadbf0d5507d9bec74809c29ffa9aaa47bfa5d81369575701" + }, + "tests/s2/test_mana_reserve_cycle.gd": { + "bytes": 3897, + "sha256": "048d79e067cc85eef1c5c5f3e412198e652a2acc08e6d910e0761c7148a34cb6" + }, + "tests/s2/test_mana_reserve_cycle.gd.uid": { + "bytes": 20, + "sha256": "2946d84694634500b2578b2bbef264c0d0ec01629e4d491d4912c5cf59e1a069" + }, + "tests/s2/test_mana_reserve_new_pid.gd": { + "bytes": 4665, + "sha256": "9f42e4f7f5aac403ee4a6091e54ebf3995e25d11a450000e5a8ce870094f7a6b" + }, + "tests/s2/test_mana_reserve_new_pid.gd.uid": { + "bytes": 20, + "sha256": "d87ba2b9f191ec6cd2011bcfde91d561c3b6c1f7f06602a2668fdc46d8d243d0" + }, + "tests/s2/test_new_pid_pairs.gd": { + "bytes": 2921, + "sha256": "9742f9ac253067e6ae69a53faed054d71925f316d038ff7c5e480c3a9be91b04" + }, + "tests/s2/test_new_pid_pairs.gd.uid": { + "bytes": 20, + "sha256": "7c50b14981a479045dd507d8776cb7cead2af696ea3e7040a5d9301a7d66a009" + }, + "tests/s2/test_original_facility_parameters.gd": { + "bytes": 4811, + "sha256": "3d5cc5f13f986f8cea9500a7f8d48d8f5803b8d0bee5eb0e7c44b3218a2e3d7b" + }, + "tests/s2/test_original_facility_parameters.gd.uid": { + "bytes": 20, + "sha256": "767f5577d0c684e2edf174264baf89ce20117e22ed3f94275bede3a35b6ff6a9" + }, + "tests/s2/test_runtime_mana_reserve.gd": { + "bytes": 7046, + "sha256": "323750a533f2bbdf95b96b1615996cd3c4155bdadc6dcfb0936eaaa19a04809b" + }, + "tests/s2/test_runtime_mana_reserve.gd.uid": { + "bytes": 20, + "sha256": "7b8344045fbf38ba739ebcca64893d8e6de4a5a81e27bd7a30eb34091d5a2ab2" + }, + "tests/s2/test_runtime_operations_cycle.gd": { + "bytes": 14104, + "sha256": "9ec6fb682e258460b3e91870fe4690f780e1053b7fa2dcf753d31bbc8107ce35" + }, + "tests/s2/test_runtime_operations_cycle.gd.uid": { + "bytes": 20, + "sha256": "76b497460484dca1babe2b911dc75e8ffbde8dabea5ac63693d07678de51ff59" + }, + "tests/s2/test_service_start_slots.gd": { + "bytes": 2778, + "sha256": "286786b9a7c2c86b8fc7ce808abd84dae05f2eccf7e2b3faa3780746ce4e2133" + }, + "tests/s2/test_service_start_slots.gd.uid": { + "bytes": 20, + "sha256": "cb26127ca17e5dad63db2f3e64cb64a74e5bb4e003a47cc6425cf68875be9881" + }, + "tests/s3/test_guest_observation_restore_order.gd": { + "bytes": 6307, + "sha256": "7abf5692a07edf8270fa9bf4d9ee89a3835741c208c4c670dc605158532284f2" + }, + "tests/s3/test_guest_observation_restore_order.gd.uid": { + "bytes": 19, + "sha256": "eb3243a324c9b563d7de81ccae96b14dee46a41e63bb578a408d709ea18d8371" + }, + "tests/s3/test_guest_service.gd": { + "bytes": 40444, + "sha256": "a104012f9e2001ae6adf76aaa935ea6cb84545f35f412e1d96d4e03209488cd9" + }, + "tests/s3/test_guest_service.gd.uid": { + "bytes": 20, + "sha256": "957b6e3829ac24c9e937642ae42d78dc76d280e029c00e900dfdf46864935301" + }, + "tests/s3/test_runtime_actor_cycle.gd": { + "bytes": 11320, + "sha256": "955cca90ee1be985e37ef166eaedb5c49f7001993afa38011fe3bf20ddb4a9b3" + }, + "tests/s3/test_runtime_actor_cycle.gd.uid": { + "bytes": 19, + "sha256": "bb64dfa2e2d790afe31d48b00eda2e7f3f98ed5ccca5b7de3d497851a70a5155" + }, + "tests/s3/test_runtime_actor_hardening.gd": { + "bytes": 19229, + "sha256": "0deb2df7be31d90a7fe70b98fe420eb748e19ab19c1cc37140f74cf0acd3fa95" + }, + "tests/s3/test_runtime_actor_hardening.gd.uid": { + "bytes": 20, + "sha256": "69a68a20dc23ad619233b9c9a8e361cc38cbebe558e2eb5ebffb4b04a43adb16" + }, + "tests/s3/test_runtime_path_traffic.gd": { + "bytes": 28077, + "sha256": "92cdada10177363ac5ebae6435d0b4c6f0c7d96e6ccc2d0731487bf4f2cdceeb" + }, + "tests/s3/test_runtime_path_traffic.gd.uid": { + "bytes": 20, + "sha256": "a04adc621877e25279334e15c7f0adffddcafaa89b9bf5f6b5e4ed8f3dfc72fc" + }, + "tests/s3/test_runtime_staff_assignment.gd": { + "bytes": 19699, + "sha256": "f6004ab1601e2910268dd5d02923c32eb697fb587ad74da1f06ca4de6c21713c" + }, + "tests/s3/test_runtime_staff_assignment.gd.uid": { + "bytes": 20, + "sha256": "15798981b417c1a93d69b8cb3ef2b4c32d2b1856d69d5603abf0bbe4b01bb8e1" + }, + "tests/s3/test_staff_payroll_operations.gd": { + "bytes": 16639, + "sha256": "05c817b7e891ac1649072ad33102561e26280b9bdd34f6f3831c7da055044f8c" + }, + "tests/s3/test_staff_payroll_operations.gd.uid": { + "bytes": 20, + "sha256": "f37cb11e7e2e140852296265fee8660e25de38512b4ef4364f997a660dad26d5" + }, + "tests/s3/test_staff_service.gd": { + "bytes": 47146, + "sha256": "82e9a5de3247251ac29b52aa524fffeb4e63a62a9ab587d62004c268a0180481" + }, + "tests/s3/test_staff_service.gd.uid": { + "bytes": 20, + "sha256": "9f11cd43495a73be6cad902b6bf2c98dd34f59b2a7c47193e80cdf6f3abc1ff3" + }, + "tests/s4/test_original_relationship_model.gd": { + "bytes": 8408, + "sha256": "c74b243dbbb54dba9bbc165e29508cca910f0beb63e32d25ebbb8ea606dccce9" + }, + "tests/s4/test_original_relationship_model.gd.uid": { + "bytes": 20, + "sha256": "d7859fa9a503001cea97861d7893017531748c7880d70483339528a9f72e2c4d" + }, + "tests/s4/test_original_relationship_runtime.gd": { + "bytes": 195513, + "sha256": "c56bdb99dd43a4e7ceb3ca2861e8db39972c5c4e805126a77e2f7da32ca5bdc9" + }, + "tests/s4/test_original_relationship_runtime.gd.uid": { + "bytes": 20, + "sha256": "67a5aad38d18bb95da0080579e93984d2172d1522de139a07640ceeff45ec52c" + }, + "tests/s4/test_placement_risk_preview_service.gd": { + "bytes": 23839, + "sha256": "165eddf9a5c51d8d9eeb85ea89e21b1ab6067b7ee057ee0fe5b189e97a71c1ad" + }, + "tests/s4/test_placement_risk_preview_service.gd.uid": { + "bytes": 20, + "sha256": "71a98084c28c551fade45679d26ca630bfdf5fd654cb9a51841dc8c94500dff6" + }, + "tests/s4/test_relationship_event_service.gd": { + "bytes": 32069, + "sha256": "ce1aa05716feed435cb68a1435a28db219cc3f056e23a442d2eaf08840771ffe" + }, + "tests/s4/test_relationship_event_service.gd.uid": { + "bytes": 19, + "sha256": "84accc609266af2e47e6c9815fd698022a569290fd36565b4f02b2bb80415957" + }, + "tests/s4/test_runtime_relationship_events.gd": { + "bytes": 33566, + "sha256": "466f9a40b3471a9bb39c670cdd1106e990d297bc8bfff0db557cd63bb74c8ef3" + }, + "tests/s4/test_runtime_relationship_events.gd.uid": { + "bytes": 20, + "sha256": "c2b710659ad613bbffb82edf8e2acafb84c5f45dc29b795ec62e7b7d32adced9" + }, + "tests/s5/test_authority_service.gd": { + "bytes": 19665, + "sha256": "983ac275dc4f40f7c8058831b7239f1f4b4e2b3f12da0bbb6ea5e8ad69afe2c5" + }, + "tests/s5/test_authority_service.gd.uid": { + "bytes": 20, + "sha256": "a5acf875917519474ccf333f7507fbd5082a64f7349501e34fdbd11585f71844" + }, + "tests/s5/test_defense_service.gd": { + "bytes": 75277, + "sha256": "6e97ace03c46091775afb5a772adc32a7add8146f36c3492e99f4ae30f6ea62b" + }, + "tests/s5/test_defense_service.gd.uid": { + "bytes": 20, + "sha256": "74cdf1e1f1332968ca0e7353593bd432c0ccf89ed05feaa158fb7025cf85868d" + }, + "tests/s5/test_runtime_authority_cycle.gd": { + "bytes": 18979, + "sha256": "33952b6253c77410c7997ddbf37e039f79bcc0ae283da76c3580ec166f928273" + }, + "tests/s5/test_runtime_authority_cycle.gd.uid": { + "bytes": 20, + "sha256": "0fbc9c9e5af8e8053455910a93a0998517cf14a50c527188e1cc394e6b367d50" + }, + "tests/s5/test_runtime_defense_autonomy.gd": { + "bytes": 28099, + "sha256": "edd762fb8698c14d2fc00175257da8708571b523213f16e6267ea9f0c8516c2a" + }, + "tests/s5/test_runtime_defense_autonomy.gd.uid": { + "bytes": 19, + "sha256": "42699094e7eed0f52e1e9c0f10c704c156b1ce225a07216696f6f8a30d6e6f8e" + }, + "tests/s5/test_runtime_defense_cycle.gd": { + "bytes": 44418, + "sha256": "a909e2af73aae43590cdd91d07ed2548f4fd2f675d26fa63aa74f6a5cda34357" + }, + "tests/s5/test_runtime_defense_cycle.gd.uid": { + "bytes": 20, + "sha256": "92cca037cee29755b83a9ef5bc7fa0eef0023b4707a780fe74b84fb196d0d45a" + }, + "tests/s5/test_runtime_event_defense.gd": { + "bytes": 27836, + "sha256": "09bd125d85714ed69f7b35b900507136a099375a10ebb1dae0ab55886387b046" + }, + "tests/s5/test_runtime_event_defense.gd.uid": { + "bytes": 20, + "sha256": "4e9d46f36dcc05047c9ea55926cb6f4a745dc876ca7e2fcaf0d230c4ffd993f2" + }, + "tests/s6/test_performance_budget.gd": { + "bytes": 3968, + "sha256": "1ae5490637d73b519bf9ed0e00bda0e034d5ea0e589493bcf8886e4d1ff63689" + }, + "tests/s6/test_performance_budget.gd.uid": { + "bytes": 20, + "sha256": "b72aece72fe55c65f763c36e146d8043c818c6e1d6afca72c14defcd1f0c4f01" + }, + "tests/s6/test_runtime_save_lifecycle.gd": { + "bytes": 30502, + "sha256": "de94d588d6ce204aa8d0221c2989b8dd900cf4e36ca51f83b464518a382a887f" + }, + "tests/s6/test_runtime_save_lifecycle.gd.uid": { + "bytes": 20, + "sha256": "304d45fa600b3381dabb3deec6143d5557e9c33c75782f4e672c3258e292c35a" + }, + "tests/s6/test_runtime_snapshot_serialization.gd": { + "bytes": 6753, + "sha256": "d9106f9defb6cc195b969ff040d24f1f8ceebe055ba66c39d4634a68620cde84" + }, + "tests/s6/test_runtime_snapshot_serialization.gd.uid": { + "bytes": 20, + "sha256": "462d7cd44e93ba1aecd2ef469b155e8ccdf305880901fcf52b3bfd5faf40a35b" + }, + "tests/s6/test_save_operations.gd": { + "bytes": 42183, + "sha256": "8e30183d45767d2b1f99c8c714e798241e0b6615c907d0baa5e148ca94667eff" + }, + "tests/s6/test_save_operations.gd.uid": { + "bytes": 20, + "sha256": "528bce673007a2d1ee87fc5d9ead3277862491403d1bb676ba9bd98eb8d933a7" + }, + "tests/s6/test_save_preflight.gd": { + "bytes": 13404, + "sha256": "49e24247649839b6f50d19b2284368efb7f8f8b189c5010491ad428e97c1c8b9" + }, + "tests/s6/test_save_preflight.gd.uid": { + "bytes": 20, + "sha256": "f3acef6b5fc18b83e13bd123de1dd830e0a3b132d27dae4e28c79c2902040665" + }, + "tests/s6/test_save_recovery_preservation.gd": { + "bytes": 9487, + "sha256": "0fc0f75e06d4371f049dc4692e9ab0d871016b633e5ac4693661a33a7390641e" + }, + "tests/s6/test_save_recovery_preservation.gd.uid": { + "bytes": 20, + "sha256": "d000277bcbded1cabe95509489284b8788da0813fead1076e0e970ce55eeabc5" + }, + "tests/special/peeping_room_fixture.gd": { + "bytes": 2861, + "sha256": "0243b1d35e1fdd8aa085894a0ce1e5cd1a189e5c98fcb859f81b70ae75b98bed" + }, + "tests/special/peeping_room_fixture.gd.uid": { + "bytes": 20, + "sha256": "a74e5ef6d8959826919a648e8b5d82e96d1c73ff22cd6c1f216be8b5c4060a8a" + }, + "tests/special/test_p13_uid_policy.py": { + "bytes": 3871, + "sha256": "d977b63ffa0672994545084c530628a930a905b9aff40a815023637047f61886" + }, + "tests/special/test_peeping_room_evidence.gd": { + "bytes": 3287, + "sha256": "390e0032d14de9a8875ced163a922341ce655744200d78b4ffa776d42c4f8c2a" + }, + "tests/special/test_peeping_room_evidence.gd.uid": { + "bytes": 20, + "sha256": "26bbc1435bcda963b5866327b887096f798b1629c7984768c85bfb6175648ec5" + }, + "tests/special/test_peeping_room_geometry.gd": { + "bytes": 4872, + "sha256": "103d85f83e1e97a8637892504264275eef23f172eeec56c94e5c022d81bf6945" + }, + "tests/special/test_peeping_room_geometry.gd.uid": { + "bytes": 19, + "sha256": "391b78806bc0bf759f00c778cb25dfaa97d47f6e309c3b302412c38123c5440c" + }, + "tests/special/test_peeping_room_reference.gd": { + "bytes": 3385, + "sha256": "188b00a60f7aefda69dc4973f1de9c14447a0d4bcdd1257a2eabe7c4782e4caf" + }, + "tests/special/test_peeping_room_reference.gd.uid": { + "bytes": 20, + "sha256": "db8bfa98b7943dba15858ccaa6681bc430efd43f40f57de99117dc19c51ac417" + }, + "tests/special/test_peeping_room_runtime.gd": { + "bytes": 7809, + "sha256": "924efd34414c12a325a1b700f799aef0396de9f15441fd88a3608292ff221657" + }, + "tests/special/test_peeping_room_runtime.gd.uid": { + "bytes": 19, + "sha256": "b742bb8e4077f111e0f7b4d9039261a06fe6deaad8ea308ba3b89c7b5a4a9069" + }, + "tests/special/test_peeping_room_save.gd": { + "bytes": 4452, + "sha256": "ba0e7644277477c1821135cae6d6fd533651799c6f9bd8c43ccf45e63b96c63c" + }, + "tests/special/test_peeping_room_save.gd.uid": { + "bytes": 19, + "sha256": "005561b37df9051e618d4714b2a91a82f4a48ec63c841cdf27c251bcd2865505" + }, + "tests/staff/test_dormitory_dimension_migration.gd": { + "bytes": 6459, + "sha256": "90737c91005975601f400fe88c9a474d10713639b73d8e1354f99bc52e812a49" + }, + "tests/staff/test_dormitory_dimension_migration.gd.uid": { + "bytes": 20, + "sha256": "d4714e6a5bd19d618dd019cf5d388775b2b6b116a0e401c332ce2bfe5a0bf12e" + }, + "tests/staff/test_dormitory_shift_cycle.gd": { + "bytes": 3857, + "sha256": "ada3c0177f00648137d02450fce5f33da0a644dae9ec861ac51648770dafebda" + }, + "tests/staff/test_dormitory_shift_cycle.gd.uid": { + "bytes": 19, + "sha256": "d7db4db3cce31dea2ddf0d80379270011908a37f30b78f5168c13b379cc6b9b3" + }, + "tests/staff/test_rescue_elevator.gd": { + "bytes": 6910, + "sha256": "251199b0dbd6eee66bd123c42fb604177dc38e9f6efa584be6ce53e8fe28d139" + }, + "tests/staff/test_rescue_elevator.gd.uid": { + "bytes": 20, + "sha256": "c26b5d6bc7a9dbea52105f22beaaafd224449827a36a7685503726ede9dfb1eb" + }, + "tests/staff/test_shift_rush.gd": { + "bytes": 3668, + "sha256": "af3d47d848c1220741992612e57736df4af05969d424b79829d9977c774e8149" + }, + "tests/staff/test_shift_rush.gd.uid": { + "bytes": 20, + "sha256": "d925bac6ee92c077476a605602404ad91cc50a151ed5e834242021579c657472" + }, + "tests/staff/test_staff_commute.gd": { + "bytes": 20046, + "sha256": "0837c92a49f8f83c03ca820eaeb23f7b1dfbc1072f8eeffcb557bb6b57b20c49" + }, + "tests/staff/test_staff_commute.gd.uid": { + "bytes": 20, + "sha256": "762cfd6f56de0d63ea0fbcdfa940071cf529ae8626edfec11f94ef123ffa01e1" + }, + "tests/staff/test_staff_dormitory.gd": { + "bytes": 4123, + "sha256": "1b908ed1bb94f7bff325faa98f8cfc658a46fa027bd3ebbfe60450aae35ade7f" + }, + "tests/staff/test_staff_dormitory.gd.uid": { + "bytes": 20, + "sha256": "ec05e96d8e990bcb2b113c0016bb864578ebcad245226bd65dc1d6b2ef26918c" + }, + "tests/staff/test_staff_rescue.gd": { + "bytes": 11393, + "sha256": "8d8c02444c35b2c41c6db42ac0195dd614835541235cd92641ca9b220f59c44c" + }, + "tests/staff/test_staff_rescue.gd.uid": { + "bytes": 20, + "sha256": "4cc93ef832c112e151df49180f3272e89b84ad121e3c02a91da71018583cf03b" + }, + "tests/staff/test_staff_rest.gd": { + "bytes": 3467, + "sha256": "fe9b9d2a8a9051850980a393b8c06b8be41de8a82d5efc998c69df3a06cf54ec" + }, + "tests/staff/test_staff_rest.gd.uid": { + "bytes": 20, + "sha256": "18a8cc751651c8d28016bd476857830de26a17c810fffac24d6885bc0930fdba" + }, + "tests/staff/test_task_work_clock.gd": { + "bytes": 2024, + "sha256": "b131fbe922e744c2075338638e3a01811618e93ae786df3ee435318048d24f9b" + }, + "tests/staff/test_task_work_clock.gd.uid": { + "bytes": 20, + "sha256": "0d976cde371fdc353bbaac33a2849737c506897c586ed1080d5ae2eb939d631f" + }, + "tests/supply/test_mimi_purchase_quote.gd": { + "bytes": 34683, + "sha256": "01f7760cf0fed33fda6358bd407fc1441a198dce9f2713e49bfcc097ee8c8ada" + }, + "tests/supply/test_mimi_purchase_quote.gd.uid": { + "bytes": 20, + "sha256": "2da07e7c142df4e2bf8321d24c6cd0be0221192bc9a3cadf4a36656045af1bb3" + }, + "tests/supply/test_normal_auto_purchase_chain.gd": { + "bytes": 15542, + "sha256": "6916d644620c49a09ab110d98fe07477bb5bb9f96da3826a0be962610cc55256" + }, + "tests/supply/test_normal_auto_purchase_chain.gd.uid": { + "bytes": 20, + "sha256": "bda094662ec9a99c086adb8badcecc68f4428e3ec0e7bbe685f9fae9f7eaccae" + }, + "tests/supply/test_normal_supply_chain.gd": { + "bytes": 12352, + "sha256": "eedbb301e68285bbd6f701cf7eec15537f116944115807e0d9133a4c2970bb1d" + }, + "tests/supply/test_normal_supply_chain.gd.uid": { + "bytes": 20, + "sha256": "d1530167a99e980ea74d7137995507971863bf913fd0b5ade70798321cc6c2b0" + }, + "tests/supply/test_supply_auto_purchase.gd": { + "bytes": 32386, + "sha256": "2551b145d583e1b63b0731290ef097603aae302347ea306770f53f750237ddfe" + }, + "tests/supply/test_supply_auto_purchase.gd.uid": { + "bytes": 20, + "sha256": "49582fe0b7c89de43215ea7dfe73b7c030e4628196d45a0b73e7b4dfb1c96a2a" + }, + "tests/supply/test_supply_auto_purchase_boundaries.gd": { + "bytes": 21259, + "sha256": "cc1a9e8fda5fc25f9fcfb391463a05957fd2ec649ae50acf2b219c3c9efaa970" + }, + "tests/supply/test_supply_auto_purchase_boundaries.gd.uid": { + "bytes": 19, + "sha256": "aa95f49a911d97ce014351358f306607ea31439f155d9a61ba9b2bf7d596447f" + }, + "tests/supply/test_supply_auto_purchase_destruction.gd": { + "bytes": 19855, + "sha256": "229c24e67bc6e59146f91e9ae111794ad39a4d9245c84aa8731b65c43c33a6f5" + }, + "tests/supply/test_supply_auto_purchase_destruction.gd.uid": { + "bytes": 20, + "sha256": "6f540665e982fba973e7372f9c37a8d61aa3fd649f2691da8b0221d60ffd927a" + }, + "tests/supply/test_supply_logistics_bridge.gd": { + "bytes": 27437, + "sha256": "c9e4d8a82b57d1cf23a8a24c24dbcf3fdbc7e516d654ab3b59850d20ef7df678" + }, + "tests/supply/test_supply_logistics_bridge.gd.uid": { + "bytes": 20, + "sha256": "015240a8e659c741f564316c0431e5d00658ef6fee604182c9cdb9aac150615f" + }, + "tests/supply/test_supply_management_service.gd": { + "bytes": 19542, + "sha256": "9b60643a827daf314f807cdc7105f227414a906e32481175451ceddd0b00eb95" + }, + "tests/supply/test_supply_management_service.gd.uid": { + "bytes": 20, + "sha256": "a1e92c9f8e6a7163dd911655340df4244ffcb8ccb94da1377fe00828e8c74526" + }, + "tests/supply/test_supply_save_migration.gd": { + "bytes": 6390, + "sha256": "a281937594be9f177103e83d0cba48d54f2d69c7303c937d0303b5f8c787f0ae" + }, + "tests/supply/test_supply_save_migration.gd.uid": { + "bytes": 19, + "sha256": "6254a4b8d366705088232cd401dde3a800c6e56b4413128c16583f42612e63a4" + }, + "tests/tmp_operations_ui_diag.gd.uid": { + "bytes": 20, + "sha256": "ce992ccde96ec0a2413e7f9cb398caa33d54cfe1357c60d96792dc0952a25cd8" + }, + "tests/transport/test_elevator_service.gd": { + "bytes": 18936, + "sha256": "e70de48a8e6f7928690d0495110451c26d9dec180c2dd7033c793155f099c2f6" + }, + "tests/transport/test_elevator_service.gd.uid": { + "bytes": 19, + "sha256": "925d6db7b36cc86e972d5a1dad494f974b406bb4d63d48621a8075c1cca88dd5" + }, + "tests/transport/test_route_wait_choice.gd": { + "bytes": 21252, + "sha256": "c4db1db2e60f1a24fbbcb6c2c3706a7ee1534c7191f612e1d8df40d0a39a97bc" + }, + "tests/transport/test_route_wait_choice.gd.uid": { + "bytes": 20, + "sha256": "2c5ab55c8f4640e0b48c6ca0e25e64127032c9568c5f7fd8f37f2fadb4011684" + }, + "tests/transport/test_runtime_build_preview.gd": { + "bytes": 8937, + "sha256": "c881b60bce7276047884303a6823da9abfaaf8c1e85dbc5f2c0ff13f0d742449" + }, + "tests/transport/test_runtime_build_preview.gd.uid": { + "bytes": 20, + "sha256": "57e136776f75f7ef7b1554f532f7a72e37dd8e70c42c2dacd91117e1d1f5bb96" + }, + "tests/transport/test_runtime_stairs.gd": { + "bytes": 11601, + "sha256": "31c90714be9b47a2935a13a896e41be9413a34fbb7a4f8677b2b7c2defa8b3d5" + }, + "tests/transport/test_runtime_stairs.gd.uid": { + "bytes": 20, + "sha256": "acac5181699895e51b2c1ddc56400d02c593ff135f087cae660c442e3f9b8274" + }, + "tests/transport/test_runtime_transport.gd": { + "bytes": 12138, + "sha256": "78a5563ff2421ae65a0988cf0d26669f54bcc0f44250b00e5334cadf1228da94" + }, + "tests/transport/test_runtime_transport.gd.uid": { + "bytes": 20, + "sha256": "a0ce72d7126ce1483e2c2b0a1a3c8e2a78ad5f6444d58e3c26d48962b82b10a4" + }, + "tests/transport/test_runtime_transport_comparison.gd": { + "bytes": 20053, + "sha256": "ba577397fa8db5a6cf92cfd398dd7a5ece49e6b59856f14772b67b51ddc0bde9" + }, + "tests/transport/test_runtime_transport_comparison.gd.uid": { + "bytes": 20, + "sha256": "534e9fa0d9af9987fbd33dbe9b2cd96a9e66947af56381e5668e1e7347ebf9f1" + }, + "tests/transport/test_runtime_warp.gd": { + "bytes": 11031, + "sha256": "cfbb69e63aca12d9d198393fd853c76be63df95e8d1e777e7a14194dbd181234" + }, + "tests/transport/test_runtime_warp.gd.uid": { + "bytes": 19, + "sha256": "be36cff26daeff957d0a5fa2b6d57a3281d88fefe74f13c87140967c26edc102" + }, + "tests/transport/test_transport_boundaries.gd": { + "bytes": 12381, + "sha256": "1a5a647c45ffab674a8f58b8bc72692c5a30090c9b99a1e6f67194bbe3586b34" + }, + "tests/transport/test_transport_boundaries.gd.uid": { + "bytes": 20, + "sha256": "d2d527ec3c053bfcb5e6102250a69da3b07e6849afb8e7fd313ae2ed8e16b03e" + }, + "tests/transport/test_transport_comparison.gd": { + "bytes": 14603, + "sha256": "7e80e9ef80500278c56f0d1ada5c911f43e3c0a9bc370045fdbebd33c2f02fd5" + }, + "tests/transport/test_transport_comparison.gd.uid": { + "bytes": 20, + "sha256": "55c77e010e78ecb7a5f743181e8f19d3aa2561b2187067c5060d2d3c023db88b" + }, + "tests/transport/test_transport_density_migration.gd": { + "bytes": 10833, + "sha256": "0860fdd20576ad2044d44a99d8533393bf95f4b4c69997cc50f2391299343f54" + }, + "tests/transport/test_transport_density_migration.gd.uid": { + "bytes": 20, + "sha256": "4689911193eef3dc361eeb818fc6551913eacbf75ab47c683972b89753c85e7c" + }, + "tests/transport/test_transport_save.gd": { + "bytes": 9863, + "sha256": "d4b41a71f2ddc43b1beb14ba8548541ce4875b6640815440e0c14a183c8ddfea" + }, + "tests/transport/test_transport_save.gd.uid": { + "bytes": 20, + "sha256": "9737d562787488b6d12e0c7919335518c5763c111a54fd747b92725c9d3aea37" + }, + "tests/ui/capture_main_dashboard.gd": { + "bytes": 2040, + "sha256": "dcaeb97ef2f8a5910d2e8b5eb8aa7f6bf5a5a4d9128e0afab3e14eb16100117c" + }, + "tests/ui/capture_main_dashboard.gd.uid": { + "bytes": 20, + "sha256": "4bd0c992d10d4a32cdcb9d73be8b6cb196275e48a5c2832fc9f1f47e5b2c912b" + }, + "tests/ui/capture_pixel_tower.gd": { + "bytes": 8327, + "sha256": "c06bc1ece7f9e60f42c80fe406f85b9083dc9bce7a7ab7d0fa07d93f79221bc7" + }, + "tests/ui/capture_pixel_tower.gd.uid": { + "bytes": 20, + "sha256": "27e4fd1133379ce6581c479685b63744bcb37ae557e7210c59ffccd4306e88bf" + }, + "tests/ui/fixtures/counted_dashboard.gd": { + "bytes": 162, + "sha256": "102bec9e27bf8d815edeaab359fcc8ceb9ea1be8ff2e764252efc38dfca1976d" + }, + "tests/ui/fixtures/counted_dashboard.gd.uid": { + "bytes": 19, + "sha256": "d0165467fbc1e9e83179a5bd6c74a8b63da49ba2ab1e4198f9cde112a7a41ed6" + }, + "tests/ui/fixtures/opening_restart_flow.gd": { + "bytes": 6413, + "sha256": "dc13245c07beec03504e6370287cbb36e99de37e2a4217fab78ed866eb3f9c71" + }, + "tests/ui/fixtures/opening_restart_flow.gd.uid": { + "bytes": 20, + "sha256": "bd91a00f4a8955c1223c7ddc5f2d36f07db8d53c6b0af882b59a87fedc78b0a4" + }, + "tests/ui/fixtures/selection_cross_process.gd": { + "bytes": 4494, + "sha256": "30667d0f21a061742eca91806d5b4efbec985a1a93b23ef1a19487431531c11f" + }, + "tests/ui/fixtures/selection_cross_process.gd.uid": { + "bytes": 19, + "sha256": "a7c06239b06aa9ac6a377ee7865c7f34e04cd7bf1f7a3560b0d8a259fbb79070" + }, + "tests/ui/test_actor_selection.gd": { + "bytes": 12477, + "sha256": "f37a0f4805adce4b538fccde1404c1a417f20639fddf36947f076d88409ba0a3" + }, + "tests/ui/test_actor_selection.gd.uid": { + "bytes": 20, + "sha256": "2d7b20068b53370dd0d708e5ea05106acc31c9bdd9ebd37cde8d23fd5dc88a90" + }, + "tests/ui/test_anri_recruitment.gd": { + "bytes": 7778, + "sha256": "74cfaf73ed01769c49498e5395fda009b70f2f6667f4f902abf4697f01f87962" + }, + "tests/ui/test_anri_recruitment.gd.uid": { + "bytes": 20, + "sha256": "e89a6a0a3b860c60479b2ef1555f10abf33b9c89ee8afd786dae24ec1f7cfdfb" + }, + "tests/ui/test_approved_free_unique_arrears_ui.gd": { + "bytes": 10118, + "sha256": "ff684e2f227896c1b5df6026f130d45f4289fc6cae40989be51ddc95b2cf135b" + }, + "tests/ui/test_approved_free_unique_arrears_ui.gd.uid": { + "bytes": 20, + "sha256": "921ea8dc6caae77253e3fa9b552e808eae343e34cb6c7dfa6c0ad2ea9259fe7c" + }, + "tests/ui/test_business_management.gd": { + "bytes": 31543, + "sha256": "2c76697f9a911e9dded63ebbbc2b82ee9e616777c50a637eebd91dc4932f85a5" + }, + "tests/ui/test_business_management.gd.uid": { + "bytes": 20, + "sha256": "658c50b3c522186a1bc4f95277c42f6790cebef90746e29f5857141f8a34535d" + }, + "tests/ui/test_chapel_gameplay.gd": { + "bytes": 6975, + "sha256": "e1996d6bd6caf46bae7becf1de2514e91a6168a686e83563b00803ac71109735" + }, + "tests/ui/test_chapel_gameplay.gd.uid": { + "bytes": 20, + "sha256": "ea9ecc1e52c434b530940638a731799d30802508ac07d3d278c3cba932e66320" + }, + "tests/ui/test_cleaning_gameplay.gd": { + "bytes": 10578, + "sha256": "38593cd17829611dd34561ec46a0d746492a6cffebc35a659d49fe69de4234ac" + }, + "tests/ui/test_cleaning_gameplay.gd.uid": { + "bytes": 20, + "sha256": "88c900d3e73a2d17d5d777ea35110ae09e5be1fc1959b2b171fdea3230bae1d2" + }, + "tests/ui/test_dashboard_coalescing.gd": { + "bytes": 2522, + "sha256": "2f4bd8e9d43911067a7e82864454f6779ae92acc48e0b8d4932e5d963e0430ec" + }, + "tests/ui/test_dashboard_coalescing.gd.uid": { + "bytes": 20, + "sha256": "36d648437a23a8e8d42d0f7cd252fcc457e25e084373c5aef6e24f074293d8b5" + }, + "tests/ui/test_defense_management.gd": { + "bytes": 24758, + "sha256": "e7debf5746e1ad5976b1afb1d2471c1c2317bcc406ed2716a2368bd4e06e0235" + }, + "tests/ui/test_defense_management.gd.uid": { + "bytes": 20, + "sha256": "44e00c3b8d3bc4febcf177e90cc2223709e570ea648e88b7e91b70758b869bf4" + }, + "tests/ui/test_dimension_migration_ui.gd": { + "bytes": 4653, + "sha256": "0f0cec88ea8bf5fccdcd5ade02fab70b7dc71135132048cd10db17ad9d964c0d" + }, + "tests/ui/test_dimension_migration_ui.gd.uid": { + "bytes": 20, + "sha256": "c8990d38cc46826a05fd80f01eb6f3ef6c5a30efb49e549be53b49517c8c0195" + }, + "tests/ui/test_elevator_management.gd": { + "bytes": 5744, + "sha256": "dff2d3f2a1cea84224aee8f70c4ad53d731df173bc7d16d7ec012c0d16c62e11" + }, + "tests/ui/test_elevator_management.gd.uid": { + "bytes": 20, + "sha256": "613de4319583488f743fc370f08a3cec3adadc52fd72c07be66328c24fd11f87" + }, + "tests/ui/test_event_log_ui.gd": { + "bytes": 7668, + "sha256": "9b1d7cb112790bb58969338ab1dc0bbe2a1c26b4307c4bfcd37491cf950c557b" + }, + "tests/ui/test_event_log_ui.gd.uid": { + "bytes": 20, + "sha256": "d1ff881138199728e339cdaff28879cfd241125dab91343b1da3c5a8d4258a00" + }, + "tests/ui/test_first_operating_day.gd": { + "bytes": 14620, + "sha256": "fcba5cee4ea7b16340871d98634cef56d80ca2197b1b069d47ae6cf287693226" + }, + "tests/ui/test_first_operating_day.gd.uid": { + "bytes": 20, + "sha256": "25a1c5fa8f5a97774857786e27301d8f47cfa13f0e183a67e771bf2a331904a5" + }, + "tests/ui/test_guest_decision_log.gd": { + "bytes": 8533, + "sha256": "8532defab87c075ad3196b44af030cdab785abed365e25d5a56d2d42f115cf71" + }, + "tests/ui/test_guest_decision_log.gd.uid": { + "bytes": 20, + "sha256": "f4bd8e3ed43884d01f14a81e94f96368c09a7f5561ecfd5102f8715328de41a3" + }, + "tests/ui/test_guest_observation.gd": { + "bytes": 3824, + "sha256": "8f5af3d6ef367512b34d0cf35fd8c1d2848d020419dddfa234120206dbe4f6e4" + }, + "tests/ui/test_guest_observation.gd.uid": { + "bytes": 19, + "sha256": "5d87f231ad2af61fff902fb745df9b50b7cfcb05b1e5ec53c841bc40d0a5be88" + }, + "tests/ui/test_layer_presentation.gd": { + "bytes": 6415, + "sha256": "2080a64df66c66a28c6d73fc5678a2e8d221e230e6afb38f2550d12bfd6deea7" + }, + "tests/ui/test_layer_presentation.gd.uid": { + "bytes": 19, + "sha256": "bea9e9b5c8a41a39c6024861b8d85aca66f0dd15368d96e96400ea06fd3783d8" + }, + "tests/ui/test_layer_skin.gd": { + "bytes": 6005, + "sha256": "aab6f0561e222f88681169a82b47631320495df4c359bcf79d2fb228c60ad83b" + }, + "tests/ui/test_layer_skin.gd.uid": { + "bytes": 19, + "sha256": "bdd4abced670f5335ebd803c9857a94060c06f19b4f09b7f031a4d9403304412" + }, + "tests/ui/test_main_audio_feedback.gd": { + "bytes": 4590, + "sha256": "9bc9e13ef3498941b6e8566c0b7666c42e294b63e18ec0da2cfa1cda3e4617bd" + }, + "tests/ui/test_main_audio_feedback.gd.uid": { + "bytes": 20, + "sha256": "f4bd2dccbc67139eb7c1de1ce482bdfedf417350510a4e9cc424c918735c9552" + }, + "tests/ui/test_main_dashboard.gd": { + "bytes": 36106, + "sha256": "305227c1077a92ef3ee522b561a68b0685767740b46b51ff789c800931647ef1" + }, + "tests/ui/test_main_dashboard.gd.uid": { + "bytes": 20, + "sha256": "b0ff678ba3b377493aefe655ee10fef0d308bb0619b6e89394da6350d5c5e554" + }, + "tests/ui/test_opening_assignment.gd": { + "bytes": 3493, + "sha256": "143cbd7ca4589540b5f04693dc7c43df8808b87934844d3dd21d33e34f813fa2" + }, + "tests/ui/test_opening_assignment.gd.uid": { + "bytes": 19, + "sha256": "1a2c47cf375d40fff661802f44ecebb5c73dcc9bbb6e7970249ff36802a9b538" + }, + "tests/ui/test_original_build_pointer.gd": { + "bytes": 19891, + "sha256": "a04a79c5e766659d10c4564d1f11c6554a27cb8af71431295e10bc4967012913" + }, + "tests/ui/test_original_build_pointer.gd.uid": { + "bytes": 20, + "sha256": "5cb6ed3b533a7035b8e87007ee21cb093ffa07e879a25f0d4abdd586c09e0bc8" + }, + "tests/ui/test_original_facility_controls.gd": { + "bytes": 4966, + "sha256": "294b39808d3454f96555b981c8f822f17e1248afa803f7c0da74c35799ae55a1" + }, + "tests/ui/test_original_facility_controls.gd.uid": { + "bytes": 20, + "sha256": "5a2544c24d9f6ac0cf1a1d0e74e93c9c3f0dc305a84add18981f63d7214b11d3" + }, + "tests/ui/test_p08_normal_placement_ops.gd": { + "bytes": 2467, + "sha256": "a5c5abdc1348e7dadafd70f73072ac98afcc4c918211c3389e88da5e903af803" + }, + "tests/ui/test_p08_normal_placement_ops.gd.uid": { + "bytes": 20, + "sha256": "7d168ac50ca82ae1979da31c467f9a5020ca5ec7616b5bf99294413d85b3b299" + }, + "tests/ui/test_p23_life_observation.gd": { + "bytes": 15915, + "sha256": "750254af7d4b8b00508e25d1ef744837d3a7d14ddebe12398e8014bf5e8c68e8" + }, + "tests/ui/test_p23_life_observation.gd.uid": { + "bytes": 19, + "sha256": "721207a56299cd53855a5ff164408507bfaaa9c83f925ead32961c5fc847fff7" + }, + "tests/ui/test_paired_bgm.gd": { + "bytes": 19476, + "sha256": "fcafe858caef15f99faa9ad8aa7971828e9053adc1357077f0a26f0f17d9bbc0" + }, + "tests/ui/test_paired_bgm.gd.uid": { + "bytes": 17, + "sha256": "c3d72aa220d14b877fc437fb75608a2094a689dac14266c6951d0fa04cc3e947" + }, + "tests/ui/test_pixel_tower.gd": { + "bytes": 21265, + "sha256": "f149f4b5507247dadf623e777e90b9bdb81f54324b406a8f55adaf89b649866a" + }, + "tests/ui/test_pixel_tower.gd.uid": { + "bytes": 20, + "sha256": "6b2fd502b27891dcc9ab00de29b7767e949cbcf55e4938eba2d6aec9f0f92890" + }, + "tests/ui/test_rank_pointer.gd": { + "bytes": 17805, + "sha256": "2c51510f80fb57068c6c06aa56566936685e679720b0fd853d8f814566e730f2" + }, + "tests/ui/test_rank_pointer.gd.uid": { + "bytes": 20, + "sha256": "741517fad1fc47d0d69e782e798f1302a00b0274368d32d1f9073d80efbead57" + }, + "tests/ui/test_room_presentation.gd": { + "bytes": 10525, + "sha256": "eeea7cfbdd534d5e182dc00ec09cb1a8d3688aba85ccf16beb98fe79c70686a9" + }, + "tests/ui/test_room_presentation.gd.uid": { + "bytes": 19, + "sha256": "2a5f7fc3c658c1cecbe1ce1a817aefd9ef43430515f891da0025e3ab63ba3e3f" + }, + "tests/ui/test_selection_autosave.gd": { + "bytes": 3098, + "sha256": "1d7d267ef171041f77241c4c2f1a1bb55a46253f803d5c496507e934bc8fa815" + }, + "tests/ui/test_selection_autosave.gd.uid": { + "bytes": 20, + "sha256": "a8ab0caf258115b351f5ec0c61161f84d2997d943fdd9cbc1d017f348562f7a8" + }, + "tests/ui/test_selection_departure.gd": { + "bytes": 7878, + "sha256": "3137f36f547514f25ce6ac775fa7a5141d12f83ca4b95da0be45fecfafe9d9b4" + }, + "tests/ui/test_selection_departure.gd.uid": { + "bytes": 20, + "sha256": "7c215d6dfa0b89a604c68d65820e34878b2a1444964c7060bcfc156ce8a52bff" + }, + "tests/ui/test_selection_lifecycle.gd": { + "bytes": 9355, + "sha256": "ed68b120f422e1b37b8cf0654b6d6605458fe01c7e5d84decc3ba6f4e9366c47" + }, + "tests/ui/test_selection_lifecycle.gd.uid": { + "bytes": 20, + "sha256": "f786d9622c55c2e52edd422ce243d84307c305871d071eee1eb65b96e963f76b" + }, + "tests/ui/test_staff_management.gd": { + "bytes": 35774, + "sha256": "7e37dc47583325a564ef48de31596adeeccfb7151ac5fce952efc6873c8ab704" + }, + "tests/ui/test_staff_management.gd.uid": { + "bytes": 20, + "sha256": "ee54ed9638407a879dcc021ad01fddb032b2dfcba2312ba53309926a50bb1a87" + }, + "tests/ui/test_staff_rescue.gd": { + "bytes": 6965, + "sha256": "928179383bda38adf9211065b644a37bed3f8128be42b7e7a0fba9a505a40b9e" + }, + "tests/ui/test_staff_rescue.gd.uid": { + "bytes": 20, + "sha256": "b46c4e697e15c94ff75affde9bbafc6287e68a33b03779f5ee8504889aa56a4d" + }, + "tests/ui/test_staff_rest.gd": { + "bytes": 3156, + "sha256": "712f2c30ec89da20835e54f2e83b22a358cc6fc05555147ce635ec2592ef75b5" + }, + "tests/ui/test_staff_rest.gd.uid": { + "bytes": 20, + "sha256": "9db2b8264e53dcf5f2f06e6dc2903855d13df9da5e62671bdebb0978029c43db" + }, + "tests/ui/test_stair_transport_details.gd": { + "bytes": 10516, + "sha256": "3abd3655eecbefe1b7cd49e1b16c42f8161c86f20380c298ec6367b42d31555f" + }, + "tests/ui/test_stair_transport_details.gd.uid": { + "bytes": 20, + "sha256": "779c58b724b750f38d91592b7369a9d15fa21ccc58853a08f4f489bfd1d4a246" + }, + "tests/ui/test_supply_auto_purchase_ui.gd": { + "bytes": 9384, + "sha256": "ad3788ae4b3f17918be67cf06c4162635da1ecba1ee0a0465d10acc019f3e3ae" + }, + "tests/ui/test_supply_auto_purchase_ui.gd.uid": { + "bytes": 20, + "sha256": "74bb4aa798695f40f849b250c4995fca394ab6e600df5682a8cf45759265528a" + }, + "tests/ui/test_supply_management.gd": { + "bytes": 13417, + "sha256": "ee96be8b31eb71e84ab813e427a28bcfb76de4a057bd964584a6a497382ea716" + }, + "tests/ui/test_supply_management.gd.uid": { + "bytes": 19, + "sha256": "9f29d5d9bf34830b98571cc34a1765346f44702664e28f9c5d161727d554d947" + }, + "tests/ui/test_ui_audio_feedback.gd": { + "bytes": 21730, + "sha256": "62c5c8080b1a05d243977a293a23ab216ef71de38fe46ca6b31c71e0af4555fe" + }, + "tests/ui/test_ui_audio_feedback.gd.uid": { + "bytes": 20, + "sha256": "344ee24a4ffb03394c308c3bbe185cf88fd72554f826c1b64927d09eabd67a78" + }, + "tests/ui/test_ui_presentation_audio_contract.gd": { + "bytes": 10823, + "sha256": "9769b89b61630ddf2ef13a927f329ddaa30e04da77987e7a868d0490244d6a25" + }, + "tests/ui/test_ui_presentation_audio_contract.gd.uid": { + "bytes": 19, + "sha256": "efb17e69ab945f62a254cbd3d3cb15856ee885e36347bd8921018bcf9e47f24e" + }, + "tests/ui/test_upkeep_closed_ui.gd": { + "bytes": 7327, + "sha256": "915db12e539d98bfcb2cfc3712693ca7fca3ff459aaacba419faff04ac712868" + }, + "tests/ui/test_upkeep_closed_ui.gd.uid": { + "bytes": 20, + "sha256": "0bb78af842663520dd25a54bde65c6c7e147e0bcc8d64a5797ecebfbbfdae3c0" + }, + "tests/ui/test_upkeep_inspector.gd": { + "bytes": 3134, + "sha256": "99895a24bcddc4c2e01d8960a2fd7eba05be237a64700d78879c68c1a0660f34" + }, + "tests/ui/test_upkeep_inspector.gd.uid": { + "bytes": 20, + "sha256": "4266627f5e713cecec9c5dc04fe291bc67a2a583f6b286f6774db8180c608917" + }, + "tests/ui/test_world_tree_rank.gd": { + "bytes": 7052, + "sha256": "8e108e3ae63d1ee3971c7b236f50a673c407835f094de0d38a736c38261767aa" + }, + "tests/ui/test_world_tree_rank.gd.uid": { + "bytes": 20, + "sha256": "9fae0add894e14555e59505705de504f1fbc396f0dbf86bbe0c1aa17fd32cec5" + }, + "tests/world/test_elevator_topology.gd": { + "bytes": 14356, + "sha256": "4710a6bba103d82a4d2febea1a2c30d029c0f1ccd2a3d9a6c1712b4fb372033b" + }, + "tests/world/test_elevator_topology.gd.uid": { + "bytes": 20, + "sha256": "5f5a10f9415fd6b27c9961a9edda188ae3d0b8a945a17f656df251035dd2676c" + }, + "tests/world/test_legacy_stairs.gd": { + "bytes": 13041, + "sha256": "258d759537aec8b7b90cab107985c9c6a16f10e85ae7ae92a9c54cc94417d48e" + }, + "tests/world/test_legacy_stairs.gd.uid": { + "bytes": 20, + "sha256": "4aa1ec1cc07e68bbe040260e9cd02e7f8e72e3043ec6901e27fdb952ebe3eea6" + }, + "tests/world/test_path_transit_density.gd": { + "bytes": 9064, + "sha256": "8de5fc8bdf8631ff41fcd4862cea40daa3316040f381f182dc6fe09dba9f3cb9" + }, + "tests/world/test_path_transit_density.gd.uid": { + "bytes": 20, + "sha256": "c83e471ff6bc0aab61bb38ae4cf651cc83a543db546449d646685f9f963a29ff" + }, + "tests/world/test_path_vertical_policy.gd": { + "bytes": 6921, + "sha256": "140cdf552309f89cd93bf1a4d38827a671a66461203f0858f1c2651a8e6e8473" + }, + "tests/world/test_path_vertical_policy.gd.uid": { + "bytes": 20, + "sha256": "c50c8e78bb3c8eb96b58f81643d12151f08c52fecdd1e4360c07ecca429ceaf7" + }, + "tests/world/test_stair_infrastructure.gd": { + "bytes": 16167, + "sha256": "f6d1a29b43875b7b1fc945611c2ed15fbdcb8bb7220addf283b30fedf2ccba28" + }, + "tests/world/test_stair_infrastructure.gd.uid": { + "bytes": 20, + "sha256": "e08f53e9f6094e073e66252037b19835c594180d8d5ccffead43972fd0c41032" + }, + "tools/build_original_asset_inventory.py": { + "bytes": 6554, + "sha256": "1ca3be772088cc02c71fe9485d590dcd77ad95d5298983bfd27f15ad056642c9" + }, + "tools/capture_facility_audit.gd": { + "bytes": 2189, + "sha256": "3c597a844284367a31f6bfac8d3a1edd20622e405e0feb07a9681ddf7baf3b4a" + }, + "tools/capture_facility_audit.gd.uid": { + "bytes": 20, + "sha256": "dae70a3ded19ae9b79d8a5b7bc5342ad308954a65654f55c78a0af1c04df5edc" + }, + "tools/check_p04_order_evidence.py": { + "bytes": 82294, + "sha256": "3bb0cde776bc295f6f18e74f1e23bf3d832d8e4f71aed260601c82d287c655fd" + }, + "tools/check_p08_migration_evidence.py": { + "bytes": 24615, + "sha256": "928353233bf85436a5aaf8c4f77f3f82472d94b8ad2646cb1b030baf92b3b5dc" + }, + "tools/check_p08_normal_placement_evidence.py": { + "bytes": 73196, + "sha256": "53acc2e29fc36f7c7e3b2a5f6d3f97ba935b9052e4b6e095b071ec240f4ff68a" + }, + "tools/check_p13_content_difference.py": { + "bytes": 30401, + "sha256": "7b29180c776218138bfe1bf23013102932d853481cff41e7d830f1f5cf5c4d26" + }, + "tools/check_p23_life_observation_evidence.py": { + "bytes": 143352, + "sha256": "e41479ae51bccdfab3f31bd348794b441c2f341179bbe33222e2aacdf88f987f" + }, + "tools/check_p24_selection_evidence.py": { + "bytes": 14622, + "sha256": "cae171fe642240e8074a9ba56b9dd501349b008ad35251bba7a776d7210a1640" + }, + "tools/regression/audio_evidence_gate.py": { + "bytes": 9256, + "sha256": "3b587f0df7d7e6d97aa01d959d3ef4db74d9b81efc945407912e8539a4d071be" + }, + "tools/regression/bootstrap-scripts.json": { + "bytes": 3627, + "sha256": "cef904f10ca8d8ec7e87144cd1ea80d169fa31a8ece3fe2a106aa09e69046843" + }, + "tools/regression/diagnostic_gate.py": { + "bytes": 3679, + "sha256": "fc006e92b1a7b5122aaa5b30ba71fb054ee34021d4daa3a19167927ecd6657b2" + }, + "tools/regression/ordinary_proof_gate.py": { + "bytes": 6290, + "sha256": "1809dd3a6d3e0dbc6b55a87fc5890afd459deec2afd317bae1272d6708854459" + }, + "tools/regression/owned_diagnostic_process.py": { + "bytes": 14004, + "sha256": "e31e93c6e2c5ea46a7d954ef8bc0b4caec1c08b86b8aef19e93b52ef24993087" + }, + "tools/regression/owned_outer.py": { + "bytes": 4177, + "sha256": "c2e3483b76db1a3ff940f23f88ea0083fc78736e874ebcdb385d766dde8866e7" + }, + "tools/regression/p09_owned_engine_process.py": { + "bytes": 3717, + "sha256": "c007e712c281573254faa1233c2ac92e100ab87393256a6dc096b35283e43037" + }, + "tools/regression/review_protocol.py": { + "bytes": 12360, + "sha256": "354a2ec9287dc052ccdba05b53443ddef28d94272471bb6a3c6a1581c6bd3efe" + }, + "tools/regression/suite-policy.json": { + "bytes": 17282, + "sha256": "164fcf07e2424bcd60657fc8eaa8bf3167f0aeda73e246662b555e8401856ed2" + }, + "tools/regression/unicode-diagnostic-contract.json": { + "bytes": 2938, + "sha256": "22fd41c59eb13e0af397984bed418870c55fa8942524c377490a90a2aca8dedd" + }, + "tools/run_all_tests.py": { + "bytes": 26296, + "sha256": "320ca668732b4ff72fc4449998af2327d4e5c527b06896740806aaf0487282b4" + }, + "tools/run_facility_audit.py": { + "bytes": 6172, + "sha256": "f5430ffd5bef013082975b0dca2c1f94a5a54f2fbee4105a56f5130f7ead4126" + }, + "tools/run_opening_restart_flow.py": { + "bytes": 2565, + "sha256": "e2b789866b14404f72af24fe60c6cad6ec77db5a8c597be08a9a58c516d7af5a" + }, + "tools/run_p08_mixed_migration.py": { + "bytes": 7939, + "sha256": "7e86737e6354a4734726ba8d3171ad5f58d6c0380aba5a0fa3c57879d580e579" + }, + "tools/run_p08_normal_placement.py": { + "bytes": 15345, + "sha256": "5cb1f58664a0bec71c8b5e853749d1c3656e0a2a027201e33fbaa6b0c0291fc6" + }, + "tools/run_p13_reference_tests.py": { + "bytes": 13957, + "sha256": "9adc8aa2a7662df8dd70386ddb0bff34574e44d7411de3b6128ddd15eb24675c" + }, + "tools/run_p18_relationship_tests.py": { + "bytes": 32904, + "sha256": "ccc8976dd9e9863366d102719dc0ae21d3a57da45dec39b4c72a3fc8c9f31a9b" + }, + "tools/run_p23_life_observation.py": { + "bytes": 22888, + "sha256": "8dbd90e22f47912b3381b514398fe1fb2c403c97d8e3d0dd675e9c8db5b5d0d1" + }, + "tools/run_upkeep_ui_flow.py": { + "bytes": 1650, + "sha256": "32d7d9e0075b70749696db01c2c27a588a35cf0ed89d8ed942cbeaece17863c9" + }, + "tools/strict_test_markers.py": { + "bytes": 9621, + "sha256": "1cb16da6c5c00c1a0610a3fc04beb97d1eb3ba492fb1bc8fe5b621d2b7bc0406" + }, + "tools/test_p08_migration_evidence.py": { + "bytes": 19293, + "sha256": "fd9ef7ec63f53dfd5e04e261606c9303d01a2e6590e22a35fef2e35df1429280" + }, + "tools/test_p08_normal_placement_evidence.py": { + "bytes": 59221, + "sha256": "8a29e3b996e2f1d15c69283faeae54555654c3cf89df99d8ce7f9eed38cd5edc" + }, + "tools/test_p23_life_observation_evidence.py": { + "bytes": 139688, + "sha256": "6890e890e54850581c9fc61f8d466396d6e92645bdc9f798885b7273d78c899a" + }, + "tools/verify_exported_opening.py": { + "bytes": 1519, + "sha256": "d1931d5e53890216fb006900789015a3ee14dce0293a4757a73fd6bb92b28d3f" + } +} diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/IMPLEMENTATION.md b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/IMPLEMENTATION.md index 875f8c1..086b65d 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/IMPLEMENTATION.md +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/IMPLEMENTATION.md @@ -721,3 +721,69 @@ read-only directory and its copy has the recorded bytes and SHA). The engine (/A the machine model stay read live. Everything else verify_eq recomputes from the bundle and the checkout as before. +## S6 implementation (repair 12; EQ_S6_AFTER_VERSION_PLAN) + +Implemented by Claude Opus 5.5 in the Desktop control session (user delegation). Repair for +the independent review of S a46418d (changes_requested: EQ5). All earlier text is retained. + +### The after version through the frozen harness (EQ5, high finding) + +- `BEFORE_SOURCE_MAP.json`: the registered base product source map, 1407 rows of + `{bytes, sha256}`, written from `collector.source_map` of the S_eq checkout. Its meaning is + fixed by the existing `SOURCE_SHA`; `compare_versions.before_source_map()` rejects duplicate + keys, row shape errors, a different row count and any digest other than `SOURCE_SHA`. +- `compare_versions.admit_source(source, registered)` is the single admission rule of both + versions. `registered` must be a sorted duplicate-free list. It runs + `check_source_closure(before_source_map(), source, registered)` and returns the closure with + `version` (before when `registered` is empty, otherwise after) and `after_sha256`. The before + version is exactly the old `SOURCE_SHA` requirement; the after version needs the changed set + equal to `registered` (a subset of `OPT_PATHS`), with no added or missing source. +- `run_eq`: `--opt-changed PATH` (repeatable, sorted by main, duplicates rejected by the rule). + `actual_pins(..., registered)` records `registered_changes` and `source_closure`; the + admission records `version` and `measured_source` (`verify_eq.MEASURED`: before + `S_eq-native-not-Q`, after `S_opt-native-not-Q`, OPT_CONTRACT_T1 §5); `pins_after` is + recomputed with the same registration. The EQ file pins (`worker`) and `frozen_commit` + include `BEFORE_SOURCE_MAP.json` (`verify_eq.DATA_NAMES`). +- `verify_eq.recompute` replaces the `SOURCE_SHA` line with `admit_source` on the recorded + map and registration and requires the recorded closure, version and label exactly; + `verify` passes the recorded registration to `actual_pins` on the checkout. The result + carries `measured_source`, `version` and `registered_changes`. +- `verify_eq.py --compare-versions --before --after ` (`compare_bundles`): + the bundle-level entry of the two-version comparator (SPEC §2, §3.2; OPT_CONTRACT_T1 §2-§4). + Both seals, passed executions, admission copies, versions, closures and labels are checked + again; every non-product pin (`dependencies`, `frozen`, `worker`, `fixture`, `engine`, + `engine_version`, `readonly`, `original_manifest`, `machine`, `platform`) must be equal; the + sealed joined reports of R-A and O-A are compared by `compare_reports` (differences, + exclusions, digest modes and violations all returned); the stored checkers' existing-defect + scenarios of both versions are listed and `after_all_e_pass` reports whether the after + version has none (the OPT acceptance judges it). Each bundle's raw recomputation, same-role + determinism and checkout pins are proven by that version's own native-verify. + +### Low findings + +- `eq_probe.gd` E5 detail: `latest_digest_dirty_before` is `runtime.get("_latest_digest_dirty")` + read just before the operation (null if a version has no such field), replacing the constant + `digest_materialized_before: true`. The checker accepts only `false` or `null`. +- `run_eq.bundled_inputs`: the bundled manifest must have `ROOT_MANIFEST_SHA` (the value + `collector.inputs` fixes; a unit test checks the literal in the collector source), and each + destination string must be absolute and already normalized (`os.path.normpath`) inside the + read-only directory. This is textual because the sandboxed verification cannot read the + originals; the run checks the resolved originals through `collector.inputs`. +- `verify_eq.seal`/`check_seal`: bundle schema `p28-02-eq-bundle-v2` with `directories`, the + sorted list of every directory (empty `/startup-profile` included). A file-only copy + of a sealed bundle now fails the seal check itself. + +### Tests and evidence kinds + +- 17 engine-free tests in `S6SourceClosure`, `S6Admission`, `S6Bundles` and `S6SealAndProbe`. + `S6Bundles` builds one sealed before and one sealed after synthetic bundle per class with + the real parallel recompute, compares them unmocked, and tampers APFS clones (`cp -c`) only; + the real state difference is a changed K value in the after R-A report. The main test in + `S6Admission` mocks `actual_pins` only to read the registration passed by main. +- Diagnostic, not formal: `EQ_S6_AFTER_ADMISSION_DIAG_R01` (Root control folder) ran the real + `run_eq.py --check` on a throwaway after-version checkout; the admitted and rejected cases + and their exits are in its SUMMARY.json. +- The first S6 bundle tests copied 709 MB synthetic bundles with `shutil.copytree` and ran + out of disk space during a class-targeted run (not retained); they now use clones. +- Full local run UNIT_OUTPUT_S6_ATTEMPT_01: 179 tests OK in 207.351 s, exit 0. +- Local run under the Runner validation seatbelt profile, UNIT_OUTPUT_S6_SEATBELT_01: 179 tests OK in 206.326 s, Python exit 0, outer 207.695 s. diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/PROGRESS.md b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/PROGRESS.md index 324a62e..ff9e5c5 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/PROGRESS.md +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/PROGRESS.md @@ -1,4 +1,78 @@ -# P28-02-EQ progress — S5 (repair 10, Claude Opus 5.5 Desktop implementation) +# P28-02-EQ progress — S6 (repair 12, Claude Opus 5.5 Desktop implementation) + +Implementer: Claude Opus 5.5 in the Desktop control session, by the user's delegation +("Codexの使用量上限いきそうなので、作業をひきとって"; Root relayed 「実装担当含めOpusに委任」). +The registered contract keeps worker codex; no Codex/Astra run was started for this stage. +Submission goes through the normal Runner submit, which makes the commit. 正式受入は保留、原本加算0。 + +- S a46418d064ebf8c8e03043bae50c29ac174b5472 (repair 11): its exact-S native passed + (native-a46418d-r01, 7 phases, cleanup errors empty, sealed), and its formal validation + cb059f305dd34e7aa811b40ad1cfb6f2 passed both checks (unit 162 tests OK; native-verify + exit 0, verified). The fresh independent Opus review (session + local_179020e9-e4c8-45ab-aaa0-be27aaa3f3d6, DESKTOP_RESULT.json + c08eedb2ff81fd308e0771aeb4330076389561255a2bb964567be28f478592cd) returned + changes_requested: EQ1-EQ4 and EQ6 met, EQ5 not met. The normal intake recorded + review_failed and repair_pending; the normal repair made repairs 12. All of it is retained. +- The high finding is accepted: the source closure was only unit-tested. run_eq and verify_eq + required the before SOURCE_SHA, so the frozen EQ could not admit an OPT S that changes only + registered allowed files (OPT_CONTRACT_T1 §2 and §4). S6 (EQ_S6_AFTER_VERSION_PLAN): + - BEFORE_SOURCE_MAP.json holds the registered base product source map (1407 rows); its + digest must equal the existing SOURCE_SHA on every read. compare_versions.admit_source + admits the before version (no registration, no difference) or an after version (the + changed set equals the sorted registered OPT files; no added or missing source). + - run_eq --opt-changed PATH (repeatable) registers the OPT files; actual_pins records + registered_changes and source_closure, the admission records version and + measured_source (before S_eq-native-not-Q, after S_opt-native-not-Q; never Q). + verify_eq re-runs the closure with the recorded registration and requires the recorded + closure, version and label; actual_pins on the checkout gets the same registration. + - verify_eq --compare-versions --before --after is the bundle-level entry + of the comparator (SPEC §2): both seals, versions and closures again, every non-product + pin equal, compare_reports on the sealed A-phase reports of R and O, existing defects of + both versions listed (after_all_e_pass for the OPT judgment). +- The three low findings are fixed: the probe records the actual _latest_digest_dirty before + each E5 operation (false or null accepted, true rejected); bundled_inputs requires the + collector's fixed manifest SHA and normalized absolute destinations inside the read-only + directory; the seal (bundle schema v2) records every directory, empty ones included. +- Evidence kinds are kept apart: + - Unit, engine-free, real code paths: admit_source; run_eq.actual_pins with a synthetic map + (only collector.source_map, inputs, host SHAs of the synthetic fixture/engine and the + machine query are patched); recompute of a real synthetic after bundle; compare_bundles + unmocked on a real before and a real after synthetic bundle (positive, a real state + difference, pin drift, closure and label tampering, seal tampering, swapped, same bundle). + One unit test (S6Admission main) mocks actual_pins only to see the registration main + passes; it is not counted as admission evidence. + - Diagnostic, not formal (EQ_S6_AFTER_ADMISSION_DIAG_R01 in the Root control folder): the + real run_eq.py --check, unmocked, on a throwaway after-version checkout (an APFS clone of + this working tree as its own temporary git repository, one allowed OPT file changed and + committed). Before version and the registered after version were admitted; no + registration, a wrong registration, a registration without change, an added source and a + non-OPT change were rejected with the source closure error. No engine was started. +- Unit evidence (engine-free `python3 -B test_eq.py`; full raw outputs with SHA files): + - Class-targeted runs during development were displayed through tail and are not claimed + as retained raw results. One of them ran out of disk space (the first S6 bundle tests + copied 709 MB synthetic bundles); the tests now clone with cp -c and build two bundles + per class. + - UNIT_OUTPUT_S6_ATTEMPT_01 (final, all changes included): 179 tests OK in 207.351 s, + Python exit 0; same bytes as UNIT_OUTPUT.txt, + SHA-256 9dd93de5fd3b66791d6902d51a055caa2c3dd559de6c42019ebb1ab147b2af11. + - UNIT_OUTPUT_S6_SEATBELT_01: the same suite under the Runner validation seatbelt profile, + run locally (see its exit line in IMPLEMENTATION.md). Local runs are not formal validation. +- Test bodies changed for S6, each recorded here: the E5 fixture detail carries + latest_digest_dirty_before false instead of digest_materialized_before true, and the + materialization test rejects true; s4_bundle_fixture takes an optional registration and + pin overrides and records commit, version, measured_source, registered_changes, + source_closure and the non-product pins; the S4 probe-admission mock returns a before + source_closure; the stored-result test records registered_changes [] in its admission and + mock; the bundled-inputs test holds its synthetic manifest to its own SHA in place of the + collector's and expects the manifest error before the escape error. All other earlier test + bodies and raw outputs are unchanged; 17 S6 tests were added. + +Next: Runner submit → exact-S native 7 phases (before version, no --opt-changed) → bundle → +p28-02-eq-unit and p28-02-eq-native-verify → fresh independent Opus review of all 6 +conditions → normal qualification, approval, integration and final → OPT/whole-unit. +23/88、4/30は不変。 + +## Retained S5 progress (unchanged historical text) Implementer: Claude Opus 5.5 in the Desktop control session, by the user's delegation ("Codexの使用量上限いきそうなので、作業をひきとって"; Root relayed 「実装担当含めOpusに委任」). diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/S6_SUPPLEMENTARY.json b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/S6_SUPPLEMENTARY.json new file mode 100644 index 0000000..19fcbd5 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/S6_SUPPLEMENTARY.json @@ -0,0 +1,31 @@ +{ + "actual_commander_context": { + "implementer": "Claude Opus 5.5 (claude-opus-5-5), Desktop control session local_a7f85421-3eed-4482-8030-c0dca669573a", + "authority": "User delegation: Codexの使用量上限いきそうなので、作業をひきとって; Root relayed 実装担当含めOpusに委任. Contract worker field stays codex as registered; no Codex/Astra run.", + "stage": "S6 (repair 12): repair for the independent review of S a46418d (changes_requested, EQ5): after-version admission and verification through the frozen source closure, the bundle-level two-version comparison, and the three low findings.", + "reviewer_session": "local_179020e9-e4c8-45ab-aaa0-be27aaa3f3d6 (fresh separate Opus 5.5, read only)", + "actual_documents": { + "EQ_S6_AFTER_VERSION_PLAN.txt": { + "sha256": "e51da52336489d069c0adf2c70639755389a049334f5816804fea51a86c25197", + "bytes": 8074, + "full_unedited": "P28-02-EQ S6 計画(repair 12。a46418d の独立レビュー changes_requested への修正)\n\n実装担当: Claude Opus 5.5(Desktop 統括セッション local_a7f85421-3eed-4482-8030-c0dca669573a、ユーザー委任)。\ncontract の worker 欄は codex のまま。Codex/Astra の run は起動しない。commit は Runner submit が作る。\n原本は 23/88、4/30 のまま。部分点なし。\n\n0. 経緯と事実\n- S a46418d: exact-S native 7 phase 合格、正式 validation cb059f30(unit 162 OK、native-verify exit 0)、review_pending。\n- 独立レビュー(local_179020e9-e4c8-45ab-aaa0-be27aaa3f3d6、Opus 5.5、fresh、読むだけ): DESKTOP_RESULT.json c08eedb2…、\n status changes_requested。EQ1〜EQ4・EQ6 は満たす、EQ5 は満たさない。intake で Runner は review_failed、repair_pending。\n- high: check_source_closure(compare_versions.py:845)が run_eq/verify_eq につながっていない。run_eq.actual_pins\n (:124)と verify_eq.recompute(:212)が source map = before の SOURCE_SHA を要求するため、OPT の許可差分だけを\n 変えた S も拒否され、OPT_CONTRACT_T1 §4 の「OPT の S で同じコマンドで eq-after-」が、凍結した EQ を変えずに\n 実行できない。この指摘は正しいと判断する。\n- low 3件: (1) eq_probe.gd の digest_materialized_before が定数 true。(2) verify の bundled_inputs が collector の\n 固定 manifest SHA を検査し直さず、resolve なしの is_relative_to。(3) seal がファイルだけで、空ディレクトリの存在を\n 束に記録しない。3件とも直す。\n\n1. before の固定(compare_versions.py)\n- 新しいファイル eq/BEFORE_SOURCE_MAP.json: 登録の base の製品 source map 全 1407 件({bytes, sha256})。\n 中身は collector.digest == SOURCE_SHA 651f7036… で固定される(既存の定数がそのまま bytes の意味を固定する)。\n S_eq の checkout の collector.source_map から作り、digest の一致を確かめてから置く。\n- before_source_map(): 読込時に重複 key を拒否し、1407 件・行の型・digest == SOURCE_SHA を要求する。\n- admit_source(source, registered): check_source_closure(before_source_map(), source, registered) を通った場合だけ\n 受け付ける。registered は重複なし・整列済みの list で、OPT_PATHS の部分集合。空なら before の版(差分 0 件、\n つまり従来の SOURCE_SHA の要求と同じ)、空でなければ after の版(実際の差分の集合 = registered、追加・欠落 0)。\n 結果に version(before/after)と after の digest を付ける。\n\n2. admission と verify(run_eq.py / verify_eq.py)\n- run_eq --check / --run に --opt-changed PATH(繰り返し可、既定は無し)を加える。actual_pins が admit_source を\n 呼び、pins に registered_changes と source_closure を記録する。admission に version を記録する。\n- measured_source: before は従来どおり 'S_eq-native-not-Q'。after は 'S_opt-native-not-Q'(OPT_CONTRACT_T1 §5\n 「OPT の提出された S で実行した」)。candidate_Q_measured は従来どおり false を要求する。\n- execution の pins_after も同じ registered で再計算する。verify は actual_pins(…, registered=admission の値) ==\n admission の pins を要求し、recompute は admit_source を記録の registered でやり直して、記録した source_closure\n と version に一致することを要求する(従来の SOURCE_SHA 固定の行を置き換える)。\n- EQ のファイルの pin(worker)に BEFORE_SOURCE_MAP.json を含める。frozen_commit も同じファイルを検査する。\n\n3. 版の間の比較の入口(verify_eq.py --compare-versions --before <束> --after <束>)\n- SPEC §2 の「2つの版の記録を比べる比較器」を、凍結した EQ の中で実行できるようにする(OPT の段階で EQ を\n 変えないため)。比較の規則は compare_versions.py の関数(admit_source、compare_reports)を使う。\n- 両方の束の seal、execution の passed、before の束が version before(registered 空)、after の束が version\n after(registered 空でない)であることを要求し、両方の admission の source_closure を admit_source でやり直す。\n- 製品以外の pin(dependencies、frozen、worker = EQ のファイル、fixture、engine、engine_version、readonly、\n original_manifest、machine、platform)が両方で完全に一致することを要求する(OPT_CONTRACT_T1 §2 の\n 「後の版の EQ・DIAG・collector・RESTART の bytes が固定の SHA と一致」)。\n- R と O それぞれ、before の A と after の A の joined(seal 済みの写し)を compare_reports で比べる。各版の中の\n A と B の差 0 は、各版の native-verify が証明済み。差・除外・違反は全て結果に残す。\n- 両版の checker から existing-defect / existing-defect-candidate の scenario を列挙し、after の版の\n 「全ての E の合格」(OPT_CONTRACT_T1 §3)を判断する材料として出す。判定の受入は OPT の受入で行う。\n- formal_acceptance は false、原本の加算は 0。\n\n4. low の修正\n- eq_probe.gd: E5 の detail に、mutation の直前の runtime.get(\"_latest_digest_dirty\") の実際の値を\n latest_digest_dirty_before として記録する(定数の digest_materialized_before を置き換える)。checker は\n false(materialize 済み)か null(その版にその欄が無い)だけを受け付け、true は失敗にする。\n- run_eq.bundled_inputs: 同梱の manifest の SHA が collector の固定値(9dac0a51…)であることを要求する。\n destination は '..' を含まない正規化済みの絶対 path で、元の read-only directory の中にあることを要求する\n (verify の seatbelt の中では元の path を読めないので、resolve ではなく字句で検査する。run の時は従来どおり\n collector.inputs が resolve で検査する)。固定値が collector の source と同じであることを試験で確かめる。\n- verify_eq.seal / check_seal: bundle.json(schema p28-02-eq-bundle-v2)に全ディレクトリの一覧を記録し、\n check_seal で実際の一覧と一致することを要求する(ファイルだけを写した束は seal の検査で失敗する)。\n\n5. 試験(engine を使わない test_eq.py)\n- before map の改ざん・欠落・重複 key の拒否。\n- admit_source: before(空)が通る、登録した差分が通る、未登録の差分・追加・欠落・登録したのに変わっていない・\n OPT_PATHS の外・重複・未整列を拒否。\n- run_eq.main の --opt-changed が actual_pins に渡ること、actual_pins が admission に記録すること。\n- recompute: registered・source_closure・version・measured_source の改ざんを拒否。\n- --compare-versions: 合成の before/after の束で、通る場合と、pin の違い・version の取り違え・closure の改ざん・\n seal の欠落を拒否する場合。\n- seal のディレクトリ、bundled_inputs の manifest SHA と '..'、probe の latest_digest_dirty_before の静的検査と\n checker の受付(false / null)と拒否(true・欠落)。\n- 既存の試験の本文を変える場合は、PROGRESS.md に1件ずつ記録する。\n\n6. 順序(従来どおり)\n- 通常の repair(repairs 12)→ 局所の全 unit PASS(生出力と SHA を保存)→ Runner submit(新しい S)→\n exact-S native 7 phase(before の版、--opt-changed なし)→ 束の配置 → 正式 validation 2件(全ログと実 exit)\n → fresh の独立 Opus の全 6 条件のレビュー → 通常の qualification・承認・統合・final → 台帳 → OPT T1 と\n whole-unit gate。\n- a46418d の native・validation・レビューの結果は、そのまま保持する(成功・失敗を書き換えない)。\n" + }, + "DESKTOP_EQ_INDEPENDENT_REVIEW_REPAIR_DECISION_A46418D.json": { + "sha256": "49e70371967a0103aeba140cbdee7876c0fc9a268bf465d435b85d4fb3e466b8", + "bytes": 1718, + "full_unedited": "{\"action\":\"request-repair\",\"task_id\":\"P28-02-EQ\",\"reason\":\"Independent review of S a46418d064ebf8c8e03043bae50c29ac174b5472 (fresh separate Opus 5.5 session local_179020e9-e4c8-45ab-aaa0-be27aaa3f3d6, DESKTOP_RESULT.json c08eedb2ff81fd308e0771aeb4330076389561255a2bb964567be28f478592cd) returned changes_requested: EQ1-EQ4 and EQ6 met, EQ5 not met. High finding: compare_versions.check_source_closure is not wired into run_eq or verify_eq; both require the product source map to equal the before SOURCE_SHA, so an OPT S that changes only registered allowed files is rejected and the frozen EQ cannot produce the after-version record required by OPT_CONTRACT_T1 sections 2 and 4. Three low findings: constant digest_materialized_before in the probe, bundled_inputs not re-checking the collector manifest SHA and using an unresolved is_relative_to, and the seal not recording directories. The finding is accepted. Repair per EQ_S6_AFTER_VERSION_PLAN.txt: a fixed before map (BEFORE_SOURCE_MAP.json, digest SOURCE_SHA) and admit_source in compare_versions; run_eq --opt-changed and admission/verify closure re-checks; a bundle-level cross-version comparison in verify_eq; fixes for the three low findings; engine-free tests for each. The a46418d native, validation and review stay retained as they are. After the repair the final S gets one exact-S native, the bundle placement, both validations and a fresh independent Opus review of all 6 conditions, then the normal integration and final. No permission, policy, timeout or Runner configuration change. No original credit (23/88, 4/30). Decided by Claude Opus 5.5 in the Desktop control session acting for Root under the user's delegation; not a CLI commander result.\"}" + }, + "eq-independent-review-a46418d-r01/DESKTOP_RESULT.json": { + "sha256": "c08eedb2ff81fd308e0771aeb4330076389561255a2bb964567be28f478592cd", + "bytes": 8060, + "full_unedited": "{\n \"task_id\": \"P28-02-EQ\",\n \"commit\": \"a46418d064ebf8c8e03043bae50c29ac174b5472\",\n \"status\": \"changes_requested\",\n \"summary\": \"独立レビュー(fresh の別 Desktop セッション、読むだけ)。入力: READY の packet f5f57016…・schema b08d2ec1…・material manifest 823cf63a… を再計算して一致。material 5980 件の bytes と SHA が manifest と全件一致(追加・欠落なし、計 2,920,895,003 bytes)。validation-runs の写しは Runner 原本と同じ SHA。bundle.json f6e1aa1e… と seal.json b4ce53ec… は native-a46418d-r01、task の build dir、material で同一。build dir には空の startup-profile 7 件がある。正式証拠: receipt cb059f30…(p28-02-eq-unit は 162 件 OK で exit 0。p28-02-eq-native-verify は exit 0 で status verified、measured_source S_eq-native-not-Q、formal_acceptance false)。診断実行(scratchpad r2〜r4・o8・o9、NATIVE_VERIFY_DRYRUN_A46418D)は数えていない。EQ1 満たす: probe が各観測の前後で S/K/C の bytes を比べ(K は DIAG と同じ欄で telemetry を含み、C は D2 の定義と instance ID)、checker が raw blob と SHA を結合している。版の間では S・latest_snapshot・latest_digest と SPEC §3.2 の K/C を比べる。比べない欄(_samples/_totals、instance ID、F1〜F3 の sidecar、F1〜F3 を含む latest の latest_digest)は理由と両方の値つきで excluded に入り、正規化した木の全体と labelled digest を比べている。SimulationDigest だけでは判定しない。S5 の blob は名前の SHA と照合し、初回 parse の時に validate_tree を全て通してから _VALID_BLOBS に入れる。失敗した blob は記録されず、毎回失敗する。inline と blob の拒否は試験 4000 件の差分照合と同じ。_fast_normalize は token の検査で外れたら元の全走査に戻り、元の方針を skeleton で動かすので、比べる範囲を狭めない。memo_scope は同じ入力の再利用と GC の停止だけ。EQ2 満たす: B1 の後に subscribe('*') で上限なく記録している。R は 1592 件(counter 6476→8068)、O は 16 件で、counter の差分・published_ids・ID の一意性で完全性を検査している。開始の counter が違えば compare_reports は不成立になり、ID は付け替えずに全欄を比べる。:788/:1346 の stream の差し替えは follow_event_stream が recent_events から回収して再購読し、existing-defect として残している(PASS にしていない)。EQ3 満たす: 3 API × 6 分類の 18 行で、code・S/K/C の前後・全イベント・X(B,SAVE_LOAD_FAILED) を記録して検査している。NA は source に根拠がある(validate は envelope だけ:simulation_snapshot.gd:16-43。Dictionary API は world.bin を読まない。O は施設が 0 件)。NA でも実際の戻り値を残している。load の失敗で K が変わること(_pause_request_serial 2→4 など)は、既存不具合の候補として残している。EQ4 満たす: E4 の 5 経路と E5 の 16 組を R と O の専用区間で実行し、前後の差と双方向の結果を実際の値で残している。latest/signal の aliasing と cached digest は existing-defect にしている。check_publishes は各 publish を command・event counter・submit に結びつけ、欠落・余分・順序違いで失敗する(r03 の規則の訂正は製品の source に合う)。静的検査で、列挙外の呼出しと hook の差し替えを拒否している。EQ5 満たさない: 同じ版の 2 PID の差は R・O とも 0 件で、各 39 シナリオを実行している。しかし、source の閉包の検査が凍結した driver と verifier につながっておらず、OPT の S を拒否する(finding 1)。EQ6 満たす: 7 phase、PID 7 つ、profile 14 個、cleanup errors は空、source map は 1407 件で 651f7036…、全 raw は seal されている。commit a46418d で、Q で測ったとは書いていない。実行者は Root 役の Desktop 統括(ユーザー委任、実装担当と同じセッション)で、記録どおり。経緯: b2dbda8 の native-verify の失敗(c02eda13…、exit 1、fixture の Operation not permitted)は失敗のまま残っている。a46418d の bundle_inputs で直し、写しが元の入力と同じ bytes と SHA であることを run_eq が検査している(再計算でも一致)。contract の worker は codex のまま、commit は Runner、実装は Opus Desktop という記録は正直。結論: EQ5 が満たされないので changes_requested。原本は 23/88・4/30 のまま、部分点なし。\",\n \"acceptance_ids\": [\n \"P28-02-EQ1\",\n \"P28-02-EQ2\",\n \"P28-02-EQ3\",\n \"P28-02-EQ4\",\n \"P28-02-EQ5\",\n \"P28-02-EQ6\"\n ],\n \"findings\": [\n {\n \"severity\": \"high\",\n \"message\": \"EQ5(OPT の版の間で同等性に使えるか): compare_versions.check_source_closure(compare_versions.py:845)は単体試験でしか呼ばれておらず、run_eq と verify_eq のどちらも使っていない。run_eq.actual_pins(run_eq.py:124)と verify_eq.recompute(verify_eq.py:212)は、source map の digest が before の SOURCE_SHA 651f7036… と完全に一致することを要求している。そのため、登録した OPT の許可差分だけを変えた S でも、admission で 'full 1407 source pin' として拒否される。凍結した参照 OPT_CONTRACT_T1.md の §4 は「OPT の S で、同じコマンドで eq-after-」と定め、§2 は後の版の EQ の bytes が固定の SHA と一致することを求めている。この後の版の実行は、凍結した EQ のファイルを変えない限りできない。つまり、この harness は登録した差分も登録外の差分と同じように拒否し、版の間の E1/E2 の比較に必要な後の記録を作れない。修正案: before の pin はそのまま検査する。後の版は、check_source_closure(固定の before, 実際の after, OPT_PATHS の部分集合として登録した集合) を通った場合だけ受け付ける。その集合と結果を admission に記録し、verify_eq でもう一度検査する。run_eq --check と verify の経路に、登録した差分が通り、追加・欠落・登録外が拒否されることの試験を加える。\"\n },\n {\n \"severity\": \"low\",\n \"message\": \"eq_probe.gd:848 は digest_materialized_before を定数 true として書いており、check_eq.py:1070 の検査は意味を持たない。直前の基準の観測(e3_observation が latest_digest を読む)で digest は実際に materialize されるので、今回の証拠への影響はない。しかし、実際の値(例: _latest_digest_dirty)を記録するべきである。\"\n },\n {\n \"severity\": \"low\",\n \"message\": \"verify の時の run_eq.bundled_inputs(run_eq.py:80-98)は、collector.inputs が固定している manifest の SHA(collect_p28_01.py:252、9dac0a51…)を検査し直さず、束の中の admission の pin に頼っている。また、resolve() しない is_relative_to で判定している。今回は、元の manifest と同梱の manifest がどちらも 9dac0a51…、fixture が eb4f7700…、9 件の入力が全て同じ bytes と SHA であることを再計算で確かめたので、影響はない。\"\n },\n {\n \"severity\": \"low\",\n \"message\": \"束の seal(verify_eq.inventory)はファイルだけを対象にしている。一方で recompute は、空の startup-profile ディレクトリ 7 件があることを要求している(verify_eq.py:259)。このため、正しく seal された束でもファイルだけを写すと検証に失敗する(place_eq_bundle.py を直した理由)。失敗する方向にしか働かないので、誤った合格は生じない。ディレクトリの存在も bundle.json に記録するとよい。\"\n }\n ]\n}\n" + }, + "EQ_S6_AFTER_ADMISSION_DIAG_R01/SUMMARY.json": { + "sha256": "201a8177f53667ec260ed3d176f6d1978f8e80e60a3ff23712da1e8bb731328a", + "bytes": 3368, + "full_unedited": "{\n \"diagnostic_only\": true,\n \"formal_evidence\": false,\n \"what\": \"real run_eq.py --check admission (no mock) on a throwaway after-version checkout\",\n \"checkout\": \"APFS clone of the S6 working tree of the implement worktree, made its own temporary git repository; the managed repository was not touched; removed after the run\",\n \"before_commit\": \"baa96a4483f8020514a057e9f55bd861f439967f\",\n \"after_commit\": \"32725792dee454d5d8b9ae7dfb4de39b0cb51ded\",\n \"opt_change\": \"one comment line appended to autoload/simulation_runtime.gd, committed\",\n \"non_opt_file\": \"scenes/main/world_preview.gd\",\n \"note\": \"non-opt-change-attempt-01 appended to scripts/world/world_preview.gd, which does not exist, so it tested an added file (rejected); non-opt-change repeats it with the existing scenes/main/world_preview.gd (rejected)\",\n \"script_sha256\": \"11e34e02c137017c567a8a497755d17301d398e3238e71ec194f9ab43d4d88ec\",\n \"cases\": {\n \"before-version\": {\n \"exit\": 0,\n \"stdout_sha256\": \"8186b1d43e09db8c27d2db8621b0c4f21c0f6e8b76aa3088dcb7e265d1c2b174\",\n \"stderr_bytes\": 0,\n \"version\": \"before\",\n \"measured_source\": \"S_eq-native-not-Q\",\n \"commit\": \"baa96a4483f8020514a057e9f55bd861f439967f\",\n \"registered_changes\": [],\n \"changed\": [],\n \"added\": [],\n \"missing\": [],\n \"candidate_Q_measured\": false,\n \"phases\": 7\n },\n \"before-with-registration\": {\n \"exit\": 1,\n \"stdout_sha256\": \"c55ad7044b5f9809786d582c3d573f3648a4bbc3f2d2fa191225cf483bba2580\",\n \"stderr_bytes\": 0,\n \"error\": \"source closure: ['source closure mismatch']\"\n },\n \"registered-after\": {\n \"exit\": 0,\n \"stdout_sha256\": \"50f5cf5687c05d12ba6027882bb426490fe7cfddef81fd162988a5ef3a556564\",\n \"stderr_bytes\": 0,\n \"version\": \"after\",\n \"measured_source\": \"S_opt-native-not-Q\",\n \"commit\": \"32725792dee454d5d8b9ae7dfb4de39b0cb51ded\",\n \"registered_changes\": [\n \"autoload/simulation_runtime.gd\"\n ],\n \"changed\": [\n \"autoload/simulation_runtime.gd\"\n ],\n \"added\": [],\n \"missing\": [],\n \"candidate_Q_measured\": false,\n \"phases\": 7\n },\n \"unregistered-change\": {\n \"exit\": 1,\n \"stdout_sha256\": \"c55ad7044b5f9809786d582c3d573f3648a4bbc3f2d2fa191225cf483bba2580\",\n \"stderr_bytes\": 0,\n \"error\": \"source closure: ['source closure mismatch']\"\n },\n \"registered-wrong-file\": {\n \"exit\": 1,\n \"stdout_sha256\": \"c55ad7044b5f9809786d582c3d573f3648a4bbc3f2d2fa191225cf483bba2580\",\n \"stderr_bytes\": 0,\n \"error\": \"source closure: ['source closure mismatch']\"\n },\n \"added-source\": {\n \"exit\": 1,\n \"stdout_sha256\": \"c55ad7044b5f9809786d582c3d573f3648a4bbc3f2d2fa191225cf483bba2580\",\n \"stderr_bytes\": 0,\n \"error\": \"source closure: ['source closure mismatch']\"\n },\n \"non-opt-change-attempt-01-actually-added-file\": {\n \"exit\": 1,\n \"stdout_sha256\": \"c55ad7044b5f9809786d582c3d573f3648a4bbc3f2d2fa191225cf483bba2580\",\n \"stderr_bytes\": 0,\n \"error\": \"source closure: ['source closure mismatch']\"\n },\n \"non-opt-change\": {\n \"exit\": 1,\n \"stdout_sha256\": \"c55ad7044b5f9809786d582c3d573f3648a4bbc3f2d2fa191225cf483bba2580\",\n \"stderr_bytes\": 0,\n \"error\": \"source closure: ['source closure mismatch']\"\n }\n },\n \"engine_started\": false,\n \"original_credit\": 0\n}\n" + } + }, + "note": "Preserved review, decision, plan and diagnostic bytes for review; not a new commander decision. The diagnostic is not formal evidence." + } +} diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT.sha256 index f1c3997..85a5244 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT.sha256 +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT.sha256 @@ -1 +1 @@ -846ab3b45705f269a81181c818dc5e3b8bc0057863794d59e8d641fe5a4e4c32 UNIT_OUTPUT.txt +9dd93de5fd3b66791d6902d51a055caa2c3dd559de6c42019ebb1ab147b2af11 UNIT_OUTPUT.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT.txt index 241027d..fc236b2 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT.txt +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT.txt @@ -149,6 +149,23 @@ test_probe_static_full_tree_blob_and_stream_requirements (__main__.S5.test_probe test_publish_pairs_bound_to_source_causes (__main__.S5.test_publish_pairs_bound_to_source_causes) ... ok test_signed_instance_ids_raw_kept_and_excluded (__main__.S5.test_signed_instance_ids_raw_kept_and_excluded) ... ok test_validate_tree_equals_s1_reference_on_mutations (__main__.S5.test_validate_tree_equals_s1_reference_on_mutations) ... ok +test_bundled_destination_must_be_normalized_inside_readonly (__main__.S6Admission.test_bundled_destination_must_be_normalized_inside_readonly) ... ok +test_check_path_admits_registered_after_version (__main__.S6Admission.test_check_path_admits_registered_after_version) ... ok +test_check_path_rejects_unregistered_or_unchanged (__main__.S6Admission.test_check_path_rejects_unregistered_or_unchanged) ... ok +test_main_passes_sorted_registration_and_records_version (__main__.S6Admission.test_main_passes_sorted_registration_and_records_version) ... ok +test_root_manifest_pin_equals_collector_literal (__main__.S6Admission.test_root_manifest_pin_equals_collector_literal) ... ok +test_after_version_bundle_recomputes (__main__.S6Bundles.test_after_version_bundle_recomputes) ... ok +test_cross_version_comparison (__main__.S6Bundles.test_cross_version_comparison) ... ok +test_cross_version_pin_closure_and_seal_rejections (__main__.S6Bundles.test_cross_version_pin_closure_and_seal_rejections) ... ok +test_cross_version_real_difference_is_not_ok (__main__.S6Bundles.test_cross_version_real_difference_is_not_ok) ... ok +test_recompute_rejects_version_closure_and_label_changes (__main__.S6Bundles.test_recompute_rejects_version_closure_and_label_changes) ... ok +test_digest_state_values (__main__.S6SealAndProbe.test_digest_state_values) ... ok +test_probe_records_actual_digest_state (__main__.S6SealAndProbe.test_probe_records_actual_digest_state) ... ok +test_seal_records_every_directory (__main__.S6SealAndProbe.test_seal_records_every_directory) ... ok +test_admit_before_and_registered_after (__main__.S6SourceClosure.test_admit_before_and_registered_after) ... ok +test_before_map_is_the_frozen_source_map (__main__.S6SourceClosure.test_before_map_is_the_frozen_source_map) ... ok +test_before_map_tampering_rejected (__main__.S6SourceClosure.test_before_map_tampering_rejected) ... ok +test_unregistered_added_missing_and_malformed_registrations_rejected (__main__.S6SourceClosure.test_unregistered_added_missing_and_malformed_registrations_rejected) ... ok test_fixed_scenario_paths (__main__.SourcesAndMetrics.test_fixed_scenario_paths) ... ok test_metric_ranges (__main__.SourcesAndMetrics.test_metric_ranges) ... ok test_source_closure_synthetic_registered_map (__main__.SourcesAndMetrics.test_source_closure_synthetic_registered_map) ... ok @@ -163,6 +180,6 @@ test_nonstring_keys_keep_types_and_values (__main__.TypedTrees.test_nonstring_ke test_unsupported_and_malformed (__main__.TypedTrees.test_unsupported_and_malformed) ... ok ---------------------------------------------------------------------- -Ran 162 tests in 120.853s +Ran 179 tests in 207.351s OK diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S6_ATTEMPT_01.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S6_ATTEMPT_01.sha256 new file mode 100644 index 0000000..2be5663 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S6_ATTEMPT_01.sha256 @@ -0,0 +1 @@ +9dd93de5fd3b66791d6902d51a055caa2c3dd559de6c42019ebb1ab147b2af11 UNIT_OUTPUT_S6_ATTEMPT_01.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S6_ATTEMPT_01.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S6_ATTEMPT_01.txt new file mode 100644 index 0000000..fc236b2 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S6_ATTEMPT_01.txt @@ -0,0 +1,185 @@ +test_all_operations (__main__.Diffs.test_all_operations) ... ok +test_invalid_operations (__main__.Diffs.test_invalid_operations) ... ok +test_reconstruction_and_proofs (__main__.Diffs.test_reconstruction_and_proofs) ... ok +test_attempt_to_normalize_violation_rejected (__main__.Normalization.test_attempt_to_normalize_violation_rejected) ... ok +test_environment_values_differ_but_normal_form_equal (__main__.Normalization.test_environment_values_differ_but_normal_form_equal) ... ok +test_every_save_event_reversible (__main__.Normalization.test_every_save_event_reversible) ... ok +test_f3_keeps_relative_paths_and_words (__main__.Normalization.test_f3_keeps_relative_paths_and_words) ... ok +test_guard_mismatch (__main__.Normalization.test_guard_mismatch) ... ok +test_nested_lookalike_is_not_eligible (__main__.Normalization.test_nested_lookalike_is_not_eligible) ... ok +test_original_transport_sha_detects_forged_timing (__main__.Normalization.test_original_transport_sha_detects_forged_timing) ... ok +test_partial_timing_payload_rejected (__main__.Normalization.test_partial_timing_payload_rejected) ... ok +test_prefix_boundary_and_reserved_token (__main__.Normalization.test_prefix_boundary_and_reserved_token) ... ok +test_sidecar_missing_duplicate_and_forged_paths (__main__.Normalization.test_sidecar_missing_duplicate_and_forged_paths) ... ok +test_snapshot_and_latest_reversible (__main__.Normalization.test_snapshot_and_latest_reversible) ... ok +test_snapshot_event_outside_recent_is_not_eligible (__main__.Normalization.test_snapshot_event_outside_recent_is_not_eligible) ... ok +test_wrong_event_and_source_are_preserved (__main__.Normalization.test_wrong_event_and_source_are_preserved) ... ok +test_wrong_timing_type_and_negative (__main__.Normalization.test_wrong_timing_type_and_negative) ... ok +test_all_events_beyond_recent_window (__main__.Reports.test_all_events_beyond_recent_window) ... ok +test_all_semantic_layers_compared (__main__.Reports.test_all_semantic_layers_compared) ... ok +test_digest_alone_is_not_enough (__main__.Reports.test_digest_alone_is_not_enough) ... ok +test_event_original_types_and_order (__main__.Reports.test_event_original_types_and_order) ... ok +test_event_start_and_ids (__main__.Reports.test_event_start_and_ids) ... ok +test_exclusions_keep_actual_values (__main__.Reports.test_exclusions_keep_actual_values) ... ok +test_handler_sets_and_counts (__main__.Reports.test_handler_sets_and_counts) ... ok +test_observation_full_layers (__main__.Reports.test_observation_full_layers) ... ok +test_product_digest_self_consistency (__main__.Reports.test_product_digest_self_consistency) ... ok +test_same_report (__main__.Reports.test_same_report) ... ok +test_scenario_existing_failures_preserved (__main__.Reports.test_scenario_existing_failures_preserved) ... ok +test_timing_digest_rule (__main__.Reports.test_timing_digest_rule) ... ok +test_unknown_or_missing_fields_rejected (__main__.Reports.test_unknown_or_missing_fields_rejected) ... ok +test_violation_presence_and_difference (__main__.Reports.test_violation_presence_and_difference) ... ok +test_O_cadence (__main__.S2Format.test_O_cadence) ... ok +test_counter_and_published_ids_binding (__main__.S2Format.test_counter_and_published_ids_binding) ... ok +test_diff_and_same_as_S_transport (__main__.S2Format.test_diff_and_same_as_S_transport) ... ok +test_digest_and_scenario_contradiction (__main__.S2Format.test_digest_and_scenario_contradiction) ... ok +test_event_no_drop_duplicate_remap (__main__.S2Format.test_event_no_drop_duplicate_remap) ... ok +test_event_original_field_types_mandatory (__main__.S2Format.test_event_original_field_types_mandatory) ... ok +test_guard_actual_not_assumed (__main__.S2Format.test_guard_actual_not_assumed) ... ok +test_harness_digest_allows_only_dictionary_order (__main__.S2Format.test_harness_digest_allows_only_dictionary_order) ... ok +test_join_is_copy_and_retains_normalization_proof (__main__.S2Format.test_join_is_copy_and_retains_normalization_proof) ... ok +test_kernel_cache_contradictions (__main__.S2Format.test_kernel_cache_contradictions) ... ok +test_lifecycle_guard_errors_and_boundaries (__main__.S2Format.test_lifecycle_guard_errors_and_boundaries) ... ok +test_missing_full_state_not_digest_only (__main__.S2Format.test_missing_full_state_not_digest_only) ... ok +test_normalized_digest_and_raw_tree_are_both_bound (__main__.S2Format.test_normalized_digest_and_raw_tree_are_both_bound) ... ok +test_product_event_shape_and_typed_array (__main__.S2Format.test_product_event_shape_and_typed_array) ... ok +test_raw_observation_binding (__main__.S2Format.test_raw_observation_binding) ... ok +test_roundtrip_tree_sha_and_raw_sha (__main__.S2Format.test_roundtrip_tree_sha_and_raw_sha) ... ok +test_s2_valid_and_not_formal_acceptance (__main__.S2Format.test_s2_valid_and_not_formal_acceptance) ... ok +test_state_witness_and_observation_mutation (__main__.S2Format.test_state_witness_and_observation_mutation) ... ok +test_stdout_exactly_one_line (__main__.S2Format.test_stdout_exactly_one_line) ... ok +test_autoload_class_and_script_import (__main__.S2Static.test_autoload_class_and_script_import) ... ok +test_comment_does_not_supply_proof (__main__.S2Static.test_comment_does_not_supply_proof) ... ok +test_current_probe (__main__.S2Static.test_current_probe) ... ok +test_full_state_and_godot_roundtrip_required (__main__.S2Static.test_full_state_and_godot_roundtrip_required) ... ok +test_no_changes_outside_preparation_or_step (__main__.S2Static.test_no_changes_outside_preparation_or_step) ... ok +test_no_event_cap_or_duplicate_report (__main__.S2Static.test_no_event_cap_or_duplicate_report) ... ok +test_pause_and_step_arguments (__main__.S2Static.test_pause_and_step_arguments) ... ok +test_textual_stringname_ordering (__main__.S2Static.test_textual_stringname_ordering) ... ok +test_unlisted_live_method_and_late_preparation (__main__.S2Static.test_unlisted_live_method_and_late_preparation) ... ok +test_variant_inference (__main__.S2Static.test_variant_inference) ... ok +test_X_recent_limit_and_counter (__main__.S3a.test_X_recent_limit_and_counter) ... ok +test_duplicate_JSON_key_rejected (__main__.S3a.test_duplicate_JSON_key_rejected) ... ok +test_e3_NA_cannot_be_PASS_or_applied (__main__.S3a.test_e3_NA_cannot_be_PASS_or_applied) ... ok +test_e3_coverage_input_and_event_count_binding (__main__.S3a.test_e3_coverage_input_and_event_count_binding) ... ok +test_e3_invented_codes_and_missing_load_code (__main__.S3a.test_e3_invented_codes_and_missing_load_code) ... ok +test_e3_valid_R_and_O_records (__main__.S3a.test_e3_valid_R_and_O_records) ... ok +test_envelope_duplicates_not_defect (__main__.S3a.test_envelope_duplicates_not_defect) ... ok +test_event_count_defect_not_silently_accepted (__main__.S3a.test_event_count_defect_not_silently_accepted) ... ok +test_exact_phase_keys (__main__.S3a.test_exact_phase_keys) ... ok +test_interval_gap_rejected (__main__.S3a.test_interval_gap_rejected) ... ok +test_invalid_input_accepted_is_not_PASS (__main__.S3a.test_invalid_input_accepted_is_not_PASS) ... ok +test_load_payload_and_pause_outcome (__main__.S3a.test_load_payload_and_pause_outcome) ... ok +test_operation_moved_outside_scenario_rejected (__main__.S3a.test_operation_moved_outside_scenario_rejected) ... ok +test_package_fixed_mutations_and_hashes (__main__.S3a.test_package_fixed_mutations_and_hashes) ... ok +test_probe_connection_required (__main__.S3a.test_probe_connection_required) ... ok +test_rejection_mutation_retained_as_defect (__main__.S3a.test_rejection_mutation_retained_as_defect) ... ok +test_save_refusal_makes_load_NA (__main__.S3a.test_save_refusal_makes_load_NA) ... ok +test_scenario_mutation_static_boundary (__main__.S3a.test_scenario_mutation_static_boundary) ... ok +test_signals_all_minutes_and_order (__main__.S3a.test_signals_all_minutes_and_order) ... ok +test_E5_cached_digest_defect_is_comparable (__main__.S3b.test_E5_cached_digest_defect_is_comparable) ... ok +test_NA_not_PASS (__main__.S3b.test_NA_not_PASS) ... ok +test_aliasing_cannot_be_PASS (__main__.S3b.test_aliasing_cannot_be_PASS) ... ok +test_aliasing_missing_record (__main__.S3b.test_aliasing_missing_record) ... ok +test_all_paths_and_ownership_R_O (__main__.S3b.test_all_paths_and_ownership_R_O) ... ok +test_digest_defect_other_checkpoint_still_rejected (__main__.S3b.test_digest_defect_other_checkpoint_still_rejected) ... ok +test_digest_materialization_required (__main__.S3b.test_digest_materialization_required) ... ok +test_empty_registry_not_NA (__main__.S3b.test_empty_registry_not_NA) ... ok +test_event_count_mismatch (__main__.S3b.test_event_count_mismatch) ... ok +test_facts_normalization_is_reversible (__main__.S3b.test_facts_normalization_is_reversible) ... ok +test_first_placeable_choice (__main__.S3b.test_first_placeable_choice) ... ok +test_interval_gap (__main__.S3b.test_interval_gap) ... ok +test_joined_s3b_self_comparison (__main__.S3b.test_joined_s3b_self_comparison) ... ok +test_load_X_not_digest_only (__main__.S3b.test_load_X_not_digest_only) ... ok +test_load_extra_event (__main__.S3b.test_load_extra_event) ... ok +test_missing_path_and_combination (__main__.S3b.test_missing_path_and_combination) ... ok +test_missing_preview_observation (__main__.S3b.test_missing_preview_observation) ... ok +test_missing_trial (__main__.S3b.test_missing_trial) ... ok +test_nested_mutation_required (__main__.S3b.test_nested_mutation_required) ... ok +test_no_staleness_assertion_for_non_tick (__main__.S3b.test_no_staleness_assertion_for_non_tick) ... ok +test_ownership_fact_dictionary_order_fallback (__main__.S3b.test_ownership_fact_dictionary_order_fallback) ... ok +test_path_order (__main__.S3b.test_path_order) ... ok +test_restore_extra_event (__main__.S3b.test_restore_extra_event) ... ok +test_signal_facts_cannot_be_dropped (__main__.S3b.test_signal_facts_cannot_be_dropped) ... ok +test_sort_rule_rejected (__main__.S3b.test_sort_rule_rejected) ... ok +test_static_handler_and_outside_mutations (__main__.S3b.test_static_handler_and_outside_mutations) ... ok +test_unpreviewed_choice (__main__.S3b.test_unpreviewed_choice) ... ok +test_wrong_registry_in_either_role (__main__.S3b.test_wrong_registry_in_either_role) ... ok +test_checkout_temp_destination_rejected (__main__.S4Bundle.test_checkout_temp_destination_rejected) ... ok +test_existing_output_never_overwritten (__main__.S4Bundle.test_existing_output_never_overwritten) ... ok +test_import_closure_rejections (__main__.S4Bundle.test_import_closure_rejections) ... ok +test_missing_bundle_manifest_seal_and_changed_bytes (__main__.S4Bundle.test_missing_bundle_manifest_seal_and_changed_bytes) ... ok +test_missing_private_evidence_and_extra_rejected (__main__.S4Bundle.test_missing_private_evidence_and_extra_rejected) ... ok +test_missing_profile_not_export_success (__main__.S4Bundle.test_missing_profile_not_export_success) ... ok +test_phase_role_pid_audio_and_guard_rejected (__main__.S4Bundle.test_phase_role_pid_audio_and_guard_rejected) ... ok +test_rebound_lifecycle_and_scenario_contradictions (__main__.S4Bundle.test_rebound_lifecycle_and_scenario_contradictions) ... ok +test_seal_normal_and_changes_not_native_proof (__main__.S4Bundle.test_seal_normal_and_changes_not_native_proof) ... ok +test_synthetic_phase_all_real_checkers_not_native_proof (__main__.S4Bundle.test_synthetic_phase_all_real_checkers_not_native_proof) ... ok +test_copied_manifest_root_and_destination_count_rejected (__main__.S4NativeBundleLogic.test_copied_manifest_root_and_destination_count_rejected) ... ok +test_failure_keeps_raw_and_no_bundle_without_starting_engine (__main__.S4NativeBundleLogic.test_failure_keeps_raw_and_no_bundle_without_starting_engine) ... ok +test_gate_none_success_not_boolean (__main__.S4NativeBundleLogic.test_gate_none_success_not_boolean) ... ok +test_receipt_and_source_rejection_matrix (__main__.S4NativeBundleLogic.test_receipt_and_source_rejection_matrix) ... ok +test_synthetic_full_bundle_positive_not_native_evidence (__main__.S4NativeBundleLogic.test_synthetic_full_bundle_positive_not_native_evidence) ... ok +test_check_accepts_true (__main__.S4ProbeAdmission.test_check_accepts_true) ... ok +test_check_rejects_false_all_errors (__main__.S4ProbeAdmission.test_check_rejects_false_all_errors) ... ok +test_run_admission_accepts_true_mock_launch_only (__main__.S4ProbeAdmission.test_run_admission_accepts_true_mock_launch_only) ... ok +test_run_admission_rejects_false_without_engine (__main__.S4ProbeAdmission.test_run_admission_rejects_false_without_engine) ... ok +test_nine_original_destinations_required (__main__.S4RemainingBindings.test_nine_original_destinations_required) ... ok +test_nonzero_determinism_rejected_after_real_join (__main__.S4RemainingBindings.test_nonzero_determinism_rejected_after_real_join) ... ok +test_owned_lifecycle_exit_diagnostic_and_profile_rejections (__main__.S4RemainingBindings.test_owned_lifecycle_exit_diagnostic_and_profile_rejections) ... ok +test_verifier_accepts_true_recomputes_raw (__main__.S4RemainingBindings.test_verifier_accepts_true_recomputes_raw) ... ok +test_verifier_rejects_false_with_every_error (__main__.S4RemainingBindings.test_verifier_rejects_false_with_every_error) ... ok +test_cached_verdict_not_trusted (__main__.S4StoredResultBindings.test_cached_verdict_not_trusted) ... ok +test_missing_sidecar_rejected_after_seal (__main__.S4StoredResultBindings.test_missing_sidecar_rejected_after_seal) ... ok +test_raw_joined_substitution_rejected_after_seal (__main__.S4StoredResultBindings.test_raw_joined_substitution_rejected_after_seal) ... ok +test_blob_transport_is_verified_and_bound (__main__.S5.test_blob_transport_is_verified_and_bound) ... ok +test_blob_trees_get_the_same_full_validation_as_inline (__main__.S5.test_blob_trees_get_the_same_full_validation_as_inline) ... ok +test_bundled_inputs_replace_unreadable_originals (__main__.S5.test_bundled_inputs_replace_unreadable_originals) ... ok +test_compare_and_digest_equal_s1_reference (__main__.S5.test_compare_and_digest_equal_s1_reference) ... ok +test_event_stream_replacement_is_existing_defect_not_pass (__main__.S5.test_event_stream_replacement_is_existing_defect_not_pass) ... ok +test_every_checkpoint_full_tree_verified_like_inline (__main__.S5.test_every_checkpoint_full_tree_verified_like_inline) +S5 drops the diff chain: each checkpoint carries a complete tree, verified alone. ... ok +test_fast_normalization_equals_original (__main__.S5.test_fast_normalization_equals_original) ... ok +test_labelled_harness_digest_falls_back_to_dictionary_order_only (__main__.S5.test_labelled_harness_digest_falls_back_to_dictionary_order_only) ... ok +test_lifecycle_binds_replacements_guard_text_and_blobs (__main__.S5.test_lifecycle_binds_replacements_guard_text_and_blobs) ... ok +test_manifest_numbers_keep_their_type (__main__.S5.test_manifest_numbers_keep_their_type) ... ok +test_memo_scope_same_results_and_restores_gc (__main__.S5.test_memo_scope_same_results_and_restores_gc) ... ok +test_path_copy_builders_equal_deepcopy_reference (__main__.S5.test_path_copy_builders_equal_deepcopy_reference) ... ok +test_probe_static_full_tree_blob_and_stream_requirements (__main__.S5.test_probe_static_full_tree_blob_and_stream_requirements) ... ok +test_publish_pairs_bound_to_source_causes (__main__.S5.test_publish_pairs_bound_to_source_causes) ... ok +test_signed_instance_ids_raw_kept_and_excluded (__main__.S5.test_signed_instance_ids_raw_kept_and_excluded) ... ok +test_validate_tree_equals_s1_reference_on_mutations (__main__.S5.test_validate_tree_equals_s1_reference_on_mutations) ... ok +test_bundled_destination_must_be_normalized_inside_readonly (__main__.S6Admission.test_bundled_destination_must_be_normalized_inside_readonly) ... ok +test_check_path_admits_registered_after_version (__main__.S6Admission.test_check_path_admits_registered_after_version) ... ok +test_check_path_rejects_unregistered_or_unchanged (__main__.S6Admission.test_check_path_rejects_unregistered_or_unchanged) ... ok +test_main_passes_sorted_registration_and_records_version (__main__.S6Admission.test_main_passes_sorted_registration_and_records_version) ... ok +test_root_manifest_pin_equals_collector_literal (__main__.S6Admission.test_root_manifest_pin_equals_collector_literal) ... ok +test_after_version_bundle_recomputes (__main__.S6Bundles.test_after_version_bundle_recomputes) ... ok +test_cross_version_comparison (__main__.S6Bundles.test_cross_version_comparison) ... ok +test_cross_version_pin_closure_and_seal_rejections (__main__.S6Bundles.test_cross_version_pin_closure_and_seal_rejections) ... ok +test_cross_version_real_difference_is_not_ok (__main__.S6Bundles.test_cross_version_real_difference_is_not_ok) ... ok +test_recompute_rejects_version_closure_and_label_changes (__main__.S6Bundles.test_recompute_rejects_version_closure_and_label_changes) ... ok +test_digest_state_values (__main__.S6SealAndProbe.test_digest_state_values) ... ok +test_probe_records_actual_digest_state (__main__.S6SealAndProbe.test_probe_records_actual_digest_state) ... ok +test_seal_records_every_directory (__main__.S6SealAndProbe.test_seal_records_every_directory) ... ok +test_admit_before_and_registered_after (__main__.S6SourceClosure.test_admit_before_and_registered_after) ... ok +test_before_map_is_the_frozen_source_map (__main__.S6SourceClosure.test_before_map_is_the_frozen_source_map) ... ok +test_before_map_tampering_rejected (__main__.S6SourceClosure.test_before_map_tampering_rejected) ... ok +test_unregistered_added_missing_and_malformed_registrations_rejected (__main__.S6SourceClosure.test_unregistered_added_missing_and_malformed_registrations_rejected) ... ok +test_fixed_scenario_paths (__main__.SourcesAndMetrics.test_fixed_scenario_paths) ... ok +test_metric_ranges (__main__.SourcesAndMetrics.test_metric_ranges) ... ok +test_source_closure_synthetic_registered_map (__main__.SourcesAndMetrics.test_source_closure_synthetic_registered_map) ... ok +test_source_pin_is_not_caller_controlled (__main__.SourcesAndMetrics.test_source_pin_is_not_caller_controlled) ... ok +test_array_order_and_all_differences (__main__.TypedTrees.test_array_order_and_all_differences) ... ok +test_components_and_sha (__main__.TypedTrees.test_components_and_sha) ... ok +test_deep_state_not_truncated (__main__.TypedTrees.test_deep_state_not_truncated) ... ok +test_duplicate_textual_keys_rejected (__main__.TypedTrees.test_duplicate_textual_keys_rejected) ... ok +test_exact_and_types (__main__.TypedTrees.test_exact_and_types) ... ok +test_nested_order_all_paths (__main__.TypedTrees.test_nested_order_all_paths) ... ok +test_nonstring_keys_keep_types_and_values (__main__.TypedTrees.test_nonstring_keys_keep_types_and_values) ... ok +test_unsupported_and_malformed (__main__.TypedTrees.test_unsupported_and_malformed) ... ok + +---------------------------------------------------------------------- +Ran 179 tests in 207.351s + +OK diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S6_SEATBELT_01.sha256 b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S6_SEATBELT_01.sha256 new file mode 100644 index 0000000..801880e --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S6_SEATBELT_01.sha256 @@ -0,0 +1 @@ +be2dd93c3cbb44b3ac74ab003f11ba368da3f4009b3b5595336f591dff52cceb UNIT_OUTPUT_S6_SEATBELT_01.txt diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S6_SEATBELT_01.txt b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S6_SEATBELT_01.txt new file mode 100644 index 0000000..b2ae828 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/UNIT_OUTPUT_S6_SEATBELT_01.txt @@ -0,0 +1,185 @@ +test_all_operations (__main__.Diffs.test_all_operations) ... ok +test_invalid_operations (__main__.Diffs.test_invalid_operations) ... ok +test_reconstruction_and_proofs (__main__.Diffs.test_reconstruction_and_proofs) ... ok +test_attempt_to_normalize_violation_rejected (__main__.Normalization.test_attempt_to_normalize_violation_rejected) ... ok +test_environment_values_differ_but_normal_form_equal (__main__.Normalization.test_environment_values_differ_but_normal_form_equal) ... ok +test_every_save_event_reversible (__main__.Normalization.test_every_save_event_reversible) ... ok +test_f3_keeps_relative_paths_and_words (__main__.Normalization.test_f3_keeps_relative_paths_and_words) ... ok +test_guard_mismatch (__main__.Normalization.test_guard_mismatch) ... ok +test_nested_lookalike_is_not_eligible (__main__.Normalization.test_nested_lookalike_is_not_eligible) ... ok +test_original_transport_sha_detects_forged_timing (__main__.Normalization.test_original_transport_sha_detects_forged_timing) ... ok +test_partial_timing_payload_rejected (__main__.Normalization.test_partial_timing_payload_rejected) ... ok +test_prefix_boundary_and_reserved_token (__main__.Normalization.test_prefix_boundary_and_reserved_token) ... ok +test_sidecar_missing_duplicate_and_forged_paths (__main__.Normalization.test_sidecar_missing_duplicate_and_forged_paths) ... ok +test_snapshot_and_latest_reversible (__main__.Normalization.test_snapshot_and_latest_reversible) ... ok +test_snapshot_event_outside_recent_is_not_eligible (__main__.Normalization.test_snapshot_event_outside_recent_is_not_eligible) ... ok +test_wrong_event_and_source_are_preserved (__main__.Normalization.test_wrong_event_and_source_are_preserved) ... ok +test_wrong_timing_type_and_negative (__main__.Normalization.test_wrong_timing_type_and_negative) ... ok +test_all_events_beyond_recent_window (__main__.Reports.test_all_events_beyond_recent_window) ... ok +test_all_semantic_layers_compared (__main__.Reports.test_all_semantic_layers_compared) ... ok +test_digest_alone_is_not_enough (__main__.Reports.test_digest_alone_is_not_enough) ... ok +test_event_original_types_and_order (__main__.Reports.test_event_original_types_and_order) ... ok +test_event_start_and_ids (__main__.Reports.test_event_start_and_ids) ... ok +test_exclusions_keep_actual_values (__main__.Reports.test_exclusions_keep_actual_values) ... ok +test_handler_sets_and_counts (__main__.Reports.test_handler_sets_and_counts) ... ok +test_observation_full_layers (__main__.Reports.test_observation_full_layers) ... ok +test_product_digest_self_consistency (__main__.Reports.test_product_digest_self_consistency) ... ok +test_same_report (__main__.Reports.test_same_report) ... ok +test_scenario_existing_failures_preserved (__main__.Reports.test_scenario_existing_failures_preserved) ... ok +test_timing_digest_rule (__main__.Reports.test_timing_digest_rule) ... ok +test_unknown_or_missing_fields_rejected (__main__.Reports.test_unknown_or_missing_fields_rejected) ... ok +test_violation_presence_and_difference (__main__.Reports.test_violation_presence_and_difference) ... ok +test_O_cadence (__main__.S2Format.test_O_cadence) ... ok +test_counter_and_published_ids_binding (__main__.S2Format.test_counter_and_published_ids_binding) ... ok +test_diff_and_same_as_S_transport (__main__.S2Format.test_diff_and_same_as_S_transport) ... ok +test_digest_and_scenario_contradiction (__main__.S2Format.test_digest_and_scenario_contradiction) ... ok +test_event_no_drop_duplicate_remap (__main__.S2Format.test_event_no_drop_duplicate_remap) ... ok +test_event_original_field_types_mandatory (__main__.S2Format.test_event_original_field_types_mandatory) ... ok +test_guard_actual_not_assumed (__main__.S2Format.test_guard_actual_not_assumed) ... ok +test_harness_digest_allows_only_dictionary_order (__main__.S2Format.test_harness_digest_allows_only_dictionary_order) ... ok +test_join_is_copy_and_retains_normalization_proof (__main__.S2Format.test_join_is_copy_and_retains_normalization_proof) ... ok +test_kernel_cache_contradictions (__main__.S2Format.test_kernel_cache_contradictions) ... ok +test_lifecycle_guard_errors_and_boundaries (__main__.S2Format.test_lifecycle_guard_errors_and_boundaries) ... ok +test_missing_full_state_not_digest_only (__main__.S2Format.test_missing_full_state_not_digest_only) ... ok +test_normalized_digest_and_raw_tree_are_both_bound (__main__.S2Format.test_normalized_digest_and_raw_tree_are_both_bound) ... ok +test_product_event_shape_and_typed_array (__main__.S2Format.test_product_event_shape_and_typed_array) ... ok +test_raw_observation_binding (__main__.S2Format.test_raw_observation_binding) ... ok +test_roundtrip_tree_sha_and_raw_sha (__main__.S2Format.test_roundtrip_tree_sha_and_raw_sha) ... ok +test_s2_valid_and_not_formal_acceptance (__main__.S2Format.test_s2_valid_and_not_formal_acceptance) ... ok +test_state_witness_and_observation_mutation (__main__.S2Format.test_state_witness_and_observation_mutation) ... ok +test_stdout_exactly_one_line (__main__.S2Format.test_stdout_exactly_one_line) ... ok +test_autoload_class_and_script_import (__main__.S2Static.test_autoload_class_and_script_import) ... ok +test_comment_does_not_supply_proof (__main__.S2Static.test_comment_does_not_supply_proof) ... ok +test_current_probe (__main__.S2Static.test_current_probe) ... ok +test_full_state_and_godot_roundtrip_required (__main__.S2Static.test_full_state_and_godot_roundtrip_required) ... ok +test_no_changes_outside_preparation_or_step (__main__.S2Static.test_no_changes_outside_preparation_or_step) ... ok +test_no_event_cap_or_duplicate_report (__main__.S2Static.test_no_event_cap_or_duplicate_report) ... ok +test_pause_and_step_arguments (__main__.S2Static.test_pause_and_step_arguments) ... ok +test_textual_stringname_ordering (__main__.S2Static.test_textual_stringname_ordering) ... ok +test_unlisted_live_method_and_late_preparation (__main__.S2Static.test_unlisted_live_method_and_late_preparation) ... ok +test_variant_inference (__main__.S2Static.test_variant_inference) ... ok +test_X_recent_limit_and_counter (__main__.S3a.test_X_recent_limit_and_counter) ... ok +test_duplicate_JSON_key_rejected (__main__.S3a.test_duplicate_JSON_key_rejected) ... ok +test_e3_NA_cannot_be_PASS_or_applied (__main__.S3a.test_e3_NA_cannot_be_PASS_or_applied) ... ok +test_e3_coverage_input_and_event_count_binding (__main__.S3a.test_e3_coverage_input_and_event_count_binding) ... ok +test_e3_invented_codes_and_missing_load_code (__main__.S3a.test_e3_invented_codes_and_missing_load_code) ... ok +test_e3_valid_R_and_O_records (__main__.S3a.test_e3_valid_R_and_O_records) ... ok +test_envelope_duplicates_not_defect (__main__.S3a.test_envelope_duplicates_not_defect) ... ok +test_event_count_defect_not_silently_accepted (__main__.S3a.test_event_count_defect_not_silently_accepted) ... ok +test_exact_phase_keys (__main__.S3a.test_exact_phase_keys) ... ok +test_interval_gap_rejected (__main__.S3a.test_interval_gap_rejected) ... ok +test_invalid_input_accepted_is_not_PASS (__main__.S3a.test_invalid_input_accepted_is_not_PASS) ... ok +test_load_payload_and_pause_outcome (__main__.S3a.test_load_payload_and_pause_outcome) ... ok +test_operation_moved_outside_scenario_rejected (__main__.S3a.test_operation_moved_outside_scenario_rejected) ... ok +test_package_fixed_mutations_and_hashes (__main__.S3a.test_package_fixed_mutations_and_hashes) ... ok +test_probe_connection_required (__main__.S3a.test_probe_connection_required) ... ok +test_rejection_mutation_retained_as_defect (__main__.S3a.test_rejection_mutation_retained_as_defect) ... ok +test_save_refusal_makes_load_NA (__main__.S3a.test_save_refusal_makes_load_NA) ... ok +test_scenario_mutation_static_boundary (__main__.S3a.test_scenario_mutation_static_boundary) ... ok +test_signals_all_minutes_and_order (__main__.S3a.test_signals_all_minutes_and_order) ... ok +test_E5_cached_digest_defect_is_comparable (__main__.S3b.test_E5_cached_digest_defect_is_comparable) ... ok +test_NA_not_PASS (__main__.S3b.test_NA_not_PASS) ... ok +test_aliasing_cannot_be_PASS (__main__.S3b.test_aliasing_cannot_be_PASS) ... ok +test_aliasing_missing_record (__main__.S3b.test_aliasing_missing_record) ... ok +test_all_paths_and_ownership_R_O (__main__.S3b.test_all_paths_and_ownership_R_O) ... ok +test_digest_defect_other_checkpoint_still_rejected (__main__.S3b.test_digest_defect_other_checkpoint_still_rejected) ... ok +test_digest_materialization_required (__main__.S3b.test_digest_materialization_required) ... ok +test_empty_registry_not_NA (__main__.S3b.test_empty_registry_not_NA) ... ok +test_event_count_mismatch (__main__.S3b.test_event_count_mismatch) ... ok +test_facts_normalization_is_reversible (__main__.S3b.test_facts_normalization_is_reversible) ... ok +test_first_placeable_choice (__main__.S3b.test_first_placeable_choice) ... ok +test_interval_gap (__main__.S3b.test_interval_gap) ... ok +test_joined_s3b_self_comparison (__main__.S3b.test_joined_s3b_self_comparison) ... ok +test_load_X_not_digest_only (__main__.S3b.test_load_X_not_digest_only) ... ok +test_load_extra_event (__main__.S3b.test_load_extra_event) ... ok +test_missing_path_and_combination (__main__.S3b.test_missing_path_and_combination) ... ok +test_missing_preview_observation (__main__.S3b.test_missing_preview_observation) ... ok +test_missing_trial (__main__.S3b.test_missing_trial) ... ok +test_nested_mutation_required (__main__.S3b.test_nested_mutation_required) ... ok +test_no_staleness_assertion_for_non_tick (__main__.S3b.test_no_staleness_assertion_for_non_tick) ... ok +test_ownership_fact_dictionary_order_fallback (__main__.S3b.test_ownership_fact_dictionary_order_fallback) ... ok +test_path_order (__main__.S3b.test_path_order) ... ok +test_restore_extra_event (__main__.S3b.test_restore_extra_event) ... ok +test_signal_facts_cannot_be_dropped (__main__.S3b.test_signal_facts_cannot_be_dropped) ... ok +test_sort_rule_rejected (__main__.S3b.test_sort_rule_rejected) ... ok +test_static_handler_and_outside_mutations (__main__.S3b.test_static_handler_and_outside_mutations) ... ok +test_unpreviewed_choice (__main__.S3b.test_unpreviewed_choice) ... ok +test_wrong_registry_in_either_role (__main__.S3b.test_wrong_registry_in_either_role) ... ok +test_checkout_temp_destination_rejected (__main__.S4Bundle.test_checkout_temp_destination_rejected) ... ok +test_existing_output_never_overwritten (__main__.S4Bundle.test_existing_output_never_overwritten) ... ok +test_import_closure_rejections (__main__.S4Bundle.test_import_closure_rejections) ... ok +test_missing_bundle_manifest_seal_and_changed_bytes (__main__.S4Bundle.test_missing_bundle_manifest_seal_and_changed_bytes) ... ok +test_missing_private_evidence_and_extra_rejected (__main__.S4Bundle.test_missing_private_evidence_and_extra_rejected) ... ok +test_missing_profile_not_export_success (__main__.S4Bundle.test_missing_profile_not_export_success) ... ok +test_phase_role_pid_audio_and_guard_rejected (__main__.S4Bundle.test_phase_role_pid_audio_and_guard_rejected) ... ok +test_rebound_lifecycle_and_scenario_contradictions (__main__.S4Bundle.test_rebound_lifecycle_and_scenario_contradictions) ... ok +test_seal_normal_and_changes_not_native_proof (__main__.S4Bundle.test_seal_normal_and_changes_not_native_proof) ... ok +test_synthetic_phase_all_real_checkers_not_native_proof (__main__.S4Bundle.test_synthetic_phase_all_real_checkers_not_native_proof) ... ok +test_copied_manifest_root_and_destination_count_rejected (__main__.S4NativeBundleLogic.test_copied_manifest_root_and_destination_count_rejected) ... ok +test_failure_keeps_raw_and_no_bundle_without_starting_engine (__main__.S4NativeBundleLogic.test_failure_keeps_raw_and_no_bundle_without_starting_engine) ... ok +test_gate_none_success_not_boolean (__main__.S4NativeBundleLogic.test_gate_none_success_not_boolean) ... ok +test_receipt_and_source_rejection_matrix (__main__.S4NativeBundleLogic.test_receipt_and_source_rejection_matrix) ... ok +test_synthetic_full_bundle_positive_not_native_evidence (__main__.S4NativeBundleLogic.test_synthetic_full_bundle_positive_not_native_evidence) ... ok +test_check_accepts_true (__main__.S4ProbeAdmission.test_check_accepts_true) ... ok +test_check_rejects_false_all_errors (__main__.S4ProbeAdmission.test_check_rejects_false_all_errors) ... ok +test_run_admission_accepts_true_mock_launch_only (__main__.S4ProbeAdmission.test_run_admission_accepts_true_mock_launch_only) ... ok +test_run_admission_rejects_false_without_engine (__main__.S4ProbeAdmission.test_run_admission_rejects_false_without_engine) ... ok +test_nine_original_destinations_required (__main__.S4RemainingBindings.test_nine_original_destinations_required) ... ok +test_nonzero_determinism_rejected_after_real_join (__main__.S4RemainingBindings.test_nonzero_determinism_rejected_after_real_join) ... ok +test_owned_lifecycle_exit_diagnostic_and_profile_rejections (__main__.S4RemainingBindings.test_owned_lifecycle_exit_diagnostic_and_profile_rejections) ... ok +test_verifier_accepts_true_recomputes_raw (__main__.S4RemainingBindings.test_verifier_accepts_true_recomputes_raw) ... ok +test_verifier_rejects_false_with_every_error (__main__.S4RemainingBindings.test_verifier_rejects_false_with_every_error) ... ok +test_cached_verdict_not_trusted (__main__.S4StoredResultBindings.test_cached_verdict_not_trusted) ... ok +test_missing_sidecar_rejected_after_seal (__main__.S4StoredResultBindings.test_missing_sidecar_rejected_after_seal) ... ok +test_raw_joined_substitution_rejected_after_seal (__main__.S4StoredResultBindings.test_raw_joined_substitution_rejected_after_seal) ... ok +test_blob_transport_is_verified_and_bound (__main__.S5.test_blob_transport_is_verified_and_bound) ... ok +test_blob_trees_get_the_same_full_validation_as_inline (__main__.S5.test_blob_trees_get_the_same_full_validation_as_inline) ... ok +test_bundled_inputs_replace_unreadable_originals (__main__.S5.test_bundled_inputs_replace_unreadable_originals) ... ok +test_compare_and_digest_equal_s1_reference (__main__.S5.test_compare_and_digest_equal_s1_reference) ... ok +test_event_stream_replacement_is_existing_defect_not_pass (__main__.S5.test_event_stream_replacement_is_existing_defect_not_pass) ... ok +test_every_checkpoint_full_tree_verified_like_inline (__main__.S5.test_every_checkpoint_full_tree_verified_like_inline) +S5 drops the diff chain: each checkpoint carries a complete tree, verified alone. ... ok +test_fast_normalization_equals_original (__main__.S5.test_fast_normalization_equals_original) ... ok +test_labelled_harness_digest_falls_back_to_dictionary_order_only (__main__.S5.test_labelled_harness_digest_falls_back_to_dictionary_order_only) ... ok +test_lifecycle_binds_replacements_guard_text_and_blobs (__main__.S5.test_lifecycle_binds_replacements_guard_text_and_blobs) ... ok +test_manifest_numbers_keep_their_type (__main__.S5.test_manifest_numbers_keep_their_type) ... ok +test_memo_scope_same_results_and_restores_gc (__main__.S5.test_memo_scope_same_results_and_restores_gc) ... ok +test_path_copy_builders_equal_deepcopy_reference (__main__.S5.test_path_copy_builders_equal_deepcopy_reference) ... ok +test_probe_static_full_tree_blob_and_stream_requirements (__main__.S5.test_probe_static_full_tree_blob_and_stream_requirements) ... ok +test_publish_pairs_bound_to_source_causes (__main__.S5.test_publish_pairs_bound_to_source_causes) ... ok +test_signed_instance_ids_raw_kept_and_excluded (__main__.S5.test_signed_instance_ids_raw_kept_and_excluded) ... ok +test_validate_tree_equals_s1_reference_on_mutations (__main__.S5.test_validate_tree_equals_s1_reference_on_mutations) ... ok +test_bundled_destination_must_be_normalized_inside_readonly (__main__.S6Admission.test_bundled_destination_must_be_normalized_inside_readonly) ... ok +test_check_path_admits_registered_after_version (__main__.S6Admission.test_check_path_admits_registered_after_version) ... ok +test_check_path_rejects_unregistered_or_unchanged (__main__.S6Admission.test_check_path_rejects_unregistered_or_unchanged) ... ok +test_main_passes_sorted_registration_and_records_version (__main__.S6Admission.test_main_passes_sorted_registration_and_records_version) ... ok +test_root_manifest_pin_equals_collector_literal (__main__.S6Admission.test_root_manifest_pin_equals_collector_literal) ... ok +test_after_version_bundle_recomputes (__main__.S6Bundles.test_after_version_bundle_recomputes) ... ok +test_cross_version_comparison (__main__.S6Bundles.test_cross_version_comparison) ... ok +test_cross_version_pin_closure_and_seal_rejections (__main__.S6Bundles.test_cross_version_pin_closure_and_seal_rejections) ... ok +test_cross_version_real_difference_is_not_ok (__main__.S6Bundles.test_cross_version_real_difference_is_not_ok) ... ok +test_recompute_rejects_version_closure_and_label_changes (__main__.S6Bundles.test_recompute_rejects_version_closure_and_label_changes) ... ok +test_digest_state_values (__main__.S6SealAndProbe.test_digest_state_values) ... ok +test_probe_records_actual_digest_state (__main__.S6SealAndProbe.test_probe_records_actual_digest_state) ... ok +test_seal_records_every_directory (__main__.S6SealAndProbe.test_seal_records_every_directory) ... ok +test_admit_before_and_registered_after (__main__.S6SourceClosure.test_admit_before_and_registered_after) ... ok +test_before_map_is_the_frozen_source_map (__main__.S6SourceClosure.test_before_map_is_the_frozen_source_map) ... ok +test_before_map_tampering_rejected (__main__.S6SourceClosure.test_before_map_tampering_rejected) ... ok +test_unregistered_added_missing_and_malformed_registrations_rejected (__main__.S6SourceClosure.test_unregistered_added_missing_and_malformed_registrations_rejected) ... ok +test_fixed_scenario_paths (__main__.SourcesAndMetrics.test_fixed_scenario_paths) ... ok +test_metric_ranges (__main__.SourcesAndMetrics.test_metric_ranges) ... ok +test_source_closure_synthetic_registered_map (__main__.SourcesAndMetrics.test_source_closure_synthetic_registered_map) ... ok +test_source_pin_is_not_caller_controlled (__main__.SourcesAndMetrics.test_source_pin_is_not_caller_controlled) ... ok +test_array_order_and_all_differences (__main__.TypedTrees.test_array_order_and_all_differences) ... ok +test_components_and_sha (__main__.TypedTrees.test_components_and_sha) ... ok +test_deep_state_not_truncated (__main__.TypedTrees.test_deep_state_not_truncated) ... ok +test_duplicate_textual_keys_rejected (__main__.TypedTrees.test_duplicate_textual_keys_rejected) ... ok +test_exact_and_types (__main__.TypedTrees.test_exact_and_types) ... ok +test_nested_order_all_paths (__main__.TypedTrees.test_nested_order_all_paths) ... ok +test_nonstring_keys_keep_types_and_values (__main__.TypedTrees.test_nonstring_keys_keep_types_and_values) ... ok +test_unsupported_and_malformed (__main__.TypedTrees.test_unsupported_and_malformed) ... ok + +---------------------------------------------------------------------- +Ran 179 tests in 206.326s + +OK diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/check_eq.py b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/check_eq.py index 6961ded..e1ee474 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/check_eq.py +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/check_eq.py @@ -973,7 +973,7 @@ def _check_e45(raw, evidence, previous): obs, detail = ev['observations'], ev['detail'] eq.require(eq.exact(detail['signals'], ev['signals']), 'scenario signals/facts binding') if scenario['id'].startswith('E5/'): - eq.require(set(detail) == {'target', 'location', 'direction', 'digest_materialized_before', 'held_before', 'held_after', 'signals'}, 'E5 detail fields') + eq.require(set(detail) == {'target', 'location', 'direction', 'latest_digest_dirty_before', 'held_before', 'held_after', 'signals'}, 'E5 detail fields') else: common = {'save_budget_before', 'save_budget_after', 'signals'} specific = { @@ -1067,7 +1067,9 @@ def _check_e45(raw, evidence, previous): _, target, location, direction = scenario['id'].split('/') eq.require(op == direction and all(detail[k] == v for k, v in [('target', target), ('location', location), ('direction', direction)]), 'E5 target/direction') eq.require(result['applicability'] == 'applied' and result['reason'] is None and len(obs) == 4, 'E5 coverage/NA') - eq.require(detail['digest_materialized_before'] is True, 'E5 digest not materialized') + # S6: the probe records the product's actual _latest_digest_dirty before the operation; + # false (materialized) or null (this version has no such field) only. + eq.require(detail['latest_digest_dirty_before'] is False or detail['latest_digest_dirty_before'] is None, 'E5 digest not materialized') minutes = [o['checkpoint']['minute'] for o in obs] eq.require(minutes == [minutes[0], minutes[0]+1, minutes[0]+1+int(direction == 'inside_out'), minutes[0]+2+int(direction == 'inside_out')], 'E5 preparation/operation/reset tick sequence') held = eq._transport(detail['held_before'], None) diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py index 982e092..968be3a 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/compare_versions.py @@ -863,6 +863,44 @@ def check_source_closure(before_map, after_map, allowed_changed): return {'ok': not errors, 'errors': errors, 'before_sha256': digest, 'added': added, 'missing': missing, 'changed': changed, 'allowed_changed': sorted(allowed)} +# S6 (EQ_S6_AFTER_VERSION_PLAN): the fixed "before" of the source closure. The file holds +# the registered base product source map; SOURCE_SHA fixes its meaning, so it is checked +# on every read rather than trusted. +BEFORE_SOURCE_MAP = Path(__file__).resolve().parent / 'BEFORE_SOURCE_MAP.json' + + +def _unique_object(pairs): + keys = [key for key, _ in pairs] + require(len(keys) == len(set(keys)), 'duplicate JSON key') + return dict(pairs) + + +def before_source_map(): + value = json.loads(BEFORE_SOURCE_MAP.read_text(encoding='utf-8'), object_pairs_hook=_unique_object) + require(type(value) is dict and len(value) == 1407, 'before map is not 1407 sources') + for name, row in value.items(): + require(type(row) is dict and set(row) == {'bytes', 'sha256'} and type(row['bytes']) is int and + type(row['sha256']) is str and re.fullmatch('[0-9a-f]{64}', row['sha256']), 'before map row') + digest = hashlib.sha256(json.dumps(value, sort_keys=True, separators=(',', ':')).encode()).hexdigest() + require(digest == SOURCE_SHA, 'before map is not the frozen 1407-source map') + return value + + +def admit_source(source, registered): + """Admission rule of both versions (OPT_CONTRACT_T1 sections 2 and 4). + + registered is the sorted, duplicate-free list of OPT files the version changes. Empty + means the before version (no difference from the frozen map, as SOURCE_SHA required + before S6); otherwise the after version, whose changed set must equal registered with + no added or missing source. Anything else is rejected with every closure error.""" + require(type(registered) is list and all(type(p) is str for p in registered), 'registered change list required') + require(registered == sorted(set(registered)), 'registered changes must be sorted and unique') + closure = check_source_closure(before_source_map(), source, registered) + require(closure['ok'], 'source closure: ' + repr(closure['errors'])) + after = hashlib.sha256(json.dumps(source, sort_keys=True, separators=(',', ':')).encode()).hexdigest() + return dict(closure, version='after' if registered else 'before', after_sha256=after) + + K_COMPARE = frozenset(('absolute_minute', 'speed', 'paused', 'snapshot_version', '_accumulator', '_skip_next_process', '_pause_request_serial', '_abort_current_tick_requested', '_last_tick_advanced', '_phase_handlers')) diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/eq_probe.gd b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/eq_probe.gd index 89a46ba..74ddc8e 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/eq_probe.gd +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/eq_probe.gd @@ -844,8 +844,9 @@ func run_e5() -> void: "snapshot_published": returned = snapshot_reference "state_updated": returned = state_reference var held_copy: Dictionary = returned.duplicate(true) + # S6: the actual digest state just before the operation (null if this version has no such field). var detail: Dictionary = {"target": target, "location": location, "direction": direction, - "digest_materialized_before": true, "held_before": transport(held_copy)} + "latest_digest_dirty_before": runtime.get("_latest_digest_dirty"), "held_before": transport(held_copy)} if direction == "outside_in": if location == "dict": returned[&"systems"][&"runtime"][&"id_generator"][&"counters"]["__p28_eq_probe"] = 1 diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/run_eq.py b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/run_eq.py index 4e4f1b5..1287eab 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/run_eq.py +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/run_eq.py @@ -43,6 +43,9 @@ FROZEN = { 'registration/ROOT_PROPOSAL_BYTE_TRANSFER.json': '63197f650849084f769e487a76458361886a37090042f1e351851c75b0384da2', } require, sha, pin, write = verify.require, verify.sha, verify.pin, verify.write +# collector.inputs fixes the Root input manifest by this SHA (collect_p28_01.py inputs()); +# the bundled copy is held to the same value (S6; test_eq checks both literals agree). +ROOT_MANIFEST_SHA = '9dac0a51d52087e691c5723b4f78f171f7998c78b582b2b6c4c904798e77644d' def load_dependencies(root=ROOT): @@ -83,13 +86,21 @@ def bundled_inputs(copies, readonly): The formal native-verify runs under the Runner seatbelt, which cannot read the original read-only directory or the fixture outside the checkout. The same rule applies: every manifest destination lies in the original read-only directory, and its copy has the - recorded bytes and SHA. The manifest SHA is bound by the caller to the admission pin.""" + recorded bytes and SHA. The manifest SHA is bound by the caller to the admission pin. + + S6: the copy must also be the manifest collector.inputs fixes, and each destination must + be a normalized absolute path ('..' never appears) inside the read-only directory. This + is checked by text because the sandboxed verification cannot read the originals; the run + itself checked the resolved originals through collector.inputs.""" manifest_path = copies / 'ROOT_INPUT_MANIFEST.json' + require(sha(manifest_path) == ROOT_MANIFEST_SHA, 'Root input manifest changed') manifest = verify.read(manifest_path) pins = {} for row in manifest['files']: - destination = Path(row['destination']) - require(destination.is_absolute() and destination.is_relative_to(readonly), 'input escapes read-only directory') + text = row['destination'] + require(type(text) is str and os.path.isabs(text) and os.path.normpath(text) == text, 'input escapes read-only directory') + destination = Path(text) + require(destination.is_relative_to(readonly), 'input escapes read-only directory') relative = destination.relative_to(readonly) copy = copies / relative require(copy.is_file() and not copy.is_symlink(), 'bundled read-only input missing') @@ -114,14 +125,17 @@ def bundle_inputs(out, readonly, fixture, pins): require(bundled_inputs(target / 'readonly', readonly) == pins['readonly'], 'read-only input copies differ') -def actual_pins(root, readonly, fixture, engine, collector, standard, copies=None): +def actual_pins(root, readonly, fixture, engine, collector, standard, copies=None, registered=()): + """registered: the OPT files the measured version changes (S6, --opt-changed); empty for + the before version. eq.admit_source decides the version from the frozen before map.""" local = root / HERE.relative_to(ROOT) dependencies = {n: sha(root / n) for n in DEPENDENCIES} require(dependencies == DEPENDENCIES, 'dependencies changed') frozen = {n: sha(local / n) for n in FROZEN} require(frozen == FROZEN, 'frozen specification changed') source = collector.source_map(standard, root) - require(len(source) == 1407 and collector.digest(source) == eq.SOURCE_SHA, 'full 1407 source pin') + closure = eq.admit_source(source, list(registered)) + require(len(source) == 1407 and collector.digest(source) == closure['after_sha256'], 'full 1407 source pin') require(sha(fixture) == collector.FIXTURE_SHA and sha(engine) == collector.ENGINE_SHA, 'fixture/engine pin') inputs = collector.inputs(readonly) if copies is None else bundled_inputs(copies, readonly) require(len(inputs['files']) == 9, 'nine original destinations required') @@ -131,7 +145,8 @@ def actual_pins(root, readonly, fixture, engine, collector, standard, copies=Non machine = subprocess.check_output(['sysctl', '-n', 'hw.model'], text=True).strip() require(machine == 'Mac16,10', 'machine pin') return {'source': source, 'source_sha256': collector.digest(source), 'dependencies': dependencies, - 'frozen': frozen, 'worker': {n: sha(local / n) for n in sorted(verify.LOCAL_NAMES)}, + 'registered_changes': closure['allowed_changed'], 'source_closure': closure, + 'frozen': frozen, 'worker': {n: sha(local / n) for n in sorted(verify.LOCAL_NAMES | verify.DATA_NAMES)}, 'fixture': pin(fixture), 'engine': pin(engine), 'engine_version': collector.VERSION, 'project': source['project.godot'], 'readonly': inputs, 'original_manifest': manifest, 'machine': machine, 'platform': sys.platform} @@ -139,7 +154,7 @@ def actual_pins(root, readonly, fixture, engine, collector, standard, copies=Non def frozen_commit(source): commit = subprocess.check_output(['git', '-C', str(ROOT), 'rev-parse', 'HEAD'], text=True).strip() - for name in list(source) + [str((HERE / n).relative_to(ROOT)) for n in verify.LOCAL_NAMES]: + for name in list(source) + [str((HERE / n).relative_to(ROOT)) for n in sorted(verify.LOCAL_NAMES | verify.DATA_NAMES)]: data = subprocess.check_output(['git', '-C', str(ROOT), 'show', commit + ':' + name]) require(data == (ROOT / name).read_bytes(), 'not frozen S: ' + name) return commit @@ -264,7 +279,8 @@ def run(admission, out, collector, standard, outer, diag): 'profiles_retained': {str(p): collector.profile_files(p) for p in profiles}} try: execution['pins_after'] = actual_pins(ROOT, Path(admission['readonly_path']), Path(admission['fixture']), - Path(admission['engine']), collector, standard) + Path(admission['engine']), collector, standard, + registered=admission['pins']['registered_changes']) require((ROOT / 'project.godot').read_bytes() == public and (stage / 'project.godot').read_bytes() == public, 'project restoration') if error is None: with check.memo_scope(): @@ -288,15 +304,19 @@ def main(): mode.add_argument('--run', action='store_true') for name in ('readonly', 'fixture', 'engine', 'output'): parser.add_argument('--' + name, type=Path, required=True) + # S6: OPT_CONTRACT_T1 §4 runs this same command on the OPT S; each changed OPT file is + # registered here (repeat the option). None means the before version. + parser.add_argument('--opt-changed', action='append', default=[], metavar='PATH') args = parser.parse_args() try: readonly, fixture, engine, out = [p.resolve() for p in (args.readonly, args.fixture, args.engine, args.output)] require(not out.exists(), 'new output required') collector, standard, outer, diag = load_dependencies() - pins = actual_pins(ROOT, readonly, fixture, engine, collector, standard) + pins = actual_pins(ROOT, readonly, fixture, engine, collector, standard, registered=sorted(args.opt_changed)) static = check.check_probe((HERE / 'eq_probe.gd').read_text()) require(static['ok'], 'probe checker: ' + repr(static['errors'])) - admission = {'measured_source': 'S_eq-native-not-Q', 'candidate_Q_measured': False, + version = pins['source_closure']['version'] + admission = {'measured_source': verify.MEASURED[version], 'version': version, 'candidate_Q_measured': False, 'commit': frozen_commit(pins['source']), 'source_map': pins['source'], 'pins': pins, 'readonly_path': str(readonly), 'fixture': str(fixture), 'engine': str(engine), 'phases': verify.PHASES, 'plan': plan(collector, standard, engine, fixture, out)} diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py index 6f8dd9d..29d0fde 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/test_eq.py @@ -1067,7 +1067,7 @@ def e45_fixture(role='R'): post['checkpoint']['latest'] = transport(after_held) post['checkpoint']['computed_latest_digest'] = 'c'*64 current = observed(tree, minute+1) - detail = {'target': target, 'location': location, 'direction': direction, 'digest_materialized_before': True, + detail = {'target': target, 'location': location, 'direction': direction, 'latest_digest_dirty_before': False, 'held_before': transport(held), 'held_after': transport(after_held)} emit('E5/'+target+'/'+location+'/'+direction, direction, [begin, baseline, post, copy.deepcopy(current)], detail) return raw, evidence, previous @@ -1132,7 +1132,7 @@ class S3b(unittest.TestCase): self.reject(lambda r, e, p: e[5]['detail'].update(held_after=e[5]['detail']['held_before'])) def test_digest_materialization_required(self): - self.reject(lambda r, e, p: e[5]['detail'].update(digest_materialized_before=False)) + self.reject(lambda r, e, p: e[5]['detail'].update(latest_digest_dirty_before=True)) def test_NA_not_PASS(self): self.reject(lambda r, e, p: r['scenarios'][18]['result'].update(applicability='PASS')) @@ -1371,16 +1371,28 @@ def s4_owned_fixture(directory, item, pid): ('process.json', 'started.json', 'ended.json', 'adapter-owned-cleanup.json', 'outer-owned-finally.json')}} -def s4_bundle_fixture(directory, collector, standard): - """Synthetic receipts only. Production validators are real; no Godot claim.""" +def s4_bundle_fixture(directory, collector, standard, registered=(), pin_overrides=None): + """Synthetic receipts only. Production validators are real; no Godot claim. + S6: registered gives an after-version admission whose map changes exactly those OPT + files (synthetic SHAs); pin_overrides replaces non-product pins.""" source = collector.source_map(standard, verifier.ROOT) + if registered: + source = copy.deepcopy(source) + for name in registered: source[name] = {'bytes': source[name]['bytes'], 'sha256': 'f'*64} + closure = eq.admit_source(source, list(registered)) for name in ('eq_probe.gd',): (directory/name).write_bytes((verifier.HERE/name).read_bytes()) (directory/'profile_guard.gd').write_text('synthetic guard bytes') (directory/'guarded.gd').write_text(driver.wrapper_text(directory)) verifier.write(directory/'root-input-manifest.json', {'synthetic_not_native': True}) pins = {'worker': {'eq_probe.gd': verifier.sha(directory/'eq_probe.gd')}, 'readonly': {'files': {'run-r02/profile_guard.gd': verifier.sha(directory/'profile_guard.gd')}, - 'manifest_sha256': verifier.sha(directory/'root-input-manifest.json')}} + 'manifest_sha256': verifier.sha(directory/'root-input-manifest.json')}, + 'registered_changes': closure['allowed_changed'], 'source_closure': closure, + 'dependencies': dict(driver.DEPENDENCIES), 'frozen': dict(driver.FROZEN), + 'fixture': {'bytes': 7, 'sha256': collector.FIXTURE_SHA}, 'engine': {'bytes': 1, 'sha256': collector.ENGINE_SHA}, + 'engine_version': collector.VERSION, 'original_manifest': {'synthetic_not_native': True}, + 'machine': 'synthetic', 'platform': 'synthetic'} + pins.update(pin_overrides or {}) commands = [collector.argv_for(Path('/synthetic/Godot'), directory/'stage', directory/'guarded.gd', True), collector.parse_argv(Path('/synthetic/Godot'), directory/'stage', directory/'eq_probe.gd'), collector.parse_argv(Path('/synthetic/Godot'), directory/'stage', directory/'guarded.gd')] + [ @@ -1412,8 +1424,8 @@ def s4_bundle_fixture(directory, collector, standard): for kind in ('startup', 'runtime'): retained[item[kind+'_profile']] = row['profile_copies'][kind]['files'] rows.append(row) cleanup.append({'pid': pid, 'engine_ended': True, 'outer_cleanup_errors': [], 'foreign_process_or_group_signals': 0}) - admission = {'source_map': source, 'phases': verifier.PHASES, 'plan': plan, 'pins': pins, - 'measured_source': 'S_eq-native-not-Q', 'candidate_Q_measured': False, + admission = {'source_map': source, 'phases': verifier.PHASES, 'plan': plan, 'pins': pins, 'commit': 'synthetic-' + closure['version'], + 'version': closure['version'], 'measured_source': verifier.MEASURED[closure['version']], 'candidate_Q_measured': False, 'readonly_path': '/synthetic/readonly', 'fixture': '/synthetic/fixture', 'engine': '/synthetic/Godot'} verifier.write(directory/'admission.json', admission) return {'passed': True, 'error': None, 'cleanup_errors': [], 'cleanup': cleanup, 'admission': admission, @@ -1594,7 +1606,7 @@ class S4ProbeAdmission(unittest.TestCase): errors = [] if ok else ['first static violation', 'second static violation'] with patch.object(sys, 'argv', argv), \ patch.object(driver, 'load_dependencies', return_value=(None, None, None, None)), \ - patch.object(driver, 'actual_pins', return_value={'source': {}}), \ + patch.object(driver, 'actual_pins', return_value={'source': {}, 'source_closure': {'version': 'before'}}), \ patch.object(checker, 'check_probe', return_value={'ok': ok, 'errors': errors}) as probe, \ patch.object(driver, 'frozen_commit', return_value='synthetic'), \ patch.object(driver, 'plan', return_value=[]), \ @@ -1685,7 +1697,7 @@ class S4StoredResultBindings(unittest.TestCase): # exercised without a mock by S4NativeBundleLogic and S4RemainingBindings. with synthetic_directory() as name: directory = Path(name) - admission = dict(readonly_path=name, fixture=name, engine=name, pins={}) + admission = dict(readonly_path=name, fixture=name, engine=name, pins={'registered_changes': []}) verifier.write(directory/'execution.json', {'admission': admission}) result = {'phases': {'R-A': {'raw': {'kind': 'raw'}, 'joined': {'kind': 'joined'}, 'proofs': [{'sidecar': 'required'}], 'checker': {'ok': True}}}} @@ -1699,7 +1711,7 @@ class S4StoredResultBindings(unittest.TestCase): verifier.write(directory/'R-A'/(key+'.json'), value) verifier.seal(directory) with patch.object(driver, 'load_dependencies', return_value=(None, None, None, None)), \ - patch.object(driver, 'actual_pins', return_value={}), \ + patch.object(driver, 'actual_pins', return_value={'registered_changes': []}), \ patch.object(verifier, 'recompute', return_value=result) as recompute: with self.assertRaisesRegex(eq.EvidenceError, 'recomputed results differ|copy differs'): verifier.verify(verifier.ROOT, directory) @@ -1713,6 +1725,7 @@ class S4StoredResultBindings(unittest.TestCase): # S5 (EQ_S5_SCALE_PLAN r01/r02): content-addressed blobs, exact fast paths, event stream. import gzip import shutil +import subprocess import tempfile @@ -2283,6 +2296,8 @@ class S5(unittest.TestCase): (original / relative).parent.mkdir(parents=True, exist_ok=True); (original / relative).write_bytes(content) rows.append({'destination': str(original / relative), 'bytes': len(content), 'sha256': hashlib.sha256(content).hexdigest()}) original.joinpath('ROOT_INPUT_MANIFEST.json').write_text(json.dumps({'files': rows})) + manifest_pin = patch.object(driver, 'ROOT_MANIFEST_SHA', verifier.sha(original / 'ROOT_INPUT_MANIFEST.json')) + manifest_pin.start(); self.addCleanup(manifest_pin.stop) fixture = self.root / 'reference.variant'; fixture.write_bytes(b'fixture') pins = {'fixture': verifier.pin(fixture), 'readonly': driver.bundled_inputs(original, original)} driver.bundle_inputs(self.root, original, fixture, pins) @@ -2298,8 +2313,11 @@ class S5(unittest.TestCase): outside = json.loads((self.root / 'inputs' / 'readonly' / 'ROOT_INPUT_MANIFEST.json').read_text()) outside['files'][0]['destination'] = '/elsewhere/a.py' (self.root / 'inputs' / 'readonly' / 'ROOT_INPUT_MANIFEST.json').write_text(json.dumps(outside)) - with self.assertRaisesRegex(eq.EvidenceError, 'input escapes read-only directory'): + with self.assertRaisesRegex(eq.EvidenceError, 'Root input manifest changed'): driver.bundled_inputs(self.root / 'inputs' / 'readonly', original) + with patch.object(driver, 'ROOT_MANIFEST_SHA', verifier.sha(self.root / 'inputs' / 'readonly' / 'ROOT_INPUT_MANIFEST.json')): + with self.assertRaisesRegex(eq.EvidenceError, 'input escapes read-only directory'): + driver.bundled_inputs(self.root / 'inputs' / 'readonly', original) def test_probe_static_full_tree_blob_and_stream_requirements(self): probe = (verifier.HERE/'eq_probe.gd').read_text() @@ -2319,5 +2337,298 @@ class S5(unittest.TestCase): self.assertFalse(checker.check_probe(probe.replace(old, new))['ok']) +# S6 (EQ_S6_AFTER_VERSION_PLAN): the after version through the frozen harness, the +# cross-version comparison, and the three low-severity review findings. +OPT_FILE = 'autoload/simulation_runtime.gd' + + +def s6_after_map(*names): + after = copy.deepcopy(eq.before_source_map()) + for name in names: after[name] = {'bytes': after[name]['bytes'], 'sha256': 'f'*64} + return after + + +def s6_sealed_bundle(directory, logic, registered=(), pin_overrides=None): + execution = s4_bundle_fixture(directory, logic.collector, logic.standard, registered, pin_overrides) + # The production parallel path of native-verify (one worker process per role phase). + with patch.object(logic.standard, 'profile_path', side_effect=lambda name: Path('/private')/name): + result = verifier.recompute(directory, execution, logic.collector, logic.standard, logic.diag, parallel=True) + verifier.write(directory/'execution.json', execution) + verifier.write(directory/'results.json', result) + for phase, values in result['phases'].items(): + for name, value in values.items(): verifier.write(directory/phase/(name+'.json'), value) + verifier.seal(directory) + return result + + +class S6SourceClosure(unittest.TestCase): + def test_before_map_is_the_frozen_source_map(self): + before = eq.before_source_map() + self.assertEqual(len(before), 1407) + self.assertTrue(eq.check_source_closure(before, before, [])['ok']) + self.assertIn(OPT_FILE, before) + + def test_before_map_tampering_rejected(self): + original = json.loads(eq.BEFORE_SOURCE_MAP.read_text()) + changed = copy.deepcopy(original); changed[OPT_FILE]['sha256'] = 'f'*64 + fewer = copy.deepcopy(original); fewer.pop(OPT_FILE) + row = json.dumps(original[OPT_FILE]) + duplicate = '{' + json.dumps(OPT_FILE) + ': ' + row + ', ' + json.dumps(original, sort_keys=True)[1:] + with synthetic_directory() as name: + for label, content in (('changed', json.dumps(changed)), ('fewer', json.dumps(fewer)), ('duplicate', duplicate), + ('extra field', json.dumps({**original, OPT_FILE: {**original[OPT_FILE], 'x': 1}}))): + target = Path(name)/(label.replace(' ', '-')+'.json'); target.write_text(content) + with self.subTest(label=label), patch.object(eq, 'BEFORE_SOURCE_MAP', target), \ + self.assertRaises(eq.EvidenceError): + eq.before_source_map() + + def test_admit_before_and_registered_after(self): + before = eq.admit_source(eq.before_source_map(), []) + self.assertEqual((before['version'], before['changed'], before['after_sha256']), ('before', [], eq.SOURCE_SHA)) + names = sorted([OPT_FILE, 'scripts/core/simulation_snapshot.gd']) + after = eq.admit_source(s6_after_map(*names), names) + self.assertEqual((after['version'], after['changed'], after['allowed_changed']), ('after', names, names)) + self.assertNotEqual(after['after_sha256'], eq.SOURCE_SHA) + + def test_unregistered_added_missing_and_malformed_registrations_rejected(self): + before = eq.before_source_map() + added = s6_after_map(OPT_FILE); added['scripts/core/new_file.gd'] = {'bytes': 1, 'sha256': 'a'*64} + missing = s6_after_map(OPT_FILE); missing.pop('scripts/core/simulation_snapshot.gd') + outside = sorted(set(before) - eq.OPT_PATHS)[0] + cases = [ + ('unregistered change', s6_after_map(OPT_FILE), []), + ('registered but unchanged', before, [OPT_FILE]), + ('registered subset only', s6_after_map(OPT_FILE, 'scripts/core/simulation_snapshot.gd'), [OPT_FILE]), + ('outside OPT paths', s6_after_map(outside), [outside]), + ('added source', added, [OPT_FILE]), + ('missing source', missing, [OPT_FILE]), + ('duplicate registration', s6_after_map(OPT_FILE), [OPT_FILE, OPT_FILE]), + ('unsorted registration', s6_after_map(OPT_FILE, 'scripts/core/command_queue.gd'), ['scripts/core/simulation_snapshot.gd', 'scripts/core/command_queue.gd']), + ('tuple registration', s6_after_map(OPT_FILE), (OPT_FILE,)), + ] + for label, source, registered in cases: + with self.subTest(label=label), self.assertRaises(eq.EvidenceError): + eq.admit_source(source, registered) + + +class S6Admission(unittest.TestCase): + @classmethod + def setUpClass(cls): + cls.collector, cls.standard, cls.outer, cls.diag = driver.load_dependencies() + + def pins(self, source, registered): + original_sha = driver.sha + def synthetic_sha(path): + if Path(path) == Path('/synthetic/fixture'): return self.collector.FIXTURE_SHA + if Path(path) == Path('/synthetic/Godot'): return self.collector.ENGINE_SHA + return original_sha(path) + with synthetic_directory() as name: + root = Path(name) + (root/'ROOT_INPUT_MANIFEST.json').write_text(json.dumps({'files': [{'destination': str(n)} for n in range(9)]})) + with patch.object(driver, 'sha', side_effect=synthetic_sha), \ + patch.object(driver.subprocess, 'check_output', return_value='Mac16,10\n'), \ + patch.object(driver, 'pin', return_value={'bytes': 1, 'sha256': 'a'*64}), \ + patch.object(self.collector, 'source_map', return_value=source), \ + patch.object(self.collector, 'inputs', return_value={'files': {str(n): 'sha' for n in range(9)}}): + return driver.actual_pins(verifier.ROOT, root, Path('/synthetic/fixture'), Path('/synthetic/Godot'), + self.collector, self.standard, registered=registered) + + def test_check_path_admits_registered_after_version(self): + pins = self.pins(s6_after_map(OPT_FILE), [OPT_FILE]) + self.assertEqual(pins['registered_changes'], [OPT_FILE]) + self.assertEqual((pins['source_closure']['version'], pins['source_closure']['changed']), ('after', [OPT_FILE])) + self.assertIn('BEFORE_SOURCE_MAP.json', pins['worker']) + before = self.pins(eq.before_source_map(), []) + self.assertEqual((before['source_closure']['version'], before['source_sha256']), ('before', eq.SOURCE_SHA)) + + def test_check_path_rejects_unregistered_or_unchanged(self): + for label, source, registered in (('unregistered', s6_after_map(OPT_FILE), []), + ('unchanged', eq.before_source_map(), [OPT_FILE])): + with self.subTest(label=label), self.assertRaisesRegex(eq.EvidenceError, 'source closure'): + self.pins(source, registered) + + def test_main_passes_sorted_registration_and_records_version(self): + with synthetic_directory() as name: + argv = ['run_eq.py', '--check', '--readonly', name, '--fixture', name, '--engine', name, + '--output', str(Path(name)/'new-output'), '--opt-changed', 'scripts/core/simulation_snapshot.gd', + '--opt-changed', OPT_FILE] + pins = {'source': {}, 'source_closure': {'version': 'after'}} + with patch.object(sys, 'argv', argv), \ + patch.object(driver, 'load_dependencies', return_value=(None, None, None, None)), \ + patch.object(driver, 'actual_pins', return_value=pins) as actual, \ + patch.object(checker, 'check_probe', return_value={'ok': True, 'errors': []}), \ + patch.object(driver, 'frozen_commit', return_value='synthetic'), \ + patch.object(driver, 'plan', return_value=[]), \ + patch('builtins.print') as output: + self.assertEqual(driver.main(), 0) + self.assertEqual(actual.call_args.kwargs['registered'], sorted([OPT_FILE, 'scripts/core/simulation_snapshot.gd'])) + admission = json.loads(output.call_args.args[0]) + self.assertEqual((admission['version'], admission['measured_source']), ('after', 'S_opt-native-not-Q')) + self.assertFalse(admission['candidate_Q_measured']) + + def test_root_manifest_pin_equals_collector_literal(self): + collector_text = (verifier.ROOT/driver.COLLECTOR).read_text() + inputs_body = collector_text[collector_text.index('def inputs(readonly):'):collector_text.index('def reused_observations')] + self.assertEqual(inputs_body.count(driver.ROOT_MANIFEST_SHA), 1) + + def test_bundled_destination_must_be_normalized_inside_readonly(self): + with synthetic_directory() as name: + root = Path(name); readonly = root/'readonly'; copies = root/'copies'; copies.mkdir() + (copies/'a.py').write_bytes(b'alpha') + for destination in (str(readonly/'..'/'copies'/'a.py'), str(readonly)+'/./a.py', 'relative/a.py'): + manifest = copies/'ROOT_INPUT_MANIFEST.json' + manifest.write_text(json.dumps({'files': [{'destination': destination, 'bytes': 5, + 'sha256': hashlib.sha256(b'alpha').hexdigest()}]})) + with self.subTest(destination=destination), \ + patch.object(driver, 'ROOT_MANIFEST_SHA', verifier.sha(manifest)), \ + self.assertRaisesRegex(eq.EvidenceError, 'input escapes read-only directory'): + driver.bundled_inputs(copies, readonly) + + +class S6Bundles(unittest.TestCase): + """A sealed before bundle and a sealed after bundle per class, each built by the real + recompute (no part mocked). The cross-version comparison runs unmocked on them, for + the positive path and for real differences; tampering runs on APFS clones (cp -c), + so copies take no space and the suite stays within the validation limit.""" + @classmethod + def setUpClass(cls): + cls.collector, cls.standard, cls.outer, cls.diag = driver.load_dependencies() + cls.versions = synthetic_directory(); root = Path(cls.versions.name) + cls.before, cls.after = root/'before', root/'after' + cls.before.mkdir(); cls.after.mkdir() + s6_sealed_bundle(cls.before, cls) + cls.after_result = s6_sealed_bundle(cls.after, cls, registered=[OPT_FILE]) + cls.directory, cls.execution = cls.before, verifier.read(cls.before/'execution.json') + + @classmethod + def tearDownClass(cls): + cls.versions.cleanup() + + recompute = S4NativeBundleLogic.recompute + + def copied(self, source, name): + target = Path(self.versions.name)/name + subprocess.run(['/bin/cp', '-c', '-R', str(source), str(target)], check=True) + self.addCleanup(shutil.rmtree, target) + verifier.check_seal(target) + return target + + def resealed(self, directory, mutate, name='execution.json'): + """Change a recorded file of a copy and seal it again (no recomputation).""" + for seal in ('bundle.json', 'seal.json'): (directory/seal).unlink() + if name == 'execution.json': + execution = verifier.read(directory/'execution.json'); mutate(execution['admission']) + for old in ('execution.json', 'admission.json'): (directory/old).unlink() + verifier.write(directory/'execution.json', execution); verifier.write(directory/'admission.json', execution['admission']) + else: + value = verifier.read(directory/name); mutate(value) + (directory/name).unlink(); verifier.write(directory/name, value) + verifier.seal(directory) + + def test_recompute_rejects_version_closure_and_label_changes(self): + mutations = [ + ('registered without change', lambda x: x['admission']['pins'].update(registered_changes=[OPT_FILE])), + ('closure record', lambda x: x['admission']['pins']['source_closure'].update(changed=[OPT_FILE])), + ('version', lambda x: x['admission'].update(version='after')), + ('label', lambda x: x['admission'].update(measured_source='S_opt-native-not-Q')), + ('registration missing', lambda x: x['admission']['pins'].pop('registered_changes')), + ] + for name, mutate in mutations: + value = copy.deepcopy(self.execution); mutate(value) + with self.subTest(name=name), self.assertRaises((eq.EvidenceError, KeyError)): self.recompute(value) + + def test_after_version_bundle_recomputes(self): + result = self.after_result + self.assertEqual((result['version'], result['measured_source'], result['registered_changes']), + ('after', 'S_opt-native-not-Q', [OPT_FILE])) + self.assertFalse(result['candidate_Q_measured']) + self.assertTrue(all(c['ok'] and c['differences'] == [] for c in result['comparisons'].values())) + self.assertEqual(verifier.read(self.after/'results.json'), result) + + def test_cross_version_comparison(self): + result = verifier.compare_bundles(self.before, self.after) + self.assertTrue(result['ok']) + self.assertEqual(set(result['comparisons']), {'R', 'O'}) + self.assertTrue(all(c['ok'] and c['differences'] == [] for c in result['comparisons'].values())) + self.assertEqual(result['versions']['after']['source_closure']['changed'], [OPT_FILE]) + self.assertEqual(result['versions']['before']['measured_source'], 'S_eq-native-not-Q') + # The synthetic E5 aliasing defects are reported per version, never turned into a pass. + self.assertTrue(result['existing_defects']['after']['R']) + self.assertFalse(result['after_all_e_pass']) + self.assertFalse(result['formal_acceptance']) + for label, call in (('swapped', lambda: verifier.compare_bundles(self.after, self.before)), + ('same bundle', lambda: verifier.compare_bundles(self.before, self.before))): + with self.subTest(label=label), self.assertRaises(eq.EvidenceError): call() + + def test_cross_version_pin_closure_and_seal_rejections(self): + drifted = self.copied(self.after, 'drifted') + self.resealed(drifted, lambda a: a['pins'].update(frozen={'SPEC.md': 'f'*64})) + with self.assertRaisesRegex(eq.EvidenceError, 'non-product pin differs between versions: frozen'): + verifier.compare_bundles(self.before, drifted) + closure = self.copied(self.after, 'closure') + self.resealed(closure, lambda a: a['pins']['source_closure'].update(changed=[])) + with self.assertRaisesRegex(eq.EvidenceError, 'after bundle version/closure'): + verifier.compare_bundles(self.before, closure) + label = self.copied(self.after, 'label') + self.resealed(label, lambda a: a.update(measured_source='S_eq-native-not-Q')) + with self.assertRaisesRegex(eq.EvidenceError, 'after bundle version/closure'): + verifier.compare_bundles(self.before, label) + extra = self.copied(self.after, 'extra') + (extra/'extra.json').write_text('{}') + with self.assertRaisesRegex(eq.EvidenceError, 'manifest/file/directory mismatch'): + verifier.compare_bundles(self.before, extra) + + def test_cross_version_real_difference_is_not_ok(self): + # A real state difference in the sealed after report, found by the unmocked comparison. + changed = self.copied(self.after, 'changed') + self.resealed(changed, lambda report: report['checkpoints'][-1]['K'].update(speed=7), name='R-A/joined.json') + result = verifier.compare_bundles(self.before, changed) + self.assertFalse(result['ok']) + self.assertTrue(result['comparisons']['R']['differences']) + self.assertEqual(result['comparisons']['O']['differences'], []) + + +class S6SealAndProbe(unittest.TestCase): + def test_seal_records_every_directory(self): + with synthetic_directory() as name: + directory = Path(name) + (directory/'R-A'/'startup-profile').mkdir(parents=True) + verifier.write(directory/'R-A'/'raw.json', {'synthetic_not_native': True}) + verifier.seal(directory) + self.assertEqual(verifier.read(directory/'bundle.json')['directories'], ['R-A', 'R-A/startup-profile']) + verifier.check_seal(directory) + (directory/'R-A'/'startup-profile').rmdir() + with self.assertRaisesRegex(eq.EvidenceError, 'manifest/file/directory mismatch'): verifier.check_seal(directory) + (directory/'R-A'/'startup-profile').mkdir(); (directory/'extra-empty').mkdir() + with self.assertRaisesRegex(eq.EvidenceError, 'manifest/file/directory mismatch'): verifier.check_seal(directory) + + def test_probe_records_actual_digest_state(self): + probe = (verifier.HERE/'eq_probe.gd').read_text() + self.assertEqual(probe.count('"latest_digest_dirty_before": runtime.get("_latest_digest_dirty")'), 1) + self.assertNotIn('digest_materialized_before', probe) + self.assertTrue(checker.check_probe(probe)['ok']) + + def test_digest_state_values(self): + def e5_rows(evidence): + return [row for row in evidence if row['id'].startswith('E5/')] + def refreshed(raw, evidence): + # The raw result facts are the probe's copy of the detail; keep them bound. + results = {s['id']: s['result'] for s in raw['scenarios']} + for row in evidence: results[row['id']]['facts'] = checker.e45_facts(row['detail']) + raw, evidence, previous = e45_fixture() + self.assertEqual(len(e5_rows(evidence)), 16) + for row in e5_rows(evidence): row['detail']['latest_digest_dirty_before'] = None + refreshed(raw, evidence) + self.assertEqual(len(checker.check_e45(raw, evidence, previous)), 21) + for label, mutate, message in (('dirty', lambda d: d.update(latest_digest_dirty_before=True), 'E5 digest not materialized'), + ('integer', lambda d: d.update(latest_digest_dirty_before=0), 'E5 digest not materialized'), + ('missing', lambda d: d.pop('latest_digest_dirty_before'), 'E5 detail fields')): + raw, evidence, previous = e45_fixture() + mutate(e5_rows(evidence)[0]['detail']) + refreshed(raw, evidence) + with self.subTest(label=label), self.assertRaisesRegex(eq.EvidenceError, message): + checker.check_e45(raw, evidence, previous) + + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/verify_eq.py b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/verify_eq.py index 99e93f8..f6ec03e 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/verify_eq.py +++ b/docs/plans/original-completion-2026-10-02/execution/p28-02/eq/verify_eq.py @@ -31,6 +31,10 @@ def split_evidence(files): LOCAL_NAMES = {'run_eq.py', 'verify_eq.py', 'check_eq.py', 'compare_versions.py', 'eq_probe.gd', 'test_eq.py'} +# S6: EQ data pinned with the code (the fixed before map of the source closure). +DATA_NAMES = {'BEFORE_SOURCE_MAP.json'} +# S6: the version a native measured, from its admitted source closure. Never Q. +MEASURED = {'before': 'S_eq-native-not-Q', 'after': 'S_opt-native-not-Q'} require = eq.require @@ -71,10 +75,18 @@ def inventory(directory, seals=False): return result +def directories(directory): + """Every directory below the bundle root, empty ones included (S6: the verifier binds + each /startup-profile directory's existence, so the seal records them too).""" + directory = Path(directory) + return sorted(p.relative_to(directory).as_posix() for p in directory.rglob('*') if p.is_dir() and not p.is_symlink()) + + def seal(directory): directory = Path(directory) require(not (directory / 'bundle.json').exists() and not (directory / 'seal.json').exists(), 'already sealed') - write(directory / 'bundle.json', {'schema': 'p28-02-eq-bundle-v1', 'files': inventory(directory)}) + write(directory / 'bundle.json', {'schema': 'p28-02-eq-bundle-v2', 'files': inventory(directory), + 'directories': directories(directory)}) write(directory / 'seal.json', {'bundle': pin(directory / 'bundle.json')}) @@ -82,7 +94,8 @@ def check_seal(directory): directory = Path(directory) manifest, sealed = read(directory / 'bundle.json'), read(directory / 'seal.json') require(sealed == {'bundle': pin(directory / 'bundle.json')}, 'seal mismatch') - require(manifest == {'schema': 'p28-02-eq-bundle-v1', 'files': inventory(directory)}, 'manifest/file mismatch') + require(manifest == {'schema': 'p28-02-eq-bundle-v2', 'files': inventory(directory), + 'directories': directories(directory)}, 'manifest/file/directory mismatch') def check_audio(audio, pid): @@ -191,7 +204,7 @@ def recompute(directory, execution, collector, standard, diag, parallel=False): require(execution['passed'] is True and execution['error'] is None and execution['cleanup_errors'] == [], 'execution failed') admission = execution['admission'] require(read(directory / 'admission.json') == admission, 'admission copy') - require(admission['measured_source'] == 'S_eq-native-not-Q' and admission['candidate_Q_measured'] is False, 'Q measurement forbidden') + require(admission['candidate_Q_measured'] is False, 'Q measurement forbidden') require(admission['phases'] == PHASES, 'phase plan') from run_eq import wrapper_text original_out = Path(admission['plan'][0]['folder']).parent @@ -209,7 +222,11 @@ def recompute(directory, execution, collector, standard, diag, parallel=False): static = check.check_probe((directory / 'eq_probe.gd').read_text()) require(static['ok'], 'probe checker: ' + repr(static['errors'])) source = admission['source_map'] - require(len(source) == 1407 and collector.digest(source) == eq.SOURCE_SHA, 'full source map pin') + # S6: the frozen before map and the registered OPT change set decide the version; the + # recorded closure, version and label must be exactly what the closure gives again. + closure = eq.admit_source(source, admission['pins']['registered_changes']) + require(admission['pins']['source_closure'] == closure and admission['version'] == closure['version'], 'recorded source closure/version') + require(admission['measured_source'] == MEASURED[closure['version']], 'measured version label') require(execution['source_after'] == source and execution['player_before'] == execution['player_after'], 'source/player preservation') require(execution['pins_after'] == admission['pins'], 'pin preservation') rows = execution['phases'] @@ -281,10 +298,65 @@ def recompute(directory, execution, collector, standard, diag, parallel=False): result = eq.compare_reports(joined[role + '-A'], joined[role + '-B']) require(result['ok'] and result['differences'] == [], 'same-role determinism failed: ' + role) comparisons[role] = result - return wire({'phases': results, 'comparisons': comparisons, 'measured_source': 'S_eq-native-not-Q', + return wire({'phases': results, 'comparisons': comparisons, 'measured_source': admission['measured_source'], + 'version': closure['version'], 'registered_changes': closure['allowed_changed'], 'candidate_Q_measured': False, 'original_credit': 0, 'formal_acceptance': False}) +VERSION_PINS = ('dependencies', 'frozen', 'worker', 'fixture', 'engine', 'engine_version', 'readonly', + 'original_manifest', 'machine', 'platform') + + +def existing_defects(directory, phase): + """Scenario outcomes the stored checker recorded as existing product defects.""" + checker = read(Path(directory) / phase / 'checker.json') + require(checker['ok'] is True, 'stored checker failed: ' + phase) + return [{'scenario': row['id'], 'status': row['status'], 'kinds': [defect['kind'] for defect in row['defects']]} + for key in ('e3', 'e45') for row in checker[key] if row['status'].startswith('existing-defect')] + + +def compare_bundles(before, after): + """S6 cross-version comparison of two sealed EQ bundles (SPEC §2/§3.2, OPT_CONTRACT_T1 §2-§4). + + Each bundle is proven by its own version's native-verify (raw recomputation, same-role + determinism, checkout pins). Here both seals, versions and source closures are checked + again, every non-product pin must be equal (the EQ, DIAG, collector and RESTART bytes, + fixture, engine and inputs), and the sealed joined reports of the A phases are compared + by compare_reports. Differences, exclusions and existing defects are all returned.""" + before, after = Path(before).resolve(), Path(after).resolve() + require(before != after, 'two different bundles required') + admissions = {} + for version, directory in (('before', before), ('after', after)): + check_seal(directory) + execution = read(directory / 'execution.json') + require(execution['passed'] is True and execution['error'] is None, version + ' native failed') + admission = execution['admission'] + require(read(directory / 'admission.json') == admission, version + ' admission copy') + closure = eq.admit_source(admission['source_map'], admission['pins']['registered_changes']) + require(closure == admission['pins']['source_closure'] and closure['version'] == version == admission['version'] and + admission['measured_source'] == MEASURED[version] and admission['candidate_Q_measured'] is False, + version + ' bundle version/closure') + admissions[version] = admission + for key in VERSION_PINS: + require(admissions['before']['pins'][key] == admissions['after']['pins'][key], 'non-product pin differs between versions: ' + key) + comparisons, reports = {}, {} + for role in ('R', 'O'): + phase = role + '-A' + for version, directory in (('before', before), ('after', after)): + eq.add_blob_root(directory / phase / 'evidence' / 'blobs') + reports[version] = read(directory / phase / 'joined.json') + eq.ACTIVE_PROFILES[:] = [reports['before']['profile_root'], reports['after']['profile_root']] + comparisons[role] = eq.compare_reports(reports['before'], reports['after']) + defects = {version: {role: existing_defects(directory, role + '-A') for role in ('R', 'O')} + for version, directory in (('before', before), ('after', after))} + return wire({'ok': all(c['ok'] and c['differences'] == [] for c in comparisons.values()), + 'versions': {version: {'commit': a['commit'], 'measured_source': a['measured_source'], + 'source_closure': a['pins']['source_closure']} for version, a in admissions.items()}, + 'comparisons': comparisons, 'existing_defects': defects, + 'after_all_e_pass': not any(defects['after'].values()), + 'formal_acceptance': False, 'original_credit': 0}) + + def verify(project_root, directory): from run_eq import load_dependencies, actual_pins project_root, directory = Path(project_root).resolve(), Path(directory).resolve() @@ -297,7 +369,8 @@ def verify(project_root, directory): # against them by run_eq before any phase. inputs = directory / 'inputs' require(actual_pins(project_root, Path(admission['readonly_path']), inputs / 'fixture' / Path(admission['fixture']).name, - Path(admission['engine']), collector, standard, copies=inputs / 'readonly') == admission['pins'], + Path(admission['engine']), collector, standard, copies=inputs / 'readonly', + registered=admission['pins']['registered_changes']) == admission['pins'], 'actual input/source/EQ pins differ') result = recompute(directory, execution, collector, standard, diag, parallel=True) require(result == read(directory / 'results.json'), 'recomputed results differ') @@ -310,6 +383,20 @@ def verify(project_root, directory): def main(): if sys.argv[1:] == ['--phase-worker']: return phase_worker() + if sys.argv[1:2] == ['--compare-versions']: + parser = argparse.ArgumentParser(description=compare_bundles.__doc__) + parser.add_argument('--compare-versions', action='store_true', required=True) + parser.add_argument('--before', type=Path, required=True) + parser.add_argument('--after', type=Path, required=True) + args = parser.parse_args() + try: + with check.memo_scope(): + result = compare_bundles(args.before, args.after) + print(json.dumps({'status': 'compared', 'result': result}, ensure_ascii=False, allow_nan=False)) + return 0 if result['ok'] else 1 + except (ValueError, OSError, KeyError, TypeError, IndexError) as error: + print(json.dumps({'status': 'failed', 'error': str(error), 'formal_acceptance': False})) + return 1 parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('--project-root', type=Path, required=True) args = parser.parse_args()