analyst(ET): auto-commit from analyst run_id=145
All checks were successful
CI / test (push) Successful in 13s
CI / test (pull_request) Successful in 13s

This commit is contained in:
2026-06-06 05:06:33 +00:00
parent 9538103eff
commit 8b5b1f0056
4 changed files with 345 additions and 0 deletions

View File

@@ -0,0 +1,95 @@
# 02 — Техническое задание (ТЗ / TRZ)
**Work Item:** ORCH-048
**Title:** staging B6 check reads registry from host worktree, not staging container
**Stage:** analysis
**Author:** analyst
**Date:** 2026-06-06
> Это ТЗ фиксирует требования и инварианты. Выбор одного из трёх архитектурных вариантов (§4) — за архитектором (ADR). Анализ варианты НЕ выбирает.
---
## 1. Задействованные модули
| Путь | Роль | Характер изменений |
|------|------|--------------------|
| `scripts/staging_check.py` | Suite живых staging-проверок; блок B6 (~строки 263284) | **Изменяется** — переписать механику получения реестра в B6 |
| `tests/` (новый файл, напр. `tests/test_staging_check_b6.py`) | Unit-тест корректности B6 | **Создаётся** |
| `docs/operations/STAGING_CHECK.md` | Док запуска suite | **Обновляется** (описание B6 + способ запуска) |
| `docs/architecture/README.md` / `CHANGELOG.md` | Golden source | **Обновляется** при необходимости |
### НЕ изменять (жёсткий инвариант scope)
- `src/projects.py` — реестр работает корректно.
- `.env`, `.env.staging`, `.env.example` — конфиг верен.
- Прод-логику оркестратора (`src/main.py` прод-роуты, `src/webhooks/*`, `src/stage_engine.py`, `src/qg/*`) — кроме случая варианта (а), если архитектор решит добавить read-only эндпоинт (см. §4а, отдельно обоснованный риск).
- Блоки A1A3, B4, B5 и блок C E2E в `staging_check.py`.
## 2. Текущее поведение (то, что чиним)
Блок B6 (`scripts/staging_check.py`):
```python
sys.path.insert(0, "/repos/orchestrator") # хост-worktree path
import importlib
if "src.projects" in sys.modules:
importlib.reload(sys.modules["src.projects"]) # перечитывает env ТЕКУЩЕГО процесса
from src.projects import known_plane_project_ids
known = known_plane_project_ids()
```
Проблема: реестр строится из `ORCH_PROJECTS_JSON` **process-env того процесса, в котором исполняется скрипт**. При запуске деплоером с хоста (`python3 scripts/staging_check.py --base-url http://localhost:8501`) переменная не задана → `_DEFAULT_PROJECTS` (ET+ORCH) → ложный FAIL. B6 не отражает реестр работающего staging-инстанса.
## 3. Требуемое поведение (контракт B6)
| ID | Требование |
|----|------------|
| TR-1 | B6 определяет набор «известных staging-инстансу Plane project id» из источника, который **гарантированно отражает окружение работающего staging-инстанса** (порт 8501 / контейнер `orchestrator-staging`), а не из локального импорта в process-env скрипта. |
| TR-2 | B6 PASS ⟺ `SANDBOX_PROJECT_ID ∈ known` И `PROD_ET_PROJECT_ID ∉ known` И `PROD_ORCH_PROJECT_ID ∉ known`. Идентификаторы — те же константы, что уже в скрипте. |
| TR-3 | B6 сохраняет формат вывода `Results.add(label, passed, detail)` с человекочитаемым detail (`sandbox=…, prod-ET=…, prod-ORCH=…`). |
| TR-4 | При недоступности источника реестра B6 даёт **детерминированный FAIL** с понятным detail (не падает с необработанным исключением, не даёт ложный PASS). |
| TR-5 | Скрипт остаётся на stdlib (без сторонних зависимостей), если выбранный вариант это допускает. |
| TR-6 | Удаляется зависимость B6 от хардкод-пути `/repos/orchestrator` для построения реестра (host-path хак), несовместимого с целью проверки. |
## 4. Варианты реализации (выбор — архитектор, в ADR)
Бизнес-запрос предлагает три варианта. Анализ перечисляет их с известными плюсами/минусами; решение и обоснование — в `06-adr/`.
### (а) HTTP-эндпоинт staging-инстанса
B6 запрашивает реестр у работающего staging-инстанса по HTTP (как делают A/B4/B5/C).
- **Сейчас подходящего эндпоинта НЕТ.** `/health`, `/status`, `/queue` реестр проектов не отдают (`src/main.py`).
- Потребуется добавить read-only эндпоинт (напр. `GET /projects`, отдающий `known_plane_project_ids()` или список репо/prefix). Это касается прод-`main.py` → выходит за «не трогать прод-логику», но изменение read-only и низкорисковое — архитектор взвешивает.
- Плюс: B6 гарантированно читает реестр именно того процесса, что обслуживает webhooks. Единый HTTP-стиль с остальными чеками.
### (б) Subprocess в окружении staging-контейнера
B6 выполняет `docker exec orchestrator-staging python3 -c "from src.projects import known_plane_project_ids; ..."` и парсит stdout.
- Плюс: не трогает прод-`main.py`; читает env контейнера напрямую.
- Минус: требует доступности docker-CLI и имени контейнера из среды запуска suite; усложняет запуск «изнутри контейнера»; есть нюансы экранирования (см. `docs/history/LESSONS_2026-06-05.md`).
### (в) Запуск suite внутри контейнера + чтение собственного process-env
Канонизировать запуск `staging_check.py` ВНУТРИ `orchestrator-staging` (`docker exec orchestrator-staging python3 …`), убрать `sys.path.insert(0, "/repos/orchestrator")`, импортировать `src.projects` из кода контейнера (его cwd/PYTHONPATH), env уже staging.
- Плюс: минимально инвазивно, не трогает прод-логику и `src.projects`; согласуется с «рекомендуемым способом запуска» в `STAGING_CHECK.md §Способы запуска.1`.
- Условие: деплоер должен запускать suite через `docker exec` (а не с хоста). Нужно синхронно обновить `.openclaw/agents/deployer.md` и `STAGING_CHECK.md`, иначе host-запуск воспроизведёт баг.
- Нюанс: внутри контейнера код лежит в `/app` (Dockerfile `COPY`), а `/repos/orchestrator` — отдельный mount; импорт должен резолвиться из кода, чьим env реально живёт инстанс.
## 5. Изменения API
- Варианты (б) и (в): **нет** изменений API.
- Вариант (а): новый read-only эндпоинт (напр. `GET /projects`) — точная схема ответа определяется архитектором. Если выбран — задокументировать в `docs/architecture/README.md` (таблица API) и `CHANGELOG.md`.
## 6. Изменения схемы БД
Нет.
## 7. Требования к новым QG checks
Нет новых QG. Поведение `check_staging_status` (ADR-0003) не меняется — меняется только достоверность одного из чеков suite, чей агрегат пишется в `15-staging-log.md`.
## 8. Артефакты pipeline, создаваемые/обновляемые
- Код: `scripts/staging_check.py` (B6), новый тест в `tests/`.
- Док: `docs/operations/STAGING_CHECK.md`; при выборе варианта (а) — `docs/architecture/README.md` (API) и `CHANGELOG.md`; при выборе (в) — `.openclaw/agents/deployer.md` (способ запуска) и `STAGING_CHECK.md`.
- ADR: `docs/work-items/ORCH-048/06-adr/ADR-001-*.md` — обоснование выбранного варианта.
## 9. Тестируемость
- Логика «PASS/FAIL по набору known id» B6 должна быть выделена в чистую, юнит-тестируемую функцию (напр. `_evaluate_b6(known: set[str]) -> tuple[bool, str]`), чтобы тест проверял оба исхода без поднятия staging-инстанса/docker. План — `04-test-plan.yaml`.
## 10. Definition of Done
- BR-1…BR-5 (01-brd) выполнены.
- staging-прогон → B6 PASS; `pytest tests/ -q` зелёный.
- Док и (при необходимости) ADR обновлены в том же PR.