Damar Yönünde Kod: AI Kodlama Ajanlarının Deponuzu Şişirmesini Durduran Yetenek

Sep 22, 2026 tarihinde Štefan Moravík tarafından yayınlandı.
AI Agents Claude Code Developer Tools Code Quality
Bu sayfada 8 dakika okuma
  1. 1Kısa özet
  2. 2Bunun çözdüğü başarısızlık
  3. 3Damar
  4. 4Ponytail
  5. 5Bir ajana bunu gerçekten yaptırmak
  6. 6Depoda ne oldu, işe yaramayan kısım dahil

Kısa özet

  • AI kodlama ajanları kod ekleme konusunda iyidir, ancak kodun zaten var olduğunu fark etme konusunda kötüdür. Kendi hâline bırakıldıklarında, bir depodaki her ilk yardımcı fonksiyon için bir ikincisini üretirler ve her okuyucu birine güvenmek için ikisini de kontrol etmek zorunda kalır.
  • Çözüm, bir ajanın takip edebilmesi için yazıya dökülmüş iki alışkanlıktır. Damar: aynı türden en yakın mevcut örneği bul ve onun şeklini, yerini ve adlarını yansıla. Ponytail: “bunun var olması gerekiyor mu” sorusundan “işleyen minimum"a uzanan bir merdiveni tırman ve tutan ilk basamakta dur.
  • İkisi de artık MIT lisanslı, herkese açık bir yetenek: GitHub’da grain-skill . İçinde yazım kuralları, sabit etiketli bir inceleme geçişi ve ajanın neyi yansıladığını adlandırmasını sağlayan kapanış satırının şekli var.
  • Ağustos’tan bu yana ana depomuzda: 386 issue ve pull request, yansılanacak örneği adlandıran bir plan yorumu taşıyor; toplamda yaklaşık 18.000 dosyalık bir ağaca yapılan 1.333 commit boyunca. Kodda 35 yerde, bilinçli bir basitleştirmeyi ve yükseltme yolunu adlandıran bir ponytail: yorumu var.
  • Rahatsız edici bulgu: ajan, yeteneği bir yetenek olarak sıfır kez çağırdı. Kurallar işe yaradı çünkü onları ayrıca projenin CLAUDE.md dosyasına, worker ajan tanımlarına ve inceleme kontrol listesine koydum. Kuralı, ajanın zaten okuduğu yere koyun.

Bu konuda daha önce bir kez yazdım ve sonucu beğenmedim, çünkü ilkeyi anlatıyordu, mekanizmayı değil. Bu, mekanizmayı içeren sürüm.

Bunun çözdüğü başarısızlık

Backend’imizden üç örnek; hepsi gerçek, hepsi testlerini geçen ajan yazımı pull request’lerden.

Uygulama servisini doğrudan bir factory’den çeken yeni bir REST route. Depodaki her kardeş route, route → controller → service → repository şeklinde ilerliyor ve her sıçrama enjekte ediliyor. Bu route ise zinciri route → service’e indirdi. Çalıştı. Ama aynı zamanda o özellik için istek doğrulama ve yanıt şekillendirmenin yaşadığı tek yer artık yoktu ve o özelliğe dokunacak bir sonraki ajanın seçebileceği iki şekil vardı.

_payloads.py, _protocol.py ve _tokens.py olarak bölünmüş aşırı büyük bir servis; her biri çıplak async def‘lerden oluşan bir modül ve servis protocol.discover(...)‘ı import üzerinden çağırıyor. Dosya uzunluğu kontrolü yeşile döndü. Bağımlılık enjeksiyonunun engellemek için var olduğu şey doğrudan geri geldi: import anında seçilen, modülü patch’lemeden yerine konulamayan ve servisin neye bağlı olduğunu belgeleyen constructor’da bulunmayan bir işbirlikçi.

