analyst(ET): auto-commit from analyst run_id=55
Some checks failed
CI / lint (push) Failing after 4s
CI / test (push) Failing after 5s
CI / build (push) Has been skipped

This commit is contained in:
2026-06-02 19:05:00 +00:00
parent d4cc872ec9
commit dabc08bd3a
4 changed files with 867 additions and 0 deletions

View File

@@ -0,0 +1,218 @@
---
type: brd
work_item_id: ET-016
title: "BRD: [ORCH-7] Self-hosting — оркестратор пилит сам себя через конвейер"
version: 1
status: draft
created_at: 2026-06-02
updated_at: 2026-06-02
authors:
- "agent:analyst"
related:
- "ORCH-1..ORCH-6"
---
# BRD — ET-016: Self-hosting оркестратора openclaw
## 1. Цель
Сделать так, чтобы код самого оркестратора **openclaw** (агентные
промпты `.openclaw/agents/*.md`, runtime, пайплайн-скрипты, конфиги
бюджета, политики безопасности) **разрабатывался тем же конвейером**,
которым он разрабатывает enduro-trails. Конкретно:
1. Изменение в любом артефакте оркестратора попадает в систему как
обычный work item (Plane), получает ID `ORCH-NNN`, проходит стадии
`analysis → architecture → development → testing → review → deploy`
и выезжает в продакшн без ручных вмешательств владельца.
2. Конвейер умеет **безопасно обновлять самого себя** (bootstrap-проблема):
момент апдейта оркестратора не должен ломать активные run-ы и не
должен «съесть» собственный артефакт деплоя.
3. На выходе ET-016 демонстрируется **smoke-кейс**: реальный work item
`ORCH-DEMO-01`, который меняет тривиальную деталь в одном из
агентных промптов (например, добавляет строку в раздел «Запрещено»
у `developer.md`), пройдён конвейером end-to-end, изменение
присутствует на продакшн-инстансе оркестратора, история стадий
зафиксирована в Plane и в `docs/work-items/ORCH-DEMO-01/`.
ET-016 — это **«доказать, что конвейер замыкается на себя»**, а не
полное переписывание оркестратора.
## 2. Контекст
### Что уже есть (ORCH-1..ORCH-6)
- **ORCH-1..3** — базовый конвейер: 6 агентов (analyst, architect,
developer, tester, reviewer, deployer), модели Sonnet 4.6 / Opus 4.7,
оформление артефактов в `docs/work-items/<plane-id>/`.
- **ORCH-4** — интеграция с Plane (work item ID — `ET-NNN` для
enduro-trails) и Gitea API (`http://localhost:3000`, токен
`ORCH_GITEA_TOKEN`).
- **ORCH-5** — деплой-хук (`/home/slin/bin/enduro-deploy-hook.sh`),
smoke-тесты, rollback на предыдущий tag.
- **ORCH-6** — UI-тестовый раннер для visual-регрессии
(`/home/slin/tools/ui-test/run_tests.js`).
- В каждом managed-репозитории (`enduro-trails` — единственный на
текущий момент) лежит `.openclaw/agents/*.md` — снимок системных
промптов агентов на момент клонирования. Runtime оркестратора и
главные конфиги (бюджеты, политики, scheduler) живут **вне репозитория
managed-проекта**, в отдельной кодовой базе оркестратора.
### Где живёт код оркестратора сейчас
На момент составления BRD точное расположение runtime-кода оркестратора
**в этом репозитории не зафиксировано**. Предположительно — отдельный
репозиторий `openclaw` рядом с `enduro-trails` на хосте mva154. Эта
неопределённость — **ключевое решение для архитектора** (см. §7 и
TRZ §3).
### Почему «self-hosting» — отдельная задача
Бутстрап-проблема: текущий пайплайн рассчитан на работу с одним
managed-репозиторием `enduro-trails` через `.task-deploy.md`, branch
naming `feature/ET-NNN-…`, Gitea repo `admin/enduro-trails`. Чтобы
конвейер работал на собственном коде, нужны:
- отдельный Plane-проект и префикс ID (`ORCH-`);
- отдельный target-репозиторий в Gitea;
- отдельный deploy-хук;
- защита от self-update во время активного run (race на тот же
агентный промпт);
- защита от «убийства родителя»: если ORCH-NNN ломает деплой, должна
быть возможность откатиться без участия сломанного оркестратора.
### Связи
- **enduro-trails** — managed-проект, остаётся работать в обычном
режиме. ET-016 НЕ меняет процесс работы с ET-NNN.
- **Plane** — добавляется проект `ORCH` с тем же набором стадий.
- **Gitea** — добавляется репозиторий `admin/openclaw` (или фиксируется
существующий).
- **mva154** — здесь живёт production-инстанс оркестратора, сюда же
деплоится новая версия.
## 3. Scope
### In scope
| # | Функция |
| ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| F-01 | Зафиксировать местоположение исходного кода оркестратора (один из вариантов: отдельный репо `openclaw` / `openclaw-runtime` / `.openclaw/` в этом же репо) — решение фиксирует архитектор в ADR. |
| F-02 | В Plane создаётся проект `ORCH` с тем же конвейером стадий: `analysis → architecture → development → testing → review → deploy`. |
| F-03 | Префикс ID `ORCH-` распознаётся orchestrator-router-ом наряду с `ET-`. Работает как минимум с двумя префиксами; путь к артефактам `docs/work-items/<plane-id>/` остаётся неизменным. |
| F-04 | Ветки оркестратора именуются `feature/ORCH-NNN-<slug>`, `bugfix/ORCH-NNN-<slug>`. Конвенция в `CLAUDE.md` оркестратора повторяет конвенцию enduro-trails. |
| F-05 | Deploy-хук для оркестратора (`/home/slin/bin/openclaw-deploy-hook.sh` или аналог) — отдельный от `enduro-deploy-hook.sh`. Перезапуск оркестратора через `docker compose` / `systemctl` — на усмотрение архитектора. |
| F-06 | **Safe self-update**: апдейт оркестратора не должен прерывать активные work item-ы. Допускается стратегия draining (новые run-ы не стартуют, ждём завершения активных, затем рестарт). |
| F-07 | **Rollback без живого оркестратора**: deploy-хук оркестратора должен уметь откатиться к предыдущему tag-у даже если новая версия не стартует (cron-сторож, systemd-таймер или внешний скрипт). |
| F-08 | **Audit trail**: каждое изменение кода оркестратора привязано к work item ORCH-NNN; запрещён прямой push в `main` без PR (защита branch protection в Gitea). |
| F-09 | **Запрет на изменение чужих work-item ID**: агент, работая над `ORCH-NNN`, не может писать в `docs/work-items/ET-*` и наоборот (см. правила в `CLAUDE.md`). |
| F-10 | Smoke-демо: создать work item `ORCH-DEMO-01` (или с реальным ID, выданным Plane), провести через все стадии. Изменение тривиальное — например, дополнить раздел «Запрещено» в `developer.md` строкой про запрет коммита бинарных артефактов > 5 MB. |
| F-11 | Документация: `docs/architecture/self-hosting.md` (или раздел в README оркестратора) с описанием бутстрап-сценария и rollback-процедуры. |
| F-12 | CI для оркестратора: lint YAML-frontmatter агентов, dry-run прогона на тестовом work item-е, smoke-tests `make orch-smoke`. |
### Out of scope
- **Multi-tenancy оркестратора** (один инстанс — несколько managed-проектов разной природы). Сейчас и так enduro-trails единственный, и self-hosting сам по себе — это лишь добавление второго проекта `ORCH`.
- **Замена моделей** (Sonnet → Haiku и т. п.) или изменение их по дефолту.
- **Миграция Plane на другую систему трекинга**.
- **Изменение конвенции Conventional Commits**.
- **Полный рефакторинг runtime оркестратора**. Если в ходе работы выявлены глубинные проблемы (например, runtime не разделяет агентные сессии корректно) — открыть отдельный work item `ORCH-NNN+1`.
- **Замена Gitea на GitHub/GitLab**.
- **Перевод оркестратора на k8s** (см. запреты архитектора).
- **Real-time observability dashboard оркестратора**. В этой задаче — только access-логи и `docs/work-items/<…>/14-deploy-log.md`.
## 4. Сценарии использования
### UC-01. Owner правит промпт агента developer
1. Owner создаёт в Plane задачу `ORCH-42`: «У developer запретить коммит файлов > 5 MB».
2. Конвейер пикает задачу, спавнит analyst-агента → артефакты в `docs/work-items/ORCH-42/`.
3. Стадии прокручиваются автоматически до deployer.
4. Deployer мерджит PR в `main` репозитория оркестратора, тэгает `vX.Y.Z`, запускает `openclaw-deploy-hook.sh`.
5. Хук дожидается завершения активных run-ов (draining ≤ 30 мин), затем рестартует оркестратор с новой версией.
6. Smoke: новый запуск любого ET-задачи показывает обновлённого `developer` агента (например, через лог системного промпта).
### UC-02. Деплой ORCH-NNN сломал runtime
1. После рестарта healthcheck FAIL (оркестратор не стартует).
2. Внешний сторож (cron каждые 60 сек, или systemd `OnFailure=`) ловит сбой и откатывает к предыдущему tag.
3. Деплой-лог `docs/work-items/ORCH-NNN/14-deploy-log.md` фиксирует rollback.
4. Work item ORCH-NNN возвращается в `back-to:dev` через Plane API.
### UC-03. Active run во время self-update
1. ET-099 в стадии `development` (developer-агент работает 12 минут).
2. ORCH-43 переходит в `deploy`.
3. Деплой-хук видит активный run → ждёт `DRAIN_TIMEOUT_SEC` (default 1800).
4. Активный run завершается успешно → рестарт оркестратора → ORCH-43 деплой успешен.
5. (Альтернатива) DRAIN_TIMEOUT истёк → деплой откладывается (статус work-item `deploy:pending`) либо принудительно прерывает run по флагу `--force` (НЕ default).
## 5. Метрики успеха
| Метрика | Критерий |
| -------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| Plane-проект ORCH создан | Видим в Plane UI; конвейер umеет создавать work item ORCH-NNN. |
| Префикс ORCH распознаётся | Команда оркестратора, принимающая `<plane-id>`, корректно работает и для `ET-NNN`, и для `ORCH-NNN`. Тест: `orch pick ORCH-DEMO-01` стартует конвейер. |
| Smoke-демо пройдено | ORCH-DEMO-01 (или аналог) завершён со статусом `done`; изменение в `developer.md` присутствует в `main` репо оркестратора; tag прописан; healthcheck PASS. |
| Бутстрап без даунтайма | В UC-03 активный ET-99 не падает; деплой ORCH-43 не теряет свой собственный артефакт. |
| Rollback работает | Имитация сломанного релиза (deploy-хук получает заведомо битый tag) → внешний сторож откатывает за ≤ 5 минут; деплой-лог отражает откат. |
| Branch protection | Попытка push в `main` оркестратора без PR (`git push origin main` напрямую) — отклоняется Gitea с 403. |
| Раздельные deploy-хуки | `enduro-deploy-hook.sh` и `openclaw-deploy-hook.sh` (или унифицированный хук с режимом `--target=enduro|orch`) — путь решения за архитектором. Тестово запускаются по отдельности, не пересекаются. |
| CI оркестратора зелёный | `make orch-lint` (валидация YAML-frontmatter всех `.openclaw/agents/*.md`) и `make orch-smoke` (dry-run одного агента) — оба возвращают 0. |
| Документация Self-hosting | `docs/architecture/self-hosting.md` (или раздел в README оркестратора) содержит: где код, как деплоится, как откатывается, как читать логи, какие env. |
| Время «созыва» | От открытия ORCH-NNN в Plane до автоматического старта analyst-стадии — ≤ 5 минут (как и для ET-NNN). |
## 6. Риски
| # | Риск | Вероятность | Влияние | Митигация |
| ---- | ------------------------------------------------------------------------------------------------- | ----------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| R-1 | Деплой ORCH-NNN роняет оркестратор → следующие задачи не пикаются | Средняя | Критическое | F-07: внешний сторож (systemd `OnFailure` или cron-watchdog) откатывает за ≤ 5 мин; healthcheck endpoint у оркестратора обязателен. |
| R-2 | Self-update во время активного run → потеря состояния | Средняя | Высокое | F-06: draining-стратегия с таймаутом; persistent state run-ов на диске (если ещё нет — отдельный work item, не в scope ET-016). |
| R-3 | Bootstrap-парадокс: ORCH-NNN ломает analyst → следующие ORCH-NNN не могут пройти анализ | Низкая | Критическое | Канарейка: после деплоя оркестратора прогон smoke-задачи `ORCH-CANARY-MIN` (фиктивная no-op задача) — если smoke FAIL, rollback. |
| R-4 | Два префикса (`ET-`, `ORCH-`) → роутер коллизит / перепутывает managed-репозитории | Средняя | Высокое | F-03: явная таблица маппинга `prefix → repo → deploy_hook` в конфиге оркестратора; unit-тест на роутер. |
| R-5 | Owner случайно push-ит в `main` оркестратора напрямую → audit-trail сломан | Низкая | Среднее | F-08: Gitea branch protection на `main`; required reviews ≥ 1. |
| R-6 | Сторонний разработчик правит `.openclaw/agents/*.md` в репо enduro-trails — изменение не доходит до runtime | Высокая | Среднее | Документация (F-11): `.openclaw/agents/*.md` в enduro-trails — это **снимок**, изменения надо вносить в репозиторий оркестратора и деплоить. Опционально (out of scope): pre-commit hook предупреждает. |
| R-7 | Plane не умеет работать с двумя проектами одновременно → необходима ручная конфигурация | Низкая | Низкое | F-02: проверка на стадии анализа; если оказывается «не умеет» — эскалация к Owner. |
| R-8 | Deploy-хук оркестратора требует прав, которых нет у service-аккаунта (`systemctl restart openclaw`) | Средняя | Среднее | F-05: уточнить с DevOps на стадии TRZ; альтернатива — рестарт через `docker compose restart openclaw` без sudo (если оркестратор контейнеризован). |
| R-9 | Раздельные репо → конвенция CLAUDE.md дрейфует между ними | Средняя | Низкое | F-11: указать в обоих CLAUDE.md ссылку на канонический документ конвенций; периодический ручной audit. |
| R-10 | Размер бюджета токенов в `.openclaw/budget.yaml` отличается для ET и ORCH задач | Средняя | Низкое | TRZ может зафиксировать раздельные бюджеты в одном файле (раздел `projects.ORCH.budget`) либо два файла. Решение архитектора. |
## 7. Зависимости
### Инфра
- mva154: production-инстанс оркестратора (предположительно Docker-контейнер `openclaw` в общем `docker-compose.yml` либо отдельный stack).
- Gitea: создать (или подтвердить существование) репозитория `admin/openclaw`. Включить branch protection на `main`.
- Plane: создать проект с ID-префиксом `ORCH`, настроить стадии `analysis`/`architecture`/`development`/`testing`/`review`/`deploy`/`done`.
- systemd / cron: настроить внешний watchdog для R-1 / R-3 митигации.
### Код / конфиги
- Runtime оркестратора (репозиторий, конкретное местоположение — решение архитектора).
- `.openclaw/agents/*.md` — канонические версии живут в репозитории оркестратора; снимок в enduro-trails синхронизируется через CI / периодический pull (out of scope какой именно механизм, но **факт расхождения не приемлем** — это R-6).
- `/home/slin/bin/openclaw-deploy-hook.sh` (новый) или расширение `enduro-deploy-hook.sh` параметром `--target` (решение архитектора).
- Env-переменные оркестратора (`ORCH_GITEA_TOKEN`, `DEPLOY_SSH_*`, потенциально `ORCH_PROJECTS=ET,ORCH` или подобная карта префиксов).
### Документация
- `docs/architecture/self-hosting.md` (или README в репозитории оркестратора) — бутстрап-сценарий, rollback, env.
- ADR в `docs/work-items/ET-016/06-adr/`:
- `ADR-NNNN-orch-repo-location.md` — где живёт код оркестратора (отдельный repo vs. submodule vs. monorepo);
- `ADR-NNNN-orch-deploy-strategy.md` — как обновляется (docker restart vs. systemd vs. blue-green);
- `ADR-NNNN-orch-self-update-draining.md` — стратегия draining активных run-ов;
- `ADR-NNNN-orch-watchdog.md` — выбор сторожа (systemd OnFailure vs. cron-script vs. internal).
- Обновления CLAUDE.md оркестратора и/или enduro-trails (раздел про двойной префикс ID).
### Связи с другими work items
- Без `ORCH-1..ORCH-6` ET-016 невозможен — там создан базовый конвейер.
- После ET-016 разблокируются дальнейшие задачи `ORCH-NNN` (рефакторинг агентов, обновление промптов, добавление новых стадий и т. п.) — все они будут идти через self-hosted конвейер.
- ET-016 НЕ зависит от текущих ET-001..ET-009 (продуктовая работа не пересекается).
## 8. Допущения
- A-1: Plane умеет работать с несколькими проектами и кастомными префиксами. Если нет — Owner эскалирует, ET-016 уходит в `back-to:analysis` с конкретной проблемой.
- A-2: Gitea admin-токен (`ORCH_GITEA_TOKEN`) имеет права на создание репо и установку branch protection.
- A-3: На mva154 есть свободные ресурсы (~512 MB RAM, ~5% CPU) для отдельного контейнера/процесса оркестратора либо текущий контейнер уже включает runtime.
- A-4: Owner готов один раз вручную провести bootstrap-деплой первой версии «self-hosted» оркестратора (по определению он не может задеплоить сам себя, пока не задеплоен).
- A-5: На время выполнения ET-016 заморозка прода не нужна; обычные ET-задачи продолжают работать, потому что инфраструктура для `ORCH-` добавляется параллельно.

