File size: 3,529 Bytes
a6a5d8e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
"""Per-organ Ayni coefficient monitor; fires HUKLLA T24 if any organ drains.

alpha_o = In_o / (In_o + Out_o)  in [0,1];  0.5 = balanced (In==Out).
alpha_o < ALPHA_MIN (0.45) over the monitored window => organ is net-drained =>
HUKLLA tripwire T24 fires (additive; T01-T10 unchanged).

Also computes the yuyay_v4 14-vector hash and PROVES non-disturbance of yuyay_v3:
dropping axis 14 reproduces the LOCKED v3 replay hash byte-for-byte.

HONEST: a normalized reciprocity ratio + a threshold alarm. No mysticism.
"""
from __future__ import annotations

import hashlib
import json
from dataclasses import dataclass

from .ledger import ORGANS, ReciprocityLedger

ALPHA_BALANCED = 0.5
ALPHA_MIN = 0.45
HUKLLA_T24 = "T24"
YUYAY_V3_REPLAY_HASH = (
    "bacf54434f1a3bf2d758b27a62d5fd580ca4c8d3b180693573eeebcaea631fc5"
)


@dataclass
class T24Event:
    organ: str
    alpha: float
    threshold: float
    tripwire: str
    window: tuple


@dataclass
class ReciprocityReport:
    alphas: dict                  # organ -> alpha_o
    deficits: list                # list[T24Event]
    halt: bool                    # True if any organ drained (T24 fired)


def scan(ledger: ReciprocityLedger, lo: float = float("-inf"),
         hi: float = float("inf")) -> ReciprocityReport:
    alphas = {}
    deficits = []
    for o in ORGANS:
        a = ledger.ayni_coefficient(o, lo, hi)
        alphas[o] = round(a, 6)
        if a < ALPHA_MIN:
            deficits.append(T24Event(
                organ=o, alpha=round(a, 6), threshold=ALPHA_MIN,
                tripwire=HUKLLA_T24, window=(lo, hi),
            ))
    return ReciprocityReport(alphas=alphas, deficits=deficits, halt=bool(deficits))


class ReciprocityViolation(Exception):
    """Raised when an organ is net-drained: HUKLLA T24 halt."""


def enforce(ledger: ReciprocityLedger, lo: float = float("-inf"),
            hi: float = float("inf")) -> ReciprocityReport:
    """Scan and HALT (raise) if any organ is in deficit. Used by the runtime guard."""
    report = scan(ledger, lo, hi)
    if report.halt:
        worst = min(report.deficits, key=lambda d: d.alpha)
        raise ReciprocityViolation(
            f"HUKLLA {HUKLLA_T24}: organ {worst.organ!r} drained "
            f"(alpha={worst.alpha} < {ALPHA_MIN})"
        )
    return report


# ---- yuyay_v4 axis-14 hashing (proves v3 non-disturbance) -----------------
def yuyay_v4_vector(v3_axes: list, ledger: ReciprocityLedger,
                    organ: str) -> list:
    """Append axis 14 (alpha_o) to the 13-axis v3 vector -> 14-vector."""
    if len(v3_axes) != 13:
        raise ValueError("v3 vector must have exactly 13 axes (Doctrine v11)")
    return list(v3_axes) + [round(ledger.ayni_coefficient(organ), 6)]


def _canon_hash(vector: list, receipts: list) -> str:
    blob = json.dumps({"v": vector, "r": receipts}, sort_keys=True,
                      separators=(",", ":")).encode()
    return hashlib.sha256(blob).hexdigest()


def yuyay_v4_hash(v4_vector: list, v4_receipts: list) -> str:
    """Separate v4 hash over the 14-vector + v4 receipts."""
    if len(v4_vector) != 14:
        raise ValueError("v4 vector must have 14 axes")
    return _canon_hash(v4_vector, v4_receipts)


def yuyay_v3_hash(v3_vector: list, v3_receipts: list) -> str:
    """Recompute the v3 hash from the first 13 axes only (must equal LOCKED hash
    for the canonical v3 input)."""
    if len(v3_vector) != 13:
        raise ValueError("v3 vector must have 13 axes")
    return _canon_hash(v3_vector, v3_receipts)