Skip to main content

Route contracts for urirun connectors — declared output shape, effect class, reversibility and composition wires

Project description

urirun-contract

AI Cost Tracking

PyPI Version Python License AI Cost Human Time Model

  • 🤖 LLM usage: $0.6783 (36 commits)
  • 👤 Human dev: ~$1400 (14.0h @ $100/h, 30min dedup)

Generated on 2026-07-05 using openrouter/qwen/qwen3-coder-next


Deklaratywne kontrakty tras dla connectorów urirun.

Kształt wyjścia, klasa efektu (query/command), odwracalność i taksonomia błędów są dziś tylko konwencją — emergentną z rozproszonych return. LLM edytujący handler nie ma punktu zakotwiczenia i dryfuje. Ten pakiet czyni kontrakt deklarowaną, wersjonowaną encją.

README.md ──(lokalny LLM)──▶ contracts.json ──(generator det.)──▶ src/handlers_generated.py
   intencja      proponuje,              kształt prawdy         sygnatura + koperta (nie edytuj)
                 człowiek recenzuje                                     │
                 + commituje                                            ▼ człowiek/LLM pisze CIAŁO
                                                                 src/handlers.py
                                                                        │
                                                                        ▼ enforce + conform (det.)
                                                                 registry (bindings.v2)

LLM biegnie lokalnie (LiteLLM + ollama / llama.cpp / vLLM). Do CI nie dociera — CI weryfikuje deterministycznie: kontrakt i wygenerowany kod są już w repo, brama tylko sprawdza zgodność.

Instalacja

pip install urirun-contract

Użycie w connectorze

# contracts.py — jedyne źródło prawdy
from urirun_contract import Contract, Wire

CONTRACTS = {
    "window/command/close": Contract(
        version="v1", effect="command", reversible=True,
        inverse_route="window/command/restore",
        inp={"id": "?str"},
        out={"action": "const:window-close", "snapshot": "obj", "inverse": "?obj"},
        errors=("unreachable",),
        examples=(...),
    ),
    "window/command/restore": Contract(...),
}
WIRES = [Wire("window/command/close", "window/command/restore", {"snapshot": "snapshot"})]
# core.py — enforce() PRZED pierwszym @conn.handler
import os
import urirun
from urirun_contract import enforce
from myconnector.contracts import CONTRACTS

conn = urirun.connector("myconn", scheme="myscheme")
enforce(conn, CONTRACTS, validate=os.environ.get("URIRUN_CONTRACT_CHECK") == "1")

@conn.handler("window/command/close", isolated=True)
def close(id: str = "") -> dict:
    ...

Pipeline (lokalnie, przed commitem)

make contract              # README → contracts.json  (LLM, bramkowane conform())
make gen                   # contracts.json → src/handlers_generated.py
make check                 # conform + anty-dryf (bez LLM)
pre-commit install         # wepnij bramy w git

API

Funkcja Opis
Contract Deklaracja trasy: efekt, reversible, inp, out, errors, examples
Wire Krawędź kompozycji: producer → consumer + mapping
conform(contracts) Oracle CI: efekt↔czasownik, wzajemny inverse, golden examples
enforce(conn, contracts, validate=...) Wrap conn.handler przed dekoratorami
check(schema, value, where) Walidator mini-języka schematu
check_wire(wire, contracts) Statyczna weryfikacja krawędzi kompozycji
envelope_violation(contract, envelope) Sprawdź kopertę; zwróć naruszenie lub None

Mini-język schematu

Token Znaczenie
"str" "int" "bool" "num" "obj" "list" "any" typy prymitywne
"?str" opcjonalny / nullable
"const:write" dokładna wartość literalna
"enum:a|b|c" wartość z listy
["int"] jednorodna lista
{"oneOf": [A, B]} unia wariantów

CI (deterministyczne, bez LLM)

# .github/workflows/contract.yml
- run: pip install urirun-contract pytest
- run: python -m pytest tests/ -q
- run: bash ci/pre_commit.sh

Przykład

examples/windowpair/     — odwracalna para window/close ↔ window/restore
  contracts.json         — deklaracja (2 kontrakty + 1 wire)
  src/handlers_generated.py  — wygenerowany szkielet (nie edytuj ręcznie)

Multi-package HTTP (architektura wdrożeniowa)

Dwa niezależnie wdrożone procesy różnych URI rozmawiające po HTTP, powiązane jednym contracts.json. Orchestrator jest bramą międzyprocesową: nie współdzieli pamięci z żadną ze stron, tylko weryfikuje JSON na sieci.

producer (Python, :8801)                    consumer-py (Python, :8802)
  window/command/close                          window/command/restore
       │                                               ▲
       │  POST /run → koperta JSON                     │
       │                                               │
       └────────────┐                    ┌─────────────┘
                    │  orchestrator       │
                    │  drive.py           │
                    │  ┌──────────────────┤
                    │  │ 1. POST producer │
                    │  │ 2. wire_payload  │
                    └──│ 3. check handoff │──▶  consumer-go (Go, :8803)
                       │ 4. POST consumer │      window/command/restore
                       └─────────────────┘      (ten sam contracts.json,
                                                 różny język i kontener)
make integration          # uruchom lokalne procesy i orchestruj (bez Dockera)
docker compose up --build --abort-on-container-exit --exit-code-from orchestrator

Udowodnione na realnych portach HTTP:

  • producer(py) ──HTTP──▶ consumer(py) — full handoff, exit 0
  • producer(py) ──HTTP──▶ consumer(go) — full handoff, exit 0
  • consumer(py) i consumer(go): snapshot=string → 422, brak url → 422 + remediation

Struktura repozytrorium

contracts.json            ← jedno źródło prawdy
toolkit/                  ← gate kopiowany do każdego obrazu (zsynchronizuj: make sync-toolkit)
packages/producer/        ← Python, :8801
packages/consumer/        ← Python, :8802
packages/consumer-go/     ← Go, :8803  (te same weryfikacje, inny runtime)
orchestrator/drive.py     ← brama: py→py + py→go
docker-compose.yml        ← 4 serwisy z health-checks

Licencja

Apache-2.0 · Tom Sapletta · https://tom.sapletta.com

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

urirun_contract-0.1.1.tar.gz (49.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

urirun_contract-0.1.1-py3-none-any.whl (34.8 kB view details)

Uploaded Python 3

File details

Details for the file urirun_contract-0.1.1.tar.gz.

File metadata

  • Download URL: urirun_contract-0.1.1.tar.gz
  • Upload date:
  • Size: 49.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for urirun_contract-0.1.1.tar.gz
Algorithm Hash digest
SHA256 b66f7e36183d7028f1e1b69f1e1e00385439352e5bb6664f036a46d462d41cc8
MD5 6a11672a9c752f8e6bc1ae07a2bdd0bb
BLAKE2b-256 671677e05166e057d973031cfe062d4246a70006938bedb9e7cfec6aba4a87b5

See more details on using hashes here.

File details

Details for the file urirun_contract-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for urirun_contract-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 a2eeec5fe10bd35226d820fd56e330185d6a27170f171e2aade516193811cb61
MD5 3c0d42a1a3cc384054f0fe380762db52
BLAKE2b-256 37cec0b5b693949c9c5c5dcdb4306c0e23d3e9e3a4cde340e22d3cecf73c6012

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page