feat(graph): research-gap (ghost) nodes (corpus graph PR C)
Turns the graph into a gap-finder: the 247 unresolved internal citations (a corpus precedent cites a ruling NOT in the corpus) collapse to 230 distinct "gap" nodes — each sized by how many corpus precedents cite it, i.e. the most-wanted missing precedent. Backend (web/graph_api.py — read-only, G2): - "gap" added to VALID_NODE_TYPES (NOT default → off unless requested). - New _gap_nodes_and_edges(): gap:<normalized citation> nodes from precedent_internal_citations WHERE cited_case_law_id IS NULL, sized by global in-degree; cites edges only from precedents present in the view (dangling-edge invariant holds). Best-effort enrichment from missing_precedents via exact normalized-citation match → gap_status + missing_precedent_id. Validated: 230 gaps, top ע"א 3213/97 (cited 5×), 230/230 matched to missing_precedents. - GraphNode += gap_status, missing_precedent_id. Metrics correctly exclude gap edges (target not a precedent). No app.py change (gated via node_types). Frontend: - graph.ts: GraphNodeType += "gap"; node fields. - graph-filter-panel: toggle "חוסרי מחקר (פסיקה חסרה)" (off by default). - graph-canvas: gaps render as faint hollow dashed circles, never recoloured by color-by; sized by citation count. - graph-node-panel: gap branch — "מצוטטת ע״י N פסיקות" + status badge + link to /missing-precedents. web-ui build + lint pass. Invariants: G2 (SELECT-only), UI2 (model grows on explicit Pydantic). api:types post-deploy. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -14,7 +14,12 @@
|
||||
import { keepPreviousData, useQuery } from "@tanstack/react-query";
|
||||
import { apiRequest } from "./client";
|
||||
|
||||
export type GraphNodeType = "precedent" | "halacha" | "topic" | "practice_area";
|
||||
export type GraphNodeType =
|
||||
| "precedent"
|
||||
| "halacha"
|
||||
| "topic"
|
||||
| "practice_area"
|
||||
| "gap";
|
||||
|
||||
export type GraphEdgeType =
|
||||
| "cites"
|
||||
@@ -38,6 +43,8 @@ export type GraphNode = {
|
||||
pagerank: number | null; // normalized 0–1, only when metrics requested
|
||||
betweenness: number | null; // normalized 0–1
|
||||
community: number | null; // dense cluster id, 0 = largest
|
||||
gap_status: string | null; // gap nodes only — open|uploaded|closed|irrelevant
|
||||
missing_precedent_id: string | null; // gap nodes only
|
||||
};
|
||||
|
||||
export type GraphFacets = {
|
||||
|
||||
Reference in New Issue
Block a user