From f2169ccf48436907ffad5c3f4e0516482e8b80c1 Mon Sep 17 00:00:00 2001 From: DanliaQwerty20 Date: Mon, 14 Sep 2026 17:12:33 +0300 Subject: [PATCH] =?UTF-8?q?docs:=20=D0=B7=D0=B0=D0=BA=D1=80=D0=B5=D0=BF?= =?UTF-8?q?=D0=B8=D1=82=D1=8C=20=D0=B2=D0=BB=D0=B0=D0=B4=D0=B5=D0=BB=D1=8C?= =?UTF-8?q?=D1=86=D0=B0=20=D0=BE=D1=80=D0=BA=D0=B5=D1=81=D1=82=D1=80=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D0=B8=20=D0=B4=D0=B8=D0=B0=D0=BB=D0=BE=D0=B3=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/adr/0013-conversation-orchestration.md | 71 +++++++++++++++++++++ docs/architecture/PLATFORM.md | 4 ++ docs/delivery/CURRENT_STATUS.md | 9 ++- docs/delivery/MVP_ROADMAP.md | 14 ++-- 4 files changed, 89 insertions(+), 9 deletions(-) create mode 100644 docs/adr/0013-conversation-orchestration.md diff --git a/docs/adr/0013-conversation-orchestration.md b/docs/adr/0013-conversation-orchestration.md new file mode 100644 index 0000000..7aba9d2 --- /dev/null +++ b/docs/adr/0013-conversation-orchestration.md @@ -0,0 +1,71 @@ +# ADR-0013: Conversation Service владеет диалогом + +- Status: accepted +- Date: 2026-09-14 + +## Контекст + +`Channel Gateway` уже принимает общий текстовый запрос и вызывает `Agent Runtime`. Следующий шаг — +создать сохранённое действие и вернуть карточку подтверждения. Если эту цепочку реализовать внутри +каждого канала или Gateway, Web, Telegram и VK начнут по-разному обрабатывать повторы, состояние +диалога и ошибки. + +`Agent Runtime` не должен сохранять действие: он переводит текст в предложение. `Action Service` +не должен вести диалог: он хранит и выполняет уже сформированное действие. + +## Решение + +Создать отдельный `Conversation Service` как владельца прикладной оркестрации сообщения. + +```mermaid +sequenceDiagram + participant Channel as Telegram / Web / VK + participant Edge as Channel Gateway + participant Talk as Conversation Service + participant Agent as Agent Runtime + participant Action as Action Service + + Channel->>Edge: текст + requestKey + Edge->>Talk: нормализованное сообщение + identity + Talk->>Agent: разобрать текст + Agent-->>Talk: предложение или вопрос + alt данных достаточно + Talk->>Action: создать действие + Action-->>Talk: actionId + payloadHash + payload + Talk-->>Edge: карточка подтверждения + else нужно уточнение + Talk-->>Edge: текстовый вопрос + end + Edge-->>Channel: общий ответ канала +``` + +Границы компонентов: + +- `Channel Gateway` проверяет identity, нормализует запрос и переводит общий ответ в протокол канала. + Он остаётся stateless и не вызывает `Agent Runtime` или `Action Service` напрямую после миграции. +- `Conversation Service` хранит сообщения и состояние диалога, обеспечивает идемпотентность по + `tenantId + subject + requestKey`, вызывает Agent и Action. +- `Agent Runtime` только возвращает предложение действия или вопрос для уточнения. +- `Action Service` остаётся источником истины для `actionId`, `payloadHash`, статуса и результата. +- `Widget SDK` проверяет и отображает общий контракт карточки. Он не вызывает Agent, MCP или базу. +- Кнопка карточки отправляет решение вместе с `actionId` и `payloadHash`; только `Action Service` + принимает или отклоняет действие. + +Переход выполняется совместимо: существующий `/api/v1/messages` остаётся временным техническим +маршрутом до появления Conversation Service. Новый диалоговый endpoint добавляется отдельно; старый +удаляется только в следующей major-версии контракта. + +## Причина + +Так один и тот же диалог работает во всех каналах, а границы остаются простыми: Gateway отвечает за +транспорт, Conversation — за ход диалога, Agent — за разбор текста, Action — за надёжное действие. +Повтор доставки из Telegram или VK не создаёт второе действие. + +## Последствия + +- Появится отдельный репозиторий `conversation-service` со своей базой и миграциями. +- До его реализации Channel Gateway продолжает прямой вызов Agent как временный мост. +- Контракт ответа канала должен различать текст, карточку подтверждения и результат. +- Карточка содержит только отображаемые данные и ссылку на сохранённое действие; секреты и правила + выполнения в неё не попадают. +- Реальные бизнес-правила уточнений и текста карточки требуют отдельного решения владельца продукта. diff --git a/docs/architecture/PLATFORM.md b/docs/architecture/PLATFORM.md index 0184d93..1359183 100644 --- a/docs/architecture/PLATFORM.md +++ b/docs/architecture/PLATFORM.md @@ -34,6 +34,10 @@ flowchart TB - Transactional outbox согласует изменения локального состояния и публикацию событий. - Контракты обратно совместимы в пределах major-версии и проверяются в CI. - Все сервисы передают W3C Trace Context и отправляют данные OpenTelemetry. +- Channel Gateway не хранит диалог и не оркестрирует бизнес-сервисы. +- Conversation Service владеет состоянием диалога и цепочкой Agent → Action. +- Agent Runtime предлагает действие, а Action Service остаётся источником его состояния и payload hash. +- Widget SDK отображает контракт ответа, но никогда не вызывает MCP напрямую. ## Границы репозиториев diff --git a/docs/delivery/CURRENT_STATUS.md b/docs/delivery/CURRENT_STATUS.md index f638cf7..e15484d 100644 --- a/docs/delivery/CURRENT_STATUS.md +++ b/docs/delivery/CURRENT_STATUS.md @@ -6,14 +6,15 @@ | Репа | Что меняем или добавляем | Ожидаемый результат | Фактический результат | Следующий шаг | |---|---|---|---|---| | `.github` | Общие workflows и правила | Одинаковый CI/CD для всех сервисов | Java, Python, Node, docs, security и container workflows работают | Подключать правила к каждой новой репе | -| `contracts` | Версионируемые внешние и внутренние API | Один проверяемый источник сетевых DTO | Bundle `2.2.0` выпущен; добавлен Channel Gateway API | Спроектировать контракт ответа для виджета | +| `contracts` | Версионируемые внешние и внутренние API | Один проверяемый источник сетевых DTO | Bundle `2.2.0` выпущен; добавлен Channel Gateway API | Добавить совместимый ответ диалога и карточку подтверждения | | `action-service` | Подтверждение и надёжное выполнение | `AWAITING_APPROVAL → APPROVED → EXECUTING → SUCCEEDED/FAILED` | jOOQ, outbox, Temporal worker и вызов MCP Gateway работают; backend acceptance зелёный | Принимать команду через Channel Gateway | | `calendar-mcp` | `create_event` | Идемпотентное создание fake-события | Fake Calendar, OIDC и защита от дублей работают в общем сценарии | Оставить эталонным fake-коннектором | | `mcp-gateway` | OIDC, allowlist и MCP client | Безопасный stateless-маршрутизатор | Foundation смержен и проверен вызовом Calendar MCP | Добавлять коннекторы только по контракту | | `deploy` | Приложения в локальном Compose | Одна команда поднимает вертикальный backend-срез | Channel, Agent, Action, Temporal, MCP Gateway и Calendar поднимаются; GitHub smoke зелёный | Ускорить сборку полного smoke | | `test-lab` | Календарный acceptance-тест | Один JWT и один контракт на всём пути | Схема Agent `2.1.0`, подтверждение и проверка часового пояса работают | Добавить повтор запроса и проверку отсутствия дубля | | `agent-runtime` | Текст в предложение действия | Детерминированное предложение встречи без скрытого выполнения | API `2.1.0`, проверка JWT и календарное предложение работают в общем сценарии | Вызывать через Channel Gateway, AI-модель пока не выбирать | -| `channel-gateway` | Общий вход каналов | Web и Telegram используют один контракт | Репа создана; JWT, OpenAPI-типы и вызов Agent работают в общем acceptance | Добавить сохранённое action в ответ после выбора orchestration | +| `channel-gateway` | Общий вход каналов | Web и Telegram используют один контракт | Репа создана; JWT, OpenAPI-типы и вызов Agent работают в общем acceptance | После Conversation Service заменить временный прямой вызов Agent | +| `conversation-service` | Состояние диалога и прикладная оркестрация | Повтор сообщения не создаёт второе действие | Граница закреплена в ADR-0013; репа ещё не создана | Добавить контракт API и создать TDD-каркас | | `widget-sdk` | Карточка подтверждения | Один UI-контракт для разных каналов | Репа ещё не создана | Спроектировать тип карточки и создать репу | ## Что уже проверено @@ -41,7 +42,9 @@ -> [готово] Action Service и Temporal worker -> [готово] Channel Gateway и Agent Runtime в общем Compose -> [готово] backend acceptance - -> [следом] контракт карточки подтверждения и Widget SDK + -> [решено] Conversation Service владеет диалогом и цепочкой Agent → Action + -> [следом] совместимый контракт диалога и карточки подтверждения + -> Conversation Service и Widget SDK -> Telegram adapter ``` diff --git a/docs/delivery/MVP_ROADMAP.md b/docs/delivery/MVP_ROADMAP.md index 1cd5b16..95ce175 100644 --- a/docs/delivery/MVP_ROADMAP.md +++ b/docs/delivery/MVP_ROADMAP.md @@ -69,12 +69,14 @@ 2. Сначала написать сквозной acceptance-тест на fake AI и fake Calendar MCP. 3. Реализовать Channel Gateway без зависимости от Telegram. 4. Сделать Telegram адаптер примером канала, а не центром архитектуры. -5. Создать Widget SDK и карточку подтверждения. -6. Реализовать Conversation Service, Approval Service и MCP Gateway минимального размера. -7. Подключить один реальный календарь за тем же контрактом, что и fake. -8. Добавить audit trail, policy decision и durable workflow. -9. Провести load, soak, chaos и restore проверки. -10. Выпустить публичную MVP-версию с demo и инструкцией запуска. +5. Добавить совместимый контракт ответа диалога и карточки подтверждения. +6. Реализовать Conversation Service минимального размера и переключить на него Channel Gateway. +7. Создать Widget SDK, который проверяет и отображает общий контракт. +8. Реализовать Approval Service только когда появятся правила подтверждения сложнее текущего Action API. +9. Подключить один реальный календарь за тем же контрактом, что и fake. +10. Добавить audit trail, policy decision и durable workflow. +11. Провести load, soak, chaos и restore проверки. +12. Выпустить публичную MVP-версию с demo и инструкцией запуска. Definition of Done MVP: