openspec archive hooks-write-target: change перенесён в openspec/changes/archive/2026-10-16-hooks-write-target/, дельта применена — openspec/specs/hook-guards/spec.md (20 требований), validate --strict проходит. Ссылки на путь спеки в harness_target.py, hook_cases_build.py и CHANGELOG переведены на openspec/specs/hook-guards/spec.md; в CLAUDE.md «Текущая работа» B1+B2 переведены в «Сделано» (PR #12, follow-ups — #13). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
4.9 KiB
Proposal: хуки решают по цели записи
Issue: #6. Источники: ретро docs/retro/2026-10-11.md — B1, B2, решение владельца 1; находки RT-1, RT-2, RT-6, RT-7.
Why
guard-main решает по тексту команды и по cwd оболочки, а не по тому, куда идёт запись. По подсчёту ретро около трёх
четвертей блокировок за период пилота ложные: 2>/dev/null считается записью, grep "npm i" — установкой пакета, Edit
файла памяти вне репозитория — записью в main, потому что cwd стоит на main-checkout (RT-1). Чужой cd останавливает
фоновый SDD-контроллер (RT-2), отказ хука запускает каскад отказов классификатора auto mode (RT-7). Реальных нарушений
main за тот же период — ноль, перехват по делу — единицы. Регрессионных тестов на реальных командах у хуков нет (RT-6),
поэтому любая правка регулярного выражения проверяется только в бою. require-plan болен тем же: корень, ветку, план и
code-paths он берёт от cwd, а не от репозитория правимого файла.
What Changes
- guard-main определяет цели записи — файлы и git-мутации — и решает по ветке репозитория каждой цели. cwd служит только базой для относительных путей.
- Неразрешимая файловая цель пропускается; git-мутация с неопределённым репозиторием блокируется.
git pushсчитается записью в main, только если он пушит в main;push origin <feature>иpush origin --delete <feature>из main-checkout проходят.- BREAKING: исключение для openspec-only коммитов и для
openspec archiveна main удаляется (решение владельца 1: архив всегда отдельным PR). Правила процесса уже приведены к этому в 0.3.0 (roles/dev.md); меняется поведение хука. pip installбольше не блокируется (пишет в окружение, не в репозиторий);npm/yarn/pnpm installв репозитории на main — блокируется, как и раньше.- require-plan берёт корень, ветку,
.claude/code-paths,.boundedи планы из репозитория правимого файла. - Сообщения блокировки получают стабильный префикс
BLOCKED [guard-main]:/BLOCKED [require-plan]:, называют цель и выход. - Регрессионный корпус: 126 записей из транскриптов плюс живые случаи, каждая с ожидаемым вердиктом; прогон из
tests/run.sh(источники) и изdoctor.sh(установленные копии). - Экстрактор
hook_blocks_export.pyвыгружает только настоящие ошибки хуков.
Capabilities
New Capabilities
hook-guards: блокирующие хуки обвязки — защита main/master/detached HEAD от записи (guard-main), требование плана для правок в коде (require-plan), их регрессионный корпус.
Modified Capabilities
Нет: openspec/specs/ пуст, это первая capability обвязки.
Impact
- Код:
hooks/guard-main.sh,hooks/require-plan.sh(становятся обёртками), новыйhooks/harness_target.py(stdlib python3, новых зависимостей нет),install.sh(копирование и--check),skills/harness-doctor/(корпус, песочница, раннер, строка в отчёте),docs/retro/scripts/hook_blocks_export.py. - Тесты:
tests/test-hook-parse.sh,tests/test-hook-corpus.sh, случаи require-plan. - Документация:
README.md,docs/HARNESS.md,CLAUDE.mdиARCHITECTURE.mdрепозитория,roles/dev.md(уточнение проcd),CHANGELOG.md0.4.0. - Установленные копии обновляются повторным
bash install.sh; регистрация хуков вsettings.jsonне меняется. - Вне задачи: B3 (allow-правило удаления веток), B4 кроме решения 1, B10 (workspace-хук awp-ca), запись в код через Bash для require-plan.