Files
legal-ai/docs/superpowers/specs/2026-05-31-fu8a-process-to-code-guards-design.md
Chaim e8431a2adf docs(spec): FU-8a process→code guards design (GAP-21/22) + split GAP-23 to #69
GAP-21: sync_agents --verify exits non-zero on drift; adapter_type mismatch
counted as drift (loud), not silent skip — makes it an enforceable gate (INV-MC1).
GAP-22: fitness-function pytest guarding against raw Paperclip HTTP + direct
agent_wakeup_requests INSERT (INV-INT1/INT3). Repo pre-scanned: 0 existing
violations → clean forward-fence. Verified vs 3+ sources (architectural fitness
functions; drift-verify non-zero exit). GAP-23 (spec→agents) split to #69.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 10:48:15 +00:00

6.8 KiB
Raw Blame History

FU-8a — מחסומי-תהליך → מחסומי-קוד (Process Barriers → Code Guards) — עיצוב

סטטוס: מאושר-לעיצוב · תאריך: 2026-05-31 · ענף: TBD מכסה: GAP-21, GAP-22 · מספק: INV-MC1, INV-INT1, INV-INT3 · משימה: TaskMaster #66 תלוי ב: — · סוג: pure-code · מחוץ-להיקף: GAP-23 (חיווט ספ→סוכנים) → #69 / FU-8b.


1. הבעיה

שני מחסומים שהיום נשענים על נוהל אנושי ולא על קוד, ולכן ניתנים להפרה שקטה:

  • GAP-21 (INV-MC1): סנכרון-סוכנים חוצה-חברות (sync_agents_across_companies.py) ידני ולא-נאכף. ב---verify (script:397) הוא יוצא 0 גם כשיש drift, ו-adapter_type-mismatch (script:388) מודפס כ-"SKIPPING" ונבלע — אין סיגנל-כשל שניתן לתלות בו gate.
  • GAP-22 (INV-INT1/INT3): אין מחסום-קוד נגד עקיפת ה-helpers המאושרים של Paperclip — קריאת httpx/requests גולמית ל-API של Paperclip (במקום web/paperclip_api.pc_request) או INSERT ישיר ל-agent_wakeup_requests (במקום ה-wakeup API). היום זה כלל-נוהל ב-CLAUDE.md/HEARTBEAT בלבד.

2. ההכרעה (מאומתת ≥3 מקורות)

Architectural fitness functions — הופכים החלטת-ארכיטקטורה מ"הסכמה חברתית" לכלל נאכף שנתפס ברגע ההפרה, כ-assertion דמוי-טסט ב-CI. שני המחסומים מיושמים ככאלה:

החלטה נימוק מקורות
GAP-21: --verify יוצא non-zero על drift; adapter_type-mismatch = drift (לא silent skip) + דיווח רם drift-verify הוא gate רק אם הוא יוצא non-zero (Terraform 0/2); "alert, don't skip silently" InfoQ fitness-functions; Firefly CI-drift; Spacelift drift
GAP-22: fitness-function (pytest שסורק את ה-repo), לא import-linter הכלל הוא דפוס-שימוש/מחרוזת (http ל-URL, מחרוזת-SQL), לא גבול-import; fitness-function כ-test-assertion ב-CI הוא הכלי InfoQ; Lukas Niessen; aipatternbook
לרוץ ב-חבילת-הטסטים הקיימת (לא CI חדש) אין CI-lint בפרויקט (רק deploy.yaml); חבילת ה-pytest היא שער-האיכות הקיים (נגזר מהמצב)

