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

121 KiB
Raw Permalink Blame History

2026-06-05

Orchestrator — CI-гейт качества закрыт (продолжение self-hosting ORCH-7)

Главный итог

CI у orchestrator теперь честно зелёный. Дефект изоляции тестов (тесты протекали друг в друга через синглтон settings) закрыт. Гейт качества для self-hosting работает по-настоящему.

Что было сделано

  • PR #27 (ветка fix/isolate-webhook-tests-from-plane) — три коммита:
    • 7bbab9c — изоляция 3 webhook-тестов от живого Plane API (моки через ИСТОЧНИК src.plane_sync.*)
    • e856e09 — миграция test_plane_webhook_generates_sequential_ids под новый контракт (задача создаётся при переходе В In Progress, а не на work_item.created)
    • 1baae81autouse-фикстура в tests/conftest.py, сбрасывает webhook-секрет (+ db_path) на синглтоне settings перед каждым тестом
  • Проверено лично на проде: полный pytest tests/ в чистом docker-окружении = 294 passed, 0 failed (было 10 failed). CI run 547/548 = success (впервые).
  • 401/HMAC/dedup тесты ЖИВЫ — фикстура их не сломала (они перекрывают её своим monkeypatch). Off-limits зона не тронута: правки только в tests/conftest.py и tests/test_webhooks.py, src/ чист.

Ключевой урок — интерференция тестов через синглтон settings

  • Settings (Pydantic, src/config.py) читает env ОДИН раз при создании объекта settings.
  • test_webhooks.py ставит секрет жёстко os.environ["..."]="" на import-time; другие файлы — через setdefault; test_webhook_dedup.py ставит реальный "s3cr3t" через monkeypatch.
  • В ПОЛНОМ прогоне pytest tests/ секрет протекал между файлами → HMAC включался → webhook-тесты ловили assert 401 == 200. По отдельности файл зелёный, вместе — красный.
  • Решение-паттерн: autouse-фикстура в conftest, сброс протекающего состояния синглтона через monkeypatch перед каждым тестом. НЕ менять сам механизм/защищённые тесты — только навести порядок с изоляцией. db_path тоже протекал (get_task_by_repo_branch возвращал stale) — Dev законно добавил и его сброс.

Мерж ВЫПОЛНЕН (05.06, Слава дал «да»)

  • PR #27 → MERGED в main (HTTP 200). main HEAD = d0a3424 Merge PR #27. Все 3 коммита фиксов в истории main.
  • PR #26 → CLOSED без мержа (поглощён #27).
  • Нюанс: CI на самом main после merge-commit отдельным прогоном не появился (workflow триггерится на push/PR-ветки; merge-commit мог не дёрнуть). Код в main = ровно то, что прогонялось зелёным (294 passed). Гейт на будущих PR работает.
  • Пункт №1 self-hosting (CI-гейт) ЗАКРЫТ. Осталось: удалить отработанные ветки fix/isolate, ci/add (косметика).

Staging-среда для orchestrator (ORCH-30..35) — дизайн оформлен, задачи в Backlog

Решения (гибрид C)

  • Агенты на staging: ПО ДЕФОЛТУ заглушки (быстро/дёшево/детерминированно — гейт проверяет работоспособность ОРКа, не качество LLM) + режим full-real по флагу (настоящий Claude CLI через claude-cli-proxy).
  • Plane/Gitea на staging — настоящие, но в песочнице (ORCH-SANDBOX проект + orchestrator-sandbox репо).
  • DEPLOY_REQUIRE_MANUAL_APPROVE=true на старте — хук тормозит после зелёного staging, ждёт «go» Славы.
  • Деплоем рулит ВНЕШНИЙ хост-хук, не сам контейнер орка (орк не может убить свой процесс на середине деплоя; rollback через PREV_IMG, образец enduro-deploy-hook.sh).
  • Задачи только в Backlog — конвейер стартует ТОЛЬКО при переходе В In Progress (Feature 1). Backlog безопасен.

Задачи (все Backlog, project ORCH id 8da6aa25-a60e-44d6-a1e2-d8ae59aa7d6a)

  • ORCH-31 id=5a68a13c-3f3b-4d9e-91f7-24b0794bed06 — staging-инфра: контейнер orchestrator-staging (порт 8501), изолированная БД через ORCH_DB_PATH/volume ./data/staging, профиль compose staging
  • ORCH-32 id=3dadcf0d-f1b6-4302-8075-8d428ace01f6 — песочница: Plane ORCH-SANDBOX + Gitea orchestrator-sandbox, реестр через env ORCH_PROJECTS_JSON (код не трогать)
  • ORCH-33 id=a11a7c0f-a78a-4309-9aa5-1c43d4355d0f — тест-сьют (smoke + доступы + e2e), режим full-real
  • ORCH-34 id=47fe9e75-d7ff-4ecb-bb99-67af9b23ab67 — хост-деплой-хук orchestrator-deploy-hook.sh (build candidate→staging-гейт→promote→health 10×6с→auto-rollback), пересекается с ORCH-21
  • ORCH-35 id=4ead9be7-e1bf-4a28-8c76-88bda1c1fc2c — стадия deploy-staging перед deploy-prod

Разведка инфры (факты для точных ТЗ)

  • compose: один service orchestrator, network_mode: host, порт 8500 в команде uvicorn (uvicorn src.main:app --host 0.0.0.0 --port 8500). Staging → просто другой порт 8501 + профиль staging.
  • ORCH_DB_PATH УЖЕ параметризован (config.py:43 дефолт /app/data/orchestrator.db) → изоляция БД через него + отдельный volume ./data/staging.
  • Реестр проектов через env ORCH_PROJECTS_JSON (JSON-массив) → sandbox добавляется в .env.staging, код менять не надо.
  • В Plane sandbox-проекта ещё НЕТ (есть ag_proj, First, ET, ORCH). В Gitea sandbox-репо ещё НЕТ (enduro-trails, openclaw-vault, orchestrator, wiki). Заведу сама через API при выкате Этапа 2.
  • ТЗ готово: tasks/orchestrator/DEV_TASK_ORCH31_STAGING_INFRA.md. Запускать Dev на ORCH-31 ТОЛЬКО когда репо свободно (не толкать двух Dev на один git одновременно).

Грабли/правила (подтверждены этой сессией)

  • Файлы памяти: durable → ТОЛЬКО memory/YYYY-MM-DD.md (append). Сегодня 2026-06-05.md.
  • Dev: код/тесты/конфиги → ТОЛЬКО в Gitea-репо orchestrator через PR. Push в main запрещён (pre-receive hook). Dev НЕ мержит — мержит ревьюер (Стрим/Слава).
  • Инфра вне репо (.env.staging реальный, Plane/Gitea sandbox-сущности, хост-деплой-хук, поднятие контейнера) — делаю я через installer/API, НЕ Dev через PR. В репо только .env.staging.example.
  • ⚠️ Dev: НЕ регистрировать раннеров, НЕ nohup. Раннер mva154-runner-orch уже есть.
  • ⚠️ Off-limits без согласования: HMAC-механизм, 9 HMAC/401 тестов, src/config.py settings, check_reviewer_verdict, check_deploy_status, merge-gate gitea.py, PLANE_STATES, set_issue_done, launcher, queue, stages.py mapping, _parse_tests_verdict, check_tests_local (только DEPRECATED, не удалять).
  • ⚠️ Грабля push: после push git log origin/main..origin/<branch> ДОЛЖЕН показать коммит ДО отчёта «PR готов».
  • ⚠️ Plane API: дёргать через base64-stdin+docker cp в контейнер orchestrator. URL http://localhost:8091 БЕЗ /api/v1 (суффикс добавляет код!), заголовок X-API-Key, токен ORCH_PLANE_API_TOKEN. Без /api/v1 Plane вернёт HTML(200) вместо JSON.
  • Прогон тестов в чистом окружении (как CI): docker run --rm -v /home/slin/repos/orchestrator:/code:ro -w /code -e PYTHONPATH=/code --entrypoint python3 $(docker inspect orchestrator --format '{{.Config.Image}}') -m pytest tests/ -q
  • Эндпоинт Actions: GET /api/v1/repos/admin/orchestrator/actions/tasks, токен docker exec orchestrator printenv ORCH_GITEA_TOKEN.
  • Сервер: slin@82.22.50.71 (sshpass, pw motoZ@yaz2010), репо /home/slin/repos/orchestrator, контейнер orchestrator порт 8500, Gitea https://git.mva154.duckdns.org.
  • Модель Dev: tokenator/claude-sonnet-4-6 (vibecode кредиты кончились; альт tokenator/claude-opus-4-8).
  • ElevenLabs TTS квота кончилась → отвечать ТЕКСТОМ.

Уборка раннеров (TODO, ждёт ОК Славы)

3 процесса act-runner: systemd act-runner.service (рабочий, mva154-runner), PID 3828601 (старый mva154-runner с 19.05), PID 4091018 (mva154-runner-orch через nohup — НЕ переживёт reboot). План: systemd-unit вместо nohup, прибить лишние. Принести Славе на ОК.

Следующие шаги

  1. [ждёт кивка] Мерж PR #27 в main, закрыть #26 → CI-гейт (пункт self-hosting) закрыт.
  2. Запустить Dev на ORCH-31 (staging-инфра) когда репо свободно.
  3. Этап 2 (ORCH-32): завести ORCH-SANDBOX в Plane + orchestrator-sandbox в Gitea при выкате.
  4. Уборка раннеров (план Славе на ОК).