İkinci bir normalizer. Zaten bir tane vardı. Ajan onu bulamadı, neredeyse aynı işi yapan sekiz satır daha yazdı ve şimdi farklı uç durum davranışlarına sahip iki fonksiyon da aynı alanı kanonikleştirdiğini iddia ediyor.

Bunların hiçbiri bir testin yakalayacağı anlamda bir bug değil. Her biri, bir ajanın var olan kod yerine üretebileceği kodu seçmesi. Bunu birkaç yüz pull request boyunca yapın ve depo artık bir şekle sahip olmaktan çıkar.

FlowHunt Logo

İşinizi büyütmeye hazır mısınız?

Bugün ücretsiz denemenizi başlatın ve günler içinde sonuçları görün.

Damar

Yeni kod, etrafındaki koddan ayırt edilemez olmalıdır. Yetenek, bu cümleyi bir ajanın yazmadan önce attığı beş adıma dönüştürüyor.

Önce örneği bul. Bir endpoint, servis, repository, query hook, store dilimi veya component için en yakın mevcut olanı bul ve onun şeklini, dosya konumunu ve adlandırmasını kopyala. Bir desen varsa yapı icat etme. Depomuzda branding dilimi, küçük, temiz ve her katmana yayıldığı için backend’in adlandırılmış örneği; yeteneğin tablosu da her yapı türü için hangi dosyanın açılacağını ve neyin yansılanacağını söylüyor.

Katmanlara saygı göster. Presentation application’ı çağırır, application domain’i çağırır ve infrastructure domain’i implemente eder. Bu çizgiler arasında yeni bir import, mimari kontrolünden geçemez. Katmanlar dokümanını oku, yeniden türetme.

Yerel damar, depo damarına karşı. Kardeşlerinle eşleş. Ama kardeşler de kanonik zincirden sapıyorsa, sapmayı kopyalamak yerine kanonik zinciri izle ve sapmayı not et. “Bu dosyadaki diğer beş route ile eşleşiyor” yeterli değil, eğer altısı da kanonik dilimin kullandığı bir katmanı atlıyorsa. Çok yerel karşılaştırdın.

Kanonik yardımcıyı yeniden kullan. Bir helper, tip veya desen zaten depoda varsa onu kullan. İki normalizer, her okuyucuyu ikisini de diff’lemeye zorlar.

Adlar anlam taşır. Koddaki mevcut kelime dağarcığını yeniden kullan. Var olan bir kavram için yeni bir ad, bir okuyucuyu bekleyen bir bug’dır.

Sondaki test, gözden geçirenlere verdiğim test: hangi satırları ajanın yazdığını yalnızca şekillerinden anlayabiliyorsanız, o kod damara karşı gelmiştir.

Ponytail

Tembellik verimlilik demektir, dikkatsizlik değil. En iyi kod, hiç yazılmayan koddur. Önce problemi tam olarak anla: değişikliğin dokunduğu her dosyayı, gerçek uçtan uca akışı. Sonra bu merdiveni tırman ve tutan ilk basamakta dur.

Tembellik merdiveni: var olması gerekiyor mu, zaten kod tabanında mı, standart kütüphane mi, yerel platform özelliği mi, kurulu bağımlılık mı, tek satır mı ve ancak ondan sonra işleyen minimum kod

Merdivenle birlikte gelen iki kural var.

Bir bug düzeltmesi bir semptom değil, kök nedendir. Bir ticket bir semptomu adlandırır. Dokunmak üzere olduğun fonksiyonun her çağıranını grep’le. Paylaşılan fonksiyondaki tek bir guard, her çağırandaki bir guard’dan daha küçük bir diff’tir ve yalnızca ticket’ın adlandırdığı yolu patch’lemek kardeş çağıranları bozuk bırakır.

Diff’i minimal tut. İncelemenin okuduğu şey diff’tir. Yol üstü refactor yok, yeniden adlandırma yok, yeniden biçimlendirme yok, “buradayken şunu da yapayım” iyileştirmeleri yok, görevin gerektirmediği dosyalara dokunmak yok. Her biri gerçek değişikliği gömer. Diff problemden büyükse, onu kırp. Fark ettiğin iyileştirmeler bu dalda ekstra commit’ler değil, bir takip issue’sudur.

