1553 lines
55 KiB
JSON
1553 lines
55 KiB
JSON
{
|
||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||
"$id": "https://kt.kz/ai/product.schema.json",
|
||
"title": "KT AI Product Contract",
|
||
"description": "Единый продуктовый контракт KT AI. ОДИН источник, ОДИН рантайм: этот контракт выдаёт дизайнер Төре ([[APP]]), потребляет templates/kt-ai-app-shell.html (кликабельный прототип), читает handoff-док и проверяет scripts/validate_product.py. Раньше форма контракта дублировалась в 4 местах (atomic_product_system.md / app-shell JSON / shadcn input-contract / Төре). Это — каноническая форма. Канон правил вёрстки: docs/DESIGN.md, docs/PRINCIPLES.md.",
|
||
"type": "object",
|
||
"required": [
|
||
"product"
|
||
],
|
||
"additionalProperties": false,
|
||
"properties": {
|
||
"archetype": {
|
||
"type": "string",
|
||
"default": "queue",
|
||
"description": "Архетип экрана из открытого реестра archetypes/registry.json (id, lowercase). Stable: queue, cockpit, dashboard, compare. Неизвестный или ещё не реализованный (status=planned) архетип безопасно деградирует в queue-таблицу. Набор открыт — новые добавляются записью в реестр + рендерером + примером, без правки ядра. См. docs/ARCHETYPES.md."
|
||
},
|
||
"layout": {
|
||
"type": "string",
|
||
"description": "Deprecated-алиас archetype. Рантайм читает archetype || layout. Для новых конфигов использовать archetype."
|
||
},
|
||
"product": {
|
||
"type": "object",
|
||
"required": [
|
||
"name",
|
||
"entity"
|
||
],
|
||
"additionalProperties": false,
|
||
"description": "Кто и о чём. name – короткое имя рабочего объекта (H1, 1-3 слова), не описание процесса.",
|
||
"properties": {
|
||
"name": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 40
|
||
},
|
||
"purpose": {
|
||
"type": "string",
|
||
"maxLength": 90,
|
||
"description": "Одна scope-фраза (subtitle)."
|
||
},
|
||
"entity": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"description": "Главная сущность: договор, заявка, лот, документ, инцидент, клиент, задача."
|
||
},
|
||
"createLabel": {
|
||
"type": "string",
|
||
"maxLength": 24,
|
||
"description": "Явная подпись кнопки создания (морфология). Если не задано — «Новый {entity}». Пример: «Новое предложение»."
|
||
},
|
||
"primary_user": {
|
||
"type": "string",
|
||
"description": "Метаданные: роль основного пользователя (для авторинга/handoff; в UI не выводится)."
|
||
},
|
||
"language": {
|
||
"type": "string",
|
||
"default": "ru",
|
||
"enum": [
|
||
"ru",
|
||
"kk",
|
||
"en"
|
||
],
|
||
"description": "Метаданные: основной язык продукта (v1 — ru; не переключает локаль рантайма)."
|
||
},
|
||
"view": {
|
||
"type": "string",
|
||
"enum": [
|
||
"operational",
|
||
"management"
|
||
],
|
||
"default": "operational",
|
||
"description": "operational – рабочая очередь владельца (по умолчанию). management – управленческий/reporting view, где допустимы ROI/FTE/эффект."
|
||
}
|
||
}
|
||
},
|
||
"user": {
|
||
"type": "object",
|
||
"additionalProperties": false,
|
||
"properties": {
|
||
"name": {
|
||
"type": "string"
|
||
},
|
||
"role": {
|
||
"type": "string"
|
||
}
|
||
}
|
||
},
|
||
"notifications": {
|
||
"type": "array",
|
||
"items": {
|
||
"type": "object",
|
||
"required": [
|
||
"text"
|
||
],
|
||
"additionalProperties": false,
|
||
"properties": {
|
||
"text": {
|
||
"type": "string"
|
||
},
|
||
"time": {
|
||
"type": "string"
|
||
},
|
||
"unread": {
|
||
"type": "boolean",
|
||
"default": false
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"steps": {
|
||
"type": "object",
|
||
"additionalProperties": false,
|
||
"description": "Этапы процесса в мастере создания. НЕ выносятся на главный список (LAYOUT_RULES 9a).",
|
||
"properties": {
|
||
"items": {
|
||
"type": "array",
|
||
"items": {
|
||
"type": "string"
|
||
}
|
||
},
|
||
"current": {
|
||
"type": "integer",
|
||
"minimum": 1
|
||
}
|
||
}
|
||
},
|
||
"nav": {
|
||
"type": "array",
|
||
"description": "Разделы sidebar. 3-5 пунктов на группу (закон Миллера).",
|
||
"items": {
|
||
"type": "object",
|
||
"required": [
|
||
"label"
|
||
],
|
||
"additionalProperties": false,
|
||
"properties": {
|
||
"label": {
|
||
"type": "string",
|
||
"maxLength": 24
|
||
},
|
||
"icon": {
|
||
"type": "string",
|
||
"description": "Имя иконки из спрайта icons/kt-ai-lucide-sprite.svg (home/feed/lots/risk/chart/tool/file/users/source/decisions/...). Монохром, Lucide."
|
||
},
|
||
"view": {
|
||
"type": "string",
|
||
"enum": [
|
||
"documents",
|
||
"registry"
|
||
],
|
||
"description": "Тип секции. «documents» → коллекция артефактов (скачиваемых) из `_docs` строк; «registry» → полный рабочий реестр (таблица с поиском/фильтрами/пагинацией) — используйте для dashboard, чтобы главная оставалась обзором."
|
||
},
|
||
"docType": {
|
||
"type": "string",
|
||
"description": "Для view=documents: какой тип документов показать (совпадает с `_docs[].type`, напр. ts/report)."
|
||
},
|
||
"group": {
|
||
"type": "string",
|
||
"maxLength": 24,
|
||
"description": "Заголовок группы разделов. Пункты с одинаковым значением идут подряд под общим заголовком; пункты без группы — просто списком, как раньше. Заголовок НЕ пункт: он не кликается и в нумерации не участвует, поэтому banner.actionNav и S.nav(i) считают только пункты. В полосе значков (832-1023px) заголовок становится разделителем."
|
||
},
|
||
"count": {
|
||
"$comment": "DEPRECATED: счётчик в пункте меню; рендерится для старых конфигов, в новых не использовать",
|
||
"type": [
|
||
"integer",
|
||
"number"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"kpis": {
|
||
"type": "array",
|
||
"description": "Тихая метрик-полоса. Каждая метрика отвечает на вопрос пользователя в этом экране (очередь, риск, просрочка), НЕ доказывает ценность продукта. ROI/FTE/экономия часов/тенге эффекта запрещены при product.view=operational (валидатор предупреждает).",
|
||
"items": {
|
||
"type": "object",
|
||
"required": [
|
||
"value",
|
||
"label"
|
||
],
|
||
"additionalProperties": false,
|
||
"properties": {
|
||
"value": {
|
||
"type": "string"
|
||
},
|
||
"label": {
|
||
"type": "string",
|
||
"maxLength": 32
|
||
},
|
||
"hint": {
|
||
"type": "string",
|
||
"maxLength": 40,
|
||
"$comment": "уточнение под значением: знаменатель, доля, период — «из 66», «за месяц»"
|
||
},
|
||
"note": {
|
||
"type": "string",
|
||
"description": "Сноска: чем это число НЕ является. Поле-источник иногда меряет не ровно то, чем показатель назван («ожидание в очереди» не отделяет автоприветствие бота от первого ответа оператора) — оговорка обязана стоять рядом с числом, а не в баннере над ним. Потолка длины нет: hint остаётся в 40 знаках, чтобы полоса плиток осталась полосой, а оговорка живёт отдельным полем и показывается мельче подписи. Не прячется под клик — спрятанное читают не все."
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"scenario": {
|
||
"type": "object",
|
||
"required": [
|
||
"headline",
|
||
"control"
|
||
],
|
||
"additionalProperties": false,
|
||
"description": "Один сквозной сценарий владельца: список → деталь → контрольное действие. control – ровно одно главное действие (глагол), один primary на экран.",
|
||
"properties": {
|
||
"headline": {
|
||
"type": "string",
|
||
"maxLength": 40,
|
||
"description": "Заголовок рабочей области, 1-3 слова."
|
||
},
|
||
"control": {
|
||
"type": "string",
|
||
"description": "Главное (primary) действие, глаголом: «Подтвердить и отправить»."
|
||
},
|
||
"reject": {
|
||
"type": "string",
|
||
"description": "Вторичное/обратное действие."
|
||
},
|
||
"confirmText": {
|
||
"type": "string",
|
||
"description": "Текст подтверждения в modal для control."
|
||
},
|
||
"aiSummary": {
|
||
"type": "string",
|
||
"maxLength": 280,
|
||
"description": "Что сделал агент: 1-2 фразы для шапки карточки (drawer). Конкретно про этот продукт — НЕ переиспользовать чужой текст. Без него блок «Что сделал агент» не показывается."
|
||
},
|
||
"approveTo": {
|
||
"type": "string",
|
||
"description": "Ключ статуса после control."
|
||
},
|
||
"rejectTo": {
|
||
"type": "string",
|
||
"description": "Ключ статуса после reject."
|
||
},
|
||
"actions": {
|
||
"type": "array",
|
||
"items": {
|
||
"type": "string"
|
||
},
|
||
"description": "Action Layer: варианты действия, которые человек может выбрать/изменить в карточке (human-in-the-loop). AI рекомендует, человек подтверждает или меняет."
|
||
}
|
||
}
|
||
},
|
||
"statuses": {
|
||
"type": "object",
|
||
"minProperties": 1,
|
||
"description": "Словарь workflow-статусов главного объекта. Ключ → { label, tone }. Confidence и тип риска моделируются отдельно, не смешиваются со статусом.",
|
||
"additionalProperties": {
|
||
"type": "object",
|
||
"required": [
|
||
"label",
|
||
"tone"
|
||
],
|
||
"additionalProperties": false,
|
||
"properties": {
|
||
"label": {
|
||
"type": "string",
|
||
"maxLength": 24,
|
||
"description": "До 4 слов."
|
||
},
|
||
"tone": {
|
||
"type": "string",
|
||
"enum": [
|
||
"ok",
|
||
"warn",
|
||
"risk",
|
||
"info"
|
||
]
|
||
},
|
||
"dim": {
|
||
"type": "boolean",
|
||
"description": "Гасит (приглушает) строки с этим статусом — терминальные/неактивные уходят на второй план, активные выделяются (паттерн «dim inactive rows»)."
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"chart": {
|
||
"type": "object",
|
||
"additionalProperties": false,
|
||
"description": "Сводный bar-chart над таблицей: раскатывает данные во времени, чтобы не искать по timestamp-колонке («data drives the form»). Напр.: обращения, разобранные AI, по дням.",
|
||
"properties": {
|
||
"title": {
|
||
"type": "string",
|
||
"maxLength": 48
|
||
},
|
||
"total": {
|
||
"type": "string",
|
||
"description": "Крупное итоговое число (например «1 240»)."
|
||
},
|
||
"unit": {
|
||
"type": "string",
|
||
"maxLength": 24,
|
||
"description": "Подпись у числа («за месяц», «всего»)."
|
||
},
|
||
"color": {
|
||
"type": "string",
|
||
"enum": [
|
||
"blue",
|
||
"green",
|
||
"orange",
|
||
"salmon",
|
||
"pink",
|
||
"primary"
|
||
],
|
||
"default": "blue"
|
||
},
|
||
"link": {
|
||
"type": "string",
|
||
"maxLength": 16,
|
||
"description": "Опц. подпись ссылки справа («Все»)."
|
||
},
|
||
"groupBy": {
|
||
"type": "string",
|
||
"description": "Ключ колонки/поля строки: бары считаются из ФИЛЬТРОВАННЫХ строк (counts по значениям), график адаптируется к выбранному табу. Если задан — заменяет статичный bars."
|
||
},
|
||
"bucket": {
|
||
"type": "string",
|
||
"enum": [
|
||
"day"
|
||
],
|
||
"description": "Временная раскатка: counts по дням за выбранный диапазон. Требует dateKey. Включает универсальный фильтр диапазона дат (7/30/90/всё), который фильтрует и таблицу, и график."
|
||
},
|
||
"dateKey": {
|
||
"type": "string",
|
||
"description": "Ключ колонки-даты (ISO YYYY-MM-DD) для bucket:day и фильтра диапазона."
|
||
},
|
||
"bars": {
|
||
"type": "array",
|
||
"description": "Столбцы. 7–31 шт.",
|
||
"items": {
|
||
"type": "object",
|
||
"required": [
|
||
"value"
|
||
],
|
||
"additionalProperties": false,
|
||
"properties": {
|
||
"label": {
|
||
"type": "string"
|
||
},
|
||
"value": {
|
||
"type": "number",
|
||
"minimum": 0
|
||
},
|
||
"hint": {
|
||
"type": "object",
|
||
"additionalProperties": false,
|
||
"description": "Подсказка марки. Строки приходят готовыми от продукта — рантайм их не форматирует и не пересчитывает.",
|
||
"properties": {
|
||
"title": {
|
||
"type": "string",
|
||
"maxLength": 80
|
||
},
|
||
"rows": {
|
||
"type": "array",
|
||
"maxItems": 3,
|
||
"items": {
|
||
"type": "object",
|
||
"required": [
|
||
"label",
|
||
"value"
|
||
],
|
||
"additionalProperties": false,
|
||
"properties": {
|
||
"label": {
|
||
"type": "string",
|
||
"maxLength": 40
|
||
},
|
||
"value": {
|
||
"type": "string",
|
||
"maxLength": 40
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"activity": {
|
||
"type": "array",
|
||
"description": "Лента активности (правая панель, триггер-иконка в топбаре): действия агента и история решений во времени. Референс: activity-timeline drawer.",
|
||
"items": {
|
||
"type": "object",
|
||
"required": [
|
||
"title"
|
||
],
|
||
"additionalProperties": false,
|
||
"properties": {
|
||
"title": {
|
||
"type": "string"
|
||
},
|
||
"time": {
|
||
"type": "string",
|
||
"description": "Метка времени («Сегодня, 14:13»)."
|
||
},
|
||
"ago": {
|
||
"type": "string",
|
||
"description": "Относительно («4 часа назад»)."
|
||
},
|
||
"tone": {
|
||
"type": "string",
|
||
"enum": [
|
||
"ok",
|
||
"warn",
|
||
"risk",
|
||
"info"
|
||
],
|
||
"description": "Цвет точки на таймлайне."
|
||
},
|
||
"who": {
|
||
"type": "string",
|
||
"description": "Кто/что инициировал."
|
||
},
|
||
"tags": {
|
||
"type": "array",
|
||
"items": {
|
||
"type": "string"
|
||
},
|
||
"description": "Чипы (датасеты/объекты)."
|
||
},
|
||
"summary": {
|
||
"type": "string",
|
||
"maxLength": 220
|
||
},
|
||
"link": {
|
||
"type": "string",
|
||
"maxLength": 32,
|
||
"description": "Подпись действия-ссылки."
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"table": {
|
||
"type": "object",
|
||
"required": [
|
||
"columns",
|
||
"rows"
|
||
],
|
||
"additionalProperties": false,
|
||
"description": "Главный рабочий объект экрана для 5+ записей.",
|
||
"properties": {
|
||
"pageSize": {
|
||
"type": "integer",
|
||
"minimum": 1,
|
||
"description": "Размер страницы таблицы. Если строк больше — появляется пагинация. По умолчанию 12."
|
||
},
|
||
"columns": {
|
||
"type": "array",
|
||
"minItems": 1,
|
||
"items": {
|
||
"type": "object",
|
||
"required": [
|
||
"key",
|
||
"label"
|
||
],
|
||
"additionalProperties": false,
|
||
"properties": {
|
||
"key": {
|
||
"type": "string",
|
||
"pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$"
|
||
},
|
||
"label": {
|
||
"type": "string",
|
||
"maxLength": 24,
|
||
"description": "1-2 слова."
|
||
},
|
||
"type": {
|
||
"type": "string",
|
||
"enum": [
|
||
"text",
|
||
"num",
|
||
"date",
|
||
"status"
|
||
],
|
||
"default": "text"
|
||
},
|
||
"sub": {
|
||
"type": "string",
|
||
"description": "Ключ поля для muted-подзаголовка под значением (двухстрочная entity-ячейка в духе ElevenLabs)."
|
||
},
|
||
"values": {
|
||
"type": "array",
|
||
"items": {
|
||
"type": "string"
|
||
},
|
||
"description": "Field-level data contract: допустимые значения для status/enum-колонок. Заполняется из паспорта/интервью, чтобы владелец видел ПРАВДУ, а не выдумку."
|
||
},
|
||
"source": {
|
||
"type": "string",
|
||
"description": "Метаданные авторинга: откуда значение (SAP, Лотус, KTWorks, агент, человек). Для трассировки/handoff; в рантайме v1 не рендерится автоматически."
|
||
},
|
||
"align": {
|
||
"type": "string",
|
||
"enum": [
|
||
"left",
|
||
"right"
|
||
],
|
||
"description": "Выравнивание ячеек. По умолчанию num — справа, остальное — слева; задаёт явный override (рендерят оба рантайма)."
|
||
},
|
||
"sortable": {
|
||
"type": "boolean",
|
||
"default": false
|
||
},
|
||
"width": {
|
||
"type": "string",
|
||
"description": "Явный override ширины колонки (напр. «140px»). По умолчанию ширина считается по содержимому колонки (из всех строк, с клампом) — не шире и не уже, чем нужно."
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"rows": {
|
||
"type": "array",
|
||
"description": "8-12 правдоподобных строк. Данные – из материалов проекта/интервью, НЕ выдуманные. _flags – список проверок агента для drawer; _docs – артефакты, которые продукт производит по записи (ТС, отчёт, СЗ…).",
|
||
"items": {
|
||
"type": "object",
|
||
"properties": {
|
||
"_flags": {
|
||
"type": "array",
|
||
"items": {
|
||
"type": "string"
|
||
}
|
||
},
|
||
"_docs": {
|
||
"type": "array",
|
||
"description": "Выходные документы записи. Показываются в drawer (секция «Документы») и в nav-секциях view=documents; каждый со статусом и кнопкой скачать.",
|
||
"items": {
|
||
"type": "object",
|
||
"required": [
|
||
"label"
|
||
],
|
||
"additionalProperties": false,
|
||
"properties": {
|
||
"label": {
|
||
"type": "string",
|
||
"description": "Имя документа: «Проект ТС», «Отчёт о консолидации», «Служебная записка»."
|
||
},
|
||
"type": {
|
||
"type": "string",
|
||
"description": "Тип для группировки в nav-секции (docType): ts/report/…"
|
||
},
|
||
"status": {
|
||
"type": "string",
|
||
"description": "Статус по жизненному циклу: «Черновик v1», «Сформирован», «После принятия»."
|
||
},
|
||
"format": {
|
||
"type": "string",
|
||
"description": "Формат для иконки/подписи: doc/pdf/xlsx."
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"drawer": {
|
||
"type": "object",
|
||
"required": [
|
||
"titleKey"
|
||
],
|
||
"additionalProperties": false,
|
||
"description": "Правый drawer деталей объекта (детали в drawer, не на новой странице).",
|
||
"properties": {
|
||
"titleKey": {
|
||
"type": "string",
|
||
"description": "Ключ колонки для заголовка drawer."
|
||
},
|
||
"fields": {
|
||
"type": "array",
|
||
"items": {
|
||
"type": "object",
|
||
"required": [
|
||
"key",
|
||
"label"
|
||
],
|
||
"additionalProperties": false,
|
||
"properties": {
|
||
"key": {
|
||
"type": "string"
|
||
},
|
||
"label": {
|
||
"type": "string"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"flagsLabel": {
|
||
"type": "string"
|
||
}
|
||
}
|
||
},
|
||
"ai": {
|
||
"type": "object",
|
||
"additionalProperties": false,
|
||
"description": "Точка входа AI-помощи (орб Төре). LLM-вызовы только через backend (app/api/ai/*), не из клиента. AI-контент атрибутируется «Сгенерировано ИИ».",
|
||
"properties": {
|
||
"intro": {
|
||
"type": "string"
|
||
},
|
||
"suggestions": {
|
||
"type": "array",
|
||
"items": {
|
||
"type": "string"
|
||
}
|
||
},
|
||
"answers": {
|
||
"type": "object",
|
||
"additionalProperties": {
|
||
"type": "string"
|
||
}
|
||
},
|
||
"fallback": {
|
||
"type": "string"
|
||
}
|
||
}
|
||
},
|
||
"banner": {
|
||
"type": "object",
|
||
"additionalProperties": false,
|
||
"description": "Системный баннер в контенте по схеме «что-почему-что делать».",
|
||
"properties": {
|
||
"text": {
|
||
"type": "string"
|
||
},
|
||
"tone": {
|
||
"type": "string",
|
||
"enum": [
|
||
"info",
|
||
"warn",
|
||
"risk",
|
||
"ok"
|
||
],
|
||
"default": "info"
|
||
},
|
||
"action": {
|
||
"type": "string",
|
||
"description": "Подпись действия баннера (делает баннер полезным, не статичным)."
|
||
},
|
||
"actionNav": {
|
||
"type": "integer",
|
||
"description": "Индекс раздела nav, куда ведёт действие баннера."
|
||
}
|
||
}
|
||
},
|
||
"search": {
|
||
"type": "object",
|
||
"additionalProperties": false,
|
||
"description": "Поиск в шапке. Настраивает поле HTML-рантайма; в React-ките те же три поля живут в пропе `search` у KTAIShell (там же items палитры). Само поле не включается и не выключается этим блоком — в HTML-рантайме оно фильтрует таблицу и есть всегда.",
|
||
"properties": {
|
||
"placeholder": {
|
||
"type": "string",
|
||
"maxLength": 40,
|
||
"description": "Подсказка в поле. По умолчанию «Поиск…». Сочетание сюда писать НЕ надо — у него свой бейдж."
|
||
},
|
||
"compact": {
|
||
"type": "boolean",
|
||
"default": false,
|
||
"description": "Узкое поле (176px) вместо полного: шапка отдаёт место остальному. Бейдж сочетания в нём не показывается — это ширина запроса, а не запроса с подписью; само сочетание продолжает работать и названо в title."
|
||
},
|
||
"shortcut": {
|
||
"type": "boolean",
|
||
"default": true,
|
||
"description": "Сочетание ⌘K/Ctrl+K и его бейдж. Выключается ОДНИМ полем: подпись без обработчика — обещание, обработчик без подписи — незаявленная горячая клавиша. Подпись берётся по клавиатуре машины: ⌘K на Apple, Ctrl K на остальных."
|
||
}
|
||
}
|
||
},
|
||
"conclusion": {
|
||
"type": "object",
|
||
"additionalProperties": false,
|
||
"required": [
|
||
"text"
|
||
],
|
||
"description": "Вывод раздела — последний блок экрана, после таблицы. Противовес баннера: баннер стоит НАД числами и предупреждает, из-за чего число соврёт; вывод стоит ПОСЛЕ данных и говорит, что из них следует (разбор смещения выборки, оговорка о методике, ответ на вопрос раздела). Без этого слота вывод уходил в баннер, и абзац текста вставал до первого числа.",
|
||
"properties": {
|
||
"title": {
|
||
"type": "string",
|
||
"maxLength": 60
|
||
},
|
||
"text": {
|
||
"type": "string",
|
||
"description": "Текст вывода. Пустая строка разделяет абзацы."
|
||
}
|
||
}
|
||
},
|
||
"compare": {
|
||
"type": "object",
|
||
"additionalProperties": false,
|
||
"description": "Данные архетипа compare: попарная сверка двух источников, расхождения подсвечены (аудит/финансы/договоры). Требуется при archetype=compare, иначе экран деградирует в queue.",
|
||
"properties": {
|
||
"aLabel": {
|
||
"type": "string"
|
||
},
|
||
"bLabel": {
|
||
"type": "string"
|
||
},
|
||
"pairs": {
|
||
"type": "array",
|
||
"items": {
|
||
"type": "object",
|
||
"required": [
|
||
"label",
|
||
"a",
|
||
"b"
|
||
],
|
||
"additionalProperties": false,
|
||
"properties": {
|
||
"label": {
|
||
"type": "string",
|
||
"description": "Имя сверяемого поля."
|
||
},
|
||
"a": {
|
||
"type": "string",
|
||
"description": "Ключ колонки источника A."
|
||
},
|
||
"b": {
|
||
"type": "string",
|
||
"description": "Ключ колонки источника B."
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"sections": {
|
||
"type": "array",
|
||
"description": "Свободная композиция (archetype custom): секции-блоки из примитивов системы в любом порядке. Архетипы — отправные точки; когда процесс не ложится в один архетип, экран собирается отсюда.",
|
||
"items": {
|
||
"type": "object",
|
||
"required": [
|
||
"title"
|
||
],
|
||
"additionalProperties": false,
|
||
"properties": {
|
||
"title": {
|
||
"type": "string"
|
||
},
|
||
"description": {
|
||
"type": "string"
|
||
},
|
||
"body": {
|
||
"type": "string"
|
||
},
|
||
"fields": {
|
||
"type": "array",
|
||
"items": {
|
||
"type": "object",
|
||
"required": [
|
||
"label",
|
||
"value"
|
||
],
|
||
"additionalProperties": false,
|
||
"properties": {
|
||
"label": {
|
||
"type": "string"
|
||
},
|
||
"value": {
|
||
"type": "string"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"type": {
|
||
"enum": [
|
||
"text",
|
||
"cards",
|
||
"chart",
|
||
"kpis",
|
||
"table",
|
||
"chat"
|
||
],
|
||
"$comment": "text (по умолчанию) | cards — сетка карточек (хаб инструментов, референс ElevenLabs Home) | chart — чарт по контракту analytics | kpis — глобальная KPI-строка | table — глобальная таблица | chat — глобальный ai-блок"
|
||
},
|
||
"width": {
|
||
"enum": [
|
||
"full",
|
||
"half"
|
||
],
|
||
"$comment": "half — секция занимает полколонки (двухколоночная композиция)"
|
||
},
|
||
"items": {
|
||
"type": "array",
|
||
"maxItems": 12,
|
||
"$comment": "для type=cards",
|
||
"items": {
|
||
"type": "object",
|
||
"additionalProperties": false,
|
||
"required": [
|
||
"title"
|
||
],
|
||
"properties": {
|
||
"title": {
|
||
"type": "string",
|
||
"maxLength": 60
|
||
},
|
||
"text": {
|
||
"type": "string",
|
||
"maxLength": 160
|
||
},
|
||
"badge": {
|
||
"type": "string",
|
||
"maxLength": 24
|
||
},
|
||
"tone": {
|
||
"enum": [
|
||
"ok",
|
||
"warn",
|
||
"risk",
|
||
"info"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"chart": {
|
||
"$ref": "#/properties/analytics/properties/charts/items",
|
||
"$comment": "для type=chart"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"onboarding": {
|
||
"type": "array",
|
||
"description": "Слайды онбординг-карусели при первом входе (2-3). Если не задано — берутся дефолтные слайды на основе product. Иконка из спрайта icons/kt-ai-lucide-sprite.svg.",
|
||
"items": {
|
||
"type": "object",
|
||
"required": [
|
||
"title",
|
||
"text"
|
||
],
|
||
"additionalProperties": false,
|
||
"properties": {
|
||
"icon": {
|
||
"type": "string",
|
||
"description": "Имя иконки из спрайта (sparkles/eye/megaphone/book/play/...)."
|
||
},
|
||
"title": {
|
||
"type": "string",
|
||
"maxLength": 48
|
||
},
|
||
"text": {
|
||
"type": "string",
|
||
"maxLength": 220
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"filterKeys": {
|
||
"$comment": "DEPRECATED: фильтры выводятся из statuses автоматически; поле рендерится для старых конфигов, в новых не использовать",
|
||
"type": "array",
|
||
"items": {
|
||
"type": "string"
|
||
}
|
||
},
|
||
"document": {
|
||
"$comment": "Архетип document: документ с правками агента по фрагментам (договор, письмо, ТЗ)",
|
||
"type": "object",
|
||
"additionalProperties": false,
|
||
"required": [
|
||
"title",
|
||
"fragments"
|
||
],
|
||
"properties": {
|
||
"title": {
|
||
"type": "string",
|
||
"maxLength": 120
|
||
},
|
||
"source": {
|
||
"type": "string",
|
||
"maxLength": 160,
|
||
"$comment": "откуда собран документ (шаблон + заявка)"
|
||
},
|
||
"fragments": {
|
||
"type": "array",
|
||
"minItems": 2,
|
||
"maxItems": 14,
|
||
"items": {
|
||
"type": "object",
|
||
"additionalProperties": false,
|
||
"required": [
|
||
"text"
|
||
],
|
||
"properties": {
|
||
"heading": {
|
||
"type": "string",
|
||
"maxLength": 90
|
||
},
|
||
"text": {
|
||
"type": "string",
|
||
"maxLength": 700
|
||
},
|
||
"was": {
|
||
"type": "string",
|
||
"maxLength": 700,
|
||
"$comment": "прежний текст для op=edit"
|
||
},
|
||
"op": {
|
||
"enum": [
|
||
"keep",
|
||
"edit",
|
||
"add",
|
||
"del"
|
||
]
|
||
},
|
||
"flag": {
|
||
"type": "string",
|
||
"maxLength": 220,
|
||
"$comment": "почему агент пометил фрагмент"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"artifact": {
|
||
"$comment": "Архетип copilot: результат-артефакт рядом с чатом",
|
||
"type": "object",
|
||
"additionalProperties": false,
|
||
"required": [
|
||
"title",
|
||
"preview"
|
||
],
|
||
"properties": {
|
||
"type": {
|
||
"enum": [
|
||
"document",
|
||
"slides",
|
||
"report",
|
||
"table",
|
||
"letter"
|
||
]
|
||
},
|
||
"title": {
|
||
"type": "string",
|
||
"maxLength": 120
|
||
},
|
||
"version": {
|
||
"type": "string",
|
||
"maxLength": 24
|
||
},
|
||
"preview": {
|
||
"type": "string",
|
||
"maxLength": 4000,
|
||
"$comment": "текст/markdown-превью артефакта"
|
||
},
|
||
"actions": {
|
||
"type": "array",
|
||
"maxItems": 3,
|
||
"items": {
|
||
"type": "string",
|
||
"maxLength": 32
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"wizard": {
|
||
"$comment": "Архетип wizard: пошаговая заявка с автозаполнением агентом",
|
||
"type": "object",
|
||
"additionalProperties": false,
|
||
"required": [
|
||
"steps"
|
||
],
|
||
"properties": {
|
||
"current": {
|
||
"type": "integer",
|
||
"minimum": 0
|
||
},
|
||
"steps": {
|
||
"type": "array",
|
||
"minItems": 2,
|
||
"maxItems": 7,
|
||
"items": {
|
||
"type": "object",
|
||
"additionalProperties": false,
|
||
"required": [
|
||
"title",
|
||
"fields"
|
||
],
|
||
"properties": {
|
||
"title": {
|
||
"type": "string",
|
||
"maxLength": 60
|
||
},
|
||
"fields": {
|
||
"type": "array",
|
||
"minItems": 1,
|
||
"maxItems": 10,
|
||
"items": {
|
||
"type": "object",
|
||
"additionalProperties": false,
|
||
"required": [
|
||
"label"
|
||
],
|
||
"properties": {
|
||
"label": {
|
||
"type": "string",
|
||
"maxLength": 60
|
||
},
|
||
"value": {
|
||
"type": [
|
||
"string",
|
||
"number"
|
||
],
|
||
"$comment": "предзаполнено"
|
||
},
|
||
"prefill": {
|
||
"type": "boolean",
|
||
"$comment": "true = заполнил агент"
|
||
},
|
||
"hint": {
|
||
"type": "string",
|
||
"maxLength": 120,
|
||
"$comment": "источник/подсказка"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"desc": {
|
||
"type": "string",
|
||
"maxLength": 160,
|
||
"$comment": "описание шага в вертикальном степпере (референс ElevenLabs)"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"inbox": {
|
||
"$comment": "Архетип inbox: список + постоянная панель чтения; ключи указывают на поля table.rows",
|
||
"type": "object",
|
||
"additionalProperties": false,
|
||
"required": [
|
||
"bodyKey"
|
||
],
|
||
"properties": {
|
||
"titleKey": {
|
||
"type": "string"
|
||
},
|
||
"subKey": {
|
||
"type": "string"
|
||
},
|
||
"timeKey": {
|
||
"type": "string"
|
||
},
|
||
"bodyKey": {
|
||
"type": "string",
|
||
"$comment": "поле строки с полным текстом (письмо, обращение)"
|
||
}
|
||
}
|
||
},
|
||
"analytics": {
|
||
"$comment": "Архетип analytics: аналитический разбор – сводка агента, чарты, выводы",
|
||
"type": "object",
|
||
"additionalProperties": false,
|
||
"required": [
|
||
"charts",
|
||
"findings"
|
||
],
|
||
"properties": {
|
||
"summary": {
|
||
"type": "string",
|
||
"maxLength": 500,
|
||
"$comment": "что агент увидел в данных, 1-3 предложения"
|
||
},
|
||
"period": {
|
||
"type": "string",
|
||
"maxLength": 60
|
||
},
|
||
"charts": {
|
||
"type": "array",
|
||
"minItems": 1,
|
||
"maxItems": 4,
|
||
"items": {
|
||
"type": "object",
|
||
"additionalProperties": false,
|
||
"required": [
|
||
"type",
|
||
"title",
|
||
"points"
|
||
],
|
||
"properties": {
|
||
"type": {
|
||
"enum": [
|
||
"bar",
|
||
"line",
|
||
"donut"
|
||
]
|
||
},
|
||
"title": {
|
||
"type": "string",
|
||
"maxLength": 90
|
||
},
|
||
"unit": {
|
||
"type": "string",
|
||
"maxLength": 20
|
||
},
|
||
"total": {
|
||
"type": [
|
||
"string",
|
||
"number"
|
||
]
|
||
},
|
||
"note": {
|
||
"type": "string",
|
||
"maxLength": 160,
|
||
"$comment": "чтение чарта в одну фразу"
|
||
},
|
||
"points": {
|
||
"type": "array",
|
||
"minItems": 2,
|
||
"maxItems": 14,
|
||
"items": {
|
||
"type": "object",
|
||
"additionalProperties": false,
|
||
"required": [
|
||
"label",
|
||
"value"
|
||
],
|
||
"properties": {
|
||
"label": {
|
||
"type": "string",
|
||
"maxLength": 40
|
||
},
|
||
"value": {
|
||
"type": [
|
||
"number",
|
||
"string"
|
||
]
|
||
},
|
||
"tone": {
|
||
"enum": [
|
||
"ok",
|
||
"warn",
|
||
"risk",
|
||
"info"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"findings": {
|
||
"type": "array",
|
||
"minItems": 1,
|
||
"maxItems": 6,
|
||
"items": {
|
||
"type": "object",
|
||
"additionalProperties": false,
|
||
"required": [
|
||
"title"
|
||
],
|
||
"properties": {
|
||
"title": {
|
||
"type": "string",
|
||
"maxLength": 120
|
||
},
|
||
"detail": {
|
||
"type": "string",
|
||
"maxLength": 300
|
||
},
|
||
"value": {
|
||
"type": [
|
||
"string",
|
||
"number"
|
||
]
|
||
},
|
||
"tone": {
|
||
"enum": [
|
||
"ok",
|
||
"warn",
|
||
"risk",
|
||
"info"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"calendar": {
|
||
"$comment": "Архетип calendar: расписание по датам (окна работ, дежурства, сроки)",
|
||
"type": "object",
|
||
"additionalProperties": false,
|
||
"required": [
|
||
"events"
|
||
],
|
||
"properties": {
|
||
"title": {
|
||
"type": "string",
|
||
"maxLength": 90
|
||
},
|
||
"range": {
|
||
"type": "string",
|
||
"maxLength": 60
|
||
},
|
||
"events": {
|
||
"type": "array",
|
||
"minItems": 2,
|
||
"maxItems": 30,
|
||
"items": {
|
||
"type": "object",
|
||
"additionalProperties": false,
|
||
"required": [
|
||
"date",
|
||
"title"
|
||
],
|
||
"properties": {
|
||
"date": {
|
||
"type": "string",
|
||
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
|
||
},
|
||
"time": {
|
||
"type": "string",
|
||
"maxLength": 20
|
||
},
|
||
"title": {
|
||
"type": "string",
|
||
"maxLength": 120
|
||
},
|
||
"note": {
|
||
"type": "string",
|
||
"maxLength": 160
|
||
},
|
||
"badge": {
|
||
"type": "string",
|
||
"maxLength": 30
|
||
},
|
||
"tone": {
|
||
"enum": [
|
||
"ok",
|
||
"warn",
|
||
"risk",
|
||
"info"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"map": {
|
||
"$comment": "Архетип map: схема-карта участка (точки 0-100 по осям, линии-связи); НЕ геокарта с тайлами",
|
||
"type": "object",
|
||
"additionalProperties": false,
|
||
"required": [
|
||
"points"
|
||
],
|
||
"properties": {
|
||
"title": {
|
||
"type": "string",
|
||
"maxLength": 90
|
||
},
|
||
"points": {
|
||
"type": "array",
|
||
"minItems": 2,
|
||
"maxItems": 24,
|
||
"items": {
|
||
"type": "object",
|
||
"additionalProperties": false,
|
||
"required": [
|
||
"label",
|
||
"x",
|
||
"y"
|
||
],
|
||
"properties": {
|
||
"label": {
|
||
"type": "string",
|
||
"maxLength": 40
|
||
},
|
||
"x": {
|
||
"type": "number",
|
||
"minimum": 0,
|
||
"maximum": 100
|
||
},
|
||
"y": {
|
||
"type": "number",
|
||
"minimum": 0,
|
||
"maximum": 100
|
||
},
|
||
"status": {
|
||
"type": "string",
|
||
"$comment": "ключ из statuses"
|
||
},
|
||
"tone": {
|
||
"enum": [
|
||
"ok",
|
||
"warn",
|
||
"risk",
|
||
"info"
|
||
]
|
||
},
|
||
"note": {
|
||
"type": "string",
|
||
"maxLength": 200
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"lines": {
|
||
"type": "array",
|
||
"maxItems": 40,
|
||
"items": {
|
||
"type": "array",
|
||
"minItems": 2,
|
||
"maxItems": 2,
|
||
"items": {
|
||
"type": "integer",
|
||
"minimum": 0
|
||
}
|
||
},
|
||
"$comment": "связи как пары индексов points"
|
||
}
|
||
}
|
||
},
|
||
"timeline": {
|
||
"$comment": "Архетип timeline: хронология дела/инцидента",
|
||
"type": "object",
|
||
"additionalProperties": false,
|
||
"required": [
|
||
"events"
|
||
],
|
||
"properties": {
|
||
"title": {
|
||
"type": "string",
|
||
"maxLength": 120
|
||
},
|
||
"events": {
|
||
"type": "array",
|
||
"minItems": 3,
|
||
"maxItems": 20,
|
||
"items": {
|
||
"type": "object",
|
||
"additionalProperties": false,
|
||
"required": [
|
||
"time",
|
||
"title"
|
||
],
|
||
"properties": {
|
||
"time": {
|
||
"type": "string",
|
||
"maxLength": 30
|
||
},
|
||
"title": {
|
||
"type": "string",
|
||
"maxLength": 140
|
||
},
|
||
"text": {
|
||
"type": "string",
|
||
"maxLength": 400
|
||
},
|
||
"actor": {
|
||
"type": "string",
|
||
"maxLength": 50
|
||
},
|
||
"tone": {
|
||
"enum": [
|
||
"ok",
|
||
"warn",
|
||
"risk",
|
||
"info"
|
||
]
|
||
},
|
||
"current": {
|
||
"type": "boolean"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"dashboard": {
|
||
"$comment": "Архетип dashboard (референс ElevenLabs): KPI-карточки как табы, выбранная метрика управляет чартом; внизу разборы",
|
||
"type": "object",
|
||
"additionalProperties": false,
|
||
"required": [
|
||
"series"
|
||
],
|
||
"properties": {
|
||
"range": {
|
||
"type": "string",
|
||
"maxLength": 60,
|
||
"$comment": "период данных, напр. «январь — июль 2026»"
|
||
},
|
||
"series": {
|
||
"type": "array",
|
||
"minItems": 1,
|
||
"maxItems": 4,
|
||
"items": {
|
||
"type": "object",
|
||
"additionalProperties": false,
|
||
"required": [
|
||
"points"
|
||
],
|
||
"properties": {
|
||
"kpi": {
|
||
"type": "integer",
|
||
"minimum": 0,
|
||
"$comment": "индекс метрики в kpis, к которой привязан ряд (по умолчанию — порядковый)"
|
||
},
|
||
"title": {
|
||
"type": "string",
|
||
"maxLength": 90
|
||
},
|
||
"unit": {
|
||
"type": "string",
|
||
"maxLength": 20
|
||
},
|
||
"total": {
|
||
"type": [
|
||
"string",
|
||
"number"
|
||
]
|
||
},
|
||
"note": {
|
||
"type": "string",
|
||
"maxLength": 160,
|
||
"$comment": "чтение чарта одной фразой"
|
||
},
|
||
"points": {
|
||
"type": "array",
|
||
"minItems": 2,
|
||
"maxItems": 32,
|
||
"items": {
|
||
"type": "object",
|
||
"additionalProperties": false,
|
||
"required": [
|
||
"label",
|
||
"value"
|
||
],
|
||
"properties": {
|
||
"label": {
|
||
"type": "string",
|
||
"maxLength": 20
|
||
},
|
||
"value": {
|
||
"type": [
|
||
"number",
|
||
"string"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"breakdowns": {
|
||
"type": "array",
|
||
"maxItems": 4,
|
||
"items": {
|
||
"type": "object",
|
||
"additionalProperties": false,
|
||
"required": [
|
||
"title",
|
||
"type",
|
||
"items"
|
||
],
|
||
"properties": {
|
||
"title": {
|
||
"type": "string",
|
||
"maxLength": 90
|
||
},
|
||
"type": {
|
||
"enum": [
|
||
"cards",
|
||
"share",
|
||
"top"
|
||
]
|
||
},
|
||
"unit": {
|
||
"type": "string",
|
||
"maxLength": 20
|
||
},
|
||
"note": {
|
||
"type": "string",
|
||
"maxLength": 160
|
||
},
|
||
"items": {
|
||
"type": "array",
|
||
"minItems": 2,
|
||
"maxItems": 10,
|
||
"items": {
|
||
"type": "object",
|
||
"additionalProperties": false,
|
||
"properties": {
|
||
"label": {
|
||
"type": "string",
|
||
"maxLength": 60
|
||
},
|
||
"value": {
|
||
"type": [
|
||
"number",
|
||
"string"
|
||
]
|
||
},
|
||
"title": {
|
||
"type": "string",
|
||
"maxLength": 60,
|
||
"$comment": "для type=cards"
|
||
},
|
||
"stats": {
|
||
"type": "array",
|
||
"maxItems": 5,
|
||
"items": {
|
||
"type": "object",
|
||
"additionalProperties": false,
|
||
"required": [
|
||
"label",
|
||
"value"
|
||
],
|
||
"properties": {
|
||
"label": {
|
||
"type": "string",
|
||
"maxLength": 40
|
||
},
|
||
"value": {
|
||
"type": [
|
||
"string",
|
||
"number"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"width": {
|
||
"type": "string",
|
||
"enum": [
|
||
"full",
|
||
"reading"
|
||
],
|
||
"description": "Ширина рабочей области свободного экрана. «reading» — мера чтения сплошного текста (~720px), «full» — общая ширина продукта. Без поля: экран только из текстовых секций читается как «reading», любой другой — «full». Секция fields считается НЕ текстом: пары «подпись — значение» на 720px читаются хуже."
|
||
}
|
||
}
|
||
}
|