name: code-quality description: Жёсткая оценка качества Unity-кода (пакета/системы/подсистемы) по канонным формулам с архитектурным множителем. Триггеры — «оцени качество кода», «прогони по критериям оценки», «проверь пакет на качество», «оцени систему X». Размер кода определяет режим: детальный анализ (≤3000 LOC), детальный по подгруппам (3000–12000 LOC при естественном делении на 2–4 равные группы), частичный (≤12000) или субъективный обзор (>12000). Баллы не смягчаются — объём фикса считается отдельно. when_to_use: Триггеры — «оцени качество кода», «прогони по критериям оценки», «проверь пакет на качество», «оцени систему X», «оцени архитектуру/структуру пакета». Слова «корректность / логичность / адекватность / правильность / спутанность» — триггер близнеца applied-quality, не этого скилла. Запускать при просьбе оценить ФОРМУ Unity-кода (метрики, паттерны, связность, документируемость) конкретного пакета или подсистемы.

Оценка качества кода (Unity)

На вход — целевой пакет/система/подсистема. На выходе — оценка по формулам с архитектурным множителем + чек-лист маркеров и red-flag'ов, либо явное предупреждение о невозможности применить канон.

Как читать этот скилл

SKILL.md — каркас: триггер, замер размера, развилка, формат вывода, жёсткие правила. Детальное — в референсах:

  • references/detailed-canon.md — полный канон ветки A (порядок чтения, pre-check расширяемости, формулы категорий 1–4, маркеры, чек-листы, grep'ы, шкалы, эталонные значения). Читается целиком перед детальным анализом. Не работать по памяти.
  • references/sharding-and-partial.md — протоколы веток A+ (подгруппы), B (частичный) и C (субъективный обзор). Читается целиком при соответствующей ветке.

0. Триггер и проверка контекста

⚠️ Подтверждение направления (ПЕРЕД запуском, обязательно)

Этот скилл меряет ФОРМУ / архитектуру кода: метрики, структуру, паттерны, связность — код «в покое».

Рядом — скилл-близнец applied-quality: он меряет ПРИКЛАДНУЮ ЛОГИКУ / поведение (корректность логических нитей вход→выход, спутанность, ступенчатость, что рвётся на re-entry/сбое/гонке) — код «в движении».

Триггеры близнецов похожи, поэтому до анализа убедиться, что пользователь хочет именно архитектуру/форму. Если формулировка неоднозначна (или могла относиться к прикладной логике/корректности) — задать ОДИН вопрос и дождаться ответа:

«Оценить архитектуру/форму (метрики, паттерны, связность — code-quality), или прикладную корректность (нити, спутанность, что порвётся в рантайме — applied-quality)?»

  • Явно «качество / архитектура / метрики / паттерны» → продолжать без вопроса.
  • Явно «корректность / логичность / адекватность / правильность / спутанность / что рвётся» → предложить переключиться на applied-quality.

Запускается, когда пользователь просит оценить качество кода конкретного пакета/системы.

Если цель не указана явно — уточнить:

«Какой пакет/система оценивается? Канон применим к одному пакету ≤3000 LOC; для большего объёма буду предупреждать о деградации точности.»

Без указания цели скилл НЕ выполняется.


1. Шаг 0 — измерение размера (всегда)

Перед любым анализом измерить LOC всех релевантных .cs файлов.

Что считается в LOC

  • Включаем: .cs файлы в целевой папке.
  • Исключаем: *.Designer.cs, любые сгенерированные файлы (содержат маркер // <auto-generated>), тестовые сборки (*Tests*, *.Tests.*, Editor/Tests/), .meta-файлы.
  • LOC = wc -l (с пустыми строками и комментариями). Для гейтинга порога этого достаточно — точная NCLOC не нужна.

Команды (по платформе)

bash / git-bash / WSL:

find <target-path> -name "*.cs" \
  -not -name "*.Designer.cs" \
  -not -path "*/Tests/*" -not -path "*Tests*" \
  -exec wc -l {} + | tail -1

PowerShell (Windows):

Get-ChildItem -Path <target-path> -Filter *.cs -Recurse |
  Where-Object {
    $_.Name -notmatch '\.Designer\.cs$' -and
    $_.FullName -notmatch '[\\/](Tests|.*Tests.*)[\\/]'
  } |
  Get-Content | Measure-Object -Line

Делегирование подсчёта

Подсчёт LOC выполнять через дешёвого агента, не в основном контексте:

  • Запустить Agent с subagent_type=Explore (или general-purpose с model=haiku).
  • Задача: «Посчитай суммарный LOC всех .cs файлов в <target-path> с исключениями выше. Верни одно число.»

Это экономит контекст основной сессии — инвентаризация не должна занимать его место.


2. Развилка по размеру

Развилка идёт только по LOC. Количество asmdef/папок верхнего уровня не влияет: один пакет может состоять из нескольких сборок, и при малом объёме его всё равно можно проанализировать детально.

Ветка A — детальный анализ

Условие: ≤3000 LOC.

→ references/detailed-canon.md (полный канон + протокол). Прочитать целиком.

Ветка A+ — разбиение на подгруппы под порог детального анализа

Условие: 3000–12000 LOC, и подсистема естественно делится на 2–4 смысловые группы, каждая ≤3000 LOC.

Жёсткие ограничения деления:

  • Не более 4 групп (выше — дилюция сигнала через усреднение делает оценку недостоверной).
  • Размеры групп сопоставимы: max_LOC / min_LOC ≤ 3. Иначе крупная группа доминирует, мелкие тонут в среднем — переходить к ветке B.
  • Границы естественные (типы акторов, бэкенды/реализации, ядро/контракты/реализации). Если деление искусственное (раздробит классы одной зоны ответственности) — ветка B.

→ references/sharding-and-partial.md.

Ветка B — частичный анализ (с предупреждением)

Условие: 3000–12000 LOC, разбиение невозможно или нецелесообразно (искусственные границы, неравные размеры, >4 групп).

→ references/sharding-and-partial.md.

Ветка C — субъективный обзор (с предупреждением)

Условие: >12000 LOC.

→ references/sharding-and-partial.md.


Формат вывода

Вне зависимости от ветки.

Шапка

[Ветка X] Оценка <target>
- LOC: <total>
- Применимость канона: [полная / частичная / субъективная]

Тело

  • Ветка A: полная оценка по формулам с расчётами и ссылками на файлы.
  • Ветка B: формулы + выборочные маркеры + явное «оценка частичная».
  • Ветка C: только качественные наблюдения с шапкой «Субъективный обзор, не оценка».

Финальный блок

Ветка A:

  • Базовый, arch и red счётчики, Итог, интерпретация по шкале (8–10 / 6–8 / 4–6 / 2–4 / 0–2).
  • Диагностический сигнал — отдельный комментарий о разрыве Базовый ↔ Итог:
    • если разрыв большой (Итог < 0.6 × Базовый): «Высокий Базовый при низком Итоге — код локально опрятен, но имеет фундаментальные архитектурные дефекты, которые осреднённые метрики не ловят. Этот разрыв — повод смотреть подсистему прицельно, а не доверять одному числу.»
    • если разрыв малый: «Базовый и Итог близки — архитектурных штрафов мало, оценка устойчива.»
  • Список «что нельзя оценить по коду» (detailed-canon.md, раздел 3.11) — при необходимости.

Ветка B:

  • Базовый, выборочные маркеры, предупреждение о неполноте.
  • Если посчитан Итог — добавить тот же диагностический комментарий, что в ветке A.

Ветка C:

  • Рекомендация декомпозировать для детального анализа.

Интерпретация шкалы итога

  • 8–10 — Отличная архитектура.
  • 6–8 — Хорошая, с minor проблемами.
  • 4–6 — Приемлемая, технический долг копится.
  • 2–4 — Проблемная, сложно поддерживать.
  • 0–2 — Критическая, требует переписывания.

Жёсткие правила

  • Применение формул — жёсткое. Балл не корректируется в сторону смягчения «потому что фикс будет дорогой» или «потому что эффект мал». Объём фикса — отдельная задача после оценки.
  • Субъективное — отдельно. В ветке A — формулы. В ветке C — мнение. В ветке B — формулы плюс явное предупреждение что часть маркеров может быть пропущена. Не смешивать.
  • Не оценивать «расширяемость» по наличию interface + virtual + hooks без проверки реальных подмен через grep (pre-check реальной расширяемости, detailed-canon.md, 3.3).
  • Каждое снижение балла — привязано к посчитанному counted violation с ссылкой на код. Иначе n/a.
  • Не подменять анализ инвентаризацией (LOC, число файлов, namespace-таблицы — это данные, не оценка).
  • Если паттерн чистый по чек-листу — балл максимальный, не «0.7 на ощупь».
  • Подсчёт LOC и grep-метрик — через дешёвого агента (Haiku, subagent_type=Explore или general-purpose). Основной контекст занимать инвентаризацией нельзя.
  • Хорошая документация плохой архитектуры ≠ хороший код — документация объясняет как обойти проблемы, а не почему их нет.