Ship It With AI Mihai Cvasnievschi

Bucla în șase faze

29 min de citit

Ce este bucla agentică în șase faze?

Cele șase faze sunt Research, Plan, Execute, Review, Verify și Ship. Fiecare fază e un skill, în sensul anatomiei agentului - un set împachetat de instrucțiuni pe care agentul îl încarcă atunci când faza e activă. Fiecare fază are un input clar, un output clar și o predare clară către faza următoare.

Fiecare fază e gândită să aibă un gate la graniță. Implementarea concretă de azi din Superpowers folosește instrucțiunile din skill ca să ceară disciplina; pentru un gating impus strict, s-ar putea să trebuiască să cablezi un hook PreToolUse specific proiectului. Impunerea fazelor la nivel de kernel e încă în curs de maturizare la mijlocul lui 2026.

Bucla în șase faze, cu rutele de eșec înapoi la Plan 1Research 2Plan 3Execute 4Review 5Verify 6Ship plan eșuat? replanifici verify picat? înapoi la plan
Figura: Bucla în șase faze. Cele mai multe eșecuri se întorc la Plan, nu la Research.

Voi parcurge fazele în ordine, iar la final îți voi arăta cum arată totul când rulează cap-coadă pe o bucată reală de muncă.

Un principiu străbate toate cele șase faze: un rezultat bun are nevoie de o țintă bine definită. Agentul poate construi aproape orice îi descrii, dar nu poate ști la care lucru te-ai referit - a defini asta e treaba primelor faze ale buclei și e exact ce numesc fazele de mai târziu „spec-ul” și „intenția”. Research fixează ce poate și scoate la suprafață ce nu poate; tu tranșezi întrebările deschise pe care le ridică; planul transformă rezultatul stabilit în verificări per task; verify măsoară ce s-a construit față de el. Rezultatul ăsta nu-l ai complet înainte să începi - e un output al research-ului și al planului, șlefuit de fiecare dată când un verify picat se întoarce la Plan, iar pentru munca cu adevărat nouă definești ce poți și lași research-ul să închidă restul. Sari peste definire și restul buclei n-are pe ce se sprijini: review-ul n-are niciun spec cu care să compare diff-ul, verify n-are ce verifica, iar „gata” e orice a decis agentul.


Faza întâi: Research.

Agentul citește codebase-ul și produce o notă de research care stabilește starea curentă, numește fișierele relevante, identifică pattern-urile existente și semnalează riscurile. Input: descrierea task-ului. Output: un document markdown de două până la patru pagini.

Ce intră în nota de research? Fișierele care vor fi atinse. Convențiile pe care le urmează acele fișiere. Testele existente care acoperă zona. Concepte înrudite din alte părți ale codebase-ului care ar putea fi relevante. Întrebările deschise ale agentului - locurile în care codebase-ul e ambiguu și unde trebuie să decidă un om. Astea nu sunt fire rămase în aer. Sunt deciziile care definesc cum va arăta „gata”, scoase la suprafață acum ca să le tranșezi înainte ca planul să se lege de ele.

Research e faza peste care echipele sar cel mai des, pentru că nu produce cod și pare overhead. Research e și faza care, din experiența mea, are cel mai mare levier din toată bucla. O notă de research proastă garantează un plan prost, care garantează o implementare proastă. O notă de research bună face restul buclei mult mai ușor, pentru că planul e ancorat în starea reală a codului, nu în prima ipoteză a agentului despre starea codului.

Research-ul, așa cum e descris, scoate la suprafață necunoscutele codebase-ului. Există o mișcare simetrică pentru ale tale, și contează cel mai mult când task-ul e în afara domeniului tău. Înainte de research-ul propriu-zis, cere-i agentului un blind spot pass: „Adaug un provider de autentificare nou și nu știu nimic despre modulele de auth din codebase-ul ăsta - ajută-mă să-mi găsesc unknown unknowns, ca să te pot prompta mai bine.” Rezultatul nu e o notă de research; e o listă cu întrebările pe care nu știai să le pui, și costă un minut. Împerechează mișcarea cu un obicei care li se pare nefiresc inginerilor seniori: spune cu voce tare care ți-e nivelul de experiență. Agentul își calibrează output-ul după expertiza pe care o deduce, și o deduce din vocabularul tău, nu din golurile tale. Declară-te fluent în domeniu și își va lăsa presupunerile implicite - exact acolo unde se ascund cele greșite. Declară ce nu știi de fapt și presupunerile ajung scrise negru pe alb, unde le poți vedea și le poți respinge.

