Przejdź do głównej zawartości

Decyzje architektoniczne, których agenci przestrzegają

Decyzja architektoniczna, której agent przestrzega, to jednostronicowy rekord decyzji architektonicznej (ADR) w repozytorium, którego ograniczenia są regułami MUSI albo NIE WOLNO, a każda wskazuje sprawdzenie, które ją egzekwuje. Agent czyta ADR przed edycją kodu, którego ten dotyczy, CI pada po złamaniu ograniczenia, a decyzję przyjmuje lub zastępuje tylko wskazany człowiek.

W sierpniu zespół ustalił, że każde wychodzące wywołanie HTTP przechodzi przez jeden wrapper z timeoutami i ponowieniami. Decyzja leży na stronie w wiki. We wrześniu jeden agent dodaje axios, żeby naprawić niestabilną integrację, drugi woła fetch prosto z warstwy domeny, a oba pull requesty przechodzą testy. Nikt nie złamał reguły, którą agent mógł zobaczyć, więc żadne review tego nie wyłapało. Ta strona jest dla tech leada, który odpowiada za takie decyzje, i dla programistów, których agenci mają ich przestrzegać.

Co zyskujesz dzięki ADR-om, których agenci przestrzegają

Dział zatytułowany „Co zyskujesz dzięki ADR-om, których agenci przestrzegają”
  • Szablon ADR z sekcją Constraints, w której każda reguła wskazuje swoje sprawdzenie albo jest oznaczona do przeglądu przez człowieka.
  • Tabelę decyzyjną: które wybory zasługują na ADR, którym wystarczy reguła lintera, a którym nic z tych rzeczy.
  • Przetestowane reguły dla TypeScriptu, Pythona i Javy, których komunikat błędu cytuje ADR, więc agent czyta powód, a nie tylko regułę.
  • adr-lint, 43-liniowy skrypt, który wywraca CI, gdy przyjęty ADR wskazuje nieistniejące sprawdzenie albo reguła powołuje się na zastąpiony ADR.
  • Konfigurację dla każdego narzędzia, która podsuwa właściwy ADR Claude Code, Codeksowi i Cursorowi, oraz regułę „zatrzymaj się i zaproponuj” dla decyzji, których nie obejmuje żaden ADR.
  • Cztery prompty do skopiowania: szkic ADR, sprawdzenie planu względem ADR-ów, odtworzenie niezapisanych decyzji z istniejącego kodu i zastąpienie decyzji.

Decyzja wymyka się przez trzy luki i żadnej z nich nie zamknie lepszy prompt.

  1. Agent nigdy nie widzi decyzji. Strona w wiki, notatka ze spotkania czy pamięć seniora leżą poza kontekstem agenta. Agent optymalizuje pod bieżące zadanie, a najkrótsza droga często przecina granicę, której nikt nie zapisał.
  2. Decyzja to proza, którą agent może zinterpretować po swojemu. „Preferuj wspólny wrapper HTTP” ustępuje pod presją: agent uznaje, że ten jeden przypadek jest wyjątkiem.
  3. Nic nie pada, gdy decyzja zostaje złamana. Testy sprawdzają zachowanie, a pull request, który dodaje drugiego klienta HTTP, zachowuje się poprawnie.

DORA wiąże architekturę z tym, czy AI w ogóle pomaga. Google Cloud, ogłaszając raport DORA 2025 (23 września 2025), pisze: „Teams working in loosely coupled architectures with fast feedback loops see gains, while those constrained by tightly coupled systems and slow processes see little or no benefit”. Nasz wniosek: decyzja, która po cichu się rozmywa, spycha kod w stronę ściśle powiązanej architektury.

ADR zamyka pierwszą lukę, gdy leży w repozytorium i trafia do kontekstu agenta. Ograniczenia zapisane jako MUSI albo NIE WOLNO zamykają drugą. Sprawdzenie uruchamiane w CI zamyka trzecią, a strona o funkcjach dopasowania architektury zamienia te sprawdzenia w wymagane bramki.

