Files
ss-tools/specs/dashboard-verification-usecases.md
busya 31b9a19a0c chore: commit remaining workspace updates
Agent:
- lifecycle: run tracking, middleware hardening, langgraph setup
- tests: agent lifecycle + langgraph setup coverage

Backend:
- async_job_runner: resilience hardening, tests
- agent_conversations: run lifecycle integration
- translate: scheduler + orchestrator SQL adjustments
- schemas/services: agent_lifecycle model extensions

Frontend:
- TaskDrawer: UX improvements
- TaskLogPanel/Viewer: safety hardening, i18n (en/ru)
- FilterBar: report filters contract + tests
- Reports page: layout adjustments

Specs:
- 036-agent-test-stabilization: runs contract, modules, events
- 037-superset-baseline-engine: catalog schema, testing API, modules
- 038-dashboard-scenario-model: scenario schema, capture profile, modules
- 039-dashboard-scenario-ui: screen models, release verification UX, modules
- dashboard-verification-usecases: new cross-cutting spec
2026-07-17 19:11:09 +03:00

61 KiB
Raw Blame History

Подсистема верификации дашбордов (036–039)

Для Project owner, BI-аналитиков и разработчиков FI-ПО. Июль 2026. Статус: спецификация готова, начало реализации.


О чём эта подсистема

Сегодня проверка дашборда после изменений выглядит так: открыть в браузере, прокликать фильтры, сверить числа глазами с Excel, сделать скриншот «на память». Через месяц повторить невозможно — никто не помнит, какие фильтры были применены и какие значения считались правильными.

Подсистема верификации дашбордов делает три вещи:

  1. Фиксирует эталон — какие значения метрик считаются правильными для данного дашборда с данными фильтрами на момент релиза.
  2. Автоматически проверяет — совпадают ли текущие значения с эталоном при каждом деплое на PREPROD и PROD, еженедельно по расписанию и после каждой ETL-загрузки.
  3. Показывает изменения — что именно поменялось в структуре дашборда между релизами (фильтры, колонки, чарты), даже если числа не изменились.

Всё это встроено в существующий релизный пайплайн (dev → preprod → prod через git) и не требует отдельного запуска.


Почему это важно для каждой роли

Project owner

Вы отвечаете за корректность данных в хранилище. Сегодня вы узнаёте, что ETL перезалил данные за закрытый период, только когда аналитик случайно замечает расхождение в отчёте — через две недели после факта.

С этой подсистемой:

  • Каждый понедельник в 9:00 система автоматически проверяет все ключевые дашборды. Если данные за закрытый период изменились задним числом — вы получаете алерт в Rusal Pulse и автоматически созданный инцидент в YouTrack в течение минуты после обнаружения.
  • Публикация новых релизов дашборда блокируется до расследования — нельзя выкатить новую версию, пока не разобрались с целостностью данных.
  • Для каждого эталонного значения хранится source_response_hash — хеш ответа Superset API на момент фиксации. Это объективный proof того, что данные были именно такими.

BI-аналитику

Вы проверяете дашборды перед релизом. Сегодня вы вручную сверяете метрики, делаете скриншоты, сравниваете XLSX-выгрузки с экраном. Это занимает 30–40 минут на дашборд и на 100% зависит от вашей внимательности.

С этой подсистемой:

  • Вы нажимаете одну кнопку на странице дашборда в superset-tools — «Создать сценарий тестирования». Система сама предлагает план проверки: какие метрики сверить, какие скриншоты снять, какие фильтры применить.
  • Вы заполняете бизнес-параметры (дата, контрагент) — не технические. Система сама знает, какие инструменты использовать.
  • Результат: человекочитаемый отчёт — не JSON, а страница с таблицей «что проверено, какие значения, совпадает ли с эталоном».
  • При создании нового релиза система автоматически сравнивает метрики с предыдущим релизом и показывает, что изменилось. Вы только подтверждаете.
  • Визуальную проверку (скриншоты) анализирует LLM — подсвечивает подозрительные места, вы принимаете решение.

Разработчику FI-ПО

Вы отвечаете за релизный пайплайн дашбордов. Сегодня деплой на PREPROD и PROD — это чисто техническая операция: упаковали, залили, проверили, что Superset не упал. Содержательная проверка («а правильно ли дашборд показывает данные?») остаётся на совести аналитика и часто пропускается.

С этой подсистемой:

  • Верификация встроена в существующий пайплайн как дополнительные gates. Не нужно менять процесс — нужно только добавить policy.
  • При деплое на PREPROD: автоматический StructureDiff — если фильтр потерял scope или чарт удалён, деплой блокируется до подтверждения.
  • При создании релиза: автоматическая метрическая проверка. Если значения разъехались — релиз не создаётся.
  • При публикации в PROD: автоматическая проверка immutability закрытых периодов. Если данные изменились задним числом — публикация блокируется.
  • Всё настраивается через VerificationPolicy в GitRepository.release_policy — per-dashboard, с наследованием от installation-wide defaults.
  • Baseline.yaml живёт в том же git-репозитории, что и дашборд. Версионируется вместе с ним. Никакой отдельной базы, никакой синхронизации.

Сценарии использования

