94 lines
11 KiB
Markdown
94 lines
11 KiB
Markdown
# Продуктовый контракт KT AI
|
||
|
||
Единый контракт, из которого собирается прототип. **Один источник, один рантайм.** Это ключевой механизм северной звезды (`GOAL.md`): *прототип === фронтенд продакшна*.
|
||
|
||
## Зачем
|
||
|
||
Раньше форма «входного контракта» дублировалась в четырёх местах и неизбежно дрейфовала:
|
||
`archive/kt_ai_atomic_product_system.md` (yaml) · JSON-конфиг в `kt-ai-app-shell.html` · `kt-ai-shadcn/.../kt-ai-product-input-contract.md` · вывод дизайнера Төре `[[APP]]`.
|
||
|
||
Теперь каноническая форма одна: **`product.schema.json`** (JSON Schema). Все остальные описания — производные от неё.
|
||
|
||
## Контур
|
||
|
||
```
|
||
Паспорт агента ─┐
|
||
├─► Төре (дизайнер [[APP]]) ──► product.config.json ──► kt-ai-app-shell.html ──► кликабельный прототип
|
||
Интервью Төре ──┘ выдаёт контракт ▲ проверяет потребляет контракт (владелец кликает, комментирует)
|
||
│
|
||
scripts/validate_product.py
|
||
(структура по схеме + lint правил ДС)
|
||
│
|
||
└──► handoff: тот же контракт читает kt-ai-prototype-handoff.md
|
||
```
|
||
|
||
- **Төре выдаёт** контракт по `product.schema.json` (Төре не трогаем — он уже эмитит эту форму).
|
||
- **`kt-ai-app-shell.html` потребляет** его из `<script id="kt-app-config">` — это рантайм, которым владеет ДС.
|
||
- **`validate_product.py` проверяет** — структуру и правила честности.
|
||
- **Handoff читает** тот же контракт: данные → mock-модуль, статусы → workflow, control → primary-действие.
|
||
|
||
## Поля (кратко; полная форма и все ограничения — в `product.schema.json`)
|
||
|
||
Ниже описаны **все 31 блок** схемы. Звёздочка — обязательное поле внутри блока.
|
||
|
||
| Блок | Назначение |
|
||
|---|---|
|
||
| `archetype` | форма экрана из открытого реестра (`queue` дефолт; см. `ARCHETYPES.md`). `layout` — deprecated-алиас |
|
||
| `product` | name (H1, 1-3 слова), purpose (scope ≤90), entity, primary_user, language, **view** (`operational`/`management`) |
|
||
| `user` | name, role владельца |
|
||
| `notifications` | лента уведомлений (text, time, unread) |
|
||
| `steps` | этапы мастера создания (items, current) — НЕ на главном списке |
|
||
| `nav` | разделы sidebar (3-5 на группу): {label, icon}; `group` → общий заголовок для идущих подряд пунктов (заголовок не пункт: в нумерации разделов не участвует, в полосе значков становится разделителем); `view:"documents"`+`docType` → секция-коллекция документов (по `_docs` строк) с кнопкой «Скачать» |
|
||
| `kpis` | тихая метрик-полоса; отвечают на работу пользователя, не на ROI продукта. Значение — всегда НОВОЕ (to-be) состояние: подпись «вместо X» не может стоять над значением X — сколько СТАЛО пишется в value, сколько БЫЛО остаётся в подписи или hint (валидатор ловит, DS-016). `hint` (≤40) — из чего считано; `note` (без потолка) — чем число НЕ является: оговорка о поле-источнике, стоит рядом с числом и не прячется под клик |
|
||
| `scenario` | один сквозной сценарий: headline, **control** (ровно один primary), reject, confirmText, approveTo/rejectTo, `aiSummary` (что сделал агент — 1-2 фразы для drawer) |
|
||
| `statuses` | словарь workflow-статусов: ключ → { label ≤4 слов, tone `ok/warn/risk/info`, `dim?` (гасит терминальные строки) } |
|
||
| `table` | columns + rows — главный объект экрана. Строка: `_flags` (признаки агента), `_docs` (выходные документы [{label,type,status,format}] — карточки со «Скачать») |
|
||
| `drawer` | детали объекта справа (titleKey, fields, flagsLabel) + секция «Документы» из `_docs` строки |
|
||
| `ai` | точка входа Төре (intro, suggestions, answers, fallback) |
|
||
| `banner` | системный баннер «что-почему-что делать» (text, tone). Стоит НАД числами: всё, что в него уходит, читают до первого числа |
|
||
| `search` | поиск в шапке: `placeholder`, `compact` (узкое поле 176px), `shortcut` (сочетание ⌘K/Ctrl+K вместе с бейджем — включаются и выключаются одним полем). В React-ките те же поля — в пропе `search` у `KTAIShell` |
|
||
| `conclusion` | вывод раздела (title, **text**) — последний блок экрана, после таблицы. Противовес баннера: баннер предупреждает ДО чисел, вывод объясняет ПОСЛЕ них. Пустая строка в `text` делит абзацы |
|
||
| `compare` | данные архетипа compare: aLabel, bLabel, pairs[{label,a,b}] |
|
||
| `sections` | данные архетипа custom: секции-карточки [{title, description?, body?, fields?}] |
|
||
| `chart` | сводный bar-chart над таблицей: title, total, unit, color, link; `groupBy` (бары из фильтрованных строк) или `bucket:"day"`+`dateKey` (раскатка по дням + универсальный фильтр диапазона) |
|
||
| `activity` | правый таймлайн-лог действий агента [{title, time, ago, tone, who, tags, summary, link}] — кнопка «Активность» в топбаре |
|
||
| `onboarding` | карусель первого входа [{icon, title, text}] — показ один раз + ссылка повторного показа в низу sidebar |
|
||
| `filterKeys` | какие поля строки дают вкладки-фильтры (string[]). Рантайм берёт **не более 4** + «Все» — закон Хика |
|
||
| `dashboard` | обзорный экран: `series*` (ряды графика), `range` (период), `breakdowns` (разборы под графиком: top-N, доли, мини-карточки) |
|
||
| `analytics` | аналитический экран: `charts*`, `findings*` (выводы словами), `summary`, `period` |
|
||
| `document` | документ с фрагментами: `title*`, `fragments*` (абзацы; помеченные агентом — с причиной), `source` |
|
||
| `artifact` | результат работы агента рядом с чатом: `type`, `title*`, `version`, `preview*`, `actions` (архетип copilot) |
|
||
| `wizard` | многошаговый процесс: `steps*` (номер, название, 1-строчное описание), `current` — вертикальный степпер слева |
|
||
| `inbox` | «список + чтение»: `bodyKey*` и ключи для заголовка/подписи/времени (`titleKey`, `subKey`, `timeKey`) |
|
||
| `calendar` | окна и брони: `events*`, `range`, `title` |
|
||
| `map` | география: `points*`, `lines`, `title` |
|
||
| `timeline` | хронология события: `events*`, `title` |
|
||
|
||
### Field-level data contract (что делает прототип правдивым)
|
||
|
||
Колонка таблицы несёт не только `key`/`label`/`type`, но и:
|
||
|
||
- `values` — допустимые значения для status/enum-колонок (из паспорта/интервью);
|
||
- `source` — откуда значение: SAP, Лотус, KTWorks, агент, человек;
|
||
- `align` / `sortable` — поведение.
|
||
|
||
Без этого слоя дизайнер выдумывает примеры, и владелец процесса ревьюит вымысел. С ним владелец видит **свои** поля, статусы и источники — первый прототип становится правдивым.
|
||
|
||
## Как проверить
|
||
|
||
```bash
|
||
python3 scripts/validate_product.py <ваш-конфиг>.json # черновая проверка (errors блокируют)
|
||
python3 scripts/validate_product.py <ваш-конфиг>.json --strict # ВОРОТА handoff/CI: warnings тоже блокируют
|
||
```
|
||
|
||
Правило: **прототип уходит в handoff/CI только при `--strict` без замечаний** (0 ошибок, 0 предупреждений). Без `--strict` проходят честностные warnings (ROI/FTE на operational, debug-язык, неизвестный архетип) — они допустимы на этапе черновика, но не на сдаче.
|
||
|
||
Валидатор — это seed `kt-ai-lint`. Он ловит:
|
||
|
||
- **ERROR** (блокирует): статус в ряду не объявлен в `statuses`; `scenario.approveTo/rejectTo` ссылается на несуществующий статус; `drawer.titleKey`/`fields` не из колонок; лишние/недостающие поля; tone вне `ok/warn/risk/info`; пустой `scenario.control`.
|
||
- **WARN** (правила честности ДС): ROI/FTE/экономия на операционном дашборде (`view=operational`); debug-язык в копирайте (`модель вернула`, `fallback`, `JSON`, `prompt`, `shell`); статус-лейбл > 4 слов; имя экрана/лейблы длиннее нормы; мало строк (< 5).
|
||
|
||
## Правило
|
||
|
||
Меняется форма контракта — меняется **только** `product.schema.json`, затем синхронизируются производные описания и проверяется `examples/`. Не плодить пятую копию контракта.
|