#!/usr/bin/env bash # spec-guard.sh — PreToolUse hook לאכיפת "פרוטוקול כתיבת-קוד" (CLAUDE.md). # # תפקיד: כשעורכים/כותבים קובץ-קוד (web/, mcp-server/, web-ui/src/, scripts/, adapters/), # מזריק תזכורת ל-Claude לקרוא את docs/spec/ ולוודא קיום ה-invariants G1–G11 — לפני שכותבים. # זוהי המקבילה האינטראקטיבית ל-INV-AG1 (שכבר אוכף על סוכני Paperclip ב-HEARTBEAT.md §"קריאת-ספ"). # # מנגנון: PreToolUse hook. קלט JSON ב-stdin (.tool_input.file_path), פלט JSON ל-stdout # (hookSpecificOutput.additionalContext) — non-blocking, רק מזכיר. תמיד exit 0. # Dedup: מזכיר פעם אחת בלבד לכל session (בכניסה הראשונה לכתיבת-קוד) כדי לא להציף. # # רישום: legal-ai/.claude/settings.json → hooks.PreToolUse (matcher "Edit|Write|MultiEdit"). # תיעוד: scripts/SCRIPTS.md. set -uo pipefail # בלי jq אין מה לעשות — אל תחסום, צא נקי command -v jq >/dev/null 2>&1 || exit 0 input="$(cat)" file_path="$(printf '%s' "$input" | jq -r '.tool_input.file_path // empty' 2>/dev/null || true)" # בלי file_path (למשל Bash) — לא רלוונטי [ -z "$file_path" ] && exit 0 # החרגות: תיעוד, markdown/טקסט/קונפיג-נתונים, בדיקות, artifacts — אלה לא "קוד הנדסי" case "$file_path" in *.md|*.markdown|*.txt|*.csv|*.lock) exit 0 ;; */docs/*|*/tests/*|*/test/*|*/__pycache__/*|*/.venv/*|*/node_modules/*|*/.git/*|*/.next/*) exit 0 ;; esac # כלילה: רק נתיבי-קוד אמיתיים case "$file_path" in */web/*|*/mcp-server/*|*/web-ui/src/*|*/scripts/*|*/adapters/*) : ;; *) exit 0 ;; esac # Dedup לכל session — מזכיר פעם אחת בלבד session_id="$(printf '%s' "$input" | jq -r '.session_id // "nosession"' 2>/dev/null || echo nosession)" marker="${TMPDIR:-/tmp}/.spec-guard-${session_id}" [ -f "$marker" ] && exit 0 : > "$marker" 2>/dev/null || true ctx="פרוטוקול כתיבת-קוד (CLAUDE.md §פרוטוקול כתיבת-קוד) — נוגעים בקובץ-קוד: ${file_path} לפני השינוי ודא: • קראת את docs/spec/00-constitution.md (ייעוד, G1–G11, אינדקס §7) + ספ-התחום הרלוונטי. • השינוי מקיים את ה-invariants: אין מסלול מקביל ליכולת קיימת (G2), נרמול-במקור ולא תיקון-בקריאה (G1), אין בליעה שקטה של שגיאות (§6). • בדקת מול docs/spec/gap-audit.md אם נוגעים ב-GAP/FU שכבר ממופה — להתאים, לא לפתור מחדש. • ה-PR יצהיר אילו invariants (G*/INV-*) נגעת בהם / מקיים (ראה .gitea/PULL_REQUEST_TEMPLATE.md). (תזכורת זו מופיעה פעם אחת בסשן.)" jq -n --arg ctx "$ctx" '{hookSpecificOutput:{hookEventName:"PreToolUse",additionalContext:$ctx}}' exit 0