# Instrumentation Spec: Маркетплейс готовых ИИ-агентов

> **Дата:** 2026-08-26 | **Источник:** Metric Design + PRD
> **Ревизия:** 2026-08-27 — Discovery по базе `00-research-evidence-base.md` (~70 источников, ~60 карточек T1/T2). Добавлены события установки/doctor/guardrails/версий. См. § Ревизия внизу.

---

## Event Schema

### События сайта (Яндекс.Метрика)

| Событие | Параметры | Триггер | Цель |
|---|---|---|---|
| `catalog_view` | — | Просмотр страницы каталога | Измерить трафик каталога |
| `package_view` | `package_id`, `platform` | Просмотр карточки агента | Измерить интерес к агенту |
| `platform_selected` | `package_id`, `platform` | Выбор платформы на карточке | Измерить выбор платформы |
| `buy_clicked` | `package_id`, `platform`, `price` | Нажатие кнопки «Купить» | Измерить конверсию в покупку |
| `telegram_started` | `package_id`, `platform` | Переход в Telegram | Измерить конверсию в Telegram |
| `free_clicked` | `package_id`, `platform` | Нажатие кнопки «Получить бесплатно» | Измерить спрос на бесплатные |

### События Telegram-бота (SQLite/JSON)

| Событие | Параметры | Триггер | Цель |
|---|---|---|---|
| `bot_start` | `user_id` | Первый запуск бота | Измерить охват бота |
| `package_selected` | `user_id`, `package_id`, `platform` | Бот получает параметры из ссылки | Измерить конверсию |
| `intent_confirmed` | `user_id`, `package_id`, `platform` | Пользователь подтверждает намерение купить | Измерить заинтересованность |
| `payment_confirmed` | `user_id`, `package_id`, `platform`, `amount` | Администратор подтверждает оплату | Измерить продажи |
| `package_delivered` | `user_id`, `package_id`, `platform`, `version` | Архив отправлен | Измерить выдачу |
| `install_success` | `user_id`, `package_id`, `platform` | Пользователь сообщает об успешной установке | Измерить установки |
| `install_error` | `user_id`, `package_id`, `platform`, `error_type` | Пользователь сообщает об ошибке | Измерить проблемы |
| `support_requested` | `user_id`, `package_id`, `platform`, `issue_type` | Обращение в поддержку | Измерить нагрузку |

---

## Metric Queries

### Воронка

```sql
-- Конверсия: посетитель → карточка → покупка → установка
SELECT
  COUNT(DISTINCT package_view) as views,
  COUNT(DISTINCT buy_clicked) as buy_clicks,
  COUNT(DISTINCT payment_confirmed) as purchases,
  COUNT(DISTINCT install_success) as installs
FROM events
WHERE date >= '2026-09-30'
```

### Retention

```sql
-- Повторное использование через 7 дней
SELECT
  COUNT(DISTINCT user_id) as users_with_2nd_use
FROM events
WHERE event_type = 'install_success'
  AND user_id IN (
    SELECT user_id FROM events
    WHERE event_type = 'install_success'
    GROUP BY user_id
    HAVING COUNT(*) >= 2
  )
```

---

## Dashboard (MVP)

| Метрика | Источник | Обновление |
|---|---|---|
| Посетители сайта | Яндекс.Метрика | Ежедневно |
| Просмотры карточек | Яндекс.Метрика | Ежедневно |
| Покупки | Бот (SQLite) | Ежедневно |
| Установки | Бот (SQLite) | Ежедневно |
| Ошибки установки | Бот (SQLite) | Ежедневно |
| Обращения в поддержку | Бот (SQLite) | Ежедневно |

---

## Ревизия 27.08.2026 — по итогам Discovery (база `00-research-evidence-base.md`)

> Основание: `product/00-research-evidence-base.md` (27.08.2026) — находки 3 (установка — барьер №1), 5 (guardrails killer-фича), 9 (гниение статики), ZIP 2.1.243 провал (SIGSEGV/autoupdate). Исходная схема выше сохранена как артефакт до-Discovery; ниже — дельта. Новые события дополняют, а не заменяют исходные (совместимость с ботом/SQLite).

### Новые события (P0 для MVP)

#### A. Установка — заменить самоотчёт на инструментированную воронку

