Для кодогенерации используются изолированные Docker-контейнеры с AI coding agents.
┌─────────────────────────────────────────────────────┐
│ LangGraph Orchestrator │
│ (Developer node в Engineering) │
└─────────────────────────────────────────────────────┘
│
Redis streams
(worker:commands / worker:{id}:*)
│
▼
┌─────────────────────────────────────────────────────┐
│ worker-manager Service │
│ (API / Docker Client / Compose Proxy) │
└─────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ Worker Container (ephemeral) │
│ - Образ: worker-base-common + тулинг │
│ - Нативные утилиты: ruff, pytest, make, python │
│ - Выполняет coding task │
│ - Запрашивает инфраструктуру через CLI │
└─────────────────────────────────────────────────────┘
Вместо Docker-in-Docker (Sysbox), система использует парадигму Flat Dev Environment, управляемую с хоста через worker-manager. Это решает проблемы с RAM, кэшами слоёв и стабильностью.
-
Dual-Network Setup: Каждый воркер подключён к двум сетям:
internal(shared codegen network) — для связи сapi,redisиworker-manager.dev_proj_<worker_id>— изолированная сеть для сайдкар-контейнеров проекта.
-
Compose Proxy: Воркеры (инжектированные AI-агенты) не имеют доступа к Docker. Для запуска инфраструктурных зависимостей (DB, Redis) агенты вызывают compose proxy через
curl $WORKER_MANAGER_URL/api/worker/$WORKER_ID/infra/compose, который проксирует запрос вworker-manager. -
Workspace Bind-Mount: Scaffolded workspace монтируется в
/workspaceвнутри контейнера. Два режима:- Pre-scaffolded (story tasks): путь на хосте
/data/workspaces/{repo_id}/— репозиторий уже подготовлен scaffolder'ом (copier + make setup + git push), workspace переиспользуется между задачами в story. - Ephemeral (standalone tasks):
/tmp/codegen/workspaces/{worker_id}/workspace/— создаётся на лету, удаляется после завершения.docker composeна хосте использует файлы из этого воркспейса для поднятия сайдкар-контейнеров.
- Pre-scaffolded (story tasks): путь на хосте
- Никаких
ports:в compose: Сервисы шаблона не публикуют порты на хост, так как это вызовет конфликты при параллельной работе воркеров. - Агенты обращаются к сайдкар-сервисам по именам хостов (
db:5432) внутри изолированной сетиdev_proj_<worker_id>.
Worker-base образ worker-base-common унифицирован:
- Ubuntu + Python 3.12 + Node.js
- Shared Tooling Layer:
ruff,pytest,mypy,copier, и т.д. установлены на уровне образа (не дублируются на каждый воркер). - Non-root user
worker(uid 1000). Код на хосте через bind-mount не становитсяroot-owned. - Выполнение тестов и линтеров происходит нативно через per-service venv-ы, без запуска дополнительных эфемерных контейнеров.
delete_worker() now cleans worker:{id}:input and worker:{id}:output streams (were orphaned forever before).
Reverse check (Redis → Docker): scans worker:status entries and cleans stale ones where the container is gone. Introspect API shows GONE status for stale workers.
Scans both WORKSPACE_BASE_PATH and SCAFFOLDED_WORKSPACE_PATH. Max age: 35h. Also cleans stale workspace:active_projects Redis entries. When workspace is deleted, calls POST /repositories/{repo_id}/notify-workspace-deleted to clear workspace_ready flag so scaffolder re-creates it before next task dispatch.
_check_project_lock() verifies worker:status — workers in terminal states (DEAD/FAILED/STOPPED) get their Redis keys cleaned up automatically, unblocking new task dispatch without manual intervention.
/api/introspect/ router with 7 endpoints:
- List workers, worker detail (with container info from Docker)
- Container logs (tail param, max 5000 lines)
- Workspace file tree, file content (path traversal protection)
- Prompts (CLAUDE.md + TASK.md)
- Kill worker
Admin-frontend nginx proxies /wm-api/ → worker-manager.