חיים (2026-06-11): "המערכת מסובכת מדי לתפעול." סריקת-עומק רב-סוכנית (18 סוכנים,
6 אשכולות × קטלוג→אימות-אדוורסרי→תכנון-יעד) מיפתה 34 משטחים ואימתה 37 ממצאים
(file:line). כולם ביטוי-UI אחד של G2 מופר שלא הורחב לשכבת-ה-UI.
תוצרים:
- docs/ia-audit-redesign.md — מצב-קיים: 5 מחלות-שורש (16 פערי-סנכרון, משטחי-אישור
כפולים, 6 נתונים-שגויים, 5 מתים, כפילות-ניווט), ממצאים פר-אשכול בטבלאות.
- docs/spec/X17-information-architecture.md — ספ-יעד: INV-IA1..IA6 מרימים את G2
(מקור-אמת יחיד) ו-G10 (שערים-אנושיים) לשכבת-המשטח; משטח-יעד (3 משטחי-intent +
בעלים-יחיד לכל ישות); כל invariant מגובה ≥3 מקורות (NN/g, GOV.UK, USWDS,
Rosenfeld/Morville, TkDodo/TanStack, Krug).
- docs/spec/README.md — אינדקס מעודכן (X1–X17 + ia-audit-redesign).
יחס לקיים (דאבל-צ'ק): ui-audit.md=שכבת-קוד (FU-10); X17=שכבת-IA מעל X6. לא כופל.
G10 נשמר 100% — מסירים משטח/ערוץ כפול, לא שער ("שער אחד"=מקום-אחד-להחליט).
עוצרים על המסמך (3א) — בקלוג-איחוד ב-#127.6, ביצוע באישור-יו"ר.
Invariants: מקיים G2 (מזהה+ממפה הפרות-UI), מקיים G10/INV-LRN1 (שערים נשמרים),
ממליץ דלתות-ספ ל-X6/07-learning/00-constitution (לאישור).
ref: #127 · feedback_operational_simplicity
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
18 KiB
IA-Audit & Redesign — מפת משטח-ההפעלה, כפילויות, וניווט-יעד
מה זה. אבחון שיטתי של משטח-ההפעלה של המערכת (כל דף/טאב/drawer/פונקציה) — מה כל אחד עושה, מה כפול, מה מת, מה מציג נתון שגוי, ואיך הכול מסתנכרן — ותכנון-מחדש של ארכיטקטורת-המידע (IA). נכתב לפי בקשת חיים (2026-06-11): "המערכת מסובכת מדי לתפעול… כל הדפים האלה מפוזרים ואין לי מושג מה כל אחד עושה והאם יש כפילויות."
היקף: משטח-ההפעלה (1א). ה-backend נכלל רק היכן שהוא גורם לכפילות/נתון-שגוי ב-UI. תוצר-אחות: ספ-היעד
docs/spec/X17-information-architecture.md. יוזמה: TaskMasterlegal-ai#127.איך הופק: סריקת-עומק רב-סוכנית (18 סוכנים, 6 אשכולות × 3 שלבים — קטלוג → אימות-אדוורסרי מול הקוד → תכנון-יעד מגובה-מקורות). כל ממצא אומת ב-
file:line; כל עקרון-תכנון מגובה ב-≥3 מקורות סמכותיים (ראה X17 §מקורות).
יחס למסמכים קיימים (דאבל-צ'ק — לא לכפול)
ui-audit.md— ביקורת-קוד פר-רכיב (enums כפולים, טיפוסים, helpers → FU-10). שכבה אחרת. מסמך זה הוא בשכבת ה-IA/הפעלה (אילו משטחים, מה כל אחד עושה, סנכרון, ניווט). חופף נקודתית ב-UI-C1 (3 דפי-פסיקה חופפים) ו-UI-D2/D3 (שקיפות-מקור) — מורחב כאן.gap-audit.md— ממצאי-ארכיטקטורה (GAP→FU). מסמך זה ברמת-הדף.X6-ui-api-contract.md— חוזה UI↔API (UI1–UI6). X17 מוסיף שכבת invariants מעל X6.
1. תקציר-מנהלים — 5 מחלות-השורש
הסריקה אימתה 37 ממצאים על פני 34 משטחים. כולם נופלים ל-5 דפוסים:
| # | מחלת-שורש | כמה | מהות |
|---|---|---|---|
| D1 | פערי-סנכרון ב-cache | 16 | mutation מבטל רק את ה-queryKey המקומי, לא את ה-aggregator/האח/ה-namespace השני → מונה/נתון תקוע ב-0–60ש' בין דפים. זהו G2 בשכבת ה-TanStack-Query cache. |
| D2 | משטחי-כתיבה/אישור כפולים | 6 (dup) + 2 confusing | אותו datum נערך/מאושר ב-2 מקומות שכותבים ל-2 ערוצים. החריף: שני שערי-למידה (decision_lessons מול promote) ו-מתודולוגיה (PUT מול promote כותבים לאותה שורה — מירוץ lost-update). זו בדיוק ה"למה 2 שערים" של חיים. |
| D3 | נתונים-שגויים/מטעים | 6 | KPI סופר דגל אינפורמטיבי-בלבד (applied_to_skill/findings_applied — "מזויף"); signature_phrases עם תווית-קרדינליות שקרית; מונה-תור שמתעלם מחברה לא-זמינה. |
| D4 | משטחים/פונקציות מתים | 5 | endpoint queue/pending ללא צרכן; כפתור applied_to_skill; ז'רגון T7/T15; AuthorityBadge חסר בחיפוש. |
| D5 | כפילות-ניווט | — | הערות-יו"ר ב-2 דפים; /operations+/diagnostics אותו intent; precedents מול precedent-library. |
התובנה המאחדת: רוב המחלות הן ביטוי-UI אחד של עקרון-על מופר — G2 (מקור-אמת יחיד / אין מסלולים מקבילים) — שמעולם לא הורחב לשכבת-ה-UI (cache + משטחים). זה בדיוק מה שחיים חווה כ"מסובך לתפעול": אותו מספר בשני מקומות, שני שערים לאותה החלטה, ומספרים שלא מתעדכנים.
ניווט-היעד (תמצית — מלא ב-X17)
שלושה משטחי-intent עם בעלים-יחיד, במקום פיזור-לפי-פורמט:
/approvals= תיבת-ההחלטות-האנושית היחידה — המקום היחיד שבו פועלים על שער. דפים אחרים מצביעים למונה, לא משכפלים אותו./operations= משטח-הקריאה-בלבד היחיד ("מה המכונה עושה") — בולע את/diagnostics./settings= משטח-התצורה היחיד. ובתוך-התחום: החלטה=workspace אחד · למידה=תיבה+ערוץ+שער אחד ·/methodology=עורך-הכללים היחיד · פסיקה=3 קורפוסים נפרדים אך מתפעלים אחיד.
כל ההצעות שומרות 100% מהשערים-האנושיים (G10/INV-LRN1). מסירים משטח/ערוץ כפול, לא שער. זו ההתאמה בין "פשטות-הפעלה" ל-G10.
2. ממצאים לפי אשכול
לכל אשכול: משטחים שקוטלגו · ממצאים מאומתים (file:line) · כיוון-היעד. הפירוט המלא (כל אלמנט + כל מקור) נשמר בפלט-הסריקה (data/audit/).
2.1 תיקים (/, /archive, /cases/[n], /compose)
3 משטחים · 2 ממצאים. מחלה: תוכן-ההחלטה מפוצל ל-2 משטחי-כתיבה עצמאיים + עורך-compose שלישי.
| ID | סוג | ממצא | file:line | תיקון |
|---|---|---|---|---|
| CAS-1 | sync-gap | DraftsPanel (העלאת DOCX) לא מבטל ['decision-blocks'] → DecisionBlocksPanel מציג source_of_truth='blocks' תקוע; אזהרת-הסטייה לא מופיעה עד רענון ידני |
exports.ts:103-107 מול decision-blocks.ts:46-49; app.py:2673 | add-invalidation |
| CAS-2 | sync-gap | useExportDocx לא מבטל ['decision-blocks'] — אותו שורש |
exports.ts:80-82 | add-invalidation |
יעד: workspace-החלטה אחד (block-editing + DOCX-פעיל) עם מחוון-מקור-אמת אחד בבעלות-המערכת ו-cache-slice משותף; אזור "השלמה והעברה" אחד לכל שערי-סיום-התיק.
2.2 אישורים + הערות-יו"ר (/approvals, /feedback)
3 משטחים · 6 ממצאים. מחלה: /api/chair/pending גוזר 4 מונים, אך כל משטח-משימה מבטל רק את ה-cache שלו ולא את ה-aggregator → התיבה והתג-בסרגל תקועים עד 60ש'.
| ID | סוג | ממצא | file:line | תיקון |
|---|---|---|---|---|
| APR-1 | sync-gap | פתרון הערה ב-/feedback לא מבטל ['chair','pending'] → מונה /approvals והתג תקועים |
feedback.ts:105; chair.ts:36; app-shell.tsx:336 | add-invalidation |
| APR-2 | duplication | הערות-יו"ר ב-2 caches (['feedback'] מול ['chair','pending']) ללא הצלבה — שני endpoints על אותה chair_feedback WHERE NOT resolved |
app.py:5650,5654 | add-invalidation |
| APR-3 | wrong-data | דגימת-ההערות ב-/approvals יכולה להראות 5 ישנות בעוד המונה כבר 0 |
app.py:5650-5654; chair.ts:36 | fix-data |
| APR-4 | sync-gap | ApprovalsBadge בסרגל תקוע אחרי פתרון-הערה/אישור-הלכה/העלאת-פסיקה |
app-shell.tsx:336; feedback.ts:105; missing-precedents.ts:256-258; precedent-library.ts:648,668 | add-invalidation |
| APR-5 | sync-gap | אישור-הלכה לא מבטל ['chair','pending'] |
precedent-library.ts:648,668; app.py:5619-5620 | add-invalidation |
| APR-6 | sync-gap | העלאת/סגירת פסיקה-חסרה לא מבטל ['chair','pending'] |
missing-precedents.ts:256-258; app.py:5636-5637 | add-invalidation |
יעד: /approvals = תיבת-הגייטים הקנונית היחידה; ['chair','pending'] = מקור-אמת יחיד ל"מה ממתין"; התג בסרגל = המונה היחיד; הערות-יו"ר יורד מהניווט-הראשי והופך לכרטיס-משימה מתוך התיבה.
2.3 פסיקה (/precedents, /missing-precedents, /digests, /precedents/[id], /graph)
13 משטחים · 5 ממצאים. מחלה: 3 קורפוסים אמיתיים ושונים — אך מתפעלים שונה ומבלבלים בשמות.
| ID | סוג | ממצא | file:line | תיקון |
|---|---|---|---|---|
| PRE-1 | confusing | שני namespaces כמעט-זהים: /api/precedents/search (typeahead לתיק) מול /api/precedent-library/search (חיפוש-קורפוס) |
app.py:3109 מול 6057 | clarify (rename/label) |
| PRE-2 | dead | GET /api/precedent-library/queue/pending — אפס צרכני-frontend (רק digests משתמש ב-queue/pending) |
app.py:6282 | delete |
| PRE-3 | wrong-data | AuthorityBadge (binding/persuasive, DERIVED) מוצג בתור-הביקורת אך נשמט בחיפוש |
library-search-panel.tsx:26-73 מול halacha-review-panel.tsx:109 | fix-data |
| PRE-4 | confusing | תג "ממתין" ב-/digests נראה לחיץ אך אינו (ב-/precedents הוא טאב-תור אמיתי) |
digests/page.tsx:23-35 | clarify |
| PRE-5 | dead | HalachaCard בחיפוש לא מרנדר authority אף שהשדה על החוט |
library-search-panel.tsx:26-73 | fix-data |
יעד: 3 הקורפוסים נשארים נפרדים (גבול אמיתי — G2/INV-DIG1) אך מתפעלים אחיד: שם-חיפוש עקבי לכל קורפוס, תבנית-"ממתין" אחת, authority מוצג בכל מקום. מחיקת ה-endpoint המת.
2.4 למידה + סגנון (/training — 6 טאבים + CorpusDetailDrawer) ⚠️ האשכול הקריטי
8 משטחים · 10 ממצאים. מחלה: "לקח" חי ב-2 namespaces ומאושר ב-2 מקומות שכותבים ל-2 ערוצי-כותב; 3 KPI על דגלים-ללא-צרכן.
| ID | סוג | ממצא | file:line | תיקון |
|---|---|---|---|---|
| LRN-1 | sync-gap | כפתור applied_to_skill ("אומץ לסקייל") אינפורמטיבי-בלבד — לא כותב ל-SKILL.md; היו"ר מאמין שהפעולה הושלמה |
lessons-tab.tsx:12-14; app.py:1471-1475 | fix-data (להסיר) |
| LRN-2 | confusing | למידה מפוצלת ל-/api/learning + /api/training לאותה ישות |
learning.ts; training.ts; app.py:1448,4616 | clarify (לאחד) |
| LRN-3 | confusing | שני שערי-אישור ללא יחס אכוף — promote מתעלם מ-review_status לגמרי |
learning-panel.tsx:89-150; lessons-tab.tsx:168-179; app.py:4574 | clarify (שער אחד) |
| LRN-4 | wrong-data | StyleReportPanel: "12 מתוך 487 שחולצו" — signature_phrases ו-total_patterns מחושבים עצמאית; אין יחס-תת-קבוצה |
style-report-panel.tsx:87-90 | fix-data |
| LRN-5 | wrong-data | findings_applied ("ממצאים שאומצו ל-SKILL: 42") סופר דגל-אינפורמטיבי → KPI "מזויף" |
curator-portrait-panel.tsx:85-86; app.py:1300-1302 | fix-data |
| LRN-6 | sync-gap | מחיקת-קורפוס לא מאפסת בחירת ComparePanel → submit מחזיר 404 |
compare-panel.tsx:119-120; training.ts:172-174 | fix-data |
| LRN-7 | keep | FullTextLazy ב-raw-fetch מחוץ ל-Query — שביר לעתיד, לא באג חי |
corpus-detail-drawer.tsx:320-348 | keep |
| LRN-8 | sync-gap | מחיקת-קורפוס מייתמת צ'אטים (style_corpus_id→NULL) בשקט, ללא אזהרה |
corpus-panel.tsx:45-54; db.py:234 | add-invalidation |
| LRN-9 | keep | סינון PatternsForSubtype stubbed (אין endpoint) — fallback חינני |
corpus-detail-drawer.tsx:351-353 | keep |
| LRN-10 | sync-gap | usePromoteLearning מבטל רק learningKeys, לא lessonsKeys.forCorpus → LessonsTab תקוע |
learning.ts:104-115; training.ts:499-502 | add-invalidation |
יעד: תיבת-אישור-למידה אחת (מקובצת לפי זוג draft↔final) · ערוץ-כותב אחד + סטטוס "זורם-לכותב" אחד (review_status='approved') · הסרת applied_to_skill (אוצרות SKILL.md = מעשה-git ידני, לא כפתור) · כל artifact תלוי בזוג שלו (progressive disclosure) · תיקון 2 ה-KPI.
2.5 מתודולוגיה (/methodology — 5 טאבים)
2 משטחים · 8 ממצאים. מחלה: כללי-הכותב נערכים מ-2 משטחים שכותבים לאותה שורה appeal_type_rules(_global, …, 'universal') — מירוץ lost-update + פער-cache.
| ID | סוג | ממצא | file:line | תיקון |
|---|---|---|---|---|
| MET-1 | sync-gap | promote מבטל ['learning'] בלבד; /methodology (['methodology',cat], staleTime 30ש') תקוע אחרי אישור |
learning.ts:113; methodology.ts:26-28; app.py:4629-4631 | add-invalidation |
| MET-2 | duplication | discussion_rules['universal'] נכתב ב-2 מקומות (PUT מול promote) — כתיבה-שנייה דורסת בשקט |
discussion-rules-panel.tsx:35-36; learning-panel.tsx:138-139; app.py:4491-4495,4629; db.py:290 | fix-data |
| MET-3 | duplication | transition_phrases['universal'] — אותו מירוץ |
methodology/page.tsx:45-49; learning-panel.tsx:125-129; app.py:4631 | fix-data |
| MET-4 | confusing | universal מוצג כדלי-תוצאה אח, אך בפועל מוקדם (prepended) לכל התוצאות — אין מודל-מנטלי |
discussion-rules-panel.tsx:16-22; lessons.py:376-379 | clarify |
| MET-5 | dead | ז'רגון T15/T7 בטקסט-העזר — מזהי-משימות פנימיים חסרי-משמעות למפעיל |
methodology/page.tsx:48,55 | fix-data |
| MET-6 | wrong-data | עורך-צ'קליסטים מציג 5 סוגי-ערר ללא מיפוי איזה appeal_type צורך כל אחד |
content-checklists-panel.tsx:17-31; app.py:4414 | clarify |
| MET-7 | confusing | 3 מושגי-"כלל" מתערבבים (ratios/rules/checklists) ללא מודל-תחולה | methodology/page.tsx:16-19; block_writer.py:912-923 | clarify |
| MET-8 | sync-gap | סדר-callbacks ב-promote → toast-הצלחה אחרי invalidation לא-מספק | learning.ts:112-113; learning-panel.tsx:138-143 | add-invalidation |
יעד: /methodology = העורך הקנוני היחיד (כל כתיבה דרך PUT אחד, עם תג-מקור "ידני/מאומץ-מלמידה"); הלמידה מנותבת דרכו (לא כותבת-במקביל) ומבטלת את שני ה-caches; explainer-תחולה inline; קופי בעברית-פשוטה (בלי T7/T15).
2.6 תפעול + אבחון + הגדרות (/operations, /diagnostics, /settings, /skills)
5 משטחים · 6 ממצאים. מחלה: 4 משטחים שמריצים שאילתות-מקור זהות בלי cache משותף + נתונים-מתים/מטעים.
| ID | סוג | ממצא | file:line | תיקון |
|---|---|---|---|---|
| ADM-1 | sync-gap | halacha_backlog מוחזר מה-backend אך נזרק ב-frontend (אין בטיפוס, לא מרונדר) |
app.py:2253; system.ts:21-32; diagnostics/page.tsx | fix-data (לרנדר/להסיר) |
| ADM-2 | sync-gap | מוני-הלכות כפולים ב-/operations ו-/approvals ללא קישור-cache |
operations.ts:60; chair.ts:36; app.py:6520,5619-5633 | add-invalidation (consolidate) |
| ADM-3 | sync-gap | מוני-פסיקה-חסרה כפולים ב-/operations ו-/approvals |
operations.ts:60; app.py:6521,5636-5647 | add-invalidation (consolidate) |
| ADM-4 | confusing | court_fetch: "בתור" כולל failed, מטשטש pending מול queued |
operations/page.tsx:286-304; app.py:6562 | clarify |
| ADM-5 | sync-gap | עריכת env ב-Coolify לא מרעננת את ערך-ה-Container ולא מזהירה על staleness עד redeploy | env-var-row.tsx:76-96; settings.ts:135 | fix-data |
| ADM-6 | wrong-data | מוני-סוכנים מסכמים רק חברות-Paperclip זמינות → עומק-תור מוקטן בשקט כשחברה לא-נטענת | app.py:6667-6689; operations/page.tsx:461-465 | clarify (להציג חלקיות) |
יעד: /approvals=תיבת-ההחלטות (כל גייט נפעל רק כאן; /operations מצביע ולא משכפל) · /operations=משטח-קריאה יחיד (בולע את /diagnostics, מרנדר halacha_backlog, מתקן queued/pending, מציג חלקיות) · /settings=תצורה (עריכת-env שמשלימה-את-עצמה: סימון-staleness + redeploy באותה שורה).
3. עדכוני-ספ מומלצים (מתועדים ב-X17)
הסריקה זיהתה ש-X6 לא מכסה את שכבת-ה-UI-state, וש-07-learning מסנקצן בטעות שני-ערוצים. ההמלצות (כל אחת מגובת-מקורות ב-X17):
- X6 — invariants חדשים בשכבת-UI: (א) aggregate-נגזר = מקור-אמת; כל mutation לטבלת-מקור חייב לבטל את ה-queryKey שלו; אסור מונה-מתחרה client-side. (ב) למונה-גייט בעלים-משטח-יחיד; אחרים מצביעים. (ג) שדה ב-OpenAPI-response — לרנדר או להסיר (אסור לזרוק בשקט). (ד) אסור להציג aggregate מדויק כש-partial-failure השמיט תורם — להציג חלקיות.
- 07-learning §0.4/§0.6: שער-אישור אחד, טרנזקציית-כותב אחת,
applied_to_skillמוסר; לקחים-מאושרים נכתבים רק דרך מסלול-המתודולוגיה היחיד. - 00-constitution G2 "הפרות ידועות": להוסיף את תאום-המתודולוגיה (
discussion_rules['universal']נכתב ע"י PUT וגם promote).
4. הבא — בקלוג-איחוד (פאזה F)
מסמך זה ממפה ומאבחן; הוא אינו משנה קוד. הבקלוג המתועדף (TaskMaster, מקושר לכל ממצא) נגזר ב-#127.6 ומחולק ל-3 גלים:
- גל-1 (זול, גבוה-ערך): הוספת-invalidation ל-16 פערי-הסנכרון + תיקון 6 הנתונים-השגויים + מחיקת המתים. תיקון מקומי, אין הגירת-IA.
- גל-2 (איחוד-משטחים): תיבת-אישור אחת · ערוץ-למידה אחד (הסרת
applied_to_skill, איחוד שני-השערים) ·/operations⊇/diagnostics. - גל-3 (ניווט): הורדת
/feedbackמהראשי · שמות-חיפוש עקביים · X17 ל-canonical.
הכרעת-יו"ר נדרשת לפני גל-2/3 (3א — עוצרים על המסמך).