From 79d7e0d2302070dd1b64f39d7f8a18edaba932e7 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sun, 6 Sep 2026 05:23:53 -0700 Subject: [PATCH 01/33] fix(epac): bind UCNS identity and validate complete structure --- epac_public_gonol.py | 95 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 84 insertions(+), 11 deletions(-) diff --git a/epac_public_gonol.py b/epac_public_gonol.py index 1eb8176..0041cf3 100644 --- a/epac_public_gonol.py +++ b/epac_public_gonol.py @@ -30,8 +30,8 @@ # module_kind: experiment # summary: EPAC candidate constructor that closes gonols on the UCNS Public Gonol carrier with oriented couplings and arity charge states; not the EDCM text-domain constructor # owner: The Interdependency -# public_surface: CONSTRUCTOR_ID, CONSTRUCTOR_VERSION, PINNED_PUBLIC_GONOL_SHA256, ClosedPublicGonol, PublicGonolReceipt, PublicGonolConstructionError, construct_public_gonol, replay_public_gonol, canonical_receipt_bytes -# internal_surface: _require_text, _identity_position, _geometry, _participant_payload, _atomic_payload, _receipt_payload, _digest +# public_surface: CONSTRUCTOR_ID, CONSTRUCTOR_VERSION, PINNED_UCNS_COMMIT, PINNED_PUBLIC_GONOL_SHA256, ClosedPublicGonol, PublicGonolReceipt, PublicGonolConstructionError, construct_public_gonol, replay_public_gonol, canonical_receipt_bytes +# internal_surface: _require_text, _identity_position, _geometry, _participant_payload, _atomic_payload, _receipt_payload, _digest, _expected_structure_from_couplings # auth_boundary: EPAC owns particle/energy gonol closure; UCNS owns Public Gonol carrier identity and native Möbius ε; EDCM text-domain constructor is not used; METAPAT affixiation is consumed, not redefined # storage_boundary: none; receipts remain caller-owned in-memory objects # network_boundary: none @@ -40,7 +40,7 @@ # tests: tests.test_epac_public_gonol, tests.test_periodic_element_gonols, tests.test_molecular_affixiation # rollout: explicit EPAC candidate constructor; no canon selection, no EDCM scale option sets, no invented position operation # rollback: remove this module; do not fall back to edcm.gonol for EPAC construction -# requires: ucns_public_gonol_geometry, ucns_native_mobius_geometry +# requires: ucns_public_gonol_geometry, ucns_native_mobius_geometry, epac_dimensional_arity # since: 2026-08-22 # unresolved: exact UCNS geometric operation of Public Gonol function positions; UCNS Möbius-carrier affixiation/coupling law; two-letter element symbols have no single carrier glyph # === END MODULE_BUILD === @@ -54,7 +54,7 @@ # # id: epac_public_gonol_binds_ucns_carrier_identity # given: identity_glyph is an admitted Public Gonol glyph -# then: the closed gonol carries the exact UCNS index/glyph pair and the pinned carrier digest +# then: the closed gonol carries the exact UCNS index/glyph pair, EPAC-owned pinned carrier digest, and exact pinned UCNS dependency identity # class: construction # since: 2026-08-22 # @@ -66,7 +66,7 @@ # # id: charged_oriented_couplings_are_the_structure # given: declared oriented couplings with per-slot charges -# then: receipt.structure is the combination of those couplings, arity charge states, and degree; no (x,y,z) coupling is inferred +# then: receipt.structure is exactly the structure derived from those couplings, arity charge states, degree, representation flags, and quaternion readouts; no caller-fabricated derived fields or (x,y,z) coupling are accepted # class: construction # since: 2026-08-22 # === END CONTRACTS === @@ -81,8 +81,12 @@ from types import MappingProxyType from typing import Any, Mapping, Sequence +from epac_dimensional_arity import ( + MOBIUS_EPSILON_T0, + space, + structure_from_charged_couplings, +) from ucns import ( - PUBLIC_GONOL_SHA256, native_mobius_state, public_gonol_function, public_gonol_sha256, @@ -91,7 +95,8 @@ CONSTRUCTOR_ID = "epac.public_gonol" CONSTRUCTOR_VERSION = "v1" -PINNED_PUBLIC_GONOL_SHA256 = PUBLIC_GONOL_SHA256 +PINNED_UCNS_COMMIT = "828c0b8bbcfc267efb5701da714191c1f73a81ff" +PINNED_PUBLIC_GONOL_SHA256 = "55d10c84529a4d7bc7714786357e977b68d9df2ac3f73d20e229580b552c2ef5" STANDING = "implemented-candidate" SELECTION_EFFECT = "none" @@ -184,6 +189,7 @@ def _geometry(identity_glyph: str | None, carrier_index: int | None) -> dict[str "state": "bound", "authority": "ucns.public_gonol", "authority_binding": "explicit", + "ucns_commit": PINNED_UCNS_COMMIT, "carrier_digest": digest, "identity_position": identity, "mobius_epsilon_t0": origin.frame.sign, @@ -233,6 +239,67 @@ def _structure_part_signature(item: Mapping[str, Any]) -> tuple[Any, int, Any]: ) +def _coupling_declaration(item: Mapping[str, Any]) -> tuple[tuple[str, ...], tuple[int | None, ...]]: + declared = item.get("declared_ids", item.get("coupling")) + if not isinstance(declared, SequenceABC) or isinstance(declared, (str, bytes)) or not declared: + raise PublicGonolConstructionError("each coupling must declare ordered dimension ids") + ids = tuple(declared) + if any(not isinstance(name, str) or not name or name.isspace() for name in ids): + raise PublicGonolConstructionError("coupling dimension ids must be exact non-empty text") + arity = item.get("arity") + if isinstance(arity, bool) or not isinstance(arity, int) or arity != len(ids): + raise PublicGonolConstructionError("coupling arity must match declared dimension ids") + + slot_charges = item.get("slot_charges") + charge_state = item.get("charge_state") + if slot_charges is None: + if ( + not isinstance(charge_state, SequenceABC) + or isinstance(charge_state, (str, bytes)) + or len(charge_state) != 2 + ): + raise PublicGonolConstructionError("coupling must carry slot charges or charge_state") + slot_charges = charge_state[0] + if not isinstance(slot_charges, SequenceABC) or isinstance(slot_charges, (str, bytes)): + raise PublicGonolConstructionError("slot_charges must be an ordered sequence") + charges = tuple(slot_charges) + if len(charges) != len(ids) or any( + charge is not None and (isinstance(charge, bool) or not isinstance(charge, int)) + for charge in charges + ): + raise PublicGonolConstructionError("slot_charges must align with declared dimensions") + if charge_state is not None and _tuple_tree(charge_state) != _tuple_tree( + (charges, MOBIUS_EPSILON_T0) + ): + raise PublicGonolConstructionError("coupling charge_state conflicts with slot charges") + return ids, charges + + +def _expected_structure_from_couplings( + couplings: Sequence[Mapping[str, Any]], +) -> Mapping[str, object]: + ambient_ids: list[str] = [] + charge_by_id: dict[str, int | None] = {} + declarations: list[tuple[str, ...]] = [] + for item in couplings: + ids, charges = _coupling_declaration(item) + declarations.append(ids) + for name, charge in zip(ids, charges): + if name not in ambient_ids: + ambient_ids.append(name) + if name in charge_by_id and charge_by_id[name] != charge: + raise PublicGonolConstructionError( + f"dimension {name!r} has conflicting charges across couplings" + ) + charge_by_id[name] = charge + declared = space( + ambient_ids, + declarations, + charges={name: charge for name, charge in charge_by_id.items() if charge is not None}, + ) + return structure_from_charged_couplings(declared) + + def _validate_structure_matches_couplings( couplings: Sequence[Mapping[str, Any]], structure: Mapping[str, Any] | None, @@ -246,12 +313,17 @@ def _validate_structure_matches_couplings( parts = structure.get("parts") if not isinstance(parts, SequenceABC) or isinstance(parts, (str, bytes)): raise PublicGonolConstructionError("structure parts must be a sequence") - expected = tuple(sorted((_coupling_signature(item) for item in couplings), key=repr)) - actual = tuple(sorted((_structure_part_signature(item) for item in parts), key=repr)) - if expected != actual: + expected_parts = tuple(sorted((_coupling_signature(item) for item in couplings), key=repr)) + actual_parts = tuple(sorted((_structure_part_signature(item) for item in parts), key=repr)) + if expected_parts != actual_parts: raise PublicGonolConstructionError( "structure must match the supplied declared couplings before closure" ) + expected_structure = _expected_structure_from_couplings(couplings) + if _tuple_tree(structure) != _tuple_tree(expected_structure): + raise PublicGonolConstructionError( + "structure derived fields must exactly match the declared couplings before closure" + ) def _participant_payload(item: ClosedPublicGonol) -> dict[str, Any]: @@ -348,7 +420,7 @@ def construct_public_gonol( couplings: Sequence[Mapping[str, Any]] = (), structure: Mapping[str, Any] | None = None, ) -> PublicGonolReceipt: - """Close one EPAC gonol on the UCNS Public Gonol carrier.""" + """Close one EPAC gonol on the pinned UCNS Public Gonol carrier.""" source_id = _require_text(source_id, field="source_id") relation = _require_text(relation, field="relation") @@ -442,6 +514,7 @@ def replay_public_gonol(receipt: PublicGonolReceipt) -> PublicGonolReceipt: "HMMM", "NONCLAIMS", "PINNED_PUBLIC_GONOL_SHA256", + "PINNED_UCNS_COMMIT", "PublicGonolConstructionError", "PublicGonolReceipt", "canonical_receipt_bytes", From 2bef7bb3b4af4cf664fe75a7139a7e3ba1afd4d5 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sun, 6 Sep 2026 05:24:31 -0700 Subject: [PATCH 02/33] test(epac): cover dependency pin and full structure validation --- tests/test_epac_public_gonol.py | 64 +++++++++++++++++++++++---------- 1 file changed, 46 insertions(+), 18 deletions(-) diff --git a/tests/test_epac_public_gonol.py b/tests/test_epac_public_gonol.py index 45af768..5f26b84 100644 --- a/tests/test_epac_public_gonol.py +++ b/tests/test_epac_public_gonol.py @@ -1,5 +1,6 @@ from __future__ import annotations +import copy import sys import unittest from pathlib import Path @@ -11,6 +12,7 @@ from epac_public_gonol import ( CONSTRUCTOR_ID, PINNED_PUBLIC_GONOL_SHA256, + PINNED_UCNS_COMMIT, PublicGonolConstructionError, construct_public_gonol, replay_public_gonol, @@ -30,11 +32,22 @@ def test_constructor_is_not_edcm(self) -> None: self.assertEqual(CONSTRUCTOR_ID, "epac.public_gonol") self.assertEqual(receipt.gonol.identity_glyph, "O") self.assertEqual(receipt.gonol.carrier_index, public_gonol_function("O").index) + self.assertEqual(PINNED_UCNS_COMMIT, "828c0b8bbcfc267efb5701da714191c1f73a81ff") + self.assertEqual( + PINNED_PUBLIC_GONOL_SHA256, + "55d10c84529a4d7bc7714786357e977b68d9df2ac3f73d20e229580b552c2ef5", + ) self.assertEqual(PINNED_PUBLIC_GONOL_SHA256, PUBLIC_GONOL_SHA256) + source = (EPAC_ROOT / "epac_public_gonol.py").read_text(encoding="utf-8") + self.assertIn( + 'PINNED_PUBLIC_GONOL_SHA256 = "55d10c84529a4d7bc7714786357e977b68d9df2ac3f73d20e229580b552c2ef5"', + source, + ) + self.assertNotIn("PINNED_PUBLIC_GONOL_SHA256 = PUBLIC_GONOL_SHA256", source) for name in ("epac_public_gonol.py", "epac_periodic.py", "epac_molecular.py"): - source = (EPAC_ROOT / name).read_text(encoding="utf-8") - self.assertNotIn("from edcm", source, name) - self.assertNotIn("import edcm", source, name) + module_source = (EPAC_ROOT / name).read_text(encoding="utf-8") + self.assertNotIn("from edcm", module_source, name) + self.assertNotIn("import edcm", module_source, name) def test_two_letter_symbol_has_no_single_glyph(self) -> None: receipt = construct_public_gonol( @@ -100,28 +113,43 @@ def test_nested_geometry_is_frozen_after_closure(self) -> None: def test_structure_must_match_declared_couplings(self) -> None: declared = space( - ["z", "x"], - [["z", "x"]], - charges={"z": 8, "x": 1}, + ["z", "x", "y"], + [["z", "x"], ["z", "y"]], + charges={"z": 8, "x": 1, "y": 1}, ) geometry = geometry_from_declared_couplings(declared) - bad_structure = { - **geometry["structure"], - "parts": ( - { - "coupling": ("z", "x"), - "arity": 2, - "charge_state": ((8, 99), 1), - }, - ), - } + bad_part = copy.deepcopy(geometry["structure"]) + bad_part["parts"][0]["charge_state"] = ((8, 99), 1) with self.assertRaisesRegex(PublicGonolConstructionError, "structure must match"): construct_public_gonol( - source_id="epac.test:bad-structure", + source_id="epac.test:bad-part", relation="epac.affixiation.unpaired-valence", couplings=geometry["couplings"], - structure=bad_structure, + structure=bad_part, ) + + mutations = { + "degree": (), + "participating_dimension_count": 99, + "ternary_coupling_declared": True, + "inferred_cartesian_embedding": True, + "representation_kind": "fabricated", + "representation_dimension": 99, + "represented_structure_dimension": 99, + "quaternions": (), + } + for key, value in mutations.items(): + with self.subTest(key=key): + bad_structure = copy.deepcopy(geometry["structure"]) + bad_structure[key] = value + with self.assertRaisesRegex(PublicGonolConstructionError, "derived fields"): + construct_public_gonol( + source_id=f"epac.test:bad-{key}", + relation="epac.affixiation.unpaired-valence", + couplings=geometry["couplings"], + structure=bad_structure, + ) + with self.assertRaisesRegex(PublicGonolConstructionError, "supplied together"): construct_public_gonol( source_id="epac.test:missing-structure", From 8526525d89689d2624e403a40c603608e68a8a9c Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sun, 6 Sep 2026 05:25:14 -0700 Subject: [PATCH 03/33] fix(epac): stamp current UCNS pin and freeze element state --- subatomic/element_affixiation_candidate.py | 88 ++++++++++++++-------- 1 file changed, 55 insertions(+), 33 deletions(-) diff --git a/subatomic/element_affixiation_candidate.py b/subatomic/element_affixiation_candidate.py index 8789fb6..d4a2f0a 100644 --- a/subatomic/element_affixiation_candidate.py +++ b/subatomic/element_affixiation_candidate.py @@ -33,18 +33,18 @@ # summary: identity-only H/He/Li/C element-gonol candidates over established UCNS carrier identity and native Möbius framing; no position operation invented # owner: The Interdependency # public_surface: ISOTOPE_DEFAULTS, CONSTRUCTION_IDS, ElementCandidate, affixiate_element, replay_element, element_receipt -# internal_surface: _canonical_record, _t_states +# internal_surface: _canonical_record, _t_states, _freeze_state # auth_boundary: none # storage_boundary: none # network_boundary: none # user_data_boundary: none # admin_only: false # tests: subatomic.test_element_affixiation_candidate -# rollout: local candidate module under stack/research/epac/subatomic/ +# rollout: extracted EPAC candidate; no canon or empirical promotion # rollback: remove module, tests, and generated receipts # requires: ucns_public_gonol_geometry, ucns_native_mobius_geometry # since: 2026-08-22 -# unresolved: Public Gonol position operations; harmonic notation; isotope defaults are instance-resolved; epac canonical repository absent +# unresolved: Public Gonol position operations; harmonic notation; isotope defaults are instance-resolved; release/reconsumption graduation remains incomplete # === END MODULE_BUILD === # === CONTRACTS === @@ -65,7 +65,7 @@ # # id: receipt_deterministic_and_replayable # given: the same element and the same pinned source identities -# then: the receipt is byte-identical across independent constructions +# then: the receipt is byte-identical across independent constructions and returned nested state cannot mutate after closure # class: correctness # # id: no_physics_or_canon_claim @@ -76,36 +76,45 @@ from __future__ import annotations +from collections.abc import Mapping from dataclasses import dataclass from fractions import Fraction import hashlib import json +from types import MappingProxyType +from typing import Any from ucns import native_mobius_state, public_gonol_function -SOURCE_COMMITS = { - "metapat": "34d954aa1e2092e615b03a180500f6b6977f501e", - "ucns": "1975fe70cf4e0826a8020c2da3047569e277af64", -} - -CONSTRUCTION_IDS = { - "relation": "metapat.affixiation_harmonics.affixiation", - "ordered_parameter": "ucns.native-mobius-turn-index", - "closure_scale": "epac.subatomic.atomic", - "status": "CROSS-DOMAIN-HYPOTHESIS", -} +SOURCE_COMMITS = MappingProxyType( + { + "metapat": "34d954aa1e2092e615b03a180500f6b6977f501e", + "ucns": "828c0b8bbcfc267efb5701da714191c1f73a81ff", + } +) + +CONSTRUCTION_IDS = MappingProxyType( + { + "relation": "metapat.affixiation_harmonics.affixiation", + "ordered_parameter": "ucns.native-mobius-turn-index", + "closure_scale": "epac.subatomic.atomic", + "status": "CROSS-DOMAIN-HYPOTHESIS", + } +) # Default isotope instances are instance-resolved, not canonical admission law. # Extended to Z=1..26 (through iron) for the subatomic gonol program. -ISOTOPE_DEFAULTS = { - "H": (1, 1), "He": (2, 4), "Li": (3, 7), "Be": (4, 9), - "B": (5, 11), "C": (6, 12), "N": (7, 14), "O": (8, 16), - "F": (9, 19), "Ne": (10, 20), "Na": (11, 23), "Mg": (12, 24), - "Al": (13, 27), "Si": (14, 28), "P": (15, 31), "S": (16, 32), - "Cl": (17, 35), "Ar": (18, 40), "K": (19, 39), "Ca": (20, 40), - "Sc": (21, 45), "Ti": (22, 48), "V": (23, 51), "Cr": (24, 52), - "Mn": (25, 55), "Fe": (26, 56), -} +ISOTOPE_DEFAULTS = MappingProxyType( + { + "H": (1, 1), "He": (2, 4), "Li": (3, 7), "Be": (4, 9), + "B": (5, 11), "C": (6, 12), "N": (7, 14), "O": (8, 16), + "F": (9, 19), "Ne": (10, 20), "Na": (11, 23), "Mg": (12, 24), + "Al": (13, 27), "Si": (14, 28), "P": (15, 31), "S": (16, 32), + "Cl": (17, 35), "Ar": (18, 40), "K": (19, 39), "Ca": (20, 40), + "Sc": (21, 45), "Ti": (22, 48), "V": (23, 51), "Cr": (24, 52), + "Mn": (25, 55), "Fe": (26, 56), + } +) @dataclass(frozen=True, slots=True) @@ -120,22 +129,22 @@ class ElementCandidate: proton_glyphs: tuple[str, ...] neutron_positions: tuple[int, ...] neutron_glyphs: tuple[str, ...] - t_states: tuple[dict, ...] + t_states: tuple[Mapping[str, Any], ...] relation_id: str ordered_parameter_id: str closure_scale: str - source_commits: dict + source_commits: Mapping[str, str] status: str receipt: str -def _t_states() -> tuple[dict, ...]: - """Traverse the Möbius turn index t in {0, 1, 2}. +def _t_states() -> tuple[dict[str, Any], ...]: + """Traverse the Möbius turn index t in {0, 1, 2} for the canonical receipt. Uses only the established native Möbius root-loop quotient. Time is not inserted: t is a declared ordered parameter, not physical time. """ - states = [] + states: list[dict[str, Any]] = [] for t in (0, 1, 2): state = native_mobius_state(Fraction(t)) states.append( @@ -153,6 +162,19 @@ def _t_states() -> tuple[dict, ...]: return tuple(states) +def _freeze_state(state: Mapping[str, Any]) -> Mapping[str, Any]: + """Freeze one returned state so closed candidate content cannot drift.""" + + return MappingProxyType( + { + "t": state["t"], + "visible_key": tuple(state["visible_key"]), + "complete_key": tuple(state["complete_key"]), + "frame": state["frame"], + } + ) + + def _canonical_record( element_id: str, symbol: str, @@ -162,7 +184,7 @@ def _canonical_record( proton_glyphs: tuple[str, ...], neutron_positions: tuple[int, ...], neutron_glyphs: tuple[str, ...], -) -> dict: +) -> dict[str, Any]: return { "element_id": element_id, "symbol": symbol, @@ -176,12 +198,12 @@ def _canonical_record( "ordered_parameter_id": CONSTRUCTION_IDS["ordered_parameter"], "t_states": list(_t_states()), "closure_scale": CONSTRUCTION_IDS["closure_scale"], - "source_commits": SOURCE_COMMITS, + "source_commits": dict(SOURCE_COMMITS), "status": CONSTRUCTION_IDS["status"], } -def element_receipt(record: dict) -> str: +def element_receipt(record: Mapping[str, Any]) -> str: """SHA-256 over canonical JSON of the construction record.""" payload = json.dumps(record, sort_keys=True, separators=(",", ":")) return hashlib.sha256(payload.encode("utf-8")).hexdigest() @@ -226,7 +248,7 @@ def affixiate_element(symbol: str) -> ElementCandidate: proton_glyphs=proton_glyphs, neutron_positions=neutron_positions, neutron_glyphs=neutron_glyphs, - t_states=record["t_states"], + t_states=tuple(_freeze_state(state) for state in record["t_states"]), relation_id=record["relation_id"], ordered_parameter_id=record["ordered_parameter_id"], closure_scale=record["closure_scale"], From 9540f02e7d578d120206cdd2e2de126bf780c536 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sun, 6 Sep 2026 05:25:39 -0700 Subject: [PATCH 04/33] test(epac): cover current provenance and immutable candidate state --- .../test_element_affixiation_candidate.py | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/subatomic/test_element_affixiation_candidate.py b/subatomic/test_element_affixiation_candidate.py index 76800d3..63f2f6a 100644 --- a/subatomic/test_element_affixiation_candidate.py +++ b/subatomic/test_element_affixiation_candidate.py @@ -45,11 +45,8 @@ def test_imports_consume_only_established_ucns_surfaces(): - # The candidate module surface must stay identity-only. If this test - # fails, a position operation or unestablished geometry was introduced. assert candidate.CONSTRUCTION_IDS["ordered_parameter"] == "ucns.native-mobius-turn-index" assert candidate.CONSTRUCTION_IDS["relation"] == "metapat.affixiation_harmonics.affixiation" - # The only UCNS geometry imported is carrier identity + Möbius framing. assert public_gonol_function(0).glyph == PUBLIC_GONOL_157[0] @@ -64,7 +61,6 @@ def test_element_identity_positions_exact(): element = candidate.affixiate_element(symbol) assert element.proton_positions == expected_p assert element.neutron_positions == expected_n - # Every assigned position is an identity coordinate on the carrier. assert all(0 <= i < len(PUBLIC_GONOL_157) for i in element.proton_positions) assert all(0 <= i < len(PUBLIC_GONOL_157) for i in element.neutron_positions) assert element.proton_glyphs == tuple( @@ -94,10 +90,26 @@ def test_receipt_deterministic_and_replayable(): assert matches is True assert replay_receipt == first.receipt assert len(first.receipt) == 64 - # Distinct participant sets produce distinct receipts. receipts = {candidate.affixiate_element(s).receipt for s in candidate.ISOTOPE_DEFAULTS} assert len(receipts) == len(candidate.ISOTOPE_DEFAULTS) + frozen = candidate.affixiate_element("He") + before = frozen.receipt + try: + frozen.t_states[0]["frame"] = "tampered" + except TypeError: + pass + else: + raise AssertionError("closed t_states must be immutable") + try: + frozen.source_commits["ucns"] = "tampered" + except TypeError: + pass + else: + raise AssertionError("closed source_commits must be immutable") + assert frozen.receipt == before + assert candidate.replay_element("He") == (True, before) + def test_no_physics_or_canon_claim(): for symbol in candidate.ISOTOPE_DEFAULTS: @@ -105,5 +117,5 @@ def test_no_physics_or_canon_claim(): assert element.status == "CROSS-DOMAIN-HYPOTHESIS" assert element.closure_scale == "epac.subatomic.atomic" assert candidate.SOURCE_COMMITS["metapat"] == "34d954aa1e2092e615b03a180500f6b6977f501e" - assert candidate.SOURCE_COMMITS["ucns"] == "1975fe70cf4e0826a8020c2da3047569e277af64" + assert candidate.SOURCE_COMMITS["ucns"] == "828c0b8bbcfc267efb5701da714191c1f73a81ff" assert PUBLIC_GONOL_SHA256 == "55d10c84529a4d7bc7714786357e977b68d9df2ac3f73d20e229580b552c2ef5" From b329ef50ab6853069dda74b02f8d52d54583033b Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sun, 6 Sep 2026 05:25:53 -0700 Subject: [PATCH 05/33] docs(epac): keep extraction verification unresolved --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index cdf8d99..9278406 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ EPAC is the independent repository for The Interdependency's elementary/particle ## Standing -- Physical repository state: extracted from the stack incubator and independently verified. +- Physical repository state: extracted from the stack incubator; exact candidate/forge verification remains unresolved until a dedicated immutable verification receipt exists. - Authority transition: incomplete until the release/reconsumption graduation gates are satisfied. - Research status: provisional / cross-domain hypothesis unless a narrower artifact says otherwise. - Empirical status: no transfer. Repository independence does not make a physics or chemistry claim true. @@ -35,14 +35,14 @@ The extraction preserves the stack research artifacts and their epistemic status ## Verification -The extraction gate executes: +The current extraction gate executes: - 41 repository regression tests; - 26 subatomic executable witnesses; - the preregistered molecular comparison, requiring all four current standings to remain `FALSIFIED`; - deterministic work-graph digest verification. -CI independently resolves the pinned UCNS source before running the same gates. +CI resolves the pinned UCNS source before running those gates. Passing those checks establishes reproducibility of the extracted research tree; it does **not** satisfy `exact_candidate_forge_verification`, stable release, or reconsumption by itself. ## Usage guidance @@ -52,6 +52,7 @@ Do not treat successful execution as empirical validation. Constructors establis ## hmmm +- exact candidate/forge verification receipt - distribution surface and first immutable release artifact - license/distribution-rights selection for this independent repository - clean package/install dependency contract for UCNS From 59fbd643c77f66869a13de18bf4d30f4187bb262 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sun, 6 Sep 2026 05:29:12 -0700 Subject: [PATCH 06/33] fix(epac): reject duplicate couplings and total-order quaternion readouts --- epac_dimensional_arity.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/epac_dimensional_arity.py b/epac_dimensional_arity.py index feaf55b..3d8a756 100644 --- a/epac_dimensional_arity.py +++ b/epac_dimensional_arity.py @@ -163,6 +163,11 @@ def __post_init__(self) -> None: ambient_ids = [dimension.id for dimension in self.ambient_dimensions] if len(ambient_ids) != len(set(ambient_ids)): raise DimensionalArityError("ambient dimensions must be unique") + coupling_ids = [item.declared_ids for item in self.couplings] + if len(coupling_ids) != len(set(coupling_ids)): + raise DimensionalArityError( + "coupling declarations must be unique; repeated physical occurrences require unique dimension ids" + ) ambient = set(ambient_ids) for item in self.couplings: missing = [name for name in item.declared_ids if name not in ambient] @@ -170,7 +175,7 @@ def __post_init__(self) -> None: raise DimensionalArityError( f"coupling {item.declared_ids} uses undeclared dimensions {tuple(missing)}" ) - declared = {item.declared_ids for item in self.couplings} + declared = set(coupling_ids) for proof in self.proofs: conclusion_missing = [ name for name in proof.conclusion.declared_ids if name not in ambient @@ -541,7 +546,7 @@ def quaternion_structure_readout(structure: Mapping[str, object]) -> tuple[objec _tuple_tree(item["represented_ids"]), ) for item in structure.get("quaternions", ()) - ) + , key=_sortable_tree) ) From 1befb60b29a4dc69d8b89ea7fa077a85f4f98810 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sun, 6 Sep 2026 05:37:31 -0700 Subject: [PATCH 07/33] fix(epac): repair quaternion readout syntax --- epac_dimensional_arity.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/epac_dimensional_arity.py b/epac_dimensional_arity.py index 3d8a756..2d68acf 100644 --- a/epac_dimensional_arity.py +++ b/epac_dimensional_arity.py @@ -542,11 +542,14 @@ def quaternion_structure_readout(structure: Mapping[str, object]) -> tuple[objec return tuple( sorted( ( - _tuple_tree(item["components"]), - _tuple_tree(item["represented_ids"]), - ) - for item in structure.get("quaternions", ()) - , key=_sortable_tree) + ( + _tuple_tree(item["components"]), + _tuple_tree(item["represented_ids"]), + ) + for item in structure.get("quaternions", ()) + ), + key=_sortable_tree, + ) ) From cfb24e28fcb566685b6e1732a2a38df82c2da60b Mon Sep 17 00:00:00 2001 From: Codex Date: Mon, 7 Sep 2026 13:09:33 +0000 Subject: [PATCH 08/33] fix(epac): close seal and provenance review gaps --- README.md | 4 +- epac_public_gonol.py | 83 ++++++++++++++--- subatomic/receipts/ucns-828c0b8/c.json | 88 +++++++++++++++++++ subatomic/receipts/ucns-828c0b8/h.json | 64 ++++++++++++++ subatomic/receipts/ucns-828c0b8/he.json | 72 +++++++++++++++ subatomic/receipts/ucns-828c0b8/li.json | 78 ++++++++++++++++ subatomic/subatomic-affixiation-baseline.md | 35 ++++++-- .../test_element_affixiation_candidate.py | 44 ++++++++++ tests/test_epac_public_gonol.py | 76 +++++++++++++++- 9 files changed, 523 insertions(+), 21 deletions(-) create mode 100644 subatomic/receipts/ucns-828c0b8/c.json create mode 100644 subatomic/receipts/ucns-828c0b8/h.json create mode 100644 subatomic/receipts/ucns-828c0b8/he.json create mode 100644 subatomic/receipts/ucns-828c0b8/li.json diff --git a/README.md b/README.md index 9278406..1001b6b 100644 --- a/README.md +++ b/README.md @@ -37,8 +37,8 @@ The extraction preserves the stack research artifacts and their epistemic status The current extraction gate executes: -- 41 repository regression tests; -- 26 subatomic executable witnesses; +- 45 repository regression tests; +- 28 subatomic executable witnesses; - the preregistered molecular comparison, requiring all four current standings to remain `FALSIFIED`; - deterministic work-graph digest verification. diff --git a/epac_public_gonol.py b/epac_public_gonol.py index 0041cf3..0877f74 100644 --- a/epac_public_gonol.py +++ b/epac_public_gonol.py @@ -31,7 +31,7 @@ # summary: EPAC candidate constructor that closes gonols on the UCNS Public Gonol carrier with oriented couplings and arity charge states; not the EDCM text-domain constructor # owner: The Interdependency # public_surface: CONSTRUCTOR_ID, CONSTRUCTOR_VERSION, PINNED_UCNS_COMMIT, PINNED_PUBLIC_GONOL_SHA256, ClosedPublicGonol, PublicGonolReceipt, PublicGonolConstructionError, construct_public_gonol, replay_public_gonol, canonical_receipt_bytes -# internal_surface: _require_text, _identity_position, _geometry, _participant_payload, _atomic_payload, _receipt_payload, _digest, _expected_structure_from_couplings +# internal_surface: _require_text, _identity_position, _verified_ucns_commit, _geometry, _tuple_tree, _canonical_structure_tree, _participant_payload, _atomic_payload, _receipt_payload, _digest, _expected_structure_from_couplings # auth_boundary: EPAC owns particle/energy gonol closure; UCNS owns Public Gonol carrier identity and native Möbius ε; EDCM text-domain constructor is not used; METAPAT affixiation is consumed, not redefined # storage_boundary: none; receipts remain caller-owned in-memory objects # network_boundary: none @@ -54,7 +54,7 @@ # # id: epac_public_gonol_binds_ucns_carrier_identity # given: identity_glyph is an admitted Public Gonol glyph -# then: the closed gonol carries the exact UCNS index/glyph pair, EPAC-owned pinned carrier digest, and exact pinned UCNS dependency identity +# then: the closed gonol carries the exact UCNS index/glyph pair, EPAC-owned pinned carrier digest, and exact pinned UCNS dependency identity only when the imported checkout head verifies; otherwise dependency identity remains hmmm # class: construction # since: 2026-08-22 # @@ -77,11 +77,15 @@ from collections.abc import Sequence as SequenceABC from dataclasses import dataclass from hashlib import sha256 +import inspect import json +from pathlib import Path +import subprocess from types import MappingProxyType from typing import Any, Mapping, Sequence from epac_dimensional_arity import ( + DimensionalArityError, MOBIUS_EPSILON_T0, space, structure_from_charged_couplings, @@ -113,8 +117,11 @@ "exact UCNS geometric operation of each Public Gonol function position", "UCNS Möbius-carrier affixiation/coupling law", "two-letter element symbols have no single Public Gonol glyph", + "runtime UCNS commit identity when the imported checkout head cannot be verified against the pin", ) +ORDER_INSENSITIVE_STRUCTURE_FIELDS = frozenset(("parts", "degree", "quaternions")) + class PublicGonolConstructionError(RuntimeError): """Fail-closed EPAC Public Gonol constructor error.""" @@ -174,6 +181,33 @@ def _identity_position(identity_glyph: str | None) -> tuple[str | None, int | No return (position.glyph, position.index) +def _verified_ucns_commit() -> str: + """Return the observed UCNS git commit only when it matches the pin.""" + + try: + source_path = Path(inspect.getfile(public_gonol_function)).resolve() + except (OSError, TypeError): + return "hmmm" + for parent in source_path.parents: + if not (parent / ".git").exists(): + continue + try: + result = subprocess.run( + ("git", "-C", str(parent), "rev-parse", "HEAD"), + check=True, + capture_output=True, + text=True, + timeout=2, + ) + except (OSError, subprocess.SubprocessError): + return "hmmm" + observed = result.stdout.strip() + if observed == PINNED_UCNS_COMMIT: + return observed + return "hmmm" + return "hmmm" + + def _geometry(identity_glyph: str | None, carrier_index: int | None) -> dict[str, Any]: digest = public_gonol_sha256() if digest != PINNED_PUBLIC_GONOL_SHA256: @@ -189,7 +223,7 @@ def _geometry(identity_glyph: str | None, carrier_index: int | None) -> dict[str "state": "bound", "authority": "ucns.public_gonol", "authority_binding": "explicit", - "ucns_commit": PINNED_UCNS_COMMIT, + "ucns_commit": _verified_ucns_commit(), "carrier_digest": digest, "identity_position": identity, "mobius_epsilon_t0": origin.frame.sign, @@ -223,6 +257,25 @@ def _tuple_tree(value: Any) -> Any: return value +def _canonical_structure_tree(structure: Mapping[str, Any]) -> Any: + canonical: list[tuple[str, Any]] = [] + for key, value in structure.items(): + field = str(key) + if field in ORDER_INSENSITIVE_STRUCTURE_FIELDS: + if not isinstance(value, SequenceABC) or isinstance(value, (str, bytes)): + canonical.append((field, _tuple_tree(value))) + continue + canonical.append( + ( + field, + tuple(sorted((_tuple_tree(item) for item in value), key=repr)), + ) + ) + continue + canonical.append((field, _tuple_tree(value))) + return tuple(sorted(canonical)) + + def _coupling_signature(item: Mapping[str, Any]) -> tuple[Any, int, Any]: declared = item.get("declared_ids", item.get("coupling")) charge_state = item.get("charge_state") @@ -268,6 +321,13 @@ def _coupling_declaration(item: Mapping[str, Any]) -> tuple[tuple[str, ...], tup for charge in charges ): raise PublicGonolConstructionError("slot_charges must align with declared dimensions") + epsilon = item.get("mobius_epsilon_t0") + if epsilon is not None and ( + isinstance(epsilon, bool) + or not isinstance(epsilon, int) + or epsilon != MOBIUS_EPSILON_T0 + ): + raise PublicGonolConstructionError("coupling mobius_epsilon_t0 conflicts with canonical epsilon") if charge_state is not None and _tuple_tree(charge_state) != _tuple_tree( (charges, MOBIUS_EPSILON_T0) ): @@ -292,12 +352,15 @@ def _expected_structure_from_couplings( f"dimension {name!r} has conflicting charges across couplings" ) charge_by_id[name] = charge - declared = space( - ambient_ids, - declarations, - charges={name: charge for name, charge in charge_by_id.items() if charge is not None}, - ) - return structure_from_charged_couplings(declared) + try: + declared = space( + ambient_ids, + declarations, + charges={name: charge for name, charge in charge_by_id.items() if charge is not None}, + ) + return structure_from_charged_couplings(declared) + except DimensionalArityError as exc: + raise PublicGonolConstructionError(str(exc)) from exc def _validate_structure_matches_couplings( @@ -320,7 +383,7 @@ def _validate_structure_matches_couplings( "structure must match the supplied declared couplings before closure" ) expected_structure = _expected_structure_from_couplings(couplings) - if _tuple_tree(structure) != _tuple_tree(expected_structure): + if _canonical_structure_tree(structure) != _canonical_structure_tree(expected_structure): raise PublicGonolConstructionError( "structure derived fields must exactly match the declared couplings before closure" ) diff --git a/subatomic/receipts/ucns-828c0b8/c.json b/subatomic/receipts/ucns-828c0b8/c.json new file mode 100644 index 0000000..ba366fa --- /dev/null +++ b/subatomic/receipts/ucns-828c0b8/c.json @@ -0,0 +1,88 @@ +{ + "A": 12, + "Z": 6, + "closure_scale": "epac.subatomic.atomic", + "element_id": "epac.subatomic_affixiation.c", + "neutron_glyphs": [ + "C", + "%", + "(", + "D", + "&", + "'" + ], + "neutron_positions": [ + 7, + 8, + 9, + 10, + 11, + 12 + ], + "ordered_parameter_id": "ucns.native-mobius-turn-index", + "proton_glyphs": [ + "A", + "!", + "\"", + "B", + "#", + "$" + ], + "proton_positions": [ + 1, + 2, + 3, + 4, + 5, + 6 + ], + "receipt": "20277205b5a82f34cd7c78fe70c9235725918f3a025f1ab3427e4cfe46ba6d90", + "relation_id": "metapat.affixiation_harmonics.affixiation", + "source_commits": { + "metapat": "34d954aa1e2092e615b03a180500f6b6977f501e", + "ucns": "828c0b8bbcfc267efb5701da714191c1f73a81ff" + }, + "status": "CROSS-DOMAIN-HYPOTHESIS", + "symbol": "C", + "t_states": [ + { + "complete_key": [ + "ucns.native-mobius-root-loop", + "0", + "positive-local-frame" + ], + "frame": "positive-local-frame", + "t": 0, + "visible_key": [ + "ucns.native-mobius-root-loop", + "0" + ] + }, + { + "complete_key": [ + "ucns.native-mobius-root-loop", + "0", + "reversed-local-frame" + ], + "frame": "reversed-local-frame", + "t": 1, + "visible_key": [ + "ucns.native-mobius-root-loop", + "0" + ] + }, + { + "complete_key": [ + "ucns.native-mobius-root-loop", + "0", + "positive-local-frame" + ], + "frame": "positive-local-frame", + "t": 2, + "visible_key": [ + "ucns.native-mobius-root-loop", + "0" + ] + } + ] +} diff --git a/subatomic/receipts/ucns-828c0b8/h.json b/subatomic/receipts/ucns-828c0b8/h.json new file mode 100644 index 0000000..9f30220 --- /dev/null +++ b/subatomic/receipts/ucns-828c0b8/h.json @@ -0,0 +1,64 @@ +{ + "A": 1, + "Z": 1, + "closure_scale": "epac.subatomic.atomic", + "element_id": "epac.subatomic_affixiation.h", + "neutron_glyphs": [], + "neutron_positions": [], + "ordered_parameter_id": "ucns.native-mobius-turn-index", + "proton_glyphs": [ + "A" + ], + "proton_positions": [ + 1 + ], + "receipt": "0a18ccf77bc26884796993925556204bf1ea3868594e076116389b853e73b248", + "relation_id": "metapat.affixiation_harmonics.affixiation", + "source_commits": { + "metapat": "34d954aa1e2092e615b03a180500f6b6977f501e", + "ucns": "828c0b8bbcfc267efb5701da714191c1f73a81ff" + }, + "status": "CROSS-DOMAIN-HYPOTHESIS", + "symbol": "H", + "t_states": [ + { + "complete_key": [ + "ucns.native-mobius-root-loop", + "0", + "positive-local-frame" + ], + "frame": "positive-local-frame", + "t": 0, + "visible_key": [ + "ucns.native-mobius-root-loop", + "0" + ] + }, + { + "complete_key": [ + "ucns.native-mobius-root-loop", + "0", + "reversed-local-frame" + ], + "frame": "reversed-local-frame", + "t": 1, + "visible_key": [ + "ucns.native-mobius-root-loop", + "0" + ] + }, + { + "complete_key": [ + "ucns.native-mobius-root-loop", + "0", + "positive-local-frame" + ], + "frame": "positive-local-frame", + "t": 2, + "visible_key": [ + "ucns.native-mobius-root-loop", + "0" + ] + } + ] +} diff --git a/subatomic/receipts/ucns-828c0b8/he.json b/subatomic/receipts/ucns-828c0b8/he.json new file mode 100644 index 0000000..10b772c --- /dev/null +++ b/subatomic/receipts/ucns-828c0b8/he.json @@ -0,0 +1,72 @@ +{ + "A": 4, + "Z": 2, + "closure_scale": "epac.subatomic.atomic", + "element_id": "epac.subatomic_affixiation.he", + "neutron_glyphs": [ + "\"", + "B" + ], + "neutron_positions": [ + 3, + 4 + ], + "ordered_parameter_id": "ucns.native-mobius-turn-index", + "proton_glyphs": [ + "A", + "!" + ], + "proton_positions": [ + 1, + 2 + ], + "receipt": "145ceddd22231a681cd4cb57aa46a5eeeb680ab1d93ccfa4d6b454b8264ee0fb", + "relation_id": "metapat.affixiation_harmonics.affixiation", + "source_commits": { + "metapat": "34d954aa1e2092e615b03a180500f6b6977f501e", + "ucns": "828c0b8bbcfc267efb5701da714191c1f73a81ff" + }, + "status": "CROSS-DOMAIN-HYPOTHESIS", + "symbol": "He", + "t_states": [ + { + "complete_key": [ + "ucns.native-mobius-root-loop", + "0", + "positive-local-frame" + ], + "frame": "positive-local-frame", + "t": 0, + "visible_key": [ + "ucns.native-mobius-root-loop", + "0" + ] + }, + { + "complete_key": [ + "ucns.native-mobius-root-loop", + "0", + "reversed-local-frame" + ], + "frame": "reversed-local-frame", + "t": 1, + "visible_key": [ + "ucns.native-mobius-root-loop", + "0" + ] + }, + { + "complete_key": [ + "ucns.native-mobius-root-loop", + "0", + "positive-local-frame" + ], + "frame": "positive-local-frame", + "t": 2, + "visible_key": [ + "ucns.native-mobius-root-loop", + "0" + ] + } + ] +} diff --git a/subatomic/receipts/ucns-828c0b8/li.json b/subatomic/receipts/ucns-828c0b8/li.json new file mode 100644 index 0000000..4a13961 --- /dev/null +++ b/subatomic/receipts/ucns-828c0b8/li.json @@ -0,0 +1,78 @@ +{ + "A": 7, + "Z": 3, + "closure_scale": "epac.subatomic.atomic", + "element_id": "epac.subatomic_affixiation.li", + "neutron_glyphs": [ + "B", + "#", + "$", + "C" + ], + "neutron_positions": [ + 4, + 5, + 6, + 7 + ], + "ordered_parameter_id": "ucns.native-mobius-turn-index", + "proton_glyphs": [ + "A", + "!", + "\"" + ], + "proton_positions": [ + 1, + 2, + 3 + ], + "receipt": "fd883cc78641d2006d1579b4a3a2f5b065cdc2a0c74d6bb1eabf926b9f02685f", + "relation_id": "metapat.affixiation_harmonics.affixiation", + "source_commits": { + "metapat": "34d954aa1e2092e615b03a180500f6b6977f501e", + "ucns": "828c0b8bbcfc267efb5701da714191c1f73a81ff" + }, + "status": "CROSS-DOMAIN-HYPOTHESIS", + "symbol": "Li", + "t_states": [ + { + "complete_key": [ + "ucns.native-mobius-root-loop", + "0", + "positive-local-frame" + ], + "frame": "positive-local-frame", + "t": 0, + "visible_key": [ + "ucns.native-mobius-root-loop", + "0" + ] + }, + { + "complete_key": [ + "ucns.native-mobius-root-loop", + "0", + "reversed-local-frame" + ], + "frame": "reversed-local-frame", + "t": 1, + "visible_key": [ + "ucns.native-mobius-root-loop", + "0" + ] + }, + { + "complete_key": [ + "ucns.native-mobius-root-loop", + "0", + "positive-local-frame" + ], + "frame": "positive-local-frame", + "t": 2, + "visible_key": [ + "ucns.native-mobius-root-loop", + "0" + ] + } + ] +} diff --git a/subatomic/subatomic-affixiation-baseline.md b/subatomic/subatomic-affixiation-baseline.md index 6aa124f..f309dc8 100644 --- a/subatomic/subatomic-affixiation-baseline.md +++ b/subatomic/subatomic-affixiation-baseline.md @@ -59,7 +59,9 @@ hydrogen/helium/lithium claims exist in current metapat or ucns checkouts. Resol ## 3. UCNS established baseline (implemented surfaces only) -Cited from current UCNS at `1975fe70`: +Cited from the historical UCNS baseline at `1975fe70`; the extracted EPAC +constructor currently pins UCNS `828c0b8bbcfc267efb5701da714191c1f73a81ff` and +retains the historical receipts as prior-version evidence: - **Public Gonol carrier** (`implemented`): exactly 157 one-scalar glyph positions in fixed order; digest `55d10c84529a4d7bc7714786357e977b68d9df2ac3f73d20e229580b552c2ef5`; every glyph is a @@ -147,7 +149,8 @@ projection; any canon promotion in METAPAT, UCNS, or elsewhere. To replay by hand: -1. Pin sources: METAPAT `34d954a`, UCNS `1975fe7` (recorded above and in `STACK_MANIFEST.md`). +1. Pin sources: METAPAT `34d954a`, UCNS `828c0b8` for the current extracted constructor; the + `1975fe7` receipt set is historical. 2. Read `metapat/docs/applications/affixiation-harmonics.md` for the semantic definitions used. 3. Read `ucns/src/ucns/public_gonol.py` and `ucns/src/ucns/direct_mobius.py` for the carrier and Möbius surfaces used. @@ -194,9 +197,11 @@ The frozen minimal decisive action from §7 is now implemented locally (not push - `element_affixiation_candidate.py` — identity-only constructor for H/He/Li/C consuming only `ucns.public_gonol_function` and `ucns.native_mobius_state`. Carries `MODULE_BUILD` and `CONTRACTS` blocks; no position operation is defined or inferred. -- `test_element_affixiation_candidate.py` — five executable witnesses with a `CHECKS` block. - Result: **5 passed** against the pinned UCNS snapshot package (`ucns/src` at `1975fe7`). -- `receipts/` — sealed construction receipts, one per element: +- `test_element_affixiation_candidate.py` — executable witnesses with a `CHECKS` block. + Current result: source-synchronized witnesses pass against the extracted EPAC UCNS pin + `828c0b8`. +- `receipts/{h,he,li,c}.json` — historical sealed construction receipts at UCNS `1975fe7`, + retained as prior-version evidence: | Element | Receipt (SHA-256) | |---|---| @@ -205,7 +210,19 @@ The frozen minimal decisive action from §7 is now implemented locally (not push | Li | `5efefff19f97e4f42fa0d85d9719adbe07c39fc7dab700a5eea13f434611bb3f` | | C | `a4026f197d6a0425b4ea5b3ff72d09d49fd159d5f59440480b5f97793b64cdc6` | -- Independent replay (`replay_element`) is byte-identical for all four elements. +- These historical records were byte-identical under their original UCNS pin; they are not the + current extracted-constructor receipts. +- `receipts/ucns-828c0b8/` — current sealed construction receipts at the extracted EPAC UCNS + pin: + + | Element | Receipt (SHA-256) | + |---|---| + | H | `0a18ccf77bc26884796993925556204bf1ea3868594e076116389b853e73b248` | + | He | `145ceddd22231a681cd4cb57aa46a5eeeb680ab1d93ccfa4d6b454b8264ee0fb` | + | Li | `fd883cc78641d2006d1579b4a3a2f5b065cdc2a0c74d6bb1eabf926b9f02685f` | + | C | `20277205b5a82f34cd7c78fe70c9235725918f3a025f1ab3427e4cfe46ba6d90` | + +- Independent replay (`replay_element`) is byte-identical for the current constructor outputs. - Status remains `CROSS-DOMAIN-HYPOTHESIS / provisional`. Nothing here establishes position operations, geometry between positions, harmonic notation, physics, or canon. @@ -280,7 +297,9 @@ law, and no scale interchange is introduced. Standing is `implemented-candidate` Two-letter names (He, Fe) are two ordered name-characters, not physical `(z, x)` / `(z, y)` couplings and not nuclear-Z charge states. Physics 3-structure stays on atom instances only. -- Evidence: **26/26 subatomic tests pass**; sibling epac suite **29 tests OK**; - CONTRACTS↔CHECKS audit **closed** (26 contracts / 26 checks). +- Historical evidence at this section's original 2026-08-22 stop: **26/26 subatomic tests + pass**; sibling epac suite **29 tests OK**; CONTRACTS↔CHECKS audit **closed** + (26 contracts / 26 checks). Current extracted-repo gate records **28 subatomic witnesses** + and **45 repository tests**. - The dimensional-arity doctrine is implemented by the sibling `epac_dimensional_arity.py` (committed); no duplicate is maintained here. Status remains `CROSS-DOMAIN-HYPOTHESIS`. diff --git a/subatomic/test_element_affixiation_candidate.py b/subatomic/test_element_affixiation_candidate.py index 63f2f6a..4c7032d 100644 --- a/subatomic/test_element_affixiation_candidate.py +++ b/subatomic/test_element_affixiation_candidate.py @@ -25,6 +25,18 @@ # mutates: none # cleanup: none # +# id: check_current_versioned_receipts_match_declared_ucns_pin +# proves: receipt_deterministic_and_replayable +# call: self::test_current_versioned_receipts_match_declared_ucns_pin +# mutates: none +# cleanup: none +# +# id: check_historical_receipts_remain_versioned_evidence +# proves: no_physics_or_canon_claim +# call: self::test_historical_receipts_remain_versioned_evidence +# mutates: none +# cleanup: none +# # id: check_no_physics_or_canon_claim # proves: no_physics_or_canon_claim # call: self::test_no_physics_or_canon_claim @@ -33,6 +45,8 @@ # === END CHECKS === from fractions import Fraction +import json +from pathlib import Path import element_affixiation_candidate as candidate from ucns import ( @@ -44,6 +58,10 @@ ) +RECEIPT_ROOT = Path(__file__).resolve().parent / "receipts" +CURRENT_RECEIPT_ROOT = RECEIPT_ROOT / "ucns-828c0b8" + + def test_imports_consume_only_established_ucns_surfaces(): assert candidate.CONSTRUCTION_IDS["ordered_parameter"] == "ucns.native-mobius-turn-index" assert candidate.CONSTRUCTION_IDS["relation"] == "metapat.affixiation_harmonics.affixiation" @@ -111,6 +129,32 @@ def test_receipt_deterministic_and_replayable(): assert candidate.replay_element("He") == (True, before) +def test_current_versioned_receipts_match_declared_ucns_pin(): + for symbol in ("H", "He", "Li", "C"): + element = candidate.affixiate_element(symbol) + expected = candidate._canonical_record( + element_id=element.element_id, + symbol=element.symbol, + Z=element.Z, + A=element.A, + proton_positions=element.proton_positions, + proton_glyphs=element.proton_glyphs, + neutron_positions=element.neutron_positions, + neutron_glyphs=element.neutron_glyphs, + ) + expected["receipt"] = element.receipt + observed = json.loads((CURRENT_RECEIPT_ROOT / f"{symbol.lower()}.json").read_text()) + assert observed == expected + assert observed["source_commits"]["ucns"] == candidate.SOURCE_COMMITS["ucns"] + + +def test_historical_receipts_remain_versioned_evidence(): + for name in ("h", "he", "li", "c"): + historical = json.loads((RECEIPT_ROOT / f"{name}.json").read_text()) + assert historical["source_commits"]["ucns"] == "1975fe70cf4e0826a8020c2da3047569e277af64" + assert historical["source_commits"]["ucns"] != candidate.SOURCE_COMMITS["ucns"] + + def test_no_physics_or_canon_claim(): for symbol in candidate.ISOTOPE_DEFAULTS: element = candidate.affixiate_element(symbol) diff --git a/tests/test_epac_public_gonol.py b/tests/test_epac_public_gonol.py index 5f26b84..e649c75 100644 --- a/tests/test_epac_public_gonol.py +++ b/tests/test_epac_public_gonol.py @@ -8,7 +8,8 @@ EPAC_ROOT = Path(__file__).resolve().parents[1] sys.path.insert(0, str(EPAC_ROOT)) -from epac_dimensional_arity import space, geometry_from_declared_couplings +from epac_dimensional_arity import DimensionalArityError, space, geometry_from_declared_couplings +import epac_public_gonol as public_gonol_module from epac_public_gonol import ( CONSTRUCTOR_ID, PINNED_PUBLIC_GONOL_SHA256, @@ -90,6 +91,25 @@ def test_charged_couplings_are_the_structure(self) -> None: ) self.assertEqual(native_mobius_state(0).frame.sign, 1) + def test_order_insensitive_derived_collections_still_seal(self) -> None: + declared = space( + ["x", "z", "y"], + [["z", "x"], ["z", "y"]], + charges={"z": 8, "x": 1, "y": 1}, + ) + geometry = geometry_from_declared_couplings(declared) + structure = copy.deepcopy(geometry["structure"]) + structure["parts"] = tuple(reversed(structure["parts"])) + structure["degree"] = tuple(reversed(structure["degree"])) + structure["quaternions"] = tuple(reversed(structure["quaternions"])) + receipt = construct_public_gonol( + source_id="epac.test:ambient-order-seal", + relation="epac.affixiation.unpaired-valence", + couplings=geometry["couplings"], + structure=structure, + ) + self.assertEqual(receipt.structure["participating_dimension_count"], 3) + def test_nested_geometry_is_frozen_after_closure(self) -> None: declared = space( ["z", "x"], @@ -157,6 +177,60 @@ def test_structure_must_match_declared_couplings(self) -> None: couplings=geometry["couplings"], ) + def test_standalone_mobius_epsilon_must_match_charge_state(self) -> None: + declared = space( + ["z", "x"], + [["z", "x"]], + charges={"z": 8, "x": 1}, + ) + geometry = geometry_from_declared_couplings(declared) + bad_couplings = copy.deepcopy(geometry["couplings"]) + bad_couplings[0]["mobius_epsilon_t0"] = -1 + with self.assertRaisesRegex(PublicGonolConstructionError, "mobius_epsilon_t0"): + construct_public_gonol( + source_id="epac.test:bad-epsilon", + relation="epac.affixiation.unpaired-valence", + couplings=bad_couplings, + structure=geometry["structure"], + ) + + def test_dimensional_errors_are_normalized_at_public_boundary(self) -> None: + duplicated = ( + { + "declared_ids": ("x", "x"), + "arity": 2, + "slot_charges": (1, 1), + "charge_state": ((1, 1), 1), + "mobius_epsilon_t0": 1, + }, + ) + structure = { + "parts": ( + { + "coupling": ("x", "x"), + "arity": 2, + "charge_state": ((1, 1), 1), + }, + ) + } + with self.assertRaises(PublicGonolConstructionError) as raised: + construct_public_gonol( + source_id="epac.test:duplicate-dimension", + relation="epac.affixiation.unpaired-valence", + couplings=duplicated, + structure=structure, + ) + self.assertIsInstance(raised.exception.__cause__, DimensionalArityError) + + def test_ucns_commit_is_not_stamped_when_runtime_head_is_not_verified(self) -> None: + original_pin = public_gonol_module.PINNED_UCNS_COMMIT + public_gonol_module.PINNED_UCNS_COMMIT = "0" * 40 + try: + geometry = public_gonol_module._geometry(None, None) + finally: + public_gonol_module.PINNED_UCNS_COMMIT = original_pin + self.assertEqual(geometry["ucns_commit"], "hmmm") + def test_unknown_glyph_fails_closed(self) -> None: with self.assertRaises(PublicGonolConstructionError): construct_public_gonol( From 86e6174a0e3c8668c4396c48e799e71cc84e04e0 Mon Sep 17 00:00:00 2001 From: Codex Date: Mon, 7 Sep 2026 13:48:23 +0000 Subject: [PATCH 09/33] fix(epac): seal canonical coupling provenance --- README.md | 2 +- epac_public_gonol.py | 214 +++++++++++++++++--- subatomic/subatomic-affixiation-baseline.md | 2 +- tests/test_epac_public_gonol.py | 101 +++++++++ 4 files changed, 291 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 1001b6b..c231ce8 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ The extraction preserves the stack research artifacts and their epistemic status The current extraction gate executes: -- 45 repository regression tests; +- 49 repository regression tests; - 28 subatomic executable witnesses; - the preregistered molecular comparison, requiring all four current standings to remain `FALSIFIED`; - deterministic work-graph digest verification. diff --git a/epac_public_gonol.py b/epac_public_gonol.py index 0877f74..6d32d99 100644 --- a/epac_public_gonol.py +++ b/epac_public_gonol.py @@ -31,7 +31,7 @@ # summary: EPAC candidate constructor that closes gonols on the UCNS Public Gonol carrier with oriented couplings and arity charge states; not the EDCM text-domain constructor # owner: The Interdependency # public_surface: CONSTRUCTOR_ID, CONSTRUCTOR_VERSION, PINNED_UCNS_COMMIT, PINNED_PUBLIC_GONOL_SHA256, ClosedPublicGonol, PublicGonolReceipt, PublicGonolConstructionError, construct_public_gonol, replay_public_gonol, canonical_receipt_bytes -# internal_surface: _require_text, _identity_position, _verified_ucns_commit, _geometry, _tuple_tree, _canonical_structure_tree, _participant_payload, _atomic_payload, _receipt_payload, _digest, _expected_structure_from_couplings +# internal_surface: _require_text, _identity_position, _verified_ucns_commit, _geometry, _tuple_tree, _canonical_coupling_record, _coupling_sort_key, _canonical_structure_tree, _participant_payload, _atomic_payload, _receipt_payload, _digest, _expected_structure_from_couplings # auth_boundary: EPAC owns particle/energy gonol closure; UCNS owns Public Gonol carrier identity and native Möbius ε; EDCM text-domain constructor is not used; METAPAT affixiation is consumed, not redefined # storage_boundary: none; receipts remain caller-owned in-memory objects # network_boundary: none @@ -54,7 +54,7 @@ # # id: epac_public_gonol_binds_ucns_carrier_identity # given: identity_glyph is an admitted Public Gonol glyph -# then: the closed gonol carries the exact UCNS index/glyph pair, EPAC-owned pinned carrier digest, and exact pinned UCNS dependency identity only when the imported checkout head verifies; otherwise dependency identity remains hmmm +# then: the closed gonol carries the exact UCNS index/glyph pair, EPAC-owned pinned carrier digest, and exact pinned UCNS dependency identity only when the imported checkout head and relevant source files verify clean; otherwise dependency identity remains hmmm # class: construction # since: 2026-08-22 # @@ -117,10 +117,20 @@ "exact UCNS geometric operation of each Public Gonol function position", "UCNS Möbius-carrier affixiation/coupling law", "two-letter element symbols have no single Public Gonol glyph", - "runtime UCNS commit identity when the imported checkout head cannot be verified against the pin", + "runtime UCNS commit identity when the imported checkout head and relevant source files cannot be verified clean against the pin", ) ORDER_INSENSITIVE_STRUCTURE_FIELDS = frozenset(("parts", "degree", "quaternions")) +COUPLING_SCHEMA_FIELDS = frozenset( + ( + "declared_ids", + "coupling", + "arity", + "slot_charges", + "charge_state", + "mobius_epsilon_t0", + ) +) class PublicGonolConstructionError(RuntimeError): @@ -181,31 +191,94 @@ def _identity_position(identity_glyph: str | None) -> tuple[str | None, int | No return (position.glyph, position.index) +def _git_root_for(path: Path) -> Path | None: + try: + result = subprocess.run( + ("git", "-C", str(path.parent), "rev-parse", "--show-toplevel"), + check=True, + capture_output=True, + text=True, + timeout=2, + ) + except (OSError, subprocess.SubprocessError): + return None + return Path(result.stdout.strip()).resolve() + + +def _ucns_source_paths() -> tuple[Path, ...]: + paths: list[Path] = [] + for dependency in (public_gonol_function, public_gonol_sha256, native_mobius_state): + try: + source_path = Path(inspect.getfile(dependency)).resolve() + except (OSError, TypeError): + return () + if source_path not in paths: + paths.append(source_path) + return tuple(paths) + + def _verified_ucns_commit() -> str: - """Return the observed UCNS git commit only when it matches the pin.""" + """Return the observed UCNS git commit only when source bytes match the pin.""" - try: - source_path = Path(inspect.getfile(public_gonol_function)).resolve() - except (OSError, TypeError): + source_paths = _ucns_source_paths() + if not source_paths: return "hmmm" - for parent in source_path.parents: - if not (parent / ".git").exists(): - continue + root = _git_root_for(source_paths[0]) + if root is None: + return "hmmm" + relative_paths: list[str] = [] + for source_path in source_paths: + if _git_root_for(source_path) != root: + return "hmmm" try: - result = subprocess.run( - ("git", "-C", str(parent), "rev-parse", "HEAD"), + relative_paths.append(source_path.relative_to(root).as_posix()) + except ValueError: + return "hmmm" + + try: + result = subprocess.run( + ("git", "-C", str(root), "rev-parse", "HEAD"), + check=True, + capture_output=True, + text=True, + timeout=2, + ) + except (OSError, subprocess.SubprocessError): + return "hmmm" + observed = result.stdout.strip() + if observed != PINNED_UCNS_COMMIT: + return "hmmm" + + try: + for relative_path in relative_paths: + subprocess.run( + ("git", "-C", str(root), "ls-files", "--error-unmatch", "--", relative_path), check=True, capture_output=True, text=True, timeout=2, ) - except (OSError, subprocess.SubprocessError): - return "hmmm" - observed = result.stdout.strip() - if observed == PINNED_UCNS_COMMIT: - return observed + status = subprocess.run( + ( + "git", + "-C", + str(root), + "status", + "--porcelain=v1", + "--untracked-files=no", + "--", + *relative_paths, + ), + check=True, + capture_output=True, + text=True, + timeout=2, + ) + except (OSError, subprocess.SubprocessError): return "hmmm" - return "hmmm" + if status.stdout.strip(): + return "hmmm" + return observed def _geometry(identity_glyph: str | None, carrier_index: int | None) -> dict[str, Any]: @@ -265,12 +338,69 @@ def _canonical_structure_tree(structure: Mapping[str, Any]) -> Any: if not isinstance(value, SequenceABC) or isinstance(value, (str, bytes)): canonical.append((field, _tuple_tree(value))) continue - canonical.append( - ( - field, - tuple(sorted((_tuple_tree(item) for item in value), key=repr)), + canonical_items = tuple( + _canonical_degree_tree(item) + if field == "degree" + else _canonical_quaternion_tree(item) + if field == "quaternions" + else _tuple_tree(item) + for item in value + ) + canonical.append((field, tuple(sorted(canonical_items, key=repr)))) + continue + canonical.append((field, _tuple_tree(value))) + return tuple(sorted(canonical)) + + +def _canonical_quaternion_tree(item: Any) -> Any: + if not isinstance(item, MappingABC): + return _tuple_tree(item) + represented_ids = item.get("represented_ids") + components = item.get("components") + axes = item.get("axes") + if ( + isinstance(represented_ids, SequenceABC) + and not isinstance(represented_ids, (str, bytes)) + and isinstance(components, SequenceABC) + and not isinstance(components, (str, bytes)) + and isinstance(axes, SequenceABC) + and not isinstance(axes, (str, bytes)) + and len(represented_ids) == 3 + and len(components) == 4 + and len(axes) == 4 + ): + local_three = ( + (axes[0], components[0]), + (represented_ids[0], axes[1], components[1]), + tuple( + sorted( + ( + (represented_ids[1], axes[2], components[2]), + (represented_ids[2], axes[3], components[3]), + ), + key=repr, ) + ), + ) + generic_fields = tuple( + sorted( + (str(key), _tuple_tree(value)) + for key, value in item.items() + if str(key) not in {"axes", "components", "represented_ids"} ) + ) + return generic_fields + (("local_three", _tuple_tree(local_three)),) + return _tuple_tree(item) + + +def _canonical_degree_tree(item: Any) -> Any: + if not isinstance(item, MappingABC): + return _tuple_tree(item) + canonical: list[tuple[str, Any]] = [] + for key, value in item.items(): + field = str(key) + if field == "incidences" and isinstance(value, SequenceABC) and not isinstance(value, (str, bytes)): + canonical.append((field, tuple(sorted((_tuple_tree(entry) for entry in value), key=repr)))) continue canonical.append((field, _tuple_tree(value))) return tuple(sorted(canonical)) @@ -293,6 +423,16 @@ def _structure_part_signature(item: Mapping[str, Any]) -> tuple[Any, int, Any]: def _coupling_declaration(item: Mapping[str, Any]) -> tuple[tuple[str, ...], tuple[int | None, ...]]: + if not isinstance(item, MappingABC): + raise PublicGonolConstructionError("each coupling must be a mapping") + extra_fields = frozenset(str(key) for key in item) - COUPLING_SCHEMA_FIELDS + if extra_fields: + names = ", ".join(sorted(extra_fields)) + raise PublicGonolConstructionError(f"coupling carries undeclared field(s): {names}") + if "declared_ids" in item and "coupling" in item and _tuple_tree(item["declared_ids"]) != _tuple_tree( + item["coupling"] + ): + raise PublicGonolConstructionError("coupling declared_ids conflicts with coupling") declared = item.get("declared_ids", item.get("coupling")) if not isinstance(declared, SequenceABC) or isinstance(declared, (str, bytes)) or not declared: raise PublicGonolConstructionError("each coupling must declare ordered dimension ids") @@ -321,9 +461,9 @@ def _coupling_declaration(item: Mapping[str, Any]) -> tuple[tuple[str, ...], tup for charge in charges ): raise PublicGonolConstructionError("slot_charges must align with declared dimensions") - epsilon = item.get("mobius_epsilon_t0") - if epsilon is not None and ( - isinstance(epsilon, bool) + if "mobius_epsilon_t0" in item and ( + (epsilon := item["mobius_epsilon_t0"]) is None + or isinstance(epsilon, bool) or not isinstance(epsilon, int) or epsilon != MOBIUS_EPSILON_T0 ): @@ -335,6 +475,23 @@ def _coupling_declaration(item: Mapping[str, Any]) -> tuple[tuple[str, ...], tup return ids, charges +def _canonical_coupling_record(item: Mapping[str, Any]) -> Mapping[str, Any]: + ids, charges = _coupling_declaration(item) + return _freeze_json( + { + "declared_ids": ids, + "arity": len(ids), + "slot_charges": charges, + "charge_state": (charges, MOBIUS_EPSILON_T0), + "mobius_epsilon_t0": MOBIUS_EPSILON_T0, + } + ) + + +def _coupling_sort_key(item: Mapping[str, Any]) -> str: + return repr(_coupling_signature(item)) + + def _expected_structure_from_couplings( couplings: Sequence[Mapping[str, Any]], ) -> Mapping[str, object]: @@ -500,7 +657,12 @@ def construct_public_gonol( ) for key, value in carried_options ) - frozen_couplings = tuple(_freeze_json(item) for item in couplings) + frozen_couplings = tuple( + sorted( + (_canonical_coupling_record(item) for item in couplings), + key=_coupling_sort_key, + ) + ) frozen_structure = None if structure is None else _freeze_json(structure) _validate_structure_matches_couplings(frozen_couplings, frozen_structure) glyph, index = _identity_position(identity_glyph) diff --git a/subatomic/subatomic-affixiation-baseline.md b/subatomic/subatomic-affixiation-baseline.md index f309dc8..ddd9ae2 100644 --- a/subatomic/subatomic-affixiation-baseline.md +++ b/subatomic/subatomic-affixiation-baseline.md @@ -300,6 +300,6 @@ law, and no scale interchange is introduced. Standing is `implemented-candidate` - Historical evidence at this section's original 2026-08-22 stop: **26/26 subatomic tests pass**; sibling epac suite **29 tests OK**; CONTRACTS↔CHECKS audit **closed** (26 contracts / 26 checks). Current extracted-repo gate records **28 subatomic witnesses** - and **45 repository tests**. + and **49 repository tests**. - The dimensional-arity doctrine is implemented by the sibling `epac_dimensional_arity.py` (committed); no duplicate is maintained here. Status remains `CROSS-DOMAIN-HYPOTHESIS`. diff --git a/tests/test_epac_public_gonol.py b/tests/test_epac_public_gonol.py index e649c75..d60cab9 100644 --- a/tests/test_epac_public_gonol.py +++ b/tests/test_epac_public_gonol.py @@ -110,6 +110,28 @@ def test_order_insensitive_derived_collections_still_seal(self) -> None: ) self.assertEqual(receipt.structure["participating_dimension_count"], 3) + def test_coupling_collection_order_is_canonicalized_before_sealing(self) -> None: + declared = space( + ["z", "x", "y"], + [["z", "x"], ["z", "y"]], + charges={"z": 8, "x": 1, "y": 1}, + ) + geometry = geometry_from_declared_couplings(declared) + first = construct_public_gonol( + source_id="epac.test:reordered-couplings", + relation="epac.affixiation.unpaired-valence", + couplings=geometry["couplings"], + structure=geometry["structure"], + ) + second = construct_public_gonol( + source_id="epac.test:reordered-couplings", + relation="epac.affixiation.unpaired-valence", + couplings=tuple(reversed(geometry["couplings"])), + structure=geometry["structure"], + ) + self.assertEqual(first.gonol.couplings, second.gonol.couplings) + self.assertEqual(first.receipt_digest, second.receipt_digest) + def test_nested_geometry_is_frozen_after_closure(self) -> None: declared = space( ["z", "x"], @@ -194,6 +216,59 @@ def test_standalone_mobius_epsilon_must_match_charge_state(self) -> None: structure=geometry["structure"], ) + null_couplings = copy.deepcopy(geometry["couplings"]) + null_couplings[0]["mobius_epsilon_t0"] = None + with self.assertRaisesRegex(PublicGonolConstructionError, "mobius_epsilon_t0"): + construct_public_gonol( + source_id="epac.test:null-epsilon", + relation="epac.affixiation.unpaired-valence", + couplings=null_couplings, + structure=geometry["structure"], + ) + + def test_coupling_records_reject_undeclared_fields_before_sealing(self) -> None: + declared = space( + ["z", "x"], + [["z", "x"]], + charges={"z": 8, "x": 1}, + ) + geometry = geometry_from_declared_couplings(declared) + bad_couplings = copy.deepcopy(geometry["couplings"]) + bad_couplings[0]["degree"] = 999 + with self.assertRaisesRegex(PublicGonolConstructionError, "undeclared field"): + construct_public_gonol( + source_id="epac.test:extra-coupling-field", + relation="epac.affixiation.unpaired-valence", + couplings=bad_couplings, + structure=geometry["structure"], + ) + + def test_coupling_alias_input_seals_to_canonical_declared_ids_payload(self) -> None: + declared = space( + ["z", "x"], + [["z", "x"]], + charges={"z": 8, "x": 1}, + ) + geometry = geometry_from_declared_couplings(declared) + alias_couplings = tuple( + { + "coupling": item["declared_ids"], + "arity": item["arity"], + "slot_charges": item["slot_charges"], + "charge_state": item["charge_state"], + "mobius_epsilon_t0": item["mobius_epsilon_t0"], + } + for item in geometry["couplings"] + ) + receipt = construct_public_gonol( + source_id="epac.test:coupling-alias", + relation="epac.affixiation.unpaired-valence", + couplings=alias_couplings, + structure=geometry["structure"], + ) + self.assertEqual(tuple(receipt.gonol.couplings[0]), ("declared_ids", "arity", "slot_charges", "charge_state", "mobius_epsilon_t0")) + self.assertEqual(receipt.gonol.couplings[0]["declared_ids"], ("z", "x")) + def test_dimensional_errors_are_normalized_at_public_boundary(self) -> None: duplicated = ( { @@ -231,6 +306,32 @@ def test_ucns_commit_is_not_stamped_when_runtime_head_is_not_verified(self) -> N public_gonol_module.PINNED_UCNS_COMMIT = original_pin self.assertEqual(geometry["ucns_commit"], "hmmm") + def test_ucns_commit_is_not_stamped_when_runtime_source_is_dirty(self) -> None: + original_run = public_gonol_module.subprocess.run + ucns_root = EPAC_ROOT / "_deps" / "ucns" + + class Result: + def __init__(self, stdout: str) -> None: + self.stdout = stdout + + def fake_run(command, **_kwargs): + if command[3:] == ("rev-parse", "--show-toplevel"): + return Result(str(ucns_root) + "\n") + if command[3:] == ("rev-parse", "HEAD"): + return Result(PINNED_UCNS_COMMIT + "\n") + if "ls-files" in command: + return Result("") + if "status" in command: + return Result(" M src/ucns/public_gonol.py\n") + raise AssertionError(f"unexpected git command: {command!r}") + + public_gonol_module.subprocess.run = fake_run + try: + geometry = public_gonol_module._geometry(None, None) + finally: + public_gonol_module.subprocess.run = original_run + self.assertEqual(geometry["ucns_commit"], "hmmm") + def test_unknown_glyph_fails_closed(self) -> None: with self.assertRaises(PublicGonolConstructionError): construct_public_gonol( From 45397a25fbf3ebe3e4ba2ad7a6be36edbc995f1d Mon Sep 17 00:00:00 2001 From: Codex Date: Mon, 7 Sep 2026 14:15:38 +0000 Subject: [PATCH 10/33] fix(epac): close remaining receipt sealing P2s --- README.md | 4 +- epac_public_gonol.py | 12 +- subatomic/element_affixiation_candidate.py | 128 ++++++++++++++++-- subatomic/subatomic-affixiation-baseline.md | 9 +- .../test_element_affixiation_candidate.py | 77 +++++++++++ tests/test_epac_public_gonol.py | 26 ++++ 6 files changed, 238 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index c231ce8..95333c2 100644 --- a/README.md +++ b/README.md @@ -37,8 +37,8 @@ The extraction preserves the stack research artifacts and their epistemic status The current extraction gate executes: -- 49 repository regression tests; -- 28 subatomic executable witnesses; +- 50 repository regression tests; +- 30 subatomic executable witnesses; - the preregistered molecular comparison, requiring all four current standings to remain `FALSIFIED`; - deterministic work-graph digest verification. diff --git a/epac_public_gonol.py b/epac_public_gonol.py index 6d32d99..1e94be0 100644 --- a/epac_public_gonol.py +++ b/epac_public_gonol.py @@ -31,7 +31,7 @@ # summary: EPAC candidate constructor that closes gonols on the UCNS Public Gonol carrier with oriented couplings and arity charge states; not the EDCM text-domain constructor # owner: The Interdependency # public_surface: CONSTRUCTOR_ID, CONSTRUCTOR_VERSION, PINNED_UCNS_COMMIT, PINNED_PUBLIC_GONOL_SHA256, ClosedPublicGonol, PublicGonolReceipt, PublicGonolConstructionError, construct_public_gonol, replay_public_gonol, canonical_receipt_bytes -# internal_surface: _require_text, _identity_position, _verified_ucns_commit, _geometry, _tuple_tree, _canonical_coupling_record, _coupling_sort_key, _canonical_structure_tree, _participant_payload, _atomic_payload, _receipt_payload, _digest, _expected_structure_from_couplings +# internal_surface: _require_text, _identity_position, _verified_ucns_commit, _geometry, _freeze_json, _json_ready, _tuple_tree, _canonical_coupling_record, _coupling_sort_key, _canonical_structure_tree, _participant_payload, _atomic_payload, _receipt_payload, _digest, _expected_structure_from_couplings, _validate_structure_matches_couplings # auth_boundary: EPAC owns particle/energy gonol closure; UCNS owns Public Gonol carrier identity and native Möbius ε; EDCM text-domain constructor is not used; METAPAT affixiation is consumed, not redefined # storage_boundary: none; receipts remain caller-owned in-memory objects # network_boundary: none @@ -523,9 +523,9 @@ def _expected_structure_from_couplings( def _validate_structure_matches_couplings( couplings: Sequence[Mapping[str, Any]], structure: Mapping[str, Any] | None, -) -> None: +) -> Mapping[str, object] | None: if not couplings and structure is None: - return + return None if not couplings or structure is None: raise PublicGonolConstructionError( "couplings and structure must be supplied together" @@ -544,6 +544,7 @@ def _validate_structure_matches_couplings( raise PublicGonolConstructionError( "structure derived fields must exactly match the declared couplings before closure" ) + return expected_structure def _participant_payload(item: ClosedPublicGonol) -> dict[str, Any]: @@ -663,8 +664,9 @@ def construct_public_gonol( key=_coupling_sort_key, ) ) - frozen_structure = None if structure is None else _freeze_json(structure) - _validate_structure_matches_couplings(frozen_couplings, frozen_structure) + supplied_structure = None if structure is None else _freeze_json(structure) + derived_structure = _validate_structure_matches_couplings(frozen_couplings, supplied_structure) + frozen_structure = None if derived_structure is None else _freeze_json(derived_structure) glyph, index = _identity_position(identity_glyph) geometry = _geometry(glyph, index) gonol_payload = _atomic_payload( diff --git a/subatomic/element_affixiation_candidate.py b/subatomic/element_affixiation_candidate.py index d4a2f0a..8326a09 100644 --- a/subatomic/element_affixiation_candidate.py +++ b/subatomic/element_affixiation_candidate.py @@ -33,7 +33,7 @@ # summary: identity-only H/He/Li/C element-gonol candidates over established UCNS carrier identity and native Möbius framing; no position operation invented # owner: The Interdependency # public_surface: ISOTOPE_DEFAULTS, CONSTRUCTION_IDS, ElementCandidate, affixiate_element, replay_element, element_receipt -# internal_surface: _canonical_record, _t_states, _freeze_state +# internal_surface: _canonical_record, _t_states, _freeze_state, _source_commits, _verified_ucns_commit, _json_ready # auth_boundary: none # storage_boundary: none # network_boundary: none @@ -65,7 +65,7 @@ # # id: receipt_deterministic_and_replayable # given: the same element and the same pinned source identities -# then: the receipt is byte-identical across independent constructions and returned nested state cannot mutate after closure +# then: the receipt is byte-identical across independent constructions and returned nested state cannot mutate after closure; exact UCNS identity is stamped only when imported source files verify clean against the declared pin # class: correctness # # id: no_physics_or_canon_claim @@ -76,20 +76,26 @@ from __future__ import annotations -from collections.abc import Mapping +from collections.abc import Mapping, Sequence from dataclasses import dataclass from fractions import Fraction import hashlib +import inspect import json +from pathlib import Path +import subprocess from types import MappingProxyType from typing import Any from ucns import native_mobius_state, public_gonol_function +PINNED_METAPAT_COMMIT = "34d954aa1e2092e615b03a180500f6b6977f501e" +PINNED_UCNS_COMMIT = "828c0b8bbcfc267efb5701da714191c1f73a81ff" + SOURCE_COMMITS = MappingProxyType( { - "metapat": "34d954aa1e2092e615b03a180500f6b6977f501e", - "ucns": "828c0b8bbcfc267efb5701da714191c1f73a81ff", + "metapat": PINNED_METAPAT_COMMIT, + "ucns": PINNED_UCNS_COMMIT, } ) @@ -175,6 +181,110 @@ def _freeze_state(state: Mapping[str, Any]) -> Mapping[str, Any]: ) +def _git_root_for(path: Path) -> Path | None: + try: + result = subprocess.run( + ("git", "-C", str(path.parent), "rev-parse", "--show-toplevel"), + check=True, + capture_output=True, + text=True, + timeout=2, + ) + except (OSError, subprocess.SubprocessError): + return None + return Path(result.stdout.strip()).resolve() + + +def _ucns_source_paths() -> tuple[Path, ...]: + paths: list[Path] = [] + for dependency in (public_gonol_function, native_mobius_state): + try: + source_path = Path(inspect.getfile(dependency)).resolve() + except (OSError, TypeError): + return () + if source_path not in paths: + paths.append(source_path) + return tuple(paths) + + +def _verified_ucns_commit() -> str: + """Return the exact pinned UCNS commit only when imported source files match it.""" + + source_paths = _ucns_source_paths() + if not source_paths: + return "hmmm" + root = _git_root_for(source_paths[0]) + if root is None: + return "hmmm" + relative_paths: list[str] = [] + for source_path in source_paths: + if _git_root_for(source_path) != root: + return "hmmm" + try: + relative_paths.append(source_path.relative_to(root).as_posix()) + except ValueError: + return "hmmm" + + try: + result = subprocess.run( + ("git", "-C", str(root), "rev-parse", "HEAD"), + check=True, + capture_output=True, + text=True, + timeout=2, + ) + except (OSError, subprocess.SubprocessError): + return "hmmm" + if result.stdout.strip() != PINNED_UCNS_COMMIT: + return "hmmm" + + try: + for relative_path in relative_paths: + subprocess.run( + ("git", "-C", str(root), "ls-files", "--error-unmatch", "--", relative_path), + check=True, + capture_output=True, + text=True, + timeout=2, + ) + status = subprocess.run( + ( + "git", + "-C", + str(root), + "status", + "--porcelain=v1", + "--untracked-files=no", + "--", + *relative_paths, + ), + check=True, + capture_output=True, + text=True, + timeout=2, + ) + except (OSError, subprocess.SubprocessError): + return "hmmm" + if status.stdout.strip(): + return "hmmm" + return PINNED_UCNS_COMMIT + + +def _source_commits() -> dict[str, str]: + return { + "metapat": PINNED_METAPAT_COMMIT, + "ucns": _verified_ucns_commit(), + } + + +def _json_ready(value: Any) -> Any: + if isinstance(value, Mapping): + return {str(key): _json_ready(item) for key, item in value.items()} + if isinstance(value, Sequence) and not isinstance(value, (str, bytes)): + return [_json_ready(item) for item in value] + return value + + def _canonical_record( element_id: str, symbol: str, @@ -198,14 +308,14 @@ def _canonical_record( "ordered_parameter_id": CONSTRUCTION_IDS["ordered_parameter"], "t_states": list(_t_states()), "closure_scale": CONSTRUCTION_IDS["closure_scale"], - "source_commits": dict(SOURCE_COMMITS), + "source_commits": _source_commits(), "status": CONSTRUCTION_IDS["status"], } def element_receipt(record: Mapping[str, Any]) -> str: """SHA-256 over canonical JSON of the construction record.""" - payload = json.dumps(record, sort_keys=True, separators=(",", ":")) + payload = json.dumps(_json_ready(record), sort_keys=True, separators=(",", ":")) return hashlib.sha256(payload.encode("utf-8")).hexdigest() @@ -252,7 +362,7 @@ def affixiate_element(symbol: str) -> ElementCandidate: relation_id=record["relation_id"], ordered_parameter_id=record["ordered_parameter_id"], closure_scale=record["closure_scale"], - source_commits=SOURCE_COMMITS, + source_commits=MappingProxyType(dict(record["source_commits"])), status=record["status"], receipt=receipt, ) @@ -284,6 +394,8 @@ def replay_element(symbol: str) -> tuple[bool, str]: "ElementCandidate", "ISOTOPE_DEFAULTS", "SOURCE_COMMITS", + "PINNED_METAPAT_COMMIT", + "PINNED_UCNS_COMMIT", "affixiate_element", "element_receipt", "replay_element", diff --git a/subatomic/subatomic-affixiation-baseline.md b/subatomic/subatomic-affixiation-baseline.md index ddd9ae2..5bd9a0b 100644 --- a/subatomic/subatomic-affixiation-baseline.md +++ b/subatomic/subatomic-affixiation-baseline.md @@ -134,6 +134,9 @@ t-state sequence (0 -> 1 -> 2), closure_scale ("atomic"), source_commits Independent replay must reproduce the receipt byte-for-byte. A receipt establishes reproducibility of the declared construction only — not geometry, physics, or measurement. +The exact UCNS source commit is recorded only when the imported `public_gonol_function` +and `native_mobius_state` source files resolve to the pinned clean UCNS checkout; +otherwise the UCNS source identity is `hmmm`. ## 5. What this establishes — and what it does not @@ -213,7 +216,7 @@ The frozen minimal decisive action from §7 is now implemented locally (not push - These historical records were byte-identical under their original UCNS pin; they are not the current extracted-constructor receipts. - `receipts/ucns-828c0b8/` — current sealed construction receipts at the extracted EPAC UCNS - pin: + pin, valid only when runtime source verification reproduces that clean checkout: | Element | Receipt (SHA-256) | |---|---| @@ -299,7 +302,7 @@ law, and no scale interchange is introduced. Standing is `implemented-candidate` atom instances only. - Historical evidence at this section's original 2026-08-22 stop: **26/26 subatomic tests pass**; sibling epac suite **29 tests OK**; CONTRACTS↔CHECKS audit **closed** - (26 contracts / 26 checks). Current extracted-repo gate records **28 subatomic witnesses** - and **49 repository tests**. + (26 contracts / 26 checks). Current extracted-repo gate records **30 subatomic witnesses** + and **50 repository tests**. - The dimensional-arity doctrine is implemented by the sibling `epac_dimensional_arity.py` (committed); no duplicate is maintained here. Status remains `CROSS-DOMAIN-HYPOTHESIS`. diff --git a/subatomic/test_element_affixiation_candidate.py b/subatomic/test_element_affixiation_candidate.py index 4c7032d..a02959a 100644 --- a/subatomic/test_element_affixiation_candidate.py +++ b/subatomic/test_element_affixiation_candidate.py @@ -31,6 +31,18 @@ # mutates: none # cleanup: none # +# id: check_unverified_ucns_source_records_hmmm +# proves: receipt_deterministic_and_replayable +# call: self::test_unverified_ucns_source_records_hmmm +# mutates: element_affixiation_candidate.subprocess.run +# cleanup: restores subprocess.run +# +# id: check_element_receipt_accepts_mapping_records +# proves: receipt_deterministic_and_replayable +# call: self::test_element_receipt_accepts_mapping_records +# mutates: none +# cleanup: none +# # id: check_historical_receipts_remain_versioned_evidence # proves: no_physics_or_canon_claim # call: self::test_historical_receipts_remain_versioned_evidence @@ -44,9 +56,11 @@ # cleanup: none # === END CHECKS === +from collections import UserDict from fractions import Fraction import json from pathlib import Path +from types import MappingProxyType import element_affixiation_candidate as candidate from ucns import ( @@ -148,6 +162,69 @@ def test_current_versioned_receipts_match_declared_ucns_pin(): assert observed["source_commits"]["ucns"] == candidate.SOURCE_COMMITS["ucns"] +def test_unverified_ucns_source_records_hmmm(): + original_run = candidate.subprocess.run + ucns_root = Path(__file__).resolve().parents[1] / "_deps" / "ucns" + + class Result: + def __init__(self, stdout: str) -> None: + self.stdout = stdout + + def fake_dirty_run(command, **_kwargs): + if command[3:] == ("rev-parse", "--show-toplevel"): + return Result(str(ucns_root) + "\n") + if command[3:] == ("rev-parse", "HEAD"): + return Result(candidate.PINNED_UCNS_COMMIT + "\n") + if "ls-files" in command: + return Result("") + if "status" in command: + return Result(" M src/ucns/direct_mobius.py\n") + raise AssertionError(f"unexpected git command: {command!r}") + + try: + candidate.subprocess.run = fake_dirty_run + element = candidate.affixiate_element("H") + finally: + candidate.subprocess.run = original_run + assert element.source_commits["ucns"] == "hmmm" + + def fake_wrong_head_run(command, **_kwargs): + if command[3:] == ("rev-parse", "--show-toplevel"): + return Result(str(ucns_root) + "\n") + if command[3:] == ("rev-parse", "HEAD"): + return Result("0" * 40 + "\n") + raise AssertionError(f"unexpected git command: {command!r}") + + try: + candidate.subprocess.run = fake_wrong_head_run + element = candidate.affixiate_element("H") + finally: + candidate.subprocess.run = original_run + assert element.source_commits["ucns"] == "hmmm" + + +def test_element_receipt_accepts_mapping_records(): + element = candidate.affixiate_element("H") + record = candidate._canonical_record( + element_id=element.element_id, + symbol=element.symbol, + Z=element.Z, + A=element.A, + proton_positions=element.proton_positions, + proton_glyphs=element.proton_glyphs, + neutron_positions=element.neutron_positions, + neutron_glyphs=element.neutron_glyphs, + ) + wrapped = UserDict( + { + **record, + "source_commits": MappingProxyType(record["source_commits"]), + "t_states": tuple(MappingProxyType(item) for item in record["t_states"]), + } + ) + assert candidate.element_receipt(wrapped) == candidate.element_receipt(record) + + def test_historical_receipts_remain_versioned_evidence(): for name in ("h", "he", "li", "c"): historical = json.loads((RECEIPT_ROOT / f"{name}.json").read_text()) diff --git a/tests/test_epac_public_gonol.py b/tests/test_epac_public_gonol.py index d60cab9..9198ec1 100644 --- a/tests/test_epac_public_gonol.py +++ b/tests/test_epac_public_gonol.py @@ -132,6 +132,32 @@ def test_coupling_collection_order_is_canonicalized_before_sealing(self) -> None self.assertEqual(first.gonol.couplings, second.gonol.couplings) self.assertEqual(first.receipt_digest, second.receipt_digest) + def test_structure_order_is_canonicalized_before_sealing(self) -> None: + declared = space( + ["x", "z", "y"], + [["z", "x"], ["z", "y"]], + charges={"z": 8, "x": 1, "y": 1}, + ) + geometry = geometry_from_declared_couplings(declared) + reordered = copy.deepcopy(geometry["structure"]) + reordered["parts"] = tuple(reversed(reordered["parts"])) + reordered["degree"] = tuple(reversed(reordered["degree"])) + reordered["quaternions"] = tuple(reversed(reordered["quaternions"])) + first = construct_public_gonol( + source_id="epac.test:reordered-structure", + relation="epac.affixiation.unpaired-valence", + couplings=geometry["couplings"], + structure=geometry["structure"], + ) + second = construct_public_gonol( + source_id="epac.test:reordered-structure", + relation="epac.affixiation.unpaired-valence", + couplings=geometry["couplings"], + structure=reordered, + ) + self.assertEqual(first.gonol.structure, second.gonol.structure) + self.assertEqual(first.receipt_digest, second.receipt_digest) + def test_nested_geometry_is_frozen_after_closure(self) -> None: declared = space( ["z", "x"], From e270a372a2c4c2de109373ecbef5a6a5fc8f7714 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 9 Sep 2026 12:10:17 -0700 Subject: [PATCH 11/33] fix(epac): bind UCNS pin to loaded code --- epac_public_gonol.py | 95 +---- epac_ucns_provenance.py | 337 ++++++++++++++++++ subatomic/element_affixiation_candidate.py | 96 +---- .../test_element_affixiation_candidate.py | 41 +-- tests/test_epac_public_gonol.py | 39 +- tests/test_epac_ucns_provenance.py | 83 +++++ 6 files changed, 456 insertions(+), 235 deletions(-) create mode 100644 epac_ucns_provenance.py create mode 100644 tests/test_epac_ucns_provenance.py diff --git a/epac_public_gonol.py b/epac_public_gonol.py index 1e94be0..e3a9570 100644 --- a/epac_public_gonol.py +++ b/epac_public_gonol.py @@ -77,10 +77,7 @@ from collections.abc import Sequence as SequenceABC from dataclasses import dataclass from hashlib import sha256 -import inspect import json -from pathlib import Path -import subprocess from types import MappingProxyType from typing import Any, Mapping, Sequence @@ -90,6 +87,7 @@ space, structure_from_charged_couplings, ) +from epac_ucns_provenance import verify_loaded_ucns_commit from ucns import ( native_mobius_state, public_gonol_function, @@ -191,94 +189,13 @@ def _identity_position(identity_glyph: str | None) -> tuple[str | None, int | No return (position.glyph, position.index) -def _git_root_for(path: Path) -> Path | None: - try: - result = subprocess.run( - ("git", "-C", str(path.parent), "rev-parse", "--show-toplevel"), - check=True, - capture_output=True, - text=True, - timeout=2, - ) - except (OSError, subprocess.SubprocessError): - return None - return Path(result.stdout.strip()).resolve() - - -def _ucns_source_paths() -> tuple[Path, ...]: - paths: list[Path] = [] - for dependency in (public_gonol_function, public_gonol_sha256, native_mobius_state): - try: - source_path = Path(inspect.getfile(dependency)).resolve() - except (OSError, TypeError): - return () - if source_path not in paths: - paths.append(source_path) - return tuple(paths) - - def _verified_ucns_commit() -> str: - """Return the observed UCNS git commit only when source bytes match the pin.""" - - source_paths = _ucns_source_paths() - if not source_paths: - return "hmmm" - root = _git_root_for(source_paths[0]) - if root is None: - return "hmmm" - relative_paths: list[str] = [] - for source_path in source_paths: - if _git_root_for(source_path) != root: - return "hmmm" - try: - relative_paths.append(source_path.relative_to(root).as_posix()) - except ValueError: - return "hmmm" + """Return the pin only when current source and executing UCNS code agree.""" - try: - result = subprocess.run( - ("git", "-C", str(root), "rev-parse", "HEAD"), - check=True, - capture_output=True, - text=True, - timeout=2, - ) - except (OSError, subprocess.SubprocessError): - return "hmmm" - observed = result.stdout.strip() - if observed != PINNED_UCNS_COMMIT: - return "hmmm" - - try: - for relative_path in relative_paths: - subprocess.run( - ("git", "-C", str(root), "ls-files", "--error-unmatch", "--", relative_path), - check=True, - capture_output=True, - text=True, - timeout=2, - ) - status = subprocess.run( - ( - "git", - "-C", - str(root), - "status", - "--porcelain=v1", - "--untracked-files=no", - "--", - *relative_paths, - ), - check=True, - capture_output=True, - text=True, - timeout=2, - ) - except (OSError, subprocess.SubprocessError): - return "hmmm" - if status.stdout.strip(): - return "hmmm" - return observed + return verify_loaded_ucns_commit( + pinned_commit=PINNED_UCNS_COMMIT, + dependencies=(public_gonol_function, public_gonol_sha256, native_mobius_state), + ) def _geometry(identity_glyph: str | None, carrier_index: int | None) -> dict[str, Any]: diff --git a/epac_ucns_provenance.py b/epac_ucns_provenance.py new file mode 100644 index 0000000..99d3e57 --- /dev/null +++ b/epac_ucns_provenance.py @@ -0,0 +1,337 @@ +"""Loaded-code-aware UCNS provenance verification shared by EPAC constructors. + +The verifier stamps a UCNS commit only when the executing function bytecode +matches the clean source at the declared commit. Verification is cached by a +witness containing HEAD, index state, source bytes, file modes, and loaded code, +so repeated nested construction avoids Git subprocesses without preserving a +stale answer. + +Usage guidance: + + commit = verify_loaded_ucns_commit( + pinned_commit=PINNED_UCNS_COMMIT, + dependencies=(public_gonol_function, native_mobius_state), + ) + # commit is the exact pin or "hmmm"; never promote "hmmm" to the pin. +""" + +# === MODULE_BUILD === +# id: epac_ucns_loaded_provenance +# module_name: epac_ucns_provenance +# module_kind: service +# summary: binds UCNS receipt provenance to clean pinned source and the function code actually executing +# owner: The Interdependency +# public_surface: verify_loaded_ucns_commit, clear_ucns_verification_cache, ucns_verification_cache_info +# internal_surface: source witness, Git metadata resolution, code fingerprint, cached verification +# auth_boundary: none +# storage_boundary: read +# network_boundary: none +# user_data_boundary: none +# admin_only: false +# tests: tests.test_epac_ucns_provenance +# rollout: called by both EPAC Public Gonol construction paths +# rollback: callers preserve ucns identity as hmmm rather than bypassing verification +# since: 2026-09-09 +# === END MODULE_BUILD === + +# === CONTRACTS === +# id: epac_ucns_pin_matches_loaded_code +# given: EPAC is about to stamp a pinned UCNS dependency identity +# then: each executing dependency function matches the clean tracked source at that exact HEAD; otherwise the identity is hmmm +# class: provenance +# +# id: epac_ucns_verification_reuses_only_identical_witness +# given: repeated construction uses unchanged HEAD, index, relevant source bytes, modes, and loaded code +# then: Git verification executes once; any witness change selects a new verification result +# class: performance +# === END CONTRACTS === + +from __future__ import annotations + +from functools import lru_cache +from hashlib import sha256 +import inspect +import marshal +from pathlib import Path +import re +import subprocess +from types import CodeType +from typing import Callable, Sequence + + +HEX40 = re.compile(r"^[0-9a-f]{40}$") +Runner = Callable[..., object] + + +def _git_root(path: Path) -> Path | None: + for candidate in (path.parent, *path.parents): + if (candidate / ".git").exists(): + return candidate.resolve() + return None + + +def _git_directories(root: Path) -> tuple[Path, Path] | None: + marker = root / ".git" + if marker.is_dir(): + git_dir = marker.resolve() + elif marker.is_file(): + line = marker.read_text(encoding="utf-8").strip() + if not line.startswith("gitdir: "): + return None + target = Path(line.removeprefix("gitdir: ")) + git_dir = (target if target.is_absolute() else root / target).resolve() + else: + return None + common_file = git_dir / "commondir" + if common_file.is_file(): + target = Path(common_file.read_text(encoding="utf-8").strip()) + common_dir = (target if target.is_absolute() else git_dir / target).resolve() + else: + common_dir = git_dir + return git_dir, common_dir + + +def _packed_ref(common_dir: Path, ref_name: str) -> str | None: + packed = common_dir / "packed-refs" + if not packed.is_file(): + return None + suffix = f" {ref_name}" + for line in packed.read_text(encoding="utf-8").splitlines(): + if line.startswith(("#", "^")) or not line.endswith(suffix): + continue + value = line.split(" ", 1)[0] + return value if HEX40.fullmatch(value) else None + return None + + +def _head_and_index_witness(root: Path) -> tuple[str, int, int] | None: + directories = _git_directories(root) + if directories is None: + return None + git_dir, common_dir = directories + head_text = (git_dir / "HEAD").read_text(encoding="utf-8").strip() + if HEX40.fullmatch(head_text): + head = head_text + elif head_text.startswith("ref: "): + ref_name = head_text.removeprefix("ref: ") + values = [] + for base in (git_dir, common_dir): + ref_path = base / ref_name + if ref_path.is_file(): + values.append(ref_path.read_text(encoding="utf-8").strip()) + head = next((value for value in values if HEX40.fullmatch(value)), None) + if head is None: + head = _packed_ref(common_dir, ref_name) + if head is None: + return None + else: + return None + index = git_dir / "index" + if not index.exists(): + index = common_dir / "index" + stat = index.stat() + return head, stat.st_mtime_ns, stat.st_size + + +def _normalized_code(code: CodeType) -> tuple[object, ...]: + constants = tuple( + ("code", _normalized_code(item)) if isinstance(item, CodeType) else item + for item in code.co_consts + ) + return ( + code.co_name, + code.co_qualname, + code.co_argcount, + code.co_posonlyargcount, + code.co_kwonlyargcount, + code.co_nlocals, + code.co_stacksize, + code.co_flags, + code.co_code, + constants, + code.co_names, + code.co_varnames, + code.co_freevars, + code.co_cellvars, + code.co_exceptiontable, + ) + + +def _code_fingerprint(code: CodeType) -> str: + return sha256(marshal.dumps(_normalized_code(code))).hexdigest() + + +def _find_code(module_code: CodeType, qualname: str) -> CodeType | None: + matches: list[CodeType] = [] + + def walk(code: CodeType) -> None: + for item in code.co_consts: + if not isinstance(item, CodeType): + continue + if item.co_qualname == qualname: + matches.append(item) + walk(item) + + walk(module_code) + return matches[0] if len(matches) == 1 else None + + +def _source_records(dependencies: Sequence[Callable[..., object]]) -> tuple[Path, tuple[tuple[object, ...], ...]] | None: + records: list[tuple[object, ...]] = [] + root: Path | None = None + for dependency in dependencies: + code = getattr(dependency, "__code__", None) + qualname = getattr(dependency, "__qualname__", None) + if not isinstance(code, CodeType) or not isinstance(qualname, str): + return None + try: + path = Path(inspect.getfile(dependency)).resolve() + data = path.read_bytes() + stat = path.stat() + except (OSError, TypeError): + return None + dependency_root = _git_root(path) + if dependency_root is None or (root is not None and dependency_root != root): + return None + root = dependency_root + try: + relative = path.relative_to(root).as_posix() + except ValueError: + return None + records.append( + ( + relative, + str(path), + qualname, + _code_fingerprint(code), + sha256(data).hexdigest(), + stat.st_mode, + ) + ) + if root is None: + return None + return root, tuple(records) + + +def _expected_code_fingerprint(path: Path, qualname: str) -> str | None: + try: + module_code = compile(path.read_bytes(), str(path), "exec", dont_inherit=True) + except (OSError, SyntaxError, ValueError): + return None + code = _find_code(module_code, qualname) + return None if code is None else _code_fingerprint(code) + + +@lru_cache(maxsize=32) +def _verify_witness( + pinned_commit: str, + root_text: str, + head: str, + index_mtime_ns: int, + index_size: int, + records: tuple[tuple[object, ...], ...], + runner: Runner, +) -> str: + del index_mtime_ns, index_size # Their presence invalidates the cache key. + if head != pinned_commit: + return "hmmm" + root = Path(root_text) + relative_paths = sorted({str(record[0]) for record in records}) + for relative, absolute, qualname, loaded_digest, disk_digest, _mode in records: + path = Path(str(absolute)) + try: + if sha256(path.read_bytes()).hexdigest() != disk_digest: + return "hmmm" + except OSError: + return "hmmm" + expected_digest = _expected_code_fingerprint(path, str(qualname)) + if expected_digest is None or expected_digest != loaded_digest: + return "hmmm" + try: + observed = runner( + ("git", "-C", str(root), "rev-parse", "HEAD"), + check=True, + capture_output=True, + text=True, + timeout=2, + ) + if getattr(observed, "stdout", "").strip() != pinned_commit: + return "hmmm" + for relative_path in relative_paths: + runner( + ("git", "-C", str(root), "ls-files", "--error-unmatch", "--", relative_path), + check=True, + capture_output=True, + text=True, + timeout=2, + ) + status = runner( + ( + "git", + "-C", + str(root), + "status", + "--porcelain=v1", + "--untracked-files=no", + "--", + *relative_paths, + ), + check=True, + capture_output=True, + text=True, + timeout=2, + ) + except (OSError, subprocess.SubprocessError): + return "hmmm" + return pinned_commit if not getattr(status, "stdout", "").strip() else "hmmm" + + +def verify_loaded_ucns_commit( + *, + pinned_commit: str, + dependencies: Sequence[Callable[..., object]], + runner: Runner = subprocess.run, +) -> str: + """Return ``pinned_commit`` only for a clean, loaded-code-matched runtime.""" + + if not HEX40.fullmatch(pinned_commit): + return "hmmm" + source = _source_records(dependencies) + if source is None: + return "hmmm" + root, records = source + try: + git_witness = _head_and_index_witness(root) + except OSError: + return "hmmm" + if git_witness is None: + return "hmmm" + head, index_mtime_ns, index_size = git_witness + return _verify_witness( + pinned_commit, + str(root), + head, + index_mtime_ns, + index_size, + records, + runner, + ) + + +def clear_ucns_verification_cache() -> None: + """Clear cached witnesses; intended for isolated tests and process repair.""" + + _verify_witness.cache_clear() + + +def ucns_verification_cache_info(): + """Expose cache counters for provenance/performance regression tests.""" + + return _verify_witness.cache_info() + + +__all__ = [ + "clear_ucns_verification_cache", + "ucns_verification_cache_info", + "verify_loaded_ucns_commit", +] diff --git a/subatomic/element_affixiation_candidate.py b/subatomic/element_affixiation_candidate.py index 8326a09..0be31a2 100644 --- a/subatomic/element_affixiation_candidate.py +++ b/subatomic/element_affixiation_candidate.py @@ -80,14 +80,12 @@ from dataclasses import dataclass from fractions import Fraction import hashlib -import inspect import json -from pathlib import Path -import subprocess from types import MappingProxyType from typing import Any from ucns import native_mobius_state, public_gonol_function +from epac_ucns_provenance import verify_loaded_ucns_commit PINNED_METAPAT_COMMIT = "34d954aa1e2092e615b03a180500f6b6977f501e" PINNED_UCNS_COMMIT = "828c0b8bbcfc267efb5701da714191c1f73a81ff" @@ -181,93 +179,13 @@ def _freeze_state(state: Mapping[str, Any]) -> Mapping[str, Any]: ) -def _git_root_for(path: Path) -> Path | None: - try: - result = subprocess.run( - ("git", "-C", str(path.parent), "rev-parse", "--show-toplevel"), - check=True, - capture_output=True, - text=True, - timeout=2, - ) - except (OSError, subprocess.SubprocessError): - return None - return Path(result.stdout.strip()).resolve() - - -def _ucns_source_paths() -> tuple[Path, ...]: - paths: list[Path] = [] - for dependency in (public_gonol_function, native_mobius_state): - try: - source_path = Path(inspect.getfile(dependency)).resolve() - except (OSError, TypeError): - return () - if source_path not in paths: - paths.append(source_path) - return tuple(paths) - - def _verified_ucns_commit() -> str: - """Return the exact pinned UCNS commit only when imported source files match it.""" - - source_paths = _ucns_source_paths() - if not source_paths: - return "hmmm" - root = _git_root_for(source_paths[0]) - if root is None: - return "hmmm" - relative_paths: list[str] = [] - for source_path in source_paths: - if _git_root_for(source_path) != root: - return "hmmm" - try: - relative_paths.append(source_path.relative_to(root).as_posix()) - except ValueError: - return "hmmm" - - try: - result = subprocess.run( - ("git", "-C", str(root), "rev-parse", "HEAD"), - check=True, - capture_output=True, - text=True, - timeout=2, - ) - except (OSError, subprocess.SubprocessError): - return "hmmm" - if result.stdout.strip() != PINNED_UCNS_COMMIT: - return "hmmm" - - try: - for relative_path in relative_paths: - subprocess.run( - ("git", "-C", str(root), "ls-files", "--error-unmatch", "--", relative_path), - check=True, - capture_output=True, - text=True, - timeout=2, - ) - status = subprocess.run( - ( - "git", - "-C", - str(root), - "status", - "--porcelain=v1", - "--untracked-files=no", - "--", - *relative_paths, - ), - check=True, - capture_output=True, - text=True, - timeout=2, - ) - except (OSError, subprocess.SubprocessError): - return "hmmm" - if status.stdout.strip(): - return "hmmm" - return PINNED_UCNS_COMMIT + """Return the pin only when current source and executing UCNS code agree.""" + + return verify_loaded_ucns_commit( + pinned_commit=PINNED_UCNS_COMMIT, + dependencies=(public_gonol_function, native_mobius_state), + ) def _source_commits() -> dict[str, str]: diff --git a/subatomic/test_element_affixiation_candidate.py b/subatomic/test_element_affixiation_candidate.py index a02959a..aaa83cb 100644 --- a/subatomic/test_element_affixiation_candidate.py +++ b/subatomic/test_element_affixiation_candidate.py @@ -34,8 +34,8 @@ # id: check_unverified_ucns_source_records_hmmm # proves: receipt_deterministic_and_replayable # call: self::test_unverified_ucns_source_records_hmmm -# mutates: element_affixiation_candidate.subprocess.run -# cleanup: restores subprocess.run +# mutates: element_affixiation_candidate.PINNED_UCNS_COMMIT +# cleanup: restores PINNED_UCNS_COMMIT # # id: check_element_receipt_accepts_mapping_records # proves: receipt_deterministic_and_replayable @@ -163,43 +163,12 @@ def test_current_versioned_receipts_match_declared_ucns_pin(): def test_unverified_ucns_source_records_hmmm(): - original_run = candidate.subprocess.run - ucns_root = Path(__file__).resolve().parents[1] / "_deps" / "ucns" - - class Result: - def __init__(self, stdout: str) -> None: - self.stdout = stdout - - def fake_dirty_run(command, **_kwargs): - if command[3:] == ("rev-parse", "--show-toplevel"): - return Result(str(ucns_root) + "\n") - if command[3:] == ("rev-parse", "HEAD"): - return Result(candidate.PINNED_UCNS_COMMIT + "\n") - if "ls-files" in command: - return Result("") - if "status" in command: - return Result(" M src/ucns/direct_mobius.py\n") - raise AssertionError(f"unexpected git command: {command!r}") - - try: - candidate.subprocess.run = fake_dirty_run - element = candidate.affixiate_element("H") - finally: - candidate.subprocess.run = original_run - assert element.source_commits["ucns"] == "hmmm" - - def fake_wrong_head_run(command, **_kwargs): - if command[3:] == ("rev-parse", "--show-toplevel"): - return Result(str(ucns_root) + "\n") - if command[3:] == ("rev-parse", "HEAD"): - return Result("0" * 40 + "\n") - raise AssertionError(f"unexpected git command: {command!r}") - + original_pin = candidate.PINNED_UCNS_COMMIT + candidate.PINNED_UCNS_COMMIT = "0" * 40 try: - candidate.subprocess.run = fake_wrong_head_run element = candidate.affixiate_element("H") finally: - candidate.subprocess.run = original_run + candidate.PINNED_UCNS_COMMIT = original_pin assert element.source_commits["ucns"] == "hmmm" diff --git a/tests/test_epac_public_gonol.py b/tests/test_epac_public_gonol.py index 9198ec1..845bc7a 100644 --- a/tests/test_epac_public_gonol.py +++ b/tests/test_epac_public_gonol.py @@ -1,6 +1,7 @@ from __future__ import annotations import copy +import inspect import sys import unittest from pathlib import Path @@ -10,6 +11,7 @@ from epac_dimensional_arity import DimensionalArityError, space, geometry_from_declared_couplings import epac_public_gonol as public_gonol_module +import epac_ucns_provenance from epac_public_gonol import ( CONSTRUCTOR_ID, PINNED_PUBLIC_GONOL_SHA256, @@ -332,30 +334,25 @@ def test_ucns_commit_is_not_stamped_when_runtime_head_is_not_verified(self) -> N public_gonol_module.PINNED_UCNS_COMMIT = original_pin self.assertEqual(geometry["ucns_commit"], "hmmm") - def test_ucns_commit_is_not_stamped_when_runtime_source_is_dirty(self) -> None: - original_run = public_gonol_module.subprocess.run - ucns_root = EPAC_ROOT / "_deps" / "ucns" - - class Result: - def __init__(self, stdout: str) -> None: - self.stdout = stdout - - def fake_run(command, **_kwargs): - if command[3:] == ("rev-parse", "--show-toplevel"): - return Result(str(ucns_root) + "\n") - if command[3:] == ("rev-parse", "HEAD"): - return Result(PINNED_UCNS_COMMIT + "\n") - if "ls-files" in command: - return Result("") - if "status" in command: - return Result(" M src/ucns/public_gonol.py\n") - raise AssertionError(f"unexpected git command: {command!r}") - - public_gonol_module.subprocess.run = fake_run + def test_ucns_commit_is_not_stamped_when_loaded_code_is_stale(self) -> None: + original_function = public_gonol_module.public_gonol_function + namespace: dict[str, object] = {} + source_path = inspect.getfile(original_function) + exec( + compile( + "def public_gonol_function(value):\n return value\n", + source_path, + "exec", + ), + namespace, + ) + public_gonol_module.public_gonol_function = namespace["public_gonol_function"] + epac_ucns_provenance.clear_ucns_verification_cache() try: geometry = public_gonol_module._geometry(None, None) finally: - public_gonol_module.subprocess.run = original_run + public_gonol_module.public_gonol_function = original_function + epac_ucns_provenance.clear_ucns_verification_cache() self.assertEqual(geometry["ucns_commit"], "hmmm") def test_unknown_glyph_fails_closed(self) -> None: diff --git a/tests/test_epac_ucns_provenance.py b/tests/test_epac_ucns_provenance.py new file mode 100644 index 0000000..b2b2c79 --- /dev/null +++ b/tests/test_epac_ucns_provenance.py @@ -0,0 +1,83 @@ +"""Executable checks for loaded-code-aware UCNS provenance and cache reuse.""" + +# === CHECKS === +# id: check_epac_ucns_pin_matches_loaded_code +# proves: epac_ucns_pin_matches_loaded_code +# call: self::test_loaded_code_mismatch_returns_hmmm +# mutates: none +# cleanup: clears verification cache +# +# id: check_epac_ucns_verification_reuses_only_identical_witness +# proves: epac_ucns_verification_reuses_only_identical_witness +# call: self::test_unchanged_witness_runs_git_once +# mutates: in-memory verification cache +# cleanup: clears verification cache +# === END CHECKS === + +from __future__ import annotations + +import inspect +import subprocess +import unittest + +from epac_ucns_provenance import ( + clear_ucns_verification_cache, + ucns_verification_cache_info, + verify_loaded_ucns_commit, +) +from epac_public_gonol import PINNED_UCNS_COMMIT +from ucns import native_mobius_state, public_gonol_function + + +class UcnsProvenanceTest(unittest.TestCase): + def tearDown(self) -> None: + clear_ucns_verification_cache() + + def test_loaded_code_mismatch_returns_hmmm(self) -> None: + namespace: dict[str, object] = {} + exec( + compile( + "def public_gonol_function(value):\n return value\n", + inspect.getfile(public_gonol_function), + "exec", + ), + namespace, + ) + stale_function = namespace["public_gonol_function"] + + observed = verify_loaded_ucns_commit( + pinned_commit=PINNED_UCNS_COMMIT, + dependencies=(stale_function, native_mobius_state), + ) + + self.assertEqual(observed, "hmmm") + + def test_unchanged_witness_runs_git_once(self) -> None: + calls: list[tuple[str, ...]] = [] + + def counting_runner(command, **kwargs): + calls.append(tuple(command)) + return subprocess.run(command, **kwargs) + + clear_ucns_verification_cache() + first = verify_loaded_ucns_commit( + pinned_commit=PINNED_UCNS_COMMIT, + dependencies=(public_gonol_function, native_mobius_state), + runner=counting_runner, + ) + first_call_count = len(calls) + second = verify_loaded_ucns_commit( + pinned_commit=PINNED_UCNS_COMMIT, + dependencies=(public_gonol_function, native_mobius_state), + runner=counting_runner, + ) + + self.assertEqual(first, PINNED_UCNS_COMMIT) + self.assertEqual(second, PINNED_UCNS_COMMIT) + self.assertGreater(first_call_count, 0) + self.assertEqual(len(calls), first_call_count) + self.assertEqual(ucns_verification_cache_info().hits, 1) + + +if __name__ == "__main__": + unittest.main() From 683e4a5c76e532998ae597ae378de9889d75810f Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 9 Sep 2026 12:28:21 -0700 Subject: [PATCH 12/33] fix(epac): retain exact UCNS receipt identity --- epac_public_gonol.py | 124 +++++++++++++++++++---------- epac_ucns_provenance.py | 38 ++++----- tests/test_epac_public_gonol.py | 12 ++- tests/test_epac_ucns_provenance.py | 20 +++++ 4 files changed, 131 insertions(+), 63 deletions(-) diff --git a/epac_public_gonol.py b/epac_public_gonol.py index e3a9570..c75a415 100644 --- a/epac_public_gonol.py +++ b/epac_public_gonol.py @@ -148,6 +148,7 @@ class ClosedPublicGonol: carried_options: tuple[tuple[str, str], ...] couplings: tuple[Mapping[str, Any], ...] structure: Mapping[str, Any] | None + geometry: Mapping[str, Any] atomic_id: str receipt_digest: str geometry_digest: str @@ -165,6 +166,7 @@ class PublicGonolReceipt: gonol: ClosedPublicGonol receipt_digest: str structure: Mapping[str, Any] | None + geometry: Mapping[str, Any] nonclaims: tuple[str, ...] hmmm: tuple[str, ...] @@ -547,6 +549,73 @@ def _digest(payload: Mapping[str, Any]) -> str: return sha256(canonical_receipt_bytes(payload)).hexdigest() +def _seal_public_gonol( + *, + source_id: str, + relation: str, + participants: tuple[ClosedPublicGonol, ...], + identity_glyph: str | None, + carrier_index: int | None, + occurrence: int, + carried_options: tuple[tuple[str, str], ...], + couplings: tuple[Mapping[str, Any], ...], + structure: Mapping[str, Any] | None, + geometry: Mapping[str, Any], +) -> PublicGonolReceipt: + """Seal already validated canonical fields with one immutable geometry receipt.""" + + frozen_geometry = _freeze_json(geometry) + gonol_payload = _atomic_payload( + source_id=source_id, + occurrence=occurrence, + relation=relation, + identity_glyph=identity_glyph, + carrier_index=carrier_index, + participants=participants, + carried_options=carried_options, + couplings=couplings, + structure=structure, + ) + atomic_id = _digest({"atomic": gonol_payload}) + geometry_digest = _digest({"geometry": frozen_geometry}) + receipt_payload = _receipt_payload( + source_id=source_id, + gonol_payload=gonol_payload, + geometry=frozen_geometry, + atomic_id=atomic_id, + geometry_digest=geometry_digest, + ) + receipt_digest = _digest(receipt_payload) + gonol = ClosedPublicGonol( + source_id=source_id, + occurrence=occurrence, + relation=relation, + identity_glyph=identity_glyph, + carrier_index=carrier_index, + participants=participants, + carried_options=carried_options, + couplings=couplings, + structure=structure, + geometry=frozen_geometry, + atomic_id=atomic_id, + receipt_digest=receipt_digest, + geometry_digest=geometry_digest, + ) + return PublicGonolReceipt( + constructor_id=CONSTRUCTOR_ID, + constructor_version=CONSTRUCTOR_VERSION, + standing=STANDING, + selection_effect=SELECTION_EFFECT, + source_id=source_id, + gonol=gonol, + receipt_digest=receipt_digest, + structure=structure, + geometry=frozen_geometry, + nonclaims=NONCLAIMS, + hmmm=HMMM, + ) + + def construct_public_gonol( *, source_id: str, @@ -586,52 +655,17 @@ def construct_public_gonol( frozen_structure = None if derived_structure is None else _freeze_json(derived_structure) glyph, index = _identity_position(identity_glyph) geometry = _geometry(glyph, index) - gonol_payload = _atomic_payload( + return _seal_public_gonol( source_id=source_id, - occurrence=occurrence, relation=relation, - identity_glyph=glyph, - carrier_index=index, participants=closed_participants, - carried_options=options, - couplings=frozen_couplings, - structure=frozen_structure, - ) - atomic_id = _digest({"atomic": gonol_payload}) - geometry_digest = _digest({"geometry": geometry}) - receipt_payload = _receipt_payload( - source_id=source_id, - gonol_payload=gonol_payload, - geometry=geometry, - atomic_id=atomic_id, - geometry_digest=geometry_digest, - ) - receipt_digest = _digest(receipt_payload) - gonol = ClosedPublicGonol( - source_id=source_id, - occurrence=occurrence, - relation=relation, identity_glyph=glyph, carrier_index=index, - participants=closed_participants, + occurrence=occurrence, carried_options=options, couplings=frozen_couplings, structure=frozen_structure, - atomic_id=atomic_id, - receipt_digest=receipt_digest, - geometry_digest=geometry_digest, - ) - return PublicGonolReceipt( - constructor_id=CONSTRUCTOR_ID, - constructor_version=CONSTRUCTOR_VERSION, - standing=STANDING, - selection_effect=SELECTION_EFFECT, - source_id=source_id, - gonol=gonol, - receipt_digest=receipt_digest, - structure=frozen_structure, - nonclaims=NONCLAIMS, - hmmm=HMMM, + geometry=geometry, ) @@ -639,16 +673,26 @@ def replay_public_gonol(receipt: PublicGonolReceipt) -> PublicGonolReceipt: """Replay one receipt from its closed gonol. Reproduces construction identity.""" gonol = receipt.gonol - return construct_public_gonol( + derived_structure = _validate_structure_matches_couplings( + gonol.couplings, + gonol.structure, + ) + frozen_structure = None if derived_structure is None else _freeze_json(derived_structure) + replayed = _seal_public_gonol( source_id=gonol.source_id, relation=gonol.relation, participants=gonol.participants, identity_glyph=gonol.identity_glyph, + carrier_index=gonol.carrier_index, occurrence=gonol.occurrence, carried_options=gonol.carried_options, couplings=gonol.couplings, - structure=gonol.structure, + structure=frozen_structure, + geometry=receipt.geometry, ) + if replayed.receipt_digest != receipt.receipt_digest: + raise PublicGonolConstructionError("receipt does not match its retained canonical payload") + return replayed __all__ = [ diff --git a/epac_ucns_provenance.py b/epac_ucns_provenance.py index 99d3e57..331e47a 100644 --- a/epac_ucns_provenance.py +++ b/epac_ucns_provenance.py @@ -236,7 +236,7 @@ def _verify_witness( if head != pinned_commit: return "hmmm" root = Path(root_text) - relative_paths = sorted({str(record[0]) for record in records}) + disk_records: dict[str, tuple[Path, str]] = {} for relative, absolute, qualname, loaded_digest, disk_digest, _mode in records: path = Path(str(absolute)) try: @@ -247,6 +247,7 @@ def _verify_witness( expected_digest = _expected_code_fingerprint(path, str(qualname)) if expected_digest is None or expected_digest != loaded_digest: return "hmmm" + disk_records[str(relative)] = (path, f"{int(_mode) & 0o177777:06o}") try: observed = runner( ("git", "-C", str(root), "rev-parse", "HEAD"), @@ -257,33 +258,28 @@ def _verify_witness( ) if getattr(observed, "stdout", "").strip() != pinned_commit: return "hmmm" - for relative_path in relative_paths: - runner( - ("git", "-C", str(root), "ls-files", "--error-unmatch", "--", relative_path), + for relative_path, (path, disk_mode) in sorted(disk_records.items()): + tree_entry = runner( + ("git", "-C", str(root), "ls-tree", pinned_commit, "--", relative_path), check=True, capture_output=True, text=True, timeout=2, ) - status = runner( - ( - "git", - "-C", - str(root), - "status", - "--porcelain=v1", - "--untracked-files=no", - "--", - *relative_paths, - ), - check=True, - capture_output=True, - text=True, - timeout=2, - ) + fields = getattr(tree_entry, "stdout", "").strip().split(None, 3) + if len(fields) != 4 or fields[0] != disk_mode or fields[1] != "blob": + return "hmmm" + pinned_blob = runner( + ("git", "-C", str(root), "cat-file", "blob", fields[2]), + check=True, + capture_output=True, + timeout=2, + ) + if getattr(pinned_blob, "stdout", b"") != path.read_bytes(): + return "hmmm" except (OSError, subprocess.SubprocessError): return "hmmm" - return pinned_commit if not getattr(status, "stdout", "").strip() else "hmmm" + return pinned_commit def verify_loaded_ucns_commit( diff --git a/tests/test_epac_public_gonol.py b/tests/test_epac_public_gonol.py index 845bc7a..5e01aee 100644 --- a/tests/test_epac_public_gonol.py +++ b/tests/test_epac_public_gonol.py @@ -35,6 +35,8 @@ def test_constructor_is_not_edcm(self) -> None: self.assertEqual(CONSTRUCTOR_ID, "epac.public_gonol") self.assertEqual(receipt.gonol.identity_glyph, "O") self.assertEqual(receipt.gonol.carrier_index, public_gonol_function("O").index) + self.assertEqual(receipt.geometry["ucns_commit"], PINNED_UCNS_COMMIT) + self.assertEqual(receipt.gonol.geometry, receipt.geometry) self.assertEqual(PINNED_UCNS_COMMIT, "828c0b8bbcfc267efb5701da714191c1f73a81ff") self.assertEqual( PINNED_PUBLIC_GONOL_SHA256, @@ -349,11 +351,17 @@ def test_ucns_commit_is_not_stamped_when_loaded_code_is_stale(self) -> None: public_gonol_module.public_gonol_function = namespace["public_gonol_function"] epac_ucns_provenance.clear_ucns_verification_cache() try: - geometry = public_gonol_module._geometry(None, None) + receipt = construct_public_gonol( + source_id="epac.test:stale-ucns", + relation="epac.provenance.test", + ) finally: public_gonol_module.public_gonol_function = original_function epac_ucns_provenance.clear_ucns_verification_cache() - self.assertEqual(geometry["ucns_commit"], "hmmm") + self.assertEqual(receipt.geometry["ucns_commit"], "hmmm") + replayed = replay_public_gonol(receipt) + self.assertEqual(replayed.receipt_digest, receipt.receipt_digest) + self.assertEqual(replayed.geometry["ucns_commit"], "hmmm") def test_unknown_glyph_fails_closed(self) -> None: with self.assertRaises(PublicGonolConstructionError): diff --git a/tests/test_epac_ucns_provenance.py b/tests/test_epac_ucns_provenance.py index b2b2c79..116d55d 100644 --- a/tests/test_epac_ucns_provenance.py +++ b/tests/test_epac_ucns_provenance.py @@ -12,6 +12,12 @@ # call: self::test_unchanged_witness_runs_git_once # mutates: in-memory verification cache # cleanup: clears verification cache +# +# id: check_epac_ucns_pin_compares_pinned_blob_bytes +# proves: epac_ucns_pin_matches_loaded_code +# call: self::test_pinned_blob_mismatch_returns_hmmm +# mutates: none +# cleanup: clears verification cache # === END CHECKS === from __future__ import annotations @@ -78,6 +84,20 @@ def counting_runner(command, **kwargs): self.assertEqual(len(calls), first_call_count) self.assertEqual(ucns_verification_cache_info().hits, 1) + def test_pinned_blob_mismatch_returns_hmmm(self) -> None: + def mismatched_blob_runner(command, **kwargs): + if "cat-file" in command: + return subprocess.CompletedProcess(command, 0, stdout=b"not-the-pinned-source") + return subprocess.run(command, **kwargs) + + observed = verify_loaded_ucns_commit( + pinned_commit=PINNED_UCNS_COMMIT, + dependencies=(public_gonol_function, native_mobius_state), + runner=mismatched_blob_runner, + ) + + self.assertEqual(observed, "hmmm") + if __name__ == "__main__": unittest.main() From 424ce67ec0997da4b10f90836143ab3c41912b8b Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 9 Sep 2026 13:02:07 -0700 Subject: [PATCH 13/33] fix(epac): bind transitive UCNS runtime state --- README.md | 2 +- epac_ucns_provenance.py | 222 ++++++++++++++++---- subatomic/subatomic-affixiation-baseline.md | 2 +- tests/test_epac_ucns_provenance.py | 26 +++ 4 files changed, 211 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index 95333c2..aa7aa9c 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ The extraction preserves the stack research artifacts and their epistemic status The current extraction gate executes: -- 50 repository regression tests; +- 53 repository regression tests; - 30 subatomic executable witnesses; - the preregistered molecular comparison, requiring all four current standings to remain `FALSIFIED`; - deterministic work-graph digest verification. diff --git a/epac_ucns_provenance.py b/epac_ucns_provenance.py index 331e47a..be9913c 100644 --- a/epac_ucns_provenance.py +++ b/epac_ucns_provenance.py @@ -1,10 +1,10 @@ """Loaded-code-aware UCNS provenance verification shared by EPAC constructors. -The verifier stamps a UCNS commit only when the executing function bytecode -matches the clean source at the declared commit. Verification is cached by a -witness containing HEAD, index state, source bytes, file modes, and loaded code, -so repeated nested construction avoids Git subprocesses without preserving a -stale answer. +The verifier stamps a UCNS commit only when each executing function and its +transitively referenced UCNS runtime state match the clean source at the +declared commit. Verification is cached by a witness containing HEAD, index +state, source bytes, file modes, and loaded state, so repeated nested +construction avoids Git subprocesses without preserving a stale answer. Usage guidance: @@ -19,10 +19,10 @@ # id: epac_ucns_loaded_provenance # module_name: epac_ucns_provenance # module_kind: service -# summary: binds UCNS receipt provenance to clean pinned source and the function code actually executing +# summary: binds UCNS receipt provenance to clean pinned source and the transitive UCNS runtime state actually executing # owner: The Interdependency # public_surface: verify_loaded_ucns_commit, clear_ucns_verification_cache, ucns_verification_cache_info -# internal_surface: source witness, Git metadata resolution, code fingerprint, cached verification +# internal_surface: source witness, Git metadata resolution, transitive loaded-state fingerprint, cached verification # auth_boundary: none # storage_boundary: read # network_boundary: none @@ -37,7 +37,7 @@ # === CONTRACTS === # id: epac_ucns_pin_matches_loaded_code # given: EPAC is about to stamp a pinned UCNS dependency identity -# then: each executing dependency function matches the clean tracked source at that exact HEAD; otherwise the identity is hmmm +# then: each executing dependency function and its transitively referenced UCNS helpers, classes, defaults, closures, and globals match the clean tracked source at that exact HEAD; otherwise the identity is hmmm # class: provenance # # id: epac_ucns_verification_reuses_only_identical_witness @@ -50,12 +50,16 @@ from functools import lru_cache from hashlib import sha256 +import importlib.util import inspect import marshal from pathlib import Path import re import subprocess -from types import CodeType +import sys +from dataclasses import fields, is_dataclass +from enum import Enum +from types import CodeType, FunctionType, ModuleType from typing import Callable, Sequence @@ -157,23 +161,142 @@ def _normalized_code(code: CodeType) -> tuple[object, ...]: ) -def _code_fingerprint(code: CodeType) -> str: - return sha256(marshal.dumps(_normalized_code(code))).hexdigest() +def _freeze_loaded_state( + value: object, + owner_module: str, + seen: dict[int, int], +) -> tuple[object, ...]: + """Normalize one transitive callable state without module-name noise.""" + + if isinstance(value, Enum): + return ("enum-member", value.name, _freeze_loaded_state(value.value, owner_module, seen)) + if value is None or isinstance(value, (bool, int, str, bytes)): + return ("literal", type(value).__name__, value) + if isinstance(value, float): + return ("float", value.hex()) + identity = id(value) + if identity in seen: + return ("ref", seen[identity]) + seen[identity] = len(seen) + if isinstance(value, tuple): + return ("tuple", *(_freeze_loaded_state(item, owner_module, seen) for item in value)) + if isinstance(value, list): + return ("list", *(_freeze_loaded_state(item, owner_module, seen) for item in value)) + if isinstance(value, (set, frozenset)): + items = [_freeze_loaded_state(item, owner_module, seen) for item in value] + return ("set", *sorted(items, key=repr)) + if isinstance(value, dict): + items = [ + ( + _freeze_loaded_state(key, owner_module, seen), + _freeze_loaded_state(item, owner_module, seen), + ) + for key, item in value.items() + ] + return ("dict", *sorted(items, key=repr)) + if isinstance(value, ModuleType): + return ("external-module", value.__name__) + if isinstance(value, CodeType): + return ("code", _normalized_code(value)) + if isinstance(value, FunctionType): + module_name = getattr(value, "__module__", "") + if module_name != owner_module: + return ("external-function", module_name, value.__qualname__) + global_state = [] + for name in sorted(set(value.__code__.co_names)): + if name in value.__globals__: + global_state.append( + (name, _freeze_loaded_state(value.__globals__[name], owner_module, seen)) + ) + closure = tuple( + _freeze_loaded_state(cell.cell_contents, owner_module, seen) + for cell in (value.__closure__ or ()) + ) + return ( + "function", + value.__qualname__, + _normalized_code(value.__code__), + _freeze_loaded_state(value.__defaults__, owner_module, seen), + _freeze_loaded_state(value.__kwdefaults__, owner_module, seen), + _freeze_loaded_state(value.__annotations__, owner_module, seen), + tuple(global_state), + closure, + ) + if isinstance(value, type): + module_name = getattr(value, "__module__", "") + if module_name != owner_module: + return ("external-class", module_name, value.__qualname__) + attributes = [] + for name, item in sorted(vars(value).items()): + if name in {"__module__", "__doc__", "__dict__", "__weakref__"}: + continue + if isinstance(item, (staticmethod, classmethod)): + item = item.__func__ + if isinstance(item, property): + item = (item.fget, item.fset, item.fdel) + if ( + name.startswith("__") + and name not in {"__annotations__", "__match_args__", "__slots__"} + and not callable(item) + ): + continue + attributes.append((name, _freeze_loaded_state(item, owner_module, seen))) + members = tuple( + (name, _freeze_loaded_state(item.value, owner_module, seen)) + for name, item in getattr(value, "__members__", {}).items() + ) + return ("class", value.__qualname__, tuple(attributes), members) + value_type = type(value) + if value_type.__module__ == owner_module and is_dataclass(value): + return ( + "dataclass-instance", + value_type.__qualname__, + tuple( + (field.name, _freeze_loaded_state(getattr(value, field.name), owner_module, seen)) + for field in fields(value) + ), + ) + if value_type.__module__ == "fractions" and hasattr(value, "numerator"): + return ("fraction", int(value.numerator), int(value.denominator)) + return ("external-object", value_type.__module__, value_type.__qualname__) -def _find_code(module_code: CodeType, qualname: str) -> CodeType | None: - matches: list[CodeType] = [] +def _transitive_fingerprint(dependency: Callable[..., object]) -> str: + owner_module = getattr(dependency, "__module__", "") + frozen = _freeze_loaded_state(dependency, owner_module, {}) + return sha256(marshal.dumps(frozen)).hexdigest() - def walk(code: CodeType) -> None: - for item in code.co_consts: - if not isinstance(item, CodeType): - continue - if item.co_qualname == qualname: - matches.append(item) - walk(item) - walk(module_code) - return matches[0] if len(matches) == 1 else None +def _fresh_dependency_fingerprints( + path: Path, + disk_digest: str, + qualnames: Sequence[str], +) -> dict[str, str] | None: + module_name = f"_epac_ucns_verified_{disk_digest[:20]}" + spec = importlib.util.spec_from_file_location(module_name, path) + if spec is None or spec.loader is None: + return None + module = importlib.util.module_from_spec(spec) + prior = sys.modules.get(module_name) + sys.modules[module_name] = module + try: + spec.loader.exec_module(module) + result: dict[str, str] = {} + for qualname in qualnames: + item: object = module + for part in qualname.split("."): + item = getattr(item, part) + if not isinstance(item, FunctionType): + return None + result[qualname] = _transitive_fingerprint(item) + return result + except (AttributeError, ImportError, OSError, RuntimeError, TypeError, ValueError): + return None + finally: + if prior is None: + sys.modules.pop(module_name, None) + else: + sys.modules[module_name] = prior def _source_records(dependencies: Sequence[Callable[..., object]]) -> tuple[Path, tuple[tuple[object, ...], ...]] | None: @@ -203,7 +326,7 @@ def _source_records(dependencies: Sequence[Callable[..., object]]) -> tuple[Path relative, str(path), qualname, - _code_fingerprint(code), + _transitive_fingerprint(dependency), sha256(data).hexdigest(), stat.st_mode, ) @@ -213,15 +336,6 @@ def _source_records(dependencies: Sequence[Callable[..., object]]) -> tuple[Path return root, tuple(records) -def _expected_code_fingerprint(path: Path, qualname: str) -> str | None: - try: - module_code = compile(path.read_bytes(), str(path), "exec", dont_inherit=True) - except (OSError, SyntaxError, ValueError): - return None - code = _find_code(module_code, qualname) - return None if code is None else _code_fingerprint(code) - - @lru_cache(maxsize=32) def _verify_witness( pinned_commit: str, @@ -236,7 +350,7 @@ def _verify_witness( if head != pinned_commit: return "hmmm" root = Path(root_text) - disk_records: dict[str, tuple[Path, str]] = {} + disk_records: dict[str, tuple[Path, str, str, list[tuple[str, str]]]] = {} for relative, absolute, qualname, loaded_digest, disk_digest, _mode in records: path = Path(str(absolute)) try: @@ -244,10 +358,25 @@ def _verify_witness( return "hmmm" except OSError: return "hmmm" - expected_digest = _expected_code_fingerprint(path, str(qualname)) - if expected_digest is None or expected_digest != loaded_digest: - return "hmmm" - disk_records[str(relative)] = (path, f"{int(_mode) & 0o177777:06o}") + relative_text = str(relative) + mode = f"{int(_mode) & 0o177777:06o}" + existing = disk_records.get(relative_text) + if existing is None: + disk_records[relative_text] = ( + path, + mode, + str(disk_digest), + [(str(qualname), str(loaded_digest))], + ) + else: + existing_path, existing_mode, existing_digest, dependencies = existing + if ( + existing_path != path + or existing_mode != mode + or existing_digest != disk_digest + ): + return "hmmm" + dependencies.append((str(qualname), str(loaded_digest))) try: observed = runner( ("git", "-C", str(root), "rev-parse", "HEAD"), @@ -258,7 +387,9 @@ def _verify_witness( ) if getattr(observed, "stdout", "").strip() != pinned_commit: return "hmmm" - for relative_path, (path, disk_mode) in sorted(disk_records.items()): + for relative_path, (path, disk_mode, _disk_digest, _dependencies) in sorted( + disk_records.items() + ): tree_entry = runner( ("git", "-C", str(root), "ls-tree", pinned_commit, "--", relative_path), check=True, @@ -279,6 +410,19 @@ def _verify_witness( return "hmmm" except (OSError, subprocess.SubprocessError): return "hmmm" + for path, _disk_mode, disk_digest, dependencies in disk_records.values(): + expected = _fresh_dependency_fingerprints( + path, + disk_digest, + tuple(qualname for qualname, _loaded_digest in dependencies), + ) + if expected is None: + return "hmmm" + if any( + expected.get(qualname) != loaded_digest + for qualname, loaded_digest in dependencies + ): + return "hmmm" return pinned_commit @@ -288,7 +432,7 @@ def verify_loaded_ucns_commit( dependencies: Sequence[Callable[..., object]], runner: Runner = subprocess.run, ) -> str: - """Return ``pinned_commit`` only for a clean, loaded-code-matched runtime.""" + """Return ``pinned_commit`` only for a clean, loaded-state-matched runtime.""" if not HEX40.fullmatch(pinned_commit): return "hmmm" diff --git a/subatomic/subatomic-affixiation-baseline.md b/subatomic/subatomic-affixiation-baseline.md index 5bd9a0b..896982d 100644 --- a/subatomic/subatomic-affixiation-baseline.md +++ b/subatomic/subatomic-affixiation-baseline.md @@ -303,6 +303,6 @@ law, and no scale interchange is introduced. Standing is `implemented-candidate` - Historical evidence at this section's original 2026-08-22 stop: **26/26 subatomic tests pass**; sibling epac suite **29 tests OK**; CONTRACTS↔CHECKS audit **closed** (26 contracts / 26 checks). Current extracted-repo gate records **30 subatomic witnesses** - and **50 repository tests**. + and **53 repository tests**. - The dimensional-arity doctrine is implemented by the sibling `epac_dimensional_arity.py` (committed); no duplicate is maintained here. Status remains `CROSS-DOMAIN-HYPOTHESIS`. diff --git a/tests/test_epac_ucns_provenance.py b/tests/test_epac_ucns_provenance.py index 116d55d..1821c6d 100644 --- a/tests/test_epac_ucns_provenance.py +++ b/tests/test_epac_ucns_provenance.py @@ -58,6 +58,32 @@ def test_loaded_code_mismatch_returns_hmmm(self) -> None: self.assertEqual(observed, "hmmm") + helper_namespace: dict[str, object] = { + "__name__": public_gonol_function.__module__ + } + exec( + compile( + "def public_gonol_position(value):\n return None\n", + inspect.getfile(public_gonol_function), + "exec", + ), + helper_namespace, + ) + loaded_globals = public_gonol_function.__globals__ + original_helper = loaded_globals["public_gonol_position"] + try: + loaded_globals["public_gonol_position"] = helper_namespace[ + "public_gonol_position" + ] + transitive_observed = verify_loaded_ucns_commit( + pinned_commit=PINNED_UCNS_COMMIT, + dependencies=(public_gonol_function, native_mobius_state), + ) + finally: + loaded_globals["public_gonol_position"] = original_helper + + self.assertEqual(transitive_observed, "hmmm") + def test_unchanged_witness_runs_git_once(self) -> None: calls: list[tuple[str, ...]] = [] From 003d113306c518d482cf1d8397a09f61f53e48b1 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 9 Sep 2026 13:52:56 -0700 Subject: [PATCH 14/33] fix(epac): version and validate retained receipts --- epac_public_gonol.py | 56 ++++++++++++++++++++++++++++++--- epac_ucns_provenance.py | 14 +++++---- tests/test_epac_public_gonol.py | 26 +++++++++++++++ 3 files changed, 86 insertions(+), 10 deletions(-) diff --git a/epac_public_gonol.py b/epac_public_gonol.py index c75a415..9d2a73b 100644 --- a/epac_public_gonol.py +++ b/epac_public_gonol.py @@ -31,7 +31,7 @@ # summary: EPAC candidate constructor that closes gonols on the UCNS Public Gonol carrier with oriented couplings and arity charge states; not the EDCM text-domain constructor # owner: The Interdependency # public_surface: CONSTRUCTOR_ID, CONSTRUCTOR_VERSION, PINNED_UCNS_COMMIT, PINNED_PUBLIC_GONOL_SHA256, ClosedPublicGonol, PublicGonolReceipt, PublicGonolConstructionError, construct_public_gonol, replay_public_gonol, canonical_receipt_bytes -# internal_surface: _require_text, _identity_position, _verified_ucns_commit, _geometry, _freeze_json, _json_ready, _tuple_tree, _canonical_coupling_record, _coupling_sort_key, _canonical_structure_tree, _participant_payload, _atomic_payload, _receipt_payload, _digest, _expected_structure_from_couplings, _validate_structure_matches_couplings +# internal_surface: _require_text, _identity_position, _verified_ucns_commit, _geometry, _freeze_json, _json_ready, _tuple_tree, _canonical_coupling_record, _coupling_sort_key, _canonical_structure_tree, _participant_payload, _atomic_payload, _receipt_payload, _digest, _expected_structure_from_couplings, _validate_structure_matches_couplings, _validate_retained_receipt # auth_boundary: EPAC owns particle/energy gonol closure; UCNS owns Public Gonol carrier identity and native Möbius ε; EDCM text-domain constructor is not used; METAPAT affixiation is consumed, not redefined # storage_boundary: none; receipts remain caller-owned in-memory objects # network_boundary: none @@ -60,7 +60,7 @@ # # id: epac_public_gonol_replays_byte_identical # given: a PublicGonolReceipt -# then: replay_public_gonol reproduces the same receipt_digest +# then: replay_public_gonol validates the complete retained envelope and reproduces the same receipt_digest # class: correctness # since: 2026-08-22 # @@ -96,7 +96,7 @@ CONSTRUCTOR_ID = "epac.public_gonol" -CONSTRUCTOR_VERSION = "v1" +CONSTRUCTOR_VERSION = "v2" PINNED_UCNS_COMMIT = "828c0b8bbcfc267efb5701da714191c1f73a81ff" PINNED_PUBLIC_GONOL_SHA256 = "55d10c84529a4d7bc7714786357e977b68d9df2ac3f73d20e229580b552c2ef5" STANDING = "implemented-candidate" @@ -549,6 +549,53 @@ def _digest(payload: Mapping[str, Any]) -> str: return sha256(canonical_receipt_bytes(payload)).hexdigest() +def _validate_retained_receipt(receipt: PublicGonolReceipt) -> None: + """Reject contradictory or stale duplicate fields before replay.""" + + if not isinstance(receipt, PublicGonolReceipt) or not isinstance( + receipt.gonol, ClosedPublicGonol + ): + raise PublicGonolConstructionError("replay requires a PublicGonolReceipt") + gonol = receipt.gonol + expected_envelope = ( + receipt.constructor_id == CONSTRUCTOR_ID + and receipt.constructor_version == CONSTRUCTOR_VERSION + and receipt.standing == STANDING + and receipt.selection_effect == SELECTION_EFFECT + and receipt.nonclaims == NONCLAIMS + and receipt.hmmm == HMMM + and receipt.source_id == gonol.source_id + and receipt.receipt_digest == gonol.receipt_digest + ) + if not expected_envelope: + raise PublicGonolConstructionError("receipt envelope is not canonical") + outer_geometry = _freeze_json(receipt.geometry) + gonol_geometry = _freeze_json(gonol.geometry) + if _tuple_tree(outer_geometry) != _tuple_tree(gonol_geometry): + raise PublicGonolConstructionError("retained receipt geometries disagree") + if _tuple_tree(receipt.structure) != _tuple_tree(gonol.structure): + raise PublicGonolConstructionError("retained receipt structures disagree") + if gonol.geometry_digest != _digest({"geometry": gonol_geometry}): + raise PublicGonolConstructionError("retained geometry digest does not match geometry") + expected_atomic_id = _digest( + { + "atomic": _atomic_payload( + source_id=gonol.source_id, + occurrence=gonol.occurrence, + relation=gonol.relation, + identity_glyph=gonol.identity_glyph, + carrier_index=gonol.carrier_index, + participants=gonol.participants, + carried_options=gonol.carried_options, + couplings=gonol.couplings, + structure=gonol.structure, + ) + } + ) + if gonol.atomic_id != expected_atomic_id: + raise PublicGonolConstructionError("retained atomic id does not match gonol") + + def _seal_public_gonol( *, source_id: str, @@ -672,6 +719,7 @@ def construct_public_gonol( def replay_public_gonol(receipt: PublicGonolReceipt) -> PublicGonolReceipt: """Replay one receipt from its closed gonol. Reproduces construction identity.""" + _validate_retained_receipt(receipt) gonol = receipt.gonol derived_structure = _validate_structure_matches_couplings( gonol.couplings, @@ -688,7 +736,7 @@ def replay_public_gonol(receipt: PublicGonolReceipt) -> PublicGonolReceipt: carried_options=gonol.carried_options, couplings=gonol.couplings, structure=frozen_structure, - geometry=receipt.geometry, + geometry=gonol.geometry, ) if replayed.receipt_digest != receipt.receipt_digest: raise PublicGonolConstructionError("receipt does not match its retained canonical payload") diff --git a/epac_ucns_provenance.py b/epac_ucns_provenance.py index be9913c..498be00 100644 --- a/epac_ucns_provenance.py +++ b/epac_ucns_provenance.py @@ -50,7 +50,6 @@ from functools import lru_cache from hashlib import sha256 -import importlib.util import inspect import marshal from pathlib import Path @@ -273,14 +272,17 @@ def _fresh_dependency_fingerprints( qualnames: Sequence[str], ) -> dict[str, str] | None: module_name = f"_epac_ucns_verified_{disk_digest[:20]}" - spec = importlib.util.spec_from_file_location(module_name, path) - if spec is None or spec.loader is None: - return None - module = importlib.util.module_from_spec(spec) + module = ModuleType(module_name) + module.__file__ = str(path) + module.__package__ = "" prior = sys.modules.get(module_name) sys.modules[module_name] = module try: - spec.loader.exec_module(module) + source = path.read_bytes() + if sha256(source).hexdigest() != disk_digest: + return None + code = compile(source, str(path), "exec", dont_inherit=True) + exec(code, module.__dict__) result: dict[str, str] = {} for qualname in qualnames: item: object = module diff --git a/tests/test_epac_public_gonol.py b/tests/test_epac_public_gonol.py index 5e01aee..2cd0555 100644 --- a/tests/test_epac_public_gonol.py +++ b/tests/test_epac_public_gonol.py @@ -1,6 +1,7 @@ from __future__ import annotations import copy +from dataclasses import replace import inspect import sys import unittest @@ -14,6 +15,7 @@ import epac_ucns_provenance from epac_public_gonol import ( CONSTRUCTOR_ID, + CONSTRUCTOR_VERSION, PINNED_PUBLIC_GONOL_SHA256, PINNED_UCNS_COMMIT, PublicGonolConstructionError, @@ -33,6 +35,7 @@ def test_constructor_is_not_edcm(self) -> None: ) self.assertEqual(receipt.constructor_id, CONSTRUCTOR_ID) self.assertEqual(CONSTRUCTOR_ID, "epac.public_gonol") + self.assertEqual(CONSTRUCTOR_VERSION, "v2") self.assertEqual(receipt.gonol.identity_glyph, "O") self.assertEqual(receipt.gonol.carrier_index, public_gonol_function("O").index) self.assertEqual(receipt.geometry["ucns_commit"], PINNED_UCNS_COMMIT) @@ -73,6 +76,29 @@ def test_replay_matches(self) -> None: second = replay_public_gonol(first) self.assertEqual(first.receipt_digest, second.receipt_digest) + contradictory_geometry = dict(first.gonol.geometry) + contradictory_geometry["ucns_commit"] = "hmmm" + contradictory_gonol = replace( + first.gonol, + geometry=contradictory_geometry, + ) + with self.assertRaisesRegex( + PublicGonolConstructionError, "retained receipt geometries disagree" + ): + replay_public_gonol(replace(first, gonol=contradictory_gonol)) + + with self.assertRaisesRegex( + PublicGonolConstructionError, "geometry digest" + ): + replay_public_gonol( + replace(first, gonol=replace(first.gonol, geometry_digest="0" * 64)) + ) + + with self.assertRaisesRegex( + PublicGonolConstructionError, "receipt envelope" + ): + replay_public_gonol(replace(first, constructor_version="v1")) + def test_charged_couplings_are_the_structure(self) -> None: declared = space( ["z", "x", "y"], From 2e62e492b5943480ab17b0b55d47de546c492348 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 9 Sep 2026 14:09:20 -0700 Subject: [PATCH 15/33] fix(replay): validate participant geometry trees --- epac_public_gonol.py | 21 ++++++++++++++++++--- tests/test_epac_public_gonol.py | 17 +++++++++++++++++ 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/epac_public_gonol.py b/epac_public_gonol.py index 9d2a73b..fb460a6 100644 --- a/epac_public_gonol.py +++ b/epac_public_gonol.py @@ -31,7 +31,7 @@ # summary: EPAC candidate constructor that closes gonols on the UCNS Public Gonol carrier with oriented couplings and arity charge states; not the EDCM text-domain constructor # owner: The Interdependency # public_surface: CONSTRUCTOR_ID, CONSTRUCTOR_VERSION, PINNED_UCNS_COMMIT, PINNED_PUBLIC_GONOL_SHA256, ClosedPublicGonol, PublicGonolReceipt, PublicGonolConstructionError, construct_public_gonol, replay_public_gonol, canonical_receipt_bytes -# internal_surface: _require_text, _identity_position, _verified_ucns_commit, _geometry, _freeze_json, _json_ready, _tuple_tree, _canonical_coupling_record, _coupling_sort_key, _canonical_structure_tree, _participant_payload, _atomic_payload, _receipt_payload, _digest, _expected_structure_from_couplings, _validate_structure_matches_couplings, _validate_retained_receipt +# internal_surface: _require_text, _identity_position, _verified_ucns_commit, _geometry, _freeze_json, _json_ready, _tuple_tree, _canonical_coupling_record, _coupling_sort_key, _canonical_structure_tree, _participant_payload, _atomic_payload, _receipt_payload, _digest, _expected_structure_from_couplings, _validate_structure_matches_couplings, _validate_retained_geometry_tree, _validate_retained_receipt # auth_boundary: EPAC owns particle/energy gonol closure; UCNS owns Public Gonol carrier identity and native Möbius ε; EDCM text-domain constructor is not used; METAPAT affixiation is consumed, not redefined # storage_boundary: none; receipts remain caller-owned in-memory objects # network_boundary: none @@ -549,6 +549,22 @@ def _digest(payload: Mapping[str, Any]) -> str: return sha256(canonical_receipt_bytes(payload)).hexdigest() +def _validate_retained_geometry_tree(gonol: ClosedPublicGonol) -> None: + """Validate the geometry digest of every retained closed participant.""" + + if not isinstance(gonol, ClosedPublicGonol): + raise PublicGonolConstructionError( + "retained participants must be closed EPAC public gonols" + ) + geometry = _freeze_json(gonol.geometry) + if gonol.geometry_digest != _digest({"geometry": geometry}): + raise PublicGonolConstructionError( + "retained geometry digest does not match geometry" + ) + for participant in gonol.participants: + _validate_retained_geometry_tree(participant) + + def _validate_retained_receipt(receipt: PublicGonolReceipt) -> None: """Reject contradictory or stale duplicate fields before replay.""" @@ -575,8 +591,7 @@ def _validate_retained_receipt(receipt: PublicGonolReceipt) -> None: raise PublicGonolConstructionError("retained receipt geometries disagree") if _tuple_tree(receipt.structure) != _tuple_tree(gonol.structure): raise PublicGonolConstructionError("retained receipt structures disagree") - if gonol.geometry_digest != _digest({"geometry": gonol_geometry}): - raise PublicGonolConstructionError("retained geometry digest does not match geometry") + _validate_retained_geometry_tree(gonol) expected_atomic_id = _digest( { "atomic": _atomic_payload( diff --git a/tests/test_epac_public_gonol.py b/tests/test_epac_public_gonol.py index 2cd0555..0e89acd 100644 --- a/tests/test_epac_public_gonol.py +++ b/tests/test_epac_public_gonol.py @@ -99,6 +99,23 @@ def test_replay_matches(self) -> None: ): replay_public_gonol(replace(first, constructor_version="v1")) + parent = construct_public_gonol( + source_id="epac.test:H2", + relation="epac.molecular.participation", + participants=(first.gonol,), + ) + forged_child_geometry = dict(first.gonol.geometry) + forged_child_geometry["ucns_commit"] = "forged-child-commit" + forged_child = replace(first.gonol, geometry=forged_child_geometry) + forged_parent = replace( + parent, + gonol=replace(parent.gonol, participants=(forged_child,)), + ) + with self.assertRaisesRegex( + PublicGonolConstructionError, "retained geometry digest" + ): + replay_public_gonol(forged_parent) + def test_charged_couplings_are_the_structure(self) -> None: declared = space( ["z", "x", "y"], From bdef24628ce4790f47759ef9c95cd379fcbadf59 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 9 Sep 2026 14:44:04 -0700 Subject: [PATCH 16/33] fix(replay): validate complete participant envelopes --- README.md | 2 +- epac_public_gonol.py | 75 +++++++++++++++++++----------- epac_ucns_provenance.py | 8 +++- tests/test_epac_public_gonol.py | 52 ++++++++++++++++++++- tests/test_epac_ucns_provenance.py | 8 ++++ 5 files changed, 116 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index aa7aa9c..8ef4b3f 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ The extraction preserves the stack research artifacts and their epistemic status The current extraction gate executes: -- 53 repository regression tests; +- 54 repository regression tests; - 30 subatomic executable witnesses; - the preregistered molecular comparison, requiring all four current standings to remain `FALSIFIED`; - deterministic work-graph digest verification. diff --git a/epac_public_gonol.py b/epac_public_gonol.py index fb460a6..ea7cfbe 100644 --- a/epac_public_gonol.py +++ b/epac_public_gonol.py @@ -31,7 +31,7 @@ # summary: EPAC candidate constructor that closes gonols on the UCNS Public Gonol carrier with oriented couplings and arity charge states; not the EDCM text-domain constructor # owner: The Interdependency # public_surface: CONSTRUCTOR_ID, CONSTRUCTOR_VERSION, PINNED_UCNS_COMMIT, PINNED_PUBLIC_GONOL_SHA256, ClosedPublicGonol, PublicGonolReceipt, PublicGonolConstructionError, construct_public_gonol, replay_public_gonol, canonical_receipt_bytes -# internal_surface: _require_text, _identity_position, _verified_ucns_commit, _geometry, _freeze_json, _json_ready, _tuple_tree, _canonical_coupling_record, _coupling_sort_key, _canonical_structure_tree, _participant_payload, _atomic_payload, _receipt_payload, _digest, _expected_structure_from_couplings, _validate_structure_matches_couplings, _validate_retained_geometry_tree, _validate_retained_receipt +# internal_surface: _require_text, _identity_position, _verified_ucns_commit, _geometry, _freeze_json, _json_ready, _tuple_tree, _canonical_coupling_record, _coupling_sort_key, _canonical_structure_tree, _participant_payload, _atomic_payload, _receipt_payload, _digest, _expected_structure_from_couplings, _validate_structure_matches_couplings, _validate_retained_gonol_tree, _validate_retained_receipt # auth_boundary: EPAC owns particle/energy gonol closure; UCNS owns Public Gonol carrier identity and native Möbius ε; EDCM text-domain constructor is not used; METAPAT affixiation is consumed, not redefined # storage_boundary: none; receipts remain caller-owned in-memory objects # network_boundary: none @@ -326,17 +326,27 @@ def _canonical_degree_tree(item: Any) -> Any: def _coupling_signature(item: Mapping[str, Any]) -> tuple[Any, int, Any]: + if not isinstance(item, MappingABC): + raise PublicGonolConstructionError("each coupling must be a mapping") + arity = item.get("arity") + if isinstance(arity, bool) or not isinstance(arity, int): + raise PublicGonolConstructionError("coupling arity must be an integer") declared = item.get("declared_ids", item.get("coupling")) charge_state = item.get("charge_state") if charge_state is None: charge_state = (item.get("slot_charges"), item.get("mobius_epsilon_t0")) - return (_tuple_tree(declared), int(item.get("arity", -1)), _tuple_tree(charge_state)) + return (_tuple_tree(declared), arity, _tuple_tree(charge_state)) def _structure_part_signature(item: Mapping[str, Any]) -> tuple[Any, int, Any]: + if not isinstance(item, MappingABC): + raise PublicGonolConstructionError("each structure part must be a mapping") + arity = item.get("arity") + if isinstance(arity, bool) or not isinstance(arity, int): + raise PublicGonolConstructionError("structure part arity must be an integer") return ( _tuple_tree(item.get("coupling")), - int(item.get("arity", -1)), + arity, _tuple_tree(item.get("charge_state")), ) @@ -549,20 +559,49 @@ def _digest(payload: Mapping[str, Any]) -> str: return sha256(canonical_receipt_bytes(payload)).hexdigest() -def _validate_retained_geometry_tree(gonol: ClosedPublicGonol) -> None: - """Validate the geometry digest of every retained closed participant.""" +def _validate_retained_gonol_tree(gonol: ClosedPublicGonol) -> None: + """Validate every retained participant's geometry and sealed identity.""" if not isinstance(gonol, ClosedPublicGonol): raise PublicGonolConstructionError( "retained participants must be closed EPAC public gonols" ) + for participant in gonol.participants: + _validate_retained_gonol_tree(participant) geometry = _freeze_json(gonol.geometry) - if gonol.geometry_digest != _digest({"geometry": geometry}): + expected_geometry_digest = _digest({"geometry": geometry}) + if gonol.geometry_digest != expected_geometry_digest: raise PublicGonolConstructionError( "retained geometry digest does not match geometry" ) - for participant in gonol.participants: - _validate_retained_geometry_tree(participant) + _validate_structure_matches_couplings(gonol.couplings, gonol.structure) + gonol_payload = _atomic_payload( + source_id=gonol.source_id, + occurrence=gonol.occurrence, + relation=gonol.relation, + identity_glyph=gonol.identity_glyph, + carrier_index=gonol.carrier_index, + participants=gonol.participants, + carried_options=gonol.carried_options, + couplings=gonol.couplings, + structure=gonol.structure, + ) + expected_atomic_id = _digest({"atomic": gonol_payload}) + if gonol.atomic_id != expected_atomic_id: + raise PublicGonolConstructionError("retained atomic id does not match gonol") + expected_receipt_digest = _digest( + _receipt_payload( + source_id=gonol.source_id, + gonol_payload=gonol_payload, + geometry=geometry, + atomic_id=expected_atomic_id, + geometry_digest=expected_geometry_digest, + ) + ) + if gonol.receipt_digest != expected_receipt_digest: + raise PublicGonolConstructionError( + "retained receipt digest does not match gonol" + ) def _validate_retained_receipt(receipt: PublicGonolReceipt) -> None: @@ -591,24 +630,7 @@ def _validate_retained_receipt(receipt: PublicGonolReceipt) -> None: raise PublicGonolConstructionError("retained receipt geometries disagree") if _tuple_tree(receipt.structure) != _tuple_tree(gonol.structure): raise PublicGonolConstructionError("retained receipt structures disagree") - _validate_retained_geometry_tree(gonol) - expected_atomic_id = _digest( - { - "atomic": _atomic_payload( - source_id=gonol.source_id, - occurrence=gonol.occurrence, - relation=gonol.relation, - identity_glyph=gonol.identity_glyph, - carrier_index=gonol.carrier_index, - participants=gonol.participants, - carried_options=gonol.carried_options, - couplings=gonol.couplings, - structure=gonol.structure, - ) - } - ) - if gonol.atomic_id != expected_atomic_id: - raise PublicGonolConstructionError("retained atomic id does not match gonol") + _validate_retained_gonol_tree(gonol) def _seal_public_gonol( @@ -699,6 +721,7 @@ def construct_public_gonol( for item in closed_participants: if not isinstance(item, ClosedPublicGonol): raise PublicGonolConstructionError("participants must already be closed EPAC public gonols") + _validate_retained_gonol_tree(item) options = tuple( ( _require_text(key, field="carried option key"), diff --git a/epac_ucns_provenance.py b/epac_ucns_provenance.py index 498be00..fd8d2b9 100644 --- a/epac_ucns_provenance.py +++ b/epac_ucns_provenance.py @@ -338,6 +338,12 @@ def _source_records(dependencies: Sequence[Callable[..., object]]) -> tuple[Path return root, tuple(records) +def _git_blob_mode(filesystem_mode: int) -> str: + """Collapse platform permission bits to the executable bit Git tracks.""" + + return "100755" if filesystem_mode & 0o111 else "100644" + + @lru_cache(maxsize=32) def _verify_witness( pinned_commit: str, @@ -361,7 +367,7 @@ def _verify_witness( except OSError: return "hmmm" relative_text = str(relative) - mode = f"{int(_mode) & 0o177777:06o}" + mode = _git_blob_mode(int(_mode)) existing = disk_records.get(relative_text) if existing is None: disk_records[relative_text] = ( diff --git a/tests/test_epac_public_gonol.py b/tests/test_epac_public_gonol.py index 0e89acd..fdc314a 100644 --- a/tests/test_epac_public_gonol.py +++ b/tests/test_epac_public_gonol.py @@ -77,7 +77,11 @@ def test_replay_matches(self) -> None: self.assertEqual(first.receipt_digest, second.receipt_digest) contradictory_geometry = dict(first.gonol.geometry) - contradictory_geometry["ucns_commit"] = "hmmm" + contradictory_geometry["ucns_commit"] = ( + "0" * 40 + if contradictory_geometry["ucns_commit"] != "0" * 40 + else "1" * 40 + ) contradictory_gonol = replace( first.gonol, geometry=contradictory_geometry, @@ -115,6 +119,28 @@ def test_replay_matches(self) -> None: PublicGonolConstructionError, "retained geometry digest" ): replay_public_gonol(forged_parent) + with self.assertRaisesRegex( + PublicGonolConstructionError, "retained geometry digest" + ): + construct_public_gonol( + source_id="epac.test:forged-child-parent", + relation="epac.molecular.participation", + participants=(forged_child,), + ) + + forged_identity = replace(first.gonol, source_id="epac.test:forged-H") + forged_identity_parent = replace( + parent, + gonol=replace(parent.gonol, participants=(forged_identity,)), + ) + with self.assertRaisesRegex(PublicGonolConstructionError, "atomic id"): + replay_public_gonol(forged_identity_parent) + with self.assertRaisesRegex(PublicGonolConstructionError, "atomic id"): + construct_public_gonol( + source_id="epac.test:forged-identity-parent", + relation="epac.molecular.participation", + participants=(forged_identity,), + ) def test_charged_couplings_are_the_structure(self) -> None: declared = space( @@ -243,6 +269,30 @@ def test_structure_must_match_declared_couplings(self) -> None: structure=bad_part, ) + malformed_arity = copy.deepcopy(geometry["structure"]) + malformed_arity["parts"][0]["arity"] = None + with self.assertRaisesRegex( + PublicGonolConstructionError, "structure part arity must be an integer" + ): + construct_public_gonol( + source_id="epac.test:null-structure-arity", + relation="epac.affixiation.unpaired-valence", + couplings=geometry["couplings"], + structure=malformed_arity, + ) + + nonmapping_part = copy.deepcopy(geometry["structure"]) + nonmapping_part["parts"] = ("not-a-mapping",) + with self.assertRaisesRegex( + PublicGonolConstructionError, "structure part must be a mapping" + ): + construct_public_gonol( + source_id="epac.test:nonmapping-structure-part", + relation="epac.affixiation.unpaired-valence", + couplings=geometry["couplings"], + structure=nonmapping_part, + ) + mutations = { "degree": (), "participating_dimension_count": 99, diff --git a/tests/test_epac_ucns_provenance.py b/tests/test_epac_ucns_provenance.py index 1821c6d..14a73e5 100644 --- a/tests/test_epac_ucns_provenance.py +++ b/tests/test_epac_ucns_provenance.py @@ -27,6 +27,7 @@ import unittest from epac_ucns_provenance import ( + _git_blob_mode, clear_ucns_verification_cache, ucns_verification_cache_info, verify_loaded_ucns_commit, @@ -39,6 +40,13 @@ class UcnsProvenanceTest(unittest.TestCase): def tearDown(self) -> None: clear_ucns_verification_cache() + def test_filesystem_permissions_normalize_to_git_blob_modes(self) -> None: + self.assertEqual(_git_blob_mode(0o100600), "100644") + self.assertEqual(_git_blob_mode(0o100644), "100644") + self.assertEqual(_git_blob_mode(0o100664), "100644") + self.assertEqual(_git_blob_mode(0o100755), "100755") + self.assertEqual(_git_blob_mode(0o100775), "100755") + def test_loaded_code_mismatch_returns_hmmm(self) -> None: namespace: dict[str, object] = {} exec( From e6ac76e5463e4266cee0a1d429a16a6cffccde91 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 9 Sep 2026 15:07:31 -0700 Subject: [PATCH 17/33] fix: close exact-head provenance review findings --- epac_public_gonol.py | 2 ++ epac_ucns_provenance.py | 7 ++----- subatomic/subatomic-affixiation-baseline.md | 2 +- tests/test_epac_public_gonol.py | 18 ++++++++++++++++++ tests/test_epac_ucns_provenance.py | 3 +++ 5 files changed, 26 insertions(+), 6 deletions(-) diff --git a/epac_public_gonol.py b/epac_public_gonol.py index ea7cfbe..09b58b2 100644 --- a/epac_public_gonol.py +++ b/epac_public_gonol.py @@ -574,6 +574,8 @@ def _validate_retained_gonol_tree(gonol: ClosedPublicGonol) -> None: raise PublicGonolConstructionError( "retained geometry digest does not match geometry" ) + if gonol.structure is not None and not isinstance(gonol.structure, MappingABC): + raise PublicGonolConstructionError("retained structure must be a mapping") _validate_structure_matches_couplings(gonol.couplings, gonol.structure) gonol_payload = _atomic_payload( source_id=gonol.source_id, diff --git a/epac_ucns_provenance.py b/epac_ucns_provenance.py index fd8d2b9..e65d00d 100644 --- a/epac_ucns_provenance.py +++ b/epac_ucns_provenance.py @@ -339,9 +339,9 @@ def _source_records(dependencies: Sequence[Callable[..., object]]) -> tuple[Path def _git_blob_mode(filesystem_mode: int) -> str: - """Collapse platform permission bits to the executable bit Git tracks.""" + """Collapse permissions to Git's owner-executable regular-file modes.""" - return "100755" if filesystem_mode & 0o111 else "100644" + return "100755" if filesystem_mode & 0o100 else "100644" @lru_cache(maxsize=32) @@ -391,7 +391,6 @@ def _verify_witness( check=True, capture_output=True, text=True, - timeout=2, ) if getattr(observed, "stdout", "").strip() != pinned_commit: return "hmmm" @@ -403,7 +402,6 @@ def _verify_witness( check=True, capture_output=True, text=True, - timeout=2, ) fields = getattr(tree_entry, "stdout", "").strip().split(None, 3) if len(fields) != 4 or fields[0] != disk_mode or fields[1] != "blob": @@ -412,7 +410,6 @@ def _verify_witness( ("git", "-C", str(root), "cat-file", "blob", fields[2]), check=True, capture_output=True, - timeout=2, ) if getattr(pinned_blob, "stdout", b"") != path.read_bytes(): return "hmmm" diff --git a/subatomic/subatomic-affixiation-baseline.md b/subatomic/subatomic-affixiation-baseline.md index 896982d..afb832e 100644 --- a/subatomic/subatomic-affixiation-baseline.md +++ b/subatomic/subatomic-affixiation-baseline.md @@ -303,6 +303,6 @@ law, and no scale interchange is introduced. Standing is `implemented-candidate` - Historical evidence at this section's original 2026-08-22 stop: **26/26 subatomic tests pass**; sibling epac suite **29 tests OK**; CONTRACTS↔CHECKS audit **closed** (26 contracts / 26 checks). Current extracted-repo gate records **30 subatomic witnesses** - and **53 repository tests**. + and **54 repository tests**. - The dimensional-arity doctrine is implemented by the sibling `epac_dimensional_arity.py` (committed); no duplicate is maintained here. Status remains `CROSS-DOMAIN-HYPOTHESIS`. diff --git a/tests/test_epac_public_gonol.py b/tests/test_epac_public_gonol.py index fdc314a..f80a935 100644 --- a/tests/test_epac_public_gonol.py +++ b/tests/test_epac_public_gonol.py @@ -128,6 +128,24 @@ def test_replay_matches(self) -> None: participants=(forged_child,), ) + malformed_structure = replace(first.gonol, structure="not-a-mapping") + malformed_parent = replace( + parent, + gonol=replace(parent.gonol, participants=(malformed_structure,)), + ) + with self.assertRaisesRegex( + PublicGonolConstructionError, "retained structure must be a mapping" + ): + replay_public_gonol(malformed_parent) + with self.assertRaisesRegex( + PublicGonolConstructionError, "retained structure must be a mapping" + ): + construct_public_gonol( + source_id="epac.test:malformed-structure-parent", + relation="epac.molecular.participation", + participants=(malformed_structure,), + ) + forged_identity = replace(first.gonol, source_id="epac.test:forged-H") forged_identity_parent = replace( parent, diff --git a/tests/test_epac_ucns_provenance.py b/tests/test_epac_ucns_provenance.py index 14a73e5..b5b94f5 100644 --- a/tests/test_epac_ucns_provenance.py +++ b/tests/test_epac_ucns_provenance.py @@ -43,7 +43,9 @@ def tearDown(self) -> None: def test_filesystem_permissions_normalize_to_git_blob_modes(self) -> None: self.assertEqual(_git_blob_mode(0o100600), "100644") self.assertEqual(_git_blob_mode(0o100644), "100644") + self.assertEqual(_git_blob_mode(0o100655), "100644") self.assertEqual(_git_blob_mode(0o100664), "100644") + self.assertEqual(_git_blob_mode(0o100744), "100755") self.assertEqual(_git_blob_mode(0o100755), "100755") self.assertEqual(_git_blob_mode(0o100775), "100755") @@ -96,6 +98,7 @@ def test_unchanged_witness_runs_git_once(self) -> None: calls: list[tuple[str, ...]] = [] def counting_runner(command, **kwargs): + self.assertNotIn("timeout", kwargs) calls.append(tuple(command)) return subprocess.run(command, **kwargs) From f937e2913b8605f04d903702262e683373dc39d3 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 9 Sep 2026 15:27:49 -0700 Subject: [PATCH 18/33] fix: validate and freeze retained gonol trees --- epac_public_gonol.py | 56 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 13 deletions(-) diff --git a/epac_public_gonol.py b/epac_public_gonol.py index 09b58b2..8d4aae2 100644 --- a/epac_public_gonol.py +++ b/epac_public_gonol.py @@ -559,15 +559,19 @@ def _digest(payload: Mapping[str, Any]) -> str: return sha256(canonical_receipt_bytes(payload)).hexdigest() -def _validate_retained_gonol_tree(gonol: ClosedPublicGonol) -> None: - """Validate every retained participant's geometry and sealed identity.""" +def _validate_retained_gonol_tree(gonol: ClosedPublicGonol) -> ClosedPublicGonol: + """Validate and deeply freeze every retained participant envelope.""" if not isinstance(gonol, ClosedPublicGonol): raise PublicGonolConstructionError( "retained participants must be closed EPAC public gonols" ) - for participant in gonol.participants: + frozen_participants = tuple( _validate_retained_gonol_tree(participant) + for participant in gonol.participants + ) + if not isinstance(gonol.geometry, MappingABC): + raise PublicGonolConstructionError("retained geometry must be a mapping") geometry = _freeze_json(gonol.geometry) expected_geometry_digest = _digest({"geometry": geometry}) if gonol.geometry_digest != expected_geometry_digest: @@ -576,6 +580,20 @@ def _validate_retained_gonol_tree(gonol: ClosedPublicGonol) -> None: ) if gonol.structure is not None and not isinstance(gonol.structure, MappingABC): raise PublicGonolConstructionError("retained structure must be a mapping") + expected_glyph, expected_index = _identity_position(gonol.identity_glyph) + expected_position = ( + None + if expected_glyph is None + else {"index": expected_index, "glyph": expected_glyph} + ) + if ( + gonol.carrier_index != expected_index + or _tuple_tree(geometry.get("identity_position")) + != _tuple_tree(expected_position) + ): + raise PublicGonolConstructionError( + "retained carrier identity does not match geometry" + ) _validate_structure_matches_couplings(gonol.couplings, gonol.structure) gonol_payload = _atomic_payload( source_id=gonol.source_id, @@ -583,7 +601,7 @@ def _validate_retained_gonol_tree(gonol: ClosedPublicGonol) -> None: relation=gonol.relation, identity_glyph=gonol.identity_glyph, carrier_index=gonol.carrier_index, - participants=gonol.participants, + participants=frozen_participants, carried_options=gonol.carried_options, couplings=gonol.couplings, structure=gonol.structure, @@ -604,9 +622,24 @@ def _validate_retained_gonol_tree(gonol: ClosedPublicGonol) -> None: raise PublicGonolConstructionError( "retained receipt digest does not match gonol" ) + return ClosedPublicGonol( + source_id=gonol.source_id, + occurrence=gonol.occurrence, + relation=gonol.relation, + identity_glyph=gonol.identity_glyph, + carrier_index=gonol.carrier_index, + participants=frozen_participants, + carried_options=_freeze_json(gonol.carried_options), + couplings=_freeze_json(gonol.couplings), + structure=_freeze_json(gonol.structure), + geometry=geometry, + atomic_id=gonol.atomic_id, + receipt_digest=gonol.receipt_digest, + geometry_digest=gonol.geometry_digest, + ) -def _validate_retained_receipt(receipt: PublicGonolReceipt) -> None: +def _validate_retained_receipt(receipt: PublicGonolReceipt) -> ClosedPublicGonol: """Reject contradictory or stale duplicate fields before replay.""" if not isinstance(receipt, PublicGonolReceipt) or not isinstance( @@ -632,7 +665,7 @@ def _validate_retained_receipt(receipt: PublicGonolReceipt) -> None: raise PublicGonolConstructionError("retained receipt geometries disagree") if _tuple_tree(receipt.structure) != _tuple_tree(gonol.structure): raise PublicGonolConstructionError("retained receipt structures disagree") - _validate_retained_gonol_tree(gonol) + return _validate_retained_gonol_tree(gonol) def _seal_public_gonol( @@ -719,11 +752,9 @@ def construct_public_gonol( relation = _require_text(relation, field="relation") if isinstance(occurrence, bool) or not isinstance(occurrence, int) or occurrence < 0: raise PublicGonolConstructionError("occurrence must be a non-negative int") - closed_participants = tuple(participants) - for item in closed_participants: - if not isinstance(item, ClosedPublicGonol): - raise PublicGonolConstructionError("participants must already be closed EPAC public gonols") - _validate_retained_gonol_tree(item) + closed_participants = tuple( + _validate_retained_gonol_tree(item) for item in participants + ) options = tuple( ( _require_text(key, field="carried option key"), @@ -759,8 +790,7 @@ def construct_public_gonol( def replay_public_gonol(receipt: PublicGonolReceipt) -> PublicGonolReceipt: """Replay one receipt from its closed gonol. Reproduces construction identity.""" - _validate_retained_receipt(receipt) - gonol = receipt.gonol + gonol = _validate_retained_receipt(receipt) derived_structure = _validate_structure_matches_couplings( gonol.couplings, gonol.structure, From 7a5371d5786552560611db8b4b40d01b61a05fff Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 9 Sep 2026 15:27:51 -0700 Subject: [PATCH 19/33] test: cover retained carrier and mutation boundaries --- tests/test_epac_public_gonol.py | 58 +++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/tests/test_epac_public_gonol.py b/tests/test_epac_public_gonol.py index f80a935..e6f7106 100644 --- a/tests/test_epac_public_gonol.py +++ b/tests/test_epac_public_gonol.py @@ -160,6 +160,64 @@ def test_replay_matches(self) -> None: participants=(forged_identity,), ) + bad_index = first.gonol.carrier_index + 1 + bad_payload = public_gonol_module._atomic_payload( + source_id=first.gonol.source_id, + occurrence=first.gonol.occurrence, + relation=first.gonol.relation, + identity_glyph=first.gonol.identity_glyph, + carrier_index=bad_index, + participants=first.gonol.participants, + carried_options=first.gonol.carried_options, + couplings=first.gonol.couplings, + structure=first.gonol.structure, + ) + bad_atomic_id = public_gonol_module._digest({"atomic": bad_payload}) + bad_receipt_digest = public_gonol_module._digest( + public_gonol_module._receipt_payload( + source_id=first.gonol.source_id, + gonol_payload=bad_payload, + geometry=first.gonol.geometry, + atomic_id=bad_atomic_id, + geometry_digest=first.gonol.geometry_digest, + ) + ) + contradictory_carrier = replace( + first.gonol, + carrier_index=bad_index, + atomic_id=bad_atomic_id, + receipt_digest=bad_receipt_digest, + ) + contradictory_parent = replace( + parent, + gonol=replace(parent.gonol, participants=(contradictory_carrier,)), + ) + with self.assertRaisesRegex( + PublicGonolConstructionError, "carrier identity" + ): + replay_public_gonol(contradictory_parent) + with self.assertRaisesRegex( + PublicGonolConstructionError, "carrier identity" + ): + construct_public_gonol( + source_id="epac.test:contradictory-carrier-parent", + relation="epac.molecular.participation", + participants=(contradictory_carrier,), + ) + + mutable_geometry = public_gonol_module._json_ready(first.gonol.geometry) + mutable_child = replace(first.gonol, geometry=mutable_geometry) + frozen_parent = construct_public_gonol( + source_id="epac.test:mutable-child-parent", + relation="epac.molecular.participation", + participants=(mutable_child,), + ) + mutable_geometry["ucns_commit"] = "post-seal-drift" + retained_geometry = frozen_parent.gonol.participants[0].geometry + self.assertNotEqual(retained_geometry["ucns_commit"], "post-seal-drift") + with self.assertRaises(TypeError): + retained_geometry["ucns_commit"] = "blocked" + def test_charged_couplings_are_the_structure(self) -> None: declared = space( ["z", "x", "y"], From a5524049951b409b2c47596be3f176daa1791d99 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 9 Sep 2026 16:11:16 -0700 Subject: [PATCH 20/33] fix: validate retained gonols against constructor normal form --- epac_public_gonol.py | 191 +++++++++++++++++++++++++++++-------------- 1 file changed, 128 insertions(+), 63 deletions(-) diff --git a/epac_public_gonol.py b/epac_public_gonol.py index 8d4aae2..494810b 100644 --- a/epac_public_gonol.py +++ b/epac_public_gonol.py @@ -31,7 +31,7 @@ # summary: EPAC candidate constructor that closes gonols on the UCNS Public Gonol carrier with oriented couplings and arity charge states; not the EDCM text-domain constructor # owner: The Interdependency # public_surface: CONSTRUCTOR_ID, CONSTRUCTOR_VERSION, PINNED_UCNS_COMMIT, PINNED_PUBLIC_GONOL_SHA256, ClosedPublicGonol, PublicGonolReceipt, PublicGonolConstructionError, construct_public_gonol, replay_public_gonol, canonical_receipt_bytes -# internal_surface: _require_text, _identity_position, _verified_ucns_commit, _geometry, _freeze_json, _json_ready, _tuple_tree, _canonical_coupling_record, _coupling_sort_key, _canonical_structure_tree, _participant_payload, _atomic_payload, _receipt_payload, _digest, _expected_structure_from_couplings, _validate_structure_matches_couplings, _validate_retained_gonol_tree, _validate_retained_receipt +# internal_surface: _require_text, _validate_occurrence, _canonical_carried_options, _identity_position, _verified_ucns_commit, _geometry_record, _geometry, _validate_retained_geometry, _freeze_json, _json_ready, _tuple_tree, _canonical_coupling_record, _coupling_sort_key, _canonical_couplings_and_structure, _canonical_structure_tree, _participant_payload, _atomic_payload, _receipt_payload, _digest, _expected_structure_from_couplings, _validate_structure_matches_couplings, _validate_retained_gonol_tree, _validate_retained_receipt # auth_boundary: EPAC owns particle/energy gonol closure; UCNS owns Public Gonol carrier identity and native Möbius ε; EDCM text-domain constructor is not used; METAPAT affixiation is consumed, not redefined # storage_boundary: none; receipts remain caller-owned in-memory objects # network_boundary: none @@ -60,7 +60,7 @@ # # id: epac_public_gonol_replays_byte_identical # given: a PublicGonolReceipt -# then: replay_public_gonol validates the complete retained envelope and reproduces the same receipt_digest +# then: replay_public_gonol validates constructor-admissible scalars and options, canonical couplings and structure, the complete fixed geometry schema, and every retained identity before reproducing the same receipt_digest # class: correctness # since: 2026-08-22 # @@ -177,6 +177,32 @@ def _require_text(value: str, *, field: str) -> str: return value +def _validate_occurrence(value: int) -> int: + if isinstance(value, bool) or not isinstance(value, int) or value < 0: + raise PublicGonolConstructionError("occurrence must be a non-negative int") + return value + + +def _canonical_carried_options( + carried_options: Sequence[tuple[str, str]], +) -> tuple[tuple[str, str], ...]: + if not isinstance(carried_options, SequenceABC) or isinstance( + carried_options, (str, bytes) + ): + raise PublicGonolConstructionError("carried options must be an ordered sequence") + options: list[tuple[str, str]] = [] + for pair in carried_options: + if not isinstance(pair, SequenceABC) or isinstance(pair, (str, bytes)) or len(pair) != 2: + raise PublicGonolConstructionError("each carried option must be a key/value pair") + options.append( + ( + _require_text(pair[0], field="carried option key"), + _require_text(pair[1], field="carried option value"), + ) + ) + return tuple(options) + + def _identity_position(identity_glyph: str | None) -> tuple[str | None, int | None]: if identity_glyph is None: return (None, None) @@ -200,14 +226,11 @@ def _verified_ucns_commit() -> str: ) -def _geometry(identity_glyph: str | None, carrier_index: int | None) -> dict[str, Any]: - digest = public_gonol_sha256() - if digest != PINNED_PUBLIC_GONOL_SHA256: - raise PublicGonolConstructionError( - "UCNS Public Gonol digest mismatch: " - f"constructor pins {PINNED_PUBLIC_GONOL_SHA256}, computed {digest}" - ) - origin = native_mobius_state(0) +def _geometry_record( + identity_glyph: str | None, + carrier_index: int | None, + ucns_commit: str, +) -> dict[str, Any]: identity: dict[str, Any] | None = None if identity_glyph is not None and carrier_index is not None: identity = {"index": carrier_index, "glyph": identity_glyph} @@ -215,14 +238,40 @@ def _geometry(identity_glyph: str | None, carrier_index: int | None) -> dict[str "state": "bound", "authority": "ucns.public_gonol", "authority_binding": "explicit", - "ucns_commit": _verified_ucns_commit(), - "carrier_digest": digest, + "ucns_commit": ucns_commit, + "carrier_digest": PINNED_PUBLIC_GONOL_SHA256, "identity_position": identity, - "mobius_epsilon_t0": origin.frame.sign, + "mobius_epsilon_t0": MOBIUS_EPSILON_T0, "position_operation": "hmmm", } +def _geometry(identity_glyph: str | None, carrier_index: int | None) -> dict[str, Any]: + digest = public_gonol_sha256() + if digest != PINNED_PUBLIC_GONOL_SHA256: + raise PublicGonolConstructionError( + "UCNS Public Gonol digest mismatch: " + f"constructor pins {PINNED_PUBLIC_GONOL_SHA256}, computed {digest}" + ) + if native_mobius_state(0).frame.sign != MOBIUS_EPSILON_T0: + raise PublicGonolConstructionError("UCNS native Möbius origin is not canonical") + return _geometry_record(identity_glyph, carrier_index, _verified_ucns_commit()) + + +def _validate_retained_geometry( + geometry: Mapping[str, Any], + identity_glyph: str | None, + carrier_index: int | None, +) -> Mapping[str, Any]: + ucns_commit = geometry.get("ucns_commit") + if ucns_commit not in {PINNED_UCNS_COMMIT, "hmmm"}: + raise PublicGonolConstructionError("retained UCNS commit is not pinned or hmmm") + expected = _geometry_record(identity_glyph, carrier_index, ucns_commit) + if _tuple_tree(geometry) != _tuple_tree(expected): + raise PublicGonolConstructionError("retained geometry is not canonical") + return _freeze_json(expected) + + def _freeze_json(value: Any) -> Any: if value is None or isinstance(value, (str, int, float, bool)): return value @@ -476,6 +525,31 @@ def _validate_structure_matches_couplings( return expected_structure +def _canonical_couplings_and_structure( + couplings: Sequence[Mapping[str, Any]], + structure: Mapping[str, Any] | None, +) -> tuple[tuple[Mapping[str, Any], ...], Mapping[str, Any] | None]: + if not isinstance(couplings, SequenceABC) or isinstance(couplings, (str, bytes)): + raise PublicGonolConstructionError("couplings must be an ordered sequence") + if structure is not None and not isinstance(structure, MappingABC): + raise PublicGonolConstructionError("structure must be a mapping") + canonical_couplings = tuple( + sorted( + (_canonical_coupling_record(item) for item in couplings), + key=_coupling_sort_key, + ) + ) + supplied_structure = None if structure is None else _freeze_json(structure) + derived_structure = _validate_structure_matches_couplings( + canonical_couplings, + supplied_structure, + ) + canonical_structure = ( + None if derived_structure is None else _freeze_json(derived_structure) + ) + return canonical_couplings, canonical_structure + + def _participant_payload(item: ClosedPublicGonol) -> dict[str, Any]: return { "source_id": item.source_id, @@ -566,14 +640,18 @@ def _validate_retained_gonol_tree(gonol: ClosedPublicGonol) -> ClosedPublicGonol raise PublicGonolConstructionError( "retained participants must be closed EPAC public gonols" ) + source_id = _require_text(gonol.source_id, field="source_id") + relation = _require_text(gonol.relation, field="relation") + occurrence = _validate_occurrence(gonol.occurrence) + carried_options = _canonical_carried_options(gonol.carried_options) frozen_participants = tuple( _validate_retained_gonol_tree(participant) for participant in gonol.participants ) if not isinstance(gonol.geometry, MappingABC): raise PublicGonolConstructionError("retained geometry must be a mapping") - geometry = _freeze_json(gonol.geometry) - expected_geometry_digest = _digest({"geometry": geometry}) + frozen_geometry = _freeze_json(gonol.geometry) + expected_geometry_digest = _digest({"geometry": frozen_geometry}) if gonol.geometry_digest != expected_geometry_digest: raise PublicGonolConstructionError( "retained geometry digest does not match geometry" @@ -581,37 +659,36 @@ def _validate_retained_gonol_tree(gonol: ClosedPublicGonol) -> ClosedPublicGonol if gonol.structure is not None and not isinstance(gonol.structure, MappingABC): raise PublicGonolConstructionError("retained structure must be a mapping") expected_glyph, expected_index = _identity_position(gonol.identity_glyph) - expected_position = ( - None - if expected_glyph is None - else {"index": expected_index, "glyph": expected_glyph} - ) - if ( - gonol.carrier_index != expected_index - or _tuple_tree(geometry.get("identity_position")) - != _tuple_tree(expected_position) - ): + if gonol.identity_glyph != expected_glyph or gonol.carrier_index != expected_index: raise PublicGonolConstructionError( "retained carrier identity does not match geometry" ) - _validate_structure_matches_couplings(gonol.couplings, gonol.structure) + geometry = _validate_retained_geometry( + frozen_geometry, + expected_glyph, + expected_index, + ) + canonical_couplings, canonical_structure = _canonical_couplings_and_structure( + gonol.couplings, + gonol.structure, + ) gonol_payload = _atomic_payload( - source_id=gonol.source_id, - occurrence=gonol.occurrence, - relation=gonol.relation, - identity_glyph=gonol.identity_glyph, - carrier_index=gonol.carrier_index, + source_id=source_id, + occurrence=occurrence, + relation=relation, + identity_glyph=expected_glyph, + carrier_index=expected_index, participants=frozen_participants, - carried_options=gonol.carried_options, - couplings=gonol.couplings, - structure=gonol.structure, + carried_options=carried_options, + couplings=canonical_couplings, + structure=canonical_structure, ) expected_atomic_id = _digest({"atomic": gonol_payload}) if gonol.atomic_id != expected_atomic_id: raise PublicGonolConstructionError("retained atomic id does not match gonol") expected_receipt_digest = _digest( _receipt_payload( - source_id=gonol.source_id, + source_id=source_id, gonol_payload=gonol_payload, geometry=geometry, atomic_id=expected_atomic_id, @@ -623,19 +700,19 @@ def _validate_retained_gonol_tree(gonol: ClosedPublicGonol) -> ClosedPublicGonol "retained receipt digest does not match gonol" ) return ClosedPublicGonol( - source_id=gonol.source_id, - occurrence=gonol.occurrence, - relation=gonol.relation, - identity_glyph=gonol.identity_glyph, - carrier_index=gonol.carrier_index, + source_id=source_id, + occurrence=occurrence, + relation=relation, + identity_glyph=expected_glyph, + carrier_index=expected_index, participants=frozen_participants, - carried_options=_freeze_json(gonol.carried_options), - couplings=_freeze_json(gonol.couplings), - structure=_freeze_json(gonol.structure), + carried_options=carried_options, + couplings=canonical_couplings, + structure=canonical_structure, geometry=geometry, - atomic_id=gonol.atomic_id, - receipt_digest=gonol.receipt_digest, - geometry_digest=gonol.geometry_digest, + atomic_id=expected_atomic_id, + receipt_digest=expected_receipt_digest, + geometry_digest=expected_geometry_digest, ) @@ -750,27 +827,15 @@ def construct_public_gonol( source_id = _require_text(source_id, field="source_id") relation = _require_text(relation, field="relation") - if isinstance(occurrence, bool) or not isinstance(occurrence, int) or occurrence < 0: - raise PublicGonolConstructionError("occurrence must be a non-negative int") + occurrence = _validate_occurrence(occurrence) closed_participants = tuple( _validate_retained_gonol_tree(item) for item in participants ) - options = tuple( - ( - _require_text(key, field="carried option key"), - _require_text(value, field="carried option value"), - ) - for key, value in carried_options - ) - frozen_couplings = tuple( - sorted( - (_canonical_coupling_record(item) for item in couplings), - key=_coupling_sort_key, - ) + options = _canonical_carried_options(carried_options) + frozen_couplings, frozen_structure = _canonical_couplings_and_structure( + couplings, + structure, ) - supplied_structure = None if structure is None else _freeze_json(structure) - derived_structure = _validate_structure_matches_couplings(frozen_couplings, supplied_structure) - frozen_structure = None if derived_structure is None else _freeze_json(derived_structure) glyph, index = _identity_position(identity_glyph) geometry = _geometry(glyph, index) return _seal_public_gonol( From a799e47bdedf7becff16a646649176afbe1223b1 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 9 Sep 2026 16:11:23 -0700 Subject: [PATCH 21/33] test: reject consistently resealed retained forgeries --- tests/test_epac_public_gonol.py | 145 ++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) diff --git a/tests/test_epac_public_gonol.py b/tests/test_epac_public_gonol.py index e6f7106..6639833 100644 --- a/tests/test_epac_public_gonol.py +++ b/tests/test_epac_public_gonol.py @@ -1,5 +1,15 @@ from __future__ import annotations +# === CHECKS === +# id: check_epac_public_gonol_retained_constructor_boundary +# proves: epac_public_gonol_binds_ucns_carrier_identity, epac_public_gonol_replays_byte_identical, charged_oriented_couplings_are_the_structure +# call: self::check_epac_public_gonol_retained_constructor_boundary +# requires: python3 +# timeout: 30 +# mutates: none +# cleanup: none +# === END CHECKS === + import copy from dataclasses import replace import inspect @@ -25,7 +35,57 @@ from ucns import PUBLIC_GONOL_SHA256, native_mobius_state, public_gonol_function +def _reseal_retained_gonol(gonol, **changes): + candidate = replace(gonol, **changes) + gonol_payload = public_gonol_module._atomic_payload( + source_id=candidate.source_id, + occurrence=candidate.occurrence, + relation=candidate.relation, + identity_glyph=candidate.identity_glyph, + carrier_index=candidate.carrier_index, + participants=candidate.participants, + carried_options=candidate.carried_options, + couplings=candidate.couplings, + structure=candidate.structure, + ) + atomic_id = public_gonol_module._digest({"atomic": gonol_payload}) + geometry_digest = public_gonol_module._digest({"geometry": candidate.geometry}) + receipt_digest = public_gonol_module._digest( + public_gonol_module._receipt_payload( + source_id=candidate.source_id, + gonol_payload=gonol_payload, + geometry=candidate.geometry, + atomic_id=atomic_id, + geometry_digest=geometry_digest, + ) + ) + return replace( + candidate, + atomic_id=atomic_id, + geometry_digest=geometry_digest, + receipt_digest=receipt_digest, + ) + + class EpacPublicGonolTest(unittest.TestCase): + def assert_retained_rejected(self, child, pattern: str) -> None: + with self.assertRaisesRegex(PublicGonolConstructionError, pattern): + construct_public_gonol( + source_id="epac.test:retained-boundary-parent", + relation="epac.molecular.participation", + participants=(child,), + ) + parent = construct_public_gonol( + source_id="epac.test:replay-boundary-parent", + relation="epac.molecular.participation", + ) + forged_parent = replace( + parent, + gonol=replace(parent.gonol, participants=(child,)), + ) + with self.assertRaisesRegex(PublicGonolConstructionError, pattern): + replay_public_gonol(forged_parent) + def test_constructor_is_not_edcm(self) -> None: receipt = construct_public_gonol( source_id="epac.test:O", @@ -218,6 +278,75 @@ def test_replay_matches(self) -> None: with self.assertRaises(TypeError): retained_geometry["ucns_commit"] = "blocked" + def test_retained_geometry_requires_the_complete_constructor_schema(self) -> None: + receipt = construct_public_gonol( + source_id="epac.test:canonical-geometry", + relation="epac.atomic.element", + identity_glyph="O", + ) + mutations = { + "state": "invented", + "authority": "caller.asserted", + "authority_binding": "implicit", + "ucns_commit": "forged-commit", + "carrier_digest": "0" * 64, + "mobius_epsilon_t0": -1, + "position_operation": "caller.asserted", + } + for field, value in mutations.items(): + with self.subTest(field=field): + geometry = public_gonol_module._json_ready(receipt.gonol.geometry) + geometry[field] = value + forged = _reseal_retained_gonol(receipt.gonol, geometry=geometry) + self.assert_retained_rejected(forged, "retained") + + geometry = public_gonol_module._json_ready(receipt.gonol.geometry) + geometry["invented_field"] = True + self.assert_retained_rejected( + _reseal_retained_gonol(receipt.gonol, geometry=geometry), + "retained geometry is not canonical", + ) + + def test_retained_couplings_are_canonical_before_identity_checks(self) -> None: + declared = space( + ["z", "x", "y"], + [["z", "x"], ["z", "y"]], + charges={"z": 8, "x": 1, "y": 1}, + ) + geometry = geometry_from_declared_couplings(declared) + receipt = construct_public_gonol( + source_id="epac.test:canonical-retained-couplings", + relation="epac.affixiation.unpaired-valence", + couplings=geometry["couplings"], + structure=geometry["structure"], + ) + reversed_couplings = tuple(reversed(receipt.gonol.couplings)) + self.assertNotEqual(reversed_couplings, receipt.gonol.couplings) + forged = _reseal_retained_gonol( + receipt.gonol, + couplings=reversed_couplings, + ) + self.assert_retained_rejected(forged, "retained atomic id") + + def test_retained_scalars_reuse_constructor_validation(self) -> None: + receipt = construct_public_gonol( + source_id="epac.test:canonical-scalars", + relation="epac.atomic.element", + carried_options=(("symbol", "O"),), + ) + mutations = ( + ({"source_id": ""}, "source_id"), + ({"relation": " "}, "relation"), + ({"occurrence": -1}, "occurrence"), + ({"occurrence": True}, "occurrence"), + ({"carried_options": (("", "O"),)}, "carried option key"), + ({"carried_options": (("symbol", " "),)}, "carried option value"), + ) + for changes, pattern in mutations: + with self.subTest(changes=changes): + forged = _reseal_retained_gonol(receipt.gonol, **changes) + self.assert_retained_rejected(forged, pattern) + def test_charged_couplings_are_the_structure(self) -> None: declared = space( ["z", "x", "y"], @@ -541,5 +670,21 @@ def test_unknown_glyph_fails_closed(self) -> None: ) +def check_epac_public_gonol_retained_constructor_boundary() -> None: + suite = unittest.TestSuite( + EpacPublicGonolTest(name) + for name in ( + "test_retained_geometry_requires_the_complete_constructor_schema", + "test_retained_couplings_are_canonical_before_identity_checks", + "test_retained_scalars_reuse_constructor_validation", + ) + ) + result = suite.run(unittest.TestResult()) + if not result.wasSuccessful(): + raise AssertionError( + f"retained constructor boundary failed: {result.failures!r} {result.errors!r}" + ) + + if __name__ == "__main__": unittest.main() From d4396472b253ff3c1b4584c87ec23d3e8cfc11a7 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 9 Sep 2026 16:32:36 -0700 Subject: [PATCH 22/33] fix: compare retained geometry with type-sensitive bytes --- epac_public_gonol.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/epac_public_gonol.py b/epac_public_gonol.py index 494810b..3f97fb2 100644 --- a/epac_public_gonol.py +++ b/epac_public_gonol.py @@ -267,7 +267,9 @@ def _validate_retained_geometry( if ucns_commit not in {PINNED_UCNS_COMMIT, "hmmm"}: raise PublicGonolConstructionError("retained UCNS commit is not pinned or hmmm") expected = _geometry_record(identity_glyph, carrier_index, ucns_commit) - if _tuple_tree(geometry) != _tuple_tree(expected): + if canonical_receipt_bytes({"geometry": geometry}) != canonical_receipt_bytes( + {"geometry": expected} + ): raise PublicGonolConstructionError("retained geometry is not canonical") return _freeze_json(expected) @@ -668,6 +670,10 @@ def _validate_retained_gonol_tree(gonol: ClosedPublicGonol) -> ClosedPublicGonol expected_glyph, expected_index, ) + if _digest({"geometry": geometry}) != expected_geometry_digest: + raise PublicGonolConstructionError( + "retained geometry digest does not match canonical geometry" + ) canonical_couplings, canonical_structure = _canonical_couplings_and_structure( gonol.couplings, gonol.structure, From 07595bafbf7ac7d3b1bc692658512cca79f04c64 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 9 Sep 2026 16:32:42 -0700 Subject: [PATCH 23/33] test: reject boolean geometry impostors --- tests/test_epac_public_gonol.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/tests/test_epac_public_gonol.py b/tests/test_epac_public_gonol.py index 6639833..1610705 100644 --- a/tests/test_epac_public_gonol.py +++ b/tests/test_epac_public_gonol.py @@ -284,16 +284,17 @@ def test_retained_geometry_requires_the_complete_constructor_schema(self) -> Non relation="epac.atomic.element", identity_glyph="O", ) - mutations = { - "state": "invented", - "authority": "caller.asserted", - "authority_binding": "implicit", - "ucns_commit": "forged-commit", - "carrier_digest": "0" * 64, - "mobius_epsilon_t0": -1, - "position_operation": "caller.asserted", - } - for field, value in mutations.items(): + mutations = ( + ("state", "invented"), + ("authority", "caller.asserted"), + ("authority_binding", "implicit"), + ("ucns_commit", "forged-commit"), + ("carrier_digest", "0" * 64), + ("mobius_epsilon_t0", -1), + ("mobius_epsilon_t0", True), + ("position_operation", "caller.asserted"), + ) + for field, value in mutations: with self.subTest(field=field): geometry = public_gonol_module._json_ready(receipt.gonol.geometry) geometry[field] = value From bd25bf08c17aac423107ab5f81e05f4d5e6fd299 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 9 Sep 2026 17:06:59 -0700 Subject: [PATCH 24/33] make retained replay equality type-sensitive --- epac_public_gonol.py | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/epac_public_gonol.py b/epac_public_gonol.py index 3f97fb2..df66b22 100644 --- a/epac_public_gonol.py +++ b/epac_public_gonol.py @@ -448,8 +448,10 @@ def _coupling_declaration(item: Mapping[str, Any]) -> tuple[tuple[str, ...], tup or epsilon != MOBIUS_EPSILON_T0 ): raise PublicGonolConstructionError("coupling mobius_epsilon_t0 conflicts with canonical epsilon") - if charge_state is not None and _tuple_tree(charge_state) != _tuple_tree( - (charges, MOBIUS_EPSILON_T0) + if charge_state is not None and canonical_receipt_bytes( + {"charge_state": charge_state} + ) != canonical_receipt_bytes( + {"charge_state": (charges, MOBIUS_EPSILON_T0)} ): raise PublicGonolConstructionError("coupling charge_state conflicts with slot charges") return ids, charges @@ -520,7 +522,11 @@ def _validate_structure_matches_couplings( "structure must match the supplied declared couplings before closure" ) expected_structure = _expected_structure_from_couplings(couplings) - if _canonical_structure_tree(structure) != _canonical_structure_tree(expected_structure): + if canonical_receipt_bytes( + {"structure": _canonical_structure_tree(structure)} + ) != canonical_receipt_bytes( + {"structure": _canonical_structure_tree(expected_structure)} + ): raise PublicGonolConstructionError( "structure derived fields must exactly match the declared couplings before closure" ) @@ -661,7 +667,11 @@ def _validate_retained_gonol_tree(gonol: ClosedPublicGonol) -> ClosedPublicGonol if gonol.structure is not None and not isinstance(gonol.structure, MappingABC): raise PublicGonolConstructionError("retained structure must be a mapping") expected_glyph, expected_index = _identity_position(gonol.identity_glyph) - if gonol.identity_glyph != expected_glyph or gonol.carrier_index != expected_index: + if canonical_receipt_bytes( + {"glyph": gonol.identity_glyph, "index": gonol.carrier_index} + ) != canonical_receipt_bytes( + {"glyph": expected_glyph, "index": expected_index} + ): raise PublicGonolConstructionError( "retained carrier identity does not match geometry" ) @@ -744,9 +754,13 @@ def _validate_retained_receipt(receipt: PublicGonolReceipt) -> ClosedPublicGonol raise PublicGonolConstructionError("receipt envelope is not canonical") outer_geometry = _freeze_json(receipt.geometry) gonol_geometry = _freeze_json(gonol.geometry) - if _tuple_tree(outer_geometry) != _tuple_tree(gonol_geometry): + if canonical_receipt_bytes( + {"geometry": outer_geometry} + ) != canonical_receipt_bytes({"geometry": gonol_geometry}): raise PublicGonolConstructionError("retained receipt geometries disagree") - if _tuple_tree(receipt.structure) != _tuple_tree(gonol.structure): + if canonical_receipt_bytes( + {"structure": receipt.structure} + ) != canonical_receipt_bytes({"structure": gonol.structure}): raise PublicGonolConstructionError("retained receipt structures disagree") return _validate_retained_gonol_tree(gonol) From 2660e9650233667206d98be9f1c8c9c2febeb714 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 9 Sep 2026 17:07:11 -0700 Subject: [PATCH 25/33] bind UCNS provenance to index and effective builtins --- epac_ucns_provenance.py | 47 ++++++++++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/epac_ucns_provenance.py b/epac_ucns_provenance.py index e65d00d..cb1f9aa 100644 --- a/epac_ucns_provenance.py +++ b/epac_ucns_provenance.py @@ -58,7 +58,7 @@ import sys from dataclasses import fields, is_dataclass from enum import Enum -from types import CodeType, FunctionType, ModuleType +from types import BuiltinFunctionType, CodeType, FunctionType, ModuleType from typing import Callable, Sequence @@ -107,7 +107,7 @@ def _packed_ref(common_dir: Path, ref_name: str) -> str | None: return None -def _head_and_index_witness(root: Path) -> tuple[str, int, int] | None: +def _head_and_index_witness(root: Path) -> tuple[str, str] | None: directories = _git_directories(root) if directories is None: return None @@ -132,8 +132,7 @@ def _head_and_index_witness(root: Path) -> tuple[str, int, int] | None: index = git_dir / "index" if not index.exists(): index = common_dir / "index" - stat = index.stat() - return head, stat.st_mtime_ns, stat.st_size + return head, sha256(index.read_bytes()).hexdigest() def _normalized_code(code: CodeType) -> tuple[object, ...]: @@ -173,6 +172,12 @@ def _freeze_loaded_state( return ("literal", type(value).__name__, value) if isinstance(value, float): return ("float", value.hex()) + if isinstance(value, BuiltinFunctionType): + return ( + "builtin-function", + getattr(value, "__module__", ""), + getattr(value, "__qualname__", getattr(value, "__name__", "")), + ) identity = id(value) if identity in seen: return ("ref", seen[identity]) @@ -202,11 +207,19 @@ def _freeze_loaded_state( if module_name != owner_module: return ("external-function", module_name, value.__qualname__) global_state = [] + builtin_state = [] + effective_builtins = value.__builtins__ + if isinstance(effective_builtins, ModuleType): + effective_builtins = vars(effective_builtins) for name in sorted(set(value.__code__.co_names)): if name in value.__globals__: global_state.append( (name, _freeze_loaded_state(value.__globals__[name], owner_module, seen)) ) + elif isinstance(effective_builtins, dict) and name in effective_builtins: + builtin_state.append( + (name, _freeze_loaded_state(effective_builtins[name], owner_module, seen)) + ) closure = tuple( _freeze_loaded_state(cell.cell_contents, owner_module, seen) for cell in (value.__closure__ or ()) @@ -219,6 +232,7 @@ def _freeze_loaded_state( _freeze_loaded_state(value.__kwdefaults__, owner_module, seen), _freeze_loaded_state(value.__annotations__, owner_module, seen), tuple(global_state), + tuple(builtin_state), closure, ) if isinstance(value, type): @@ -349,12 +363,11 @@ def _verify_witness( pinned_commit: str, root_text: str, head: str, - index_mtime_ns: int, - index_size: int, + index_digest: str, records: tuple[tuple[object, ...], ...], runner: Runner, ) -> str: - del index_mtime_ns, index_size # Their presence invalidates the cache key. + del index_digest # Its presence binds cache reuse to the complete index bytes. if head != pinned_commit: return "hmmm" root = Path(root_text) @@ -406,6 +419,21 @@ def _verify_witness( fields = getattr(tree_entry, "stdout", "").strip().split(None, 3) if len(fields) != 4 or fields[0] != disk_mode or fields[1] != "blob": return "hmmm" + index_entry = runner( + ("git", "-C", str(root), "ls-files", "--stage", "--", relative_path), + check=True, + capture_output=True, + text=True, + ) + index_fields = getattr(index_entry, "stdout", "").strip().split(None, 3) + if ( + len(index_fields) != 4 + or index_fields[0] != fields[0] + or index_fields[1] != fields[2] + or index_fields[2] != "0" + or index_fields[3] != relative_path + ): + return "hmmm" pinned_blob = runner( ("git", "-C", str(root), "cat-file", "blob", fields[2]), check=True, @@ -451,13 +479,12 @@ def verify_loaded_ucns_commit( return "hmmm" if git_witness is None: return "hmmm" - head, index_mtime_ns, index_size = git_witness + head, index_digest = git_witness return _verify_witness( pinned_commit, str(root), head, - index_mtime_ns, - index_size, + index_digest, records, runner, ) From f3c9a4489aef41202f622c19f1e6be778a191435 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 9 Sep 2026 17:07:21 -0700 Subject: [PATCH 26/33] test boolean integer replay forgeries --- tests/test_epac_public_gonol.py | 41 +++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/tests/test_epac_public_gonol.py b/tests/test_epac_public_gonol.py index 1610705..695331e 100644 --- a/tests/test_epac_public_gonol.py +++ b/tests/test_epac_public_gonol.py @@ -348,6 +348,46 @@ def test_retained_scalars_reuse_constructor_validation(self) -> None: forged = _reseal_retained_gonol(receipt.gonol, **changes) self.assert_retained_rejected(forged, pattern) + def test_boolean_integer_aliases_are_rejected_at_every_retained_boundary(self) -> None: + carrier = construct_public_gonol( + source_id="epac.test:boolean-carrier", + relation="epac.atomic.element", + identity_glyph=public_gonol_function(1).glyph, + ) + forged_carrier = _reseal_retained_gonol( + carrier.gonol, carrier_index=True + ) + self.assert_retained_rejected(forged_carrier, "carrier identity") + + outer_geometry = public_gonol_module._json_ready(carrier.geometry) + outer_geometry["mobius_epsilon_t0"] = True + with self.assertRaisesRegex(PublicGonolConstructionError, "geometries disagree"): + replay_public_gonol(replace(carrier, geometry=outer_geometry)) + + declared = space( + ["z", "x"], [["z", "x"]], charges={"z": 8, "x": 1} + ) + geometry = geometry_from_declared_couplings(declared) + boolean_structure = copy.deepcopy(geometry["structure"]) + boolean_structure["inferred_cartesian_embedding"] = 0 + with self.assertRaisesRegex(PublicGonolConstructionError, "derived fields"): + construct_public_gonol( + source_id="epac.test:boolean-structure", + relation="epac.affixiation.unpaired-valence", + couplings=geometry["couplings"], + structure=boolean_structure, + ) + + boolean_charge = copy.deepcopy(geometry["couplings"]) + boolean_charge[0]["charge_state"] = ((8, True), True) + with self.assertRaisesRegex(PublicGonolConstructionError, "charge_state"): + construct_public_gonol( + source_id="epac.test:boolean-charge", + relation="epac.affixiation.unpaired-valence", + couplings=boolean_charge, + structure=geometry["structure"], + ) + def test_charged_couplings_are_the_structure(self) -> None: declared = space( ["z", "x", "y"], @@ -678,6 +718,7 @@ def check_epac_public_gonol_retained_constructor_boundary() -> None: "test_retained_geometry_requires_the_complete_constructor_schema", "test_retained_couplings_are_canonical_before_identity_checks", "test_retained_scalars_reuse_constructor_validation", + "test_boolean_integer_aliases_are_rejected_at_every_retained_boundary", ) ) result = suite.run(unittest.TestResult()) From fa63853c710620695389871b4ca7b20387c52241 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 9 Sep 2026 17:07:31 -0700 Subject: [PATCH 27/33] expose provenance checks and adversarial witnesses --- tests/test_epac_ucns_provenance.py | 87 ++++++++++++++++++++++++++++-- 1 file changed, 84 insertions(+), 3 deletions(-) diff --git a/tests/test_epac_ucns_provenance.py b/tests/test_epac_ucns_provenance.py index b5b94f5..d865ae2 100644 --- a/tests/test_epac_ucns_provenance.py +++ b/tests/test_epac_ucns_provenance.py @@ -3,19 +3,19 @@ # === CHECKS === # id: check_epac_ucns_pin_matches_loaded_code # proves: epac_ucns_pin_matches_loaded_code -# call: self::test_loaded_code_mismatch_returns_hmmm +# call: self::check_epac_ucns_pin_matches_loaded_code # mutates: none # cleanup: clears verification cache # # id: check_epac_ucns_verification_reuses_only_identical_witness # proves: epac_ucns_verification_reuses_only_identical_witness -# call: self::test_unchanged_witness_runs_git_once +# call: self::check_epac_ucns_verification_reuses_only_identical_witness # mutates: in-memory verification cache # cleanup: clears verification cache # # id: check_epac_ucns_pin_compares_pinned_blob_bytes # proves: epac_ucns_pin_matches_loaded_code -# call: self::test_pinned_blob_mismatch_returns_hmmm +# call: self::check_epac_ucns_pin_compares_pinned_blob_bytes # mutates: none # cleanup: clears verification cache # === END CHECKS === @@ -23,11 +23,17 @@ from __future__ import annotations import inspect +from hashlib import sha256 +from pathlib import Path import subprocess +import tempfile +from types import FunctionType import unittest from epac_ucns_provenance import ( _git_blob_mode, + _transitive_fingerprint, + _verify_witness, clear_ucns_verification_cache, ucns_verification_cache_info, verify_loaded_ucns_commit, @@ -94,6 +100,25 @@ def test_loaded_code_mismatch_returns_hmmm(self) -> None: self.assertEqual(transitive_observed, "hmmm") + def test_effective_builtins_are_part_of_loaded_state(self) -> None: + forged_globals = dict(public_gonol_function.__globals__) + forged_builtins = dict(public_gonol_function.__builtins__) + forged_builtins["len"] = sum + forged_globals["__builtins__"] = forged_builtins + forged = FunctionType( + public_gonol_function.__code__, + forged_globals, + public_gonol_function.__name__, + public_gonol_function.__defaults__, + public_gonol_function.__closure__, + ) + forged.__kwdefaults__ = public_gonol_function.__kwdefaults__ + forged.__annotations__ = public_gonol_function.__annotations__ + self.assertNotEqual( + _transitive_fingerprint(forged), + _transitive_fingerprint(public_gonol_function), + ) + def test_unchanged_witness_runs_git_once(self) -> None: calls: list[tuple[str, ...]] = [] @@ -135,6 +160,62 @@ def mismatched_blob_runner(command, **kwargs): self.assertEqual(observed, "hmmm") + def test_staged_blob_mismatch_returns_hmmm(self) -> None: + with tempfile.TemporaryDirectory() as directory: + path = Path(directory) / "public_gonol.py" + source = b"def public_gonol_function(value): return value\n" + path.write_bytes(source) + pinned_blob = "a" * 40 + staged_blob = "b" * 40 + calls: list[tuple[str, ...]] = [] + + def staged_runner(command, **_kwargs): + calls.append(tuple(command)) + if "rev-parse" in command: + return subprocess.CompletedProcess(command, 0, stdout=PINNED_UCNS_COMMIT + "\n") + if "ls-tree" in command: + line = f"100644 blob {pinned_blob}\tpublic_gonol.py\n" + return subprocess.CompletedProcess(command, 0, stdout=line) + if "ls-files" in command: + line = f"100644 {staged_blob} 0\tpublic_gonol.py\n" + return subprocess.CompletedProcess(command, 0, stdout=line) + raise AssertionError(command) + + observed = _verify_witness( + PINNED_UCNS_COMMIT, directory, PINNED_UCNS_COMMIT, + sha256(b"index").hexdigest(), + (("public_gonol.py", str(path), "public_gonol_function", + "loaded", sha256(source).hexdigest(), 0o100644),), + staged_runner, + ) + self.assertEqual(observed, "hmmm") + self.assertTrue(any("ls-files" in call for call in calls)) + + +def _run_provenance_cases(*names: str) -> None: + suite = unittest.TestSuite(UcnsProvenanceTest(name) for name in names) + result = suite.run(unittest.TestResult()) + if not result.wasSuccessful(): + raise AssertionError(f"provenance checks failed: {result.failures!r} {result.errors!r}") + + +def check_epac_ucns_pin_matches_loaded_code() -> None: + _run_provenance_cases( + "test_loaded_code_mismatch_returns_hmmm", + "test_effective_builtins_are_part_of_loaded_state", + ) + + +def check_epac_ucns_verification_reuses_only_identical_witness() -> None: + _run_provenance_cases("test_unchanged_witness_runs_git_once") + + +def check_epac_ucns_pin_compares_pinned_blob_bytes() -> None: + _run_provenance_cases( + "test_pinned_blob_mismatch_returns_hmmm", + "test_staged_blob_mismatch_returns_hmmm", + ) + if __name__ == "__main__": unittest.main() From ce8ed85a8d75e96576a7d0e480c806b9d4a7f85a Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 9 Sep 2026 17:07:41 -0700 Subject: [PATCH 28/33] update repository regression count --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8ef4b3f..936fd11 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ The extraction preserves the stack research artifacts and their epistemic status The current extraction gate executes: -- 54 repository regression tests; +- 60 repository regression tests; - 30 subatomic executable witnesses; - the preregistered molecular comparison, requiring all four current standings to remain `FALSIFIED`; - deterministic work-graph digest verification. From 91a287d26897b4515fe42d811a35c03581483791 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 9 Sep 2026 17:35:57 -0700 Subject: [PATCH 29/33] Validate retained UCNS commit type --- epac_public_gonol.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/epac_public_gonol.py b/epac_public_gonol.py index df66b22..adf1eb0 100644 --- a/epac_public_gonol.py +++ b/epac_public_gonol.py @@ -264,7 +264,10 @@ def _validate_retained_geometry( carrier_index: int | None, ) -> Mapping[str, Any]: ucns_commit = geometry.get("ucns_commit") - if ucns_commit not in {PINNED_UCNS_COMMIT, "hmmm"}: + if not isinstance(ucns_commit, str) or ucns_commit not in { + PINNED_UCNS_COMMIT, + "hmmm", + }: raise PublicGonolConstructionError("retained UCNS commit is not pinned or hmmm") expected = _geometry_record(identity_glyph, carrier_index, ucns_commit) if canonical_receipt_bytes({"geometry": geometry}) != canonical_receipt_bytes( From 2bf4c226a687bf4b7e887afac45fb726a7e767df Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 9 Sep 2026 17:35:59 -0700 Subject: [PATCH 30/33] Bind provenance witness to effective Git index --- epac_ucns_provenance.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/epac_ucns_provenance.py b/epac_ucns_provenance.py index cb1f9aa..e2d9cf3 100644 --- a/epac_ucns_provenance.py +++ b/epac_ucns_provenance.py @@ -52,6 +52,7 @@ from hashlib import sha256 import inspect import marshal +import os from pathlib import Path import re import subprocess @@ -129,9 +130,16 @@ def _head_and_index_witness(root: Path) -> tuple[str, str] | None: return None else: return None - index = git_dir / "index" - if not index.exists(): - index = common_dir / "index" + configured_index = os.environ.get("GIT_INDEX_FILE") + if configured_index: + index = Path(configured_index) + if not index.is_absolute(): + index = root / index + index = index.resolve() + else: + index = git_dir / "index" + if not index.exists(): + index = common_dir / "index" return head, sha256(index.read_bytes()).hexdigest() From 09316b0f61e9fed919e95cee19a26a06f5e26e11 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 9 Sep 2026 17:36:00 -0700 Subject: [PATCH 31/33] Test malformed retained UCNS commit --- tests/test_epac_public_gonol.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_epac_public_gonol.py b/tests/test_epac_public_gonol.py index 695331e..d44a5a4 100644 --- a/tests/test_epac_public_gonol.py +++ b/tests/test_epac_public_gonol.py @@ -289,6 +289,7 @@ def test_retained_geometry_requires_the_complete_constructor_schema(self) -> Non ("authority", "caller.asserted"), ("authority_binding", "implicit"), ("ucns_commit", "forged-commit"), + ("ucns_commit", {"forged": "commit"}), ("carrier_digest", "0" * 64), ("mobius_epsilon_t0", -1), ("mobius_epsilon_t0", True), From 1a205613750a576471b149fab89e7b89449d1a2b Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 9 Sep 2026 17:36:02 -0700 Subject: [PATCH 32/33] Test alternate index and declare check mutations --- tests/test_epac_ucns_provenance.py | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/tests/test_epac_ucns_provenance.py b/tests/test_epac_ucns_provenance.py index d865ae2..536de89 100644 --- a/tests/test_epac_ucns_provenance.py +++ b/tests/test_epac_ucns_provenance.py @@ -4,8 +4,8 @@ # id: check_epac_ucns_pin_matches_loaded_code # proves: epac_ucns_pin_matches_loaded_code # call: self::check_epac_ucns_pin_matches_loaded_code -# mutates: none -# cleanup: clears verification cache +# mutates: ucns.public_gonol module global public_gonol_position; in-memory verification cache +# cleanup: restores public_gonol_position; clears verification cache # # id: check_epac_ucns_verification_reuses_only_identical_witness # proves: epac_ucns_verification_reuses_only_identical_witness @@ -16,7 +16,7 @@ # id: check_epac_ucns_pin_compares_pinned_blob_bytes # proves: epac_ucns_pin_matches_loaded_code # call: self::check_epac_ucns_pin_compares_pinned_blob_bytes -# mutates: none +# mutates: in-memory verification cache # cleanup: clears verification cache # === END CHECKS === @@ -24,14 +24,17 @@ import inspect from hashlib import sha256 +import os from pathlib import Path import subprocess import tempfile from types import FunctionType import unittest +from unittest.mock import patch from epac_ucns_provenance import ( _git_blob_mode, + _head_and_index_witness, _transitive_fingerprint, _verify_witness, clear_ucns_verification_cache, @@ -162,6 +165,20 @@ def mismatched_blob_runner(command, **kwargs): def test_staged_blob_mismatch_returns_hmmm(self) -> None: with tempfile.TemporaryDirectory() as directory: + git_dir = Path(directory) / ".git" + git_dir.mkdir() + (git_dir / "HEAD").write_text(PINNED_UCNS_COMMIT, encoding="utf-8") + (git_dir / "index").write_bytes(b"default-index") + alternate_index = Path(directory) / "alternate-index" + alternate_index.write_bytes(b"alternate-index-v1") + with patch.dict(os.environ, {"GIT_INDEX_FILE": "alternate-index"}): + first_witness = _head_and_index_witness(Path(directory)) + alternate_index.write_bytes(b"alternate-index-v2") + second_witness = _head_and_index_witness(Path(directory)) + self.assertIsNotNone(first_witness) + self.assertIsNotNone(second_witness) + self.assertNotEqual(first_witness[1], second_witness[1]) + path = Path(directory) / "public_gonol.py" source = b"def public_gonol_function(value): return value\n" path.write_bytes(source) From e535c507194402b742f49207264efed30454c1f8 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Wed, 9 Sep 2026 17:36:04 -0700 Subject: [PATCH 33/33] Correct repository test count --- subatomic/subatomic-affixiation-baseline.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subatomic/subatomic-affixiation-baseline.md b/subatomic/subatomic-affixiation-baseline.md index afb832e..7a9b3f8 100644 --- a/subatomic/subatomic-affixiation-baseline.md +++ b/subatomic/subatomic-affixiation-baseline.md @@ -303,6 +303,6 @@ law, and no scale interchange is introduced. Standing is `implemented-candidate` - Historical evidence at this section's original 2026-08-22 stop: **26/26 subatomic tests pass**; sibling epac suite **29 tests OK**; CONTRACTS↔CHECKS audit **closed** (26 contracts / 26 checks). Current extracted-repo gate records **30 subatomic witnesses** - and **54 repository tests**. + and **60 repository tests**. - The dimensional-arity doctrine is implemented by the sibling `epac_dimensional_arity.py` (committed); no duplicate is maintained here. Status remains `CROSS-DOMAIN-HYPOTHESIS`.