/ scripts / pre-commit-graph-health
pre-commit-graph-health
  1  #!/bin/bash
  2  #
  3  # Pre-commit hook: Graph Health Check
  4  #
  5  # Implements Dellanna's principle: Tight feedback loops
  6  # Catch orphans and broken links at commit time, not later.
  7  #
  8  # Install:
  9  #   ln -sf ../../scripts/pre-commit-graph-health .git/hooks/pre-commit
 10  #
 11  # Or:
 12  #   cp scripts/pre-commit-graph-health .git/hooks/pre-commit
 13  #
 14  
 15  set -e
 16  
 17  REPO_ROOT="$(git rev-parse --show-toplevel)"
 18  cd "$REPO_ROOT"
 19  
 20  echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
 21  echo "GRAPH HEALTH CHECK (pre-commit)"
 22  echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
 23  echo
 24  
 25  # Check if any markdown files are being committed
 26  STAGED_MD=$(git diff --cached --name-only --diff-filter=ACM | grep '\.md$' || true)
 27  
 28  if [ -z "$STAGED_MD" ]; then
 29      echo "No markdown files staged. Skipping graph health check."
 30      exit 0
 31  fi
 32  
 33  echo "Staged markdown files:"
 34  echo "$STAGED_MD" | while read f; do echo "  - $f"; done
 35  echo
 36  
 37  # Run orphan detector in quick mode
 38  # Only check staged files for orphan status
 39  ORPHANS_FOUND=0
 40  MISSING_STRUCTURE=0
 41  
 42  for file in $STAGED_MD; do
 43      if [ ! -f "$file" ]; then
 44          continue
 45      fi
 46  
 47      # Check for principle/shape headers
 48      if ! grep -q '^\- \*\*principle\*\*' "$file" 2>/dev/null; then
 49          if [[ "$file" == docs/* || "$file" == patterns/* || "$file" == sessions/backfill/* ]]; then
 50              echo "⚠  Missing principle header: $file"
 51              MISSING_STRUCTURE=1
 52          fi
 53      fi
 54  
 55      if ! grep -q '^\- \*\*shape\*\*' "$file" 2>/dev/null; then
 56          if [[ "$file" == docs/* || "$file" == patterns/* || "$file" == sessions/backfill/* ]]; then
 57              echo "⚠  Missing shape header: $file"
 58              MISSING_STRUCTURE=1
 59          fi
 60      fi
 61  
 62      # Check for Related section
 63      if ! grep -q '^## Related' "$file" 2>/dev/null; then
 64          if [[ "$file" == docs/* || "$file" == patterns/* || "$file" == sessions/backfill/* ]]; then
 65              echo "⚠  Missing Related section: $file"
 66              MISSING_STRUCTURE=1
 67          fi
 68      fi
 69  
 70      # Check for at least one wiki-link
 71      if ! grep -q '\[\[' "$file" 2>/dev/null; then
 72          echo "⚠  No wiki-links found (potential orphan): $file"
 73          ORPHANS_FOUND=1
 74      fi
 75  done
 76  
 77  echo
 78  
 79  if [ $MISSING_STRUCTURE -eq 1 ] || [ $ORPHANS_FOUND -eq 1 ]; then
 80      echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
 81      echo "GRAPH HEALTH WARNINGS"
 82      echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
 83      echo
 84      echo "Pages are at risk of becoming orphans (A4: prevent ruin)"
 85      echo
 86      echo "Quick fix:"
 87      echo "  python3 scripts/resonance_engine.py <file> --dry-run"
 88      echo "  python3 scripts/resonance_engine.py <file>  # to apply"
 89      echo
 90      echo "Commit anyway? Use: git commit --no-verify"
 91      echo
 92  
 93      # Warning only - don't block the commit
 94      # Change exit 1 if you want to block
 95      exit 0
 96  fi
 97  
 98  echo "✓ Graph health check passed"
 99  echo
100  exit 0