Исходные `install_success` / `install_error` (самоотчёт пользователя) оставляем для обратной совместимости, но **источником истины** становится инструментированная воронка из installer/doctor. Мерить `time-to-first-successful-task`, а не «скачал ZIP» (находка 3).

| Событие | Параметры | Триггер (кто пишет) | Цель |
|---|---|---|---|
| `install_started` | `user_id`, `package_id`, `platform`, `version`, `model_version`, `os`, `install_method` (`npx` \| `web_fallback` \| `manual`) | `install.sh` при запуске (до любых сайд-эффектов) | Знаменатель воронки установки; ловит SIGSEGV-провалы как `install_failed` без `install_started` — см. ZIP 2.1.243 |
| `install_success` (v2) | `user_id`, `package_id`, `platform`, `version`, `model_version`, `os`, `duration_ms`, `install_method` | `install.sh` при коде 0 + `doctor_check` = pass | Числитель; `duration_ms` = time-to-first-success |
| `install_failed` | `user_id`, `package_id`, `platform`, `version`, `model_version`, `os`, `error_type`, `error_stage`, `duration_ms`, `install_method` | `install.sh` при ненулевом коде или `doctor_check` = fail | Детализация провалов; `error_type`: `sigsegv` \| `node_missing` \| `permission_denied` \| `token_invalid` \| `network` \| `model_mismatch` \| `unknown` |

> Дедупликация: `install_success` v2 пишет тот же `event_type`, что и старый самоотчёт, но с обязательными полями `version`/`model_version`/`install_method`/`duration_ms`. Запросы различают источник по наличию `install_method`.

#### B. Doctor-проверки

| Событие | Параметры | Триггер | Цель |
|---|---|---|---|
| `doctor_check` | `user_id`, `package_id`, `platform`, `version`, `model_version`, `os`, `check` (`deps` \| `token` \| `permissions` \| `model_pinned` \| `overall`), `result` (`pass` \| `fail` \| `warn`), `details` | `doctor.sh` после каждой проверки | Диагностика «почему не установилось»; `overall=pass` = «зелёная галочка: агент готов» (P0 §7 базы) |

#### C. Guardrails — обязательное логирование срабатываний

| Событие | Параметры | Триггер | Цель |
|---|---|---|---|
| `guardrail_triggered` | `user_id`, `package_id`, `platform`, `version`, `model_version`, `guardrail` (`email_delete_limit` \| `budget_cap` \| `publish_confirm` \| `token_scope` \| `rate_limit` \| `other`), `action` (`blocked` \| `confirm_requested` \| `confirmed` \| `denied`), `resource` | Код транспорта агента при попытке выйти за hard-limit (находка 5) | Доказать ценность guardrails; без этого события QA задачи №31 из 23-deliver не считается закрытой |

#### D. Версионирование — модель и Kit

Ко всем событиям установки/doctor/guardrails уже добавлены `version` (версия Kit) и `model_version` (пин модели). Дополнительно:

| Событие | Параметры | Триггер | Цель |
|---|---|---|---|
| `model_version` | `package_id`, `platform`, `version`, `model_version`, `previous_model_version` | Публикация Kit / миграция модели | Отследить «гниение» (находка 9 — Polza/DeepSeek V4) и эффект смены модели на `install_failed`/`guardrail_triggered` |

> Связка: `model_version` — не пользовательское событие, а релиз-событие. Пишется в ту же таблицу с `user_id = NULL`, чтобы JOIN по `(package_id, platform, version)` показывал, какая модель стояла на момент каждой установки.

### Обновлённые Metric Queries

#### Воронка установки (инструментированная, а не самоотчёт)

```sql
-- Воронка: started → success / failed (истинная конверсия установки)
-- Знаменатель — install_started, а не buy_clicked
SELECT
  COUNT(DISTINCT CASE WHEN event_type='install_started' THEN user_id END)  AS started,
  COUNT(DISTINCT CASE WHEN event_type='install_success' THEN user_id END)  AS success,
  COUNT(DISTINCT CASE WHEN event_type='install_failed' THEN user_id END)   AS failed,
  ROUND(100.0 * COUNT(DISTINCT CASE WHEN event_type='install_success' THEN user_id END)
        / NULLIF(COUNT(DISTINCT CASE WHEN event_type='install_started' THEN user_id END),0),1) AS success_rate_pct,
  AVG(CASE WHEN event_type='install_success' THEN duration_ms END) AS avg_time_to_success_ms
FROM events
WHERE package_id = :package_id AND date >= '2026-09-30';

-- Разрез по методу установки (npx-first vs web_fallback — урок ZIP 2.1.243)
SELECT install_method, COUNT(*) AS n,
       AVG(duration_ms) AS avg_ms,
       SUM(CASE WHEN event_type='install_failed' AND error_type='sigsegv' THEN 1 ELSE 0 END) AS sigsegv_cnt
FROM events
WHERE event_type IN ('install_success','install_failed')
GROUP BY install_method;
```