View File

@@ -0,0 +1,160 @@
---
type: trz
work_item_id: ET-016
title: "ТЗ: Self-hosting оркестратора openclaw"
version: 1
status: draft
created_at: 2026-06-02
updated_at: 2026-06-02
authors:
- "agent:analyst"
based_on: "01-brd.md v1"
---
# ТЗ — ET-016: Self-hosting оркестратора
## 1. Краткое резюме
Конвейер оркестратора openclaw должен уметь разрабатывать свой собственный
код через те же стадии, через которые он разрабатывает enduro-trails.
ET-016 добавляет второй managed-проект `ORCH`, реализует безопасный
self-update и доказывает работоспособность smoke-кейсом.
Архитектурно ключевые решения (расположение репо, стратегия деплоя,
draining, watchdog) — за architect-агентом; в ТЗ зафиксированы
**требования к поведению**, не реализация.
## 2. Функциональные требования
### 2.1 Plane-проект ORCH
| ID | Требование |
| ----- | ----------------------------------------------------------------------------------------------------------------------- |
| FR-01 | В Plane существует проект с префиксом `ORCH` (название проекта на усмотрение Owner, например «openclaw runtime»). |
| FR-02 | Стадии проекта ORCH совпадают по составу со стадиями enduro-trails: `analysis`, `architecture`, `development`, `testing`, `review`, `deploy`, `done`, `back-to:*`. |
| FR-03 | Лейблы `arch:major-change`, `back-to:analysis`, `back-to:dev`, `back-to:review`, `stage:ready-to-deploy` доступны в обоих проектах. |
| FR-04 | Owner может создать work item ORCH-NNN из Plane UI; конвейер в течение ≤ 5 минут пикает его и запускает стадию analysis. |
### 2.2 Роутер префиксов
| ID | Требование |
| ----- | ----------------------------------------------------------------------------------------------------------------------- |
| FR-05 | В конфигурации оркестратора есть машиночитаемая таблица маппинга `prefix → {plane_project, gitea_repo, deploy_hook, claude_md_path}`. |
| FR-06 | Поддерживаются минимум два префикса: `ET` (managed-проект enduro-trails) и `ORCH` (managed-проект openclaw runtime). |
| FR-07 | Префикс извлекается из `<plane-id>` строго через регэксп `^([A-Z]+)-(\d+)$` (Plane-конвенция). |
| FR-08 | При неизвестном префиксе оркестратор останавливает запуск с явной ошибкой `unknown_prefix=XXX`, без падений и без коллизий с другим проектом. |
### 2.3 Репозиторий оркестратора
| ID | Требование |
| ----- | ----------------------------------------------------------------------------------------------------------------------- |
| FR-09 | Существует Gitea-репозиторий, в котором живёт код оркестратора. Конкретное имя (`admin/openclaw`, `admin/openclaw-runtime` и т. п.) фиксируется ADR. |
| FR-10 | В корне репозитория оркестратора есть свой `CLAUDE.md` с конвенциями (Conventional Commits, ветки `feature/ORCH-NNN-…`). |
| FR-11 | На ветке `main` репозитория оркестратора включена Gitea branch protection: required reviews ≥ 1, прямой push запрещён. |
| FR-12 | Существуют ветки и теги вида `feature/ORCH-NNN-…`, `vMAJOR.MINOR.PATCH` (semver) — формат идентичен enduro-trails. |
### 2.4 Деплой оркестратора
| ID | Требование |
| ----- | ----------------------------------------------------------------------------------------------------------------------- |
| FR-13 | Существует deploy-хук, перезапускающий production-инстанс оркестратора на mva154. Имя/путь — за ADR (например, `/home/slin/bin/openclaw-deploy-hook.sh`). |
| FR-14 | Хук неинтерактивный: запускается SSH-командой без TTY, возвращает корректный exit code (0 — успех, ≠ 0 — fail). |
| FR-15 | Хук выполняет healthcheck оркестратора после рестарта (endpoint и его формат — за ADR; минимум — TCP-ping порта runtime либо `GET /healthz` 200). |
| FR-16 | При неуспешном healthcheck в течение `HEALTHCHECK_TIMEOUT_SEC` (default 60) хук вызывает rollback на предыдущий tag и возвращает exit 1. |
| FR-17 | После успешного rollback healthcheck повторно проверяется; если и rollback не поднимает оркестратор — хук возвращает exit 2 (critical), Owner получает уведомление (механизм out of scope; минимум — запись в журнал systemd / Docker logs). |
### 2.5 Safe self-update
| ID | Требование |
| ----- | ----------------------------------------------------------------------------------------------------------------------- |
| FR-18 | Перед рестартом оркестратора deploy-хук переводит его в режим `drain`: новые work item-ы не пикаются. |
| FR-19 | Активные run-ы продолжают работу до завершения либо до `DRAIN_TIMEOUT_SEC` (default 1800, конфигурируемо). |
| FR-20 | По истечении DRAIN_TIMEOUT хук имеет два режима: `wait-and-fail` (default — отложить деплой, work item ORCH-NNN остаётся в `deploy:pending`) и `force` (прервать активные run-ы — допустимо только при явном флаге, не default). |
| FR-21 | После рестарта оркестратор автоматически выходит из `drain` (флаг сбрасывается). |
| FR-22 | Состояние `drain` персистентно (файл / БД / lock); рестарт хоста сохраняет его до явного снятия. |
### 2.6 Watchdog и rollback вне оркестратора
| ID | Требование |
| ----- | ----------------------------------------------------------------------------------------------------------------------- |
| FR-23 | Существует механизм восстановления, **не зависящий от живости оркестратора**: внешний sensor каждые `WATCHDOG_INTERVAL_SEC` (default 60) проверяет здоровье runtime; если N=3 подряд отказа — автоматически откатывает к предыдущему tag. |
| FR-24 | Конкретный механизм (systemd `OnFailure=`, отдельный systemd-таймер, cron, supervisord) — за ADR. |
| FR-25 | Watchdog **сам не подвержен self-update** (живёт вне deploy-хука оркестратора; апгрейд watchdog — ручной). |
| FR-26 | Лог откатов watchdog пишет в файл (например `/var/log/openclaw-watchdog.log`); каждое срабатывание — отдельная строка с timestamp, from_tag, to_tag, reason. |
### 2.7 Smoke-демо (доказательство замыкания)
| ID | Требование |
| ----- | ----------------------------------------------------------------------------------------------------------------------- |
| FR-27 | В рамках ET-016 создаётся реальный work item `ORCH-DEMO-01` (или иной ORCH-NNN, выданный Plane), содержащий **тривиальное** изменение в одном из агентных промптов. Рекомендация: добавить в `developer.md` в раздел «Запрещено» строку про коммит бинарных файлов > 5 MB. |
| FR-28 | Work item проходит все стадии конвейера автоматически, без ручных переходов, кроме Owner-approval, если затронутая ADR `arch:major-change` (для smoke — НЕ затрагивает, должен пройти без approval). |
| FR-29 | После деплоя ORCH-DEMO-01: в репозитории оркестратора в `main` появляется изменённый файл; production-инстанс перезапущен; следующая стартующая ET-задача показывает обновлённого `developer` агента (валидация: первая строка системного промпта содержит новую строку в разделе «Запрещено»). |
| FR-30 | Полный артефакт-набор `docs/work-items/ORCH-DEMO-01/` создан и закоммичен. |
### 2.8 CI оркестратора
| ID | Требование |
| ----- | ----------------------------------------------------------------------------------------------------------------------- |
| FR-31 | В репозитории оркестратора есть Gitea Actions workflow на push в `feature/ORCH-*` и PR в `main`: lint + smoke. |
| FR-32 | Lint включает: валидация YAML-frontmatter каждого `.openclaw/agents/*.md` (поля `name`, `description`, `model`, `tools` обязательны и корректного типа). |
| FR-33 | Smoke включает: dry-run запуск одного агента на синтетическом work item-е (без реальных Anthropic вызовов — режим mock или stub). |
| FR-34 | CI запрещает мерж PR в `main` при FAIL любого из шагов. |
### 2.9 Sync `.openclaw/` снимков
| ID | Требование |
| ----- | ----------------------------------------------------------------------------------------------------------------------- |
| FR-35 | После deploy ORCH-NNN снимок `.openclaw/agents/*.md` в managed-репозиториях (enduro-trails и будущих) должен быть обновлён. |
| FR-36 | Механизм синхронизации — за ADR. Минимум — автоматический PR из CI оркестратора в каждый managed-репозиторий с заголовком `chore(openclaw): sync agents from ORCH-NNN`. |
| FR-37 | Дрейф `.openclaw/` в managed-репозитории относительно репо оркестратора виден через CI managed-репозитория (например, `make orch-snapshot-check` в CI enduro-trails). |
## 3. Архитектурные решения (передаются архитектору)
Архитектор обязан в стадии architecture зафиксировать ADR по следующим вопросам:
1. **Где живёт runtime-код оркестратора?**
- Вариант A: отдельный Gitea-репозиторий `admin/openclaw` рядом с enduro-trails.
- Вариант B: monorepo с подкаталогом `orchestrator/` (не рекомендуется — нарушает изоляцию).
- Вариант C: подмодуль `.openclaw/` в каждом managed-репозитории (не рекомендуется — синхронизация будет адом).
- **Рекомендация анализа**: вариант A.
2. **Стратегия деплоя на mva154**: docker compose restart / systemd unit / blue-green.
3. **Draining стратегия**: lock-файл / DB-флаг / signal SIGTERM / k8s-style PreStop hook (последнее out of scope — k8s запрещён).
4. **Watchdog**: systemd `OnFailure=` + Restart= / отдельный systemd timer / cron-script / отдельный docker-контейнер.
5. **Sync `.openclaw/`**: автоматический PR / `git subtree pull` в CI managed-репо / симлинки на хосте (нежелательно).
6. **Healthcheck endpoint**: формат и порт — за ADR; минимум — `GET /healthz` HTTP 200 / `curl localhost:PORT`.
7. **Конфиг префиксов**: где хранится таблица `prefix → {plane_project, gitea_repo, …}` — YAML в репо оркестратора, env-переменные, иное.
## 4. Нефункциональные требования
| ID | Требование |
| ------ | ----------------------------------------------------------------------------------------------------------------------- |
| NFR-01 | Время полного self-update (от merge PR ORCH-NNN до завершения healthcheck): ≤ 10 минут при пустом draining-окне. |
| NFR-02 | Время watchdog-rollback: ≤ 5 минут от момента детекции FAIL. |
| NFR-03 | Расход RAM оркестратора после рестарта: не превышает baseline ± 20 %. |
| NFR-04 | Логи деплоя оркестратора ротируются (logrotate / docker log-driver): не более 100 MB на инстанс. |
| NFR-05 | Все env-переменные оркестратора (включая токены) задаются через `.env` или systemd-EnvironmentFile, не через git. |
| NFR-06 | Конфиги (`prefix-map`, `budget.yaml`) валидируются на старте; некорректный конфиг → старт прерывается с явной ошибкой. |
| NFR-07 | Безопасность: deploy-хук оркестратора **не имеет прав** на изменение `.openclaw/agents/` в managed-репо в обход PR. |
## 5. Out of scope (повтор для строгости)
- Замена моделей агентов.
- Multi-tenancy (несколько managed-проектов разной природы — кроме связки ET + ORCH).
- Real-time observability dashboard.
- Миграция Gitea / Plane / Anthropic API.
- Полный рефакторинг внутреннего runtime оркестратора.
- Поддержка более двух префиксов одновременно (только ET и ORCH в этой задаче; расширение — отдельный work item).
## 6. Открытые вопросы (Q&A для architect и Owner)
| # | Вопрос | К кому |
| --- | --------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| Q-1 | Какой Gitea-репозиторий выбран для runtime оркестратора? Создавать новый или использовать существующий? | architect + Owner |
| Q-2 | На каком порту слушает healthcheck оркестратора сейчас (если есть)? | architect |
| Q-3 | Управляется ли production оркестратора через docker compose или systemd unit? | architect |
| Q-4 | Допустимо ли требовать у Owner ручной bootstrap первой self-hosted версии (см. A-4 BRD §8)? | Owner |
| Q-5 | Plane: поддерживается ли создание нового проекта с произвольным префиксом без миграции? | Owner |
| Q-6 | Нужен ли в smoke-демо отдельный «канареечный» прогон фиктивного ET-задания после деплоя оркестратора (R-3 BRD §6)? | architect |
| Q-7 | Должен ли watchdog уметь уведомлять Owner (Telegram/email)? Если да — это отдельный work item или включено в ET-016? | Owner |
Аналитик рекомендует: Q-7 — отдельный work item (out of scope). Остальные — обязательно ответить в ADR.

