Files
improvise/scripts/bd-audit-ids
T
Edward Langley 168a28d2c5 tooling: the dead-ID audit compares positively and is a checked script
improvise-52eq: the AGENTS.md recipe searched `bd show` output for "not
found" and printed "all resolve" when there was none, so a bd that was
missing, failing or never run passed the audit. scripts/bd-audit-ids
keeps the file scan and exclusions, then `comm -23`s the cited ids
against `bd list --all --limit 0 --json`. A dead id is exit 1 and is
named. A bd that does not answer is exit 3, never a pass.

scripts/bd-audit-ids-test.sh has eight cases on a throwaway repo with a
fake bd. The old recipe as a rival fails 7 of the 8. Disabling the
comparison fails the dead-id case, and an empty exclusion list fails the
pass case. CI runs it with the other named suites. The "One environment
note" now reports which forms the guard refused and allowed, as observed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze
2026-09-23 08:00:05 -07:00

76 lines
2.7 KiB
Bash
Executable File

#!/usr/bin/env bash
# The dead-ID audit: every improvise-<id> the tree cites must be a ticket bd
# knows. See AGENTS.md, "Cite a ticket ID you have read back" (improvise-52eq).
set -euo pipefail
usage() {
cat >&2 <<'EOF'
usage: bd-audit-ids
Run from anywhere inside the repository. Takes no arguments.
exit 0 every cited id is a ticket bd lists
exit 1 at least one cited id is not; each is printed
exit 3 bd could not answer: missing, failing, or listing nothing
exit 4 usage error, or the file scan itself failed
The comparison is POSITIVE: a cited id passes only by appearing in what
`bd list --all` returns. The recipe this replaced looked for bd's "not found"
lines and reported "all resolve" when there were none, so a bd that never ran
read as a clean audit.
THIS SCRIPT'S `$?` MUST BE THE ONE YOU READ. Nothing may follow it in the same
pipeline or `;` list.
EOF
exit 4
}
[ $# -eq 0 ] || usage
BD="${BD_AUDIT_BD:-bd}"
ROOTS=(context README.md AGENTS.md CLAUDE.md crates src tests examples web
harness docs .agents .claude)
# Crate, package, artifact and file names that are shaped like ids. Anchored,
# because an unanchored `gp` would silently exclude any real ticket id starting with it.
EXCLUDE='^improvise-(core|formula|io|protocol|command|gp|ws|worker|wasm|harness|registry|report|side|web)$'
work=$(mktemp -d)
trap 'rm -rf "$work"' EXIT
cd "$(git rev-parse --show-toplevel)"
git ls-files -z --cached --others --exclude-standard -- "${ROOTS[@]}" > "$work/files"
# xargs exits 123 when one grep batch matched nothing, which is not an error.
set +e
xargs -0 grep -d skip -ohE 'improvise-[a-z0-9]{3,8}\b' < "$work/files" > "$work/raw"
rc=$?
set -e
[ "$rc" -eq 0 ] || [ "$rc" -eq 123 ] || { echo "bd-audit-ids: grep failed ($rc)" >&2; exit 4; }
sort -u "$work/raw" | { grep -vE "$EXCLUDE" || true; } > "$work/cited"
if ! command -v "$BD" >/dev/null 2>&1; then
echo "bd-audit-ids: '$BD' is not on PATH, so nothing was checked." >&2
exit 3
fi
if ! "$BD" list --all --limit 0 --json > "$work/known.json" 2> "$work/bd.err"; then
echo "bd-audit-ids: '$BD list' failed, so nothing was checked:" >&2
cat "$work/bd.err" >&2
exit 3
fi
if ! jq -r '.[].id' "$work/known.json" 2>/dev/null | sort -u > "$work/known"; then
echo "bd-audit-ids: '$BD list' did not print a JSON list of issues." >&2
exit 3
fi
if [ ! -s "$work/known" ]; then
echo "bd-audit-ids: '$BD list' returned no issues; refusing to call that a pass." >&2
exit 3
fi
comm -23 "$work/cited" "$work/known" > "$work/dead"
if [ -s "$work/dead" ]; then
echo "bd-audit-ids: cited but not a ticket bd knows:"
sed 's/^/ /' "$work/dead"
exit 1
fi
printf 'bd-audit-ids: all %d cited ids resolve (bd knows %d)\n' \
"$(wc -l < "$work/cited" | tr -d ' ')" "$(wc -l < "$work/known" | tr -d ' ')"