#### Doctor-диагностика

```sql
-- Где сыпется doctor
SELECT check, result, COUNT(*) AS n
FROM events
WHERE event_type='doctor_check' AND result != 'pass'
GROUP BY check, result
ORDER BY n DESC;

-- Доля «зелёных галочек»
SELECT
  ROUND(100.0 * SUM(CASE WHEN check='overall' AND result='pass' THEN 1 ELSE 0 END) / COUNT(*),1) AS green_pct
FROM events WHERE event_type='doctor_check' AND check='overall';
```

#### Guardrails

```sql
-- Срабатывания guardrails по типу
SELECT guardrail, action, COUNT(*) AS n
FROM events
WHERE event_type='guardrail_triggered'
GROUP BY guardrail, action
ORDER BY n DESC;

-- Попытки без guardrails были бы инцидентами (blocked + confirm_requested)
SELECT COUNT(*) AS prevented_incidents
FROM events
WHERE event_type='guardrail_triggered' AND action IN ('blocked','confirm_requested');
```

#### Версионирование / гниение

```sql
-- Успешность установки по версии Kit и модели
SELECT version, model_version,
       COUNT(DISTINCT CASE WHEN event_type='install_success' THEN user_id END) AS success,
       COUNT(DISTINCT CASE WHEN event_type='install_failed' THEN user_id END)  AS failed
FROM events
WHERE event_type IN ('install_success','install_failed')
GROUP BY version, model_version
ORDER BY version DESC;
```

#### Главная воронка MVP (paid → first successful business outcome)

```sql
-- Единственная метрика, закрывающая главный вопрос Discovery:
-- «заплатят ли за reusable workflow и дойдут ли до бизнес-результата»
SELECT
  COUNT(DISTINCT CASE WHEN event_type='payment_confirmed' THEN user_id END) AS paid,
  COUNT(DISTINCT CASE WHEN event_type='install_success' THEN user_id END)   AS installed,
  -- first business outcome — событие агента (пишет сам Kit, напр. posts_published / wb_cards_created)
  COUNT(DISTINCT CASE WHEN event_type='first_business_outcome' THEN user_id END) AS first_outcome,
  ROUND(100.0 * COUNT(DISTINCT CASE WHEN event_type='first_business_outcome' THEN user_id END)
        / NULLIF(COUNT(DISTINCT CASE WHEN event_type='payment_confirmed' THEN user_id END),0),1) AS paid_to_outcome_pct
FROM events
WHERE date >= '2026-09-30';
```

### Dashboard — новые строки

| Метрика | Источник | Обновление | Порог MVP |
|---|---|---|---|
| `install_success / install_started` | `install.sh`/`doctor.sh` | Ежедневно | ≥70% |
| `avg time-to-first-success` | `install_success.duration_ms` | Ежедневно | <15 мин (p50) |
| `doctor overall pass` | `doctor_check` | Ежедневно | ≥90% |
| `guardrail_triggered` (by guardrail) | код транспорта | Ежедневно | >0 = фича работает; всплеск `blocked` → проверить лимиты |
| `sigsegv / install_failed` | `install_failed` | Ежедневно | 0 (регресс ZIP 2.1.243) |
| `paid → first_outcome` | бот + Kit | Ежедневно | ≥3 пользователя с outcome за 30 дней |

### Связь с чек-листом

- QA задач №29–32 из `23-deliver-launch-checklist.md` (ревизия 27.08) считается закрытым только при наличии соответствующих событий в этой спецификации.
- События пишутся локально (SQLite/JSON) + дублируются в Яндекс.Метрику где применимо; PII — только `user_id` (Telegram ID), без содержимого писем/постов.
