212 lines
38 KiB
Markdown
212 lines
38 KiB
Markdown
# 2026-06-06
|
||
|
||
## ORCH-46 запущен конвейером (вариант A) — 04:06 UTC
|
||
- Слава выбрал **вариант A** («вклеить findings», минимальный), велел сделать **автономно** (вести до конца как ORCH-47, дёргать только если упрётся в его решение).
|
||
- ТЗ: `tasks/orchestrator/DEV_TASK_ORCH-046.md` (3 варианта дизайна, выбран A). Описание варианта A залито в Plane ORCH-46 (заголовок укорочен 120→77 символов под QG-0).
|
||
- **Суть A:** в `src/stage_engine.py` встраивать ТЕКСТ замечаний в task_desc деву (не только ссылку):
|
||
- reviewer REQUEST_CHANGES (~стр.419): парсить `## Findings` из 12-review.md → вынуть P0/P1 дословно
|
||
- tester FAIL (~стр.455): вынуть reason + фрагмент 13-test-report.md
|
||
- новый хелпер-парсер (graceful, never raise, fallback на ссылку)
|
||
- НЕ трогать: гейты check_* (ORCH-45/47), QG-реестр, retry/rollback-логику, webhook-пути.
|
||
- **task 37**, ветка `feature/ORCH-046-stage-engine-pass-reviewer-tes`, analyst run 139.
|
||
- **ПЛАН (автономно):** дать конвейеру пройти analyst→arch→dev→review→testing→deploy-staging.
|
||
- Это правка ЯДРА → следить внимательнее. На BRD-апруве задача встанет ждать Approved Славы (by design) — НЕ забыть, что на BRD нужен человек.
|
||
- Возможные затыки: (1) BRD-апрув ждёт Славу; (2) staging B6 isolation FAIL (как у ORCH-47 — не блокер кода, но даст FAILED на deploy-staging); (3) если петля dev↔review — теперь должна быть короче, т.к. фикс про передачу findings.
|
||
- Финал: ручной merge + ребилд прода (build образа + рестарт + claude-auth check) — по накатанному из LESSONS_2026-06-05.md.
|
||
|
||
## ✅ ORCH-46 ЗАКРЫТА (вариант A, автономно по доверию Славы) — 04:50 UTC
|
||
- Слава дал «вариант В» = вести совсем без остановок, апрув BRD за него.
|
||
- **Прошёл конвейером БЕЗ ЕДИНОЙ ПЕТЛИ** (иронично — задача про устранение петель): analysis→architecture→development→review (APPROVED с 1 раза)→testing (check_tests_passed принял result:PASS)→deploy-staging. Дев=1 заход.
|
||
- **BRD-апрув не понадобился:** задача стартовала через In Progress (а не Backlog) → это и есть Approved-эквивалент входа, BRD-гейт не застопорил (analysis→architecture auto-advance).
|
||
- **Реализация (проверила лично):** новый `src/review_parse.py` (extract_review_findings/extract_test_failures, never raise, graceful fallback на ссылку), `stage_engine.py` +37/-6 — вклеивает `Findings (P0/P1):` дословно деву + `Причина: {reason}` для tester. Критичная логика (retry/rollback/QG-реестр/гейты) НЕ тронута. ADR-001 «embed-findings-in-task-desc». 50 тестов passed.
|
||
- **Merge PR #43** (`0bc23984`), деплой (chown+reset+build+up+health+auth-check) — review_parse активен в /app, claude-auth жив.
|
||
- **Staging FAIL = тот же B6/ORCH-48** (sandbox=NO, prod-ET/ORCH=YES) — деплоер сам в triage-note указал: `ORCH_PROJECTS_JSON` staging смотрит на прод. К коду ORCH-46 отношения НЕТ (9/10 PASS). Решение как с ORCH-47: код в прод, B6 отдельно.
|
||
- ✅ Plane ORCH-046 → Done; task37 → done в БД.
|
||
|
||
## Состояние прод-гейтов/ядра после ORCH-46:
|
||
- ✅ check_ci_green — поллинг (ORCH-45)
|
||
- ✅ check_tests_passed — читает result: (ORCH-47)
|
||
- ✅ stage_engine — передаёт деву ТЕКСТ findings, не только ссылку (ORCH-46)
|
||
- Бэклог high: **ORCH-48/B6** (staging registry isolation — теперь стоит поднять приоритет: блокирует автономный deploy-staging у ВСЕХ ORCH-задач!), ORCH-44 (надёжность запуска агента)
|
||
|
||
## ORCH-48 / B6 — ROOT CAUSE найден (05:00 UTC) — баг в ТЕСТЕ, не в инфре
|
||
- Деплоер думал: misconfig staging-контейнера (ORCH_PROJECTS_JSON смотрит на прод). **НЕВЕРНО.**
|
||
- **Факт (проверено прямым запуском в orchestrator-staging):** `known_plane_project_ids()` отдаёт count=1, sandbox=True, ET=False, ORCH=False. `.env.staging` УЖЕ правильно задаёт ORCH_PROJECTS_JSON=только sandbox. **Изоляция реестра в staging работает идеально.**
|
||
- **Баг — в самом B6-чеке** `scripts/staging_check.py` (стр.263+): делает `sys.path.insert(0,"/repos/orchestrator")` + import `src.projects` из ХОСТ-worktree (где env НЕ staging) → `importlib.reload` подхватывает env процесса harness, а не staging-контейнера → читается built-in _DEFAULT_PROJECTS (ET+ORCH) → ложный FAIL.
|
||
- **Решение ORCH-48:** B6 должен проверять реестр ВНУТРИ staging-контейнера (его env), а не импортить из host-worktree. Правка кода `scripts/staging_check.py` → подходит для конвейера.
|
||
- Built-in default registry (`src/projects.py` _DEFAULT_PROJECTS) = ET+ORCH — он и подхватывался при пустом env у harness.
|
||
|
||
|
||
## Приоритизация ORCH-46 vs ORCH-48 (утро 06.06) — для контекста
|
||
- Слава утром спросил «что первым: ORCH-46 или ORCH-48». Рекомендовала ORCH-46 первой (корень ручного пинания задач: «испорченный телефон» dev↔review, нет передачи текста findings, нет памяти между кругами). → Взяли ORCH-46, закрыли (см. выше).
|
||
- **Следующая по логике — ORCH-48/B6** (root cause уже найден, см. блок выше): правка `scripts/staging_check.py`, чтобы B6 проверял реестр ВНУТРИ staging-контейнера, а не импортил `src.projects` из host-worktree. Это разблокирует автономный deploy-staging для ВСЕХ ORCH-задач (сейчас у всех ложный FAIL на B6).
|
||
- Прочий бэклог high: ORCH-44 (надёжность запуска агента).
|
||
|
||
## ORCH-48 переигран на вариант (в) (06:56 UTC) — по решению Славы
|
||
- Первый прогон: архитектор выбрал **вариант (а)** (HTTP-эндпоинт `GET /projects`), дев написал код, конвейер прошёл БЕЗ петель (analyst→…→deployer все exit 0) → **deploy-staging FAILED** → откат на development.
|
||
- Причина FAIL = **курица-яйцо варианта (а):** B6 ходит на `/projects` работающего staging-инстанса, а эндпоинт запечён в образ → в текущем образе его НЕТ (404 на 8501 и 8500 проверено) → ложный FAIL. Требует ручного bootstrap-деплоя. Это класс поломки автономности.
|
||
- **Слава выбрал вариант (в)** («запуск suite ВНУТРИ контейнера, без HTTP-эндпоинта») — принципиально без курицы-яйца ни сейчас, ни в будущем.
|
||
- **Переигровка (сделала):** (1) `git reset --hard 8b5b1f0` ветки до analyst-артефактов (стёрла ADR(а) `f77825b` + код(а) `2cf873a` + reviewer/tester auto-commits), force-push; (2) встроила в `02-trz.md §4` блок «РЕШЕНИЕ ПРИНЯТО ВЛАДЕЛЬЦЕМ: вариант (в)» с обоснованием + что обязан зафиксировать архитектор (убрать host-path хак, запуск через `docker exec`, синхронно править `deployer.md`+`STAGING_CHECK.md`, чистая `_evaluate_b6`, НЕ трогать прод-main/projects/.env), коммит `7a6c7a0`; (3) `update_task_stage(38,"architecture")` + `enqueue_job(architect)` через `/tmp/replay_arch.py` с guard'ами (agent_running=None, нет активных jobs). job 91, run 151 architect стартовал 06:56.
|
||
- ⚠️ Существует PR #45 на эту ветку (открыт при работе под (а)) — после переигровки указывает на пересобранную ветку. Не мержить раньше прохождения staging.
|
||
- **Топология (для архитектора в ADR):** Dockerfile НЕ копирует `scripts/` в образ → `staging_check.py` только через mount `/repos/orchestrator/scripts/...`, путь запуска внутри контейнера учесть.
|
||
- **План автономно:** довести arch→dev→review→testing→deploy-staging. Теперь staging должен пройти САМ (в варианте (в) bootstrap не нужен). Финал — merge PR + ребилд прода по LESSONS_2026-06-05.
|
||
|
||
## ✅ ORCH-48 ЗАКРЫТА на варианте (в) (07:12 UTC) — идеально, без петель, без касания прода
|
||
- Переигровка прошла arch→dev→review→tester (runs 151-154, все exit 0) БЕЗ петель.
|
||
- **Архитектор зафиксировал (в)** (ADR `ADR-001-b6-registry-via-in-container-run.md`): host-path хак убран, чистая `_evaluate_b6(known)->(bool,str)`, запуск suite через `docker exec orchestrator-staging`, `/projects`-эндпоинт НЕ добавлен, прод-`src/main.py` НЕ тронут.
|
||
- **deploy-staging: `staging_status: SUCCESS, 10/10 PASS`** — ГЛАВНОЕ: **B6 ✓ PASS** `[sandbox=YES, prod-ET=NO, prod-ORCH=NO]` САМ, без bootstrap. Деплоер запускал suite ВНУТРИ контейнера через docker.sock (CLI в env агента нет) → B6 читает реестр из env staging-инстанса.
|
||
- **Стадия deploy:** деплоер `deploy_status: SUCCESS`, restart/rebuild **не требовался и НЕ делался** (изменения только в bind-mounted `scripts/`+`deployer.md`+доки, `src/` и Dockerfile не тронуты). Прод-контейнер 8500 НЕ тронут (zero group-risk для ET).
|
||
- **Финальный merge (сделала вручную):** орк сам смержил только логи (PR #47/#48), а сам фикс-код остался в feature-ветке (by design — фичу мержит владелец). Смержила **PR #45** (`2a36ed80`) feature→main.
|
||
- **Rollout:** `git pull` host-репо `/home/slin/repos/orchestrator` (владелец slin, sudo НЕ нужен — репо чистое) → HEAD `2a36ed8`. Проверено в живом bind-mount: `_evaluate_b6`=3, host-path хак=0, `deployer.md` docker exec=1.
|
||
- ✅ Plane ORCH-048 → Done; task38 → done; prod-8500 health=200, staging-8501 health=200.
|
||
- **УРОК:** орк закрывает задачу в done и мержит ТОЛЬКО логи (15-staging/14-deploy) — **сам фикс-код в main НЕ вливается автоматически**. Финальный merge feature-PR в main + host `git pull` — ручной шаг владельца. Проверять `git log origin/main..feature` ПЕРЕД тем как считать задачу закрытой.
|
||
|
||
## Состояние прод-гейтов/ядра после ORCH-48 (обновлено):
|
||
- ✅ check_ci_green — поллинг (ORCH-45)
|
||
- ✅ check_tests_passed — читает result: (ORCH-47)
|
||
- ✅ stage_engine — передаёт деву ТЕКСТ findings (ORCH-46)
|
||
- ✅ B6 staging-чек — читает реестр ВНУТРИ staging-контейнера, больше НЕ ложный FAIL (ORCH-48) → deploy-staging разблокирован для ВСЕХ ORCH-задач!
|
||
- Бэклог: ORCH-44 (надёжность запуска агента)
|
||
|
||
## ORCH-44 запущен конвейером (07:39 UTC) — надёжность запуска агента
|
||
- **Три проблемы** (инцидент ORCH-17 05.06, застряла ~30мин): П1 preflight слеп к auth (`claude --version` отвечает даже при Not logged in); П2 `--effort`+`--print`+json → пустой stdout; П3 пустой лог трактуется как успех/висит.
|
||
- **Разведка (сделала перед запуском):** `preflight.py` — только exists+`--version` (явный коммент «deliberately no prompt ping»). Бинарь `AgentLauncher.CLAUDE_BIN=/opt/claude-code/bin/claude.exe`. Реальные креды `/home/slin/.claude/.credentials.json` (`claudeAiOauth.expiresAt`). cmd сборка launcher.py стр.305-307 (`--print --output-format json {effort_flag}`), `_monitor_agent` стр.460 (ключ по exit_code, не по содержимому). queue claim-gating стр.154-164.
|
||
- **РЕШЕНИЕ СЛАВЫ:** П1 = ОБА (🅾): preflight упреждающе читает cred-файл (exists+читаемо+expiresAt в будущем) + `_monitor_agent` постфактум ловит 'Not logged in' → breaker+failed. П3 = делать (пустой лог/нет result-JSON → job failed, не вечный running). **П2 ВНЕ SCOPE** — effort НУЖЕН и работает, НЕ убирать как unsupported; хотфикс `ORCH_AGENT_EFFORT_*=\"\"` оставить, полный возврат → отдельная задача.
|
||
- **Создана ORCH-50** (Backlog, не автостарт): «Эффорт агентов: заставить --effort работать с --print/json» — разведка комбинаций флагов, вернуть effort в прод без потери result-JSON.
|
||
- **Запуск:** описание ORCH-44 дополнено блоком «РЕШЕНИЕ ВЛАДЕЛЬЦА» → In Progress (e331bfb3) → webhook `handle_status_start`→`start_pipeline`. **task 39 ORCH-044**, ветка `feature/ORCH-044-preflight-auth-effort`, analyst run 157.
|
||
- **Веду автономно** (как 46/48). Грабли на радаре: это правка КРИТИЧНОЙ launcher/preflight-логики — следить внимательно; staging B6 теперь должен пройти (ORCH-48). Финал: merge feature-PR (НЕ только логи! урок ORCH-48) + host git pull; если тронет `src/` → ребилд прода только с ОК Славы (общий ET+ORCH).
|
||
|
||
## Документация сессии 05.06 — финал (подтверждено)
|
||
- `docs/history/LESSONS_2026-06-05.md` в main орка через **PR #42** (`615a778d`), подтверждено `OK-IN-MAIN`.
|
||
- Внутри: постмортем ORCH-17/45/47, уловка-22 ORCH-47 (гейт чинит сам себя), памятка деплоя прода (`/app` запечён в образ → нужен `build`; порты 8500/8501; полная последовательность chown+reset+build+up+health+auth-check), грабли с root-owned файлами (рассинхрон git).
|
||
|
||
## ORCH-44 — диагностика застревания + CI-fix (07:39–08:30 UTC)
|
||
- **Запущена и заапрувлена от Славы** (проверила артефакты, поправила scope: P2/`--effort` исключён → вынесен в ORCH-50, оставлены P1 оба подхода + P3).
|
||
- **Застряла на `development`** — гейт `check_ci_green` не пропускал: CI в Gitea красный.
|
||
- **Сначала подумала на flaky-раннер** (локально 504 passed, CI падал за ~13с), ретриггернула empty-commit `92fc118` — упало снова → полезла в лог CI.
|
||
- **🐞 Корень — регрессия дева:** добавил в `preflight.py` auth-gate `_check_auth()` (читает `~/.claude/.credentials.json`, default ON — это фикс П1), но **не обновил существующий тест** `test_resilience.py::TestPreflight::test_ok_when_version_succeeds` (мокал только `claude --version`). У меня локально зелено (креды в контейнере есть), CI-раннер под slin без валидных кред → `ok=False` → `assert True` падает.
|
||
- **Нюанс репро (от дева):** `_credentials_path()` берёт `AgentLauncher.AGENT_HOME` (хардкод `/home/slin`), игнорит `HOME`-env. Faithful-репро: `ORCH_CLAUDE_CREDENTIALS_PATH=/tmp/nope.json`.
|
||
- **Передала Dev-агенту** (правка кода/тестов — не моя роль). Фикс: class-scoped `@pytest.fixture(autouse=True)` в `TestPreflight` мокает `preflight._check_auth → (True, ...)`. Прод-логику НЕ трогал, `preflight_check_auth=True` цел (фикс ORCH-17 не ослаблен). Коммит `6fbf7a3`, CI → **success** (runs 134/135 зелёные). Проверила независимо combined=success.
|
||
- **Гейт `check_ci_green` завязан на Gitea webhook о CI-status `success`** (`src/webhooks/gitea.py:201`). Webhook о новом зелёном не продвинул (раннер в другой сети / status-webhook не дошёл) → задача висела на development.
|
||
- **Пнула гейт штатным путём** (`temp/kick_ci_gate.py` — воспроизводит success-ветку webhook с guard'ами: задача найдена по repo+branch, нет активных job, `check_ci_green→True`): `development → review`, reviewer в очередь (job 100). НЕ хак БД — вызов штатных функций орка. `get_agent_for_stage("development")` → `reviewer` (агент = тот, кого запускают при выходе из стадии).
|
||
- **TODO при следующем заходе:** проверить, докуда уехал конвейер после reviewer (job 100) — review→testing→staging.
|
||
|
||
## ORCH-40 ПРИМЕНЁН К ПРОДУ (16:27 UTC) — uid 1000
|
||
- Конвейер прошёл (task 41, все агенты exit 0), код качественный (учёл все 3 мины из моего scope + сам нашёл 4-ю: ssh-маунт /root/.ssh -> /home/slin/.ssh).
|
||
- **Применение к проду (ручной шаг, как ORCH-42):**
|
||
1. `sudo chown -R 1000:1000 /home/slin/.claude` (пароль slin `motoZ@yaz2010` через `sudo -S`) — мина P-1 (creds были root:root 0600 -> uid 1000 не читал -> убило бы preflight). Теперь slin:slin, читаемо под 1000. ✅
|
||
2. merge PR #53 -> main (`39cb5dd`), `user:"1000:1000"` в main compose.
|
||
3. `git pull` + `docker compose up -d --no-build orchestrator` (compose подхватил user:1000:1000, образ НЕ пересобирался — менялся только compose, не код).
|
||
4. Проверки: uid=1000 ✅, health 200 ok ✅, preflight True (2.1.142) ✅, docker.sock present (gid 999 жив, для ORCH-36) ✅.
|
||
- Скрипт с авто-откатом: `temp/apply_orch40.sh` (откат = закомментить user: -> рестарт на root).
|
||
- **Эффект:** агенты пишут файлы как slin:slin, git pull при деплоях не сломается. Фундамент эпика ORCH-54.
|
||
- ⚠️ **Граблю на будущее:** при смене uid контейнера ОБЯЗАТЕЛЬНО сначала chown creds (`/home/slin/.claude`), иначе preflight (ORCH-044) завернёт весь конвейер.
|
||
|
||
## ORCH-50 — новая задача (effort) — Backlog
|
||
- По решению Славы: «effort нужен и работает, надо научиться с ним работать». Вынесен из ORCH-44 как отдельная задача-исследование (НЕ хоронить как unsupported). title_len 74.
|
||
|
||
## ORCH-51 — Автономный ребилд прода — Backlog (id `0db4942e-a7e0-4906-8290-f104b2774bc4`)
|
||
- Задача-проектирование (дизайн до кода). 8 вопросов: предикат is_safe_to_rebuild(), **race/потеря webhook при рестарте (кейс Славы — главный)**, парадокс само-ребилда (орк рестартит сам себя → внешний хук, связка ORCH-36), maintenance/drain, lock, post-rebuild health+авто-rollback (ORCH-21), уведомления, аварийный флаг `ORCH_AUTO_PROD_REBUILD`.
|
||
- **Идея Славы (06.06): blue-green HA — 2 инстанса за балансировщиком.** Дописала разделом «Стратегия деплоя A vs B»:
|
||
- A = single-instance + maintenance/drain + reconciliation-скан (проще, быстрее).
|
||
- B = blue-green HA (целевая, крупнее). Подводные камни: **SQLite не шарится → миграция на Postgres**, claim через row-lock (FOR UPDATE SKIP LOCKED), общий storage worktree, общий claude-auth, drain активных агентов (3-6 мин), leader-election для queue_worker (иначе двойной клейм).
|
||
- Рекомендация Стрим: A и B — этапы, не «или/или». B оформить отдельным крупным эпиком, зависящим от ORCH-51(A) и ORCH-36.
|
||
- Связи: ORCH-36/21/48/28/1b/40.
|
||
- ⚠️ Пока ORCH-51 не сделана — прод-ребилд под ORCH-44 (трогает src/) спрашивать у Славы вручную.
|
||
|
||
---
|
||
|
||
## ORCH-40 применён к проду (uid 1000) + регрессия → ORCH-43 запущена — 16:00-17:00 UTC
|
||
|
||
### Эпик ORCH-54 (автономное внедрение) — порядок: 40 → 43 → 36 → 53(∥) → 51 → approve-политика
|
||
|
||
### ORCH-40 (права, контейнер под host uid 1000) — ПРОВЕРЕНА + ПРИМЕНЕНА В ПРОД ✅
|
||
- **Проверка качества кода (PR #53):** агенты учли ВСЕ 3 мины из моего scope (+4-ю сами доразведали):
|
||
- `user: "1000:1000"` на prod+staging; `group_add: ["999"]` сохранён (МИНА 1 docker.sock=gid999)
|
||
- SSH-маунт перенесён `/root/.ssh` → `/home/slin/.ssh` (агент сам нашёл, я не указывала)
|
||
- ADR честно зафиксировал блокер P-1: `chown -R 1000:1000 /home/slin/.claude` ПЕРЕД рестартом
|
||
- тесты `test_orch040_compose.py`, ADR, INFRA.md на месте
|
||
- **Применение к проду (Слава дал «да», деструктивная прод-операция), порядок:**
|
||
1. chown creds: `.credentials.json` был `root:root 0600` → не читался под uid 1000 (МИНА P-1). `sudo -S` с паролем slin → `slin:slin`. (`.claude.json` и ssh-ключи уже были slin:slin)
|
||
2. merge PR #53 → main (`39cb5dd`), `user:"1000:1000"` в main compose
|
||
3. рестарт `docker compose up -d --no-build orchestrator` (код не менялся — только compose, образ не пересобирать)
|
||
4. проверки ВСЕ зелёные с 1-го захода: uid=1000, health 200 ok, preflight=True (claude 2.1.142 залогинен под 1000), docker.sock present
|
||
- **Скрипт с авто-откатом:** `temp/apply_orch40.sh` (откат = sed comment user: → recreate под root). Откат НЕ понадобился.
|
||
|
||
### 🔴 РЕГРЕССИЯ от ORCH-40 (поймана на первом запуске ORCH-43, починена вручную)
|
||
- Первый job под uid 1000 упал: `fatal: could not create leading directories ... /repos/_wt/.../.git: Permission denied`
|
||
- **Причина:** старые worktree-папки в `/repos/_wt/` остались `root:root` (созданы прежним root-контейнером) → uid 1000 не может создать папку рядом.
|
||
- **Пробел ORCH-40:** задача сменила compose, но НЕ нормализовала legacy root-файлы (ADR упоминал, deployer не сделал).
|
||
- **Fix (one-time cleanup, sudo):** `chown -R 1000:1000` на `/repos/_wt`, `.git`-объекты ОБОИХ репо (orchestrator + enduro-trails), `data/runs/*.log` (37 root-логов). Теперь 0 root-файлов везде. Удалила stale локальную ветку `feature/ORCH-043`.
|
||
- **TODO:** дописать legacy-чистку как follow-up к ORCH-40 в Plane (на чистой среде грабли повторятся). Слава спрошен — ждёт ответ.
|
||
|
||
### ⚠️ УРОК: миграция uid контейнера = нормализовать ВСЕ существующие файлы
|
||
- Смена `user:` в compose НЕ трогает уже созданные root-файлы в bind-mount. Любой git/worktree/data затык с Permission denied → chown -R на host под новый uid. Проверять `/repos/_wt`, `.git/objects`, `.git/worktrees`, `data/runs`.
|
||
|
||
### ORCH-43 (merge-gate feature→main) — ЗАПУЩЕНА в конвейер (task 42, analyst бежит после fix)
|
||
- **Разведка (важно для будущего):** сейчас deployer мержит в main ТОЛЬКО docs-артефакты (14-deploy-log, 15-staging-log) отдельным PR (`qg/checks.py:_deploy_log_from_main:431`). **Сам feature-код (src/) в main НЕ мержится автоматически** — я делала руками (PR #52, #53). check_deploy_status пишет «бумажный» SUCCESS.
|
||
- **Дыры:** (1) нет реального мержа кода фичи; (2) нет проверки свежести main vs точка ответвления → гонка при max_concurrency>1.
|
||
- **Scope ORCH-43:** реальный мерж feature→main + merge-gate (свежесть main, auto-rebase, re-test, откат на development при конфликте/красном). Файлы: `stage_engine.py`, `qg/checks.py`, `git_worktree.py`, `webhooks/gitea.py`. Скрипт запуска: `temp/launch_orch43.py`.
|
||
- Точка ответвления: `git worktree add -b branch wt origin/main` (`git_worktree.py:ensure_worktree`).
|
||
|
||
### Баги в бэклог (Слава просил)
|
||
- **ORCH-55** — Telegram bump не сработал (карточка ORCH-040 #17216 осталась вверху, регресс ORCH-42). Копать `notifications.py` — вероятно флаг bump в проде выключен. Код bump В ПРОДЕ ЕСТЬ (4 вхождения в `/app/src/notifications.py`), но не отрабатывает.
|
||
- **ORCH-56** — я (Стрим) узнаю о завершении задачи только на heartbeat (~30 мин), не в реал-тайм. Рекомендация: вариант B (орк пингует мою сессию sessions_send на done → реагирую сама без вопроса Славы). Скрипт: `temp/create_bugs.py`.
|
||
|
||
### Watchdog за конвейером (HEARTBEAT.md) — поставлен ранее этой сессии
|
||
- На каждом heartbeat: `docker exec orchestrator python3 /tmp/orch_watch.py` → активные ORCH (stage!=done) + очередь (queued/running) + последние failed/transient. State: `memory/heartbeat-state.json`.
|
||
- ⚠️ Ограничение: heartbeat = таймер, НЕ push. Между событием и докладом до 30 мин (это и есть баг ORCH-56).
|
||
|
||
### ORCH-43 (merge-gate feature→main) — В ПРОДЕ ✅ (18:42 UTC)
|
||
- Конвейер прошёл (task 42), регрессия прав починена (см. выше ORCH-57). Review APPROVED (0 блокеров), 535 тестов passed.
|
||
- **Код:** `src/merge_gate.py` (+340: branch_is_behind_main, auto_rebase_onto_main, retest_branch, file-lease), stage_engine +180, qg/checks +82 (check_branch_mergeable на deploy-staging→deploy edge), db/config/webhooks. +2689/-7, 29 файлов.
|
||
- **Мерж PR #54:** ⚠️ **ВАЖНО — Gitea merge auth:** хедер ДОЛЖЕН быть `Authorization: token <ORCH_GITEA_TOKEN>` (формат `token `, как в орке stage_engine.py:118). НЕ маскировать токен `***`-плейсхолдером — он подставляется буквально → 401! POST `/repos/admin/orchestrator/pulls/{N}/merge` body `{"Do":"merge"}`. Скрипт: `temp/merge_pr54.py`.
|
||
- **Деплой (ручной, rebuild+restart):** `git pull` → `docker compose build orchestrator` → `up -d` → health+preflight. Скрипт с авто-откатом: `temp/deploy_orch43.sh`. Проверки: merge_gate.py в контейнере yes, uid 1000, health ok, preflight True. main `c21a279`.
|
||
- **Эффект:** конвейер теперь САМ мержит feature→main (свежесть+rebase+re-test). Последний ручной мерж позади.
|
||
- ⚠️ **Ирония:** ORCH-43 чинит «код не вливается в main» — и сама в это упёрлась (deploy SUCCESS бумажный, мерж ручной). Это же — корень ORCH-36.
|
||
|
||
### ORCH-36 (исполняемый деплой) — РАЗВЕДКА + запуск
|
||
- **Корень:** стадия deploy СЕЙЧАС = бумажная. deployer-агент (`.openclaw/agents/deployer.md` — промпты агентов В РЕПО!) только пишет 14-deploy-log.md с deploy_status:SUCCESS. Реального build+restart+health НЕТ.
|
||
- **Маркер в коде:** deployer.md: «Real docker/SSH deploys are handled by `scripts/orchestrator-deploy-hook.sh` (ORCH-36)» — скрипта ЕЩЁ НЕТ.
|
||
- **🔴 ГЛАВНАЯ МИНА (self-hosting):** прод-контейнер orchestrator (8500) — ОДИН на ВСЕ проекты, и В НЁМ сам deployer бежит. НЕЛЬЗЯ `docker compose up -d orchestrator` из контейнера — убьёт себя. Решение: detached-хук на хосте (nohup/systemd-run/at через docker.sock gid 999 или ssh), рестарт ПОСЛЕ выхода агента.
|
||
- **Scope:** создать `scripts/orchestrator-deploy-hook.sh` (pull→build→up→health→auto-rollback), self-путь detached, deploy_status из реального исхода, для не-self — ssh DEPLOY_SSH_*. Скрипт запуска: `temp/launch_orch36.py`.
|
||
- **Промпты агентов (ВАЖНО!):** `.openclaw/agents/*.md` в репо (analyst/architect/developer/reviewer/tester/deployer) — версионируются, правятся конвейером.
|
||
|
||
### Прод-доступ (закрепить)
|
||
- `slin@82.22.50.71`, пароль `motoZ@yaz2010`, ConnectTimeout=15. Репо `/home/slin/repos/orchestrator`. docker через `sg docker -c`.
|
||
- Plane In Progress state id = `e331bfb3-e17e-4699-ba48-4abb89c21b7b` (flip туда = автозапуск конвейера через webhook). Проект ORCH id `8da6aa25-a60e-44d6-a1e2-d8ae59aa7d6a`.
|
||
- Health: `http://localhost:8500/health`, очередь+resilience: `http://localhost:8500/queue`.
|
||
- Gitea API: `http://localhost:3000/api/v1`, токен env `ORCH_GITEA_TOKEN`, repo `admin/orchestrator`. Merge PR: POST `/repos/admin/orchestrator/pulls/{N}/merge` body `{"Do":"merge"}`.
|
||
|
||
### 🏆 ORCH-36 (исполняемый деплой) + ORCH-53 (sweeper/reconciler) — ОБА В ПРОДЕ (21:24 UTC)
|
||
- **Вечерний марафон:** обе задачи прошли конвейер автономно (через рабочий merge-gate ORCH-43), Слава апрувил на гейтах. Эпик ORCH-54: **4 из 6 в проде**.
|
||
- **ORCH-53 (sweeper) — DONE с первого захода:** analyst→arch→dev→reviewer→tester→deployer, реворка НЕ было. Файл назван `src/reconciler.py` (НЕ sweeper.py!). PR #56 merged первым (чистый).
|
||
- **ORCH-36 (деплой) — через реворк (review отработал!):**
|
||
- 1-й заход developer упёрся в **таймаут 1800с (30 мин)** → SIGKILL (exit -9), система сама ушла в attempt 2 (resilience ORCH-1b), наработки в worktree сохранились → 2-й заход добил.
|
||
- reviewer завернул REQUEST_CHANGES (2 реальных P1: sentinel-маркеры self-deploy не чистятся на rollback; нет .env.example для новых флагов + процедуры approve в INFRA) → конвейер сам откатил dev→review→fix→APPROVED.
|
||
- Код: `src/self_deploy.py` (+338), `src/stage_engine.py` (+247), config.py, launcher.py, `scripts/orchestrator-deploy-hook.sh`, deployer.md. +2888/-8, 35 файлов. CI green, review APPROVED, tester PASS.
|
||
- **approve-механизм для прод-деплоя 8500 = Telegram-кнопка** (решение Славы), флаг `DEPLOY_REQUIRE_MANUAL_APPROVE=true` (дефолт).
|
||
- **🔴 BOOTSTRAP-ПАРАДОКС (важный урок):** ORCH-36 застряла в петле deploy→development. deployer на стадии deploy не писал `14-deploy-log.md` (старая логика в проде ≠ новая в ветке) → гейт check_deploy_status FAILED → откат. Self-репо НЕ может задеплоить сам себя через старую логику — нужен ручной разрыв цикла (мерж+деплой один раз, дальше катит своей же логикой). Как с ORCH-40/43.
|
||
- **🔴 MERGE-CONFLICT при ручном мерже (урок):** после мержа PR #56 main ушёл вперёд → PR #55 дал CONFLICT 409 (`.env.example`, CHANGELOG, README, INFRA, **src/config.py**). Разрулила НЕ rebase (9 коммитов = 9 конфликтов), а **merge main→ветку** (1 разбор). config.py-конфликт был чисто аддитивный: HEAD добавлял self_deploy-настройки, main — reconcile-настройки → нужны ОБА блока, склеить убрав маркеры. Скрипт разрешения на хосте. ⚠️ grep `=======` в docs/*/13-test-report.md = ЛОЖНОЕ срабатывание (markdown-разделители, не git-маркеры). PR #55 merged после rebase+CI green.
|
||
- **Деплой:** `temp/deploy_36_53.sh` (pull→build→up→health+preflight+проверка обоих файлов+reconciler в логах, авто-rollback). Откат не понадобился. self_deploy.py yes, reconciler.py yes, uid 1000, health ok, preflight True.
|
||
- **🔥 RECONCILER ДОКАЗАЛ СЕБЯ СРАЗУ:** в первую секунду после старта в логах: `reconciler: ORCH-036 development разблокирована (потерян webhook)` + `ET-013 development разблокирована`. Sweeper нашёл и разблокировал ДВЕ застрявшие задачи, включая саму ORCH-36 из bootstrap-петли. Ручной heartbeat-watchdog больше не нужен — система чинит себя сама.
|
||
|
||
### Уроки вечера (закрепить):
|
||
- **Заголовки ORCH-задач ≤80 символов** — иначе QG-0 (check title length) заворачивает старт. ORCH-53 был 83 → завернул, подрезала до 71.
|
||
- **Время хоста ≠ UTC:** файлы worktree датированы по мск (+3), БД/системное в UTC. Не баг, но путает сверки etime/updated_at.
|
||
- **Developer-таймаут 1800с** мал для мясных задач (деплой-хук+кнопка+callback). Если упрётся — поднять `agent_timeout_seconds` override или дробить на под-задачи. Пока спас resilience-ретрай (наработки в worktree не теряются между attempt).
|
||
- **Gitea merge auth:** `Authorization: token <ORCH_GITEA_TOKEN>` (буквально, НЕ маскировать `***` → 401). Скрипт: `temp/merge_both.py`.
|
||
|
||
### Эпик ORCH-54 — статус на конец 06.06:
|
||
```
|
||
✅ ORCH-40 — права (uid 1000) → прод
|
||
✅ ORCH-43 — merge-gate → прод
|
||
✅ ORCH-36 — исполняемый деплой → прод (Telegram-кнопка approve)
|
||
✅ ORCH-53 — sweeper/reconciler → прод (уже чинит зависания)
|
||
☐ ORCH-51 — окно/HA → бэклог (на свежую голову)
|
||
☐ обкатка автономного деплоя → следующая задача поедет через новый деплой сама
|
||
```
|
||
- **Что конвейер умеет САМ теперь:** мержит feature→main (merge-gate+rebase), реально катит в прод (build+restart+health), прод-деплор спросит Telegram-кнопку перед рестартом 8500, чинит застрявшие задачи (reconciler при потере webhook).
|
||
- **Последний ручной шаг — мой деплой — уходит.** Со следующей задачи конвейер катит сам.
|
||
- Слава: «Оставим concurrency=1, не рискуем» — НЕ поднимать max_concurrency (одна БД/очередь на все проекты, последовательно надёжнее).
|