58 lines
6.7 KiB
Markdown
58 lines
6.7 KiB
Markdown
# BRD — ORCH-047: check_tests_passed должен читать поле `result:` из тест-отчёта
|
||
|
||
## 1. Контекст и проблема
|
||
|
||
Quality Gate `check_tests_passed` (`src/qg/checks.py`, функция-парсер `_parse_tests_verdict`) гейтит переход `testing → deploy-staging`. Он читает машиночитаемый вердикт из YAML-frontmatter артефакта `13-test-report.md`.
|
||
|
||
**Дефект (обнаружен дев-агентом в ходе ORCH-17, подтверждён 05.06.2026):**
|
||
парсер читает ТОЛЬКО поля `verdict:` и `status:`. Однако промпт тестер-агента (`.openclaw/agents/tester.md`, строки 51–56 и 78–80) предписывает эмитить машиночитаемое поле **`result: PASS|FAIL`** — и НЕ упоминает ни `verdict:`, ни `status:`.
|
||
|
||
В результате тестер, честно следующий своей инструкции (реальный отчёт ORCH-017: `result: PASS`, без `verdict:`/`status:`), упирается в ветку «ни verdict, ни status не заданы» → гейт возвращает `False` с причиной *"No machine-readable verdict/status in test report frontmatter"* → задача откатывается `testing → development`.
|
||
|
||
**Последствие:** ЛЮБАЯ задача, где тестер пишет `result: PASS` (то есть строго по своей инструкции), застревает в бесконечной петле `testing ↔ development` до исчерпания `MAX_DEVELOPER_RETRIES`. Именно это крутило ORCH-17. ORCH-016 прошёл раньше лишь потому, что его отчёт избыточно нёс И `verdict:`, И `result:`.
|
||
|
||
**Корень:** рассинхрон контракта. Гейт (потребитель) и промпт тестера (производитель) описывают разные имена машиночитаемого поля.
|
||
|
||
## 2. Бизнес-цель
|
||
|
||
Привести контракт гейта `check_tests_passed` в соответствие с тем, что тестер-агенту реально велено эмитить, чтобы корректные тест-отчёты (`result: PASS`) проходили гейт, а отрицательные (`result: FAIL`) — надёжно откатывали задачу. Устранить ложноотрицательные срабатывания, ломающие конвейер всех проектов.
|
||
|
||
## 3. Заинтересованные стороны
|
||
|
||
- **Owner / Стрим, Слава** — выявили дефект при разборе ORCH-17 (05.06).
|
||
- **Все проекты общего прод-инстанса** (orchestrator self-hosting + enduro-trails) — потребители shared quality-gate. Это SHARED-изменение, влияет на всех.
|
||
- **Тестер-агент** — производитель `13-test-report.md`.
|
||
|
||
## 4. Объём работ (scope)
|
||
|
||
### В объёме
|
||
- `_parse_tests_verdict` читает `result:` как первоклассное машиночитаемое поле НАРАВНЕ с `verdict:` и `status:`.
|
||
- Семантика приоритетов сохраняется и распространяется на все три поля:
|
||
- negative-токен в ЛЮБОМ из трёх (`result`/`verdict`/`status`) → FAIL и авторитетен (перебивает positive в другом поле);
|
||
- при отсутствии negative — positive-токен в ЛЮБОМ из трёх → PASS;
|
||
- ни одно из трёх полей не задано → FAIL (нет машиночитаемого вердикта);
|
||
- заданы, но не распознаны → FAIL.
|
||
- Обратная совместимость: отчёты, несущие только `verdict:`/`status:` (стиль enduro-trails ET-001…ET-014, ORCH-016), продолжают работать ровно как раньше.
|
||
- **ADR** на изменение семантики shared testing-гейта (правило 2 CLAUDE.md — обязательно для сквозного изменения).
|
||
- Обновление документации: `docs/architecture/README.md` (строка про машинные ключи вердикт-парсера), `CHANGELOG.md`.
|
||
|
||
### Вне объёма
|
||
- Изменение промпта тестера (`.openclaw/agents/tester.md`). Контракт приводится со стороны гейта к тому, что тестеру УЖЕ велено эмитить; промпт не трогаем.
|
||
- Изменение других гейтов (`check_reviewer_verdict`, `check_deploy_status`, `check_staging_status`) — у них свои поля (`verdict:`, `deploy_status:`, `staging_status:`), они вне этого дефекта.
|
||
- Изменения ORCH-017 (про ссылки) — это отдельный work item.
|
||
|
||
## 5. Ограничения и риски
|
||
|
||
- **SHARED quality-gate, общий прод-инстанс.** Изменение затрагивает enduro-trails наравне с orchestrator. Регресс недопустим: набор положительных/отрицательных токенов и поведение для старого формата (`verdict:`/`status:`) должны остаться неизменными.
|
||
- **Self-hosting.** Орк правит сам себя; деплой проходит через обязательную стадию `deploy-staging` (8501). Прод-контейнер `orchestrator` (8500) не ронять.
|
||
- Изменение читает только frontmatter, никогда не прозу (канон гейтов из `docs/architecture/README.md`).
|
||
- Парсер не должен бросать исключения ни при каком вводе (битый YAML, пустой файл, frontmatter-не-mapping) → всегда `(False, reason)`.
|
||
|
||
## 6. Эталонный код
|
||
|
||
Дев-агент уже написал референс-реализацию в ветке `feature/ORCH-017` (`src/qg/checks.py` + `tests/test_qg.py`, 23 теста). Его допустимо использовать как ориентир, но оформить чисто через данный work item с собственным ADR.
|
||
|
||
## 7. Критерий успеха
|
||
|
||
Тест-отчёт с одним лишь `result: PASS` проходит гейт `check_tests_passed`; с `result: FAIL` — нет. Старый формат (`verdict:`/`status:`) не регрессирует. Все pytest зелёные. ADR заведён.
|