# 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).
