Merge pull request 'feat(learning): graduated gate — panel-consensus style lessons auto-flow to writer (P0)' (#341) from worktree-graduated-gate into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 7s
G12 Leak-Guard / leak-guard (push) Successful in 4s
Lint — undefined names / undefined-names (push) Successful in 10s

This commit was merged in pull request #341.
This commit is contained in:
2026-06-28 21:46:29 +00:00
2 changed files with 29 additions and 11 deletions

View File

@@ -62,9 +62,9 @@
3. **בדיקת-ציטוטים**`extract_internal_citations` מקשר את הפסיקה שההחלטה מצטטת לספרייה; כל ציטוט שאינו בספרייה **מסומן אוטומטית** כ-`missing_precedent` (open) להעלאה ע"י היו"ר. 3. **בדיקת-ציטוטים**`extract_internal_citations` מקשר את הפסיקה שההחלטה מצטטת לספרייה; כל ציטוט שאינו בספרייה **מסומן אוטומטית** כ-`missing_precedent` (open) להעלאה ע"י היו"ר.
4. הציטוטים-המקושרים מזינים את **לולאת-ה-corroboration** (X11): ציטוט-נכנס מההחלטה שלנו מחזק את ההלכות של התקדים המצוטט (`corroboration_rebuild`). 4. הציטוטים-המקושרים מזינים את **לולאת-ה-corroboration** (X11): ציטוט-נכנס מההחלטה שלנו מחזק את ההלכות של התקדים המצוטט (`corroboration_rebuild`).
ואז שני שלבים אוטומטיים נפרדים (`run-learning` / `run-halacha`) המעירים worker מקומי (claude/DeepSeek/Gemini מקומיים בלבד): ואז שני שלבים אוטומטיים נפרדים (`run-learning` / `run-halacha`) המעירים worker מקומי (claude/DeepSeek/Gemini מקומיים בלבד):
- **למידה:** `ingest_final_version` (Opus distillation) → **פאנל-סגנון דו-סוכני** (DeepSeek+Gemini, "למידה כפולה") שמצביע על כל לקח-style_method; הסכמה 2/2 → `decision_lesson` (`source=panel:deepseek+gemini`); פיצול → ליו"ר. - **למידה:** `ingest_final_version` (Opus distillation) → **פאנל-סגנון דו-סוכני** (DeepSeek+Gemini, "למידה כפולה") שמצביע על כל לקח-style_method; הסכמה 2/2 → `decision_lesson` (`source=panel:deepseek+gemini`) **שזורם אוטומטית לכותב** כ-`approved` (שער-מדורג, INV-LRN1) — הפיך (veto-יו"ר ב-/training); פיצול → ליו"ר.
- **הלכות:** `extract_internal_citations``precedent_extract_halachot``corroboration_rebuild`**פאנל-הלכות תלת-סוכני** (`halacha_panel_approve.py --apply`). - **הלכות:** `extract_internal_citations``precedent_extract_halachot``corroboration_rebuild`**פאנל-הלכות תלת-סוכני** (`halacha_panel_approve.py --apply`).
שני הפאנלים **הפיכים** (גיבוי-CSV ל-`data/audit/`) ומסלימים מחלוקות. ההטמעה הסופית ל-`SKILL.md`/`legal-decision-lessons.md` נשארת **אישור-יו"ר ידני** (INV-LRN1/G10) — הפאנל יוצר *הצעות* בלבד. שני הפאנלים **הפיכים** (גיבוי-CSV ל-`data/audit/`) ומסלימים מחלוקות. ההטמעה ל-`SKILL.md`/`legal-decision-lessons.md` ולכל **מהות** נשארת **אישור-יו"ר ידני קשיח** (INV-LRN1/G10); לקחי-**סגנון** בקונצנזוס זורמים אוטומטית-והפיך לכותב.
### 0.7 מדד-ההכללה הפרוספקטיבי (held-out trend — "מסלול A") ### 0.7 מדד-ההכללה הפרוספקטיבי (held-out trend — "מסלול A")
**השאלה שזה עונה:** האם הלמידה באמת *מכלילה* — כלומר משפרת טיוטות של תיקים **שלא נלמדו** — ולא רק "משננת" תיקים שכבר ראינו. מדד-מרחק-הסגנון (שלב [7]) על תיק שלקחיו כבר הוטמעו אינו held-out; מדידה רטרואקטיבית בלתי-אפשרית כי הלקחים נשמרים `appeal_type_rules` (`universal`) **ללא תיוג-מקור** → אין leave-one-out. לכן המדידה **פרוספקטיבית**: נלכדת ברגע היחיד שבו היא נקייה. **השאלה שזה עונה:** האם הלמידה באמת *מכלילה* — כלומר משפרת טיוטות של תיקים **שלא נלמדו** — ולא רק "משננת" תיקים שכבר ראינו. מדד-מרחק-הסגנון (שלב [7]) על תיק שלקחיו כבר הוטמעו אינו held-out; מדידה רטרואקטיבית בלתי-אפשרית כי הלקחים נשמרים `appeal_type_rules` (`universal`) **ללא תיוג-מקור** → אין leave-one-out. לכן המדידה **פרוספקטיבית**: נלכדת ברגע היחיד שבו היא נקייה.
@@ -185,13 +185,12 @@
## 3. Invariants של התחום ## 3. Invariants של התחום
### INV-LRN1: עדכון-ידע דורש אישור-יוידני — אין auto-commit (governance →G10) ### INV-LRN1: עדכון-ידע דורש שער-יו— **שער מדורג** לפי סיכון (governance →G10)
**כלל:** מנגנוני-הלמידה (Hermes, ניתוח-פידבק שבועי) **מציעים בלבד**. כל שינוי ב- **כלל (מעודכן 2026-06-28, הכרעת-יו"ר):** השער **מדורג לפי סיכון-התוכן**, לא אחיד:
[SKILL.md](../../skills/decision/SKILL.md) או ב-[legal-decision-lessons.md](../legal-decision-lessons.md) - **מהות** (הלכה / תקדים / עובדה / כל שינוי ב-[SKILL.md](../../skills/decision/SKILL.md) או ב-[legal-decision-lessons.md](../legal-decision-lessons.md)) → **שער-קשיח**: בחינה ואישור ידניים של היו"ר/חיים ואז commit ידני — **לעולם לא auto-committed**. פאנל-ההלכות התלת-סוכני מציע בלבד.
מחייב **בחינה ואישור ידניים של היו"ר/חיים** ואז commit ידני — **לעולם לא auto-committed**. - **סגנון** (`decision_lessons` בקטגוריות style/structure/lexicon/tabular, וכן discussion_rules / transition_phrases / anti_patterns) שעבר **קונצנזוס-פאנל 2/2****זורם אוטומטית לכותב** (`review_status='approved'`), **הפיך**: היו"ר רואה ויכול **לבטל בדיעבד** ב-/training. זהו שינוי-קול נמוך-סיכון (טהור-מהות לפי INV-LRN5), בקרת-איכות מובנית (2 מודלים), והפיכוּת — ולכן עדיין "תחת בקרת-המשתמש" במובן NCSC/CEPEJ (veto, לא אישור-מראש על כל פריט).
Hermes כותב comment + `decision_lesson`, לא קבצים; ה-CEO השבועי כותב לקובץ אך הצעותיו
מאומתות ידנית לפני קיבוע. זהו פֶּאֶט של [INV-G10](00-constitution.md#inv-g10-המערכת-מסייעת--שערים-אנושיים-הם-invariant) זהו פֶּאֶט של [INV-G10](00-constitution.md#inv-g10-המערכת-מסייעת--שערים-אנושיים-הם-invariant) על שכבת-הידע: הלמידה כפופה לשיקול-הדעת האנושי — קשיח למהות, הפיך-veto לסגנון. **מימוש:** `scripts/style_lesson_panel.py:_review_status_for` קובע `approved` לקטגוריות-סגנון בקונצנזוס, `proposed` אחרת; הכותב צורך רק `approved` ([db.get_recent_decision_lessons]).
על שכבת-הידע: גם הלמידה כפופה לשיקול-הדעת האנושי.
**מקורות:** NCSC/JTC — *Principles & Practices for AI Use in Courts* (human-in-the-loop; **מקורות:** NCSC/JTC — *Principles & Practices for AI Use in Courts* (human-in-the-loop;
never replace human judgment) · Council of Europe / CEPEJ (2018, under user control) · never replace human judgment) · Council of Europe / CEPEJ (2018, under user control) ·
Federal Judicial Center — *Judicial Writing Manual* (2d ed.) | סטטוס: verified Federal Judicial Center — *Judicial Writing Manual* (2d ed.) | סטטוס: verified

View File

@@ -110,6 +110,19 @@ def _category(change: dict) -> str:
return "style" return "style"
# Graduated gate (INV-LRN1, chair decision 2026-06-28): a STYLE lesson the panel
# kept by 2/2 consensus flows straight to the writer (review_status='approved'),
# reversibly — the chair can veto it in /training. SUBSTANCE (halacha/precedent/
# fact) never reaches here (it's filtered to `substance` and skipped, and routes
# through the strict 3-judge halacha gate), so every category this panel emits is
# style and auto-approves. The constant keeps the gate explicit and future-proof.
_STYLE_CATEGORIES = frozenset({"style", "structure", "lexicon", "tabular"})
def _review_status_for(category: str) -> str:
return "approved" if category in _STYLE_CATEGORIES else "proposed"
# ── two judges, one signature: (system, user) -> dict|None ── # ── two judges, one signature: (system, user) -> dict|None ──
async def judge_deepseek(client: httpx.AsyncClient, system: str, user: str) -> dict | None: async def judge_deepseek(client: httpx.AsyncClient, system: str, user: str) -> dict | None:
@@ -323,18 +336,24 @@ async def main(args: argparse.Namespace) -> int:
_lesson_text(r["_change"])]) _lesson_text(r["_change"])])
written = 0 written = 0
approved = 0
for r in fresh: for r in fresh:
cat = _category(r["_change"])
rs = _review_status_for(cat)
await db.add_decision_lesson( await db.add_decision_lesson(
UUID(corpus_id), UUID(corpus_id),
lesson_text=_lesson_text(r["_change"]), lesson_text=_lesson_text(r["_change"]),
category=_category(r["_change"]), category=cat,
source="panel:deepseek+gemini", source="panel:deepseek+gemini",
created_by="panel", created_by="panel",
review_status=rs,
) )
written += 1 written += 1
approved += (rs == "approved")
chair = cc["split"] + cc["incomplete"] chair = cc["split"] + cc["incomplete"]
print(f"\nAPPLIED (reversible): wrote {written} decision_lesson proposals " print(f"\nAPPLIED (reversible): wrote {written} decision_lessons "
f"({approved} auto-approved style → writer; graduated gate) "
f"(source=panel:deepseek+gemini) · {skipped_dup} כפילויות דולגו · " f"(source=panel:deepseek+gemini) · {skipped_dup} כפילויות דולגו · "
f"{chair} escalated to chair · {len(substance)} substance skipped") f"{chair} escalated to chair · {len(substance)} substance skipped")
print(f"backup → {backup}") print(f"backup → {backup}")