Artefactul de research e durabil. Ajunge în commit alături de modificare. Șase luni mai târziu, când alt developer lucrează pe cod adiacent și vrea să știe „de ce e structurat lucrul ăsta așa”, nota de research e acolo. E memoria instituțională pe care echipa n-o avea înainte.


Faza a doua: Plan.

Agentul citește nota de research și produce un plan la nivel de fișier. Fiecare task din plan numește fișierul de modificat, modificarea de făcut și verificarea care dovedește că modificarea a funcționat. Fiecare task e dimensionat la două-cinci minute de muncă - destul de mic încât un eșec să fie recuperabil, destul de mare încât overhead-ul comutării între task-uri să nu domine.

Planul numește și ce teste trebuie adăugate sau actualizate. Dacă planul nu pomenește de teste, planul e incomplet și agentul se întoarce la treabă. Ideea e ca regula asta să fie impusă printr-un hook; instrucțiunile din skill cer rigoarea, iar impunerea strictă e ceva ce cablezi tu, per proiect, pe măsură ce maturitatea echipei o justifică.

Planul spune și ce înseamnă „gata” pentru întreaga modificare - rezultatul față de care va măsura verify - nu doar verificările per task. Un plan care numește fișiere, task-uri și teste, dar nu spune niciodată ce ar trebui să obțină modificarea, a descompus munca fără s-o definească; contractul outer-loop din Anexa B.6 impune o linie „Done când” la nivelul buclei exterioare, iar bucla interioară are nevoie de același lucru la scara unei singure modificări.

Planul e gate-ul unde un reviewer uman contează cel mai mult. Citești planul. Respingi task-urile prea vagi, prea mari sau prost ordonate. Adaugi task-urile pe care planul le-a ratat. Scoți task-urile care ies din scop. Agentul revizuiește. Tu aprobi. Abia apoi începe execute.

Review-ul de plan ia câteva minute. Te scutește de o după-amiază pierdută în ziua în care planul era greșit și ai fi descoperit asta abia în execute - de unde e mult mai greu de dat înapoi.


Faza a treia: Execute.

Aici își câștigă pâinea componenta principală recursivă din Capitolul 1 - subagenții. Execute e faza în care orchestratorul trimite în lucru mai mulți agenți-copil constrânși, fiecare lucrând la un task delimitat, în propriul context izolat.

Agentul trimite câte un subagent per task. Fiecare subagent lucrează în propriul context izolat - o trăsătură arhitecturală cheie, pentru că contaminarea contextului e cel mai mare motiv pentru care sesiunile lungi de agent o iau razna. Raționamentul confuz din task-ul unu nu poluează foaia curată a task-ului patru. Fiecare subagent citește doar ce are nevoie, face modificarea care i-a fost atribuită, rulează pasul de verificare din plan și raportează înapoi. Agentul-orchestrator asamblează rezultatele.

Execute e faza care produce cod vizibil pe ecran. E și faza care beneficiază cel mai mult de izolare. Fără izolarea subagenților, o schimbare cu opt task-uri într-o singură sesiune de agent se termină cu un context window îndesat cu codul a opt task-uri, rezultate parțiale, output de debugging și un agent care ia decizii în task-ul șapte pe baza unei amintiri deformate a deciziilor din task-ul doi. Cu izolare, fiecare task pornește proaspăt. Fiecare task e mic. Fiecare task reușește sau eșuează pe propriile merite.

Dacă un task eșuează, orchestratorul decide dacă reîncearcă, ocolește eșecul sau se oprește și întreabă omul. Cele mai multe eșecuri sunt recuperabile - prima încercare a agentului a ratat un detaliu pe care nota de research îl semnalase, a doua încercare încorporează corecția. Unele eșecuri sunt blocante - task-ul, așa cum a fost planificat, nu poate fi dus la capăt, iar planul trebuie revizuit. Orchestratorul le deosebește pe cele două.

Ce nu rezolvă izolarea subagenților: contaminarea la nivelul orchestratorului. Orchestratorul tot ține rezumate ale muncii fiecărui subagent, iar dacă rezumatul lui despre rezultatul task-ului unu e imprecis, subagentul task-ului patru poate face o presupunere care contrazice ceva ce task-ul unu chiar a stabilit. Am văzut cu ochii mei o fază de execute cu șase subagenți producând editări reciproc inconsistente exact din motivul ăsta. Izolarea e reală și valoroasă; nu e o soluție-minune. Orchestratorul rămâne un punct unic de context, iar rezumatele lui rămân un loc pe unde se poate strecura deriva. Citește mesajele de predare a task-urilor din orchestrator cu același scepticism cu care ai citi update-urile de standup ale unui inginer junior.