Które decyzje potrzebują ADR, a którym wystarczy reguła?

Dział zatytułowany „Które decyzje potrzebują ADR, a którym wystarczy reguła?”

ADR kosztuje decyzję człowieka i review. Przeznaczaj go na wybory, których cofnięcie jest kosztowne. Skill domain-modeling Matta Pococka (w mattpocock/skills, sprawdzone 26 września 2026) proponuje ADR tylko wtedy, gdy spełnione są trzy warunki: wybór jest „Hard to reverse”, „Surprising without context” i „The result of a real trade-off”. Stosuj ten sam test, a potem zdecyduj, jak egzekwować każde ograniczenie.

WybórADR?Jak go egzekwować
Granice modułów i kierunek zależności („domena nie robi I/O”)TakReguła zależności: dependency-cruiser, import-linter albo ArchUnit
Jedna biblioteka na jeden problem (klient HTTP, ORM, daty, logowanie)TakZakaz importu: ESLint no-restricted-imports, Ruff TID251, ArchUnit
Nowa baza danych, kolejka albo usługa zewnętrznaTakPrzegląd człowieka: code owners na kodzie infrastruktury i manifestach zależności
Publiczne API albo kontrakt zdarzeńTakDiff powierzchni API albo kontraktu w CI (zobacz stronę o funkcjach dopasowania)
Wzorce obsługi błędów, ponowień i idempotencjiTak, jeśli był prawdziwy kompromisReguła lintera, gdzie się da, w pozostałych przypadkach ograniczenie Review: sprawdzane przez recenzenta
Nazewnictwo, formatowanie, układ plikówNieKonfiguracja lintera i formatera, bez ADR
„Wybieraj nudną technologię”, „trzymaj prosto”NieNic tego nie sprawdzi, więc agenta to nie ogranicza. Uzasadnienie wpisz w sekcję Context ADR-u, który z niego wynika

Ostatni wiersz jest ważny. Zasada bez sprawdzenia nie zatrzyma agenta. Albo zamień ją w konkretne ograniczenie („NIE WOLNO dodawać zależności runtime bez przyjętego ADR”), albo zostaw w sekcji Context jako powód jakiegoś ograniczenia.

Zacznij od popularnego szablonu MADR (4.0.0, 17 września 2024). MADR ma już opcjonalny element „Confirmation”, który pyta, jak zgodność z ADR „can/will be confirmed”, i podsuwa „a design/code review or a test with a library such as ArchUnit”. Wersja dla agentów czyni tę sekcję obowiązkową i czytelną maszynowo, a do tego dodaje instrukcję na wypadek, gdy decyzja nie pasuje do zadania.

