AGENTS.md · git:20260810.6f985a1 · 2026-08-10 · sha256 1e9eeaf259f9713c

AGENTS.md git:20260810.6f985a1A

Immutable. This exact content is served forever at /api/v1/blob/1e9eeaf259f9713c.

# AGENTS.md

Инструкции для агента, работающего **над самим плагином** (не для тех, кто его использует).
Дополняет `CLAUDE.md`, а не заменяет его: принципы конструкции и правила, нарушение которых
ломает плагин, описаны там.

## Что это за проект

`1c-quality-gate` — плагин Claude Code для контроля качества разработки на 1С:Предприятие
(язык BSL, XML-выгрузки конфигураций и расширений). Версия — в
`.claude-plugin/plugin.json`, в документации не дублируется.

Плагин делает четыре вещи:

1. **Блокирующий гейт.** Правка файла 1С (через `PostToolUse`-хук на `Write|Edit|MultiEdit`)
   взводит гейт; `Stop`-хук не даёт завершить сессию, пока гейт не снят. Снятие возможно
   только с машиночитаемым следом проверок (evidence), который проверяется валидатором.
2. **Четыре контура проверки:** код BSL (статический анализатор + антипаттерны), архитектура
   (SOLID/GRASP/паттерны для 1С), XML-структуры метаданных, гигиена файлов.
3. **Адаптивная глубина прогона** по трём осям: объём правки (C0…C3), архетипы кода
   (множество меток), сложность. Итог — `max` по осям.
4. **Честность про непроверенное.** Недоступный инструмент — не тишина, а запись `skipped`
   с причиной; полностью зелёный отчёт без записи `not_verified` валидатор отклоняет.

Это **не линтер**: плагин запускает внешние статические анализаторы (`itrous/bsl-analyzer`
по умолчанию, `1c-syntax/bsl-language-server` запасной), а не заменяет их.

## Язык

Отвечать и писать файлы **по-русски**. Код, команды, имена файлов, идентификаторы и
технические термины — в оригинале. Комментарии в коде — тоже по-русски.

## Раскладка репозитория

```
.claude-plugin/plugin.json       манифест (только метаданные; version обязателен)
.claude-plugin/marketplace.json  маркетплейс-манифест (version держать синхронно с plugin.json)
.mcp.json                        MCP-серверы ПЛОСКИМ объектом, без обёртки mcpServers
skills/<имя>/SKILL.md            навыки; имя в frontmatter = имя каталога
skills/<имя>/references/         справочники навыков (чеклисты, антипаттерны, карты)
agents/<имя>.md                  субагенты (bsl-verifier)
commands/<имя>.md                слэш-команды (/gate, /gate-status)
hooks/hooks.json                 хуки; пути только через ${CLAUDE_PLUGIN_ROOT}
hooks/_shared.mjs                общая механика хуков (чтение payload, корень проекта)
tools/*.mjs                      исполняемые проверки (Node.js, без зависимостей)
tools/xml/*.py                   валидаторы XML метаданных (Python 3.8+)
shared/                          знание, общее для нескольких навыков (routing-contract.md)
assets/analyzer/                 конфиги анализаторов, runtime-manifest.json, sentinel-фикстура
tests/run-tests.mjs              тесты программных проверок
tests/fixtures/                  фикстуры (байтовые — генерируются, не хранятся)
docs/                            INSTALL.md, analyzer-integration.md, false-positives-cfe.md
```

Компоненты **не перечисляются** в манифесте — Claude Code подхватывает их по соглашению об
именах каталогов.

## Технологический стек

- **Node.js 18+** (ES-модули, `node:`-импорты) — все хуки и инструменты в `tools/`.
  **Зависимостей нет** и быть не должно: `node_modules/` и `package-lock.json` в `.gitignore`
  как защита от случайного `npm i`. `package.json` в проекте нет — скрипты запускаются
  напрямую: `node tools/<имя>.mjs`.
- **Python 3.8+** — валидаторы XML в `tools/xml/` (стандартная библиотека, `-Path` —
  универсальное имя параметра у всех валидаторов).
- **Внешние бинарники:** статический анализатор BSL плагин скачивает сам при первом прогоне
  (`tools/analyzer-bootstrap.mjs`): закреплённый релиз из `assets/analyzer/runtime-manifest.json`,
  проверка SHA-256 и размера до запуска, установка в каталог данных плагина.
