# LLM Integration Module — Work Plan **Date**: 2026-02-10 **Status**: Implemented ## Overview Added `markitect/llm/` package providing concrete `LLMAdapter` implementations so any MarkiTect component can call an LLM through OpenRouter (HTTP) or Claude Code CLI (subprocess). ## Module Layout ``` markitect/llm/ ├── __init__.py # Public API ├── exceptions.py # LLMError hierarchy (extends MarkitectError) ├── config.py # LLMConfig dataclass, API key resolution ├── _http.py # Sync HTTP helper (urllib.request) ├── _token_estimator.py # Rough token counting for CLI backend ├── openrouter.py # OpenRouterAdapter(LLMAdapter) ├── claude_code.py # ClaudeCodeAdapter(LLMAdapter) └── factory.py # create_adapter() factory function ``` ## Design Decisions - Implements existing `LLMAdapter` ABC — no interface changes - No new pip dependencies (stdlib only: urllib.request, subprocess) - API key resolution: constructor arg > env var > project-root key file - Factory pattern: `create_adapter("openrouter")` or `create_adapter("claude-code")` ## Testing - 42 unit tests in `tests/unit/llm/` (all mocked, no network) - Integration tests in `tests/integration/llm/` (skip if no API key / CLI) ## Example Integration `examples/infospace-with-history/process_chapters.py` accepts `--provider` and `--model` CLI args. When a provider is specified, each pipeline stage auto-generates output via the LLM adapter instead of waiting for manual input. ## Verification ```bash # Unit tests pytest tests/unit/llm/ -v # Integration (OpenRouter) OPENROUTER_API_KEY=$(cat apikey-openrouter.txt) pytest tests/integration/llm/test_openrouter_live.py -v # Integration (Claude Code CLI) pytest tests/integration/llm/test_claude_code_live.py -v # End-to-end python examples/infospace-with-history/process_chapters.py \ --chapter book-1-chapter-03 --provider claude-code --no-commit ```