Przejdź do głównej zawartości

Pakiet dowodów: co musi udowodnić pull request agenta

Pakiet dowodów (evidence bundle) to ustrukturyzowany blok w pull requeście agenta, który dowodzi zmiany: link do specyfikacji i zmiana zachowania, każde kryterium akceptacji przypisane do sprawdzenia, które się wykonało, wyniki poleceń, dowody z działania lub ewaluacji, klasa ryzyka, wrażliwe ścieżki, zmiany wyroczni i pochodzenie. Check w CI parsuje pakiet i blokuje merge, gdy jest niekompletny.

Agenci twojego zespołu otwierają kilkanaście pull requestów dziennie, a każdy opis brzmi tak samo: „Zaimplementowałem paginację, dodałem testy, wszystkie checki przechodzą”. Trzy z nich po cichu zmieniły fixture testowe, jeden dotknął webhooka płatności, a żaden nie mówi, którego kryterium akceptacji dowodzi który test. Nie odróżnisz bezpiecznych od ryzykownych bez czytania każdego diffa, a właśnie tę pracę agenci mieli ci oszczędzić.

Ta strona jest dla programistów, którzy konfigurują agentów, tech leadów, którzy odpowiadają za zasady review, i CTO, którzy potrzebują jednego zapisu audytowego na każdą zmianę. To kanoniczny schemat manifestu zmiany w całym serwisie: pochodzenie zmian i routing według ryzyka kieruje zmiany na podstawie tych pól, a czytanie dowodów zamiast kodu wyjaśnia, jak recenzent je czyta.

  • Schemat pole po polu, z informacją, kto wypełnia każde pole i jak CI je weryfikuje.
  • Szablon pull requesta, który agenci i ludzie wypełniają tak samo.
  • Przetestowany check CI (około 80 linii Node), który oblewa niekompletny pakiet i przelicza klasę ryzyka z diffa.
  • Tabelę routingu, która zamienia klasę ryzyka w odpowiedź na pytania, kto zatwierdza i kto musi czytać kod.
  • Trzy prompty do skopiowania: przygotuj pakiet, zaudytuj pakiet względem diffa, napraw oblany check.
  • Tryby awarii bramki opartej na pakiecie i sposób wyjścia z każdego z nich.

Opis to proza, którą agent napisał o własnej pracy. Może być błędny w sposób, którego nikt nie zauważy aż do produkcji. Skala, przy której ma to znaczenie, została zmierzona: raport Acceleration Whiplash firmy Faros AI (kwiecień 2026; telemetria z 22 000 programistów i ponad 4000 zespołów; telemetria dostawcy z bazy klientów Faros) pokazał wzrost mediany czasu w review o 441,5% i o 31,3% więcej pull requestów scalanych bez żadnego review. Generowanie się przeskalowało, czytanie nie.

Rozwiązaniem jest wymaganie wyników sprawdzeń zamiast deklaracji o nich. Jak ujął to jeden z praktyków: „Model może przekonywać, że jego praca jest skończona. Deterministyczny walidator może udowodnić, że brakuje wymaganego pola” (tłum. własne; oryginał: „A model can argue that its work is complete. A deterministic validator can prove that a required field is missing.”; NARESH, Graph Engineering for AI Coding Agents, DEV Community, 30 lipca 2025). Pakiet jest tym, co taki walidator czyta.

Pakiet ma siedem sekcji. Sednem projektu jest kolumna Weryfikacja w CI: każde pole, w którym agent mógłby pomylić się na swoją korzyść, jest albo przeliczane z diffa, albo sprawdzane względem gałęzi.

