13 KiB
13 KiB
claude-harness
Что это
Пакет обвязки для разработки с Claude Code: глобальный CLAUDE.md с процессом, три блокирующих хука и неблокирующий role-hint, скрипты подключения проекта и skill диагностики. Для одного разработчика, который ведёт фичи через superpowers, хранит задачи в Gitea и требования в OpenSpec. Главный сценарий: bash install.sh ставит глобальную часть в ~/.claude, adopt-project.sh подключает существующий проект, new-project.sh создаёт новый; дальше проект живёт по docs/HARNESS.md. Репозиторий — источник; установленные копии в ~/.claude по месту не правятся.
Стек и ограничения
- Bash (
set -euo pipefail), markdown иpython3stdlib (3.8+). Логика guard-main и require-plan —hooks/harness_target.py, их.sh— обёртки; в остальных хуках и скриптах JSON разбирается встроеннымpython3. Других зависимостей времени выполнения нет. Внешние CLI (tea,openspec,codegraph) проверяются, но не требуются для установки. - Хук блокирует вызов только через
exit 2с сообщением в stderr;exit 0— пропустить. Любой сбой разбора входа должен приводить к пропуску, не к блокировке. install.shидемпотентен: повторный запуск не ломаетsettings.jsonи делает бэкапыCLAUDE.mdиsettings.jsonс меткой времени. Вsettings.jsonон сливаетhooksи только дописываетpermissions.allowизglobal/permissions.json; чужие правила не трогает. Агент запускает его только с--no-permissions: права ставит владелец.- Хуки работают из
~/.claude/hooks/, пути вsettings.hooks.jsonчерез$HOME;CLAUDE_CONFIG_DIRпереопределяет~/.claude. - macOS и Linux;
python3должен быть в PATH сессии Claude Code.
Архитектура
hooks/— поведение обвязки, единственный «код» с логикой.guard-main.sh(PreToolUse на Edit/Write/MultiEdit/Bash): запрет записи в репозиторий на main/master/detached HEAD по цели записи (файл, цели команды Bash, git-мутации), без исключений.require-plan.sh(PreToolUse на Edit/Write/MultiEdit): правки в каталогах кода репозитория файла только при плане для ветки или файле.bounded. Обе — обёртки надharness_target.py:parse(команда → цели, без ФС) →resolve(путь → корень и ветка) →decide; режимtargets— отладка разбора.harness-check.sh(SessionStart): проверка, что проект подключён.role-hint.sh(SessionStart, все источники): подсказка роли поsession_title.settings.hooks.json— блок, которыйinstall.shсливает в~/.claude/settings.json.install.sh,adopt-project.sh,new-project.sh— установка и бутстрап.install.shкопируетglobal/,hooks/,project-template/,adopt-project.sh,new-project.shиskills/harness-doctorв~/.claude/{CLAUDE.md,hooks,harness,skills}.adopt-project.shработает на веткеchore/harness-initи вливает её ff в текущую ветку; это единственная разрешённая запись на main вне PR.global/CLAUDE.md— глобальные правила процесса, ставятся в~/.claude/CLAUDE.md.global/permissions.json— allow-правила цикла фичи (без merge и push в main),install.shдописывает их в~/.claude/settings.jsonи кладёт копию в~/.claude/harness/дляdoctor.sh.project-template/—CLAUDE.md,CLAUDE.harness-section.md(секция «OpenSpec и superpowers», по нейharness-checkузнаёт подключённый проект),ARCHITECTURE.md,gitignore.skills/harness-doctor/— skill диагностики:scripts/doctor.shснимает состояние машины и проекта и прогоняет самотест хуков;SKILL.md— чеклист прочтения отчёта.fixtures/hook-cases.jsonl+scripts/hook_corpus.py— регрессионный корпус хуков (реальные команды с ожидаемым вердиктом, прогон в песочнице); лежит в skill, чтобыdoctor.shгонял его по установленным копиям.roles/— общий слой ролей (формат: четыре раздела, см. спеку ролей),skills/role/— skill/role,agents/briefing.md— агент выжимки,link-roles.sh— симлинки workspace → репозитории направлений. Ставятсяinstall.shв~/.claude/{roles,skills/role,agents,harness}.tests/— тесты пакета на bash:run.sh+test-*.sh, работают с источниками,install.shставят во временныйCLAUDE_CONFIG_DIR.caveman/config.json— выключенный по умолчанию caveman.examples/— реальныйCLAUDE.mdпроекта-пилота.docs/HARNESS.md— как устроен цикл фичи, SDD, маркировка, закрытие.docs/PILOT-2026-09-27.md— пилот.docs/retro/— ретроспективы, их метрики (<дата>.metrics.json) и скрипты:retro_metrics.py(срез метрик и поправки владельца),retro_leftovers.py(хвосты закрытия),hook_blocks_export.pyиhook_cases_build.py(блокировки → корпус); проектный skill/harness-retro—.claude/skills/harness-retro/.docs/superpowers/specs/— спеки фич обвязки,docs/superpowers/plans/— планы.- Связь слоёв: хуки читают JSON вызова из stdin и состояние git проекта; скрипты бутстрапа читают
project-template/;doctor.shчитает установленные копии в~/.claude, не репозиторий.
Команды
bash tests/run.sh [имя]— весь набор тестов. Зелёным считается только весь набор.bash install.sh --check— проверка окружения: бинарники, плагины, конфликты, allow-правила обвязки.bash install.sh [--no-permissions]— установка глобальной части, идемпотентно;--no-permissions— без allow-правил.bash skills/harness-doctor/scripts/doctor.sh [проект]— отчёт и самотест хуков. Только чтение.bash adopt-project.sh <папка> [--no-merge] [--push]— подключить существующий проект. Из терминала, не из Claude Code.bash new-project.sh <папка> [ssh-url]— каркас нового проекта./harness-retro <папка проекта> [--since ГГГГ-ММ-ДД]— ретро обвязки (в сессии в этом репозитории). Под ним:python3 docs/retro/scripts/retro_metrics.py <папка> [--since …] [--out …] [--markdown --prev …] [--corrections]— срез метрик;retro_leftovers.py <папка> [--fetch] [--markdown]— хвосты закрытия;hook_blocks_export.py [--since …] [--id-prefix …] <каталог> [...]— выгрузка блокировок в JSONL;hook_cases_build.py > skills/harness-doctor/fixtures/hook-cases.jsonl— сборка корпуса из разметки.python3 skills/harness-doctor/scripts/hook_corpus.py hooks [--summary]— корпус хуков по источникам.python3 hooks/harness_target.py targets '<команда>' [cwd]— какие цели записи видит хук.
Тесты
tests/run.sh— автоматические тесты источников (хуки через фиктивный JSON, скрипты во временных каталогах, размеры). Самотест хуков вdoctor.shпроверяет установленные копии; перед нимbash install.sh.- Ручная проверка хука: на main в любом репозитории попросить агента создать файл, ожидается
BLOCKED. - Хуки:
test-hook-parse— разбор команды на цели;test-hook-guard-main,test-hook-require-plan— сценарии спекиhook-guardsв песочнице из настоящих репозиториев;test-hook-corpus— корпус реальных команд (assert на запись, корпус должен совпадать со сборкойhook_cases_build.py);test-hook-export— экстрактор. Ретро:test-retro-metrics(синтетические транскрипты),test-retro-leftovers(песочница репозиториев),test-retro-skill. Плюсrole-hintи скриптыinstall.sh,doctor.sh,link-roles.sh. - Правишь разбор или вердикт — сначала случай в
test-hook-parse/test-hook-guard-main; меняется ожидаемый вердикт реальной команды — разметка вhook_cases_build.pyи пересборка корпуса.
Текущая работа
Бэклог обвязки — docs/retro/2026-10-11.md, раздел 4 (B1–B12), решения владельца — раздел 5. Находки ретро маркируются RT-n.
- Сделано: B5+B6 часть 1 — слой ролей (PR #4, 0.3.0). Часть 2 (awp-ca) — issue #2, отложенные находки — issue #5.
- Сделано: B1+B2 и отмена исключения openspec-only для guard-main — хуки по цели записи и корпус хуков (issue #6, PR #12, 0.4.0), спека —
openspec/specs/hook-guards/. Отложенные находки — issue #13. - Сделано: B3 — allow-правило
git push origin --deleteпечатают adopt/new-project, проверяет doctor (issue #22, 0.4.2). B4 закрыт в #6 (решение владельца 1). B10 — workspace-хук awp-ca, в части 2 issue #2. - Сделано: allow-правила цикла фичи ставит
install.sh(issue #24, 0.5.0; пересмотр решения владельца 2). - Сделано: worktree —
EnterWorktreeв<repo>/.claude/worktrees/<slug>, вход без подтверждения (issue #25, 0.5.1). Для awp-ca вопрос открыт в части 2 issue #2. - Сделано: B12 —
/harness-retro: срез метрик, поправки владельца, хвосты закрытия, корпус по сегментам (issue #29, 0.6.0), спека —openspec/specs/harness-retro/. - Дальше: первое ретро
/harness-retroпо полигону — на машине с awp-ca; остальные пункты бэклога — по мере надобности.
OpenSpec и superpowers
- Вход в любую задачу — superpowers:brainstorming. Skills openspec-propose и openspec-explore сами по себе не запускать.
- Когда brainstorming классифицировал задачу как architectural, структуру change создать через
openspec new change <id>(или/opsx:propose <id>), а содержимое proposal.md, specs/ и design.md написать по итогам brainstorming. tasks.md из OpenSpec не заполнять — задачи живут в плане superpowers. /opsx:applyне использовать: исполнение идёт через writing-plans и SDD/executing-plans.openspec archive <id>— после merge PR, как часть чеклиста закрытия.- Хук require-plan защищает любой каталог
src/на любой глубине. Если код лежит иначе — перечислить каталоги (префиксы от корня, по одному в строке) в.claude/code-paths. В этом репозитории код —hooks/иskills/, они перечислены в.claude/code-paths.