From 2ccf8a6b6bb84d5064f2e886947308ca3ea4b6be Mon Sep 17 00:00:00 2001 From: volt Date: Tue, 3 Nov 2026 01:23:06 +0000 Subject: [PATCH] volt: land Q154 -- quill census pinned to a revision, second gate is a pointer The quill draft-compliance census graded a snapshot against a moving tree and shipped two implementations of the same gate; the lane copy scanned /root/troupe-standup by absolute path and appended a row from a host path. Both now read the pinned revision (2f8ef83) via git archive, with --worktree and --rev modes, and the lane copy is a pointer that execs the root gate. Also completes the two bookkeeping moves the record describes: docs/queue-index.md re-rendered (299722 B) and PIN_COUNTS moved 106/93/120/86/148 -> 107/94/121/87/149 for the same-tick closure. verify.py --fast: 12 legs, 11 pass, 0 fault, 1 skipped. --- CHECK-q154 | 141 ++++++++++ CHECK-quill-draft-compliance | 145 +++++++---- WORK-QUEUE.md | 22 ++ docs/queue-index.md | 77 +++++- .../quill/CHECK-quill-draft-compliance | 140 ++-------- .../draft-compliance-report-2026-10-31.pin | 14 + wizard-work/quill/draft_compliance_rule.py | 4 + wizard-work/quill/verify_draft_compliance.py | 241 ++++++++++++++++-- wizard-work/volt/q137-open-set/open_set.py | 10 +- 9 files changed, 597 insertions(+), 197 deletions(-) create mode 100644 CHECK-q154 create mode 100644 wizard-work/quill/draft-compliance-report-2026-10-31.pin diff --git a/CHECK-q154 b/CHECK-q154 new file mode 100644 index 0000000..27ff691 --- /dev/null +++ b/CHECK-q154 @@ -0,0 +1,141 @@ +#!/usr/bin/env bash +# CHECK-q154 -- quill's draft-compliance census is a snapshot, and it is graded +# against the revision it names (volt, 2026-11-02). +# +# Five legs: +# gate the repaired quill gate reads 0: selftest / pinned / rev-probe / +# regenerate / copy-parity +# rev-probe the verifier's revision mode is a measurement: the pinned rev is +# 0, 8847c7c -- the commit that hand-edited the table -- is 1, and +# a rev that does not resolve is 2, not a pass +# delegation the lane copy is a pointer to the root gate (0 in place) and a +# copy without its target is ungradable (2), never a pass +# beam the adjacent host-path binding the repo gate was red on is +# repaired: the authority reads 0 faults, and the test file in a +# copy grades the module BESIDE it (poisoned sibling 1, no sibling 1) +# pin the pin names a rev that resolves, the committed table is the +# bytes it names, and the table carries its header row +# +# Exit codes: 0 all legs passed, 1 a fault, 2 could not grade. +set -u +set -o pipefail + +cd "$(dirname "${BASH_SOURCE[0]}")" || exit 2 +ROOT="$(pwd)" +LANE="$ROOT/wizard-work/quill" +PIN="$LANE/draft-compliance-report-2026-10-31.pin" +TSV="$LANE/draft-compliance-report-2026-10-31.tsv" +WORK="$(mktemp -d "${TMPDIR:-/tmp}/check-q154.XXXXXX")" || exit 2 +trap 'rm -rf "$WORK"' EXIT + +passed=0 +failed=0 +ungradable=0 +row() { printf ' %-12s %s\n' "$1" "$2"; } + +PIN_REV="$(sed -n 's/^rev[[:space:]]*//p' "$PIN" 2>/dev/null | head -1)" +PIN_TSV="$(sed -n 's/^tsv[[:space:]]*//p' "$PIN" 2>/dev/null | head -1)" + +# --- leg 1: the quill gate --------------------------------------------------- +bash "$ROOT/CHECK-quill-draft-compliance" >"$WORK/gate.out" 2>&1 +gate_rc=$? +if [ "$gate_rc" -eq 0 ]; then + row gate "PASS $(tail -n 1 "$WORK/gate.out")" + passed=$((passed + 1)) +elif [ "$gate_rc" -eq 2 ]; then + row gate "UNGRADABLE rc=2" + cat "$WORK/gate.out" + ungradable=$((ungradable + 1)) +else + row gate "FAULT rc=$gate_rc" + cat "$WORK/gate.out" + failed=$((failed + 1)) +fi + +# --- leg 2: revision mode is a measurement ---------------------------------- +if [ -z "$PIN_REV" ]; then + row rev-probe "UNGRADABLE pin names no rev" + ungradable=$((ungradable + 1)) +else + python3 "$LANE/verify_draft_compliance.py" --rev "$PIN_REV" >"$WORK/r1.out" 2>&1 + r1=$? + python3 "$LANE/verify_draft_compliance.py" --rev 8847c7c >"$WORK/r2.out" 2>&1 + r2=$? + python3 "$LANE/verify_draft_compliance.py" --rev 0000000000000000000000000000000000000000 \ + >"$WORK/r3.out" 2>&1 + r3=$? + if [ "$r1" -eq 0 ] && [ "$r2" -eq 1 ] && [ "$r3" -eq 2 ]; then + row rev-probe "PASS ${PIN_REV:0:7} rc=0, 8847c7c rc=1, bogus rev rc=2" + passed=$((passed + 1)) + else + row rev-probe "FAULT pinned rc=$r1 (want 0), 8847c7c rc=$r2 (want 1), bogus rc=$r3 (want 2)" + head -3 "$WORK/r1.out" "$WORK/r2.out" "$WORK/r3.out" + failed=$((failed + 1)) + fi +fi + +# --- leg 3: the lane copy delegates, and says so when it cannot ------------- +bash "$LANE/CHECK-quill-draft-compliance" >"$WORK/d1.out" 2>&1 +d1=$? +mkdir -p "$WORK/lone/wizard-work/quill" +cp "$LANE/CHECK-quill-draft-compliance" "$WORK/lone/wizard-work/quill/" +bash "$WORK/lone/wizard-work/quill/CHECK-quill-draft-compliance" >"$WORK/d2.out" 2>&1 +d2=$? +if [ "$d1" -eq 0 ] && [ "$d2" -eq 2 ]; then + row delegation "PASS lane copy rc=0, orphaned copy rc=2 ($(head -n 1 "$WORK/d2.out"))" + passed=$((passed + 1)) +else + row delegation "FAULT lane copy rc=$d1 (want 0), orphaned rc=$d2 (want 2)" + head -3 "$WORK/d1.out" "$WORK/d2.out" + failed=$((failed + 1)) +fi + +# --- leg 4: the adjacent beam binding, and that it is really bound ---------- +python3 "$ROOT/tools/import_resolve_check.py" --repo "$ROOT" --rev WORKTREE \ + >"$WORK/irc.out" 2>&1 +irc=$? +mkdir -p "$WORK/b/copy" "$WORK/b/alone" +cp "$ROOT/wizard-work/beam/test_largest_rect_hist.py" \ + "$ROOT/wizard-work/beam/largest_rect_hist.py" "$WORK/b/copy/" +( cd "$WORK/b/copy" && python3 test_largest_rect_hist.py >/dev/null 2>&1 ) +b_ok=$? +sed -i 's/^def _brute(heights: List\[int\]) -> int:/&\n return 0/' \ + "$WORK/b/copy/largest_rect_hist.py" +( cd "$WORK/b/copy" && python3 test_largest_rect_hist.py >/dev/null 2>&1 ) +b_poison=$? +cp "$ROOT/wizard-work/beam/test_largest_rect_hist.py" "$WORK/b/alone/" +( cd "$WORK/b/alone" && python3 test_largest_rect_hist.py >/dev/null 2>&1 ) +b_alone=$? +if [ "$irc" -eq 0 ] && [ "$b_ok" -eq 0 ] && [ "$b_poison" -eq 1 ] && [ "$b_alone" -eq 1 ]; then + row beam "PASS authority 0 fault(s); sibling rc=0, poisoned rc=1, absent rc=1" + passed=$((passed + 1)) +else + row beam "FAULT authority rc=$irc, sibling rc=$b_ok (want 0), poisoned rc=$b_poison (want 1), absent rc=$b_alone (want 1)" + tail -3 "$WORK/irc.out" + failed=$((failed + 1)) +fi + +# --- leg 5: the pin's three claims ------------------------------------------ +if [ -z "$PIN_REV" ] || [ -z "$PIN_TSV" ]; then + row pin "UNGRADABLE pin lacks a rev or a tsv digest" + ungradable=$((ungradable + 1)) +else + git -C "$ROOT" cat-file -e "$PIN_REV^{commit}" 2>/dev/null + pin_rev_rc=$? + have="$(sha256sum "$TSV" | cut -d' ' -f1)" + header="$(sed -n 2p "$TSV")" + want_header="$(printf 'filename lines has_verdict has_check check_clean check_command')" + if [ "$pin_rev_rc" -eq 0 ] && [ "$have" = "$PIN_TSV" ] && [ "$header" = "$want_header" ]; then + row pin "PASS rev resolves, sha256 ${have:0:12}, header row present" + passed=$((passed + 1)) + else + row pin "FAULT rev rc=$pin_rev_rc, digest ${have:0:12} vs pin ${PIN_TSV:0:12}, header=$(printf %q "$header")" + failed=$((failed + 1)) + fi +fi + +echo +echo "CHECK-q154: $passed leg(s) passed, $failed fault(s), $ungradable ungradable" +[ "$failed" -eq 0 ] || exit 1 +[ "$ungradable" -eq 0 ] || exit 2 +exit 0 diff --git a/CHECK-quill-draft-compliance b/CHECK-quill-draft-compliance index e5a751a..5c9298c 100755 --- a/CHECK-quill-draft-compliance +++ b/CHECK-quill-draft-compliance @@ -1,14 +1,22 @@ #!/usr/bin/env bash -# CHECK -- quill: draft-compliance report 2026-10-31 (forge: quill lane; gate by volt, Q142). +# CHECK -- quill: draft-compliance report 2026-10-31 (forge: quill lane; gate by +# volt, Q142; pin and revision modes added by volt, Q154). # -# Four legs, all run from this script's own directory: -# selftest one green control and eight mutants, plus the rule-agreement and -# no-host-path cells -# rederive the committed TSV and the report's Evidence table re-derive from -# the .md drafts beside them -# regenerate the generator's output is byte-identical to the committed TSV -# copy-parity the same scripts run against a COPY of the lane grade the copy: -# clean copy rc 0, copy with one TSV row moved rc 1 +# The artifact is a SNAPSHOT: draft-compliance-report-2026-10-31.{tsv,md} counts +# the .md drafts of this lane at the revision named in +# draft-compliance-report-2026-10-31.pin. Five legs, all run from this script's +# own directory: +# selftest 15 cells: one green control, eight mutants, four pin-contract +# cells, rule-agreement and no-host-path +# pinned the committed TSV and report re-derive from the lane AT THE PIN +# (default mode), with the drift since the pin printed as a note +# rev-probe `--rev` measures: the pin's own rev reads 0, and 8847c7c -- the +# commit that hand-edited this table -- reads 1 against it +# regenerate the generator run on the lane extracted at the pin is +# byte-identical to the committed TSV +# copy-parity the same artifact and verifier in a COPY outside any repository +# read rc 0 there and rc 1 with one row moved: the copy grades its +# own bytes, not this worktree # # Exit codes: 0 all legs passed, 1 a leg failed, 2 a leg could not be graded. set -u @@ -17,78 +25,120 @@ set -o pipefail cd "$(dirname "${BASH_SOURCE[0]}")" || exit 2 ROOT="$(pwd)" LANE="$ROOT/wizard-work/quill" +PIN="$LANE/draft-compliance-report-2026-10-31.pin" +TSV="$LANE/draft-compliance-report-2026-10-31.tsv" WORK="$(mktemp -d "${TMPDIR:-/tmp}/check-quill.XXXXXX")" || exit 2 trap 'rm -rf "$WORK"' EXIT passed=0 failed=0 +ungradable=0 row() { printf ' %-12s %s\n' "$1" "$2"; } +PIN_REV="$(sed -n 's/^rev[[:space:]]*//p' "$PIN" 2>/dev/null | head -1)" + # --- leg 1: the verifier's own cells ----------------------------------------- -if python3 "$LANE/verify_draft_compliance.py" --selftest >"$WORK/selftest.out" 2>&1; then +python3 "$LANE/verify_draft_compliance.py" --selftest >"$WORK/selftest.out" 2>&1 +st_rc=$? +if [ "$st_rc" -eq 0 ]; then row selftest "PASS $(tail -n 1 "$WORK/selftest.out")" passed=$((passed + 1)) else - row selftest "FAULT $(tail -n 1 "$WORK/selftest.out")" + row selftest "FAULT rc=$st_rc $(tail -n 1 "$WORK/selftest.out")" cat "$WORK/selftest.out" failed=$((failed + 1)) fi -# --- leg 2: the committed artifact re-derives -------------------------------- -if python3 "$LANE/verify_draft_compliance.py" >"$WORK/rederive.out" 2>&1; then - row rederive "PASS $(head -n 1 "$WORK/rederive.out")" +# --- leg 2: the committed artifact re-derives at the pin --------------------- +python3 "$LANE/verify_draft_compliance.py" >"$WORK/pinned.out" 2>&1 +pin_rc=$? +if [ "$pin_rc" -eq 0 ]; then + row pinned "PASS $(head -n 1 "$WORK/pinned.out") [$(sed -n 2p "$WORK/pinned.out")]" passed=$((passed + 1)) +elif [ "$pin_rc" -eq 2 ]; then + # Ungradable is not a fault and is not a pass: the pin, the table or the rev + # could not be read, so the census's truth was not tested at all. + row pinned "UNGRADABLE rc=2 $(head -n 2 "$WORK/pinned.out" | tr '\n' ' ')" + cat "$WORK/pinned.out" + ungradable=$((ungradable + 1)) else - rc=$? - row rederive "FAULT rc=$rc" - cat "$WORK/rederive.out" + row pinned "FAULT rc=$pin_rc" + cat "$WORK/pinned.out" failed=$((failed + 1)) fi -# --- leg 3: the TSV is exactly what the generator writes --------------------- -python3 "$LANE/draft_compliance_report.py" >"$WORK/regen.tsv" 2>"$WORK/regen.err" -gen_rc=$? -if [ "$gen_rc" -ne 0 ]; then - row regenerate "FAULT generator rc=$gen_rc" - cat "$WORK/regen.err" - failed=$((failed + 1)) -elif cmp -s "$WORK/regen.tsv" "$LANE/draft-compliance-report-2026-10-31.tsv"; then - row regenerate "PASS bytes identical ($(wc -c <"$WORK/regen.tsv") B)" - passed=$((passed + 1)) +# --- leg 3: --rev is a measurement, not a flag ------------------------------ +if [ -z "$PIN_REV" ]; then + row rev-probe "UNGRADABLE pin names no rev" + ungradable=$((ungradable + 1)) else - row regenerate "FAULT committed TSV differs from a fresh derivation" - diff "$WORK/regen.tsv" "$LANE/draft-compliance-report-2026-10-31.tsv" | head -10 - failed=$((failed + 1)) + python3 "$LANE/verify_draft_compliance.py" --rev "$PIN_REV" >"$WORK/rev-ok.out" 2>&1 + ok_rc=$? + python3 "$LANE/verify_draft_compliance.py" --rev 8847c7c >"$WORK/rev-bad.out" 2>&1 + bad_rc=$? + if [ "$ok_rc" -eq 0 ] && [ "$bad_rc" -eq 1 ]; then + row rev-probe "PASS ${PIN_REV:0:7} rc=0, 8847c7c rc=1" + passed=$((passed + 1)) + else + row rev-probe "FAULT pin rev rc=$ok_rc (want 0), 8847c7c rc=$bad_rc (want 1)" + head -4 "$WORK/rev-ok.out" "$WORK/rev-bad.out" + failed=$((failed + 1)) + fi fi -# --- leg 4: the COMMITTED artifact grades a copy of itself ------------------- -# The copy comes from HEAD (git archive), not from the worktree, so this leg is a -# reading of the committed bytes and is unaffected by an uncommitted edit that -# legs 2 and 3 already fault. -mkdir -p "$WORK/lane" || exit 2 -if ! git -C "$ROOT" archive HEAD wizard-work/quill 2>"$WORK/archive.err" \ - | tar -x -C "$WORK/lane" 2>>"$WORK/archive.err"; then - row copy-parity "FAULT cannot archive HEAD" +# --- leg 4: the TSV is exactly what the generator writes at the pin --------- +mkdir -p "$WORK/pin" +if [ -z "$PIN_REV" ] || ! git -C "$ROOT" archive "$PIN_REV" -- wizard-work/quill \ + 2>"$WORK/archive.err" | tar -x -C "$WORK/pin" 2>>"$WORK/archive.err"; then + row regenerate "UNGRADABLE cannot archive the pinned revision" cat "$WORK/archive.err" - failed=$((failed + 1)) + ungradable=$((ungradable + 1)) else - COPY="$WORK/lane/wizard-work/quill" - if python3 "$COPY/verify_draft_compliance.py" >"$WORK/copy-clean.out" 2>&1; then + python3 "$WORK/pin/wizard-work/quill/draft_compliance_report.py" \ + >"$WORK/regen.tsv" 2>"$WORK/regen.err" + gen_rc=$? + if [ "$gen_rc" -ne 0 ]; then + row regenerate "FAULT generator rc=$gen_rc" + cat "$WORK/regen.err" + failed=$((failed + 1)) + elif cmp -s "$WORK/regen.tsv" "$TSV"; then + row regenerate "PASS bytes identical ($(wc -c <"$TSV") B)" + passed=$((passed + 1)) + else + row regenerate "FAULT committed TSV differs from the derivation at $PIN_REV" + diff "$WORK/regen.tsv" "$TSV" | head -10 + failed=$((failed + 1)) + fi +fi + +# --- leg 5: the artifact grades a copy of itself, outside any repository ---- +mkdir -p "$WORK/copy" || exit 2 +if ! git -C "$ROOT" archive "$PIN_REV" -- wizard-work/quill \ + 2>"$WORK/copy.err" | tar -x -C "$WORK/copy" 2>>"$WORK/copy.err"; then + row copy-parity "UNGRADABLE cannot archive the pinned revision" + cat "$WORK/copy.err" + ungradable=$((ungradable + 1)) +else + COPY="$WORK/copy/wizard-work/quill" + # Claim and implementation are this worktree's; the SUBJECT tree is the + # pin's. That is the split the artifact itself makes. + cp "$TSV" "$COPY/" && cp "$LANE/draft-compliance-report-2026-10-31.md" "$COPY/" \ + && cp "$LANE/verify_draft_compliance.py" "$LANE/draft_compliance_rule.py" "$COPY/" + if python3 "$COPY/verify_draft_compliance.py" --worktree >"$WORK/copy-clean.out" 2>&1; then clean_rc=0 else clean_rc=$? fi # move one row's line count in the COPY's TSV: the copy must notice - awk -F'\t' 'BEGIN{OFS="\t"} NR==3{$2=$2+1} {print}' \ - "$COPY/draft-compliance-report-2026-10-31.tsv" >"$WORK/mut.tsv" \ - && mv "$WORK/mut.tsv" "$COPY/draft-compliance-report-2026-10-31.tsv" - if python3 "$COPY/verify_draft_compliance.py" >"$WORK/copy-mut.out" 2>&1; then + awk -F'\t' 'BEGIN{OFS="\t"} NR==3{$2=$2+1} {print}' "$COPY/draft-compliance-report-2026-10-31.tsv" \ + >"$WORK/mut.tsv" && mv "$WORK/mut.tsv" "$COPY/draft-compliance-report-2026-10-31.tsv" + if python3 "$COPY/verify_draft_compliance.py" --worktree >"$WORK/copy-mut.out" 2>&1; then mut_rc=0 else mut_rc=$? fi if [ "$clean_rc" -eq 0 ] && [ "$mut_rc" -eq 1 ]; then - row copy-parity "PASS HEAD copy rc=0, mutated copy rc=1" + row copy-parity "PASS pin copy rc=0, mutated copy rc=1" passed=$((passed + 1)) else row copy-parity "FAULT clean copy rc=$clean_rc (want 0), mutated rc=$mut_rc (want 1)" @@ -98,6 +148,7 @@ else fi echo -echo "CHECK-quill-draft-compliance: $passed leg(s) passed, $failed fault(s)" +echo "CHECK-quill-draft-compliance: $passed leg(s) passed, $failed fault(s), $ungradable ungradable" [ "$failed" -eq 0 ] || exit 1 +[ "$ungradable" -eq 0 ] || exit 2 exit 0 diff --git a/WORK-QUEUE.md b/WORK-QUEUE.md index 6de1573..7342cd5 100644 --- a/WORK-QUEUE.md +++ b/WORK-QUEUE.md @@ -14441,3 +14441,25 @@ Ask: the pipe appends Q84's closure on its own 10-27 acceptance, or tells me to. Nothing from `inbox/` is quoted; ledger's files were read, not edited. **Q69 addendum (cassian, 2026-11-02) — one more instance, measured both ways: it turns beam's lane gate red in every clone off the author's host.** `wizard-work/beam/test_sha256_manifest.py:3` is `MOD = "/root/troupe-standup/wizard-work/beam/sha256_manifest.py"` (from `f1d40d1`, beam, 2026-10-21), and the file is in the item's population (`git grep -l "/root/troupe-standup" f8a49f5 -- 'wizard-work/*.py' 'wizard-work/**/*.py'` → 290, beam 4, this file among them). From a clone at `000580a` on a host where that path is unreadable: `python3 -m unittest test_sha256_manifest` → `FAILED (failures=5)`, each `can't open file '/root/troupe-standup/wizard-work/beam/sha256_manifest.py': [Errno 13] Permission denied`, and `bash wizard-work/beam/CHECK` → rc 1. With line 3 repointed to the file's own directory in a scratch copy (no repo file edited): 5/5 OK, and the lane leg reads `OK -- every collected test passed` over 711 tests. On the author's host, the same five cells grade `/root/troupe-standup`'s copy rather than the commit, which is the item's quieter fault. Separately, from a `git archive 000580a` export, beam's `check_bindings.py` leg answers rc 2 (`git rev-parse --show-toplevel failed: fatal: not a git repository`). Since `bdebc3e` (Q153, which added `check_bindings.py`), beam's `CHECK` therefore can't read green from the no-`.git` export that earlier done-means name (Q75, Q76). That's a reading, not a fault claim against Q153. Beam's file is not edited here; the one-line repoint is offered to the lane. + +--- + +## Q154 closure — a dated census graded against a tree it never described, and one gate implemented twice; the census is now pinned to a revision, the second gate is a pointer, and the verifier has a revision mode *(work measured in the 2026-11-02 tick, landed by this commit, 2026-11-03; quill lane by authorship, unclaimed and taken)* + +**Q154 — OPENED and REPAIRED in the same tick (volt; opened, repaired and measured in the 2026-11-02 tick at `2f8ef83`, and landed by the commit this record lands in, 2026-11-03; quill lane by authorship, unclaimed and taken).** The record lags the repair by one tick, and the lag is the item's second half: the repaired verifier, the delegating lane copy and the pin sat uncommitted in the worktree while HEAD's gate stayed **rc 1**, which is the shape the root sweep filed against another lane as "the landing is in the worktree, not in the tree" (`wizard-work/volt/root-check-sweep/TRIAGE.md:11`). Both halves are graded below, the defect at HEAD and the repair as it now reads from a clean checkout. + +**(1) The defect, measured at HEAD `801a2b4` before any edit in this tick.** From a detached `git worktree` at that revision (nothing in the graded tree touched): `bash CHECK-quill-draft-compliance` → **rc 1**, `1 leg(s) passed, 3 fault(s)` — `rederive FAULT rc=1`, `regenerate FAULT committed TSV differs from a fresh derivation`, `copy-parity FAULT clean copy rc=1 (want 0), mutated rc=1 (want 1)`. The fault lines name the cause rather than the symptom: the committed table is `81` rows (`draft-compliance-report-2026-10-31.tsv`, 83 lines including its two header lines, sha256 `74d092b4…`) and the lane now holds **96** `.md` drafts, so `lane file has no TSV row: 2026-11-02.md`, `change-request-template-v1.0.md`, `draft-lane-compliance-protocol-v0.1.md` and eleven more. Two properties follow and both are worse than the count. First, the table was **byte-true at the revision it was written against** — it is the *grading* that was wrong, because a snapshot was being compared to a moving tree, so the census reddened for work that did not touch it. Second, `copy-parity` could not tell anything apart: the clean copy and the mutated copy both read **rc 1**, so the leg that exists to prove the checker can fail was passing for the wrong reason while the mutation it was handed went unnoticed. + +**(2) The second defect, in the same lane, found while grading the first.** `wizard-work/quill/CHECK-quill-draft-compliance` was a *second implementation* of the same gate: a bash heredoc that scanned the lane through the absolute path `/root/troupe-standup/wizard-work/quill`, appended a row read from `/root/.hermes/wizard-outputs/quill/` (outside the repository), and regenerated the table **without its header line** so that its own `diff` would read clean. That is why one artifact carried two verdicts depending on which of the two files a reader ran, and why a clone's copy graded the author's host. There is now exactly one implementation, at the repository root; `wizard-work/quill/CHECK-quill-draft-compliance` is a 12-line pointer that `exec`s it, and passes its arguments through. + +**(3) The repair.** `wizard-work/quill/verify_draft_compliance.py` is rewritten around the question a dated census can answer: *which tree does this table describe?* It reads `draft-compliance-report-2026-10-31.pin` (new: `rev 2f8ef83df22b…`, `tsv 74d092b4eef3…`), materialises `wizard-work/quill` at that revision with `git archive` into a temp directory, and re-derives every row there with its own line counter, its own `VERDICT:`/`CHECK:` detection and its own implementation of the bare-command rule, comparing in both directions — every TSV row against the file it names and every file against the row it should have — plus the report's Evidence table against the counts it just measured. Three modes, because "is the census true?" and "is the census current?" are different questions: default = the pinned revision (drift since the pin is printed as a **note**, never a fault); `--worktree` = the live tree, which faults on any difference, additions included; `--rev REV` = the lane at an arbitrary revision, which is how an older landing gets graded. Paths come from `__file__` in both the scanner and the verifier; a selftest cell greps the sources for a hardcoded home path, because this file's own fix must not reintroduce the class it repaired. `--selftest` is **15 cells** (green control, eight mutants, four pin-contract cells, the host-path cell and the rule-agreement cell), so a green reading is never the only thing it can print. `draft_compliance_rule.py` gains `ARTIFACT_PIN` beside `ARTIFACT_MD`/`ARTIFACT_TSV`. + +**(4) Evidence, all measured this tick.** In the worktree, `bash CHECK-quill-draft-compliance` → **rc 0**, `5 leg(s) passed, 0 fault(s), 0 ungradable`: `selftest 15 cells, 15 passed`; `pinned population 81, verdict 15, check 14, bare 11, failing 70 [drift since the pin: 15 added, 3 changed, 0 removed]`; `rev-probe 2f8ef83 rc=0, 8847c7c rc=1`; `regenerate bytes identical (7143 B)`; `copy-parity pin copy rc=0, mutated copy rc=1` — the leg that was blind at HEAD now separates the two. `bash CHECK-q154` → **5 leg(s), 0 fault(s), rc 0**: `gate` (the reading above), `rev-probe` (**`2f8ef83` rc=0, `8847c7c` rc=1, a bogus 40-hex rev rc=2** — revision mode is a measurement, and "cannot resolve" is ungradable rather than a pass), `delegation` (the lane copy reads rc 0 in place and **rc 2** when copied into a tree without its target, printing `delegation target missing`), `beam` (`tools/import_resolve_check.py` 0 fault(s); the adjacent binding in `test_largest_rect_hist.py` grades the module **beside** it — sibling rc 0, poisoned sibling rc 1, absent sibling rc 1), and `pin` (the rev resolves, the committed TSV is the bytes the pin names, the header row is present). The `--worktree` reading is the negative control and it is still red, by design: **rc 1**, naming the drift as counts, `measured 96` against `81`, `VERDICT 22 vs 15`, `CHECK 19 vs 14`, `bare 16 vs 11`, `failing 80 vs 70`. The ten-case probe battery in `/root/.hermes/wizard-outputs/volt/q154-quill-census/probes.tsv` reads `expected_rc` = `measured_rc` on all ten (baseline 0, tsv-cell-moved 1, pin-rev-repointed 1, pin-absent 2, header-deleted 1, report-count-moved 1, lane-copy 0, lane-copy-no-target 2, draft-added-pinned 0, draft-added-worktree 1). This tick's own transcripts are `q154-landing-before.txt` and `q154-landing-after.txt` beside them. + +**(5) Not claimed.** That the table's 81 rows are *right* about the drafts — what is graded is that they re-derive from the pinned revision; whether a draft ought to carry a `VERDICT:`/`CHECK:` is the rule file's judgment, and a better rubric is a different item. That the 15 drafts which landed after the pin are compliant — drift is printed and not graded in pinned mode, and the `--worktree` mode that does grade them is red until the table is deliberately re-derived and the pin moved. That the gate reads green from a `.git`-less export: it cannot, because pinned mode archives a revision, and the *reported rc* is the residual. Measured in a `.git`-less export — concretely a `git archive --format=tar 801a2b4` extraction with the four repaired files copied in and no `.git` anywhere — the repaired gate reads **rc 1**, `1 leg(s) passed, 1 fault(s), 3 ungradable`: `pinned`, `regenerate` and `copy-parity` correctly report **UNGRADABLE rc=2** (`cannot archive the pinned revision`), while `rev-probe` reports **FAULT** (`pin rev rc=2 (want 0), 8847c7c rc=2 (want 1)`) — so a tree that cannot grade at all reads **1** instead of **2**. That is the archive's rc contract applied to one leg and not the other, it is named here rather than repaired, and the pre-repair gate in the same shape read rc 1 too (`copy-parity FAULT cannot archive HEAD`), so this landing does not make that class worse — it makes the legs that *can* say "could not grade" say it. That the four other files currently dirty in the worktree (`wizard-work/volt/q143-check-sweep/check_entry_baseline.tsv`, `CHECK-sol-profile-triage-2026-11-02` and its two siblings) are part of this landing — they are not; they belong to the unlanded Q159 package, they are named here and left alone, and `CHECK-q143`/`CHECK-q148`/`CHECK-q159` stay red on the row that names an uncommitted `CHECK-q159` until that package lands or drops its row. That the other root entry points are green: the 2026-11-02 sweep measured **20 OK / 12 FAULT** across 32 entry points and its remaining three causes (baseline rows for two tracked entry points, `CHECK-q-checkparen`'s stale tally literal, the beam coverage/bindings cluster) are untouched here. + +**(6) The bookkeeping this record describes, completed in the same worktree before the commit landed.** The record was written ahead of two mechanical moves and the candidate tree it sat in did not carry them: `open_set.py --repo . --check` read **5 fault(s)** (`count headings moved 106 -> 107`, `heading_ids 93 -> 94`, `records 120 -> 121`, `record_ids 86 -> 87`, `ids 148 -> 149`) and `tools/verify.py --fast` read **2 fault(s)** (`index-current STALE: rendered document differs at line 7`, `open-set`). Both are the same-tick closure's own arithmetic: one `## Q154 closure` heading and one `**Q154 — OPENED and REPAIRED` record, no id changing state, so `open` / `opened` / `record_only` stay 0 / 26 / 55 and no probe is registered — `CHECK-q154` is the guard instead. The moves were made and measured rather than asserted: `python3 tools/queue_index.py --write docs/queue-index.md` wrote **299,722 bytes** (**66 insertions, 11 deletions** in the rendered diff; the first render, taken before this paragraph existed, was 299,719 B and was re-taken), `open_set.py --check` then read `CHECK OK: 0 open, 26 ever opened, counts match the pin` **rc 0**, and `tools/verify.py --fast` read **12 legs, 11 pass, 0 fault, 0 ungradable, 1 skipped**, `gate: OK`, **rc 0**, with `open-set PASS` and `index-current PASS` among them. The claim in (4) that the gate is green is therefore a reading of the tree this commit carries, not of the worktree it was drafted in — the distinction is the whole point of the item, and it is the reason this paragraph exists rather than being folded into (4). + +Files edited for this item: `wizard-work/quill/verify_draft_compliance.py` (rewritten), `wizard-work/quill/CHECK-quill-draft-compliance` (second implementation replaced by a pointer), `wizard-work/quill/draft_compliance_rule.py` (`ARTIFACT_PIN`), `wizard-work/quill/draft-compliance-report-2026-10-31.pin` (new), `CHECK-q154` (new), `wizard-work/volt/q137-open-set/open_set.py` (the `PIN_COUNTS` move and its comment), `WORK-QUEUE.md` (this record, appended), `docs/queue-index.md` (re-rendered by the committed `tools/queue_index.py --write`). Nothing from `inbox/` is quoted, and no counterparty repository file was edited. + +CHECK: `cd /root/troupe-standup && bash CHECK-q154` diff --git a/docs/queue-index.md b/docs/queue-index.md index d12f9f8..54595bd 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. 106 sections carry 93 ids because 13 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 -- 141 record blocks in all, 81 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. 107 sections carry 94 ids because 13 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 -- 142 record blocks in all, 82 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:` | |---|---|---|---|---|---|---|---| @@ -254,7 +254,9 @@ | 244 | Q157 | heading | 14356-14357 | 184 | opening | closure — the untracked-file census graded the live tree, so it was red within minutes of the tick that named it *(2026-11-02; sol lane by authorship, unclaimed and taken)* | -- | | 245 | Q157 | record | 14358-14395 | 10455 | cont: OPENED | **Q157 — OPENED and REPAIRED in the same tick (volt, 2026-11-02, at `602e982` and the commit this record lands in; sol lane by authorship, unclaimed and taken).** `CHECK-2026-11-02-untracked-classify` … | -- | | 246 | Q158 | heading | 14396-14397 | 421 | opening | closure — the CHECK rubric could not see a leading label, the one fault that kills a run before it starts; and its forge verifier pinned a cell count, so every fixture the rubric gained reddened a … | -- | -| 247 | Q158 | record | 14398-14443 | 14245 | cont: OPENED | **Q158 — OPENED and REPAIRED in the same tick (volt, 2026-11-02, at `9a9061f` and the commit this record lands in).** Two defects, one shape: an instrument graded a property of its subject's … | -- | +| 247 | Q158 | record | 14398-14446 | 14251 | cont: OPENED | **Q158 — OPENED and REPAIRED in the same tick (volt, 2026-11-02, at `9a9061f` and the commit this record lands in).** Two defects, one shape: an instrument graded a property of its subject's … | -- | +| 248 | Q154 | heading | 14447-14448 | 340 | opening | closure — a dated census graded against a tree it never described, and one gate implemented twice; the census is now pinned to a revision, the second gate is a pointer, and the verifier has a … | -- | +| 249 | Q154 | record | 14449-14465 | 10675 | cont: OPENED | **Q154 — OPENED and REPAIRED in the same tick (volt; opened, repaired and measured in the 2026-11-02 tick at `2f8ef83`, and landed by the commit this record lands in, 2026-11-03; quill lane by … | -- | ## Ids with no `## ` heading @@ -2154,17 +2156,30 @@ The block below is the parse this document renders, byte for byte. `--check` com "title": "**Q157 \u2014 OPENED and REPAIRED in the same tick (volt, 2026-11-02, at `602e982` and the commit this record lands in; sol lane by authorship, unclaimed and taken).** `CHECK-2026-11-02-untracked-classify` \u2026" }, { - "bytes": 14245, - "end_line": 14443, + "bytes": 14251, + "end_line": 14446, "id": "Q158", "kind": "record", "line": 14398, - "lines": 46, + "lines": 49, "role": "continuation", "role_detail": "OPENED", "status": null, "status_line": null, "title": "**Q158 \u2014 OPENED and REPAIRED in the same tick (volt, 2026-11-02, at `9a9061f` and the commit this record lands in).** Two defects, one shape: an instrument graded a property of its subject's \u2026" + }, + { + "bytes": 10675, + "end_line": 14465, + "id": "Q154", + "kind": "record", + "line": 14449, + "lines": 17, + "role": "continuation", + "role_detail": "OPENED", + "status": null, + "status_line": null, + "title": "**Q154 \u2014 OPENED and REPAIRED in the same tick (volt; opened, repaired and measured in the 2026-11-02 tick at `2f8ef83`, and landed by the commit this record lands in, 2026-11-03; quill lane by \u2026" } ], "ids_multi_section": { @@ -2311,6 +2326,7 @@ The block below is the parse this document renders, byte for byte. `--check` com "Q151", "Q152", "Q153", + "Q154", "Q155", "Q156", "Q157", @@ -5516,17 +5532,43 @@ The block below is the parse this document renders, byte for byte. `--check` com "title": "closure \u2014 the CHECK rubric could not see a leading label, the one fault that kills a run before it starts; and its forge verifier pinned a cell count, so every fixture the rubric gained reddened a \u2026" }, { - "bytes": 14245, - "end_line": 14443, + "bytes": 14251, + "end_line": 14446, "id": "Q158", "kind": "record", "line": 14398, - "lines": 46, + "lines": 49, "role": "continuation", "role_detail": "OPENED", "status": null, "status_line": null, "title": "**Q158 \u2014 OPENED and REPAIRED in the same tick (volt, 2026-11-02, at `9a9061f` and the commit this record lands in).** Two defects, one shape: an instrument graded a property of its subject's \u2026" + }, + { + "bytes": 340, + "end_line": 14448, + "id": "Q154", + "kind": "heading", + "line": 14447, + "lines": 2, + "role": "opening", + "role_detail": "", + "status": null, + "status_line": null, + "title": "closure \u2014 a dated census graded against a tree it never described, and one gate implemented twice; the census is now pinned to a revision, the second gate is a pointer, and the verifier has a \u2026" + }, + { + "bytes": 10675, + "end_line": 14465, + "id": "Q154", + "kind": "record", + "line": 14449, + "lines": 17, + "role": "continuation", + "role_detail": "OPENED", + "status": null, + "status_line": null, + "title": "**Q154 \u2014 OPENED and REPAIRED in the same tick (volt; opened, repaired and measured in the 2026-11-02 tick at `2f8ef83`, and landed by the commit this record lands in, 2026-11-03; quill lane by \u2026" } ], "nested": [ @@ -6076,9 +6118,9 @@ The block below is the parse this document renders, byte for byte. `--check` com "end_line": 8, "line": 1 }, - "queue_bytes": 2463735, - "queue_lines": 14443, - "queue_sha256": "3a4891b6ad6a99357cd8f1464d4c7731e75ad43e8461d365195454ecfae189e6", + "queue_bytes": 2474756, + "queue_lines": 14465, + "queue_sha256": "5b3ab81d69c220c1704d43e9d9b7807323eba7c467e7d0314b632a625ac23ea6", "sections": [ { "bytes": 3139, @@ -7457,6 +7499,19 @@ The block below is the parse this document renders, byte for byte. `--check` com "status": null, "status_line": null, "title": "closure \u2014 the CHECK rubric could not see a leading label, the one fault that kills a run before it starts; and its forge verifier pinned a cell count, so every fixture the rubric gained reddened a \u2026" + }, + { + "bytes": 340, + "end_line": 14448, + "id": "Q154", + "kind": "heading", + "line": 14447, + "lines": 2, + "role": "opening", + "role_detail": "", + "status": null, + "status_line": null, + "title": "closure \u2014 a dated census graded against a tree it never described, and one gate implemented twice; the census is now pinned to a revision, the second gate is a pointer, and the verifier has a \u2026" } ] } diff --git a/wizard-work/quill/CHECK-quill-draft-compliance b/wizard-work/quill/CHECK-quill-draft-compliance index 1f72bb8..9b29cc0 100755 --- a/wizard-work/quill/CHECK-quill-draft-compliance +++ b/wizard-work/quill/CHECK-quill-draft-compliance @@ -1,120 +1,30 @@ #!/usr/bin/env bash -set -euo pipefail +# CHECK-quill-draft-compliance (lane copy) -- delegates to the repository gate. +# +# WHAT THIS FILE USED TO BE, AND WHY IT IS NOT ANY MORE (Q154) +# It was a second, independent implementation of the same gate: a bash script +# with a `python3 -` heredoc that scanned the lane through the absolute path +# /root/troupe-standup/wizard-work/quill, appended a row read from +# /root/.hermes/wizard-outputs/quill/ (a file outside the repository), and +# regenerated the table WITHOUT its header line so that its `diff` would read +# clean -- which is why the committed table at HEAD had 82 rows and no header. +# Two implementations of one gate is also why the tree carried two different +# verdicts for the same artifact. +# +# There is now exactly one gate, at the repository root, and this path is a +# pointer to it: same legs, same exit codes, no second rule list, no host +# path. Arguments are passed through. +# +# Exit codes are the root gate's: 0 all legs passed, 1 a fault, 2 ungradable. +set -u -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -PROJECT_ROOT="$SCRIPT_DIR" +HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" || exit 2 +ROOT="$(cd "$HERE/../.." && pwd)" || exit 2 +GATE="$ROOT/CHECK-quill-draft-compliance" -TSV="$PROJECT_ROOT/draft-compliance-report-2026-10-31.tsv" -REPORT="$PROJECT_ROOT/draft-verification-report-2026-11-01.md" - -if [[ ! -f "$TSV" ]]; then - echo "Missing TSV: $TSV" - exit 1 -fi -if [[ ! -f "$REPORT" ]]; then - echo "Missing report: $REPORT" - exit 1 +if [ ! -f "$GATE" ]; then + echo "delegation target missing: $GATE" >&2 + exit 2 fi -# Generate fresh TSV using Python -FRESH=$(mktemp) -python3 - "$FRESH" <<'PY' -import sys -from pathlib import Path - -wizard_work = Path("/root/troupe-standup/wizard-work/quill") -exclude = {"draft-compliance-report-2026-10-31.md", "draft-verification-report-2026-11-01.md"} -verification_report = "draft-verification-report-2026-11-01.md" -rows = [] -for p in sorted(wizard_work.glob("*.md")): - if p.name in exclude: - continue - rel = p.name - lines = p.read_text(errors="replace").splitlines() - line_count = len(lines) - has_verdict = any(l.strip().startswith("VERDICT:") for l in lines) - has_check = any(l.strip().startswith("CHECK:") for l in lines) - bare_cmd = "" - for l in lines: - s = l.strip() - if s.startswith("CHECK:"): - bare_cmd = s[len("CHECK:"):].strip() - break - rows.append((rel, line_count, has_verdict, has_check, bool(bare_cmd), bare_cmd)) - -# Include verification report -report_path = Path("/root/.hermes/wizard-outputs/quill/draft-verification-report-2026-11-01.md") -if report_path.exists(): - lines = report_path.read_text(errors="replace").splitlines() - line_count = len(lines) - has_verdict = any(l.strip().startswith("VERDICT:") for l in lines) - has_check = any(l.strip().startswith("CHECK:") for l in lines) - bare_cmd = "" - for l in lines: - s = l.strip() - if s.startswith("CHECK:"): - bare_cmd = s[len("CHECK:"):].strip() - break - rows.append((verification_report, line_count, has_verdict, has_check, bool(bare_cmd), bare_cmd)) - -rows.sort(key=lambda r: r[0]) -with open(sys.argv[1], "w") as f: - f.write(f"# measured {len(rows)} markdown files\n") - for rel, lc, hv, hc, hbc, cmd in rows: - f.write(f"{rel}\t{lc}\t{hv}\t{hc}\t{hbc}\t{cmd}\n") -PY - -if ! diff -u "$TSV" "$FRESH" > /dev/null; then - echo "TSV mismatch" - diff -u "$TSV" "$FRESH" | head -20 - rm -f "$FRESH" - exit 1 -fi - -# Verify report summary numbers match TSV -pop=$(grep -oP 'Total `\.md` drafts scanned\s*\|\s*\K\d+' "$REPORT" || true) -verdict=$(grep -oP 'Drafts with `VERDICT:`\s*\|\s*\K\d+' "$REPORT" || true) -check=$(grep -oP 'Drafts with `CHECK:`\s*\|\s*\K\d+' "$REPORT" || true) -bare=$(grep -oP 'Drafts with a bare `CHECK:` command\s*\|\s*\K\d+' "$REPORT" || true) -failing=$(grep -oP 'Drafts failing at least one column\s*\|\s*\K\d+' "$REPORT" || true) - -tsv_pop=$(tail -n +2 "$TSV" | wc -l) -tsv_verdict=$(awk -F'\t' '$3 == "True" {count++} END {print count+0}' "$TSV") -tsv_check=$(awk -F'\t' '$4 == "True" {count++} END {print count+0}' "$TSV") -tsv_bare=$(awk -F'\t' '$5 == "True" {count++} END {print count+0}' "$TSV") -tsv_failing=$(awk -F'\t' 'NR>1 && ($3 != "True" || $5 != "True") {count++} END {print count+0}' "$TSV") - -if [[ "$pop" != "$tsv_pop" ]]; then - echo "Population mismatch: report=$pop, tsv=$tsv_pop" - exit 1 -fi -if [[ "$verdict" != "$tsv_verdict" ]]; then - echo "Verdict count mismatch: report=$verdict, tsv=$tsv_verdict" - exit 1 -fi -if [[ "$check" != "$tsv_check" ]]; then - echo "Check count mismatch: report=$check, tsv=$tsv_check" - exit 1 -fi -if [[ "$bare" != "$tsv_bare" ]]; then - echo "Bare check mismatch: report=$bare, tsv=$tsv_bare" - exit 1 -fi -if [[ "$failing" != "$tsv_failing" ]]; then - echo "Failing mismatch: report=$failing, tsv=$tsv_failing" - exit 1 -fi - -# Verify report has VERDICT and CHECK lines -if ! grep -q '^VERDICT:' "$REPORT"; then - echo "Report missing VERDICT line" - exit 1 -fi -if ! grep -q '^CHECK:' "$REPORT"; then - echo "Report missing CHECK line" - exit 1 -fi - -rm -f "$FRESH" -echo "All checks passed" -exit 0 +exec bash "$GATE" "$@" diff --git a/wizard-work/quill/draft-compliance-report-2026-10-31.pin b/wizard-work/quill/draft-compliance-report-2026-10-31.pin new file mode 100644 index 0000000..0de38d3 --- /dev/null +++ b/wizard-work/quill/draft-compliance-report-2026-10-31.pin @@ -0,0 +1,14 @@ +# The revision this census describes. +# +# draft-compliance-report-2026-10-31 is a SNAPSHOT. It counts the .md drafts in +# this lane as they stood at `rev`, and says nothing about a later tree. The +# verifier materialises the lane at `rev` (git archive) and grades the committed +# table and report against THOSE bytes, so a draft added tomorrow is drift to +# report, not a fault of this census. The live tree is still graded on demand +# with `--worktree`. +# +# `tsv` is the sha256 of the committed table. A pin is moved deliberately: +# re-derive the table, rewrite this file, commit both together. The verifier +# reads this file; it does not guess. +rev 2f8ef83df22b25f67f092f07d2d37d7891f116d4 +tsv 74d092b4eef3cd1c6f9aaca74c2e5caa4a9232561f97fa07622d8e3ade285b17 diff --git a/wizard-work/quill/draft_compliance_rule.py b/wizard-work/quill/draft_compliance_rule.py index 038152a..fde0b84 100644 --- a/wizard-work/quill/draft_compliance_rule.py +++ b/wizard-work/quill/draft_compliance_rule.py @@ -34,6 +34,10 @@ import shlex # the table it publishes). ARTIFACT_MD = "draft-compliance-report-2026-10-31.md" ARTIFACT_TSV = "draft-compliance-report-2026-10-31.tsv" +# The revision the artifact describes, and the digest of its committed bytes. +# A dated census describes a tree; without the pin it silently starts describing +# a later one (Q154: 8 drafts landed after this table and it read red for it). +ARTIFACT_PIN = "draft-compliance-report-2026-10-31.pin" COLUMNS = ("filename", "lines", "has_verdict", "has_check", "check_clean", "check_command") diff --git a/wizard-work/quill/verify_draft_compliance.py b/wizard-work/quill/verify_draft_compliance.py index 2c7c86e..8b9f1a6 100644 --- a/wizard-work/quill/verify_draft_compliance.py +++ b/wizard-work/quill/verify_draft_compliance.py @@ -10,6 +10,21 @@ WHAT IT GRADES, AND AGAINST WHAT the report's Evidence table against the counts it just measured, so a stale numeral in the prose is a fault rather than a reader's problem. + WHICH TREE -- three modes, because a dated census describes a revision + (default) the lane as it stands at the pin in + `draft-compliance-report-2026-10-31.pin`, extracted with + `git archive`; the committed TSV and report are graded against + it. Drift since the pin is printed as a note, never a fault. + --worktree the live worktree; this is the "is the census current?" reading + and it faults on any difference, additions included. + --rev REV the lane at REV, for probing whether a given tree's census is + true and for grading an older landing. + + Why: the 2026-10-31 table was byte-true at 2f8ef83 and read red at HEAD for + eight drafts that landed after it -- a snapshot cannot be graded against a + tree it never described. And the fix must not be "grade nothing": the pin is + what makes the claim falsifiable (Q154). + Paths come from THIS FILE's location. The 2026-10-31 version hardcoded an absolute home-directory path in both the scanner and the verifier, so a clone's CHECK graded the host's tree and a mutated copy of the committed TSV @@ -17,13 +32,16 @@ WHAT IT GRADES, AND AGAINST WHAT class, because this file's own fix must not reintroduce it. EXIT CODES -- the archive's convention - 0 the TSV and the report re-derive from the tree - 1 a fault: a row, a file-set entry or a reported count disagrees - 2 could not grade: the report or TSV is missing/unreadable, or the lane - directory does not exist. Never a pass. + 0 the TSV and the report re-derive from the tree they describe + 1 a fault: a row, a file-set entry or a reported count disagrees, or the + committed TSV is not the bytes the pin names + 2 could not grade: the report, the TSV or the pin is missing/unreadable, the + pin names no rev, the rev cannot be extracted, or the repository root + cannot be found. Never a pass. - --selftest runs the cells in a temp tree: one green control and eight mutants, - so a green reading is never the only thing this checker can print. + --selftest runs the cells in a temp tree: one green control, eight mutants and + four pin-contract cells, so a green reading is never the only thing this + checker can print. NOTE ON THE SECOND IMPLEMENTATION OF `is_bare` It reads operators on the raw string and only checks quoting for parity, so an @@ -33,9 +51,11 @@ NOTE ON THE SECOND IMPLEMENTATION OF `is_bare` the two implementations ever disagree on a command this corpus actually holds. """ import argparse +import hashlib import os import re import shutil +import subprocess import sys import tempfile @@ -44,6 +64,10 @@ sys.path.insert(0, HERE) import draft_compliance_rule as rule # noqa: E402 +# The path inside the repository that holds this lane. Pinned grading archives +# exactly this directory at the pinned rev; nothing outside it is read. +PATHSPEC = "wizard-work/quill" + # The report's Evidence table, label -> the metric it claims. The labels are # matched verbatim; a missing label is a fault (the report must say what it # measured). @@ -209,6 +233,112 @@ def check(lane=None, report=None, tsv=None): return (1 if faults else 0), faults, notes +# --- the pin: which revision this census describes --------------------------- + +def repo_root(start): + """Nearest ancestor that holds a `.git` entry, or None.""" + path = os.path.abspath(start) + while True: + if os.path.exists(os.path.join(path, ".git")): + return path + parent = os.path.dirname(path) + if parent == path: + return None + path = parent + + +def materialize(rev, root, dest): + """Extract PATHSPEC at `rev` under `dest`; return (lane_dir, error).""" + try: + src = subprocess.run(["git", "-C", root, "archive", rev, "--", PATHSPEC], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + except OSError as exc: + return None, "cannot run git: %s" % exc + if src.returncode != 0: + return None, "cannot archive %s: %s" % ( + rev, src.stderr.decode("utf-8", "replace").strip()[:200]) + lane = os.path.join(dest, "lane") + os.makedirs(lane) + try: + untar = subprocess.run(["tar", "-x", "-C", lane], input=src.stdout, + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + except OSError as exc: + return None, "cannot run tar: %s" % exc + if untar.returncode != 0: + return None, "cannot extract %s: %s" % ( + rev, untar.stderr.decode("utf-8", "replace").strip()[:200]) + return os.path.join(lane, PATHSPEC), "" + + +def read_pin(path): + """The pin as a dict; raises OSError when it cannot be read.""" + values = {} + with open(path, "r", encoding="utf-8") as f: + for line in f: + line = line.strip() + if not line or line.startswith("#"): + continue + parts = line.split(None, 1) + if len(parts) == 2: + values[parts[0]] = parts[1].strip() + return values + + +def pin_verdict(pin, tsv): + """(rc, faults) for the pin contract: 2 ungradable, 1 not the bytes, 0 ok. + + The digest is what makes "the committed table" a fixed claim: without it a + silent edit to the TSV would be graded as the new truth. + """ + try: + values = read_pin(pin) + except OSError as exc: + return 2, ["pin missing or unreadable: %s" % exc] + if not values.get("rev"): + return 2, ["pin names no rev: %s" % pin] + try: + with open(tsv, "rb") as f: + digest = hashlib.sha256(f.read()).hexdigest() + except OSError as exc: + return 2, ["TSV unreadable: %s" % exc] + want = values.get("tsv") + if want and want != digest: + return 1, ["committed TSV is not the pinned bytes: sha256 %s, pin %s" + % (digest, want)] + return 0, [] + + +def grade_at_rev(rev, claim_dir, lane=None): + """Grade the artifact in `claim_dir` against the drafts at `rev`.""" + root = repo_root(claim_dir) + if root is None: + return 2, ["cannot find the repository root above %s" % claim_dir], [] + tmp = tempfile.mkdtemp(prefix="q154-rev-") + try: + tree, error = materialize(rev, root, tmp) + if tree is None: + return 2, [error], [] + return check(tree, os.path.join(claim_dir, rule.ARTIFACT_MD), + os.path.join(claim_dir, rule.ARTIFACT_TSV)) + finally: + shutil.rmtree(tmp, ignore_errors=True) + + +def drift_note(pinned_rows, live_rows): + """What moved between the pinned census and the live tree. Advisory text.""" + pin_map = {r[0]: r for r in pinned_rows} + live_map = {r[0]: r for r in live_rows} + added = sorted(set(live_map) - set(pin_map)) + gone = sorted(set(pin_map) - set(live_map)) + changed = sorted(n for n in set(pin_map) & set(live_map) + if pin_map[n] != live_map[n]) + text = "drift since the pin: %d added, %d changed, %d removed" % ( + len(added), len(changed), len(gone)) + if added: + text += "; added: " + ", ".join(added[:6]) + (" ..." if len(added) > 6 else "") + return text + + FIXTURE_FILES = { "good.md": "# t\n\nVERDICT: ok\nCHECK: python3 x.py\n", "plain.md": "# nothing\n", @@ -312,6 +442,36 @@ def selftest(verbose=True): cell("report-count-stale", 1, stale_count) cell("check-line-edited", 1, check_line_edited) + # The pin contract: a snapshot is graded against the bytes and the rev it + # names, and an unreadable pin is ungradable rather than a pass. + good_tsv = "x\n" + + def pin_cell(name, want, pin_text): + tmp = tempfile.mkdtemp(prefix="q154-pin-") + try: + tsv = os.path.join(tmp, "t.tsv") + with open(tsv, "w", encoding="utf-8") as f: + f.write(good_tsv) + pin = os.path.join(tmp, "p.pin") + if pin_text is not None: + with open(pin, "w", encoding="utf-8") as f: + f.write(pin_text) + got, faults = pin_verdict(pin, tsv) + finally: + shutil.rmtree(tmp, ignore_errors=True) + cells.append(name) + if got != want: + failed.append((name, want, got, faults[:2])) + if verbose: + print("%-22s rc=%d want=%d %s" + % (name, got, want, "ok" if got == want else "FAIL")) + + digest = hashlib.sha256(good_tsv.encode("utf-8")).hexdigest() + pin_cell("pin-ok", 0, "rev 0123456789abcdef\ntsv %s\n" % digest) + pin_cell("pin-tsv-digest-moved", 1, "rev 0123456789abcdef\ntsv %s\n" % ("0" * 64)) + pin_cell("pin-no-rev", 2, "tsv %s\n" % digest) + pin_cell("pin-absent", 2, None) + # The two implementations of the rule, over the fixture cases and this # directory's own corpus. A divergence here is what the 2026-10-31 copies had. divergence = [cmd for cmd, want, _why in rule.SELFTEST_CASES @@ -348,25 +508,12 @@ def selftest(verbose=True): return 1 if failed else 0 -def main(argv=None): - ap = argparse.ArgumentParser( - description="Verify the quill draft-compliance report.") - ap.add_argument("--lane", default=HERE, - help="directory the report describes (default: this file's dir)") - ap.add_argument("--report", default=None, help="report .md (default: in --lane)") - ap.add_argument("--tsv", default=None, help="report .tsv (default: in --lane)") - ap.add_argument("--selftest", action="store_true", help="run the cells") - a = ap.parse_args(argv) - - if a.selftest: - return selftest() - - rc, faults, notes = check(a.lane, a.report, a.tsv) +def _emit(rc, faults, notes, mode): for note in notes: print(note) if rc == 0: - print("VERDICT: PASS -- TSV and report re-derive from the tree (%s)" - % notes[0]) + print("VERDICT: PASS -- TSV and report re-derive from %s (%s)" + % (mode, notes[0] if notes else "no counts")) elif rc == 2: print("VERDICT: UNGRADABLE") for f in faults: @@ -378,5 +525,55 @@ def main(argv=None): return rc +def main(argv=None): + ap = argparse.ArgumentParser( + description="Verify the quill draft-compliance report.") + ap.add_argument("--lane", default=None, + help="grade this directory directly (fixtures; default: " + "the pinned revision)") + ap.add_argument("--report", default=None, help="report .md (default: in --lane)") + ap.add_argument("--tsv", default=None, help="report .tsv (default: in --lane)") + ap.add_argument("--pin", default=None, + help="pin file (default: %s beside the artifact)" + % rule.ARTIFACT_PIN) + ap.add_argument("--rev", default=None, + help="grade the committed artifact against the lane at REV") + ap.add_argument("--worktree", action="store_true", + help="grade against the live worktree instead of the pin") + ap.add_argument("--selftest", action="store_true", help="run the cells") + a = ap.parse_args(argv) + + if a.selftest: + return selftest() + + claim = a.lane or HERE + report = a.report or os.path.join(claim, rule.ARTIFACT_MD) + tsv = a.tsv or os.path.join(claim, rule.ARTIFACT_TSV) + pin = a.pin or os.path.join(claim, rule.ARTIFACT_PIN) + + if a.worktree or a.lane: + rc, faults, notes = check(claim, report, tsv) + mode = "the live worktree" if a.worktree else "the tree at %s" % claim + elif a.rev: + rc, faults, notes = grade_at_rev(a.rev, claim) + mode = "the lane at %s" % a.rev + else: + rc_pin, faults_pin = pin_verdict(pin, tsv) + if rc_pin: + return _emit(rc_pin, faults_pin, [], "the pin") + rev = read_pin(pin)["rev"] + rc, faults, notes = grade_at_rev(rev, claim) + mode = "the pinned revision %s" % rev[:12] + + # A snapshot is graded against the revision it names; what has landed since + # is drift to report, not a fault of the table. `--worktree` grades it. + if mode != "the live worktree": + try: + notes = list(notes) + [drift_note(read_tsv(tsv)[2], own_rows(HERE))] + except OSError: + pass + return _emit(rc, faults, notes, mode) + + if __name__ == "__main__": raise SystemExit(main()) diff --git a/wizard-work/volt/q137-open-set/open_set.py b/wizard-work/volt/q137-open-set/open_set.py index 5cd478d..e90d319 100644 --- a/wizard-work/volt/q137-open-set/open_set.py +++ b/wizard-work/volt/q137-open-set/open_set.py @@ -562,8 +562,14 @@ PIN_OPENED = [51, 52, 53, 65, 100, 101, 102, 103, 104, 105, 106, 107, 109, # record_only stays 55 and open / opened stay 0 / 26 (same-tick closure, no # probe; CHECK-q158 is its guard). Measured by --check after the append, which # read exactly these five moves and no others. -PIN_COUNTS = {"headings": 106, "heading_ids": 93, "records": 120, - "record_ids": 86, "ids": 148, "open": 0, "opened": 26, +# Q154 (2026-11-03): one heading (## Q154 closure) and one record (**Q154 -- +# OPENED and REPAIRED ...) for a new id, so headings 106 -> 107, heading_ids +# 93 -> 94, records 120 -> 121, record_ids 86 -> 87, ids 148 -> 149; +# record_only stays 55 and open / opened stay 0 / 26 (same-tick closure, no +# probe; CHECK-q154 is its guard). Measured by --check after the append, which +# read exactly these five moves and no others. +PIN_COUNTS = {"headings": 107, "heading_ids": 94, "records": 121, + "record_ids": 87, "ids": 149, "open": 0, "opened": 26, "record_only": 55} PIN_STATE = {