Polityka planowania: zaakceptowane artefakty przed ryzykownym wykonaniem
ENPolityka planowania dla agentów AI wymaga zaakceptowanych plików intent.md, spec.md i plan.md, zanim agent zmieni wrażliwy kod, taki jak auth, billing, migracje czy infrastruktura. Akceptacją jest merge zatwierdzony przez code ownera, a check CI blokuje każdy pull request, który bez niej dotyka chronionych ścieżek. Plan mode pomaga napisać plan, ale nie egzekwuje polityki.
Ta strona jest dla CTO, który odpowiada za pytanie 17 w CTO Scorecard, i dla tech leada, który ma to wdrożyć. Typowa sytuacja: zespół ustalił, że „ryzykowne zmiany zaczynają się od planu”, wszyscy używają Plan mode, a w zeszłym miesiącu agent i tak wypuścił migrację schematu, której planu nikt nie zatwierdził. Inżynier wyszedł z Plan mode po dwóch minutach, a reviewer zobaczył tylko diff.
Q17 · Wzmacnianie organizacji: Czy zmiany wrażliwe wymagają zaakceptowanych artefaktów intent, spec i plan przed wykonaniem?
Odpowiedź za maksymalną liczbę punktów: zaakceptowane intent, spec i plan są wymagane przed uzyskaniem prawa zapisu; hook lub CI weryfikuje artefakty, a nazwany approver kontroluje ryzykowne akcje.
Co daje ci ta polityka planowania
Dział zatytułowany „Co daje ci ta polityka planowania”- Tabelę wyzwalaczy, która rozstrzyga, które zmiany wymagają zaakceptowanego planu, po ścieżce i ryzyku, a nie po liczbie linii
- Plik polityki, który commitujesz bez zmian i dopasowujesz w jednym review
- Workflow „najpierw plan” dla Claude Code, Codex i Cursora, który tworzy trzy artefakty
- Przetestowany skrypt i workflow CI, które odrzucają pull request dotykający chronionych ścieżek bez zaakceptowanych artefaktów
- Trzy prompty do skopiowania: szkic planu, atak na plan i porównanie końcowego diffu z planem
- Test kontrolny bramki, który dowodzi, że bramka działa, bez czytania implementacji
Treść artefaktów pochodzi z szablonów łańcucha artefaktów, a sam etap opisuje strona etapu Plan. Ta strona dotyczy wyłącznie organizacyjnej bramki wokół nich.
Dlaczego Plan mode nie jest polityką planowania?
Dział zatytułowany „Dlaczego Plan mode nie jest polityką planowania?”Wszystkie trzy agenty potrafią planować przed edycją. Żaden nie zapisuje w twoim repozytorium, kto zaakceptował który plan, i każdy pozwala osobie przy klawiaturze przejść do wykonania. Właśnie tę lukę mierzy Q17.
| Narzędzie | Funkcja „najpierw plan” (sprawdzone 2026-09-26, chyba że zaznaczono) | Co egzekwuje | Czego nie udowodni |
|---|---|---|---|
| Claude Code 2.1.283 | Tryb uprawnień plan: odczyt i analiza, edycje zablokowane do zatwierdzenia planu. Wejście przez /plan, Shift+Tab lub claude --permission-mode plan | Brak edycji plików w sesji planowania | Że plan zaakceptował ktoś inny niż właściciel sesji. Od v2.1.283 większość sesji interaktywnych startuje w trybie auto, a nie w Plan mode, chyba że wybierzesz inaczej |
| Codex CLI 0.157.1 | /plan w sesji interaktywnej; starszy --sandbox read-only albo profil uprawnień :read-only (beta) dla dowolnego uruchomienia | Brak zapisów w trybie read-only | codex exec nie ma flagi planu (sprawdzone w codex exec --help, 0.157.1), więc uruchomienia bez nadzoru potrzebują sandboksa lub profilu uprawnień tylko do odczytu oraz bramki, a nie trybu |
| Cursor | Plan Mode „tworzy szczegółowe plany implementacji przed napisaniem jakiegokolwiek kodu” (dokumentacja Cursora, sprawdzone 2026-08-28) | Planowanie przed kodem w tej rozmowie | Akceptacji, tożsamości approvera ani powiązania planu ze scalonym diffem |
Dlatego polityka traktuje Plan mode jako narzędzie autorskie, a kontrolę przenosi tam, gdzie agent nie może jej przedefiniować: do gałęzi domyślnej, CODEOWNERS, ochrony gałęzi i wymaganego checka CI. To ten sam podział na radę i władzę, który polityka governance i autonomii stosuje do każdej kontroli agentów.
Które zmiany wymagają zaakceptowanego planu?
Dział zatytułowany „Które zmiany wymagają zaakceptowanego planu?”Wyzwalaczem jest to, co zmiana może zepsuć, a nie jej rozmiar. Trzy linie w sprawdzaniu tokenu są groźniejsze niż 400 linii zmian w tekstach. Zacznij od tej tabeli i przypisz każdemu wierszowi prawdziwe ścieżki w swoim repozytorium.
| Wyzwalacz | Przykładowe ścieżki | Dlaczego plan jest obowiązkowy | Nazwany approver |
|---|---|---|---|
| Migracja schematu lub danych | db/migrations/ | Trudna do cofnięcia; liczy się kolejność deployu i backfillu | Code owner platformy danych |
| Uwierzytelnianie, autoryzacja, sesje | src/auth/ | Zły default blokuje użytkowników albo wpuszcza niewłaściwych | Code owner bezpieczeństwa |
| Pieniądze: billing, cennik, uprawnienia do planów | src/billing/ | Ciche błędy kosztują przychód lub zwroty | Code owner płatności |
| Infrastruktura, CI i konfiguracja deployu | infra/, .github/ | Zmienia znaczenie „zielonego” i „wdrożonego” dla każdej innej zmiany | Code owner platformy |
| Publiczne kontrakty API | api/openapi.yaml | Integracje zewnętrznych klientów przestają działać, a żaden test tu nie zaświeci się na czerwono | Właściciel API |
| Przepływy danych wrażliwych | pliki, które czytają lub eksportują dane osobowe | Ekspozycja regulacyjna | Właściciel prywatności lub bezpieczeństwa |
Wszystko spoza tabeli idzie zwykłą ścieżką evidence bundle. Tabela wyznacza też, gdzie zaczyna się klasa ryzyka high: zmiana, która wymaga zaakceptowanego planu, prawie zawsze ma w bundle klasę high.
Prawo zapisu oznacza tu prawo zapisu do main: agent może szkicować zmianę na gałęzi, ale nic, co dotyka chronionej ścieżki, nie trafi do main bez zaakceptowanego planu.
Przyjmij plik polityki
Dział zatytułowany „Przyjmij plik polityki”Commituj politykę obok kodu, którym zarządza, żeby każda sesja agenta i każdy reviewer czytali ten sam tekst. Popraw ścieżki i zespoły, a potem scal plik przez to samo review code ownera, które opisuje.
# Plan gate policy
Owner: VP Engineering. Reviewed: quarterly. Version: 1.
## ScopeA change needs accepted artifacts when it touches a protected path:db/migrations/, src/auth/, src/billing/, infra/, .github/, api/openapi.yaml,scripts/check-plan-gate.sh.
## Accepted artifactsEach protected change has a directory changes/SLUG/ with intent.md, spec.mdand plan.md (templates: docs/templates/). The artifacts are accepted when a pullrequest that adds them is approved by the code owner of the affected area andmerged to main. Main is the only record of acceptance.
## ImplementationThe implementation pull request names its directory with a line"Change-Dir: changes/SLUG" in its description. It must not edit the acceptedartifacts. A material deviation (new file outside plan.md, changed data shape,changed rollout or rollback) stops the work: amend the plan in its own pullrequest first. A Change-Dir serves one implementation pull request, and everyprotected path that pull request touches must appear in the file list of plan.md.
## EnforcementThe plan-gate CI check is required on main. Code-owner review is required forchanges/, the protected paths, and the gate itself. Write access means writeaccess to main: agents may draft on a branch, but nothing that touches aprotected path reaches main without an accepted plan. Agents never hold mergerights or production credentials.
## ExceptionsEmergency fixes use the audited ruleset bypass, are named in the incidentrecord, and get a retroactive plan pull request within two business days.The platform team reports every bypass in the monthly engineering review.Plik zostaje po angielsku, bo czytają go agenty i narzędzia, a nazwy w nim muszą zgadzać się ze skryptem. Jeśli zespół pracuje po polsku, dodaj polską wersję obok, ale źródłem prawdy zostaw jeden plik.
Jak skonfigurować plan gate?
Dział zatytułowany „Jak skonfigurować plan gate?”Bramka ma trzy części: własność w CODEOWNERS, skrypt sprawdzający i wymagany workflow. Dodaj je w jednym pull requeście, scal go i dopiero wtedy oznacz check jako wymagany. Kolejność ma znaczenie, bo poniższy workflow uruchamia kopię skryptu, która już jest na gałęzi domyślnej.
-
Przypisz właścicieli. Dodaj katalog zmian, każdą chronioną ścieżkę i samą bramkę do
.github/CODEOWNERS. Potem włącz Require review from Code Owners w ochronie gałęzi lub rulesecie dlamain.# .github/CODEOWNERS/changes/ @acme/architecture/db/migrations/ @acme/data-platform/src/auth/ @acme/security/src/billing/ @acme/payments/infra/ @acme/platform/.github/ @acme/platform/api/openapi.yaml @acme/api/scripts/check-plan-gate.sh @acme/platformZastąp zespoły
@acme/...własnymi. Jeśli jedna grupa architektury jest zbyt ogólna dla/changes/, nadawaj katalogom zmian prefiks domeny, na przykładchanges/billing-SLUG/, i dodaj/changes/billing-*/ @acme/paymentspod linią/changes/. Wzorzec zakończony/obejmuje katalog i wszystko, co jest w nim zagnieżdżone, a w CODEOWNERS wygrywa ostatnia pasująca linia, więc linia domeny musi stać po ogólnej. -
Dodaj skrypt sprawdzający. Przepuszcza pull requesty, które nie dotykają chronionej ścieżki. Dla pozostałych wymaga linii
Change-Dir:, wymaga, żeby trzy artefakty były już na gałęzi bazowej, i odrzuca ich edycję w tym samym pull requeście.#!/usr/bin/env bash# scripts/check-plan-gate.sh: fail a PR that changes protected paths without accepted artifactsset -euo pipefailBASE="origin/${GITHUB_BASE_REF:?run on a pull_request event}"PROTECTED='^(db/migrations/|src/auth/|src/billing/|infra/|\.github/|api/openapi\.yaml$|scripts/check-plan-gate\.sh$)'changed="$(git diff --name-only "$BASE"...HEAD)"hits="$(grep -E "$PROTECTED" <<<"$changed" || true)"if [ -z "$hits" ]; thenecho "plan-gate: no protected paths changed"exit 0fiprintf 'plan-gate: protected paths changed:\n%s\n' "$hits"dir="$(printf '%s\n' "${PR_BODY:-}" | tr -d '\r' \| sed -nE 's#^Change-Dir:[[:space:]]*(changes/[A-Za-z0-9._-]+)/?[[:space:]]*$#\1#p' | head -n1)"if [ -z "$dir" ]; thenecho "::error::Add a line 'Change-Dir: changes/SLUG' to the PR description."exit 1fifor f in intent.md spec.md plan.md; doif ! git cat-file -e "$BASE:$dir/$f" 2>/dev/null; thenecho "::error::$dir/$f is not on $BASE. Merge the plan PR, approved by a code owner, first."exit 1fidoneif grep -q "^$dir/" <<<"$changed"; thenecho "::error::This PR edits the accepted artifacts in $dir. Amend them in a separate plan PR."exit 1fiecho "plan-gate: $dir accepted at $(git log -1 --format=%h "$BASE" -- "$dir")"Utrzymuj
PROTECTEDidentyczne z zakresem w pliku polityki. Ostatnia linia wypisuje commit, który zaakceptował plan, czyli wersję artefaktów, z którą związany jest pull request. -
Dodaj workflow. Uruchamia się ponownie po edycji opisu i wykonuje skrypt z gałęzi bazowej, więc sama edycja
scripts/check-plan-gate.shw pull requeście nie zmienia werdyktu dla tego samego pull requesta. Pull request, który edytuje także workflow, już może go zmienić; opisuje to akapit pod YAML-em..github/workflows/plan-gate.yml name: plan-gateon:pull_request:types: [opened, edited, synchronize, reopened]permissions:contents: readjobs:plan-gate:runs-on: ubuntu-lateststeps:- uses: actions/checkout@v7with:fetch-depth: 0persist-credentials: false- name: Require accepted intent, spec and plan for protected pathsrun: |git show "origin/${GITHUB_BASE_REF}:scripts/check-plan-gate.sh" > "$RUNNER_TEMP/check-plan-gate.sh"bash "$RUNNER_TEMP/check-plan-gate.sh"env:PR_BODY: ${{ github.event.pull_request.body }}Opis trafia do skryptu przez
env, a nie przez interpolację w liniirun, więc tekst w opisie pull requesta nie wstrzyknie poleceń powłoki. Skrypt jest najpierw zapisywany do pliku, więc jego brak przerywa krok. Przy przekazaniu potokiem dobashnieudanygit showdałby mu pusty strumień i krok by przeszedł, bo gdy krokrunnie podajeshell, GitHub uruchamia go bezpipefail.Sam plik workflow nie jest chroniony w ten sposób. Przy zdarzeniu
pull_requestGitHub uruchamia plik workflow z commita scalającego tego pull requesta, więc pull request może tak zmienićplan-gate.yml, żeby pominąć sprawdzenie i nadal świecić na zielono. Przed tym chroni linia/.github/wCODEOWNERSz kroku 1 razem z Require review from Code Owners: żadna zmiana workflow nie zostanie scalona bez zgody właściciela z zespołu platformy. Bez tej reguły przeglądu bramka ma charakter wyłącznie doradczy. -
Ustaw check jako wymagany. Spodziewaj się, że
plan-gatepadnie na samym pull requeście konfiguracyjnym, bo skryptu nie ma jeszcze namain. Dlatego check nie jest jeszcze wymagany. Od następnego pull requesta świeci na zielono. Po scaleniu pull requesta konfiguracyjnego dodajplan-gatejako wymagany status check namain. Prawo do merge’a zostaje przy ludziach; agenty otwierają pull requesty, ale nigdy ich nie scalają. -
Dziel każdą chronioną zmianę na dwa pull requesty. Pull request planu dodaje
changes/SLUG/i nic więcej, a zatwierdza go code owner. Pull request implementacji startuje po tym merge’u, zawieraChange-Dir: changes/SLUGi opisuje odchylenia od planu. -
Uruchom test kontrolny bramki z następnej sekcji, zanim ogłosisz politykę.
Twórz artefakty w każdym narzędziu
Dział zatytułowany „Twórz artefakty w każdym narzędziu”Pliki artefaktów i bramka są takie same dla każdego narzędzia. Różni się to, jak utrzymujesz agenta w trybie tylko do odczytu podczas planowania i jak plan trafia do changes/SLUG/.
Uruchom sesję planowania, która nie może edytować plików:
claude --permission-mode planW trwającej sesji użyj /plan albo przełączaj tryby przez Shift+Tab. Wklej prompt planowania poniżej, dopracuj plan, a potem go zatwierdź i poproś Claude Code, żeby zapisał tylko trzy pliki w changes/SLUG/ i otworzył pull request planu. Jeśli w repozytorium przeważa wrażliwa praca, ustaw planowanie jako domyślne: "permissions": { "defaultMode": "plan" } we wspólnym .claude/settings.json. Ustawienia projektu akceptują plan; ignorują auto i bypassPermissions.
W interaktywnym CLI uruchom /plan i wklej prompt planowania. Dla skryptowego szkicu tylko do odczytu zapisz ostatnią wiadomość do pliku i zacommituj go samodzielnie:
codex exec --sandbox read-only -o /tmp/plan-draft.md \ "Read changes/2026-09-sso/intent.md and spec.md. Draft plan.md following docs/templates/plan.md. Do not modify files."To starszy mechanizm --sandbox read-only, który codex exec nadal akceptuje w wersji 0.157.1. Blokuje zapisy przez całe uruchomienie, co daje mocniejszą gwarancję niż tryb, z którego sesja może wyjść. OpenAI preferuje teraz profile uprawnień (beta): codex exec -c default_permissions=":read-only" .... Używaj jednego albo drugiego, bo według OpenAI te dwa systemy się nie łączą. Skopiuj szkic do changes/2026-09-sso/plan.md i otwórz pull request planu.
Przełącz agenta w Plan Mode, zanim wkleisz prompt planowania. Przejrzyj i popraw plan w rozmowie, potem wróć do trybu Agent i poproś o zapisanie tylko trzech plików w changes/SLUG/, niczego więcej. Zapisem akceptacji jest pull request planu, a nie rozmowa.
Prompty do skopiowania dla plan gate
Dział zatytułowany „Prompty do skopiowania dla plan gate”Skąd wiesz, że plan gate działa?
Dział zatytułowany „Skąd wiesz, że plan gate działa?”Działanie bramki udowadniasz jej własnymi testami, a nie czytaniem kodu agenta. Uruchom te cztery testy raz przy wdrożeniu i ponownie po każdej zmianie zakresu lub workflow:
| Test | Jak go uruchomić | Oczekiwany wynik |
|---|---|---|
| Chroniona zmiana bez planu | Otwórz pull request w wersji roboczej (draft), który edytuje jeden plik w src/auth/ i nie ma linii Change-Dir: | plan-gate pada z błędem „Add a line” |
| Plan w tym samym pull requeście | Dodaj do tego pull requesta changes/test/ z trzema plikami i linię Change-Dir: | Pada: artefaktów nie ma jeszcze na main |
| Zaakceptowany plan | Usuń changes/test/ z draftu, scal te trzy pliki w osobnym pull requeście planu zatwierdzonym przez code ownera, potem zrób rebase draftu | Przechodzi i wypisuje commit akceptujący |
| Plan edytowany w trakcie implementacji | Zmień jedną linię w changes/test/plan.md w drafcie | Pada z komunikatem „Amend them in a separate plan PR” |
Potem zrób test świeżej sesji w każdym narzędziu, które wspiera twoja organizacja: otwórz nową sesję bez prywatnego kontekstu i zapytaj „What must happen before you edit db/migrations/?”. Poprawna odpowiedź cytuje docs/policies/plan-gate.md. Jeśli nie cytuje, odwołaj się do polityki we wspólnych regułach opisanych na stronie o wspólnych regułach agentów.
Jako bieżący dowód co miesiąc policz z logów CI: pull requesty dotykające chronionych ścieżek, ile przeszło bramkę za pierwszym razem i ile scalono przez bypass. Rosnąca liczba bypassów to wczesny sygnał, że zakres jest za szeroki albo review planów trwa za długo. Sam zapis akceptacji to scalony pull request planu z zatwierdzeniem code ownera przechowywanym przez GitHub.
Co się psuje, gdy egzekwujesz plan gate?
Dział zatytułowany „Co się psuje, gdy egzekwujesz plan gate?”Kolejka pull requestów planu staje się wąskim gardłem. Code ownerzy, którzy dostają długie plany, przestają je czytać. Naprawa: ogranicz plan.md do jednego ekranu plus listy plików, najpierw uruchom prompt „atak na plan” i dołącz jego tabelę, a w polityce zapisz oczekiwany czas odpowiedzi na review planu.
Zakres jest za szeroki, więc wszystko wymaga planu. Inżynierowie zaczynają pisać puste plany, żeby przejść dalej. Naprawa: usuń każdą ścieżkę, której dziesięć ostatnich zmian nie spowodowało incydentu ani rollbacku, i przenieś ją na zwykłą ścieżkę evidence bundle. Spodziewaj się tarcia na .github/ od pierwszego dnia, bo każda rutynowa edycja workflow, podbicie wersji akcji przez Dependabota lub Renovate i każda edycja CODEOWNERS wymaga wtedy Change-Dir: zawęź ten wpis w PROTECTED do .github/workflows/plan-gate.yml i .github/CODEOWNERS albo kieruj automatyczne podbicia zależności przez mały, stały plan changes/ci-maintenance/.
Plany są zatwierdzone, ale diff odpływa. Bramka dowodzi, że plan istniał, a nie że kod się go trzyma. Spełnia ją też każdy wcześniej zaakceptowany katalog changes/SLUG/, więc nowy ryzykowny pull request może powołać się na stary, niezwiązany plan. Jeden Change-Dir obsługuje jeden pull request implementacji: prompt porównujący diff z planem i reviewer sprawdzają, że każda chroniona ścieżka, której dotyka pull request, jest na liście plików w plan.md. Naprawa: wymagaj sekcji „Plan deviations” z trzeciego promptu w każdym pull requeście implementacji i niech agent review oznacza pliki, których plan nie wymienia.
Ktoś osłabia bramkę. Edycja PROTECTED albo workflow sama jest chronioną zmianą. Kopia skryptu z gałęzi bazowej chroni tylko skrypt: plik workflow uruchamia się z samego pull requesta, więc da się go zmienić tak, żeby przechodził. Naprawa: trzymaj .github/ i skrypt pod code ownerami platformy z włączonym Require review from Code Owners, bo to ta reguła faktycznie blokuje taką edycję, i dalej uruchamiaj skrypt z gałęzi bazowej, tak jak robi to powyższy workflow.
Awaria nie może czekać na plan. Naprawa: użyj audytowanego bypassu rulesetu, wpisz go do zapisu incydentu i scal retroaktywny pull request planu w ciągu dwóch dni, które wyznacza polityka. Przeglądaj każdy bypass co miesiąc.
Ścieżka w monorepo się przenosi. Katalog po zmianie nazwy po cichu wypada z PROTECTED. Naprawa: dodaj test jednostkowy, który sprawdza, że każdy chroniony katalog ze skryptu nadal istnieje w repozytorium.
Co dalej z governance planowania
Dział zatytułowany „Co dalej z governance planowania”Plan gate to jedna z kilku kontroli. Umieść ją obok pozostałych, a potem połącz z tym, co reviewerzy czytają przy merge’u.