INV-TOOL4 (visibility / persistence). תור בקשות-החילוץ (metadata/halacha) נשמר
ב-case_law.{metadata,halacha}_extraction_requested_at ומרוקן ע"י
precedent_process_pending — אבל לא היה כלי לראות את עומק-התור.
נוסף:
- db.extraction_queue_status() — count + גיל הבקשה הוותיקה לכל kind (read-only).
- plib.extraction_status() — tool wrapper (envelope _ok/_err).
- רישום extraction_status ב-server.py ליד precedent_process_pending.
- precedent_process_pending קיבל _clamp_limit (עקביות עם GAP-53).
תוספתי, read-only, אפס שבירה. עודכנו X9 (INV-TOOL4 ✅) ו-gap-audit (GAP-45 ✅).
py_compile עבר על 3 קבצי הקוד.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
23 KiB
Gap-Audit — פערים בין המערכת הקיימת ל-spec
מסמך זה הוא מפת-הפערים הקנונית בין המערכת הקיימת (קוד ב-web/, mcp-server/,
scripts/) לבין ה-invariants שב-docs/spec/. הוא תוצר של תת-פרויקט 2
(מיפוי-פערים), ומובחן מ-docs/audit-report.md הישן: ה-audit הוא
דוח-מצב נקודתי, וזה ה-gap-map שמקשר כל ממצא ל-invariant מופר וליחידת-תיקון.
איך הופק: סקירה חוצת-קבצים של כל קבצי-הספ (00 + 01–07 + X1–X5) מול הקוד הקיים,
30.5.2026. כל ממצא נושא: invariant מופר (ה-G*/INV-* שהוא סותר), הערכת-severity,
קבצים מושפעים (file:line), ו-תיקון מוצע.
הערה על severity/priority: דירוג ה-severity להלן הוא הערכה הנדסית (לפי סיכון לשלמות-נתונים, דליפה חוצת-קורפוס, ועקיפת שער אנושי). קביעת ה-priority בפועל — מה לתקן ראשון — היא של היו"ר. ה-severity מנמק; הוא אינו מכריע.
23 הממצאים
סטטוס מחזור-1 (עודכן 31.5.2026): כל 23 הממצאים ✅ נסגרו — FU-1..FU-8b מוזגו ל-main (PRs #11–#23: FU-1/2a, FU-2b #15, FU-2c #17, FU-3, FU-4, FU-5 #18, FU-6, FU-7 #13, FU-8a #16, FU-8b #23). 122 בדיקות עוברות. הטבלה נשמרת כתיעוד-מקור; פירוט-ה-FU והסטטוס בסעיף "יחידות-תיקון".
| ID | כותרת | invariant מופר | severity | קבצים מושפעים (file:line) | תיקון מוצע |
|---|---|---|---|---|---|
| GAP-01 | שני מסלולי ingest מקבילים שמתפצלים | INV-ING1, G2 | High | precedent_library.py:88, internal_decisions.py:73 |
מסלול-קליטה קנוני יחיד; ישויות-אחיות חולקות פייפליין |
| GAP-02 | ingest פנימי מדלג על חילוץ metadata | INV-ING3, DM1, RET2 | Critical | internal_decisions.py:208 |
להוסיף request_metadata_extraction לכל סוג; חוסם indexing ריק |
| GAP-03 | אין upsert דטרמיניסטי על מזהה קנוני | INV-ING2, G3 | Critical | precedent_library.py, internal_decisions.py |
upsert על מפתח קנוני — קליטה חוזרת = update לא duplicate |
| GAP-04 | ולידציית-enum א-סימטרית | INV-G4 | Medium | precedent_library.py:131-134 |
להחיל אותה ולידציית practice_area/source_type בשני המסלולים |
| GAP-05 | staging/derivation/citation-guard/multimodal/fallback א-סימטריים | INV-ING1, G2 | High | 01-ingest §4 (שני המסלולים) |
מיזוג כל שלבי-העיבוד למסלול הקנוני האחד |
| GAP-06 | case_number מנורמל בקריאה בלבד | INV-G1, ID1 | High | db.py:1196-1211 |
נרמול בנקודת-הכתיבה; 8126-25→canonical |
| GAP-07 | מספרי-תיק מעורבים (חודש/חסר) — reconciliation חד-פעמי | INV-ID1 | High | data (cases, case_law) | מיגרציה: canonical = הצורה הרשמית שהוקצתה [chair-confirmed] |
| GAP-08 | ציטוט-מלא נשמר כ-case_number | INV-DM2, ID2 | Medium | data (legacy pre-V15) | ניקוי: ציטוט = שדה-תצוגה נגזר, לא מזהה |
| GAP-09 | embedding אינו GENERATED (בניגוד ל-tsvectors) |
INV-DM3, RET, G6 | High | schema (chunks/case_law) | re-index באכיפה — טריגר או GENERATED-equivalent בשינוי תוכן |
| GAP-10 | דליפת הלכה חוצת-קורפוס | INV-RET1, G5 | Critical | db.py:3168, db.py:3401, JOINs 3236-3238/3475-3477 |
להוסיף cl.source_kind ל-halacha_filters |
| GAP-11 | אין eval harness / gold-set מתויג | INV-RET4, G8 | High | telemetry.log_search_bg (היחיד) |
להקים eval harness + gold-set; precision/recall נמדד |
| GAP-12 | search_decisions מזהיר אך לא חוסם practice_area חסר | INV-RET, G5 | High | search.py:45-49, search.py:172-176 |
לחסום query בלי practice_area — ערבוב-תחום אסור |
| GAP-13 | אין דגל searchable מפורש |
INV-DM1 | Medium | schema (case_law, chunks) | דגל searchable שמסומן רק כשחוזה-השלמות מתקיים |
| GAP-14 | backlog הלכות סמוי | INV-QA1, G10 | Medium | (אין health-check) | לחשוף pending_review ב-health-check / dashboard |
| GAP-15 | שער-ייצוא נאכף-זרימה ולא נאכף-קוד | INV-QA3, EX3 | Critical | drafting.py:384 |
export_docx קורא validate_decision + בודק export_blocked |
| GAP-16 | neutral_background קריטי-אך-עובר | INV-QA3 (05 §1.2) |
High | qa_validator.py:70 |
בלוק-ו ריק/חסר = passed=False; חוסם ייצוא |
| GAP-17 | active_draft_path נגזר זוחל ל-source-of-truth | INV-EX1, AUD2 | High | db.py:189 |
DOCX = נגזר; re-sync בלוקים אחרי revise/apply_user_edit |
| GAP-18 | audit_log כמעט לא נכתב | INV-AUD1 | High | cases.py:203 (היחיד) |
כתיבת audit על upload/extract/write_block/export |
| GAP-19 | אין קישור block→source-chunks | INV-AUD1 | High | decision_blocks (model_used בלבד) |
לתעד אילו chunks/precedents הזינו כל בלוק |
| GAP-20 | citation→corpus לא נאכף אוטומטית | INV-AUD3 | Medium | decision_paragraphs.citations |
ולידציה שכל ציטוט בטקסט פתיר לקורפוס |
| GAP-21 | cross-company sync ידני ולא-נאכף | INV-MC1 | Medium | sync_agents_across_companies.py:387-389 |
אכיפת --apply אחרי שינוי-Master; להרעיש על דילוג adapter_type |
| GAP-22 | אינטגרציית-Paperclip על נוהל ולא מחסום-קוד | INV-INT1, INT3 | Medium | schema / lint (אין) | אילוץ-schema נגד DB-insert; linter נגד httpx/curl גולמי |
| GAP-23 | הספ עדיין לא מחובר לסוכנים | INV-AG1 | High | .claude/agents/HEARTBEAT.md, agent files |
חובת קריאת 00-constitution + ספ-תחום לפני פעולה |
ממצאי מחזור-2 (8 משטחי-האפליקציה מחוץ לצינור-הליבה) — GAP-24..62
הופקו בסקירת-קוד word-for-word (30–31.5.2026) של 8 המשטחים: גבול-Paperclip, web-ui, מילוי-שדות, אחסון-ניתוחים, כלי-MCP (71), סוכנים+skills, deploy/env. ממצאי-ה-UI ברמת-הדף מפורטים ב-ui-audit.md. ה-invariants ב-X6–X10. כל מחזור-2 פתוח (אומת 31.5.2026: creds plaintext קיימים, 2 לקוחות קיימים, אין get_appraiser_facts, analyst חסר 3 כלים).
| ID | כותרת | invariant מופר | severity | קבצים מושפעים (file:line) | תיקון מוצע |
|---|---|---|---|---|---|
| GAP-24 | שני לקוחות Paperclip מקבילים (api מול client legacy) | INV-INT4, G2 | High | web/paperclip_api.py, web/paperclip_client.py |
לקוח-API קנוני יחיד |
| GAP-25 | גישת-DB ישירה ל-Paperclip (INSERT projects/issues/plugin_state) עוקפת API+audit | INV-INT4, G2, G9 | High | web/paperclip_client.py |
להעביר הכל ל-API; להסיר מסלול-DB |
| GAP-26 | company/agent IDs קשיחים — סותר X3 §1א | INV-INT5, G2 | High | web/paperclip_client.py:36-62, web/app.py:3976, plugin worker.ts |
מיפוי מ-config/env |
| GAP-27 | company_id נגזר בשתי דרכים (prefix מול fallback-map) |
INV-INT6, G2 | Medium | web/app.py (prefix), web/paperclip_client.py (_FALLBACK_APPEAL_TYPE_TO_COMPANY) |
פונקציית-גזירה יחידה |
| GAP-28 | webhooks fire-and-forget בולעים שגיאות, ללא idempotency | INV-INT7, G9, §6 | Medium | web/paperclip_api.py:87-205 |
event-id+dedup+רישום-כישלון |
| GAP-29 | חוזה-אירוע webhook לא-מתוקען (eventType חופשי, default שקט) | INV-INT8, G2 | Medium | web/paperclip_api.py:87+, plugin onWebhook |
enum-אירוע מגורס |
| GAP-30 | ~60% endpoints ללא Pydantic → unknown → טיפוסים ידניים סוטים |
INV-UI1/UI2, G2/G4 | High | web/app.py (רוב), web-ui/src/lib/api/cases.ts:1-9 |
response models + api:types |
| GAP-31 | PracticeArea/enum-סטטוס משוכפלים פרונט (3 מקומות, ערכים שונים) |
INV-UI1, G2 | High | web-ui/src/lib/practice-area.ts:12, lib/api/precedent-library.ts:26, components/precedents/practice-area.ts |
SSoT יחיד (ui-audit UI-A1/B1) |
| GAP-32 | אין envelope עקבי; שגיאות נבלעות ב-UI | INV-UI3/UI4, §6 | Medium | web/app.py (search ועוד), דפי-UI |
envelope אחיד + error-card |
| GAP-33 | fallback SSE מסתיר כישלון; cache-TTL לא-תואם (5ש'↔300ש') | INV-UI5 | Low | web-ui/src/lib/api/documents.ts:226-232 |
terminal-state מפורש |
| GAP-34 | URLs קשיחים ב-UI/בק | INV-UI3/ENV3 | Low | web-ui/.../app-shell.tsx:70, web/app.py:110 |
env |
| GAP-35 | מקור-מילוי-שדות לא-מוצהר — מפוזר על 4 שירותים | INV-FP1, G9 | High | precedent_metadata_extractor.py, halacha_extractor.py, ingest.py, db.py (recompute_searchable) |
טבלת-provenance SSoT (X8 §2) |
| GAP-36 | אין שקיפות-UI למה מולא ע"י Opus מול ידני | INV-UI6/FP1, G9 | Medium | web-ui/src/app/precedents/[id]/page.tsx:160-185 |
חיווי מקור-מילוי |
| GAP-37 | placeholder "(טרם חולץ)" כמחרוזת-קסם לא-מתועדת |
INV-FP2 | Low | internal_decisions.py, precedent_metadata_extractor.py |
constant מתועד |
| GAP-38 | שתי עמודות-סטטוס-חילוץ ב-case_law | INV-DM1, G2 | Medium | db.py:603-606 |
סטטוס יחיד / extraction-jobs |
| GAP-39 | legal_arguments ללא שער-אישור (בניגוד ל-halachot) |
INV-DM5, G10 | High | db.py:845-872 |
review_status ל-legal_arguments |
| GAP-40 | legal_arguments.cited_precedents TEXT[] ללא FK → הזיות-LLM נבלעות |
INV-DM6, G9, §6 | Medium | db.py:858, argument_aggregator.py |
FK + דיווח-כישלון-קישור |
| GAP-41 | appraiser_facts↔claims התנגשות; appraiser_side default '' מעורפל |
INV-DM6 | Medium | db.py:549-576 |
CHECK + הבחנה document↔case |
| GAP-42 | 20+ enums כ-TEXT חופשי; אין embedding-provenance | INV-DM6/DM4, G4 | Medium | db.py (source_type, rule_type, status…) |
CHECK-enums + עמודת-model |
| GAP-43 | case_precedents↔case_law טבלאות-פסיקה מקבילות legacy |
INV-G2 | Low | db.py |
איחוד/סימון-deprecated |
| GAP-44 | אסימטריית extract/get — אין get_appraiser_facts (חילוץ-חוזר יקר) |
INV-TOOL4, G2 | High | mcp-server/.../drafting.py, server.py:563 |
להוסיף get_appraiser_facts |
| GAP-45 | תור-חילוץ סמוי (pending-initial מול pending-review); אין extraction-job table | INV-TOOL4/FP5, G10 | Medium | precedent_library.py, ingest.py |
*_extraction_status tool + טבלת-jobs |
| GAP-46 | הרשאות-סוכן לא-מתועדות (analyst/researcher חסרי כלים) | INV-AG3/TOOL6 | High | .claude/agents/legal-analyst.md, legal-researcher.md |
יישור tools↔instructions |
| GAP-47 | draft_section ללא provenance (chunk→document/page); הנחיות-יו"ר ב-md ולא DB |
INV-TOOL4, G9 | Medium | mcp-server/.../drafting.py |
provenance בפלט + DB ל-directions |
| GAP-48 | envelope-תשובה לא-עקבי (71 כלים: string/JSON/{error}) | INV-TOOL1, G2 | Medium | mcp-server/.../server.py, tools/ |
wrapper {status,data,message} |
| GAP-49 | 6 כלי-חיפוש חופפים + precedent_search_library שם-מטעה |
INV-TOOL2, G2 | Medium | server.py (search_*), precedents.py:81 |
מיזוג + rename לפי-קורפוס |
| GAP-50 | 6 כלי-כתיבת-בלוק חופפים (draft_section/get_block_context/write_/save_) | INV-TOOL2, G2 | Medium | server.py:500-616 |
מיזוג context↔write |
| GAP-51 | set_outcome enum-mismatch (3≠4); אוצרות-מילים סותרות |
INV-TOOL1/UI1 | Medium | block_writer.py:442 מול lessons.py:11, workflow.py:145 |
SSoT יחיד ל-outcome |
| GAP-52 | רוב הכלים לא-idempotent (case_create/document_upload/precedent_attach) | INV-TOOL3, G3 | Medium | server.py, tools/ |
upsert/ON CONFLICT |
| GAP-53 | אין limit-caps (precedent_library_list/search_*/list_chair_feedback) | INV-TOOL5 | Low | tools/ | clamp ל-max |
| GAP-54 | 3 מסלולי-קליטת-פסיקה ולידציה א-סימטרית; citation-guard לא-מתועד | INV-ING1, G2 | Medium | precedent_library.py, internal_decisions.py |
איחוד (תואם GAP-01/05) |
| GAP-55 | Infisical dead-code; מקור-config לא-מתועד (Coolify-only) | INV-ENV2, G2 | Medium | mcp-server/.../config.py |
לתעד Coolify SSoT / לבודד Infisical |
| GAP-56 | UUIDs קשיחים (company/agent) — תואם GAP-26 | INV-ENV3/INT5 | High | web/paperclip_client.py:36-62, web/app.py:3976 |
config-driven |
| GAP-57 | creds plaintext בברירת-מחדל (paperclip:paperclip) |
INV-ENV4, G9, §6 | High | web/paperclip_client.py:21, web/app.py:3789,3964 |
default ריק + fail-loud |
| GAP-58 | GITEA_ACCESS_TOKEN↔GITEA_TOKEN שני שמות; קטלוג חלקי |
INV-ENV1 | Low | web/gitea_client.py:22, git_sync.py:30, tools/cases.py:28 |
שם קנוני יחיד + קטלוג |
| GAP-59 | chat-URL docs↔reality (10.0.1.1 מול host.docker.internal) |
INV-ENV3 | Medium | web/chat_proxy.py:49, chat_service/server.py |
יישור env + תיעוד |
| GAP-60 | 13/40+ env vars ב-drift-catalog; 8+ סודות בלתי-מנוטרים | INV-ENV5/ENV1 | Medium | web/mcp_env_catalog.py |
קטלוג מקיף |
| GAP-61 | URLs + /home/chaim קשיחים |
INV-ENV3 | Low | web/paperclip_client.py:31, app.py |
env/config |
| GAP-62 | start.sh לא-נכשל-על-uvicorn; deploy-curl fire-and-forget | INV-ENV2/§6 | Low | start.sh, .gitea/workflows/deploy.yaml |
health-gate + אימות-deploy |
יחידות-תיקון מוצעות (Proposed Fix-Units)
23 הממצאים מקובצים ל-8 יחידות-עבודה קוהרנטיות. הקיבוץ נגזר מהעיקרון שרבים מהממצאים נפתרים יחד (כל פערי ה-ingest-asymmetry → יחידה אחת). זהו זרע למשימות TaskMaster ולתת-פרויקט 3 (שכבת-שלמות).
✅ מחזור-1 הושלם (31.5.2026): FU-1..FU-8b כולם מוזגו ל-main. מחזור-2 (FU-9..15, להלן) נגזר מ-GAP-24..62 ופתוח.
FU-1 — איחוד מסלול-הקליטה (Unify ingest path)
- מכסה: GAP-01, GAP-02, GAP-04, GAP-05
- מספק invariants: INV-ING1, INV-ING3, INV-G2, INV-G4; (תורם ל-DM1/RET2 דרך GAP-02)
- effort: L
- תלויות: — (יסוד — FU-2/FU-3 נשענים עליה)
- סוג: pure-code
FU-2 — קליטה idempotent + מזהים קנוניים
- מכסה: GAP-03, GAP-06, GAP-07, GAP-08, GAP-13
- מספק invariants: INV-ING2, INV-G3, INV-G1, INV-ID1, INV-ID2, INV-DM2, INV-DM1
- effort: L
- תלויות: FU-1 (מסלול אחד לפני upsert אחיד)
- סוג: data-migration — GAP-07 reconciliation של case_number מעורב (chair-confirmed), GAP-08 ניקוי ציטוט-כ-מזהה; + code (upsert key, write-time normalize, דגל searchable)
FU-3 — re-index באכיפה בשינוי-תוכן
- מכסה: GAP-09
- מספק invariants: INV-DM3, INV-G6, INV-RET (freshness)
- effort: M
- תלויות: FU-1 (re-embed יושב בקליטה הקנונית)
- סוג: data-migration — re-chunk/re-embed של רשומות קיימות + טריגר/אכיפה קדימה
FU-4 — הפרדת-קורפוס נאכפת בכל query
- מכסה: GAP-10, GAP-12
- מספק invariants: INV-RET1, INV-G5
- effort: M
- תלויות: — (עצמאי; דחוף — Critical leak)
- סוג: pure-code
FU-5 — eval harness + נראות-בריאות
- מכסה: GAP-11, GAP-14
- מספק invariants: INV-RET4, INV-G8, INV-QA1, INV-G10 (נראות backlog)
- effort: M
- תלויות: FU-2 (gold-set יציב דורש מזהים קנוניים)
- סוג: pure-code + chair-decision — הגדרת gold-set מתויג דורשת אישור היו"ר (מה "תוצאה נכונה" לכל query)
FU-6 — שערי-QA נאכפים-קוד (Code-enforced gates)
- מכסה: GAP-15, GAP-16
- מספק invariants: INV-QA3, INV-EX3, INV-G10
- effort: S
- תלויות: — (עצמאי; חוסם עקיפת-ייצוא)
- סוג: pure-code
FU-7 — Audit-trail + provenance (זרע תת-פרויקט 3)
- מכסה: GAP-17, GAP-18, GAP-19, GAP-20
- מספק invariants: INV-AUD1, INV-AUD2, INV-AUD3, INV-EX1, INV-G9
- effort: L
- תלויות: FU-1 (provenance נלכד בקליטה/כתיבה הקנונית)
- סוג: pure-code (schema-additive) — חלק מ-GAP-17 דורש data-backfill קל לסנכרון בלוקים↔DOCX קיימים
FU-8 — מחסומי-תהליך הופכים למחסומי-קוד
- מכסה: GAP-21, GAP-22, GAP-23
- מספק invariants: INV-MC1, INV-INT1, INV-INT3, INV-AG1
- effort: M
- תלויות: ה-spec גמור (GAP-23 דורש קבצי-ספ יציבים לחבר לסוכנים)
- סוג: pure-code + chair-decision — GAP-23 (חיבור ספ לסוכני-Paperclip) הוא prerequisite לתת-פרויקט 5 ומשנה התנהגות-סוכן בייצור
- סטטוס: ✅ FU-8a (GAP-21/22, PR #16) + FU-8b (GAP-23, PR #23) מוזגו.
— מחזור-2 (FU-9..15): 8 משטחי-האפליקציה מחוץ לצינור-הליבה. כולם פתוחים. —
FU-9 — לקוח-Paperclip קנוני
- מכסה: GAP-24..29 · invariants: INV-INT4–INT8 · effort: L · תלויות: X7 יציב
- סוג: code — איחוד 2 הלקוחות, הסרת מסלול-DB, IDs מ-config, company_id יחיד, webhook idempotency+enum
FU-10 — חוזה UI↔API + design-system SSoT
- מכסה: GAP-30..34 + ui-audit (UI-A1..D6) · invariants: INV-UI1–UI6 · effort: L · תלויות: —
- סוג: code — Pydantic models+
api:types, SSoT ל-enums/תוויות/tones, helpers משותפים, ניקוי redundancy
FU-11 — מילוי-שדות מוצהר + שקיפות-UI
- מכסה: GAP-35..37 · invariants: INV-FP1–FP5, UI6 · effort: M · תלויות: —
- סוג: code — טבלת-provenance SSoT, formalize placeholder, חיווי "מולא-ע"י-Opus" + searchable + pending ב-UI
FU-12 — חיזוק אחסון-הניתוחים
- מכסה: GAP-38..43 · invariants: INV-DM4–DM6 · effort: M · תלויות: FU-1
- סוג: code + data-migration קל — provenance, שער-אישור ל-legal_arguments, CHECK-enums, FK, איחוד case_precedents
FU-13 — סוכנים + skills — ✅ נסגר (2026-06-06)
- מכסה: GAP-46 (מרחיב GAP-23) · invariants: INV-AG3, INV-TOOL6 · effort: S · תלויות: ה-spec יציב
- סוג: code/docs — שלמות-הרשאות (tools↔instructions), DRY-boilerplate, dedup-skills
- סטטוס: הכרעת-יו"ר "היבריד". התברר שהפער ב-31.5 היה רחב מדי (יוחס לפי תיאור-תפקיד, לא הוראות בפועל).
researcher כבר היה תקין (מיושן ב-spec). analyst קיבל
aggregate_claims_to_arguments+ שלב 7 ("שלב 1");extract_references/extract_internal_citationsנשארו אצל researcher (מטלת-מחקר, לא analyst). עודכן X4 §2א.
FU-14 — חוזה כלי-ה-MCP
- מכסה: GAP-44,45,47..54 · invariants: INV-TOOL1–TOOL5 · effort: L · תלויות: FU-1
- סוג: code — envelope אחיד, מיזוג חיפוש/בלוקים, idempotency, limit-caps, get-symmetry, set_outcome SSoT
- סטטוס חלקי (פרוסה 1, 2026-06-06): ✅ GAP-44 — נוסף
get_appraiser_facts(ה-get המקביל ל-extract, INV-TOOL4); ✅ GAP-53 — נוסף_clamp_limit(תקרה 200, INV-TOOL5) על ~13 כלי list/search + הוספת limit ל-list_chair_feedback(שהיה ללא תקרה). - סטטוס חלקי (פרוסה 2, 2026-06-06): ✅ GAP-52 (INV-TOOL3 idempotency) —
case_create/precedent_attach/document_uploadמחזירים קיים במקום כפילות (בדיקת-מפתח ברמת-אפליקציה; document_upload לפי SHA-256 → מדלג OCR/embed כפול); ✅ GAP-45 (INV-TOOL4 visibility) — נוסףextraction_statusשחושף עומק תור-החילוץ (metadata/halacha) + גיל הבקשה הוותיקה. נותר: GAP-51 (set_outcome enum SSoT — דורש הכרעת-domain), GAP-48 (envelope), GAP-49/50 (מיזוג+rename — שובר).
FU-15 — deploy/env/secrets
- מכסה: GAP-55..62 · invariants: INV-ENV1–ENV5 · effort: M · תלויות: —
- סוג: code/config + chair-decision (rotation סודות) — env-catalog SSoT, מקור-config יחיד, de-hardcode, drift מלא, start.sh עמיד
- סטטוס חלקי: GAP-57 (creds plaintext, אבטחה CWE-798) נסגר ב-web/ 2026-06-06 — 3 מופעים ב-
web/paperclip_api.py/paperclip_client.py/app.pyהומרו ל-require_paperclip_db_url()fail-loud. נותרו 2 מופעים בסקריפטים מקומיים (sync_agents_across_companies.py,sync_missing_agent_skills.py) + GAP-55,56,58–62 — לטיפול ב-FU-15 המלא.
סיכום סיווג לפי סוג-עבודה
- pure-code (ללא מיגרציה): FU-1, FU-4, FU-6; הליבה של FU-7, FU-8.
- דורש data-migration: FU-2 (case_number reconciliation, ניקוי ציטוטים), FU-3 (re-chunk/re-embed), backfill קל ב-FU-7 (סנכרון בלוקים↔DOCX).
- דורש chair-decision: FU-5 (הגדרת gold-set), FU-8/GAP-23 (חיבור ספ לסוכנים); GAP-07 כבר chair-confirmed (canonical = הצורה הרשמית שהוקצתה).
רצף מומלץ (תלויות): FU-1 → FU-2 → FU-3; FU-4 ו-FU-6 במקביל (עצמאיים, Critical); FU-7 אחרי FU-1; FU-5 אחרי FU-2; FU-8 אחרי ייצוב-הספ. (מחזור-1 ✅ הושלם.)
מחזור-2 (FU-9..15) — 8 משטחי-האפליקציה: FU-10 (UI+design-system) ו-FU-15 (deploy/env) עצמאיים — ניתן במקביל. FU-9 (לקוח-Paperclip) אחרי X7. FU-12 (אחסון) ו-FU-14 (כלי-MCP) אחרי FU-1. FU-11 (מילוי-שדות) עצמאי. FU-13 (סוכנים+skills) אחרי ייצוב-הספ. סיווג: pure-code — FU-9/10/11/13/14; +data-migration קל — FU-12; +chair-decision — FU-15 (rotation סודות). priority בפועל — של היו"ר.