#!/usr/bin/env bash # Pre-commit advisory: warn when newly-added essay files are missing a # monogram (mark.svg) or the epistemic status field. Warning only — # this hook never blocks a commit. The author is the one staging, and # the audit table at `make audit-marks` is the canonical view; this # hook just nudges at the moment of commit. # # Install (one-time): # # ln -s ../../tools/hooks/pre-commit-marks.sh .git/hooks/pre-commit # # Or chain into an existing pre-commit: # # bash tools/hooks/pre-commit-marks.sh # # Scope: newly-added (status `A`) .md files under content/essays/. # Modified files are not warned about — the author has presumably made # a deliberate choice about marks by then. set -u # Newly-added .md files under content/essays/ in this commit. mapfile -t added < <( git diff --cached --name-status --diff-filter=A -- 'content/essays/*.md' \ | awk '{ print $2 }' ) if [[ ${#added[@]} -eq 0 ]]; then exit 0 fi warnings=0 for path in "${added[@]}"; do # Resolve the dual-form mark.svg candidate path. Mirrors # build/Marks.hs and tools/audit-marks.py. if [[ "$(basename -- "$path")" == "index.md" ]]; then mark="$(dirname -- "$path")/mark.svg" else mark="${path%.md}.mark.svg" fi has_mark=0 has_status=0 [[ -f "$mark" ]] && has_mark=1 # Best-effort frontmatter probe: does any line in the YAML head # block start with `status:`? Avoids a YAML dependency in the # hook, which has to run before the build environment is sourced. if awk '/^---$/{f++; next} f==1 && /^status:[[:space:]]*[^[:space:]]/{print; exit}' \ -- "$path" \ | grep -q .; then has_status=1 fi if [[ $has_mark -eq 0 || $has_status -eq 0 ]]; then if [[ $warnings -eq 0 ]]; then echo "[marks] advisory: newly-added essays missing marks:" >&2 fi msgs=() [[ $has_mark -eq 0 ]] && msgs+=("no mark.svg at $mark") [[ $has_status -eq 0 ]] && msgs+=("no status: in frontmatter") printf ' %s — %s\n' "$path" "$(IFS=, ; echo "${msgs[*]}")" >&2 warnings=$((warnings + 1)) fi done if [[ $warnings -gt 0 ]]; then echo "[marks] (advisory only — commit not blocked. \`make audit-marks\` for the full report.)" >&2 fi exit 0