SekcjaPolaKto wypełniaWeryfikacja w CIKiedy wymagana
Specyfikacjaspec.link, spec.delta (zmiany zachowania prostymi zdaniami), spec.unrequestedAgent, na podstawie zgłoszenia lub spec.mdLink to URL albo plik istniejący w gałęzi; delta nie jest pustaZawsze
AkceptacjaJeden wpis na kryterium: criterion, check (plik:linia albo polecenie), resultAgent, po uruchomieniu sprawdzeńKażdy result to pass; każdy cytowany plik istniejeZawsze
Sprawdzeniacommand, exit_code, opcjonalnie summary (np. wynik testów mutacyjnych)AgentKażdy exit_code to 0. CI uruchamia też własne wymagane joby; pakiet nigdy ich nie zastępujeZawsze
Działaniekind (screenshot, trace, video, preview-url), ref, covers (identyfikatory kryteriów)Agent, z podglądu lub przebiegu w przeglądarceObecne, gdy zmieniły się ścieżki UIGdy pasują globy z polityki
Ewaluacjesuite, score, baselineAgent albo job ewaluacyjny w CIscore ≥ baselineGdy zmieniły się prompty, konfiguracja modelu lub harness agenta
Ryzykoclass (low, standard, high), touches (klasy wrażliwe), oracle_changes (ścieżka, kierunek, powód), rollbackAgent proponujeCI przelicza klasy wrażliwe i pliki wyroczni z diffa, ustala próg i oblewa niższą deklaracjęZawsze
Pochodzenieagent (narzędzie i wersja), model, session, task, human_ownerAgent oraz człowiek, który odpowiada za zmianęagent, model i human_owner są wypełnioneZawsze

Trzy zasady pilnują uczciwości schematu:

  1. Zadeklarowana klasa ryzyka może tylko podnieść wyliczony próg. Agent, który wpisze class: low przy zmianie w płatnościach, obleje check; człowiek, który oznaczy nieszkodliwą zmianę jako high, dostanie surowsze review i to jest dozwolone.
  2. Zmiana wyroczni nigdy nie jest domyślnie neutralna. Każdy edytowany test, snapshot, workflow CI, konfiguracja lintera lub typów musi trafić na listę z kierunkiem (direction) stricter, looser albo neutral. Wpis looser wymusza high, bo zmienia znaczenie „zielonego” dla każdej innej zmiany.
  3. Pochodzenie się zapisuje, ale nie steruje routingiem. Zmiany ludzi, zmiany wspierane przez AI i zmiany agentów używają tego samego pakietu i tego samego routingu. Strona o pochodzeniu i routingu wyjaśnia, dlaczego autorstwo jest słabym wskaźnikiem ryzyka.

