# מפת הקורפוס — גרף ציטוטים אינטראקטיבי (`/graph`) תצוגת‑רשת אינטראקטיבית של קורפוס הפסיקה, בסגנון Obsidian Graph View, **מוטמעת נייטיב ב‑web‑ui**. כל פריט הוא נקודה, קישורים הם קווים, וגודל הנקודה משקף חשיבות — כך שאפשר להתמקד בנושא ולראות מה קשור אליו. ## למה נייטיב ולא Obsidian (G2) הרעיון המקורי היה לייצא את הקורפוס ל‑Obsidian vault. **נדחה** — vault הוא **עותק מקביל של הקורפוס שמתיישן**, בדיוק כשל‑השורש ש‑[G2](spec/00-constitution.md) (מקור‑אמת יחיד, ללא מסלול מקביל) בא לייבש. הגרף הנייטיב קורא את ה‑DB החי → **אפס drift**, ומתחבר לדפים הקיימים (`/precedents`, `/missing-precedents`, `/digests`). **התובנה המאפשרת:** כל קשתות הגרף כבר היו קיימות בטבלאות — הגרף רק חושף אותן. הוא **projection קריא‑בלבד** (SELECT בלבד), ולכן אינו יכול לסטות מהמקור. הוא **אינו מסלול אחזור** ([03-retrieval](spec/03-retrieval.md)) — מחזיר טופולוגיה (nodes+edges+מטריקות), לא תוצאות חיפוש מדורגות. ## שכבות (כולן opt‑in דרך toggles, מלבד הבסיס) | שכבה | נקודות | קשתות | מקור הדאטה | |------|--------|-------|------------| | **בסיס** | פסיקה (`cl:`) · נושא (`tag:`) · תחום (`pa:`) | `cites` · `same_chain` · `tagged` · `in_area` | `case_law`, `precedent_internal_citations`, `case_law_relations`, `subject_tags` | | **הלכות** | הלכה (`hal:`) | `extracted_from` · `corroborates` · `equivalent` | `halachot`, `halacha_citation_corroboration`, `equivalent_halachot` | | **חוסרי מחקר** | gap (`gap:`) — חלול/מקווקו | `cites` (פסיקה→gap) | `precedent_internal_citations` (cited_case_law_id IS NULL) + העשרה מ‑`missing_precedents` | | **יומונים** | יומון (`dig:`) — טורקיז | `covers` (יומון→פסיקה/gap) | `digests` | **גודל נקודה** = חשיבות: ציטוטים נכנסים (פסיקה), אזכורים (הלכה), מספר מצטטים (gap). **צבע** (color‑by, ברירת‑מחדל "סוג"): סוג · תחום · דרגת‑סמכות · **אשכול** (community) · עדכניות. ## אנליטיקה (Graph Analysis) `metrics=true` מפעיל חישוב **in‑memory** (ללא DB) ב‑[`web/graph_metrics.py`](../web/graph_metrics.py) — pure, ללא תלויות (אין networkx): - **PageRank** (power‑iteration) — השפעה גלובלית. - **Betweenness** (Brandes) — "גשריות" (פסיקות שמחברות אשכולות). - **Community** (label‑propagation דטרמיניסטי + fallback ל‑connected‑components) — אשכולות תמטיים. מחושב על **תת‑גרף הפסיקות בלבד** (cites/same_chain) — קשתות hub/gap/digest/halacha מוחרגות. ב‑UI: בוררי "צביעה לפי" / "גודל לפי" + פאנל דירוג ("המשפיעות" / "גשרים"). ## ניווט וחוויה - **Deep‑link** `/graph?focus=cl:` — לינק שיתופי; כפתור **"הצג בגרף"** בכל דף פסיקה. - **Local graph** — לחיצה על נקודה → התמקדות בשכניה (BFS, סליידר עומק 1–3). - **ייצוא PNG** · פאנל עשיר (headnote/summary) · מקרא נקודות+קשתות · סינון מטא‑דאטה (בית‑משפט/דרגה/יו״ר/מחוז/שנים). ## API קריאה‑בלבד, `response_model` מפורש (UI2). מוגדר ב‑[`web/app.py`](../web/app.py) (~`/api/graph/*`), לוגיקה ב‑[`web/graph_api.py`](../web/graph_api.py): | endpoint | תיאור | |----------|-------| | `GET /api/graph/corpus` | הגרף המלא. params: `node_types` (csv), `metrics`, `practice_area`/`source`/`court`/`precedent_level`/`chair`/`district`/`year_from`/`year_to`, `min_citations`, `q`, `limit` (cap 400, max 1500) | | `GET /api/graph/node/{id}/neighborhood` | Local graph: צומת + שכנים בעומק 1–3 | | `GET /api/graph/facets` | ערכי סינון ייחודיים (courts/levels/chairs/districts) | ## קבצים - **Backend:** [`web/graph_api.py`](../web/graph_api.py) (הרכבת nodes/edges, helpers `_edges_and_hubs`/`_gap_nodes_and_edges`/`_digest_nodes_and_edges`/`_halacha_nodes_and_edges`) · [`web/graph_metrics.py`](../web/graph_metrics.py) (מטריקות) · endpoints ב‑[`web/app.py`](../web/app.py). - **Frontend:** [`web-ui/src/app/graph/page.tsx`](../web-ui/src/app/graph/page.tsx) · [`web-ui/src/components/graph/`](../web-ui/src/components/graph/) (`graph-view` orchestrator · `graph-canvas` ציור react‑force‑graph‑2d · `graph-filter-panel` · `graph-node-panel`) · hooks ב‑[`web-ui/src/lib/api/graph.ts`](../web-ui/src/lib/api/graph.ts). ## איך מוסיפים שכבה חדשה 1. הוסף ערך ל‑`VALID_NODE_TYPES` ב‑`graph_api.py` (לא ל‑`DEFAULT_NODE_TYPES` אם רוצים שיהיה כבוי). 2. כתוב `_X_nodes_and_edges(conn, prec_ids)` — SELECT בלבד; חבר nodes לפסיקות שבתצוגה. 3. חבר בשתי פונקציות הבנייה (`build_corpus_graph` + `build_node_neighborhood`) מאחורי `if "X" in types`. 4. **dangling‑edge invariant:** כל קשת — שני קצותיה חייבים להיות nodes בתצוגה (סנן מול `prec_ids`/קבוצת ה‑ids). 5. Frontend: toggle ב‑`graph-filter-panel` · צבע/רינדור ב‑`graph-canvas` (`NODE_COLORS`/`colorForNode`/`linkColor`) · ענף בפאנל ב‑`graph-node-panel`. 6. אם גדל מודל התגובה — אחרי deploy: `cd web-ui && npm run api:types`. ## Invariants - **G2** — projection קריא‑בלבד דרך `db.get_pool()`; אפס כתיבות; מטריקות in‑memory. ללא store מקביל. - **G5** — כל פילטר server‑side, parameterized. - **UI2** — `response_model` מפורש בכל endpoint; **UI4** — שגיאות UI מוצגות, לא נבלעות. - **טופולוגיה ≠ אחזור** — מבנה הקורפוס, לא תוצאות חיפוש. ## היסטוריית מימוש PR #113 (בסיס) · #118 (תיקון תוויות) · #126 (מטא‑דאטה) · #129 (אנליטיקה) · #131 (gaps) · #132 (יומונים) · #134 (ניווט) · #137 (הלכות) · #139 (api:types).