From 44b595e593dc2549bdc397491de54ecf613ea2b7 Mon Sep 17 00:00:00 2001 From: Volt Date: Sat, 24 Oct 2026 04:35:34 +0000 Subject: [PATCH] volt: write-axis -- guard manifest_audit.py's --json write, probe it; leg green 8/8 manifest_audit.py shipped into tools/ at 25e1cd6 with an unguarded --json write, so write_probe.py graded it NO_PROBE and verify.py's write-axis leg read FAULT (rc 1) on every run. - tools/manifest_audit.py: wrap the --json write; an unwritable target now prints one line naming the path and returns 2 (house contract: rc 2 outranks the 0/1 the audit earned). Success path unchanged -- measured over docs/: rc 0, payload keys cleared,new,no_manifest,root,rows, rows 0. - tools/write_probe.py: WRITE_PROBES row (--root {tinyrepo} --json {target}). Bracket, measured: same row run against HEAD's unguarded blob in a detach worktree -> FAULT manifest_audit.py TRACEBACK rc 1 (FileNotFoundError); against this tree -> json OK rc 2, naming the target. write_probe --selftest 15/15, manifest_audit --selftest 17/17, verify.py --repo . 8/8 legs pass, selftest-sweep pin 22 pinned / 22 agree. --- tools/manifest_audit.py | 23 ++++++++++++++++++----- tools/write_probe.py | 1 + 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/tools/manifest_audit.py b/tools/manifest_audit.py index 6e393db..6e62fd4 100755 --- a/tools/manifest_audit.py +++ b/tools/manifest_audit.py @@ -46,8 +46,12 @@ WHY THIS IS IN `tools/` AND IN NO verify.py LEG report a machine-local path as a repo verdict -- the "advice that names a target which does not exist" defect `verify.py` opens with, one level down. It is discovered by `selftest_sweep.py` from `tools/*.py` and graded by both - of that sweep's input axes and by the count pin (17 cells), which is what a - tool in no leg gets: a tool in no leg is ungraded nowhere. + of that sweep's input axes and by the count pin (17 cells). The write end is + graded too, by `write_probe.py`'s json axis -- that probe runs this tool + against a throwaway fixture root, so the fixture, not the host, is what the + verdict describes. What no leg does is grade `--root` against this repository: + that stays a caller's explicit request, because the artifact tree a reader + cares about is theirs, not the checkout's. The two axes it is graded on, and why the third does not apply to it: read-refusal --root that does not exist, and --root naming a file, are @@ -401,9 +405,18 @@ def main(argv=None) -> int: "new": [{"dir": r["dir"], "class": r["verdict"]} for r in new], "cleared": [{"dir": d, "class": c} for d, c in cleared], } - with open(args.json, "w", encoding="utf-8") as fh: - json.dump(blob, fh, indent=2, sort_keys=True) - fh.write("\n") + try: + with open(args.json, "w", encoding="utf-8") as fh: + json.dump(blob, fh, indent=2, sort_keys=True) + fh.write("\n") + except OSError as exc: + # House contract, graded by tools/write_probe.py: a target this host + # cannot write is rc 2 with one line naming it. rc 2 outranks the + # 0/1 the audit earned -- a caller who asked for a file and got a + # traceback cannot know a grade happened at all. + print("manifest_audit: cannot write --json %s: %s" % (args.json, exc), + file=sys.stderr) + return 2 if (args.fail or args.strict) and new: return 1 return 0 diff --git a/tools/write_probe.py b/tools/write_probe.py index 3ee947a..51a180b 100644 --- a/tools/write_probe.py +++ b/tools/write_probe.py @@ -168,6 +168,7 @@ WRITE_PROBES = ( ("gate_blame.py", ["--repo", "{tinyrepo}", "--leg", "selftest-sweep", "--range", "1", "--json", "{target}"]), ("landing_check.py", ["--repo", "{tinyrepo}", "--json", "{target}"]), + ("manifest_audit.py", ["--root", "{tinyrepo}", "--json", "{target}"]), ("path_claim_check.py", ["--repo", "{tinyrepo}", "--json", "{target}"]), ("queue_append_audit.py", ["--repo", "{tinyrepo}", "--json", "{target}"]), ("queue_claim_check.py", ["--queue", "{queue}", "--json", "{target}"]),