P28-02-EQ: 意味を保つ軽量化:同等性の先行固定(harness)

This commit is contained in:
Agent Control Runner
2026-10-22 06:42:29 +09:00
parent a46418d064
commit 9adbbee334
16 changed files with 6682 additions and 33 deletions
@@ -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 <bundle> --after <bundle>` (`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 `<phase>/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.
@@ -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 <bundle> --after <bundle> 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に委任」).
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
846ab3b45705f269a81181c818dc5e3b8bc0057863794d59e8d641fe5a4e4c32 UNIT_OUTPUT.txt
9dd93de5fd3b66791d6902d51a055caa2c3dd559de6c42019ebb1ab147b2af11 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
@@ -0,0 +1 @@
9dd93de5fd3b66791d6902d51a055caa2c3dd559de6c42019ebb1ab147b2af11 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
@@ -0,0 +1 @@
be2dd93c3cbb44b3ac74ab003f11ba368da3f4009b3b5595336f591dff52cceb 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
@@ -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)
@@ -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'))
@@ -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
@@ -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)}
@@ -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,6 +2313,9 @@ 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, '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)
@@ -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)
@@ -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 <phase>/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()