I-ați dat lui Claude Code un proiect necunoscut și ați primit răspunsul: "Istoricul este păstrat în browser, reține ultimele 100 de înregistrări și este restaurat după reîncărcare". Sună suficient de concret ca să copiați afirmația în README. Dar mai întâi merită să deschideți sursele pe care se bazează răspunsul.

Vom analiza o astfel de concluzie: vom transforma cerința în întrebări, vom citi un fragment scurt de cod și vom stabili ce comportament trebuie verificat la rulare. La final veți avea un raport concis, din care reiese ce funcționează și ce mai trebuie verificat.

O singură cerință, nu o trecere în revistă a întregului proiect

Haiku 50 este o aplicație mică ce generează poezii din trei versuri pe baza unor cuvinte-cheie. Utilizatorul alege limba, primește textul și vede istoricul generărilor. Pentru analiza noastră este suficientă o singură cerință: ultimele 100 de generări trebuie să fie păstrate în browser și disponibile după reîncărcarea paginii.

Ilustrație pentru Haiku 50. Mai jos vom analiza comportamentul aplicației prin cod și scenarii.

Aici, Haiku 50 este un exemplu de studiu. Codul și răspunsurile agentului sunt pregătite pentru analiză; deducem comportamentul așteptat din cod. Nu verificăm arhiva originală a proiectului. Articolul conține tot ce vă trebuie: nu va fi nevoie să descărcați aplicația, să obțineți o cheie API sau să porniți generatorul.

În loc să cerem "explică-mi cum funcționează totul aici", vom pune trei întrebări. Este salvată o generare nouă în stocare? Citește aplicația datele salvate la următoarea deschidere? Ce se întâmplă când sunt mai mult de o sută de înregistrări?

Prima solicitare pentru Claude Code ar putea arăta astfel:

Analizează doar istoricul generărilor. Nu modifica încă codul.
Găsește traseul de la obținerea unei poezii noi până la salvarea ei,
apoi traseul de la deschiderea paginii până la afișarea istoricului.
Verifică unde este limitat numărul de înregistrări salvate.
Pentru fiecare concluzie, indică fișierul, liniile și un fragment scurt.
Enumeră separat ce mai trebuie verificat prin rulare.

O astfel de solicitare delimitează clar căutarea. Dacă agentul descoperă că istoricul are legătură cu alt fișier, poate explica de ce merită citit și acela. Iar dumneavoastră veți putea verifica mai ușor câteva locuri-cheie decât întregul rezumat al aplicației.

Trimiterea la un fișier nu înlocuiește citirea lui

Să presupunem că avem fișierul didactic history.js. După o generare reușită, interfața apelează addToHistory(item), iar renderHistory doar afișează lista primită. În acest exemplu nu există alți gestionari ai istoricului.

const STORAGE_KEY = "haiku-history";
let history = [];

function addToHistory(item) {
  history.unshift(item);
  localStorage.setItem(STORAGE_KEY, JSON.stringify(history));
  renderHistory(history.slice(0, 100));
}

function startHistory() {
  renderHistory(history);
}
startHistory();

Pentru a citi fragmentul, este suficient să deosebiți două locuri de stocare. Tabloul history trăiește în memoria paginii deschise. localStorage păstrează datele site-ului în browser între deschideri; aplicația trebuie să le scrie explicit acolo și apoi să le citească înapoi. Stocarea este legată de protocol, gazdă și port, așa că la verificare trebuie să păstrați aceeași adresă și același profil de browser. Comportamentul este descris în documentația localStorage.

Să presupunem că agentul a răspuns:

Istoricul păstrează ultimele 100 de generări și este restaurat
după reîncărcare. Sursă: history.js:4-13,
sunt folosite localStorage și slice(0, 100).

Avem calea și liniile. Acum să verificăm dacă ele confirmă toată afirmația. În fișierul didactic, prima linie începe cu const STORAGE_KEY; și liniile goale sunt incluse în numerotare.

  • linia 5, history.unshift(item), adaugă o înregistrare nouă la începutul tabloului;
  • linia 6, apelul localStorage.setItem, scrie întregul tablou în stocare. Conversia în JSON este necesară pentru a-l salva ca șir;
  • linia 7, renderHistory(history.slice(0, 100)), trimite primele 100 de elemente spre afișare. slice creează un tablou nou și nu îl scurtează pe cel original, după cum se arată în documentația acestei metode;
  • la pornire, linia 2, let history = [], creează un tablou gol, iar funcția startHistory și apelul ei de la liniile 10-13 îl afișează. Aici nu se citește nimic din stocare.

După ce citim codul, răspunsul se schimbă: codul prevede salvarea istoricului și limitează afișarea la o sută de elemente. În această implementare nu există restaurare la pornire și nici nu am găsit o limită pentru numărul de înregistrări salvate.

