Commit Graph

1189 Commits

Author SHA1 Message Date
6f60dc7a14 Merge remote-tracking branch 'origin/main' into rebase-359
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 4s
Lint — undefined names / undefined-names (pull_request) Successful in 10s
# Conflicts:
#	docs/spec/04-analysis-writing.md
2026-06-30 12:20:57 +00:00
99574f0eba Merge pull request 'fix(export): תיקוני-תבנית DOCX — חתימות לסוף, א–ד ללא נתונים, "החלטה"=כותרת (#205)' (#355) from worktree-agent-a4e6a6d273c4c3379 into main
Some checks failed
G12 Leak-Guard / leak-guard (push) Has been cancelled
Lint — undefined names / undefined-names (push) Has been cancelled
Build & Deploy / build-and-deploy (push) Has been cancelled
2026-06-30 12:18:41 +00:00
085de937da Merge pull request 'feat(analysis): סיכום-מנהלים מזוקק של טענות הצדדים — מסמך הכנה לדיון (#202, WS3)' (#358) from worktree-agent-abc25c98bc1092fa3 into main
Some checks failed
G12 Leak-Guard / leak-guard (push) Has been cancelled
Build & Deploy / build-and-deploy (push) Has been cancelled
Lint — undefined names / undefined-names (push) Has been cancelled
2026-06-30 12:18:09 +00:00
9e6a441076 Merge remote-tracking branch 'origin/main' into rebase-358
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 3s
Lint — undefined names / undefined-names (pull_request) Successful in 10s
# Conflicts:
#	docs/spec/04-analysis-writing.md
2026-06-30 12:16:41 +00:00
eb0653fb80 Merge pull request 'feat(calibration): כיול-אמפירי model×effort מול הסופיים (#208)' (#360) from worktree-agent-a5a22be0318670871 into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 1m27s
G12 Leak-Guard / leak-guard (push) Successful in 5s
Lint — undefined names / undefined-names (push) Successful in 10s
2026-06-30 12:15:46 +00:00
f935f166a9 feat(calibration): כיול-אמפירי model×effort מול הסופיים (#208)
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 3s
Lint — undefined names / undefined-names (pull_request) Successful in 10s
A/B harness שמכייל את ה-effort הנעוץ per-בלוק (#204) מול הסופיים של דפנה:
מייצר מחדש כל בלוק דרך מסלול-הייצור (write_block(effort_override=…) →
claude_session.query → claude -p, Opus 4.8, מקומי-בלבד) ומודד מול הסקשן
המתאים בסופי דרך style_distance.block_distance_to_final (change_percent,
anti_pattern_total, golden-ratio deviation, composite distance). ממליץ
per-בלוק על ה-effort הקרוב-ביותר לסופי.

- scripts/calibrate_effort.py — ההארנס (מודל eval_retrieval.py): --self-test
  (offline, מוכיח מדידה+המלצה, אפס DB/CLI) · --dry-run · --efforts/--blocks/
  --case/--repeats. דוח data/eval/effort-calibration-<ts>.{json,md} עם
  גודל-מדגם בולט — עדות-כיוון, לא רגרסיה (מעט סופיים-עלויים).
- style_distance.py — block_distance_to_final + split_final_by_section
  (מקור-מדידה יחיד, G2; reuse compute_diff_stats/count_anti_patterns/chunker).
- block_writer.py — write_block(effort_override=) להזרקת effort per-קריאה
  בלי לדרוס את ברירות-המחדל הנעוצות; רושם את ה-effort האפקטיבי.
- scripts/SCRIPTS.md — ערך חדש.

Invariants: G8 (eval-harness — מדידה אמפירית, לא הנחה) · G2 (reuse של
style_distance/learning_loop — אין מסלול-מדד מקביל) · claude_session
local-only (reference_claude_generation_path) · INV-LRN4/5 (השוואה מול
הסופי, מדידת-סגנון; אין מהות-תיק נגררת). אומת: --self-test 14/14 PASS.
הריצה החיה host-only (claude CLI) — לא ניתנת-להרצה ב-worktree/קונטיינר.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 12:13:43 +00:00
33b36e38ee Merge pull request 'feat(analysis): analyze_protocol — ניתוח פרוטוקול-דיון השוואתי (WS4 #203)' (#357) from worktree-agent-aefd5594d532d9f06 into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 1m32s
G12 Leak-Guard / leak-guard (push) Successful in 4s
Lint — undefined names / undefined-names (push) Successful in 10s
2026-06-30 12:12:05 +00:00
8d704e6e40 Merge remote-tracking branch 'origin/main' into rebase-357
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 4s
Lint — undefined names / undefined-names (pull_request) Successful in 10s
# Conflicts:
#	mcp-server/src/legal_mcp/services/db.py
2026-06-30 12:09:49 +00:00
faee621f0b Merge pull request 'feat(drafting): טיוטת-ביניים דטרמיניסטית — Opus 4.8 + effort per-בלוק (#204)' (#356) from worktree-agent-a0d2502e8308bc27c into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 1m27s
G12 Leak-Guard / leak-guard (push) Successful in 4s
Lint — undefined names / undefined-names (push) Successful in 10s
2026-06-30 12:03:42 +00:00
8ece726b8d Merge pull request 'feat(documents): מסמך-עיקרי — is_primary נגזר + רשימה קנונית (#200)' (#354) from worktree-agent-a59ef17c17ecd1d31 into main
Some checks failed
Build & Deploy / build-and-deploy (push) Has been cancelled
G12 Leak-Guard / leak-guard (push) Has been cancelled
Lint — undefined names / undefined-names (push) Has been cancelled
2026-06-30 12:03:01 +00:00
aa2548ff5d feat(analysis): סיכום-מנהלים מזוקק של טענות הצדדים — מסמך הכנה לדיון (#202, WS3)
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 4s
Lint — undefined names / undefined-names (pull_request) Successful in 10s
מסמך פרוזה נפרד מטיוטת-הביניים (החלטת-יו"ר): תמצית מוקפדת של טענות+תשובות
להכנת היו"ר לדיון. נגזר מ-legal_arguments/claims הקיימים — אותו מקור-אמת,
ללא חילוץ-מחדש (G2). מתוחם לטענות-התיק בלבד (INV-AH).

- כלי-MCP חדש summarize_party_claims (drafting.py + server.py); ייצור עובר
  claude_session נעוץ Opus 4.8 + effort=high (זיקוק/סינתזה); local-only.
- שירות party_claims_summary.py: בחירת-מקור arguments→claims, פרומפט מעוגן-מקור,
  שמירה ל-data/cases/{n}/documents/research/ (git + S3).
- ייצוא DOCX בסגנון-תבנית דפנה (build_party_claims_summary_docx) + endpoints
  read/download/export-docx ב-web/app.py (מגישים בלבד — אין claude CLI בקונטיינר).
- _next_version הוכלל ל-prefix-scoped (תאימות-לאחור) למניעת התנגשות-גרסאות.
- ספ 04-analysis-writing.md §1.3 + 8 בדיקות אופליין (מקור/נעיצת-מודל/markdown→docx).

Invariants: G2 (מקור-אמת יחיד, בלי מסלול מקביל) · X9 TOOL1/TOOL4 (envelope +
extract↔serve) · INV-AH (עיגון-מקור, abstention על טענה לא-ברורה) ·
claude_session local-only · G9 (provenance — נשמר durably + git/S3).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 11:22:20 +00:00
9ef0547997 docs(spec): WS7 — reconcile 01/02/03/04/06 + gap-audit; verify 7 workflow-redesign leaks closed (#207)
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 3s
Lint — undefined names / undefined-names (pull_request) Successful in 10s
WS7 of the workflow-redesign initiative required closing 7 known leaks along
the way. Cross-code audit verified ALL 7 were already closed in prior cycles
(FU-1/4/5/6/7 + IA waves); the spec still carried stale "known violation" text.
This PR aligns the spec to actual code state and verifies each closure with a
test. No new code path created — this is a spec-alignment audit, not a re-solve.

7 leaks → status (all closed/gated, each with a test):
1. cross-corpus halachot (#56, GAP-10/FU-4) — cl.source_kind in halacha_filters
   (db.py:7516,7519); test_precedent_corpus_isolation.py
2. invisible halacha backlog (GAP-14/FU-5) — health halacha_backlog
   (app.py:2352-2364) + extraction_status/halachot_pending
3. no eval harness (GAP-11/FU-5, G8) — scripts/eval_retrieval.py
   (P/R/MRR/nDCG vs gold-set+baseline); --self-test ALL PASS
4. export gate not hard-block (GAP-15/FU-6, INV-EX3) — export_docx checks
   qa_run_exists + get_critical_qa_failures before exporter (drafting.py:462-494);
   test_export_qa_gate.py
5. metadata on internal path (GAP-02/FU-1, INV-ING3) — unified ingest.ingest_document
   queues metadata+halacha together (ingest.py:233-234); test_unified_ingest.py
6. DOCX creep to source-of-truth (GAP-17/FU-7, INV-EX1) — active_draft_path is
   revision-anchor only; drift caught by cases.blocks_stale flag (V22)
7. UI cache-invalidation (GAP-33/FU-10) — qc.invalidateQueries on mutations

Also added forward-pointer notes for the workflow-redesign additions owned by
sibling tasks (02 documents is_primary/doc_category → #200; 04 re-analysis /
summarize_party_claims / analyze_protocol → #200/#202/#203), kept additive to
avoid line conflicts. block-schema.md interim/template edits deferred to #204/#205.

Invariants: maintains G2 (single source of truth, no parallel path — all leak
closures extend the canonical path), G8 (eval harness now exists), G10 (human
gates visible: halacha backlog + hard export gate), INV-ING3 (unified metadata
queue), INV-EX1 (DOCX is derived; blocks_stale drift flag), INV-RET1/G5 (#56
cross-corpus halacha isolation).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 11:22:11 +00:00
24e3e2fe80 feat(analysis): analyze_protocol — comparative hearing-protocol analysis (WS4 #203)
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 4s
Lint — undefined names / undefined-names (pull_request) Successful in 10s
מנתח פרוטוקול-דיון מול כתבי-הטענות: אילו טענות ירדו/חוזקו/עלו-חדשות + חידוד
שאלות משפטיות, ומחלץ נתוני כותרת (א–ד). התוצאה נכנסת לידע-התיק.

- protocol_analyzer.py — ניתוח השוואתי דרך claude_session (Opus 4.8, effort=high,
  מקומי בלבד); שער anti-hallucination (quote-or-retract) ב-_normalize_change;
  חילוץ א–ד + הזנת hearing_date חזרה ל-cases (לא דורס קלט-יו"ר).
- claims_extractor: protocol → claim_type='protocol'; extract_claims קולט protocol.
- block_writer._build_claims_context מחריג claim_type='protocol' מבלוק ז (INV-WR4).
- db: טבלת protocol_analysis (V47, idempotent per-doc) + replace/list helpers.
- tools/drafting + server: analyze_protocol + get_protocol_analysis (extract/get).
- ספ 04-analysis-writing §1.3 + 15 בדיקות.

Invariants: G1 (נרמול-במקור: hearing_date לעמודה הקנונית), G2 (ידע-תיק נגזר
ממקור-האמת protocol+legal_arguments, לא מסלול מקביל), INV-TOOL3 (idempotent
per document_id), INV-TOOL4 (extract/get symmetry), INV-AH (quote-or-retract),
INV-WR4 (בלוק ז = טענות-כתב מקוריות בלבד), claude_session local-only, G12 (נקי
מ-Paperclip — leak-guard עובר).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 11:21:13 +00:00
aad2de9205 feat(drafting): טיוטת-ביניים דטרמיניסטית — נעיצת Opus 4.8 + effort per-בלוק (#204)
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 4s
Lint — undefined names / undefined-names (pull_request) Successful in 10s
מנגנון-הייצור (claude_session→claude -p) לא העביר model/effort: BLOCK_CONFIG
הגדיר temp+model per-בלוק שהיו מטא-דאטה-מת (block_writer.py:447 העביר רק
prompt/timeout/tools). הייצור רץ על מודל ברירת-המחדל של ה-CLI עם פרומפטים-חופשיים
→ מקור אי-העקביות בטיוטת-הביניים.

תיקון (עקביות-מבנית, WS5):
- נעיצת model="claude-opus-4-8" (GENERATION_MODEL) לכל בלוקי-ה-AI + effort per-בלוק
  שמועבר בפועל דרך claude_session.query → `claude -p --model --effort`.
  מפת-effort: ה=medium · ו=medium · ז=high · ח=medium · ט=high · יא=high · י=xhigh.
- ניסוח-פתיחה קבוע לבלוק-ה (תמיד "לפנינו ערר…", סוף ל-OR "עניינה של החלטה זו").
- מבנה-פנימי קבוע לבלוק-ה; סדר-בלוקים בייצוא כבר קבוע (_INTERIM_BLOCK_ORDER).
- הסרת שדות temp/model המתים מ-BLOCK_CONFIG; "temp" deprecated (Opus 4.7/4.8 דוחים
  temperature→400). decision_blocks.temperature נשמר=0 לתאימות-עמודה בלבד.
- timeout נגזר מ-effort (לא מפיצול sonnet/opus שכבר לא קיים).
- עדכון endpoint reference /api/settings/mcp/blocks + blocks-tab + McpBlock לחשוף effort.
- ספ: docs/block-schema.md §3 (effort מחליף temperature), docs/spec/06-export.md
  (דטרמיניזם-מבני של טיוטת-הביניים).

G2 (מקור-אמת יחיד) — אין מסלול-ייצור מקביל: write_interim_draft מתזמר את אותו
write_and_store_block→write_block של ההחלטה המלאה.
claude_session-local-only — הייצור נשאר דרך גשר-ה-CLI, לא SDK/קונטיינר.
INV-EX1 — סדר-ייצוא דטרמיניסטי נשמר; G11 — עקרונות-הכתיבה ל-12 הבלוקים נשמרים.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 11:18:56 +00:00
23e088d25e fix(export): clear template tables in _clear_body — חתימות לסוף, א–ד ללא נתונים (#205)
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 4s
Lint — undefined names / undefined-names (pull_request) Successful in 10s
תיקוני-תבנית DOCX (WS5 ת1–ת3): הטמפלט decision_template.docx מכיל 3 טבלאות-
דוגמה (כותרת מוסדית / הרכב / חתימות). _clear_body הסיר רק <w:p> והשאיר את
הטבלאות. כתוצאה:

- ת3 (שורש): טבלת-החתימות שרדה במיקום-הטמפלט (למעלה, צמוד לטבלת-הכותרת/בלוק-ד),
  וכל תוכן-ההחלטה נדחף אחריה. החתימות הופיעו בראש המסמך במקום בסוף.
- ת1: טבלאות הכותרת/הרכב הזריקו נתוני בלוק-א–ד שלא חולצו מהפרוטוקול.

התיקון בשכבת-הרינדור (G1 — לתקן במקור, לא לשכפל סימפטום): _clear_body מסיר
כעת את כל גוף-המסמך (פסקאות, טבלאות, ו-bookmarks יתומים) ומשאיר רק sectPr.
ההחלטה משוחזרת כולה מ-decision_blocks (INV-EX1) — החתימות מגיעות מ-block-yod-bet
שמרונדר אחרון בסדר-הבלוקים, ולכן טבלאות-הדוגמה הן פיגום מיושן שצריך להימחק.

ת2 כבר תקין: block-dalet מרנדר רק את הכותרת "החלטה" (Heading 1, מתעלם מתוכן-
ה-DB) — הוסף test מפורש לנעילה.

תוקן גם ב-analysis_docx_exporter._clear_body (אותו באג, סימטריה G2).

Tests: 4 regression חדשים + 27 docx-tests עוברים.

Invariants: INV-EX1 (DOCX נתון-נגזר מ-decision_blocks, ללא דליפת תוכן-טמפלט) ·
G1 (תיקון-במקור) · G2 (סימטריה בין שני ה-exporters) · G11/block-schema
(block-ד = כותרת בלבד, block-יב = חתימות בסוף).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 11:16:39 +00:00
7a7249af38 feat(documents): מסמך-עיקרי — is_primary נגזר + רשימה קנונית (#200)
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 4s
Lint — undefined names / undefined-names (pull_request) Successful in 10s
WS2 (#200): מבחין בין מסמך-עיקרי (מסמך-מהות שהיו"ר עוקבת אחריו לניתוח)
למשני. רשימה קנונית מאושרת-יו"ר: appeal/response/objection/protocol/
appraisal/decision; כל doc_type אחר = משני.

- db.PRIMARY_DOC_TYPES = מקור-אמת יחיד (tuple) + is_primary_doc_type().
- SCHEMA_V47: documents.is_primary BOOLEAN GENERATED ALWAYS AS
  (doc_type = ANY(PRIMARY_DOC_TYPES)) STORED — Postgres גוזר, אין מסלול-
  כתיבה מקביל, לא יכול לסטות מ-doc_type (G1/G2/INV-DM7, כמו ה-tsvectors).
  אידמפוטנטי (ADD COLUMN IF NOT EXISTS, ביטוי קבוע) + אינדקס חלקי
  idx_documents_primary לשאילתת "עיקריים שטרם-נותחו" (#201).
- _row_to_doc גוזר גם בקריאה (רשומות טרום-מיגרציה) + מוסיף doc_category
  ∈ {primary, secondary}. נחשף דרך document_list / case_get / API.
- 02-data-model.md §2ג מתעד את השדה הנגזר.

Invariants: G1 (נרמול-במקור — נגזר, לא נכתב), G2/INV-DM7 (מקור-אמת
יחיד, אין עמודה כפולה/מסלול מקביל), INV-DM3 (דפוס GENERATED drift-free),
INV-DM6 (ללא enum-TEXT חדש — סיווג נגזר). §6 (אין בליעה שקטה).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 11:16:26 +00:00
61e6be4b90 Merge pull request 'docs(heartbeat): שער קריאת-הערות לפני סגירה — מונע נפילת הערות-יו"ר (#164)' (#353) from worktree-comment-recheck-gate into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 9s
G12 Leak-Guard / leak-guard (push) Successful in 4s
Lint — undefined names / undefined-names (push) Successful in 10s
2026-06-30 10:22:07 +00:00
24e02621df docs(heartbeat): comment-recheck gate before done — prevent dropped chair comments
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 4s
Lint — undefined names / undefined-names (pull_request) Successful in 10s
Belt-and-suspenders to the plugin sweep (plugin-legal-ai #3). Comments that
arrive mid-run aren't re-read automatically — an agent reads comments once at
run start (§2), so a chair comment that lands after that point and before the
run closes the issue is never seen. That is exactly how a chair comment on
CMP-190 (2026-06-30) was dropped.

Adds a mandatory gate to HEARTBEAT §4ב: before PATCH status=done, re-read
comments and compare to the run-start list. If a new unaddressed chair comment
exists — do not close. Either handle it (and record a comment) or, if it
widens scope, keep the issue open and hand back to the CEO (§4ג). Never mark
done while a chair comment waits unanswered.

The plugin sweep catches orphaned comments within ~2 min; this gate prevents
the drop at the source. Refs legal-ai #164.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 10:20:47 +00:00
0f68cb2d0b Merge pull request 'feat(ui): באדג'י synthesis/superseded + provenance ב-lessons-tab (#162)' (#352) from worktree-lessons-synthesis-badges into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 1m31s
G12 Leak-Guard / leak-guard (push) Successful in 5s
Lint — undefined names / undefined-names (push) Successful in 10s
2026-06-28 22:59:55 +00:00
987da57da4 feat(ui): synthesis/superseded badges + merge provenance in lessons-tab (#162)
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 4s
Lint — undefined names / undefined-names (pull_request) Successful in 10s
עוצב ואושר דרך שער-העיצוב (Claude Design 12c-training-lessons.html).
- lessons-tab: SOURCE_BADGE['synthesis']="סינתזה" (navy מלא) · REVIEW_BADGE['superseded']="מוזג"
  (אפור-מעומעם, לא נדחה); שורות superseded מעומעמות (opacity).
- provenance: לקח-על מציג "⤷ מוזג מ-N לקחים · דחייה תשחזר אותם".
- backend: list_decision_lessons + _lesson_to_json מחזירים synthesized_from; training.ts
  DecisionLesson — 'synthesis'/'superseded' ל-unions + synthesized_from?: string[].

הבאדג'ים היו מוגנים-fallback קודם (ללא קריסה) — כעת מתויגים נכון. closes #162.

בדיקות: py_compile ✓ · leak-guard ✓ · tsc --noEmit ✓.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 22:59:31 +00:00
1136711ec8 Merge pull request 'docs(voice): apply corpus-56 fingerprint refresh (chair-approved, #161)' (#351) from worktree-apply-voice-fingerprint into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 7s
G12 Leak-Guard / leak-guard (push) Successful in 5s
Lint — undefined names / undefined-names (push) Successful in 10s
2026-06-28 22:55:33 +00:00
d83d1b248f docs(voice): apply corpus-56 fingerprint refresh (chair-approved, #161)
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 4s
Lint — undefined names / undefined-names (pull_request) Successful in 11s
The chair (Dafna/chaim) reviewed and approved the full corpus-refresh proposal
generated by scripts/regenerate_voice_fingerprint.py and committed it to the live
voice-fingerprint — satisfying the INV-LRN1 hard chair-gate (a human approved;
the script only ever proposed). +81/-15 lines: all the deletions are reword-and-
expand of existing lines (no curated insight lost), the additions are style/method
refinements grounded in the 56-decision corpus (INV-LRN5 — no case substance):

- §1.2 conditional-acceptance as an "anחנו" verb (מקובל עלינו vs נציין)
- §1.3 ruling variation "ראשית, צודק [צד]... אלא ש"
- §1.5 emphasis always annotated "(הדגשת הח\"מ)"
- §1.8 bounded appraiser-restraint (professional plane only; legal plane = no deference)
- §1.9 inverse twin "ניתן היה לסיים... אלא ש"
- §1.11 quantitative anchoring as a reframing device (cross-type)
- §1.12 measured block ratios (background 17 / claims 27 / discussion 42 / summary 14)
- §1.13 faithful rendering of a party's internal reasoning
- §2.2 two-sided pendulum for the restraint paragraph + expanded party-verb catalog
- §4.8 new template "ניתן היה לסיים — אלא ש"
- §5.x agent instructions updated to reference the new patterns

Invariants: INV-LRN1 (chair approved before commit — the gate held), INV-LRN5
(style/method only, no substance).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 22:55:07 +00:00
0398274564 Merge pull request 'feat(learning): העלאת תקרת-לקחים-לכותב 15 → 60 — סוגר את #157' (#350) from worktree-writer-lessons-limit into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 1m26s
G12 Leak-Guard / leak-guard (push) Successful in 5s
Lint — undefined names / undefined-names (push) Successful in 10s
2026-06-28 22:51:19 +00:00
a6fb632221 feat(learning): raise writer lessons cap 15 → 60 (config.WRITER_LESSONS_LIMIT) — closes #157
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 4s
Lint — undefined names / undefined-names (pull_request) Successful in 11s
עכשיו שהלקחים מנוכי-כפילות (סינתזה #158) ומאושרי-יו"ר, התקרה 15 חתכה בשקט הנחיות-סגנון
מובחנות ו-vetted (רישוי/סגנון 29>15). מעלים ל-60 (env-tunable WRITER_LESSONS_LIMIT) —
מכסה כל shard נוכחי עם מרווח; הסינתזה שומרת על אי-רדודנטיות בצמיחה. ה-WARN על חיתוך נשאר
רשת-הביטחון (חוקה §6) ומפנה לסינתזה/העלאת-התקרה. block_writer צורך דרך config.

Invariants: INV-LRN1/G10 (עדיין רק approved זורם; superseded מוחרג), G2. closes #157 בפועל.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 22:50:55 +00:00
5e7097399f Merge pull request 'tune(learning): סף-אשכול סינתזת-לקחים 0.82 → 0.68 (#158)' (#349) from worktree-synth-threshold-068 into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 1m30s
G12 Leak-Guard / leak-guard (push) Successful in 6s
Lint — undefined names / undefined-names (push) Successful in 11s
2026-06-28 22:45:11 +00:00
6c3c6a16c2 tune(learning): lesson-synthesis cluster threshold 0.82 → 0.68 (#158)
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 4s
Lint — undefined names / undefined-names (pull_request) Successful in 10s
כיול אמפירי (dry-run על 81 לקחים): הלקחים מגוונים (חציון-דמיון ~0.48, מקס' ~0.72), כך
ש-0.82 מיזג 0 אשכולות. 0.68 תופס 5 קונסולידציות אמיתיות (רישוי+השבחה+מבנה), כולן עברו את
שער-ה-drift 0.80 (0.848–0.916) → נאמנות נשמרת. שער-ה-drift נשאר רשת-הביטחון מתחת לסף.

Invariants: INV-LRN8 (כיול-סף בלבד; המנגנון/השערים ללא שינוי). depends-on #158.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 22:44:55 +00:00
7a7db6933d Merge pull request 'feat(learning): voice-fingerprint corpus-refresh proposal generator (#161, prose half)' (#348) from worktree-voice-fingerprint-refresh into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 1m27s
G12 Leak-Guard / leak-guard (push) Successful in 4s
Lint — undefined names / undefined-names (push) Successful in 10s
2026-06-28 22:26:39 +00:00
d3d379af65 Merge pull request 'feat(learning): סינתזת-לקחים — מיזוג לקחים חופפים ללקח-על עשיר (#158 / INV-LRN8)' (#347) from worktree-lesson-synthesis into main
Some checks failed
Build & Deploy / build-and-deploy (push) Has been cancelled
G12 Leak-Guard / leak-guard (push) Has been cancelled
Lint — undefined names / undefined-names (push) Has been cancelled
2026-06-28 22:26:28 +00:00
9a19db1ec1 feat(learning): voice-fingerprint corpus-refresh proposal generator (#161, prose half)
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 4s
Lint — undefined names / undefined-names (pull_request) Successful in 11s
The voice-fingerprint (docs/daphna-voice-fingerprint.md) is the PRIMARY abstract
style channel the writer consumes (07-learning §0.2 channel A), but it was
hand-authored and never regenerated from the growing corpus — the "voice" the
writer adapts stayed frozen while finals accumulated. PR #345 unfroze the
structural half (corpus-measured ratios → writer); this is the prose half.

scripts/regenerate_voice_fingerprint.py reads the corpus (style_corpus stats +
a bounded block-level style_exemplars sample + measured section ratios) and asks
Opus (local) to PROPOSE refinements/additions to the fingerprint — STYLE / METHOD
/ VOICE / LEXICON only, grounded in corpus evidence, never case substance
(INV-LRN5), preserving curated insights rather than replacing them.

CHAIR-GATED, HARD (INV-LRN1): the prose profile is voice-knowledge, not a
low-risk style rule, so it does NOT auto-flow. The script writes a PROPOSAL to
data/curator-proposals/ (the existing curator-proposal surface) and NEVER
overwrites the live fingerprint; the chair reviews and hand-commits accepted parts
— the same manual gate the fingerprint already uses. Runs on the host (claude CLI).

Reuses claude_session + measure_corpus_ratios + the curator-proposals dir (G2 —
no parallel synthesis or gate). SCRIPTS.md + spec §0.2 updated.

Invariants: INV-LRN1 (hard chair gate for voice-knowledge prose), INV-LRN5
(style-only synthesis), G2 (reuses existing synthesis inputs + proposal surface).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 22:26:04 +00:00
14ab7b0cae feat(learning): lesson synthesis — merge overlapping lessons into richer super-lessons (#158 / INV-LRN8)
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 4s
Lint — undefined names / undefined-names (pull_request) Successful in 10s
הפתרון-האמיתי לחיתוך-השקט limit=15 (#157): במקום ערימת לקחים גולמיים חופפים, ממזגים
לקחי-סגנון דומים ל"לקח-על" אחד עשיר ומוכלל — הסט שזורם לכותב קטֵן ומשתבח (Authorial
Style Profiling). מחקה את סינתזת-הקנוני (V41/INV-LRN6) על אותה טבלה (G2, אין מאגר-מקביל).

מנגנון (services/lesson_synthesis.py, מסלול-יחיד):
- אשכול greedy לפי cosine (LESSON_SYNTH_CLUSTER_THRESHOLD) בתוך shard practice_area+category.
- מיזוג ע"י claude_session מעוגן-מקור (INV-AH, סגנון-בלבד INV-LRN5, abstain) + שער-drift
  (cosine מול centroid ≥ LESSON_SYNTH_DRIFT_FLOOR).
- לקח-על נכתב source='synthesis' + synthesized_from; המקורות→review_status='superseded'.
- שער מדורג-הפיך (הכרעת-יו"ר): מקורות approved → לקח-על approved (זורם), veto-יו"ר משחזר
  את המקורות (db.revert_lesson_synthesis, מחובר ל-PATCH lessons).
- idempotency: lookup-cosine מול synthesis קיים לפני INSERT.

נגזרות: SCHEMA_V46 (embedding vector(1024) + synthesized_from + ivfflat); כלי-MCP
lesson_synthesize_pending; scripts/backfill_lesson_synthesis.py (--dry-run/--apply, audit CSV);
config LESSON_SYNTH_*; spec INV-LRN8; SCRIPTS.md.

get_recent_decision_lessons ללא שינוי — superseded יוצא (מסנן approved), synthesis נכנס.
UI badges (synthesis/superseded) נדחים לשער-העיצוב (מוגנים ב-fallback, ללא קריסה).

בדיקות: py_compile ✓ · leak-guard G12 ✓ · smoke-test טהור לאשכול/cosine/centroid ✓.
אימות functional מלא (dry-run מול DB+voyage+claude CLI) — בהוסט אחרי-deploy, כמו V41.

Invariants: G2 (מסלול-יחיד, אותה טבלה), INV-AH (עיגון+drift), INV-LRN1/G10 (שער מדורג-הפיך),
INV-LRN5 (סגנון-בלבד), INV-LRN8 (חדש). depends-on #157/#159.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 22:24:42 +00:00
c1983ea41d Merge pull request 'feat(ops): host_sync.sh — auto-sync host tree to origin/main (#160)' (#346) from worktree-host-sync into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 8s
G12 Leak-Guard / leak-guard (push) Successful in 4s
Lint — undefined names / undefined-names (push) Successful in 10s
2026-06-28 22:20:40 +00:00
80a5daa3e3 feat(ops): host_sync.sh — auto-sync host tree to origin/main (P-#160)
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 4s
Lint — undefined names / undefined-names (pull_request) Successful in 10s
The writer, learning panels, and legal_mcp tools run from the HOST tree
(Paperclip agents claude -p with cwd=~/legal-ai; pm2 services import from
mcp-server/src) — not the container. A merge + Coolify deploy only refreshes the
FastAPI container; host-side code stayed on the last manual `git pull`. On
2026-06-28 the host was 16 commits behind, so a day of learning-loop fixes sat
dormant until pulled by hand.

host_sync.sh (run every minute via cron, like the existing data/training pull)
fast-forwards the host tree to origin/main when it falls behind. Fast-forward
ONLY — never forces, so the perpetually-dirty .taskmaster/tasks/tasks.json is
never clobbered (clean ff leaves it; an upstream conflict logs + bails for manual
handling). Agent runs spawn fresh and pick up new code with no restart; only the
long-running pm2 services that import app code (chat_service, court_fetch_service,
reaper) are restarted, and only when their own files changed (precise, minimal
churn). Logs to data/logs/host_sync.log.

Cron entry (added on the host, flock-guarded):
  * * * * * flock -n /tmp/host_sync.lock bash ~/legal-ai/scripts/host_sync.sh

SCRIPTS.md updated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 22:20:13 +00:00
9455da7567 Merge pull request 'feat(learning): feed corpus-measured ratios to the writer (P2 #7, structural half)' (#345) from worktree-corpus-ratios-writer into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 1m25s
G12 Leak-Guard / leak-guard (push) Successful in 4s
Lint — undefined names / undefined-names (push) Successful in 10s
2026-06-28 22:11:13 +00:00
638dbf9b9f feat(learning): feed corpus-measured section ratios to the writer (P2 #7, structural half)
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 3s
Lint — undefined names / undefined-names (pull_request) Successful in 10s
Golden ratios were measured from the corpus (style_distance.measure_corpus_ratios)
but never reached the writer — it used only the hardcoded STRUCTURE_GUIDANCE text.
So the structural target was frozen, and drafts kept deviating (e.g. discussion
block 10% vs a 40-47% target) with no corrective signal.

_structure_guidance_with_corpus(outcome, practice_area) now appends the
corpus-measured section ratios for the block's outcome to the structure guidance,
at both writer entry points (write_block + get_block_context) via one shared helper
(G2). Because measure_corpus_ratios reads style_corpus — which grows with every
enrolled final (see exemplar-growth, #343) — the writer's structural target now
reflects Dafna's ACTUAL current distribution and improves as the corpus grows.
Deterministic (no LLM); best-effort.

This is the STRUCTURAL half of the voice-profile-refresh (#7). The remaining half —
LLM-regenerating the abstract voice-fingerprint PROSE from the corpus (chair-gated)
— is a distinct larger initiative, deliberately deferred rather than rushed.

Invariants: G1 (the writer gets the live measured target, not a frozen constant),
G2 (one structure-guidance builder shared by both entry points; reuses the existing
measure_corpus_ratios — no parallel measurement), INV-LRN4 (the corpus the loop
grows now feeds the writer's structural target).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 22:10:39 +00:00
97f3f50d0b Merge pull request 'feat(learning): chair-feedback style corrections auto-flow to writer (P1 #6)' (#344) from worktree-chair-feedback-flow into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 1m28s
G12 Leak-Guard / leak-guard (push) Successful in 4s
Lint — undefined names / undefined-names (push) Successful in 10s
2026-06-28 22:07:30 +00:00
8b23542dec feat(learning): chair-feedback style corrections auto-flow to the writer (P1 #6)
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 3s
Lint — undefined names / undefined-names (pull_request) Successful in 10s
The chair-feedback chain was DEAD: 27 feedback rows captured, 0 ever became a
lesson the writer reads (no weekly-analysis job ever existed). The chair's own
corrections — the most authoritative signal of all, and exactly "learn from every
returned draft" — went nowhere.

decision_lessons can't carry them: it's FK-coupled to a style_corpus row (a signed
final), which a case-in-progress doesn't have. So chair STYLE feedback instead
rides the discussion_rules channel that already reaches the writer for all blocks —
the same path /training promote uses.

- db.append_global_rule: the locked read-modify-write append, extracted from web
  `_append_methodology_override` into one shared impl (G2). The web function is now
  a thin wrapper that seeds defaults; chair-feedback calls it directly.
- record_chair_feedback (MCP tool): a STYLE-category correction (style/wrong_tone/
  wrong_structure) with a lesson_extracted flows immediately to discussion_rules.
  The chair IS the gate — no separate approval (INV-LRN1 graduated gate). SUBSTANCE
  feedback (missing_content/factual_error/other) is case-specific → recorded only.

Invariants: INV-LRN1 (chair-authored style = highest authority, flows; substance
not auto-flowed), G2 (single append impl shared by promote + feedback), INV-LRN5
(style channel only).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 22:06:58 +00:00
b8eb0ee123 Merge pull request 'feat(learning): ניתוח-§A של האוצֵר רץ על mark-final — לכידת source='curator' על כל סופי (#159)' (#342) from worktree-curator-autofire into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 8s
G12 Leak-Guard / leak-guard (push) Successful in 4s
Lint — undefined names / undefined-names (push) Successful in 10s
2026-06-28 22:03:15 +00:00
b0a6c2fe01 Merge pull request 'feat(learning): grow style-exemplars from every final (P1 #5)' (#343) from worktree-grow-exemplars into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 1m28s
G12 Leak-Guard / leak-guard (push) Successful in 4s
Lint — undefined names / undefined-names (push) Successful in 10s
2026-06-28 21:58:12 +00:00
93a9404663 feat(learning): grow style-exemplars from every final (P1 #5)
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 3s
Lint — undefined names / undefined-names (pull_request) Successful in 10s
The style-exemplar corpus (channel B — the writer's block-level retrieval of
Dafna's real prose) was FROZEN at the one-time seed backfill: new finals were
enrolled into style_corpus but never broken into exemplars, so the richest style
channel never grew (8137/8126/8174 had 0 exemplars). The writer kept retrieving
only March–April seed paragraphs no matter how many finals were signed.

Extract the per-decision exemplar logic (section→paragraph→Voyage-embed→replace)
into a shared service `legal_mcp.services.style_exemplars.extract_and_store` —
the SINGLE implementation now used by BOTH the one-time backfill and the live
enrollment path (G2; no parallel extractor). `_enroll_final_in_library` calls it
on every final upload (source='internal_committee', the same source the writer's
search_style_exemplars reads). Voyage embeds over REST → container-safe;
best-effort, surfaced in the upload response, never fails the upload.

Effect: every signed final now grows the exemplar corpus, so the writer's
block-level style retrieval improves with each decision — the core "learn from
every decision" fix for channel B. Path A (style_distance_history) will track
whether the larger exemplar pool reduces style-distance over time.

Invariants: G2 (one extraction path shared by backfill + enroll), INV-LRN5
(style/structure prose only — substance routes elsewhere), INV-LRN4 (the
draft↔final loop now feeds the exemplar channel, not just the lesson channel).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 21:57:38 +00:00
4d6268820c feat(learning): curator §A fires on mark-final — capture source='curator' findings on every final (#159)
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 3s
Lint — undefined names / undefined-names (pull_request) Successful in 10s
חלופה ז (agent-centric) — סוגר את פער-המימוש מ-#157:

1. final_learning_pipeline.py — סדר-מחדש: enroll_style_corpus רץ ראשון (לפני הדיסטילציה של עד
   30 דק'), כך שרשומת style_corpus קיימת תוך שניות — והאוצֵר יכול לרשום ממצאים בלי מירוץ.
   enroll/ingest בלתי-תלויים; panel נשאר אחרון. תוויות [1/3]/[2/3] עודכנו.

2. hermes-curator.md PIPELINE-WAKE BRANCH — מבדיל final_learning_* (ממשיך ל-§A, מצב AUTO) מ-
   final_halacha_* (exit כקודם). ב-AUTO: §A.1–§A.5b → record_curator_findings, דילוג על §A.6
   (interaction) כדי לא להעיר את דפנה (הממצאים proposed ונסקרים ב-/training). §A.5b קיבל retry
   כרשת-ביטחון למירוץ-שארית.

3. docs/spec/07-learning.md §0.6 + §1.1 — עודכנו לסדר-הצינור החדש; הערת "פער-מימוש פתוח" → "נסגר".

Invariants: G2 (מחולל-יחיד לממצאי-curator — הסוכן; אין כפילות-תבונה), INV-LRN1/G10 (proposed,
שער-יו"ר), INV-LRN3, INV-DUR1 (סדר-צעדים בשמות יציבים; checkpoint resume — edge-case של ריצה
מקבילה-לפריסה, סיכון נמוך). depends-on #157.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 21:56:36 +00:00
07bd8bee48 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
2026-06-28 21:46:29 +00:00
044de2c0f0 feat(learning): graduated gate — panel-consensus style lessons auto-flow to writer (P0)
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 4s
Lint — undefined names / undefined-names (pull_request) Successful in 10s
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) <noreply@anthropic.com>
2026-06-28 21:45:56 +00:00
cfcfe4df48 Merge pull request 'fix(learning): כרטיס-אוצֵר כן-3-ערוצים + לכידת ממצאי-אוצֵר (source='curator')' (#339) from worktree-curator-learning-surface into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 1m29s
G12 Leak-Guard / leak-guard (push) Successful in 5s
Lint — undefined names / undefined-names (push) Successful in 10s
2026-06-28 21:28:53 +00:00
6427911baf Merge pull request 'fix(writer): always feed canonical anti-patterns to the writer' (#340) from worktree-writer-anti-patterns into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 1m25s
G12 Leak-Guard / leak-guard (push) Successful in 5s
Lint — undefined names / undefined-names (push) Successful in 10s
2026-06-28 21:24:57 +00:00
d7201736f2 fix(writer): always feed canonical anti-patterns to the writer
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 3s
Lint — undefined names / undefined-names (pull_request) Successful in 10s
The learning loop measured anti-patterns but never corrected them. style_distance
detects markdown headers / bullet lists / mid-paragraph mini-lists (from the
canonical lessons.ANTI_PATTERNS), but the writer only received anti-pattern
guidance if a chair `anti_patterns` override existed in appeal_type_rules — and
none does. So _build_style_context's `if ov:` branch injected nothing, the writer
was never told to avoid them, and drafts kept emitting them (8137: 28 hits, the
worst, newest — anti-patterns were trending UP, not down).

Anti-patterns are structural invariants of Dafna's voice (continuous legal
narrative — no markdown, no bullets), not overridable preferences. So inject the
canonical ANTI_PATTERNS notes ALWAYS, from the same list style_distance measures
against (single source of truth), with any chair additions layered on top. This
closes the measure-but-don't-correct gap: the next draft should show the markdown/
bullet anti-patterns drop, and Path A (style_distance_history) will confirm it.

Invariants: G1 (correct at source — the writer, not a post-hoc stripper), G2
(one canonical anti-pattern list shared by detection and instruction — no parallel
list), INV-LRN4 (closes the feedback half of the draft↔final loop).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 21:24:24 +00:00
be774ab87e fix(learning): honest 3-channel curator card + capture curator findings (source='curator')
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 4s
Lint — undefined names / undefined-names (pull_request) Successful in 9s
תיקוני-מבנה ללולאת-הלמידה (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>
2026-06-28 21:20:05 +00:00
c00e7b4f49 Merge pull request 'docs(spec): Path A — prospective held-out style-distance trend (07-learning §0.7)' (#338) from worktree-spec-path-a into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 8s
G12 Leak-Guard / leak-guard (push) Successful in 3s
Lint — undefined names / undefined-names (push) Successful in 10s
2026-06-28 21:16:35 +00:00
927be5c6bb docs(spec): add Path A — prospective held-out style-distance trend (07-learning §0.7)
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 4s
Lint — undefined names / undefined-names (pull_request) Successful in 10s
Documents the prospective held-out methodology shipped in PR #337: why a clean
retrospective held-out is impossible (lessons stored universal/untagged → no
leave-one-out), and how the system instead captures a clean generalization
datapoint at final-upload — before this case's lessons are folded — via a
style_distance snapshot + lesson-pool size into style_distance_history,
surfaced by GET /api/learning/style-distance-history.

Adds §0.7, wires step [7] MEASUREMENT and INV-LRN4 to it. Notes the
change_percent style/content confound and the one-time clean window.

Invariants documented: INV-LRN4 (this is its trend surface), G2 (reuses
style_distance + appeal_type_rules — no parallel metric path).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 21:16:11 +00:00
84afdcb36c Merge pull request 'feat(learning): prospective held-out style-distance trend (Path A)' (#337) from worktree-style-distance-history into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 1m28s
G12 Leak-Guard / leak-guard (push) Successful in 4s
Lint — undefined names / undefined-names (push) Successful in 10s
2026-06-28 21:03:50 +00:00
ab510328af feat(learning): prospective held-out style-distance trend (Path A)
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 4s
Lint — undefined names / undefined-names (pull_request) Successful in 9s
A clean held-out test of voice learning was no longer runnable: every
final-uploaded case already has its lessons folded, and lessons are stored
universal/untagged so leave-one-out is impossible. Path A makes the test
prospective instead — capture the generalization datapoint at the one moment
it's clean.

On final upload, after the draft↔final pair is created but BEFORE this
case's lessons are folded (folding is a separate manual /training step), we
snapshot style_distance (anti_pattern_total, golden-ratio max-deviation,
change_percent) alongside the current voice-lesson pool size. Because the
draft was written with only the PRIOR pool, each row is a clean "with N
accumulated lessons, our draft on this unseen case scored X" datapoint. As
the pool grows over cases, a downward trend = learning generalizes.

- db: SCHEMA_V45 style_distance_history (append-only) + helpers
  voice_lesson_pool_sizes / record_style_distance_snapshot /
  get_style_distance_history.
- app: best-effort capture in api_upload_final_decision (never fails the
  upload); GET /api/learning/style-distance-history for the trend.

Reuses the existing style_distance service + appeal_type_rules pool — no
parallel metric path. The 8 existing cases are already folded, so the table
starts empty and fills from the next final (their clean window is past).

Invariants: G2 (reuse style_distance/appeal_type_rules — one path),
INV-LRN4 (measure the draft↔final gap; this is its trend surface). LLM-free
(style_distance is deterministic) so it runs in the container.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 21:03:10 +00:00