Files
legal-ai/scripts/spec-guard.sh
Chaim d2b622f28e
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 5s
feat(ci): G12 leak-guard — enforce the Agent Platform Port seam (R4, #113)
המאכף האוטומטי של INV-G12 (docs/spec/X15 §4). שני כללים קשיחים:
1. mcp-server/src (שכבת-האינטליגנציה) ללא סמלי-Paperclip — allowlist מנומק לפי
   substring ל-6 ההפניות הלגיטימיות (pm2-bridge + הערות-מקור company_id).
2. import seam — רק web/agent_platform_port.py (+ קבצי-המעטפת) מייבאים paperclip_*.

מימוש קנוני אחד (scripts/leak_guard.py, stdlib-בלבד), משותף לשלושה אכיפנים (G2):
• CI hard gate: .gitea/workflows/leak-guard.yaml (pull_request + push→main)
• pytest: mcp-server/tests/test_platform_port_leak_guard.py (כולל self-test שמוודא
  שה-guard תופס הזרקה — לא ירקב)
• hook בזמן-אמת: spec-guard.sh בודק את התוכן-הנכתב (new_string/content) על כתיבה
  ל-mcp-server/src ומזהיר על הזרקת-Paperclip (לא-deduped); תזכורת-הספ עודכנה ל-G1–G12.

מחריג קבצים-נוצרים (web-ui types.ts) ומעטפת מוצהרת; הפרונט מחוץ להיקף-האינטליגנציה
(ממצא R3). עודכן scripts/SCRIPTS.md.

אימות: סריקה נקייה exit 0; הזרקת pc.sh ל-mcp-server → exit 1; seam-violation ב-web → exit 1;
hook מזהיר על mcp-server ומזכיר-ספ על web; pytest 3 passed; bash -n + YAML תקינים.

Invariants: G12 (אכיפה), G2 (מאכף יחיד לשלושה צרכנים).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 09:40:42 +00:00

74 lines
4.5 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# spec-guard.sh — PreToolUse hook לאכיפת "פרוטוקול כתיבת-קוד" (CLAUDE.md).
#
# תפקיד: כשעורכים/כותבים קובץ-קוד (web/, mcp-server/, web-ui/src/, scripts/, adapters/),
# מזריק תזכורת ל-Claude לקרוא את docs/spec/ ולוודא קיום ה-invariants G1G11 — לפני שכותבים.
# זוהי המקבילה האינטראקטיבית ל-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
# ── G12 leak-guard (INV-G12 / docs/spec/X15) — warn at write-time ──────────────
# PreToolUse fires BEFORE the edit, so we inspect the CONTENT being written
# (new_string / content), not the file on disk — this catches a Paperclip symbol
# being introduced into the intelligence layer right now. NOT session-deduped:
# every such write should warn. The hard gate is the CI fitness-test
# (mcp-server/tests/test_platform_port_leak_guard.py via scripts/leak_guard.py).
leak_warn=""
case "$file_path" in
*/mcp-server/src/*)
new_content="$(printf '%s' "$input" | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null || true)"
if printf '%s' "$new_content" | grep -qE 'paperclip|Paperclip|PAPERCLIP|wakeup|heartbeat|HEARTBEAT|pc_request|pc\.sh|X-Paperclip|agent_wakeup|heartbeat_run|ctx\.agents|issueId'; then
leak_warn="⚠️ G12 (שער-הפלטפורמה) — התוכן שאתה כותב ל-${file_path} (שכבת-האינטליגנציה) מכיל מונח ספציפי-Paperclip. אסור (INV-G12): נתב מגע-פלטפורמה דרך web/agent_platform_port.py. אם זו הערת-מקור בלבד — הוסף רשומה מנומקת ל-allowlist ב-scripts/leak_guard.py, אחרת ה-CI (test_platform_port_leak_guard) ייכשל. ראה docs/spec/X15-agent-platform-port.md.
"
fi
;;
esac
# Dedup לכל session — תזכורת-הספ מופיעה פעם אחת בלבד (אזהרת-leak אינה deduped)
session_id="$(printf '%s' "$input" | jq -r '.session_id // "nosession"' 2>/dev/null || echo nosession)"
marker="${TMPDIR:-/tmp}/.spec-guard-${session_id}"
spec_ctx=""
if [ ! -f "$marker" ]; then
: > "$marker" 2>/dev/null || true
spec_ctx="פרוטוקול כתיבת-קוד (CLAUDE.md §פרוטוקול כתיבת-קוד) — נוגעים בקובץ-קוד: ${file_path}
לפני השינוי ודא:
• קראת את docs/spec/00-constitution.md (ייעוד, G1G12, אינדקס §7) + ספ-התחום הרלוונטי.
• השינוי מקיים את ה-invariants: אין מסלול מקביל ליכולת קיימת (G2), נרמול-במקור ולא תיקון-בקריאה (G1), שער-הפלטפורמה (G12 — Paperclip רק דרך agent_platform_port.py), אין בליעה שקטה של שגיאות (§6).
• בדקת מול docs/spec/gap-audit.md אם נוגעים ב-GAP/FU שכבר ממופה — להתאים, לא לפתור מחדש.
• ה-PR יצהיר אילו invariants (G*/INV-*) נגעת בהם / מקיים (ראה .gitea/PULL_REQUEST_TEMPLATE.md).
(תזכורת זו מופיעה פעם אחת בסשן.)"
fi
ctx="${leak_warn}${spec_ctx}"
[ -z "$ctx" ] && exit 0
jq -n --arg ctx "$ctx" '{hookSpecificOutput:{hookEventName:"PreToolUse",additionalContext:$ctx}}'
exit 0