#!/usr/bin/env bash # # Refuse tracked text that names a path under status/explorations/. # # status/explorations/ is a local lab notebook git ignores # (status/MAINTAINING.md, "Where things live"), so a tracked file naming a # path under it points at something another clone does not have. This check # reads what git would commit (the index plus untracked files the ignore rules # do not exclude, binaries skipped) for the notebook's directory shape, # explorations/-, and leaves out what MAINTAINING.md freezes # (archived changes, status/archive, status/log), design/ (synced from # upstream, never edited here) and the notebook itself. The - # template MAINTAINING.md and the skills use has no digits, so a description # of the convention is not a hit. # # It lives here and not in internal/lint because it is repository hygiene, # not part of the shipped program; `make lint` runs it after the program's # own lint. Exits 1 with one file:line per hit, 0 on a clean tree. # # Usage: ./scripts/notebook-citations.sh [repo-root] set -euo pipefail cd "${1:-$(dirname "$0")/..}" pattern='explorations/[a-z0-9]+(-[a-z0-9]+)*-20[0-9]{2}-[0-9]{2}' hits=$(git grep -n -I -E --untracked "$pattern" -- . \ ':!design' ':!openspec/changes/archive' ':!status/archive' \ ':!status/explorations' ':!status/log' ':!test/screens' || true) if [[ -z "$hits" ]]; then echo "notebook-citations: ok" >&2 exit 0 fi count=0 while IFS= read -r line; do file=${line%%:*} rest=${line#*:} lineno=${rest%%:*} text=${rest#*:} cite=$(grep -oE "$pattern" <<<"$text" | head -1) printf '%s:%s: [notebook-citation] cites the exploration notebook "%s", which a clone does not have; state the fact or cite its tracked home (status/MAINTAINING.md, "Where things live")\n' \ "$file" "$lineno" "$cite" >&2 count=$((count + 1)) done <<<"$hits" echo >&2 echo "notebook-citations: $count hit(s)" >&2 exit 1