הספ (docs/spec/, G1–G11) חובר לסוכני Paperclip דרך INV-AG1 אבל לא למסלול שבו רוב הקוד נכתב בפועל — הסשן האינטראקטיבי של Claude Code. סוגר את הפער לפני מחזור-2 (FU-9..15), שהוא כולו כתיבת-קוד. שלוש שכבות אכיפה: 1. תיעוד — CLAUDE.md §"פרוטוקול כתיבת-קוד" + docs/spec בטבלת-הייחוס 2. hook — scripts/spec-guard.sh (PreToolUse על Edit/Write/MultiEdit, רשום ב-.claude/settings.json) מזכיר פעם-בסשן בכל נגיעה בקובץ-קוד; non-blocking 3. PR — .gitea/PULL_REQUEST_TEMPLATE.md עם סעיף-חובה "Invariants" המקבילה האינטראקטיבית ל-INV-AG1 שכבר אוכף על הסוכנים (HEARTBEAT §"קריאת-ספ"). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
54 lines
2.9 KiB
Bash
Executable File
54 lines
2.9 KiB
Bash
Executable File
#!/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
|