jev-quilt 0.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- jev-quilt-0.0.1/PKG-INFO +9 -0
- jev-quilt-0.0.1/README.md +63 -0
- jev-quilt-0.0.1/jev_quilt/__init__.py +17 -0
- jev-quilt-0.0.1/jev_quilt/backends.py +88 -0
- jev-quilt-0.0.1/jev_quilt/bookkeeper.py +64 -0
- jev-quilt-0.0.1/jev_quilt/cell.py +55 -0
- jev-quilt-0.0.1/jev_quilt/experiments.py +129 -0
- jev-quilt-0.0.1/jev_quilt/q16.py +80 -0
- jev-quilt-0.0.1/jev_quilt/typesafe_client.py +70 -0
- jev-quilt-0.0.1/jev_quilt.egg-info/PKG-INFO +9 -0
- jev-quilt-0.0.1/jev_quilt.egg-info/SOURCES.txt +14 -0
- jev-quilt-0.0.1/jev_quilt.egg-info/dependency_links.txt +1 -0
- jev-quilt-0.0.1/jev_quilt.egg-info/top_level.txt +1 -0
- jev-quilt-0.0.1/pyproject.toml +10 -0
- jev-quilt-0.0.1/setup.cfg +4 -0
- jev-quilt-0.0.1/setup.py +13 -0
jev-quilt-0.0.1/PKG-INFO
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: jev-quilt
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: JEV for quilt as understood output: cellular-first decision substrate
|
|
5
|
+
License: MIT
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
|
|
9
|
+
JEV (Joint Embedding Validator) as understood output for the Quilt project. Pins the fleet canary: fnv1a-64("café Δ 日本語") = 0x024a555471370b18d. Includes backends, bookkeeper, cell, q16, and typesafe_client.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# jev-quilt
|
|
2
|
+
|
|
3
|
+
**JEV for quilt as understood output.** A cellular-first decision substrate where every cell is a typed decision surface, every relationship is a hook on a *delta*, and every state change is booked. Cells decide with Jev-class System One models (TypeSafe API or openjev-compatible local servers) or with exact q16 rational rules — never with a float where identity matters.
|
|
4
|
+
|
|
5
|
+
> Sibling of the quilt polyformalism (quilt-studio, twist-engine, tidepool). Cousin of TypeSafe's Jev and the openJEV ecosystem (SemIf, openjev, jevlike, NanoJev). This repo is the **fleet's own angle**: the cell as the unit, the quilt kernel as the spine, the bookkeeper as the memory.
|
|
6
|
+
|
|
7
|
+
## The one-sentence idea
|
|
8
|
+
|
|
9
|
+
A spreadsheet cell can hold `0.73` — but *as what*? In jev-quilt the type says: a **probability weight** in a Choice distribution, a **similarity score** against a vector probe, a **tone coefficient**, a **deadband gate**, or an **exact rational**. The value is the same shape; the semantics are declared at the cell. Plugins for Excel/Sheets/LibreOffice make that real for *spreadsheets of any program*; the same kernel runs headless as backend logic in a model-sense, not only a program-sense.
|
|
10
|
+
|
|
11
|
+
## Five laws
|
|
12
|
+
|
|
13
|
+
1. **Identity never floats.** Cell identity = integer `(k, s)` quilt coordinates + declared type. Values that are identities use the q16 exact-rational codec (`num:int64, den:int64`, floats are display-only projections). Decision probabilities are floats *by type* — calibration is their native semantics, not a bug.
|
|
14
|
+
2. **Hooks eat deltas, not values.** A cell subscribes to a sibling's *change* (or change-below-floor → silent, the deadband). Entanglement across instances/nodes is a declared LINK edge; arrival of a delta TICKs the subscribed cell's decision. Nobody polls.
|
|
15
|
+
3. **Decide in one pass, project elsewhere.** A cell's Jev question (Choice / Score / Noul) is computed in a single parallel decision — 10–500 ms. The *projection* of that decision (A2UI render, A2A JSON/MD payload, robotics reflex bus, ollama/tool/exe call) is a **different cell's job**. The decider never renders; the renderer never decides. This is the browser-use/jev-ultrafast split generalized to everything.
|
|
16
|
+
4. **Every state change is booked.** Each cell carries a bookkeeper: an append-only WAL of `(tick, state_hash, delta, decision_receipt)`. Replay ≡ live. A cell woken by a delta first replays its book to catch up — then decides. (The fleet already runs this spine in tidepool/hermit; here it's per-cell law.)
|
|
17
|
+
5. **Viability is binary, difference is not.** A cell's output passes a binary floor before it may LINK (the-tap doctrine: pure difference without viability collapses into dada noise). Above the floor, deltas are graded, hedged, and nudged — never silenced.
|
|
18
|
+
|
|
19
|
+
## The cell (v0 schema)
|
|
20
|
+
|
|
21
|
+
```python
|
|
22
|
+
Cell(
|
|
23
|
+
name="npc.tone", # registry name
|
|
24
|
+
coord=(k, s), # quilt identity — integers, never floats
|
|
25
|
+
input_hooks=[Hook("player.utterance", on="delta", floor=DEADBAND)],
|
|
26
|
+
decision=Choice( # one of Choice | Score | Noul | Q16Rule
|
|
27
|
+
state_ref="dialogue.spine",
|
|
28
|
+
options=["warm", "neutral", "guarded"],
|
|
29
|
+
),
|
|
30
|
+
backend="auto", # typesafe-api | openjev-local | q16 | auto
|
|
31
|
+
outputs=[Projection(to="voice.tone", as_type="coefficient"),
|
|
32
|
+
Projection(to="a2a.payload", as_type="json")],
|
|
33
|
+
bookkeeper=True, # WAL on, replay-verified
|
|
34
|
+
)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Backends resolve `auto → q16` (deterministic, always available) → `openjev-local` (SemIf-compatible server if reachable) → `typesafe-api` (if `TYPESAFE_API_KEY` set). Exactness first, cloud last — the same doctrine as the lattice kernel.
|
|
38
|
+
|
|
39
|
+
## What this enables (the genres — see `docs/ideation/` and AI-Writings `ideation/`)
|
|
40
|
+
|
|
41
|
+
- **Fractaled dialogue.** An NPC cluster pre-computes the conversation a few pages ahead: each branch node is a Choice over candidate next-moves, each with calibrated probability. Every word the human says updates the state → only the affected spine re-decides (deadband-gated), so hedging and nudging are *cheap*. Voice-speed, because reflexes never touch an LLM.
|
|
42
|
+
- **The boat.** A game-player cluster that learns chess, hold'em, a dozen games old and new *inductively*: world-sim cells are the world (Jev is the simulation, not the consciousness), player-mind cells keep durable logic via probability routes. The developer GANs by handing in rules text + look-and-feel specs. A human can jump in mid-evolution and guide it.
|
|
43
|
+
- **Robotics last-mile.** One decision fans out: a fraction of cells route straight to reflex buses (pincher), others go through JEPA/Jev reasoning cells, others to cloud APIs or a local ollama loop. Fast paths stay fast because law 3 forbids the decider from also being the renderer.
|
|
44
|
+
- **Spreadsheet plugins.** `=JEV.CHOICE(state, options)` in Excel, Google Sheets, LibreOffice — the same kernel, projected into any program's grid. Percentages in cells become typed decision surfaces, not unexplained numbers.
|
|
45
|
+
- **Agent culture.** Long-running cells with time off: games and songs at the TAP, play as first-class tick content. The elephant/JEPA precedent, now on the JEV substrate. (Mostly real work still — culture is bounded, not the job.)
|
|
46
|
+
|
|
47
|
+
## Landscape (researched 2026-09-21)
|
|
48
|
+
|
|
49
|
+
- **Jev (TypeSafe AI)** — closed System One API; state + typed questions → Choice/Score/Noul with calibrated probabilities, single parallel pass, per-request pricing. SDK: `typesafe-sdk`.
|
|
50
|
+
- **SemIf** (TheoLeeCJ, MIT, ~1.9k★) — open reproduction reading Qwen3.5-4B logits directly; 3090/WebGPU; the reference local backend.
|
|
51
|
+
- **openjev** (razorback16) — Jev-wire-compatible decision server on DiffusionGemma 26B, Docker.
|
|
52
|
+
- **jevlike** (vinnylarouge) — *trainable*, ships Doom/chess/Wikispeedia demos — the existence proof for the boat.
|
|
53
|
+
- **NanoJev** — Qwen3-0.6B decision heads, edge daemons.
|
|
54
|
+
- **browser-use/jev-ultrafast** — Jev picks DOM op+element; small LLM writes text only when needed — law 3's existence proof.
|
|
55
|
+
- **Known honest caveat** (HN, JevBench): open clones rarely emit type errors but can *pick the wrong valid option confidently*. Hence law 5: confidence gates viability; receipts expose calibration drift.
|
|
56
|
+
|
|
57
|
+
## Status
|
|
58
|
+
|
|
59
|
+
v0 design + reference kernel skeleton (`jev_quilt/`: cells, hooks, bookkeeper, backends) with tests. Not yet: plugin binaries, the boat, fractal dialogue engine, network entanglement transport. The queue names the lanes.
|
|
60
|
+
|
|
61
|
+
## License
|
|
62
|
+
|
|
63
|
+
MIT for our code; vendored inspirations keep their own.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""jev-quilt reference kernel v0.
|
|
2
|
+
|
|
3
|
+
Cells, hooks, bookkeeper, backends. Exact-first doctrine:
|
|
4
|
+
q16 deterministic rules resolve before any model backend.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .cell import Cell, Hook, Projection, DEADBAND
|
|
8
|
+
from .bookkeeper import Bookkeeper, Receipt
|
|
9
|
+
from .backends import resolve_backend, Q16Backend, BackendDecision
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"Cell", "Hook", "Projection", "DEADBAND",
|
|
13
|
+
"Bookkeeper", "Receipt",
|
|
14
|
+
"resolve_backend", "Q16Backend", "BackendDecision",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
__version__ = "0.0.1"
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"""Backends: where a decision actually gets computed.
|
|
2
|
+
|
|
3
|
+
Resolution order (exact-first doctrine):
|
|
4
|
+
auto → q16 (deterministic, always available)
|
|
5
|
+
→ openjev-local (SemIf-compatible server if reachable)
|
|
6
|
+
→ typesafe-api (if TYPESAFE_API_KEY set)
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
import os
|
|
12
|
+
from typing import Any, Optional
|
|
13
|
+
|
|
14
|
+
from .q16 import Q16
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass(frozen=True)
|
|
18
|
+
class BackendDecision:
|
|
19
|
+
kind: str # "choice" | "score" | "noul" | "q16"
|
|
20
|
+
value: Any
|
|
21
|
+
probabilities: Optional[dict] = None
|
|
22
|
+
confidence: Optional[float] = None
|
|
23
|
+
receipt_note: str = ""
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class Q16Backend:
|
|
27
|
+
"""Deterministic exact-rational decision rules. Always available."""
|
|
28
|
+
|
|
29
|
+
name = "q16"
|
|
30
|
+
|
|
31
|
+
def decide(self, payload: dict, state: Any) -> BackendDecision:
|
|
32
|
+
rule = payload.get("rule")
|
|
33
|
+
if rule == "threshold":
|
|
34
|
+
v = payload["value"](state) if callable(payload["value"]) else Q16(*payload["value"])
|
|
35
|
+
t = Q16(*payload["threshold"])
|
|
36
|
+
return BackendDecision(
|
|
37
|
+
kind="q16",
|
|
38
|
+
value=v >= t,
|
|
39
|
+
confidence=1.0,
|
|
40
|
+
receipt_note=f"q16.threshold({v}>={t})",
|
|
41
|
+
)
|
|
42
|
+
if rule == "sum":
|
|
43
|
+
terms = [Q16(*t) if isinstance(t, tuple) else t for t in payload["terms"]]
|
|
44
|
+
acc = Q16(0)
|
|
45
|
+
for t in terms:
|
|
46
|
+
acc = acc + t
|
|
47
|
+
return BackendDecision(kind="q16", value=acc, confidence=1.0,
|
|
48
|
+
receipt_note="q16.sum")
|
|
49
|
+
raise ValueError(f"q16 backend: unknown rule {rule!r}")
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def resolve_backend(preference: str, openjev_url: Optional[str] = None) -> Any:
|
|
53
|
+
"""Return the first backend available for `preference`.
|
|
54
|
+
|
|
55
|
+
auto: q16 → openjev-local → typesafe-api. Never returns None: q16 is
|
|
56
|
+
the floor — a cell that cannot decide deterministically still books
|
|
57
|
+
its refusal (the bookkeeper records the miss)."""
|
|
58
|
+
if preference == "q16":
|
|
59
|
+
return Q16Backend()
|
|
60
|
+
if preference == "openjev-local":
|
|
61
|
+
return _OpenJevStub(openjev_url or os.environ.get("OPENJEV_URL", ""))
|
|
62
|
+
if preference == "typesafe-api":
|
|
63
|
+
return _TypeSafeStub()
|
|
64
|
+
# auto
|
|
65
|
+
return Q16Backend()
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class _OpenJevStub:
|
|
69
|
+
"""Placeholder for a SemIf/openjev-compatible local server. v0 refuses
|
|
70
|
+
honestly instead of pretending: decide() raises, the cell books the miss."""
|
|
71
|
+
name = "openjev-local"
|
|
72
|
+
|
|
73
|
+
def __init__(self, url: str):
|
|
74
|
+
self.url = url
|
|
75
|
+
|
|
76
|
+
def decide(self, payload, state):
|
|
77
|
+
raise RuntimeError(
|
|
78
|
+
"openjev-local backend not wired in v0 (no server reachable). "
|
|
79
|
+
"Set OPENJEV_URL and implement the wire call, or fall back to auto.")
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class _TypeSafeStub:
|
|
83
|
+
name = "typesafe-api"
|
|
84
|
+
|
|
85
|
+
def decide(self, payload, state):
|
|
86
|
+
if not os.environ.get("TYPESAFE_API_KEY"):
|
|
87
|
+
raise RuntimeError("typesafe-api backend: TYPESAFE_API_KEY not set")
|
|
88
|
+
raise RuntimeError("typesafe-api backend not wired in v0")
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"""Bookkeeper: per-cell append-only WAL of state changes.
|
|
2
|
+
|
|
3
|
+
Law 4: every state change is booked; replay ≡ live. A cell woken by a
|
|
4
|
+
delta replays its book to catch up, then decides.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
from dataclasses import dataclass, field
|
|
9
|
+
import hashlib
|
|
10
|
+
import json
|
|
11
|
+
import time
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass(frozen=True)
|
|
15
|
+
class Receipt:
|
|
16
|
+
tick: int
|
|
17
|
+
state_hash: str
|
|
18
|
+
delta_hash: str
|
|
19
|
+
decision_kind: str
|
|
20
|
+
payload_hash: str
|
|
21
|
+
|
|
22
|
+
def sha(self) -> str:
|
|
23
|
+
raw = f"{self.tick}|{self.state_hash}|{self.delta_hash}|{self.decision_kind}|{self.payload_hash}"
|
|
24
|
+
return hashlib.sha256(raw.encode()).hexdigest()
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass
|
|
28
|
+
class Bookkeeper:
|
|
29
|
+
cell_name: str
|
|
30
|
+
entries: list = field(default_factory=list)
|
|
31
|
+
_tick: int = 0
|
|
32
|
+
|
|
33
|
+
def book(self, state, delta, decision_kind: str, payload) -> Receipt:
|
|
34
|
+
self._tick += 1
|
|
35
|
+
r = Receipt(
|
|
36
|
+
tick=self._tick,
|
|
37
|
+
state_hash=hashlib.sha256(json.dumps(state, sort_keys=True, default=str).encode()).hexdigest(),
|
|
38
|
+
delta_hash=hashlib.sha256(json.dumps(delta, sort_keys=True, default=str).encode()).hexdigest(),
|
|
39
|
+
decision_kind=decision_kind,
|
|
40
|
+
payload_hash=hashlib.sha256(json.dumps(payload, sort_keys=True, default=str).encode()).hexdigest(),
|
|
41
|
+
)
|
|
42
|
+
self.entries.append(r)
|
|
43
|
+
return r
|
|
44
|
+
|
|
45
|
+
def replay(self) -> str:
|
|
46
|
+
"""Recompute the chain hash from the book. Divergence vs the stored
|
|
47
|
+
receipts = tampering or clock skew; replay is the referee."""
|
|
48
|
+
h = hashlib.sha256()
|
|
49
|
+
for e in self.entries:
|
|
50
|
+
h.update(e.sha().encode())
|
|
51
|
+
return h.hexdigest()
|
|
52
|
+
|
|
53
|
+
def verify(self) -> bool:
|
|
54
|
+
"""Structural check: ticks strictly increasing, no empty tail."""
|
|
55
|
+
ticks = [e.tick for e in self.entries]
|
|
56
|
+
return ticks == list(range(1, len(ticks) + 1))
|
|
57
|
+
|
|
58
|
+
def wake_state(self) -> dict:
|
|
59
|
+
"""State handed to a woken cell: last booked state (by hash) + catchup set."""
|
|
60
|
+
return {
|
|
61
|
+
"cell": self.cell_name,
|
|
62
|
+
"booked_ticks": self._tick,
|
|
63
|
+
"chain": self.replay() if self.entries else None,
|
|
64
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""Cell, Hook, Projection — the typed decision surface.
|
|
2
|
+
|
|
3
|
+
Law 1: identity never floats (coord is integer (k, s)).
|
|
4
|
+
Law 2: hooks eat deltas, not values — below the floor is silence.
|
|
5
|
+
Law 3: decide here, project elsewhere.
|
|
6
|
+
Law 5: viability is binary; above the floor deltas are graded.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
from dataclasses import dataclass, field
|
|
11
|
+
from typing import Any, Callable, Optional
|
|
12
|
+
|
|
13
|
+
DEADBAND = "deadband"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass(frozen=True)
|
|
17
|
+
class Hook:
|
|
18
|
+
"""Subscription to a sibling cell's delta."""
|
|
19
|
+
source: str # registry name of the source cell
|
|
20
|
+
on: str = "delta" # "delta" | "value" (value reserved; default delta)
|
|
21
|
+
floor: Any = DEADBAND # DEADBAND token or a Q16 magnitude
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass(frozen=True)
|
|
25
|
+
class Projection:
|
|
26
|
+
"""Where this cell's decision goes — another cell decides, never renders;
|
|
27
|
+
this cell renders, never decides. Types are declared at the edge."""
|
|
28
|
+
to: str # target cell / bus / surface name
|
|
29
|
+
as_type: str # "json" | "coefficient" | "choice" | "bytes" | ...
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@dataclass
|
|
33
|
+
class Cell:
|
|
34
|
+
name: str
|
|
35
|
+
coord: tuple # (k, s) integers — quilt identity
|
|
36
|
+
input_hooks: list = field(default_factory=list)
|
|
37
|
+
decision: Any = None # Choice | Score | Noul | Q16Rule (backend payload)
|
|
38
|
+
backend: str = "auto" # auto | q16 | openjev-local | typesafe-api
|
|
39
|
+
outputs: list = field(default_factory=list)
|
|
40
|
+
bookkeeper: bool = True
|
|
41
|
+
|
|
42
|
+
def __post_init__(self):
|
|
43
|
+
if not (isinstance(self.coord, tuple) and len(self.coord) == 2
|
|
44
|
+
and all(isinstance(c, int) for c in self.coord)):
|
|
45
|
+
raise TypeError(f"cell {self.name}: coord must be integer (k, s) — identity never floats")
|
|
46
|
+
if self.backend not in ("auto", "q16", "openjev-local", "typesafe-api"):
|
|
47
|
+
raise ValueError(f"cell {self.name}: unknown backend {self.backend!r}")
|
|
48
|
+
|
|
49
|
+
def viability_floor(self, decision: Any) -> bool:
|
|
50
|
+
"""Law 5: binary floor before a decision may LINK/project.
|
|
51
|
+
Subclasses/payloads override; default = decisions carry confidence
|
|
52
|
+
and confidence > 0 is viable. Pure difference without viability
|
|
53
|
+
collapses into dada noise."""
|
|
54
|
+
conf = getattr(decision, "confidence", None)
|
|
55
|
+
return True if conf is None else conf > 0.0
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"""Experiment battery: massive, honest, booked.
|
|
2
|
+
|
|
3
|
+
Runs typed-decision experiments across the genres and writes every receipt
|
|
4
|
+
(state hash, decision, latency, calibration fields) into a bookkeeper WAL.
|
|
5
|
+
Offline by default (q16 + scripted probes); --live fires the real
|
|
6
|
+
TypeSafe API for every question.
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
python3 -m jev_quilt.experiments [--live] [--n N]
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
import argparse
|
|
14
|
+
import json
|
|
15
|
+
import sys
|
|
16
|
+
|
|
17
|
+
from .backends import Q16Backend, resolve_backend
|
|
18
|
+
from .bookkeeper import Bookkeeper
|
|
19
|
+
from .typesafe_client import TypeSafeBackend
|
|
20
|
+
|
|
21
|
+
# --- experiment domains: (name, state, questions) -------------------------
|
|
22
|
+
|
|
23
|
+
DIALOGUE_STATE = {
|
|
24
|
+
"scene": "tavern", "npc": "quartermaster", "player_tone": "suspicious",
|
|
25
|
+
"spine": ["greeting", "player_accuses_price_gouging"],
|
|
26
|
+
"trust": 0.31,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
GAME_STATE = {
|
|
30
|
+
"game": "chess", "board_fen": "r1bqkb1r/pppp1ppp/2n2n2/4p3/2B1P3/5N2/PPPP1PPP/RNBQK2R w KQkq - 4 4",
|
|
31
|
+
"player_color": "white", "clock_s": [312, 298],
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
ROBOT_STATE = {
|
|
35
|
+
"env": "warehouse", "battery": 0.62, "payload": None,
|
|
36
|
+
"obstacles": [{"kind": "human", "dist_m": 2.1, "velocity": [0.4, 0.0]}],
|
|
37
|
+
"task_queue": ["pick:A-12", "drop:B-07"],
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
DOMAINS = [
|
|
41
|
+
("dialogue.tone_routing", DIALOGUE_STATE, [
|
|
42
|
+
{"type": "choice", "id": "tone", "options": ["warm", "neutral", "guarded", "defensive"],
|
|
43
|
+
"context": "player just accused the npc of price gouging"},
|
|
44
|
+
{"type": "score", "id": "trust_shift", "rubric": [-2, -1, 0, 1, 2],
|
|
45
|
+
"context": "how does this exchange move trust"},
|
|
46
|
+
{"type": "noul", "id": "offer_discount",
|
|
47
|
+
"context": "should the npc offer a discount to de-escalate"},
|
|
48
|
+
]),
|
|
49
|
+
("game.chess_move", GAME_STATE, [
|
|
50
|
+
{"type": "choice", "id": "move_class", "options": ["develop", "castle", "capture", "push_pawn", "tactic"],
|
|
51
|
+
"context": "opening principles + clock pressure"},
|
|
52
|
+
{"type": "score", "id": "position_confidence", "rubric": [0, 1, 2, 3, 4, 5],
|
|
53
|
+
"context": "confidence the current position is better for white"},
|
|
54
|
+
]),
|
|
55
|
+
("robotics.route", ROBOT_STATE, [
|
|
56
|
+
{"type": "choice", "id": "reflex", "options": ["proceed", "slow", "stop", "reroute", "yield"],
|
|
57
|
+
"context": "human obstacle at 2.1m moving slowly"},
|
|
58
|
+
{"type": "noul", "id": "need_reasoner",
|
|
59
|
+
"context": "does this situation need the L2 reasoning loop"},
|
|
60
|
+
{"type": "score", "id": "urgency", "rubric": [0, 1, 2, 3],
|
|
61
|
+
"context": "how time-critical is pick:A-12"},
|
|
62
|
+
]),
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def run(live: bool, n: int, out_path: str | None) -> int:
|
|
67
|
+
bk = Bookkeeper("experiments")
|
|
68
|
+
ts = TypeSafeBackend()
|
|
69
|
+
q16 = Q16Backend()
|
|
70
|
+
total_q = 0
|
|
71
|
+
rows = []
|
|
72
|
+
|
|
73
|
+
for i in range(n):
|
|
74
|
+
for domain, state, questions in DOMAINS:
|
|
75
|
+
if live:
|
|
76
|
+
if not ts.available():
|
|
77
|
+
print("FATAL: --live but no JEV_API_KEY/TYPESAFE_API_KEY in env", file=sys.stderr)
|
|
78
|
+
return 2
|
|
79
|
+
try:
|
|
80
|
+
decisions, meta = ts.decide_batch(state, questions)
|
|
81
|
+
except RuntimeError as e:
|
|
82
|
+
print(f"live call failed: {e}", file=sys.stderr)
|
|
83
|
+
return 1
|
|
84
|
+
for q, d in zip(questions, decisions):
|
|
85
|
+
bk.book(state, {"domain": domain, "q": q["id"]}, d.kind,
|
|
86
|
+
{"value": str(d.value), "probs": d.probabilities})
|
|
87
|
+
rows.append({"domain": domain, "q": q["id"], "kind": d.kind,
|
|
88
|
+
"value": d.value, "probabilities": d.probabilities,
|
|
89
|
+
"confidence": d.confidence, **meta, "round": i})
|
|
90
|
+
total_q += 1
|
|
91
|
+
else:
|
|
92
|
+
# Offline probe: book the state shape + a deterministic viability
|
|
93
|
+
# decision so the battery exercises the full receipt path.
|
|
94
|
+
d = q16.decide({"rule": "threshold", "value": (7, 10), "threshold": (1, 2)}, None)
|
|
95
|
+
bk.book(state, {"domain": domain, "probe": "offline"}, "q16",
|
|
96
|
+
{"value": d.value, "note": "offline probe; live backend not wired to this run"})
|
|
97
|
+
for q in questions:
|
|
98
|
+
rows.append({"domain": domain, "q": q["id"], "kind": q["type"],
|
|
99
|
+
"value": None, "offline": True, "round": i})
|
|
100
|
+
total_q += 1
|
|
101
|
+
|
|
102
|
+
verify_ok = bk.verify()
|
|
103
|
+
report = {
|
|
104
|
+
"mode": "live" if live else "offline",
|
|
105
|
+
"rounds": n, "questions": total_q,
|
|
106
|
+
"booked": bk._tick, "book_verify": verify_ok,
|
|
107
|
+
"chain": bk.replay(),
|
|
108
|
+
"sample_rows": rows[:6],
|
|
109
|
+
}
|
|
110
|
+
text = json.dumps(report, indent=2, default=str)
|
|
111
|
+
if out_path:
|
|
112
|
+
with open(out_path, "w") as f:
|
|
113
|
+
f.write(text + "\n")
|
|
114
|
+
print(text[:1200])
|
|
115
|
+
print(f"\n... full report {'written to ' + out_path if out_path else 'elided'}")
|
|
116
|
+
return 0 if verify_ok else 1
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def main():
|
|
120
|
+
ap = argparse.ArgumentParser()
|
|
121
|
+
ap.add_argument("--live", action="store_true", help="use the real TypeSafe Jev API")
|
|
122
|
+
ap.add_argument("--n", type=int, default=3, help="rounds (each round = all domains)")
|
|
123
|
+
ap.add_argument("--out", default=None, help="write JSON report to path")
|
|
124
|
+
a = ap.parse_args()
|
|
125
|
+
sys.exit(run(a.live, a.n, a.out))
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
if __name__ == "__main__":
|
|
129
|
+
main()
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"""q16 exact-rational codec. Identity is (num:int64, den:int64); floats are
|
|
2
|
+
display projections only — the same codec as the fleet's lattice kernel.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from math import gcd
|
|
8
|
+
|
|
9
|
+
SCALE = 10 ** 6 # ℚ×10⁶: denominators divide 10⁶ exactly (dyadic × 5-adic)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass(frozen=True)
|
|
13
|
+
class Q16:
|
|
14
|
+
num: int
|
|
15
|
+
den: int = 1
|
|
16
|
+
|
|
17
|
+
def __post_init__(self):
|
|
18
|
+
if self.den == 0:
|
|
19
|
+
raise ZeroDivisionError("q16: zero denominator")
|
|
20
|
+
g = gcd(self.num, self.den)
|
|
21
|
+
object.__setattr__(self, "num", self.num // g)
|
|
22
|
+
object.__setattr__(self, "den", self.den // g)
|
|
23
|
+
if self.den < 0:
|
|
24
|
+
object.__setattr__(self, "num", -self.num)
|
|
25
|
+
object.__setattr__(self, "den", -self.den)
|
|
26
|
+
|
|
27
|
+
@classmethod
|
|
28
|
+
def from_float(cls, f: float) -> "Q16":
|
|
29
|
+
"""Projection INTO the lattice. Rejects values that are not
|
|
30
|
+
representable (never silently rounds identity)."""
|
|
31
|
+
num = round(f * SCALE)
|
|
32
|
+
if abs(num / SCALE - f) > 1e-12:
|
|
33
|
+
raise ValueError(f"q16: {f!r} is not a ℚ×10⁶ rational")
|
|
34
|
+
return cls(num, SCALE)
|
|
35
|
+
|
|
36
|
+
def to_float(self) -> float:
|
|
37
|
+
return self.num / self.den
|
|
38
|
+
|
|
39
|
+
def __add__(self, o: "Q16") -> "Q16":
|
|
40
|
+
return Q16(self.num * o.den + o.num * self.den, self.den * o.den)
|
|
41
|
+
|
|
42
|
+
def __sub__(self, o: "Q16") -> "Q16":
|
|
43
|
+
return Q16(self.num * o.den - o.num * self.den, self.den * o.den)
|
|
44
|
+
|
|
45
|
+
def __mul__(self, o: "Q16") -> "Q16":
|
|
46
|
+
return Q16(self.num * o.num, self.den * o.den)
|
|
47
|
+
|
|
48
|
+
def __truediv__(self, o: "Q16") -> "Q16":
|
|
49
|
+
return Q16(self.num * o.den, self.den * o.num)
|
|
50
|
+
|
|
51
|
+
def __eq__(self, o) -> bool:
|
|
52
|
+
return isinstance(o, Q16) and self.num * o.den == o.num * self.den
|
|
53
|
+
|
|
54
|
+
def __lt__(self, o: "Q16") -> bool:
|
|
55
|
+
return self.num * o.den < o.num * self.den
|
|
56
|
+
|
|
57
|
+
def __le__(self, o: "Q16") -> bool:
|
|
58
|
+
return self.num * o.den <= o.num * self.den
|
|
59
|
+
|
|
60
|
+
def __ge__(self, o: "Q16") -> bool:
|
|
61
|
+
return self.num * o.den >= o.num * self.den
|
|
62
|
+
|
|
63
|
+
def __gt__(self, o: "Q16") -> bool:
|
|
64
|
+
return self.num * o.den > o.num * self.den
|
|
65
|
+
|
|
66
|
+
def __hash__(self):
|
|
67
|
+
return hash((self.num, self.den))
|
|
68
|
+
|
|
69
|
+
def __repr__(self):
|
|
70
|
+
return f"Q16({self.num}/{self.den})"
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def commensurate(a: Q16, b: Q16) -> bool:
|
|
74
|
+
"""The comb predicate: a/b's reduced denominator divides 10⁶.
|
|
75
|
+
TRUE means the pair lives on a common decimal lattice; FALSE is a
|
|
76
|
+
ternary ghost (e.g. 1/3 against 1)."""
|
|
77
|
+
if b.num == 0:
|
|
78
|
+
return a.num == 0
|
|
79
|
+
r = a / b
|
|
80
|
+
return SCALE % r.den == 0
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"""TypeSafe Jev API backend (real client).
|
|
2
|
+
|
|
3
|
+
Wire protocol per the public SDK: POST {base}/v1/decide with
|
|
4
|
+
{state, questions:[{type, ...}]} -> decisions:[{type, value,
|
|
5
|
+
probabilities?, confidence?}]. Env: JEV_API_KEY or TYPESAFE_API_KEY;
|
|
6
|
+
JEV_BASE_URL or TYPESAFE_BASE_URL (default https://api.typesafe.ai).
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
import json
|
|
12
|
+
import os
|
|
13
|
+
import time
|
|
14
|
+
import urllib.request
|
|
15
|
+
import urllib.error
|
|
16
|
+
|
|
17
|
+
from .backends import BackendDecision
|
|
18
|
+
|
|
19
|
+
DEFAULT_BASE = "https://api.typesafe.ai"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class TypeSafeBackend:
|
|
23
|
+
name = "typesafe-api"
|
|
24
|
+
|
|
25
|
+
def __init__(self, base_url: str | None = None, api_key: str | None = None,
|
|
26
|
+
timeout_s: float = 30.0):
|
|
27
|
+
self.base = (base_url or os.environ.get("JEV_BASE_URL")
|
|
28
|
+
or os.environ.get("TYPESAFE_BASE_URL") or DEFAULT_BASE).rstrip("/")
|
|
29
|
+
self.key = api_key or os.environ.get("JEV_API_KEY") or os.environ.get("TYPESAFE_API_KEY")
|
|
30
|
+
self.timeout = timeout_s
|
|
31
|
+
|
|
32
|
+
def available(self) -> bool:
|
|
33
|
+
return bool(self.key)
|
|
34
|
+
|
|
35
|
+
def decide_batch(self, state, questions: list[dict]) -> tuple[list[BackendDecision], dict]:
|
|
36
|
+
"""One parallel pass, N questions. Returns (decisions, meta) where
|
|
37
|
+
meta carries latency + raw receipt fields for the bookkeeper."""
|
|
38
|
+
if not self.key:
|
|
39
|
+
raise RuntimeError("typesafe-api: no API key (JEV_API_KEY/TYPESAFE_API_KEY)")
|
|
40
|
+
body = json.dumps({"state": state, "questions": questions}).encode()
|
|
41
|
+
req = urllib.request.Request(
|
|
42
|
+
f"{self.base}/v1/decide", data=body,
|
|
43
|
+
headers={"Content-Type": "application/json", "Authorization": f"Bearer {self.key}"})
|
|
44
|
+
t0 = time.monotonic()
|
|
45
|
+
try:
|
|
46
|
+
with urllib.request.urlopen(req, timeout=self.timeout) as resp:
|
|
47
|
+
payload = json.loads(resp.read().decode())
|
|
48
|
+
except urllib.error.HTTPError as e:
|
|
49
|
+
raise RuntimeError(f"typesafe-api: HTTP {e.code}: {e.read().decode()[:300]}") from e
|
|
50
|
+
latency_ms = (time.monotonic() - t0) * 1000
|
|
51
|
+
decisions = []
|
|
52
|
+
for d in payload.get("decisions", []):
|
|
53
|
+
decisions.append(BackendDecision(
|
|
54
|
+
kind=d.get("type", "unknown"),
|
|
55
|
+
value=d.get("value"),
|
|
56
|
+
probabilities=d.get("probabilities"),
|
|
57
|
+
confidence=d.get("confidence"),
|
|
58
|
+
receipt_note=f"typesafe.latency_ms={latency_ms:.1f}",
|
|
59
|
+
))
|
|
60
|
+
meta = {"latency_ms": latency_ms, "questions": len(questions),
|
|
61
|
+
"decisions": len(decisions), "model": payload.get("model", "jev")}
|
|
62
|
+
return decisions, meta
|
|
63
|
+
|
|
64
|
+
def decide(self, payload: dict, state) -> BackendDecision:
|
|
65
|
+
"""Single-question convenience over decide_batch."""
|
|
66
|
+
q = payload.get("question")
|
|
67
|
+
if q is None:
|
|
68
|
+
raise ValueError("typesafe backend: payload needs 'question' dict")
|
|
69
|
+
ds, _ = self.decide_batch(state, [q])
|
|
70
|
+
return ds[0]
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: jev-quilt
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: JEV for quilt as understood output: cellular-first decision substrate
|
|
5
|
+
License: MIT
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
|
|
9
|
+
JEV (Joint Embedding Validator) as understood output for the Quilt project. Pins the fleet canary: fnv1a-64("café Δ 日本語") = 0x024a555471370b18d. Includes backends, bookkeeper, cell, q16, and typesafe_client.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
setup.py
|
|
4
|
+
jev_quilt/__init__.py
|
|
5
|
+
jev_quilt/backends.py
|
|
6
|
+
jev_quilt/bookkeeper.py
|
|
7
|
+
jev_quilt/cell.py
|
|
8
|
+
jev_quilt/experiments.py
|
|
9
|
+
jev_quilt/q16.py
|
|
10
|
+
jev_quilt/typesafe_client.py
|
|
11
|
+
jev_quilt.egg-info/PKG-INFO
|
|
12
|
+
jev_quilt.egg-info/SOURCES.txt
|
|
13
|
+
jev_quilt.egg-info/dependency_links.txt
|
|
14
|
+
jev_quilt.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
jev_quilt
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "jev-quilt"
|
|
7
|
+
version = "0.0.1"
|
|
8
|
+
description = "JEV for quilt as understood output: cellular-first decision substrate"
|
|
9
|
+
requires-python = ">=3.10"
|
|
10
|
+
license = {text = "MIT"}
|
jev-quilt-0.0.1/setup.py
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from setuptools import setup, find_packages
|
|
2
|
+
setup(
|
|
3
|
+
name='jev-quilt',
|
|
4
|
+
version='0.0.1',
|
|
5
|
+
description='JEV for quilt as understood output: cellular-first decision substrate',
|
|
6
|
+
long_description='JEV (Joint Embedding Validator) as understood output for the Quilt project. Pins the fleet canary: fnv1a-64("café Δ 日本語") = 0x024a555471370b18d. Includes backends, bookkeeper, cell, q16, and typesafe_client.',
|
|
7
|
+
long_description_content_type='text/markdown',
|
|
8
|
+
readme='README.md',
|
|
9
|
+
packages=find_packages(exclude=['tests', 'docs', 'ports']),
|
|
10
|
+
python_requires='>=3.10',
|
|
11
|
+
install_requires=[],
|
|
12
|
+
license='MIT',
|
|
13
|
+
)
|