- **MCP-сервис v8std** (`https://ai.v8std.ru/mcp`, объявлен в `.mcp.json`) — обязательная
  зависимость, тексты стандартов #stdNNN запрашиваются через него во время работы.

## Команды перед коммитом

```bash
node tests/run-tests.mjs             # тесты программных проверок (самодостаточный раннер)
node tools/validate-package.mjs      # целостность пакета, ссылки, утечки проектных данных
node tools/gen-signs-map-md.mjs      # перегенерация signs-map.md, если менялся signs-map.json
```

То же гоняет CI (`.github/workflows/validate.yml`, Node 20 + Python 3.12 на ubuntu-latest)
плюс компиляция Python-валидаторов (`python -m compileall tools/xml`) и сверка производной
`signs-map.md` с источником через `git diff --exit-code`.

## Как устроена механика гейта

- Состояние — в проекте пользователя: `.claude/.state/qg-pending.json` (взведённые гейты) и
  `qg-done.json` (журнал снятий). **Именуется по сессии** (`session_id` из payload хука) —
  общий на проект маркер запирает сессию, которая правила совсем другие файлы.
- `hooks/gate-arm.mjs` (PostToolUse) — взводит гейт на правках `.bsl`/`.os` и XML метаданных
  (классификация — по маркерам выгрузки 1С: `Configuration.xml`, `cf/`, `cfe/`, типовые
  каталоги объектов). В не-1С проектах плагин обязан молчать. Вывод — JSON с
  `hookSpecificOutput.additionalContext`, иначе до модели не доходит.
- `hooks/gate-check.mjs` (Stop) — блокирует завершение своей сессии (exit 2), пока гейт не
  снят. Любая внутренняя ошибка хуков — молча exit 0: хук качества не имеет права ломать
  работу.
- `tools/gate.mjs` — единственный законный путь снятия: `release --evidence <файл>` либо
  `release --class C0|C1 --reason "<почему>"` (для C2/C3 только след; заявленный класс
  сверяется с реальным охватом). Команда `verify --layer <code|arch|xml|hygiene>` отмечает
  файлы проверенными; отметку снимает следующая правка.
- Формат следа описан в `skills/quality-gate/references/evidence-format.md`; валидируется
  `tools/evidence-validator.mjs` (режим `--gate` для снятия гейта).
- `tools/config.mjs` — единственный читатель `.1c-quality-gate.json`: умолчания → файл →
  переменные окружения. Новый настраиваемый параметр заводится ТОЛЬКО через `DEFAULTS` этого
  модуля: ключ, которого там нет, объявляется неизвестным, а не применяется молча. Сам файл
  создаёт `gate-arm` при первом взводе — это единственное место, где уже известно, что проект
  на 1С; повторно после удаления не создаётся (маркер `.claude/.state/qg-config-init.json`).

## Правила, нарушение которых ломает плагин

- **Пути только через переменные.** `${CLAUDE_PLUGIN_ROOT}` внутри плагина,
  `${CLAUDE_PROJECT_DIR}` для проекта пользователя. Абсолютный путь работает только у автора.
- **Никаких проектных данных.** Плагин публичный: имена систем, модулей, полей внешних
  контрактов, пути машин автора в артефакт не попадают. Проверяется автоматически —
  `node tools/validate-package.mjs`.
- **Тексты стандартов не воспроизводятся.** Публикуются только ссылки и номера вида
  `#stdNNN`; тексты запрашиваются через MCP `v8std` во время работы. Это лицензионное
  ограничение, а не стиль (подробности — в `LICENSE`).
- **Frontmatter навыков — только поддерживаемые поля.** `inclusion`, `fileMatchPattern` и
  подобные из других сред молча не работают: навык просто не активируется. Триггеры по типам
  файлов живут в хуках.
- **Frontmatter `name` навыка = имя каталога**, иначе навык не подхватится.

## Тестирование

- Раннер — `tests/run-tests.mjs` (`node tests/run-tests.mjs [--verbose]`), самодостаточный,
  без тест-фреймворка; коды выхода 0/1. Рабочий каталог — во временной папке ОС.
- Покрывается только то, что является **кодом**: гигиена файлов, сверка «диск ↔ состав»
  (`tools/xml/orphan-check.mjs`), валидатор следа, механика гейта, нормализация вывода
  анализаторов, манифест установки.
- Контуры `code` и `arch` — инструкции для модели, программно их прогнать нельзя. Для них
  тесты проверяют только **полноту правил** (что строка про конкретный антипаттерн не
  исчезла). Это ловит регрессию удаления, но не качество применения.
