Agent Dev 101

Модуль 17 · Урок 17.12

Урок 17.12. Завершение ветки разработки

На этой странице
  1. Зачем это нужно
  2. Основная идея
  3. Шаг 1: верифицировать тесты
  4. Шаг 2: определить окружение
  5. Шаг 3: определить базовую ветку
  6. Шаг 4: предъявить опции
  7. Шаг 5: исполнить выбор
  8. Шаг 6: очистка workspace
  9. Быстрая шпаргалка
  10. Отмазки
  11. Практика
  12. Краткое резюме
  13. Вопросы для самопроверки
  14. Что дальше
  15. Источники

Дополнительный источник: https://lzw.me/docs/opencodedocs/obra/superpowers/advanced/branch-completion/index.html

Зачем это нужно

Седьмой, завершающий шаг базового workflow (урок 17.5). Скилл finishing-a-development-branch активируется, когда реализация завершена, тесты проходят и пора решать, как интегрировать работу. Это короткий, но важный скилл: он закрывает цикл, открытый в уроке 17.7 (изоляция), — снимает изоляцию правильно: проверить, спросить, исполнить выбор, вычистить. Ошибки на этом шаге дороги: merge не в ту базу или удаление worktree с незакоммиченными файлами теряют работу.

Сквозная идея модуля здесь замыкается: все шаги оставляли за человеком право решать (HARD-GATE в уроке 17.6, выбор исполнения в 17.9, adjudикация находок в 17.11); финальное решение об интеграции — тоже решение человека, и скилл это фиксирует явно.

Основная идея

Формула скилла: «Verify tests → Detect environment → Present options → Execute choice → Clean up» — проверить тесты → определить окружение → предъявить опции → исполнить выбор → вычистить. Меню опций предъявляется ровно как написано — кратко, исчерпывающе, без импровизированных пунктов; решение об интеграции принимает человек. Скилл объявляется в начале: «I'm using the finishing-a-development-branch skill to complete this work».

flowchart TD A["Шаг 1: полный suite"] -->|красный| B["Отчет о падениях,<br/>СТОП"] A -->|зеленый| C["Шаг 2: определить окружение<br/>(обычное репо / worktree /<br/>detached HEAD)"] C --> D["Шаг 3: определить базовую ветку<br/>(подтвердить)"] D --> E["Шаг 4: меню опций"] E --> F["Шаг 5: исполнить выбор"] F --> G["Шаг 6: очистка workspace<br/>(по правилам владения)"]

Шаг 1: верифицировать тесты

Полный suite проекта (npm test / cargo test / pytest / go test ./...).

Падают — отчитаться о падениях и остановиться: меню появляется только после зеленого suite:

text
Tests failing (<N> failures). Must fix before completing:

[показать падения]

Проходят — к шагу 2. Смысл первого шага (из таблицы рационализаций): «зеленый прогон доказывает только то дерево, на котором он ran» — «тесты проходили раньше в сессии» не считается: прогон выполняется на дереве, которое вы собираетесь интегрировать.

Шаг 2: определить окружение

bash
GIT_DIR=$(cd "$(git rev-parse --git-dir)" 2>/dev/null && pwd -P)
GIT_COMMON=$(cd "$(git rev-parse --git-common-dir)" 2>/dev/null && pwd -P)
# зафиксировать сейчас, пока мы еще внутри workspace — шаг 5 меняет
# каталог до того, как очистке (шаг 6) понадобится это значение
WORKTREE_PATH=$(git rev-parse --show-toplevel)

Таблица скилла:

Состояние Меню Очистка
GIT_DIR == GIT_COMMON (обычное репо) стандартные 3 опции worktree чистить нечего
GIT_DIR != GIT_COMMON, именованная ветка стандартные 3 опции по признаку владения (шаг 6)
GIT_DIR != GIT_COMMON, detached HEAD сокращенные 2 опции (без merge) управляется извне — оставить на месте

Шаг 3: определить базовую ветку

