All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 1m27s
Adds a third corpus of legal authority distinct from style_corpus (Daphna's prior decisions for voice) and case_precedents (chair-attached quotes per case). The new corpus holds chair-uploaded court rulings and other appeals committee decisions, with binding rules (הלכות) extracted automatically and queued for chair approval. Pipeline (web/app.py + services/precedent_library.py): file → extract → chunk → Voyage embed → halacha_extractor → store + publish progress over the existing Redis SSE channel. Schema V7 (services/db.py): extends case_law with source_kind + extraction status fields under a CHECK constraint pinning practice_area to the three appeals committee domains (rishuy_uvniya, betterment_levy, compensation_197). New precedent_chunks (vector(1024)) and halachot tables (vector(1024) over rule_statement, IVFFlat indexes, gin on practice_areas/subject_tags). Halachot start as pending_review; only approved/published rows are visible to search_precedent_library. Agents: legal-writer, legal-researcher, legal-analyst, legal-ceo, legal-qa get search_precedent_library. legal-writer prompt explains the three-corpus distinction and CREAC use; legal-qa now verifies that every cited halacha resolves to an approved row in the corpus. UI: /precedents page with four tabs — library / semantic search / pending review (J/K nav, A/R/E shortcuts, badge count) / stats. Reuses the existing upload-sheet progress + SSE pattern. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
97 lines
3.7 KiB
TypeScript
97 lines
3.7 KiB
TypeScript
"use client";
|
||
|
||
import Link from "next/link";
|
||
import { AppShell } from "@/components/app-shell";
|
||
import { Card, CardContent } from "@/components/ui/card";
|
||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||
import { Badge } from "@/components/ui/badge";
|
||
import { LibraryListPanel } from "@/components/precedents/library-list-panel";
|
||
import { LibrarySearchPanel } from "@/components/precedents/library-search-panel";
|
||
import { HalachaReviewPanel } from "@/components/precedents/halacha-review-panel";
|
||
import { LibraryStatsPanel } from "@/components/precedents/library-stats-panel";
|
||
import { useHalachotPending } from "@/lib/api/precedent-library";
|
||
|
||
/**
|
||
* Precedent Library admin page.
|
||
*
|
||
* Four tabs:
|
||
* - ספרייה — browse all uploaded precedents (filters + upload + delete)
|
||
* - חיפוש סמנטי — semantic search across halachot + chunks
|
||
* - ממתין לאישור — chair review queue (PRIMARY tab; halachot from
|
||
* auto-extraction must be approved before agents can use them)
|
||
* - סטטיסטיקה — counts and coverage
|
||
*
|
||
* Distinct from /training (style corpus = Daphna's voice) and the
|
||
* per-case precedent attacher (chair-attached quotes scoped to a case).
|
||
*/
|
||
|
||
function PendingBadge() {
|
||
const { data } = useHalachotPending();
|
||
const n = data?.count ?? 0;
|
||
if (!n) return null;
|
||
return (
|
||
<Badge
|
||
variant="outline"
|
||
className="ms-1 bg-gold-wash text-gold-deep border-gold/40 text-[0.65rem]"
|
||
>
|
||
{n}
|
||
</Badge>
|
||
);
|
||
}
|
||
|
||
export default function PrecedentsPage() {
|
||
return (
|
||
<AppShell>
|
||
<section className="space-y-6">
|
||
<header>
|
||
<nav className="text-[0.78rem] text-ink-muted mb-1">
|
||
<Link href="/" className="hover:text-gold-deep">בית</Link>
|
||
<span aria-hidden> · </span>
|
||
<span className="text-navy">ספריית פסיקה</span>
|
||
</nav>
|
||
<h1 className="text-navy mb-0">ספריית הפסיקה הסמכותית</h1>
|
||
<p className="text-ink-muted text-sm mt-1 max-w-3xl">
|
||
פסיקה חיצונית — פסקי דין של ערכאות עליונות והחלטות של ועדות ערר אחרות.
|
||
כל קובץ עובר חילוץ הלכות אוטומטי, וההלכות ממתינות לאישור היו"ר לפני
|
||
שהן זמינות לסוכני הכתיבה (legal-writer וכו').
|
||
</p>
|
||
</header>
|
||
|
||
<div className="h-[2px] bg-gradient-to-l from-transparent via-gold to-transparent" />
|
||
|
||
<Card className="bg-surface border-rule shadow-sm">
|
||
<CardContent className="px-6 py-5">
|
||
<Tabs defaultValue="library" dir="rtl">
|
||
<TabsList className="bg-rule-soft/60">
|
||
<TabsTrigger value="library">ספרייה</TabsTrigger>
|
||
<TabsTrigger value="search">חיפוש סמנטי</TabsTrigger>
|
||
<TabsTrigger value="review">
|
||
ממתין לאישור
|
||
<PendingBadge />
|
||
</TabsTrigger>
|
||
<TabsTrigger value="stats">סטטיסטיקה</TabsTrigger>
|
||
</TabsList>
|
||
|
||
<TabsContent value="library" className="mt-5">
|
||
<LibraryListPanel />
|
||
</TabsContent>
|
||
|
||
<TabsContent value="search" className="mt-5">
|
||
<LibrarySearchPanel />
|
||
</TabsContent>
|
||
|
||
<TabsContent value="review" className="mt-5">
|
||
<HalachaReviewPanel />
|
||
</TabsContent>
|
||
|
||
<TabsContent value="stats" className="mt-5">
|
||
<LibraryStatsPanel />
|
||
</TabsContent>
|
||
</Tabs>
|
||
</CardContent>
|
||
</Card>
|
||
</section>
|
||
</AppShell>
|
||
);
|
||
}
|