fix(writer): disable tools on block_writer + style_analyzer claude_session calls
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 6s

המשך ל-#182 — שני האתרים שנותרו עם query()‎ ליצירת-טקסט/ניתוח, ששמרו על
ברירת-המחדל של ה-CLI (כל הכלים פעילים) ולכן חשופים לאותו error_max_turns:
המודל פולט stop_reason:"tool_use", מפיל את --max-turns 1, ומאלץ retry יקר.

- block_writer.py:413 — כתיבת פרוזת בלוק (Opus/Sonnet). יצירת-טקסט טהורה,
  אף פעם לא צריך כלי.
- style_analyzer.py:166/183/196 — single/multi-pass + synthesis; הפלט מפוענח
  כ-JSON (_parse_and_store_patterns/_extract_json). text→JSON טהור.

מיישר את שני האחרונים לאותו מסלול קנוני (claude_session.query(tools="")).
עכשיו כל קריאות ה-LLM שאינן צריכות כלים מעבירות tools="".

Invariants: מקיים INV-G2 (מסלול קנוני יחיד; סימטריה). אין בליעה שקטה (§6).
ללא שינוי-ספ.

בדיקות: py_compile נקי; 18 בדיקות (block/style/writer) עוברות.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-11 12:03:37 +00:00
parent 33663b9816
commit 64db643e6d
2 changed files with 4 additions and 1 deletions

View File

@@ -410,7 +410,7 @@ async def write_block(
# Call Claude via Claude Code session (no API) # Call Claude via Claude Code session (no API)
model_key = block_cfg["model"] model_key = block_cfg["model"]
timeout = claude_session.LONG_TIMEOUT if model_key == "opus" else claude_session.DEFAULT_TIMEOUT timeout = claude_session.LONG_TIMEOUT if model_key == "opus" else claude_session.DEFAULT_TIMEOUT
content = await claude_session.query(prompt, timeout=timeout) content = await claude_session.query(prompt, timeout=timeout, tools="") # prose gen — no tool_use → no error_max_turns
sources = await _collect_block_sources(case_id, block_id) sources = await _collect_block_sources(case_id, block_id)
sources["case_law_ids"] = _precedent_case_law_ids sources["case_law_ids"] = _precedent_case_law_ids

View File

@@ -166,6 +166,7 @@ async def _analyze_single_pass(rows, appeal_subtype: str = "") -> dict:
raw = await claude_session.query( raw = await claude_session.query(
ANALYSIS_PROMPT.format(decisions=decisions_text), ANALYSIS_PROMPT.format(decisions=decisions_text),
timeout=claude_session.LONG_TIMEOUT, timeout=claude_session.LONG_TIMEOUT,
tools="", # text→JSON style analysis — no tool_use → no error_max_turns
) )
return await _parse_and_store_patterns(raw, len(rows), appeal_subtype) return await _parse_and_store_patterns(raw, len(rows), appeal_subtype)
@@ -183,6 +184,7 @@ async def _analyze_multi_pass(rows, appeal_subtype: str = "") -> dict:
raw = await claude_session.query( raw = await claude_session.query(
SINGLE_DECISION_PROMPT.format(decision=decision_text), SINGLE_DECISION_PROMPT.format(decision=decision_text),
timeout=claude_session.LONG_TIMEOUT, timeout=claude_session.LONG_TIMEOUT,
tools="", # text→JSON style analysis — no tool_use → no error_max_turns
) )
patterns = _extract_json(raw) patterns = _extract_json(raw)
@@ -199,6 +201,7 @@ async def _analyze_multi_pass(rows, appeal_subtype: str = "") -> dict:
patterns=json.dumps(all_patterns, ensure_ascii=False, indent=2), patterns=json.dumps(all_patterns, ensure_ascii=False, indent=2),
), ),
timeout=claude_session.LONG_TIMEOUT, timeout=claude_session.LONG_TIMEOUT,
tools="", # text→JSON style analysis — no tool_use → no error_max_turns
) )
return await _parse_and_store_patterns(raw, len(rows), appeal_subtype) return await _parse_and_store_patterns(raw, len(rows), appeal_subtype)