From fad7837bb35d8775dc0a47e965360d5183771141 Mon Sep 17 00:00:00 2001 From: ledger Date: Sun, 1 Nov 2026 12:23:51 +0000 Subject: [PATCH] volt: q148 -- retake tool for the entry-point baseline, three rows re-taken, one signed --- CHECK-q148 | 136 +++++ WORK-QUEUE.md | 22 + docs/queue-index.md | 71 ++- wizard-work/volt/q137-open-set/open_set.py | 10 +- .../q143-check-sweep/check_entry_baseline.tsv | 15 +- wizard-work/volt/q143-check-sweep/retake.py | 508 ++++++++++++++++++ 6 files changed, 739 insertions(+), 23 deletions(-) create mode 100644 CHECK-q148 create mode 100644 wizard-work/volt/q143-check-sweep/retake.py diff --git a/CHECK-q148 b/CHECK-q148 new file mode 100644 index 0000000..e7c6f16 --- /dev/null +++ b/CHECK-q148 @@ -0,0 +1,136 @@ +#!/usr/bin/env bash +# CHECK-q148 -- the baseline re-take tool, and the re-take it performed. +# +# Q148 (2026-11-01): `check_entry_baseline.tsv` fails in the direction nobody +# automates -- a row whose entry point has since been repaired reads IMPROVED in +# the sweep, and the row is re-taken by hand (Q145, Q146, Q147 each did it once). +# `wizard-work/volt/q143-check-sweep/retake.py` measures named rows with the +# sweep's own `run_entry`/`classify`, reports the codes that moved, and rewrites +# only those rows behind `--write`, with a provenance comment. +# +# leg 1 the tool's 12-cell selftest +# leg 2 two rows the sweep recorded green still read green from the tool +# leg 3 a copy of the baseline with one row's code moved is named, written +# back, and reads clean on a second take (the tool's own contract) +# leg 4 the baseline on disk carries this tick's provenance block and still +# parses under the sweep's own reader +# leg 5 no row in the baseline names evidence the tree does not have +# (the MISSING direction; the NEW direction is another lane's row) +# +# rc 0 all legs pass, rc 1 a leg faulted, rc 2 could not grade. +set -u +HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" || { echo "CANNOT GRADE: no directory"; exit 2; } +ROOT="$(git -C "$HERE" rev-parse --show-toplevel 2>/dev/null)" || { echo "CANNOT GRADE: not a git repository"; exit 2; } +SWEEP="$ROOT/wizard-work/volt/q143-check-sweep" +TOOL="$SWEEP/retake.py" +BASE="$SWEEP/check_entry_baseline.tsv" +for f in "$TOOL" "$BASE" "$SWEEP/check_sweep.py"; do + [ -f "$f" ] || { echo "CANNOT GRADE: missing $f"; exit 2; } +done +PY="${PYTHON:-python3}" +WORK="$(mktemp -d "${TMPDIR:-/tmp}/q148.XXXXXX")" || exit 2 +trap 'rm -rf "$WORK"' EXIT + +# The baseline is a shared file: other ticks re-take rows in it, and a re-take is +# an atomic whole-file replace. Leg 3 grades the TOOL by mutating a copy and +# asking it to name the move, so it compares against a snapshot taken here, not +# against $BASE at compare time -- otherwise a lane that re-took a row between +# the copy and the compare reads as this tool writing the wrong row (measured: +# 2026-11-01 11:57Z and 12:14Z, FAIL beside a green tool selftest). +SNAP="$WORK/base.orig.tsv" +cp "$BASE" "$SNAP" 2>/dev/null && [ -s "$SNAP" ] \ + || { echo "CANNOT GRADE: cannot snapshot $BASE"; exit 2; } + +faults=0 +pass() { echo "PASS $1"; } +fail() { echo "FAIL $1"; faults=$((faults+1)); } + +# leg 1 +if out="$("$PY" "$TOOL" --selftest 2>&1)"; then + pass "selftest $(printf '%s' "$out" | tail -1 | sed 's/selftest: //')" +else + fail "selftest"; printf '%s\n' "$out" | tail -4 +fi + +# leg 2 -- two green rows, measured again +if out="$("$PY" "$TOOL" --repo "$ROOT" --path CHECK-q147 --path CHECK-q146 2>&1)"; then + pass "green-rows $(printf '%s' "$out" | tail -1 | sed 's/retake: //')" +else + fail "green-rows rc=$?"; printf '%s\n' "$out" | grep '^MOVED' | head -3 +fi + +# leg 3 -- the mutation: one row's code moved, named, written, re-read clean. +# The mutation is applied to the snapshot, so what is compared at the end is +# "the tool's rewrite vs the file it was handed". +"$PY" - "$SNAP" "$WORK/base.tsv" <<'PY' +import sys +src, dst = sys.argv[1], sys.argv[2] +lines = open(src, encoding="utf-8").read().split("\n") +out = [] +for line in lines: + parts = line.split("\t") + if parts[0] == "CHECK-q147" and len(parts) > 2: + parts[1] = "1" + line = "\t".join(parts) + out.append(line) +open(dst, "w", encoding="utf-8", newline="\n").write("\n".join(out)) +PY +out="$("$PY" "$TOOL" --baseline "$WORK/base.tsv" --repo "$ROOT" --path CHECK-q147 2>&1)"; rc=$? +if [ "$rc" -eq 1 ] && printf '%s' "$out" | grep -q '^MOVED CHECK-q147 1 -> 0'; then + wout="$("$PY" "$TOOL" --baseline "$WORK/base.tsv" --repo "$ROOT" --path CHECK-q147 --write 2>&1)"; wrc=$? + if [ "$wrc" -eq 0 ] && "$PY" "$TOOL" --baseline "$WORK/base.tsv" --repo "$ROOT" --path CHECK-q147 >/dev/null 2>&1; then + if "$PY" - "$SNAP" "$WORK/base.tsv" <<'PY' +import sys +def rows(p): + out = {} + for line in open(p, encoding="utf-8"): + if line.startswith("#") or not line.strip(): + continue + parts = line.rstrip("\n").split("\t") + out[parts[0]] = (parts[1], parts[2] if len(parts) > 2 else "") + return out +a, b = rows(sys.argv[1]), rows(sys.argv[2]) +bad = ["%s %s!=%s" % (k, a[k], b[k]) for k in a if a.get(k) != b.get(k)] +print("data rows: %d compared, %d differ" % (len(a), len(bad))) +sys.exit(1 if bad else 0) +PY + then + pass "mutation named, written, re-read clean, other rows identical" + else + fail "mutation reintroduced a difference in another row" + fi + else + fail "mutation write rc=$wrc or second take still moved" + fi +else + fail "mutation not named (rc=$rc)"; printf '%s\n' "$out" | tail -2 +fi + +# leg 4 -- the on-disk baseline carries this tick's provenance and still parses +if grep -q '^# row-level re-take (q148 via retake.py' "$BASE" \ + && "$PY" - "$BASE" <<'PY' +import sys +sys.path.insert(0, sys.argv[1].rsplit("/", 1)[0]) +import check_sweep +rev, rows = check_sweep.read_baseline(sys.argv[1]) +print("baseline parses: %d row(s), rev %s" % (len(rows), rev)) +sys.exit(0 if rows and rev else 1) +PY +then + pass "provenance block present, baseline parses" +else + fail "provenance block missing or baseline does not parse" +fi + +# leg 5 -- no MISSING row (evidence the baseline names and the tree lacks) +out="$("$PY" "$SWEEP/check_sweep.py" --repo "$ROOT" --paths 2>&1)" +if printf '%s' "$out" | grep -q '^FAIL: MISSING'; then + fail "baseline names a path the tree lacks" + printf '%s\n' "$out" | grep '^FAIL: MISSING' | head -3 +else + pass "no MISSING row ($(printf '%s' "$out" | tail -1 | sed 's/paths: //'))" +fi + +echo "q148: $((5-faults)) of 5 leg(s) passed" +[ "$faults" -eq 0 ] || exit 1 +exit 0 diff --git a/WORK-QUEUE.md b/WORK-QUEUE.md index 339d603..59172a8 100644 --- a/WORK-QUEUE.md +++ b/WORK-QUEUE.md @@ -14062,3 +14062,25 @@ CHECK: bash CHECK-q146 Files edited for this item: `wizard-work/ledger/workqueue-census/verify_workqueue_census.py` (new), `wizard-work/ledger/workqueue-census/CHECK` (rewritten), `wizard-work/ledger/workqueue-census/extract_workqueue_census.py` (wrapper), `wizard-work/ledger/workqueue-census/README.md`, `wizard-work/ledger/workqueue-census/workqueue-census.md` (header and footer only), `wizard-work/ledger/workqueue-census/manifest.json` (schema v2, rev, blob, measured timestamp), `CHECK-q147` (new entry point, 4 legs), `wizard-work/volt/q143-check-sweep/check_entry_baseline.tsv` (one row re-taken, one added), `wizard-work/volt/q63_unwired_baseline.tsv` (one class row added for the new verifier, measured at `de6d848`, so the Q65 gate's fault count is unmoved at 60), `wizard-work/volt/q137-open-set/open_set.py` (its record-count pin, moved by this append), `WORK-QUEUE.md` (this record, appended), `docs/queue-index.md` (re-rendered). The probe, the mutator, the two mutants and the re-take script are under `/root/.hermes/wizard-outputs/volt/q147-workqueue-census/`. Nothing from `inbox/` is quoted, and no counterparty repository file was edited. CHECK: bash CHECK-q147 + +**Q148 — DONE at the commit this record lands in (opened and repaired in the same tick, volt, 2026-11-01; volt lane by authorship, unclaimed and taken).** `check_sweep.py` grades every entry point in the tree against `check_entry_baseline.tsv` and faults in both directions, but only one of those directions had a tool: a code that moved `0 -> 1` names itself, and a code that moved `1 -> 0` reads `IMPROVED ... re-take the baseline` and then waits for a human to copy the path, run the entry point, and type the code and the fault line into the right row. Three ticks did that by hand (`Q145`, `Q146`, `Q147`), each of them typing numbers into a file whose whole contract is that every number in it was measured. + +**(0) Entry state, measured at `3118da3` with the sweep's own `run_entry` (`--timeout 120 --jobs 4`), every row whose recorded code was not 0 -- 29 rows.** `retake` did not exist yet, so this was a probe over the same rows: **29 measured, 3 moved, 26 unchanged**, `0` rows missing from the tree, and one `NEW` entry point (`wizard-work/quill/CHECK-quill-draft-compliance`, another lane's second copy of that gate, untracked at the time of reading). The three that moved: + +- `wizard-work/volt/CHECK-toolsmd-drift` **1 -> 0** (`TOOLSMD OK: drift 0 at HEAD and WORKTREE; ... gate fast legs all green (65s)`), the repair `Q145` landed and never re-took; +- `wizard-work/volt/q137-open-set/CHECK-q137` **1 -> 0** (`q137: 4 leg(s), all passed`), the same class: `Q147` noted the row as stale and left it red; +- `wizard-work/sphinx/archive-transformer-pdf-modality-2026-10-23/CHECK.py` **124 -> 1**, which is not a repair but a reading that had stopped being true: at the baseline's 120 s ceiling the entry point timed out, and at `--timeout 240` it finishes in **97.78 s** and fails on its own assertions -- `CHECK-FAIL: 1 verify_archive.py exits 0 (54 checks, 1 failures), 3 rebuilt record == archived record (4 differing leaves)`. A row that records `124` records the ceiling, not the artifact. + +**(1) The tool.** `wizard-work/volt/q143-check-sweep/retake.py` imports `check_sweep.run_entry`, `classify` and `read_baseline` rather than re-implementing them, so a row it writes is a reading the sweep would take. It measures the red rows by default (`--all` for every row, `--path` for named ones), prints the codes that moved, and rewrites **only those rows** behind `--write`: the two changed fields are replaced on the physical line, every other byte of the file is left alone, and a provenance comment is inserted before the first data row naming the tool, the date, the timeout, the job count, the rev and each moved row. `--sign` covers the sweep's other direction -- a path that landed after the last take -- and appends its row only after measuring it. Two refusals are structural rather than advisory: a write is **refused whole** if any named row is missing from the tree (`rc 1`, `refusing to write -- 1 named row(s) missing from the tree; a re-take that skips a path would claim coverage it does not have`), and a malformed baseline is `rc 2` `CANNOT GRADE`, never a pass. After writing, the tool re-reads the file with `parse_baseline` and faults if the row on disk is not the row it says it wrote. + +**(2) The defect the tool found in itself, before it was allowed to write.** The note is the entry point's first fault line, copied from its output -- and a fault line can carry a tab. Written verbatim into a tab-separated file that row gains a field, `read_baseline` reads `parts[2]`, and the writer reports success while the reader grades a truncated note: measured on a fixture, `'FAIL tabbed\tfaultline after the tab'` wrote **4 fields** and read back as **`'FAIL tabbed'`**. So `clean_note()` collapses whitespace and tabs before the cut at 160 characters, in both the re-take and the sign path, and the `note-sanitised` cell now asserts three fields and the whole note read back through `check_sweep.read_baseline`. + +**(3) The re-take it performed, measured.** `--path CHECK-toolsmd-drift --path CHECK-q137 --write` -> `2 measured, 2 moved and written`; `--path archive-transformer-pdf-modality --timeout 240 --write` -> `1 measured, 1 moved and written`; `--sign CHECK-q148` -> `SIGNED CHECK-q148 0 (green)`, re-taken once more after the entry point was staged (`1 -> 0`, `q148: 5 of 5 leg(s) passed`). The baseline moved **106 -> 107 rows** with a `git diff --stat` of **12 insertions, 3 deletions**: three codes re-taken, one row signed, four provenance blocks, and no other row touched. The 240 s line is deliberate and stated in its own provenance block: that entry point reads `124` at a 120 s ceiling and `1` at 240 s, and a baseline that stores the ceiling instead of the artifact is the defect this item exists to name. + +**(4) Evidence.** `--selftest` -> **12 cells, 12 passed, 0 failed**, `rc 0`: green control, a moved code named without writing, a write that updates exactly one row and is idempotent, a write refused for a missing path, a malformed baseline (`rc 2`), the 160-character note cut, the fault-hint rule matching the sweep's (the `FAIL` line, not the last), the imported contract (`run_entry is check_sweep.run_entry`), a baseline that names one entry point and gets no invented rows, a one-shot sign that refuses to sign twice, a tab-bearing note kept to one cell, and a host-path grep of the file. `bash CHECK-q148` -> **5 of 5 legs**, `rc 0`: the selftest, two green rows re-measured in place (`2 measured, 0 moved`), the mutation (a copy of the baseline with `CHECK-q147` moved to `1` is named `MOVED ... 1 -> 0`, written back, re-read clean, and its 106 other rows compared field by field -- `data rows: 107 compared, 0 differ`), the provenance block plus a parse of the baseline through the sweep's own reader, and the `MISSING` direction of the sweep's `--paths` leg, which at the take read `108 entry point(s), 107 baseline path(s), 1 fault(s)` -- the one fault being the quill `NEW` named above, not a `MISSING` (later ticks added entry points of their own; the leg grades the `MISSING` direction only, so a `NEW` row elsewhere cannot make it pass by accident). The full before-reading and both write transcripts are under `/root/.hermes/wizard-outputs/volt/q148-baseline-retake/`, and the baseline's pre-edit copy is `baseline-before.tsv` beside them. + +**(5) Not claimed.** That the two `1 -> 0` rows are stable -- both are host-load-sensitive entry points (the drift guard itself runs the 12-leg gate, `65-83 s`) and a later take can move either; that `CHECK-q148` passed on every take -- one take, run while a second writer held the baseline file, printed `FAIL mutation reintroduced a difference in another row`, and the row it left behind was re-taken after the entry point was staged (the committed tree reads 5 of 5, measured twice); that the sphinx entry point regressed since its baseline reading -- `124` was a timeout at the old ceiling, and what it does at 240 s is fail its own assertions, which is a reading of that artifact this record does not judge; that the other 26 red rows are sound or stale -- they were measured and unchanged, and none of them was examined; that the sweep's `--check` was re-run whole -- it was not, `--paths` and the row-level takes are what this tick read; that `wizard-work/quill/CHECK-quill-draft-compliance` is repaired -- it is a tracked second copy of that gate that the baseline does not name (the baseline names the repo-root `CHECK-quill-draft-compliance`), and its `NEW` fault is named here, not touched; that `CHECK-q148`'s own row is green by any other reading than this tick's (its row was signed and then re-taken at `rc 0` with the note `q148: 5 of 5 leg(s) passed`). + +Files edited for this item: `wizard-work/volt/q143-check-sweep/retake.py` (new), `CHECK-q148` (new entry point, 5 legs), `wizard-work/volt/q143-check-sweep/check_entry_baseline.tsv` (three rows re-taken, one row signed, four provenance blocks; every other row byte-identical -- `git diff --stat`: 12 insertions, 3 deletions), `wizard-work/volt/q137-open-set/open_set.py` (its record-count pin, moved by this append), `WORK-QUEUE.md` (this record, appended), `docs/queue-index.md` (re-rendered). Nothing from `inbox/` is quoted, and no counterparty repository file was edited. + +CHECK: bash CHECK-q148 diff --git a/docs/queue-index.md b/docs/queue-index.md index a6781ed..7d18aab 100644 --- a/docs/queue-index.md +++ b/docs/queue-index.md @@ -4,7 +4,7 @@ **What this is.** One row per item of `WORK-QUEUE.md`: its line span, its size, and the first `Status:` marker in its body verbatim. An item is a `## ` section, or a record that opens an id with no heading of its own, or a later block-initial record for an id that is already an item (`kind` and `role` say which, and each item's block runs to the line before the next item opens). Whether an item is *open* is not decided here -- that verdict is `tools/queue_claim_check.py`'s, and this document does not overrule it. -**What it exposes.** The queue is two-tier. 97 sections carry 86 ids because 11 ids own a second, continuation section; 57 further ids are opened by a record and own no heading at all, and they have rows and extents here -- 128 record blocks in all, 71 of them a later closure or correction for an id already opened. The same **57 ids** are listed again in the table below, which carries what a bounds row cannot -- the form that opened each one and how often the file names it: grepping `^## Q41` finds nothing while Q41 is a live item the file names 30 times. +**What it exposes.** The queue is two-tier. 97 sections carry 86 ids because 11 ids own a second, continuation section; 58 further ids are opened by a record and own no heading at all, and they have rows and extents here -- 129 record blocks in all, 71 of them a later closure or correction for an id already opened. The same **58 ids** are listed again in the table below, which carries what a bounds row cannot -- the form that opened each one and how often the file names it: grepping `^## Q41` finds nothing while Q41 is a live item the file names 30 times. | # | id | kind | lines | bytes | role | title | first `Status:` | |---|---|---|---|---|---|---|---| @@ -232,7 +232,8 @@ | 222 | Q144 | record | 13994-14015 | 8083 | record: BOLD-LEAD | **Q144 — DONE at `535ab77` and the commit this record lands in (opened 2026-11-01 by the tick that drafted these repairs and was interrupted before landing them; finished in this tick; queue-wide, no … | -- | | 223 | Q145 | record | 14016-14031 | 5408 | record: BOLD-LEAD | **Q145 — DONE at the commit this record lands in (opened and repaired in the same tick, volt, 2026-11-01; volt lane by authorship, unclaimed and taken).** Two of this lane's entry points read … | -- | | 224 | Q146 | record | 14032-14049 | 8221 | record: BOLD-LEAD | **Q146 — DONE at the commit this record lands in (opened and repaired in the same tick, volt, 2026-11-01; ledger lane by authorship for the roster extract, unclaimed and taken).** Two entry points in … | -- | -| 225 | Q147 | record | 14050-14064 | 9508 | record: BOLD-LEAD | **Q147 — DONE at the commit this record lands in (opened and repaired in the same tick, volt, 2026-11-01; ledger lane by authorship for the census artifact, unclaimed and taken).** The workqueue … | -- | +| 225 | Q147 | record | 14050-14065 | 9509 | record: BOLD-LEAD | **Q147 — DONE at the commit this record lands in (opened and repaired in the same tick, volt, 2026-11-01; ledger lane by authorship for the census artifact, unclaimed and taken).** The workqueue … | -- | +| 226 | Q148 | record | 14066-14086 | 8289 | record: BOLD-LEAD | **Q148 — DONE at the commit this record lands in (opened and repaired in the same tick, volt, 2026-11-01; volt lane by authorship, unclaimed and taken).** `check_sweep.py` grades every entry point in … | -- | ## Ids with no `## ` heading @@ -294,9 +295,10 @@ Opened as records inside another section. `line` is the record's own opening lin | Q142 | 13962 | 13962 | 1 | Q141 | BULLET+BOLD | BOLD-LEAD | | Q143 | 13980 | 13980 | 1 | Q142 | BULLET+BOLD | BOLD-LEAD | | Q144 | 13994 | 13980 | 3 | Q143 | BULLET+BOLD | BOLD-LEAD | -| Q145 | 14016 | 14016 | 1 | Q144 | BULLET+BOLD | BOLD-LEAD | -| Q146 | 14032 | 14032 | 2 | Q145 | BULLET+BOLD | BOLD-LEAD | -| Q147 | 14050 | 14050 | 1 | Q146 | BULLET+BOLD | BOLD-LEAD | +| Q145 | 14016 | 14016 | 3 | Q144 | BULLET+BOLD | BOLD-LEAD | +| Q146 | 14032 | 14032 | 3 | Q145 | BULLET+BOLD | BOLD-LEAD | +| Q147 | 14050 | 14050 | 3 | Q146 | BULLET+BOLD | BOLD-LEAD | +| Q148 | 14066 | 14066 | 1 | Q147 | BULLET+BOLD | BOLD-LEAD | **Not in this document.** Ids the prose corpus names that the queue has never mentioned (`checkins/`, `replies/`, `recoveries/`, `audits/`, `docs/`, the top-level documents; `tools/` excluded). That set moves with the prose, not with the queue, so embedding it here would make `--check` go RED for a reason that has nothing to do with the queue being current. It is reported on demand: `python3 tools/queue_index.py --outside`. @@ -1960,17 +1962,30 @@ The block below is the parse this document renders, byte for byte. `--check` com "title": "**Q146 \u2014 DONE at the commit this record lands in (opened and repaired in the same tick, volt, 2026-11-01; ledger lane by authorship for the roster extract, unclaimed and taken).** Two entry points in \u2026" }, { - "bytes": 9508, - "end_line": 14064, + "bytes": 9509, + "end_line": 14065, "id": "Q147", "kind": "record", "line": 14050, - "lines": 15, + "lines": 16, "role": "record", "role_detail": "BOLD-LEAD", "status": null, "status_line": null, "title": "**Q147 \u2014 DONE at the commit this record lands in (opened and repaired in the same tick, volt, 2026-11-01; ledger lane by authorship for the census artifact, unclaimed and taken).** The workqueue \u2026" + }, + { + "bytes": 8289, + "end_line": 14086, + "id": "Q148", + "kind": "record", + "line": 14066, + "lines": 21, + "role": "record", + "role_detail": "BOLD-LEAD", + "status": null, + "status_line": null, + "title": "**Q148 \u2014 DONE at the commit this record lands in (opened and repaired in the same tick, volt, 2026-11-01; volt lane by authorship, unclaimed and taken).** `check_sweep.py` grades every entry point in \u2026" } ], "ids_multi_section": { @@ -5021,17 +5036,30 @@ The block below is the parse this document renders, byte for byte. `--check` com "title": "**Q146 \u2014 DONE at the commit this record lands in (opened and repaired in the same tick, volt, 2026-11-01; ledger lane by authorship for the roster extract, unclaimed and taken).** Two entry points in \u2026" }, { - "bytes": 9508, - "end_line": 14064, + "bytes": 9509, + "end_line": 14065, "id": "Q147", "kind": "record", "line": 14050, - "lines": 15, + "lines": 16, "role": "record", "role_detail": "BOLD-LEAD", "status": null, "status_line": null, "title": "**Q147 \u2014 DONE at the commit this record lands in (opened and repaired in the same tick, volt, 2026-11-01; ledger lane by authorship for the census artifact, unclaimed and taken).** The workqueue \u2026" + }, + { + "bytes": 8289, + "end_line": 14086, + "id": "Q148", + "kind": "record", + "line": 14066, + "lines": 21, + "role": "record", + "role_detail": "BOLD-LEAD", + "status": null, + "status_line": null, + "title": "**Q148 \u2014 DONE at the commit this record lands in (opened and repaired in the same tick, volt, 2026-11-01; volt lane by authorship, unclaimed and taken).** `check_sweep.py` grades every entry point in \u2026" } ], "nested": [ @@ -5526,7 +5554,7 @@ The block below is the parse this document renders, byte for byte. `--check` com "form": "BOLD-LEAD", "id": "Q145", "line": 14016, - "refs": 1, + "refs": 3, "section": "Q144", "shape": "BULLET+BOLD" }, @@ -5535,7 +5563,7 @@ The block below is the parse this document renders, byte for byte. `--check` com "form": "BOLD-LEAD", "id": "Q146", "line": 14032, - "refs": 2, + "refs": 3, "section": "Q145", "shape": "BULLET+BOLD" }, @@ -5544,9 +5572,18 @@ The block below is the parse this document renders, byte for byte. `--check` com "form": "BOLD-LEAD", "id": "Q147", "line": 14050, - "refs": 1, + "refs": 3, "section": "Q146", "shape": "BULLET+BOLD" + }, + { + "first_mention": 14066, + "form": "BOLD-LEAD", + "id": "Q148", + "line": 14066, + "refs": 1, + "section": "Q147", + "shape": "BULLET+BOLD" } ], "preamble": { @@ -5554,9 +5591,9 @@ The block below is the parse this document renders, byte for byte. `--check` com "end_line": 8, "line": 1 }, - "queue_bytes": 2358058, - "queue_lines": 14064, - "queue_sha256": "eaccafd47b66ec4f6d5e758f2f1d69204ff0a7a0b2acd04f96bed4fae25da56a", + "queue_bytes": 2366348, + "queue_lines": 14086, + "queue_sha256": "acc7e08fe53f9b3e073717f9bb80d8d1c1fcb65904a00badec7441314598712a", "sections": [ { "bytes": 3139, diff --git a/wizard-work/volt/q137-open-set/open_set.py b/wizard-work/volt/q137-open-set/open_set.py index 2403bc6..f7c7d6c 100644 --- a/wizard-work/volt/q137-open-set/open_set.py +++ b/wizard-work/volt/q137-open-set/open_set.py @@ -487,9 +487,13 @@ PIN_OPENED = [51, 52, 53, 65, 100, 101, 102, 103, 104, 105, 106, 107, 109, # that carries the record: 106 -> 107 records, 137 -> 138 ids, 72 -> 73 # record_ids, 51 -> 52 record_only; headings, heading_ids, open and opened # unchanged (97 / 86 / 0 / 26), so no id changed its state. -PIN_COUNTS = {"headings": 97, "heading_ids": 86, "records": 107, - "record_ids": 73, "ids": 138, "open": 0, "opened": 26, - "record_only": 52} +# Q148 (2026-11-01): the same move for the same reason -- one appended record, +# one appended id, no heading: 107 -> 108 records, 138 -> 139 ids, 73 -> 74 +# record_ids, 52 -> 53 record_only; headings, heading_ids, open and opened +# unchanged (97 / 86 / 0 / 26), so again no id changed its state. +PIN_COUNTS = {"headings": 97, "heading_ids": 86, "records": 108, + "record_ids": 74, "ids": 139, "open": 0, "opened": 26, + "record_only": 53} PIN_STATE = { 100: "REPAIRED", 101: "REPAIRED", 102: "REPAIRED", 103: "REPAIRED", diff --git a/wizard-work/volt/q143-check-sweep/check_entry_baseline.tsv b/wizard-work/volt/q143-check-sweep/check_entry_baseline.tsv index c529b9e..331f5ad 100644 --- a/wizard-work/volt/q143-check-sweep/check_entry_baseline.tsv +++ b/wizard-work/volt/q143-check-sweep/check_entry_baseline.tsv @@ -9,6 +9,13 @@ # Q147 tick after the census was re-pinned at 95b6964; the row above it is # unchanged. Note: this entry point now runs a 13-cell selftest plus a 17-leg # check, so its reading is a function of the pin and not of the queue's length. +# row-level re-take (q148 via retake.py, 2026-11-01): 2 row(s) measured, --timeout 120 --jobs 4, at HEAD 3118da3; 2 code(s) moved. +# wizard-work/volt/CHECK-toolsmd-drift 1 -> 0 (green) +# wizard-work/volt/q137-open-set/CHECK-q137 1 -> 0 (green) +# row-level re-take (q148 via retake.py, 2026-11-01): 1 row(s) measured, --timeout 240 --jobs 4, at HEAD 3118da3; 1 code(s) moved. +# wizard-work/sphinx/archive-transformer-pdf-modality-2026-10-23/CHECK.py 124 -> 1 (red) +# row-level re-take (q148 via retake.py, 2026-11-01): 1 row(s) measured, --timeout 120 --jobs 4, at HEAD 326288c; 1 code(s) moved. +# CHECK-q148 1 -> 0 (green) CHECK 0 verify_selftest_sweep_q93_refactor: ALL GREEN (0 failed, all checks) CHECK-2026-11-01-ledger-dir-census 0 VERDICT: rc 0 -- the committed CSV is the derivation at the pinned rev CHECK-ledger-dir-census 0 VERDICT: rc 0 -- the committed CSV is the derivation at the pinned rev @@ -91,7 +98,7 @@ wizard-work/sphinx/archive-agentic-memory-5paper-dossier-2026-10-25/CHECK.txt 0 wizard-work/sphinx/archive-lcmm-corpus-2026-10-26/CHECK.sh 0 CHECK: PASS wizard-work/sphinx/archive-lcmm-metadata-2026-10-25/CHECK.sh 0 CHECK: GREEN -- dossier holds wizard-work/sphinx/archive-mmlongcite-2026-10-25/CHECK.sh 0 CHECK: GREEN -- archive holds -wizard-work/sphinx/archive-transformer-pdf-modality-2026-10-23/CHECK.py 124 TIMEOUT after 120s +wizard-work/sphinx/archive-transformer-pdf-modality-2026-10-23/CHECK.py 1 FAILED: J re-rendered page rasters match (3 samples) wizard-work/sphinx/arxiv-digest-verified-2026-10-25/CHECK.py 0 ALL CHECKS PASSED wizard-work/sphinx/arxiv-fulltext-2026-10-25/CHECK.sh 1 FAIL L2 fixture units exits 0 rc=1 err= recent call last): wizard-work/sphinx/figure-locator-llama3-2026-10-24/CHECK.txt 0 12/12 mutation checks passed @@ -111,7 +118,9 @@ wizard-work/volt/CHECK-q136 0 q136: 7 leg(s), 7 passed, 0 fault(s) wizard-work/volt/CHECK-q89 0 q89: 24 leg line(s), 0 fault -- OK wizard-work/volt/CHECK-q90 0 q90: 7 leg(s), 0 fault -- OK wizard-work/volt/CHECK-q97 0 Q97 GATE: rc 0 -- a refusal that echoes the invocation is fatal on both input axes, and a mutating flag rename is caught. -wizard-work/volt/CHECK-toolsmd-drift 1 TOOLSMD FAIL: a graded gate leg ran red -wizard-work/volt/q137-open-set/CHECK-q137 1 FAIL count ids moved 135 -> 133 +wizard-work/volt/CHECK-toolsmd-drift 0 TOOLSMD OK: drift 0 at HEAD and WORKTREE; tool_map selftest all cells passed; gate fast legs all green (65s) +wizard-work/volt/q137-open-set/CHECK-q137 0 q137: 4 leg(s), all passed wizard-work/volt/q140/CHECK-q140 0 Q140 OK wizard-work/volt/q144-check-entry/CHECK-q144 0 entry point for the four repaired CHECKs plus a mutant: 6 legs, all passed. First measured by the interrupted tick while the file was staged and never committed (the sweep's --paths leg read MISSING for it); committed by 846fe39, and this row is the post-commit reading +# rows signed (q148 via retake.py, 2026-11-01): 1 entry point(s) measured, --timeout 300 --jobs 4, at HEAD 326288c +CHECK-q148 0 q148: 5 of 5 leg(s) passed diff --git a/wizard-work/volt/q143-check-sweep/retake.py b/wizard-work/volt/q143-check-sweep/retake.py new file mode 100644 index 0000000..9a739dc --- /dev/null +++ b/wizard-work/volt/q143-check-sweep/retake.py @@ -0,0 +1,508 @@ +#!/usr/bin/env python3 +"""retake.py -- re-take named rows of the CHECK entry-point baseline. + +WHY THIS EXISTS + `check_sweep.py` grades the tree against `check_entry_baseline.tsv` and fails + in both directions: a code that moved `0 -> 1` is a revert, and a code that + moved `1 -> 0` is "IMPROVED ... re-take the baseline". The second direction is + a chore done by hand in Q145/Q146/Q147 -- copy the path, run the entry point, + paste the code and the first fault line into the right row, and write a + provenance comment so a reader knows which tick moved it. Done by hand it is + slow, it is typed rather than measured, and a mistyped code is invisible: the + baseline's whole contract is that every number in it was measured. + + This tool is that chore, with the contract imported rather than re-implemented: + measurement is `check_sweep.run_entry` and `check_sweep.classify`, the baseline + reader is `check_sweep.read_baseline`, so a row written here is a reading the + sweep would take. It measures, reports, and (only with `--write`) rewrites the + rows whose code moved, leaving every other byte of the file alone. + +WHAT IT MEASURES + By default, the rows whose recorded code is not 0 -- the audit that matters, + because a green row can only degrade and a red row is the one that might have + been repaired since. `--all` measures every row; `--path` (repeatable, + substring match) narrows to named rows. + +EXIT CODES -- the tree's convention + 0 no row moved (dry run), or every moved row was written (`--write`) + 1 a row moved and nothing was written (dry run), or a write was refused + because the baseline names a path the tree does not have + 2 could not grade: no baseline, unreadable or malformed baseline, no repo + + `--selftest` runs 12 cells in a fixture tree: a green control, a moved code, + a write, a write refused for a missing path, a malformed baseline, the note + cut, the fault-hint rule, the imported contract, a baseline that does not name + every entry point (it must not invent rows), a one-shot sign of a path the + baseline does not name, a host-path grep of this file, and a note that carries + a tab (it must stay one cell and read back whole). A green reading is never + the only thing this tool can print. + +NOT CLAIMED + That a green row measures the right thing -- that is each entry point's own + selftest. Nor that a re-take is stable: a row that is a function of host load + or of a live API can move between two takes, which is why the provenance + comment records the timeout, the job count and the rev. +""" +import argparse +import concurrent.futures +import datetime +import os +import re +import subprocess +import sys + +HERE = os.path.dirname(os.path.abspath(__file__)) +sys.path.insert(0, HERE) + +import check_sweep # noqa: E402 + +run_entry = check_sweep.run_entry +classify = check_sweep.classify + +DEFAULT_BASELINE = os.path.join(HERE, "check_entry_baseline.tsv") +NOTE_CUT = 160 + + +def repo_of(path): + """The git toplevel that owns `path`, or the tree above this tool.""" + d = os.path.dirname(os.path.abspath(path)) + try: + r = subprocess.run(["git", "-C", d, "rev-parse", "--show-toplevel"], + capture_output=True, text=True, timeout=60) + if r.returncode == 0 and r.stdout.strip(): + return r.stdout.strip() + except (OSError, subprocess.SubprocessError): + pass + return os.path.dirname(os.path.dirname(HERE)) + + +def head_rev(repo): + try: + r = subprocess.run(["git", "-C", repo, "rev-parse", "--short", "HEAD"], + capture_output=True, text=True, timeout=60) + if r.returncode == 0: + return r.stdout.strip() or "unknown" + except (OSError, subprocess.SubprocessError): + pass + return "unknown" + + +class BaselineError(Exception): + """The baseline cannot be graded: a parse fault, not a row fault.""" + + +def parse_baseline(path): + """-> (lines, rows); rows are dicts with the physical line index. + + Comments and blank lines are kept verbatim in `lines` so a rewrite can be + expressed as "replace these three field values on these line numbers". + """ + if not os.path.isfile(path): + raise BaselineError("no baseline at %s" % path) + try: + with open(path, "r", encoding="utf-8") as fh: + lines = fh.read().split("\n") + except OSError as exc: + raise BaselineError("cannot read %s: %s" % (path, exc)) + rows = [] + for i, line in enumerate(lines): + if not line.strip() or line.startswith("#"): + continue + parts = line.split("\t") + if len(parts) < 2: + raise BaselineError("line %d has no tab: %r" % (i + 1, line)) + if not parts[1].strip().isdigit(): + raise BaselineError("line %d rc is not an integer: %r" + % (i + 1, line)) + rows.append({"line": i, "path": parts[0], "rc": int(parts[1].strip()), + "note": parts[2] if len(parts) > 2 else ""}) + if not rows: + raise BaselineError("baseline has no rows: %s" % path) + return lines, rows + + +def select(rows, want_all, only): + out = [] + for r in rows: + if only and not any(s in r["path"] for s in only): + continue + if want_all or only or r["rc"] != 0: + out.append(r) + return out + + +def measure(repo, rows, timeout, jobs): + """One reading per named row, in sorted path order, `jobs` at a time.""" + todo = sorted(rows, key=lambda r: r["path"]) + missing = [r for r in todo if not os.path.isfile(os.path.join(repo, r["path"]))] + present = [r for r in todo if r not in missing] + + def one(r): + rc, note = run_entry(repo, r["path"], timeout) + return {"path": r["path"], "was": r["rc"], "now": rc, + "note": clean_note(note)[:NOTE_CUT], "state": classify(rc)} + + if jobs < 2 or len(present) < 2: + got = [one(r) for r in present] + else: + got = [] + with concurrent.futures.ThreadPoolExecutor(max_workers=jobs) as pool: + futures = {pool.submit(one, r): r for r in present} + for fut in concurrent.futures.as_completed(futures): + got.append(fut.result()) + got.sort(key=lambda g: g["path"]) + return got, [r["path"] for r in missing] + + +def moved(readings): + return [g for g in readings if g["was"] != g["now"]] + + +def clean_note(note): + """A note safe for a tab-separated row: tabs and runs of whitespace become + one space, because a tab inside the note adds a field and the reader that + grades the row would see a truncated note while the writer reported success.""" + return " ".join(note.replace("\t", " ").split()) + + +def provenance(count, moved_rows, rev, timeout, jobs, stamp): + """The comment block a rewrite leaves behind, one line per moved row.""" + head = ("# row-level re-take (q148 via retake.py, %s): %d row(s) measured," + " --timeout %d --jobs %d, at HEAD %s; %d code(s) moved." + % (stamp, count, timeout, jobs, rev, len(moved_rows))) + body = ["# %s %d -> %d (%s)" % (m["path"], m["was"], m["now"], m["state"]) + for m in moved_rows] + return [head] + body + + +def rewrite(lines, rows, readings, rev, timeout, jobs, stamp): + """-> new list of lines: changed rows updated in place, one comment block + inserted after the leading comment block. Order and every other byte kept.""" + line_of = {r["path"]: r["line"] for r in rows} + by_line = {line_of[g["path"]]: g for g in readings if g["path"] in line_of} + out = [] + inserted = False + block = provenance(len(readings), moved(readings), rev, timeout, jobs, stamp) + first_row = next((i for i, l in enumerate(lines) + if l.strip() and not l.startswith("#")), len(lines)) + for i, line in enumerate(lines): + if i == first_row and not inserted: + out.extend(block) + inserted = True + r = by_line.get(i) + if r is None: + out.append(line) + continue + parts = line.split("\t") + parts[1] = str(r["now"]) + note = clean_note(r["note"]) + if len(parts) > 2: + parts[2] = note + else: + parts.append(note) + out.append("\t".join(parts)) + if not inserted: + out.extend(block) + return out + + +def sign(baseline, lines, rows, repo, paths, timeout, jobs): + """Measure paths the baseline does not name and append their rows. + + The sweep's OTHER fault direction: an entry point that landed after the last + take is `NEW` until a tick measures and signs it. This is that signing, with + the same `run_entry`, appended after the last data row. + """ + known = {r["path"] for r in rows} + out = [] + for p in paths: + if p in known: + print("retake: refusing to sign %s -- the baseline already names it" + " (a code change is a re-take, not a sign)" % p) + return 1 + if not os.path.isfile(os.path.join(repo, p)): + print("CANNOT GRADE: %s is not in the tree at %s" % (p, repo)) + return 2 + out.append(p) + + rev = head_rev(repo) + stamped = [] + for p in out: + rc, note = run_entry(repo, p, timeout) + note = clean_note(note)[:NOTE_CUT] + stamped.append((p, rc, note[:NOTE_CUT], classify(rc))) + print("SIGNED %s %d (%s) %s" % (p, rc, classify(rc), note[:NOTE_CUT])) + + stamp = datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%d") + block = ["# rows signed (q148 via retake.py, %s): %d entry point(s) measured," + " --timeout %d --jobs %d, at HEAD %s" + % (stamp, len(stamped), timeout, jobs, rev)] + body = lines[:] + tail = body.pop() if body and body[-1] == "" else "" + body.extend(block) + body.extend("%s\t%d\t%s" % (p, rc, note) for p, rc, note, _s in stamped) + if tail == "": + body.append("") + tmp = baseline + ".sign.tmp" + with open(tmp, "w", encoding="utf-8", newline="\n") as fh: + fh.write("\n".join(body)) + os.replace(tmp, baseline) + _l, after = parse_baseline(baseline) + disk = {r["path"]: r["rc"] for r in after} + bad = [p for p, rc, _n, _s in stamped if disk.get(p) != rc] + if bad: + print("retake: SIGNED WRONG ROWS (re-read disagrees): %s" % ", ".join(bad)) + return 1 + print("retake: %d row(s) signed into %s" % (len(stamped), baseline)) + return 0 + + +def main(argv=None): + ap = argparse.ArgumentParser( + description="Re-take named rows of the CHECK entry-point baseline.") + ap.add_argument("--baseline", default=DEFAULT_BASELINE) + ap.add_argument("--repo", default=None) + ap.add_argument("--path", action="append", default=[], + help="substring of a baseline path; repeatable") + ap.add_argument("--all", action="store_true", + help="measure every row, not only the red ones") + ap.add_argument("--timeout", type=int, default=120) + ap.add_argument("--jobs", type=int, default=4) + ap.add_argument("--write", action="store_true") + ap.add_argument("--sign", action="append", default=[], metavar="PATH", + help="measure a path the baseline does not name and append " + "it; repeatable, and a write") + ap.add_argument("--verbose", action="store_true") + ap.add_argument("--selftest", action="store_true") + a = ap.parse_args(argv) + + if a.selftest: + return selftest(a.verbose) + + baseline = os.path.abspath(a.baseline) + repo = os.path.abspath(a.repo) if a.repo else repo_of(baseline) + try: + lines, rows = parse_baseline(baseline) + except BaselineError as exc: + print("CANNOT GRADE: %s" % exc) + return 2 + if not os.path.isdir(repo): + print("CANNOT GRADE: no repo at %s" % repo) + return 2 + + if a.sign: + return sign(baseline, lines, rows, repo, a.sign, a.timeout, a.jobs) + + targets = select(rows, a.all, a.path) + if not targets: + print("retake: nothing to measure (0 row(s) selected)") + return 0 + + rev = head_rev(repo) + readings, missing = measure(repo, targets, a.timeout, a.jobs) + moves = moved(readings) + + print("# retake %s" % baseline) + print("# repo %s at HEAD %s; timeout %ds, jobs %d; %d row(s) measured" + % (repo, rev, a.timeout, a.jobs, len(readings))) + for p in missing: + print("MISSING %s -- the baseline names it, the tree does not have it" % p) + for m in moves: + print("MOVED %s %d -> %d (%s) %s" + % (m["path"], m["was"], m["now"], m["state"], m["note"])) + if a.verbose: + for g in readings: + if g["was"] == g["now"]: + print("SAME %s %d (%s)" % (g["path"], g["now"], g["state"])) + + if not a.write: + print("retake: %d measured, %d moved, %d unchanged%s" + % (len(readings), len(moves), len(readings) - len(moves), + "; nothing written (dry run)" if moves else "")) + return 1 if (moves or missing) else 0 + + if missing: + print("retake: refusing to write -- %d named row(s) missing from the " + "tree; a re-take that skips a path would claim coverage it does " + "not have" % len(missing)) + return 1 + if not moves: + print("retake: %d measured, 0 moved; nothing written" % len(readings)) + return 0 + + stamp = datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%d") + new_lines = rewrite(lines, rows, readings, rev, a.timeout, a.jobs, stamp) + body = "\n".join(new_lines) + tmp = baseline + ".retake.tmp" + with open(tmp, "w", encoding="utf-8", newline="\n") as fh: + fh.write(body) + os.replace(tmp, baseline) + # Read it back: the rows this tool says it wrote must be the rows on disk. + _lines, after = parse_baseline(baseline) + disk = {r["path"]: r["rc"] for r in after} + bad = [m["path"] for m in moves if disk.get(m["path"]) != m["now"]] + if bad: + print("retake: WROTE WRONG ROWS (re-read disagrees): %s" % ", ".join(bad)) + return 1 + print("retake: %d measured, %d moved and written into %s" + % (len(readings), len(moves), baseline)) + return 0 + + +# --------------------------------------------------------------------- selftest + +FIXTURES = { + "CHECK-a": "#!/bin/bash\necho 'PASS a is green'\nexit 0\n", + "CHECK-b": "#!/bin/bash\necho 'warming up'\necho 'FAIL b is red'\nexit 1\n", + "CHECK-loud": "#!/bin/bash\nprintf 'ok %0300d\\n' 0\nexit 0\n", + "CHECK-tabbed": "#!/bin/bash\nprintf 'FAIL tabbed\\tfaultline after the tab\\n'\nexit 1\n", +} + + +def selftest(verbose=False): + import tempfile + cell_failed = 0 + cells = 0 + + def cell(name, ok, detail=""): + nonlocal cell_failed, cells + cells += 1 + if not ok: + cell_failed += 1 + print(" %-24s %s %s" % (name, "PASS" if ok else "FAIL", detail if + (verbose or not ok) else "")) + + def run(argv): + """main() with its report captured, so cell lines stay readable.""" + import contextlib + import io + buf = io.StringIO() + with contextlib.redirect_stdout(buf): + rc = main(argv) + return rc, buf.getvalue() + + work = tempfile.mkdtemp(prefix="retake-selftest.") + try: + tree = os.path.join(work, "tree") + os.makedirs(tree) + for name, body in FIXTURES.items(): + p = os.path.join(tree, name) + with open(p, "w", encoding="utf-8") as fh: + fh.write(body) + os.chmod(p, 0o755) + + base = os.path.join(work, "baseline.tsv") + green = ("# path\trc\tnote -- fixture baseline\n" + "# a comment that must survive a rewrite\n" + "CHECK-a\t0\tPASS a is green\n" + "CHECK-b\t1\tFAIL b is red\n") + with open(base, "w", encoding="utf-8") as fh: + fh.write(green) + + # 1 -- green control: a baseline that agrees with the tree moves nothing + rc, _o = run(["--baseline", base, "--repo", tree, "--all"]) + cell("green-control", rc == 0, "rc=%d" % rc) + + # 2 -- a moved code is named, and the dry run writes nothing + with open(base, "w", encoding="utf-8") as fh: + fh.write(green.replace("CHECK-b\t1\tFAIL b is red", + "CHECK-b\t0\tFAIL b is red")) + before = open(base, encoding="utf-8").read() + rc, _o = run(["--baseline", base, "--repo", tree, "--all"]) + after = open(base, encoding="utf-8").read() + cell("moved-code-named", rc == 1 and after == before, + "rc=%d bytes-unchanged=%s" % (rc, after == before)) + + # 3 -- the write moves exactly that row and keeps the comments + rc, _o = run(["--baseline", base, "--repo", tree, "--all", "--write"]) + text = open(base, encoding="utf-8").read() + _l, rows = parse_baseline(base) + rc2, _o2 = run(["--baseline", base, "--repo", tree, "--all"]) + code = {r["path"]: r["rc"] for r in rows} + cell("write-updates-row", rc == 0 and code["CHECK-b"] == 1 + and "a comment that must survive" in text + and "retake.py" in text and rc2 == 0, + "rc=%d b=%d idempotent_rc=%d" % (rc, code["CHECK-b"], rc2)) + + # 4 -- a baseline row with no file in the tree is a refusal, not a skip + with open(base, "w", encoding="utf-8") as fh: + fh.write(green + "CHECK-gone\t0\tnothing\n") + rc, _o = run(["--baseline", base, "--repo", tree, "--all", "--write"]) + text = open(base, encoding="utf-8").read() + cell("missing-row-refused", rc == 1 and "CHECK-gone\t0" in text, + "rc=%d untouched=%s" % (rc, "CHECK-gone\t0" in text)) + + # 5 -- a malformed baseline cannot be graded (2, never a pass) + with open(base, "w", encoding="utf-8") as fh: + fh.write(green + "CHECK-a\tnot-an-int\tx\n") + rc, _o = run(["--baseline", base, "--repo", tree, "--all"]) + cell("malformed-ungradable", rc == 2, "rc=%d" % rc) + + # 6 -- the note is cut at the same width the sweep uses + with open(base, "w", encoding="utf-8") as fh: + fh.write("# path\trc\tnote\nCHECK-loud\t1\tstale\n") + rc, _o = run(["--baseline", base, "--repo", tree, "--all", "--write"]) + _l, rows = parse_baseline(base) + note = rows[0]["note"] if rows else "" + cell("note-cut", rc == 0 and 0 < len(note) <= NOTE_CUT, + "len=%d" % len(note)) + + # 7 -- the fault-hint rule is the sweep's: the FAIL line, not the last + rc, note = run_entry(tree, "CHECK-b", 30) + cell("fault-hint-parity", rc == 1 and note.startswith("FAIL b is red"), + "note=%r" % note) + + # 8 -- the contract is imported, not re-implemented + cell("contract-imported", run_entry is check_sweep.run_entry + and classify is check_sweep.classify, "") + + # 9 -- a baseline that does not name every entry point invents no rows + with open(base, "w", encoding="utf-8") as fh: + fh.write("# path\trc\tnote\nCHECK-a\t0\tPASS a is green\n") + rc, _o = run(["--baseline", base, "--repo", tree, "--all", "--write"]) + _l, rows = parse_baseline(base) + cell("invents-no-rows", rc == 0 and len(rows) == 1 + and rows[0]["path"] == "CHECK-a", "rows=%d" % len(rows)) + + # 10 -- this file names no host path + src = open(os.path.abspath(__file__), encoding="utf-8").read() + cell("no-host-path", ("/" + "root/") not in src, "") + + # 11 -- a path the baseline does not name is measured and signed once + with open(base, "w", encoding="utf-8") as fh: + fh.write("# path\trc\tnote\nCHECK-a\t0\tPASS a is green\n") + rc, _o = run(["--baseline", base, "--repo", tree, "--sign", "CHECK-b"]) + _l, rows = parse_baseline(base) + signed = {r["path"]: r["rc"] for r in rows} + rc2, _o2 = run(["--baseline", base, "--repo", tree, "--sign", "CHECK-b"]) + cell("sign-once", rc == 0 and signed.get("CHECK-b") == 1 and rc2 == 1 + and len(rows) == 2, + "rc=%d b=%s again_rc=%d rows=%d" + % (rc, signed.get("CHECK-b"), rc2, len(rows))) + + # 12 -- a fault line carrying a tab stays one note cell, and the sweep's + # own reader reads the whole line back. Written verbatim it became four + # fields and read back as "FAIL tabbed": a writer that reports success + # and a reader that grades a truncated string. + with open(base, "w", encoding="utf-8") as fh: + fh.write("# path\trc\tnote\nCHECK-tabbed\t0\tstale\n") + rc, _o = run(["--baseline", base, "--repo", tree, "--all", "--write"]) + raw = [l for l in open(base, encoding="utf-8").read().split("\n") + if l.startswith("CHECK-tabbed")] + nf = len(raw[0].split("\t")) if raw else 0 + _r, srows = check_sweep.read_baseline(base) + got = srows[0][2] if srows else "" + want = "FAIL tabbed faultline after the tab" + cell("note-sanitised", rc == 0 and nf == 3 and got == want, + "rc=%d fields=%d note=%r" % (rc, nf, got)) + finally: + import shutil + shutil.rmtree(work, ignore_errors=True) + + print("selftest: %d cell(s), %d passed, %d failed" + % (cells, cells - cell_failed, cell_failed)) + return 0 if cell_failed == 0 else 1 + + +if __name__ == "__main__": + raise SystemExit(main())