Files
kolaytercih/docs/gece-vardiyasi/2026-10-05/05-yazilimci-qa-duzeltmeleri.md
bilalgursen fd464e9cc2 docs(gece): yazılımcı QA düzeltmeleri raporu
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-05 01:14:08 +03:00

13 KiB
Raw Blame History

05 — Yazılımcı: QA düzeltmeleri (danışman sohbeti)

Dal gece/eval-jev · kaynak rapor 03-qa-dal-ve-kod-denetimi.md · 5 Ekim 2026 gecesi · yazılımcı

Özet (5 madde)

  1. QA'nın 9 maddesinden 8'i düzeltildi (H1, H2, H3, M1–M5, L1–L3, L5, L6 + cagri.ts importu); her biri ayrı commit. H4'e (model araç çağırmadan "Kaydettim" diyor) görev gereği dokunulmadı.
  2. sistemPromptu artık içe aktarılabilir: src/lib/ai/danisman-prompt.ts (sistemPromptu, PROFIL_ONAY_SOR). Metin birebir aynı (eski/yeni satır karşılaştırması: tek fark export).
  3. Kredi tarafındaki iki delik kapandı: zaman aşımında yarım cevap artık "tamam" sayılmıyor ve kredi iade ediliyor (H2); "evet. <gerçek soru>" artık bedelsiz geçmiyor (H3).
  4. İki bilinçli karar verildi: H3'te sıkı kalıp eşleşmesi seçildi; M1'de sunucu davranışı korunup istemci metni düzeltildi (kopmada iade, bedava cevap kapısı olurdu). Gerekçeler aşağıda.
  5. Doğrulama: typegen + tsc + lint (eslint 0 uyarı, tasarım denetimi 0 hata / 12 eski uyarı) + tek pnpm build (1935 sayfa) geçti. Gerçek model çağrısı: 4 adım (sınır 15). Tarayıcı ve sunucu açılmadı; route düzeyi davranışlar (402 vb.) fonksiyon testine dayanır, aşağıda "koddan çıkarım" diye işaretli.

Commit listesi

Sha Hata Mesaj
3e4886e Ek refactor(danisman): sistemPromptu saf modüle taşındı
4e2470e H1 (1) fix(danisman): aynı adımda iki profil_guncelle birbirini ezmesin
1191f16 M2 (6) fix(danisman): 100 mesajı aşan geçmişte en yeni 100 dönsün
08f4ec2 M3 (7) fix(danisman): modele giden pencere tutarlı olsun
3f1e770 H3 (3) fix(danisman): bedelsiz onay yolu yalnız gerçek onayda açılsın [KARAR]
90a9994 H2 (2) fix(danisman): zaman aşımında yarım cevap tamam sayılmasın, kredi iade edilsin
3c3183b M1 (5) fix(danisman): bağlantı kopunca istemci "iade edildi" demesin
72b673b M4+M5 (8) fix(danisman): araç argümanları şemayla doğrulansın, "300 km" 300 okunsun
b26df27 L1–L3, L5, L6 (9) fix(danisman): Türkçe-duyarsız il/bölüm/üniversite eşleşmesi, kısa girdi hatası

Değişen dosyalar: src/app/api/soru/route.ts, src/lib/ai/{danisman-prompt,sohbet-gecmisi}.ts (yeni), src/lib/ai/{araclar,sohbet-akisi,cagri}.ts, src/lib/danisman-profil-db.ts, src/lib/mesafe.ts, src/features/rapor/rapor-queries.ts, src/features/rapor/components/sohbet-client.tsx (yalnız toast metni + yorum).

Düzeltmeler ve kanıt

Hepsi çalıştırılarak doğrulandı (aksi yazılmadıkça). Betikler scratchpad yz/ altında, commit edilmedi.

Ek — sistemPromptu taşındı

  • Yeni yol: import { sistemPromptu } from "@/lib/ai/danisman-prompt". Girdi: { params, listeOzeti, kilitli?, profil? }.
  • Kanıt: HEAD'deki fonksiyon gövdesiyle yeni dosyadaki gövdenin diff'i yalnız export kelimesi; tsx --conditions=react-server ile Next dışından çağrıldı (4.621 karakter döndü).
  • Next kılavuzu (route.md) route dosyasından ek dışa aktarımı anlatmıyor; ayrı dosya görev tanımındaki yönlendirmeyle seçildi.