3. הרכיבים

  • Modify scripts/sync_agents_across_companies.py (GAP-21):
    • --verify יחזיר exit 1 כש-plan לא-ריק או כשיש adapter_type-mismatch (כיום return שקט).
    • adapter_type-mismatch: נספר ל-mismatches ומדווח רם (), לא רק "SKIPPING"; נכלל בסיגנל-הכשל של --verify. (ה-skip עצמו ב---apply נשמר — לא מסנכרנים adapter_type אוטומטית — אבל --verify נכשל כדי לאלץ טיפול ידני.)
  • Create mcp-server/tests/test_paperclip_access_guard.py (GAP-22) — fitness-function שסורק את עץ-המקור (web/, mcp-server/src/, scripts/, plugin-legal-ai/ אם רלוונטי) ונכשל אם נמצא:
    1. קריאת-HTTP גולמית ל-Paperclip — httpx/requests/aiohttp עם PAPERCLIP_API_URL או localhost:3100/pc.nautilusמחוץ ל-web/paperclip_api.py (ה-helper המאושר).
    2. INSERT INTO agent_wakeup_requests (כל קובץ) — חייב לעבור דרך wakeup API.
    3. curl ... $PAPERCLIP_API_URL ב-shell — מחוץ ל-scripts/pc.sh.
    • מימוש: סריקת-טקסט ממוקדת (regex) עם allowlist מפורש (הקבצים המאושרים) + הודעת-כשל שמסבירה את ה-helper הנכון. (AST מלא מיותר — הדפוסים הם מחרוזות-URL/SQL, לא מבנה-קוד.)
  • Create scripts/check_paperclip_access.py (GAP-22, אופציונלי-דק) — wrapper הניתן להרצה ידנית/CI שמריץ את אותה לוגיקת-סריקה (מייבא מהטסט או חולק helper); exit non-zero על הפרה. (אם הטסט מספיק — לדלג, YAGNI.)

4. שינויי-התנהגות וסיכון

שינוי השפעה סיכון
--verify יוצא 1 על drift הופך ל-gate שמיש (אפשר לתלות בו cron/CI) נמוך — לא משנה --apply; משנה רק exit-code של verify
adapter_type-mismatch רם + נכלל ב-fail drift של adapter לא נבלע נמוך — דיווח; ה-skip ב-apply נשמר
fitness-function guard הפרה עתידית תיכשל בטסטים נמוך — ה-repo נסרק 2026-05-31: 0 הפרות קיימות (אין httpx גולמי ל-Paperclip, אין INSERT ל-agent_wakeup_requests, אין curl גולמי). הגדר הוא גדר-קדימה נקי, אפס תיקוני-קוד קיימים
allowlist קבצים מאושרים (paperclip_api.py, pc.sh) פטורים נמוך — מפורש ומתועד

5. אסטרטגיית בדיקה

  • GAP-22 fitness-function נבדק על עצמו: הטסט מאתר דפוס-הפרה מוזרק (fixture עם httpx ל-Paperclip) ומאשר שהוא נתפס; ומאשר שה-helpers המאושרים (paperclip_api.py) לא מסומנים. כלומר הטסט בודק את הסורק על דוגמאות חיוביות+שליליות, ואז מריץ אותו על ה-repo האמיתי (חייב לעבור — אחרת יש הפרה קיימת לתקן).
  • GAP-21 — בדיקת-יחידה ללוגיקת ה-exit/mismatch: מתוך master/mirror סינתטיים, --verify עם drift מחזיר 1; ללא drift מחזיר 0; adapter_type-mismatch → 1 + הודעה. (refactor של לוגיקת-ההכרעה לפונקציה טהורה _verify_exit_code(plan, mismatches) שניתנת לבדיקה offline בלי DB/Paperclip.)
  • חבילה מלאה ירוקה; smoke: sync...py --verify מול ה-state הנוכחי (לדווח אם drift קיים).

6. סדר-ביצוע

  1. בדיקות אדומות: _verify_exit_code (GAP-21) + סורק ה-guard על fixtures (GAP-22).
  2. GAP-21: refactor --verify ל-_verify_exit_code + ספירת mismatches + exit 1 + דיווח רם.
  3. GAP-22: סורק (tests/test_paperclip_access_guard.py) + allowlist; הרצה על ה-repo וטיפול בהפרות קיימות (תיקון או allowlist מנומק).
  4. (אופציונלי) scripts/check_paperclip_access.py אם רוצים הרצה עצמאית.
  5. חבילה ירוקה + smoke (--verify) + SCRIPTS.md (אם נוסף סקריפט) + PR+merge + TaskMaster #66.

GAP-23 (#69) — חיווט הספ ל-HEARTBEAT/סוכנים — מחוץ-להיקף (משנה התנהגות-ייצור, דורש החלטה).