Git PR Lifecycle Safeguard
Запуск Навыка
При явном вызове или однозначном смысловом совпадении применяйте навык сразу. Перед первым шагом покажите ровно одну короткую контекстную строку (не более 30 слов) и продолжайте работу в том же ответе, не ожидая реакции:
Применяю «Безопасное проведение изменений через Pull Request»: <кратко назовите конкретную дополнительную процедуру или проверяемый результат для текущего запроса>; продолжаю без ожидания.
Не включайте в строку author_github, внутреннее имя папки или пересказ всего запроса. Не спрашивайте, применять ли навык.
Если одновременно подходят совместимые навыки, выберите минимальный набор и покажите одну общую строку. Если подходы ведут к несовместимым результатам и запрос не позволяет выбрать, спросите только о желаемом результате, не о разрешении применить навык.
Запуск навыка не расширяет полномочия. Выполните всю безопасную и уже разрешённую часть; запросите подтверждение только непосредственно перед ещё не разрешённым внешним или изменяющим действием. Не запрашивайте повторно уже данное разрешение и не дублируйте системное окно подтверждения.
Обзор
Skill защищает цикл WIP/old commit -> clean PR -> merge -> branch cleanup. Он нужен не для любого git-вопроса, а когда есть риск смешать состояния: dirty tree, старый локальный commit, неправильная feature branch, stale remote branch, PR после merge, branch cleanup или remote branch clutter.
Главный принцип: сначала доказать реальное состояние через read-only проверку, затем менять repo только по явному и проверенному scope.
Естественные Входы
Запускайте skill на фразы:
- «вынеси это в отдельную ветку»;
- «сохрани старый commit»;
- «сделай PR, но не смешивай»;
- «этот WIP не должен попасть в текущую ветку»;
- «PR смержен, что теперь?»;
- «убери branch clutter»;
- «можно архивировать после PR?»;
- «почисти remote branches»;
- «доведи локальную работу до clean PR»;
- «пока шли тесты, main продвинулся; перед commit ещё раз сверь базу и не потеряй WIP»;
- «после merge верни repo в чистое состояние».
Общий Первый Шаг
Перед любым изменяющим действием выполните read-only reality check. Если доступен sverka-git-pered-deystviem, используйте его правила как нижний gate.
Минимальный снимок:
git -C <repo> status --short --branch --untracked-files=all
git -C <repo> diff --stat
git -C <repo> diff --cached --stat
git -C <repo> stash list --max-count=5
git -C <repo> branch -vv
Если работа касается push, PR, merge или remote cleanup, после локального снимка обновите refs и проверьте PR state:
git -C <repo> fetch --all --prune
git -C <repo> branch -r --merged origin/main
git -C <repo> branch -r --no-merged origin/main
Не называйте repo «чистым», если чистое только рабочее дерево, но активная ветка не та, upstream [gone], есть локальный commit без PR или осталась remote branch с diff относительно origin/main.
Явная Граница Одобрения Перед Публикацией
Обычный цикл ниже не добавляет отдельный вопрос об одобрении. Но если
пользователь явно потребовал сначала показать кандидата, действуйте так:
После окончательного staging успешно обновите remote refs и зафиксируйте:
- выбранный до одобрения режим границы. По умолчанию
strict-base:
любой сдвиг base запрещает сам push. Режим target-only допустим,
только если пользователь до одобрения явно согласился, что
push защищается по target/destination, а base ограничивает только PR diff.
Менять режим после одобрения нельзя;
- имя remote, полные имена base/target refs и один фактический
destination. Без сырого вывода в tool log получите списки из
git remote get-url --all "<remote>" и
git remote get-url --push --all "<remote>". Для этой границы оба
списка должны содержать ровно один и тот же URL, а к этой URL не
должна применяться ни одна url.*.insteadOf или url.*.pushInsteadOf. Иначе не
публикуйте: имя origin или уже раскрытая URL не исключают
повторную подстановку адреса;
- полные строки
<base-full-ref> и <target-full-ref> должны различаться.
Их равенство запрещает одобрение, commit, push и работу с PR: точный
lease защищает значение указанного ref, но не доказывает, что target не
является самой base-веткой;
- destination должен быть без встроенного пароля или token,
секретного query/fragment и приватного локального пути, чтобы его можно
было безопасно показать пользователю и передать
git ls-remote и git push.
Иначе остановитесь до push и настройте credential-free destination;
- OID staged tree из
git write-tree;
- OID base и target либо подтверждённое отсутствие target читайте
напрямую с этого destination через
git ls-remote --heads "<destination>" "<base-full-ref>" "<target-full-ref>";
- при существующем target OID HEAD должен точно совпадать с OID target; при
отсутствии target OID HEAD должен точно совпадать с OID base. Иначе сначала
пересоберите кандидата от точного удалённого состояния;
- если существует
MERGE_HEAD, он должен содержать ровно один OID,
совпадающий с OID base. Дополнительные merge parents требуют пересборки;
- OID текущего HEAD как первого будущего parent и, если существует
MERGE_HEAD, все OID из него как остальных будущих parents;
- ожидаемый merge-base base и будущего commit: для обычного commit это
merge-base между base и HEAD, для merge с base среди
MERGE_HEAD — OID
base. Merge без base среди будущих parents этим правилом не публикуйте.
- точный снимок будущих метаданных commit: сообщение побайтово, включая
trailers, строки author и committer с name, email, date и timezone,
режим подписи и полный ожидаемый набор headers с их значениями. Не
подменяйте этот снимок текущими значениями Git config. Если значение
подписи или другого header нельзя зафиксировать до одобрения, этот commit
требует отдельного показа и нового одобрения после создания, но до push.
Покажите пользователю все зафиксированные выше поля снимка, включая режим
границы, remote, полные base/target refs и их OID, destination, staged tree,
HEAD, будущих parents, merge-base и метаданные commit, а также полный
кандидат PR через
git diff --cached <expected-merge-base-oid> --; при существующем target
также покажите изменение относительно него через
git diff --cached <target-oid> --.
Итоговый tree diff не доказывает отсутствие промежуточной неопубликованной
истории и не заменяет точное совпадение HEAD с target или base.
После полного показа считайте этот снимок единственным текущим кандидатом
одобрения. Новый полный снимок сразу аннулирует прежний кандидат и его
одобрение.
Получите явное одобрение этого снимка. Пользователь не обязан повторять
все SHA, refs, destination и метаданные: фраза
одобряю последний показанный снимок достаточна, только если существует
ровно один текущий кандидат и после его показа не менялось ни одно поле.
Такое одобрение относится ко всему снимку, а не только к staged tree.
Ответ да, один OID staged tree, сокращённый SHA или ссылка на прежний
снимок недостаточны. Непосредственно перед commit снова
обновите remote refs и сравните все зафиксированные значения, включая полный
список будущих parents, метаданные commit, режим границы, destination и
отсутствие URL-подстановок, с одобренными.
Ошибка обновления или любое изменение запрещает commit, push, создание и
обновление PR до нового показа и одобрения.
Только после успешного сравнения создайте commit из одобренных значений:
явно передайте точные bytes сообщения, author/committer identities,
timestamps/timezones, режим подписи и ожидаемые headers; не оставляйте их
Git config или текущему времени.
Tree нового commit должен совпасть с одобренным tree, упорядоченный список
его parents — с одобренным списком, а merge-base base и commit — с ожидаемым
merge-base. До push, не выводя неожиданные raw metadata в tool log,
прочитайте полное содержимое объекта через
git cat-file commit "<verified-commit-oid>" и побайтово сравните его
headers и сообщение с одобренным снимком. Любой дополнительный header или
изменение author, committer, trailers, подписи либо сообщения, в том числе
внесённое hook-ом, делает commit новым кандидатом: не публикуйте его до
нового показа и одобрения. Перед push снова сравните destination и отсутствие
URL-подстановок, перечитайте с него base/target и повторите проверки commit.
Push выполняйте в явно зафиксированный destination и только с явным refspec
<verified-commit-oid>:refs/heads/<target>. Сам push должен включать точное
серверное условие target:
# target существовал при одобрении
git push "--force-with-lease=refs/heads/<target>:<approved-target-oid>" \
"<approved-push-destination>" \
"<verified-commit-oid>:refs/heads/<target>"
# target отсутствовал при одобрении; пустой expect требует его отсутствия
git push "--force-with-lease=refs/heads/<target>:" \
"<approved-push-destination>" \
"<verified-commit-oid>:refs/heads/<target>"
Точный lease — только server-side CAS для обновляемого target ref;
при совпадении expect он сам по себе может разрешить non-fast-forward.
Поэтому прежние gates обязаны отдельно доказать нужную ancestry и
fast-forward от одобренного target.
Обычный git push не умеет атомарно сделать update target зависимым от
неизменности base, который не обновляется. Повторный fetch или no-op
refspec для base не создают server-side cross-ref CAS. Если одобрение запрещает
любую публикацию при сдвиге base, остановитесь до push, пока не доказан
такой серверный guard. Только в заранее одобренном режиме target-only
сдвиг base после target push запрещает работу с PR и требует нового diff
и одобрения, но не выдавайте это за server-side запрет самого push.
После push, но до работы с PR, прямым git ls-remote с одобренного
destination снова прочитайте base/target: OID base должен остаться
одобренным, а OID target — указывать ровно на этот commit.
Создайте или обновите PR только для этих веток и прочитайте его обратно: имена
head/base PR должны совпасть с ожидаемыми ветками, а OID head PR должен
совпасть с проверенным OID target. OID base PR не заменяет повторную проверку
живого OID удалённой base. Иначе снова покажите кандидата и получите новое
одобрение.
Режим 1: local-wip-to-clean-pr
Используйте, когда локальный WIP или старый commit нужно вынести в отдельный PR без смешения с текущей веткой.
Процесс:
- Зафиксируйте исходный scope:
- текущая ветка и upstream;
- staged, unstaged, untracked;
- нужные файлы или commit SHA;
- есть ли чужие изменения в рабочем дереве.
- если в одном intended-файле смешаны нужные и чужие hunks и их нельзя
безопасно разделить, остановитесь до staging, stash и rebase и запросите
один выбор точного состава патча.
- Если есть WIP в текущем дереве, сохраните его безопасно:
- общий
git stash push --include-untracked -m "<описание>" допустим,
только если весь status, включая untracked, доказанно относится к задаче;
создание новой записи и глобальную чистоту после неё докажите по
references/late-base-gate.md;
- явный
git add <paths> только после проверки scope, если пользователь подтвердил файлы;
- не используйте общий stash или
git add . при mixed worktree.
- Создайте clean branch от актуального
origin/main:
git switch -c codex/<short-name> origin/main;
- для старого commit используйте
git cherry-pick <sha>.
- Разрешайте конфликты без потери текущих строк:
- для
catalog.md сохраняйте уже существующие skill rows и добавляйте новую строку рядом;
- для registry/docs не откатывайте изменения, пришедшие в
origin/main;
- после ручного разрешения проверяйте отсутствие стандартных conflict-marker строк.
- Доведите пакет до текущего repo contract:
known-exceptions.yaml;
- секция
## Логирование Сбоев;
- examples и catalog row для
team-ready;
- отсутствие шаблонных заглушек.
- Привяжите проверки к точному состоянию:
- обновите refs и сохраните
tested_base_sha;
- разделите clean committed-only состояние и WIP; для WIP проверьте весь
status, включая untracked, stage только доказанный intended scope и
сохраните
tested_tree=$(git -C <repo> write-tree);
- не продолжайте автоматически при mixed WIP;
- выполните
git diff --check, git diff --cached --check, полную suite и
нужные живые пробы.
- После тестов выполните поздний гейт базы до любого commit:
- после каждого первоначального или повторного test run заново обновите
refs, сравните
current_base_sha с tested_base_sha и докажите через
merge-base --is-ancestor, что база входит в HEAD;
- только после успешных compare и ancestry, до commit, сохраните
verified_base_sha; новый drift возвращает процесс к этому же gate;
- при drift commit запрещён: clean committed-only переносите без stash, а
WIP — только по fail-closed процедуре
references/late-base-gate.md;
- после переноса заново получите
tested_tree, повторите полную suite,
base-sensitive checks и затронутые живые пробы; для изменения Codex
plugin явно пересчитайте semver относительно нового origin/main, сохранив
выбранный до drift тип повышения (patch, minor или major); если тип
не доказан, остановитесь для одного выбора до повторных тестов.
- Сформируйте commit и свяжите его с тестами:
- непосредственно до commit повторно сравните index с
tested_tree,
докажите отсутствие tracked изменений вне index, untracked и unmerged;
- после commit сохраните
verified_head_sha и докажите, что его tree в
точности равен tested_tree, а staged, unstaged и untracked отсутствуют;
- после доказанного commit удалите только созданный процессом
recovery-stash: заново найдите его текущий selector по сохранённым object
SHA и subject, непосредственно перед
stash drop ещё раз сверьте SHA и
не выполняйте cleanup без исключительного контроля над stash reflog;
если точная идентичность или такой контроль не доказаны, сохраните stash
и сообщите его SHA и команду восстановления. Исходные stashes не меняйте.
- Непосредственно перед push выполните короткий гейт ещё раз:
- после fetch база должна равняться
verified_base_sha и входить в HEAD;
- текущие HEAD и tree должны равняться
verified_head_sha и tested_tree,
а полный status — оставаться пустым;
- любой drift возвращает процесс к переносу и повторным проверкам.
- Push:
- новую ветку публикуйте обычным
git push -u origin <branch>;
- перед переписыванием опубликованной ветки сохраните её remote SHA, а
после rebase/amend используйте только явный lease
--force-with-lease=refs/heads/<branch>:<expected_remote_sha> по правилам
references/late-base-gate.md.
Если действует явная граница одобрения, вместо этой сокращённой команды
используйте явные destination, refspec и exact lease из раздела выше.
- После push, но до PR, снова получите
origin/main и точный remote head:
- base drift возвращает процесс к rebase и повторным тестам;
- remote head, не равный
verified_head_sha, останавливает процесс;
- оставшийся из-за заблокированного cleanup recovery-stash сохраняйте по
object SHA и явно называйте способ восстановления.
- Откройте PR - это стандартное завершение цикла
local-wip-to-clean-pr, а не
шаг, ожидающий отдельного запроса на публикацию:
- title и body должны описывать scope, происхождение WIP и проверки;
- затем проверьте
mergeable, changed files и checks.
- После открытия или обновления PR проверьте автоматическое review от
chatgpt-codex-connector: если согласны с замечанием - почините и
запушьте фикс; если не согласны или видите иначе - ответьте на
комментарий с обоснованием на русском. Не оставляйте замечание бота без
ответа ни в одну, ни в другую сторону. Это про обработку уже пришедшего
отзыва, а не про подмену собственного review содержимого PR.
Если title или body изменены после выполнения PR-governance job, старый зелёный
job не подтверждает новые метаданные. Снова проверьте текущий текст локальным
governance script, если он есть в repo. Для утверждения именно о CI нужен новый
pull_request event с уже исправленными метаданными: простой rerun старого job
может использовать прежний event payload. Не создавайте бессодержательный
commit только ради нового события — разделяйте локальную проверку текущего
текста и устаревший CI-сигнал до следующего содержательного push или иного
штатного нового события.
Режим 2: post-merge-branch-housekeeping
Используйте после merge или когда пользователь хочет убрать branch clutter.
Процесс:
- Обновите refs:
- Проверьте, что PR действительно merged, а не только green:
- PR
state;
mergedAt или merge commit;
- commit reachable из
origin/main.
- Верните локальный repo в ожидаемое состояние:
- если worktree clean, переключитесь на
main;
- fast-forward local
main до origin/main;
- не продолжайте новую работу из старой feature branch.
- Удалите локальные branches только если они merged в
origin/main.
- Для remote cleanup:
- перечислите
git branch -r --merged origin/main;
- сверяйте с PR state, если branch name неочевиден;
- удаляйте remote branch только если она доказанно merged или явно признана stale/discarded пользователем.
- Unmerged remote branches не удаляйте автоматически:
- покажите commit, diff, возраст, PR state;
- классифицируйте
keep, delete after confirmation, rebuild as new PR.
- В конце покажите:
- текущую ветку;
- clean worktree;
- локальные branches;
- remote branches, которые остались, и почему.
Правила Безопасности
Нельзя:
- использовать
git add . при mixed worktree;
- создавать общий stash при недоказанном mixed WIP;
- продолжать commit или push после drift
origin/main по результатам старых тестов;
- удалять recovery-stash по текущей позиции вместо записанного object SHA;
- удалять ветку, если commit не reachable из
origin/main или merged PR;
- force-push без явного ожидаемого remote SHA в
--force-with-lease;
- выполнять
git reset --hard;
- считать
git branch -r достаточным доказательством для удаления remote branch;
- продолжать новую работу из старой feature branch после merge;
- считать skipped publish job проблемой без проверки условия workflow;
- считать
200, green check или merged PR доказательством локальной установки.
Границы
Не используйте skill:
- для учебного вопроса без намерения менять repo;
- для CI-debug как отдельной задачи, если проблема уже локализована в логах GitHub Actions;
- для публикации PR, если пользователь просил только анализ или план;
- для destructive cleanup вне подтверждённого repo;
- чтобы заменить review содержимого PR.
Если есть несколько repo-кандидатов или пользователь не указал target repo, остановитесь после read-only поиска и попросите выбрать один repo.
Опрос После Использования
Опрос задаётся один раз — после завершения цикла (PR влит и cleanup сделан) или явного стопа, не посреди рабочего цикла. Если пользователь уже ответил «пропустить» в этой сессии, не переспрашивайте.
Опрос по skill:
1. Что в этом использовании provedenie-vetki-do-uborki было полезно?
2. Что стоит доработать в skill или его формате?
Можно ответить коротко или написать "пропустить".
Если пользователь ответил, сохраните санированную карточку в ~/.codex/skill-runs/provedenie-vetki-do-uborki/usage-feedback.jsonl — лучше через bundled script:
python3 scripts/log_usage_feedback.py --liked "..." --improve "..." --outcome "..."
Script перед записью редактирует приватные пути, контакты и token-like строки и сохраняет redaction_applied и redaction_types. Если запись невозможна из-за sandbox, прав или отсутствия tools, не делайте вид, что лог сохранён: скажите об этом и покажите короткую JSONL-карточку для ручного сохранения. Raw-ответы, контакты, пути и секреты не коммитить.
Логирование Сбоев
Перед выполнением прочитайте локальный known-exceptions.yaml как список уже известных случаев и применяйте подходящее do_next_time без нового поиска.
Если пользователь поправил skill, tool/API/browser упал, нарушен режим работы, пришлось искать workaround или skill сделал ложное предположение, запишите приватную карточку в ~/.codex/skill-runs/<skill-name>/exception-log.jsonl.
Пишите факты: что skill хотел сделать, что сделал, где сломался, какая предпосылка была ложной и что сделать в следующий раз. Если поле неизвестно, пишите unknown. Raw logs не коммитить.
Критерий Готовности
Работа завершена, когда:
- рабочее дерево clean или явно назван оставшийся intentional WIP;
- текущая ветка соответствует этапу: clean PR branch до merge,
main после cleanup;
- PR создан или cleanup завершён;
- проверки названы явно;
- поздний гейт после тестов и короткий гейт перед push прошли на одном
verified_base_sha, а опубликованный verified_head_sha содержит ровно
проверенный tested_tree;
- созданный процессом recovery-stash удалён по object SHA либо сохранён с
точной командой восстановления; исходные stashes не изменены;
- merged local branches удалены;
- remote branches удалены только если merged/closed и safe;
- оставшиеся unmerged branches перечислены с причиной keep/delete-later;
- пользователь понимает, что не было изменено и почему.
1---2name: provedenie-vetki-do-uborki3description: «Вынеси WIP или старый commit в ветку», «сделай PR, не смешивая», «PR смержен, архивировать?», «убери branch clutter и remote branches», «пока шли тесты, main продвинулся».4---56# Git PR Lifecycle Safeguard78## Запуск Навыка910При явном вызове или однозначном смысловом совпадении применяйте навык сразу. Перед первым шагом покажите ровно одну короткую контекстную строку (не более 30 слов) и продолжайте работу в том же ответе, не ожидая реакции:1112Применяю **«Безопасное проведение изменений через Pull Request»**: <кратко назовите конкретную дополнительную процедуру или проверяемый результат для текущего запроса>; продолжаю без ожидания.1314Не включайте в строку `author_github`, внутреннее имя папки или пересказ всего запроса. Не спрашивайте, применять ли навык.1516Если одновременно подходят совместимые навыки, выберите минимальный набор и покажите одну общую строку. Если подходы ведут к несовместимым результатам и запрос не позволяет выбрать, спросите только о желаемом результате, не о разрешении применить навык.1718Запуск навыка не расширяет полномочия. Выполните всю безопасную и уже разрешённую часть; запросите подтверждение только непосредственно перед ещё не разрешённым внешним или изменяющим действием. Не запрашивайте повторно уже данное разрешение и не дублируйте системное окно подтверждения.1920## Обзор2122Skill защищает цикл `WIP/old commit -> clean PR -> merge -> branch cleanup`. Он нужен не для любого git-вопроса, а когда есть риск смешать состояния: dirty tree, старый локальный commit, неправильная feature branch, stale remote branch, PR после merge, branch cleanup или remote branch clutter.2324Главный принцип: сначала доказать реальное состояние через read-only проверку, затем менять repo только по явному и проверенному scope.2526## Естественные Входы2728Запускайте skill на фразы:2930- «вынеси это в отдельную ветку»;31- «сохрани старый commit»;32- «сделай PR, но не смешивай»;33- «этот WIP не должен попасть в текущую ветку»;34- «PR смержен, что теперь?»;35- «убери branch clutter»;36- «можно архивировать после PR?»;37- «почисти remote branches»;38- «доведи локальную работу до clean PR»;39- «пока шли тесты, main продвинулся; перед commit ещё раз сверь базу и не потеряй WIP»;40- «после merge верни repo в чистое состояние».4142## Общий Первый Шаг4344Перед любым изменяющим действием выполните read-only reality check. Если доступен `sverka-git-pered-deystviem`, используйте его правила как нижний gate.4546Минимальный снимок:4748```bash49git -C <repo> status --short --branch --untracked-files=all50git -C <repo> diff --stat51git -C <repo> diff --cached --stat52git -C <repo> stash list --max-count=553git -C <repo> branch -vv54```5556Если работа касается push, PR, merge или remote cleanup, после локального снимка обновите refs и проверьте PR state:5758```bash59git -C <repo> fetch --all --prune60git -C <repo> branch -r --merged origin/main61git -C <repo> branch -r --no-merged origin/main62```6364Не называйте repo «чистым», если чистое только рабочее дерево, но активная ветка не та, upstream `[gone]`, есть локальный commit без PR или осталась remote branch с diff относительно `origin/main`.6566## Явная Граница Одобрения Перед Публикацией6768Обычный цикл ниже не добавляет отдельный вопрос об одобрении. Но если69пользователь явно потребовал сначала показать кандидата, действуйте так:70711. После окончательного staging успешно обновите remote refs и зафиксируйте:72 - выбранный до одобрения режим границы. По умолчанию `strict-base`:73 любой сдвиг base запрещает сам push. Режим `target-only` допустим,74 только если пользователь до одобрения явно согласился, что75 push защищается по target/destination, а base ограничивает только PR diff.76 Менять режим после одобрения нельзя;77 - имя remote, полные имена base/target refs и один фактический78 destination. Без сырого вывода в tool log получите списки из79 `git remote get-url --all "<remote>"` и80 `git remote get-url --push --all "<remote>"`. Для этой границы оба81 списка должны содержать ровно один и тот же URL, а к этой URL не82 должна применяться ни одна `url.*.insteadOf` или `url.*.pushInsteadOf`. Иначе не83 публикуйте: имя `origin` или уже раскрытая URL не исключают84 повторную подстановку адреса;85 - полные строки `<base-full-ref>` и `<target-full-ref>` должны различаться.86 Их равенство запрещает одобрение, `commit`, `push` и работу с PR: точный87 lease защищает значение указанного ref, но не доказывает, что target не88 является самой base-веткой;89 - destination должен быть без встроенного пароля или token,90 секретного query/fragment и приватного локального пути, чтобы его можно91 было безопасно показать пользователю и передать `git ls-remote` и `git push`.92 Иначе остановитесь до push и настройте credential-free destination;93 - OID staged tree из `git write-tree`;94 - OID base и target либо подтверждённое отсутствие target читайте95 напрямую с этого destination через96 `git ls-remote --heads "<destination>" "<base-full-ref>" "<target-full-ref>"`;97 - при существующем target OID HEAD должен точно совпадать с OID target; при98 отсутствии target OID HEAD должен точно совпадать с OID base. Иначе сначала99 пересоберите кандидата от точного удалённого состояния;100 - если существует `MERGE_HEAD`, он должен содержать ровно один OID,101 совпадающий с OID base. Дополнительные merge parents требуют пересборки;102 - OID текущего HEAD как первого будущего parent и, если существует103 `MERGE_HEAD`, все OID из него как остальных будущих parents;104 - ожидаемый merge-base base и будущего commit: для обычного commit это105 merge-base между base и HEAD, для merge с base среди `MERGE_HEAD` — OID106 base. Merge без base среди будущих parents этим правилом не публикуйте.107 - точный снимок будущих метаданных commit: сообщение побайтово, включая108 trailers, строки author и committer с name, email, date и timezone,109 режим подписи и полный ожидаемый набор headers с их значениями. Не110 подменяйте этот снимок текущими значениями Git config. Если значение111 подписи или другого header нельзя зафиксировать до одобрения, этот commit112 требует отдельного показа и нового одобрения после создания, но до push.113 Покажите пользователю все зафиксированные выше поля снимка, включая режим114 границы, remote, полные base/target refs и их OID, destination, staged tree,115 HEAD, будущих parents, merge-base и метаданные commit, а также полный116 кандидат PR через `git diff --cached <expected-merge-base-oid> --`; при существующем target117 также покажите изменение относительно него через118 `git diff --cached <target-oid> --`.119 Итоговый tree diff не доказывает отсутствие промежуточной неопубликованной120 истории и не заменяет точное совпадение HEAD с target или base.121 После полного показа считайте этот снимок единственным текущим кандидатом122 одобрения. Новый полный снимок сразу аннулирует прежний кандидат и его123 одобрение.1242. Получите явное одобрение этого снимка. Пользователь не обязан повторять125 все SHA, refs, destination и метаданные: фраза126 `одобряю последний показанный снимок` достаточна, только если существует127 ровно один текущий кандидат и после его показа не менялось ни одно поле.128 Такое одобрение относится ко всему снимку, а не только к staged tree.129 Ответ `да`, один OID staged tree, сокращённый SHA или ссылка на прежний130 снимок недостаточны. Непосредственно перед `commit` снова131 обновите remote refs и сравните все зафиксированные значения, включая полный132 список будущих parents, метаданные commit, режим границы, destination и133 отсутствие URL-подстановок, с одобренными.134 Ошибка обновления или любое изменение запрещает `commit`, `push`, создание и135 обновление PR до нового показа и одобрения.136 Только после успешного сравнения создайте commit из одобренных значений:137 явно передайте точные bytes сообщения, author/committer identities,138 timestamps/timezones, режим подписи и ожидаемые headers; не оставляйте их139 Git config или текущему времени.1403. Tree нового commit должен совпасть с одобренным tree, упорядоченный список141 его parents — с одобренным списком, а merge-base base и commit — с ожидаемым142 merge-base. До `push`, не выводя неожиданные raw metadata в tool log,143 прочитайте полное содержимое объекта через144 `git cat-file commit "<verified-commit-oid>"` и побайтово сравните его145 headers и сообщение с одобренным снимком. Любой дополнительный header или146 изменение author, committer, trailers, подписи либо сообщения, в том числе147 внесённое hook-ом, делает commit новым кандидатом: не публикуйте его до148 нового показа и одобрения. Перед `push` снова сравните destination и отсутствие149 URL-подстановок, перечитайте с него base/target и повторите проверки commit.150 Push выполняйте в явно зафиксированный destination и только с явным refspec151 `<verified-commit-oid>:refs/heads/<target>`. Сам push должен включать точное152 серверное условие target:153154 ```bash155 # target существовал при одобрении156 git push "--force-with-lease=refs/heads/<target>:<approved-target-oid>" \157 "<approved-push-destination>" \158 "<verified-commit-oid>:refs/heads/<target>"159160 # target отсутствовал при одобрении; пустой expect требует его отсутствия161 git push "--force-with-lease=refs/heads/<target>:" \162 "<approved-push-destination>" \163 "<verified-commit-oid>:refs/heads/<target>"164 ```165166 Точный lease — только server-side CAS для обновляемого target ref;167 при совпадении expect он сам по себе может разрешить non-fast-forward.168 Поэтому прежние gates обязаны отдельно доказать нужную ancestry и169 fast-forward от одобренного target.170171 Обычный `git push` не умеет атомарно сделать update target зависимым от172 неизменности base, который не обновляется. Повторный fetch или no-op173 refspec для base не создают server-side cross-ref CAS. Если одобрение запрещает174 любую публикацию при сдвиге base, остановитесь до push, пока не доказан175 такой серверный guard. Только в заранее одобренном режиме `target-only`176 сдвиг base после target push запрещает работу с PR и требует нового diff177 и одобрения, но не выдавайте это за server-side запрет самого push.1784. После `push`, но до работы с PR, прямым `git ls-remote` с одобренного179 destination снова прочитайте base/target: OID base должен остаться180 одобренным, а OID target — указывать ровно на этот commit.181 Создайте или обновите PR только для этих веток и прочитайте его обратно: имена182 head/base PR должны совпасть с ожидаемыми ветками, а OID head PR должен183 совпасть с проверенным OID target. OID base PR не заменяет повторную проверку184 живого OID удалённой base. Иначе снова покажите кандидата и получите новое185 одобрение.186187## Режим 1: local-wip-to-clean-pr188189Используйте, когда локальный WIP или старый commit нужно вынести в отдельный PR без смешения с текущей веткой.190191Процесс:1921931. Зафиксируйте исходный scope:194 - текущая ветка и upstream;195 - staged, unstaged, untracked;196 - нужные файлы или commit SHA;197 - есть ли чужие изменения в рабочем дереве.198 - если в одном intended-файле смешаны нужные и чужие hunks и их нельзя199 безопасно разделить, остановитесь до staging, stash и rebase и запросите200 один выбор точного состава патча.2012. Если есть WIP в текущем дереве, сохраните его безопасно:202 - общий `git stash push --include-untracked -m "<описание>"` допустим,203 только если весь status, включая untracked, доказанно относится к задаче;204 создание новой записи и глобальную чистоту после неё докажите по205 `references/late-base-gate.md`;206 - явный `git add <paths>` только после проверки scope, если пользователь подтвердил файлы;207 - не используйте общий stash или `git add .` при mixed worktree.2083. Создайте clean branch от актуального `origin/main`:209 - `git switch -c codex/<short-name> origin/main`;210 - для старого commit используйте `git cherry-pick <sha>`.2114. Разрешайте конфликты без потери текущих строк:212 - для `catalog.md` сохраняйте уже существующие skill rows и добавляйте новую строку рядом;213 - для registry/docs не откатывайте изменения, пришедшие в `origin/main`;214 - после ручного разрешения проверяйте отсутствие стандартных conflict-marker строк.2155. Доведите пакет до текущего repo contract:216 - `known-exceptions.yaml`;217 - секция `## Логирование Сбоев`;218 - examples и catalog row для `team-ready`;219 - отсутствие шаблонных заглушек.2206. Привяжите проверки к точному состоянию:221 - обновите refs и сохраните `tested_base_sha`;222 - разделите clean committed-only состояние и WIP; для WIP проверьте весь223 status, включая untracked, stage только доказанный intended scope и224 сохраните `tested_tree=$(git -C <repo> write-tree)`;225 - не продолжайте автоматически при mixed WIP;226 - выполните `git diff --check`, `git diff --cached --check`, полную suite и227 нужные живые пробы.2287. После тестов выполните поздний гейт базы до любого commit:229 - после каждого первоначального или повторного test run заново обновите230 refs, сравните `current_base_sha` с `tested_base_sha` и докажите через231 `merge-base --is-ancestor`, что база входит в `HEAD`;232 - только после успешных compare и ancestry, до commit, сохраните233 `verified_base_sha`; новый drift возвращает процесс к этому же gate;234 - при drift commit запрещён: clean committed-only переносите без stash, а235 WIP — только по fail-closed процедуре `references/late-base-gate.md`;236 - после переноса заново получите `tested_tree`, повторите полную suite,237 base-sensitive checks и затронутые живые пробы; для изменения Codex238 plugin явно пересчитайте semver относительно нового `origin/main`, сохранив239 выбранный до drift тип повышения (`patch`, `minor` или `major`); если тип240 не доказан, остановитесь для одного выбора до повторных тестов.2418. Сформируйте commit и свяжите его с тестами:242 - непосредственно до commit повторно сравните index с `tested_tree`,243 докажите отсутствие tracked изменений вне index, untracked и unmerged;244 - после commit сохраните `verified_head_sha` и докажите, что его tree в245 точности равен `tested_tree`, а staged, unstaged и untracked отсутствуют;246 - после доказанного commit удалите только созданный процессом247 recovery-stash: заново найдите его текущий selector по сохранённым object248 SHA и subject, непосредственно перед `stash drop` ещё раз сверьте SHA и249 не выполняйте cleanup без исключительного контроля над stash reflog;250 если точная идентичность или такой контроль не доказаны, сохраните stash251 и сообщите его SHA и команду восстановления. Исходные stashes не меняйте.2529. Непосредственно перед push выполните короткий гейт ещё раз:253 - после fetch база должна равняться `verified_base_sha` и входить в `HEAD`;254 - текущие HEAD и tree должны равняться `verified_head_sha` и `tested_tree`,255 а полный status — оставаться пустым;256 - любой drift возвращает процесс к переносу и повторным проверкам.25710. Push:258 - новую ветку публикуйте обычным `git push -u origin <branch>`;259 - перед переписыванием опубликованной ветки сохраните её remote SHA, а260 после rebase/amend используйте только явный lease261 `--force-with-lease=refs/heads/<branch>:<expected_remote_sha>` по правилам262 `references/late-base-gate.md`.263 Если действует явная граница одобрения, вместо этой сокращённой команды264 используйте явные destination, refspec и exact lease из раздела выше.26511. После push, но до PR, снова получите `origin/main` и точный remote head:266 - base drift возвращает процесс к rebase и повторным тестам;267 - remote head, не равный `verified_head_sha`, останавливает процесс;268 - оставшийся из-за заблокированного cleanup recovery-stash сохраняйте по269 object SHA и явно называйте способ восстановления.27012. Откройте PR - это стандартное завершение цикла `local-wip-to-clean-pr`, а не271 шаг, ожидающий отдельного запроса на публикацию:272 - title и body должны описывать scope, происхождение WIP и проверки;273 - затем проверьте `mergeable`, changed files и checks.27413. После открытия или обновления PR проверьте автоматическое review от275 `chatgpt-codex-connector`: если согласны с замечанием - почините и276 запушьте фикс; если не согласны или видите иначе - ответьте на277 комментарий с обоснованием на русском. Не оставляйте замечание бота без278 ответа ни в одну, ни в другую сторону. Это про обработку уже пришедшего279 отзыва, а не про подмену собственного review содержимого PR.280281Если title или body изменены после выполнения PR-governance job, старый зелёный282job не подтверждает новые метаданные. Снова проверьте текущий текст локальным283governance script, если он есть в repo. Для утверждения именно о CI нужен новый284`pull_request` event с уже исправленными метаданными: простой rerun старого job285может использовать прежний event payload. Не создавайте бессодержательный286commit только ради нового события — разделяйте локальную проверку текущего287текста и устаревший CI-сигнал до следующего содержательного push или иного288штатного нового события.289290## Режим 2: post-merge-branch-housekeeping291292Используйте после merge или когда пользователь хочет убрать branch clutter.293294Процесс:2952961. Обновите refs:297 - `git fetch --all --prune`.2982. Проверьте, что PR действительно merged, а не только green:299 - PR `state`;300 - `mergedAt` или merge commit;301 - commit reachable из `origin/main`.3023. Верните локальный repo в ожидаемое состояние:303 - если worktree clean, переключитесь на `main`;304 - fast-forward local `main` до `origin/main`;305 - не продолжайте новую работу из старой feature branch.3064. Удалите локальные branches только если они merged в `origin/main`.3075. Для remote cleanup:308 - перечислите `git branch -r --merged origin/main`;309 - сверяйте с PR state, если branch name неочевиден;310 - удаляйте remote branch только если она доказанно merged или явно признана stale/discarded пользователем.3116. Unmerged remote branches не удаляйте автоматически:312 - покажите commit, diff, возраст, PR state;313 - классифицируйте `keep`, `delete after confirmation`, `rebuild as new PR`.3147. В конце покажите:315 - текущую ветку;316 - clean worktree;317 - локальные branches;318 - remote branches, которые остались, и почему.319320## Правила Безопасности321322Нельзя:323324- использовать `git add .` при mixed worktree;325- создавать общий stash при недоказанном mixed WIP;326- продолжать commit или push после drift `origin/main` по результатам старых тестов;327- удалять recovery-stash по текущей позиции вместо записанного object SHA;328- удалять ветку, если commit не reachable из `origin/main` или merged PR;329- force-push без явного ожидаемого remote SHA в `--force-with-lease`;330- выполнять `git reset --hard`;331- считать `git branch -r` достаточным доказательством для удаления remote branch;332- продолжать новую работу из старой feature branch после merge;333- считать skipped publish job проблемой без проверки условия workflow;334- считать `200`, green check или merged PR доказательством локальной установки.335336## Границы337338Не используйте skill:339340- для учебного вопроса без намерения менять repo;341- для CI-debug как отдельной задачи, если проблема уже локализована в логах GitHub Actions;342- для публикации PR, если пользователь просил только анализ или план;343- для destructive cleanup вне подтверждённого repo;344- чтобы заменить review содержимого PR.345346Если есть несколько repo-кандидатов или пользователь не указал target repo, остановитесь после read-only поиска и попросите выбрать один repo.347348## Опрос После Использования349350Опрос задаётся один раз — после завершения цикла (PR влит и cleanup сделан) или явного стопа, не посреди рабочего цикла. Если пользователь уже ответил «пропустить» в этой сессии, не переспрашивайте.351352```text353Опрос по skill:3541. Что в этом использовании provedenie-vetki-do-uborki было полезно?3552. Что стоит доработать в skill или его формате?356Можно ответить коротко или написать "пропустить".357```358359Если пользователь ответил, сохраните санированную карточку в `~/.codex/skill-runs/provedenie-vetki-do-uborki/usage-feedback.jsonl` — лучше через bundled script:360361```bash362python3 scripts/log_usage_feedback.py --liked "..." --improve "..." --outcome "..."363```364365Script перед записью редактирует приватные пути, контакты и token-like строки и сохраняет `redaction_applied` и `redaction_types`. Если запись невозможна из-за sandbox, прав или отсутствия tools, не делайте вид, что лог сохранён: скажите об этом и покажите короткую JSONL-карточку для ручного сохранения. Raw-ответы, контакты, пути и секреты не коммитить.366367## Логирование Сбоев368369Перед выполнением прочитайте локальный `known-exceptions.yaml` как список уже известных случаев и применяйте подходящее `do_next_time` без нового поиска.370371Если пользователь поправил skill, tool/API/browser упал, нарушен режим работы, пришлось искать workaround или skill сделал ложное предположение, запишите приватную карточку в `~/.codex/skill-runs/<skill-name>/exception-log.jsonl`.372373Пишите факты: что skill хотел сделать, что сделал, где сломался, какая предпосылка была ложной и что сделать в следующий раз. Если поле неизвестно, пишите `unknown`. Raw logs не коммитить.374375## Критерий Готовности376377Работа завершена, когда:378379- рабочее дерево clean или явно назван оставшийся intentional WIP;380- текущая ветка соответствует этапу: clean PR branch до merge, `main` после cleanup;381- PR создан или cleanup завершён;382- проверки названы явно;383- поздний гейт после тестов и короткий гейт перед push прошли на одном384 `verified_base_sha`, а опубликованный `verified_head_sha` содержит ровно385 проверенный `tested_tree`;386- созданный процессом recovery-stash удалён по object SHA либо сохранён с387 точной командой восстановления; исходные stashes не изменены;388- merged local branches удалены;389- remote branches удалены только если merged/closed и safe;390- оставшиеся unmerged branches перечислены с причиной keep/delete-later;391- пользователь понимает, что не было изменено и почему.