Kódovať po srsti: zručnosť, ktorá zastaví AI kódovacích agentov v napučiavaní vášho repozitára

Publikované dňa Sep 22, 2026 autorom Štefan Moravík.
AI Agents Claude Code Developer Tools Code Quality
Na tejto stránke 8 min čítania
  1. 1Krátka verzia
  2. 2Zlyhanie, pre ktoré je to určené
  3. 3Grain
  4. 4Ponytail
  5. 5Ako prinútiť agenta, aby to naozaj robil
  6. 6Čo sa stalo v repozitári, vrátane tej časti, ktorá nefungovala

Krátka verzia

  • AI kódovací agenti sú dobrí v pridávaní kódu a zlí v tom, aby si všimli, že ten kód už existuje. Ak ich necháte bez dozoru, dajú repozitáru druhého pomocníka ku každému prvému a každý čitateľ musí skontrolovať oboch, aby mohol veriť ktorémukoľvek.
  • Riešením sú dva návyky zapísané tak, aby ich agent dodržal. Grain: nájdi najbližší existujúci príklad tej istej veci a zrkadli jeho tvar, umiestnenie a názvy. Ponytail: vystúp po rebríku od “musí to vôbec existovať” po “minimum, ktoré funguje”, a zastav na prvom priečku, ktorý udrží.
  • Obe sú teraz verejnou zručnosťou s licenciou MIT: grain-skill na GitHube . Obsahuje pravidlá pre tvorbu, recenzný priechod s pevnými značkami a podobu záverečného riadku, ktorý prinúti agenta pomenovať, čo zrkadlil.
  • V našom hlavnom repozitári od augusta: 386 issue a pull requestov nesie plánovací komentár, ktorý pomenúva vzor na zrkadlenie, naprieč 1 333 commitmi do stromu s približne 18 000 súbormi. 35 miest v kóde nesie komentár ponytail:, ktorý pomenúva zámernú simplifikáciu a jej cestu k vylepšeniu.
  • Nepríjemné zistenie: agent vyvolal túto zručnosť ako zručnosť nula raz. Pravidlá fungovali preto, lebo som ich dal aj do projektového CLAUDE.md, do definícií worker agentov a do recenzného checklistu. Dajte pravidlo tam, kde agent už číta.

Písal som o tom už raz a výsledok sa mi nepáčil, pretože opisoval princíp a nie mechanizmus. Toto je verzia s mechanizmom.

Zlyhanie, pre ktoré je to určené

Tri príklady z nášho backendu, všetky skutočné, všetky z pull requestov napísaných agentom, ktoré prešli svojimi testami.

Nová REST routa, ktorá si vytiahla aplikačnú službu priamo z továrne. Každá sesterská routa v repozitári ide routa → controller → service → repository, pričom každý skok je injektovaný. Táto skolabovala reťaz na routa → service. Fungovalo to. Znamenalo to však aj to, že jediné miesto, kde pre túto funkciu žije validácia požiadaviek a tvarovanie odpovedí, neexistovalo, a ďalší agent, ktorý sa funkcie dotkol, mal na výber dva tvary.

Predimenzovaná služba rozdelená na _payloads.py, _protocol.py a _tokens.py, každý z nich modul holých async def, pričom služba volá protocol.discover(...) cez import. Kontrola dĺžky súboru prešla na zeleno. To, čomu má dependency injection zabrániť, sa vrátilo okamžite: spolupracovník zvolený v čase importu, nenahraditeľný bez patchovania modulu, chýbajúci v konštruktore, ktorý dokumentuje, na čom služba závisí.

Druhý normalizátor. Jeden už existoval. Agent ho nenašiel, napísal ďalších osem riadkov, ktoré robili takmer to isté, a teraz si dve funkcie s odlišným správaním v okrajových prípadoch nárokujú kanonizovať to isté pole.

Žiadny z nich nie je bug v tom zmysle, v akom ho zachytí test. Každý je prípadom agenta, ktorý zvolil kód, ktorý dokázal vygenerovať, namiesto kódu, ktorý existoval. Urobte to naprieč niekoľkými stovkami pull requestov a repozitár prestane mať tvar.

FlowHunt Logo

Pripravení rozšíriť svoje podnikanie?

Začnite svoju 30-dňovú skúšobnú verziu ešte dnes a vidzte výsledky behom pár dní.

Grain

Nový kód by mal byť na nerozoznanie od kódu okolo neho. Zručnosť mení túto vetu na päť krokov, ktoré agent vykoná predtým, než začne písať.

Najprv nájdi vzor. Pre endpoint, službu, repozitár, query hook, store slice alebo komponent nájdi najbližší existujúci a skopíruj jeho tvar, umiestnenie súboru a pomenovanie. Nevymýšľaj štruktúru, keď vzor existuje. V našom repozitári je slice branding pomenovaným vzorom pre backend, pretože je malý, čistý a pokrýva každú vrstvu, a tabuľka v zručnosti hovorí pre každý typ artefaktu, ktorý súbor otvoriť a čo zrkadliť.