---
status: accepted
date: 2026-09-14
decision-makers: Anna Kowalska (tech lead), Tomasz Nowak (platform)
scope: src/**
---
# ADR-0012: All outbound HTTP goes through src/lib/http.ts
## Context
Three HTTP clients are in use (axios, got, the global fetch), each with its own
timeout and retry behavior. During the 2026-08-30 payment-provider outage, calls
through got hung for 120 seconds because it had no timeout, and the checkout
workers exhausted their pool.
## Decision
All outbound HTTP calls go through `src/lib/http.ts`, a wrapper over the platform
`fetch` with a 10-second default timeout, retries with jitter for idempotent
methods, and trace headers. We add no other HTTP client library.
## Consequences
- Good: one place to change timeouts, retries and tracing; one behavior during an outage.
- Bad: streaming uploads and websockets need the wrapper extended first.
- Given up: axios interceptors, which two services used for auth headers.
## Constraints
- **adr-0012-c1** Code under `src/` MUST NOT import `axios`, `got`, `node-fetch` or `undici`. Check: `eslint.config.js#adr-0012-c1`
- **adr-0012-c2** Code under `src/domain/` MUST NOT import `src/lib/http.ts`; the domain does no I/O. Check: `.dependency-cruiser.cjs#adr-0012-c2`
- **adr-0012-c3** New call sites pass an explicit timeout when a call can take longer than 10 seconds. Review: the reviewer confirms it from the test that covers the slow path.
## When the agent must stop
If a task needs something the wrapper cannot do (streaming, websockets, a client
certificate), stop. Write a proposed ADR that amends this one, and do not add a
client library.
## Revisit when
More than one service needs websockets, or the platform `fetch` gains a feature we
would otherwise wrap.

ADR-y piszemy tu po angielsku, bo czytają je agenci i cały zespół, a nazwy sekcji wykorzystuje skrypt adr-lint. Cztery zasady sprawiają, że ten format działa z agentami:

  • Jedna strona, jedna decyzja. Agent wczytuje ADR do kontekstu przy każdym zadaniu, którego ten dotyczy, więc każdy dodatkowy akapit kosztuje tokeny przy każdym uruchomieniu. Analizę opcji zostaw w pull requeście.
  • Każde ograniczenie ma identyfikator i źródło werdyktu. Check: wskazuje plik i identyfikator reguły w nim; Review: mówi, kto sprawdza ręcznie i na podstawie jakiego dowodu. Ograniczenie bez żadnego z nich to życzenie.
  • Komunikat reguły cytuje identyfikator. Gdy sprawdzenie pada, agent widzi adr-0012-c1 i ścieżkę do ADR, otwiera go i czyta, dlaczego.
  • scope mówi, gdzie decyzja obowiązuje. Routing w każdym narzędziu korzysta z tego pola, żeby wczytywać tylko ADR-y dotyczące edytowanych plików.

Jak zapisać ograniczenie, które sprawdzi narzędzie?

Dział zatytułowany „Jak zapisać ograniczenie, które sprawdzi narzędzie?”

Większość decyzji architektonicznych sprowadza się do dwóch kształtów reguły: „ten kod nie importuje tamtego kodu” i „nikt nie importuje tej biblioteki”. Każdy popularny stos ma narzędzie do obu. Poniższe reguły uruchomiliśmy 26 września 2026 (ESLint 10.11.0 z typescript-eslint 8.70.1, dependency-cruiser 18.4.0, Ruff 0.16.9) i każda padła na podłożonym naruszeniu, z identyfikatorem ADR w wyniku.

Zakaz biblioteki realizuje wbudowana reguła ESLint no-restricted-imports. Agent czyta pole message:

eslint.config.js
import { defineConfig } from 'eslint/config';
import tseslint from 'typescript-eslint';
export default defineConfig({
files: ['src/**/*.ts'],
languageOptions: { parser: tseslint.parser },
rules: {
'no-restricted-imports': ['error', {
paths: ['axios', 'got', 'node-fetch', 'undici'].map((name) => ({
name,
message: 'adr-0012-c1: outbound HTTP goes through src/lib/http.ts. See docs/adr/0012-outbound-http.md.',
})),
}],
},
});

Granicę realizuje reguła dependency-cruiser nazwana identyfikatorem ograniczenia:

// .dependency-cruiser.cjs (add to the forbidden array)
{
name: 'adr-0012-c2',
severity: 'error',
comment: 'ADR-0012: the domain layer does no I/O. Pass the data in from src/app instead of importing src/lib/http.ts.',
from: { path: '^src/domain/' },
to: { path: '^src/lib/http\\.ts$' },
},

Naruszenie daje w ESLint komunikat 'axios' import is restricted from being used. adr-0012-c1: outbound HTTP goes through src/lib/http.ts…, a w dependency-cruiser error adr-0012-c2: src/domain/order.ts → src/lib/http.ts. Uruchamiaj ESLint z --no-inline-config, żeby komentarz eslint-disable nie mógł wyłączyć ograniczenia.

