feat(learning): שער-אישור ל-decision_lessons — רק לקח מאושר זורם לכותב (INV-LRN1, #126) #202

Merged
chaim merged 1 commits from worktree-lesson-approval-gate into main 2026-06-11 18:14:39 +00:00
Owner

הקשר

אודיט #122 חשף דליפה: לקחי-הפאנל (decision_lessons) זרמו לכותב אוטומטית (block_writer.py:927get_recent_decision_lessons) ללא סינון-אישור — הפאנל כתב, הכותב צרך מיד, בעקיפת שער-היו"ר (INV-LRN1/G10). מה שהיו"ר אישר ב-promote הלך לערוץ נפרד (appeal_type_rules). כלומר תוכן לא-מאושר השפיע על הכתיבה.

השינוי — שער-אישור מפורש

  • review_status (proposed/approved/rejected) ל-decision_lessons (SCHEMA_V34, ADD COLUMN IF NOT EXISTS).
  • get_recent_decision_lessons (צרכן-הכותב) מחזיר רק approved — זה הגייט.
  • הפאנל (style_lesson_panel) כותב proposed (ברירת-מחדל) → לא זורם עד אישור.
  • לקח שהיו"ר מקליד ידנית ב-/training = approved מיידית (מדלג על שער-ההצעה — חתימת-יו"ר ישירה).
  • UI (lessons-tab.tsx, טאב "קורפוס" ב-/training): תג-סטטוס (ממתין לאישור/מאושר · זורם לכותב/נדחה) + כפתורי אשר / דחה / בטל-אישור.

הכרעת-יו"ר (2026-06-11)

כל 41 הלקחים שקדמו לשער מתאפסים ל-proposedשום לקח לא זורם עד אישור מפורש. ברירת-המחדל של העמודה (DEFAULT 'proposed') מיישמת זאת אוטומטית על הקיימים.

Invariants

  • INV-LRN1 / G10 (מקיים) — עדכון-ידע לערוץ-הכותב דורש אישור-יו"ר מפורש; אין auto-commit.
  • INV-LRN5 (נשמר) — substance ממילא מסונן בפאנל; השער על style_method בלבד.
  • G1 (מקיים) — סינון-במקור (get_recent), לא תיקון-בקריאה אצל הכותב.
  • G2 (מקיים) — אותו פנקס decision_lessons; אין מסלול מקביל.

בדיקה

  • backend: py_compile עובר; _run_schema_migrations (db.py:55, בתוך get_pool) מבטיח שהעמודה קיימת לפני כל שאילתה (idempotent).
  • frontend: eslint נקי; tsc --noEmit עובר (ה-build המלא נכשל רק על symlink־node_modules ב-worktree — מגבלת Turbopack, לא קוד).
  • post-deploy: להריץ npm run api:types (review_status נוסף ל-payload; הטיפוסים הידניים ב-training.ts כבר מעודכנים).

ref: #122 · #126 · data/audit/learning-loop-activity-20260611.md

🤖 Generated with Claude Code

