Uruchom ograniczoną pętlę review-fix dla PR
ENOgraniczona pętla review-fix dla pull requestu to workflow agenta, który czyta nowe komentarze z review i nieudane checki CI, klasyfikuje każdą uwagę, odtwarza te wymagające działania, nakłada najmniejszą poprawkę w zatwierdzonym zakresie, ponawia wymagane bramki i zatrzymuje się przed imiennie wskazanym człowiekiem. Kluczowe jest ograniczenie: rejestr, limit prób i jawne warunki stopu.
Pytanie scorecardu (Q19): Jak rozwiązywane są uwagi z review i nieudane checki CI na pull requestach?
Odpowiedź za maksimum punktów: Ograniczona pętla triaguje nowe uwagi, naprawia potwierdzone przyczyny, ponawia wymagane checki i kończy pracę gotowa do akceptacji przez imiennie wskazanego człowieka.
Ta strona jest dla deweloperów odpowiedzialnych za pull requesty pisane przez agentów oraz dla tech leadów, którzy ustalają reguły działania takich pętli. Twój PR ma 11 komentarzy od bota review i dwóch kolegów, job integracyjny jest czerwony, a połowa uwag dotyczy kodu, który ostatni push już zmienił. Kopiowanie każdego komentarza do czatu działa przy jednym PR. Nie przetrwa tygodnia takich PR-ów, a nieograniczona pętla @bot fix this chętnie przepisze test, aż ten przejdzie.
Co daje ograniczona pętla review-fix
Dział zatytułowany „Co daje ograniczona pętla review-fix”- Plik rejestru, który zapisuje każdą uwagę, jej klasę, commit (head), względem którego ją sprawdzono, i sposób rozwiązania.
- Skrypt snapshotu, który zbiera nierozwiązane wątki review i wymagane checki przez GitHub CLI (
gh). - Trzy prompty do skopiowania: triaż, poprawka i raport końcowy.
- Wywołania headless dla Claude Code i Codex oraz odpowiednik w Cursorze.
- Sposób sprawdzenia wyniku pętli na podstawie dowodów, bez ponownego czytania całego diffa.
Co pętla robi w jednym przebiegu?
Dział zatytułowany „Co pętla robi w jednym przebiegu?”Jeden przebieg obsługuje każdą nową uwagę raz, a potem się zatrzymuje. Pętla nigdy sama nie zaczyna nowego projektu rozwiązania; uwaga, która go wymaga, wraca do planowania.
snapshot (head SHA, wątki, checki) → klasyfikuj każdą nową uwagę → odtwórz defekty do naprawy → popraw w zatwierdzonym zakresie → ponów bramki dotknięte zmianą + wymagane → jedna odpowiedź na uwagę, aktualizacja rejestru → stop: wszystko czyste | potrzebna decyzja człowieka | limit próbStan pętli żyje w pliku w kopii roboczej gałęzi PR, a nie w pamięci agenta. Nie commituj go (dodaj .pr-loop/ do .gitignore), a jego podsumowanie wklej do PR:
{ "pr": 412, "base_sha": "9c1e4d2", "items": [ { "id": "thread:PRRT_kwDOA1b2c3", "source": "review-thread", "checked_at_sha": "4f7a0b1", "class": "defect", "repro": "npm test -- tests/billing/proration.test.ts", "status": "fixed", "attempts": 1, "fix_sha": "a81c9e0" }, { "id": "check:integration", "source": "required-check", "checked_at_sha": "4f7a0b1", "class": "needs-human", "reason": "Fix requires a schema migration, outside plan.md", "status": "escalated", "attempts": 0 } ]}Całą pracę wykonują trzy pola. Stabilne id (node ID wątku review albo nazwa checka) chroni przed dwukrotną odpowiedzią na ten sam komentarz. checked_at_sha oznacza uwagi jako nieaktualne, gdy nowszy push zmienił cytowany kod. attempts egzekwuje limit dla każdej uwagi osobno, więc jeden uparty błąd nie zużyje całego budżetu.
Co agent może zmieniać i kiedy musi się zatrzymać?
Dział zatytułowany „Co agent może zmieniać i kiedy musi się zatrzymać?”Wpisz tę tabelę do AGENTS.md albo CLAUDE.md, żeby pętla czytała ją w każdym przebiegu.
| Agent może | Agent musi się zatrzymać i zapytać, gdy |
|---|---|
| Czytać nierozwiązane wątki, wyniki checków i logi nieudanych jobów | Uwaga jest sprzeczna z intent.md, spec.md lub plan.md |
| Odtworzyć zgłoszony błąd lokalnie | Błędu nie da się odtworzyć z dostępnych dowodów |
Edytować pliki w zakresie zatwierdzonym przez plan.md | Poprawka wymaga migracji, nowej zależności, dostępu do produkcji lub plików spoza zakresu |
| Ponawiać udokumentowane komendy testów i lintera | Ta sama uwaga nie przechodzi po trzech próbach |
| Odpowiedzieć w wątku z dowodem poprawki | Reviewer prosi o decyzję produktową, bezpieczeństwa, prawną lub architektoniczną |
| Pushować na gałąź PR | Cokolwiek innego: merge, deploy i zmiana ochrony gałęzi nigdy nie są w zakresie |
Chroniona gałąź, wymagane review i akceptacja release’u pozostają poza pętlą. Zielony check to dowód dla reviewera, a nie zgoda na merge.
Uruchom jeden przebieg pętli
Dział zatytułowany „Uruchom jeden przebieg pętli”-
Otwórz draft pull requestu, gdy lokalne bramki przejdą. Podlinkuj
intent.md,spec.mdiplan.md(łańcuch artefaktów) i dołącz dowody z testów. Strona o pakiecie dowodów definiuje, co musi zawierać opis takiego PR. -
Czekaj na wyniki zamiast odpytywać w pętli.
gh pr checks 412 --watch --requiredblokuje do zakończenia wymaganych checków. Review pojawiają się, gdy ludzie lub boty je opublikują, więc uruchamiaj przebieg po złożeniu review, a nie według zegara. -
Zrób snapshot. Zapisz poniższy skrypt jako
scripts/pr-loop-snapshot.shi uruchom go z gałęzi PR. Zapisuje head commit, nierozwiązane wątki review i wymagane checki dla tego przebiegu:#!/usr/bin/env bashset -euo pipefailPR="${1:?usage: pr-loop-snapshot.sh PR_NUMBER}"OUT=".pr-loop/pass-$(date +%Y%m%dT%H%M%S)"mkdir -p "$OUT"gh pr view "$PR" --json headRefOid,url,reviews,comments > "$OUT/pr.json"# gh exits 1 when a check failed and 8 while checks are pending; keep the snapshot either waygh pr checks "$PR" --required --json name,bucket,link,workflow > "$OUT/checks.json" || truegh api graphql -F owner='{owner}' -F repo='{repo}' -F pr="$PR" -f query='query($owner: String!, $repo: String!, $pr: Int!) {repository(owner: $owner, name: $repo) {pullRequest(number: $pr) {# first 100 threads only; paginate with pageInfo/endCursor for morereviewThreads(first: 100) {nodes { id isResolved isOutdated path linecomments(first: 20) { nodes { author { login } body } } }}}}}' > "$OUT/threads.json"echo "$OUT"isOutdatedto informacja od GitHuba, że cytowane linie zmieniły się od czasu komentarza. Zapytanie czyta najwyżej 100 wątków; PR z większą liczbą wymagapageInfo { hasNextPage endCursor }, zmiennej$endCursor: Stringprzekazanej jakoafter:orazgh api graphql --paginate, inaczej reszta wątków po cichu przepada. Polebucketgrupuje stany checków wpass,fail,pending,skippingicancel. -
Klasyfikuj przed edycją. Uruchom na snapshocie prompt triażu z sekcji niżej. Każda uwaga dostaje dokładnie jedną klasę:
defect,question,duplicate,stale,notelubneeds-human. Dalej idą tylko uwagidefect. -
Odtwórz każdy defekt. Agent pisze najwęższą komendę, która kończy się błędem z powodu zgłoszonej przyczyny, na przykład jeden plik testów albo jedną regułę lintera, i zapisuje ją w polu
reprorejestru. Uwaga, której nie da się odtworzyć, staje sięneeds-human, a nie spekulatywnym patchem. -
Nałóż najmniejszą poprawkę w zakresie. Jeden commit na uwagę, z jej
idw komunikacie commita. Poprawka nigdy nie edytuje testu, żeby przeszedł, nie obniża progu pokrycia i nie dodaje wyciszenia lintera. -
Ponów bramki na nowym head. Najpierw komenda
repro, która teraz musi przejść, potem każda wymagana bramka repozytorium. Zapisz w rejestrze komendę, kod wyjścia i nowy head SHA. -
Odpowiedz raz i się zatrzymaj. Opublikuj jedną odpowiedź na każdy naprawiony wątek, z commitem i przechodzącą komendą. Rozwiązanie wątków zostaw reviewerowi. Zakończ przebieg raportem końcowym, a kolejny uruchom dopiero po nowych uwagach.
Prompty do triażu, poprawek i raportu końcowego
Dział zatytułowany „Prompty do triażu, poprawek i raportu końcowego”Zamień npm run lint i npm test na udokumentowane bramki swojego repozytorium. Prompty zakładają, że rejestr leży w .pr-loop/ledger.json. Zapisz trzy prompty jako .pr-loop/prompts/triage.txt, fix.txt i report.txt; poniższe komendy czytają je stamtąd.
Uruchom pętlę w Claude Code, Codex lub Cursorze
Dział zatytułowany „Uruchom pętlę w Claude Code, Codex lub Cursorze”Kontrakt pętli, rejestr i prompty są takie same w każdym narzędziu. Różni się sposób uruchomienia przebiegu bez nadzoru i bot review, który dostarcza uwagi.
Uruchom przebieg headless z gałęzi PR. claude -p startuje w trybie uprawnień Manual (od v2.1.285 w trybie auto u zewnętrznych dostawców lub z wyłączoną telemetrią), więc nazwij tryb i dozwolone narzędzia jawnie, a do tego ogranicz wydatki:
SNAP=$(scripts/pr-loop-snapshot.sh 412)[ -f .pr-loop/ledger.json ] || echo '{"items":[]}' > .pr-loop/ledger.json
# Triage: no Bash, so no commits and no test runs; it may write only filesclaude -p "$(cat .pr-loop/prompts/triage.txt)" \ --permission-mode manual \ --allowedTools "Read,Grep,Glob,Edit,Write" \ --max-budget-usd 2 \ --output-format json > "$SNAP/triage.json"test -z "$(git status --porcelain -- . ':!.pr-loop')" || { echo "triage edited source files; stop" >&2; false; }
# Fix: runs only after you have read the ledger diffclaude -p "$(cat .pr-loop/prompts/fix.txt)" \ --permission-mode acceptEdits \ --allowedTools "Read,Grep,Glob,Edit,Bash(npm test *),Bash(npm run lint),Bash(gh run view *),Bash(git add *),Bash(git commit *)" \ --max-budget-usd 5 \ --output-format json > "$SNAP/result.json"Zacznij od czystego drzewa roboczego. Linia z rejestrem tworzy pusty rejestr przy pierwszym przebiegu. Triaż nie dostaje Bash, więc nie uruchomi testów ani nie zrobi commita; nadal może zapisywać pliki, bo musi zaktualizować rejestr, i dlatego tryb plan nie pasuje do tego kroku. Właściwym zabezpieczeniem jest linia z git status: zgłasza błąd, jeśli triaż zmienił cokolwiek poza .pr-loop/. Przeczytaj diff rejestru, zanim uruchomisz przebieg naprawczy. git push celowo nie ma na liście dozwolonych narzędzi, więc pushujesz sam, po przeczytaniu raportu końcowego. Przed pierwszym pushem /code-review w sesji interaktywnej wykonuje lokalny przegląd.
Na GitHubie anthropics/claude-code-action@v1 odpowiada na komentarz z frazą wyzwalającą (domyślnie @claude). Domyślnie ignoruje autorów komentarzy bez prawa zapisu; w jobie, który może pushować, zostaw allowed_non_write_users nieustawione. Przewodnik CI/CD dla Claude Code opisuje plik workflow. Zarządzany Code Review (Team i Enterprise, research preview) publikuje uwagi jako komentarze inline, a jego check run Claude Code Review zawsze kończy się wynikiem neutral, więc nigdy nie zatwierdza ani nie blokuje PR. Traktuj jego komentarze jako kolejne wejście tej pętli, a nie jej zamiennik. Odpowiedź na jego komentarz nie wywołuje reakcji. Jeśli repozytorium uruchamia review po każdym pushu (@claude review always), kolejny przebieg rozwiązuje wątek, gdy problem zniknie; w przeciwnym razie skomentuj @claude review.
Uruchom przebieg przez codex exec. Profil uprawnień :workspace (beta) pozwala Codexowi pisać tylko w checkoucie, a --output-schema wymusza raport końcowy, który da się sparsować. Najpierw zapisz ten minimalny schemat jako .pr-loop/report.schema.json:
{ "type": "object", "additionalProperties": false, "required": ["head_sha", "items", "verdict"], "properties": { "head_sha": { "type": "string" }, "items": { "type": "array", "items": { "type": "object", "additionalProperties": false, "required": ["id", "class", "status", "repro", "fix_sha"], "properties": { "id": { "type": "string" }, "class": { "type": "string", "enum": ["defect", "question", "duplicate", "stale", "note", "needs-human"] }, "status": { "type": "string" }, "repro": { "type": ["string", "null"] }, "fix_sha": { "type": ["string", "null"] } } } }, "verdict": { "type": "string" } }}Następnie uruchom przebieg:
SNAP=$(scripts/pr-loop-snapshot.sh 412)[ -f .pr-loop/ledger.json ] || echo '{"items":[]}' > .pr-loop/ledger.json
# Triage first; read the ledger diff before the fix passcodex exec -c default_permissions=":workspace" \ -o "$SNAP/triage.md" \ "$(cat .pr-loop/prompts/triage.txt)"test -z "$(git status --porcelain -- . ':!.pr-loop')" || { echo "triage edited source files; stop" >&2; false; }
cat .pr-loop/ledger.json | codex exec \ -c default_permissions=":workspace" \ --output-schema .pr-loop/report.schema.json \ -o "$SNAP/report.json" \ "$(cat .pr-loop/prompts/fix.txt)"W Codex CLI 0.157.1 profil :workspace montuje .git tylko do odczytu, więc krok 4 promptu naprawczego nie może zrobić commita: przebieg edytuje pliki i pisze raport, a fix_sha zostaje null. Po przeczytaniu raportu zrób commity sam, jeden na każdy id uwagi, i uzupełnij fix_sha. Triaż także działa w profilu :workspace, bo zapisuje rejestr; :read-only zablokowałby ten zapis. Linia z git status po nim zgłasza błąd, jeśli triaż dotknął czegokolwiek poza .pr-loop/. Dane z potoku (stdin) są dołączane do promptu jako blok <stdin>. Przed pushem codex review --base main wykonuje drugi, niezależny przegląd gałęzi względem main. W Codex CLI 0.157.1 flagi --base nie da się połączyć z własnymi instrukcjami przeglądu (CLI odrzuca tę parę), więc wskazówki dla przeglądu trzymaj w AGENTS.md.
Dla czerwonego CI po pushach na własne gałęzie przewodnik CI/CD dla Codex pokazuje openai/codex-action@v1 rozbite na wyzwalacz tylko do odczytu, job, który może pisać wyłącznie w checkoucie, i job otwierający draft PR. Stosuj ten podział zamiast dawać jednemu jobowi jednocześnie sekret i prawo pushowania.
Bugbot przegląda pull requesty i publikuje uwagi; traktuj jego komentarze jako kolejne źródło w snapshocie. Prompty triażu i poprawek uruchamiaj w agencie Cursora na gałęzi PR: najpierw uruchom prompt triażu i przejrzyj rejestr, zanim pozwolisz na jakiekolwiek edycje. Do przebiegu bez nadzoru służy tryb print (-p) w Cursor CLI, który uruchamia te same prompty headless.
Funkcje Bugbot oraz PR Routing & Approval w Cursorze zweryfikowaliśmy ostatnio 2026-08-28; zanim włączysz prawo zapisu dla jakiejkolwiek automatycznej poprawki, sprawdź aktualną konfigurację na stronie o Bugbocie.
Jeśli agent ma czytać stan PR przez połączenie narzędziowe zamiast gh, serwer GitHub MCP udostępnia pull requesty i logi Actions, a jego URL przyjmuje sufiks /readonly dla każdego zestawu narzędzi. W Claude Code dodaje go claude mcp add --transport http github https://api.githubcopilot.com/mcp/ -H "Authorization: Bearer $GITHUB_PAT_TOKEN"; powłoka podstawia token w chwili uruchomienia komendy. W Codex codex mcp add github --url https://api.githubcopilot.com/mcp/ --bearer-token-env-var GITHUB_PAT_TOKEN trzyma token w zmiennej środowiskowej. CLI gh zużywa mniej tokenów przy tych samych odczytach.
Jak sprawdzić wynik pętli bez czytania całego diffa?
Dział zatytułowany „Jak sprawdzić wynik pętli bez czytania całego diffa?”Weryfikuj przebieg na podstawie jego dowodów, a kod czytaj tylko tam, gdzie wskazują dowody.
-
Każda poprawka ma stan „przed” i „po”. Każda uwaga
fixedwskazuje komendęrepro. Uruchom sam jedną lub dwie na rodzicu commita z poprawką i na head: najpierw musi zakończyć się błędem, a potem przejść. -
Wymagane checki są zielone na head wskazanym w raporcie. Porównaj SHA z raportu z
gh pr view 412 --json headRefOid. Raport o starszym SHA jest nieaktualny. -
Nic nie wyszło poza zatwierdzony zakres. Wypisz pliki zmienione przez commity pętli i porównaj je z
plan.md:Okno terminala git log --format=%H --grep='^fix(review):' origin/main..HEAD \| xargs -r git show --name-only --format= | sort -uKażdą ścieżkę spoza zakresu planu, każdy plik testów i każdą konfigurację CI z tej listy czytasz linia po linii.
-
Wyrocznia się nie przesunęła. Poprawka, która dotknęła testu, snapshotu lub progu, z definicji jest
needs-human, nawet jeśli agent sklasyfikował ją jako defekt. -
Imiennie wskazany człowiek akceptuje. Pętla kończy się na READY FOR REVIEW. Reviewer zatwierdza, a release przechodzi przez bramkę akceptacji produkcyjnej.
Pełny protokół triażu, którym reviewer przechodzi PR napisany przez agenta, opisuje strona o review PR agenta bez czytania każdej linii.
Co psuje się w pętli review-fix i jak z tego wyjść?
Dział zatytułowany „Co psuje się w pętli review-fix i jak z tego wyjść?”Pętla odpowiada na ten sam komentarz w każdym przebiegu. Rejestr nie ma stabilnego id albo agent identyfikuje uwagi po treści komentarza. Naprawa: kluczuj po node ID wątku lub nazwie checka, usuń zduplikowane odpowiedzi i ponów triaż na aktualnym rejestrze.
Poprawka celuje w kod, który poprzedni push już zmienił. Uwagę sprawdzono względem starszego head. Naprawa: oznacz jako stale uwagi, których checked_at_sha różni się od bieżącego headRefOid, zrób nowy snapshot i ponów triaż.
Niestabilny (flaky) test zostaje „naprawiony”. Repro przeszło za pierwszym razem, a agent i tak nałożył patch albo dodał retry. Naprawa: wymagaj, żeby repro zawiodło przed jakąkolwiek edycją, zrób revert commita i przekaż test właścicielowi niestabilnych testów jako needs-human.
Checki są czerwone po trzech próbach. Przyczyna leży poza zakresem, który dostał agent, albo środowisko różni się od CI. Naprawa: zatrzymaj tę uwagę, dołącz ostatni log błędu (gh run view RUN_ID --log-failed) i eskaluj. Nie podnoś limitu prób dla tej uwagi.
Patch odpływa od planu. Kontrola zakresu pokazuje pliki spoza plan.md albo poprawka wprowadza nową abstrakcję. Naprawa: zrób revert commita i odeślij uwagę do planowania. Komentarz z review, który wymaga zmiany projektu, to nowy plan, a nie poprawka.
Zielone checki uruchamiają merge lub deploy. Ktoś podpiął auto-merge pod wynik pętli. Naprawa: usuń auto-merge z workflow pętli, trzymaj merge za ochroną gałęzi i wymaganym review człowieka, a rollback traktuj jako siatkę bezpieczeństwa.
Lista kontrolna pętli review-fix gotowej na Q19
Dział zatytułowany „Lista kontrolna pętli review-fix gotowej na Q19”- Każda przetworzona uwaga ma stabilne
id, jedną klasę i head SHA, względem którego ją sprawdzono. - Każdy naprawiony defekt ma komendę repro, która zawiodła przed poprawką i przechodzi po niej.
- Poprawki mieszczą się w zakresie
plan.mdi nigdy nie osłabiają testu, progu ani reguły lintera. - Wymagane checki przeszły na head SHA wskazanym w raporcie końcowym.
- Każda uwaga ma limit prób, a pętla zatrzymuje się z raportem zamiast ponawiać bez końca.
- Pętla nie może zrobić merge ani deployu, a akceptuje imiennie wskazany człowiek.
Dokąd dalej: review PR i release
Dział zatytułowany „Dokąd dalej: review PR i release”Pętla przyjmuje uwagi z warstwowego review PR i przekazuje czysty PR do bramki release’u. Klucz odpowiedzi dla dewelopera przypisuje każde pytanie scorecardu do jego strony.