Что это и на чём основано
Спека описывает вкладку «Аналитик» конструктора отчётов РРЭ: состояния диалога, компоненты, поведение уточняющих вопросов и критерии приёмки для фронтенда.
Исходники сервиса недоступны (GITHUB_TOKEN в окружении шага отсутствует, репозиторий не клонирован —
шаги 1–3 прогона по той же причине не выполнены). Поэтому спека и макет сняты с работающего сервиса
sol-mspg313y-6zr.apps.sreda-ai.ru,
проверено 12.08.2026:
GET /— HTML конструктора: палитра, сетка, компоненты и текущая разметка вкладки «Аналитик»;POST /api/agent/chat— четыре реальных диалога: тексты вопросов, опции, конфигурации, строки результата;GET /api/agent/context— 7 источников, правила витрины, связи, словарь (7 562 символа), 4 открытых вопроса.
1. Экран и структура
Вкладка — четвёртая в существующей навигации (Данные · Конструктор · Отчёт ПУНЦ · Аналитик),
сетка и палитра конструктора не меняются. Сверху вниз:
| Блок | Содержимое | Статус |
|---|---|---|
| Панель «Диалог с аналитиком» | заголовок + пилюля статуса, поясняющий абзац, строка понимания, область чата, поле ввода + «Отправить» / «Начать заново», подпись о движке разбора | есть |
| Строка понимания запроса | чипы: Источник · Показатель · Разрез · Период · Единицы · Сравнение; заполненный — синий, спрашиваемый сейчас — жёлтый, пустой — серый | новое |
| Панель «Что будет посчитано» | карточка подтверждения: человекочитаемое summary, свёрнутый JSON, кнопки «Считать» / «Поправить» | есть |
| Панель «Результат» | счётчик строк, кнопки Excel · CSV · PDF · «Открыть в конструкторе», таблица (дельта-колонки при сравнении), легенда дельты, предупреждения витрины | есть |
| Панель «Контекст аналитика» | 7 источников, правила витрины, связи, открытые вопросы энергетику из ПРИЁМКА.md, словарь целиком | есть |
2. Состояния диалога
| Состояние | Что видит пользователь | Признак в ответе API |
|---|---|---|
| Пустое | заголовок «Спросите словами, что посчитать», пояснение про 7 источников и три чипа-примера, по клику отправляющие запрос | — |
| Уточнение | пилюля «уточняет» (жёлтая), пузырь аналитика с вопросом, ряд быстрых ответов с подписью «Быстрый ответ», жёлтый чип спрашиваемого слота | status:"ask", question.options |
| Подтверждение | пилюля «ждёт подтверждения» (синяя), карточка конфигурации с синей левой границей, кнопки «Считать» / «Поправить» | status:"confirm", config, summary[] |
| Результат | пилюля «посчитано» (зелёная), таблица, выгрузки, предупреждения, подсказки «Что дальше» | status:"result", result |
| Оговорка | центрированный жёлтый пузырь «Важно» — например «Не понял, что с чем сравнивать — считаю без сравнения» | notes[] |
| Ошибка | красный пузырь «Ошибка» с текстом сервера; ввод остаётся доступен, состояние диалога не теряется | HTTP 4xx/5xx или error |
| Ожидание | курсивная строка «Аналитик думает…», поле ввода и кнопка заблокированы | запрос в полёте |
3. Уточняющие вопросы: слоты и порядок
Агент не додумывает недостающее. Порядок опроса — от того, без чего конфигурацию нельзя собрать, к деталям:
| Слот | Когда спрашивается | Опции быстрых ответов (реальные) |
|---|---|---|
intent | не назван ни показатель, ни разрез | примеры запросов |
compare_field | сказано «сравни», но разрез сравнения не определён | вид начисления · уровень напряжения · ценовая категория · диапазон мощности · контрагент · договор · регион · подразделение |
compare_value, compare_value2 | разрез сравнения есть, стороны не названы | значения разреза из данных: ВН · НН · СН1 · СН2 · ФСК220 |
period | период не указан | 2024-08 (единственный период в data.db) |
unit | показатель «Объём»: в данных кВт·ч и кВт вперемешку, складывать нельзя | кВт·ч · МВт·ч · кВт · разбить по единице измерения |
Правила поведения
- один вопрос за раз — не анкета из пяти полей;
- вопрос всегда сопровождается кнопками-вариантами из фактических значений данных, ручной ввод остаётся доступен;
- после ответа кнопки предыдущего вопроса убираются из ленты — нельзя ответить на вопрос, который уже снят;
- уже собранные слоты видны в строке понимания: пользователь не гадает, что аналитик «услышал»;
- перед расчётом — обязательное подтверждение конфигурации; никакой расчёт не идёт по догадке;
- реплика в состоянии подтверждения, отличная от «да/считай/ок», трактуется как правка, а не как отказ.
4. Компоненты и токены
Все переменные — из существующего конструктора, новых цветов не вводится:
--accent:#2b6cb0, --line:#e2e5ea, --muted:#6b7684,
--warnbg:#fff6e0, рост #1b6b45, снижение #a3261e.
| Компонент | Спецификация |
|---|---|
Пузырь .bubble | радиус 12px (угол со стороны автора — 3px), max-width 78% (на мобильном 92%), надпись автора 11px uppercase; свой — заливка акцентом, аналитик — белый с рамкой, «Важно» — жёлтый по центру, «Ошибка» — красный слева |
Лента .chat | фиксированная высота 46vh (мобильный — 56vh), автоскролл вниз,
aria-live="polite"; фиксированная высота вместо max-height — чтобы блок не «прыгал» при первом ответе |
Быстрый ответ .quick button | пилюля 14px, рамка #d3e0f0, текст акцентом, ховер #eef3fa, подпись ряда 11px серым |
Чип слота .slot | 12px, три состояния: заполнен (синий), спрашивается (жёлтый), пуст (серый) |
| Карточка подтверждения | рамка акцентом, левая граница 4px, фон #f7fbff, summary списком,
JSON — в <details> |
| Дельта-ячейка | правое выравнивание, tabular-nums, ▲ рост зелёным / ▼ снижение красным, пусто — «—»; заголовок дельта-колонки на тон темнее (#e9eef5) |
| Пилюля статуса | ask — жёлтая «уточняет», confirm — синяя «ждёт подтверждения», result — зелёная «посчитано» |
5. Контракт с бэкендом (снят с работающего сервиса)
POST /api/agent/chat
{ "message": "покажи начисления по регионам", "state": null }
200 →
{ "status": "ask", // ask | confirm | result
"reply": "За какой период считать? В данных есть: 2024-08.",
"question": { "slot": "period", "text": "…", "options": ["2024-08"] },
"notes": [], // оговорки → пузыри «Важно»
"config": {…}, "summary": ["Источник: Начисления (00102)", …],
"result": { "row_count": 5, "columns": [{key,title,role,type,unit}], "rows": [...], "warnings": [] },
"state": {…} } // вернуть без изменений в следующем запросе
GET /api/agent/context → dictionary, sources[7], relations, rules, open_questions
POST /api/agent/export?fmt=xlsx|csv|pdf → файл по состоянию диалога
Дельта-колонки приходят ключами *__delta и *__delta_pct — фронтенд опознаёт
их по суффиксу и раскрашивает; легенда показывается только при их наличии.
6. Дефекты, найденные на работающем сервисе
Все воспроизведены 12.08.2026 через POST /api/agent/chat; реплики приведены дословно.
| Дефект | Воспроизведение | Решение в макете |
|---|---|---|
| UX-1. Ответ на собственный вопрос не принимается. Агент спросил, какое значение взять за базу сравнения, и перечислил «ВН, НН, СН1, СН2, ФСК220»; ответ «ВН» отвергается. | «сравни объём по видам начисления» → «уровень напряжения» → «ВН» → «Не понял ответ. Сравниваю по разрезу "Уровень напряжения". Какое значение взять за базу сравнения (первое)?» | Значение из question.options обязано приниматься — оно же подставляется кнопкой быстрого ответа.
В макете такой ответ принимается и заполняет слот. |
| UX-2. Две стороны сравнения одной репликой не понимаются. | «ВН и СН2» на вопрос о базе сравнения → «Не понял ответ». | Разбор вытаскивает оба значения разреза из реплики: первое — база, второе — сторона сравнения. |
| UX-3. Разрез, названный в исходном запросе, спрашивается заново. | «сравни объём по уровням напряжения» → агент всё равно спрашивает «Что с чем сравнить?». | Разрез из запроса заполняет compare_field, спрашиваются только стороны. |
| UX-4. «Не понял ответ» без выхода. Повтор того же вопроса, вариантов действий не предложено. | «2024-08» в ответ на вопрос о сравнении → дословный повтор вопроса. | Вопрос сопровождается кнопками вариантов; ответ невпопад не стирает уже собранные слоты — они видны в строке понимания. |
| UX-5. Пустой чат ничего не предлагает. Только текст «Диалог пуст. Спросите словами, что посчитать» — энергетик не знает, какие формулировки понимаются. | .chat:empty::after в текущей вёрстке. |
Пустое состояние с тремя кликабельными примерами запросов. |
| UX-6. Двойное отрицание в дельте. При снижении выводится «▼ -99,96»: стрелка уже несёт знак. | текущая логика раскраски дельта-ячеек. | В ячейку идёт модуль со стрелкой: «▼ −99,96 %»; заголовок процентной колонки — «Дельта, %». |
UX-7. Вёрстка ломается на телефоне. min-width:420px у поля ввода даёт горизонтальный
скролл на экранах уже ~460px. |
панель диалога в текущей разметке. | Медиазапрос ≤720px: поле на всю ширину, кнопки в строку, пузыри до 92%, лента 56vh. |
| UX-8. Состояние разбора невидимо. Пользователь узнаёт, что понял агент, только на карточке подтверждения. | — | Строка понимания над лентой, обновляется после каждой реплики. |
7. Критерии приёмки для фронтенда
- вкладка «Аналитик» открывается в существующей навигации, палитра и сетка конструктора не изменены;
- поле ввода: Enter — отправить, Shift+Enter — перенос строки; на время запроса поле и кнопка заблокированы, в ленте — «Аналитик думает…»;
- на неоднозначный запрос приходит пузырь с вопросом, пилюля «уточняет» и кнопки вариантов из
question.options; - кнопки предыдущего вопроса исчезают после ответа; повторный клик по устаревшему варианту невозможен;
- перед расчётом показывается карточка конфигурации с summary и JSON; расчёт запускается только по «Считать» / «да»;
- в результате: счётчик строк, таблица с правым выравниванием мер, предупреждения витрины из
warnings; - при сравнении: колонки
*__deltaи*__delta_pctраскрашены и снабжены легендой; пустые значения — «—»; - «Начать заново» очищает ленту, состояние, карточку конфигурации и результат;
- ошибка сервера показывается пузырём «Ошибка» и не обрывает диалог;
- на экране 360px нет горизонтального скролла; лента чата —
aria-live="polite", фокус после отправки возвращается в поле ввода.
8. Что в макете не покрыто
- Сводный документ из нескольких отчётов и дашборд с графиками — отдельные шаги ТЗ, в макете вкладки не рисовались;
- Состояние сравнения с дельтой показано на макетных числах: живой сервис на диалогах 12.08.2026 до ответа с дельта-колонками не дошёл (см. UX-1 и UX-2) — числа помечены прямо в таблице;
- Выгрузки в макете не выполняются: кнопки показывают, какой запрос уйдёт на сервисе;
- макет работает на записанных ответах — браузерный вызов живого API невозможен, сервис
не отдаёт заголовок
Access-Control-Allow-Origin(проверено 12.08.2026).