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

513 lines
38 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 2026-06-02 — Daily Log
## ET-009: GPS Sources (EnduroRussia + Wikiloc) — Pipeline Completed 🎉
### Pipeline stages (all passed):
1.**analysis** — analyst (Sonnet), produced BRD, TRZ, acceptance criteria, test plans
2.**architecture** — architect v2 (Opus 4.7), ADRs + infrastructure requirements
3.**development** — developer (Opus 4.7 1M), 19 files, 1287 lines. Commit `3577ff3`
4.**review** — reviewer (Opus), found P1 bugs F-01, F-02
5.**development fix** — developer (Sonnet), commit `fc03746`: 159 lines in `gps_tracks.js`
6.**review round 2** — reviewer (Opus), APPROVED, only P3 minors remain
7.**testing** — tester (Sonnet), 25/25 pytest + 24/24 js tests PASS
8.**deploy** — deployer (Sonnet), PR #16 merged, image rebuilt, collector running
### Key results:
- **EnduroRussia parser**: `enduro_russia.py` — scraping + GPX parsing
- **Wikiloc parser**: `wikiloc.py` — Wikiloc GPX integration
- **Dynamic source filters (F-01)**: `_buildGpsFiltersUI` pulls source_id from `/api/gps-tracks/health.tracks_by_source`
- **Attribution fix (F-02)**: attribution set at `addSource` time via `_ensureGpsSources(map, attribution)`, not by mutating `src.attribution` (MapLibre AttributionControl issue)
- **Collector running**: 305 EnduroRussia tracks, fetching one per 5s, 34+ already in DB
- **Commits**: `eaa6b4c` (analyst), `4be7fbf` (architect), `3577ff3` (dev), `fc03746` (dev fix)
- **PR**: #16 merged → main at `b5ba7b2`
### Known issues:
- **Nginx 502** on external URL (port 5556 routing) — not ET-009 specific, needs nginx config fix
- **gps_sources.yaml** — ADR files inside Docker image (not volume), old image had `proposed`; fixed by rebuilding image
---
## Orchestrator Issues Discovered
### Critical bug: Launcher Popen broken inside container
- All Claude processes (claude.exe) become zombies when launched via orchestrator's Python subprocess
- Root cause: `docker` binary not available inside container, Popen flags wrong
- **Workaround established**: base64-encode Python launch script → ssh to host → decode → docker cp → docker exec python3
- This pattern avoids shell quoting hell
### Other orchestrator bugs:
- `.task-arch.md`, `.task-dev.md`, `.task-review.md` not regenerated per-stage (carry over from previous task)
- Workaround: manually rewrite these files before each stage launch
- No CI configured in Gitea → every commit triggers false "CI failed" webhook alert
- Tokenator API: all 8 models down for maintenance (June 1, still down June 2 morning)
### Agent launch manual pattern:
```bash
# 1. Base64-encode the Python launch script
cat launch_script.py | base64 -w0
# 2. SSH to host, decode, cp to container, exec
ssh slin@82.22.50.71 "
echo 'BASE64_STRING' | base64 -d > /tmp/launch.py
docker cp /tmp/launch.py orchestrator:/tmp/launch.py
docker exec orchestrator python3 /tmp/launch.py
"
```
---
## Models Configuration Changes
- **DeepSeek V4 models added** to openclaw.json:
- `openrouter/deepseek/deepseek-v4`
- `openrouter/deepseek/deepseek-v4-pro`
- `openrouter/deepseek/deepseek-v4-flash`
- Current model for main agent: `openrouter/deepseek/deepseek-v4-pro`
---
## User Preferences (re-confirmed during ET-009)
- **User wants visibility at each pipeline stage** — frustrated by silent automated advances
- **User wants to approve before advancing**: analyst → `:approved:` → architect → developer → reviewer → tester → deployer
- Only analyst requires manual `:approved:`; architect, reviewer, tester should auto-advance but notify
- Deployer should ask before deploying
---
## Глубокий аудит оркестратора (мультиагенты) — 2026-06-02
### Проведено
- **Аудит кода:** `tasks/multi-agent/AUDIT_2026-06-02.md` — 3 BLOCKER, 5 SERIOUS, 7 MEDIUM, 5 LOW
- **Аудит документации:** `tasks/multi-agent/DOCS_AUDIT_2026-06-02.md`
- **ТЗ для Dev:** `tasks/multi-agent/DEV_TASK_ORCHESTRATOR_FIXES.md` (9 задач)
### Корневые баги (BLOCKER)
- **B-1:** нет `docker` бинарника в контейнере orchestrator → `_write_task_file` через `docker run` падает молча → агент читает старый `.task-*.md`
- **B-2:** `Popen` + PIPE + daemon-поток → claude-зомби, `exit_code` теряется (в БД `exit=None` для всех ET-009)
- **B-3:** `.task-*.md` тащатся между задачами + коммитятся в git
### Ключевая находка по докам
- **P1 zombie из `LESSONS_ET006.md` (22 мая) = мой B-2.** Баг известен 11 дней, не починен → повторился на ET-008/009
- Системная проблема: lessons пишутся, но не конвертируются в задачи
- Расхождение код↔док: README говорит review QG=`check_review_approved`, код использует `check_reviewer_verdict`
### Dev-агент запущен
- Model: **tokenator/claude-opus-4-8** (modelApplied: true)
- taskName: `orch_fixes`, runId: 2f18ca88
- Deploy-хук `/home/slin/bin/enduro-deploy-hook.sh` СУЩЕСТВУЕТ и корректен
- В orchestrator были незакоммиченные правки (M launcher/config/notifications/plane_sync) — Dev разберёт в Task 1
## ET-009 Artifacts
- **Plane issue**: `64e98247-509f-4c30-9955-a5531ab7d1ee` (sequence #5)
- **Plane workspace**: `ag_proj`, project `7a79f0a9-5278-49cd-9007-9a338f238f9c`
- **Orchestrator DB**: task_id=16
- **Repo**: `/home/slin/repos/enduro-trails` on mva154
- **Docs**: `docs/work-items/ET-009/` — 00 through 14 (BRD, TRZ, acceptance, tests, ADRs, infra, data, risks, review, test report, deploy)
- **Docker**: container `enduro-trails`, image rebuilt with new ADR files, collector running
# 2026-06-02 — Daily Log
## ET-009: GPS Sources (EnduroRussia + Wikiloc) — Pipeline Completed 🎉
### Pipeline stages (all passed):
1.**analysis** — analyst (Sonnet), produced BRD, TRZ, acceptance criteria, test plans
2.**architecture** — architect v2 (Opus 4.7), ADRs + infrastructure requirements
3.**development** — developer (Opus 4.7 1M), 19 files, 1287 lines. Commit `3577ff3`
4.**review** — reviewer (Opus), found P1 bugs F-01, F-02
5.**development fix** — developer (Sonnet), commit `fc03746`: 159 lines in `gps_tracks.js`
6.**review round 2** — reviewer (Opus), APPROVED, only P3 minors remain
7.**testing** — tester (Sonnet), 25/25 pytest + 24/24 js tests PASS
8.**deploy** — deployer (Sonnet), PR #16 merged, image rebuilt, collector running
### Key results:
- **EnduroRussia parser**: `enduro_russia.py` — scraping + GPX parsing
- **Wikiloc parser**: `wikiloc.py` — Wikiloc GPX integration
- **Dynamic source filters (F-01)**: `_buildGpsFiltersUI` pulls source_id from `/api/gps-tracks/health.tracks_by_source`
- **Attribution fix (F-02)**: attribution set at `addSource` time via `_ensureGpsSources(map, attribution)`, not by mutating `src.attribution` (MapLibre AttributionControl issue)
- **Collector running**: 305 EnduroRussia tracks, fetching one per 5s, 34+ already in DB
- **Commits**: `eaa6b4c` (analyst), `4be7fbf` (architect), `3577ff3` (dev), `fc03746` (dev fix)
- **PR**: #16 merged → main at `b5ba7b2`
### Known issues:
- **Nginx 502** on external URL (port 5556 routing) — not ET-009 specific, needs nginx config fix
- **gps_sources.yaml** — ADR files inside Docker image (not volume), old image had `proposed`; fixed by rebuilding image
---
## Orchestrator Issues Discovered
### Critical bug: Launcher Popen broken inside container
- All Claude processes (claude.exe) become zombies when launched via orchestrator's Python subprocess
- Root cause: `docker` binary not available inside container, Popen flags wrong
- **Workaround established**: base64-encode Python launch script → ssh to host → decode → docker cp → docker exec python3
- This pattern avoids shell quoting hell
### Other orchestrator bugs:
- `.task-arch.md`, `.task-dev.md`, `.task-review.md` not regenerated per-stage (carry over from previous task)
- Workaround: manually rewrite these files before each stage launch
- No CI configured in Gitea → every commit triggers false "CI failed" webhook alert
- Tokenator API: all 8 models down for maintenance (June 1, still down June 2 morning)
### Agent launch manual pattern:
```bash
# 1. Base64-encode the Python launch script
cat launch_script.py | base64 -w0
# 2. SSH to host, decode, cp to container, exec
ssh slin@82.22.50.71 "
echo 'BASE64_STRING' | base64 -d > /tmp/launch.py
docker cp /tmp/launch.py orchestrator:/tmp/launch.py
docker exec orchestrator python3 /tmp/launch.py
"
```
---
## Models Configuration Changes
- **DeepSeek V4 models added** to openclaw.json:
- `openrouter/deepseek/deepseek-v4`
- `openrouter/deepseek/deepseek-v4-pro`
- `openrouter/deepseek/deepseek-v4-flash`
- Current model for main agent: `openrouter/deepseek/deepseek-v4-pro`
---
## User Preferences (re-confirmed during ET-009)
- **User wants visibility at each pipeline stage** — frustrated by silent automated advances
- **User wants to approve before advancing**: analyst → `:approved:` → architect → developer → reviewer → tester → deployer
- Only analyst requires manual `:approved:`; architect, reviewer, tester should auto-advance but notify
- Deployer should ask before deploying
---
## Глубокий аудит оркестратора (мультиагенты) — 2026-06-02
### Проведено
- **Аудит кода:** `tasks/multi-agent/AUDIT_2026-06-02.md` — 3 BLOCKER, 5 SERIOUS, 7 MEDIUM, 5 LOW
- **Аудит документации:** `tasks/multi-agent/DOCS_AUDIT_2026-06-02.md`
- **ТЗ для Dev:** `tasks/multi-agent/DEV_TASK_ORCHESTRATOR_FIXES.md` (9 задач)
### Корневые баги (BLOCKER)
- **B-1:** нет `docker` бинарника в контейнере orchestrator → `_write_task_file` через `docker run` падает молча → агент читает старый `.task-*.md`
- **B-2:** `Popen` + PIPE + daemon-поток → claude-зомби, `exit_code` теряется (в БД `exit=None` для всех ET-009)
- **B-3:** `.task-*.md` тащатся между задачами + коммитятся в git
### Ключевая находка по докам
- **P1 zombie из `LESSONS_ET006.md` (22 мая) = мой B-2.** Баг известен 11 дней, не починен → повторился на ET-008/009
- Системная проблема: lessons пишутся, но не конвертируются в задачи
- Расхождение код↔док: README говорит review QG=`check_review_approved`, код использует `check_reviewer_verdict`
### Dev-агент — РЕЗУЛЬТАТ (ПРИНЯТО ✅)
- Model: **tokenator/claude-opus-4-8** (modelApplied: true), taskName `orch_fixes`, runId 2f18ca88
- **Починено:** B-1, B-2, B-3, S-5, S-1, M-1 + 2 доп-фикса найденных в бою:
- **git safe.directory** в Dockerfile (без него auto-commit падал на «dubious ownership»)
- **init:true** в compose (tini как PID 1, добивает grandchild-зомби от claude/node)
- **11 коммитов** в main orchestrator (Conventional Commits), запушены
- **Тесты:** 26 passed (launcher + qg) — гонял в контейнере (хостовый .venv сломан, symlinks на py3.10)
- **Автономный прогон:** через `launcher.launch()`, 0 зомби, auto commit+push сработал
- **Доки обновлены:** ARCHITECTURE, README (QG-таблица), `BUGFIXES_2026-06-02.md`
### Моя независимая проверка (на сервере, не на слово)
- ✅ health `{"status":"ok"}`, 0 defunct процессов
- ✅ B-1: `_write_task_file` через `open()` + raise (код подтверждён)
- ✅ S-5: verdict читается только из YAML frontmatter
- ✅ 26 тестов зелёные
- ✅ init:true в compose, PR #19 open+mergeable
### ⚠️ ТРЕБУЕТ ДЕЙСТВИЯ
- **PR #19** (enduro-trails: `.gitignore` + `reviewer.md`) — ветка main защищена, нужен merge человеком. Спросила Славу — ждёт ответа.
### Честные расхождения (Dev не скрыл)
- Хостовый `.venv` сломан (symlinks py3.10) — тесты в контейнере
- `test_webhooks.py` — 9 pre-existing падений (401/signature), были ДО правок, вне scope
- **Вне scope (отдельные задачи на потом):** S-2/S-3 (rollback в shared-репо), S-4 (git worktree per task), M-3 (дубль `_try_advance_stage`), **F-2b (очередь задач вместо daemon-потоков — главный целевой рефактор)**, M-7 (идемпотентность webhook)
### Открытый вопрос Славе
- Смержить PR #19?
- Завести в Plane оставшиеся задачи (worktree, очередь задач)?
## ET-009 Artifacts
- **Plane issue**: `64e98247-509f-4c30-9955-a5531ab7d1ee` (sequence #5)
- **Plane workspace**: `ag_proj`, project `7a79f0a9-5278-49cd-9007-9a338f238f9c`
- **Orchestrator DB**: task_id=16
- **Repo**: `/home/slin/repos/enduro-trails` on mva154
- **Docs**: `docs/work-items/ET-009/` — 00 through 14 (BRD, TRZ, acceptance, tests, ADRs, infra, data, risks, review, test report, deploy)
- **Docker**: container `enduro-trails`, image rebuilt with new ADR files, collector running
---
## ORCH-2 [S-4] git worktree — ПРИНЯТО ✅ (2026-06-02)
### Dev-агент (Opus 4.8 Tokenator)
- taskName: `orch2_worktree`, TЗ: `tasks/orchestrator/DEV_TASK_ORCH2_WORKTREE.md`
- НОВЫЙ файл: `src/git_worktree.py` (5 функций: `_safe`, `get_worktree_path`, `ensure_worktree`, `remove_worktree`, `cleanup_orphaned`)
- Изменены: `src/agents/launcher.py` (worktree-пути), `src/qg/checks.py` (чтение артефактов + тесты из worktree), `src/webhooks/gitea.py` (git-операция), `src/config.py` (+worktrees_dir)
- Тесты: **37 passed** (9 fail = pre-existing webhook 401, baseline — не изменилось)
- **Тест изоляции (live):** два worktree на независимые ветки → A≠B, shared repo не тронут ✅
- PR #1 в orchestrator: open, mergeable
### Замечен побочный эффект (важно!)
В shared `/repos/enduro-trails` обнаружена ветка **`ET-012-m-3-stage-engine`** с авто-коммитом от **analyst, run_id=52**. Это M-3 (ORCH-4) — оркестратор САМ запустил analyst и тот отработал АВТОНОМНО. Но создал задачу в неправильном репо (enduro-trails вместо orchestrator), потому что default_repo всё ещё enduro-trails. Доказывает: автономность починена, но multi-repo пока не настроено.
### Обсуждение self-hosting оркестратора
- Слава заметил: оркестратор пилится Dev-агентом в обход своего конвейера
- Причина: bootstrap-проблема — нельзя чинить сломанную машину, пока едешь на ней
- Цель на будущее: self-hosting (оркестратор берёт свои же задачи через полный конвейер)
- Нужна задача ORCH-6: self-hosting (после ORCH-1 очереди задач + multi-repo)
### Нейминг — финальное решение
- Единое имя: **`orchestrator`**
- Gitea-репо переименован `agent-dev``orchestrator`
- Plane-проект `orchestrator` (identifier `ORCH`, id `8da6aa25-a60e-44d6-a1e2-d8ae59aa7d6a`)
- Workspace `tasks/multi-agent/``tasks/orchestrator/`
- Папка/контейнер/compose уже были `orchestrator`
- Plane задачи: ORCH-1 (F-2b), ORCH-2 (S-4), ORCH-3 (S-2/S-3), ORCH-4 (M-3), ORCH-5 (M-7)
### Открытые вопросы Славе
1. Смержить PR #19 (enduro-trails)?
2. Смержить PR #1 (orchestrator worktree)?
---
## ИНЦИДЕНТ: Plane-webhook авто-запустил конвейер по всем ORCH-1..7 (2026-06-02 19:00)
### Что случилось
- Создала в Plane задачи ORCH-1..7 — **Plane-webhook поймал каждую и авто-запустил конвейер** (analyst→architect, auto-commit)
- Всё ушло в **неправильный репо enduro-trails** (`plane.py:91` hardcode `repo=settings.default_repo`), наплодило мусор ET-010..016
- Корень: Plane-webhook (id `93f0c342-a614-4248-9d0f-c107276f5620`) срабатывает на ЛЮБ\u041eЕ issue в workspace, без фильтра по проекту
- ⚠️ **ПОЗИТИВ:** автономность реально работает — analyst exit=0, auto-commit, worktree (ORCH-2) сработал
### Меры (сделано)
- 🛡️ **Plane-webhook ДЕАКТИВИРОВАН** в Plane postgres: `UPDATE webhooks SET is_active=false`. Проверено: `is_active=f`
- Plane postgres: контейнер `plane-app-plane-db-1`, `PGPASSWORD=plane`, db `plane`, user `plane`, table `webhooks`
- Обратно включить после ORCH-6: `UPDATE webhooks SET is_active=true WHERE id=...`
- 🧹 Вычищено: все ветки ET-010..016 (git local+remote, 204), worktree `_wt/enduro-trails/*` (root-owned → sudo rm), тестовые iso-A/iso-B, tasks≥19 в БД орка, agent_runs≥19
- Plane чист: orchestrator=7 (ORCH-1..7), enduro=5 (родные). Junk ET-issues в Plane не было (орк генерил ET-номера сам в git+БД)
- Заметка на сервере: `orchestrator/docs/INCIDENT_2026-06-02_webhook_autorun.txt`
### ROOT FIX = ORCH-6 (multi-repo)
- `plane.py:91` `repo=settings.default_repo` → нужен фильтр по `plane_project_id` + маппинг repo per project
- Пока ORCH-6 не сделан — webhook ДЕРЖАТЬ ВЫКЛЮЧЕННЫМ
### Открытые вопросы
- Смержить PR #19 (enduro-trails) + PR #1 (orchestrator worktree)?
### Нейминг — финальное решение
- Единое имя: **`orchestrator`**
- Gitea-репо переименован `agent-dev``orchestrator`
- Plane-проект `orchestrator` (identifier `ORCH`, id `8da6aa25-a60e-44d6-a1e2-d8ae59aa7d6a`)
- Workspace `tasks/multi-agent/``tasks/orchestrator/`
- Папка/контейнер/compose уже были `orchestrator`
- Plane задачи: ORCH-1 (F-2b), ORCH-2 (S-4), ORCH-3 (S-2/S-3), ORCH-4 (M-3), ORCH-5 (M-7)
### Открытые вопросы Славе
1. Смержить PR #19 (enduro-trails)?
2. Смержить PR #1 (orchestrator worktree)?
---
## ИНЦИДЕНТ: Plane-webhook авто-запустил конвейер по всем ORCH-1..7 (2026-06-02 19:00)
### Что случилось
- Создала в Plane задачи ORCH-1..7 — **Plane-webhook поймал каждую и авто-запустил конвейер** (analyst→architect, auto-commit)
- Всё ушло в **неправильный репо enduro-trails** (`plane.py:91` hardcode `repo=settings.default_repo`), наплодило мусор ET-010..016
- Корень: Plane-webhook (id `93f0c342-a614-4248-9d0f-c107276f5620`) срабатывает на ЛЮБ\u041eЕ issue в workspace, без фильтра по проекту
- ⚠️ **ПОЗИТИВ:** автономность реально работает — analyst exit=0, auto-commit, worktree (ORCH-2) сработал
### Меры (сделано)
- 🛡️ **Plane-webhook ДЕАКТИВИРОВАН** в Plane postgres: `UPDATE webhooks SET is_active=false`. Проверено: `is_active=f`
- Plane postgres: контейнер `plane-app-plane-db-1`, `PGPASSWORD=plane`, db `plane`, user `plane`, table `webhooks`
- Обратно включить после ORCH-6: `UPDATE webhooks SET is_active=true WHERE id=...`
- 🧹 Вычищено: все ветки ET-010..016 (git local+remote, 204), worktree `_wt/enduro-trails/*` (root-owned → sudo rm), тестовые iso-A/iso-B, tasks≥19 в БД орка, agent_runs≥19
- Plane чист: orchestrator=7 (ORCH-1..7), enduro=5 (родные). Junk ET-issues в Plane не было (орк генерил ET-номера сам в git+БД)
- Заметка на сервере: `orchestrator/docs/INCIDENT_2026-06-02_webhook_autorun.txt`
### ROOT FIX = ORCH-6 (multi-repo)
- `plane.py:91` `repo=settings.default_repo` → нужен фильтр по `plane_project_id` + маппинг repo per project
- Пока ORCH-6 не сделан — webhook ДЕРЖАТЬ ВЫКЛЮЧЕННЫМ
### Открытые вопросы
- Смержить PR #19 (enduro-trails) + PR #1 (orchestrator worktree)?
---
## ORCH-6 (Multi-repo) — Dev-прогон (2026-06-02 ~19:20-19:28)
### ТЗ
- Файл: `tasks/orchestrator/DEV_TASK_ORCH6_MULTIREPO.md` (снайперское, все точки кода file:line собраны Стрим заранее)
- Цель: реестр проектов (Plane id→repo+prefix) + фильтр webhook по проекту + resolve repo + plane_sync в правильный проект + prefix per project. Закрывает корень инцидента, снимает предохранитель.
- Маппинг по умолчанию: enduro `7a79f0a9-...`→repo enduro-trails/ET; orchestrator `8da6aa25-...`→repo orchestrator/ORCH
### Прогон 1 (упал по таймауту LLM на Task 2, не вина кода) — но сделал ~75%, ФУНКЦИОНАЛ РАБОТАЕТ
✅ Готово (Task 1-5), проверено вживую:
- `src/projects.py` (4607 байт) — ProjectConfig + 4 резолвера + дефолт-реестр
- plane.py — фильтр по проекту (unknown→ignored) + resolve repo
- db.py — `get_next_work_item_id(repo, prefix)` per project (ORCH-001 vs ET-010)
- plane_sync.py — `_resolve_project_id`, параметризация (обратно совместимо)
- gitea.py — unknown repo→ignored (3 хэндлера)
- **Resolve-тест в контейнере прошёл:** orchestrator→orchestrator/ORCH, enduro→enduro-trails/ET, unknown→None ✅
- Все файлы компилируются; тесты 37 passed / 9 failed (те же pre-existing 401/signature, baseline не сломан)
НЕ доделано (Task 6-7): тесты test_projects/test_plane_webhook, коммит, PR, пересборка, доки. Всё в working tree (не закоммичено).
### Решение: НЕ начинать заново, дослать Dev добивку (Task 6-7) — рабочие 75% терять глупо из-за инфра-таймаута
- Запущен 2-й прогон (taskName `orch6_finish`/добивка), session subagent `24ac376a...`
- ⚠️ Дубль-событие о падении прогона 1 (subagent `080bc9bc...`) прилетело позже — уже обработано, NO_REPLY
### КРИТИЧНО на потом
- 🚫 Webhook ОСТАЁТСЯ выключенным до моего финального ревью фильтра (иначе риск повторить инцидент)
- Включить webhook (`is_active=true`) — мой шаг ПОСЛЕ проверки что фильтр реально режет unknown-проекты
- Tokenator API: жив, ключ в `/home/slin/openclaw/data/.env` (НЕ в orchestrator/.env). Ключ содержит `|` — bash sed/grep его режет, брать через Python
- Plane API токен (60 симв) в orchestrator/.env РАБОЧИЙ — баг был в bash sed-парсинге, через Python HTTP 200
- Тесты орка — ТОЛЬКО в контейнере через образ (хостовый .venv сломан): `IMG=$(docker inspect orchestrator --format '{{.Config.Image}}'); docker run --rm -v /home/slin/repos/orchestrator:/code -w /code --entrypoint python3 $IMG -m pytest tests/ -q`
- Workspace `tasks/multi-agent/``tasks/orchestrator/`
- Папка/контейнер/compose уже были `orchestrator`
- Plane задачи: ORCH-1 (F-2b), ORCH-2 (S-4), ORCH-3 (S-2/S-3), ORCH-4 (M-3), ORCH-5 (M-7)
### Открытые вопросы Славе
1. Смержить PR #19 (enduro-trails)?
2. Смержить PR #1 (orchestrator worktree)?
---
## ИНЦИДЕНТ: Plane-webhook авто-запустил конвейер по всем ORCH-1..7 (2026-06-02 19:00)
### Что случилось
- Создала в Plane задачи ORCH-1..7 — **Plane-webhook поймал каждую и авто-запустил конвейер** (analyst→architect, auto-commit)
- Всё ушло в **неправильный репо enduro-trails** (`plane.py:91` hardcode `repo=settings.default_repo`), наплодило мусор ET-010..016
- Корень: Plane-webhook (id `93f0c342-a614-4248-9d0f-c107276f5620`) срабатывает на ЛЮБ\u041eЕ issue в workspace, без фильтра по проекту
- ⚠️ **ПОЗИТИВ:** автономность реально работает — analyst exit=0, auto-commit, worktree (ORCH-2) сработал
### Меры (сделано)
- 🛡️ **Plane-webhook ДЕАКТИВИРОВАН** в Plane postgres: `UPDATE webhooks SET is_active=false`. Проверено: `is_active=f`
- Plane postgres: контейнер `plane-app-plane-db-1`, `PGPASSWORD=plane`, db `plane`, user `plane`, table `webhooks`
- Обратно включить после ORCH-6: `UPDATE webhooks SET is_active=true WHERE id=...`
- 🧹 Вычищено: все ветки ET-010..016 (git local+remote, 204), worktree `_wt/enduro-trails/*` (root-owned → sudo rm), тестовые iso-A/iso-B, tasks≥19 в БД орка, agent_runs≥19
- Plane чист: orchestrator=7 (ORCH-1..7), enduro=5 (родные). Junk ET-issues в Plane не было (орк генерил ET-номера сам в git+БД)
- Заметка на сервере: `orchestrator/docs/INCIDENT_2026-06-02_webhook_autorun.txt`
### ROOT FIX = ORCH-6 (multi-repo)
- `plane.py:91` `repo=settings.default_repo` → нужен фильтр по `plane_project_id` + маппинг repo per project
- Пока ORCH-6 не сделан — webhook ДЕРЖАТЬ ВЫКЛЮЧЕННЫМ
### Открытые вопросы
- Смержить PR #19 (enduro-trails) + PR #1 (orchestrator worktree)?
---
## ORCH-6 (Multi-repo) — Dev-прогон (2026-06-02 ~19:20-19:28)
### ТЗ
- Файл: `tasks/orchestrator/DEV_TASK_ORCH6_MULTIREPO.md` (снайперское, все точки кода file:line собраны Стрим заранее)
- Цель: реестр проектов (Plane id→repo+prefix) + фильтр webhook по проекту + resolve repo + plane_sync в правильный проект + prefix per project. Закрывает корень инцидента, снимает предохранитель.
- Маппинг по умолчанию: enduro `7a79f0a9-...`→repo enduro-trails/ET; orchestrator `8da6aa25-...`→repo orchestrator/ORCH
### Прогон 1 (упал по таймауту LLM на Task 2, не вина кода) — но сделал ~75%, ФУНКЦИОНАЛ РАБОТАЕТ
✅ Готово (Task 1-5), проверено вживую:
- `src/projects.py` (4607 байт) — ProjectConfig + 4 резолвера + дефолт-реестр
- plane.py — фильтр по проекту (unknown→ignored) + resolve repo
- db.py — `get_next_work_item_id(repo, prefix)` per project (ORCH-001 vs ET-010)
- plane_sync.py — `_resolve_project_id`, параметризация (обратно совместимо)
- gitea.py — unknown repo→ignored (3 хэндлера)
- **Resolve-тест в контейнере прошёл:** orchestrator→orchestrator/ORCH, enduro→enduro-trails/ET, unknown→None ✅
- Все файлы компилируются; тесты 37 passed / 9 failed (те же pre-existing 401/signature, baseline не сломан)
НЕ доделано (Task 6-7): тесты test_projects/test_plane_webhook, коммит, PR, пересборка, доки. Всё в working tree (не закоммичено).
### Решение: НЕ начинать заново, дослать Dev добивку (Task 6-7) — рабочие 75% терять глупо из-за инфра-таймаута
- Запущен 2-й прогон (taskName `orch6_finish`/добивка), session subagent `24ac376a...`
- ⚠️ Дубль-событие о падении прогона 1 (subagent `080bc9bc...`) прилетело позже — уже обработано, NO_REPLY
### КРИТИЧНО на потом
- 🚫 Webhook ОСТАЁТСЯ выключенным до моего финального ревью фильтра (иначе риск повторить инцидент)
- Включить webhook (`is_active=true`) — мой шаг ПОСЛЕ проверки что фильтр реально режет unknown-проекты
- Tokenator API: жив, ключ в `/home/slin/openclaw/data/.env` (НЕ в orchestrator/.env). Ключ содержит `|` — bash sed/grep его режет, брать через Python
- Plane API токен (60 симв) в orchestrator/.env РАБОЧИЙ — баг был в bash sed-парсинге, через Python HTTP 200
- Тесты орка — ТОЛЬКО в контейнере через образ (хостовый .venv сломан): `IMG=$(docker inspect orchestrator --format '{{.Config.Image}}'); docker run --rm -v /home/slin/repos/orchestrator:/code -w /code --entrypoint python3 $IMG -m pytest tests/ -q`
### ✅ ORCH-6 ДОДЕЛАН (прогон 2, ~19:35) — проверено мной вживую, НЕ на слово
- **PR #2** (orchestrator, ветка `feature/ORCH-6-multirepo`) — open, **mergeable:True**
- 7 коммитов Conventional Commits
- Оба тест-файла созданы (test_projects, test_plane_webhook)
- **Тесты: 57 passed** (20 новых зелёных), 9 fail — те же pre-existing 401/TypeError, baseline ЦЕЛ
- Контейнер пересобран, health ok
- Resolve вживую: orchestrator→ORCH, enduro→ET, unknown→None ✅
- 🛡️ Webhook ОСТАЁТСЯ выключен (`is_active=f`) — Dev не трогал, как и договорено
### 🔵 ЖДЁТ РЕШЕНИЯ СЛАВЫ (спросила, ОК пока нет)
1. Смержить **PR #2** (multi-repo) в main orchestrator
2. После мержа — **включить Plane-webhook** (`UPDATE webhooks SET is_active=true`) — теперь безопасно, фильтр режет чужие проекты
- Делать без ОК НЕ буду: мерж в main + включение автозапуска = живая автономная система
- Также висят: PR #19 (enduro-trails), PR #1 (orchestrator worktree)
### Следующий бэклог ORCH (после ORCH-6 merge+webhook on)
- ORCH-1 (F-2b очередь задач вместо in-process daemon) — следующий приоритет
- ORCH-3 (S-2/S-3 rollback), ORCH-4 (M-3 stage-engine), ORCH-5 (M-7 идемпотентность webhook dedup)
---
## ORCH-6 ЗАМЕРЖЕН + Webhook ВКЛЮЧЁН (2026-06-02 ~21:00) — проверено вживую
### Сделано (с ОК Славы «Делай»)
-**PR #2 смержен** в main orchestrator (HTTP 200, merge commit `b021ff7`)
- ✅ Контейнер пересобран из main, health ok
-В main также прилетел `test_git_worktree.py` (ORCH-2 хвост) — норма
-**Plane-webhook ВКЛЮЧЁН обратно**: `UPDATE webhooks SET is_active=true``is_active=t`, UPDATE 1
### Боевой тест предохранителя (двойная защита, подтверждено на проде)
1. 🛡️ HMAC-подпись: webhook без валидной подписи → `401 Invalid signature` (секрет 40 симв настроен)
2. 🛡️ Фильтр проекта: webhook с ВАЛИДНОЙ подписью от неизвестного проекта → `200 {"status":"ignored","reason":"unknown project"}`, лог `ignoring event from unknown project (known: 2)`
3. ✅ Задача НЕ создалась (11→11) — инцидент технически невозможен
### Грабли (повтор из инцидента — записать чтоб не наступать)
- Postgres-пароль Plane: `\x27`-экранирование кавычек через ssh+docker ЛОМАЕТСЯ. Рабочий способ — писать SQL в файл и `psql -f`, пароль брать из env Plane-контейнера (`len=5`)
- Plane postgres: контейнер `plane-app-plane-db-1`, db/user `plane`
---
## ORCH-1 (F-2b) — Персистентная очередь задач (2026-06-02 ~21:00)
### Контекст проблемы (in-process архитектура)
- `launcher.launch()` синхронно: `subprocess.Popen(claude)` + 2 daemon-thread (`_watchdog` таймаут-киллер 1800с + `_monitor_agent` ждёт/коммитит/advance stage)
- 8 точек вызова: `plane.py:189,234,308,389` + `gitea.py:126,203,275,300`
- Беды: рестарт орка = агенты-сироты + потеря работы; нет лимита параллелизма; нет ретраев; webhook блокируется на спавне
### ТЗ
- `tasks/orchestrator/DEV_TASK_ORCH1_QUEUE.md` (снайперское, все file:line собраны заранее)
- Решение: таблица `jobs` (queued/running/done/failed) + atomic `claim_next_job` + `queue_worker.py` петля + `max_concurrency` + ретраи + requeue running на старте (restart-safe) + `/queue` эндпоинт
### ✅ Базовая очередь готова (PR #3) — проверено мной вживую
- **76 passed** (19 новых тестов очереди, вкл. атомарность claim на 8 потоках/20 jobs), 9 fail — те же pre-existing 401
- `/queue` живой: counts, max_concurrency, recent
- PR #3 open, mergeable:True
- Фиксы B-1/B-2/M-1/ORCH-2/ORCH-6 не тронуты
- Живой прогон: queued→running→done, ретрай, restart-safe
### ⚠️ Resilience-слой Dev в базовый PR #3 НЕ встроил
- Моё уточнение (preflight/429/backoff/breaker) пришло когда Dev уже ушёл в финал T8-T12 → в коде НЕТ ни `preflight.py`, ни классификатора 429, ни breaker, ни колонок backoff
- Урок: при дослыле уточнения в активную сессию Dev — проверять, что оно реально вошло в код, а не только в отчёт «done»
---
## ORCH-1b (Resilience-слой) — дослан отдельной задачей (2026-06-02 ~21:00)
### Идея Славы (отличный вопрос про надёжность claude CLI)
- Два РАЗНЫХ зверя, лечить раздельно:
- **CLI недоступен** (бинарь/сеть) → дешёвый preflight `claude --version` + TCP, кэш 45с, токены НЕ жжёт. Мёртв → job ждёт в очереди, не падает
- **Rate limit 429** → предсказать НЕЛЬЗЯ; prompt-ping перед запуском = трата лимита, ТАК НЕ ДЕЛАТЬ. Ловить 429 на ВЫХОДЕ (паттерны в логе: `429`/`rate limit`/`overloaded`/`Retry-After`), классифицировать transient vs permanent
- **Backoff** для transient: exp + `available_at`/`next_attempt_at` колонка в очереди + уважать `Retry-After`. Очередь = идеальное место для backoff
- **Circuit breaker**: 3 фейла подряд → пауза 5 мин (CLI не дёргаем, лимит не выжигаем) + алерт → half-open проба → закрыли
- Ретраи раздельные: transient (429) ≠ code-fault (attempts=2)
### Статус
- Задача `orch1b_resilience` запущена на Dev (Opus 4.8), поверх той же ветки/PR #3 (фокусные коммиты)
- Требует: безопасная миграция БД через PRAGMA-проверку (prod-база `jobs` уже живая)
### ⚠️ Урок: тест-алерты дёргают Славу
- Dev гонял retry-тест с синтетическим `repo r-retry` / job 3 → fail-алерт долетел в Telegram, Слава испугался («Ау»)
- Проверка: `/queue` всё по нулям, в прод-БД никакого `r-retry`/job 3 нет — жил только в эфемерной pytest-БД
- **TODO для ORCH-1b**: подавить Telegram-нотификации в тестовых прогонах (нотификации только прод, не pytest)
### Следующие шаги
- Дождаться `orch1b_resilience`, проверить вживую (preflight без трат токенов, 429-классификатор, backoff, breaker, миграция)
- Слить PR #3 (base queue + resilience) ОДНИМ куском после полной проверки
- Дальше бэклог: ORCH-3 (S-2/S-3 rollback), ORCH-4 (M-3 stage-engine), ORCH-5 (M-7 idempotency/webhook dedup)
### Висящие вопросы Славе
- PR #19 (enduro-trails), PR #1 (orchestrator worktree) — мержить?
- PR #2 уже смержен (ORCH-6)