quill: add standup draft verifier and sample

This commit is contained in:
quill committed 2026-11-01 14:40:52 +00:00
1 parent 9e476c538c
commit d3c515b955
4 files changed
+207 -78

No files matched your search

+134
View File
@@ -0,0 +1,134 @@
#!/usr/bin/env bash
# CHECK-q149 -- the beam lane's gate, and the eight cells it was not grading.
#
# Q149 (2026-11-01): `wizard-work/beam/test_pathguard.py` imported `pytest` for
# `pytest.raises` alone, on an interpreter with no pytest. The import failed,
# `run_lane_tests.py` reported all eight cells as one `IMPORT-FAIL` line, and
# `bash wizard-work/beam/CHECK` read rc 1 -- a red gate, named in Q145's record
# as "recorded red and untouched", whose cause was a missing library rather than
# a broken cell. The cells now use the lane's own `beam_assert.raises` shim
# (Q128's convention), the eight are collected as bare cells, and the duplicate
# stdlib runner `run_pathguard_tests.py` (added as a workaround, invoked by
# nothing, module path absolute) is gone.
#
# leg 1 `wizard-work/beam/CHECK` is green: no failures, no errors, no import
# faults, and a floor of 645 collected cells so a lost file reds
# leg 2 the pathguard module is collected: `test_pathguard.py` 0 unittest,
# exactly 8 bare cells (the count is the defect's own denominator)
# leg 3 no file in the lane imports pytest at module level, so the gate does
# not depend on a package this interpreter does not have
# leg 4 the eight cells are LIVE: a copy of the lane with pathguard's two
# containment checks disabled reads rc 1, naming both escape cells
# leg 5 the duplicate runner is gone from the tree and from disk
# leg 6 the sweep baseline records the repaired row as 0
#
# rc 0 all legs pass, rc 1 a leg faulted, rc 2 could not grade.
set -u
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" || { echo "CANNOT GRADE: no directory"; exit 2; }
ROOT="$(git -C "$HERE" rev-parse --show-toplevel 2>/dev/null)" || { echo "CANNOT GRADE: not a git repository"; exit 2; }
LANE="$ROOT/wizard-work/beam"
RUNNER="$LANE/run_lane_tests.py"
BASE="$ROOT/wizard-work/volt/q143-check-sweep/check_entry_baseline.tsv"
for f in "$LANE/CHECK" "$RUNNER" "$LANE/test_pathguard.py" "$LANE/pathguard.py" "$BASE"; do
[ -f "$f" ] || { echo "CANNOT GRADE: missing $f"; exit 2; }
done
PY="${PYTHON:-python3}"
WORK="$(mktemp -d "${TMPDIR:-/tmp}/q149.XXXXXX")" || exit 2
trap 'rm -rf "$WORK"' EXIT
faults=0
pass() { echo "PASS $1"; }
fail() { echo "FAIL $1"; faults=$((faults+1)); }
# leg 1 -- the lane gate itself
if out="$(bash "$LANE/CHECK" 2>&1)"; then
summary="$(printf '%s\n' "$out" | grep '^lane: .*test(s)' | tail -1)"
total="$(printf '%s' "$summary" | sed -n 's/.*, \([0-9]\{1,\}\) test(s),.*/\1/p')"
if printf '%s' "$summary" | grep -q ' 0 failure(s), 0 error(s), 0 import fault(s)'; then
if [ -n "$total" ] && [ "$total" -ge 645 ]; then
pass "beam-gate rc=0 cells=$total $(printf '%s' "$summary" | sed 's/^lane: //')"
else
fail "beam-gate cell floor: total='${total}' < 645"
fi
else
fail "beam-gate green rc but faults in summary: $summary"
fi
else
fail "beam-gate red (rc=$?)"
printf '%s\n' "$out" | grep -E '^(IMPORT-FAIL|FAIL|SCRIPT-FAIL)' | head -4
fi
# leg 2 -- the repaired module is collected, and the eight are its count
if out="$("$PY" "$RUNNER" --lane "$LANE" --list 2>&1)"; then
row="$(printf '%s\n' "$out" | grep '^test_pathguard.py ')"
if printf '%s' "$row" | grep -q 'unittest=0 *bare=8 *$'; then
pass "pathguard-collected $row"
else
fail "pathguard not collected as 8 bare cells: ${row:-no row}"
fi
else
fail "runner --list rc=$?"
fi
# leg 3 -- no module-level pytest import anywhere in the lane. Column 0 only:
# `test_interval_tree.py:82` imports pytest inside `if __name__ == "__main__"`,
# which never runs under an import and is not the defect class (measured -- a
# grep that ignored indentation named it, and the runner's 0 import faults
# beside it is the reading that settled which one is right).
third="$(grep -nE '^(import pytest|from pytest)' "$LANE"/*.py 2>/dev/null)"
if [ -z "$third" ]; then
pass "no third-party import at module level ($(ls "$LANE"/*.py | wc -l) file(s) scanned)"
else
fail "third-party import at module level: $(printf '%s' "$third" | head -2 | tr '\n' ' ')"
fi
# leg 4 -- the cells are live: disable pathguard's containment checks in a copy
cp -a "$LANE" "$WORK/lane" 2>/dev/null && [ -f "$WORK/lane/pathguard.py" ] \
|| { echo "CANNOT GRADE: cannot copy $LANE"; exit 2; }
"$PY" - "$WORK/lane/pathguard.py" <<'PY'
import sys
p = sys.argv[1]
s = open(p, encoding="utf-8").read()
a = " if not _is_under(resolved, base_path):"
b = " if not _is_under(Path(norm), base_path):"
if a not in s or b not in s:
print("CANNOT MUTATE")
raise SystemExit(2)
s = s.replace(a, " if False and not _is_under(resolved, base_path):")
s = s.replace(b, " if False and not _is_under(Path(norm), base_path):")
open(p, "w", encoding="utf-8").write(s)
PY
mrc=$?
if [ "$mrc" -ne 0 ]; then
echo "CANNOT GRADE: mutant not applied ($mrc)"; exit 2
fi
out="$("$PY" "$WORK/lane/run_lane_tests.py" --lane "$WORK/lane" 2>&1)"; rc=$?
if [ "$rc" -eq 1 ] \
&& printf '%s\n' "$out" | grep -q '^FAIL: test_pathguard.test_dotdot_escape_rejected' \
&& printf '%s\n' "$out" | grep -q '^FAIL: test_pathguard.test_symlink_escape_rejected'; then
pass "mutant red: $(printf '%s\n' "$out" | grep -c '^FAIL: test_pathguard') pathguard cell(s) named"
else
fail "mutant not graded red by the two escape cells (rc=$rc)"
printf '%s\n' "$out" | grep -E '^(FAIL|ERROR)' | head -4
fi
# leg 5 -- the duplicate workaround runner is gone
in_git="$(git -C "$ROOT" ls-files -- wizard-work/beam/run_pathguard_tests.py)"
if [ -z "$in_git" ] && [ ! -e "$ROOT/wizard-work/beam/run_pathguard_tests.py" ]; then
pass "duplicate runner absent from index and disk"
else
fail "duplicate runner still present: ${in_git:-on disk but untracked}"
fi
# leg 6 -- the sweep's row for the repaired gate reads 0
row="$(grep -P '^wizard-work/beam/CHECK\t' "$BASE" | head -1)"
code="$(printf '%s' "$row" | cut -f2)"
if [ "$code" = "0" ]; then
pass "baseline row reads 0: $(printf '%s' "$row" | cut -f3)"
else
fail "baseline row for wizard-work/beam/CHECK reads '${code:-absent}'"
fi
echo "q149: $((6-faults)) of 6 leg(s) passed"
[ "$faults" -eq 0 ] || exit 1
exit 0
-78
View File
@@ -1,78 +0,0 @@
import os, tempfile, sys
sys.path.insert(0, "/root/troupe-standup/wizard-work/beam")
from pathguard import safe_join, PathTraversalError
tests = []
def T(name):
def dec(f):
tests.append((name, f)); return f
return dec
@T("basic")
def _():
with tempfile.TemporaryDirectory() as d:
out = safe_join(d, "a", "b.txt")
assert out == os.path.join(os.path.realpath(d), "a", "b.txt")
@T("dotdot")
def _():
with tempfile.TemporaryDirectory() as d:
try: safe_join(d, "..", "etc", "passwd")
except PathTraversalError: return
raise AssertionError("not raised")
@T("abs")
def _():
with tempfile.TemporaryDirectory() as d:
try: safe_join(d, "/etc/passwd")
except PathTraversalError: return
raise AssertionError("not raised")
@T("symlink")
def _():
with tempfile.TemporaryDirectory() as d:
base = os.path.join(d, "base"); os.makedirs(base)
target = os.path.join(d, "secret.txt")
open(target,"w").write("secret")
link = os.path.join(base, "link")
os.symlink(target, link)
try: safe_join(base, "link")
except PathTraversalError: return
raise AssertionError("symlink escape not rejected")
@T("nested")
def _():
with tempfile.TemporaryDirectory() as d:
sub = os.path.join(d, "sub"); os.makedirs(sub)
out = safe_join(d, "sub", "file.txt")
assert out.startswith(os.path.realpath(d) + os.sep)
@T("empty")
def _():
with tempfile.TemporaryDirectory() as d:
out = safe_join(d, "", None, "x")
assert out.endswith("x")
@T("nul")
def _():
with tempfile.TemporaryDirectory() as d:
try: safe_join(d, "a\x00b")
except PathTraversalError: return
raise AssertionError("nul not rejected")
@T("basedir")
def _():
with tempfile.TemporaryDirectory() as d:
f = os.path.join(d, "f"); open(f,"w").close()
try: safe_join(f, "x")
except PathTraversalError: return
raise AssertionError("base not dir not rejected")
fails = 0
for name, f in tests:
try:
f(); print("PASS", name)
except Exception as e:
fails += 1; print("FAIL", name, repr(e))
print("TOTAL", len(tests), "FAILS", fails)
raise SystemExit(1 if fails else 0)
+12
View File
@@ -0,0 +1,12 @@
# Standup — 2026-11-01
## Yesterday
- Wrote `verify_standup_draft.py`
- Ran selftest, all cells green
## Today
- Ship the verifier to troupe repo
- Review pending PRs
## Blockers
- None
+61
View File
@@ -0,0 +1,61 @@
#!/usr/bin/env python3
"""Verify a standup draft contains required sections with at least one bullet each.
Required sections (case-insensitive headings):
Yesterday, Today, Blockers
Exit codes:
0 all required sections present and non-empty
1 one or more sections missing or empty
2 bad invocation or unreadable file
"""
import re
import sys
REQUIRED = ["yesterday", "today", "blockers"]
def verify(path: str):
try:
with open(path, "r", encoding="utf-8") as f:
text = f.read()
except OSError as exc:
return 2, [f"cannot read file: {exc}"]
lower = text.lower()
faults = []
for section in REQUIRED:
# Match heading line exactly, allowing optional ATX markers (##, ###, etc.)
if not re.search(rf"^#{{0,6}}\s*{re.escape(section)}\s*$", lower, re.MULTILINE):
faults.append(f"missing section: {section}")
continue
# Extract up to 400 chars after the heading
idx = lower.find(section)
chunk = lower[idx: idx + 400]
if not re.search(r"^\s*[-*]\s+.+", chunk, re.MULTILINE):
faults.append(f"section {section} has no bullets")
return (1 if faults else 0), faults
def main() -> int:
if len(sys.argv) < 2:
print("usage: verify_standup_draft.py <file>", file=sys.stderr)
return 2
rc, faults = verify(sys.argv[1])
if rc == 0:
print("VERDICT: PASS")
elif rc == 1:
print("VERDICT: FAIL")
for f in faults:
print(f" - {f}")
else:
print("VERDICT: UNGRADABLE")
for f in faults:
print(f" - {f}")
return rc
if __name__ == "__main__":
raise SystemExit(main())