local-review.yml (push) Invalid workflow file
Auto-version and Release / release (push) Successful in 9s
CI Pipeline / lint (push) Failing after 28s
CI Pipeline / go-surface (push) Failing after 18s
CI Pipeline / rust-surface (push) Successful in 4m8s
CI Pipeline / canary (push) Failing after 1m4s
CI Pipeline / best-practices (push) Successful in 6s
CI Pipeline / documentation (push) Successful in 7s
CI Pipeline / type-check (push) Failing after 35s
CI Pipeline / gitea-offline (push) Successful in 18s
CI Pipeline / unit-tests (push) Failing after 8m14s
deploy / deploy (push) Failing after 15m11s
CI Pipeline / required-checks (push) Failing after 1s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Failing after 9s
- ci.yml: query_memory in ALL THREE rust build lists + a shadow step. - scripts/qm_shadow.py: the honest shadow — the TRUE pre-shim Python oracle (recovered from git history 6f44a87~1 — the parity harness pointed at the superseded src/rune/query_memory.py, comparing Rust against Rust) vs the Rust CLI on the frozen 24-command sequence in isolated HOMEs. - Fresh evidence: 24/24 commands exact-equal, history.jsonl + topic_stats.json byte-parity. The authority switch itself was already landed (shared/query_memory.py = AUTHORITY-SWITCHED shim, verification wall green).
159 lines
6.4 KiB
Python
159 lines
6.4 KiB
Python
#!/usr/bin/env python3
|
|
"""qm_shadow.py — #2447 remaining: the shadow comparison, honestly.
|
|
|
|
The original parity harness (src/rust/query_memory/parity_test.py) compares
|
|
the WRONG Python side now: it points at src/rune/query_memory.py — a file
|
|
that no longer exists (the oracle moved to shared/ and was superseded by the
|
|
AUTHORITY-SWITCHED shim). A shadow against the shim compares Rust vs Rust.
|
|
|
|
This harness extracts the TRUE pre-shim Python oracle from git history
|
|
(6f44a87~1:shared/query_memory.py, the commit that superseded it) and runs
|
|
an identical frozen command sequence through:
|
|
|
|
- the pre-shim Python oracle (its own CLI, HOME-pinned store)
|
|
- the Rust CLI binary (target/release/query_memory, HOME-pinned store)
|
|
|
|
Comparison (byte-parity laws from the frozen contract):
|
|
1. stdout per command
|
|
2. history.jsonl — byte parity with ISO timestamps masked
|
|
3. topic_stats.json — byte parity (catches float-repr divergence)
|
|
|
|
Divergence = defect (exit 1). Equal = the shadow evidence for the authority
|
|
switch (exit 0).
|
|
|
|
python3 scripts/qm_shadow.py # fresh shadow run
|
|
python3 scripts/qm_shadow.py --print # also dump per-command outputs
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import os
|
|
import re
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
from pathlib import Path
|
|
|
|
REPO = Path("/mnt/workdrive/rune")
|
|
PY = sys.executable
|
|
PRE_SHIM_REF = "6f44a87~1"
|
|
PRE_SHIM_PATH = "shared/query_memory.py"
|
|
RS_BIN = REPO / "src/rust/query_memory/target/release/query_memory"
|
|
TS_RE = re.compile(r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?\+00:00")
|
|
|
|
SEQUENCE = [
|
|
("record", ["memory consolidation test", "--strategy", "consolidated"]),
|
|
("record", ["memory retrieval failed", "--strategy", "direct"]),
|
|
("record", ["web search results ranking", "--strategy", "direct"]),
|
|
("record", ["python file parsing", "--strategy", "ast"]),
|
|
("record", ["unknown gibberish xyzzy", "--strategy", "consolidated"]),
|
|
("record", ["memory web python", "--strategy", "consolidated"]), # tie-break probe
|
|
("record", ["mémoire 取得框架 🧠 test", "--strategy", "consolidated"]), # unicode
|
|
("record", ['quotes "back\\slash" and ,commas;', "--strategy", "direct"]),
|
|
("record", ["memory recall", "--strategy", "consolidated"]),
|
|
("record", ["memory store", "--strategy", "hybrid"]),
|
|
("record", ["memory index", "--strategy", "consolidated"]),
|
|
("record", ["memory lookup", "--strategy", "direct"]),
|
|
("record", ["memory cache", "--strategy", "hybrid"]),
|
|
("record", ["memory grep", "--strategy", "consolidated"]),
|
|
("record", ["memory embedding", "--strategy", "direct"]),
|
|
("record", ["memory vector", "--strategy", "hybrid"]),
|
|
("record", ["memory search", "--strategy", "consolidated"]),
|
|
("record", ["memory query", "--strategy", "direct"]), # crosses >=10
|
|
("rate", ["memory consolidation"]),
|
|
("rate", ["web crawling"]),
|
|
("rate", ["python unittest"]),
|
|
("rate", ["nothing matches here"]),
|
|
("health", []),
|
|
("stats", []),
|
|
]
|
|
|
|
|
|
def _oracle_script(cache: Path) -> Path:
|
|
"""Extract the pre-shim oracle from git history (cached per run)."""
|
|
if cache.exists():
|
|
return cache
|
|
r = subprocess.run(
|
|
["git", "-C", str(REPO), "show", f"{PRE_SHIM_REF}:{PRE_SHIM_PATH}"],
|
|
capture_output=True,
|
|
text=True,
|
|
timeout=30,
|
|
)
|
|
if r.returncode != 0 or "QueryMemory" not in r.stdout:
|
|
raise RuntimeError(
|
|
f"cannot recover the pre-shim oracle from {PRE_SHIM_REF}:{PRE_SHIM_PATH} — "
|
|
f"the shadow needs the true Python implementation"
|
|
)
|
|
cache.parent.mkdir(parents=True, exist_ok=True)
|
|
cache.write_text(r.stdout)
|
|
return cache
|
|
|
|
|
|
def run(cmd_list: list, home: str) -> tuple[int, str]:
|
|
env = dict(os.environ, HOME=home)
|
|
p = subprocess.run(cmd_list, env=env, capture_output=True, text=True, timeout=30)
|
|
return p.returncode, p.stdout + (f"[stderr: {p.stderr}]" if p.stderr else "")
|
|
|
|
|
|
def main() -> int:
|
|
ap = argparse.ArgumentParser()
|
|
ap.add_argument("--print", action="store_true", dest="verbose")
|
|
args = ap.parse_args()
|
|
|
|
if not RS_BIN.exists():
|
|
raise RuntimeError(f"Rust CLI not built: {RS_BIN}")
|
|
|
|
with tempfile.TemporaryDirectory(prefix="qm_shadow_") as td:
|
|
work = Path(td)
|
|
py_home = work / "home_py"
|
|
rs_home = work / "home_rs"
|
|
py_home.mkdir()
|
|
rs_home.mkdir()
|
|
oracle = _oracle_script(work / "qm_py_oracle.py")
|
|
|
|
for label, argv in SEQUENCE:
|
|
rc_py, out_py = run([PY, str(oracle), label] + argv, str(py_home))
|
|
rc_rs, out_rs = run([str(RS_BIN), label] + argv, str(rs_home))
|
|
if rc_py != rc_rs or out_py != out_rs:
|
|
print(f"✗ DIVERGENCE at {label} {argv[:1]} (rc {rc_py} vs {rc_rs})")
|
|
if args.verbose:
|
|
print(f" py: {out_py!r}\n rs: {out_rs!r}")
|
|
return 1
|
|
|
|
# history.jsonl byte parity (timestamps masked)
|
|
hist_py = py_home / ".config/opencode/memory/query_memory/history.jsonl"
|
|
hist_rs = rs_home / ".config/opencode/memory/query_memory/history.jsonl"
|
|
if not hist_py.exists() and not hist_rs.exists():
|
|
print("✗ history.jsonl missing in BOTH (sequence never wrote history)")
|
|
return 1
|
|
h_py = TS_RE.sub("<TS>", hist_py.read_text()) if hist_py.exists() else "<MISSING>"
|
|
h_rs = TS_RE.sub("<TS>", hist_rs.read_text()) if hist_rs.exists() else "<MISSING>"
|
|
if h_py != h_rs:
|
|
print("✗ history.jsonl DIVERGENCE (masked)")
|
|
return 1
|
|
|
|
# topic_stats.json byte parity
|
|
st_py = py_home / ".config/opencode/memory/query_memory/topic_stats.json"
|
|
st_rs = rs_home / ".config/opencode/memory/query_memory/topic_stats.json"
|
|
b_py = st_py.read_bytes() if st_py.exists() else b"<MISSING>"
|
|
b_rs = st_rs.read_bytes() if st_rs.exists() else b"<MISSING>"
|
|
if b_py != b_rs:
|
|
print("✗ topic_stats.json DIVERGENCE (byte)")
|
|
return 1
|
|
|
|
print(
|
|
f"SHADOW OK: {len(SEQUENCE)}/{len(SEQUENCE)} commands exact-equal, "
|
|
f"history + topic_stats byte-parity (pre-shim oracle vs Rust)"
|
|
)
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
try:
|
|
raise SystemExit(main())
|
|
except Exception as e: # noqa: BLE001 — terminal reporter: prints and exits 1
|
|
print(f"qm_shadow: {e}", file=sys.stderr)
|
|
raise SystemExit(1)
|