Ревью и вливание кода¶
Задача на код считается сделанной, когда её результат принят: ревью одобрено
человеком и ветка влита. И то и другое — критерии приёмки самой задачи,
которые объявляет её тип, а не отдельные задачи ревью и правок. Статья описывает,
как это устроено для типа coding-task пакета selfdev, что видит ревьюер, что
происходит при отказе и как исполнитель продолжает работу. Она для руководителей
разработки, ревьюеров и администраторов установки. Обоснование — TAI-ADR-0053 и
CP-ADR-0067 (амендмент В5–В9).
Как это устроено¶
sequenceDiagram
autonumber
participant A as Агент-исполнитель (демон)
participant CP as Control Plane
participant R as Ревьюер (человек)
participant S as Исполнитель скиллов (git.merge@1)
A->>CP: коммит на ветке task/<publicId>, публикация, succeed_run
CP->>CP: попытка проверки: claim снят, зависимые недоступны
CP->>R: gate-approval критерия review (approver из типа)
alt approve
R->>CP: approve
CP->>S: git.merge@1 полномочиями ревьюера (основание — approval)
alt merged: true
CP->>CP: task.verified → done; зависимые доступны
else conflict / branch_moved
CP->>A: task.verification_failed, комментарий; задача в todo
end
else reject
R->>CP: reject с комментарием
CP->>A: task.verification_failed, комментарий; задача в todo
end
A->>CP: та же задача, та же ветка, «Замечания последней проверки» в prompt
- Исполнитель сдаёт задачу: демон коммитит работу на ветку
task/<publicId>, публикует её в forge и завершает прогон с артефактомcommit. - Ядро открывает попытку проверки: claim снят, задачу нельзя взять, её
зависимые не выдаются (
task_not_ready) — они не начнутся на базе без предшественника. - Критерий
review(human) — ядро запрашивает gate-approval у ревьюера, объявленного типом. - После одобрения критерий
merge(deterministic) вызывает скиллgit.merge@1: влить ровно одобренный коммит в целевую ветку. - Оба пройдены — задача выполнена (
task.verified,task.completed), зависимые становятся доступны.
Задача без опубликованного коммита (исполнитель ничего не изменил, публикация не
удалась) пропускает оба критерия — у них условие when на
$.task.artifact[commit].metadata.published — и становится выполненной сразу.
Критерии типа coding-task¶
acceptance:
- key: review
kind: human
description: Ревью кода человеком …
spec:
approver: ${SELFDEV_REVIEWER_PRINCIPAL}
when: ["$.task.artifact[commit].metadata.published"]
- key: merge
kind: deterministic
description: Одобренный коммит влит в целевую ветку скиллом git.merge@1 …
spec:
skill: git.merge@1
inputs:
repository: "$.task.artifact[commit].metadata.repository!"
branch: "$.task.artifact[commit].metadata.branch!"
commit: "$.task.artifact[commit].metadata.commit!"
target: "$.task.artifact[commit].metadata.targetBranch!"
message: "Merge $.task.publicId!: $.task.title"
expect: {merged: true}
when: ["$.task.artifact[commit].metadata.published"]
- Критерии принадлежат типу: задача не может их заменить (критерий задачи с
ключом
reviewилиmerge—422 invalid_acceptance), только добавить свои. merge— внешняя запись: ядро допускает её, только если раньше в той же попытке прошёлhumanс тем жеwhen. Вызов идёт полномочиями ревьюера, решившего gate, с основаниемauthorizationBasis = {kind: approval, …}: влить ветку разрешил человек, а не агент, сдавший работу.- Ревьюер установки — переменная
SELFDEV_REVIEWER_PRINCIPAL(UUID principal'а человека). Агент никогда не принимает собственную работу: решающим может быть только человек.
Общие правила критериев типа, when и внешней записи — в статье Типы задач и
статусы.
Артефакт commit¶
Всё, что нужно ревьюеру и скиллу вливания, демон исполнителя кладёт в метаданные
артефакта commit задачи:
| Поле | Значение |
|---|---|
branch |
Ветка задачи task/<publicId> |
commit |
Сдаваемый коммит |
published |
Опубликована ли ветка в forge; false — смотреть нечего, критерии пропускаются |
repository |
Адрес remote, куда опубликована ветка |
targetBranch |
Куда вливать: ветка, от которой отведена рабочая копия (поле задачи baseBranch, например ветка фичи), иначе ветка по умолчанию зеркала |
workspaceKey |
Ключ рабочей копии на хосте исполнителя |
Ревьюер смотрит изменения от merge-base с целевой веткой: ветка могла быть
отведена от старой базы, и в прямом git diff origin/<target> … свежие чужие
коммиты выглядят как удаления.
git fetch origin
git diff $(git merge-base origin/<targetBranch> origin/task/<publicId>) origin/task/<publicId>
Решение ревьюера¶
- Консоль — задача и её запрос решения видны в карточке задачи и на экране согласований; решение — кнопками (см. Консоль платформы).
- Telegram — пакет
notifyприсылает назначенному ревьюеру уведомление с кнопками «Одобрить» / «Отклонить» (см. Правила уведомлений). - Claude Code с плагином оператора —
cp_list_approvals, затемcp_approveилиcp_rejectпосле явного решения человека (см. Повседневные сценарии).
Комментарий к отказу — главное, что получит исполнитель: пишите, что исправить.
Отказ и неудачное вливание¶
| Что случилось | Причина провала критерия | Что дальше |
|---|---|---|
| Ревьюер отклонил | approval_rejected у review |
Комментарий с решением ревьюера, задача в todo тому же исполнителю |
| Конфликт при вливании | провал merge: reason: conflict (вывод git в details) |
Комментарий, задача в todo тому же исполнителю: подтянуть целевую ветку и разрешить конфликт |
| Целевая ветка сдвинулась во время вливания | провал merge: reason: branch_moved |
Так же; повторная сдача запросит новое решение |
| Коммит уже влит | merged: true, reason: already_merged |
Критерий пройден |
Отдельных задач правок и вливания нет: вернувшаяся задача — та же задача, с тем же исполнителем, на той же ветке.
- Замечания в prompt. Если последняя попытка задачи провалена, демон исполнителя перед прогоном читает её и добавляет в prompt блок «Замечания последней проверки»: номер попытки, результат каждого исполненного критерия, у проваленного — причина и комментарий ревьюера (см. Возврат исполнителю).
- Та же ветка. Рабочая копия берёт ветку
task/<publicId>: локальную, если она есть в зеркале, иначе опубликованную в forge (другой исполнитель, новое зеркало), и только если нет ни той, ни другой — новую от базы. Следующая публикация проходит без--force, а ревьюер видит новый коммит той же ветки. - Новое решение. Повторная сдача открывает новую попытку и запрашивает новое одобрение: решение прошлой попытки не засчитывается.
- Третий провал подряд — задача в статусе категории
blocked, дальше решает человек; демон исполнителя такую задачу не берёт.
Что нужно установке¶
| Что | Зачем |
|---|---|
Пакет selfdev с типом coding-task и скиллом git.merge@1 |
Критерии приёмки и скилл вливания |
SELFDEV_REVIEWER_PRINCIPAL в .env установки |
Кто решает review |
Исполнитель скиллов с taimen_selfdev.git_merge:run в skills.local и правом skills.execute |
Кто исполняет git.merge@1 (например кодовый агент пакета) |
| Токен forge с правом записи в целевую ветку у исполнителя скиллов | Скилл пушит результат вливания |
У ревьюера — skills.invoke и tasks.write на задаче |
Вливание идёт его полномочиями |
Пакет notify |
Уведомление ревьюеру о запросе решения |
Прежняя схема ревью
Отдельный тип задачи ревью, который заводил демон исполнителя после успешного
прогона (переменные CONTROL_PLANE_AGENT_REVIEW*, раздел
workingCopy.review описания агента), и задачи «правки по ревью» из исхода
approval в поставке больше не используются: демон такие задачи не заводит, а
раздел workingCopy.review игнорирует с предупреждением в журнале. Открытые
задачи прежнего типа ревью доводятся исходами approval их типа; после этого
выведите тип из оборота (retire.TaskType файла установки).
Типичные проблемы¶
| Симптом | Причина | Что делать |
|---|---|---|
Задача сразу done, ревью не запрошено |
Нет опубликованного коммита: published: false или изменений не было — критерии skipped |
Проверить журнал демона (публикация ветки) и артефакт commit |
Критерий review провален no_approver |
Нет человека, у которого запросить решение | Задать SELFDEV_REVIEWER_PRINCIPAL (UUID человека) и опубликовать тип заново |
merge провален no_decision |
Решение не прошло в этой попытке | Проверить, что review одобрен именно в текущей попытке |
merge провален с кодом прав |
У ревьюера нет skills.invoke / tasks.write или прав скилла |
Выдать права связке ревьюера |
merge не выполняется долго, затем no_result |
Скилл никто не исполняет: нет исполнителя скиллов с git_merge:run |
Проверить описание исполнителя скиллов и его фактическое состояние |
| Зависимая задача не берётся | Предшественник на приёмке (verification_pending) |
Решить ревью |
Задача в blocked после трёх отказов |
Лимит попыток | Разобраться и вернуть задачу в работу вручную |
См. также¶
- Типы задач и статусы — приёмка типа.
- Цели, приёмка и evidence — стадия проверки.
- Рабочие копии — ветка задачи и публикация.
- Агенты описанием — исполнитель и скиллы агента.
- Approvals
- Повседневные сценарии