Files
dev-skills/av-dev-pm/skills/canon/references/canon.md
T
avandClaude Opus 5 354a6b03d5 канон 4: слаг подкреплён проверкой, обещанный судья заведён
Оба пункта заметок оказались одним классом: правило записано и никем не
исполняется.

Слаги. canon.md говорил «слаги файлов, capability и задач — английские,
kebab-case» одной строкой в хвосте раскладки, а docs.py имён файлов не
смотрел вовсе. Итог нашёлся в самом плагине: единственный пример ADR в
скилле docs назывался ADR-2026-08-03-ochered-tablicej. Раскладка канона
при этом приглашала к нарушению — в схеме стояли плейсхолдеры <тема>.md,
то есть слово «тема» по-русски там, где надо писать <slug>.

docs.py check теперь смотрит имена: кириллица и не-kebab-case жёстко,
форма ADR-ГГГГ-ММ-ДД-slug.md жёстко, транслит эвристикой, то есть
замечанием. Проверяются docs/conventions, docs/research, docs/adr и имена
capability; каталог задач не трогается — его слаги ведёт tasks.py.

Набор маркеров транслита подобран так, чтобы ложных срабатываний не было
вовсе: выброшены ost (ловит post, cost), sch (schema), ya (yaml), nost
(nostalgia), хвост ii (radii). Цена названа в комментарии —
sostoyanie-partii проходит мимо. Правило, краснеющее на правде, приучает
пролистывать весь блок, и это дороже пропуска.

Агенты. В canon.md есть таблица «Что проверяет машина, а что человек», и
её правая колонка — смысловой дубль, поведение в architecture.md,
протухший факт, достаточность честной строки — три версии описывала
работу, которую никто не делал: скилл canon предлагал агенту судить об
этом самому, то есть проверять то, что он же и писал.

Заведены двое, разрез по глубине — тот же довод, что развёл task-form и
doc-wording. doc-consistency читает docs/ и openspec/, сверяет документы
между собой (факт в двух домах, прямое противоречие, поведение в обзоре
вместо спек, ADR без ссылки на design.md и без парного статуса, число без
провенанса, заглушка вместо честной строки) и зовётся на шаге синка
документации. doc-code-drift читает репозиторий, отвечает на «этот факт
ещё верен» и зовётся раз в спринт на сессии.

Перечень фактов, сверяемых с кодом, закрыт: имя ветки, команды, пути,
зависимости поимённо, настройки с числом, единые точки проекта,
capability, проверяемые инварианты. «Сверить архитектуру с кодом» —
задача без дна, и агент, которому её поставили, выдаёт правдоподобную
труху. Отсюда форма его доклада: начинается таблицей проверенного, а не
находками, — по ней видно, чего он не смотрел.

Карта домов уехала в устав doc-consistency помеченной копией: устав
ссылался на файл плагина, а агент работает в репозитории проекта, где
плагина может не быть. copies.py её сторожит.

Попутно: докстрока copies.py показывала закрывающие маркеры как
<!-- /дом -->, а код требует <!-- /дом: <id> -->. Нашлось первой же
попыткой ими воспользоваться.

DECISIONS тема 28 (ННОО–ХХЦЦ, следствия 105–108).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 10:20:39 +03:00

