Files
portal/docs/adr/ADR-019-research-tooling.md
T
2026-06-14 15:44:42 +03:00

149 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ADR-019: Off-phase research-tooling (Perplexity Pack)
**Status:** Accepted
**Date:** 2026-06-14
**Контекст:** эпик «Perplexity Pack», spec `docs/superpowers/specs/2026-06-14-perplexity-pack-research-tooling-design-v3.md`, провенанс-вет `docs/research/research-vet.md`.
## Context
В тулчейне Лидерры не было выделенного слоя веб-разведки. Существующие узлы дают
знания узких типов: `context7` (#60) — документация библиотек/SDK; `openapi`-mcp (#47)
— интроспекция нашего REST-API; `Laravel Boost` (#10) — Laravel-экосистема и runtime-запросы;
`Sentry`/`Redis` MCP (#34/#35) — runtime-факты прод-системы; `graphify` (#86) — внутренний
граф проекта; `GitHub` MCP (#3) — операции с репозиторием. Ни один не покрывает **открытый
веб**: актуальные практики, нормативные требования, фич-разведку конкурентов, deep-research
с цитатами.
Три зрелых MCP-сервера закрывают этот пробел: **perplexity** (ранжированный ответ-с-источниками поверх sonar), **exa** (нейро/семантическое обнаружение источников), **firecrawl** (глубокое чтение и обход страниц). Все три присутствовали только в ветке `worktree-perplexity-pack`;
main и нормативка их не знали.
Аналогичный паттерн «новый off-phase слой» закрывался ранее: A8 infosec (ADR-014), C1
marketing (ADR-015), knowledge-graph (ADR-017). Дисциплина та же: провенанс-вет IS9 →
перенос конфигурации в main → формализация в нормативке → реестр узлов.
**Риск ecosystem.** Все три — внешние пакеты с платными API-ключами. Snyk/SentinelOne
«ToxicSkills» 2025: ≈13% маркетплейс-артефактов содержат критичные дефекты. Провенанс-гейт
IS9 (прецедент A8/C1) обязателен ДО формализации; вет завершён — `docs/research/research-vet.md`,
все три **ПРИНЯТ**.
**Решение заказчика (зафиксировано):** платные API приняты владельцем (owner waiver,
Вариант 2); ключи (`PERPLEXITY_API_KEY` / `EXA_API_KEY` / `FIRECRAWL_API_KEY`) живут только
в пользовательском окружении, никогда в репозитории.
## Decision
Принят слой **research-tooling** — новая **20-я off-phase подкатегория**, номера Tooling
**#87#89**, классификация роутера `research`.
| # | Узел | Источник | Тип | Назначение |
|---|---|---|---|---|
| 87 | perplexity MCP | `@perplexity-ai/mcp-server` | внешний MCP, READ-ONLY | ранжированный ответ-с-источниками (search/ask/research/reason; sonar) |
| 88 | exa MCP | `exa-mcp-server` (exa-labs) | внешний MCP, READ-ONLY | семантическое/нейро обнаружение источников (web_search_exa/web_fetch_exa) |
| 89 | firecrawl MCP | `firecrawl-mcp` (Firecrawl/Mendable) | внешний MCP, READ-ONLY (read-тяжёлый) | глубокое чтение и обход (scrape/batch/map/search/crawl/extract + agent) |
**Детали решений:**
1. **#87 perplexity** — первичный «дай ответ-с-источниками». Четыре инструмента поверх
sonar-моделей: `perplexity_search` (ранжированный web), `perplexity_ask` (sonar-pro
real-time), `perplexity_research` (sonar-deep-research, медленный 30s+), `perplexity_reason`
(sonar-reasoning-pro). READ-ONLY. Базовый URL через AITUNNEL-прокси (`PERPLEXITY_BASE_URL`).
2. **#88 exa** — обнаружение того, что keyword-поиск пропускает: семантический `web_search_exa` плюс `web_fetch_exa`. READ-ONLY.
3. **#89 firecrawl** — прочитать страницу целиком/обойти сайт/извлечь структурированное;
`firecrawl_agent` — автономный web-research. READ-ONLY (read-тяжёлый режим).
**Gate-постура (реализована, commit `bfc1f575`):** все инструменты трёх серверов
(`mcp__perplexity__*` / `mcp__exa__*` / `mcp__firecrawl__*`) классифицированы как **read_only**
в `tools/mcp-tool-classifier.mjs` (+тест). Это не намерение, а зафиксированный факт: router-gate
пускает их без approve, мутаций они не несут.
## Boundaries (конфликт-аудит)
- **RT1 — ↔ context7 (#60):** разные слои знаний. context7 = документация библиотек/SDK
(vendor docs известного пакета); research-tooling = открытый веб — практики, нормы,
конкуренты, новости. context7 первый для «как настроить пакет X»; research для «что
индустрия делает с Y».
- **RT2 — ↔ openapi-mcp (#47):** разный объект. openapi = наш REST-спек (introspection
endpoints/схем); research = внешние источники в вебе.
- **RT3 — ↔ Laravel Boost (#10):** разный масштаб. Boost = Laravel-экосистема и runtime-запросы
в app/; research = веб вне проекта.
- **RT4 — ↔ Sentry (#34) / Redis (#35):** разная плоскость. Sentry/Redis = runtime-факты
прод-системы (ошибки/очереди/кэш); research = внешние знания.
- **RT5 — ↔ graphify (#86):** направление. graphify = внутренний граф проекта (наружу не
ходит); research = наружу, в открытый веб. Post-mortem: graphify даёт blast radius внутри,
research приносит внешний контекст.
- **RT6 — ↔ GitHub MCP (#3):** разный канал. GitHub = операции с репозиторием/issues/PR;
research = открытый веб.
- **RT7 — внутренние слои (anti-overlap внутри пака):** хотя все три «ищут в вебе», роли
не пересекаются. **perplexity** = ранжированный ответ-с-источниками; **exa** = семантическое
обнаружение источников по смыслу; **firecrawl** = глубокое чтение/обход конкретных страниц.
Канонический порядок — связка L17: perplexity (ответ) → exa (обнаружение) → firecrawl
(глубокое чтение).
- **RT8 — платные API + запрет авто-трат:** все три держат платные ключи (прецедент MKT8
/ READ-ONLY Sentry/Redis). Ключи только в пользовательском окружении; без авто-расхода
без нужды; gitleaks стережёт утечку в репозиторий.
- **RT9 — классификация `research` ≠ analysis/knowledge_graph_query/planning:** `research`
= разведка широты во внешнем вебе на крупных/абстрактных задачах. Не перехватывает
`analysis` (статанализ кода — Semgrep/ToB), `knowledge_graph_query` (внутренний граф —
graphify), `planning` (Superpowers/CCPM). Разграничение — триггер-ключевые слова +
настоящий ADR.
## Alternatives Considered
- **Только WebSearch/WebFetch (встроенные)** — отклонено: дают сырой список/одну страницу,
без ранжированного ответа-с-источниками, без семантического обнаружения, без глубокого
обхода. research-tooling — качественный апгрейд.
- **Один сервер вместо трёх** — отклонено: роли не дублируются (RT7); ответ ≠ обнаружение ≠
глубокое чтение. Один сервер не закрывает все три потребности.
- **DEFERRED до Б-1** — отклонено: владелец принял платные API сейчас (owner waiver);
слой полезен немедленно для разведки практик/норм при проектировании.
## Consequences
**Positive:**
- Закрыт пробел «открытый веб»: 0 → 3 узла research-разведки.
- Новая **20-я off-phase подкатегория research-tooling**; номера #87#89.
- Связка **L17** research chain (`brainstorming` → perplexity → exa → firecrawl) в
routing-off-phase.md (canonical chain).
- Провенанс-вет IS9 всех трёх пройден ДО формализации — ни одного FAIL.
- Gate-постура read_only зафиксирована в коде (не декларация): мутаций нет.
**Neutral / Cautionary:**
- Платные API: расход контролируется дисциплиной (без авто-вызовов без нужды); ключи в env.
- Bulk-load MCP-инструментов исторически ронял субагентов API-ошибкой; +3 сервера
увеличивают суммарное число инструментов — митигация через deferred-tools (схемы по запросу),
риск помечен в дом-README раздела.
- `perplexity_research` медленный (30s+) — для глубоких задач, не для быстрых вопросов.
## Related Decisions
- **ADR-014** — A8 infosec-tooling; IS9-провенанс-дисциплина, прецедент платных/внешних.
- **ADR-015** — C1 marketing-tooling; паттерн «пустой/новый слой → наполнение», MKT8
(READ-ONLY + запрет авто-трат) — прямой предок RT8.
- **ADR-017** — knowledge-graph-tooling; граница «внутрь vs наружу» (graphify ↔ research, RT5).
## Enforcement
Граница research-tooling против смежных узлов (RT1–RT9) проверяется при маршрутизации: задача
«открытый веб / практики / нормы / конкуренты» → research-узлы (#87#89); задача «документация
библиотеки» → context7 (#60); «наш API» → openapi (#47); «внутренний граф» → graphify (#86);
«runtime прод» → Sentry/Redis (#34/#35). Read-only-постура трёх серверов закреплена в
`tools/mcp-tool-classifier.mjs` (+тест в `tools/mcp-tool-classifier.test.mjs`) — router-gate
пускает их без approve и блокирует любую не-read_only попытку по умолчанию. Ключи API только
в пользовательском окружении; gitleaks (pre-commit/pre-push) блокирует утечку в репозиторий.
Узлы #87#89 живут в `docs/registry/nodes.yaml` (`subcategory: research-tooling`,
`triggers.classification: research`); инвариант покрытия карточками (Машина 3-E) требует
контракт-карточку на каждый узел (`docs/registry/contracts/{perplexity,exa,firecrawl}-mcp.contract.json`).
## References
- `docs/superpowers/specs/2026-06-14-perplexity-pack-research-tooling-design-v3.md` — design (D1D9).
- `docs/research/research-vet.md` — IS9 провенанс-вет (#87/#88/#89, все ПРИНЯТ).
- `docs/research/README.md` — дом раздела research-tooling.
- `docs/Tooling_v8_3.md` §4.60–§4.62 — 9-атрибутные блоки узлов #87#89.
- `docs/Plugin_stack_rules_v1.md` R10.1 Блок 3 + R15.6 — реестр ролей MCP-серверов.
- `docs/Pravila_raboty_Claude_v1_1.md` §13.2 — Off-phase research-tooling абзац.
- `docs/routing-off-phase.md` — связка L17 (research chain) + routing #87#89.
- `.mcp.json` — три блока mcpServers (perplexity/exa/firecrawl); commit `bfc1f575` (gate read_only).