Aynı hata, başka başlık: bir LLM bulgusuna kimlik vermek
CommitBrief'te bir bulgunun 'aynısı' sayılması başlıktan kural kimliğine taşındı; baseline, policy ve PR thread'leri bu kararın üstüne kuruldu.
Kısaca
CommitBrief ilk baseline'ında bulguyu dosya, severity ve başlıkla tanıyordu; model başlığı değiştirince bulgu geri geliyordu. v1.19.0'da kimlik dosya, kapalı taksonomiden bir kural kimliği ve symbol oldu. Baseline, policy, SARIF ve PR yorum senkronu aynı kimliğe yaslanıyor.
Baseline’a aldığım bir bulgu, hata aynı kaldığı hâlde geri geliyordu. Değişen tek şey modelin bulguya verdiği başlıktı.
CommitBrief’te bir bulgunun “aynısı” olmanın neye bağlı olduğunu uzun süre sormadım. Bu yazı, o sorunun cevabını bulgunun kimliği olarak yazılı hâle getirmenin ve bu tek kararın arkasından gelen özelliklerin hikâyesi. Aracı neden yazdığımı ve PR akışına nasıl taşıdığımı önceki yazılarda anlatmıştım.
v1: kimlik başlıktı
v1.8.0’da (2026-06-20) baseline geldi. Mevcut bir depoda bugünkü bulguları bir kez kabul ediyorsunuz, sonraki koşularda yalnız yeni olanları görüyorsunuz. Bir bulguyu tanımak için şu parmak izini kullanıyordum:
sha256(File + Severity + normalize(Title))
Satır kaymasına dayanıklıydı: bulgu dosyada yukarı aşağı gitse de baseline’da kalıyordu. Ama başlığa bağlıydı, ve başlığı yazan ben değil, modeldi. Model aynı hatayı bir sonraki koşuda başka bir başlıkla yazınca, baseline’a aldığım bulgu “yeni” sayılıp geri geliyordu. Modelin severity’yi yeniden derecelendirmesi de aynı sonucu veriyordu.
Aynı tavanı v1.10.0’daki policy gate’de de görmüştüm. Changelog’a o gün şunu yazmışım: “Rule-id-scoped allow/deny lists are deferred (findings carry no stable rule id).” Kural bazlı izin ve yasak listesi yapamıyordum, çünkü bulgunun kararlı bir kural kimliği yoktu.
“Aynı”yı tanımlamak
v1.19.0’da (2026-10-18) kimliği başlıktan çıkarıp iki parçaya böldüm.
Birincisi kural kimliği (rule_id). 30 kimlikli kapalı bir taksonomi: sec.injection, correctness.error-handling, test.flaky ve general.other gibi. Model bunu kendisi seçiyor; OpenAI, Anthropic ve Gemini şemalarında rule_id zorunlu ve değerleri taksonomiyle sınırlı. Boş ya da bilinmeyen bir değer gelirse tekrar denenmiyor, doğrudan general.other’a çekiliyor. Etiket konusunda gevşek olan bir model, geçerli bir review’ı bozmasın istedim. Deterministik üreticiler kimliği kendileri veriyor: flaky süzgeci test.flaky, leaks ise sec.hardcoded-secret yazıyor.
İkincisi symbol. Modelden gelmiyor, diff’ten yerelde türetiliyor: bulgunun satırını içeren hunk’ta o satıra kadar, git’in varsayılan funcname kuralına uyan son satır, yani ilk karakteri harf, _ ya da $ olan satır. Parantez içleri ()’ye indirildiği için parametre listesi değişince symbol değişmiyor. Bu yüzden kimlik şu oldu:
fingerprint = sha256(file, rule_id, symbol)
Başlık, severity ve satır numarası formülde yok. Kimlik her koşuda yerelde hesaplanıyor, cache’e yazılmıyor; cache’ten gelen bulgu için de güncel diff’ten yeniden hesaplanıyor. Formül bir gün değişirse eski kimlikler cache’te kalıp yanlış eşleşmesin diye böyle yaptım.
Aynı kimlikle gelenler
Kimlik bir kere kararlı olunca, bekleyen özellikler tek tek yerine oturdu.
- Baseline v2 artık kimlikleri saklıyor. Başlığı değişen bulgu baseline’dan düşmüyor.
- Policy
rules.denyverules.allowkazandı.denylistesindeki bir kuraldan tek bir bulgu kapıyı kapatıyor;allowlistesindekiler eşiklerden ve toplamdan muaf tutuluyor. Girdi, taksonomideki bir kimlik ya da<category>.*. - Satır içi işaretler kural kapsamı aldı:
commitbrief-ignore[sec.injection]: gerekçeyalnız o kuralın bulgusunu susturuyor. - SARIF çıktısı kimliği
partialFingerprints["commitbrief/v1"]altında taşıyor. SARIF’in başarısız olduğunda neden dosya yazmadığı ayrı bir konu; burada yalnız anıyorum.
Zincirin en görünür halkası v1.20.0’daki remote pr değişikliği. Eskiden her koşu yorumları yeniden atıyordu. Şimdi her satır içi yorumun sonunda gizli bir marker var:
<!-- commitbrief:fp=<fingerprint> v=1 -->
Bir sonraki koşu kendi thread’lerini bu marker’dan tanıyor. Durmaya devam eden bulguya dokunmuyor (metin değiştiyse yorumu yerinde düzenliyor), yeni bulguyu bir kez yazıyor, kaybolan bulgunun thread’ini kapatıyor, geri dönen bulgunun thread’ini yeniden açıyor. Bir insanın çözdüğü ya da yeniden açtığı thread’lere hiç dokunmuyor. Aynı kimliğin tekrarları tek thread’de Also at: altında toplanıyor. Thread’i kapatma yetkisi yoksa yanıt olarak No longer present as of <sha> yazıyor.
Aynı sürümde --since-last-review da geldi: her tam PR review’ının sonuna <!-- commitbrief:reviewed=<head sha> --> marker’ı ekleniyor, bayrakla yalnız yeni commit aralığı inceleniyor. Force-push, merge commit ya da aralık güvenle belirlenemezse tam review’a dönüyor. v1.21.0’dan beri remote pr satır içi susturmaya da uyuyor; baseline remote pr’a uygulanmıyor.
Bedeli
- v1’den v2’ye geçiş kayıplı. Başlık hash’lerinden kural kimliği ve symbol geri çıkarılamıyor;
--update-baselineile yeniden almak gerekiyor. - v1.20 öncesi yorumlarda marker yok. Önceden review edilmiş bir PR’da ilk v1.20 koşusu bulguları bir kez daha yazıyor.
- Taksonomi bloğu prompt’a changelog’daki tahminle yaklaşık 690 token ekliyor. System prompt cache anahtarının parçası olduğu için mevcut cache girdileri yükseltmeden sonra bir kez ıskalıyor.
Sınırlar — yine dürüst liste
- Kimlik hâlâ kısmen modele bağlı.
rule_id’yi model seçiyor ve bulgunun satırını o veriyor; satır da hangi symbol’e düşeceğini belirliyor. Aynı hata iki koşuda farklı kuralla gelirse kimlik değişir. Bu kararlılığın ne kadar tuttuğuna dair burada vereceğim bir ölçümüm yok; modelleri review kalitesi ekseninde ölçtüğüm önceki yazırule_idkararlılığını ölçmedi. - Kapalı taksonomi kaba.
general.other’a düşen bulgular ayırt edilemiyor; baseline’daki kapsamı da geniş. - Aynı kuralın aynı symbol’deki iki bulgusu çakışır. Baseline’a alınan bir bulgu, aynı symbol’de aynı kuraldan gelecek bulguları da gizler.
- Girintili satır symbol olmaz. Python sınıf metotlarında symbol sınıf satırına ya da boş değere düşebilir; kardeş metotlar aynı symbol’ü paylaşır.
- Symbol, diff’in türüne bağlı. Tarama önce yeni taraftaki satırlara bakıyor, bulamazsa git’in eski koddan yazdığı hunk başlığına düşüyor. Aralıkta yeniden adlandırılan bir fonksiyon için
--stagedilemain..HEADfarklı symbol, dolayısıyla farklı kimlik verebilir. Baseline’ı aldığınız türden diff’le karşılaştırın. Dosya adı değişince de kimlik değişir. - CLI tabanlı sağlayıcılar düz metin ürettiği için
rule_idve fingerprint yok.
Denemek için
Kendi aracınızda ya da CommitBrief’te bir bulguyu baseline’a alıp bir sonraki koşuda geri gelip gelmediğine bakın. Geliyorsa, aracınızın “aynı bulgu”yu neye bağladığını yazılı hâle getirmek için iyi bir gün bugün.
Bu konudaki deneyler
Tan Assistant: toplantıyı sesi ve değişen ekran kareleriyle nota çeviren masaüstü uygulaması
Rust ve Tauri 2 ile yazılan açık kaynak bir masaüstü uygulaması toplantının sesini ve değişen ekran karelerini kaydedip özet ve aksiyon notu çıkarıyor.
Şu an ne yapıyor
Toplantının mikrofon ve sistem sesini ayrı kanallarda, ekranın yalnızca değişen karelerini kaydedip özet, karar, aksiyon maddesi ve açık soru içeren bir not çıkarıyor. Toplantı kaydını videoya çevirmeden nota dönüştürmek isteyen herkes kaynaktan derleyip deneyebilir.
TokenMetrics: AI agent token harcamasını projeye göre görünür kılmak
Claude Code, Codex CLI ve Gemini CLI loglarını yerelde okuyan bir masaüstü uygulaması, token kullanımını proje, model ve oturuma göre gösteriyor.
Şu an ne yapıyor
AI agent token kullanımını yerel loglardan toplayıp proje, model, oturum ve zaman bazında gösteriyor; tahmini maliyet ve abonelik limiti takibi sunuyor. Claude Code, Codex CLI veya Gemini CLI'ı yoğun kullanıp harcamasını görmek isteyen geliştirici kurabilir.
Yorumlar
Yorum yapmak için GitHub hesabınızla giriş yapmanız yeterli. Yorumlar GitHub Discussions üzerinde saklanır.