Przejdź do głównej zawartości

Operacje masowe w Codex: jedna zmiana w wielu pakietach

Operacja masowa w Codex wprowadza jedną, dobrze zdefiniowaną zmianę, na przykład wymianę biblioteki logowania, w wielu pakietach lub repozytoriach. Codemod załatwia mechaniczną większość, jedna partycja pilotażowa sprawdza przepis, a resztę obsługują równoległe uruchomienia codex exec w osobnych worktree Git. Każda partycja przechodzi tę samą skryptową bramkę przed scaleniem.

Twój zespół przyjął @acme/logger, a old-logger wciąż jest importowany w 47 plikach w 12 pakietach. Zamiana regexem radzi sobie z prostymi importami i psuje całą resztę: własne transporty, instancje loggera przekazywane przez konstruktory i testy, które sprawdzają treść logów. Jedna sesja Codex przechodząca przez wszystkie 12 pakietów wyczerpuje kontekst w połowie. Dwanaście sesji bez nadzoru daje dwanaście różnych interpretacji słowa „migruj”. Ta strona jest dla programisty, który prowadzi migrację, i dla tech leada, który musi zatwierdzić 12 pull requestów bez czytania każdej ich linii.

  • Regułę decyzyjną: kiedy zmiana jest operacją masową, kiedy zestawem równoległych torów funkcjonalnych, a kiedy zwykłym codemodem.
  • Plik przepisu i manifest partycji, dzięki którym każdy agent wprowadza tę samą zmianę w ten sam sposób.
  • Skrypt uruchamiający jednego agenta codex exec na partycję, każdego we własnym worktree i na własnej gałęzi, z limitem współbieżności.
  • Ścisły raport JSON dla każdej partycji i skrypt bramki, który dowodzi poprawności partycji bez czytania jej diffu.
  • Cztery prompty do skopiowania: przepis, wykonawca partycji, recenzent i naprawa po odrzuceniu przez bramkę.

Polecenia i flagi na tej stronie sprawdzono 2026-09-26 w Codex CLI 0.157.1 (codex --help, codex exec --help, codex cloud exec --help).

Twoja zmiana to operacja masowa, zestaw torów czy codemod?

Dział zatytułowany „Twoja zmiana to operacja masowa, zestaw torów czy codemod?”

Operacja masowa to jeden przepis zastosowany w wielu miejscach. To coś innego niż równoległa praca nad funkcjami opisana w przepływach wieloagentowych w Codex, gdzie każdy tor buduje coś innego. To rozróżnienie decyduje o sposobie weryfikacji: w operacji masowej każda partycja musi spełnić ten sam niezmiennik, więc jedna bramka sprawdza wszystkie.

