andrey.epifantsev 079d0a44bc docs(spec): change hooks-write-target — хуки решают по цели записи (#6)
proposal, specs/hook-guards (16 требований), design с Decisions made without discussion. B1, B2, решение владельца 1; RT-1, RT-2, RT-6, RT-7.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 23:57:07 +04:00

54 lines
4.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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.md` 0.4.0.
- Установленные копии обновляются повторным `bash install.sh`; регистрация хуков в `settings.json` не меняется.
- Вне задачи: B3 (allow-правило удаления веток), B4 кроме решения 1, B10 (workspace-хук awp-ca), запись в код через Bash
для require-plan.