# ADR-2026-08-11. Границу распознавания доменного признака держит норма, а не код - **Дата:** 2026-08-11 - **Источник:** [openspec/changes/archive/2026-08-11-errors-as-instead-of-typecast/design.md](../../openspec/changes/archive/2026-08-11-errors-as-instead-of-typecast/design.md), раздел `Decisions`, Решение 3 ## Решение Признак «работы нет» узнаётся через `errors.As`, то есть на любой глубине цепочки ошибки. Встречный риск — отказ, к которому признак примешался по дороге, — закрыт **требованием спеки**, а не проверкой в коде воркера. Дословно из источника: > Граница ставится **нормой, а не кодом**: спека требует, чтобы признак рождался > только ответом хранилища на опрос этим же шагом, и запрещает слою сохранять > чужой признак в цепочке своей ошибки. ## Почему Приведение типа видело только вершину цепочки — потому и ломалось от первой же обёртки. `errors.As` эту проблему устраняет, но устраняет симметрично: признак теперь виден и там, где его никто не клал осознанно. Отказ, к которому признак примешался обёрткой или `errors.Join`, воркер зачёл бы пустым прогоном — задача осталась бы в своём состоянии и переопрашивалась раз в секунду без единой записи. Это тот же класс, от которого защищает инвариант «Принятая запись не теряется молча», только с обратным знаком относительно чинимого дефекта. Кодовый вариант рассмотрен и отвергнут по цене: > **Рассмотрено и отвергнуто — научить воркер различать «признак на вершине» от > «признака в глубине».** Отвергнуто по цене: `errors.As` такого различения не > даёт вовсе, пришлось бы либо проверять вершину вручную (то есть вернуть > приведение типа, которое чинится), либо заводить свой обход цепочки. Код > усложняется ради случая, которого сегодня нет ни одного, а защита от него нужна > на входе — при написании нового слоя, — где норма работает, а проверка в > рантайме опоздала бы. ## Последствия - `+` код остался коротким: одна проверка вместо разбора цепочки вручную. - `+` защита стоит там, где ошибку совершают, — за письменным столом автора нового слоя, а не в рантайме, где она уже случилась. - `−` норма не механизирована: её нарушение поймает только ревью или чтение. Единственный `MUST` требования `pipeline` без машинного оракула — этот. - `−` правило живёт в двух документах: требованием в [openspec/specs/pipeline/spec.md](../../openspec/specs/pipeline/spec.md) и прозой в [conventions/errors.md](../conventions/errors.md), где оно нужно автору в момент письма. Второй адрес ссылается на первый и нормой не является — разойтись они могут только правкой, сделанной мимо спеки.