docs(gece): yazılımcı QA düzeltmeleri raporu
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
133
docs/gece-vardiyasi/2026-10-05/05-yazilimci-qa-duzeltmeleri.md
Normal file
133
docs/gece-vardiyasi/2026-10-05/05-yazilimci-qa-duzeltmeleri.md
Normal file
@@ -0,0 +1,133 @@
|
||||
# 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).
|
||||
Reference in New Issue
Block a user