Costul conex e medierea, atunci când subagenți rulați în paralel fac editări conflictuale. Medierea ieftină: orchestratorul detectează că două ramuri au atins același fișier în moduri incompatibile, renunță la ramura mai târzie și o rerulează secvențial, cu output-ul primei ramuri pasat ca context. Medierea scumpă: orchestratorul rezumă schimbările aflate în conflict, cere unui model mai capabil să aleagă merge-ul corect, apoi îl reaplică. Cele mai multe conflicte sunt ieftine. Unele nu sunt, iar cele scumpe mănâncă exact câștigul de viteză pentru care ai paralelizat.

Costul de coordonare apare ca mediere de conflicte - rerularea unei ramuri abandonate, sau plata unui model mai capabil care să aleagă un merge - și e mărginit. Marginea: cu cât task-urile subagenților sunt mai independente, cu atât rata de conflict e mai mică. Modul de a-i ține independenți e să delimitezi pe fișier sau pe modul, nu pe feature. Șase subagenți care editează fiecare câte un fișier - sigur. Șase subagenți care editează toți același feature, pe fișiere care se suprapun - rețeta pentru cazul scump, de fiecare dată. Din experiența mea, echipele care se lovesc de problema asta trimit de obicei prea mulți subagenți pentru cât e de fapt de lucru. Trei subagenți bine delimitați termină mai repede decât opt care se calcă pe picioare, de fiecare dată.

Tot în execute se întâlnește agentul cu guvernanța. Fiecare tool call trece prin gate-ul de permisiuni. Fiecare comandă Bash trece prin hook-urile de securitate. Fiecare scriere de fișier trece prin sandbox. Dacă agentul încearcă ceva ce stratul de guvernanță nu permite, acțiunea e blocată, agentul raportează înapoi orchestratorului, orchestratorul decide cum merge mai departe. Rigoarea trăiește în straturile de sub execute; execute doar rulează munca.

Încă un artefact aparține fazei ăsteia. Research-ul produce o notă; planul produce un plan; execute, așa cum a fost descris până acum, produce doar cod. Adaugă un fișier de note de implementare ținut din mers: fiecare loc în care implementarea a trebuit să devieze de la plan și de ce, fiecare edge case descoperit în mijlocul task-ului și nemenționat de plan, fiecare decizie pe care un subagent a luat-o acolo unde planul a lăsat-o deschisă. Notele nu-l costă pe agent aproape nimic și plătesc de două ori. La review, reviewerul de conformitate cu spec-ul le citește primele - fișierul e o listă de mărturisiri cu exact locurile în care diff-ul și planul nu se pun de acord, adică exact ce există reviewerul ăla să găsească. Și sunt antidotul pentru drift-ul de rezumate al orchestratorului numit mai sus: devierea e consemnată în momentul în care se întâmplă, de subagentul care a făcut-o, în loc să supraviețuiască doar ca o linie comprimată într-un mesaj de hand-off. Planul e harta; notele sunt teritoriul care raportează înapoi.


Faza a patra: Review.

Doi revieweri. În secvență.

Întâi, conformitatea cu spec-ul. Agentul citește nota de research originală, planul aprobat și diff-ul real. Răspunde la o singură întrebare: implementarea corespunde spec-ului? Dacă da, o spune. Dacă nu, semnalează decalajul. Conformitatea cu spec-ul e o competență diferită de calitatea codului. O modificare poate fi cod de calitate care face lucrul greșit. O modificare poate fi cod urât care face exact lucrul corect. Reviewerul de spec se ocupă doar de prima dimensiune.

Apoi, calitatea codului. Un agent diferit. Un prompt diferit. Citește doar diff-ul. Întreabă: e cod bun, după standardele echipei? Naming. Stil. Edge case-uri. Acoperirea cu teste. Tratarea erorilor. Considerații de performanță. Comentează pe diff așa cum ar face-o un reviewer senior.

Motivul pentru care le desparți în doi revieweri e că, făcute simultan, amândouă ies mai prost. Un reviewer care întreabă în același timp „corespunde spec-ului?” și „e bine scris?” tinde să le amestece. Spec-ul ajunge cântărit prin prisma calității codului, sau calitatea codului prin prisma conformității cu spec-ul, și pierzi semnalul distinct pe care trebuia să-l dea fiecare. Doi revieweri, două preocupări, zero amestec.

Output-ul fazei de review e structurat. Fiecare constatare are o severitate. Constatările critice blochează ship-ul. Cele importante se repară înainte de ship. Sugestiile se notează în descrierea PR-ului. Agentul rezolvă automat constatările blocante și pe cele importante (în limitele planului) și scoate sugestiile la suprafață, ca să decidă reviewerul uman.


Cum faci review pe un diff scris de agent?