UC-1: Ad-hoc проверка дашборда аналитиком

Кто: BI-аналитик.
Когда: перед релизом, при подозрении на проблему, при аудите.
Режим: диалог с агентом.

1. Аналитик открывает дашборд FI-0080 в superset-tools (страница дашборда в нашем приложении, не в самом Superset), среда ss-dev.
2. Нажимает «Создать сценарий тестирования».
3. Попадает в /agent (встроенный чат superset-tools). Система уже знает контекст:
   dashboard_id=42, среда=ss-dev, цель=build_dashboard_test_scenario.

4. Агент: «Дашборд FI-0080. Что проверяем?»
   Аналитик: «Фильтры, метрику просроченной ДЗ, XLSX-выгрузку».

5. Агент показывает сценарий из 18 шагов — как бизнес-план, не как код:
   ┌──────────────────────────────────────────────────────────────┐
   │ Сценарий проверки FI-0080                                    │
   │                                                              │
   │ [Открыть дашборд] → [Применить фильтры] → [Метрика через API]│
   │     → [Скачать XLSX] → [Сравнить с baseline] → [Отчёт]       │
   │                                                              │
   │ Шагов: 18 | Инструменты: browser, Superset API, XLSX, report │
   └──────────────────────────────────────────────────────────────┘

6. Аналитик: «Добавь скриншоты вкладки с графиком».
   Агент обновляет сценарий — теперь 20 шагов.

7. Аналитик заполняет параметры:
   ┌──────────────────────────────────────────────────────────────┐
   │ Дата тестирования    [29.05.2026]                            │
   │ Контрагент           [АСК]                                   │
   │ Baseline             [использовать утверждённый (v1.2.3)]     │
   │ Скриншоты            [✓]                                     │
   └──────────────────────────────────────────────────────────────┘

8. Агент генерирует черновик. Аналитик видит артефакты:
   ┌──────────────────────────────────────────────────────────────┐
   │ dashboard_42_test_scenario/                                  │
   │ ├── scenario.yaml                     ✓                      │
   │ ├── runner.plan.json                  ✓                      │
   │ ├── xlsx_assertions.py                ⚠ нужен просмотр       │
   │ ├── report_template.md                ✓                      │
   │ └── evidence/                                                │
   │     └── screenshot_debt_tab.webp       ✓                     │
   └──────────────────────────────────────────────────────────────┘

9. Аналитик жмёт «Сохранить». Появляется подтверждение:
   ┌──────────────────────────────────────────────────────────────┐
   │ Сохранить артефакты?                                         │
   │ Путь: tests/generated/dashboards/fi_0080/                    │
   │ Файлов: 5 | Предупреждений: 1                                │
   │                                                              │
   │ [Подтвердить] [Отмена]                                       │
   └──────────────────────────────────────────────────────────────┘

10. Готово. Артефакты в git-репозитории дашборда.

Результат: проверка выполнена, результаты сохранены, эталоны зафиксированы. В любой момент можно повторить.


UC-2: Релиз дашборда с автоматической верификацией

Кто: Разработчик дашборда + Release manager.
Когда: каждый цикл dev → preprod → prod.
Режим: автоматический + structured panels (без агента).

РАЗРАБОТЧИК вносит изменения в Superset DEV:
  • Добавлен chart_400 «Распределение по регионам»
  • Исправлен layout главной вкладки
  • chart_300 «Детализация по месяцам» — удалён (устарел)

SYNC → COMMIT → PUSH → жмёт «Deploy to PREPROD».

───────────────────────────────────────────────────────────
АВТОМАТИЧЕСКИ (deploy hook):
───────────────────────────────────────────────────────────

StructureDiff: текущий dev vs baseline из v1.2.3 (последний релиз)

  Результат:
  ┌──────────────────────────────────────────────────────────┐
  │ ⛔ CRITICAL (1)                                          │
  │   chart_300 удалён                                      │
  │   Был в v1.2.3, отсутствует в текущем dev.              │
  │                                                          │
  │ ⚠ WARNING (1)                                           │
  │   chart_128: порядок колонок изменён                     │
  │   Было: [Контрагент, Сумма, %] → Стало: [Контрагент, %, Сумма]│
  │   Затронуто: XLSX-выгрузка, скриншоты                   │
  │                                                          │
  │ ℹ INFO (1)                                              │
  │   chart_400: новый чарт                                  │
  └──────────────────────────────────────────────────────────┘

  → DEPLOY ЗАБЛОКИРОВАН (CRITICAL не решён).

Разработчик на странице PREPROD-деплоя:
  Видит красную карточку «chart_300 удалён».
  Жмёт «Подтвердить», вводит комментарий:
    «Chart устарел, заменён на chart_400 «Распределение по регионам»»
  → CRITICAL разрешён.

  Жмёт «Deploy to PREPROD» повторно → деплой выполнен.

───────────────────────────────────────────────────────────
АВТОМАТИЧЕСКИ (post-deploy hook):
───────────────────────────────────────────────────────────