Decyzja o wyborze bazy danych czy kolejki rzadko sprowadza się do reguły importu. Oznacz ją jako Review: i obejmij manifesty (package.json, pyproject.toml, pom.xml, kod infrastruktury) regułą code owners, żeby nowa zależność nie mogła wejść bez człowieka, który zna ADR-y. Jak sprawdzić, czy zależność dodana przez agenta jest prawdziwa i bezpieczna, opisuje strona o weryfikacji zależności.

  1. Utwórz docs/adr/ i indeks. docs/adr/README.md ma jeden wiersz tabeli na każdy ADR: identyfikator, status, zakres i regułę w jednym zdaniu. Komórka z identyfikatorem linkuje do pliku, bo tego szuka adr-lint: | [ADR-0012](0012-outbound-http.md) | accepted | src/** | Outbound HTTP only through src/lib/http.ts |. Indeks agent wczytuje przy każdym zadaniu; pełny ADR tylko wtedy, gdy edytuje pliki z jego zakresu.

  2. Zapisz decyzje, które zespół już podjął. Uruchom poniższy prompt „odtwórz niezapisane decyzje”. Znajduje wzorce, których kod już się trzyma, i liczy wyjątki. Tech lead wybiera trzy do pięciu najważniejszych, a zespół przyjmuje je jako ADR-y. Agent pisze szkic; nie decyduje.

  3. Wprowadzaj każdy ADR razem z jego sprawdzeniami w jednym pull requeście. ADR, reguła lintera albo zależności i, w istniejącym kodzie, baseline obecnych naruszeń wchodzą razem. Decyzja bez sprawdzenia nie jest przyjęta.

  4. Dodaj adr-lint do CI. Skrypt z sekcji o udowadnianiu, że decyzje nadal obowiązują (niżej na tej stronie), wywraca build, gdy ADR i jego sprawdzenia się rozjadą.

  5. Podsuń ADR-y do kontekstu każdego agenta. Użyj konfiguracji dla poszczególnych narzędzi opisanej niżej. Część wspólna to jeden blok instrukcji w AGENTS.md albo CLAUDE.md.

  6. Obejmij ADR-y i pliki reguł regułą code owners. Dodaj /docs/adr/, pliki konfiguracji reguł i scripts/adr-lint.mjs do CODEOWNERS z tech leadem jako właścicielem i włącz w regułach gałęzi wymóg review od code ownera. Bez tego ustawienia CODEOWNERS tylko prosi o review; nie blokuje merge’a.

  7. Naucz agenta zatrzymywać się i proponować. Gdy zadanie wymaga wyboru, którego nie obejmuje żaden ADR (nowa zależność, nowy magazyn danych, przekroczenie granicy), agent zapisuje docs/adr/NNNN-title.md ze status: proposed i się zatrzymuje. Człowiek przyjmuje, odrzuca albo poprawia propozycję.

  8. Zastępuj, nigdy nie edytuj. Gdy decyzja się zmienia, nowy ADR zastępuje stary, status starego zmienia się na superseded by ADR-NNNN, a reguły powołujące się na stary identyfikator zostają w tym samym pull requeście przemianowane albo usunięte. CI jest czerwone w tym pull requeście, dopóki tech lead nie ustawi w nim status: accepted nowego ADR-u, i właśnie ten czerwony stan jest bramką akceptacji.

Blok instrukcji jest taki sam we wszystkich trzech narzędziach. Umieść go w AGENTS.md albo w CLAUDE.md, jeśli zespół używa tylko Claude Code:

## Architecture decisions
- The accepted decisions are indexed in docs/adr/README.md. Before you edit a file,
read every accepted ADR whose scope matches it.
- A lint or dependency failure that cites `adr-NNNN-cN` is an architecture decision,
not a style nit. Fix the code; never edit the rule, its baseline or the ADR.
- If the task needs a new runtime dependency, a new data store or queue, a new public
API, or a change an ADR forbids: stop. Write docs/adr/NNNN-short-title.md with
`status: proposed`, the options you considered and the constraint you propose,
then report back without implementing.
- Never set an ADR's status to accepted. A human does that in review.

Narzędzia różnią się tym, jak niezawodnie właściwy ADR trafia do kontekstu.

Zaimportuj indeks w CLAUDE.md, żeby wczytywał się przy starcie. Claude Code rozwija importy @ścieżka do kontekstu na początku sesji, a ścieżka w backtickach zostaje zwykłym tekstem:

CLAUDE.md
@docs/adr/README.md

Potem daj każdemu często używanemu ADR-owi regułę ograniczoną do ścieżek. Plik w .claude/rules/ z polem paths wczytuje się dopiero wtedy, gdy Claude czyta pasujący plik, więc pełna treść ograniczeń trafia do kontekstu dokładnie wtedy, gdy jest potrzebna:

---
paths:
- "src/**/*.ts"
---
# ADR-0012 applies here
Outbound HTTP only through src/lib/http.ts (adr-0012-c1). Nothing under src/domain/
imports it (adr-0012-c2). Full decision: docs/adr/0012-outbound-http.md

