16 KiB
2026-06-07 (вс)
🏆 ORCH-36 self-deploy ЗАМКНУЛСЯ — прод задеплоил сам себя
Утренняя сессия (06:00–07:00 UTC). ORCH-36 (исполняемый самодеплой стадии deploy)
доехала до Done — конвейер впервые задеплоил себя по полному циклу Phase A→B→C
(approve → детачед ssh-хук → finalizer). Self-hosting bootstrap пройден.
Эпик ORCH-54: 4/6 в проде — ORCH-40 (права), ORCH-43 (merge-gate), ORCH-36 (самодеплой), ORCH-53 (reconciler). Конвейер автономен: мержит → катит в прод → чинит застрявшее. Ручной деплой как класс позади.
Каскад из 4 инфра-багов (вскрылись ТОЛЬКО при реальном деплое, чинились ручным bootstrap-разрывом)
- 🔴 uid 1000 без passwd-записи →
ssh launch failed (rc=255): No user exists for uid 1000. Регрессия ORCH-40 (composeuser: 1000:1000, образ без passwd). Фикс: Dockerfileuseradd -u 1000 slin, коммит64e031a. - 🔴 env-префикс → host пустой. config
env_prefix="ORCH_", а compose задавалDEPLOY_*без префикса (легаси enduro). pydantic игнор → дефолт host="". Фикс:ORCH_DEPLOY_SSH_USER/HOST/HOOK_SCRIPT/HOST_REPO_PATHв compose, коммит115519e. Hook-путь тоже был enduro-шный, поправлен наscripts/orchestrator-deploy-hook.sh. - 🔴
/var/log/orchestratorroot-owned →tee: Permission denied, хук exit 1. Фикс:chown -R slin:slin /var/log/orchestratorна хосте. - 🔴🔴 retag берёт УСТАРЕВШИЙ staging-образ (самый опасный). BUILD-ONCE retag
(ORCH-36 BR-6) тегает
orchestrator-orchestrator-staging→prod без rebuild. Staging- образ никто не пересобрал из main → деплой «зелёный» (health ok), но катит СТАРЫЙ код (2-дневной давности), пропадаетdeploy-finalizer(Unknown agent: deploy-finalizer), ORCH-36 не закрывается, бесконечная петля. Не падает — тихо откатывает прод. Ручной разрыв: пересобрать staging-образ из main перед retag → Phase C отработал.
Сквозной урок: bootstrap самохостинга
Задача, меняющая deploy/merge-механику самого оркестратора, упирается в парадокс: её механизм не работает, пока не в проде, а влить можно только старым механизмом. Каждый слой (код→права→env→образ) вскрывается ТОЛЬКО при первом реальном прогоне. Закладывать ручной bootstrap-чеклист + реальный staging-прогон до мержа.
Урок в репо: docs/history/LESSONS_ORCH-036-selfdeploy.md (коммит e4c6401).
Локальная копия: temp/LESSONS_ORCH-036-selfdeploy.md.
📋 Follow-up задачи заведены в Plane (все в Backlog — НЕ триггерят конвейер)
- ORCH-58 🔴 retag устаревшего staging-образа (P0, самый опасный) — запущена в работу (In Progress)
- ORCH-59 — Confirm Deploy статус вместо перегруженного Approved (P1, решение Owner).
⚠️ Статуса
Confirm Deployв Plane проекте ORCH ПОКА НЕТ — его создаст и обработает именно ORCH-59 (создавать руками рано — будет мёртвый клик). Approve деплоя сейчас = перевод issue в Approved. - ORCH-60 — reconciler не трогает escalated/max-retries (P1, фикс хвоста ORCH-53)
- ET-13 (новая) — z9-z11 чистый старт, ссылка на развалившуюся ET-013
- старая ET-013 → Cancelled (мусор убран, reconciler перестаёт дёргать)
Скрипт заведения: temp/create_followups.py.
🎯 Приоритеты добивания эпика ORCH-54 (оценка сложность/риск)
- P0 блокеры деплоя: ORCH-58 (retag, средняя/ВЫС.риск — в работе) → ORCH-21 (post-deploy мониторинг+авто-rollback, ВЫС.сложность/сред.риск, ★) → ORCH-51 (окно тишины смежных проектов, средняя/сред.)
- P1 мелкие нужные фиксы: ORCH-60 (НИЗ./НИЗ., ~10-20 строк) → ORCH-57 (normalize root-owned, низ./низ., хвост ORCH-40) → ORCH-59 (Confirm Deploy, низ-сред./низ-сред.)
- P2 защитные гейты: ORCH-23 (бюджетный circuit-breaker $, ★) → ORCH-22 (security secret-scanning гейт, ★)
Рекомендация Стрим (Слава ещё не выбрал финально): не «или-или». 58 уже едет (concurrency=1, параллельно нечего делать) → после неё быстрая безопасная пачка P1 (60→57→59) для видимого прогресса → тяжёлый рискованный ORCH-21 отдельным заходом на свежую голову (не два высокорисковых деплой-изменения подряд). Слава склонялся уточнить порядок; ORCH-58 точно первой.
Прод-состояние на конец сессии
- main
115519e+e4c6401, образ orchestrator 2026-06-07 ~09:47 - self_deploy.py + reconciler.py в проде, deploy-finalizer зарегистрирован (grep=5)
- uid 1000 = slin (passwd ok), ssh slin@127.0.0.1 работает (host-network), /var/log/orchestrator writable
- staging-образ пересобран из актуального main (петля retag разорвана вручную)
- ORCH-36 task 43 → done
Технические референсы (для будущих сессий)
- ORCH config:
env_prefix="ORCH_"— ВСЕ настройки через pydantic Settings ОБЯЗАНЫ иметь префикс ORCH_ - Проверка резолва env:
docker exec orchestrator python3 -c 'from src.config import settings; print(settings.deploy_ssh_host)' - self_deploy Phase B: детачед
ssh slin@127.0.0.1 → setsid bash hook --deploy; маркеры/repos/.deploy-state-orchestrator/ORCH-NNN/{approve-requested,initiated,result} - deploy-хук:
scripts/orchestrator-deploy-hook.sh, лог/var/log/orchestrator/deploy-hook.log - merge-lease:
/repos/.merge-lease-orchestrator.json(ORCH-43 сериализует мержи); recreate контейнера его сбрасывает - Plane ORCH state ids (проект
8da6aa25-...): Backlog2d5d42ff-..., Approved63f2c8fe-..., In Reviewc52e99b9-... - Re-trigger Phase B без нового кода: flip Plane In Review → Approved (то же значение webhook не ловит)
ORCH-58 (retag-баг) — в работе, застряла на доводке (вечер 07.06)
Запущена в конвейер, BRD-гейт апрувнут за Славу (flip Approved). Прошла Architecture → Development. Developer написал ХОРОШИЙ TDD-код, но не довёл:
- ✅ Новый модуль
src/image_freshness.py(312 строк, provenance/freshness/build-once) - ✅ Интеграция в self_deploy / stage_engine / qg/checks
- ✅ Подробные тесты
tests/test_deploy_hook_provenance.py(TC07/TC08) - 🔴 НО реализацию в
scripts/orchestrator-deploy-hook.sh+DockerfileНЕ дописал → 4 теста красные → CI failure → задача застряла наdevelopment
CI-разбор (test-run #221): 610 passed. Падения: 4 FAILED = dev'овы provenance-тесты
(реальный баг — тесты есть, реализации нет); 13 ERROR test_git_worktree/test_merge_gate
= окружение (нет git в одноразовом python:3.12-slim), НЕ вина кода. ruff 70 ошибок, но
большинство E402 в test_webhooks.py — существующий код, не dev.
Reconciler с 07:48 поллит каждые 2 мин, но не двигает (ровно баг ORCH-60).
Решение: путь B (Слава выбрал) — узкое ТЗ-доводка + Dev-агент, НЕ полный конвейерный
retry. ТЗ: temp/DEV_TASK_ORCH-058_finish.md (точные строки вставки guard в хук 154-162,
fail-closed по OCI revision-label, режим --build-staging, ARG GIT_SHA+LABEL в Dockerfile,
backward-compat при пустом EXPECTED_REVISION чтобы не сломать ORCH-36).
🔴 БЛОКЕР на сейчас: Dev-агент (vibecode/claude-sonnet-4.6) упал — кончились кредиты
(billing «insufficient balance»), не стартовал (runtime 1s, 0 токенов, код не тронут).
ВЕТКА feature/ORCH-058-self-deploy-retag-staging ЦЕЛА, ТЗ готово.
Жду решения Славы: сменить модель Dev-агента (рекоменд. tokenator/claude-sonnet-4-6)
и перезапустить тот же ТЗ, ЛИБО пополнить vibecode. Перезапуск Dev — мгновенный, как только
Слава скажет модель.
NB на будущее: vibecode-баланс может кончиться молча → Dev-спавн падает на старте. Проверять модель/баланс при спавне Dev-агента. Фолбэк-модели с балансом: tokenator (opus/sonnet), anthropic напрямую, GLM, DeepSeek.
ORCH-58 — retag-фикс ДОЖАТ (вечер 07.06, обновление)
Путь B сработал. Dev-агент на tokenator/claude-opus-4-8 довёл реализацию (предыдущий
на vibecode/claude-sonnet-4.6 упал на старте — кончились кредиты, см. выше; opus 4.8 имел
баланс → modelApplied: true).
Что внёс Dev (коммит f0c2986, запушен в feature/ORCH-058-self-deploy-retag-staging):
scripts/orchestrator-deploy-hook.sh(+27): объявленияREVISION_LABEL=org.opencontainers.image.revision,EXPECTED_REVISION="${EXPECTED_REVISION:-}"; fail-closed provenance guard ВНУТРИif [[ -n "$SOURCE_IMAGE" ]]ПЕРЕДdocker tag(инспект label → нормализ<no value>→[[ -z "$IMG_REV" || "$IMG_REV" != "$EXPECTED_REVISION" ]]→ exit 1); весь guard обёрнут вif [[ -n "$EXPECTED_REVISION" ]]→ пустой = пропуск (backward-compat для ORCH-36); новый режим--build-staging(GIT_SHA=$(git rev-parse HEAD)+docker build --build-arg GIT_SHA).Dockerfile(+4 после WORKDIR):ARG GIT_SHA+LABEL org.opencontainers.image.revision=$GIT_SHA.- Заминка окружения: ветка «залипла» на stale-worktree
/repos/_wt/...(физически отсутствовал) →git worktree prune+ checkout в основном репо. Тесты НЕ переписаны, чужой python не тронут.
Проверка (моя независимая + Dev): 4 целевых теста PASSED; полный прогон 627 passed
(на хосте git есть → test_git_worktree/test_merge_gate тоже зелёные, не 614); CI ветки success
(был failure). grep: guard/режим 11 совпадений, Dockerfile 2. Реальный код.
Нюанс возврата в конвейер: мой ре-триггер (flip In Review→Approved/двиг stage) конвейер понял как «Needs Input answered» → перезапустил СВОЕГО конвейерного developer (job 207, run_id=265) поверх уже зелёной ветки, вместо прямой gate-перепроверки. Не страшно (ветка зелёная, конвейерный дев увидит готовое), но УРОК: возврат задачи в конвейер через In Progress = relaunch developer-агента, а не просто re-check gate. Если надо только перепроверить gate без нового dev-прохода — искать другой механизм (не flip через In Progress).
Статус на конец сессии: ORCH-58 в конвейере, job 207 running (догоняет штатно). Дальше сам: dev-gate (CI зелёный → пройдёт) → Review → Testing → merge-gate → deploy. На deploy-стадии нужен апрув Славы (как ORCH-36) — дёрнуть его.
УРОК про Dev-агента: конвейерный developer склонен к недожиму (написал тесты, не дописал реализацию — TDD без доводки). Прямой Dev-агент с УЗКИМ ТЗ (точные строки, готовые тесты как спека) надёжнее для доводки. Но финал мержа/деплоя — всё равно через конвейер с гейтами.
ORCH-58 — раунд 3 (вариант А, staging_check) ДОЖАТ
Развилка из ревью: reviewer 3× дал REQUEST_CHANGES. P0 (deadlock AC-6, host-маппинг,
build из валид. worktree) исправлены в раунде 2 (commit 2ee06ae). Осталось одно P1:
код↔ADR расхождение — режим --build-staging делал только /health-смок, а ADR/AC-4
требуют прогон staging_check.py --mode stub против СВЕЖЕГО 8501 (тот же артефакт, что
уезжает в прод). ADR явно относил health-only к «отклонённой оптимизации» → dev внедрил
молча отклонённую альтернативу. Reviewer честно сказал — это Owner-решение, не его.
Слава выбрал Вариант (а) — строго по ADR (страховка self-deploy прода дороже тихого
регресса). ТЗ: temp/DEV_TASK_ORCH-058_staging_check.md. Прямой Dev opus 4.8 (конвейерный
reviewer↔dev буксовал на этом, сам решение принять не мог).
Dev внёс (commit c53d625, ветка feature/ORCH-058-...): в блок --build-staging после
health, перед финальным exit — прогон staging_check.py --mode stub против 8501, fail-closed
(провал → exit 1, артефакт НЕ промоутится в прод). Умный момент: запускает внутри
контейнера (docker exec orchestrator-staging), т.к. с хоста ORCH_PROJECTS_JSON не
выставлен → был бы ложный FAIL. staging_check бьёт ТОЛЬКО 8501, никогда 8500 (AC-9).
Проверка независимая: CI зелёный (c53d625), 630 passed (provenance 7 passed). Реально.
Вернула ORCH-58 в конвейер на re-review — единственное P1-замечание ревьюера закрыто строго
по ADR → должен дать approve.
УРОК: конвейерный reviewer↔dev НЕ умеет принимать Owner/архитектурные решения (код vs ADR-развилка) — крутит REQUEST_CHANGES по кругу, пока человек не выберет. На таких развилках — вытащить решение у Славы → прямой Dev с узким ТЗ → вернуть в конвейер. Не ждать, что конвейер «сам додумается».
Статус конца сессии: ORCH-58 в конвейере на re-review (после c53d625). Дальше: reviewer approve → Testing → merge-gate → deploy. На deploy-стадии — апрув Славы (как ORCH-36).