quality-gate · git:20260915.26cac8d · 2026-09-15 · sha256 fbcd31c95bc2f1c0

quality-gate git:20260915.26cac8dA

Immutable. This exact content never changes and is served at /api/v1/blob/fbcd31c95bc2f1c0.

---
name: quality-gate
description: >-
  Оркестратор контроля качества 1С-разработки. Определяет профиль изменения по трём осям
  (объём правки, архетипы кода, сложность), выбирает глубину каждого контура, запускает
  проверки, формирует отчёт с машиночитаемым следом и снимает блокирующий гейт.
  Вызывать после правок BSL или XML метаданных 1С, перед завершением работы и коммитом.
  Триггеры: «прогони гейт качества», «проверь код перед коммитом», «сними гейт»,
  «отревьюй что я написал», «проверь по стандартам», «готов ли код к коммиту».
license: MIT
---

# quality-gate — оркестратор контроля качества 1С

Единственная точка входа плагина. Контуры (`code`, `arch`, `xml`, `hygiene`) не вызываются
напрямую: сначала считается **профиль изменения**, он решает глубину.

> **Главное правило.** Полный прогон на правке комментария — налог, из-за которого гейт
> начинают обходить; пропуск без следа — ложная зелень. Глубина адаптивная, но **любой
> пропуск фиксируется явной записью с причиной**.

<ЖЁСТКИЙ-ШЛЮЗ>
По умолчанию — только проверка и отчёт. НЕ переписывай бизнес-логику и НЕ меняй метаданные по
своей инициативе. Правки — только в режиме `--fix`, из безопасных категорий. Critical и любые
изменения логики, проведения, запросов, прав — никогда без явного подтверждения пользователя.
</ЖЁСТКИЙ-ШЛЮЗ>

---

## Инварианты прогона

Девять утверждений: усвоен только этот блок — прогон ещё имеет смысл; нарушено любое —
уже нет.

1. **Профиль считается один раз**, до контуров; контуры его не пересчитывают.
2. **Глубина — по профилю, не по привычке**: не гонять архитектуру на опечатке, не
   ограничиваться гигиеной на новом модуле проведения.
3. **Контур исполняется вызовом навыка**, а не по памяти.
4. **Строку следа печатает инструмент**, где он есть — не модель по смыслу.
5. **Любой пропуск — запись `skipped` с причиной.** Молчание неотличимо от выполнения.
6. **Вердикт «чисто» признаёт непроверяемое** — записью `not_verified`.
7. **Находка — с номером стандарта, кодом диагностики или эвристикой** и значением против
   порога; 🔴/🟠 блокируют «Чисто», вне `--fix` — только отчёт.
8. **Гейт снимается утилитой** `gate.mjs release`, а не удалением файла состояния.
9. **План печатает `gate.mjs plan`**; модель вправе поднять глубину с причиной, понизить —
   нет.

---

## Шаг 1. План

### Путь к инструментам плагина (`$QG`)

Все команды ниже используют `$QG` — каталог плагина. Под OpenCode он готов в `QG_ROOT`; в
Claude Code `CLAUDE_PLUGIN_ROOT` оболочке не видна — путь схлопнулся бы в `/tools/...`.

Разреши путь **первой командой прогона**, дальше подставляй значение буквально. Кандидат —
только после `test -d "$QG/tools"`: переменная сама по себе не гарантирует актуальный плагин.

```bash
QG="${QG_ROOT:-}"
[ ! -d "$QG/tools" ] && QG="${CLAUDE_PLUGIN_ROOT:-}"
[ ! -d "$QG/tools" ] && QG="$(node -e "const p=require(require('node:os').homedir()+'/.claude/plugins/installed_plugins.json').plugins;const k=Object.keys(p).find(n=>n.startsWith('1c-quality-gate@'));if(k&&p[k][0])process.stdout.write(p[k][0].installPath)" 2>/dev/null)"
[ ! -d "$QG/tools" ] && QG="$(ls -d ~/.claude/plugins/cache/*/1c-quality-gate/*/ 2>/dev/null | sort -V | tail -1)" && QG="${QG%/}"
test -d "$QG/tools" && echo "$QG" || { echo "Плагин не найден ни в одном харнессе" >&2; exit 1; }
```

`sort -V` обязателен: без него берётся устаревшая версия плагина
(`references/run-environment.md`).

### Профиль и план прогона

```bash
node "$QG/tools/gate.mjs" plan --files <f> [<f> ...] [--no-analyzer]
```

Без `--files` — состав из взведённой сессии (`gate.mjs status`). Печатает профиль по трём
осям, строку `scope` (с `config=...`), инструменты по порядку, что закрыть в следе.
`--no-analyzer` — когда анализатор недоступен или падает; ось сложности тогда `not_computed`,
`driver` не бывает `complexity:*`.

**Строку `[qg scope: ...]` перенеси в отчёт дословно** — валидатор пересчитывает профиль сам.
Расхождение — сверь порог: `node "$QG/tools/config.mjs" show`. **Профиль можно поднять,
нельзя понизить**: увидел то, чего план не видит (правка тише архетипа, но трогает деньги) —
подними, добавь «глубина поднята: <причина>»; обратное валидатор не пропустит.

Почему оси устроены так — `references/profile-axes.md`; данные — `tools/profile.mjs`,
`tools/gate.mjs`.

---

## Шаг 2. Инструменты

