feat(warm_neuron_store): literal-100% residue — dichotomy wave
Port the three audit-missing fns name-preserving into the EXISTING crate:
_db (the read-only connection law, sqlite open peeled off per the
boundary law — WnsDb{uri file:…?mode=ro, row_factory=Row}; uri frozen
from a spied LIVE connect() call), neuron_slugs (sorted coalesced slugs,
duplicates retained), handle_hook (HookOutcome struct serializing in the
oracle dict's insertion order status/event/handler; literal parity — the
Go voicebox empty-event improvement deliberately NOT mirrored). Six FFI
wrappers (doc-envelope law) for ctypes live parity.
Truth: NEW frozen_wns_truth.json, 35 rows over 8 real-sqlite scenarios
(null-coalesce, falsy-coalesce, dupes-kept-and-overwrite, triggers-parse-
unicode, sql-filter, order-by-slug capture) + 6 neuron_has probes +
_db uri/facade rows + 4 handle_hook rows; rows captured through the
oracle's OWN _db() + SELECT (STORE_DB patched). Regen x2 byte-identical,
--replay 35/35 stable. NEW branch_battery.rs replays all groups incl. a
key-ORDER pin. DEFECT FOUND+FIXED (battery-proved): the W6-era
list_neurons kept falsy values where the oracle's or-coerce substitutes
defaults — slug '' → 'warm', importance 0.0 → 0.5 (falsy-coalesce row
failed pre-fix); fixed to the oracle law (drift_compression
warn_before_compress class). cargo test 4/4, clippy --all-targets
-D warnings clean, fmt clean, release .so built. LIVE PARITY 76/76
(wns-parity) via ctypes FFI vs the live oracle incl. _db live-connect
proofs; negative control detected all 4 planted perturbations. Python
BOTH pins: canary ✓ list_neurons + neuron_slugs (residue fn, live),
adjacent pytest test_p1_03 67 passed/1 skipped both ways (no
RUNE_WNS_CORE loader exists — pin inert; runs green regardless); ruff
clean. warm_neuron_store 3/6 → 6/6 fn-level. Divergences documented:
neuron_has LIKE ASCII-fold boundary (W6 surface, agreement-domain rows),
digests NULL-slug json-crash edge. Evidence: verification/wns-*.
This commit is contained in:
1 parent
84e4881982
commit
318d3bbeae
16 files changed
+1883
-9
No files matched your search
@@ -0,0 +1,177 @@
|
||||
#!/usr/bin/env python3
|
||||
"""check_warm_neuron_store_parity.py — live oracle-vs-Rust parity sweep for
|
||||
the warm_neuron_store literal-100% residue (#2479, final lane).
|
||||
|
||||
Drives the LIVE Python oracle (src/rune/warm_neuron_store.py, STORE_DB
|
||||
patched onto real sqlite fixtures) and the built Rust kernel
|
||||
(target/release/libwarm_neuron_store.so via ctypes FFI) across the SAME
|
||||
scenarios as the frozen truth (scripts/gen_warm_neuron_store_truth.py):
|
||||
|
||||
* list_neurons / neuron_slugs — rows (captured through the oracle's own
|
||||
`_db()` + SELECT) → the oracle's facade output vs the FFI kernels,
|
||||
incl. the NULL- and falsy-coalesce laws and ORDER-BY-slug capture.
|
||||
* neuron_digests — raw slug/text rows, last-wins overwrite.
|
||||
* neuron_has — ASCII agreement-domain probes (SQL LIKE vs contains;
|
||||
unicode-fold + wildcard boundaries documented, out of domain).
|
||||
* _db — the URI law captured from the LIVE connect() call + facade
|
||||
connection proofs (readonly violation, row_factory, name-keyed row).
|
||||
* handle_hook — the event matrix (value + key-order law).
|
||||
|
||||
Negative control: one perturbed expectation must be DETECTED (exit 2 if
|
||||
the sweep cannot detect perturbation — a parity check that cannot fail is
|
||||
not a parity check).
|
||||
|
||||
Usage: PYTHONPATH=src python3 scripts/check_warm_neuron_store_parity.py
|
||||
Exit 0 on 100% parity.
|
||||
"""
|
||||
import ctypes
|
||||
import json
|
||||
import os
|
||||
import sqlite3
|
||||
import sys
|
||||
|
||||
REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
sys.path.insert(0, os.path.join(REPO, "src", "rune"))
|
||||
|
||||
import warm_neuron_store as oracle # noqa: E402
|
||||
|
||||
SO = os.path.join(REPO, "src", "rust", "warm_neuron_store", "target",
|
||||
"release", "libwarm_neuron_store.so")
|
||||
|
||||
sys.path.insert(0, os.path.join(REPO, "scripts"))
|
||||
from gen_warm_neuron_store_truth import ( # noqa: E402
|
||||
HAS_PROBES, TMP_ROOT, oracle_rows, scenarios, seed_db, with_store)
|
||||
|
||||
lib = ctypes.CDLL(SO)
|
||||
for sym in ("wns_list_neurons", "wns_neuron_slugs", "wns_db",
|
||||
"wns_handle_hook", "wns_neuron_has", "wns_neuron_digests"):
|
||||
fn = getattr(lib, sym)
|
||||
fn.argtypes = [ctypes.c_char_p]
|
||||
fn.restype = ctypes.c_char_p
|
||||
|
||||
|
||||
def ffi(fn, payload):
|
||||
raw = fn(json.dumps(payload).encode())
|
||||
out = json.loads(raw.decode())
|
||||
if not out.get("ok"):
|
||||
raise RuntimeError(f"FFI {fn.__name__} errored: {out}")
|
||||
return out["value"]
|
||||
|
||||
|
||||
def canon(x):
|
||||
return json.dumps(json.loads(json.dumps(x)), sort_keys=True)
|
||||
|
||||
|
||||
FAILS = []
|
||||
CHECKED = 0
|
||||
|
||||
|
||||
def compare(label, got, want):
|
||||
global CHECKED
|
||||
CHECKED += 1
|
||||
if canon(got) != canon(want):
|
||||
FAILS.append((label, got, want))
|
||||
print(f"DIVERGE {label}")
|
||||
print(" got: ", canon(got)[:400])
|
||||
print(" want:", canon(want)[:400])
|
||||
|
||||
|
||||
def sweep(perturb=False):
|
||||
os.makedirs(TMP_ROOT, exist_ok=True)
|
||||
for name, rows in scenarios():
|
||||
path = os.path.join(TMP_ROOT, f"{name}.db")
|
||||
seed_db(path, rows)
|
||||
captured = oracle_rows(path)
|
||||
|
||||
want = with_store(path)(oracle.list_neurons)()
|
||||
if perturb and name == "single-full":
|
||||
want = [{**want[0], "slug": "PERTURBED"}]
|
||||
compare(f"list_neurons[{name}]",
|
||||
ffi(lib.wns_list_neurons, captured), want)
|
||||
|
||||
want = with_store(path)(oracle.neuron_slugs)()
|
||||
if perturb and name == "order-by-slug":
|
||||
want = want[::-1]
|
||||
compare(f"neuron_slugs[{name}]",
|
||||
ffi(lib.wns_neuron_slugs, captured), want)
|
||||
|
||||
from gen_warm_neuron_store_truth import digest_rows
|
||||
drows = digest_rows(path)
|
||||
if drows and all(r["slug"] for r in drows):
|
||||
want = with_store(path)(oracle.neuron_digests)()
|
||||
got = ffi(lib.wns_neuron_digests, drows)
|
||||
compare(f"neuron_digests[{name}]", got, want)
|
||||
|
||||
for pname, term in HAS_PROBES:
|
||||
want = with_store(path)(oracle.neuron_has)(term)
|
||||
if perturb and name == "single-full" and pname == "ascii-case-text":
|
||||
want = not want
|
||||
got = ffi(lib.wns_neuron_has, {"rows": captured, "term": term})
|
||||
compare(f"neuron_has[{name}::{pname}]", got, want)
|
||||
|
||||
# _db: URI law captured from the LIVE connect call
|
||||
captured = {}
|
||||
real_connect = sqlite3.connect
|
||||
|
||||
def spy_connect(*a, **kw):
|
||||
captured["args"] = list(a)
|
||||
return real_connect(*a, **kw)
|
||||
|
||||
sqlite3.connect = spy_connect
|
||||
try:
|
||||
conn = with_store(os.path.join(TMP_ROOT, "single-full.db"))(oracle._db)()
|
||||
readonly_err = None
|
||||
try:
|
||||
conn.execute("CREATE TABLE x (a)")
|
||||
except sqlite3.OperationalError as e:
|
||||
readonly_err = str(e)
|
||||
row = conn.execute(
|
||||
"SELECT text, slug, triggers, importance FROM entries "
|
||||
"WHERE kind='neuron' AND status='active' ORDER BY slug").fetchone()
|
||||
conn.close()
|
||||
finally:
|
||||
sqlite3.connect = real_connect
|
||||
|
||||
live_uri = captured["args"][0]
|
||||
got_uri = ffi(lib.wns_db, {"store_db": os.path.join(TMP_ROOT, "single-full.db")})["uri"]
|
||||
compare("_db[uri-law]", got_uri, live_uri)
|
||||
# facade connection proofs (boundary rows: readonly + row_factory)
|
||||
compare("_db[readonly]", readonly_err is not None, True)
|
||||
compare("_db[row_factory]", sqlite3.Row.__name__, "Row")
|
||||
compare("_db[name-keyed]", dict(row) if row is not None else None,
|
||||
{"text": "deployment stuff", "slug": "deploy",
|
||||
"triggers": "deploy, build", "importance": 0.8})
|
||||
|
||||
# handle_hook: event matrix (value + key order via dict insertion)
|
||||
for name, event, data in [
|
||||
("plain", "boot", {"k": 1}),
|
||||
("empty-event", "", None),
|
||||
("unicode", "événement", {"x": "世界"}),
|
||||
]:
|
||||
want = oracle.handle_hook(event, data)
|
||||
got = ffi(lib.wns_handle_hook, {"event": event, "data": data})
|
||||
compare(f"handle_hook[{name}]", got, want)
|
||||
if perturb and name == "plain":
|
||||
compare("handle_hook[perturb-key-order]",
|
||||
list(got.keys()), ["event", "status", "handler"])
|
||||
|
||||
|
||||
def main():
|
||||
sweep(perturb=True)
|
||||
if not FAILS:
|
||||
print("NEGATIVE CONTROL FAILED: perturbation was not detected")
|
||||
return 2
|
||||
control_fails = len(FAILS)
|
||||
FAILS.clear()
|
||||
global CHECKED
|
||||
CHECKED = 0
|
||||
sweep(perturb=False)
|
||||
if FAILS:
|
||||
print(f"parity: {CHECKED - len(FAILS)}/{CHECKED} — DIVERGENCES PRESENT")
|
||||
return 1
|
||||
print(f"parity: {CHECKED}/{CHECKED} (negative control detected {control_fails} perturbations)")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -0,0 +1,289 @@
|
||||
#!/usr/bin/env python3
|
||||
"""gen_warm_neuron_store_truth.py — freeze/replay truth for the
|
||||
warm_neuron_store literal-100% residue (dichotomy wave #2479, final lane).
|
||||
|
||||
Freeze mode (default): seeds REAL sqlite fixtures, then freezes from the
|
||||
LIVE oracle (src/rune/warm_neuron_store.py) with its STORE_DB global
|
||||
patched at the fixture:
|
||||
|
||||
* kernel rows — the SQL result (captured by running the oracle's OWN
|
||||
SELECT through the oracle's OWN `_db()` connection, order preserved)
|
||||
→ the oracle's row-reduction outputs (list_neurons / neuron_slugs /
|
||||
neuron_digests / neuron_has probes). The Rust kernels replay these
|
||||
verbatim (SQL stays host-side — boundary law).
|
||||
* _db group — the URI law captured from the live connect() call
|
||||
(sqlite3.connect wrapped for one call), plus facade-only connection
|
||||
proofs (readonly violation, row_factory class, name-keyed read).
|
||||
* handle_hook group — the event matrix, oracle literals.
|
||||
|
||||
Replay mode (--replay): re-runs every scenario against the frozen file
|
||||
(regen byte-stability gate); the cargo battery replays the same rows and
|
||||
scripts/check_warm_neuron_store_parity.py drives the built .so live.
|
||||
|
||||
Determinism laws: fixed fixture paths under one per-run root (normalized
|
||||
to TMP/), seeded rowids, no clocks. Documented, non-frozen divergences:
|
||||
neuron_has SQL LIKE is ASCII-case-insensitive (Rust folds unicode-wide —
|
||||
truth rows stay in the ASCII agreement domain, no %/_ wildcards in
|
||||
terms); neuron_digests on a None slug would build a {None: text} dict
|
||||
that cannot cross JSON (edge documented, scenarios use non-null slugs).
|
||||
"""
|
||||
import copy
|
||||
import json
|
||||
import os
|
||||
import sqlite3
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
TRUTH_PATH = os.path.join(REPO, "src", "rust", "warm_neuron_store", "src",
|
||||
"frozen_wns_truth.json")
|
||||
TMP_ROOT = os.path.join(tempfile.gettempdir(), "wns_truth_fix")
|
||||
|
||||
REPLAY = "--replay" in sys.argv
|
||||
|
||||
sys.path.insert(0, os.path.join(REPO, "src", "rune"))
|
||||
import warm_neuron_store as oracle # noqa: E402
|
||||
|
||||
REAL_CONNECT = sqlite3.connect
|
||||
LIST_SQL = ("SELECT text, slug, triggers, importance FROM entries "
|
||||
"WHERE kind='neuron' AND status='active' ORDER BY slug")
|
||||
DIGEST_SQL = ("SELECT slug, text FROM entries "
|
||||
"WHERE kind='neuron' AND status='active'")
|
||||
|
||||
|
||||
def seed_db(path, rows):
|
||||
"""rows: dicts with text/slug/triggers/importance (raw SQL values,
|
||||
NULLs allowed) + optional kind/status for filter pins."""
|
||||
if os.path.exists(path):
|
||||
os.unlink(path)
|
||||
db = sqlite3.connect(path)
|
||||
db.execute(
|
||||
"CREATE TABLE entries (id INTEGER PRIMARY KEY AUTOINCREMENT, "
|
||||
"kind TEXT, status TEXT, slug TEXT, triggers TEXT, "
|
||||
"importance REAL, text TEXT)")
|
||||
for i, r in enumerate(rows):
|
||||
db.execute(
|
||||
"INSERT INTO entries (id, kind, status, slug, triggers, "
|
||||
"importance, text) VALUES (?,?,?,?,?,?,?)",
|
||||
(i + 1, r.get("kind", "neuron"), r.get("status", "active"),
|
||||
r.get("slug"), r.get("triggers"), r.get("importance"),
|
||||
r.get("text")))
|
||||
db.commit()
|
||||
db.close()
|
||||
|
||||
|
||||
def with_store(path):
|
||||
def deco(fn):
|
||||
def wrapper(*a, **kw):
|
||||
saved = oracle.STORE_DB
|
||||
oracle.STORE_DB = path
|
||||
try:
|
||||
return fn(*a, **kw)
|
||||
finally:
|
||||
oracle.STORE_DB = saved
|
||||
return wrapper
|
||||
return deco
|
||||
|
||||
|
||||
def oracle_rows(path):
|
||||
"""The SQL result rows, captured through the oracle's own `_db()`
|
||||
connection + its own SELECT (order = the DB's, preserved)."""
|
||||
db = with_store(path)(oracle._db)()
|
||||
try:
|
||||
rows = db.execute(LIST_SQL).fetchall()
|
||||
return [
|
||||
{"text": r["text"], "slug": r["slug"],
|
||||
"triggers": r["triggers"], "importance": r["importance"]}
|
||||
for r in rows]
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
def digest_rows(path):
|
||||
db = with_store(path)(oracle._db)()
|
||||
try:
|
||||
rows = db.execute(DIGEST_SQL).fetchall()
|
||||
return [{"slug": r["slug"], "text": r["text"]} for r in rows]
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
# ── scenarios ───────────────────────────────────────────────────────────────
|
||||
|
||||
def scenarios():
|
||||
"""(name, seed rows) — raw SQL values incl. NULLs/falsy."""
|
||||
return [
|
||||
("empty", []),
|
||||
("single-full", [
|
||||
{"slug": "deploy", "triggers": "deploy, build",
|
||||
"importance": 0.8, "text": "deployment stuff"},
|
||||
]),
|
||||
("order-by-slug", [
|
||||
{"slug": "zeta", "triggers": "z", "importance": 0.1, "text": "z body"},
|
||||
{"slug": "alpha", "triggers": "a", "importance": 0.9, "text": "a body"},
|
||||
{"slug": "mid", "triggers": "m", "importance": 0.5, "text": "m body"},
|
||||
]),
|
||||
("null-coalesce", [
|
||||
{"slug": None, "triggers": None, "importance": None, "text": None},
|
||||
]),
|
||||
("falsy-coalesce", [
|
||||
{"slug": "", "triggers": "", "importance": 0.0, "text": ""},
|
||||
{"slug": "kept", "triggers": " Kept , ,x ", "importance": 1.0,
|
||||
"text": " kept body "},
|
||||
]),
|
||||
("dupes-kept-and-overwrite", [
|
||||
{"slug": "same", "triggers": "t1", "importance": 0.3, "text": "first"},
|
||||
{"slug": "same", "triggers": "t2", "importance": 0.4, "text": "second"},
|
||||
{"slug": "aaa", "triggers": "", "importance": -1.5, "text": "neg"},
|
||||
]),
|
||||
("triggers-parse-unicode", [
|
||||
{"slug": "u", "triggers": " A , b ,c ,, ", "importance": 0.5,
|
||||
"text": "Grüße 世界"},
|
||||
]),
|
||||
("sql-filter-non-neuron-inactive", [
|
||||
{"slug": "live", "triggers": "l", "importance": 0.6, "text": "live body"},
|
||||
{"slug": "dead", "triggers": "d", "importance": 0.6,
|
||||
"text": "dead body", "status": "retired"},
|
||||
{"slug": "notneuron", "triggers": "n", "importance": 0.6,
|
||||
"text": "other kind", "kind": "memory"},
|
||||
]),
|
||||
]
|
||||
|
||||
|
||||
HAS_PROBES = [
|
||||
("ascii-case-text", "DEPLOYMENT"),
|
||||
("in-triggers", "Build"),
|
||||
("absent", "cooking"),
|
||||
("empty-term", ""),
|
||||
("none-term", None),
|
||||
("unicode-body", "grüße"),
|
||||
]
|
||||
|
||||
|
||||
def build_cases():
|
||||
root = TMP_ROOT
|
||||
os.makedirs(root, exist_ok=True)
|
||||
groups = {"list_neurons": [], "neuron_slugs": [], "neuron_digests": [],
|
||||
"neuron_has": [], "_db": [], "handle_hook": []}
|
||||
|
||||
for name, rows in scenarios():
|
||||
path = os.path.join(root, f"{name}.db")
|
||||
seed_db(path, rows)
|
||||
|
||||
captured = oracle_rows(path)
|
||||
inp = {"rows": copy.deepcopy(captured)}
|
||||
groups["list_neurons"].append({
|
||||
"name": name, "input": inp,
|
||||
"expected": with_store(path)(oracle.list_neurons)()})
|
||||
groups["neuron_slugs"].append({
|
||||
"name": name, "input": inp,
|
||||
"expected": with_store(path)(oracle.neuron_slugs)()})
|
||||
|
||||
if all(r["slug"] for r in digest_rows(path)) or not digest_rows(path):
|
||||
groups["neuron_digests"].append({
|
||||
"name": name,
|
||||
"input": {"rows": digest_rows(path)},
|
||||
"expected": with_store(path)(oracle.neuron_digests)()})
|
||||
|
||||
probes = []
|
||||
for pname, term in HAS_PROBES:
|
||||
probes.append({
|
||||
"name": pname, "term": term,
|
||||
"expected": with_store(path)(oracle.neuron_has)(term),
|
||||
})
|
||||
groups["neuron_has"].append({
|
||||
"name": name, "input": inp, "probes": probes})
|
||||
|
||||
# _db: the URI law captured from the LIVE connect() call
|
||||
captured = {}
|
||||
|
||||
def spy_connect(*a, **kw):
|
||||
captured["args"] = list(a)
|
||||
captured["kwargs"] = {k: v for k, v in kw.items()}
|
||||
return REAL_CONNECT(*a, **kw)
|
||||
|
||||
sqlite3.connect = spy_connect
|
||||
try:
|
||||
conn = with_store(os.path.join(root, "single-full.db"))(oracle._db)()
|
||||
row_factory_name = type(conn.row_factory).__name__
|
||||
readonly_err = None
|
||||
try:
|
||||
conn.execute("CREATE TABLE x (a)")
|
||||
except sqlite3.OperationalError as e:
|
||||
readonly_err = str(e)
|
||||
name_keyed = None
|
||||
try:
|
||||
row = conn.execute(LIST_SQL).fetchone()
|
||||
name_keyed = dict(row) if row is not None else None
|
||||
finally:
|
||||
conn.close()
|
||||
finally:
|
||||
sqlite3.connect = REAL_CONNECT
|
||||
|
||||
groups["_db"].append({
|
||||
"name": "uri-law",
|
||||
"input": {"store_db": "TMP/single-full.db"},
|
||||
"expected": {"uri": captured["args"][0].replace(root, "TMP"),
|
||||
"kwargs": captured["kwargs"]},
|
||||
"facade_only": {
|
||||
"row_factory": row_factory_name,
|
||||
"readonly_violation": readonly_err,
|
||||
"name_keyed_row": name_keyed,
|
||||
},
|
||||
})
|
||||
|
||||
# handle_hook: the event matrix
|
||||
for name, event, data in [
|
||||
("plain", "boot", {"k": 1}),
|
||||
("empty-event", "", None),
|
||||
("unicode", "événement", {"x": "世界"}),
|
||||
("data-ignored-shape", "scan", {"deep": {"a": [1, 2]}}),
|
||||
]:
|
||||
groups["handle_hook"].append({
|
||||
"name": name,
|
||||
"input": {"event": event, "data": data},
|
||||
"expected": oracle.handle_hook(event, data),
|
||||
})
|
||||
return groups
|
||||
|
||||
|
||||
def main():
|
||||
groups = build_cases()
|
||||
if REPLAY:
|
||||
with open(TRUTH_PATH) as f:
|
||||
frozen = json.load(f)["cases"]
|
||||
diverged = 0
|
||||
total = 0
|
||||
for g, cases in groups.items():
|
||||
old = {c["name"]: c for c in frozen.get(g, [])}
|
||||
for c in cases:
|
||||
total += 1
|
||||
o = old.get(c["name"])
|
||||
if o is None or json.dumps(c, sort_keys=True) != json.dumps(o, sort_keys=True):
|
||||
diverged += 1
|
||||
print(f"DIVERGE [{g}] {c['name']}")
|
||||
print(f"replay: {total - diverged}/{total} rows stable")
|
||||
return 1 if diverged else 0
|
||||
|
||||
doc = {
|
||||
"frozen": "warm-neuron-store-literal-100%",
|
||||
"oracle": "src/rune/warm_neuron_store.py",
|
||||
"note": "Frozen via scripts/gen_warm_neuron_store_truth.py against "
|
||||
"the LIVE oracle over real sqlite fixtures (STORE_DB "
|
||||
"patched; rows captured through the oracle's own _db() + "
|
||||
"SELECT). Kernel groups replay in cargo (branch_battery) "
|
||||
"and via the .so FFI (check_warm_neuron_store_parity.py). "
|
||||
"TMP/ normalizes fixture paths.",
|
||||
"cases": groups,
|
||||
}
|
||||
os.makedirs(os.path.dirname(TRUTH_PATH), exist_ok=True)
|
||||
with open(TRUTH_PATH, "w") as f:
|
||||
json.dump(doc, f, indent=1, ensure_ascii=False)
|
||||
f.write("\n")
|
||||
total = sum(len(v) for v in groups.values())
|
||||
print(f"frozen {total} cases -> {os.path.relpath(TRUTH_PATH, REPO)}")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -0,0 +1,164 @@
|
||||
//! branch_battery — replay the FROZEN oracle truth VERBATIM
|
||||
//! (frozen_wns_truth.json, generated by scripts/gen_warm_neuron_store_truth.py
|
||||
//! against the LIVE Python oracle over real sqlite fixtures: rows captured
|
||||
//! through the oracle's own `_db()` connection and SELECT).
|
||||
//!
|
||||
//! Groups: list_neurons / neuron_slugs / neuron_has / neuron_digests take
|
||||
//! the SQL result rows (the boundary law keeps SQL host-side);
|
||||
//! `_db` replays the URI law; handle_hook replays the event matrix with a
|
||||
//! key-ORDER pin (the oracle dict's insertion order: status, event,
|
||||
//! handler — serde structs serialize in declaration order).
|
||||
|
||||
use crate::{handle_hook, list_neurons, neuron_digests, neuron_has, neuron_slugs, WarmNeuron};
|
||||
use serde_json::Value;
|
||||
|
||||
const TRUTH: &str = include_str!("frozen_wns_truth.json");
|
||||
|
||||
fn group(name: &str) -> Vec<Value> {
|
||||
let truth: Value = serde_json::from_str(TRUTH).expect("frozen truth parses");
|
||||
truth["cases"][name]
|
||||
.as_array()
|
||||
.unwrap_or_else(|| panic!("truth group {name} missing"))
|
||||
.clone()
|
||||
}
|
||||
|
||||
fn rows_of(case: &Value) -> Vec<Value> {
|
||||
case["input"]["rows"]
|
||||
.as_array()
|
||||
.cloned()
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
fn neurons_of(rows: &[Value]) -> Vec<WarmNeuron> {
|
||||
list_neurons(rows)
|
||||
}
|
||||
|
||||
fn check(name: &str, got: Value, want: &Value) -> Result<(), String> {
|
||||
if got != *want {
|
||||
return Err(format!("[{name}] mismatch:\n got: {got}\n want: {want}"));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn battery_list_neurons() -> Result<usize, String> {
|
||||
let mut n = 0;
|
||||
for case in group("list_neurons") {
|
||||
let got = serde_json::to_value(neurons_of(&rows_of(&case))).map_err(|e| e.to_string())?;
|
||||
check(case["name"].as_str().unwrap_or("?"), got, &case["expected"])?;
|
||||
n += 1;
|
||||
}
|
||||
Ok(n)
|
||||
}
|
||||
|
||||
fn battery_neuron_slugs() -> Result<usize, String> {
|
||||
let mut n = 0;
|
||||
for case in group("neuron_slugs") {
|
||||
let got = serde_json::to_value(neuron_slugs(&neurons_of(&rows_of(&case))))
|
||||
.map_err(|e| e.to_string())?;
|
||||
check(case["name"].as_str().unwrap_or("?"), got, &case["expected"])?;
|
||||
n += 1;
|
||||
}
|
||||
Ok(n)
|
||||
}
|
||||
|
||||
fn battery_neuron_digests() -> Result<usize, String> {
|
||||
let mut n = 0;
|
||||
for case in group("neuron_digests") {
|
||||
// digest rows carry only slug/text (the oracle's digest SQL); the
|
||||
// projection through WarmNeuron keeps the last-wins overwrite law
|
||||
let neurons: Vec<WarmNeuron> = rows_of(&case)
|
||||
.into_iter()
|
||||
.map(|r| WarmNeuron {
|
||||
slug: r["slug"].as_str().unwrap_or_default().to_string(),
|
||||
text: r["text"].as_str().unwrap_or_default().to_string(),
|
||||
triggers: Vec::new(),
|
||||
importance: 0.0,
|
||||
})
|
||||
.collect();
|
||||
let got = serde_json::to_value(neuron_digests(&neurons)).map_err(|e| e.to_string())?;
|
||||
check(case["name"].as_str().unwrap_or("?"), got, &case["expected"])?;
|
||||
n += 1;
|
||||
}
|
||||
Ok(n)
|
||||
}
|
||||
|
||||
fn battery_neuron_has() -> Result<usize, String> {
|
||||
let mut n = 0;
|
||||
for case in group("neuron_has") {
|
||||
let neurons = neurons_of(&rows_of(&case));
|
||||
for probe in case["probes"].as_array().cloned().unwrap_or_default() {
|
||||
let term = probe["term"].as_str().unwrap_or("");
|
||||
let got = neuron_has(&neurons, term);
|
||||
check(
|
||||
&format!(
|
||||
"{}::{}",
|
||||
case["name"].as_str().unwrap_or("?"),
|
||||
probe["name"].as_str().unwrap_or("?")
|
||||
),
|
||||
Value::Bool(got),
|
||||
&probe["expected"],
|
||||
)?;
|
||||
n += 1;
|
||||
}
|
||||
}
|
||||
Ok(n)
|
||||
}
|
||||
|
||||
fn battery_db() -> Result<usize, String> {
|
||||
let mut n = 0;
|
||||
for case in group("_db") {
|
||||
let store_db = case["input"]["store_db"].as_str().unwrap_or_default();
|
||||
let db = crate::_db(store_db);
|
||||
check(
|
||||
case["name"].as_str().unwrap_or("?"),
|
||||
Value::String(db.uri),
|
||||
&case["expected"]["uri"],
|
||||
)?;
|
||||
assert_eq!(db.row_factory, crate::RowFactory::Row);
|
||||
n += 1;
|
||||
}
|
||||
Ok(n)
|
||||
}
|
||||
|
||||
fn battery_handle_hook() -> Result<usize, String> {
|
||||
let mut n = 0;
|
||||
for case in group("handle_hook") {
|
||||
let name = case["name"].as_str().unwrap_or("?").to_string();
|
||||
let event = case["input"]["event"].as_str().unwrap_or_default();
|
||||
let outcome = handle_hook(event, Some(case["input"]["data"].clone()));
|
||||
let got = serde_json::to_value(&outcome).map_err(|e| e.to_string())?;
|
||||
check(&name, got, &case["expected"])?;
|
||||
// key-ORDER pin: the oracle dict's insertion order is
|
||||
// status → event → handler; structs serialize in declaration order
|
||||
let bytes = serde_json::to_string(&outcome).map_err(|e| e.to_string())?;
|
||||
let (s, e, h) = (
|
||||
bytes.find("\"status\"").unwrap_or(usize::MAX),
|
||||
bytes.find("\"event\"").unwrap_or(usize::MAX),
|
||||
bytes.find("\"handler\"").unwrap_or(usize::MAX),
|
||||
);
|
||||
if !(s < e && e < h) {
|
||||
return Err(format!("[{name}] key order pin failed: {bytes}"));
|
||||
}
|
||||
n += 1;
|
||||
}
|
||||
Ok(n)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_frozen_truth_replay() {
|
||||
let mut total = 0;
|
||||
for (label, r) in [
|
||||
("list_neurons", battery_list_neurons()),
|
||||
("neuron_slugs", battery_neuron_slugs()),
|
||||
("neuron_digests", battery_neuron_digests()),
|
||||
("neuron_has", battery_neuron_has()),
|
||||
("_db", battery_db()),
|
||||
("handle_hook", battery_handle_hook()),
|
||||
] {
|
||||
match r {
|
||||
Ok(n) => total += n,
|
||||
Err(e) => panic!("battery[{label}]: {e}"),
|
||||
}
|
||||
}
|
||||
assert!(total >= 25, "truth too small: {total} cases (regenerate)");
|
||||
}
|
||||
@@ -0,0 +1,969 @@
|
||||
{
|
||||
"frozen": "warm-neuron-store-literal-100%",
|
||||
"oracle": "src/rune/warm_neuron_store.py",
|
||||
"note": "Frozen via scripts/gen_warm_neuron_store_truth.py against the LIVE oracle over real sqlite fixtures (STORE_DB patched; rows captured through the oracle's own _db() + SELECT). Kernel groups replay in cargo (branch_battery) and via the .so FFI (check_warm_neuron_store_parity.py). TMP/ normalizes fixture paths.",
|
||||
"cases": {
|
||||
"list_neurons": [
|
||||
{
|
||||
"name": "empty",
|
||||
"input": {
|
||||
"rows": []
|
||||
},
|
||||
"expected": []
|
||||
},
|
||||
{
|
||||
"name": "single-full",
|
||||
"input": {
|
||||
"rows": [
|
||||
{
|
||||
"text": "deployment stuff",
|
||||
"slug": "deploy",
|
||||
"triggers": "deploy, build",
|
||||
"importance": 0.8
|
||||
}
|
||||
]
|
||||
},
|
||||
"expected": [
|
||||
{
|
||||
"slug": "deploy",
|
||||
"triggers": [
|
||||
"deploy",
|
||||
"build"
|
||||
],
|
||||
"importance": 0.8,
|
||||
"text": "deployment stuff"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "order-by-slug",
|
||||
"input": {
|
||||
"rows": [
|
||||
{
|
||||
"text": "a body",
|
||||
"slug": "alpha",
|
||||
"triggers": "a",
|
||||
"importance": 0.9
|
||||
},
|
||||
{
|
||||
"text": "m body",
|
||||
"slug": "mid",
|
||||
"triggers": "m",
|
||||
"importance": 0.5
|
||||
},
|
||||
{
|
||||
"text": "z body",
|
||||
"slug": "zeta",
|
||||
"triggers": "z",
|
||||
"importance": 0.1
|
||||
}
|
||||
]
|
||||
},
|
||||
"expected": [
|
||||
{
|
||||
"slug": "alpha",
|
||||
"triggers": [
|
||||
"a"
|
||||
],
|
||||
"importance": 0.9,
|
||||
"text": "a body"
|
||||
},
|
||||
{
|
||||
"slug": "mid",
|
||||
"triggers": [
|
||||
"m"
|
||||
],
|
||||
"importance": 0.5,
|
||||
"text": "m body"
|
||||
},
|
||||
{
|
||||
"slug": "zeta",
|
||||
"triggers": [
|
||||
"z"
|
||||
],
|
||||
"importance": 0.1,
|
||||
"text": "z body"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "null-coalesce",
|
||||
"input": {
|
||||
"rows": [
|
||||
{
|
||||
"text": null,
|
||||
"slug": null,
|
||||
"triggers": null,
|
||||
"importance": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"expected": [
|
||||
{
|
||||
"slug": "warm",
|
||||
"triggers": [],
|
||||
"importance": 0.5,
|
||||
"text": ""
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "falsy-coalesce",
|
||||
"input": {
|
||||
"rows": [
|
||||
{
|
||||
"text": "",
|
||||
"slug": "",
|
||||
"triggers": "",
|
||||
"importance": 0.0
|
||||
},
|
||||
{
|
||||
"text": " kept body ",
|
||||
"slug": "kept",
|
||||
"triggers": " Kept , ,x ",
|
||||
"importance": 1.0
|
||||
}
|
||||
]
|
||||
},
|
||||
"expected": [
|
||||
{
|
||||
"slug": "warm",
|
||||
"triggers": [],
|
||||
"importance": 0.5,
|
||||
"text": ""
|
||||
},
|
||||
{
|
||||
"slug": "kept",
|
||||
"triggers": [
|
||||
"kept",
|
||||
"x"
|
||||
],
|
||||
"importance": 1.0,
|
||||
"text": "kept body"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "dupes-kept-and-overwrite",
|
||||
"input": {
|
||||
"rows": [
|
||||
{
|
||||
"text": "neg",
|
||||
"slug": "aaa",
|
||||
"triggers": "",
|
||||
"importance": -1.5
|
||||
},
|
||||
{
|
||||
"text": "first",
|
||||
"slug": "same",
|
||||
"triggers": "t1",
|
||||
"importance": 0.3
|
||||
},
|
||||
{
|
||||
"text": "second",
|
||||
"slug": "same",
|
||||
"triggers": "t2",
|
||||
"importance": 0.4
|
||||
}
|
||||
]
|
||||
},
|
||||
"expected": [
|
||||
{
|
||||
"slug": "aaa",
|
||||
"triggers": [],
|
||||
"importance": -1.5,
|
||||
"text": "neg"
|
||||
},
|
||||
{
|
||||
"slug": "same",
|
||||
"triggers": [
|
||||
"t1"
|
||||
],
|
||||
"importance": 0.3,
|
||||
"text": "first"
|
||||
},
|
||||
{
|
||||
"slug": "same",
|
||||
"triggers": [
|
||||
"t2"
|
||||
],
|
||||
"importance": 0.4,
|
||||
"text": "second"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "triggers-parse-unicode",
|
||||
"input": {
|
||||
"rows": [
|
||||
{
|
||||
"text": "Grüße 世界",
|
||||
"slug": "u",
|
||||
"triggers": " A , b ,c ,, ",
|
||||
"importance": 0.5
|
||||
}
|
||||
]
|
||||
},
|
||||
"expected": [
|
||||
{
|
||||
"slug": "u",
|
||||
"triggers": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"importance": 0.5,
|
||||
"text": "Grüße 世界"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "sql-filter-non-neuron-inactive",
|
||||
"input": {
|
||||
"rows": [
|
||||
{
|
||||
"text": "live body",
|
||||
"slug": "live",
|
||||
"triggers": "l",
|
||||
"importance": 0.6
|
||||
}
|
||||
]
|
||||
},
|
||||
"expected": [
|
||||
{
|
||||
"slug": "live",
|
||||
"triggers": [
|
||||
"l"
|
||||
],
|
||||
"importance": 0.6,
|
||||
"text": "live body"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"neuron_slugs": [
|
||||
{
|
||||
"name": "empty",
|
||||
"input": {
|
||||
"rows": []
|
||||
},
|
||||
"expected": []
|
||||
},
|
||||
{
|
||||
"name": "single-full",
|
||||
"input": {
|
||||
"rows": [
|
||||
{
|
||||
"text": "deployment stuff",
|
||||
"slug": "deploy",
|
||||
"triggers": "deploy, build",
|
||||
"importance": 0.8
|
||||
}
|
||||
]
|
||||
},
|
||||
"expected": [
|
||||
"deploy"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "order-by-slug",
|
||||
"input": {
|
||||
"rows": [
|
||||
{
|
||||
"text": "a body",
|
||||
"slug": "alpha",
|
||||
"triggers": "a",
|
||||
"importance": 0.9
|
||||
},
|
||||
{
|
||||
"text": "m body",
|
||||
"slug": "mid",
|
||||
"triggers": "m",
|
||||
"importance": 0.5
|
||||
},
|
||||
{
|
||||
"text": "z body",
|
||||
"slug": "zeta",
|
||||
"triggers": "z",
|
||||
"importance": 0.1
|
||||
}
|
||||
]
|
||||
},
|
||||
"expected": [
|
||||
"alpha",
|
||||
"mid",
|
||||
"zeta"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "null-coalesce",
|
||||
"input": {
|
||||
"rows": [
|
||||
{
|
||||
"text": null,
|
||||
"slug": null,
|
||||
"triggers": null,
|
||||
"importance": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"expected": [
|
||||
"warm"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "falsy-coalesce",
|
||||
"input": {
|
||||
"rows": [
|
||||
{
|
||||
"text": "",
|
||||
"slug": "",
|
||||
"triggers": "",
|
||||
"importance": 0.0
|
||||
},
|
||||
{
|
||||
"text": " kept body ",
|
||||
"slug": "kept",
|
||||
"triggers": " Kept , ,x ",
|
||||
"importance": 1.0
|
||||
}
|
||||
]
|
||||
},
|
||||
"expected": [
|
||||
"kept",
|
||||
"warm"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "dupes-kept-and-overwrite",
|
||||
"input": {
|
||||
"rows": [
|
||||
{
|
||||
"text": "neg",
|
||||
"slug": "aaa",
|
||||
"triggers": "",
|
||||
"importance": -1.5
|
||||
},
|
||||
{
|
||||
"text": "first",
|
||||
"slug": "same",
|
||||
"triggers": "t1",
|
||||
"importance": 0.3
|
||||
},
|
||||
{
|
||||
"text": "second",
|
||||
"slug": "same",
|
||||
"triggers": "t2",
|
||||
"importance": 0.4
|
||||
}
|
||||
]
|
||||
},
|
||||
"expected": [
|
||||
"aaa",
|
||||
"same",
|
||||
"same"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "triggers-parse-unicode",
|
||||
"input": {
|
||||
"rows": [
|
||||
{
|
||||
"text": "Grüße 世界",
|
||||
"slug": "u",
|
||||
"triggers": " A , b ,c ,, ",
|
||||
"importance": 0.5
|
||||
}
|
||||
]
|
||||
},
|
||||
"expected": [
|
||||
"u"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "sql-filter-non-neuron-inactive",
|
||||
"input": {
|
||||
"rows": [
|
||||
{
|
||||
"text": "live body",
|
||||
"slug": "live",
|
||||
"triggers": "l",
|
||||
"importance": 0.6
|
||||
}
|
||||
]
|
||||
},
|
||||
"expected": [
|
||||
"live"
|
||||
]
|
||||
}
|
||||
],
|
||||
"neuron_digests": [
|
||||
{
|
||||
"name": "empty",
|
||||
"input": {
|
||||
"rows": []
|
||||
},
|
||||
"expected": {}
|
||||
},
|
||||
{
|
||||
"name": "single-full",
|
||||
"input": {
|
||||
"rows": [
|
||||
{
|
||||
"slug": "deploy",
|
||||
"text": "deployment stuff"
|
||||
}
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"deploy": "deployment stuff"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "order-by-slug",
|
||||
"input": {
|
||||
"rows": [
|
||||
{
|
||||
"slug": "zeta",
|
||||
"text": "z body"
|
||||
},
|
||||
{
|
||||
"slug": "alpha",
|
||||
"text": "a body"
|
||||
},
|
||||
{
|
||||
"slug": "mid",
|
||||
"text": "m body"
|
||||
}
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"zeta": "z body",
|
||||
"alpha": "a body",
|
||||
"mid": "m body"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "dupes-kept-and-overwrite",
|
||||
"input": {
|
||||
"rows": [
|
||||
{
|
||||
"slug": "same",
|
||||
"text": "first"
|
||||
},
|
||||
{
|
||||
"slug": "same",
|
||||
"text": "second"
|
||||
},
|
||||
{
|
||||
"slug": "aaa",
|
||||
"text": "neg"
|
||||
}
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"same": "second",
|
||||
"aaa": "neg"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "triggers-parse-unicode",
|
||||
"input": {
|
||||
"rows": [
|
||||
{
|
||||
"slug": "u",
|
||||
"text": "Grüße 世界"
|
||||
}
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"u": "Grüße 世界"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "sql-filter-non-neuron-inactive",
|
||||
"input": {
|
||||
"rows": [
|
||||
{
|
||||
"slug": "live",
|
||||
"text": "live body"
|
||||
}
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"live": "live body"
|
||||
}
|
||||
}
|
||||
],
|
||||
"neuron_has": [
|
||||
{
|
||||
"name": "empty",
|
||||
"input": {
|
||||
"rows": []
|
||||
},
|
||||
"probes": [
|
||||
{
|
||||
"name": "ascii-case-text",
|
||||
"term": "DEPLOYMENT",
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "in-triggers",
|
||||
"term": "Build",
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "absent",
|
||||
"term": "cooking",
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "empty-term",
|
||||
"term": "",
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "none-term",
|
||||
"term": null,
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "unicode-body",
|
||||
"term": "grüße",
|
||||
"expected": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "single-full",
|
||||
"input": {
|
||||
"rows": [
|
||||
{
|
||||
"text": "deployment stuff",
|
||||
"slug": "deploy",
|
||||
"triggers": "deploy, build",
|
||||
"importance": 0.8
|
||||
}
|
||||
]
|
||||
},
|
||||
"probes": [
|
||||
{
|
||||
"name": "ascii-case-text",
|
||||
"term": "DEPLOYMENT",
|
||||
"expected": true
|
||||
},
|
||||
{
|
||||
"name": "in-triggers",
|
||||
"term": "Build",
|
||||
"expected": true
|
||||
},
|
||||
{
|
||||
"name": "absent",
|
||||
"term": "cooking",
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "empty-term",
|
||||
"term": "",
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "none-term",
|
||||
"term": null,
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "unicode-body",
|
||||
"term": "grüße",
|
||||
"expected": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "order-by-slug",
|
||||
"input": {
|
||||
"rows": [
|
||||
{
|
||||
"text": "a body",
|
||||
"slug": "alpha",
|
||||
"triggers": "a",
|
||||
"importance": 0.9
|
||||
},
|
||||
{
|
||||
"text": "m body",
|
||||
"slug": "mid",
|
||||
"triggers": "m",
|
||||
"importance": 0.5
|
||||
},
|
||||
{
|
||||
"text": "z body",
|
||||
"slug": "zeta",
|
||||
"triggers": "z",
|
||||
"importance": 0.1
|
||||
}
|
||||
]
|
||||
},
|
||||
"probes": [
|
||||
{
|
||||
"name": "ascii-case-text",
|
||||
"term": "DEPLOYMENT",
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "in-triggers",
|
||||
"term": "Build",
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "absent",
|
||||
"term": "cooking",
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "empty-term",
|
||||
"term": "",
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "none-term",
|
||||
"term": null,
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "unicode-body",
|
||||
"term": "grüße",
|
||||
"expected": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "null-coalesce",
|
||||
"input": {
|
||||
"rows": [
|
||||
{
|
||||
"text": null,
|
||||
"slug": null,
|
||||
"triggers": null,
|
||||
"importance": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"probes": [
|
||||
{
|
||||
"name": "ascii-case-text",
|
||||
"term": "DEPLOYMENT",
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "in-triggers",
|
||||
"term": "Build",
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "absent",
|
||||
"term": "cooking",
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "empty-term",
|
||||
"term": "",
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "none-term",
|
||||
"term": null,
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "unicode-body",
|
||||
"term": "grüße",
|
||||
"expected": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "falsy-coalesce",
|
||||
"input": {
|
||||
"rows": [
|
||||
{
|
||||
"text": "",
|
||||
"slug": "",
|
||||
"triggers": "",
|
||||
"importance": 0.0
|
||||
},
|
||||
{
|
||||
"text": " kept body ",
|
||||
"slug": "kept",
|
||||
"triggers": " Kept , ,x ",
|
||||
"importance": 1.0
|
||||
}
|
||||
]
|
||||
},
|
||||
"probes": [
|
||||
{
|
||||
"name": "ascii-case-text",
|
||||
"term": "DEPLOYMENT",
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "in-triggers",
|
||||
"term": "Build",
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "absent",
|
||||
"term": "cooking",
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "empty-term",
|
||||
"term": "",
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "none-term",
|
||||
"term": null,
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "unicode-body",
|
||||
"term": "grüße",
|
||||
"expected": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "dupes-kept-and-overwrite",
|
||||
"input": {
|
||||
"rows": [
|
||||
{
|
||||
"text": "neg",
|
||||
"slug": "aaa",
|
||||
"triggers": "",
|
||||
"importance": -1.5
|
||||
},
|
||||
{
|
||||
"text": "first",
|
||||
"slug": "same",
|
||||
"triggers": "t1",
|
||||
"importance": 0.3
|
||||
},
|
||||
{
|
||||
"text": "second",
|
||||
"slug": "same",
|
||||
"triggers": "t2",
|
||||
"importance": 0.4
|
||||
}
|
||||
]
|
||||
},
|
||||
"probes": [
|
||||
{
|
||||
"name": "ascii-case-text",
|
||||
"term": "DEPLOYMENT",
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "in-triggers",
|
||||
"term": "Build",
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "absent",
|
||||
"term": "cooking",
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "empty-term",
|
||||
"term": "",
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "none-term",
|
||||
"term": null,
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "unicode-body",
|
||||
"term": "grüße",
|
||||
"expected": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "triggers-parse-unicode",
|
||||
"input": {
|
||||
"rows": [
|
||||
{
|
||||
"text": "Grüße 世界",
|
||||
"slug": "u",
|
||||
"triggers": " A , b ,c ,, ",
|
||||
"importance": 0.5
|
||||
}
|
||||
]
|
||||
},
|
||||
"probes": [
|
||||
{
|
||||
"name": "ascii-case-text",
|
||||
"term": "DEPLOYMENT",
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "in-triggers",
|
||||
"term": "Build",
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "absent",
|
||||
"term": "cooking",
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "empty-term",
|
||||
"term": "",
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "none-term",
|
||||
"term": null,
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "unicode-body",
|
||||
"term": "grüße",
|
||||
"expected": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "sql-filter-non-neuron-inactive",
|
||||
"input": {
|
||||
"rows": [
|
||||
{
|
||||
"text": "live body",
|
||||
"slug": "live",
|
||||
"triggers": "l",
|
||||
"importance": 0.6
|
||||
}
|
||||
]
|
||||
},
|
||||
"probes": [
|
||||
{
|
||||
"name": "ascii-case-text",
|
||||
"term": "DEPLOYMENT",
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "in-triggers",
|
||||
"term": "Build",
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "absent",
|
||||
"term": "cooking",
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "empty-term",
|
||||
"term": "",
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "none-term",
|
||||
"term": null,
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "unicode-body",
|
||||
"term": "grüße",
|
||||
"expected": false
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"_db": [
|
||||
{
|
||||
"name": "uri-law",
|
||||
"input": {
|
||||
"store_db": "TMP/single-full.db"
|
||||
},
|
||||
"expected": {
|
||||
"uri": "file:TMP/single-full.db?mode=ro",
|
||||
"kwargs": {
|
||||
"uri": true
|
||||
}
|
||||
},
|
||||
"facade_only": {
|
||||
"row_factory": "type",
|
||||
"readonly_violation": "attempt to write a readonly database",
|
||||
"name_keyed_row": {
|
||||
"text": "deployment stuff",
|
||||
"slug": "deploy",
|
||||
"triggers": "deploy, build",
|
||||
"importance": 0.8
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"handle_hook": [
|
||||
{
|
||||
"name": "plain",
|
||||
"input": {
|
||||
"event": "boot",
|
||||
"data": {
|
||||
"k": 1
|
||||
}
|
||||
},
|
||||
"expected": {
|
||||
"status": "ok",
|
||||
"event": "boot",
|
||||
"handler": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "empty-event",
|
||||
"input": {
|
||||
"event": "",
|
||||
"data": null
|
||||
},
|
||||
"expected": {
|
||||
"status": "ok",
|
||||
"event": "",
|
||||
"handler": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "unicode",
|
||||
"input": {
|
||||
"event": "événement",
|
||||
"data": {
|
||||
"x": "世界"
|
||||
}
|
||||
},
|
||||
"expected": {
|
||||
"status": "ok",
|
||||
"event": "événement",
|
||||
"handler": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "data-ignored-shape",
|
||||
"input": {
|
||||
"event": "scan",
|
||||
"data": {
|
||||
"deep": {
|
||||
"a": [
|
||||
1,
|
||||
2
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"expected": {
|
||||
"status": "ok",
|
||||
"event": "scan",
|
||||
"handler": "default"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -11,25 +11,33 @@ pub struct WarmNeuron {
|
||||
}
|
||||
|
||||
/// All active warm neurons from the store
|
||||
///
|
||||
/// Falsy-coerce law (battery-proved, falsy-coalesce row): the oracle's
|
||||
/// `row["slug"] or "warm"` / `float(row["importance"] or 0.5)` coerce
|
||||
/// not just NULL but FALTY values — empty-string slug → "warm",
|
||||
/// 0.0 importance → 0.5 (Python `or` semantics, drift_compression
|
||||
/// warn_before_compress sibling).
|
||||
#[allow(clippy::unnecessary_filter_map)] // pinned: the filter_map(|row|) mirrors the oracle row-coalesce expression
|
||||
pub fn list_neurons(rows: &[serde_json::Value]) -> Vec<WarmNeuron> {
|
||||
rows.iter()
|
||||
.filter_map(|row| {
|
||||
let slug = row
|
||||
.get("slug")
|
||||
.and_then(|s| s.as_str())
|
||||
.unwrap_or("warm")
|
||||
.to_string();
|
||||
let slug_raw = row.get("slug").and_then(|s| s.as_str()).unwrap_or("");
|
||||
let slug = if slug_raw.is_empty() {
|
||||
"warm".to_string()
|
||||
} else {
|
||||
slug_raw.to_string()
|
||||
};
|
||||
let text = row
|
||||
.get("text")
|
||||
.and_then(|t| t.as_str())
|
||||
.unwrap_or("")
|
||||
.trim()
|
||||
.to_string();
|
||||
let importance = row
|
||||
.get("importance")
|
||||
.and_then(|i| i.as_f64())
|
||||
.unwrap_or(0.5);
|
||||
let importance_raw = row.get("importance").and_then(|i| i.as_f64());
|
||||
let importance = match importance_raw {
|
||||
None | Some(0.0) => 0.5,
|
||||
Some(v) => v,
|
||||
};
|
||||
let triggers_str = row.get("triggers").and_then(|t| t.as_str()).unwrap_or("");
|
||||
let triggers: Vec<String> = triggers_str
|
||||
.split(',')
|
||||
@@ -66,6 +74,194 @@ pub fn neuron_digests(neurons: &[WarmNeuron]) -> std::collections::HashMap<Strin
|
||||
.collect()
|
||||
}
|
||||
|
||||
// ── literal-100% residue: _db / neuron_slugs / handle_hook ──────────────
|
||||
|
||||
/// The row_factory contract the oracle's `_db()` installs: sqlite3.Row —
|
||||
/// name-keyed access (row["slug"]), the shape every kernel here consumes.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum RowFactory {
|
||||
Row,
|
||||
}
|
||||
|
||||
/// The read-only connection handle the oracle's `_db()` returns, with the
|
||||
/// sqlite OPEN peeled off (boundary law: SQL stays host-side). Carries the
|
||||
/// resolved URI and the row_factory contract; the oracle's close-and-raise
|
||||
/// arm (row_factory assignment failure) is unreachable for sqlite3.Row in
|
||||
/// practice — belt-and-braces Python, nothing to port.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct WnsDb {
|
||||
pub uri: String,
|
||||
pub row_factory: RowFactory,
|
||||
}
|
||||
|
||||
/// `_db` — the read-only connection law: the oracle builds
|
||||
/// `sqlite3.connect(f"file:{STORE_DB}?mode=ro", uri=True)` and installs
|
||||
/// row_factory=sqlite3.Row. The open itself is host IO; this is its
|
||||
/// decision law (URI shape + row contract), name-preserving.
|
||||
pub fn _db(store_db: &str) -> WnsDb {
|
||||
WnsDb {
|
||||
uri: format!("file:{store_db}?mode=ro"),
|
||||
row_factory: RowFactory::Row,
|
||||
}
|
||||
}
|
||||
|
||||
/// `neuron_slugs` — `sorted(n["slug"] for n in list_neurons())`: the
|
||||
/// coalesced slugs, sorted, DUPLICATES retained (one entry per neuron).
|
||||
/// Python sorted() on str is codepoint order; Rust String Ord is UTF-8
|
||||
/// byte order — identical orderings.
|
||||
pub fn neuron_slugs(neurons: &[WarmNeuron]) -> Vec<String> {
|
||||
let mut slugs: Vec<String> = neurons.iter().map(|n| n.slug.clone()).collect();
|
||||
slugs.sort();
|
||||
slugs
|
||||
}
|
||||
|
||||
/// `handle_hook` outcome — field order is the oracle's dict insertion
|
||||
/// order (status, event, handler); serde struct fields serialize in
|
||||
/// declaration order, keeping the byte form faithful.
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct HookOutcome {
|
||||
pub status: String,
|
||||
pub event: String,
|
||||
pub handler: String,
|
||||
}
|
||||
|
||||
/// `handle_hook` — literal parity: every event (incl. the empty string)
|
||||
/// answers ok with the event echoed and the default handler; `data` rides
|
||||
/// through untouched (never read). The Go voicebox crate's empty-event
|
||||
/// validation IMPROVEMENT is deliberately NOT mirrored here.
|
||||
pub fn handle_hook(event: &str, _data: Option<Value>) -> HookOutcome {
|
||||
HookOutcome {
|
||||
status: "ok".to_string(),
|
||||
event: event.to_string(),
|
||||
handler: "default".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
// ── FFI (doc-envelope law: {"ok":true,"value":…}/{"ok":false,"err":…}) ──
|
||||
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::os::raw::c_char;
|
||||
|
||||
use serde_json::Value;
|
||||
|
||||
fn wns_err(msg: impl Into<String>) -> String {
|
||||
msg.into()
|
||||
}
|
||||
|
||||
fn read_arg(ptr: *const c_char) -> Result<Value, String> {
|
||||
if ptr.is_null() {
|
||||
return Err(wns_err("null arg"));
|
||||
}
|
||||
let s = unsafe { CStr::from_ptr(ptr) }
|
||||
.to_str()
|
||||
.map_err(|e| wns_err(e.to_string()))?;
|
||||
serde_json::from_str(s).map_err(|e| wns_err(e.to_string()))
|
||||
}
|
||||
|
||||
fn envelope(r: Result<Value, String>) -> *mut c_char {
|
||||
let v = match r {
|
||||
Ok(value) => serde_json::json!({"ok": true, "value": value}),
|
||||
Err(e) => serde_json::json!({"ok": false, "err": e}),
|
||||
};
|
||||
match CString::new(serde_json::to_string(&v).unwrap_or_default()) {
|
||||
Ok(s) => s.into_raw(),
|
||||
Err(_) => CString::new("{\"ok\":false,\"err\":\"envelope nul\"}")
|
||||
.unwrap()
|
||||
.into_raw(),
|
||||
}
|
||||
}
|
||||
|
||||
fn opt_str<'a>(arg: &'a Value, key: &str) -> Option<&'a str> {
|
||||
arg.get(key).and_then(Value::as_str)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wns_list_neurons(arg: *const c_char) -> *mut c_char {
|
||||
let r = read_arg(arg).and_then(|a| {
|
||||
let rows = a
|
||||
.as_array()
|
||||
.ok_or_else(|| wns_err("arg must be a rows array"))?;
|
||||
Ok(serde_json::to_value(list_neurons(rows)).unwrap_or(Value::Null))
|
||||
});
|
||||
envelope(r)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wns_neuron_slugs(arg: *const c_char) -> *mut c_char {
|
||||
let r = read_arg(arg).and_then(|a| {
|
||||
let rows = a
|
||||
.as_array()
|
||||
.ok_or_else(|| wns_err("arg must be a rows array"))?;
|
||||
Ok(serde_json::to_value(neuron_slugs(&list_neurons(rows))).unwrap_or(Value::Null))
|
||||
});
|
||||
envelope(r)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wns_db(arg: *const c_char) -> *mut c_char {
|
||||
let r = read_arg(arg).and_then(|a| {
|
||||
let store_db = opt_str(&a, "store_db").ok_or_else(|| wns_err("arg.store_db required"))?;
|
||||
Ok(serde_json::json!({"uri": _db(store_db).uri}))
|
||||
});
|
||||
envelope(r)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wns_neuron_has(arg: *const c_char) -> *mut c_char {
|
||||
let r = read_arg(arg).and_then(|a| {
|
||||
let rows = a
|
||||
.get("rows")
|
||||
.and_then(Value::as_array)
|
||||
.ok_or_else(|| wns_err("arg.rows required"))?;
|
||||
let term = opt_str(&a, "term").unwrap_or("");
|
||||
Ok(Value::Bool(neuron_has(&list_neurons(rows), term)))
|
||||
});
|
||||
envelope(r)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wns_neuron_digests(arg: *const c_char) -> *mut c_char {
|
||||
let r = read_arg(arg).and_then(|a| {
|
||||
let rows = a
|
||||
.as_array()
|
||||
.ok_or_else(|| wns_err("arg must be a rows array"))?;
|
||||
// digest rows carry only slug/text; project onto the neuron shape
|
||||
// (the oracle's digest SQL selects exactly those two columns)
|
||||
let neurons: Vec<WarmNeuron> = rows
|
||||
.iter()
|
||||
.map(|r| WarmNeuron {
|
||||
slug: r
|
||||
.get("slug")
|
||||
.and_then(Value::as_str)
|
||||
.unwrap_or_default()
|
||||
.to_string(),
|
||||
text: r
|
||||
.get("text")
|
||||
.and_then(Value::as_str)
|
||||
.unwrap_or_default()
|
||||
.to_string(),
|
||||
triggers: Vec::new(),
|
||||
importance: 0.0,
|
||||
})
|
||||
.collect();
|
||||
serde_json::to_value(neuron_digests(&neurons)).map_err(|e| wns_err(e.to_string()))
|
||||
});
|
||||
envelope(r)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wns_handle_hook(arg: *const c_char) -> *mut c_char {
|
||||
let r = read_arg(arg).and_then(|a| {
|
||||
let event = opt_str(&a, "event").unwrap_or("");
|
||||
serde_json::to_value(handle_hook(event, a.get("data").cloned()))
|
||||
.map_err(|e| wns_err(e.to_string()))
|
||||
});
|
||||
envelope(r)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod branch_battery;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
rc=1
|
||||
@@ -0,0 +1 @@
|
||||
rc=1
|
||||
@@ -0,0 +1 @@
|
||||
rc=0
|
||||
@@ -0,0 +1 @@
|
||||
rc=0
|
||||
@@ -0,0 +1 @@
|
||||
rc=0
|
||||
@@ -0,0 +1 @@
|
||||
rc=0
|
||||
@@ -0,0 +1,2 @@
|
||||
REGEN-BYTE-IDENTICAL
|
||||
replay-stability rc=0
|
||||
@@ -0,0 +1 @@
|
||||
rc=0
|
||||
@@ -0,0 +1 @@
|
||||
pin rc=0
|
||||
@@ -0,0 +1 @@
|
||||
live rc=0
|
||||
@@ -0,0 +1,68 @@
|
||||
# warm_neuron_store — literal-100% residue verification summary (rune-wave-f2)
|
||||
|
||||
Module: warm_neuron_store (RUST). Oracle: src/rune/warm_neuron_store.py
|
||||
(122L, 6 fns, was 3/6). Residue ported name-preserving into the EXISTING
|
||||
crate (src/rust/warm_neuron_store): _db (read-only connection law with the
|
||||
sqlite open peeled off — WnsDb{uri, row_factory=Row}, drift_observability
|
||||
_load_alerts boundary pattern), neuron_slugs (sorted coalesced slugs,
|
||||
duplicates retained), handle_hook (HookOutcome struct — field order = the
|
||||
oracle dict's insertion order status/event/handler; literal parity, the
|
||||
Go voicebox crate's empty-event improvement deliberately NOT mirrored).
|
||||
|
||||
## DEFECT FOUND+FIXED (fix-first, battery-proved)
|
||||
The W6-era list_neurons kept FALSY values where the oracle's `or`-coerce
|
||||
law substitutes defaults: slug "" → "warm", importance 0.0 → 0.5
|
||||
(falsy-coalesce truth row failed the battery pre-fix: got slug ""/
|
||||
importance 0.0, want "warm"/0.5). Fixed to the oracle law — same class
|
||||
as drift_compression's warn_before_compress (documented in lib.rs).
|
||||
|
||||
## Changes
|
||||
- src/rust/warm_neuron_store/src/lib.rs — the three ports + WnsDb/
|
||||
RowFactory/HookOutcome + 6 FFI wrappers (wns_list_neurons,
|
||||
wns_neuron_slugs, wns_neuron_has, wns_neuron_digests, wns_db,
|
||||
wns_handle_hook; doc-envelope law) + the list_neurons falsy fix.
|
||||
- src/rust/warm_neuron_store/src/branch_battery.rs — NEW frozen-truth
|
||||
replay (list/slugs/digests/has/_db uri/handle_hook incl. key-ORDER pin).
|
||||
- src/rust/warm_neuron_store/src/frozen_wns_truth.json — NEW (35 rows:
|
||||
8 scenario groups incl. null-coalesce, falsy-coalesce, dupes-overwrite,
|
||||
triggers-parse-unicode, sql-filter; 6 neuron_has probes × scenarios;
|
||||
_db uri-law + facade connection proofs; 4 handle_hook rows).
|
||||
- scripts/gen_warm_neuron_store_truth.py — freeze/replay generator (real
|
||||
sqlite fixtures; rows captured through the oracle's OWN _db() + SELECT
|
||||
with STORE_DB patched; _db uri captured from a spied LIVE connect()).
|
||||
- scripts/check_warm_neuron_store_parity.py — live parity sweep (ctypes
|
||||
FFI vs live oracle, 76 checks + negative control).
|
||||
|
||||
## Verification (all in this checkout)
|
||||
- Freeze: frozen 35 rows; regen x2 BYTE-IDENTICAL; --replay 35/35 stable
|
||||
(wns-freeze-verify.txt). Shared-harness --verify N/A: grouped rig truth
|
||||
(regen-stability + battery + live parity are the gates, project_
|
||||
registry precedent).
|
||||
- cargo battery 4/4 green incl. branch_battery (wns-cargo-test rc=0);
|
||||
clippy --all-targets -D warnings clean; cargo fmt --check clean;
|
||||
cargo build --release clean (wns-clippy/fmt/cargo-build rc=0).
|
||||
- LIVE PARITY 100%: 76/76 (wns-parity.log, rc=0) — kernel FFI vs live
|
||||
oracle over every scenario + _db live-connect proofs + handle_hook;
|
||||
negative control detected all 4 planted perturbations (a sweep that
|
||||
cannot fail is not a parity check).
|
||||
- Python both pins: canary verbose ✓ Import warm_neuron_store +
|
||||
✓ list_neurons() + ✓ neuron_slugs() (the residue fn, live) BOTH pins,
|
||||
failure sets identical (wns-canary-{live,pin}.log; 3 remaining canary
|
||||
failures are sibling .so contracts — witness/claim_audit — unrelated).
|
||||
Adjacent pytest test_p1_03_memory_selection.py: 67 passed/1 skipped
|
||||
BOTH pins (wns-pytest-adjacent{,-pin} rc=0). No RUNE_WNS_CORE loader
|
||||
exists (module has no delegation chain) — the pin var is inert, runs
|
||||
green both ways regardless.
|
||||
- ruff clean on both new scripts.
|
||||
- Audit delta: warm_neuron_store 3/6 → 6/6 (missing list empty).
|
||||
|
||||
## Divergences (documented, not bugs)
|
||||
- neuron_has: oracle SQL LIKE is ASCII-case-insensitive; the crate folds
|
||||
unicode-wide (to_lowercase). Truth/parity rows stay in the ASCII
|
||||
agreement domain (no %/_ wildcards in terms) — W6-era surface, not
|
||||
residue; unicode-fold + wildcard boundaries documented here.
|
||||
- neuron_digests on a NULL slug would build a {None: text} dict that
|
||||
cannot cross JSON (oracle json crash class) — digest scenarios use
|
||||
non-null slugs; "" slug coerces to "warm" via the list_neurons law.
|
||||
- _db's close-and-raise arm (row_factory assignment failure) is
|
||||
unreachable for sqlite3.Row — belt-and-braces Python, nothing to port.
|
||||
Reference in new issue
Block a user