Un diff scris de agent eșuează altfel decât unul scris de om, așa că îl citești în altă ordine. Un diff de om eșuează la execuție - o greșeală de tastare, un off-by-one, edge case-ul pe care autorul l-a uitat - și vânezi greșeala linie cu linie, pentru că acolo o lasă un om obosit. Un diff de agent sosește fără astea. Compilează, trece de lint, se citește ca un cod idiomatic pe care echipa ta l-ar face merge fără niciun comentariu. Eșuează cu un strat mai sus, la intenție și context - o regulă de business plauzibilă și greșită, codul corect pus în stratul greșit - și niciuna dintre astea nu se anunță singură pe pagină. Un bug de agent arată ca acel cod pe care un inginer bun l-ar scrie pentru un task ușor diferit. Fluența nu e corectitudine, iar cititul pe fluență nu-l va prinde.

Așa că petrece primele zece minute deasupra codului, nu în el. Începe cu diff-stat-ul raportat la plan, înainte de o singură linie de implementare: forma schimbării se potrivește cu forma cererii? Un fișier atins pe care planul nu l-a numit niciodată e primul semnal, nu o notă de subsol - un diff care depășește scopul e agentul care decide ceva ce nu i-ai cerut să decidă.

Citește apoi testele, și citește ce afirmă, nu dacă trec. Verdele e cel mai ieftin semnal din diff și cel pe care îl ai deja. Un test care afirmă ce face implementarea în loc de ce cerea intenția va trece și tot va fi greșit; faza de Verify revine la asta, la de ce testele agentului merită o a doua citire.

Apoi verifică granițele despre care echipa ta a scris reguli - pattern-urile interzise din AGENTS.md, convențiile de strat, modulele periculoase de atins. Agentul încalcă o convenție sigur pe el și în stil fluent, așa că o trecere de graniță nu arată greșit; arată curat, exact ce cititul pe stil trece cu vederea. Și dă grep pe fiecare nume nou pe care-l introduce diff-ul - fiecare API, funcție sau cheie de config pe care n-o recunoști - aceeași verificare încrucișată pe care Capitolul 6 o rulează împotriva invenției sigure pe ea, pentru că apelul care nu există se citește la fel de plauzibil ca cel care există.

Abia acum, linie cu linie. Ăsta e stratul mecanic pe care cei doi revieweri de mai sus l-au măturat deja - conformitatea cu spec-ul, calitatea codului - așa că nu le repeți trecerea; cheltuiești minutele pe care ți le-au cumpărat pe cele două lucruri pe care ei nu le pot judeca, corectitudinea de business și potrivirea arhitecturală. Aici iese la suprafață regula de business plauzibilă și greșită, și aici un idiom învechit din versiunea de framework pe care modelul o știe cel mai bine se citește ca un cleanup și ajunge în producție ca o regresie. Citirea nu dispare pe măsură ce tooling-ul se îmbunătățește. Devine mai scurtă și mai ascuțită, țintită pe erorile de intenție care supraviețuiesc tuturor filtrelor din amonte - iar când se degradează în schimb într-o privire fugară la bifele verzi, pattern-ul patru din Capitolul 9 stăpânește ce se întâmplă mai departe.

Există un test care arată dacă citirea chiar s-a întâmplat, și agentul îl poate administra. Înainte să aprobi, pune-l să-ți dea un quiz despre modificare: ce se întâmplă la margini, ce modul deține comportamentul nou, ce se strică primul dacă presupunerea de sub task-ul trei e greșită. Trei-patru întrebări, un minut. Dacă poți răspunde, aprobarea înseamnă ceva. Dacă nu poți, nu făceai review - dădeai rubber-stamp cu pași în plus, și e mai bine să afli asta la gate decât în producție. Degradarea din pattern-ul patru e invizibilă din interior; quiz-ul o face măsurabilă.

Anexa B.8 e ordinea asta de citire într-o singură pagină.


Faza a cincea: Verify.

Faza de Verify e locul unde rulează testele. Mai exact, rulează testele noi - testele care exersează modificarea. Suita de teste existentă rulează deja în execute (orice task care modifică cod rulează testele existente relevante, ca să se asigure că nu a stricat nimic). Verify e despre întrebarea dacă modificarea e cu adevărat corectă - corectă față de rezultatul pe care l-ai definit în research și în plan - nu doar dacă testele existente încă trec.

Pentru logica de backend, verify înseamnă de obicei teste unitare și teste de integrare. Planul a numit ce teste trebuie adăugate; faza de Execute le-a adăugat; verify le rulează și raportează rezultatele.