Ve sınırlar, çünkü en çok yanlış anlaşılabilecek kelime “tembel”. Bir güven sınırındaki girdi doğrulamayı, veri kaybını önleyen hata işlemeyi, güvenliği, erişilebilirlik temellerini veya kullanıcının istediği herhangi bir şeyi asla basitleştirip atlama. Anlama konusunda asla tembel olma: merdiven çözümü kısaltır, asla okumayı değil. Yanlış yerdeki küçük bir diff ikinci bir bug’dır. Önemsiz olmayan mantık geride çalıştırılabilir bir kontrol bırakır; mantık bozulursa başarısız olan en küçük şey.

Ajan bir basamağı bilerek seçtiğinde ve tavanı biliyorsa, bunu kodda söyler:

# ponytail: global kilit, verim önemliyse hesap başına kilitler

Depomuzda şu anda bunlardan 35 tane var. Her biri, gelecekteki bir okuyucunun aksi hâlde yeniden kurgulamak zorunda kalacağı bir karar ve tavan aşıldığında nereye bakılacağını gösteren bir işaret.

Bir ajana bunu gerçekten yaptırmak

Bir dokümandaki ilke, bir davranış değildir. Bu ikisini davranışa dönüştüren üç mekanizma var ve onları şu sıraya koyardım.

Brief örneği taşır. Architect deseninde ana model bir worker için bir brief yazar ve brief’in Design alanı, yansılanacak en yakın mevcut deseni ve minimal kök neden değişikliğini adlandırır. Worker’ın damarı bulması gerekmez. Ona verilir. Depomuz genelinde 386 issue ve pull request üzerindeki 491 plan yorumu tam olarak budur: kimse yazmadan önce neyin yansılanacağını adlandıran bir planlama adımı.

Ajan, neyi yansıladığıyla kapanır. Her uygulayıcının raporu tek bir satırla biter: mirrored: <path> ya da yeni deseni ve neden hiçbir kardeşin uymadığını adlandırır. Bu ucuz ve eklediğim en iyi tek inceleme yardımcısı. Yanlış türde bir dosyayı işaret eden bir mirrored: satırı, diff’i açmadan önce yanlış olduğunu söyler. Eksik olan bir tanesi ise ajanın bakmadığını söyler.

İnceleme aynı çıtayı sabit bir sırayla uygular. İnceleme yeteneğimizin sabit etiketli iki geçişi var ve bulguları gözden geçirenler ve ajanlar arasında karşılaştırılabilir kılan şey bu etiketler.

İki inceleme geçişi: yapı geçişi diverge, duplicate, layer, misplaced, reach-in, inconsistent, own ve chain etiketlerini kullanır; kesme geçişi delete, stdlib, native, yagni ve shrink etiketlerini kullanır. Yapı önce çalışır çünkü tutarlılık kesmelerden üstündür

Önce yapı. Bu, en yakın örnekten sapıyor mu, var olan bir yardımcıyı çoğaltıyor mu, bir katmanı geçiyor mu, yanlış yerde mi duruyor, başka bir modülün iç işleyişine mi uzanıyor, tutarsız adlar mı kullanıyor, enjekte etmesi gereken bir şeyin sahipliğini mi alıyor, kanonik çağrı zincirini mi kırıyor? Sonra kesmeler. Neler silinebilir, standart kütüphaneyle değiştirilebilir, yerel bir özellikle değiştirilebilir, spekülatif olarak düşürülebilir veya küçültülebilir?

Sıra bir kuraldır, bir tercih değil. Tutarlılık kesmelerden üstündür. Kodu kardeşlerinden saptırarak bırakan bir kesme bir kazanç değildir, çünkü okuyucu sekiz satır kazanmak için artık iki şekil öğrenmek zorundadır. Yapıyı önce çalıştırın, o zaman kesme geçişi yalnızca zaten uyumlu olan koda dokunur.