View File

@@ -0,0 +1,196 @@
---
type: acceptance-criteria
work_item_id: ET-016
title: "AC: Self-hosting оркестратора"
version: 1
status: draft
created_at: 2026-06-02
updated_at: 2026-06-02
authors:
- "agent:analyst"
---
# Acceptance Criteria — ET-016
Все AC формулируются как «given-when-then», чтобы tester мог их прогнать
вручную или автоматически. Каждый AC привязан к одному или нескольким
FR из `02-trz.md`.
## AC-01. Plane-проект ORCH существует и видим конвейеру
**Given** Plane API запущен на `http://localhost:8080` (или текущий адрес из env).
**When** обратиться `GET /api/v1/workspaces/<ws>/projects/?identifier=ORCH`.
**Then** ответ 200, в списке проектов есть проект с `identifier="ORCH"`,
у него заданы стадии `analysis`, `architecture`, `development`, `testing`,
`review`, `deploy`, `done`.
Соответствует: FR-01..FR-04.
## AC-02. Роутер префиксов работает для ET и ORCH
**Given** оркестратор запущен в режиме CLI `orch --version` возвращает 0.
**When** запустить `orch route ET-001` и `orch route ORCH-DEMO-01`.
**Then** обе команды возвращают exit 0, печатают разные `gitea_repo`,
разные `claude_md_path`, разные `deploy_hook`. При запуске
`orch route XYZ-001` (неизвестный префикс) команда возвращает exit ≠ 0
с сообщением, содержащим строку `unknown_prefix=XYZ`.
(Конкретное имя команды `orch route` — указатель; tester валидирует
эквивалент после implementation согласно ADR.)
Соответствует: FR-05..FR-08.
## AC-03. Репо оркестратора защищён branch protection
**Given** Gitea доступен, token имеет admin-права.
**When** попытаться `git push origin main` напрямую в репо оркестратора.
**Then** push отклонён с кодом 403 / `protected branch`. Mерж через PR с
≥ 1 approve работает.
Соответствует: FR-09..FR-12.
## AC-04. Deploy-хук успешного релиза
**Given** в репо оркестратора есть мердж в `main` и tag `v0.X.Y` для
тривиального изменения (например, обновление комментария в README).
**When** запустить `ssh slin@127.0.0.1 bash /home/slin/bin/openclaw-deploy-hook.sh v0.X.Y`
(или эквивалент по ADR).
**Then**:
- Exit code 0.
- Healthcheck endpoint возвращает 200 в течение ≤ 60 секунд после рестарта.
- Запись в логе оркестратора отражает рестарт.
- Текущий tag оркестратора (через `orch --version` или эквивалент) — `v0.X.Y`.
Соответствует: FR-13..FR-17.
## AC-05. Deploy-хук неуспешного релиза → rollback
**Given** в репо оркестратора есть tag `v0.X.Z` (заведомо битый — например,
синтаксическая ошибка в YAML-frontmatter одного из агентов; tester подкладывает локально для теста).
**When** запустить deploy-хук с этим тегом.
**Then**:
- Healthcheck FAIL в пределах HEALTHCHECK_TIMEOUT_SEC.
- Хук автоматически переключает на предыдущий tag.
- Healthcheck PASS после rollback.
- Exit code = 1 (релиз провален, но runtime жив).
- `docs/work-items/<orch-id>/14-deploy-log.md` (если применимо) или
`/var/log/openclaw-deploy.log` содержит запись об откате.
Соответствует: FR-16..FR-17.
## AC-06. Draining не убивает активный run
**Given** запущен ET-99 (синтетическая длинная задача, ≥ 5 минут — например, развёрнутый pytest на enduro-trails).
**When** запустить deploy ORCH-NNN с `DRAIN_TIMEOUT_SEC=900`.
**Then**:
- Оркестратор переводится в `drain`, новые ET / ORCH задачи не пикаются (validate: создать ET-100 в Plane — он не должен стартовать пока drain).
- ET-99 продолжает работать, не падает.
- После завершения ET-99 (≤ 10 минут) оркестратор рестартует.
- После рестарта `drain` сбрасывается; ET-100 пикается.
Соответствует: FR-18..FR-22.
## AC-07. Watchdog откатывает сломанный релиз без участия оркестратора
**Given** оркестратор задеплоен в заведомо сломанной версии (healthcheck FAIL), но
deploy-хук по какой-то причине не отработал rollback (имитируется: tester убивает процесс хука после tag-switch, до healthcheck).
**When** ждать `WATCHDOG_INTERVAL_SEC * 3` секунд (default 60 × 3 = 180 сек).
**Then**:
- Watchdog обнаружил FAIL.
- Watchdog инициировал rollback к предыдущему tag.
- Healthcheck PASS после rollback (≤ 5 минут от старта инцидента).
- `/var/log/openclaw-watchdog.log` содержит строку с `from_tag`, `to_tag`, `reason`.
Соответствует: FR-23..FR-26.
## AC-08. Smoke-демо ORCH-DEMO-01 пройден end-to-end
**Given** ET-016 завершён до стадии deploy; всё что выше — задеплоено.
**When** Owner создаёт в Plane work item с заголовком «Добавить запрет на коммит файлов > 5 MB в developer.md», префикс ORCH, без лейбла `arch:major-change`.
**Then**:
- Конвейер пикает работу в ≤ 5 минут.
- Стадии проходят: analysis → architecture → development → testing → review → deploy → done.
- В репозитории оркестратора в `main`: файл `.openclaw/agents/developer.md` (или путь до него в этом репо) содержит новую строку в разделе «Запрещено».
- На production-инстансе оркестратора эта новая строка присутствует (validate: после деплоя стартует любая следующая задача, в логе системного промпта `developer` есть новая строка).
- `docs/work-items/ORCH-DEMO-01/` содержит полный набор артефактов (01..14 по соглашению, кроме тех, что не применимы — например, 04b/08, если задача не UI/не data).
- Tag оркестратора инкрементирован на 1 patch.
- Healthcheck PASS.
Соответствует: FR-27..FR-30 (главное «доказательство замыкания»).
## AC-09. Прямой push в `main` оркестратора заблокирован
**Given** разработчик с admin-токеном Gitea.
**When** `git push origin main` в репо оркестратора напрямую (минуя PR).
**Then** push отклонён с 403; работает только merge через PR.
Соответствует: FR-08, FR-11.
## AC-10. Изоляция work-item-ID между ET и ORCH
**Given** одновременно открыты ET-099 (стадия development) и ORCH-099 (стадия development).
**When** developer-агент по ORCH-099 пытается записать файл в `docs/work-items/ET-099/` (синтетическая попытка через tester-задачу).
**Then** запись отклонена (tooling-уровень — например, sandbox / pre-commit-hook / агентный guard). Минимум — reviewer-агент в ORCH-099 видит факт записи в чужой work-item и помечает P0 finding `cross-work-item-write`.
Соответствует: FR-09 (BRD).
## AC-11. CI оркестратора блокирует мерж невалидного промпта
**Given** в репо оркестратора открыт PR с битым YAML-frontmatter одного агента (например, `model: ` без значения).
**When** Gitea Actions запускает workflow.
**Then** lint FAIL; PR не может быть смержен; в комментариях PR — ссылка на ошибку.
Соответствует: FR-31..FR-34.
## AC-12. Sync `.openclaw/` снимка в enduro-trails
**Given** ORCH-DEMO-01 успешно задеплоен (AC-08 пройден).
**When** проверить `.openclaw/agents/developer.md` в репо enduro-trails в ветке `main`.
**Then** либо:
- (а) файл уже обновлён (если автоматическая синхронизация через PR прошла) — в `main` enduro-trails есть merge-commit с заголовком, содержащим `sync agents from ORCH-DEMO-01`;
- (б) открыт PR с такой синхронизацией (если выбран ADR-вариант с ручным merge снимка).
В обоих случаях запуск `make orch-snapshot-check` (или эквивалент) в репо enduro-trails показывает корректность снимка (хеш файлов в `.openclaw/agents/` совпадает с релизом оркестратора).
Соответствует: FR-35..FR-37.
## AC-13. Документация Self-hosting опубликована
**Given** ET-016 завершён до стадии review.
**When** проверить наличие `docs/architecture/self-hosting.md` (или README раздел в репо оркестратора, как зафиксирует ADR).
**Then** документ содержит обязательно:
- Где живёт runtime-код оркестратора (репо, путь на сервере).
- Команды для bootstrap первой версии.
- Команды для rollback вручную (если watchdog не сработал).
- Описание env-переменных оркестратора.
- Описание формата конфига префиксов.
- Контакты эскалации (Owner email/Telegram).
Соответствует: F-11 BRD, NFR-05.
## AC-14. Бюджет токенов задачи соблюдён
**Given** ET-016 завершён.
**When** orchestrator подсчитывает суммарный расход токенов по всем стадиям.
**Then** суммарный расход не превышает бюджет, заданный в `.openclaw/budget.yaml` для work item типа `infrastructure` (или ближайшего аналога). При превышении — finding P1 в `12-review.md`.
Соответствует: правило #5 для агентов из CLAUDE.md.
## AC-15. Артефакты ET-016 полные
**Given** ET-016 на стадии review.
**When** проверить `docs/work-items/ET-016/`.
**Then** присутствуют:
- 00-business-request.md (входной)
- 01-brd.md
- 02-trz.md
- 03-acceptance-criteria.md (этот файл)
- 04-test-plan.yaml
- 06-adr/ (минимум 3 ADR по списку из §3 TRZ)
- 07-infra-requirements.md
- 10-tech-risks.md
- 12-review.md
- 13-test-report.md
- 14-deploy-log.md
(Файлы 04b-ui-test-cases.md и 08-data-requirements.md не применимы — задача не UI и не data-bound.)

