bsl-code-review · git:20260908.3fee1cd · 2026-09-08 · sha256 27c4178dde5b9b0d
bsl-code-review git:20260908.3fee1cdA
Immutable. This exact content never changes and is served at /api/v1/blob/27c4178dde5b9b0d.
--- 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` карточка не попадёт в `examined`. Сравнивать не с чем (новый файл без истории) — `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`); полный перечень по архетипам — `ARCHETYPES[*].refs` в `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 — ревью логики моделью Вызови `advisor()`. Более сильная модель видит весь транскрипт: задачу, шаги, написанный код. Ловит то, что статика не видит в принципе — неверную бизнес-логику, упущенные сценарии, неучтённые состояния. Замечаниям давай весомый вес. ### Холодный читатель — второй взгляд с противоположным входом Дополнительно к `advisor()`, когда цена ошибки высока: класс C3 либо затронуты проведение, деньги, права, необратимые операции. Ценность даёт противоположность входов, а не второе мнение — почему, разбирает `references/cold-reader.md`. **Передавать:** только сравнение версий и содержимое изменённых файлов. **Не передавать:** формулировку задачи, свои выводы, названия найденных проблем — узнавший намерение читатель перестаёт быть холодным. Три вопроса, на которые он отвечает: 1. Что этот код делает **как написан**, а не как задуман? 2. На каких входных данных он ломается или ведёт себя неожиданно? 3. Какое ожидаемое поведение из него не следует? **Модель — не дешёвая:** выносится суждение о логике, уровень не ниже основной модели сессии. Расхождение его выводов с `advisor()` — сигнал, а не шум: код допускает два прочтения. ## Слой 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] ``` Вторая строка — из тех, что печатает инструмент: `attribute-access` стал инструментальным, и написанная руками, она валидатор больше не проходит. Формат — `../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`.