ZmianaUżyjDlaczego
Czysto składniowa (zmiana nazwy importu, funkcji, opcji)Sam codemod, np. ast-grepDeterministyczny, przeglądasz go jako jedną regułę, nie kosztuje czasu agenta
Jeden przepis, ale każde miejsce wymaga oceny (sygnatury wywołań, konfiguracja, testy)Operacja masowa w Codex (ta strona)Codemod robi większość, agenci obsługują długi ogon wszędzie tak samo
Kilka różnych funkcji we wspólnej bazie koduRównoległe toryKażdy tor potrzebuje własnego planu i własnej definicji „gotowe”
Mniej niż około pięć plikówJedna sesja CodexPodział na partycje kosztuje więcej, niż oszczędza
  1. Utwórz gałąź integracyjną i napisz przepis. Odgałęź się od main jako chore/logger-migration. Uruchom prompt przepisu poniżej w zwykłej sesji Codex: agent bada, jak baza kodu używa old-logger, i zapisuje docs/migrations/logger.md, zbiór reguł „przed i po” z jedną implementacją wzorcową. Przeczytaj i popraw ten plik. To jedyny artefakt, którego słucha każdy agent, więc tu najlepiej wydać czas na przegląd. Potem zrób commit docs/migrations/logger.md na gałęzi chore/logger-migration: skrypt tworzy każdy worktree z tej gałęzi, więc worktree widzą tylko pliki z commitów.

  2. Wprowadź wszystko, co wspólne, przed równoległym uruchomieniem partycji. Dodaj @acme/logger do package.json każdego pakietu i zaktualizuj lockfile w jednym commicie na gałęzi integracyjnej. Zainstaluj zależności, zanim ruszy którykolwiek agent, żeby żadna partycja nie zależała od tego, czy agent ma dostęp do sieci. Agenci nie mogą też dotykać głównego lockfile’a: jeśli edytuje go dwunastu agentów, dostajesz dwanaście konfliktów.

  3. Napisz manifest partycji, zanim uruchomisz codemod. Wypisz po jednym pakiecie w wierszu w partitions.txt. Zbuduj go teraz, gdy każdy pakiet używający old-logger jeszcze go wymienia. Po codemodzie pakiet, którego jedynym odwołaniem był domyślny import, przestaje pasować, choć jego wywołania wciąż używają starego API:

    Okno terminala
    # uruchom w terminalu w katalogu głównym repozytorium, przed krokiem 4
    git grep -l old-logger -- packages/ ':!packages/*/package.json' | cut -d/ -f2 | sort -u > partitions.txt

    Ułóż wiersze od największego pakietu, żeby wolne partycje ruszyły najwcześniej.

  4. Uruchom codemod dla części mechanicznej. Zamień proste importy przez ast-grep (npm install -g @ast-grep/cli, wersja 0.45.3 w npm na 2026-09-26), a potem zrób commit:

    Okno terminala
    # uruchom w terminalu w katalogu głównym repozytorium
    ast-grep run -l ts -p "import \$X from 'old-logger'" -r "import \$X from '@acme/logger';" -U packages/

    Codemod zostawia każde miejsce, w którym stare API jest faktycznie wywoływane. Te miejsca to praca dla agentów, a codemod zmniejszył każdą partycję.

  5. Przeprowadź pilot na jednej partycji i przeczytaj cały jej diff. Uruchom skrypt poniżej dla jednej partycji, wybierając pakiet, który używa loggera na kilka sposobów. To jedyny diff, który czytasz linia po linii. Każdy znaleziony błąd staje się nową regułą w docs/migrations/logger.md, a nie uwagą dla jednego agenta. Po każdej zmianie przepisu zrób jej commit, a potem usuń worktree i gałąź pilota przed ponownym uruchomieniem (git worktree remove --force ../wt-logger-PARTITION, potem git branch -D batch/logger-PARTITION); skrypt nie użyje ponownie żadnego z nich. Powtarzaj, aż pilot przejdzie bramkę, a ty zgodzisz się z diffem.

  6. Uruchom pozostałe partycje równolegle. Uruchom skrypt na reszcie manifestu, bez wiersza pilota, z limitem trzech równoległych agentów. Każdy agent pracuje we własnym worktree na własnej gałęzi, więc nieudana partycja nigdy nie blokuje ani nie psuje innej.

  7. Przepuść każdą partycję przez bramkę, potem scal. Uruchom skrypt bramki dla każdej partycji. Partycja, która nie przejdzie, wraca do agenta razem z wynikiem bramki; nie otwierasz jej diffu. Scalaj przechodzące gałęzie do chore/logger-migration pojedynczo przez git merge --no-ff, w kolejności z manifestu, żeby każda partycja została jednym commitem scalającym, który da się cofnąć.

  8. Uruchom globalną bramkę i dokończ sekwencyjnie. Po ostatnim scaleniu uruchom raz pełne sprawdzenie typów, lint i zestaw testów oraz potwierdź niezmiennik w całym repozytorium. Potem usuń old-logger z każdego package.json i z lockfile’a w jednym końcowym commicie i otwórz jeden pull request z podsumowaniem dowodów z sekcji o bramce poniżej.

Uruchom partycje równolegle ze skryptu przez codex exec

Dział zatytułowany „Uruchom partycje równolegle ze skryptu przez codex exec”

Skrypt tworzy jeden worktree i jedną gałąź na partycję z gałęzi integracyjnej, instaluje zależności poza sandboksem agenta, uruchamia agenta ze ścisłym schematem wyjścia i commituje wynik. Zapisz go jako scripts/batch/run-one.sh i dodaj .codex-runs/ do .gitignore.