Rešpektuj vrstvy. Presentation volá application, application volá domain a infrastructure implementuje domain. Nový import naprieč týmito líniami neprejde architektonickou kontrolou. Prečítaj si dokument o vrstvách, neodvodzuj ho nanovo.

Lokálny grain proti grain repozitára. Prispôsob sa svojim sesterským súborom. Ak sa však samotné sesterské súbory odchyľujú od kanonickej reťaze, nasleduj kanonickú reťaz a odchýlku poznamenaj, namiesto toho, aby si kopíroval drift. “Zhoduje sa s ostatnými piatimi routami v tomto súbore” nestačí, ak všetkých šesť preskakuje vrstvu, ktorú kanonický slice používa. Porovnával si príliš lokálne.

Znovu použi kanonického pomocníka. Ak pomocník, typ alebo vzor už v repozitári žije, použi ho. Dva normalizátory nútia každého čitateľa porovnať oba.

Názvy nesú význam. Znovu použi slovník, ktorý už v kóde je. Nový názov pre existujúci koncept je bug, ktorý čaká na čitateľa.

Test na konci je ten, ktorý dávam recenzentom: ak dokážete len podľa tvaru povedať, ktoré riadky napísal agent, išlo to proti srsti.

Ponytail

Lenivý znamená efektívny, nie nedbalý. Najlepší kód je ten, ktorý nikdy nenapíšeme. Najprv dôkladne pochop problém — každý súbor, ktorého sa zmena dotkne, skutočný end-to-end tok — a potom vystúp po tomto rebríku a zastav na prvom priečku, ktorý udrží.

Rebrík lenivosti: musí to vôbec existovať, už je to v kódovej základni, štandardná knižnica, natívna funkcia platformy, nainštalovaná závislosť, jeden riadok, a až potom minimum kódu, ktoré funguje

S rebríkom idú ruka v ruke dve pravidlá.

Oprava bugu je koreňová príčina, nie symptóm. Ticket pomenúva symptóm. Prehľadaj grepom každého volajúceho funkcie, ktorej sa chystáš dotknúť. Jedna kontrola v zdieľanej funkcii je menší diff než kontrola v každom volajúcom, a zalátanie len tej cesty, ktorú pomenúva ticket, necháva sesterských volajúcich pokazených.

Udržuj diff minimálny. Diff je to, čo recenzia číta. Žiadne refaktory mimochodom, žiadne premenovania, žiadne preformátovanie, žiadne vylepšenia typu “keď už som tu”, žiadne dotýkanie sa súborov, ktoré úloha nevyžadovala. Každé z nich zakopáva skutočnú zmenu. Ak je diff väčší než problém, zrež ho. Vylepšenia, ktoré si si všimol, sú follow-up issue, nie extra commity na tejto vetve.

A limity, pretože “lenivý” je slovo, ktoré sa najpravdepodobnejšie prečíta nesprávne. Nikdy nezjednodušuj preč validáciu vstupov na hranici dôvery, ošetrenie chýb, ktoré zabraňuje strate dát, bezpečnosť, základy prístupnosti ani nič, o čo používateľ požiadal. Nikdy nebuď lenivý v porozumení: rebrík skracuje riešenie, nikdy čítanie. Malý diff na nesprávnom mieste je druhý bug. Netriviálna logika po sebe necháva jednu spustiteľnú kontrolu, tú najmenšiu vec, ktorá zlyhá, ak sa logika pokazí.

Keď agent zámerne zvolí priečku a pozná strop, povie to v kóde:

# ponytail: global lock, per-account locks if throughput matters

V našom repozitári je ich teraz 35. Každý je rozhodnutie, ktoré by budúci čitateľ inak musel rekonštruovať, a značka, kam sa pozrieť, keď sa narazí na strop.

Ako prinútiť agenta, aby to naozaj robil

Princíp v dokumente nie je správanie. Tieto dva premenili na správanie tri mechanizmy a zoradil by som ich v tomto poradí.

Zadanie nesie vzor. V architektonickom vzore hlavný model píše zadanie pre workera a pole Design v zadaní pomenúva najbližší existujúci vzor na zrkadlenie a minimálnu zmenu riešiacu koreňovú príčinu. Worker nemusí grain hľadať. Dostane ho. Naprieč naším repozitárom to sú tých 491 plánovacích komentárov pri 386 issue a pull requestoch: plánovací krok, ktorý pomenúva, čo zrkadliť, skôr než niekto začne písať.

Agent končí tým, čo zrkadlil. Správa každého implementátora končí jedným riadkom, mirrored: <path>, alebo pomenuje nový vzor a dôvod, prečo sa žiadny sesterský nehodil. Je to lacné a je to najlepšia recenzná pomôcka, akú som pridal. Riadok mirrored: ukazujúci na nesprávny typ súboru vám povie, že diff je zlý, ešte predtým, než ho otvoríte. Chýbajúci riadok vám povie, že agent sa nepozrel.

Recenzia vynucuje rovnakú latku, v pevnom poradí. Naša recenzná zručnosť má dva priechody s pevnými značkami a práve značky robia zistenia porovnateľnými medzi recenzentmi a medzi agentmi.

