diff --git a/AGENTS.md b/AGENTS.md index 26b2f2fe..223bacd0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,7 +1,10 @@ # UCNS agent instructions -- Treat UCNS as a geometry repository. +- Treat UCNS as a geometry and mathematical-representation repository whose cross-domain role is geometric scale/representation transport, never semantic transfer. - Read `CANON.md` before changing domain behavior. +- Placement test: if work constructs geometric carriers, motion, attachment, recursion, or transport across a declared scale/representation boundary, it may belong in UCNS. +- If work defines what the transported structure means in a domain, keep that meaning with the domain consumer or METAPAT authority. +- If work measures whether a claimed transformation preserves an observable, keep that measurement in EDCM; UCNS supplies only the represented geometry and its own mathematical evidence. - Keep only code, tests, documents, and evidence that directly construct, represent, certify, falsify, or replay geometry/topology. - Do not introduce lexical, NLP, dictionary, morphology, definition, semantic-graph, EDCM-measurement, PTCNA-state, generic evaluator/laboratory, or cross-stack adapter machinery into UCNS. - Every Public Gonol glyph is a function position. Do not create letter/punctuation/digit/symbol subclasses as UCNS architecture. diff --git a/CANON.md b/CANON.md index f173571d..f6ce829f 100644 --- a/CANON.md +++ b/CANON.md @@ -10,8 +10,50 @@ UCNS assigns elements of an unknowable to completion through geometric motion. Assignment, ordered motion, orientation, nesting, recursive scale, and scoped completion are load-bearing. Text labels, lexical definitions, corpora, hashes, evaluator frameworks, and external semantic graphs are not substitutes for geometry. +## Scale-transformation jurisdiction + +UCNS is the geometric and mathematical-representation substrate for constructing how structure changes across declared scale or representation boundaries. Its cross-domain role is structural, not semantic: a consumer may supply domain meaning and domain evidence, while UCNS owns only the geometry of the representation, motion, attachment, recursion, and transport it actually constructs. + +A claimed UCNS scale transformation must declare enough geometry to identify both sides of the transition and the operation between them. At minimum, the construction must make explicit: + +- the source and target geometric boundaries or carriers; +- the geometric operation that relates them; +- the attachment, origin, or provenance needed to establish continuity of the construction; +- which geometric distinctions are retained, changed, or discarded by the operation; and +- the standing of the relation: candidate, selected within a declared scope, ratified, or `hmmm`. + +Identity across scale is not inferred from similar coordinates, labels, hashes, or downstream meaning. Composition is likewise not assumed: when two scale transitions are claimed to compose, the composed geometric law must itself be constructed or tested. + +METAPAT remains the semantic authority for cross-domain terms and transfer constraints. EDCM owns measurement and evaluation. EPAC, consciousness constructions, language constructions, and other consumers retain their own domain semantics and evidence standards. Their recurrence may test UCNS structure; it does not move their semantics into UCNS. + +The present repository contains candidate pieces of this formalism, including exact carrier state, native Möbius return, radius/layer recursion, continuum-to-finite gonal trace, lattice address structure, an exact multiplicative scale-action candidate, displacement, lift selection, and motion. Their existence does not establish one complete scale-transformation law. + +## Multiplicative scale-action candidate + +UCNS has an executable domain-agnostic candidate action on an ordered positive exact-rational coordinate carrier: + +```text +T_q(x)_i = q^w_i x_i +``` + +where `q > 0` is an exact rational factor and each `w_i` is an integer. For one fixed ordered weight vector, the candidate constructs exact composition, identity, and inverse: + +```text +T_p o T_q = T_(p*q) +T_1 = identity +T_q^-1 = T_(1/q) +``` + +For a monomial `I_a(x) = product(x_i^a_i)`, the candidate's structural scale weight is `sum(a_i*w_i)`; the monomial is invariant under the action when that weight is zero. + +This establishes an exact algebraic candidate component, not the complete UCNS scale-transition law. UCNS assigns no domain meaning to the coordinate positions or weights. A consumer may bind physical, chemical, linguistic, consciousness, or other meanings externally under its own authority and evidence. + +`hmmm`: how this diagonal action binds to native Möbius origin/attachment, recursive carrier transitions, and the full higher-dimensional construction remains unresolved. + + ## Public Gonol carrier + The exact 157-position Public Gonol arrangement is retained as geometry. Every admitted glyph is a Public Gonol function position. No active UCNS rule divides these positions into letters, punctuation, symbols, digits, lexical glyphs, or other linguistic classes. The exact operation of a function position must be supplied by a geometric construction. It may be identity-like ("carry on") where geometry supports that behavior. Unicode names and dictionary definitions do not define Public Gonol function semantics. @@ -168,4 +210,4 @@ Those experiments remain recoverable from Git history but carry no current UCNS A construction may close only relative to its declared geometric boundary. No executable convenience is promoted to the complete UCNS merely because it produces coordinates, hashes, scores, or labels. -`hmmm`: ratification of the modular-orbit / continuum-boundary-trace candidates; the full circle → epicycle → disk → sphere → recursive-scale transition law; exact direct coupling across distant scales; the visible-circle trace → native Möbius complete-state lift; any law selecting one continuum lift from a finite modular congruence class; and the geometric operation of Public Gonol function positions not yet constructed. +`hmmm`: ratification of the modular-orbit / continuum-boundary-trace candidates; one explicit composition law binding the present candidate pieces into a complete UCNS scale-transformation formalism; the full circle → epicycle → disk → sphere → recursive-scale transition law; exact direct coupling across distant scales; the visible-circle trace → native Möbius complete-state lift; any law selecting one continuum lift from a finite modular congruence class; and the geometric operation of Public Gonol function positions not yet constructed. diff --git a/CLAUDE.md b/CLAUDE.md index 86632471..3e8247d5 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,4 +4,6 @@ Read `AGENTS.md`, then `CANON.md`. This repository is geometry-only. Active implementation work is limited to geometric/topological construction and the exact evidence required to reproduce or falsify it. +Its cross-domain purpose is geometric scale/representation transport: UCNS may construct how structure is carried across declared boundaries, while consumer semantics stay with the consumer, METAPAT governs semantic transfer, and EDCM owns measurement/evaluation. + Do not restore semantic, lexical, corpus, EDCM-measurement, PTCNA, generic evaluator, or cross-stack machinery from Git history into the active tree. diff --git a/README.md b/README.md index a7ac28b5..c3c446b3 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ UCNS — Geometry Repository