Într-un proiect real, fragmentul s-ar putea să nu fie suficient: încărcarea datelor poate fi mutată într-un alt modul. De aceea, merită să-i cereți agentului: "Arată toate locurile unde se citește și se scrie această cheie și cine apelează aceste funcții". În exemplul nostru didactic cunoaștem limitele analizei, așa că putem continua.

Verificați comportamentul după reîncărcare

Citirea codului ne-a indicat unde să căutăm discrepanța. Acum stabilim condițiile observației. Pagina este deschisă într-un profil obișnuit de browser, la aceeași adresă, salvarea este permisă, iar istoricul este inițial gol. În scenariul didactic apare o generare reușită, cu eticheta recognoscibilă A; codul nu se schimbă între pași.

Mai jos este evoluția așteptată a scenariului pe baza codului. Să adăugăm încă un pas: după reîncărcare obținem o înregistrare nouă B.

PasCe așteptăm pe ecranCe așteptăm în stocare pentru cheia haiku-history
Am deschis pagina cu istoricul golListă goalăNu există înregistrări
Am adăugat generarea AO înregistrare ATablou cu înregistrarea A
Am reîncărcat aceeași paginăListă goalăTabloul cu înregistrarea A a rămas
Am adăugat generarea B după reîncărcareDoar înregistrarea BTablou doar cu B; înregistrarea A a fost suprascrisă

Pentru o observație reală, puteți vedea conținutul stocării în instrumentele pentru dezvoltatori ale browserului, în secțiunea de stocare a datelor site-ului. Deschideți valoarea unei chei concrete și comparați înregistrarea cu cea pe care tocmai ați adăugat-o. Lista goală de pe ecran nu este suficientă.

Afirmația "după reîncărcare, totul a fost șters" ar fi inexactă. Datele au rămas în stocare, dar aplicația nu le-a citit. În această implementare, legătura se întrerupe între șirul salvat și tabloul trimis spre afișare.

Următoarea adăugare arată consecința acestei erori. După reîncărcare, tabloul din memorie este gol, așa că va conține doar B, iar localStorage.setItem va înlocui istoricul salvat cu un tablou cu o singură înregistrare. Conform cerinței, ar trebui să rămână B și A; codul păstrează doar B. Problema afectează atât afișarea, cât și păstrarea istoricului.

Putem formula deja concluzia pe baza codului: "În startHistory nu se citește istoricul salvat; următoarea adăugare va suprascrie înregistrările anterioare". Pentru a confirma comportamentul la rulare, parcurgeți toți cei patru pași și comparați după fiecare lista de pe ecran cu conținutul stocării.

Verificați limita de 100

Am lămurit restaurarea. Cerința mai are o parte: păstrarea ultimelor 100 de generări. O singură înregistrare nu poate verifica această limită.

Să folosim un scenariu separat, cu istoricul gol. Vom transmite pe rând aceleiași funcții de adăugare 101 înregistrări pregătite, etichetate de la 1 la 101, fără reîncărcare între adăugări. Nu trebuie să facem 101 solicitări către generator pentru a verifica istoricul: aici ne interesează comportamentul după ce înregistrarea este deja obținută.

Înregistrarea nouă ajunge la începutul tabloului. Prin urmare, după ultima adăugare, pe ecran vor apărea etichetele de la 101 la 2, în total 100. Dar salvarea a primit tabloul întreg: în stocare vor rămâne etichetele de la 101 la 1, în total 101. Trebuie verificat atât numărul, cât și conținutul înregistrărilor. Altfel, riscați să nu observați că aplicația păstrează cele mai vechi în locul celor mai recente.

Aici răspunsul agentului a generalizat prea mult. Numărul 100 chiar apare în cod, dar se referă la afișare. Concluzia exactă pe baza codului: "Interfața afișează ultimele 100 de înregistrări; în scenariul prezentat, stocarea conține 101, așadar cerința privind dimensiunea istoricului salvat nu este îndeplinită".

Ce parte a aplicației verifică scenariul

Înregistrările pregătite ne permit să verificăm separat istoricul. Ele nu spun nimic despre disponibilitatea serviciului de generare, calitatea poeziilor sau transmiterea limbii selectate. Pentru aceste cerințe sunt necesare scenarii separate.

Pregătiți un raport scurt

Este util să salvați rezultatul investigației lângă proiect, ca să nu recitiți dialogul mâine. În exemplu, vom numi fișierul HANDOFF_REVIEW.md. Numele este doar orientativ; mai important este să puteți reconstitui pașii verificării din raport.

Iată raportul bazat pe citirea codului didactic. Câmpul cu comportamentul așteptat indică ce trebuie urmărit la rulare:

Domeniu: istoricul generărilor, versiunea didactică history.js din articol.
Metodă de analiză: citirea fragmentului didactic.
Nu s-a rulat aplicația în browser.

Cerință: păstrarea ultimelor 100 de generări în browser
și afișarea lor după reîncărcare.

