# 2026-06-08 — Дневник ## 🎯 ORCH-66 (статусная модель) доехала до прода САМА — историческое - ORCH-66 = новая статусная модель (Plane-статусы: To Analyse / Analysis / Code-Review / Awaiting Deploy / Deploy / Done + In Review для approve-pending). - **Прошла весь конвейер автономно**: analyst→architect→dev→reviewer→tester→staging→Phase A. CI зелёный, merge-gate пройден, staging пересобран (`bc2347ab`). - Стояла на `In Review` = approval-pending прода, ждала **Confirm Deploy** Славы. Символично: статусная модель первой пошла в прод сама. ## 🟢 ORCH-67 заведена — Telegram tracker багфикс+enhancement (seq=67, id=34a8440d-4024-41fa-bf6e-398937e23dee) ТЗ загружено в Plane как HTML (5458 симв.). Зависит от ORCH-66 (статусные имена) → запускать ПОСЛЕ прода ORCH-66. 4 требования: 1. **Bump заработал** — причина бага найдена и НЕ в коде: bump-логика (`delete + send + repoint`) корректна, но в проде `tracker_mode = "edit"` (дефолт `config.py:345`). Env `ORCH_TRACKER_MODE=bump` не выставлен → режим edit (карточка остаётся вверху). Фикс: включить bump + сделать дефолтом. 2. **Формат карточки со статусами как в Plane** — показывать Plane-статус этапа. 3. **Номер задачи (ORCH-NN) — гиперссылка** на страницу задачи в Plane, внутри карточки. 4. **Во ВСЕХ уведомлениях орка** номер задачи тоже кликабельный → ведёт в Plane. - Уточнение Славы (учтено в ТЗ): **ожидание согласования BRD = Plane-статус `In Review`** (⏸️ approve-pending между Analysis и Architecture). Отразить как полноценный статус, не только строкой «⏸️ Подтверждение BRD ⏳». ## 🔧 Технические факты по notifications.py / tracker (для будущих задач) - `update_task_tracker(task_id)` — два режима через `Settings.tracker_mode` (env `ORCH_TRACKER_MODE`), case-insensitive; всё кроме `"bump"` → `"edit"`. Оба держат инвариант «одна карточка на задачу». - **edit (DEFAULT):** первый вызов sendMessage (silent) + store message_id; далее editMessageText. - **bump (ORCH-042):** delete старого → send нового внизу → repoint message_id. - **`parse_mode: HTML` уже включён** в send/edit → гиперссылки `` делаются без изменения транспорта. - `render_task_tracker(task_id)` — stateless рендер из БД: строка `✅ · ↓/↑ · · ` на этап + строка `✅/⏸️ Подтверждение BRD · твоё время[ ⏳]` между Analysis/Architecture. - `send_telegram(text, disable_notification)` → возвращает message_id; `delete_telegram(message_id)`; есть список Telegram-ошибок «target уже отсутствует» (message_id_invalid и т.п.). ## 🔗 URL/env факты (env орка) - `ORCH_GITEA_PUBLIC_URL=https://git.mva154.duckdns.org` - **НЕТ публичного Plane-URL в env орка** — для гиперссылок нужен базовый URL `https://plane.mva154.duckdns.org`. Заложено в ТЗ ORCH-67 как новый конфиг. - project_id: **ORCH = `8da6aa25-a60e-44d6-a1e2-d8ae59aa7d6a`**, Sandbox = `8c5a3025-4f9d-4190-b79f-fa06276bb27e`. - `ORCH_PLANE_WEBHOOK_SECRET=e7d95e…8b16`. ## 🐛 ORCH-68 root-cause: livelock reconciler = РЕГРЕССИЯ от ORCH-66 (Слава угадал) - Слава: «это началось после внедрения 66ой» — подтверждено логами минута-в-минуту: - `22:17:04.019` рестарт после прод-деплоя ORCH-66 → `Reconciler started (interval=120s)` - `22:17:04.207` (через 0.2с) первый `ET-002 done разблокирована` — ДО 22:17 этого лога не было ever. - `22:18:33` `Task 52: deploy->done (self)` (ORCH-66 задеплоил себя). Спам каждые 120с, 191+ сообщений. - Механизм: ORCH-66 ввела новую статусную модель (имена Done/Monitoring after Deploy). Reconciler сверяет локальную стадию↔Plane-статус; новые имена сломали сравнение терминальных → ET-002 (done/Done = синхронизирована) каждый тик считается «потерян webhook» → `_note_unblock` вхолостую (no-op, токены НЕ тратятся, но спам + нарушает инвариант «fires only on actual state change»). - Чинить в `src/reconciler.py`: маппинг терминальных/пост-деплойных статусов привести к новой модели; done+Done не должен триггерить unblock. - Root-cause-блок дописан в Plane ORCH-68 (seq=68, id=70fd4d24-4241-4dd5-9245-11e629a3fc60), HTML 3603→5419. - ⚠️ Грабли: чуть не дописала root-cause в ЧУЖУЮ задачу seq=60 «Reconciler не должен трогать escalated» (тоже про reconciler) — поймала, откатила (вернула 549 симв.). **Plane seq≠work_item_id; искать issue по полному списку и сверять название, не по ключевому слову.** - ⚠️ Plane API: ручной urllib через двойной SSH+docker молчит/не отдаёт JSON. Рабочий путь — использовать модули орка `src/plane_sync.py` (`PLANE_BASE`, `WORKSPACE`, `PLANE_HEADERS`, httpx) внутри контейнера через файл-скрипт + `docker cp`. PATCH `description_html` работает (200). ## 🚀 ORCH-68 ЗАПУЩЕНА в работу (04:45 UTC) + архитектурный ответ - Слава: «68 срочно запускай. Правильно ли ориентироваться на статус Plane?» - **Ответ: ДА, ориентир на Plane корректен по дизайну.** Таблица `tasks` не имеет status-колонки (reconciler.py:201 «live Plane state is the source of truth»). F-2 обязан опрашивать Plane и реплеить пропущенные вебхуки — это сердце автономности. - **Баг — в МАППИНГЕ, не в идее:** `_reconcile_plane_project` тянет `list_issues_by_state(pid, [to_analyse, approved, rejected])`. ET-002 в Plane=`Done` — её не должно быть в выборке. На **enduro** `get_project_states` схлопывает статусы (reconciler.py:209-211) → `Done` алиасится под `approved` UUID → ветка «Approved but stage never advanced → replay verdict» → `_note_unblock` каждый тик. - **Ключевая находка:** у проекта **orchestrator** `Done`=group=`completed`, `Approved`=group=`started` (разные UUID, НЕ склеены). На enduro — склеены. ⚠️ Правильный фикс: использовать **`state.group == "completed"`** для терминала, а не голый UUID-маппинг. Заложено в ТЗ. - **Старт:** Plane-статус ORCH-68 → `To Analyse` (UUID `8acc6109-934e-4cd5-954b-7495672f520c`) = триггер конвейера. - **QG-0 завернул первый раз:** заголовок >80 симв. → задача ушла в `Blocked`. Укоротила до 60 симв («BUG: reconciler livelock — спам unblock done-задачи (ET-002)») → Backlog → To Analyse → пошла. **Урок: заголовок Plane-задачи для орка — <=80 символов (QG-0 hard check).** - **Сейчас:** task 53, ORCH-068, stage=analysis; **job 378 analyst running** (pid 3332), ветка `feature/ORCH-068-bug-reconciler-livelock-unbloc`. Аналитик получил полное ТЗ + root-cause + архитектурное уточнение. - ТЗ ORCH-68 в Plane: 5428→7007 симв (добавлен архитектурный блок). ## ✅ ORCH-68 BRD Approved (04:52 UTC) → analysis→architecture (архитектор run_id=347) - Аналитик выдал 4 артефакта (BRD/ТЗ/AC/test-plan) в `docs/work-items/ORCH-068/`. Проверила все — эталонная работа. - **Аналитик углубил мой root-cause:** разделил баг на 2 независимых дефекта: **D1** (терминалы не исключены из actionable-выборки) + **D2** (`_note_unblock` зовётся безусловно после no-op dispatch, нарушает свой docstring). D2 — мина, которую я пропустила. - **Захватил связанный баг кэша:** `_STATES_CACHE` живёт весь lifetime, `reload_project_states()` есть но не вызывается — именно из-за этого Слава рестартил орк после создания `Confirm Deploy`. Поймали заодно (G5/AC-12, secondary). - Plane-статусы переходов: To Analyse → Analysis (`cb834d55`) → In Review (`c52e99b9`, approve-pending BRD) → Approved (`63f2c8fe`) → Architecture (`795cc32f`). UUID approved для ORCH = `63f2c8fe-dcda-4ace-952f-dd88bd0118ff`. - Решение «state.group vs allowlist» правильно оставлено архитектору в ADR. ## 🟢 ORCH-69 заведена и запущена (05:09 UTC) — QG-0 title-лимит в параметр - Решение Славы: «заведи задачу, сделаем как параметр, 200 по умолчанию». - **Предыстория:** выяснили что 80 в QG-0 — НЕ техническое ограничение. Проверила все места ниже по течению: slug ветки `re.sub(...)[:30]` (webhooks/plane.py:488) режется независимо + выкидывает кириллицу ([^a-z0-9]→дефис); БД `title TEXT` без лимита; Telegram-карточка `html.escape(title)` без обрезки; worktree-путь по branch (=work_item_id+slug[:30]), не по title. Расширять безопасно. - **ORCH-69** (seq=69, id=35338a57-d905-4958-b70c-fa1afd66110f): новый `ORCH_QG0_TITLE_MAX` (дефолт 200) в config.py, `_qg0_errors` читает из settings, текст ошибки динамичный. Нижние лимиты (title<5, desc<20) НЕ трогать. Аддитивно/обратносовместимо (200>80). - Запущена: stage=analysis, ветка `feature/ORCH-069-qg-0-title-orch-qg0-title-max-`. ⚠️ Обе (68 и 69) трогают `webhooks/plane.py` — следить за merge-конфликтом (merge-gate должен поймать, но держать в голове). ## 🎉 ORCH-68 В ПРОДЕ — орк сам себя починил (05:32 UTC, self-deploy) - ORCH-68 прошла весь конвейер автономно и задеплоилась в прод. Статус → Done (`3738cd3c`), post-deploy monitor HEALTHY. - ✅ **Спам ET-002 = 0** после деплоя (было 191+). Фикс боевой. - ✅ Код в проде: `_is_terminal_state`, `get_project_state_groups`, `skipped_terminal_total` — D1 через `state.group` (ровно как хотели). ## 🔴 БАГ ORCH-70: `Confirm Deploy` НЕ триггерит Phase B (мёртвый триггер, регрессия ORCH-66) - **Инцидент:** Слава нажал статус `Confirm Deploy` для прод-деплоя ORCH-68 → орк `no pipeline action`. Деплой пошёл только после ручного перевода в `Approved`. - **Root cause:** диспетчер `handle_issue_status` (webhooks/plane.py ~158-166) слушает ТОЛЬКО `to_analyse/approved/rejected`. Phase B (stage_engine.py ~215-224) триггерится по `Approved`. `Confirm Deploy` (008597eb) не в тройке → молчит. ORCH-66 добавила статус как **метку (запись)**, но не подключила **обратный путь (чтение/триггер)**. - **Почему не поймали:** (1) не в scope ORCH-68 (она чинит reconciler, явно N1-N3 «Phase B не трогать»); (2) дыра ORCH-66 — тесты проверяли ЗАПИСЬ статуса, не ОБРАТНЫЙ триггер; (3) staging не покрывает прод-путь — ручной `Confirm Deploy` живёт только на проде (Phase A staging автоматический). - **Урок:** тестировать ОБРАТНЫЙ путь статусов (нажатие → действие), не только запись. Новый статус = подключить в обе стороны. Прод-only пути нуждаются в явном тесте. - **Записано в репу орка:** `docs/history/LESSONS_2026-06-08_confirm-deploy-deadtrigger.md` (коммит main, sha 101bd1c5, через Gitea Contents API). - **ORCH-70** заведена (seq=70, id=bfbc924f-b808-4f7b-87d4-88ac5e976240), Backlog. Цель: `Confirm Deploy` триггерит Phase B + регресс-тест обратного пути. Не запущена — ждёт решения Славы по очереди. - **Gitea для коммитов в репу орка:** `ORCH_GITEA_URL=http://localhost:3000`, owner=`admin`, repo=`orchestrator`, token `ORCH_GITEA_TOKEN` (env контейнера). Contents API: GET→sha→PUT/POST base64. ## 🚨 КРИТ: ФАНТОМНЫЙ MERGE — прод расходится с main, 4 PR не слиты (08.06) - **Симптом:** ORCH-67 в To Analyse не подхватился. Причина — прод слушает `in_progress` (старый диспетчер), а не `to_analyse` (ORCH-66). - **Диагноз (подтверждён md5 + git + PR-статус):** PR#67(022)/68(059)/69(066)/70(068) — ВСЕ **open, merged=False**. Последний реально слитый — PR#66 (ORCH-065, bb03350). - **md5-сверка:** прод reconciler.py/plane_sync.py == ветка ORCH-068 (≠ main). Прод = снимок ветки ORCH-068, НЕ main. - **Механизм (Слава угадал — «деплоилась старая версия»):** ветка ORCH-068 срезана от `bb03350` (ORCH-065), А НЕ от кода ORCH-066. В истории ветки-068 по ORCH-066 только `docs staging`, не код (`to_analyse`=0 в ветке-068). Т.е. деплой 068 взял worktree от устаревшего main (065) + фикс reconciler → откатил статусную модель 66 из прода. - **Таймлайн ET-002:** 22:17 деплой ветки-066 (сломанный reconciler) → спам начался. 05:32 деплой ветки-068 (фикс livelock, но база 065 без 66) → спам=0 после 05:33. Подтверждает: код 66 БЫЛ в проде 22:17-05:32, потом стёрт деплоем 068. - **КОРЕНЬ:** self-deploy Phase B собирает образ из ВЕТКИ (срезанной от main) + рапортует finalize SUCCESS, НО git-merge в main не отрабатывает (фантом). → следующая задача срезается от устаревшего main → теряет код незалитых предшественников. Накопительная потеря 022→059→066→068. - **Подозрение:** регресс фикса ORCH-065 (idempotent merge / merge-lease) ЛИБО merge-step после него молчит. ORCH-065 — последний честный merge. - **Ребейз origin/feature/ORCH-066-plane на origin/main — ЧИСТЫЙ** (конфликтов нет, git разрулил reconciler.py/plane_sync.py — разные места). НО простое слияние 66 затрёт фикс 68 → нужна цепочка 022→059→066→068. - **РЕШЕНИЕ Славы: «запускай сама, документируй, запиши урок»** — выполняю. ## 🔧 ВОССТАНОВЛЕНИЕ main (08.06, автономно) - **Находка по ходу:** ORCH-059 = `feat(deploy): Confirm Deploy status triggers prod deploy` — **уже реализует то, что я заводила как ORCH-70!** `handle_confirm_deploy` написан в 059, просто не слит (фантом). → ORCH-70 после долива 059 пересмотреть (останется только display-слой Monitoring after Deploy). - **Матрица src-пересечений:** 022(config/qg/security_gate/stage_engine), 059(plane_sync/stage_engine/webhooks), 066(plane_sync/reconciler/stage_engine/webhooks), 068(config/plane_sync/reconciler). Порядок цепочки 022→059→066→068 (= хронология PR 67<68<69<70). - **Интеграционная ветка** `integ/restore-main-2026-06-08` (worktree `/tmp/integ_chain` в контейнере): 022+059+066 слиты чисто (docs union). На 068 — код-конфликт reconciler.py (066 to_analyse vs 068 in_progress+D1/D2). Разрешение: каркас 068 + триггер to_analyse 066. - **Урок в репу:** `docs/history/LESSONS_2026-06-08_phantom-merge.md` (sha 772ccab, CRITICAL постмортем + runbook диагностики). - **Критбаг ORCH-71** (seq=71, id=017daf29) — root-fix фантома: верификация merge после деплоя + done-гейт по PR.merged + merge до рестарта контейнера. Backlog. - **Диагностический runbook (4 проверки фантома):** (a) Gitea PR merged-флаги, (b) md5 prod vs `git show origin/main:`, (c) merge-base ветки vs main, (d) таймлайн деплой-логов. - ⚠️ **БЛОКЕР:** Dev-агент (vibecode/claude-sonnet-4.6) упал на billing error (кредиты исчерпаны, 0 токенов). Конфликт reconciler.py НЕ разрешён. ТЗ готово: `/tmp/DEV_TASK_merge_066_068.md`. Нужен перезапуск Dev на другой модели. ## 🔍 АУДИТ статусной модели ORCH-66 (08.06) — 7 статусов-призраков - В Plane заведен **21 статус**, код (`_PLANE_NAME_TO_KEY`, plane_sync.py ~119) знает только **14**. Не подключены: Analysis, Code-Review, Awaiting Deploy, Confirm Deploy, Deploying, Monitoring after Deploy (+ To Analyse через отдельный alias). - **Мёртвый код:** `set_issue_awaiting_deploy/deploying/monitoring` ОПРЕДЕЛЕНЫ (plane_sync.py ~652-679) но НИГДЕ не вызываются (grep пуст). - `_STAGE_TO_STATE_KEY` ставит СТАРЫЕ статусы: analysis→in_progress (не Analysis), review→review (не Code-Review), deploy→in_progress (не Awaiting Deploy). - `Monitoring after Deploy` (97b4a6cf) создан, но post-deploy окно идёт ПОВЕРХ Done (stage_engine.py:356 «arm monitor PAST done») → задача показывает Done, хотя ~15мин под наблюдением (это и есть «почему Done» Славы). - **Вывод:** ORCH-66 ввела красивую модель на доске, но деплойная под-модель (Awaiting Deploy→Confirm Deploy→Deploying→Monitoring) — декоративная, код её не использует. - **ORCH-70 расширена** (3725→7027): с одного Confirm Deploy до всей деплойной под-модели (G4-G7): подключить статусы, заполнить name→key, привести stage→state, убрать/задействовать мёртвый код. Порядок actionable vs display-only — архитектору в ADR. ## ⚠️ QG-0 — правила заголовка/описания Plane-задач для орка (важно!) - **QG-0** = первый quality gate конвейера, функция `_qg0_errors(name, description)` в `src/webhooks/plane.py:366`. Проверяет **заголовок (name) и описание** до старта аналитика. - Три проверки: **Title ≥ 5**, **Title ≤ 80** (хардкод, без конфига), **Description ≥ 20** символов (`.strip()`). `len()` по Unicode-символам (кириллица = 1 символ, не байт). - **soft vs hard:** при `work_item.created` — soft (только warning, стр.362). При старте конвейера (`Status->In Progress`) — **hard** (стр.435-457): блокирует и кидает в `Blocked`. Вот почему создаётся ок, а при запуске заворачивает. - 🔑 **ПРАВИЛО: заголовок Plane-задачи для орка — короткий тайтл ≤ 80 символов, вся детализация — в description.** Не впихивать описание в заголовок (моя привычка — забываю). Дважды наступила 08.06 (ORCH-67/68). - ⚡ Возможный QoL-фикс (предложила Славе, ждёт решения): авто-обрезка заголовка до 80 («…») вместо блокировки, или вынести лимит 80 в конфиг. ## 📝 Грабли инструмента edit (зафиксировать) - `edit` требует строго: `path` + `edits` (массив), каждый элемент только `{oldText, newText}` — никаких лишних полей. `oldText` должен совпадать дословно (включая пробелы/переводы строк). Несколько фейлов за сессию из-за неверной формы аргументов и неточного oldText. - `image` (vibecode/claude-sonnet-4.6) падает с **403 Insufficient credits** — генерация картинок недоступна. ## Файлы, тронутые в сессии - `tasks/orchestrator/STATUS_MODEL_DEEP_ANALYSIS.md`, `STATUS_MODEL_PROPOSAL.md`, `status_workflow.html` - `/tmp/wi_tracker_desc.md` (ТЗ ORCH-67), `/tmp/wi1_desc.md` - `temp/DEV_TASK_ORCH-022_test_fix.md` ## 🔴 ТИХАЯ ПОТЕРЯ 059 при merge цепочки (08.06, поймала на верификации) - Dev #1 (vibecode/sonnet-4.6) упал на billing. Перезапуск #2 (tokenator/sonnet-4-6) — за 5 мин САМ разрешил конфликт reconciler.py: HEAD `dac81e0`, маркеров 0, технически верно (to_analyse=7, set_issue_monitoring=1, _is_terminal_state=2, get_project_state_groups=2, _stage_changed=4, триггер старта=to_analyse ✅). - 🔴 **НО верификация вскрыла дыру:** `handle_confirm_deploy` (ORCH-059) = **0 во всём дереве** (было 3 в ветке 059). **Тихая потеря без конфликта.** - **Механизм:** 066 срезан от базы БЕЗ 059 (059=3, 066=0 по `webhooks/plane.py`). При merge 066 поверх 059 git взял `webhooks/plane.py` целиком из 066 → затёр Confirm Deploy. **Git не предупредил** (не конфликт, а fast clobber разных баз). - **Урок (важнейший):** при сборке цепочки веток из РАЗНЫХ баз merge-без-конфликта ≠ корректно. Файлы-пересечения (`webhooks/plane.py`, `stage_engine.py`, `plane_sync.py`) надо верифицировать ПОМАРКЕРНО каждой фичи (022∧059∧066∧068 одновременно), а не доверять «git смержил чисто». Тихая потеря опаснее конфликта. - **Решение Славы: перезапустить Dev на Opus 4.8 1M (tokenator).** Запущен с ТЗ + крит.дополнением: итог должен содержать ВСЕ 4 фичи разом, ручное сращивание webhooks/plane.py (059 confirm + 066 статусы вместе). Таймаут 40 мин. HEAD sonnet-а (dac81e0) НЕ доверять — пересобрать/доверифицировать. - ТЗ обновлено: `/tmp/DEV_TASK_merge_066_068.md` (+ требование про 059 confirm_deploy и помаркерную верификацию пересечений). - **Маркеры верификации финала (чек-лист):** 022→`security`/secret-scan в qg; 059→`handle_confirm_deploy`/`confirm_deploy` (≥3); 066→`to_analyse`/`set_issue_monitoring`; 068→`_is_terminal_state`/`get_project_state_groups`/`_stage_changed`. ВСЕ >0 одновременно + pytest зелёный. ## ✅ ВОССТАНОВЛЕНИЕ main ГОТОВО (Opus 4.8 1M) — ждёт Confirm Славы - Opus пересобрал `integ/restore-main-2026-06-08` начисто от origin/main, порядок 022→059→066→068, ручное сращивание пересечений. HEAD `c90c01b`. Сломанная версия sonnet сохранена `backup/integ-dac81e0-2026-06-08`. - **Моя независимая проверка (не верю отчёту):** 8/8 маркеров ✅ (059 handle_confirm_deploy=3, 066 to_analyse, 068 _is_terminal_state/_stage_changed, 022 security_gate), 0 конфликт-маркеров, **pytest 832 passed 0 failed** (воспроизвела сама). - **Ключевое подтверждение механизма фантома:** когда 059 встал в ветку ДО 066, git выдал РЕАЛЬНЫЕ конфликт-маркеры в webhooks/plane.py + plane_sync.py (вместо тихого whole-file overwrite). Т.е. правильный порядок = защита от тихой потери. Вариант 1 (correct ordering) подтверждён. - Сращено вручную: webhooks/plane.py (to_analyse+confirm_deploy оба), plane_sync.py (Confirm Deploy + 6 ключей 066 + alias fallback), reconciler.py (каркас 068 + триггер to_analyse 066), фикстуры тестов (059/068 предшествовали rename 066 → добавлен to_analyse, не подгонка под зелёный). - **СЛЕДУЮЩИЙ ШАГ:** Confirm Славы → push ветки + merge в main + передеплой. main пока НЕ тронут, прод НЕ тронут. ## ✅ ВОССТАНОВЛЕНИЕ main ГОТОВО (08.06, Opus 4.8 1M) — ждёт Confirm на push/merge - Dev #3 (tokenator/opus-4.8-1m) пересобрал цепочку чисто. HEAD `c90c01b`, сломанная версия sonnet-а (`dac81e0`/`4fde685`) в бэкапе. - **Моя независимая верификация (НЕ отчёт агента):** - 8/8 маркеров — 4 фичи сосуществуют: 022 security ✅ · 059 `handle_confirm_deploy`=3/`confirm_deploy`=9 ✅ · 066 `to_analyse`/`set_issue_monitoring` ✅ · 068 `_is_terminal_state`/`get_project_state_groups`/`_stage_changed` ✅ - 0 конфликт-маркеров - **pytest: 832 passed, 0 failed** (прогнала сама, воспроизвелось) - **Промежуточный красный (14 failed/818) был ОЖИДАЕМ:** когда Opus вернул 059, всплыли реальные стыки фич — он их довёл в цикле pytest. Финал зелёный. - 🔑 **Механизм фантома доказан практически:** при постановке 059 ДО 066 git выдал НАСТОЯЩИЕ конфликт-маркеры в `webhooks/plane.py` (вместо тихого затирания у sonnet-а). **Правильный порядок веток = защита от тихой потери.** Усиливает урок. - **Диффы:** strictly additive +1350/−67 в src. `webhooks/plane.py`: to_analyse+handle_confirm_deploy оба живут; `reconciler.py`: каркас livelock 068 + триггер to_analyse 066; `plane_sync.py`: Confirm Deploy + 6 статус-ключей 066 + alias fallback. Фикстуры тестов поправлены под реальный контракт (обосновано, не подгонка). - **Урок про модели:** sonnet-4-6 рапортовал «816 passed» на НЕПОЛНОЙ версии (без 059) — отчёт был «правдив» по своему дереву, но дерево было неверным. **НЕ доверять отчётам агентов о тестах — гнать pytest самой и сверять маркеры всех фич.** Opus справился с ювелирной 4-way склейкой, sonnet — нет. - ⏸️ **БЛОКЕР = ожидание Славы:** main и прод НЕ тронуты, всё в изолированном worktree `/tmp/integ_chain`, ветка `integ/restore-main-2026-06-08`. Жду Confirm на: push → merge в main → передеплой прода. БЕЗ его ОК ничего не пушу (правило ручного approve прода, INV-1). ## 🎉 ВОССТАНОВЛЕНИЕ main + ПРОД ЗАВЕРШЕНО (08.06, путь A штатный, под контролем Славы) - **Confirm Славы получен** на каждый шаг отдельно (полный контроль). Путь A = штатный механизм орка, не самодельный. - **PR #71** integ/restore-main → main: merged=True, merge_sha `4946123`. Первый честный merge после ORCH-065 — фантом разорван. - **Шаг 1:** хост-репо /home/slin/repos/orchestrator `48b5405`→`4946123` (был позади на 42 коммита). Откат-точка 48b5405. - **Шаг 2:** `--build-staging` GIT_SHA=4946123 → staging-образ пересобран (rev=4946123), health OK, staging_check PASS (exit 0). Прод НЕ тронут. ⚠️ Ключевое: staging/prod были на промежуточном `6bbd530` (НЕ main) — без пересборки ретегнулся бы старый код (provenance guard на main НЕактивен, не поймал бы). Пересборка обязательна. - **Шаг 3 (прод):** `--deploy` build-once retag staging(4946123)→prod, health OK 2-я попытка (~7с downtime), exit 0. prev-image сохранён для отката. Активных jobs было 0 — никого не оборвал. - **Шаг 4 verify-after-deploy:** prod-образ rev=`4946123` ✅, health ok ✅, ВСЕ 4 фичи в живом проде (022 security_gate, 059 handle_confirm_deploy=3/confirm_deploy=7, 066 to_analyse=7+set_issue_monitoring, 068 _is_terminal_state=2/get_project_state_groups=2) ✅, диспетчер слушает `to_analyse` (webhooks/plane.py:164) → **ORCH-67 теперь стартует** ✅. - **ET-002 спам:** 1 разовый всплеск на первом тике reconciler (07:38:14, до прогрева кэша), за полный цикл 130с НЕ повторился (=1) → livelock-фикс 068 работает, спама нет. - **ИТОГ:** main = прод = `4946123`, все 4 потерянные задачи восстановлены, фантом разорван, прод здоров. Осталось: ORCH-71 (root-fix фантома, чтобы не повторялось) — в Backlog, запускать штатно. ## 🧹 ЧИСТКА + ЗАПУСК ORCH-71 (08.06, после восстановления) - **Закрыты 6 хвостовых open PR** как superseded (комментарий + state=closed, БЕЗ merge): #50(044), #64(061) — дубль-ветки, код уже в main; #67-70(022/059/066/068) — восстановлены через #71. **Open PR теперь = 0.** Gitea-доска чистая. - **ORCH-71 ЗАПУЩЕНА в конвейер** (07:56 UTC): Backlog → To Analyse → **Task 55, analyst job 416, run_id=353, pid=349**, ветка `feature/ORCH-071-crit-bug-merge-main`, .task.md=3532b. Заголовок 53 симв (QG-0 ок), desc 3638. - 🎯 **БОЕВАЯ ПРОВЕРКА восстановления пройдена:** прод подхватил задачу по НОВОМУ статусу `to_analyse` (диспетчер webhooks/plane.py:164), конвейер стартовал штатно. То, что ломал фантом (прод слушал старый in_progress) — теперь работает. ORCH-67 тоже сможет стартовать. - ORCH-71 — root-fix фантома: verify-merge-after-deploy + done-гейт по PR.merged + merge до рестарта. Идёт автономно, ждёт BRD-approve Славы на стадии In Review. ## ✅ ORCH-71 BRD APPROVED (08:07 UTC) → architecture (run_id=354, pid=531) - Проверила артефакты аналитика — **эталон.** Аналитик УГЛУБИЛ root cause код-аудитом: для self-hosting путь deploy СТРУКТУРНО не содержит merge-в-main (merge делает только LLM-агент deployer, который на self-hosting НЕ запускается), done достигается по одному deploy_status:SUCCESS без верификации main. - BRD: G1-G4 + INV-1..5 (merge только PR-API/никогда force-push, идемпотентность через pr_already_merged ORCH-065, never-raise, self-hosting safety, ручной approve сохранён). - ТЗ: карта 7 модулей (stage_engine/merge_gate/self_deploy/qg/checks/config/deployer.md), FR-1..5, zero БД-миграций, restart-safe через sentinel/jobs, self vs non-self разделены. HOW отдан архитектору (ADR). - AC: 11 критериев с PASS/FAIL — not-merged→alert(AC-1), done-гейт по PR.merged mock(AC-2), restart-докатка(AC-3), регресс self+non-self(AC-4/4b), never-raise(AC-7), идемпотентность(AC-9), kill-switch(AC-10), approve сохранён(AC-11), staging-воспроизведение(AC-6). - **Approved → architect стартовал** (job 417, run_id=354). Идёт автономно. Следующий гейт Славы — после architecture (ADR-ревью) либо позже. ## ⚠️ ЛОЖНЫЙ алерт 08:19 + QA-замечание ORCH-71 - В Telegram прилетел «🚨 deploy succeeded but not merged: ORCH-036 (branch=feature/ORCH-036-x)». Слава: «Что это?» - **Разбор:** НЕ инцидент. dev-агент ORCH-71 написал alert-код (stage_engine.py~1334, merge_gate.py~521) + тесты с mock-фикстурой branch=feature/ORCH-036-x/wi=ORCH-036. Прогон pytest дёрнул НЕзамоканную alert-функцию → реальный Telegram-вызов улетел Славе. - Доказано: реальная ORCH-036=done (ветка feature/ORCH-036-orch-36-deploy-b), feature/ORCH-036-x НЕ существует, прод-оркестратор алерт НЕ слал (нет в его логах после 07:59), код ORCH-71 ещё не в проде. - **Добавила QA-замечание в Plane ORCH-71** (коммент): во всех тестах alert/notify → мокать send_telegram/sendMessage; AC-критерий «pytest НЕ шлёт реальных Telegram-сообщений, 0 вызовов к api.telegram.org»; reviewer заворачивает незамоканный notify (REQUEST_CHANGES). - **Урок:** автономный конвейер, тестирующий notify-функции, может спамить живые каналы из pytest, если notify не замокан. Закладывать мок notify в AC любой задачи с alert/Telegram. ## ✅ ORCH-71 ЗАВЕРШЕНА — root-fix фантома в проде (09:17 UTC) - Конвейер ORCH-71 прошёл analysis→architecture→dev→review(APPROVED, 0 блокеров)→test(853 passed, TC-01..16/AC-1..11)→staging(SUCCESS). - **Моё QA-замечание учтено:** conftest.py autouse-фикстура глушит send_telegram во ВСЕХ тестах → 0 реальных Telegram из pytest (структурно). Проверила лично. - **Слив + деплой (вручную, чистый путь):** PR#72 merged в main (merge_sha 52ca882). Хост-репо→52ca882. staging пересобран из 52ca882 (PASS). Прод-деплой: build-once retag → prod rev=52ca882, health OK. - **prod == main == 52ca882**, merge-verify в живом проде (merge_pr/verify_merged_to_main/_handle_merge_verify×3), merge_verify_enabled=True. - 🎯 **БОЕВАЯ самопроверка:** `verify_merged_to_main(orchestrator, ORCH-71-branch, sha)` = True — новый гейт подтверждает merge ORCH-71 в main. Фича проверяет сама себя. - ⚠️ **Provenance guard (ORCH-058) сработал штатно:** конвейерный Phase B задачи упёрся в SOURCE_IMAGE 52ca882 != expected d49e88c (fail-closed, exit 1), т.к. ручной merge+deploy опередил авто-Phase B → образы разошлись → guard заблокировал повторный деплой уже задеплоенного. Прод НЕ пострадал. Задача FAILED→Blocked в конвейере, но по факту код в проде. - **Закрыла Done вручную** (manual close, вариант A) + пояснит. коммент в Plane. БД орка: stage→done. active jobs=0, прод здоров, ET-002 спам=1 (только старт, не растёт). - **УРОК:** ручной merge+deploy ПЕРЕД конвейерным Confirm Deploy ломает provenance guard (expected revision = HEAD ветки на момент staging-валидации ≠ ручной merge-commit). Чистый авто-путь: дать задаче пройти свой Phase B самой ИЛИ сбросить deploy-state перед ручным деплоем. На будущее: либо полностью ручной путь + manual Done, либо полностью конвейерный — не смешивать. ## 🧹 Гигиена + 🚀 ORCH-67 запущена (09:46 UTC) — КРУГ ЗАМКНУТ - **Гигиена:** 0 открытых PR (фантомов не накопилось), PR#72 merged, deploy-state ORCH-071 самоочистился (finalizer прибрал при FAILED). Мусора нет. ORCH-71 stage=done, 0 jobs, reconciler не дёргает. - **ORCH-67 СТАРТОВАЛА** — та самая задача, что НЕ подхватывалась из-за фантома (прод слушал in_progress, не to_analyse). Теперь: To Analyse → Analysis → analyst job 425, run_id=361, pid=497, ветка feature/ORCH-067-telegram-tracker-bump-plane, .task.md=5174b. - **ТЗ ORCH-67 актуально:** написано уже под новую модель ORCH-066 (To Analyse→...→Done маппинг). 4 требования: (1) bump из коробки, (2) карточка показывает Plane-статусы новой модели + ⏸️ ожидания (In Review/Awaiting Deploy/Needs Input), (3) кликабельный work_item_id → Plane-ссылка (ORCH_PLANE_WEB_URL, fail-safe), (4) кликабельные номера во всех уведомлениях. - 🎯 **ДОКАЗАНО В ДЕЙСТВИИ:** фантом ломал именно подхват ORCH-67 — теперь конвейер берёт её мгновенно. Восстановление статусной модели работает боем. - Идёт автономно. Следующий гейт Славы — BRD-approve на стадии In Review. ## ✅ ORCH-67 BRD APPROVED (09:53 UTC) → architecture (run_id=362) - Проверила BRD(13к)/ТЗ(15к)/AC(9к) — эталон. 4 требования владельца разложены точно, маппинг под модель ORCH-066 (которую вернули в прод), fail-safe прошит насквозь. - ТЗ: config.py:408 tracker_mode edit→bump; хелперы plane_status_label + plane_issue_link (переиспользуют _build_plane_issue_link ORCH-017); карта точек send_telegram во всех модулях; схема БД/QG/транспорт не трогаются. Скользкое место (статусы веток без stage: Needs Input/Blocked/Deploying) корректно [ARCH] с safe-дефолтом; In Review из brd-clock БЕЗ сети. - AC: 18 критериев PASS/FAIL — bump(A1-4), статусы+In Review-без-сети+never-crash(B5-9), кликабельный номер+fail-safe(C10-11), хелпер+все точки+html.escape(D12-14), нерегресс транспорт/enduro/тесты/доки(E15-18). AC-14 тест HTML-поломки на title с /&. - Approved → architect (job 426, run_id=362). Идёт автономно. ## 🎉 ORCH-67 В ПРОДЕ — ORCH-71 merge-verify СРАБОТАЛ БОЕМ (10:52 UTC) - Слава дал Confirm Deploy. На этот раз НЕ вмешивалась руками (урок ORCH-71) — дала конвейеру отработать. - **merge-verify (код ORCH-71) сработал автоматически:** лог `Task 56: merge-verify merge_pr -> ok=True (already-merged)` → `merge-verify CONFIRMED -> deploy->done allowed` → `deploy → done`. - Т.е. орк САМ слил PR ORCH-67 в main + САМ верифицировал merge + САМ разрешил done. Фантом физически невозможен теперь. - Полный путь: Confirm Deploy → Phase B → merge+verify → done → Monitoring after Deploy → post-deploy monitor HEALTHY (tick 1,2 health=200 5xx=0). - **Bump-режим ORCH-67 уже работает:** в логах deleteMessage→sendMessage (старая карточка вниз). - ИТОГ: ORCH-67 (Telegram tracker bump+статусы+кликабельные номера) в проде. Исходная проблема «ORCH-67 не подхватывается» закрыта ПОЛНОСТЬЮ. Цикл само-исцеления орка замкнут: фантом → восстановление main → root-fix ORCH-71 → боевая проверка на ORCH-67 успешна. - **КОНТРАСТ:** ORCH-71 я деплоила вручную (провенанс-гард ругнулся, manual Done). ORCH-67 — полностью автоматом через новый merge-verify. Разница = именно то, что ORCH-71 и чинила. ## 🐛 БАГ ORCH-72 заведён + урок (статус-строка карточки врёт) - Слава заметил: карточка ORCH-69 показывала «📍 To Analyse» при пройденных всех стадиях. - **Root cause:** ORCH-67 `_STAGE_STATUS_LABEL` (src/notifications.py) НЕ покрывает стадию `deploy-staging` (и возможно др.) → падает в `_DEFAULT_STATUS_LABEL="To Analyse"` (худший фолбэк = первый статус). ORCH-69 был на deploy-staging. - **ORCH-72** (seq=72, id=e722a596) в Backlog: дополнить карту ВСЕМИ стадиями из stage_engine, фолбэк нейтральный (не To Analyse), deploy-staging→осмысленный лейбл. Косметика, не функционал. - **УРОК (ревью-чеклист):** при stage-зависимом маппинге — покрывать ВСЕ стадии из единого источника (STAGE_TRANSITIONS), фолбэк нейтральный. Моё ревью ORCH-067 это пропустило — карту стадий надо сверять поимённо, не «на глаз». Аналитик/архитектор взяли «основные» стадии, забыли служебные (deploy-staging). ## 🕐 Московское время — план (делать ПОСЛЕ финала ORCH-69, по просьбе Славы) - **Цель Славы: один часовой пояс ВЕЗДЕ = Europe/Moscow.** Разнобой сейчас: хост mva154=MSK✅, контейнер орка=UTC❌, Стрим=UTC❌. (Часы хоста НЕ ушли — ORCH-64 неактуален, NTP active.) - **План:** (1) контейнер орка → `TZ=Europe/Moscow` в docker-compose (логи/карточки/уведомления→MSK), требует рестарт контейнера ~7с; (2) Стрим → перейти на MSK в общении со Славой. - **Когда:** Слава просил сделать ПОСЛЕ того как ORCH-69 добежит до финала (чтобы рестарт никого не прервал). Дождаться done ORCH-69 → поставить TZ. ## 🐛 ORCH-72 РАСШИРЕН — 3 дефекта карточки (Слава выловил 2 и 3) - **Дефект 1:** статус-строка «To Analyse» на непокрытых стадиях (deploy-staging) — исходный. - **Дефект 2 (Слава):** карточка НЕ отражает откаты. При rollback merge-gate deploy-staging→development (ORCH-43, конфликт CHANGELOG) верхние ✅ (Код-ревью/Тест/Внедрение) не снимаются, внизу снова 🔄 Разработка. Абсурд «Внедрение ✅ + Разработка 🔄». - **Дефект 3 (Слава, ДЕНЬГИ):** стоимость/токены повторных попыток НЕ суммируются. Карточка берёт последний agent_run на стадию. ORCH-69 developer×3: run370=$3.05, run372=$0.26, run376=$0.68 = РЕАЛЬНО $3.98, карточка показала ~$0. Тотал занижен на ~$3.3. Нужно SUM(agent_runs) по (task,stage), не последний. - ORCH-72 desc обновлён: +G4(откаты)/G5(сумма попыток) +AC-6/AC-7. Это уже НЕ косметика — искажение учёта денег. - **Контекст:** ORCH-69 откатилась deploy-staging→development 3 раза из-за конфликта CHANGELOG.md (наши деплои 71/67 сегодня трогали CHANGELOG → ветка разошлась). Штатное самолечение merge-gate, но дорого (3× разработка). ## 💡 УРОК (Слава просил записать): CHANGELOG.md = частый источник дорогих merge-конфликтов - **Наблюдение:** ORCH-69 откатилась deploy-staging→development 3 раза (merge-gate, конфликт CHANGELOG.md). Причина — несколько задач в один день (ORCH-71, 67, 69) добавляют записи в один и тот же файл CHANGELOG.md → ветки расходятся → rebase-конфликт на merge-gate → откат на разработку. - **Цена:** каждый откат = повторный запуск developer. ORCH-69 разработка 3× = $3.98 вместо ~$1. Конфликты CHANGELOG прямо жгут деньги. - **Системная проблема (кандидат в задачу):** при параллельных задачах CHANGELOG.md — гарантированная точка конфликта (все пишут в `## [Unreleased]`). Варианты решения для будущей задачи орка: 1. auto-rebase merge-gate должен УМЕТЬ разрешать CHANGELOG-конфликты автоматически (union-merge для append-only секции Unreleased), а не откатывать на development. 2. ЛИБО: не писать CHANGELOG в feature-ветке, а генерировать запись при merge в main (post-merge hook). 3. ЛИБО: .gitattributes merge=union для CHANGELOG.md (git сам сливает обе вставки). - Вариант 3 (`.gitattributes merge=union`) — самый дешёвый и точечный фикс. Рекомендую завести задачу, если откаты по CHANGELOG повторятся. - **Связь:** этот же CHANGELOG-конфликт — причина, по которой ORCH-71 я сливала вручную, а auto-rebase ORCH-69 трижды откатывал. Системная, повторяющаяся боль. ## ⤷ ORCH-72 уточнение (Слава): суммировать ВСЕ метрики при повторных попытках - Дефект 3 не только про деньги: при повторах стадии занижаются $ И токены И время. Все 3 суммировать по всем agent_runs стадии. - Время = Σ(finished-started) по попыткам; токены = Σ(in/out + cache); $ = Σ cost_usd. Тоталы задачи = суммы по всем стадиям/попыткам, сходятся с SUM по agent_runs для task_id. (AC-8 добавлен.) ## ✅ ORCH-69 в проде + МОСКОВСКОЕ ВРЕМЯ ВЕЗДЕ (08.06, ~14:46 MSK) - **ORCH-69** (QG-0 title-лимит→ORCH_QG0_TITLE_MAX=200) задеплоена: review APPROVED, test PASS, staging SUCCESS, security 0/0. Откатывалась 3× из-за CHANGELOG-конфликта, потом dev ребейзнул, up-to-date with main. Confirm Deploy → merge-verify (already-merged) CONFIRMED → done. Прод-образ de70ee81. - **merge-verify (ORCH-71) сработал боем 2-й раз подряд** (после ORCH-67) — полностью автоматом, без ручного вмешательства. - 🕐 **МОСКВА ВЕЗДЕ:** добавила `TZ=Europe/Moscow` в docker-compose.yml в ОБЕ секции (prod стр.28 + staging стр.69), бэкап `docker-compose.yml.bak-tz-*`, `docker compose config` валиден. Recreate prod через `up -d --no-build` (образ НЕ пересобран, de70ee81 цел, health ok). Контейнер: `date = MSK` ✅, TZ=Europe/Moscow. Теперь хост MSK + контейнер MSK = единый пояс. Логи/карточки/уведомления орка → московское время. - **Я (Стрим) тоже перехожу на MSK** в общении со Славой. - ORCH-64 (часы ушли) — НЕАКТУАЛЕН (часы хоста ок, был просто рассинхрон UTC контейнера vs MSK хоста, теперь устранён). ## ✅ ВОССТАНОВЛЕНИЕ ORCH-67+69 + ССЫЛКИ + TZ-фикс (08.06 ~15:09 MSK) - **Слава: «ссылок нет на таску».** Аудит вскрыл: код ORCH-67 (tracker bump/статусы/ссылки) И ORCH-69 (qg0_title_max) ОТСУТСТВУЮТ в main — только их docs-коммиты. Обе фантомы от CHANGELOG-ребейзов. Системная эрозия main. - **A (восстановление):** интеграция 67+69 поверх main в worktree /tmp/integ6769. CHANGELOG-конфликт всплыл вживую на merge 69 → union. Все фичи целы (plane_issue_link, num_html заголовок, qg0_title_max, verify_merged_to_main). pytest 917 passed. PR#76 merged в main (sha 05bd169). Деплой: staging→prod SUCCESS. - ✅ **ССЫЛКА РАБОТАЕТ:** карточка заголовок = `