VerificationRun(trigger=deploy_to_preprod):

  Метрическая проверка:
    Просроченная ДЗ     1 234 567  ✓
    Доля просрочки      12,4%      ✓
    Всего должников     342        ✓
    chart_400 (новый)   —          ⚠ нет baseline
    ...

    Итого: 6✓ 1⚠ 0✕

  Визуальная проверка:
    2 скриншота снято, LLM находок нет → ✓

  XLSX:
    checksum изменился (порядок колонок другой) → ⚠

  Overall: ⚠ WARN

Страница PREPROD-деплоя, вкладка «Верификация»:
  ┌──────────────────────────────────────────────────────────┐
  │ Верификация PREPROD                                      │
  │                                                          │
  │ Структура: ✓ (CRITICAL решён)                            │
  │ Метрики: 6✓ 1⚠ — chart_400 без baseline                 │
  │ Визуально: ✓                                            │
  │ XLSX: ⚠ порядок колонок изменён                         │
  │                                                          │
  │ [Перезапустить] [Подтвердить]                            │
  └──────────────────────────────────────────────────────────┘

Разработчик жмёт «Validate deployment» — валидация пройдена.

───────────────────────────────────────────────────────────
RELEASE MANAGER создаёт релиз:
───────────────────────────────────────────────────────────

Имя: «v1.3.0 — график по регионам, фикс layout»
Версия: v1.3.0

  → Жмёт «Create release».

АВТОМАТИЧЕСКИ:
  • VerificationRun для PREPROD = WARN → OK (политика разрешает)
  • Baseline-наследование от v1.2.3:
    - 4 метрики унаследованы (chart_hash не изменился)
    - 2 метрики переизвлечены (chart_hash изменился)
    - 1 метрика — новая (chart_400)
  • StructureDiff v1.2.3 → v1.3.0: 0 CRITICAL, 1 WARNING, 1 INFO
  • VerificationRun(trigger=release_create): ✓ PASS

Страница релиза v1.3.0:
  ┌──────────────────────────────────────────────────────────┐
  │ Релиз v1.3.0                                             │
  │                                                          │
  │ Верификация: ✓ PASS                                      │
  │   Структура: 0/1/1 (все решены)                          │
  │   Baseline: 7 метрик (4 унаследовано, 2 переизвлечено,   │
  │             1 новый)                                     │
  │                                                          │
  │ [Approve]                                                │
  └──────────────────────────────────────────────────────────┘

Release manager жмёт «Approve», вводит комментарий.
Затем жмёт «Publish to PROD».

АВТОМАТИЧЕСКИ (publish hook):
  • PREPROD matches release ✓
  • drift_status = in_sync ✓
  • VerificationRun re-check ✓
  • Immutability: закрытых периодов нет → OK

Релиз v1.3.0 опубликован в PROD.

Post-publish: VerificationRun фиксирует метрики PROD
             для будущих scheduled-проверок.

Результат: релиз прошёл через структурную, метрическую и визуальную проверку автоматически. Аналитик и release manager только подтверждали решения на каждом gate.


UC-3: Еженедельная автоматическая проверка PROD

Кто: никто (полный автомат).
Когда: каждый понедельник 9:00 MSK.
Режим: cron → алерт при проблемах.

Scheduler: понедельник 9:00.
Для каждого дашборда с policy.scheduled_verification_enabled=true:

  1. Берёт последний опубликованный релиз
  2. Берёт его baseline.yaml из git
  3. Для каждой метрики: Superset API запрос → сравнение с expected
  4. Для закрытых периодов: сравнение source_response_hash
  5. Результат: VerificationRun(trigger=scheduled, env=prod)

ТРИ ВОЗМОЖНЫХ ИСХОДА:

Сценарий A — Всё OK:
  Все метрики совпадают. Закрытые периоды не нарушены.
  → VerificationRun: ✓ PASS
  → Тихая запись в историю проверок
  → На странице дашборда зелёный значок «Последняя проверка: ✓»

Сценарий B — Данные изменились (открытый период):
  Метрика «Всего должников»: было 342 → стало 358
  → VerificationRun: ⚠ WARN
  → Алерт в Rusal Pulse #dashboard-alerts (низкий приоритет):
    «FI-0080: 1 метрика изменилась. Всего должников: 342→358 (+16)»
  → На странице дашборда жёлтый значок

Сценарий C — Immutability violation (закрытый период):
  Метрика «Просроченная ДЗ», период май 2026 (закрыт 01.06)
  source_response_hash изменился!
  
  → VerificationRun: ⛔ BLOCKED (immutability_violation)
  → CRITICAL алерт в Rusal Pulse #incidents:
    «⛔ FI-0080: НАРУШЕНИЕ НЕИЗМЕННОСТИ ДАННЫХ.
     Период: май 2026. Метрика: Просроченная ДЗ.
     Baseline (01.06): 1 234 567.89
     Сейчас (14.07):   1 500 000.00
     [Подробнее] [Создать инцидент]»
  → Автоматически создан YouTrack issue
  → Публикация новых релизов FI-0080 заблокирована
  → На странице дашборда красный баннер до расследования

Результат: целостность данных проверяется автоматически и непрерывно. Нарушения детектятся в день возникновения, а не через две недели руками аналитика.


UC-4: ETL-triggered — проверка после загрузки данных

Кто: никто (event-driven).
Когда: сразу после завершения ETL-процесса.
Режим: maintenance event → верификация затронутых дашбордов.