H1 — iki profil_guncelle birbirini eziyordu

  • Değişen: profilAlanYaz oku → değiştir → yaz yerine tek SQL ifadesi (json_set / json_remove, upsert).
  • Önce: iki araç Promise.all ile → DB {"maxKm":300}; her araç yalnız kendi alanını görüyor.
  • Sonra: DB {"evIl":"ANKARA","maxKm":300}; iki araç çıktısında da iki satır. Silme ve geçersiz değer (maxKm: 5 → hata) çalışıyor.
  • Gerçek modelle: "evet" → model iki profil_guncelle'yi aynı adımda çağırdı → DB'de ikisi de var.
  • Not: üretim libsql (uzak) kullanıyorsa json_set desteği koddan çıkarım; lokalde file: ile doğrulandı.

H2 — zaman aşımında yarım cevap "tamam" sayılıyordu

  • Değişen: sohbet-akisi.ts — "abort" parçası istemciye geçirilmiyor; döngüden sonra zaman aşımı sinyaline bakılıp hata fırlatılıyor → onYarim (iade + yarım kayıt) + hata parçası. İsteğe bağlı zamanAsimiMs (varsayılan 120 sn; test için).
  • Önce (sahte sağlayıcı "takıl", 120,0 sn): [onTamam] "Bu cevap takılacak ve ", parçalar … abort finish.
  • Sonra (zamanAsimiMs: 4000): [onYarim] "Bu cevap takılacak ve " → iade, parçalar … error(Danışman şu anda yanıt veremiyor.). Normal cevap ve "yarıda kes" modu eskisi gibi (onTamam / hata).
  • Varsayılan 120 sn ile düzeltme sonrası yeniden koşulmadı (aynı kod yolu; koddan çıkarım).

H3 — bedelsiz onay yolu kredi atlatıyordu [KARAR]

  • Seçim: sıkı kalıp. Mesaj noktalama atıldıktan sonra baştan sona onay sözlerinden oluşmalı (evet / olur / tamam / kaydet / hayır / gerek yok… + "lütfen", "bunu", "teşekkürler" dolgusu). Uymayan mesaj normal kredili soru.
  • Gerekçe: en sade çözüm ve deliği kökten kapatıyor — bedelsiz turda soru metni hiç taşınamıyor. "Yalnız profil_guncelle açık + kısa cevap sınırı" seçeneği danismanAkisi'ne iki yeni parametre ister ve "evet, peki hukuk?" yine bedelsiz model turu harcar; eklenmedi. 26 Eyl kararı ("profil onayı kredi harcamaz") gerçek onay için aynen duruyor.
  • Önce/sonra (eski fonksiyon betiğe birebir kopyalandı, 16 vaka): "evet. Ege hukuk taban sırası kaç?", "evet ama izmir hukuk kaç", "tamam, peki ODTÜ?", "evet hukuk" → önce bedelsiz, sonra kredili. "evet", "Evet.", "EVET!", "evet, kaydet lütfen", "hayır", "Hayır, gerek yok." vb. 12 gerçek onay → bedelsiz kaldı.
  • 0 kredide 402 dönmesi: route'ta kalıba uymayan mesaj spendCreditForMessage yoluna düşer (koddan çıkarım; sunucu açılmadı).
  • Yan etki: kalıpta olmayan onay ("aynen", "ok") 1 kredi harcar; 0 kredide 402 alır.

M1 (5) — istemci kopunca "iade edildi" diyordu

  • Seçim: sunucu doğru, istemci metni yanlış. Sunucu kopmada üretip kaydetmeye devam eder, kredi harcanmış kalır. Kopmada iade seçilmedi: cevabı okuyup son anda bağlantıyı kesen kullanıcı her soruda iade alırdı.
  • Değişen: yalnız toast metni — "Bağlantı koptu. Cevap tamamlanırsa sohbetine kaydedilir, tamamlanamazsa kredin iade edilir — yeniden göndermeden önce sayfayı yenile." + iki yorum. Görsel değişiklik yok.
  • Kanıt: metin değişikliği; tarayıcıda denenmedi (koddan çıkarım). Sunucu davranışını QA çalıştırarak doğrulamıştı.
  • Kalan: soru hâlâ giriş kutusuna geri konuyor; kullanıcı uyarıya rağmen yeniden gönderirse iki kredi öder. İstemci "sunucu hatası" ile "bağlantı koptu"yu ayırt edemiyor; ayırmak davranış değişikliği ister (tasarımcı/ürün kararı).

