feat(ui): דף /scripts — קטלוג סקריפטים read-only מ-SCRIPTS.md
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 8s
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 8s
מגיש את 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>
This commit is contained in:
86
web-ui/src/app/scripts/page.tsx
Normal file
86
web-ui/src/app/scripts/page.tsx
Normal file
@@ -0,0 +1,86 @@
|
||||
"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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user