ETL-процесс «Загрузка финансовых данных» завершился в 06:15.
Maintenance event: ended, datasets_affected=[
  dataset_finance_debt (id=77),
  dataset_finance_receivables (id=82)
]

Event listener (автоматически):
  1. Ищет все дашборды, использующие затронутые dataset-ы:
     → FI-0080 (dataset 77), FI-0042 (dataset 82)
  
  2. Для каждого запускает VerificationRun(trigger=etl_completed):
     — Метрическая проверка ТОЛЬКО метрик на затронутых dataset-ах
     — Immutability check для закрытых периодов
  
  3. Результаты через 45 секунд:
     FI-0080: ✓ PASS — данные загружены корректно
     FI-0042: ⚠ WARN — 2 метрики изменились (периоды открытые)
  
  4. Сводный алерт:
     «ETL «Загрузка финансовых данных» завершён в 06:15.
      Проверено дашбордов: 2. Результат: 1✓ 1⚠.
      FI-0042: Всего контрагентов 847→852, Средний срок 34→36 дней.
      [Подробнее]»

Результат: Project owner узнаёт о проблеме с данными через минуту после завершения ETL, а не когда аналитик заметит расхождение в отчёте через три дня.


UC-5: Immutability violation — полный сценарий

Кто: Автоматика → Project owner → DBA.
Когда: scheduled-проверка обнаружила изменение данных задним числом.
Режим: автоматическое обнаружение + ручное расследование.

Понедельник 14.07.2026, 9:00. Scheduled-проверка FI-0080.

Для baseline_entry «Просроченная ДЗ» (период май 2026, закрыт 01.06):
  immutability.enabled = true
  immutability.policy = block_publish
  expected.value (на 01.06) = 1 234 567.89
  source_response_hash (на 01.06) = sha256:aaa111...

Сейчас (14.07, тот же запрос к Superset):
  actual.value = 1 500 000.00
  source_response_hash = sha256:bbb222...  ← НЕ СОВПАДАЕТ!

→ IMMUTABILITY VIOLATION

АВТОМАТИЧЕСКИ:
  1. VerificationRun.status = BLOCKED
  2. Блокировка publish для всех pending-релизов FI-0080
  3. Алерт в Rusal Pulse #incidents + email Project owner
  4. YouTrack issue создан автоматически:
     «Immutability violation: FI-0080 / Просроченная ДЗ / май 2026»
  5. На странице дашборда — красный баннер:

  ┌──────────────────────────────────────────────────────────┐
  │ ⛔ НАРУШЕНИЕ НЕИЗМЕННОСТИ ДАННЫХ                          │
  │                                                          │
  │ Дашборд: FI-0080                                         │
  │ Период: май 2026 (закрыт 01.06.2026)                     │
  │ Метрика: Просроченная ДЗ                                  │
  │                                                          │
  │ Значение при закрытии периода:  1 234 567.89              │
  │ Значение сейчас:                1 500 000.00              │
  │ Расхождение:                    +265 432.11 (+21,5%)      │
  │                                                          │
  │ Возможная причина: данные за май были изменены задним     │
  │ числом (перезаливка ETL, исправление ошибки в источнике). │
  │                                                          │
  │ [Создать инцидент] [Скачать evidence] [Уведомить DBA]     │
  └──────────────────────────────────────────────────────────┘

Project owner (через 2 минуты после алерта):
  Открывает страницу VerificationRun.
  Видит: source_response_hash изменился, все предыдущие проверки (8 недель) были OK.
  Жмёт «Уведомить DBA».

DBA расследует:
  Выясняет: в пятницу 11.07 ETL-процесс перезалил данные за май
  из-за ошибки в конфигурации источника (подключился к тестовой базе).
  Данные восстановлены из бэкапа.

DBA закрывает инцидент в YouTrack.

Project owner перезапускает scheduled-проверку вручную:
  → source_response_hash снова sha256:aaa111 → immutability violation cleared
  → VerificationRun: ✓ PASS
  → Блокировка публикации новых релизов FI-0080 снята
  → Красный баннер на странице дашборда исчезает

Хронология:
  9:00  — scheduled-проверка запущена
  9:01  — violation обнаружен, алерт отправлен
  9:03  — архитектор уведомлён
  9:15  — DBA начал расследование
  10:30 — причина найдена, данные восстановлены
  10:35 — перепроверка: ✓ PASS, блокировка снята

Время от обнаружения до разрешения: 1 час 35 минут.
Без подсистемы: аналитик заметил бы расхождение через 1–2 недели.

Результат: нарушение целостности данных детектится, расследуется и исправляется за часы, а не за недели. Блокировка публикации новых релизов предотвращает каскадное распространение проблемы.


UC-6: Структурная регрессия фильтра

Кто: Разработчик дашборда.
Когда: при деплое на PREPROD.
Режим: pipeline gate — блокировка до подтверждения.

Разработчик меняет дашборд в DEV:
  Фильтр «Контрагент»: раньше применялся к chart_128 и chart_200,
  теперь — только к chart_128 (поменял scope).

  Разработчик НЕ заметил, что chart_200 потерял фильтрацию.
  Числовые метрики chart_128 не изменились — числовая проверка PASS.

