Files
wiki/memory/2026-06-06.md
2026-06-07 00:40:01 +03:00

212 lines
38 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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:3908: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 (одна БД/очередь на все проекты, последовательно надёжнее).