volt: q148 -- retake tool for the entry-point baseline, three rows re-taken, one signed
This commit is contained in:
1 parent
326288cd49
commit
fad7837bb3
6 files changed
+739
-23
No files matched your search
+136
@@ -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
|
||||
@@ -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
|
||||
+54
-17
@@ -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,
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
Can't render this file because it contains an unexpected character in line 88 and column 87.
|
@@ -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())
|
||||
Reference in new issue
Block a user