SYNC → COMMIT → Deploy to PREPROD.

АВТОМАТИЧЕСКИ:
  StructureDiff: текущий dev vs baseline из последнего релиза

  Change detected:
    target: native_filters[contractor].scope
    kind: filter_scope_narrowed
    severity: CRITICAL
    before: [chart_128, chart_200]
    after: [chart_128]
    affected_charts: [200 — «Динамика по контрагентам»]
    rationale: «Фильтр «Контрагент» больше не фильтрует chart_200.
               Данные chart_200 будут показываться без ограничения
               по контрагенту, хотя раньше фильтровались.»

  → DEPLOY ЗАБЛОКИРОВАН.

Разработчик на странице PREPROD-деплоя видит:
  ┌──────────────────────────────────────────────────────────┐
  │ ⛔ CRITICAL: фильтр «Контрагент» потерял scope           │
  │                                                          │
  │ Chart_200 «Динамика по контрагентам» больше              │
  │ не фильтруется. Его данные теперь показывают             │
  │ ВСЕХ контрагентов, а не выбранного.                      │
  │                                                          │
  │ Это ожидаемо?                                            │
  │                                                          │
  │ [Да, подтвердить]  [Нет, буду править]                   │
  └──────────────────────────────────────────────────────────┘

Вариант A (ошибка):
  Разработчик: «Нет, буду править»
  → возвращается в DEV, правит scope фильтра
  → SYNC → COMMIT → Deploy (StructureDiff снова, теперь OK)

Вариант B (осознанное изменение):
  Разработчик: «Да, подтвердить»
  Причина: «Chart_200 теперь использует dataset-level фильтр
            в виртуальном датасете. Dashboard-фильтр не нужен.»
  
  → CRITICAL resolved
  → Деплой разблокирован
  
  НО: метрическая проверка для chart_200 показывает WARNING —
  baseline был с фильтром, новые данные без фильтра.
  Разработчик подтверждает: метрики переизвлечены.

Результат: структурная регрессия поймана до того, как сломанный дашборд попал в PREPROD. Раньше это заметил бы только аналитик при ручной проверке — или никто.


UC-7: Baseline-наследование при создании релиза

Кто: Release manager.
Когда: создание нового релиза.
Режим: structured panel — таблица + кнопка «Подтвердить».

Релиз v1.4.0 создаётся на основе PREPROD.

Предыдущий релиз: v1.3.0, baseline.yaml с 7 метриками.

АВТОМАТИЧЕСКИ:
  Система сравнивает content_hash каждого чарта между v1.3.0 и v1.4.0.

  ┌──────────────────────────────────────────────────────────┐
  │ Baseline-наследование: v1.3.0 → v1.4.0                  │
  │                                                          │
  │ Метрика               v1.3.0        v1.4.0     Статус    │
  │ ──────────────────────────────────────────────────────── │
  │ Просроченная ДЗ       1 234 567     1 234 567   ↻ унасл  │
  │ Доля просрочки        12,4%         12,4%       ↻ унасл  │
  │ Всего должников       342           342         ↻ унасл  │
  │ XLSX checksum         sha256:hhh    sha256:hhh  ↻ унасл  │
  │ ──────────────────────────────────────────────────────── │
  │ Топ контрагентов      1 500 000     1 520 000   ⚡ переизв│
  │   chart_hash изменился. Значение переизвлечено из PREPROD.│
  │   Δ: +20 000 (+1,3%)                                     │
  │ ──────────────────────────────────────────────────────── │
  │ Динамика ДЗ           342           355         ⚡ переизв│
  │   chart_hash изменился. Значение переизвлечено из PREPROD.│
  │   Δ: +13                                                │
  │ ──────────────────────────────────────────────────────── │
  │ Распределение         —             845 000     ✚ новый  │
  │   Новый чарт (chart_500), значения извлечены из PREPROD.  │
  └──────────────────────────────────────────────────────────┘

  Итого: 4 унаследовано, 2 переизвлечено, 1 новый.

Release manager проверяет переизвлечённые значения:
  • «Топ контрагентов» +1,3% — ожидаемо, новый контрагент в мае.
  • «Динамика ДЗ» +13 — ожидаемо, сезонный рост просрочки.

Жмёт «Подтвердить все» — baseline.yaml для v1.4.0 зафиксирован.
Релиз создан.

Результат: baseline не требует ручного перезаполнения при каждом релизе. Release manager только проверяет автоматически вычисленный diff и подтверждает. Наследование гарантирует, что эталоны не теряются между релизами.


Архитектурная карта