- **Фикстуры с байтовой семантикой генерируются, а не хранятся** (git нормализует переводы
  строк и может снять BOM). Невидимые символы задаются кодом (`String.fromCharCode`), а не
  литералом. Хранимые фикстуры с значимыми байтами помечены `-text` в `.gitattributes`.
- **Новая проверка приходит с двумя тестами:** что находит дефект, и что молчит на заведомо
  корректном коде. Тесты проверяются мутациями: сломай проверку намеренно — тест обязан
  упасть. Тест, который не падает при поломке, хуже отсутствующего.

## Принципы конструкции (держать в голове при любой правке)

- **Пропуск проверки обязан оставлять след.** Невыполненная проверка неотличима от
  выполненной, если после неё ничего не остаётся. Недоступный инструмент → запись `skipped`
  с причиной, а не тишина.
- **Вердикт «чисто» обязан признавать непроверяемое.** Компилируемость тел BSL-модулей не
  проверяется ничем, кроме платформы; полностью зелёный отчёт без `not_verified` отклоняется.
- **Ложная находка вреднее пропущенной.** Она провоцирует переделку рабочего кода, и после
  двух-трёх таких проверку отключают. Поэтому у каждого архитектурного признака обязателен
  **контр-сигнал** — законная форма, в которой это не дефект; новая проверка без
  контр-сигнала не принимается. Неразобранные файлы называются неразобранными, а не
  источником сотен проблем.
- **Часовой против ложной зелени.** Вместе с рабочими файлами прогоняется фикстура с
  заведомым нарушением (`assets/analyzer/sentinel-fixture/`, требует диагностики по
  метаданным). Часовой проверяется **по целям**, а не «хотя бы один живой»: живой v8std не
  маскирует отсутствие часового по анализатору. Фикстура обязана оставаться невалидной.
- **Градация вместо «всё или ничего».** Три строки внутри транзакции опаснее трёхсот строк
  переименований — глубина считается по трём осям, для мелкой правки прогон занимает секунды.
- **Приближение лучше пропуска, но должно быть заявлено.** Где разбор неточен, находка не
  блокирует, и это сказано прямо.

## Синхронизация производных файлов

- `skills/bsl-architecture-review/references/signs-map.json` — **источник истины** по
  архитектурным признакам; `signs-map.md` — производный, перегенерируется только скриптом
  `node tools/gen-signs-map-md.mjs`. Ручная правка производного рассинхронизирует его с
  источником — CI это поймает.
- Версия в `.claude-plugin/plugin.json` и `.claude-plugin/marketplace.json` держится
  синхронно (проверяется `validate-package.mjs`).
- Обновление версии анализатора: поменять `version` и суммы в
  `assets/analyzer/runtime-manifest.json`, взяв их из GitHub API релиза (поле `digest`
  у каждого asset).

## Безопасность и лицензии

- Код, скрипты, чеклисты, карты и эвристики — MIT.
- Статические анализаторы в пакет не входят: скачиваются с релизов автора, распространяются
  по своим лицензиям, запускаются как внешние программы; SHA-256 сверяется до запуска.
- Тексты стандартов 1С не воспроизводятся (см. выше) — PR со скопированными текстами
  принят не будет.
- Секретов в проекте нет и быть не должно; `validate-package.mjs` ловит следы проектных
  данных автоматически.

## Стиль коммитов

Conventional Commits на русском: `<тип>(<область>): описание`. Типы: `feat`, `fix`, `docs`,
`refactor`, `chore`, `test`. Область — имя контура или компонента (`контур-кода`, `гейт`,
`контур-архитектуры`). Описание — в повелительном наклонении, без точки. В теле полезно
объяснить **почему**, а не только что: правила этого плагина часто неочевидны.

## Стиль кода

- Node: ES-модули, только `node:`-импорты, без внешних зависимостей; файлы `.mjs` с shebang
  `#!/usr/bin/env node`. CLI-коды выхода: 0 — успех, 1 — мягкая проблема/не найдено,
  2 — блокирующая ошибка.
- Каждый инструмент начинается с docstring-комментария: зачем существует, какой дефект
  ловит, формат использования. Комментарии объясняют **почему** код такой, а не что он делает.
- Общая логика выносится в один модуль (`hooks/_shared.mjs`), а не копируется: скопированная
  в два места механика разъезжается при первой же правке.