diff --git a/.github/workflows/process.yml b/.github/workflows/process.yml index 6a615679..e6818e93 100644 --- a/.github/workflows/process.yml +++ b/.github/workflows/process.yml @@ -255,6 +255,10 @@ jobs: - name: Review id: review uses: anthropics/claude-code-action@v1 + env: + # Вне рабочей копии: восстановление дерева ревьюером не должно + # уничтожать его собственный артефакт (#220). + REVIEW_DOC: ${{ runner.temp }}/review-document.md with: # Подписка, а не отдельный счёт API: токен выпускается через # `claude setup-token` (Pro/Max). Действуют лимиты подписки. @@ -388,15 +392,25 @@ jobs: тип, приоритет, S1-new. «Оставили в тексте ревью» закрытием не считается и прямо запрещено §12. - Напиши полный документ ревью в файл - docs/reviews/-REVIEW-${{ github.event.issue.number }}-r${{ needs.guard.outputs.cycle }}.md + Напиши полный документ ревью в файл, путь которого лежит в + переменной окружения REVIEW_DOC (абсолютный, ВНЕ репозитория). + + Почему не в docs/reviews: документ там был некоммитнутым файлом того + же дерева, которое ты мутируешь, проверяя «умеет ли тест падать». На + #220 три раунда подряд документ исчезал — восстановление дерева + (`git checkout -- .`, `git clean -fd`) сносит собственный артефакт + ревью, потому что он untracked. В репозиторий его положит шаг + публикации, взяв из REVIEW_DOC; тебе трогать docs/reviews не нужно. + + В самом репозитории не создавай файлов вообще: любые изменения в + рабочей копии будут отброшены. (SPEC для этапа spec, CODE для code): скоуп, как проверялось, находки с воспроизведением, что проверено и корректно, чего не проверял. Для r2 и дальше добавь два раздела: «Закрытие раунда r» — таблица «находка | чем закрыта | где это видно», и «Унаследовано из r» — что принято без повторной проверки, с - документом и SHA. Каталог docs/reviews/ создай, если его нет. Больше не - пиши ничего: любой файл вне docs/reviews/ опубликован не будет. + документом и SHA. Файл пиши по пути из REVIEW_DOC — ничего другого + публиковать не нужно и не будет. Затем оставь в issue краткий комментарий: вердикт, ключевые находки и ссылка на документ. Первой строкой — вердикт в формате §7.2: @@ -419,6 +433,7 @@ jobs: NUM: ${{ github.event.issue.number }} STAGE: ${{ needs.guard.outputs.stage }} CYCLE: ${{ needs.guard.outputs.cycle }} + SOURCE: ${{ runner.temp }}/review-document.md run: | # Ветки задачи может не быть: у задач, размеченных до появления # конвейера, ТЗ лежит прямо в dev. Раньше шаг в этом случае молча @@ -432,8 +447,29 @@ jobs: marker=CODE-REVIEW if [ "$STAGE" = "spec" ]; then marker=SPEC-REVIEW; fi doc="docs/reviews/${marker}-${NUM}-r${CYCLE}.md" + # Рабочая копия отбрасывается ДО того, как документ попадёт в дерево: + # ревьюер правит код, проверяя «умеет ли тест падать», и его правки + # публиковаться не должны. git checkout -- . 2>/dev/null || true + # docs/reviews исключён из уборки: ревьюер мог написать документ по + # старому пути, и клин не должен его съесть до `git add` — ровно так + # оба пути остаются работоспособными. git clean -fd -e docs/reviews -e node_modules >/dev/null 2>&1 || true + # Документ приезжает извне репозитория (#220). Три раунда подряд он + # терялся, пока лежал некоммитнутым файлом в том же дереве, которое + # ревьюер мутирует и затем восстанавливает: `git checkout -- .` плюс + # `git clean -fd` сносят собственный артефакт ревью, потому что он + # untracked. Теперь его место — RUNNER_TEMP, и уборка дерева ему не + # страшна. + if [ -f "$SOURCE" ]; then + mkdir -p docs/reviews + cp "$SOURCE" "$doc" + echo "документ взят из $SOURCE ($(wc -c < "$doc") байт)" + else + # Совместимость: ревьюер мог написать по старому пути, если промпт + # ещё не обновился в этой ветке. + echo "::warning::$SOURCE не найден — ищу документ в рабочей копии" + fi git add docs/reviews 2>/dev/null || true if git diff --cached --quiet; then # Пустая рабочая копия — ещё не провал: ревьюер иногда коммитит @@ -449,7 +485,7 @@ jobs: # остались только комментариями, метки переставились, и пропажу # заметило лишь следующее ревью — issue #171. Падение ДО шага с # меткой сохраняет инвариант «метка не сменилась = прогон упал». - echo "::error::вердикт есть, а документа $doc нет ни в рабочей копии, ни в $target — ревью без артефакта (#171)" + echo "::error::вердикт есть, а документа нет: ни $SOURCE, ни $doc в рабочей копии, ни $doc в $target — ревью без артефакта (#171, #220)" exit 1 fi git -c user.name="claude[bot]" \