Files
legal-ai/web-ui/src/app/scripts/page.tsx
Chaim 8651529327
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 8s
feat(ui): דף /scripts — קטלוג סקריפטים read-only מ-SCRIPTS.md
מגיש את scripts/SCRIPTS.md כדף ב-/scripts: שם · סוג · תפקיד · תזמון
לכל סקריפט בתיקיית scripts/. מקור-האמת היחיד נשאר SCRIPTS.md (G2 — אין
מסלול-תוכן מקביל); עריכה דרך git, לא מה-UI.

- web/app.py: GET /api/scripts/catalog קורא את הקובץ בזמן-ריצה (מחקה את
  דפוס get_curator_prompt; HTTPException על כשל — אין בליעה שקטה §6)
- Dockerfile: COPY scripts/SCRIPTS.md (לא הועתק לקונטיינר עד כה)
- web-ui: דף /scripts (AppShell + רכיב Markdown הקיים) + מודול api + קישור ניווט
- SCRIPTS.md: תיעוד ingest_bulletins.py — היה הקובץ היחיד מ-73 שלא תועד

Invariants: G2 (מקור-אמת יחיד), G12 (אין מגע-Paperclip), X6 (UI↔API).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 19:42:44 +00:00

87 lines
3.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import { useQuery } from "@tanstack/react-query";
import { AppShell } from "@/components/app-shell";
import { Card, CardContent } from "@/components/ui/card";
import { Markdown } from "@/components/ui/markdown";
import { fetchScriptsCatalog } from "@/lib/api/scripts";
/*
* /scripts — read-only catalog of everything under scripts/.
*
* The content is `scripts/SCRIPTS.md` verbatim (active · archived · deleted
* tables), served by GET /api/scripts/catalog. SCRIPTS.md is the single
* source of truth — CLAUDE.md mandates updating it on every script change —
* so we render it directly rather than re-describing the scripts here.
*/
export default function ScriptsPage() {
const { data, isLoading, isError, error } = useQuery({
queryKey: ["scripts-catalog"],
queryFn: ({ signal }) => fetchScriptsCatalog(signal),
});
const lastModified =
data?.last_modified != null
? new Date(data.last_modified * 1000).toLocaleDateString("he-IL", {
year: "numeric",
month: "long",
day: "numeric",
})
: null;
return (
<AppShell>
<section className="space-y-6">
<div className="flex items-end justify-between gap-4">
<div>
<h1 className="text-xl font-bold text-navy">סקריפטים</h1>
<p className="text-sm text-ink-muted mt-1">
קטלוג כל הסקריפטים בתיקיית{" "}
<code className="rounded bg-rule-soft px-1 py-0.5 font-mono text-[0.78rem]">
scripts/
</code>{" "}
שם, סוג, תפקיד ותזמון. מקור-האמת הוא{" "}
<code className="rounded bg-rule-soft px-1 py-0.5 font-mono text-[0.78rem]">
scripts/SCRIPTS.md
</code>
; עריכה דרך git, לא מכאן.
</p>
</div>
{data?.gitea_url ? (
<a
href={data.gitea_url}
target="_blank"
rel="noreferrer"
className="shrink-0 text-sm text-gold-deep hover:text-gold underline underline-offset-2"
>
מקור ב-Gitea
</a>
) : null}
</div>
<Card className="bg-surface border-rule shadow-sm">
<CardContent className="px-6 py-5">
{isLoading ? (
<p className="text-sm text-ink-muted">טוען קטלוג</p>
) : isError ? (
<p className="text-sm text-danger">
שגיאה בטעינת הקטלוג: {(error as Error)?.message ?? "לא ידוע"}
</p>
) : data ? (
<>
<Markdown content={data.content} />
{lastModified ? (
<p className="mt-6 pt-3 border-t border-rule text-xs text-ink-muted">
עודכן לאחרונה: {lastModified}
</p>
) : null}
</>
) : null}
</CardContent>
</Card>
</section>
</AppShell>
);
}