Pentru codul de frontend, verify devine mai interesant. Testarea de frontend a fost dintotdeauna grea - testele de UI sunt fragile, testele snapshot sunt casante, QA-ul manual nu scalează. Workflow-ul agentic are aici un răspuns adevărat, și e unul dintre lucrurile care mă entuziasmează cel mai tare. Răspunsul: Playwright cu accessibility tree.

Playwright cu accessibility tree înseamnă următorul lucru. Playwright e o bibliotecă de automatizare de browser. Pilotează un browser real (headless sau vizibil) printr-o secvență de interacțiuni. Accessibility tree e structura pe care browserele o întrețin pentru tehnologiile asistive - screen readere, control vocal și restul. Accessibility tree descrie pagina în termeni semantici: există un buton cu eticheta asta, există un câmp de formular etichetat „email”, există o listă de elemente cu numele astea. Accessibility tree e stabil. Nu se schimbă când restilizezi pagina, pentru că etichetele și rolurile nu se schimbă. Refactor de CSS? Accessibility tree e același. Schimbi biblioteca de componente? Accessibility tree e același.

Verify, în workflow-ul agentic, scrie teste pe accessibility tree, nu pe pixeli și nu pe selectoare CSS. Testul spune „navighează la pagina de profil a utilizatorului, găsește câmpul etichetat Priority, schimbă-i valoarea, apasă Save, verifică faptul că noua valoare se afișează”. Testul ăsta trece indiferent dacă UI-ul e stilizat cu Tailwind, cu Bootstrap, cu Material sau cu nimic. Testul trece indiferent dacă acel câmp e implementat ca select dropdown, ca radio group sau ca o componentă custom. Testul afirmă comportamentul - adică exact ce te interesează.

Rulez asta cu echipe din banking în mod constant. Au în spate istorii lungi de automatizări de teste UI eșuate - teste flaky, suite casante, ingineri juniori care pierd săptămâni vânând diff-uri de snapshot. Pattern-ul cu accessibility tree e primul lucru care, din experiența mea, ține suitele de teste UI verzi luni și ani la rând. Agentul scrie testele. Testele supraviețuiesc refactor-urilor. Echipa are încredere în semnalul verde.


Poți avea încredere în testele scrise de agent?

O suită de teste verde scrisă de agent e un indiciu, nu o dovadă.

E un indiciu că modificarea face ce spune testul. Nu e o dovadă că testul spune ce trebuie. Exemplul lucrat de mai târziu din acest capitol face decalajul concret: task-ul de audit log a livrat un test care trecea și care verifica vechiul format de log. Verde - și greșit. Suita era fericită. Comportamentul era incorect. Nimic în afară de Review nu l-a prins, pentru că nimic altceva nu se uita la ce pretindea testul - doar la dacă trece.

Procentul de coverage nu închide decalajul ăsta; îi lărgește iluzia. Coverage-ul măsoară ce linii s-au executat, nu dacă s-a verificat ceva cu sens. Un agent care optimizează pentru un gate de coverage va scrie teste care apelează codul, nu afirmă nimic de substanță și fac cifra verde. Primești metrica, nu și siguranța. Un coverage mare pe teste scrise de agent îți spune că acel cod a rulat în timpul testului. Nu îți spune că acel cod e corect.

Testele de caracterizare au aceeași formă de limitare, numită în Capitolul 8: fixează comportamentul curent, nu corectitudinea. Sunt cu adevărat valoroase - o plasă de siguranță contra regresiilor, care îi permite agentului să refactorizeze fără să schimbe pe tăcute ce face codul. Dar vor conserva un bug la fel de fidel cum conservă un feature. O suită de caracterizare care e verde după un refactor demonstrează că nu ai schimbat comportamentul. Nu spune nimic despre dacă acel comportament a fost vreodată corect.

Așa că disciplina e cea evidentă, aplicată acolo unde echipele uită s-o aplice: fă review pe testele agentului cu aceeași seriozitate cu care faci review pe codul agentului. Citește ce afirmă testele, nu doar dacă trec. Mai ales pentru logica de backend, un om sau un al doilea agent ar trebui să verifice aserțiunile față de spec - față de ce trebuie să facă acel cod - nu față de implementarea care se nimerește să le stea în față. Un test scris pornind de la implementare va fi de acord cu implementarea. Exact ăsta e modul de eșec. Aserțiunea trebuie să vină din intenție.


Faza a șasea: Ship.

Ship e faza care produce artefactul pe care îl preia procesul normal de review al echipei tale. Agentul face commit cu un mesaj structurat. Dă push pe branch și deschide un pull request cu o descriere structurată: ce s-a schimbat, de ce, cum s-a verificat, ce riscuri rămân, ce revieweri sunt etichetați. Dacă la început a fost legat un ticket de Jira, agentul actualizează ticketul. Dacă notificările de Slack sunt cablate, agentul postează pe canalul relevant.