Depoda ne oldu, işe yaramayan kısım dahil

1 Ağustos’tan bu yana ana depomuz 1.333 commit aldı; çoğu inceleme altında ajan tarafından yazıldı. Bu dönemdeki issue ve pull request’lerin 386’sı, yansılanacak örneği adlandıran bir plan yorumu taşıyor; toplamda 491 böyle yorum. Kanonik zincir, yeni bir endpoint’in varsayılan şekli ve controller’ı atlayan iki eski route, ikinci bir stil değil, kaldırılmakta olan bir sapma olarak dokümanda listeleniyor.

35 ponytail: yorumu beklediğimden daha küçük bir sayı ve bence bu doğru. Çoğu basitleştirme bir yoruma değmez. Değenler, bir tavanı olanlar.

Şimdi, aslında raporlamak istemediğim kısım. Grain ve ponytail’i bir Claude Code yeteneği olarak yayınladım: yetenek dizininde bir açıklama, istek üzerine yüklenen bir gövde ve CLAUDE.md’de kod yazmadan önce onu çağırmasını söyleyen bir satır. Beş haftalık transcript boyunca ajan onu adıyla sıfır kez çağırdı. mirrored: kapanış satırı yedi yanıtta göründü.

Kurallar yine de yerini buldu. Yerini buldular çünkü aynı metin, ajanın seçim yapmadan okuduğu üç yerde de vardı: ilk turdan itibaren bağlamda olan projenin CLAUDE.md’si; “en yakın mevcut örneğin şeklini, konumunu ve adlandırmasını yansıla” ve “gerçekten işleyen en tembel çözüme uzan” ifadelerini dikkate alınacak bir yetenek olarak değil, kural olarak söyleyen worker ajan tanımları; ve etiketleri, onları yok sayan bir pull request’i başarısız bırakan inceleme kontrol listesi. Yeteneğin gövdesi, bu üçünün işaret ettiği kanonik referans hâline geldi. Bir tetikleyici olarak ise hiçbir şey yapmadı.

Yani bir ajan için konvansiyonları paketleyen herkese aktaracağım ders şu. Bir yetenek, bir kuralın uzun sürümü için iyi bir yerdir. Kuralın kendisi için kötü bir yerdir, çünkü ajan onu yüklemeye karar vermek zorundadır ve çoğunlukla vermez. Tek paragraflık sürümü her zaman bağlamda olan dosyaya koyun, emir kipindeki sürümü kodu yazan ajanın tanımına koyun ve kontrolü merge’ü kapıda tutan incelemeye koyun. Sonra ayrıntı için üçünü de yeteneğe yönlendirin.

Herkese açık sürüm github.com/LivinTribunal/grain-skill adresinde bu şekilde düzenlenmiş: ajanın kafasında tutabileceği kuralları içeren kısa bir SKILL.md, merdiveni ve anti-desenleri içeren tam doküman, inceleme etiketleri ve hangi paragrafın CLAUDE.md’nize, hangisinin uygulayıcınızın tanımına gideceğini söyleyen bir README. İşlenmiş örneği kendi kanonik örneğinizle değiştirin ve iş tamam.

Sıkça sorulan sorular

Štefan, FlowHunt'ı geliştiren bir yapay zeka ve yazılım mühendisidir. Ürünün kendisinin ötesinde, geliştirme maliyetlerini düşürürken kod kalitesini artıran geliştiriciler için agentic yazılım mühendisliği iş akışları tasarlar.

Štefan Moravík
Štefan Moravík
Yapay Zeka & Yazılım Mühendisi

Ajanlarınıza Ekibinizin Zaten Uyguladığı Konvansiyonları Verin

FlowHunt, bir ajanın her workflow'da izlemesi gereken kuralları, örnekleri ve inceleme adımlarını eklemenize olanak tanır, böylece çıktısı içine düştüğü koda uyar.