Продолжение сессии (флаш #2)

PR #27 СМЕРЖЕН в main / #26 закрыт

  • PR #27 merged (HTTP 200), main HEAD = d0a3424 "Merge PR #27". Все три коммита фиксов в истории main (изоляция Plane + seq-тест + изоляция секрета).
  • PR #26 закрыт без мержа (поглощён #27). Подтверждено API: #27 state=closed merged=True; #26 state=closed merged=False.
  • CI-гейт качества orchestrator закрыт по-настоящему → главный блокер self-hosting (ORCH-7) снят.
  • Грабля по экранированию: при мерже через Gitea API двойной SSH-эскейп кавычек поехал → передавала скрипт через base64 (echo b64 | base64 -d | bash). Рабочий приём для сложных команд через sshpass.
  • ⚠️ Косметика-TODO: удалить отработанные ветки fix/isolate-webhook-tests-from-plane и ci/add-gitea-workflow (обе merged/closed).

Этап 1 (ORCH-31) — staging-инфра ГОТОВА, PR #28 (ждёт мержа на момент флаша)

  • Dev отработал, ветка feature/ORCH-31-staging-infra, PR #28 open, mergeable.
  • 4 файла, прод-блок compose НЕ тронут (diff чистый: @@ -25,3 +25,39 @@ — чистое добавление в конце, прод-строки 1-25 без изменений).
  • Проверено на проде лично: обычный docker compose config показывает ТОЛЬКО orchestrator; staging виден ЛИШЬ с --profile staging → случайно не поднимется. Контейнера orchestrator-staging на проде нет (крутится только прод, Up 15h). БД изолирована через volume ./data/staging (на хосте ещё не создан — создастся при первом запуске).
  • ⚠️ Нюанс: docker compose config --profile staging без реального .env.staging не выводит детали порта 8501 — это норма, реальная валидация при выкате с настоящим .env.staging (Этап 2).
  • Развилка (ждёт ОК Славы): мержить #28 сейчас (чистый инфра-код в main, ничего не запускается — staging «спящий чертёж») ИЛИ ждать. Я ЗА мерж сейчас (вариант 1) — main маленькими безопасными кусками.
  • На хосте куча orchestrator.db.bak-deploy* — бэкапы прод-БД от прошлых деплоев 03-04.06, НЕ наша история, не трогать.

Объяснила Славе что проверяют 294 теста (для контекста)

Группы тестов orchestrator (страховочная сетка перед самодеплоем): гейт качества (41), Telegram-трекер (28), resilience/переживание рестарта (26), usage+queue (23+19), движок этапов конвейера (22), запуск агентов через Claude CLI (18), webhooks Plane/Gitea + дедуп + подпись (16+9+8), маршрутизация проектов после инцидента 02.06 (16), git-worktree изоляция веток (9), мелочёвка (task.md, комменты, ротация логов, вердикты). Тесты НЕ вшиты в docker-образ — только в репо (правильно).

Время

Сессия идёт глубокой ночью UTC (~04:40-04:50), у Славы утро ~07:40 UTC+3. Несколько раз предлагала паузу — Слава продолжает работать.

Следующий шаг (на момент флаша)

Жду ОК Славы: мержить PR #28 → идти на Этап 2 (ORCH-32: песочница Plane ORCH-SANDBOX + Gitea orchestrator-sandbox + реальный .env.staging + поднятие staging-контейнера через installer).


Продолжение (флаш #3) — STAGING-СТЕНД ПОДНЯТ 🚀

PR #28 смержен → Этапы 1+2 выкачены, staging живой на проде

  • PR #28 merged (main HEAD 3b68a29). ⚠️ Грабля: при мерже через Gitea API заголовок Authorization сглючил → token is required (HTTP 401); фикс — AUTH = "token " + TOK отдельной переменной, не инлайнить. Со второго раза HTTP 200.
  • Этап 2 (ORCH-32) песочница создана: Gitea-репо admin/orchestrator-sandbox (auto-init main) + Plane-проект "ORCH Sandbox" (identifier SANDBOX, id 8c5a3025-4f9d-4190-b79f-fa06276bb27e). Имя в Plane БЕЗ дефиса — Plane не пускает спецсимволы в name (ошибка "Project name cannot contain special characters").
  • Токены — вариант 1 (Слава подтвердил): общие с продом, изоляция по проекту/репо.
  • .env.staging собран (скрипт из прод-.env + staging-оверрайды), бэкап прод-.env сделан (.env.bak-before-staging-*), в .gitignore (IGNORED ok), прод .env цел (23 строки).

Изоляция staging (КЛЮЧЕВОЕ — проверено лично, всё зелёное)

  • Реестр ORCH_PROJECTS_JSON = ТОЛЬКО sandboxknown_plane_project_ids() = {8c5a3025...}, боевые ORCH(8da6aa25)/ET(7a79f0a9) = False → события по ним фильтр ORCH-6 режет в ignored. Staging физически не реагирует на боевые задачи.
  • БД физически раздельная: volume ./data/stagingdata/staging/orchestrator.db (32KB свежая). Прод-БД не трогает.
  • Telegram пустой (Слава: вариант 1, staging молчит) — ORCH_TELEGRAM_CHAT_ID="" и BOT_TOKEN="". Не спамит боевой канал.
  • ORCH_STAGING=true пометка.
  • Подъём: sg docker -c "docker compose --profile staging up -d --build orchestrator-staging".

Проверки выката (все )

  • staging 8501 /health=ok, /queue=ok (queued/running/done/failed=0, preflight_ok, Claude Code 2.1.142).
  • прод 8500 /health=ok, контейнер Up 16h БЕЗ рестарта (не дёрнулся).
  • реестр: sandbox=True, боевой ORCH=False, боевой ET=False.

Важные технические факты (для след. этапов)

  • Gitea-webhook прод-репо orchestrator жёстко шлёт на http://localhost:8500/webhook/gitea. Sandbox-репо orchestrator-sandbox пока БЕЗ хуков (настрою на 8501 в Этапе 3 при e2e).
  • Plane-webhooks через workspace API = 404 (Plane настраивает их через UI/инстанс plane-app-*, не через API). Прод получает Plane-события webhook'ом на 8500. Staging боевые Plane-события НЕ получит, пока ему отдельно не настроят webhook → плюс к безопасности.
  • Орк роутеры: /webhook/plane, /webhook/gitea (main.py:92-93, prefix /webhook).
  • 8500=прод (uvicorn pid живой), 8501=staging.
  • ORCH_REPOS_DIR в .env=/home/slin/repos, но compose env-секция перебивает на /repos → внутри контейнера /repos (правильно).
  • Образ staging: orchestrator-orchestrator-staging:latest, контейнер orchestrator-staging.

Следующий шаг

Этап 3 (ORCH-33): тест-сьют staging — smoke + проверка доступов (Plane sandbox + Gitea sandbox реальными вызовами) + e2e (задача в SANDBOX → ветка в orchestrator-sandbox → статусы+комменты в Plane, верификация по API), режим full-real. Перед e2e: настроить Gitea-webhook sandbox-репо на localhost:8501. Это код для Dev (тест-скрипт) + моя инфра (webhook).


Staging-среда orchestrator — Этапы 2-3 ВЫКАЧЕНЫ (05.06, утро)

Этап 1 (ORCH-31) — закрыт

  • PR #28 смержен в main, main HEAD 3b68a29 "Merge PR #28", коммит ORCH-31 6c1e5ff в main.
  • ⚠️ Грабля мержа: заголовок авторизации Gitea при первом заходе пришёл как *** (санитайзер) → HTTP 401 token is required. Фикс: явно token <tok> → HTTP 200 merged. Запомнить: при мерже через Gitea API проверять, что заголовок реально token <значение>, а не затёртый.

Этап 2 (ORCH-32) — песочница создана + staging-контейнер ПОДНЯТ

  • Gitea-репо песочницы: admin/orchestrator-sandbox (main, auto-init).
  • Plane-проект песочницы: name "ORCH Sandbox" (Plane НЕ пускает дефис/спецсимволы в name → без дефиса), identifier SANDBOX, project_id 8c5a3025-4f9d-4190-b79f-fa06276bb27e.
  • Токены — вариант 1 (решение Славы): общие с продом, изоляция по проекту/репо + раздельная БД (НЕ отдельные токены).
  • Telegram staging — вариант 1 (решение Славы): пустой/выключенный, staging молчит в телегу (смотрим по логам/API). Никакого спама в боевой канал.
  • .env.staging собран на проде (/home/slin/repos/orchestrator/.env.staging, в .gitignore, НЕ коммитится): реестр ORCH_PROJECTS_JSON = ТОЛЬКО sandbox (боевые ET/ORCH → ignored фильтром ORCH-6), Telegram пустой, БД через volume, ORCH_STAGING=true. Прод .env (23 строки) цел, бэкап сделан.
  • Контейнер orchestrator-staging поднят на 8501 (docker compose --profile staging up -d), образ orchestrator-orchestrator-staging:latest. Проверено лично: /health=ok, /queue=ok (Claude Code 2.1.142 виден), прод orchestrator Up 16h БЕЗ рестарта.
  • Изоляция подтверждена: staging знает ТОЛЬКО sandbox (known_plane_project_ids()={8c5a3025...}); боевые ORCH(8da6aa25)/ET(7a79f0a9) → False; БД физически раздельная data/staging/orchestrator.db.

Webhook-изоляция (важная находка)

  • Gitea webhook прод-репо orchestrator шлёт жёстко на localhost:8500/webhook/gitea (прод). Sandbox-репо пока БЕЗ хуков (правильно).
  • Plane webhooks через workspace API недоступны (404) — настраиваются на уровне Plane-инстанса/UI (plane-app-* контейнеры). Прод-Plane шлёт на 8500. Staging боевые Plane-события НЕ получит, пока webhook в Plane не настроен на 8501.
  • Главный ключ изоляции: ORCH_PROJECTS_JSON staging = только sandbox → даже если событие прилетит, всё не-sandbox → ignored (фильтр ORCH-6).

Этап 3 (ORCH-33) — тест-сьют ГОТОВ, PR #29 (ждёт мержа)

  • Dev написал scripts/staging_check.py (smoke A + доступы B + e2e C, exit-code, cleanup в finally) + docs/STAGING_CHECK.md. Ветка feature/ORCH-33-staging-testsuite. PR #29 open.
  • Проверено лично на проде: 10/10 PASS, exit 0. Файлы только новые (src/tests/compose/.env не тронуты). Боевое НЕ задето (нет staging-check веток в orchestrator/enduro-trails, нет тест-задач в боевом ORCH). Песочница чиста после cleanup (sandbox-репо = только main, Plane SANDBOX = 0 задач). Прод 8500 жив.
  • Ключевое архитектурное знание (порядок старта конвейера): при старте сначала resolve проекта → подтяг name/desc из Plane → QG-0 валидация → создаётся work_item_id + ветка + начальные доки + строка задачи в БД → ТОЛЬКО ПОТОМ enqueue аналитика (Claude CLI через launcher). Значит e2e проверяет РАННИЕ артефакты (ветка/доки) ДО запуска LLM — быстро, без расхода кредитов. Аналитика не ждём.
  • Режима заглушек агентов (гибрид C) в коде НЕТ — но для e2e он и не нужен (проверяем раннюю стадию до LLM).

Открытый нюанс (не блокер)

  • Bot-токены агентов (ORCH_PLANE_BOT_ANALYST и пр.) НЕ добавлены членами в SANDBOX-проект → add_comment от их имени = 403. Dev заменил проверку «коммент в Plane» на надёжный ранний артефакт «analyst job в очереди». Чтобы закрыть полностью — добавить бот-аккаунты в SANDBOX через Plane API (моя инфра-работа, мелкая).

Следующие шаги

  1. Мерж PR #29 (Этап 3) — предложено + добавить ботов в SANDBOX.
  2. Этап 4 (ORCH-34): хост-деплой-хук orchestrator-deploy-hook.sh (промоут staging→prod, health 10×6с=60с, auto-rollback PREV_IMG). Образец /home/slin/bin/enduro-deploy-hook.sh.
  3. Этап 5 (ORCH-35): стадия deploy-staging перед deploy-prod в конвейере.

Идентификаторы (Этап 2-3)

  • Plane SANDBOX project_id: 8c5a3025-4f9d-4190-b79f-fa06276bb27e, identifier SANDBOX
  • Gitea sandbox-репо: admin/orchestrator-sandbox
  • staging порт 8501, контейнер orchestrator-staging, профиль compose staging, образ orchestrator-orchestrator-staging:latest, БД data/staging/orchestrator.db, .env.staging (в .gitignore)
  • main HEAD после Этапа 1: 3b68a29; PR #28 merged, PR #29 open (Этап 3)
  • ТЗ: tasks/orchestrator/DEV_TASK_ORCH33_STAGING_TESTSUITE.md; отчёт tasks/orchestrator/reports/dev-2026-06-05-orch33-staging-testsuite.md

Этап 3 закрыт + боты в SANDBOX (05.06, продолжение)

PR #29 смержен → Этап 3 в main

  • PR #29 merged (HTTP 200, AUTH="token "+TOK — урок учтён). main HEAD 93169f1, коммит сьюта 94334bd.

Нюанс с бот-комментами закрыт (Plane membership)

  • Корень 403 при add_comment бот-токеном: бот-токен ВИДИТ проект (GET 200), но НЕ может постить комменты, пока его owner НЕ член проекта. Воспроизвела: бот POST comment=403, админ POST comment=201.
  • 7 бот-аккаунтов Plane (workspace members): Analyst c925cbcd-a8dc-4506-978e-15354ce3ad31, Developer bfe59a48-a7cd-4ce1-a78b-83f8891a4aba, Reviewer 9836a30d-1294-430d-8109-ceb3e784d1d8, Tester 7cdfc9e7-c552-4fd1-b4a7-3b1f03e72751, Architect 6d82b825-c8b2-447c-bca0-c4d34c6200ac, Deployer ebf17448-d544-465e-8b0e-57581f76507c, Стрим 468040f8-f609-406a-84d2-a119880a5e8e. (+ admin-токен owner = mva154 daf4d3f4..., + системный Plane 43c79cc2...).
  • Identity бот-токена узнаётся через GET {PBASE}/users/me/ с X-API-Key: <bot-token> → возвращает id+display_name.
  • Добавление члена проекта Plane (РАБОЧИЙ формат): POST /workspaces/{slug}/projects/{pid}/members/ body {"member": <user_id>, "role": 15} ПООДИНОЧКЕ. ⚠️ Формат {"members":[{...}]} и member_id НЕ работают (400 "member: This field is required"). role 15 = member.
  • Все 7 ботов добавлены членами SANDBOX (теперь 8 members). Верифицировано: Analyst и Developer боты постят комменты → HTTP 201. Нюанс Этапа 3 устранён.

Дальше

Этап 4 (ORCH-34): хост-деплой-хук orchestrator-deploy-hook.sh (промоут staging→prod, health 10×6с=60с, auto-rollback по PREV_IMG). Образец /home/slin/bin/enduro-deploy-hook.sh.


Этап 4 (ORCH-34) деплой-хук — ГОТОВО + чистка Plane (05.06, продолжение)

Закрыты в Plane (Backlog → Done НАПРЯМУЮ, минуя In Progress)

  • ORCH-30, ORCH-31, ORCH-32, ORCH-33 → Done (верифицированы).
  • ⚠️ Важная тонкость безопасности: боевой webhook ORCH-проекта идёт на прод (8500). Переход задачи В In Progress запустил бы конвейер по ней! Поэтому выполненные задачи двигать Backlog → Done напрямую, минуя In Progress. Прод не дёрнулся.
  • State id Done в проекте ORCH: 3738cd3c-7610-4907-ba5e-26b9a248d9c0.
  • ⚠️ In Progress id ПЛАВАЕТ — был b873d9eb... (в памяти), стал e331bfb3.... ВСЕГДА запрашивать states свежим API-вызовом, НЕ по памяти.
  • ОстаютсяBacklog: ORCH-34 (закрою после мержа), ORCH-35 (не начат).

Бот-аккаунты добавлены в SANDBOX (нюанс Этапа 3 закрыт)

  • 403 при коммите бот-токеном был НЕ из-за доступа к проекту (GET 200 у всех 7 ботов), а из-за членства: чтобы постить комменты, владелец бот-токена должен быть member проекта.
  • Plane API формат добавления члена: POST /projects/<id>/members/ с телом {"member": <user_id>, "role": 15} — ПООДИНОЧКЕ (не массивом), поле member (НЕ member_id!), role 15 = member.
  • Добавила всех 7 владельцев бот-токенов в SANDBOX → коммент бот-токеном теперь 201 (было 403). Проверено воспроизведением.
  • user-id ботов узнаются через workspace-members API.

Этап 4 — деплой-хук (проверено мной на проде, оба сценария)

  • Dev: scripts/orchestrator-deploy-hook.sh (176 строк) + docs/DEPLOY_HOOK.md. Ветка feature/ORCH-34-deploy-hook, коммит a6cbacb. PR #30 open.
  • Happy-path : deploy → health ok за 1 попытку → exit 0.
  • Авто-rollback (главное): Я сама подсунула битый образ (busybox exit 1, перетегла как staging-образ) → хук прождал 10×6с=60с (HTTP 000) → САМ откатился на PREV_IMG → рестарт → post-health 5×3с → поднялся → staging снова ok. Реальный exit-code хука = 1 при фейле (проверила без пайпа | tail, который съедал rc).
  • Heredoc-грабля Dev: при передаче скрипта через heredoc терялись кавычки в grep/curl -w → health давал «not ready» при HTTP 200. Фикс Dev: cat > файл из локального файла, не heredoc. ЗАПОМНИТЬ для будущих shell-скриптов через heredoc.
  • Прод цел: StartedAt 2026-06-04T13:08:13Z не менялся (Up 17h), 8500 ok. Файлы только новые, staging восстановлен, временные теги убраны.
  • Параметризация: дефолт БЕЗОПАСНЫЙ (TARGET_SERVICE=orchestrator-staging, PORT=8501, profile staging). Прод поддержан через override env, но НЕ дефолт. Отдельный PREV_IMAGE_FILE для staging.

Этап 5 (ORCH-35) — последний, ПЛАН (ещё не спущен Dev)

  • Цель: встроить стадию deploy-staging ПЕРЕД deploy-prod в конвейер (src/stages.py), тестер привязать к staging-эндпоинту 8501.
  • ⚠️ Самый рискованный этап: трогает боевой конвейер деплоя, часть src/ в off-limits. Перед спуском Dev — ЖИВАЯ разведка по коду стадий (как устроены deploy-стадии, точки встройки), показать план Славе.
  • Из дизайна §4/§7: промоут с ручным approve на старте (DEPLOY_REQUIRE_MANUAL_APPROVE=true) — хук тормозит после зелёного staging, ждёт «go» Славы. Полный авто — позже.
  • Из дизайна §6: агенты на staging — гибрид C (заглушки по умолчанию + full-real по флагу). Режима заглушек в коде ПОКА НЕТ (выяснено на Этапе 3) — возможно, понадобится на Этапе 5 или отдельной задачей.

Идентификаторы (обновление)

  • main HEAD после Этапа 3 (PR #29 merged): 93169f1
  • PR #30 (Этап 4) — open, коммит a6cbacb
  • Done state id (ORCH project): 3738cd3c-7610-4907-ba5e-26b9a248d9c0
  • ТЗ Этап 4: tasks/orchestrator/DEV_TASK_ORCH34_DEPLOY_HOOK.md; отчёт tasks/orchestrator/reports/dev-2026-06-05-orch34-deploy-hook.md
  • Деплой-хук: scripts/orchestrator-deploy-hook.sh, образец enduro: /home/slin/bin/enduro-deploy-hook.sh

ORCH-36 (Вариант B самодеплоя) заведён в Backlog + критерии «доверия к автоматике» (05.06)

ORCH-36 создан в Plane Backlog

  • id 84a6c09d-7a03-4cb7-a58b-3d8963c565a5, seq 36, name "ORCH-36: Исполняемый самодеплой — стадия deploy дёргает хост-хук (Вариант B)".
  • Суть: стадия deploy реально дёргает хост-хук orchestrator-deploy-hook.sh (ORCH-34) через ssh → промоут в прод (8500) с health+авто-rollback. На старте — ОБЯЗАТЕЛЬНЫЙ ручной approve (DEPLOY_REQUIRE_MANUAL_APPROVE=true). Делается ПОСЛЕ ORCH-35 (Вариант A — staging-гейт ворота).
  • Слава: "позже вернёмся" → лежит в бэклоге детально описанной.

«Доверие к автоматике» — ФОРМАЛЬНЫЕ критерии (для флага true→false)

Переход DEPLOY_REQUIRE_MANUAL_APPROVE true→false (manual approve → полный авто) — ТОЛЬКО когда ВСЕ 5 закрыты (метрики набираются в режиме ручного approve):

  1. ≥10 успешных промоутов подряд (staging зелёный → approve → прод поднялся, откат не нужен).
  2. Zero false-negative (критично): staging-гейт НИ РАЗУ не пропустил битый деплой как «зелёный».
  3. Авто-rollback проверен в бою ≥2-3 раза: recovery rate 100%, MTTR <60с.
  4. Ни одного «молчаливого» деплоя: каждый промоут/откат → Plane + Telegram.
  5. Период наблюдения: ≥10 деплоев ИЛИ ≥2 недели без инцидентов в manual-approve. Когда 5/5 → осознанное переключение флага отдельным шагом.

Этап 5 (ORCH-35) = Вариант A (решение по объёму ждёт Славу: только A или A+B)

  • Вариант A: стадия deploy-staging МЕЖДУ testing и deploy, QG check_staging_status (образец check_deploy_status), deployer гоняет staging_check.py против 8501. Прод-деплой недостижим пока staging не зелёный. Off-limits: не ломать существующие QG/rollback.
  • Полный план разведки — в tasks/orchestrator/DESIGN_STAGING_ENV.md (раздел "РАЗВЕДКА КОДА ДЛЯ ЭТАПА 5").

Этап 5 (ORCH-35) — staging-гейт встроен , проверено лично + найден архитектурный нюанс (05.06 ~07:30 UTC)

Что сделано Dev (PR #31, ветка feature/ORCH-35-staging-gate, коммит e0b6e92, НЕ мержен)

Вставлена стадия deploy-staging МЕЖДУ testing и deploy. Новая цепочка: testing → deploy-staging → deploy → done.

  • src/stages.pySTAGE_TRANSITIONS: testing→deploy-staging (agent=deployer, qg=check_tests_passed), deploy-staging→deploy (agent=deployer, qg=check_staging_status), deploy→done без изменений
  • src/qg/checks.py — новый check_staging_status + _parse_staging_status (парсит staging_status: SUCCESS|FAILED из 15-staging-log.md), зарегистрирован в QG_CHECKS
  • src/stage_engine.py — rollback-ветка: FAILED на deploy-staging → откат на development (по образцу БАГ-8 deploy)
  • .openclaw/agents/deployer.md — НОВЫЙ файл (в репо его не было), инструкция для обеих стадий deployer
  • tests/test_qg.py, tests/test_stage_engine.py — обновлены + 18 новых staging-тестов

Проверено МНОЙ лично на проде (не со слов Dev)

  • 312 passed, 0 failed — прогнала весь набор сама. Способ: прод-образ орка (там все зависимости) + примонтировала исходники ветки поверх → честный прогон в реальном окружении. (В прод-контейнере tests/ нет — образ собран без них; чистый python-образ не имеет зависимостей — поэтому монтирование в прод-образ.)
  • Цепочка вживую: get_next_stage("testing")=="deploy-staging", ("deploy-staging")=="deploy", ("deploy")=="done"; get_qg_for_stage("deploy-staging")=="check_staging_status"
  • QG-логика вживую: SUCCESS→(True), FAILED→(False), missing→(False) ✓
  • Rollback staging-провала → development (3 теста) ✓
  • git diff: только код (.openclaw/agents/deployer.md, src/qg/checks.py, src/stage_engine.py, src/stages.py, tests/*). off-limits (.env/compose/staging_check.py/deploy-hook.sh) не тронуты. Прод 8500 не задет.

⚠️ АРХИТЕКТУРНЫЙ НЮАНС (раскопала сама, ЖДЁТ решения Славы перед мержем)

Промпты агентов (deployer.md и пр.) живут В КАЖДОМ репозитории задач, а не в репо orchestrator.

  • launcher.py делает cat {system_prompt} ВНУТРИ work_path (= клон ЦЕЛЕВОГО репо задачи). Путь .openclaw/agents/deployer.md.
  • enduro-trails-репо имеет полный набор промптов (analyst/architect/deployer/developer/reviewer/tester.md от 04.06), но deployer.md там СТАРЫЙ — про staging-гейт не знает.
  • orchestrator-репо — Dev положил новый deployer.md с staging-инструкцией (правильно для self-hosting: орк деплоит сам себя, work_path=клон orchestrator).

Проблема: стадия deploy-staging ГЛОБАЛЬНАЯ (в STAGE_TRANSITIONS) → применяется ко ВСЕМ проектам конвейера. Но:

  1. У enduro deployer-промпт не знает про staging → не напишет 15-staging-log.md → гейт FAIL → enduro-задачи откатятся на development и застрянут
  2. staging_check.py --base-url localhost:8501 = staging ОРКА. У enduro своего staging нет. Гейт концептуально orchestrator-специфичный.

Варианты (предложены Славе):

  • 🅰️ (моя рекомендация) deploy-staging УСЛОВНЫЙ — гейт только для self-hosting (проект orchestrator), для остальных стадия пропускается/пустой pass. Правильная инкапсуляция.
  • 🅱️ оставить как есть + обновить enduro deployer.md + поднять enduro-staging (большой объём, выходит за рамки)
  • 🅲️ заморозить мерж как known-issue (активных enduro-задач нет), мержить после A

СТАТУС: жду решение Славы. PR #31 НЕ мержен. ORCH-35 НЕ закрыт.

Identifiers Этапа 5

  • PR #31 в Gitea (admin/orchestrator), ветка feature/ORCH-35-staging-gate, коммит e0b6e92, НЕ merged
  • ORCH-35 issue id: 4ead9be7-e1bf-4a28-8c76-88bda1c1fc2c
  • Done state id: 3738cd3c-7610-4907-ba5e-26b9a248d9c0
  • Новый артефакт стадии: docs/work-items/<wi>/15-staging-log.md, машинное поле staging_status:
  • Прогон тестов: образ прод-орка + монтирование исходников ветки → 312 passed

Вариант B вынесен в ORCH-36 (Backlog) — исполняемый самодеплой

Создан ORCH-36 «Исполняемый самодеплой — стадия deploy дёргает хост-хук (Вариант B)» в Backlog с детальным описанием. Внутри зашиты 5 метрик «доверия к автоматике» для переключения флага manual approve → авто:

  1. ≥10 успешных промоутов подряд (откат не понадобился)
  2. Zero false-negative — staging-гейт ни разу не пропустил битый деплой (критично)
  3. Авто-rollback в бою ≥2-3 раза (recovery 100%, MTTR <60с)
  4. Ни одного «молчаливого» деплоя (каждый → Plane + Telegram)
  5. Период ≥10 деплоев ИЛИ ≥2 недели без инцидентов Связи: ORCH-7/21/34/35. Ждёт когда вернёмся.

ORCH-35 ДОРАБОТКА — условный staging-гейт (Вариант А) проверено лично (05.06 ~07:40 UTC)

Решение Славы: Вариант А — условный гейт

Гейт deploy-staging срабатывает реально ТОЛЬКО для self-hosting (проект orchestrator). Для остальных проектов (enduro-trails и пр.) — мгновенный зелёный pass, чтобы их задачи НЕ застряли на откате.

Что сделал Dev (коммит e0c14fa в той же ветке feature/ORCH-35-staging-gate)

  • src/qg/checks.py:451-455SELF_HOSTING_REPO = "orchestrator" + is_self_hosting_repo(repo) (case-insensitive)
  • check_staging_status: если repo НЕ self-hosting → сразу (True, "Staging gate N/A for <repo>"), файл 15-staging-log.md даже не читается. Если orchestrator → реальная проверка как было.
  • STAGE_TRANSITIONS НЕ трогали — стадия остаётся в цепочке для всех, условность зашита в QG.
  • tests/test_qg.py — +7 новых тестов под условную логику

Проверено МНОЙ лично на проде (прод-образ орка + примонтированы исходники ветки)

  • 319 passed, 0 failed (было 312, +7 новых)
  • Условность вживую (через docker cp файла в контейнер, НЕ -v mount — volume-mount файла НЕ подхватывается, урок!):
    • check_staging_status("enduro-trails", ...) → (True, "Staging gate N/A...") БЕЗ файла ✓
    • check_staging_status("orchestrator", ...) без файла → (False) ✓, с staging_status: SUCCESS → (True) ✓
  • repo приходит как plain gitea name (ProjectConfig.repo из реестра projects.py) — подтверждено, сравнение корректное
  • Доработка тронула только qg/checks.py + tests/test_qg.py. git diff ветки показывает 6 файлов — это НАКОПЛЕННЫЙ diff всей ветки против main (первый коммит e0b6e92 + доработка e0c14fa), сама доработка stages.py НЕ меняла.

projects.py (разведано, реестр проектов из ORCH-6 фикса 02.06)

Связывает Plane-проект uuid ↔ Gitea-репо ↔ префикс. ProjectConfig (frozen): plane_project_id, repo, work_item_prefix, name. Источник: env ORCH_PROJECTS_JSON → settings.projects_json, fallback _DEFAULT_PROJECTS (enduro-trails ET первый намеренно, orchestrator ORCH). Парсер устойчив (битый элемент скип, пусто→дефолт). Отсюда берётся способ отличить self-hosting (repo=="orchestrator").

СТАТУС: СМЕРЖЕНО И ЗАКРЫТО (05.06 ~07:43 UTC)

  • PR #31 СМЕРЖЕН (merge commit f1b3146, merged=True/closed). main HEAD = f1b3146, под ним e0c14fa + e0b6e92.
  • ORCH-35 переведён Backlog→Done напрямую (HTTP 200, state 3738cd3c). Мимо In Progress — webhook не дёрнут.
  • ORCH-35 id 4ead9be7-e1bf-4a28-8c76-88bda1c1fc2c

🏁 СЕРИЯ САМОДЕПЛОЯ — ФИНАЛ

Все 5 этапов готовы и проверены лично:

  • Этап 1 ORCH-31 Done (PR #28)
  • Этап 2 ORCH-32 Done (песочница staging 8501)
  • Этап 3 ORCH-33 Done (PR #29, staging_check.py)
  • Этап 4 ORCH-34 Done (PR #30, deploy-hook.sh + авто-rollback)
  • Этап 5 ORCH-35 DONE (PR #31 смержен f1b3146, условный staging-гейт, 319 тестов)
  • Вариант B вынесен в ORCH-36 (Backlog) — исполняемый деплой, на потом

ДОКУМЕНТАЦИЯ ОРКА = golden source в репо (задача Славы 05.06 ~08:30)

Слава хочет: вся дока по орку в репо (код+дока по единым канонам), чтобы мульти-агенты знали где дока, ИСПОЛЬЗОВАЛИ и АКТУАЛИЗИРОВАЛИ.

КЛЮЧЕВОЙ ИНСАЙТ (подтверждён Славой): структура папок ≠ агенты её используют. Агент видит ТОЛЬКО свой system_prompt (.openclaw/agents/<role>.md) + task. Канон держится на 3 слоях.

3-слойный канон (согласован):

  1. Структура docs/: README, ARCHITECTURE, PIPELINE, PRODUCT_VISION, adr/ (1 решение=1 файл adr-NNNN-slug.md), operations/, work-items//, history/ (архив), CHANGELOG, CONTRIBUTING, AGENTS.md
  2. Промпты агентов (★): полный набор .openclaw/agents/*.md в репо орка по образцу enduro — жёстко: читай docs/, пиши work-items, архитектор ведёт ADR, каждый обновляет CHANGELOG. Reviewer-gate: если доку не обновили → REQUEST_CHANGES (канон держится автоматически)
  3. Канон процесса: CONTRIBUTING.md + AGENTS.md в корне, на них ссылаются промпты

⚠️ ИНФРА-ИЗОЛЯЦИЯ (проверено по факту):

  • РИСК: прод-орк (8500) — ОДИН инстанс на ВСЕ проекты (ET+ORCH), ОБЩАЯ БД /app/data/orchestrator.db, общая очередь. Self-доработка орка бежит в том же инстансе, что держит ET → рестарт/падение = групповой риск. Staging-гейт (ORCH-35) — страховка.
  • ХОРОШО: staging (8501) полностью изолирован (свой ORCH_PROJECTS_JSON=только sandbox); репы раздельные (worktree ORCH-2)
  • Инфру ВЕДЁМ в репо: docs/operations/INFRA.md (RUNBOOK). Секреты — ТОЛЬКО в .env хоста (.env.example канон). Уже есть: .env.example, .env.staging.example, compose, Dockerfile трекаются; .env НЕ в гите ✓

⚠️ ДЫРА у орка: в репо orchestrator .openclaw/agents/ — ТОЛЬКО deployer.md! Нет analyst/architect/developer/reviewer/tester. У enduro — полный набор с дока-каноном. self-доработка орка упадёт без этих промптов.

ЗАДАЧИ Plane:

  • ORCH-9 «Онбординг (turnkey)» — НАПОЛНИЛА детально (3-слойный канон + инфра + AC), id c333bf6a-76dd-4214-aab2-61af4a8fbc58, Backlog. Источник: temp/orch9_desc.md
  • ORCH-11 «Полная дока мультиагентов» id a396db3e-8618-491f-b62c-cc2bc490e502 (пустая)
  • ORCH-24 «Персистентная БЗ» id 4c2009b3-3dad-456f-9f9e-1c1fa3d9dda6 (пустая)

РЕШЕНИЯ Славы (финал по канону):

  1. Паспорт = per-repo CLAUDE.md (НЕ AGENTS.md, НЕ единый на все). Изоляция репо/проектов — фича. Каждый проект — свой паспорт, точно описывает свой проект. Канон enduro: CLAUDE.md + docs/architecture/ (папка!) + adr/, артефакты 00-business-request..15-staging-log, 04-test-plan.YAML (не md!), per-wi ADR-NNN (upper) / global adr-NNNN (lower). НЕТ CONTRIBUTING.md — конвенции внутри CLAUDE.md.
  2. INFRA.md остаётся как орк-специфика (у enduro аналога нет, но self-hosting риск реален).
  3. Промпты агентов + reviewer-gate — СЕЙЧАС через Dev.
  4. ORCH-9 — сформировать ПРИНЦИПЫ подготовки промптов (методичка), ET = пример-референс, НЕ генерить промпты под enduro.

СДЕЛАНО:

  • Комплект доки (8 файлов) написала САМА по канону enduro, выверено против кода (ДВА ревью: сначала нашла что выдумала свой канон ≡ AGENTS/CONTRIBUTING, потом переписала под enduro-канон). Архив: temp/orch_docs_canon.tgz, доставлен на slin /tmp/orch_docs_canon.tgz. Исходники: temp/orch_docs/.
  • Методичка ORCH-9 tasks/orchestrator/ORCH9_PROMPT_PRINCIPLES.md — принципы подготовки промптов (каркас, инварианты, роль-специфика, reviewer-gate, ET=референс). Ссылка добавлена в описание ORCH-9.
  • Dev запущен (orch9_docs_canon, session eef3f0c0): ТЗ DEV_TASK_ORCH9_DOCS_CANON.md — заливка доки + реструктуризация docs/ (git mv в operations/, history/, ARCHITECTURE.md→architecture/internals.md) + промпты агентов (analyst..tester) + reviewer-gate. Ветка docs/ORCH-9-canon, PR не мержить.

ПРОВЕРИТЬ после Dev (лично): структура docs/ по канону, полный набор .openclaw/agents/ (6 ролей), 0 битых ссылок, git mv сохранил историю, README цепочка актуальная, reviewer-gate в promptе, diff только docs/.openclaw (НЕ src/tests/compose).

🏁🏁🏁 СЕРИЯ САМОДЕПЛОЯ ПОЛНОСТЬЮ ЗАВЕРШЕНА 05.06.2026. Орк имеет staging-предохранитель: прод-деплой недостижим, пока staging-гейт не зелёный (для self-hosting). Следующий шаг когда вернёмся — ORCH-36 (исполняемый деплой) с 5 метриками доверия.

ORCH-9 (часть 1) ЗАВЕРШЕНА Dev → ПРОВЕРЕНО МНОЙ ЛИЧНО на проде (PR #32, коммит 7c68d1d, НЕ смержен)

Dev (session orch9_docs_canon) отработал, я проверила не со слов:

  • Структура канона: CLAUDE.md (5543b, паспорт орка) + CHANGELOG.md в корне; мои маркеры целы (self-hosting, deploy-staging, 04-test-plan.yaml, ADR-NNN). docs/ по канону enduro: architecture/ (README + adr/ + internals.md), operations/ (INFRA, DEPLOY_HOOK, STAGING, STAGING_CHECK, SETUP_WEBHOOKS), history/ (8 архивных BUGFIXES/LESSONS/INCIDENT).
  • git mv сохранил историю (R097/R100 в diff = renames, не пересоздание). Старый docs/ARCHITECTURE.md → docs/architecture/internals.md (глубина: схема БД SQL, resilience, потоки — сохранена).
  • Промпты агентов (6 ролей) .openclaw/agents/: analyst, architect, developer, reviewer, tester, deployer. Все ссылаются на CLAUDE.md + docs/architecture/README.md. Модели верные (architect/reviewer→opus, остальные→sonnet, сверено с launcher.py AGENT_CONFIGS). architect ведёт ADR (per-wi 06-adr/ADR-NNN + сверка с global architecture/adr/). self-hosting раздел у architect/developer/deployer (не ронять прод-контейнер, ссылка INFRA).
  • Reviewer-gate: reviewer.md содержит правило REQUEST_CHANGES при необновлённой доке (P0, через YAML verdict:, БЕЗ правки кода QG).
  • Чистота diff: ТОЛЬКО docs/ + .openclaw/agents/ + README/CLAUDE/CHANGELOG. Код/тесты/compose/.env/scripts НЕ тронуты.
  • README + internals цепочка актуальна (deploy-staging).

РАЗДЕЛЕНИЕ СКОПА (Слава, 05.06 Вариант Б): две РАЗНЫЕ задачи, НЕ мешать!

  • Орк-специфика (паспорт+промпты САМОГО орка+reviewer-gate) = self-hosting, не ORCH-9. Остаётся в репо orchestrator, PR #32 СМЕРЖЕН в main 05.06 (Слава дал «делай» → мерж через API): merge commit 5ecd1c4, merged=True/closed. main HEAD = 5ecd1c4. Методичка ОТКАЧЕНА из этой ветки (reset 7c68d1d, force-with-lease). Ветка docs/ORCH-9-canon HEAD = 7c68d1d (только орк-канон).
  • Онбординг (ORCH-9) = ОТДЕЛЬНЫЙ РЕПО onboard2orch (Слава: онбординг ≠ код орка, изоляция). Создан: https://git.mva154.duckdns.org/admin/onboard2orch (коммит 3b0ea44). Структура: README.md, principles/PROMPT_PRINCIPLES.md, checklists/ONBOARDING_CHECKLIST.md, examples/enduro-trails/README.md (референс-указатели, НЕ копии). Описание ORCH-9 в Plane обновлено ссылкой на репо.
  • Исходники onboard2orch: temp/onboard2orch/. Методичка-оригинал остаётся в tasks/orchestrator/ORCH9_PROMPT_PRINCIPLES.md (process-копия).
  • ГЛАВНЫЙ УРОК: не мешать «про орк как проект» и «про онбординг любых проектов». Разные репо, разные задачи. Слава поймал моё смешение скопа.

(устарело, было до разделения):

  1. PR #32 мержит Слава ВРУЧНУЮ (правило: агентам push/merge в main запрещён). Если попросит «мержи» прямо — могу через API. Пока ждёт его ручного мержа.
  2. Методичку положила в репоdocs/operations/ONBOARDING_PROMPTS.md (коммит 23c7950, в той же ветке docs/ORCH-9-canon → часть PR #32). Ветка теперь: 7c68d1d (канон+промпты) + 23c7950 (методичка).
  • Ветка docs/ORCH-9-canon HEAD = 23c7950, main = f1b3146 (до мержа PR #32).

Артефакты ORCH-9:

  • ТЗ Dev: tasks/orchestrator/DEV_TASK_ORCH9_DOCS_CANON.md
  • Методичка: tasks/orchestrator/ORCH9_PROMPT_PRINCIPLES.md (КАРКАС промпта + инварианты канона + роль-специфика + чеклист готовности; ET=референс, не шаблон)
  • Комплект доки (исходники): temp/orch_docs/ (CLAUDE.md, CHANGELOG.md, docs/architecture/README.md + adr/adr-0001..0003 + adr/README.md, docs/operations/INFRA.md)
  • Архив доставки: temp/orch_docs_canon.tgz → slin /tmp/orch_docs_canon.tgz
  • Отчёт Dev: tasks/orchestrator/reports/dev-2026-06-05-orch9-docs-canon.md

ЗАПУСК САМОДОРАБОТКИ — ревью готовности (05.06, Слава: «Старт», таска ORCH-16):

  • БЛОКЕР 1 УСТРАНЁН: прод-образ отставал (checks.py без is_self_hosting_repo). Ребилд из main 5ecd1c4 (ОК Славы). Постпроверка: checks.py=main 3f9fe07, is_self_hosting_repo(enduro)=False/(orchestrator)=True, staging-gate enduro=пропуск, 6 ET-задач на месте, 319 passed. Прод синхронен. (Тесты НЕ в образе — Dockerfile COPY только src/+data/, гонять из /repos/orchestrator или CI.)
  • БЛОКЕР 2 = ORCH-10 (в работе): plane_sync.py хардкодит PLANE_STATES = UUID СТАТУСОВ ТОЛЬКО ENDURO. ORCH-проект имел 5 базовых статусов, нет стадийных. Слава: «сделать в ORCH такую же статусную модель как в ET, недостающие добавить».
    • СДЕЛАЛА: создала 9 недостающих статусов в ORCH-проекте через Plane API (Architecture/Development/Review/Testing/Approved/Rejected/Needs Input/In Review/Blocked) — теперь 14 шт, идентично ET по составу. UUID НОВЫЕ (свои у ORCH).
    • Dev запущен (orch10_states, session 305f824d): ТЗ DEV_TASK_ORCH10_PER_PROJECT_STATES.md — динамический резолвинг статусов по project_id (get_project_states + кэш + fallback _DEFAULT_STATES). КРИТИЧНО: webhook-сравнение in_progress резолвить по проекту (иначе ORCH-задача не стартует). Ветка feature/ORCH-10-per-project-states.
    • ORCH-10 ГОТОВ → ПРОВЕРЕНО МНОЙ лично (PR #33): diff только plane_sync.py+webhooks/plane.py+tests, 342 passed (+23), резолвинг живой (ET→b873d9eb/3020bbb7, ORCH→e331bfb3/795cc32f, UUID разные), enduro не сломан. get_project_states(project_id)+кэш+fallback _DEFAULT_STATES. ЖДЁТ МЕРЖА PR #33. После мержа → ребилд прода → проверка в контейнере → ORCH-16 старт.
    • Полные карты UUID обоих проектов — в ТЗ (сняты с прода). ORCH-37 заведена (гигиена статусов Plane, Backlog, id 9ccc5490). ORCH-16 ОСТАЛАСЬ в Backlog (мой PATCH state упал 400 — и хорошо, конвейер НЕ запущен). В описание ORCH-16 дописаны ответы на 2 вопроса (текст+ссылка+1-строка вердикт; один коммент на агента).
  • ПОРЯДОК: ORCH-10 (Dev) → ребилд прода → проверка резолвинга лично → ТОГДА ORCH-16 Backlog→In Progress (старт конвейера).
  • ORCH-16 = «Единообразные коммент-артефакты в Plane» id 2b80c58c-2a83-4ab0-aa69-b7f5d2f8c345, мелкая, наполнена. Первая самодоработка-прогрев.

КЛЮЧЕВЫЕ PLANE state-id (оба проекта):

  • ORCH in_progress e331bfb3-e17e-4699-ba48-4abb89c21b7b, backlog 2d5d42ff-..., done 3738cd3c-.... Стадийные: architecture 795cc32f, development f5ed4705, review 2026f3d9, testing 81c5cd78, approved 63f2c8fe, rejected 4c769e90, needs_input 99978b3f, in_review c52e99b9, blocked 505f01a6.
  • ET in_progress b873d9eb-... (остальные — в ТЗ ORCH-10 и plane_sync.py PLANE_STATES).
  • ORCH-проект plane_id 8da6aa25-a60e-44d6-a1e2-d8ae59aa7d6a, ET plane_id 7a79f0a9-5278-49cd-9007-9a338f238f9c.

ФАКТЫ ОРКА (золотой источник, для будущих сессий):

  • НЕТ Makefile, НЕТ budget.yaml (в отличие от enduro). Тесты: pytest tests/ -q (из .gitea/workflows/ci.yml). CI = Gitea Actions.
  • Прод 8500, staging 8501 (изолированная БД ./data/staging, profile staging, только sandbox-проект). External: https://openclaw.mva154.duckdns.org/orchestrator/. Webhook: .../orchestrator/webhook/gitea (+ /webhook/plane).
  • Эндпоинты: GET /health, /status, /queue; POST /webhook/plane, /webhook/gitea (prefix /webhook + route).
  • ADR-формат: per-work-item docs/work-items/<id>/06-adr/ADR-NNN-slug.md (UPPER, 3 цифры); сквозные docs/architecture/adr/adr-NNNN-slug.md (lower, 4 цифры). Индекс — adr/README.md.
  • Канон артефактов: 00-business-request, 01-brd, 02-trz, 03-acceptance-criteria, 04-test-plan.YAML, 06-adr/, 07-infra-req, 08-data-req, 10-tech-risks, 12-review(verdict:), 13-test-report, 14-deploy-log(deploy_status:), 15-staging-log(staging_status:).
  • main HEAD до PR #32 = f1b3146 (merge ORCH-35).

Эталон enduro для канона: /home/slin/repos/enduro-trails/ — CLAUDE.md (паспорт), docs/architecture/ (README+adr), .openclaw/agents/*.md (6 ролей, эталон каркаса промпта: frontmatter→контекст→что прочесть→что произвести→принципы→запрещено→эскалация).

2026-06-05

Orchestrator — CI-гейт качества закрыт (продолжение self-hosting ORCH-7)

Главный итог

CI у orchestrator теперь честно зелёный. Дефект изоляции тестов (тесты протекали друг в друга через синглтон settings) закрыт. Гейт качества для self-hosting работает по-настоящему.

Что было сделано

  • PR #27 (ветка fix/isolate-webhook-tests-from-plane) — три коммита:
    • 7bbab9c — изоляция 3 webhook-тестов от живого Plane API (моки через ИСТОЧНИК src.plane_sync.*)
    • e856e09 — миграция test_plane_webhook_generates_sequential_ids под новый контракт (задача создаётся при переходе В In Progress, а не на work_item.created)
    • 1baae81autouse-фикстура в tests/conftest.py, сбрасывает webhook-секрет (+ db_path) на синглтоне settings перед каждым тестом
  • Проверено лично на проде: полный pytest tests/ в чистом docker-окружении = 294 passed, 0 failed (было 10 failed). CI run 547/548 = success (впервые).
  • 401/HMAC/dedup тесты ЖИВЫ — фикстура их не сломала (они перекрывают её своим monkeypatch). Off-limits зона не тронута: правки только в tests/conftest.py и tests/test_webhooks.py, src/ чист.

Ключевой урок — интерференция тестов через синглтон settings

  • Settings (Pydantic, src/config.py) читает env ОДИН раз при создании объекта settings.
  • test_webhooks.py ставит секрет жёстко os.environ["..."]="" на import-time; другие файлы — через setdefault; test_webhook_dedup.py ставит реальный "s3cr3t" через monkeypatch.
  • В ПОЛНОМ прогоне pytest tests/ секрет протекал между файлами → HMAC включался → webhook-тесты ловили assert 401 == 200. По отдельности файл зелёный, вместе — красный.
  • Решение-паттерн: autouse-фикстура в conftest, сброс протекающего состояния синглтона через monkeypatch перед каждым тестом. НЕ менять сам механизм/защищённые тесты — только навести порядок с изоляцией. db_path тоже протекал (get_task_by_repo_branch возвращал stale) — Dev законно добавил и его сброс.

Мерж ВЫПОЛНЕН (05.06, Слава дал «да»)

  • PR #27 → MERGED в main (HTTP 200). main HEAD = d0a3424 Merge PR #27. Все 3 коммита фиксов в истории main.
  • PR #26 → CLOSED без мержа (поглощён #27).
  • Нюанс: CI на самом main после merge-commit отдельным прогоном не появился (workflow триггерится на push/PR-ветки; merge-commit мог не дёрнуть). Код в main = ровно то, что прогонялось зелёным (294 passed). Гейт на будущих PR работает.
  • Пункт №1 self-hosting (CI-гейт) ЗАКРЫТ. Осталось: удалить отработанные ветки fix/isolate, ci/add (косметика).

Staging-среда для orchestrator (ORCH-30..35) — дизайн оформлен, задачи в Backlog

(подробности выше по тексту дня; см. историю)


СЕССИЯ flush 11:36 UTC — ребилд прода + статусная модель ORCH = ET

Ребилд прода ВЫПОЛНЕН (Слава дал ОК)

  • Блокер src/qg/checks.py рассинхрон устранён: docker compose up -d --build orchestrator из main (5ecd1c4).
  • Постпроверка ЛИЧНО: прод checks.py == main 3f9fe07; is_self_hosting_repo("enduro-trails")=False (ET пропускает staging-гейт «N/A»), ("orchestrator")=True; 6 ET-задач на месте; очередь+breaker(closed)+preflight живы; 319 passed (тесты гонятся из /repos/orchestrator — в образ НЕ копируются, только src/+data/).
  • ФАКТ: Dockerfile орка build: . копирует только src/ + data/; тестов в образе нет (CI/репо).

Статусная модель ORCH приведена к ET (Слава: «использовать такую же модель как в ET, не хватает — добавь»)

  • В ORCH-проекте было 5 базовых статусов, в ET — 14. Создала 9 недостающих через Plane API (Architecture/Development/Review/Testing/Approved/Rejected/Needs Input/In Review/Blocked) с теми же name/color/group. Теперь ORCH = 14, идентично ET по составу.
  • ⚠️ UUID у ORCH-статусов СВОИ (Plane генерит уникальные) → всплыл блокер ORCH-10 (код хардкодит ET-UUID). Самое критичное: webhook распознавал «старт конвейера» только по ET-UUID in_progress → ORCH-задача (её UUID e331bfb3) НЕ стартовала бы. Поэтому мой PATCH ORCH-16 state упал 400 — и хорошо, конвейер не встал криво.

ORCH-10 (per-project резолвинг статусов) — ГОТОВ, ПРОВЕРЕН ЛИЧНО, PR #33 ЖДЁТ МЕРЖА

  • Сделал Dev по ТЗ DEV_TASK_ORCH10_PER_PROJECT_STATES.md (полные карты UUID обоих проектов в ТЗ — Dev не гадал).
  • Решение: get_project_states(project_id) читает статусы из Plane API + кэш _STATES_CACHE + fallback _DEFAULT_STATES (=текущие ET-значения). reload_project_states() для сброса.
  • Проверено мной: diff только plane_sync.py+webhooks/plane.py+tests; 342 passed (+23, 0 регрессий); живой резолвинг ET→ET-UUID (in_progress b873d9eb, architecture 3020bbb7), ORCH→ORCH-UUID (in_progress e331bfb3, architecture 795cc32f), UUID разные; enduro не сломан; webhook-старт распознаётся для обоих проектов.
  • PR #33: admin/orchestrator#33НЕ смержен, жду «мержи» от Славы.

ORCH-37 заведена (по просьбе Славы) — гигиена статусов Plane

  • Backlog, id 9ccc5490. Суть: статусов на доске много, используем не все → ревизия + чистка неиспользуемых/дублей, минимальный набор под фактический конвейер. ОБЯЗАТЕЛЬНО согласовать со Славой и не сломать ET (статусы общие, после ORCH-10 резолвятся per-project). Не срочно.

ORCH-16 ЗАПУЩЕНА — ПЕРВАЯ САМОДОРАБОТКА ОРКА В ПОЛЁТЕ (11:44 UTC)

  1. PR #33 СМЕРЖЕН (Слава: «мержи»), merge commit a2cf145, main обновлён.
  2. Ребилд прода из main выполнен, health 200.
  3. Резолвинг в ЖИВОМ контейнере: ET→b873d9eb, ORCH→e331bfb3/795cc32f, разные, ET-задачи (6) целы, очередь жива.
  4. ORCH-16 Backlog→In Progress → webhook СТАРТАНУЛ конвейер: Task 33, analyst запущен (run_id=93, pid=78), стадия analysis, ветка feature/ORCH-016-plane, worktree создан, 00-business-request.md записан. claude.exe реально пашет (роль analyst прочиталась из клона репо — self-hosting каркас работает).
  • ГРАБЛЯ №1 (решена): QG-0 завернул первый старт — Title слишком длинный (макс 80 символов). Орк корректно перевёл в Blocked (наш новый ORCH-статус 505f01a6 сработал — резолвинг per-project в бою!). Укоротила название до 55 симв («Единообразные коммент-артефакты в Plane от всех агентов»), сброс Backlog→In Progress → старт прошёл. ⚠️ УРОК: название задачи ORCH/ET ≤80 символов, иначе QG-0 блок.
  • ГРАБЛЯ №2 (не системная): транзиентный 403 на коммент аналитика при залпе webhook-ов (гонка при сбросе статуса). Ручной POST коммента прошёл 201 — токен прав имеет. Не блокер, конвейер не встал.
  • ORCH-16 id 2b80c58c-2a83-4ab0-aa69-b7f5d2f8c345, в описании ответы на 2 вопроса (текст+ссылка+1-строка вердикт; один коммент на агента за стадию). Дальше конвейер идёт сам: analysis→architecture→development→review→testing→deploy. НЕ дёргать без нужды.
  • PATCH статуса Plane: правильное поле = state (НЕ state_id), значение = UUID статуса. {"state":"<uuid>"} → HTTP 200.

🎉🎉 ORCH-16 ДОЕХАЛ ДО DONE — ПЕРВАЯ ПОЛНАЯ САМОДОРАБОТКА ОРКА (12:52, 05.06)

  • Полный цикл: Backlog→In Progress→analysis→architecture→development→review→testing→deploy-staging→deploy→done. Все стадии авто, очередь чистая (done 39, failed 0). Ветка feature/ORCH-016-plane, фича закоммичена (0663da6 feat(plane): unified status-comment format with duration line).
  • Фикс ботов (важный урок): 403 на комменты — боты-агенты не были членами ORCH-проекта. Добавила 7 ботов через POST /projects/<id>/members/ поле {"member":<id>,"role":15} (НЕ member_id). user_id ботов взяла из ET: Reviewer 9836a30d, Стрим 468040f8, Architect 6d82b825, Analyst c925cbcd, Deployer ebf17448, Tester 7cdfc9e7, Developer bfe59a48. Теперь ORCH = 8 членов.
  • Rework-цикл работает: Слава отклонил (Rejected) + коммент «добавьте длительность работы» → орк прокинул причину в .task.md → аналитик доработал. Результат: usage-метрики в комментах (📛 Architect готов · 345.7k in / 14.7k out · $0.91).
  • ГРАБЛЯ QG-0: название >80 символов → Blocked. Укоротила. Правило: название задачи ≤80.
  • onboard2orch чеклист обновлён (коммит e8d521bf): Шаг 1a (статусы Plane) + Шаг 1b (боты в проект) + усилен Шаг 5.

💰 РАСХОД ORCH-16 — вскрылась проблема бюджета (→ ORCH-38)

  • Итого ORCH-16: ~$20.32 (analyst $1.10+$1.71, architect $0.91, developer $13.68, reviewer $2.13, tester $0.78).
  • КОРЕНЬ: стоимость линейна от cache_read_tokens (перечитывание контекста циклами tool-call). developer run 96: cache_read 18.98M.
  • ET vs ORCH (пруф agent_runs): ET developer avg $1.91 (n=16), макс $9.16 (run 65, 11.98M). ORCH developer $13.68. Вывод: раздувание было и в ET (run 65), но в ORCH пик (~7.5x типичного). Гипотезы: промпт developer не даёт целевые файлы→слепой обход src/; модель opus дороже sonnet.
  • Агенты пишут usage в БД agent_runs (cols: cost_usd, input_tokens, output_tokens, cache_read_tokens, cache_creation_tokens, model, agent, task_id). /app/data/orchestrator.db.

НОВЫЕ ORCH-ЗАДАЧИ (Backlog):

  • ORCH-37 Гигиена статусов Plane (id 9ccc5490) — ревизия/чистка неиспользуемых.
  • ORCH-38 Бюджет и эффективность агентов (id 2afa7b07) — контроль расхода токенов: целевые файлы в task, бюджет-лимит per-stage, метрика-сводка, sonnet vs opus.

Скоуп ORCH-9 разведён (Вариант Б, ранее в сессии):

  • Орк-репо = только орк (PR #32 смержен в main 5ecd1c4: CLAUDE.md паспорт + дока канона + 6 промптов + reviewer-gate).
  • Онбординг = отдельный репо onboard2orch (https://git.mva154.duckdns.org/admin/onboard2orch, коммит 3b0ea44): principles/checklist/examples(ET-референс). Методичка убрана из орк-ветки.

КЛЮЧЕВЫЕ PLANE state-id (оба проекта, для будущих сессий):

  • ORCH (plane_id 8da6aa25-a60e-44d6-a1e2-d8ae59aa7d6a): backlog 2d5d42ff, todo b5d3f512, in_progress e331bfb3, architecture 795cc32f, development f5ed4705, review 2026f3d9, testing 81c5cd78, approved 63f2c8fe, rejected 4c769e90, done 3738cd3c, cancelled 59d1d210, needs_input 99978b3f, in_review c52e99b9, blocked 505f01a6.
  • ET (plane_id 7a79f0a9-5278-49cd-9007-9a338f238f9c): backlog 113b24f6, todo 2c7d3df3, in_progress b873d9eb, architecture 3020bbb7, development 9920609b, review ba0d802c, testing 7855d807, approved a519a341, rejected ba958f3c, done 381a2833, cancelled b1cae7f9, needs_input babf08a3, in_review 38fb1f64, blocked 6c4543f9.

ФАКТЫ ОРКА (золотой источник):

  • НЕТ Makefile, НЕТ budget.yaml. Тесты: pytest tests/ -q. CI = Gitea Actions.
  • Прод 8500, staging 8501 (изолир. БД ./data/staging, profile staging). External: https://openclaw.mva154.duckdns.org/orchestrator/. Webhook: .../orchestrator/webhook/gitea (+ /webhook/plane).
  • Эндпоинты: GET /health, /status, /queue; POST /webhook/plane, /webhook/gitea.
  • Dockerfile build: . копирует только src/ + data/ (тестов в образе нет).
  • Webhook старт конвейера: if new_state == PLANE_STATES["in_progress"] (после ORCH-10 — резолв по project_id). Фильтр по проекту: unknown project → ignore (ORCH-6).
  • main HEAD = 5ecd1c4 (Merge PR #32).
  • Прод: контейнер orchestrator, image orchestrator-orchestrator. SSH: sshpass -p 'motoZ@yaz2010' ssh slin@82.22.50.71. compose /home/slin/repos/orchestrator/docker-compose.yml.

Эталон enduro для канона: /home/slin/repos/enduro-trails/ — CLAUDE.md, docs/architecture/, .openclaw/agents/*.md (6 ролей).


🔧 ORCH-16 деплой + ORCH-39 (тесты/CI) — финал дня (05.06 вечер)

ORCH-16: done ≠ в проде (важное различие)

  • ORCH-16 в Plane = done, НО фича в прод НЕ выкачена. deploy-staging прошёл (staging_status: SUCCESS, коммит 053ea3b — только docs, merge staging-log в main).
  • Фича-код 0663da6 (единый формат коммента + строка длительности) — только в ветке feature/ORCH-016-plane. PR #34 ОТКРЫТ, не влит.
  • Прод на 8500 работает на СТАРОМ коде. Это правильный предохранитель self-hosting: орк не мержит/не ребилдит себя сам без ОК Славы.

Ревью PR #34 лично (вердикт)

  • +3452/-112, 27 файлов. Боялась мусора за $13.68 — оказалось код ГРАМОТНЫЙ.
  • build_status_comment() — единая точка для всех ролей. Обратная совместимость сохранена (старые usage_comment/artifact_links не удалены). frontmatter.py — защитный ридер, никогда не падает.
  • 43 теста ORCH-16 — зелёные.
  • НО: 4 теста падали (test_m6_sequence.py ×2, test_plane_webhook.py ×2) — НЕ вина ORCH-16, пришли с ORCH-10 (PR #33), отставший контракт.

Типы item в Plane (этот инстанс) — проверено через API

  • Epics = 404, issue-types/work-item-types = 404 (кастомные типы выключены)
  • parent у issue → sub-issues (под-задачи) РАБОТАЮТ
  • modules (≈эпики), cycles (спринты) — есть, но пусты (n=0)
  • Декомпозиция: через parent + modules, не через Epic→Story→Task типы.

ORCH-39: починка отставших тестов + дыра CI

  • Завела ORCH-39 (id 7c061055, Backlog) — для трекинга. Исполнение НЕ конвейером, а Dev напрямую (принцип ORCH-38: не жечь $15-20 на правку 4 тестов).
  • Корень падений (диагноз мой): тесты хардкодят _IN_PROGRESS = "b873d9eb..." (ET in_progress UUID) для запросов по ORCH-проекту. После ORCH-10 get_project_states(ORCH)["in_progress"] = e331bfb3, не совпадает → pipeline не стартует → задача не создаётся → assert падает. Тесты отстали от per-project резолвинга, код прода правильный.
  • ТЗ: tasks/orchestrator/DEV_TASK_ORCH39_FIX_WEBHOOK_TESTS.md (точные UUID-карты ET/ORCH, точки мока, off-limits src/).

Per-project state UUID (ЗАФИКСИРОВАТЬ — пригодятся)

  • ET (enduro-trails): in_progress=b873d9eb-993c-48cd-97ac-99a9b1623967, approved=a519a341-dada-4a91-8910-7604f82b79c5, rejected=ba958f3c-5db5-461d-8f82-89425e413b97
  • ORCH (orchestrator): in_progress=e331bfb3-e17e-4699-ba48-4abb89c21b7b, approved=63f2c8fe-dcda-4ace-952f-dd88bd0118ff, rejected=4c769e90-bf80-4a52-b97a-e1c84904bfc3

Dev фейл на биллинге → перезапуск

  • Первый Dev упал: кончились кредиты дефолтной vibecode-модели. Перезапустила с tokenator/claude-opus явно. (Урок: при billing-фейле Dev — сразу перезапуск с tokenator-моделью.)

PR #35 (ORCH-39) — проверено лично

  • fix/ORCH-39-webhook-tests → main, mergeable, НЕ смержен. +87/-9, 5 файлов. src/ НЕ тронут (только tests/ + pytest.ini + requirements.txt + ci.yml).
  • Мой прогон: 342 passed, 0 failed, 0 skipped (было 336 passed/6 skipped/4 failed).
  • БОНУС-находка Dev (глубже моей): в requirements.txt не было pytest-asyncio → 6 async-тестов test_orch10_states.py МОЛЧА скипались. То есть async-пути ORCH-10 (per-project старт конвейера) вообще не проверялись, CI светил зелёным. Теперь pytest-asyncio добавлен, asyncio_mode=auto, --strict-markers, ci.yml set -euo pipefail. Те 6 тестов теперь PASSED.

Порядок мержа (ждёт ОК Славы — НЕ мержу сама)

  1. PR #35 (ORCH-39) → main (база честно зелёная)
  2. PR #34 (ORCH-16) → main (фича единого коммента)
  3. Ребилд прод-контейнера на 8500 → фича реально заработает

Урок: CI-гейт был дырявым на самой важной логике

  • Две дыры в одном месте: (а) красные тесты пропускались, (б) async-тесты скипались из-за отсутствия pytest-asyncio. Оба светили зелёным CI. Для self-hosting честный гейт качества критичен — теперь закрыто в PR #35.

🏁 ФИНАЛ ДНЯ (05.06 вечер) — ORCH-16 в проде, ET-11 self-driving, ORCH-41 конфигурируемые модели

ORCH-39 + ORCH-16 ВЫКАЧЕНЫ В ПРОД

  • PR #35 (ORCH-39, тесты+CI) смержен (f375be24, 342 passed).
  • PR #34 (ORCH-16, единый формат коммента) rebase на main → 402 passed → смержен (8da571d).
  • Прод ребилжен из main: build_status_comment×9, frontmatter.py в контейнере, .env цел (23 строки), очередь чистая.
  • ORCH-39 → Done (PATCH HTTP 200). ⚠️ Способ выполнения Plane-PATCH из контейнера: скрипт /tmp/fix39.pydocker cp в orchestrator:/tmp/docker exec orchestrator python3. Вложенные os.popen внутри python-однострочника ломаются на экранировании (printenv ... not found) — НЕ делать, использовать heredoc+docker cp.

ORCH-40 заведена (Backlog, id cec9a5ef) — фикс root-прав deployer

  • Контейнер orchestrator работает под uid=0(root) → агенты пишут root-файлы в смонтированный хост-репо → ломает git под slin. При ребилде чинила руками (chown -R slin + git reset --hard + clean). Корневой фикс отложен (трогает рантайм агентов, выше риск).

АУДИТ БЭКЛОГА ORCH (обратный рассинхрон — НЕ найден, Done честные)

Проверила материально 14 «Done»-задач на проде (файл/контейнер/таблица/эндпоинт, не по статусу):

  • ORCH-16 (build_status_comment ×9 + frontmatter.py в контейнере)
  • ORCH-1 (таблица jobs, /queue живой)
  • ORCH-2 (git_worktree.py, worktree enduro+orchestrator)
  • ORCH-6 (projects.py, plane_project_id ×10)
  • ORCH-31 (контейнер orchestrator-staging Up)
  • ORCH-29 (PRODUCT_VISION.md + .pptx)
  • ORCH-34/35/36 (deploy-hook.log 18.9KB)
  • ⚠️ ORCH-36 нюанс (не баг статуса): числится Done «исполняемый самодеплой», но при ребилде ORCH-16 катила прод РУКАМИ. deploy-hook.log есть → механизм есть, но автоматизм self-deploy орка-на-себя стоит перепроверить при случае. Не срочно.
  • Итог: 40 задач = 25 Backlog, 15 Done. Все Done подтверждены материально. ORCH-39 поправлена Backlog→Done.

🎉🎉 ET-11 — ПЕРВЫЙ ПОЛНЫЙ SELF-DRIVING ET-ЗАДАЧИ ЧЕРЕЗ ОРК НА ЖИВОМ ПРОДЕ

  • ET-11 = «Healthcheck enduro-trails-app падает: в контейнере нет curl (ложный unhealthy)» (id e60715d4, work_item ET-015).
  • Диагноз (мой, лично): healthcheck = curl -f localhost:5556/api/health, но в контейнере нет ни curl, ни wget (образ голый, только python) → healthcheck ВСЕГДА fail, FailingStreak 3762. Само приложение здоровое (HTTP 200/7мс, живой трафик, RestartCount=0). Ложная тревога 31 час.
  • Конвейер прошёл ВЕСЬ цикл сам: analysis→architecture→development→review→testing→deploy→done. На гейте Approved остановился и дождался Славы (Слава заапрувил вручную в 15:17 — человек-в-петле сработал штатно, НЕ автопроскок).
  • РЕАЛЬНО ПОЧИНИЛ БАГ НА ПРОДЕ: PR #30 «use python urllib for container healthcheck» (заменили отсутствующий curl на python — ровно как я закладывала в ET-11). Смержен. PR #31 deploy (tag v0.0.7) смержен.
  • Результат на живом проде: контейнер enduro-trails-app-1 теперь Up (healthy), FailingStreak 0 (было 3762), HTTP 200/4мс. Прод НЕ упал даже без staging у ET.
  • Боевая обкатка ORCH-16: все агенты постили комменты единого формата (в логе comment added to ET-015 author=deployer ×2). Фича единого коммента работает в бою.
  • ⚠️ Риск был реальный: у ET НЕТ staging → deployer катил в живой прод 5556. Обошлось, но на будущее — для рискованных ET-задач держать стоп-флаг на deploy.

ORCH-41 — КОНФИГУРИРУЕМЫЕ МОДЕЛИ + EFFORT per-agent + per-project (фундамент мультипровайдеров ORCH-13)

Задача Славы: «модель выбирается в настройках, под каждого агента, с per-project override. Сделать сейчас.»

КОРЕНЬ почему агенты были на Opus 4.7 (разобрала лично, по боевым логам):

  • src/agents/launcher.py AGENT_CONFIGS: architect/reviewer → "model": "opus" (алиас!), остальные — модели НЕТ (CLI-дефолт).
  • Алиас opus в CLI 2.1.142 резолвится в claude-opus-4-7 (НЕ обновился на 4.8 авто). Подтверждено runs/102.log, runs/103.log → реально летит claude-opus-4-7.
  • 4.8 доступна — проверила прямым вызовом: claude-opus-4-8 / opus-4-8 / claude-opus-4-8-20250930 все subtype: success. CLI+аккаунт поддерживают, просто алиас не привязан.

Режимы работы CLI 2.1.142 (разведано, для будущего):

  • --effort low|medium|high|xhigh|max ГЛАВНЫЙ рычаг «качество vs стоимость» (аналог reasoning-бюджета). Раз 4.7=4.8 по цене, effort важнее версии.
  • --model (алиас/полное имя), --fallback-model (автофолбэк при overloaded, работает с --print), --permission-mode (acceptEdits/auto/bypassPermissions/plan/dontAsk), --bare (без хуков/LSP/memory).

Реализация (Dev, PR #36 feat/ORCH-41-agent-models, проверено мной лично):

  • src/config.py Settings: agent_model_default (дефолт claude-opus-4-8), agent_model_<agent> + agent_effort_<agent> (env ORCH_AGENT_MODEL_*, ORCH_AGENT_EFFORT_*). Паттерн как plane_bot_*.
  • src/projects.py ProjectConfig: поля agent_models + agent_efforts (dict, field(default_factory=dict) — frozen dataclass!), парсятся из projects_json (опционально).
  • resolve_agent_model/effort — приоритет: per-project → env per-agent → default → CLI-дефолт.
  • launcher.py: убран хардкод "model":"opus", модель+effort резолвятся.
  • Раскладка effort (согласовано Славой): думающие (analyst/architect/developer/reviewer) → high, механические (tester/deployer) → medium.
  • Дефолт модели = claude-opus-4-8 (Слава: «4.8 и 4.7 стоят одинаково, по дефолту 4.8»).
  • Проверено лично на проде: 423 passed (402+21), off-limits (gates/webhook/HMAC/queue) НЕ тронуты, резолвинг вживую: analyst/developer→opus-4-8/high, tester/deployer→opus-4-8/medium. Хардкод opus убран.
  • PR #36 — Слава дал ОК на мерж (последнее сообщение), мерж+ребилд ещё НЕ выполнены на момент флаша. После мержа: ребилд прода (учесть грабли root-прав ORCH-40), чтобы агенты реально поехали на 4.8/effort. Реальное переключение env прода — осознанно, с оглядкой на бюджет ORCH-38.

НОВЫЕ ORCH-ЗАДАЧИ дня:

  • ORCH-40 (id cec9a5ef) — фикс root-прав deployer, Backlog.
  • ORCH-41 (id 17f9a73f) — конфигурируемые модели per-agent, в работе → PR #36 готов, ждёт мержа.
  • ET-11 (id e60715d4) — healthcheck curl, Done через конвейер (исправлено на проде, v0.0.7).

КЛЮЧЕВЫЕ УРОКИ дня:

  • launcher.py model был алиасом opus → CLI резолвил в 4.7. Конфигурируемость (env+per-project) — правильное решение вместо хардкода версии.
  • effort = главный рычаг цены/качества при равной цене версий модели.
  • Plane-PATCH из контейнера: скрипт-файл + docker cp + docker exec, НЕ вложенные os.popen.
  • Зеркало /repos/orchestrator отстаёт от Gitea — источник истины при мерже = Gitea API, не локальный клон.
  • PR #34 мержить squash через Gitea, не force-push rebase (чище, mergeable=True).
  • Человек-в-петле (гейт Approved) работает штатно — ET-11 встала, дождалась ОК Славы, поехала. Не автопроскок.
  • Per-project state UUID (повтор для надёжности): ET in_progress b873d9eb, approved a519a341, rejected ba958f3c; ORCH in_progress e331bfb3, approved 63f2c8fe, rejected 4c769e90.

Артефакты дня:

  • ТЗ ORCH-41: tasks/orchestrator/DEV_TASK_ORCH41_AGENT_MODELS.md
  • ТЗ ORCH-39: tasks/orchestrator/DEV_TASK_ORCH39_FIX_WEBHOOK_TESTS.md
  • Отчёт ORCH-39: tasks/orchestrator/reports/dev-2026-06-05-orch39-webhook-tests.md
  • main HEAD после PR #34: 8da571d. PR #36 (ORCH-41) смержен 401bf66f (squash), прод ребилжен.

ORCH-41 ЗАКРЫТ + прод на 4.8 (финал)

  • PR #36 смержен (401bf66f), прод ребилжен из main (root-права починила превентивно — грабля ORCH-40, .env 23 строки цел).
  • РЕЗОЛВИНГ В ЖИВОМ КОНТЕЙНЕРЕ: analyst/architect/developer/reviewer→opus-4-8/high, tester/deployer→opus-4-8/medium. Алиас opus→4.7 устранён.
  • ORCH-41 → Done (Plane PATCH HTTP 200, минуя In Progress). prod /health=200, ET-задачи целы (17 в БД).

⚠️ ET-11 застряла в Testing → закрыта руками (Done) — ПРИЧИНА (не баг кода)

  • ET-11 (work_item ET-015) deploy завершился 15:43, БД орка стадия=done, фикс В ПРОДЕ (healthcheck healthy/streak 0, v0.0.7). НО Plane-статус застрял на Testing.
  • Корень: ET-11 ехала ДО мержа ORCH-16/39, на СТАРОМ stage_engine, где финальный переход deploy→done в Plane был дырявым. Фикс «set_issue_done всегда докручивает Plane Done» (stage_engine.py:269, через set_issue_doneget_project_states(pid)["done"], ORCH-10 резолвинг) приехал в прод только при ребилде под ORCH-41 (16:45).
  • Проверено: резолвинг done-state для ET вживую = 381a2833 , _resolve_project_id("ET-015")→ET-проект . Код ТЕПЕРЬ правильный — будущие задачи дойдут до Done сами. Это РАЗОВЫЙ хвост старого кода, не системная дыра.
  • ET-11 закрыта вручную Testing→Done (PATCH {"state":"381a2833"} HTTP 200, минуя In Progress).
  • УРОК: при ребилде прода лог контейнера обнуляется (docker logs показывает только с нового StartedAt) — старую историю стадий смотреть в БД tasks, не в логе.

🏆 ORCH-7 ЗАКРЫТА (Done) — ГЛАВНАЯ ВЕХА SELF-HOSTING

  • Зонтичная мета-задача «орк пилит сам себя через конвейер» → Done (Backlog→Done напрямую, минуя In Progress; PATCH HTTP 200, итог-коммент 201). id 8a40d57a-1a4f-42dd-8e8c-48635bfb0bb9.
  • Доказано в бою: ORCH-16 (первая самодоработка кода орка через весь конвейер) + ET-11 (self-driving для внешних проектов). Инфра: CI-гейт (ORCH-39), staging (ORCH-31..35), единый формат (ORCH-16), per-project статусы/модели (ORCH-10/41).
  • Остаток в дочерних: ORCH-36 (исполняемый самодеплой — сейчас прод ребилжу руками), ORCH-8 (самообучение).

🎯 ИТОГ ДНЯ 05.06 — 5 задач в Done: ORCH-7 (зонтик self-hosting), ORCH-16, ORCH-39, ORCH-41, ET-11. Орк официально умеет дорабатывать сам себя.

⚠️ КОНКУРЕНТНОСТЬ ОРКА — важный факт (разведано 05.06)

  • max_concurrency=1 (дефолт, env ORCH_MAX_CONCURRENCY не задан, config.py:48). Считается по JOBS (стадиям-агентам), НЕ по задачам: count_running_jobs()=COUNT(*) FROM jobs WHERE status=running.
  • СЛЕДСТВИЕ (критично): когда задача висит на гейте Approved (ждёт ревью человека) — её job уже done, СЛОТ СВОБОДЕН → орк может стартовать СЛЕДУЮЩУЮ задачу в том же репо даже при concurrency=1. «Гуськом до деплоя» НЕ гарантировано.
  • Обход Славы (решение): запускать задачи в одном репо ПО ОДНОЙ вручную (A→done→B). Надёжно обходит гонку мержа без доработки.
  • worktree (ORCH-2) изолирует ветки на разработке, НО при параллели в одном репо — гонка мержа на финише (обе ветки от main@X, первый влил→main@Y, второй конфликт/старый код). Для РАЗНЫХ репо параллель безопасна.

НОВЫЕ ORCH-ЗАДАЧИ в Backlog (05.06 вечер):

  • ORCH-40 (id cec9a5ef) — фикс root-прав deployer.
  • ORCH-41 (id 17f9a73f) — СДЕЛАНО/Done (конфигурируемые модели).
  • ORCH-42 (id 1564136e) — Telegram live-tracker режим bump (карточка падает вниз при обновлении, флаг ORCH_TRACKER_MODE=edit|bump, deleteMessage+sendMessage тихо). Слава: «bump нравится, пусть орк делает» — self-hosting через конвейер.
  • ORCH-43 (id d770a7a2) — безопасная параллель в одном репо: merge-gate + auto-rebase + re-test + single-flight per repo (не стартовать новую задачу пока предыдущая не дошла до done). Флаг ORCH_SERIALIZE_PER_REPO.

🔴 ИНЦИДЕНТ: ORCH-17 застряла на Analysis — ДВЕ причины (05.06 вечер ~17:00-17:35)

Карточка ORCH-17 висела на Analysis ~30 мин. Аналитики стартовали (run 107/109/111) и мгновенно умирали с пустым логом (0 байт), job 54 оставался running. Расследование выявило ДВА независимых корня:

Причина №1: 🔐 Авторизация claude слетела (ГЛАВНАЯ)

  • При ребилде контейнера под ORCH-41 (16:45) пересоздание сломало claude-auth:
    • /home/slin/.claude/.credentials.json стал owner=root (контейнер под uid=0 портит владельца смонтированных файлов — снова грабля ORCH-40!)
    • /root/.claude в контейнере = ПУСТЫШКА (claude под HOME=/root создал болванку .claude.json 293 байта, настоящие creds лежат в /home/slin/.claude* но туда claude не смотрел)
  • Симптом: claude → "Not logged in · Please run /login", is_error, 57ms, пустой stdout.
  • ФИКС (двойной):
    1. chown slin:slin /home/slin/.claude/.credentials.json (вернула владельца — токен внутри был ВАЛИДНЫЙ, дело только в правах)
    2. ПОСТОЯННЫЙ: в docker-compose.yml (prod+staging блоки) добавила монтирование /home/slin/.claude → /root/.claude и .claude.json → /root/.claude.json напрямую — переживёт рестарт (симлинки внутри контейнера НЕ переживают пересоздание).
  • ⚠️ ВАЖНО launcher.py: агенты запускаются с принудительным HOME=/home/slin (env в launcher, ~стр.290-320). НО claude всё равно умудрялся читать /root в части случаев → надёжнее смонтировать creds в ОБА места.

Причина №2: ⚙️ --effort гасит вывод claude (РЕГРЕССИЯ ORCH-41)

  • Флаг --effort <любое: low/medium/high/xhigh/max> + --print в CLI 2.1.142ПУСТОЙ stdout, even stderr молчит, мгновенно.
  • Изолировано матрицей тестов: без effort работает , с effort пусто (при любом значении).
  • ФИКС (временный): отключила effort в проде через .env: ORCH_AGENT_EFFORT_DEFAULT="" + пустые per-agent → резолвер вернёт пусто → флаг --effort НЕ добавляется в cmd. Модель claude-opus-4-8 ОСТАЛАСЬ.
  • TODO: завести ORCH-44 — корректная интеграция effort (возможно несовместим с --output-format json, или другой способ передачи). Сейчас effort отключён — не теряем фичу, просто не используем.

Грабля диагностики (моя):

  • Промежуточные ручные тесты claude обрывались по таймауту 40-50с → выглядело как «зависание», сбивало диагноз. Аналитик с system-prompt + task.md думает ~66с. При таймауте 90с+ всё работает. ⚠️ НЕ ставить timeout <90с при ручной проверке claude-агента с полным контекстом.

Команда launcher (рабочая, проверена E2E):

  • Полная команда launcher с HOME=/home/slin, --print, --output-format json, system-prompt + task.md, БЕЗ effort → работает (66с, 13 turns, is_error:false).

ИТОГ инцидента:

  • ORCH-17 разблокирована: аналитик отработал (run 114, лог 3487 байт), job 54→done, BRD/ТЗ/AC написаны, Plane-комменты запощены, state→in_review (c52e99b9). Ждёт Approved Славы.
  • Авторизация claude: починена + защищена монтированием (постоянно).
  • effort: отключён в проде (конвейер работает на 4.8 без effort).
  • ORCH-44 заведена (id d8ad65a7, Backlog) — «Надёжность запуска агента», 3 дыры: (1) preflight слеп к auth, (2) --effort фикс, (3) пустой лог → failed. Приоритет высокий.
  • 📋 TODO: апрувнуть ORCH-17 (ждёт Approved Славы).

🔍 ДЫРА В PREFLIGHT (разведано 05.06 — почему проверка не поймала сбой)

  • src/preflight.py проверяет ТОЛЬКО: (a) os.path.exists(CLAUDE_BIN), (b) claude --version (timeout 5s, без токенов).
  • ⚠️ claude --version ОТВЕЧАЕТ ДАЖЕ БЕЗ ЛОГИНА (версия — локальная инфа). Поэтому preflight=ok, а реальный запуск падает Not logged in. Preflight слеп к авторизации и к битым флагам (--effort).
  • Код прямым текстом: «🚫 deliberately do NOT do a prompt ping — would burn rate limit». Дизайн «дёшево, без токенов» → ценой слепоты к auth.
  • Фикс (ORCH-44): дешёвая проверка auth без токенов — читаемость+права .credentials.json + дата истечения OAuth (claudeAiOauth.expiresAt) внутри.

КРИТИЧНЫЕ УРОКИ на будущее:

  1. Ребилд/пересоздание контейнера orchestrator ЛОМАЕТ claude-auth (root-owned creds + /root/.claude пустышка). Теперь защищено монтированием в compose, НО проверять после каждого ребилда: docker exec orchestrator bash -c 'cd /tmp && HOME=/home/slin /opt/claude-code/bin/claude.exe --print "ОК"' (timeout 90с).
  2. claude бинарь: реальный путь /opt/claude-code/bin/claude.exe (смонтирован ro, 232MB). /usr/bin/claude (env ORCH_CLAUDE_BIN) в контейнере НЕ существует — это хостовый симлинк, launcher хардкодит правильный путь.
  3. --effort НЕ использовать с текущим CLI 2.1.142 + --print/--output-format json — гасит вывод. Ждёт ORCH-44.
  4. Пустой run-лог (0 байт) + job running + процесс мёртв = claude упал на старте (auth ИЛИ битый флаг). Смотреть: сначала auth (claude --print вручную), потом флаги (effort).

🏁 ORCH-17 — застряла ВТОРОЙ раз на гейте check_ci_green (RACE, разведано 05.06 18:1x)

  • После починки auth задача доехала dev→PR #37 (434 теста), но застряла на stage=development, agent_running=None, очередь пустая.
  • Корень — гонка CI: гейт check_ci_green опросил Gitea-CI ровно один раз в 17:58:54 → pending. CI дописал success в 17:58:55 (промах на 1 сек). Лог: Task 35: QG 'check_ci_green' not passed after developer: CI state: pending. Повторного опроса гейта НЕТ → задача висит насмерть с зелёным CI.
  • Проверка CI: combined state: success (push #46 + PR #47 оба success). Готова, гейт промахнулся.
  • Пинок вручную (безопасно, без ребилда/мержа): advance_stage(task_id=35, current_stage='development', repo='orchestrator', work_item_id='ORCH-017', branch='feature/ORCH-017-brd-plane-telegram', finished_agent='developer')advanced=True development->review, reviewer запущен (run 117, job 57). Поехала.
  • ORCH-45 заведена (id ab21608b-31e2-44fe-a2a5-99701a3a1ec3, Backlog, high) — check_ci_green должен ПОЛЛИТЬ CI с ретраем (pending→ждать N×15с, success→advance, failure→rollback, вечный pending→уведомить, не застревать молча). Родственна ORCH-44.

🛠️ Инфра-грабли прода (05.06)

  • В контейнере orchestrator НЕТ curl и НЕТ sqlite3 — запросы к Gitea/Plane/БД делать через python3 -c (urllib + sqlite3-модуль).
  • Таблица tasks: нет колонок status/role — реальные: id, plane_id, repo, branch, stage, agent_running, work_item_id, plane_issue_id, tracker_message_id, title, brd_review_started_at, brd_review_ended_at. Статус задачи = stage + Plane-state; статус job — в таблице jobs (колонка agent, не role).
  • Создание задачи Plane через скрипт: лучший способ — написать .py локально → base64 -w0ssh "echo <b64> | base64 -d > /tmp/x.py"docker cpdocker exec python3. base64 полностью обходит экранирование кириллицы/скобок (heredoc с кириллицей и ( падает с Syntax error). Локальный heredoc+scp НЕ работает — разные хосты.

🔁 ORCH-17 — петля dev↔review↔testing и разбор с Славой (05.06 вечер)

  • После пинка CI-гейта задача нарезала круги и упёрлась в max retries reached (MAX_DEVELOPER_RETRIES=3, stage_engine.py:56). Встала на development, ждёт человека.
  • Два разных заворота в петле: (a) tester FAIL check_tests_passed: No machine-readable verdict/status; (b) reviewer REQUEST_CHANGES — governance: дев протащил правку shared quality-gate src/qg/checks.py в косметическую задачу про ссылки (влияет на ВСЕ проекты общего прода, требует ADR по CLAUDE.md правило 2).
  • Ключевой вывод про правку гейта: дев починил РЕАЛЬНЫЙ баг ядра — _parse_tests_verdict читал только verdict:/status:, а промпт тестера велит писать result: PASS. Честный тестер → ложный FAIL → петля. Т.е. дев прав по сути, reviewer прав процедурно (shared-инфра без ADR).
  • Почему дев не понял ревьюера (корень для ORCH-46): орк при REQUEST_CHANGES шлёт деву только "Fix findings in 12-review.md" — без текста претензий (испорченный телефон); + противоречивые сигналы (tester "чини тесты" vs reviewer "не трогай gate"); + нет памяти между кругами (каждый dev = новый чистый агент).
  • Решение Славы (вариант А): из ORCH-17 убрать правку гейта (оставить только ссылки), фикс гейта — отдельной задачей следующей.
  • Новые задачи: ORCH-46 (id beaab0e7-eb49-41b9-b5e5-8d7246a3d9f1, Backlog, high) — передача замечаний деву; ORCH-47 (id 89d9a4b3-f80c-4387-b6f1-97b1f6dc9113, Backlog, high) — фикс check_tests_passed читать result: (с ADR, идёт следующей, готовый код-референс уже в ветке ORCH-017).
  • Дотолкивание ORCH-17: Dev-агент откатывает 2 файла к origin/main (src/qg/checks.py, tests/test_qg.py), остальное (ссылки/доки/ADR) остаётся → потом пинок гейта.

🪤 ORCH-17 — ДЕДЛОК после отката (05.06 поздний вечер) — НЕ повторять карусель

  • Откат дева (revert d615747, PR #37) убрал КОД гейта (src/qg/checks.py+tests/test_qg.py к origin/main), но оставил 2 doc-строки про ту правку → ревьюер снова REQUEST_CHANGES:
    • docs/architecture/README.md:61 — описывает что гейт читает result: (код уже не читает)
    • CHANGELOG.md:24 — запись про фикс гейта под ORCH-017 + ссылка на удалённые тесты
    • Обе строки принадлежат ORCH-47, в ORCH-017 их быть не должно. Урок: при откате кода чистить И доки/CHANGELOG, иначе рассинхрон код↔доки → ревьюер заворачивает.
  • ОБЪЕКТИВНЫЙ ДЕДЛОК (главное): тест-отчёт ORCH-017 написан с result: PASS (под новый контракт). Поэтому:
    • С фиксом гейта в ветке → reviewer заворачивает (governance/ADR).
    • Без фикса гейта (после отката) → check_tests_passed не видит result: → ложный «Tests FAILED» → откат.
    • Куда ни кинь — клин. ORCH-17 физически НЕ может пройти конвейер автономно, пока не приедет ORCH-47 (фикс result:).
  • ORCH-17 застревала 4-5 раз, каждый раз пинала руками — симптом: косметика (2 ссылки) ради полувечера возни, потому что орк сам не может (дыры ORCH-44/45/46/47).
  • Развилка, предложена Славе (ждёт решения):
    • 🅱️ Ручной мерж PR #37 (код ссылок готов, 434 теста зелёные, ревьюер: «технически корректно», претензии только процедурные) → ссылки уезжают в ядро, работают во всех проектах. Требует ОК Славы на мерж.
    • 🅲️ Сначала прогнать ORCH-47 (фикс гейта+ADR), потом ORCH-17 проедет сама — ещё один полный цикл ради готовых ссылок.
    • Стрим рекомендует 🅱️ — хватит доказывать конвейеру то, что готово.
  • Урок про мою роль: когда раз за разом пинаю гейты и чищу за девом вручную — это сигнал «орк не тянет автономно», честнее предложить ручной мерж/эскалацию, чем гонять карусель кругов.

ORCH-17 ЗАКРЫТА вручную + уроки в репо (05.06 поздний вечер)

  • Ручной merge PR #37 (merge-commit 26c6f267, merged=True, closed). Решение Славы «мержи» — выход из объективного дедлока (см. выше). Код ссылок (approve-ping links) уехал в ядро → работает во всех проектах (орк один на всех).
  • В смерженной ветке: src/notifications.py, src/config.py, тесты ссылок, ADR-001 на approve-links, полный пакет work-item доков. БЕЗ правки shared-гейта (она целиком в ORCH-47).
  • Прибрано: Plane ORCH-017 → Done; БД орка task 35 → stage=done, очередь пустая.
  • Уроки сохранены в репо: docs/history/LESSONS_ORCH-017.md через PR #38 → смержен в main. Папка docs/history/ — устоявшийся паттерн постмортемов (LESSONS_/BUGFIXES_/INCIDENT_*). Внутри: хронология 5 застреваний, 4 корневые дыры (P1→ORCH-45, P2→ORCH-46, P3→ORCH-47, P4→ORCH-44), главный урок про дедлок shared-инфры, урок про откат (код+доки+changelog вместе), урок про роль оператора (ручной merge вместо карусели).

🔑 Gitea API грабля (05.06)

  • create-PR эндпоинт Gitea требует заголовок Authorization: token <TOKEN>, а НЕ просто токен/другую форму → иначе 401. (merge-PR прошёл с другой формой, но на create Gitea строже.) Токен: ORCH_GITEA_TOKEN в env контейнера orchestrator.

🅲 План разравнивания дороги перед ORCH-47 (05.06, решение Славы «С»)

  • Слава выбрал вариант 🅲: сначала починить ORCH-45 (CI-гонка) Dev-агентом напрямую (мелкая гигиена конвейера, НЕ через сам конвейер), потом ORCH-47 гнать конвейером гладко.
  • Почему не конвейером: ORCH-44/45/46 ещё не в проде → ORCH-47 наступит на те же грабли (CI-гонка, испорченный телефон). И ORCH-47 меняет сам гейт check_tests_passed — «чинить весы стоя на них» → нужен ADR + ручной контроль на мерже.

ORCH-45 готова (CI-poll-retry) — ждёт мержа (05.06)

  • PR #39, ветка feature/ORCH-045-ci-poll-retry, открыт, НЕ мержен (ждёт ОК Славы — shared-гейт).
  • Dev-агент (tokenator/claude-opus-4-8) сделал: check_ci_green из single-shot → поллинг с ретраем (12 попыток × 10с): терминальные success/failure сразу, pending → ждёт, истёк лимит → явный False с причиной "CI still pending after Ns" (не виснет молча).
  • Параметры вынесены в config.py как env: ORCH_CI_POLL_MAX_ATTEMPTS / ORCH_CI_POLL_INTERVAL_S.
  • Файлы: src/qg/checks.py, src/config.py, тесты, docs/architecture/decisions/ADR-0004*, README-индекс, CHANGELOG.
  • Проверила лично: check_tests_passed НЕ тронут (grep пустой, ORCH-47 не задет); тесты прогнала своими руками — 62 passed (5 новых на гонку); набор файлов ровно разрешённый.
  • ⚠️ Сноска: при совместном прогоне с test_webhooks.py 4 теста падают — пре-существующая проблема изоляции settings (воспроизводится на чистом main без наших правок). К ORCH-45 не относится → потенциальная будущая задача (изоляция settings в тестах).
  • Следующий шаг: ждёт «мержи» Славы на #39 → закрыть ORCH-45 в Plane → запустить ORCH-47 конвейером.

ORCH-45 ЗАДЕПЛОЕНА в прод (05.06 ~20:30) — ребилд состоялся

  • PR #39 смержен (merge-commit 982698c4), ORCH-45 → Done в Plane.
  • Деплой потребовал ребилда образа (не просто рестарт): /app запечён в образ (build: ., COPY src/), не volume на repo. Деплой-хук с --no-build НЕ довозит код — обязательно docker compose build orchestrator.
  • prod орк = порт 8500 (status ok), staging = 8501, profile prod = пустой (стартует обычным up -d), network_mode: host. Деплой-хук по дефолту целит в STAGING (by design) — для прода нужны env TARGET_SERVICE=orchestrator TARGET_PORT=8500.
  • Новый поллящий гейт активен в /app (маркеры ci_poll = 4). Health 200.
  • claude-auth ПЕРЕЖИЛ ребилд (боевая проверка HOME=/home/slin claude.exe --print -> ОК; креды owner=slin 1000:1000). Инцидент НЕ повторился.

ГРАБЛЯ: хост-репо рассинхронизирован с git (агенты пишут под root) — 05.06

  • Хост-репо был на ветке feature/ORCH-045-..., не на main -> git pull origin main в хуке не подтягивал main.
  • Рабочая копия ЗАСЕЯНА untracked+modified файлами агентов под uid=0 (root-owned) -> git pull --ff-only падал Permission denied / would be overwritten, rm под slin не мог снести.
  • Решение (отработано): (1) sudo chown -R slin:slin /home/slin/repos/orchestrator; (2) проверить modified=MATCH-MAIN и untracked=IN-MAIN (дубликаты, ничего ценного); (3) git reset --hard origin/main + git clean -fd -e '*.bak*' -e '.deploy-prev-image-prod'; (4) build + up -d + health + проверка claude-auth.
  • Урок: перед деплоем орка ВСЕГДА сверять состояние хост-репо (ветка + git status). Хук сам это НЕ разруливает.

Бэклог high после 05.06 (порядок):

  • ORCH-45 — CI-poll-retry → PR #39 ГОТОВ, ждёт мержа
  • ORCH-47 — гейт check_tests_passed читать result: (с ADR) → следующая, конвейером после ровной дороги
  • ORCH-46 — испорченный телефон (передача замечаний деву: текст findings + склейка tester/reviewer + память между кругами)
  • ORCH-44 — надёжность запуска агента (preflight слеп к auth, --effort гасит вывод, пустой лог→failed)

ORCH-47 ЗАКРЫТА (фикс тестер-гейта result:) — 05.06 ~21:35

  • Прошёл конвейером: analyst→arch→dev→review→testing. Уловка-22: ORCH-47 чинит гейт check_tests_passed (читать result:), но в проде крутился старый гейт → не понимал result: PASS от тестера → 3 круга dev↔review↔tester → Blocked. Тот же дедлок-класс, что у ORCH-17.
  • Выход (🅱️): проверила diff+тесты сама (68 passed, +6 на result:), reviewer APPROVED v3, CI green → ручной merge PR #40 (5d04de9e) → ребилд прода (chown+reset+build+up+health+auth-check, claude-auth пережил) → умный гейт активен.
  • После деплоя пнула task 36 advance_stage(dev,finished=developer) → CI-гейт green → review→testing прошёл check_tests_passed (принял result: PASS!) → deploy-staging.
  • Встал на staging: check_staging_status: FAILED. Деплоер честно: 9/10 PASS, B6 Registry isolation FAIL (sandbox=NO, prod-ET/ORCH=YES BAD — staging видит боевые проекты, нарушает «staging только sandbox»). Деплоер НЕ стал натягивать зелёнку (вне мандата) → откат на development by design. К самому фиксу гейта отношения НЕ имеет — E2E против sandbox прошёл.
  • Решение Славы: B6 — отдельной задачей, ORCH-47 закрыть (код в проде, работает).
  • ORCH-047 → Done в Plane; task 36 → done в БД. Gitea merge-грабля подтвердилась снова (нужен Authorization: token <…>; heredoc через ssh+docker глотает вывод → скрипт+base64+docker cp).
  • 🆕 ORCH-048 заведена (id 7fb4f0f0-576c-46e7-b7ec-84909c99fffe, Backlog): B6 staging registry isolation — реестр staging должен видеть только sandbox; гипотеза — src.projects.known_plane_project_ids() читает host-env. Не блокер фикса гейта.

Прод-гейты сейчас (после деплоев 05.06):

  • check_ci_green — поллинг с ретраем (ORCH-45, в проде)
  • check_tests_passed — читает result:/verdict:/status: (ORCH-47, в проде)
  • Бэклог high: ORCH-48 (staging isolation), ORCH-46 (испорченный телефон), ORCH-44 (надёжность запуска агента)