#!/usr/bin/env bash # # Fail when an agent-instruction or architecture document references a # repository file path that no longer exists. Keeps CLAUDE.md / AGENTS.md / # ARCHITECTURE.md / docs/architecture honest after refactors move code. # # Checked files: all tracked AGENTS.md, CLAUDE.md, ARCHITECTURE.md, and # docs/architecture/*.md. # # A reference is any token starting with crates/, rustfs/, scripts/, docs/, # .github/ or .config/ that ends in a known file extension. Tokens containing # globs or placeholders, extensionless tokens (HTTP routes, directory # references, org/repo shorthands), and lines containing URLs are skipped. set -euo pipefail ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" cd "$ROOT_DIR" FAILURES=0 doc_files() { git ls-files 'AGENTS.md' '*/AGENTS.md' 'CLAUDE.md' 'ARCHITECTURE.md' 'docs/architecture/*.md' } check_file() { local doc="$1" # Path-like tokens; strip surrounding backticks/brackets/punctuation later. # Lines with URLs are skipped wholesale: path fragments inside links are # external, not repo paths. # grep exits 1 on no matches; that must not kill the script under pipefail. { grep -vE 'https?://' "$doc" || true; } \ | { grep -oE '(crates|rustfs|scripts|docs|\.github|\.config)/[A-Za-z0-9_./-]+' || true; } \ | sed -e 's/[.,;:)]*$//' -e 's:/$::' \ | sort -u \ | while IFS= read -r ref; do case "$ref" in (*'*'*|*'<'*|*'>'*|*'{'*|*'}'*|*'…'*) continue ;; esac # Only verify references with a known file extension. Extensionless # tokens are too often HTTP routes (rustfs/admin/v3/...), org/repo # shorthands (rustfs/backlog), or glob prefixes — not repo paths. case "$ref" in (*.rs|*.md|*.sh|*.toml|*.yml|*.yaml|*.mak|*.proto) ;; (*) continue ;; esac if [[ ! -e "$ref" ]]; then printf 'stale path reference: %s -> %s\n' "$doc" "$ref" >&2 echo "FAIL" >> "$FAIL_MARKER" fi done } FAIL_MARKER="$(mktemp)" trap 'rm -f "$FAIL_MARKER"' EXIT while IFS= read -r doc; do [[ -f "$doc" ]] && check_file "$doc" done < <(doc_files) if [[ -s "$FAIL_MARKER" ]]; then count="$(wc -l < "$FAIL_MARKER" | tr -d ' ')" printf '\n%s stale doc path reference(s) found.\n' "$count" >&2 printf 'Fix the doc to match the current tree, or update the moved code path.\n' >&2 exit 1 fi printf 'doc path check passed\n'