View File

@@ -0,0 +1,293 @@
---
type: test-plan
work_item_id: ET-016
title: "Test plan: Self-hosting оркестратора"
version: 1
status: draft
created_at: 2026-06-02
updated_at: 2026-06-02
authors:
- "agent:analyst"
---
# Test plan ET-016 — Self-hosting оркестратора
#
# Структура: unit / integration / e2e / manual.
# UI / Playwright тестов нет — задача не затрагивает фронтенд enduro-trails.
# Все тесты доступны для запуска через `make orch-test` в репозитории оркестратора
# и через CI Gitea Actions.
unit:
- id: U-01
name: "prefix_router: распознаёт ET и ORCH"
suite: orchestrator/tests/test_prefix_router.py
fr_refs: [FR-05, FR-06, FR-07, FR-08]
description: |
Параметризованный тест: входы "ET-001", "ORCH-099", "ABC-1", "et-1",
"ET-", "ET-001-x". Проверить корректное извлечение префикса и номера
для валидных IDs и raise UnknownPrefixError / InvalidIdError для невалидных.
expected:
- "ET-001 → (prefix=ET, num=1)"
- "ORCH-099 → (prefix=ORCH, num=99)"
- "ABC-1 → UnknownPrefixError(prefix='ABC')"
- "et-1 → InvalidIdError"
- "ET- → InvalidIdError"
- id: U-02
name: "prefix_map: загрузка конфига и валидация"
suite: orchestrator/tests/test_prefix_map.py
fr_refs: [FR-05]
description: |
Загрузить prefix-map YAML с ключами ET и ORCH. Проверить, что для
каждого префикса определены plane_project, gitea_repo, deploy_hook,
claude_md_path. Битый YAML или отсутствующий ключ → ConfigError.
expected:
- "valid yaml → dict с двумя префиксами"
- "yaml без gitea_repo для ORCH → ConfigError('missing gitea_repo')"
- id: U-03
name: "agent_frontmatter_validator: lint всех .openclaw/agents/*.md"
suite: orchestrator/tests/test_agent_lint.py
fr_refs: [FR-32]
description: |
Прочитать каждый файл из .openclaw/agents/, распарсить YAML-frontmatter,
проверить обязательные поля (name, description, model, tools).
Параметризован по списку файлов.
expected:
- "все 6 файлов проходят валидацию"
- "синтетический файл с пустым model → ValidationError"
- id: U-04
name: "drain_state: запись и чтение"
suite: orchestrator/tests/test_drain_state.py
fr_refs: [FR-18, FR-21, FR-22]
description: |
Установить drain=True, перезапустить процесс (имитация), проверить,
что состояние сохранилось. Снять drain — проверить, что новые run-ы пикаются.
expected:
- "set_drain(True) → файл /var/lib/openclaw/drain существует"
- "set_drain(False) → файл удалён"
- "is_drained() читает корректно после рестарта"
- id: U-05
name: "deploy_hook_arg_parser: target=enduro|orch"
suite: orchestrator/tests/test_deploy_hook.py
fr_refs: [FR-13, FR-14]
description: |
Если выбрана стратегия унифицированного deploy-хука (ADR §3.2),
параметризовать тест на --target=enduro и --target=orch.
Проверить, что для каждого target используется правильный compose
файл / systemd unit / git path.
expected:
- "--target=enduro вызывает enduro-deploy steps"
- "--target=orch вызывает orch-deploy steps"
- "--target=unknown → exit 2"
integration:
- id: I-01
name: "orchestrator стартует и пикает работу с обоими префиксами"
suite: orchestrator/tests/integration/test_pickup.py
fr_refs: [FR-04, FR-05]
description: |
Замокать Plane API так, чтобы он отдавал одно work item ET-X
и одно ORCH-Y. Запустить scheduler. Проверить, что оба пикаются,
каждый стартует со своим claude_md_path, своим gitea_repo.
expected:
- "ET-X стартует analyst в репо enduro-trails"
- "ORCH-Y стартует analyst в репо оркестратора"
- "Логи содержат корректные пути к CLAUDE.md"
- id: I-02
name: "Gitea branch protection действительно блокирует push в main"
suite: orchestrator/tests/integration/test_gitea_protection.py
fr_refs: [FR-11]
description: |
Через локальный Gitea (testcontainer / тестовый инстанс с тем же
настроенным репо): попытка `git push origin main` напрямую → ожидаем
ошибку 403 / "protected branch". Push в feature-ветку → успех.
expected:
- "direct push to main → fail (403)"
- "push to feature/ORCH-1-test → success"
- id: I-03
name: "Healthcheck endpoint возвращает 200 после старта"
suite: orchestrator/tests/integration/test_healthcheck.py
fr_refs: [FR-15]
description: |
Поднять оркестратор в test-режиме (например, через docker compose
из репо оркестратора), проверить /healthz возвращает 200 в течение
30 секунд после старта. Убить процесс — /healthz → connection refused.
expected:
- "GET /healthz → 200 within 30s"
- "после kill: GET /healthz → connection refused"
- id: I-04
name: "Drain mode: новые run-ы не пикаются, активные не падают"
suite: orchestrator/tests/integration/test_drain.py
fr_refs: [FR-18, FR-19, FR-21]
description: |
Запустить mock-задачу длительностью 60 сек. После 10 сек активной
задачи установить drain=True. Создать второй mock-work-item.
Проверить: активная задача завершилась успешно, второй work item
НЕ был запущен. Снять drain → второй пикается.
expected:
- "active run completes successfully"
- "queued work item not picked while drain=True"
- "after drain=False: queued work item picked"
- id: I-05
name: "Sync agents PR создаётся после deploy ORCH-NNN"
suite: orchestrator/tests/integration/test_sync_pr.py
fr_refs: [FR-35, FR-36]
description: |
Имитировать успешный deploy ORCH-NNN, содержащий изменение в
.openclaw/agents/developer.md. Проверить, что в Gitea для репо
enduro-trails открыт PR с заголовком, содержащим "sync agents from ORCH-NNN".
expected:
- "PR exists in admin/enduro-trails"
- "PR head branch: chore/openclaw-sync-ORCH-NNN"
- "PR diff содержит обновлённый developer.md"
- id: I-06
name: "Snapshot check скрипт обнаруживает дрейф"
suite: orchestrator/tests/integration/test_snapshot_check.py
fr_refs: [FR-37]
description: |
Артифициально внести изменение в `.openclaw/agents/developer.md` в
enduro-trails (без соответствующего изменения в репо оркестратора).
Запустить `make orch-snapshot-check`. Ожидаем exit ≠ 0 и diff в выводе.
После приведения файлов в соответствие → exit 0.
expected:
- "drift detected → exit 1, diff printed"
- "after sync → exit 0"
e2e:
- id: E-01
name: "ORCH-DEMO-01 smoke: полный конвейер end-to-end"
suite: manual + scripts/e2e_orch_demo.sh
fr_refs: [FR-27, FR-28, FR-29, FR-30]
description: |
Создать work item в Plane с заголовком из FR-27 BRD (добавить строку
в "Запрещено" у developer.md). Запустить конвейер. Дождаться done.
Проверить:
- В репозитории оркестратора в main новая строка присутствует.
- В production-инстансе оркестратора (mva154) код обновлён
(запустить следующую ET-задачу, в логе её analyst-стадии вытащить
system prompt developer-агента, ожидаемая новая строка присутствует).
- В docs/work-items/ORCH-DEMO-01/ присутствуют все обязательные артефакты.
- В Gitea репо оркестратора есть tag vX.Y.Z+1.
- Deploy-лог записан.
expected:
- "work item status: done в Plane"
- "tag vX.Y.Z+1 в репо оркестратора"
- "developer-агент содержит новую строку"
- "healthcheck PASS на production"
- id: E-02
name: "Сломанный релиз → watchdog rollback"
suite: manual + scripts/e2e_watchdog_rollback.sh
fr_refs: [FR-23, FR-24, FR-26]
description: |
Подложить локально tag vX.Y.Z+2 c заведомо битой YAML-frontmatter
одного из агентов. Запустить deploy-хук, ИМИТИРОВАТЬ зависание хука
(kill -STOP) до этапа healthcheck. Подождать 3 интервала watchdog (≥ 180 сек).
Проверить, что watchdog откатил релиз.
expected:
- "watchdog log содержит запись с from_tag=vX.Y.Z+2, to_tag=vX.Y.Z+1"
- "healthcheck PASS после rollback"
- "production-инстанс на tag vX.Y.Z+1"
- id: E-03
name: "ET-задача продолжает работать во время self-update ORCH-задачи"
suite: manual + scripts/e2e_concurrent_run.sh
fr_refs: [FR-19, FR-20]
description: |
Запустить синтетическую длинную ET-задачу (mock, 5 минут).
Через 1 минуту запустить deploy ORCH-NNN (любой тривиальный).
Дождаться завершения ET-задачи, затем рестарта оркестратора, затем
успеха ORCH-NNN.
expected:
- "ET-задача завершена успешно"
- "ORCH-NNN deploy success"
- "Промежуточный лог содержит фазу drain"
- "Очередной new work item не пикался во время drain"
- id: E-04
name: "Прямой push в main репо оркестратора отклоняется"
suite: manual
fr_refs: [FR-11]
description: |
Из любой машины с push-доступом: `git push origin main` напрямую в
репо оркестратора → ожидаем 403/protected branch.
expected:
- "git push fails with exit ≠ 0"
- "stderr содержит 'protected branch' или 'push declined'"
- id: E-05
name: "Cross-write блокирован: ORCH-агент не пишет в docs/work-items/ET-*"
suite: manual + orchestrator/tests/integration/test_cross_write_guard.py
fr_refs: [F-09 BRD, AC-10]
description: |
Запустить ORCH-99-mock с developer-агентом, которому в задаче
требуется (синтетически) записать файл `docs/work-items/ET-099/test.md`.
Ожидаем: либо tooling-level block (sandbox), либо reviewer P0 finding.
expected:
- "запись отклонена ИЛИ зафиксирован P0 в 12-review.md ORCH-99"
manual:
- id: M-01
name: "Документация self-hosting.md проверка"
fr_refs: [AC-13]
description: |
Открыть docs/architecture/self-hosting.md и убедиться вручную в
наличии разделов: bootstrap, rollback, env-переменные, формат
prefix-map, контакты эскалации.
- id: M-02
name: "Проверка branch protection в Gitea UI"
fr_refs: [FR-11]
description: |
Зайти в Gitea, открыть repo settings → branches → main, убедиться:
"Enable Push Protection" вкл, "Require pull request" вкл, минимум 1 reviewer.
- id: M-03
name: "Проверка бюджета токенов в .openclaw/budget.yaml"
fr_refs: [AC-14]
description: |
Открыть .openclaw/budget.yaml. Убедиться, что есть отдельная запись
для задач типа infrastructure (либо ORCH-задач). Сравнить с фактическим
расходом ET-016 (из лога оркестратора).
# Минимальный smoke на CI оркестратора (Gitea Actions):
ci_smoke:
- id: CI-01
name: "make orch-lint"
description: |
Запускается на каждый push в feature/ORCH-* и PR в main.
Включает U-01..U-03.
fr_refs: [FR-31, FR-32]
blocks_merge: true
- id: CI-02
name: "make orch-smoke"
description: |
Запускается на каждый PR в main репо оркестратора.
Включает I-01, I-03, I-04 (mock Anthropic API через stub).
fr_refs: [FR-33, FR-34]
blocks_merge: true
# Регрессия enduro-trails: убедиться, что ET-016 не сломал обычный конвейер.
regression_enduro:
- id: R-01
name: "Любая существующая ET-задача всё ещё пикается"
description: |
Создать тривиальную ET-задачу (например, "обновить дату в README"),
убедиться, что конвейер для неё работает как раньше.
fr_refs: [NFR-03]
- id: R-02
name: "Production enduro-trails не упал во время ET-016 deploy"
description: |
В моменты деплоя ORCH-* (если они идут параллельно с прогоном ET-задачи)
запрашивать /api/health enduro-trails и убеждаться, что 200 OK.
fr_refs: [BRD §3 out-of-scope]