Выполни команды раздела «## Инструменты» плана по порядку — файлы уже подставлены. У части
есть исполняемый инструмент: он печатает строку следа (`[qg applied: ...]` / `[qg skipped:
...]`) сам — переноси дословно, не сочиняй.

Прогон отмечается в журнале `qg-runs.jsonl`: валидатор сверяет по нему каждую запись
`applied` — инструмент видел **весь** состав правки, а не файл из десяти; `skipped ...
reason=not_applicable` — тоже утверждение о работе. Прогоны по частям складываются.
`platform-context-run.mjs`, когда включён планом, обязателен: анализатор знает имена
конфигурации, но не платформы. `query-lint` берёт и изменённые XML, не только `.bsl`.

**Перед повторным прогоном слоя проверь `gate.mjs status`:** отработавший по этому
содержимому слой пропускается с причиной `verified_earlier` (`references/evidence-format.md`).

---

## Шаг 3. Контуры

Запускай контуры и глубины из `resolved: code=... arch=... xml=... hygiene=...` плана.
Каждый контур обязан вернуть `applied` либо `skipped` — **молчание не допускается**.

| Контур | Навык |
|---|---|
| `code` | `bsl-code-review` |
| `arch` | `bsl-architecture-review` |
| `xml` | `xml-structure-review` |
| `hygiene` | `file-hygiene` |

Передавай контуру профиль целиком: класс, архетипы, файлы.

### Контур исполняется вызовом навыка, а не по памяти

Таблица называет навыки, а не проверки: чем проверяется признак — в SKILL.md контура. Прогон
без открытия навыка — чеклист для чтения глазами, не проверка
(`references/run-environment.md`).

### Субагенты в составе прогона

Четыре штатных, **только читающие**: возвращают факты, запись формирует контур. Три дешёвые;
`antipattern-reader` — на модели уровня контура: семантика LLM-антипаттернов не
механизируется до haiku.

| Субагент | Вызывает | Факты | Спавнов |
|---|---|---|---|
| `bsl-verifier` | `code` | сигнатуры платформы, экспортность модулей, метаданные | на список файлов |
| `antipattern-reader` | `code` | кандидаты с цитатами; аттестует `tools/catalog.mjs` | на контур |
| `bsl-scout` | `arch` | вызывающие, экспорты, триггеры XML | по вопросу |
| `xml-runner` | `xml` | «диск ↔ состав», валидаторы структуры | на контур |

Недоступность субагента, контура или инструмента проверку не отменяет — она проходит сама
либо получает `skipped` с причиной (`references/run-environment.md`).

---

### Слой 3: состязательный аудит

Самая дорогая проверка, никогда не запускается сама: контуры предлагают её при классе C3 с
находками 🔴/🟠, запуск — только по явному согласию пользователя
(`references/adversarial-audit.md`).

---

## Шаг 4. Sentinel — проверка живости источника стандартов

Один раз за прогон запроси через MCP `v8std` стандарт, чей номер — `sentinel.id` настройки
(умолчание `std454`): `v8std_get_page("<id>")`, ожидание — страница найдена.

Без неё «нарушений не найдено» неотличимо от «сервис недоступен»: неподтверждённый часовой
делает прогон недостоверным (`references/run-environment.md`).

---

## Шаг 5. Отчёт и след

Отчёт для человека — находки по важности (🔴 Critical / 🟠 Major / 🟡 Minor). Ниже, в
`## quality evidence`, — машиночитаемый след: строка на проверку
(`references/evidence-format.md`).

**Каждая запись `not_verified` повторяется в человекочитаемой части фразой**: «Ошибок: 0»
рядом с невидимым `not_verified` читается как «проверено».

Минимум следа: `scope` (Шаг 1), `sentinel` (Шаг 4), запись от каждого контура и всё из плана
«Закрыть в следе» — включая `not_verified: dimension=compilation`, если платформа не
запускалась (её не проверяет ничто другое).

**Сработал архетип «Запрос» — выполни запрос до вердикта** (консоль запросов, тестовые
параметры): текст остаётся строковым литералом, «Неоднозначное поле» доживает до продуктива.
Выполнить негде — законный исход, но записанный:

```
[qg applied: layer=code, scope=query-execution, ids=[qg:QRY-EXECUTED], verdict=clean]
[qg not_verified: dimension=query-execution, reason=no_platform]
```

**Файл, до которого не добрался анализатор, не проверен** — `analyzer-run.mjs` печатает
запись сам, переноси дословно.

```bash
node "$QG/tools/evidence-validator.mjs" <файл отчёта> --gate
```

---

## Шаг 6. Снятие гейта

Гейт снимается **только** утилитой, не удалением файла состояния:

```bash
node "$QG/tools/gate.mjs" release --evidence <файл отчёта>        # по результатам прогона
node "$QG/tools/gate.mjs" release --class C0 --reason "<почему>"  # C0/C1 без прогона
```

Отчёт — во временный каталог, не в проект: `release` копирует его в архив вне git;
ссылайся на путь `Копия отчёта:` (`references/run-environment.md`).

НЕ снимай гейт, если прогон прерван на полпути и отчёт не сформирован: он должен остаться
для повторной проверки.

**Чужие сессии не трогай.** Гейт разделён по сессиям: несколько в `gate.mjs status` —
`verify`/`release` без `--session <id>` отказывают, «самая свежая» может быть чужой.
Идентификатор — в подсказке при взводе и в сообщении о блокировке
(`references/run-environment.md`).