From 1ec068cae0d67a316e68704a66ea9683ebe3674c Mon Sep 17 00:00:00 2001 From: volt Date: Wed, 4 Nov 2026 12:47:43 +0000 Subject: [PATCH] volt: Q168 land -- the append audit grades the pin axis beside the index axis queue_append_audit.py now runs two graders out of one `git archive`: grade_index (unchanged vocabulary) and grade_pin, which runs the rev's own open_set.py --check beside the rev's own queue. PASS / DRIFT / UNGRADABLE / ERROR; rc 1 when either axis is fatal, so --guard means "index current and pin moved". --axis {both,index,pin} narrows the run; the report prints index:/pin:/drift:. Checks landed with it: CHECK-append-pin (5 legs, rc 0 here). Measured at 12fb1b0's parent line: --selftest 43/43; --guard rc 0 pin:PASS; 1c3c855..56d3853 rc 1 pin:DRIFT "count headings moved 116 -> 117" while --axis index over the same range reads rc 0, and 12fb1b0's pre-axis blob reads rc 0 too, so the red is the axis and not the range. PIN_COUNTS moved to the post-append counts (119 headings/103 ids, 131 records/97 ids) and docs/queue-index.md re-rendered; docs/TOOLS.md row follows the tool's flags. --- CHECK-append-pin | 108 ++++++ WORK-QUEUE.md | 22 ++ docs/TOOLS.md | 2 +- docs/queue-index.md | 83 +++- tools/queue_append_audit.py | 354 ++++++++++++++---- wizard-work/volt/q137-open-set/open_set.py | 12 +- .../q143-check-sweep/check_entry_baseline.tsv | 1 + 7 files changed, 487 insertions(+), 95 deletions(-) create mode 100755 CHECK-append-pin diff --git a/CHECK-append-pin b/CHECK-append-pin new file mode 100755 index 0000000..93ed31b --- /dev/null +++ b/CHECK-append-pin @@ -0,0 +1,108 @@ +#!/usr/bin/env bash +# CHECK -- the Q168 repair: the append audit now grades the queue's own PIN, in +# each commit's own tree, beside the rendered index. +# +# `tools/queue_append_audit.py` graded one axis: was `docs/queue-index.md` +# re-rendered in the commit that appended to `WORK-QUEUE.md`? `56d3853` is the +# counter-example the repo gate paid for -- it re-rendered its index (PASS, +# rc 0) and left `open_set.py`'s PIN_COUNTS two headings behind, which the +# open-set leg only read two commits later. Five legs: +# selftest the tool's own cells pass, and there are 43 of them +# gate the newest queue-touching commit is clean on BOTH axes +# axes the historic commit reads index PASS, pin DRIFT, rc 1 -- and the +# same commit read --axis index alone reads rc 0, so the red is the +# pin axis and not the range +# preaxis the tool AS IT STOOD BEFORE THE AXIS reads rc 0 over that same +# range, so the changed reading is the axis and not the history +# axis --axis pin grades the pin alone and sets no index verdict +# rc 0 clean, rc 1 a fault it graded, rc 2 it could not grade at all. +set -u + +ROOT="$(cd "$(dirname "$0")" && pwd)" +TOOL="tools/queue_append_audit.py" +PIN_TOOL="wizard-work/volt/q137-open-set/open_set.py" +PRE_AXIS_REV="12fb1b0" # the last commit before the pin axis was written +DRIFT_REV="56d3853" # index PASS, pin DRIFT: the shape the axis exists for +DRIFT_PARENT="1c3c855" +DRIFT_COUNT="count headings moved 116 -> 117" +WANT_CELLS=43 + +faults=0 +leg() { printf '%-9s %s\n' "$1" "$2"; } + +for f in "$ROOT/$TOOL" "$ROOT/$PIN_TOOL"; do + if [ ! -f "$f" ]; then + echo "append-pin: missing $f; cannot grade" >&2 + exit 2 + fi +done +if ! git -C "$ROOT" rev-parse --git-dir >/dev/null 2>&1; then + echo "append-pin: $ROOT is not a git repository; no commit can be graded" >&2 + exit 2 +fi +if ! git -C "$ROOT" cat-file -e "$PRE_AXIS_REV:$TOOL" 2>/dev/null; then + echo "append-pin: $PRE_AXIS_REV has no $TOOL; the pre-axis reading cannot be taken" >&2 + exit 2 +fi + +TMP="$(mktemp -d "${TMPDIR:-/tmp}/append-pin.XXXXXX")" || exit 2 +trap 'rm -rf "$TMP"' EXIT + +# selftest -- the tool's own cells, including the six pin-axis cells +out="$(cd "$ROOT" && python3 "$TOOL" --selftest 2>&1)"; rc=$? +summary="$(printf '%s\n' "$out" | grep '^selftest:')" +if [ "$rc" -eq 0 ] && [ "$summary" = "selftest: $WANT_CELLS cells, $WANT_CELLS passed, 0 failed" ]; then + leg selftest "ok (rc 0, $summary)" +else + leg selftest "FAULT (rc $rc, ${summary:-no summary line})"; faults=$((faults + 1)) +fi + +# gate -- the newest queue-touching commit, on both axes, in its own tree +out="$(cd "$ROOT" && python3 "$TOOL" --repo "$ROOT" --guard 2>&1)"; rc=$? +if [ "$rc" -eq 0 ] \ + && printf '%s\n' "$out" | grep -q 'pin:PASS' \ + && printf '%s\n' "$out" | grep -q 'every graded commit left its own tree consistent'; then + leg gate "ok (rc 0, $(printf '%s\n' "$out" | grep -o 'pin:[A-Z]*' | head -1), index and pin clean)" +else + leg gate "FAULT (rc $rc: $(printf '%s\n' "$out" | grep '^verdict:' | head -1))" + faults=$((faults + 1)) +fi + +# axes -- the commit the index axis called clean and the pin axis calls DRIFT +out="$(cd "$ROOT" && python3 "$TOOL" --repo "$ROOT" --from "$DRIFT_PARENT" --to "$DRIFT_REV" 2>&1)"; rc=$? +idx="$(cd "$ROOT" && python3 "$TOOL" --repo "$ROOT" --from "$DRIFT_PARENT" --to "$DRIFT_REV" --axis index 2>&1)"; irc=$? +if [ "$rc" -eq 1 ] && [ "$irc" -eq 0 ] \ + && printf '%s\n' "$out" | grep -q 'pin:DRIFT' \ + && printf '%s\n' "$out" | grep -qF "$DRIFT_COUNT" \ + && printf '%s\n' "$out" | grep -q "drift: $DRIFT_REV"; then + leg axes "ok ($DRIFT_REV rc 1 pin:DRIFT, --axis index rc 0; $(printf '%s\n' "$out" | grep -o 'count headings moved [0-9]* -> [0-9]*'))" +else + leg axes "FAULT (rc $rc want 1, --axis index rc $irc want 0)"; faults=$((faults + 1)) +fi + +# preaxis -- the same range through the tool before the axis: rc 0 +git -C "$ROOT" show "$PRE_AXIS_REV:$TOOL" > "$TMP/pre_axis.py" || exit 2 +out="$(cd "$ROOT" && python3 "$TMP/pre_axis.py" --repo "$ROOT" --from "$DRIFT_PARENT" --to "$DRIFT_REV" 2>&1)"; rc=$? +if [ "$rc" -eq 0 ] && printf '%s\n' "$out" | grep -q 'every graded commit left the index current'; then + leg preaxis "ok ($PRE_AXIS_REV's tool reads rc 0 over the same range; the axis moved the reading)" +else + leg preaxis "FAULT (pre-axis tool rc $rc want 0 -- the range was red before the axis)"; faults=$((faults + 1)) +fi + +# axis -- --axis pin grades one axis and writes no index verdict for it +json="$TMP/pin.json" +out="$(cd "$ROOT" && python3 "$TOOL" --repo "$ROOT" --guard --axis pin --json "$json" 2>&1)"; rc=$? +verdicts="$(grep -c '"verdict"' "$json" 2>/dev/null || true)" +passes="$(grep -c '"pin": "PASS"' "$json" 2>/dev/null || true)" +if [ "$rc" -eq 0 ] && [ "${verdicts:-1}" -eq 0 ] && [ "${passes:-0}" -eq 1 ]; then + leg axis "ok (rc 0, 0 index verdicts, 1 pin PASS in the JSON)" +else + leg axis "FAULT (rc $rc, index verdicts ${verdicts:-?}, pin PASS ${passes:-?})"; faults=$((faults + 1)) +fi + +if [ "$faults" -eq 0 ]; then + echo "append-pin: 5 leg(s), 0 fault(s)" + exit 0 +fi +echo "append-pin: 5 leg(s), $faults fault(s)" +exit 1 diff --git a/WORK-QUEUE.md b/WORK-QUEUE.md index 95f9229..52453e2 100644 --- a/WORK-QUEUE.md +++ b/WORK-QUEUE.md @@ -14690,3 +14690,25 @@ At `406dd17`, `python3 tools/verify.py --fast` read **12 legs, 10 pass, 1 fault, **(3) Bookkeeping, measured after the append and before the commit landed.** The append carries a heading (`## Q167 closure`) and a record (`**Q167 — OPENED and REPAIRED ...`) for a new id: headings 117 -> 118, heading_ids 101 -> 102, records 129 -> 130, record_ids 95 -> 96, ids 156 -> 157; `record_only` stays 55 and `open` / `opened` stay 0 / 26, because a same-tick `OPENED and REPAIRED` is a closure (the Q138 rule), so no probe is registered for Q167 and CHECK-q167 is its guard. `python3 tools/queue_index.py --write docs/queue-index.md` re-rendered. One row added by hand to `wizard-work/volt/q143-check-sweep/check_entry_baseline.tsv` for the new root entry point, with the code measured at this landing. **(4) Not claimed.** That the append's author had a rule to read: Q156 wrote the rule down, and `tools/queue_append_audit.py` still grades the index only, not the pin — so a commit in this shape reads `append-audit PASS` while the gate reds. This record repairs the pin and guards the committed tree at HEAD; it does not extend the per-commit audit, and that gap is named here as the next instrument rather than closed. That the new baseline row is a pass in the sweep: it is a reading taken by hand, and the sweep leg that would grade it (`check_sweep.py`) is not in the `--fast` gate. + +## Q168 closure — the append audit graded the rendered index and not the queue's own pin, so `56d3853` read clean in the one tool built to catch that commit; the pin is now a second axis, graded in the same tree *(volt, 2026-11-04, at `12fb1b0` for the tool as it stood and the commit this record lands in; tools lane, unclaimed and taken)* + +**Q168 — OPENED and REPAIRED in the same tick (volt; opened, repaired and measured in the 2026-11-04 12:29 tick at `12fb1b0`, and recorded by the commit this record lands in; tools lane, no lane owns it by authorship, unclaimed and taken).** `tools/queue_append_audit.py` answered one question: did the commit that appended to `WORK-QUEUE.md` re-render `docs/queue-index.md` in its own tree? `56d3853` answered yes and was still wrong. That commit appended the second Q69 addendum, shipped the re-rendered index, and left `wizard-work/volt/q137-open-set/open_set.py`'s `PIN_COUNTS` where Q156 had put it, so the queue's own pin check read red in the commit itself while the audit built to grade that commit read green. Q167's record names the consequence — the repo gate stood red at `HEAD` for two commits, `406dd17` reading `fault: open-set` — and names the gap in its own (4): *"`tools/queue_append_audit.py` still grades the index only, not the pin"*. This record closes that, because a guard whose subject is "the queue's bookkeeping is consistent in its own commit" cannot be one axis deep. + +**(1) The gap, measured at two revs instead of read off the diff.** At `56d3853`, the pre-axis tool (`git show 12fb1b0:tools/queue_append_audit.py`) over `1c3c855..56d3853` reads **rc 0**, one row: `PASS 56d3853 … index:yes index current: index: 267 items …`. That same commit's own tree, exported with `git archive` and graded by its own `open_set.py`, reads **rc 1**: `queue: 14675 lines, 117 headings/101 ids, 129 records/95 ids`, `FAIL count headings moved 116 -> 117`, `CHECK 1 fault(s)`. Its parent `1c3c855` reads **rc 0** under the same pin, `CHECK OK: … counts match the pin`. So the fault is one commit wide and the audit's blind spot is exactly its width: the axis that was graded was current, the axis that was not was the one the gate reds on. + +**(2) The repair: a second axis, graded in the same materialised tree, reported beside the first.** `audit_commit` is now two graders — `grade_index` (unchanged in verdict vocabulary: PASS / STALE / UNGRADABLE / ERROR, still `tools/queue_index.py` as it existed at that rev) and `grade_pin`, which runs the rev's own `wizard-work/volt/q137-open-set/open_set.py --check` with the rev's own `WORK-QUEUE.md` beside it. The pin vocabulary is PASS / DRIFT (rc 1: the queue moved, the pin did not) / UNGRADABLE (no `open_set.py` at that rev — the pin is younger than the queue — or the tool refused with rc 2) / ERROR, and `DRIFT` is in neither the index buckets nor `UNGRADABLE`: a tree the tool could not read is not a drift. Both axes come out of one `git archive`, so a row cannot be current on one tree and drifted on another. `--axis {both,index,pin}` narrows the run to one axis (`both` is the default), the report prints `index:` and `pin:` columns and a `drift:` line, and `pin_graded` counts PASS+DRIFT+ERROR only, the same rule `graded` already followed. rc is 1 when **either** axis is fatal, so `--guard` — the shape the repo gate calls — now means "the commit about to be pushed left the index current **and** moved the pin". + +**(3) Readings after, at this tree.** `python3 tools/queue_append_audit.py --selftest` → **43 cells, 43 passed, 0 failed** (25 before the axis; the fixture grew a pin stub and two commits: one that appends a heading and re-renders without moving the pin, one that appends a record and moves it). `--repo . --guard` → **rc 0**, `PASS 12fb1b0 … pin:PASS`, `graded: 1 of 1 index, 1 of 1 pin`, `verdict: every graded commit left its own tree consistent`. `--repo . --from 1c3c855 --to 56d3853` → **rc 1**, `PASS … pin:DRIFT … | pin: FAIL count headings moved 116 -> 117`, `drift: 56d3853`, `verdict: 1 commit(s) left their own tree inconsistent -- 0 index, 1 pin`. `--axis index` over the same range reads **rc 0**, and the pre-axis blob reads **rc 0** over it, so the red is the new axis and not the range. Run over the whole default range (`--axis pin`, 283 queue-touching commits, rows in `/root/.hermes/wizard-outputs/volt/q168-pin-range.json`): **36 PASS, 2 DRIFT, 245 UNGRADABLE** — the pin is younger than those commits, and `pin_graded` is 38 of 283. Cross-tabbed against the index axis over the same 283 revs (`265 PASS, 18 STALE`): the only rev the index axis calls PASS and the pin axis calls DRIFT is **`56d3853`**, the drift `c05f05a` having already been STALE on the index axis. So the second axis adds exactly one fault to the table, and it is the one the repo gate stayed red over. + +**(4) The guard this item ships: `CHECK-append-pin`, five legs, rc 0/1/2.** `selftest` (rc 0 and exactly the 43-cell summary line, so a deleted cell is a fault and not a shorter green), `gate` (`--guard` rc 0 with `pin:PASS` and the clean verdict line), `axes` (the historic range rc 1 with `pin:DRIFT`, the tool's own `count headings moved 116 -> 117`, and a `drift: 56d3853` line **while** `--axis index` over the same range reads rc 0), `preaxis` (`12fb1b0`'s blob reads rc 0 over that same range — the changed reading is the axis, not the history) and `axis` (`--guard --axis pin --json` reads rc 0, writes **0** `"verdict"` keys and one `"pin": "PASS"`). Measured here: `bash CHECK-append-pin` → **rc 0**, `append-pin: 5 leg(s), 0 fault(s)`, every leg printing its own reading. + +**(5) The teeth, measured by neutering the axis rather than argued from the fixture.** A copy of the tool whose `grade_pin` returns `{"pin": "PASS", "pin_rc": 0}` unconditionally reads **43 cells, 36 passed, 7 failed** on `--selftest` (the pin cells, the drift detail, the drift report line, the two axis-scoped cells and the `--guard`-on-drift cell), and **rc 0 with `pin: 1 PASS`** over `1c3c855..56d3853` — the same range that reads rc 1 above. So the red in (3) is the axis's measurement and not a range that was red anyway. + +**(6) Bookkeeping, measured after this append and before the commit landed.** The append carries one heading (`## Q168 closure`) and one record (`**Q168 — OPENED and REPAIRED …**`) for a new id: headings 118 → 119, heading_ids 102 → 103, records 130 → 131, record_ids 96 → 97, ids 157 → 158; `record_only` stays 55 and `open` / `opened` stay 0 / 26, because a same-tick `OPENED and REPAIRED` is a closure (the Q138 rule), so no probe is registered for Q168 and `CHECK-append-pin` is its guard. `PIN_COUNTS` in `open_set.py` moved to the counts this append makes — the repair's own subject, applied to the repair's own commit, and the new `pin` axis is what grades it at the landing. `python3 tools/queue_index.py --write docs/queue-index.md` re-rendered; one row was added to `wizard-work/volt/q143-check-sweep/check_entry_baseline.tsv` for the new entry point with the code measured above (rc 0). + +**(7) Not claimed.** That `DRIFT` means the commit was *wrong* to land — it means the pin and the queue disagreed in that tree, which is what `open_set.py --check` already said in the same tree. That the axis is expensive — it is one subprocess per graded commit, taken from the same `git archive` the index axis already paid for, and `--axis index` restores the old cost exactly. That the historical table is now clean — the default range still carries the 18 index-STALE commits it carried before, and this record repairs none of them; what changed is that a pin drift is no longer invisible in the same run. That every future append will move the pin correctly — the axis makes the miss visible in the commit that lands it, which is the whole of what a guard can do. That `open_set.py` belongs to `tools/` — it does not; the audit reads it as the queue's pin wherever it lives, and a move of that path is a `UNGRADABLE` row and a one-line edit here, not a silent pass. + +Files: `tools/queue_append_audit.py` (the pin axis, `grade_index`/`grade_pin`, `--axis`, the report columns, the 43-cell selftest), `CHECK-append-pin` (new, five legs), `wizard-work/volt/q137-open-set/open_set.py` (the `PIN_COUNTS` move), `wizard-work/volt/q143-check-sweep/check_entry_baseline.tsv` (one row), `WORK-QUEUE.md` (this record), `docs/queue-index.md` (re-rendered). Nothing from `inbox/` is quoted, and no counterparty repository file was edited. + +CHECK: `bash CHECK-append-pin` diff --git a/docs/TOOLS.md b/docs/TOOLS.md index b5302f5..45a0297 100644 --- a/docs/TOOLS.md +++ b/docs/TOOLS.md @@ -25,7 +25,7 @@ module docstring, flags from the tool's own `--help`, probe rows from | `landing_check.py` | is every file at this revision actually served by the forge? | `--repo` `--rev` `--branch` `--base-url` `--path` `--max-bytes` `--timeout` `--json` `--quiet` `--selftest` | 1 / 0 / 1 | - | | `manifest_audit.py` | does an artifact's `files.sha256` still describe the bytes beside it? | `--root` `--baseline` `--strict` `--fail` `--json` `--quiet` `--selftest` | 1 / 0 / 2 | - | | `path_claim_check.py` | does every in-namespace path this archive names exist at this revision? | `--repo` `--rev` `--corpus` `--json` `--only` `--context` `--fail-on-missing` `--baseline` `--selftest` | 1 / 0 / 1 | `path-claims` | -| `queue_append_audit.py` | was the queue's index current IN THE TREE of every commit that touched the queue? | `--repo` `--queue` `--index` `--from` `--to` `--all` `--guard` `--timeout` `--json` `--selftest` | 1 / 0 / 1 | `append-audit` | +| `queue_append_audit.py` | did every queue-touching commit leave its own tree consistent: its index current, and its pin moved to where the queue's counts went? | `--repo` `--queue` `--index` `--from` `--to` `--all` `--guard` `--axis` `--timeout` `--json` `--selftest` | 1 / 0 / 1 | `append-audit` | | `queue_claim_check.py` | the claim check for `WORK-QUEUE.md`, shipped with its tests. | `--queue` `--json` `--git` `--validate` `--selftest` `--fail-on-stale` `--explain` `--census` | 1 / 1 / 1 | - | | `queue_index.py` | the work queue's table of contents, and the gate that it is current. | `--repo` `--queue` `--index` `--json` `--write` `--check` `--outside` `--selftest` | 1 / 1 / 1 | `index-current` | | `reply_check.py` | does every reply file's own header agree with its own name? | `--repo` `--dir` `--roster` `--head-lines` `--json` `--baseline` `--emit-baseline` | 1 / 0 / 1 | `reply-headings` | diff --git a/docs/queue-index.md b/docs/queue-index.md index 0a457b9..45da976 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. 118 sections carry 102 ids because 15 ids own a second, continuation section; 60 further ids are opened by a record and own no heading at all, and they have rows and extents here -- 151 record blocks in all, 91 of them a later closure or correction for an id already opened. The same **60 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. 119 sections carry 103 ids because 15 ids own a second, continuation section; 60 further ids are opened by a record and own no heading at all, and they have rows and extents here -- 152 record blocks in all, 92 of them a later closure or correction for an id already opened. The same **60 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:` | |---|---|---|---|---|---|---|---| @@ -276,7 +276,9 @@ | 266 | Q69 | heading | 14633-14654 | 6065 | cont: addendum | addendum — the host-absolute class counted by AST position: 542 of 1345 tracked files carry such a path as a value, and volt's one default-root defect now follows its own file *(volt, 2026-11-04, at … | -- | | 267 | Q69 | heading | 14655-14676 | 5482 | cont: addendum | addendum 2 — the probe's scratch root derived from TMPDIR: one of the nine named files is clean, and the lane reads 8 code files / 15 constants *(volt, 2026-11-04, at `5b71db6` and the commit this … | -- | | 268 | Q167 | heading | 14677-14678 | 228 | opening | closure — the queue's pin sat two commits behind the queue, and nothing graded the pin in the commit *(volt, 2026-11-04, at `56d3853` and the commit this record lands in; sol lane by authorship … | -- | -| 269 | Q167 | record | 14679-14692 | 4171 | cont: OPENED | **Q167 — OPENED and REPAIRED in the same tick (volt, 2026-11-04, at `56d3853` and the commit this record lands in; sol lane by authorship, unclaimed and taken).** The repo gate has been red at HEAD … | -- | +| 269 | Q167 | record | 14679-14693 | 4172 | cont: OPENED | **Q167 — OPENED and REPAIRED in the same tick (volt, 2026-11-04, at `56d3853` and the commit this record lands in; sol lane by authorship, unclaimed and taken).** The repo gate has been red at HEAD … | -- | +| 270 | Q168 | heading | 14694-14695 | 344 | opening | closure — the append audit graded the rendered index and not the queue's own pin, so `56d3853` read clean in the one tool built to catch that commit; the pin is now a second axis, graded in the same … | -- | +| 271 | Q168 | record | 14696-14714 | 8236 | cont: OPENED | **Q168 — OPENED and REPAIRED in the same tick (volt; opened, repaired and measured in the 2026-11-04 12:29 tick at `12fb1b0`, and recorded by the commit this record lands in; tools lane, no lane owns … | -- | ## Ids with no `## ` heading @@ -331,7 +333,7 @@ Opened as records inside another section. `line` is the record's own opening lin | Q135 | 13797 | 13797 | 2 | Q114 | BULLET+BOLD | BOLD-LEAD | | Q136 | 13831 | 13831 | 1 | Q87 | BULLET+BOLD | BOLD-LEAD | | Q137 | 13847 | 13847 | 3 | Q136 | BULLET+BOLD | BOLD-LEAD | -| Q138 | 13879 | 13879 | 15 | Q137 | BULLET+BOLD | BOLD-LEAD | +| Q138 | 13879 | 13879 | 16 | Q137 | BULLET+BOLD | BOLD-LEAD | | Q139 | 13897 | 13897 | 4 | Q138 | BULLET+BOLD | BOLD-LEAD | | Q140 | 13918 | 13918 | 9 | Q139 | BULLET+BOLD | BOLD-LEAD | | Q141 | 13938 | 13938 | 6 | Q140 | BULLET+BOLD | BOLD-LEAD | @@ -2306,17 +2308,30 @@ The block below is the parse this document renders, byte for byte. `--check` com "title": "**Q84 \u2014 CLOSED at HEAD. The repair landed at `b14d2e4` (\"beam: cells for interval_overlap.py -- CHECK 202 -> 214, rc 0; docstring names has_any_overlap, early exit added (Q84)\") and the pipe accepted \u2026" }, { - "bytes": 4171, - "end_line": 14692, + "bytes": 4172, + "end_line": 14693, "id": "Q167", "kind": "record", "line": 14679, - "lines": 14, + "lines": 15, "role": "continuation", "role_detail": "OPENED", "status": null, "status_line": null, "title": "**Q167 \u2014 OPENED and REPAIRED in the same tick (volt, 2026-11-04, at `56d3853` and the commit this record lands in; sol lane by authorship, unclaimed and taken).** The repo gate has been red at HEAD \u2026" + }, + { + "bytes": 8236, + "end_line": 14714, + "id": "Q168", + "kind": "record", + "line": 14696, + "lines": 19, + "role": "continuation", + "role_detail": "OPENED", + "status": null, + "status_line": null, + "title": "**Q168 \u2014 OPENED and REPAIRED in the same tick (volt; opened, repaired and measured in the 2026-11-04 12:29 tick at `12fb1b0`, and recorded by the commit this record lands in; tools lane, no lane owns \u2026" } ], "ids_multi_section": { @@ -2484,7 +2499,8 @@ The block below is the parse this document renders, byte for byte. `--check` com "Q164", "Q165", "Q166", - "Q167" + "Q167", + "Q168" ], "items": [ { @@ -5972,17 +5988,43 @@ The block below is the parse this document renders, byte for byte. `--check` com "title": "closure \u2014 the queue's pin sat two commits behind the queue, and nothing graded the pin in the commit *(volt, 2026-11-04, at `56d3853` and the commit this record lands in; sol lane by authorship \u2026" }, { - "bytes": 4171, - "end_line": 14692, + "bytes": 4172, + "end_line": 14693, "id": "Q167", "kind": "record", "line": 14679, - "lines": 14, + "lines": 15, "role": "continuation", "role_detail": "OPENED", "status": null, "status_line": null, "title": "**Q167 \u2014 OPENED and REPAIRED in the same tick (volt, 2026-11-04, at `56d3853` and the commit this record lands in; sol lane by authorship, unclaimed and taken).** The repo gate has been red at HEAD \u2026" + }, + { + "bytes": 344, + "end_line": 14695, + "id": "Q168", + "kind": "heading", + "line": 14694, + "lines": 2, + "role": "opening", + "role_detail": "", + "status": null, + "status_line": null, + "title": "closure \u2014 the append audit graded the rendered index and not the queue's own pin, so `56d3853` read clean in the one tool built to catch that commit; the pin is now a second axis, graded in the same \u2026" + }, + { + "bytes": 8236, + "end_line": 14714, + "id": "Q168", + "kind": "record", + "line": 14696, + "lines": 19, + "role": "continuation", + "role_detail": "OPENED", + "status": null, + "status_line": null, + "title": "**Q168 \u2014 OPENED and REPAIRED in the same tick (volt; opened, repaired and measured in the 2026-11-04 12:29 tick at `12fb1b0`, and recorded by the commit this record lands in; tools lane, no lane owns \u2026" } ], "nested": [ @@ -6414,7 +6456,7 @@ The block below is the parse this document renders, byte for byte. `--check` com "form": "BOLD-LEAD", "id": "Q138", "line": 13879, - "refs": 15, + "refs": 16, "section": "Q137", "shape": "BULLET+BOLD" }, @@ -6532,9 +6574,9 @@ The block below is the parse this document renders, byte for byte. `--check` com "end_line": 8, "line": 1 }, - "queue_bytes": 2548660, - "queue_lines": 14692, - "queue_sha256": "4abf6817fef75d3b13ef3b1fa4b38e4f74b5b56ae26727c555d46d5d46e8be03", + "queue_bytes": 2557241, + "queue_lines": 14714, + "queue_sha256": "9341e983b3aecc12c5f42dbd4b9df8274d6115dea08df01a29c1875bfaa7a5d7", "sections": [ { "bytes": 3139, @@ -8069,6 +8111,19 @@ The block below is the parse this document renders, byte for byte. `--check` com "status": null, "status_line": null, "title": "closure \u2014 the queue's pin sat two commits behind the queue, and nothing graded the pin in the commit *(volt, 2026-11-04, at `56d3853` and the commit this record lands in; sol lane by authorship \u2026" + }, + { + "bytes": 344, + "end_line": 14695, + "id": "Q168", + "kind": "heading", + "line": 14694, + "lines": 2, + "role": "opening", + "role_detail": "", + "status": null, + "status_line": null, + "title": "closure \u2014 the append audit graded the rendered index and not the queue's own pin, so `56d3853` read clean in the one tool built to catch that commit; the pin is now a second axis, graded in the same \u2026" } ] } diff --git a/tools/queue_append_audit.py b/tools/queue_append_audit.py index 58cf3b8..a44b2ac 100644 --- a/tools/queue_append_audit.py +++ b/tools/queue_append_audit.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 -"""queue_append_audit.py -- was the queue's index current IN THE TREE of every -commit that touched the queue? +"""queue_append_audit.py -- did every queue-touching commit leave its own tree +consistent: its index current, and its pin moved to where the queue's counts +went? WHY THIS EXISTS `docs/queue-index.md` is rendered from `WORK-QUEUE.md` and pins it by sha256, @@ -22,7 +23,9 @@ WHY THIS EXISTS the gate as it existed there. WHAT IT MEASURES -- one row per commit that touches the queue in the range - verdict PASS the commit's own tree passes its own --check (rc 0) + verdict the INDEX axis: the commit's own tree passes its own + `tools/queue_index.py --check` (rc 0) + PASS rc 0 STALE --check graded a stale rendered document (rc 1) UNGRADABLE the gate did not exist in that tree (no tools/queue_index.py, or no index document), or the @@ -32,6 +35,19 @@ WHAT IT MEASURES -- one row per commit that touches the queue in the range bucket is the exact defect this tool was built after. ERROR any other exit, a crash, or a timeout. rc 1 without the tool's `STALE:` line is a crash, not a fault. + pin the PIN axis: the same tree's own + `wizard-work/volt/q137-open-set/open_set.py --check`, which + compares WORK-QUEUE.md's counts with the PIN_COUNTS that file + carries. + PASS rc 0, the pin moved with the append + DRIFT rc 1, the queue moved and the pin did not + UNGRADABLE no open_set.py at that rev (the pin is younger than + the queue), or the tool refused with rc 2 + ERROR any other exit, a crash, or a timeout + The two axes are graded in ONE materialised tree and reported + side by side, because neither stands for the other: `56d3853` + re-rendered its index and left the pin two headings behind, so + its row reads `PASS` on the index and `DRIFT` on the pin. queue_add/del numstat for the queue in that commit. index_changed whether the same commit also changed the index document -- the mechanical shape of the rule, reported BESIDE the verdict and @@ -41,7 +57,8 @@ WHAT IT MEASURES -- one row per commit that touches the queue in the range would be such a case, and the verdict would say so). Precedence is deliberate: the verdict comes from a checkout of the commit, - never from its message, and never from a run at HEAD. + never from its message, and never from a run at HEAD. `--axis` narrows the run + to one of the two axes; the default grades both. WHAT IT DOES NOT DO It repairs nothing, decides nothing about whether an UNGRADABLE commit should @@ -49,7 +66,7 @@ WHAT IT DOES NOT DO `tools/queue_claim_check.py`'s verdict. `--guard` is the same measurement restricted to the NEWEST queue-touching commit, which is the shape a tick's `check.sh` can call: rc 0 means the commit about to be pushed left the index - current in its own tree. + current AND the pin moved in its own tree. EXIT CODES (house contract, decided 2026-10-17 at 6ee8fce) 0 ran; nothing graded faulty (UNGRADABLE rows are reported, not faults) @@ -78,8 +95,15 @@ import tempfile QUEUE_DEFAULT = "WORK-QUEUE.md" INDEX_DEFAULT = "docs/queue-index.md" GATE_TOOL = "tools/queue_index.py" +# The queue's own pin, graded in the SAME materialised tree: `open_set.py +# --check` compares WORK-QUEUE.md's counts against the PIN_COUNTS the file +# carries. The index axis cannot see it -- `56d3853` rendered its index and left +# the pin two headings behind -- so the audit grades both axes, each reported +# beside the other and neither standing for the other. +PIN_TOOL = "wizard-work/volt/q137-open-set/open_set.py" HERE = os.path.dirname(os.path.abspath(__file__)) FATAL = ("STALE", "ERROR") +PIN_FATAL = ("DRIFT", "ERROR") # ---------------------------------------------------------------- git plumbing @@ -166,61 +190,126 @@ def materialise(repo, rev, paths, dest): # ------------------------------------------------------------------- one commit -def audit_commit(repo, rev, queue, index, timeout): - """Grade one commit IN ITS OWN TREE. Never raises.""" +def run_check(cmd, cwd, timeout): + """(rc, stdout, stderr, why) -- a timeout is a verdict, never a traceback.""" + try: + p = subprocess.run(cmd, cwd=cwd, capture_output=True, timeout=timeout) + except subprocess.TimeoutExpired: + return None, "", "", "--check timed out after %ss" % timeout + return (p.returncode, p.stdout.decode("utf-8", "replace"), + p.stderr.decode("utf-8", "replace"), "") + + +def grade_index(td, queue, index, timeout): + """The index axis, measured in `td`: {verdict, rc, detail}.""" + tool = os.path.join(td, GATE_TOOL) + cmd = [sys.executable, tool, + "--repo", td, + "--queue", os.path.join(td, queue), + "--check", os.path.join(td, index)] + rc, s, e, why = run_check(cmd, td, timeout) + if why: + return {"verdict": "ERROR", "rc": None, "detail": why} + first = (s.strip() or e.strip() or "").splitlines() + out = {"rc": rc, "detail": first[0][:180] if first else ""} + if rc == 0: + out["verdict"] = "PASS" + elif rc == 1 and "STALE:" in s: + out["verdict"] = "STALE" + elif rc == 2: + out["verdict"] = "UNGRADABLE" + else: + # rc 1 with no STALE line is a crash wearing the verdict code; rc 3 + # is retired. Neither is a graded fault, and neither is a pass. + out["verdict"] = "ERROR" + return out + + +def grade_pin(td, timeout): + """The pin axis, measured in `td`: {pin, pin_rc, pin_detail}. + + `open_set.py --check` compares the queue's own counts against the PIN_COUNTS + the file carries, so a commit that appends a heading or a record and leaves + the pin where it was reads DRIFT here even when its index is current -- the + exact shape `56d3853` landed in, which the index axis read PASS. + """ + tool = os.path.join(td, PIN_TOOL) + rc, s, e, why = run_check([sys.executable, tool, "--check"], td, timeout) + if why: + return {"pin": "ERROR", "pin_rc": None, "pin_detail": why} + lines = (s.strip() or e.strip() or "").splitlines() + fault = [ln for ln in lines if ln.startswith("FAIL")] + out = {"pin_rc": rc, "pin_detail": (fault[0] if fault else (lines[-1] if lines else ""))[:180]} + if rc == 0: + out["pin"] = "PASS" + elif rc == 1: + out["pin"] = "DRIFT" + elif rc == 2: + # the pin tool itself refused: a tree it cannot read is not a drift + out["pin"] = "UNGRADABLE" + else: + out["pin"] = "ERROR" + return out + + +def audit_commit(repo, rev, queue, index, timeout, axis="both"): + """Grade one commit IN ITS OWN TREE. Never raises. + + Two axes, graded independently in one materialised tree, because neither + stands for the other: a commit can leave the rendered index current and the + queue's own pin two headings behind (Q167's landing), and a commit can move + the pin while shipping no index at all. + """ row = {"rev": rev} row.update(commit_meta(repo, rev)) add, delete, touched_index = numstat(repo, rev, queue, index) row.update({"queue_add": add, "queue_del": delete, - "index_changed": touched_index, "rc": None, "detail": ""}) + "index_changed": touched_index, "rc": None, "detail": "", + "pin_rc": None, "pin_detail": ""}) + + want_index = axis in ("both", "index") + want_pin = axis in ("both", "pin") if not exists(repo, rev, queue): - row.update(verdict="UNGRADABLE", - detail="%s does not exist at this rev" % queue) + missing = "%s does not exist at this rev" % queue + row.update(verdict="UNGRADABLE", detail=missing, + pin="UNGRADABLE", pin_detail=missing) return row - # The gate as it existed AT THAT REV, not as it exists today: a revision - # where queue_index.py had not been written yet has no gate, and no claim - # about its index can be true or false. - if not exists(repo, rev, GATE_TOOL): - row.update(verdict="UNGRADABLE", - detail="no %s at this rev (the gate did not exist yet)" % GATE_TOOL) - return row - if not exists(repo, rev, index): - row.update(verdict="UNGRADABLE", - detail="no %s at this rev (nothing to compare against)" % index) + if want_index: + # The gate as it existed AT THAT REV, not as it exists today: a revision + # where queue_index.py had not been written yet has no gate, and no + # claim about its index can be true or false. + if not exists(repo, rev, GATE_TOOL): + row.update(verdict="UNGRADABLE", + detail="no %s at this rev (the gate did not exist yet)" % GATE_TOOL) + want_index = False + elif not exists(repo, rev, index): + row.update(verdict="UNGRADABLE", + detail="no %s at this rev (nothing to compare against)" % index) + want_index = False + if want_pin and not exists(repo, rev, PIN_TOOL): + # the pin is younger than the queue: absent is UNGRADABLE, never DRIFT + row.update(pin="UNGRADABLE", + pin_detail="no %s at this rev" % PIN_TOOL) + want_pin = False + if not want_index and not want_pin: return row + wanted = [p for p in (queue, index, GATE_TOOL, PIN_TOOL) if exists(repo, rev, p)] td = tempfile.mkdtemp(prefix="qaa-") try: - ok, why = materialise(repo, rev, [queue, index, GATE_TOOL], td) + ok, why = materialise(repo, rev, wanted, td) if not ok: - row.update(verdict="ERROR", detail="could not materialise: %s" % why) + why = "could not materialise: %s" % why + if want_index: + row.update(verdict="ERROR", detail=why) + if want_pin: + row.update(pin="ERROR", pin_detail=why) return row - tool = os.path.join(td, GATE_TOOL) - cmd = [sys.executable, tool, - "--repo", td, - "--queue", os.path.join(td, queue), - "--check", os.path.join(td, index)] - try: - p = subprocess.run(cmd, cwd=td, capture_output=True, timeout=timeout) - except subprocess.TimeoutExpired: - row.update(verdict="ERROR", detail="--check timed out after %ss" % timeout) - return row - s = p.stdout.decode("utf-8", "replace") - e = p.stderr.decode("utf-8", "replace") - first = (s.strip() or e.strip() or "").splitlines() - row["detail"] = first[0][:180] if first else "" - row["rc"] = p.returncode - if p.returncode == 0: - row["verdict"] = "PASS" - elif p.returncode == 1 and "STALE:" in s: - row["verdict"] = "STALE" - elif p.returncode == 2: - row["verdict"] = "UNGRADABLE" - else: - # rc 1 with no STALE line is a crash wearing the verdict code; rc 3 - # is retired. Neither is a graded fault, and neither is a pass. - row["verdict"] = "ERROR" + if want_index: + row.update(grade_index(td, queue, index, timeout)) + if want_pin: + row.update(grade_pin(td, timeout)) return row finally: shutil.rmtree(td, ignore_errors=True) @@ -238,7 +327,7 @@ def queue_revs(repo, queue, rev_from, rev_to): def audit(repo, queue, index, rev_from, rev_to, guard=False, timeout=30, - all_history=False): + all_history=False, axis="both"): """(rc, payload). The only place exit codes are decided. Range rules, in order: @@ -253,8 +342,9 @@ def audit(repo, queue, index, rev_from, rev_to, guard=False, timeout=30, """ payload = {"repo": repo, "queue": queue, "index": index, "from": None, "to": None, "guard": bool(guard), - "auto_from": False, "pre_gate": 0, - "rows": [], "counts": {}, "graded": 0, "rc": None} + "auto_from": False, "pre_gate": 0, "axis": axis, + "rows": [], "counts": {}, "pin_counts": {}, + "graded": 0, "pin_graded": 0, "rc": None} def _grade_error(msg): """Attach a grade error to the payload and return the (2, payload) verdict. @@ -310,14 +400,21 @@ def audit(repo, queue, index, rev_from, rev_to, guard=False, timeout=30, except (ValueError, AttributeError): payload["pre_gate"] = 0 - rows = [audit_commit(repo, r, queue, index, timeout) for r in revs] - counts = {} + rows = [audit_commit(repo, r, queue, index, timeout, axis) for r in revs] + counts, pin_counts = {}, {} for r in rows: - counts[r["verdict"]] = counts.get(r["verdict"], 0) + 1 + if "verdict" in r: + counts[r["verdict"]] = counts.get(r["verdict"], 0) + 1 + if "pin" in r: + pin_counts[r["pin"]] = pin_counts.get(r["pin"], 0) + 1 payload["rows"] = rows payload["counts"] = counts - payload["graded"] = counts.get("PASS", 0) + counts.get("STALE", 0) + counts.get("ERROR", 0) - payload["rc"] = 1 if any(r["verdict"] in FATAL for r in rows) else 0 + payload["pin_counts"] = pin_counts + payload["graded"] = sum(counts.get(k, 0) for k in ("PASS", "STALE", "ERROR")) + payload["pin_graded"] = sum(pin_counts.get(k, 0) for k in ("PASS", "DRIFT", "ERROR")) + index_fault = any(r.get("verdict") in FATAL for r in rows) + pin_fault = any(r.get("pin") in PIN_FATAL for r in rows) + payload["rc"] = 1 if (index_fault or pin_fault) else 0 return payload["rc"], payload @@ -349,30 +446,47 @@ def report(payload, stream=sys.stdout): for r in payload["rows"]: add, dele = r["queue_add"], r["queue_del"] q = "q %s/%s" % (add if add is not None else "-", dele if dele is not None else "-") - w(" %-10s %-8s %-25s %-9s index:%-3s %s\n" - % (r["verdict"], r["short"], r["date"][:25], q, - "yes" if r["index_changed"] else "no", r["detail"])) + note = r.get("detail") or "" + if r.get("pin") and r["pin"] != "PASS": + note = "%s | pin: %s" % (note, r.get("pin_detail") or r["pin"]) + w(" %-10s %-8s %-25s %-9s index:%-3s pin:%-10s %s\n" + % (r.get("verdict") or "-", r["short"], r["date"][:25], q, + "yes" if r["index_changed"] else "no", r.get("pin") or "-", note)) c = payload["counts"] + pc = payload["pin_counts"] w("\nsummary: %d commit(s) -- %s\n" % (len(payload["rows"]), ", ".join("%d %s" % (c[k], k) for k in ("PASS", "STALE", "UNGRADABLE", "ERROR") if k in c) or "nothing graded")) + w("pin: %s\n" + % (", ".join("%d %s" % (pc[k], k) for k in ("PASS", "DRIFT", "UNGRADABLE", "ERROR") if k in pc) + or "not graded")) ungradable = c.get("UNGRADABLE", 0) - w("graded: %d of %d%s\n" + w("graded: %d of %d index, %d of %d pin%s\n" % (payload["graded"], len(payload["rows"]), - (" (%d could not be graded -- reported, NOT counted as stale)" % ungradable) + payload["pin_graded"], len(payload["rows"]), + (" (%d index UNGRADABLE -- reported, NOT counted as stale)" % ungradable) if ungradable else "")) - stale = [r["short"] for r in payload["rows"] if r["verdict"] == "STALE"] + stale = [r["short"] for r in payload["rows"] if r.get("verdict") == "STALE"] if stale: w("stale: %s\n" % " ".join(stale)) - bad = [r["short"] for r in payload["rows"] if r["verdict"] == "ERROR"] + drift = [r["short"] for r in payload["rows"] if r.get("pin") == "DRIFT"] + if drift: + w("drift: %s\n" % " ".join(drift)) + bad = [r["short"] for r in payload["rows"] if r.get("verdict") == "ERROR"] + pbad = [r["short"] for r in payload["rows"] if r.get("pin") == "ERROR"] if bad: w("error: %s\n" % " ".join(bad)) + if pbad: + w("pin err: %s\n" % " ".join(pbad)) if payload["rc"] == 0: - w("verdict: every graded commit left the index current in its own tree\n") + w("verdict: every graded commit left its own tree consistent -- " + "the index current and the pin where the queue put it\n") else: - w("verdict: %d commit(s) did NOT leave the index current in their own tree -- " - "rc 1\n" % (len(stale) + len(bad))) + w("verdict: %d commit(s) left their own tree inconsistent -- " + "%d index, %d pin -- rc 1\n" + % (len(stale) + len(bad) + len(drift) + len(pbad), len(stale) + len(bad), + len(drift) + len(pbad))) # ------------------------------------------------------------------- selftest @@ -381,13 +495,40 @@ def _sh(cwd, *args): return subprocess.run(args, cwd=cwd, capture_output=True, text=True) -def _fixture(base): - """A five-commit history with one commit of each kind. Returns (repo, revs). +PIN_STUB = '''#!/usr/bin/env python3 +"""A stand-in for wizard-work/volt/q137-open-set/open_set.py's --check: count +the queue's headings and compare them with the PIN this commit carries.""" +import argparse +import sys - A: queue only, no gate tool -> UNGRADABLE - B: appends, and adds tools/queue_index.py + its render -> PASS - C: appends to the queue, no re-render -> STALE - D: appends AND re-renders -> PASS +QUEUE = "WORK-QUEUE.md" +PIN = @PIN@ + +ap = argparse.ArgumentParser() +ap.add_argument("--check", action="store_true") +ap.parse_args() + +n = len([ln for ln in open(QUEUE, encoding="utf-8") if ln.startswith("## ")]) +print("queue: %d heading(s)" % n) +if n != PIN: + print("FAIL count headings moved %d -> %d" % (PIN, n)) + print("CHECK 1 fault(s)") + sys.exit(1) +print("CHECK OK: counts match the pin") +sys.exit(0) +''' + + +def _fixture(base): + """A seven-commit history with one commit of each kind. Returns (repo, revs). + + A: queue only, no gate tool -> index UNGRADABLE, pin UNGRADABLE + B: appends, adds tools/queue_index.py + its render + the pin tool (PIN=1) + -> both PASS + C: appends to the queue, no re-render -> index STALE, pin PASS + D: appends AND re-renders -> both PASS + F: appends a HEADING and re-renders, pin left -> index PASS, pin DRIFT + G: appends a record and moves the pin to 2 -> both PASS E: touches an unrelated file -> not selected at all """ repo = os.path.join(base, "repo") @@ -402,15 +543,19 @@ def _fixture(base): _sh(repo, "git", "add", "-A") _sh(repo, "git", "commit", "-q", "-m", "A: queue only") + pin_dir = os.path.join(repo, os.path.dirname(PIN_TOOL)) + os.makedirs(pin_dir) os.makedirs(os.path.join(repo, "tools")) os.makedirs(os.path.join(repo, "docs")) + with open(os.path.join(repo, PIN_TOOL), "w", encoding="utf-8") as fh: + fh.write(PIN_STUB.replace("@PIN@", "1")) with open(os.path.join(repo, GATE_TOOL), "w", encoding="utf-8") as fh: fh.write(open(os.path.join(HERE, "queue_index.py"), encoding="utf-8").read()) with open(queue, "a", encoding="utf-8") as fh: fh.write("- beta appended\n") _sh(repo, sys.executable, GATE_TOOL, "--repo", ".", "--write", INDEX_DEFAULT) _sh(repo, "git", "add", "-A") - _sh(repo, "git", "commit", "-q", "-m", "B: append + gate + index") + _sh(repo, "git", "commit", "-q", "-m", "B: append + gate + pin + index") with open(queue, "a", encoding="utf-8") as fh: fh.write("- gamma appended\n") @@ -423,6 +568,23 @@ def _fixture(base): _sh(repo, "git", "add", "-A") _sh(repo, "git", "commit", "-q", "-m", "D: append + re-render") + # F: the shape Q167 landed in -- the index is re-rendered and current, the + # pin is not moved, so the two axes disagree in ONE row. + with open(queue, "a", encoding="utf-8") as fh: + fh.write("\n## Q2 -- beta\n\nStatus: open\n") + _sh(repo, sys.executable, GATE_TOOL, "--repo", ".", "--write", INDEX_DEFAULT) + _sh(repo, "git", "add", "-A") + _sh(repo, "git", "commit", "-q", "-m", "F: new heading + re-render, pin left") + + # G: the repair commit -- touches the queue and moves the pin with it. + with open(queue, "a", encoding="utf-8") as fh: + fh.write("- epsilon appended\n") + with open(os.path.join(repo, PIN_TOOL), "w", encoding="utf-8") as fh: + fh.write(PIN_STUB.replace("@PIN@", "2")) + _sh(repo, sys.executable, GATE_TOOL, "--repo", ".", "--write", INDEX_DEFAULT) + _sh(repo, "git", "add", "-A") + _sh(repo, "git", "commit", "-q", "-m", "G: append + move the pin") + with open(os.path.join(repo, "notes.txt"), "w", encoding="utf-8") as fh: fh.write("unrelated\n") _sh(repo, "git", "add", "-A") @@ -440,12 +602,12 @@ def selftest(): base = tempfile.mkdtemp(prefix="qaa-selftest-") try: repo, revs = _fixture(base) - a, b, c, d, e = revs + a, b, c, d, f, g, e = revs rc, p = audit(repo, QUEUE_DEFAULT, INDEX_DEFAULT, None, "HEAD", all_history=True) rows = {r["rev"]: r for r in p["rows"]} - check("the audit selects the 4 queue-touching commits, not the 5th", len(p["rows"]), 4) + check("the audit selects the 6 queue-touching commits, not the 7th", len(p["rows"]), 6) check("a commit with no gate tool is UNGRADABLE, not STALE", rows[a]["verdict"], "UNGRADABLE") check("the commit that added the gate and its index is PASS", rows[b]["verdict"], "PASS") check("an append with no re-render is STALE", rows[c]["verdict"], "STALE") @@ -455,20 +617,52 @@ def selftest(): check("the stale row's numstat is the append", (rows[c]["queue_add"], rows[c]["queue_del"]), (1, 0)) check("a range with a STALE row exits 1", rc, 1) check("counts keep UNGRADABLE out of the STALE bucket", p["counts"].get("STALE"), 1) - check("graded counts PASS+STALE+ERROR only", p["graded"], 3) + check("graded counts PASS+STALE+ERROR only", p["graded"], 5) check("the STALE detail carries the tool's own word", "STALE:" in rows[c]["detail"], True) + # -- the pin axis, measured in the same trees ----------------------- + check("a commit that predates the pin tool is pin UNGRADABLE", rows[a]["pin"], "UNGRADABLE") + check("the commit that shipped the pin reads pin PASS", rows[b]["pin"], "PASS") + check("an index-stale commit whose pin matches reads pin PASS", rows[c]["pin"], "PASS") + check("a new heading with the pin left behind reads pin DRIFT", rows[f]["pin"], "DRIFT") + check("the DRIFT row's INDEX is still PASS -- the axes are independent", + rows[f]["verdict"], "PASS") + check("the DRIFT row names the count that moved", + "count headings moved 1 -> 2" in rows[f]["pin_detail"], True) + check("a queue-touching commit that moves the pin reads pin PASS", rows[g]["pin"], "PASS") + check("DRIFT is kept out of the pin PASS bucket", p["pin_counts"].get("DRIFT"), 1) + check("pin UNGRADABLE is counted, not folded into DRIFT", p["pin_counts"].get("UNGRADABLE"), 1) + check("pin_graded counts PASS+DRIFT+ERROR only", p["pin_graded"], 5) + check("a DRIFT row alone exits 1", rows[f]["pin_rc"], 1) + + rc_p, p_p = audit(repo, QUEUE_DEFAULT, INDEX_DEFAULT, None, f, guard=True, + axis="pin") + check("--axis pin grades the pin alone and still exits 1 on DRIFT", + (rc_p, p_p["rows"][0]["pin"]), (1, "DRIFT")) + check("--axis pin sets no index verdict on the row", + "verdict" in p_p["rows"][0], False) + check("--axis pin counts no index rows", p_p["counts"], {}) + rc_i, p_i = audit(repo, QUEUE_DEFAULT, INDEX_DEFAULT, None, c, guard=True, + axis="index") + check("--axis index reads the same commit STALE on its own axis", + (rc_i, p_i["rows"][0]["verdict"], "pin" in p_i["rows"][0]), + (1, "STALE", False)) + rc_g, p_g = audit(repo, QUEUE_DEFAULT, INDEX_DEFAULT, None, "HEAD", guard=True) check("--guard on a clean head exits 0", rc_g, 0) check("--guard reports exactly one commit", len(p_g["rows"]), 1) + check("--guard's one row is clean on BOTH axes", + (p_g["rows"][0]["verdict"], p_g["rows"][0]["pin"]), ("PASS", "PASS")) rc_s, _ = audit(repo, QUEUE_DEFAULT, INDEX_DEFAULT, None, c, guard=True) check("--guard on the stale commit exits 1", rc_s, 1) + rc_f, _ = audit(repo, QUEUE_DEFAULT, INDEX_DEFAULT, None, f, guard=True) + check("--guard on the drift commit exits 1", rc_f, 1) # Default range: begin where the gate does. B introduced the index, so # the default table starts at B's parent and A is counted, not listed. rc_a, p_a = audit(repo, QUEUE_DEFAULT, INDEX_DEFAULT, None, "HEAD") check("the default range begins at the commit that introduced the index", - (p_a["auto_from"], len(p_a["rows"])), (True, 3)) + (p_a["auto_from"], len(p_a["rows"])), (True, 5)) check("pre-gate commits are counted, not silently dropped", p_a["pre_gate"], 1) check("the default range still grades the stale commit", rc_a, 1) @@ -491,8 +685,9 @@ def selftest(): report(p_j, stream=buf) with open(json_path, encoding="utf-8") as fh: loaded = json.load(fh) - check("--json round-trips the same 4 rows", len(loaded["rows"]), 4) + check("--json round-trips the same 6 rows", len(loaded["rows"]), 6) check("the report names the stale commit by short sha", c[:7] in buf.getvalue(), True) + check("the report names the drift commit on its own line", "drift: " + f[:7] in buf.getvalue(), True) check("a report with a fault never prints a clean verdict", "every graded commit" in buf.getvalue(), False) finally: @@ -524,6 +719,9 @@ def main(argv=None): "commits as UNGRADABLE rows too") ap.add_argument("--guard", action="store_true", help="grade only the newest queue-touching commit") + ap.add_argument("--axis", choices=("both", "index", "pin"), default="both", + help="which axis to grade: the rendered index, the queue's " + "own PIN_COUNTS, or both (default both)") ap.add_argument("--timeout", type=int, default=30, help="seconds per commit's --check (default 30)") ap.add_argument("--json", metavar="PATH", help="write the rows here") @@ -533,7 +731,7 @@ def main(argv=None): return selftest() rc, payload = audit(args.repo, args.queue, args.index, args.rev_from, args.rev_to, args.guard, args.timeout, - args.all_history) + args.all_history, args.axis) report(payload) if args.json: try: diff --git a/wizard-work/volt/q137-open-set/open_set.py b/wizard-work/volt/q137-open-set/open_set.py index bed1ec4..868cc4e 100644 --- a/wizard-work/volt/q137-open-set/open_set.py +++ b/wizard-work/volt/q137-open-set/open_set.py @@ -639,8 +639,16 @@ PIN_OPENED = [51, 52, 53, 65, 100, 101, 102, 103, 104, 105, 106, 107, 109, # move was measured by --check after the append -- it named exactly these five # faults and no others -- and CHECK-q167 now grades the pin in the COMMIT # (git archive HEAD, that tree's own open_set.py), not only in the worktree. -PIN_COUNTS = {"headings": 118, "heading_ids": 102, "records": 130, - "record_ids": 96, "ids": 157, "open": 0, "opened": 26, +# Q168 (2026-11-04): one heading (## Q168 closure) and one record (**Q168 -- +# OPENED and REPAIRED ...) for a new id: headings 118 -> 119, heading_ids 102 -> +# 103, records 130 -> 131, record_ids 96 -> 97, ids 157 -> 158; record_only +# stays 55 and open / opened stay 0 / 26 (same-tick closure, no probe; +# CHECK-append-pin is its guard). The move was measured by --check after the +# append, which named exactly these five faults and no others, and the audit +# that repairs this item now grades this pin as a second axis in the commit -- +# this record's own commit included. +PIN_COUNTS = {"headings": 119, "heading_ids": 103, "records": 131, + "record_ids": 97, "ids": 158, "open": 0, "opened": 26, "record_only": 55} PIN_STATE = { 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 c99907e..56165c4 100644 --- a/wizard-work/volt/q143-check-sweep/check_entry_baseline.tsv +++ b/wizard-work/volt/q143-check-sweep/check_entry_baseline.tsv @@ -23,6 +23,7 @@ # wizard-work/ledger/2026-10-29-checkin-census/CHECK 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-append-pin 0 append-pin: 5 leg(s), 0 fault(s) -- the pin axis reads 56d3853 pin:DRIFT where the pre-axis tool read PASS CHECK-ledger-dir-census 0 VERDICT: rc 0 -- the committed CSV is the derivation at the pinned rev CHECK-q-checkparen 0 verify_fix: 0 leg(s) faulted CHECK-q143 0 q143: 2 leg(s), all passed