תיקוני-מבנה ללולאת-הלמידה (TaskMaster #157):
1. כרטיס ה-curator (/training טאב "אוצֵר") ספר decision_lessons WHERE source='curator'
— ערך שאף מסלול-קוד לא כתב → תמיד 0. עוצב-מחדש (דרך שער-העיצוב Claude Design, אושר)
להציג ביושר את שלושת ערוצי-ההזנה לכותב: דיסטילציה→appeal_type_rules (180, זורם),
פאנל→decision_lessons (81, ממתין), אוצֵר→source='curator'. get_curator_stats שוכתב.
2. drift ספ↔סוכן: 07-learning.md §1.1 + INV-LRN3 קבעו שהאוצֵר רושם ממצאים כ-decision_lesson
source='curator', אך הסוכן כתב comments בלבד — הממצאים האיכותיים אבדו. נוסף כלי-MCP
record_curator_findings + §A.5b ב-hermes-curator.md (read-only נשמר; הצעה מגודרת-שער).
3. get_recent_decision_lessons(limit=15) חתך בשקט — נוסף WARN על מה שנחתך (חוקה §6);
הפתרון האמיתי = סינתזת-לקחים (TaskMaster #158).
Invariants: מקיים INV-LRN1/G10 (שער-יו"ר), INV-LRN3 (לכידה מובנית), INV-IA2/IA5 (מקור-אמת
יחיד), G12 (leak-guard עובר), G2 (אין מסלול מקביל — אותם מאגרים). פער-מימוש פתוח מתועד:
§A לא רץ אוטומטית על mark-final (pipeline-wake exits) → נדחה לתכנון נפרד.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
qa_passed was set by the old agent pipeline but not included in the
trimmed 10-status CASE_STATUSES list or LEGACY_STATUS_LABELS, causing
the status badge and workflow timeline to render nothing ("לא ידוע").
Added qa_passed → "טיוטה" to LEGACY_STATUS_LABELS as a display-only
fallback so any case still carrying this value renders correctly until
migrated. Case 8174-12-24 status updated to drafted via PUT /api/cases.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a one-click 'reset agents' action for cases where writer/QA agents
are stuck in Paperclip's error state (triggered by recovery loop or
failed run). Addresses the root cause documented in
reference_paperclip_recovery_loops: reassigns open issues from agents
back to the chair user, and calls reset_agent_session for each error
agent to clear wedged runtime sessions.
Changes:
- paperclip_client.py: reset_case_agents() — reassigns stuck issues +
clears error status in Paperclip DB + calls reset_agent_session
- agent_platform_port.py: exports pc_reset_case_agents (G12 gate)
- app.py: POST /api/cases/{case_number}/agents/reset endpoint
- agents.ts: useResetCaseAgents mutation hook + AgentResetResult type
- agent-status-widget.tsx: 'אפס' button (shown only when error agents
exist) with Dialog confirmation + loading state + toast feedback
Invariants: G12 (Paperclip only via port), G2 (no parallel path —
uses existing reset_agent_session + pc_get_case_issues).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Full code review of the case-detail page (14 components) surfaced these,
all fixed here:
Logic bugs
- case-edit-dialog: form.reset ran on the 5s useCase refetch while the dialog
was open, clobbering in-progress edits. Now resets only on open→true.
- status-changer: `selected` never synced to async/external `currentStatus`
(stale dropdown). Reworked to track currentStatus until an explicit pick;
resets to tracking after save.
- decision-blocks-panel: `block.content`/`word_count` accessed without null
guards (endpoint has no response model) → potential render crash. Coerced
with `?? ""` / `?? 0`. `STATUS_LABELS[status]` now falls back to the raw
status instead of rendering literal "undefined".
- document-type-editor: `await mutateAsync()` in async click handlers without
try/catch → unhandled promise rejection. Wrapped (errors still surface via
isError).
Resilience / hygiene
- page.tsx: a transient 5xx on the background poll flipped the WHOLE page to
the error card and discarded loaded data. Now gated on `!data`, plus a
"נסה שוב" retry.
- cases.ts useUpdateCase: invalidated casesKeys.all, which re-invalidated the
detail it had just optimistically patched. Scoped to the list prefix.
RTL correctness (logical properties)
- agent-status-widget `mr-auto`→`ms-auto`; agent-activity-feed `mr-auto`→
`me-auto`, icon `ml-1/ml-2`→`me-1/me-2`, required `*` `mr-1`→`ms-1`;
document-type-editor list `pr-4`→`ps-4`.
Minors
- drafts-panel: `<a href>`→`next/link` (operations + citation links) for SPA
nav. agent-activity-feed: issueMap memoized; comment Textarea aria-label.
upload-sheet: `unknown` status no longer shown as green success (neutral
icon + "רענן לאישור"). citations.ts: case_name typed `string | null`.
Design gate: visual-touching items (RTL gap side, retry button, neutral
upload icon) were chair-authorized via the reviewed-findings approval ("fix
all"); none alter an approved page layout — they are correctness fixes.
tsc clean; eslint clean (1 pre-existing form.watch warning, untouched line).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Implements the Claude-Design-approved inline status banners for the
"חשב טיעונים" panel (mockup 25-legal-arguments-panel): the four endpoint
states (queued / exists / no_claims / skipped) now render as tone-coded
banners below the header instead of a transient toast. Toast is kept only
for hard transport errors.
Also fixes a pre-existing double-card bug found while reviewing the page:
the page's "arguments" tab already wraps the panel in <Card><CardContent>
(page.tsx:151-155), yet LegalArgumentsPanel rendered its OWN <Card> too —
unlike its sibling tab panels (DecisionBlocksPanel/DraftsPanel/
AgentActivityFeed) which render a plain <div>. The panel now matches that
convention (single card, no double border/padding), consistent with the
approved single-card mockup.
Design gate: card 25 approved by חיים. tsc + eslint clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The RunLogDialog rendered the live agent log inside a Radix ScrollArea.
Radix wraps Viewport children in an inner `display:table` div that
shrink-wraps to the widest unbreakable token — the long `toolu_…` IDs and
`/home/chaim/…` file paths in the raw JSON log. That table cell expands
instead of constraining width, so `whitespace-pre-wrap break-words` never
had a width to wrap against and the text spilled out past the dialog
borders.
Replace the ScrollArea with a plain width-constrained scrollable div and
switch break-words → break-all so the long unbreakable IDs/paths wrap too.
Pure presentational fix (no invariant surface).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The /aggregate-arguments endpoint ran an in-container BackgroundTask that
called claude_session (the local `claude` CLI) — which does not exist in the
FastAPI container. The button silently produced nothing, and on `force` it
destructively DELETEd existing arguments *before* the doomed LLM call.
Replace the inline task with the established delegation pattern used by
"חלץ עובדות שמאיות" (extract-appraiser-facts): a cheap in-container DB
pre-check (no_claims / exists), then a Paperclip wakeup of the company's
legal-analyst, which runs mcp__legal-ai__aggregate_claims_to_arguments
locally (where the CLI lives) and reports back. `force` now runs locally too,
so delete+recompute are atomic on the host — no more destructive failure.
Frontend: AggregateArgumentsResult becomes a discriminated union
(queued | no_claims | exists | skipped) and the toast is status-accurate
instead of the misleading fixed "refresh in a minute".
Invariants: G12 (Paperclip touch confined to paperclip_client behind the
agent_platform_port), G2 (replaces the broken path, no parallel capability),
engineering §6 (explicit statuses, no silent swallow).
UI change is logic/toast only (no visual-layout change) — within the
Claude-Design-gate bug-fix exemption. Richer inline status panels deferred
to the gate.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Frontend half of the citation-verification panel (backend in #323), as the agreed
third tab in /compose — matching the approved X17 mockup 24-citation-verification:
- lib/api/citation-verification.ts: hand-written types + useCitationVerification
query + useVerifyCitation mutation (POST verify, invalidates the view).
- components/compose/citation-verification-panel.tsx: per legal argument →
supporting corpus precedents with the cited_by authority chips (אומץ ×N /
אובחן ×N), the exact supporting_quote, ✓ מאמת / ✗ לא רלוונטי verify actions, a
per-citation chair-note field, and the per-issue 📡 radar (unlinked digests,
pointer-only). Summary strip + INV-AH/INV-DIG1 reminders.
- compose page: third tab "אימות פסיקה" alongside עורך הבלוקים / עמדות וטענות.
No api:types regen needed (endpoints return assembled dicts; types hand-written
per the lib/api convention). tsc + eslint clean.
Invariants: INV-AH (writer cites only verified), INV-DIG1 (digest never cited),
G2 (consumes the one backend view). Visual matches the gate-approved mockup.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The hearing-date/updated/sync metadata dl dropped below the title (taking rows and
pushing the band down) when the appellants/respondents line was long, because the
outer row used flex-wrap. Fix:
- Drop flex-wrap on the title↔metadata row (and flex-1 on the title block) so the
metadata dl stays parallel to the H1; the title block shrinks instead.
- Clamp the parties line (and the subject fallback) to 2 lines with line-clamp-2 +
title tooltip, so a long party list no longer grows the band.
Chair-directed layout fix; existing components, no new design.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Chair-directed navigation/layout fixes (existing components, no new design):
1. "פתח עורך החלטה" moved into the case-page band actions (right after "העלאת
מסמכים") so it's reachable from EVERY tab, not only סקירה. Removed the now-
redundant full-width CTA from the overview tab.
2. Prominent "→ חזרה לדף התיק" back-link added to the /compose header (the
breadcrumb link was too subtle).
3. Home cases table: rail trimmed 360→280px and the title cell made min-w-0 so the
table gets the width it needs and no longer shows a horizontal scrollbar.
No backend / API change. The larger NEW citation-verification panel stays gated
behind Claude Design (preview 24-citation-verification already pushed).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The precedent-detail "ציטוטים מקושרים" panel rendered only MANUAL appeal-chain
links (case_law_relations), so it stayed empty even when decisions cite the
ruling — the automatic citation graph (precedent_internal_citations) was never
surfaced. e.g. עע"מ 317/10 (שפר) has 12 incoming citations in the DB, none shown.
Fills the existing panel from the citation graph (data/logic only, no new
visual design — gate-exempt per web-ui/AGENTS.md):
- citation_extractor.list_citations_to_case_law: return source precedent_level/
court/date too (additive; reuses the one canonical incoming query — G2).
- precedent_library.get_precedent: add incoming_citations[], shaped like the
RelatedCase row. No parallel resolution path.
- web-ui: render incoming citations in the same row style, read-only (no unlink),
de-duped against manual links; manual "קשר" linking preserved alongside.
Invariants: G2 (single citation-resolution path, reused), G1 (graph self-heals
via existing relink_orphan_citations on upload). No schema change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The /graph "משנה / עד שנה" dropdown was hardcoded to 1994–2026, so dated
precedents below 1994 were unreachable by the year filter. After backfilling
decision dates, the corpus now has precedents from 1982 (ע"א 725/81), 1988
(910/86) and 1990 (בג"ץ 1578/90).
Floor → 1980 (covers the oldest); ceiling → current year via getFullYear()
so the range never ages out. Pure UI-logic change — same year_from/year_to
params, no new data path (G2), no backend touch.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The table fetched limit:200 while the header shows the true open count (~497,
via a separate COUNT). With accordion grouping this became visible: sections
summed to exactly 200 (e.g. 16 chair / 173 digest / 11 other) — and 90 of the
106 committee rows (the high-value "cited by Dafna" ones) were hidden past row
200. True buckets: chair 106 / digest 328 / other 63.
- web-ui: list limit 200 → 1000 so all open rows load; accordion section counts
(computed from the loaded set) now equal the header total.
- backend: list cap 500 → 2000 to allow it (response stays a few hundred KB).
Logic/data only — no visual change (bug-fix exception to the design gate).
tsc --noEmit clean; py_compile clean.
Follow-up: when the backlog (digests grow daily) approaches the cap, move to
server-side per-bucket counts + pagination/virtualization (design gate).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Chair-approved (Claude Design card 09): split the flat table into collapsible
sections by where the gap surfaced, so the high-value "cited by Dafna" rulings
aren't buried among the 330 digest rows.
- Three <details> accordion sections within the active status tab:
· "צוטט ע״י דפנה" — rows with a resolved chair from the citation-graph bridge
(cited_by_chairs non-empty); open by default.
· "יומון" — discovery_source='digest'; collapsed.
· "אחר" — party-cited / manual remainder; collapsed.
- Row JSX extracted to renderRow() and reused across sections; shared
TableHeaderRow(); grouping via useMemo over the current result set.
- Empty sections are hidden; section header shows source chip + count.
No backend change — groups on existing cited_by_chairs / discovery_source.
tsc --noEmit clean.
Invariants: INV-IA* (task-oriented surface, single gate) — UI only.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Implements the chair-approved redesign of /missing-precedents (Claude Design
card 09). The "צוטט ע״י" and "תיק" columns were empty for ~98% of rows because
the corpus-decision reliance lives in precedent_internal_citations (keyed to
case_law), a different system than missing_precedents (keyed to cases).
Backend (G2 — read-time bridge, no stored duplication):
- list_missing_precedents: new cited_by_chairs / cited_by_decisions columns,
resolved from the citation graph by normalized docket number (same
normalization the relinker uses). For an open gap cited by committee
decisions, surfaces the chair(s) (e.g. דפנה תמיר) + the deciding case numbers.
Frontend (matches approved mockup):
- "צוטט ע״י" shows the chair chip (bridge) with priority over the generic
discovery-source chips; "תיק" shows the deciding decision number(s) + "+N".
- Status filter reduced to פתוח / נסגר (removed הועלה, לא-רלוונטי, הכל).
- "פסיקה" column collapses to a single line when case_name is empty — fixes the
duplicated-citation two-row rendering.
- Lifecycle note simplified to open → closed.
Verified: bridge SQL returns chair+decisions on live data; tsc --noEmit clean;
py_compile clean.
Follow-up (data, separate): LLM backfill of legal_topic (נושא); create
missing_precedents rows for the 28 graph-cited rulings not yet tracked.
Invariants: G2 (single source of truth — bridge derived at read, no duplicated
column) · INV-AH context (closing source gaps).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The 3-judge panel deliberation was only surfaced in the pending queue; the
'rejected'/'approved' tabs hid WHY an item was auto-rejected/approved even
though the data is captured (reviewer='panel:... maj-not-entailed'). And those
tabs had no way to locate a specific item.
- useHalachotByStatus now requests include_panel_round=true and accepts a
server-side search term (same /api/halachot params the pending queue uses).
- HalachaRestoreCard renders the existing PanelDeliberation component when a
round exists — same card the chair already sees in pending.
- RestorePanel gains the same locate-bar (debounced, server-side search) +
a match-count indicator; the bar stays visible on empty/loading so a search
is always clearable.
Reuses already-approved UI (deliberation = Design card 18, locate-bar = card
19); composition onto a sibling surface, approved directly by chaim. tsc +
eslint clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The pending review queue split items into 'להכרעתך' (chair judgment) vs
'דורש תיקון-חילוץ' (needs re-extraction) by a too-blunt predicate: ANY
quality flag + no panel round → re-extraction. That misfiled fact-specific
'application' items (extraction is fine; the open question is whether the
rule generalizes) as extraction defects, contradicting the backend, which
treats only quote_unverified/truncated_quote/thin_restatement/near_duplicate
as defects and routes 'application' to chair judgment.
Now isExtractionFixItem checks the backend's DEFECT set, so 'application'
(and any other non-defect flag) lands in 'להכרעתך'. For 8508-03-24 this
moves 21 application items judgment→correct and leaves 6 thin_restatement
as the only re-extraction items.
Logic-only fix (predicate), no visual change — design-gate exempt per
web-ui/AGENTS.md. tsc + eslint clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
UI changes to halacha-review-panel.tsx:
- instance_type badge (עיקרון מקורי / ציטוט / יישום) in meta row
- "מוזכר ב-N פסיקות" pill when instance_count > 1
- CanonicalSection component: canonical_statement (view + edit), instances accordion
Backend:
- list_halachot SQL: adds canonical_id, instance_type, canonical_statement,
instance_count via LEFT JOIN canonical_halachot
- list_canonical_instances(canonical_id) → compact rows for accordion
- GET /api/canonical-halachot/{canonical_id}/instances endpoint
- PATCH /api/halachot/{id}: canonical_statement propagates to canonical_halachot
- HalachaUpdateRequest: canonical_statement field
- useCanonicalInstances hook + CanonicalInstance type in precedent-library.ts
INV-G10 (chair gate): only the chair can edit canonical_statement (same
flow as rule_statement — PATCH /api/halachot/{id} with reviewer="דפנה").
G2: canonical data flows through canonical_halachot, not a parallel store.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- הסרת כרטיס "סקירת התיק" הדל (3 אלמנטים בלבד)
- כפתור "התחל תהליך" עלה לפס-הפעולות בראש הדף (ליד "העלאת מסמכים")
- כרטיס חדש AgentActivityPreview: 4 הissues האחרונים + קישור לטאב מלא
- "תוצאה צפויה" ירדה לשורת מטא-דאטה בראיל הסטטוס (מוצגת רק אם נקבעה)
- תיקון באג: expected_outcome לא נשמר — guard if expected_outcome: הוחלף ב-is not None
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
כרטיס-התכניות בדף /precedents הציג רק review_status=pending_review,
כך שתכניות מאושרות (התקינות, בשימוש-חוזר בבלוק ט) לא היו נגישות לעיון.
ה-backend כבר תמך ב-?review_status= ו-?q= — חסר רק חוט-UI.
- plans.ts: usePlansPending → usePlansAll (טעינת כל המרשם בקריאה אחת;
הפאנל מסנן client-side — מרשם קטן, מונה-מדויק לכל סגמנט, חיפוש מיידי)
- plans-review-panel: סרגל-מצב (ממתינים/מאושרות/כולן) עם מונים + תיבת-חיפוש
fuzzy (מספר/שם/ייעוד/aliases, מנורמל-bidi); הערת-קטיעה אם >1000 (בלי cap שקט)
- PlanCard מסתעף לפי review_status: מאושרת/נדחתה → תג-מצב + "החזר לתור"
(review→pending_review) במקום אשר/דחה; דדופ-candidates רק בתור
עבר דרך שער-עיצוב Claude Design (מוקאפ 22-plans-review מאושר ע"י חיים).
ללא שינוי-backend. מרחיב מרשם-V38 הקיים — לא מסלול מקביל.
Invariants: G2 (יכולת קיימת, endpoint קיים) · INV-IA2 (שער-יחיד /precedents)
· G10 נשמר (review_status שער-יו"ר).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
שני פערים שצפו מ-/precedents בחילוץ-ההלכות:
1. **practice_area לא סומן** — השדה הועבר ל-LLM כקונטקסט-קריאה-בלבד ולא חולץ
מעולם, כך שהעלאות שהשאירו אותו ריק נשארו ריקות והרדיו ב-/precedents הופיע
ללא בחירה. עכשיו נגזר ב-apply_to_record: עדיפות לגזירה דטרמיניסטית מקידומת
מספר-התיק (1xxx→rishuy, 8xxx→היטל, 9xxx→197 — מקור-אמת לדוקטי ועדת-ערר,
INV-AH rule-based), ובנפילה — סיווג-תוכן של ה-LLM (שדה practice_area חדש
בפרומפט, אנום-סגור) עבור פסקי-בית-משפט שהקידומת שלהם אינה מקודדת תחום.
ממלא רק כשריק (G1 — נרמול במקור, לא תיקון-בקריאה).
2. **שם-יו"ר לא חולץ** (למשל 1132-09-24) — המיזוג היה מגודר על
source_kind=='internal_committee' בלבד, ודילג בשקט על החלטות-ועדה שהועלו
במסלול הפסיקה החיצוני (external_upload + source_type=appeals_committee, כמו
החלטת ת"א מנבו) — היו"ר ישב בבלוק-החתימה אך לא חולץ. עכשיו מגודר על "האם זו
החלטת-ועדה" (source_type/level אפקטיביים), לעולם לא על פסק-בית-משפט. ה-CHECK
כופה non-empty רק ל-internal_committee, לכן כתיבה ל-external בטוחה.
חיזוק-פרומפט (לבקשת היו"ר): chair_name מציין מפורשות את בלוק-החתימה הדו-טורי
(מזכיר↔יו"ר — לקחת את צד-היו"ר) ומזהיר לא לחלץ יו"ר של פסקי-דין **מצוטטים**
בגוף ההחלטה.
UI (לוגיקה-בלבד, פטור משער-העיצוב): edit-sheet מסנכרן-מחדש מהרשומה הטרייה בכל
פתיחה (re-arm על סגירה) ו-usePrecedent עושה poll בזמן חילוץ — כך מילוי-רקע של
practice_area/chair_name מופיע בלי refresh מלא ("הכפתור לא נשאר מסומן").
בדיקות: test_metadata_extract_chair_practice_area.py (6 תרחישי-מיזוג, offline).
Invariants: G1 (נרמול-במקור), G2 (אותו extractor, לא מסלול מקביל),
INV-AH (גזירה דטרמיניסטית מועדפת, abstention כשאין ודאות).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ה-gitea_url מצביע על קובץ scripts/SCRIPTS.md, אבל הקישור הפר-סקריפט הוסיף
אחריו את שם-הסקריפט → …/scripts/SCRIPTS.md/<name> (404 ב-Gitea). מתקן:
מסיר את שם-הקובץ האחרון מהבסיס לפני הוספת שם-הסקריפט, כך שהקישור מצביע
על …/scripts/<name>.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
SCRIPTS.md: הסקריפטים החד-פעמיים (25, לפי עמודת Scheduled) הוצאו מסעיף
"## סקריפטים פעילים" אל סעיף חדש "## חד פעמי" בתחתית (לפני .archive),
מקובצים באותם תתי-כותרות ### לפי תת-נושא. כל 79 השורות (54 חוזרות + 25
חד-פעמיות) נשמרו מילה-במילה. הערת-הקונבנציה עודכנה.
/scripts: ה-parser מזהה את סעיף "## חד פעמי" כסקשן נפרד; הרינדור דו-רמתי —
כותרת-סעיף "פעילים" + קבוצות, ואז כותרת-סעיף "חד פעמי" + קבוצות-משנה
מוזחות (ms-5), מקופלות כברירת-מחדל. סטטוס-השורה נגזר מהסעיף.
מאושר דרך שער-העיצוב (מוקאפ 16-scripts עודכן; חיים אישר מראש).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
תור-ההלכות שלף רק 500 ממתינות בעלות-עדיפות מתוך ~1,372, בלי שום דרך
לאתר פס"ד מסוים. הלכה מדורגת מתחת לחלון (למשל 1180-11-25, מקומות 921/1305)
פשוט נעלמה — הספירה בספרייה הציגה "2 ממתינות" אך התור לא הראה אותן.
- list_halachot: פרמטר search (case_number/case_name/rule_statement, ILIKE)
— סינון בצד-השרת כך שפריט מתחת לחלון נשאר נגיש. מרחיב את מסלול-השליפה
היחיד, לא יוצר מסלול מקביל (G2).
- count_halachot: ספירה מלאה לאותו פילטר (ל-"N מתוך TOTAL").
- /api/halachot: search + with_total (ברירת-מחדל off; קוראים קיימים לא מושפעים).
- UI (תור-הלכות): שורת-חיפוש מהוקצבת (debounce 300ms), הערת "חלון התצוגה"
(500 מתוך הסך), ושורת-הקשר-תוצאה עם ניקוי. בחיפוש — כל הקבוצות התואמות
נפתחות; הניווט המקלדתי והשערים (G10) ללא שינוי.
מאומת מול ה-DB: search='1180-11-25' → 2 הממתינות (index 20 נקייה→להכרעתך,
index 23 nli_unsupported→דורש תיקון-חילוץ); count=2.
עיצוב: עבר שער Claude Design (X17, כרטיס 19-halacha-queue-unified) ואושר.
Invariants: מקיים G2 (מסלול-שליפה יחיד), INV-G10 (שער-יו"ר ללא שינוי),
INV-IA (מקור-אמת יחיד לתור). ללא בליעת-שגיאות.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
יישור /compose למוקאפ 03-case-workspace (הכרעת חיים: המוקאפ נכון). ה-main
הופך לרצועת-2-טאבים:
- "עורך הבלוקים" (ברירת-מחדל) — שימוש-חוזר ב-DecisionBlocksPanel הקיים
(12 בלוקים, סטטוס, ספירת-מילים, עורך-inline על parchment, שמירה PUT).
- "עמדות וטענות" — עורך-העמדות/טענות הקיים (SubsectionCard/ChairEditor),
הועבר כמות-שהוא לטאב.
הגייטינג שונה: העמוד נטען לפי caseQuery (לא analysis), כך שעורך-הבלוקים
מוצג גם כשטרם בוצע ניתוח; ענפי-ה-analysis (pending/not-found/error/data)
עברו לתוך טאב-העמדות. band + rail (מסמכים/פסיקה/השלמה) ללא שינוי.
אין שינוי-backend — GET/PUT decision-blocks + useDecisionBlocks/useSaveBlock
כבר קיימים. מאושר דרך שער-העיצוב (מוקאפ 03 עודכן עם רצועת-הטאבים).
Invariant: G2 — שימוש-חוזר ב-DecisionBlocksPanel, ללא מסלול-עריכת-בלוקים מקביל.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
נשאר תחת ספריית-פסיקה (לבקשת חיים) אך משופר:
- שני מדדי-על: פסיקות בקורפוס · הלכות בסך-הכל.
- כרטיס חדש "סטטוס סקירת הלכות" — פס-מוערם מאושרות/ממתינות/נדחו, מנצל את
halachot_rejected שנחשף ב-/api/precedent-library/stats (PR #273).
- "פילוח לפי תחום" ו"לפי רמת-תקדים" כפסים אופקיים במקום רשימות-טקסט.
מאושר דרך שער-העיצוב (Claude Design 07b-precedents-stats).
Invariant: G2 — צרכן read-only של מקור-הספירה היחיד (precedent_library_stats).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
עיצוב-מחדש בכיוון "כרטיסים מרועננים" (מאושר ע"י חיים, Claude Design 01-approvals):
- פס-חומרה דק (3px) בקצה-התחלה של כל כרטיס (border-s לפי severity) במקום
תג-מספר קטן. הספירה הראשית (המספר הגדול) נשמרת.
- כרטיס תור-נקי מעומעם: רקע parchment, ללא צל, מספר ב-ink-muted, שבב "✓ תור נקי".
- מבנה 2×2 והלוגיקה (usePendingApprovals, samples, CTA) ללא שינוי.
מאושר דרך שער-העיצוב.
Invariant: INV-IA1 — מרכז-אישורים נשאר השער-האנושי-היחיד; שינוי ויזואלי בלבד.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
המספרים בתגי תור-ההלכות היו תקרות-שאילתה ולא ספירה אמיתית:
- "ממתינות 500" = pendingData.items.length עם limit=500
- "נדחו 1000 / אושרו 1000" = useHalachotByStatus(...,1000) — תקרה 1000
ובלי refetchInterval התגים התעדכנו רק בכניסה לדף.
המקור האמיתי כבר קיים: /api/precedent-library/stats מריץ COUNT(*) אמיתי
(pending=1373, approved=2100). מוסיף לו halachot_rejected + halachot_deferred,
מחבר את תגי-ה-HalachaReviewPanel למקור הזה, ומוסיף polling (30s) כדי שהם
יתעדכנו חי. מסיר את useHalachaCount המיותר.
תור-העבודה עצמו עדיין נטען עד 500 פריטים (cap-עבודה לגיטימי); רק תצוגת
הספירות תוקנה להציג את הסך-האמיתי.
Invariants: מקיים G1 (נרמול-במקור — ספירה אמיתית מ-COUNT(*) במקום len(rows)
מתוקרת בקריאה) ו-G2 (מאחד על מקור-הספירה הקיים, ללא endpoint-ספירה מקביל).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two follow-ups to the usage-% feature:
1. The /api/oauth/usage endpoint 429s when polled often — /operations refreshes
every 5s and each refresh hit it (plus the supervisor + ad-hoc calls). Cache
the last good payload on the host bridge for 60s and serve it; only re-fetch
when stale, so Anthropic sees ~1 req/min regardless of dashboard polling. On
a fetch failure (e.g. a transient 429) serve the last good payload instead of
blanking the card. The 5-hour window moves slowly, so 60s stays fresh.
2. The third meter showed weekly-Opus, which is null on this account (the
per-model weekly cap that's actually populated is Sonnet). Switched the
display to seven_day_sonnet / "שבועי · Sonnet". (The supervisor keeps gating
on seven_day_opus — the halacha drain runs Opus, so the Opus cap is the
correct gate even when it's null/inactive.)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>