bcf644f893
PR-2 of DS AI routing policy (2026-05-23, see plan ~/.claude/plans/document-server-ai-cheeky-reddy.md + memory project_document_server_ai_routing_policy). DS 의 모든 backend 호출이 llm-router :8890 단일 경유. 정칙 정합: - 신규 RouterBackend (services/llm/backends.py) — alias 별 router POST + requires_gate 분기 (mac-mini-default 만 llm_gate FOREGROUND 보호). - 기존 GemmaMacMiniBackend + QwenMacBookBackend = legacy 보존 (DS_BACKENDS_VIA_ROUTER=false rollback safety only). 1주 후 별 cleanup PR (PR-DS-Backends-Legacy-Cleanup-1) 로 폐기. - get_backend factory dual-path (env flag) — backward-compat (gemma-macmini alias → mac-mini-default 매핑). - search.py:457 Query pattern 확장: mac-mini-default|claude-cloud|auto 추가. /ask/react 의 isinstance(QwenMacBookBackend) → hasattr duck-typing (RouterBackend + Legacy 모두 generate_with_tools 구현). - SearchAskBackendConfig 에 router_url 신규 (env LLM_ROUTER_URL 또는 hardcoded MVP default http://100.76.254.116:8890). - docker-compose.yml fastapi env 에 LLM_ROUTER_URL + DS_BACKENDS_VIA_ROUTER 추가. AIClient (_call_chat, call_triage, call_primary, call_fallback) 경유 path 는 별 PR (PR-AIClient-Router-Migration-1) — MVP scope C 채택, 회귀 risk 최소화. Closure (즉시 fixture/matrix): - factory smoke 6 alias (None/mac-mini-default/gemma-macmini/ qwen-macbook/claude-cloud/auto) + 1 invalid (nonsense → ValueError). - live 3 case: mac-mini-default 200 \"pong! 🏓\" + qwen-macbook cold 502 upstream_502_primary=ConnectError + claude-cloud 503 provider_not_configured. - silent fallback 0 + direct M5/Mac mini socket 0 (RouterBackend 만 router 호출). Backup: ~/.local/share/ds-routing-pr2-backups/20260523/ (backends.py + config.py + search.py + docker-compose.yml). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>