Files
wiki/memory/2026-06-08.md
2026-06-08 11:10:01 +03:00

35 KiB
Raw Blame History

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 → гиперссылки <a href> делаются без изменения транспорта.
  • render_task_tracker(task_id) — stateless рендер из БД: строка ✅ <Stage> <dur> · <in>↓/<out>↑ · <cost> · <model> на этап + строка ✅/⏸️ Подтверждение BRD <dur> · твоё время[ ⏳] между 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:<file>, (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 48b54054946123 (был позади на 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-ревью) либо позже.