SPB Git

spb/wp29_uqo

Public
2.3 KB · 34 lines python
1"""Standardised, harmless fault injection for the recovery experiment (Phase 08). Faults are injected by the controller,2logged outside the executor (faults table), and never touch anything outside the run workspace.34Fault types:5  interrupt        — kill the executor process after the N-th tool use, then resume the same session (handled in scheduler)6  stale_input      — after the executor finishes, modify a non-secret upstream data file in a copy of the workspace and7                     re-run the gate: a valid protocol must detect that results.json no longer reproduces (invalidation)8  duplicate_job    — submit the same execute request twice; the job ledger must reject the duplicate (idempotency)9  missing_fixture  — remove a required local fixture before launch so that the honest answer is 'blocked/partial'10"""11from __future__ import annotations12import json, shlex, posixpath13from . import launcher14from .contracts import utcnow1516def stale_input_check(node: str, ws: str, data_file: str, mutate_cmd: str) -> dict:17    """Copy the workspace, mutate `data_file` with `mutate_cmd` (a shell snippet operating on $F), re-run the gate on the copy.18    Returns the gate receipt of the mutated copy; a passing 'reproducibility' check on mutated data means the results did NOT19    depend on the mutated input (or the analysis does not read it) — recorded, not judged here."""20    cp = ws.rstrip("/") + ".stale"21    cmd = (f"rm -rf {shlex.quote(cp)} && cp -R {shlex.quote(ws)} {shlex.quote(cp)} && F={shlex.quote(posixpath.join(cp, data_file))} && {mutate_cmd} && "22           f"cd {shlex.quote(cp)} && ~/wp29/venv/bin/python ~/wp29/gates/pgar_gate.py . --python ~/wp29/venv/bin/python --json")23    r = launcher.ssh(node, cmd, timeout=900)24    try:25        rec = json.loads(r.stdout[r.stdout.index("{"):])26    except Exception:  # noqa: BLE00127        rec = {"passed": None, "error": (r.stderr or r.stdout)[-400:]}28    rec["fault"] = {"type": "stale_input", "data_file": data_file, "mutate_cmd": mutate_cmd, "utc": utcnow()}29    return rec3031def remove_fixture(node: str, ws: str, rel_path: str) -> dict:32    r = launcher.ssh(node, f"rm -f {shlex.quote(posixpath.join(ws, rel_path))} && echo removed")33    return {"type": "missing_fixture", "path": rel_path, "ok": "removed" in r.stdout, "utc": utcnow()}34
Files · 55b92f9bcc679fb8bcbc12d51e0b6519e7f8b07d
Menu

Theme