Ship durează treizeci de secunde. E faza cea mai ușoară. E și faza care face restul buclei digerabil pentru echipă, pentru că artefactul produs de agent - pull request-ul - e exact artefactul pe care echipa e deja obișnuită să-l revizuiască. Nu există o „bandă specială pentru AI” în repository-ul tău. Există același proces de review de PR prin care trece orice modificare. Reviewerul citește diff-ul, citește descrierea, citește nota de research din linkul atașat descrierii, citește rezultatele testelor, aprobă sau cere modificări. Ca de obicei.

Asta e proprietatea care face ca livrarea cu agenți să funcționeze în practică. Agentul nu îți rupe procesul existent. Agentul îți alimentează procesul existent cu muncă mai bine formulată.


Bucla completă, pe un feature mic, ia în jur de douăzeci-treizeci de minute de timp total, cu ceas. Pe un feature mediu, o oră. Pe unul mare, câteva ore - iar feature-ul mare ar fi luat zile fără agent, deci comparația e în favoarea ta.

Totalul include și timpul de procesare al agentului, și timpul tău de review la gate-urile umane. Agentul în sine rulează poate o treime până la jumătate din timpul total; restul ești tu citind nota de research, tu revizuind planul, tu aprobând diff-ul, tu privind cum trece pasul de verify. Gate-urile umane sunt limitatorul de ritm într-un workflow sănătos, nu agentul. Dacă bucla ta ia trei ore pe un feature mic, problema e aproape sigur că gate-urile sunt supra-inginerite sau că le faci într-un du-te-vino lent în loc de o singură trecere concentrată. Agentul nu te salvează de propria cultură a ședințelor.

Fricțiunea față de „lasă pur și simplu agentul să scrie codul” e timpul de gate - nota, planul, review-ul de diff - și e mărginită. Beneficiul față de „livrează cod fără rigoare” e substanțial.


Timpii buclei la repetiție nu sunt timpii buclei în producție. Am învățat asta dintr-un demo pe care l-am rulat pentru echipa unui client la începutul acestui an. Planul demo-ului prevedea o rulare de architecture review care producea un raport HTML dintr-un repo proaspăt în aproximativ patru minute. La repetiție, cu AGENTS.md-ul agentului pre-încărcat și cu căile din repo deja în cache, patru minute erau fezabile. Prima încercare live, în fața echipei, a luat opt minute per pane și a pornit un cronometru pe răbdarea publicului pe care îl simțeam ticăind din fața sălii. A doua încercare live, două zile mai târziu, în altă sală, a luat zece minute.

Pattern-ul nu era un bug. Era diferența previzibilă dintre o rulare cu cache cald și una pornită la rece. Disciplina pe care ar fi trebuit s-o construiesc în planul demo-ului de la bun început e aceeași disciplină pe care o predă capitolul ăsta: presupune că variabila contează, planifică pentru timpii cei mai proști, ai un fallback pregătit pentru momentul în care sistemul live îți spulberă bugetul. Pattern-ul de recuperare pe care îl folosesc acum la fiecare demo are două straturi: un artefact de fallback pre-generat, într-un branch de git pe care îl pot scoate cu un checkout în două secunde, și o sesiune reluabilă, pe care o pot continua din starea de la repetiție dacă sesiunea live îngheață. Niciunul nu e spectaculos. Amândouă au eliminat modul de eșec al demo-urilor live pe care îl tot improvizam de un an.


Un exemplu lucrat.

Ca să facem bucla concretă, iată un feature care curge prin toate cele șase faze. Feature-ul e mic: adaugă un câmp priority pe recordul Wire, într-un serviciu bancar reglementat. Priority e una dintre valorile low / normal / high / urgent, are default normal, iar flag-ul urgent declanșează un queue separat de compliance review.

Research. I-am cerut agentului să citească codebase-ul și să producă o notă de research. Nota a numit patru fișiere pe care nu le-aș fi găsit nici într-o oră de grep: recordul Wire în sine, directorul de migrații, serviciul queue-ului de compliance review și emitter-ul de audit log. A ridicat și o întrebare deschisă: priority să fie enum sau text liber, dat fiind că spec-ul reglementatorului folosește text liber în unele documente și enum în altele. Am ales enum. Alegerea asta nu era un detaliu - definea ținta față de care fazele de mai târziu aveau să verifice modificarea.

