Контур проверки кода BSL: диагностики статического анализатора, антипаттерны производительности и механики платформы, стандарты разработки #stdNNN, именование, верификация сигнатур API и существования общих модулей. Уровень «внутри тела метода» — то, что чинится заменой строк. Вызывается оркестратором quality-gate с готовым профилем изменения; напрямую — по запросу «проверь код», «отревьюй что я написал», «проверь на антипаттерны».
Installs into .claude/skills of the current project.
Are you the author of Bsl Code Review?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/romandredan-bsl-code-review)
---
name: bsl-code-review
description: >-
Контур проверки кода BSL: диагностики статического анализатора, антипаттерны производительности
и механики платформы, стандарты разработки #stdNNN, именование, верификация сигнатур API и
существования общих модулей. Уровень «внутри тела метода» — то, что чинится заменой строк.
Вызывается оркестратором quality-gate с готовым профилем изменения; напрямую — по запросу
«проверь код», «отревьюй что я написал», «проверь на антипаттерны».
license: MIT
---
# bsl-code-review — контур кода
Проверяет то, что чинится **внутри тела метода**: замена строк, без нового шва. Всё, что
требует выделения метода, переноса в другой модуль, нового экспорта или изменения «кто кого
вызывает», принадлежит контуру `bsl-architecture-review` — граница и правила отсева повторов
находок в `shared/routing-contract.md`.
<ЖЁСТКИЙ-ШЛЮЗ>
Только проверка и отчёт. НЕ переписывай логику, запросы, транзакции и права по своей
инициативе. В режиме `--fix` допустимы лишь безопасные категории (см. ниже).
</ЖЁСТКИЙ-ШЛЮЗ>
## Инварианты контура
Пять утверждений, без которых прогон контура недействителен.
1. **Каталог антипаттернов проходится всегда** — читателем либо самостоятельно, но след
печатает `catalog.mjs attest`.
2. **Строку следа инструментальной проверки печатает инструмент** — переноси дословно,
своих находок этого класса не добавляй: результат детерминирован.
3. **Каждое замечание доказуемо**: номер стандарта, код диагностики или название
антипаттерна плюс строка кода. «Так лучше» — не находка.
4. **Пропуск фиксируется.** Недоступный инструмент или субагент даёт `skipped` с причиной;
молчание неотличимо от выполнения.
5. **Файл, который анализатор не разобрал, не проверен** — вердикт «чисто» по нему
невозможен, и в отчёте он назван поимённо.
## Вход
От оркестратора: класс изменения (C0…C3), сработавшие архетипы, список изменённых файлов.
Глубину (Слой 1 / Слой 1+2 / Слой 1+2 с предложением Слоя 3) печатает план (`gate.mjs plan`,
поле `resolved: code=...`) — архетип может поднять её сверх класса, понизить нельзя. При
прямом вызове — определи профиль сам по правилам `quality-gate`.
---
## Слой 1а — статический анализ
Строка плана для `analyzer-run.mjs` — одна команда: она находит корень конфигурации, прогоняет
только изменённые файлы, проверяет часового и формирует записи следа. Вывод — находки по
файлам и готовый блок `## quality evidence`. Перенеси его в отчёт как есть: записи следа по
слою `code` сочинять руками не нужно и нельзя.
**Твоя работа здесь — триаж, а не припоминание.** Список нарушений детерминирован. От тебя
требуется отделить то, что надо чинить сейчас, от того, что является осознанной нормой этого
проекта, и назвать последствие каждой оставленной находки. Коды расшифровывай через
`v8std_explain_diagnostics` и привязывай к номеру стандарта.
Четыре режима вывода, каждый из которых меняет то, что можно утверждать по результату:
- **Информационные находки свёрнуты** в одну строку, полный список — флаг `--all`. В след
коды попадают в любом случае.
- **Проект без основной конфигурации** (репозиторий одного расширения): диагностики о
неразрешённых именах понижены до информационных — обратно **не поднимай**, отличить их от
настоящих ошибок в этом режиме нечем.
- **«НЕ РАЗОБРАНО файлов»** — по этим файлам не проверено **ничего**. Назови их в отчёте
поимённо: вердикт «чисто» по ним невозможен.
- **Часовой `status=not_found`** — прогон недостоверен, вердикт «чисто» запрещён; разберись
с анализатором и повтори.
Что стоит за каждым режимом и известные случаи — `references/analyzer-output.md`. Гейтовый
анализ идёт с конфигом из состава плагина: проектный `subsystemsFilter` вывести изменённые
файлы из проверки не может.
**Если анализатор недоступен** — команда сама запишет
`[qg skipped: layer=code, scope=static-analysis, planned=[bslls:*], reason=analyzer_unavailable]`
и вернёт код 1. Продолжай со Слоя 1б: он ловит другое и от анализатора не зависит.
### Второй движок — сверка со справочником платформы
Строка плана для `platform-context-run.mjs`. Ловит то, чего анализатор не видит вовсе:
несуществующий член платформенного типа, значение системного перечисления, конструктор,
свойство объекта. Всё это компилируется и падает при выполнении. Сервер справки движок
заводит сам: ищет поднятый, а не найдя — ставит закреплённый релиз и поднимает свой по
установленной платформе. Где платформы на машине нет, пишет `skipped` с причиной и
возвращает код 1 — это законный исход.
Два правила: **`info` «низкая уверенность» не отбрасывать** (класс смешанный) и **часовой
`not_found` — «чисто» запрещено**. Остальное — `references/platform-api.md`.
## Слой 1б — то, чего анализатор не видит
### 1. Каталог антипаттернов — субагент `antipattern-reader`
Строка плана для `catalog.mjs index` печатает индекс триггеров; полная карточка читается по
попаданию, не заранее. **Сначала сохрани `git diff HEAD --` по изменённым `.bsl` в файл** —
признаку `qg:AI-11` нужно сравнение версий — у читателя нет оболочки, чтобы построить его
самому, а `attest` вычисляет diff сам и без него карточку не пропустит; переданный файл лишь
сверяется. Сравнивать не с чем (новый файл без истории) — `attest --no-diff-available`
печатает честный `skipped` вместо молчания.
**Делегируй субагенту `antipattern-reader`**: передай вывод `index`, список изменённых `.bsl`
и путь к файлу диффа. Он не знает задачи и возвращает JSON — сохрани в файл: путь к нему,
список файлов и путь к диффу — в строку плана `"$QG/tools/catalog.mjs" attest --diff <файл>`.
Инструмент сверяет полноту списка проверенных признаков, состав файлов и цитату каждой
находки с самим файлом, после чего печатает строки следа `ai-antipatterns` и
`platform-antipatterns` и пишет журнал. Отвергнутый результат — повтори запуск читателя с
его замечаниями, не правь JSON руками. Читателя в среде нет — прогони индекс сам по той же
процедуре и аттестуй так же: строку следа в обоих случаях печатает инструмент.
Признаки с инструментом (`bsl-lint`, `query-lint`, `rename-check`) в проход не входят — их
строки печатают инструменты, а карточка нужна для «как чинить»:
`node "$QG/tools/catalog.mjs" card <ID>`.
### 2. Проверки по тексту кода
Команды — строки плана для `query-lint.mjs`, `bsl-lint.mjs`, `rename-check.mjs`: план
печатает их только когда применимо, а полный список признаков с разбором каждого — в
`references/catalog/INDEX.md` (`qg:BSL-UNBOUNDED-STRING-COLUMN` там же — механическая
половина AI-16). XML идёт в `query-lint` наравне с `.bsl`: `<query>` СКД и `<QueryText>`
динамического списка — тоже носитель запроса.
**`attribute-access` покрыт инструментом лишь частично.** Доказать ссылочность в пределах
одного файла удаётся не всегда: ссылка из чужой функции или из недокументированного параметра
остаётся неопознанной. `clean` здесь означает «механическая часть чиста» и разбора #std437
глазами не отменяет — инструмент задаёт нижнюю границу, а не верхнюю.
Записи следа обоих — по инварианту 2, дословно, без своих находок.
Граф вызовов оба не строят: запрос, собранный конкатенацией или `СтрШаблон`, виден им лишь
частями, и вердикт «чисто» этого не закрывает — разбор приближений в справочнике правила.
### 3. Стандарты под архетип
Не весь свод подряд — только релевантное: справочники и разделы `checklist-code.md`
печатает план (`gate.mjs plan`) — общие разделы всегда, прочие под архетип; перечень —
`BASE_CHECKLIST` и `ARCHETYPES` в `tools/profile.mjs`. Глубокая
вложенность и длинные методы архетипом не считаются и в план не попадают — при такой правке
открывай `bsl-refactoring.md` сам. Тексты самих стандартов запрашивай через MCP `v8std` по
номеру.
### 4. Именование
`#std454` — частая и легко пропускаемая ошибка: сокращения-префиксы, не-CamelCase,
булево не в утвердительной форме. Детали и примеры — в `references/checklist-code.md`.
### 5. Символы в исходнике
В коде и комментариях только ASCII-дефис. Длинное тире и его родственники дают у анализатора
ошибку недопустимого символа. Кавычки-ёлочки допустимы.
### 6. Верификация API — субагент `bsl-verifier`
Сигнатуры платформенных методов, существование и экспортность общих модулей, состав объектов
метаданных. Процедура — `references/api-verification.md`.
**Делегируй субагенту `bsl-verifier`**, передав ему список изменённых `.bsl`-файлов. Он
дешёвый, работает по той же процедуре и возвращает вердикт, список нарушений с локациями и
раздел «Не проверено». Вызов **один на весь список**: каждый лишний инстанс поднимает свою
сессию индекса кода, а справочник платформы на stdio-транспорте вдобавок не переносит
параллельных обращений.
Если прогнан второй движок слоя 1а, платформенная часть уже закрыта: субагенту остаются
общие модули, метаданные и контекст доступности.
Субагента в среде может не быть — тогда прогоняй `api-verification.md` сам. **Результат
обязан попасть в след одинаково в обоих случаях** (инвариант 4):
```
[qg applied: layer=code, scope=api-verification, ids=[qg:API-SIGNATURE,qg:API-MODULE], verdict=clean]
[qg skipped: layer=code, scope=api-verification, reason=platform_unavailable]
```
> Для класса C1 на этом контур завершается — переходи к отчёту.
---
## Слой 2 — ревью логики моделью
Ловит невидимое статике: неверную бизнес-логику, упущенные сценарии и состояния.
Исполнителей два, с противоположными входами — почему, разбирает `references/cold-reader.md`.
| Условие | Исполнитель |
|---|---|
| класс C3 либо затронуты проведение, деньги, права, необратимые операции | субагент `cold-reader` обязательно; `advisor()` — дополнительно, если он есть в среде |
| прочие L2, `advisor()` есть | `advisor()` — видит транскрипт, сверяет обещанное с написанным |
| прочие L2, `advisor()` нет | `cold-reader`; `skipped` законен, только если недоступен и он |
**`cold-reader` получает ровно две вещи:** путь к сохранённому сравнению версий и пути
изменённых файлов. Формулировку задачи, свои выводы и названия найденных проблем не передавай:
узнавший намерение читатель перестаёт быть холодным. Вопросы и формат ответа — в файле агента.
**Модель не ниже модели сессии.** В файле агента стоит `opus`; сессия на модели выше —
передай её параметром `model` при запуске. Расхождение читателя с `advisor()` — сигнал, а
не шум: код допускает два прочтения. Находку читателя без цитаты из файла не принимай.
**Слой заканчивается записью следа** — иначе его пропуск на C3 неотличим от прогона; дефект
без своего признака — `qg:LOGIC-CONTRACT` или `qg:LOGIC-CASE-LOSS`:
```
[qg applied: layer=code, scope=logic-review, ids=[qg:LOGIC-CONTRACT], verdict=violation:qg:LOGIC-CONTRACT]
[qg skipped: layer=code, scope=logic-review, reason=reviewer_unavailable]
```
## Слой 3 — состязательный аудит (только по подтверждению)
**Никогда не запускается сам** — контур лишь предлагает его в отчёте и ждёт явного согласия.
Суть: веер независимых ревьюеров по измерениям, затем по каждой находке несколько
проверяющих, которым поставлена задача её **опровергнуть**. Проходит только то, что
опровергнуть не удалось.
Состав измерений, пороги, правила голосования, асимметрия для находок 🔴 и порядок действий,
когда оркестрация недоступна, — в `../quality-gate/references/adversarial-audit.md`.
---
## Автофикс (`--fix`)
**Можно:** именование (через переименование символа анализатором, не текстовой заменой),
форматирование и отступы, канонические ключевые слова, магические литералы на системные
константы, очевидные quick-fix анализатора.
**Нельзя без подтверждения:** любая правка логики, проведения, запросов; транзакции и
блокировки; права и привилегированный режим; всё, помеченное 🔴; сигнатуры экспортных методов
(ломает вызывающих).
После автофикса прогони Слой 1 заново — правки могли внести новые диагностики.
---
## Выход
### Находки
```
[🔴/🟠/🟡] <краткая суть>
Где: <путь:строка>
Правило: #stdNNN п.X | антипаттерн «<название>» | #bslls:<Код>
Проблема: <что именно не так здесь>
Как исправить: <конкретно; для 🔴 — со ссылкой на пример из справочника>
Уверенность: средняя | требует проверки — опускается при высокой
```
При не-высокой уверенности следом — проверка, которая находку закроет. Довод, снимающий
находку без такой проверки, обязан опираться на прочитанный источник — правило и пример в
`../quality-gate/references/evidence-format.md`.
Ключ локации `<путь>::<Метод>:<строка>` обязателен — по нему оркестратор дедуплицирует
находки с архитектурным контуром (правила — в `shared/routing-contract.md`).
### Записи следа
Минимум одна на каждый слой — выполненный или пропущенный:
```
[qg applied: layer=code, scope=query-in-loop, ids=[std436,bslls:QueryInLoop], verdict=clean]
[qg applied: layer=code, scope=attribute-access, ids=[qg:BSL-REF-DOT-ACCESS,std437], verdict=violation:qg:BSL-REF-DOT-ACCESS]
[qg skipped: layer=code, scope=static-analysis, planned=[bslls:*], reason=analyzer_unavailable]
```
Вторую строку печатает инструмент: написанная руками, она валидатор не проходит.
Формат — `../quality-gate/references/evidence-format.md`.
Два измерения контур закрыть не может и обязан об этом сказать. **Компилируемость тел
модулей** проверяет только платформа: без запуска проверки конфигурации нужна запись
`[qg not_verified: dimension=compilation, reason=no_platform]`, иначе полностью чистый вердикт
валидатор отклонит. **Выполнимость запроса** — то же самое при сработавшем архетипе «Запрос»:
```
[qg applied: layer=code, scope=query-execution, ids=[qg:QRY-EXECUTED], verdict=clean]
[qg not_verified: dimension=query-execution, reason=no_platform]
```
Проверка по тексту кода (пункт 2 Слоя 1б) её не заменяет — «Поле не найдено» и
несовместимость типов в `ОБЪЕДИНИТЬ` всплывают только при выполнении. Почему оба измерения
устроены так — `../quality-gate/references/evidence-format.md`.