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>
6.8 KiB
6.8 KiB
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/אם רלוונטי) ונכשל אם נמצא:- קריאת-HTTP גולמית ל-Paperclip —
httpx/requests/aiohttpעםPAPERCLIP_API_URLאוlocalhost:3100/pc.nautilus— מחוץ ל-web/paperclip_api.py(ה-helper המאושר). INSERT INTO agent_wakeup_requests(כל קובץ) — חייב לעבור דרך wakeup API.curl ... $PAPERCLIP_API_URLב-shell — מחוץ ל-scripts/pc.sh.
- מימוש: סריקת-טקסט ממוקדת (regex) עם allowlist מפורש (הקבצים המאושרים) + הודעת-כשל שמסבירה את ה-helper הנכון. (AST מלא מיותר — הדפוסים הם מחרוזות-URL/SQL, לא מבנה-קוד.)
- קריאת-HTTP גולמית ל-Paperclip —
- 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. סדר-ביצוע
- בדיקות אדומות:
_verify_exit_code(GAP-21) + סורק ה-guard על fixtures (GAP-22). - GAP-21: refactor
--verifyל-_verify_exit_code+ ספירת mismatches + exit 1 + דיווח רם. - GAP-22: סורק (
tests/test_paperclip_access_guard.py) + allowlist; הרצה על ה-repo וטיפול בהפרות קיימות (תיקון או allowlist מנומק). - (אופציונלי)
scripts/check_paperclip_access.pyאם רוצים הרצה עצמאית. - חבילה ירוקה + smoke (
--verify) + SCRIPTS.md (אם נוסף סקריפט) + PR+merge + TaskMaster #66.
GAP-23 (#69) — חיווט הספ ל-HEARTBEAT/סוכנים — מחוץ-להיקף (משנה התנהגות-ייצור, דורש החלטה).