Задания, отчёты и патчи, лежавшие в C:\Users\Ochenstarik\projects и в домашней папке, перенесены в agents/. Разложено по агентам там, где имя файла позволяло определить автора; остальное — в _salvage-2026-08-18/ и разбирается вручную. Патчи в notes/salvage-2026-08-18/ — незакоммиченная работа из брошенных рабочих копий: она существовала только на диске. Тяжёлое (релизные архивы, инсталляторы, наборы данных) в репозиторий не попало: оно лежит рядом, в Agent_projects/_archive и Agent_projects/_data. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
7 KiB
Правила работы — AGENTS.md в корне репозитория.
Репозиторий: https://github.com/ochenstarik-ui/kagent, база — свежий main
Ветка: новая от origin/main, wt/c5-nats-events
Зависимостей нет. Задача трогает Python-сервисы и конфигурацию, с c1 и c4 по файлам не пересекается и может идти параллельно.
Проблема
services/nats/src/events.py — клиент JetStream: подключение, публикация доменного
события, подписка durable-консьюмером, запрос-ответ. Модуль не импортируется ни одним
сервисом и попал в docs/known-drift.json.
Кроме того, он не заработал бы и при подключении: subscribe() вызывает pull_subscribe с
именем потока, который нигде не создаётся. Вызова add_stream в модуле нет. Первая же
подписка упадёт на отсутствующем потоке.
Каталог services/nats при этом не является сервисом: в нём нет ни requirements.txt, ни
Dockerfile, ни записи в docker-compose.yml. Это библиотека, лежащая в каталоге сервисов.
Что сделать
1. Починить клиент
- создавать поток идемпотентно перед публикацией и подпиской: если поток отсутствует — создать с предметами по префиксу, если существует — использовать существующий;
- имя потока и набор предметов вычислять по одному правилу, а не двумя разными местами в коде;
- подтверждение и отрицательное подтверждение сообщения уже есть — сохранить;
- при недоступности брокера соединение повторяется с ограничением, а не бесконечно.
2. Переместить как библиотеку
services/nats — не сервис. Перенести модуль туда, где он является общей библиотекой
Python-сервисов, например packages/py-events либо services/_shared, и подключить как
зависимость к использующим сервисам. Выбранный вариант обосновать одной строкой в отчёте:
структура каталогов описана в ТЗ, раздел 7, и не должна расходиться с фактом.
3. Подключить к одному сервису
Достаточно одного настоящего потребителя, чтобы возможность считалась подключённой.
Выбрать services/pipeline: он уже выполняет шаги и знает об их результате.
Публиковать доменные события жизненного цикла шага с именами из ТЗ, раздел 10:
task.started, agent.started, agent.completed, artifact.created, task.failed.
Событие содержит идентификатор, тип, версию схемы, время, идентификаторы проекта и задачи,
корреляционный идентификатор — как требует ADR-0002.
- адрес брокера из
NATS_URL, значение по умолчанию и запись в.env.example; nats-pyдобавить вrequirements.txtсервиса; версия уже используется вservices/orchestrator, взять ту же;- в
docker-compose.ymlдобавить зависимостьpipelineотnatsпо состоянию работоспособности; - недоступность брокера не должна ронять пайплайн. Публикация — побочный эффект, а не условие выполнения шага. При недоступности брокера событие теряется с записью в лог, шаг продолжается. Это осознанный выбор на текущем этапе: гарантированная доставка требует outbox из ADR-0010, которого ещё нет. Отметить это в отчёте.
4. Доказательство
Модульные тесты на заглушке брокера: событие сериализуется с обязательными полями, имя потока вычисляется одинаково для публикации и подписки, недоступность брокера не прерывает работу.
Интеграционный тест с настоящим брокером в непрерывной интеграции: сервисный контейнер
nats:2.11-alpine с включённым JetStream, публикация и получение события подписчиком,
повторное создание потока не ломает работу.
Добавить возможность в docs/capabilities.json со ссылкой на имя нового job как на
доказательство и снять запись из docs/known-drift.json.
Чего не делать
- публикация событий из Control Plane на TypeScript — отдельная задача, там понадобится своя реализация клиента;
- outbox и гарантированная доставка — ADR-0010, отдельный этап;
- подключение оркестратора: он вообще отсутствует в
docker-compose.yml, это отдельная проблема.
Критерий приёмки
ruff check services scripts
python -m pytest tests/unit -q
python scripts/drift_check.py
- модуль импортируется настоящим сервисом, а не только тестом;
drift_check.pyне сообщает про модуль событий; вknown-drift.jsonосталось две записи либо одна, если c3 уже принята;- job с брокером в CI зелёный, интеграционный тест публикует и получает событие;
roadmap_status.pyпоказывает возможность событийного потока подтверждённой доказательством — вывод до и после в отчёте;- ссылка на зелёный прогон приложена.