Port the eleven audit-named missing fns name-preserving 1:1 from src/rune/cache.py (recordHit/_record_hit, recordMiss, flushStats, getCache, putCache, invalidateScope, invalidateAll, nowTs, parseTs, cacheStats, handleHook) with the in-memory hit/miss accumulation (threshold 50 / interval 30s), INVALIDATION_MAP, full schema (both indexes) and an oracle-byte-parity CLI (usage gates, --json indent=2, rune-aware :20 padding and [:200] truncation, compact hook line, PLUGIN manifest). Clock/monotonic/DB behind Env seams. Frozen truth: 78 cases via the shared freeze_truth.py harness (envelope, pinned clock, sandboxed RUNE_MEMORY_DIR), byte-identical regen + --verify green. Go battery replays verbatim + flush-branch seam pins + 16-case CLI live parity (100%). Python oracle battery 12 passed BOTH pins. Audit: cache 6/17 -> 17/17 FULL (GO).
164 lines
5.8 KiB
Python
164 lines
5.8 KiB
Python
"""Cache oracle battery — dichotomy wave gap closure (#2479).
|
|
|
|
The Go core (src/go/cache) ports the eleven audit-named missing fns
|
|
1:1; this battery pins the PYTHON ORACLE itself (sandboxed memory dir,
|
|
frozen clock, monkeypatched monotonic — no real filesystem writes
|
|
outside the sandbox) and cross-checks the committed frozen truth
|
|
byte-identically against the live oracle (delegation-live law). Both
|
|
pins run green: RUNE_CACHE_CORE=python and unset (cache has no core
|
|
seam — the pin documents the freeze convention either way).
|
|
"""
|
|
|
|
import importlib
|
|
import json
|
|
import os
|
|
import sqlite3
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
ROOT = Path(__file__).resolve().parent.parent
|
|
sys.path.insert(0, str(ROOT / "src"))
|
|
|
|
FROZEN = ROOT / "src/go/cache/frozen_truth.json"
|
|
FROZEN_NOW = "2026-10-13T12:00:00+00:00"
|
|
|
|
|
|
@pytest.fixture()
|
|
def oracle(monkeypatch, tmp_path):
|
|
"""A freshly-imported rune.cache against a throwaway DB with a
|
|
frozen clock (module globals reset — import-time DB_PATH derived
|
|
from the sandbox)."""
|
|
monkeypatch.setenv("RUNE_MEMORY_DIR", str(tmp_path))
|
|
monkeypatch.setenv("RUNE_FROZEN_NOW", FROZEN_NOW)
|
|
import rune.cache as cache_mod
|
|
mod = importlib.reload(cache_mod)
|
|
return mod
|
|
|
|
|
|
def db_hit_miss(mod, key):
|
|
db = sqlite3.connect(mod.DB_PATH)
|
|
try:
|
|
row = db.execute("SELECT hit_count, miss_count FROM cache WHERE key=?", (key,)).fetchone()
|
|
return row
|
|
finally:
|
|
db.close()
|
|
|
|
|
|
def test_frozen_truth_replay(oracle):
|
|
"""The committed truth replays against the live oracle: same case
|
|
sequence, same sandbox conditions, identical expected values."""
|
|
doc = json.loads(FROZEN.read_text())
|
|
assert doc["frozen_now"] == FROZEN_NOW
|
|
cases = []
|
|
for c in doc["cases"]:
|
|
cases.append({"fn": c["fn"], "args": c["args"], "kwargs": c.get("kwargs", {})})
|
|
sys.path.insert(0, str(ROOT / "scripts"))
|
|
from freeze_truth import freeze as _freeze
|
|
|
|
fresh = _freeze("rune.cache", cases, oracle_module="rune.cache")
|
|
assert len(fresh) == len(doc["cases"])
|
|
for frozen, live in zip(doc["cases"], fresh):
|
|
assert frozen["expected"] == live["expected"], f"divergence at {frozen['fn']}"
|
|
assert json.loads(json.dumps(fresh)) == json.loads(json.dumps(doc["cases"]))
|
|
|
|
|
|
def test_pending_hit_visibility(oracle):
|
|
"""The double-get audit fix: the pending in-memory count is visible
|
|
to the NEXT get before any flush (row + pending invariant)."""
|
|
oracle.put_cache("k", "value")
|
|
first = oracle.get_cache("k")
|
|
second = oracle.get_cache("k")
|
|
assert first["hit_count"] == 0
|
|
assert second["hit_count"] == 1
|
|
|
|
|
|
def test_true_miss_writes_nothing(oracle):
|
|
"""A key never seen records no miss (no write-on-read for ghosts)."""
|
|
result = oracle.get_cache("ghost")
|
|
assert result == {"hit": False, "key": "ghost"}
|
|
assert oracle._miss_counts == {}
|
|
|
|
|
|
def test_invalidated_miss_records(oracle):
|
|
oracle.put_cache("k", "v")
|
|
oracle.invalidate("k")
|
|
assert oracle.get_cache("k") == {"hit": False, "key": "k"}
|
|
assert oracle._miss_counts.get("k") == 1
|
|
|
|
|
|
def test_flush_threshold(oracle):
|
|
"""_FLUSH_THRESHOLD=50: no DB write before the 50th event, all
|
|
pending counts land on it."""
|
|
oracle.put_cache("k", "v")
|
|
for _ in range(oracle._FLUSH_THRESHOLD - 1):
|
|
oracle.get_cache("k")
|
|
assert db_hit_miss(oracle, "k")[0] == 0
|
|
oracle.get_cache("k") # the 50th event
|
|
assert db_hit_miss(oracle, "k")[0] == oracle._FLUSH_THRESHOLD
|
|
|
|
|
|
def test_flush_interval(oracle, monkeypatch):
|
|
"""_FLUSH_INTERVAL=30s: a monotonic jump past the interval flushes
|
|
on the next record (the branch the frozen truth cannot idle for)."""
|
|
real_monotonic = oracle.time.monotonic
|
|
t = {"now": real_monotonic()}
|
|
monkeypatch.setattr(oracle.time, "monotonic", lambda: t["now"])
|
|
oracle.put_cache("k", "v")
|
|
oracle.get_cache("k")
|
|
assert db_hit_miss(oracle, "k")[0] == 0
|
|
t["now"] += oracle._FLUSH_INTERVAL + 0.5
|
|
oracle.get_cache("k")
|
|
assert db_hit_miss(oracle, "k")[0] == 2
|
|
|
|
|
|
def test_upsert_preserves_counts(oracle):
|
|
oracle.put_cache("k", "v1")
|
|
oracle.get_cache("k")
|
|
oracle.get_cache("k")
|
|
oracle.cache_stats() # flush -> DB hit_count 2
|
|
oracle.put_cache("k", "v2") # upsert must NOT reset stats
|
|
assert db_hit_miss(oracle, "k")[0] == 2
|
|
assert oracle.get_cache("k")["hit_count"] == 2
|
|
|
|
|
|
def test_hit_rate_half_even():
|
|
"""f'{x:.0f}%' ties round half-to-even (quirk #3 family); the Go
|
|
port's %.0f must agree (pinned in cache_test.go)."""
|
|
assert f"{12.5:.0f}" == "12"
|
|
assert f"{13.5:.0f}" == "14"
|
|
|
|
|
|
def test_invalidation_map_scopes(oracle):
|
|
result = oracle.handle_hook("memory.created", {})
|
|
assert result["scopes"] == ["retrieval", "warm_digest"]
|
|
assert oracle.handle_hook("nothing.here", None) == {
|
|
"status": "ok", "event": "nothing.here", "handler": "cache"}
|
|
|
|
|
|
def test_plugin_manifest(oracle):
|
|
assert oracle.PLUGIN["name"] == "cache"
|
|
assert oracle.PLUGIN["hooks"] == {
|
|
"on_session_end": "handle_hook", "on_memory_add": "handle_hook"}
|
|
assert oracle.PLUGIN["auto_activate"] is True
|
|
|
|
|
|
def test_cli_usage_bytes(tmp_path):
|
|
"""The oracle CLI usage gates print exactly these bytes."""
|
|
env = dict(os.environ, RUNE_MEMORY_DIR=str(tmp_path),
|
|
PYTHONPATH=str(ROOT / "src"))
|
|
r = subprocess.run([sys.executable, "-m", "rune.cache", "get"],
|
|
capture_output=True, text=True, cwd=ROOT, env=env)
|
|
assert r.returncode == 0
|
|
assert r.stdout == "usage: cache.py get <key>\n"
|
|
|
|
|
|
def test_compress_and_hash(oracle):
|
|
text = "# comment\n====\nkeep this substantive line\n(_source_: cite)\nab\n"
|
|
compressed = oracle._compress(text)
|
|
assert compressed == "keep this substantive line"
|
|
assert oracle._hash("hello") == __import__("hashlib").sha256(b"hello").hexdigest()[:16]
|