Zapisz go jako .claude/rules/adr-0012-outbound-http.md. Oba mechanizmy opisuje dokumentacja pamięci Claude Code, sprawdzona względem Claude Code 2.1.283 26 września 2026. Jeśli trzymasz jeden AGENTS.md dla wszystkich narzędzi, Claude Code czyta go bezpośrednio, gdy projekt nie ma CLAUDE.md, od wersji 2.1.277 (kanał latest na 26 września 2026); w starszych wersjach wstaw @AGENTS.md do CLAUDE.md.

Żeby sprawdzić plan względem ADR-ów, zanim zmieni się jakikolwiek plik, uruchom sesję przez claude --permission-mode plan i użyj poniższego promptu do sprawdzenia planu. Żeby Claude nie edytował plików reguł, użyj reguł deny i hooka Stop ze strony o funkcjach dopasowania.

Skill grill-with-docs Matta Pococka zamienia pisanie szkicu w rozmowę: przepytuje cię o projekt i na bieżąco zapisuje uzgodnione decyzje w docs/adr/. Według migawki skills.sh z 26 września 2026 miał 1 046 834 instalacje (liczba z drugiej ręki, z lustra LinklyAI/best-skills). Zainstaluj go w Claude Code przez claude plugin install mattpocock-skills (cały plugin z 25 skillami, około 1600 tokenów opisów skilli na sesję; sprawdzisz to przez claude plugin details mattpocock-skills) albo dla Codeksa przez npx skills add mattpocock/skills --skill grill-with-docs grilling domain-modeling -a codex (dla Cursora -a cursor). Instaluj wszystkie trzy nazwy: grill-with-docs to jednolinijkowy wskaźnik na dwa pozostałe. Jego ADR-y nie mają sekcji Constraints, więc dopisz ją przed przyjęciem. Więcej skilli tego rodzaju porównuje strona o najlepszych skillach do praktyki programistycznej.

Sprawdzenie planu uruchamiaj w trybie planowania. Pierwszy i trzeci prompt zapisują tylko pliki, które same wskazują, a nic, co wytworzą, nie jest przyjęte bez decyzji człowieka; jeśli nowe reguły z pierwszego promptu trafią do CI, będą czerwone, dopóki ADR nie zostanie przyjęty. Czwarty edytuje pliki reguł, więc jego pull request człowiek przegląda jako zmianę reguł, przez code owners.

Nikt nie powinien ponownie czytać kodu, żeby potwierdzić, że ADR jest wciąż prawdziwy. Robią to trzy rzeczy: same reguły, sprawdzenie spójności między ADR-ami a regułami i zapis tego, kto co przyjął.

