---
phase: 11-manual-ruff-cli-mypy
plan: 05
type: execute
wave: 2
depends_on:
  - "11-04"
files_modified:
  - src/corpus_analyzer/llm/rewriter.py
autonomous: true
requirements:
  - MYPY-05

must_haves:
  truths:
    - "`uv run mypy src/ --no-error-summary 2>&1 | grep 'rewriter.py'` returns empty (zero errors)"
    - "The DEFAULT_SYSTEM_PROMPT trailing comma bug is fixed — it is now a `str`, not `tuple[str]`"
    - "The `process_document` function has full type annotations on all parameters"
    - "The attr-defined error on `adv_rewriter.client.db` is gone (resolved by plan 04 adding the field)"
    - "`uv run mypy src/` exits 0 — the entire codebase has zero mypy errors"
    - "All 281 tests still pass"
  artifacts:
    - path: "src/corpus_analyzer/llm/rewriter.py"
      provides: "Mypy-clean rewriter with genuine bug fixed (DEFAULT_SYSTEM_PROMPT is now a str)"
  key_links:
    - from: "src/corpus_analyzer/llm/rewriter.py"
      to: "DEFAULT_SYSTEM_PROMPT"
      via: "trailing comma removal — changes runtime type from tuple[str] to str"
      pattern: "DEFAULT_SYSTEM_PROMPT"
    - from: "src/corpus_analyzer/llm/rewriter.py"
      to: "OllamaClient.db"
      via: "adv_rewriter.client.db = db (attr-defined resolved by plan 04)"
      pattern: "client\\.db"
---

<objective>
Fix all 7 mypy errors in `llm/rewriter.py`: the genuine DEFAULT_SYSTEM_PROMPT trailing-comma bug (causes operator error at line 401), the missing annotations on `process_document`, and the attr-defined error on `client.db` (already resolved by plan 04 adding the field to OllamaClient).

Purpose: MYPY-05 — this is the final file to fix. After plan 05 completes, `uv run mypy src/` exits 0.
Output: A mypy-clean rewriter.py with a genuine runtime bug fixed.

This plan depends on plan 04 (wave 1) because `adv_rewriter.client.db = db` (line 409) requires `OllamaClient.db` to exist — added in plan 04.
</objective>

<execution_context>
@/home/ollie/.claude/get-shit-done/workflows/execute-plan.md
@/home/ollie/.claude/get-shit-done/templates/summary.md
</execution_context>

<context>
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/phases/11-manual-ruff-cli-mypy/11-RESEARCH.md
@.planning/phases/11-manual-ruff-cli-mypy/11-04-SUMMARY.md
</context>

<tasks>

<task type="auto">
  <name>Task 1: Fix DEFAULT_SYSTEM_PROMPT trailing comma bug and process_document annotations</name>
  <files>src/corpus_analyzer/llm/rewriter.py</files>
  <action>
Read the full file first. This task fixes the two root causes of rewriter.py's mypy errors.

**Fix 1 — DEFAULT_SYSTEM_PROMPT trailing comma (line ~230):**
The constant ends with `""",` — a trailing comma after the triple-quoted string. This makes `DEFAULT_SYSTEM_PROMPT` a `tuple[str]` instead of `str`, causing the operator error at line 401 (`system_prompt += "..."`).

Find the constant definition (search for `DEFAULT_SYSTEM_PROMPT`). The last line of the string should end with `"""` followed by a newline, NOT `""",`.

```python
# Before (bug):
DEFAULT_SYSTEM_PROMPT = """...
Be concise but comprehensive. Preserve important details. Do not include these instructions in the output.""",

# After (fix — remove the trailing comma):
DEFAULT_SYSTEM_PROMPT = """...
Be concise but comprehensive. Preserve important details. Do not include these instructions in the output."""
```

This is a genuine bug: at runtime, calling `rewrite_category(...)` with a category not in `CATEGORY_PROMPTS` would have caused a `TypeError` at line 401. Removing the comma is the correct fix — not a cast.

After this fix, the operator error at line 401 should disappear from mypy output.

**Fix 2 — `process_document` missing annotations (line ~240):**
Read the actual signature. The function has unannotated parameters (likely `doc` and `adv_rewriter`):
```python
from corpus_analyzer.core.models import Document
from typing import Any

def process_document(
    doc: Document,
    client: OllamaClient,
    ...
    adv_rewriter: Any,
    ...
) -> ...:  # use actual return type from the existing annotation or add -> None
```
`adv_rewriter` is typed `Any` because `AdvancedRewriter` is imported conditionally inside the function to avoid circular imports. Do NOT move the import — keep `adv_rewriter: Any`.

Read the full parameter list and annotate every unannotated parameter. The research document (pattern 10) shows the minimum; adapt to the actual signature.

After both fixes, run:
```bash
uv run mypy src/ --no-error-summary 2>&1 | grep "rewriter.py"
```
Must return empty.
  </action>
  <verify>
    <automated>uv run mypy src/ --no-error-summary 2>&1 | grep "rewriter.py" | wc -l | grep -q "^0$" && echo "rewriter.py: 0 errors"</automated>
  </verify>
  <done>Zero mypy errors in rewriter.py; DEFAULT_SYSTEM_PROMPT is a str (no trailing comma); process_document is fully annotated.</done>
</task>

<task type="auto">
  <name>Task 2: Full mypy clean gate and final test run</name>
  <files>src/corpus_analyzer/llm/rewriter.py</files>
  <action>
Run the complete mypy check to confirm zero errors across the entire codebase, then run the full test suite.

**Step 1 — Full mypy gate:**
```bash
uv run mypy src/ --no-error-summary 2>&1
```
Expected output: `Success: no issues found in N source files` (exit 0).

If any errors remain, fix them in rewriter.py now. Do NOT leave errors for phase 12 — phase 11's success criteria require zero mypy errors.

**Step 2 — Ruff check (confirm cli.py fix from plan 01 is intact):**
```bash
uv run ruff check .
```
Expected: exit 0 (cli.py was fixed in plan 01; other files were already clean).

**Step 3 — Full test suite:**
```bash
uv run pytest -v 2>&1 | tail -20
```
All 281 tests must pass. If any test fails, investigate whether the DEFAULT_SYSTEM_PROMPT fix changed runtime behaviour: the constant being a `str` instead of `tuple[str]` is the correct type — any test relying on tuple behaviour was relying on a bug.
  </action>
  <verify>
    <automated>uv run mypy src/ --no-error-summary 2>&1 | grep -c "error:" | grep -q "^0$" && echo "mypy: 0 errors" && uv run pytest -x -q 2>&1 | tail -5</automated>
  </verify>
  <done>`uv run mypy src/` exits 0 with no errors; all 281 tests pass; the entire phase 11 goal is achieved.</done>
</task>

</tasks>

<verification>
After both tasks:
1. `uv run mypy src/ --no-error-summary` — exits 0, "Success: no issues found"
2. `uv run ruff check .` — exits 0 (zero violations anywhere)
3. `uv run pytest -v` — all 281 tests green
4. `DEFAULT_SYSTEM_PROMPT` is a `str` (no trailing comma)
5. `OllamaClient.db` attribute exists (from plan 04)
</verification>

<success_criteria>
- Zero mypy errors in llm/rewriter.py
- `uv run mypy src/` exits 0 — entire codebase clean
- DEFAULT_SYSTEM_PROMPT bug fixed (was tuple, now str)
- All 281 tests pass
</success_criteria>

<output>
After completion, create `.planning/phases/11-manual-ruff-cli-mypy/11-05-SUMMARY.md`
</output>
