CI Pipeline / best-practices (push) Successful in 11s
CI Pipeline / documentation (push) Successful in 3s
CI Pipeline / rust-surface (push) Failing after 17s
CI Pipeline / go-surface (push) Failing after 20s
CI Pipeline / gitea-offline (push) Successful in 16s
CI Pipeline / required-checks (push) Canceled after 0s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Canceled after 0s
CI Pipeline / type-check (push) Canceled after 29s
deploy / deploy (push) Canceled after 47s
Auto-version and Release / release (push) Canceled after 50s
CI Pipeline / lint (push) Canceled after 45s
CI Pipeline / unit-tests (push) Canceled after 45s
CI Pipeline / canary (push) Canceled after 46s
184 lines
7.4 KiB
Python
184 lines
7.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Freeze the provider_budget truth corpus (dichotomy wave #2479 gap-closing, GO).
|
|
|
|
Drives the LIVE Python oracle (src/rune/provider_budget.py) through the
|
|
shared harness (scripts/freeze_truth.py — RUNE_PROVIDER_BUDGET_CORE=python
|
|
pinned, inputs deep-copied, {"fn","args","kwargs","expected"} envelope) and
|
|
freezes to src/go/provider-budget/truth_frozen.json (embedded VERBATIM by
|
|
the Go battery, truth_frozen_test.go).
|
|
|
|
Determinism contract (why a fixture HOME): the module-level oracle fns all
|
|
run through the global ProviderBudgetTracker, whose storage/config paths
|
|
come from $HOME (expanduser("~/.rune/provider_budgets.json") and
|
|
"~/.config/mimocode/mimocode.jsonc"). Every case therefore replays against
|
|
a REBUILT fixture home:
|
|
|
|
HOME = /tmp/rune_pb_truth_home
|
|
.rune/provider_budgets.json ← STORAGE_FIXTURE (seeded providers)
|
|
.config/mimocode/mimocode.jsonc ← CONFIG_FIXTURE (init-branch surface)
|
|
|
|
Stateful cases (track_usage mutations) are legal because the oracle's own
|
|
_save mutates the fixture home identically on every replay from the same
|
|
initial state — the truth is a replayable script over the canonical home.
|
|
|
|
What is frozen vs seam-tested (JSON-envelope law): freeze() json.dumps the
|
|
expected value, so object-returning fns (get_tracker, get_best_provider →
|
|
ProviderBudget) freeze only at their None arms, and check_provider on a
|
|
KNOWN provider freezes nowhere (datetime.now timestamp + live socket).
|
|
Those branches are pinned by the Go seam battery (fake transport + pinned
|
|
clock) and the random-op live parity instead.
|
|
|
|
Coverage via this harness: get_status (empty tie-break → tracked shifts →
|
|
budget exhaustion → post-failover all-down), track_usage (known+cost,
|
|
known default-cost, unknown no-op, disabled-provider tracking), failover
|
|
(disable-last-available → None arm, unknown no-op arm), check_provider
|
|
(not-found arm), get_best_provider (all-down → None arm).
|
|
|
|
Self-verifying: rebuilds the fixture home, freezes, rebuilds AGAIN, then
|
|
runs the shared harness gate — must report byte-identical:
|
|
|
|
PYTHONPATH=src python3 scripts/freeze_truth.py --verify \
|
|
src/go/provider-budget/truth_frozen.json \
|
|
--module rune.provider_budget
|
|
|
|
Run:
|
|
python3 scripts/gen_provider_budget_truth.py
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
REPO = Path(__file__).resolve().parents[1]
|
|
sys.path.insert(0, str(REPO / "src"))
|
|
sys.path.insert(0, str(REPO / "scripts"))
|
|
|
|
HOME = Path("/tmp/rune_pb_truth_home")
|
|
STORAGE = HOME / ".rune" / "provider_budgets.json"
|
|
CONFIG = HOME / ".config" / "mimocode" / "mimocode.jsonc"
|
|
OUT = REPO / "src" / "go" / "provider-budget" / "truth_frozen.json"
|
|
|
|
# WARNING: keep byte-equal with the fixtures embedded in
|
|
# src/go/provider-budget/truth_frozen_test.go — the Go battery replays the
|
|
# frozen truth against the SAME canonical initial state.
|
|
CONFIG_FIXTURE = {
|
|
"provider": {
|
|
"anthropic-claude": {
|
|
"options": {"baseURL": "https://api.anthropic.example", "apiKey": "sk-fixture-anthropic"},
|
|
},
|
|
"openai-main": {
|
|
"options": {"baseURL": "https://api.openai.example/v1", "apiKey": "sk-fixture-openai"},
|
|
},
|
|
"ollama": {
|
|
"options": {"baseURL": "http://127.0.0.1:11434", "apiKey": ""},
|
|
},
|
|
},
|
|
}
|
|
|
|
|
|
def _provider(name, ptype, url, limit, used, tlimit, tused, enabled):
|
|
return {
|
|
"name": name,
|
|
"provider_type": ptype,
|
|
"url": url,
|
|
"monthly_limit": limit,
|
|
"monthly_used": used,
|
|
"token_limit": tlimit,
|
|
"tokens_used": tused,
|
|
"rpm_limit": 0,
|
|
"rpm_remaining": 0,
|
|
"tpm_limit": 0,
|
|
"tpm_remaining": 0,
|
|
"enabled": enabled,
|
|
"last_check": None,
|
|
"last_error": None,
|
|
}
|
|
|
|
|
|
STORAGE_FIXTURE = {
|
|
# alpha: available, budget_remaining 7.0 — ties with delta (7.0) at case 1;
|
|
# the oracle's stable sort keeps insertion order → best = alpha.
|
|
"alpha": _provider("alpha", "openai-compatible", "https://alpha.example/v1",
|
|
10.0, 3.0, 100000, 40000, True),
|
|
# beta: over budget (5.0 >= 5.0) — unavailable arm.
|
|
"beta": _provider("beta", "openai-compatible", "https://beta.example/v1",
|
|
5.0, 5.0, 0, 0, True),
|
|
# gamma: disabled — unavailable arm.
|
|
"gamma": _provider("gamma", "anthropic", "https://gamma.example",
|
|
20.0, 0.0, 0, 0, False),
|
|
# delta: available, budget_remaining 7.0 — the tie partner.
|
|
"delta": _provider("delta", "openai-compatible", "https://delta.example/v1",
|
|
7.0, 0.0, 0, 0, True),
|
|
}
|
|
|
|
|
|
def build_fixture_home():
|
|
"""Rebuild the canonical fixture home from scratch (idempotent)."""
|
|
shutil.rmtree(HOME, ignore_errors=True)
|
|
CONFIG.parent.mkdir(parents=True, exist_ok=True)
|
|
CONFIG.write_text(json.dumps(CONFIG_FIXTURE, indent=2) + "\n")
|
|
STORAGE.parent.mkdir(parents=True, exist_ok=True)
|
|
STORAGE.write_text(json.dumps(STORAGE_FIXTURE, indent=2) + "\n")
|
|
|
|
|
|
def freeze() -> list:
|
|
os.environ["HOME"] = str(HOME)
|
|
os.environ["RUNE_PROVIDER_BUDGET_CORE"] = "python" # poisoned-truth law
|
|
|
|
import rune.provider_budget as pb # noqa: E402 — after HOME pin
|
|
from freeze_truth import freeze as harness_freeze # noqa: E402
|
|
|
|
cases = [
|
|
# Case 1: loaded-state tie-break — alpha vs delta both rem 7.0,
|
|
# stable sort keeps file insertion order → best_provider "alpha".
|
|
("get_status", (), {}),
|
|
# Mutations: known+cost, known default-cost (kwargs {}), unknown no-op.
|
|
("track_usage", ("alpha", 5000, 2.5), {}),
|
|
("track_usage", ("alpha", 1000), {}),
|
|
("track_usage", ("ghost", 100), {}),
|
|
# alpha now used 5.5 → rem 4.5 < delta 7.0 → best flips to delta.
|
|
("get_status", (), {}),
|
|
# Zero-token + pure-cost usage pushes alpha over budget (15.5 >= 10).
|
|
("track_usage", ("alpha", 0, 10.0), {}),
|
|
# Exhaustion arm: alpha over, beta over, gamma disabled → best delta.
|
|
("get_status", (), {}),
|
|
# Disable the last available provider → best None (failover None arm).
|
|
("failover", ("delta",), {}),
|
|
("get_best_provider", (), {}),
|
|
# Unknown-provider failover is a no-op (no disable, no save).
|
|
("failover", ("ghost",), {}),
|
|
# All-down status: best_provider null, delta.enabled false persisted.
|
|
("get_status", (), {}),
|
|
# check_provider not-found arm (no socket, no timestamp).
|
|
("check_provider", ("ghost",), {}),
|
|
# Disabled providers still accumulate tracked usage (parity quirk).
|
|
("track_usage", ("delta", 10, 0.25), {}),
|
|
]
|
|
pb._tracker = None # fresh singleton per phase
|
|
return harness_freeze("rune.provider_budget", cases, oracle_module="rune.provider_budget")
|
|
|
|
|
|
def main() -> int:
|
|
build_fixture_home()
|
|
truth = freeze()
|
|
OUT.write_text(json.dumps(truth, indent=2, ensure_ascii=False) + "\n")
|
|
print(f"frozen {len(truth)} cases → {OUT}")
|
|
|
|
# Self-verify: rebuild the canonical home (same initial state) and run
|
|
# the shared harness gate — must report byte-identical.
|
|
build_fixture_home()
|
|
env = dict(os.environ, HOME=str(HOME), PYTHONPATH=str(REPO / "src"))
|
|
r = subprocess.run(
|
|
[sys.executable, str(REPO / "scripts" / "freeze_truth.py"),
|
|
"--verify", str(OUT), "--module", "rune.provider_budget"],
|
|
env=env,
|
|
)
|
|
return r.returncode
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|