Plan. Agentul a produs un plan de șase task-uri, în ordine: adaugă coloana în baza de date, cu default; actualizează clasa recordului Wire; actualizează serviciul wire-builder; actualizează contractul de API; actualizează logica de rutare pe compliance ca să citească noul câmp; actualizează emitter-ul de audit log. Fiecare task era constrâns la un fișier sau la o pereche de fișiere. La review am prins o singură chestiune: task-ul cinci depindea de schimbarea de contract de API din task-ul patru, dar ordinea era corectă și agentul marcase dependența în descrierea task-ului. Aprobat.

Execute. Șase subagenți în paralel, câte unul per task, fiecare constrâns la fișierul lui. S-au întors în mai puțin de trei minute. Cinci task-uri au avut teste care treceau din prima. Al șaselea (emitter-ul de audit log) avea un test care trecea, dar testul era greșit - verifica vechiul format de log. Prins la Review.

Review. Reviewerul de conformitate cu spec-ul a prins faptul că testul task-ului de audit log verifica vechiul format. A semnalat și că migrației îi lipsea direcția de down. Reviewerul de calitate a codului n-a găsit nimic notabil. Subagentul implementator a reparat ambele puncte și a rerulat testele relevante.

Verify. Agentul a rulat suita completă de teste (3.400 de teste), un smoke test pe serviciul de rutare compliance din staging și a produs un diff al schimbării de contract de API pentru review-ul reglementatorului. Toate verzi. Timp total de agent: 47 de minute, de la research la verify.

Ship. PR deschis cu nota de research, planul, rapoartele per task, review-urile de conformitate cu spec-ul și de calitate a codului și dovezile din teste atașate. Reviewerul senior a petrecut unsprezece minute pe PR, a pus o singură întrebare (dacă flag-ul urgent ar trebui să fie vizibil în dashboard-ul de metrici - lucru la care nu mă gândisem) și a aprobat. Merged. Tot feature-ul, de la „hai să adăugăm un câmp de prioritate” la cod în merge, a luat nouăzeci de minute de ceas, cumulat între agent și mine.

Nouăzeci de minute, nu cele douăzeci sau treizeci pe care le citam pentru un feature mic - diferența e contextul reglementat: o suită de 3.400 de teste, un smoke test pe staging și un diff de contract pentru reglementator. Mic ca scop nu înseamnă mic ca ceremonie. Și tot nu minutele sunt ideea; artefactele sunt. Fiecare pas a produs ceva ce un reviewer senior poate audita. Bucla e disciplina care convertește capabilitatea agentului în muncă pe care o pot apăra.


Toată bucla, dintr-o privire:

Faza Artefactul Gate-ul uman Eșecul prins
Research Nota de research (2-4 pagini) Verificare de plauzibilitate pe domeniu Context lipsă
Plan Plan de task-uri la nivel de fișier Review de scop și ordine Descompunere proastă
Execute Diff + rapoarte per task Niciunul sau lejer Drift de implementare
Review Rapoarte de conformitate cu spec-ul + calitate Review de senior Cod greșit sau slab
Verify Dovezi din teste (failing -> passing) Review de QA sau de owner Eșec comportamental
Ship PR cu lanțul de dovezi Procesul normal de PR Încălcare de proces

Sidebar: echipa care a livrat cu jumătate de buclă.

Ceremonia completă nu e mereu doza potrivită, iar dacă aș pretinde contrariul, mi-ai retrage încrederea prima dată când ai vedea o echipă prosperând fără ea. O echipă pe care am urmărit-o a rulat livrare cu agenți aproape un an cu ceea ce părea jumătate de buclă. Research-ul era un fir de comentarii pe ticket. Planul era trei bullet-uri în descrierea PR-ului. Fără note de research, fără agenți de review, fără gate-uri formale. Velocitatea a crescut. Defectele nu.

A funcționat datorită a trei condiții, iar condițiile sunt lecția. Echipa era mică, senioră și își construise singură codebase-ul, deci funcția de research era aproape gratuită - contextul pe care o notă de research există ca să-l asambleze era deja în capetele lor. Suita de CI era cu adevărat strictă, deci funcția de verify rula la fiecare push, fie că o numea cineva fază, fie că nu. Iar cultura de PR era deja serioasă, deci review-ul se întâmpla, cu discernământ, pentru că așa fusese dintotdeauna.

Uită-te la lista aia: research, verify, review. Funcțiile n-au dispărut. Erau construite în pereții echipei, așa că forma explicită era redundantă. Asta e lectura onestă a buclei - nu e un preț pe care îl plătești ca să folosești agenți; e forma explicită a șase funcții care trebuie să se întâmple undeva. O echipă care a mutat o parte din funcții în pereții ei - în infrastructură, în cultură - poate merge mai lejer exact acolo, și nicăieri altundeva.