Konfiguracja to pięć plików. Dodaj je w jednym pull requeście, scal go, a dopiero potem ustaw check jako wymagany. Kolejność ma znaczenie, co wyjaśnia sekcja o trybach awarii.

  1. Dodaj szablon pull requesta. GitHub wypełnia opis pull requestów otwieranych w interfejsie webowym treścią .github/pull_request_template.md. Agenci, którzy otwierają pull requesty z wiersza poleceń, dostają tę samą strukturę z promptu do pakietu niżej, który wskazuje im ten plik.

    .github/pull_request_template.md
    ## What changed and why
    <!-- Two or three sentences for a human. The bundle below is the evidence. -->
    ## Evidence bundle
    ~~~yaml
    evidence_bundle: 1
    spec:
    link: docs/specs/orders-pagination.md # or the issue URL
    delta:
    - GET /orders returns 50 items per page and a next_cursor
    - The old page parameter returns 400
    unrequested: [] # behavior nobody asked for
    acceptance:
    - criterion: "AC1: first page has 50 items and a next_cursor"
    check: tests/orders.contract.test.ts:42
    result: pass # pass | fail | unverified
    - criterion: "AC2: the page parameter returns 400"
    check: tests/orders.contract.test.ts:88
    result: pass
    checks:
    - command: npm test
    exit_code: 0
    - command: npx stryker run --mutate "src/orders/**/*.ts"
    exit_code: 0
    summary: 81% mutation score on changed files
    evals: [] # suite, score, baseline
    runtime: [] # kind, ref, covers
    risk:
    class: standard # low | standard | high
    touches: [] # auth, money, schema, migrations, infra
    oracle_changes:
    - path: tests/orders.contract.test.ts
    direction: stricter # stricter | looser | neutral
    reason: new contract cases for AC1 and AC2
    rollback: revert the merge commit; no migration, no flag
    provenance:
    agent: Claude Code 2.1.283
    model: claude-opus-5-5
    session: https://claude.ai/code/session_EXAMPLE
    task: https://github.com/acme/shop/issues/412
    human_owner: "@anna"
    ~~~
  2. Napisz plik polityki. Nazywa klasy wrażliwe z ich minimalnym ryzykiem, ścieżki wyroczni oraz ścieżki, które wymagają dowodów z działania lub ewaluacji. Dopasuj globy do swojego repozytorium; te odpowiadają klasom eskalacji, których używa reszta serwisu.

    # .github/evidence-policy.yml (owned by CODEOWNERS; editing it is an oracle change)
    sensitive:
    auth: { globs: ['**/auth/**', '**/middleware/**', '**/*permission*'], min_risk: high }
    money: { globs: ['**/billing/**', '**/payments/**', '**/pricing/**'], min_risk: high }
    schema: { globs: ['**/*.sql', '**/openapi*', '**/*.proto'], min_risk: high }
    migrations: { globs: ['**/migrations/**'], min_risk: high }
    infra: { globs: ['infra/**', '**/*.tf', '.github/workflows/**'], min_risk: standard }
    oracle:
    - '**/*.test.*'
    - '**/__snapshots__/**'
    - '.github/workflows/**'
    - '.github/evidence-policy.yml'
    - '.github/CODEOWNERS'
    - 'scripts/check-evidence.mjs'
    - 'tsconfig*.json'
    - 'eslint.config.*'
    runtime_required:
    - 'src/components/**'
    - 'src/pages/**'
    evals_required:
    - 'prompts/**'
  3. Dodaj skrypt sprawdzający. Czyta treść pull requesta ze zdarzenia GitHuba, parsuje pierwszy blok yaml zaczynający się od evidence_bundle: i porównuje go z diffem. Zależy od yaml (2.9.1 w npm) i minimatch (10.2.6 w npm); obie wersje sprawdzone 2026-09-26.

    // scripts/check-evidence.mjs: fails a pull request whose evidence bundle is
    // missing, incomplete, or contradicted by the diff. Usage:
    // node check-evidence.mjs <policy.yml>
    import { appendFileSync, existsSync, readFileSync } from 'node:fs';
    import { execFileSync } from 'node:child_process';
    import { parse } from 'yaml';
    import { minimatch } from 'minimatch';
    const RANK = { low: 0, standard: 1, high: 2 };
    const policy = parse(readFileSync(process.argv[2], 'utf8'));
    const pr = JSON.parse(readFileSync(process.env.GITHUB_EVENT_PATH, 'utf8')).pull_request;
    const errors = [];
    const fail = (msg) => errors.push(msg);
    // 1. What CI knows without asking the agent: the changed files.
    const changed = (process.env.EVIDENCE_CHANGED_FILES ??
    execFileSync('git', ['diff', '--name-only', `${pr.base.sha}...HEAD`], { encoding: 'utf8' }))
    .split('\n').filter(Boolean);
    const touching = (globs) => changed.filter((f) => globs.some((g) => minimatch(f, g, { dot: true })));
    // 2. The bundle: the first yaml fence (backticks or tildes) that starts with evidence_bundle:
    const block = (pr.body ?? '').match(/(`{3}|~{3})ya?ml\r?\n(evidence_bundle:[\s\S]*?)\1/);
    if (!block) {
    console.error('No evidence bundle found. Fill in the template from .github/pull_request_template.md.');
    process.exit(1);
    }
    const b = parse(block[2]) ?? {};
    // 3. Spec link and delta
    if (!b.spec?.link) fail('spec.link is empty');
    else if (!/^https?:\/\//.test(b.spec.link) && !existsSync(b.spec.link)) fail(`spec.link ${b.spec.link} does not exist`);
    if (!b.spec?.delta?.length) fail('spec.delta lists no behavior change');
    // 4. Acceptance: every criterion names a check that exists and passed
    if (!b.acceptance?.length) fail('acceptance is empty');
    for (const a of b.acceptance ?? []) {
    if (a.result !== 'pass') fail(`acceptance "${a.criterion}" is ${a.result ?? 'missing a result'}`);
    const ref = /^([^\s:]+):(\d+)$/.exec(a.check ?? '');
    if (!a.check) fail(`acceptance "${a.criterion}" names no check`);
    else if (ref && !existsSync(ref[1])) fail(`acceptance "${a.criterion}" cites ${ref[1]}, which is not in the branch`);
    }
    for (const c of b.checks ?? []) if (c.exit_code !== 0) fail(`check "${c.command}" exited ${c.exit_code}`);
    if (!b.checks?.length) fail('checks lists no command that ran');
    // 5. Sensitive paths: CI recomputes them and sets the risk floor
    let floor = 'low';
    const declared = new Set(b.risk?.touches ?? []);
    for (const [name, rule] of Object.entries(policy.sensitive)) {
    const hits = touching(rule.globs);
    if (!hits.length) continue;
    if (!declared.has(name)) fail(`diff touches ${name} (${hits.join(', ')}) but risk.touches omits it`);
    if (RANK[rule.min_risk] > RANK[floor]) floor = rule.min_risk;
    }
    // 6. Oracle changes: every edited test, CI or lint file is declared with a direction
    const listed = new Map((b.risk?.oracle_changes ?? []).map((o) => [o.path, o.direction]));
    for (const f of touching(policy.oracle)) {
    const dir = listed.get(f);
    if (!dir) fail(`oracle file ${f} changed but is not in risk.oracle_changes`);
    else if (!['stricter', 'looser', 'neutral'].includes(dir)) fail(`oracle change ${f} has direction ${dir}; use stricter, looser or neutral`);
    if (RANK[floor] < RANK.standard) floor = 'standard';
    if (dir === 'looser') floor = 'high';
    }
    // 7. Runtime evidence and evals, where the policy requires them
    if (touching(policy.runtime_required).length && !b.runtime?.length) fail('UI paths changed but runtime lists no screenshot or trace');
    if (touching(policy.evals_required).length) {
    if (!b.evals?.length) fail('prompt or model paths changed but evals is empty');
    for (const e of b.evals ?? []) if (!(e.score >= e.baseline)) fail(`eval ${e.suite} scored ${e.score} against baseline ${e.baseline}`);
    }
    // 8. Risk class and provenance
    if (!Object.hasOwn(RANK, b.risk?.class ?? '')) fail('risk.class must be low, standard or high');
    else if (RANK[b.risk.class] < RANK[floor]) fail(`risk.class is ${b.risk.class}, but the diff requires at least ${floor}`);
    if (!b.risk?.rollback) fail('risk.rollback is empty');
    for (const k of ['agent', 'model', 'human_owner']) if (!b.provenance?.[k]) fail(`provenance.${k} is empty`);
    const risk = RANK[b.risk?.class] > RANK[floor] ? b.risk.class : floor;
    if (process.env.GITHUB_OUTPUT) appendFileSync(process.env.GITHUB_OUTPUT, `risk=${risk}\n`);
    console.log(`Changed files: ${changed.length}. Risk class: ${risk}.`);
    if (errors.length) {
    console.error(`Evidence bundle incomplete (${errors.length}):\n- ${errors.join('\n- ')}`);
    process.exit(1);
    }
    console.log('Evidence bundle complete.');
  4. Dodaj workflow. Dwa szczegóły sprawiają, że można mu ufać. Ładuje skrypt i politykę z commita bazowego, więc pull request nie osłabi skryptu ani polityki, które go oceniają. Sam plik workflow uruchamia się jednak z pull requesta, dlatego krok 5 daje katalogowi .github/workflows/ właściciela kodu i wymaga review od właścicieli kodu (albo robisz z niego workflow wymagany przez ruleset). Checkout ustawia persist-credentials: false, więc token nie trafia do .git/config; gh pr edit czyta GH_TOKEN z własnego kroku. Uruchamia się też na edited, więc poprawienie opisu ponownie uruchamia check bez nowego pusha.

    .github/workflows/evidence-bundle.yml
    name: evidence-bundle
    on:
    pull_request:
    types: [opened, edited, synchronize, reopened, ready_for_review]
    permissions:
    contents: read
    pull-requests: write
    jobs:
    evidence:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v7
    with:
    fetch-depth: 0
    persist-credentials: false
    - uses: actions/setup-node@v7
    with:
    node-version: 24
    - name: Load the checker and policy from the base branch
    run: |
    mkdir -p /tmp/evidence
    git show "${{ github.event.pull_request.base.sha }}:scripts/check-evidence.mjs" > /tmp/evidence/check.mjs
    git show "${{ github.event.pull_request.base.sha }}:.github/evidence-policy.yml" > /tmp/evidence/policy.yml
    npm install --prefix /tmp/evidence --no-save yaml@2.9.1 minimatch@10.2.6
    - name: Check the evidence bundle
    id: check
    run: node /tmp/evidence/check.mjs /tmp/evidence/policy.yml
    - name: Label the risk class
    if: always() && steps.check.outputs.risk != ''
    env:
    GH_TOKEN: ${{ github.token }}
    run: |
    RISK="${{ steps.check.outputs.risk }}"
    STALE=$(printf 'risk:%s\n' low standard high | grep -vx "risk:$RISK" | paste -sd, -)
    gh pr edit "${{ github.event.pull_request.number }}" --remove-label "$STALE" --add-label "risk:$RISK"

    Utwórz raz etykiety risk:low, risk:standard i risk:high; gh pr edit --add-label nie tworzy brakujących etykiet. Krok zdejmuje też dwie pozostałe etykiety risk:*, bo samo --add-label nigdy żadnej nie usuwa: pull request, który po pushu przechodzi ze standard do high, miałby inaczej obie, a wszystko, co kieruje zmiany według etykiet, odczytałoby nieaktualną klasę.

  5. Ustaw check jako wymagany i chroń bramkę. W rulesecie gałęzi main wymagaj statusu evidence i review od właścicieli kodu. Potem daj właściciela, który nie jest agentem, trzem grupom ścieżek: plikom samej bramki (łącznie z samym CODEOWNERS, promptami i szablonem pull requesta, bo GitHub stosuje CODEOWNERS z gałęzi bazowej, więc pull request, który go edytuje, mógłby inaczej bez review usunąć własnego właściciela), każdemu globowi z min_risk: high oraz chronionym wyroczniom: testom akceptacyjnym lub kontraktowym, które kodują specyfikację, i konfiguracji typów oraz lintera dla całego repozytorium. To właśnie egzekwuje wiersz high w tabeli routingu dla tych ścieżek: wymagane review właściciela kodu obejmuje każdy pull request, który ich dotyka, niezależnie od etykiety.

    Nie dawaj właściciela każdej ścieżce **/*.test.* ani snapshotom. Zwykłe testy zmieniają się w większości pull requestów standard, więc objęcie ich własnością postawiłoby każdy z nich przed właścicielem kodu i zlikwidowało ścieżkę z jednym recenzentem. Takie zmiany nadal trafiają do risk.oracle_changes i czyta je recenzent standard. Jedno ograniczenie: zmiana looser w teście bez właściciela podnosi klasę do high, a etykietę do risk:high, ale CODEOWNERS nie widzi etykiet, więc nic nie wymusza na niej właściciela kodu. Recenzent eskaluje ją ręcznie, a test, którego osłabienie byłoby kosztowne, powinien leżeć na chronionej ścieżce.

    # .github/CODEOWNERS
    .github/evidence-policy.yml @acme/platform
    .github/workflows/ @acme/platform
    scripts/check-evidence.mjs @acme/platform
    .github/CODEOWNERS @acme/platform
    .github/prompts/ @acme/platform
    .github/pull_request_template.md @acme/platform
    # Every min_risk: high glob in the policy
    **/auth/** @acme/security
    **/middleware/** @acme/security
    **/*permission* @acme/security
    **/billing/** @acme/payments
    **/payments/** @acme/payments
    **/pricing/** @acme/payments
    **/*.sql @acme/data
    **/openapi* @acme/data
    **/*.proto @acme/data
    **/migrations/** @acme/data
    # Protected oracles only: spec-level tests and repo-wide config
    **/*.contract.test.* @acme/platform
    tsconfig*.json @acme/platform
    eslint.config.* @acme/platform

Testuj bramkę tak jak każdą wyrocznię: fixture’ami, które muszą przejść, i fixture’ami, które muszą oblać. Zmienna EVIDENCE_CHANGED_FILES zastępuje git diff, więc fixture potrzebuje tylko sztucznego pliku zdarzenia i listy ścieżek:

Okno terminala
# Terminal, repository root. ev-billing.json holds {"pull_request":{"base":{"sha":"x"},"body":"..."}}
GITHUB_EVENT_PATH=fixtures/ev-billing.json \
EVIDENCE_CHANGED_FILES=$'src/billing/refund.ts\nsrc/pages/orders.astro' \
node scripts/check-evidence.mjs .github/evidence-policy.yml

Uruchomiony na szablonie z góry, ze zmienionym plikiem płatności i stroną UI oraz z cytowanymi plikami specyfikacji i testu (docs/specs/orders-pagination.md, tests/orders.contract.test.ts) obecnymi w gałęzi, skrypt kończy się kodem 1 i trzema błędami: risk.touches pomija money, runtime jest puste oraz risk.class is standard, but the diff requires at least high. Trzymaj jeden fixture na każdą regułę (brak pakietu, niezweryfikowane kryterium, brak cytowanego pliku testu, niezadeklarowana zmiana wyroczni, zmiana wyroczni looser, brak ewaluacji) i uruchamiaj je w zwykłym jobie testowym. Zmiana bramki, która psuje fixture, zostanie wyłapana, zanim trafi do main.

Pakiet rozstrzyga, kto robi review i co czyta. Ta tabela to polityka na start; wersja dla całej organizacji należy do polityki autonomii i klas ryzyka.

Klasa ryzykaTypowy wyzwalaczZatwierdzenieKto czyta kodPo merge’u
lowDokumentacja, teksty, izolowany UI z dowodami z działania, bez zmian wyroczniJeden recenzent na podstawie pakietu albo reguła zatwierdzania (zob. zakładkę Cursor)Domyślnie nikt; próbkowanie według dziennika zaufaniaZwykły deploy
standardZmiana zachowania w pokrytym kodzie; zmiany wyroczni stricter lub neutral; infrastrukturaJeden recenzent na podstawie pakietu plus ustalenia agenta recenzującegoRecenzent czyta zmiany wyroczni i każde zachowanie z unrequestedCanary lub flaga, jeśli są dostępne
highUwierzytelnianie, pieniądze, schematy, migracje, zmiana wyroczni looserWłaściciel kodu z CODEOWNERSWskazany właściciel czyta kod, oprócz pakietuStopniowe wdrożenie i bramka zatwierdzenia produkcyjnego

Ścieżki wpisane do CODEOWNERS (pliki samej bramki, wrażliwe globy i chronione wyrocznie) wymagają swojego właściciela kodu niezależnie od klasy. Zmiana zwykłego testu lub snapshotu w kierunku stricter albo neutral zostaje na ścieżce z jednym recenzentem; zmiana looser dostaje etykietę risk:high, a recenzent musi ręcznie przekazać ją właścicielowi kodu, bo CODEOWNERS nie widzi etykiet.

standard odpowiada klasie medium w polityce organizacji; zmiany critical to tutaj high plus bramka zatwierdzenia produkcyjnego.

Przy low i standard zadaniem recenzenta jest przeczytanie pakietu w kolejności: zmiana specyfikacji, linie akceptacji, zmiany wyroczni, dowody z działania. Kolejność czytania i klasy eskalacji opisuje czytanie dowodów zamiast kodu, a protokół triage’u — code review PR-a agenta.

Format pakietu i check w CI są identyczne dla wszystkich trzech narzędzi. Różni się miejsce, w którym agent działa, gdy wypełnia pakiet. W każdym narzędziu najpierw dodaj ten fragment do pliku instrukcji, który agent czyta (CLAUDE.md w Claude Code, AGENTS.md w Codeksie, reguła projektu w Cursorze):

## Pull requests
Every pull request body contains the evidence bundle from
.github/pull_request_template.md. Run every check you cite and paste real exit
codes. Never mark a criterion `pass` without running its check. List every
test, snapshot, CI or lint file you changed under risk.oracle_changes. Never
edit .github/evidence-policy.yml or scripts/check-evidence.mjs.

Z terminala, na własnej gałęzi funkcji, uruchom prompt do pakietu w trybie headless i otwórz pull request z jego wynikiem. dontAsk z dokładną allowlistą to udokumentowany wzorzec dla przebiegów bez nadzoru: wszystko spoza listy zostaje odrzucone, zamiast czekać na potwierdzenie:

Okno terminala
# Terminal, feature branch checked out (Claude Code 2.1.283, `latest` channel)
claude -p "$(cat .github/prompts/evidence-bundle.md)" --permission-mode dontAsk \
--allowedTools "Read,Grep,Glob,Bash(git diff:*),Bash(git log:*),Bash(npm test:*),Bash(npx stryker run:*)" \
> pr-body.md
gh pr create --title "Cursor pagination for GET /orders" --body-file pr-body.md

W GitHub Actions anthropics/claude-code-action@v1 przyjmuje --json-schema w claude_args i udostępnia zwalidowany wynik jako wyjście kroku structured_output. Przydaje się, gdy chcesz mieć pakiet jako dane, a nie jako komentarz. W CI na gałęzi, której nie ufasz, dodaj --bare --setting-sources "" --strict-mcp-config i nie przekazuj żadnych sekretów poza kluczem API.

Claude Code może dodawać atrybucję do commitów i pull requestów; zostaw ją włączoną: to darmowy zapis pochodzenia, zgodny z polem provenance.agent w pakiecie.

Dowody z działania zbierzesz skillem agent-browser: każdy z trzech agentów może nim sterować działającą aplikacją i zapisywać zrzuty ekranu. Zainstaluj CLI poleceniem npm install -g agent-browser && agent-browser install, a skill poleceniem npx skills add vercel-labs/agent-browser (flagi dla poszczególnych agentów i przypinanie wersji opisuje podlinkowana strona). Wgraj zrzuty jako artefakty workflow i podaj URL artefaktu w runtime.ref.

Zapisz pierwszy prompt jako .github/prompts/evidence-bundle.md, żeby polecenia powyżej mogły go wczytać.

Check nie znajduje skryptu przy pierwszym pull requeście. Workflow czyta scripts/check-evidence.mjs z commita bazowego, a w pull requeście, który go dodaje, baza jeszcze go nie ma. Wyjście: najpierw scal pięć plików bez wymaganego checka, potem dodaj wymagany check do rulesetu.

Pakiet podaje pass dla sprawdzeń, które nigdy się nie wykonały. Agent wkleja wiarygodnie wyglądające kody wyjścia. Wyjście: trzymaj prawdziwe joby testowe jako osobne wymagane checki, żeby sekcja checks była deklaracją, którą CI potwierdza niezależnie. Dodaj prompt audytowy jako krok agenta recenzującego dla pull requestów standard i high, a sprzeczny pakiet traktuj jak oblane review.

Linie akceptacji cytują testy, które nie testują kryterium. tests/orders.test.ts:1 istnieje i przechodzi, ale nie dowodzi niczego o paginacji. Skrypt widzi, że plik istnieje, a nie co sprawdza. Wyjście: przy zmianach standard recenzent otwiera każdą cytowaną linię, a miary siły wyroczni, takie jak wynik testów mutacyjnych na zmienionych plikach, trafiają do checks.

Agent osłabia test i nazywa to neutral. Skrypt ufa zadeklarowanemu kierunkowi. Wyjście: umieść testy kodujące specyfikację na chronionej ścieżce z właścicielem w CODEOWNERS, niech recenzent standard porówna zadeklarowany kierunek każdej innej zmiany wyroczni z jej diffem, a ochrona wyroczni pokazuje hooki, które w ogóle nie pozwalają agentowi edytować testów.

Globy polityki rozjeżdżają się z kodem. Nowy katalog src/checkout/ obsługuje pieniądze, ale nie pasuje do żadnego globu, więc zmiany w płatnościach przechodzą jako low. Wyjście: przeglądaj .github/evidence-policy.yml przy każdym nowym katalogu najwyższego poziomu i dodaj fixture dla każdego wrażliwego katalogu, żeby zmiana nazwy oblała test fixture’ów.

Każdy pull request staje się high. Jeśli globy polityki obejmują pół repozytorium, pakiet kieruje wszystko do właścicieli kodu i wracasz do czytania każdego diffa. Wyjście: zawęź globy do kodu, w którym błąd jest drogi i późno wykrywany, a resztę przenieś do standard z dowodami z działania.

Etykiety nie działają w pull requestach z forków. GITHUB_TOKEN w zdarzeniu pull_request z forka ma tylko prawo odczytu, więc gh pr edit się nie powiedzie. Wyjście: uruchamiaj agentów na gałęziach w tym samym repozytorium albo pomiń krok etykietowania dla forków i kieruj zmiany na podstawie wyniku checka.

Pakiet staje się formalnością wypełnianą ręcznie. Wyjście: śledź jedną liczbę na zespół, kompletność dowodów: scalone pull requesty, których pakiet przeszedł check za pierwszym podejściem, podzielone przez wszystkie scalone pull requesty, miesięcznie. Spadający trend oznacza, że agenci albo ludzie zgadują. Definicja i wartości bazowe są w ramach metryk.

Najczęstsze pytania

Czym jest pakiet dowodów?

Ustrukturyzowanym blokiem w pull requeście agenta, który podaje link do specyfikacji i zmianę zachowania, przypisuje każdemu kryterium akceptacji sprawdzenie, które się wykonało, wymienia polecenia i ich kody wyjścia, linkuje zrzuty ekranu, ślady lub ewaluacje, deklaruje klasę ryzyka, wrażliwe ścieżki i zmiany wyroczni oraz zapisuje pochodzenie zmiany. CI parsuje go i oblewa pull request, gdy pakiet jest niekompletny.

Po co CI przelicza pola, które agent już zadeklarował?

Bo pakiet napisał agent. CI wyznacza zmienione pliki, wrażliwe ścieżki i edytowane testy z samego diffa, a potem oblewa pakiet wszędzie tam, gdzie deklaracja jest uboższa niż diff. Zadeklarowana klasa ryzyka może podnieść próg wyliczony przez CI, nigdy go obniżyć.

Czy pakiet dowodów zastępuje code review?

Nie. Zmienia to, co recenzent czyta najpierw, i rozstrzyga, kto musi czytać kod. Zmiany o ryzyku low i standard są zatwierdzane na podstawie pakietu. CODEOWNERS wymusza, by zmiany w uwierzytelnianiu, pieniądzach, schematach, migracjach i chronionych wyroczniach czytał wskazany właściciel kodu; osłabiony zwykły test też ma ryzyko high, a recenzent ręcznie przekazuje go właścicielowi kodu.

Czy pakiet dotyczy tylko zmian pisanych przez agentów?

Nie. Ten sam pakiet i ten sam routing obowiązują zmiany ludzi, zmiany wspierane przez AI i zmiany agentów. Pochodzenie zapisuje się do pomiarów i audytu, nigdy nie służy jako sygnał ryzyka.