┌─────────────────────────────────────────────────────────────────────┐
│                                                                     │
│  039 UI Layer                                                       │
│  ┌─────────────────────┐  ┌──────────────────────────────────┐     │
│  │ Agent Workspace     │  │ Pipeline Verification Views      │     │
│  │ (диалог с агентом)  │  │ (автоматические страницы)        │     │
│  │                     │  │                                  │     │
│  │ • ScenarioPreview   │  │ • VerificationStatusBadge        │     │
│  │ • ParameterPanel    │  │ • StructureDiffPanel             │     │
│  │ • ArtifactPreview   │  │ • VerificationHistoryList        │     │
│  │ • EvidencePanel     │  │ • ImmutabilityViolationBanner    │     │
│  │ • ConfirmationCard  │  │                                  │     │
│  └────────┬────────────┘  └──────────────┬───────────────────┘     │
│           │                              │                          │
│  038 Scenario Model                     │                          │
│  ┌─────────────────────┐               │                          │
│  │ • ScenarioCompiler  │               │                          │
│  │ • Validator         │               │                          │
│  │ • PackCompiler      │               │                          │
│  │ • CaptureDispatch   │               │                          │
│  │ • VlmAnalysis       │               │                          │
│  └────────┬────────────┘               │                          │
│           │                              │                          │
│  037 Baseline Engine                    │                          │
│  ┌──────────────────────────────────────────────────────┐         │
│  │ • QueryModel.Inspect    • Comparison.Compare          │         │
│  │ • Filters.Normalize     • Structure.Diff              │         │
│  │ • QueryExecutor         • Immutability.Detect         │         │
│  │ • Result.Normalize      • Release.ExtractBaseline     │         │
│  │ • Catalog.Load          • Visual.Compare              │         │
│  └────────────────────────┬─────────────────────────────┘         │
│                           │                                        │
│  036 Agent Run Stabilization                                      │
│  ┌──────────────────────────────────────────────────────┐         │
│  │ • AgentRun (manual/scheduled/etl_completed/...)      │         │
│  │ • DraftArtifact (screenshot_evidence, ...)           │         │
│  │ • ApprovalGate (HITL)                                │         │
│  │ • Evidence.Adapter (ScreenshotService bridge)        │         │
│  │ • VerificationRun (AgentRun ↔ DashboardRelease)      │         │
│  └──────────────────────────────────────────────────────┘         │
│                                                                     │
│  Git Repository (существующий)                     Superset API     │
│  ┌────────────────────────────┐  ┌────────────────────────────┐    │
│  │ • baseline.yaml            │  │ • chart data               │    │
│  │ • visual_baselines/        │  │ • dataset query             │    │
│  │ • verification_report.md   │  │ • dashboard export          │    │
│  │ • DashboardRelease         │  │ • native filters            │    │
│  └────────────────────────────┘  └────────────────────────────┘    │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

Граница: где нужен агент, а где нет

Use Case Агент? Интерфейс
UC-1 Ad-hoc проверка ✅ Да Диалог + structured panels
UC-2 Релиз с верификацией ❌ Нет Страницы деплоя/релиза, кнопки Confirm/Dismiss
UC-3 Scheduled проверка ❌ Нет Полный автомат, алерт при проблемах
UC-4 ETL-triggered ❌ Нет Полный автомат, event-driven
UC-5 Immutability violation ❌ Нет Алерт → страница VerificationRun → расследование
UC-6 Структурная регрессия ❌ Нет Страница PREPROD-деплоя, кнопка Confirm/Dismiss
UC-7 Baseline-наследование ❌ Нет Страница создания релиза, таблица + «Подтвердить»

Агент нужен только в одном сценарии из семи — когда аналитик создаёт сценарий проверки с нуля или итеративно его уточняет. Все остальные сценарии — это structured views с кнопками, которые потребляют данные из автоматически созданных VerificationRun-ов.


Оценка трудозатрат

Сводка

┌──────────────────────┬──────────┬──────────┬──────────┬─────────────────┐
│ Показатель           │ Backend  │ Frontend │ DevOps   │ Итого           │
├──────────────────────┼──────────┼──────────┼──────────┼─────────────────┤
│ FTE (ставок)         │ 1.5      │ 1.0      │ 0.3      │ 2.8 FTE         │
│ Календарных месяцев  │ 5        │ 5        │ 2        │ 5 месяцев       │
│ FTE-месяцев          │ 7.0      │ 4.5      │ 0.5      │ 12.0 FTE-мес    │
│ Человекочасов (net)  │ 1 120    │ 720      │ 80       │ 1 920 ч         │
│ Человекочасов (full) │ 1 400    │ 900      │ 100      │ 2 400 ч         │
└──────────────────────┴──────────┴──────────┴──────────┴─────────────────┘

Full = net + 25% (code review, совещания, документация, непродуктивное время).
1 человекочас net = 1 час написания кода / тестов / отладки.

Детализация по фичам

