Files
ersatztv/scripts/issue-qualification-audit.sh
T
timothyandClaude Opus 4.8 f1b2521228
Build ErsatzTV Image / Docs update reminder (pull_request) Successful in 7s
Build ErsatzTV Image / decisions.md append-only (pull_request) Successful in 7s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 8s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 6s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 4m31s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 7m9s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
chore(process): #312 H12 — session-end issue-qualification audit
scripts/issue-qualification-audit.sh: lists OPEN issues missing a `priority:` label
(the #237 ranking keys off priority:/gate labels, so an unlabeled issue is invisible
to it). "Fully qualified" = has a priority: label; gate-vs-backlog derives from the
review label / milestone, and a milestone is NOT required (backlog is unmilestoned).
Advisory (exit 1 if any unqualified); fail-open without Gitea creds. Wired into the
kickoff session-end protocol + a lore bullet. Tested live (flagged 2) + no-creds no-op.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-12 20:21:20 +02:00

61 lines
2.7 KiB
Bash
Executable File

#!/usr/bin/env bash
# H12 (ersatztv#312) — session-end audit: list OPEN issues that are not "fully qualified" for the
# #237 ranking protocol. An issue is qualified when it carries a `priority:` label — that is the
# signal triage happened; gate-vs-backlog is then derivable (a `review` label / open milestone =
# gate, otherwise backlog), and a milestone is deliberately NOT required (backlog is unmilestoned).
# So the one mandatory check is: does the issue have a `priority: {high,medium,low}` label?
#
# Run it at session end (kickoff session-end protocol) and qualify anything it lists before closing.
# Advisory: prints the under-qualified set and exits 1 if any exist, 0 if all clean. Fail-OPEN with
# no creds / Gitea unreachable (prints a notice, exits 0 — never a spurious signal).
#
# Creds from env: ETV_GITEA_TOKEN or ETV_GITEA_BASICAUTH (user:pass). ETV_GITEA_URL overrides the
# base (default: the LAN instance); ETV_GITEA_REPO overrides owner/repo (default timothy/ersatztv).
set -uo pipefail
base_url="${ETV_GITEA_URL:-http://192.168.1.95:3000}/api/v1"
repo="${ETV_GITEA_REPO:-timothy/ersatztv}"
gq() {
local path="$1"
if [ -n "${ETV_GITEA_TOKEN:-}" ]; then
curl -sf -H "Authorization: token $ETV_GITEA_TOKEN" "$base_url/$path" 2>/dev/null
elif [ -n "${ETV_GITEA_BASICAUTH:-}" ]; then
curl -sf -u "$ETV_GITEA_BASICAUTH" "$base_url/$path" 2>/dev/null
else
return 1
fi
}
if [ -z "${ETV_GITEA_TOKEN:-}" ] && [ -z "${ETV_GITEA_BASICAUTH:-}" ]; then
echo "H12 audit: no Gitea creds in env (ETV_GITEA_TOKEN or ETV_GITEA_BASICAUTH) — skipping (no-op)."
exit 0
fi
# Page through OPEN issues (type=issues excludes PRs; .pull_request guard is belt-and-suspenders).
# Emit "#N<TAB>title" for any issue with NO 'priority:' label.
missing=""
page=1
while :; do
batch=$(gq "repos/$repo/issues?state=open&type=issues&limit=50&page=$page") || {
echo "H12 audit: Gitea unreachable — skipping (no-op)."; exit 0; }
count=$(printf '%s' "$batch" | jq 'length' 2>/dev/null || echo 0)
[ "${count:-0}" -eq 0 ] && break
rows=$(printf '%s' "$batch" | jq -r '
.[]
| select(.pull_request == null)
| select(([ (.labels // [])[].name | select(startswith("priority:")) ] | length) == 0)
| "#\(.number)\t\(.title)"' 2>/dev/null || true)
[ -n "$rows" ] && missing="${missing}${rows}"$'\n'
page=$((page + 1))
done
if [ -z "$(printf '%s' "$missing" | tr -d '[:space:]')" ]; then
echo "H12 audit: every open issue carries a priority: label. ✓"
exit 0
fi
echo "H12 audit: OPEN issues missing a 'priority:' label — qualify these before session end"
echo "(the #237 ranking keys off priority:/gate labels; an unlabeled issue is invisible to it):"
printf '%s' "$missing" | sed '/^[[:space:]]*$/d' | sed 's/^/ /'
exit 1