-UCNS is a geometry repository. +UCNS is a geometry repository and domain-independent mathematical-representation substrate for constructing transformations across declared scale or representation boundaries. Its active scope is limited to constructions that directly represent or test geometry: @@ -14,13 +14,44 @@ Its active scope is limited to constructions that directly represent or test geo - Möbius vesica and Seed-of-Life constructions and certificates; - candidate exact finite modular-action orbit and circle geometry; - candidate exact visible-circle continuum wave / gonal boundary traces; +- candidate exact multiplicative scale actions and monomial-invariant kernels; - prime-indexed ribbon, link, interval, Milnor, Alexander, and related topological geometry; - numerical machinery used to certify those constructions. Everything semantic is outside this repository's active domain: lexical corpora, definitions, morphology, NLP parsing, function-name semantics, EDCM measurement profiles, PTCNA state, evaluator laboratories, and cross-stack adapters. +## Scale-transformation jurisdiction + +UCNS supplies geometry for asking what survives, changes, or disappears when a construction is represented across a declared scale or representation boundary. A consumer supplies domain meaning; METAPAT constrains cross-domain semantic transfer; EDCM measures claimed observables. UCNS does not absorb those roles. + +The current repository already contains pieces of this architecture: carrier and origin state, native Möbius transport and return, candidate radius/layer recursion, continuum-to-finite gonal traces, discrete lattice addresses, displacement and lift candidates, and candidate motion. These are evidence-bearing components, not yet one complete scale-transformation law. + +Use this placement test before adding a cross-domain feature: + +```text +geometric representation / transport across scale -> UCNS +domain meaning and domain evidence -> consuming domain +cross-domain semantic authority -> METAPAT +measurement / evaluation of claimed observables -> EDCM +``` + +See `docs/scale-transformation-jurisdiction.md` for the contract, current primitive audit, usage guidance, and unresolved boundary. + +### Multiplicative scale-action candidate + +`src/ucns/scale_action.py` implements one exact candidate component: + +```text +T_q(x)_i = q^w_i x_i +``` + +for positive exact rational `q`, positive exact rational coordinates, and an ordered integer weight vector `w`. Actions with the same weights compose as `T_p o T_q = T_(p*q)`; reciprocal factors invert. A monomial `product(x_i^a_i)` is structurally invariant exactly when `sum(a_i*w_i) = 0`. + +The core carries no domain axis names. Physics, chemistry, language, consciousness, or other domain bindings belong in consumer repositories under exact provenance; those consumers may bind ordered coordinate names and claims without transferring them into UCNS. + The poster above is a display certificate of those constructions. It is not an interpretation layer. + ## Public Gonol The Public Gonol is the exact ordered 157-position carrier in `src/ucns/public_gonol.py`. Every glyph is a Public Gonol function position. UCNS does not divide glyphs into letters, punctuation, digits, or symbols for construction. @@ -156,7 +187,6 @@ raise SystemExit(run_suite(["tests", "-c", "pyproject.toml", "--noconftest", "-- PY .venv/bin/python -m build .venv/bin/python -m twine check dist/* -.venv/bin/python tools/verify_distributions.py . dist ``` The independent interval checks also require system MPFR (for example, diff --git a/docs/scale-transformation-jurisdiction.md b/docs/scale-transformation-jurisdiction.md new file mode 100644 index 00000000..462c4d09 --- /dev/null +++ b/docs/scale-transformation-jurisdiction.md @@ -0,0 +1,112 @@ +# UCNS scale-transformation jurisdiction + +Standing: **canonical repository jurisdiction; incomplete formalism**. + +UCNS is the geometric and mathematical-representation substrate for constructing how structure changes across declared scale or representation boundaries. This document makes that repository role explicit without promoting any unresolved candidate geometry. + +The distinction is load-bearing: + +```text +METAPAT cross-domain semantic authority and transfer constraints +UCNS geometric representation and scale/representation transport +EDCM measurement, projection, and evaluation of claimed observables +consumer domain meaning, evidence, and interpretation +``` + +A repeated structure across EPAC, consciousness, language, physics, or another domain can motivate and falsify UCNS geometry. Recurrence does not transfer the source domain's vocabulary, mechanism, conservation law, or evidence standard into UCNS. + +## Minimal geometric contract + +A UCNS scale/representation transformation is admissible only when the construction declares enough geometry to distinguish a real transition from two unrelated records. + +For a source construction (X_a), target construction (X_b), and candidate geometric operation (R_{a\to b}), require: + +1. **source boundary** — the exact source carrier or geometric boundary; +2. **target boundary** — the exact target carrier or geometric boundary; +3. **operation** — the constructed geometric action relating source to target; +4. **continuity evidence** — attachment, origin, provenance, or another geometric witness sufficient to justify that the target is a transformation of the source; +5. **distinction accounting** — which geometric distinctions remain recoverable, which change, and which are discarded; +6. **composition status** — if (R_{b\to c}\circ R_{a\to b}) is claimed, construct or test that composition rather than assuming it; +7. **standing** — candidate, selected within an explicitly declared scope, ratified, or `hmmm`. + +Coordinate similarity, equal hashes, matching labels, or a shared downstream interpretation do not establish geometric identity across scale. + +No universal completed `ScaleTransform` law is introduced here. `src/ucns/scale_action.py` implements one narrower exact candidate component: a diagonal multiplicative action `T_q(x)_i = q^w_i x_i` with exact composition, inversion, and monomial-invariant detection. It does not bind the existing Möbius, origin/attachment, recursive carrier, or higher-dimensional transition machinery into one universal transform. + +## Current primitive audit + +| UCNS surface | Present contribution | Standing relative to scale transformation | +|---|---|---| +| Public Gonol carrier | exact ordered 157-position geometric carrier | carrier floor; not itself a scale law | +| native Möbius state | exact framed transport; 360° visible / 720° complete return | established geometric return primitive | +| modular orbit geometry | exact finite action and cycle decomposition | candidate representation component | +| gonal boundary trace | exact continuum-covering to finite gonal action relation | candidate cross-representation component | +| radius recursion | radius from breadth plus deck-translation layer recursion | direct candidate scale-recursion component | +| lattice carrier | discrete deck/modular address structure | candidate address substrate | +| visible/lifted displacement | candidate transport on the carrier | candidate transform component; scope-bounded selection where recorded | +| lift selection | explicit alternatives and selection gate for finite-to-lifted witnesses | candidate selection machinery | +| multiplicative scale action | exact `T_q(x)_i = q^w_i x_i`, multiplicative composition, inverse, and monomial-invariant kernel | executable domain-agnostic candidate component | +| motion | ordered accumulation of selected-scoped displacement with radius/layer state | candidate composed transport | +| circle → epicycle → disk → sphere → recursive scale | not yet constructed as one law | `hmmm` | + +This audit means UCNS already contains much of the machinery the scale-transform purpose requires. It does **not** mean the components presently compose into one complete formalism. + +## Cross-domain consumption + +A consumer should bind its own states to UCNS geometry without moving its semantics into UCNS. + +For EPAC, an electron, atom, boundary, ligand, or molecule remains an EPAC object. UCNS may represent a declared geometric relation between levels. EDCM may then test whether a distinction survives, collapses, or becomes measurable under that representation. + +For consciousness work, stimulus, somatic response, integrated state, learned association, or persistent model remain consciousness-domain terms. UCNS may represent declared coupling geometry or scale transport only when that geometry is independently specified. + +Renormalization-group flow is therefore a useful external test case, not UCNS doctrine. If UCNS can express an RG scale flow without importing field-theory semantics, that is evidence for the abstraction. RG vocabulary does not become UCNS primitive vocabulary merely because the structures correspond. + +Physics bindings, including the conditional six-axis confinement fixture formerly drafted here, belong in a consumer repository such as Stack. UCNS may supply the exact ordered integer weight vector and multiplicative action; the names `(epsilon, mu, c, hbar, m, L)`, the Compton/confinement algebra, varying-constants hypotheses, and all empirical or physical claims stay outside UCNS under exact provenance and non-transfer boundaries. + +## Usage guidance + +When adding a proposed scale transformation: + +1. Name the two geometric boundaries, not merely two domain labels. +2. Construct the operation using existing UCNS primitives where possible. +3. Identify the continuity witness that makes the target a transformation of the source. +4. State exactly what information the operation preserves, transforms, or forgets. +5. If the operation composes with another UCNS transition, test the composition explicitly. +6. Keep domain interpretation outside UCNS. +7. Bind every executable candidate to its source-owned `CONTRACTS`, test-owned `CHECKS`, replay path, falsifiers, and standing. +8. Leave unresolved geometry as `hmmm`; do not fill the gap with a generic abstraction. + +### Placement examples + +- “EPAC valence means outer-shell occupancy” — EPAC, not UCNS. +- “These two EPAC states map to the same declared UCNS boundary state under operation (R)” — UCNS geometry plus EPAC binding. +- “The mapping loses a behaviorally relevant ligand distinction” — EDCM measurement/evaluation against an EPAC observable. +- “Two consciousness time windows share this geometric coupling transform” — UCNS only after the coupling geometry and boundaries are independently declared. +- “All such transformations are energy flows” — not licensed by structural recurrence; METAPAT/domain restraint applies. +- “A six-axis physical hypothesis gives names to the ordered coordinates of `T_q`” — consumer/Stack physics fixture, not UCNS. + +## Acceptance target + +The missing architectural result is not another label. It is an explicit, replayable composition law that binds the existing carrier, origin/attachment, recursion, lift, and motion primitives into a scale-transition construction while preserving each component's current standing. + +A future complete contract should be able to answer, for an exact transformation: + +```text +what is the source geometry? +what is the target geometry? +what operation connects them? +what establishes continuity? +what survives? +what changes? +what is forgotten? +does composition hold where claimed? +what is the evidence/status? +``` + +Until then, UCNS has a declared jurisdiction and candidate machinery, not a completed universal scale-transform theorem. + +## hmmm + +The complete circle → epicycle → disk → sphere → recursive-scale transition law; exact composition across distant scales; the unified attachment/origin law needed to follow one construction across those boundaries; and the relation between current candidate components remain unresolved. + +The map now has a legend. The bridge still has to carry weight. diff --git a/src/ucns/__init__.py b/src/ucns/__init__.py index 0d4f47c2..1d5079f4 100644 --- a/src/ucns/__init__.py +++ b/src/ucns/__init__.py @@ -2,19 +2,19 @@ # id: ucns_geometry_public_surface # module_name: __init__ # module_kind: facade -# summary: geometry-only UCNS public surface including the visible-circle displacement candidate +# summary: geometry-only UCNS public surface including exact scale/representation candidates # owner: Erin Spencer -# public_surface: carrier geometry, framed Mobius root loop, exact Public Gonol carrier, Mobius vesica and seed geometry, exact modular orbit geometry, exact visible-circle gonal wave boundary trace, exact visible-circle displacement candidate +# public_surface: carrier geometry, framed Mobius root loop, exact Public Gonol carrier, Mobius vesica and seed geometry, modular orbit geometry, visible-circle gonal wave boundary trace, displacement/lift/motion candidates, exact multiplicative scale-action candidate # internal_surface: none # auth_boundary: none # storage_boundary: none # network_boundary: none # user_data_boundary: none # admin_only: false -# tests: tests.test_public_gonol, tests.test_geometry_public_surface, tests.test_carrier, tests.test_modular_orbit, tests.test_gonal_boundary_trace, tests.test_visible_displacement +# tests: tests.test_public_gonol, tests.test_geometry_public_surface, tests.test_carrier, tests.test_modular_orbit, tests.test_gonal_boundary_trace, tests.test_visible_displacement, tests.test_scale_action # rollout: active geometry-only package facade # rollback: restore prior facade from Git history -# requires: directed_carrier_floor, ucns_native_mobius_geometry, ucns_public_gonol_geometry, ucns_mobius_vesica_candidate, ucns_mobius_seed_of_life_candidate, ucns_modular_orbit_geometry, ucns_gonal_boundary_trace, ucns_visible_displacement_candidate +# requires: directed_carrier_floor, ucns_native_mobius_geometry, ucns_public_gonol_geometry, ucns_mobius_vesica_candidate, ucns_mobius_seed_of_life_candidate, ucns_modular_orbit_geometry, ucns_gonal_boundary_trace, ucns_visible_displacement_candidate, ucns_multiplicative_scale_action_candidate # since: 2026-08-20 # unresolved: canonical completion of the full UCNS geometric construction # === END MODULE_BUILD === @@ -97,6 +97,12 @@ # then: the lift-selection builders, error, and controls runner are public with candidate standing # class: correctness # since: 2026-09-21 +# +# id: geometry_public_surface_includes_scale_action_candidate +# given: the active ucns package facade is imported +# then: the exact domain-agnostic multiplicative scale action, application receipt, invariant helper, builders, and replay are public with candidate standing +# class: correctness +# since: 2026-09-23 # === END CONTRACTS === """UCNS geometry. @@ -248,6 +254,17 @@ MotionFalsificationError, run_motion_falsification, ) +from .scale_action import ( + SCHEMA as SCALE_ACTION_SCHEMA, + VERSION as SCALE_ACTION_VERSION, + MultiplicativeScaleAction, + ScaleActionError, + ScaleActionRecord, + build_scale_action, + build_scale_action_record, + monomial_value, + replay_scale_action_record, +) from .mobius_vesica import __all__ as _mobius_vesica_all from .mobius_vesica import * # noqa: F401,F403 - geometric public module from .mobius_seed import __all__ as _mobius_seed_all @@ -302,6 +319,11 @@ "RADIUS_RECURSION_VERSION", "RadiusRecursionError", "RadiusRecursionRecord", + "SCALE_ACTION_SCHEMA", + "SCALE_ACTION_VERSION", + "ScaleActionError", + "ScaleActionRecord", + "MultiplicativeScaleAction", "STRUCTURAL_NULL", "STRUCTURAL_NULL_ORIGIN", "StructuralNullIdentity", @@ -322,6 +344,8 @@ "build_placement_frame", "build_provenance_interval_lift", "build_radius_recursion", + "build_scale_action", + "build_scale_action_record", "build_visible_displacement", "carrier_from_breadth", "deck_translate", @@ -337,6 +361,7 @@ "MotionFalsificationError", "MotionRecord", "MotionStepRecord", + "monomial_value", "native_mobius_state", "project", "public_gonol_function", @@ -351,6 +376,7 @@ "replay_motion", "replay_placement_frame", "replay_radius_recursion", + "replay_scale_action_record", "replay_visible_displacement", "run_displacement_selection", "run_falsification", diff --git a/src/ucns/scale_action.py b/src/ucns/scale_action.py new file mode 100644 index 00000000..c34c482e --- /dev/null +++ b/src/ucns/scale_action.py @@ -0,0 +1,431 @@ +# === MODULE_BUILD === +# id: ucns_multiplicative_scale_action_candidate +# module_name: scale_action +# module_kind: experiment +# summary: exact domain-agnostic multiplicative scale action with composition, inversion, monomial-invariant detection, and replayable application receipts +# owner: Erin Spencer +# public_surface: SCHEMA, VERSION, ScaleActionError, MultiplicativeScaleAction, ScaleActionRecord, build_scale_action, build_scale_action_record, monomial_value, replay_scale_action_record +# internal_surface: exact positive-rational coercion, integer exponentiation, canonical receipt serialization +# auth_boundary: none +# storage_boundary: immutable records only +# network_boundary: none +# user_data_boundary: none +# admin_only: false +# tests: tests.test_scale_action +# rollout: executable candidate behind explicit caller construction; not selected or ratified as the complete UCNS scale law +# rollback: remove this module, facade exports, tests, and scale-action documentation +# requires: none +# since: 2026-09-23 +# unresolved: binding to native Mobius origin/attachment, recursive carrier boundaries, and the complete higher-scale composition law +# === END MODULE_BUILD === +# +# === CONTRACTS === +# id: scale_action_applies_integer_weights_exactly +# given: a positive exact rational factor q, an ordered integer weight vector w, and positive exact rational state x +# then: coordinate i transforms exactly as x_i -> q^w_i * x_i with no floating-point arithmetic +# class: correctness +# since: 2026-09-23 +# +# id: scale_action_composes_multiplicatively +# given: two actions with the same ordered weight vector and factors p and q +# then: sequential application equals one action with factor p*q; factor 1 is identity and reciprocal factor is inverse +# class: correctness +# since: 2026-09-23 +# +# id: scale_action_monomial_invariants_are_weight_kernel +# given: a monomial exponent vector a on the same ordered coordinates +# then: the monomial is structurally invariant exactly when sum(a_i*w_i) = 0, and invariant values are preserved exactly by application +# class: correctness +# since: 2026-09-23 +# +# id: scale_action_core_is_domain_agnostic +# given: a scale action or application receipt +# then: the UCNS core stores only ordered integer weights, exact scale factors, exact coordinates, standing, and provenance receipt data; domain names and interpretations are external +# class: doctrine +# since: 2026-09-23 +# +# id: scale_action_receipts_replay_exactly +# given: a canonical application receipt +# then: replay reconstructs the same action and target byte-identically while malformed or tampered receipts fail closed +# class: safety +# since: 2026-09-23 +# === END CONTRACTS === + +"""Exact multiplicative scale-action candidate. + +For an ordered positive coordinate state ``x`` and integer weight vector ``w``, +this module implements the diagonal action + + T_q(x)_i = q**w_i * x_i + +for positive exact rational ``q``. Actions with the same weights compose as + + T_p o T_q = T_(p*q), + +with identity ``q = 1`` and inverse ``q -> 1/q``. + +For a monomial ``I_a(x) = product(x_i**a_i)``, the structural scale weight is + + sum(a_i * w_i). + +The monomial is invariant under every factor in this one-parameter action +exactly when that weight is zero. + +This is a domain-agnostic mathematical representation candidate. UCNS does not +assign physical, chemical, linguistic, consciousness, or other semantics to the +coordinates or weights. Consumers own those bindings. The candidate also does +not claim to be the complete UCNS scale-transition law: attachment/origin, +recursive carrier transitions, and composition with the native Mobius geometry +remain separate unresolved work. +""" + +from __future__ import annotations + +from dataclasses import dataclass +from fractions import Fraction +from hashlib import sha256 +import json +from typing import Iterable + +SCHEMA = "ucns.multiplicative-scale-action-candidate" +VERSION = "0.1.0" +_STANDING = "candidate" + + +class ScaleActionError(ValueError): + """Raised when an exact multiplicative scale action fails closed.""" + + +def _coerce_weights(weights: Iterable[int]) -> tuple[int, ...]: + try: + resolved = tuple(weights) + except TypeError as exc: + raise ScaleActionError("weights must be an iterable of integers") from exc + if not resolved: + raise ScaleActionError("weights must be nonempty") + if any(isinstance(value, bool) or not isinstance(value, int) for value in resolved): + raise ScaleActionError("weights must contain nonboolean integers only") + return resolved + + +def _coerce_positive_fraction(name: str, value: int | Fraction) -> Fraction: + if isinstance(value, bool) or not isinstance(value, (int, Fraction)): + raise ScaleActionError(f"{name} must be an exact integer or Fraction") + resolved = Fraction(value) + if resolved <= 0: + raise ScaleActionError(f"{name} must be positive") + return resolved + + +def _coerce_state( + state: Iterable[int | Fraction], + arity: int, +) -> tuple[Fraction, ...]: + try: + raw = tuple(state) + except TypeError as exc: + raise ScaleActionError("state must be an iterable of exact coordinates") from exc + if len(raw) != arity: + raise ScaleActionError("state arity must equal the action weight arity") + return tuple( + _coerce_positive_fraction(f"state[{index}]", value) + for index, value in enumerate(raw) + ) + + +def _coerce_powers(powers: Iterable[int], arity: int) -> tuple[int, ...]: + try: + resolved = tuple(powers) + except TypeError as exc: + raise ScaleActionError("powers must be an iterable of integers") from exc + if len(resolved) != arity: + raise ScaleActionError("monomial power arity must equal the action weight arity") + if any(isinstance(value, bool) or not isinstance(value, int) for value in resolved): + raise ScaleActionError("monomial powers must contain nonboolean integers only") + return resolved + + +def _fraction_power(value: Fraction, exponent: int) -> Fraction: + if exponent >= 0: + return value ** exponent + return Fraction(1, 1) / (value ** (-exponent)) + + +def _fraction_text(value: Fraction) -> str: + return str(value.numerator) if value.denominator == 1 else f"{value.numerator}/{value.denominator}" + + +def _fraction_from_text(name: str, value: object) -> Fraction: + if not isinstance(value, str): + raise ScaleActionError(f"{name} must be a canonical fraction string") + try: + resolved = Fraction(value) + except (ValueError, ZeroDivisionError) as exc: + raise ScaleActionError(f"{name} is not a valid fraction") from exc + if _fraction_text(resolved) != value: + raise ScaleActionError(f"{name} is not in canonical fraction form") + if resolved <= 0: + raise ScaleActionError(f"{name} must be positive") + return resolved + + +def monomial_value( + state: Iterable[int | Fraction], + powers: Iterable[int], +) -> Fraction: + """Evaluate one exact monomial on positive exact rational coordinates.""" + + raw_state = tuple(state) + raw_powers = tuple(powers) + resolved_state = _coerce_state(raw_state, len(raw_state)) + resolved_powers = _coerce_powers(raw_powers, len(resolved_state)) + value = Fraction(1, 1) + for coordinate, exponent in zip(resolved_state, resolved_powers, strict=True): + value *= _fraction_power(coordinate, exponent) + return value + + +@dataclass(frozen=True, slots=True) +class MultiplicativeScaleAction: + """One exact diagonal multiplicative action on an ordered scale carrier.""" + + weights: tuple[int, ...] + factor: Fraction + + def __post_init__(self) -> None: + if not isinstance(self.weights, tuple): + raise ScaleActionError("canonical weights must be an immutable tuple") + _coerce_weights(self.weights) + if not isinstance(self.factor, Fraction): + raise ScaleActionError("canonical factor must be a Fraction") + _coerce_positive_fraction("factor", self.factor) + + @property + def arity(self) -> int: + return len(self.weights) + + def apply( + self, + state: Iterable[int | Fraction], + ) -> tuple[Fraction, ...]: + """Apply ``x_i -> factor**weight_i * x_i`` exactly.""" + + resolved = _coerce_state(state, self.arity) + return tuple( + coordinate * _fraction_power(self.factor, weight) + for coordinate, weight in zip(resolved, self.weights, strict=True) + ) + + def compose(self, other: "MultiplicativeScaleAction") -> "MultiplicativeScaleAction": + """Return the action equivalent to applying this action then ``other``.""" + + if not isinstance(other, MultiplicativeScaleAction): + raise ScaleActionError("composition requires another scale action") + if self.weights != other.weights: + raise ScaleActionError("scale actions compose only when ordered weights match") + return MultiplicativeScaleAction( + weights=self.weights, + factor=self.factor * other.factor, + ) + + def inverse(self) -> "MultiplicativeScaleAction": + """Return the exact reciprocal-factor inverse action.""" + + return MultiplicativeScaleAction( + weights=self.weights, + factor=Fraction(1, 1) / self.factor, + ) + + def monomial_weight(self, powers: Iterable[int]) -> int: + """Return the scale weight ``sum(a_i*w_i)`` of one monomial.""" + + resolved = _coerce_powers(powers, self.arity) + return sum( + exponent * weight + for exponent, weight in zip(resolved, self.weights, strict=True) + ) + + def is_invariant(self, powers: Iterable[int]) -> bool: + """Return whether the monomial exponent vector lies in the weight kernel.""" + + return self.monomial_weight(powers) == 0 + + def preserves_monomial( + self, + state: Iterable[int | Fraction], + powers: Iterable[int], + ) -> bool: + """Verify exact preservation for a structurally invariant monomial.""" + + resolved_state = _coerce_state(state, self.arity) + resolved_powers = _coerce_powers(powers, self.arity) + if self.monomial_weight(resolved_powers) != 0: + return False + return monomial_value(resolved_state, resolved_powers) == monomial_value( + self.apply(resolved_state), + resolved_powers, + ) + + def as_dict(self) -> dict[str, object]: + return { + "weights": list(self.weights), + "factor": _fraction_text(self.factor), + } + + +def build_scale_action( + weights: Iterable[int], + factor: int | Fraction, +) -> MultiplicativeScaleAction: + """Build the canonical exact action from caller-supplied ordered weights.""" + + return MultiplicativeScaleAction( + weights=_coerce_weights(weights), + factor=_coerce_positive_fraction("factor", factor), + ) + + +def _record_payload( + action: MultiplicativeScaleAction, + source: tuple[Fraction, ...], + target: tuple[Fraction, ...], +) -> dict[str, object]: + return { + "schema": SCHEMA, + "version": VERSION, + "standing": _STANDING, + "action": action.as_dict(), + "source": [_fraction_text(value) for value in source], + "target": [_fraction_text(value) for value in target], + } + + +@dataclass(frozen=True, slots=True) +class ScaleActionRecord: + """Replayable exact witness of one scale-action application.""" + + action: MultiplicativeScaleAction + source: tuple[Fraction, ...] + target: tuple[Fraction, ...] + receipt_sha256: str + + def __post_init__(self) -> None: + if not isinstance(self.action, MultiplicativeScaleAction): + raise ScaleActionError("record action must be a validated scale action") + if not isinstance(self.source, tuple) or not isinstance(self.target, tuple): + raise ScaleActionError("record source and target must be immutable tuples") + resolved_source = _coerce_state(self.source, self.action.arity) + resolved_target = _coerce_state(self.target, self.action.arity) + if resolved_source != self.source or resolved_target != self.target: + raise ScaleActionError("record coordinates must be canonical Fractions") + if self.action.apply(self.source) != self.target: + raise ScaleActionError("record target does not equal exact action on source") + expected = sha256( + json.dumps( + _record_payload(self.action, self.source, self.target), + sort_keys=True, + separators=(",", ":"), + ).encode("utf-8") + ).hexdigest() + if self.receipt_sha256 != expected: + raise ScaleActionError("record receipt digest does not match its exact payload") + + def as_dict(self) -> dict[str, object]: + payload = _record_payload(self.action, self.source, self.target) + payload["receipt_sha256"] = self.receipt_sha256 + return payload + + def receipt_bytes(self) -> bytes: + return json.dumps( + self.as_dict(), + sort_keys=True, + separators=(",", ":"), + ).encode("utf-8") + + +def build_scale_action_record( + weights: Iterable[int], + factor: int | Fraction, + source: Iterable[int | Fraction], +) -> ScaleActionRecord: + """Apply one exact action and bind the result into a replayable receipt.""" + + action = build_scale_action(weights, factor) + resolved_source = _coerce_state(source, action.arity) + target = action.apply(resolved_source) + payload = _record_payload(action, resolved_source, target) + receipt = sha256( + json.dumps(payload, sort_keys=True, separators=(",", ":")).encode("utf-8") + ).hexdigest() + return ScaleActionRecord( + action=action, + source=resolved_source, + target=target, + receipt_sha256=receipt, + ) + + +def replay_scale_action_record(data: bytes) -> ScaleActionRecord: + """Reconstruct an application receipt and require byte-identical replay.""" + + if not isinstance(data, bytes): + raise ScaleActionError("receipt must be bytes") + try: + obj = json.loads(data.decode("utf-8")) + except (UnicodeDecodeError, json.JSONDecodeError) as exc: + raise ScaleActionError("receipt is not valid canonical JSON") from exc + if not isinstance(obj, dict): + raise ScaleActionError("receipt root must be an object") + expected_keys = { + "schema", + "version", + "standing", + "action", + "source", + "target", + "receipt_sha256", + } + if set(obj) != expected_keys: + raise ScaleActionError("receipt fields do not match the scale-action schema") + if obj["schema"] != SCHEMA or obj["version"] != VERSION or obj["standing"] != _STANDING: + raise ScaleActionError("receipt schema, version, or standing mismatch") + action_obj = obj["action"] + if not isinstance(action_obj, dict) or set(action_obj) != {"weights", "factor"}: + raise ScaleActionError("receipt action is malformed") + weights = action_obj["weights"] + if not isinstance(weights, list): + raise ScaleActionError("receipt weights must be a list") + factor = _fraction_from_text("action.factor", action_obj["factor"]) + source_obj = obj["source"] + target_obj = obj["target"] + if not isinstance(source_obj, list) or not isinstance(target_obj, list): + raise ScaleActionError("receipt source and target must be lists") + source = tuple( + _fraction_from_text(f"source[{index}]", value) + for index, value in enumerate(source_obj) + ) + target = tuple( + _fraction_from_text(f"target[{index}]", value) + for index, value in enumerate(target_obj) + ) + rebuilt = build_scale_action_record(weights, factor, source) + if rebuilt.target != target: + raise ScaleActionError("receipt target does not match replayed target") + if rebuilt.receipt_sha256 != obj["receipt_sha256"]: + raise ScaleActionError("receipt digest does not match replayed application") + if rebuilt.receipt_bytes() != data: + raise ScaleActionError("receipt does not replay byte-identically") + return rebuilt + + +__all__ = [ + "SCHEMA", + "VERSION", + "ScaleActionError", + "MultiplicativeScaleAction", + "ScaleActionRecord", + "build_scale_action", + "build_scale_action_record", + "monomial_value", + "replay_scale_action_record", +] diff --git a/tests/test_scale_action.py b/tests/test_scale_action.py new file mode 100644 index 00000000..db4925c3 --- /dev/null +++ b/tests/test_scale_action.py @@ -0,0 +1,165 @@ +# === CHECKS === +# id: check_scale_action_applies_integer_weights_exactly +# proves: scale_action_applies_integer_weights_exactly +# call: self::test_scale_action_applies_integer_weights_exactly +# requires: python3 +# timeout: 10 +# mutates: none +# cleanup: none +# +# id: check_scale_action_composes_multiplicatively +# proves: scale_action_composes_multiplicatively +# call: self::test_scale_action_composes_multiplicatively +# requires: python3 +# timeout: 10 +# mutates: none +# cleanup: none +# +# id: check_scale_action_monomial_invariants_are_weight_kernel +# proves: scale_action_monomial_invariants_are_weight_kernel +# call: self::test_scale_action_monomial_invariants_are_weight_kernel +# requires: python3 +# timeout: 10 +# mutates: none +# cleanup: none +# +# id: check_scale_action_core_is_domain_agnostic +# proves: scale_action_core_is_domain_agnostic +# call: self::test_scale_action_core_is_domain_agnostic +# requires: python3 +# timeout: 10 +# mutates: none +# cleanup: none +# +# id: check_scale_action_receipts_replay_exactly +# proves: scale_action_receipts_replay_exactly +# call: self::test_scale_action_receipts_replay_exactly +# requires: python3 +# timeout: 10 +# mutates: none +# cleanup: none +# +# id: check_geometry_public_surface_includes_scale_action_candidate +# proves: geometry_public_surface_includes_scale_action_candidate +# call: self::test_facade_exports_scale_action +# requires: python3 +# timeout: 10 +# mutates: none +# cleanup: none +# === END CHECKS === + +from __future__ import annotations + +from fractions import Fraction +import json + +import pytest + +from ucns import ( + SCALE_ACTION_SCHEMA, + MultiplicativeScaleAction, + ScaleActionError, + build_scale_action, + build_scale_action_record, + monomial_value, + replay_scale_action_record, +) + + +def test_scale_action_applies_integer_weights_exactly() -> None: + action = build_scale_action((1, 0, -1, 2), Fraction(3, 2)) + source = (Fraction(2), Fraction(3), Fraction(5), Fraction(7)) + assert action.apply(source) == ( + Fraction(3), + Fraction(3), + Fraction(10, 3), + Fraction(63, 4), + ) + assert action.arity == 4 + + +def test_scale_action_composes_multiplicatively() -> None: + weights = (1, -1, 2) + source = (Fraction(2), Fraction(3), Fraction(5)) + q = build_scale_action(weights, Fraction(3, 2)) + p = build_scale_action(weights, Fraction(5, 3)) + + composed = q.compose(p) + assert composed.factor == Fraction(5, 2) + assert p.apply(q.apply(source)) == composed.apply(source) + + identity = build_scale_action(weights, 1) + assert identity.apply(source) == source + assert q.inverse().apply(q.apply(source)) == source + + with pytest.raises(ScaleActionError): + q.compose(build_scale_action((1, -1, 1), 2)) + + +def test_scale_action_monomial_invariants_are_weight_kernel() -> None: + # External fixtures may bind meanings to these six ordered axes. + # UCNS sees only the exact weight vector. + action = build_scale_action((1, 1, -1, 1, 2, 0), Fraction(7, 5)) + state = tuple(Fraction(value) for value in (2, 3, 5, 7, 11, 13)) + + invariant_powers = ( + (-1, 1, 0, 0, 0, 0), + (0, 0, 1, 1, 0, 0), + (0, 0, 2, 0, 1, 0), + (0, 0, -1, 1, -1, 0), + (0, 0, 1, -1, 1, 1), + ) + for powers in invariant_powers: + assert action.monomial_weight(powers) == 0 + assert action.is_invariant(powers) + assert action.preserves_monomial(state, powers) + assert monomial_value(state, powers) == monomial_value(action.apply(state), powers) + + noninvariant = (1, 1, 0, 0, 0, 0) + assert action.monomial_weight(noninvariant) == 2 + assert not action.is_invariant(noninvariant) + assert not action.preserves_monomial(state, noninvariant) + + +def test_scale_action_core_is_domain_agnostic() -> None: + record = build_scale_action_record( + (1, 1, -1, 1, 2, 0), + Fraction(3, 2), + (2, 3, 5, 7, 11, 13), + ) + payload = record.as_dict() + assert set(payload["action"]) == {"weights", "factor"} + serialized = json.dumps(payload, sort_keys=True) + for forbidden in ("epsilon", "permittivity", "permeability", "mass", "hbar", "charge", "consciousness"): + assert forbidden not in serialized.lower() + + +def test_scale_action_receipts_replay_exactly() -> None: + record = build_scale_action_record( + (1, -1, 2), + Fraction(5, 3), + (2, 3, 7), + ) + assert replay_scale_action_record(record.receipt_bytes()) == record + + obj = json.loads(record.receipt_bytes()) + obj["target"][0] = "999" + tampered = json.dumps(obj, sort_keys=True, separators=(",", ":")).encode("utf-8") + with pytest.raises(ScaleActionError): + replay_scale_action_record(tampered) + + with pytest.raises(ScaleActionError): + build_scale_action((), 1) + with pytest.raises(ScaleActionError): + build_scale_action((1,), 0) + with pytest.raises(ScaleActionError): + MultiplicativeScaleAction((1,), 1) # canonical constructor requires Fraction + + +def test_facade_exports_scale_action() -> None: + import ucns + + assert ucns.SCALE_ACTION_SCHEMA == SCALE_ACTION_SCHEMA + assert hasattr(ucns, "build_scale_action") + assert hasattr(ucns, "build_scale_action_record") + assert hasattr(ucns, "replay_scale_action_record")