## הקשר אודיט #122 חשף **דליפה**: לקחי-הפאנל (`decision_lessons`) זרמו לכותב אוטומטית (`block_writer.py:927` → `get_recent_decision_lessons`) **ללא סינון-אישור** — הפאנל כתב, הכותב צרך מיד, בעקיפת שער-היו"ר (INV-LRN1/G10). מה שהיו"ר אישר ב-`promote` הלך לערוץ נפרד (`appeal_type_rules`). כלומר תוכן לא-מאושר השפיע על הכתיבה. ## השינוי — שער-אישור מפורש - **`review_status`** (`proposed`/`approved`/`rejected`) ל-`decision_lessons` (SCHEMA_V34, `ADD COLUMN IF NOT EXISTS`). - **`get_recent_decision_lessons`** (צרכן-הכותב) מחזיר **רק `approved`** — זה הגייט. - הפאנל (`style_lesson_panel`) כותב `proposed` (ברירת-מחדל) → לא זורם עד אישור. - לקח שהיו"ר מקליד ידנית ב-/training = `approved` מיידית (מדלג על שער-ההצעה — חתימת-יו"ר ישירה). - **UI** ([lessons-tab.tsx](web-ui/src/components/training/lessons-tab.tsx), טאב "קורפוס" ב-/training): תג-סטטוס (`ממתין לאישור`/`מאושר · זורם לכותב`/`נדחה`) + כפתורי **אשר / דחה / בטל-אישור**. ## הכרעת-יו"ר (2026-06-11) כל 41 הלקחים שקדמו לשער מתאפסים ל-`proposed` — **שום לקח לא זורם עד אישור מפורש**. ברירת-המחדל של העמודה (`DEFAULT 'proposed'`) מיישמת זאת אוטומטית על הקיימים. ## Invariants - **INV-LRN1 / G10 (מקיים)** — עדכון-ידע לערוץ-הכותב דורש אישור-יו"ר מפורש; אין auto-commit. - **INV-LRN5 (נשמר)** — substance ממילא מסונן בפאנל; השער על style_method בלבד. - **G1 (מקיים)** — סינון-במקור (`get_recent`), לא תיקון-בקריאה אצל הכותב. - **G2 (מקיים)** — אותו פנקס `decision_lessons`; אין מסלול מקביל. ## בדיקה - backend: `py_compile` עובר; `_run_schema_migrations` (db.py:55, בתוך `get_pool`) מבטיח שהעמודה קיימת לפני כל שאילתה (idempotent). - frontend: `eslint` נקי; `tsc --noEmit` עובר (ה-build המלא נכשל רק על symlink־node_modules ב-worktree — מגבלת Turbopack, לא קוד). - **post-deploy:** להריץ `npm run api:types` (review_status נוסף ל-payload; הטיפוסים הידניים ב-`training.ts` כבר מעודכנים). ref: #122 · #126 · data/audit/learning-loop-activity-20260611.md 🤖 Generated with [Claude Code](https://claude.com/claude-code)
chaim added 1 commit 2026-06-11 18:14:27 +00:00
feat(learning): שער-אישור ל-decision_lessons — רק לקח מאושר זורם לכותב (INV-LRN1, #126)
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 12s
4b01283e3b
אודיט #122 חשף שלקחי-הפאנל (decision_lessons) זרמו לכותב אוטומטית
(block_writer → get_recent_decision_lessons) ללא סינון-אישור — הפאנל כתב,
והכותב צרך מיד, בעקיפת שער-היו"ר (INV-LRN1/G10). מנגד, מה שהיו"ר אישר ב-promote
הלך לערוץ נפרד (appeal_type_rules). תוצאה: דליפה — תוכן לא-מאושר השפיע על הכתיבה.

התיקון — שער-אישור מפורש:
- עמודת review_status (proposed|approved|rejected) ל-decision_lessons (SCHEMA_V34).
- get_recent_decision_lessons (צרכן-הכותב) מחזיר רק review_status='approved'.
- הפאנל (style_lesson_panel) כותב 'proposed' (ברירת-מחדל) → לא זורם עד אישור.
- לקח שהיו"ר מקליד ידנית ב-/training = 'approved' מיידית (מדלג על שער-ההצעה).
- UI (lessons-tab, טאב "קורפוס" ב-/training): תג-סטטוס + כפתורי אשר/דחה/בטל-אישור.

הכרעת-יו"ר (2026-06-11): כל הלקחים שקדמו לשער (41) מתאפסים ל-'proposed' —
שום לקח לא זורם עד אישור מפורש (ברירת-המחדל של העמודה מיישמת זאת על הקיימים).

Invariants:
- INV-LRN1 / G10 (מקיים) — עדכון-ידע לערוץ-הכותב דורש אישור-יו"ר מפורש; אין auto-commit.
- INV-LRN5 (נשמר) — substance ממילא מסונן בפאנל; השער הוא על style_method בלבד.
- G1 (מקיים) — סינון-במקור (get_recent) ולא תיקון-בקריאה אצל הכותב.
- G2 (מקיים) — אותו פנקס decision_lessons; אין מסלול מקביל.

api:types: להריץ npm run api:types אחרי deploy (review_status נוסף ל-payload;
הטיפוסים הידניים ב-training.ts כבר מעודכנים, tsc עובר).

ref: #122 · #126 · data/audit/learning-loop-activity-20260611.md

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
chaim scheduled this pull request to auto merge when all checks succeed 2026-06-11 18:14:36 +00:00
chaim merged commit 24480950f1 into main 2026-06-11 18:14:39 +00:00
chaim deleted branch worktree-lesson-approval-gate 2026-06-11 18:14:41 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: ezer-mishpati/legal-ai#202