Dva recenzné priechody: priechod štruktúry označuje diverge, duplicate, layer, misplaced, reach-in, inconsistent, own a chain; priechod škrtania označuje delete, stdlib, native, yagni a shrink. Štruktúra ide prvá, pretože konzistencia poráža škrtanie

Najprv štruktúra. Odchyľuje sa to od najbližšieho vzoru, duplikuje to existujúceho pomocníka, prekračuje to vrstvu, sedí to na nesprávnom mieste, siaha to do vnútorností iného modulu, používa to nekonzistentné názvy, privlastňuje si to niečo, čo by malo injektovať, alebo to láme kanonickú reťaz volaní? Potom škrtanie. Čo by sa dalo vymazať, nahradiť štandardnou knižnicou, nahradiť natívnou funkciou, vyhodiť ako špekulatívne alebo zmenšiť?

Poradie je pravidlo, nie preferencia. Konzistencia poráža škrtanie. Škrtnutie, po ktorom kód zostane odchýlený od svojich sesterských súborov, nie je výhra, pretože čitateľ sa teraz musí naučiť dva tvary, aby ušetril osem riadkov. Spustite najprv štruktúru a priechod škrtania sa dotkne len kódu, ktorý už sedí.

Čo sa stalo v repozitári, vrátane tej časti, ktorá nefungovala

Od 1. augusta náš hlavný repozitár prijal 1 333 commitov, väčšinu z nich napísal agent pod recenziou. 386 issue a pull requestov v tomto období nesie plánovací komentár, ktorý pomenúva vzor na zrkadlenie, celkovo 491 takých komentárov. Kanonická reťaz je predvoleným tvarom nového endpointu a dve staršie routy, ktoré preskakujú controller, sú v dokumente uvedené ako odchýlka, ktorá sa ruší, nie ako druhý štýl.

Tých 35 komentárov ponytail: je menšie číslo, než som očakával, a myslím, že je to správne. Väčšina zjednodušení nestojí za komentár. Tie, ktoré áno, sú tie, ktoré majú strop.

Teraz tá časť, ktorú by som radšej neuvádzal. Vydal som grain a ponytail ako zručnosť pre Claude Code: popis v indexe zručností, telo, ktoré sa načíta na požiadanie, a riadok v CLAUDE.md hovoriaci, aby ju vyvolal pred písaním kódu. Naprieč piatimi týždňami prepisov agent vyvolal túto zručnosť podľa mena nula raz. Záverečný riadok mirrored: sa objavil v siedmich odpovediach.

Pravidlá sa napriek tomu dostali do praxe. Dostali sa preto, lebo ten istý text bol aj na troch miestach, ktoré agent číta bez toho, aby si to vybral: v projektovom CLAUDE.md, ktorý je v kontexte od prvého ťahu; v definíciách worker agentov, ktoré hovoria “zrkadli tvar, umiestnenie a pomenovanie najbližšieho existujúceho príkladu” a “siahnite po najlenivejšom riešení, ktoré naozaj funguje” ako pravidlá, nie ako zručnosť na zváženie; a v recenznom checkliste, ktorého značky neprepustia pull request, ktorý ich ignoruje. Telo zručnosti sa stalo kanonickým odkazom, na ktorý tieto tri ukazujú. Ako spúšťač neurobilo nič.

Takže lekcia, ktorú by som odovzdal každému, kto balí konvencie pre agenta, je táto. Zručnosť je dobré miesto pre dlhú verziu pravidla. Je zlým miestom pre samotné pravidlo, pretože agent sa musí rozhodnúť, že ju načíta, a väčšinou to neurobí. Dajte jednoodstavcovú verziu do súboru, ktorý je vždy v kontexte, dajte imperatívnu verziu do definície agenta, ktorý píše kód, a dajte kontrolu do recenzie, ktorá prepúšťa merge. Potom všetky tri nasmerujte na zručnosť pre detaily.

Verejná verzia na github.com/LivinTribunal/grain-skill je usporiadaná týmto spôsobom: krátky SKILL.md s pravidlami, ktoré agent udrží v hlave, plný dokument s rebríkom a anti-vzormi, recenzné značky a README, ktoré hovorí, ktorý odsek patrí do vášho CLAUDE.md a ktorý do definície vášho implementátora. Nahraďte rozpracovaný príklad vlastným kanonickým vzorom a je hotovo.

Najčastejšie kladené otázky

Štefan je AI a softvérový inžinier, ktorý vyvíja FlowHunt. Okrem samotného produktu navrhuje agentic software-engineering workflows pre vývojárov, ktoré znižujú vývojové náklady a zvyšujú kvalitu kódu.

Štefan Moravík
Štefan Moravík
AI & Softvérový Inžinier

Dajte svojim agentom konvencie, ktoré váš tím už dodržiava

FlowHunt vám umožňuje pripojiť pravidlá, príklady a recenzné kroky, ktoré má agent dodržiavať, ku každému workflow, aby jeho výstup zodpovedal kódu, do ktorého sa dostane.