# adr-0009: Толерантность staging-вердикта к заведомо инфраструктурным FAIL

- **Статус:** accepted
- **Дата:** 2026-06-07
- **Задача:** ORCH-061
- **Детально:** `docs/work-items/ORCH-061/06-adr/ADR-001-staging-infra-tolerance.md`

## Контекст
Self-hosting `orchestrator` зацикливался на `deploy-staging`: `staging_check.py`
давал 2 ложных FAIL (C9a — ветка в sandbox, C9b — analyst-job в очереди), вызванных
отсутствием sandbox-настроек (bot-аккаунты не члены SANDBOX-проекта), а не регрессом
кода. `staging_check.py` делал `sys.exit(1)` при любом FAIL → deployer писал
`staging_status: FAILED` → `check_staging_status` FAILED → откат `deploy-staging →
development` → петля (жгла developer-ретраи и кредиты). Прод-деплой орка приходилось
доводить вручную — блокер автономного внедрения (ORCH-54).

## Решение
Классифицировать проверки staging-suite на **REAL** (pipeline) и **SANDBOX_INFRA**
(заведомо инфраструктурные, узкий allowlist `{C9a, C9b}`) и сделать вердикт
толерантным к инфра-FAIL, сохранив fail-closed для реальных проверок:

- Новый leaf-модуль `src/staging_verdict.py` (pure, never-raise, stdlib):
  `classify_check(label)` + `compute_staging_verdict(items, infra_tolerant)`.
  Правило: упала хоть одна REAL → FAILED/exit1; упали ТОЛЬКО SANDBOX_INFRA и
  толерантность вкл → SUCCESS/exit0 (waived); толерантность выкл → legacy strict
  (любой FAIL → FAILED).
- `scripts/staging_check.py` помечает проверки категориями, считает вердикт через
  `staging_verdict`, печатает `INFRA-WAIVED` при вайвере (наблюдаемость).
- Kill-switch `staging_infra_tolerance_enabled` (env
  `ORCH_STAGING_INFRA_TOLERANCE_ENABLED`, дефолт `True`; в `.env.staging`).
- `check_staging_status` / `_parse_staging_status` / `STAGE_TRANSITIONS` / реестр
  `QG_CHECKS` — **без изменений**; новый QG-чек не вводится. Условность ORCH-35
  сохранена (не-self → no-op N/A).
- Инвариант FR-3: «no changes to commit» на action-стадиях (`deploy-staging`/`deploy`)
  не есть недовыполнение — продвижение определяется exit0 + гейт-вердиктом
  (launcher уже не откатывает; добавлена observability-строка).

## Альтернативы
- Только починить sandbox-инфру (направление а) — хрупко, не структурно, вне
  автономной досягаемости таска; оставлено как опциональное hardening.
- «Зелёный по умолчанию» при недоступности проверок — запрещён (fail-closed).
- Новый QG-чек / структурный артефакт `15-staging-log.md` — избыточно, меняло бы
  контракты/реестр; толерантность размещена в suite до артефакта.

## Последствия
- Петля устранена; страховка цела (реальный регресс → FAILED → откат).
- Чистая вердикт-логика юнит-тестируема без live staging/docker.
- Контракты гейтов/стадий/вердиктов/реестра и схема БД неизменны.
- Риск: узкое окно — реальный регресс именно в создании ветки/постановке
  analyst-job может быть заваивен; митигировано allowlist'ом `{C9a,C9b}` + условием
  «все REAL (вкл. C7/C8) зелёные» + INFRA-WAIVED-логом. Разблокирует ORCH-54.

## Связи
adr-0003 (условный staging-гейт — база `is_self_hosting_repo` / `check_staging_status`),
adr-0006 (merge-gate), adr-0007 (исполняемый self-deploy), adr-0008 (провенанс
staging-образа). Блокирует ORCH-54.
