Standalone CLI с единой рамкой качества для разных репозиториев. Он читает self-reported
ответы из tracked .harness.json и измеряет то, что можно одинаково проверить в любом репозитории.
Тесты, сборку и линтеры проекта харнес не запускает — за них отвечает CI самого проекта.
curl -fsSL https://raw.githubusercontent.com/gently-whitesnow/harness-cli/master/install.sh | shСкрипт определяет платформу, сверяет sha256 и кладёт бинарь в ~/.local/bin/harness без
sudo. Никакого .NET runtime для запуска не нужно. Той же командой харнес обновляется: пинить
при установке нечего, потому что поведение задаёт проверяемый репозиторий, а не бинарь.
Внутри репозитория с .harness.json скрипт заодно выполняет harness setup, который
активирует commit-шаблон и commit-msg hook этого клона.
Для disposable-контейнера или installer-задачи бинарь можно оставить внутри клона:
curl -fsSL https://raw.githubusercontent.com/gently-whitesnow/harness-cli/master/install.sh \
| sh -s -- --scope clone--scope clone атомарно устанавливает его в
$(git rev-parse --git-common-dir)/harness/bin/harness, под lock-файлом защищает две
параллельные установки и обязательно выполняет harness setup. Hook получает стабильный
абсолютный путь к этому бинарю, поэтому продолжает работать после завершения контейнера и
остаётся общим для всех linked worktree клона. User-каталоги и tracked-файлы этот режим не
меняет.
HARNESS_VERSION=2.10.0 ставит конкретный релиз, HARNESS_INSTALL_DIR меняет каталог
обычной user-установки, а HARNESS_NO_SETUP=1 отключает подготовку клона.
harness init /path/to/repository # выбрать application/library и создать явную рамку
harness init --kind application # то же без интерактивного stdin
harness upgrade # поднять pin и получить маршрут миграции
harness check # проверить репозиторий
harness budget update # создать или ужать DSM-бюджет
harness setup # подготовить этот клон
harness version # релиз бинаря и текущий контрактinit задаёт один вопрос — приложение это или standalone-библиотека. Для приложения он
фиксирует architecture.standard: sliced-dotnet/1, для библиотеки — явный
architecture.applicable: false; карту каталогов он не генерирует. Команда создаёт
.harness.json и .harness.budget.json с текущими DSM-метриками и явными settings,
applicability и policy. Неотвеченные frame-вопросы — off, кроме обязательного verify.
По умолчанию фиксируется текущий релиз; --latest включает rolling-контракт. Существующие
файлы команда не перезаписывает и в Git не добавляет. Если в корне нет .editorconfig,
init записывает эталонный файл харнеса — тот же baseline, который затем требует
editorconfig.dotnet. В скриптах и CI тот же выбор задаётся через --kind application|library. init также активирует шаблон коммита и commit-msg hook; после
нового клонирования это делает идемпотентный harness setup. Если frame требует setup,
обычный check явно падает в неподготовленном клоне. Для CI сообщения проверяются явным
диапазоном: harness commits check <base>..<head>.
answers.verify.paths называет tracked скрипт всех проверок, включая harness check; харнес
его не запускает и не инспектирует. Здесь это ./verify.sh; commit range задаёт отдельно CI.
Применимый complexity.csharp требует tracked .harness.budget.json. Он измеряет файлы
внутри архитектурных зон sliced-dotnet (тесты вне зоны не входят) и бюджетирует mean reach —
сколько файлов достигает изменение в среднем — и core size. Превышение потолка блокирует
check, а улучшение предлагает выполнить harness budget update. Команда создаёт baseline,
мигрирует бюджет контракта 2.5 или атомарно ужимает оба значения; повышать бюджет она не
умеет — такое изменение делается вручную как обычный tracked-дифф для ревью.
Путь можно не указывать для текущего репозитория. harness help перечисляет команды и
проверки; check печатает строку со статусом на каждую проверку, --verbose раскрывает
причины, --all — полный список измеренных субъектов, --only <check-id> запускает одну.
Каждая проверка называет файлы, которые читает по имени, поэтому файл в рабочем дереве без
git add отчёт называет строкой not in the index: untracked-файл не является
доказательством. harness explain <check-id> описывает смысл и исправление проверки.
version в .harness.json называет релиз харнеса и фиксирует весь контракт проверки:
какие вопросы задаются и какие проверки выполняются. Это единственная версия в конфиге.
Бинарь исполняет ровно один текущий контракт. Пин на другую версию останавливает прогон с
кодом 2; единственный путь сменить pin — harness upgrade. Команда меняет только pin и
печатает полный маршрут контракта 2.0: удалённые проверки/секции, новый стандарт, явную
policy и DSM-бюджет. Ответы владельца она не угадывает. Все правки принимаются одним
reviewable-коммитом. ADR-0023
GitLab:
harness:
image: ghcr.io/gently-whitesnow/harness:2.10.0
script:
- harness check
- harness commits check "$CI_MERGE_REQUEST_DIFF_BASE_SHA..$CI_COMMIT_SHA"GitHub Actions или любой контур без доступа к ghcr.io:
- name: Repository harness
run: |
curl -fsSL https://raw.githubusercontent.com/gently-whitesnow/harness-cli/master/install.sh | sh
~/.local/bin/harness checkЭталон — рабочий .harness.json этого репозитория: в нём представлены все
формы ответа и секции конфигурации. paths служит навигацией и не проверяется как
доказательство. Каждый shipped check обязан иметь явный policy: required блокирует,
advisory оставляет находки видимыми без провала, off отключает. Каждый параметр
settings и каждая ось applicability также обязательны: список проверок и их состояние
читаются прямо из файла, defaults в ридере нет. Для неприменимой оси используется
{ "applicable": false, "reason": "..." }; для применимой — { "applicable": true }.
Коды возврата: 0 — всё выбранное прошло, 1 — доказано нарушение, 2 — проверить
достоверно не удалось (сюда же относится отсутствующий или невалидный .harness.json).
То, что не воспроизводит чужой пайплайн и что в каждом репозитории расходится:
- связанность: граф зависимостей между модулями и типами; доказанный цикл модулей blocking;
- форма sliced-dotnet: канонические слои, слайсы, направления Proven-зависимостей и неблокирующие структурные advisories: группировка плоских каталогов, плотность X-контрактов, словарь имён по всему zone;
- DSM-сложность: mean reach и core size файлового графа продукта, propagation cost как справка;
- не больше одного верхнеуровневого C#
classилиrecordв authored-файле; - нормализованные межфайловые повторы C#;
- документационная политика: один корневой навигационный документ и симлинки на него;
- .NET-рамка: hardened
Directory.Build.props, central packages,.slnx, эталонный.editorconfigи учёт подавленных warnings: адресное подавление блокируется, выключение правила для всего репозитория печатается в каждом отчёте.
Харнес несёт общий стандарт формы, который иначе копировался бы между репозиториями.
Отчёт печатает архитектуру и DSM-бюджет рядом с текущими значениями и областью измерения;
модель трёх ярусов, формулы и словарь раскрываются через harness explain и ADR-0032/0033.
Специфичные для продукта контракты и архитектурные правила остаются в самом репозитории.
Лендинг — статика в site/: все проверки, формулы циклов, DSM и дупликации, конструктор
.harness.json. Реестр и версия зеркалят бинарь и сверяются тестом; что обновлять — site/AGENTS.md, почему — ADR-0047.