M2 (6) — 100 mesajı aşınca en eski 100 dönüyordu

  • Değişen: sohbetGecmisiGetir yeniden eskiye + rowid sıralayıp 100 alır, çevirir; GET /api/soru aynı fonksiyonu kullanır (kopya sorgu kalktı).
  • Önce (120 dolgu mesajı): dönen 100, ilk "dolgu 1", son "dolgu 100".
  • Sonra: ilk "dolgu 21", son "dolgu 120", sıra birebir doğru (aynı saniyeye düşen soru-cevap çiftleri dahil — created_at saniye çözünürlüklü).

M3 (7) — modele bozuk rol sırası gidiyordu

  • Değişen: modelPenceresi (src/lib/ai/sohbet-gecmisi.ts) — baştaki danışman mesajları atılır, art arda aynı rol tek mesajda birleşir (yinelenen metin bir kez). 12'lik pencere sorgusuna rowid sıralaması eklendi.
  • Önce → sonra (roller): uauauauauuua+yeni → uauauauauuuau → uauauauauau; auauauauauau+yeni → auauauauauauu → uauauauauau; aynı soru üç kez → tek mesaj.
  • Birleştirme seçildi (atma değil): cevapsız kalan mesajdaki bilgi ("Ankara'da yaşıyorum") kaybolmasın.

M4 + M5 (8) — sayiParse ve argüman doğrulama

  • sayiParse: birim eki sayıdan ayrıldı. "300 km" önce "Değer kabul edilmedi" (300.000 okunuyordu), sonra "Evden en fazla 300 km". "400 bin TL", "300k" eskisi gibi.
  • aracCalistirici argümanı ARACLAR şemasına göre denetliyor: bilinmeyen alan, yanlış tip, geçersiz seçenek, alt sınır, eksik zorunlu alan. Örnek sonuçlar:
    • arama: 12345 → önce "Araç çalışmadı; veriye ulaşılamadı" · sonra "arama: metin olmalı (gelen: 12345)".
    • dilim: "orta" → önce süzgeç dilim = undefined, 2.234 sonuç · sonra "dilim: geçersiz seçenek …; şunlardan biri olmalı: hayal, dengeli, guvenli".
    • ucret_ust: -5 → önce "yıllık ücret ≤ -5 TL", 757 sonuç · sonra "ucret_ust: en az 1 olmalı". 0 da aynı hata (önce sessizce yok sayılıyordu).
    • tur: "__proto__" → önce TypeError · sonra açık hata.
  • QA'nın 118 vakalık arac-test.ts'i yeniden koşuldu: FIRLATTI sayısı 5 → 0; geçerli vakaların sonuç sayıları değişmedi.
  • İsteğe bağlı alanda null "verilmedi" sayılır (modeller boş alanı böyle yollayabiliyor).

L1–L3, L5, L6 (9)

Girdi Önce Sonra
program_ara il:"IZMIR" İl tanınmadı 129 sonuç
program_ara arama:"isletme" / "ISLETME" 0 513 (İşletme ile aynı)
program_ara universite:"bogazici" / "ODTÜ" 0 / 0 12 / 22
il_ozeti "Afyon" İl bulunamadı Afyonkarahisar
profil_guncelle evIl "IZMIR" İl tanınmadı Yaşadığı il: İzmir
bolum_ozeti "a", "---" Abaza Dili ve Edebiyatı "en az 3 harf yaz"
bolum_istihdam ["a"] Acil Yardım "en az 3 harf yaz"
universite_profili "a" Abdullah Gül "en az 3 harf yaz"
universite_profili "DEÜ" bulunamadı Dokuz Eylül Üniversitesi
program_ara arama:"%" 3.247 sonuç "en az 3 harf yaz"
  • Bölüm/üniversite araması SQL LIKE yerine katlanmış adla JS'te eşleniyor (ayrık 1.744 bölüm adı, 322 üniversite adı bir kez okunur). İşletme 513, iKTiSAT 171, hukuk 140: önce/sonra aynı.
  • Hata logu artık yalnız mesajı basıyor; cagri.ts kullanılmayan import kalktı (eslint uyarısı 1 → 0).
  • Gerçek modelle: "IZMIR'de isletme okumak istiyorum…" → program_ara {"arama":"İşletme","il":"İzmir"}, 19 eşleşme, cevap geldi.

