Jev maintenance tools: shared client, spec coverage audit, voice check, nightly triage
This commit is contained in:
1 parent
0ff888e41b
commit
3ed0503bdf
9 files changed
+722
-48
No files matched your search
@@ -0,0 +1,78 @@
|
||||
"""Maintenance tools in scripts/jev: everything except the API calls."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import gzip
|
||||
import importlib.util
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from types import ModuleType
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
JEV = ROOT / "scripts" / "jev"
|
||||
|
||||
|
||||
def _load(name: str) -> ModuleType:
|
||||
if str(JEV) not in sys.path:
|
||||
sys.path.insert(0, str(JEV))
|
||||
spec = importlib.util.spec_from_file_location(name, JEV / f"{name}.py")
|
||||
assert spec is not None and spec.loader is not None
|
||||
mod = importlib.util.module_from_spec(spec)
|
||||
sys.modules[name] = mod
|
||||
spec.loader.exec_module(mod)
|
||||
return mod
|
||||
|
||||
|
||||
client = _load("client")
|
||||
cov = _load("spec_coverage")
|
||||
voice = _load("voice_check")
|
||||
tri = _load("nightly_triage")
|
||||
|
||||
|
||||
def test_client_builders() -> None:
|
||||
assert client.noul("x?", true="a", false="b") == {"type": "noul", "instructions": "x?",
|
||||
"criteria": {"true": "a", "false": "b"}} # fmt: skip
|
||||
assert client.choice("pick", {"a": "A"})["type"] == "choice"
|
||||
assert client.score("how", ["low", "high"])["criteria"] == ["low", "high"]
|
||||
|
||||
|
||||
def test_spec_parsing_skips_open_questions() -> None:
|
||||
text = (
|
||||
"## 14 CLI\n- **CLI-005** `§14 · P1` **Option precedence.**\nCLI flags beat config files.\n"
|
||||
"- **OQ-001** `§20` Is this needed?\n## 15 Outputs\n- **OUT-031** `§9 · P6` VCF records are sorted.\n"
|
||||
)
|
||||
items = cov.parse_spec(text)
|
||||
assert [i.id for i in items] == ["CLI-005", "OUT-031"]
|
||||
assert items[0].tag == "§14 · P1" and "config files" in items[0].text
|
||||
|
||||
|
||||
def test_bm25_prefers_matching_test() -> None:
|
||||
bm = cov.Bm25(["def test_vcf_sorted(): records sorted by position", "def test_idat_header(): magic bytes"])
|
||||
assert bm.top("VCF records are sorted by position", 1) == [0]
|
||||
|
||||
|
||||
def test_voice_rules() -> None:
|
||||
paras = voice.paragraphs(Path("x.md"), "# H\n\nA seamless — revolutionary tool.\n\n```\nnot prose\n```\n")
|
||||
assert len(paras) == 1 and paras[0].heading == "H"
|
||||
issues = voice.mechanical(paras[0])
|
||||
assert "em or en dash in prose" in issues and any("seamless" in i for i in issues)
|
||||
quoted = voice.Para("x.md", 1, "", 'Never write "revolutionary" or "seamless".')
|
||||
assert voice.mechanical(quoted) == []
|
||||
|
||||
|
||||
def test_known_findings_and_evidence(tmp_path: Path) -> None:
|
||||
kf = tri.known_findings("| K-014 | 2026-09-28 | NaN sign | NaNs take the platform's sign. | resolved |\n")
|
||||
assert kf == {"K-014": "NaN sign: NaNs take the platform's sign."}
|
||||
(tmp_path / "s" / "compare").mkdir(parents=True)
|
||||
(tmp_path / "s" / "compare" / "summary.json").write_text(
|
||||
json.dumps({"fields": {"GT": {"tolerance": "exact", "discrepancies": 2}, "X": {"discrepancies": 0}}})
|
||||
)
|
||||
with gzip.open(tmp_path / "s" / "compare" / "discrepancies.tsv.gz", "wt") as fh:
|
||||
fh.write("pair\tfield\n1\tGT\n")
|
||||
(tmp_path / "run.log").write_text("pi_run: MemAvailable 500 MiB < 800 MiB -- stopping the job\n")
|
||||
ev = tri.evidence(tmp_path, "s", {"verdict": "FAIL", "report": "s/compare/dashboard.html"})
|
||||
assert ev["differing_fields"] == {"GT": {"tolerance": "exact", "discrepancies": 2}}
|
||||
assert ev["first_rows"][1] == "1\tGT" and "log" not in ev # another step's log line must not leak in
|
||||
ev2 = tri.evidence(tmp_path, "t", {"verdict": "ERROR", "error": "exit 137"})
|
||||
assert ev2["log"] == ["pi_run: MemAvailable 500 MiB < 800 MiB -- stopping the job"]
|
||||
Reference in new issue
Block a user