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

134 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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. <soru>" → 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).