Free

Sessiz Hataları Claude ile Ayıklamak

Tıklamanın hiçbir şey yapmadığı üç gerçek hata — prompt'a eklenen bir cümle cevabı kilitleyene dek Claude her seferinde yanıldı.


Bug'lar iki türlüdür. Hata fırlatanlar — stack trace'i Claude'a verirsin, 30 saniyede cevap gelir. Fırlatmayanlar — tıklamaya tepki vermeyen buton, hareket etmeyen sayfa, sessizce başarısız olan form — işte bunlarda Claude ilk denemede yanılır. Aptal olduğundan değil. Göremediğinden.

how2claude'un ödeme akışını kurarken üst üste üç tane bununla karşılaştım. İşte post-mortem ve artık sessiz bug'lar için kullandığım prompt desenleri.

Bug 1: Cüzdan adresinde saklanan tam genişlikli bir soru işareti

x402 kripto ödemelerini bağladım. Yerelde çalışıyordu. Production'da ilk tıklamada console'da invalid_string at payTo. Signing flow başlamadı bile — facilitator'ın Zod şeması isteği önce reddetti.

Cüzdan 42 karakterlik bir 0x... adresiydi, gözüm alışık, temiz görünüyordu. Claude'a config/credentials/production.yml.enc içindeki wallet alanını kontrol ettirdim:

w = Rails.application.credentials.dig(:x402, :wallet_address).to_s
puts "length: #{w.length}"
# => 43

43 karakter. EVM adresleri 42 olmalı. 43. karakter bir Çin tam genişlikli soru işaretiydi (U+FF1F), Çince giriş yönteminden kopyala-yapıştır sırasında bulaşmış.

Claude'un ilk taraması hiçbir şey işaretlemedi — ona göre 0x ile başlayan ve doğru görünen bir string'di. Uzunluğu kendiliğinden saymadı. Prompt'a şu cümleyi ekle: "bu adres beklenenden 1 karakter uzun — her codepoint'i ayrı ayrı yazdır". 0xFF1F ortaya çıkınca dava kapanır.

Bug 2: Stripe Checkout butonu tıklamaya yanıt vermedi

Fiyatlandırma sayfasındaki Subscribe butonu — tıkla, sayfa kıpırdamıyor. Hata yok. Network sekmesi POST'un gittiğini, Stripe'ın checkout.stripe.com için 302 döndürdüğünü gösteriyordu — ve sonra... hiçbir şey.

Önce Claude'a controller'ı kontrol ettirdim. Mantık doğruydu: redirect_to session.url, allow_other_host: true. JS — ilgili listener yok.

Sonunda response header'ını fark ettim: Content-Type: text/vnd.turbo-stream.html. Turbo, button_to'nun submit'ini Turbo Stream isteği olarak yakalıyordu ve Turbo Stream cross-origin 302'leri takip etmez — yani yönlendirme yutuluyor ve sayfa sessizce olduğu yerde kalıyordu.

Fix:

<%= button_to "Subscribe", ..., data: { turbo: false } %>

Aynı bug bir ay sonra Google OAuth butonunda tekrar çarptı. Framework seviyesindeki interceptor'lar sessiz bug'ların bereketli toprağıdır — Claude varsayılan olarak "istek/yanıt" doğrultusunda doğrusal muhakeme yapar, semantiği yeniden yazan bir ara katman olup olmadığını kendiliğinden araştırmaz. Prompt'a ekle: "bu tıklamanın geçtiği her framework seviyesindeki interceptor'ı dolaş — bu isteği browser → sunucu → browser yolculuğunda işleyen her middleware/JS katmanını listele."

Bug 3: Monthly/Yearly geçişi tıklamaya yanıt vermedi

Fiyatlandırma sayfasındaki aylık/yıllık geçiş için Stimulus controller — butona tıkla, hiçbir şey değişmiyor. Controller metodu fire oluyordu (console.log ile onaylı), ama this.monthlyTarget undefined'dı.

Claude'un ilk tahmini: target adında yazım hatası. Değildi. data-pricing-target="monthly" DOM'daydı.

Sorun scope'taydı. data-controller="pricing" geçiş butonunun konteynerinde iken, iki grid bölümü o konteynerin dışında duruyordu. Stimulus sadece controller elemanının alt ağacında target arar; dışarıdakiler onun için yoktur. data-controller'ı tüm bölümü saran <section>'a taşıdım — düzeldi.

Bu bug "kod doğru" diye bağırır — tüm isimler tutuyor, tüm attribute'lar yerli yerinde, sadece özellik çalışmıyor. Claude varsayılan olarak kodu satır satır okur; DOM yapısını kendiliğinden görselleştirmez. Prompt'a ekle: "data-controller='pricing' olan elemanın ata ve torun ağacını çiz — hangi data-pricing-target'lerin alt ağaçta olduğunu, hangilerinin olmadığını işaretle."

Sessiz bug'lar için üç prompt deseni

Üç bug dışarıdan aynı görünüyordu: tıkla, hiçbir şey olmuyor, hata yok. Claude her seferinde ilk başta yanıldı, her seferinde prompt'a eklenen fazladan bir cümle onu kilitledi. Ortak desen:

1. Ona beklenen ve gerçekleşen arasındaki nicel farkı söyle — sadece "yanlış" deme

"Cüzdan adresinde sorun var" değil, "beklenenden 1 karakter daha uzun".
"Buton çalışmıyor" değil, "yanıt 302, ama browser takip etmedi".
"Geçiş bozuk" değil, "controller metodu fire oluyor ama target undefined".

Fark ne kadar dar olursa, Claude'un arama alanı o kadar küçülür.

2. Onu görünmez katmanlara yönlendir — framework, browser, encoding

Sessiz bug'lar neredeyse hiç senin iş kodunda yaşamaz. Turbo'da yaşarlar, Stimulus scope'unda yaşarlar, karakter kodlamasında yaşarlar, CSP'de, CORS'ta, service worker'larda. Claude'un varsayılanı senin kodunu okumak. Açıkça ona git ve o katmanlara bak de.

3. Sonuç değil, ara durum iste

"Her codepoint'i yazdır." "Response header'ları listele." "DOM alt ağacını dump et." Claude'a cevaba doğru muhakeme yaptırmak yerine ara durumu somutlaştır. Sessiz bug'ın "sessiz" kısmı, muhakeme zincirinin bir adımında geçerli olmayan gizli bir varsayım olmasıdır. Ara durumu somutlaştırmak o varsayımı ortaya zorla çıkarmanın yoludur.


Hatalar Claude'un bildiğini sınar. Sessiz bug'lar sana verdiği sinyalin kalitesini sınar. Ne kadar spesifik olursan, cevabı o kadar hızlı bulur.