fix(hooks): worktree-цепочка резолвится по новой ветке (O-4, #63) #71
Loading…
x
Reference in New Issue
Block a user
No description provided.
Delete Branch "feat/63-guard-worktree-chain"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Что и почему
Issue #63 (находка O-4): цепочка
git worktree add <path> -b <branch> … && cd <path> && openspec archive …в одной команде блокировалась guard-main по ветке основного checkout (main), хотя worktree создаётся на новой ветке и последующие команды выполнились бы уже в нём.Причина в парсере.
hooks/harness_target.pyне разбиралgit worktree add: цельopenspec archiveв каталоге ещё не существующего worktree поднималасьresolve()до объемлющего репозитория и оценивалась по его ветке — main. Спец-случай «worktree— не мутация» только пропускал самgit worktree add, пары «путь → ветка» нигде не сохранялись.Изменения
hooks/harness_target.py:_worktree()—git worktree add <путь> -b|-B <ветка>запоминает пару «путь → ветка» (с учётомgit -C, относительный путь считается от каталога-C);parse()/_Stateполучают список этих пар через_wts(доп. аргумент, рекурсияbash -c/evalего наследует); режимtargetsи схема целей не меняются —parseостаётся без обращений к ФС;decide_guard()переводит пути worktree в реальные (realpath) и для цели, лежащей под таким путём, берёт ветку из пары вместо ветки объемлющего репозитория. Цели вне пути worktree оцениваются как раньше — по объемлющему репозиторию.openspec/specs/hook-guards/spec.md— новое требование «Новый worktree внутри той же команды» и два сценария (цепочка сcd— пропуск;openspec archiveбезcdв main — блок).tests/test-hook-guard-main.sh— три регрессии в песочнице: цепочка черезgit worktree add -b, то же черезgit -C, и негативный случай безcd(остаётся блок).Проверка
bash tests/run.sh→passed 633, failed 0(до правок — 630/0).git worktree add … -b … | tail -2 && cd … && openspec archive …, cwd — репозиторий на main):python3 hooks/harness_target.py targets …даёт цельfile <repo>/.claude/worktrees/archive-dsh-openspec openspec archive, guard-main —exit 0. Безcdта же цели —exit 2.Решения реализации
targetsне меняется): это вход решения, а не цель записи; схемаfile|git|switchи тестtest-hook-parseостаются прежними.openspec,git -C), а не только наopenspec archive, — так требование issue выполняется без частного случая.-b/-B. Формаgit worktree add <��уть> <существующая ветка>и ветка в переменной не мапятся: вердикт остаётся прежним (по объемлющему репозиторию), ложного пропуска нет.Ограничения / не сделано
test-hook-guard-main; добавление live-кейса меняет счётчик в синтетическом сегментеtest-hook-corpusи выходит за bounded-объём. Если владелец хочет кейс — отдельным follow-up.Рулинг контроллера R-1 (по ревью T1.2): берём точный вариант — явный switch (over[root]) выигрывает у wt-пары. Порядок в decide_guard: over[root] → wt-пара (только для целей с индексом >= позиции add) → resolved. Ложных блоков не добавляет: over заполняется только явным switch/checkout в этой команде. Объём правок: T1.1–T1.4 + негативы T1.6. T1.5 и T1.8 — deferred, занесены в #70.
aep referenced this pull request2026-10-24 22:06:17 +03:00
Итог ревью: merge ok. Свежий ревьюер (v4-pro): перепроверка дельты 8d8dd89..e064de7 — test-hook-guard-main 78/0, test-hook-parse 91/0, test-hook-corpus 151/0 (вердикты корпуса не изменились); матрица 16 граничных цепочек: ложные пропуски 0→2, пере-блокировок нет. Находки: T1.1-T1.4, T1.6, T1.7 — fixed e064de7; T1.5, T1.8 — deferred в #70; T1.9 — rejected (обоснованно); T2.1 — rejected (осознанный компромисс R-1), опциональный follow-up в #70. Контроллер O-1 (инцидент с tea comments в сессии) — fixed, к коду не относится. Merge — по команде владельца.