ADR-0045: Tier 3 LLM matcher + matching moderation queue

Status: accepted Date: 2026-04-29 Deciders: agent-claude

Контекст

Tier 1 (точное MPN) + Tier 2 (отпечаток) уже работают в matcher-worker. Probable cases (Tier 2 score 0.5–0.8) тихо пишутся как MatchConfidenceProbable без верификации. Конфликты Tier 1 (один MPN — несколько canonical-ов) застревают со статусом MatchStatusConflict. Manual review pipeline отсутствует.

ADR-0044 ввёл platform/llm через CLIProxy + sashabaranov SDK. Этот ADR описывает первый consumer LLM на match-стороне, плюс matching-specific moderation queue для weak/probable LLM-результатов.

Решение

  1. Tier 3 LLM-валидация синхронно в MatcherService.RunBatch. После Tier 1+2 неоднозначные кейсы собираются в pending list; единый batched LLM call (chunks of 20); результаты apply’ятся с маппингом per spec §4.3.
  2. Два разных prompt builders — binary для probable (1 candidate), conflict для multi-candidate selection. Два LLM call’а: один батч для probable, один для conflict.
  3. Confidence маппинг строго per spec §4.3. ≥0.85 strong, 0.7–0.85 probable, <0.7 weak, !match unmatched.
  4. Matching-specific moderation queue (match_moderation_queue) — таблица в matching BC, UNIQUE partial idx (offer_id) WHERE status='pending' для идемпотентности. Общий cross-source Moderation BC выделим когда появится второй consumer.
  5. Admin HTTP endpoints в matching/api/http с Bearer-token middleware (ENV ADMIN_API_KEY). Empty key → 503 (нельзя случайно залить prod без auth).
  6. LLM failure handling без auto-retry. Chunk dropped с метрикой match.tier3.chunk_dropped{reason}. Decisions остаются с pre-LLM статусом. Manual re-trigger через CLI — отдельным циклом.
  7. Reuse platform/llmLLMClient.Chat(model=ModelMatch=sonnet, JSONMode=true). Никаких extension’ов в platform/llm.

Последствия

Плюсы:

  • Probable + conflict cases больше не висят без обработки.
  • Реальный pipeline для ручного review с явным lifecycle.
  • Базис для будущего общего Moderation BC.

Минусы / accepted trade-offs:

  • LLM cost растёт: Sonnet дороже Haiku, conflict prompts длиннее. Мониторинг через CLIProxy usage stats.
  • Reject на tier1-conflict не откатывает LLM-выбор (известное ограничение первого цикла).
  • Нет multi-reviewer claim, нет auto-retry.

Альтернативы, отклонённые

  • Async Tier 3 в отдельном воркере — отклонено: добавляет процесс, удлиняет feedback loop.
  • Без moderation queue (только confidence) — отклонено per user signal: «довести этап максимально».
  • Общий Moderation BC сразу — отклонено: преждевременная абстракция.

Реализация

Затронутые компоненты:

backend/internal/core/matching/:

  • domain/llm_validator.go, moderation.go, prompt.go, metrics.go
  • app/llm_validator.go (BatchedValidator)
  • app/matcher.go (расширение — pending collection + apply)
  • app/moderation_service.go
  • app/metrics.go (AtomicMatchingMetrics)
  • infra/postgres/moderation_repo.go
  • infra/postgres/decision_repo.go (+llm_confidence column)
  • infra/postgres/candidate_reader.go (+GetCanonicalDetails, +GetOfferDigest)
  • api/http/moderation_handler.go, admin_auth.go, dto.go
  • di.go (full rewrite — providers + handler registrar)

backend/migrations/:

  • 0038_create_match_moderation_queue.sql
  • 0039_match_decisions_llm_confidence.sql

backend/cmd/matcher-worker/main.go — добавлен llm.Module.

backend/internal/platform/config/config.goAdmin{APIKey} struct.

Deferred items

  1. Общий cross-source Moderation BC (после второго consumer).
  2. AI-агентная модерация в sandbox (Phase 4 AI-слой).
  3. Auto-retry on LLM failure.
  4. Multi-reviewer claim mechanism.
  5. LLM cost tracking aggregation.
  6. Reject-handler для tier1-conflict (manual override).
  7. UI для moderation review.
  8. Expired auto-cleanup для stale pending items.

Ссылки

  • ADR-0044 — LLM gateway + char-pipeline foundation
  • ADR-0030 — Backend DI rule
  • Spec Phase 2 от 21 апреля — docs/superpowers/specs/2026-04-21-phase2-matcher-llm-design.md
  • Spec этого цикла — docs/superpowers/specs/2026-04-29-tier3-llm-matcher-design.md
  • Plan этого цикла — docs/superpowers/plans/2026-04-29-tier3-llm-matcher.md