Conform codului:
- history.js:6, localStorage.setItem, salvează întregul tablou;
- history.js:7, renderHistory(history.slice(0, 100)),
  limitează doar afișarea;
- history.js:10-13, startHistory și apelul ei,
  afișează lista fără să citească datele salvate.

Comportament așteptat pe baza codului:
- după adăugare, înregistrarea A apare pe ecran și în stocare;
- după reîncărcare, A rămâne în stocare, iar lista este goală;
- adăugarea lui B după reîncărcare înlocuiește istoricul salvat:
  rămâne doar B, nu B și A;
- într-un scenariu separat, după 101 adăugări pornind de la o stare goală,
  pe ecran vor fi 100 de înregistrări (101..2), în stocare 101 (101..1).

Discrepanțe conform codului: istoricul nu este restaurat la pornire,
așa că următoarea adăugare va suprascrie istoricul anterior;
istoricul salvat nu este limitat la ultimele 100 de înregistrări.

Neverificat: funcționarea generatorului, erorile de salvare,
funcționarea simultană în mai multe file.

Pasul următor: reproduceți ambele scenarii și notați observațiile.
Apoi corectați citirea la pornire și limitarea tabloului salvat,
după care repetați aceleași scenarii.

În propriul raport, înlocuiți "versiunea didactică" cu versiunea verificată a proiectului, de exemplu commit-ul și existența modificărilor necomise. După rulare, adăugați un câmp separat, "Observații efective", și atașați rezultatele sau o notă despre pașii efectuați manual. Comparați-le cu comportamentul așteptat; dacă nu ați putut rula aplicația, lăsați câmpul necompletat și adăugați o mențiune corespunzătoare. Aici, toate datele necesare sunt în articol; într-un proiect mare, doar trimiterile la linii nu vor fi suficiente pentru a repeta verificarea.

Un astfel de raport vă ajută să formulați următoarea sarcină pentru agent. Agentul are deja două discrepanțe concrete, nu o solicitare vagă de tipul "fă istoricul mai fiabil". În plus, este clar ce concluzii ar fi premature.

Verificați singuri concluzia

În aceeași implementare didactică, am adăugat un buton de ștergere. Gestionarul lui arată astfel:

function clearHistory() {
  history = [];
  renderHistory(history);
}

Înainte de apăsare, în listă și în stocare exista înregistrarea A. După apăsare, lista a devenit goală. Agentul a scris: "Butonul șterge complet istoricul salvat".

Ce concluzie este confirmată: istoricul a dispărut de pe ecran, înregistrarea a fost ștearsă din localStorage sau ambele? Și ce ar trebui verificat în continuare? Încercați să răspundeți înainte de explicație.

Explicație

Este confirmată dispariția listei de pe ecran. Codul arată și resetarea tabloului din memorie. Totuși, gestionarul nu modifică localStorage, iar renderHistory doar afișează lista, conform condiției, așa că A rămâne în stocare.

Următoarea verificare este să citiți valoarea cheii haiku-history imediat după apăsare. După implementarea restaurării istoricului, merită și să reîncărcați pagina pentru a vă asigura că înregistrările șterse nu reapar. În varianta inițială, o singură reîncărcare nu ar ajuta: și fără ștergere, aceasta afișează o listă goală la pornire. Iată un detaliu care poate încurca verificarea.

Cum formulați astfel de sarcini pentru Claude Code

Într-un proiect de lucru, începeți cu o singură afirmație care vă influențează următoarea decizie. De exemplu, dacă istoricul poate fi folosit sau dacă trebuie mai întâi reparată restaurarea lui. Dați-i agentului un format de răspuns în care să fie ușor să deschideți sursa și să verificați concluzia:

Verifică afirmația: [comportamentul concret al aplicației].
Mai întâi găsește fișierele relevante și citește locurile necesare.
Nu modifica încă codul.

Răspunde cu:
1. Ce confirmă codul: fișier, linii, fragment scurt.
2. Ce scenariu verifică comportamentul la rulare.
3. Ce s-a executat efectiv și ce s-a observat.
4. Concluzia exactă și necunoscutele rămase.

Dacă aplicația nu poate fi rulată, spune clar acest lucru.
Nu prezenta scenariul propus ca pe o verificare efectuată.

După răspuns, deschideți sursele concluziilor-cheie, comparați observația cu cerința și abia apoi transferați rezultatul în notițe sau documentație. Dacă sursa nu este suficientă, următoarea solicitare este deja clară: găsirea locului unde se citește istoricul, verificarea valorii cheii, repetarea scenariului cu 101 înregistrări. Astfel, analiza avansează prin pași mici, ușor de verificat.

Pentru o întrebare simplă despre numele unei funcții, este suficientă trimiterea la cod. Când răspunsul implică salvarea datelor, restaurarea sau limita de dimensiune, merită să urmăriți comportamentul până la capăt. Amploarea verificării depinde de ceea ce urmează să afirmați.