d74d3113e5
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
149 lines
13 KiB
Markdown
149 lines
13 KiB
Markdown
# 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 (D1–D9).
|
||
- `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).
|