# Сократить legacy через выбор одного workflow runtime

> Исторический snapshot. После разделения chat/voice адреса и deployment ownership изменились: чат — https://chat-agent.gis-master.ru/, file UI/diagnostics — https://voice.gis-master.ru/. Текущая поставка: [DEPLOYMENT](</experiments/voice-ai/archive/w/DOCS/DEPLOYMENT.md>). Старые адреса и service owners ниже описывают дату исследования, а не инструкции для текущего runtime.

Статус: предложение, не реализовано. Инвазивность: **Средняя**. Основа: `webrtc-komaroff@772de4a`, 16.09.2026.

В репозитории поддерживаются Python LangGraph, Ruby DSL/adapter и Ruby AsyncGraph. В DRS объявлены все три, хотя Agent выбирает один subject. У них повторяются сценарии, модели памяти и валидация JSON. Само наличие трёх каталогов не делает два из них мёртвыми: у них могут быть отдельные consumers или экспериментальные пользователи.

![От трёх реализаций к одному контракту](</experiments/voice-ai/archive/w/DOCS/architecture-2026-09-16/diagrams/p05-runtime.svg>)

Сначала нужен контракт поведения и corpus. После сравнения можно выбрать runtime и удалить неиспользуемые реализации. Переименование `src_*` не влияет на эту проблему.

## Предлагаемая правка

Зафиксировать поддерживаемые сценарии, errors, pending states, edit semantics и UI commands в общем golden corpus. Одни JSON fixtures прогонять через каждый runtime; сравнивать нормализованное поведение, исключая случайные UUID и timestamps.

Для wire contract выбрать один versioned schema source. Генерировать или проверять Python/Ruby/TypeScript validators по нему, но сохранить ручные domain checks. Слепая генерация DTO не решает смысловую совместимость.

По логам subscriptions и владельцам интеграций установить consumers каждого subject. Затем выбрать один runtime. Текущее `ruby_node` — исходный кандидат, потому что его выбирает DRS default и для него есть executable specs; это не доказательство, что он быстрее или функционально полнее Python.

Удаление выполнять в два этапа: прекратить routing и сборку ненужных компонентов после наблюдаемого окна, затем удалить source, manifests и документацию вместе. Оставить release tag, migration note и проверенный rollback path.

## Измеряемый результат

Статический baseline: Python runtime — **2263**, Ruby DSL — **4205**, Ruby-node — **3913** физических строк `.py/.rb`, включая tests и комментарии. Команда подсчёта в evidence ledger. Эти числа не показывают количество legacy и не дают разрешения удалить 6468 строк автоматически.

Цель при выбранном одном движке: число production workflow implementations **3 → 1**, число поддерживаемых run contracts — один versioned формат, расхождения golden corpus — **0** по обязательным сценариям. Считать также число dependency manifests, build time выбранных jobs и время внесения одинакового изменения в сценарий. Runtime RSS и стоимость не выводятся из LOC.

## Что можно потерять

Альтернативы могут содержать уникальные сценарии, routing heuristics или memory behavior. Сравнение должно охватить free speech, flight follow-up, airports, explicit echo, ошибки tools, отсутствие модели и edit. Не переносить всё уникальное без оценки: некоторые ветви могут быть устаревшими, а некоторые — нужными контрактами.

Откат — вернуть subject и образ зафиксированного предыдущего runtime. После изменения схемы состояния такая простота пропадает; сначала сохранить compatible envelope.

## Основания

[DRS runtime selection](<https://git.giscloud.ru/voice-chat/webrtc-komaroff/-/blob/772de4a714ae6c5abea91946e85a1953ee919ec3/stack/webrtc.drs>), [Python engine](<https://git.giscloud.ru/voice-chat/webrtc-komaroff/-/blob/772de4a714ae6c5abea91946e85a1953ee919ec3/src_langgraph/engine.py>), [Ruby-node registry](<https://git.giscloud.ru/voice-chat/webrtc-komaroff/-/blob/772de4a714ae6c5abea91946e85a1953ee919ec3/src_langgraph_rb_node/lib/src_langgraph_rb_node/scenarios/built_in_registry.rb>), [Ruby DSL](<https://git.giscloud.ru/voice-chat/webrtc-komaroff/-/blob/772de4a714ae6c5abea91946e85a1953ee919ec3/src_langgraph_rb/lib/src_langgraph_rb/scenarios/built_in_catalog.rb>). [Strangler Fig](<https://learn.microsoft.com/en-us/azure/architecture/patterns/strangler-fig>) описывает постепенное переключение потребителей. Он помогает организовать переход, но не выбирает язык или библиотеку вместо parity-проверки.

[Все предложения](</experiments/voice-ai/archive/w/DOCS/architecture-2026-09-16/improvements/README.md>) · [Фактическая архитектура](</experiments/voice-ai/archive/w/DOCS/architecture-2026-09-16/README.md>)