┌──────┬──────────────────────────┬──────────┬────────────┬─────────┬──────────┐
│ Фича │ Компоненты               │ LoC      │ Календарь  │ FTE     │ Человеко-│
│      │                          │          │ (недель)   │ (ставок)│ часы net │
├──────┼──────────────────────────┼──────────┼────────────┼─────────┼──────────┤
│      │                          │          │            │         │          │
│ 036  │ AgentRun, AgentRunEvent, │ ~8 000   │ 5          │ 1.0 BE  │ 200 BE   │
│      │ DraftArtifact,           │ backend  │            │ 0.3 FE  │  45 FE   │
│      │ ApprovalGate (ORM +      │ ~2 500   │            │         │          │
│      │ Pydantic + API + Svc)    │ frontend │            │         │          │
│      │ Evidence.Adapter         │          │            │         │          │
│      │ AgentRunModel (FE)       │          │            │         │          │
│      │ ConfirmationCard ext.    │          │            │         │          │
│      │                          │          │            │         │          │
│ 037  │ DashboardQueryModel      │ ~13 000  │ 9          │ 1.0 BE  │ 360 BE   │
│      │ Filters, QueryExecutor,  │ backend  │            │ 0.1 FE  │  30 FE   │
│      │ Normalize, Compare       │ ~2 000   │            │         │          │
│      │ Structure.Diff           │ frontend │            │         │          │
│      │ Immutability.Detect      │          │            │         │          │
│      │ Visual.Compare           │          │            │         │          │
│      │ Release.ExtractBaseline  │          │            │         │          │
│      │ Catalog.Load/Write       │          │            │         │          │
│      │ VerificationRun (ORM+API)│          │            │         │          │
│      │                          │          │            │         │          │
│ 038  │ ChecklistCatalog (19)    │ ~10 000  │ 8          │ 1.0 BE  │ 320 BE   │
│      │ CapabilityMapper         │ backend  │            │ 0.1 FE  │  25 FE   │
│      │ ScenarioCompiler         │ ~1 500   │            │         │          │
│      │ Validator, Resolver      │ frontend │            │         │          │
│      │ PackCompiler             │          │            │         │          │
│      │ Capture.Dispatch         │          │            │         │          │
│      │ Vlm.Analyze              │          │            │         │          │
│      │ Human.Disposition        │          │            │         │          │
│      │ Step templates           │          │            │         │          │
│      │                          │          │            │         │          │
│ 039  │ ApiClient, WorkspaceModel│ ~3 500   │ 8          │ 0.2 BE  │  70 BE   │
│      │ EntryAction, Workspace   │ backend  │            │ 1.0 FE  │ 560 FE   │
│      │ Progress, ScenarioViews  │ ~8 000   │            │         │          │
│      │ Parameters, Baseline     │ frontend │            │         │          │
│      │ ArtifactPreview,Evidence │          │            │         │          │
│      │ ConfirmationBinding      │          │            │         │          │
│      │ ReleaseVerification.*    │          │            │         │          │
│      │ E2E tests                │          │            │         │          │
│      │                          │          │            │         │          │
│ Инт. │ Интеграционное тест-е    │ —        │ 2          │ 0.5 BE  │  40 BE   │
│      │ Исправления, докум-я     │          │            │ 0.5 FE  │  60 FE   │
│      │                          │          │            │         │          │
├──────┼──────────────────────────┼──────────┼────────────┼─────────┼──────────┤
│ИТОГО │                          │ ~34 000  │ 20 календ. │ 1.5 BE  │1 010 BE  │
│      │                          │ backend  │ недель     │ 1.0 FE  │  720 FE  │
│      │                          │ ~14 000  │ (5 мес.)   │ 0.3 Ops │   80 Ops │
│      │                          │ frontend │            │ ─────── │ ──────── │
│      │                          │          │            │ 2.8 FTE │1 810 net │
│      │                          │          │            │  avg    │2 260 full│
└──────┴──────────────────────────┴──────────┴────────────┴─────────┴──────────┘

Фазы и загрузка по ролям (календарный план)

         Месяц 1        Месяц 2        Месяц 3        Месяц 4        Месяц 5
         W1 W2 W3 W4    W5 W6 W7 W8    W9 W10 W11 W12 W13 W14 W15 W16 W17 W18 W19 W20
         │              │              │              │              │
BE #1    ████████████████████████████████████████████████████████████████████░░░░████
         036 AgentRun   036 AgentRun   038 Scenario  038 Scenario   038        Интегр.
         foundations    + gates        Compiler+Val  Capture+VLM   PackComp   +fixes

BE #2            ░░░░████████████████████████████████████████████████████████░░░░████
                 036 dep 037 QueryModel  037 Compare   037 StructDiff 037 Immutab.  Интегр.
                 ready   +Filters+Exec   +Normalize   +Visual       +Release      +fixes

FE #1    ████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██████████████████████████████████
         036 Model  036 стабилизация      039 DTOs     039 Workspace 039 Evidence     Интегр.
         +Cards    фронта 036             стабильны    +Params      +Rel.Verify +E2E  +fixes

Ops      ░░░░░░░░░░████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░████████░░░░
         Настройка CI + Testcontainers                  Мониторинг          Релиз
                                                        верификаций         +миграции


Условные обозначения:
  ████  — активная разработка (полная загрузка)
  ░░░░  — частичная загрузка / ожидание / поддержка
  │     — граница недели

Простой разработчиков исключён: BE #2 стартует на неделю позже BE #1
(дожидается foundation 036), но его загрузка заполняется параллельными
задачами из 037, не зависящими от 036. FE получает стабильные DTO не
раньше недели 4, до этого работает над моделью AgentRun и карточками.

Расчёт человекочасов

Backend (суммарно 1.5 FTE):
  BE #1 (1.0 FTE):
    Недели 1–5  (036): 5 нед × 40ч = 200ч net  → full ~250ч
    Недели 6–14 (038): 9 нед × 40ч = 360ч net  → full ~450ч
    Недели 18–20 (инт): 3 нед × 20ч =  60ч net → full  ~75ч
    Итого BE #1: 620ч net / ~775ч full
  
  BE #2 (1.0 FTE):
    Недели 1–2  (ожидание 036 foundation):      2 нед × 10ч =  20ч
    Недели 3–11 (037): 9 нед × 40ч = 360ч net  → full ~450ч
    Недели 18–20 (инт): 3 нед × 20ч =  60ч net → full  ~75ч
    Итого BE #2: 440ч net / ~550ч full
  
  Всего backend: 1 060ч net / ~1 325ч full

Frontend (1.0 FTE):
  Недели 1–3   (036 базовые компоненты): 3 нед × 40ч = 120ч
  Недели 4–9   (стабилизация + ожидание DTOs): 6 нед × 15ч =  90ч
  Недели 10–18 (039 полный цикл): 9 нед × 40ч = 360ч
  Недели 19–20 (интеграция + E2E):     2 нед × 40ч =  80ч
  Итого frontend: 650ч net / ~810ч full

DevOps (0.3 FTE):
  Недели 4–5  (CI + Testcontainers):  2 нед × 20ч =  40ч
  Недели 16–17 (мониторинг):          2 нед × 10ч =  20ч
  Недели 18–19 (миграции + релиз):    2 нед × 15ч =  30ч
  Итого ops: 90ч net / ~110ч full

═══════════════════════════════════════════════════════════════
ИТОГО:      1 800ч net   /   ~2 250ч full
            12.0 FTE-месяцев
            2.8 FTE × 5 календарных месяцев
═══════════════════════════════════════════════════════════════

Допущения и риски графика

Фактор Оценка Влияние на человекочасы
Сложность Superset chart-data API (4.1.2) Высокая +15% к 037, если API нестабилен
Готовность VLM-провайдера (модель + промпт) Средняя +5% к 038, если требуется тюнинг промптов
Зрелость существующего GitService Высокая (уже в проде) Экономия ~10% на 037 (Catalog)
Наличие Testcontainers для Superset Требует настройки +3–5 дней DevOps на старте
Стабилизация DTOs между backend и frontend Стандартный риск Учтено в «ожидании DTOs» для FE
Рефакторинг по итогам code review Стандартный +25% в full-оценке

Сравнение: MVP vs полный объём

┌─────────────────────┬──────────────────┬──────────────────────────┐
│                     │ MVP              │ Полный объём              │
│                     │ (3.5 месяца)     │ (5 месяцев)               │
├─────────────────────┼──────────────────┼──────────────────────────┤
│ FTE                 │ 1.5 BE + 0.5 FE  │ 1.5 BE + 1.0 FE + 0.3 Ops│
│ Человекочасов (net) │ ~900ч            │ ~1 800ч                   │
│ FTE-месяцев         │ ~6.5             │ ~12.0                     │
├─────────────────────┼──────────────────┼──────────────────────────┤
│ Что входит          │ 036 полностью    │ Всё из MVP +              │
│                     │ 037: метрическая │ 037: StructureDiff        │
│                     │ проверка без     │ + Immutability            │
│                     │ StructureDiff    │ + Visual baseline         │
│                     │ и визуальных     │ 038: сценарии + VLM +     │
│                     │ baseline-ов      │ capture + disposition     │
│                     │ 039: Agent       │ 039: Agent Workspace +    │
│                     │ Workspace без    │ Pipeline Views +          │
│                     │ Pipeline Views   │ EvidencePanel + E2E       │
├─────────────────────┼──────────────────┼──────────────────────────┤
│ Use cases           │ UC-1 (ручная     │ Все 7 use cases           │
│                     │ проверка)        │                            │
│                     │ UC-2 частично    │                            │
│                     │ (базовая метрика)│                            │
└─────────────────────┴──────────────────┴──────────────────────────┘

Что это даёт бизнесу

До подсистемы:

  • Проверка дашборда перед релизом: 30–40 минут ручной работы аналитика на каждый дашборд
  • Детект изменения данных задним числом: 1–2 недели (пока кто-то случайно не заметит)
  • Повторяемость проверок: нулевая (никто не помнит точные фильтры и значения)
  • Аудит: «кажется, в мае было около 1,2 млн»
  • Структурные регрессии: обнаруживаются в PROD пользователями

С подсистемой:

  • Проверка дашборда перед релизом: 1 клик (автоматическая) + 5 минут на подтверждение результатов аналитиком
  • Детект изменения данных задним числом: < 1 минуты (scheduled + ETL-triggered)
  • Повторяемость: 100% (baseline.yaml в git, версионирован с дашбордом)
  • Аудит: «01.06.2026, baseline v1.2.3, метрика X = 1 234 567.89, source_response_hash = sha256:abc, captured через Superset API»
  • Структурные регрессии: блокируются на этапе деплоя в PREPROD

Следующие шаги

  1. Утверждение спецификации — ревью архитекторами и тимлидом
  2. Приоритизация — MVP: 036 + базовая 037 (метрическая проверка без StructureDiff и visual)
  3. Начало реализации — 036 Phase 1 (модели и миграции)

Документация по спецификациям: specs/036-agent-test-stabilization/ … specs/039-dashboard-scenario-ui/