Testul e contabilitate, nu optimism. Pentru fiecare fază peste care vrei să sari, numește lucrul care îi face deja treaba. Dacă nu-l poți numi, faza rămâne.


O precizare de vocabular înainte să mergem mai departe, pentru că termenul „buclă” începe să fie suprasolicitat în domeniu. Cele șase faze de aici sunt bucla interioară (inner loop): o unitate de muncă, șase funcții, cu gate-uri ținute de tine. Mai există și o buclă exterioară (outer loop), tot mai răspândită - reinvocarea agentului la interval sau pe un queue, fără nimeni între iterații, până când o condiție e îndeplinită. Acela e un instrument diferit, cu precondiții diferite, și e pattern-ul final din Capitolul 9. Dependența curge într-un singur sens: o buclă exterioară e exact atât de sigură cât e mecanizarea funcțiilor pe care le rerulează, pentru că ea compune orice disciplină - sau orice absență - pe care o împachetează.


Igiena contextului

Fiecare fază din bucla asta rulează înăuntrul unui context window, iar fereastra e memoria de lucru a agentului. Tot ce e încărcat în ea - system prompt-ul, fișierele citite, rezultatele tool-urilor, conversația de până acum - concurează pentru aceeași atenție mărginită de care agentul are nevoie ca să raționeze. Capitolul 1 a numit limita și a spus că ferestrele mai mari doar ridică plafonul; igiena contextului e cum lucrezi înăuntrul ei. Capitolul ăsta a numit deja contaminarea contextului drept cel mai mare mod de eșec al sesiunilor lungi. Asta e practica ce o previne.

Prima disciplină e să încarci ce cere task-ul și să faci referire la rest. Pointere, nu payload-uri. Documentul de arhitectură e pus ca link în AGENTS.md, nu lipit în el; nota de research numește fișierele care contează și unde să le găsești, în loc să le pună conținutul inline. Bugetul de două sute de linii pentru AGENTS.md din Capitolul 6 e aceeași disciplină aplicată stratului mereu-încărcat - liniile care se încarcă la începutul fiecărei sesiuni sunt spațiul cel mai scump din fereastră, așa că ori își merită locul, ori dispar.

Granița dintre sesiuni e instrumentul. O unitate de muncă per sesiune. Artefactele pe care bucla asta le trece în commit - nota de research, planul, rapoartele per task - există tocmai ca sesiunea următoare să pornească curată și să citească din repository starea de care are nevoie, în loc să târască după ea istoricul cât o conversație întreagă. Context proaspăt per unitate de muncă e forma din bucla interioară a ceea ce face pattern-ul opt la fiecare iterație; argumentul buclei exterioare e al Capitolului 9.

Contaminarea se anunță singură, dacă stai cu ochii pe ea. Patru semne. Agentul răspunde din nou la o întrebare pe care o rezolvase deja mai devreme în sesiune. Citează o versiune învechită a unui fișier pe care l-a editat acum o oră. Uită o constrângere pe care o respecta acum douăzeci de minute. Editările lui devin tot mai neglijente pe măsură ce sesiunea se lungește. Când vezi asta, nu te certa cu sesiunea - nu poți readuce un context window la coerență prin dispută. Dă commit la starea durabilă, încheie sesiunea, pornește curat. Sesiunea proaspătă nu e progres pierdut; e chiar progresul, recitit din repository, fără zgomot.

Compactarea e o predare, nu o continuare. Când harness-ul rezumă o fereastră plină ca să facă loc, pierde detalii - asta înseamnă să rezumi - așa că tratează o sesiune compactată așa cum ai trata predarea muncii tale unui inginer nou în prag: tot ce contează și nu e scris într-un fișier până atunci s-a pierdut. Subagenții sunt cealaltă jumătate a instrumentului, izolând fiecare task în propria lui fereastră, ca confuzia unui task să nu ajungă niciodată la următorul. Rezumatele lor de predare se citesc cu același scepticism pe care faza de execute îl cere deja pentru cele ale orchestratorului.

Anexa B.7 e disciplina asta într-o singură pagină.


Plugin-ul Superpowers la care am tot făcut referire e o implementare a buclei interioare. Există și altele - Spec Kit de la GitHub, framework-uri BMAD, colecții de skill-uri construite de echipe pentru uz propriu. Diferă în detalii. Împărtășesc pattern-ul buclei iterative. Alege ce se integrează cu workflow-ul tău, cu tool-urile tale, cu constrângerile tale de conformitate. Vehiculul contează mai puțin decât disciplina.

Capitolul următor: artefactul care face disciplina portabilă între membrii echipei, între repository-uri și în timp. AGENTS.md.