431 lines
34 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Канон документов проекта
**Версия 4.**
Это **единственный дом определения канона**. Скиллы `init`, `canon` и `docs`
читают его, а не пересказывают: три описания одной раскладки разъедутся, и
работать будет то, которое прочитали последним. Меняется канон — меняется этот
файл и появляется запись в [changelog.md](changelog.md).
## Зачем канон жёсткий
Пути фиксированы, и проект под них подгоняется, а не наоборот. Причина не
техническая: проектов много, все малого и среднего размера, и ориентироваться в
слегка похожих, но разных раскладках дороже, чем один раз привести их к общей.
Рядом лежит OpenSpec, у которого структура тоже строгая.
Цена принята сознательно: плагин не переносится на чужой репозиторий как есть —
чужой репозиторий **приводится** к канону скиллом `canon`.
Раскладка отвечает, **где** текст лежит и на какой вопрос отвечает. Каким он
должен быть **словами** — общий для всех документов канона файл
[language.md](language.md): информационный стиль, англицизмы, жаргон. Он
относится и к задачам, и к решениям ADR, и к запискам разведки.
## Сопровождение и эксплуатация — целое и часть
Одна тема живёт в трёх местах канона, и путать их слова нельзя.
**Сопровождение** — всё, чем держат проект: инструмент и сборка, процесс,
выкладка, метрики и логи, инфраструктура, дежурство. **Эксплуатация** — его
часть: работа системы на проде. Целое и часть, и никогда наоборот.
| Место | Уровень | Что там |
| --- | --- | --- |
| `ROADMAP.md`, секция `Сопровождение` | план | **работы**, которые собираемся делать: цели и их задачи |
| `architecture.md`, раздел «Эксплуатация» | состояние | **как устроено сейчас**: где работает, что рядом, кто перезапускает |
| эксплуатационный проход ревью | оптика | **чем проверяем**: «это упало через неделю на проде» |
Слово **«поддержка» не употребляется вовсе** — в нём слышится помощь
пользователю, а это другая работа.
**Граница с возможностями проходит по тому, кто наблюдает.** «Приложение
сообщает о своём состоянии» — возможность приложения, её место среди прочих
целей: наблюдает пользователь сервиса. «Дежурный видит состояние на одном
экране» — сопровождение: наблюдаем мы. Одни и те же метрики попадают в разные
секции роадмапа, и это верно — секции отвечают на разные вопросы.
## Раскладка
```
CLAUDE.md памятка агенту: что это, стек, инварианты с
severity, команды, семантика гейта, запреты
docs/
.pm.json версия канона и пути, нужные проверкам
passport.md зачем и для кого; чем НЕ является; сценарии
architecture.md как сложено — обзор; окружение и эксплуатация
database.md схема хранилища; представление данных и настройки
security.md периметр; недоверенный вход; что вне модели
conventions/
README.md индекс, правило промоута, что механизировано
<slug>.md
research/
README.md как снималось, индекс
<slug>.md наблюдения и числа с провенансом
adr/
README.md индекс записей, статусы, правило замены
template.md
ADR-ГГГГ-ММ-ДД-slug.md
review.md настройка конвейера под проект + журнал дефектов
tasks/ скилл tasks: items/, ROADMAP.md, BACKLOG.md,
SPRINT.md, REJECTED.md
openspec/
config.yaml только нужды генерации артефактов + ссылки
specs/<capability>/spec.md что система делает — нормативно
changes/archive/ архив изменений с design.md — сырьё для ADR
```
### Имена файлов английские, текст русский
**Текст документов русский; имена файлов, capability и задач — английские,
kebab-case.** Причина не эстетическая: имя файла стоит в ссылках из других
документов, в коммитах и в путях, которые набирают руками, — а кириллица в пути
ломается по-разному в разных местах и не набирается на английской раскладке.
**Транслита не заводим.** Слаг именуется английским словом **по сути**, а не
записью русского латиницей: `queue-as-table`, а не `ochered-tablicej`. Транслит
нечитаем тому, кто ищет по смыслу, и не сокращается.
У ADR имя вдобавок несёт форму — `ADR-ГГГГ-ММ-ДД-slug.md`: по ней записи
сортируются, и по ней же ищется дата решения.
`docs.py check` проверяет кириллицу и kebab-case **жёстко**, форму имени ADR —
тоже, а транслит **эвристикой**, то есть замечанием: английское слово от
транслита машина не отличает. Слаги каталога задач ведёт `tasks.py` — там та же
проверка и тот же разрез.
**Переименование — не правка, а перенос ссылок**: делается одним проходом по
всем местам, где имя упомянуто, иначе останутся битые ссылки. Для задач это
умеет `tasks.py adopt`; для документов канона правит человек, а `docs.py` потом
показывает, что ссылки целы.
## Роли документов
Одна строка на каждый — на какой вопрос он отвечает и кто его читает.
| Документ | Вопрос | Кто читает, кроме человека |
| --- | --- | --- |
| `CLAUDE.md` | что нельзя нарушать, чем краснеет гейт | все агенты, всегда |
| `passport.md` | зачем и для кого, чем это **не** является | `architecture`, `rubric`, `reimpl`, `specs` |
| `architecture.md` | как сложено и где что работает | все проходы ревью |
| `database.md` | что лежит в хранилище и какими настройками | `ops`, `adversary`, `reimpl` |
| `security.md` | против кого защищаемся и что вне модели | `adversary` |
| `conventions/` | как мы пишем код | `code` |
| `research/` | что показала реальность, а не документация | `specs`, `reimpl`, `ops`, `adversary` |
| `adr/` | почему решено именно так | `architecture` |
| `review.md` | как настроен конвейер и что уже проскакивало | `triage`, каждый проход — свою часть |
| `openspec/specs/` | что система делает — нормативно | `specs` |
### `passport.md`
Цель; закрытый список потребителей и что каждому нужно; **чем целью не
является** — это граница домена, по которой архитектурный проход судит о
переносе понятия; типовые сценарии; мера, по которой проект считается удавшимся;
референсы, у кого подсматривать.
### `architecture.md` — **обзор, не поведение**
Принципы; компоненты **со ссылками на capability**, а не с пересказом их
требований; **единые точки проекта** — где генерируются идентификаторы и время,
где единственный парсер входного формата, где маппинг доменной ошибки в код
ответа, где общий путь приёма (это материал для вопроса «не появился ли второй
способ»); внешние границы и форматы чужих систем; окружение — где работает, что
рядом, кто перезапускает; **внешние зависимости поимённо** и чем каждая
отказывает (не только «падает», но и «отвечает медленно», «молчит», «отдаёт
мусор»); кто заметит отказ и когда; характер потока — непрерывный, по запросу,
по расписанию; деплой; открытые вопросы.
**Обратимости здесь нет** — её единственный дом `CLAUDE.md`: туда ходят пять
проходов, и раздвоение адреса означало бы, что проект написал ответ, а ревью его
не прочитало.
**Поведение системы сюда не пишется.** Его нормативный дом — `openspec/specs/`,
куда `opsx:archive` вливает дельты; второй дом синхронизировать руками
невозможно, и он разойдётся.
Раздел, ещё не разнесённый при переезде, помечается маркером долга:
```
<!-- канон: поведение → openspec/specs/<capability> -->
```
`docs.py` считает маркеры и печатает остаток числом. Гейт от них **не краснеет**:
это долг, а не отказ, иначе постепенный переезд стал бы невозможен.
### `database.md`
Схема: таблицы, ключи, связи, правило времени и идентификаторов. Плюс то, чего
нет в схеме, но без чего замер не превращается в находку: **чем физически лежит
запись** (сжатый BLOB, JSON-строка, колонки), что происходит при чтении и записи
(распаковка целиком, read-modify-write), и **настройки с числовым значением**
таймаут занятости, режим журналирования, лимит тела, размер пула, ретеншен.
Конвенции идентификаторов и именования — не схема, они в `conventions/`.
### `security.md`
**Периметр первой строкой.** «Сервис открыт наружу» и «контур доверенный,
публичного интернета здесь нет, не выдумывай его» — противоположные постановки
под одним заголовком, и враждебный проход между ними сам не выберет. Контур ещё
не развёрнут — назови **оба** периметра, целевой и сегодняшний, и скажи прямо,
против какого строятся находки.
Дальше: что недоверенное и каким каналом приходит; **из чего строятся пути и
ключи** (раскладка файлов, состав координатного ключа, имя каталога) — отсюда
строится выход за пределы песочницы; что разграничивает доступ; что
чувствительнее чего; **что вне модели** — перечислить явно.
### `conventions/`
Прозой остаётся **только то, что не выражается правилом**. `README.md` держит
индекс, правило промоута и **перечень уже механизированного** со ссылкой на
место механизации — конфиг линтера, собственный анализатор, тест-сканер
исходников. Непойманное место механизации означает, что проход добросовестно
проверит уже проверенное.
### `research/`
Наблюдения за внешним миром: что реально шлёт источник, чем документация формата
расходится с практикой, какие числа сняты с живого потока. **Числа — с
провенансом**, то есть с командой или условиями, которыми получены.
`README.md` — как снималось и индекс тем.
Число без источника проход обязан читать как условие, а не как замер. Число, чей
источник по ссылке не подтвердился, не выбрасывается и не переписывается по
догадке — остаётся с пометкой «расходится с источником: там <что нашли>».
### `adr/`
**ADR — промоут поверх архивных `design.md`, а не второе сочинение.** Запись
цитирует решение и ссылается на `openspec/changes/archive/<id>/design.md`.
Заводится, когда верно одно из трёх:
<!-- дом: adr-когда-заводить -->
- **дорогой откат** — переделка стоит дороже переписывания одного файла;
- **намеренный отказ** от очевидного подхода;
- **пересмотр прежнего решения** — тогда у старой записи обязателен статус
«заменено на».
<!-- /дом: adr-когда-заводить -->
Не заводится для рутины и для того, что видно из кода и `git log`.
Записи неизменяемы: передумали — заводится новая, старая получает статус.
Активная запись статуса не имеет.
**Статус живёт полем меты записи**, там же, где дата и источник:
`- **Статус:** заменено на ADR-…` либо `- **Статус:** устарело`. Места ему в
шаблоне не отводилось, и каждая запись изобретала своё — то абзацем, то
заголовком; в таблице `adr/README.md` статус при этом обязан быть, а брать его
оттуда, где он у каждого свой, нельзя.
### `review.md`
Два раздела с разными сроками жизни.
**Настройка конвейера под проект**, пять подразделов с точными именами — по ним
проходы находят свой кусок:
- **Типовые узлы** — рода узлов проекта и 3–5 проверяемых свойств к каждому;
- **Типовые ложноположительные** — находки, которые здесь выглядят убедительно и
всегда неверны, каждая со строкой «почему здесь это не дефект»;
- **Вопросы к проходам** — поимённо, в форме `<имя прохода>: <вопрос>
(<провенанс>)`;
- **Триггеры профиля** — проектная конкретизация правила выбора профиля ревью:
что в этом проекте считается **новым понятием или структурной единицей** (это
поднимает прогон до `wide`) и **где живут правила идентичности, слияния и
разбора** (до `deep`) — перечнем мест, производным от теста конвейера, а не
вторым определением класса. Уточняет умолчания, а не отменяет их. Рабочее
умолчание — `standard`: миграция схемы и публичный контракт ступень **не**
поднимают, их проверяют проходы, которые в `standard` и так есть;
- **Недоступно проверке** — два подраздела: «не проверит ни один проход»
(принципиальная граница, по факту промаха не пересматривается) и «перестали
проверять сознательно» (пересматривается первым).
**Журнал дефектов:** запись на каждый воспроизведённый дефект с пометкой
**проскочил / пойман ревью**. Проскочившие — эвал-сет для калибровки конвейера,
выборка по пометке. Пойманные с оракулом — лучшая опора для прохода: проектные,
воспроизводимые, однажды оказавшиеся правдой.
### `tasks/`
Раскладку, форму записи и команды держит скилл `tasks` — канон фиксирует имена
файлов (`items/`, `ROADMAP.md`, `BACKLOG.md`, `SPRINT.md`, `REJECTED.md`) и то,
от чего зависит, читается ли проект как продукт.
**`ROADMAP.md` отвечает на «что приложение уже умеет и чего ещё не умеет».** Это
не очередь работ: цель — **возможность приложения**, задача — шаг к ней.
Достигнутая цель из роадмапа **не исчезает** — строка с датой переезжает в
секцию достигнутого, потому что «что умеет» и есть половина вопроса, ради
которого документ открывают. Вторым домом поведения роадмап при этом не
становится: нормативное поведение живёт в `openspec/specs/`, роадмап отвечает,
**когда и в каком порядке** оно появилось.
**У каждой записи есть тип, и тип решает, что с ней можно делать.** Дом типа —
поле меты `Тип` первой строкой; эмодзи в заголовке от него производна. Словарь
закрыт:
| Тип | Что это | Обязательные разделы | Цель |
| --- | --- | --- | --- |
| 🎯 `goal` | возможность приложения | `Завершение` | — |
| ✨ `feature` | снаружи появляется то, чего не было | `Затрагивает`, `Критерии приёмки` | обязательна |
| 🐞 `fix` | поведение расходится с заявленным | `Воспроизведение`, `Затрагивает`, `Критерии приёмки` | нет |
| 🧹 `chore` | обслуживание, поведение не меняется | `Затрагивает`, `Критерии приёмки` | нет |
| 🔬 `research` | исход — знание, а не изменение | `Вопрос`, `Куда ляжет ответ` | нет |
Схема требуется **к взятию в спринт**, а не к заведению: беклог пополняется чаще,
чем разбирается, и требование на входе выгоняло бы в заметки то, что должно
лежать задачей. Запись, не собравшая разделы своего типа, — законное состояние
беклога; невзятой её делает `sprint take`.
Отдельного типа для незаполненной записи нет: «ещё не описано» — состояние, а не
род работы, и называется оно **`research` без раздела «Вопрос»**. Такая запись в
спринт не берётся и лежит в конце своей категории.
Раскладку, форму записи и алгоритм работы над каждым типом держит скилл `tasks`
(`references/task-<тип>.md`); канон фиксирует только словарь типов и то, от чего
зависит, читается ли проект как продукт.
### `CLAUDE.md`
Что это и стек; **инварианты с severity рядом с формулировкой** — по ним проходы
присваивают `critical`, поэтому severity стоит здесь, а не выводится каждым
проходом заново; команды; **семантика гейта** — чем краснеет безусловно и почему,
где логи, что означает исход, чего в гейте намеренно нет, **кто и когда обязан
гонять дорогое вне гейта**.
Плюс то, что нужно git-операциям и проходам и не выводится ниоткуда:
- **имя основной ветки** — от неё считается база диффа
(`git merge-base HEAD <ветка>`), в неё вливает батч, от неё ветвятся задачи.
Угадывание между `master` и `main` ломает интеграцию целиком;
- **что запускать запрещено, с путями** — рабочая БД, боевой каталог данных,
внешние сервисы. Запретом с путями, а не «будь осторожен»;
- **где `testdata`** и что в них лежит; **куда писать временное**;
- **что считается необратимым** — единственный дом: от обратимости зависит вся
шкала ранжирования триажа и право проходов на `critical`;
- **общий станок**, врывающийся в замороженный спринт; **ориентир по размеру
спринта**.
### `openspec/config.yaml`
**Только нужды генерации артефактов** — язык, правила именования capability,
придирки валидатора RFC 2119 — плюс ссылки на документы канона. Правило ревью,
пересказ конвенций и инварианты сюда не пишутся: у них есть свои дома, и второй
дом разойдётся на первой же правке.
## Правило единственного дома
Факт живёт ровно в одном файле; остальные ссылаются. Карта на случай спора:
<!-- дом: карта-домов -->
| Факт | Дом |
| --- | --- |
| поведение системы | `openspec/specs/<capability>/spec.md` |
| почему решено так | `adr/`, источник — архивный `design.md` |
| граница домена, «чем не является» | `passport.md` |
| инвариант и его severity | `CLAUDE.md` |
| что приложение умеет и чего не умеет; порядок работ | `docs/tasks/ROADMAP.md` |
| измеренное число | `research/` |
| настройка с числовым значением | `database.md` |
| периметр и модель угроз | `security.md` |
| что необратимо | `CLAUDE.md` — **не** `architecture.md` |
| единые точки проекта | `architecture.md` |
| имя основной ветки, `testdata`, временный каталог | `CLAUDE.md` |
| что уже механизировано правилом | `conventions/README.md` |
<!-- /дом: карта-домов -->
## Пустое называется пустым
Скелет канона заводится **целиком** с первого дня. Незаполненный документ держит
**одну честную информативную строку**, а не заглушку:
- «внешних зависимостей нет — смотри на диск и на СУБД»;
- «наблюдений на живых данных нет: внешний источник один, формат документирован»;
- «прецедентов не накоплено»;
- «сознательно ничего не отключали»;
- «архитектуры пока нет: кода нет, заводится первой задачей».
Проход читает такую строку **как факт** и не тратит на неё обязательный вопрос.
Отсутствие файла он не может прочитать никак, а «TBD» читает как пробел —
поэтому `docs.py check` отличает честную строку от нетронутого плейсхолдера
шаблона и напоминает о втором.
## Слотов нет
Файлы и каталоги, которых в каноне **нет**, и куда уезжает их содержимое:
| Было | Куда |
| --- | --- |
| `docs/review-brief.md` | документы канона и есть бриф; остаток — в `review.md` |
| `docs/specs/` | `openspec/specs/` (поведение) и `architecture.md` (обзор) |
| `docs/drafts/` | идея → запись `research`; отказ → ADR; порядок → `ROADMAP.md`; размышление → `opsx:explore` |
| `docs/plan.md` | `docs/tasks/ROADMAP.md` |
| `BRIEF.md` | `passport.md` |
| `docs/backlog/` | `docs/tasks/` |
| `docs/review-journal.md`, `docs/review/journal.md` | `docs/review.md` |
## Что проверяет машина, а что человек
Граница объявляется вслух в каждом отчёте: `check`, отчитавшийся «канон
соблюдён» на проекте, где из шести файлов три лишние, хуже отсутствующего.
| Проверяет `docs.py` | Судит агент | Какой |
| --- | --- | --- |
| отсутствующие пути канона | смысловой дубль документа и capability | `doc-consistency` |
| файлы в `docs/` вне канона | поведение, оставшееся в `architecture.md` | `doc-consistency` |
| имя файла не kebab-case латиницей; форма имени ADR | транслит в имени — сверх эвристики | `doc-wording` |
| битые относительные ссылки | прямое противоречие между документами | `doc-consistency` |
| версия канона и её отставание | достаточность честной строки в пустом слоте | `doc-consistency` |
| нетронутый плейсхолдер шаблона | ADR без ссылки на `design.md`, замена без парного статуса | `doc-consistency` |
| маркеры долга — числом | **протухший факт, разошедшийся с кодом** | `doc-code-drift` |
| миграция изменена, а `database.md` нет | зависимость в манифесте, не названная в обзоре | `doc-code-drift` |
| capability без упоминания в `architecture.md` | второй способ там, где обзор обещал единственный | `doc-code-drift` |
| | связность и читаемость | `doc-wording` |
**Агентов двое, и разведены они по глубине, а не по охвату.** `doc-consistency`
читает только `docs/` и `openspec/` — сверка текста с текстом дёшева и зовётся на
каждом синке документации. `doc-code-drift` читает репозиторий и гоняет читающие
команды: дорого, и зовётся раз в спринт и перед приведением проекта к канону.
Слитый агент делал бы дешёвую половину редкой, а дорогую — поверхностной; тот же
разрез, что между `task-form` и `doc-wording`.
**Перечень фактов, которые `doc-code-drift` сверяет с кодом, закрыт** — имя
основной ветки, команды, пути, зависимости поимённо, настройки с числовым
значением, единые точки проекта, capability, проверяемые инварианты. «Сверить
архитектуру с кодом» задача без дна, и агент, которому её поставили, выдаёт
правдоподобную труху вместо находок.
## `docs/.pm.json`
```json
{
"canon": 4,
"migrations": "internal/store/migrations",
"tasks": {
"backlog": "INDEX.md"
}
}
```
`canon` — версия канона, под которую проект приведён, целым числом: обратной
совместимости у канона нет, есть «приведён» и «не приведён». `migrations` — путь
каталога миграций, если БД есть; по нему `docs.py` делает сверку с
`database.md`. `tasks` — настройки каталога задач, переехавшие сюда из прежнего
`<tasks>/.tasks.json`: **один конфиг на весь канон, а не по одному на каталог**.
Внутри `tasks` — **только имена файлов и заголовков** (`items`, `backlog`,
`roadmap`, `sprint`, `rejected`, `sprint_section`, `oracle_word` и заголовки
разделов тела: `criteria_heading`, `surface_heading`, `questions_heading`,
`completion_heading`, `repro_heading`, `question_heading`, `answer_heading`,
`scope_heading`), и ключ пишется, лишь когда имя отличается от умолчания.
**Словаря типов здесь нет** — он закрыт каноном, а не настраивается проектом:
настраиваемый словарь типов разъехался бы на синонимах ровно так же, как
открытый. **Категорий беклога здесь тоже нет:** их дом — заголовки `##` самого
индекса, и второй список сразу разошёлся бы с первым. Неизвестный ключ `tasks.py`
отвергает кодом 3, поэтому лишнее слово в этом объекте останавливает работу с
задачами целиком.
Ключей будет больше по мере роста проверок; неизвестный ключ `docs.py`
игнорирует, отсутствующий — считает «проверка неприменима» и говорит об этом
строкой, а не молчит.