Reguły działają jako wymagane sprawdzenia CI w każdym pull requeście, tak jak na stronie o funkcjach dopasowania, razem z kanarkiem, który dowodzi, że reguła wciąż potrafi paść.

Sprawdzenie spójności to scripts/adr-lint.mjs. Pada, gdy przyjęty ADR nie ma ograniczeń, gdy ograniczenie nie ma ani Check:, ani Review:, gdy sprawdzenie wskazuje nieistniejący identyfikator reguły, gdy reguła powołuje się na ADR, który nie jest przyjęty, albo gdy ADR-u brakuje w indeksie:

#!/usr/bin/env node
// scripts/adr-lint.mjs: every accepted ADR constraint names a live check,
// and every check names an accepted ADR.
import { existsSync, readdirSync, readFileSync } from 'node:fs';
const DIR = 'docs/adr';
const ENFORCERS = ['eslint.config.js', '.dependency-cruiser.cjs']; // add pyproject.toml, ArchitectureTest.java…
const errors = [];
const accepted = new Set();
const index = readFileSync(`${DIR}/README.md`, 'utf8');
for (const file of readdirSync(DIR).filter((f) => /^\d{4}-.*\.md$/.test(f))) {
const text = readFileSync(`${DIR}/${file}`, 'utf8');
const id = file.slice(0, 4);
const status = text.match(/^status:\s*(.+)$/m)?.[1].trim() ?? 'missing';
if (!index.includes(`(${file})`)) errors.push(`${file}: not listed in ${DIR}/README.md`);
if (status !== 'accepted') continue;
accepted.add(id);
const section = text.split(/^## Constraints$/m)[1]?.split(/^## /m)[0] ?? '';
const bullets = section.split('\n').filter((l) => l.startsWith('- '));
if (bullets.length === 0) errors.push(`${file}: accepted ADR has no constraints`);
for (const line of bullets) {
const check = line.match(/Check: `([^`#]+)#([^`]+)`/);
if (check) {
const [, path, ruleId] = check;
if (!existsSync(path) || !new RegExp(`\\b${ruleId}\\b`).test(readFileSync(path, 'utf8')))
errors.push(`${file}: ${ruleId} is not defined in ${path}`);
} else if (!line.includes('Review:')) {
errors.push(`${file}: constraint has neither "Check:" nor "Review:": ${line.slice(0, 60)}`);
}
}
}
for (const path of ENFORCERS.filter((p) => existsSync(p))) {
for (const [, id] of readFileSync(path, 'utf8').matchAll(/adr-(\d{4})-c\d+/g))
if (!accepted.has(id)) errors.push(`${path}: rule cites ADR-${id}, which is not accepted`);
}
if (errors.length) {
console.error(errors.join('\n'));
process.exit(1);
}
console.log(`adr-lint: ${accepted.size} accepted ADRs, every constraint traced.`);

Uruchomiliśmy go 26 września 2026 w Node.js na przykładzie ADR-0012 z tej strony. Przeszedł na czystej konfiguracji i padł w każdym podłożonym przypadku: przy przemianowanej regule (adr-0012-c2 is not defined in .dependency-cruiser.cjs), przy zastąpionym ADR, którego reguły wciąż działały (rule cites ADR-0012, which is not accepted), i przy ograniczeniu bez źródła werdyktu. Dodaj go jako kolejny krok w jobie CI z funkcjami dopasowania: node scripts/adr-lint.mjs. Nie potrzebuje zależności ani klucza API.

Akceptacja dzieli się tak samo jak przy bramkach funkcji dopasowania:

KtoOdpowiada zaZatwierdza
Tech leadZestaw ADR-ów, indeks i pliki regułKażdą zmianę statusu ADR na accepted albo superseded, przez code owners
ZespółSamą decyzjęPull request z ADR, w zwykłym review, zanim ADR zostanie przyjęty
Programista albo agentZielone sprawdzenia; szkice ADR-ów w statusie proposedNic w przyjętych ADR-ach ani regułach
Recenzent (człowiek albo agent do review)Ograniczenia Review:Każdy pull request, który dotyka zakresu ADR

Trzy liczby mówią tech leadowi, czy system działa, a każdą da się odczytać z repozytorium: proponowane ADR-y na miesiąc (agenci zatrzymują się przy decyzjach, zamiast je podejmować), ograniczenia, które padły w tygodniu na pull requestach agentów (reguły żyją), i przyjęte ograniczenia oznaczone Review: (malejący udział oznacza, że coraz większa część architektury jest sprawdzana maszynowo). Te liczby stoją obok pakietu dowodów, który zespół czyta zamiast diffu.

Agent edytuje ADR, żeby pasował do jego kodu. Zmienia ograniczenie albo sam ustawia swojej propozycji status accepted. Jak z tego wyjść: code owners na docs/adr/, linia „never set accepted” w bloku instrukcji i review, które każdą zmianę w przyjętym ADR traktuje jak zmianę reguły. adr-lint wyłapuje regułę i ADR, które po takiej edycji przestały się zgadzać.

Agent spełnia literę, a łamie intencję. Opakowuje axios w plik src/lib/http2.ts albo przenosi I/O do folderu, którego reguła nie obejmuje. Jak z tego wyjść: pisz ograniczenia jako listę tego, co dozwolone („tylko src/lib/http.ts może importować undici”), a nie tego, co zakazane. W dependency-cruiser to reguła forbidden z from: { pathNot: '^src/lib/http\\.ts$' } i to: { path: 'node_modules/(undici|axios|got)' }, więc nowy http2.ts pada, gdy tylko zaimportuje klienta. Potem łataj lukę w regule tego samego dnia, w którym ją znajdziesz. Triage w review pull requesta agenta traktuje nowe pliki przy granicy jako sygnał ryzyka.

Katalog ADR-ów przerasta kontekst. Czterdzieści ADR-ów wczytywanych przy każdym zadaniu wypycha kod. Jak z tego wyjść: przy starcie wczytuj tylko indeks, każdy wiersz indeksu trzymaj w jednej linii, a pełne ADR-y wczytuj przez reguły ograniczone do ścieżek albo instrukcję „przeczytaj ADR, którego zakres pasuje”. Zastępuj śmiało: zastąpiony ADR znika z przyjętych wierszy indeksu.

Nieaktualny ADR sprawia, że agent „naprawia” poprawny kod. Kod poszedł dalej za zgodą zespołu, ale nikt nie zastąpił ADR-u, więc agent cofa zmianę, żeby była zgodna. Jak z tego wyjść: decyzja zmienia się tylko przez nowy ADR, w tym samym pull requeście co kod. Linia „Revisit when” daje tech leadowi powód do przeglądu każdego ADR-u, a prompt odtwarzający decyzje pokazuje, gdzie kod i ADR-y się rozjechały.

Każda sesja agenta zatrzymuje się, żeby zaproponować ADR. Lista wyzwalaczy jest za szeroka i zespół tonie w propozycjach. Jak z tego wyjść: zawęź ją do czterech wyzwalaczy z bloku instrukcji i napisz ADR-y dla wzorców, o które agent ciągle pyta. Jeśli to samo pytanie pada trzy razy, zespół ma niezapisaną decyzję.

Reguła istnieje, ale nikt nie pamięta dlaczego. Stara reguła lintera blokuje dobrą zmianę, a agent nie ma z czym dyskutować. Jak z tego wyjść: adr-lint odrzuca każdą regułę, która powołuje się na nieprzyjęty ADR, więc każda reguła adr- ma zapisany powód. W sporach agent zapisuje swoje argumenty w tym samym ARCH_DISPUTE.md, którego używa strona o funkcjach dopasowania, a decyzję podejmuje tech lead.

Na ścieżce tech leada następny krok to egzekwowanie tych ograniczeń jako bramek w CI.