feat(precedents): metadata auto-fill, edit sheet, persuasive extraction
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 1m28s
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 1m28s
Three improvements to the precedent library based on usage feedback:
1. Auto-fill metadata at upload time. New service
precedent_metadata_extractor reads the ruling's full_text and
suggests case_name (short), summary, headnote, key_quote,
subject_tags, appeal_subtype. The merge policy fills only empty
fields, preserving everything the chair typed in the upload form.
Wired into the ingest pipeline; also exposed as a re-run endpoint
POST /api/precedent-library/{id}/extract-metadata for existing
records.
2. Edit sheet in the UI. Pencil icon on each library row opens a
pre-populated form covering every field. A Sparkles button on the
sheet runs the metadata extractor on demand and refreshes the
form. The case_number is read-only because halachot are FK'd to
it; renaming requires delete + re-upload.
3. Halacha extractor branches on is_binding. Sources marked binding
(Supreme/Administrative) keep the strict halacha prompt. Non-binding
sources (other appeals committees, district courts on planning
matters) get a different prompt that extracts applications,
interpretive principles, and persuasive conclusions — labeled with
new rule_types 'application' and 'persuasive'. The fallback also
widens chunk selection: if the chunker labeled nothing as
legal_analysis/ruling/conclusion, we now run on all chunks rather
than returning zero halachot for a usable ruling.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { Trash2, Plus, RefreshCw } from "lucide-react";
|
||||
import { Trash2, Plus, RefreshCw, Pencil } from "lucide-react";
|
||||
import { toast } from "sonner";
|
||||
import {
|
||||
Table, TableBody, TableCell, TableHead, TableHeader, TableRow,
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
} from "@/lib/api/precedent-library";
|
||||
import { PRACTICE_AREAS, PRECEDENT_LEVELS, practiceAreaShort } from "./practice-area";
|
||||
import { PrecedentUploadSheet } from "./precedent-upload-sheet";
|
||||
import { PrecedentEditSheet } from "./precedent-edit-sheet";
|
||||
|
||||
function formatDate(iso: string | null) {
|
||||
if (!iso) return "—";
|
||||
@@ -55,7 +56,12 @@ function StatusPill({ p }: { p: Precedent }) {
|
||||
);
|
||||
}
|
||||
|
||||
function PrecedentRow({ p }: { p: Precedent }) {
|
||||
function PrecedentRow({
|
||||
p, onEdit,
|
||||
}: {
|
||||
p: Precedent;
|
||||
onEdit: (id: string) => void;
|
||||
}) {
|
||||
const del = useDeletePrecedent();
|
||||
const reExtract = useReExtractHalachot();
|
||||
|
||||
@@ -105,6 +111,14 @@ function PrecedentRow({ p }: { p: Precedent }) {
|
||||
</TableCell>
|
||||
<TableCell className="text-end">
|
||||
<div className="flex items-center gap-1 justify-end">
|
||||
<Button
|
||||
variant="ghost" size="sm" onClick={() => onEdit(p.id)}
|
||||
aria-label={`ערוך את ${p.case_number}`}
|
||||
title="ערוך פרטים"
|
||||
className="text-ink-muted hover:text-navy"
|
||||
>
|
||||
<Pencil className="w-4 h-4" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost" size="sm" onClick={onReExtract}
|
||||
disabled={reExtract.isPending}
|
||||
@@ -133,6 +147,7 @@ export function LibraryListPanel() {
|
||||
const [precedentLevel, setPrecedentLevel] = useState("");
|
||||
const [search, setSearch] = useState("");
|
||||
const [uploadOpen, setUploadOpen] = useState(false);
|
||||
const [editingId, setEditingId] = useState<string | null>(null);
|
||||
|
||||
const { data, isPending, error } = usePrecedents({
|
||||
practiceArea: practiceArea || undefined,
|
||||
@@ -222,7 +237,9 @@ export function LibraryListPanel() {
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
) : (
|
||||
data.items.map((p) => <PrecedentRow key={p.id} p={p} />)
|
||||
data.items.map((p) => (
|
||||
<PrecedentRow key={p.id} p={p} onEdit={setEditingId} />
|
||||
))
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
@@ -230,6 +247,10 @@ export function LibraryListPanel() {
|
||||
)}
|
||||
|
||||
<PrecedentUploadSheet open={uploadOpen} onOpenChange={setUploadOpen} />
|
||||
<PrecedentEditSheet
|
||||
caseLawId={editingId}
|
||||
onOpenChange={(open) => { if (!open) setEditingId(null); }}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user