Şartnameden sapmalar

  1. Araç tanımı (modele giden şema) dört yerde değişti — sistem prompt metni değişmedi, ama eval mühendisi bilmeli: program_id ve program_idler öğeleri string | integer; profil_guncelle.deger string | number | null; ucret_ust minimum: 1; dil seçeneklerine Almanca, Fransızca, Arapça, Rusça eklendi. Sebep: gövdeler bunları zaten kabul ediyordu (gerçek model deger: 300 sayısı gönderdi; "Almanca" süzgeci 17 sonuç veriyordu); şema sıkı doğrulanınca çalışan çağrılar kırılırdı.
  2. dil genişletmesi 8 numaranın parçası ama b26df27 (9) commit'ine girdi (aynı dosya, etkileşimsiz kısmi ekleme yapılamadı).
  3. danismanAkisi'ne isteğe bağlı zamanAsimiMs eklendi (H2'yi 120 sn beklemeden test etmek için).
  4. L4 (uzun girdi araç sonucuna yansıyor), L7 (baştaki boş satır), L8 (Jev eşiği), L9 (depodaki app.db şeması) görev listesinde yoktu; dokunulmadı.

Düzeltilemeyen / açık kalan

  • H4 — görev gereği dokunulmadı (yapay zekâ mühendisi).
  • M1'in istemci yarısı tam kapanmadı: metin doğru ama soru kutuya geri konuyor (yukarıda).
  • /api/soru hız sınırı yok (QA H3 notu): bedelsiz "evet" turu sınırsız tekrarlanabilir. Her tur yalnız onay taşıyor, soru soramıyor; yine de model çağrısı maliyeti var.
  • Route düzeyinde uçtan uca test yapılmadı (sunucu açılmadı): 402, başlıklar, GET cevabı koddan çıkarım.

Merge sonrası doğrulanması gerekenler

  • Üretim veritabanında (libsql) profil_guncelle ile iki alan kaydı — json_set yolu.
  • 0 kredili hesapla "evet. " → 402; yalnız "evet" → bedelsiz.
  • Tarayıcıda bağlantı kopması: yeni toast metni ve sayfa yenilenince cevabın görünmesi.
  • Eval turunda araç şeması değişikliklerinin (sapma 1) model davranışına etkisi.

Çalışma ağacı notu

  • data/app.db commit edilmedi. Test için eklenen 120 dolgu mesajı ve qa-arac-kullanici profil satırı silindi; QA'nın kayıtlarından qa-arac-kullanici'nın sohbet mesajları da silindi (dolgu eklerken temizlendi).
  • src/lib/db.ts ve src/lib/rapor-havuzu.ts başka bir ajanın commit'lenmemiş değişikliği; dokunulmadı. tsc/lint/build bu değişiklikler çalışma ağacındayken koşuldu, yani build tam olarak b26df27 commit'ini değil o anki ağacı doğruladı.
  • Para ve kişisel veriye (kredi, profil) dokunuldu: guvenlik-uyum denetimi önerilir.

Bilal'den istenen

  1. [BİLAL] H3 kararını onayla ya da değiştir: yalnız baştan sona evet/hayır olan mesaj bedelsiz; "evet + soru" 1 kredi (1 dk).
  2. [BİLAL] M1: bağlantı kopunca soru giriş kutusuna geri konmaya devam etsin mi (yeniden gönderen iki kredi öder) — kaldırılsın mı (2 dk).
  3. /api/soru'ya hız sınırı eklensin mi (1 dk).