architect(ET): auto-commit from architect run_id=126
All checks were successful
CI / test (push) Successful in 11s
All checks were successful
CI / test (push) Successful in 11s
This commit is contained in:
@@ -58,7 +58,7 @@ created → analysis → architecture → development → review → testing →
|
||||
```
|
||||
|
||||
- **Длительность** считается launcher'ом (`_monitor_agent`) и пробрасывается в `_post_usage_comments`; для analyst (коммент строится в `stage_engine`) используется DB-фоллбэк `usage.get_agent_duration(task_id, agent)`.
|
||||
- **Vердикт-парсер** — `src/frontmatter.read_frontmatter_value(...)` (defensive, никогда не raise). Машинные ключи: `verdict:` (reviewer/tester), `deploy_status:` (14-deploy-log.md), `staging_status:` (15-staging-log.md).
|
||||
- **Vердикт-парсер** — `src/frontmatter.read_frontmatter_value(...)` (defensive, никогда не raise). Машинные ключи: reviewer → `verdict:` (12-review.md); **testing-гейт `check_tests_passed` (13-test-report.md) → любое из трёх равноправных: `result:` (канон промпта тестера), `verdict:`, `status:`** (ORCH-047, ADR-001); deployer → `deploy_status:` (14-deploy-log.md), `staging_status:` (15-staging-log.md). Negative-токен в любом поле авторитетен (перебивает positive).
|
||||
- Формат коммента **не** меняет реестр гейтов и стадий; коммент — отображение, не управление.
|
||||
|
||||
## База данных (SQLite)
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
# ADR-001: testing-гейт читает `result:` наравне с `verdict:`/`status:`
|
||||
|
||||
- **Статус:** Accepted
|
||||
- **Дата:** 2026-06-05
|
||||
- **Задача:** ORCH-047
|
||||
- **Область:** SHARED quality-gate `check_tests_passed` (общий прод-инстанс: orchestrator + enduro-trails)
|
||||
|
||||
## Контекст
|
||||
|
||||
Quality Gate `check_tests_passed` (`src/qg/checks.py`, парсер `_parse_tests_verdict`) гейтит
|
||||
переход `testing → deploy-staging`, читая машиночитаемый вердикт ТОЛЬКО из YAML-frontmatter
|
||||
артефакта `13-test-report.md` (канон гейтов: frontmatter, никогда не проза — см.
|
||||
`docs/architecture/README.md`).
|
||||
|
||||
Существует рассинхрон контракта между производителем и потребителем вердикта:
|
||||
|
||||
- **Потребитель** (`_parse_tests_verdict`) читает поля `verdict:` и `status:`.
|
||||
- **Производитель** (`.openclaw/agents/tester.md`, строки 51–56, 78–80) предписывает тестеру
|
||||
эмитить машиночитаемое поле **`result: PASS|FAIL`** и НЕ упоминает `verdict:`/`status:`.
|
||||
|
||||
Тестер, честно следуя своей инструкции, пишет `result: PASS` без `verdict:`/`status:`. Парсер
|
||||
попадает в ветку «ни verdict, ни status не заданы» → `(False, "No machine-readable
|
||||
verdict/status…")` → откат `testing → development` и петля до исчерпания
|
||||
`MAX_DEVELOPER_RETRIES`. Это наблюдалось на ORCH-17; ORCH-016 прошёл лишь потому, что его отчёт
|
||||
избыточно нёс И `verdict:`, И `result:`.
|
||||
|
||||
Корень — несовпадение имён поля контракта, а не логики токенов. Наборы positive/negative-токенов
|
||||
исправны и менять их нельзя (обратная совместимость с реальными отчётами enduro-trails
|
||||
ET-001…ET-014).
|
||||
|
||||
## Решение
|
||||
|
||||
Привести контракт гейта к тому, что тестеру УЖЕ велено эмитить — со стороны гейта, не трогая
|
||||
промпт тестера.
|
||||
|
||||
1. `_parse_tests_verdict` читает **три равноправных** машиночитаемых поля из frontmatter:
|
||||
`result:` (канон промпта тестера), `verdict:`, `status:` (легаси/enduro-trails). Достаточно
|
||||
ЛЮБОГО одного непустого.
|
||||
2. Семантика приоритетов сохраняется и распространяется на все три поля через объединённую строку
|
||||
`fields = f"{verdict} {status} {result}"`:
|
||||
- negative-токен (`_TESTS_NEGATIVE_TOKENS`) в любом поле → FAIL и **авторитетен** (проверяется
|
||||
первым, перебивает positive в другом поле);
|
||||
- иначе positive-токен (`_TESTS_POSITIVE_TOKENS`) в любом поле → PASS;
|
||||
- ни одно из трёх не задано → FAIL («No machine-readable verdict/status/result…»);
|
||||
- заданы, но не распознаны → FAIL.
|
||||
3. Наборы токенов **не изменяются**.
|
||||
4. Парсер не бросает исключений ни на каком вводе (битый YAML, пустой файл, frontmatter-не-mapping)
|
||||
→ всегда `(False, reason)`.
|
||||
5. Сигнатура `check_tests_passed`, имя гейта и реестр `QG_CHECKS` **не меняются** — снапшот
|
||||
`tests/test_qg_registry_snapshot.py` остаётся зелёным.
|
||||
|
||||
### Альтернативы (отклонены)
|
||||
|
||||
- **Править промпт тестера** (`verdict:` вместо `result:`) — отклонено: контракт уже задокументирован
|
||||
для тестера как `result:`; единичная правка гейта дешевле и не требует переучивать агента, плюс
|
||||
ломала бы совместимость со старыми отчётами, где встречается `verdict:`/`status:`.
|
||||
- **Глобальный ADR в `docs/architecture/adr/`** — не требуется: изменение не добавляет гейт/стадию/
|
||||
компонент и не меняет топологию; это приведение парсинга существующего гейта к контракту. Канон
|
||||
гейтов в README обновляется точечно.
|
||||
|
||||
## Последствия
|
||||
|
||||
- **Плюс:** корректные отчёты `result: PASS` проходят гейт; `result: FAIL` надёжно откатывает.
|
||||
Петля `testing ↔ development` устранена для всех проектов общего инстанса.
|
||||
- **Плюс:** полная обратная совместимость — отчёты только с `verdict:`/`status:` работают как
|
||||
раньше; существующие тесты `TestCheckTestsPassed` зелёные без правок (кроме обновления reason-текста
|
||||
«…verdict/status…» → «…verdict/status/result…»).
|
||||
- **Минус/ограничение:** число распознаваемых имён поля растёт до трёх — формально шире поверхность
|
||||
«случайного PASS». Митигируется тем, что negative-токен авторитетен и читается только frontmatter.
|
||||
- **SHARED-риск:** изменение затрагивает enduro-trails наравне с orchestrator. Регресс по наборам
|
||||
токенов недопустим → они заморожены; покрытие — `04-test-plan.yaml` (AC-04/AC-05).
|
||||
- **Self-hosting:** деплой строго через `deploy-staging` (8501); прод-контейнер `orchestrator`
|
||||
(8500) не перезапускать в рамках разработки/тестинга.
|
||||
|
||||
## Связи
|
||||
|
||||
- BRD/ТЗ: `docs/work-items/ORCH-047/01-brd.md`, `02-trz.md`.
|
||||
- Канон гейтов и вердикт-парсер: `docs/architecture/README.md`.
|
||||
- Промпт-производитель: `.openclaw/agents/tester.md` (`result: PASS|FAIL`).
|
||||
- adr-0003 (staging-гейт) — обязательная страховка перед прод-деплоем self.
|
||||
10
docs/work-items/ORCH-047/10-tech-risks.md
Normal file
10
docs/work-items/ORCH-047/10-tech-risks.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# Технические риски — ORCH-047
|
||||
|
||||
| # | Риск | Вероятность | Влияние | Митигация |
|
||||
|---|------|-------------|---------|-----------|
|
||||
| R-1 | Регресс набора токенов ломает enduro-trails (SHARED-гейт, общий прод-инстанс) | Низкая | Высокое | Наборы `_TESTS_NEGATIVE_TOKENS`/`_TESTS_POSITIVE_TOKENS` **заморожены** (не трогать). Покрытие AC-05 на реальных формах ET-001…ET-014 + ORCH-016. |
|
||||
| R-2 | Новое поле `result:` расширяет поверхность ложного PASS | Низкая | Среднее | Negative-токен авторитетен (проверяется первым, перебивает positive). Читается только frontmatter, не проза (AC-03, AC-06, AC-07). |
|
||||
| R-3 | Парсер бросает исключение на битом вводе → падение `_run_qg` | Низкая | Высокое | Defensive-контракт сохранён: любой ввод (нет frontmatter / битый YAML / не-mapping / пустой) → `(False, reason)`, никогда raise (AC-08). |
|
||||
| R-4 | Незаметное изменение реестра гейтов | Очень низкая | Среднее | Сигнатура, имя гейта и `QG_CHECKS` неизменны; снапшот `tests/test_qg_registry_snapshot.py` зелёный (AC-10). |
|
||||
| R-5 | Self-hosting: деплой роняет прод-контейнер всех проектов | Низкая | Высокое | Деплой только через `deploy-staging` (8501); прод `orchestrator` (8500) не перезапускать в dev/test (CLAUDE.md, adr-0003). |
|
||||
| R-6 | Изменение поведения без обновления golden-source доки → REQUEST_CHANGES на review | Средняя | Низкое | ADR-001 заведён; `docs/architecture/README.md` (вердикт-парсер) обновлён архитектором; `CHANGELOG.md` — дев в том же PR (AC-11). |
|
||||
Reference in New Issue
Block a user