Базовая ветка — то, от чего ответвилась работа; обычно названа в плане, разговоре или upstream ветки. Неизвестна — спросить: «This branch split from <лучшая догадка> — верно?» Подтверждение до merge обязательно: merge не в ту базу дорого отменять.

Шаг 4: предъявить опции

Обычное репо и worktree с именованной веткой — ровно эти 3 опции:

text
Implementation complete. What would you like to do?

1. Merge back to <base-branch> locally
2. Push and create a Pull Request
3. Keep the branch as-is (I'll handle it later)

Which option?

Detached HEAD — ровно эти 2:

text
Implementation complete. You're on a detached HEAD (externally managed workspace).

1. Push as new branch and create a Pull Request
2. Keep as-is (I'll handle it later)

Which option?

Правила меню (важные!): меню предъявляется дословно — кратко, с опциями из списка и без придумывания. Выбрасывание работы появляется только как ответ на явную просьбу партнера (раздел ниже). Подождать ответа: решение об интеграции — его. Отдельное правило детекции среды из урока 17.7 помнит о ветке: detached HEAD «управляется извне» — отсюда сокращенное меню без merge.

Шаг 5: исполнить выбор

Опция 1: merge локально

bash
MAIN_ROOT=$(git -C "$(git rev-parse --git-common-dir)/.." rev-parse --show-toplevel)
cd "$MAIN_ROOT"

# merge сначала — успех проверить до удаления чего-либо
git checkout <base-branch>
git pull
git merge <feature-branch>

# верифицировать тесты на смерженном результате
<test command>

Тесты падают на результате — стоп, worktree и ветка остаются на месте, разбираться: ничего не запушено, merge локален и обратим. Результат зеленый — очистка worktree (шаг 6), затем удаление ветки:

bash
git branch -d <feature-branch>

Опция 2: push и PR

bash
git push -u origin <feature-branch>
# из detached HEAD — назвать новую ветку на remote:
# git push origin HEAD:refs/heads/<new-branch>

Затем PR/MR против <base-branch> инструментарием форджа — CLI при наличии, или URL создания, который печатает большинство форджей при push, — по шаблону и конвенциям репо; URL — партнеру. Worktree сохраняется: итерации по замечаниям PR происходят в нем.

Опция 3: оставить как есть

Отчет: Keeping branch <name>. Worktree preserved at <path>.

Если партнер просит выбросить работу

Путь существует только как ответ на явную просьбу выбросить работу. Подтверждение дословно:

text
This will permanently delete:
- Branch <name>
- All commits: <commit-list>
- Worktree at <path>

Type 'discard' to confirm.

Ждать именно слово discard. После подтверждения — смена каталога в MAIN_ROOT, очистка (шаг 6) и git branch -D <feature-branch>.

Шаг 6: очистка workspace

Выполняется для опции 1 и подтвержденного discard. Опции 2 и 3 worktree всегда сохраняют. Оба вызывающих уже сменили каталог в корень главного репо — удаление worktree обязано выполняться извне него — и используют GIT_DIR/GIT_COMMON/WORKTREE_PATH, зафиксированные в шаге 2 до смены каталога.

  • GIT_DIR == GIT_COMMON: обычное репо, чистить нечего; готово.
  • WORKTREE_PATH внутри .worktrees/ или worktrees/: worktree создал Superpowers — очистка наша:
bash
git worktree remove "$WORKTREE_PATH"
git worktree prune  # самозаживление: подчистить устаревшие регистрации
  • Удаление отказано (contains modified or untracked files): в worktree есть файлы, которых нет больше нигде — незакоммиченные планы, заметки, черновики. Никогда --force по собственной инициативе. Показать партнеру, что на кону:
bash
git -C "$WORKTREE_PATH" status --porcelain -uall
text
Worktree removal refused — these files were never committed:

<список файлов>

1. Commit them to <branch> before cleanup
2. Move them into <main repo root>
3. Delete them (unrecoverable)

Which?

Исполнить выбор, затем удалить worktree.

  • Иначе: workspace принадлежит среде хоста — оставить на месте; есть инструмент выхода из workspace (нативный тул каркаса) — использовать его.

Быстрая шпаргалка

Опция Merge Push Worktree Ветка
1. Merge локально да — удаляется удаляется
2. PR — да сохраняется сохраняется
3. Оставить — — сохраняется сохраняется
Discard (только явная просьба) — — удаляется удаляется (force)

Отмазки

Выборка таблицы рационализаций скилла:

Отмазка Реальность
«Тесты проходили раньше в сессии» Прогони suite на дереве, которое интегрируешь. Зеленый прогон доказывает только то дерево, на котором ran.
«Очевидно хочет merge» Интеграция — решение партнера. Предъяви меню и жди.
«Похоже, закончил с фичей — предложу выбросить» Меню исчерпывающе как написано. Discard — только когда партнер попросил теми словами.
«"Yeah, get rid of it" считается подтверждением» Только напечатанное слово discard авторизует удаление.
«PR поднят — worktree теперь мусор» Замечания PR правятся в этом worktree. Он остается до приземления работы.
«Другой worktree выглядит устаревшим — почищу и его» Чистятся только worktree под .worktrees//worktrees/. Остальное принадлежит среде.
«Removal refused — --force просто закончит очистку» Отказ значит: файлы существуют только там. --force уничтожает их навсегда. Покажи партнеру и спроси.
«Падение смерженного результата — наверняка flaky» Падающий результат останавливает все. Ветка и worktree на месте, пока не разберетесь.
«База очевидно main» Подтверди точку ответвления или спроси. Merge не в ту базу дорого отменять.
«Push отвергнут — force-push исправит» Отвергнутый push значит: remote ушел вперед. Разберись; force-push — только по явной просьбе партнера.

Практика

На учебной ветке (из практики урока 17.7) пройдите завершение целиком:

  1. Прогоните suite; зафиксируйте, зеленый ли он на дереве, которое интегрируете.
  2. Определите окружение командами шага 2; сверьте с ожиданием (worktree с именованной веткой).
  3. Предъявите меню дословно и «исполните» выбор опции 1: merge, тесты на результате, удаление ветки, очистка worktree.
  4. Сымитируйте отказ удаления: создайте в worktree незакоммиченный файл и убедитесь, что git worktree remove отказывает; напишите три опции из скилла для этого случая.

Краткое резюме

finishing-a-development-branch закрывает цикл: верифицировать тесты на интегрируемом дереве → определить окружение и базовую ветку → предъявить меню дословно (3 опции, или 2 для detached HEAD) → исполнить выбор → вычистить по правилам владения.

  • Меню — дословно, без импровизации; решение об интеграции — человека; discard — только по явной просьбе и слову discard.
  • Merge: тесты прогоняются на смерженном результате; падение — стоп, все остается на месте.
  • PR: worktree сохраняется для итераций по замечаниям.
  • Отказ удаления worktree: файлы, которых нет нигде больше; --force по своей инициативе запрещен — показать партнеру и спросить.

Вопросы для самопроверки

  1. Почему «тесты проходили раньше в сессии» не считается верификацией шага 1?
  2. Как окружение (обычное репо / worktree / detached HEAD) меняет меню опций и правила очистки?
  3. Почему подтверждение discard обязано быть напечатанным словом, а не «Yeah, get rid of it»?
  4. Что происходит при падении тестов на смерженном результате и почему это «дешевле», чем могло бы быть?
  5. Почему опция PR сохраняет worktree, а merge — нет?
  6. При отказе удаления worktree: какие три опции предъявляются и почему --force по инициативе агента запрещен?

Что дальше

Семь шагов базового workflow пройдены. Следующая пара уроков — сквозные дисциплины качества: урок 17.13 разбирает systematic-debugging (4 фазы корневой причины) и verification-before-completion (доказательства прежде заявлений).

Источники

Обновлено 03.10.2026