Spaces:
Running
Running
File size: 6,316 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 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | """Reciprocity ledger — the AYNI-OS reciprocity organism.
A real, append-only, double-entry give/take ledger over the empire's 14 organs.
Every resource movement is recorded as a KIPU receipt. Reciprocity (Ayni) is the
*pairing* of a take with one or more future gives that return >= the consumed amount
to the drained organ within a finite time-lag tau_max (Trivers 1971 "time-lagged
symbiosis"; Axelrod & Hamilton 1981 direct reciprocity).
This module is pure stdlib (open-source: Python only). No mysticism.
"""
from __future__ import annotations
import hashlib
import json
import time as _time
from dataclasses import asdict, dataclass
from typing import Optional
# Doctrine v11: 14 organs.
ORGANS = (
"amaru", "sentra", "rosie", "vessels", "killinchu", "kanchay", "wayra",
"puriq", "yuyay", "hukla", "khipu", "lambda_spine", "yawar", "tinkuy",
)
assert len(ORGANS) == 14, "Doctrine v11 LOCKED: 14 organs"
def _now() -> float:
return _time.time()
@dataclass(frozen=True)
class Receipt:
"""A single KIPU ledger entry (event). Append-only, content-addressed.
side: 'take' (organ consumes resource r, amount>0 leaving the organ)
'give' (organ receives resource r, amount>0 entering the organ)
pair_id: links a take to the give(s) that reciprocate it (Ayni pairing).
prev_hash / entry_hash: KIPU receipt chain (tamper-evident).
"""
seq: int
ts: float
organ: str
side: str # 'take' | 'give'
resource: str
amount: float
pair_id: str
prev_hash: str
entry_hash: str = ""
def signed_payload(self) -> str:
d = {k: v for k, v in asdict(self).items() if k != "entry_hash"}
return json.dumps(d, sort_keys=True, separators=(",", ":"))
def compute_hash(self) -> str:
return hashlib.sha256(self.signed_payload().encode()).hexdigest()
class ReciprocityLedger:
"""Append-only double-entry reciprocity ledger (event store)."""
def __init__(self) -> None:
self._entries: list[Receipt] = []
# ---- write path -----------------------------------------------------
def _append(self, organ: str, side: str, resource: str, amount: float,
pair_id: str, ts: Optional[float] = None) -> Receipt:
if organ not in ORGANS:
raise ValueError(f"unknown organ {organ!r}")
if side not in ("take", "give"):
raise ValueError("side must be 'take' or 'give'")
if amount < 0:
raise ValueError("amount must be >= 0")
seq = len(self._entries)
prev_hash = self._entries[-1].entry_hash if self._entries else "GENESIS"
r = Receipt(
seq=seq, ts=ts if ts is not None else _now(), organ=organ,
side=side, resource=resource, amount=amount, pair_id=pair_id,
prev_hash=prev_hash,
)
r = Receipt(**{**asdict(r), "entry_hash": r.compute_hash()})
self._entries.append(r)
return r
def record_exchange(self, *, taker: str, giver: str, resource: str,
amount: float, pair_id: str,
ts: Optional[float] = None) -> tuple[Receipt, Receipt]:
"""Record a balanced internal exchange as a DOUBLE-ENTRY pair:
`giver` gives `amount` of `resource` to `taker` (taker's take is the
consumption; giver's give is the reciprocation source). Internal exchanges
net to zero across the empire (Ayni conservation, double-entry).
Returns (take_receipt, give_receipt).
"""
base = ts if ts is not None else _now()
take = self._append(taker, "take", resource, amount, pair_id, ts=base)
give = self._append(giver, "give", resource, amount, pair_id, ts=base)
return take, give
def reciprocate(self, *, organ: str, resource: str, amount: float,
pair_id: str, ts: Optional[float] = None) -> Receipt:
"""Record a future give that returns resource to a previously-drained organ.
This is the Ayni 'pay-back' leg closing a pair_id (>= original take)."""
return self._append(organ, "give", resource, amount, pair_id, ts=ts)
def drain(self, *, organ: str, resource: str, amount: float,
pair_id: str, ts: Optional[float] = None) -> Receipt:
"""Record an unmatched take (a net drain on `organ`)."""
return self._append(organ, "take", resource, amount, pair_id, ts=ts)
# ---- read path ------------------------------------------------------
def entries(self, until_ts: Optional[float] = None) -> list[Receipt]:
if until_ts is None:
return list(self._entries)
return [e for e in self._entries if e.ts <= until_ts]
def verify_chain(self, until_ts: Optional[float] = None) -> bool:
"""Verify KIPU receipt chain integrity up to until_ts."""
prev = "GENESIS"
for e in self.entries(until_ts):
if e.prev_hash != prev:
return False
if e.compute_hash() != e.entry_hash:
return False
prev = e.entry_hash
return True
def flows(self, organ: str, lo: float = float("-inf"),
hi: float = float("inf")) -> tuple[float, float]:
"""Return (In_o, Out_o) over [lo, hi] for `organ`."""
gin = sum(e.amount for e in self._entries
if e.organ == organ and e.side == "give" and lo <= e.ts <= hi)
out = sum(e.amount for e in self._entries
if e.organ == organ and e.side == "take" and lo <= e.ts <= hi)
return gin, out
def ayni_coefficient(self, organ: str, lo: float = float("-inf"),
hi: float = float("inf")) -> float:
"""alpha_o = In / (In + Out); 0.5 when idle (both zero)."""
gin, out = self.flows(organ, lo, hi)
if gin + out == 0:
return 0.5
return gin / (gin + out)
def to_jsonl(self) -> str:
return "\n".join(json.dumps(asdict(e), sort_keys=True) for e in self._entries)
@classmethod
def from_jsonl(cls, text: str) -> "ReciprocityLedger":
led = cls()
for line in text.splitlines():
if not line.strip():
continue
d = json.loads(line)
led._entries.append(Receipt(**d))
return led
|