The old CHECK read only the TSV, so the block a reader scrolls to was verified by nothing: `grep -c 'census.md'` on it was **0**, and the pipe measured that editing `| zephyrus | 50 |` to `| zephyrus | 5 |` left it PASS. Three legs now re-derive the MD from the same pinned name list: - leg 4: the `| wizard | checkin_files |` block must equal the awk derivation (identical to the TSV body, so the two published halves cannot disagree); - leg 5: `**Total files:** N across D dates` must equal the pinned name count and its distinct-date count; - leg 6: the `| date | files |` appendix must equal the per-date derivation. Probes (`q88-probe-md.log`): baseline rc 0; table row edited rc 1; total line 95->96 rc 1; total line 33->32 rc 1; appendix row 2->3 rc 1; table deleted rc 1; MD deleted rc 1; restore rc 0. The `q88-probe.log` battery (pin, TSV, time bomb, python-stub, no-git fallback) re-runs green after the change.
169 lines
7.1 KiB
Bash
Executable File
169 lines
7.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# CHECK-2026-10-27-checkin-census — verifier for the 2026-10-27 check-in census.
|
|
#
|
|
# Verdict: exit 0 iff the committed TSV equals a re-derivation of the census from
|
|
# the PINNED name list beside it, and the pin itself is a real revision of
|
|
# `checkins/`. Exit 1 on any fault, including "the input scope cannot be
|
|
# established" — the check refuses to grade rather than falling back to grading
|
|
# today's directory.
|
|
#
|
|
# WHAT CHANGED AND WHY (Q88). The previous revision recomputed the row set from
|
|
# `checkins/*.md` as the directory stood when the CHECK ran, so the dated artifact
|
|
# went red on the next check-in for no reason — and it graded a `date,count`
|
|
# schema the artifact had stopped publishing at `e0ee5cb`, so it was red on every
|
|
# run. The input is now the committed `2026-10-27-checkin-census.files`.
|
|
#
|
|
# The recompute is awk/sort/cmp over the name list — it does not import, read or
|
|
# re-run `extract_checkin_census_2026-10-27.py`, so the grader and the generator
|
|
# cannot agree by sharing a bug.
|
|
#
|
|
# `set -u`, no `set -e`: each leg reports and the script decides, so a green
|
|
# verdict always means every leg ran.
|
|
|
|
set -u
|
|
|
|
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO="$(git -C "$HERE" rev-parse --show-toplevel 2>/dev/null)" \
|
|
|| REPO="$(cd "$HERE/../.." && pwd)"
|
|
FILES="$HERE/2026-10-27-checkin-census.files"
|
|
TSV="$HERE/2026-10-27-checkin-census.tsv"
|
|
MD="$HERE/2026-10-27-checkin-census.md"
|
|
TAB="$(printf '\t')"
|
|
|
|
fail() { printf 'FAIL: %s\n' "$*" >&2; exit 1; }
|
|
scope_fail() { printf 'FAIL: SCOPE NOT ESTABLISHED: %s\n' "$*" >&2; exit 1; }
|
|
|
|
tmp="$(mktemp -d)"
|
|
trap 'rm -rf "$tmp"' EXIT
|
|
|
|
# ---------------------------------------------------------------- leg 1: scope
|
|
# The pin is the artifact's input. If it is absent, malformed, unsorted,
|
|
# duplicated or undated there is nothing to recompute from, and the check says so
|
|
# instead of grading whatever the directory holds.
|
|
[ -s "$FILES" ] || scope_fail "pinned name list missing or empty: ${FILES#"$REPO"/}"
|
|
|
|
header="$(head -n 1 "$FILES")"
|
|
if ! [[ $header =~ ^#\ pin\ checkins@([0-9a-f]{40})\ tree=([0-9a-f]{40})$ ]]; then
|
|
scope_fail "pin header not understood: '$header'"
|
|
fi
|
|
pin_commit="${BASH_REMATCH[1]}"
|
|
pin_tree="${BASH_REMATCH[2]}"
|
|
|
|
tail -n +2 "$FILES" > "$tmp/names"
|
|
[ -s "$tmp/names" ] || scope_fail "pin names no files"
|
|
|
|
undated="$(grep -cvE '^[0-9]{4}-[0-9]{2}-[0-9]{2}-.*\.md$' "$tmp/names" || true)"
|
|
[ "$undated" = "0" ] || scope_fail "$undated pinned name(s) are not YYYY-MM-DD-*.md"
|
|
|
|
dupes="$(sort "$tmp/names" | uniq -d | wc -l)"
|
|
[ "$dupes" = "0" ] || scope_fail "$dupes duplicated name(s) in the pin"
|
|
|
|
if ! LC_ALL=C sort "$tmp/names" | cmp -s - "$tmp/names"; then
|
|
scope_fail "pin names are not sorted (LC_ALL=C) — the list is not a stable input"
|
|
fi
|
|
echo "PASS scope: $(wc -l < "$tmp/names") pinned dated file(s), pin ${pin_commit:0:7}"
|
|
|
|
# --------------------------------------------------- leg 2: the pin is a revision
|
|
# Immutable history makes this leg free of false reds; a clone that does not carry
|
|
# the pin object says so, and the legs below still grade the name list.
|
|
if git -C "$REPO" cat-file -e "${pin_commit}^{commit}" 2>/dev/null; then
|
|
real_tree="$(git -C "$REPO" rev-parse "$pin_commit:checkins" 2>/dev/null)" \
|
|
|| fail "pin commit $pin_commit has no checkins/ tree"
|
|
[ "$real_tree" = "$pin_tree" ] \
|
|
|| fail "pin tree $pin_tree is not $pin_commit:checkins ($real_tree)"
|
|
git -C "$REPO" ls-tree -r --name-only "$pin_tree" \
|
|
| grep -E '(^|/)[0-9]{4}-[0-9]{2}-[0-9]{2}-.*\.md$' \
|
|
| sed 's#.*/##' | LC_ALL=C sort > "$tmp/git_names"
|
|
if ! cmp -s "$tmp/git_names" "$tmp/names"; then
|
|
printf 'FAIL: pin name list != checkins/ at %s\n' "${pin_commit:0:7}" >&2
|
|
diff -u "$tmp/git_names" "$tmp/names" >&2 || true
|
|
exit 1
|
|
fi
|
|
echo "PASS pin: name list == checkins/ tree ${pin_tree:0:7} at ${pin_commit:0:7}"
|
|
else
|
|
echo "SKIP pin: commit ${pin_commit:0:7} not in this object database —" \
|
|
"the committed name list is the pin"
|
|
fi
|
|
|
|
# ------------------------------------------- leg 3: derive the per-wizard table
|
|
awk '
|
|
{ n = $0
|
|
sub(/\.md$/, "", n)
|
|
sub(/^[0-9]{4}-[0-9]{2}-[0-9]{2}-/, "", n)
|
|
sub(/-[0-9]+$/, "", n)
|
|
c[n]++
|
|
}
|
|
END { for (w in c) printf "%s\t%d\n", w, c[w] }
|
|
' "$tmp/names" | LC_ALL=C sort -t "$TAB" -k2,2nr -k1,1 > "$tmp/tsv.body"
|
|
|
|
{ printf 'wizard%scheckin_files\n' "$TAB"; cat "$tmp/tsv.body"; } > "$tmp/tsv.expected"
|
|
|
|
[ -s "$TSV" ] || fail "TSV missing or empty: ${TSV#"$REPO"/}"
|
|
if ! cmp -s "$tmp/tsv.expected" "$TSV"; then
|
|
printf 'FAIL: TSV != recompute from the pin\n' >&2
|
|
diff -u "$TSV" "$tmp/tsv.expected" >&2 || true
|
|
exit 1
|
|
fi
|
|
echo "PASS tsv: $(($(wc -l < "$TSV") - 1)) wizard row(s)," \
|
|
"$(awk -F"$TAB" 'NR>1{s+=$2} END{print s+0}' "$TSV") file(s)"
|
|
|
|
# ------------------------------------------- leg 4: the MD's published table
|
|
# The MD is what a reader scrolls to, and until now nothing graded it: editing
|
|
# `| zephyrus | 51 |` to `| zephyrus | 5 |` left the old CHECK PASS.
|
|
[ -s "$MD" ] || fail "MD missing or empty: ${MD#"$REPO"/}"
|
|
awk -F'|' '
|
|
/^\| *wizard *\| *checkin_files *\| *$/ { inb = 1; next }
|
|
inb && /^\|[- |]*$/ { next }
|
|
inb && /^\|/ {
|
|
w = $2; n = $3
|
|
gsub(/[[:space:]]/, "", w); gsub(/[[:space:]]/, "", n)
|
|
printf "%s\t%s\n", w, n; next
|
|
}
|
|
inb { inb = 0 }
|
|
' "$MD" > "$tmp/md.body"
|
|
echo "PASS tables: MD per-wizard block is $(wc -l < "$tmp/md.body") row(s)"
|
|
if ! cmp -s "$tmp/tsv.body" "$tmp/md.body"; then
|
|
printf 'FAIL: MD per-wizard table != recompute from the pin\n' >&2
|
|
diff -u "$tmp/tsv.body" "$tmp/md.body" >&2 || true
|
|
exit 1
|
|
fi
|
|
|
|
# ------------------------------------------------- leg 5: the MD's total line
|
|
want_files="$(wc -l < "$tmp/names")"
|
|
want_dates="$(cut -c1-10 "$tmp/names" | sort -u | wc -l)"
|
|
read -r md_files md_dates < <(
|
|
sed -n 's/^\*\*Total files:\*\* \([0-9][0-9]*\) across \([0-9][0-9]*\) dates.*$/\1 \2/p' "$MD"
|
|
)
|
|
[ -n "${md_files:-}" ] || fail "MD carries no '**Total files:** N across D dates' line"
|
|
if [ "$md_files" != "$want_files" ] || [ "$md_dates" != "$want_dates" ]; then
|
|
fail "MD total line says ${md_files} files / ${md_dates} dates; the pin gives" \
|
|
"${want_files} / ${want_dates}"
|
|
fi
|
|
echo "PASS total: MD says ${md_files} file(s) across ${md_dates} date(s)"
|
|
|
|
# --------------------------------------------- leg 6: the MD's per-date appendix
|
|
awk -F'|' '
|
|
/^\| *date *\| *files *\| *$/ { inb = 1; next }
|
|
inb && /^\|[- |]*$/ { next }
|
|
inb && /^\|/ {
|
|
d = $2; n = $3
|
|
gsub(/[[:space:]]/, "", d); gsub(/[[:space:]]/, "", n)
|
|
printf "%s\t%s\n", d, n; next
|
|
}
|
|
inb { inb = 0 }
|
|
' "$MD" > "$tmp/md.dates"
|
|
cut -c1-10 "$tmp/names" | LC_ALL=C sort | uniq -c \
|
|
| awk '{printf "%s\t%d\n", $2, $1}' | LC_ALL=C sort > "$tmp/pin.dates"
|
|
if ! cmp -s "$tmp/pin.dates" "$tmp/md.dates"; then
|
|
printf 'FAIL: MD per-date appendix != recompute from the pin\n' >&2
|
|
diff -u "$tmp/pin.dates" "$tmp/md.dates" >&2 || true
|
|
exit 1
|
|
fi
|
|
echo "PASS appendix: $(wc -l < "$tmp/md.dates") date row(s) agree with the pin"
|
|
|
|
# -------------------------------------------------------------------- verdict
|
|
printf 'VERDICT=PASS census-2026-10-27 rows=%s files=%s pin=%s\n' \
|
|
"$(($(wc -l < "$TSV") - 1))" \
|
|
"$(awk -F"$TAB" 'NR>1{s+=$2} END{print s+0}' "$TSV")" "${pin_commit:0:7}"
|
|
exit 0
|