4 Commits

Author SHA1 Message Date
c7156b575e feat(calibration): style-clean recommend_effort (anti-primary) + confidence + --rerank (#213)
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 4s
Lint — undefined names / undefined-names (pull_request) Successful in 10s
Make the effort-calibration recommendation style-clean (style acquisition is
the goal — write like chair Dafna Tamir):

- recommend_effort ranks by anti_pattern_total (PRIMARY, the clean style-rule
  violation count) → golden_ratio_deviation_pp (SECONDARY, structural-style,
  None=worst) → distance (faint final tiebreak). change_percent is EXCLUDED from
  the ranking (it mixes style with content-completeness per 07-learning §0.7 —
  noise for STYLE) and kept in the report as context only.
- Add a confidence flag ("clear"/"weak"): a pick whose anti-pattern lead over the
  runner-up is within noise (margin < epsilon = max(0.5, 0.20·spread)) is flagged
  ⚠️ weak, so an over-claimed pick (the old confident block-zayin "low") is never
  shown as confident. Rendered as a confidence column in the report.
- Add --rerank <report.json>: re-apply the new key to a saved calibration JSON
  offline (NO LLM, NO DB), print + write *-reranked.md. Re-ranks today's 8-final
  run without regenerating.
- recommend_effort stays a single shared pure function reused by
  scripts/calibrate_block_yod.py (G2); both --self-test suites pass.
- Spec note added (07-learning §0.7) + SCRIPTS.md updated.

Invariants: G8 (style-clean empirical ranking), G2 (single shared recommend_effort,
reused by the block-yod harness — no parallel metric path), INV-LRN5 (style-only
signal; change% reported-not-ranked).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 19:00:41 +00:00
9402c7302f fix(tz): timezone-aware datetimes — unblock TZ=Asia/Jerusalem (#210)
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 3s
Lint — undefined names / undefined-names (pull_request) Successful in 10s
Backend follow-up to INV-UI9 (X6 §"אודיט-נלווה"): make server-side
datetimes explicit so flipping the container to TZ=Asia/Jerusalem cannot
silently skew stored or displayed timestamps. Storage stays UTC; human
display is Israel time.

- audit.py: naive datetime.utcnow() → datetime.now(timezone.utc) for the
  TIMESTAMPTZ audit_log.created_at. Under TZ=Asia/Jerusalem the naive UTC
  wall-clock would be read as Israel-local and stored ~3h off. (§6: no
  silent skew.)
- calibrate_effort.py: _ts() report stamp now Israel-time via
  ZoneInfo("Asia/Jerusalem") with a filename-safe "-IL" suffix (script runs
  on the UTC host); added a labeled "שעון ישראל" line to the report header
  so the chair-facing timestamp is unambiguous. --self-test still ALL PASS.
- research_md.py: display fields made deterministic Israel-tz —
  update_chair_position timestamp (datetime.now(IL_TZ)) and parse() mtime
  (datetime.fromtimestamp(..., tz=IL_TZ)) — correct regardless of process TZ.

Left intentionally Israel-local-day date.today()/year-cutoff call sites
untouched (drafting/party_claims_summary/block_writer/court_fetch_supreme)
— a Jerusalem committee wants the Israel calendar day; they resolve
correctly once TZ flips.

Invariants: INV-UI9 (store-UTC / display-Israel, server side); §6
(timezone-aware datetimes, no silent ~3h skew).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 17:24:17 +00:00
70a06c3745 fix(calibration): drop block-yod + per-cell guard + incremental write (#208)
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 5s
Lint — undefined names / undefined-names (pull_request) Successful in 10s
A live calibration run crashed with no error handling and lost ~2h of work:
the per-cell loop in _run() reached block-yod (discussion), block_writer.write_block
raised ValueError("לא ניתן לכתוב בלוק דיון ללא כיוון מאושר…") because the discussion
block needs an approved direction calibration cases don't have, and since the report
was only written at the very end of main(), every completed generation was lost.

Three robustness fixes (no metric/scoring change — G2):

1. Drop block-yod from default CALIBRATABLE_BLOCKS — out of WS5 interim-draft scope
   AND structurally non-calibratable standalone (needs brainstorm→approve_direction).
   Kept in new VALID_BLOCKS so a user can still force it via --blocks block-yod.
2. Per-cell try/except in _run(): any single (case, block, effort) cell failure is
   logged as a warning (case/block/effort/error) and skipped, never fatal —
   defense-in-depth for a forced block-yod and for transient rate-limits mid-run.
3. Incremental persistence: _write_report flushes after each completed block (ts
   threaded into _run), so a crash later in the grid never loses finished blocks.
   JSON/MD shape unchanged — partial results omit not-yet-done blocks from by_block.

--self-test: ALL PASS (14/14). block-yod gone from --dry-run defaults.

Invariants — נוגע / מקיים:
- G8 (eval-harness robustness) — partial results persist; a single-cell failure is
  non-fatal; the harness survives block-yod's missing-direction raise and rate-limits.
- G2 (מקור-מדידה יחיד) — no metric-path change; _score_cell / block_distance_to_final
  / recommend_effort / aggregate_cell untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 15:49:15 +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