diff --git a/web-ui/src/app/diagnostics/page.tsx b/web-ui/src/app/diagnostics/page.tsx index 56ab867..9d2f6b6 100644 --- a/web-ui/src/app/diagnostics/page.tsx +++ b/web-ui/src/app/diagnostics/page.tsx @@ -129,6 +129,57 @@ export default function DiagnosticsPage() { + {/* Halacha review backlog (ADM-1, INV-IA5): render the human-gate + counter the backend returns; the action lives at /approvals + (INV-IA1 — this surface only points, never decides). */} + + +

+ + תור אישור הלכות + + {isPending ? "—" : (data?.halacha_backlog?.pending_review ?? 0)} + + + לאישור ← + +

+ {isPending ? ( + + ) : ( +
+
+
ממתינים (נקי)
+
+ {data?.halacha_backlog?.pending_clean ?? 0} +
+
+
+
דורש תיקון
+
+ {data?.halacha_backlog?.pending_flagged ?? 0} +
+
+
+
אושרו
+
+ {data?.halacha_backlog?.approved ?? 0} +
+
+
+
הוותיק ביותר
+
+ {formatRelativeTime(data?.halacha_backlog?.oldest_pending_at ?? null)} +
+
+
+ )} +
+
+ {/* Active tasks */} diff --git a/web-ui/src/app/methodology/page.tsx b/web-ui/src/app/methodology/page.tsx index 1374051..76e063e 100644 --- a/web-ui/src/app/methodology/page.tsx +++ b/web-ui/src/app/methodology/page.tsx @@ -45,14 +45,14 @@ export default function MethodologyPage() { diff --git a/web-ui/src/app/operations/page.tsx b/web-ui/src/app/operations/page.tsx index 3fc752f..78a239f 100644 --- a/web-ui/src/app/operations/page.tsx +++ b/web-ui/src/app/operations/page.tsx @@ -443,8 +443,23 @@ function LiveAgentsPanel() {

סוכנים פעילים

{data ? (
- רצים {data.running} - בתור {data.queued} + {/* ADM-6 (INV-IA5): counts sum only the companies that loaded. + When a company errored, mark the totals as a floor ("+") so + the operator isn't shown a shrunken depth as if complete. */} + + רצים {data.running}{data.errors.length > 0 ? "+" : ""} + + + בתור {data.queued}{data.errors.length > 0 ? "+" : ""} + + {data.errors.length > 0 ? ( + + ⚠ חלקי + + ) : null}
) : null} diff --git a/web-ui/src/app/settings/_components/env-var-row.tsx b/web-ui/src/app/settings/_components/env-var-row.tsx index 65c71eb..c570703 100644 --- a/web-ui/src/app/settings/_components/env-var-row.tsx +++ b/web-ui/src/app/settings/_components/env-var-row.tsx @@ -87,11 +87,23 @@ export function EnvVarRow({ )} -
+
Container: {spec.container_value ?? — לא מוגדר —} + {/* ADM-5 (INV-IA5/INV-IA6): when Coolify ≠ Container the container is + running a stale value until a redeploy — say so in plain Hebrew + right here, not only via the top "Drift" badge. */} + {coolifyAvailable && spec.drift && ( + + ממתין ל-redeploy + + )}
diff --git a/web-ui/src/components/methodology/content-checklists-panel.tsx b/web-ui/src/components/methodology/content-checklists-panel.tsx index bbd945d..9eb24ab 100644 --- a/web-ui/src/components/methodology/content-checklists-panel.tsx +++ b/web-ui/src/components/methodology/content-checklists-panel.tsx @@ -30,6 +30,17 @@ const CHECKLIST_ORDER = [ "betterment_levy", ]; +// MET-6 (INV-IA6/INV-IA5): which case selects each checklist — mirrors the +// server's get_content_checklist() routing (lessons.py:580-622) so the chair +// sees *when* a checklist is consumed, not five unlabelled types. +const CHECKLIST_APPLIES: Record = { + licensing_substantive: "ברירת-מחדל — כל ערר רישוי שאינו נופל לקטגוריה אחרת", + licensing_threshold: "עררי רישוי בנושא סמכות / סף / סילוק-על-הסף / זכות-ערר", + licensing_property: "עררי רישוי בנושא תימוכין קנייניים / בעלות / הסכמת-דיירים", + tama38: 'עררים בנושא תמ"א 38 / חיזוק', + betterment_levy: "תיקי היטל השבחה (8xxx)", +}; + type ChecklistItem = { key: string; label: string; @@ -131,12 +142,19 @@ export function ContentChecklistsPanel() {
-

{current.label}

+
+

{current.label}

+ {CHECKLIST_APPLIES[current.key] && ( +

+ חל על: {CHECKLIST_APPLIES[current.key]} +

+ )} +

diff --git a/web-ui/src/components/training/compare-panel.tsx b/web-ui/src/components/training/compare-panel.tsx index 6d78d77..11644cd 100644 --- a/web-ui/src/components/training/compare-panel.tsx +++ b/web-ui/src/components/training/compare-panel.tsx @@ -118,7 +118,15 @@ export function ComparePanel() { const { data: corpus, isPending } = useCorpus(); const [a, setA] = useState(null); const [b, setB] = useState(null); - const cmp = useCompare(a, b); + + // LRN-6 (INV-IA2): if a selected decision was deleted from the corpus on + // another surface, a cached selection would POST a stale id and 404. Derive + // the effective selection from the refreshed corpus instead of holding it in + // state — a deleted id resolves to null (no effect, no stale POST). + const ids = corpus ? new Set(corpus.map((c) => c.id)) : null; + const validA = a && (!ids || ids.has(a)) ? a : null; + const validB = b && (!ids || ids.has(b)) ? b : null; + const cmp = useCompare(validA, validB); return (

@@ -133,7 +141,7 @@ export function ComparePanel() {