#!/usr/bin/env bash
# run-one.sh PARTYCJA: migruje jeden pakiet we własnym worktree i na własnej gałęzi
set -euo pipefail
p="$1"
base="${BASE:-chore/logger-migration}"
root=$(git rev-parse --show-toplevel)
runs="$root/.codex-runs"
wt="$root/../wt-logger-$p"
mkdir -p "$runs"
git worktree add -q -b "batch/logger-$p" "$wt" "$base"
(cd "$wt" && pnpm install --frozen-lockfile --silent) # zainstaluj przed uruchomieniem agenta; partycja nie może zależeć od dostępu agenta do sieci
sed "s|{{PARTITION}}|$p|g" "$root/prompts/logger-partition.md" |
codex exec -C "$wt" \
-c default_permissions=":workspace" \
--output-schema "$root/prompts/partition-report.schema.json" \
-o "$runs/$p.json" \
--json - > "$runs/$p.jsonl"
git -C "$wt" add -A
git -C "$wt" commit -q -m "chore(logger): migrate packages/$p (codex exec)" || echo "$p: no changes"

Raz nadaj skryptom prawo wykonywania, a potem uruchom skrypt z katalogu głównego repozytorium z limitem współbieżności:

Okno terminala
# uruchom w terminalu w katalogu głównym repozytorium, na gałęzi chore/logger-migration
chmod +x scripts/batch/*.sh
./scripts/batch/run-one.sh api # pilot (krok 5)
xargs -P 3 -n 1 ./scripts/batch/run-one.sh < partitions.txt # uruchomienie równoległe (krok 6)

Przed uruchomieniem równoległym usuń wiersz pilota z partitions.txt albo usuń jego worktree i gałąź, bo git worktree add -b odmawia utworzenia gałęzi, która już istnieje.

Cztery decyzje w tym skrypcie są celowe:

  • Jeden worktree na partycję, tworzony przez skrypt. Równolegli agenci w jednym checkoucie dzielą drzewo robocze, node_modules i cache buildów, a niedokończona edycja jednego agenta psuje testy drugiego. codex exec --worktree tworzy zarządzany worktree, ale operacja masowa potrzebuje nazwanej gałęzi dla każdej partycji i znanej ścieżki dla bramki, więc skrypt tworzy je sam. Przygotowanie i sprzątanie worktree opisuje strona izolowane zadania Codex w worktree Git.
  • -c default_permissions=":workspace" wybiera wbudowany profil uprawnień workspace, który OpenAI przedkłada nad starszą flagę --sandbox. Profile są w becie (Codex CLI 0.138.0 i nowsze), więc przypnij wersję CLI, której używa skrypt.
  • - czyta prompt ze stdin, więc jeden plik szablonu obsługuje każdą partycję, a zmienia się tylko {{PARTITION}}.
  • Commituje skrypt, nie agent. Wynik nie zależy od tego, czy sandbox może pisać do współdzielonego katalogu .git, a każda gałąź kończy się dokładnie jednym commitem, który możesz cofnąć.

Zapisz schemat raportu jako prompts/partition-report.schema.json. Codex waliduje końcową wiadomość w trybie ścisłym, więc każdy obiekt wymienia wszystkie swoje właściwości w required i ustawia additionalProperties na false:

{
"type": "object",
"properties": {
"status": { "type": "string", "enum": ["migrated", "partial", "needs_human"] },
"files_changed": { "type": "array", "items": { "type": "string" } },
"remaining_references": {
"type": "array",
"items": {
"type": "object",
"properties": {
"file": { "type": "string" },
"line": { "type": ["integer", "null"] },
"reason": { "type": "string" }
},
"required": ["file", "line", "reason"],
"additionalProperties": false
}
},
"decisions": { "type": "array", "items": { "type": "string" } },
"commands_run": { "type": "array", "items": { "type": "string" } }
},
"required": ["status", "files_changed", "remaining_references", "decisions", "commands_run"],
"additionalProperties": false
}

Najwięcej czasu przeglądu oszczędza pole decisions. Wymienia każdy wybór, którego agent dokonał poza przepisem, więc wiesz dokładnie, które partycje wymagają ludzkiego spojrzenia i jakiej reguły brakuje w przepisie.

Jak udowodnić poprawność partycji bez czytania każdego diffu?

Dział zatytułowany „Jak udowodnić poprawność partycji bez czytania każdego diffu?”

Każda partycja przechodzi sześć sprawdzeń, zanim spojrzy na nią człowiek, od najtańszego. Raport to deklaracja agenta; sprawdzenia od drugiego do szóstego testują ją sygnałami, których agent nie może sam wytworzyć. Zapisz skrypt jako scripts/batch/gate.sh i uruchom go raz dla każdej partycji:

#!/usr/bin/env bash
# gate.sh PARTYCJA: udowadnia poprawność jednej partycji bez czytania jej diffu
set -euo pipefail
p="$1"
base="${BASE:-chore/logger-migration}"
root=$(git rev-parse --show-toplevel)
report="$root/.codex-runs/$p.json"
cd "$root/../wt-logger-$p"
fail() { echo "FAIL $p: $*"; exit 1; }
# 1. Werdykt samego agenta. Schemat gwarantuje kształt, nie prawdziwość.
if [ -f "$report" ]; then
jq -e '.status == "migrated"' "$report" >/dev/null || fail "agent reported $(jq -r .status "$report")"
elif [ "${CLOUD:-0}" = 1 ]; then
echo "SKIP $p: no report (cloud partition), check 1 skipped"
else
fail "no report at $report"
fi
# 2. Żadnych zmian bez commita, nic poza partycją.
[ -z "$(git status --porcelain)" ] || fail "uncommitted changes"
stray=$(git diff --name-only "$base"...HEAD | grep -v "^packages/$p/" || true)
[ -z "$stray" ] || fail "files outside packages/$p: $stray"
# 3. Niezmiennik: w pakiecie nie został żaden import starej biblioteki.
# Codemod usunął już zwykłe importy, więc to łapie głównie require()
# i reeksporty; wywołania udowadnia sprawdzenie 6.
if git grep -n -E "from ['\"]old-logger['\"]|require\(['\"]old-logger['\"]\)" -- "packages/$p"; then
fail "old-logger is still imported"
fi
# 4. Bez osłabionych testów: mniej wierszy z asercjami niż wcześniej to sygnał alarmowy.
removed=$(git diff "$base"...HEAD -- "packages/$p" | grep -c '^-.*expect(' || true)
added=$(git diff "$base"...HEAD -- "packages/$p" | grep -c '^+.*expect(' || true)
[ "$removed" -le "$added" ] || fail "$removed assertion lines removed, $added added"
# 5. Budżet diffu: wymiana loggera jest mała, przepisanie kodu nie.
lines=$(git diff --numstat "$base"...HEAD | awk '{s+=$1+$2} END {print s+0}')
[ "$lines" -le "${MAX_LINES:-400}" ] || fail "$lines changed lines (budget ${MAX_LINES:-400})"
# 6. Uruchom ponownie bramki pakietu. Nigdy nie ufaj „testy przechodzą” w raporcie.
pnpm --filter "./packages/$p" run typecheck
pnpm --filter "./packages/$p" run lint
pnpm --filter "./packages/$p" run test
echo "PASS $p"

Samo sprawdzenie trzecie po codemodzie dowodzi niewiele: pakiet może importować @acme/logger i nadal wywoływać stare API. Niezmiennik podpierają sprawdzenie typów i testy ze sprawdzenia szóstego, bo wywołanie czegoś, czego nowa biblioteka nie eksportuje, się nie skompiluje.

2026-09-26 uruchomiliśmy skrypt i bramkę na testowym repozytorium z dwoma pakietami (z zaślepkami zamiast codex i pnpm): bramka odrzuciła partycję, która edytowała drugi pakiet, oraz taką, która zostawiła import, a przepuściła poprawioną.

Dla partycji, których raport zawiera decisions, dodaj recenzenta tylko do odczytu. W Codex CLI 0.157.1 codex exec review --base nie przyjmuje własnych instrukcji (the argument '--base <BRANCH>' cannot be used with '[PROMPT]', sprawdzone 2026-09-26), więc recenzent to zwykłe uruchomienie codex exec z profilem tylko do odczytu. Raport leży w ignorowanym przez Git katalogu .codex-runs/ głównego checkoutu, którego worktree recenzenta nie zawiera, więc polecenie dokleja decisions do promptu, zamiast wskazywać plik:

Okno terminala
# uruchom w terminalu w katalogu głównym repozytorium, dla jednej partycji
p=api
{ sed "s|{{PARTITION}}|$p|g" prompts/logger-review.md
jq -r '.decisions[] | "- " + .' ".codex-runs/$p.json"
} | codex exec -C "../wt-logger-$p" -c default_permissions=":read-only" \
-o "$PWD/.codex-runs/$p-review.md" -

Gdy każda partycja przejdzie bramkę, jedno polecenie zamienia raporty w tabelę dowodów do opisu pull requesta:

Okno terminala
jq -r '[input_filename, .status, (.files_changed | length), (.decisions | join("; "))] | @tsv' .codex-runs/*.json

Kto co zatwierdza. Tech lead zatwierdza przepis i diff pilota przed równoległym uruchomieniem partycji, a czyta diffy tylko tych partycji, które mają niepuste decisions albo uwagi recenzenta. Całą resztę zatwierdza bramka i globalne uruchomienie pełnego zestawu testów po ostatnim scaleniu. Na tym polega sens operacji masowej: ludzka uwaga idzie na reguły i wyjątki, a nie na 47 niemal identycznych plików.

Partycja, której build lub testy są za wolne na laptop, albo taka, która dwa razy nie powiodła się lokalnie, pasuje do zadania w chmurze. Najpierw wypchnij gałąź integracyjną, bo codex cloud exec działa na twojej bieżącej gałęzi, chyba że podasz --branch, a kontener pobiera kod z origin:

Okno terminala
# uruchom w terminalu w katalogu głównym repozytorium
git push -u origin chore/logger-migration
p=billing
codex cloud exec --env ENV_ID --branch chore/logger-migration --attempts 2 \
"$(sed "s|{{PARTITION}}|$p|g" prompts/logger-partition.md)"
codex cloud list --env ENV_ID # znajdź TASK_ID
git worktree add -b "batch/logger-$p" "../wt-logger-$p" chore/logger-migration
(cd "../wt-logger-$p" && codex cloud diff TASK_ID --attempt 1 && codex cloud apply TASK_ID --attempt 1)

ENV_ID to identyfikator lub etykieta twojego środowiska w chmurze, a TASK_ID to identyfikator, który wypisuje codex cloud exec. W wersji 0.157.1 codex cloud jest oznaczone jako eksperymentalne. Zadanie w chmurze nie ma --output-schema, więc nie powstaje plik raportu: zrób commit zastosowanego diffu samodzielnie poleceniami git -C "../wt-logger-$p" add -A i git -C "../wt-logger-$p" commit. Potem uruchom bramkę jako CLOUD=1 ./scripts/batch/gate.sh "$p". Z CLOUD=1 sprawdzenie pierwsze pomija brakujący raport i wypisuje SKIP, więc decydują sprawdzenia od drugiego do szóstego. Bez tej zmiennej brak raportu oznacza odrzucenie partycji, co wyłapuje lokalne uruchomienie, którego raport zginął. Konfigurację środowiska i to, kiedy opłaca się kilka prób (best-of-N), opisuje strona środowiska chmurowe Codex.

Przeprowadź tę samą operację w wielu repozytoriach

Dział zatytułowany „Przeprowadź tę samą operację w wielu repozytoriach”

Gdy partycjami są repozytoria, a nie pakiety, skrypt zmienia się w trzech miejscach: klonuje zamiast dodawać worktree, gałąź powstaje w każdym repozytorium, a sprawdzenie granic w bramce zamienia się w „żadnych plików poza src/ i test/” albo w to, co wasze repozytoria mają wspólnego. Trzymaj przepis w jednym miejscu i kopiuj go do każdego klonu przed uruchomieniem, żeby każde repozytorium dostało te same reguły:

#!/usr/bin/env bash
# run-one-repo.sh REPO_URL: wariant run-one.sh dla wielu repozytoriów
set -euo pipefail
repo="$1"; name=$(basename "$repo" .git); dir="$HOME/batch/$name"
recipe="${RECIPE:-$PWD/docs/migrations/logger.md}" # ścieżka bezwzględna, ustalona przed jakimkolwiek cd
git clone -q "$repo" "$dir"
git -C "$dir" switch -c chore/logger-migration
mkdir -p "$dir/docs/migrations" && cp "$recipe" "$dir/docs/migrations/"
(cd "$dir" && pnpm install --frozen-lockfile --silent)

Wywołanie codex exec i commit są takie same jak w run-one.sh, z -C "$dir". Otwieraj jeden pull request na repozytorium po przejściu jego bramki, żeby każdy zespół-właściciel sam przejrzał i scalił swoją zmianę.

Ustal współbieżność według tego, co jesteś w stanie przepuścić przez bramkę, a nie według tego, na co pozwala plan. Zacznij od trzech równoległych agentów; zwiększ liczbę dopiero wtedy, gdy pierwsza runda przejdzie bramkę bez poprawek. Przed dużym uruchomieniem sprawdź /usage w sesji interaktywnej, bo operacja masowa mnoży zużycie mniej więcej przez liczbę partycji. Limity planów i ich pięciogodzinne oraz tygodniowe okna opisuje strona zarządzanie kosztami Codex.

Codex domyślnie używa GPT-6 Astra. Stosuj regułę obowiązującą w całym serwisie: zostań przy modelu domyślnym, najpierw dostosuj poziom rozumowania (-c model_reasoning_effort="medium"), a model zmieniaj dopiero wtedy, gdy wskażą to twoje własne testy. Operacja masowa daje ci taki test za darmo. Uruchom ponownie partycję pilotażową z -m gpt-6-sol lub -m gpt-6-luna i ustaw ten sam poziom -c model_reasoning_effort=... zarówno dla przebiegu na Astrze, jak i dla przebiegu porównawczego: w Codex Astra domyślnie działa z poziomem low, a Sol i Luna z medium, więc porównanie na ustawieniach domyślnych mierzy naraz model i poziom rozumowania. Jeśli tańszy model przejdzie tę samą bramkę z tymi samymi decisions, użyj go dla pozostałych partycji. Aktualne modele i ceny Codex znajdziesz w przeglądzie modeli.

ObjawPrzyczynaWyjście z sytuacji
Partycje rozwiązują ten sam przypadek różniePrzepis go nie obejmowałDopisz regułę do docs/migrations/logger.md, potem uruchom ponownie tylko partycje, których decisions wspominają ten przypadek
Bramka: pliki poza partycjąAgent „naprawił” wspólny plik albo sąsiedni pakietUsuń worktree i gałąź (git worktree remove --force ../wt-logger-PARTITION && git branch -D batch/logger-PARTITION), potem uruchom ponownie run-one.sh; jeśli wspólna zmiana jest potrzebna, najpierw zrób jej commit na gałęzi integracyjnej
Wiele partycji zgłasza needs_human przy tym samym wzorcuWzorzec użycia, którego nie miał pilotZatrzymaj uruchomienie (Ctrl+C zatrzymuje xargs), rozszerz przepis, powtórz pilot na jednej z tych partycji
Konflikty w lockfile’u lub głównej konfiguracjiZmiany zależności zostawiono agentomPrzenieś je do wspólnego commita przed równoległym uruchomieniem (krok 2), potem zrób rebase gałęzi partycji
Bramka: usunięte linie asercjiAgent skasował test, którego nie umiał zmigrowaćOdeślij wynik bramki z promptem naprawczym poniżej; nigdy nie scalaj partycji, która straciła asercje
git worktree add się nie udaje: gałąź już istniejePoprzednie uruchomienie zostawiło gałąź i worktreegit worktree remove ../wt-logger-PARTITION, potem git branch -d batch/logger-PARTITION (-D dopiero po sprawdzeniu, że nie ma tam nic, czego potrzebujesz)
Laptop przestaje odpowiadaćTrzy instalacje i trzy zestawy testów narazZmniejsz -P albo przenieś najcięższe partycje do chmury
Globalny zestaw testów pada, choć wszystkie partycje przeszłyZachowanie między pakietami, np. wspólny format logów parsowany dalejCofaj scalenia partycji pojedynczo przez git revert -m 1 MERGE_SHA, aż testy przejdą; ostatnie cofnięte to winowajca

Zapisz poniższy prompt naprawczy jako prompts/logger-fix.md i renderuj go tym samym poleceniem sed co pozostałe szablony; polecenie dokleja wynik bramki. Przebieg naprawczy używa tych samych --output-schema i -o co run-one.sh, więc nadpisuje .codex-runs/$p.json świeżym raportem; bez tego sprawdzenie pierwsze czytałoby wciąż pierwotny werdykt partial lub needs_human i partycja nigdy by nie przeszła. Commit wyniku robisz sam przed ponownym przejściem przez bramkę:

Okno terminala
# uruchom w terminalu w katalogu głównym repozytorium, dla jednej odrzuconej partycji
p=api
{ sed "s|{{PARTITION}}|$p|g" prompts/logger-fix.md
./scripts/batch/gate.sh "$p" 2>&1 | tail -n 60
} | codex exec -C "../wt-logger-$p" -c default_permissions=":workspace" \
--output-schema "$PWD/prompts/partition-report.schema.json" \
-o "$PWD/.codex-runs/$p.json" -
git -C "../wt-logger-$p" add -A
git -C "../wt-logger-$p" commit -q -m "fix(logger): gate fixes for packages/$p"
./scripts/batch/gate.sh "$p"

Po ostatnim scaleniu posprzątaj: usuń każdy worktree partycji przez git worktree remove, skasuj scalone gałęzie przez git branch -d i uruchom git worktree prune.