From 044de2c0f06871d9620b0421fe69711f6ceae2ad Mon Sep 17 00:00:00 2001 From: Chaim Date: Sun, 28 Jun 2026 21:45:56 +0000 Subject: [PATCH] =?UTF-8?q?feat(learning):=20graduated=20gate=20=E2=80=94?= =?UTF-8?q?=20panel-consensus=20style=20lessons=20auto-flow=20to=20writer?= =?UTF-8?q?=20(P0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The voice-learning panel produced 81 vetted style lessons — all stuck at review_status='proposed' with 0 ever approved — so the writer (which reads only 'approved') received NONE of them. The system captured learning but never let it flow. Chair decision (2026-06-28): a GRADUATED gate by content risk. - STYLE lessons (categories style/structure/lexicon/tabular) the 2/2 panel kept → created as review_status='approved' → flow to the writer immediately, reversibly (chair vetoes in /training). The deepseek+gemini panel only emits style_method and only on 2/2 consensus, so this is exactly the gate's criterion; substance is already filtered out and skipped, and routes through the strict halacha gate. - SUBSTANCE (halacha/precedent/fact) stays a HARD chair gate — unchanged. style_lesson_panel.py: _review_status_for(category) sets the gate explicitly (approved for _STYLE_CATEGORIES, else proposed); the apply loop passes it to db.add_decision_lesson (which already accepts review_status — no DB change). Spec: INV-LRN1 rewritten as the graduated gate (hard for substance; reversible auto-flow for consensus style — still "under user control" via veto, per NCSC/CEPEJ); §0.6 updated to match. A one-time backfill of the 81 existing panel style lessons to 'approved' runs separately (DB, post-merge). Invariants: INV-LRN1 (amended — graduated), INV-LRN5 (style-only, substance never auto-flows), G10 (human control preserved as reversible veto). Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/spec/07-learning.md | 17 ++++++++--------- scripts/style_lesson_panel.py | 23 +++++++++++++++++++++-- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/docs/spec/07-learning.md b/docs/spec/07-learning.md index 8929e67..6786cac 100644 --- a/docs/spec/07-learning.md +++ b/docs/spec/07-learning.md @@ -62,9 +62,9 @@ 3. **בדיקת-ציטוטים** — `extract_internal_citations` מקשר את הפסיקה שההחלטה מצטטת לספרייה; כל ציטוט שאינו בספרייה **מסומן אוטומטית** כ-`missing_precedent` (open) להעלאה ע"י היו"ר. 4. הציטוטים-המקושרים מזינים את **לולאת-ה-corroboration** (X11): ציטוט-נכנס מההחלטה שלנו מחזק את ההלכות של התקדים המצוטט (`corroboration_rebuild`). ואז שני שלבים אוטומטיים נפרדים (`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`). -שני הפאנלים **הפיכים** (גיבוי-CSV ל-`data/audit/`) ומסלימים מחלוקות. ההטמעה הסופית ל-`SKILL.md`/`legal-decision-lessons.md` נשארת **אישור-יו"ר ידני** (INV-LRN1/G10) — הפאנל יוצר *הצעות* בלבד. +שני הפאנלים **הפיכים** (גיבוי-CSV ל-`data/audit/`) ומסלימים מחלוקות. ההטמעה ל-`SKILL.md`/`legal-decision-lessons.md` ולכל **מהות** נשארת **אישור-יו"ר ידני קשיח** (INV-LRN1/G10); לקחי-**סגנון** בקונצנזוס זורמים אוטומטית-והפיך לכותב. --- @@ -162,13 +162,12 @@ ## 3. Invariants של התחום -### INV-LRN1: עדכון-ידע דורש אישור-יו"ר ידני — אין auto-commit (governance →G10) -**כלל:** מנגנוני-הלמידה (Hermes, ניתוח-פידבק שבועי) **מציעים בלבד**. כל שינוי ב- -[SKILL.md](../../skills/decision/SKILL.md) או ב-[legal-decision-lessons.md](../legal-decision-lessons.md) -מחייב **בחינה ואישור ידניים של היו"ר/חיים** ואז commit ידני — **לעולם לא auto-committed**. -Hermes כותב comment + `decision_lesson`, לא קבצים; ה-CEO השבועי כותב לקובץ אך הצעותיו -מאומתות ידנית לפני קיבוע. זהו פֶּאֶט של [INV-G10](00-constitution.md#inv-g10-המערכת-מסייעת--שערים-אנושיים-הם-invariant) -על שכבת-הידע: גם הלמידה כפופה לשיקול-הדעת האנושי. +### INV-LRN1: עדכון-ידע דורש שער-יו"ר — **שער מדורג** לפי סיכון (governance →G10) +**כלל (מעודכן 2026-06-28, הכרעת-יו"ר):** השער **מדורג לפי סיכון-התוכן**, לא אחיד: +- **מהות** (הלכה / תקדים / עובדה / כל שינוי ב-[SKILL.md](../../skills/decision/SKILL.md) או ב-[legal-decision-lessons.md](../legal-decision-lessons.md)) → **שער-קשיח**: בחינה ואישור ידניים של היו"ר/חיים ואז 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, לא אישור-מראש על כל פריט). + +זהו פֶּאֶט של [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; never replace human judgment) · Council of Europe / CEPEJ (2018, under user control) · Federal Judicial Center — *Judicial Writing Manual* (2d ed.) | סטטוס: verified diff --git a/scripts/style_lesson_panel.py b/scripts/style_lesson_panel.py index 2533298..d431a7b 100644 --- a/scripts/style_lesson_panel.py +++ b/scripts/style_lesson_panel.py @@ -110,6 +110,19 @@ def _category(change: dict) -> str: 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 ── 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"])]) written = 0 + approved = 0 for r in fresh: + cat = _category(r["_change"]) + rs = _review_status_for(cat) await db.add_decision_lesson( UUID(corpus_id), lesson_text=_lesson_text(r["_change"]), - category=_category(r["_change"]), + category=cat, source="panel:deepseek+gemini", created_by="panel", + review_status=rs, ) written += 1 + approved += (rs == "approved") 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"{chair} escalated to chair · {len(substance)} substance skipped") print(f"backup → {backup}")