РЕШЕНО (B213) — проверяет Temporal.
VerificationWorkflow — единственный CI. bash-контур воркера
(Claude Code worker, внешний репозиторий, задачи CW-23/24/25) свои гейты как авторитет не
исполняет; его push в Forgejo покрывается вебхуком (CI-6,
webhook_receiver) → Temporal. Реализация — CI-9-S2 (заглушка → диспатч) + маршрут
worker-а через вебхук.
Записано в «Решения» (2026-09-14).
НЕСТЫКОВКА (B219) — открыта: публикация dev-env не сделана.
Решение «публиковать можно» зафиксировано (2026-09-14): добавить цель push-dev-env
(два тега — стабильный v0.1.0 + commit-SHA, без :latest) и конвенцию
координаты ${REGISTRY_ADDR}/dev-env-<repo>:v0.1.0. Сама публикация и
межрепозиторный контракт координаты ещё не реализованы ни в одном репо.
Что это за задача
Сегодня проверка кода — заглушка: VerificationWorkflow читает verify.command из
.meeseeks/project.yml и просто логирует его, ничего не исполняя. CI-9 переводит исполнение
в Nomad-джобу — как агентов — и учит её гонять стадии из project.yml.
Зависит от: CI-4 (каркас VerificationWorkflow), CI-5 (триггер на верном SHA), NM-1/NM-5 (доставка кода: repo-fetch, read-бот → MinIO).
Как устроена verify-джоба
Группа verify (nomad/verify.nomad.hcl) — четыре таска в одной bridge-сети:
| Таск | Роль | Что делает |
|---|---|---|
repo-fetch | prestart | скачивает снапшот репозитория и распаковывает в alloc dir до старта проверки. |
dind | prestart-сайдкар | привилегированный docker-демон (docker:27-dind) — чтобы стадии могли собирать контейнеры. |
wait-for-dockerd | prestart | ждёт готовности docker-демона; таймаут — отдельный код выхода (112). |
verify | main | исполняет стадии; образ — dev-env целевого репозитория. |
Два входа
Вход А · после агента (CI-5)
DevPipeline после успешного шага берёт commit_sha из task_result.json и запускает
VerificationWorkflow на проверенном SHA — не на «последнем на ветке».
Вход Б · человек запушил (CI-6)
Приёмник вебхука Forgejo (webhook_receiver.py) стартует VerificationWorkflow на
коммите события без участия агента.
Срезы CI-9
Задача разбита на три среза. Все три закрыты — CI-9 Done.
Срез 1 · среда · Done
verify-джоба поднимается в Nomad: repo-fetch распаковывает чекаут, dind-сайдкар отдаёт демон, wait-loop ждёт готовности и отличает недоступность демона от красной стадии кодом выхода. Стадии ещё не исполняются — срез даёт наблюдаемую среду прогона.
Подзадачи CI-9.1, CI-9.2
Срез 2 · перестать быть заглушкой · Done
VerificationWorkflow вместо in-process stub диспатчит verify.nomad.hcl на (repo, ref), идемпотентно по step_id, и ждёт результат по контракту task_result.json/exit_code. Verify-таск исполняет стадии из project.yml по порядку — lint.steps, затем verify.command — и на первой ошибке останавливается, называя упавшую стадию по имени.
Подзадачи CI-9.3, CI-9.4, CI-9.5
Срез 3 · регрессия · Done
Различимость причины красноты доказана прогоном: нарушение lint и провал verify дают разные результаты, чистый репозиторий проходит все стадии. Реестр тесткейсов CI-9 прогоняется целиком.
Подзадача CI-9.6
Подзадачи CI-9
| ID | Слой | Что делает | Зависит от |
|---|---|---|---|
CI-9.1 | Infra | verify.nomad.hcl: группа verify (repo-fetch + dind + verify), bridge-сеть. | — |
CI-9.2 | Infra | Wait-loop готовности dockerd в entrypoint; таймаут — отдельный exit code. | CI-9.1 |
CI-9.3 | Домен | parse_project_config расширен: упорядоченный список стадий (lint.steps + verify.command) с именем и командой; test.steps не читается. | — |
CI-9.4 | Orchestration | VerificationWorkflow.run() вместо stub диспатчит verify.nomad.hcl (идемпотентно по step_id), ждёт результат по task_result.json/exit_code. | CI-9.1, CI-9.3 |
CI-9.5 | Домен | Последовательное исполнение стадий внутри verify-таска; первая ошибка стопит прогон, результат называет упавшую стадию. | CI-9.3, CI-9.4 |
CI-9.6 | Тест | Регрессионный прогон: нарушение lint / провал verify / чистый репозиторий. | CI-9.2, CI-9.4, CI-9.5 |
Тесткейсы
Кейсы, привязанные к CI-9 в листе «Тесткейсы» (колонка «Единица бэклога»):
| TC-ID | Дано | Когда | Тогда |
|---|---|---|---|
TC-CI-9.1-a | verify.nomad.hcl с группой verify (repo-fetch + dind + wait-for-dockerd + verify) | `nomad job run` | repo-fetch распаковал тарбол; dind в running; wait-for-dockerd вышел 0; verify стартует |
TC-CI-9.2-a | dind ещё не готов | wait-for-dockerd в wait-loop на `docker info` | при готовности — код 0, verify стартует; при таймауте — код 112, отличимый от 1 и 0 |
TC-CI-9.3-a | project.yml с lint.steps и verify.command | parse_project_config | упорядоченный список стадий: lint по именам, затем verify, у каждой имя и команда |
TC-CI-9.3-b | project.yml без verify.command | parse_project_config | MissingVerifyCommandError — поведение не сломано |
TC-CI-9.4-a | VerificationWorkflow.run() на (repo, ref) | шаг исполняется | verify.nomad.hcl задиспатчена через dispatch_job_with_meta с (repo, ref) в meta; in-process не исполняется |
TC-CI-9.4-b | та же пара (repo, ref) уже продиспатчена | повторный run() | диспатч идемпотентен по step_id — второй джобы нет |
TC-CI-9.5-a | внесено нарушение lint-стадии (import-linter) | verify-таск исполняет стадии по порядку | прогон остановлен на lint, verify.command не запускается; результат называет упавшую стадию |
TC-CI-9.6-a | репозиторий с нарушением lint и отдельно с провалом verify, рядом чистый | регрессионный прогон на трёх | оба нарушения красные с различимой причиной; чистый — зелёный |
Рамки и решения
Правила, внутри которых делается CI-9 (лист «Архитектура», «Решения»):
- A-43 — один шаг = один диспатч, одна аллокация, один контейнер; рестарты и решедулы отключены.
- A-44 — дорогая аллокация не резервируется до гейта; проверка комплектности — дешёвым prestart-таском.
- A-45 / B51 — при провале prestart poststop не запускается; ожидание сигнала получает короткий первый порог.
- A-46 / B164 — образ верификации = dev-env целевого репозитория; отдельный minimal runner запрещён.
- A-47 / B66 — образы тегируются стабильным тегом + commit-SHA; `:latest` не используется.
- B103 / B143 — сигнал не источник истины: уведомление ставит флаг, значение перечитывается у владельца факта.
- C51 — связка Temporal↔Nomad в общем виде (push-модель, watcher) вынесена за рамки, пересмотр отложен.
- B159 / C159 — координата образа main-таски передаётся meta; на CI-9-S1 задаётся вручную.
Решения CI-9-S2
Три развилки, державшие срез в NeedSpec, закрыты (решения 2026-09-15).
| Развилка | Решение |
|---|---|
| Runner стадий | docker/verify/run_stages.py запечён в dev-env образ, verify-таск зовёт его как command (nomad/ исключён .dockerignore). |
| Получение результата | опрос read_alloc_status (обобщён: main_task_name/fetch_task_name/result_file) до терминала; имя упавшей стадии — из result.json. |
| Источник координаты | verify_image в meta — имя без registry, registry подставляет HCL (${REGISTRY_ADDR}/${NOMAD_META_verify_image}); публикация dev-env — push-dev-env (B219 частично: остальные репо — отдельный долг). |
Что готово
Готово
nomad/verify.nomad.hcl— группа verify (repo-fetch + dind + wait-for-dockerd + verify).- Runner
docker/verify/run_stages.py— стадии lint.steps → verify по порядку, стоп на первой ошибке. VerificationWorkflow—dispatch_verification(идемпотентно по step_id) + poll до терминала.parse_project_config— упорядоченные стадии (CI-9.3).push-dev-env+DEV_ENV_IMAGE v0.1.0(B219).- Реестр тесткейсов CI-9 (1-a..9.6-a) зелёный:
verify-ci9-s3.
Осталось (долг)
- Публикация dev-env в остальных продуктовых репо (B219 — только mr_meeseeks закрыт).
- Вход А передаёт плейсхолдер
_DEFAULT_VERIFICATION_REPO— источник repo из входа пайплайна.
Связи
Блокирует
CI-7 (commit-status — публиковать нечего, пока нет вердикта), RA-2/RA-3 (ревьюер и гейт «CI зелёный»), CM-3 (стадии import-linter/tach), PL-1 (пилот).
Перед
CI-9-S1 (среда), CI-4/CI-5 (каркас + триггер), NM-1/NM-5 (доставка кода).